source: trunk/third/gstreamer/tools/gst-xmlinspect.c @ 21005

Revision 21005, 28.7 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21004, which included commits to RCS files with non-trunk default branches.
RevLine 
[21004]1#ifdef HAVE_CONFIG_H
2#  include "config.h"
3#endif
4
5#include <gst/gst.h>
6#include <gst/control/control.h>
7#include <string.h>
8#include <locale.h>
9#include <glib/gprintf.h>
10
11#define PUT_START_TAG(pfx,tag)                                  \
12G_STMT_START{                                                   \
13  g_print ("%*.*s<%s>\n", pfx, pfx, "", tag);                   \
14}G_STMT_END
15
16#define PUT_END_TAG(pfx,tag)                                    \
17G_STMT_START{                                                   \
18  g_print ("%*.*s</%s>\n", pfx, pfx, "", tag);                  \
19}G_STMT_END
20
21#define PUT_ESCAPED(pfx,tag,value)                              \
22G_STMT_START{                                                   \
23  const gchar *toconv = value;                                  \
24  if (value) {                                                  \
25    gchar *v = g_markup_escape_text (toconv, strlen (toconv));  \
26    g_print ("%*.*s<%s>%s</%s>\n", pfx, pfx, "", tag, v, tag);  \
27    g_free (v);                                                 \
28  }                                                             \
29}G_STMT_END
30
31#ifdef G_HAVE_ISO_VARARGS
32
33#define PUT_STRING(pfx, ...)                                    \
34G_STMT_START{                                                   \
35  gchar *ps_val = g_strdup_printf(__VA_ARGS__);                 \
36  g_print ("%*.*s%s\n", pfx, pfx, "", ps_val);                  \
37  g_free(ps_val);                                               \
38}G_STMT_END
39
40#elif defined(G_HAVE_GNUC_VARARGS)
41
42#define PUT_STRING(pfx, str, a...)                              \
43G_STMT_START{                                                   \
44  g_print ("%*.*s"str"\n", pfx, pfx, "" , ##a);                 \
45}G_STMT_END
46
47#else
48
49static inline void
50PUT_STRING (int pfx, const char *format, ...)
51{
52  va_list varargs;
53
54  g_print ("%*.*s", pfx, pfx, "");
55  va_start (varargs, format);
56  g_vprintf (format, varargs);
57  va_end (varargs);
58  g_print ("\n");
59}
60
61#endif
62
63static void
64print_caps (const GstCaps * caps, gint pfx)
65{
66  char *s;
67
68  if (!caps)
69    return;
70
71  s = gst_caps_to_string (caps);
72  PUT_ESCAPED (pfx, "caps", s);
73  g_free (s);
74}
75
76static void
77print_formats (const GstFormat * formats, gint pfx)
78{
79  while (formats && *formats) {
80    const GstFormatDefinition *definition;
81
82    definition = gst_format_get_details (*formats);
83    if (definition)
84      PUT_STRING (pfx, "<format id=\"%d\" nick=\"%s\">%s</format>",
85          *formats, definition->nick, definition->description);
86    else
87      PUT_STRING (pfx, "<format id=\"%d\">unknown</format>", *formats);
88
89    formats++;
90  }
91}
92
93static void
94print_query_types (const GstQueryType * types, gint pfx)
95{
96  while (types && *types) {
97    const GstQueryTypeDefinition *definition;
98
99    definition = gst_query_type_get_details (*types);
100    if (definition)
101      PUT_STRING (pfx, "<query-type id=\"%d\" nick=\"%s\">%s</query-type>",
102          *types, definition->nick, definition->description);
103    else
104      PUT_STRING (pfx, "<query-type id=\"%d\">unknown</query-type>", *types);
105
106    types++;
107  }
108}
109
110static void
111print_event_masks (const GstEventMask * masks, gint pfx)
112{
113#ifndef GST_DISABLE_ENUMTYPES
114  GType event_type;
115  GEnumClass *klass;
116  GType event_flags;
117  GFlagsClass *flags_class = NULL;
118
119  event_type = gst_event_type_get_type ();
120  klass = (GEnumClass *) g_type_class_ref (event_type);
121
122  while (masks && masks->type) {
123    GEnumValue *value;
124    gint flags = 0, index = 0;
125
126    switch (masks->type) {
127      case GST_EVENT_SEEK:
128        flags = masks->flags;
129        event_flags = gst_seek_type_get_type ();
130        flags_class = (GFlagsClass *) g_type_class_ref (event_flags);
131        break;
132      default:
133        break;
134    }
135
136    value = g_enum_get_value (klass, masks->type);
137    PUT_STRING (pfx, "<event type=\"%s\">", value->value_nick);
138
139    while (flags) {
140      GFlagsValue *value;
141
142      if (flags & 1) {
143        value = g_flags_get_first_value (flags_class, 1 << index);
144
145        if (value)
146          PUT_ESCAPED (pfx + 1, "flag", value->value_nick);
147        else
148          PUT_ESCAPED (pfx + 1, "flag", "?");
149      }
150      flags >>= 1;
151      index++;
152    }
153    PUT_END_TAG (pfx, "event");
154
155    masks++;
156  }
157#endif
158}
159
160static void
161output_hierarchy (GType type, gint level, gint * maxlevel)
162{
163  GType parent;
164
165  parent = g_type_parent (type);
166
167  *maxlevel = *maxlevel + 1;
168  level++;
169
170  PUT_STRING (level, "<object name=\"%s\">", g_type_name (type));
171
172  if (parent)
173    output_hierarchy (parent, level, maxlevel);
174
175  PUT_END_TAG (level, "object");
176}
177
178static void
179print_element_properties (GstElement * element, gint pfx)
180{
181  GParamSpec **property_specs;
182  gint num_properties, i;
183  gboolean readable;
184
185  property_specs = g_object_class_list_properties
186      (G_OBJECT_GET_CLASS (element), &num_properties);
187
188  PUT_START_TAG (pfx, "element-properties");
189
190  for (i = 0; i < num_properties; i++) {
191    GValue value = { 0, };
192    GParamSpec *param = property_specs[i];
193
194    readable = FALSE;
195
196    g_value_init (&value, param->value_type);
197    if (param->flags & G_PARAM_READABLE) {
198      g_object_get_property (G_OBJECT (element), param->name, &value);
199      readable = TRUE;
200    }
201    PUT_START_TAG (pfx + 1, "element-property");
202    PUT_ESCAPED (pfx + 2, "name", g_param_spec_get_name (param));
203    PUT_ESCAPED (pfx + 2, "type", g_type_name (param->value_type));
204    PUT_ESCAPED (pfx + 2, "nick", g_param_spec_get_nick (param));
205    PUT_ESCAPED (pfx + 2, "blurb", g_param_spec_get_blurb (param));
206    if (readable) {
207      PUT_ESCAPED (pfx + 2, "flags", "RW");
208    } else {
209      PUT_ESCAPED (pfx + 2, "flags", "W");
210    }
211
212    switch (G_VALUE_TYPE (&value)) {
213      case G_TYPE_STRING:
214        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
215        break;
216      case G_TYPE_BOOLEAN:
217        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
218        break;
219      case G_TYPE_ULONG:
220      {
221        GParamSpecULong *pulong = G_PARAM_SPEC_ULONG (param);
222
223        PUT_STRING (pfx + 2, "<range min=\"%lu\" max=\"%lu\"/>",
224            pulong->minimum, pulong->maximum);
225        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
226        break;
227      }
228      case G_TYPE_LONG:
229      {
230        GParamSpecLong *plong = G_PARAM_SPEC_LONG (param);
231
232        PUT_STRING (pfx + 2, "<range min=\"%ld\" max=\"%ld\"/>",
233            plong->minimum, plong->maximum);
234        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
235        break;
236      }
237      case G_TYPE_UINT:
238      {
239        GParamSpecUInt *puint = G_PARAM_SPEC_UINT (param);
240
241        PUT_STRING (pfx + 2, "<range min=\"%u\" max=\"%u\"/>",
242            puint->minimum, puint->maximum);
243        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
244        break;
245      }
246      case G_TYPE_INT:
247      {
248        GParamSpecInt *pint = G_PARAM_SPEC_INT (param);
249
250        PUT_STRING (pfx + 2, "<range min=\"%d\" max=\"%d\"/>",
251            pint->minimum, pint->maximum);
252        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
253        break;
254      }
255      case G_TYPE_UINT64:
256      {
257        GParamSpecUInt64 *puint64 = G_PARAM_SPEC_UINT64 (param);
258
259        PUT_STRING (pfx + 2,
260            "<range min=\"%" G_GUINT64_FORMAT "\" max=\"%" G_GUINT64_FORMAT
261            "\"/>", puint64->minimum, puint64->maximum);
262        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
263        break;
264      }
265      case G_TYPE_INT64:
266      {
267        GParamSpecInt64 *pint64 = G_PARAM_SPEC_INT64 (param);
268
269        PUT_STRING (pfx + 2,
270            "<range min=\"%" G_GINT64_FORMAT "\" max=\"%" G_GINT64_FORMAT
271            "\"/>", pint64->minimum, pint64->maximum);
272        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
273        break;
274      }
275      case G_TYPE_FLOAT:
276      {
277        GParamSpecFloat *pfloat = G_PARAM_SPEC_FLOAT (param);
278
279        PUT_STRING (pfx + 2, "<range min=\"%f\" max=\"%f\"/>",
280            pfloat->minimum, pfloat->maximum);
281        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
282        break;
283      }
284      case G_TYPE_DOUBLE:
285      {
286        GParamSpecDouble *pdouble = G_PARAM_SPEC_DOUBLE (param);
287
288        PUT_STRING (pfx + 2, "<range min=\"%g\" max=\"%g\"/>",
289            pdouble->minimum, pdouble->maximum);
290        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
291        break;
292      }
293      default:
294        if (param->value_type == GST_TYPE_CAPS) {
295          GstCaps *caps = g_value_peek_pointer (&value);
296
297          if (!caps)
298            PUT_ESCAPED (pfx + 2, "default", "NULL");
299          else {
300            print_caps (caps, 2);
301          }
302        } else if (G_IS_PARAM_SPEC_ENUM (param)) {
303          GEnumValue *values;
304          guint j = 0;
305          gint enum_value;
306
307          values = G_ENUM_CLASS (g_type_class_ref (param->value_type))->values;
308          enum_value = g_value_get_enum (&value);
309
310          while (values[j].value_name) {
311            if (values[j].value == enum_value)
312              break;
313            j++;
314          }
315          PUT_STRING (pfx + 2, "<default>%d</default>", values[j].value);
316
317          PUT_START_TAG (pfx + 2, "enum-values");
318          j = 0;
319          while (values[j].value_name) {
320            PUT_STRING (pfx + 3, "<value value=\"%d\" nick=\"%s\"/>",
321                values[j].value, values[j].value_nick);
322            j++;
323          }
324          PUT_END_TAG (pfx + 2, "enum-values");
325        } else if (G_IS_PARAM_SPEC_FLAGS (param)) {
326          GFlagsValue *values;
327          guint j = 0;
328          gint flags_value;
329
330          values = G_FLAGS_CLASS (g_type_class_ref (param->value_type))->values;
331          flags_value = g_value_get_flags (&value);
332
333          PUT_STRING (pfx + 2, "<default>%d</default>", flags_value);
334
335          PUT_START_TAG (pfx + 2, "flags");
336          j = 0;
337          while (values[j].value_name) {
338            PUT_STRING (pfx + 3, "<flag value=\"%d\" nick=\"%s\"/>",
339                values[j].value, values[j].value_nick);
340            j++;
341          }
342          PUT_END_TAG (pfx + 2, "flags");
343        } else if (G_IS_PARAM_SPEC_OBJECT (param)) {
344          PUT_ESCAPED (pfx + 2, "object-type", g_type_name (param->value_type));
345        }
346        break;
347    }
348
349    PUT_END_TAG (pfx + 1, "element-property");
350  }
351  PUT_END_TAG (pfx, "element-properties");
352}
353
354static void
355print_element_dynparamaters (GstElement * element, gint pfx)
356{
357  GstDParamManager *dpman;
358  GParamSpec **specs;
359  gint x;
360
361  PUT_START_TAG (pfx, "dyn-params");
362
363  if ((dpman = gst_dpman_get_manager (element))) {
364    specs = gst_dpman_list_dparam_specs (dpman);
365    for (x = 0; specs[x] != NULL; x++) {
366      PUT_START_TAG (pfx + 1, "dyn-param");
367
368      PUT_ESCAPED (pfx + 2, "name", g_param_spec_get_name (specs[x]));
369      PUT_ESCAPED (pfx + 2, "type", g_type_name (specs[x]->value_type));
370      PUT_ESCAPED (pfx + 2, "nick", g_param_spec_get_nick (specs[x]));
371      PUT_ESCAPED (pfx + 2, "blurb", g_param_spec_get_blurb (specs[x]));
372
373      switch (G_PARAM_SPEC_VALUE_TYPE (specs[x])) {
374        case G_TYPE_INT64:
375          PUT_STRING (pfx + 2,
376              "<range min=\"%" G_GINT64_FORMAT "\" max=\"%" G_GINT64_FORMAT
377              "\"/>", ((GParamSpecInt64 *) specs[x])->minimum,
378              ((GParamSpecInt64 *) specs[x])->maximum);
379          PUT_STRING (pfx + 2, "<default>%" G_GINT64_FORMAT "</default>",
380              ((GParamSpecInt64 *) specs[x])->default_value);
381          break;
382        case G_TYPE_INT:
383          PUT_STRING (pfx + 2, "<range min=\"%d\" max=\"%d\"/>",
384              ((GParamSpecInt *) specs[x])->minimum,
385              ((GParamSpecInt *) specs[x])->maximum);
386          PUT_STRING (pfx + 2, "<default>%d</default>",
387              ((GParamSpecInt *) specs[x])->default_value);
388          break;
389        case G_TYPE_FLOAT:
390          PUT_STRING (pfx + 2, "<range min=\"%f\" max=\"%f\"/>",
391              ((GParamSpecFloat *) specs[x])->minimum,
392              ((GParamSpecFloat *) specs[x])->maximum);
393          PUT_STRING (pfx + 2, "<default>%f</default>",
394              ((GParamSpecFloat *) specs[x])->default_value);
395          break;
396        default:
397          break;
398      }
399      PUT_END_TAG (pfx + 1, "dyn-param");
400    }
401    g_free (specs);
402  }
403  PUT_END_TAG (pfx, "dyn-params");
404}
405
406static void
407print_element_signals (GstElement * element, gint pfx)
408{
409  guint *signals;
410  guint nsignals;
411  gint i, k;
412  GSignalQuery *query;
413
414  signals = g_signal_list_ids (G_OBJECT_TYPE (element), &nsignals);
415  for (k = 0; k < 2; k++) {
416    gint counted = 0;
417
418    if (k == 0)
419      PUT_START_TAG (pfx, "element-signals");
420    else
421      PUT_START_TAG (pfx, "element-actions");
422
423    for (i = 0; i < nsignals; i++) {
424      gint n_params;
425      GType return_type;
426      const GType *param_types;
427      gint j;
428
429      query = g_new0 (GSignalQuery, 1);
430      g_signal_query (signals[i], query);
431
432      if ((k == 0 && !(query->signal_flags & G_SIGNAL_ACTION)) ||
433          (k == 1 && (query->signal_flags & G_SIGNAL_ACTION))) {
434        n_params = query->n_params;
435        return_type = query->return_type;
436        param_types = query->param_types;
437
438        PUT_START_TAG (pfx + 1, "signal");
439        PUT_ESCAPED (pfx + 2, "name", query->signal_name);
440        PUT_ESCAPED (pfx + 2, "return-type", g_type_name (return_type));
441        PUT_ESCAPED (pfx + 2, "object-type",
442            g_type_name (G_OBJECT_TYPE (element)));
443
444        PUT_START_TAG (pfx + 2, "params");
445        for (j = 0; j < n_params; j++) {
446          PUT_ESCAPED (pfx + 3, "type", g_type_name (param_types[j]));
447        }
448
449        PUT_END_TAG (pfx + 2, "params");
450
451        PUT_END_TAG (pfx + 1, "signal");
452
453        counted++;
454      }
455
456      g_free (query);
457    }
458    if (k == 0)
459      PUT_END_TAG (pfx, "element-signals");
460    else
461      PUT_END_TAG (pfx, "element-actions");
462  }
463}
464
465static gint
466print_element_info (GstElementFactory * factory)
467{
468  GstElement *element;
469  GstObjectClass *gstobject_class;
470  GstElementClass *gstelement_class;
471  GList *pads;
472  GstPad *pad;
473  GstRealPad *realpad;
474  GstPadTemplate *padtemplate;
475  GList *children;
476  GstElement *child;
477  gint maxlevel = 0;
478
479  element = gst_element_factory_create (factory, "element");
480  if (!element) {
481    g_print ("couldn't construct element for some reason\n");
482    return -1;
483  }
484  PUT_START_TAG (0, "element");
485  PUT_ESCAPED (1, "name", GST_PLUGIN_FEATURE_NAME (factory));
486
487  gstobject_class = GST_OBJECT_CLASS (G_OBJECT_GET_CLASS (element));
488  gstelement_class = GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element));
489
490  PUT_START_TAG (1, "details");
491  PUT_ESCAPED (2, "long-name", factory->details.longname);
492  PUT_ESCAPED (2, "class", factory->details.klass);
493  PUT_ESCAPED (2, "description", factory->details.description);
494  PUT_ESCAPED (2, "authors", factory->details.author);
495  PUT_END_TAG (1, "details");
496
497  output_hierarchy (G_OBJECT_TYPE (element), 0, &maxlevel);
498
499  PUT_START_TAG (1, "pad-templates");
500  if (factory->numpadtemplates) {
501    pads = factory->padtemplates;
502    while (pads) {
503      padtemplate = (GstPadTemplate *) (pads->data);
504      pads = g_list_next (pads);
505
506      PUT_START_TAG (2, "pad-template");
507      PUT_ESCAPED (3, "name", padtemplate->name_template);
508
509      if (padtemplate->direction == GST_PAD_SRC)
510        PUT_ESCAPED (3, "direction", "src");
511      else if (padtemplate->direction == GST_PAD_SINK)
512        PUT_ESCAPED (3, "direction", "sink");
513      else
514        PUT_ESCAPED (3, "direction", "unknown");
515
516      if (padtemplate->presence == GST_PAD_ALWAYS)
517        PUT_ESCAPED (3, "presence", "always");
518      else if (padtemplate->presence == GST_PAD_SOMETIMES)
519        PUT_ESCAPED (3, "presence", "sometimes");
520      else if (padtemplate->presence == GST_PAD_REQUEST) {
521        PUT_ESCAPED (3, "presence", "request");
522        PUT_ESCAPED (3, "request-function",
523            GST_DEBUG_FUNCPTR_NAME (gstelement_class->request_new_pad));
524      } else
525        PUT_ESCAPED (3, "presence", "unknown");
526
527      if (padtemplate->caps) {
528        print_caps (padtemplate->caps, 3);
529      }
530      PUT_END_TAG (2, "pad-template");
531    }
532  }
533  PUT_END_TAG (1, "pad-templates");
534
535  PUT_START_TAG (1, "element-flags");
536  if (GST_FLAG_IS_SET (element, GST_ELEMENT_COMPLEX)) {
537    PUT_ESCAPED (2, "flag", "GST_ELEMENT_COMPLEX");
538  }
539  if (GST_FLAG_IS_SET (element, GST_ELEMENT_DECOUPLED)) {
540    PUT_ESCAPED (2, "flag", "GST_ELEMENT_DECOUPLED");
541  }
542  if (GST_FLAG_IS_SET (element, GST_ELEMENT_THREAD_SUGGESTED)) {
543    PUT_ESCAPED (2, "flag", "GST_ELEMENT_THREADSUGGESTED");
544  }
545  if (GST_FLAG_IS_SET (element, GST_ELEMENT_EVENT_AWARE)) {
546    PUT_ESCAPED (2, "flag", "GST_ELEMENT_EVENT_AWARE");
547  }
548  PUT_END_TAG (1, "element-flags");
549
550  if (GST_IS_BIN (element)) {
551    PUT_START_TAG (1, "bin-flags");
552
553    if (GST_FLAG_IS_SET (element, GST_BIN_FLAG_MANAGER)) {
554      PUT_ESCAPED (2, "flag", "GST_BIN_FLAG_MANAGER");
555    }
556    if (GST_FLAG_IS_SET (element, GST_BIN_SELF_SCHEDULABLE)) {
557      PUT_ESCAPED (2, "flag", "GST_BIN_SELF_SCHEDULABLE");
558    }
559    if (GST_FLAG_IS_SET (element, GST_BIN_FLAG_PREFER_COTHREADS)) {
560      PUT_ESCAPED (2, "flag", "GST_BIN_FLAG_PREFER_COTHREADS");
561    }
562    PUT_END_TAG (1, "bin-flags");
563  }
564
565
566  PUT_START_TAG (1, "element-implementation");
567  if (element->loopfunc)
568    PUT_STRING (2, "<loop-based function=\"%s\"/>",
569        GST_DEBUG_FUNCPTR_NAME (element->loopfunc));
570
571  PUT_STRING (2, "<state-change function=\"%s\"/>",
572      GST_DEBUG_FUNCPTR_NAME (gstelement_class->change_state));
573
574#ifndef GST_DISABLE_LOADSAVE
575  PUT_STRING (2, "<save function=\"%s\"/>",
576      GST_DEBUG_FUNCPTR_NAME (gstobject_class->save_thyself));
577  PUT_STRING (2, "<load function=\"%s\"/>",
578      GST_DEBUG_FUNCPTR_NAME (gstobject_class->restore_thyself));
579#endif
580  PUT_END_TAG (1, "element-implementation");
581
582  PUT_START_TAG (1, "clocking-interaction");
583  if (gst_element_requires_clock (element)) {
584    PUT_STRING (2, "<requires-clock/>");
585  }
586  if (gst_element_provides_clock (element)) {
587    GstClock *clock;
588
589    clock = gst_element_get_clock (element);
590    if (clock)
591      PUT_STRING (2, "<provides-clock name=\"%s\"/>", GST_OBJECT_NAME (clock));
592  }
593  PUT_END_TAG (1, "clocking-interaction");
594
595#ifndef GST_DISABLE_INDEX
596  if (gst_element_is_indexable (element)) {
597    PUT_STRING (1, "<indexing-capabilities/>");
598  }
599#endif
600
601  PUT_START_TAG (1, "pads");
602  if (element->numpads) {
603    const GList *pads;
604
605    pads = gst_element_get_pad_list (element);
606    while (pads) {
607      pad = GST_PAD (pads->data);
608      pads = g_list_next (pads);
609      realpad = GST_PAD_REALIZE (pad);
610
611      PUT_START_TAG (2, "pad");
612      PUT_ESCAPED (3, "name", gst_pad_get_name (pad));
613
614      if (gst_pad_get_direction (pad) == GST_PAD_SRC)
615        PUT_ESCAPED (3, "direction", "src");
616      else if (gst_pad_get_direction (pad) == GST_PAD_SINK)
617        PUT_ESCAPED (3, "direction", "sink");
618      else
619        PUT_ESCAPED (3, "direction", "unknown");
620
621      if (GST_IS_GHOST_PAD (pad))
622        PUT_ESCAPED (3, "ghost", gst_pad_get_name (pad));
623
624      if (pad->padtemplate)
625        PUT_ESCAPED (3, "template", pad->padtemplate->name_template);
626
627      PUT_START_TAG (3, "implementation");
628      if (realpad->chainfunc)
629        PUT_STRING (4, "<chain-based function=\"%s\"/>",
630            GST_DEBUG_FUNCPTR_NAME (realpad->chainfunc));
631      if (realpad->getfunc)
632        PUT_STRING (4, "<get-based function=\"%s\"/>",
633            GST_DEBUG_FUNCPTR_NAME (realpad->getfunc));
634      if (realpad->formatsfunc != gst_pad_get_formats_default) {
635        PUT_STRING (4, "<formats-function function=\"%s\">",
636            GST_DEBUG_FUNCPTR_NAME (realpad->formatsfunc));
637        print_formats (gst_pad_get_formats (GST_PAD (realpad)), 5);
638        PUT_END_TAG (4, "formats-function");
639      }
640      if (realpad->convertfunc != gst_pad_convert_default)
641        PUT_STRING (4, "<convert-function function=\"%s\"/>",
642            GST_DEBUG_FUNCPTR_NAME (realpad->convertfunc));
643      if (realpad->eventfunc != gst_pad_event_default)
644        PUT_STRING (4, "<event-function function=\"%s\"/>",
645            GST_DEBUG_FUNCPTR_NAME (realpad->eventfunc));
646      if (realpad->eventmaskfunc != gst_pad_get_event_masks_default) {
647        PUT_STRING (4, "<event-mask-func function=\"%s\">",
648            GST_DEBUG_FUNCPTR_NAME (realpad->eventmaskfunc));
649        print_event_masks (gst_pad_get_event_masks (GST_PAD (realpad)), 5);
650        PUT_END_TAG (4, "event-mask-func");
651      }
652      if (realpad->queryfunc != gst_pad_query_default)
653        PUT_STRING (4, "<query-function function=\"%s\"/>",
654            GST_DEBUG_FUNCPTR_NAME (realpad->queryfunc));
655      if (realpad->querytypefunc != gst_pad_get_query_types_default) {
656        PUT_STRING (4, "<query-type-func function=\"%s\">",
657            GST_DEBUG_FUNCPTR_NAME (realpad->querytypefunc));
658        print_query_types (gst_pad_get_query_types (GST_PAD (realpad)), 5);
659        PUT_END_TAG (4, "query-type-func");
660      }
661
662      if (realpad->intlinkfunc != gst_pad_get_internal_links_default)
663        PUT_STRING (4, "<intlink-function function=\"%s\"/>",
664            GST_DEBUG_FUNCPTR_NAME (realpad->intlinkfunc));
665
666      if (realpad->bufferallocfunc)
667        PUT_STRING (4, "<bufferalloc-function function=\"%s\"/>",
668            GST_DEBUG_FUNCPTR_NAME (realpad->bufferallocfunc));
669      PUT_END_TAG (3, "implementation");
670
671      if (realpad->caps) {
672        print_caps (realpad->caps, 3);
673      }
674      PUT_END_TAG (2, "pad");
675    }
676  }
677  PUT_END_TAG (1, "pads");
678
679  print_element_properties (element, 1);
680  print_element_dynparamaters (element, 1);
681  print_element_signals (element, 1);
682
683  /* for compound elements */
684  if (GST_IS_BIN (element)) {
685    PUT_START_TAG (1, "children");
686    children = (GList *) gst_bin_get_list (GST_BIN (element));
687    while (children) {
688      child = GST_ELEMENT (children->data);
689      children = g_list_next (children);
690
691      PUT_ESCAPED (2, "child", GST_ELEMENT_NAME (child));
692    }
693    PUT_END_TAG (1, "children");
694  }
695  PUT_END_TAG (0, "element");
696
697  return 0;
698}
699
700static void
701print_element_list (void)
702{
703  GList *plugins;
704
705  plugins = gst_registry_pool_plugin_list ();
706  while (plugins) {
707    GList *features;
708    GstPlugin *plugin;
709
710    plugin = (GstPlugin *) (plugins->data);
711    plugins = g_list_next (plugins);
712
713    features = gst_plugin_get_feature_list (plugin);
714    while (features) {
715      GstPluginFeature *feature;
716
717      feature = GST_PLUGIN_FEATURE (features->data);
718
719      if (GST_IS_ELEMENT_FACTORY (feature)) {
720        GstElementFactory *factory;
721
722        factory = GST_ELEMENT_FACTORY (feature);
723        g_print ("%s:  %s: %s\n", plugin->desc.name,
724            GST_PLUGIN_FEATURE_NAME (factory), factory->details.longname);
725      }
726#ifndef GST_DISABLE_INDEX
727      else if (GST_IS_INDEX_FACTORY (feature)) {
728        GstIndexFactory *factory;
729
730        factory = GST_INDEX_FACTORY (feature);
731        g_print ("%s:  %s: %s\n", plugin->desc.name,
732            GST_PLUGIN_FEATURE_NAME (factory), factory->longdesc);
733      }
734#endif
735      else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
736        GstTypeFindFactory *factory;
737
738        factory = GST_TYPE_FIND_FACTORY (feature);
739        if (factory->extensions) {
740          guint i = 0;
741
742          g_print ("%s type: ", plugin->desc.name);
743          while (factory->extensions[i]) {
744            g_print ("%s%s", i > 0 ? ", " : "", factory->extensions[i]);
745            i++;
746          }
747        } else
748          g_print ("%s type: N/A\n", plugin->desc.name);
749      } else if (GST_IS_SCHEDULER_FACTORY (feature)) {
750        GstSchedulerFactory *factory;
751
752        factory = GST_SCHEDULER_FACTORY (feature);
753        g_print ("%s:  %s: %s\n", plugin->desc.name,
754            GST_PLUGIN_FEATURE_NAME (factory), factory->longdesc);
755      } else {
756        g_print ("%s:  %s (%s)\n", plugin->desc.name,
757            GST_PLUGIN_FEATURE_NAME (feature),
758            g_type_name (G_OBJECT_TYPE (feature)));
759      }
760
761      features = g_list_next (features);
762    }
763  }
764}
765
766static void
767print_plugin_info (GstPlugin * plugin)
768{
769  GList *features;
770  gint num_features = 0;
771  gint num_elements = 0;
772  gint num_autoplug = 0;
773  gint num_types = 0;
774  gint num_schedulers = 0;
775  gint num_indexes = 0;
776  gint num_other = 0;
777
778  g_print ("Plugin Details:\n");
779  g_print ("  Name:\t\t%s\n", plugin->desc.name);
780  g_print ("  Description:\t%s\n", plugin->desc.description);
781  g_print ("  Filename:\t%s\n", plugin->filename);
782  g_print ("  Version:\t%s\n", plugin->desc.version);
783  g_print ("  License:\t%s\n", plugin->desc.license);
784  g_print ("  Package:\t%s\n", plugin->desc.package);
785  g_print ("  Origin URL:\t%s\n", plugin->desc.origin);
786  g_print ("\n");
787
788  features = gst_plugin_get_feature_list (plugin);
789
790  while (features) {
791    GstPluginFeature *feature;
792
793    feature = GST_PLUGIN_FEATURE (features->data);
794
795    if (GST_IS_ELEMENT_FACTORY (feature)) {
796      GstElementFactory *factory;
797
798      factory = GST_ELEMENT_FACTORY (feature);
799      g_print ("  %s: %s\n", GST_OBJECT_NAME (factory),
800          factory->details.longname);
801      num_elements++;
802    }
803#ifndef GST_DISABLE_INDEX
804    else if (GST_IS_INDEX_FACTORY (feature)) {
805      GstIndexFactory *factory;
806
807      factory = GST_INDEX_FACTORY (feature);
808      g_print ("  %s: %s\n", GST_OBJECT_NAME (factory), factory->longdesc);
809      num_indexes++;
810    }
811#endif
812    else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
813      GstTypeFindFactory *factory;
814
815      factory = GST_TYPE_FIND_FACTORY (feature);
816      if (factory->extensions) {
817        guint i = 0;
818
819        g_print ("%s type: ", plugin->desc.name);
820        while (factory->extensions[i]) {
821          g_print ("%s%s", i > 0 ? ", " : "", factory->extensions[i]);
822          i++;
823        }
824      } else
825        g_print ("%s type: N/A\n", plugin->desc.name);
826      num_types++;
827    } else if (GST_IS_SCHEDULER_FACTORY (feature)) {
828      GstSchedulerFactory *factory;
829
830      factory = GST_SCHEDULER_FACTORY (feature);
831      g_print ("  %s: %s\n", GST_OBJECT_NAME (factory), factory->longdesc);
832      num_schedulers++;
833    } else {
834      g_print ("  %s (%s)\n", gst_object_get_name (GST_OBJECT (feature)),
835          g_type_name (G_OBJECT_TYPE (feature)));
836      num_other++;
837    }
838    num_features++;
839    features = g_list_next (features);
840  }
841  g_print ("\n  %d features:\n", num_features);
842  if (num_elements > 0)
843    g_print ("  +-- %d elements\n", num_elements);
844  if (num_autoplug > 0)
845    g_print ("  +-- %d autopluggers\n", num_autoplug);
846  if (num_types > 0)
847    g_print ("  +-- %d types\n", num_types);
848  if (num_schedulers > 0)
849    g_print ("  +-- %d schedulers\n", num_schedulers);
850  if (num_indexes > 0)
851    g_print ("  +-- %d indexes\n", num_indexes);
852  if (num_other > 0)
853    g_print ("  +-- %d other objects\n", num_other);
854
855  g_print ("\n");
856}
857
858
859int
860main (int argc, char *argv[])
861{
862  GstElementFactory *factory;
863  GstPlugin *plugin;
864  gchar *so;
865  struct poptOption options[] = {
866    {"gst-inspect-plugin", 'p', POPT_ARG_STRING | POPT_ARGFLAG_STRIP, NULL, 0,
867        "Show plugin details", NULL},
868    {"gst-inspect-scheduler", 's', POPT_ARG_STRING | POPT_ARGFLAG_STRIP, NULL,
869          0,
870        "Show scheduler details", NULL},
871    POPT_TABLEEND
872  };
873
874  setlocale (LC_ALL, "");
875
876  gst_init_with_popt_table (&argc, &argv, options);
877  gst_control_init (&argc, &argv);
878
879  PUT_STRING (0, "<?xml version=\"1.0\"?>");
880
881  /* if no arguments, print out list of elements */
882  if (argc == 1) {
883    print_element_list ();
884
885    /* else we try to get a factory */
886  } else {
887    /* first check for help */
888    if (strstr (argv[1], "-help")) {
889      g_print ("Usage: %s\t\t\tList all registered elements\n", argv[0]);
890      g_print ("       %s element-name\tShow element details\n", argv[0]);
891      g_print ("       %s plugin-name[.so]\tShow information about plugin\n",
892          argv[0]);
893      return 0;
894    }
895
896    /* only search for a factory if there's not a '.so' */
897    if (!strstr (argv[1], ".so")) {
898      factory = gst_element_factory_find (argv[1]);
899
900      /* if there's a factory, print out the info */
901      if (factory)
902        return print_element_info (factory);
903      else {
904        GstPluginFeature *feature;
905
906        /* FIXME implement other pretty print function for these */
907        feature = gst_registry_pool_find_feature (argv[1],
908            GST_TYPE_SCHEDULER_FACTORY);
909        if (feature) {
910          g_print ("%s: a scheduler\n", argv[1]);
911          return 0;
912        }
913#ifndef GST_DISABLE_INDEX
914        feature = gst_registry_pool_find_feature (argv[1],
915            GST_TYPE_INDEX_FACTORY);
916        if (feature) {
917          g_print ("%s: an index\n", argv[1]);
918          return 0;
919        }
920#endif
921        feature = gst_registry_pool_find_feature (argv[1],
922            GST_TYPE_TYPE_FIND_FACTORY);
923        if (feature) {
924          g_print ("%s: a type find function\n", argv[1]);
925          return 0;
926        }
927#ifndef GST_DISABLE_URI
928        feature = gst_registry_pool_find_feature (argv[1],
929            GST_TYPE_URI_HANDLER);
930        if (feature) {
931          g_print ("%s: an uri handler\n", argv[1]);
932          return 0;
933        }
934#endif
935      }
936    } else {
937      /* strip the .so */
938      so = strstr (argv[1], ".so");
939      so[0] = '\0';
940    }
941
942    /* otherwise assume it's a plugin */
943    plugin = gst_registry_pool_find_plugin (argv[1]);
944
945    /* if there is such a plugin, print out info */
946
947    if (plugin) {
948      print_plugin_info (plugin);
949    } else {
950      g_print ("no such element or plugin '%s'\n", argv[1]);
951      return -1;
952    }
953  }
954
955  return 0;
956}
Note: See TracBrowser for help on using the repository browser.