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 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel