API doc updates.
[platform/upstream/gstreamer.git] / gst / gstutils.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *
5  * gstutils.c: Utility functions: gtk_get_property stuff, etc.
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 <stdio.h>
24 #include <string.h>
25
26 #include "gst_private.h"
27 #include "gstutils.h"
28
29 #include "gstextratypes.h"
30
31 #define ZERO(mem) memset(&mem, 0, sizeof(mem))
32
33 /**
34  * gst_util_get_int_arg:
35  * @object: the object to query
36  * @argname: the name of the argument
37  *
38  * Retrieves a property of an object as an integer.
39  *
40  * Returns: the property of the object
41  */
42 gint
43 gst_util_get_int_arg (GObject * object, const gchar * argname)
44 {
45   GValue value;
46
47   ZERO (value);
48   g_value_init (&value, G_TYPE_INT);
49   g_object_get_property (G_OBJECT (object), argname, &value);
50
51   return g_value_get_int (&value);
52 }
53
54 /**
55  * gst_util_get_bool_arg:
56  * @object: the object to query
57  * @argname: the name of the argument
58  *
59  * Retrieves a property of an object as a boolean.
60  *
61  * Returns: the property of the object
62  */
63 gint
64 gst_util_get_bool_arg (GObject * object, const gchar * argname)
65 {
66   GValue value;
67
68   ZERO (value);
69   g_value_init (&value, G_TYPE_BOOLEAN);
70   g_object_get_property (G_OBJECT (object), argname, &value);
71
72   return g_value_get_boolean (&value);
73 }
74
75 /**
76  * gst_util_get_long_arg:
77  * @object: the object to query
78  * @argname: the name of the argument
79  *
80  * Retrieves a property of an object as a long.
81  *
82  * Returns: the property of the object
83  */
84 glong
85 gst_util_get_long_arg (GObject * object, const gchar * argname)
86 {
87   GValue value;
88
89   ZERO (value);
90   g_value_init (&value, G_TYPE_LONG);
91   g_object_get_property (G_OBJECT (object), argname, &value);
92
93   return g_value_get_long (&value);
94 }
95
96 /**
97  * gst_util_get_int64_arg:
98  * @object: the object to query
99  * @argname: the name of the argument
100  *
101  * Retrieves a property of an object as an int64.
102  *
103  * Returns: the property of the object
104  */
105 gint64
106 gst_util_get_int64_arg (GObject *object, const gchar *argname)
107 {
108   GValue value;
109
110   ZERO (value);
111   g_value_init (&value, G_TYPE_INT64);
112   g_object_get_property (G_OBJECT (object), argname, &value);
113
114   return g_value_get_int64 (&value);
115 }
116
117 /**
118  * gst_util_get_float_arg:
119  * @object: the object to query
120  * @argname: the name of the argument
121  *
122  * Retrieves a property of an object as a float.
123  *
124  * Returns: the property of the object
125  */
126 gfloat
127 gst_util_get_float_arg (GObject * object, const gchar * argname)
128 {
129   GValue value;
130
131   ZERO (value);
132   g_value_init (&value, G_TYPE_FLOAT);
133   g_object_get_property (G_OBJECT (object), argname, &value);
134
135   return g_value_get_float (&value);
136 }
137
138 /**
139  * gst_util_get_double_arg:
140  * @object: the object to query
141  * @argname: the name of the argument
142  *
143  * Retrieves a property of an object as a double.
144  *
145  * Returns: the property of the object
146  */
147 gdouble
148 gst_util_get_double_arg (GObject * object, const gchar * argname)
149 {
150   GValue value;
151
152   ZERO (value);
153   g_value_init (&value, G_TYPE_DOUBLE);
154   g_object_get_property (G_OBJECT (object), argname, &value);
155
156   return g_value_get_double (&value);
157 }
158
159 /**
160  * gst_util_get_string_arg:
161  * @object: the object to query
162  * @argname: the name of the argument
163  *
164  * Retrieves a property of an object as a string.
165  *
166  * Returns: the property of the object
167  */
168 const gchar *
169 gst_util_get_string_arg (GObject * object, const gchar * argname)
170 {
171   GValue value;
172
173   ZERO (value);
174   g_value_init (&value, G_TYPE_STRING);
175   g_object_get_property (G_OBJECT (object), argname, &value);
176
177   return g_value_get_string (&value);   /* memleak? */
178 }
179
180 /**
181  * gst_util_get_pointer_arg:
182  * @object: the object to query
183  * @argname: the name of the argument
184  *
185  * Retrieves a property of an object as a pointer.
186  *
187  * Returns: the property of the object
188  */
189 gpointer
190 gst_util_get_pointer_arg (GObject * object, const gchar * argname)
191 {
192   GValue value;
193
194   ZERO (value);
195   g_value_init (&value, G_TYPE_POINTER);
196   g_object_get_property (G_OBJECT (object), argname, &value);
197
198   return g_value_get_pointer (&value);
199 }
200
201 /**
202  * gst_util_get_widget_property:
203  * @object: the object to query
204  * @argname: the name of the argument
205  *
206  * Retrieves a property of an object as a widget.
207  *
208  * Returns: the property of the object
209  */
210 /* COMMENTED OUT BECAUSE WE HAVE NO MORE gtk.h
211 GtkWidget*
212 gst_util_get_widget_property (GObject *object, const gchar *argname) 
213 {
214   GtkArg arg;
215
216   arg.name = argname;
217   gtk_object_getv(G_OBJECT(object),1,&arg);
218   
219   return GTK_WIDGET(G_VALUE_OBJECT(arg));
220 }
221 */
222
223 /**
224  * gst_util_dump_mem:
225  * @mem: a pointer to the memory to dump
226  * @size: the size of the memory block to dump
227  *
228  * Dumps the memory block into a hex representation. Useful for debugging.
229  */
230 void
231 gst_util_dump_mem (guchar * mem, guint size)
232 {
233   guint i, j;
234
235   i = j = 0;
236   while (i < size) {
237     if (j == 0) {
238       g_print ("\n%08x : ", i);
239       j = 15;
240     }
241     else {
242       j--;
243     }
244     g_print ("%02x ", mem[i]);
245     i++;
246   }
247   g_print ("\n");
248 }
249
250 /**
251  * gst_util_set_object_arg:
252  * @object: the object to set the argument of
253  * @name: the name of the argument to set
254  * @value: the string value to set
255  *
256  * Convertes the string value to the type of the objects argument and
257  * sets the argument with it.
258  */
259 void
260 gst_util_set_object_arg (GObject * object, const gchar * name, const gchar * value)
261 {
262   if (name && value) {
263     GParamSpec *paramspec;
264
265     paramspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), name);
266
267     if (!paramspec) {
268       return;
269     }
270
271     GST_DEBUG (0, "paramspec->flags is %d, paramspec->value_type is %d\n",
272                paramspec->flags, paramspec->value_type);
273
274     if (paramspec->flags & G_PARAM_WRITABLE) {
275       switch (paramspec->value_type) {
276         case G_TYPE_STRING:
277           g_object_set (G_OBJECT (object), name, value, NULL);
278           break;
279         case G_TYPE_ENUM:
280         case G_TYPE_INT:{
281           gint i;
282
283           sscanf (value, "%d", &i);
284           g_object_set (G_OBJECT (object), name, i, NULL);
285           break;
286         }
287         case G_TYPE_UINT:{
288           guint i;
289
290           sscanf (value, "%u", &i);
291           g_object_set (G_OBJECT (object), name, i, NULL);
292           break;
293         }
294         case G_TYPE_LONG:{
295           glong i;
296
297           sscanf (value, "%ld", &i);
298           g_object_set (G_OBJECT (object), name, i, NULL);
299           break;
300         }
301         case G_TYPE_ULONG:{
302           gulong i;
303
304           sscanf (value, "%lu", &i);
305           g_object_set (G_OBJECT (object), name, i, NULL);
306           break;
307         }
308         case G_TYPE_BOOLEAN:{
309           gboolean i = FALSE;
310
311           if (!strncmp ("true", value, 4))
312             i = TRUE;
313           g_object_set (G_OBJECT (object), name, i, NULL);
314           break;
315         }
316         case G_TYPE_CHAR:{
317           gchar i;
318
319           sscanf (value, "%c", &i);
320           g_object_set (G_OBJECT (object), name, i, NULL);
321           break;
322         }
323         case G_TYPE_UCHAR:{
324           guchar i;
325
326           sscanf (value, "%c", &i);
327           g_object_set (G_OBJECT (object), name, i, NULL);
328           break;
329         }
330         case G_TYPE_FLOAT:{
331           gfloat i;
332
333           sscanf (value, "%f", &i);
334           g_object_set (G_OBJECT (object), name, i, NULL);
335           break;
336         }
337         case G_TYPE_DOUBLE:{
338           gfloat i;
339
340           sscanf (value, "%g", &i);
341           g_object_set (G_OBJECT (object), name, (gdouble) i, NULL);
342           break;
343         }
344         default:
345           if (G_IS_PARAM_SPEC_ENUM (paramspec)) {
346             gint i;
347
348             sscanf (value, "%d", &i);
349             g_object_set (G_OBJECT (object), name, i, NULL);
350           }
351           else if (paramspec->value_type == GST_TYPE_FILENAME) {
352             g_object_set (G_OBJECT (object), name, value, NULL);
353           }
354           break;
355       }
356     }
357   }
358 }
359
360 /* -----------------------------------------------------
361  *
362  *  The following code will be moved out of the main
363  * gstreamer library someday.
364  */
365
366 #include "gstpad.h"
367 #include "gsttype.h"
368 #include "gstprops.h"
369 #include "gstpropsprivate.h"
370
371 static void
372 string_append_indent (GString * str, gint count)
373 {
374   gint xx;
375
376   for (xx = 0; xx < count; xx++)
377     g_string_append_c (str, ' ');
378 }
379
380 static void
381 gst_print_props (GString * buf, gint indent, GList * props, gboolean showname)
382 {
383   GList *elem;
384   guint width = 0;
385
386   if (showname)
387     for (elem = props; elem; elem = g_list_next (elem)) {
388       GstPropsEntry *prop = elem->data;
389       const gchar *name = g_quark_to_string (prop->propid);
390
391       if (width < strlen (name))
392         width = strlen (name);
393     }
394
395   for (elem = props; elem; elem = g_list_next (elem)) {
396     GstPropsEntry *prop = elem->data;
397
398     string_append_indent (buf, indent);
399     if (showname) {
400       const gchar *name = g_quark_to_string (prop->propid);
401
402       g_string_append (buf, name);
403       string_append_indent (buf, 2 + width - strlen (name));
404     }
405
406     switch (prop->propstype) {
407       case GST_PROPS_INT_ID:
408         g_string_append_printf (buf, "%d (int)\n", prop->data.int_data);
409         break;
410       case GST_PROPS_INT_RANGE_ID:
411         g_string_append_printf (buf, "%d - %d (int)\n",
412                                 prop->data.int_range_data.min, prop->data.int_range_data.max);
413         break;
414       case GST_PROPS_FLOAT_ID:
415         g_string_append_printf (buf, "%f (float)\n", prop->data.float_data);
416         break;
417       case GST_PROPS_FLOAT_RANGE_ID:
418         g_string_append_printf (buf, "%f - %f (float)\n",
419                                 prop->data.float_range_data.min, prop->data.float_range_data.max);
420         break;
421       case GST_PROPS_BOOL_ID:
422         g_string_append_printf (buf, "%s\n", prop->data.bool_data ? "TRUE" : "FALSE");
423         break;
424       case GST_PROPS_STRING_ID:
425         g_string_append_printf (buf, "\"%s\"\n", prop->data.string_data.string);
426         break;
427       case GST_PROPS_FOURCC_ID:
428         g_string_append_printf (buf, "'%c%c%c%c' (fourcc)\n",
429                                 prop->data.fourcc_data & 0xff,
430                                 prop->data.fourcc_data >> 8 & 0xff,
431                                 prop->data.fourcc_data >> 16 & 0xff,
432                                 prop->data.fourcc_data >> 24 & 0xff);
433         break;
434       case GST_PROPS_LIST_ID:
435         gst_print_props (buf, indent + 2, prop->data.list_data.entries, FALSE);
436         break;
437       default:
438         g_string_append_printf (buf, "unknown proptype %d\n", prop->propstype);
439         break;
440     }
441   }
442 }
443
444 /**
445  * gst_print_pad_caps:
446  * @buf: the buffer to print the caps in
447  * @indent: initial indentation
448  * @pad: the pad to print the caps from
449  *
450  * Write the pad capabilities in a human readable format into
451  * the given GString.
452  */
453 void
454 gst_print_pad_caps (GString * buf, gint indent, GstPad * pad)
455 {
456   GstRealPad *realpad;
457   GstCaps *caps;
458
459   realpad = GST_PAD_REALIZE (pad);
460   caps = realpad->caps;
461
462   if (!caps) {
463     string_append_indent (buf, indent);
464     g_string_printf (buf, "%s:%s has no capabilities", GST_DEBUG_PAD_NAME (pad));
465   }
466   else {
467     gint capx = 0;
468
469     while (caps) {
470       GstType *type;
471
472       string_append_indent (buf, indent);
473       g_string_append_printf (buf, "Cap[%d]: %s\n", capx++, caps->name);
474
475       type = gst_type_find_by_id (caps->id);
476       string_append_indent (buf, indent + 2);
477       g_string_append_printf (buf, "MIME type: %s\n", type->mime ? type->mime : "unknown/unknown");
478
479       if (caps->properties)
480         gst_print_props (buf, indent + 4, caps->properties->properties, TRUE);
481
482       caps = caps->next;
483     }
484   }
485 }
486
487 /**
488  * gst_print_element_args:
489  * @buf: the buffer to print the args in
490  * @indent: initial indentation
491  * @element: the element to print the args of
492  *
493  * Print the element argument in a human readable format in the given
494  * GString.
495  */
496 void
497 gst_print_element_args (GString * buf, gint indent, GstElement * element)
498 {
499   gint num_properties;
500   gint px;
501   guint width;
502
503   GParamSpec **property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (element),
504                                                                 &num_properties);
505
506   width = 0;
507   for (px = 0; px < num_properties; px++) {
508     GParamSpec *param = property_specs[px];
509
510     if (width < strlen (param->name))
511       width = strlen (param->name);
512   }
513
514   for (px = 0; px < num_properties; px++) {
515     GParamSpec *param = property_specs[px];
516     GValue value;
517
518     ZERO (value);
519
520     g_value_init (&value, param->value_type);
521     g_object_get_property (G_OBJECT (element), param->name, &value);
522
523     string_append_indent (buf, indent);
524     g_string_append (buf, param->name);
525     string_append_indent (buf, 2 + width - strlen (param->name));
526
527     if (G_IS_PARAM_SPEC_ENUM (param)) {
528       GEnumValue *values;
529
530 #ifdef USE_GLIB2
531       values = G_ENUM_CLASS (g_type_class_ref (param->value_type))->values;
532 #else
533       values = gtk_type_enum_get_values (param->value_type);
534 #endif
535
536       g_string_append_printf (buf, "%s (%s)",
537                               values[g_value_get_enum (&value)].value_nick,
538                               g_type_name (G_VALUE_TYPE (&value)));
539     }
540     else {
541       switch (G_VALUE_TYPE (&value)) {
542         case G_TYPE_STRING:
543           g_string_append_printf (buf, "\"%s\"", g_value_get_string (&value));
544           break;
545         case G_TYPE_BOOLEAN:
546           g_string_append (buf, g_value_get_boolean (&value) ? "TRUE" : "FALSE");
547           break;
548         case G_TYPE_ULONG:{
549           gulong val = g_value_get_ulong (&value);
550
551           g_string_append_printf (buf, "%lu (0x%lx)", val, val);
552           break;
553         }
554         case G_TYPE_LONG:{
555           glong val = g_value_get_long (&value);
556
557           g_string_append_printf (buf, "%ld (0x%lx)", val, val);
558           break;
559         }
560         case G_TYPE_UINT:{
561           guint val = g_value_get_uint (&value);
562
563           g_string_append_printf (buf, "%u (0x%x)", val, val);
564           break;
565         }
566         case G_TYPE_INT:{
567           gint val = g_value_get_int (&value);
568
569           g_string_append_printf (buf, "%d (0x%x)", val, val);
570           break;
571         }
572         case G_TYPE_FLOAT:
573           g_string_append_printf (buf, "%f", g_value_get_float (&value));
574           break;
575         case G_TYPE_DOUBLE:
576           g_string_append_printf (buf, "%f", g_value_get_double (&value));
577           break;
578         default:
579           g_string_append_printf (buf, "unknown value_type %d", G_VALUE_TYPE (&value));
580           break;
581       }
582     }
583
584     g_string_append_c (buf, '\n');
585
586     if (G_VALUE_TYPE (&value)) {
587       g_value_unset (&value);
588     }
589   }
590   g_free (property_specs);
591 }
592
593 /**
594  * gst_util_has_arg:
595  * @object: an object
596  * @argname: a property it might have
597  * @arg_type: the type of the argument it should have
598  * 
599  * Determines whether this @object has a property of name
600  * @argname and of type @arg_type
601  * 
602  * Return value: TRUE if it has the prop, else FALSE
603  **/
604 gboolean
605 gst_util_has_arg (GObject *object, const gchar *argname, GType arg_type)
606 {
607   GParamSpec *pspec;
608
609   pspec = g_object_class_find_property (
610           G_OBJECT_GET_CLASS (object), argname);
611
612   if (!pspec)
613     return FALSE;
614
615   if (pspec->value_type != arg_type)
616     return FALSE;
617
618   return TRUE;
619 }