gstobject.c 33.9 KB
Newer Older
1 2 3
/* GStreamer
 * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
 *                    2000 Wim Taymans <wtay@chello.be>
4
 *                    2005 Wim Taymans <wim@fluendo.com>
5 6
 *
 * gstobject.c: Fundamental class used for all of GStreamer
Erik Walthinsen's avatar
Erik Walthinsen committed
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
23

24 25 26 27
/**
 * SECTION:gstobject
 * @short_description: Base class for the GStreamer object hierarchy
 *
28 29
 * #GstObject provides a root for the object hierarchy tree filed in by the
 * GStreamer library.  It is currently a thin wrapper on top of
30 31
 * #GObject. It is an abstract class that is not very usable on its own.
 *
32 33 34
 * #GstObject gives us basic refcounting, parenting functionality and locking.
 * Most of the function are just extended for special GStreamer needs and can be
 * found under the same name in the base class of #GstObject which is #GObject
35 36
 * (e.g. g_object_ref() becomes gst_object_ref()).
 *
37 38 39
 * The most interesting difference between #GstObject and #GObject is the
 * "floating" reference count. A #GObject is created with a reference count of
 * 1, owned by the creator of the #GObject. (The owner of a reference is the
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
40
 * code section that has the right to call gst_object_unref() in order to
41 42 43
 * remove that reference.) A #GstObject is created with a reference count of 1
 * also, but it isn't owned by anyone; Instead, the initial reference count
 * of a #GstObject is "floating". The floating reference can be removed by
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
44 45
 * anyone at any time, by calling gst_object_sink().  gst_object_sink() does
 * nothing if an object is already sunk (has no floating reference).
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
46
 *
47
 * When you add a #GstElement to its parent container, the parent container will
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
48
 * do this:
49 50 51 52 53 54
 * <informalexample>
 * <programlisting>
 *   gst_object_ref (GST_OBJECT (child_element));
 *   gst_object_sink (GST_OBJECT (child_element));
 * </programlisting>
 * </informalexample>
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
55 56 57
 * This means that the container now owns a reference to the child element
 * (since it called gst_object_ref()), and the child element has no floating
 * reference.
58
 *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
59
 * The purpose of the floating reference is to keep the child element alive
60 61
 * until you add it to a parent container, which then manages the lifetime of
 * the object itself:
62 63 64 65 66 67 68 69 70
 * <informalexample>
 * <programlisting>
 *    element = gst_element_factory_make (factoryname, name);
 *    // element has one floating reference to keep it alive
 *    gst_bin_add (GST_BIN (bin), element);
 *    // element has one non-floating reference owned by the container
 * </programlisting>
 * </informalexample>
 *
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
71
 * Another effect of this is, that calling gst_object_unref() on a bin object,
72
 * will also destoy all the #GstElement objects in it. The same is true for
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
73
 * calling gst_bin_remove().
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
74
 *
75 76 77 78 79
 * Special care has to be taken for all methods that gst_object_sink() an object
 * since if the caller of those functions had a floating reference to the object,
 * the object reference is now invalid.
 *
 * In contrast to #GObject instances, #GstObject adds a name property. The functions
80 81
 * gst_object_set_name() and gst_object_get_name() are used to set/get the name
 * of the object.
82 83
 *
 * Last reviewed on 2005-11-09 (0.9.4)
84
 */
Erik Walthinsen's avatar
Erik Walthinsen committed
85

86 87
#include "gst_private.h"

88
#include "gstobject.h"
89
#include "gstmarshal.h"
90
#include "gstinfo.h"
91
#include "gstutils.h"
92

93 94
#ifndef GST_DISABLE_TRACE
#include "gsttrace.h"
95
static GstAllocTrace *_gst_object_trace;
96
#endif
Erik Walthinsen's avatar
Erik Walthinsen committed
97

98 99
#define DEBUG_REFCOUNT

