aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSjoerd Simons <sjoerd.simons@collabora.co.uk>2011-11-18 02:15:09 +0800
committerSjoerd Simons <sjoerd.simons@collabora.co.uk>2011-11-19 01:49:56 +0800
commite40052870d5566ccc48109ef3f8202c889a06eab (patch)
tree161d6cfdb2f8fb074cda8152a4ab1cba0b9112f6
parentd4461277da015bdf03e7fdb82b8973d3022c0e59 (diff)
downloadgsoc2013-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
-rw-r--r--src/empathy-audio-sink.c131
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");