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