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
47 GType _gst_object_type = 0;
49 typedef struct _GstSignalObject GstSignalObject;
50 typedef struct _GstSignalObjectClass GstSignalObjectClass;
52 static GType gst_signal_object_get_type (void);
53 static void gst_signal_object_class_init (GstSignalObjectClass *klass);
54 static void gst_signal_object_init (GstSignalObject *object);
56 static guint gst_signal_object_signals[SO_LAST_SIGNAL] = { 0 };
58 static void gst_object_class_init (GstObjectClass *klass);
59 static void gst_object_init (GstObject *object);
61 static void gst_object_set_property (GObject * object, guint prop_id, const GValue * value,
63 static void gst_object_get_property (GObject * object, guint prop_id, GValue * value,
66 static void gst_object_dispose (GObject *object);
67 static void gst_object_finalize (GObject *object);
69 static GObjectClass *parent_class = NULL;
70 static guint gst_object_signals[LAST_SIGNAL] = { 0 };
73 gst_object_get_type (void)
75 if (!_gst_object_type) {
76 static const GTypeInfo object_info = {
77 sizeof (GstObjectClass),
80 (GClassInitFunc) gst_object_class_init,
85 (GInstanceInitFunc) gst_object_init,
88 _gst_object_type = g_type_register_static (G_TYPE_OBJECT, "GstObject", &object_info, G_TYPE_FLAG_ABSTRACT);
90 return _gst_object_type;
94 gst_object_class_init (GstObjectClass *klass)
96 GObjectClass *gobject_class;
98 gobject_class = (GObjectClass*) klass;
100 parent_class = g_type_class_ref (G_TYPE_OBJECT);
102 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_object_set_property);
103 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_object_get_property);
105 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_NAME,
106 g_param_spec_string ("name", "Name", "The name of the object",
107 NULL, G_PARAM_READWRITE));
109 gst_object_signals[PARENT_SET] =
110 g_signal_new("parent_set", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
111 G_STRUCT_OFFSET (GstObjectClass, parent_set), NULL, NULL,
112 g_cclosure_marshal_VOID__OBJECT,G_TYPE_NONE,1,
114 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
115 gst_object_signals[OBJECT_SAVED] =
116 g_signal_new("object_saved", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
117 G_STRUCT_OFFSET (GstObjectClass, object_saved), NULL, NULL,
118 g_cclosure_marshal_VOID__POINTER,G_TYPE_NONE,1,
122 klass->path_string_separator = "/";
124 // klass->signal_object = g_object_new(gst_signal_object_get_type (,NULL));
126 gobject_class->dispose = gst_object_dispose;
127 gobject_class->finalize = gst_object_finalize;
131 gst_object_init (GstObject *object)
133 object->lock = g_mutex_new();
134 object->parent = NULL;
138 GST_FLAG_SET (object, GST_FLOATING);
143 * @object: GstObject to reference
145 * Increments the refence count on the object.
147 * Returns: A pointer to the object
150 gst_object_ref (GstObject *object)
152 g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
154 GST_DEBUG (GST_CAT_REFCOUNTING, "ref '%s' %d->%d\n",GST_OBJECT_NAME(object),
155 G_OBJECT(object)->ref_count,G_OBJECT(object)->ref_count+1);
157 g_object_ref (G_OBJECT (object));
160 #define gst_object_ref gst_object_ref
164 * @object: GstObject to unreference
166 * Decrements the refence count on the object. If reference count hits
167 * zero, destroy the object.
170 gst_object_unref (GstObject *object)
172 g_return_if_fail (GST_IS_OBJECT (object));
174 GST_DEBUG (GST_CAT_REFCOUNTING, "unref '%s' %d->%d\n",GST_OBJECT_NAME(object),
175 G_OBJECT(object)->ref_count,G_OBJECT(object)->ref_count-1);
177 g_object_unref (G_OBJECT (object));
179 #define gst_object_unref gst_object_unref
183 * @object: GstObject to sink
185 * Removes floating reference on an object. Any newly created object has
186 * a refcount of 1 and is FLOATING. This function should be used when
187 * creating a new object to symbolically 'take ownership of' the object.
190 gst_object_sink (GstObject *object)
192 g_return_if_fail (object != NULL);
193 g_return_if_fail (GST_IS_OBJECT (object));
195 GST_DEBUG (GST_CAT_REFCOUNTING, "sink '%s'\n",GST_OBJECT_NAME(object));
196 if (GST_OBJECT_FLOATING (object))
198 GST_FLAG_UNSET (object, GST_FLOATING);
199 gst_object_unref (object);
204 * gst_object_destroy:
205 * @object: GstObject to destroy
207 * Destroy the object.
210 gst_object_destroy (GstObject *object)
212 g_return_if_fail (object != NULL);
213 g_return_if_fail (GST_IS_OBJECT (object));
215 GST_DEBUG (GST_CAT_REFCOUNTING, "destroy '%s'\n",GST_OBJECT_NAME(object));
216 if (!GST_OBJECT_DESTROYED (object))
218 /* need to hold a reference count around all class method
221 gst_object_ref (object);
222 G_OBJECT_GET_CLASS (object)->dispose (G_OBJECT (object));
223 gst_object_unref (object);
228 gst_object_dispose (GObject *object)
230 GST_DEBUG (GST_CAT_REFCOUNTING, "dispose '%s'\n",GST_OBJECT_NAME(object));
231 GST_FLAG_SET (GST_OBJECT (object), GST_DESTROYED);
232 GST_OBJECT_PARENT (object) = NULL;
234 parent_class->dispose (object);
237 /* finilize is called when the object has to free its resources */
239 gst_object_finalize (GObject *object)
241 GstObject *gstobject;
243 gstobject = GST_OBJECT (object);
245 GST_DEBUG (GST_CAT_REFCOUNTING, "finalize '%s'\n",GST_OBJECT_NAME(object));
247 if (gstobject->name != NULL)
248 g_free (gstobject->name);
250 g_mutex_free (gstobject->lock);
252 parent_class->finalize (object);
256 * gst_object_set_name:
257 * @object: GstObject to set the name of
258 * @name: new name of object
260 * Set the name of the object.
263 gst_object_set_name (GstObject *object, const gchar *name)
265 g_return_if_fail (object != NULL);
266 g_return_if_fail (GST_IS_OBJECT (object));
267 g_return_if_fail (name != NULL);
269 if (object->name != NULL)
270 g_free (object->name);
272 object->name = g_strdup (name);
276 * gst_object_get_name:
277 * @object: GstObject to get the name of
279 * Get the name of the object.
281 * Returns: name of the object
284 gst_object_get_name (GstObject *object)
286 g_return_val_if_fail (object != NULL, NULL);
287 g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
293 * gst_object_set_parent:
294 * @object: GstObject to set parent of
295 * @parent: new parent of object
297 * Set the parent of the object. The object's reference count is
299 * signals the parent-set signal
302 gst_object_set_parent (GstObject *object, GstObject *parent)
304 g_return_if_fail (object != NULL);
305 g_return_if_fail (GST_IS_OBJECT (object));
306 g_return_if_fail (parent != NULL);
307 g_return_if_fail (GST_IS_OBJECT (parent));
308 g_return_if_fail (object != parent);
310 if (object->parent != NULL) {
311 GST_ERROR_OBJECT (object,object->parent, "object's parent is already set, must unparent first");
315 gst_object_ref (object);
316 gst_object_sink (object);
317 object->parent = parent;
319 g_signal_emit (G_OBJECT (object), gst_object_signals[PARENT_SET], 0, parent);
323 * gst_object_get_parent:
324 * @object: GstObject to get parent of
326 * Return the parent of the object.
328 * Returns: parent of the object
331 gst_object_get_parent (GstObject *object)
333 g_return_val_if_fail (object != NULL, NULL);
334 g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
336 return object->parent;
340 * gst_object_unparent:
341 * @object: GstObject to unparent
343 * Clear the parent of the object, removing the associated reference.
346 gst_object_unparent (GstObject *object)
348 g_return_if_fail (object != NULL);
349 g_return_if_fail (GST_IS_OBJECT(object));
350 if (object->parent == NULL)
353 GST_DEBUG (GST_CAT_REFCOUNTING, "unparent '%s'\n",GST_OBJECT_NAME(object));
355 object->parent = NULL;
356 gst_object_unref (object);
361 * @object: GstObject to reference
363 * Increments the refence count on the object.
365 * Returns: Apointer to the Object
367 #ifndef gst_object_ref
369 gst_object_ref (GstObject *object)
371 g_return_if_fail (object != NULL, NULL);
372 g_return_if_fail (GST_IS_OBJECT (object), NULL);
374 //#ifdef HAVE_ATOMIC_H
375 // g_return_if_fail (atomic_read (&(object->refcount)) > 0);
376 // atomic_inc (&(object->refcount))
378 g_return_if_fail (object->refcount > 0);
380 // object->refcount++;
381 g_object_ref((GObject *)object);
387 #endif /* gst_object_ref */
391 * @object: GstObject to unreference
393 * Decrements the refence count on the object. If reference count hits
394 * zero, destroy the object.
396 #ifndef gst_object_unref
398 gst_object_unref (GstObject *object)
402 g_return_if_fail (object != NULL);
403 g_return_if_fail (GST_IS_OBJECT (object));
406 g_return_if_fail (atomic_read (&(object->refcount)) > 0);
407 reftest = atomic_dec_and_test (&(object->refcount))
409 g_return_if_fail (object->refcount > 0);
412 reftest = (object->refcount == 0);
416 /* if we ended up with the refcount at zero */
418 /* get the count to 1 for gtk_object_destroy() */
420 atomic_set (&(object->refcount),1);
422 object->refcount = 1;
425 gtk_object_destroy (G_OBJECT (object));
426 /* drop the refcount back to zero */
428 atomic_set (&(object->refcount),0);
430 object->refcount = 0;
432 /* finalize the object */
433 // FIXME this is an evil hack that should be killed
434 // FIXMEFIXMEFIXMEFIXME
435 // gtk_object_finalize(G_OBJECT(object));
438 #endif /* gst_object_unref */
441 * gst_object_check_uniqueness:
442 * @list: a list of #GstObject to check through
443 * @name: the name to search for
445 * This function checks through the list of objects to see if the name
446 * given appears in the list as the name of an object. It returns TRUE if
447 * the name does not exist in the list.
449 * Returns: TRUE if the name doesn't appear in the list, FALSE if it does.
452 gst_object_check_uniqueness (GList *list, const gchar *name)
454 g_return_val_if_fail (name != NULL, FALSE);
457 GstObject *child = GST_OBJECT (list->data);
459 list = g_list_next(list);
461 if (strcmp(GST_OBJECT_NAME(child), name) == 0)
469 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
471 * gst_object_save_thyself:
472 * @object: GstObject to save
473 * @parent: The parent XML node to save the object into
475 * Saves the given object into the parent XML node.
477 * Returns: the new xmlNodePtr with the saved object
480 gst_object_save_thyself (GstObject *object, xmlNodePtr parent)
482 GstObjectClass *oclass;
484 g_return_val_if_fail (object != NULL, parent);
485 g_return_val_if_fail (GST_IS_OBJECT (object), parent);
486 g_return_val_if_fail (parent != NULL, parent);
488 oclass = (GstObjectClass *)G_OBJECT_GET_CLASS(object);
489 if (oclass->save_thyself)
490 oclass->save_thyself (object, parent);
492 g_signal_emit (G_OBJECT (object), gst_object_signals[OBJECT_SAVED], 0, parent);
498 * gst_object_restore_thyself:
499 * @object: GstObject to load into
500 * @parent: The parent XML node to load the object from
502 * Restores the given object with the data from the parent XML node.
505 gst_object_restore_thyself (GstObject *object, xmlNodePtr parent)
507 GstObjectClass *oclass;
509 g_return_if_fail (object != NULL);
510 g_return_if_fail (GST_IS_OBJECT (object));
511 g_return_if_fail (parent != NULL);
513 oclass = (GstObjectClass *)G_OBJECT_GET_CLASS(object);
514 if (oclass->restore_thyself)
515 oclass->restore_thyself (object, parent);
517 #endif /* GST_DISABLE_LOADSAVE_REGISTRY */
520 gst_object_set_property (GObject* object, guint prop_id,
521 const GValue* value, GParamSpec* pspec)
523 GstObject *gstobject;
525 /* it's not null if we got it, but it might not be ours */
526 g_return_if_fail (GST_IS_OBJECT (object));
528 gstobject = GST_OBJECT (object);
532 gst_object_set_name (gstobject, g_value_get_string (value));
535 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
541 gst_object_get_property (GObject* object, guint prop_id,
542 GValue* value, GParamSpec* pspec)
544 GstObject *gstobject;
546 /* it's not null if we got it, but it might not be ours */
547 g_return_if_fail (GST_IS_OBJECT (object));
549 gstobject = GST_OBJECT (object);
553 g_value_set_string (value, (gchar*)GST_OBJECT_NAME (gstobject));
556 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
561 * gst_object_get_path_string:
562 * @object: GstObject to get the path from
564 * Generates a string describing the path of the object in
565 * the object hierarchy. Usefull for debugging
567 * Returns: a string describing the path of the object
570 gst_object_get_path_string (GstObject *object)
572 GSList *parentage = NULL;
575 gchar *prevpath, *path;
576 const char *component;
577 gchar *separator = "";
578 gboolean free_component;
580 parentage = g_slist_prepend (NULL, object);
582 path = g_strdup ("");
584 // first walk the object hierarchy to build a list of the parents
586 if (GST_IS_OBJECT (object)) {
587 parent = gst_object_get_parent (object);
589 parentage = g_slist_prepend (parentage, NULL);
593 if (parent != NULL) {
594 parentage = g_slist_prepend (parentage, parent);
598 } while (object != NULL);
600 // then walk the parent list and print them out
603 if (GST_IS_OBJECT (parents->data)) {
604 GstObjectClass *oclass = (GstObjectClass *)G_OBJECT_GET_CLASS(parents->data);
606 component = gst_object_get_name (parents->data);
607 separator = oclass->path_string_separator;
608 free_component = FALSE;
610 component = g_strdup_printf("%p",parents->data);
612 free_component = TRUE;
616 path = g_strjoin (separator, prevpath, component, NULL);
619 g_free((gchar *)component);
621 parents = g_slist_next(parents);
624 g_slist_free (parentage);
631 struct _GstSignalObject {
635 struct _GstSignalObjectClass {
636 GObjectClass parent_class;
639 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
640 void (*object_loaded) (GstSignalObject *object, GstObject *new, xmlNodePtr self);
641 #endif /* GST_DISABLE_LOADSAVE_REGISTRY */
645 gst_signal_object_get_type (void)
647 static GType signal_object_type = 0;
649 if (!signal_object_type) {
650 static const GTypeInfo signal_object_info = {
651 sizeof(GstSignalObjectClass),
654 (GClassInitFunc)gst_signal_object_class_init,
657 sizeof(GstSignalObject),
659 (GInstanceInitFunc)gst_signal_object_init,
662 signal_object_type = g_type_register_static(G_TYPE_OBJECT, "GstSignalObject", &signal_object_info, 0);
664 return signal_object_type;
668 gst_signal_object_class_init (GstSignalObjectClass *klass)
670 GObjectClass *gobject_class;
672 gobject_class = (GObjectClass*) klass;
674 parent_class = g_type_class_ref (G_TYPE_OBJECT);
676 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
677 gst_signal_object_signals[SO_OBJECT_LOADED] =
678 g_signal_new("object_loaded", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
679 G_STRUCT_OFFSET (GstObjectClass, parent_set), NULL, NULL,
680 gst_marshal_VOID__OBJECT_POINTER,G_TYPE_NONE,2,
681 G_TYPE_OBJECT,G_TYPE_POINTER);
686 gst_signal_object_init (GstSignalObject *object)
691 * gst_class_signal_connect
692 * @klass: the GstObjectClass to attach the signal to
693 * @name: the name of the signal to attach to
694 * @func: the signal function
695 * @func_data: a pointer to user data
697 * Connect to a class signal.
699 * Returns: the signal id.
702 gst_class_signal_connect (GstObjectClass *klass,
707 return g_signal_connect (klass->signal_object, name, func, func_data);
710 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
712 * gst_class_signal_emit_by_name:
713 * @object: the object that sends the signal
714 * @name: the name of the signal to emit
715 * @self: data for the signal
717 * emits the named class signal.
720 gst_class_signal_emit_by_name (GstObject *object,
724 GstObjectClass *oclass;
726 oclass = (GstObjectClass *)G_OBJECT_GET_CLASS(object);
728 g_signal_emit_by_name (oclass->signal_object, name, object, self);
731 #endif /* GST_DISABLE_LOADSAVE_REGISTRY */