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) {