36253931cbf4f6fd25b2a288dc4f143a0c0e888c
[platform/upstream/gstreamer.git] / subprojects / gst-plugins-base / gst / playback / gsturidecodebin3.c
1 /* GStreamer
2  * Copyright (C) <2007> Wim Taymans <wim.taymans@gmail.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 /* TODO/FIXME:
21  *
22  * * BUFFERING MESSAGES
23  * ** How/Where do we deal with buffering messages from a new/prerolling
24  *    source ? Ideally we want to re-use the same sourcebin ?
25  * ** Remember last buffering messages per source handler, if the SourceEntry
26  *    group_id is the one being currently outputted on the source ghostpads,
27  *    post the (last) buffering messages.
28  *    If no group_id is being outputted (still prerolling), then output
29  *    the messages directly
30  *
31  * * ASYNC HANDLING
32  * ** URIDECODEBIN3 is not async-aware.
33  *
34  * * GAPLESS HANDLING
35  * ** Correlate group_id and URI to know when/which stream is being outputted/started
36  */
37
38 /**
39  * SECTION:element-uridecodebin3
40  * @title: uridecodebin3
41  *
42  * Decodes data from a URI into raw media. It selects a source element that can
43  * handle the given #GstURIDecodeBin3:uri scheme and connects it to a decodebin.
44  */
45
46 #ifdef HAVE_CONFIG_H
47 #  include "config.h"
48 #endif
49
50 #include <string.h>
51
52 #include <gst/gst.h>
53 #include <gst/gst-i18n-plugin.h>
54 #include <gst/pbutils/missing-plugins.h>
55
56 #include "gstplay-enum.h"
57 #include "gstrawcaps.h"
58 #include "gstplaybackelements.h"
59 #include "gstplaybackutils.h"
60
61 #define GST_TYPE_URI_DECODE_BIN3 \
62   (gst_uri_decode_bin3_get_type())
63 #define GST_URI_DECODE_BIN3(obj) \
64   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_URI_DECODE_BIN3,GstURIDecodeBin3))
65 #define GST_URI_DECODE_BIN3_CLASS(klass) \
66   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_URI_DECODE_BIN3,GstURIDecodeBin3Class))
67 #define GST_IS_URI_DECODE_BIN3(obj) \
68   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_URI_DECODE_BIN3))
69 #define GST_IS_URI_DECODE_BIN3_CLASS(klass) \
70   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_URI_DECODE_BIN3))
71 #define GST_URI_DECODE_BIN3_CAST(obj) ((GstURIDecodeBin3 *) (obj))
72
73 typedef struct _GstSourceGroup GstSourceGroup;
74 typedef struct _GstURIDecodeBin3 GstURIDecodeBin3;
75 typedef struct _GstURIDecodeBin3Class GstURIDecodeBin3Class;
76
77 #define GST_URI_DECODE_BIN3_LOCK(dec) (g_mutex_lock(&((GstURIDecodeBin3*)(dec))->lock))
78 #define GST_URI_DECODE_BIN3_UNLOCK(dec) (g_mutex_unlock(&((GstURIDecodeBin3*)(dec))->lock))
79
80 typedef struct _GstPlayItem GstPlayItem;
81 typedef struct _GstSourceItem GstSourceItem;
82 typedef struct _GstSourceHandler GstSourceHandler;
83 typedef struct _OutputPad OutputPad;
84
85 /* A structure describing a play item, which travels through the elements
86  * over time. */
87 struct _GstPlayItem
88 {
89   GstURIDecodeBin3 *uridecodebin;
90
91   /* Main URI */
92   GstSourceItem *main_item;
93
94   /* Auxiliary URI */
95   /* FIXME : Replace by a list later */
96   GstSourceItem *sub_item;
97
98   /* The group_id used to identify this play item via STREAM_START events
99    * This is the group_id which will be used externally (i.e. rewritten
100    * to outgoing STREAM_START events and in emitted signals).
101    * The urisourcebin-specific group_id is located in GstSourceItem */
102   guint group_id;
103
104   /* Is this play item the one being currently outputted by decodebin3
105    * and on our source ghostpads */
106   gboolean currently_outputted;
107 };
108
109 struct _GstSourceItem
110 {
111   /* The GstPlayItem to which this GstSourceItem belongs to */
112   GstPlayItem *play_item;
113
114   gchar *uri;
115
116   /* The urisourcebin controlling this uri
117    * Can be NULL */
118   GstSourceHandler *handler;
119
120   /* The groupid created by urisourcebin for this uri */
121   guint internal_groupid;
122
123   /* FIXME : Add tag lists and other uri-specific items here ? */
124 };
125
126 /* Structure wrapping everything related to a urisourcebin */
127 struct _GstSourceHandler
128 {
129   GstURIDecodeBin3 *uridecodebin;
130
131   GstElement *urisourcebin;
132
133   /* Signal handlers */
134   gulong pad_added_id;
135   gulong pad_removed_id;
136   gulong source_setup_id;
137   gulong about_to_finish_id;
138
139   /* TRUE if the controlled urisourcebin was added to uridecodebin */
140   gboolean active;
141
142   /* whether urisourcebin is drained or not.
143    * Reset if/when setting a new URI */
144   gboolean drained;
145
146   /* Whether urisourcebin posted EOS on all pads and
147    * there is no pending entry */
148   gboolean is_eos;
149
150   /* TRUE if the urisourcebin handles main item */
151   gboolean is_main_source;
152
153   /* buffering message stored for after switching */
154   GstMessage *pending_buffering_msg;
155 };
156
157 /* Controls an output source pad */
158 struct _OutputPad
159 {
160   GstURIDecodeBin3 *uridecodebin;
161
162   GstPad *target_pad;
163   GstPad *ghost_pad;
164
165   /* Downstream event probe id */
166   gulong probe_id;
167
168   /* TRUE if the pad saw EOS. Reset to FALSE on STREAM_START */
169   gboolean is_eos;
170
171   /* The last seen (i.e. current) group_id
172    * Can be (guint)-1 if no group_id was seen yet */
173   guint current_group_id;
174 };
175
176 /**
177  * GstURIDecodeBin3
178  *
179  * uridecodebin3 element struct
180  */
181 struct _GstURIDecodeBin3
182 {
183   GstBin parent_instance;
184
185   GMutex lock;                  /* lock for constructing */
186
187   /* Properties */
188   GstElement *source;
189   guint64 connection_speed;     /* In bits/sec (0 = unknown) */
190   GstCaps *caps;
191   guint64 buffer_duration;      /* When buffering, buffer duration (ns) */
192   guint buffer_size;            /* When buffering, buffer size (bytes) */
193   gboolean download;
194   gboolean use_buffering;
195   guint64 ring_buffer_max_size;
196
197   GList *play_items;            /* List of GstPlayItem ordered by time of
198                                  * creation. Head of list is therefore the
199                                  * current (or pending if initial) one being
200                                  * outputted */
201   GstPlayItem *current;         /* Currently active GstPlayItem. Can be NULL
202                                  * if no entry is active yet (i.e. no source
203                                  * pads) */
204
205   /* sources.
206    * FIXME : Replace by a more modular system later on */
207   GstSourceHandler *main_handler;
208   GstSourceHandler *sub_handler;
209
210   /* URI handling
211    * FIXME : Switch to a playlist-based API */
212   gchar *uri;
213   gboolean uri_changed;         /* TRUE if uri changed */
214   gchar *suburi;
215   gboolean suburi_changed;      /* TRUE if suburi changed */
216
217   /* A global decodebin3 that's used to actually do decoding */
218   GstElement *decodebin;
219
220   /* db3 signals */
221   gulong db_pad_added_id;
222   gulong db_pad_removed_id;
223   gulong db_select_stream_id;
224   gulong db_about_to_finish_id;
225
226   GList *output_pads;           /* List of OutputPad */
227
228   GList *source_handlers;       /* List of SourceHandler */
229
230   /* Whether we already signalled about-to-finish or not
231    * FIXME: Track this by group-id ! */
232   gboolean posted_about_to_finish;
233 };
234
235 static gint
236 gst_uridecodebin3_select_stream (GstURIDecodeBin3 * dbin,
237     GstStreamCollection * collection, GstStream * stream)
238 {
239   GST_LOG_OBJECT (dbin, "default select-stream, returning -1");
240
241   return -1;
242 }
243
244 struct _GstURIDecodeBin3Class
245 {
246   GstBinClass parent_class;
247
248     gint (*select_stream) (GstURIDecodeBin3 * dbin,
249       GstStreamCollection * collection, GstStream * stream);
250 };
251
252 GST_DEBUG_CATEGORY_STATIC (gst_uri_decode_bin3_debug);
253 #define GST_CAT_DEFAULT gst_uri_decode_bin3_debug
254
255 /* signals */
256 enum
257 {
258   SIGNAL_SELECT_STREAM,
259   SIGNAL_SOURCE_SETUP,
260   SIGNAL_ABOUT_TO_FINISH,
261   LAST_SIGNAL
262 };
263
264 #if 0
265 static GstStaticCaps raw_audio_caps = GST_STATIC_CAPS ("audio/x-raw(ANY)");
266 static GstStaticCaps raw_video_caps = GST_STATIC_CAPS ("video/x-raw(ANY)");
267 #endif
268
269 /* properties */
270 #define DEFAULT_PROP_URI            NULL
271 #define DEFAULT_PROP_SUBURI            NULL
272 #define DEFAULT_CONNECTION_SPEED    0
273 #define DEFAULT_CAPS                (gst_static_caps_get (&default_raw_caps))
274 #define DEFAULT_BUFFER_DURATION     -1
275 #define DEFAULT_BUFFER_SIZE         -1
276 #define DEFAULT_DOWNLOAD            FALSE
277 #define DEFAULT_USE_BUFFERING       FALSE
278 #define DEFAULT_RING_BUFFER_MAX_SIZE 0
279
280 enum
281 {
282   PROP_0,
283   PROP_URI,
284   PROP_CURRENT_URI,
285   PROP_SUBURI,
286   PROP_CURRENT_SUBURI,
287   PROP_SOURCE,
288   PROP_CONNECTION_SPEED,
289   PROP_BUFFER_SIZE,
290   PROP_BUFFER_DURATION,
291   PROP_DOWNLOAD,
292   PROP_USE_BUFFERING,
293   PROP_RING_BUFFER_MAX_SIZE,
294   PROP_CAPS
295 };
296
297 static guint gst_uri_decode_bin3_signals[LAST_SIGNAL] = { 0 };
298
299 static GstStaticCaps default_raw_caps = GST_STATIC_CAPS (DEFAULT_RAW_CAPS);
300
301 static GstStaticPadTemplate video_src_template =
302 GST_STATIC_PAD_TEMPLATE ("video_%u",
303     GST_PAD_SRC,
304     GST_PAD_SOMETIMES,
305     GST_STATIC_CAPS_ANY);
306
307 static GstStaticPadTemplate audio_src_template =
308 GST_STATIC_PAD_TEMPLATE ("audio_%u",
309     GST_PAD_SRC,
310     GST_PAD_SOMETIMES,
311     GST_STATIC_CAPS_ANY);
312
313 static GstStaticPadTemplate text_src_template =
314 GST_STATIC_PAD_TEMPLATE ("text_%u",
315     GST_PAD_SRC,
316     GST_PAD_SOMETIMES,
317     GST_STATIC_CAPS_ANY);
318
319 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src_%u",
320     GST_PAD_SRC,
321     GST_PAD_SOMETIMES,
322     GST_STATIC_CAPS_ANY);
323
324 GType gst_uri_decode_bin3_get_type (void);
325 #define gst_uri_decode_bin3_parent_class parent_class
326 G_DEFINE_TYPE (GstURIDecodeBin3, gst_uri_decode_bin3, GST_TYPE_BIN);
327
328 #define _do_init \
329     GST_DEBUG_CATEGORY_INIT (gst_uri_decode_bin3_debug, "uridecodebin3", 0, "URI decoder element 3"); \
330     playback_element_init (plugin);
331 GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (uridecodebin3, "uridecodebin3",
332     GST_RANK_NONE, GST_TYPE_URI_DECODE_BIN3, _do_init);
333
334 #define REMOVE_SIGNAL(obj,id)            \
335 if (id) {                                \
336   g_signal_handler_disconnect (obj, id); \
337   id = 0;                                \
338 }
339
340 static void gst_uri_decode_bin3_set_property (GObject * object, guint prop_id,
341     const GValue * value, GParamSpec * pspec);
342 static void gst_uri_decode_bin3_get_property (GObject * object, guint prop_id,
343     GValue * value, GParamSpec * pspec);
344 static void gst_uri_decode_bin3_finalize (GObject * obj);
345 static GstSourceHandler *new_source_handler (GstURIDecodeBin3 * uridecodebin,
346     gboolean is_main);
347
348 static GstStateChangeReturn gst_uri_decode_bin3_change_state (GstElement *
349     element, GstStateChange transition);
350 static gboolean gst_uri_decodebin3_send_event (GstElement * element,
351     GstEvent * event);
352
353 static gboolean
354 _gst_int_accumulator (GSignalInvocationHint * ihint,
355     GValue * return_accu, const GValue * handler_return, gpointer dummy)
356 {
357   gint res = g_value_get_int (handler_return);
358
359   g_value_set_int (return_accu, res);
360
361   if (res == -1)
362     return TRUE;
363
364   return FALSE;
365 }
366
367
368 static void
369 gst_uri_decode_bin3_class_init (GstURIDecodeBin3Class * klass)
370 {
371   GObjectClass *gobject_class;
372   GstElementClass *gstelement_class;
373
374   gobject_class = G_OBJECT_CLASS (klass);
375   gstelement_class = GST_ELEMENT_CLASS (klass);
376
377   gobject_class->set_property = gst_uri_decode_bin3_set_property;
378   gobject_class->get_property = gst_uri_decode_bin3_get_property;
379   gobject_class->finalize = gst_uri_decode_bin3_finalize;
380
381   g_object_class_install_property (gobject_class, PROP_URI,
382       g_param_spec_string ("uri", "URI", "URI to decode",
383           DEFAULT_PROP_URI, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
384
385   g_object_class_install_property (gobject_class, PROP_CURRENT_URI,
386       g_param_spec_string ("current-uri", "Current URI",
387           "The currently playing URI", NULL,
388           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
389
390   g_object_class_install_property (gobject_class, PROP_SUBURI,
391       g_param_spec_string ("suburi", ".sub-URI", "Optional URI of a subtitle",
392           NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
393
394   g_object_class_install_property (gobject_class, PROP_CURRENT_SUBURI,
395       g_param_spec_string ("current-suburi", "Current .sub-URI",
396           "The currently playing URI of a subtitle",
397           NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
398
399   g_object_class_install_property (gobject_class, PROP_SOURCE,
400       g_param_spec_object ("source", "Source", "Source object used",
401           GST_TYPE_ELEMENT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
402
403   g_object_class_install_property (gobject_class, PROP_CONNECTION_SPEED,
404       g_param_spec_uint64 ("connection-speed", "Connection Speed",
405           "Network connection speed in kbps (0 = unknown)",
406           0, G_MAXUINT64 / 1000, DEFAULT_CONNECTION_SPEED,
407           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
408
409   g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
410       g_param_spec_int ("buffer-size", "Buffer size (bytes)",
411           "Buffer size when buffering streams (-1 default value)",
412           -1, G_MAXINT, DEFAULT_BUFFER_SIZE,
413           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
414
415   g_object_class_install_property (gobject_class, PROP_BUFFER_DURATION,
416       g_param_spec_int64 ("buffer-duration", "Buffer duration (ns)",
417           "Buffer duration when buffering streams (-1 default value)",
418           -1, G_MAXINT64, DEFAULT_BUFFER_DURATION,
419           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
420
421   /**
422    * GstURIDecodeBin3::download:
423    *
424    * For certain media type, enable download buffering.
425    */
426   g_object_class_install_property (gobject_class, PROP_DOWNLOAD,
427       g_param_spec_boolean ("download", "Download",
428           "Attempt download buffering when buffering network streams",
429           DEFAULT_DOWNLOAD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
430   /**
431    * GstURIDecodeBin3::use-buffering:
432    *
433    * Emit BUFFERING messages based on low-/high-percent thresholds of the
434    * demuxed or parsed data.
435    * When download buffering is activated and used for the current media
436    * type, this property does nothing. Otherwise perform buffering on the
437    * demuxed or parsed media.
438    */
439   g_object_class_install_property (gobject_class, PROP_USE_BUFFERING,
440       g_param_spec_boolean ("use-buffering", "Use Buffering",
441           "Perform buffering on demuxed/parsed media",
442           DEFAULT_USE_BUFFERING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
443
444   /**
445    * GstURIDecodeBin3::ring-buffer-max-size
446    *
447    * The maximum size of the ring buffer in kilobytes. If set to 0, the ring
448    * buffer is disabled. Default is 0.
449    */
450   g_object_class_install_property (gobject_class, PROP_RING_BUFFER_MAX_SIZE,
451       g_param_spec_uint64 ("ring-buffer-max-size",
452           "Max. ring buffer size (bytes)",
453           "Max. amount of data in the ring buffer (bytes, 0 = ring buffer disabled)",
454           0, G_MAXUINT, DEFAULT_RING_BUFFER_MAX_SIZE,
455           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
456
457   g_object_class_install_property (gobject_class, PROP_CAPS,
458       g_param_spec_boxed ("caps", "Caps",
459           "The caps on which to stop decoding. (NULL = default)",
460           GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
461
462   /**
463    * GstURIDecodebin3::select-stream
464    * @decodebin: a #GstURIDecodebin3
465    * @collection: a #GstStreamCollection
466    * @stream: a #GstStream
467    *
468    * This signal is emitted whenever @decodebin needs to decide whether
469    * to expose a @stream of a given @collection.
470    *
471    * Note that the prefered way to select streams is to listen to
472    * GST_MESSAGE_STREAM_COLLECTION on the bus and send a
473    * GST_EVENT_SELECT_STREAMS with the streams the user wants.
474    *
475    * Returns: 1 if the stream should be selected, 0 if it shouldn't be selected.
476    * A value of -1 (default) lets @decodebin decide what to do with the stream.
477    * */
478   gst_uri_decode_bin3_signals[SIGNAL_SELECT_STREAM] =
479       g_signal_new ("select-stream", G_TYPE_FROM_CLASS (klass),
480       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBin3Class, select_stream),
481       _gst_int_accumulator, NULL, NULL, G_TYPE_INT, 2,
482       GST_TYPE_STREAM_COLLECTION, GST_TYPE_STREAM);
483
484   /**
485    * GstURIDecodeBin3::source-setup:
486    * @bin: the uridecodebin.
487    * @source: source element
488    *
489    * This signal is emitted after a source element has been created, so
490    * it can be configured by setting additional properties (e.g. set a
491    * proxy server for an http source, or set the device and read speed for
492    * an audio cd source).
493    */
494   gst_uri_decode_bin3_signals[SIGNAL_SOURCE_SETUP] =
495       g_signal_new ("source-setup", G_TYPE_FROM_CLASS (klass),
496       G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
497   /**
498    * GstURIDecodeBin3::about-to-finish:
499    *
500    * This signal is emitted when the data for the selected URI is
501    * entirely buffered and it is safe to specify another URI.
502    */
503   gst_uri_decode_bin3_signals[SIGNAL_ABOUT_TO_FINISH] =
504       g_signal_new ("about-to-finish", G_TYPE_FROM_CLASS (klass),
505       G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0, G_TYPE_NONE);
506
507
508   gst_element_class_add_static_pad_template (gstelement_class,
509       &video_src_template);
510   gst_element_class_add_static_pad_template (gstelement_class,
511       &audio_src_template);
512   gst_element_class_add_static_pad_template (gstelement_class,
513       &text_src_template);
514   gst_element_class_add_static_pad_template (gstelement_class, &src_template);
515   gst_element_class_set_static_metadata (gstelement_class,
516       "URI Decoder", "Generic/Bin/Decoder",
517       "Autoplug and decode an URI to raw media",
518       "Edward Hervey <edward@centricular.com>, Jan Schmidt <jan@centricular.com>");
519
520   gstelement_class->change_state = gst_uri_decode_bin3_change_state;
521   gstelement_class->send_event =
522       GST_DEBUG_FUNCPTR (gst_uri_decodebin3_send_event);
523
524   klass->select_stream = gst_uridecodebin3_select_stream;
525 }
526
527 static GstPadProbeReturn
528 db_src_probe (GstPad * pad, GstPadProbeInfo * info, OutputPad * output)
529 {
530   /* FIXME : IMPLEMENT */
531
532   /* EOS : Mark pad as EOS */
533
534   /* STREAM_START : Store group_id and check if currently active
535    *  PlayEntry changed */
536
537   return GST_PAD_PROBE_OK;
538 }
539
540 static OutputPad *
541 add_output_pad (GstURIDecodeBin3 * dec, GstPad * target_pad)
542 {
543   OutputPad *output;
544   gchar *pad_name;
545   GstEvent *stream_start;
546
547   output = g_slice_new0 (OutputPad);
548
549   GST_LOG_OBJECT (dec, "Created output %p", output);
550
551   output->uridecodebin = dec;
552   output->target_pad = target_pad;
553   output->current_group_id = (guint) - 1;
554   pad_name = gst_pad_get_name (target_pad);
555   output->ghost_pad = gst_ghost_pad_new (pad_name, target_pad);
556   g_free (pad_name);
557
558   gst_pad_set_active (output->ghost_pad, TRUE);
559
560   stream_start = gst_pad_get_sticky_event (target_pad,
561       GST_EVENT_STREAM_START, 0);
562   if (stream_start) {
563     gst_pad_store_sticky_event (output->ghost_pad, stream_start);
564     gst_event_unref (stream_start);
565   } else {
566     GST_WARNING_OBJECT (target_pad,
567         "Exposing pad without stored stream-start event");
568   }
569
570   gst_element_add_pad (GST_ELEMENT (dec), output->ghost_pad);
571
572   output->probe_id =
573       gst_pad_add_probe (output->target_pad,
574       GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, (GstPadProbeCallback) db_src_probe,
575       output, NULL);
576
577   /* FIXME: LOCK TO PROTECT PAD LIST */
578   dec->output_pads = g_list_append (dec->output_pads, output);
579
580   return output;
581 }
582
583 static void
584 db_pad_added_cb (GstElement * element, GstPad * pad, GstURIDecodeBin3 * dec)
585 {
586   GST_DEBUG_OBJECT (dec, "Wrapping new pad %s:%s", GST_DEBUG_PAD_NAME (pad));
587
588   if (GST_PAD_IS_SRC (pad))
589     add_output_pad (dec, pad);
590 }
591
592 static void
593 db_pad_removed_cb (GstElement * element, GstPad * pad, GstURIDecodeBin3 * dec)
594 {
595   GList *tmp;
596   OutputPad *output = NULL;
597
598   if (!GST_PAD_IS_SRC (pad))
599     return;
600
601   GST_DEBUG_OBJECT (dec, "pad %s:%s", GST_DEBUG_PAD_NAME (pad));
602   /* FIXME: LOCK for list access */
603
604   for (tmp = dec->output_pads; tmp; tmp = tmp->next) {
605     OutputPad *cand = (OutputPad *) tmp->data;
606
607     if (cand->target_pad == pad) {
608       output = cand;
609       dec->output_pads = g_list_delete_link (dec->output_pads, tmp);
610       break;
611     }
612   }
613
614   if (output) {
615     GST_LOG_OBJECT (element, "Removing output %p", output);
616     /* Remove source ghost pad */
617     gst_ghost_pad_set_target ((GstGhostPad *) output->ghost_pad, NULL);
618     gst_element_remove_pad ((GstElement *) dec, output->ghost_pad);
619
620     /* FIXME : Update global/current PlayEntry group_id (did we switch ?) */
621
622     /* Remove event probe */
623     gst_pad_remove_probe (output->target_pad, output->probe_id);
624
625     g_slice_free (OutputPad, output);
626   }
627 }
628
629 static gint
630 db_select_stream_cb (GstElement * decodebin,
631     GstStreamCollection * collection, GstStream * stream,
632     GstURIDecodeBin3 * uridecodebin)
633 {
634   gint response = -1;
635
636   g_signal_emit (uridecodebin,
637       gst_uri_decode_bin3_signals[SIGNAL_SELECT_STREAM], 0, collection, stream,
638       &response);
639   return response;
640 }
641
642 static void
643 db_about_to_finish_cb (GstElement * decodebin, GstURIDecodeBin3 * uridecodebin)
644 {
645   if (!uridecodebin->posted_about_to_finish) {
646     uridecodebin->posted_about_to_finish = TRUE;
647     g_signal_emit (uridecodebin,
648         gst_uri_decode_bin3_signals[SIGNAL_ABOUT_TO_FINISH], 0, NULL);
649   }
650 }
651
652 static void
653 gst_uri_decode_bin3_init (GstURIDecodeBin3 * dec)
654 {
655   g_mutex_init (&dec->lock);
656
657   dec->uri = DEFAULT_PROP_URI;
658   dec->suburi = DEFAULT_PROP_SUBURI;
659   dec->connection_speed = DEFAULT_CONNECTION_SPEED;
660   dec->caps = DEFAULT_CAPS;
661   dec->buffer_duration = DEFAULT_BUFFER_DURATION;
662   dec->buffer_size = DEFAULT_BUFFER_SIZE;
663   dec->download = DEFAULT_DOWNLOAD;
664   dec->use_buffering = DEFAULT_USE_BUFFERING;
665   dec->ring_buffer_max_size = DEFAULT_RING_BUFFER_MAX_SIZE;
666
667   dec->decodebin = gst_element_factory_make ("decodebin3", NULL);
668   gst_bin_add (GST_BIN_CAST (dec), dec->decodebin);
669   dec->db_pad_added_id =
670       g_signal_connect (dec->decodebin, "pad-added",
671       G_CALLBACK (db_pad_added_cb), dec);
672   dec->db_pad_removed_id =
673       g_signal_connect (dec->decodebin, "pad-removed",
674       G_CALLBACK (db_pad_removed_cb), dec);
675   dec->db_select_stream_id =
676       g_signal_connect (dec->decodebin, "select-stream",
677       G_CALLBACK (db_select_stream_cb), dec);
678   dec->db_about_to_finish_id =
679       g_signal_connect (dec->decodebin, "about-to-finish",
680       G_CALLBACK (db_about_to_finish_cb), dec);
681
682   GST_OBJECT_FLAG_SET (dec, GST_ELEMENT_FLAG_SOURCE);
683   gst_bin_set_suppressed_flags (GST_BIN (dec),
684       GST_ELEMENT_FLAG_SOURCE | GST_ELEMENT_FLAG_SINK);
685 }
686
687 static void
688 gst_uri_decode_bin3_finalize (GObject * obj)
689 {
690   GstURIDecodeBin3 *dec = GST_URI_DECODE_BIN3 (obj);
691
692   g_mutex_clear (&dec->lock);
693   g_free (dec->uri);
694   g_free (dec->suburi);
695
696   G_OBJECT_CLASS (parent_class)->finalize (obj);
697 }
698
699 static GstStateChangeReturn
700 activate_source_item (GstSourceItem * item)
701 {
702   GstSourceHandler *handler = item->handler;
703
704   if (handler == NULL) {
705     GST_WARNING ("Can't activate item without a handler");
706     return GST_STATE_CHANGE_FAILURE;
707   }
708
709   g_object_set (handler->urisourcebin, "uri", item->uri, NULL);
710   if (!handler->active) {
711     gst_bin_add ((GstBin *) handler->uridecodebin, handler->urisourcebin);
712     /* if (!gst_element_sync_state_with_parent (handler->urisourcebin)) */
713     /*   return GST_STATE_CHANGE_FAILURE; */
714     handler->active = TRUE;
715   }
716
717   return GST_STATE_CHANGE_SUCCESS;
718 }
719
720 static void
721 src_pad_added_cb (GstElement * element, GstPad * pad,
722     GstSourceHandler * handler)
723 {
724   GstURIDecodeBin3 *uridecodebin;
725   GstPad *sinkpad = NULL;
726   GstPadLinkReturn res;
727   GstPlayItem *current_play_item;
728   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
729
730   uridecodebin = handler->uridecodebin;
731   current_play_item = uridecodebin->current;
732
733   GST_DEBUG_OBJECT (uridecodebin,
734       "New pad %" GST_PTR_FORMAT " from source %" GST_PTR_FORMAT, pad, element);
735
736   /* FIXME: Add probe to unify group_id and detect EOS */
737
738   /* Try to link to main sink pad only if it's from a main handler */
739   if (handler->is_main_source) {
740     sinkpad = gst_element_get_static_pad (uridecodebin->decodebin, "sink");
741     if (gst_pad_is_linked (sinkpad)) {
742       gst_object_unref (sinkpad);
743       sinkpad = NULL;
744     }
745   }
746
747   if (sinkpad == NULL)
748     sinkpad =
749         gst_element_request_pad_simple (uridecodebin->decodebin, "sink_%u");
750
751   if (sinkpad) {
752     GST_DEBUG_OBJECT (uridecodebin,
753         "Linking %" GST_PTR_FORMAT " to %" GST_PTR_FORMAT, pad, sinkpad);
754     res = gst_pad_link (pad, sinkpad);
755     gst_object_unref (sinkpad);
756     if (GST_PAD_LINK_FAILED (res))
757       goto link_failed;
758   }
759
760   /* Activate sub_item after the main source activation was finished */
761   if (handler->is_main_source && current_play_item->sub_item
762       && !current_play_item->sub_item->handler) {
763     current_play_item->sub_item->handler =
764         new_source_handler (uridecodebin, FALSE);
765     ret = activate_source_item (current_play_item->sub_item);
766     if (ret == GST_STATE_CHANGE_FAILURE)
767       goto sub_item_activation_failed;
768   }
769
770   return;
771
772 link_failed:
773   {
774     GST_ERROR_OBJECT (uridecodebin,
775         "failed to link pad %s:%s to decodebin, reason %s (%d)",
776         GST_DEBUG_PAD_NAME (pad), gst_pad_link_get_name (res), res);
777     return;
778   }
779 sub_item_activation_failed:
780   {
781     GST_ERROR_OBJECT (uridecodebin,
782         "failed to activate subtitle playback item");
783     return;
784   }
785 }
786
787 static void
788 src_pad_removed_cb (GstElement * element, GstPad * pad,
789     GstSourceHandler * handler)
790 {
791   GstURIDecodeBin3 *uridecodebin = handler->uridecodebin;
792   GstPad *peer_pad = gst_pad_get_peer (pad);
793
794   if (peer_pad) {
795     GstPadTemplate *templ = gst_pad_get_pad_template (peer_pad);
796
797     GST_DEBUG_OBJECT (uridecodebin,
798         "Source %" GST_PTR_FORMAT " removed pad %" GST_PTR_FORMAT " peer %"
799         GST_PTR_FORMAT, element, pad, peer_pad);
800
801     if (templ) {
802       if (GST_PAD_TEMPLATE_PRESENCE (templ) == GST_PAD_REQUEST) {
803         GST_DEBUG_OBJECT (uridecodebin,
804             "Releasing decodebin pad %" GST_PTR_FORMAT, peer_pad);
805         gst_element_release_request_pad (uridecodebin->decodebin, peer_pad);
806       }
807       gst_object_unref (templ);
808     }
809
810     gst_object_unref (peer_pad);
811   }
812 }
813
814 static void
815 src_source_setup_cb (GstElement * element, GstElement * source,
816     GstSourceHandler * handler)
817 {
818   g_signal_emit (handler->uridecodebin,
819       gst_uri_decode_bin3_signals[SIGNAL_SOURCE_SETUP], 0, source, NULL);
820 }
821
822 static void
823 src_about_to_finish_cb (GstElement * element, GstSourceHandler * handler)
824 {
825   /* FIXME : check if all sources are done */
826   if (!handler->uridecodebin->posted_about_to_finish) {
827     handler->uridecodebin->posted_about_to_finish = TRUE;
828     g_signal_emit (handler->uridecodebin,
829         gst_uri_decode_bin3_signals[SIGNAL_ABOUT_TO_FINISH], 0, NULL);
830   }
831 }
832
833 static GstSourceHandler *
834 new_source_handler (GstURIDecodeBin3 * uridecodebin, gboolean is_main)
835 {
836   GstSourceHandler *handler;
837
838   handler = g_slice_new0 (GstSourceHandler);
839
840   handler->uridecodebin = uridecodebin;
841   handler->is_main_source = is_main;
842   handler->urisourcebin = gst_element_factory_make ("urisourcebin", NULL);
843   /* Set pending properties */
844   g_object_set (handler->urisourcebin,
845       "connection-speed", uridecodebin->connection_speed / 1000,
846       "download", uridecodebin->download,
847       "use-buffering", uridecodebin->use_buffering,
848       "buffer-duration", uridecodebin->buffer_duration,
849       "buffer-size", uridecodebin->buffer_size,
850       "ring-buffer-max-size", uridecodebin->ring_buffer_max_size, NULL);
851
852   handler->pad_added_id =
853       g_signal_connect (handler->urisourcebin, "pad-added",
854       (GCallback) src_pad_added_cb, handler);
855   handler->pad_removed_id =
856       g_signal_connect (handler->urisourcebin, "pad-removed",
857       (GCallback) src_pad_removed_cb, handler);
858   handler->source_setup_id =
859       g_signal_connect (handler->urisourcebin, "source-setup",
860       (GCallback) src_source_setup_cb, handler);
861   handler->about_to_finish_id =
862       g_signal_connect (handler->urisourcebin, "about-to-finish",
863       (GCallback) src_about_to_finish_cb, handler);
864
865   uridecodebin->source_handlers =
866       g_list_append (uridecodebin->source_handlers, handler);
867
868   return handler;
869 }
870
871 static void
872 gst_uri_decode_bin3_set_property (GObject * object, guint prop_id,
873     const GValue * value, GParamSpec * pspec)
874 {
875   GstURIDecodeBin3 *dec = GST_URI_DECODE_BIN3 (object);
876
877   switch (prop_id) {
878     case PROP_URI:
879       if (dec->uri)
880         g_free (dec->uri);
881       dec->uri = g_value_dup_string (value);
882       break;
883     case PROP_SUBURI:
884       if (dec->suburi)
885         g_free (dec->suburi);
886       dec->suburi = g_value_dup_string (value);
887       break;
888     case PROP_CONNECTION_SPEED:
889       GST_URI_DECODE_BIN3_LOCK (dec);
890       dec->connection_speed = g_value_get_uint64 (value) * 1000;
891       GST_URI_DECODE_BIN3_UNLOCK (dec);
892       break;
893     case PROP_BUFFER_SIZE:
894       dec->buffer_size = g_value_get_int (value);
895       break;
896     case PROP_BUFFER_DURATION:
897       dec->buffer_duration = g_value_get_int64 (value);
898       break;
899     case PROP_DOWNLOAD:
900       dec->download = g_value_get_boolean (value);
901       break;
902     case PROP_USE_BUFFERING:
903       dec->use_buffering = g_value_get_boolean (value);
904       break;
905     case PROP_RING_BUFFER_MAX_SIZE:
906       dec->ring_buffer_max_size = g_value_get_uint64 (value);
907       break;
908     case PROP_CAPS:
909       GST_OBJECT_LOCK (dec);
910       if (dec->caps)
911         gst_caps_unref (dec->caps);
912       dec->caps = g_value_dup_boxed (value);
913       GST_OBJECT_UNLOCK (dec);
914       break;
915     default:
916       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
917       break;
918   }
919 }
920
921 static void
922 gst_uri_decode_bin3_get_property (GObject * object, guint prop_id,
923     GValue * value, GParamSpec * pspec)
924 {
925   GstURIDecodeBin3 *dec = GST_URI_DECODE_BIN3 (object);
926
927   switch (prop_id) {
928     case PROP_URI:
929     {
930       g_value_set_string (value, dec->uri);
931       break;
932     }
933     case PROP_CURRENT_URI:
934     {
935       if (dec->current && dec->current->main_item) {
936         g_value_set_string (value, dec->current->main_item->uri);
937       } else {
938         g_value_set_string (value, NULL);
939       }
940       break;
941     }
942     case PROP_SUBURI:
943     {
944       g_value_set_string (value, dec->suburi);
945       break;
946     }
947     case PROP_CURRENT_SUBURI:
948     {
949       if (dec->current && dec->current->sub_item) {
950         g_value_set_string (value, dec->current->sub_item->uri);
951       } else {
952         g_value_set_string (value, NULL);
953       }
954       break;
955     }
956     case PROP_SOURCE:
957     {
958       GST_OBJECT_LOCK (dec);
959       g_value_set_object (value, dec->source);
960       GST_OBJECT_UNLOCK (dec);
961       break;
962     }
963     case PROP_CONNECTION_SPEED:
964       GST_URI_DECODE_BIN3_LOCK (dec);
965       g_value_set_uint64 (value, dec->connection_speed / 1000);
966       GST_URI_DECODE_BIN3_UNLOCK (dec);
967       break;
968     case PROP_BUFFER_SIZE:
969       GST_OBJECT_LOCK (dec);
970       g_value_set_int (value, dec->buffer_size);
971       GST_OBJECT_UNLOCK (dec);
972       break;
973     case PROP_BUFFER_DURATION:
974       GST_OBJECT_LOCK (dec);
975       g_value_set_int64 (value, dec->buffer_duration);
976       GST_OBJECT_UNLOCK (dec);
977       break;
978     case PROP_DOWNLOAD:
979       g_value_set_boolean (value, dec->download);
980       break;
981     case PROP_USE_BUFFERING:
982       g_value_set_boolean (value, dec->use_buffering);
983       break;
984     case PROP_RING_BUFFER_MAX_SIZE:
985       g_value_set_uint64 (value, dec->ring_buffer_max_size);
986       break;
987     case PROP_CAPS:
988       GST_OBJECT_LOCK (dec);
989       g_value_set_boxed (value, dec->caps);
990       GST_OBJECT_UNLOCK (dec);
991       break;
992     default:
993       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
994       break;
995   }
996 }
997
998 static void
999 free_source_handler (GstURIDecodeBin3 * uridecodebin,
1000     GstSourceHandler * handler)
1001 {
1002   GST_LOG_OBJECT (uridecodebin, "source handler %p", handler);
1003   if (handler->active) {
1004     GST_LOG_OBJECT (uridecodebin, "Removing %" GST_PTR_FORMAT,
1005         handler->urisourcebin);
1006     gst_element_set_state (handler->urisourcebin, GST_STATE_NULL);
1007     gst_bin_remove ((GstBin *) uridecodebin, handler->urisourcebin);
1008   }
1009   uridecodebin->source_handlers =
1010       g_list_remove (uridecodebin->source_handlers, handler);
1011   g_slice_free (GstSourceHandler, handler);
1012 }
1013
1014 static GstSourceItem *
1015 new_source_item (GstURIDecodeBin3 * dec, GstPlayItem * item, gchar * uri)
1016 {
1017   GstSourceItem *sourceitem = g_slice_new0 (GstSourceItem);
1018
1019   sourceitem->play_item = item;
1020   sourceitem->uri = uri;
1021
1022   return sourceitem;
1023 }
1024
1025 static void
1026 free_source_item (GstURIDecodeBin3 * uridecodebin, GstSourceItem * item)
1027 {
1028   GST_LOG_OBJECT (uridecodebin, "source item %p", item);
1029   if (item->handler)
1030     free_source_handler (uridecodebin, item->handler);
1031   g_slice_free (GstSourceItem, item);
1032 }
1033
1034 static GstPlayItem *
1035 new_play_item (GstURIDecodeBin3 * dec, gchar * uri, gchar * suburi)
1036 {
1037   GstPlayItem *item = g_slice_new0 (GstPlayItem);
1038
1039   item->uridecodebin = dec;
1040   item->main_item = new_source_item (dec, item, uri);
1041   if (suburi)
1042     item->sub_item = new_source_item (dec, item, suburi);
1043
1044   return item;
1045 }
1046
1047 static void
1048 free_play_item (GstURIDecodeBin3 * dec, GstPlayItem * item)
1049 {
1050   GST_LOG_OBJECT (dec, "play item %p", item);
1051   if (item->main_item)
1052     free_source_item (dec, item->main_item);
1053   if (item->sub_item)
1054     free_source_item (dec, item->sub_item);
1055
1056   g_slice_free (GstPlayItem, item);
1057 }
1058
1059 /* Sync source handlers for the given play item. Might require creating/removing some
1060  * and/or configure the handlers accordingly */
1061 static GstStateChangeReturn
1062 assign_handlers_to_item (GstURIDecodeBin3 * dec, GstPlayItem * item)
1063 {
1064   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
1065
1066   /* FIXME : Go over existing handlers to see if we can assign some to the
1067    * given item */
1068
1069   /* Create missing handlers */
1070   if (item->main_item->handler == NULL) {
1071     item->main_item->handler = new_source_handler (dec, TRUE);
1072     ret = activate_source_item (item->main_item);
1073     if (ret == GST_STATE_CHANGE_FAILURE)
1074       return ret;
1075   }
1076
1077   return ret;
1078 }
1079
1080 /* Called to activate the next play item */
1081 static GstStateChangeReturn
1082 activate_next_play_item (GstURIDecodeBin3 * dec)
1083 {
1084   GstPlayItem *item;
1085   GstStateChangeReturn ret;
1086
1087   /* If there is no current play entry, create one from the uri/suburi
1088    * FIXME : Use a playlist API in the future */
1089   item = new_play_item (dec, dec->uri, dec->suburi);
1090
1091   ret = assign_handlers_to_item (dec, item);
1092   if (ret == GST_STATE_CHANGE_FAILURE) {
1093     free_play_item (dec, item);
1094     return ret;
1095   }
1096
1097   dec->play_items = g_list_append (dec->play_items, item);
1098   dec->current = dec->play_items->data;
1099
1100   return ret;
1101 }
1102
1103 static void
1104 free_play_items (GstURIDecodeBin3 * dec)
1105 {
1106   GList *tmp;
1107
1108   for (tmp = dec->play_items; tmp; tmp = tmp->next) {
1109     GstPlayItem *item = (GstPlayItem *) tmp->data;
1110     free_play_item (dec, item);
1111   }
1112
1113   g_list_free (dec->play_items);
1114   dec->play_items = NULL;
1115   dec->current = NULL;
1116 }
1117
1118 static GstStateChangeReturn
1119 gst_uri_decode_bin3_change_state (GstElement * element,
1120     GstStateChange transition)
1121 {
1122   GstStateChangeReturn ret;
1123   GstURIDecodeBin3 *uridecodebin = (GstURIDecodeBin3 *) element;
1124
1125   switch (transition) {
1126     case GST_STATE_CHANGE_NULL_TO_READY:
1127       g_object_set (uridecodebin->decodebin, "caps", uridecodebin->caps, NULL);
1128       break;
1129     case GST_STATE_CHANGE_READY_TO_PAUSED:
1130       ret = activate_next_play_item (uridecodebin);
1131       if (ret == GST_STATE_CHANGE_FAILURE)
1132         goto failure;
1133     default:
1134       break;
1135   }
1136
1137   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1138   if (ret == GST_STATE_CHANGE_FAILURE)
1139     goto failure;
1140
1141   switch (transition) {
1142     case GST_STATE_CHANGE_PAUSED_TO_READY:
1143       /* FIXME: Cleanup everything */
1144       free_play_items (uridecodebin);
1145       /* Free play item */
1146       uridecodebin->posted_about_to_finish = FALSE;
1147       break;
1148     default:
1149       break;
1150   }
1151
1152   return ret;
1153
1154   /* ERRORS */
1155 failure:
1156   {
1157     if (transition == GST_STATE_CHANGE_READY_TO_PAUSED)
1158       free_play_items (uridecodebin);
1159     return ret;
1160   }
1161 }
1162
1163 static gboolean
1164 gst_uri_decodebin3_send_event (GstElement * element, GstEvent * event)
1165 {
1166   GstURIDecodeBin3 *self = GST_URI_DECODE_BIN3 (element);
1167
1168   if (GST_EVENT_IS_UPSTREAM (event) && self->decodebin)
1169     return gst_element_send_event (self->decodebin, event);
1170
1171   return GST_ELEMENT_CLASS (parent_class)->send_event (element, event);
1172 }