提交 988e85a5 编写于 作者: M Marc-André Lureau 提交者: Eric Blake

domain: add <codec> sound sub-element

Allow specifying sound device codecs. See formatdomain.html for
more details.
上级 0aaebd7a
......@@ -3616,6 +3616,25 @@ qemu-kvm -net nic,model=? /dev/null
</dd>
</dl>
<p>
<span class="since">Since 0.9.13</span>, a sound element
with <code>ich6</code> model can have optional
sub-elements <code>&lt;codec&gt;</code> to attach various audio
codecs to the audio device. If not specified, a default codec
will be attached to allow playback and recording. Valid values
are 'duplex' (advertise a line-in and a line-out) and 'micro'
(advertise a speaker and a microphone).
</p>
<pre>
...
&lt;devices&gt;
&lt;sound model='ich6'&gt;
&lt;codec type='micro'/&gt;
&lt;sound/&gt;
&lt;/devices&gt;
...</pre>
<p>
Each <code>sound</code> element has an optional
sub-element <code>&lt;address&gt;</code> which can tie the
......
......@@ -2250,6 +2250,16 @@
</choice>
</element>
</define>
<define name="codec">
<element name="codec">
<attribute name="type">
<choice>
<value>duplex</value>
<value>micro</value>
</choice>
</attribute>
</element>
</define>
<define name="sound">
<element name="sound">
<attribute name="model">
......@@ -2261,12 +2271,19 @@
<value>ich6</value>
</choice>
</attribute>
<optional>
<ref name="alias"/>
</optional>
<optional>
<ref name="address"/>
</optional>
<interleave>
<optional>
<ref name="alias"/>
</optional>
<optional>
<ref name="address"/>
</optional>
<zeroOrMore>
<choice>
<ref name="codec"/>
</choice>
</zeroOrMore>
</interleave>
</element>
</define>
<define name="watchdog">
......
......@@ -354,6 +354,10 @@ VIR_ENUM_IMPL(virDomainSmartcard, VIR_DOMAIN_SMARTCARD_TYPE_LAST,
"host-certificates",
"passthrough")
VIR_ENUM_IMPL(virDomainSoundCodec, VIR_DOMAIN_SOUND_CODEC_TYPE_LAST,
"duplex",
"micro")
VIR_ENUM_IMPL(virDomainSoundModel, VIR_DOMAIN_SOUND_MODEL_LAST,
"sb16",
"es1370",
......@@ -1304,6 +1308,14 @@ void virDomainSmartcardDefFree(virDomainSmartcardDefPtr def)
VIR_FREE(def);
}
void virDomainSoundCodecDefFree(virDomainSoundCodecDefPtr def)
{
if (!def)
return;
VIR_FREE(def);
}
void virDomainSoundDefFree(virDomainSoundDefPtr def)
{
if (!def)
......@@ -1311,6 +1323,11 @@ void virDomainSoundDefFree(virDomainSoundDefPtr def)
virDomainDeviceInfoClear(&def->info);
int i;
for (i = 0 ; i < def->ncodecs ; i++)
virDomainSoundCodecDefFree(def->codecs[i]);
VIR_FREE(def->codecs);
VIR_FREE(def);
}
......@@ -6374,18 +6391,52 @@ error:
}
static virDomainSoundCodecDefPtr
virDomainSoundCodecDefParseXML(const xmlNodePtr node)
{
char *type;
virDomainSoundCodecDefPtr def;
if (VIR_ALLOC(def) < 0) {
virReportOOMError();
return NULL;
}
type = virXMLPropString(node, "type");
if ((def->type = virDomainSoundCodecTypeFromString(type)) < 0) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
_("unknown codec type '%s'"), type);
goto error;
}
cleanup:
VIR_FREE(type);
return def;
error:
virDomainSoundCodecDefFree(def);
def = NULL;
goto cleanup;
}
static virDomainSoundDefPtr
virDomainSoundDefParseXML(const xmlNodePtr node,
xmlXPathContextPtr ctxt,
unsigned int flags)
{
char *model;
virDomainSoundDefPtr def;
xmlNodePtr save = ctxt->node;
if (VIR_ALLOC(def) < 0) {
virReportOOMError();
return NULL;
}
ctxt->node = node;
model = virXMLPropString(node, "model");
if ((def->model = virDomainSoundModelTypeFromString(model)) < 0) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
......@@ -6393,12 +6444,43 @@ virDomainSoundDefParseXML(const xmlNodePtr node,
goto error;
}
if (def->model == VIR_DOMAIN_SOUND_MODEL_ICH6) {
int ncodecs;
xmlNodePtr *codecNodes = NULL;
/* parse the <codec> subelements for sound models that support it */
ncodecs = virXPathNodeSet("./codec", ctxt, &codecNodes);
if (ncodecs < 0)
goto error;
if (ncodecs > 0) {
int ii;
if (VIR_ALLOC_N(def->codecs, ncodecs) < 0) {
virReportOOMError();
VIR_FREE(codecNodes);
goto error;
}
for (ii = 0; ii < ncodecs; ii++) {
virDomainSoundCodecDefPtr codec = virDomainSoundCodecDefParseXML(codecNodes[ii]);
if (codec == NULL)
goto error;
codec->cad = def->ncodecs; /* that will do for now */
def->codecs[def->ncodecs++] = codec;
}
VIR_FREE(codecNodes);
}
}
if (virDomainDeviceInfoParseXML(node, NULL, &def->info, flags) < 0)
goto error;
cleanup:
VIR_FREE(model);
ctxt->node = save;
return def;
error:
......@@ -6951,7 +7033,7 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virCapsPtr caps,
goto error;
} else if (xmlStrEqual(node->name, BAD_CAST "sound")) {
dev->type = VIR_DOMAIN_DEVICE_SOUND;
if (!(dev->data.sound = virDomainSoundDefParseXML(node, flags)))
if (!(dev->data.sound = virDomainSoundDefParseXML(node, ctxt, flags)))
goto error;
} else if (xmlStrEqual(node->name, BAD_CAST "watchdog")) {
dev->type = VIR_DOMAIN_DEVICE_WATCHDOG;
......@@ -8818,6 +8900,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
goto no_memory;
for (i = 0 ; i < n ; i++) {
virDomainSoundDefPtr sound = virDomainSoundDefParseXML(nodes[i],
ctxt,
flags);
if (!sound)
goto error;
......@@ -11782,12 +11865,31 @@ virDomainSmartcardDefFormat(virBufferPtr buf,
return 0;
}
static int
virDomainSoundCodecDefFormat(virBufferPtr buf,
virDomainSoundCodecDefPtr def)
{
const char *type = virDomainSoundCodecTypeToString(def->type);
if (!type) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected codec type %d"), def->type);
return -1;
}
virBufferAsprintf(buf, " <codec type='%s'/>\n", type);
return 0;
}
static int
virDomainSoundDefFormat(virBufferPtr buf,
virDomainSoundDefPtr def,
unsigned int flags)
{
const char *model = virDomainSoundModelTypeToString(def->model);
bool children = false;
int i;
if (!model) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
......@@ -11797,10 +11899,24 @@ virDomainSoundDefFormat(virBufferPtr buf,
virBufferAsprintf(buf, " <sound model='%s'", model);
for (i = 0; i < def->ncodecs; i++) {
if (!children) {
virBufferAddLit(buf, ">\n");
children = true;
}
virDomainSoundCodecDefFormat(buf, def->codecs[i]);
}
if (virDomainDeviceInfoIsSet(&def->info, flags)) {
virBufferAddLit(buf, ">\n");
if (!children) {
virBufferAddLit(buf, ">\n");
children = true;
}
if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0)
return -1;
}
if (children) {
virBufferAddLit(buf, " </sound>\n");
} else {
virBufferAddLit(buf, "/>\n");
......
......@@ -65,6 +65,9 @@ typedef virDomainNetDef *virDomainNetDefPtr;
typedef struct _virDomainInputDef virDomainInputDef;
typedef virDomainInputDef *virDomainInputDefPtr;
typedef struct _virDomainSoundCodecDef virDomainSoundCodecDef;
typedef virDomainSoundCodecDef *virDomainSoundCodecDefPtr;
typedef struct _virDomainSoundDef virDomainSoundDef;
typedef virDomainSoundDef *virDomainSoundDefPtr;
......@@ -996,6 +999,13 @@ struct _virDomainInputDef {
virDomainDeviceInfo info;
};
enum virDomainSoundCodecType {
VIR_DOMAIN_SOUND_CODEC_TYPE_DUPLEX,
VIR_DOMAIN_SOUND_CODEC_TYPE_MICRO,
VIR_DOMAIN_SOUND_CODEC_TYPE_LAST
};
enum virDomainSoundModel {
VIR_DOMAIN_SOUND_MODEL_SB16,
VIR_DOMAIN_SOUND_MODEL_ES1370,
......@@ -1006,9 +1016,17 @@ enum virDomainSoundModel {
VIR_DOMAIN_SOUND_MODEL_LAST
};
struct _virDomainSoundCodecDef {
int type;
int cad;
};
struct _virDomainSoundDef {
int model;
virDomainDeviceInfo info;
int ncodecs;
virDomainSoundCodecDefPtr *codecs;
};
enum virDomainWatchdogModel {
......@@ -1848,6 +1866,7 @@ void virDomainChrDefFree(virDomainChrDefPtr def);
void virDomainChrSourceDefFree(virDomainChrSourceDefPtr def);
int virDomainChrSourceDefCopy(virDomainChrSourceDefPtr src,
virDomainChrSourceDefPtr dest);
void virDomainSoundCodecDefFree(virDomainSoundCodecDefPtr def);
void virDomainSoundDefFree(virDomainSoundDefPtr def);
void virDomainMemballoonDefFree(virDomainMemballoonDefPtr def);
void virDomainWatchdogDefFree(virDomainWatchdogDefPtr def);
......@@ -2164,6 +2183,7 @@ VIR_ENUM_DECL(virDomainSmartcard)
VIR_ENUM_DECL(virDomainChr)
VIR_ENUM_DECL(virDomainChrTcpProtocol)
VIR_ENUM_DECL(virDomainChrSpicevmc)
VIR_ENUM_DECL(virDomainSoundCodec)
VIR_ENUM_DECL(virDomainSoundModel)
VIR_ENUM_DECL(virDomainMemballoonModel)
VIR_ENUM_DECL(virDomainSmbiosMode)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册