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 /* Object signals and args */
30 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
46 GType _gst_object_type = 0;
48 typedef struct _GstSignalObject GstSignalObject;
49 typedef struct _GstSignalObjectClass GstSignalObjectClass;
51 static GType gst_signal_object_get_type (void);
52 static void gst_signal_object_class_init (GstSignalObjectClass *klass);
53 static void gst_signal_object_init (GstSignalObject *object);
55 static guint gst_signal_object_signals[SO_LAST_SIGNAL] = { 0 };
57 static void gst_object_class_init (GstObjectClass *klass);
58 static void gst_object_init (GstObject *object);
60 static void gst_object_dispose (GObject *object);
61 static void gst_object_finalize (GObject *object);
63 static GObjectClass *parent_class = NULL;
64 static guint gst_object_signals[LAST_SIGNAL] = { 0 };
67 gst_object_get_type (void)
69 if (!_gst_object_type) {
70 static const GTypeInfo object_info = {
71 sizeof (GstObjectClass),
74 (GClassInitFunc) gst_object_class_init,
79 (GInstanceInitFunc) gst_object_init,
82 _gst_object_type = g_type_register_static (G_TYPE_OBJECT, "GstObject", &object_info, G_TYPE_FLAG_ABSTRACT);
84 return _gst_object_type;
88 gst_object_class_init (GstObjectClass *klass)
90 GObjectClass *gobject_class;
92 gobject_class = (GObjectClass*) klass;
94 parent_class = g_type_class_ref (G_TYPE_OBJECT);
96 gst_object_signals[PARENT_SET] =
97 g_signal_new("parent_set", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
98 G_STRUCT_OFFSET (GstObjectClass, parent_set), NULL, NULL,
99 g_cclosure_marshal_VOID__OBJECT,G_TYPE_NONE,1,
101 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
102 gst_object_signals[OBJECT_SAVED] =
103 g_signal_new("object_saved", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
104 G_STRUCT_OFFSET (GstObjectClass, object_saved), NULL, NULL,
105 g_cclosure_marshal_VOID__POINTER,G_TYPE_NONE,1,
109 klass->path_string_separator = "/";
111 // klass->signal_object = g_object_new(gst_signal_object_get_type (,NULL));
113 gobject_class->dispose = gst_object_dispose;
114 gobject_class->finalize = gst_object_finalize;
118 gst_object_init (GstObject *object)
120 object->lock = g_mutex_new();
121 object->parent = NULL;
124 GST_FLAG_SET (object, GST_FLOATING);
129 * @object: GstObject to reference
131 * Increments the refence count on the object.
133 * Returns: A pointer to the object
136 gst_object_ref (GstObject *object)
138 g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
140 GST_DEBUG (GST_CAT_REFCOUNTING, "ref '%s' %d->%d\n",GST_OBJECT_NAME(object),
141 G_OBJECT(object)->ref_count,G_OBJECT(object)->ref_count+1);
143 g_object_ref (G_OBJECT (object));
146 #define gst_object_ref gst_object_ref
150 * @object: GstObject to unreference
152 * Decrements the refence count on the object. If reference count hits
153 * zero, destroy the object.
156 gst_object_unref (GstObject *object)
158 g_return_if_fail (GST_IS_OBJECT (object));
160 GST_DEBUG (GST_CAT_REFCOUNTING, "unref '%s' %d->%d\n",GST_OBJECT_NAME(object),
161 G_OBJECT(object)->ref_count,G_OBJECT(object)->ref_count-1);
163 g_object_unref (G_OBJECT (object));
165 #define gst_object_unref gst_object_unref
169 * @object: GstObject to sink
171 * Removes floating reference on an object. Any newly created object has
172 * a refcount of 1 and is FLOATING. This function should be used when
173 * creating a new object to symbolically 'take ownership of' the object.
176 gst_object_sink (GstObject *object)
178 g_return_if_fail (object != NULL);
179 g_return_if_fail (GST_IS_OBJECT (object));
181 GST_DEBUG (GST_CAT_REFCOUNTING, "sink '%s'\n",GST_OBJECT_NAME(object));
182 if (GST_OBJECT_FLOATING (object))
184 GST_FLAG_UNSET (object, GST_FLOATING);
185 gst_object_unref (object);
190 * gst_object_destroy:
191 * @object: GstObject to destroy
193 * Destroy the object.
196 gst_object_destroy (GstObject *object)
198 g_return_if_fail (object != NULL);
199 g_return_if_fail (GST_IS_OBJECT (object));
201 GST_DEBUG (GST_CAT_REFCOUNTING, "destroy '%s'\n",GST_OBJECT_NAME(object));
202 if (!GST_OBJECT_DESTROYED (object))
204 /* need to hold a reference count around all class method
207 gst_object_ref (object);
208 G_OBJECT_GET_CLASS (object)->dispose (G_OBJECT (object));
209 gst_object_unref (object);
214 gst_object_dispose (GObject *object)
216 GST_DEBUG (GST_CAT_REFCOUNTING, "dispose '%s'\n",GST_OBJECT_NAME(object));
217 GST_FLAG_SET (GST_OBJECT (object), GST_DESTROYED);
218 GST_OBJECT_PARENT (object) = NULL;
220 parent_class->dispose (object);
223 /* finilize is called when the object has to free its resources */
225 gst_object_finalize (GObject *object)
227 GstObject *gstobject;
229 gstobject = GST_OBJECT (object);
231 GST_DEBUG (GST_CAT_REFCOUNTING, "finalize '%s'\n",GST_OBJECT_NAME(object));
233 if (gstobject->name != NULL)
234 g_free (gstobject->name);
236 g_mutex_free (gstobject->lock);
238 parent_class->finalize (object);
242 * gst_object_set_name:
243 * @object: GstObject to set the name of
244 * @name: new name of object
246 * Set the name of the object.
249 gst_object_set_name (GstObject *object, const gchar *name)
251 g_return_if_fail (object != NULL);
252 g_return_if_fail (GST_IS_OBJECT (object));
253 g_return_if_fail (name != NULL);
255 if (object->name != NULL)
256 g_free (object->name);
258 object->name = g_strdup (name);
262 * gst_object_get_name:
263 * @object: GstObject to get the name of
265 * Get the name of the object.
267 * Returns: name of the object
270 gst_object_get_name (GstObject *object)
272 g_return_val_if_fail (object != NULL, NULL);
273 g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
279 * gst_object_set_parent:
280 * @object: GstObject to set parent of
281 * @parent: new parent of object
283 * Set the parent of the object. The object's reference count is
285 * signals the parent-set signal
288 gst_object_set_parent (GstObject *object, GstObject *parent)
290 g_return_if_fail (object != NULL);
291 g_return_if_fail (GST_IS_OBJECT (object));
292 g_return_if_fail (parent != NULL);
293 g_return_if_fail (GST_IS_OBJECT (parent));
294 g_return_if_fail (object != parent);
296 if (object->parent != NULL) {
297 GST_ERROR_OBJECT (object,object->parent, "object's parent is already set, must unparent first");
301 gst_object_ref (object);
302 gst_object_sink (object);
303 object->parent = parent;
305 g_signal_emit (G_OBJECT (object), gst_object_signals[PARENT_SET], 0, parent);
309 * gst_object_get_parent:
310 * @object: GstObject to get parent of
312 * Return the parent of the object.
314 * Returns: parent of the object
317 gst_object_get_parent (GstObject *object)
319 g_return_val_if_fail (object != NULL, NULL);
320 g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
322 return object->parent;
326 * gst_object_unparent:
327 * @object: GstObject to unparent
329 * Clear the parent of the object, removing the associated reference.
332 gst_object_unparent (GstObject *object)
334 g_return_if_fail (object != NULL);
335 g_return_if_fail (GST_IS_OBJECT(object));
336 if (object->parent == NULL)
339 GST_DEBUG (GST_CAT_REFCOUNTING, "unparent '%s'\n",GST_OBJECT_NAME(object));
341 object->parent = NULL;
342 gst_object_unref (object);
347 * @object: GstObject to reference
349 * Increments the refence count on the object.
351 * Returns: Apointer to the Object
353 #ifndef gst_object_ref
355 gst_object_ref (GstObject *object)
357 g_return_if_fail (object != NULL, NULL);
358 g_return_if_fail (GST_IS_OBJECT (object), NULL);
360 //#ifdef HAVE_ATOMIC_H
361 // g_return_if_fail (atomic_read (&(object->refcount)) > 0);
362 // atomic_inc (&(object->refcount))
364 g_return_if_fail (object->refcount > 0);
366 // object->refcount++;
367 g_object_ref((GObject *)object);
373 #endif /* gst_object_ref */
377 * @object: GstObject to unreference
379 * Decrements the refence count on the object. If reference count hits
380 * zero, destroy the object.
382 #ifndef gst_object_unref
384 gst_object_unref (GstObject *object)
388 g_return_if_fail (object != NULL);
389 g_return_if_fail (GST_IS_OBJECT (object));
392 g_return_if_fail (atomic_read (&(object->refcount)) > 0);
393 reftest = atomic_dec_and_test (&(object->refcount))
395 g_return_if_fail (object->refcount > 0);
398 reftest = (object->refcount == 0);
402 /* if we ended up with the refcount at zero */
404 /* get the count to 1 for gtk_object_destroy() */
406 atomic_set (&(object->refcount),1);
408 object->refcount = 1;
411 gtk_object_destroy (G_OBJECT (object));
412 /* drop the refcount back to zero */
414 atomic_set (&(object->refcount),0);
416 object->refcount = 0;
418 /* finalize the object */
419 // FIXME this is an evil hack that should be killed
420 // FIXMEFIXMEFIXMEFIXME
421 // gtk_object_finalize(G_OBJECT(object));
424 #endif /* gst_object_unref */
427 * gst_object_check_uniqueness:
428 * @list: a list of #GstObject to check through
429 * @name: the name to search for
431 * This function checks through the list of objects to see if the name
432 * given appears in the list as the name of an object. It returns TRUE if
433 * the name does not exist in the list.
435 * Returns: TRUE if the name doesn't appear in the list, FALSE if it does.
438 gst_object_check_uniqueness (GList *list, const gchar *name)
440 g_return_val_if_fail (name != NULL, FALSE);
443 GstObject *child = GST_OBJECT (list->data);
445 list = g_list_next(list);
447 if (strcmp(GST_OBJECT_NAME(child), name) == 0)
455 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
457 * gst_object_save_thyself:
458 * @object: GstObject to save
459 * @parent: The parent XML node to save the object into
461 * Saves the given object into the parent XML node.
463 * Returns: the new xmlNodePtr with the saved object
466 gst_object_save_thyself (GstObject *object, xmlNodePtr parent)
468 GstObjectClass *oclass;
470 g_return_val_if_fail (object != NULL, parent);
471 g_return_val_if_fail (GST_IS_OBJECT (object), parent);
472 g_return_val_if_fail (parent != NULL, parent);
474 oclass = (GstObjectClass *)G_OBJECT_GET_CLASS(object);
475 if (oclass->save_thyself)
476 oclass->save_thyself (object, parent);
478 g_signal_emit (G_OBJECT (object), gst_object_signals[OBJECT_SAVED], 0, parent);
484 * gst_object_restore_thyself:
485 * @object: GstObject to load into
486 * @parent: The parent XML node to load the object from
488 * Restores the given object with the data from the parent XML node.
491 gst_object_restore_thyself (GstObject *object, xmlNodePtr parent)
493 GstObjectClass *oclass;
495 g_return_if_fail (object != NULL);
496 g_return_if_fail (GST_IS_OBJECT (object));
497 g_return_if_fail (parent != NULL);
499 oclass = (GstObjectClass *)G_OBJECT_GET_CLASS(object);
500 if (oclass->restore_thyself)
501 oclass->restore_thyself (object, parent);
503 #endif /* GST_DISABLE_LOADSAVE_REGISTRY */
506 * gst_object_get_path_string:
507 * @object: GstObject to get the path from
509 * Generates a string describing the path of the object in
510 * the object hierarchy. Usefull for debugging
512 * Returns: a string describing the path of the object
515 gst_object_get_path_string (GstObject *object)
517 GSList *parentage = NULL;
520 gchar *prevpath, *path;
521 const char *component;
522 gchar *separator = "";
523 gboolean free_component;
525 parentage = g_slist_prepend (NULL, object);
527 path = g_strdup ("");
529 // first walk the object hierarchy to build a list of the parents
531 if (GST_IS_OBJECT (object)) {
532 parent = gst_object_get_parent (object);
534 parentage = g_slist_prepend (parentage, NULL);
538 if (parent != NULL) {
539 parentage = g_slist_prepend (parentage, parent);
543 } while (object != NULL);
545 // then walk the parent list and print them out
548 if (GST_IS_OBJECT (parents->data)) {
549 GstObjectClass *oclass = (GstObjectClass *)G_OBJECT_GET_CLASS(parents->data);
551 component = gst_object_get_name (parents->data);
552 separator = oclass->path_string_separator;
553 free_component = FALSE;
555 component = g_strdup_printf("%p",parents->data);
557 free_component = TRUE;
561 path = g_strjoin (separator, prevpath, component, NULL);
564 g_free((gchar *)component);
566 parents = g_slist_next(parents);
569 g_slist_free (parentage);
576 struct _GstSignalObject {
580 struct _GstSignalObjectClass {
581 GObjectClass parent_class;
584 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
585 void (*object_loaded) (GstSignalObject *object, GstObject *new, xmlNodePtr self);
586 #endif /* GST_DISABLE_LOADSAVE_REGISTRY */
590 gst_signal_object_get_type (void)
592 static GType signal_object_type = 0;
594 if (!signal_object_type) {
595 static const GTypeInfo signal_object_info = {
596 sizeof(GstSignalObjectClass),
599 (GClassInitFunc)gst_signal_object_class_init,
602 sizeof(GstSignalObject),
604 (GInstanceInitFunc)gst_signal_object_init,
607 signal_object_type = g_type_register_static(G_TYPE_OBJECT, "GstSignalObject", &signal_object_info, 0);
609 return signal_object_type;
613 gst_signal_object_class_init (GstSignalObjectClass *klass)
615 GObjectClass *gobject_class;
617 gobject_class = (GObjectClass*) klass;
619 parent_class = g_type_class_ref (G_TYPE_OBJECT);
621 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
622 gst_signal_object_signals[SO_OBJECT_LOADED] =
623 g_signal_new("object_loaded", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
624 G_STRUCT_OFFSET (GstObjectClass, parent_set), NULL, NULL,
625 gst_marshal_VOID__OBJECT_POINTER,G_TYPE_NONE,2,
626 G_TYPE_OBJECT,G_TYPE_POINTER);
631 gst_signal_object_init (GstSignalObject *object)
636 * gst_class_signal_connect
637 * @klass: the GstObjectClass to attach the signal to
638 * @name: the name of the signal to attach to
639 * @func: the signal function
640 * @func_data: a pointer to user data
642 * Connect to a class signal.
644 * Returns: the signal id.
647 gst_class_signal_connect (GstObjectClass *klass,
652 return g_signal_connect (klass->signal_object, name, func, func_data);
655 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
657 * gst_class_signal_emit_by_name:
658 * @object: the object that sends the signal
659 * @name: the name of the signal to emit
660 * @self: data for the signal
662 * emits the named class signal.
665 gst_class_signal_emit_by_name (GstObject *object,
669 GstObjectClass *oclass;
671 oclass = (GstObjectClass *)G_OBJECT_GET_CLASS(object);
673 g_signal_emit_by_name (oclass->signal_object, name, object, self);
676 #endif /* GST_DISABLE_LOADSAVE_REGISTRY */