gst/gstconfig.h.in: Psych out gtk-doc.
[platform/upstream/gstreamer.git] / tools / gst-inspect.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *               2000 Wim Taymans <wtay@chello.be>
4  *               2004 Thomas Vander Stichele <thomas@apestaart.org>
5  *
6  * gst-inspect.c: tool to inspect the GStreamer registry
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #  include "config.h"
26 #endif
27
28 #include <gst/gst.h>
29 #include <gst/controller/gstcontroller.h>
30
31 #include "gst/gst-i18n-app.h"
32
33 #include <string.h>
34 #include <locale.h>
35 #include <glib/gprintf.h>
36
37 static char *_name;
38
39 static int print_element_info (GstElementFactory * factory,
40     gboolean print_names);
41
42 void
43 n_print (const char *format, ...)
44 {
45   va_list args;
46   gint retval;
47
48   if (_name)
49     g_print (_name);
50
51   va_start (args, format);
52   retval = g_vprintf (format, args);
53   va_end (args);
54 }
55
56 static gboolean
57 print_field (GQuark field, const GValue * value, gpointer pfx)
58 {
59   gchar *str = gst_value_serialize (value);
60
61   n_print ("%s  %15s: %s\n", (gchar *) pfx, g_quark_to_string (field), str);
62   g_free (str);
63   return TRUE;
64 }
65
66 static void
67 print_caps (const GstCaps * caps, const gchar * pfx)
68 {
69   guint i;
70
71   g_return_if_fail (caps != NULL);
72
73   if (gst_caps_is_any (caps)) {
74     n_print ("%sANY\n", pfx);
75     return;
76   }
77   if (gst_caps_is_empty (caps)) {
78     n_print ("%sEMPTY\n", pfx);
79     return;
80   }
81
82   for (i = 0; i < gst_caps_get_size (caps); i++) {
83     GstStructure *structure = gst_caps_get_structure (caps, i);
84
85     n_print ("%s%s\n", pfx, gst_structure_get_name (structure));
86     gst_structure_foreach (structure, print_field, (gpointer) pfx);
87   }
88 }
89
90 #if 0
91 static void
92 print_formats (const GstFormat * formats)
93 {
94   while (formats && *formats) {
95     const GstFormatDefinition *definition;
96
97     definition = gst_format_get_details (*formats);
98     if (definition)
99       n_print ("\t\t(%d):\t%s (%s)\n", *formats,
100           definition->nick, definition->description);
101     else
102       n_print ("\t\t(%d):\tUnknown format\n", *formats);
103
104     formats++;
105   }
106 }
107 #endif
108
109 static void
110 print_query_types (const GstQueryType * types)
111 {
112   while (types && *types) {
113     const GstQueryTypeDefinition *definition;
114
115     definition = gst_query_type_get_details (*types);
116     if (definition)
117       n_print ("\t\t(%d):\t%s (%s)\n", *types,
118           definition->nick, definition->description);
119     else
120       n_print ("\t\t(%d):\tUnknown query format\n", *types);
121
122     types++;
123   }
124 }
125
126 #ifndef GST_DISABLE_ENUMTYPES
127 #if 0
128 static void
129 print_event_masks (const GstEventMask * masks)
130 {
131   GType event_type;
132   GEnumClass *klass;
133   GType event_flags;
134   GFlagsClass *flags_class = NULL;
135
136   event_type = gst_event_type_get_type ();
137   klass = (GEnumClass *) g_type_class_ref (event_type);
138
139   while (masks && masks->type) {
140     GEnumValue *value;
141     gint flags = 0, index = 0;
142
143     switch (masks->type) {
144       case GST_EVENT_SEEK:
145         flags = masks->flags;
146         event_flags = gst_seek_type_get_type ();
147         flags_class = (GFlagsClass *) g_type_class_ref (event_flags);
148         break;
149       default:
150         break;
151     }
152
153     value = g_enum_get_value (klass, masks->type);
154     g_print ("\t\t%s ", value->value_nick);
155
156     while (flags) {
157       GFlagsValue *value;
158
159       if (flags & 1) {
160         value = g_flags_get_first_value (flags_class, 1 << index);
161
162         if (value)
163           g_print ("| %s ", value->value_nick);
164         else
165           g_print ("| ? ");
166       }
167       flags >>= 1;
168       index++;
169     }
170     g_print ("\n");
171
172     masks++;
173   }
174 }
175 #endif
176 #else
177 static void
178 print_event_masks (const GstEventMask * masks)
179 {
180 }
181 #endif
182
183 static char *
184 get_rank_name (gint rank)
185 {
186   switch (rank) {
187     case GST_RANK_NONE:
188       return "none";
189     case GST_RANK_MARGINAL:
190       return "marginal";
191     case GST_RANK_SECONDARY:
192       return "secondary";
193     case GST_RANK_PRIMARY:
194       return "primary";
195     default:
196       return "unknown";
197   }
198 }
199
200 static void
201 print_factory_details_info (GstElementFactory * factory)
202 {
203   n_print ("Factory Details:\n");
204   n_print ("  Long name:\t%s\n", factory->details.longname);
205   n_print ("  Class:\t%s\n", factory->details.klass);
206   n_print ("  Description:\t%s\n", factory->details.description);
207   n_print ("  Author(s):\t%s\n", factory->details.author);
208   n_print ("  Rank:\t\t%s (%d)\n",
209       get_rank_name (GST_PLUGIN_FEATURE (factory)->rank),
210       GST_PLUGIN_FEATURE (factory)->rank);
211   n_print ("\n");
212 }
213
214 static void
215 print_hierarchy (GType type, gint level, gint * maxlevel)
216 {
217   GType parent;
218   gint i;
219
220   parent = g_type_parent (type);
221
222   *maxlevel = *maxlevel + 1;
223   level++;
224
225   if (parent)
226     print_hierarchy (parent, level, maxlevel);
227
228   if (_name)
229     g_print (_name);
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     n_print ("\n");
240 }
241
242 static void
243 print_interfaces (GType type)
244 {
245   guint n_ifaces;
246   GType *iface, *ifaces = g_type_interfaces (type, &n_ifaces);
247
248   if (ifaces) {
249     if (n_ifaces) {
250       g_print ("Implemented Interfaces:\n");
251       iface = ifaces;
252       while (*iface) {
253         g_print ("  %s\n", g_type_name (*iface));
254         iface++;
255       }
256       g_print ("\n");
257       g_free (ifaces);
258     }
259   }
260 }
261
262 static void
263 print_element_properties_info (GstElement * element)
264 {
265   GParamSpec **property_specs;
266   guint num_properties, i;
267   gboolean readable;
268   gboolean first_flag;
269
270   property_specs = g_object_class_list_properties
271       (G_OBJECT_GET_CLASS (element), &num_properties);
272   n_print ("\n");
273   n_print ("Element Properties:\n");
274
275   for (i = 0; i < num_properties; i++) {
276     GValue value = { 0, };
277     GParamSpec *param = property_specs[i];
278
279     readable = FALSE;
280
281     g_value_init (&value, param->value_type);
282
283     n_print ("  %-20s: %s\n", g_param_spec_get_name (param),
284         g_param_spec_get_blurb (param));
285
286     first_flag = TRUE;
287     n_print ("%-23.23s flags: ", "");
288     if (param->flags & G_PARAM_READABLE) {
289       g_object_get_property (G_OBJECT (element), param->name, &value);
290       readable = TRUE;
291       g_print ((first_flag ? "readable" : ", readable"));
292       first_flag = FALSE;
293     }
294     if (param->flags & G_PARAM_WRITABLE) {
295       g_print ((first_flag ? "writable" : ", writable"));
296       first_flag = FALSE;
297     }
298     if (param->flags & GST_PARAM_CONTROLLABLE) {
299       g_print ((first_flag ? "controllable" : ", controllable"));
300       first_flag = FALSE;
301     }
302     n_print ("\n");
303
304     switch (G_VALUE_TYPE (&value)) {
305       case G_TYPE_STRING:
306       {
307         GParamSpecString *pstring = G_PARAM_SPEC_STRING (param);
308
309         n_print ("%-23.23s String. ", "");
310         g_print ("Default: \"%s\" ", pstring->default_value);
311         if (readable) {
312           const char *string_val = g_value_get_string (&value);
313
314           if (string_val == NULL)
315             g_print ("Current: \"\"");
316           else
317             g_print ("Current: \"%s\"", string_val);
318         }
319         break;
320       }
321       case G_TYPE_BOOLEAN:
322       {
323         GParamSpecBoolean *pboolean = G_PARAM_SPEC_BOOLEAN (param);
324
325         n_print ("%-23.23s Boolean. ", "");
326         g_print ("Default: %s ", (pboolean->default_value ? "true" : "false"));
327         if (readable)
328           g_print ("Current: %s",
329               (g_value_get_boolean (&value) ? "true" : "false"));
330         break;
331       }
332       case G_TYPE_ULONG:
333       {
334         GParamSpecULong *pulong = G_PARAM_SPEC_ULONG (param);
335
336         n_print ("%-23.23s Unsigned Long. ", "");
337         g_print ("Range: %lu - %lu Default: %lu ",
338             pulong->minimum, pulong->maximum, pulong->default_value);
339         if (readable)
340           g_print ("Current: %lu", g_value_get_ulong (&value));
341         break;
342       }
343       case G_TYPE_LONG:
344       {
345         GParamSpecLong *plong = G_PARAM_SPEC_LONG (param);
346
347         n_print ("%-23.23s Long. ", "");
348         g_print ("Range: %ld - %ld Default: %ld ",
349             plong->minimum, plong->maximum, plong->default_value);
350         if (readable)
351           g_print ("Current: %ld", g_value_get_long (&value));
352         break;
353       }
354       case G_TYPE_UINT:
355       {
356         GParamSpecUInt *puint = G_PARAM_SPEC_UINT (param);
357
358         n_print ("%-23.23s Unsigned Integer. ", "");
359         g_print ("Range: %u - %u Default: %u ",
360             puint->minimum, puint->maximum, puint->default_value);
361         if (readable)
362           g_print ("Current: %u", g_value_get_uint (&value));
363         break;
364       }
365       case G_TYPE_INT:
366       {
367         GParamSpecInt *pint = G_PARAM_SPEC_INT (param);
368
369         n_print ("%-23.23s Integer. ", "");
370         g_print ("Range: %d - %d Default: %d ",
371             pint->minimum, pint->maximum, pint->default_value);
372         if (readable)
373           g_print ("Current: %d", g_value_get_int (&value));
374         break;
375       }
376       case G_TYPE_UINT64:
377       {
378         GParamSpecUInt64 *puint64 = G_PARAM_SPEC_UINT64 (param);
379
380         n_print ("%-23.23s Unsigned Integer64. ", "");
381         g_print ("Range: %" G_GUINT64_FORMAT " - %" G_GUINT64_FORMAT
382             " Default: %" G_GUINT64_FORMAT " ",
383             puint64->minimum, puint64->maximum, puint64->default_value);
384         if (readable)
385           g_print ("Current: %" G_GUINT64_FORMAT, g_value_get_uint64 (&value));
386         break;
387       }
388       case G_TYPE_INT64:
389       {
390         GParamSpecInt64 *pint64 = G_PARAM_SPEC_INT64 (param);
391
392         n_print ("%-23.23s Integer64. ", "");
393         g_print ("Range: %" G_GINT64_FORMAT " - %" G_GINT64_FORMAT
394             " Default: %" G_GINT64_FORMAT " ",
395             pint64->minimum, pint64->maximum, pint64->default_value);
396         if (readable)
397           g_print ("Current: %" G_GINT64_FORMAT, g_value_get_int64 (&value));
398         break;
399       }
400       case G_TYPE_FLOAT:
401       {
402         GParamSpecFloat *pfloat = G_PARAM_SPEC_FLOAT (param);
403
404         n_print ("%-23.23s Float. ", "");
405         g_print ("Range: %15.7g - %15.7g Default: %15.7g ",
406             pfloat->minimum, pfloat->maximum, pfloat->default_value);
407         if (readable)
408           g_print ("Current: %15.7g\n", g_value_get_float (&value));
409         break;
410       }
411       case G_TYPE_DOUBLE:
412       {
413         GParamSpecDouble *pdouble = G_PARAM_SPEC_DOUBLE (param);
414
415         n_print ("%-23.23s Double. ", "");
416         g_print ("Range: %15.7g - %15.7g Default: %15.7g ",
417             pdouble->minimum, pdouble->maximum, pdouble->default_value);
418         if (readable)
419           g_print ("Current: %15.7g\n", g_value_get_double (&value));
420         break;
421       }
422       default:
423         if (param->value_type == GST_TYPE_URI) {
424           n_print ("%-23.23s URI", "");
425         }
426         if (param->value_type == GST_TYPE_CAPS) {
427           const GstCaps *caps = gst_value_get_caps (&value);
428
429           if (!caps)
430             n_print ("%-23.23s Caps (NULL)", "");
431           else {
432             print_caps (caps, "                           ");
433           }
434         } else if (G_IS_PARAM_SPEC_ENUM (param)) {
435           GEnumValue *values;
436           guint j = 0;
437           gint enum_value;
438
439           values = G_ENUM_CLASS (g_type_class_ref (param->value_type))->values;
440           enum_value = g_value_get_enum (&value);
441
442           while (values[j].value_name) {
443             if (values[j].value == enum_value)
444               break;
445             j++;
446           }
447
448           n_print ("%-23.23s Enum \"%s\" Current: %d, \"%s\"", "",
449               g_type_name (G_VALUE_TYPE (&value)),
450               enum_value, values[j].value_nick);
451
452           j = 0;
453           while (values[j].value_name) {
454             g_print ("\n%s%-23.23s    (%d): \t%s", "",
455                 _name, values[j].value, values[j].value_nick);
456             j++;
457           }
458           /* g_type_class_unref (ec); */
459         } else if (G_IS_PARAM_SPEC_FLAGS (param)) {
460           GFlagsValue *values;
461           guint j = 0;
462           gint flags_value;
463           GString *flags = NULL;
464
465           values = G_FLAGS_CLASS (g_type_class_ref (param->value_type))->values;
466           flags_value = g_value_get_flags (&value);
467
468           while (values[j].value_name) {
469             if (values[j].value & flags_value) {
470               if (flags) {
471                 g_string_append_printf (flags, " | %s", values[j].value_nick);
472               } else {
473                 flags = g_string_new (values[j].value_nick);
474               }
475             }
476             j++;
477           }
478
479           n_print ("%-23.23s Flags \"%s\" Current: %d, \"%s\"", "",
480               g_type_name (G_VALUE_TYPE (&value)),
481               flags_value, (flags ? flags->str : "(none)"));
482
483           j = 0;
484           while (values[j].value_name) {
485             g_print ("\n%s%-23.23s    (%d): \t%s", "",
486                 _name, values[j].value, values[j].value_nick);
487             j++;
488           }
489
490           if (flags)
491             g_string_free (flags, TRUE);
492         } else if (G_IS_PARAM_SPEC_OBJECT (param)) {
493           n_print ("%-23.23s Object of type \"%s\"", "",
494               g_type_name (param->value_type));
495         } else {
496           n_print ("%-23.23s Unknown type %ld \"%s\"", "", param->value_type,
497               g_type_name (param->value_type));
498         }
499         break;
500     }
501     if (!readable)
502       g_print (" Write only\n");
503     else
504       g_print ("\n");
505   }
506   if (num_properties == 0)
507     n_print ("  none\n");
508
509   g_free (property_specs);
510 }
511
512 static void
513 print_pad_templates_info (GstElement * element, GstElementFactory * factory)
514 {
515   GstElementClass *gstelement_class;
516   const GList *pads;
517   GstStaticPadTemplate *padtemplate;
518
519   n_print ("Pad Templates:\n");
520   if (!factory->numpadtemplates) {
521     n_print ("  none\n");
522     return;
523   }
524
525   gstelement_class = GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element));
526
527   pads = factory->staticpadtemplates;
528   while (pads) {
529     padtemplate = (GstStaticPadTemplate *) (pads->data);
530     pads = g_list_next (pads);
531
532     if (padtemplate->direction == GST_PAD_SRC)
533       n_print ("  SRC template: '%s'\n", padtemplate->name_template);
534     else if (padtemplate->direction == GST_PAD_SINK)
535       n_print ("  SINK template: '%s'\n", padtemplate->name_template);
536     else
537       n_print ("  UNKNOWN!!! template: '%s'\n", padtemplate->name_template);
538
539     if (padtemplate->presence == GST_PAD_ALWAYS)
540       n_print ("    Availability: Always\n");
541     else if (padtemplate->presence == GST_PAD_SOMETIMES)
542       n_print ("    Availability: Sometimes\n");
543     else if (padtemplate->presence == GST_PAD_REQUEST) {
544       n_print ("    Availability: On request\n");
545       n_print ("      Has request_new_pad() function: %s\n",
546           GST_DEBUG_FUNCPTR_NAME (gstelement_class->request_new_pad));
547     } else
548       n_print ("    Availability: UNKNOWN!!!\n");
549
550     if (padtemplate->static_caps.string) {
551       n_print ("    Capabilities:\n");
552       print_caps (gst_static_caps_get (&padtemplate->static_caps), "      ");
553     }
554
555     n_print ("\n");
556   }
557 }
558
559 static void
560 print_element_flag_info (GstElement * element)
561 {
562   gboolean have_flags = FALSE;
563
564   n_print ("\n");
565   n_print ("Element Flags:\n");
566
567   if (!have_flags)
568     n_print ("  no flags set\n");
569
570   if (GST_IS_BIN (element)) {
571     n_print ("\n");
572     n_print ("Bin Flags:\n");
573     if (!have_flags)
574       n_print ("  no flags set\n");
575   }
576 }
577
578 static void
579 print_implementation_info (GstElement * element)
580 {
581   GstObjectClass *gstobject_class;
582   GstElementClass *gstelement_class;
583
584   gstobject_class = GST_OBJECT_CLASS (G_OBJECT_GET_CLASS (element));
585   gstelement_class = GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element));
586
587   n_print ("\n");
588   n_print ("Element Implementation:\n");
589
590   n_print ("  No loopfunc(), must be chain-based or not configured yet\n");
591
592   n_print ("  Has change_state() function: %s\n",
593       GST_DEBUG_FUNCPTR_NAME (gstelement_class->change_state));
594 #ifndef GST_DISABLE_LOADSAVE
595   n_print ("  Has custom save_thyself() function: %s\n",
596       GST_DEBUG_FUNCPTR_NAME (gstobject_class->save_thyself));
597   n_print ("  Has custom restore_thyself() function: %s\n",
598       GST_DEBUG_FUNCPTR_NAME (gstobject_class->restore_thyself));
599 #endif
600 }
601
602 static void
603 print_clocking_info (GstElement * element)
604 {
605   if (!gst_element_requires_clock (element) &&
606       !(gst_element_provides_clock (element) &&
607           gst_element_get_clock (element))) {
608     n_print ("\n");
609     n_print ("Element has no clocking capabilities.");
610     return;
611   }
612
613   n_print ("\n");
614   n_print ("Clocking Interaction:\n");
615   if (gst_element_requires_clock (element)) {
616     n_print ("  element requires a clock\n");
617   }
618
619   if (gst_element_provides_clock (element)) {
620     GstClock *clock;
621
622     clock = gst_element_get_clock (element);
623     if (clock)
624       n_print ("  element provides a clock: %s\n", GST_OBJECT_NAME (clock));
625     else
626       n_print ("  element is supposed to provide a clock but returned NULL\n");
627   }
628 }
629
630 #ifndef GST_DISABLE_INDEX
631 static void
632 print_index_info (GstElement * element)
633 {
634   if (gst_element_is_indexable (element)) {
635     n_print ("\n");
636     n_print ("Indexing capabilities:\n");
637     n_print ("  element can do indexing\n");
638   } else {
639     n_print ("\n");
640     n_print ("Element has no indexing capabilities.\n");
641   }
642 }
643 #else
644 static void
645 print_index_info (GstElement * element)
646 {
647 }
648 #endif
649
650 static void
651 print_pad_info (GstElement * element)
652 {
653   const GList *pads;
654   GstPad *pad;
655
656   n_print ("\n");
657   n_print ("Pads:\n");
658
659   if (!element->numpads) {
660     n_print ("  none\n");
661     return;
662   }
663
664   pads = element->pads;
665   while (pads) {
666     pad = GST_PAD (pads->data);
667     pads = g_list_next (pads);
668
669     n_print ("");
670
671     if (gst_pad_get_direction (pad) == GST_PAD_SRC)
672       g_print ("  SRC: '%s'", gst_pad_get_name (pad));
673     else if (gst_pad_get_direction (pad) == GST_PAD_SINK)
674       g_print ("  SINK: '%s'", gst_pad_get_name (pad));
675     else
676       g_print ("  UNKNOWN!!!: '%s'", gst_pad_get_name (pad));
677
678     g_print ("\n");
679
680     n_print ("    Implementation:\n");
681     if (pad->chainfunc)
682       n_print ("      Has chainfunc(): %s\n",
683           GST_DEBUG_FUNCPTR_NAME (pad->chainfunc));
684     if (pad->getrangefunc)
685       n_print ("      Has getrangefunc(): %s\n",
686           GST_DEBUG_FUNCPTR_NAME (pad->getrangefunc));
687     if (pad->eventfunc != gst_pad_event_default)
688       n_print ("      Has custom eventfunc(): %s\n",
689           GST_DEBUG_FUNCPTR_NAME (pad->eventfunc));
690     if (pad->queryfunc != gst_pad_query_default)
691       n_print ("      Has custom queryfunc(): %s\n",
692           GST_DEBUG_FUNCPTR_NAME (pad->queryfunc));
693     if (pad->querytypefunc != gst_pad_get_query_types_default) {
694       n_print ("        Provides query types:\n");
695       print_query_types (gst_pad_get_query_types (pad));
696     }
697
698     if (pad->intlinkfunc != gst_pad_get_internal_links_default)
699       n_print ("      Has custom intconnfunc(): %s\n",
700           GST_DEBUG_FUNCPTR_NAME (pad->intlinkfunc));
701
702     if (pad->bufferallocfunc)
703       n_print ("      Has bufferallocfunc(): %s\n",
704           GST_DEBUG_FUNCPTR_NAME (pad->bufferallocfunc));
705
706     if (pad->padtemplate)
707       n_print ("    Pad Template: '%s'\n", pad->padtemplate->name_template);
708
709     if (pad->caps) {
710       n_print ("    Capabilities:\n");
711       print_caps (pad->caps, "      ");
712     }
713   }
714 }
715
716 #if 0
717 static gint
718 compare_signal_names (GSignalQuery * a, GSignalQuery * b)
719 {
720   return strcmp (a->signal_name, b->signal_name);
721 }
722 #endif
723
724 static void
725 print_signal_info (GstElement * element)
726 {
727   /* Signals/Actions Block */
728   guint *signals;
729   guint nsignals;
730   gint i = 0, j, k;
731   GSignalQuery *query = NULL;
732   GType type;
733   GSList *found_signals, *l;
734
735   for (k = 0; k < 2; k++) {
736     found_signals = NULL;
737     for (type = G_OBJECT_TYPE (element); type; type = g_type_parent (type)) {
738       if (type == GST_TYPE_ELEMENT || type == GST_TYPE_OBJECT)
739         break;
740
741       if (type == GST_TYPE_BIN && G_OBJECT_TYPE (element) != GST_TYPE_BIN)
742         continue;
743
744       signals = g_signal_list_ids (type, &nsignals);
745       for (i = 0; i < nsignals; i++) {
746         query = g_new0 (GSignalQuery, 1);
747         g_signal_query (signals[i], query);
748
749         if ((k == 0 && !(query->signal_flags & G_SIGNAL_ACTION)) ||
750             (k == 1 && (query->signal_flags & G_SIGNAL_ACTION)))
751           found_signals = g_slist_append (found_signals, query);
752       }
753     }
754
755     if (found_signals) {
756       n_print ("\n");
757       if (k == 0)
758         n_print ("Element Signals:\n");
759       else
760         n_print ("Element Actions:\n");
761     } else {
762       continue;
763     }
764
765     for (l = found_signals; l; l = l->next) {
766       gchar *indent;
767       int indent_len;
768
769       query = (GSignalQuery *) l->data;
770       indent_len = strlen (query->signal_name) +
771           strlen (g_type_name (query->return_type)) + 24;
772
773       indent = g_new0 (gchar, indent_len + 1);
774       memset (indent, ' ', indent_len);
775
776       n_print ("  \"%s\" :  %s user_function (%s* object",
777           query->signal_name,
778           g_type_name (query->return_type), g_type_name (type));
779
780       for (j = 0; j < query->n_params; j++) {
781         if (G_TYPE_IS_FUNDAMENTAL (query->param_types[j])) {
782           g_print (",\n%s%s%s arg%d", _name, indent,
783               g_type_name (query->param_types[j]), j);
784         } else {
785           g_print (",\n%s%s%s* arg%d", _name, indent,
786               g_type_name (query->param_types[j]), j);
787         }
788       }
789
790       if (k == 0)
791         g_print (",\n%s%sgpointer user_data);\n", _name, indent);
792       else
793         g_print (");\n");
794
795       g_free (indent);
796     }
797
798     if (found_signals) {
799       g_slist_foreach (found_signals, (GFunc) g_free, NULL);
800       g_slist_free (found_signals);
801     }
802   }
803 }
804
805 static void
806 print_children_info (GstElement * element)
807 {
808   GList *children;
809
810   if (!GST_IS_BIN (element))
811     return;
812
813   children = (GList *) GST_BIN (element)->children;
814   if (children) {
815     n_print ("\n");
816     g_print ("Children:\n");
817   }
818
819   while (children) {
820     n_print ("  %s\n", GST_ELEMENT_NAME (GST_ELEMENT (children->data)));
821     children = g_list_next (children);
822   }
823 }
824
825 static void
826 print_element_list (gboolean print_all)
827 {
828   GList *plugins, *orig_plugins;
829
830   orig_plugins = plugins = gst_default_registry_get_plugin_list ();
831   while (plugins) {
832     GList *features, *orig_features;
833     GstPlugin *plugin;
834
835     plugin = (GstPlugin *) (plugins->data);
836     plugins = g_list_next (plugins);
837
838     orig_features = features =
839         gst_registry_get_feature_list_by_plugin (gst_registry_get_default (),
840         plugin->desc.name);
841     while (features) {
842       GstPluginFeature *feature;
843
844       feature = GST_PLUGIN_FEATURE (features->data);
845
846       if (GST_IS_ELEMENT_FACTORY (feature)) {
847         GstElementFactory *factory;
848
849         factory = GST_ELEMENT_FACTORY (feature);
850         if (print_all)
851           print_element_info (factory, TRUE);
852         else
853           g_print ("%s:  %s: %s\n", plugin->desc.name,
854               GST_PLUGIN_FEATURE_NAME (factory), factory->details.longname);
855       }
856 #ifndef GST_DISABLE_INDEX
857       else if (GST_IS_INDEX_FACTORY (feature)) {
858         GstIndexFactory *factory;
859
860         factory = GST_INDEX_FACTORY (feature);
861         if (!print_all)
862           g_print ("%s:  %s: %s\n", plugin->desc.name,
863               GST_PLUGIN_FEATURE_NAME (factory), factory->longdesc);
864       }
865 #endif
866       else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
867         GstTypeFindFactory *factory;
868
869         factory = GST_TYPE_FIND_FACTORY (feature);
870         if (!print_all)
871           g_print ("%s: %s: ", plugin->desc.name,
872               gst_plugin_feature_get_name (feature));
873         if (factory->extensions) {
874           guint i = 0;
875
876           while (factory->extensions[i]) {
877             if (!print_all)
878               g_print ("%s%s", i > 0 ? ", " : "", factory->extensions[i]);
879             i++;
880           }
881           if (!print_all)
882             g_print ("\n");
883         } else {
884           if (!print_all)
885             g_print ("no extensions\n");
886         }
887       } else {
888         if (!print_all)
889           n_print ("%s:  %s (%s)\n", plugin->desc.name,
890               GST_PLUGIN_FEATURE_NAME (feature),
891               g_type_name (G_OBJECT_TYPE (feature)));
892       }
893
894       features = g_list_next (features);
895     }
896
897     gst_plugin_feature_list_free (orig_features);
898   }
899
900   gst_plugin_list_free (plugins);
901 }
902
903 static void
904 print_plugin_info (GstPlugin * plugin)
905 {
906   n_print ("Plugin Details:\n");
907   n_print ("  Name:\t\t\t%s\n", plugin->desc.name);
908   n_print ("  Description:\t\t%s\n", plugin->desc.description);
909   n_print ("  Filename:\t\t%s\n",
910       plugin->filename ? plugin->filename : "(null)");
911   n_print ("  Version:\t\t%s\n", plugin->desc.version);
912   n_print ("  License:\t\t%s\n", plugin->desc.license);
913   n_print ("  Source module:\t%s\n", plugin->desc.source);
914   n_print ("  Binary package:\t%s\n", plugin->desc.package);
915   n_print ("  Origin URL:\t\t%s\n", plugin->desc.origin);
916   n_print ("\n");
917 }
918
919 static void
920 print_plugin_features (GstPlugin * plugin)
921 {
922   GList *features;
923   gint num_features = 0;
924   gint num_elements = 0;
925   gint num_types = 0;
926   gint num_indexes = 0;
927   gint num_other = 0;
928
929   features =
930       gst_registry_get_feature_list_by_plugin (gst_registry_get_default (),
931       plugin->desc.name);
932
933   while (features) {
934     GstPluginFeature *feature;
935
936     feature = GST_PLUGIN_FEATURE (features->data);
937
938     if (GST_IS_ELEMENT_FACTORY (feature)) {
939       GstElementFactory *factory;
940
941       factory = GST_ELEMENT_FACTORY (feature);
942       n_print ("  %s: %s\n", GST_PLUGIN_FEATURE_NAME (factory),
943           factory->details.longname);
944       num_elements++;
945     }
946 #ifndef GST_DISABLE_INDEX
947     else if (GST_IS_INDEX_FACTORY (feature)) {
948       GstIndexFactory *factory;
949
950       factory = GST_INDEX_FACTORY (feature);
951       n_print ("  %s: %s\n", GST_OBJECT_NAME (factory), factory->longdesc);
952       num_indexes++;
953     }
954 #endif
955     else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
956       GstTypeFindFactory *factory;
957
958       factory = GST_TYPE_FIND_FACTORY (feature);
959       if (factory->extensions) {
960         guint i = 0;
961
962         g_print ("%s type: ", plugin->desc.name);
963         while (factory->extensions[i]) {
964           g_print ("%s%s", i > 0 ? ", " : "", factory->extensions[i]);
965           i++;
966         }
967         g_print ("\n");
968       } else
969         g_print ("%s type: N/A\n", plugin->desc.name);
970
971       num_types++;
972     } else {
973       n_print ("  %s (%s)\n", gst_object_get_name (GST_OBJECT (feature)),
974           g_type_name (G_OBJECT_TYPE (feature)));
975       num_other++;
976     }
977     num_features++;
978     features = g_list_next (features);
979   }
980   n_print ("\n");
981   n_print ("  %d features:\n", num_features);
982   if (num_elements > 0)
983     n_print ("  +-- %d elements\n", num_elements);
984   if (num_types > 0)
985     n_print ("  +-- %d types\n", num_types);
986   if (num_indexes > 0)
987     n_print ("  +-- %d indexes\n", num_indexes);
988   if (num_other > 0)
989     n_print ("  +-- %d other objects\n", num_other);
990
991   n_print ("\n");
992 }
993
994 static int
995 print_element_features (const gchar * element_name)
996 {
997   GstPluginFeature *feature;
998
999   /* FIXME implement other pretty print function for these */
1000 #ifndef GST_DISABLE_INDEX
1001   feature = gst_default_registry_find_feature (element_name,
1002       GST_TYPE_INDEX_FACTORY);
1003   if (feature) {
1004     n_print ("%s: an index\n", element_name);
1005     return 0;
1006   }
1007 #endif
1008   feature = gst_default_registry_find_feature (element_name,
1009       GST_TYPE_TYPE_FIND_FACTORY);
1010   if (feature) {
1011     n_print ("%s: a typefind function\n", element_name);
1012     return 0;
1013   }
1014 #ifndef GST_DISABLE_URI
1015   feature = gst_default_registry_find_feature (element_name,
1016       GST_TYPE_URI_HANDLER);
1017   if (feature) {
1018     n_print ("%s: an uri handler\n", element_name);
1019     return 0;
1020   }
1021 #endif
1022
1023   return -1;
1024 }
1025
1026 static int
1027 print_element_info (GstElementFactory * factory, gboolean print_names)
1028 {
1029   GstElement *element;
1030   gint maxlevel = 0;
1031
1032   factory =
1033       GST_ELEMENT_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE
1034           (factory)));
1035
1036   element = gst_element_factory_create (factory, NULL);
1037   if (!element) {
1038     g_print ("couldn't construct element for some reason\n");
1039     return -1;
1040   }
1041
1042   if (print_names)
1043     _name = g_strdup_printf ("%s: ", GST_PLUGIN_FEATURE (factory)->name);
1044   else
1045     _name = "";
1046
1047   print_factory_details_info (factory);
1048   if (GST_PLUGIN_FEATURE (factory)->plugin_name) {
1049     GstPlugin *plugin;
1050
1051     plugin = gst_registry_find_plugin (gst_registry_get_default (),
1052         GST_PLUGIN_FEATURE (factory)->plugin_name);
1053     if (plugin) {
1054       print_plugin_info (plugin);
1055     }
1056   }
1057
1058   print_hierarchy (G_OBJECT_TYPE (element), 0, &maxlevel);
1059   print_interfaces (G_OBJECT_TYPE (element));
1060
1061   print_pad_templates_info (element, factory);
1062   print_element_flag_info (element);
1063   print_implementation_info (element);
1064   print_clocking_info (element);
1065   print_index_info (element);
1066   print_pad_info (element);
1067   print_element_properties_info (element);
1068   print_signal_info (element);
1069   print_children_info (element);
1070
1071   gst_object_unref (factory);
1072
1073   if (_name != "")
1074     g_free (_name);
1075
1076   return 0;
1077 }
1078
1079 int
1080 main (int argc, char *argv[])
1081 {
1082   gboolean print_all = FALSE;
1083   struct poptOption options[] = {
1084     {"print-all", 'a', POPT_ARG_NONE | POPT_ARGFLAG_STRIP, &print_all, 0,
1085         N_("Print all elements"), NULL},
1086     POPT_TABLEEND
1087   };
1088
1089 #ifdef GETTEXT_PACKAGE
1090   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
1091   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1092   textdomain (GETTEXT_PACKAGE);
1093 #endif
1094
1095   gst_init_with_popt_table (&argc, &argv, options);
1096
1097   if (print_all && argc > 2) {
1098     g_print ("-a requires no extra arguments\n");
1099     return 1;
1100   }
1101
1102   /* if no arguments, print out list of elements */
1103   if (argc == 1 || print_all) {
1104     print_element_list (print_all);
1105     /* else we try to get a factory */
1106   } else {
1107     GstElementFactory *factory;
1108     GstPlugin *plugin;
1109     const char *arg = argv[argc - 1];
1110     int retval;
1111
1112     factory = gst_element_factory_find (arg);
1113     /* if there's a factory, print out the info */
1114     if (factory) {
1115       retval = print_element_info (factory, print_all);
1116     } else {
1117       retval = print_element_features (arg);
1118     }
1119
1120     /* otherwise check if it's a plugin */
1121     if (retval) {
1122       plugin = gst_default_registry_find_plugin (arg);
1123
1124       /* if there is such a plugin, print out info */
1125       if (plugin) {
1126         print_plugin_info (plugin);
1127         print_plugin_features (plugin);
1128       } else {
1129         g_print ("No such element or plugin '%s'\n", arg);
1130         return -1;
1131       }
1132     }
1133   }
1134
1135   return 0;
1136 }