Tizen 2.0 Release
[framework/multimedia/gst-plugins-bad0.10.git] / tests / examples / opencv / gst_element_print_properties.c
1 /* GStreamer
2  * Copyright (C) 2010 Wesley Miller <wmiller@sdr.com>
3  *
4  *
5  *  gst_element_print_properties(): a tool to inspect GStreamer
6  *                                  element properties
7  *
8  *  This program is free software: you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation, either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22
23
24 #include <gst/gst.h>
25 #include <string.h>
26 #include <stdio.h>
27 #include <locale.h>
28
29 #include "gst_element_print_properties.h"
30
31
32 void
33 gst_element_print_properties (GstElement * element)
34 {
35   /////////////////////////////////////////////////////////////////////////////
36   //
37   // Formatting setup
38   //
39   //    Change the valuses of c2w, c3w and c4w to adjust the 2nd, 3rd and 4th
40   //    column widths, respectively.  The gutter width is fixed at 3 and
41   //    alwasys prints as " | ".  Column 1 has a fixed width of 3.
42   //
43   //    The first two rows for each element's output are its element class
44   //    name (e.g. "GstAudioResample") and its element factory name
45   //    ("audioresample").  The long element factory name ("Audio resampler")
46   //    is in column 4 following the element factory name.
47   //
48   //    Most properties use this format.  Multivalued items like CAPS, certain
49   //    GST_TYPEs and enums are different.
50   //
51   //      Column 1  contains the rwc, "readable", "writable", "controllable"
52   //                flags of the property.
53   //      Column 2  contains the property name
54   //      Column 3  contains the current value
55   //      Column 4  contains the property type, e.g. G_TYPE_INT
56   //      Column 5  contains the range, if there is one, and the default.
57   //                The range is encosed in parentheses. e.g.  "(1-10)   5"
58   //
59   //    CAPS, enums, flags and some undefined items have no columns 4 or 5 and
60   //    column 3 will contain a description of the item.  Additional rows may
61   //    list specific valused (CAPS and flags).
62   //
63   //    String values are enclosed in double quotes.  A missing right quote
64   //    inidicates the string had been truncated.
65   //
66   //  Screen column
67   //  ----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9--->
68   //
69   //  formatted columns with built in gutters
70   //  --- | ---------c2---------- | ---------c3-------- | -----------c4---------- | --> unspecified
71   //
72   //  <-->|<--- property name --->|<-- current value -->|<-------- type --------->|<----- range and default ----->
73   //      | ELEMENT CLASS NAME    | GstAudioResample    |                         |
74   //      | ELEMENT FACTORY NAME  | audioresample       | Audio resampler         |
75   //  RW- | name                  | "audioResampler"    | G_TYPE_STRING           | null
76   //  RW- | qos                   | false               | G_TYPE_BOOLEAN          | false
77   //  RW- | quality               | 8                   | G_TYPE_INT              | (0 - 10)   4
78   //
79   /////////////////////////////////////////////////////////////////////////////
80
81   const guint c2w = 21;         // column 2 width
82   const guint c3w = 19;         // column 3 width
83   const guint c4w = 23;         // column 4 width
84
85   /////////////////////////////////////////////////////////////////////////////
86   // end configuration variables.
87   /////////////////////////////////////////////////////////////////////////////
88
89   GParamSpec **property_specs;
90   guint num_properties, i;
91   gboolean readable;
92
93
94   g_return_if_fail (element != NULL);
95
96   property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (element),
97       &num_properties);
98
99    /*--- draw the header information ---*/
100   print_column_titles (c2w, c3w, c4w);
101   print_element_info (element, c2w, c3w, c4w);
102
103
104   for (i = 0; i < num_properties; i++) {
105     gchar flags[4];
106     GValue value = { 0, };
107     GParamSpec *param = property_specs[i];
108
109     readable = FALSE;
110
111     g_value_init (&value, param->value_type);
112
113     flags[0] = '-';
114     flags[1] = '-';
115     flags[2] = '-';
116     flags[3] = 0x0;
117
118     if (param->flags & G_PARAM_READABLE) {
119       g_object_get_property (G_OBJECT (element), param->name, &value);
120       readable = TRUE;
121       flags[0] = 'r';
122     }
123
124     if (param->flags & G_PARAM_WRITABLE)
125       flags[1] = 'w';
126
127     if (param->flags & GST_PARAM_CONTROLLABLE)
128       flags[2] = 'c';
129
130     g_print ("%s |", flags);
131     g_print (" %-*s | ", c2w, g_param_spec_get_name (param));
132
133     switch (G_VALUE_TYPE (&value)) {
134       case G_TYPE_STRING:      // String
135       {
136         GParamSpecString *pstring = G_PARAM_SPEC_STRING (param);
137         if (readable) {         /* current */
138           const char *string_val = g_value_get_string (&value);
139           gchar work_string[100];
140
141           if (string_val == NULL)
142             sprintf (work_string, "\"%s\"", "null");
143           else
144             sprintf (work_string, "\"%s\"", string_val);
145           g_print ("%-*.*s", c3w, c3w, work_string);
146         } else {
147           g_print ("%-*s", c3w, "<not readable>");      /* alt current */
148         }
149         g_print (" | %-*s", c4w, "G_TYPE_STRING");      /* type */
150
151         if (pstring->default_value == NULL)
152           g_print (" | %s", "null");    /* default */
153         else
154           g_print (" | \"%s\"", pstring->default_value);        /* default */
155         break;
156       }
157
158       case G_TYPE_BOOLEAN:     //  Boolean
159       {
160         GParamSpecBoolean *pboolean = G_PARAM_SPEC_BOOLEAN (param);
161         if (readable)           /* current */
162           g_print ("%-*s", c3w,
163               (g_value_get_boolean (&value) ? "true" : "false"));
164         else
165           g_print ("%-*s", c3w, "<not readable>");
166         g_print (" | %-*s", c4w, "G_TYPE_BOOLEAN");     /* type */
167         g_print (" | %s ",      /* default */
168             (pboolean->default_value ? "true" : "false"));
169         break;
170       }
171
172       case G_TYPE_ULONG:       //  Unsigned Long
173       {
174         GParamSpecULong *pulong = G_PARAM_SPEC_ULONG (param);
175         if (readable)           /* current */
176           g_print ("%-*lu", c3w, g_value_get_ulong (&value));
177         else
178           g_print ("%-*s", c3w, "<not readable>");
179         g_print (" | %-*s", c4w, "G_TYPE_ULONG");       /* type */
180         g_print (" | (%lu - %lu)   %lu ", pulong->minimum, pulong->maximum,     /* range */
181             pulong->default_value);     /* default */
182         break;
183       }
184
185       case G_TYPE_LONG:        //  Long
186       {
187         GParamSpecLong *plong = G_PARAM_SPEC_LONG (param);
188         if (readable)           /* current */
189           g_print ("%-*ld", c3w, g_value_get_long (&value));
190         else
191           g_print ("%-*s", c3w, "<not readable>");
192         g_print (" | %-*s", c4w, "G_TYPE_LONG");        /* type */
193         g_print (" | (%ld - %ld)   %ld ", plong->minimum, plong->maximum,       /* range */
194             plong->default_value);      /* default */
195         break;
196       }
197
198       case G_TYPE_UINT:        //  Unsigned Integer
199       {
200         GParamSpecUInt *puint = G_PARAM_SPEC_UINT (param);
201         if (readable)           /* current */
202           g_print ("%-*u", c3w, g_value_get_uint (&value));
203         else
204           g_print ("%-*s", c3w, "<not readable>");
205         g_print (" | %-*s", c4w, "G_TYPE_UINT");        /* type */
206         g_print (" | (%u - %u)   %u ", puint->minimum, puint->maximum,  /* range */
207             puint->default_value);      /* default */
208         break;
209       }
210
211       case G_TYPE_INT:         //  Integer
212       {
213         GParamSpecInt *pint = G_PARAM_SPEC_INT (param);
214         if (readable)           /* current */
215           g_print ("%-*d", c3w, g_value_get_int (&value));
216         else
217           g_print ("%-*s", c3w, "<not readable>");
218         g_print (" | %-*s", c4w, "G_TYPE_INT"); /* type */
219         g_print (" | (%d - %d)   %d ", pint->minimum, pint->maximum,    /* range */
220             pint->default_value);       /* default */
221         break;
222       }
223
224       case G_TYPE_UINT64:      //  Unsigned Integer64.
225       {
226         GParamSpecUInt64 *puint64 = G_PARAM_SPEC_UINT64 (param);
227         if (readable)           /* current */
228           g_print ("%-*" G_GUINT64_FORMAT, c3w, g_value_get_uint64 (&value));
229         else
230           g_print ("%-*s", c3w, "<not readable>");
231         g_print (" | %-*s", c4w, "G_TYPE_UINT64");      /* type */
232         g_print (" | (%" G_GUINT64_FORMAT " - %" G_GUINT64_FORMAT ")" "   %" G_GUINT64_FORMAT " ", puint64->minimum, puint64->maximum,  /* range */
233             puint64->default_value);    /* default */
234         break;
235       }
236
237       case G_TYPE_INT64:       // Integer64
238       {
239         GParamSpecInt64 *pint64 = G_PARAM_SPEC_INT64 (param);
240         if (readable)           /* current */
241           g_print ("%-*" G_GINT64_FORMAT, c3w, g_value_get_int64 (&value));
242         else
243           g_print ("%-*s", c3w, "<not readable>");
244         g_print (" | %-*s", c4w, "G_TYPE_INT64");       /* type */
245         g_print (" | (%" G_GINT64_FORMAT " - %" G_GINT64_FORMAT ")" "   %" G_GINT64_FORMAT " ", pint64->minimum, pint64->maximum,       /* range */
246             pint64->default_value);     /* default */
247         break;
248       }
249
250       case G_TYPE_FLOAT:       //  Float.
251       {
252         GParamSpecFloat *pfloat = G_PARAM_SPEC_FLOAT (param);
253         if (readable)           /* current */
254           g_print ("%-*g", c3w, g_value_get_float (&value));
255         else
256           g_print ("%-*s", c3w, "<not readable>");
257         g_print (" | %-*s", c4w, "G_TYPE_FLOAT");       /* type */
258         g_print (" | (%g - %g)   %g ", pfloat->minimum, pfloat->maximum,        /* range */
259             pfloat->default_value);     /* default */
260         break;
261       }
262
263       case G_TYPE_DOUBLE:      //  Double
264       {
265         GParamSpecDouble *pdouble = G_PARAM_SPEC_DOUBLE (param);
266         if (readable)           /* current */
267           g_print ("%-*g", c3w, g_value_get_double (&value));
268         else
269           g_print ("%-*s", c3w, "<not readable>");
270         g_print (" | %-*s", c4w, "G_TYPE_DOUBLE");      /* type */
271         g_print (" | (%g - %g)   %g ", pdouble->minimum, pdouble->maximum,      /* range */
272             pdouble->default_value);    /* default */
273         break;
274       }
275
276       default:
277         if (param->value_type == GST_TYPE_CAPS) {
278           const GstCaps *caps = gst_value_get_caps (&value);
279           if (!caps)
280             g_print ("%-*s | %-*.*s |", c3w, "Caps (NULL)", c4w, c4w, " ");
281           else {
282             gchar prefix_string[100];
283             sprintf (prefix_string, "    | %-*.*s | ", c2w, c2w, " ");
284             print_caps (caps, prefix_string);
285           }
286         }
287
288         else if (G_IS_PARAM_SPEC_ENUM (param)) {
289           GParamSpecEnum *penum = G_PARAM_SPEC_ENUM (param);
290           GEnumValue *values;
291           guint j = 0;
292           gint enum_value;
293           const gchar *def_val_nick = "", *cur_val_nick = "";
294           gchar work_string[100];
295
296           values = G_ENUM_CLASS (g_type_class_ref (param->value_type))->values;
297           enum_value = g_value_get_enum (&value);
298
299           while (values[j].value_name) {
300             if (values[j].value == enum_value)
301               cur_val_nick = values[j].value_nick;
302             if (values[j].value == penum->default_value)
303               def_val_nick = values[j].value_nick;
304             j++;
305           }
306
307           sprintf (work_string, "%d, \"%s\"", enum_value, cur_val_nick);
308           g_print ("%-*.*s", c3w, c3w, work_string);
309           g_print (" | Enum \"%s\" : %d, \"%s\"",
310               g_type_name (G_VALUE_TYPE (&value)),
311               penum->default_value, def_val_nick);
312         }
313
314         else if (G_IS_PARAM_SPEC_FLAGS (param)) {
315           GParamSpecFlags *pflags = G_PARAM_SPEC_FLAGS (param);
316           GFlagsValue *vals;
317           gchar *cur, *def;
318           gchar work_string[100];
319
320           vals = pflags->flags_class->values;
321           cur = flags_to_string (vals, g_value_get_flags (&value));     /* current */
322           def = flags_to_string (vals, pflags->default_value);  /* default */
323
324           /* current */
325           sprintf (work_string, "0x%08x, \"%s\"",
326               g_value_get_flags (&value), cur);
327           g_print ("%-*.*s", c3w, c3w, work_string);
328
329           /* type */
330           sprintf (work_string, "Flags \"%s\"",
331               g_type_name (G_VALUE_TYPE (&value)));
332           g_print ("%-*.*s", c4w, c4w, work_string);
333
334           /* default */
335           g_print (" | 0x%08x, \"%s\"", pflags->default_value, def);
336
337           /* values list */
338           while (vals[0].value_name) {
339             sprintf (work_string, "\n    | %-*.*s |   (0x%08x): %-16s - %s",
340                 c2w, c2w, "",
341                 vals[0].value, vals[0].value_nick, vals[0].value_name);
342             g_print ("%s", work_string);
343             ++vals;
344           }
345
346           g_free (cur);
347           g_free (def);
348         }
349
350         else if (G_IS_PARAM_SPEC_OBJECT (param)) {
351           g_print ("%-*.*s | Object of type \"%s\"",
352               c3w, c3w,
353               g_type_name (param->value_type), g_type_name (param->value_type));
354         }
355
356         else if (G_IS_PARAM_SPEC_BOXED (param)) {
357           g_print ("%-*.*s | Boxed pointer of type \"%s\"",
358               c3w, c3w,
359               g_type_name (param->value_type), g_type_name (param->value_type));
360         }
361
362         else if (G_IS_PARAM_SPEC_POINTER (param)) {
363           if (param->value_type != G_TYPE_POINTER) {
364             g_print ("%-*.*s | Pointer of type \"%s\"",
365                 c3w, c3w,
366                 g_type_name (param->value_type),
367                 g_type_name (param->value_type));
368           } else {
369             g_print ("%-*.*s |", c3w, c3w, "Pointer.");
370           }
371         }
372
373         else if (param->value_type == G_TYPE_VALUE_ARRAY) {
374           GParamSpecValueArray *pvarray = G_PARAM_SPEC_VALUE_ARRAY (param);
375           if (pvarray->element_spec) {
376             g_print ("%-*.*s :Array of GValues of type \"%s\"",
377                 c3w, c3w,
378                 g_type_name (pvarray->element_spec->value_type),
379                 g_type_name (pvarray->element_spec->value_type));
380           } else {
381             g_print ("%-*.*s :", c3w, c3w, "Array of GValues");
382           }
383         }
384
385         else if (GST_IS_PARAM_SPEC_FRACTION (param)) {
386           GstParamSpecFraction *pfraction = GST_PARAM_SPEC_FRACTION (param);
387           gchar work_string[100];
388
389           if (readable) {       /* current */
390             sprintf (work_string, "%d/%d",
391                 gst_value_get_fraction_numerator (&value),
392                 gst_value_get_fraction_denominator (&value));
393             g_print ("%-*.*s", c3w, c3w, work_string);
394           } else
395             g_print ("%-*s", c3w, "<not readable>");
396
397           g_print (" | %-*.*s", /* type */
398               c3w, c3w, " Fraction. ");
399           g_print (" | (%d/%d - %d/%d)",        /* range */
400               pfraction->min_num, pfraction->min_den,
401               pfraction->max_num, pfraction->max_den);
402           g_print ("   %d/%d ", /* default */
403               pfraction->def_num, pfraction->def_den);
404         }
405
406         else if (GST_IS_PARAM_SPEC_MINI_OBJECT (param)) {
407           g_print ("%-*.*s | MiniObject of type \"%s\"",
408               c3w, c3w,
409               g_type_name (param->value_type), g_type_name (param->value_type));
410         }
411
412         else {
413           g_print ("Unknown type %ld \"%s\"",
414               (glong) param->value_type, g_type_name (param->value_type));
415
416         }
417         break;
418     }
419
420     if (!readable)
421       g_print (" Write only\n");
422     else
423       g_print ("\n");
424
425     g_value_reset (&value);
426   }
427
428   if (0 == num_properties)
429     g_print ("  none\n");
430
431   g_free (property_specs);
432 }
433
434 //------------------------------------------------------------------------------
435 void
436 print_column_titles (guint c2w, guint c3w, guint c4w)
437 {
438   //////////////////////////////////////////////////////////////////////////
439   //
440   // Create Header for property listing
441   // RWF | --- element name ---- | ---------c3-------- | -----------c4---------- | --> unspecified
442   //
443   //////////////////////////////////////////////////////////////////////////
444   gchar work_string[200];
445   gchar dashes[] = "-----------------------------";
446   gint llen = 0;
447   gint rlen = 0;
448
449       /*--- column 1 - RWC ---*/
450   sprintf (work_string, "<-->|<");
451
452       /*--- column 2 - property name ---*/
453   llen = (c2w - 15) / 2;        /* width of " property name " = 15 */
454   rlen = c2w - 15 - llen;
455
456   strncat (work_string, dashes, llen);
457   strcat (work_string, " property name ");
458   strncat (work_string, dashes, rlen);
459   strcat (work_string, ">|<");
460
461       /*--- column 3 - current value ---*/
462   llen = (c3w - 15) / 2;        /* width of " current value " = 15 */
463   rlen = c3w - 15 - llen;
464
465   strncat (work_string, dashes, llen);
466   strcat (work_string, " current value ");
467   strncat (work_string, dashes, rlen);
468   strcat (work_string, ">|<");
469
470       /*--- column 4 - type ---*/
471   llen = (c4w - 6) / 2;         /* width of " type " = 6 */
472   rlen = c4w - 6 - llen;
473
474   strncat (work_string, dashes, llen);
475   strcat (work_string, " type ");
476   strncat (work_string, dashes, rlen);
477   strcat (work_string, ">|<");
478
479       /*--- column 5 - range and default ---*/
480   strcat (work_string, "----- range and default ----->");
481
482   g_print ("\n%s\n", work_string);
483 }
484
485 //------------------------------------------------------------------------------
486 void
487 print_element_info (GstElement * element, guint c2w, guint c3w, guint c4w)
488 {
489   /////////////////////////////////////////////////////////////////////////////
490   //
491   // Print element factory and class information as part of each header
492   //
493   /////////////////////////////////////////////////////////////////////////////
494   gchar work_string[100];
495   GstElementFactory *factory = gst_element_get_factory (element);
496
497   sprintf (work_string, "ELEMENT CLASS NAME");
498   g_print ("    | %-*s", c2w, work_string);
499   g_print (" | %-*s", c3w, g_type_name (G_OBJECT_TYPE (element)));
500   g_print (" | %-*s | \n", c4w, "");
501
502
503   sprintf (work_string, "ELEMENT FACTORY NAME");
504   g_print ("    | %-*s", c2w, work_string);
505
506   g_print (" | %-*s", c3w,
507       gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
508   g_print (" | %-*s | \n", c4w, gst_element_factory_get_longname (factory));
509
510 // "Audio Resampler"   g_print( " | %-*s",      c3w, gst_element_factory_get_longname( gst_element_get_factory( element )) );
511
512
513 }
514
515 //------------------------------------------------------------------------------
516 gchar *
517 flags_to_string (GFlagsValue * vals, guint flags)
518 {
519   /////////////////////////////////////////////////////////////////////////////
520   //
521   // List individual flags in separate rows
522   //
523   /////////////////////////////////////////////////////////////////////////////
524   GString *s = NULL;
525   guint flags_left, i;
526
527   /* first look for an exact match and count the number of values */
528   for (i = 0; vals[i].value_name != NULL; ++i) {
529     if (vals[i].value == flags)
530       return g_strdup (vals[i].value_nick);
531   }
532
533   s = g_string_new (NULL);
534
535   /* we assume the values are sorted from lowest to highest value */
536   flags_left = flags;
537   while (i > 0) {
538     --i;
539     if (0 != vals[i].value && (flags_left & vals[i].value) == vals[i].value) {
540       if (0 < s->len)
541         g_string_append (s, " | ");
542       g_string_append (s, vals[i].value_nick);
543       flags_left -= vals[i].value;
544       if (0 == flags_left)
545         break;
546     }
547   }
548
549   if (0 == s->len)
550     g_string_assign (s, "(none)");
551
552   return g_string_free (s, FALSE);
553 }
554
555
556 //------------------------------------------------------------------------------
557 void
558 print_caps (const GstCaps * caps, const gchar * pfx)
559 {
560   /////////////////////////////////////////////////////////////////////////////
561   //
562   // Print each caps value on a separate line
563   //
564   /////////////////////////////////////////////////////////////////////////////
565   guint i;
566
567   g_return_if_fail (caps != NULL);
568
569   if (gst_caps_is_any (caps)) {
570     g_print ("%s | %s", pfx, "ANY                 |                     |");
571     return;
572   }
573   if (gst_caps_is_empty (caps)) {
574     g_print ("%s | %s", pfx, "EMPTY               |                     |");
575     return;
576   }
577
578   for (i = 0; i < gst_caps_get_size (caps); i++) {
579     GstStructure *structure = gst_caps_get_structure (caps, i);
580     g_print ("%s", gst_structure_get_name (structure));
581     gst_structure_foreach (structure, print_field, (gpointer) pfx);
582   }
583 }
584
585 //------------------------------------------------------------------------------
586 gboolean
587 print_field (GQuark field, const GValue * value, gpointer pfx)
588 {
589   /////////////////////////////////////////////////////////////////////////////
590   //
591   // printing function for individual caps fields
592   //
593   /////////////////////////////////////////////////////////////////////////////
594   gchar *str = gst_value_serialize (value);
595   g_print ("\n%s  %-15.15s - %s",
596       (gchar *) pfx, g_quark_to_string (field), str);
597   g_free (str);
598   return TRUE;
599 }