gst-xmlinspect.c 20 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/* GStreamer gst-xmlinspect
 * Copyright (C) 2003 Wim Taymans <wtay@chello.be>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

/* FIXME 0.11: remove gst-xmlinspect and gst-feedback etc. */
21
22
23
24
#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

25
#include <string.h>
David Schleef's avatar
David Schleef committed
26
#include <locale.h>
27
#include <glib/gprintf.h>
28

29
30
#include "tools.h"

Christian Meyer's avatar
Christian Meyer committed
31
#define PUT_START_TAG(pfx,tag)                                  \
32
G_STMT_START{                                                   \
Christian Meyer's avatar
Christian Meyer committed
33
  g_print ("%*.*s<%s>\n", pfx, pfx, "", tag);                   \
34
35
}G_STMT_END

Christian Meyer's avatar
Christian Meyer committed
36
#define PUT_END_TAG(pfx,tag)                                    \
37
G_STMT_START{                                                   \
Christian Meyer's avatar
Christian Meyer committed
38
  g_print ("%*.*s</%s>\n", pfx, pfx, "", tag);                  \
39
40
41
42
43
44
45
}G_STMT_END

#define PUT_ESCAPED(pfx,tag,value)                              \
G_STMT_START{                                                   \
  const gchar *toconv = value;                                  \
  if (value) {                                                  \
    gchar *v = g_markup_escape_text (toconv, strlen (toconv));  \
Christian Meyer's avatar
Christian Meyer committed
46
    g_print ("%*.*s<%s>%s</%s>\n", pfx, pfx, "", tag, v, tag);  \
47
48
49
50
    g_free (v);                                                 \
  }                                                             \
}G_STMT_END

51
52
#ifdef G_HAVE_ISO_VARARGS

Christian Meyer's avatar
Christian Meyer committed
53
#define PUT_STRING(pfx, ...)                                    \
54
55
56
57
58
59
60
61
G_STMT_START{                                                   \
  gchar *ps_val = g_strdup_printf(__VA_ARGS__);                 \
  g_print ("%*.*s%s\n", pfx, pfx, "", ps_val);                  \
  g_free(ps_val);                                               \
}G_STMT_END

#elif defined(G_HAVE_GNUC_VARARGS)

