Merge branch 'master' into 0.11
[platform/upstream/gstreamer.git] / gst / gstobject.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *                    2005 Wim Taymans <wim@fluendo.com>
5  *
6  * gstobject.c: Fundamental class used for all of GStreamer
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 /**
25  * SECTION:gstobject
26  * @short_description: Base class for the GStreamer object hierarchy
27  *
28  * #GstObject provides a root for the object hierarchy tree filed in by the
29  * GStreamer library.  It is currently a thin wrapper on top of
30  * #GObject. It is an abstract class that is not very usable on its own.
31  *
32  * #GstObject gives us basic refcounting, parenting functionality and locking.
33  * Most of the function are just extended for special GStreamer needs and can be
34  * found under the same name in the base class of #GstObject which is #GObject
35  * (e.g. g_object_ref() becomes gst_object_ref()).
36  *
37  * The most interesting difference between #GstObject and #GObject is the
38  * "floating" reference count. A #GObject is created with a reference count of
39  * 1, owned by the creator of the #GObject. (The owner of a reference is the
40  * code section that has the right to call gst_object_unref() in order to
41  * remove that reference.) A #GstObject is created with a reference count of 1
42  * also, but it isn't owned by anyone; Instead, the initial reference count
43  * of a #GstObject is "floating". The floating reference can be removed by
44  * anyone at any time, by calling gst_object_sink().  gst_object_sink() does
45  * nothing if an object is already sunk (has no floating reference).
46  *
47  * When you add a #GstElement to its parent container, the parent container will
48  * do this:
49  * <informalexample>
50  * <programlisting>
51  *   gst_object_ref (GST_OBJECT (child_element));
52  *   gst_object_sink (GST_OBJECT (child_element));
53  * </programlisting>
54  * </informalexample>
55  * This means that the container now owns a reference to the child element
56  * (since it called gst_object_ref()), and the child element has no floating
57  * reference.
58  *
59  * The purpose of the floating reference is to keep the child element alive
60  * until you add it to a parent container, which then manages the lifetime of
61  * the object itself:
62  * <informalexample>
63  * <programlisting>
64  *    element = gst_element_factory_make (factoryname, name);
65  *    // element has one floating reference to keep it alive
66  *    gst_bin_add (GST_BIN (bin), element);
67  *    // element has one non-floating reference owned by the container
68  * </programlisting>
69  * </informalexample>
70  *
71  * Another effect of this is, that calling gst_object_unref() on a bin object,
72  * will also destoy all the #GstElement objects in it. The same is true for
73  * calling gst_bin_remove().
74  *
75  * Special care has to be taken for all methods that gst_object_sink() an object
76  * since if the caller of those functions had a floating reference to the object,
77  * the object reference is now invalid.
78  *
79  * In contrast to #GObject instances, #GstObject adds a name property. The functions
80  * gst_object_set_name() and gst_object_get_name() are used to set/get the name
81  * of the object.
82  *
83  * Last reviewed on 2005-11-09 (0.9.4)
84  */
85
86 #include "gst_private.h"
87
88 #include "gstobject.h"
89 #include "gstmarshal.h"
90 #include "gstinfo.h"
91 #include "gstutils.h"
92
93 #ifndef GST_DISABLE_TRACE
94 #include "gsttrace.h"
95 static GstAllocTrace *_gst_object_trace;
96 #endif
97
98 #define DEBUG_REFCOUNT
99
100 /* Object signals and args */
101 enum
102 {
103   DEEP_NOTIFY,
104   LAST_SIGNAL
105 };
106
107 enum
108 {
109   PROP_0,
110   PROP_NAME,
111   PROP_PARENT,
112   PROP_LAST
113 };
114
115 enum
116 {
117   SO_OBJECT_LOADED,
118   SO_LAST_SIGNAL
119 };
120
121 /* maps type name quark => count */
122 static GData *object_name_counts = NULL;
123
124 G_LOCK_DEFINE_STATIC (object_name_mutex);
125
126 static void gst_object_set_property (GObject * object, guint prop_id,
127     const GValue * value, GParamSpec * pspec);
128 static void gst_object_get_property (GObject * object, guint prop_id,
129     GValue * value, GParamSpec * pspec);
130
131 static void gst_object_dispatch_properties_changed (GObject * object,
132     guint n_pspecs, GParamSpec ** pspecs);
133
134 static void gst_object_dispose (GObject * object);
135 static void gst_object_finalize (GObject * object);
136
137 static gboolean gst_object_set_name_default (GstObject * object);
138
139 static guint gst_object_signals[LAST_SIGNAL] = { 0 };
140
141 static GParamSpec *properties[PROP_LAST];
142
143 G_DEFINE_ABSTRACT_TYPE (GstObject, gst_object, G_TYPE_INITIALLY_UNOWNED);
144
145 static void
146 gst_object_class_init (GstObjectClass * klass)
147 {
148   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
149
150 #ifndef GST_DISABLE_TRACE
151   _gst_object_trace = gst_alloc_trace_register (g_type_name (GST_TYPE_OBJECT));
152 #endif
153
154   gobject_class->set_property = gst_object_set_property;
155   gobject_class->get_property = gst_object_get_property;
156
157   properties[PROP_NAME] =
158       g_param_spec_string ("name", "Name", "The name of the object", NULL,
159       G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
160   g_object_class_install_property (gobject_class, PROP_NAME,
161       properties[PROP_NAME]);
162
163   properties[PROP_PARENT] =
164       g_param_spec_object ("parent", "Parent", "The parent of the object",
165       GST_TYPE_OBJECT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
166   g_object_class_install_property (gobject_class, PROP_PARENT,
167       properties[PROP_PARENT]);
168
169   /**
170    * GstObject::deep-notify:
171    * @gstobject: a #GstObject
172    * @prop_object: the object that originated the signal
173    * @prop: the property that changed
174    *
175    * The deep notify signal is used to be notified of property changes. It is
176    * typically attached to the toplevel bin to receive notifications from all
177    * the elements contained in that bin.
178    */
179   gst_object_signals[DEEP_NOTIFY] =
180       g_signal_new ("deep-notify", G_TYPE_FROM_CLASS (klass),
181       G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED |
182       G_SIGNAL_NO_HOOKS, G_STRUCT_OFFSET (GstObjectClass, deep_notify), NULL,
183       NULL, gst_marshal_VOID__OBJECT_PARAM, G_TYPE_NONE, 2, GST_TYPE_OBJECT,
184       G_TYPE_PARAM);
185
186   klass->path_string_separator = "/";
187
188   /* see the comments at gst_object_dispatch_properties_changed */
189   gobject_class->dispatch_properties_changed
190       = GST_DEBUG_FUNCPTR (gst_object_dispatch_properties_changed);
191
192   gobject_class->dispose = gst_object_dispose;
193   gobject_class->finalize = gst_object_finalize;
194 }
195
196 static void
197 gst_object_init (GstObject * object)
198 {
199   object->lock = g_mutex_new ();
200   object->parent = NULL;
201   object->name = NULL;
202   GST_CAT_TRACE_OBJECT (GST_CAT_REFCOUNTING, object, "%p new", object);
203
204 #ifndef GST_DISABLE_TRACE
205   gst_alloc_trace_new (_gst_object_trace, object);
206 #endif
207
208   object->flags = 0;
209 }
210
211 /**
212  * gst_object_ref:
213  * @object: a #GstObject to reference
214  *
215  * Increments the reference count on @object. This function
216  * does not take the lock on @object because it relies on
217  * atomic refcounting.
218  *
219  * This object returns the input parameter to ease writing
220  * constructs like :
221  *  result = gst_object_ref (object->parent);
222  *
223  * Returns: (transfer full): A pointer to @object
224  */
225 gpointer
226 gst_object_ref (gpointer object)
227 {
228   g_return_val_if_fail (object != NULL, NULL);
229
230 #ifdef DEBUG_REFCOUNT
231   GST_CAT_TRACE_OBJECT (GST_CAT_REFCOUNTING, object, "%p ref %d->%d", object,
232       ((GObject *) object)->ref_count, ((GObject *) object)->ref_count + 1);
233 #endif
234   g_object_ref (object);
235
236   return object;
237 }
238
239 /**
240  * gst_object_unref:
241  * @object: a #GstObject to unreference
242  *
243  * Decrements the reference count on @object.  If reference count hits
244  * zero, destroy @object. This function does not take the lock
245  * on @object as it relies on atomic refcounting.
246  *
247  * The unref method should never be called with the LOCK held since
248  * this might deadlock the dispose function.
249  */
250 void
251 gst_object_unref (gpointer object)
252 {
253   g_return_if_fail (object != NULL);
254   g_return_if_fail (((GObject *) object)->ref_count > 0);
255
256 #ifdef DEBUG_REFCOUNT
257   GST_CAT_TRACE_OBJECT (GST_CAT_REFCOUNTING, object, "%p unref %d->%d", object,
258       ((GObject *) object)->ref_count, ((GObject *) object)->ref_count - 1);
259 #endif
260   g_object_unref (object);
261 }
262
263 /**
264  * gst_object_ref_sink:
265  * @object: a #GstObject to sink
266  *
267  * Increase the reference count of @object, and possibly remove the floating
268  * reference, if @object has a floating reference.
269  *
270  * In other words, if the object is floating, then this call "assumes ownership"
271  * of the floating reference, converting it to a normal reference by clearing
272  * the floating flag while leaving the reference count unchanged. If the object
273  * is not floating, then this call adds a new normal reference increasing the
274  * reference count by one.
275  */
276 gpointer
277 gst_object_ref_sink (gpointer object)
278 {
279   g_return_val_if_fail (object != NULL, NULL);
280
281 #ifdef DEBUG_REFCOUNT
282   GST_CAT_TRACE_OBJECT (GST_CAT_REFCOUNTING, object, "%p ref_sink %d->%d",
283       object, ((GObject *) object)->ref_count,
284       ((GObject *) object)->ref_count + 1);
285 #endif
286   return g_object_ref_sink (object);
287 }
288
289 /**
290  * gst_object_replace:
291  * @oldobj: (inout) (transfer full): pointer to a place of a #GstObject to
292  *     replace
293  * @newobj: (transfer none): a new #GstObject
294  *
295  * Unrefs the #GstObject pointed to by @oldobj, refs @newobj and
296  * puts @newobj in *@oldobj. Be carefull when calling this
297  * function, it does not take any locks. You might want to lock
298  * the object owning @oldobj pointer before calling this
299  * function.
300  *
301  * Make sure not to LOCK @oldobj because it might be unreffed
302  * which could cause a deadlock when it is disposed.
303  */
304 void
305 gst_object_replace (GstObject ** oldobj, GstObject * newobj)
306 {
307   g_return_if_fail (oldobj != NULL);
308   g_return_if_fail (*oldobj == NULL || GST_IS_OBJECT (*oldobj));
309   g_return_if_fail (newobj == NULL || GST_IS_OBJECT (newobj));
310
311 #ifdef DEBUG_REFCOUNT
312   GST_CAT_TRACE (GST_CAT_REFCOUNTING, "replace %p %s (%d) with %p %s (%d)",
313       *oldobj, *oldobj ? GST_STR_NULL (GST_OBJECT_NAME (*oldobj)) : "(NONE)",
314       *oldobj ? G_OBJECT (*oldobj)->ref_count : 0,
315       newobj, newobj ? GST_STR_NULL (GST_OBJECT_NAME (newobj)) : "(NONE)",
316       newobj ? G_OBJECT (newobj)->ref_count : 0);
317 #endif
318
319   if (G_LIKELY (*oldobj != newobj)) {
320     if (newobj)
321       gst_object_ref (newobj);
322     if (*oldobj)
323       gst_object_unref (*oldobj);
324
325     *oldobj = newobj;
326   }
327 }
328
329 /* dispose is called when the object has to release all links
330  * to other objects */
331 static void
332 gst_object_dispose (GObject * object)
333 {
334   GstObject *parent;
335
336   GST_CAT_TRACE_OBJECT (GST_CAT_REFCOUNTING, object, "dispose");
337
338   GST_OBJECT_LOCK (object);
339   if ((parent = GST_OBJECT_PARENT (object)))
340     goto have_parent;
341   GST_OBJECT_PARENT (object) = NULL;
342   GST_OBJECT_UNLOCK (object);
343
344   ((GObjectClass *) gst_object_parent_class)->dispose (object);
345
346   return;
347
348   /* ERRORS */
349 have_parent:
350   {
351     g_critical ("\nTrying to dispose object \"%s\", but it still has a "
352         "parent \"%s\".\nYou need to let the parent manage the "
353         "object instead of unreffing the object directly.\n",
354         GST_OBJECT_NAME (object), GST_OBJECT_NAME (parent));
355     GST_OBJECT_UNLOCK (object);
356     /* ref the object again to revive it in this error case */
357     gst_object_ref (object);
358     return;
359   }
360 }
361
362 /* finalize is called when the object has to free its resources */
363 static void
364 gst_object_finalize (GObject * object)
365 {
366   GstObject *gstobject = GST_OBJECT_CAST (object);
367
368   GST_CAT_TRACE_OBJECT (GST_CAT_REFCOUNTING, object, "finalize");
369
370   g_signal_handlers_destroy (object);
371
372   g_free (gstobject->name);
373   g_mutex_free (gstobject->lock);
374
375 #ifndef GST_DISABLE_TRACE
376   gst_alloc_trace_free (_gst_object_trace, object);
377 #endif
378
379   ((GObjectClass *) gst_object_parent_class)->finalize (object);
380 }
381
382 /* Changing a GObject property of a GstObject will result in "deep-notify"
383  * signals being emitted by the object itself, as well as in each parent
384  * object. This is so that an application can connect a listener to the
385  * top-level bin to catch property-change notifications for all contained
386  * elements.
387  *
388  * MT safe.
389  */
390 static void
391 gst_object_dispatch_properties_changed (GObject * object,
392     guint n_pspecs, GParamSpec ** pspecs)
393 {
394   GstObject *gst_object, *parent, *old_parent;
395   guint i;
396 #ifndef GST_DISABLE_GST_DEBUG
397   gchar *name = NULL;
398   const gchar *debug_name;
399 #endif
400
401   /* do the standard dispatching */
402   ((GObjectClass *)
403       gst_object_parent_class)->dispatch_properties_changed (object, n_pspecs,
404       pspecs);
405
406   gst_object = GST_OBJECT_CAST (object);
407 #ifndef GST_DISABLE_GST_DEBUG
408   if (G_UNLIKELY (__gst_debug_min >= GST_LEVEL_LOG)) {
409     name = gst_object_get_name (gst_object);
410     debug_name = GST_STR_NULL (name);
411   } else
412     debug_name = "";
413 #endif
414
415   /* now let the parent dispatch those, too */
416   parent = gst_object_get_parent (gst_object);
417   while (parent) {
418     for (i = 0; i < n_pspecs; i++) {
419       GST_CAT_LOG_OBJECT (GST_CAT_PROPERTIES, parent,
420           "deep notification from %s (%s)", debug_name, pspecs[i]->name);
421
422       g_signal_emit (parent, gst_object_signals[DEEP_NOTIFY],
423           g_quark_from_string (pspecs[i]->name), gst_object, pspecs[i]);
424     }
425
426     old_parent = parent;
427     parent = gst_object_get_parent (old_parent);
428     gst_object_unref (old_parent);
429   }
430 #ifndef GST_DISABLE_GST_DEBUG
431   g_free (name);
432 #endif
433 }
434
435 /**
436  * gst_object_default_deep_notify:
437  * @object: the #GObject that signalled the notify.
438  * @orig: a #GstObject that initiated the notify.
439  * @pspec: a #GParamSpec of the property.
440  * @excluded_props: (array zero-terminated=1) (element-type gchar*)
441  *     (allow-none):a set of user-specified properties to exclude or
442  *     NULL to show all changes.
443  *
444  * A default deep_notify signal callback for an object. The user data
445  * should contain a pointer to an array of strings that should be excluded
446  * from the notify. The default handler will print the new value of the property
447  * using g_print.
448  *
449  * MT safe. This function grabs and releases @object's LOCK for getting its
450  *          path string.
451  */
452 void
453 gst_object_default_deep_notify (GObject * object, GstObject * orig,
454     GParamSpec * pspec, gchar ** excluded_props)
455 {
456   GValue value = { 0, };        /* the important thing is that value.type = 0 */
457   gchar *str = NULL;
458   gchar *name = NULL;
459
460   if (pspec->flags & G_PARAM_READABLE) {
461     /* let's not print these out for excluded properties... */
462     while (excluded_props != NULL && *excluded_props != NULL) {
463       if (strcmp (pspec->name, *excluded_props) == 0)
464         return;
465       excluded_props++;
466     }
467     g_value_init (&value, pspec->value_type);
468     g_object_get_property (G_OBJECT (orig), pspec->name, &value);
469
470     /* FIXME: handle flags */
471     if (G_IS_PARAM_SPEC_ENUM (pspec)) {
472       GEnumValue *enum_value;
473       GEnumClass *klass = G_ENUM_CLASS (g_type_class_ref (pspec->value_type));
474
475       enum_value = g_enum_get_value (klass, g_value_get_enum (&value));
476
477       str = g_strdup_printf ("%s (%d)", enum_value->value_nick,
478           enum_value->value);
479       g_type_class_unref (klass);
480     } else {
481       str = g_strdup_value_contents (&value);
482     }
483     name = gst_object_get_path_string (orig);
484     g_print ("%s: %s = %s\n", name, pspec->name, str);
485     g_free (name);
486     g_free (str);
487     g_value_unset (&value);
488   } else {
489     name = gst_object_get_path_string (orig);
490     g_warning ("Parameter %s not readable in %s.", pspec->name, name);
491     g_free (name);
492   }
493 }
494
495 static gboolean
496 gst_object_set_name_default (GstObject * object)
497 {
498   const gchar *type_name;
499   gint count;
500   gchar *name;
501   GQuark q;
502   guint i, l;
503
504   /* to ensure guaranteed uniqueness across threads, only one thread
505    * may ever assign a name */
506   G_LOCK (object_name_mutex);
507
508   if (!object_name_counts) {
509     g_datalist_init (&object_name_counts);
510   }
511
512   q = g_type_qname (G_OBJECT_TYPE (object));
513   count = GPOINTER_TO_INT (g_datalist_id_get_data (&object_name_counts, q));
514   g_datalist_id_set_data (&object_name_counts, q, GINT_TO_POINTER (count + 1));
515
516   G_UNLOCK (object_name_mutex);
517
518   /* GstFooSink -> foosink<N> */
519   type_name = g_quark_to_string (q);
520   if (strncmp (type_name, "Gst", 3) == 0)
521     type_name += 3;
522   name = g_strdup_printf ("%s%d", type_name, count);
523   l = strlen (name);
524   for (i = 0; i < l; i++)
525     name[i] = g_ascii_tolower (name[i]);
526
527   GST_OBJECT_LOCK (object);
528   if (G_UNLIKELY (object->parent != NULL))
529     goto had_parent;
530
531   g_free (object->name);
532   object->name = name;
533
534   GST_OBJECT_UNLOCK (object);
535
536   return TRUE;
537
538 had_parent:
539   {
540     g_free (name);
541     GST_WARNING ("parented objects can't be renamed");
542     GST_OBJECT_UNLOCK (object);
543     return FALSE;
544   }
545 }
546
547 /**
548  * gst_object_set_name:
549  * @object: a #GstObject
550  * @name:   new name of object
551  *
552  * Sets the name of @object, or gives @object a guaranteed unique
553  * name (if @name is NULL).
554  * This function makes a copy of the provided name, so the caller
555  * retains ownership of the name it sent.
556  *
557  * Returns: TRUE if the name could be set. Since Objects that have
558  * a parent cannot be renamed, this function returns FALSE in those
559  * cases.
560  *
561  * MT safe.  This function grabs and releases @object's LOCK.
562  */
563 gboolean
564 gst_object_set_name (GstObject * object, const gchar * name)
565 {
566   gboolean result;
567
568   g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
569
570   GST_OBJECT_LOCK (object);
571
572   /* parented objects cannot be renamed */
573   if (G_UNLIKELY (object->parent != NULL))
574     goto had_parent;
575
576   if (name != NULL) {
577     g_free (object->name);
578     object->name = g_strdup (name);
579     GST_OBJECT_UNLOCK (object);
580     result = TRUE;
581   } else {
582     GST_OBJECT_UNLOCK (object);
583     result = gst_object_set_name_default (object);
584   }
585   /* FIXME-0.11: this misses a g_object_notify (object, "name"); unless called
586    * from gst_object_set_property.
587    * Ideally remove such custom setters (or make it static).
588    */
589   return result;
590
591   /* error */
592 had_parent:
593   {
594     GST_WARNING ("parented objects can't be renamed");
595     GST_OBJECT_UNLOCK (object);
596     return FALSE;
597   }
598 }
599
600 /**
601  * gst_object_get_name:
602  * @object: a #GstObject
603  *
604  * Returns a copy of the name of @object.
605  * Caller should g_free() the return value after usage.
606  * For a nameless object, this returns NULL, which you can safely g_free()
607  * as well.
608  *
609  * Free-function: g_free
610  *
611  * Returns: (transfer full): the name of @object. g_free() after usage.
612  *
613  * MT safe. This function grabs and releases @object's LOCK.
614  */
615 gchar *
616 gst_object_get_name (GstObject * object)
617 {
618   gchar *result = NULL;
619
620   g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
621
622   GST_OBJECT_LOCK (object);
623   result = g_strdup (object->name);
624   GST_OBJECT_UNLOCK (object);
625
626   return result;
627 }
628
629 /**
630  * gst_object_set_parent:
631  * @object: a #GstObject
632  * @parent: new parent of object
633  *
634  * Sets the parent of @object to @parent. The object's reference count will
635  * be incremented, and any floating reference will be removed (see gst_object_ref_sink()).
636  *
637  * Returns: TRUE if @parent could be set or FALSE when @object
638  * already had a parent or @object and @parent are the same.
639  *
640  * MT safe. Grabs and releases @object's LOCK.
641  */
642 gboolean
643 gst_object_set_parent (GstObject * object, GstObject * parent)
644 {
645   g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);
646   g_return_val_if_fail (GST_IS_OBJECT (parent), FALSE);
647   g_return_val_if_fail (object != parent, FALSE);
648
649   GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object,
650       "set parent (ref and sink)");
651
652   GST_OBJECT_LOCK (object);
653   if (G_UNLIKELY (object->parent != NULL))
654     goto had_parent;
655
656   object->parent = parent;
657   g_object_ref_sink (object);
658   GST_OBJECT_UNLOCK (object);
659
660   /* FIXME, this does not work, the deep notify takes the lock from the parent
661    * object and deadlocks when the parent holds its lock when calling this
662    * function (like _element_add_pad()) */
663   /* g_object_notify_by_pspec ((GObject *)object, properties[PROP_PARENT]); */
664
665   return TRUE;
666
667   /* ERROR handling */
668 had_parent:
669   {
670     GST_CAT_DEBUG_OBJECT (GST_CAT_REFCOUNTING, object,
671         "set parent failed, object already had a parent");
672     GST_OBJECT_UNLOCK (object);
673     return FALSE;
674   }
675 }
676
677 /**
678  * gst_object_get_parent:
679  * @object: a #GstObject
680  *
681  * Returns the parent of @object. This function increases the refcount
682  * of the parent object so you should gst_object_unref() it after usage.
683  *
684  * Returns: (transfer full): parent of @object, this can be NULL if @object
685  *   has no parent. unref after usage.
686  *
687  * MT safe. Grabs and releases @object's LOCK.
688  */
689 GstObject *
690 gst_object_get_parent (GstObject * object)
691 {
692   GstObject *result = NULL;
693
694   g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
695
696   GST_OBJECT_LOCK (object);
697   result = object->parent;
698   if (G_LIKELY (result))
699     gst_object_ref (result);
700   GST_OBJECT_UNLOCK (object);
701
702   return result;
703 }
704
705 /**
706  * gst_object_unparent:
707  * @object: a #GstObject to unparent
708  *
709  * Clear the parent of @object, removing the associated reference.
710  * This function decreases the refcount of @object.
711  *
712  * MT safe. Grabs and releases @object's lock.
713  */
714 void
715 gst_object_unparent (GstObject * object)
716 {
717   GstObject *parent;
718
719   g_return_if_fail (GST_IS_OBJECT (object));
720
721   GST_OBJECT_LOCK (object);
722   parent = object->parent;
723
724   if (G_LIKELY (parent != NULL)) {
725     GST_CAT_TRACE_OBJECT (GST_CAT_REFCOUNTING, object, "unparent");
726     object->parent = NULL;
727     GST_OBJECT_UNLOCK (object);
728
729     /* g_object_notify_by_pspec ((GObject *)object, properties[PROP_PARENT]); */
730
731     gst_object_unref (object);
732   } else {
733     GST_OBJECT_UNLOCK (object);
734   }
735 }
736
737 /**
738  * gst_object_has_ancestor:
739  * @object: a #GstObject to check
740  * @ancestor: a #GstObject to check as ancestor
741  *
742  * Check if @object has an ancestor @ancestor somewhere up in
743  * the hierarchy. One can e.g. check if a #GstElement is inside a #GstPipeline.
744  *
745  * Returns: TRUE if @ancestor is an ancestor of @object.
746  *
747  * MT safe. Grabs and releases @object's locks.
748  */
749 gboolean
750 gst_object_has_ancestor (GstObject * object, GstObject * ancestor)
751 {
752   GstObject *parent, *tmp;
753
754   if (!ancestor || !object)
755     return FALSE;
756
757   parent = gst_object_ref (object);
758   do {
759     if (parent == ancestor) {
760       gst_object_unref (parent);
761       return TRUE;
762     }
763
764     tmp = gst_object_get_parent (parent);
765     gst_object_unref (parent);
766     parent = tmp;
767   } while (parent);
768
769   return FALSE;
770 }
771
772 /**
773  * gst_object_check_uniqueness:
774  * @list: (transfer none) (element-type Gst.Object): a list of #GstObject to
775  *      check through
776  * @name: the name to search for
777  *
778  * Checks to see if there is any object named @name in @list. This function
779  * does not do any locking of any kind. You might want to protect the
780  * provided list with the lock of the owner of the list. This function
781  * will lock each #GstObject in the list to compare the name, so be
782  * carefull when passing a list with a locked object.
783  *
784  * Returns: TRUE if a #GstObject named @name does not appear in @list,
785  * FALSE if it does.
786  *
787  * MT safe. Grabs and releases the LOCK of each object in the list.
788  */
789 gboolean
790 gst_object_check_uniqueness (GList * list, const gchar * name)
791 {
792   gboolean result = TRUE;
793
794   g_return_val_if_fail (name != NULL, FALSE);
795
796   for (; list; list = g_list_next (list)) {
797     GstObject *child;
798     gboolean eq;
799
800     child = GST_OBJECT_CAST (list->data);
801
802     GST_OBJECT_LOCK (child);
803     eq = strcmp (GST_OBJECT_NAME (child), name) == 0;
804     GST_OBJECT_UNLOCK (child);
805
806     if (G_UNLIKELY (eq)) {
807       result = FALSE;
808       break;
809     }
810   }
811   return result;
812 }
813
814
815 static void
816 gst_object_set_property (GObject * object, guint prop_id,
817     const GValue * value, GParamSpec * pspec)
818 {
819   GstObject *gstobject;
820
821   gstobject = GST_OBJECT_CAST (object);
822
823   switch (prop_id) {
824     case PROP_NAME:
825       gst_object_set_name (gstobject, g_value_get_string (value));
826       break;
827     case PROP_PARENT:
828       gst_object_set_parent (gstobject, g_value_get_object (value));
829       break;
830     default:
831       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
832       break;
833   }
834 }
835
836 static void
837 gst_object_get_property (GObject * object, guint prop_id,
838     GValue * value, GParamSpec * pspec)
839 {
840   GstObject *gstobject;
841
842   gstobject = GST_OBJECT_CAST (object);
843
844   switch (prop_id) {
845     case PROP_NAME:
846       g_value_take_string (value, gst_object_get_name (gstobject));
847       break;
848     case PROP_PARENT:
849       g_value_take_object (value, gst_object_get_parent (gstobject));
850       break;
851     default:
852       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
853       break;
854   }
855 }
856
857 /**
858  * gst_object_get_path_string:
859  * @object: a #GstObject
860  *
861  * Generates a string describing the path of @object in
862  * the object hierarchy. Only useful (or used) for debugging.
863  *
864  * Free-function: g_free
865  *
866  * Returns: (transfer full): a string describing the path of @object. You must
867  *          g_free() the string after usage.
868  *
869  * MT safe. Grabs and releases the #GstObject's LOCK for all objects
870  *          in the hierarchy.
871  */
872 gchar *
873 gst_object_get_path_string (GstObject * object)
874 {
875   GSList *parentage;
876   GSList *parents;
877   void *parent;
878   gchar *prevpath, *path;
879   const gchar *typename;
880   gchar *component;
881   const gchar *separator;
882
883   /* ref object before adding to list */
884   gst_object_ref (object);
885   parentage = g_slist_prepend (NULL, object);
886
887   path = g_strdup ("");
888
889   /* first walk the object hierarchy to build a list of the parents,
890    * be carefull here with refcounting. */
891   do {
892     if (GST_IS_OBJECT (object)) {
893       parent = gst_object_get_parent (object);
894       /* add parents to list, refcount remains increased while
895        * we handle the object */
896       if (parent)
897         parentage = g_slist_prepend (parentage, parent);
898     } else {
899       break;
900     }
901     object = parent;
902   } while (object != NULL);
903
904   /* then walk the parent list and print them out. we need to
905    * decrease the refcounting on each element after we handled
906    * it. */
907   for (parents = parentage; parents; parents = g_slist_next (parents)) {
908     if (G_IS_OBJECT (parents->data)) {
909       typename = G_OBJECT_TYPE_NAME (parents->data);
910     } else {
911       typename = NULL;
912     }
913     if (GST_IS_OBJECT (parents->data)) {
914       GstObject *item = GST_OBJECT_CAST (parents->data);
915       GstObjectClass *oclass = GST_OBJECT_GET_CLASS (item);
916       gchar *objname = gst_object_get_name (item);
917
918       component = g_strdup_printf ("%s:%s", typename, objname);
919       separator = oclass->path_string_separator;
920       /* and unref now */
921       gst_object_unref (item);
922       g_free (objname);
923     } else {
924       if (typename) {
925         component = g_strdup_printf ("%s:%p", typename, parents->data);
926       } else {
927         component = g_strdup_printf ("%p", parents->data);
928       }
929       separator = "/";
930     }
931
932     prevpath = path;
933     path = g_strjoin (separator, prevpath, component, NULL);
934     g_free (prevpath);
935     g_free (component);
936   }
937
938   g_slist_free (parentage);
939
940   return path;
941 }