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

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