99 #ifndef GST_DISABLE_TRACE |
98 #ifndef GST_DISABLE_TRACE |
100 #include "gsttrace.h" |
99 #include "gsttrace.h" |
101 static GstAllocTrace *_gst_object_trace; |
100 static GstAllocTrace *_gst_object_trace; |
102 #endif |
101 #endif |
103 |
102 |
104 |
|
105 #define DEBUG_REFCOUNT |
103 #define DEBUG_REFCOUNT |
106 |
104 |
107 /* Object signals and args */ |
105 /* Object signals and args */ |
|
106 /* FIXME-0.11: have a read-only parent property instead of the two signals |
|
107 * then we get notify::parent for free */ |
108 enum |
108 enum |
109 { |
109 { |
110 PARENT_SET, |
110 PARENT_SET, |
111 PARENT_UNSET, |
111 PARENT_UNSET, |
112 #ifndef GST_DISABLE_LOADSAVE |
112 #ifndef GST_DISABLE_LOADSAVE |
142 static void gst_signal_object_init (GstSignalObject * object); |
142 static void gst_signal_object_init (GstSignalObject * object); |
143 |
143 |
144 #ifndef GST_DISABLE_LOADSAVE |
144 #ifndef GST_DISABLE_LOADSAVE |
145 static guint gst_signal_object_signals[SO_LAST_SIGNAL] = { 0 }; |
145 static guint gst_signal_object_signals[SO_LAST_SIGNAL] = { 0 }; |
146 #endif |
146 #endif |
147 |
|
148 static void gst_object_class_init (GstObjectClass * klass); |
|
149 static void gst_object_init (GTypeInstance * instance, gpointer g_class); |
|
150 |
147 |
151 static void gst_object_set_property (GObject * object, guint prop_id, |
148 static void gst_object_set_property (GObject * object, guint prop_id, |
152 const GValue * value, GParamSpec * pspec); |
149 const GValue * value, GParamSpec * pspec); |
153 static void gst_object_get_property (GObject * object, guint prop_id, |
150 static void gst_object_get_property (GObject * object, guint prop_id, |
154 GValue * value, GParamSpec * pspec); |
151 GValue * value, GParamSpec * pspec); |
165 xmlNodePtr self); |
162 xmlNodePtr self); |
166 #endif |
163 #endif |
167 |
164 |
168 static GObjectClass *parent_class = NULL; |
165 static GObjectClass *parent_class = NULL; |
169 static guint gst_object_signals[LAST_SIGNAL] = { 0 }; |
166 static guint gst_object_signals[LAST_SIGNAL] = { 0 }; |
170 #ifdef __SYMBIAN32__ |
167 |
171 EXPORT_C |
168 G_DEFINE_ABSTRACT_TYPE (GstObject, gst_object, G_TYPE_OBJECT); |
172 #endif |
|
173 |
|
174 |
|
175 GType |
|
176 gst_object_get_type (void) |
|
177 { |
|
178 static GType gst_object_type = 0; |
|
179 |
|
180 if (G_UNLIKELY (gst_object_type == 0)) { |
|
181 static const GTypeInfo object_info = { |
|
182 sizeof (GstObjectClass), |
|
183 NULL, |
|
184 NULL, |
|
185 (GClassInitFunc) gst_object_class_init, |
|
186 NULL, |
|
187 NULL, |
|
188 sizeof (GstObject), |
|
189 0, |
|
190 gst_object_init, |
|
191 NULL |
|
192 }; |
|
193 |
|
194 gst_object_type = |
|
195 g_type_register_static (G_TYPE_OBJECT, "GstObject", &object_info, |
|
196 G_TYPE_FLAG_ABSTRACT); |
|
197 } |
|
198 return gst_object_type; |
|
199 } |
|
200 |
169 |
201 static void |
170 static void |
202 gst_object_class_init (GstObjectClass * klass) |
171 gst_object_class_init (GstObjectClass * klass) |
203 { |
172 { |
204 GObjectClass *gobject_class; |
173 GObjectClass *gobject_class = G_OBJECT_CLASS (klass); |
205 |
|
206 gobject_class = G_OBJECT_CLASS (klass); |
|
207 |
174 |
208 parent_class = g_type_class_peek_parent (klass); |
175 parent_class = g_type_class_peek_parent (klass); |
209 |
176 |
210 #ifndef GST_DISABLE_TRACE |
177 #ifndef GST_DISABLE_TRACE |
211 _gst_object_trace = gst_alloc_trace_register (g_type_name (GST_TYPE_OBJECT)); |
178 _gst_object_trace = gst_alloc_trace_register (g_type_name (GST_TYPE_OBJECT)); |
214 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_object_set_property); |
181 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_object_set_property); |
215 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_object_get_property); |
182 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_object_get_property); |
216 |
183 |
217 g_object_class_install_property (gobject_class, ARG_NAME, |
184 g_object_class_install_property (gobject_class, ARG_NAME, |
218 g_param_spec_string ("name", "Name", "The name of the object", |
185 g_param_spec_string ("name", "Name", "The name of the object", |
219 NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); |
186 NULL, |
|
187 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); |
220 |
188 |
221 /** |
189 /** |
222 * GstObject::parent-set: |
190 * GstObject::parent-set: |
223 * @gstobject: a #GstObject |
191 * @gstobject: a #GstObject |
224 * @parent: the new parent |
192 * @parent: the new parent |
292 gobject_class->dispose = gst_object_dispose; |
260 gobject_class->dispose = gst_object_dispose; |
293 gobject_class->finalize = gst_object_finalize; |
261 gobject_class->finalize = gst_object_finalize; |
294 } |
262 } |
295 |
263 |
296 static void |
264 static void |
297 gst_object_init (GTypeInstance * instance, gpointer g_class) |
265 gst_object_init (GstObject * object) |
298 { |
266 { |
299 GstObject *object = GST_OBJECT (instance); |
|
300 |
|
301 object->lock = g_mutex_new (); |
267 object->lock = g_mutex_new (); |
302 object->parent = NULL; |
268 object->parent = NULL; |
303 object->name = NULL; |
269 object->name = NULL; |
304 GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "%p new", object); |
270 GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "%p new", object); |
305 |
271 |
368 GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "%p unref %d->%d", |
335 GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "%p unref %d->%d", |
369 object, |
336 object, |
370 ((GObject *) object)->ref_count, ((GObject *) object)->ref_count - 1); |
337 ((GObject *) object)->ref_count, ((GObject *) object)->ref_count - 1); |
371 #endif |
338 #endif |
372 g_object_unref (object); |
339 g_object_unref (object); |
|
340 } |
|
341 |
|
342 /** |
|
343 * gst_object_ref_sink: |
|
344 * @object: a #GstObject to sink |
|
345 * |
|
346 * Increase the reference count of @object, and possibly remove the floating |
|
347 * reference, if @object has a floating reference. |
|
348 * |
|
349 * In other words, if the object is floating, then this call "assumes ownership" |
|
350 * of the floating reference, converting it to a normal reference by clearing |
|
351 * the floating flag while leaving the reference count unchanged. If the object |
|
352 * is not floating, then this call adds a new normal reference increasing the |
|
353 * reference count by one. |
|
354 * |
|
355 * MT safe. This function grabs and releases @object lock. |
|
356 * |
|
357 * Since: 0.10.24 |
|
358 */ |
|
359 #ifdef __SYMBIAN32__ |
|
360 EXPORT_C |
|
361 #endif |
|
362 |
|
363 void |
|
364 gst_object_ref_sink (gpointer object) |
|
365 { |
|
366 g_return_if_fail (GST_IS_OBJECT (object)); |
|
367 |
|
368 GST_OBJECT_LOCK (object); |
|
369 if (G_LIKELY (GST_OBJECT_IS_FLOATING (object))) { |
|
370 GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "unsetting floating flag"); |
|
371 GST_OBJECT_FLAG_UNSET (object, GST_OBJECT_FLOATING); |
|
372 GST_OBJECT_UNLOCK (object); |
|
373 } else { |
|
374 GST_OBJECT_UNLOCK (object); |
|
375 gst_object_ref (object); |
|
376 } |
373 } |
377 } |
374 |
378 |
375 /** |
379 /** |
376 * gst_object_sink: |
380 * gst_object_sink: |
377 * @object: a #GstObject to sink |
381 * @object: a #GstObject to sink |
435 g_return_if_fail (oldobj != NULL); |
439 g_return_if_fail (oldobj != NULL); |
436 g_return_if_fail (*oldobj == NULL || GST_IS_OBJECT (*oldobj)); |
440 g_return_if_fail (*oldobj == NULL || GST_IS_OBJECT (*oldobj)); |
437 g_return_if_fail (newobj == NULL || GST_IS_OBJECT (newobj)); |
441 g_return_if_fail (newobj == NULL || GST_IS_OBJECT (newobj)); |
438 |
442 |
439 #ifdef DEBUG_REFCOUNT |
443 #ifdef DEBUG_REFCOUNT |
440 GST_CAT_LOG (GST_CAT_REFCOUNTING, "replace %s (%d) with %s (%d)", |
444 GST_CAT_LOG (GST_CAT_REFCOUNTING, "replace %p %s (%d) with %p %s (%d)", |
441 *oldobj ? GST_STR_NULL (GST_OBJECT_NAME (*oldobj)) : "(NONE)", |
445 *oldobj, *oldobj ? GST_STR_NULL (GST_OBJECT_NAME (*oldobj)) : "(NONE)", |
442 *oldobj ? G_OBJECT (*oldobj)->ref_count : 0, |
446 *oldobj ? G_OBJECT (*oldobj)->ref_count : 0, |
443 newobj ? GST_STR_NULL (GST_OBJECT_NAME (newobj)) : "(NONE)", |
447 newobj, newobj ? GST_STR_NULL (GST_OBJECT_NAME (newobj)) : "(NONE)", |
444 newobj ? G_OBJECT (newobj)->ref_count : 0); |
448 newobj ? G_OBJECT (newobj)->ref_count : 0); |
445 #endif |
449 #endif |
446 |
450 |
447 if (G_LIKELY (*oldobj != newobj)) { |
451 if (G_LIKELY (*oldobj != newobj)) { |
448 if (newobj) |
452 if (newobj) |
523 guint n_pspecs, GParamSpec ** pspecs) |
527 guint n_pspecs, GParamSpec ** pspecs) |
524 { |
528 { |
525 GstObject *gst_object, *parent, *old_parent; |
529 GstObject *gst_object, *parent, *old_parent; |
526 guint i; |
530 guint i; |
527 gchar *name, *debug_name; |
531 gchar *name, *debug_name; |
528 GstObjectClass *klass; |
|
529 |
|
530 /* we fail when this is not a GstObject */ |
|
531 g_return_if_fail (GST_IS_OBJECT (object)); |
|
532 |
|
533 klass = GST_OBJECT_GET_CLASS (object); |
|
534 |
532 |
535 /* do the standard dispatching */ |
533 /* do the standard dispatching */ |
536 G_OBJECT_CLASS (parent_class)->dispatch_properties_changed (object, n_pspecs, |
534 parent_class->dispatch_properties_changed (object, n_pspecs, pspecs); |
537 pspecs); |
|
538 |
535 |
539 gst_object = GST_OBJECT_CAST (object); |
536 gst_object = GST_OBJECT_CAST (object); |
540 name = gst_object_get_name (gst_object); |
537 name = gst_object_get_name (gst_object); |
541 debug_name = GST_STR_NULL (name); |
538 debug_name = GST_STR_NULL (name); |
542 |
539 |
543 /* now let the parent dispatch those, too */ |
540 /* now let the parent dispatch those, too */ |
544 parent = gst_object_get_parent (gst_object); |
541 parent = gst_object_get_parent (gst_object); |
545 while (parent) { |
542 while (parent) { |
546 for (i = 0; i < n_pspecs; i++) { |
543 for (i = 0; i < n_pspecs; i++) { |
547 GST_LOG_OBJECT (parent, "deep notification from %s (%s)", |
544 GST_CAT_LOG_OBJECT (GST_CAT_PROPERTIES, parent, |
548 debug_name, pspecs[i]->name); |
545 "deep notification from %s (%s)", debug_name, pspecs[i]->name); |
549 |
546 |
550 g_signal_emit (parent, gst_object_signals[DEEP_NOTIFY], |
547 g_signal_emit (parent, gst_object_signals[DEEP_NOTIFY], |
551 g_quark_from_string (pspecs[i]->name), GST_OBJECT_CAST (object), |
548 g_quark_from_string (pspecs[i]->name), gst_object, pspecs[i]); |
552 pspecs[i]); |
|
553 } |
549 } |
554 |
550 |
555 old_parent = parent; |
551 old_parent = parent; |
556 parent = gst_object_get_parent (old_parent); |
552 parent = gst_object_get_parent (old_parent); |
557 gst_object_unref (old_parent); |
553 gst_object_unref (old_parent); |
595 excluded_props++; |
591 excluded_props++; |
596 } |
592 } |
597 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec)); |
593 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec)); |
598 g_object_get_property (G_OBJECT (orig), pspec->name, &value); |
594 g_object_get_property (G_OBJECT (orig), pspec->name, &value); |
599 |
595 |
|
596 /* FIXME: handle flags */ |
600 if (G_IS_PARAM_SPEC_ENUM (pspec)) { |
597 if (G_IS_PARAM_SPEC_ENUM (pspec)) { |
601 GEnumValue *enum_value; |
598 GEnumValue *enum_value; |
602 |
599 GEnumClass *klass = G_ENUM_CLASS (g_type_class_ref (pspec->value_type)); |
603 enum_value = |
600 |
604 g_enum_get_value (G_ENUM_CLASS (g_type_class_ref (pspec->value_type)), |
601 enum_value = g_enum_get_value (klass, g_value_get_enum (&value)); |
605 g_value_get_enum (&value)); |
|
606 |
602 |
607 str = g_strdup_printf ("%s (%d)", enum_value->value_nick, |
603 str = g_strdup_printf ("%s (%d)", enum_value->value_nick, |
608 enum_value->value); |
604 enum_value->value); |
|
605 g_type_class_unref (klass); |
609 } else { |
606 } else { |
610 str = g_strdup_value_contents (&value); |
607 str = g_strdup_value_contents (&value); |
611 } |
608 } |
612 name = gst_object_get_path_string (orig); |
609 name = gst_object_get_path_string (orig); |
613 g_print ("%s: %s = %s\n", name, pspec->name, str); |
610 g_print ("%s: %s = %s\n", name, pspec->name, str); |
647 /* GstFooSink -> foosinkN */ |
644 /* GstFooSink -> foosinkN */ |
648 type_name = g_quark_to_string (q); |
645 type_name = g_quark_to_string (q); |
649 if (strncmp (type_name, "Gst", 3) == 0) |
646 if (strncmp (type_name, "Gst", 3) == 0) |
650 type_name += 3; |
647 type_name += 3; |
651 tmp = g_strdup_printf ("%s%d", type_name, count); |
648 tmp = g_strdup_printf ("%s%d", type_name, count); |
652 name = g_ascii_strdown (tmp, strlen (tmp)); |
649 name = g_ascii_strdown (tmp, -1); |
653 g_free (tmp); |
650 g_free (tmp); |
654 |
651 |
655 result = gst_object_set_name (object, name); |
652 result = gst_object_set_name (object, name); |
656 g_free (name); |
653 g_free (name); |
657 |
654 |
812 * Returns: TRUE if @parent could be set or FALSE when @object |
810 * Returns: TRUE if @parent could be set or FALSE when @object |
813 * already had a parent or @object and @parent are the same. |
811 * already had a parent or @object and @parent are the same. |
814 * |
812 * |
815 * MT safe. Grabs and releases @object's LOCK. |
813 * MT safe. Grabs and releases @object's LOCK. |
816 */ |
814 */ |
817 #ifdef __SYMBIAN32__ |
815 |
818 EXPORT_C |
816 #ifdef __SYMBIAN32__ |
819 #endif |
817 EXPORT_C |
|
818 #endif |
|
819 |
820 gboolean |
820 gboolean |
821 gst_object_set_parent (GstObject * object, GstObject * parent) |
821 gst_object_set_parent (GstObject * object, GstObject * parent) |
822 { |
822 { |
823 g_return_val_if_fail (GST_IS_OBJECT (object), FALSE); |
823 g_return_val_if_fail (GST_IS_OBJECT (object), FALSE); |
824 g_return_val_if_fail (GST_IS_OBJECT (parent), FALSE); |
824 g_return_val_if_fail (GST_IS_OBJECT (parent), FALSE); |
915 if (G_LIKELY (parent != NULL)) { |
917 if (G_LIKELY (parent != NULL)) { |
916 GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "unparent"); |
918 GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "unparent"); |
917 object->parent = NULL; |
919 object->parent = NULL; |
918 GST_OBJECT_UNLOCK (object); |
920 GST_OBJECT_UNLOCK (object); |
919 |
921 |
920 g_signal_emit (G_OBJECT (object), gst_object_signals[PARENT_UNSET], 0, |
922 g_signal_emit (object, gst_object_signals[PARENT_UNSET], 0, parent); |
921 parent); |
|
922 |
923 |
923 gst_object_unref (object); |
924 gst_object_unref (object); |
924 } else { |
925 } else { |
925 GST_OBJECT_UNLOCK (object); |
926 GST_OBJECT_UNLOCK (object); |
926 } |
927 } |
1029 oclass = GST_OBJECT_GET_CLASS (object); |
1030 oclass = GST_OBJECT_GET_CLASS (object); |
1030 |
1031 |
1031 if (oclass->save_thyself) |
1032 if (oclass->save_thyself) |
1032 oclass->save_thyself (object, parent); |
1033 oclass->save_thyself (object, parent); |
1033 |
1034 |
1034 g_signal_emit (G_OBJECT (object), gst_object_signals[OBJECT_SAVED], 0, |
1035 g_signal_emit (object, gst_object_signals[OBJECT_SAVED], 0, parent); |
1035 parent); |
|
1036 |
1036 |
1037 return parent; |
1037 return parent; |
1038 } |
1038 } |
1039 |
1039 |
1040 /** |
1040 /** |
1154 |
1155 |
1155 /* then walk the parent list and print them out. we need to |
1156 /* then walk the parent list and print them out. we need to |
1156 * decrease the refcounting on each element after we handled |
1157 * decrease the refcounting on each element after we handled |
1157 * it. */ |
1158 * it. */ |
1158 for (parents = parentage; parents; parents = g_slist_next (parents)) { |
1159 for (parents = parentage; parents; parents = g_slist_next (parents)) { |
|
1160 if (G_IS_OBJECT (parents->data)) { |
|
1161 typename = G_OBJECT_TYPE_NAME (parents->data); |
|
1162 } else { |
|
1163 typename = NULL; |
|
1164 } |
1159 if (GST_IS_OBJECT (parents->data)) { |
1165 if (GST_IS_OBJECT (parents->data)) { |
1160 GstObject *item = GST_OBJECT_CAST (parents->data); |
1166 GstObject *item = GST_OBJECT_CAST (parents->data); |
1161 GstObjectClass *oclass = GST_OBJECT_GET_CLASS (item); |
1167 GstObjectClass *oclass = GST_OBJECT_GET_CLASS (item); |
1162 |
1168 gchar *objname = gst_object_get_name (item); |
1163 component = gst_object_get_name (item); |
1169 |
|
1170 component = g_strdup_printf ("%s:%s", typename, objname); |
1164 separator = oclass->path_string_separator; |
1171 separator = oclass->path_string_separator; |
1165 /* and unref now */ |
1172 /* and unref now */ |
1166 gst_object_unref (item); |
1173 gst_object_unref (item); |
|
1174 g_free (objname); |
1167 } else { |
1175 } else { |
1168 component = g_strdup_printf ("%p", parents->data); |
1176 if (typename) { |
|
1177 component = g_strdup_printf ("%s:%p", typename, parents->data); |
|
1178 } else { |
|
1179 component = g_strdup_printf ("%p", parents->data); |
|
1180 } |
1169 separator = "/"; |
1181 separator = "/"; |
1170 } |
1182 } |
1171 |
1183 |
1172 prevpath = path; |
1184 prevpath = path; |
1173 path = g_strjoin (separator, prevpath, component, NULL); |
1185 path = g_strjoin (separator, prevpath, component, NULL); |
1195 void (*object_loaded) (GstSignalObject * object, GstObject * new, |
1207 void (*object_loaded) (GstSignalObject * object, GstObject * new, |
1196 xmlNodePtr self); |
1208 xmlNodePtr self); |
1197 #endif |
1209 #endif |
1198 }; |
1210 }; |
1199 |
1211 |
1200 static GType |
1212 G_DEFINE_TYPE (GstSignalObject, gst_signal_object, G_TYPE_OBJECT); |
1201 gst_signal_object_get_type (void) |
|
1202 { |
|
1203 static GType signal_object_type = 0; |
|
1204 |
|
1205 if (G_UNLIKELY (signal_object_type == 0)) { |
|
1206 static const GTypeInfo signal_object_info = { |
|
1207 sizeof (GstSignalObjectClass), |
|
1208 NULL, |
|
1209 NULL, |
|
1210 (GClassInitFunc) gst_signal_object_class_init, |
|
1211 NULL, |
|
1212 NULL, |
|
1213 sizeof (GstSignalObject), |
|
1214 0, |
|
1215 (GInstanceInitFunc) gst_signal_object_init, |
|
1216 NULL |
|
1217 }; |
|
1218 |
|
1219 signal_object_type = |
|
1220 g_type_register_static (G_TYPE_OBJECT, "GstSignalObject", |
|
1221 &signal_object_info, 0); |
|
1222 } |
|
1223 return signal_object_type; |
|
1224 } |
|
1225 |
1213 |
1226 static void |
1214 static void |
1227 gst_signal_object_class_init (GstSignalObjectClass * klass) |
1215 gst_signal_object_class_init (GstSignalObjectClass * klass) |
1228 { |
1216 { |
1229 GObjectClass *gobject_class; |
|
1230 |
|
1231 gobject_class = (GObjectClass *) klass; |
|
1232 |
|
1233 parent_class = g_type_class_peek_parent (klass); |
1217 parent_class = g_type_class_peek_parent (klass); |
1234 |
1218 |
1235 #ifndef GST_DISABLE_LOADSAVE |
1219 #ifndef GST_DISABLE_LOADSAVE |
1236 gst_signal_object_signals[SO_OBJECT_LOADED] = |
1220 gst_signal_object_signals[SO_OBJECT_LOADED] = |
1237 g_signal_new ("object-loaded", G_TYPE_FROM_CLASS (klass), |
1221 g_signal_new ("object-loaded", G_TYPE_FROM_CLASS (klass), |