conf: add support for audio backend specific settings
This pulls in the remaining QEMU audio backend specific settings to the XML schema. <audio id="1" type="alsa"> <input dev="/dev/dsp0"/> <output dev="/dev/dsp1"/> </audio> <audio id="1" type="coreaudio"> <input bufferCount="50"/> <output bufferCount="42"/> </audio> <audio id="1" type="file" path="audio.wav"/> <audio id="1" type="jack"> <input serverName="fish" clientName="food" connectPorts="yum"/> <output serverName="fish" clientName="food" connectPorts="yum"/> </audio> <audio id="1" type="oss" tryMMap="yes" exclusive="yes" dspPolicy="3"> <input dev="/dev/dsp0" bufferCount="50" tryPoll="yes"/> <output dev="/dev/dsp1" bufferCount="30" tryPoll="no"/> </audio> <audio id="1" type="pulseaudio" serverName="acme.example.org"> <input name="fish" streamName="food" latency="100"/> <output name="fish" streamName="food" latency="200"/> </audio> <audio type='sdl' id='1' driver='pulseaudio'> <input bufferCount='40'/> <output bufferCount='40'/> </audio> Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
c99e72d18d
commit
3e97d81a81
@ -6929,29 +6929,6 @@ ALSA audio backend
|
|||||||
|
|
||||||
The 'alsa' audio type uses the ALSA host audio device framework.
|
The 'alsa' audio type uses the ALSA host audio device framework.
|
||||||
|
|
||||||
:since:`Since 7.2.0, qemu`
|
|
||||||
|
|
||||||
Coreaudio audio backend
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
The 'coreaudio' audio backend delegates to a CoreAudio host audio framework
|
|
||||||
for input and output on macOS.
|
|
||||||
|
|
||||||
:since:`Since 7.2.0, qemu`
|
|
||||||
|
|
||||||
Jack audio backend
|
|
||||||
^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
The 'jack' audio backend delegates to a Jack daemon for audio input
|
|
||||||
and output.
|
|
||||||
|
|
||||||
:since:`Since 7.2.0, qemu`
|
|
||||||
|
|
||||||
OSS audio backend
|
|
||||||
^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
The 'oss' audio type uses the OSS host audio device framework.
|
|
||||||
|
|
||||||
The following additional attributes are permitted on the ``<input>``
|
The following additional attributes are permitted on the ``<input>``
|
||||||
and ``<output>`` elements
|
and ``<output>`` elements
|
||||||
|
|
||||||
@ -6962,9 +6939,116 @@ and ``<output>`` elements
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
<audio type='oss' id='1'>
|
<audio id="1" type="alsa">
|
||||||
<input dev='/dev/dsp0'/>
|
<input dev="/dev/dsp0"/>
|
||||||
<output dev='/dev/dsp0'/>
|
<output dev="/dev/dsp1"/>
|
||||||
|
</audio>
|
||||||
|
|
||||||
|
:since:`Since 7.2.0, qemu`
|
||||||
|
|
||||||
|
Coreaudio audio backend
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The 'coreaudio' audio backend delegates to a CoreAudio host audio framework
|
||||||
|
for input and output on macOS.
|
||||||
|
|
||||||
|
The following additional attributes are permitted on the ``<input>``
|
||||||
|
and ``<output>`` elements
|
||||||
|
|
||||||
|
* ``bufferCount``
|
||||||
|
|
||||||
|
The number of buffers. It is recommended to set the ``bufferLength``
|
||||||
|
attribute at the same time.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
<audio id="1" type="coreaudio">
|
||||||
|
<input bufferCount="50"/>
|
||||||
|
<output bufferCount="42"/>
|
||||||
|
</audio>
|
||||||
|
|
||||||
|
:since:`Since 7.2.0, qemu`
|
||||||
|
|
||||||
|
Jack audio backend
|
||||||
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The 'jack' audio backend delegates to a Jack daemon for audio input
|
||||||
|
and output.
|
||||||
|
|
||||||
|
The following additional attributes are permitted on the ``<input>``
|
||||||
|
and ``<output>`` elements
|
||||||
|
|
||||||
|
* ``serverName``
|
||||||
|
|
||||||
|
Select the Jack server instance to connect to.
|
||||||
|
|
||||||
|
* ``clientName``
|
||||||
|
|
||||||
|
The client name to identify as. The server may modify this to
|
||||||
|
ensure uniqueness unless ``exactName`` is enabled
|
||||||
|
|
||||||
|
* ``connectPorts``
|
||||||
|
|
||||||
|
A regular expression of Jack client port names to monitor and
|
||||||
|
connect to.
|
||||||
|
|
||||||
|
* ``exactName``
|
||||||
|
|
||||||
|
Use the exact ``clientName`` requested
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
<audio id="1" type="jack">
|
||||||
|
<input serverName="fish" clientName="food" connectPorts="system:capture_[13]" exactName="yes"/>
|
||||||
|
<output serverName="fish" clientName="food" connectPorts="system:playback_[13]" exactName="yes"/>
|
||||||
|
</audio>
|
||||||
|
|
||||||
|
:since:`Since 7.2.0, qemu`
|
||||||
|
|
||||||
|
OSS audio backend
|
||||||
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The 'oss' audio type uses the OSS host audio device framework.
|
||||||
|
|
||||||
|
The following additional attributes are permitted on the ``<audio>``
|
||||||
|
element
|
||||||
|
|
||||||
|
* ``tryMMap``
|
||||||
|
|
||||||
|
Attempt to use mmap for data transfer
|
||||||
|
|
||||||
|
* ``exclusive``
|
||||||
|
|
||||||
|
Enforce exclusive access to the host device
|
||||||
|
|
||||||
|
* ``dspPolicy``
|
||||||
|
|
||||||
|
Set the timing policy of the device, values between -1 and 10.
|
||||||
|
Smaller numbers result in lower latency but higher CPU usage.
|
||||||
|
A negatve value requests use of fragment mode.
|
||||||
|
|
||||||
|
The following additional attributes are permitted on the ``<input>``
|
||||||
|
and ``<output>`` elements
|
||||||
|
|
||||||
|
* ``dev``
|
||||||
|
|
||||||
|
Path to the host device node to connect the backend to. A hypervisor
|
||||||
|
specific default applies if not specified.
|
||||||
|
|
||||||
|
* ``bufferCount``
|
||||||
|
|
||||||
|
The number of buffers. It is recommended to set the ``bufferLength``
|
||||||
|
attribute at the same time.
|
||||||
|
|
||||||
|
* ``tryPoll``
|
||||||
|
|
||||||
|
Attempt to use polling mode
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
<audio type='oss' id='1' tryMMap='yes' exclusive='yes' dspPolicy='4'>
|
||||||
|
<input dev='/dev/dsp0' bufferCount='40' tryPoll='yes'/>
|
||||||
|
<output dev='/dev/dsp0' bufferCount='40' tryPoll='yes'/>
|
||||||
</audio>
|
</audio>
|
||||||
|
|
||||||
:since:`Since 6.7.0, bhyve; Since 7.2.0, qemu`
|
:since:`Since 6.7.0, bhyve; Since 7.2.0, qemu`
|
||||||
@ -6975,6 +7059,35 @@ PulseAudio audio backend
|
|||||||
The 'pulseaudio' audio backend delegates to a PulseAudio daemon audio input
|
The 'pulseaudio' audio backend delegates to a PulseAudio daemon audio input
|
||||||
and output.
|
and output.
|
||||||
|
|
||||||
|
The following additional attributes are permitted on the ``<audio>``
|
||||||
|
element
|
||||||
|
|
||||||
|
* ``serverName``
|
||||||
|
|
||||||
|
Hostname of the PulseAudio server
|
||||||
|
|
||||||
|
The following additional attributes are permitted on the ``<input>``
|
||||||
|
and ``<output>`` elements
|
||||||
|
|
||||||
|
* ``name``
|
||||||
|
|
||||||
|
The sink/source name to use
|
||||||
|
|
||||||
|
* ``streamName``
|
||||||
|
|
||||||
|
The name to identify the stream associated with the VM
|
||||||
|
|
||||||
|
* ``latency``
|
||||||
|
|
||||||
|
Desired latency for the server to target in microseconds
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
<audio id="1" type="pulseaudio" serverName="acme.example.org">
|
||||||
|
<input name="fish" streamName="food" latency="100"/>
|
||||||
|
<output name="fish" streamName="food" latency="200"/>
|
||||||
|
</audio>
|
||||||
|
|
||||||
:since:`Since 7.2.0, qemu`
|
:since:`Since 7.2.0, qemu`
|
||||||
|
|
||||||
SDL audio backend
|
SDL audio backend
|
||||||
@ -6991,9 +7104,20 @@ element
|
|||||||
SDL audio driver. The ``name`` attribute specifies SDL driver name,
|
SDL audio driver. The ``name`` attribute specifies SDL driver name,
|
||||||
one of 'esd', 'alsa', 'arts', 'pulseaudio'.
|
one of 'esd', 'alsa', 'arts', 'pulseaudio'.
|
||||||
|
|
||||||
|
The following additional attributes are permitted on the ``<input>``
|
||||||
|
and ``<output>`` elements
|
||||||
|
|
||||||
|
* ``bufferCount``
|
||||||
|
|
||||||
|
The number of buffers. It is recommended to set the ``bufferLength``
|
||||||
|
attribute at the same time.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
<audio type='sdl' id='1' driver='pulseaudio'/>
|
<audio type='sdl' id='1' driver='pulseaudio'>
|
||||||
|
<input bufferCount='40'/>
|
||||||
|
<output bufferCount='40'/>
|
||||||
|
</audio>
|
||||||
|
|
||||||
:since:`Since 7.2.0, qemu`
|
:since:`Since 7.2.0, qemu`
|
||||||
|
|
||||||
@ -7005,6 +7129,10 @@ it does not connect to any host audio framework. It exclusively
|
|||||||
allows a SPICE server to send and receive audio. This is the default
|
allows a SPICE server to send and receive audio. This is the default
|
||||||
backend when SPICE graphics are enabled in QEMU.
|
backend when SPICE graphics are enabled in QEMU.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
<audio type='spice' id='1'/>
|
||||||
|
|
||||||
:since:`Since 7.2.0, qemu`
|
:since:`Since 7.2.0, qemu`
|
||||||
|
|
||||||
File audio backend
|
File audio backend
|
||||||
@ -7014,6 +7142,10 @@ The 'file' audio backend is an output only driver which records
|
|||||||
audio to a file. The file format is implementation defined, and
|
audio to a file. The file format is implementation defined, and
|
||||||
defaults to 'WAV' with QEMU.
|
defaults to 'WAV' with QEMU.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
<audio id="1" type="file" path="audio.wav"/>
|
||||||
|
|
||||||
:since:`Since 7.2.0, qemu`
|
:since:`Since 7.2.0, qemu`
|
||||||
|
|
||||||
:anchor:`<a id="elementsWatchdog"/>`
|
:anchor:`<a id="elementsWatchdog"/>`
|
||||||
|
@ -4608,6 +4608,26 @@
|
|||||||
|
|
||||||
<define name="audiojack">
|
<define name="audiojack">
|
||||||
<ref name="audiocommonattr"/>
|
<ref name="audiocommonattr"/>
|
||||||
|
<optional>
|
||||||
|
<attribute name="serverName">
|
||||||
|
<data type="string"/>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<attribute name="clientName">
|
||||||
|
<data type="string"/>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<attribute name="connectPorts">
|
||||||
|
<data type="string"/>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<attribute name="exactName">
|
||||||
|
<ref name="virYesNo"/>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
<ref name="audiocommonchild"/>
|
<ref name="audiocommonchild"/>
|
||||||
</define>
|
</define>
|
||||||
|
|
||||||
@ -4618,16 +4638,46 @@
|
|||||||
<ref name="deviceName"/>
|
<ref name="deviceName"/>
|
||||||
</attribute>
|
</attribute>
|
||||||
</optional>
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<attribute name="bufferCount">
|
||||||
|
<ref name="uint32"/>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<attribute name="tryPoll">
|
||||||
|
<ref name="virYesNo"/>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
<ref name="audiocommonchild"/>
|
<ref name="audiocommonchild"/>
|
||||||
</define>
|
</define>
|
||||||
|
|
||||||
<define name="audiopulseaudio">
|
<define name="audiopulseaudio">
|
||||||
<ref name="audiocommonattr"/>
|
<ref name="audiocommonattr"/>
|
||||||
|
<optional>
|
||||||
|
<attribute name="name">
|
||||||
|
<data type="string"/>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<attribute name="streamName">
|
||||||
|
<data type="string"/>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<attribute name="latency">
|
||||||
|
<ref name="uint32"/>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
<ref name="audiocommonchild"/>
|
<ref name="audiocommonchild"/>
|
||||||
</define>
|
</define>
|
||||||
|
|
||||||
<define name="audiosdl">
|
<define name="audiosdl">
|
||||||
<ref name="audiocommonattr"/>
|
<ref name="audiocommonattr"/>
|
||||||
|
<optional>
|
||||||
|
<attribute name="bufferCount">
|
||||||
|
<ref name="uint32"/>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
<ref name="audiocommonchild"/>
|
<ref name="audiocommonchild"/>
|
||||||
</define>
|
</define>
|
||||||
|
|
||||||
@ -4721,6 +4771,21 @@
|
|||||||
<value>oss</value>
|
<value>oss</value>
|
||||||
</choice>
|
</choice>
|
||||||
</attribute>
|
</attribute>
|
||||||
|
<optional>
|
||||||
|
<attribute name="tryMMap">
|
||||||
|
<ref name="virYesNo"/>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<attribute name="exclusive">
|
||||||
|
<ref name="virYesNo"/>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<attribute name="dspPolicy">
|
||||||
|
<data type="int"/>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
<interleave>
|
<interleave>
|
||||||
<optional>
|
<optional>
|
||||||
<element name="input">
|
<element name="input">
|
||||||
@ -4738,6 +4803,11 @@
|
|||||||
<attribute name="type">
|
<attribute name="type">
|
||||||
<value>pulseaudio</value>
|
<value>pulseaudio</value>
|
||||||
</attribute>
|
</attribute>
|
||||||
|
<optional>
|
||||||
|
<attribute name="serverName">
|
||||||
|
<data type="string"/>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
<interleave>
|
<interleave>
|
||||||
<optional>
|
<optional>
|
||||||
<element name="input">
|
<element name="input">
|
||||||
@ -4799,6 +4869,11 @@
|
|||||||
<attribute name="type">
|
<attribute name="type">
|
||||||
<value>file</value>
|
<value>file</value>
|
||||||
</attribute>
|
</attribute>
|
||||||
|
<optional>
|
||||||
|
<attribute name="path">
|
||||||
|
<ref name="filePath"/>
|
||||||
|
</attribute>
|
||||||
|
</optional>
|
||||||
<interleave>
|
<interleave>
|
||||||
<optional>
|
<optional>
|
||||||
<element name="input">
|
<element name="input">
|
||||||
|
@ -2918,12 +2918,33 @@ void virDomainSoundDefFree(virDomainSoundDefPtr def)
|
|||||||
g_free(def);
|
g_free(def);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
virDomainAudioIOALSAFree(virDomainAudioIOALSAPtr def)
|
||||||
|
{
|
||||||
|
g_free(def->dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
virDomainAudioIOJackFree(virDomainAudioIOJackPtr def)
|
||||||
|
{
|
||||||
|
g_free(def->serverName);
|
||||||
|
g_free(def->clientName);
|
||||||
|
g_free(def->connectPorts);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
virDomainAudioIOOSSFree(virDomainAudioIOOSSPtr def)
|
virDomainAudioIOOSSFree(virDomainAudioIOOSSPtr def)
|
||||||
{
|
{
|
||||||
g_free(def->dev);
|
g_free(def->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
virDomainAudioIOPulseAudioFree(virDomainAudioIOPulseAudioPtr def)
|
||||||
|
{
|
||||||
|
g_free(def->name);
|
||||||
|
g_free(def->streamName);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
virDomainAudioDefFree(virDomainAudioDefPtr def)
|
virDomainAudioDefFree(virDomainAudioDefPtr def)
|
||||||
{
|
{
|
||||||
@ -2935,12 +2956,16 @@ virDomainAudioDefFree(virDomainAudioDefPtr def)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_ALSA:
|
case VIR_DOMAIN_AUDIO_TYPE_ALSA:
|
||||||
|
virDomainAudioIOALSAFree(&def->backend.alsa.input);
|
||||||
|
virDomainAudioIOALSAFree(&def->backend.alsa.output);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_COREAUDIO:
|
case VIR_DOMAIN_AUDIO_TYPE_COREAUDIO:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_JACK:
|
case VIR_DOMAIN_AUDIO_TYPE_JACK:
|
||||||
|
virDomainAudioIOJackFree(&def->backend.jack.input);
|
||||||
|
virDomainAudioIOJackFree(&def->backend.jack.output);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_OSS:
|
case VIR_DOMAIN_AUDIO_TYPE_OSS:
|
||||||
@ -2949,6 +2974,9 @@ virDomainAudioDefFree(virDomainAudioDefPtr def)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_PULSEAUDIO:
|
case VIR_DOMAIN_AUDIO_TYPE_PULSEAUDIO:
|
||||||
|
virDomainAudioIOPulseAudioFree(&def->backend.pulseaudio.input);
|
||||||
|
virDomainAudioIOPulseAudioFree(&def->backend.pulseaudio.output);
|
||||||
|
g_free(def->backend.pulseaudio.serverName);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_SDL:
|
case VIR_DOMAIN_AUDIO_TYPE_SDL:
|
||||||
@ -2958,6 +2986,7 @@ virDomainAudioDefFree(virDomainAudioDefPtr def)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_FILE:
|
case VIR_DOMAIN_AUDIO_TYPE_FILE:
|
||||||
|
g_free(def->backend.file.path);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_LAST:
|
case VIR_DOMAIN_AUDIO_TYPE_LAST:
|
||||||
@ -14046,12 +14075,118 @@ virDomainAudioCommonParse(virDomainAudioIOCommonPtr def,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
virDomainAudioALSAParse(virDomainAudioIOALSAPtr def,
|
||||||
|
xmlNodePtr node)
|
||||||
|
{
|
||||||
|
def->dev = virXMLPropString(node, "dev");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virDomainAudioCoreAudioParse(virDomainAudioIOCoreAudioPtr def,
|
||||||
|
xmlNodePtr node)
|
||||||
|
{
|
||||||
|
g_autofree char *bufferCount = virXMLPropString(node, "bufferCount");
|
||||||
|
|
||||||
|
if (bufferCount &&
|
||||||
|
virStrToLong_ui(bufferCount, NULL, 10,
|
||||||
|
&def->bufferCount) < 0) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
|
_("cannot parse 'bufferCount' value '%s'"), bufferCount);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virDomainAudioJackParse(virDomainAudioIOJackPtr def,
|
||||||
|
xmlNodePtr node)
|
||||||
|
{
|
||||||
|
g_autofree char *exactName = virXMLPropString(node, "exactName");
|
||||||
|
|
||||||
|
def->serverName = virXMLPropString(node, "serverName");
|
||||||
|
def->clientName = virXMLPropString(node, "clientName");
|
||||||
|
def->connectPorts = virXMLPropString(node, "connectPorts");
|
||||||
|
|
||||||
|
if (exactName &&
|
||||||
|
((def->exactName =
|
||||||
|
virTristateBoolTypeFromString(exactName)) <= 0)) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
|
_("unknown 'exactName' value '%s'"), exactName);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
virDomainAudioOSSParse(virDomainAudioIOOSSPtr def,
|
virDomainAudioOSSParse(virDomainAudioIOOSSPtr def,
|
||||||
xmlNodePtr node)
|
xmlNodePtr node)
|
||||||
{
|
{
|
||||||
|
g_autofree char *tryPoll = virXMLPropString(node, "tryPoll");
|
||||||
|
g_autofree char *bufferCount = virXMLPropString(node, "bufferCount");
|
||||||
|
|
||||||
def->dev = virXMLPropString(node, "dev");
|
def->dev = virXMLPropString(node, "dev");
|
||||||
|
|
||||||
|
if (tryPoll &&
|
||||||
|
((def->tryPoll =
|
||||||
|
virTristateBoolTypeFromString(tryPoll)) <= 0)) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
|
_("unknown 'tryPoll' value '%s'"), tryPoll);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bufferCount &&
|
||||||
|
virStrToLong_ui(bufferCount, NULL, 10,
|
||||||
|
&def->bufferCount) < 0) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
|
_("cannot parse 'bufferCount' value '%s'"), bufferCount);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virDomainAudioPulseAudioParse(virDomainAudioIOPulseAudioPtr def,
|
||||||
|
xmlNodePtr node)
|
||||||
|
{
|
||||||
|
g_autofree char *latency = virXMLPropString(node, "latency");
|
||||||
|
|
||||||
|
def->name = virXMLPropString(node, "name");
|
||||||
|
def->streamName = virXMLPropString(node, "streamName");
|
||||||
|
|
||||||
|
if (latency &&
|
||||||
|
virStrToLong_ui(latency, NULL, 10,
|
||||||
|
&def->latency) < 0) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
|
_("cannot parse 'latency' value '%s'"), latency);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virDomainAudioSDLParse(virDomainAudioIOSDLPtr def,
|
||||||
|
xmlNodePtr node)
|
||||||
|
{
|
||||||
|
g_autofree char *bufferCount = virXMLPropString(node, "bufferCount");
|
||||||
|
|
||||||
|
if (bufferCount &&
|
||||||
|
virStrToLong_ui(bufferCount, NULL, 10,
|
||||||
|
&def->bufferCount) < 0) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
|
_("cannot parse 'bufferCount' value '%s'"), bufferCount);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14109,22 +14244,69 @@ virDomainAudioDefParseXML(virDomainXMLOptionPtr xmlopt G_GNUC_UNUSED,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_ALSA:
|
case VIR_DOMAIN_AUDIO_TYPE_ALSA:
|
||||||
|
if (inputNode)
|
||||||
|
virDomainAudioALSAParse(&def->backend.alsa.input, inputNode);
|
||||||
|
if (outputNode)
|
||||||
|
virDomainAudioALSAParse(&def->backend.alsa.output, outputNode);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_COREAUDIO:
|
case VIR_DOMAIN_AUDIO_TYPE_COREAUDIO:
|
||||||
|
if (inputNode)
|
||||||
|
virDomainAudioCoreAudioParse(&def->backend.coreaudio.input, inputNode);
|
||||||
|
if (outputNode)
|
||||||
|
virDomainAudioCoreAudioParse(&def->backend.coreaudio.output, outputNode);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_JACK:
|
case VIR_DOMAIN_AUDIO_TYPE_JACK:
|
||||||
|
if (inputNode)
|
||||||
|
virDomainAudioJackParse(&def->backend.jack.input, inputNode);
|
||||||
|
if (outputNode)
|
||||||
|
virDomainAudioJackParse(&def->backend.jack.output, outputNode);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_OSS:
|
case VIR_DOMAIN_AUDIO_TYPE_OSS: {
|
||||||
|
g_autofree char *tryMMap = virXMLPropString(node, "tryMMap");
|
||||||
|
g_autofree char *exclusive = virXMLPropString(node, "exclusive");
|
||||||
|
g_autofree char *dspPolicy = virXMLPropString(node, "dspPolicy");
|
||||||
|
|
||||||
|
if (tryMMap && ((def->backend.oss.tryMMap =
|
||||||
|
virTristateBoolTypeFromString(tryMMap)) <= 0)) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
|
_("unknown 'tryMMap' value '%s'"), tryMMap);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exclusive && ((def->backend.oss.exclusive =
|
||||||
|
virTristateBoolTypeFromString(exclusive)) <= 0)) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
|
_("unknown 'exclusive' value '%s'"), exclusive);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dspPolicy) {
|
||||||
|
if (virStrToLong_i(dspPolicy, NULL, 10,
|
||||||
|
&def->backend.oss.dspPolicy) < 0) {
|
||||||
|
virReportError(VIR_ERR_XML_ERROR,
|
||||||
|
_("cannot parse 'dspPolicy' value '%s'"), dspPolicy);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
def->backend.oss.dspPolicySet = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (inputNode)
|
if (inputNode)
|
||||||
virDomainAudioOSSParse(&def->backend.oss.input, inputNode);
|
virDomainAudioOSSParse(&def->backend.oss.input, inputNode);
|
||||||
if (outputNode)
|
if (outputNode)
|
||||||
virDomainAudioOSSParse(&def->backend.oss.output, outputNode);
|
virDomainAudioOSSParse(&def->backend.oss.output, outputNode);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_PULSEAUDIO:
|
case VIR_DOMAIN_AUDIO_TYPE_PULSEAUDIO:
|
||||||
|
def->backend.pulseaudio.serverName = virXMLPropString(node, "serverName");
|
||||||
|
|
||||||
|
if (inputNode)
|
||||||
|
virDomainAudioPulseAudioParse(&def->backend.pulseaudio.input, inputNode);
|
||||||
|
if (outputNode)
|
||||||
|
virDomainAudioPulseAudioParse(&def->backend.pulseaudio.output, outputNode);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_SDL: {
|
case VIR_DOMAIN_AUDIO_TYPE_SDL: {
|
||||||
@ -14136,6 +14318,11 @@ virDomainAudioDefParseXML(virDomainXMLOptionPtr xmlopt G_GNUC_UNUSED,
|
|||||||
_("unknown SDL driver '%s'"), driver);
|
_("unknown SDL driver '%s'"), driver);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (inputNode)
|
||||||
|
virDomainAudioSDLParse(&def->backend.sdl.input, inputNode);
|
||||||
|
if (outputNode)
|
||||||
|
virDomainAudioSDLParse(&def->backend.sdl.output, outputNode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14143,6 +14330,7 @@ virDomainAudioDefParseXML(virDomainXMLOptionPtr xmlopt G_GNUC_UNUSED,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_FILE:
|
case VIR_DOMAIN_AUDIO_TYPE_FILE:
|
||||||
|
def->backend.file.path = virXMLPropString(node, "path");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_LAST:
|
case VIR_DOMAIN_AUDIO_TYPE_LAST:
|
||||||
@ -26635,11 +26823,68 @@ virDomainAudioCommonFormat(virDomainAudioIOCommonPtr def,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
virDomainAudioALSAFormat(virDomainAudioIOALSAPtr def,
|
||||||
|
virBufferPtr buf)
|
||||||
|
{
|
||||||
|
virBufferEscapeString(buf, " dev='%s'", def->dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
virDomainAudioCoreAudioFormat(virDomainAudioIOCoreAudioPtr def,
|
||||||
|
virBufferPtr buf)
|
||||||
|
{
|
||||||
|
if (def->bufferCount)
|
||||||
|
virBufferAsprintf(buf, " bufferCount='%u'", def->bufferCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
virDomainAudioJackFormat(virDomainAudioIOJackPtr def,
|
||||||
|
virBufferPtr buf)
|
||||||
|
{
|
||||||
|
virBufferEscapeString(buf, " serverName='%s'", def->serverName);
|
||||||
|
virBufferEscapeString(buf, " clientName='%s'", def->clientName);
|
||||||
|
virBufferEscapeString(buf, " connectPorts='%s'", def->connectPorts);
|
||||||
|
if (def->exactName)
|
||||||
|
virBufferAsprintf(buf, " exactName='%s'",
|
||||||
|
virTristateBoolTypeToString(def->exactName));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
virDomainAudioOSSFormat(virDomainAudioIOOSSPtr def,
|
virDomainAudioOSSFormat(virDomainAudioIOOSSPtr def,
|
||||||
virBufferPtr buf)
|
virBufferPtr buf)
|
||||||
{
|
{
|
||||||
virBufferEscapeString(buf, " dev='%s'", def->dev);
|
virBufferEscapeString(buf, " dev='%s'", def->dev);
|
||||||
|
if (def->bufferCount)
|
||||||
|
virBufferAsprintf(buf, " bufferCount='%u'", def->bufferCount);
|
||||||
|
if (def->tryPoll)
|
||||||
|
virBufferAsprintf(buf, " tryPoll='%s'",
|
||||||
|
virTristateBoolTypeToString(def->tryPoll));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
virDomainAudioPulseAudioFormat(virDomainAudioIOPulseAudioPtr def,
|
||||||
|
virBufferPtr buf)
|
||||||
|
{
|
||||||
|
virBufferEscapeString(buf, " name='%s'", def->name);
|
||||||
|
virBufferEscapeString(buf, " streamName='%s'", def->streamName);
|
||||||
|
if (def->latency)
|
||||||
|
virBufferAsprintf(buf, " latency='%u'", def->latency);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
virDomainAudioSDLFormat(virDomainAudioIOSDLPtr def,
|
||||||
|
virBufferPtr buf)
|
||||||
|
{
|
||||||
|
if (def->bufferCount)
|
||||||
|
virBufferAsprintf(buf, " bufferCount='%u'", def->bufferCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -26665,20 +26910,40 @@ virDomainAudioDefFormat(virBufferPtr buf,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_ALSA:
|
case VIR_DOMAIN_AUDIO_TYPE_ALSA:
|
||||||
|
virDomainAudioALSAFormat(&def->backend.alsa.input, &inputBuf);
|
||||||
|
virDomainAudioALSAFormat(&def->backend.alsa.output, &outputBuf);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_COREAUDIO:
|
case VIR_DOMAIN_AUDIO_TYPE_COREAUDIO:
|
||||||
|
virDomainAudioCoreAudioFormat(&def->backend.coreaudio.input, &inputBuf);
|
||||||
|
virDomainAudioCoreAudioFormat(&def->backend.coreaudio.output, &outputBuf);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_JACK:
|
case VIR_DOMAIN_AUDIO_TYPE_JACK:
|
||||||
|
virDomainAudioJackFormat(&def->backend.jack.input, &inputBuf);
|
||||||
|
virDomainAudioJackFormat(&def->backend.jack.output, &outputBuf);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_OSS:
|
case VIR_DOMAIN_AUDIO_TYPE_OSS:
|
||||||
|
if (def->backend.oss.tryMMap)
|
||||||
|
virBufferAsprintf(buf, " tryMMap='%s'",
|
||||||
|
virTristateBoolTypeToString(def->backend.oss.tryMMap));
|
||||||
|
if (def->backend.oss.exclusive)
|
||||||
|
virBufferAsprintf(buf, " exclusive='%s'",
|
||||||
|
virTristateBoolTypeToString(def->backend.oss.exclusive));
|
||||||
|
if (def->backend.oss.dspPolicySet)
|
||||||
|
virBufferAsprintf(buf, " dspPolicy='%d'", def->backend.oss.dspPolicy);
|
||||||
|
|
||||||
virDomainAudioOSSFormat(&def->backend.oss.input, &inputBuf);
|
virDomainAudioOSSFormat(&def->backend.oss.input, &inputBuf);
|
||||||
virDomainAudioOSSFormat(&def->backend.oss.output, &outputBuf);
|
virDomainAudioOSSFormat(&def->backend.oss.output, &outputBuf);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_PULSEAUDIO:
|
case VIR_DOMAIN_AUDIO_TYPE_PULSEAUDIO:
|
||||||
|
virBufferEscapeString(buf, " serverName='%s'",
|
||||||
|
def->backend.pulseaudio.serverName);
|
||||||
|
|
||||||
|
virDomainAudioPulseAudioFormat(&def->backend.pulseaudio.input, &inputBuf);
|
||||||
|
virDomainAudioPulseAudioFormat(&def->backend.pulseaudio.output, &outputBuf);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_SDL:
|
case VIR_DOMAIN_AUDIO_TYPE_SDL:
|
||||||
@ -26686,12 +26951,16 @@ virDomainAudioDefFormat(virBufferPtr buf,
|
|||||||
virBufferAsprintf(buf, " driver='%s'",
|
virBufferAsprintf(buf, " driver='%s'",
|
||||||
virDomainAudioSDLDriverTypeToString(
|
virDomainAudioSDLDriverTypeToString(
|
||||||
def->backend.sdl.driver));
|
def->backend.sdl.driver));
|
||||||
|
|
||||||
|
virDomainAudioSDLFormat(&def->backend.sdl.input, &inputBuf);
|
||||||
|
virDomainAudioSDLFormat(&def->backend.sdl.output, &outputBuf);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_SPICE:
|
case VIR_DOMAIN_AUDIO_TYPE_SPICE:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_FILE:
|
case VIR_DOMAIN_AUDIO_TYPE_FILE:
|
||||||
|
virBufferEscapeString(buf, " path='%s'", def->backend.file.path);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_AUDIO_TYPE_LAST:
|
case VIR_DOMAIN_AUDIO_TYPE_LAST:
|
||||||
|
@ -1494,11 +1494,47 @@ struct _virDomainAudioIOCommon {
|
|||||||
unsigned int bufferLength; /* milliseconds */
|
unsigned int bufferLength; /* milliseconds */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct _virDomainAudioIOALSA virDomainAudioIOALSA;
|
||||||
|
typedef virDomainAudioIOALSA *virDomainAudioIOALSAPtr;
|
||||||
|
struct _virDomainAudioIOALSA {
|
||||||
|
char *dev;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _virDomainAudioIOCoreAudio virDomainAudioIOCoreAudio;
|
||||||
|
typedef virDomainAudioIOCoreAudio *virDomainAudioIOCoreAudioPtr;
|
||||||
|
struct _virDomainAudioIOCoreAudio {
|
||||||
|
unsigned int bufferCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _virDomainAudioIOJack virDomainAudioIOJack;
|
||||||
|
typedef virDomainAudioIOJack *virDomainAudioIOJackPtr;
|
||||||
|
struct _virDomainAudioIOJack {
|
||||||
|
char *serverName;
|
||||||
|
char *clientName;
|
||||||
|
char *connectPorts;
|
||||||
|
virTristateBool exactName;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct _virDomainAudioIOOSS virDomainAudioIOOSS;
|
typedef struct _virDomainAudioIOOSS virDomainAudioIOOSS;
|
||||||
typedef virDomainAudioIOOSS *virDomainAudioIOOSSPtr;
|
typedef virDomainAudioIOOSS *virDomainAudioIOOSSPtr;
|
||||||
struct _virDomainAudioIOOSS {
|
struct _virDomainAudioIOOSS {
|
||||||
char *dev;
|
char *dev;
|
||||||
|
unsigned int bufferCount;
|
||||||
|
virTristateBool tryPoll;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _virDomainAudioIOPulseAudio virDomainAudioIOPulseAudio;
|
||||||
|
typedef virDomainAudioIOPulseAudio *virDomainAudioIOPulseAudioPtr;
|
||||||
|
struct _virDomainAudioIOPulseAudio {
|
||||||
|
char *name;
|
||||||
|
char *streamName;
|
||||||
|
unsigned int latency;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _virDomainAudioIOSDL virDomainAudioIOSDL;
|
||||||
|
typedef virDomainAudioIOSDL *virDomainAudioIOSDLPtr;
|
||||||
|
struct _virDomainAudioIOSDL {
|
||||||
|
unsigned int bufferCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _virDomainAudioDef {
|
struct _virDomainAudioDef {
|
||||||
@ -1509,13 +1545,39 @@ struct _virDomainAudioDef {
|
|||||||
virDomainAudioIOCommon input;
|
virDomainAudioIOCommon input;
|
||||||
virDomainAudioIOCommon output;
|
virDomainAudioIOCommon output;
|
||||||
union {
|
union {
|
||||||
|
struct {
|
||||||
|
virDomainAudioIOALSA input;
|
||||||
|
virDomainAudioIOALSA output;
|
||||||
|
} alsa;
|
||||||
|
struct {
|
||||||
|
virDomainAudioIOCoreAudio input;
|
||||||
|
virDomainAudioIOCoreAudio output;
|
||||||
|
} coreaudio;
|
||||||
|
struct {
|
||||||
|
virDomainAudioIOJack input;
|
||||||
|
virDomainAudioIOJack output;
|
||||||
|
} jack;
|
||||||
struct {
|
struct {
|
||||||
virDomainAudioIOOSS input;
|
virDomainAudioIOOSS input;
|
||||||
virDomainAudioIOOSS output;
|
virDomainAudioIOOSS output;
|
||||||
|
virTristateBool tryMMap;
|
||||||
|
virTristateBool exclusive;
|
||||||
|
bool dspPolicySet;
|
||||||
|
int dspPolicy;
|
||||||
} oss;
|
} oss;
|
||||||
struct {
|
struct {
|
||||||
|
virDomainAudioIOPulseAudio input;
|
||||||
|
virDomainAudioIOPulseAudio output;
|
||||||
|
char *serverName;
|
||||||
|
} pulseaudio;
|
||||||
|
struct {
|
||||||
|
virDomainAudioIOSDL input;
|
||||||
|
virDomainAudioIOSDL output;
|
||||||
int driver; /* virDomainAudioSDLDriver */
|
int driver; /* virDomainAudioSDLDriver */
|
||||||
} sdl;
|
} sdl;
|
||||||
|
struct {
|
||||||
|
char *path;
|
||||||
|
} file;
|
||||||
} backend;
|
} backend;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user