gstreamer_core/gst/gstminiobject.c
changeset 0 0e761a78d257
child 8 4a7fac7dd34a
equal deleted inserted replaced
-1:000000000000 0:0e761a78d257
       
     1 /* GStreamer
       
     2  * Copyright (C) 2005 David Schleef <ds@schleef.org>
       
     3  *
       
     4  * gstminiobject.h: Header for GstMiniObject
       
     5  *
       
     6  * This library is free software; you can redistribute it and/or
       
     7  * modify it under the terms of the GNU Library General Public
       
     8  * License as published by the Free Software Foundation; either
       
     9  * version 2 of the License, or (at your option) any later version.
       
    10  *
       
    11  * This library is distributed in the hope that it will be useful,
       
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    14  * Library General Public License for more details.
       
    15  *
       
    16  * You should have received a copy of the GNU Library General Public
       
    17  * License along with this library; if not, write to the
       
    18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    19  * Boston, MA 02111-1307, USA.
       
    20  */
       
    21 /**
       
    22  * SECTION:gstminiobject
       
    23  * @short_description: Lightweight base class for the GStreamer object hierarchy
       
    24  *
       
    25  * #GstMiniObject is a baseclass like #GObject, but has been stripped down of 
       
    26  * features to be fast and small.
       
    27  * It offers sub-classing and ref-counting in the same way as #GObject does.
       
    28  * It has no properties and no signal-support though.
       
    29  *
       
    30  * Last reviewed on 2005-11-23 (0.9.5)
       
    31  */
       
    32 #ifdef HAVE_CONFIG_H
       
    33 #include "config.h"
       
    34 #endif
       
    35 
       
    36 #include "gst/gst_private.h"
       
    37 #include "gst/gstminiobject.h"
       
    38 #include "gst/gstinfo.h"
       
    39 #include <gobject/gvaluecollector.h>
       
    40 
       
    41 #ifndef GST_DISABLE_TRACE
       
    42 #include "gsttrace.h"
       
    43 static GstAllocTrace *_gst_mini_object_trace;
       
    44 #endif
       
    45 
       
    46 #define DEBUG_REFCOUNT
       
    47 
       
    48 #if 0
       
    49 static void gst_mini_object_base_init (gpointer g_class);
       
    50 static void gst_mini_object_base_finalize (gpointer g_class);
       
    51 #endif
       
    52 static void gst_mini_object_class_init (gpointer g_class, gpointer class_data);
       
    53 static void gst_mini_object_init (GTypeInstance * instance, gpointer klass);
       
    54 
       
    55 static void gst_value_mini_object_init (GValue * value);
       
    56 static void gst_value_mini_object_free (GValue * value);
       
    57 static void gst_value_mini_object_copy (const GValue * src_value,
       
    58     GValue * dest_value);
       
    59 static gpointer gst_value_mini_object_peek_pointer (const GValue * value);
       
    60 static gchar *gst_value_mini_object_collect (GValue * value,
       
    61     guint n_collect_values, GTypeCValue * collect_values, guint collect_flags);
       
    62 static gchar *gst_value_mini_object_lcopy (const GValue * value,
       
    63     guint n_collect_values, GTypeCValue * collect_values, guint collect_flags);
       
    64 
       
    65 static GstMiniObject *gst_mini_object_copy_default (const GstMiniObject * obj);
       
    66 static void gst_mini_object_finalize (GstMiniObject * obj);
       
    67 #ifdef __SYMBIAN32__
       
    68 EXPORT_C
       
    69 #endif
       
    70 
       
    71 
       
    72 GType
       
    73 gst_mini_object_get_type (void)
       
    74 {
       
    75   static GType _gst_mini_object_type = 0;
       
    76 
       
    77   if (G_UNLIKELY (_gst_mini_object_type == 0)) {
       
    78     GTypeValueTable value_table = {
       
    79       gst_value_mini_object_init,
       
    80       gst_value_mini_object_free,
       
    81       gst_value_mini_object_copy,
       
    82       gst_value_mini_object_peek_pointer,
       
    83       "p",
       
    84       gst_value_mini_object_collect,
       
    85       "p",
       
    86       gst_value_mini_object_lcopy
       
    87     };
       
    88     GTypeInfo mini_object_info = {
       
    89       sizeof (GstMiniObjectClass),
       
    90 #if 0
       
    91       gst_mini_object_base_init,
       
    92       gst_mini_object_base_finalize,
       
    93 #else
       
    94       NULL, NULL,
       
    95 #endif
       
    96       gst_mini_object_class_init,
       
    97       NULL,
       
    98       NULL,
       
    99       sizeof (GstMiniObject),
       
   100       0,
       
   101       (GInstanceInitFunc) gst_mini_object_init,
       
   102       NULL
       
   103     };
       
   104     static const GTypeFundamentalInfo mini_object_fundamental_info = {
       
   105       (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE |
       
   106           G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE)
       
   107     };
       
   108 
       
   109     mini_object_info.value_table = &value_table;
       
   110 
       
   111     _gst_mini_object_type = g_type_fundamental_next ();
       
   112     g_type_register_fundamental (_gst_mini_object_type, "GstMiniObject",
       
   113         &mini_object_info, &mini_object_fundamental_info, G_TYPE_FLAG_ABSTRACT);
       
   114 
       
   115 #ifndef GST_DISABLE_TRACE
       
   116     _gst_mini_object_trace =
       
   117         gst_alloc_trace_register (g_type_name (_gst_mini_object_type));
       
   118 #endif
       
   119   }
       
   120 
       
   121   return _gst_mini_object_type;
       
   122 }
       
   123 
       
   124 #if 0
       
   125 static void
       
   126 gst_mini_object_base_init (gpointer g_class)
       
   127 {
       
   128   /* do nothing */
       
   129 }
       
   130 
       
   131 static void
       
   132 gst_mini_object_base_finalize (gpointer g_class)
       
   133 {
       
   134   /* do nothing */
       
   135 }
       
   136 #endif
       
   137 
       
   138 static void
       
   139 gst_mini_object_class_init (gpointer g_class, gpointer class_data)
       
   140 {
       
   141   GstMiniObjectClass *mo_class = GST_MINI_OBJECT_CLASS (g_class);
       
   142 
       
   143   mo_class->copy = gst_mini_object_copy_default;
       
   144   mo_class->finalize = gst_mini_object_finalize;
       
   145 }
       
   146 
       
   147 static void
       
   148 gst_mini_object_init (GTypeInstance * instance, gpointer klass)
       
   149 {
       
   150   GstMiniObject *mini_object = GST_MINI_OBJECT_CAST (instance);
       
   151 
       
   152   mini_object->refcount = 1;
       
   153 }
       
   154 
       
   155 static GstMiniObject *
       
   156 gst_mini_object_copy_default (const GstMiniObject * obj)
       
   157 {
       
   158   g_warning ("GstMiniObject classes must implement GstMiniObject::copy");
       
   159   return NULL;
       
   160 }
       
   161 
       
   162 static void
       
   163 gst_mini_object_finalize (GstMiniObject * obj)
       
   164 {
       
   165   /* do nothing */
       
   166 }
       
   167 
       
   168 /**
       
   169  * gst_mini_object_new:
       
   170  * @type: the #GType of the mini-object to create
       
   171  *
       
   172  * Creates a new mini-object of the desired type.
       
   173  *
       
   174  * MT safe
       
   175  *
       
   176  * Returns: the new mini-object.
       
   177  */
       
   178 #ifdef __SYMBIAN32__
       
   179 EXPORT_C
       
   180 #endif
       
   181 
       
   182 GstMiniObject *
       
   183 gst_mini_object_new (GType type)
       
   184 {
       
   185   GstMiniObject *mini_object;
       
   186 
       
   187   /* we don't support dynamic types because they really aren't useful,
       
   188    * and could cause refcount problems */
       
   189   mini_object = (GstMiniObject *) g_type_create_instance (type);
       
   190 
       
   191 #ifndef GST_DISABLE_TRACE
       
   192   gst_alloc_trace_new (_gst_mini_object_trace, mini_object);
       
   193 #endif
       
   194 
       
   195   return mini_object;
       
   196 }
       
   197 
       
   198 /* FIXME 0.11: Current way of doing the copy makes it impossible
       
   199  * to currectly chain to the parent classes and do a copy in a
       
   200  * subclass without knowing all internals of the parent classes.
       
   201  *
       
   202  * For 0.11 we should do something like the following:
       
   203  *  - The GstMiniObjectClass::copy() implementation of GstMiniObject
       
   204  *    should call g_type_create_instance() with the type of the source
       
   205  *    object.
       
   206  *  - All GstMiniObjectClass::copy() implementations should as first
       
   207  *    thing chain up to the parent class and then do whatever they need
       
   208  *    to do to copy their type specific data. Note that this way the
       
   209  *    instance_init() functions are called!
       
   210  */
       
   211 
       
   212 /**
       
   213  * gst_mini_object_copy:
       
   214  * @mini_object: the mini-object to copy
       
   215  *
       
   216  * Creates a copy of the mini-object.
       
   217  *
       
   218  * MT safe
       
   219  *
       
   220  * Returns: the new mini-object.
       
   221  */
       
   222 #ifdef __SYMBIAN32__
       
   223 EXPORT_C
       
   224 #endif
       
   225 
       
   226 GstMiniObject *
       
   227 gst_mini_object_copy (const GstMiniObject * mini_object)
       
   228 {
       
   229   GstMiniObjectClass *mo_class;
       
   230 
       
   231   g_return_val_if_fail (mini_object != NULL, NULL);
       
   232 
       
   233   mo_class = GST_MINI_OBJECT_GET_CLASS (mini_object);
       
   234 
       
   235   return mo_class->copy (mini_object);
       
   236 }
       
   237 
       
   238 /**
       
   239  * gst_mini_object_is_writable:
       
   240  * @mini_object: the mini-object to check
       
   241  *
       
   242  * Checks if a mini-object is writable.  A mini-object is writable
       
   243  * if the reference count is one and the #GST_MINI_OBJECT_FLAG_READONLY
       
   244  * flag is not set.  Modification of a mini-object should only be
       
   245  * done after verifying that it is writable.
       
   246  *
       
   247  * MT safe
       
   248  *
       
   249  * Returns: TRUE if the object is writable.
       
   250  */
       
   251 #ifdef __SYMBIAN32__
       
   252 EXPORT_C
       
   253 #endif
       
   254 
       
   255 gboolean
       
   256 gst_mini_object_is_writable (const GstMiniObject * mini_object)
       
   257 {
       
   258   g_return_val_if_fail (mini_object != NULL, FALSE);
       
   259 
       
   260   return (GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) == 1) &&
       
   261       ((mini_object->flags & GST_MINI_OBJECT_FLAG_READONLY) == 0);
       
   262 }
       
   263 
       
   264 /**
       
   265  * gst_mini_object_make_writable:
       
   266  * @mini_object: the mini-object to make writable
       
   267  *
       
   268  * Checks if a mini-object is writable.  If not, a writable copy is made and
       
   269  * returned.  This gives away the reference to the original mini object,
       
   270  * and returns a reference to the new object.
       
   271  *
       
   272  * MT safe
       
   273  *
       
   274  * Returns: a mini-object (possibly the same pointer) that is writable.
       
   275  */
       
   276 #ifdef __SYMBIAN32__
       
   277 EXPORT_C
       
   278 #endif
       
   279 
       
   280 GstMiniObject *
       
   281 gst_mini_object_make_writable (GstMiniObject * mini_object)
       
   282 {
       
   283   GstMiniObject *ret;
       
   284 
       
   285   g_return_val_if_fail (mini_object != NULL, NULL);
       
   286 
       
   287   if (gst_mini_object_is_writable (mini_object)) {
       
   288     ret = (GstMiniObject *) mini_object;
       
   289   } else {
       
   290     ret = gst_mini_object_copy (mini_object);
       
   291     gst_mini_object_unref ((GstMiniObject *) mini_object);
       
   292   }
       
   293 
       
   294   return ret;
       
   295 }
       
   296 
       
   297 /**
       
   298  * gst_mini_object_ref:
       
   299  * @mini_object: the mini-object
       
   300  *
       
   301  * Increase the reference count of the mini-object.
       
   302  *
       
   303  * Note that the refcount affects the writeability
       
   304  * of @mini-object, see gst_mini_object_is_writable(). It is 
       
   305  * important to note that keeping additional references to
       
   306  * GstMiniObject instances can potentially increase the number
       
   307  * of memcpy operations in a pipeline, especially if the miniobject
       
   308  * is a #GstBuffer.
       
   309  *
       
   310  * Returns: the mini-object.
       
   311  */
       
   312 #ifdef __SYMBIAN32__
       
   313 EXPORT_C
       
   314 #endif
       
   315 
       
   316 GstMiniObject *
       
   317 gst_mini_object_ref (GstMiniObject * mini_object)
       
   318 {
       
   319   g_return_val_if_fail (mini_object != NULL, NULL);
       
   320   /* we cannot assert that the refcount > 0 since a bufferalloc
       
   321    * function might resurrect an object
       
   322    g_return_val_if_fail (mini_object->refcount > 0, NULL);
       
   323    */
       
   324 #ifdef DEBUG_REFCOUNT
       
   325   g_return_val_if_fail (GST_IS_MINI_OBJECT (mini_object), NULL);
       
   326 
       
   327   GST_CAT_LOG (GST_CAT_REFCOUNTING, "%p ref %d->%d",
       
   328       mini_object,
       
   329       GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object),
       
   330       GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) + 1);
       
   331 #endif
       
   332 
       
   333   g_atomic_int_inc (&mini_object->refcount);
       
   334 
       
   335   return mini_object;
       
   336 }
       
   337 
       
   338 static void
       
   339 gst_mini_object_free (GstMiniObject * mini_object)
       
   340 {
       
   341   GstMiniObjectClass *mo_class;
       
   342 
       
   343   mo_class = GST_MINI_OBJECT_GET_CLASS (mini_object);
       
   344   mo_class->finalize (mini_object);
       
   345 
       
   346   /* if the refcount is still 0 we can really free the
       
   347    * object, else the finalize method recycled the object */
       
   348   if (g_atomic_int_get (&mini_object->refcount) == 0) {
       
   349 #ifndef GST_DISABLE_TRACE
       
   350     gst_alloc_trace_free (_gst_mini_object_trace, mini_object);
       
   351 #endif
       
   352     g_type_free_instance ((GTypeInstance *) mini_object);
       
   353   }
       
   354 }
       
   355 
       
   356 /**
       
   357  * gst_mini_object_unref:
       
   358  * @mini_object: the mini-object
       
   359  *
       
   360  * Decreases the reference count of the mini-object, possibly freeing
       
   361  * the mini-object.
       
   362  */
       
   363 #ifdef __SYMBIAN32__
       
   364 EXPORT_C
       
   365 #endif
       
   366 
       
   367 void
       
   368 gst_mini_object_unref (GstMiniObject * mini_object)
       
   369 {
       
   370   g_return_if_fail (mini_object != NULL);
       
   371   g_return_if_fail (mini_object->refcount > 0);
       
   372 
       
   373 #ifdef DEBUG_REFCOUNT
       
   374   g_return_if_fail (GST_IS_MINI_OBJECT (mini_object));
       
   375 
       
   376   GST_CAT_LOG (GST_CAT_REFCOUNTING, "%p unref %d->%d",
       
   377       mini_object,
       
   378       GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object),
       
   379       GST_MINI_OBJECT_REFCOUNT_VALUE (mini_object) - 1);
       
   380 #endif
       
   381 
       
   382   if (G_UNLIKELY (g_atomic_int_dec_and_test (&mini_object->refcount))) {
       
   383     gst_mini_object_free (mini_object);
       
   384   }
       
   385 }
       
   386 
       
   387 /**
       
   388  * gst_mini_object_replace:
       
   389  * @olddata: pointer to a pointer to a mini-object to be replaced
       
   390  * @newdata: pointer to new mini-object
       
   391  *
       
   392  * Modifies a pointer to point to a new mini-object.  The modification
       
   393  * is done atomically, and the reference counts are updated correctly.
       
   394  * Either @newdata and the value pointed to by @olddata may be NULL.
       
   395  */
       
   396 #ifdef __SYMBIAN32__
       
   397 EXPORT_C
       
   398 #endif
       
   399 
       
   400 void
       
   401 gst_mini_object_replace (GstMiniObject ** olddata, GstMiniObject * newdata)
       
   402 {
       
   403   GstMiniObject *olddata_val;
       
   404 
       
   405   g_return_if_fail (olddata != NULL);
       
   406 
       
   407 #ifdef DEBUG_REFCOUNT
       
   408   GST_CAT_LOG (GST_CAT_REFCOUNTING, "replace %p (%d) with %p (%d)",
       
   409       *olddata, *olddata ? (*olddata)->refcount : 0,
       
   410       newdata, newdata ? newdata->refcount : 0);
       
   411 #endif
       
   412 
       
   413   olddata_val = g_atomic_pointer_get ((gpointer *) olddata);
       
   414 
       
   415   if (olddata_val == newdata)
       
   416     return;
       
   417 
       
   418   if (newdata)
       
   419     gst_mini_object_ref (newdata);
       
   420 
       
   421   while (!g_atomic_pointer_compare_and_exchange ((gpointer *) olddata,
       
   422           olddata_val, newdata)) {
       
   423     olddata_val = g_atomic_pointer_get ((gpointer *) olddata);
       
   424   }
       
   425 
       
   426   if (olddata_val)
       
   427     gst_mini_object_unref (olddata_val);
       
   428 }
       
   429 
       
   430 static void
       
   431 gst_value_mini_object_init (GValue * value)
       
   432 {
       
   433   value->data[0].v_pointer = NULL;
       
   434 }
       
   435 
       
   436 static void
       
   437 gst_value_mini_object_free (GValue * value)
       
   438 {
       
   439   if (value->data[0].v_pointer) {
       
   440     gst_mini_object_unref (GST_MINI_OBJECT_CAST (value->data[0].v_pointer));
       
   441   }
       
   442 }
       
   443 
       
   444 static void
       
   445 gst_value_mini_object_copy (const GValue * src_value, GValue * dest_value)
       
   446 {
       
   447   if (src_value->data[0].v_pointer) {
       
   448     dest_value->data[0].v_pointer =
       
   449         gst_mini_object_ref (GST_MINI_OBJECT_CAST (src_value->data[0].
       
   450             v_pointer));
       
   451   } else {
       
   452     dest_value->data[0].v_pointer = NULL;
       
   453   }
       
   454 }
       
   455 
       
   456 static gpointer
       
   457 gst_value_mini_object_peek_pointer (const GValue * value)
       
   458 {
       
   459   return value->data[0].v_pointer;
       
   460 }
       
   461 
       
   462 static gchar *
       
   463 gst_value_mini_object_collect (GValue * value, guint n_collect_values,
       
   464     GTypeCValue * collect_values, guint collect_flags)
       
   465 {
       
   466   gst_value_set_mini_object (value, collect_values[0].v_pointer);
       
   467 
       
   468   return NULL;
       
   469 }
       
   470 
       
   471 static gchar *
       
   472 gst_value_mini_object_lcopy (const GValue * value, guint n_collect_values,
       
   473     GTypeCValue * collect_values, guint collect_flags)
       
   474 {
       
   475   gpointer *mini_object_p = collect_values[0].v_pointer;
       
   476 
       
   477   if (!mini_object_p) {
       
   478     return g_strdup_printf ("value location for '%s' passed as NULL",
       
   479         G_VALUE_TYPE_NAME (value));
       
   480   }
       
   481 
       
   482   if (!value->data[0].v_pointer)
       
   483     *mini_object_p = NULL;
       
   484   else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
       
   485     *mini_object_p = value->data[0].v_pointer;
       
   486   else
       
   487     *mini_object_p = gst_mini_object_ref (value->data[0].v_pointer);
       
   488 
       
   489   return NULL;
       
   490 }
       
   491 
       
   492 /**
       
   493  * gst_value_set_mini_object:
       
   494  * @value:       a valid #GValue of %GST_TYPE_MINI_OBJECT derived type
       
   495  * @mini_object: mini object value to set
       
   496  *
       
   497  * Set the contents of a %GST_TYPE_MINI_OBJECT derived #GValue to
       
   498  * @mini_object.
       
   499  * The caller retains ownership of the reference.
       
   500  */
       
   501 #ifdef __SYMBIAN32__
       
   502 EXPORT_C
       
   503 #endif
       
   504 
       
   505 void
       
   506 gst_value_set_mini_object (GValue * value, GstMiniObject * mini_object)
       
   507 {
       
   508   gpointer *pointer_p;
       
   509 
       
   510   g_return_if_fail (GST_VALUE_HOLDS_MINI_OBJECT (value));
       
   511   g_return_if_fail (mini_object == NULL || GST_IS_MINI_OBJECT (mini_object));
       
   512 
       
   513   pointer_p = &value->data[0].v_pointer;
       
   514   gst_mini_object_replace ((GstMiniObject **) pointer_p, mini_object);
       
   515 }
       
   516 
       
   517 /**
       
   518  * gst_value_take_mini_object:
       
   519  * @value:       a valid #GValue of %GST_TYPE_MINI_OBJECT derived type
       
   520  * @mini_object: mini object value to take
       
   521  *
       
   522  * Set the contents of a %GST_TYPE_MINI_OBJECT derived #GValue to
       
   523  * @mini_object.
       
   524  * Takes over the ownership of the caller's reference to @mini_object;
       
   525  * the caller doesn't have to unref it any more.
       
   526  */
       
   527 #ifdef __SYMBIAN32__
       
   528 EXPORT_C
       
   529 #endif
       
   530 
       
   531 void
       
   532 gst_value_take_mini_object (GValue * value, GstMiniObject * mini_object)
       
   533 {
       
   534   gpointer *pointer_p;
       
   535 
       
   536   g_return_if_fail (GST_VALUE_HOLDS_MINI_OBJECT (value));
       
   537   g_return_if_fail (mini_object == NULL || GST_IS_MINI_OBJECT (mini_object));
       
   538 
       
   539   pointer_p = &value->data[0].v_pointer;
       
   540   /* takes additional refcount */
       
   541   gst_mini_object_replace ((GstMiniObject **) pointer_p, mini_object);
       
   542   /* remove additional refcount */
       
   543   if (mini_object)
       
   544     gst_mini_object_unref (mini_object);
       
   545 }
       
   546 
       
   547 /**
       
   548  * gst_value_get_mini_object:
       
   549  * @value:   a valid #GValue of %GST_TYPE_MINI_OBJECT derived type
       
   550  *
       
   551  * Get the contents of a %GST_TYPE_MINI_OBJECT derived #GValue.
       
   552  * Does not increase the refcount of the returned object.
       
   553  *
       
   554  * Returns: mini object contents of @value
       
   555  */
       
   556 #ifdef __SYMBIAN32__
       
   557 EXPORT_C
       
   558 #endif
       
   559 
       
   560 GstMiniObject *
       
   561 gst_value_get_mini_object (const GValue * value)
       
   562 {
       
   563   g_return_val_if_fail (GST_VALUE_HOLDS_MINI_OBJECT (value), NULL);
       
   564 
       
   565   return value->data[0].v_pointer;
       
   566 }
       
   567 
       
   568 /* param spec */
       
   569 
       
   570 static GType gst_param_spec_mini_object_get_type (void);
       
   571 
       
   572 #define GST_TYPE_PARAM_SPEC_MINI_OBJECT (gst_param_spec_mini_object_get_type())
       
   573 #define GST_PARAM_SPEC_MINI_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_PARAM_SPEC_MINI_OBJECT, GstParamSpecMiniObject))
       
   574 
       
   575 typedef struct _GstParamSpecMiniObject GstParamSpecMiniObject;
       
   576 struct _GstParamSpecMiniObject
       
   577 {
       
   578   GParamSpec parent_instance;
       
   579 };
       
   580 
       
   581 static void
       
   582 param_mini_object_init (GParamSpec * pspec)
       
   583 {
       
   584   /* GParamSpecMiniObject *ospec = G_PARAM_SPEC_MINI_OBJECT (pspec); */
       
   585 }
       
   586 
       
   587 static void
       
   588 param_mini_object_set_default (GParamSpec * pspec, GValue * value)
       
   589 {
       
   590   value->data[0].v_pointer = NULL;
       
   591 }
       
   592 
       
   593 static gboolean
       
   594 param_mini_object_validate (GParamSpec * pspec, GValue * value)
       
   595 {
       
   596   GstParamSpecMiniObject *ospec = GST_PARAM_SPEC_MINI_OBJECT (pspec);
       
   597   GstMiniObject *mini_object = value->data[0].v_pointer;
       
   598   gboolean changed = FALSE;
       
   599 
       
   600   if (mini_object
       
   601       && !g_value_type_compatible (G_OBJECT_TYPE (mini_object),
       
   602           G_PARAM_SPEC_VALUE_TYPE (ospec))) {
       
   603     gst_mini_object_unref (mini_object);
       
   604     value->data[0].v_pointer = NULL;
       
   605     changed = TRUE;
       
   606   }
       
   607 
       
   608   return changed;
       
   609 }
       
   610 
       
   611 static gint
       
   612 param_mini_object_values_cmp (GParamSpec * pspec,
       
   613     const GValue * value1, const GValue * value2)
       
   614 {
       
   615   guint8 *p1 = value1->data[0].v_pointer;
       
   616   guint8 *p2 = value2->data[0].v_pointer;
       
   617 
       
   618   /* not much to compare here, try to at least provide stable lesser/greater result */
       
   619 
       
   620   return p1 < p2 ? -1 : p1 > p2;
       
   621 }
       
   622 
       
   623 static GType
       
   624 gst_param_spec_mini_object_get_type (void)
       
   625 {
       
   626   static GType type;
       
   627 
       
   628   if (G_UNLIKELY (type) == 0) {
       
   629     static const GParamSpecTypeInfo pspec_info = {
       
   630       sizeof (GstParamSpecMiniObject),  /* instance_size */
       
   631       16,                       /* n_preallocs */
       
   632       param_mini_object_init,   /* instance_init */
       
   633       G_TYPE_OBJECT,            /* value_type */
       
   634       NULL,                     /* finalize */
       
   635       param_mini_object_set_default,    /* value_set_default */
       
   636       param_mini_object_validate,       /* value_validate */
       
   637       param_mini_object_values_cmp,     /* values_cmp */
       
   638     };
       
   639     /* FIXME 0.11: Should really be GstParamSpecMiniObject */
       
   640     type = g_param_type_register_static ("GParamSpecMiniObject", &pspec_info);
       
   641   }
       
   642 
       
   643   return type;
       
   644 }
       
   645 
       
   646 /**
       
   647  * gst_param_spec_mini_object:
       
   648  * @name: the canonical name of the property
       
   649  * @nick: the nickname of the property
       
   650  * @blurb: a short description of the property
       
   651  * @object_type: the #GstMiniObjectType for the property
       
   652  * @flags: a combination of #GParamFlags
       
   653  *
       
   654  * Creates a new #GParamSpec instance that hold #GstMiniObject references.
       
   655  *
       
   656  * Returns: a newly allocated #GParamSpec instance
       
   657  */
       
   658 #ifdef __SYMBIAN32__
       
   659 EXPORT_C
       
   660 #endif
       
   661 
       
   662 GParamSpec *
       
   663 gst_param_spec_mini_object (const char *name, const char *nick,
       
   664     const char *blurb, GType object_type, GParamFlags flags)
       
   665 {
       
   666   GstParamSpecMiniObject *ospec;
       
   667 
       
   668   g_return_val_if_fail (g_type_is_a (object_type, GST_TYPE_MINI_OBJECT), NULL);
       
   669 
       
   670   ospec = g_param_spec_internal (GST_TYPE_PARAM_SPEC_MINI_OBJECT,
       
   671       name, nick, blurb, flags);
       
   672   G_PARAM_SPEC (ospec)->value_type = object_type;
       
   673 
       
   674   return G_PARAM_SPEC (ospec);
       
   675 }