2000-12-28 22:12:02 +00:00
|
|
|
/* GStreamer
|
2005-06-27 08:16:51 +00:00
|
|
|
*
|
2000-12-28 22:12:02 +00:00
|
|
|
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
|
2005-03-07 18:27:42 +00:00
|
|
|
* 2004 Wim Taymans <wim@fluendo.com>
|
2000-12-28 22:12:02 +00:00
|
|
|
*
|
|
|
|
* gstbin.c: GstBin container object and support code
|
2000-01-30 09:03:00 +00:00
|
|
|
*
|
|
|
|
* 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.
|
2005-03-07 18:27:42 +00:00
|
|
|
*
|
|
|
|
* MT safe.
|
2000-01-30 09:03:00 +00:00
|
|
|
*/
|
|
|
|
|
2000-12-28 22:12:02 +00:00
|
|
|
#include "gst_private.h"
|
2000-12-08 18:24:16 +00:00
|
|
|
|
2001-12-18 19:03:07 +00:00
|
|
|
#include "gstevent.h"
|
2000-12-15 01:57:34 +00:00
|
|
|
#include "gstbin.h"
|
2004-02-03 03:31:26 +00:00
|
|
|
#include "gstmarshal.h"
|
2002-02-03 20:07:09 +00:00
|
|
|
#include "gstxml.h"
|
2003-06-29 14:05:49 +00:00
|
|
|
#include "gstinfo.h"
|
2004-02-24 12:41:19 +00:00
|
|
|
#include "gsterror.h"
|
2000-08-21 21:20:38 +00:00
|
|
|
|
2000-12-26 23:51:04 +00:00
|
|
|
#include "gstscheduler.h"
|
2002-12-19 21:31:03 +00:00
|
|
|
#include "gstindex.h"
|
2004-07-12 21:27:11 +00:00
|
|
|
#include "gstutils.h"
|
2000-12-26 23:51:04 +00:00
|
|
|
|
2004-08-03 09:51:37 +00:00
|
|
|
GST_DEBUG_CATEGORY_STATIC (bin_debug);
|
|
|
|
#define GST_CAT_DEFAULT bin_debug
|
|
|
|
#define GST_LOG_BIN_CONTENTS(bin, text) GST_LOG_OBJECT ((bin), \
|
|
|
|
text ": %d elements: %u PLAYING, %u PAUSED, %u READY, %u NULL, own state: %s", \
|
|
|
|
(bin)->numchildren, (guint) (bin)->child_states[3], \
|
|
|
|
(guint) (bin)->child_states[2], (bin)->child_states[1], \
|
|
|
|
(bin)->child_states[0], gst_element_state_get_name (GST_STATE (bin)))
|
|
|
|
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
static GstElementDetails gst_bin_details = GST_ELEMENT_DETAILS ("Generic bin",
|
|
|
|
"Generic/Bin",
|
|
|
|
"Simple container object",
|
2005-03-07 18:27:42 +00:00
|
|
|
"Erik Walthinsen <omega@cse.ogi.edu>," "Wim Taymans <wim@fluendo.com>");
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2004-06-12 13:45:17 +00:00
|
|
|
GType _gst_bin_type = 0;
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
static void gst_bin_dispose (GObject * object);
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2004-07-29 20:33:49 +00:00
|
|
|
static GstElementStateReturn gst_bin_change_state (GstElement * element);
|
2005-03-21 17:34:02 +00:00
|
|
|
static GstElementStateReturn gst_bin_get_state (GstElement * element,
|
|
|
|
GstElementState * state, GstElementState * pending, GTimeVal * timeout);
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2005-03-09 16:10:59 +00:00
|
|
|
static gboolean gst_bin_add_func (GstBin * bin, GstElement * element);
|
|
|
|
static gboolean gst_bin_remove_func (GstBin * bin, GstElement * element);
|
|
|
|
|
2003-02-10 20:32:32 +00:00
|
|
|
#ifndef GST_DISABLE_INDEX
|
2005-03-09 16:10:59 +00:00
|
|
|
static void gst_bin_set_index_func (GstElement * element, GstIndex * index);
|
2003-02-10 20:32:32 +00:00
|
|
|
#endif
|
2005-03-09 16:10:59 +00:00
|
|
|
static GstClock *gst_bin_get_clock_func (GstElement * element);
|
|
|
|
static void gst_bin_set_clock_func (GstElement * element, GstClock * clock);
|
2002-12-19 21:31:03 +00:00
|
|
|
|
2005-03-28 14:54:33 +00:00
|
|
|
static void gst_bin_set_manager (GstElement * element, GstPipeline * manager);
|
2005-03-21 17:34:02 +00:00
|
|
|
static void gst_bin_set_bus (GstElement * element, GstBus * bus);
|
|
|
|
static void gst_bin_set_scheduler (GstElement * element, GstScheduler * sched);
|
2003-01-11 20:08:03 +00:00
|
|
|
|
2005-03-28 14:54:33 +00:00
|
|
|
static gboolean gst_bin_send_event (GstElement * element, GstEvent * event);
|
2005-05-12 15:09:17 +00:00
|
|
|
static gboolean gst_bin_query (GstElement * element, GstQuery * query);
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2001-06-25 06:45:56 +00:00
|
|
|
#ifndef GST_DISABLE_LOADSAVE
|
2004-03-13 15:27:01 +00:00
|
|
|
static xmlNodePtr gst_bin_save_thyself (GstObject * object, xmlNodePtr parent);
|
|
|
|
static void gst_bin_restore_thyself (GstObject * object, xmlNodePtr self);
|
2001-06-24 21:18:28 +00:00
|
|
|
#endif
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2005-05-12 19:45:44 +00:00
|
|
|
static gint bin_element_is_sink (GstElement * child, GstBin * bin);
|
|
|
|
|
2000-01-30 09:03:00 +00:00
|
|
|
/* Bin signals and args */
|
2001-12-15 22:37:35 +00:00
|
|
|
enum
|
|
|
|
{
|
2002-12-19 21:31:03 +00:00
|
|
|
ELEMENT_ADDED,
|
|
|
|
ELEMENT_REMOVED,
|
2000-01-30 09:03:00 +00:00
|
|
|
LAST_SIGNAL
|
|
|
|
};
|
|
|
|
|
2001-12-15 22:37:35 +00:00
|
|
|
enum
|
|
|
|
{
|
2003-05-15 22:46:37 +00:00
|
|
|
ARG_0
|
2004-03-13 15:27:01 +00:00
|
|
|
/* FILL ME */
|
2000-01-30 09:03:00 +00:00
|
|
|
};
|
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
static void gst_bin_base_init (gpointer g_class);
|
|
|
|
static void gst_bin_class_init (GstBinClass * klass);
|
|
|
|
static void gst_bin_init (GstBin * bin);
|
2000-01-30 09:03:00 +00:00
|
|
|
|
|
|
|
static GstElementClass *parent_class = NULL;
|
|
|
|
static guint gst_bin_signals[LAST_SIGNAL] = { 0 };
|
|
|
|
|
2004-03-26 03:46:16 +00:00
|
|
|
/**
|
|
|
|
* gst_bin_get_type:
|
|
|
|
*
|
|
|
|
* Returns: the type of #GstBin
|
|
|
|
*/
|
2001-06-25 01:20:11 +00:00
|
|
|
GType
|
2001-01-20 03:10:44 +00:00
|
|
|
gst_bin_get_type (void)
|
2000-11-04 18:54:07 +00:00
|
|
|
{
|
2001-10-21 18:00:31 +00:00
|
|
|
if (!_gst_bin_type) {
|
2001-06-25 01:20:11 +00:00
|
|
|
static const GTypeInfo bin_info = {
|
2001-12-15 22:37:35 +00:00
|
|
|
sizeof (GstBinClass),
|
2003-10-31 19:32:47 +00:00
|
|
|
gst_bin_base_init,
|
2001-06-25 01:20:11 +00:00
|
|
|
NULL,
|
2001-12-15 22:37:35 +00:00
|
|
|
(GClassInitFunc) gst_bin_class_init,
|
2001-06-25 01:20:11 +00:00
|
|
|
NULL,
|
|
|
|
NULL,
|
2001-12-15 22:37:35 +00:00
|
|
|
sizeof (GstBin),
|
2004-04-09 19:05:03 +00:00
|
|
|
0,
|
2001-12-15 22:37:35 +00:00
|
|
|
(GInstanceInitFunc) gst_bin_init,
|
2001-09-14 22:16:47 +00:00
|
|
|
NULL
|
2000-01-30 09:03:00 +00:00
|
|
|
};
|
2001-12-15 22:37:35 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
_gst_bin_type =
|
2004-03-15 19:27:17 +00:00
|
|
|
g_type_register_static (GST_TYPE_ELEMENT, "GstBin", &bin_info, 0);
|
2004-08-03 09:51:37 +00:00
|
|
|
|
|
|
|
GST_DEBUG_CATEGORY_INIT (bin_debug, "bin", GST_DEBUG_BOLD,
|
|
|
|
"debugging info for the 'bin' container element");
|
2000-01-30 09:03:00 +00:00
|
|
|
}
|
2001-10-21 18:00:31 +00:00
|
|
|
return _gst_bin_type;
|
2000-01-30 09:03:00 +00:00
|
|
|
}
|
|
|
|
|
2003-10-31 19:32:47 +00:00
|
|
|
static void
|
|
|
|
gst_bin_base_init (gpointer g_class)
|
|
|
|
{
|
|
|
|
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2003-10-31 19:32:47 +00:00
|
|
|
gst_element_class_set_details (gstelement_class, &gst_bin_details);
|
|
|
|
}
|
|
|
|
|
2000-01-30 09:03:00 +00:00
|
|
|
static void
|
2001-12-15 22:37:35 +00:00
|
|
|
gst_bin_class_init (GstBinClass * klass)
|
2000-11-04 18:54:07 +00:00
|
|
|
{
|
2001-06-25 01:20:11 +00:00
|
|
|
GObjectClass *gobject_class;
|
2001-01-29 00:06:02 +00:00
|
|
|
GstObjectClass *gstobject_class;
|
2000-01-30 09:03:00 +00:00
|
|
|
GstElementClass *gstelement_class;
|
|
|
|
|
2001-12-15 22:37:35 +00:00
|
|
|
gobject_class = (GObjectClass *) klass;
|
|
|
|
gstobject_class = (GstObjectClass *) klass;
|
|
|
|
gstelement_class = (GstElementClass *) klass;
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2001-06-25 01:20:11 +00:00
|
|
|
parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2002-12-19 21:31:03 +00:00
|
|
|
gst_bin_signals[ELEMENT_ADDED] =
|
2004-03-13 15:27:01 +00:00
|
|
|
g_signal_new ("element-added", G_TYPE_FROM_CLASS (klass),
|
|
|
|
G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_added), NULL,
|
|
|
|
NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
|
2002-12-19 21:31:03 +00:00
|
|
|
gst_bin_signals[ELEMENT_REMOVED] =
|
2004-03-13 15:27:01 +00:00
|
|
|
g_signal_new ("element-removed", G_TYPE_FROM_CLASS (klass),
|
|
|
|
G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (GstBinClass, element_removed), NULL,
|
|
|
|
NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
|
2001-12-18 19:03:07 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_bin_dispose);
|
2002-01-18 22:44:19 +00:00
|
|
|
|
2001-06-25 06:45:56 +00:00
|
|
|
#ifndef GST_DISABLE_LOADSAVE
|
2004-03-13 15:27:01 +00:00
|
|
|
gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_bin_save_thyself);
|
|
|
|
gstobject_class->restore_thyself =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_bin_restore_thyself);
|
2001-06-24 21:18:28 +00:00
|
|
|
#endif
|
2001-01-29 00:06:02 +00:00
|
|
|
|
2004-07-29 20:33:49 +00:00
|
|
|
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_bin_change_state);
|
2005-03-21 17:34:02 +00:00
|
|
|
gstelement_class->get_state = GST_DEBUG_FUNCPTR (gst_bin_get_state);
|
2003-02-10 20:32:32 +00:00
|
|
|
#ifndef GST_DISABLE_INDEX
|
2005-03-09 16:10:59 +00:00
|
|
|
gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index_func);
|
2003-02-10 20:32:32 +00:00
|
|
|
#endif
|
2005-03-09 16:10:59 +00:00
|
|
|
gstelement_class->get_clock = GST_DEBUG_FUNCPTR (gst_bin_get_clock_func);
|
|
|
|
gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_bin_set_clock_func);
|
2005-03-28 14:54:33 +00:00
|
|
|
gstelement_class->set_manager = GST_DEBUG_FUNCPTR (gst_bin_set_manager);
|
2005-03-21 17:34:02 +00:00
|
|
|
gstelement_class->set_bus = GST_DEBUG_FUNCPTR (gst_bin_set_bus);
|
|
|
|
gstelement_class->set_scheduler = GST_DEBUG_FUNCPTR (gst_bin_set_scheduler);
|
2001-10-17 10:21:27 +00:00
|
|
|
|
2005-03-28 14:54:33 +00:00
|
|
|
gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_bin_send_event);
|
2005-05-12 15:09:17 +00:00
|
|
|
gstelement_class->query = GST_DEBUG_FUNCPTR (gst_bin_query);
|
2005-03-28 14:54:33 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
klass->add_element = GST_DEBUG_FUNCPTR (gst_bin_add_func);
|
|
|
|
klass->remove_element = GST_DEBUG_FUNCPTR (gst_bin_remove_func);
|
2003-10-14 00:00:37 +00:00
|
|
|
}
|
|
|
|
|
2001-01-20 03:10:44 +00:00
|
|
|
static void
|
2001-12-15 22:37:35 +00:00
|
|
|
gst_bin_init (GstBin * bin)
|
2000-11-04 18:54:07 +00:00
|
|
|
{
|
2000-01-30 09:03:00 +00:00
|
|
|
bin->numchildren = 0;
|
|
|
|
bin->children = NULL;
|
2005-03-07 18:27:42 +00:00
|
|
|
bin->children_cookie = 0;
|
2000-01-30 09:03:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_bin_new:
|
|
|
|
* @name: name of new bin
|
|
|
|
*
|
|
|
|
* Create a new bin with given name.
|
|
|
|
*
|
|
|
|
* Returns: new bin
|
|
|
|
*/
|
2001-12-15 22:37:35 +00:00
|
|
|
GstElement *
|
|
|
|
gst_bin_new (const gchar * name)
|
2000-11-04 18:54:07 +00:00
|
|
|
{
|
2002-04-11 20:35:18 +00:00
|
|
|
return gst_element_factory_make ("bin", name);
|
2000-01-30 09:03:00 +00:00
|
|
|
}
|
|
|
|
|
2005-03-09 16:10:59 +00:00
|
|
|
/* set the index on all elements in this bin
|
|
|
|
*
|
2005-06-27 08:16:51 +00:00
|
|
|
* MT safe
|
2005-03-09 16:10:59 +00:00
|
|
|
*/
|
|
|
|
#ifndef GST_DISABLE_INDEX
|
|
|
|
static void
|
|
|
|
gst_bin_set_index_func (GstElement * element, GstIndex * index)
|
2003-02-10 20:32:32 +00:00
|
|
|
{
|
2005-03-09 16:10:59 +00:00
|
|
|
GstBin *bin;
|
|
|
|
GList *children;
|
2003-02-10 20:32:32 +00:00
|
|
|
|
2005-03-09 16:10:59 +00:00
|
|
|
bin = GST_BIN (element);
|
2003-02-10 20:32:32 +00:00
|
|
|
|
2005-03-09 16:10:59 +00:00
|
|
|
GST_LOCK (bin);
|
|
|
|
for (children = bin->children; children; children = g_list_next (children)) {
|
|
|
|
GstElement *child = GST_ELEMENT (children->data);
|
|
|
|
|
|
|
|
gst_element_set_index (child, index);
|
|
|
|
}
|
|
|
|
GST_UNLOCK (bin);
|
2003-02-10 20:32:32 +00:00
|
|
|
}
|
2005-03-09 16:10:59 +00:00
|
|
|
#endif
|
2003-02-10 20:32:32 +00:00
|
|
|
|
2005-03-09 16:10:59 +00:00
|
|
|
/* set the clock on all elements in this bin
|
2002-03-31 14:04:50 +00:00
|
|
|
*
|
2005-06-27 08:16:51 +00:00
|
|
|
* MT safe
|
2002-03-31 14:04:50 +00:00
|
|
|
*/
|
2005-03-09 16:10:59 +00:00
|
|
|
static void
|
|
|
|
gst_bin_set_clock_func (GstElement * element, GstClock * clock)
|
2002-02-03 20:07:09 +00:00
|
|
|
{
|
2005-03-09 16:10:59 +00:00
|
|
|
GList *children;
|
|
|
|
GstBin *bin;
|
2002-02-03 20:07:09 +00:00
|
|
|
|
2005-03-09 16:10:59 +00:00
|
|
|
bin = GST_BIN (element);
|
2002-02-03 20:07:09 +00:00
|
|
|
|
2005-03-09 16:10:59 +00:00
|
|
|
GST_LOCK (bin);
|
|
|
|
for (children = bin->children; children; children = g_list_next (children)) {
|
|
|
|
GstElement *child = GST_ELEMENT (children->data);
|
2002-02-03 20:07:09 +00:00
|
|
|
|
2005-03-09 16:10:59 +00:00
|
|
|
gst_element_set_clock (child, clock);
|
|
|
|
}
|
|
|
|
GST_UNLOCK (bin);
|
2002-02-03 20:07:09 +00:00
|
|
|
}
|
|
|
|
|
2005-03-09 16:10:59 +00:00
|
|
|
/* get the clock for this bin by asking all of the children in this bin
|
2002-03-31 14:04:50 +00:00
|
|
|
*
|
2005-06-27 08:16:51 +00:00
|
|
|
* MT safe
|
2002-03-31 14:04:50 +00:00
|
|
|
*/
|
2005-03-09 16:10:59 +00:00
|
|
|
static GstClock *
|
|
|
|
gst_bin_get_clock_func (GstElement * element)
|
2001-05-25 21:00:07 +00:00
|
|
|
{
|
2005-03-09 16:10:59 +00:00
|
|
|
GstClock *result = NULL;
|
2005-03-07 18:27:42 +00:00
|
|
|
GstBin *bin;
|
|
|
|
GList *children;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
bin = GST_BIN (element);
|
|
|
|
|
|
|
|
GST_LOCK (bin);
|
|
|
|
for (children = bin->children; children; children = g_list_next (children)) {
|
|
|
|
GstElement *child = GST_ELEMENT (children->data);
|
2002-12-19 21:31:03 +00:00
|
|
|
|
2005-03-09 16:10:59 +00:00
|
|
|
result = gst_element_get_clock (child);
|
|
|
|
if (result)
|
|
|
|
break;
|
2005-03-07 18:27:42 +00:00
|
|
|
}
|
|
|
|
GST_UNLOCK (bin);
|
2005-03-09 16:10:59 +00:00
|
|
|
|
|
|
|
return result;
|
2002-12-19 21:31:03 +00:00
|
|
|
}
|
|
|
|
|
2005-03-21 17:34:02 +00:00
|
|
|
/* set the bus on all of the children in this bin
|
|
|
|
*
|
2005-06-27 08:16:51 +00:00
|
|
|
* MT safe
|
2005-03-21 17:34:02 +00:00
|
|
|
*/
|
2002-12-19 21:31:03 +00:00
|
|
|
static void
|
2005-03-21 17:34:02 +00:00
|
|
|
gst_bin_set_bus (GstElement * element, GstBus * bus)
|
2002-12-19 21:31:03 +00:00
|
|
|
{
|
2005-03-21 17:34:02 +00:00
|
|
|
GList *children;
|
|
|
|
GstBin *bin;
|
2004-11-22 23:50:37 +00:00
|
|
|
|
2005-03-21 17:34:02 +00:00
|
|
|
bin = GST_BIN (element);
|
2004-11-22 23:50:37 +00:00
|
|
|
|
2005-03-21 17:34:02 +00:00
|
|
|
parent_class->set_bus (element, bus);
|
2004-11-22 23:50:37 +00:00
|
|
|
|
2005-03-21 17:34:02 +00:00
|
|
|
GST_LOCK (bin);
|
|
|
|
for (children = bin->children; children; children = g_list_next (children)) {
|
|
|
|
GstElement *child = GST_ELEMENT (children->data);
|
2004-11-22 23:50:37 +00:00
|
|
|
|
2005-03-21 17:34:02 +00:00
|
|
|
gst_element_set_bus (child, bus);
|
2001-05-25 21:00:07 +00:00
|
|
|
}
|
2005-03-21 17:34:02 +00:00
|
|
|
GST_UNLOCK (bin);
|
2001-05-25 21:00:07 +00:00
|
|
|
}
|
|
|
|
|
2005-03-21 17:34:02 +00:00
|
|
|
/* set the scheduler on all of the children in this bin
|
|
|
|
*
|
2005-06-27 08:16:51 +00:00
|
|
|
* MT safe
|
2005-03-21 17:34:02 +00:00
|
|
|
*/
|
2001-09-14 22:16:47 +00:00
|
|
|
static void
|
2005-03-21 17:34:02 +00:00
|
|
|
gst_bin_set_scheduler (GstElement * element, GstScheduler * sched)
|
2001-05-25 21:00:07 +00:00
|
|
|
{
|
2005-03-21 17:34:02 +00:00
|
|
|
GList *children;
|
|
|
|
GstBin *bin;
|
2001-05-25 21:00:07 +00:00
|
|
|
|
2005-03-21 17:34:02 +00:00
|
|
|
bin = GST_BIN (element);
|
2001-05-25 21:00:07 +00:00
|
|
|
|
2005-03-21 17:34:02 +00:00
|
|
|
parent_class->set_scheduler (element, sched);
|
2002-11-02 13:54:34 +00:00
|
|
|
|
2005-03-21 17:34:02 +00:00
|
|
|
GST_LOCK (bin);
|
|
|
|
for (children = bin->children; children; children = g_list_next (children)) {
|
|
|
|
GstElement *child = GST_ELEMENT (children->data);
|
2004-11-22 23:50:37 +00:00
|
|
|
|
2005-03-21 17:34:02 +00:00
|
|
|
gst_element_set_scheduler (child, sched);
|
2001-05-25 21:00:07 +00:00
|
|
|
}
|
2005-03-21 17:34:02 +00:00
|
|
|
GST_UNLOCK (bin);
|
2001-05-25 21:00:07 +00:00
|
|
|
}
|
|
|
|
|
2005-03-28 14:54:33 +00:00
|
|
|
/* set the manager on all of the children in this bin
|
|
|
|
*
|
2005-06-27 08:16:51 +00:00
|
|
|
* MT safe
|
2005-03-28 14:54:33 +00:00
|
|
|
*/
|
|
|
|
static void
|
|
|
|
gst_bin_set_manager (GstElement * element, GstPipeline * manager)
|
|
|
|
{
|
|
|
|
GstBin *bin = GST_BIN (element);
|
|
|
|
GList *kids;
|
|
|
|
GstElement *kid;
|
|
|
|
|
|
|
|
GST_ELEMENT_CLASS (parent_class)->set_manager (element, manager);
|
|
|
|
|
|
|
|
GST_LOCK (element);
|
|
|
|
for (kids = bin->children; kids != NULL; kids = kids->next) {
|
|
|
|
kid = GST_ELEMENT (kids->data);
|
|
|
|
gst_element_set_manager (kid, manager);
|
|
|
|
}
|
|
|
|
GST_UNLOCK (element);
|
|
|
|
}
|
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
/* add an element to this bin
|
|
|
|
*
|
2005-06-27 08:16:51 +00:00
|
|
|
* MT safe
|
2002-03-31 14:04:50 +00:00
|
|
|
*/
|
2005-03-07 18:27:42 +00:00
|
|
|
static gboolean
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_bin_add_func (GstBin * bin, GstElement * element)
|
2000-11-04 18:54:07 +00:00
|
|
|
{
|
2005-03-07 18:27:42 +00:00
|
|
|
gchar *elem_name;
|
2001-12-10 18:08:35 +00:00
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
/* we obviously can't add ourself to ourself */
|
|
|
|
if (G_UNLIKELY (GST_ELEMENT_CAST (element) == GST_ELEMENT_CAST (bin)))
|
|
|
|
goto adding_itself;
|
2003-03-25 19:39:18 +00:00
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
/* get the element name to make sure it is unique in this bin, FIXME, another
|
|
|
|
* thread can change the name after the unlock. */
|
|
|
|
GST_LOCK (element);
|
|
|
|
elem_name = g_strdup (GST_ELEMENT_NAME (element));
|
|
|
|
GST_UNLOCK (element);
|
2000-07-17 17:14:15 +00:00
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
GST_LOCK (bin);
|
2005-05-12 12:17:23 +00:00
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
/* then check to see if the element's name is already taken in the bin,
|
|
|
|
* we can safely take the lock here. This check is probably bogus because
|
|
|
|
* you can safely change the element name after adding it to the bin. */
|
|
|
|
if (G_UNLIKELY (gst_object_check_uniqueness (bin->children,
|
|
|
|
elem_name) == FALSE))
|
|
|
|
goto duplicate_name;
|
2004-07-11 12:16:29 +00:00
|
|
|
|
2001-12-14 22:59:21 +00:00
|
|
|
/* set the element's parent and add the element to the bin's list of children */
|
2005-03-10 12:51:45 +00:00
|
|
|
if (G_UNLIKELY (!gst_object_set_parent (GST_OBJECT_CAST (element),
|
|
|
|
GST_OBJECT_CAST (bin))))
|
2005-03-07 18:27:42 +00:00
|
|
|
goto had_parent;
|
2001-12-04 22:12:50 +00:00
|
|
|
|
2005-05-12 19:45:44 +00:00
|
|
|
if (GST_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK))
|
|
|
|
GST_FLAG_SET (bin, GST_ELEMENT_IS_SINK);
|
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
bin->children = g_list_prepend (bin->children, element);
|
2000-01-30 09:03:00 +00:00
|
|
|
bin->numchildren++;
|
2005-03-07 18:27:42 +00:00
|
|
|
bin->children_cookie++;
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2005-03-21 17:34:02 +00:00
|
|
|
gst_element_set_manager (element, GST_ELEMENT (bin)->manager);
|
|
|
|
gst_element_set_bus (element, GST_ELEMENT (bin)->bus);
|
2005-03-07 18:27:42 +00:00
|
|
|
gst_element_set_scheduler (element, GST_ELEMENT_SCHEDULER (bin));
|
2005-05-18 13:49:08 +00:00
|
|
|
gst_element_set_clock (element, GST_ELEMENT_CLOCK (bin));
|
2005-03-07 18:27:42 +00:00
|
|
|
|
|
|
|
GST_UNLOCK (bin);
|
2000-12-30 02:41:15 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_CAT_DEBUG_OBJECT (GST_CAT_PARENTAGE, bin, "added element \"%s\"",
|
2005-03-07 18:27:42 +00:00
|
|
|
elem_name);
|
|
|
|
g_free (elem_name);
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2002-12-19 21:31:03 +00:00
|
|
|
g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_ADDED], 0, element);
|
2005-03-07 18:27:42 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
/* ERROR handling here */
|
|
|
|
adding_itself:
|
Docs updates, clean up some headers.
Original commit message from CVS:
* docs/design/part-MT-refcounting.txt:
* docs/design/part-conventions.txt:
* docs/design/part-gstobject.txt:
* docs/design/part-relations.txt:
* docs/design/part-standards.txt:
* gst/gstbin.c: (gst_bin_add_func), (gst_bin_add),
(gst_bin_remove_func), (gst_bin_remove), (gst_bin_iterate_recurse),
(gst_bin_get_by_name), (gst_bin_get_by_interface),
(gst_bin_iterate_all_by_interface):
* gst/gstbuffer.h:
* gst/gstclock.h:
* gst/gstelement.c: (gst_element_class_init),
(gst_element_change_state), (gst_element_set_loop_function):
* gst/gstelement.h:
* gst/gstiterator.c:
* gst/gstobject.c: (gst_object_class_init), (gst_object_ref),
(gst_object_unref), (gst_object_sink), (gst_object_dispose),
(gst_object_dispatch_properties_changed), (gst_object_set_name),
(gst_object_set_parent), (gst_object_unparent),
(gst_object_check_uniqueness):
* gst/gstobject.h:
Docs updates, clean up some headers.
Free iterators in GstBin.
GstObject is now looking good.
2005-03-08 14:38:06 +00:00
|
|
|
{
|
|
|
|
GST_LOCK (bin);
|
|
|
|
g_warning ("Cannot add bin %s to itself", GST_ELEMENT_NAME (bin));
|
|
|
|
GST_UNLOCK (bin);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2005-03-07 18:27:42 +00:00
|
|
|
duplicate_name:
|
Docs updates, clean up some headers.
Original commit message from CVS:
* docs/design/part-MT-refcounting.txt:
* docs/design/part-conventions.txt:
* docs/design/part-gstobject.txt:
* docs/design/part-relations.txt:
* docs/design/part-standards.txt:
* gst/gstbin.c: (gst_bin_add_func), (gst_bin_add),
(gst_bin_remove_func), (gst_bin_remove), (gst_bin_iterate_recurse),
(gst_bin_get_by_name), (gst_bin_get_by_interface),
(gst_bin_iterate_all_by_interface):
* gst/gstbuffer.h:
* gst/gstclock.h:
* gst/gstelement.c: (gst_element_class_init),
(gst_element_change_state), (gst_element_set_loop_function):
* gst/gstelement.h:
* gst/gstiterator.c:
* gst/gstobject.c: (gst_object_class_init), (gst_object_ref),
(gst_object_unref), (gst_object_sink), (gst_object_dispose),
(gst_object_dispatch_properties_changed), (gst_object_set_name),
(gst_object_set_parent), (gst_object_unparent),
(gst_object_check_uniqueness):
* gst/gstobject.h:
Docs updates, clean up some headers.
Free iterators in GstBin.
GstObject is now looking good.
2005-03-08 14:38:06 +00:00
|
|
|
{
|
|
|
|
g_warning ("Name %s is not unique in bin %s, not adding",
|
|
|
|
elem_name, GST_ELEMENT_NAME (bin));
|
|
|
|
GST_UNLOCK (bin);
|
|
|
|
g_free (elem_name);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2005-03-07 18:27:42 +00:00
|
|
|
had_parent:
|
Docs updates, clean up some headers.
Original commit message from CVS:
* docs/design/part-MT-refcounting.txt:
* docs/design/part-conventions.txt:
* docs/design/part-gstobject.txt:
* docs/design/part-relations.txt:
* docs/design/part-standards.txt:
* gst/gstbin.c: (gst_bin_add_func), (gst_bin_add),
(gst_bin_remove_func), (gst_bin_remove), (gst_bin_iterate_recurse),
(gst_bin_get_by_name), (gst_bin_get_by_interface),
(gst_bin_iterate_all_by_interface):
* gst/gstbuffer.h:
* gst/gstclock.h:
* gst/gstelement.c: (gst_element_class_init),
(gst_element_change_state), (gst_element_set_loop_function):
* gst/gstelement.h:
* gst/gstiterator.c:
* gst/gstobject.c: (gst_object_class_init), (gst_object_ref),
(gst_object_unref), (gst_object_sink), (gst_object_dispose),
(gst_object_dispatch_properties_changed), (gst_object_set_name),
(gst_object_set_parent), (gst_object_unparent),
(gst_object_check_uniqueness):
* gst/gstobject.h:
Docs updates, clean up some headers.
Free iterators in GstBin.
GstObject is now looking good.
2005-03-08 14:38:06 +00:00
|
|
|
{
|
|
|
|
g_warning ("Element %s already has parent", elem_name);
|
|
|
|
GST_UNLOCK (bin);
|
|
|
|
g_free (elem_name);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2000-01-30 09:03:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2003-01-11 20:08:03 +00:00
|
|
|
* gst_bin_add:
|
|
|
|
* @bin: #GstBin to add element to
|
|
|
|
* @element: #GstElement to add to bin
|
2000-01-30 09:03:00 +00:00
|
|
|
*
|
2004-03-26 03:46:16 +00:00
|
|
|
* Adds the given element to the bin. Sets the element's parent, and thus
|
2004-10-13 13:03:25 +00:00
|
|
|
* takes ownership of the element. An element can only be added to one bin.
|
2005-03-07 18:27:42 +00:00
|
|
|
*
|
2005-06-27 08:16:51 +00:00
|
|
|
* MT safe.
|
|
|
|
*
|
2005-03-07 18:27:42 +00:00
|
|
|
* Returns: TRUE if the element could be added, FALSE on wrong parameters or
|
|
|
|
* the bin does not want to accept the element.
|
2000-01-30 09:03:00 +00:00
|
|
|
*/
|
2005-03-07 18:27:42 +00:00
|
|
|
gboolean
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_bin_add (GstBin * bin, GstElement * element)
|
2000-11-04 18:54:07 +00:00
|
|
|
{
|
2003-01-11 20:08:03 +00:00
|
|
|
GstBinClass *bclass;
|
2005-03-07 18:27:42 +00:00
|
|
|
gboolean result;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
|
|
|
|
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
|
2003-01-11 20:08:03 +00:00
|
|
|
|
|
|
|
bclass = GST_BIN_GET_CLASS (bin);
|
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
if (G_UNLIKELY (bclass->add_element == NULL))
|
|
|
|
goto no_function;
|
|
|
|
|
|
|
|
GST_CAT_DEBUG (GST_CAT_PARENTAGE, "adding element %s to bin %s",
|
|
|
|
GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin));
|
|
|
|
|
|
|
|
result = bclass->add_element (bin, element);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
Docs updates, clean up some headers.
Original commit message from CVS:
* docs/design/part-MT-refcounting.txt:
* docs/design/part-conventions.txt:
* docs/design/part-gstobject.txt:
* docs/design/part-relations.txt:
* docs/design/part-standards.txt:
* gst/gstbin.c: (gst_bin_add_func), (gst_bin_add),
(gst_bin_remove_func), (gst_bin_remove), (gst_bin_iterate_recurse),
(gst_bin_get_by_name), (gst_bin_get_by_interface),
(gst_bin_iterate_all_by_interface):
* gst/gstbuffer.h:
* gst/gstclock.h:
* gst/gstelement.c: (gst_element_class_init),
(gst_element_change_state), (gst_element_set_loop_function):
* gst/gstelement.h:
* gst/gstiterator.c:
* gst/gstobject.c: (gst_object_class_init), (gst_object_ref),
(gst_object_unref), (gst_object_sink), (gst_object_dispose),
(gst_object_dispatch_properties_changed), (gst_object_set_name),
(gst_object_set_parent), (gst_object_unparent),
(gst_object_check_uniqueness):
* gst/gstobject.h:
Docs updates, clean up some headers.
Free iterators in GstBin.
GstObject is now looking good.
2005-03-08 14:38:06 +00:00
|
|
|
/* ERROR handling */
|
2005-03-07 18:27:42 +00:00
|
|
|
no_function:
|
Docs updates, clean up some headers.
Original commit message from CVS:
* docs/design/part-MT-refcounting.txt:
* docs/design/part-conventions.txt:
* docs/design/part-gstobject.txt:
* docs/design/part-relations.txt:
* docs/design/part-standards.txt:
* gst/gstbin.c: (gst_bin_add_func), (gst_bin_add),
(gst_bin_remove_func), (gst_bin_remove), (gst_bin_iterate_recurse),
(gst_bin_get_by_name), (gst_bin_get_by_interface),
(gst_bin_iterate_all_by_interface):
* gst/gstbuffer.h:
* gst/gstclock.h:
* gst/gstelement.c: (gst_element_class_init),
(gst_element_change_state), (gst_element_set_loop_function):
* gst/gstelement.h:
* gst/gstiterator.c:
* gst/gstobject.c: (gst_object_class_init), (gst_object_ref),
(gst_object_unref), (gst_object_sink), (gst_object_dispose),
(gst_object_dispatch_properties_changed), (gst_object_set_name),
(gst_object_set_parent), (gst_object_unparent),
(gst_object_check_uniqueness):
* gst/gstobject.h:
Docs updates, clean up some headers.
Free iterators in GstBin.
GstObject is now looking good.
2005-03-08 14:38:06 +00:00
|
|
|
{
|
|
|
|
g_warning ("adding elements to bin %s is not supported",
|
|
|
|
GST_ELEMENT_NAME (bin));
|
|
|
|
return FALSE;
|
|
|
|
}
|
2003-01-11 20:08:03 +00:00
|
|
|
}
|
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
/* remove an element from the bin
|
|
|
|
*
|
|
|
|
* MT safe
|
|
|
|
*/
|
|
|
|
static gboolean
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_bin_remove_func (GstBin * bin, GstElement * element)
|
2003-01-11 20:08:03 +00:00
|
|
|
{
|
2005-03-07 18:27:42 +00:00
|
|
|
gchar *elem_name;
|
2003-01-11 20:08:03 +00:00
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
/* grab element name so we can print it */
|
|
|
|
GST_LOCK (element);
|
|
|
|
elem_name = g_strdup (GST_ELEMENT_NAME (element));
|
|
|
|
GST_UNLOCK (element);
|
2001-05-25 21:00:07 +00:00
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
GST_LOCK (bin);
|
2001-12-14 22:59:21 +00:00
|
|
|
/* the element must be in the bin's list of children */
|
2005-03-07 18:27:42 +00:00
|
|
|
if (G_UNLIKELY (g_list_find (bin->children, element) == NULL))
|
|
|
|
goto not_in_bin;
|
2005-01-31 23:21:52 +00:00
|
|
|
|
2001-12-14 22:59:21 +00:00
|
|
|
/* now remove the element from the list of elements */
|
2000-11-04 18:54:07 +00:00
|
|
|
bin->children = g_list_remove (bin->children, element);
|
2000-01-30 09:03:00 +00:00
|
|
|
bin->numchildren--;
|
2005-03-07 18:27:42 +00:00
|
|
|
bin->children_cookie++;
|
2005-05-12 19:45:44 +00:00
|
|
|
|
|
|
|
/* check if we a sink */
|
|
|
|
if (GST_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK)) {
|
|
|
|
GList *other_sink;
|
|
|
|
|
|
|
|
/* check if we removed the last sink */
|
|
|
|
other_sink = g_list_find_custom (bin->children,
|
|
|
|
bin, (GCompareFunc) bin_element_is_sink);
|
|
|
|
if (!other_sink) {
|
|
|
|
/* yups, we're not a sink anymore */
|
|
|
|
GST_FLAG_UNSET (bin, GST_ELEMENT_IS_SINK);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
GST_UNLOCK (bin);
|
2001-12-10 18:08:35 +00:00
|
|
|
|
2004-07-29 20:33:49 +00:00
|
|
|
GST_CAT_INFO_OBJECT (GST_CAT_PARENTAGE, bin, "removed child \"%s\"",
|
2005-03-07 18:27:42 +00:00
|
|
|
elem_name);
|
|
|
|
g_free (elem_name);
|
|
|
|
|
2005-03-21 17:34:02 +00:00
|
|
|
gst_element_set_manager (element, NULL);
|
|
|
|
gst_element_set_bus (element, NULL);
|
2005-03-07 18:27:42 +00:00
|
|
|
gst_element_set_scheduler (element, NULL);
|
2000-12-30 02:41:15 +00:00
|
|
|
|
2005-05-12 13:18:14 +00:00
|
|
|
/* unlock any waiters for the state change. It is possible that
|
|
|
|
* we are waiting for an ASYNC state change on this element. The
|
|
|
|
* element cannot be added to another bin yet as it is not yet
|
|
|
|
* unparented. */
|
|
|
|
GST_STATE_LOCK (element);
|
|
|
|
GST_STATE_BROADCAST (element);
|
|
|
|
GST_STATE_UNLOCK (element);
|
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
/* we ref here because after the _unparent() the element can be disposed
|
|
|
|
* and we still need it to fire a signal. */
|
2005-03-10 12:51:45 +00:00
|
|
|
gst_object_ref (GST_OBJECT_CAST (element));
|
|
|
|
gst_object_unparent (GST_OBJECT_CAST (element));
|
2001-05-25 21:00:07 +00:00
|
|
|
|
2002-12-19 21:31:03 +00:00
|
|
|
g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_REMOVED], 0, element);
|
|
|
|
/* element is really out of our control now */
|
2005-03-10 12:51:45 +00:00
|
|
|
gst_object_unref (GST_OBJECT_CAST (element));
|
2005-03-07 18:27:42 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
Docs updates, clean up some headers.
Original commit message from CVS:
* docs/design/part-MT-refcounting.txt:
* docs/design/part-conventions.txt:
* docs/design/part-gstobject.txt:
* docs/design/part-relations.txt:
* docs/design/part-standards.txt:
* gst/gstbin.c: (gst_bin_add_func), (gst_bin_add),
(gst_bin_remove_func), (gst_bin_remove), (gst_bin_iterate_recurse),
(gst_bin_get_by_name), (gst_bin_get_by_interface),
(gst_bin_iterate_all_by_interface):
* gst/gstbuffer.h:
* gst/gstclock.h:
* gst/gstelement.c: (gst_element_class_init),
(gst_element_change_state), (gst_element_set_loop_function):
* gst/gstelement.h:
* gst/gstiterator.c:
* gst/gstobject.c: (gst_object_class_init), (gst_object_ref),
(gst_object_unref), (gst_object_sink), (gst_object_dispose),
(gst_object_dispatch_properties_changed), (gst_object_set_name),
(gst_object_set_parent), (gst_object_unparent),
(gst_object_check_uniqueness):
* gst/gstobject.h:
Docs updates, clean up some headers.
Free iterators in GstBin.
GstObject is now looking good.
2005-03-08 14:38:06 +00:00
|
|
|
/* ERROR handling */
|
2005-03-07 18:27:42 +00:00
|
|
|
not_in_bin:
|
Docs updates, clean up some headers.
Original commit message from CVS:
* docs/design/part-MT-refcounting.txt:
* docs/design/part-conventions.txt:
* docs/design/part-gstobject.txt:
* docs/design/part-relations.txt:
* docs/design/part-standards.txt:
* gst/gstbin.c: (gst_bin_add_func), (gst_bin_add),
(gst_bin_remove_func), (gst_bin_remove), (gst_bin_iterate_recurse),
(gst_bin_get_by_name), (gst_bin_get_by_interface),
(gst_bin_iterate_all_by_interface):
* gst/gstbuffer.h:
* gst/gstclock.h:
* gst/gstelement.c: (gst_element_class_init),
(gst_element_change_state), (gst_element_set_loop_function):
* gst/gstelement.h:
* gst/gstiterator.c:
* gst/gstobject.c: (gst_object_class_init), (gst_object_ref),
(gst_object_unref), (gst_object_sink), (gst_object_dispose),
(gst_object_dispatch_properties_changed), (gst_object_set_name),
(gst_object_set_parent), (gst_object_unparent),
(gst_object_check_uniqueness):
* gst/gstobject.h:
Docs updates, clean up some headers.
Free iterators in GstBin.
GstObject is now looking good.
2005-03-08 14:38:06 +00:00
|
|
|
{
|
|
|
|
g_warning ("Element %s is not in bin %s", elem_name,
|
|
|
|
GST_ELEMENT_NAME (bin));
|
|
|
|
GST_UNLOCK (bin);
|
|
|
|
g_free (elem_name);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2000-01-30 09:03:00 +00:00
|
|
|
}
|
|
|
|
|
2003-01-11 20:08:03 +00:00
|
|
|
/**
|
|
|
|
* gst_bin_remove:
|
|
|
|
* @bin: #GstBin to remove element from
|
|
|
|
* @element: #GstElement to remove
|
|
|
|
*
|
2004-03-26 03:46:16 +00:00
|
|
|
* Remove the element from its associated bin, unparenting it as well.
|
|
|
|
* Unparenting the element means that the element will be dereferenced,
|
|
|
|
* so if the bin holds the only reference to the element, the element
|
|
|
|
* will be freed in the process of removing it from the bin. If you
|
|
|
|
* want the element to still exist after removing, you need to call
|
2003-01-11 20:08:03 +00:00
|
|
|
* #gst_object_ref before removing it from the bin.
|
2005-03-07 18:27:42 +00:00
|
|
|
*
|
2005-06-27 08:16:51 +00:00
|
|
|
* MT safe.
|
|
|
|
*
|
2005-03-07 18:27:42 +00:00
|
|
|
* Returns: TRUE if the element could be removed, FALSE on wrong parameters or
|
|
|
|
* the bin does not want to remove the element.
|
2003-01-11 20:08:03 +00:00
|
|
|
*/
|
2005-03-07 18:27:42 +00:00
|
|
|
gboolean
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_bin_remove (GstBin * bin, GstElement * element)
|
2003-01-11 20:08:03 +00:00
|
|
|
{
|
|
|
|
GstBinClass *bclass;
|
2005-03-07 18:27:42 +00:00
|
|
|
gboolean result;
|
2003-01-11 20:08:03 +00:00
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
|
|
|
|
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
|
2003-01-11 20:08:03 +00:00
|
|
|
|
|
|
|
bclass = GST_BIN_GET_CLASS (bin);
|
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
if (G_UNLIKELY (bclass->remove_element == NULL))
|
|
|
|
goto no_function;
|
|
|
|
|
|
|
|
GST_CAT_DEBUG (GST_CAT_PARENTAGE, "removing element %s from bin %s",
|
|
|
|
GST_ELEMENT_NAME (element), GST_ELEMENT_NAME (bin));
|
|
|
|
|
|
|
|
result = bclass->remove_element (bin, element);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
Docs updates, clean up some headers.
Original commit message from CVS:
* docs/design/part-MT-refcounting.txt:
* docs/design/part-conventions.txt:
* docs/design/part-gstobject.txt:
* docs/design/part-relations.txt:
* docs/design/part-standards.txt:
* gst/gstbin.c: (gst_bin_add_func), (gst_bin_add),
(gst_bin_remove_func), (gst_bin_remove), (gst_bin_iterate_recurse),
(gst_bin_get_by_name), (gst_bin_get_by_interface),
(gst_bin_iterate_all_by_interface):
* gst/gstbuffer.h:
* gst/gstclock.h:
* gst/gstelement.c: (gst_element_class_init),
(gst_element_change_state), (gst_element_set_loop_function):
* gst/gstelement.h:
* gst/gstiterator.c:
* gst/gstobject.c: (gst_object_class_init), (gst_object_ref),
(gst_object_unref), (gst_object_sink), (gst_object_dispose),
(gst_object_dispatch_properties_changed), (gst_object_set_name),
(gst_object_set_parent), (gst_object_unparent),
(gst_object_check_uniqueness):
* gst/gstobject.h:
Docs updates, clean up some headers.
Free iterators in GstBin.
GstObject is now looking good.
2005-03-08 14:38:06 +00:00
|
|
|
/* ERROR handling */
|
2005-03-07 18:27:42 +00:00
|
|
|
no_function:
|
Docs updates, clean up some headers.
Original commit message from CVS:
* docs/design/part-MT-refcounting.txt:
* docs/design/part-conventions.txt:
* docs/design/part-gstobject.txt:
* docs/design/part-relations.txt:
* docs/design/part-standards.txt:
* gst/gstbin.c: (gst_bin_add_func), (gst_bin_add),
(gst_bin_remove_func), (gst_bin_remove), (gst_bin_iterate_recurse),
(gst_bin_get_by_name), (gst_bin_get_by_interface),
(gst_bin_iterate_all_by_interface):
* gst/gstbuffer.h:
* gst/gstclock.h:
* gst/gstelement.c: (gst_element_class_init),
(gst_element_change_state), (gst_element_set_loop_function):
* gst/gstelement.h:
* gst/gstiterator.c:
* gst/gstobject.c: (gst_object_class_init), (gst_object_ref),
(gst_object_unref), (gst_object_sink), (gst_object_dispose),
(gst_object_dispatch_properties_changed), (gst_object_set_name),
(gst_object_set_parent), (gst_object_unparent),
(gst_object_check_uniqueness):
* gst/gstobject.h:
Docs updates, clean up some headers.
Free iterators in GstBin.
GstObject is now looking good.
2005-03-08 14:38:06 +00:00
|
|
|
{
|
|
|
|
g_warning ("removing elements from bin %s is not supported",
|
|
|
|
GST_ELEMENT_NAME (bin));
|
|
|
|
return FALSE;
|
|
|
|
}
|
2005-03-07 18:27:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static GstIteratorItem
|
|
|
|
iterate_child (GstIterator * it, GstElement * child)
|
|
|
|
{
|
|
|
|
gst_object_ref (GST_OBJECT (child));
|
|
|
|
return GST_ITERATOR_ITEM_PASS;
|
2003-01-11 20:08:03 +00:00
|
|
|
}
|
|
|
|
|
2003-02-11 20:15:50 +00:00
|
|
|
/**
|
2005-03-07 18:27:42 +00:00
|
|
|
* gst_bin_iterate_elements:
|
|
|
|
* @bin: #Gstbin to iterate the elements of
|
|
|
|
*
|
2005-06-27 08:16:51 +00:00
|
|
|
* Get an iterator for the elements in this bin.
|
|
|
|
* Each element will have its refcount increased, so unref
|
|
|
|
* after use.
|
|
|
|
*
|
|
|
|
* MT safe.
|
2005-03-07 18:27:42 +00:00
|
|
|
*
|
|
|
|
* Returns: a #GstIterator of #GstElements. gst_iterator_free after
|
|
|
|
* use. returns NULL when passing bad parameters.
|
2003-02-11 20:15:50 +00:00
|
|
|
*/
|
2005-03-07 18:27:42 +00:00
|
|
|
GstIterator *
|
|
|
|
gst_bin_iterate_elements (GstBin * bin)
|
2003-02-11 20:15:50 +00:00
|
|
|
{
|
2005-03-07 18:27:42 +00:00
|
|
|
GstIterator *result;
|
2003-02-11 20:15:50 +00:00
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
g_return_val_if_fail (GST_IS_BIN (bin), NULL);
|
|
|
|
|
|
|
|
GST_LOCK (bin);
|
|
|
|
/* add ref because the iterator refs the bin. When the iterator
|
2005-06-27 08:16:51 +00:00
|
|
|
* is freed it will unref the bin again using the provided dispose
|
2005-03-07 18:27:42 +00:00
|
|
|
* function. */
|
|
|
|
gst_object_ref (GST_OBJECT (bin));
|
|
|
|
result = gst_iterator_new_list (GST_GET_LOCK (bin),
|
|
|
|
&bin->children_cookie,
|
|
|
|
&bin->children,
|
|
|
|
bin,
|
|
|
|
(GstIteratorItemFunction) iterate_child,
|
|
|
|
(GstIteratorDisposeFunction) gst_object_unref);
|
|
|
|
GST_UNLOCK (bin);
|
2003-02-11 20:15:50 +00:00
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
return result;
|
|
|
|
}
|
2003-02-11 20:15:50 +00:00
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
static GstIteratorItem
|
|
|
|
iterate_child_recurse (GstIterator * it, GstElement * child)
|
|
|
|
{
|
|
|
|
gst_object_ref (GST_OBJECT (child));
|
|
|
|
if (GST_IS_BIN (child)) {
|
|
|
|
GstIterator *other = gst_bin_iterate_recurse (GST_BIN (child));
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
gst_iterator_push (it, other);
|
2003-02-11 20:15:50 +00:00
|
|
|
}
|
2005-03-07 18:27:42 +00:00
|
|
|
return GST_ITERATOR_ITEM_PASS;
|
|
|
|
}
|
2003-02-11 20:15:50 +00:00
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
/**
|
|
|
|
* gst_bin_iterate_recurse:
|
|
|
|
* @bin: #Gstbin to iterate the elements of
|
|
|
|
*
|
2005-06-27 08:16:51 +00:00
|
|
|
* Get an iterator for the elements in this bin.
|
|
|
|
* Each element will have its refcount increased, so unref
|
|
|
|
* after use. This iterator recurses into GstBin children.
|
|
|
|
*
|
|
|
|
* MT safe.
|
2005-03-07 18:27:42 +00:00
|
|
|
*
|
|
|
|
* Returns: a #GstIterator of #GstElements. gst_iterator_free after
|
|
|
|
* use. returns NULL when passing bad parameters.
|
|
|
|
*/
|
|
|
|
GstIterator *
|
|
|
|
gst_bin_iterate_recurse (GstBin * bin)
|
|
|
|
{
|
|
|
|
GstIterator *result;
|
|
|
|
|
|
|
|
g_return_val_if_fail (GST_IS_BIN (bin), NULL);
|
|
|
|
|
|
|
|
GST_LOCK (bin);
|
|
|
|
/* add ref because the iterator refs the bin. When the iterator
|
2005-06-27 08:16:51 +00:00
|
|
|
* is freed it will unref the bin again using the provided dispose
|
2005-03-07 18:27:42 +00:00
|
|
|
* function. */
|
|
|
|
gst_object_ref (GST_OBJECT (bin));
|
|
|
|
result = gst_iterator_new_list (GST_GET_LOCK (bin),
|
|
|
|
&bin->children_cookie,
|
|
|
|
&bin->children,
|
|
|
|
bin,
|
|
|
|
(GstIteratorItemFunction) iterate_child_recurse,
|
|
|
|
(GstIteratorDisposeFunction) gst_object_unref);
|
|
|
|
GST_UNLOCK (bin);
|
|
|
|
|
|
|
|
return result;
|
2003-02-11 20:15:50 +00:00
|
|
|
}
|
|
|
|
|
gst/: Fix state changes for non sinks. We now change sinks, then elements with unconnected srcpads, then the rest.
Original commit message from CVS:
* gst/gstbin.c: (bin_element_is_sink), (has_ancestor),
(bin_element_is_semi_sink), (append_child), (gst_bin_change_state):
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare),
(gst_pad_link), (gst_pad_accept_caps), (gst_pad_query),
(gst_pad_send_event), (gst_pad_start_task):
* gst/gstqueue.c: (gst_queue_init), (gst_queue_locked_flush),
(gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop),
(gst_queue_sink_activate), (gst_queue_src_activate),
(gst_queue_change_state):
* gst/gstqueue.h:
Fix state changes for non sinks. We now change sinks, then elements
with unconnected srcpads, then the rest.
More efficient queue unlocking in flush and state changes.
Set the pad activate mode even if it does not have an activate
function.
2005-05-25 19:33:39 +00:00
|
|
|
/* returns 0 when TRUE because this is a GCompareFunc */
|
2005-05-14 18:01:12 +00:00
|
|
|
/* MT safe */
|
2005-03-09 16:10:59 +00:00
|
|
|
static gint
|
|
|
|
bin_element_is_sink (GstElement * child, GstBin * bin)
|
|
|
|
{
|
gst/: Fix state changes for non sinks. We now change sinks, then elements with unconnected srcpads, then the rest.
Original commit message from CVS:
* gst/gstbin.c: (bin_element_is_sink), (has_ancestor),
(bin_element_is_semi_sink), (append_child), (gst_bin_change_state):
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare),
(gst_pad_link), (gst_pad_accept_caps), (gst_pad_query),
(gst_pad_send_event), (gst_pad_start_task):
* gst/gstqueue.c: (gst_queue_init), (gst_queue_locked_flush),
(gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop),
(gst_queue_sink_activate), (gst_queue_src_activate),
(gst_queue_change_state):
* gst/gstqueue.h:
Fix state changes for non sinks. We now change sinks, then elements
with unconnected srcpads, then the rest.
More efficient queue unlocking in flush and state changes.
Set the pad activate mode even if it does not have an activate
function.
2005-05-25 19:33:39 +00:00
|
|
|
gboolean is_sink;
|
|
|
|
|
2005-03-09 16:10:59 +00:00
|
|
|
/* we lock the child here for the remainder of the function to
|
2005-05-12 19:45:44 +00:00
|
|
|
* get its name safely. */
|
2005-03-09 16:10:59 +00:00
|
|
|
GST_LOCK (child);
|
gst/: Fix state changes for non sinks. We now change sinks, then elements with unconnected srcpads, then the rest.
Original commit message from CVS:
* gst/gstbin.c: (bin_element_is_sink), (has_ancestor),
(bin_element_is_semi_sink), (append_child), (gst_bin_change_state):
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare),
(gst_pad_link), (gst_pad_accept_caps), (gst_pad_query),
(gst_pad_send_event), (gst_pad_start_task):
* gst/gstqueue.c: (gst_queue_init), (gst_queue_locked_flush),
(gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop),
(gst_queue_sink_activate), (gst_queue_src_activate),
(gst_queue_change_state):
* gst/gstqueue.h:
Fix state changes for non sinks. We now change sinks, then elements
with unconnected srcpads, then the rest.
More efficient queue unlocking in flush and state changes.
Set the pad activate mode even if it does not have an activate
function.
2005-05-25 19:33:39 +00:00
|
|
|
is_sink = GST_FLAG_IS_SET (child, GST_ELEMENT_IS_SINK);
|
|
|
|
GST_UNLOCK (child);
|
|
|
|
|
|
|
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
|
|
|
|
"child %s %s sink", GST_OBJECT_NAME (child), is_sink ? "is" : "is not");
|
|
|
|
|
|
|
|
return is_sink ? 0 : 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
has_ancestor (GstObject * object, GstObject * ancestor)
|
|
|
|
{
|
|
|
|
GstObject *parent;
|
|
|
|
gboolean result = FALSE;
|
|
|
|
|
|
|
|
if (object == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (object == ancestor)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
parent = gst_object_get_parent (object);
|
|
|
|
result = has_ancestor (parent, ancestor);
|
|
|
|
if (parent)
|
|
|
|
gst_object_unref (GST_OBJECT_CAST (parent));
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* returns 0 when TRUE because this is a GCompareFunc.
|
|
|
|
* This function returns elements that have no connected srcpads and
|
|
|
|
* are therefore not reachable from a real sink. */
|
|
|
|
/* MT safe */
|
|
|
|
static gint
|
|
|
|
bin_element_is_semi_sink (GstElement * child, GstBin * bin)
|
|
|
|
{
|
|
|
|
int ret = 1;
|
|
|
|
|
|
|
|
/* we lock the child here for the remainder of the function to
|
|
|
|
* get its pads and name safely. */
|
|
|
|
GST_LOCK (child);
|
|
|
|
|
|
|
|
/* check if this is a sink element, these are the elements
|
|
|
|
* without (linked) source pads. */
|
|
|
|
if (child->numsrcpads == 0) {
|
|
|
|
/* shortcut */
|
2005-03-09 16:10:59 +00:00
|
|
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
|
gst/: Fix state changes for non sinks. We now change sinks, then elements with unconnected srcpads, then the rest.
Original commit message from CVS:
* gst/gstbin.c: (bin_element_is_sink), (has_ancestor),
(bin_element_is_semi_sink), (append_child), (gst_bin_change_state):
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare),
(gst_pad_link), (gst_pad_accept_caps), (gst_pad_query),
(gst_pad_send_event), (gst_pad_start_task):
* gst/gstqueue.c: (gst_queue_init), (gst_queue_locked_flush),
(gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop),
(gst_queue_sink_activate), (gst_queue_src_activate),
(gst_queue_change_state):
* gst/gstqueue.h:
Fix state changes for non sinks. We now change sinks, then elements
with unconnected srcpads, then the rest.
More efficient queue unlocking in flush and state changes.
Set the pad activate mode even if it does not have an activate
function.
2005-05-25 19:33:39 +00:00
|
|
|
"adding child %s as sink", GST_OBJECT_NAME (child));
|
|
|
|
ret = 0;
|
2005-03-09 16:10:59 +00:00
|
|
|
} else {
|
gst/: Fix state changes for non sinks. We now change sinks, then elements with unconnected srcpads, then the rest.
Original commit message from CVS:
* gst/gstbin.c: (bin_element_is_sink), (has_ancestor),
(bin_element_is_semi_sink), (append_child), (gst_bin_change_state):
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare),
(gst_pad_link), (gst_pad_accept_caps), (gst_pad_query),
(gst_pad_send_event), (gst_pad_start_task):
* gst/gstqueue.c: (gst_queue_init), (gst_queue_locked_flush),
(gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop),
(gst_queue_sink_activate), (gst_queue_src_activate),
(gst_queue_change_state):
* gst/gstqueue.h:
Fix state changes for non sinks. We now change sinks, then elements
with unconnected srcpads, then the rest.
More efficient queue unlocking in flush and state changes.
Set the pad activate mode even if it does not have an activate
function.
2005-05-25 19:33:39 +00:00
|
|
|
/* loop over all pads, try to figure out if this element
|
|
|
|
* is a semi sink because it has no linked source pads */
|
|
|
|
GList *pads;
|
|
|
|
gboolean connected_src = FALSE;
|
|
|
|
|
|
|
|
for (pads = child->srcpads; pads; pads = g_list_next (pads)) {
|
|
|
|
GstPad *peer;
|
|
|
|
|
|
|
|
if ((peer = gst_pad_get_peer (GST_PAD_CAST (pads->data)))) {
|
|
|
|
connected_src =
|
|
|
|
has_ancestor (GST_OBJECT_CAST (peer), GST_OBJECT_CAST (bin));
|
|
|
|
gst_object_unref (GST_OBJECT_CAST (peer));
|
|
|
|
if (connected_src) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (connected_src) {
|
|
|
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
|
|
|
|
"not adding child %s as sink: linked source pads",
|
|
|
|
GST_OBJECT_NAME (child));
|
|
|
|
} else {
|
|
|
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
|
|
|
|
"adding child %s as sink since it has unlinked source pads in this bin",
|
|
|
|
GST_OBJECT_NAME (child));
|
|
|
|
ret = 0;
|
|
|
|
}
|
2005-05-14 18:01:12 +00:00
|
|
|
}
|
gst/: Fix state changes for non sinks. We now change sinks, then elements with unconnected srcpads, then the rest.
Original commit message from CVS:
* gst/gstbin.c: (bin_element_is_sink), (has_ancestor),
(bin_element_is_semi_sink), (append_child), (gst_bin_change_state):
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare),
(gst_pad_link), (gst_pad_accept_caps), (gst_pad_query),
(gst_pad_send_event), (gst_pad_start_task):
* gst/gstqueue.c: (gst_queue_init), (gst_queue_locked_flush),
(gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop),
(gst_queue_sink_activate), (gst_queue_src_activate),
(gst_queue_change_state):
* gst/gstqueue.h:
Fix state changes for non sinks. We now change sinks, then elements
with unconnected srcpads, then the rest.
More efficient queue unlocking in flush and state changes.
Set the pad activate mode even if it does not have an activate
function.
2005-05-25 19:33:39 +00:00
|
|
|
GST_UNLOCK (child);
|
|
|
|
|
|
|
|
return ret;
|
2005-05-14 18:01:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
|
|
|
sink_iterator_filter (GstElement * child, GstBin * bin)
|
|
|
|
{
|
2005-05-16 21:17:14 +00:00
|
|
|
if (bin_element_is_sink (child, bin) == 0) {
|
2005-05-14 18:01:12 +00:00
|
|
|
/* returns 0 because this is a GCompareFunc */
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
/* child carries a ref from gst_bin_iterate_elements -- drop if not passing
|
|
|
|
through */
|
|
|
|
gst_object_unref ((GstObject *) child);
|
|
|
|
return 1;
|
2005-03-09 16:10:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_bin_iterate_sinks:
|
|
|
|
* @bin: #Gstbin to iterate on
|
|
|
|
*
|
|
|
|
* Get an iterator for the sink elements in this bin.
|
2005-06-27 08:16:51 +00:00
|
|
|
* Each element will have its refcount increased, so unref
|
|
|
|
* after use.
|
2005-03-09 16:10:59 +00:00
|
|
|
*
|
2005-03-10 12:51:45 +00:00
|
|
|
* The sink elements are those without any linked srcpads.
|
|
|
|
*
|
2005-03-09 16:10:59 +00:00
|
|
|
* MT safe.
|
2005-06-27 08:16:51 +00:00
|
|
|
*
|
|
|
|
* Returns: a #GstIterator of #GstElements. gst_iterator_free after use.
|
2005-03-09 16:10:59 +00:00
|
|
|
*/
|
|
|
|
GstIterator *
|
|
|
|
gst_bin_iterate_sinks (GstBin * bin)
|
|
|
|
{
|
|
|
|
GstIterator *children;
|
|
|
|
GstIterator *result;
|
|
|
|
|
|
|
|
g_return_val_if_fail (GST_IS_BIN (bin), NULL);
|
|
|
|
|
|
|
|
children = gst_bin_iterate_elements (bin);
|
|
|
|
result = gst_iterator_filter (children,
|
2005-05-14 18:01:12 +00:00
|
|
|
(GCompareFunc) sink_iterator_filter, bin);
|
2005-03-09 16:10:59 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2005-06-23 10:37:09 +00:00
|
|
|
/* 2 phases:
|
|
|
|
* 1) check state of all children with 0 timeout to find ERROR and
|
|
|
|
* NO_PREROLL elements. return if found.
|
|
|
|
* 2) perform full blocking wait with requested timeout.
|
2005-06-27 08:16:51 +00:00
|
|
|
*
|
2005-06-23 10:37:09 +00:00
|
|
|
* 2) cannot be performed when 1) returns results as the sinks might
|
|
|
|
* not be able to complete the state change making 2) block forever.
|
2005-03-10 12:51:45 +00:00
|
|
|
*
|
2005-03-21 17:34:02 +00:00
|
|
|
* MT safe
|
2002-01-01 15:58:51 +00:00
|
|
|
*/
|
2005-03-21 17:34:02 +00:00
|
|
|
static GstElementStateReturn
|
|
|
|
gst_bin_get_state (GstElement * element, GstElementState * state,
|
|
|
|
GstElementState * pending, GTimeVal * timeout)
|
2003-04-18 23:34:21 +00:00
|
|
|
{
|
2005-03-28 14:54:33 +00:00
|
|
|
GstBin *bin = GST_BIN (element);
|
2005-06-23 10:37:09 +00:00
|
|
|
GstElementStateReturn ret = GST_STATE_SUCCESS;
|
2005-03-28 14:54:33 +00:00
|
|
|
GList *children;
|
|
|
|
guint32 children_cookie;
|
2005-06-23 10:37:09 +00:00
|
|
|
gboolean zero_timeout;
|
2005-06-27 18:11:24 +00:00
|
|
|
gboolean have_no_preroll;
|
2005-06-23 10:37:09 +00:00
|
|
|
|
|
|
|
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "getting state");
|
2005-03-28 14:54:33 +00:00
|
|
|
|
2005-06-23 10:37:09 +00:00
|
|
|
zero_timeout = timeout != NULL && timeout->tv_sec == 0
|
|
|
|
&& timeout->tv_usec == 0;
|
|
|
|
|
2005-06-27 18:11:24 +00:00
|
|
|
/* lock bin, no element can be added or removed between going into
|
|
|
|
* the quick scan and the blocking wait. */
|
|
|
|
GST_LOCK (bin);
|
|
|
|
|
|
|
|
restart:
|
|
|
|
have_no_preroll = FALSE;
|
|
|
|
|
2005-06-23 10:37:09 +00:00
|
|
|
/* if we have a non zero timeout we must make sure not to block
|
|
|
|
* on the sinks when we have NO_PREROLL elements. This is why we do
|
|
|
|
* a quick check if there are still NO_PREROLL elements. We also
|
|
|
|
* catch the error elements this way. */
|
|
|
|
if (!zero_timeout) {
|
|
|
|
GTimeVal tv;
|
|
|
|
gboolean have_async = FALSE;
|
|
|
|
|
|
|
|
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "checking for NO_PREROLL");
|
|
|
|
/* use 0 timeout so we don't block on the sinks */
|
|
|
|
GST_TIME_TO_TIMEVAL (0, tv);
|
|
|
|
children = bin->children;
|
2005-06-27 18:11:24 +00:00
|
|
|
children_cookie = bin->children_cookie;
|
2005-06-23 10:37:09 +00:00
|
|
|
while (children) {
|
|
|
|
GstElement *child = GST_ELEMENT_CAST (children->data);
|
|
|
|
|
2005-06-27 18:11:24 +00:00
|
|
|
gst_object_ref (GST_OBJECT_CAST (child));
|
|
|
|
/* now we release the lock to enter a non blocking wait. We
|
|
|
|
* release the lock anyway since we can. */
|
|
|
|
GST_UNLOCK (bin);
|
|
|
|
|
2005-06-23 10:37:09 +00:00
|
|
|
ret = gst_element_get_state (child, NULL, NULL, &tv);
|
2005-06-27 18:11:24 +00:00
|
|
|
|
|
|
|
gst_object_unref (GST_OBJECT_CAST (child));
|
|
|
|
|
|
|
|
/* now grab the lock to iterate to the next child */
|
|
|
|
GST_LOCK (bin);
|
|
|
|
if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
|
|
|
|
/* child added/removed during state change, restart. We need
|
|
|
|
* to restart with the quick check as a no-preroll element could
|
|
|
|
* have been added here and we don't want to block on sinks then.*/
|
|
|
|
goto restart;
|
|
|
|
}
|
|
|
|
|
2005-06-23 10:37:09 +00:00
|
|
|
switch (ret) {
|
|
|
|
/* report FAILURE or NO_PREROLL immediatly */
|
|
|
|
case GST_STATE_FAILURE:
|
2005-06-27 18:11:24 +00:00
|
|
|
goto done;
|
2005-06-23 10:37:09 +00:00
|
|
|
case GST_STATE_NO_PREROLL:
|
|
|
|
/* we have to continue scanning as there might be
|
|
|
|
* ERRORS too */
|
|
|
|
have_no_preroll = TRUE;
|
|
|
|
break;
|
|
|
|
case GST_STATE_ASYNC:
|
|
|
|
have_async = TRUE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
children = g_list_next (children);
|
|
|
|
}
|
|
|
|
/* if we get here, we have no FAILURES, check for any NO_PREROLL
|
|
|
|
* elements then. */
|
2005-06-27 18:11:24 +00:00
|
|
|
if (have_no_preroll) {
|
|
|
|
ret = GST_STATE_NO_PREROLL;
|
|
|
|
goto done;
|
|
|
|
}
|
2005-06-23 10:37:09 +00:00
|
|
|
|
|
|
|
/* if we get here, no NO_PREROLL elements are in the pipeline */
|
|
|
|
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "no NO_PREROLL elements");
|
|
|
|
|
|
|
|
/* if no ASYNC elements exist we don't even have to poll with a
|
|
|
|
* timeout again */
|
2005-06-27 18:11:24 +00:00
|
|
|
if (!have_async) {
|
|
|
|
ret = GST_STATE_SUCCESS;
|
|
|
|
goto done;
|
|
|
|
}
|
2005-06-23 10:37:09 +00:00
|
|
|
}
|
2005-03-28 14:54:33 +00:00
|
|
|
|
|
|
|
/* next we poll all children for their state to see if one of them
|
2005-06-27 18:11:24 +00:00
|
|
|
* is still busy with its state change. We did not release the bin lock
|
|
|
|
* yet so the elements are the same as the ones from the quick scan. */
|
2005-03-28 14:54:33 +00:00
|
|
|
children = bin->children;
|
|
|
|
children_cookie = bin->children_cookie;
|
|
|
|
while (children) {
|
|
|
|
GstElement *child = GST_ELEMENT_CAST (children->data);
|
|
|
|
|
|
|
|
gst_object_ref (GST_OBJECT_CAST (child));
|
2005-06-27 18:11:24 +00:00
|
|
|
/* now we release the lock to enter the potentialy blocking wait */
|
2005-03-28 14:54:33 +00:00
|
|
|
GST_UNLOCK (bin);
|
|
|
|
|
2005-06-27 18:11:24 +00:00
|
|
|
/* ret is ASYNC if some child is still performing the state change
|
|
|
|
* ater the timeout. */
|
2005-03-28 14:54:33 +00:00
|
|
|
ret = gst_element_get_state (child, NULL, NULL, timeout);
|
|
|
|
|
|
|
|
gst_object_unref (GST_OBJECT_CAST (child));
|
|
|
|
|
|
|
|
/* now grab the lock to iterate to the next child */
|
|
|
|
GST_LOCK (bin);
|
2005-06-27 18:11:24 +00:00
|
|
|
if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
|
|
|
|
/* child added/removed during state change, restart. We need
|
|
|
|
* to restart with the quick check as a no-preroll element could
|
|
|
|
* have been added here and we don't want to block on sinks then.*/
|
2005-03-28 14:54:33 +00:00
|
|
|
goto restart;
|
2005-06-27 18:11:24 +00:00
|
|
|
}
|
2005-03-28 14:54:33 +00:00
|
|
|
|
2005-06-23 10:37:09 +00:00
|
|
|
switch (ret) {
|
|
|
|
case GST_STATE_SUCCESS:
|
|
|
|
break;
|
|
|
|
case GST_STATE_FAILURE:
|
|
|
|
case GST_STATE_NO_PREROLL:
|
|
|
|
/* report FAILURE and NO_PREROLL immediatly */
|
|
|
|
goto done;
|
|
|
|
break;
|
|
|
|
case GST_STATE_ASYNC:
|
|
|
|
/* since we checked for non prerollable elements before,
|
|
|
|
* the first ASYNC return is the real return value */
|
|
|
|
if (!zero_timeout)
|
|
|
|
goto done;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
2005-05-12 12:17:23 +00:00
|
|
|
}
|
2005-03-28 14:54:33 +00:00
|
|
|
children = g_list_next (children);
|
|
|
|
}
|
2005-06-27 18:11:24 +00:00
|
|
|
/* if we got here, all elements can do preroll */
|
|
|
|
have_no_preroll = FALSE;
|
|
|
|
|
2005-06-23 10:37:09 +00:00
|
|
|
done:
|
2005-03-28 14:54:33 +00:00
|
|
|
GST_UNLOCK (bin);
|
|
|
|
|
2005-06-27 18:11:24 +00:00
|
|
|
/* now we can take the state lock, it is possible that new elements
|
|
|
|
* are added now and we still report the old state. No problem though as
|
|
|
|
* the return is still consistent, the effect is as if the element was
|
|
|
|
* added after this function completed. */
|
2005-03-28 14:54:33 +00:00
|
|
|
GST_STATE_LOCK (bin);
|
|
|
|
switch (ret) {
|
|
|
|
case GST_STATE_SUCCESS:
|
|
|
|
/* we can commit the state */
|
|
|
|
gst_element_commit_state (element);
|
|
|
|
break;
|
|
|
|
case GST_STATE_FAILURE:
|
|
|
|
/* some element failed, abort the state change */
|
|
|
|
gst_element_abort_state (element);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* other cases are just passed along */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* and report the state if needed */
|
|
|
|
if (state)
|
|
|
|
*state = GST_STATE (element);
|
|
|
|
if (pending)
|
|
|
|
*pending = GST_STATE_PENDING (element);
|
|
|
|
|
2005-06-27 18:11:24 +00:00
|
|
|
GST_STATE_NO_PREROLL (element) = have_no_preroll;
|
|
|
|
|
2005-06-23 10:37:09 +00:00
|
|
|
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
|
|
|
|
"state current: %s, pending: %s, error: %d, no_preroll: %d, result: %d",
|
|
|
|
gst_element_state_get_name (GST_STATE (element)),
|
|
|
|
gst_element_state_get_name (GST_STATE_PENDING (element)),
|
|
|
|
GST_STATE_ERROR (element), GST_STATE_NO_PREROLL (element), ret);
|
|
|
|
|
2005-03-28 14:54:33 +00:00
|
|
|
GST_STATE_UNLOCK (bin);
|
|
|
|
|
|
|
|
return ret;
|
2001-12-04 22:12:50 +00:00
|
|
|
}
|
2000-01-30 09:03:00 +00:00
|
|
|
|
gst/: Fix state changes for non sinks. We now change sinks, then elements with unconnected srcpads, then the rest.
Original commit message from CVS:
* gst/gstbin.c: (bin_element_is_sink), (has_ancestor),
(bin_element_is_semi_sink), (append_child), (gst_bin_change_state):
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare),
(gst_pad_link), (gst_pad_accept_caps), (gst_pad_query),
(gst_pad_send_event), (gst_pad_start_task):
* gst/gstqueue.c: (gst_queue_init), (gst_queue_locked_flush),
(gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop),
(gst_queue_sink_activate), (gst_queue_src_activate),
(gst_queue_change_state):
* gst/gstqueue.h:
Fix state changes for non sinks. We now change sinks, then elements
with unconnected srcpads, then the rest.
More efficient queue unlocking in flush and state changes.
Set the pad activate mode even if it does not have an activate
function.
2005-05-25 19:33:39 +00:00
|
|
|
static void
|
|
|
|
append_child (gpointer child, GQueue * queue)
|
|
|
|
{
|
|
|
|
g_queue_push_tail (queue, child);
|
|
|
|
}
|
|
|
|
|
2005-06-27 18:11:24 +00:00
|
|
|
/**
|
|
|
|
* gst_bin_iterate_state_order:
|
|
|
|
* @bin: #Gstbin to iterate on
|
|
|
|
*
|
|
|
|
* Get an iterator for the elements in this bin in the order
|
|
|
|
* in which a state change should be performed on them. This
|
|
|
|
* means that first the sinks and then the other elements will
|
|
|
|
* be returned.
|
|
|
|
* Each element will have its refcount increased, so unref
|
|
|
|
* after use.
|
|
|
|
*
|
|
|
|
* MT safe.
|
|
|
|
*
|
|
|
|
* Returns: a #GstIterator of #GstElements. gst_iterator_free after use.
|
|
|
|
*/
|
|
|
|
GstIterator *
|
|
|
|
gst_bin_iterate_state_order (GstBin * bin)
|
|
|
|
{
|
|
|
|
GstIterator *result;
|
|
|
|
|
|
|
|
g_return_val_if_fail (GST_IS_BIN (bin), NULL);
|
|
|
|
|
|
|
|
result = NULL;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2005-03-21 17:34:02 +00:00
|
|
|
/* this function is called with the STATE_LOCK held. It works
|
|
|
|
* as follows:
|
2004-07-12 21:27:11 +00:00
|
|
|
*
|
2005-03-21 17:34:02 +00:00
|
|
|
* 1) put all sink elements on the queue.
|
2005-06-23 10:37:09 +00:00
|
|
|
* 2) put all semisink elements on the queue.
|
|
|
|
* 3) change state of elements in queue, put linked elements to queue.
|
|
|
|
* 4) while queue not empty goto 3)
|
2004-07-12 21:27:11 +00:00
|
|
|
*
|
2005-03-21 17:34:02 +00:00
|
|
|
* This will effectively change the state of all elements in the bin
|
|
|
|
* from the sinks to the sources. We have to change the states this
|
|
|
|
* way so that when a source element pushes data, the downstream element
|
|
|
|
* is in the right state to receive the data.
|
2005-03-10 12:51:45 +00:00
|
|
|
*
|
2005-03-21 17:34:02 +00:00
|
|
|
* MT safe.
|
|
|
|
*/
|
2004-07-29 20:33:49 +00:00
|
|
|
static GstElementStateReturn
|
|
|
|
gst_bin_change_state (GstElement * element)
|
2004-07-12 21:27:11 +00:00
|
|
|
{
|
2005-03-28 14:54:33 +00:00
|
|
|
GstBin *bin;
|
|
|
|
GstElementStateReturn ret;
|
|
|
|
GstElementState old_state, pending;
|
|
|
|
gboolean have_async = FALSE;
|
2005-06-23 10:37:09 +00:00
|
|
|
gboolean have_no_preroll = FALSE;
|
2005-03-28 14:54:33 +00:00
|
|
|
GList *children;
|
|
|
|
guint32 children_cookie;
|
|
|
|
GQueue *elem_queue; /* list of elements waiting for a state change */
|
gst/: Fix state changes for non sinks. We now change sinks, then elements with unconnected srcpads, then the rest.
Original commit message from CVS:
* gst/gstbin.c: (bin_element_is_sink), (has_ancestor),
(bin_element_is_semi_sink), (append_child), (gst_bin_change_state):
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare),
(gst_pad_link), (gst_pad_accept_caps), (gst_pad_query),
(gst_pad_send_event), (gst_pad_start_task):
* gst/gstqueue.c: (gst_queue_init), (gst_queue_locked_flush),
(gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop),
(gst_queue_sink_activate), (gst_queue_src_activate),
(gst_queue_change_state):
* gst/gstqueue.h:
Fix state changes for non sinks. We now change sinks, then elements
with unconnected srcpads, then the rest.
More efficient queue unlocking in flush and state changes.
Set the pad activate mode even if it does not have an activate
function.
2005-05-25 19:33:39 +00:00
|
|
|
GQueue *semi_queue; /* list of elements with no connected srcpads */
|
2005-06-27 18:11:24 +00:00
|
|
|
GQueue *temp; /* queue of leftovers */
|
2005-03-28 14:54:33 +00:00
|
|
|
|
|
|
|
bin = GST_BIN (element);
|
|
|
|
|
|
|
|
/* we don't need to take the STATE_LOCK, it is already taken */
|
|
|
|
old_state = GST_STATE (element);
|
|
|
|
pending = GST_STATE_PENDING (element);
|
|
|
|
|
|
|
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
|
|
|
"changing state of children from %s to %s",
|
|
|
|
gst_element_state_get_name (old_state),
|
|
|
|
gst_element_state_get_name (pending));
|
|
|
|
|
|
|
|
if (pending == GST_STATE_VOID_PENDING)
|
|
|
|
return GST_STATE_SUCCESS;
|
|
|
|
|
2005-06-27 18:11:24 +00:00
|
|
|
/* all elements added to these queues should have their refcount
|
2005-03-28 14:54:33 +00:00
|
|
|
* incremented */
|
|
|
|
elem_queue = g_queue_new ();
|
gst/: Fix state changes for non sinks. We now change sinks, then elements with unconnected srcpads, then the rest.
Original commit message from CVS:
* gst/gstbin.c: (bin_element_is_sink), (has_ancestor),
(bin_element_is_semi_sink), (append_child), (gst_bin_change_state):
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare),
(gst_pad_link), (gst_pad_accept_caps), (gst_pad_query),
(gst_pad_send_event), (gst_pad_start_task):
* gst/gstqueue.c: (gst_queue_init), (gst_queue_locked_flush),
(gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop),
(gst_queue_sink_activate), (gst_queue_src_activate),
(gst_queue_change_state):
* gst/gstqueue.h:
Fix state changes for non sinks. We now change sinks, then elements
with unconnected srcpads, then the rest.
More efficient queue unlocking in flush and state changes.
Set the pad activate mode even if it does not have an activate
function.
2005-05-25 19:33:39 +00:00
|
|
|
semi_queue = g_queue_new ();
|
2005-05-12 19:45:44 +00:00
|
|
|
temp = g_queue_new ();
|
2005-03-28 14:54:33 +00:00
|
|
|
|
|
|
|
/* first step, find all sink elements, these are the elements
|
|
|
|
* without (linked) source pads. */
|
|
|
|
GST_LOCK (bin);
|
|
|
|
restart:
|
|
|
|
children = bin->children;
|
|
|
|
children_cookie = bin->children_cookie;
|
|
|
|
while (children) {
|
|
|
|
GstElement *child = GST_ELEMENT_CAST (children->data);
|
|
|
|
|
|
|
|
gst_object_ref (GST_OBJECT_CAST (child));
|
|
|
|
GST_UNLOCK (bin);
|
|
|
|
|
|
|
|
if (bin_element_is_sink (child, bin) == 0) {
|
|
|
|
g_queue_push_tail (elem_queue, child);
|
gst/: Fix state changes for non sinks. We now change sinks, then elements with unconnected srcpads, then the rest.
Original commit message from CVS:
* gst/gstbin.c: (bin_element_is_sink), (has_ancestor),
(bin_element_is_semi_sink), (append_child), (gst_bin_change_state):
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare),
(gst_pad_link), (gst_pad_accept_caps), (gst_pad_query),
(gst_pad_send_event), (gst_pad_start_task):
* gst/gstqueue.c: (gst_queue_init), (gst_queue_locked_flush),
(gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop),
(gst_queue_sink_activate), (gst_queue_src_activate),
(gst_queue_change_state):
* gst/gstqueue.h:
Fix state changes for non sinks. We now change sinks, then elements
with unconnected srcpads, then the rest.
More efficient queue unlocking in flush and state changes.
Set the pad activate mode even if it does not have an activate
function.
2005-05-25 19:33:39 +00:00
|
|
|
} else if (bin_element_is_semi_sink (child, bin) == 0) {
|
|
|
|
g_queue_push_tail (semi_queue, child);
|
2005-05-12 19:45:44 +00:00
|
|
|
} else {
|
|
|
|
g_queue_push_tail (temp, child);
|
2005-03-28 14:54:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GST_LOCK (bin);
|
|
|
|
if (G_UNLIKELY (children_cookie != bin->children_cookie)) {
|
|
|
|
/* undo what we had */
|
|
|
|
g_queue_foreach (elem_queue, (GFunc) gst_object_unref, NULL);
|
gst/: Fix state changes for non sinks. We now change sinks, then elements with unconnected srcpads, then the rest.
Original commit message from CVS:
* gst/gstbin.c: (bin_element_is_sink), (has_ancestor),
(bin_element_is_semi_sink), (append_child), (gst_bin_change_state):
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare),
(gst_pad_link), (gst_pad_accept_caps), (gst_pad_query),
(gst_pad_send_event), (gst_pad_start_task):
* gst/gstqueue.c: (gst_queue_init), (gst_queue_locked_flush),
(gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop),
(gst_queue_sink_activate), (gst_queue_src_activate),
(gst_queue_change_state):
* gst/gstqueue.h:
Fix state changes for non sinks. We now change sinks, then elements
with unconnected srcpads, then the rest.
More efficient queue unlocking in flush and state changes.
Set the pad activate mode even if it does not have an activate
function.
2005-05-25 19:33:39 +00:00
|
|
|
g_queue_foreach (semi_queue, (GFunc) gst_object_unref, NULL);
|
2005-05-12 19:45:44 +00:00
|
|
|
g_queue_foreach (temp, (GFunc) gst_object_unref, NULL);
|
2005-03-28 14:54:33 +00:00
|
|
|
while (g_queue_pop_head (elem_queue));
|
gst/: Fix state changes for non sinks. We now change sinks, then elements with unconnected srcpads, then the rest.
Original commit message from CVS:
* gst/gstbin.c: (bin_element_is_sink), (has_ancestor),
(bin_element_is_semi_sink), (append_child), (gst_bin_change_state):
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare),
(gst_pad_link), (gst_pad_accept_caps), (gst_pad_query),
(gst_pad_send_event), (gst_pad_start_task):
* gst/gstqueue.c: (gst_queue_init), (gst_queue_locked_flush),
(gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop),
(gst_queue_sink_activate), (gst_queue_src_activate),
(gst_queue_change_state):
* gst/gstqueue.h:
Fix state changes for non sinks. We now change sinks, then elements
with unconnected srcpads, then the rest.
More efficient queue unlocking in flush and state changes.
Set the pad activate mode even if it does not have an activate
function.
2005-05-25 19:33:39 +00:00
|
|
|
while (g_queue_pop_head (semi_queue));
|
2005-05-12 19:45:44 +00:00
|
|
|
while (g_queue_pop_head (temp));
|
2005-03-28 14:54:33 +00:00
|
|
|
goto restart;
|
|
|
|
}
|
|
|
|
|
|
|
|
children = g_list_next (children);
|
|
|
|
}
|
|
|
|
GST_UNLOCK (bin);
|
|
|
|
|
gst/: Fix state changes for non sinks. We now change sinks, then elements with unconnected srcpads, then the rest.
Original commit message from CVS:
* gst/gstbin.c: (bin_element_is_sink), (has_ancestor),
(bin_element_is_semi_sink), (append_child), (gst_bin_change_state):
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare),
(gst_pad_link), (gst_pad_accept_caps), (gst_pad_query),
(gst_pad_send_event), (gst_pad_start_task):
* gst/gstqueue.c: (gst_queue_init), (gst_queue_locked_flush),
(gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop),
(gst_queue_sink_activate), (gst_queue_src_activate),
(gst_queue_change_state):
* gst/gstqueue.h:
Fix state changes for non sinks. We now change sinks, then elements
with unconnected srcpads, then the rest.
More efficient queue unlocking in flush and state changes.
Set the pad activate mode even if it does not have an activate
function.
2005-05-25 19:33:39 +00:00
|
|
|
/* now change state for semi sink elements first so add them in
|
|
|
|
* front of the other elements */
|
|
|
|
g_queue_foreach (temp, (GFunc) append_child, semi_queue);
|
|
|
|
g_queue_free (temp);
|
|
|
|
|
2005-05-14 15:54:49 +00:00
|
|
|
/* can be the case for a bin like ( identity ) */
|
gst/: Fix state changes for non sinks. We now change sinks, then elements with unconnected srcpads, then the rest.
Original commit message from CVS:
* gst/gstbin.c: (bin_element_is_sink), (has_ancestor),
(bin_element_is_semi_sink), (append_child), (gst_bin_change_state):
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare),
(gst_pad_link), (gst_pad_accept_caps), (gst_pad_query),
(gst_pad_send_event), (gst_pad_start_task):
* gst/gstqueue.c: (gst_queue_init), (gst_queue_locked_flush),
(gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop),
(gst_queue_sink_activate), (gst_queue_src_activate),
(gst_queue_change_state):
* gst/gstqueue.h:
Fix state changes for non sinks. We now change sinks, then elements
with unconnected srcpads, then the rest.
More efficient queue unlocking in flush and state changes.
Set the pad activate mode even if it does not have an activate
function.
2005-05-25 19:33:39 +00:00
|
|
|
if (g_queue_is_empty (elem_queue) && !g_queue_is_empty (semi_queue)) {
|
2005-05-14 15:54:49 +00:00
|
|
|
GQueue *q = elem_queue;
|
|
|
|
|
gst/: Fix state changes for non sinks. We now change sinks, then elements with unconnected srcpads, then the rest.
Original commit message from CVS:
* gst/gstbin.c: (bin_element_is_sink), (has_ancestor),
(bin_element_is_semi_sink), (append_child), (gst_bin_change_state):
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare),
(gst_pad_link), (gst_pad_accept_caps), (gst_pad_query),
(gst_pad_send_event), (gst_pad_start_task):
* gst/gstqueue.c: (gst_queue_init), (gst_queue_locked_flush),
(gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop),
(gst_queue_sink_activate), (gst_queue_src_activate),
(gst_queue_change_state):
* gst/gstqueue.h:
Fix state changes for non sinks. We now change sinks, then elements
with unconnected srcpads, then the rest.
More efficient queue unlocking in flush and state changes.
Set the pad activate mode even if it does not have an activate
function.
2005-05-25 19:33:39 +00:00
|
|
|
elem_queue = semi_queue;
|
|
|
|
semi_queue = q;
|
2005-05-14 15:54:49 +00:00
|
|
|
}
|
|
|
|
|
2005-03-28 14:54:33 +00:00
|
|
|
/* second step, change state of elements in the queue */
|
|
|
|
while (!g_queue_is_empty (elem_queue)) {
|
2005-05-12 19:45:44 +00:00
|
|
|
GstElement *qelement;
|
2005-03-28 14:54:33 +00:00
|
|
|
GList *pads;
|
|
|
|
gboolean locked;
|
|
|
|
|
2005-05-12 19:45:44 +00:00
|
|
|
/* take element */
|
|
|
|
qelement = g_queue_pop_head (elem_queue);
|
gst/: Fix state changes for non sinks. We now change sinks, then elements with unconnected srcpads, then the rest.
Original commit message from CVS:
* gst/gstbin.c: (bin_element_is_sink), (has_ancestor),
(bin_element_is_semi_sink), (append_child), (gst_bin_change_state):
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare),
(gst_pad_link), (gst_pad_accept_caps), (gst_pad_query),
(gst_pad_send_event), (gst_pad_start_task):
* gst/gstqueue.c: (gst_queue_init), (gst_queue_locked_flush),
(gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop),
(gst_queue_sink_activate), (gst_queue_src_activate),
(gst_queue_change_state):
* gst/gstqueue.h:
Fix state changes for non sinks. We now change sinks, then elements
with unconnected srcpads, then the rest.
More efficient queue unlocking in flush and state changes.
Set the pad activate mode even if it does not have an activate
function.
2005-05-25 19:33:39 +00:00
|
|
|
/* we don't need it in the semi_queue anymore */
|
|
|
|
g_queue_remove_all (semi_queue, qelement);
|
2005-05-12 19:45:44 +00:00
|
|
|
|
|
|
|
/* if queue is empty now, continue with a non-sink */
|
|
|
|
if (g_queue_is_empty (elem_queue)) {
|
|
|
|
GstElement *non_sink;
|
|
|
|
|
|
|
|
GST_DEBUG ("sinks and upstream elements exhausted");
|
gst/: Fix state changes for non sinks. We now change sinks, then elements with unconnected srcpads, then the rest.
Original commit message from CVS:
* gst/gstbin.c: (bin_element_is_sink), (has_ancestor),
(bin_element_is_semi_sink), (append_child), (gst_bin_change_state):
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare),
(gst_pad_link), (gst_pad_accept_caps), (gst_pad_query),
(gst_pad_send_event), (gst_pad_start_task):
* gst/gstqueue.c: (gst_queue_init), (gst_queue_locked_flush),
(gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop),
(gst_queue_sink_activate), (gst_queue_src_activate),
(gst_queue_change_state):
* gst/gstqueue.h:
Fix state changes for non sinks. We now change sinks, then elements
with unconnected srcpads, then the rest.
More efficient queue unlocking in flush and state changes.
Set the pad activate mode even if it does not have an activate
function.
2005-05-25 19:33:39 +00:00
|
|
|
non_sink = g_queue_pop_head (semi_queue);
|
2005-05-12 19:45:44 +00:00
|
|
|
if (non_sink) {
|
|
|
|
GST_DEBUG ("found lefover non-sink %s", GST_OBJECT_NAME (non_sink));
|
|
|
|
g_queue_push_tail (elem_queue, non_sink);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-03-28 14:54:33 +00:00
|
|
|
/* queue all elements connected to the sinkpads of this element */
|
|
|
|
GST_LOCK (qelement);
|
|
|
|
pads = qelement->sinkpads;
|
|
|
|
while (pads) {
|
|
|
|
GstPad *pad = GST_PAD_CAST (pads->data);
|
|
|
|
GstPad *peer;
|
|
|
|
|
|
|
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
|
|
|
"found sinkpad %s:%s", GST_DEBUG_PAD_NAME (pad));
|
|
|
|
|
|
|
|
peer = gst_pad_get_peer (pad);
|
|
|
|
if (peer) {
|
gst/gstutils.c: RPAD fixes all around.
Original commit message from CVS:
2005-06-08 Andy Wingo <wingo@pobox.com>
* gst/gstutils.c: RPAD fixes all around.
(gst_element_link_pads): Refcounting fixes.
* tools/gst-inspect.c:
* tools/gst-xmlinspect.c:
* parse/grammar.y:
* gst/base/gsttypefindhelper.c:
* gst/base/gstbasesink.c:
* gst/gstqueue.c: RPAD fixes.
* gst/gstghostpad.h:
* gst/gstghostpad.c: New ghost pad implementation as full proxy
pads. The tricky thing is they provide both source and sink
interfaces, since they proxy the internal pad for the external
pad, and vice versa. Implement with lower-level ProxyPad objects,
with the interior proxy pad as a child of the exterior ghost pad.
Should write a doc on this.
* gst/gstpad.h: s/RPAD/PAD/, s/RealPad/Pad/.
(gst_pad_set_name, gst_pad_set_parent): Macros removed, use
gst_object API.
* gst/gstpad.c: Big changes. No more stub base GstPad, now all
pads are real pads. No ghost pads in this file. Not documenting
the myriad s/RPAD/PAD/ and REALIZE fixes.
(gst_pad_class_init): Add properties for "direction" and
"template". Both are construct-only, so they can't change during
the life of the pad. Fixes properly deriving from GstPad.
(gst_pad_custom_new, gst_pad_custom_new_from_template): Gone. For
derived objects, just set properties when creating the objects via
g_object_new.
(gst_pad_get_parent): Implement as a function, return NULL if the
parent is not an element.
(gst_pad_get_real_parent, gst_pad_add_ghost_pad)
(gst_pad_remove_ghost_pad, gst_pad_realize): Removed.
* gst/gstobject.c (gst_object_class_init): Make name a construct
property. Don't set it in the object init.
* gst/gstelement.c (gst_element_add_pad): Don't allow adding pads
with UNKNOWN direction.
(gst_element_add_ghost_pad): Remove non-orthogonal API. Replace
with gst_element_add_pad (e, gst_ghost_pad_new (name, pad)).
(gst_element_remove_pad): Remove ghost-pad special cases.
(gst_element_pads_activate): Remove rpad cruft.
* gst/gstbin.c (gst_bin_change_state): Use gst_pad_get_parent to
catch the pad's-parent-not-an-element case.
* gst/gst.h: Include gstghostpad.h.
* gst/gst.c (init_post): No more real, ghost pads.
* gst/Makefile.am: Add gstghostpad.[ch].
* check/Makefile.am:
* check/gst/gstbin.c:
* check/gst/gstghostpad.c (test_ghost_pads): Check that linking
into a bin creates ghost pads, and that the refcounts are right.
Partly moved from gstbin.c.
2005-06-08 22:16:27 +00:00
|
|
|
GstElement *peer_elem;
|
2005-03-28 14:54:33 +00:00
|
|
|
|
gst/gstutils.c: RPAD fixes all around.
Original commit message from CVS:
2005-06-08 Andy Wingo <wingo@pobox.com>
* gst/gstutils.c: RPAD fixes all around.
(gst_element_link_pads): Refcounting fixes.
* tools/gst-inspect.c:
* tools/gst-xmlinspect.c:
* parse/grammar.y:
* gst/base/gsttypefindhelper.c:
* gst/base/gstbasesink.c:
* gst/gstqueue.c: RPAD fixes.
* gst/gstghostpad.h:
* gst/gstghostpad.c: New ghost pad implementation as full proxy
pads. The tricky thing is they provide both source and sink
interfaces, since they proxy the internal pad for the external
pad, and vice versa. Implement with lower-level ProxyPad objects,
with the interior proxy pad as a child of the exterior ghost pad.
Should write a doc on this.
* gst/gstpad.h: s/RPAD/PAD/, s/RealPad/Pad/.
(gst_pad_set_name, gst_pad_set_parent): Macros removed, use
gst_object API.
* gst/gstpad.c: Big changes. No more stub base GstPad, now all
pads are real pads. No ghost pads in this file. Not documenting
the myriad s/RPAD/PAD/ and REALIZE fixes.
(gst_pad_class_init): Add properties for "direction" and
"template". Both are construct-only, so they can't change during
the life of the pad. Fixes properly deriving from GstPad.
(gst_pad_custom_new, gst_pad_custom_new_from_template): Gone. For
derived objects, just set properties when creating the objects via
g_object_new.
(gst_pad_get_parent): Implement as a function, return NULL if the
parent is not an element.
(gst_pad_get_real_parent, gst_pad_add_ghost_pad)
(gst_pad_remove_ghost_pad, gst_pad_realize): Removed.
* gst/gstobject.c (gst_object_class_init): Make name a construct
property. Don't set it in the object init.
* gst/gstelement.c (gst_element_add_pad): Don't allow adding pads
with UNKNOWN direction.
(gst_element_add_ghost_pad): Remove non-orthogonal API. Replace
with gst_element_add_pad (e, gst_ghost_pad_new (name, pad)).
(gst_element_remove_pad): Remove ghost-pad special cases.
(gst_element_pads_activate): Remove rpad cruft.
* gst/gstbin.c (gst_bin_change_state): Use gst_pad_get_parent to
catch the pad's-parent-not-an-element case.
* gst/gst.h: Include gstghostpad.h.
* gst/gst.c (init_post): No more real, ghost pads.
* gst/Makefile.am: Add gstghostpad.[ch].
* check/Makefile.am:
* check/gst/gstbin.c:
* check/gst/gstghostpad.c (test_ghost_pads): Check that linking
into a bin creates ghost pads, and that the refcounts are right.
Partly moved from gstbin.c.
2005-06-08 22:16:27 +00:00
|
|
|
peer_elem = gst_pad_get_parent (peer);
|
2005-03-28 14:54:33 +00:00
|
|
|
|
|
|
|
if (peer_elem) {
|
|
|
|
GstObject *parent;
|
|
|
|
|
|
|
|
/* see if this element is in the bin we are currently handling */
|
|
|
|
parent = gst_object_get_parent (GST_OBJECT_CAST (peer_elem));
|
|
|
|
if (parent && parent == GST_OBJECT_CAST (bin)) {
|
2005-06-23 10:37:09 +00:00
|
|
|
GList *oldelem;
|
|
|
|
|
2005-03-28 14:54:33 +00:00
|
|
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
|
|
|
"adding element %s to queue", GST_ELEMENT_NAME (peer_elem));
|
|
|
|
|
2005-06-23 10:37:09 +00:00
|
|
|
/* make sure we don't have duplicates */
|
|
|
|
while ((oldelem = g_queue_find (semi_queue, peer_elem))) {
|
|
|
|
gst_object_unref (GST_OBJECT (peer_elem));
|
|
|
|
g_queue_delete_link (semi_queue, oldelem);
|
|
|
|
}
|
|
|
|
while ((oldelem = g_queue_find (elem_queue, peer_elem))) {
|
|
|
|
gst_object_unref (GST_OBJECT (peer_elem));
|
|
|
|
g_queue_delete_link (elem_queue, oldelem);
|
|
|
|
}
|
2005-06-27 08:16:51 +00:00
|
|
|
/* was reffed before pushing on the queue by the
|
2005-03-28 14:54:33 +00:00
|
|
|
* gst_object_get_parent() call we used to get the element. */
|
|
|
|
g_queue_push_tail (elem_queue, peer_elem);
|
|
|
|
} else {
|
|
|
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
|
|
|
"not adding element %s to queue, it is in another bin",
|
|
|
|
GST_ELEMENT_NAME (peer_elem));
|
2005-05-11 03:37:10 +00:00
|
|
|
gst_object_unref (GST_OBJECT_CAST (peer_elem));
|
2005-03-28 14:54:33 +00:00
|
|
|
}
|
|
|
|
if (parent) {
|
gst/gstutils.c: RPAD fixes all around.
Original commit message from CVS:
2005-06-08 Andy Wingo <wingo@pobox.com>
* gst/gstutils.c: RPAD fixes all around.
(gst_element_link_pads): Refcounting fixes.
* tools/gst-inspect.c:
* tools/gst-xmlinspect.c:
* parse/grammar.y:
* gst/base/gsttypefindhelper.c:
* gst/base/gstbasesink.c:
* gst/gstqueue.c: RPAD fixes.
* gst/gstghostpad.h:
* gst/gstghostpad.c: New ghost pad implementation as full proxy
pads. The tricky thing is they provide both source and sink
interfaces, since they proxy the internal pad for the external
pad, and vice versa. Implement with lower-level ProxyPad objects,
with the interior proxy pad as a child of the exterior ghost pad.
Should write a doc on this.
* gst/gstpad.h: s/RPAD/PAD/, s/RealPad/Pad/.
(gst_pad_set_name, gst_pad_set_parent): Macros removed, use
gst_object API.
* gst/gstpad.c: Big changes. No more stub base GstPad, now all
pads are real pads. No ghost pads in this file. Not documenting
the myriad s/RPAD/PAD/ and REALIZE fixes.
(gst_pad_class_init): Add properties for "direction" and
"template". Both are construct-only, so they can't change during
the life of the pad. Fixes properly deriving from GstPad.
(gst_pad_custom_new, gst_pad_custom_new_from_template): Gone. For
derived objects, just set properties when creating the objects via
g_object_new.
(gst_pad_get_parent): Implement as a function, return NULL if the
parent is not an element.
(gst_pad_get_real_parent, gst_pad_add_ghost_pad)
(gst_pad_remove_ghost_pad, gst_pad_realize): Removed.
* gst/gstobject.c (gst_object_class_init): Make name a construct
property. Don't set it in the object init.
* gst/gstelement.c (gst_element_add_pad): Don't allow adding pads
with UNKNOWN direction.
(gst_element_add_ghost_pad): Remove non-orthogonal API. Replace
with gst_element_add_pad (e, gst_ghost_pad_new (name, pad)).
(gst_element_remove_pad): Remove ghost-pad special cases.
(gst_element_pads_activate): Remove rpad cruft.
* gst/gstbin.c (gst_bin_change_state): Use gst_pad_get_parent to
catch the pad's-parent-not-an-element case.
* gst/gst.h: Include gstghostpad.h.
* gst/gst.c (init_post): No more real, ghost pads.
* gst/Makefile.am: Add gstghostpad.[ch].
* check/Makefile.am:
* check/gst/gstbin.c:
* check/gst/gstghostpad.c (test_ghost_pads): Check that linking
into a bin creates ghost pads, and that the refcounts are right.
Partly moved from gstbin.c.
2005-06-08 22:16:27 +00:00
|
|
|
gst_object_unref (parent);
|
2005-03-28 14:54:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
gst_object_unref (GST_OBJECT_CAST (peer));
|
|
|
|
} else {
|
|
|
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
|
|
|
"pad %s:%s does not have a peer", GST_DEBUG_PAD_NAME (pad));
|
|
|
|
}
|
|
|
|
pads = g_list_next (pads);
|
|
|
|
}
|
|
|
|
/* peel off the locked flag and release the element lock */
|
|
|
|
locked = GST_FLAG_IS_SET (qelement, GST_ELEMENT_LOCKED_STATE);
|
|
|
|
GST_UNLOCK (qelement);
|
|
|
|
|
|
|
|
if (G_UNLIKELY (locked))
|
|
|
|
goto next_element;
|
|
|
|
|
|
|
|
qelement->base_time = element->base_time;
|
|
|
|
ret = gst_element_set_state (qelement, pending);
|
|
|
|
switch (ret) {
|
|
|
|
case GST_STATE_SUCCESS:
|
|
|
|
GST_CAT_DEBUG (GST_CAT_STATES,
|
|
|
|
"child '%s' changed state to %d(%s) successfully",
|
|
|
|
GST_ELEMENT_NAME (qelement), pending,
|
|
|
|
gst_element_state_get_name (pending));
|
|
|
|
break;
|
|
|
|
case GST_STATE_ASYNC:
|
|
|
|
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
|
|
|
|
"child '%s' is changing state asynchronously",
|
|
|
|
GST_ELEMENT_NAME (qelement));
|
|
|
|
have_async = TRUE;
|
|
|
|
break;
|
|
|
|
case GST_STATE_FAILURE:
|
|
|
|
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
|
|
|
|
"child '%s' failed to go to state %d(%s)",
|
|
|
|
GST_ELEMENT_NAME (qelement),
|
|
|
|
pending, gst_element_state_get_name (pending));
|
|
|
|
ret = GST_STATE_FAILURE;
|
|
|
|
/* release refcount of element we popped off the queue */
|
|
|
|
gst_object_unref (GST_OBJECT (qelement));
|
|
|
|
goto exit;
|
2005-06-23 10:37:09 +00:00
|
|
|
case GST_STATE_NO_PREROLL:
|
|
|
|
GST_CAT_DEBUG (GST_CAT_STATES,
|
|
|
|
"child '%s' changed state to %d(%s) successfully without preroll",
|
|
|
|
GST_ELEMENT_NAME (qelement), pending,
|
|
|
|
gst_element_state_get_name (pending));
|
|
|
|
have_no_preroll = TRUE;
|
|
|
|
break;
|
2005-03-28 14:54:33 +00:00
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
next_element:
|
|
|
|
gst_object_unref (GST_OBJECT (qelement));
|
|
|
|
}
|
|
|
|
|
2005-06-23 10:37:09 +00:00
|
|
|
if (have_no_preroll) {
|
|
|
|
ret = GST_STATE_NO_PREROLL;
|
|
|
|
} else if (have_async) {
|
2005-03-28 14:54:33 +00:00
|
|
|
ret = GST_STATE_ASYNC;
|
|
|
|
} else {
|
2005-06-23 10:37:09 +00:00
|
|
|
if ((ret = parent_class->change_state (element)) == GST_STATE_SUCCESS) {
|
2005-03-28 14:54:33 +00:00
|
|
|
/* we can commit the state change now */
|
|
|
|
gst_element_commit_state (element);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
|
|
|
|
"done changing bin's state from %s to %s, now in %s",
|
|
|
|
gst_element_state_get_name (old_state),
|
|
|
|
gst_element_state_get_name (pending),
|
|
|
|
gst_element_state_get_name (GST_STATE (element)));
|
|
|
|
|
|
|
|
exit:
|
2005-06-23 10:37:09 +00:00
|
|
|
/* release refcounts in queue, should normally be empty unless we
|
|
|
|
* had an error. */
|
2005-03-28 14:54:33 +00:00
|
|
|
g_queue_foreach (elem_queue, (GFunc) gst_object_unref, NULL);
|
|
|
|
g_queue_free (elem_queue);
|
gst/: Fix state changes for non sinks. We now change sinks, then elements with unconnected srcpads, then the rest.
Original commit message from CVS:
* gst/gstbin.c: (bin_element_is_sink), (has_ancestor),
(bin_element_is_semi_sink), (append_child), (gst_bin_change_state):
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_link_prepare),
(gst_pad_link), (gst_pad_accept_caps), (gst_pad_query),
(gst_pad_send_event), (gst_pad_start_task):
* gst/gstqueue.c: (gst_queue_init), (gst_queue_locked_flush),
(gst_queue_handle_sink_event), (gst_queue_chain), (gst_queue_loop),
(gst_queue_sink_activate), (gst_queue_src_activate),
(gst_queue_change_state):
* gst/gstqueue.h:
Fix state changes for non sinks. We now change sinks, then elements
with unconnected srcpads, then the rest.
More efficient queue unlocking in flush and state changes.
Set the pad activate mode even if it does not have an activate
function.
2005-05-25 19:33:39 +00:00
|
|
|
g_queue_foreach (semi_queue, (GFunc) gst_object_unref, NULL);
|
|
|
|
g_queue_free (semi_queue);
|
2005-03-28 14:54:33 +00:00
|
|
|
|
|
|
|
return ret;
|
2000-01-30 09:03:00 +00:00
|
|
|
}
|
|
|
|
|
2001-01-20 03:10:44 +00:00
|
|
|
static void
|
2001-12-15 22:37:35 +00:00
|
|
|
gst_bin_dispose (GObject * object)
|
2000-11-04 18:54:07 +00:00
|
|
|
{
|
|
|
|
GstBin *bin = GST_BIN (object);
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2004-05-03 14:45:38 +00:00
|
|
|
GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose");
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
/* ref to not hit 0 again */
|
|
|
|
gst_object_ref (GST_OBJECT (object));
|
2002-02-17 19:58:29 +00:00
|
|
|
|
2004-05-06 21:40:55 +00:00
|
|
|
while (bin->children) {
|
|
|
|
gst_bin_remove (bin, GST_ELEMENT (bin->children->data));
|
2000-01-30 09:03:00 +00:00
|
|
|
}
|
2005-03-07 18:27:42 +00:00
|
|
|
GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose no children");
|
2004-05-06 21:40:55 +00:00
|
|
|
g_assert (bin->children == NULL);
|
|
|
|
g_assert (bin->numchildren == 0);
|
2001-05-25 21:00:07 +00:00
|
|
|
|
2001-09-28 19:16:02 +00:00
|
|
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
2000-01-30 09:03:00 +00:00
|
|
|
}
|
|
|
|
|
gst/gstbin.c: Add default event/set_manager handlers. The set_manager handler takes care that the manager is distribu...
Original commit message from CVS:
* gst/gstbin.c: (gst_bin_class_init), (gst_bin_set_manager),
(gst_bin_send_event):
Add default event/set_manager handlers. The set_manager handler
takes care that the manager is distributed over kids that were
already in the bin before the manager was set. The event handler
is a utility virtual function that sends the event over all sinks,
so that gst_element_send_event (bin, event); has the expected
behaviour.
* gst/gstpad.c: (gst_pad_event_default):
Re-install default event handling for discontinuities, so that
seeking works without requiring hacks in applications or extra
code in sinks.
* gst/gstpipeline.c: (gst_pipeline_class_init),
(gst_pipeline_send_event):
Half hack, half utility: set a pipeline to PAUSED for seek events,
since that is the only way we can guarantee a/v sync. Means that
you can do gst_element_seek (pipeline, method, pos); on a pipeline
and it "just works".
2005-03-25 09:57:42 +00:00
|
|
|
/*
|
|
|
|
* This function is a utility event handler for seek events.
|
2005-03-28 14:54:33 +00:00
|
|
|
* It will send the event to all sinks.
|
gst/gstbin.c: Add default event/set_manager handlers. The set_manager handler takes care that the manager is distribu...
Original commit message from CVS:
* gst/gstbin.c: (gst_bin_class_init), (gst_bin_set_manager),
(gst_bin_send_event):
Add default event/set_manager handlers. The set_manager handler
takes care that the manager is distributed over kids that were
already in the bin before the manager was set. The event handler
is a utility virtual function that sends the event over all sinks,
so that gst_element_send_event (bin, event); has the expected
behaviour.
* gst/gstpad.c: (gst_pad_event_default):
Re-install default event handling for discontinuities, so that
seeking works without requiring hacks in applications or extra
code in sinks.
* gst/gstpipeline.c: (gst_pipeline_class_init),
(gst_pipeline_send_event):
Half hack, half utility: set a pipeline to PAUSED for seek events,
since that is the only way we can guarantee a/v sync. Means that
you can do gst_element_seek (pipeline, method, pos); on a pipeline
and it "just works".
2005-03-25 09:57:42 +00:00
|
|
|
* Applications are free to override this behaviour and
|
|
|
|
* implement their own seek handler, but this will work for
|
|
|
|
* pretty much all cases in practice.
|
|
|
|
*/
|
|
|
|
static gboolean
|
|
|
|
gst_bin_send_event (GstElement * element, GstEvent * event)
|
|
|
|
{
|
|
|
|
GstBin *bin = GST_BIN (element);
|
|
|
|
GstIterator *iter;
|
|
|
|
gboolean res = TRUE;
|
2005-03-28 14:54:33 +00:00
|
|
|
gboolean done = FALSE;
|
gst/gstbin.c: Add default event/set_manager handlers. The set_manager handler takes care that the manager is distribu...
Original commit message from CVS:
* gst/gstbin.c: (gst_bin_class_init), (gst_bin_set_manager),
(gst_bin_send_event):
Add default event/set_manager handlers. The set_manager handler
takes care that the manager is distributed over kids that were
already in the bin before the manager was set. The event handler
is a utility virtual function that sends the event over all sinks,
so that gst_element_send_event (bin, event); has the expected
behaviour.
* gst/gstpad.c: (gst_pad_event_default):
Re-install default event handling for discontinuities, so that
seeking works without requiring hacks in applications or extra
code in sinks.
* gst/gstpipeline.c: (gst_pipeline_class_init),
(gst_pipeline_send_event):
Half hack, half utility: set a pipeline to PAUSED for seek events,
since that is the only way we can guarantee a/v sync. Means that
you can do gst_element_seek (pipeline, method, pos); on a pipeline
and it "just works".
2005-03-25 09:57:42 +00:00
|
|
|
|
|
|
|
iter = gst_bin_iterate_sinks (bin);
|
|
|
|
GST_DEBUG_OBJECT (bin, "Sending event to sink children");
|
|
|
|
|
2005-03-28 14:54:33 +00:00
|
|
|
while (!done) {
|
|
|
|
gpointer data;
|
|
|
|
|
|
|
|
switch (gst_iterator_next (iter, &data)) {
|
|
|
|
case GST_ITERATOR_OK:
|
|
|
|
{
|
|
|
|
GstElement *sink;
|
|
|
|
|
|
|
|
gst_event_ref (event);
|
|
|
|
sink = GST_ELEMENT_CAST (data);
|
|
|
|
res &= gst_element_send_event (sink, event);
|
|
|
|
gst_object_unref (GST_OBJECT (sink));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case GST_ITERATOR_RESYNC:
|
|
|
|
gst_iterator_resync (iter);
|
|
|
|
res = TRUE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
case GST_ITERATOR_DONE:
|
|
|
|
done = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
gst/gstbin.c: Add default event/set_manager handlers. The set_manager handler takes care that the manager is distribu...
Original commit message from CVS:
* gst/gstbin.c: (gst_bin_class_init), (gst_bin_set_manager),
(gst_bin_send_event):
Add default event/set_manager handlers. The set_manager handler
takes care that the manager is distributed over kids that were
already in the bin before the manager was set. The event handler
is a utility virtual function that sends the event over all sinks,
so that gst_element_send_event (bin, event); has the expected
behaviour.
* gst/gstpad.c: (gst_pad_event_default):
Re-install default event handling for discontinuities, so that
seeking works without requiring hacks in applications or extra
code in sinks.
* gst/gstpipeline.c: (gst_pipeline_class_init),
(gst_pipeline_send_event):
Half hack, half utility: set a pipeline to PAUSED for seek events,
since that is the only way we can guarantee a/v sync. Means that
you can do gst_element_seek (pipeline, method, pos); on a pipeline
and it "just works".
2005-03-25 09:57:42 +00:00
|
|
|
}
|
|
|
|
gst_iterator_free (iter);
|
|
|
|
gst_event_unref (event);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2005-05-12 15:09:17 +00:00
|
|
|
static gboolean
|
|
|
|
gst_bin_query (GstElement * element, GstQuery * query)
|
|
|
|
{
|
|
|
|
GstBin *bin = GST_BIN (element);
|
|
|
|
GstIterator *iter;
|
|
|
|
gboolean res = FALSE, done = FALSE;
|
|
|
|
|
|
|
|
iter = gst_bin_iterate_sinks (bin);
|
|
|
|
GST_DEBUG_OBJECT (bin, "Sending event to sink children");
|
|
|
|
|
|
|
|
while (!(res || done)) {
|
|
|
|
gpointer data;
|
|
|
|
|
|
|
|
switch (gst_iterator_next (iter, &data)) {
|
|
|
|
case GST_ITERATOR_OK:
|
|
|
|
{
|
|
|
|
GstElement *sink;
|
|
|
|
|
|
|
|
sink = GST_ELEMENT_CAST (data);
|
|
|
|
res = gst_element_query (sink, query);
|
|
|
|
gst_object_unref (GST_OBJECT (sink));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case GST_ITERATOR_RESYNC:
|
|
|
|
gst_iterator_resync (iter);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
case GST_ITERATOR_DONE:
|
|
|
|
done = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
gst_iterator_free (iter);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
static gint
|
|
|
|
compare_name (GstElement * element, const gchar * name)
|
|
|
|
{
|
|
|
|
gint eq;
|
|
|
|
|
|
|
|
GST_LOCK (element);
|
gst/: Fix name lookup in GstBin.
Original commit message from CVS:
* gst/gstbin.c: (gst_bin_send_event), (compare_name),
(gst_bin_get_by_name):
* gst/gstbuffer.h:
* gst/gstclock.c: (gst_clock_entry_new), (gst_clock_class_init),
(gst_clock_finalize):
* gst/gstdata.c: (gst_data_replace):
* gst/gstdata.h:
* gst/gstelement.c: (gst_element_request_pad),
(gst_element_pads_activate):
* gst/gstobject.c: (gst_object_init), (gst_object_ref),
(gst_object_unref):
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_peer_set_active),
(gst_pad_set_checkgetrange_function),
(gst_pad_link_check_compatible_unlocked), (gst_pad_set_caps),
(gst_pad_check_pull_range), (gst_pad_pull_range),
(gst_static_pad_template_get_caps), (gst_pad_start_task),
(gst_pad_pause_task), (gst_pad_stop_task):
* gst/gstutils.c: (gst_element_get_compatible_pad_template),
(gst_element_request_pad), (gst_pad_proxy_getcaps):
Fix name lookup in GstBin.
Added _data_replace() function and _buffer_replace()
Use finalize method to clean up clock.
Fix refcounting on request pads.
Fix pad schedule mode error.
Some more object refcounting debug info,
2005-05-05 09:28:01 +00:00
|
|
|
eq = strcmp (GST_ELEMENT_NAME (element), name);
|
2005-03-07 18:27:42 +00:00
|
|
|
GST_UNLOCK (element);
|
|
|
|
|
|
|
|
if (eq != 0) {
|
|
|
|
gst_object_unref (GST_OBJECT (element));
|
|
|
|
}
|
|
|
|
return eq;
|
|
|
|
}
|
|
|
|
|
2000-03-27 19:53:43 +00:00
|
|
|
/**
|
|
|
|
* gst_bin_get_by_name:
|
|
|
|
* @bin: #Gstbin to search
|
|
|
|
* @name: the element name to search for
|
|
|
|
*
|
2005-03-07 18:27:42 +00:00
|
|
|
* Get the element with the given name from this bin. This
|
|
|
|
* function recurses into subbins.
|
|
|
|
*
|
2005-06-27 08:16:51 +00:00
|
|
|
* MT safe.
|
|
|
|
*
|
2005-03-07 18:27:42 +00:00
|
|
|
* Returns: the element with the given name. Returns NULL if the
|
|
|
|
* element is not found or when bad parameters were given. Unref after
|
2005-06-27 08:16:51 +00:00
|
|
|
* use.
|
2000-03-27 19:53:43 +00:00
|
|
|
*/
|
2001-12-15 22:37:35 +00:00
|
|
|
GstElement *
|
|
|
|
gst_bin_get_by_name (GstBin * bin, const gchar * name)
|
2000-11-04 18:54:07 +00:00
|
|
|
{
|
2005-03-07 18:27:42 +00:00
|
|
|
GstIterator *children;
|
|
|
|
GstIterator *result;
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2000-11-04 18:54:07 +00:00
|
|
|
g_return_val_if_fail (GST_IS_BIN (bin), NULL);
|
2000-01-30 09:03:00 +00:00
|
|
|
|
gst/: Fix name lookup in GstBin.
Original commit message from CVS:
* gst/gstbin.c: (gst_bin_send_event), (compare_name),
(gst_bin_get_by_name):
* gst/gstbuffer.h:
* gst/gstclock.c: (gst_clock_entry_new), (gst_clock_class_init),
(gst_clock_finalize):
* gst/gstdata.c: (gst_data_replace):
* gst/gstdata.h:
* gst/gstelement.c: (gst_element_request_pad),
(gst_element_pads_activate):
* gst/gstobject.c: (gst_object_init), (gst_object_ref),
(gst_object_unref):
* gst/gstpad.c: (gst_pad_set_active), (gst_pad_peer_set_active),
(gst_pad_set_checkgetrange_function),
(gst_pad_link_check_compatible_unlocked), (gst_pad_set_caps),
(gst_pad_check_pull_range), (gst_pad_pull_range),
(gst_static_pad_template_get_caps), (gst_pad_start_task),
(gst_pad_pause_task), (gst_pad_stop_task):
* gst/gstutils.c: (gst_element_get_compatible_pad_template),
(gst_element_request_pad), (gst_pad_proxy_getcaps):
Fix name lookup in GstBin.
Added _data_replace() function and _buffer_replace()
Use finalize method to clean up clock.
Fix refcounting on request pads.
Fix pad schedule mode error.
Some more object refcounting debug info,
2005-05-05 09:28:01 +00:00
|
|
|
GST_CAT_INFO (GST_CAT_PARENTAGE, "[%s]: looking up child element %s",
|
|
|
|
GST_ELEMENT_NAME (bin), name);
|
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
children = gst_bin_iterate_recurse (bin);
|
|
|
|
result = gst_iterator_find_custom (children,
|
|
|
|
(GCompareFunc) compare_name, (gpointer) name);
|
Docs updates, clean up some headers.
Original commit message from CVS:
* docs/design/part-MT-refcounting.txt:
* docs/design/part-conventions.txt:
* docs/design/part-gstobject.txt:
* docs/design/part-relations.txt:
* docs/design/part-standards.txt:
* gst/gstbin.c: (gst_bin_add_func), (gst_bin_add),
(gst_bin_remove_func), (gst_bin_remove), (gst_bin_iterate_recurse),
(gst_bin_get_by_name), (gst_bin_get_by_interface),
(gst_bin_iterate_all_by_interface):
* gst/gstbuffer.h:
* gst/gstclock.h:
* gst/gstelement.c: (gst_element_class_init),
(gst_element_change_state), (gst_element_set_loop_function):
* gst/gstelement.h:
* gst/gstiterator.c:
* gst/gstobject.c: (gst_object_class_init), (gst_object_ref),
(gst_object_unref), (gst_object_sink), (gst_object_dispose),
(gst_object_dispatch_properties_changed), (gst_object_set_name),
(gst_object_set_parent), (gst_object_unparent),
(gst_object_check_uniqueness):
* gst/gstobject.h:
Docs updates, clean up some headers.
Free iterators in GstBin.
GstObject is now looking good.
2005-03-08 14:38:06 +00:00
|
|
|
gst_iterator_free (children);
|
2000-12-30 02:41:15 +00:00
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
return GST_ELEMENT_CAST (result);
|
2000-01-30 09:03:00 +00:00
|
|
|
}
|
|
|
|
|
2001-01-29 00:06:02 +00:00
|
|
|
/**
|
|
|
|
* gst_bin_get_by_name_recurse_up:
|
|
|
|
* @bin: #Gstbin to search
|
|
|
|
* @name: the element name to search for
|
|
|
|
*
|
2005-06-27 08:16:51 +00:00
|
|
|
* MT safe.
|
|
|
|
*
|
2001-01-29 00:06:02 +00:00
|
|
|
* Get the element with the given name from this bin. If the
|
|
|
|
* element is not found, a recursion is performed on the parent bin.
|
|
|
|
*
|
2005-03-07 18:27:42 +00:00
|
|
|
* Returns: the element with the given name or NULL when the element
|
2005-06-27 08:16:51 +00:00
|
|
|
* was not found or bad parameters were given. Unref after use.
|
2001-01-29 00:06:02 +00:00
|
|
|
*/
|
2001-12-15 22:37:35 +00:00
|
|
|
GstElement *
|
|
|
|
gst_bin_get_by_name_recurse_up (GstBin * bin, const gchar * name)
|
2001-01-29 00:06:02 +00:00
|
|
|
{
|
2005-03-07 18:27:42 +00:00
|
|
|
GstElement *result;
|
2001-01-29 00:06:02 +00:00
|
|
|
|
|
|
|
g_return_val_if_fail (GST_IS_BIN (bin), NULL);
|
|
|
|
g_return_val_if_fail (name != NULL, NULL);
|
|
|
|
|
|
|
|
result = gst_bin_get_by_name (bin, name);
|
|
|
|
|
2001-12-15 22:37:35 +00:00
|
|
|
if (!result) {
|
2005-03-07 18:27:42 +00:00
|
|
|
GstObject *parent;
|
|
|
|
|
|
|
|
parent = gst_object_get_parent (GST_OBJECT_CAST (bin));
|
Bump version number, we're now 0.9.0
Original commit message from CVS:
* configure.ac:
* gst/gst_private.h:
* gst/gstbin.c: (gst_bin_add_func), (gst_bin_add),
(gst_bin_remove_func), (gst_bin_remove),
(gst_bin_get_by_name_recurse_up):
* gst/gstclock.c: (gst_clock_id_ref), (gst_clock_id_unref),
(gst_clock_id_compare_func), (gst_clock_id_wait),
(gst_clock_id_wait_async), (gst_clock_init),
(gst_clock_adjust_unlocked), (gst_clock_get_time):
* gst/gstelement.h:
* gst/gstinfo.c: (_gst_debug_init):
* gst/gstobject.h:
* gst/gstpad.c: (_gst_pad_default_fixate_foreach),
(gst_pad_collectv), (gst_pad_collect_valist), (gst_pad_query):
* gst/gstpad.h:
Bump version number, we're now 0.9.0
Add future debugging category.
Fix NULL _unref() in _get_by_name_recurse_up
Rearrange gstpad.h.
Update some docs.
2005-03-09 11:08:18 +00:00
|
|
|
if (parent) {
|
|
|
|
if (GST_IS_BIN (parent)) {
|
|
|
|
result = gst_bin_get_by_name_recurse_up (GST_BIN_CAST (parent), name);
|
|
|
|
}
|
|
|
|
gst_object_unref (parent);
|
2001-12-15 22:37:35 +00:00
|
|
|
}
|
2001-01-29 00:06:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
static gint
|
|
|
|
compare_interface (GstElement * element, gpointer interface)
|
2000-11-04 18:54:07 +00:00
|
|
|
{
|
2005-03-07 18:27:42 +00:00
|
|
|
gint ret;
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
if (G_TYPE_CHECK_INSTANCE_TYPE (element, GPOINTER_TO_INT (interface))) {
|
|
|
|
ret = 0;
|
|
|
|
} else {
|
|
|
|
/* we did not find the element, need to release the ref
|
|
|
|
* added by the iterator */
|
|
|
|
gst_object_unref (GST_OBJECT (element));
|
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
return ret;
|
2000-01-30 09:03:00 +00:00
|
|
|
}
|
|
|
|
|
2003-12-16 19:35:26 +00:00
|
|
|
/**
|
|
|
|
* gst_bin_get_by_interface:
|
|
|
|
* @bin: bin to find element in
|
|
|
|
* @interface: interface to be implemented by interface
|
|
|
|
*
|
2004-07-09 08:45:18 +00:00
|
|
|
* Looks for the first element inside the bin that implements the given
|
2003-12-16 19:35:26 +00:00
|
|
|
* interface. If such an element is found, it returns the element. You can
|
|
|
|
* cast this element to the given interface afterwards.
|
2004-07-09 08:45:18 +00:00
|
|
|
* If you want all elements that implement the interface, use
|
2005-06-27 08:16:51 +00:00
|
|
|
* gst_bin_iterate_all_by_interface(). The function recurses inside bins.
|
2005-03-07 18:27:42 +00:00
|
|
|
*
|
|
|
|
* MT safe.
|
2005-06-27 08:16:51 +00:00
|
|
|
*
|
|
|
|
* Returns: An #GstElement inside the bin implementing the interface.
|
|
|
|
* Unref after use.
|
2003-12-16 19:35:26 +00:00
|
|
|
*/
|
|
|
|
GstElement *
|
2004-03-13 15:27:01 +00:00
|
|
|
gst_bin_get_by_interface (GstBin * bin, GType interface)
|
2003-12-16 19:35:26 +00:00
|
|
|
{
|
2005-03-07 18:27:42 +00:00
|
|
|
GstIterator *children;
|
|
|
|
GstIterator *result;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2003-12-16 19:35:26 +00:00
|
|
|
g_return_val_if_fail (GST_IS_BIN (bin), NULL);
|
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
children = gst_bin_iterate_recurse (bin);
|
|
|
|
result = gst_iterator_find_custom (children, (GCompareFunc) compare_interface,
|
|
|
|
GINT_TO_POINTER (interface));
|
Docs updates, clean up some headers.
Original commit message from CVS:
* docs/design/part-MT-refcounting.txt:
* docs/design/part-conventions.txt:
* docs/design/part-gstobject.txt:
* docs/design/part-relations.txt:
* docs/design/part-standards.txt:
* gst/gstbin.c: (gst_bin_add_func), (gst_bin_add),
(gst_bin_remove_func), (gst_bin_remove), (gst_bin_iterate_recurse),
(gst_bin_get_by_name), (gst_bin_get_by_interface),
(gst_bin_iterate_all_by_interface):
* gst/gstbuffer.h:
* gst/gstclock.h:
* gst/gstelement.c: (gst_element_class_init),
(gst_element_change_state), (gst_element_set_loop_function):
* gst/gstelement.h:
* gst/gstiterator.c:
* gst/gstobject.c: (gst_object_class_init), (gst_object_ref),
(gst_object_unref), (gst_object_sink), (gst_object_dispose),
(gst_object_dispatch_properties_changed), (gst_object_set_name),
(gst_object_set_parent), (gst_object_unparent),
(gst_object_check_uniqueness):
* gst/gstobject.h:
Docs updates, clean up some headers.
Free iterators in GstBin.
GstObject is now looking good.
2005-03-08 14:38:06 +00:00
|
|
|
gst_iterator_free (children);
|
2005-03-07 18:27:42 +00:00
|
|
|
|
|
|
|
return GST_ELEMENT_CAST (result);
|
2003-12-16 19:35:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_bin_get_all_by_interface:
|
|
|
|
* @bin: bin to find elements in
|
|
|
|
* @interface: interface to be implemented by interface
|
|
|
|
*
|
2004-07-09 08:45:18 +00:00
|
|
|
* Looks for all elements inside the bin that implements the given
|
2003-12-16 19:35:26 +00:00
|
|
|
* interface. You can safely cast all returned elements to the given interface.
|
2005-03-07 18:27:42 +00:00
|
|
|
* The function recurses bins inside bins. The iterator will return a series
|
2005-06-27 08:16:51 +00:00
|
|
|
* of #GstElement that should be unreffed after use.
|
2003-12-16 19:35:26 +00:00
|
|
|
*
|
2005-03-10 12:51:45 +00:00
|
|
|
* MT safe.
|
2005-06-27 08:16:51 +00:00
|
|
|
*
|
|
|
|
* Returns: A #GstIterator for the elements inside the bin implementing the
|
|
|
|
* given interface.
|
2003-12-16 19:35:26 +00:00
|
|
|
*/
|
2005-03-07 18:27:42 +00:00
|
|
|
GstIterator *
|
|
|
|
gst_bin_iterate_all_by_interface (GstBin * bin, GType interface)
|
2003-12-16 19:35:26 +00:00
|
|
|
{
|
2005-03-07 18:27:42 +00:00
|
|
|
GstIterator *children;
|
|
|
|
GstIterator *result;
|
2004-03-13 15:27:01 +00:00
|
|
|
|
2003-12-16 19:35:26 +00:00
|
|
|
g_return_val_if_fail (GST_IS_BIN (bin), NULL);
|
|
|
|
|
2005-03-07 18:27:42 +00:00
|
|
|
children = gst_bin_iterate_recurse (bin);
|
|
|
|
result = gst_iterator_filter (children, (GCompareFunc) compare_interface,
|
|
|
|
GINT_TO_POINTER (interface));
|
|
|
|
|
|
|
|
return result;
|
2003-12-16 19:35:26 +00:00
|
|
|
}
|
|
|
|
|
2001-06-25 06:45:56 +00:00
|
|
|
#ifndef GST_DISABLE_LOADSAVE
|
2001-01-20 03:10:44 +00:00
|
|
|
static xmlNodePtr
|
2001-12-15 22:37:35 +00:00
|
|
|
gst_bin_save_thyself (GstObject * object, xmlNodePtr parent)
|
2000-11-04 18:54:07 +00:00
|
|
|
{
|
2001-01-29 00:06:02 +00:00
|
|
|
GstBin *bin = GST_BIN (object);
|
|
|
|
xmlNodePtr childlist, elementnode;
|
2000-01-30 09:03:00 +00:00
|
|
|
GList *children;
|
|
|
|
GstElement *child;
|
|
|
|
|
2001-01-29 00:06:02 +00:00
|
|
|
if (GST_OBJECT_CLASS (parent_class)->save_thyself)
|
|
|
|
GST_OBJECT_CLASS (parent_class)->save_thyself (GST_OBJECT (bin), parent);
|
2000-01-30 09:03:00 +00:00
|
|
|
|
GCC 4 fixen.
Original commit message from CVS:
2005-05-04 Andy Wingo <wingo@pobox.com>
* check/Makefile.am:
* docs/gst/tmpl/gstatomic.sgml:
* docs/gst/tmpl/gstplugin.sgml:
* gst/base/gstbasesink.c: (gst_basesink_activate):
* gst/base/gstbasesrc.c: (gst_basesrc_class_init),
(gst_basesrc_init), (gst_basesrc_set_dataflow_funcs),
(gst_basesrc_query), (gst_basesrc_set_property),
(gst_basesrc_get_property), (gst_basesrc_check_get_range),
(gst_basesrc_activate):
* gst/base/gstbasesrc.h:
* gst/base/gstbasetransform.c: (gst_base_transform_sink_activate),
(gst_base_transform_src_activate):
* gst/elements/gstelements.c:
* gst/elements/gstfakesrc.c: (gst_fakesrc_class_init),
(gst_fakesrc_set_property), (gst_fakesrc_get_property):
* gst/elements/gsttee.c: (gst_tee_sink_activate):
* gst/elements/gsttypefindelement.c: (find_element_get_length),
(gst_type_find_element_checkgetrange),
(gst_type_find_element_activate):
* gst/gstbin.c: (gst_bin_save_thyself), (gst_bin_restore_thyself):
* gst/gstcaps.c: (gst_caps_do_simplify), (gst_caps_save_thyself),
(gst_caps_load_thyself):
* gst/gstelement.c: (gst_element_pads_activate),
(gst_element_save_thyself), (gst_element_restore_thyself):
* gst/gstpad.c: (gst_pad_load_and_link), (gst_pad_save_thyself),
(gst_ghost_pad_save_thyself), (gst_pad_check_pull_range):
* gst/gstpad.h:
* gst/gstxml.c: (gst_xml_write), (gst_xml_parse_doc),
(gst_xml_parse_file), (gst_xml_parse_memory),
(gst_xml_get_element), (gst_xml_make_element):
* gst/indexers/gstfileindex.c: (gst_file_index_load),
(_file_index_id_save_xml), (gst_file_index_commit):
* gst/registries/gstlibxmlregistry.c: (read_string), (read_uint),
(read_enum), (load_pad_template), (load_feature), (load_plugin),
(load_paths):
* libs/gst/dataprotocol/dataprotocol.c: (gst_dp_packet_from_caps),
(gst_dp_packet_from_event), (gst_dp_caps_from_packet):
* tools/gst-complete.c: (main):
* tools/gst-compprep.c: (main):
* tools/gst-inspect.c: (print_element_properties_info):
* tools/gst-launch.c: (xmllaunch_parse_cmdline):
* tools/gst-xmlinspect.c: (print_element_properties):
GCC 4 fixen.
2005-05-04 21:29:44 +00:00
|
|
|
childlist = xmlNewChild (parent, NULL, (xmlChar *) "children", NULL);
|
2000-01-30 09:03:00 +00:00
|
|
|
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_CAT_INFO (GST_CAT_XML, "[%s]: saving %d children",
|
|
|
|
GST_ELEMENT_NAME (bin), bin->numchildren);
|
2000-12-30 02:41:15 +00:00
|
|
|
|
2000-01-30 09:03:00 +00:00
|
|
|
children = bin->children;
|
|
|
|
while (children) {
|
2000-11-04 18:54:07 +00:00
|
|
|
child = GST_ELEMENT (children->data);
|
GCC 4 fixen.
Original commit message from CVS:
2005-05-04 Andy Wingo <wingo@pobox.com>
* check/Makefile.am:
* docs/gst/tmpl/gstatomic.sgml:
* docs/gst/tmpl/gstplugin.sgml:
* gst/base/gstbasesink.c: (gst_basesink_activate):
* gst/base/gstbasesrc.c: (gst_basesrc_class_init),
(gst_basesrc_init), (gst_basesrc_set_dataflow_funcs),
(gst_basesrc_query), (gst_basesrc_set_property),
(gst_basesrc_get_property), (gst_basesrc_check_get_range),
(gst_basesrc_activate):
* gst/base/gstbasesrc.h:
* gst/base/gstbasetransform.c: (gst_base_transform_sink_activate),
(gst_base_transform_src_activate):
* gst/elements/gstelements.c:
* gst/elements/gstfakesrc.c: (gst_fakesrc_class_init),
(gst_fakesrc_set_property), (gst_fakesrc_get_property):
* gst/elements/gsttee.c: (gst_tee_sink_activate):
* gst/elements/gsttypefindelement.c: (find_element_get_length),
(gst_type_find_element_checkgetrange),
(gst_type_find_element_activate):
* gst/gstbin.c: (gst_bin_save_thyself), (gst_bin_restore_thyself):
* gst/gstcaps.c: (gst_caps_do_simplify), (gst_caps_save_thyself),
(gst_caps_load_thyself):
* gst/gstelement.c: (gst_element_pads_activate),
(gst_element_save_thyself), (gst_element_restore_thyself):
* gst/gstpad.c: (gst_pad_load_and_link), (gst_pad_save_thyself),
(gst_ghost_pad_save_thyself), (gst_pad_check_pull_range):
* gst/gstpad.h:
* gst/gstxml.c: (gst_xml_write), (gst_xml_parse_doc),
(gst_xml_parse_file), (gst_xml_parse_memory),
(gst_xml_get_element), (gst_xml_make_element):
* gst/indexers/gstfileindex.c: (gst_file_index_load),
(_file_index_id_save_xml), (gst_file_index_commit):
* gst/registries/gstlibxmlregistry.c: (read_string), (read_uint),
(read_enum), (load_pad_template), (load_feature), (load_plugin),
(load_paths):
* libs/gst/dataprotocol/dataprotocol.c: (gst_dp_packet_from_caps),
(gst_dp_packet_from_event), (gst_dp_caps_from_packet):
* tools/gst-complete.c: (main):
* tools/gst-compprep.c: (main):
* tools/gst-inspect.c: (print_element_properties_info):
* tools/gst-launch.c: (xmllaunch_parse_cmdline):
* tools/gst-xmlinspect.c: (print_element_properties):
GCC 4 fixen.
2005-05-04 21:29:44 +00:00
|
|
|
elementnode = xmlNewChild (childlist, NULL, (xmlChar *) "element", NULL);
|
2001-01-29 00:06:02 +00:00
|
|
|
gst_object_save_thyself (GST_OBJECT (child), elementnode);
|
2000-11-04 18:54:07 +00:00
|
|
|
children = g_list_next (children);
|
2000-01-30 09:03:00 +00:00
|
|
|
}
|
2000-09-27 19:33:10 +00:00
|
|
|
return childlist;
|
|
|
|
}
|
|
|
|
|
2001-01-20 03:10:44 +00:00
|
|
|
static void
|
2001-12-15 22:37:35 +00:00
|
|
|
gst_bin_restore_thyself (GstObject * object, xmlNodePtr self)
|
2000-11-04 18:54:07 +00:00
|
|
|
{
|
2001-01-29 00:06:02 +00:00
|
|
|
GstBin *bin = GST_BIN (object);
|
|
|
|
xmlNodePtr field = self->xmlChildrenNode;
|
2000-09-27 19:33:10 +00:00
|
|
|
xmlNodePtr childlist;
|
|
|
|
|
|
|
|
while (field) {
|
GCC 4 fixen.
Original commit message from CVS:
2005-05-04 Andy Wingo <wingo@pobox.com>
* check/Makefile.am:
* docs/gst/tmpl/gstatomic.sgml:
* docs/gst/tmpl/gstplugin.sgml:
* gst/base/gstbasesink.c: (gst_basesink_activate):
* gst/base/gstbasesrc.c: (gst_basesrc_class_init),
(gst_basesrc_init), (gst_basesrc_set_dataflow_funcs),
(gst_basesrc_query), (gst_basesrc_set_property),
(gst_basesrc_get_property), (gst_basesrc_check_get_range),
(gst_basesrc_activate):
* gst/base/gstbasesrc.h:
* gst/base/gstbasetransform.c: (gst_base_transform_sink_activate),
(gst_base_transform_src_activate):
* gst/elements/gstelements.c:
* gst/elements/gstfakesrc.c: (gst_fakesrc_class_init),
(gst_fakesrc_set_property), (gst_fakesrc_get_property):
* gst/elements/gsttee.c: (gst_tee_sink_activate):
* gst/elements/gsttypefindelement.c: (find_element_get_length),
(gst_type_find_element_checkgetrange),
(gst_type_find_element_activate):
* gst/gstbin.c: (gst_bin_save_thyself), (gst_bin_restore_thyself):
* gst/gstcaps.c: (gst_caps_do_simplify), (gst_caps_save_thyself),
(gst_caps_load_thyself):
* gst/gstelement.c: (gst_element_pads_activate),
(gst_element_save_thyself), (gst_element_restore_thyself):
* gst/gstpad.c: (gst_pad_load_and_link), (gst_pad_save_thyself),
(gst_ghost_pad_save_thyself), (gst_pad_check_pull_range):
* gst/gstpad.h:
* gst/gstxml.c: (gst_xml_write), (gst_xml_parse_doc),
(gst_xml_parse_file), (gst_xml_parse_memory),
(gst_xml_get_element), (gst_xml_make_element):
* gst/indexers/gstfileindex.c: (gst_file_index_load),
(_file_index_id_save_xml), (gst_file_index_commit):
* gst/registries/gstlibxmlregistry.c: (read_string), (read_uint),
(read_enum), (load_pad_template), (load_feature), (load_plugin),
(load_paths):
* libs/gst/dataprotocol/dataprotocol.c: (gst_dp_packet_from_caps),
(gst_dp_packet_from_event), (gst_dp_caps_from_packet):
* tools/gst-complete.c: (main):
* tools/gst-compprep.c: (main):
* tools/gst-inspect.c: (print_element_properties_info):
* tools/gst-launch.c: (xmllaunch_parse_cmdline):
* tools/gst-xmlinspect.c: (print_element_properties):
GCC 4 fixen.
2005-05-04 21:29:44 +00:00
|
|
|
if (!strcmp ((char *) field->name, "children")) {
|
2004-03-13 15:27:01 +00:00
|
|
|
GST_CAT_INFO (GST_CAT_XML, "[%s]: loading children",
|
2004-03-15 19:27:17 +00:00
|
|
|
GST_ELEMENT_NAME (object));
|
2001-01-18 11:16:53 +00:00
|
|
|
childlist = field->xmlChildrenNode;
|
2000-09-27 19:33:10 +00:00
|
|
|
while (childlist) {
|
GCC 4 fixen.
Original commit message from CVS:
2005-05-04 Andy Wingo <wingo@pobox.com>
* check/Makefile.am:
* docs/gst/tmpl/gstatomic.sgml:
* docs/gst/tmpl/gstplugin.sgml:
* gst/base/gstbasesink.c: (gst_basesink_activate):
* gst/base/gstbasesrc.c: (gst_basesrc_class_init),
(gst_basesrc_init), (gst_basesrc_set_dataflow_funcs),
(gst_basesrc_query), (gst_basesrc_set_property),
(gst_basesrc_get_property), (gst_basesrc_check_get_range),
(gst_basesrc_activate):
* gst/base/gstbasesrc.h:
* gst/base/gstbasetransform.c: (gst_base_transform_sink_activate),
(gst_base_transform_src_activate):
* gst/elements/gstelements.c:
* gst/elements/gstfakesrc.c: (gst_fakesrc_class_init),
(gst_fakesrc_set_property), (gst_fakesrc_get_property):
* gst/elements/gsttee.c: (gst_tee_sink_activate):
* gst/elements/gsttypefindelement.c: (find_element_get_length),
(gst_type_find_element_checkgetrange),
(gst_type_find_element_activate):
* gst/gstbin.c: (gst_bin_save_thyself), (gst_bin_restore_thyself):
* gst/gstcaps.c: (gst_caps_do_simplify), (gst_caps_save_thyself),
(gst_caps_load_thyself):
* gst/gstelement.c: (gst_element_pads_activate),
(gst_element_save_thyself), (gst_element_restore_thyself):
* gst/gstpad.c: (gst_pad_load_and_link), (gst_pad_save_thyself),
(gst_ghost_pad_save_thyself), (gst_pad_check_pull_range):
* gst/gstpad.h:
* gst/gstxml.c: (gst_xml_write), (gst_xml_parse_doc),
(gst_xml_parse_file), (gst_xml_parse_memory),
(gst_xml_get_element), (gst_xml_make_element):
* gst/indexers/gstfileindex.c: (gst_file_index_load),
(_file_index_id_save_xml), (gst_file_index_commit):
* gst/registries/gstlibxmlregistry.c: (read_string), (read_uint),
(read_enum), (load_pad_template), (load_feature), (load_plugin),
(load_paths):
* libs/gst/dataprotocol/dataprotocol.c: (gst_dp_packet_from_caps),
(gst_dp_packet_from_event), (gst_dp_caps_from_packet):
* tools/gst-complete.c: (main):
* tools/gst-compprep.c: (main):
* tools/gst-inspect.c: (print_element_properties_info):
* tools/gst-launch.c: (xmllaunch_parse_cmdline):
* tools/gst-xmlinspect.c: (print_element_properties):
GCC 4 fixen.
2005-05-04 21:29:44 +00:00
|
|
|
if (!strcmp ((char *) childlist->name, "element")) {
|
2004-03-15 19:27:17 +00:00
|
|
|
GstElement *element =
|
|
|
|
gst_xml_make_element (childlist, GST_OBJECT (bin));
|
|
|
|
|
|
|
|
/* it had to be parented to find the pads, now we ref and unparent so
|
|
|
|
* we can add it to the bin */
|
|
|
|
gst_object_ref (GST_OBJECT (element));
|
|
|
|
gst_object_unparent (GST_OBJECT (element));
|
|
|
|
|
|
|
|
gst_bin_add (bin, element);
|
|
|
|
}
|
|
|
|
childlist = childlist->next;
|
2000-09-27 19:33:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
field = field->next;
|
|
|
|
}
|
2004-07-04 10:26:24 +00:00
|
|
|
if (GST_OBJECT_CLASS (parent_class)->restore_thyself)
|
|
|
|
(GST_OBJECT_CLASS (parent_class)->restore_thyself) (object, self);
|
2000-01-30 09:03:00 +00:00
|
|
|
}
|
2001-10-17 10:21:27 +00:00
|
|
|
#endif /* GST_DISABLE_LOADSAVE */
|