]> git.0d.be Git - empathy.git/commitdiff
Use pulesink as audio sink
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>
Mon, 15 Aug 2011 07:44:28 +0000 (09:44 +0200)
committerGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>
Mon, 15 Aug 2011 12:38:12 +0000 (14:38 +0200)
As we did for puslesrc, this can still be overriden with an env variable for
debuging purposes.

Relying on pulse allows us to remove all the software volume control logic.

src/empathy-audio-sink.c

index c410d7a306d34a874d578916008ba03058348a1d..e571b242681c204763b09b0ee0c1aaafc6020616 100644 (file)
 #include <stdlib.h>
 
 #include <gst/audio/audio.h>
-#include <gst/farsight/fs-element-added-notifier.h>
 
 #include "empathy-audio-sink.h"
 
+#define DEBUG_FLAG EMPATHY_DEBUG_VOIP
+#include <libempathy/empathy-debug.h>
 
 G_DEFINE_TYPE(EmpathyGstAudioSink, empathy_audio_sink, GST_TYPE_BIN)
 
@@ -39,36 +40,6 @@ enum
 
 static guint signals[LAST_SIGNAL] = {0};
 #endif
-typedef struct {
-  GstPad *pad;
-  GstElement *bin;
-  GstElement *volume;
-  GstElement *sink;
-} AudioBin;
-
-static AudioBin *
-audio_bin_new (GstPad *pad,
-    GstElement *bin,
-    GstElement *volume,
-    GstElement *sink)
-{
-  AudioBin *result = g_slice_new0 (AudioBin);
-
-  result->pad = pad;
-  result->bin = bin;
-  result->volume = gst_object_ref (volume);
-  result->sink = sink;
-
-  return result;
-}
-
-static void
-audio_bin_free (AudioBin *bin)
-{
-  gst_object_unref (bin->volume);
-  g_slice_free (AudioBin, bin);
-}
-
 
 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE(
     "sink%d",
@@ -84,89 +55,19 @@ enum {
 
 struct _EmpathyGstAudioSinkPrivate
 {
-  gboolean dispose_has_run;
-  FsElementAddedNotifier *notifier;
-
-  gdouble volume;
-
-  /* Pad -> *owned* subbin hash */
-  GHashTable *audio_bins;
-
-  /* Mutex to hold while change the hash table */
-  GMutex *audio_bins_lock;
+  GstElement *sink;
 };
 
 #define EMPATHY_GST_AUDIO_SINK_GET_PRIVATE(o) \
   (G_TYPE_INSTANCE_GET_PRIVATE ((o), EMPATHY_TYPE_GST_AUDIO_SINK, \
   EmpathyGstAudioSinkPrivate))
 
-static void
-empathy_audio_sink_element_added_cb (FsElementAddedNotifier *notifier,
-  GstBin *bin, GstElement *element, EmpathyGstAudioSink *self)
-{
-  EmpathyGstAudioSinkPrivate *priv = EMPATHY_GST_AUDIO_SINK_GET_PRIVATE (self);
-
-  if (g_object_class_find_property (G_OBJECT_GET_CLASS (element), "volume"))
-    {
-      /* An element was added with a volume property, lets find its subbin and
-       * update the volume in it */
-      GHashTableIter iter;
-      AudioBin *audio_bin = NULL;
-      gpointer value;
-
-      g_mutex_lock (self->priv->audio_bins_lock);
-      g_hash_table_iter_init (&iter, priv->audio_bins);
-
-      while (g_hash_table_iter_next (&iter, NULL, &value))
-        {
-          AudioBin *b = value;
-
-          if (gst_object_has_ancestor (GST_OBJECT (element),
-              GST_OBJECT (b->bin)))
-            {
-              audio_bin = b;
-              break;
-            }
-        }
-
-      if (audio_bin == NULL)
-        {
-          g_warning ("Element added that doesn't belong to us ?");
-          return;
-        }
-
-      /* Set the old volume to 1 and the new volume to the volume */
-      g_object_set (audio_bin->volume, "volume", 1.0, NULL);
-      gst_object_unref (audio_bin->volume);
-
-      audio_bin->volume = gst_object_ref (element);
-      g_object_set (audio_bin->volume, "volume", self->priv->volume, NULL);
-      g_mutex_unlock (self->priv->audio_bins_lock);
-    }
-}
-
 static void
 empathy_audio_sink_init (EmpathyGstAudioSink *self)
 {
-  EmpathyGstAudioSinkPrivate *priv;
-
-  priv = self->priv = EMPATHY_GST_AUDIO_SINK_GET_PRIVATE (self);
-
-  priv->volume = 1.0;
-
-  priv->audio_bins = g_hash_table_new_full (g_direct_hash, g_direct_equal,
-    NULL, (GDestroyNotify) audio_bin_free);
-
-  priv->audio_bins_lock = g_mutex_new ();
-
-  priv->notifier = fs_element_added_notifier_new ();
-  g_signal_connect (priv->notifier, "element-added",
-    G_CALLBACK (empathy_audio_sink_element_added_cb), self);
+  self->priv = EMPATHY_GST_AUDIO_SINK_GET_PRIVATE (self);
 }
 
-static void empathy_audio_sink_dispose (GObject *object);
-static void empathy_audio_sink_finalize (GObject *object);
-
 static GstPad * empathy_audio_sink_request_new_pad (GstElement *self,
   GstPadTemplate *templ,
   const gchar* name);
@@ -219,9 +120,6 @@ empathy_audio_sink_class_init (EmpathyGstAudioSinkClass
   g_type_class_add_private (empathy_audio_sink_class,
     sizeof (EmpathyGstAudioSinkPrivate));
 
-  object_class->dispose = empathy_audio_sink_dispose;
-  object_class->finalize = empathy_audio_sink_finalize;
-
   object_class->set_property = empathy_audio_sink_set_property;
   object_class->get_property = empathy_audio_sink_get_property;
 
@@ -234,45 +132,6 @@ empathy_audio_sink_class_init (EmpathyGstAudioSinkClass
   g_object_class_install_property (object_class, PROP_VOLUME, param_spec);
 }
 
-void
-empathy_audio_sink_dispose (GObject *object)
-{
-  EmpathyGstAudioSink *self = EMPATHY_GST_AUDIO_SINK (object);
-  EmpathyGstAudioSinkPrivate *priv = EMPATHY_GST_AUDIO_SINK_GET_PRIVATE (self);
-
-  if (priv->dispose_has_run)
-    return;
-
-  priv->dispose_has_run = TRUE;
-
-  if (priv->notifier != NULL)
-    g_object_unref (priv->notifier);
-  priv->notifier = NULL;
-
-  if (priv->audio_bins != NULL)
-    g_hash_table_unref (priv->audio_bins);
-  priv->audio_bins = NULL;
-
-  if (priv->audio_bins_lock != NULL)
-    g_mutex_free (priv->audio_bins_lock);
-  priv->audio_bins_lock = NULL;
-
-  if (G_OBJECT_CLASS (empathy_audio_sink_parent_class)->dispose)
-    G_OBJECT_CLASS (empathy_audio_sink_parent_class)->dispose (object);
-}
-
-void
-empathy_audio_sink_finalize (GObject *object)
-{
-  //EmpathyGstAudioSink *self = EMPATHY_GST_AUDIO_SINK (object);
-  //EmpathyGstAudioSinkPrivate *priv =
-  //  EMPATHY_GST_AUDIO_SINK_GET_PRIVATE (self);
-
-  /* free any data held directly by the object here */
-
-  G_OBJECT_CLASS (empathy_audio_sink_parent_class)->finalize (object);
-}
-
 GstElement *
 empathy_audio_sink_new (void)
 {
@@ -287,32 +146,44 @@ empathy_audio_sink_new (void)
   return gst_element_factory_make ("empathyaudiosink", NULL);
 }
 
+static gboolean
+check_volume_support (EmpathyGstAudioSink *self)
+{
+  gchar *name;
+
+  if (g_object_class_find_property (G_OBJECT_GET_CLASS (self->priv->sink),
+        "volume"))
+    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);
-  GHashTableIter iter;
-  gpointer value;
-
-  priv->volume = volume;
 
-  g_mutex_lock (priv->audio_bins_lock);
-
-  g_hash_table_iter_init (&iter, priv->audio_bins);
-  while (g_hash_table_iter_next (&iter, NULL, &value))
-    {
-      AudioBin *b = value;
-      g_object_set (b->volume, "volume", volume, NULL);
-    }
+  if (!check_volume_support (sink))
+      return;
 
-  g_mutex_unlock (priv->audio_bins_lock);
+  g_object_set (priv->sink, "volume", volume, NULL);
 }
 
 gdouble
 empathy_audio_sink_get_volume (EmpathyGstAudioSink *sink)
 {
   EmpathyGstAudioSinkPrivate *priv = EMPATHY_GST_AUDIO_SINK_GET_PRIVATE (sink);
-  return priv->volume;
+  gdouble volume;
+
+  if (!check_volume_support (sink))
+      return 1.0;
+
+  g_object_get (priv->sink, "volume", &volume, NULL);
+  return volume;
 }
 
 static GstPad *
@@ -321,10 +192,10 @@ empathy_audio_sink_request_new_pad (GstElement *element,
   const gchar* name)
 {
   EmpathyGstAudioSink *self = EMPATHY_GST_AUDIO_SINK (element);
-  GstElement *bin, *sink, *volume, *resample, *audioconvert0, *audioconvert1;
+  GstElement *bin, *volume, *resample, *audioconvert0, *audioconvert1;
   GstPad *pad = NULL;
   GstPad *subpad, *filterpad;
-  AudioBin *audiobin;
+  const gchar *sink_element;
 
   bin = gst_bin_new (NULL);
 
@@ -352,15 +223,18 @@ empathy_audio_sink_request_new_pad (GstElement *element,
 
   gst_bin_add (GST_BIN (bin), volume);
 
-  sink = gst_element_factory_make ("gconfaudiosink", NULL);
-  if (sink == NULL)
+  sink_element = g_getenv ("EMPATHY_AUDIO_SINK");
+  if (sink_element == NULL)
+    sink_element = "pulsesink";
+
+  self->priv->sink = gst_element_factory_make (sink_element, NULL);
+  if (self->priv->sink == NULL)
     goto error;
 
-  gst_bin_add (GST_BIN (bin), sink);
-  fs_element_added_notifier_add (self->priv->notifier, GST_BIN (sink));
+  gst_bin_add (GST_BIN (bin), self->priv->sink);
 
   if (!gst_element_link_many (audioconvert0, resample, audioconvert1,
-      volume, sink, NULL))
+      volume, self->priv->sink, NULL))
     goto error;
 
   filterpad = gst_element_get_static_pad (audioconvert0, "sink");
@@ -372,25 +246,11 @@ empathy_audio_sink_request_new_pad (GstElement *element,
   if (!gst_element_add_pad (GST_ELEMENT (bin), subpad))
     goto error;
 
-
-  /* Ensure that state changes only happen _after_ the element has been added
-   * to the hash table. But add it to the bin first so we can create our
-   * ghostpad (if we create the ghostpad before adding it to the bin it will
-   * get unlinked) */
-  gst_element_set_locked_state (GST_ELEMENT (bin), TRUE);
   gst_bin_add (GST_BIN (self), bin);
 
   pad = gst_ghost_pad_new (name, subpad);
   g_assert (pad != NULL);
 
-  audiobin = audio_bin_new (pad, bin, volume, sink);
-
-  g_mutex_lock (self->priv->audio_bins_lock);
-  g_hash_table_insert (self->priv->audio_bins, pad, audiobin);
-  g_mutex_unlock (self->priv->audio_bins_lock);
-
-  gst_element_set_locked_state (GST_ELEMENT (bin), FALSE);
-
   if (!gst_element_sync_state_with_parent (bin))
     goto error;
 
@@ -400,16 +260,11 @@ empathy_audio_sink_request_new_pad (GstElement *element,
   if (!gst_element_add_pad (GST_ELEMENT (self), pad))
     goto error;
 
-
   return pad;
 
 error:
   if (pad != NULL)
     {
-      g_mutex_lock (self->priv->audio_bins_lock);
-      g_hash_table_remove (self->priv->audio_bins, pad);
-      g_mutex_unlock (self->priv->audio_bins_lock);
-
       gst_object_unref (pad);
     }
 
@@ -422,26 +277,6 @@ static void
 empathy_audio_sink_release_pad (GstElement *element,
   GstPad *pad)
 {
-  EmpathyGstAudioSink *self = EMPATHY_GST_AUDIO_SINK (element);
-  AudioBin *abin;
-
-  g_mutex_lock (self->priv->audio_bins_lock);
-  abin = g_hash_table_lookup (self->priv->audio_bins, pad);
-  g_hash_table_steal (self->priv->audio_bins, pad);
-  g_mutex_unlock (self->priv->audio_bins_lock);
-
-  if (abin == NULL)
-    {
-      g_warning ("Releasing a pad that doesn't belong to us ?");
-      return;
-    }
-
   gst_pad_set_active (pad, FALSE);
   gst_element_remove_pad (element, pad);
-
-  gst_element_set_locked_state (abin->bin, TRUE);
-  gst_element_set_state (abin->bin, GST_STATE_NULL);
-  gst_bin_remove (GST_BIN (self), abin->bin);
-
-  audio_bin_free (abin);
 }