Christian Meyer's avatar
Christian Meyer committed
62
#define PUT_STRING(pfx, str, a...)                              \
63
G_STMT_START{                                                   \
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
64
  g_print ("%*.*s"str"\n", pfx, pfx, "" , ##a);                 \
65
66
}G_STMT_END

67
68
69
70
71
72
73
74
75
76
77
78
79
80
#else

static inline void
PUT_STRING (int pfx, const char *format, ...)
{
  va_list varargs;

  g_print ("%*.*s", pfx, pfx, "");
  va_start (varargs, format);
  g_vprintf (format, varargs);
  va_end (varargs);
  g_print ("\n");
}

81
82
#endif

Christian Meyer's avatar
Christian Meyer committed
83
static void
84
print_caps (const GstCaps * caps, gint pfx)
85
{
David Schleef's avatar
David Schleef committed
86
  char *s;
87
88
89
90

  if (!caps)
    return;

David Schleef's avatar
David Schleef committed
91
92
  s = gst_caps_to_string (caps);
  PUT_ESCAPED (pfx, "caps", s);
93
  g_free (s);
94
95
}

96
#if 0
Christian Meyer's avatar
Christian Meyer committed
97
static void
98
print_formats (const GstFormat * formats, gint pfx)
99
100
101
102
103
104
105
{
  while (formats && *formats) {
    const GstFormatDefinition *definition;

    definition = gst_format_get_details (*formats);
    if (definition)
      PUT_STRING (pfx, "<format id=\"%d\" nick=\"%s\">%s</format>",
106
          *formats, definition->nick, definition->description);
107
    else
108
      PUT_STRING (pfx, "<format id=\"%d\">unknown</format>", *formats);
109
110
111
112

    formats++;
  }
}
113
#endif
114

Christian Meyer's avatar
Christian Meyer committed
115
static void
116
print_query_types (const GstQueryType * types, gint pfx)
117
118
119
120
121
122
123
{
  while (types && *types) {
    const GstQueryTypeDefinition *definition;

    definition = gst_query_type_get_details (*types);
    if (definition)
      PUT_STRING (pfx, "<query-type id=\"%d\" nick=\"%s\">%s</query-type>",
124
          *types, definition->nick, definition->description);
125
    else
126
      PUT_STRING (pfx, "<query-type id=\"%d\">unknown</query-type>", *types);
127
128
129
130
131

    types++;
  }
}

132
#if 0
Christian Meyer's avatar
Christian Meyer committed
133
static void
134
print_event_masks (const GstEventMask * masks, gint pfx)
135
136
137
138
139
140
{
  GType event_type;
  GEnumClass *klass;
  GType event_flags;
  GFlagsClass *flags_class = NULL;

141
  event_type = gst_event_type_get_type ();
142
143
144
145
146
147
148
149
  klass = (GEnumClass *) g_type_class_ref (event_type);

  while (masks && masks->type) {
    GEnumValue *value;
    gint flags = 0, index = 0;

    switch (masks->type) {
      case GST_EVENT_SEEK:
150
151
152
153
        flags = masks->flags;
        event_flags = gst_seek_type_get_type ();
        flags_class = (GFlagsClass *) g_type_class_ref (event_flags);
        break;
154
      default:
155
        break;
156
    }
Christian Meyer's avatar
Christian Meyer committed
157

158
    value = g_enum_get_value (klass, masks->type);
159
    PUT_STRING (pfx, "<event type=\"%s\">", value->value_nick);
160
161
162
163
164

    while (flags) {
      GFlagsValue *value;

      if (flags & 1) {
165
        value = g_flags_get_first_value (flags_class, 1 << index);
166

167
168
169
170
        if (value)
          PUT_ESCAPED (pfx + 1, "flag", value->value_nick);
        else
          PUT_ESCAPED (pfx + 1, "flag", "?");
171
172
173
174
175
      }
      flags >>= 1;
      index++;
    }
    PUT_END_TAG (pfx, "event");
Christian Meyer's avatar
Christian Meyer committed
176

177
178
179
    masks++;
  }
}
180
#endif
181
182

static void
183
output_hierarchy (GType type, gint level, gint * maxlevel)
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
{
  GType parent;

  parent = g_type_parent (type);

  *maxlevel = *maxlevel + 1;
  level++;

  PUT_STRING (level, "<object name=\"%s\">", g_type_name (type));

  if (parent)
    output_hierarchy (parent, level, maxlevel);

  PUT_END_TAG (level, "object");
}

static void
201
print_element_properties (GstElement * element, gint pfx)
202
203
{
  GParamSpec **property_specs;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
204
205
  guint num_properties;
  gint i;
206
  gboolean readable;
Christian Meyer's avatar
Christian Meyer committed
207
208

  property_specs = g_object_class_list_properties
209
      (G_OBJECT_GET_CLASS (element), &num_properties);
210
211
212
213
214
215

  PUT_START_TAG (pfx, "element-properties");

  for (i = 0; i < num_properties; i++) {
    GValue value = { 0, };
    GParamSpec *param = property_specs[i];
216

217
218
219
220
221
222
223
224
225
    readable = FALSE;

    g_value_init (&value, param->value_type);
    if (param->flags & G_PARAM_READABLE) {
      g_object_get_property (G_OBJECT (element), param->name, &value);
      readable = TRUE;
    }
    PUT_START_TAG (pfx + 1, "element-property");
    PUT_ESCAPED (pfx + 2, "name", g_param_spec_get_name (param));
226
    PUT_ESCAPED (pfx + 2, "type", g_type_name (param->value_type));
227
228
229
230
    PUT_ESCAPED (pfx + 2, "nick", g_param_spec_get_nick (param));
    PUT_ESCAPED (pfx + 2, "blurb", g_param_spec_get_blurb (param));
    if (readable) {
      PUT_ESCAPED (pfx + 2, "flags", "RW");
231
    } else {
232
233
234
235
      PUT_ESCAPED (pfx + 2, "flags", "W");
    }

    switch (G_VALUE_TYPE (&value)) {
Christian Meyer's avatar
Christian Meyer committed
236
      case G_TYPE_STRING:
237
238
        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
        break;
Christian Meyer's avatar
Christian Meyer committed
239
      case G_TYPE_BOOLEAN:
240
241
        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
        break;
Christian Meyer's avatar
Christian Meyer committed
242
      case G_TYPE_ULONG:
243
      {
244
        GParamSpecULong *pulong = G_PARAM_SPEC_ULONG (param);
245

246
247
248
249
        PUT_STRING (pfx + 2, "<range min=\"%lu\" max=\"%lu\"/>",
            pulong->minimum, pulong->maximum);
        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
        break;
250
      }
Christian Meyer's avatar
Christian Meyer committed
251
      case G_TYPE_LONG:
252
      {
253
        GParamSpecLong *plong = G_PARAM_SPEC_LONG (param);
254

255
256
257
258
        PUT_STRING (pfx + 2, "<range min=\"%ld\" max=\"%ld\"/>",
            plong->minimum, plong->maximum);
        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
        break;
259
      }
Christian Meyer's avatar
Christian Meyer committed
260
      case G_TYPE_UINT:
261
      {
262
        GParamSpecUInt *puint = G_PARAM_SPEC_UINT (param);
263

264
265
266
267
        PUT_STRING (pfx + 2, "<range min=\"%u\" max=\"%u\"/>",
            puint->minimum, puint->maximum);
        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
        break;
268
      }
Christian Meyer's avatar
Christian Meyer committed
269
      case G_TYPE_INT:
270
      {
271
        GParamSpecInt *pint = G_PARAM_SPEC_INT (param);
272

273
274
275
276
        PUT_STRING (pfx + 2, "<range min=\"%d\" max=\"%d\"/>",
            pint->minimum, pint->maximum);
        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
        break;
277
      }
Christian Meyer's avatar
Christian Meyer committed
278
      case G_TYPE_UINT64:
279
      {
280
        GParamSpecUInt64 *puint64 = G_PARAM_SPEC_UINT64 (param);
281

282
283
284
285
286
        PUT_STRING (pfx + 2,
            "<range min=\"%" G_GUINT64_FORMAT "\" max=\"%" G_GUINT64_FORMAT
            "\"/>", puint64->minimum, puint64->maximum);
        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
        break;
287
      }
Christian Meyer's avatar
Christian Meyer committed
288
      case G_TYPE_INT64:
289
      {
290
        GParamSpecInt64 *pint64 = G_PARAM_SPEC_INT64 (param);
291

292
293
294
295
296
        PUT_STRING (pfx + 2,
            "<range min=\"%" G_GINT64_FORMAT "\" max=\"%" G_GINT64_FORMAT
            "\"/>", pint64->minimum, pint64->maximum);
        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
        break;
297
      }
Christian Meyer's avatar
Christian Meyer committed
298
      case G_TYPE_FLOAT:
299
      {
300
        GParamSpecFloat *pfloat = G_PARAM_SPEC_FLOAT (param);
301

302
303
304
305
        PUT_STRING (pfx + 2, "<range min=\"%f\" max=\"%f\"/>",
            pfloat->minimum, pfloat->maximum);
        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
        break;
306
      }
Christian Meyer's avatar
Christian Meyer committed
307
      case G_TYPE_DOUBLE:
308
      {
309
        GParamSpecDouble *pdouble = G_PARAM_SPEC_DOUBLE (param);
310

311
312
313
314
        PUT_STRING (pfx + 2, "<range min=\"%g\" max=\"%g\"/>",
            pdouble->minimum, pdouble->maximum);
        PUT_ESCAPED (pfx + 2, "default", g_strdup_value_contents (&value));
        break;
315
316
      }
      default:
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
        if (param->value_type == GST_TYPE_CAPS) {
          GstCaps *caps = g_value_peek_pointer (&value);

          if (!caps)
            PUT_ESCAPED (pfx + 2, "default", "NULL");
          else {
            print_caps (caps, 2);
          }
        } else if (G_IS_PARAM_SPEC_ENUM (param)) {
          GEnumValue *values;
          guint j = 0;
          gint enum_value;

          values = G_ENUM_CLASS (g_type_class_ref (param->value_type))->values;
          enum_value = g_value_get_enum (&value);

          while (values[j].value_name) {
            if (values[j].value == enum_value)
              break;
            j++;
          }
          PUT_STRING (pfx + 2, "<default>%d</default>", values[j].value);

          PUT_START_TAG (pfx + 2, "enum-values");
          j = 0;
          while (values[j].value_name) {
            PUT_STRING (pfx + 3, "<value value=\"%d\" nick=\"%s\"/>",
                values[j].value, values[j].value_nick);
            j++;
          }
          PUT_END_TAG (pfx + 2, "enum-values");
        } else if (G_IS_PARAM_SPEC_FLAGS (param)) {
          GFlagsValue *values;
          guint j = 0;
          gint flags_value;

          values = G_FLAGS_CLASS (g_type_class_ref (param->value_type))->values;
          flags_value = g_value_get_flags (&value);

          PUT_STRING (pfx + 2, "<default>%d</default>", flags_value);

          PUT_START_TAG (pfx + 2, "flags");
          j = 0;
          while (values[j].value_name) {
            PUT_STRING (pfx + 3, "<flag value=\"%d\" nick=\"%s\"/>",
                values[j].value, values[j].value_nick);
            j++;
          }
          PUT_END_TAG (pfx + 2, "flags");
        } else if (G_IS_PARAM_SPEC_OBJECT (param)) {
          PUT_ESCAPED (pfx + 2, "object-type", g_type_name (param->value_type));
        }
        break;
370
371
372
373
374
    }

    PUT_END_TAG (pfx + 1, "element-property");
  }
  PUT_END_TAG (pfx, "element-properties");
Stefan Kost's avatar
Stefan Kost committed
375
  g_free (property_specs);
376
377
378
}

static void
379
print_element_signals (GstElement * element, gint pfx)
380
381
382
383
384
{
  guint *signals;
  guint nsignals;
  gint i, k;
  GSignalQuery *query;
Christian Meyer's avatar
Christian Meyer committed
385

386
387
388
389
390
391
392
393
394
395
396
397
398
399
  signals = g_signal_list_ids (G_OBJECT_TYPE (element), &nsignals);
  for (k = 0; k < 2; k++) {
    gint counted = 0;

    if (k == 0)
      PUT_START_TAG (pfx, "element-signals");
    else
      PUT_START_TAG (pfx, "element-actions");

    for (i = 0; i < nsignals; i++) {
      gint n_params;
      GType return_type;
      const GType *param_types;
      gint j;
Christian Meyer's avatar
Christian Meyer committed
400

401
      query = g_new0 (GSignalQuery, 1);
402
403
404
      g_signal_query (signals[i], query);

      if ((k == 0 && !(query->signal_flags & G_SIGNAL_ACTION)) ||
405
406
407
408
          (k == 1 && (query->signal_flags & G_SIGNAL_ACTION))) {
        n_params = query->n_params;
        return_type = query->return_type;
        param_types = query->param_types;
409

410
411
412
413
414
        PUT_START_TAG (pfx + 1, "signal");
        PUT_ESCAPED (pfx + 2, "name", query->signal_name);
        PUT_ESCAPED (pfx + 2, "return-type", g_type_name (return_type));
        PUT_ESCAPED (pfx + 2, "object-type",
            g_type_name (G_OBJECT_TYPE (element)));
415

416
417
418
419
        PUT_START_TAG (pfx + 2, "params");
        for (j = 0; j < n_params; j++) {
          PUT_ESCAPED (pfx + 3, "type", g_type_name (param_types[j]));
        }
420

421
        PUT_END_TAG (pfx + 2, "params");
422

423
        PUT_END_TAG (pfx + 1, "signal");
424

425
        counted++;
426
427
428
429
430
431
432
433
434
435
      }

      g_free (query);
    }
    if (k == 0)
      PUT_END_TAG (pfx, "element-signals");
    else
      PUT_END_TAG (pfx, "element-actions");
  }
}
Christian Meyer's avatar
Christian Meyer committed
436

437
static gint
438
print_element_info (GstElementFactory * factory)
439
440
441
442
443
444
{
  GstElement *element;
  GstObjectClass *gstobject_class;
  GstElementClass *gstelement_class;
  GList *pads;
  GstPad *pad;
445
  GstStaticPadTemplate *padtemplate;
446
447
448
449
450
451
452
453
454
455
456
457
458
459
  gint maxlevel = 0;

  element = gst_element_factory_create (factory, "element");
  if (!element) {
    g_print ("couldn't construct element for some reason\n");
    return -1;
  }
  PUT_START_TAG (0, "element");
  PUT_ESCAPED (1, "name", GST_PLUGIN_FEATURE_NAME (factory));

  gstobject_class = GST_OBJECT_CLASS (G_OBJECT_GET_CLASS (element));
  gstelement_class = GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS (element));

  PUT_START_TAG (1, "details");
460
461
462
463
  PUT_ESCAPED (2, "long-name", factory->details.longname);
  PUT_ESCAPED (2, "class", factory->details.klass);
  PUT_ESCAPED (2, "description", factory->details.description);
  PUT_ESCAPED (2, "authors", factory->details.author);
464
465
466
467
468
469
  PUT_END_TAG (1, "details");

  output_hierarchy (G_OBJECT_TYPE (element), 0, &maxlevel);

  PUT_START_TAG (1, "pad-templates");
  if (factory->numpadtemplates) {
470
    pads = factory->staticpadtemplates;
471
    while (pads) {
472
      padtemplate = (GstStaticPadTemplate *) (pads->data);
473
      pads = g_list_next (pads);
474
475

      PUT_START_TAG (2, "pad-template");
476
      PUT_ESCAPED (3, "name", padtemplate->name_template);
477
478

      if (padtemplate->direction == GST_PAD_SRC)
479
        PUT_ESCAPED (3, "direction", "src");
480
      else if (padtemplate->direction == GST_PAD_SINK)
481
        PUT_ESCAPED (3, "direction", "sink");
482
      else
483
        PUT_ESCAPED (3, "direction", "unknown");
484
485

      if (padtemplate->presence == GST_PAD_ALWAYS)
486
        PUT_ESCAPED (3, "presence", "always");
487
      else if (padtemplate->presence == GST_PAD_SOMETIMES)
488
        PUT_ESCAPED (3, "presence", "sometimes");
489
      else if (padtemplate->presence == GST_PAD_REQUEST) {
490
491
492
        PUT_ESCAPED (3, "presence", "request");
        PUT_ESCAPED (3, "request-function",
            GST_DEBUG_FUNCPTR_NAME (gstelement_class->request_new_pad));
493
      } else
494
        PUT_ESCAPED (3, "presence", "unknown");
495

496
497
      if (padtemplate->static_caps.string) {
        print_caps (gst_static_caps_get (&padtemplate->static_caps), 3);
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
      }
      PUT_END_TAG (2, "pad-template");
    }
  }
  PUT_END_TAG (1, "pad-templates");

  PUT_START_TAG (1, "element-flags");
  PUT_END_TAG (1, "element-flags");

  if (GST_IS_BIN (element)) {
    PUT_START_TAG (1, "bin-flags");

    PUT_END_TAG (1, "bin-flags");
  }


  PUT_START_TAG (1, "element-implementation");

Christian Meyer's avatar
Christian Meyer committed
516
  PUT_STRING (2, "<state-change function=\"%s\"/>",
517
      GST_DEBUG_FUNCPTR_NAME (gstelement_class->change_state));
518
519

#ifndef GST_DISABLE_LOADSAVE
Christian Meyer's avatar
Christian Meyer committed
520
  PUT_STRING (2, "<save function=\"%s\"/>",
521
      GST_DEBUG_FUNCPTR_NAME (gstobject_class->save_thyself));
Christian Meyer's avatar
Christian Meyer committed
522
  PUT_STRING (2, "<load function=\"%s\"/>",
523
      GST_DEBUG_FUNCPTR_NAME (gstobject_class->restore_thyself));
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
#endif
  PUT_END_TAG (1, "element-implementation");

  PUT_START_TAG (1, "clocking-interaction");
  if (gst_element_requires_clock (element)) {
    PUT_STRING (2, "<requires-clock/>");
  }
  if (gst_element_provides_clock (element)) {
    GstClock *clock;

    clock = gst_element_get_clock (element);
    if (clock)
      PUT_STRING (2, "<provides-clock name=\"%s\"/>", GST_OBJECT_NAME (clock));
  }
  PUT_END_TAG (1, "clocking-interaction");

  if (gst_element_is_indexable (element)) {
    PUT_STRING (1, "<indexing-capabilities/>");
  }

  PUT_START_TAG (1, "pads");
  if (element->numpads) {
    const GList *pads;
547

548
    pads = element->pads;
549
550
551
552
553
    while (pads) {
      pad = GST_PAD (pads->data);
      pads = g_list_next (pads);

      PUT_START_TAG (2, "pad");
554
      PUT_ESCAPED (3, "name", gst_pad_get_name (pad));
555
556

      if (gst_pad_get_direction (pad) == GST_PAD_SRC)
557
        PUT_ESCAPED (3, "direction", "src");
558
      else if (gst_pad_get_direction (pad) == GST_PAD_SINK)
559
        PUT_ESCAPED (3, "direction", "sink");
560
      else
561
        PUT_ESCAPED (3, "direction", "unknown");
562
563

      if (pad->padtemplate)
564
        PUT_ESCAPED (3, "template", pad->padtemplate->name_template);
565
566

      PUT_START_TAG (3, "implementation");
567
      if (pad->chainfunc)
568
        PUT_STRING (4, "<chain-based function=\"%s\"/>",
569
570
            GST_DEBUG_FUNCPTR_NAME (pad->chainfunc));
      if (pad->getrangefunc)
Wim Taymans's avatar
Wim Taymans committed
571
        PUT_STRING (4, "<get-range-based function=\"%s\"/>",
572
573
            GST_DEBUG_FUNCPTR_NAME (pad->getrangefunc));
      if (pad->eventfunc != gst_pad_event_default)
574
        PUT_STRING (4, "<event-function function=\"%s\"/>",
575
576
            GST_DEBUG_FUNCPTR_NAME (pad->eventfunc));
      if (pad->queryfunc != gst_pad_query_default)
577
        PUT_STRING (4, "<query-function function=\"%s\"/>",
578
579
            GST_DEBUG_FUNCPTR_NAME (pad->queryfunc));
      if (pad->querytypefunc != gst_pad_get_query_types_default) {
580
        PUT_STRING (4, "<query-type-func function=\"%s\">",
581
582
            GST_DEBUG_FUNCPTR_NAME (pad->querytypefunc));
        print_query_types (gst_pad_get_query_types (pad), 5);
583
        PUT_END_TAG (4, "query-type-func");
584
585
      }

586
587
588
      if (pad->iterintlinkfunc != gst_pad_iterate_internal_links_default)
        PUT_STRING (4, "<iterintlink-function function=\"%s\"/>",
            GST_DEBUG_FUNCPTR_NAME (pad->iterintlinkfunc));
589

590
      if (pad->bufferallocfunc)
591
        PUT_STRING (4, "<bufferalloc-function function=\"%s\"/>",
592
            GST_DEBUG_FUNCPTR_NAME (pad->bufferallocfunc));
593
594
      PUT_END_TAG (3, "implementation");

595
596
      if (pad->caps) {
        print_caps (pad->caps, 3);
597
598
599
600
601
602
603
604
605
606
      }
      PUT_END_TAG (2, "pad");
    }
  }
  PUT_END_TAG (1, "pads");

  print_element_properties (element, 1);
  print_element_signals (element, 1);

  /* for compound elements */
Wim Taymans's avatar
Wim Taymans committed
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
  /* FIXME: gst_bin_get_list does not exist anymore
     if (GST_IS_BIN (element)) {
     GList *children;
     GstElement *child;
     PUT_START_TAG (1, "children");
     children = (GList *) gst_bin_get_list (GST_BIN (element));
     while (children) {
     child = GST_ELEMENT (children->data);
     children = g_list_next (children);

     PUT_ESCAPED (2, "child", GST_ELEMENT_NAME (child));
     }
     PUT_END_TAG (1, "children");
     }
   */
622
623
624
625
626
  PUT_END_TAG (0, "element");

  return 0;
}

