Re: [PATCH v3 3/6] conf: allow to map sound device to host device
On Fri, Aug 07, 2020 at 07:09:32PM +0400, Roman Bogorodskiy wrote: > Introduce a new device element "" which allows > to map guest sound device specified using the "" > element to specific audio backend. > > Example: > > > > > > > > > > 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 > --- > 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, >audioId) < 0 || > +def->audioId == 0) { > +virReportError(VIR_ERR_XML_ERROR, > + _("Invalid audio 'id' value '%s'"), tmp); > +goto error; > +} > +} > + > if
[PATCH v3 3/6] conf: allow to map sound device to host device
Introduce a new device element "" which allows to map guest sound device specified using the "" element to specific audio backend. Example: 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 --- 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(-) diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index fb9638f3f6..c933c71035 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4372,12 +4372,47 @@ + + + + + + + + + + + + + + + oss + + + + + + + + + + + + + + + + + + + + @@ -5303,6 +5338,7 @@ + diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index d61108e125..59ad8937a4 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -688,6 +688,10 @@ virDomainCapsDeviceDefValidate(const virDomainCaps *caps, ret = virDomainCapsDeviceVideoDefValidate(caps, dev->data.video); break; +case VIR_DOMAIN_DEVICE_AUDIO: +/* TODO: add validation */ +break; + case VIR_DOMAIN_DEVICE_DISK: case VIR_DOMAIN_DEVICE_REDIRDEV: case VIR_DOMAIN_DEVICE_NET: diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index f9cdc4efa9..165d5d5f7a 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -323,6 +323,7 @@ VIR_ENUM_IMPL(virDomainDevice, "memory", "iommu", "vsock", + "audio", ); VIR_ENUM_IMPL(virDomainDiskDevice, @@ -729,6 +730,11 @@ VIR_ENUM_IMPL(virDomainSoundModel, "ich7", ); +VIR_ENUM_IMPL(virDomainAudioType, + VIR_DOMAIN_AUDIO_TYPE_LAST, + "oss", +); + VIR_ENUM_IMPL(virDomainKeyWrapCipherName, VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_LAST, "aes", @@ -2872,6 +2878,24 @@ void virDomainSoundDefFree(virDomainSoundDefPtr def) VIR_FREE(def); } +void virDomainAudioDefFree(virDomainAudioDefPtr def) +{ +if (!def) +return; + +switch (def->type) { +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