[PATCH 2/4] conf: allow to map sound device to host device

Daniel P. Berrangé berrange at redhat.com
Tue Jul 21 16:32:08 UTC 2020


On Sat, Jul 18, 2020 at 04:31:16PM +0400, Roman Bogorodskiy wrote:
> Extend <sound> device element to accept "soundDevice"
> sub-element which allows to map guest sound device to host
> sound device.
> 
> Example
> 
>   <sound model='ich6'>
>     <soundDevice playback='/dev/dsp0' recording='/dev/dsp0'/>
>   </sound>

IIUC, FreeBSD's audio subsystem is the classic OSS API ?

> 
> The "playback" attribute points to the playback device,
> and "recording" attribute points to the recording device.

I'm thinking about how we'll have to deal with QEMU's sound backend
options, and alignment with BHyve / FreeBSD.

In QEMU there are multiple backends, OSS, ALSA, PulseAudio, SPICE,
VNC, and many more. The backends have many properties, and many
of the properties can be set separately for input and output.

IIUC, QEMU can expose multiple sound devices to the guest too.

I think this means that we can have a M:N relationship between
a sound device, and an audio backend, not just 1:1.

Assuming I'm right about the M:N relationship, I assume that
of multiple cards all do playback concurrently, something
will have todo mixing of the streams ?  How will that work
with audio capture, is only one card allowed to capture at
any time ?

I'm copying Gerd to confirm the above...

Anyway, if we have M:N relation, then we'll need separate
configuration elements.

So I think we'd need to allow something like this:

   <sound model='ich6'>
     <audio id="audio0"/>
   </sound>

   <sound model='ich6'>
     <audio id="audio1"/>
   </sound>

   <sound model='ich6'>
     <audio id="audio1"/>
   </sound>

   <audio type="oss" id="audio0">
     <input dev='/dev/dsp0'/>
     <output dev='/dev/dsp0'/>
   </audio>

   <audio type="spice" id="audio1"/>


Here we have one sound device connected to OSS, and two sound
devices connected to SPICE. 

> 
> Signed-off-by: Roman Bogorodskiy <bogorodskiy at gmail.com>
> ---
>  docs/schemas/domaincommon.rng | 15 +++++++++++++++
>  src/conf/domain_conf.c        | 24 ++++++++++++++++++++++++
>  src/conf/domain_conf.h        |  3 +++
>  3 files changed, 42 insertions(+)
> 
> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
> index a810f569c6..b11b3f2af6 100644
> --- a/docs/schemas/domaincommon.rng
> +++ b/docs/schemas/domaincommon.rng
> @@ -4346,6 +4346,18 @@
>        </attribute>
>      </element>
>    </define>
> +  <define name="soundDevice">
> +    <element name="soundDevice">
> +       <attribute name="playback">
> +         <text/>
> +       </attribute>
> +       <optional>
> +         <attribute name="recording">
> +           <text/>
> +         </attribute>
> +       </optional>
> +    </element>
> +  </define>
>    <define name="sound">
>      <element name="sound">
>        <attribute name="model">
> @@ -4366,6 +4378,9 @@
>          <optional>
>            <ref name="address"/>
>          </optional>
> +	<optional>
> +	  <ref name="soundDevice"/>
> +	</optional>
>          <zeroOrMore>
>            <ref name="codec"/>
>          </zeroOrMore>
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 7ecd2818b9..b678a2319d 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -2850,6 +2850,9 @@ void virDomainSoundDefFree(virDomainSoundDefPtr def)
>          virDomainSoundCodecDefFree(def->codecs[i]);
>      VIR_FREE(def->codecs);
>  
> +    VIR_FREE(def->playback);
> +    VIR_FREE(def->recording);
> +
>      VIR_FREE(def);
>  }
>  
> @@ -14984,6 +14987,8 @@ virDomainSoundDefParseXML(virDomainXMLOptionPtr xmlopt,
>      virDomainSoundDefPtr def;
>      VIR_XPATH_NODE_AUTORESTORE(ctxt);
>      g_autofree char *model = NULL;
> +    char *recording = NULL;
> +    xmlNodePtr soundDeviceNode;
>  
>      if (VIR_ALLOC(def) < 0)
>          return NULL;
> @@ -15024,6 +15029,14 @@ virDomainSoundDefParseXML(virDomainXMLOptionPtr xmlopt,
>          }
>      }
>  
> +    soundDeviceNode = virXPathNode("./soundDevice", ctxt);
> +    if (soundDeviceNode) {
> +        def->playback = virXMLPropString(soundDeviceNode, "playback");
> +        recording = virXMLPropString(soundDeviceNode, "recording");
> +        if (recording)
> +            def->recording = recording;
> +    }
> +
>      if (virDomainDeviceInfoParseXML(xmlopt, node, &def->info, flags) < 0)
>          goto error;
>  
> @@ -15056,6 +15069,9 @@ virDomainSoundDefEquals(const virDomainSoundDef *a,
>          !virDomainDeviceInfoAddressIsEqual(&a->info, &b->info))
>          return false;
>  
> +    if ((a->playback != b->playback) || (a->recording != b->recording))
> +        return false;
> +
>      return true;
>  }
>  
> @@ -27284,6 +27300,14 @@ virDomainSoundDefFormat(virBufferPtr buf,
>      for (i = 0; i < def->ncodecs; i++)
>          virDomainSoundCodecDefFormat(&childBuf, def->codecs[i]);
>  
> +    if (def->playback) {
> +        virBufferAsprintf(&childBuf, "<soundDevice playback='%s'", def->playback);
> +        if (def->recording)
> +            virBufferAsprintf(&childBuf, " recording='%s'/>\n", def->recording);
> +        else
> +            virBufferAddLit(&childBuf, "/>\n");
> +    }
> +
>      if (virDomainDeviceInfoFormat(&childBuf, &def->info, flags) < 0)
>          return -1;
>  
> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> index 241149af24..b501f48442 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -1415,6 +1415,9 @@ struct _virDomainSoundDef {
>  
>      size_t ncodecs;
>      virDomainSoundCodecDefPtr *codecs;
> +
> +    char *playback;
> +    char *recording;
>  };
>  
>  typedef enum {
> -- 
> 2.27.0
> 

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