Erik Walthinsen's avatar
Erik Walthinsen committed
100
/* Object signals and args */
Stefan Kost's avatar
Stefan Kost committed
101 102
/* FIXME-0.11: have a read-only parent property instead of the two signals
 * then we get notify::parent for free */
103 104
enum
{
Erik Walthinsen's avatar
Erik Walthinsen committed
105
  PARENT_SET,
106
  PARENT_UNSET,
107
#ifndef GST_DISABLE_LOADSAVE
108
  OBJECT_SAVED,
109
#endif
Wim Taymans's avatar
Wim Taymans committed
110
  DEEP_NOTIFY,
Erik Walthinsen's avatar
Erik Walthinsen committed
111 112 113
  LAST_SIGNAL
};

114 115
enum
{
Erik Walthinsen's avatar
Erik Walthinsen committed
116
  ARG_0,
117
  ARG_NAME
118
      /* FILL ME */
Erik Walthinsen's avatar
Erik Walthinsen committed
119 120
};

121 122
enum
{
123 124 125 126
  SO_OBJECT_LOADED,
  SO_LAST_SIGNAL
};

127 128
/* maps type name quark => count */
static GData *object_name_counts = NULL;
129

130
G_LOCK_DEFINE_STATIC (object_name_mutex);
131

132 133 134
typedef struct _GstSignalObject GstSignalObject;
typedef struct _GstSignalObjectClass GstSignalObjectClass;

135 136 137
static GType gst_signal_object_get_type (void);
static void gst_signal_object_class_init (GstSignalObjectClass * klass);
static void gst_signal_object_init (GstSignalObject * object);
138

139
#ifndef GST_DISABLE_LOADSAVE
140
static guint gst_signal_object_signals[SO_LAST_SIGNAL] = { 0 };
Wim Taymans's avatar
Wim Taymans committed
141
#endif
Erik Walthinsen's avatar
Erik Walthinsen committed
142

143 144 145 146 147 148
static void gst_object_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec);
static void gst_object_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec);
static void gst_object_dispatch_properties_changed (GObject * object,
    guint n_pspecs, GParamSpec ** pspecs);
Wim Taymans's avatar
Wim Taymans committed
149

150 151
static void gst_object_dispose (GObject * object);
static void gst_object_finalize (GObject * object);
152

153
static gboolean gst_object_set_name_default (GstObject * object);
154

155
#ifndef GST_DISABLE_LOADSAVE
156 157
static void gst_object_real_restore_thyself (GstObject * object,
    xmlNodePtr self);
158 159
#endif

160
static GObjectClass *parent_class = NULL;
Erik Walthinsen's avatar
Erik Walthinsen committed
161 162
static guint gst_object_signals[LAST_SIGNAL] = { 0 };

163
G_DEFINE_ABSTRACT_TYPE (GstObject, gst_object, G_TYPE_OBJECT);
Erik Walthinsen's avatar
Erik Walthinsen committed
164

165
static void
166
gst_object_class_init (GstObjectClass * klass)
167
{
168
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
Erik Walthinsen's avatar
Erik Walthinsen committed
169

170
  parent_class = g_type_class_peek_parent (klass);
Erik Walthinsen's avatar
Erik Walthinsen committed
171

172 173 174 175
#ifndef GST_DISABLE_TRACE
  _gst_object_trace = gst_alloc_trace_register (g_type_name (GST_TYPE_OBJECT));
#endif

Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
176 177
  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_object_set_property);
  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_object_get_property);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
178

