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