Show signals/actions of parent classes
[platform/upstream/gstreamer.git] / tools / gst-inspect.c
1 #ifdef HAVE_CONFIG_H
2 #  include "config.h"
3 #endif
4
5 #include <gst/gst.h>
6 #include <gst/control/control.h>
7 #include <string.h>
8
9 static void
10 print_prop (GstPropsEntry *prop, gboolean showname, const gchar *pfx)
11 {
12   GstPropsType type;
13
14   if (showname)
15     g_print("%s%-20.20s: ", pfx, gst_props_entry_get_name (prop));
16   else
17     g_print(pfx);
18
19   type = gst_props_entry_get_props_type (prop);
20
21   switch (type) {
22     case GST_PROPS_INT_TYPE:
23     {
24       gint val;
25       gst_props_entry_get_int (prop, &val);
26       g_print("Integer: %d\n", val);
27       break;
28     }
29     case GST_PROPS_INT_RANGE_TYPE:
30     {
31       gint min, max;
32       gst_props_entry_get_int_range (prop, &min, &max);
33       g_print("Integer range: %d - %d\n", min, max);
34       break;
35     }
36     case GST_PROPS_FLOAT_TYPE:
37     {
38       gfloat val;
39       gst_props_entry_get_float (prop, &val);
40       g_print("Float: %g\n", val);
41       break;
42     }
43     case GST_PROPS_FLOAT_RANGE_TYPE:
44     {
45       gfloat min, max;
46       gst_props_entry_get_float_range (prop, &min, &max);
47       g_print("Float range: %g - %g\n", min, max);
48       break;
49     }
50     case GST_PROPS_BOOLEAN_TYPE:
51     {
52       gboolean val;
53       gst_props_entry_get_boolean (prop, &val);
54       g_print("Boolean: %s\n", val ? "TRUE" : "FALSE");
55       break;
56     }
57     case GST_PROPS_STRING_TYPE:
58     {
59       const gchar *val;
60       gst_props_entry_get_string (prop, &val);
61       g_print("String: \"%s\"\n", val);
62       break;
63     }
64     case GST_PROPS_FOURCC_TYPE:
65     {
66       guint32 val;
67       gst_props_entry_get_fourcc_int (prop, &val);
68       g_print("FourCC: '%c%c%c%c'\n",
69              (gchar)( val        & 0xff),
70              (gchar)((val >> 8)  & 0xff),
71              (gchar)((val >> 16) & 0xff),
72              (gchar)((val >> 24) & 0xff));
73       break;
74     }
75     case GST_PROPS_LIST_TYPE:
76     {
77       const GList *list;
78       gchar *longprefix;
79
80       gst_props_entry_get_list (prop, &list);
81       g_print ("List:\n");
82       longprefix = g_strdup_printf ("%s ", pfx);
83       while (list) {
84         GstPropsEntry *listentry;
85
86         listentry = (GstPropsEntry*) (list->data);
87         print_prop (listentry, FALSE, longprefix);
88
89         list = g_list_next (list);
90       }
91       g_free (longprefix);
92       break;
93     }
94     default:
95       g_print("unknown props %d\n", type);
96   }
97 }
98
99 static void
100 print_props (GstProps *properties, const gchar *pfx)
101 {
102   GList *props;
103   GstPropsEntry *prop;
104
105   props = properties->properties;
106   while (props) {
107     prop = (GstPropsEntry*)(props->data);
108     props = g_list_next(props);
109
110     print_prop(prop,TRUE,pfx);
111   }
112 }
113
114 static void
115 print_caps (const GstCaps *caps, const gchar *pfx)
116 {
117   while (caps) {
118     GstType *type;
119
120     g_print ("%s'%s': (%sfixed)\n", pfx, caps->name, (GST_CAPS_IS_FIXED (caps) ? "" : "NOT "));
121
122     type = gst_type_find_by_id (caps->id);
123     if (type)
124       g_print ("%s  MIME type: '%s':\n", pfx, type->mime);
125     else
126       g_print ("%s  MIME type: 'unknown/unknown':\n", pfx);
127
128     if (caps->properties) {
129       gchar *prefix = g_strdup_printf ("%s  ", pfx);
130
131       print_props(caps->properties, prefix);
132
133       g_free (prefix);
134     }
135
136     caps = caps->next;
137   }
138 }
139
140 static void
141 print_formats (const GstFormat *formats)
142 {
143   while (formats && *formats) {
144     const GstFormatDefinition *definition;
145
146     definition = gst_format_get_details (*formats);
147     if (definition)
148       g_print ("\t\t(%d):\t%s (%s)\n", *formats,
149                definition->nick, definition->description);
150     else
151       g_print ("\t\t(%d):\tUnknown format\n", *formats);
152
153     formats++;
154   }
155 }
156
157 static void
158 print_query_types (const GstQueryType *types)
159 {
160   while (types && *types) {
161     const GstQueryTypeDefinition *definition;
162
163     definition = gst_query_type_get_details (*types);
164     if (definition)
165       g_print ("\t\t(%d):\t%s (%s)\n", *types,
166                definition->nick, definition->description);
167     else
168       g_print ("\t\t(%d):\tUnknown query format\n", *types);
169
170     types++;
171   }
172 }
173
174 static void
175 print_event_masks (const GstEventMask *masks)
176 {
177 #ifndef GST_DISABLE_ENUMTYPES
178   GType event_type;
179   GEnumClass *klass;
180   GType event_flags;
181   GFlagsClass *flags_class = NULL;
182
183   event_type = gst_event_type_get_type();
184   klass = (GEnumClass *) g_type_class_ref (event_type);
185
186   while (masks && masks->type) {
187     GEnumValue *value;
188     gint flags = 0, index = 0;
189
190     switch (masks->type) {
191       case GST_EVENT_SEEK:
192         flags = masks->flags;
193         event_flags = gst_seek_type_get_type ();
194         flags_class = (GFlagsClass *) g_type_class_ref (event_flags);
195         break;
196       default:
197         break;
198     }
199
200     value = g_enum_get_value (klass, masks->type);
201     g_print ("\t\t%s ", value->value_nick);
202
203     while (flags) {
204       GFlagsValue *value;
205
206       if (flags & 1) {
207         value = g_flags_get_first_value (flags_class, 1 << index);
208
209         if (value)
210           g_print ("| %s ", value->value_nick);
211         else
212           g_print ("| ? ");
213       }
214       flags >>= 1;
215       index++;
216     }
217     g_print ("\n");
218
219     masks++;
220   }
221 #endif
222 }
223
224 static void
225 output_hierarchy (GType type, gint level, gint *maxlevel)
226 {
227   GType parent;
228   gint i;
229
230   parent = g_type_parent (type);
231
232   *maxlevel = *maxlevel + 1;
233   level++;
234
235   if (parent)
236     output_hierarchy (parent, level, maxlevel);
237
238   for (i=1; i<*maxlevel-level; i++)
239    g_print ("      ");
240   if (*maxlevel-level)
241     g_print (" +----");
242
243   g_print ("%s\n", g_type_name (type));
244
245   if (level == 1)
246     g_print ("\n");
247 }
248
249 static void
250 print_element_properties (GstElement *element)
251 {
252   GParamSpec **property_specs;
253   gint num_properties,i;
254   gboolean readable;
255   const char *string_val;
256
257   property_specs = g_object_class_list_properties
258                      (G_OBJECT_GET_CLASS (element), &num_properties);
259   g_print("\nElement Arguments:\n");
260
261   for (i = 0; i < num_properties; i++) {
262     GValue value = { 0, };
263     GParamSpec *param = property_specs[i];
264     readable = FALSE;
265
266     g_value_init (&value, param->value_type);
267     if (param->flags & G_PARAM_READABLE) {
268       g_object_get_property (G_OBJECT (element), param->name, &value);
269       readable = TRUE;
270     }
271
272     g_print("  %-20s: %s\n", g_param_spec_get_name (param),
273                                g_param_spec_get_blurb (param));
274
275     switch (G_VALUE_TYPE (&value)) {
276       case G_TYPE_STRING:
277         string_val = g_value_get_string (&value);
278         g_print ("%-23.23s String. ", "");
279         if (readable) {
280           if (string_val == NULL)
281             g_print ("(Default \"\")");
282           else
283             g_print ("(Default \"%s\")", g_value_get_string (&value));
284         }
285         break;
286       case G_TYPE_BOOLEAN:
287         g_print ("%-23.23s Boolean. ", "");
288         if (readable) g_print ("(Default %s)", (g_value_get_boolean (&value) ? "true" : "false"));
289         break;
290       case G_TYPE_ULONG:
291       {
292         GParamSpecULong *pulong = G_PARAM_SPEC_ULONG (param);
293         g_print("%-23.23s Unsigned Long. ", "");
294         if (readable) g_print("Range: %lu - %lu (Default %lu)",
295                         pulong->minimum, pulong->maximum, g_value_get_ulong (&value));
296         break;
297       }
298       case G_TYPE_LONG:
299       {
300         GParamSpecLong *plong = G_PARAM_SPEC_LONG (param);
301         g_print("%-23.23s Long. ", "");
302         if (readable) g_print("Range: %ld - %ld (Default %ld)",
303                         plong->minimum, plong->maximum, g_value_get_long (&value));
304         break;
305       }
306       case G_TYPE_UINT:
307       {
308         GParamSpecUInt *puint = G_PARAM_SPEC_UINT (param);
309         g_print("%-23.23s Unsigned Integer. ", "");
310         if (readable) g_print("Range: %u - %u (Default %u)",
311                         puint->minimum, puint->maximum, g_value_get_uint (&value));
312         break;
313       }
314       case G_TYPE_INT:
315       {
316         GParamSpecInt *pint = G_PARAM_SPEC_INT (param);
317         g_print("%-23.23s Integer. ", "");
318         if (readable) g_print("Range: %d - %d (Default %d)",
319                         pint->minimum, pint->maximum, g_value_get_int (&value));
320         break;
321       }
322       case G_TYPE_UINT64:
323       {
324         GParamSpecUInt64 *puint64 = G_PARAM_SPEC_UINT64 (param);
325         g_print("%-23.23s Unsigned Integer64. ", "");
326         if (readable) g_print("Range: %" G_GUINT64_FORMAT " - %"
327                         G_GUINT64_FORMAT " (Default %" G_GUINT64_FORMAT ")",
328                         puint64->minimum, puint64->maximum,
329                         g_value_get_uint64 (&value));
330         break;
331       }
332       case G_TYPE_INT64:
333       {
334         GParamSpecInt64 *pint64 = G_PARAM_SPEC_INT64 (param);
335         g_print("%-23.23s Integer64. ", "");
336         if (readable) g_print("Range: %" G_GINT64_FORMAT " - %" G_GINT64_FORMAT                         " (Default %" G_GINT64_FORMAT ")", pint64->minimum,
337                         pint64->maximum, g_value_get_int64 (&value));
338         break;
339       }
340       case G_TYPE_FLOAT:
341       {
342         GParamSpecFloat *pfloat = G_PARAM_SPEC_FLOAT (param);
343         g_print("%-23.23s Float. Default: %-8.8s %15.7g\n", "", "",
344                 g_value_get_float (&value));
345         g_print("%-23.23s Range: %15.7g - %15.7g", "",
346                pfloat->minimum, pfloat->maximum);
347         break;
348       }
349       case G_TYPE_DOUBLE:
350       {
351         GParamSpecDouble *pdouble = G_PARAM_SPEC_DOUBLE (param);
352         g_print("%-23.23s Double. Default: %-8.8s %15.7g\n", "", "",
353                 g_value_get_double (&value));
354         g_print("%-23.23s Range: %15.7g - %15.7g", "",
355                pdouble->minimum, pdouble->maximum);
356         break;
357       }
358       default:
359         if (param->value_type == GST_TYPE_URI) {
360           g_print("%-23.23s URI", "");
361         }
362         if (param->value_type == GST_TYPE_CAPS) {
363           GstCaps *caps = g_value_peek_pointer (&value);
364
365           if (!caps)
366             g_print("%-23.23s Caps (NULL)", "");
367           else {
368             print_caps (caps, "                           ");
369           }
370         }
371         else if (G_IS_PARAM_SPEC_ENUM (param)) {
372           GEnumValue *values;
373           guint j = 0;
374           gint enum_value;
375
376           values = G_ENUM_CLASS (g_type_class_ref (param->value_type))->values;
377           enum_value = g_value_get_enum (&value);
378
379           while (values[j].value_name) {
380             if (values[j].value == enum_value)
381               break;
382             j++; 
383           }
384
385           g_print ("%-23.23s Enum \"%s\" (default %d, \"%s\")", "",
386                         g_type_name (G_VALUE_TYPE (&value)),
387                         enum_value, values[j].value_nick);
388
389           j = 0;
390           while (values[j].value_name) {
391             g_print("\n%-23.23s    (%d): \t%s", "",
392                         values[j].value, values[j].value_nick);
393             j++;
394           }
395           /* g_type_class_unref (ec); */
396         }
397         else if (G_IS_PARAM_SPEC_FLAGS (param)) {
398           GFlagsValue *values;
399           guint j = 0;
400           gint flags_value;
401           GString *flags = NULL;
402
403           values = G_FLAGS_CLASS (g_type_class_ref (param->value_type))->values;
404           flags_value = g_value_get_flags (&value);
405
406           while (values[j].value_name) {
407             if (values[j].value & flags_value) {
408               if (flags) {
409                 g_string_append_printf (flags, " | %s", values[j].value_nick);
410               }
411               else {
412                 flags = g_string_new (values[j].value_nick);
413               }
414             }
415             j++;
416           }
417
418           g_print("%-23.23s Flags \"%s\" (default %d, \"%s\")", "",
419                       g_type_name (G_VALUE_TYPE (&value)),
420                       flags_value, (flags ? flags->str : "(none)"));
421
422           j = 0;
423           while (values[j].value_name) {
424             g_print("\n%-23.23s    (%d): \t%s", "",
425                       values[j].value, values[j].value_nick);
426             j++;
427           }
428
429           if (flags)
430             g_string_free (flags, TRUE);
431         }
432         else if (G_IS_PARAM_SPEC_OBJECT (param)) {
433           g_print("%-23.23s Object of type \"%s\"", "",
434                       g_type_name(param->value_type));
435         }
436         else {
437           g_print ("%-23.23s Unknown type %ld \"%s\"", "", param->value_type,
438                       g_type_name(param->value_type));
439         }
440         break;
441     }
442     if (!readable)
443       g_print (" Write only\n");
444     else
445       g_print ("\n");
446   }
447   if (num_properties == 0)
448     g_print ("  none\n");
449 }
450
451 static gint
452 print_element_info (GstElementFactory *factory)
453 {
454   GstElement *element;
455   GstObjectClass *gstobject_class;
456   GstElementClass *gstelement_class;
457   GList *pads;
458   GstPad *pad;
459   GstRealPad *realpad;
460   GstPadTemplate *padtemplate;
461   GList *children;
462   GstElement *child;
463   gboolean have_flags;
464   gint maxlevel = 0;
465
466   element = gst_element_factory_create (factory, "element");
467   if (!element) {
468     g_print ("couldn't construct element for some reason\n");
469     return -1;
470   }
471
472   gstobject_class = GST_OBJECT_CLASS (G_OBJECT_GET_CLASS (element));
473   gstelement_class = GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element));
474
475   g_print ("Factory Details:\n");
476   g_print ("  Long name:\t%s\n",   factory->details->longname);
477   g_print ("  Class:\t%s\n",       factory->details->klass);
478   g_print ("  License:\t%s\n",     factory->details->license);
479   g_print ("  Description:\t%s\n", factory->details->description);
480   g_print ("  Version:\t%s\n",     factory->details->version);
481   g_print ("  Author(s):\t%s\n",   factory->details->author);
482   g_print ("  Copyright:\t%s\n",   factory->details->copyright);
483   g_print ("\n");
484
485   output_hierarchy (G_OBJECT_TYPE (element), 0, &maxlevel);
486
487   g_print ("Pad Templates:\n");
488   if (factory->numpadtemplates) {
489     pads = factory->padtemplates;
490     while (pads) {
491       padtemplate = (GstPadTemplate*)(pads->data);
492       pads = g_list_next(pads);
493
494       if (padtemplate->direction == GST_PAD_SRC)
495         g_print ("  SRC template: '%s'\n", padtemplate->name_template);
496       else if (padtemplate->direction == GST_PAD_SINK)
497         g_print ("  SINK template: '%s'\n", padtemplate->name_template);
498       else
499         g_print ("  UNKNOWN!!! template: '%s'\n", padtemplate->name_template);
500
501       if (padtemplate->presence == GST_PAD_ALWAYS)
502         g_print ("    Availability: Always\n");
503       else if (padtemplate->presence == GST_PAD_SOMETIMES)
504         g_print ("    Availability: Sometimes\n");
505       else if (padtemplate->presence == GST_PAD_REQUEST) {
506         g_print ("    Availability: On request\n");
507         g_print ("      Has request_new_pad() function: %s\n",
508                 GST_DEBUG_FUNCPTR_NAME (gstelement_class->request_new_pad));
509       }
510       else
511         g_print ("    Availability: UNKNOWN!!!\n");
512
513       if (padtemplate->caps) {
514         g_print ("    Capabilities:\n");
515         print_caps (padtemplate->caps, "      ");
516       }
517
518       g_print ("\n");
519     }
520   } else
521     g_print ("  none\n");
522
523   have_flags = FALSE;
524
525   g_print ("\nElement Flags:\n");
526   if (GST_FLAG_IS_SET (element, GST_ELEMENT_COMPLEX)) {
527     g_print ("  GST_ELEMENT_COMPLEX\n");
528     have_flags = TRUE;
529   }
530   if (GST_FLAG_IS_SET (element, GST_ELEMENT_DECOUPLED)) {
531     g_print ("  GST_ELEMENT_DECOUPLED\n");
532     have_flags = TRUE;
533   }
534   if (GST_FLAG_IS_SET (element, GST_ELEMENT_THREAD_SUGGESTED)) {
535     g_print ("  GST_ELEMENT_THREADSUGGESTED\n");
536     have_flags = TRUE;
537   }
538   if (GST_FLAG_IS_SET (element, GST_ELEMENT_EVENT_AWARE)) {
539     g_print("  GST_ELEMENT_EVENT_AWARE\n");
540     have_flags = TRUE;
541   }
542   if (!have_flags)
543     g_print("  no flags set\n");
544
545   if (GST_IS_BIN (element)) {
546     g_print ("\nBin Flags:\n");
547     if (GST_FLAG_IS_SET (element, GST_BIN_FLAG_MANAGER)) {
548       g_print ("  GST_BIN_FLAG_MANAGER\n");
549       have_flags = TRUE;
550     }
551     if (GST_FLAG_IS_SET (element, GST_BIN_SELF_SCHEDULABLE)) {
552       g_print ("  GST_BIN_SELF_SCHEDULABLE\n");
553       have_flags = TRUE;
554     }
555     if (GST_FLAG_IS_SET (element, GST_BIN_FLAG_PREFER_COTHREADS)) {
556       g_print ("  GST_BIN_FLAG_PREFER_COTHREADS\n");
557       have_flags = TRUE;
558     }
559     if (!have_flags)
560       g_print ("  no flags set\n");
561   }
562
563
564
565   g_print ("\nElement Implementation:\n");
566
567   if (element->loopfunc)
568     g_print ("  loopfunc()-based element: %s\n",
569             GST_DEBUG_FUNCPTR_NAME (element->loopfunc));
570   else
571     g_print ("  No loopfunc(), must be chain-based or not configured yet\n");
572
573   g_print ("  Has change_state() function: %s\n",
574           GST_DEBUG_FUNCPTR_NAME (gstelement_class->change_state));
575 #ifndef GST_DISABLE_LOADSAVE
576   g_print ("  Has custom save_thyself() function: %s\n",
577           GST_DEBUG_FUNCPTR_NAME (gstobject_class->save_thyself));
578   g_print ("  Has custom restore_thyself() function: %s\n",
579           GST_DEBUG_FUNCPTR_NAME (gstobject_class->restore_thyself));
580 #endif
581
582   have_flags = FALSE;
583
584   g_print ("\nClocking Interaction:\n");
585   if (gst_element_requires_clock (element)) {
586     g_print ("  element requires a clock\n");
587     have_flags = TRUE;
588   }
589   if (gst_element_provides_clock (element)) {
590     GstClock *clock;
591
592     clock = gst_element_get_clock (element);
593     if (clock)
594       g_print ("  element provides a clock: %s\n", GST_OBJECT_NAME(clock));
595     else
596       g_print ("  element is supposed to provide a clock but returned NULL\n");
597     have_flags = TRUE;
598   }
599   if (!have_flags) {
600     g_print ("  none\n");
601   }
602
603 #ifndef GST_DISABLE_INDEX
604   g_print ("\nIndexing capabilities:\n");
605   if (gst_element_is_indexable (element)) {
606     g_print ("  element can do indexing\n");
607   }
608   else {
609     g_print ("  none\n");
610   }
611 #endif
612
613   g_print ("\nPads:\n");
614   if (element->numpads) {
615     const GList *pads;
616     pads = gst_element_get_pad_list (element);
617     while (pads) {
618       pad = GST_PAD (pads->data);
619       pads = g_list_next (pads);
620       realpad = GST_PAD_REALIZE (pad);
621
622       if (gst_pad_get_direction (pad) == GST_PAD_SRC)
623         g_print ("  SRC: '%s'", gst_pad_get_name (pad));
624       else if (gst_pad_get_direction (pad) == GST_PAD_SINK)
625         g_print ("  SINK: '%s'", gst_pad_get_name (pad));
626       else
627         g_print ("  UNKNOWN!!!: '%s'\n", gst_pad_get_name (pad));
628
629       if (GST_IS_GHOST_PAD (pad))
630         g_print (", ghost of real pad %s:%s\n", GST_DEBUG_PAD_NAME (realpad));
631       else
632         g_print ("\n");
633
634       g_print ("    Implementation:\n");
635       if (realpad->chainfunc)
636         g_print ("      Has chainfunc(): %s\n",
637                 GST_DEBUG_FUNCPTR_NAME (realpad->chainfunc));
638       if (realpad->getfunc)
639         g_print ("      Has getfunc(): %s\n",
640                 GST_DEBUG_FUNCPTR_NAME (realpad->getfunc));
641       if (realpad->formatsfunc != gst_pad_get_formats_default) {
642         g_print ("      Supports seeking/conversion/query formats:\n");
643         print_formats (gst_pad_get_formats (GST_PAD (realpad)));
644       }
645       if (realpad->convertfunc != gst_pad_convert_default)
646         g_print ("      Has custom convertfunc(): %s\n",
647                 GST_DEBUG_FUNCPTR_NAME (realpad->convertfunc));
648       if (realpad->eventfunc != gst_pad_event_default)
649         g_print ("      Has custom eventfunc(): %s\n",
650                 GST_DEBUG_FUNCPTR_NAME (realpad->eventfunc));
651       if (realpad->eventmaskfunc != gst_pad_get_event_masks_default) {
652         g_print ("        Provides event masks:\n");
653         print_event_masks (gst_pad_get_event_masks (GST_PAD (realpad)));
654       }
655       if (realpad->queryfunc != gst_pad_query_default)
656         g_print ("      Has custom queryfunc(): %s\n",
657                 GST_DEBUG_FUNCPTR_NAME (realpad->queryfunc));
658       if (realpad->querytypefunc != gst_pad_get_query_types_default) {
659         g_print ("        Provides query types:\n");
660         print_query_types (gst_pad_get_query_types (GST_PAD (realpad)));
661       }
662
663       if (realpad->intlinkfunc != gst_pad_get_internal_links_default)
664         g_print ("      Has custom intconnfunc(): %s\n",
665                 GST_DEBUG_FUNCPTR_NAME(realpad->intlinkfunc));
666
667       if (realpad->bufferpoolfunc)
668         g_print ("      Has bufferpoolfunc(): %s\n",
669                 GST_DEBUG_FUNCPTR_NAME(realpad->bufferpoolfunc));
670
671       if (pad->padtemplate)
672         g_print ("    Pad Template: '%s'\n",
673                 pad->padtemplate->name_template);
674
675       if (realpad->caps) {
676         g_print ("    Capabilities:\n");
677         print_caps (realpad->caps, "      ");
678       }
679     }
680   } else
681     g_print ("  none\n");
682
683   print_element_properties (element);
684
685   /* Dynamic Parameters block */
686   {
687     GstDParamManager* dpman;
688     GParamSpec** specs;
689     gint x;
690
691     g_print ("\nDynamic Parameters:\n");
692     if((dpman = gst_dpman_get_manager (element))) {
693       specs = gst_dpman_list_dparam_specs (dpman);
694       for (x = 0; specs[x] != NULL; x++) {
695         g_print ("  %-20.20s: ", g_param_spec_get_name (specs[x]));
696
697         switch (G_PARAM_SPEC_VALUE_TYPE (specs[x])) {
698           case G_TYPE_INT64:
699             g_print ("64 Bit Integer (Default %" G_GINT64_FORMAT ", Range %"
700                          G_GINT64_FORMAT " -> %" G_GINT64_FORMAT ")",
701             ((GParamSpecInt64 *) specs[x])->default_value,
702             ((GParamSpecInt64 *) specs[x])->minimum,
703             ((GParamSpecInt64 *) specs[x])->maximum);
704             break;
705           case G_TYPE_INT:
706             g_print ("Integer (Default %d, Range %d -> %d)",
707             ((GParamSpecInt *) specs[x])->default_value,
708             ((GParamSpecInt *) specs[x])->minimum,
709             ((GParamSpecInt *) specs[x])->maximum);
710             break;
711           case G_TYPE_FLOAT:
712             g_print ("Float. Default: %-8.8s %15.7g\n", "",
713               ((GParamSpecFloat *) specs[x])->default_value);
714             g_print ("%-23.23s Range: %15.7g - %15.7g", "",
715               ((GParamSpecFloat *) specs[x])->minimum,
716               ((GParamSpecFloat *) specs[x])->maximum);
717             break;
718         default: g_print ("unknown %ld", G_PARAM_SPEC_VALUE_TYPE (specs[x]));
719         }
720         g_print ("\n");
721       }
722       g_free (specs);
723     }
724     else {
725       g_print ("  none\n");
726     }
727   }
728
729   /* Signals/Actions Block */
730   {
731     guint *signals;
732     guint nsignals;
733     gint i, k;
734     GSignalQuery *query;
735     GType type;
736
737     for (k = 0; k < 2; k++) {
738       gint counted = 0;
739
740       if (k == 0)
741         g_print ("\nElement Signals:\n");
742       else
743         g_print ("\nElement Actions:\n");
744
745       for(type = G_OBJECT_TYPE(element); type; type = g_type_parent(type)){
746         signals = g_signal_list_ids (type, &nsignals);
747
748         for (i = 0; i < nsignals; i++) {
749           gint n_params;
750           GType return_type;
751           const GType *param_types;
752           gint j;
753
754           query = g_new0 (GSignalQuery,1);
755           g_signal_query (signals[i], query);
756
757           if ((k == 0 && !(query->signal_flags & G_SIGNAL_ACTION)) ||
758               (k == 1 &&  (query->signal_flags & G_SIGNAL_ACTION))) {
759             n_params = query->n_params;
760             return_type = query->return_type;
761             param_types = query->param_types;
762
763             g_print ("  \"%s\" :\t %s user_function (%s* object",
764                     query->signal_name, g_type_name (return_type),
765                     g_type_name (type));
766
767             for (j = 0; j < n_params; j++) {
768               g_print (",\n    \t\t\t\t%s arg%d", g_type_name(param_types[j]), j);
769             }
770             if (k == 0)
771               g_print (",\n    \t\t\t\tgpointer user_data);\n");
772             else
773               g_print (");\n");
774
775             counted++;
776           }
777
778           g_free (query);
779         }
780       }
781       if (counted == 0) g_print ("  none\n");
782     }
783   }
784
785   /* for compound elements */
786   if (GST_IS_BIN (element)) {
787     g_print ("\nChildren:\n");
788     children = (GList *) gst_bin_get_list (GST_BIN (element));
789     if (!children)
790       g_print ("  none\n");
791     else {
792       while (children) {
793         child = GST_ELEMENT (children->data);
794         children = g_list_next (children);
795
796         g_print ("  %s\n", GST_ELEMENT_NAME (child));
797       }
798     }
799   }
800
801   return 0;
802 }
803
804 static void
805 print_element_list (void)
806 {
807   GList *plugins;
808
809   plugins = gst_registry_pool_plugin_list();
810   while (plugins) {
811     GList *features;
812     GstPlugin *plugin;
813
814     plugin = (GstPlugin*)(plugins->data);
815     plugins = g_list_next (plugins);
816
817     features = gst_plugin_get_feature_list (plugin);
818     while (features) {
819       GstPluginFeature *feature;
820
821       feature = GST_PLUGIN_FEATURE (features->data);
822
823       if (GST_IS_ELEMENT_FACTORY (feature)) {
824         GstElementFactory *factory;
825
826         factory = GST_ELEMENT_FACTORY (feature);
827         g_print ("%s:  %s: %s\n", plugin->name,
828                 GST_PLUGIN_FEATURE_NAME (factory) ,factory->details->longname);
829       }
830 #ifndef GST_DISABLE_AUTOPLUG
831       else if (GST_IS_AUTOPLUG_FACTORY (feature)) {
832         GstAutoplugFactory *factory;
833
834         factory = GST_AUTOPLUG_FACTORY (feature);
835         g_print ("%s:  %s: %s\n", plugin->name,
836                 GST_PLUGIN_FEATURE_NAME (factory), factory->longdesc);
837       }
838 #endif
839 #ifndef GST_DISABLE_INDEX
840       else if (GST_IS_INDEX_FACTORY (feature)) {
841         GstIndexFactory *factory;
842
843         factory = GST_INDEX_FACTORY (feature);
844         g_print ("%s:  %s: %s\n", plugin->name,
845                 GST_PLUGIN_FEATURE_NAME (factory), factory->longdesc);
846       }
847 #endif
848       else if (GST_IS_TYPE_FACTORY (feature)) {
849         GstTypeFactory *factory;
850
851         factory = GST_TYPE_FACTORY (feature);
852         if (factory->exts)
853           g_print ("%s type:  %s: %s\n", plugin->name,
854                   factory->mime, factory->exts);
855         else
856           g_print ("%s type:  %s: N/A\n", plugin->name,
857                   factory->mime);
858
859         if (factory->typefindfunc)
860           g_print ("      Has typefind function: %s\n",
861                   GST_DEBUG_FUNCPTR_NAME (factory->typefindfunc));
862       }
863       else if (GST_IS_SCHEDULER_FACTORY (feature)) {
864         GstSchedulerFactory *factory;
865
866         factory = GST_SCHEDULER_FACTORY (feature);
867         g_print ("%s:  %s: %s\n", plugin->name,
868                 GST_PLUGIN_FEATURE_NAME (factory), factory->longdesc);
869       }
870 #ifndef GST_DISABLE_URI
871       else if (GST_IS_URI_HANDLER (feature)) {
872         GstURIHandler *handler;
873
874         handler = GST_URI_HANDLER (feature);
875         g_print ("%s:  %s: \"%s\" (%s) element \"%s\" property \"%s\"\n",
876                 plugin->name, GST_PLUGIN_FEATURE_NAME (handler), handler->uri,
877                 handler->longdesc, handler->element, handler->property);
878       }
879 #endif
880       else {
881         g_print ("%s:  %s (%s)\n", plugin->name,
882                 GST_PLUGIN_FEATURE_NAME (feature),
883                 g_type_name (G_OBJECT_TYPE (feature)));
884       }
885
886       features = g_list_next (features);
887     }
888   }
889 }
890
891 static void
892 print_plugin_info (GstPlugin *plugin)
893 {
894   GList *features;
895   gint num_features = 0;
896   gint num_elements = 0;
897   gint num_autoplug = 0;
898   gint num_types = 0;
899   gint num_schedulers = 0;
900   gint num_indexes = 0;
901   gint num_other = 0;
902
903   g_print ("Plugin Details:\n");
904   g_print ("  Name:\t\t%s\n",    plugin->name);
905   g_print ("  Long Name:\t%s\n", plugin->longname);
906   g_print ("  Filename:\t%s\n",  plugin->filename);
907   g_print ("\n");
908
909   features = gst_plugin_get_feature_list (plugin);
910
911   while (features) {
912     GstPluginFeature *feature;
913
914     feature = GST_PLUGIN_FEATURE (features->data);
915
916     if (GST_IS_ELEMENT_FACTORY (feature)) {
917       GstElementFactory *factory;
918
919       factory = GST_ELEMENT_FACTORY (feature);
920       g_print ("  %s: %s\n", GST_OBJECT_NAME (factory),
921               factory->details->longname);
922       num_elements++;
923     }
924 #ifndef GST_DISABLE_AUTOPLUG
925     else if (GST_IS_AUTOPLUG_FACTORY (feature)) {
926       GstAutoplugFactory *factory;
927
928       factory = GST_AUTOPLUG_FACTORY (feature);
929       g_print ("  %s: %s\n", GST_OBJECT_NAME (factory), factory->longdesc);
930       num_autoplug++;
931     }
932 #endif
933 #ifndef GST_DISABLE_INDEX
934     else if (GST_IS_INDEX_FACTORY (feature)) {
935       GstIndexFactory *factory;
936
937       factory = GST_INDEX_FACTORY (feature);
938       g_print ("  %s: %s\n", GST_OBJECT_NAME (factory), factory->longdesc);
939       num_indexes++;
940     }
941 #endif
942     else if (GST_IS_TYPE_FACTORY (feature)) {
943       GstTypeFactory *factory;
944
945       factory = GST_TYPE_FACTORY (feature);
946       g_print ("  %s: %s\n", factory->mime, factory->exts);
947
948       if (factory->typefindfunc)
949         g_print ("      Has typefind function: %s\n",
950                 GST_DEBUG_FUNCPTR_NAME (factory->typefindfunc));
951       num_types++;
952     }
953     else if (GST_IS_SCHEDULER_FACTORY (feature)) {
954       GstSchedulerFactory *factory;
955
956       factory = GST_SCHEDULER_FACTORY (feature);
957       g_print ("  %s: %s\n", GST_OBJECT_NAME (factory), factory->longdesc);
958       num_schedulers++;
959     }
960     else {
961       g_print ("  %s (%s)\n", gst_object_get_name (GST_OBJECT (feature)),
962                              g_type_name (G_OBJECT_TYPE (feature)));
963       num_other++;
964     }
965     num_features++;
966     features = g_list_next (features);
967   }
968   g_print ("\n  %d features:\n", num_features);
969   if (num_elements > 0)
970     g_print ("  +-- %d elements\n", num_elements);
971   if (num_autoplug > 0)
972     g_print ("  +-- %d autopluggers\n", num_autoplug);
973   if (num_types > 0)
974     g_print ("  +-- %d types\n", num_types);
975   if (num_schedulers > 0)
976     g_print ("  +-- %d schedulers\n", num_schedulers);
977   if (num_indexes > 0)
978     g_print ("  +-- %d indexes\n", num_indexes);
979   if (num_other > 0)
980     g_print ("  +-- %d other objects\n", num_other);
981
982   g_print ("\n");
983 }
984
985 int
986 main (int argc, char *argv[])
987 {
988   GstElementFactory *factory;
989   GstPlugin *plugin;
990   gchar *so;
991   struct poptOption options[] = {
992     {"gst-inspect-plugin", 'p', POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, 0,
993                    "Show plugin details", NULL},
994     {"gst-inspect-scheduler", 's', POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, 0,
995                    "Show scheduler details", NULL},
996     POPT_TABLEEND
997   };
998
999   gst_init_with_popt_table (&argc, &argv, options);
1000   gst_control_init (&argc, &argv);
1001
1002   /* if no arguments, print out list of elements */
1003   if (argc == 1) {
1004     print_element_list();
1005
1006   /* else we try to get a factory */
1007   } else {
1008     /* first check for help */
1009     if (strstr (argv[1], "-help")) {
1010       g_print ("Usage: %s\t\t\tList all registered elements\n",argv[0]);
1011       g_print ("       %s element-name\tShow element details\n",argv[0]);
1012       g_print ("       %s plugin-name[.so]\tShow information about plugin\n",
1013               argv[0]);
1014       return 0;
1015     }
1016
1017     /* only search for a factory if there's not a '.so' */
1018     if (! strstr (argv[1], ".so")) {
1019       factory = gst_element_factory_find (argv[1]);
1020
1021       /* if there's a factory, print out the info */
1022       if (factory)
1023         return print_element_info (factory);
1024       else {
1025          GstPluginFeature* feature;
1026
1027          /* FIXME implement other pretty print function for these */
1028          feature = gst_registry_pool_find_feature (argv[1],
1029                                                    GST_TYPE_SCHEDULER_FACTORY);
1030          if (feature) {
1031            g_print ("%s: a scheduler\n", argv[1]);
1032            return 0;
1033          }
1034 #ifndef GST_DISABLE_INDEX
1035          feature = gst_registry_pool_find_feature (argv[1],
1036                                                    GST_TYPE_INDEX_FACTORY);
1037          if (feature) {
1038            g_print ("%s: an index\n", argv[1]);
1039            return 0;
1040          }
1041 #endif
1042 #ifndef GST_DISABLE_AUTOPLUG
1043          feature = gst_registry_pool_find_feature (argv[1],
1044                                                    GST_TYPE_AUTOPLUG_FACTORY);
1045          if (feature) {
1046            g_print ("%s: an autoplugger\n", argv[1]);
1047            return 0;
1048          }
1049 #endif
1050          feature = gst_registry_pool_find_feature (argv[1],
1051                                                    GST_TYPE_TYPE_FACTORY);
1052          if (feature) {
1053            g_print ("%s: an type\n", argv[1]);
1054            return 0;
1055          }
1056 #ifndef GST_DISABLE_URI
1057          feature = gst_registry_pool_find_feature (argv[1],
1058                                                    GST_TYPE_URI_HANDLER);
1059          if (feature) {
1060            g_print ("%s: an uri handler\n", argv[1]);
1061            return 0;
1062          }
1063 #endif
1064       }
1065     } else {
1066       /* strip the .so */
1067       so = strstr(argv[1],".so");
1068       so[0] = '\0';
1069     }
1070
1071     /* otherwise assume it's a plugin */
1072     plugin = gst_registry_pool_find_plugin (argv[1]);
1073
1074     /* if there is such a plugin, print out info */
1075
1076     if (plugin) {
1077       print_plugin_info (plugin);
1078
1079     } else {
1080       g_print("no such element or plugin '%s'\n", argv[1]);
1081       return -1;
1082     }
1083   }
1084
1085   return 0;
1086 }