179
  g_object_class_install_property (gobject_class, ARG_NAME,
180
      g_param_spec_string ("name", "Name", "The name of the object",
181 182
          NULL,
          G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
Wim Taymans's avatar
Wim Taymans committed
183

184 185
  /**
   * GstObject::parent-set:
186
   * @gstobject: a #GstObject
187 188
   * @parent: the new parent
   *
189
   * Emitted when the parent of an object is set.
190
   */
Erik Walthinsen's avatar
Erik Walthinsen committed
191
  gst_object_signals[PARENT_SET] =
192 193
      g_signal_new ("parent-set", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
      G_STRUCT_OFFSET (GstObjectClass, parent_set), NULL, NULL,
194
      g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_OBJECT);
195 196 197

  /**
   * GstObject::parent-unset:
198
   * @gstobject: a #GstObject
199 200
   * @parent: the old parent
   *
201
   * Emitted when the parent of an object is unset.
202
   */
203
  gst_object_signals[PARENT_UNSET] =
204 205
      g_signal_new ("parent-unset", G_TYPE_FROM_CLASS (klass),
      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstObjectClass, parent_unset), NULL,
206
      NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_OBJECT);
207

208
#ifndef GST_DISABLE_LOADSAVE
209 210
  /**
   * GstObject::object-saved:
211
   * @gstobject: a #GstObject
212 213
   * @xml_node: the xmlNodePtr of the parent node
   *
214
   * Trigered whenever a new object is saved to XML. You can connect to this
215 216 217 218 219
   * signal to insert custom XML tags into the core XML.
   */
  /* FIXME This should be the GType of xmlNodePtr instead of G_TYPE_POINTER
   *       (if libxml would use GObject)
   */
220
  gst_object_signals[OBJECT_SAVED] =
221 222 223 224
      g_signal_new ("object-saved", G_TYPE_FROM_CLASS (klass),
      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstObjectClass, object_saved), NULL,
      NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);

225
  klass->restore_thyself = gst_object_real_restore_thyself;
226
#endif
227 228 229

  /**
   * GstObject::deep-notify:
230
   * @gstobject: a #GstObject
231 232 233 234 235 236 237
   * @prop_object: the object that originated the signal
   * @prop: the property that changed
   *
   * The deep notify signal is used to be notified of property changes. It is
   * typically attached to the toplevel bin to receive notifications from all
   * the elements contained in that bin.
   */
Wim Taymans's avatar
Wim Taymans committed
238
  gst_object_signals[DEEP_NOTIFY] =
239 240 241
      g_signal_new ("deep-notify", G_TYPE_FROM_CLASS (klass),
      G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED |
      G_SIGNAL_NO_HOOKS, G_STRUCT_OFFSET (GstObjectClass, deep_notify), NULL,
242
      NULL, gst_marshal_VOID__OBJECT_PARAM, G_TYPE_NONE, 2, GST_TYPE_OBJECT,
243
      G_TYPE_PARAM);
244 245

  klass->path_string_separator = "/";
246 247
  klass->lock = g_new0 (GStaticRecMutex, 1);
  g_static_rec_mutex_init (klass->lock);
248 249

  klass->signal_object = g_object_new (gst_signal_object_get_type (), NULL);
Wim Taymans's avatar
Wim Taymans committed
250

251
  /* see the comments at gst_object_dispatch_properties_changed */
Wim Taymans's avatar
Wim Taymans committed
252
  gobject_class->dispatch_properties_changed
253
      = GST_DEBUG_FUNCPTR (gst_object_dispatch_properties_changed);
254

255
  gobject_class->dispose = gst_object_dispose;
256
  gobject_class->finalize = gst_object_finalize;
Erik Walthinsen's avatar
Erik Walthinsen committed
257 258
}

259
static void
260
gst_object_init (GstObject * object)
261
{
262
  object->lock = g_mutex_new ();
Erik Walthinsen's avatar
Erik Walthinsen committed
263
  object->parent = NULL;
Wim Taymans's avatar
Wim Taymans committed
264
  object->name = NULL;
Wim Taymans's avatar
Wim Taymans committed
265
  GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "%p new", object);
266

267 268 269 270
#ifndef GST_DISABLE_TRACE
  gst_alloc_trace_new (_gst_object_trace, object);
#endif

271
  object->flags = 0;
272
  GST_OBJECT_FLAG_SET (object, GST_OBJECT_FLOATING);
Erik Walthinsen's avatar
Erik Walthinsen committed
273 274
}

