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

Revision 21448, 32.5 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21447, 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 (GST_PAD (realpad)) == GST_PAD_SRC)
647      g_print ("  SRC: '%s'", gst_pad_get_name (pad));
648    else if (gst_pad_get_direction (GST_PAD (realpad)) == GST_PAD_SINK)
649      g_print ("  SINK: '%s'", gst_pad_get_name (pad));
650    else
651      g_print ("  UNKNOWN!!!: '%s'", 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        if (G_TYPE_IS_FUNDAMENTAL (query->param_types[j])) {
826          g_print (",\n%s%s%s arg%d", _name, indent,
827              g_type_name (query->param_types[j]), j);
828        } else {
829          g_print (",\n%s%s%s* arg%d", _name, indent,
830              g_type_name (query->param_types[j]), j);
831        }
832      }
833
834      if (k == 0)
835        g_print (",\n%s%sgpointer user_data);\n", _name, indent);
836      else
837        g_print (");\n");
838
839      g_free (indent);
840    }
841
842    if (found_signals) {
843      g_slist_foreach (found_signals, (GFunc) g_free, NULL);
844      g_slist_free (found_signals);
845    }
846  }
847}
848
849static void
850print_children_info (GstElement * element)
851{
852  GList *children;
853
854  if (!GST_IS_BIN (element))
855    return;
856
857  children = (GList *) gst_bin_get_list (GST_BIN (element));
858  if (children) {
859    n_print ("\n");
860    g_print ("Children:\n");
861  }
862
863  while (children) {
864    n_print ("  %s\n", GST_ELEMENT_NAME (GST_ELEMENT (children->data)));
865    children = g_list_next (children);
866  }
867}
868
869static void
870print_element_list (gboolean print_all)
871{
872  GList *plugins;
873
874  plugins = gst_registry_pool_plugin_list ();
875  while (plugins) {
876    GList *features;
877    GstPlugin *plugin;
878
879    plugin = (GstPlugin *) (plugins->data);
880    plugins = g_list_next (plugins);
881
882    features = gst_plugin_get_feature_list (plugin);
883    while (features) {
884      GstPluginFeature *feature;
885
886      feature = GST_PLUGIN_FEATURE (features->data);
887
888      if (GST_IS_ELEMENT_FACTORY (feature)) {
889        GstElementFactory *factory;
890
891        factory = GST_ELEMENT_FACTORY (feature);
892        if (print_all)
893          print_element_info (factory, TRUE);
894        else
895          g_print ("%s:  %s: %s\n", plugin->desc.name,
896              GST_PLUGIN_FEATURE_NAME (factory), factory->details.longname);
897      }
898#ifndef GST_DISABLE_INDEX
899      else if (GST_IS_INDEX_FACTORY (feature)) {
900        GstIndexFactory *factory;
901
902        factory = GST_INDEX_FACTORY (feature);
903        if (!print_all)
904          g_print ("%s:  %s: %s\n", plugin->desc.name,
905              GST_PLUGIN_FEATURE_NAME (factory), factory->longdesc);
906      }
907#endif
908      else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
909        GstTypeFindFactory *factory;
910
911        factory = GST_TYPE_FIND_FACTORY (feature);
912        if (!print_all)
913          g_print ("%s: %s: ", plugin->desc.name,
914              gst_plugin_feature_get_name (feature));
915        if (factory->extensions) {
916          guint i = 0;
917
918          while (factory->extensions[i]) {
919            if (!print_all)
920              g_print ("%s%s", i > 0 ? ", " : "", factory->extensions[i]);
921            i++;
922          }
923          if (!print_all)
924            g_print ("\n");
925        } else {
926          if (!print_all)
927            g_print ("no extensions\n");
928        }
929      } else if (GST_IS_SCHEDULER_FACTORY (feature)) {
930        GstSchedulerFactory *factory;
931
932        factory = GST_SCHEDULER_FACTORY (feature);
933        if (!print_all)
934          g_print ("%s:  %s: %s\n", plugin->desc.name,
935              GST_PLUGIN_FEATURE_NAME (factory), factory->longdesc);
936      } else {
937        if (!print_all)
938          n_print ("%s:  %s (%s)\n", plugin->desc.name,
939              GST_PLUGIN_FEATURE_NAME (feature),
940              g_type_name (G_OBJECT_TYPE (feature)));
941      }
942
943      features = g_list_next (features);
944    }
945  }
946}
947
948static void
949print_plugin_info (GstPlugin * plugin)
950{
951  n_print ("Plugin Details:\n");
952  n_print ("  Name:\t\t%s\n", plugin->desc.name);
953  n_print ("  Description:\t%s\n", plugin->desc.description);
954  n_print ("  Filename:\t%s\n", plugin->filename ? plugin->filename : "(null)");
955  n_print ("  Version:\t%s\n", plugin->desc.version);
956  n_print ("  License:\t%s\n", plugin->desc.license);
957  n_print ("  Package:\t%s\n", plugin->desc.package);
958  n_print ("  Origin URL:\t%s\n", plugin->desc.origin);
959  n_print ("\n");
960}
961
962static void
963print_plugin_features (GstPlugin * plugin)
964{
965  GList *features;
966  gint num_features = 0;
967  gint num_elements = 0;
968  gint num_types = 0;
969  gint num_schedulers = 0;
970  gint num_indexes = 0;
971  gint num_other = 0;
972
973  features = gst_plugin_get_feature_list (plugin);
974
975  while (features) {
976    GstPluginFeature *feature;
977
978    feature = GST_PLUGIN_FEATURE (features->data);
979
980    if (GST_IS_ELEMENT_FACTORY (feature)) {
981      GstElementFactory *factory;
982
983      factory = GST_ELEMENT_FACTORY (feature);
984      n_print ("  %s: %s\n", GST_OBJECT_NAME (factory),
985          factory->details.longname);
986      num_elements++;
987    }
988#ifndef GST_DISABLE_INDEX
989    else if (GST_IS_INDEX_FACTORY (feature)) {
990      GstIndexFactory *factory;
991
992      factory = GST_INDEX_FACTORY (feature);
993      n_print ("  %s: %s\n", GST_OBJECT_NAME (factory), factory->longdesc);
994      num_indexes++;
995    }
996#endif
997    else if (GST_IS_TYPE_FIND_FACTORY (feature)) {
998      GstTypeFindFactory *factory;
999
1000      factory = GST_TYPE_FIND_FACTORY (feature);
1001      if (factory->extensions) {
1002        guint i = 0;
1003
1004        g_print ("%s type: ", plugin->desc.name);
1005        while (factory->extensions[i]) {
1006          g_print ("%s%s", i > 0 ? ", " : "", factory->extensions[i]);
1007          i++;
1008        }
1009        g_print ("\n");
1010      } else
1011        g_print ("%s type: N/A\n", plugin->desc.name);
1012
1013      num_types++;
1014    } else if (GST_IS_SCHEDULER_FACTORY (feature)) {
1015      GstSchedulerFactory *factory;
1016
1017      factory = GST_SCHEDULER_FACTORY (feature);
1018      n_print ("  %s: %s\n", GST_OBJECT_NAME (factory), factory->longdesc);
1019      num_schedulers++;
1020    } else {
1021      n_print ("  %s (%s)\n", gst_object_get_name (GST_OBJECT (feature)),
1022          g_type_name (G_OBJECT_TYPE (feature)));
1023      num_other++;
1024    }
1025    num_features++;
1026    features = g_list_next (features);
1027  }
1028  n_print ("\n");
1029  n_print ("  %d features:\n", num_features);
1030  if (num_elements > 0)
1031    n_print ("  +-- %d elements\n", num_elements);
1032  if (num_types > 0)
1033    n_print ("  +-- %d types\n", num_types);
1034  if (num_schedulers > 0)
1035    n_print ("  +-- %d schedulers\n", num_schedulers);
1036  if (num_indexes > 0)
1037    n_print ("  +-- %d indexes\n", num_indexes);
1038  if (num_other > 0)
1039    n_print ("  +-- %d other objects\n", num_other);
1040
1041  n_print ("\n");
1042}
1043
1044static int
1045print_element_features (const gchar * element_name)
1046{
1047  GstPluginFeature *feature;
1048
1049  /* FIXME implement other pretty print function for these */
1050  feature = gst_registry_pool_find_feature (element_name,
1051      GST_TYPE_SCHEDULER_FACTORY);
1052  if (feature) {
1053    n_print ("%s: a scheduler\n", element_name);
1054    return 0;
1055  }
1056#ifndef GST_DISABLE_INDEX
1057  feature = gst_registry_pool_find_feature (element_name,
1058      GST_TYPE_INDEX_FACTORY);
1059  if (feature) {
1060    n_print ("%s: an index\n", element_name);
1061    return 0;
1062  }
1063#endif
1064  feature = gst_registry_pool_find_feature (element_name,
1065      GST_TYPE_TYPE_FIND_FACTORY);
1066  if (feature) {
1067    n_print ("%s: a typefind function\n", element_name);
1068    return 0;
1069  }
1070#ifndef GST_DISABLE_URI
1071  feature = gst_registry_pool_find_feature (element_name, GST_TYPE_URI_HANDLER);
1072  if (feature) {
1073    n_print ("%s: an uri handler\n", element_name);
1074    return 0;
1075  }
1076#endif
1077
1078  return -1;
1079}
1080
1081static int
1082print_element_info (GstElementFactory * factory, gboolean print_names)
1083{
1084  GstElement *element;
1085  gint maxlevel = 0;
1086
1087  element = gst_element_factory_create (factory, NULL);
1088  if (!element) {
1089    g_print ("couldn't construct element for some reason\n");
1090    return -1;
1091  }
1092
1093  if (print_names)
1094    _name = g_strdup_printf ("%s: ", GST_PLUGIN_FEATURE (factory)->name);
1095  else
1096    _name = "";
1097
1098  print_factory_details_info (factory);
1099  if (GST_PLUGIN_FEATURE (factory)->manager) {
1100    GstPlugin *plugin = (GstPlugin *) GST_PLUGIN_FEATURE (factory)->manager;
1101
1102    print_plugin_info (plugin);
1103  }
1104
1105  print_hierarchy (G_OBJECT_TYPE (element), 0, &maxlevel);
1106
1107  print_pad_templates_info (element, factory);
1108  print_element_flag_info (element);
1109  print_implementation_info (element);
1110  print_clocking_info (element);
1111  print_index_info (element);
1112  print_pad_info (element);
1113  print_element_properties_info (element);
1114  print_dynamic_parameters_info (element);
1115  print_signal_info (element);
1116  print_children_info (element);
1117
1118  if (_name != "")
1119    g_free (_name);
1120
1121  return 0;
1122}
1123
1124int
1125main (int argc, char *argv[])
1126{
1127  gboolean print_all = FALSE;
1128  struct poptOption options[] = {
1129    {"print-all", 'a', POPT_ARG_NONE | POPT_ARGFLAG_STRIP, &print_all, 0,
1130        N_("Print all elements"), NULL},
1131    POPT_TABLEEND
1132  };
1133
1134#ifdef GETTEXT_PACKAGE
1135  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
1136  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
1137  textdomain (GETTEXT_PACKAGE);
1138#endif
1139
1140  gst_init_with_popt_table (&argc, &argv, options);
1141  gst_control_init (&argc, &argv);
1142
1143  if (print_all && argc > 2) {
1144    g_print ("-a requires no extra arguments\n");
1145    return 1;
1146  }
1147
1148  /* if no arguments, print out list of elements */
1149  if (argc == 1 || print_all) {
1150    print_element_list (print_all);
1151    /* else we try to get a factory */
1152  } else {
1153    GstElementFactory *factory;
1154    GstPlugin *plugin;
1155    const char *arg = argv[argc - 1];
1156    int retval;
1157
1158    factory = gst_element_factory_find (arg);
1159    /* if there's a factory, print out the info */
1160    if (factory) {
1161      retval = print_element_info (factory, print_all);
1162    } else {
1163      retval = print_element_features (arg);
1164    }
1165
1166    /* otherwise check if it's a plugin */
1167    if (retval) {
1168      plugin = gst_registry_pool_find_plugin (arg);
1169
1170      /* if there is such a plugin, print out info */
1171      if (plugin) {
1172        print_plugin_info (plugin);
1173        print_plugin_features (plugin);
1174      } else {
1175        g_print ("No such element or plugin '%s'\n", arg);
1176        return -1;
1177      }
1178    }
1179  }
1180
1181  return 0;
1182}
Note: See TracBrowser for help on using the repository browser.