discoverer: Add APIs to simply get installer details for missing plugins
[platform/upstream/gstreamer.git] / gst-libs / gst / pbutils / gstdiscoverer-types.c
1 /* GStreamer
2  * Copyright (C) 2010 Collabora Multimedia
3  *               2010 Nokia Corporation
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "pbutils.h"
26 #include "pbutils-private.h"
27
28 static GstDiscovererStreamInfo
29     * gst_discoverer_info_copy_int (GstDiscovererStreamInfo * info,
30     GHashTable * stream_map);
31
32 static GstDiscovererContainerInfo
33     * gst_stream_container_info_copy_int (GstDiscovererContainerInfo * ptr,
34     GHashTable * stream_map);
35
36 static GstDiscovererAudioInfo
37     * gst_discoverer_audio_info_copy_int (GstDiscovererAudioInfo * ptr);
38
39 static GstDiscovererVideoInfo
40     * gst_discoverer_video_info_copy_int (GstDiscovererVideoInfo * ptr);
41
42 static GstDiscovererSubtitleInfo
43     * gst_discoverer_subtitle_info_copy_int (GstDiscovererSubtitleInfo * ptr);
44
45 /* Per-stream information */
46
47 G_DEFINE_TYPE (GstDiscovererStreamInfo, gst_discoverer_stream_info,
48     G_TYPE_OBJECT);
49
50 static void
51 gst_discoverer_stream_info_init (GstDiscovererStreamInfo * info)
52 {
53   /* Nothing needs initialization */
54 }
55
56 static void
57 gst_discoverer_stream_info_finalize (GObject * object)
58 {
59   GstDiscovererStreamInfo *info = (GstDiscovererStreamInfo *) object;
60
61   if (info->next)
62     g_object_unref ((GObject *) info->next);
63
64   if (info->caps)
65     gst_caps_unref (info->caps);
66
67   if (info->tags)
68     gst_tag_list_unref (info->tags);
69
70   if (info->toc)
71     gst_toc_unref (info->toc);
72
73   g_free (info->stream_id);
74
75   if (info->misc)
76     gst_structure_free (info->misc);
77 }
78
79 static void
80 gst_discoverer_stream_info_class_init (GObjectClass * klass)
81 {
82   klass->finalize = gst_discoverer_stream_info_finalize;
83 }
84
85 static GstDiscovererStreamInfo *
86 gst_discoverer_stream_info_new (void)
87 {
88   return (GstDiscovererStreamInfo *)
89       g_object_new (GST_TYPE_DISCOVERER_STREAM_INFO, NULL);
90 }
91
92 static GstDiscovererStreamInfo *
93 gst_discoverer_info_copy_int (GstDiscovererStreamInfo * info,
94     GHashTable * stream_map)
95 {
96   GstDiscovererStreamInfo *ret;
97   GType ltyp;
98
99   g_return_val_if_fail (info != NULL, NULL);
100
101   ltyp = G_TYPE_FROM_INSTANCE (info);
102
103   if (ltyp == GST_TYPE_DISCOVERER_CONTAINER_INFO) {
104     ret = (GstDiscovererStreamInfo *)
105         gst_stream_container_info_copy_int (
106         (GstDiscovererContainerInfo *) info, stream_map);
107   } else if (ltyp == GST_TYPE_DISCOVERER_AUDIO_INFO) {
108     ret = (GstDiscovererStreamInfo *)
109         gst_discoverer_audio_info_copy_int ((GstDiscovererAudioInfo *) info);
110
111   } else if (ltyp == GST_TYPE_DISCOVERER_VIDEO_INFO) {
112     ret = (GstDiscovererStreamInfo *)
113         gst_discoverer_video_info_copy_int ((GstDiscovererVideoInfo *) info);
114
115   } else if (ltyp == GST_TYPE_DISCOVERER_SUBTITLE_INFO) {
116     ret = (GstDiscovererStreamInfo *)
117         gst_discoverer_subtitle_info_copy_int ((GstDiscovererSubtitleInfo *)
118         info);
119
120   } else
121     ret = gst_discoverer_stream_info_new ();
122
123   if (info->next) {
124     ret->next = gst_discoverer_info_copy_int (info->next, stream_map);
125     ret->next->previous = ret;
126   }
127
128   if (info->caps)
129     ret->caps = gst_caps_copy (info->caps);
130
131   if (info->tags)
132     ret->tags = gst_tag_list_copy (info->tags);
133
134   if (info->toc)
135     ret->toc = gst_toc_ref (info->toc);
136
137   if (info->stream_id)
138     ret->stream_id = g_strdup (info->stream_id);
139
140   if (info->misc)
141     ret->misc = gst_structure_copy (info->misc);
142
143   if (stream_map)
144     g_hash_table_insert (stream_map, info, ret);
145
146   return ret;
147 }
148
149 /* Container information */
150 G_DEFINE_TYPE (GstDiscovererContainerInfo, gst_discoverer_container_info,
151     GST_TYPE_DISCOVERER_STREAM_INFO);
152
153 static void
154 gst_discoverer_container_info_init (GstDiscovererContainerInfo * info)
155 {
156   /* Nothing to initialize */
157 }
158
159 static GstDiscovererContainerInfo *
160 gst_discoverer_container_info_new (void)
161 {
162   return (GstDiscovererContainerInfo *)
163       g_object_new (GST_TYPE_DISCOVERER_CONTAINER_INFO, NULL);
164 }
165
166 static void
167 gst_discoverer_container_info_finalize (GObject * object)
168 {
169   GstDiscovererContainerInfo *info = (GstDiscovererContainerInfo *) object;
170   GList *tmp;
171
172   for (tmp = ((GstDiscovererContainerInfo *) info)->streams; tmp;
173       tmp = tmp->next)
174     g_object_unref ((GObject *) tmp->data);
175
176   gst_discoverer_stream_info_list_free (info->streams);
177
178   gst_discoverer_stream_info_finalize ((GObject *) info);
179 }
180
181 static void
182 gst_discoverer_container_info_class_init (GObjectClass * klass)
183 {
184   klass->finalize = gst_discoverer_container_info_finalize;
185 }
186
187 static GstDiscovererContainerInfo *
188 gst_stream_container_info_copy_int (GstDiscovererContainerInfo * ptr,
189     GHashTable * stream_map)
190 {
191   GstDiscovererContainerInfo *ret;
192   GList *tmp;
193
194   g_return_val_if_fail (ptr != NULL, NULL);
195
196   ret = gst_discoverer_container_info_new ();
197
198   for (tmp = ((GstDiscovererContainerInfo *) ptr)->streams; tmp;
199       tmp = tmp->next) {
200     GstDiscovererStreamInfo *subtop = gst_discoverer_info_copy_int (tmp->data,
201         stream_map);
202     ret->streams = g_list_append (ret->streams, subtop);
203     if (stream_map)
204       g_hash_table_insert (stream_map, tmp->data, subtop);
205   }
206
207   return ret;
208 }
209
210 /* Audio information */
211 G_DEFINE_TYPE (GstDiscovererAudioInfo, gst_discoverer_audio_info,
212     GST_TYPE_DISCOVERER_STREAM_INFO);
213
214 static void
215 gst_discoverer_audio_info_finalize (GObject * object)
216 {
217   GstDiscovererAudioInfo *info = (GstDiscovererAudioInfo *) object;
218
219   g_free (info->language);
220
221   G_OBJECT_CLASS (gst_discoverer_audio_info_parent_class)->finalize (object);
222 }
223
224 static void
225 gst_discoverer_audio_info_class_init (GObjectClass * klass)
226 {
227   klass->finalize = gst_discoverer_audio_info_finalize;
228 }
229
230 static void
231 gst_discoverer_audio_info_init (GstDiscovererAudioInfo * info)
232 {
233   info->language = NULL;
234 }
235
236 static GstDiscovererAudioInfo *
237 gst_discoverer_audio_info_new (void)
238 {
239   return (GstDiscovererAudioInfo *)
240       g_object_new (GST_TYPE_DISCOVERER_AUDIO_INFO, NULL);
241 }
242
243 static GstDiscovererAudioInfo *
244 gst_discoverer_audio_info_copy_int (GstDiscovererAudioInfo * ptr)
245 {
246   GstDiscovererAudioInfo *ret;
247
248   ret = gst_discoverer_audio_info_new ();
249
250   ret->channels = ptr->channels;
251   ret->sample_rate = ptr->sample_rate;
252   ret->depth = ptr->depth;
253   ret->bitrate = ptr->bitrate;
254   ret->max_bitrate = ptr->max_bitrate;
255   ret->language = g_strdup (ptr->language);
256
257   return ret;
258 }
259
260 /* Subtitle information */
261 G_DEFINE_TYPE (GstDiscovererSubtitleInfo, gst_discoverer_subtitle_info,
262     GST_TYPE_DISCOVERER_STREAM_INFO);
263
264 static void
265 gst_discoverer_subtitle_info_init (GstDiscovererSubtitleInfo * info)
266 {
267   info->language = NULL;
268 }
269
270 static void
271 gst_discoverer_subtitle_info_finalize (GObject * object)
272 {
273   GstDiscovererSubtitleInfo *info = (GstDiscovererSubtitleInfo *) object;
274
275   g_free (info->language);
276
277   G_OBJECT_CLASS (gst_discoverer_subtitle_info_parent_class)->finalize (object);
278 }
279
280 static void
281 gst_discoverer_subtitle_info_class_init (GObjectClass * klass)
282 {
283   klass->finalize = gst_discoverer_subtitle_info_finalize;
284 }
285
286 static GstDiscovererSubtitleInfo *
287 gst_discoverer_subtitle_info_new (void)
288 {
289   return (GstDiscovererSubtitleInfo *)
290       g_object_new (GST_TYPE_DISCOVERER_SUBTITLE_INFO, NULL);
291 }
292
293 static GstDiscovererSubtitleInfo *
294 gst_discoverer_subtitle_info_copy_int (GstDiscovererSubtitleInfo * ptr)
295 {
296   GstDiscovererSubtitleInfo *ret;
297
298   ret = gst_discoverer_subtitle_info_new ();
299
300   ret->language = g_strdup (ptr->language);
301
302   return ret;
303 }
304
305 /* Video information */
306 G_DEFINE_TYPE (GstDiscovererVideoInfo, gst_discoverer_video_info,
307     GST_TYPE_DISCOVERER_STREAM_INFO);
308
309 static void
310 gst_discoverer_video_info_class_init (GObjectClass * klass)
311 {
312   /* Nothing to initialize */
313 }
314
315 static void
316 gst_discoverer_video_info_init (GstDiscovererVideoInfo * info)
317 {
318   /* Nothing to initialize */
319 }
320
321 static GstDiscovererVideoInfo *
322 gst_discoverer_video_info_new (void)
323 {
324   return (GstDiscovererVideoInfo *)
325       g_object_new (GST_TYPE_DISCOVERER_VIDEO_INFO, NULL);
326 }
327
328 static GstDiscovererVideoInfo *
329 gst_discoverer_video_info_copy_int (GstDiscovererVideoInfo * ptr)
330 {
331   GstDiscovererVideoInfo *ret;
332
333   ret = gst_discoverer_video_info_new ();
334
335   ret->width = ptr->width;
336   ret->height = ptr->height;
337   ret->depth = ptr->depth;
338   ret->framerate_num = ptr->framerate_num;
339   ret->framerate_denom = ptr->framerate_denom;
340   ret->par_num = ptr->par_num;
341   ret->par_denom = ptr->par_denom;
342   ret->interlaced = ptr->interlaced;
343   ret->bitrate = ptr->bitrate;
344   ret->max_bitrate = ptr->max_bitrate;
345   ret->is_image = ptr->is_image;
346
347   return ret;
348 }
349
350 /* Global stream information */
351 G_DEFINE_TYPE (GstDiscovererInfo, gst_discoverer_info, G_TYPE_OBJECT);
352
353 static void
354 gst_discoverer_info_init (GstDiscovererInfo * info)
355 {
356   info->missing_elements_details = g_ptr_array_new_with_free_func (g_free);
357 }
358
359 static void
360 gst_discoverer_info_finalize (GObject * object)
361 {
362   GstDiscovererInfo *info = (GstDiscovererInfo *) object;
363   g_free (info->uri);
364
365   if (info->stream_info)
366     g_object_unref ((GObject *) info->stream_info);
367
368   if (info->misc)
369     gst_structure_free (info->misc);
370
371   g_list_free (info->stream_list);
372
373   if (info->tags)
374     gst_tag_list_unref (info->tags);
375
376   if (info->toc)
377     gst_toc_unref (info->toc);
378
379   g_ptr_array_unref (info->missing_elements_details);
380 }
381
382 static GstDiscovererInfo *
383 gst_discoverer_info_new (void)
384 {
385   return (GstDiscovererInfo *) g_object_new (GST_TYPE_DISCOVERER_INFO, NULL);
386 }
387
388 /**
389  * gst_discoverer_info_copy:
390  * @ptr: (transfer none): a #GstDiscovererInfo
391  *
392  * Returns: (transfer full): A copy of the #GstDiscovererInfo
393  */
394 GstDiscovererInfo *
395 gst_discoverer_info_copy (GstDiscovererInfo * ptr)
396 {
397   GstDiscovererInfo *ret;
398   GHashTable *stream_map;
399   GList *tmp;
400
401   g_return_val_if_fail (ptr != NULL, NULL);
402
403   stream_map = g_hash_table_new (g_direct_hash, NULL);
404
405   ret = gst_discoverer_info_new ();
406
407   ret->uri = g_strdup (ptr->uri);
408   if (ptr->stream_info) {
409     ret->stream_info = gst_discoverer_info_copy_int (ptr->stream_info,
410         stream_map);
411   }
412   ret->duration = ptr->duration;
413   if (ptr->misc)
414     ret->misc = gst_structure_copy (ptr->misc);
415
416   /* We need to set up the new list of streams to correspond to old one. The
417    * list just contains a set of pointers to streams in the stream_info tree,
418    * so we keep a map of old stream info objects to the corresponding new
419    * ones and use that to figure out correspondence in stream_list. */
420   for (tmp = ptr->stream_list; tmp; tmp = tmp->next) {
421     GstDiscovererStreamInfo *old_stream = (GstDiscovererStreamInfo *) tmp->data;
422     GstDiscovererStreamInfo *new_stream = g_hash_table_lookup (stream_map,
423         old_stream);
424     g_assert (new_stream != NULL);
425     ret->stream_list = g_list_append (ret->stream_list, new_stream);
426   }
427
428   if (ptr->tags)
429     ret->tags = gst_tag_list_copy (ptr->tags);
430
431   if (ptr->toc)
432     ret->toc = gst_toc_ref (ptr->toc);
433
434   g_hash_table_destroy (stream_map);
435   return ret;
436 }
437
438 static void
439 gst_discoverer_info_class_init (GObjectClass * klass)
440 {
441   klass->finalize = gst_discoverer_info_finalize;
442 }
443
444 /**
445  * gst_discoverer_stream_info_list_free:
446  * @infos: (element-type GstPbutils.DiscovererStreamInfo): a #GList of #GstDiscovererStreamInfo
447  *
448  * Decrements the reference count of all contained #GstDiscovererStreamInfo
449  * and fress the #GList.
450  */
451 void
452 gst_discoverer_stream_info_list_free (GList * infos)
453 {
454   GList *tmp;
455
456   for (tmp = infos; tmp; tmp = tmp->next)
457     gst_discoverer_stream_info_unref ((GstDiscovererStreamInfo *) tmp->data);
458   g_list_free (infos);
459 }
460
461 /**
462  * gst_discoverer_info_get_streams:
463  * @info: a #GstDiscovererInfo
464  * @streamtype: a #GType derived from #GstDiscovererStreamInfo
465  *
466  * Finds the #GstDiscovererStreamInfo contained in @info that match the
467  * given @streamtype.
468  *
469  * Returns: (transfer full) (element-type GstPbutils.DiscovererStreamInfo): A #GList of
470  * matching #GstDiscovererStreamInfo. The caller should free it with
471  * gst_discoverer_stream_info_list_free().
472  */
473 GList *
474 gst_discoverer_info_get_streams (GstDiscovererInfo * info, GType streamtype)
475 {
476   GList *tmp, *res = NULL;
477
478   for (tmp = info->stream_list; tmp; tmp = tmp->next) {
479     GstDiscovererStreamInfo *stmp = (GstDiscovererStreamInfo *) tmp->data;
480
481     if (G_TYPE_CHECK_INSTANCE_TYPE (stmp, streamtype))
482       res = g_list_append (res, gst_discoverer_stream_info_ref (stmp));
483   }
484
485   return res;
486 }
487
488 /**
489  * gst_discoverer_info_get_audio_streams:
490  * @info: a #GstDiscovererInfo
491  *
492  * Finds all the #GstDiscovererAudioInfo contained in @info
493  *
494  * Returns: (transfer full) (element-type GstPbutils.DiscovererStreamInfo): A #GList of
495  * matching #GstDiscovererStreamInfo. The caller should free it with
496  * gst_discoverer_stream_info_list_free().
497  */
498 GList *
499 gst_discoverer_info_get_audio_streams (GstDiscovererInfo * info)
500 {
501   return gst_discoverer_info_get_streams (info, GST_TYPE_DISCOVERER_AUDIO_INFO);
502 }
503
504 /**
505  * gst_discoverer_info_get_video_streams:
506  * @info: a #GstDiscovererInfo
507  *
508  * Finds all the #GstDiscovererVideoInfo contained in @info
509  *
510  * Returns: (transfer full) (element-type GstPbutils.DiscovererStreamInfo): A #GList of
511  * matching #GstDiscovererStreamInfo. The caller should free it with
512  * gst_discoverer_stream_info_list_free().
513  */
514 GList *
515 gst_discoverer_info_get_video_streams (GstDiscovererInfo * info)
516 {
517   return gst_discoverer_info_get_streams (info, GST_TYPE_DISCOVERER_VIDEO_INFO);
518 }
519
520 /**
521  * gst_discoverer_info_get_subtitle_streams:
522  * @info: a #GstDiscovererInfo
523  *
524  * Finds all the #GstDiscovererSubtitleInfo contained in @info
525  *
526  * Returns: (transfer full) (element-type GstPbutils.DiscovererStreamInfo): A #GList of
527  * matching #GstDiscovererStreamInfo. The caller should free it with
528  * gst_discoverer_stream_info_list_free().
529  */
530 GList *
531 gst_discoverer_info_get_subtitle_streams (GstDiscovererInfo * info)
532 {
533   return gst_discoverer_info_get_streams (info,
534       GST_TYPE_DISCOVERER_SUBTITLE_INFO);
535 }
536
537 /**
538  * gst_discoverer_info_get_container_streams:
539  * @info: a #GstDiscovererInfo
540  *
541  * Finds all the #GstDiscovererContainerInfo contained in @info
542  *
543  * Returns: (transfer full) (element-type GstPbutils.DiscovererStreamInfo): A #GList of
544  * matching #GstDiscovererStreamInfo. The caller should free it with
545  * gst_discoverer_stream_info_list_free().
546  */
547 GList *
548 gst_discoverer_info_get_container_streams (GstDiscovererInfo * info)
549 {
550   return gst_discoverer_info_get_streams (info,
551       GST_TYPE_DISCOVERER_CONTAINER_INFO);
552 }
553
554 /**
555  * gst_discoverer_stream_info_get_stream_type_nick:
556  * @info: a #GstDiscovererStreamInfo
557  *
558  * Returns: a human readable name for the stream type of the given @info (ex : "audio",
559  * "container",...).
560  */
561 const gchar *
562 gst_discoverer_stream_info_get_stream_type_nick (GstDiscovererStreamInfo * info)
563 {
564   if (GST_IS_DISCOVERER_CONTAINER_INFO (info))
565     return "container";
566   if (GST_IS_DISCOVERER_AUDIO_INFO (info))
567     return "audio";
568   if (GST_IS_DISCOVERER_VIDEO_INFO (info)) {
569     if (gst_discoverer_video_info_is_image ((GstDiscovererVideoInfo *)
570             info))
571       return "video(image)";
572     else
573       return "video";
574   }
575   if (GST_IS_DISCOVERER_SUBTITLE_INFO (info))
576     return "subtitles";
577   return "unknown";
578 }
579
580 /* ACCESSORS */
581
582
583 #define GENERIC_ACCESSOR_CODE(parent, parenttype, parentgtype, fieldname, type, failval) \
584   type parent##_get_##fieldname(const parenttype info) {                        \
585     g_return_val_if_fail(G_TYPE_CHECK_INSTANCE_TYPE((info), parentgtype), failval); \
586     return (info)->fieldname;                           \
587   }
588
589 /**
590  * gst_discoverer_stream_info_get_previous:
591  * @info: a #GstDiscovererStreamInfo
592  *
593  * Returns: (transfer full): the previous #GstDiscovererStreamInfo in a chain.
594  * %NULL for starting points. Unref with #gst_discoverer_stream_info_unref
595  * after usage.
596  */
597 GstDiscovererStreamInfo *
598 gst_discoverer_stream_info_get_previous (GstDiscovererStreamInfo * info)
599 {
600   g_return_val_if_fail (GST_IS_DISCOVERER_STREAM_INFO (info), NULL);
601
602   if (info->previous)
603     return gst_discoverer_stream_info_ref (info->previous);
604   return NULL;
605 }
606
607 /**
608  * gst_discoverer_stream_info_get_next:
609  * @info: a #GstDiscovererStreamInfo
610  *
611  * Returns: (transfer full): the next #GstDiscovererStreamInfo in a chain. %NULL
612  * for final streams.
613  * Unref with #gst_discoverer_stream_info_unref after usage.
614  */
615 GstDiscovererStreamInfo *
616 gst_discoverer_stream_info_get_next (GstDiscovererStreamInfo * info)
617 {
618   g_return_val_if_fail (GST_IS_DISCOVERER_STREAM_INFO (info), NULL);
619
620   if (info->next)
621     return gst_discoverer_stream_info_ref (info->next);
622   return NULL;
623 }
624
625
626 /**
627  * gst_discoverer_stream_info_get_caps:
628  * @info: a #GstDiscovererStreamInfo
629  *
630  * Returns: (transfer full): the #GstCaps of the stream. Unref with
631  * #gst_caps_unref after usage.
632  */
633 GstCaps *
634 gst_discoverer_stream_info_get_caps (GstDiscovererStreamInfo * info)
635 {
636   g_return_val_if_fail (GST_IS_DISCOVERER_STREAM_INFO (info), NULL);
637
638   if (info->caps)
639     return gst_caps_ref (info->caps);
640   return NULL;
641 }
642
643 /**
644  * gst_discoverer_stream_info_get_tags:
645  * @info: a #GstDiscovererStreamInfo
646  *
647  * Returns: (transfer none): the tags contained in this stream. If you wish to
648  * use the tags after the life-time of @info you will need to copy them.
649  */
650 const GstTagList *
651 gst_discoverer_stream_info_get_tags (GstDiscovererStreamInfo * info)
652 {
653   g_return_val_if_fail (GST_IS_DISCOVERER_STREAM_INFO (info), NULL);
654
655   return info->tags;
656 }
657
658 /**
659  * gst_discoverer_stream_info_get_toc:
660  * @info: a #GstDiscovererStreamInfo
661  *
662  * Returns: (transfer none): the TOC contained in this stream. If you wish to
663  * use the TOC after the life-time of @info you will need to copy it.
664  */
665 const GstToc *
666 gst_discoverer_stream_info_get_toc (GstDiscovererStreamInfo * info)
667 {
668   g_return_val_if_fail (GST_IS_DISCOVERER_STREAM_INFO (info), NULL);
669
670   return info->toc;
671 }
672
673 /**
674  * gst_discoverer_stream_info_get_stream_id:
675  * @info: a #GstDiscovererStreamInfo
676  *
677  * Returns: (transfer none): the stream ID of this stream. If you wish to
678  * use the stream ID after the life-time of @info you will need to copy it.
679  */
680 const gchar *
681 gst_discoverer_stream_info_get_stream_id (GstDiscovererStreamInfo * info)
682 {
683   g_return_val_if_fail (GST_IS_DISCOVERER_STREAM_INFO (info), NULL);
684
685   return info->stream_id;
686 }
687
688 /**
689  * gst_discoverer_stream_info_get_misc:
690  * @info: a #GstDiscovererStreamInfo
691  *
692  * Deprecated: This functions is deprecated since version 1.4, use
693  * gst_discoverer_stream_get_missing_elements_installer_details
694  *
695  * Returns: (transfer none): additional information regarding the stream (for
696  * example codec version, profile, etc..). If you wish to use the #GstStructure
697  * after the life-time of @info you will need to copy it.
698  */
699 const GstStructure *
700 gst_discoverer_stream_info_get_misc (GstDiscovererStreamInfo * info)
701 {
702   g_return_val_if_fail (GST_IS_DISCOVERER_STREAM_INFO (info), NULL);
703
704   return info->misc;
705 }
706
707 /* GstDiscovererContainerInfo */
708
709 /**
710  * gst_discoverer_container_info_get_streams:
711  * @info: a #GstDiscovererStreamInfo
712  *
713  * Returns: (transfer full) (element-type GstPbutils.DiscovererStreamInfo): the list of
714  * #GstDiscovererStreamInfo this container stream offers.
715  * Free with gst_discoverer_stream_info_list_free() after usage.
716  */
717
718 GList *
719 gst_discoverer_container_info_get_streams (GstDiscovererContainerInfo * info)
720 {
721   GList *res = NULL, *tmp;
722
723   g_return_val_if_fail (GST_IS_DISCOVERER_CONTAINER_INFO (info), NULL);
724
725   for (tmp = info->streams; tmp; tmp = tmp->next)
726     res =
727         g_list_append (res,
728         gst_discoverer_stream_info_ref ((GstDiscovererStreamInfo *) tmp->data));
729
730   return res;
731 }
732
733 /* GstDiscovererAudioInfo */
734
735 #define AUDIO_INFO_ACCESSOR_CODE(fieldname, type, failval)              \
736   GENERIC_ACCESSOR_CODE(gst_discoverer_audio_info, GstDiscovererAudioInfo*, \
737                         GST_TYPE_DISCOVERER_AUDIO_INFO,         \
738                         fieldname, type, failval)
739
740 /**
741  * gst_discoverer_audio_info_get_channels:
742  * @info: a #GstDiscovererAudioInfo
743  *
744  * Returns: the number of channels in the stream.
745  */
746
747 AUDIO_INFO_ACCESSOR_CODE (channels, guint, 0);
748
749 /**
750  * gst_discoverer_audio_info_get_sample_rate:
751  * @info: a #GstDiscovererAudioInfo
752  *
753  * Returns: the sample rate of the stream in Hertz.
754  */
755
756 AUDIO_INFO_ACCESSOR_CODE (sample_rate, guint, 0);
757
758 /**
759  * gst_discoverer_audio_info_get_depth:
760  * @info: a #GstDiscovererAudioInfo
761  *
762  * Returns: the number of bits used per sample in each channel.
763  */
764
765 AUDIO_INFO_ACCESSOR_CODE (depth, guint, 0);
766
767 /**
768  * gst_discoverer_audio_info_get_bitrate:
769  * @info: a #GstDiscovererAudioInfo
770  *
771  * Returns: the average or nominal bitrate of the stream in bits/second.
772  */
773
774 AUDIO_INFO_ACCESSOR_CODE (bitrate, guint, 0);
775
776 /**
777  * gst_discoverer_audio_info_get_max_bitrate:
778  * @info: a #GstDiscovererAudioInfo
779  *
780  * Returns: the maximum bitrate of the stream in bits/second.
781  */
782
783 AUDIO_INFO_ACCESSOR_CODE (max_bitrate, guint, 0);
784
785 /**
786  * gst_discoverer_audio_info_get_language:
787  * @info: a #GstDiscovererAudioInfo
788  *
789  * Returns: the language of the stream, or NULL if unknown.
790  */
791
792 AUDIO_INFO_ACCESSOR_CODE (language, const gchar *, NULL);
793
794 /* GstDiscovererVideoInfo */
795
796 #define VIDEO_INFO_ACCESSOR_CODE(fieldname, type, failval)              \
797   GENERIC_ACCESSOR_CODE(gst_discoverer_video_info, GstDiscovererVideoInfo*, \
798                         GST_TYPE_DISCOVERER_VIDEO_INFO,                 \
799                         fieldname, type, failval)
800
801 /**
802  * gst_discoverer_video_info_get_width:
803  * @info: a #GstDiscovererVideoInfo
804  *
805  * Returns: the width of the video stream in pixels.
806  */
807
808 VIDEO_INFO_ACCESSOR_CODE (width, guint, 0);
809
810 /**
811  * gst_discoverer_video_info_get_height:
812  * @info: a #GstDiscovererVideoInfo
813  *
814  * Returns: the height of the video stream in pixels.
815  */
816
817 VIDEO_INFO_ACCESSOR_CODE (height, guint, 0);
818
819 /**
820  * gst_discoverer_video_info_get_depth:
821  * @info: a #GstDiscovererVideoInfo
822  *
823  * Returns: the depth in bits of the video stream.
824  */
825
826 VIDEO_INFO_ACCESSOR_CODE (depth, guint, 0);
827
828 /**
829  * gst_discoverer_video_info_get_framerate_num:
830  * @info: a #GstDiscovererVideoInfo
831  *
832  * Returns: the framerate of the video stream (numerator).
833  */
834
835 VIDEO_INFO_ACCESSOR_CODE (framerate_num, guint, 0);
836
837 /**
838  * gst_discoverer_video_info_get_framerate_denom:
839  * @info: a #GstDiscovererVideoInfo
840  *
841  * Returns: the framerate of the video stream (denominator).
842  */
843
844 VIDEO_INFO_ACCESSOR_CODE (framerate_denom, guint, 0);
845
846 /**
847  * gst_discoverer_video_info_get_par_num:
848  * @info: a #GstDiscovererVideoInfo
849  *
850  * Returns: the Pixel Aspect Ratio (PAR) of the video stream (numerator).
851  */
852
853 VIDEO_INFO_ACCESSOR_CODE (par_num, guint, 0);
854
855 /**
856  * gst_discoverer_video_info_get_par_denom:
857  * @info: a #GstDiscovererVideoInfo
858  *
859  * Returns: the Pixel Aspect Ratio (PAR) of the video stream (denominator).
860  */
861
862 VIDEO_INFO_ACCESSOR_CODE (par_denom, guint, 0);
863
864 /**
865  * gst_discoverer_video_info_is_interlaced:
866  * @info: a #GstDiscovererVideoInfo
867  *
868  * Returns: %TRUE if the stream is interlaced, else %FALSE.
869  */
870 gboolean
871 gst_discoverer_video_info_is_interlaced (const GstDiscovererVideoInfo * info)
872 {
873   g_return_val_if_fail (GST_IS_DISCOVERER_VIDEO_INFO (info), FALSE);
874
875   return info->interlaced;
876 }
877
878 /**
879  * gst_discoverer_video_info_get_bitrate:
880  * @info: a #GstDiscovererVideoInfo
881  *
882  * Returns: the average or nominal bitrate of the video stream in bits/second.
883  */
884
885 VIDEO_INFO_ACCESSOR_CODE (bitrate, guint, 0);
886
887 /**
888  * gst_discoverer_video_info_get_max_bitrate:
889  * @info: a #GstDiscovererVideoInfo
890  *
891  * Returns: the maximum bitrate of the video stream in bits/second.
892  */
893
894 VIDEO_INFO_ACCESSOR_CODE (max_bitrate, guint, 0);
895
896 /**
897  * gst_discoverer_video_info_is_image:
898  * @info: a #GstDiscovererVideoInfo
899  *
900  * Returns: #TRUE if the video stream corresponds to an image (i.e. only contains
901  * one frame).
902  */
903 gboolean
904 gst_discoverer_video_info_is_image (const GstDiscovererVideoInfo * info)
905 {
906   g_return_val_if_fail (GST_IS_DISCOVERER_VIDEO_INFO (info), FALSE);
907
908   return info->is_image;
909 }
910
911 /* GstDiscovererSubtitleInfo */
912
913 #define SUBTITLE_INFO_ACCESSOR_CODE(fieldname, type, failval)                     \
914   GENERIC_ACCESSOR_CODE(gst_discoverer_subtitle_info, GstDiscovererSubtitleInfo*, \
915                         GST_TYPE_DISCOVERER_SUBTITLE_INFO,                        \
916                         fieldname, type, failval)
917
918 /**
919  * gst_discoverer_subtitle_info_get_language:
920  * @info: a #GstDiscovererSubtitleInfo
921  *
922  * Returns: the language of the stream, or NULL if unknown.
923  */
924
925 SUBTITLE_INFO_ACCESSOR_CODE (language, const gchar *, NULL);
926
927 /* GstDiscovererInfo */
928
929 #define DISCOVERER_INFO_ACCESSOR_CODE(fieldname, type, failval)         \
930   GENERIC_ACCESSOR_CODE(gst_discoverer_info, GstDiscovererInfo*,        \
931                         GST_TYPE_DISCOVERER_INFO,                       \
932                         fieldname, type, failval)
933
934 /**
935  * gst_discoverer_info_get_uri:
936  * @info: a #GstDiscovererInfo
937  *
938  * Returns: (transfer none): the URI to which this information corresponds to.
939  * Copy it if you wish to use it after the life-time of @info.
940  */
941
942 DISCOVERER_INFO_ACCESSOR_CODE (uri, const gchar *, NULL);
943
944 /**
945  * gst_discoverer_info_get_result:
946  * @info: a #GstDiscovererInfo
947  *
948  * Returns: the result of the discovery as a #GstDiscovererResult.
949  */
950
951 DISCOVERER_INFO_ACCESSOR_CODE (result, GstDiscovererResult, GST_DISCOVERER_OK);
952
953 /**
954  * gst_discoverer_info_get_stream_info:
955  * @info: a #GstDiscovererInfo
956  *
957  * Returns: (transfer full): the structure (or topology) of the URI as a
958  * #GstDiscovererStreamInfo.
959  * This structure can be traversed to see the original hierarchy. Unref with
960  * gst_discoverer_stream_info_unref() after usage.
961  */
962
963 GstDiscovererStreamInfo *
964 gst_discoverer_info_get_stream_info (GstDiscovererInfo * info)
965 {
966   g_return_val_if_fail (GST_IS_DISCOVERER_INFO (info), NULL);
967
968   if (info->stream_info)
969     return gst_discoverer_stream_info_ref (info->stream_info);
970   return NULL;
971 }
972
973 /**
974  * gst_discoverer_info_get_stream_list:
975  * @info: a #GstDiscovererInfo
976  *
977  * Returns: (transfer full) (element-type GstPbutils.DiscovererStreamInfo): the list of
978  * all streams contained in the #info. Free after usage
979  * with gst_discoverer_stream_info_list_free().
980  */
981 GList *
982 gst_discoverer_info_get_stream_list (GstDiscovererInfo * info)
983 {
984   GList *res = NULL, *tmp;
985
986   g_return_val_if_fail (GST_IS_DISCOVERER_INFO (info), NULL);
987
988   for (tmp = info->stream_list; tmp; tmp = tmp->next)
989     res =
990         g_list_append (res,
991         gst_discoverer_stream_info_ref ((GstDiscovererStreamInfo *) tmp->data));
992
993   return res;
994 }
995
996 /**
997  * gst_discoverer_info_get_duration:
998  * @info: a #GstDiscovererInfo
999  *
1000  * Returns: the duration of the URI in #GstClockTime (nanoseconds).
1001  */
1002
1003 DISCOVERER_INFO_ACCESSOR_CODE (duration, GstClockTime, GST_CLOCK_TIME_NONE);
1004
1005 /**
1006  * gst_discoverer_info_get_seekable:
1007  * @info: a #GstDiscovererInfo
1008  *
1009  * Returns: the whether the URI is seekable.
1010  */
1011
1012 DISCOVERER_INFO_ACCESSOR_CODE (seekable, gboolean, FALSE);
1013
1014 /**
1015  * gst_discoverer_info_get_misc:
1016  * @info: a #GstDiscovererInfo
1017  *
1018  * Deprecated: This functions is deprecated since version 1.4, use
1019  * gst_discoverer_info_get_missing_elements_installer_details
1020  *
1021  * Returns: (transfer none): Miscellaneous information stored as a #GstStructure
1022  * (for example: information about missing plugins). If you wish to use the
1023  * #GstStructure after the life-time of @info, you will need to copy it.
1024  */
1025
1026 DISCOVERER_INFO_ACCESSOR_CODE (misc, const GstStructure *, NULL);
1027
1028 /**
1029  * gst_discoverer_info_get_tags:
1030  * @info: a #GstDiscovererInfo
1031  *
1032  * Returns: (transfer none): all tags contained in the URI. If you wish to use
1033  * the tags after the life-time of @info, you will need to copy them.
1034  */
1035
1036 DISCOVERER_INFO_ACCESSOR_CODE (tags, const GstTagList *, NULL);
1037
1038 /**
1039  * gst_discoverer_info_get_toc:
1040  * @info: a #GstDiscovererInfo
1041  *
1042  * Returns: (transfer none): TOC contained in the URI. If you wish to use
1043  * the TOC after the life-time of @info, you will need to copy it.
1044  */
1045
1046 DISCOVERER_INFO_ACCESSOR_CODE (toc, const GstToc *, NULL);
1047
1048 /**
1049  * gst_discoverer_info_ref:
1050  * @info: a #GstDiscovererInfo
1051  *
1052  * Increments the reference count of @info.
1053  *
1054  * Returns: the same #GstDiscovererInfo object
1055  */
1056
1057 /**
1058  * gst_discoverer_info_unref:
1059  * @info: a #GstDiscovererInfo
1060  *
1061  * Decrements the reference count of @info.
1062  */
1063
1064 /**
1065  * gst_discoverer_stream_info_ref:
1066  * @info: a #GstDiscovererStreamInfo
1067  *
1068  * Increments the reference count of @info.
1069  *
1070  * Returns: the same #GstDiscovererStreamInfo object
1071  */
1072
1073 /**
1074  * gst_discoverer_stream_info_unref:
1075  * @info: a #GstDiscovererStreamInfo
1076  *
1077  * Decrements the reference count of @info.
1078  */
1079
1080
1081 /**
1082  * gst_discoverer_info_get_missing_elements_installer_details:
1083  * @info: a #GstDiscovererStreamInfo to retrieve installer detail
1084  * for the missing element
1085  *
1086  * Get the installer details for missing elements
1087  *
1088  * Returns: (transfer full): (array zero-terminated=1): An array of strings
1089  * containing informations about how to install the various missing elements
1090  * for @info to be usable. Free with g_strfreev.
1091  *
1092  * Since: 1.4
1093  */
1094 const gchar **
1095 gst_discoverer_info_get_missing_elements_installer_details (const
1096     GstDiscovererInfo * info)
1097 {
1098
1099   if (info->result != GST_DISCOVERER_MISSING_PLUGINS) {
1100     GST_WARNING_OBJECT (info, "Trying to get missing element installed details "
1101         "but result is not 'MISSING_PLUGINS'");
1102
1103     return NULL;
1104   }
1105
1106   if (info->missing_elements_details->pdata[info->missing_elements_details->
1107           len]) {
1108     GST_DEBUG ("Adding NULL pointer to the end of missing_elements_details");
1109     g_ptr_array_add (info->missing_elements_details, NULL);
1110   }
1111
1112   return (const gchar **) info->missing_elements_details->pdata;
1113 }