275 276
/**
 * gst_object_ref:
277
 * @object: a #GstObject to reference
278
 *
279
 * Increments the reference count on @object. This function
280
 * does not take the lock on @object because it relies on
281 282 283 284 285
 * atomic refcounting.
 *
 * This object returns the input parameter to ease writing
 * constructs like :
 *  result = gst_object_ref (object->parent);
Wim Taymans's avatar
Wim Taymans committed
286
 *
287
 * Returns: A pointer to @object
288
 */
289 290
gpointer
gst_object_ref (gpointer object)
291
{
292
  g_return_val_if_fail (object != NULL, NULL);
293

294
#ifdef DEBUG_REFCOUNT
Wim Taymans's avatar
Wim Taymans committed
295 296
  GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "%p ref %d->%d",
      object,
297 298
      ((GObject *) object)->ref_count, ((GObject *) object)->ref_count + 1);
#endif
299
  g_object_ref (object);
300 301 302 303 304 305

  return object;
}

/**
 * gst_object_unref:
306
 * @object: a #GstObject to unreference
307
 *
308
 * Decrements the reference count on @object.  If reference count hits
309 310
 * zero, destroy @object. This function does not take the lock
 * on @object as it relies on atomic refcounting.
311 312 313
 *
 * The unref method should never be called with the LOCK held since
 * this might deadlock the dispose function.
314
 */
315 316
void
gst_object_unref (gpointer object)
317
{
318
  g_return_if_fail (object != NULL);
319 320 321 322 323 324 325
  g_return_if_fail (((GObject *) object)->ref_count > 0);

#ifdef DEBUG_REFCOUNT
  GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "%p unref %d->%d",
      object,
      ((GObject *) object)->ref_count, ((GObject *) object)->ref_count - 1);
#endif
326
  g_object_unref (object);
327 328
}

329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
/**
 * gst_object_ref_sink:
 * @object: a #GstObject to sink
 *
 * Increase the reference count of @object, and possibly remove the floating
 * reference, if @object has a floating reference.
 *
 * In other words, if the object is floating, then this call "assumes ownership"
 * of the floating reference, converting it to a normal reference by clearing
 * the floating flag while leaving the reference count unchanged. If the object
 * is not floating, then this call adds a new normal reference increasing the
 * reference count by one.
 *
 * MT safe. This function grabs and releases @object lock.
 *
 * Since: 0.10.24
 */
void
gst_object_ref_sink (gpointer object)
{
  g_return_if_fail (GST_IS_OBJECT (object));

  GST_OBJECT_LOCK (object);
  if (G_LIKELY (GST_OBJECT_IS_FLOATING (object))) {
    GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "unsetting floating flag");
    GST_OBJECT_FLAG_UNSET (object, GST_OBJECT_FLOATING);
    GST_OBJECT_UNLOCK (object);
  } else {
    GST_OBJECT_UNLOCK (object);
    gst_object_ref (object);
  }
}

362 363
/**
 * gst_object_sink:
364 365
 * @object: a #GstObject to sink
 *
366
 * If @object was floating, the #GST_OBJECT_FLOATING flag is removed
367 368
 * and @object is unreffed. When @object was not floating,
 * this function does nothing.
369
 *
370 371
 * Any newly created object has a refcount of 1 and is floating.
 * This function should be used when creating a new object to
372 373 374 375
 * symbolically 'take ownership' of @object. This done by first doing a
 * gst_object_ref() to keep a reference to @object and then gst_object_sink()
 * to remove and unref any floating references to @object.
 * Use gst_object_set_parent() to have this done for you.
376
 *
377
 * MT safe. This function grabs and releases @object lock.
378 379
 */
void
380
gst_object_sink (gpointer object)
381 382 383
{
  g_return_if_fail (GST_IS_OBJECT (object));

384
  GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "sink");
Wim Taymans's avatar
Wim Taymans committed
385

386
  GST_OBJECT_LOCK (object);
