Docs updates: remove sink, src, filter, connection added gstinfo to docs.
[platform/upstream/gstreamer.git] / gst / gstobject.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *
5  * gstobject.c: Fundamental class used for all of GStreamer
6  *
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.
11  *
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.
16  *
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.
21  */
22
23 #include "gst_private.h"
24
25 #include "gstobject.h"
26 #include "gstpad.h"
27 #include "gstelement.h"
28
29 /* Object signals and args */
30 enum {
31   PARENT_SET,
32   LAST_SIGNAL
33 };
34
35 enum {
36   ARG_0,
37   /* FILL ME */
38 };
39
40
41 static void gst_object_class_init(GstObjectClass *klass);
42 static void gst_object_init(GstObject *object);
43
44
45 static GtkObjectClass *parent_class = NULL;
46 static guint gst_object_signals[LAST_SIGNAL] = { 0 };
47
48 GtkType gst_object_get_type(void) {
49   static GtkType object_type = 0;
50
51   if (!object_type) {
52     static const GtkTypeInfo object_info = {
53       "GstObject",
54       sizeof(GstObject),
55       sizeof(GstObjectClass),
56       (GtkClassInitFunc)gst_object_class_init,
57       (GtkObjectInitFunc)gst_object_init,
58       (GtkArgSetFunc)NULL,
59       (GtkArgGetFunc)NULL,
60       (GtkClassInitFunc)NULL,
61     };
62     object_type = gtk_type_unique(gtk_object_get_type(),&object_info);
63   }
64   return object_type;
65 }
66
67 static void gst_object_class_init(GstObjectClass *klass) {
68   GtkObjectClass *gtkobject_class;
69
70   gtkobject_class = (GtkObjectClass*)klass;
71
72   parent_class = gtk_type_class(gtk_object_get_type());
73
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,
78                    GST_TYPE_OBJECT);
79   gtk_object_class_add_signals(gtkobject_class,gst_object_signals,LAST_SIGNAL);
80 }
81
82 static void gst_object_init(GstObject *object) {
83   object->lock = g_mutex_new();
84 #ifdef HAVE_ATOMIC_H
85   atomic_set(&(object->refcount),1);
86 #else
87   object->refcount++;
88 #endif
89   object->parent = NULL;
90 }
91
92 /**
93  * gst_object_new:
94  *
95  * Create a new, empty object.  Not very useful, should never be used.
96  *
97  * Returns: new object
98  */
99 GstObject *gst_object_new() {
100   return GST_OBJECT(gtk_type_new(gst_object_get_type()));
101 }
102
103 /**
104  * gst_object_set_parent:
105  * @object: GstObject to set parent of
106  * @parent: new parent of object
107  *
108  * Set the parent of the object.  The object's reference count is
109  * incremented.
110  * signals the parent-set signal
111  */
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);
118
119   if (object->parent != NULL) {
120     ERROR_OBJECT(object,object->parent,"object's parent is already set, must unparent first");
121     return;
122   }
123
124   gst_object_ref(object);
125   gst_object_sink(object);
126   object->parent = parent;
127
128   gtk_signal_emit(GTK_OBJECT(object),gst_object_signals[PARENT_SET],parent);
129 }
130
131 /**
132  * gst_object_get_parent:
133  * @object: GstObject to get parent of
134  *
135  * Return the parent of the object.
136  *
137  * Returns: parent of the object
138  */
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);
142
143   return object->parent;
144 }
145
146 /**
147  * gst_object_unparent:
148  * @object: GstObject to unparent
149  *
150  * Clear the parent of the object, removing the associated reference.
151  */
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)
156     return;
157
158   object->parent = NULL;
159   gst_object_unref(object);
160 }
161
162 /**
163  * gst_object_ref:
164  * @object: GstObject to reference
165  *
166  * Increments the refence count on the object.
167  */
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));
172
173 #ifdef HAVE_ATOMIC_H
174   g_return_if_fail(atomic_read(&(object->refcount)) > 0);
175   atomic_inc(&(object->refcount))
176 #else
177   g_return_if_fail(object->refcount > 0);
178   GST_LOCK(object);
179   object->refcount++;
180   GST_UNLOCK(object);
181 #endif
182 }
183 #endif /* gst_object_ref */
184
185 /**
186  * gst_object_unref:
187  * @object: GstObject to unreference
188  *
189  * Decrements the refence count on the object.  If reference count hits
190  * zero, destroy the object.
191  */
192 #ifndef gst_object_unref
193 void gst_object_unref (GstObject *object) {
194   int reftest;
195
196   g_return_if_fail(object != NULL);
197   g_return_if_fail(GST_IS_OBJECT(object));
198
199 #ifdef HAVE_ATOMIC_H
200   g_return_if_fail(atomic_read(&(object->refcount)) > 0);
201   reftest = atomic_dec_and_test(&(object->refcount))
202 #else
203   g_return_if_fail(object->refcount > 0);
204   GST_LOCK(object);
205   object->refcount--;
206   reftest = (object->refcount == 0);
207   GST_UNLOCK(object);
208 #endif
209
210   /* if we ended up with the refcount at zero */
211   if (reftest) {
212     /* get the count to 1 for gtk_object_destroy() */
213 #ifdef HAVE_ATOMIC_H
214     atomic_set(&(object->refcount),1);
215 #else
216     object->refcount = 1;
217 #endif
218     /* destroy it */
219     gtk_object_destroy(GTK_OBJECT(object));
220     /* drop the refcount back to zero */
221 #ifdef HAVE_ATOMIC_H
222     atomic_set(&(object->refcount),0);
223 #else
224     object->refcount = 0;
225 #endif
226     /* finalize the object */
227     // FIXME this is an evil hack that should be killed
228 // FIXMEFIXMEFIXMEFIXME
229 //    gtk_object_finalize(GTK_OBJECT(object));
230   }
231 }
232 #endif /* gst_object_unref */
233
234 /**
235  * gst_object_sink:
236  * @object: GstObject to sink
237  *
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.
241  */
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));
246
247   if (GTK_OBJECT_FLOATING(object)) {
248     GTK_OBJECT_UNSET_FLAGS(object, GTK_FLOATING);
249     gst_object_unref(object);
250   }
251 }
252 #endif /* gst_object_sink */
253
254
255 /**
256  * gst_object_get_path_string:
257  * @object: GstObject to get the path from
258  *
259  * Generates a string describing the path of the object in
260  * the object hierarchy. Usefull for debugging
261  * 
262  * Returns: a string describing the path of the object
263  */
264 gchar*
265 gst_object_get_path_string(GstObject *object) 
266 {
267   GSList *parentage = NULL;
268   GSList *parents;
269   void *parent;
270   gchar *prevpath, *path = ""; 
271   const char *component;
272   gchar *separator = "";
273   gboolean free_component;
274
275   parentage = g_slist_prepend (NULL, object);
276        
277   // first walk the object hierarchy to build a list of the parents
278   do {
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));
284       } else {
285         parent = gst_object_get_parent (object);
286       }
287     } else {
288       parentage = g_slist_prepend (parentage, NULL);
289       parent = NULL;
290     }
291
292     if (parent != NULL) { 
293       parentage = g_slist_prepend (parentage, parent);
294     }
295  
296     object = parent;
297   } while (object != NULL);
298
299   // then walk the parent list and print them out
300   parents = parentage;
301   while (parents) {
302     if (GST_IS_OBJECT(parents->data)) {
303       if (GST_IS_PAD(parents->data)) {
304         component = gst_pad_get_name(GST_PAD(parents->data));
305         separator = ".";
306         free_component = FALSE;
307       } else if (GST_IS_ELEMENT(parents->data)) {
308         component = gst_element_get_name(GST_ELEMENT(parents->data));
309         separator = "/";
310         free_component = FALSE;
311       } else {
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);
314         separator = "/";
315         free_component = TRUE;
316       }
317     } else {
318       component = g_strdup_printf("%p",parents->data);  
319       separator = "/";
320       free_component = TRUE;
321     }
322       
323     prevpath = path;
324     path = g_strjoin(separator,prevpath,component,NULL);
325     g_free(prevpath);
326     if (free_component)
327       g_free((gchar *)component);
328
329     parents = g_slist_next(parents);
330   }
331     
332   g_slist_free(parentage);
333               
334   return path;
335 }
336