[Spice-devel] [PATCH] audio: use GstVolume to have volume control.

Victor Toso victortoso at redhat.com
Wed Feb 4 07:20:24 PST 2015


Using GstVolume in the pipeline to have volume control instead of
changing sink and src elements directly.
---
 gtk/spice-gstaudio.c | 119 +++++++++++++++++++++++----------------------------
 1 file changed, 53 insertions(+), 66 deletions(-)

diff --git a/gtk/spice-gstaudio.c b/gtk/spice-gstaudio.c
index 892028c..8ac6aac 100644
--- a/gtk/spice-gstaudio.c
+++ b/gtk/spice-gstaudio.c
@@ -30,12 +30,15 @@
 #define SPICE_GSTAUDIO_GET_PRIVATE(obj)                                  \
     (G_TYPE_INSTANCE_GET_PRIVATE((obj), SPICE_TYPE_GSTAUDIO, SpiceGstaudioPrivate))
 
+#define MUTE_STR(mute) ((mute) ? "muted" : "not muted")
+
 G_DEFINE_TYPE(SpiceGstaudio, spice_gstaudio, SPICE_TYPE_AUDIO)
 
 struct stream {
     GstElement              *pipe;
     GstElement              *src;
     GstElement              *sink;
+    GstElement              *vol;
     guint                   rate;
     guint                   channels;
 };
@@ -73,6 +76,11 @@ void stream_dispose(struct stream *s)
         gst_object_unref(s->sink);
         s->sink = NULL;
     }
+
+    if (s->vol) {
+        gst_object_unref(s->vol);
+        s->vol = NULL;
+    }
 }
 
 static void spice_gstaudio_dispose(GObject *obj)
