remove query types
[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 "tools.h"
29
30 #include <string.h>
31 #include <locale.h>
32 #include <glib/gprintf.h>
33
34 static char *_name = NULL;
35
36 static int print_element_info (GstElementFactory * factory,
37     gboolean print_names);
38
39 static void
40 n_print (const char *format, ...)
41 {
42   va_list args;
43
44   if (_name)
45     g_print ("%s", _name);
46
47   va_start (args, format);
48   g_vprintf (format, args);
49   va_end (args);
50 }
51
52 static gboolean
53 print_field (GQuark field, const GValue * value, gpointer pfx)
54 {
55   gchar *str = gst_value_serialize (value);
56
57   n_print ("%s  %15s: %s\n", (gchar *) pfx, g_quark_to_string (field), str);
58   g_free (str);
59   return TRUE;
60 }
61
62 static void
63 print_caps (const GstCaps * caps, const gchar * pfx)
64 {
65   guint i;
66
67   g_return_if_fail (caps != NULL);
68
69   if (gst_caps_is_any (caps)) {
70     n_print ("%sANY\n", pfx);
71     return;
72   }
73   if (gst_caps_is_empty (caps)) {
74     n_print ("%sEMPTY\n", pfx);
75     return;
76   }
77
78   for (i = 0; i < gst_caps_get_size (caps); i++) {
79     GstStructure *structure = gst_caps_get_structure (caps, i);
80
81     n_print ("%s%s\n", pfx, gst_structure_get_name (structure));
82     gst_structure_foreach (structure, print_field, (gpointer) pfx);
83   }
84 }
85
86 #if 0
87 static void
88 print_formats (const GstFormat * formats)
89 {
90   while (formats && *formats) {
91     const GstFormatDefinition *definition;
92
93     definition = gst_format_get_details (*formats);
94     if (definition)
95       n_print ("\t\t(%d):\t%s (%s)\n", *formats,
96           definition->nick, definition->description);
97     else
98       n_print ("\t\t(%d):\tUnknown format\n", *formats);
99
100     formats++;
101   }
102 }
103
104 static void
105 print_event_masks (const GstEventMask * masks)
106 {
107   GType event_type;
108   GEnumClass *klass;
109   GType event_flags;
110   GFlagsClass *flags_class = NULL;
111
112   event_type = gst_event_type_get_type ();
113   klass = (GEnumClass *) g_type_class_ref (event_type);
114
115   while (masks && masks->type) {
116     GEnumValue *value;
117     gint flags = 0, index = 0;
118
119     switch (masks->type) {
120       case GST_EVENT_SEEK:
121         flags = masks->flags;
122         event_flags = gst_seek_type_get_type ();
123         flags_class = (GFlagsClass *) g_type_class_ref (event_flags);
124         break;
125       default:
126         break;
127     }
128
129     value = g_enum_get_value (klass, masks->type);
130     g_print ("\t\t%s ", value->value_nick);
131
132     while (flags) {
133       GFlagsValue *value;
134
135       if (flags & 1) {
136         value = g_flags_get_first_value (flags_class, 1 << index);
137
138         if (value)
139           g_print ("| %s ", value->value_nick);
140         else
141           g_print ("| ? ");
142       }
143       flags >>= 1;
144       index++;
145     }
146     g_print ("\n");
147
148     masks++;
149   }
150 }
151 #endif
152
153 static const char *
154 get_rank_name (char *s, gint rank)
155 {
156   static const int ranks[4] = {
157     GST_RANK_NONE, GST_RANK_MARGINAL, GST_RANK_SECONDARY, GST_RANK_PRIMARY
158   };
159   static const char *rank_names[4] = { "none", "marginal", "secondary",
160     "primary"
161   };
162   int i;
163   int best_i;
164
165   best_i = 0;
166   for (i = 0; i < 4; i++) {
167     if (rank == ranks[i])
168       return rank_names[i];
169     if (abs (rank - ranks[i]) < abs (rank - ranks[best_i])) {
170       best_i = i;
171     }
172   }
173
174   sprintf (s, "%s %c %d", rank_names[best_i],
175       (rank - ranks[best_i] > 0) ? '+' : '-', abs (ranks[best_i] - rank));
176
177   return s;
178 }
179
180 static gboolean
181 print_factory_details_metadata (GQuark field_id, const GValue * value,
182     gpointer user_data)
183 {
184   gchar *val = g_strdup_value_contents (value);
185   gchar *key = g_strdup (g_quark_to_string (field_id));
186
187   key[0] = g_ascii_toupper (key[0]);
188   n_print ("  %s:\t\t%s\n", key, val);
189   g_free (val);
190   g_free (key);
191   return TRUE;
192 }
193
194 static void
195 print_factory_details_info (GstElementFactory * factory)
196 {
197   char s[20];
198
199   n_print ("Factory Details:\n");
200   n_print ("  Rank:\t\t%s (%d)\n",
201       get_rank_name (s, GST_PLUGIN_FEATURE (factory)->rank),
202       GST_PLUGIN_FEATURE (factory)->rank);
203   gst_structure_foreach ((GstStructure *) factory->metadata,
204       print_factory_details_metadata, NULL);
205   n_print ("\n");
206 }
207
208 static void
209 print_hierarchy (GType type, gint level, gint * maxlevel)
210 {
211   GType parent;
212   gint i;
213
214   parent = g_type_parent (type);
215
216   *maxlevel = *maxlevel + 1;
217   level++;
218
219   if (parent)
220     print_hierarchy (parent, level, maxlevel);
221
222   if (_name)
223     g_print ("%s", _name);
224
225   for (i = 1; i < *maxlevel - level; i++)
226     g_print ("      ");
227   if (*maxlevel - level)
228     g_print (" +----");
229
230   g_print ("%s\n", g_type_name (type));
231
232   if (level == 1)
233     n_print ("\n");
234 }
235
236 static void
237 print_interfaces (GType type)
238 {
239   guint n_ifaces;
240   GType *iface, *ifaces = g_type_interfaces (type, &n_ifaces);
241
242   if (ifaces) {
243     if (n_ifaces) {
244       if (_name)
245         g_print ("%s", _name);
246       g_print (_("Implemented Interfaces:\n"));
247       iface = ifaces;
248       while (*iface) {
249         if (_name)
250           g_print ("%s", _name);
251         g_print ("  %s\n", g_type_name (*iface));
252         iface++;
253       }
254       if (_name)
255         g_print ("%s", _name);
256       g_print ("\n");
257     }
258     g_free (ifaces);
259   }
260 }
261
262 static gchar *
263 flags_to_string (GFlagsValue * vals, guint flags)
264 {
265   GString *s = NULL;
266   guint flags_left, i;
267
268   /* first look for an exact match and count the number of values */
269   for (i = 0; vals[i].value_name != NULL; ++i) {
270     if (vals[i].value == flags)
271       return g_strdup (vals[i].value_nick);
272   }
273
274   s = g_string_new (NULL);
275
276   /* we assume the values are sorted from lowest to highest value */
277   flags_left = flags;
278   while (i > 0) {
279     --i;
280     if (vals[i].value != 0 && (flags_left & vals[i].value) == vals[i].value) {
281       if (s->len > 0)
282         g_string_append_c (s, '+');
283       g_string_append (s, vals[i].value_nick);
284       flags_left -= vals[i].value;
285       if (flags_left == 0)
286         break;
287     }
288   }
289
290   if (s->len == 0)
291     g_string_assign (s, "(none)");
292
293   return g_string_free (s, FALSE);
294 }
295
296 #define KNOWN_PARAM_FLAGS \
297   (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY | \
298   G_PARAM_LAX_VALIDATION |  G_PARAM_STATIC_STRINGS | \
299   G_PARAM_READABLE | G_PARAM_WRITABLE | GST_PARAM_CONTROLLABLE | \
300   GST_PARAM_MUTABLE_PLAYING | GST_PARAM_MUTABLE_PAUSED | \
301   GST_PARAM_MUTABLE_READY)
302
303 static void
304 print_element_properties_info (GstElement * element)
305 {
306   GParamSpec **property_specs;
307   guint num_properties, i;
308   gboolean readable;
309   gboolean first_flag;
310
311   property_specs = g_object_class_list_properties
312       (G_OBJECT_GET_CLASS (element), &num_properties);
313   n_print ("\n");
314   n_print ("Element Properties:\n");
315
316   for (i = 0; i < num_properties; i++) {
317     GValue value = { 0, };
318     GParamSpec *param = property_specs[i];
319
320     readable = FALSE;
321
322     g_value_init (&value, param->value_type);
323
324     n_print ("  %-20s: %s\n", g_param_spec_get_name (param),
325         g_param_spec_get_blurb (param));
326
327     first_flag = TRUE;
328     n_print ("%-23.23s flags: ", "");
329     if (param->flags & G_PARAM_READABLE) {
330       g_object_get_property (G_OBJECT (element), param->name, &value);
331       readable = TRUE;
332       g_print ("%s%s", (first_flag) ? "" : ", ", _("readable"));
333       first_flag = FALSE;
334     }
335     if (param->flags & G_PARAM_WRITABLE) {
336       g_print ("%s%s", (first_flag) ? "" : ", ", _("writable"));
337       first_flag = FALSE;
338     }
339     if (param->flags & GST_PARAM_CONTROLLABLE) {
340       g_print (", %s", _("controllable"));
341       first_flag = FALSE;
342     }
343     if (param->flags & GST_PARAM_MUTABLE_PLAYING) {
344       g_print (", %s", _("changeable in NULL, READY, PAUSED or PLAYING state"));
345     } else if (param->flags & GST_PARAM_MUTABLE_PAUSED) {
346       g_print (", %s", _("changeable only in NULL, READY or PAUSED state"));
347     } else if (param->flags & GST_PARAM_MUTABLE_READY) {
348       g_print (", %s", _("changeable only in NULL or READY state"));
349     }
350     if (param->flags & ~KNOWN_PARAM_FLAGS) {
351       g_print ("%s0x%0x", (first_flag) ? "" : ", ",
352           param->flags & ~KNOWN_PARAM_FLAGS);
353     }
354     n_print ("\n");
355
356     switch (G_VALUE_TYPE (&value)) {
357       case G_TYPE_STRING:
358       {
359         GParamSpecString *pstring = G_PARAM_SPEC_STRING (param);
360
361         n_print ("%-23.23s String. ", "");
362
363         if (pstring->default_value == NULL)
364           g_print ("Default: null ");
365         else
366           g_print ("Default: \"%s\" ", pstring->default_value);
367
368         if (readable) {
369           const char *string_val = g_value_get_string (&value);
370
371           if (string_val == NULL)
372             g_print ("Current: null");
373           else
374             g_print ("Current: \"%s\"", string_val);
375         }
376         break;
377       }
378       case G_TYPE_BOOLEAN:
379       {
380         GParamSpecBoolean *pboolean = G_PARAM_SPEC_BOOLEAN (param);
381
382         n_print ("%-23.23s Boolean. ", "");
383         g_print ("Default: %s ", (pboolean->default_value ? "true" : "false"));
384         if (readable)
385           g_print ("Current: %s",
386               (g_value_get_boolean (&value) ? "true" : "false"));
387         break;
388       }
389       case G_TYPE_ULONG:
390       {
391         GParamSpecULong *pulong = G_PARAM_SPEC_ULONG (param);
392
393         n_print ("%-23.23s Unsigned Long. ", "");
394         g_print ("Range: %lu - %lu Default: %lu ",
395             pulong->minimum, pulong->maximum, pulong->default_value);
396         if (readable)
397           g_print ("Current: %lu", g_value_get_ulong (&value));
398         break;
399       }
400       case G_TYPE_LONG:
401       {
402         GParamSpecLong *plong = G_PARAM_SPEC_LONG (param);
403
404         n_print ("%-23.23s Long. ", "");
405         g_print ("Range: %ld - %ld Default: %ld ",
406             plong->minimum, plong->maximum, plong->default_value);
407         if (readable)
408           g_print ("Current: %ld", g_value_get_long (&value));
409         break;
410       }
411       case G_TYPE_UINT:
412       {
413         GParamSpecUInt *puint = G_PARAM_SPEC_UINT (param);
414
415         n_print ("%-23.23s Unsigned Integer. ", "");
416         g_print ("Range: %u - %u Default: %u ",
417             puint->minimum, puint->maximum, puint->default_value);
418         if (readable)
419           g_print ("Current: %u", g_value_get_uint (&value));
420         break;
421       }
422       case G_TYPE_INT:
423       {
424         GParamSpecInt *pint = G_PARAM_SPEC_INT (param);
425
426         n_print ("%-23.23s Integer. ", "");
427         g_print ("Range: %d - %d Default: %d ",
428             pint->minimum, pint->maximum, pint->default_value);
429         if (readable)
430           g_print ("Current: %d", g_value_get_int (&value));
431         break;
432       }
433       case G_TYPE_UINT64:
434       {
435         GParamSpecUInt64 *puint64 = G_PARAM_SPEC_UINT64 (param);
436
437         n_print ("%-23.23s Unsigned Integer64. ", "");
438         g_print ("Range: %" G_GUINT64_FORMAT " - %" G_GUINT64_FORMAT
439             " Default: %" G_GUINT64_FORMAT " ",
440             puint64->minimum, puint64->maximum, puint64->default_value);
441         if (readable)
442           g_print ("Current: %" G_GUINT64_FORMAT, g_value_get_uint64 (&value));
443         break;
444       }
445       case G_TYPE_INT64:
446       {
447         GParamSpecInt64 *pint64 = G_PARAM_SPEC_INT64 (param);
448
449         n_print ("%-23.23s Integer64. ", "");
450         g_print ("Range: %" G_GINT64_FORMAT " - %" G_GINT64_FORMAT
451             " Default: %" G_GINT64_FORMAT " ",
452             pint64->minimum, pint64->maximum, pint64->default_value);
453         if (readable)
454           g_print ("Current: %" G_GINT64_FORMAT, g_value_get_int64 (&value));
455         break;
456       }
457       case G_TYPE_FLOAT:
458       {
459         GParamSpecFloat *pfloat = G_PARAM_SPEC_FLOAT (param);
460
461         n_print ("%-23.23s Float. ", "");
462         g_print ("Range: %15.7g - %15.7g Default: %15.7g ",
463             pfloat->minimum, pfloat->maximum, pfloat->default_value);
464         if (readable)
465           g_print ("Current: %15.7g", g_value_get_float (&value));
466         break;
467       }
468       case G_TYPE_DOUBLE:
469       {
470         GParamSpecDouble *pdouble = G_PARAM_SPEC_DOUBLE (param);
471
472         n_print ("%-23.23s Double. ", "");
473         g_print ("Range: %15.7g - %15.7g Default: %15.7g ",
474             pdouble->minimum, pdouble->maximum, pdouble->default_value);
475         if (readable)
476           g_print ("Current: %15.7g", g_value_get_double (&value));
477         break;
478       }
479       default:
480         if (param->value_type == GST_TYPE_CAPS) {
481           const GstCaps *caps = gst_value_get_caps (&value);
482
483           if (!caps)
484             n_print ("%-23.23s Caps (NULL)", "");
485           else {
486             print_caps (caps, "                           ");
487           }
488         } else if (G_IS_PARAM_SPEC_ENUM (param)) {
489           GParamSpecEnum *penum = G_PARAM_SPEC_ENUM (param);
490           GEnumValue *values;
491           guint j = 0;
492           gint enum_value;
493           const gchar *def_val_nick = "", *cur_val_nick = "";
494
495           values = G_ENUM_CLASS (g_type_class_ref (param->value_type))->values;
496           enum_value = g_value_get_enum (&value);
497
498           while (values[j].value_name) {
499             if (values[j].value == enum_value)
500               cur_val_nick = values[j].value_nick;
501             if (values[j].value == penum->default_value)
502               def_val_nick = values[j].value_nick;
503             j++;
504           }
505
506           n_print
507               ("%-23.23s Enum \"%s\" Default: %d, \"%s\" Current: %d, \"%s\"",
508               "", g_type_name (G_VALUE_TYPE (&value)), penum->default_value,
509               def_val_nick, enum_value, cur_val_nick);
510
511           j = 0;
512           while (values[j].value_name) {
513             g_print ("\n");
514             if (_name)
515               g_print ("%s", _name);
516             g_print ("%-23.23s    (%d): %-16s - %s", "",
517                 values[j].value, values[j].value_nick, values[j].value_name);
518             j++;
519           }
520           /* g_type_class_unref (ec); */
521         } else if (G_IS_PARAM_SPEC_FLAGS (param)) {
522           GParamSpecFlags *pflags = G_PARAM_SPEC_FLAGS (param);
523           GFlagsValue *vals;
524           gchar *cur, *def;
525
526           vals = pflags->flags_class->values;
527
528           cur = flags_to_string (vals, g_value_get_flags (&value));
529           def = flags_to_string (vals, pflags->default_value);
530
531           n_print
532               ("%-23.23s Flags \"%s\" Default: 0x%08x, \"%s\" Current: 0x%08x, \"%s\"",
533               "", g_type_name (G_VALUE_TYPE (&value)), pflags->default_value,
534               def, g_value_get_flags (&value), cur);
535
536           while (vals[0].value_name) {
537             g_print ("\n");
538             if (_name)
539               g_print ("%s", _name);
540             g_print ("%-23.23s    (0x%08x): %-16s - %s", "",
541                 vals[0].value, vals[0].value_nick, vals[0].value_name);
542             ++vals;
543           }
544
545           g_free (cur);
546           g_free (def);
547         } else if (G_IS_PARAM_SPEC_OBJECT (param)) {
548           n_print ("%-23.23s Object of type \"%s\"", "",
549               g_type_name (param->value_type));
550         } else if (G_IS_PARAM_SPEC_BOXED (param)) {
551           n_print ("%-23.23s Boxed pointer of type \"%s\"", "",
552               g_type_name (param->value_type));
553         } else if (G_IS_PARAM_SPEC_POINTER (param)) {
554           if (param->value_type != G_TYPE_POINTER) {
555             n_print ("%-23.23s Pointer of type \"%s\".", "",
556                 g_type_name (param->value_type));
557           } else {
558             n_print ("%-23.23s Pointer.", "");
559           }
560         } else if (param->value_type == G_TYPE_VALUE_ARRAY) {
561           GParamSpecValueArray *pvarray = G_PARAM_SPEC_VALUE_ARRAY (param);
562
563           if (pvarray->element_spec) {
564             n_print ("%-23.23s Array of GValues of type \"%s\"", "",
565                 g_type_name (pvarray->element_spec->value_type));
566           } else {
567             n_print ("%-23.23s Array of GValues", "");
568           }
569         } else if (GST_IS_PARAM_SPEC_FRACTION (param)) {
570           GstParamSpecFraction *pfraction = GST_PARAM_SPEC_FRACTION (param);
571
572           n_print ("%-23.23s Fraction. ", "");
573
574           g_print ("Range: %d/%d - %d/%d Default: %d/%d ",
575               pfraction->min_num, pfraction->min_den,
576               pfraction->max_num, pfraction->max_den,
577               pfraction->def_num, pfraction->def_den);
578           if (readable)
579             g_print ("Current: %d/%d",
580                 gst_value_get_fraction_numerator (&value),
581                 gst_value_get_fraction_denominator (&value));
582
583         } else {
584           n_print ("%-23.23s Unknown type %ld \"%s\"", "", param->value_type,
585               g_type_name (param->value_type));
586         }
587         break;
588     }
589     if (!readable)
590       g_print (" Write only\n");
591     else
592       g_print ("\n");
593
594     g_value_reset (&value);
595   }
596   if (num_properties == 0)
597     n_print ("  none\n");
598
599   g_free (property_specs);
600 }
601
602 static void
603 print_pad_templates_info (GstElement * element, GstElementFactory * factory)
604 {
605   GstElementClass *gstelement_class;
606   const GList *pads;
607   GstStaticPadTemplate *padtemplate;
608
609   n_print ("Pad Templates:\n");
610   if (!factory->numpadtemplates) {
611     n_print ("  none\n");
612     return;
613   }
614
615   gstelement_class = GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element));
616
617   pads = factory->staticpadtemplates;
618   while (pads) {
619     padtemplate = (GstStaticPadTemplate *) (pads->data);
620     pads = g_list_next (pads);
621
622     if (padtemplate->direction == GST_PAD_SRC)
623       n_print ("  SRC template: '%s'\n", padtemplate->name_template);
624     else if (padtemplate->direction == GST_PAD_SINK)
625       n_print ("  SINK template: '%s'\n", padtemplate->name_template);
626     else
627       n_print ("  UNKNOWN!!! template: '%s'\n", padtemplate->name_template);
628
629     if (padtemplate->presence == GST_PAD_ALWAYS)
630       n_print ("    Availability: Always\n");
631     else if (padtemplate->presence == GST_PAD_SOMETIMES)
632       n_print ("    Availability: Sometimes\n");
633     else if (padtemplate->presence == GST_PAD_REQUEST) {
634       n_print ("    Availability: On request\n");
635       n_print ("      Has request_new_pad() function: %s\n",
636           GST_DEBUG_FUNCPTR_NAME (gstelement_class->request_new_pad));
637     } else
638       n_print ("    Availability: UNKNOWN!!!\n");
639
640     if (padtemplate->static_caps.string) {
641       n_print ("    Capabilities:\n");
642       print_caps (gst_static_caps_get (&padtemplate->static_caps), "      ");
643     }
644
645     n_print ("\n");
646   }
647 }
648
649 static void
650 print_element_flag_info (GstElement * element)
651 {
652   gboolean have_flags = FALSE;
653
654   n_print ("\n");
655   n_print ("Element Flags:\n");
656
657   if (!have_flags)
658     n_print ("  no flags set\n");
659
660   if (GST_IS_BIN (element)) {
661     n_print ("\n");
662     n_print ("Bin Flags:\n");
663     if (!have_flags)
664       n_print ("  no flags set\n");
665   }
666 }
667
668 static void
669 print_implementation_info (GstElement * element)
670 {
671   GstElementClass *gstelement_class;
672
673   gstelement_class = GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element));
674
675   n_print ("\n");
676   n_print ("Element Implementation:\n");
677
678   n_print ("  Has change_state() function: %s\n",
679       GST_DEBUG_FUNCPTR_NAME (gstelement_class->change_state));
680 }
681
682 static void
683 print_clocking_info (GstElement * element)
684 {
685   if (!gst_element_requires_clock (element) &&
686       !(gst_element_provides_clock (element) &&
687           gst_element_get_clock (element))) {
688     n_print ("\n");
689     n_print ("Element has no clocking capabilities.");
690     return;
691   }
692
693   n_print ("\n");
694   n_print ("Clocking Interaction:\n");
695   if (gst_element_requires_clock (element)) {
696     n_print ("  element requires a clock\n");
697   }
698
699   if (gst_element_provides_clock (element)) {
700     GstClock *clock;
701
702     clock = gst_element_get_clock (element);
703     if (clock)
704       n_print ("  element provides a clock: %s\n", GST_OBJECT_NAME (clock));
705     else
706       n_print ("  element is supposed to provide a clock but returned NULL\n");
707   }
708 }
709
710 static void
711 print_index_info (GstElement * element)
712 {
713   if (gst_element_is_indexable (element)) {
714     n_print ("\n");
715     n_print ("Indexing capabilities:\n");
716     n_print ("  element can do indexing\n");
717   } else {
718     n_print ("\n");
719     n_print ("Element has no indexing capabilities.\n");
720   }
721 }
722
723 static void
724 print_uri_handler_info (GstElement * element)
725 {
726   if (GST_IS_URI_HANDLER (element)) {
727     const gchar *uri_type;
728     gchar **uri_protocols;
729
730     if (gst_uri_handler_get_uri_type (GST_URI_HANDLER (element)) == GST_URI_SRC)
731       uri_type = "source";
732     else if (gst_uri_handler_get_uri_type (GST_URI_HANDLER (element)) ==
733         GST_URI_SINK)
734       uri_type = "sink";
735     else
736       uri_type = "unknown";
737
738     uri_protocols = gst_uri_handler_get_protocols (GST_URI_HANDLER (element));
739
740     n_print ("\n");
741     n_print ("URI handling capabilities:\n");
742     n_print ("  Element can act as %s.\n", uri_type);
743
744     if (uri_protocols && *uri_protocols) {
745       n_print ("  Supported URI protocols:\n");
746       for (; *uri_protocols != NULL; uri_protocols++)
747         n_print ("    %s\n", *uri_protocols);
748     } else {
749       n_print ("  No supported URI protocols\n");
750     }
751   } else {
752     n_print ("Element has no URI handling capabilities.\n");
753   }
754 }
755
756 static void
757 print_pad_info (GstElement * element)
758 {
759   const GList *pads;
760   GstPad *pad;
761
762   n_print ("\n");
763   n_print ("Pads:\n");
764
765   if (!element->numpads) {
766     n_print ("  none\n");
767     return;
768   }
769
770   pads = element->pads;
771   while (pads) {
772     gchar *name;
773     GstCaps *caps;
774
775     pad = GST_PAD (pads->data);
776     pads = g_list_next (pads);
777
778     n_print ("");
779
780     name = gst_pad_get_name (pad);
781     if (gst_pad_get_direction (pad) == GST_PAD_SRC)
782       g_print ("  SRC: '%s'", name);
783     else if (gst_pad_get_direction (pad) == GST_PAD_SINK)
784       g_print ("  SINK: '%s'", name);
785     else
786       g_print ("  UNKNOWN!!!: '%s'", name);
787
788     g_free (name);
789
790     g_print ("\n");
791
792     n_print ("    Implementation:\n");
793     if (pad->chainfunc)
794       n_print ("      Has chainfunc(): %s\n",
795           GST_DEBUG_FUNCPTR_NAME (pad->chainfunc));
796     if (pad->getrangefunc)
797       n_print ("      Has getrangefunc(): %s\n",
798           GST_DEBUG_FUNCPTR_NAME (pad->getrangefunc));
799     if (pad->eventfunc != gst_pad_event_default)
800       n_print ("      Has custom eventfunc(): %s\n",
801           GST_DEBUG_FUNCPTR_NAME (pad->eventfunc));
802     if (pad->queryfunc != gst_pad_query_default)
803       n_print ("      Has custom queryfunc(): %s\n",
804           GST_DEBUG_FUNCPTR_NAME (pad->queryfunc));
805
806     if (pad->iterintlinkfunc != gst_pad_iterate_internal_links_default)
807       n_print ("      Has custom iterintlinkfunc(): %s\n",
808           GST_DEBUG_FUNCPTR_NAME (pad->iterintlinkfunc));
809
810     if (pad->getcapsfunc)
811       n_print ("      Has getcapsfunc(): %s\n",
812           GST_DEBUG_FUNCPTR_NAME (pad->getcapsfunc));
813     /* gst_pad_acceptcaps_default is static :/ */
814     if (pad->acceptcapsfunc)
815       n_print ("      Has acceptcapsfunc(): %s\n",
816           GST_DEBUG_FUNCPTR_NAME (pad->acceptcapsfunc));
817     if (pad->fixatecapsfunc)
818       n_print ("      Has fixatecapsfunc(): %s\n",
819           GST_DEBUG_FUNCPTR_NAME (pad->fixatecapsfunc));
820
821
822     if (pad->padtemplate)
823       n_print ("    Pad Template: '%s'\n", pad->padtemplate->name_template);
824
825     caps = gst_pad_get_current_caps (pad);
826     if (caps) {
827       n_print ("    Capabilities:\n");
828       print_caps (caps, "      ");
829       gst_caps_unref (caps);
830     }
831   }
832 }
833
834 static gboolean
835 has_sometimes_template (GstElement * element)
836 {
837   GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
838   GList *l;
839
840   for (l = klass->padtemplates; l != NULL; l = l->next) {
841     if (GST_PAD_TEMPLATE (l->data)->presence == GST_PAD_SOMETIMES)
842       return TRUE;
843   }
844
845   return FALSE;
846 }
847
848 static void
849 print_signal_info (GstElement * element)
850 {
851   /* Signals/Actions Block */
852   guint *signals;
853   guint nsignals;
854   gint i = 0, j, k;
855   GSignalQuery *query = NULL;
856   GType type;
857   GSList *found_signals, *l;
858
859   for (k = 0; k < 2; k++) {
860     found_signals = NULL;
861
862     /* For elements that have sometimes pads, also list a few useful GstElement
863      * signals. Put these first, so element-specific ones come later. */
864     if (k == 0 && has_sometimes_template (element)) {
865       query = g_new0 (GSignalQuery, 1);
866       g_signal_query (g_signal_lookup ("pad-added", GST_TYPE_ELEMENT), query);
867       found_signals = g_slist_append (found_signals, query);
868       query = g_new0 (GSignalQuery, 1);
869       g_signal_query (g_signal_lookup ("pad-removed", GST_TYPE_ELEMENT), query);
870       found_signals = g_slist_append (found_signals, query);
871       query = g_new0 (GSignalQuery, 1);
872       g_signal_query (g_signal_lookup ("no-more-pads", GST_TYPE_ELEMENT),
873           query);
874       found_signals = g_slist_append (found_signals, query);
875     }
876
877     for (type = G_OBJECT_TYPE (element); type; type = g_type_parent (type)) {
878       if (type == GST_TYPE_ELEMENT || type == GST_TYPE_OBJECT)
879         break;
880
881       if (type == GST_TYPE_BIN && G_OBJECT_TYPE (element) != GST_TYPE_BIN)
882         continue;
883
884       signals = g_signal_list_ids (type, &nsignals);
885       for (i = 0; i < nsignals; i++) {
886         query = g_new0 (GSignalQuery, 1);
887         g_signal_query (signals[i], query);
888
889         if ((k == 0 && !(query->signal_flags & G_SIGNAL_ACTION)) ||
890             (k == 1 && (query->signal_flags & G_SIGNAL_ACTION)))
891           found_signals = g_slist_append (found_signals, query);
892         else
893           g_free (query);
894       }
895       g_free (signals);
896       signals = NULL;
897     }
898
899     if (found_signals) {
900       n_print ("\n");
901       if (k == 0)
902         n_print ("Element Signals:\n");
903       else
904         n_print ("Element Actions:\n");
905     } else {
906       continue;
907     }
908
909     for (l = found_signals; l; l = l->next) {
910       gchar *indent;
911       int indent_len;
912
913       query = (GSignalQuery *) l->data;
914       indent_len = strlen (query->signal_name) +
915           strlen (g_type_name (query->return_type)) + 24;
916
917       indent = g_new0 (gchar, indent_len + 1);
918       memset (indent, ' ', indent_len);
919
920       n_print ("  \"%s\" :  %s user_function (%s* object",
921           query->signal_name,
922           g_type_name (query->return_type), g_type_name (type));
923
924       for (j = 0; j < query->n_params; j++) {
925         if (_name)
926           g_print ("%s", _name);
927         if (G_TYPE_IS_FUNDAMENTAL (query->param_types[j])) {
928           g_print (",\n%s%s arg%d", indent,
929               g_type_name (query->param_types[j]), j);
930         } else if (G_TYPE_IS_ENUM (query->param_types[j])) {
931           g_print (",\n%s%s arg%d", indent,
932               g_type_name (query->param_types[j]), j);
933         } else {
934           g_print (",\n%s%s* arg%d", indent,
935               g_type_name (query->param_types[j]), j);
936         }
937       }
938
939       if (k == 0) {
940         if (_name)
941           g_print ("%s", _name);
942         g_print (",\n%sgpointer user_data);\n", indent);
943       } else
944         g_print (");\n");
945
946       g_free (indent);
947     }
948
949     if (found_signals) {
950       g_slist_foreach (found_signals, (GFunc) g_free, NULL);
951       g_slist_free (found_signals);
952     }
953   }
954 }
955
956 static void
957 print_children_info (GstElement * element)
958 {
959   GList *children;
960
961   if (!GST_IS_BIN (element))
962     return;
963
964   children = (GList *) GST_BIN (element)->children;
965   if (children) {
966     n_print ("\n");
967     g_print ("Children:\n");
968   }
969
970   while (children) {
971     n_print ("  %s\n", GST_ELEMENT_NAME (GST_ELEMENT (children->data)));
972     children = g_list_next (children);
973   }
974 }
975
976 static void
977 print_blacklist (void)
978 {
979   GList *plugins, *cur;
980   gint count = 0;
981
982   g_print ("%s\n", _("Blacklisted files:"));
983
984   plugins = gst_default_registry_get_plugin_list ();
985   for (cur = plugins; cur != NULL; cur = g_list_next (cur)) {
986     GstPlugin *plugin = (GstPlugin *) (cur->data);
987     if (plugin->flags & GST_PLUGIN_FLAG_BLACKLISTED) {
988       g_print ("  %s\n", plugin->desc.name);
989       count++;
990     }
991   }
992
993   g_print ("\n");
994   g_print (_("Total count: "));
995   g_print (ngettext ("%d blacklisted file", "%d blacklisted files", count),
996       count);
997   g_print ("\n");
998   gst_plugin_list_free (plugins);
999 }
1000
1001 static void
1002 print_element_list (gboolean print_all)
1003 {
1004   int plugincount = 0, featurecount = 0, blacklistcount = 0;
1005   GList *plugins, *orig_plugins;
1006
1007   orig_plugins = plugins = gst_default_registry_get_plugin_list ();
1008   while (plugins) {
1009     GList *features, *orig_features;
1010     GstPlugin *plugin;
1011
1012     plugin = (GstPlugin *) (plugins->data);
1013     plugins = g_list_next (plugins);
1014     plugincount++;
1015
1016     if (plugin->flags & GST_PLUGIN_FLAG_BLACKLISTED) {
1017       blacklistcount++;
1018       continue;
1019     }
1020
1021     orig_features = features =
1022         gst_registry_get_feature_list_by_plugin (gst_registry_get_default (),
1023         plugin->desc.name);
1024     while (features) {
1025       GstPluginFeature *feature;
1026
1027       if (G_UNLIKELY (features->data == NULL))
1028         goto next;
1029       feature = GST_PLUGIN_FEATURE (features->data);
1030       featurecount++;
1031
1032       if (GST_IS_ELEMENT_FACTORY (feature)) {
1033         GstElementFactory *factory;
1034
1035         factory = GST_ELEMENT_FACTORY (feature);
1036         if (print_all)
1037           print_element_info (factory, TRUE);
1038         else
1039           g_print ("%s:  %s: %s\n", plugin->desc.name,
1040               GST_OBJECT_NAME (factory),
1041               gst_element_factory_get_longname (factory));
1042       } else if (GST_IS_INDEX_FACTORY (feature)) {
1043         GstIndexFactory *factory;
1044
1045         factory = GST_INDEX_FACTORY (feature);
1046         if (!print_all)
1047           g_print ("%s:  %s: %s\n", plugin->desc.name,
1048               GST_OBJECT_NAME (factory), factory->longdesc);
1049       } else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
1050         GstTypeFindFactory *factory;
1051
1052         factory = GST_TYPE_FIND_FACTORY (feature);
1053         if (!print_all)
1054           g_print ("%s: %s: ", plugin->desc.name,
1055               gst_plugin_feature_get_name (feature));
1056         if (factory->extensions) {
1057           guint i = 0;
1058
1059           while (factory->extensions[i]) {
1060             if (!print_all)
1061               g_print ("%s%s", i > 0 ? ", " : "", factory->extensions[i]);
1062             i++;
1063           }
1064           if (!print_all)
1065             g_print ("\n");
1066         } else {
1067           if (!print_all)
1068             g_print ("no extensions\n");
1069         }
1070       } else {
1071         if (!print_all)
1072           n_print ("%s:  %s (%s)\n", plugin->desc.name,
1073               GST_OBJECT_NAME (feature), g_type_name (G_OBJECT_TYPE (feature)));
1074       }
1075
1076     next:
1077       features = g_list_next (features);
1078     }
1079
1080     gst_plugin_feature_list_free (orig_features);
1081   }
1082
1083   gst_plugin_list_free (orig_plugins);
1084
1085   g_print ("\n");
1086   g_print (_("Total count: "));
1087   g_print (ngettext ("%d plugin", "%d plugins", plugincount), plugincount);
1088   if (blacklistcount) {
1089     g_print (" (");
1090     g_print (ngettext ("%d blacklist entry", "%d blacklist entries",
1091             blacklistcount), blacklistcount);
1092     g_print (" not shown)");
1093   }
1094   g_print (", ");
1095   g_print (ngettext ("%d feature", "%d features", featurecount), featurecount);
1096   g_print ("\n");
1097 }
1098
1099 static void
1100 print_all_uri_handlers (void)
1101 {
1102   GList *plugins, *p, *features, *f;
1103
1104   plugins = gst_default_registry_get_plugin_list ();
1105
1106   for (p = plugins; p; p = p->next) {
1107     GstPlugin *plugin = (GstPlugin *) (p->data);
1108
1109     features =
1110         gst_registry_get_feature_list_by_plugin (gst_registry_get_default (),
1111         plugin->desc.name);
1112
1113     for (f = features; f; f = f->next) {
1114       GstPluginFeature *feature = GST_PLUGIN_FEATURE (f->data);
1115
1116       if (GST_IS_ELEMENT_FACTORY (feature)) {
1117         GstElementFactory *factory;
1118         GstElement *element;
1119
1120         factory = GST_ELEMENT_FACTORY (gst_plugin_feature_load (feature));
1121         if (!factory) {
1122           g_print ("element plugin %s couldn't be loaded\n", plugin->desc.name);
1123           continue;
1124         }
1125
1126         element = gst_element_factory_create (factory, NULL);
1127         if (!element) {
1128           g_print ("couldn't construct element for %s for some reason\n",
1129               GST_OBJECT_NAME (factory));
1130           gst_object_unref (factory);
1131           continue;
1132         }
1133
1134         if (GST_IS_URI_HANDLER (element)) {
1135           const gchar *dir;
1136           gchar **uri_protocols, *joined;
1137
1138           switch (gst_uri_handler_get_uri_type (GST_URI_HANDLER (element))) {
1139             case GST_URI_SRC:
1140               dir = "read";
1141               break;
1142             case GST_URI_SINK:
1143               dir = "write";
1144               break;
1145             default:
1146               dir = "unknown";
1147               break;
1148           }
1149
1150           uri_protocols =
1151               gst_uri_handler_get_protocols (GST_URI_HANDLER (element));
1152           joined = g_strjoinv (", ", uri_protocols);
1153
1154           g_print ("%s (%s, rank %u): %s\n",
1155               gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)), dir,
1156               gst_plugin_feature_get_rank (GST_PLUGIN_FEATURE (factory)),
1157               joined);
1158
1159           g_free (joined);
1160         }
1161
1162         gst_object_unref (element);
1163         gst_object_unref (factory);
1164       }
1165     }
1166
1167     gst_plugin_feature_list_free (features);
1168   }
1169
1170   gst_plugin_list_free (plugins);
1171 }
1172
1173 static void
1174 print_plugin_info (GstPlugin * plugin)
1175 {
1176   n_print ("Plugin Details:\n");
1177   n_print ("  Name:\t\t\t%s\n", plugin->desc.name);
1178   n_print ("  Description:\t\t%s\n", plugin->desc.description);
1179   n_print ("  Filename:\t\t%s\n",
1180       plugin->filename ? plugin->filename : "(null)");
1181   n_print ("  Version:\t\t%s\n", plugin->desc.version);
1182   n_print ("  License:\t\t%s\n", plugin->desc.license);
1183   n_print ("  Source module:\t%s\n", plugin->desc.source);
1184   if (plugin->desc.release_datetime != NULL) {
1185     const gchar *tz = "(UTC)";
1186     gchar *str, *sep;
1187
1188     /* may be: YYYY-MM-DD or YYYY-MM-DDTHH:MMZ */
1189     /* YYYY-MM-DDTHH:MMZ => YYYY-MM-DD HH:MM (UTC) */
1190     str = g_strdup (plugin->desc.release_datetime);
1191     sep = strstr (str, "T");
1192     if (sep != NULL) {
1193       *sep = ' ';
1194       sep = strstr (sep + 1, "Z");
1195       if (sep != NULL)
1196         *sep = ' ';
1197     } else {
1198       tz = "";
1199     }
1200     n_print ("  Source release date:\t%s%s\n", str, tz);
1201     g_free (str);
1202   }
1203   n_print ("  Binary package:\t%s\n", plugin->desc.package);
1204   n_print ("  Origin URL:\t\t%s\n", plugin->desc.origin);
1205   n_print ("\n");
1206 }
1207
1208 static void
1209 print_plugin_features (GstPlugin * plugin)
1210 {
1211   GList *features, *origlist;
1212   gint num_features = 0;
1213   gint num_elements = 0;
1214   gint num_typefinders = 0;
1215   gint num_indexes = 0;
1216   gint num_other = 0;
1217
1218   origlist = features =
1219       gst_registry_get_feature_list_by_plugin (gst_registry_get_default (),
1220       plugin->desc.name);
1221
1222   while (features) {
1223     GstPluginFeature *feature;
1224
1225     feature = GST_PLUGIN_FEATURE (features->data);
1226
1227     if (GST_IS_ELEMENT_FACTORY (feature)) {
1228       GstElementFactory *factory;
1229
1230       factory = GST_ELEMENT_FACTORY (feature);
1231       n_print ("  %s: %s\n", GST_OBJECT_NAME (factory),
1232           gst_element_factory_get_longname (factory));
1233       num_elements++;
1234     } else if (GST_IS_INDEX_FACTORY (feature)) {
1235       GstIndexFactory *factory;
1236
1237       factory = GST_INDEX_FACTORY (feature);
1238       n_print ("  %s: %s\n", GST_OBJECT_NAME (factory), factory->longdesc);
1239       num_indexes++;
1240     } else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
1241       GstTypeFindFactory *factory;
1242
1243       factory = GST_TYPE_FIND_FACTORY (feature);
1244       if (factory->extensions) {
1245         guint i = 0;
1246
1247         g_print ("%s: %s: ", plugin->desc.name,
1248             gst_plugin_feature_get_name (feature));
1249         while (factory->extensions[i]) {
1250           g_print ("%s%s", i > 0 ? ", " : "", factory->extensions[i]);
1251           i++;
1252         }
1253         g_print ("\n");
1254       } else
1255         g_print ("%s: %s: no extensions\n", plugin->desc.name,
1256             gst_plugin_feature_get_name (feature));
1257
1258       num_typefinders++;
1259     } else if (feature) {
1260       n_print ("  %s (%s)\n", gst_object_get_name (GST_OBJECT (feature)),
1261           g_type_name (G_OBJECT_TYPE (feature)));
1262       num_other++;
1263     }
1264     num_features++;
1265     features = g_list_next (features);
1266   }
1267
1268   gst_plugin_feature_list_free (origlist);
1269
1270   n_print ("\n");
1271   n_print ("  %d features:\n", num_features);
1272   if (num_elements > 0)
1273     n_print ("  +-- %d elements\n", num_elements);
1274   if (num_typefinders > 0)
1275     n_print ("  +-- %d typefinders\n", num_typefinders);
1276   if (num_indexes > 0)
1277     n_print ("  +-- %d indexes\n", num_indexes);
1278   if (num_other > 0)
1279     n_print ("  +-- %d other objects\n", num_other);
1280
1281   n_print ("\n");
1282 }
1283
1284 static int
1285 print_element_features (const gchar * element_name)
1286 {
1287   GstPluginFeature *feature;
1288
1289   /* FIXME implement other pretty print function for these */
1290   feature = gst_default_registry_find_feature (element_name,
1291       GST_TYPE_INDEX_FACTORY);
1292   if (feature) {
1293     n_print ("%s: an index\n", element_name);
1294     return 0;
1295   }
1296   feature = gst_default_registry_find_feature (element_name,
1297       GST_TYPE_TYPE_FIND_FACTORY);
1298   if (feature) {
1299     n_print ("%s: a typefind function\n", element_name);
1300     return 0;
1301   }
1302
1303   return -1;
1304 }
1305
1306 static int
1307 print_element_info (GstElementFactory * factory, gboolean print_names)
1308 {
1309   GstElement *element;
1310   gint maxlevel = 0;
1311
1312   factory =
1313       GST_ELEMENT_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE
1314           (factory)));
1315
1316   if (!factory) {
1317     g_print ("element plugin couldn't be loaded\n");
1318     return -1;
1319   }
1320
1321   element = gst_element_factory_create (factory, NULL);
1322   if (!element) {
1323     g_print ("couldn't construct element for some reason\n");
1324     return -1;
1325   }
1326
1327   if (print_names)
1328     _name = g_strdup_printf ("%s: ", GST_OBJECT_NAME (factory));
1329   else
1330     _name = NULL;
1331
1332   print_factory_details_info (factory);
1333   if (GST_PLUGIN_FEATURE (factory)->plugin_name) {
1334     GstPlugin *plugin;
1335
1336     plugin = gst_registry_find_plugin (gst_registry_get_default (),
1337         GST_PLUGIN_FEATURE (factory)->plugin_name);
1338     if (plugin) {
1339       print_plugin_info (plugin);
1340     }
1341   }
1342
1343   print_hierarchy (G_OBJECT_TYPE (element), 0, &maxlevel);
1344   print_interfaces (G_OBJECT_TYPE (element));
1345
1346   print_pad_templates_info (element, factory);
1347   print_element_flag_info (element);
1348   print_implementation_info (element);
1349   print_clocking_info (element);
1350   print_index_info (element);
1351   print_uri_handler_info (element);
1352   print_pad_info (element);
1353   print_element_properties_info (element);
1354   print_signal_info (element);
1355   print_children_info (element);
1356
1357   gst_object_unref (element);
1358   gst_object_unref (factory);
1359   g_free (_name);
1360
1361   return 0;
1362 }
1363
1364
1365 static void
1366 print_plugin_automatic_install_info_codecs (GstElementFactory * factory)
1367 {
1368   GstPadDirection direction;
1369   const gchar *type_name;
1370   const gchar *klass;
1371   const GList *static_templates, *l;
1372   GstCaps *caps = NULL;
1373   guint i, num;
1374
1375   klass = gst_element_factory_get_klass (factory);
1376   g_return_if_fail (klass != NULL);
1377
1378   if (strstr (klass, "Demuxer") ||
1379       strstr (klass, "Decoder") ||
1380       strstr (klass, "Depay") || strstr (klass, "Parser")) {
1381     type_name = "decoder";
1382     direction = GST_PAD_SINK;
1383   } else if (strstr (klass, "Muxer") ||
1384       strstr (klass, "Encoder") || strstr (klass, "Pay")) {
1385     type_name = "encoder";
1386     direction = GST_PAD_SRC;
1387   } else {
1388     return;
1389   }
1390
1391   /* decoder/demuxer sink pads should always be static and there should only
1392    * be one, the same applies to encoders/muxers and source pads */
1393   static_templates = gst_element_factory_get_static_pad_templates (factory);
1394   for (l = static_templates; l != NULL; l = l->next) {
1395     GstStaticPadTemplate *tmpl = NULL;
1396
1397     tmpl = (GstStaticPadTemplate *) l->data;
1398     if (tmpl->direction == direction) {
1399       caps = gst_static_pad_template_get_caps (tmpl);
1400       break;
1401     }
1402   }
1403
1404   if (caps == NULL) {
1405     g_printerr ("Couldn't find static pad template for %s '%s'\n",
1406         type_name, GST_OBJECT_NAME (factory));
1407     return;
1408   }
1409
1410   caps = gst_caps_make_writable (caps);
1411   num = gst_caps_get_size (caps);
1412   for (i = 0; i < num; ++i) {
1413     GstStructure *s;
1414     gchar *s_str;
1415
1416     s = gst_caps_get_structure (caps, i);
1417     /* remove fields that are almost always just MIN-MAX of some sort
1418      * in order to make the caps look less messy */
1419     gst_structure_remove_field (s, "pixel-aspect-ratio");
1420     gst_structure_remove_field (s, "framerate");
1421     gst_structure_remove_field (s, "channels");
1422     gst_structure_remove_field (s, "width");
1423     gst_structure_remove_field (s, "height");
1424     gst_structure_remove_field (s, "rate");
1425     gst_structure_remove_field (s, "depth");
1426     gst_structure_remove_field (s, "clock-rate");
1427     s_str = gst_structure_to_string (s);
1428     g_print ("%s-%s\n", type_name, s_str);
1429     g_free (s_str);
1430   }
1431   gst_caps_unref (caps);
1432 }
1433
1434 static void
1435 print_plugin_automatic_install_info_protocols (GstElementFactory * factory)
1436 {
1437   gchar **protocols, **p;
1438
1439   protocols = gst_element_factory_get_uri_protocols (factory);
1440   if (protocols != NULL && *protocols != NULL) {
1441     switch (gst_element_factory_get_uri_type (factory)) {
1442       case GST_URI_SINK:
1443         for (p = protocols; *p != NULL; ++p)
1444           g_print ("urisink-%s\n", *p);
1445         break;
1446       case GST_URI_SRC:
1447         for (p = protocols; *p != NULL; ++p)
1448           g_print ("urisource-%s\n", *p);
1449         break;
1450       default:
1451         break;
1452     }
1453     g_strfreev (protocols);
1454   }
1455 }
1456
1457 static void
1458 print_plugin_automatic_install_info (GstPlugin * plugin)
1459 {
1460   const gchar *plugin_name;
1461   GList *features, *l;
1462
1463   plugin_name = gst_plugin_get_name (plugin);
1464
1465   /* not interested in typefind factories, only element factories */
1466   features = gst_registry_get_feature_list (gst_registry_get_default (),
1467       GST_TYPE_ELEMENT_FACTORY);
1468
1469   for (l = features; l != NULL; l = l->next) {
1470     GstPluginFeature *feature;
1471
1472     feature = GST_PLUGIN_FEATURE (l->data);
1473
1474     /* only interested in the ones that are in the plugin we just loaded */
1475     if (g_str_equal (plugin_name, feature->plugin_name)) {
1476       GstElementFactory *factory;
1477
1478       g_print ("element-%s\n", gst_plugin_feature_get_name (feature));
1479
1480       factory = GST_ELEMENT_FACTORY (feature);
1481       print_plugin_automatic_install_info_protocols (factory);
1482       print_plugin_automatic_install_info_codecs (factory);
1483     }
1484   }
1485
1486   g_list_foreach (features, (GFunc) gst_object_unref, NULL);
1487   g_list_free (features);
1488 }
1489
1490 static void
1491 print_all_plugin_automatic_install_info (void)
1492 {
1493   GList *plugins, *orig_plugins;
1494
1495   orig_plugins = plugins = gst_default_registry_get_plugin_list ();
1496   while (plugins) {
1497     GstPlugin *plugin;
1498
1499     plugin = (GstPlugin *) (plugins->data);
1500     plugins = g_list_next (plugins);
1501
1502     print_plugin_automatic_install_info (plugin);
1503   }
1504   gst_plugin_list_free (orig_plugins);
1505 }
1506
1507 int
1508 main (int argc, char *argv[])
1509 {
1510   gboolean print_all = FALSE;
1511   gboolean do_print_blacklist = FALSE;
1512   gboolean plugin_name = FALSE;
1513   gboolean print_aii = FALSE;
1514   gboolean uri_handlers = FALSE;
1515 #ifndef GST_DISABLE_OPTION_PARSING
1516   GOptionEntry options[] = {
1517     {"print-all", 'a', 0, G_OPTION_ARG_NONE, &print_all,
1518         N_("Print all elements"), NULL},
1519     {"print-blacklist", 'b', 0, G_OPTION_ARG_NONE, &do_print_blacklist,
1520         N_("Print list of blacklisted files"), NULL},
1521     {"print-plugin-auto-install-info", '\0', 0, G_OPTION_ARG_NONE, &print_aii,
1522         N_("Print a machine-parsable list of features the specified plugin "
1523               "or all plugins provide.\n                                       "
1524               "Useful in connection with external automatic plugin "
1525               "installation mechanisms"), NULL},
1526     {"plugin", '\0', 0, G_OPTION_ARG_NONE, &plugin_name,
1527         N_("List the plugin contents"), NULL},
1528     {"uri-handlers", 'u', 0, G_OPTION_ARG_NONE, &uri_handlers,
1529           N_
1530           ("Print supported URI schemes, with the elements that implement them"),
1531         NULL},
1532     GST_TOOLS_GOPTION_VERSION,
1533     {NULL}
1534   };
1535   GOptionContext *ctx;
1536   GError *err = NULL;
1537 #endif
1538
1539 #ifdef ENABLE_NLS
1540   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
1541   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1542   textdomain (GETTEXT_PACKAGE);
1543 #endif
1544
1545   g_thread_init (NULL);
1546
1547   gst_tools_set_prgname ("gst-inspect");
1548
1549 #ifndef GST_DISABLE_OPTION_PARSING
1550   ctx = g_option_context_new ("[ELEMENT-NAME | PLUGIN-NAME]");
1551   g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE);
1552   g_option_context_add_group (ctx, gst_init_get_option_group ());
1553   if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
1554     g_print ("Error initializing: %s\n", err->message);
1555     exit (1);
1556   }
1557   g_option_context_free (ctx);
1558 #else
1559   gst_init (&argc, &argv);
1560 #endif
1561
1562   gst_tools_print_version ("gst-inspect");
1563
1564   if (print_all && argc > 1) {
1565     g_print ("-a requires no extra arguments\n");
1566     return 1;
1567   }
1568
1569   if (uri_handlers && argc > 1) {
1570     g_print ("-u requires no extra arguments\n");
1571     exit (1);
1572   }
1573
1574   /* if no arguments, print out list of elements */
1575   if (uri_handlers) {
1576     print_all_uri_handlers ();
1577   } else if (argc == 1 || print_all) {
1578     if (do_print_blacklist)
1579       print_blacklist ();
1580     else {
1581       if (print_aii)
1582         print_all_plugin_automatic_install_info ();
1583       else
1584         print_element_list (print_all);
1585     }
1586   } else {
1587     /* else we try to get a factory */
1588     GstElementFactory *factory;
1589     GstPlugin *plugin;
1590     const char *arg = argv[argc - 1];
1591     int retval;
1592
1593     if (!plugin_name) {
1594       factory = gst_element_factory_find (arg);
1595
1596       /* if there's a factory, print out the info */
1597       if (factory) {
1598         retval = print_element_info (factory, print_all);
1599         gst_object_unref (factory);
1600       } else {
1601         retval = print_element_features (arg);
1602       }
1603     } else {
1604       retval = -1;
1605     }
1606
1607     /* otherwise check if it's a plugin */
1608     if (retval) {
1609       plugin = gst_default_registry_find_plugin (arg);
1610
1611       /* if there is such a plugin, print out info */
1612       if (plugin) {
1613         if (print_aii) {
1614           print_plugin_automatic_install_info (plugin);
1615         } else {
1616           print_plugin_info (plugin);
1617           print_plugin_features (plugin);
1618         }
1619       } else {
1620         GError *error = NULL;
1621
1622         if (g_file_test (arg, G_FILE_TEST_EXISTS)) {
1623           plugin = gst_plugin_load_file (arg, &error);
1624
1625           if (plugin) {
1626             if (print_aii) {
1627               print_plugin_automatic_install_info (plugin);
1628             } else {
1629               print_plugin_info (plugin);
1630               print_plugin_features (plugin);
1631             }
1632           } else {
1633             g_print (_("Could not load plugin file: %s\n"), error->message);
1634             g_error_free (error);
1635             return -1;
1636           }
1637         } else {
1638           g_print (_("No such element or plugin '%s'\n"), arg);
1639           return -1;
1640         }
1641       }
1642     }
1643   }
1644
1645   return 0;
1646 }