387
  if (G_LIKELY (GST_OBJECT_IS_FLOATING (object))) {
388
    GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "clear floating flag");
389
    GST_OBJECT_FLAG_UNSET (object, GST_OBJECT_FLOATING);
390
    GST_OBJECT_UNLOCK (object);
391
    gst_object_unref (object);
392
  } else {
393
    GST_OBJECT_UNLOCK (object);
394 395 396
  }
}

397
/**
398
 * gst_object_replace:
399 400
 * @oldobj: pointer to a place of a #GstObject to replace
 * @newobj: a new #GstObject
401
 *
402 403
 * Unrefs the #GstObject pointed to by @oldobj, refs @newobj and
 * puts @newobj in *@oldobj. Be carefull when calling this
404
 * function, it does not take any locks. You might want to lock
405
 * the object owning @oldobj pointer before calling this
406
 * function.
407
 *
408
 * Make sure not to LOCK @oldobj because it might be unreffed
409
 * which could cause a deadlock when it is disposed.
410 411
 */
void
412
gst_object_replace (GstObject ** oldobj, GstObject * newobj)
413
{
414 415 416
  g_return_if_fail (oldobj != NULL);
  g_return_if_fail (*oldobj == NULL || GST_IS_OBJECT (*oldobj));
  g_return_if_fail (newobj == NULL || GST_IS_OBJECT (newobj));
417

418
#ifdef DEBUG_REFCOUNT
419 420
  GST_CAT_LOG (GST_CAT_REFCOUNTING, "replace %p %s (%d) with %p %s (%d)",
      *oldobj, *oldobj ? GST_STR_NULL (GST_OBJECT_NAME (*oldobj)) : "(NONE)",
421
      *oldobj ? G_OBJECT (*oldobj)->ref_count : 0,
422
      newobj, newobj ? GST_STR_NULL (GST_OBJECT_NAME (newobj)) : "(NONE)",
423
      newobj ? G_OBJECT (newobj)->ref_count : 0);
424
#endif
Wim Taymans's avatar
Wim Taymans committed
425

426
  if (G_LIKELY (*oldobj != newobj)) {
427 428 429 430
    if (newobj)
      gst_object_ref (newobj);
    if (*oldobj)
      gst_object_unref (*oldobj);
431 432 433 434 435

    *oldobj = newobj;
  }
}

436 437
/* dispose is called when the object has to release all links
 * to other objects */
438
static void
439
gst_object_dispose (GObject * object)
440
{
441 442
  GstObject *parent;

443
  GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "dispose");
444

445
  GST_OBJECT_LOCK (object);
446 447
  if ((parent = GST_OBJECT_PARENT (object)))
    goto have_parent;
448
  GST_OBJECT_PARENT (object) = NULL;
449
  GST_OBJECT_UNLOCK (object);
450

451
  parent_class->dispose (object);
452 453 454 455 456 457 458 459 460 461 462

  return;

  /* ERRORS */
have_parent:
  {
    g_critical ("\nTrying to dispose object \"%s\", but it still has a "
        "parent \"%s\".\nYou need to let the parent manage the "
        "object instead of unreffing the object directly.\n",
        GST_OBJECT_NAME (object), GST_OBJECT_NAME (parent));
    GST_OBJECT_UNLOCK (object);
463
    /* ref the object again to revive it in this error case */
464
    gst_object_ref (object);
465 466
    return;
  }
467 468
}

469
/* finalize is called when the object has to free its resources */
470
static void
471
gst_object_finalize (GObject * object)
472
{
473
  GstObject *gstobject = GST_OBJECT (object);
474

475
  GST_CAT_LOG_OBJECT (GST_CAT_REFCOUNTING, object, "finalize");
476

477 478
  g_signal_handlers_destroy (object);

479
  g_free (gstobject->name);
480
  g_mutex_free (gstobject->lock);
481

482
#ifndef GST_DISABLE_TRACE
483
  gst_alloc_trace_free (_gst_object_trace, object);
484 485
#endif

486
  parent_class->finalize (object);
487 488
}

