436e37c1293ae006a56c36b17a2c0282586c051c
[platform/upstream/gst-plugins-base.git] / 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 "gstplayback.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   /* Last buffering information */
121   gint last_perc;
122   GstMessage *last_buffering_message;
123
124   /* The groupid created by urisourcebin for this uri */
125   guint internal_groupid;
126
127   /* FIXME : Add tag lists and other uri-specific items here ? */
128 };
129
130 /* Structure wrapping everything related to a urisourcebin */
131 struct _GstSourceHandler
132 {
133   GstURIDecodeBin3 *uridecodebin;
134
135   GstElement *urisourcebin;
136
137   /* Signal handlers */
138   gulong pad_added_id;
139   gulong pad_removed_id;
140   gulong source_setup_id;
141   gulong about_to_finish_id;
142
143   /* TRUE if the controlled urisourcebin was added to uridecodebin */
144   gboolean active;
145
146   /* whether urisourcebin is drained or not.
147    * Reset if/when setting a new URI */
148   gboolean drained;
149
150   /* Whether urisourcebin posted EOS on all pads and
151    * there is no pending entry */
152   gboolean is_eos;
153
154   /* TRUE if the urisourcebin handles main item */
155   gboolean is_main_source;
156
157   /* buffering message stored for after switching */
158   GstMessage *pending_buffering_msg;
159 };
160
161 /* Controls an output source pad */
162 struct _OutputPad
163 {
164   GstURIDecodeBin3 *uridecodebin;
165
166   GstPad *target_pad;
167   GstPad *ghost_pad;
168
169   /* Downstream event probe id */
170   gulong probe_id;
171
172   /* TRUE if the pad saw EOS. Resetted to FALSE on STREAM_START */
173   gboolean is_eos;
174
175   /* The last seen (i.e. current) group_id
176    * Can be (guint)-1 if no group_id was seen yet */
177   guint current_group_id;
178 };
179
180 /**
181  * GstURIDecodeBin3
182  *
183  * uridecodebin3 element struct
184  */
185 struct _GstURIDecodeBin3
186 {
187   GstBin parent_instance;
188
189   GMutex lock;                  /* lock for constructing */
190
191   /* Properties */
192   GstElement *source;
193   guint64 connection_speed;     /* In bits/sec (0 = unknown) */
194   GstCaps *caps;
195   guint64 buffer_duration;      /* When buffering, buffer duration (ns) */
196   guint buffer_size;            /* When buffering, buffer size (bytes) */
197   gboolean download;
198   gboolean use_buffering;
199   guint64 ring_buffer_max_size;
200
201   GList *play_items;            /* List of GstPlayItem ordered by time of
202                                  * creation. Head of list is therefore the
203                                  * current (or pending if initial) one being
204                                  * outputted */
205   GstPlayItem *current;         /* Currently active GstPlayItem. Can be NULL
206                                  * if no entry is active yet (i.e. no source
207                                  * pads) */
208
209   /* sources.
210    * FIXME : Replace by a more modular system later on */
211   GstSourceHandler *main_handler;
212   GstSourceHandler *sub_handler;
213
214   /* URI handling
215    * FIXME : Switch to a playlist-based API */
216   gchar *uri;
217   gboolean uri_changed;         /* TRUE if uri changed */
218   gchar *suburi;
219   gboolean suburi_changed;      /* TRUE if suburi changed */
220
221   /* A global decodebin3 that's used to actually do decoding */
222   GstElement *decodebin;
223
224   /* db3 signals */
225   gulong db_pad_added_id;
226   gulong db_pad_removed_id;
227   gulong db_select_stream_id;
228   gulong db_about_to_finish_id;
229
230   GList *output_pads;           /* List of OutputPad */
231
232   GList *source_handlers;       /* List of SourceHandler */
233
234   /* Whether we already signalled about-to-finish or not
235    * FIXME: Track this by group-id ! */
236   gboolean posted_about_to_finish;
237 };
238
239 struct _GstURIDecodeBin3Class
240 {
241   GstBinClass parent_class;
242
243     gint (*select_stream) (GstURIDecodeBin3 * dbin,
244       GstStreamCollection * collection, GstStream * stream);
245 };
246
247 GST_DEBUG_CATEGORY_STATIC (gst_uri_decode_bin3_debug);
248 #define GST_CAT_DEFAULT gst_uri_decode_bin3_debug
249
250 /* signals */
251 enum
252 {
253   SIGNAL_SELECT_STREAM,
254   SIGNAL_SOURCE_SETUP,
255   SIGNAL_ABOUT_TO_FINISH,
256   LAST_SIGNAL
257 };
258
259 #if 0
260 static GstStaticCaps raw_audio_caps = GST_STATIC_CAPS ("audio/x-raw(ANY)");
261 static GstStaticCaps raw_video_caps = GST_STATIC_CAPS ("video/x-raw(ANY)");
262 #endif
263
264 /* properties */
265 #define DEFAULT_PROP_URI            NULL
266 #define DEFAULT_PROP_SUBURI            NULL
267 #define DEFAULT_PROP_SOURCE         NULL
268 #define DEFAULT_CONNECTION_SPEED    0
269 #define DEFAULT_CAPS                (gst_static_caps_get (&default_raw_caps))
270 #define DEFAULT_BUFFER_DURATION     -1
271 #define DEFAULT_BUFFER_SIZE         -1
272 #define DEFAULT_DOWNLOAD            FALSE
273 #define DEFAULT_USE_BUFFERING       FALSE
274 #define DEFAULT_RING_BUFFER_MAX_SIZE 0
275
276 enum
277 {
278   PROP_0,
279   PROP_URI,
280   PROP_CURRENT_URI,
281   PROP_SUBURI,
282   PROP_CURRENT_SUBURI,
283   PROP_SOURCE,
284   PROP_CONNECTION_SPEED,
285   PROP_BUFFER_SIZE,
286   PROP_BUFFER_DURATION,
287   PROP_DOWNLOAD,
288   PROP_USE_BUFFERING,
289   PROP_RING_BUFFER_MAX_SIZE,
290   PROP_CAPS
291 };
292
293 static guint gst_uri_decode_bin3_signals[LAST_SIGNAL] = { 0 };
294
295 static GstStaticCaps default_raw_caps = GST_STATIC_CAPS (DEFAULT_RAW_CAPS);
296
297 static GstStaticPadTemplate video_src_template =
298 GST_STATIC_PAD_TEMPLATE ("video_%u",
299     GST_PAD_SRC,
300     GST_PAD_SOMETIMES,
301     GST_STATIC_CAPS_ANY);
302
303 static GstStaticPadTemplate audio_src_template =
304 GST_STATIC_PAD_TEMPLATE ("audio_%u",
305     GST_PAD_SRC,
306     GST_PAD_SOMETIMES,
307     GST_STATIC_CAPS_ANY);
308
309 static GstStaticPadTemplate text_src_template =
310 GST_STATIC_PAD_TEMPLATE ("text_%u",
311     GST_PAD_SRC,
312     GST_PAD_SOMETIMES,
313     GST_STATIC_CAPS_ANY);
314
315 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src_%u",
316     GST_PAD_SRC,
317     GST_PAD_SOMETIMES,
318     GST_STATIC_CAPS_ANY);
319
320 GType gst_uri_decode_bin3_get_type (void);
321 #define gst_uri_decode_bin3_parent_class parent_class
322 G_DEFINE_TYPE (GstURIDecodeBin3, gst_uri_decode_bin3, GST_TYPE_BIN);
323
324 #define REMOVE_SIGNAL(obj,id)            \
325 if (id) {                                \
326   g_signal_handler_disconnect (obj, id); \
327   id = 0;                                \
328 }
329
330 static void gst_uri_decode_bin3_set_property (GObject * object, guint prop_id,
331     const GValue * value, GParamSpec * pspec);
332 static void gst_uri_decode_bin3_get_property (GObject * object, guint prop_id,
333     GValue * value, GParamSpec * pspec);
334 static void gst_uri_decode_bin3_finalize (GObject * obj);
335
336 static GstStateChangeReturn gst_uri_decode_bin3_change_state (GstElement *
337     element, GstStateChange transition);
338
339 static gboolean
340 _gst_int_accumulator (GSignalInvocationHint * ihint,
341     GValue * return_accu, const GValue * handler_return, gpointer dummy)
342 {
343   gint res = g_value_get_int (handler_return);
344
345   if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
346     g_value_set_int (return_accu, res);
347
348   if (res == -1)
349     return TRUE;
350
351   return FALSE;
352 }
353
354
355 static void
356 gst_uri_decode_bin3_class_init (GstURIDecodeBin3Class * klass)
357 {
358   GObjectClass *gobject_class;
359   GstElementClass *gstelement_class;
360
361   gobject_class = G_OBJECT_CLASS (klass);
362   gstelement_class = GST_ELEMENT_CLASS (klass);
363
364   gobject_class->set_property = gst_uri_decode_bin3_set_property;
365   gobject_class->get_property = gst_uri_decode_bin3_get_property;
366   gobject_class->finalize = gst_uri_decode_bin3_finalize;
367
368   g_object_class_install_property (gobject_class, PROP_URI,
369       g_param_spec_string ("uri", "URI", "URI to decode",
370           DEFAULT_PROP_URI, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
371
372   g_object_class_install_property (gobject_class, PROP_CURRENT_URI,
373       g_param_spec_string ("current-uri", "Current URI",
374           "The currently playing URI", NULL,
375           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
376
377   g_object_class_install_property (gobject_class, PROP_SUBURI,
378       g_param_spec_string ("suburi", ".sub-URI", "Optional URI of a subtitle",
379           NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
380
381   g_object_class_install_property (gobject_class, PROP_CURRENT_SUBURI,
382       g_param_spec_string ("current-suburi", "Current .sub-URI",
383           "The currently playing URI of a subtitle",
384           NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
385
386   g_object_class_install_property (gobject_class, PROP_SOURCE,
387       g_param_spec_object ("source", "Source", "Source object used",
388           GST_TYPE_ELEMENT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
389
390   g_object_class_install_property (gobject_class, PROP_CONNECTION_SPEED,
391       g_param_spec_uint64 ("connection-speed", "Connection Speed",
392           "Network connection speed in kbps (0 = unknown)",
393           0, G_MAXUINT64 / 1000, DEFAULT_CONNECTION_SPEED,
394           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
395
396   g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE,
397       g_param_spec_int ("buffer-size", "Buffer size (bytes)",
398           "Buffer size when buffering streams (-1 default value)",
399           -1, G_MAXINT, DEFAULT_BUFFER_SIZE,
400           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
401
402   g_object_class_install_property (gobject_class, PROP_BUFFER_DURATION,
403       g_param_spec_int64 ("buffer-duration", "Buffer duration (ns)",
404           "Buffer duration when buffering streams (-1 default value)",
405           -1, G_MAXINT64, DEFAULT_BUFFER_DURATION,
406           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
407
408   /**
409    * GstURIDecodeBin3::download:
410    *
411    * For certain media type, enable download buffering.
412    */
413   g_object_class_install_property (gobject_class, PROP_DOWNLOAD,
414       g_param_spec_boolean ("download", "Download",
415           "Attempt download buffering when buffering network streams",
416           DEFAULT_DOWNLOAD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
417   /**
418    * GstURIDecodeBin3::use-buffering:
419    *
420    * Emit BUFFERING messages based on low-/high-percent thresholds of the
421    * demuxed or parsed data.
422    * When download buffering is activated and used for the current media
423    * type, this property does nothing. Otherwise perform buffering on the
424    * demuxed or parsed media.
425    */
426   g_object_class_install_property (gobject_class, PROP_USE_BUFFERING,
427       g_param_spec_boolean ("use-buffering", "Use Buffering",
428           "Perform buffering on demuxed/parsed media",
429           DEFAULT_USE_BUFFERING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
430
431   /**
432    * GstURIDecodeBin3::ring-buffer-max-size
433    *
434    * The maximum size of the ring buffer in kilobytes. If set to 0, the ring
435    * buffer is disabled. Default is 0.
436    */
437   g_object_class_install_property (gobject_class, PROP_RING_BUFFER_MAX_SIZE,
438       g_param_spec_uint64 ("ring-buffer-max-size",
439           "Max. ring buffer size (bytes)",
440           "Max. amount of data in the ring buffer (bytes, 0 = ring buffer disabled)",
441           0, G_MAXUINT, DEFAULT_RING_BUFFER_MAX_SIZE,
442           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
443
444   g_object_class_install_property (gobject_class, PROP_CAPS,
445       g_param_spec_boxed ("caps", "Caps",
446           "The caps on which to stop decoding. (NULL = default)",
447           GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
448
449   /**
450    * GstURIDecodebin3::select-stream
451    * @decodebin: a #GstURIDecodebin3
452    * @collection: a #GstStreamCollection
453    * @stream: a #GstStream
454    *
455    * This signal is emitted whenever @decodebin needs to decide whether
456    * to expose a @stream of a given @collection.
457    *
458    * Returns: 1 if the stream should be selected, 0 if it shouldn't be selected.
459    * A value of -1 (default) lets @decodebin decide what to do with the stream.
460    * */
461   gst_uri_decode_bin3_signals[SIGNAL_SELECT_STREAM] =
462       g_signal_new ("select-stream", G_TYPE_FROM_CLASS (klass),
463       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBin3Class, select_stream),
464       _gst_int_accumulator, NULL, g_cclosure_marshal_generic,
465       G_TYPE_INT, 2, GST_TYPE_STREAM_COLLECTION, GST_TYPE_STREAM);
466
467   /**
468    * GstURIDecodeBin3::source-setup:
469    * @bin: the uridecodebin.
470    * @source: source element
471    *
472    * This signal is emitted after a source element has been created, so
473    * it can be configured by setting additional properties (e.g. set a
474    * proxy server for an http source, or set the device and read speed for
475    * an audio cd source).
476    */
477   gst_uri_decode_bin3_signals[SIGNAL_SOURCE_SETUP] =
478       g_signal_new ("source-setup", G_TYPE_FROM_CLASS (klass),
479       G_SIGNAL_RUN_LAST, 0, NULL, NULL,
480       g_cclosure_marshal_generic, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
481   /**
482    * GstURIDecodeBin3::about-to-finish:
483    *
484    * This signal is emitted when the data for the selected URI is
485    * entirely buffered and it is safe to specify anothe URI.
486    */
487   gst_uri_decode_bin3_signals[SIGNAL_ABOUT_TO_FINISH] =
488       g_signal_new ("about-to-finish", G_TYPE_FROM_CLASS (klass),
489       G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE,
490       0, G_TYPE_NONE);
491
492
493   gst_element_class_add_static_pad_template (gstelement_class,
494       &video_src_template);
495   gst_element_class_add_static_pad_template (gstelement_class,
496       &audio_src_template);
497   gst_element_class_add_static_pad_template (gstelement_class,
498       &text_src_template);
499   gst_element_class_add_static_pad_template (gstelement_class, &src_template);
500   gst_element_class_set_static_metadata (gstelement_class,
501       "URI Decoder", "Generic/Bin/Decoder",
502       "Autoplug and decode an URI to raw media",
503       "Edward Hervey <edward@centricular.com>, Jan Schmidt <jan@centricular.com>");
504
505   gstelement_class->change_state = gst_uri_decode_bin3_change_state;
506
507 }
508
509 static GstPadProbeReturn
510 db_src_probe (GstPad * pad, GstPadProbeInfo * info, OutputPad * output)
511 {
512   /* FIXME : IMPLEMENT */
513
514   /* EOS : Mark pad as EOS */
515
516   /* STREAM_START : Store group_id and check if currently active
517    *  PlayEntry changed */
518
519   return GST_PAD_PROBE_OK;
520 }
521
522 static OutputPad *
523 add_output_pad (GstURIDecodeBin3 * dec, GstPad * target_pad)
524 {
525   OutputPad *output;
526   gchar *pad_name;
527
528   output = g_slice_new0 (OutputPad);
529
530   GST_LOG_OBJECT (dec, "Created output %p", output);
531
532   output->uridecodebin = dec;
533   output->target_pad = target_pad;
534   output->current_group_id = (guint) - 1;
535   pad_name = gst_pad_get_name (target_pad);
536   output->ghost_pad = gst_ghost_pad_new (pad_name, target_pad);
537   g_free (pad_name);
538
539   gst_pad_set_active (output->ghost_pad, TRUE);
540   gst_element_add_pad (GST_ELEMENT (dec), output->ghost_pad);
541
542   output->probe_id =
543       gst_pad_add_probe (output->target_pad,
544       GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, (GstPadProbeCallback) db_src_probe,
545       output, NULL);
546
547   /* FIXME: LOCK TO PROTECT PAD LIST */
548   dec->output_pads = g_list_append (dec->output_pads, output);
549
550   return output;
551 }
552
553 static void
554 db_pad_added_cb (GstElement * element, GstPad * pad, GstURIDecodeBin3 * dec)
555 {
556   GST_DEBUG_OBJECT (dec, "Wrapping new pad %s:%s", GST_DEBUG_PAD_NAME (pad));
557
558   if (GST_PAD_IS_SRC (pad))
559     add_output_pad (dec, pad);
560 }
561
562 static void
563 db_pad_removed_cb (GstElement * element, GstPad * pad, GstURIDecodeBin3 * dec)
564 {
565   GList *tmp;
566   OutputPad *output = NULL;
567
568   if (!GST_PAD_IS_SRC (pad))
569     return;
570
571   GST_DEBUG_OBJECT (dec, "pad %s:%s", GST_DEBUG_PAD_NAME (pad));
572   /* FIXME: LOCK for list access */
573
574   for (tmp = dec->output_pads; tmp; tmp = tmp->next) {
575     OutputPad *cand = (OutputPad *) tmp->data;
576
577     if (cand->target_pad == pad) {
578       output = cand;
579       dec->output_pads = g_list_remove_link (dec->output_pads, tmp);
580       break;
581     }
582   }
583
584   if (output) {
585     GST_LOG_OBJECT (element, "Removing output %p", output);
586     /* Remove source ghost pad */
587     gst_ghost_pad_set_target ((GstGhostPad *) output->ghost_pad, NULL);
588     gst_element_remove_pad ((GstElement *) dec, output->ghost_pad);
589
590     /* FIXME : Update global/current PlayEntry group_id (did we switch ?) */
591
592     /* Remove event probe */
593     gst_pad_remove_probe (output->target_pad, output->probe_id);
594
595     g_slice_free (OutputPad, output);
596   }
597 }
598
599 static gint
600 db_select_stream_cb (GstElement * decodebin,
601     GstStreamCollection * collection, GstStream * stream,
602     GstURIDecodeBin3 * uridecodebin)
603 {
604   gint response = -1;
605
606   g_signal_emit (uridecodebin,
607       gst_uri_decode_bin3_signals[SIGNAL_SELECT_STREAM], 0, collection, stream,
608       &response);
609   return response;
610 }
611
612 static void
613 db_about_to_finish_cb (GstElement * decodebin, GstURIDecodeBin3 * uridecodebin)
614 {
615   if (!uridecodebin->posted_about_to_finish) {
616     uridecodebin->posted_about_to_finish = TRUE;
617     g_signal_emit (uridecodebin,
618         gst_uri_decode_bin3_signals[SIGNAL_ABOUT_TO_FINISH], 0, NULL);
619   }
620 }
621
622 static void
623 gst_uri_decode_bin3_init (GstURIDecodeBin3 * dec)
624 {
625   g_mutex_init (&dec->lock);
626
627   dec->caps = gst_static_caps_get (&default_raw_caps);
628
629   dec->decodebin = gst_element_factory_make ("decodebin3", NULL);
630   gst_bin_add (GST_BIN_CAST (dec), dec->decodebin);
631   dec->db_pad_added_id =
632       g_signal_connect (dec->decodebin, "pad-added",
633       G_CALLBACK (db_pad_added_cb), dec);
634   dec->db_pad_removed_id =
635       g_signal_connect (dec->decodebin, "pad-removed",
636       G_CALLBACK (db_pad_removed_cb), dec);
637   dec->db_select_stream_id =
638       g_signal_connect (dec->decodebin, "select-stream",
639       G_CALLBACK (db_select_stream_cb), dec);
640   dec->db_about_to_finish_id =
641       g_signal_connect (dec->decodebin, "about-to-finish",
642       G_CALLBACK (db_about_to_finish_cb), dec);
643
644   GST_OBJECT_FLAG_SET (dec, GST_ELEMENT_FLAG_SOURCE);
645   gst_bin_set_suppressed_flags (GST_BIN (dec),
646       GST_ELEMENT_FLAG_SOURCE | GST_ELEMENT_FLAG_SINK);
647 }
648
649 static void
650 gst_uri_decode_bin3_finalize (GObject * obj)
651 {
652   GstURIDecodeBin3 *dec = GST_URI_DECODE_BIN3 (obj);
653
654   g_mutex_clear (&dec->lock);
655
656   G_OBJECT_CLASS (parent_class)->finalize (obj);
657 }
658
659 static GstStateChangeReturn
660 activate_source_item (GstSourceItem * item)
661 {
662   GstSourceHandler *handler = item->handler;
663
664   if (handler == NULL) {
665     GST_WARNING ("Can't activate item without a handler");
666     return GST_STATE_CHANGE_FAILURE;
667   }
668
669   g_object_set (handler->urisourcebin, "uri", item->uri, NULL);
670   if (!handler->active) {
671     gst_bin_add ((GstBin *) handler->uridecodebin, handler->urisourcebin);
672     /* if (!gst_element_sync_state_with_parent (handler->urisourcebin)) */
673     /*   return GST_STATE_CHANGE_FAILURE; */
674     handler->active = TRUE;
675   }
676
677   return GST_STATE_CHANGE_SUCCESS;
678 }
679
680 static void
681 src_pad_added_cb (GstElement * element, GstPad * pad,
682     GstSourceHandler * handler)
683 {
684   GstURIDecodeBin3 *uridecodebin;
685   GstPad *sinkpad = NULL;
686   GstPadLinkReturn res;
687
688   uridecodebin = handler->uridecodebin;
689
690   GST_DEBUG_OBJECT (uridecodebin,
691       "New pad %" GST_PTR_FORMAT " from source %" GST_PTR_FORMAT, pad, element);
692
693   /* FIXME: Add probe to unify group_id and detect EOS */
694
695   /* Try to link to main sink pad only if it's from a main handler */
696   if (handler->is_main_source) {
697     sinkpad = gst_element_get_static_pad (uridecodebin->decodebin, "sink");
698     if (gst_pad_is_linked (sinkpad)) {
699       gst_object_unref (sinkpad);
700       sinkpad = NULL;
701     }
702   }
703
704   if (sinkpad == NULL)
705     sinkpad = gst_element_get_request_pad (uridecodebin->decodebin, "sink_%u");
706
707   if (sinkpad) {
708     GST_DEBUG_OBJECT (uridecodebin,
709         "Linking %" GST_PTR_FORMAT " to %" GST_PTR_FORMAT, pad, sinkpad);
710     res = gst_pad_link (pad, sinkpad);
711     gst_object_unref (sinkpad);
712     if (GST_PAD_LINK_FAILED (res))
713       goto link_failed;
714   }
715   return;
716
717 link_failed:
718   {
719     GST_ERROR_OBJECT (uridecodebin,
720         "failed to link pad %s:%s to decodebin, reason %s (%d)",
721         GST_DEBUG_PAD_NAME (pad), gst_pad_link_get_name (res), res);
722     return;
723   }
724 }
725
726 static void
727 src_pad_removed_cb (GstElement * element, GstPad * pad,
728     GstSourceHandler * handler)
729 {
730   /* FIXME : IMPLEMENT */
731 }
732
733 static void
734 src_source_setup_cb (GstElement * element, GstElement * source,
735     GstSourceHandler * handler)
736 {
737   g_signal_emit (handler->uridecodebin,
738       gst_uri_decode_bin3_signals[SIGNAL_SOURCE_SETUP], 0, source, NULL);
739 }
740
741 static void
742 src_about_to_finish_cb (GstElement * element, GstSourceHandler * handler)
743 {
744   /* FIXME : check if all sources are done */
745   if (!handler->uridecodebin->posted_about_to_finish) {
746     handler->uridecodebin->posted_about_to_finish = TRUE;
747     g_signal_emit (handler->uridecodebin,
748         gst_uri_decode_bin3_signals[SIGNAL_ABOUT_TO_FINISH], 0, NULL);
749   }
750 }
751
752 static GstSourceHandler *
753 new_source_handler (GstURIDecodeBin3 * uridecodebin, gboolean is_main)
754 {
755   GstSourceHandler *handler;
756
757   handler = g_slice_new0 (GstSourceHandler);
758
759   handler->uridecodebin = uridecodebin;
760   handler->is_main_source = is_main;
761   handler->urisourcebin = gst_element_factory_make ("urisourcebin", NULL);
762   /* Set pending properties */
763   g_object_set (handler->urisourcebin,
764       "connection-speed", uridecodebin->connection_speed / 1000,
765       "download", uridecodebin->download,
766       "use-buffering", uridecodebin->use_buffering,
767       "buffer-duration", uridecodebin->buffer_duration,
768       "buffer-size", uridecodebin->buffer_size,
769       "ring-buffer-max-size", uridecodebin->ring_buffer_max_size, NULL);
770
771   handler->pad_added_id =
772       g_signal_connect (handler->urisourcebin, "pad-added",
773       (GCallback) src_pad_added_cb, handler);
774   handler->pad_removed_id =
775       g_signal_connect (handler->urisourcebin, "pad-removed",
776       (GCallback) src_pad_removed_cb, handler);
777   handler->source_setup_id =
778       g_signal_connect (handler->urisourcebin, "source-setup",
779       (GCallback) src_source_setup_cb, handler);
780   handler->about_to_finish_id =
781       g_signal_connect (handler->urisourcebin, "about-to-finish",
782       (GCallback) src_about_to_finish_cb, handler);
783
784   uridecodebin->source_handlers =
785       g_list_append (uridecodebin->source_handlers, handler);
786
787   return handler;
788 }
789
790 static void
791 gst_uri_decode_bin3_set_property (GObject * object, guint prop_id,
792     const GValue * value, GParamSpec * pspec)
793 {
794   GstURIDecodeBin3 *dec = GST_URI_DECODE_BIN3 (object);
795
796   switch (prop_id) {
797     case PROP_URI:
798       if (dec->uri)
799         g_free (dec->uri);
800       dec->uri = g_value_dup_string (value);
801       break;
802     case PROP_SUBURI:
803       if (dec->suburi)
804         g_free (dec->suburi);
805       dec->suburi = g_value_dup_string (value);
806       break;
807     case PROP_CONNECTION_SPEED:
808       GST_URI_DECODE_BIN3_LOCK (dec);
809       dec->connection_speed = g_value_get_uint64 (value) * 1000;
810       GST_URI_DECODE_BIN3_UNLOCK (dec);
811       break;
812     case PROP_BUFFER_SIZE:
813       dec->buffer_size = g_value_get_int (value);
814       break;
815     case PROP_BUFFER_DURATION:
816       dec->buffer_duration = g_value_get_int64 (value);
817       break;
818     case PROP_DOWNLOAD:
819       dec->download = g_value_get_boolean (value);
820       break;
821     case PROP_USE_BUFFERING:
822       dec->use_buffering = g_value_get_boolean (value);
823       break;
824     case PROP_RING_BUFFER_MAX_SIZE:
825       dec->ring_buffer_max_size = g_value_get_uint64 (value);
826       break;
827     case PROP_CAPS:
828       GST_OBJECT_LOCK (dec);
829       if (dec->caps)
830         gst_caps_unref (dec->caps);
831       dec->caps = g_value_dup_boxed (value);
832       GST_OBJECT_UNLOCK (dec);
833       break;
834     default:
835       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
836       break;
837   }
838 }
839
840 static void
841 gst_uri_decode_bin3_get_property (GObject * object, guint prop_id,
842     GValue * value, GParamSpec * pspec)
843 {
844   GstURIDecodeBin3 *dec = GST_URI_DECODE_BIN3 (object);
845
846   switch (prop_id) {
847     case PROP_URI:
848     {
849       g_value_set_string (value, dec->uri);
850       break;
851     }
852     case PROP_CURRENT_URI:
853     {
854       g_value_set_string (value, dec->suburi);
855       break;
856     }
857     case PROP_SUBURI:
858     {
859       /* FIXME : Return current uri */
860       g_value_set_string (value, dec->uri);
861       break;
862     }
863     case PROP_CURRENT_SUBURI:
864     {
865       /* FIXME : Return current suburi */
866       g_value_set_string (value, dec->suburi);
867       break;
868     }
869     case PROP_SOURCE:
870     {
871       GST_OBJECT_LOCK (dec);
872       g_value_set_object (value, dec->source);
873       GST_OBJECT_UNLOCK (dec);
874       break;
875     }
876     case PROP_CONNECTION_SPEED:
877       GST_URI_DECODE_BIN3_LOCK (dec);
878       g_value_set_uint64 (value, dec->connection_speed / 1000);
879       GST_URI_DECODE_BIN3_UNLOCK (dec);
880       break;
881     case PROP_BUFFER_SIZE:
882       GST_OBJECT_LOCK (dec);
883       g_value_set_int (value, dec->buffer_size);
884       GST_OBJECT_UNLOCK (dec);
885       break;
886     case PROP_BUFFER_DURATION:
887       GST_OBJECT_LOCK (dec);
888       g_value_set_int64 (value, dec->buffer_duration);
889       GST_OBJECT_UNLOCK (dec);
890       break;
891     case PROP_DOWNLOAD:
892       g_value_set_boolean (value, dec->download);
893       break;
894     case PROP_USE_BUFFERING:
895       g_value_set_boolean (value, dec->use_buffering);
896       break;
897     case PROP_RING_BUFFER_MAX_SIZE:
898       g_value_set_uint64 (value, dec->ring_buffer_max_size);
899       break;
900     case PROP_CAPS:
901       GST_OBJECT_LOCK (dec);
902       g_value_set_boxed (value, dec->caps);
903       GST_OBJECT_UNLOCK (dec);
904       break;
905     default:
906       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
907       break;
908   }
909 }
910
911 static void
912 free_source_handler (GstURIDecodeBin3 * uridecodebin,
913     GstSourceHandler * handler)
914 {
915   GST_LOG_OBJECT (uridecodebin, "source handler %p", handler);
916   if (handler->active) {
917     GST_LOG_OBJECT (uridecodebin, "Removing %" GST_PTR_FORMAT,
918         handler->urisourcebin);
919     gst_element_set_state (handler->urisourcebin, GST_STATE_NULL);
920     gst_bin_remove ((GstBin *) uridecodebin, handler->urisourcebin);
921   }
922   uridecodebin->source_handlers =
923       g_list_remove (uridecodebin->source_handlers, handler);
924   g_slice_free (GstSourceHandler, handler);
925 }
926
927 static GstSourceItem *
928 new_source_item (GstURIDecodeBin3 * dec, GstPlayItem * item, gchar * uri)
929 {
930   GstSourceItem *sourceitem = g_slice_new0 (GstSourceItem);
931
932   sourceitem->play_item = item;
933   sourceitem->uri = uri;
934
935   return sourceitem;
936 }
937
938 static void
939 free_source_item (GstURIDecodeBin3 * uridecodebin, GstSourceItem * item)
940 {
941   GST_LOG_OBJECT (uridecodebin, "source item %p", item);
942   if (item->handler)
943     free_source_handler (uridecodebin, item->handler);
944   g_slice_free (GstSourceItem, item);
945 }
946
947 static GstPlayItem *
948 new_play_item (GstURIDecodeBin3 * dec, gchar * uri, gchar * suburi)
949 {
950   GstPlayItem *item = g_slice_new0 (GstPlayItem);
951
952   item->uridecodebin = dec;
953   item->main_item = new_source_item (dec, item, uri);
954   if (suburi)
955     item->sub_item = new_source_item (dec, item, suburi);
956
957   return item;
958 }
959
960 static void
961 free_play_item (GstURIDecodeBin3 * dec, GstPlayItem * item)
962 {
963   GST_LOG_OBJECT (dec, "play item %p", item);
964   if (item->main_item)
965     free_source_item (dec, item->main_item);
966   if (item->sub_item)
967     free_source_item (dec, item->sub_item);
968
969   g_slice_free (GstPlayItem, item);
970 }
971
972 /* Sync source handlers for the given play item. Might require creating/removing some
973  * and/or configure the handlers accordingly */
974 static GstStateChangeReturn
975 assign_handlers_to_item (GstURIDecodeBin3 * dec, GstPlayItem * item)
976 {
977   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
978
979   /* FIXME : Go over existing handlers to see if we can assign some to the
980    * given item */
981
982   /* Create missing handlers */
983   if (item->main_item->handler == NULL) {
984     item->main_item->handler = new_source_handler (dec, TRUE);
985     ret = activate_source_item (item->main_item);
986     if (ret == GST_STATE_CHANGE_FAILURE)
987       return ret;
988   }
989
990   if (item->sub_item && item->sub_item->handler) {
991     item->sub_item->handler = new_source_handler (dec, FALSE);
992     ret = activate_source_item (item->sub_item);
993   }
994
995   return ret;
996 }
997
998 /* Called to activate the next play item */
999 static GstStateChangeReturn
1000 activate_next_play_item (GstURIDecodeBin3 * dec)
1001 {
1002   GstPlayItem *item;
1003   GstStateChangeReturn ret;
1004
1005   /* If there is no current play entry, create one from the uri/suburi
1006    * FIXME : Use a playlist API in the future */
1007   item = new_play_item (dec, dec->uri, dec->suburi);
1008
1009   ret = assign_handlers_to_item (dec, item);
1010   if (ret == GST_STATE_CHANGE_FAILURE) {
1011     free_play_item (dec, item);
1012     return ret;
1013   }
1014
1015   dec->play_items = g_list_append (dec->play_items, item);
1016
1017   return ret;
1018 }
1019
1020 static void
1021 free_play_items (GstURIDecodeBin3 * dec)
1022 {
1023   GList *tmp;
1024
1025   for (tmp = dec->play_items; tmp; tmp = tmp->next) {
1026     GstPlayItem *item = (GstPlayItem *) tmp->data;
1027     free_play_item (dec, item);
1028   }
1029
1030   g_list_free (dec->play_items);
1031   dec->play_items = NULL;
1032 }
1033
1034 static GstStateChangeReturn
1035 gst_uri_decode_bin3_change_state (GstElement * element,
1036     GstStateChange transition)
1037 {
1038   GstStateChangeReturn ret;
1039   GstURIDecodeBin3 *uridecodebin = (GstURIDecodeBin3 *) element;
1040
1041   switch (transition) {
1042     case GST_STATE_CHANGE_READY_TO_PAUSED:
1043       ret = activate_next_play_item (uridecodebin);
1044       if (ret == GST_STATE_CHANGE_FAILURE)
1045         goto failure;
1046     default:
1047       break;
1048   }
1049
1050   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1051   if (ret == GST_STATE_CHANGE_FAILURE)
1052     goto failure;
1053
1054   switch (transition) {
1055     case GST_STATE_CHANGE_PAUSED_TO_READY:
1056       /* FIXME: Cleanup everything */
1057       free_play_items (uridecodebin);
1058       /* Free play item */
1059       uridecodebin->posted_about_to_finish = FALSE;
1060       break;
1061     default:
1062       break;
1063   }
1064
1065   return ret;
1066
1067   /* ERRORS */
1068 failure:
1069   {
1070     if (transition == GST_STATE_CHANGE_READY_TO_PAUSED)
1071       free_play_items (uridecodebin);
1072     return ret;
1073   }
1074 }
1075
1076
1077 gboolean
1078 gst_uri_decode_bin3_plugin_init (GstPlugin * plugin)
1079 {
1080   GST_DEBUG_CATEGORY_INIT (gst_uri_decode_bin3_debug, "uridecodebin3", 0,
1081       "URI decoder element 3");
1082
1083   return gst_element_register (plugin, "uridecodebin3", GST_RANK_NONE,
1084       GST_TYPE_URI_DECODE_BIN3);
1085 }