source: trunk/third/gstreamer/gst/gstobject.c @ 21448

Revision 21448, 23.1 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21447, which included commits to RCS files with non-trunk default branches.
RevLine 
[18713]1/* GStreamer
2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 *                    2000 Wim Taymans <wtay@chello.be>
4 *
5 * gstobject.c: Fundamental class used for all of GStreamer
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23#include "gst_private.h"
24
25#include "gstobject.h"
[21004]26#include "gstmarshal.h"
27#include "gstinfo.h"
[18713]28
[21004]29#ifndef GST_DISABLE_TRACE
30#include "gsttrace.h"
31#endif
32
[18713]33/* Object signals and args */
[21004]34enum
35{
[18713]36  PARENT_SET,
37  PARENT_UNSET,
38#ifndef GST_DISABLE_LOADSAVE_REGISTRY
39  OBJECT_SAVED,
40#endif
41  DEEP_NOTIFY,
42  LAST_SIGNAL
43};
44
[21004]45enum
46{
[18713]47  ARG_0,
[21004]48  ARG_NAME
49      /* FILL ME */
[18713]50};
51
[21004]52enum
53{
[18713]54  SO_OBJECT_LOADED,
55  SO_LAST_SIGNAL
56};
57
58GType _gst_object_type = 0;
59static GHashTable *object_name_counts = NULL;
[21004]60
[18713]61G_LOCK_DEFINE_STATIC (object_name_mutex);
62
63typedef struct _GstSignalObject GstSignalObject;
64typedef struct _GstSignalObjectClass GstSignalObjectClass;
65
[21004]66static GType gst_signal_object_get_type (void);
67static void gst_signal_object_class_init (GstSignalObjectClass * klass);
68static void gst_signal_object_init (GstSignalObject * object);
[18713]69
[21004]70#ifndef GST_DISABLE_LOADSAVE_REGISTRY
[18713]71static guint gst_signal_object_signals[SO_LAST_SIGNAL] = { 0 };
[21004]72#endif
[18713]73
[21004]74static void gst_object_class_init (GstObjectClass * klass);
75static void gst_object_init (GstObject * object);
[18713]76
[21004]77#ifndef GST_DISABLE_TRACE
78static GObject *gst_object_constructor (GType type,
79    guint n_construct_properties, GObjectConstructParam * construct_params);
80#endif
[18713]81
[21004]82static void gst_object_set_property (GObject * object, guint prop_id,
83    const GValue * value, GParamSpec * pspec);
84static void gst_object_get_property (GObject * object, guint prop_id,
85    GValue * value, GParamSpec * pspec);
86static void gst_object_dispatch_properties_changed (GObject * object,
87    guint n_pspecs, GParamSpec ** pspecs);
[18713]88
[21004]89static void gst_object_dispose (GObject * object);
90static void gst_object_finalize (GObject * object);
91
[18713]92#ifndef GST_DISABLE_LOADSAVE_REGISTRY
[21004]93static void gst_object_real_restore_thyself (GstObject * object,
94    xmlNodePtr self);
[18713]95#endif
96
97static GObjectClass *parent_class = NULL;
98static guint gst_object_signals[LAST_SIGNAL] = { 0 };
99
100GType
101gst_object_get_type (void)
102{
103  if (!_gst_object_type) {
104    static const GTypeInfo object_info = {
105      sizeof (GstObjectClass),
106      NULL,
107      NULL,
108      (GClassInitFunc) gst_object_class_init,
109      NULL,
110      NULL,
111      sizeof (GstObject),
[21004]112      0,
[18713]113      (GInstanceInitFunc) gst_object_init,
114      NULL
115    };
[21004]116
117    _gst_object_type =
118        g_type_register_static (G_TYPE_OBJECT, "GstObject", &object_info,
119        G_TYPE_FLAG_ABSTRACT);
[18713]120  }
121  return _gst_object_type;
122}
123
124static void
[21004]125gst_object_class_init (GstObjectClass * klass)
[18713]126{
127  GObjectClass *gobject_class;
128
[21004]129  gobject_class = (GObjectClass *) klass;
[18713]130
131  parent_class = g_type_class_ref (G_TYPE_OBJECT);
132
133  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_object_set_property);
134  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_object_get_property);
135
136  g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NAME,
[21004]137      g_param_spec_string ("name", "Name", "The name of the object",
138          NULL, G_PARAM_READWRITE));
[18713]139
140  gst_object_signals[PARENT_SET] =
[21004]141      g_signal_new ("parent-set", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
142      G_STRUCT_OFFSET (GstObjectClass, parent_set), NULL, NULL,
143      g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT);
[18713]144  gst_object_signals[PARENT_UNSET] =
[21004]145      g_signal_new ("parent-unset", G_TYPE_FROM_CLASS (klass),
146      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstObjectClass, parent_unset), NULL,
147      NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_OBJECT);
[18713]148#ifndef GST_DISABLE_LOADSAVE_REGISTRY
[21004]149  /* FIXME This should be the GType of xmlNodePtr instead of G_TYPE_POINTER */
[18713]150  gst_object_signals[OBJECT_SAVED] =
[21004]151      g_signal_new ("object-saved", G_TYPE_FROM_CLASS (klass),
152      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstObjectClass, object_saved), NULL,
153      NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
154
[18713]155  klass->restore_thyself = gst_object_real_restore_thyself;
156#endif
157  gst_object_signals[DEEP_NOTIFY] =
[21004]158      g_signal_new ("deep-notify", G_TYPE_FROM_CLASS (klass),
159      G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED |
160      G_SIGNAL_NO_HOOKS, G_STRUCT_OFFSET (GstObjectClass, deep_notify), NULL,
161      NULL, gst_marshal_VOID__OBJECT_PARAM, G_TYPE_NONE, 2, G_TYPE_OBJECT,
162      G_TYPE_PARAM);
[18713]163
164  klass->path_string_separator = "/";
165
166  klass->signal_object = g_object_new (gst_signal_object_get_type (), NULL);
167
[21004]168  /* see the comments at gst_object_dispatch_properties_changed */
[18713]169  gobject_class->dispatch_properties_changed
[21004]170      = GST_DEBUG_FUNCPTR (gst_object_dispatch_properties_changed);
[18713]171
172  gobject_class->dispose = gst_object_dispose;
173  gobject_class->finalize = gst_object_finalize;
[21004]174#ifndef GST_DISABLE_TRACE
175  gobject_class->constructor = gst_object_constructor;
176#endif
[18713]177}
178
179static void
[21004]180gst_object_init (GstObject * object)
[18713]181{
[21004]182  object->lock = g_mutex_new ();
[18713]183  object->parent = NULL;
184  object->name = NULL;
185
186  object->flags = 0;
187  GST_FLAG_SET (object, GST_FLOATING);
188}
189
[21004]190#ifndef GST_DISABLE_TRACE
191static GObject *
192gst_object_constructor (GType type, guint n_construct_properties,
193    GObjectConstructParam * construct_params)
194{
195  const gchar *name;
196  GstAllocTrace *trace;
197  GObject *obj =
198      G_OBJECT_CLASS (parent_class)->constructor (type, n_construct_properties,
199      construct_params);
200
201  name = g_type_name (type);
202
203  trace = gst_alloc_trace_get (name);
204  if (!trace) {
205    trace = gst_alloc_trace_register (name);
206  }
207  gst_alloc_trace_new (trace, obj);
208
209  return obj;
210}
211#endif
[18713]212/**
213 * gst_object_ref:
214 * @object: GstObject to reference
215 *
216 * Increments the refence count on the object.
217 *
218 * Returns: A pointer to the object
219 */
[21004]220GstObject *
221gst_object_ref (GstObject * object)
[18713]222{
223  g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
224
[21004]225  GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "ref %d->%d",
226      G_OBJECT (object)->ref_count, G_OBJECT (object)->ref_count + 1);
[18713]227
228  g_object_ref (G_OBJECT (object));
229  return object;
230}
231
232/**
233 * gst_object_unref:
234 * @object: GstObject to unreference
235 *
236 * Decrements the refence count on the object.  If reference count hits
237 * zero, destroy the object.
238 */
239void
[21004]240gst_object_unref (GstObject * object)
[18713]241{
242  g_return_if_fail (GST_IS_OBJECT (object));
243  g_return_if_fail (G_OBJECT (object)->ref_count > 0);
244
[21004]245  GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "unref %d->%d",
246      G_OBJECT (object)->ref_count, G_OBJECT (object)->ref_count - 1);
[18713]247
248  g_object_unref (G_OBJECT (object));
249}
250
251/**
252 * gst_object_sink:
253 * @object: GstObject to sink
254 *
255 * Removes floating reference on an object.  Any newly created object has
256 * a refcount of 1 and is FLOATING.  This function should be used when
[21004]257 * creating a new object to symbolically 'take ownership' of the object.
[18713]258 * Use #gst_object_set_parent to have this done for you.
259 */
260void
[21004]261gst_object_sink (GstObject * object)
[18713]262{
263  g_return_if_fail (object != NULL);
264  g_return_if_fail (GST_IS_OBJECT (object));
265
[21004]266  GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "sink");
[18713]267
268  if (GST_OBJECT_FLOATING (object)) {
269    GST_FLAG_UNSET (object, GST_FLOATING);
270    gst_object_unref (object);
271  }
272}
273
274/**
[21004]275 * gst_object_replace:
[18713]276 * @oldobj: pointer to place of old GstObject
277 * @newobj: new GstObject
278 *
279 * Unrefs the object pointer to by oldobj, refs the newobj and
280 * puts the newobj in *oldobj.
281 */
282void
[21004]283gst_object_replace (GstObject ** oldobj, GstObject * newobj)
[18713]284{
[21004]285  g_return_if_fail (oldobj != NULL);
286  g_return_if_fail (*oldobj == NULL || GST_IS_OBJECT (*oldobj));
287  g_return_if_fail (newobj == NULL || GST_IS_OBJECT (newobj));
288
289  GST_CAT_LOG (GST_CAT_REFCOUNTING, "replace %s (%d) with %s (%d)",
290      *oldobj ? GST_STR_NULL (GST_OBJECT_NAME (*oldobj)) : "(NONE)",
291      *oldobj ? G_OBJECT (*oldobj)->ref_count : 0,
292      newobj ? GST_STR_NULL (GST_OBJECT_NAME (newobj)) : "(NONE)",
293      newobj ? G_OBJECT (newobj)->ref_count : 0);
294
[18713]295  if (*oldobj != newobj) {
296    if (newobj)
297      gst_object_ref (newobj);
298    if (*oldobj)
299      gst_object_unref (*oldobj);
300
301    *oldobj = newobj;
302  }
303}
304
[21004]305static void
306gst_object_dispose (GObject * object)
[18713]307{
[21004]308  GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose");
[18713]309
310  GST_FLAG_SET (GST_OBJECT (object), GST_DESTROYED);
311  GST_OBJECT_PARENT (object) = NULL;
312
313  parent_class->dispose (object);
314}
315
[21004]316/* finalize is called when the object has to free its resources */
[18713]317static void
[21004]318gst_object_finalize (GObject * object)
[18713]319{
320  GstObject *gstobject = GST_OBJECT (object);
321
[21004]322  GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "finalize");
[18713]323
324  g_signal_handlers_destroy (object);
325
[21004]326  g_free (gstobject->name);
[18713]327
328  g_mutex_free (gstobject->lock);
329
[21004]330#ifndef GST_DISABLE_TRACE
331  {
332    const gchar *name;
333    GstAllocTrace *trace;
334
335    name = g_type_name (G_OBJECT_TYPE (object));
336    trace = gst_alloc_trace_get (name);
337    g_assert (trace);
338    gst_alloc_trace_free (trace, object);
339  }
340#endif
341
[18713]342  parent_class->finalize (object);
343}
344
[21004]345/* Changing a GObject property of a GstObject will result in "deep_notify"
346 * signals being emitted by the object itself, as well as in each parent
347 * object. This is so that an application can connect a listener to the
[18713]348 * top-level bin to catch property-change notifications for all contained
349 * elements. */
350static void
[21004]351gst_object_dispatch_properties_changed (GObject * object,
352    guint n_pspecs, GParamSpec ** pspecs)
[18713]353{
354  GstObject *gst_object;
355  guint i;
356
357  /* do the standard dispatching */
[21004]358  G_OBJECT_CLASS (parent_class)->dispatch_properties_changed (object, n_pspecs,
359      pspecs);
[18713]360
361  /* now let the parent dispatch those, too */
362  gst_object = GST_OBJECT_PARENT (object);
363  while (gst_object) {
364    /* need own category? */
365    for (i = 0; i < n_pspecs; i++) {
[21447]366      GST_CAT_LOG (GST_CAT_SIGNAL, "deep notification from %s to %s (%s)",
[21004]367          GST_OBJECT_NAME (object) ? GST_OBJECT_NAME (object) : "(null)",
368          GST_OBJECT_NAME (gst_object) ? GST_OBJECT_NAME (gst_object) :
369          "(null)", pspecs[i]->name);
370      g_signal_emit (gst_object, gst_object_signals[DEEP_NOTIFY],
371          g_quark_from_string (pspecs[i]->name), (GstObject *) object,
372          pspecs[i]);
[18713]373    }
374
375    gst_object = GST_OBJECT_PARENT (gst_object);
376  }
377}
378
379/**
380 * gst_object_default_deep_notify:
381 * @object: the #GObject that signalled the notify.
382 * @orig: a #GstObject that initiated the notify.
383 * @pspec: a #GParamSpec of the property.
384 * @excluded_props: a set of user-specified properties to exclude or
385 *  NULL to show all changes.
386 *
387 * Adds a default deep_notify signal callback to an
388 * element. The user data should contain a pointer to an array of
389 * strings that should be excluded from the notify.
390 * The default handler will print the new value of the property
391 * using g_print.
392 */
393void
[21004]394gst_object_default_deep_notify (GObject * object, GstObject * orig,
395    GParamSpec * pspec, gchar ** excluded_props)
[18713]396{
[21004]397  GValue value = { 0, };        /* the important thing is that value.type = 0 */
[21447]398  gchar *str = NULL;
[18713]399  gchar *name = NULL;
400
401  if (pspec->flags & G_PARAM_READABLE) {
402    /* let's not print these out for excluded properties... */
403    while (excluded_props != NULL && *excluded_props != NULL) {
404      if (strcmp (pspec->name, *excluded_props) == 0)
405        return;
406      excluded_props++;
407    }
408    g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
409    g_object_get_property (G_OBJECT (orig), pspec->name, &value);
410
411    if (G_IS_PARAM_SPEC_ENUM (pspec)) {
412      GEnumValue *enum_value;
413
[21004]414      enum_value =
415          g_enum_get_value (G_ENUM_CLASS (g_type_class_ref (pspec->value_type)),
416          g_value_get_enum (&value));
417
[18713]418      str = g_strdup_printf ("%s (%d)", enum_value->value_nick,
[21004]419          enum_value->value);
420    } else {
[18713]421      str = g_strdup_value_contents (&value);
422    }
423    name = gst_object_get_path_string (orig);
424    g_print ("%s: %s = %s\n", name, pspec->name, str);
425    g_free (name);
426    g_free (str);
427    g_value_unset (&value);
428  } else {
429    name = gst_object_get_path_string (orig);
[21004]430    g_warning ("Parameter %s not readable in %s.", pspec->name, name);
[18713]431    g_free (name);
432  }
433}
434
435static void
[21004]436gst_object_set_name_default (GstObject * object)
[18713]437{
438  gint count;
439  gchar *name, *tmp;
440  const gchar *type_name;
[21004]441
[18713]442  type_name = G_OBJECT_TYPE_NAME (object);
443
444  /* to ensure guaranteed uniqueness across threads, only one thread
445   * may ever assign a name */
446  G_LOCK (object_name_mutex);
447
[21004]448  if (!object_name_counts) {
449    object_name_counts = g_hash_table_new_full (g_str_hash, g_str_equal,
450        g_free, NULL);
451  }
[18713]452
453  count = GPOINTER_TO_INT (g_hash_table_lookup (object_name_counts, type_name));
[21004]454  g_hash_table_insert (object_name_counts, g_strdup (type_name),
455      GINT_TO_POINTER (count + 1));
456
[18713]457  G_UNLOCK (object_name_mutex);
458
459  /* GstFooSink -> foosinkN */
460  if (strncmp (type_name, "Gst", 3) == 0)
461    type_name += 3;
462  tmp = g_strdup_printf ("%s%d", type_name, count);
463  name = g_ascii_strdown (tmp, strlen (tmp));
464  g_free (tmp);
[21004]465
[18713]466  gst_object_set_name (object, name);
467  g_free (name);
468}
469
470/**
471 * gst_object_set_name:
472 * @object: GstObject to set the name of
473 * @name: new name of object
474 *
475 * Sets the name of the object, or gives the element a guaranteed unique
476 * name (if @name is NULL).
477 */
478void
[21004]479gst_object_set_name (GstObject * object, const gchar * name)
[18713]480{
481  g_return_if_fail (object != NULL);
482  g_return_if_fail (GST_IS_OBJECT (object));
483
484  if (object->name != NULL)
485    g_free (object->name);
486
487  if (name != NULL)
488    object->name = g_strdup (name);
489  else
490    gst_object_set_name_default (object);
491}
492
493/**
494 * gst_object_get_name:
495 * @object: GstObject to get the name of
496 *
497 * Get the name of the object.
498 *
499 * Returns: name of the object
500 */
[21004]501const gchar *
502gst_object_get_name (GstObject * object)
[18713]503{
504  g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
505
506  return object->name;
507}
508
509/**
510 * gst_object_set_parent:
511 * @object: GstObject to set parent of
512 * @parent: new parent of object
513 *
[21004]514 * Sets the parent of @object. The object's reference count will be incremented,
515 * and any floating reference will be removed (see gst_object_sink()).
516 *
517 * Causes the parent-set signal to be emitted.
[18713]518 */
519void
[21004]520gst_object_set_parent (GstObject * object, GstObject * parent)
[18713]521{
522  g_return_if_fail (object != NULL);
523  g_return_if_fail (GST_IS_OBJECT (object));
524  g_return_if_fail (parent != NULL);
525  g_return_if_fail (GST_IS_OBJECT (parent));
526  g_return_if_fail (object != parent);
[21004]527  g_return_if_fail (object->parent == NULL);
[18713]528
[21004]529  GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "set parent (ref and sink)");
[18713]530  gst_object_ref (object);
531  gst_object_sink (object);
532  object->parent = parent;
533
534  g_signal_emit (G_OBJECT (object), gst_object_signals[PARENT_SET], 0, parent);
535}
536
537/**
538 * gst_object_get_parent:
539 * @object: GstObject to get parent of
540 *
[21004]541 * Returns the parent of @object.
[18713]542 *
543 * Returns: parent of the object
544 */
[21004]545GstObject *
546gst_object_get_parent (GstObject * object)
[18713]547{
548  g_return_val_if_fail (object != NULL, NULL);
549  g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
550
551  return object->parent;
552}
553
554/**
555 * gst_object_unparent:
556 * @object: GstObject to unparent
557 *
[21004]558 * Clear the parent of @object, removing the associated reference.
[18713]559 */
560void
[21004]561gst_object_unparent (GstObject * object)
[18713]562{
563  g_return_if_fail (object != NULL);
[21004]564  g_return_if_fail (GST_IS_OBJECT (object));
[18713]565  if (object->parent == NULL)
566    return;
567
[21004]568  GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "unparent");
[18713]569
[21004]570  g_signal_emit (G_OBJECT (object), gst_object_signals[PARENT_UNSET], 0,
571      object->parent);
572
[18713]573  object->parent = NULL;
574  gst_object_unref (object);
575}
576
577/**
578 * gst_object_check_uniqueness:
579 * @list: a list of #GstObject to check through
580 * @name: the name to search for
581 *
[21004]582 * Checks to see if there is any object named @name in @list.
[18713]583 *
[21004]584 * Returns: TRUE if the name does not appear in the list, FALSE if it does.
[18713]585 */
586gboolean
[21004]587gst_object_check_uniqueness (GList * list, const gchar * name)
[18713]588{
589  g_return_val_if_fail (name != NULL, FALSE);
590
591  while (list) {
592    GstObject *child = GST_OBJECT (list->data);
593
594    list = g_list_next (list);
[21004]595
596    if (strcmp (GST_OBJECT_NAME (child), name) == 0)
[18713]597      return FALSE;
598  }
599
600  return TRUE;
601}
602
603
604#ifndef GST_DISABLE_LOADSAVE_REGISTRY
605/**
606 * gst_object_save_thyself:
607 * @object: GstObject to save
608 * @parent: The parent XML node to save the object into
609 *
610 * Saves the given object into the parent XML node.
611 *
612 * Returns: the new xmlNodePtr with the saved object
613 */
614xmlNodePtr
[21004]615gst_object_save_thyself (GstObject * object, xmlNodePtr parent)
[18713]616{
617  GstObjectClass *oclass;
618
619  g_return_val_if_fail (object != NULL, parent);
620  g_return_val_if_fail (GST_IS_OBJECT (object), parent);
621  g_return_val_if_fail (parent != NULL, parent);
622
623  oclass = GST_OBJECT_GET_CLASS (object);
624
625  if (oclass->save_thyself)
626    oclass->save_thyself (object, parent);
627
[21004]628  g_signal_emit (G_OBJECT (object), gst_object_signals[OBJECT_SAVED], 0,
629      parent);
[18713]630
631  return parent;
632}
633
634/**
635 * gst_object_restore_thyself:
636 * @object: GstObject to load into
637 * @self: The XML node to load the object from
638 *
639 * Restores the given object with the data from the parent XML node.
640 */
641void
[21004]642gst_object_restore_thyself (GstObject * object, xmlNodePtr self)
[18713]643{
644  GstObjectClass *oclass;
645
646  g_return_if_fail (object != NULL);
647  g_return_if_fail (GST_IS_OBJECT (object));
648  g_return_if_fail (self != NULL);
649
650  oclass = GST_OBJECT_GET_CLASS (object);
651
652  if (oclass->restore_thyself)
653    oclass->restore_thyself (object, self);
654}
655
656static void
[21004]657gst_object_real_restore_thyself (GstObject * object, xmlNodePtr self)
[18713]658{
659  g_return_if_fail (object != NULL);
660  g_return_if_fail (GST_IS_OBJECT (object));
661  g_return_if_fail (self != NULL);
[21004]662
663  gst_class_signal_emit_by_name (object, "object_loaded", self);
[18713]664}
665#endif /* GST_DISABLE_LOADSAVE_REGISTRY */
666
667static void
[21004]668gst_object_set_property (GObject * object, guint prop_id,
669    const GValue * value, GParamSpec * pspec)
[18713]670{
671  GstObject *gstobject;
[21004]672
[18713]673  /* it's not null if we got it, but it might not be ours */
674  g_return_if_fail (GST_IS_OBJECT (object));
[21004]675
[18713]676  gstobject = GST_OBJECT (object);
677
678  switch (prop_id) {
679    case ARG_NAME:
680      gst_object_set_name (gstobject, g_value_get_string (value));
681      break;
682    default:
683      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
684      break;
685  }
686}
687
688static void
[21004]689gst_object_get_property (GObject * object, guint prop_id,
690    GValue * value, GParamSpec * pspec)
[18713]691{
692  GstObject *gstobject;
[21004]693
[18713]694  /* it's not null if we got it, but it might not be ours */
695  g_return_if_fail (GST_IS_OBJECT (object));
[21004]696
[18713]697  gstobject = GST_OBJECT (object);
698
699  switch (prop_id) {
700    case ARG_NAME:
[21004]701      g_value_set_string (value, (gchar *) GST_OBJECT_NAME (gstobject));
[18713]702      break;
703    default:
704      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
705      break;
706  }
707}
708
709/**
710 * gst_object_get_path_string:
711 * @object: GstObject to get the path from
712 *
713 * Generates a string describing the path of the object in
[21004]714 * the object hierarchy. Only useful (or used) for debugging.
[18713]715 *
716 * Returns: a string describing the path of the object
717 */
[21004]718gchar *
719gst_object_get_path_string (GstObject * object)
[18713]720{
721  GSList *parentage = NULL;
722  GSList *parents;
723  void *parent;
724  gchar *prevpath, *path;
725  const char *component;
726  gchar *separator = "";
727  gboolean free_component;
728
729  parentage = g_slist_prepend (NULL, object);
730
731  path = g_strdup ("");
732
733  /* first walk the object hierarchy to build a list of the parents */
734  do {
735    if (GST_IS_OBJECT (object)) {
736      parent = gst_object_get_parent (object);
737    } else {
738      parentage = g_slist_prepend (parentage, NULL);
739      parent = NULL;
740    }
741
742    if (parent != NULL) {
743      parentage = g_slist_prepend (parentage, parent);
744    }
745
746    object = parent;
747  } while (object != NULL);
748
749  /* then walk the parent list and print them out */
750  parents = parentage;
751  while (parents) {
752    if (GST_IS_OBJECT (parents->data)) {
753      GstObjectClass *oclass = GST_OBJECT_GET_CLASS (parents->data);
754
755      component = gst_object_get_name (parents->data);
756      separator = oclass->path_string_separator;
757      free_component = FALSE;
758    } else {
[21004]759      component = g_strdup_printf ("%p", parents->data);
[18713]760      separator = "/";
761      free_component = TRUE;
762    }
763
764    prevpath = path;
765    path = g_strjoin (separator, prevpath, component, NULL);
[21004]766    g_free (prevpath);
[18713]767    if (free_component)
[21004]768      g_free ((gchar *) component);
[18713]769
[21004]770    parents = g_slist_next (parents);
[18713]771  }
772
773  g_slist_free (parentage);
774
775  return path;
776}
777
778
779
[21004]780struct _GstSignalObject
781{
[18713]782  GObject object;
783};
784
[21004]785struct _GstSignalObjectClass
786{
787  GObjectClass parent_class;
[18713]788
789  /* signals */
790#ifndef GST_DISABLE_LOADSAVE_REGISTRY
[21004]791  void (*object_loaded) (GstSignalObject * object, GstObject * new,
792      xmlNodePtr self);
793#endif                          /* GST_DISABLE_LOADSAVE_REGISTRY */
[18713]794};
795
796static GType
797gst_signal_object_get_type (void)
798{
799  static GType signal_object_type = 0;
800
801  if (!signal_object_type) {
802    static const GTypeInfo signal_object_info = {
[21004]803      sizeof (GstSignalObjectClass),
[18713]804      NULL,
805      NULL,
[21004]806      (GClassInitFunc) gst_signal_object_class_init,
[18713]807      NULL,
808      NULL,
[21004]809      sizeof (GstSignalObject),
810      0,
811      (GInstanceInitFunc) gst_signal_object_init,
[18713]812      NULL
813    };
[21004]814
815    signal_object_type =
816        g_type_register_static (G_TYPE_OBJECT, "GstSignalObject",
817        &signal_object_info, 0);
[18713]818  }
819  return signal_object_type;
820}
821
822static void
[21004]823gst_signal_object_class_init (GstSignalObjectClass * klass)
[18713]824{
825  GObjectClass *gobject_class;
826
[21004]827  gobject_class = (GObjectClass *) klass;
[18713]828
829  parent_class = g_type_class_ref (G_TYPE_OBJECT);
830
831#ifndef GST_DISABLE_LOADSAVE_REGISTRY
832  gst_signal_object_signals[SO_OBJECT_LOADED] =
[21004]833      g_signal_new ("object-loaded", G_TYPE_FROM_CLASS (klass),
834      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstSignalObjectClass, object_loaded),
835      NULL, NULL, gst_marshal_VOID__OBJECT_POINTER, G_TYPE_NONE, 2,
836      G_TYPE_OBJECT, G_TYPE_POINTER);
[18713]837#endif
838}
839
840static void
[21004]841gst_signal_object_init (GstSignalObject * object)
[18713]842{
843}
844
845/**
846 * gst_class_signal_connect
847 * @klass: the GstObjectClass to attach the signal to
848 * @name: the name of the signal to attach to
849 * @func: the signal function
850 * @func_data: a pointer to user data
851 *
852 * Connect to a class signal.
853 *
854 * Returns: the signal id.
855 */
856guint
[21004]857gst_class_signal_connect (GstObjectClass * klass,
858    const gchar * name, gpointer func, gpointer func_data)
[18713]859{
860  return g_signal_connect (klass->signal_object, name, func, func_data);
861}
862
863#ifndef GST_DISABLE_LOADSAVE_REGISTRY
864/**
865 * gst_class_signal_emit_by_name:
866 * @object: the object that sends the signal
867 * @name: the name of the signal to emit
868 * @self: data for the signal
869 *
870 * emits the named class signal.
871 */
872void
[21004]873gst_class_signal_emit_by_name (GstObject * object,
874    const gchar * name, xmlNodePtr self)
[18713]875{
876  GstObjectClass *oclass;
877
878  oclass = GST_OBJECT_GET_CLASS (object);
879
880  g_signal_emit_by_name (oclass->signal_object, name, object, self);
881}
882
883#endif /* GST_DISABLE_LOADSAVE_REGISTRY */
Note: See TracBrowser for help on using the repository browser.