489 490 491
/* Changing a GObject property of a GstObject will result in "deep_notify"
 * signals being emitted by the object itself, as well as in each parent
 * object. This is so that an application can connect a listener to the
Wim Taymans's avatar
Wim Taymans committed
492
 * top-level bin to catch property-change notifications for all contained
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
493
 * elements.
494
 *
495 496
 * This function is not MT safe in glib < 2.8 so we need to lock it with a
 * classwide mutex in that case.
497 498 499
 *
 * MT safe.
 */
Wim Taymans's avatar
Wim Taymans committed
500
static void
501 502
gst_object_dispatch_properties_changed (GObject * object,
    guint n_pspecs, GParamSpec ** pspecs)
Wim Taymans's avatar
Wim Taymans committed
503
{
504
  GstObject *gst_object, *parent, *old_parent;
Wim Taymans's avatar
Wim Taymans committed
505
  guint i;
506 507
  gchar *name, *debug_name;

Wim Taymans's avatar
Wim Taymans committed
508
  /* do the standard dispatching */
Wim Taymans's avatar
Wim Taymans committed
509
  parent_class->dispatch_properties_changed (object, n_pspecs, pspecs);
510 511 512 513

  gst_object = GST_OBJECT_CAST (object);
  name = gst_object_get_name (gst_object);
  debug_name = GST_STR_NULL (name);
Wim Taymans's avatar
Wim Taymans committed
514 515

  /* now let the parent dispatch those, too */
516 517
  parent = gst_object_get_parent (gst_object);
  while (parent) {
Wim Taymans's avatar
Wim Taymans committed
518
    for (i = 0; i < n_pspecs; i++) {
519 520
      GST_CAT_LOG_OBJECT (GST_CAT_PROPERTIES, parent,
          "deep notification from %s (%s)", debug_name, pspecs[i]->name);
521 522

      g_signal_emit (parent, gst_object_signals[DEEP_NOTIFY],
Wim Taymans's avatar
Wim Taymans committed
523
          g_quark_from_string (pspecs[i]->name), gst_object, pspecs[i]);
Wim Taymans's avatar
Wim Taymans committed
524 525
    }

526 527 528
    old_parent = parent;
    parent = gst_object_get_parent (old_parent);
    gst_object_unref (old_parent);
Wim Taymans's avatar
Wim Taymans committed
529
  }
530
  g_free (name);
Wim Taymans's avatar
Wim Taymans committed
531 532
}

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
533
/**
Wim Taymans's avatar
Wim Taymans committed
534 535 536 537
 * gst_object_default_deep_notify:
 * @object: the #GObject that signalled the notify.
 * @orig: a #GstObject that initiated the notify.
 * @pspec: a #GParamSpec of the property.
Wim Taymans's avatar
Wim Taymans committed
538 539
 * @excluded_props: a set of user-specified properties to exclude or
 *  NULL to show all changes.
Wim Taymans's avatar
Wim Taymans committed
540
 *
541
 * A default deep_notify signal callback for an object. The user data
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
542 543
 * should contain a pointer to an array of strings that should be excluded
 * from the notify. The default handler will print the new value of the property
Wim Taymans's avatar
Wim Taymans committed
544
 * using g_print.
545
 *
546 547
 * MT safe. This function grabs and releases @object's LOCK for getting its
 *          path string.
Wim Taymans's avatar
Wim Taymans committed
548 549
 */
void
550 551
gst_object_default_deep_notify (GObject * object, GstObject * orig,
    GParamSpec * pspec, gchar ** excluded_props)
