提交 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 ...@@ -3616,6 +3616,25 @@ qemu-kvm -net nic,model=? /dev/null
</dd> </dd>
</dl> </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> <p>
Each <code>sound</code> element has an optional Each <code>sound</code> element has an optional
sub-element <code>&lt;address&gt;</code> which can tie the sub-element <code>&lt;address&gt;</code> which can tie the
......
...@@ -2250,6 +2250,16 @@ ...@@ -2250,6 +2250,16 @@
</choice> </choice>
</element> </element>
</define> </define>
<define name="codec">
<element name="codec">
<attribute name="type">
<choice>
<value>duplex</value>
<value>micro</value>
</choice>
</attribute>
</element>
</define>
<define name="sound"> <define name="sound">
<element name="sound"> <element name="sound">
<attribute name="model"> <attribute name="model">
...@@ -2261,12 +2271,19 @@ ...@@ -2261,12 +2271,19 @@
<value>ich6</value> <value>ich6</value>
</choice> </choice>
</attribute> </attribute>
<optional> <interleave>
<ref name="alias"/> <optional>
</optional> <ref name="alias"/>
<optional> </optional>
<ref name="address"/> <optional>
</optional> <ref name="address"/>
</optional>
<zeroOrMore>
<choice>
<ref name="codec"/>
</choice>
</zeroOrMore>
</interleave>
</element> </element>
</define> </define>
<define name="watchdog"> <define name="watchdog">
......
...@@ -354,6 +354,10 @@ VIR_ENUM_IMPL(virDomainSmartcard, VIR_DOMAIN_SMARTCARD_TYPE_LAST, ...@@ -354,6 +354,10 @@ VIR_ENUM_IMPL(virDomainSmartcard, VIR_DOMAIN_SMARTCARD_TYPE_LAST,
"host-certificates", "host-certificates",
"passthrough") "passthrough")
VIR_ENUM_IMPL(virDomainSoundCodec, VIR_DOMAIN_SOUND_CODEC_TYPE_LAST,
"duplex",
"micro")
VIR_ENUM_IMPL(virDomainSoundModel, VIR_DOMAIN_SOUND_MODEL_LAST, VIR_ENUM_IMPL(virDomainSoundModel, VIR_DOMAIN_SOUND_MODEL_LAST,
"sb16", "sb16",
"es1370", "es1370",
...@@ -1304,6 +1308,14 @@ void virDomainSmartcardDefFree(virDomainSmartcardDefPtr def) ...@@ -1304,6 +1308,14 @@ void virDomainSmartcardDefFree(virDomainSmartcardDefPtr def)
VIR_FREE(def); VIR_FREE(def);
} }
void virDomainSoundCodecDefFree(virDomainSoundCodecDefPtr def)
{
if (!def)
return;
VIR_FREE(def);
}
void virDomainSoundDefFree(virDomainSoundDefPtr def) void virDomainSoundDefFree(virDomainSoundDefPtr def)
{ {
if (!def) if (!def)
...@@ -1311,6 +1323,11 @@ void virDomainSoundDefFree(virDomainSoundDefPtr def) ...@@ -1311,6 +1323,11 @@ void virDomainSoundDefFree(virDomainSoundDefPtr def)
virDomainDeviceInfoClear(&def->info); virDomainDeviceInfoClear(&def->info);
int i;
for (i = 0 ; i < def->ncodecs ; i++)
virDomainSoundCodecDefFree(def->codecs[i]);
VIR_FREE(def->codecs);
VIR_FREE(def); VIR_FREE(def);
} }
...@@ -6374,18 +6391,52 @@ error: ...@@ -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 static virDomainSoundDefPtr
virDomainSoundDefParseXML(const xmlNodePtr node, virDomainSoundDefParseXML(const xmlNodePtr node,
xmlXPathContextPtr ctxt,
unsigned int flags) unsigned int flags)
{ {
char *model; char *model;
virDomainSoundDefPtr def; virDomainSoundDefPtr def;
xmlNodePtr save = ctxt->node;
if (VIR_ALLOC(def) < 0) { if (VIR_ALLOC(def) < 0) {
virReportOOMError(); virReportOOMError();
return NULL; return NULL;
} }
ctxt->node = node;
model = virXMLPropString(node, "model"); model = virXMLPropString(node, "model");
if ((def->model = virDomainSoundModelTypeFromString(model)) < 0) { if ((def->model = virDomainSoundModelTypeFromString(model)) < 0) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR, virDomainReportError(VIR_ERR_INTERNAL_ERROR,
...@@ -6393,12 +6444,43 @@ virDomainSoundDefParseXML(const xmlNodePtr node, ...@@ -6393,12 +6444,43 @@ virDomainSoundDefParseXML(const xmlNodePtr node,
goto error; 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) if (virDomainDeviceInfoParseXML(node, NULL, &def->info, flags) < 0)
goto error; goto error;
cleanup: cleanup:
VIR_FREE(model); VIR_FREE(model);
ctxt->node = save;
return def; return def;
error: error:
...@@ -6951,7 +7033,7 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virCapsPtr caps, ...@@ -6951,7 +7033,7 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virCapsPtr caps,
goto error; goto error;
} else if (xmlStrEqual(node->name, BAD_CAST "sound")) { } else if (xmlStrEqual(node->name, BAD_CAST "sound")) {
dev->type = VIR_DOMAIN_DEVICE_SOUND; dev->type = VIR_DOMAIN_DEVICE_SOUND;
if (!(dev->data.sound = virDomainSoundDefParseXML(node, flags))) if (!(dev->data.sound = virDomainSoundDefParseXML(node, ctxt, flags)))
goto error; goto error;
} else if (xmlStrEqual(node->name, BAD_CAST "watchdog")) { } else if (xmlStrEqual(node->name, BAD_CAST "watchdog")) {
dev->type = VIR_DOMAIN_DEVICE_WATCHDOG; dev->type = VIR_DOMAIN_DEVICE_WATCHDOG;
...@@ -8818,6 +8900,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, ...@@ -8818,6 +8900,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
goto no_memory; goto no_memory;
for (i = 0 ; i < n ; i++) { for (i = 0 ; i < n ; i++) {
virDomainSoundDefPtr sound = virDomainSoundDefParseXML(nodes[i], virDomainSoundDefPtr sound = virDomainSoundDefParseXML(nodes[i],
ctxt,
flags); flags);
if (!sound) if (!sound)
goto error; goto error;
...@@ -11782,12 +11865,31 @@ virDomainSmartcardDefFormat(virBufferPtr buf, ...@@ -11782,12 +11865,31 @@ virDomainSmartcardDefFormat(virBufferPtr buf,
return 0; 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 static int
virDomainSoundDefFormat(virBufferPtr buf, virDomainSoundDefFormat(virBufferPtr buf,
virDomainSoundDefPtr def, virDomainSoundDefPtr def,
unsigned int flags) unsigned int flags)
{ {
const char *model = virDomainSoundModelTypeToString(def->model); const char *model = virDomainSoundModelTypeToString(def->model);
bool children = false;
int i;
if (!model) { if (!model) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR, virDomainReportError(VIR_ERR_INTERNAL_ERROR,
...@@ -11797,10 +11899,24 @@ virDomainSoundDefFormat(virBufferPtr buf, ...@@ -11797,10 +11899,24 @@ virDomainSoundDefFormat(virBufferPtr buf,
virBufferAsprintf(buf, " <sound model='%s'", model); 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)) { if (virDomainDeviceInfoIsSet(&def->info, flags)) {
virBufferAddLit(buf, ">\n"); if (!children) {
virBufferAddLit(buf, ">\n");
children = true;
}
if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0) if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0)
return -1; return -1;
}
if (children) {
virBufferAddLit(buf, " </sound>\n"); virBufferAddLit(buf, " </sound>\n");
} else { } else {
virBufferAddLit(buf, "/>\n"); virBufferAddLit(buf, "/>\n");
......
...@@ -65,6 +65,9 @@ typedef virDomainNetDef *virDomainNetDefPtr; ...@@ -65,6 +65,9 @@ typedef virDomainNetDef *virDomainNetDefPtr;
typedef struct _virDomainInputDef virDomainInputDef; typedef struct _virDomainInputDef virDomainInputDef;
typedef virDomainInputDef *virDomainInputDefPtr; typedef virDomainInputDef *virDomainInputDefPtr;
typedef struct _virDomainSoundCodecDef virDomainSoundCodecDef;
typedef virDomainSoundCodecDef *virDomainSoundCodecDefPtr;
typedef struct _virDomainSoundDef virDomainSoundDef; typedef struct _virDomainSoundDef virDomainSoundDef;
typedef virDomainSoundDef *virDomainSoundDefPtr; typedef virDomainSoundDef *virDomainSoundDefPtr;
...@@ -996,6 +999,13 @@ struct _virDomainInputDef { ...@@ -996,6 +999,13 @@ struct _virDomainInputDef {
virDomainDeviceInfo info; virDomainDeviceInfo info;
}; };
enum virDomainSoundCodecType {
VIR_DOMAIN_SOUND_CODEC_TYPE_DUPLEX,
VIR_DOMAIN_SOUND_CODEC_TYPE_MICRO,
VIR_DOMAIN_SOUND_CODEC_TYPE_LAST
};
enum virDomainSoundModel { enum virDomainSoundModel {
VIR_DOMAIN_SOUND_MODEL_SB16, VIR_DOMAIN_SOUND_MODEL_SB16,
VIR_DOMAIN_SOUND_MODEL_ES1370, VIR_DOMAIN_SOUND_MODEL_ES1370,
...@@ -1006,9 +1016,17 @@ enum virDomainSoundModel { ...@@ -1006,9 +1016,17 @@ enum virDomainSoundModel {
VIR_DOMAIN_SOUND_MODEL_LAST VIR_DOMAIN_SOUND_MODEL_LAST
}; };
struct _virDomainSoundCodecDef {
int type;
int cad;
};
struct _virDomainSoundDef { struct _virDomainSoundDef {
int model; int model;
virDomainDeviceInfo info; virDomainDeviceInfo info;
int ncodecs;
virDomainSoundCodecDefPtr *codecs;
}; };
enum virDomainWatchdogModel { enum virDomainWatchdogModel {
...@@ -1848,6 +1866,7 @@ void virDomainChrDefFree(virDomainChrDefPtr def); ...@@ -1848,6 +1866,7 @@ void virDomainChrDefFree(virDomainChrDefPtr def);
void virDomainChrSourceDefFree(virDomainChrSourceDefPtr def); void virDomainChrSourceDefFree(virDomainChrSourceDefPtr def);
int virDomainChrSourceDefCopy(virDomainChrSourceDefPtr src, int virDomainChrSourceDefCopy(virDomainChrSourceDefPtr src,
virDomainChrSourceDefPtr dest); virDomainChrSourceDefPtr dest);
void virDomainSoundCodecDefFree(virDomainSoundCodecDefPtr def);
void virDomainSoundDefFree(virDomainSoundDefPtr def); void virDomainSoundDefFree(virDomainSoundDefPtr def);
void virDomainMemballoonDefFree(virDomainMemballoonDefPtr def); void virDomainMemballoonDefFree(virDomainMemballoonDefPtr def);
void virDomainWatchdogDefFree(virDomainWatchdogDefPtr def); void virDomainWatchdogDefFree(virDomainWatchdogDefPtr def);
...@@ -2164,6 +2183,7 @@ VIR_ENUM_DECL(virDomainSmartcard) ...@@ -2164,6 +2183,7 @@ VIR_ENUM_DECL(virDomainSmartcard)
VIR_ENUM_DECL(virDomainChr) VIR_ENUM_DECL(virDomainChr)
VIR_ENUM_DECL(virDomainChrTcpProtocol) VIR_ENUM_DECL(virDomainChrTcpProtocol)
VIR_ENUM_DECL(virDomainChrSpicevmc) VIR_ENUM_DECL(virDomainChrSpicevmc)
VIR_ENUM_DECL(virDomainSoundCodec)
VIR_ENUM_DECL(virDomainSoundModel) VIR_ENUM_DECL(virDomainSoundModel)
VIR_ENUM_DECL(virDomainMemballoonModel) VIR_ENUM_DECL(virDomainMemballoonModel)
VIR_ENUM_DECL(virDomainSmbiosMode) VIR_ENUM_DECL(virDomainSmbiosMode)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册