Christian Meyer's avatar
Christian Meyer committed
627
628
int
main (int argc, char *argv[])
629
630
{
  GstElementFactory *factory;
631
  GOptionEntry options[] = {
632
    GST_TOOLS_GOPTION_VERSION,
633
    {NULL}
634
  };
635
636
  GOptionContext *ctx;
  GError *err = NULL;
637

David Schleef's avatar
David Schleef committed
638
639
  setlocale (LC_ALL, "");

640
641
642
  if (!g_thread_supported ())
    g_thread_init (NULL);

643
644
  gst_tools_print_version ("gst-xmlinspect");

645
  ctx = g_option_context_new ("[ELEMENT-NAME]");
646
647
648
649
650
651
  g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE);
  g_option_context_add_group (ctx, gst_init_get_option_group ());
  if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
    g_print ("Error initializing: %s\n", err->message);
    exit (1);
  }
652
  g_option_context_free (ctx);
Christian Meyer's avatar
Christian Meyer committed
653

654
  /* if no arguments, print out all elements */
655
  if (argc == 1) {
656
    GList *features, *f;
657

658
659
    features = gst_registry_get_feature_list (gst_registry_get_default (),
        GST_TYPE_ELEMENT_FACTORY);
660

661
    PUT_STRING (0, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
662

663
664
    for (f = features; f != NULL; f = f->next)
      print_element_info (GST_ELEMENT_FACTORY (f->data));
665

666
667
668
    gst_plugin_feature_list_free (features);
    return 0;
  }
669

670
671
  /* else we try to get a factory */
  factory = gst_element_factory_find (argv[1]);
672

673
674
675
676
  /* if there's a factory, print out the info */
  if (factory) {
    PUT_STRING (0, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
    return print_element_info (factory);
677
678
  }

679
680
681
  /* otherwise, error out */
  g_printerr ("no such element '%s'\n", argv[1]);
  return -1;
682
}