[libvirt] [PATCH libvirt 2/5] domain: add <codec> sound sub-element

Marc-André Lureau marcandre.lureau at gmail.com
Fri May 4 17:22:41 UTC 2012


Allow specifying sound device codecs. See formatdomain.html for
more details.
---
 docs/formatdomain.html.in     |   16 ++++++
 docs/schemas/domaincommon.rng |   29 +++++++---
 src/conf/domain_conf.c        |  119 ++++++++++++++++++++++++++++++++++++++++-
 src/conf/domain_conf.h        |   20 +++++++
 4 files changed, 176 insertions(+), 8 deletions(-)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index e1fe0c4..3e4e42b 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -3595,6 +3595,22 @@ qemu-kvm -net nic,model=? /dev/null
     </dl>
 
     <p>
+      Since 0.9.13, a sound element with <code>ich6</code> model can
+      have optional sub-elements <code><codec></code> to attach
+      various audio codecs to the audio device. If not specified, a
+      default codec will be attached to allow playback and recording.
+    </p>
+
+<pre>
+  ...
+  <devices>
+    <sound model='ich6'>
+      <codec type='micro'/>
+    <sound/>
+  </devices>
+  ...</pre>
+
+    <p>
       Each <code>sound</code> element has an optional
       sub-element <code><address></code> which can tie the
       device to a particular PCI
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 8419ccc..7984555 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -2224,6 +2224,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">
@@ -2235,12 +2245,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">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 3fce7e5..7077709 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -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",
@@ -1298,6 +1302,14 @@ void virDomainSmartcardDefFree(virDomainSmartcardDefPtr def)
     VIR_FREE(def);
 }
 
+void virDomainSoundCodecDefFree(virDomainSoundCodecDefPtr def)
+{
+    if (!def)
+        return;
+
+    VIR_FREE(def);
+}
+
 void virDomainSoundDefFree(virDomainSoundDefPtr def)
 {
     if (!def)
@@ -1305,6 +1317,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);
 }
 
@@ -6320,18 +6337,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,
@@ -6339,12 +6390,42 @@ 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();
+                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:
@@ -6897,7 +6978,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;
@@ -8711,6 +8792,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;
@@ -11676,11 +11758,30 @@ virDomainSmartcardDefFormat(virBufferPtr buf,
 }
 
 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);
+    int children = 0;
+    int i;
 
     if (!model) {
         virDomainReportError(VIR_ERR_INTERNAL_ERROR,
@@ -11690,10 +11791,24 @@ virDomainSoundDefFormat(virBufferPtr buf,
 
     virBufferAsprintf(buf, "    <sound model='%s'",  model);
 
+    for (i = 0; i < def->ncodecs; i++) {
+        if (!children) {
+            virBufferAddLit(buf, ">\n");
+            children = 1;
+        }
+        virDomainSoundCodecDefFormat(buf, def->codecs[i]);
+    }
+
     if (virDomainDeviceInfoIsSet(&def->info, flags)) {
-        virBufferAddLit(buf, ">\n");
+        if (!children) {
+            virBufferAddLit(buf, ">\n");
+            children = 1;
+        }
         if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0)
             return -1;
+    }
+
+    if (children) {
         virBufferAddLit(buf, "    </sound>\n");
     } else {
         virBufferAddLit(buf, "/>\n");
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 5aa8fc1..e061ef7 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -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;
 
@@ -992,6 +995,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,
@@ -1002,9 +1012,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 {
@@ -1834,6 +1852,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);
@@ -2150,6 +2169,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)
-- 
1.7.10




More information about the libvir-list mailing list