diff options
author | Sjoerd Simons <sjoerd.simons@collabora.co.uk> | 2011-11-18 02:15:09 +0800 |
---|---|---|
committer | Sjoerd Simons <sjoerd.simons@collabora.co.uk> | 2011-11-19 01:49:56 +0800 |
commit | e40052870d5566ccc48109ef3f8202c889a06eab (patch) | |
tree | 161d6cfdb2f8fb074cda8152a4ab1cba0b9112f6 /src/empathy-audio-sink.c | |
parent | d4461277da015bdf03e7fdb82b8973d3022c0e59 (diff) | |
download | gsoc2013-empathy-e40052870d5566ccc48109ef3f8202c889a06eab.tar gsoc2013-empathy-e40052870d5566ccc48109ef3f8202c889a06eab.tar.gz gsoc2013-empathy-e40052870d5566ccc48109ef3f8202c889a06eab.tar.bz2 gsoc2013-empathy-e40052870d5566ccc48109ef3f8202c889a06eab.tar.lz gsoc2013-empathy-e40052870d5566ccc48109ef3f8202c889a06eab.tar.xz gsoc2013-empathy-e40052870d5566ccc48109ef3f8202c889a06eab.tar.zst gsoc2013-empathy-e40052870d5566ccc48109ef3f8202c889a06eab.zip |
Keep the audio sinks volume property synchronized with the pulse volume
Diffstat (limited to 'src/empathy-audio-sink.c')
-rw-r--r-- | src/empathy-audio-sink.c | 131 |
1 files changed, 92 insertions, 39 deletions
diff --git a/src/empathy-audio-sink.c b/src/empathy-audio-sink.c index b35edb331..372e9f991 100644 --- a/src/empathy-audio-sink.c +++ b/src/empathy-audio-sink.c @@ -62,6 +62,9 @@ struct _EmpathyGstAudioSinkPrivate { GstElement *sink; gboolean echo_cancel; + gdouble volume; + gint volume_idle_id; + GStaticMutex volume_mutex; }; #define EMPATHY_GST_AUDIO_SINK_GET_PRIVATE(o) \ @@ -73,6 +76,7 @@ empathy_audio_sink_init (EmpathyGstAudioSink *self) { self->priv = EMPATHY_GST_AUDIO_SINK_GET_PRIVATE (self); self->priv->echo_cancel = TRUE; + g_static_mutex_init (&self->priv->volume_mutex); } static GstPad * empathy_audio_sink_request_new_pad (GstElement *self, @@ -86,11 +90,13 @@ static void empathy_audio_sink_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { + EmpathyGstAudioSink *self = EMPATHY_GST_AUDIO_SINK (object); switch (property_id) { case PROP_VOLUME: - empathy_audio_sink_set_volume (EMPATHY_GST_AUDIO_SINK (object), - g_value_get_double (value)); + g_static_mutex_lock (&self->priv->volume_mutex); + self->priv->volume = g_value_get_double (value); + g_static_mutex_unlock (&self->priv->volume_mutex); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -101,11 +107,11 @@ static void empathy_audio_sink_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { + EmpathyGstAudioSink *self = EMPATHY_GST_AUDIO_SINK (object); switch (property_id) { case PROP_VOLUME: - g_value_set_double (value, - empathy_audio_sink_get_volume (EMPATHY_GST_AUDIO_SINK (object))); + g_value_set_double (value, self->priv->volume); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -113,6 +119,23 @@ empathy_audio_sink_get_property (GObject *object, } static void +empathy_audio_sink_dispose (GObject *object) +{ + EmpathyGstAudioSink *self = EMPATHY_GST_AUDIO_SINK (object); + EmpathyGstAudioSinkPrivate *priv = self->priv; + + if (priv->volume_idle_id != 0) + g_source_remove (priv->volume_idle_id); + priv->volume_idle_id = 0; + + g_static_mutex_free (&self->priv->volume_mutex); + + /* release any references held by the object here */ + if (G_OBJECT_CLASS (empathy_audio_sink_parent_class)->dispose) + G_OBJECT_CLASS (empathy_audio_sink_parent_class)->dispose (object); +} + +static void empathy_audio_sink_class_init (EmpathyGstAudioSinkClass *empathy_audio_sink_class) { @@ -129,6 +152,7 @@ empathy_audio_sink_class_init (EmpathyGstAudioSinkClass object_class->set_property = empathy_audio_sink_set_property; object_class->get_property = empathy_audio_sink_get_property; + object_class->dispose = empathy_audio_sink_dispose; element_class->request_new_pad = empathy_audio_sink_request_new_pad; element_class->release_pad = empathy_audio_sink_release_pad; @@ -153,43 +177,18 @@ empathy_audio_sink_new (void) return gst_element_factory_make ("empathyaudiosink", NULL); } -static gboolean -check_volume_support (EmpathyGstAudioSink *self) -{ - gchar *name; - - if (GST_IS_STREAM_VOLUME (self->priv->sink)) - return TRUE; - - name = gst_element_get_name (self->priv->sink); - DEBUG ("Element %s doesn't support volume", name); - - g_free (name); - return FALSE; -} - void empathy_audio_sink_set_volume (EmpathyGstAudioSink *sink, gdouble volume) { - EmpathyGstAudioSinkPrivate *priv = EMPATHY_GST_AUDIO_SINK_GET_PRIVATE (sink); - - if (!check_volume_support (sink)) - return; - - g_object_set (priv->sink, "volume", volume, NULL); + g_object_set (sink, "volume", volume, NULL); } gdouble empathy_audio_sink_get_volume (EmpathyGstAudioSink *sink) { EmpathyGstAudioSinkPrivate *priv = EMPATHY_GST_AUDIO_SINK_GET_PRIVATE (sink); - gdouble volume; - - if (!check_volume_support (sink)) - return 1.0; - g_object_get (priv->sink, "volume", &volume, NULL); - return volume; + return priv->volume; } static GstElement * @@ -224,13 +223,50 @@ create_sink (EmpathyGstAudioSink *self) return sink; } +static gboolean +empathy_audio_sink_volume_idle_updated (gpointer user_data) +{ + EmpathyGstAudioSink *self = EMPATHY_GST_AUDIO_SINK (user_data); + + g_static_mutex_lock (&self->priv->volume_mutex); + self->priv->volume_idle_id = 0; + g_static_mutex_unlock (&self->priv->volume_mutex); + + g_object_notify (G_OBJECT (self), "volume"); + + return FALSE; +} + +static void +empathy_audio_sink_volume_updated (GObject *object, + GParamSpec *pspec, + gpointer user_data) +{ + EmpathyGstAudioSink *self = EMPATHY_GST_AUDIO_SINK (user_data); + gdouble volume; + + g_static_mutex_lock (&self->priv->volume_mutex); + + g_object_get (object, "volume", &volume, NULL); + if (self->priv->volume == volume) + goto out; + + self->priv->volume = volume; + if (self->priv->volume_idle_id == 0) + self->priv->volume_idle_id = g_idle_add ( + empathy_audio_sink_volume_idle_updated, self); + +out: + g_static_mutex_unlock (&self->priv->volume_mutex); +} + static GstPad * empathy_audio_sink_request_new_pad (GstElement *element, GstPadTemplate *templ, const gchar* name) { EmpathyGstAudioSink *self = EMPATHY_GST_AUDIO_SINK (element); - GstElement *bin, *volume, *resample, *audioconvert0, *audioconvert1; + GstElement *bin, *resample, *audioconvert0, *audioconvert1; GstPad *pad = NULL; GstPad *subpad, *filterpad; @@ -254,20 +290,37 @@ empathy_audio_sink_request_new_pad (GstElement *element, gst_bin_add (GST_BIN (bin), audioconvert1); - volume = gst_element_factory_make ("volume", NULL); - if (volume == NULL) - goto error; - - gst_bin_add (GST_BIN (bin), volume); - self->priv->sink = create_sink (self); if (self->priv->sink == NULL) goto error; + if (GST_IS_STREAM_VOLUME (self->priv->sink)) + { + gdouble volume; + /* We can't do a bidirection bind as the ::notify comes from another + * thread, for other bits of empathy it's most simpler if it comes from + * the main thread */ + g_object_bind_property (self, "volume", self->priv->sink, "volume", + G_BINDING_DEFAULT); + + /* sync and callback for bouncing */ + g_object_get (self->priv->sink, "volume", &volume, NULL); + g_object_set (self, "volume", volume, NULL); + g_signal_connect (self->priv->sink, "notify::volume", + G_CALLBACK (empathy_audio_sink_volume_updated), self); + } + else + { + gchar *n = gst_element_get_name (self->priv->sink); + + DEBUG ("Element %s doesn't support volume", n); + g_free (n); + } + gst_bin_add (GST_BIN (bin), self->priv->sink); if (!gst_element_link_many (audioconvert0, resample, audioconvert1, - volume, self->priv->sink, NULL)) + self->priv->sink, NULL)) goto error; filterpad = gst_element_get_static_pad (audioconvert0, "sink"); |