diff options
Diffstat (limited to 'src/empathy-audio-sink.c')
-rw-r--r-- | src/empathy-audio-sink.c | 245 |
1 files changed, 40 insertions, 205 deletions
diff --git a/src/empathy-audio-sink.c b/src/empathy-audio-sink.c index c410d7a30..e571b2426 100644 --- a/src/empathy-audio-sink.c +++ b/src/empathy-audio-sink.c @@ -23,10 +23,11 @@ #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,16 +55,7 @@ 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) \ @@ -101,72 +63,11 @@ struct _EmpathyGstAudioSinkPrivate 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); } |