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 #include "gstelement.h"
29 /* Object signals and args */
41 static void gst_object_class_init(GstObjectClass *klass);
42 static void gst_object_init(GstObject *object);
45 static GtkObjectClass *parent_class = NULL;
46 static guint gst_object_signals[LAST_SIGNAL] = { 0 };
48 GtkType gst_object_get_type(void) {
49 static GtkType object_type = 0;
52 static const GtkTypeInfo object_info = {
55 sizeof(GstObjectClass),
56 (GtkClassInitFunc)gst_object_class_init,
57 (GtkObjectInitFunc)gst_object_init,
60 (GtkClassInitFunc)NULL,
62 object_type = gtk_type_unique(gtk_object_get_type(),&object_info);
67 static void gst_object_class_init(GstObjectClass *klass) {
68 GtkObjectClass *gtkobject_class;
70 gtkobject_class = (GtkObjectClass*)klass;
72 parent_class = gtk_type_class(gtk_object_get_type());
74 gst_object_signals[PARENT_SET] =
75 gtk_signal_new("parent_set",GTK_RUN_LAST,gtkobject_class->type,
76 GTK_SIGNAL_OFFSET(GstObjectClass,parent_set),
77 gtk_marshal_NONE__POINTER,GTK_TYPE_NONE,1,
79 gtk_object_class_add_signals(gtkobject_class,gst_object_signals,LAST_SIGNAL);
82 static void gst_object_init(GstObject *object) {
83 object->lock = g_mutex_new();
85 atomic_set(&(object->refcount),1);
89 object->parent = NULL;
95 * Create a new, empty object. Not very useful, should never be used.
99 GstObject *gst_object_new() {
100 return GST_OBJECT(gtk_type_new(gst_object_get_type()));
104 * gst_object_set_parent:
105 * @object: GstObject to set parent of
106 * @parent: new parent of object
108 * Set the parent of the object. The object's reference count is
110 * signals the parent-set signal
112 void gst_object_set_parent(GstObject *object,GstObject *parent) {
113 g_return_if_fail(object != NULL);
114 g_return_if_fail(GST_IS_OBJECT(object));
115 g_return_if_fail(parent != NULL);
116 g_return_if_fail(GST_IS_OBJECT(parent));
117 g_return_if_fail(object != parent);
119 if (object->parent != NULL) {
120 ERROR_OBJECT(object,object->parent,"object's parent is already set, must unparent first");
124 gst_object_ref(object);
125 gst_object_sink(object);
126 object->parent = parent;
128 gtk_signal_emit(GTK_OBJECT(object),gst_object_signals[PARENT_SET],parent);
132 * gst_object_get_parent:
133 * @object: GstObject to get parent of
135 * Return the parent of the object.
137 * Returns: parent of the object
139 GstObject *gst_object_get_parent(GstObject *object) {
140 g_return_val_if_fail(object != NULL, NULL);
141 g_return_val_if_fail(GST_IS_OBJECT(object), NULL);
143 return object->parent;
147 * gst_object_unparent:
148 * @object: GstObject to unparent
150 * Clear the parent of the object, removing the associated reference.
152 void gst_object_unparent(GstObject *object) {
153 g_return_if_fail(object != NULL);
154 g_return_if_fail(GST_IS_OBJECT(object));
155 if (object->parent == NULL)
158 object->parent = NULL;
159 gst_object_unref(object);
164 * @object: GstObject to reference
166 * Increments the refence count on the object.
168 #ifndef gst_object_ref
169 void gst_object_ref (GstObject *object) {
170 g_return_if_fail(object != NULL);
171 g_return_if_fail(GST_IS_OBJECT(object));
174 g_return_if_fail(atomic_read(&(object->refcount)) > 0);
175 atomic_inc(&(object->refcount))
177 g_return_if_fail(object->refcount > 0);
183 #endif /* gst_object_ref */
187 * @object: GstObject to unreference
189 * Decrements the refence count on the object. If reference count hits
190 * zero, destroy the object.
192 #ifndef gst_object_unref
193 void gst_object_unref (GstObject *object) {
196 g_return_if_fail(object != NULL);
197 g_return_if_fail(GST_IS_OBJECT(object));
200 g_return_if_fail(atomic_read(&(object->refcount)) > 0);
201 reftest = atomic_dec_and_test(&(object->refcount))
203 g_return_if_fail(object->refcount > 0);
206 reftest = (object->refcount == 0);
210 /* if we ended up with the refcount at zero */
212 /* get the count to 1 for gtk_object_destroy() */
214 atomic_set(&(object->refcount),1);
216 object->refcount = 1;
219 gtk_object_destroy(GTK_OBJECT(object));
220 /* drop the refcount back to zero */
222 atomic_set(&(object->refcount),0);
224 object->refcount = 0;
226 /* finalize the object */
227 // FIXME this is an evil hack that should be killed
228 // FIXMEFIXMEFIXMEFIXME
229 // gtk_object_finalize(GTK_OBJECT(object));
232 #endif /* gst_object_unref */
236 * @object: GstObject to sink
238 * Removes floating reference on an object. Any newly created object has
239 * a refcount of 1 and is FLOATING. This function should be used when
240 * creating a new object to symbolically 'take ownership of' the object.
242 #ifndef gst_object_sink
243 void gst_object_sink(GstObject *object) {
244 g_return_if_fail(object != NULL);
245 g_return_if_fail(GST_IS_OBJECT(object));
247 if (GTK_OBJECT_FLOATING(object)) {
248 GTK_OBJECT_UNSET_FLAGS(object, GTK_FLOATING);
249 gst_object_unref(object);
252 #endif /* gst_object_sink */
256 * gst_object_get_path_string:
257 * @object: GstObject to get the path from
259 * Generates a string describing the path of the object in
260 * the object hierarchy. Usefull for debugging
262 * Returns: a string describing the path of the object
265 gst_object_get_path_string(GstObject *object)
267 GSList *parentage = NULL;
270 gchar *prevpath, *path = "";
271 const char *component;
272 gchar *separator = "";
273 gboolean free_component;
275 parentage = g_slist_prepend (NULL, object);
277 // first walk the object hierarchy to build a list of the parents
279 if (GST_IS_OBJECT(object)) {
280 if (GST_IS_PAD(object)) {
281 parent = GST_PAD(object)->parent;
282 // } else if (GST_IS_ELEMENT(object)) {
283 // parent = gst_element_get_parent(GST_ELEMENT(object));
285 parent = gst_object_get_parent (object);
288 parentage = g_slist_prepend (parentage, NULL);
292 if (parent != NULL) {
293 parentage = g_slist_prepend (parentage, parent);
297 } while (object != NULL);
299 // then walk the parent list and print them out
302 if (GST_IS_OBJECT(parents->data)) {
303 if (GST_IS_PAD(parents->data)) {
304 component = gst_pad_get_name(GST_PAD(parents->data));
306 free_component = FALSE;
307 } else if (GST_IS_ELEMENT(parents->data)) {
308 component = gst_element_get_name(GST_ELEMENT(parents->data));
310 free_component = FALSE;
312 // component = g_strdup_printf("a %s",gtk_type_name(gtk_identifier_get_type(parents->data)));
313 component = g_strdup_printf("unknown%p",parents->data);
315 free_component = TRUE;
318 component = g_strdup_printf("%p",parents->data);
320 free_component = TRUE;
324 path = g_strjoin(separator,prevpath,component,NULL);
327 g_free((gchar *)component);
329 parents = g_slist_next(parents);
332 g_slist_free(parentage);