summaryrefslogtreecommitdiffstats
path: root/ext/gconf/gstgconfaudiosink.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/gconf/gstgconfaudiosink.c')
-rw-r--r--ext/gconf/gstgconfaudiosink.c174
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;