diff --git a/src/qemu_conf.c b/src/qemu_conf.c index d9b82b2..bfd9ba4 100644 --- a/src/qemu_conf.c +++ b/src/qemu_conf.c @@ -1011,6 +1011,41 @@ static int qemudParseInputXML(virConnectPtr conn, return -1; } +/* Sound device helper functions */ +static int qemudSoundDriverFromString(virConnectPtr conn, + const char *driver) { + if (STREQ(driver, "all")) { + return QEMU_SOUND_ALL; + } else if (STREQ(driver, "sb16")) { + return QEMU_SOUND_SB16; + } else if (STREQ(driver, "es1370")) { + return QEMU_SOUND_ES1370; + } else if (STREQ(driver, "pcspk")) { + return QEMU_SOUND_PCSPK; + } + + qemudReportError(conn, NULL, NULL, VIR_ERR_INVALID_ARG, + _("invalid sound driver '%s'"), driver); + return -1; +} + +static const char *qemudSoundDriverToString(virConnectPtr conn, + const int driver) { + + if (driver == QEMU_SOUND_ALL) { + return "all"; + } else if (driver == QEMU_SOUND_SB16) { + return "sb16"; + } else if (driver == QEMU_SOUND_ES1370) { + return "es1370"; + } else if (driver == QEMU_SOUND_PCSPK) { + return "pcspk"; + } + + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("invalid sound driver '%d'"), driver); + return NULL; +} /* * Parses a libvirt XML definition of a guest, and populates the @@ -1486,6 +1521,25 @@ static struct qemud_vm_def *qemudParseXML(virConnectPtr conn, } } xmlXPathFreeObject(obj); + + /* Parse sound driver xml */ + obj = xmlXPathEval(BAD_CAST "/domain/devices/sound", ctxt); + if ((obj == NULL) || (obj->type != XPATH_NODESET) || + (obj->nodesetval == NULL) || (obj->nodesetval->nodeNr == 0)) { + def->soundDriver = QEMU_SOUND_NONE; + } else if ((prop = xmlGetProp(obj->nodesetval->nodeTab[0], + BAD_CAST "driver"))) { + + if ((def->soundDriver = qemudSoundDriverFromString(conn, + (char *) prop)) < 0) + goto error; + + xmlFree(prop); + prop = NULL; + } else { + def->soundDriver = QEMU_SOUND_NONE; + } + xmlXPathFreeObject(obj); obj = NULL; /* If graphics are enabled, there's an implicit PS2 mouse */ @@ -1694,6 +1748,7 @@ int qemudBuildCommandLine(virConnectPtr conn, (vm->def->os.cmdline[0] ? 2 : 0) + /* cmdline */ (vm->def->graphicsType == QEMUD_GRAPHICS_VNC ? 2 : (vm->def->graphicsType == QEMUD_GRAPHICS_SDL ? 0 : 1)) + /* graphics */ + (vm->def->soundDriver == QEMU_SOUND_NONE ? 0 : 2) + /* sound */ (vm->migrateFrom[0] ? 3 : 0); /* migrateFrom */ snprintf(memory, sizeof(memory), "%lu", vm->def->memory/1024); @@ -1970,6 +2025,14 @@ int qemudBuildCommandLine(virConnectPtr conn, /* SDL is the default. no args needed */ } + /* Add sound hardware */ + if (vm->def->soundDriver != QEMU_SOUND_NONE) { + if (!((*argv)[++n] = strdup("-soundhw"))) + goto no_memory; + if (!((*argv)[++n] = strdup((char *) qemudSoundDriverToString(conn, vm->def->soundDriver)))) + goto no_memory; + } + if (vm->migrateFrom[0]) { if (!((*argv)[++n] = strdup("-S"))) goto no_memory; @@ -3125,7 +3188,11 @@ char *qemudGenerateXML(virConnectPtr conn, break; } - if (def->graphicsType == QEMUD_GRAPHICS_VNC) { + if (def->soundDriver != QEMU_SOUND_NONE) { + if (virBufferVSprintf(buf, " \n", + qemudSoundDriverToString(conn, + def->soundDriver)) < 0) + goto no_memory; } if (virBufferAddLit(buf, " \n") < 0) diff --git a/src/qemu_conf.h b/src/qemu_conf.h index c59b1fa..1383c10 100644 --- a/src/qemu_conf.h +++ b/src/qemu_conf.h @@ -136,6 +136,14 @@ struct qemud_vm_input_def { struct qemud_vm_input_def *next; }; +enum qemu_vm_sound_driver { + QEMU_SOUND_NONE, + QEMU_SOUND_ALL, + QEMU_SOUND_SB16, + QEMU_SOUND_ES1370, + QEMU_SOUND_PCSPK, +}; + /* Flags for the 'type' field in next struct */ enum qemud_vm_device_type { QEMUD_DEVICE_DISK, @@ -214,6 +222,7 @@ struct qemud_vm_def { int vncActivePort; char vncListen[BR_INET_ADDR_MAXLEN]; char *keymap; + int soundDriver; int ndisks; struct qemud_vm_disk_def *disks; diff --git a/src/xend_internal.c b/src/xend_internal.c index 6ba4571..b470731 100644 --- a/src/xend_internal.c +++ b/src/xend_internal.c @@ -1783,6 +1783,18 @@ xend_parse_sexp_desc(virConnectPtr conn, struct sexpr *root, } } } + + if (sexpr_node(root, "domain/image/hvm/soundhw")) { + tmp = sexpr_node(root, "domain/image/hvm/soundhw"); + if (tmp && *tmp) { + if (STREQ(tmp, "all") || + STREQ(tmp, "pcspk") || + STREQ(tmp, "sb16") || + STREQ(tmp, "es1370")) { + virBufferVSprintf(&buf, " \n", tmp); + } + } + } } /* Graphics device (HVM <= 3.0.4, or PV <= 3.0.3) vnc config */ diff --git a/src/xm_internal.c b/src/xm_internal.c index 3d845dc..91c7cf1 100644 --- a/src/xm_internal.c +++ b/src/xm_internal.c @@ -934,6 +934,15 @@ char *xenXMDomainFormatXML(virConnectPtr conn, virConfPtr conf) { /* Ignore else branch - probably some other non-input device we don't support in libvirt yet */ } + + if ((xenXMConfigGetString(conf, "soundhw", &str) == 0) && str) { + if (STREQ(str, "all") || + STREQ(str, "pcspk") || + STREQ(str, "sb16") || + STREQ(str, "es1370")) { + virBufferVSprintf(buf, " \n", str); + } + } } /* HVM guests, or old PV guests use this config format */ @@ -2081,6 +2090,11 @@ virConfPtr xenXMParseXMLToConfig(virConnectPtr conn, const char *xml) { if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "usbdevice", "string(/domain/devices/input[@bus='usb' or (not(@bus) and @type='tablet')]/@type)", 1, "cannot set the usbdevice parameter") < 0) goto error; + + if (xenXMConfigSetStringFromXPath(conn, conf, ctxt, "soundhw", + "string(/domain/devices/sound[@driver]", + 1, "cannot set soundhw parameter") < 0) + goto error; } if (hvm || priv->xendConfigVersion < 3) { diff --git a/src/xml.c b/src/xml.c index 8e95103..f4bfb29 100644 --- a/src/xml.c +++ b/src/xml.c @@ -877,6 +877,14 @@ virDomainParseXMLOSDescHVM(virConnectPtr conn, xmlNodePtr node, nodes = NULL; } + cur = virXPathNode("/domain/devices/sound", ctxt); + if (cur) { + xmlChar *driver = NULL; + driver = xmlGetProp(cur, (xmlChar *) "driver"); + if (driver) + virBufferVSprintf(buf, "(soundhw '%s')", driver); + xmlFree(driver); + } res = virXPathBoolean("count(domain/devices/console) > 0", ctxt); if (res < 0) {