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_XML
46 typedef struct _GstSignalObject GstSignalObject;
47 typedef struct _GstSignalObjectClass GstSignalObjectClass;
49 static GtkType gst_signal_object_get_type (void);
50 static void gst_signal_object_class_init (GstSignalObjectClass *klass);
51 static void gst_signal_object_init (GstSignalObject *object);
53 static guint gst_signal_object_signals[SO_LAST_SIGNAL] = { 0 };
55 static void gst_object_class_init (GstObjectClass *klass);
56 static void gst_object_init (GstObject *object);
58 static void gst_object_real_destroy (GtkObject *gtk_object);
59 static void gst_object_shutdown (GtkObject *gtk_object);
60 static void gst_object_finalize (GtkObject *gtk_object);
62 static GtkObjectClass *parent_class = NULL;
63 static guint gst_object_signals[LAST_SIGNAL] = { 0 };
66 gst_object_inititialize (void)
71 gst_object_get_type (void)
73 static GtkType object_type = 0;
76 static const GtkTypeInfo object_info = {
79 sizeof(GstObjectClass),
80 (GtkClassInitFunc)gst_object_class_init,
81 (GtkObjectInitFunc)gst_object_init,
84 (GtkClassInitFunc)NULL,
86 object_type = gtk_type_unique(gtk_object_get_type(),&object_info);
92 gst_object_class_init (GstObjectClass *klass)
94 GtkObjectClass *gtkobject_class;
96 gtkobject_class = (GtkObjectClass*) klass;
98 parent_class = gtk_type_class (gtk_object_get_type ());
100 gst_object_signals[PARENT_SET] =
101 gtk_signal_new ("parent_set", GTK_RUN_LAST, gtkobject_class->type,
102 GTK_SIGNAL_OFFSET (GstObjectClass, parent_set),
103 gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1,
105 #ifndef GST_DISABLE_XML
106 gst_object_signals[OBJECT_SAVED] =
107 gtk_signal_new ("object_saved", GTK_RUN_LAST, gtkobject_class->type,
108 GTK_SIGNAL_OFFSET (GstObjectClass, object_saved),
109 gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1,
112 gtk_object_class_add_signals (gtkobject_class, gst_object_signals, LAST_SIGNAL);
114 klass->path_string_separator = "/";
115 klass->signal_object = gtk_type_new (gst_signal_object_get_type ());
117 gtkobject_class->shutdown = gst_object_shutdown;
118 gtkobject_class->destroy = gst_object_real_destroy;
119 gtkobject_class->finalize = gst_object_finalize;
123 gst_object_init (GstObject *object)
125 GstObjectClass *oclass;
127 oclass = GST_OBJECT_CLASS (GTK_OBJECT (object)->klass);
129 object->lock = g_mutex_new();
131 atomic_set(&(object->refcount),1);
133 object->refcount = 1;
135 object->parent = NULL;
138 GST_FLAG_SET (object, GST_FLOATING);
144 * Create a new, empty object. Not very useful, should never be used.
146 * Returns: new object
149 gst_object_new (void)
151 return GST_OBJECT (gtk_type_new (gst_object_get_type ()));
156 * @object: GstObject to reference
158 * Increments the refence count on the object.
160 * Returns: A pointer to the object
163 gst_object_ref (GstObject *object)
165 g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
167 GST_DEBUG (GST_CAT_REFCOUNTING, "ref '%s' %d->%d\n",GST_OBJECT_NAME(object),
168 GTK_OBJECT(object)->ref_count,GTK_OBJECT(object)->ref_count+1);
170 gtk_object_ref (GTK_OBJECT (object));
174 #define gst_object_ref gst_object_ref
178 * @object: GstObject to unreference
180 * Decrements the refence count on the object. If reference count hits
181 * zero, destroy the object.
184 gst_object_unref (GstObject *object)
186 g_return_if_fail (GST_IS_OBJECT (object));
188 GST_DEBUG (GST_CAT_REFCOUNTING, "unref '%s' %d->%d\n",GST_OBJECT_NAME(object),
189 GTK_OBJECT(object)->ref_count,GTK_OBJECT(object)->ref_count-1);
191 gtk_object_unref (GTK_OBJECT (object));
193 #define gst_object_unref gst_object_unref
197 * @object: GstObject to sink
199 * Removes floating reference on an object. Any newly created object has
200 * a refcount of 1 and is FLOATING. This function should be used when
201 * creating a new object to symbolically 'take ownership of' the object.
204 gst_object_sink (GstObject *object)
206 g_return_if_fail (object != NULL);
207 g_return_if_fail (GST_IS_OBJECT (object));
209 GST_DEBUG (GST_CAT_REFCOUNTING, "sink '%s'\n",GST_OBJECT_NAME(object));
210 if (GST_OBJECT_FLOATING (object))
212 GST_FLAG_UNSET (object, GST_FLOATING);
213 gst_object_unref (object);
218 gst_object_destroy (GstObject *object)
220 g_return_if_fail (object != NULL);
221 g_return_if_fail (GST_IS_OBJECT (object));
223 GST_DEBUG (GST_CAT_REFCOUNTING, "destroy '%s'\n",GST_OBJECT_NAME(object));
224 if (!GST_OBJECT_DESTROYED (object))
226 /* need to hold a reference count around all class method
229 gst_object_ref (object);
230 GTK_OBJECT (object)->klass->shutdown (GTK_OBJECT (object));
231 gst_object_unref (object);
236 gst_object_shutdown (GtkObject *object)
238 GST_DEBUG (GST_CAT_REFCOUNTING, "shutdown '%s'\n",GST_OBJECT_NAME(object));
239 GST_FLAG_SET (GST_OBJECT (object), GST_DESTROYED);
240 parent_class->shutdown (GTK_OBJECT (object));
243 /* finilize is called when the object has to free its resources */
245 gst_object_real_destroy (GtkObject *gtk_object)
247 GST_DEBUG (GST_CAT_REFCOUNTING, "destroy '%s'\n",GST_OBJECT_NAME(gtk_object));
249 GST_OBJECT_PARENT (gtk_object) = NULL;
251 parent_class->destroy (gtk_object);
254 /* finilize is called when the object has to free its resources */
256 gst_object_finalize (GtkObject *gtk_object)
260 object = GST_OBJECT (gtk_object);
262 GST_DEBUG (GST_CAT_REFCOUNTING, "finalize '%s'\n",GST_OBJECT_NAME(object));
264 if (object->name != NULL)
265 g_free (object->name);
267 g_mutex_free (object->lock);
269 parent_class->finalize (gtk_object);
273 * gst_object_set_name:
274 * @object: GstObject to set the name of
275 * @name: new name of object
277 * Set the name of the object.
280 gst_object_set_name (GstObject *object, const gchar *name)
282 g_return_if_fail (object != NULL);
283 g_return_if_fail (GST_IS_OBJECT (object));
284 g_return_if_fail (name != NULL);
286 if (object->name != NULL)
287 g_free (object->name);
289 object->name = g_strdup (name);
293 * gst_object_get_name:
294 * @object: GstObject to get the name of
296 * Get the name of the object.
298 * Returns: name of the object
301 gst_object_get_name (GstObject *object)
303 g_return_val_if_fail (object != NULL, NULL);
304 g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
310 * gst_object_set_parent:
311 * @object: GstObject to set parent of
312 * @parent: new parent of object
314 * Set the parent of the object. The object's reference count is
316 * signals the parent-set signal
319 gst_object_set_parent (GstObject *object, GstObject *parent)
321 g_return_if_fail (object != NULL);
322 g_return_if_fail (GST_IS_OBJECT (object));
323 g_return_if_fail (parent != NULL);
324 g_return_if_fail (GST_IS_OBJECT (parent));
325 g_return_if_fail (object != parent);
327 if (object->parent != NULL) {
328 GST_ERROR_OBJECT (object,object->parent, "object's parent is already set, must unparent first");
332 gst_object_ref (object);
333 gst_object_sink (object);
334 object->parent = parent;
336 gtk_signal_emit (GTK_OBJECT (object), gst_object_signals[PARENT_SET], parent);
340 * gst_object_get_parent:
341 * @object: GstObject to get parent of
343 * Return the parent of the object.
345 * Returns: parent of the object
348 gst_object_get_parent (GstObject *object)
350 g_return_val_if_fail (object != NULL, NULL);
351 g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
353 return object->parent;
357 * gst_object_unparent:
358 * @object: GstObject to unparent
360 * Clear the parent of the object, removing the associated reference.
363 gst_object_unparent (GstObject *object)
365 g_return_if_fail (object != NULL);
366 g_return_if_fail (GST_IS_OBJECT(object));
367 if (object->parent == NULL)
370 object->parent = NULL;
371 gst_object_unref (object);
376 * @object: GstObject to reference
378 * Increments the refence count on the object.
380 * Returns: Apointer to the Object
382 #ifndef gst_object_ref
384 gst_object_ref (GstObject *object)
386 g_return_if_fail (object != NULL, NULL);
387 g_return_if_fail (GST_IS_OBJECT (object), NULL);
390 g_return_if_fail (atomic_read (&(object->refcount)) > 0);
391 atomic_inc (&(object->refcount))
393 g_return_if_fail (object->refcount > 0);
401 #endif /* gst_object_ref */
405 * @object: GstObject to unreference
407 * Decrements the refence count on the object. If reference count hits
408 * zero, destroy the object.
410 #ifndef gst_object_unref
412 gst_object_unref (GstObject *object)
416 g_return_if_fail (object != NULL);
417 g_return_if_fail (GST_IS_OBJECT (object));
420 g_return_if_fail (atomic_read (&(object->refcount)) > 0);
421 reftest = atomic_dec_and_test (&(object->refcount))
423 g_return_if_fail (object->refcount > 0);
426 reftest = (object->refcount == 0);
430 /* if we ended up with the refcount at zero */
432 /* get the count to 1 for gtk_object_destroy() */
434 atomic_set (&(object->refcount),1);
436 object->refcount = 1;
439 gtk_object_destroy (GTK_OBJECT (object));
440 /* drop the refcount back to zero */
442 atomic_set (&(object->refcount),0);
444 object->refcount = 0;
446 /* finalize the object */
447 // FIXME this is an evil hack that should be killed
448 // FIXMEFIXMEFIXMEFIXME
449 // gtk_object_finalize(GTK_OBJECT(object));
452 #endif /* gst_object_unref */
455 * gst_object_check_uniqueness:
456 * @list: a list of #GstObject to check through
457 * @name: the name to search for
459 * This function checks through the list of objects to see if the name
460 * given appears in the list as the name of an object. It returns TRUE if
461 * the name does not exist in the list.
463 * Returns: TRUE if the name doesn't appear in the list, FALSE if it does.
466 gst_object_check_uniqueness (GList *list, const gchar *name)
471 child = GST_OBJECT (list->data);
472 list = g_list_next(list);
474 if (strcmp(GST_OBJECT_NAME(child), name) == 0) return FALSE;
481 #ifndef GST_DISABLE_XML
484 * gst_object_save_thyself:
485 * @object: GstObject to save
486 * @parent: The parent XML node to save the object into
488 * Saves the given object into the parent XML node.
490 * Returns: the new xmlNodePtr with the saved object
493 gst_object_save_thyself (GstObject *object, xmlNodePtr parent)
495 GstObjectClass *oclass;
497 g_return_val_if_fail (object != NULL, parent);
498 g_return_val_if_fail (GST_IS_OBJECT (object), parent);
499 g_return_val_if_fail (parent != NULL, parent);
501 oclass = GST_OBJECT_CLASS (GTK_OBJECT (object)->klass);
503 if (oclass->save_thyself)
504 oclass->save_thyself (object, parent);
506 #ifndef GST_DISABLE_XML
507 gtk_signal_emit (GTK_OBJECT (object), gst_object_signals[OBJECT_SAVED], parent);
513 #endif // GST_DISABLE_XML
516 * gst_object_get_path_string:
517 * @object: GstObject to get the path from
519 * Generates a string describing the path of the object in
520 * the object hierarchy. Usefull for debugging
522 * Returns: a string describing the path of the object
525 gst_object_get_path_string (GstObject *object)
527 GSList *parentage = NULL;
530 gchar *prevpath, *path;
531 const char *component;
532 gchar *separator = "";
533 gboolean free_component;
535 parentage = g_slist_prepend (NULL, object);
537 path = g_strdup ("");
539 // first walk the object hierarchy to build a list of the parents
541 if (GST_IS_OBJECT (object)) {
542 parent = gst_object_get_parent (object);
544 parentage = g_slist_prepend (parentage, NULL);
548 if (parent != NULL) {
549 parentage = g_slist_prepend (parentage, parent);
553 } while (object != NULL);
555 // then walk the parent list and print them out
558 if (GST_IS_OBJECT (parents->data)) {
559 GstObjectClass *oclass = GST_OBJECT_CLASS (GTK_OBJECT (parents->data)->klass);
561 component = gst_object_get_name (parents->data);
562 separator = oclass->path_string_separator;
563 free_component = FALSE;
565 component = g_strdup_printf("%p",parents->data);
567 free_component = TRUE;
571 path = g_strjoin (separator, prevpath, component, NULL);
574 g_free((gchar *)component);
576 parents = g_slist_next(parents);
579 g_slist_free (parentage);
586 struct _GstSignalObject {
590 struct _GstSignalObjectClass {
591 GtkObjectClass parent_class;
594 #ifndef GST_DISABLE_XML
595 void (*object_loaded) (GstSignalObject *object, GstObject *new, xmlNodePtr self);
596 #endif GST_DISABLE_XML
600 gst_signal_object_get_type (void)
602 static GtkType signal_object_type = 0;
604 if (!signal_object_type) {
605 static const GtkTypeInfo signal_object_info = {
607 sizeof(GstSignalObject),
608 sizeof(GstSignalObjectClass),
609 (GtkClassInitFunc)gst_signal_object_class_init,
610 (GtkObjectInitFunc)gst_signal_object_init,
613 (GtkClassInitFunc)NULL,
615 signal_object_type = gtk_type_unique(gtk_object_get_type(),&signal_object_info);
617 return signal_object_type;
621 gst_signal_object_class_init (GstSignalObjectClass *klass)
623 GtkObjectClass *gtkobject_class;
625 gtkobject_class = (GtkObjectClass*) klass;
627 parent_class = gtk_type_class (gtk_object_get_type ());
629 #ifndef GST_DISABLE_XML
630 gst_signal_object_signals[SO_OBJECT_LOADED] =
631 gtk_signal_new ("object_loaded", GTK_RUN_LAST, gtkobject_class->type,
632 GTK_SIGNAL_OFFSET (GstSignalObjectClass, object_loaded),
633 gtk_marshal_NONE__POINTER_POINTER, GTK_TYPE_NONE, 2,
634 GST_TYPE_OBJECT, GTK_TYPE_POINTER);
635 gtk_object_class_add_signals (gtkobject_class, gst_signal_object_signals, LAST_SIGNAL);
640 gst_signal_object_init (GstSignalObject *object)
645 * gst_class_signal_connect
646 * @klass: the GstObjectClass to attach the signal to
647 * @name: the name of the signal to attach to
648 * @func: the signal function
649 * @func_data: a pointer to user data
651 * Connect to a class signal.
653 * Returns: the signal id.
656 gst_class_signal_connect (GstObjectClass *klass,
661 return gtk_signal_connect (klass->signal_object, name, func, func_data);
664 #ifndef GST_DISABLE_XML
666 * gst_class_signal_emit_by_name:
667 * @object: the object that sends the signal
668 * @name: the name of the signal to emit
669 * @self: data for the signal
671 * emits the named class signal.
674 gst_class_signal_emit_by_name (GstObject *object,
678 GstObjectClass *oclass;
680 oclass = GST_OBJECT_CLASS (GTK_OBJECT (object)->klass);
682 gtk_signal_emit_by_name (oclass->signal_object, name, object, self);
685 #endif // GST_DISABLE_XML