diff options
Diffstat (limited to 'ext/gconf/gstgconfaudiosink.c')
-rw-r--r-- | ext/gconf/gstgconfaudiosink.c | 174 |
1 files changed, 65 insertions, 109 deletions
diff --git a/ext/gconf/gstgconfaudiosink.c b/ext/gconf/gstgconfaudiosink.c index 375c2ede..25b06e32 100644 --- a/ext/gconf/gstgconfaudiosink.c +++ b/ext/gconf/gstgconfaudiosink.c @@ -28,11 +28,13 @@ #include "gstgconfaudiosink.h" static void gst_gconf_audio_sink_dispose (GObject * object); -static void cb_toggle_element (GConfClient * client, +static void cb_change_child (GConfClient * client, guint connection_id, GConfEntry * entry, gpointer data); static GstStateChangeReturn gst_gconf_audio_sink_change_state (GstElement * element, GstStateChange transition); +static void gst_gconf_switch_profile (GstGConfAudioSink * sink, + GstGConfProfile profile); enum { @@ -40,7 +42,8 @@ enum PROP_PROFILE }; -GST_BOILERPLATE (GstGConfAudioSink, gst_gconf_audio_sink, GstBin, GST_TYPE_BIN); +GST_BOILERPLATE (GstGConfAudioSink, gst_gconf_audio_sink, GstSwitchSink, + GST_TYPE_SWITCH_SINK); static void gst_gconf_audio_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); @@ -55,14 +58,8 @@ gst_gconf_audio_sink_base_init (gpointer klass) GST_ELEMENT_DETAILS ("GConf audio sink", "Sink/Audio", "Audio sink embedding the GConf-settings for audio output", - "Ronald Bultje <rbultje@ronald.bitfreak.net>"); - GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - - gst_element_class_add_pad_template (eklass, - gst_static_pad_template_get (&sink_template)); + "Ronald Bultje <rbultje@ronald.bitfreak.net>\n" + "Jan Schmidt <thaytan@mad.scientist.com>"); gst_element_class_set_details (eklass, &gst_gconf_audio_sink_details); } @@ -101,68 +98,28 @@ gst_gconf_audio_sink_class_init (GstGConfAudioSinkClass * klass) GST_TYPE_GCONF_PROFILE, GCONF_PROFILE_SOUNDS, G_PARAM_READWRITE)); } -/* - * Hack to make negotiation work. - */ - static void gst_gconf_audio_sink_reset (GstGConfAudioSink * sink) { - GstPad *targetpad; - - /* fakesink */ - if (sink->kid) { - gst_element_set_state (sink->kid, GST_STATE_NULL); - gst_bin_remove (GST_BIN (sink), sink->kid); - } - sink->kid = gst_element_factory_make ("fakesink", "testsink"); - gst_bin_add (GST_BIN (sink), sink->kid); - - targetpad = gst_element_get_pad (sink->kid, "sink"); - gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad); - gst_object_unref (targetpad); + gst_switch_sink_set_child (GST_SWITCH_SINK (sink), NULL); g_free (sink->gconf_str); sink->gconf_str = NULL; - if (sink->connection) { - gconf_client_notify_remove (sink->client, sink->connection); - sink->connection = 0; - } -} - -static const gchar * -get_gconf_key_for_profile (int profile) -{ - switch (profile) { - case GCONF_PROFILE_SOUNDS: - return GST_GCONF_DIR GST_GCONF_AUDIOSINK_KEY; - case GCONF_PROFILE_MUSIC: - return GST_GCONF_DIR GST_GCONF_MUSIC_AUDIOSINK_KEY; - case GCONF_PROFILE_CHAT: - return GST_GCONF_DIR GST_GCONF_CHAT_AUDIOSINK_KEY; - default: - g_return_val_if_reached (NULL); - } + gst_gconf_switch_profile (sink, GCONF_PROFILE_NONE); } static void gst_gconf_audio_sink_init (GstGConfAudioSink * sink, GstGConfAudioSinkClass * g_class) { - sink->pad = gst_ghost_pad_new_no_target ("sink", GST_PAD_SINK); - gst_element_add_pad (GST_ELEMENT (sink), sink->pad); - gst_gconf_audio_sink_reset (sink); sink->client = gconf_client_get_default (); - gconf_client_add_dir (sink->client, GST_GCONF_DIR, + gconf_client_add_dir (sink->client, GST_GCONF_DIR "/default", GCONF_CLIENT_PRELOAD_RECURSIVE, NULL); - sink->profile = GCONF_PROFILE_SOUNDS; - sink->connection = gconf_client_notify_add (sink->client, - get_gconf_key_for_profile (sink->profile), cb_toggle_element, - sink, NULL, NULL); + gst_gconf_switch_profile (sink, GCONF_PROFILE_SOUNDS); } static void @@ -171,11 +128,7 @@ gst_gconf_audio_sink_dispose (GObject * object) GstGConfAudioSink *sink = GST_GCONF_AUDIO_SINK (object); if (sink->client) { - if (sink->connection) { - gconf_client_notify_remove (sink->client, sink->connection); - sink->connection = 0; - } - + gst_gconf_switch_profile (sink, GCONF_PROFILE_NONE); g_object_unref (G_OBJECT (sink->client)); sink->client = NULL; } @@ -187,12 +140,11 @@ gst_gconf_audio_sink_dispose (GObject * object) } static gboolean -do_toggle_element (GstGConfAudioSink * sink) +do_change_child (GstGConfAudioSink * sink) { const gchar *key; - GstPad *targetpad; gchar *new_gconf_str; - GstState cur, next; + GstElement *new_kid; key = gst_gconf_get_key_for_sink_profile (sink->profile); new_gconf_str = gst_gconf_get_string (key); @@ -204,57 +156,65 @@ do_toggle_element (GstGConfAudioSink * sink) (strlen (new_gconf_str) == 0 || strcmp (sink->gconf_str, new_gconf_str) == 0)) { g_free (new_gconf_str); - GST_DEBUG_OBJECT (sink, "GConf key was updated, but it didn't change"); - return TRUE; - } - - /* Sometime, it would be lovely to allow sink changes even when - * already running, but this involves sending an appropriate new-segment - * and possibly prerolling etc */ - GST_OBJECT_LOCK (sink); - cur = GST_STATE (sink); - next = GST_STATE_PENDING (sink); - GST_OBJECT_UNLOCK (sink); - - if (cur > GST_STATE_READY || next == GST_STATE_PAUSED) { GST_DEBUG_OBJECT (sink, - "Auto-sink is already running. Ignoring GConf change"); + "GConf key was updated, but it didn't change. Ignoring"); return TRUE; } GST_DEBUG_OBJECT (sink, "GConf key changed: '%s' to '%s'", GST_STR_NULL (sink->gconf_str), GST_STR_NULL (new_gconf_str)); - g_free (sink->gconf_str); - sink->gconf_str = new_gconf_str; - - /* kill old element */ - if (sink->kid) { - GST_DEBUG_OBJECT (sink, "Removing old kid"); - gst_element_set_state (sink->kid, GST_STATE_NULL); - gst_bin_remove (GST_BIN (sink), sink->kid); - sink->kid = NULL; - } + GST_DEBUG_OBJECT (sink, "Creating new child for profile %d", sink->profile); + new_kid = + gst_gconf_render_bin_with_default (new_gconf_str, DEFAULT_AUDIOSINK); - GST_DEBUG_OBJECT (sink, "Creating new kid"); - if (!(sink->kid = gst_gconf_get_default_audio_sink (sink->profile))) { + if (new_kid == NULL) { GST_ELEMENT_ERROR (sink, LIBRARY, SETTINGS, (NULL), ("Failed to render audio sink from GConf")); - g_free (sink->gconf_str); - sink->gconf_str = NULL; - return FALSE; + goto fail; + } + + if (!gst_switch_sink_set_child (GST_SWITCH_SINK (sink), new_kid)) { + GST_WARNING_OBJECT (sink, "Failed to update child element"); + goto fail; } - gst_element_set_state (sink->kid, GST_STATE (sink)); - gst_bin_add (GST_BIN (sink), sink->kid); - - /* re-attach ghostpad */ - GST_DEBUG_OBJECT (sink, "Creating new ghostpad"); - targetpad = gst_element_get_pad (sink->kid, "sink"); - gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad); - gst_object_unref (targetpad); + + g_free (sink->gconf_str); + sink->gconf_str = new_gconf_str; + GST_DEBUG_OBJECT (sink, "done changing gconf audio sink"); return TRUE; + +fail: + g_free (new_gconf_str); + return FALSE; +} + +static void +gst_gconf_switch_profile (GstGConfAudioSink * sink, GstGConfProfile profile) +{ + if (sink->client == NULL) + return; + + if (sink->connection) { + const gchar *key = gst_gconf_get_key_for_sink_profile (sink->profile); + + GST_DEBUG_OBJECT (sink, "Unsubscribing old key %s for profile %d", + key, sink->profile); + gconf_client_notify_remove (sink->client, sink->connection); + sink->connection = 0; + } + + sink->profile = profile; + if (profile != GCONF_PROFILE_NONE) { + const gchar *key = gst_gconf_get_key_for_sink_profile (sink->profile); + + GST_DEBUG_OBJECT (sink, "Subscribing to key %s for profile %d", + key, profile); + sink->connection = gconf_client_notify_add (sink->client, key, + cb_change_child, sink, NULL, NULL); + } } static void @@ -267,13 +227,7 @@ gst_gconf_audio_sink_set_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_PROFILE: - sink->profile = g_value_get_enum (value); - if (sink->connection) { - gconf_client_notify_remove (sink->client, sink->connection); - } - sink->connection = gconf_client_notify_add (sink->client, - get_gconf_key_for_profile (sink->profile), cb_toggle_element, - sink, NULL, NULL); + gst_gconf_switch_profile (sink, g_value_get_enum (value)); break; default: break; @@ -299,10 +253,10 @@ gst_gconf_audio_sink_get_property (GObject * object, guint prop_id, } static void -cb_toggle_element (GConfClient * client, +cb_change_child (GConfClient * client, guint connection_id, GConfEntry * entry, gpointer data) { - do_toggle_element (GST_GCONF_AUDIO_SINK (data)); + do_change_child (GST_GCONF_AUDIO_SINK (data)); } static GstStateChangeReturn @@ -314,8 +268,10 @@ gst_gconf_audio_sink_change_state (GstElement * element, switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: - if (!do_toggle_element (sink)) + if (!do_change_child (sink)) { + gst_gconf_audio_sink_reset (sink); return GST_STATE_CHANGE_FAILURE; + } break; default: break; |