[PATCH v3 3/6] conf: allow to map sound device to host device
Daniel P. Berrangé
berrange at redhat.com
Fri Aug 7 16:07:55 UTC 2020
On Fri, Aug 07, 2020 at 07:09:32PM +0400, Roman Bogorodskiy wrote:
> Introduce a new device element "<audio>" which allows
> to map guest sound device specified using the "<sound>"
> element to specific audio backend.
>
> Example:
>
> <sound model='ich7'>
> <audio id='1'/>
> </sound>
> <audio id='1' type='oss'>
> <input dev='/dev/dsp0'/>
> <output dev='/dev/dsp0'/>
> </audio>
>
> This block maps to OSS audio backend on the host using
> /dev/dsp0 device for both input (recording)
> and output (playback).
>
> OSS is the only backend supported so far.
>
> Signed-off-by: Roman Bogorodskiy <bogorodskiy at gmail.com>
> ---
> docs/schemas/domaincommon.rng | 36 +++++++
> src/conf/domain_capabilities.c | 4 +
> src/conf/domain_conf.c | 176 ++++++++++++++++++++++++++++++++-
> src/conf/domain_conf.h | 28 ++++++
> src/conf/virconftypes.h | 3 +
> src/libvirt_private.syms | 2 +
> src/qemu/qemu_command.c | 1 +
> src/qemu/qemu_domain.c | 1 +
> src/qemu/qemu_domain_address.c | 2 +
> src/qemu/qemu_driver.c | 5 +
> src/qemu/qemu_hotplug.c | 3 +
> src/qemu/qemu_validate.c | 1 +
> 12 files changed, 260 insertions(+), 2 deletions(-)
> +void virDomainAudioDefFree(virDomainAudioDefPtr def)
> +{
> + if (!def)
> + return;
> +
> + switch (def->type) {
Cast to (virDomainAudioType), so the compiler forces the
existance of all possible cases.
> + case VIR_DOMAIN_AUDIO_TYPE_OSS:
> + VIR_FREE(def->backend.oss.inputDev);
> + VIR_FREE(def->backend.oss.outputDev);
> + break;
> +
> + case VIR_DOMAIN_AUDIO_TYPE_LAST:
> + break;
> + }
> +
> + VIR_FREE(def);
> +}
> +
> virDomainSoundDefPtr
> virDomainSoundDefRemove(virDomainDefPtr def, size_t idx)
> {
> @@ -3225,6 +3249,9 @@ void virDomainDeviceDefFree(virDomainDeviceDefPtr def)
> case VIR_DOMAIN_DEVICE_VSOCK:
> virDomainVsockDefFree(def->data.vsock);
> break;
> + case VIR_DOMAIN_DEVICE_AUDIO:
> + virDomainAudioDefFree(def->data.audio);
> + break;
> case VIR_DOMAIN_DEVICE_LAST:
> case VIR_DOMAIN_DEVICE_NONE:
> break;
> @@ -3485,6 +3512,10 @@ void virDomainDefFree(virDomainDefPtr def)
> virDomainSoundDefFree(def->sounds[i]);
> VIR_FREE(def->sounds);
>
> + for (i = 0; i < def->naudios; i++)
> + virDomainAudioDefFree(def->audios[i]);
> + VIR_FREE(def->audios);
> +
> for (i = 0; i < def->nvideos; i++)
> virDomainVideoDefFree(def->videos[i]);
> VIR_FREE(def->videos);
> @@ -4073,6 +4104,7 @@ virDomainDeviceGetInfo(virDomainDeviceDefPtr device)
> case VIR_DOMAIN_DEVICE_LEASE:
> case VIR_DOMAIN_DEVICE_GRAPHICS:
> case VIR_DOMAIN_DEVICE_IOMMU:
> + case VIR_DOMAIN_DEVICE_AUDIO:
> case VIR_DOMAIN_DEVICE_LAST:
> case VIR_DOMAIN_DEVICE_NONE:
> break;
> @@ -4167,6 +4199,9 @@ virDomainDeviceSetData(virDomainDeviceDefPtr device,
> case VIR_DOMAIN_DEVICE_LEASE:
> device->data.lease = devicedata;
> break;
> + case VIR_DOMAIN_DEVICE_AUDIO:
> + device->data.audio = devicedata;
> + break;
> case VIR_DOMAIN_DEVICE_NONE:
> case VIR_DOMAIN_DEVICE_LAST:
> break;
> @@ -4433,6 +4468,7 @@ virDomainDeviceInfoIterateInternal(virDomainDefPtr def,
> case VIR_DOMAIN_DEVICE_MEMORY:
> case VIR_DOMAIN_DEVICE_IOMMU:
> case VIR_DOMAIN_DEVICE_VSOCK:
> + case VIR_DOMAIN_DEVICE_AUDIO:
> break;
> }
> #endif
> @@ -5425,6 +5461,7 @@ virDomainDeviceDefPostParseCommon(virDomainDeviceDefPtr dev,
> case VIR_DOMAIN_DEVICE_PANIC:
> case VIR_DOMAIN_DEVICE_MEMORY:
> case VIR_DOMAIN_DEVICE_IOMMU:
> + case VIR_DOMAIN_DEVICE_AUDIO:
> ret = 0;
> break;
>
> @@ -6814,6 +6851,8 @@ virDomainDeviceDefValidateInternal(const virDomainDeviceDef *dev,
> case VIR_DOMAIN_DEVICE_SHMEM:
> return virDomainShmemDefValidate(dev->data.shmem);
>
> + case VIR_DOMAIN_DEVICE_AUDIO:
> + /* TODO: validate? */
> case VIR_DOMAIN_DEVICE_LEASE:
> case VIR_DOMAIN_DEVICE_FS:
> case VIR_DOMAIN_DEVICE_SOUND:
> @@ -15016,10 +15055,10 @@ virDomainSoundDefParseXML(virDomainXMLOptionPtr xmlopt,
> virDomainSoundDefPtr def;
> VIR_XPATH_NODE_AUTORESTORE(ctxt);
> g_autofree char *model = NULL;
> + xmlNodePtr audioNode;
>
> if (VIR_ALLOC(def) < 0)
> return NULL;
> -
> ctxt->node = node;
>
> model = virXMLPropString(node, "model");
> @@ -15056,6 +15095,18 @@ virDomainSoundDefParseXML(virDomainXMLOptionPtr xmlopt,
> }
> }
>
> + audioNode = virXPathNode("./audio", ctxt);
> + if (audioNode) {
> + g_autofree char *tmp = NULL;
> + tmp = virXMLPropString(audioNode, "id");
> + if (virStrToLong_ui(tmp, NULL, 10, &def->audioId) < 0 ||
> + def->audioId == 0) {
> + virReportError(VIR_ERR_XML_ERROR,
> + _("Invalid audio 'id' value '%s'"), tmp);
> + goto error;
> + }
> + }
> +
> if (virDomainDeviceInfoParseXML(xmlopt, node, &def->info, flags) < 0)
> goto error;
>
> @@ -15107,6 +15158,58 @@ virDomainSoundDefFind(const virDomainDef *def,
> }
>
>
> +static virDomainAudioDefPtr
> +virDomainAudioDefParseXML(virDomainXMLOptionPtr xmlopt G_GNUC_UNUSED,
> + xmlNodePtr node G_GNUC_UNUSED,
> + xmlXPathContextPtr ctxt G_GNUC_UNUSED)
> +{
> + virDomainAudioDefPtr def;
> + VIR_XPATH_NODE_AUTORESTORE(ctxt);
> + g_autofree char *tmp = NULL;
> + g_autofree char *type = NULL;
> +
> + if (VIR_ALLOC(def) < 0)
> + return NULL;
> + ctxt->node = node;
> +
> + type = virXMLPropString(node, "type");
> + if ((def->type = virDomainAudioTypeTypeFromString(type)) < 0) {
> + virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
> + _("unknown audio type '%s'"), type);
> + goto error;
> + }
> +
> + tmp = virXMLPropString(node, "id");
> + if (virStrToLong_ui(tmp, NULL, 10, &def->id) < 0 ||
> + def->id == 0) {
> + virReportError(VIR_ERR_XML_ERROR,
> + _("invalid audio 'id' value '%s'"), tmp);
> + goto error;
> + }
> +
> + if (def->type == VIR_DOMAIN_AUDIO_TYPE_OSS) {
Use a switch here again to force compiler checking of all csaes.
> + xmlNodePtr inputDevNode, outputDevNode;
> +
> + inputDevNode = virXPathNode("./input", ctxt);
> + outputDevNode = virXPathNode("./output", ctxt);
> +
> + if (!inputDevNode || !outputDevNode) {
> + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> + _("Audio type OSS requires to have <input> "
> + "and <output> specified"));
> + goto error;
> + }
> +
> + def->backend.oss.inputDev = virXMLPropString(inputDevNode, "dev");
> + def->backend.oss.outputDev = virXMLPropString(outputDevNode, "dev");
> + }
Looks fine bar the switch()
Regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
More information about the libvir-list
mailing list