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 */
39 static void gst_object_class_init (GstObjectClass *klass);
40 static void gst_object_init (GstObject *object);
42 static GtkObjectClass *parent_class = NULL;
43 static guint gst_object_signals[LAST_SIGNAL] = { 0 };
46 gst_object_get_type (void)
48 static GtkType object_type = 0;
51 static const GtkTypeInfo object_info = {
54 sizeof(GstObjectClass),
55 (GtkClassInitFunc)gst_object_class_init,
56 (GtkObjectInitFunc)gst_object_init,
59 (GtkClassInitFunc)NULL,
61 object_type = gtk_type_unique(gtk_object_get_type(),&object_info);
67 gst_object_class_init (GstObjectClass *klass)
69 GtkObjectClass *gtkobject_class;
71 gtkobject_class = (GtkObjectClass*) klass;
73 parent_class = gtk_type_class (gtk_object_get_type ());
75 gst_object_signals[PARENT_SET] =
76 gtk_signal_new ("parent_set", GTK_RUN_LAST, gtkobject_class->type,
77 GTK_SIGNAL_OFFSET (GstObjectClass, parent_set),
78 gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1,
80 gtk_object_class_add_signals (gtkobject_class, gst_object_signals, LAST_SIGNAL);
82 klass->path_string_separator = "/";
86 gst_object_init (GstObject *object)
88 object->lock = g_mutex_new();
90 atomic_set(&(object->refcount),1);
94 object->parent = NULL;
100 * Create a new, empty object. Not very useful, should never be used.
102 * Returns: new object
105 gst_object_new (void)
107 return GST_OBJECT (gtk_type_new (gst_object_get_type ()));
111 * gst_object_set_name:
112 * @object: GstObject to set the name of
113 * @name: new name of object
115 * Set the name of the object.
118 gst_object_set_name (GstObject *object, const gchar *name)
120 g_return_if_fail (object != NULL);
121 g_return_if_fail (GST_IS_OBJECT (object));
122 g_return_if_fail (name != NULL);
124 if (object->name != NULL)
125 g_free (object->name);
127 object->name = g_strdup (name);
131 * gst_object_get_name:
132 * @object: GstObject to get the name of
134 * Get the name of the object.
136 * Returns: name of the object
139 gst_object_get_name (GstObject *object)
141 g_return_val_if_fail (object != NULL, NULL);
142 g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
148 * gst_object_set_parent:
149 * @object: GstObject to set parent of
150 * @parent: new parent of object
152 * Set the parent of the object. The object's reference count is
154 * signals the parent-set signal
157 gst_object_set_parent (GstObject *object, GstObject *parent)
159 g_return_if_fail (object != NULL);
160 g_return_if_fail (GST_IS_OBJECT (object));
161 g_return_if_fail (parent != NULL);
162 g_return_if_fail (GST_IS_OBJECT (parent));
163 g_return_if_fail (object != parent);
165 if (object->parent != NULL) {
166 GST_ERROR_OBJECT (object,object->parent, "object's parent is already set, must unparent first");
170 gst_object_ref (object);
171 gst_object_sink (object);
172 object->parent = parent;
174 gtk_signal_emit (GTK_OBJECT (object), gst_object_signals[PARENT_SET], parent);
178 * gst_object_get_parent:
179 * @object: GstObject to get parent of
181 * Return the parent of the object.
183 * Returns: parent of the object
186 gst_object_get_parent (GstObject *object)
188 g_return_val_if_fail (object != NULL, NULL);
189 g_return_val_if_fail (GST_IS_OBJECT (object), NULL);
191 return object->parent;
195 * gst_object_unparent:
196 * @object: GstObject to unparent
198 * Clear the parent of the object, removing the associated reference.
201 gst_object_unparent (GstObject *object)
203 g_return_if_fail (object != NULL);
204 g_return_if_fail (GST_IS_OBJECT(object));
205 if (object->parent == NULL)
208 object->parent = NULL;
209 gst_object_unref (object);
214 * @object: GstObject to reference
216 * Increments the refence count on the object.
218 #ifndef gst_object_ref
220 gst_object_ref (GstObject *object)
222 g_return_if_fail (object != NULL);
223 g_return_if_fail (GST_IS_OBJECT (object));
226 g_return_if_fail (atomic_read (&(object->refcount)) > 0);
227 atomic_inc (&(object->refcount))
229 g_return_if_fail (object->refcount > 0);
235 #endif /* gst_object_ref */
239 * @object: GstObject to unreference
241 * Decrements the refence count on the object. If reference count hits
242 * zero, destroy the object.
244 #ifndef gst_object_unref
246 gst_object_unref (GstObject *object)
250 g_return_if_fail (object != NULL);
251 g_return_if_fail (GST_IS_OBJECT (object));
254 g_return_if_fail (atomic_read (&(object->refcount)) > 0);
255 reftest = atomic_dec_and_test (&(object->refcount))
257 g_return_if_fail (object->refcount > 0);
260 reftest = (object->refcount == 0);
264 /* if we ended up with the refcount at zero */
266 /* get the count to 1 for gtk_object_destroy() */
268 atomic_set (&(object->refcount),1);
270 object->refcount = 1;
273 gtk_object_destroy (GTK_OBJECT (object));
274 /* drop the refcount back to zero */
276 atomic_set (&(object->refcount),0);
278 object->refcount = 0;
280 /* finalize the object */
281 // FIXME this is an evil hack that should be killed
282 // FIXMEFIXMEFIXMEFIXME
283 // gtk_object_finalize(GTK_OBJECT(object));
286 #endif /* gst_object_unref */
290 * @object: GstObject to sink
292 * Removes floating reference on an object. Any newly created object has
293 * a refcount of 1 and is FLOATING. This function should be used when
294 * creating a new object to symbolically 'take ownership of' the object.
296 #ifndef gst_object_sink
298 gst_object_sink (GstObject *object)
300 g_return_if_fail (object != NULL);
301 g_return_if_fail (GST_IS_OBJECT (object));
303 if (GTK_OBJECT_FLOATING (object)) {
304 GTK_OBJECT_UNSET_FLAGS (object, GTK_FLOATING);
305 gst_object_unref (object);
308 #endif /* gst_object_sink */
311 gst_object_save_thyself (GstObject *object, xmlNodePtr parent)
313 GstObjectClass *oclass;
315 g_return_val_if_fail (object != NULL, parent);
316 g_return_val_if_fail (GST_IS_OBJECT (object), parent);
317 g_return_val_if_fail (parent != NULL, parent);
319 oclass = GST_OBJECT_CLASS (GTK_OBJECT (object)->klass);
321 if (oclass->save_thyself)
322 oclass->save_thyself (object, parent);
328 gst_object_load_thyself (xmlNodePtr self, GstObject *parent)
330 g_print ("gstobject: load thyself\n");
334 * gst_object_get_path_string:
335 * @object: GstObject to get the path from
337 * Generates a string describing the path of the object in
338 * the object hierarchy. Usefull for debugging
340 * Returns: a string describing the path of the object
343 gst_object_get_path_string (GstObject *object)
345 GSList *parentage = NULL;
348 gchar *prevpath, *path = "";
349 const char *component;
350 gchar *separator = "";
351 gboolean free_component;
353 parentage = g_slist_prepend (NULL, object);
355 // first walk the object hierarchy to build a list of the parents
357 if (GST_IS_OBJECT (object)) {
358 parent = gst_object_get_parent (object);
360 parentage = g_slist_prepend (parentage, NULL);
364 if (parent != NULL) {
365 parentage = g_slist_prepend (parentage, parent);
369 } while (object != NULL);
371 // then walk the parent list and print them out
374 if (GST_IS_OBJECT (parents->data)) {
375 GstObjectClass *oclass = GST_OBJECT_CLASS (GTK_OBJECT (parents->data));
377 component = GST_OBJECT_NAME (parents->data);
378 separator = oclass->path_string_separator;
379 free_component = FALSE;
381 component = g_strdup_printf("%p",parents->data);
383 free_component = TRUE;
387 path = g_strjoin (separator, prevpath, component, NULL);
390 g_free((gchar *)component);
392 parents = g_slist_next(parents);
395 g_slist_free (parentage);