summaryrefslogtreecommitdiffstats
path: root/ext/gconf/gstgconfaudiosink.c
diff options
context:
space:
mode:
authorJan Schmidt <thaytan@mad.scientist.com>2007-02-13 16:01:29 +0000
committerJan Schmidt <thaytan@mad.scientist.com>2007-02-13 16:01:29 +0000
commitb1aa8fef181a00cc6dc6fa38654ceb937cec3898 (patch)
tree9e22511ad16ba44c88d8335cdbc1d46418bd5398 /ext/gconf/gstgconfaudiosink.c
parent5116ff603e735bf5045db60df8025e4b824acb81 (diff)
Re-factor the gconfaudiosink into a "GstSwitchSink" base class and a child that implements the GConf key monitoring. ...
Original commit message from CVS: * ext/gconf/Makefile.am: * ext/gconf/gconf.c: (gst_gconf_get_string), (gst_gconf_get_key_for_sink_profile), (gst_gconf_set_string), (gst_gconf_render_bin_with_default): * ext/gconf/gconf.h: * ext/gconf/gstgconfaudiosink.c: (gst_gconf_audio_sink_base_init), (gst_gconf_audio_sink_reset), (gst_gconf_audio_sink_init), (gst_gconf_audio_sink_dispose), (do_change_child), (gst_gconf_switch_profile), (gst_gconf_audio_sink_set_property), (cb_change_child), (gst_gconf_audio_sink_change_state): * ext/gconf/gstgconfaudiosink.h: * ext/gconf/gstswitchsink.c: (gst_switch_sink_base_init), (gst_switch_sink_class_init), (gst_switch_sink_reset), (gst_switch_sink_init), (gst_switch_sink_dispose), (gst_switch_commit_new_kid), (gst_switch_sink_set_child), (gst_switch_sink_set_property), (gst_switch_sink_handle_event), (gst_switch_sink_get_property), (gst_switch_sink_change_state): * ext/gconf/gstswitchsink.h: * gst/autodetect/gstautoaudiosink.c: (gst_auto_audio_sink_class_init), (gst_auto_audio_sink_dispose), (gst_auto_audio_sink_clear_kid), (gst_auto_audio_sink_reset), (gst_auto_audio_sink_detect): * gst/autodetect/gstautovideosink.c: (gst_auto_video_sink_class_init), (gst_auto_video_sink_dispose), (gst_auto_video_sink_clear_kid), (gst_auto_video_sink_reset), (gst_auto_video_sink_detect): Re-factor the gconfaudiosink into a "GstSwitchSink" base class and a child that implements the GConf key monitoring. The end goal of this is an audio sink that can be changed on the fly, but at the moment it still only changes on the next READY transition.
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;