@@ -207,8 +215,9 @@ static void record_start(SpiceRecordChannel *channel, gint format, gint channels
             g_strdup_printf("audio/x-raw,format=\"S16LE\",channels=%d,rate=%d,"
                             "layout=interleaved", channels, frequency);
         gchar *pipeline =
-            g_strdup_printf("autoaudiosrc name=audiosrc ! queue ! audioconvert ! audioresample ! "
-                            "appsink caps=\"%s\" name=appsink", audio_caps);
+            g_strdup_printf("autoaudiosrc name=audiosrc ! volume name=appvol ! queue ! "
+                            "audioconvert ! audioresample ! appsink caps=\"%s\" name=appsink",
+                            audio_caps);
 
         p->record.pipe = gst_parse_launch(pipeline, &error);
         if (error != NULL) {
@@ -222,6 +231,7 @@ static void record_start(SpiceRecordChannel *channel, gint format, gint channels
 
         p->record.src = gst_bin_get_by_name(GST_BIN(p->record.pipe), "audiosrc");
         p->record.sink = gst_bin_get_by_name(GST_BIN(p->record.pipe), "appsink");
+        p->record.vol = gst_bin_get_by_name(GST_BIN(p->record.pipe), "appvol");
         p->record.rate = frequency;
         p->record.channels = channels;
 
@@ -301,8 +311,10 @@ static void playback_start(SpicePlaybackChannel *channel, gint format, gint chan
                             "layout=interleaved", channels, frequency);
         gchar *pipeline = g_strdup (g_getenv("SPICE_GST_AUDIOSINK"));
         if (pipeline == NULL)
-            pipeline = g_strdup_printf("appsrc is-live=1 do-timestamp=0 caps=\"%s\" name=\"appsrc\" ! queue ! "
-                                       "audioconvert ! audioresample ! autoaudiosink name=\"audiosink\"", audio_caps);
+            pipeline =
+                g_strdup_printf("appsrc is-live=1 do-timestamp=0 caps=\"%s\" name=\"appsrc\" ! "
+                                "volume name=appvol ! queue ! audioconvert ! audioresample ! "
+                                "autoaudiosink name=\"audiosink\"", audio_caps);
         SPICE_DEBUG("audio pipeline: %s", pipeline);
         p->playback.pipe = gst_parse_launch(pipeline, &error);
         if (error != NULL) {
@@ -311,6 +323,7 @@ static void playback_start(SpicePlaybackChannel *channel, gint format, gint chan
         }
         p->playback.src = gst_bin_get_by_name(GST_BIN(p->playback.pipe), "appsrc");
         p->playback.sink = gst_bin_get_by_name(GST_BIN(p->playback.pipe), "audiosink");
+        p->playback.vol = gst_bin_get_by_name(GST_BIN(p->playback.pipe), "appvol");
         p->playback.rate = frequency;
         p->playback.channels = channels;
 
@@ -353,13 +366,12 @@ static void playback_data(SpicePlaybackChannel *channel,
 static void playback_volume_changed(GObject *object, GParamSpec *pspec, gpointer data)
 {
     SpiceGstaudio *gstaudio = data;
-    GstElement *e;
     guint16 *volume;
     guint nchannels;
     SpiceGstaudioPrivate *p = gstaudio->priv;
-    gdouble vol;
+    gdouble old_vol, vol;
 
-    if (!p->playback.sink)
+    if (!p->playback.sink || !p->playback.vol)
         return;
 
     g_object_get(object,
@@ -370,54 +382,44 @@ static void playback_volume_changed(GObject *object, GParamSpec *pspec, gpointer
     g_return_if_fail(nchannels > 0);
 
     vol = 1.0 * volume[0] / VOLUME_NORMAL;
-
-    if (GST_IS_BIN(p->playback.sink))
-        e = gst_bin_get_by_interface(GST_BIN(p->playback.sink), GST_TYPE_STREAM_VOLUME);
-    else
-        e = g_object_ref(p->playback.sink);
-
-    if (GST_IS_STREAM_VOLUME(e))
-        gst_stream_volume_set_volume(GST_STREAM_VOLUME(e), GST_STREAM_VOLUME_FORMAT_CUBIC, vol);
-    else
-        g_object_set(e, "volume", vol, NULL);
-
-    g_object_unref(e);
+    old_vol = gst_stream_volume_get_volume(GST_STREAM_VOLUME(p->playback.vol),
+                                           GST_STREAM_VOLUME_FORMAT_CUBIC);
+    if (old_vol != vol) {
+        SPICE_DEBUG("playback: volume changed from %f to %f [%u]",
+                    old_vol, vol, volume[0]);
+        gst_stream_volume_set_volume(GST_STREAM_VOLUME(p->playback.vol),
+                                     GST_STREAM_VOLUME_FORMAT_CUBIC,
+                                     vol);
+    }
 }
 
 static void playback_mute_changed(GObject *object, GParamSpec *pspec, gpointer data)
 {
     SpiceGstaudio *gstaudio = data;
     SpiceGstaudioPrivate *p = gstaudio->priv;
-    GstElement *e;
-    gboolean mute;
+    gboolean old_mute, mute;
 
-    if (!p->playback.sink)
+    if (!p->playback.sink || !p->playback.vol)
         return;
 
     g_object_get(object, "mute", &mute, NULL);
-    SPICE_DEBUG("playback mute changed %u", mute);
-
-    if (GST_IS_BIN(p->playback.sink))
-        e = gst_bin_get_by_interface(GST_BIN(p->playback.sink), GST_TYPE_STREAM_VOLUME);
-    else
-        e = g_object_ref(p->playback.sink);
-
-    if (GST_IS_STREAM_VOLUME(e))
-        gst_stream_volume_set_mute(GST_STREAM_VOLUME(e), mute);
-
-    g_object_unref(e);
+    old_mute = gst_stream_volume_get_mute(GST_STREAM_VOLUME(p->playback.vol));
+    if (old_mute != mute) {
+        SPICE_DEBUG("playback: mute changed from %s to %s",
+                    MUTE_STR(old_mute), MUTE_STR(mute));
+        gst_stream_volume_set_mute(GST_STREAM_VOLUME(p->playback.vol), mute);
+    }
 }
 
 static void record_volume_changed(GObject *object, GParamSpec *pspec, gpointer data)
 {
     SpiceGstaudio *gstaudio = data;
     SpiceGstaudioPrivate *p = gstaudio->priv;
-    GstElement *e;
     guint16 *volume;
     guint nchannels;
-    gdouble vol;
+    gdouble old_vol, vol;
 
-    if (!p->record.src)
+    if (!p->record.src || !p->record.vol)
         return;
 
     g_object_get(object,
@@ -428,46 +430,31 @@ static void record_volume_changed(GObject *object, GParamSpec *pspec, gpointer d
     g_return_if_fail(nchannels > 0);
 
     vol = 1.0 * volume[0] / VOLUME_NORMAL;
-
-    /* TODO directsoundsrc doesn't support IDirectSoundBuffer_SetVolume */
-    /* TODO pulsesrc doesn't support volume property, it's all coming! */
-
-    if (GST_IS_BIN(p->record.src))
-        e = gst_bin_get_by_interface(GST_BIN(p->record.src), GST_TYPE_STREAM_VOLUME);
-    else
-        e = g_object_ref(p->record.src);
-
-    if (GST_IS_STREAM_VOLUME(e))
-        gst_stream_volume_set_volume(GST_STREAM_VOLUME(e), GST_STREAM_VOLUME_FORMAT_CUBIC, vol);
-    else
-        g_warning("gst lacks volume capabilities on src (TODO)");
-
-    g_object_unref(e);
+    old_vol = gst_stream_volume_get_volume(GST_STREAM_VOLUME(p->record.vol), GST_STREAM_VOLUME_FORMAT_CUBIC);
+    if (old_vol != vol) {
+        SPICE_DEBUG("record: volume changed from %f to %f [%u]", old_vol, vol, volume[0]);
+        gst_stream_volume_set_volume(GST_STREAM_VOLUME(p->record.vol),
+                                     GST_STREAM_VOLUME_FORMAT_CUBIC,
+                                     vol);
+    }
 }
 
 static void record_mute_changed(GObject *object, GParamSpec *pspec, gpointer data)
 {
     SpiceGstaudio *gstaudio = data;
     SpiceGstaudioPrivate *p = gstaudio->priv;
-    GstElement *e;
-    gboolean mute;
+    gboolean old_mute, mute;
 
-    if (!p->record.src)
+    if (!p->record.src || !p->record.vol)
         return;
 
     g_object_get(object, "mute", &mute, NULL);
-
-    if (GST_IS_BIN(p->record.src))
-        e = gst_bin_get_by_interface(GST_BIN(p->record.src), GST_TYPE_STREAM_VOLUME);
-    else
-        e = g_object_ref(p->record.src);
-
-    if (GST_IS_STREAM_VOLUME (e))
-        gst_stream_volume_set_mute(GST_STREAM_VOLUME(e), mute);
-    else
-        g_warning("gst lacks mute capabilities on src: %d (TODO)", mute);
-
-    g_object_unref(e);
+    old_mute = gst_stream_volume_get_mute(GST_STREAM_VOLUME(p->record.vol));
+    if (old_mute != mute) {
+        SPICE_DEBUG("record: mute changed from %s to %s",
+                    MUTE_STR(old_mute), MUTE_STR(mute));
+        gst_stream_volume_set_mute(GST_STREAM_VOLUME(p->record.vol), mute);
+    }
 }
 
 static void
-- 
2.1.0



More information about the Spice-devel mailing list