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 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_NAME,
103 g_param_spec_string ("name", "Name", "The name of the object",
104 NULL, G_PARAM_READWRITE));
106 gst_object_signals[PARENT_SET] =
107 g_signal_new("parent_set", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
108 G_STRUCT_OFFSET (GstObjectClass, parent_set), NULL, NULL,
109 g_cclosure_marshal_VOID__OBJECT,G_TYPE_NONE,1,
111 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
112 gst_object_signals[OBJECT_SAVED] =
113 g_signal_new("object_saved", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
114 G_STRUCT_OFFSET (GstObjectClass, object_saved), NULL, NULL,
115 g_cclosure_marshal_VOID__POINTER,G_TYPE_NONE,1,
119 klass->path_string_separator = "/";
121 // klass->signal_object = g_object_new(gst_signal_object_get_type (,NULL));
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 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;
137 GST_FLAG_SET (object, GST_FLOATING);
142 * @object: GstObject to reference
144 * Increments the refence count on the object.
146 * Returns: A pointer to the object
149 gst_object_ref (GstObject *object)
151 g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
153 GST_DEBUG (GST_CAT_REFCOUNTING, "ref '%s' %d->%d\n",GST_OBJECT_NAME(object),
154 G_OBJECT(object)->ref_count,G_OBJECT(object)->ref_count+1);
156 g_object_ref (G_OBJECT (object));
159 #define gst_object_ref gst_object_ref
163 * @object: GstObject to unreference
165 * Decrements the refence count on the object. If reference count hits
166 * zero, destroy the object.
169 gst_object_unref (GstObject *object)
171 g_return_if_fail (GST_IS_OBJECT (object));
173 GST_DEBUG (GST_CAT_REFCOUNTING, "unref '%s' %d->%d\n",GST_OBJECT_NAME(object),
174 G_OBJECT(object)->ref_count,G_OBJECT(object)->ref_count-1);
176 g_object_unref (G_OBJECT (object));
178 #define gst_object_unref gst_object_unref
182 * @object: GstObject to sink
184 * Removes floating reference on an object. Any newly created object has
185 * a refcount of 1 and is FLOATING. This function should be used when
186 * creating a new object to symbolically 'take ownership of' the object.
189 gst_object_sink (GstObject *object)
191 g_return_if_fail (object != NULL);
192 g_return_if_fail (GST_IS_OBJECT (object));
194 GST_DEBUG (GST_CAT_REFCOUNTING, "sink '%s'\n",GST_OBJECT_NAME(object));
195 if (GST_OBJECT_FLOATING (object))
197 GST_FLAG_UNSET (object, GST_FLOATING);
198 gst_object_unref (object);
203 * gst_object_destroy:
204 * @object: GstObject to destroy
206 * Destroy the object.
209 gst_object_destroy (GstObject *object)
211 g_return_if_fail (object != NULL);
212 g_return_if_fail (GST_IS_OBJECT (object));
214 GST_DEBUG (GST_CAT_REFCOUNTING, "destroy '%s'\n",GST_OBJECT_NAME(object));
215 if (!GST_OBJECT_DESTROYED (object))
217 /* need to hold a reference count around all class method
220 gst_object_ref (object);
221 G_OBJECT_GET_CLASS (object)->dispose (G_OBJECT (object));
222 gst_object_unref (object);
227 gst_object_dispose (GObject *object)
229 GST_DEBUG (GST_CAT_REFCOUNTING, "dispose '%s'\n",GST_OBJECT_NAME(object));
230 GST_FLAG_SET (GST_OBJECT (object), GST_DESTROYED);
231 GST_OBJECT_PARENT (object) = NULL;
233 parent_class->dispose (object);
236 /* finilize is called when the object has to free its resources */
238 gst_object_finalize (GObject *object)
240 GstObject *gstobject;
242 gstobject = GST_OBJECT (object);
244 GST_DEBUG (GST_CAT_REFCOUNTING, "finalize '%s'\n",GST_OBJECT_NAME(object));
246 if (gstobject->name != NULL)
247 g_free (gstobject->name);
249 g_mutex_free (gstobject->lock);
251 parent_class->finalize (object);
255 * gst_object_set_name:
256 * @object: GstObject to set the name of
257 * @name: new name of object
259 * Set the name of the object.
262 gst_object_set_name (GstObject *object, const gchar *name)
264 g_return_if_fail (object != NULL);
265 g_return_if_fail (GST_IS_OBJECT (object));
266 g_return_if_fail (name != NULL);
268 if (object->name != NULL)
269 g_free (object->name);
271 object->name = g_strdup (name);
275 * gst_object_get_name:
276 * @object: GstObject to get the name of
278 * Get the name of the object.
280 * Returns: name of the object
283 gst_object_get_name (GstObject *object)
285 g_return_val_if_fail (object != NULL, NULL);
286 g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
292 * gst_object_set_parent:
293 * @object: GstObject to set parent of
294 * @parent: new parent of object
296 * Set the parent of the object. The object's reference count is
298 * signals the parent-set signal
301 gst_object_set_parent (GstObject *object, GstObject *parent)
303 g_return_if_fail (object != NULL);
304 g_return_if_fail (GST_IS_OBJECT (object));
305 g_return_if_fail (parent != NULL);
306 g_return_if_fail (GST_IS_OBJECT (parent));
307 g_return_if_fail (object != parent);
309 if (object->parent != NULL) {
310 GST_ERROR_OBJECT (object,object->parent, "object's parent is already set, must unparent first");
314 gst_object_ref (object);
315 gst_object_sink (object);
316 object->parent = parent;
318 g_signal_emit (G_OBJECT (object), gst_object_signals[PARENT_SET], 0, parent);
322 * gst_object_get_parent:
323 * @object: GstObject to get parent of
325 * Return the parent of the object.
327 * Returns: parent of the object
330 gst_object_get_parent (GstObject *object)
332 g_return_val_if_fail (object != NULL, NULL);
333 g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
335 return object->parent;
339 * gst_object_unparent:
340 * @object: GstObject to unparent
342 * Clear the parent of the object, removing the associated reference.
345 gst_object_unparent (GstObject *object)
347 g_return_if_fail (object != NULL);
348 g_return_if_fail (GST_IS_OBJECT(object));
349 if (object->parent == NULL)
352 GST_DEBUG (GST_CAT_REFCOUNTING, "unparent '%s'\n",GST_OBJECT_NAME(object));
354 object->parent = NULL;
355 gst_object_unref (object);
360 * @object: GstObject to reference
362 * Increments the refence count on the object.
364 * Returns: Apointer to the Object
366 #ifndef gst_object_ref
368 gst_object_ref (GstObject *object)
370 g_return_if_fail (object != NULL, NULL);
371 g_return_if_fail (GST_IS_OBJECT (object), NULL);
373 //#ifdef HAVE_ATOMIC_H
374 // g_return_if_fail (atomic_read (&(object->refcount)) > 0);
375 // atomic_inc (&(object->refcount))
377 g_return_if_fail (object->refcount > 0);
379 // object->refcount++;
380 g_object_ref((GObject *)object);
386 #endif /* gst_object_ref */
390 * @object: GstObject to unreference
392 * Decrements the refence count on the object. If reference count hits
393 * zero, destroy the object.
395 #ifndef gst_object_unref
397 gst_object_unref (GstObject *object)
401 g_return_if_fail (object != NULL);
402 g_return_if_fail (GST_IS_OBJECT (object));
405 g_return_if_fail (atomic_read (&(object->refcount)) > 0);
406 reftest = atomic_dec_and_test (&(object->refcount))
408 g_return_if_fail (object->refcount > 0);
411 reftest = (object->refcount == 0);
415 /* if we ended up with the refcount at zero */
417 /* get the count to 1 for gtk_object_destroy() */
419 atomic_set (&(object->refcount),1);
421 object->refcount = 1;
424 gtk_object_destroy (G_OBJECT (object));
425 /* drop the refcount back to zero */
427 atomic_set (&(object->refcount),0);
429 object->refcount = 0;
431 /* finalize the object */
432 // FIXME this is an evil hack that should be killed
433 // FIXMEFIXMEFIXMEFIXME
434 // gtk_object_finalize(G_OBJECT(object));
437 #endif /* gst_object_unref */
440 * gst_object_check_uniqueness:
441 * @list: a list of #GstObject to check through
442 * @name: the name to search for
444 * This function checks through the list of objects to see if the name
445 * given appears in the list as the name of an object. It returns TRUE if
446 * the name does not exist in the list.
448 * Returns: TRUE if the name doesn't appear in the list, FALSE if it does.
451 gst_object_check_uniqueness (GList *list, const gchar *name)
453 g_return_val_if_fail (name != NULL, FALSE);
456 GstObject *child = GST_OBJECT (list->data);
458 list = g_list_next(list);
460 if (strcmp(GST_OBJECT_NAME(child), name) == 0)
468 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
470 * gst_object_save_thyself:
471 * @object: GstObject to save
472 * @parent: The parent XML node to save the object into
474 * Saves the given object into the parent XML node.
476 * Returns: the new xmlNodePtr with the saved object
479 gst_object_save_thyself (GstObject *object, xmlNodePtr parent)
481 GstObjectClass *oclass;
483 g_return_val_if_fail (object != NULL, parent);
484 g_return_val_if_fail (GST_IS_OBJECT (object), parent);
485 g_return_val_if_fail (parent != NULL, parent);
487 oclass = (GstObjectClass *)G_OBJECT_GET_CLASS(object);
488 if (oclass->save_thyself)
489 oclass->save_thyself (object, parent);
491 g_signal_emit (G_OBJECT (object), gst_object_signals[OBJECT_SAVED], 0, parent);
497 * gst_object_restore_thyself:
498 * @object: GstObject to load into
499 * @parent: The parent XML node to load the object from
501 * Restores the given object with the data from the parent XML node.
504 gst_object_restore_thyself (GstObject *object, xmlNodePtr parent)
506 GstObjectClass *oclass;
508 g_return_if_fail (object != NULL);
509 g_return_if_fail (GST_IS_OBJECT (object));
510 g_return_if_fail (parent != NULL);
512 oclass = (GstObjectClass *)G_OBJECT_GET_CLASS(object);
513 if (oclass->restore_thyself)
514 oclass->restore_thyself (object, parent);
516 #endif /* GST_DISABLE_LOADSAVE_REGISTRY */
519 gst_object_set_property (GObject* object, guint prop_id,
520 const GValue* value, GParamSpec* pspec)
522 GstObject *gstobject;
524 /* it's not null if we got it, but it might not be ours */
525 g_return_if_fail (GST_IS_OBJECT (object));
527 gstobject = GST_OBJECT (object);
531 gst_object_set_name (gstobject, g_value_get_string (value));
534 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
540 gst_object_get_property (GObject* object, guint prop_id,
541 GValue* value, GParamSpec* pspec)
543 GstObject *gstobject;
545 /* it's not null if we got it, but it might not be ours */
546 g_return_if_fail (GST_IS_OBJECT (object));
548 gstobject = GST_OBJECT (object);
552 g_value_set_string (value, (gchar*)GST_OBJECT_NAME (gstobject));
555 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
560 * gst_object_get_path_string:
561 * @object: GstObject to get the path from
563 * Generates a string describing the path of the object in
564 * the object hierarchy. Usefull for debugging
566 * Returns: a string describing the path of the object
569 gst_object_get_path_string (GstObject *object)
571 GSList *parentage = NULL;
574 gchar *prevpath, *path;
575 const char *component;
576 gchar *separator = "";
577 gboolean free_component;
579 parentage = g_slist_prepend (NULL, object);
581 path = g_strdup ("");
583 // first walk the object hierarchy to build a list of the parents
585 if (GST_IS_OBJECT (object)) {
586 parent = gst_object_get_parent (object);
588 parentage = g_slist_prepend (parentage, NULL);
592 if (parent != NULL) {
593 parentage = g_slist_prepend (parentage, parent);
597 } while (object != NULL);
599 // then walk the parent list and print them out
602 if (GST_IS_OBJECT (parents->data)) {
603 GstObjectClass *oclass = (GstObjectClass *)G_OBJECT_GET_CLASS(parents->data);
605 component = gst_object_get_name (parents->data);
606 separator = oclass->path_string_separator;
607 free_component = FALSE;
609 component = g_strdup_printf("%p",parents->data);
611 free_component = TRUE;
615 path = g_strjoin (separator, prevpath, component, NULL);
618 g_free((gchar *)component);
620 parents = g_slist_next(parents);
623 g_slist_free (parentage);
630 struct _GstSignalObject {
634 struct _GstSignalObjectClass {
635 GObjectClass parent_class;
638 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
639 void (*object_loaded) (GstSignalObject *object, GstObject *new, xmlNodePtr self);
640 #endif /* GST_DISABLE_LOADSAVE_REGISTRY */
644 gst_signal_object_get_type (void)
646 static GType signal_object_type = 0;
648 if (!signal_object_type) {
649 static const GTypeInfo signal_object_info = {
650 sizeof(GstSignalObjectClass),
653 (GClassInitFunc)gst_signal_object_class_init,
656 sizeof(GstSignalObject),
658 (GInstanceInitFunc)gst_signal_object_init,
661 signal_object_type = g_type_register_static(G_TYPE_OBJECT, "GstSignalObject", &signal_object_info, 0);
663 return signal_object_type;
667 gst_signal_object_class_init (GstSignalObjectClass *klass)
669 GObjectClass *gobject_class;
671 gobject_class = (GObjectClass*) klass;
673 parent_class = g_type_class_ref (G_TYPE_OBJECT);
675 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
676 gst_signal_object_signals[SO_OBJECT_LOADED] =
677 g_signal_new("object_loaded", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
678 G_STRUCT_OFFSET (GstObjectClass, parent_set), NULL, NULL,
679 gst_marshal_VOID__OBJECT_POINTER,G_TYPE_NONE,2,
680 G_TYPE_OBJECT,G_TYPE_POINTER);
685 gst_signal_object_init (GstSignalObject *object)
690 * gst_class_signal_connect
691 * @klass: the GstObjectClass to attach the signal to
692 * @name: the name of the signal to attach to
693 * @func: the signal function
694 * @func_data: a pointer to user data
696 * Connect to a class signal.
698 * Returns: the signal id.
701 gst_class_signal_connect (GstObjectClass *klass,
706 return g_signal_connect (klass->signal_object, name, func, func_data);
709 #ifndef GST_DISABLE_LOADSAVE_REGISTRY
711 * gst_class_signal_emit_by_name:
712 * @object: the object that sends the signal
713 * @name: the name of the signal to emit
714 * @self: data for the signal
716 * emits the named class signal.
719 gst_class_signal_emit_by_name (GstObject *object,
723 GstObjectClass *oclass;
725 oclass = (GstObjectClass *)G_OBJECT_GET_CLASS(object);
727 g_signal_emit_by_name (oclass->signal_object, name, object, self);
730 #endif /* GST_DISABLE_LOADSAVE_REGISTRY */