[Libvir] [PATCH] sound support for qemu and xen

Jerone Young jyoung5 at us.ibm.com
Tue Apr 22 15:29:17 UTC 2008


I was actually thinking about doing this very patch :-) . Are you going
to also enable virt-manager to make use of it ? Since it's just good old
qemu it will be great for local KVM use.

Though it would be really nice if pulse audio support to where added to
qemu. Then someway expose options also through libvirt on which audio
subsystem to use (oss, alsa, or pulseaudio). Then with pulse audio you
do have the ability to transport it over the net (though never tried it
or set it up yet), to work with remote clients.


On Mon, 2008-04-21 at 13:02 -0400, Cole Robinson wrote:
> The patch below adds xml support for the soundhw option to qemu
> and xen. The new xml element takes the form:
> 
> <sound driver='drivername'/>
> 
> Where driver name can be pcspk, sb16, es1370, or all.
> 
> 
> Everything seems to be in working order but I have a few
> implementation questions:
> 
> 1) Should multiple drivers be able to be specified? qemu
> accommodates this, allowing  '-soundhw sb16,pcspk' for example.
> If this should be allowed, what should the xml format be? 
> 
> 2) Should acceptable driver options be hardcoded? The other option
> is to just pass the input straight to qemu. This patch has the
> options hardcoded.
> 
> Also I realize this will probably need to be rediff'd around
> Dan's serial + parallel device patch, but I figured I would just
> get this out there.
> 
> Thanks,
> Cole
> plain text document attachment (libvirt-sound-patch)
> 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, "    <sound driver='%s'/>\n",
> +                              qemudSoundDriverToString(conn,
> +                                                       def->soundDriver)) < 0)
> +            goto no_memory;
>      }
> 
>      if (virBufferAddLit(buf, "  </devices>\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, "    <sound driver='%s'/>\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, "    <sound driver='%s'/>\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) {
> --
> Libvir-list mailing list
> Libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list




More information about the libvir-list mailing list