2 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3 * 2000 Wim Taymans <wtay@chello.be>
5 * gstobject.c: Fundamental class used for all of GStreamer
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.
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.
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.
23 #include "gst_private.h"
25 #include "gstobject.h"
27 #ifndef GST_DISABLE_TRACE
31 /* Object signals and args */
35 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
53 GType _gst_object_type = 0;
54 static GHashTable *object_name_counts = NULL;
55 G_LOCK_DEFINE_STATIC (object_name_mutex);
57 typedef struct _GstSignalObject GstSignalObject;
58 typedef struct _GstSignalObjectClass GstSignalObjectClass;
60 static GType gst_signal_object_get_type (void);
61 static void gst_signal_object_class_init (GstSignalObjectClass *klass);
62 static void gst_signal_object_init (GstSignalObject *object);
64 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
65 static guint gst_signal_object_signals[SO_LAST_SIGNAL] = { 0 };
68 static void gst_object_class_init (GstObjectClass *klass);
69 static void gst_object_init (GstObject *object);
70 #ifndef GST_DISABLE_TRACE
71 static GObject * gst_object_constructor (GType type, guint n_construct_properties,
72 GObjectConstructParam *construct_params);
75 static void gst_object_set_property (GObject * object, guint prop_id, const GValue * value,
77 static void gst_object_get_property (GObject * object, guint prop_id, GValue * value,
79 static void gst_object_dispatch_properties_changed (GObject *object,
83 static void gst_object_dispose (GObject *object);
84 static void gst_object_finalize (GObject *object);
86 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
87 static void gst_object_real_restore_thyself (GstObject *object, xmlNodePtr self);
90 static GObjectClass *parent_class = NULL;
91 static guint gst_object_signals[LAST_SIGNAL] = { 0 };
94 gst_object_get_type (void)
96 if (!_gst_object_type) {
97 static const GTypeInfo object_info = {
98 sizeof (GstObjectClass),
101 (GClassInitFunc) gst_object_class_init,
106 (GInstanceInitFunc) gst_object_init,
109 _gst_object_type = g_type_register_static (G_TYPE_OBJECT, "GstObject", &object_info, G_TYPE_FLAG_ABSTRACT);
111 return _gst_object_type;
115 gst_object_class_init (GstObjectClass *klass)
117 GObjectClass *gobject_class;
119 gobject_class = (GObjectClass*) klass;
121 parent_class = g_type_class_ref (G_TYPE_OBJECT);
123 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_object_set_property);
124 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_object_get_property);
126 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NAME,
127 g_param_spec_string ("name", "Name", "The name of the object",
128 NULL, G_PARAM_READWRITE));
130 gst_object_signals[PARENT_SET] =
131 g_signal_new ("parent_set", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
132 G_STRUCT_OFFSET (GstObjectClass, parent_set), NULL, NULL,
133 g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
135 gst_object_signals[PARENT_UNSET] =
136 g_signal_new ("parent_unset", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
137 G_STRUCT_OFFSET (GstObjectClass, parent_unset), NULL, NULL,
138 g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
140 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
141 gst_object_signals[OBJECT_SAVED] =
142 g_signal_new ("object_saved", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
143 G_STRUCT_OFFSET (GstObjectClass, object_saved), NULL, NULL,
144 g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1,
147 klass->restore_thyself = gst_object_real_restore_thyself;
149 gst_object_signals[DEEP_NOTIFY] =
150 g_signal_new ("deep_notify", G_TYPE_FROM_CLASS (klass),
151 G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED | G_SIGNAL_NO_HOOKS,
152 G_STRUCT_OFFSET (GstObjectClass, deep_notify), NULL, NULL,
153 gst_marshal_VOID__OBJECT_PARAM, G_TYPE_NONE,
154 2, G_TYPE_OBJECT, G_TYPE_PARAM);
156 klass->path_string_separator = "/";
158 klass->signal_object = g_object_new (gst_signal_object_get_type (), NULL);
160 /* see the comments at gst_object_dispatch_properties_changed */
161 gobject_class->dispatch_properties_changed
162 = GST_DEBUG_FUNCPTR (gst_object_dispatch_properties_changed);
164 gobject_class->dispose = gst_object_dispose;
165 gobject_class->finalize = gst_object_finalize;
166 #ifndef GST_DISABLE_TRACE
167 gobject_class->constructor = gst_object_constructor;
172 gst_object_init (GstObject *object)
174 object->lock = g_mutex_new();
175 object->parent = NULL;
179 GST_FLAG_SET (object, GST_FLOATING);
182 #ifndef GST_DISABLE_TRACE
184 gst_object_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_params)
187 GstAllocTrace *trace;
188 GObject *obj = G_OBJECT_CLASS (parent_class)->constructor (type, n_construct_properties, construct_params);
190 name = g_type_name (type);
192 trace = gst_alloc_trace_get (name);
194 trace = gst_alloc_trace_register (name);
196 gst_alloc_trace_new (trace, obj);
203 * @object: GstObject to reference
205 * Increments the refence count on the object.
207 * Returns: A pointer to the object
210 gst_object_ref (GstObject *object)
212 g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
214 GST_DEBUG (GST_CAT_REFCOUNTING, "ref %p '%s' %d->%d", object,
215 GST_STR_NULL (GST_OBJECT_NAME (object)),
216 G_OBJECT (object)->ref_count,
217 G_OBJECT (object)->ref_count + 1);
219 g_object_ref (G_OBJECT (object));
225 * @object: GstObject to unreference
227 * Decrements the refence count on the object. If reference count hits
228 * zero, destroy the object.
231 gst_object_unref (GstObject *object)
233 g_return_if_fail (GST_IS_OBJECT (object));
234 g_return_if_fail (G_OBJECT (object)->ref_count > 0);
236 GST_DEBUG (GST_CAT_REFCOUNTING, "unref %p '%s' %d->%d", object,
237 GST_STR_NULL (GST_OBJECT_NAME (object)),
238 G_OBJECT (object)->ref_count,
239 G_OBJECT (object)->ref_count - 1);
241 g_object_unref (G_OBJECT (object));
246 * @object: GstObject to sink
248 * Removes floating reference on an object. Any newly created object has
249 * a refcount of 1 and is FLOATING. This function should be used when
250 * creating a new object to symbolically 'take ownership of' the object.
251 * Use #gst_object_set_parent to have this done for you.
254 gst_object_sink (GstObject *object)
256 g_return_if_fail (object != NULL);
257 g_return_if_fail (GST_IS_OBJECT (object));
259 GST_DEBUG (GST_CAT_REFCOUNTING, "sink %p '%s'", object, GST_STR_NULL (GST_OBJECT_NAME (object)));
261 if (GST_OBJECT_FLOATING (object)) {
262 GST_FLAG_UNSET (object, GST_FLOATING);
263 gst_object_unref (object);
268 * gst_object_replace:
269 * @oldobj: pointer to place of old GstObject
270 * @newobj: new GstObject
272 * Unrefs the object pointer to by oldobj, refs the newobj and
273 * puts the newobj in *oldobj.
276 gst_object_replace (GstObject **oldobj, GstObject *newobj)
278 GST_DEBUG (GST_CAT_REFCOUNTING, "replace %p %p", *oldobj, newobj);
280 if (*oldobj != newobj) {
281 if (newobj) gst_object_ref (newobj);
282 if (*oldobj) gst_object_unref (*oldobj);
289 gst_object_dispose (GObject *object)
291 GST_DEBUG (GST_CAT_REFCOUNTING, "dispose %p '%s'", object, GST_STR_NULL (GST_OBJECT_NAME (object)));
293 GST_FLAG_SET (GST_OBJECT (object), GST_DESTROYED);
294 GST_OBJECT_PARENT (object) = NULL;
296 parent_class->dispose (object);
299 /* finilize is called when the object has to free its resources */
301 gst_object_finalize (GObject *object)
303 GstObject *gstobject = GST_OBJECT (object);
305 GST_DEBUG (GST_CAT_REFCOUNTING, "finalize %p '%s'", object, GST_STR_NULL (GST_OBJECT_NAME (object)));
307 g_signal_handlers_destroy (object);
309 g_free (gstobject->name);
311 g_mutex_free (gstobject->lock);
313 #ifndef GST_DISABLE_TRACE
316 GstAllocTrace *trace;
318 name = g_type_name (G_OBJECT_TYPE (object));
319 trace = gst_alloc_trace_get (name);
321 gst_alloc_trace_free (trace, object);
325 parent_class->finalize (object);
328 /* Changing a GObject property of a GstObject will result in "deep_notify"
329 * signals being emitted by the object itself, as well as in each parent
330 * object. This is so that an application can connect a listener to the
331 * top-level bin to catch property-change notifications for all contained
334 gst_object_dispatch_properties_changed (GObject *object,
338 GstObject *gst_object;
341 /* do the standard dispatching */
342 G_OBJECT_CLASS (parent_class)->dispatch_properties_changed (object, n_pspecs, pspecs);
344 /* now let the parent dispatch those, too */
345 gst_object = GST_OBJECT_PARENT (object);
347 /* need own category? */
348 for (i = 0; i < n_pspecs; i++) {
349 GST_DEBUG (GST_CAT_EVENT, "deep notification from %s to %s (%s)", GST_OBJECT_NAME (object),
350 GST_OBJECT_NAME (gst_object), pspecs[i]->name);
351 g_signal_emit (gst_object, gst_object_signals[DEEP_NOTIFY], g_quark_from_string (pspecs[i]->name),
352 (GstObject *) object, pspecs[i]);
355 gst_object = GST_OBJECT_PARENT (gst_object);
360 * gst_object_default_deep_notify:
361 * @object: the #GObject that signalled the notify.
362 * @orig: a #GstObject that initiated the notify.
363 * @pspec: a #GParamSpec of the property.
364 * @excluded_props: a set of user-specified properties to exclude or
365 * NULL to show all changes.
367 * Adds a default deep_notify signal callback to an
368 * element. The user data should contain a pointer to an array of
369 * strings that should be excluded from the notify.
370 * The default handler will print the new value of the property
374 gst_object_default_deep_notify (GObject *object, GstObject *orig,
375 GParamSpec *pspec, gchar **excluded_props)
377 GValue value = { 0, }; /* the important thing is that value.type = 0 */
381 if (pspec->flags & G_PARAM_READABLE) {
382 /* let's not print these out for excluded properties... */
383 while (excluded_props != NULL && *excluded_props != NULL) {
384 if (strcmp (pspec->name, *excluded_props) == 0)
388 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
389 g_object_get_property (G_OBJECT (orig), pspec->name, &value);
391 if (G_IS_PARAM_SPEC_ENUM (pspec)) {
392 GEnumValue *enum_value;
393 enum_value = g_enum_get_value (G_ENUM_CLASS (g_type_class_ref (pspec->value_type)),
394 g_value_get_enum (&value));
396 str = g_strdup_printf ("%s (%d)", enum_value->value_nick,
400 str = g_strdup_value_contents (&value);
402 name = gst_object_get_path_string (orig);
403 g_print ("%s: %s = %s\n", name, pspec->name, str);
406 g_value_unset (&value);
408 name = gst_object_get_path_string (orig);
409 g_warning ("Parameter %s not readable in %s.",
416 gst_object_set_name_default (GstObject *object)
420 const gchar *type_name;
422 type_name = G_OBJECT_TYPE_NAME (object);
424 /* to ensure guaranteed uniqueness across threads, only one thread
425 * may ever assign a name */
426 G_LOCK (object_name_mutex);
428 if (!object_name_counts)
429 object_name_counts = g_hash_table_new (g_str_hash, g_str_equal);
431 count = GPOINTER_TO_INT (g_hash_table_lookup (object_name_counts, type_name));
432 g_hash_table_insert (object_name_counts, g_strdup (type_name),
433 GINT_TO_POINTER (count + 1));
435 G_UNLOCK (object_name_mutex);
437 /* GstFooSink -> foosinkN */
438 if (strncmp (type_name, "Gst", 3) == 0)
440 tmp = g_strdup_printf ("%s%d", type_name, count);
441 name = g_ascii_strdown (tmp, strlen (tmp));
444 gst_object_set_name (object, name);
449 * gst_object_set_name:
450 * @object: GstObject to set the name of
451 * @name: new name of object
453 * Sets the name of the object, or gives the element a guaranteed unique
454 * name (if @name is NULL).
457 gst_object_set_name (GstObject *object, const gchar *name)
459 g_return_if_fail (object != NULL);
460 g_return_if_fail (GST_IS_OBJECT (object));
462 if (object->name != NULL)
463 g_free (object->name);
466 object->name = g_strdup (name);
468 gst_object_set_name_default (object);
472 * gst_object_get_name:
473 * @object: GstObject to get the name of
475 * Get the name of the object.
477 * Returns: name of the object
480 gst_object_get_name (GstObject *object)
482 g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
488 * gst_object_set_parent:
489 * @object: GstObject to set parent of
490 * @parent: new parent of object
492 * Set the parent of the object. The object's reference count is
494 * signals the parent-set signal
497 gst_object_set_parent (GstObject *object, GstObject *parent)
499 g_return_if_fail (object != NULL);
500 g_return_if_fail (GST_IS_OBJECT (object));
501 g_return_if_fail (parent != NULL);
502 g_return_if_fail (GST_IS_OBJECT (parent));
503 g_return_if_fail (object != parent);
505 if (object->parent != NULL) {
506 GST_ERROR_OBJECT (object,object->parent, "object's parent is already set, must unparent first");
510 gst_object_ref (object);
511 gst_object_sink (object);
512 object->parent = parent;
514 g_signal_emit (G_OBJECT (object), gst_object_signals[PARENT_SET], 0, parent);
518 * gst_object_get_parent:
519 * @object: GstObject to get parent of
521 * Return the parent of the object.
523 * Returns: parent of the object
526 gst_object_get_parent (GstObject *object)
528 g_return_val_if_fail (object != NULL, NULL);
529 g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
531 return object->parent;
535 * gst_object_unparent:
536 * @object: GstObject to unparent
538 * Clear the parent of the object, removing the associated reference.
541 gst_object_unparent (GstObject *object)
543 g_return_if_fail (object != NULL);
544 g_return_if_fail (GST_IS_OBJECT(object));
545 if (object->parent == NULL)
548 GST_DEBUG (GST_CAT_REFCOUNTING, "unparent '%s'",GST_OBJECT_NAME(object));
550 g_signal_emit (G_OBJECT (object), gst_object_signals[PARENT_UNSET], 0, object->parent);
552 object->parent = NULL;
553 gst_object_unref (object);
557 * gst_object_check_uniqueness:
558 * @list: a list of #GstObject to check through
559 * @name: the name to search for
561 * This function checks through the list of objects to see if the name
562 * given appears in the list as the name of an object. It returns TRUE if
563 * the name does not exist in the list.
565 * Returns: TRUE if the name doesn't appear in the list, FALSE if it does.
568 gst_object_check_uniqueness (GList *list, const gchar *name)
570 g_return_val_if_fail (name != NULL, FALSE);
573 GstObject *child = GST_OBJECT (list->data);
575 list = g_list_next (list);
577 if (strcmp (GST_OBJECT_NAME (child), name) == 0)
585 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
587 * gst_object_save_thyself:
588 * @object: GstObject to save
589 * @parent: The parent XML node to save the object into
591 * Saves the given object into the parent XML node.
593 * Returns: the new xmlNodePtr with the saved object
596 gst_object_save_thyself (GstObject *object, xmlNodePtr parent)
598 GstObjectClass *oclass;
600 g_return_val_if_fail (object != NULL, parent);
601 g_return_val_if_fail (GST_IS_OBJECT (object), parent);
602 g_return_val_if_fail (parent != NULL, parent);
604 oclass = GST_OBJECT_GET_CLASS (object);
606 if (oclass->save_thyself)
607 oclass->save_thyself (object, parent);
609 g_signal_emit (G_OBJECT (object), gst_object_signals[OBJECT_SAVED], 0, parent);
615 * gst_object_restore_thyself:
616 * @object: GstObject to load into
617 * @self: The XML node to load the object from
619 * Restores the given object with the data from the parent XML node.
622 gst_object_restore_thyself (GstObject *object, xmlNodePtr self)
624 GstObjectClass *oclass;
626 g_return_if_fail (object != NULL);
627 g_return_if_fail (GST_IS_OBJECT (object));
628 g_return_if_fail (self != NULL);
630 oclass = GST_OBJECT_GET_CLASS (object);
632 if (oclass->restore_thyself)
633 oclass->restore_thyself (object, self);
637 gst_object_real_restore_thyself (GstObject *object, xmlNodePtr self)
639 g_return_if_fail (object != NULL);
640 g_return_if_fail (GST_IS_OBJECT (object));
641 g_return_if_fail (self != NULL);
643 gst_class_signal_emit_by_name (object, "object_loaded", self);
645 #endif /* GST_DISABLE_LOADSAVE_REGISTRY */
648 gst_object_set_property (GObject* object, guint prop_id,
649 const GValue* value, GParamSpec* pspec)
651 GstObject *gstobject;
653 /* it's not null if we got it, but it might not be ours */
654 g_return_if_fail (GST_IS_OBJECT (object));
656 gstobject = GST_OBJECT (object);
660 gst_object_set_name (gstobject, g_value_get_string (value));
663 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
669 gst_object_get_property (GObject* object, guint prop_id,
670 GValue* value, GParamSpec* pspec)
672 GstObject *gstobject;
674 /* it's not null if we got it, but it might not be ours */
675 g_return_if_fail (GST_IS_OBJECT (object));
677 gstobject = GST_OBJECT (object);
681 g_value_set_string (value, (gchar*)GST_OBJECT_NAME (gstobject));
684 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
690 * gst_object_get_path_string:
691 * @object: GstObject to get the path from
693 * Generates a string describing the path of the object in
694 * the object hierarchy. Only useful (or used) for debugging
696 * Returns: a string describing the path of the object
699 gst_object_get_path_string (GstObject *object)
701 GSList *parentage = NULL;
704 gchar *prevpath, *path;
705 const char *component;
706 gchar *separator = "";
707 gboolean free_component;
709 parentage = g_slist_prepend (NULL, object);
711 path = g_strdup ("");
713 /* first walk the object hierarchy to build a list of the parents */
715 if (GST_IS_OBJECT (object)) {
716 parent = gst_object_get_parent (object);
718 parentage = g_slist_prepend (parentage, NULL);
722 if (parent != NULL) {
723 parentage = g_slist_prepend (parentage, parent);
727 } while (object != NULL);
729 /* then walk the parent list and print them out */
732 if (GST_IS_OBJECT (parents->data)) {
733 GstObjectClass *oclass = GST_OBJECT_GET_CLASS (parents->data);
735 component = gst_object_get_name (parents->data);
736 separator = oclass->path_string_separator;
737 free_component = FALSE;
739 component = g_strdup_printf("%p",parents->data);
741 free_component = TRUE;
745 path = g_strjoin (separator, prevpath, component, NULL);
748 g_free((gchar *)component);
750 parents = g_slist_next(parents);
753 g_slist_free (parentage);
760 struct _GstSignalObject {
764 struct _GstSignalObjectClass {
765 GObjectClass parent_class;
768 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
769 void (*object_loaded) (GstSignalObject *object, GstObject *new, xmlNodePtr self);
770 #endif /* GST_DISABLE_LOADSAVE_REGISTRY */
774 gst_signal_object_get_type (void)
776 static GType signal_object_type = 0;
778 if (!signal_object_type) {
779 static const GTypeInfo signal_object_info = {
780 sizeof(GstSignalObjectClass),
783 (GClassInitFunc)gst_signal_object_class_init,
786 sizeof(GstSignalObject),
788 (GInstanceInitFunc)gst_signal_object_init,
791 signal_object_type = g_type_register_static(G_TYPE_OBJECT, "GstSignalObject", &signal_object_info, 0);
793 return signal_object_type;
797 gst_signal_object_class_init (GstSignalObjectClass *klass)
799 GObjectClass *gobject_class;
801 gobject_class = (GObjectClass*) klass;
803 parent_class = g_type_class_ref (G_TYPE_OBJECT);
805 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
806 gst_signal_object_signals[SO_OBJECT_LOADED] =
807 g_signal_new ("object_loaded", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
808 G_STRUCT_OFFSET (GstSignalObjectClass, object_loaded), NULL, NULL,
809 gst_marshal_VOID__OBJECT_POINTER, G_TYPE_NONE, 2,
810 G_TYPE_OBJECT, G_TYPE_POINTER);
815 gst_signal_object_init (GstSignalObject *object)
820 * gst_class_signal_connect
821 * @klass: the GstObjectClass to attach the signal to
822 * @name: the name of the signal to attach to
823 * @func: the signal function
824 * @func_data: a pointer to user data
826 * Connect to a class signal.
828 * Returns: the signal id.
831 gst_class_signal_connect (GstObjectClass *klass,
836 return g_signal_connect (klass->signal_object, name, func, func_data);
839 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
841 * gst_class_signal_emit_by_name:
842 * @object: the object that sends the signal
843 * @name: the name of the signal to emit
844 * @self: data for the signal
846 * emits the named class signal.
849 gst_class_signal_emit_by_name (GstObject *object,
853 GstObjectClass *oclass;
855 oclass = GST_OBJECT_GET_CLASS (object);
857 g_signal_emit_by_name (oclass->signal_object, name, object, self);
860 #endif /* GST_DISABLE_LOADSAVE_REGISTRY */