Re: [PATCH v3 3/6] conf: allow to map sound device to host device

2020-08-07 Thread Daniel P . Berrangé
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

2020-08-07 Thread Roman Bogorodskiy
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