Wim Taymans's avatar
Wim Taymans committed
552
{
553
  GValue value = { 0, };        /* the important thing is that value.type = 0 */
554
  gchar *str = NULL;
555
  gchar *name = NULL;
Wim Taymans's avatar
Wim Taymans committed
556 557 558 559 560

  if (pspec->flags & G_PARAM_READABLE) {
    /* let's not print these out for excluded properties... */
    while (excluded_props != NULL && *excluded_props != NULL) {
      if (strcmp (pspec->name, *excluded_props) == 0)
561
        return;
Wim Taymans's avatar
Wim Taymans committed
562 563 564 565 566
      excluded_props++;
    }
    g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
    g_object_get_property (G_OBJECT (orig), pspec->name, &value);

567
    /* FIXME: handle flags */
Wim Taymans's avatar
Wim Taymans committed
568 569
    if (G_IS_PARAM_SPEC_ENUM (pspec)) {
      GEnumValue *enum_value;
570
      GEnumClass *klass = G_ENUM_CLASS (g_type_class_ref (pspec->value_type));
571

572
      enum_value = g_enum_get_value (klass, g_value_get_enum (&value));
Wim Taymans's avatar
Wim Taymans committed
573 574

      str = g_strdup_printf ("%s (%d)", enum_value->value_nick,
575
          enum_value->value);
576
      g_type_class_unref (klass);
577
    } else {
Wim Taymans's avatar
Wim Taymans committed
578 579
      str = g_strdup_value_contents (&value);
    }
580 581 582
    name = gst_object_get_path_string (orig);
    g_print ("%s: %s = %s\n", name, pspec->name, str);
    g_free (name);
Wim Taymans's avatar
Wim Taymans committed
583 584 585
    g_free (str);
    g_value_unset (&value);
  } else {
586
    name = gst_object_get_path_string (orig);
587
    g_warning ("Parameter %s not readable in %s.", pspec->name, name);
588
    g_free (name);
Wim Taymans's avatar
Wim Taymans committed
589 590 591
  }
}

592
static gboolean
593
gst_object_set_name_default (GstObject * object)
594
{
595
  const gchar *type_name;
596
  gint count;
597
  gchar *name, *tmp;
598
  gboolean result;
599
  GQuark q;
600

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
601 602
  /* to ensure guaranteed uniqueness across threads, only one thread
   * may ever assign a name */
603 604
  G_LOCK (object_name_mutex);

605
  if (!object_name_counts) {
606
    g_datalist_init (&object_name_counts);
607
  }
608

609 610 611
  q = g_type_qname (G_OBJECT_TYPE (object));
  count = GPOINTER_TO_INT (g_datalist_id_get_data (&object_name_counts, q));
  g_datalist_id_set_data (&object_name_counts, q, GINT_TO_POINTER (count + 1));
612

613 614
  G_UNLOCK (object_name_mutex);

615
  /* GstFooSink -> foosinkN */
616
  type_name = g_quark_to_string (q);
617 618 619
  if (strncmp (type_name, "Gst", 3) == 0)
    type_name += 3;
  tmp = g_strdup_printf ("%s%d", type_name, count);
620
  name = g_ascii_strdown (tmp, -1);
621
  g_free (tmp);
622

623
  result = gst_object_set_name (object, name);
624
  g_free (name);
625 626

  return result;
627 628
}

629 630
/**
 * gst_object_set_name:
631
 * @object: a #GstObject
632
 * @name:   new name of object
633
 *
634
 * Sets the name of @object, or gives @object a guaranteed unique
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
635
 * name (if @name is NULL).
636 637 638
 * This function makes a copy of the provided name, so the caller
 * retains ownership of the name it sent.
 *
639 640 641
 * Returns: TRUE if the name could be set. Since Objects that have
 * a parent cannot be renamed, this function returns FALSE in those
 * cases.
642
 *
643
 * MT safe.  This function grabs and releases @object's LOCK.
644
 */
