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