Initialise some variables to get the thing to compile
[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 Arguments:\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_ELEMENT_RANK_NONE:
449       return "none";
450     case GST_ELEMENT_RANK_MARGINAL:
451       return "marginal";
452     case GST_ELEMENT_RANK_SECONDARY:
453       return "secondary";
454     case GST_ELEMENT_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 ("  License:\t%s\n",     factory->details->license);
489   g_print ("  Description:\t%s\n", factory->details->description);
490   g_print ("  Version:\t%s\n",     factory->details->version);
491   g_print ("  Author(s):\t%s\n",   factory->details->author);
492   g_print ("  Copyright:\t%s\n",   factory->details->copyright);
493   g_print ("  Rank:\t\t%s\n",      get_rank_name(GST_PLUGIN_FEATURE(factory)->rank));
494   g_print ("\n");
495
496   output_hierarchy (G_OBJECT_TYPE (element), 0, &maxlevel);
497
498   g_print ("Pad Templates:\n");
499   if (factory->numpadtemplates) {
500     pads = factory->padtemplates;
501     while (pads) {
502       padtemplate = (GstPadTemplate*)(pads->data);
503       pads = g_list_next(pads);
504
505       if (padtemplate->direction == GST_PAD_SRC)
506         g_print ("  SRC template: '%s'\n", padtemplate->name_template);
507       else if (padtemplate->direction == GST_PAD_SINK)
508         g_print ("  SINK template: '%s'\n", padtemplate->name_template);
509       else
510         g_print ("  UNKNOWN!!! template: '%s'\n", padtemplate->name_template);
511
512       if (padtemplate->presence == GST_PAD_ALWAYS)
513         g_print ("    Availability: Always\n");
514       else if (padtemplate->presence == GST_PAD_SOMETIMES)
515         g_print ("    Availability: Sometimes\n");
516       else if (padtemplate->presence == GST_PAD_REQUEST) {
517         g_print ("    Availability: On request\n");
518         g_print ("      Has request_new_pad() function: %s\n",
519                 GST_DEBUG_FUNCPTR_NAME (gstelement_class->request_new_pad));
520       }
521       else
522         g_print ("    Availability: UNKNOWN!!!\n");
523
524       if (padtemplate->caps) {
525         g_print ("    Capabilities:\n");
526         print_caps (padtemplate->caps, "      ");
527       }
528
529       g_print ("\n");
530     }
531   } else
532     g_print ("  none\n");
533
534   have_flags = FALSE;
535
536   g_print ("\nElement Flags:\n");
537   if (GST_FLAG_IS_SET (element, GST_ELEMENT_COMPLEX)) {
538     g_print ("  GST_ELEMENT_COMPLEX\n");
539     have_flags = TRUE;
540   }
541   if (GST_FLAG_IS_SET (element, GST_ELEMENT_DECOUPLED)) {
542     g_print ("  GST_ELEMENT_DECOUPLED\n");
543     have_flags = TRUE;
544   }
545   if (GST_FLAG_IS_SET (element, GST_ELEMENT_THREAD_SUGGESTED)) {
546     g_print ("  GST_ELEMENT_THREADSUGGESTED\n");
547     have_flags = TRUE;
548   }
549   if (GST_FLAG_IS_SET (element, GST_ELEMENT_EVENT_AWARE)) {
550     g_print("  GST_ELEMENT_EVENT_AWARE\n");
551     have_flags = TRUE;
552   }
553   if (!have_flags)
554     g_print("  no flags set\n");
555
556   if (GST_IS_BIN (element)) {
557     g_print ("\nBin Flags:\n");
558     if (GST_FLAG_IS_SET (element, GST_BIN_FLAG_MANAGER)) {
559       g_print ("  GST_BIN_FLAG_MANAGER\n");
560       have_flags = TRUE;
561     }
562     if (GST_FLAG_IS_SET (element, GST_BIN_SELF_SCHEDULABLE)) {
563       g_print ("  GST_BIN_SELF_SCHEDULABLE\n");
564       have_flags = TRUE;
565     }
566     if (GST_FLAG_IS_SET (element, GST_BIN_FLAG_PREFER_COTHREADS)) {
567       g_print ("  GST_BIN_FLAG_PREFER_COTHREADS\n");
568       have_flags = TRUE;
569     }
570     if (!have_flags)
571       g_print ("  no flags set\n");
572   }
573
574
575
576   g_print ("\nElement Implementation:\n");
577
578   if (element->loopfunc)
579     g_print ("  loopfunc()-based element: %s\n",
580             GST_DEBUG_FUNCPTR_NAME (element->loopfunc));
581   else
582     g_print ("  No loopfunc(), must be chain-based or not configured yet\n");
583
584   g_print ("  Has change_state() function: %s\n",
585           GST_DEBUG_FUNCPTR_NAME (gstelement_class->change_state));
586 #ifndef GST_DISABLE_LOADSAVE
587   g_print ("  Has custom save_thyself() function: %s\n",
588           GST_DEBUG_FUNCPTR_NAME (gstobject_class->save_thyself));
589   g_print ("  Has custom restore_thyself() function: %s\n",
590           GST_DEBUG_FUNCPTR_NAME (gstobject_class->restore_thyself));
591 #endif
592
593   have_flags = FALSE;
594
595   g_print ("\nClocking Interaction:\n");
596   if (gst_element_requires_clock (element)) {
597     g_print ("  element requires a clock\n");
598     have_flags = TRUE;
599   }
600   if (gst_element_provides_clock (element)) {
601     GstClock *clock;
602
603     clock = gst_element_get_clock (element);
604     if (clock)
605       g_print ("  element provides a clock: %s\n", GST_OBJECT_NAME(clock));
606     else
607       g_print ("  element is supposed to provide a clock but returned NULL\n");
608     have_flags = TRUE;
609   }
610   if (!have_flags) {
611     g_print ("  none\n");
612   }
613
614 #ifndef GST_DISABLE_INDEX
615   g_print ("\nIndexing capabilities:\n");
616   if (gst_element_is_indexable (element)) {
617     g_print ("  element can do indexing\n");
618   }
619   else {
620     g_print ("  none\n");
621   }
622 #endif
623
624   g_print ("\nPads:\n");
625   if (element->numpads) {
626     const GList *pads;
627     pads = gst_element_get_pad_list (element);
628     while (pads) {
629       pad = GST_PAD (pads->data);
630       pads = g_list_next (pads);
631       realpad = GST_PAD_REALIZE (pad);
632
633       if (gst_pad_get_direction (pad) == GST_PAD_SRC)
634         g_print ("  SRC: '%s'", gst_pad_get_name (pad));
635       else if (gst_pad_get_direction (pad) == GST_PAD_SINK)
636         g_print ("  SINK: '%s'", gst_pad_get_name (pad));
637       else
638         g_print ("  UNKNOWN!!!: '%s'\n", gst_pad_get_name (pad));
639
640       if (GST_IS_GHOST_PAD (pad))
641         g_print (", ghost of real pad %s:%s\n", GST_DEBUG_PAD_NAME (realpad));
642       else
643         g_print ("\n");
644
645       g_print ("    Implementation:\n");
646       if (realpad->chainfunc)
647         g_print ("      Has chainfunc(): %s\n",
648                 GST_DEBUG_FUNCPTR_NAME (realpad->chainfunc));
649       if (realpad->getfunc)
650         g_print ("      Has getfunc(): %s\n",
651                 GST_DEBUG_FUNCPTR_NAME (realpad->getfunc));
652       if (realpad->formatsfunc != gst_pad_get_formats_default) {
653         g_print ("      Supports seeking/conversion/query formats:\n");
654         print_formats (gst_pad_get_formats (GST_PAD (realpad)));
655       }
656       if (realpad->convertfunc != gst_pad_convert_default)
657         g_print ("      Has custom convertfunc(): %s\n",
658                 GST_DEBUG_FUNCPTR_NAME (realpad->convertfunc));
659       if (realpad->eventfunc != gst_pad_event_default)
660         g_print ("      Has custom eventfunc(): %s\n",
661                 GST_DEBUG_FUNCPTR_NAME (realpad->eventfunc));
662       if (realpad->eventmaskfunc != gst_pad_get_event_masks_default) {
663         g_print ("        Provides event masks:\n");
664         print_event_masks (gst_pad_get_event_masks (GST_PAD (realpad)));
665       }
666       if (realpad->queryfunc != gst_pad_query_default)
667         g_print ("      Has custom queryfunc(): %s\n",
668                 GST_DEBUG_FUNCPTR_NAME (realpad->queryfunc));
669       if (realpad->querytypefunc != gst_pad_get_query_types_default) {
670         g_print ("        Provides query types:\n");
671         print_query_types (gst_pad_get_query_types (GST_PAD (realpad)));
672       }
673
674       if (realpad->intlinkfunc != gst_pad_get_internal_links_default)
675         g_print ("      Has custom intconnfunc(): %s\n",
676                 GST_DEBUG_FUNCPTR_NAME(realpad->intlinkfunc));
677
678       if (realpad->bufferpoolfunc)
679         g_print ("      Has bufferpoolfunc(): %s\n",
680                 GST_DEBUG_FUNCPTR_NAME(realpad->bufferpoolfunc));
681
682       if (pad->padtemplate)
683         g_print ("    Pad Template: '%s'\n",
684                 pad->padtemplate->name_template);
685
686       if (realpad->caps) {
687         g_print ("    Capabilities:\n");
688         print_caps (realpad->caps, "      ");
689       }
690     }
691   } else
692     g_print ("  none\n");
693
694   print_element_properties (element);
695
696   /* Dynamic Parameters block */
697   {
698     GstDParamManager* dpman;
699     GParamSpec** specs;
700     gint x;
701
702     g_print ("\nDynamic Parameters:\n");
703     if((dpman = gst_dpman_get_manager (element))) {
704       specs = gst_dpman_list_dparam_specs (dpman);
705       for (x = 0; specs[x] != NULL; x++) {
706         g_print ("  %-20.20s: ", g_param_spec_get_name (specs[x]));
707
708         switch (G_PARAM_SPEC_VALUE_TYPE (specs[x])) {
709           case G_TYPE_INT64:
710             g_print ("64 Bit Integer (Default %" G_GINT64_FORMAT ", Range %"
711                          G_GINT64_FORMAT " -> %" G_GINT64_FORMAT ")",
712             ((GParamSpecInt64 *) specs[x])->default_value,
713             ((GParamSpecInt64 *) specs[x])->minimum,
714             ((GParamSpecInt64 *) specs[x])->maximum);
715             break;
716           case G_TYPE_INT:
717             g_print ("Integer (Default %d, Range %d -> %d)",
718             ((GParamSpecInt *) specs[x])->default_value,
719             ((GParamSpecInt *) specs[x])->minimum,
720             ((GParamSpecInt *) specs[x])->maximum);
721             break;
722           case G_TYPE_FLOAT:
723             g_print ("Float. Default: %-8.8s %15.7g\n", "",
724               ((GParamSpecFloat *) specs[x])->default_value);
725             g_print ("%-23.23s Range: %15.7g - %15.7g", "",
726               ((GParamSpecFloat *) specs[x])->minimum,
727               ((GParamSpecFloat *) specs[x])->maximum);
728             break;
729         default: g_print ("unknown %ld", G_PARAM_SPEC_VALUE_TYPE (specs[x]));
730         }
731         g_print ("\n");
732       }
733       g_free (specs);
734     }
735     else {
736       g_print ("  none\n");
737     }
738   }
739
740   /* Signals/Actions Block */
741   {
742     guint *signals;
743     guint nsignals;
744     gint i, k;
745     GSignalQuery *query;
746     GType type;
747
748     for (k = 0; k < 2; k++) {
749       gint counted = 0;
750
751       if (k == 0)
752         g_print ("\nElement Signals:\n");
753       else
754         g_print ("\nElement Actions:\n");
755
756       for(type = G_OBJECT_TYPE(element); type; type = g_type_parent(type)){
757         signals = g_signal_list_ids (type, &nsignals);
758
759         for (i = 0; i < nsignals; i++) {
760           gint n_params;
761           GType return_type;
762           const GType *param_types;
763           gint j;
764
765           query = g_new0 (GSignalQuery,1);
766           g_signal_query (signals[i], query);
767
768           if ((k == 0 && !(query->signal_flags & G_SIGNAL_ACTION)) ||
769               (k == 1 &&  (query->signal_flags & G_SIGNAL_ACTION))) {
770             n_params = query->n_params;
771             return_type = query->return_type;
772             param_types = query->param_types;
773
774             g_print ("  \"%s\" :\t %s user_function (%s* object",
775                     query->signal_name, g_type_name (return_type),
776                     g_type_name (type));
777
778             for (j = 0; j < n_params; j++) {
779               g_print (",\n    \t\t\t\t%s arg%d", g_type_name(param_types[j]), j);
780             }
781             if (k == 0)
782               g_print (",\n    \t\t\t\tgpointer user_data);\n");
783             else
784               g_print (");\n");
785
786             counted++;
787           }
788
789           g_free (query);
790         }
791       }
792       if (counted == 0) g_print ("  none\n");
793     }
794   }
795
796   /* for compound elements */
797   if (GST_IS_BIN (element)) {
798     g_print ("\nChildren:\n");
799     children = (GList *) gst_bin_get_list (GST_BIN (element));
800     if (!children)
801       g_print ("  none\n");
802     else {
803       while (children) {
804         child = GST_ELEMENT (children->data);
805         children = g_list_next (children);
806
807         g_print ("  %s\n", GST_ELEMENT_NAME (child));
808       }
809     }
810   }
811
812   return 0;
813 }
814
815 static void
816 print_element_list (void)
817 {
818   GList *plugins;
819
820   plugins = gst_registry_pool_plugin_list();
821   while (plugins) {
822     GList *features;
823     GstPlugin *plugin;
824
825     plugin = (GstPlugin*)(plugins->data);
826     plugins = g_list_next (plugins);
827
828     features = gst_plugin_get_feature_list (plugin);
829     while (features) {
830       GstPluginFeature *feature;
831
832       feature = GST_PLUGIN_FEATURE (features->data);
833
834       if (GST_IS_ELEMENT_FACTORY (feature)) {
835         GstElementFactory *factory;
836
837         factory = GST_ELEMENT_FACTORY (feature);
838         g_print ("%s:  %s: %s\n", plugin->name,
839                 GST_PLUGIN_FEATURE_NAME (factory) ,factory->details->longname);
840       }
841 #ifndef GST_DISABLE_AUTOPLUG
842       else if (GST_IS_AUTOPLUG_FACTORY (feature)) {
843         GstAutoplugFactory *factory;
844
845         factory = GST_AUTOPLUG_FACTORY (feature);
846         g_print ("%s:  %s: %s\n", plugin->name,
847                 GST_PLUGIN_FEATURE_NAME (factory), factory->longdesc);
848       }
849 #endif
850 #ifndef GST_DISABLE_INDEX
851       else if (GST_IS_INDEX_FACTORY (feature)) {
852         GstIndexFactory *factory;
853
854         factory = GST_INDEX_FACTORY (feature);
855         g_print ("%s:  %s: %s\n", plugin->name,
856                 GST_PLUGIN_FEATURE_NAME (factory), factory->longdesc);
857       }
858 #endif
859       else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
860         GstTypeFindFactory *factory;
861
862         factory = GST_TYPE_FIND_FACTORY (feature);
863         if (factory->extensions) {
864           guint i = 0;
865           g_print ("%s type: ", plugin->name);
866           while (factory->extensions[i]) {
867             g_print ("%s%s", i > 0 ? ", " : "", factory->extensions[i]);
868             i++;
869           }
870         } else
871           g_print ("%s type: N/A\n", plugin->name);
872       }
873       else if (GST_IS_SCHEDULER_FACTORY (feature)) {
874         GstSchedulerFactory *factory;
875
876         factory = GST_SCHEDULER_FACTORY (feature);
877         g_print ("%s:  %s: %s\n", plugin->name,
878                 GST_PLUGIN_FEATURE_NAME (factory), factory->longdesc);
879       }
880 #ifndef GST_DISABLE_URI
881       else if (GST_IS_URI_HANDLER (feature)) {
882         GstURIHandler *handler;
883
884         handler = GST_URI_HANDLER (feature);
885         g_print ("%s:  %s: \"%s\" (%s) element \"%s\" property \"%s\"\n",
886                 plugin->name, GST_PLUGIN_FEATURE_NAME (handler), handler->uri,
887                 handler->longdesc, handler->element, handler->property);
888       }
889 #endif
890       else {
891         g_print ("%s:  %s (%s)\n", plugin->name,
892                 GST_PLUGIN_FEATURE_NAME (feature),
893                 g_type_name (G_OBJECT_TYPE (feature)));
894       }
895
896       features = g_list_next (features);
897     }
898   }
899 }
900
901 static void
902 print_plugin_info (GstPlugin *plugin)
903 {
904   GList *features;
905   gint num_features = 0;
906   gint num_elements = 0;
907   gint num_autoplug = 0;
908   gint num_types = 0;
909   gint num_schedulers = 0;
910   gint num_indexes = 0;
911   gint num_other = 0;
912
913   g_print ("Plugin Details:\n");
914   g_print ("  Name:\t\t%s\n",    plugin->name);
915   g_print ("  Long Name:\t%s\n", plugin->longname);
916   g_print ("  Filename:\t%s\n",  plugin->filename);
917   g_print ("\n");
918
919   features = gst_plugin_get_feature_list (plugin);
920
921   while (features) {
922     GstPluginFeature *feature;
923
924     feature = GST_PLUGIN_FEATURE (features->data);
925
926     if (GST_IS_ELEMENT_FACTORY (feature)) {
927       GstElementFactory *factory;
928
929       factory = GST_ELEMENT_FACTORY (feature);
930       g_print ("  %s: %s\n", GST_OBJECT_NAME (factory),
931               factory->details->longname);
932       num_elements++;
933     }
934 #ifndef GST_DISABLE_AUTOPLUG
935     else if (GST_IS_AUTOPLUG_FACTORY (feature)) {
936       GstAutoplugFactory *factory;
937
938       factory = GST_AUTOPLUG_FACTORY (feature);
939       g_print ("  %s: %s\n", GST_OBJECT_NAME (factory), factory->longdesc);
940       num_autoplug++;
941     }
942 #endif
943 #ifndef GST_DISABLE_INDEX
944     else if (GST_IS_INDEX_FACTORY (feature)) {
945       GstIndexFactory *factory;
946
947       factory = GST_INDEX_FACTORY (feature);
948       g_print ("  %s: %s\n", GST_OBJECT_NAME (factory), factory->longdesc);
949       num_indexes++;
950     }
951 #endif
952     else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
953       GstTypeFindFactory *factory;
954
955       factory = GST_TYPE_FIND_FACTORY (feature);
956       if (factory->extensions) {
957         guint i = 0;
958         g_print ("%s type: ", plugin->name);
959         while (factory->extensions[i]) {
960           g_print ("%s%s", i > 0 ? ", " : "", factory->extensions[i]);
961           i++;
962         }
963       } else
964         g_print ("%s type: N/A\n", plugin->name);
965
966       num_types++;
967     }
968     else if (GST_IS_SCHEDULER_FACTORY (feature)) {
969       GstSchedulerFactory *factory;
970
971       factory = GST_SCHEDULER_FACTORY (feature);
972       g_print ("  %s: %s\n", GST_OBJECT_NAME (factory), factory->longdesc);
973       num_schedulers++;
974     }
975     else {
976       g_print ("  %s (%s)\n", gst_object_get_name (GST_OBJECT (feature)),
977                              g_type_name (G_OBJECT_TYPE (feature)));
978       num_other++;
979     }
980     num_features++;
981     features = g_list_next (features);
982   }
983   g_print ("\n  %d features:\n", num_features);
984   if (num_elements > 0)
985     g_print ("  +-- %d elements\n", num_elements);
986   if (num_autoplug > 0)
987     g_print ("  +-- %d autopluggers\n", num_autoplug);
988   if (num_types > 0)
989     g_print ("  +-- %d types\n", num_types);
990   if (num_schedulers > 0)
991     g_print ("  +-- %d schedulers\n", num_schedulers);
992   if (num_indexes > 0)
993     g_print ("  +-- %d indexes\n", num_indexes);
994   if (num_other > 0)
995     g_print ("  +-- %d other objects\n", num_other);
996
997   g_print ("\n");
998 }
999
1000 int
1001 main (int argc, char *argv[])
1002 {
1003   GstElementFactory *factory;
1004   GstPlugin *plugin;
1005   gchar *so;
1006   struct poptOption options[] = {
1007     {"gst-inspect-plugin", 'p', POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, 0,
1008                    "Show plugin details", NULL},
1009     {"gst-inspect-scheduler", 's', POPT_ARG_STRING|POPT_ARGFLAG_STRIP, NULL, 0,
1010                    "Show scheduler details", NULL},
1011     POPT_TABLEEND
1012   };
1013
1014   gst_init_with_popt_table (&argc, &argv, options);
1015   gst_control_init (&argc, &argv);
1016
1017   /* if no arguments, print out list of elements */
1018   if (argc == 1) {
1019     print_element_list();
1020
1021   /* else we try to get a factory */
1022   } else {
1023     /* first check for help */
1024     if (strstr (argv[1], "-help")) {
1025       g_print ("Usage: %s\t\t\tList all registered elements\n",argv[0]);
1026       g_print ("       %s element-name\tShow element details\n",argv[0]);
1027       g_print ("       %s plugin-name[.so]\tShow information about plugin\n",
1028               argv[0]);
1029       return 0;
1030     }
1031
1032     /* only search for a factory if there's not a '.so' */
1033     if (! strstr (argv[1], ".so")) {
1034       factory = gst_element_factory_find (argv[1]);
1035
1036       /* if there's a factory, print out the info */
1037       if (factory)
1038         return print_element_info (factory);
1039       else {
1040          GstPluginFeature* feature;
1041
1042          /* FIXME implement other pretty print function for these */
1043          feature = gst_registry_pool_find_feature (argv[1],
1044                                                    GST_TYPE_SCHEDULER_FACTORY);
1045          if (feature) {
1046            g_print ("%s: a scheduler\n", argv[1]);
1047            return 0;
1048          }
1049 #ifndef GST_DISABLE_INDEX
1050          feature = gst_registry_pool_find_feature (argv[1],
1051                                                    GST_TYPE_INDEX_FACTORY);
1052          if (feature) {
1053            g_print ("%s: an index\n", argv[1]);
1054            return 0;
1055          }
1056 #endif
1057 #ifndef GST_DISABLE_AUTOPLUG
1058          feature = gst_registry_pool_find_feature (argv[1],
1059                                                    GST_TYPE_AUTOPLUG_FACTORY);
1060          if (feature) {
1061            g_print ("%s: an autoplugger\n", argv[1]);
1062            return 0;
1063          }
1064 #endif
1065          feature = gst_registry_pool_find_feature (argv[1],
1066                                                    GST_TYPE_TYPE_FIND_FACTORY);
1067          if (feature) {
1068            g_print ("%s: a typefind function\n", argv[1]);
1069            return 0;
1070          }
1071 #ifndef GST_DISABLE_URI
1072          feature = gst_registry_pool_find_feature (argv[1],
1073                                                    GST_TYPE_URI_HANDLER);
1074          if (feature) {
1075            g_print ("%s: an uri handler\n", argv[1]);
1076            return 0;
1077          }
1078 #endif
1079       }
1080     } else {
1081       /* strip the .so */
1082       so = strstr(argv[1],".so");
1083       so[0] = '\0';
1084     }
1085
1086     /* otherwise assume it's a plugin */
1087     plugin = gst_registry_pool_find_plugin (argv[1]);
1088
1089     /* if there is such a plugin, print out info */
1090
1091     if (plugin) {
1092       print_plugin_info (plugin);
1093
1094     } else {
1095       g_print("no such element or plugin '%s'\n", argv[1]);
1096       return -1;
1097     }
1098   }
1099
1100   return 0;
1101 }