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