Commit b1aa8fef authored by Jan Schmidt's avatar Jan Schmidt
Browse files

Re-factor the gconfaudiosink into a "GstSwitchSink" base class and a child...

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.
parent 5116ff60
2007-02-13 Jan Schmidt <thaytan@mad.scientist.com>
* 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.
2007-02-13 Stefan Kost <ensonic@users.sf.net>
* gst/avi/gstavidemux.c: (gst_avi_demux_handle_src_query),
......
......@@ -6,6 +6,7 @@ libgstgconfelements_la_SOURCES = \
gstgconfelements.c \
gstgconfvideosink.c \
gstgconfvideosrc.c \
gstswitchsink.c \
gconf.c
DIR_CFLAGS = -DGST_GCONF_DIR=\"/system/gstreamer/@GST_MAJORMINOR@\"
......@@ -19,4 +20,5 @@ noinst_HEADERS = \
gstgconfelements.h \
gstgconfvideosink.h \
gstgconfvideosrc.h \
gstswitchsink.h \
gconf.h
/* GStreamer
* nf_get_default_audio_sink
* Copyright (C) <2002> Thomas Vander Stichele <thomas@apestaart.org>
* Copyright (C) <2006> Jürg Billeter <j@bitron.ch>
*
......@@ -26,6 +27,8 @@
#include "config.h"
#endif
#include <gst/gst.h>
#include "gconf.h"
#include "gstgconfelements.h" /* for debug category */
......@@ -63,8 +66,12 @@ gst_gconf_get_string (const gchar * key)
{
GError *error = NULL;
gchar *value = NULL;
gchar *full_key = g_strdup_printf ("%s/%s", GST_GCONF_DIR, key);
gchar *full_key;
if (!g_str_has_prefix (key, GST_GCONF_DIR))
full_key = g_strdup_printf ("%s/%s", GST_GCONF_DIR, key);
else
full_key = g_strdup (key);
value = gconf_client_get_string (gst_gconf_get_client (), full_key, &error);
g_free (full_key);
......@@ -79,20 +86,20 @@ gst_gconf_get_string (const gchar * key)
}
const gchar *
gst_gconf_get_key_for_sink_profile (guint profile)
gst_gconf_get_key_for_sink_profile (GstGConfProfile profile)
{
switch (profile) {
case GCONF_PROFILE_SOUNDS:
return GST_GCONF_AUDIOSINK_KEY;
return GST_GCONF_DIR "/" GST_GCONF_AUDIOSINK_KEY;
case GCONF_PROFILE_MUSIC:
return GST_GCONF_MUSIC_AUDIOSINK_KEY;
return GST_GCONF_DIR "/" GST_GCONF_MUSIC_AUDIOSINK_KEY;
case GCONF_PROFILE_CHAT:
return GST_GCONF_CHAT_AUDIOSINK_KEY;
return GST_GCONF_DIR "/" GST_GCONF_CHAT_AUDIOSINK_KEY;
default:
break;
}
g_return_val_if_reached (GST_GCONF_AUDIOSINK_KEY);
g_return_val_if_reached (GST_GCONF_DIR "/" GST_GCONF_AUDIOSINK_KEY);
}
/**
......@@ -106,7 +113,12 @@ void
gst_gconf_set_string (const gchar * key, const gchar * value)
{
GError *error = NULL;
gchar *full_key = g_strdup_printf ("%s/%s", GST_GCONF_DIR, key);
gchar *full_key;
if (!g_str_has_prefix (key, GST_GCONF_DIR))
full_key = g_strdup_printf ("%s/%s", GST_GCONF_DIR, key);
else
full_key = g_strdup (key);
gconf_client_set_string (gst_gconf_get_client (), full_key, value, &error);
if (error) {
......@@ -149,27 +161,25 @@ gst_gconf_render_bin_from_key (const gchar * key)
}
/**
* gst_gconf_get_default_audio_sink:
* @profile: the appropriate application profile.
* gst_gconf_render_bin_with_default:
* @bin: a #gchar string corresponding to pipeline to construct.
* @default: a pipeline description to use as default if the GConf key
* pipeline fails to construct.
*
* Render audio output bin from GStreamer GConf key : "default/audiosink".
* If key is invalid, the default audio sink for the platform is used
* (typically osssink or sunaudiosink).
* Render bin from GConf key @key using @default as a fallback.
*
* Returns: a #GstElement containing the audio output bin, or NULL if
* everything failed.
* Returns: a #GstElement containing the rendered bin.
*/
GstElement *
gst_gconf_get_default_audio_sink (int profile)
gst_gconf_render_bin_with_default (const gchar * bin,
const gchar * default_sink)
{
GstElement *ret;
const gchar *key;
key = gst_gconf_get_key_for_sink_profile (profile);
ret = gst_gconf_render_bin_from_key (key);
ret = gst_element_factory_make (bin, NULL);
if (!ret) {
ret = gst_element_factory_make (DEFAULT_AUDIOSINK, NULL);
ret = gst_element_factory_make (default_sink, NULL);
if (!ret)
g_warning ("No GConf default audio sink key and %s doesn't work",
......
......@@ -37,12 +37,13 @@ G_BEGIN_DECLS
#define GST_GCONF_VIDEOSRC_KEY "default/videosrc"
#define GST_GCONF_VIDEOSINK_KEY "default/videosink"
enum
typedef enum
{
GCONF_PROFILE_SOUNDS,
GCONF_PROFILE_MUSIC,
GCONF_PROFILE_CHAT
};
GCONF_PROFILE_CHAT,
GCONF_PROFILE_NONE /* Internal value only */
} GstGConfProfile;
gchar * gst_gconf_get_string (const gchar *key);
void gst_gconf_set_string (const gchar *key,
......@@ -51,6 +52,8 @@ void gst_gconf_set_string (const gchar *key,
const gchar * gst_gconf_get_key_for_sink_profile (guint profile);
GstElement * gst_gconf_render_bin_from_key (const gchar *key);
GstElement * gst_gconf_render_bin_with_default (const gchar *bin,
const gchar *default_sink);
GstElement * gst_gconf_get_default_video_sink (void);
GstElement * gst_gconf_get_default_audio_sink (int profile);
......
......@@ -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;
......
......@@ -22,6 +22,7 @@
#include <gst/gst.h>
#include <gconf/gconf-client.h>
#include "gstswitchsink.h"
G_BEGIN_DECLS
......@@ -39,21 +40,19 @@ G_BEGIN_DECLS
(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_GCONF_AUDIO_SINK))
typedef struct _GstGConfAudioSink {
GstBin parent;
GstSwitchSink parent;
/* explicit pointers to stuff used */
GConfClient *client;
int profile;
GstGConfProfile profile;
guint connection;
GstElement *kid;
GstPad *pad;
/* Current gconf string */
gchar *gconf_str;
} GstGConfAudioSink;
typedef struct _GstGConfAudioSinkClass {
GstBinClass parent_class;
GstSwitchSinkClass parent_class;
} GstGConfAudioSinkClass;
GType gst_gconf_audio_sink_get_type (void);
......
/* GStreamer
* (c) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
* (c) 2006 Jürg Billeter <j@bitron.ch>
* (c) 2007 Jan Schmidt <thaytan@noraisin.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include "gstswitchsink.h"
GST_DEBUG_CATEGORY_STATIC (switch_debug);
#define GST_CAT_DEFAULT switch_debug
static void gst_switch_sink_dispose (GObject * object);
static GstStateChangeReturn
gst_switch_sink_change_state (GstElement * element, GstStateChange transition);
enum
{
PROP_0
};
GST_BOILERPLATE (GstSwitchSink, gst_switch_sink, GstBin, GST_TYPE_BIN);
static void gst_switch_sink_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_switch_sink_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static void
gst_switch_sink_base_init (gpointer klass)
{
GST_DEBUG_CATEGORY_INIT (switch_debug, "switchsink", 0, "switchsink element");
}
static void
gst_switch_sink_class_init (GstSwitchSinkClass * klass)
{
GObjectClass *oklass = G_OBJECT_CLASS (klass);
GstElementClass *eklass = GST_ELEMENT_CLASS (klass);
GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
GstPadTemplate *child_pad_templ;
oklass->set_property = gst_switch_sink_set_property;
oklass->get_property = gst_switch_sink_get_property;
oklass->dispose = gst_switch_sink_dispose;
eklass->change_state = gst_switch_sink_change_state;
/* Provide a default pad template if the child didn't */
child_pad_templ = gst_element_class_get_pad_template (eklass, "sink");
if (child_pad_templ == NULL) {
gst_element_class_add_pad_template (eklass,
gst_static_pad_template_get (&sink_template));
}
}
static void
gst_switch_sink_reset (GstSwitchSink * sink)
{
/* fakesink */
if (sink->kid == NULL) {
gst_switch_sink_set_child (sink, NULL);
}
}
static void
gst_switch_sink_init (GstSwitchSink * sink, GstSwitchSinkClass * g_class)
{
sink->pad = gst_ghost_pad_new_no_target ("sink", GST_PAD_SINK);
gst_element_add_pad (GST_ELEMENT (sink), sink->pad);
gst_switch_sink_reset (sink);
}
static void
gst_switch_sink_dispose (GObject * object)
{
GstSwitchSink *sink = GST_SWITCH_SINK (object);
GstElement **p_kid = &sink->kid;
gst_object_replace ((GstObject **) p_kid, NULL);
GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
}
gboolean
gst_switch_commit_new_kid (GstSwitchSink * sink)
{
GstPad *targetpad;
GstState cur_state;
GstElement *new_kid, *old_kid;
gboolean is_fakesink = FALSE;
/* need locking around member accesses */
GST_OBJECT_LOCK (sink);
cur_state = GST_STATE (sink);
new_kid = sink->new_kid;
sink->new_kid = NULL;
GST_OBJECT_UNLOCK (sink);
/* Fakesink by default if NULL is passed as the new child */
if (new_kid == NULL) {
GST_DEBUG_OBJECT (sink, "Replacing kid with fakesink");
new_kid = gst_element_factory_make ("fakesink", "testsink");
g_object_set (new_kid, "sync", TRUE, NULL);
is_fakesink = TRUE;
} else {
GST_DEBUG_OBJECT (sink, "Setting new kid");
}