645
gboolean
646
gst_object_set_name (GstObject * object, const gchar * name)
647
{
648
  gboolean result;
649

650 651
  g_return_val_if_fail (GST_IS_OBJECT (object), FALSE);

652
  GST_OBJECT_LOCK (object);
653

654 655 656 657 658 659
  /* parented objects cannot be renamed */
  if (G_UNLIKELY (object->parent != NULL))
    goto had_parent;

  if (name != NULL) {
    g_free (object->name);
660
    object->name = g_strdup (name);
661
    GST_OBJECT_UNLOCK (object);
662 663
    result = TRUE;
  } else {
664
    GST_OBJECT_UNLOCK (object);
665
    result = gst_object_set_name_default (object);
666 667 668 669 670 671
  }
  return result;

  /* error */
had_parent:
  {
Stefan Kost's avatar
Stefan Kost committed
672
    GST_WARNING ("parented objects can't be renamed");
673
    GST_OBJECT_UNLOCK (object);
674 675
    return FALSE;
  }
676 677 678 679
}

/**
 * gst_object_get_name:
680
 * @object: a #GstObject
681
 *
682
 * Returns a copy of the name of @object.
683 684 685
 * Caller should g_free() the return value after usage.
 * For a nameless object, this returns NULL, which you can safely g_free()
 * as well.
686
 *
687
 * Returns: the name of @object. g_free() after usage.
688
 *
689
 * MT safe. This function grabs and releases @object's LOCK.
690
 */
691
gchar *
692
gst_object_get_name (GstObject * object)
693
{
694 695
  gchar *result = NULL;

696 697
  g_return_val_if_fail (GST_IS_OBJECT (object), NULL);

698
  GST_OBJECT_LOCK (object);
699
  result = g_strdup (object->name);
700
  GST_OBJECT_UNLOCK (object);
701 702 703 704 705 706

  return result;
}

/**
 * gst_object_set_name_prefix:
707
 * @object:      a #GstObject
708
 * @name_prefix: new name prefix of @object
709
 *
710
 * Sets the name prefix of @object to @name_prefix.
711 712 713
 * This function makes a copy of the provided name prefix, so the caller
 * retains ownership of the name prefix it sent.
 *
714
 * MT safe.  This function grabs and releases @object's LOCK.
715 716 717 718 719 720
 */
void
gst_object_set_name_prefix (GstObject * object, const gchar * name_prefix)
{
  g_return_if_fail (GST_IS_OBJECT (object));

721
  GST_OBJECT_LOCK (object);
722 723
  g_free (object->name_prefix);
  object->name_prefix = g_strdup (name_prefix); /* NULL gives NULL */
724
  GST_OBJECT_UNLOCK (object);
725 726 727 728
}

/**
 * gst_object_get_name_prefix:
729
 * @object: a #GstObject
730
 *
731
 * Returns a copy of the name prefix of @object.
732 733 734 735
 * Caller should g_free() the return value after usage.
 * For a prefixless object, this returns NULL, which you can safely g_free()
 * as well.
 *
736
 * Returns: the name prefix of @object. g_free() after usage.
737
 *
738
 * MT safe. This function grabs and releases @object's LOCK.
739 740 741 742 743 744 745 746
 */
gchar *
gst_object_get_name_prefix (GstObject * object)
{
  gchar *result = NULL;

  g_return_val_if_fail (GST_IS_OBJECT (object), NULL);

747
  GST_OBJECT_LOCK (object);
748
  result = g_strdup (object->name_prefix);
749
  GST_OBJECT_UNLOCK (object);
750 751

  return result;
Erik Walthinsen's avatar
Erik Walthinsen committed
752 753 754 755
}

/**
 * gst_object_set_parent:
756
 * @object: a #GstObject
Erik Walthinsen's avatar
Erik Walthinsen committed
757 758
 * @parent: new parent of object
 *
759
 * Sets the parent of @object to @parent. The object's reference count will
760
 * be incremented, and any floating reference will be removed (see gst_object_sink()).
761
 *
762 763
 * This function causes the parent-set signal to be emitted when the parent
 * was successfully set.
764
 *
765 766
 * Returns: TRUE if @parent could be set or FALSE when @object
 * already had a parent or @object and @parent are the same.
767
 *