Merge branch 'master' into 0.11
[platform/upstream/gstreamer.git] / gst / playback / gstplaybin2.c
1 /* GStreamer
2  * Copyright (C) <2007> Wim Taymans <wim.taymans@gmail.com>
3  * Copyright (C) <2011> Sebastian Dröge <sebastian.droege@collabora.co.uk>
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., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /**
22  * SECTION:element-playbin2
23  *
24  * Playbin2 provides a stand-alone everything-in-one abstraction for an
25  * audio and/or video player.
26  *
27  * playbin2 is considered stable now. It is the prefered playback API now,
28  * and replaces the old #playbin element, which is no longer supported.
29  *
30  * It can handle both audio and video files and features
31  * <itemizedlist>
32  * <listitem>
33  * automatic file type recognition and based on that automatic
34  * selection and usage of the right audio/video/subtitle demuxers/decoders
35  * </listitem>
36  * <listitem>
37  * visualisations for audio files
38  * </listitem>
39  * <listitem>
40  * subtitle support for video files. Subtitles can be store in external
41  * files.
42  * </listitem>
43  * <listitem>
44  * stream selection between different video/audio/subtitles streams
45  * </listitem>
46  * <listitem>
47  * meta info (tag) extraction
48  * </listitem>
49  * <listitem>
50  * easy access to the last video frame
51  * </listitem>
52  * <listitem>
53  * buffering when playing streams over a network
54  * </listitem>
55  * <listitem>
56  * volume control with mute option
57  * </listitem>
58  * </itemizedlist>
59  *
60  * <refsect2>
61  * <title>Usage</title>
62  * <para>
63  * A playbin2 element can be created just like any other element using
64  * gst_element_factory_make(). The file/URI to play should be set via the #GstPlayBin2:uri
65  * property. This must be an absolute URI, relative file paths are not allowed.
66  * Example URIs are file:///home/joe/movie.avi or http://www.joedoe.com/foo.ogg
67  *
68  * Playbin is a #GstPipeline. It will notify the application of everything
69  * that's happening (errors, end of stream, tags found, state changes, etc.)
70  * by posting messages on its #GstBus. The application needs to watch the
71  * bus.
72  *
73  * Playback can be initiated by setting the element to PLAYING state using
74  * gst_element_set_state(). Note that the state change will take place in
75  * the background in a separate thread, when the function returns playback
76  * is probably not happening yet and any errors might not have occured yet.
77  * Applications using playbin should ideally be written to deal with things
78  * completely asynchroneous.
79  *
80  * When playback has finished (an EOS message has been received on the bus)
81  * or an error has occured (an ERROR message has been received on the bus) or
82  * the user wants to play a different track, playbin should be set back to
83  * READY or NULL state, then the #GstPlayBin2:uri property should be set to the
84  * new location and then playbin be set to PLAYING state again.
85  *
86  * Seeking can be done using gst_element_seek_simple() or gst_element_seek()
87  * on the playbin element. Again, the seek will not be executed
88  * instantaneously, but will be done in a background thread. When the seek
89  * call returns the seek will most likely still be in process. An application
90  * may wait for the seek to finish (or fail) using gst_element_get_state() with
91  * -1 as the timeout, but this will block the user interface and is not
92  * recommended at all.
93  *
94  * Applications may query the current position and duration of the stream
95  * via gst_element_query_position() and gst_element_query_duration() and
96  * setting the format passed to GST_FORMAT_TIME. If the query was successful,
97  * the duration or position will have been returned in units of nanoseconds.
98  * </para>
99  * </refsect2>
100  * <refsect2>
101  * <title>Advanced Usage: specifying the audio and video sink</title>
102  * <para>
103  * By default, if no audio sink or video sink has been specified via the
104  * #GstPlayBin2:audio-sink or #GstPlayBin2:video-sink property, playbin will use the autoaudiosink
105  * and autovideosink elements to find the first-best available output method.
106  * This should work in most cases, but is not always desirable. Often either
107  * the user or application might want to specify more explicitly what to use
108  * for audio and video output.
109  *
110  * If the application wants more control over how audio or video should be
111  * output, it may create the audio/video sink elements itself (for example
112  * using gst_element_factory_make()) and provide them to playbin using the
113  * #GstPlayBin2:audio-sink or #GstPlayBin2:video-sink property.
114  *
115  * GNOME-based applications, for example, will usually want to create
116  * gconfaudiosink and gconfvideosink elements and make playbin use those,
117  * so that output happens to whatever the user has configured in the GNOME
118  * Multimedia System Selector configuration dialog.
119  *
120  * The sink elements do not necessarily need to be ready-made sinks. It is
121  * possible to create container elements that look like a sink to playbin,
122  * but in reality contain a number of custom elements linked together. This
123  * can be achieved by creating a #GstBin and putting elements in there and
124  * linking them, and then creating a sink #GstGhostPad for the bin and pointing
125  * it to the sink pad of the first element within the bin. This can be used
126  * for a number of purposes, for example to force output to a particular
127  * format or to modify or observe the data before it is output.
128  *
129  * It is also possible to 'suppress' audio and/or video output by using
130  * 'fakesink' elements (or capture it from there using the fakesink element's
131  * "handoff" signal, which, nota bene, is fired from the streaming thread!).
132  * </para>
133  * </refsect2>
134  * <refsect2>
135  * <title>Retrieving Tags and Other Meta Data</title>
136  * <para>
137  * Most of the common meta data (artist, title, etc.) can be retrieved by
138  * watching for TAG messages on the pipeline's bus (see above).
139  *
140  * Other more specific meta information like width/height/framerate of video
141  * streams or samplerate/number of channels of audio streams can be obtained
142  * from the negotiated caps on the sink pads of the sinks.
143  * </para>
144  * </refsect2>
145  * <refsect2>
146  * <title>Buffering</title>
147  * Playbin handles buffering automatically for the most part, but applications
148  * need to handle parts of the buffering process as well. Whenever playbin is
149  * buffering, it will post BUFFERING messages on the bus with a percentage
150  * value that shows the progress of the buffering process. Applications need
151  * to set playbin to PLAYING or PAUSED state in response to these messages.
152  * They may also want to convey the buffering progress to the user in some
153  * way. Here is how to extract the percentage information from the message
154  * (requires GStreamer >= 0.10.11):
155  * |[
156  * switch (GST_MESSAGE_TYPE (msg)) {
157  *   case GST_MESSAGE_BUFFERING: {
158  *     gint percent = 0;
159  *     gst_message_parse_buffering (msg, &amp;percent);
160  *     g_print ("Buffering (%%u percent done)", percent);
161  *     break;
162  *   }
163  *   ...
164  * }
165  * ]|
166  * Note that applications should keep/set the pipeline in the PAUSED state when
167  * a BUFFERING message is received with a buffer percent value < 100 and set
168  * the pipeline back to PLAYING state when a BUFFERING message with a value
169  * of 100 percent is received (if PLAYING is the desired state, that is).
170  * </refsect2>
171  * <refsect2>
172  * <title>Embedding the video window in your application</title>
173  * By default, playbin (or rather the video sinks used) will create their own
174  * window. Applications will usually want to force output to a window of their
175  * own, however. This can be done using the #GstXOverlay interface, which most
176  * video sinks implement. See the documentation there for more details.
177  * </refsect2>
178  * <refsect2>
179  * <title>Specifying which CD/DVD device to use</title>
180  * The device to use for CDs/DVDs needs to be set on the source element
181  * playbin creates before it is opened. The only way to do this at the moment
182  * is to connect to playbin's "notify::source" signal, which will be emitted
183  * by playbin when it has created the source element for a particular URI.
184  * In the signal callback you can check if the source element has a "device"
185  * property and set it appropriately. In future ways might be added to specify
186  * the device as part of the URI, but at the time of writing this is not
187  * possible yet.
188  * </refsect2>
189  * <refsect2>
190  * <title>Handling redirects</title>
191  * <para>
192  * Some elements may post 'redirect' messages on the bus to tell the
193  * application to open another location. These are element messages containing
194  * a structure named 'redirect' along with a 'new-location' field of string
195  * type. The new location may be a relative or an absolute URI. Examples
196  * for such redirects can be found in many quicktime movie trailers.
197  * </para>
198  * </refsect2>
199  * <refsect2>
200  * <title>Examples</title>
201  * |[
202  * gst-launch -v playbin uri=file:///path/to/somefile.avi
203  * ]| This will play back the given AVI video file, given that the video and
204  * audio decoders required to decode the content are installed. Since no
205  * special audio sink or video sink is supplied (not possible via gst-launch),
206  * playbin will try to find a suitable audio and video sink automatically
207  * using the autoaudiosink and autovideosink elements.
208  * |[
209  * gst-launch -v playbin uri=cdda://4
210  * ]| This will play back track 4 on an audio CD in your disc drive (assuming
211  * the drive is detected automatically by the plugin).
212  * |[
213  * gst-launch -v playbin uri=dvd://1
214  * ]| This will play back title 1 of a DVD in your disc drive (assuming
215  * the drive is detected automatically by the plugin).
216  * </refsect2>
217  */
218
219 #ifdef HAVE_CONFIG_H
220 #include "config.h"
221 #endif
222
223 #include <string.h>
224 #include <gst/gst.h>
225
226 #include <gst/gst-i18n-plugin.h>
227 #include <gst/pbutils/pbutils.h>
228 #include <gst/interfaces/streamvolume.h>
229
230 #include "gstplay-enum.h"
231 #include "gstplay-marshal.h"
232 #include "gstplayback.h"
233 #include "gstplaysink.h"
234 #include "gstsubtitleoverlay.h"
235
236 GST_DEBUG_CATEGORY_STATIC (gst_play_bin_debug);
237 #define GST_CAT_DEFAULT gst_play_bin_debug
238
239 #define GST_TYPE_PLAY_BIN               (gst_play_bin_get_type())
240 #define GST_PLAY_BIN(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PLAY_BIN,GstPlayBin))
241 #define GST_PLAY_BIN_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PLAY_BIN,GstPlayBinClass))
242 #define GST_IS_PLAY_BIN(obj)            (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PLAY_BIN))
243 #define GST_IS_PLAY_BIN_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PLAY_BIN))
244
245 #define VOLUME_MAX_DOUBLE 10.0
246
247 typedef struct _GstPlayBin GstPlayBin;
248 typedef struct _GstPlayBinClass GstPlayBinClass;
249 typedef struct _GstSourceGroup GstSourceGroup;
250 typedef struct _GstSourceSelect GstSourceSelect;
251
252 typedef GstCaps *(*SourceSelectGetMediaCapsFunc) (void);
253
254 /* has the info for a selector and provides the link to the sink */
255 struct _GstSourceSelect
256 {
257   const gchar *media_list[8];   /* the media types for the selector */
258   SourceSelectGetMediaCapsFunc get_media_caps;  /* more complex caps for the selector */
259   GstPlaySinkType type;         /* the sink pad type of the selector */
260
261   GstElement *selector;         /* the selector */
262   GPtrArray *channels;
263   GstPad *srcpad;               /* the source pad of the selector */
264   GstPad *sinkpad;              /* the sinkpad of the sink when the selector
265                                  * is linked
266                                  */
267   GstEvent *sinkpad_delayed_event;
268   gulong sinkpad_data_probe;
269 };
270
271 #define GST_SOURCE_GROUP_GET_LOCK(group) (((GstSourceGroup*)(group))->lock)
272 #define GST_SOURCE_GROUP_LOCK(group) (g_mutex_lock (GST_SOURCE_GROUP_GET_LOCK(group)))
273 #define GST_SOURCE_GROUP_UNLOCK(group) (g_mutex_unlock (GST_SOURCE_GROUP_GET_LOCK(group)))
274
275 enum
276 {
277   PLAYBIN_STREAM_AUDIO = 0,
278   PLAYBIN_STREAM_VIDEO,
279   PLAYBIN_STREAM_TEXT,
280   PLAYBIN_STREAM_LAST
281 };
282
283 /* a structure to hold the objects for decoding a uri and the subtitle uri
284  */
285 struct _GstSourceGroup
286 {
287   GstPlayBin *playbin;
288
289   GMutex *lock;
290
291   gboolean valid;               /* the group has valid info to start playback */
292   gboolean active;              /* the group is active */
293
294   /* properties */
295   gchar *uri;
296   gchar *suburi;
297   GValueArray *streaminfo;
298   GstElement *source;
299
300   GPtrArray *video_channels;    /* links to selector pads */
301   GPtrArray *audio_channels;    /* links to selector pads */
302   GPtrArray *text_channels;     /* links to selector pads */
303
304   GstElement *audio_sink;       /* autoplugged audio and video sinks */
305   GstElement *video_sink;
306
307   /* uridecodebins for uri and subtitle uri */
308   GstElement *uridecodebin;
309   GstElement *suburidecodebin;
310   gint pending;
311   gboolean sub_pending;
312
313   gulong pad_added_id;
314   gulong pad_removed_id;
315   gulong no_more_pads_id;
316   gulong notify_source_id;
317   gulong drained_id;
318   gulong autoplug_factories_id;
319   gulong autoplug_select_id;
320   gulong autoplug_continue_id;
321
322   gulong sub_pad_added_id;
323   gulong sub_pad_removed_id;
324   gulong sub_no_more_pads_id;
325   gulong sub_autoplug_continue_id;
326
327   GMutex *stream_changed_pending_lock;
328   GList *stream_changed_pending;
329
330   /* selectors for different streams */
331   GstSourceSelect selector[PLAYBIN_STREAM_LAST];
332 };
333
334 #define GST_PLAY_BIN_GET_LOCK(bin) (&((GstPlayBin*)(bin))->lock)
335 #define GST_PLAY_BIN_LOCK(bin) (g_static_rec_mutex_lock (GST_PLAY_BIN_GET_LOCK(bin)))
336 #define GST_PLAY_BIN_UNLOCK(bin) (g_static_rec_mutex_unlock (GST_PLAY_BIN_GET_LOCK(bin)))
337
338 /* lock to protect dynamic callbacks, like no-more-pads */
339 #define GST_PLAY_BIN_DYN_LOCK(bin)    g_mutex_lock ((bin)->dyn_lock)
340 #define GST_PLAY_BIN_DYN_UNLOCK(bin)  g_mutex_unlock ((bin)->dyn_lock)
341
342 /* lock for shutdown */
343 #define GST_PLAY_BIN_SHUTDOWN_LOCK(bin,label)           \
344 G_STMT_START {                                          \
345   if (G_UNLIKELY (g_atomic_int_get (&bin->shutdown)))   \
346     goto label;                                         \
347   GST_PLAY_BIN_DYN_LOCK (bin);                          \
348   if (G_UNLIKELY (g_atomic_int_get (&bin->shutdown))) { \
349     GST_PLAY_BIN_DYN_UNLOCK (bin);                      \
350     goto label;                                         \
351   }                                                     \
352 } G_STMT_END
353
354 /* unlock for shutdown */
355 #define GST_PLAY_BIN_SHUTDOWN_UNLOCK(bin)         \
356   GST_PLAY_BIN_DYN_UNLOCK (bin);                  \
357
358 /**
359  * GstPlayBin2:
360  *
361  * playbin element structure
362  */
363 struct _GstPlayBin
364 {
365   GstPipeline parent;
366
367   GStaticRecMutex lock;         /* to protect group switching */
368
369   /* the groups, we use a double buffer to switch between current and next */
370   GstSourceGroup groups[2];     /* array with group info */
371   GstSourceGroup *curr_group;   /* pointer to the currently playing group */
372   GstSourceGroup *next_group;   /* pointer to the next group */
373
374   /* properties */
375   guint connection_speed;       /* connection speed in bits/sec (0 = unknown) */
376   gint current_video;           /* the currently selected stream */
377   gint current_audio;           /* the currently selected stream */
378   gint current_text;            /* the currently selected stream */
379
380   guint64 buffer_duration;      /* When buffering, the max buffer duration (ns) */
381   guint buffer_size;            /* When buffering, the max buffer size (bytes) */
382
383   /* our play sink */
384   GstPlaySink *playsink;
385
386   /* the last activated source */
387   GstElement *source;
388
389   /* lock protecting dynamic adding/removing */
390   GMutex *dyn_lock;
391   /* if we are shutting down or not */
392   gint shutdown;
393
394   GMutex *elements_lock;
395   guint32 elements_cookie;
396   GList *elements;              /* factories we can use for selecting elements */
397
398   gboolean have_selector;       /* set to FALSE when we fail to create an
399                                  * input-selector, so that we only post a
400                                  * warning once */
401
402   GstElement *audio_sink;       /* configured audio sink, or NULL      */
403   GstElement *video_sink;       /* configured video sink, or NULL      */
404   GstElement *text_sink;        /* configured text sink, or NULL       */
405
406   struct
407   {
408     gboolean valid;
409     GstFormat format;
410     gint64 duration;
411   } duration[5];                /* cached durations */
412
413   guint64 ring_buffer_max_size; /* 0 means disabled */
414 };
415
416 struct _GstPlayBinClass
417 {
418   GstPipelineClass parent_class;
419
420   /* notify app that the current uri finished decoding and it is possible to
421    * queue a new one for gapless playback */
422   void (*about_to_finish) (GstPlayBin * playbin);
423
424   /* notify app that number of audio/video/text streams changed */
425   void (*video_changed) (GstPlayBin * playbin);
426   void (*audio_changed) (GstPlayBin * playbin);
427   void (*text_changed) (GstPlayBin * playbin);
428
429   /* notify app that the tags of audio/video/text streams changed */
430   void (*video_tags_changed) (GstPlayBin * playbin, gint stream);
431   void (*audio_tags_changed) (GstPlayBin * playbin, gint stream);
432   void (*text_tags_changed) (GstPlayBin * playbin, gint stream);
433
434   /* get audio/video/text tags for a stream */
435   GstTagList *(*get_video_tags) (GstPlayBin * playbin, gint stream);
436   GstTagList *(*get_audio_tags) (GstPlayBin * playbin, gint stream);
437   GstTagList *(*get_text_tags) (GstPlayBin * playbin, gint stream);
438
439   /* get the last video frame and convert it to the given caps */
440   GstBuffer *(*convert_frame) (GstPlayBin * playbin, GstCaps * caps);
441
442   /* get audio/video/text pad for a stream */
443   GstPad *(*get_video_pad) (GstPlayBin * playbin, gint stream);
444   GstPad *(*get_audio_pad) (GstPlayBin * playbin, gint stream);
445   GstPad *(*get_text_pad) (GstPlayBin * playbin, gint stream);
446 };
447
448 /* props */
449 #define DEFAULT_URI               NULL
450 #define DEFAULT_SUBURI            NULL
451 #define DEFAULT_SOURCE            NULL
452 #define DEFAULT_FLAGS             GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_TEXT | \
453                                   GST_PLAY_FLAG_SOFT_VOLUME
454 #define DEFAULT_N_VIDEO           0
455 #define DEFAULT_CURRENT_VIDEO     -1
456 #define DEFAULT_N_AUDIO           0
457 #define DEFAULT_CURRENT_AUDIO     -1
458 #define DEFAULT_N_TEXT            0
459 #define DEFAULT_CURRENT_TEXT      -1
460 #define DEFAULT_SUBTITLE_ENCODING NULL
461 #define DEFAULT_AUDIO_SINK        NULL
462 #define DEFAULT_VIDEO_SINK        NULL
463 #define DEFAULT_VIS_PLUGIN        NULL
464 #define DEFAULT_TEXT_SINK         NULL
465 #define DEFAULT_VOLUME            1.0
466 #define DEFAULT_MUTE              FALSE
467 #define DEFAULT_FRAME             NULL
468 #define DEFAULT_FONT_DESC         NULL
469 #define DEFAULT_CONNECTION_SPEED  0
470 #define DEFAULT_BUFFER_DURATION   -1
471 #define DEFAULT_BUFFER_SIZE       -1
472 #define DEFAULT_RING_BUFFER_MAX_SIZE 0
473
474 enum
475 {
476   PROP_0,
477   PROP_URI,
478   PROP_SUBURI,
479   PROP_SOURCE,
480   PROP_FLAGS,
481   PROP_N_VIDEO,
482   PROP_CURRENT_VIDEO,
483   PROP_N_AUDIO,
484   PROP_CURRENT_AUDIO,
485   PROP_N_TEXT,
486   PROP_CURRENT_TEXT,
487   PROP_SUBTITLE_ENCODING,
488   PROP_AUDIO_SINK,
489   PROP_VIDEO_SINK,
490   PROP_VIS_PLUGIN,
491   PROP_TEXT_SINK,
492   PROP_VOLUME,
493   PROP_MUTE,
494   PROP_FRAME,
495   PROP_FONT_DESC,
496   PROP_CONNECTION_SPEED,
497   PROP_BUFFER_SIZE,
498   PROP_BUFFER_DURATION,
499   PROP_AV_OFFSET,
500   PROP_RING_BUFFER_MAX_SIZE,
501   PROP_LAST
502 };
503
504 /* signals */
505 enum
506 {
507   SIGNAL_ABOUT_TO_FINISH,
508   SIGNAL_CONVERT_FRAME,
509   SIGNAL_VIDEO_CHANGED,
510   SIGNAL_AUDIO_CHANGED,
511   SIGNAL_TEXT_CHANGED,
512   SIGNAL_VIDEO_TAGS_CHANGED,
513   SIGNAL_AUDIO_TAGS_CHANGED,
514   SIGNAL_TEXT_TAGS_CHANGED,
515   SIGNAL_GET_VIDEO_TAGS,
516   SIGNAL_GET_AUDIO_TAGS,
517   SIGNAL_GET_TEXT_TAGS,
518   SIGNAL_GET_VIDEO_PAD,
519   SIGNAL_GET_AUDIO_PAD,
520   SIGNAL_GET_TEXT_PAD,
521   SIGNAL_SOURCE_SETUP,
522   LAST_SIGNAL
523 };
524
525 static void gst_play_bin_class_init (GstPlayBinClass * klass);
526 static void gst_play_bin_init (GstPlayBin * playbin);
527 static void gst_play_bin_finalize (GObject * object);
528
529 static void gst_play_bin_set_property (GObject * object, guint prop_id,
530     const GValue * value, GParamSpec * spec);
531 static void gst_play_bin_get_property (GObject * object, guint prop_id,
532     GValue * value, GParamSpec * spec);
533
534 static GstStateChangeReturn gst_play_bin_change_state (GstElement * element,
535     GstStateChange transition);
536
537 static void gst_play_bin_handle_message (GstBin * bin, GstMessage * message);
538 static gboolean gst_play_bin_query (GstElement * element, GstQuery * query);
539
540 static GstTagList *gst_play_bin_get_video_tags (GstPlayBin * playbin,
541     gint stream);
542 static GstTagList *gst_play_bin_get_audio_tags (GstPlayBin * playbin,
543     gint stream);
544 static GstTagList *gst_play_bin_get_text_tags (GstPlayBin * playbin,
545     gint stream);
546
547 static GstBuffer *gst_play_bin_convert_frame (GstPlayBin * playbin,
548     GstCaps * caps);
549
550 static GstPad *gst_play_bin_get_video_pad (GstPlayBin * playbin, gint stream);
551 static GstPad *gst_play_bin_get_audio_pad (GstPlayBin * playbin, gint stream);
552 static GstPad *gst_play_bin_get_text_pad (GstPlayBin * playbin, gint stream);
553
554 static gboolean setup_next_source (GstPlayBin * playbin, GstState target);
555
556 static void no_more_pads_cb (GstElement * decodebin, GstSourceGroup * group);
557 static void pad_removed_cb (GstElement * decodebin, GstPad * pad,
558     GstSourceGroup * group);
559
560 static void gst_play_bin_suburidecodebin_block (GstElement * suburidecodebin,
561     gboolean block);
562 static void gst_play_bin_suburidecodebin_seek_to_start (GstElement *
563     suburidecodebin);
564
565 static GstElementClass *parent_class;
566
567 static guint gst_play_bin_signals[LAST_SIGNAL] = { 0 };
568
569 #define REMOVE_SIGNAL(obj,id)            \
570 if (id) {                                \
571   g_signal_handler_disconnect (obj, id); \
572   id = 0;                                \
573 }
574
575 static GType
576 gst_play_bin_get_type (void)
577 {
578   static GType gst_play_bin_type = 0;
579
580   if (!gst_play_bin_type) {
581     static const GTypeInfo gst_play_bin_info = {
582       sizeof (GstPlayBinClass),
583       NULL,
584       NULL,
585       (GClassInitFunc) gst_play_bin_class_init,
586       NULL,
587       NULL,
588       sizeof (GstPlayBin),
589       0,
590       (GInstanceInitFunc) gst_play_bin_init,
591       NULL
592     };
593     static const GInterfaceInfo svol_info = {
594       NULL, NULL, NULL
595     };
596
597     gst_play_bin_type = g_type_register_static (GST_TYPE_PIPELINE,
598         "GstPlayBin2", &gst_play_bin_info, 0);
599
600     g_type_add_interface_static (gst_play_bin_type, GST_TYPE_STREAM_VOLUME,
601         &svol_info);
602   }
603
604   return gst_play_bin_type;
605 }
606
607 static void
608 gst_play_bin_class_init (GstPlayBinClass * klass)
609 {
610   GObjectClass *gobject_klass;
611   GstElementClass *gstelement_klass;
612   GstBinClass *gstbin_klass;
613
614   gobject_klass = (GObjectClass *) klass;
615   gstelement_klass = (GstElementClass *) klass;
616   gstbin_klass = (GstBinClass *) klass;
617
618   parent_class = g_type_class_peek_parent (klass);
619
620   gobject_klass->set_property = gst_play_bin_set_property;
621   gobject_klass->get_property = gst_play_bin_get_property;
622
623   gobject_klass->finalize = gst_play_bin_finalize;
624
625   /**
626    * GstPlayBin2:uri
627    *
628    * Set the next URI that playbin will play. This property can be set from the
629    * about-to-finish signal to queue the next media file.
630    */
631   g_object_class_install_property (gobject_klass, PROP_URI,
632       g_param_spec_string ("uri", "URI", "URI of the media to play",
633           NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
634
635   /**
636    * GstPlayBin2:suburi
637    *
638    * Set the next subtitle URI that playbin will play. This property can be
639    * set from the about-to-finish signal to queue the next subtitle media file.
640    */
641   g_object_class_install_property (gobject_klass, PROP_SUBURI,
642       g_param_spec_string ("suburi", ".sub-URI", "Optional URI of a subtitle",
643           NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
644
645   g_object_class_install_property (gobject_klass, PROP_SOURCE,
646       g_param_spec_object ("source", "Source", "Source element",
647           GST_TYPE_ELEMENT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
648
649   /**
650    * GstPlayBin2:flags
651    *
652    * Control the behaviour of playbin.
653    */
654   g_object_class_install_property (gobject_klass, PROP_FLAGS,
655       g_param_spec_flags ("flags", "Flags", "Flags to control behaviour",
656           GST_TYPE_PLAY_FLAGS, DEFAULT_FLAGS,
657           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
658
659   /**
660    * GstPlayBin2:n-video
661    *
662    * Get the total number of available video streams.
663    */
664   g_object_class_install_property (gobject_klass, PROP_N_VIDEO,
665       g_param_spec_int ("n-video", "Number Video",
666           "Total number of video streams", 0, G_MAXINT, 0,
667           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
668   /**
669    * GstPlayBin2:current-video
670    *
671    * Get or set the currently playing video stream. By default the first video
672    * stream with data is played.
673    */
674   g_object_class_install_property (gobject_klass, PROP_CURRENT_VIDEO,
675       g_param_spec_int ("current-video", "Current Video",
676           "Currently playing video stream (-1 = auto)",
677           -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
678   /**
679    * GstPlayBin2:n-audio
680    *
681    * Get the total number of available audio streams.
682    */
683   g_object_class_install_property (gobject_klass, PROP_N_AUDIO,
684       g_param_spec_int ("n-audio", "Number Audio",
685           "Total number of audio streams", 0, G_MAXINT, 0,
686           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
687   /**
688    * GstPlayBin2:current-audio
689    *
690    * Get or set the currently playing audio stream. By default the first audio
691    * stream with data is played.
692    */
693   g_object_class_install_property (gobject_klass, PROP_CURRENT_AUDIO,
694       g_param_spec_int ("current-audio", "Current audio",
695           "Currently playing audio stream (-1 = auto)",
696           -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
697   /**
698    * GstPlayBin2:n-text
699    *
700    * Get the total number of available subtitle streams.
701    */
702   g_object_class_install_property (gobject_klass, PROP_N_TEXT,
703       g_param_spec_int ("n-text", "Number Text",
704           "Total number of text streams", 0, G_MAXINT, 0,
705           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
706   /**
707    * GstPlayBin2:current-text:
708    *
709    * Get or set the currently playing subtitle stream. By default the first
710    * subtitle stream with data is played.
711    */
712   g_object_class_install_property (gobject_klass, PROP_CURRENT_TEXT,
713       g_param_spec_int ("current-text", "Current Text",
714           "Currently playing text stream (-1 = auto)",
715           -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
716
717   g_object_class_install_property (gobject_klass, PROP_SUBTITLE_ENCODING,
718       g_param_spec_string ("subtitle-encoding", "subtitle encoding",
719           "Encoding to assume if input subtitles are not in UTF-8 encoding. "
720           "If not set, the GST_SUBTITLE_ENCODING environment variable will "
721           "be checked for an encoding to use. If that is not set either, "
722           "ISO-8859-15 will be assumed.", NULL,
723           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
724
725   g_object_class_install_property (gobject_klass, PROP_VIDEO_SINK,
726       g_param_spec_object ("video-sink", "Video Sink",
727           "the video output element to use (NULL = default sink)",
728           GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
729   g_object_class_install_property (gobject_klass, PROP_AUDIO_SINK,
730       g_param_spec_object ("audio-sink", "Audio Sink",
731           "the audio output element to use (NULL = default sink)",
732           GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
733   g_object_class_install_property (gobject_klass, PROP_VIS_PLUGIN,
734       g_param_spec_object ("vis-plugin", "Vis plugin",
735           "the visualization element to use (NULL = default)",
736           GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
737   g_object_class_install_property (gobject_klass, PROP_TEXT_SINK,
738       g_param_spec_object ("text-sink", "Text plugin",
739           "the text output element to use (NULL = default textoverlay)",
740           GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
741
742   /**
743    * GstPlayBin2:volume:
744    *
745    * Get or set the current audio stream volume. 1.0 means 100%,
746    * 0.0 means mute. This uses a linear volume scale.
747    *
748    */
749   g_object_class_install_property (gobject_klass, PROP_VOLUME,
750       g_param_spec_double ("volume", "Volume", "The audio volume, 1.0=100%",
751           0.0, VOLUME_MAX_DOUBLE, 1.0,
752           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
753   g_object_class_install_property (gobject_klass, PROP_MUTE,
754       g_param_spec_boolean ("mute", "Mute",
755           "Mute the audio channel without changing the volume", FALSE,
756           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
757
758   /**
759    * GstPlayBin2:frame:
760    * @playbin: a #GstPlayBin2
761    *
762    * Get the currently rendered or prerolled frame in the video sink.
763    * The #GstCaps on the buffer will describe the format of the buffer.
764    */
765   g_object_class_install_property (gobject_klass, PROP_FRAME,
766       g_param_spec_boxed ("frame", "Frame",
767           "The last frame (NULL = no video available)",
768           GST_TYPE_BUFFER, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
769   g_object_class_install_property (gobject_klass, PROP_FONT_DESC,
770       g_param_spec_string ("subtitle-font-desc",
771           "Subtitle font description",
772           "Pango font description of font "
773           "to be used for subtitle rendering", NULL,
774           G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
775
776   g_object_class_install_property (gobject_klass, PROP_CONNECTION_SPEED,
777       g_param_spec_uint ("connection-speed", "Connection Speed",
778           "Network connection speed in kbps (0 = unknown)",
779           0, G_MAXUINT / 1000, DEFAULT_CONNECTION_SPEED,
780           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
781
782   g_object_class_install_property (gobject_klass, PROP_BUFFER_SIZE,
783       g_param_spec_int ("buffer-size", "Buffer size (bytes)",
784           "Buffer size when buffering network streams",
785           -1, G_MAXINT, DEFAULT_BUFFER_SIZE,
786           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
787   g_object_class_install_property (gobject_klass, PROP_BUFFER_DURATION,
788       g_param_spec_int64 ("buffer-duration", "Buffer duration (ns)",
789           "Buffer duration when buffering network streams",
790           -1, G_MAXINT64, DEFAULT_BUFFER_DURATION,
791           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
792   /**
793    * GstPlayBin2:av-offset:
794    *
795    * Control the synchronisation offset between the audio and video streams.
796    * Positive values make the audio ahead of the video and negative values make
797    * the audio go behind the video.
798    *
799    * Since: 0.10.30
800    */
801   g_object_class_install_property (gobject_klass, PROP_AV_OFFSET,
802       g_param_spec_int64 ("av-offset", "AV Offset",
803           "The synchronisation offset between audio and video in nanoseconds",
804           G_MININT64, G_MAXINT64, 0,
805           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
806
807   /**
808    * GstQueue2:ring-buffer-max-size
809    *
810    * The maximum size of the ring buffer in bytes. If set to 0, the ring
811    * buffer is disabled. Default 0.
812    *
813    * Since: 0.10.31
814    */
815   g_object_class_install_property (gobject_klass, PROP_RING_BUFFER_MAX_SIZE,
816       g_param_spec_uint64 ("ring-buffer-max-size",
817           "Max. ring buffer size (bytes)",
818           "Max. amount of data in the ring buffer (bytes, 0 = ring buffer disabled)",
819           0, G_MAXUINT, DEFAULT_RING_BUFFER_MAX_SIZE,
820           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
821
822   /**
823    * GstPlayBin2::about-to-finish
824    * @playbin: a #GstPlayBin2
825    *
826    * This signal is emitted when the current uri is about to finish. You can
827    * set the uri and suburi to make sure that playback continues.
828    */
829   gst_play_bin_signals[SIGNAL_ABOUT_TO_FINISH] =
830       g_signal_new ("about-to-finish", G_TYPE_FROM_CLASS (klass),
831       G_SIGNAL_RUN_LAST,
832       G_STRUCT_OFFSET (GstPlayBinClass, about_to_finish), NULL, NULL,
833       gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
834
835   /**
836    * GstPlayBin2::video-changed
837    * @playbin: a #GstPlayBin2
838    *
839    * This signal is emitted whenever the number or order of the video
840    * streams has changed. The application will most likely want to select
841    * a new video stream.
842    */
843   gst_play_bin_signals[SIGNAL_VIDEO_CHANGED] =
844       g_signal_new ("video-changed", G_TYPE_FROM_CLASS (klass),
845       G_SIGNAL_RUN_LAST,
846       G_STRUCT_OFFSET (GstPlayBinClass, video_changed), NULL, NULL,
847       gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
848   /**
849    * GstPlayBin2::audio-changed
850    * @playbin: a #GstPlayBin2
851    *
852    * This signal is emitted whenever the number or order of the audio
853    * streams has changed. The application will most likely want to select
854    * a new audio stream.
855    */
856   gst_play_bin_signals[SIGNAL_AUDIO_CHANGED] =
857       g_signal_new ("audio-changed", G_TYPE_FROM_CLASS (klass),
858       G_SIGNAL_RUN_LAST,
859       G_STRUCT_OFFSET (GstPlayBinClass, audio_changed), NULL, NULL,
860       gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
861   /**
862    * GstPlayBin2::text-changed
863    * @playbin: a #GstPlayBin2
864    *
865    * This signal is emitted whenever the number or order of the text
866    * streams has changed. The application will most likely want to select
867    * a new text stream.
868    */
869   gst_play_bin_signals[SIGNAL_TEXT_CHANGED] =
870       g_signal_new ("text-changed", G_TYPE_FROM_CLASS (klass),
871       G_SIGNAL_RUN_LAST,
872       G_STRUCT_OFFSET (GstPlayBinClass, text_changed), NULL, NULL,
873       gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
874
875   /**
876    * GstPlayBin2::video-tags-changed
877    * @playbin: a #GstPlayBin2
878    * @stream: stream index with changed tags
879    *
880    * This signal is emitted whenever the tags of a video stream have changed.
881    * The application will most likely want to get the new tags.
882    *
883    * Since: 0.10.24
884    */
885   gst_play_bin_signals[SIGNAL_VIDEO_TAGS_CHANGED] =
886       g_signal_new ("video-tags-changed", G_TYPE_FROM_CLASS (klass),
887       G_SIGNAL_RUN_LAST,
888       G_STRUCT_OFFSET (GstPlayBinClass, video_tags_changed), NULL, NULL,
889       gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
890
891   /**
892    * GstPlayBin2::audio-tags-changed
893    * @playbin: a #GstPlayBin2
894    * @stream: stream index with changed tags
895    *
896    * This signal is emitted whenever the tags of an audio stream have changed.
897    * The application will most likely want to get the new tags.
898    *
899    * Since: 0.10.24
900    */
901   gst_play_bin_signals[SIGNAL_AUDIO_TAGS_CHANGED] =
902       g_signal_new ("audio-tags-changed", G_TYPE_FROM_CLASS (klass),
903       G_SIGNAL_RUN_LAST,
904       G_STRUCT_OFFSET (GstPlayBinClass, audio_tags_changed), NULL, NULL,
905       gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
906
907   /**
908    * GstPlayBin2::text-tags-changed
909    * @playbin: a #GstPlayBin2
910    * @stream: stream index with changed tags
911    *
912    * This signal is emitted whenever the tags of a text stream have changed.
913    * The application will most likely want to get the new tags.
914    *
915    * Since: 0.10.24
916    */
917   gst_play_bin_signals[SIGNAL_TEXT_TAGS_CHANGED] =
918       g_signal_new ("text-tags-changed", G_TYPE_FROM_CLASS (klass),
919       G_SIGNAL_RUN_LAST,
920       G_STRUCT_OFFSET (GstPlayBinClass, text_tags_changed), NULL, NULL,
921       gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
922
923   /**
924    * GstPlayBin2::source-setup:
925    * @playbin: a #GstPlayBin2
926    * @source: source element
927    *
928    * This signal is emitted after the source element has been created, so
929    * it can be configured by setting additional properties (e.g. set a
930    * proxy server for an http source, or set the device and read speed for
931    * an audio cd source). This is functionally equivalent to connecting to
932    * the notify::source signal, but more convenient.
933    *
934    * Since: 0.10.33
935    */
936   gst_play_bin_signals[SIGNAL_SOURCE_SETUP] =
937       g_signal_new ("source-setup", G_TYPE_FROM_CLASS (klass),
938       G_SIGNAL_RUN_LAST, 0, NULL, NULL,
939       gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT);
940
941   /**
942    * GstPlayBin2::get-video-tags
943    * @playbin: a #GstPlayBin2
944    * @stream: a video stream number
945    *
946    * Action signal to retrieve the tags of a specific video stream number.
947    * This information can be used to select a stream.
948    *
949    * Returns: a GstTagList with tags or NULL when the stream number does not
950    * exist.
951    */
952   gst_play_bin_signals[SIGNAL_GET_VIDEO_TAGS] =
953       g_signal_new ("get-video-tags", G_TYPE_FROM_CLASS (klass),
954       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
955       G_STRUCT_OFFSET (GstPlayBinClass, get_video_tags), NULL, NULL,
956       gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
957   /**
958    * GstPlayBin2::get-audio-tags
959    * @playbin: a #GstPlayBin2
960    * @stream: an audio stream number
961    *
962    * Action signal to retrieve the tags of a specific audio stream number.
963    * This information can be used to select a stream.
964    *
965    * Returns: a GstTagList with tags or NULL when the stream number does not
966    * exist.
967    */
968   gst_play_bin_signals[SIGNAL_GET_AUDIO_TAGS] =
969       g_signal_new ("get-audio-tags", G_TYPE_FROM_CLASS (klass),
970       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
971       G_STRUCT_OFFSET (GstPlayBinClass, get_audio_tags), NULL, NULL,
972       gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
973   /**
974    * GstPlayBin2::get-text-tags
975    * @playbin: a #GstPlayBin2
976    * @stream: a text stream number
977    *
978    * Action signal to retrieve the tags of a specific text stream number.
979    * This information can be used to select a stream.
980    *
981    * Returns: a GstTagList with tags or NULL when the stream number does not
982    * exist.
983    */
984   gst_play_bin_signals[SIGNAL_GET_TEXT_TAGS] =
985       g_signal_new ("get-text-tags", G_TYPE_FROM_CLASS (klass),
986       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
987       G_STRUCT_OFFSET (GstPlayBinClass, get_text_tags), NULL, NULL,
988       gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
989   /**
990    * GstPlayBin2::convert-frame
991    * @playbin: a #GstPlayBin2
992    * @caps: the target format of the frame
993    *
994    * Action signal to retrieve the currently playing video frame in the format
995    * specified by @caps.
996    * If @caps is %NULL, no conversion will be performed and this function is
997    * equivalent to the #GstPlayBin::frame property.
998    *
999    * Returns: a #GstBuffer of the current video frame converted to #caps.
1000    * The caps on the buffer will describe the final layout of the buffer data.
1001    * %NULL is returned when no current buffer can be retrieved or when the
1002    * conversion failed.
1003    */
1004   gst_play_bin_signals[SIGNAL_CONVERT_FRAME] =
1005       g_signal_new ("convert-frame", G_TYPE_FROM_CLASS (klass),
1006       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1007       G_STRUCT_OFFSET (GstPlayBinClass, convert_frame), NULL, NULL,
1008       gst_play_marshal_BUFFER__BOXED, GST_TYPE_BUFFER, 1, GST_TYPE_CAPS);
1009
1010   /**
1011    * GstPlayBin2::get-video-pad
1012    * @playbin: a #GstPlayBin2
1013    * @stream: a video stream number
1014    *
1015    * Action signal to retrieve the stream-selector sinkpad for a specific
1016    * video stream.
1017    * This pad can be used for notifications of caps changes, stream-specific
1018    * queries, etc.
1019    *
1020    * Returns: a #GstPad, or NULL when the stream number does not exist.
1021    */
1022   gst_play_bin_signals[SIGNAL_GET_VIDEO_PAD] =
1023       g_signal_new ("get-video-pad", G_TYPE_FROM_CLASS (klass),
1024       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1025       G_STRUCT_OFFSET (GstPlayBinClass, get_video_pad), NULL, NULL,
1026       gst_play_marshal_OBJECT__INT, GST_TYPE_PAD, 1, G_TYPE_INT);
1027   /**
1028    * GstPlayBin2::get-audio-pad
1029    * @playbin: a #GstPlayBin2
1030    * @stream: an audio stream number
1031    *
1032    * Action signal to retrieve the stream-selector sinkpad for a specific
1033    * audio stream.
1034    * This pad can be used for notifications of caps changes, stream-specific
1035    * queries, etc.
1036    *
1037    * Returns: a #GstPad, or NULL when the stream number does not exist.
1038    */
1039   gst_play_bin_signals[SIGNAL_GET_AUDIO_PAD] =
1040       g_signal_new ("get-audio-pad", G_TYPE_FROM_CLASS (klass),
1041       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1042       G_STRUCT_OFFSET (GstPlayBinClass, get_audio_pad), NULL, NULL,
1043       gst_play_marshal_OBJECT__INT, GST_TYPE_PAD, 1, G_TYPE_INT);
1044   /**
1045    * GstPlayBin2::get-text-pad
1046    * @playbin: a #GstPlayBin2
1047    * @stream: a text stream number
1048    *
1049    * Action signal to retrieve the stream-selector sinkpad for a specific
1050    * text stream.
1051    * This pad can be used for notifications of caps changes, stream-specific
1052    * queries, etc.
1053    *
1054    * Returns: a #GstPad, or NULL when the stream number does not exist.
1055    */
1056   gst_play_bin_signals[SIGNAL_GET_TEXT_PAD] =
1057       g_signal_new ("get-text-pad", G_TYPE_FROM_CLASS (klass),
1058       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
1059       G_STRUCT_OFFSET (GstPlayBinClass, get_text_pad), NULL, NULL,
1060       gst_play_marshal_OBJECT__INT, GST_TYPE_PAD, 1, G_TYPE_INT);
1061
1062   klass->get_video_tags = gst_play_bin_get_video_tags;
1063   klass->get_audio_tags = gst_play_bin_get_audio_tags;
1064   klass->get_text_tags = gst_play_bin_get_text_tags;
1065
1066   klass->convert_frame = gst_play_bin_convert_frame;
1067
1068   klass->get_video_pad = gst_play_bin_get_video_pad;
1069   klass->get_audio_pad = gst_play_bin_get_audio_pad;
1070   klass->get_text_pad = gst_play_bin_get_text_pad;
1071
1072   gst_element_class_set_details_simple (gstelement_klass,
1073       "Player Bin 2", "Generic/Bin/Player",
1074       "Autoplug and play media from an uri",
1075       "Wim Taymans <wim.taymans@gmail.com>");
1076
1077   gstelement_klass->change_state =
1078       GST_DEBUG_FUNCPTR (gst_play_bin_change_state);
1079   gstelement_klass->query = GST_DEBUG_FUNCPTR (gst_play_bin_query);
1080
1081   gstbin_klass->handle_message =
1082       GST_DEBUG_FUNCPTR (gst_play_bin_handle_message);
1083 }
1084
1085 static void
1086 init_group (GstPlayBin * playbin, GstSourceGroup * group)
1087 {
1088   int n;
1089
1090   /* store the array for the different channels */
1091   group->video_channels = g_ptr_array_new ();
1092   group->audio_channels = g_ptr_array_new ();
1093   group->text_channels = g_ptr_array_new ();
1094   group->lock = g_mutex_new ();
1095   /* init selectors. The selector is found by finding the first prefix that
1096    * matches the media. */
1097   group->playbin = playbin;
1098   /* If you add any items to these lists, check that media_list[] is defined
1099    * above to be large enough to hold MAX(items)+1, so as to accomodate a
1100    * NULL terminator (set when the memory is zeroed on allocation) */
1101   group->selector[PLAYBIN_STREAM_AUDIO].media_list[0] = "audio/";
1102   group->selector[PLAYBIN_STREAM_AUDIO].type = GST_PLAY_SINK_TYPE_AUDIO;
1103   group->selector[PLAYBIN_STREAM_AUDIO].channels = group->audio_channels;
1104   group->selector[PLAYBIN_STREAM_VIDEO].media_list[0] = "video/";
1105   group->selector[PLAYBIN_STREAM_VIDEO].type = GST_PLAY_SINK_TYPE_VIDEO;
1106   group->selector[PLAYBIN_STREAM_VIDEO].channels = group->video_channels;
1107   group->selector[PLAYBIN_STREAM_TEXT].media_list[0] = "text/";
1108   group->selector[PLAYBIN_STREAM_TEXT].media_list[1] = "application/x-subtitle";
1109   group->selector[PLAYBIN_STREAM_TEXT].media_list[2] = "application/x-ssa";
1110   group->selector[PLAYBIN_STREAM_TEXT].media_list[3] = "application/x-ass";
1111   group->selector[PLAYBIN_STREAM_TEXT].media_list[4] = "video/x-dvd-subpicture";
1112   group->selector[PLAYBIN_STREAM_TEXT].media_list[5] = "subpicture/";
1113   group->selector[PLAYBIN_STREAM_TEXT].media_list[6] = "subtitle/";
1114   group->selector[PLAYBIN_STREAM_TEXT].get_media_caps =
1115       gst_subtitle_overlay_create_factory_caps;
1116   group->selector[PLAYBIN_STREAM_TEXT].type = GST_PLAY_SINK_TYPE_TEXT;
1117   group->selector[PLAYBIN_STREAM_TEXT].channels = group->text_channels;
1118
1119   for (n = 0; n < PLAYBIN_STREAM_LAST; n++) {
1120     GstSourceSelect *select = &group->selector[n];
1121     select->sinkpad_delayed_event = NULL;
1122     select->sinkpad_data_probe = 0;
1123   }
1124 }
1125
1126 static void
1127 free_group (GstPlayBin * playbin, GstSourceGroup * group)
1128 {
1129   int n;
1130
1131   for (n = 0; n < PLAYBIN_STREAM_LAST; n++) {
1132     GstSourceSelect *select = &group->selector[n];
1133     if (select->sinkpad && select->sinkpad_data_probe)
1134       gst_pad_remove_data_probe (select->sinkpad, select->sinkpad_data_probe);
1135     if (select->sinkpad_delayed_event)
1136       gst_event_unref (select->sinkpad_delayed_event);
1137   }
1138
1139   g_free (group->uri);
1140   g_free (group->suburi);
1141   g_ptr_array_free (group->video_channels, TRUE);
1142   g_ptr_array_free (group->audio_channels, TRUE);
1143   g_ptr_array_free (group->text_channels, TRUE);
1144
1145   g_mutex_free (group->lock);
1146   if (group->audio_sink) {
1147     if (group->audio_sink != playbin->audio_sink)
1148       gst_element_set_state (group->audio_sink, GST_STATE_NULL);
1149     gst_object_unref (group->audio_sink);
1150   }
1151   group->audio_sink = NULL;
1152   if (group->video_sink) {
1153     if (group->video_sink != playbin->video_sink)
1154       gst_element_set_state (group->video_sink, GST_STATE_NULL);
1155     gst_object_unref (group->video_sink);
1156   }
1157   group->video_sink = NULL;
1158
1159   g_list_free (group->stream_changed_pending);
1160   group->stream_changed_pending = NULL;
1161
1162   if (group->stream_changed_pending_lock)
1163     g_mutex_free (group->stream_changed_pending_lock);
1164   group->stream_changed_pending_lock = NULL;
1165 }
1166
1167 static void
1168 notify_volume_cb (GObject * selector, GParamSpec * pspec, GstPlayBin * playbin)
1169 {
1170   g_object_notify (G_OBJECT (playbin), "volume");
1171 }
1172
1173 static void
1174 notify_mute_cb (GObject * selector, GParamSpec * pspec, GstPlayBin * playbin)
1175 {
1176   g_object_notify (G_OBJECT (playbin), "mute");
1177 }
1178
1179 /* Must be called with elements lock! */
1180 static void
1181 gst_play_bin_update_elements_list (GstPlayBin * playbin)
1182 {
1183   GList *res, *tmp;
1184
1185   if (!playbin->elements ||
1186       playbin->elements_cookie !=
1187       gst_default_registry_get_feature_list_cookie ()) {
1188     if (playbin->elements)
1189       gst_plugin_feature_list_free (playbin->elements);
1190     res =
1191         gst_element_factory_list_get_elements
1192         (GST_ELEMENT_FACTORY_TYPE_DECODABLE, GST_RANK_MARGINAL);
1193     tmp =
1194         gst_element_factory_list_get_elements
1195         (GST_ELEMENT_FACTORY_TYPE_AUDIOVIDEO_SINKS, GST_RANK_MARGINAL);
1196     playbin->elements = g_list_concat (res, tmp);
1197     playbin->elements =
1198         g_list_sort (playbin->elements, gst_plugin_feature_rank_compare_func);
1199     playbin->elements_cookie = gst_default_registry_get_feature_list_cookie ();
1200   }
1201 }
1202
1203 static void
1204 gst_play_bin_init (GstPlayBin * playbin)
1205 {
1206   g_static_rec_mutex_init (&playbin->lock);
1207   playbin->dyn_lock = g_mutex_new ();
1208
1209   /* assume we can create a selector */
1210   playbin->have_selector = TRUE;
1211
1212   /* init groups */
1213   playbin->curr_group = &playbin->groups[0];
1214   playbin->next_group = &playbin->groups[1];
1215   init_group (playbin, &playbin->groups[0]);
1216   init_group (playbin, &playbin->groups[1]);
1217
1218   /* first filter out the interesting element factories */
1219   playbin->elements_lock = g_mutex_new ();
1220
1221   /* add sink */
1222   playbin->playsink = g_object_new (GST_TYPE_PLAY_SINK, NULL);
1223   gst_bin_add (GST_BIN_CAST (playbin), GST_ELEMENT_CAST (playbin->playsink));
1224   gst_play_sink_set_flags (playbin->playsink, DEFAULT_FLAGS);
1225   /* Connect to notify::volume and notify::mute signals for proxying */
1226   g_signal_connect (playbin->playsink, "notify::volume",
1227       G_CALLBACK (notify_volume_cb), playbin);
1228   g_signal_connect (playbin->playsink, "notify::mute",
1229       G_CALLBACK (notify_mute_cb), playbin);
1230
1231   playbin->current_video = DEFAULT_CURRENT_VIDEO;
1232   playbin->current_audio = DEFAULT_CURRENT_AUDIO;
1233   playbin->current_text = DEFAULT_CURRENT_TEXT;
1234
1235   playbin->buffer_duration = DEFAULT_BUFFER_DURATION;
1236   playbin->buffer_size = DEFAULT_BUFFER_SIZE;
1237   playbin->ring_buffer_max_size = DEFAULT_RING_BUFFER_MAX_SIZE;
1238 }
1239
1240 static void
1241 gst_play_bin_finalize (GObject * object)
1242 {
1243   GstPlayBin *playbin;
1244
1245   playbin = GST_PLAY_BIN (object);
1246
1247   free_group (playbin, &playbin->groups[0]);
1248   free_group (playbin, &playbin->groups[1]);
1249
1250   if (playbin->source)
1251     gst_object_unref (playbin->source);
1252   if (playbin->video_sink) {
1253     gst_element_set_state (playbin->video_sink, GST_STATE_NULL);
1254     gst_object_unref (playbin->video_sink);
1255   }
1256   if (playbin->audio_sink) {
1257     gst_element_set_state (playbin->audio_sink, GST_STATE_NULL);
1258     gst_object_unref (playbin->audio_sink);
1259   }
1260   if (playbin->text_sink) {
1261     gst_element_set_state (playbin->text_sink, GST_STATE_NULL);
1262     gst_object_unref (playbin->text_sink);
1263   }
1264
1265   if (playbin->elements)
1266     gst_plugin_feature_list_free (playbin->elements);
1267
1268   g_static_rec_mutex_free (&playbin->lock);
1269   g_mutex_free (playbin->dyn_lock);
1270   g_mutex_free (playbin->elements_lock);
1271
1272   G_OBJECT_CLASS (parent_class)->finalize (object);
1273 }
1274
1275 static void
1276 gst_play_bin_set_uri (GstPlayBin * playbin, const gchar * uri)
1277 {
1278   GstSourceGroup *group;
1279
1280   if (uri == NULL) {
1281     g_warning ("cannot set NULL uri");
1282     return;
1283   }
1284
1285   GST_PLAY_BIN_LOCK (playbin);
1286   group = playbin->next_group;
1287
1288   GST_SOURCE_GROUP_LOCK (group);
1289   /* store the uri in the next group we will play */
1290   g_free (group->uri);
1291   group->uri = g_strdup (uri);
1292   group->valid = TRUE;
1293   GST_SOURCE_GROUP_UNLOCK (group);
1294
1295   GST_DEBUG ("set new uri to %s", uri);
1296   GST_PLAY_BIN_UNLOCK (playbin);
1297 }
1298
1299 static void
1300 gst_play_bin_set_suburi (GstPlayBin * playbin, const gchar * suburi)
1301 {
1302   GstSourceGroup *group;
1303
1304   GST_PLAY_BIN_LOCK (playbin);
1305   group = playbin->next_group;
1306
1307   GST_SOURCE_GROUP_LOCK (group);
1308   g_free (group->suburi);
1309   group->suburi = g_strdup (suburi);
1310   GST_SOURCE_GROUP_UNLOCK (group);
1311
1312   GST_DEBUG ("setting new .sub uri to %s", suburi);
1313
1314   GST_PLAY_BIN_UNLOCK (playbin);
1315 }
1316
1317 static void
1318 gst_play_bin_set_flags (GstPlayBin * playbin, GstPlayFlags flags)
1319 {
1320   gst_play_sink_set_flags (playbin->playsink, flags);
1321   gst_play_sink_reconfigure (playbin->playsink);
1322 }
1323
1324 static GstPlayFlags
1325 gst_play_bin_get_flags (GstPlayBin * playbin)
1326 {
1327   GstPlayFlags flags;
1328
1329   flags = gst_play_sink_get_flags (playbin->playsink);
1330
1331   return flags;
1332 }
1333
1334 /* get the currently playing group or if nothing is playing, the next
1335  * group. Must be called with the PLAY_BIN_LOCK. */
1336 static GstSourceGroup *
1337 get_group (GstPlayBin * playbin)
1338 {
1339   GstSourceGroup *result;
1340
1341   if (!(result = playbin->curr_group))
1342     result = playbin->next_group;
1343
1344   return result;
1345 }
1346
1347 static GstPad *
1348 gst_play_bin_get_video_pad (GstPlayBin * playbin, gint stream)
1349 {
1350   GstPad *sinkpad = NULL;
1351   GstSourceGroup *group;
1352
1353   GST_PLAY_BIN_LOCK (playbin);
1354   group = get_group (playbin);
1355   if (stream < group->video_channels->len) {
1356     sinkpad = g_ptr_array_index (group->video_channels, stream);
1357     gst_object_ref (sinkpad);
1358   }
1359   GST_PLAY_BIN_UNLOCK (playbin);
1360
1361   return sinkpad;
1362 }
1363
1364 static GstPad *
1365 gst_play_bin_get_audio_pad (GstPlayBin * playbin, gint stream)
1366 {
1367   GstPad *sinkpad = NULL;
1368   GstSourceGroup *group;
1369
1370   GST_PLAY_BIN_LOCK (playbin);
1371   group = get_group (playbin);
1372   if (stream < group->audio_channels->len) {
1373     sinkpad = g_ptr_array_index (group->audio_channels, stream);
1374     gst_object_ref (sinkpad);
1375   }
1376   GST_PLAY_BIN_UNLOCK (playbin);
1377
1378   return sinkpad;
1379 }
1380
1381 static GstPad *
1382 gst_play_bin_get_text_pad (GstPlayBin * playbin, gint stream)
1383 {
1384   GstPad *sinkpad = NULL;
1385   GstSourceGroup *group;
1386
1387   GST_PLAY_BIN_LOCK (playbin);
1388   group = get_group (playbin);
1389   if (stream < group->text_channels->len) {
1390     sinkpad = g_ptr_array_index (group->text_channels, stream);
1391     gst_object_ref (sinkpad);
1392   }
1393   GST_PLAY_BIN_UNLOCK (playbin);
1394
1395   return sinkpad;
1396 }
1397
1398
1399 static GstTagList *
1400 get_tags (GstPlayBin * playbin, GPtrArray * channels, gint stream)
1401 {
1402   GstTagList *result;
1403   GstPad *sinkpad;
1404
1405   if (!channels || stream >= channels->len)
1406     return NULL;
1407
1408   sinkpad = g_ptr_array_index (channels, stream);
1409   g_object_get (sinkpad, "tags", &result, NULL);
1410
1411   return result;
1412 }
1413
1414 static GstTagList *
1415 gst_play_bin_get_video_tags (GstPlayBin * playbin, gint stream)
1416 {
1417   GstTagList *result;
1418   GstSourceGroup *group;
1419
1420   GST_PLAY_BIN_LOCK (playbin);
1421   group = get_group (playbin);
1422   result = get_tags (playbin, group->video_channels, stream);
1423   GST_PLAY_BIN_UNLOCK (playbin);
1424
1425   return result;
1426 }
1427
1428 static GstTagList *
1429 gst_play_bin_get_audio_tags (GstPlayBin * playbin, gint stream)
1430 {
1431   GstTagList *result;
1432   GstSourceGroup *group;
1433
1434   GST_PLAY_BIN_LOCK (playbin);
1435   group = get_group (playbin);
1436   result = get_tags (playbin, group->audio_channels, stream);
1437   GST_PLAY_BIN_UNLOCK (playbin);
1438
1439   return result;
1440 }
1441
1442 static GstTagList *
1443 gst_play_bin_get_text_tags (GstPlayBin * playbin, gint stream)
1444 {
1445   GstTagList *result;
1446   GstSourceGroup *group;
1447
1448   GST_PLAY_BIN_LOCK (playbin);
1449   group = get_group (playbin);
1450   result = get_tags (playbin, group->text_channels, stream);
1451   GST_PLAY_BIN_UNLOCK (playbin);
1452
1453   return result;
1454 }
1455
1456 static GstBuffer *
1457 gst_play_bin_convert_frame (GstPlayBin * playbin, GstCaps * caps)
1458 {
1459   return gst_play_sink_convert_frame (playbin->playsink, caps);
1460 }
1461
1462 /* Returns current stream number, or -1 if none has been selected yet */
1463 static int
1464 get_current_stream_number (GstPlayBin * playbin, GPtrArray * channels)
1465 {
1466   /* Internal API cleanup would make this easier... */
1467   int i;
1468   GstPad *pad, *current;
1469   GstObject *selector = NULL;
1470   int ret = -1;
1471
1472   for (i = 0; i < channels->len; i++) {
1473     pad = g_ptr_array_index (channels, i);
1474     if ((selector = gst_pad_get_parent (pad))) {
1475       g_object_get (selector, "active-pad", &current, NULL);
1476       gst_object_unref (selector);
1477
1478       if (pad == current) {
1479         gst_object_unref (current);
1480         ret = i;
1481         break;
1482       }
1483
1484       if (current)
1485         gst_object_unref (current);
1486     }
1487   }
1488
1489   return ret;
1490 }
1491
1492 static gboolean
1493 gst_play_bin_set_current_video_stream (GstPlayBin * playbin, gint stream)
1494 {
1495   GstSourceGroup *group;
1496   GPtrArray *channels;
1497   GstPad *sinkpad;
1498
1499   GST_PLAY_BIN_LOCK (playbin);
1500
1501   GST_DEBUG_OBJECT (playbin, "Changing current video stream %d -> %d",
1502       playbin->current_video, stream);
1503
1504   group = get_group (playbin);
1505   if (!(channels = group->video_channels))
1506     goto no_channels;
1507
1508   if (stream == -1 || channels->len <= stream) {
1509     sinkpad = NULL;
1510   } else {
1511     /* take channel from selected stream */
1512     sinkpad = g_ptr_array_index (channels, stream);
1513   }
1514
1515   if (sinkpad)
1516     gst_object_ref (sinkpad);
1517   GST_PLAY_BIN_UNLOCK (playbin);
1518
1519   if (sinkpad) {
1520     GstObject *selector;
1521
1522     if ((selector = gst_pad_get_parent (sinkpad))) {
1523       /* activate the selected pad */
1524       g_object_set (selector, "active-pad", sinkpad, NULL);
1525       gst_object_unref (selector);
1526     }
1527     gst_object_unref (sinkpad);
1528   }
1529   return TRUE;
1530
1531 no_channels:
1532   {
1533     GST_PLAY_BIN_UNLOCK (playbin);
1534     GST_DEBUG_OBJECT (playbin, "can't switch video, we have no channels");
1535     return FALSE;
1536   }
1537 }
1538
1539 static gboolean
1540 gst_play_bin_set_current_audio_stream (GstPlayBin * playbin, gint stream)
1541 {
1542   GstSourceGroup *group;
1543   GPtrArray *channels;
1544   GstPad *sinkpad;
1545
1546   GST_PLAY_BIN_LOCK (playbin);
1547
1548   GST_DEBUG_OBJECT (playbin, "Changing current audio stream %d -> %d",
1549       playbin->current_audio, stream);
1550
1551   group = get_group (playbin);
1552   if (!(channels = group->audio_channels))
1553     goto no_channels;
1554
1555   if (stream == -1 || channels->len <= stream) {
1556     sinkpad = NULL;
1557   } else {
1558     /* take channel from selected stream */
1559     sinkpad = g_ptr_array_index (channels, stream);
1560   }
1561
1562   if (sinkpad)
1563     gst_object_ref (sinkpad);
1564   GST_PLAY_BIN_UNLOCK (playbin);
1565
1566   if (sinkpad) {
1567     GstObject *selector;
1568
1569     if ((selector = gst_pad_get_parent (sinkpad))) {
1570       /* activate the selected pad */
1571       g_object_set (selector, "active-pad", sinkpad, NULL);
1572       gst_object_unref (selector);
1573     }
1574     gst_object_unref (sinkpad);
1575   }
1576   return TRUE;
1577
1578 no_channels:
1579   {
1580     GST_PLAY_BIN_UNLOCK (playbin);
1581     GST_DEBUG_OBJECT (playbin, "can't switch audio, we have no channels");
1582     return FALSE;
1583   }
1584 }
1585
1586 static void
1587 _suburidecodebin_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data)
1588 {
1589   GST_DEBUG_OBJECT (pad, "Pad blocked: %d", blocked);
1590 }
1591
1592 static void
1593 gst_play_bin_suburidecodebin_seek_to_start (GstElement * suburidecodebin)
1594 {
1595   GstIterator *it = gst_element_iterate_src_pads (suburidecodebin);
1596   GstPad *sinkpad;
1597   GValue item = { 0, };
1598
1599   if (it && gst_iterator_next (it, &item) == GST_ITERATOR_OK
1600       && ((sinkpad = g_value_get_object (&item)) != NULL)) {
1601     GstEvent *event;
1602
1603     event =
1604         gst_event_new_seek (1.0, GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
1605         GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, -1);
1606     if (!gst_pad_send_event (sinkpad, event)) {
1607       event =
1608           gst_event_new_seek (1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
1609           GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, -1);
1610       if (!gst_pad_send_event (sinkpad, event))
1611         GST_DEBUG_OBJECT (suburidecodebin, "Seeking to the beginning failed!");
1612     }
1613
1614     g_value_unset (&item);
1615   }
1616
1617   if (it)
1618     gst_iterator_free (it);
1619 }
1620
1621 static void
1622 gst_play_bin_suburidecodebin_block (GstElement * suburidecodebin,
1623     gboolean block)
1624 {
1625   GstIterator *it = gst_element_iterate_src_pads (suburidecodebin);
1626   gboolean done = FALSE;
1627   GValue item = { 0, };
1628
1629   GST_DEBUG_OBJECT (suburidecodebin, "Blocking suburidecodebin: %d", block);
1630
1631   if (!it)
1632     return;
1633   while (!done) {
1634     GstPad *sinkpad;
1635
1636     switch (gst_iterator_next (it, &item)) {
1637       case GST_ITERATOR_OK:
1638         sinkpad = g_value_get_object (&item);
1639         gst_pad_set_blocked_async (sinkpad, block, _suburidecodebin_blocked_cb,
1640             NULL);
1641         g_value_reset (&item);
1642         break;
1643       case GST_ITERATOR_DONE:
1644         done = TRUE;
1645         break;
1646       case GST_ITERATOR_RESYNC:
1647         gst_iterator_resync (it);
1648         break;
1649       case GST_ITERATOR_ERROR:
1650         done = TRUE;
1651         break;
1652     }
1653   }
1654   g_value_unset (&item);
1655   gst_iterator_free (it);
1656 }
1657
1658 static gboolean
1659 gst_play_bin_set_current_text_stream (GstPlayBin * playbin, gint stream)
1660 {
1661   GstSourceGroup *group;
1662   GPtrArray *channels;
1663   GstPad *sinkpad;
1664
1665   GST_PLAY_BIN_LOCK (playbin);
1666
1667   GST_DEBUG_OBJECT (playbin, "Changing current text stream %d -> %d",
1668       playbin->current_text, stream);
1669
1670   group = get_group (playbin);
1671   if (!(channels = group->text_channels))
1672     goto no_channels;
1673
1674   if (stream == -1 || channels->len <= stream) {
1675     sinkpad = NULL;
1676   } else {
1677     /* take channel from selected stream */
1678     sinkpad = g_ptr_array_index (channels, stream);
1679   }
1680
1681   if (sinkpad)
1682     gst_object_ref (sinkpad);
1683   GST_PLAY_BIN_UNLOCK (playbin);
1684
1685   if (sinkpad) {
1686     GstObject *selector;
1687
1688     if ((selector = gst_pad_get_parent (sinkpad))) {
1689       GstPad *old_sinkpad;
1690
1691       g_object_get (selector, "active-pad", &old_sinkpad, NULL);
1692
1693       if (old_sinkpad != sinkpad) {
1694         gboolean need_unblock, need_block, need_seek;
1695         GstPad *src, *peer = NULL, *oldpeer = NULL;
1696         GstElement *parent_element = NULL, *old_parent_element = NULL;
1697
1698         /* Now check if we need to seek the suburidecodebin to the beginning
1699          * or if we need to block all suburidecodebin sinkpads or if we need
1700          * to unblock all suburidecodebin sinkpads
1701          */
1702         if (sinkpad)
1703           peer = gst_pad_get_peer (sinkpad);
1704         if (old_sinkpad)
1705           oldpeer = gst_pad_get_peer (old_sinkpad);
1706
1707         if (peer)
1708           parent_element = gst_pad_get_parent_element (peer);
1709         if (oldpeer)
1710           old_parent_element = gst_pad_get_parent_element (oldpeer);
1711
1712         need_block = (old_parent_element == group->suburidecodebin
1713             && parent_element != old_parent_element);
1714         need_unblock = (parent_element == group->suburidecodebin
1715             && parent_element != old_parent_element);
1716         need_seek = (parent_element == group->suburidecodebin);
1717
1718         if (peer)
1719           gst_object_unref (peer);
1720         if (oldpeer)
1721           gst_object_unref (oldpeer);
1722         if (parent_element)
1723           gst_object_unref (parent_element);
1724         if (old_parent_element)
1725           gst_object_unref (old_parent_element);
1726
1727         /* Block all suburidecodebin sinkpads */
1728         if (need_block)
1729           gst_play_bin_suburidecodebin_block (group->suburidecodebin, TRUE);
1730
1731         /* activate the selected pad */
1732         g_object_set (selector, "active-pad", sinkpad, NULL);
1733
1734         src = gst_element_get_static_pad (GST_ELEMENT_CAST (selector), "src");
1735         peer = gst_pad_get_peer (src);
1736         if (peer) {
1737           GstStructure *s;
1738           GstEvent *event;
1739           /* Flush the subtitle renderer to remove any
1740            * currently displayed subtitles. This event will
1741            * never travel outside subtitleoverlay!
1742            */
1743           s = gst_structure_empty_new ("subtitleoverlay-flush-subtitle");
1744           event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, s);
1745           gst_pad_send_event (peer, event);
1746           gst_object_unref (peer);
1747         }
1748         gst_object_unref (src);
1749
1750         /* Unblock pads if necessary */
1751         if (need_unblock)
1752           gst_play_bin_suburidecodebin_block (group->suburidecodebin, FALSE);
1753
1754         /* seek to the beginning */
1755         if (need_seek)
1756           gst_play_bin_suburidecodebin_seek_to_start (group->suburidecodebin);
1757       }
1758       gst_object_unref (selector);
1759
1760       if (old_sinkpad)
1761         gst_object_unref (old_sinkpad);
1762     }
1763     gst_object_unref (sinkpad);
1764   }
1765   return TRUE;
1766
1767 no_channels:
1768   {
1769     GST_PLAY_BIN_UNLOCK (playbin);
1770     return FALSE;
1771   }
1772 }
1773
1774 static void
1775 gst_play_bin_set_sink (GstPlayBin * playbin, GstElement ** elem,
1776     const gchar * dbg, GstElement * sink)
1777 {
1778   GST_INFO_OBJECT (playbin, "Setting %s sink to %" GST_PTR_FORMAT, dbg, sink);
1779
1780   GST_PLAY_BIN_LOCK (playbin);
1781   if (*elem != sink) {
1782     GstElement *old;
1783
1784     old = *elem;
1785     if (sink)
1786       gst_object_ref_sink (sink);
1787
1788     *elem = sink;
1789     if (old)
1790       gst_object_unref (old);
1791   }
1792   GST_LOG_OBJECT (playbin, "%s sink now %" GST_PTR_FORMAT, dbg, *elem);
1793   GST_PLAY_BIN_UNLOCK (playbin);
1794 }
1795
1796 static void
1797 gst_play_bin_set_encoding (GstPlayBin * playbin, const gchar * encoding)
1798 {
1799   GstElement *elem;
1800
1801   GST_PLAY_BIN_LOCK (playbin);
1802
1803   /* set subtitles on all current and next decodebins. */
1804   if ((elem = playbin->groups[0].uridecodebin))
1805     g_object_set (G_OBJECT (elem), "subtitle-encoding", encoding, NULL);
1806   if ((elem = playbin->groups[0].suburidecodebin))
1807     g_object_set (G_OBJECT (elem), "subtitle-encoding", encoding, NULL);
1808   if ((elem = playbin->groups[1].uridecodebin))
1809     g_object_set (G_OBJECT (elem), "subtitle-encoding", encoding, NULL);
1810   if ((elem = playbin->groups[1].suburidecodebin))
1811     g_object_set (G_OBJECT (elem), "subtitle-encoding", encoding, NULL);
1812
1813   gst_play_sink_set_subtitle_encoding (playbin->playsink, encoding);
1814   GST_PLAY_BIN_UNLOCK (playbin);
1815 }
1816
1817 static void
1818 gst_play_bin_set_property (GObject * object, guint prop_id,
1819     const GValue * value, GParamSpec * pspec)
1820 {
1821   GstPlayBin *playbin = GST_PLAY_BIN (object);
1822
1823   switch (prop_id) {
1824     case PROP_URI:
1825       gst_play_bin_set_uri (playbin, g_value_get_string (value));
1826       break;
1827     case PROP_SUBURI:
1828       gst_play_bin_set_suburi (playbin, g_value_get_string (value));
1829       break;
1830     case PROP_FLAGS:
1831       gst_play_bin_set_flags (playbin, g_value_get_flags (value));
1832       break;
1833     case PROP_CURRENT_VIDEO:
1834       gst_play_bin_set_current_video_stream (playbin, g_value_get_int (value));
1835       break;
1836     case PROP_CURRENT_AUDIO:
1837       gst_play_bin_set_current_audio_stream (playbin, g_value_get_int (value));
1838       break;
1839     case PROP_CURRENT_TEXT:
1840       gst_play_bin_set_current_text_stream (playbin, g_value_get_int (value));
1841       break;
1842     case PROP_SUBTITLE_ENCODING:
1843       gst_play_bin_set_encoding (playbin, g_value_get_string (value));
1844       break;
1845     case PROP_VIDEO_SINK:
1846       gst_play_bin_set_sink (playbin, &playbin->video_sink, "video",
1847           g_value_get_object (value));
1848       break;
1849     case PROP_AUDIO_SINK:
1850       gst_play_bin_set_sink (playbin, &playbin->audio_sink, "audio",
1851           g_value_get_object (value));
1852       break;
1853     case PROP_VIS_PLUGIN:
1854       gst_play_sink_set_vis_plugin (playbin->playsink,
1855           g_value_get_object (value));
1856       break;
1857     case PROP_TEXT_SINK:
1858       gst_play_bin_set_sink (playbin, &playbin->text_sink, "text",
1859           g_value_get_object (value));
1860       break;
1861     case PROP_VOLUME:
1862       gst_play_sink_set_volume (playbin->playsink, g_value_get_double (value));
1863       break;
1864     case PROP_MUTE:
1865       gst_play_sink_set_mute (playbin->playsink, g_value_get_boolean (value));
1866       break;
1867     case PROP_FONT_DESC:
1868       gst_play_sink_set_font_desc (playbin->playsink,
1869           g_value_get_string (value));
1870       break;
1871     case PROP_CONNECTION_SPEED:
1872       GST_PLAY_BIN_LOCK (playbin);
1873       playbin->connection_speed = g_value_get_uint (value) * 1000;
1874       GST_PLAY_BIN_UNLOCK (playbin);
1875       break;
1876     case PROP_BUFFER_SIZE:
1877       playbin->buffer_size = g_value_get_int (value);
1878       break;
1879     case PROP_BUFFER_DURATION:
1880       playbin->buffer_duration = g_value_get_int64 (value);
1881       break;
1882     case PROP_AV_OFFSET:
1883       gst_play_sink_set_av_offset (playbin->playsink,
1884           g_value_get_int64 (value));
1885       break;
1886     case PROP_RING_BUFFER_MAX_SIZE:
1887       playbin->ring_buffer_max_size = g_value_get_uint64 (value);
1888       break;
1889     default:
1890       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1891       break;
1892   }
1893 }
1894
1895 static GstElement *
1896 gst_play_bin_get_current_sink (GstPlayBin * playbin, GstElement ** elem,
1897     const gchar * dbg, GstPlaySinkType type)
1898 {
1899   GstElement *sink = gst_play_sink_get_sink (playbin->playsink, type);
1900
1901   GST_LOG_OBJECT (playbin, "play_sink_get_sink() returned %s sink %"
1902       GST_PTR_FORMAT ", the originally set %s sink is %" GST_PTR_FORMAT,
1903       dbg, sink, dbg, *elem);
1904
1905   if (sink == NULL) {
1906     GST_PLAY_BIN_LOCK (playbin);
1907     if ((sink = *elem))
1908       gst_object_ref (sink);
1909     GST_PLAY_BIN_UNLOCK (playbin);
1910   }
1911
1912   return sink;
1913 }
1914
1915 static void
1916 gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value,
1917     GParamSpec * pspec)
1918 {
1919   GstPlayBin *playbin = GST_PLAY_BIN (object);
1920
1921   switch (prop_id) {
1922     case PROP_URI:
1923     {
1924       GstSourceGroup *group;
1925
1926       GST_PLAY_BIN_LOCK (playbin);
1927       group = get_group (playbin);
1928       g_value_set_string (value, group->uri);
1929       GST_PLAY_BIN_UNLOCK (playbin);
1930       break;
1931     }
1932     case PROP_SUBURI:
1933     {
1934       GstSourceGroup *group;
1935
1936       GST_PLAY_BIN_LOCK (playbin);
1937       group = get_group (playbin);
1938       g_value_set_string (value, group->suburi);
1939       GST_PLAY_BIN_UNLOCK (playbin);
1940       break;
1941     }
1942     case PROP_SOURCE:
1943     {
1944       GST_OBJECT_LOCK (playbin);
1945       g_value_set_object (value, playbin->source);
1946       GST_OBJECT_UNLOCK (playbin);
1947       break;
1948     }
1949     case PROP_FLAGS:
1950       g_value_set_flags (value, gst_play_bin_get_flags (playbin));
1951       break;
1952     case PROP_N_VIDEO:
1953     {
1954       GstSourceGroup *group;
1955       gint n_video;
1956
1957       GST_PLAY_BIN_LOCK (playbin);
1958       group = get_group (playbin);
1959       n_video = (group->video_channels ? group->video_channels->len : 0);
1960       g_value_set_int (value, n_video);
1961       GST_PLAY_BIN_UNLOCK (playbin);
1962       break;
1963     }
1964     case PROP_CURRENT_VIDEO:
1965       GST_PLAY_BIN_LOCK (playbin);
1966       g_value_set_int (value, playbin->current_video);
1967       GST_PLAY_BIN_UNLOCK (playbin);
1968       break;
1969     case PROP_N_AUDIO:
1970     {
1971       GstSourceGroup *group;
1972       gint n_audio;
1973
1974       GST_PLAY_BIN_LOCK (playbin);
1975       group = get_group (playbin);
1976       n_audio = (group->audio_channels ? group->audio_channels->len : 0);
1977       g_value_set_int (value, n_audio);
1978       GST_PLAY_BIN_UNLOCK (playbin);
1979       break;
1980     }
1981     case PROP_CURRENT_AUDIO:
1982       GST_PLAY_BIN_LOCK (playbin);
1983       g_value_set_int (value, playbin->current_audio);
1984       GST_PLAY_BIN_UNLOCK (playbin);
1985       break;
1986     case PROP_N_TEXT:
1987     {
1988       GstSourceGroup *group;
1989       gint n_text;
1990
1991       GST_PLAY_BIN_LOCK (playbin);
1992       group = get_group (playbin);
1993       n_text = (group->text_channels ? group->text_channels->len : 0);
1994       g_value_set_int (value, n_text);
1995       GST_PLAY_BIN_UNLOCK (playbin);
1996       break;
1997     }
1998     case PROP_CURRENT_TEXT:
1999       GST_PLAY_BIN_LOCK (playbin);
2000       g_value_set_int (value, playbin->current_text);
2001       GST_PLAY_BIN_UNLOCK (playbin);
2002       break;
2003     case PROP_SUBTITLE_ENCODING:
2004       GST_PLAY_BIN_LOCK (playbin);
2005       g_value_take_string (value,
2006           gst_play_sink_get_subtitle_encoding (playbin->playsink));
2007       GST_PLAY_BIN_UNLOCK (playbin);
2008       break;
2009     case PROP_VIDEO_SINK:
2010       g_value_take_object (value,
2011           gst_play_bin_get_current_sink (playbin, &playbin->video_sink,
2012               "video", GST_PLAY_SINK_TYPE_VIDEO));
2013       break;
2014     case PROP_AUDIO_SINK:
2015       g_value_take_object (value,
2016           gst_play_bin_get_current_sink (playbin, &playbin->audio_sink,
2017               "audio", GST_PLAY_SINK_TYPE_AUDIO));
2018       break;
2019     case PROP_VIS_PLUGIN:
2020       g_value_take_object (value,
2021           gst_play_sink_get_vis_plugin (playbin->playsink));
2022       break;
2023     case PROP_TEXT_SINK:
2024       g_value_take_object (value,
2025           gst_play_bin_get_current_sink (playbin, &playbin->text_sink,
2026               "text", GST_PLAY_SINK_TYPE_TEXT));
2027       break;
2028     case PROP_VOLUME:
2029       g_value_set_double (value, gst_play_sink_get_volume (playbin->playsink));
2030       break;
2031     case PROP_MUTE:
2032       g_value_set_boolean (value, gst_play_sink_get_mute (playbin->playsink));
2033       break;
2034     case PROP_FRAME:
2035       gst_value_take_buffer (value,
2036           gst_play_sink_get_last_frame (playbin->playsink));
2037       break;
2038     case PROP_FONT_DESC:
2039       g_value_take_string (value,
2040           gst_play_sink_get_font_desc (playbin->playsink));
2041       break;
2042     case PROP_CONNECTION_SPEED:
2043       GST_PLAY_BIN_LOCK (playbin);
2044       g_value_set_uint (value, playbin->connection_speed / 1000);
2045       GST_PLAY_BIN_UNLOCK (playbin);
2046       break;
2047     case PROP_BUFFER_SIZE:
2048       GST_OBJECT_LOCK (playbin);
2049       g_value_set_int (value, playbin->buffer_size);
2050       GST_OBJECT_UNLOCK (playbin);
2051       break;
2052     case PROP_BUFFER_DURATION:
2053       GST_OBJECT_LOCK (playbin);
2054       g_value_set_int64 (value, playbin->buffer_duration);
2055       GST_OBJECT_UNLOCK (playbin);
2056       break;
2057     case PROP_AV_OFFSET:
2058       g_value_set_int64 (value,
2059           gst_play_sink_get_av_offset (playbin->playsink));
2060       break;
2061     case PROP_RING_BUFFER_MAX_SIZE:
2062       g_value_set_uint64 (value, playbin->ring_buffer_max_size);
2063       break;
2064     default:
2065       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2066       break;
2067   }
2068 }
2069
2070 static void
2071 gst_play_bin_update_cached_duration_from_query (GstPlayBin * playbin,
2072     gboolean valid, GstQuery * query)
2073 {
2074   GstFormat fmt;
2075   gint64 duration;
2076   gint i;
2077
2078   GST_DEBUG_OBJECT (playbin, "Updating cached duration from query");
2079   gst_query_parse_duration (query, &fmt, &duration);
2080
2081   for (i = 0; i < G_N_ELEMENTS (playbin->duration); i++) {
2082     if (playbin->duration[i].format == 0 || fmt == playbin->duration[i].format) {
2083       playbin->duration[i].valid = valid;
2084       playbin->duration[i].format = fmt;
2085       playbin->duration[i].duration = valid ? duration : -1;
2086       break;
2087     }
2088   }
2089 }
2090
2091 static void
2092 gst_play_bin_update_cached_duration (GstPlayBin * playbin)
2093 {
2094   const GstFormat formats[] =
2095       { GST_FORMAT_TIME, GST_FORMAT_BYTES, GST_FORMAT_DEFAULT };
2096   gboolean ret;
2097   GstQuery *query;
2098   gint i;
2099
2100   GST_DEBUG_OBJECT (playbin, "Updating cached durations before group switch");
2101   for (i = 0; i < G_N_ELEMENTS (formats); i++) {
2102     query = gst_query_new_duration (formats[i]);
2103     ret =
2104         GST_ELEMENT_CLASS (parent_class)->query (GST_ELEMENT_CAST (playbin),
2105         query);
2106     gst_play_bin_update_cached_duration_from_query (playbin, ret, query);
2107     gst_query_unref (query);
2108   }
2109 }
2110
2111 static gboolean
2112 gst_play_bin_query (GstElement * element, GstQuery * query)
2113 {
2114   GstPlayBin *playbin = GST_PLAY_BIN (element);
2115   gboolean ret;
2116
2117   /* During a group switch we shouldn't allow duration queries
2118    * because it's not clear if the old or new group's duration
2119    * is returned and if the sinks are already playing new data
2120    * or old data. See bug #585969
2121    *
2122    * While we're at it, also don't do any other queries during
2123    * a group switch or any other event that causes topology changes
2124    * by taking the playbin lock in any case.
2125    */
2126   GST_PLAY_BIN_LOCK (playbin);
2127
2128   if (GST_QUERY_TYPE (query) == GST_QUERY_DURATION) {
2129     GstSourceGroup *group = playbin->curr_group;
2130     gboolean pending;
2131
2132     GST_SOURCE_GROUP_LOCK (group);
2133     if (group->stream_changed_pending_lock) {
2134       g_mutex_lock (group->stream_changed_pending_lock);
2135       pending = group->pending || group->stream_changed_pending;
2136       g_mutex_unlock (group->stream_changed_pending_lock);
2137     } else {
2138       pending = group->pending;
2139     }
2140     if (pending) {
2141       GstFormat fmt;
2142       gint i;
2143
2144       ret = FALSE;
2145       gst_query_parse_duration (query, &fmt, NULL);
2146       for (i = 0; i < G_N_ELEMENTS (playbin->duration); i++) {
2147         if (fmt == playbin->duration[i].format) {
2148           ret = playbin->duration[i].valid;
2149           gst_query_set_duration (query, fmt,
2150               (ret ? playbin->duration[i].duration : -1));
2151           break;
2152         }
2153       }
2154       /* if nothing cached yet, we might as well request duration,
2155        * such as during initial startup */
2156       if (ret) {
2157         GST_DEBUG_OBJECT (playbin,
2158             "Taking cached duration because of pending group switch: %d", ret);
2159         GST_SOURCE_GROUP_UNLOCK (group);
2160         GST_PLAY_BIN_UNLOCK (playbin);
2161         return ret;
2162       }
2163     }
2164     GST_SOURCE_GROUP_UNLOCK (group);
2165   }
2166
2167   ret = GST_ELEMENT_CLASS (parent_class)->query (element, query);
2168
2169   if (GST_QUERY_TYPE (query) == GST_QUERY_DURATION)
2170     gst_play_bin_update_cached_duration_from_query (playbin, ret, query);
2171   GST_PLAY_BIN_UNLOCK (playbin);
2172
2173   return ret;
2174 }
2175
2176 /* mime types we are not handling on purpose right now, don't post a
2177  * missing-plugin message for these */
2178 static const gchar *blacklisted_mimes[] = {
2179   NULL
2180 };
2181
2182 static void
2183 gst_play_bin_handle_message (GstBin * bin, GstMessage * msg)
2184 {
2185   GstPlayBin *playbin = GST_PLAY_BIN (bin);
2186   GstSourceGroup *group;
2187
2188   if (gst_is_missing_plugin_message (msg)) {
2189     gchar *detail;
2190     guint i;
2191
2192     detail = gst_missing_plugin_message_get_installer_detail (msg);
2193     for (i = 0; detail != NULL && blacklisted_mimes[i] != NULL; ++i) {
2194       if (strstr (detail, "|decoder-") && strstr (detail, blacklisted_mimes[i])) {
2195         GST_LOG_OBJECT (bin, "suppressing message %" GST_PTR_FORMAT, msg);
2196         gst_message_unref (msg);
2197         g_free (detail);
2198         return;
2199       }
2200     }
2201     g_free (detail);
2202   } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ELEMENT) {
2203     const GstStructure *s = gst_message_get_structure (msg);
2204
2205     /* Drop all stream-changed messages except the last one */
2206     if (strcmp ("playbin2-stream-changed", gst_structure_get_name (s)) == 0) {
2207       guint32 seqnum = gst_message_get_seqnum (msg);
2208       GList *l, *l_prev;
2209
2210       group = playbin->curr_group;
2211       g_mutex_lock (group->stream_changed_pending_lock);
2212       for (l = group->stream_changed_pending; l;) {
2213         guint32 l_seqnum = GPOINTER_TO_UINT (l->data);
2214
2215         if (l_seqnum == seqnum) {
2216           l_prev = l;
2217           l = l->next;
2218           group->stream_changed_pending =
2219               g_list_delete_link (group->stream_changed_pending, l_prev);
2220           if (group->stream_changed_pending) {
2221             gst_message_unref (msg);
2222             msg = NULL;
2223             break;
2224           }
2225         } else {
2226           l = l->next;
2227         }
2228       }
2229       g_mutex_unlock (group->stream_changed_pending_lock);
2230     }
2231   } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ASYNC_START ||
2232       GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ASYNC_DONE) {
2233     GstObject *src = GST_OBJECT_CAST (msg->src);
2234
2235     /* Ignore async state changes from the uridecodebin children,
2236      * see bug #602000. */
2237     group = playbin->curr_group;
2238     if (src && (group = playbin->curr_group) &&
2239         ((group->uridecodebin && src == GST_OBJECT_CAST (group->uridecodebin))
2240             || (group->suburidecodebin
2241                 && src == GST_OBJECT_CAST (group->suburidecodebin)))) {
2242       GST_DEBUG_OBJECT (playbin,
2243           "Ignoring async state change of uridecodebin: %s",
2244           GST_OBJECT_NAME (src));
2245       gst_message_unref (msg);
2246       msg = NULL;
2247     }
2248   } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
2249     /* If we get an error of the subtitle uridecodebin transform
2250      * them into warnings and disable the subtitles */
2251     group = playbin->curr_group;
2252     if (group && group->suburidecodebin) {
2253       if (G_UNLIKELY (gst_object_has_ancestor (msg->src, GST_OBJECT_CAST
2254                   (group->suburidecodebin)))) {
2255         GError *err;
2256         gchar *debug = NULL;
2257         GstMessage *new_msg;
2258         GstIterator *it;
2259         gboolean done = FALSE;
2260         GValue item = { 0, };
2261
2262         gst_message_parse_error (msg, &err, &debug);
2263         new_msg = gst_message_new_warning (msg->src, err, debug);
2264
2265         gst_message_unref (msg);
2266         g_error_free (err);
2267         g_free (debug);
2268         msg = new_msg;
2269
2270         REMOVE_SIGNAL (group->suburidecodebin, group->sub_pad_added_id);
2271         REMOVE_SIGNAL (group->suburidecodebin, group->sub_pad_removed_id);
2272         REMOVE_SIGNAL (group->suburidecodebin, group->sub_no_more_pads_id);
2273         REMOVE_SIGNAL (group->suburidecodebin, group->sub_autoplug_continue_id);
2274
2275         it = gst_element_iterate_src_pads (group->suburidecodebin);
2276         while (it && !done) {
2277           GstPad *p = NULL;
2278           GstIteratorResult res;
2279
2280           res = gst_iterator_next (it, &item);
2281
2282           switch (res) {
2283             case GST_ITERATOR_DONE:
2284               done = TRUE;
2285               break;
2286             case GST_ITERATOR_OK:
2287               p = g_value_get_object (&item);
2288               pad_removed_cb (NULL, p, group);
2289               g_value_reset (&item);
2290               break;
2291
2292             case GST_ITERATOR_RESYNC:
2293               gst_iterator_resync (it);
2294               break;
2295             case GST_ITERATOR_ERROR:
2296               done = TRUE;
2297               break;
2298           }
2299         }
2300         g_value_unset (&item);
2301         if (it)
2302           gst_iterator_free (it);
2303
2304         gst_object_ref (group->suburidecodebin);
2305         gst_bin_remove (bin, group->suburidecodebin);
2306         gst_element_set_locked_state (group->suburidecodebin, FALSE);
2307
2308         if (group->sub_pending) {
2309           group->sub_pending = FALSE;
2310           no_more_pads_cb (NULL, group);
2311         }
2312       }
2313     }
2314   }
2315
2316   if (msg)
2317     GST_BIN_CLASS (parent_class)->handle_message (bin, msg);
2318 }
2319
2320 static void
2321 selector_active_pad_changed (GObject * selector, GParamSpec * pspec,
2322     GstPlayBin * playbin)
2323 {
2324   const gchar *property;
2325   GstSourceGroup *group;
2326   GstSourceSelect *select = NULL;
2327   int i;
2328
2329   GST_PLAY_BIN_LOCK (playbin);
2330   group = get_group (playbin);
2331
2332   for (i = 0; i < PLAYBIN_STREAM_LAST; i++) {
2333     if (selector == G_OBJECT (group->selector[i].selector)) {
2334       select = &group->selector[i];
2335     }
2336   }
2337
2338   /* We got a pad-change after our group got switched out; no need to notify */
2339   if (!select) {
2340     GST_PLAY_BIN_UNLOCK (playbin);
2341     return;
2342   }
2343
2344   switch (select->type) {
2345     case GST_PLAY_SINK_TYPE_VIDEO:
2346     case GST_PLAY_SINK_TYPE_VIDEO_RAW:
2347       property = "current-video";
2348       playbin->current_video = get_current_stream_number (playbin,
2349           group->video_channels);
2350       break;
2351     case GST_PLAY_SINK_TYPE_AUDIO:
2352     case GST_PLAY_SINK_TYPE_AUDIO_RAW:
2353       property = "current-audio";
2354       playbin->current_audio = get_current_stream_number (playbin,
2355           group->audio_channels);
2356       break;
2357     case GST_PLAY_SINK_TYPE_TEXT:
2358       property = "current-text";
2359       playbin->current_text = get_current_stream_number (playbin,
2360           group->text_channels);
2361       break;
2362     default:
2363       property = NULL;
2364   }
2365   GST_PLAY_BIN_UNLOCK (playbin);
2366
2367   if (property)
2368     g_object_notify (G_OBJECT (playbin), property);
2369 }
2370
2371 static void
2372 selector_blocked (GstPad * pad, gboolean blocked, gpointer user_data)
2373 {
2374   /* no nothing */
2375   GST_DEBUG_OBJECT (pad, "blocked callback, blocked: %d", blocked);
2376 }
2377
2378 /* this callback sends a delayed event once the pad becomes unblocked */
2379 static gboolean
2380 stream_changed_data_probe (GstPad * pad, GstMiniObject * object, gpointer data)
2381 {
2382   GstSourceSelect *select = (GstSourceSelect *) data;
2383   GstEvent *e;
2384
2385   /* we need do this just once, so cleanup first */
2386   gst_pad_remove_data_probe (pad, select->sinkpad_data_probe);
2387   select->sinkpad_data_probe = 0;
2388   e = select->sinkpad_delayed_event;
2389   select->sinkpad_delayed_event = NULL;
2390
2391   /* really, this should not happen */
2392   if (!e) {
2393     GST_WARNING ("Data probed called, but no delayed event");
2394     return TRUE;
2395   }
2396
2397   if (GST_IS_EVENT (object)
2398       && GST_EVENT_TYPE (GST_EVENT_CAST (object)) == GST_EVENT_SEGMENT) {
2399     /* push the event first, then send the delayed one */
2400     gst_event_ref (GST_EVENT_CAST (object));
2401     gst_pad_send_event (pad, GST_EVENT_CAST (object));
2402     gst_pad_send_event (pad, e);
2403     return FALSE;
2404   } else {
2405     /* send delayed event, then allow the caller to go on */
2406     gst_pad_send_event (pad, e);
2407     return TRUE;
2408   }
2409 }
2410
2411 /* helper function to lookup stuff in lists */
2412 static gboolean
2413 array_has_value (const gchar * values[], const gchar * value)
2414 {
2415   gint i;
2416
2417   for (i = 0; values[i]; i++) {
2418     if (values[i] && g_str_has_prefix (value, values[i]))
2419       return TRUE;
2420   }
2421   return FALSE;
2422 }
2423
2424 typedef struct
2425 {
2426   GstPlayBin *playbin;
2427   gint stream_id;
2428   GstPlaySinkType type;
2429 } NotifyTagsData;
2430
2431 static void
2432 notify_tags_cb (GObject * object, GParamSpec * pspec, gpointer user_data)
2433 {
2434   NotifyTagsData *ntdata = (NotifyTagsData *) user_data;
2435   gint signal;
2436
2437   GST_DEBUG_OBJECT (ntdata->playbin, "Tags on pad %" GST_PTR_FORMAT
2438       " with stream id %d and type %d have changed",
2439       object, ntdata->stream_id, ntdata->type);
2440
2441   switch (ntdata->type) {
2442     case GST_PLAY_SINK_TYPE_VIDEO:
2443     case GST_PLAY_SINK_TYPE_VIDEO_RAW:
2444       signal = SIGNAL_VIDEO_TAGS_CHANGED;
2445       break;
2446     case GST_PLAY_SINK_TYPE_AUDIO:
2447     case GST_PLAY_SINK_TYPE_AUDIO_RAW:
2448       signal = SIGNAL_AUDIO_TAGS_CHANGED;
2449       break;
2450     case GST_PLAY_SINK_TYPE_TEXT:
2451       signal = SIGNAL_TEXT_TAGS_CHANGED;
2452       break;
2453     default:
2454       signal = -1;
2455       break;
2456   }
2457
2458   if (signal >= 0)
2459     g_signal_emit (G_OBJECT (ntdata->playbin), gst_play_bin_signals[signal], 0,
2460         ntdata->stream_id);
2461 }
2462
2463 /* this function is called when a new pad is added to decodebin. We check the
2464  * type of the pad and add it to the selector element of the group.
2465  */
2466 static void
2467 pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
2468 {
2469   GstPlayBin *playbin;
2470   GstCaps *caps;
2471   const GstStructure *s;
2472   const gchar *name;
2473   GstPad *sinkpad;
2474   GstPadLinkReturn res;
2475   GstSourceSelect *select = NULL;
2476   gint i;
2477   gboolean changed = FALSE;
2478
2479   playbin = group->playbin;
2480
2481   caps = gst_pad_get_caps (pad, NULL);
2482   s = gst_caps_get_structure (caps, 0);
2483   name = gst_structure_get_name (s);
2484
2485   GST_DEBUG_OBJECT (playbin,
2486       "pad %s:%s with caps %" GST_PTR_FORMAT " added in group %p",
2487       GST_DEBUG_PAD_NAME (pad), caps, group);
2488
2489   /* major type of the pad, this determines the selector to use */
2490   for (i = 0; i < PLAYBIN_STREAM_LAST; i++) {
2491     if (array_has_value (group->selector[i].media_list, name)) {
2492       select = &group->selector[i];
2493       break;
2494     } else if (group->selector[i].get_media_caps) {
2495       GstCaps *media_caps = group->selector[i].get_media_caps ();
2496
2497       if (media_caps && gst_caps_can_intersect (media_caps, caps)) {
2498         select = &group->selector[i];
2499         gst_caps_unref (media_caps);
2500         break;
2501       }
2502       gst_caps_unref (media_caps);
2503     }
2504   }
2505   /* no selector found for the media type, don't bother linking it to a
2506    * selector. This will leave the pad unlinked and thus ignored. */
2507   if (select == NULL)
2508     goto unknown_type;
2509
2510   GST_SOURCE_GROUP_LOCK (group);
2511   if (select->selector == NULL && playbin->have_selector) {
2512     /* no selector, create one */
2513     GST_DEBUG_OBJECT (playbin, "creating new input selector");
2514     select->selector = gst_element_factory_make ("input-selector", NULL);
2515     if (select->selector == NULL) {
2516       /* post the missing selector message only once */
2517       playbin->have_selector = FALSE;
2518       gst_element_post_message (GST_ELEMENT_CAST (playbin),
2519           gst_missing_element_message_new (GST_ELEMENT_CAST (playbin),
2520               "input-selector"));
2521       GST_ELEMENT_WARNING (playbin, CORE, MISSING_PLUGIN,
2522           (_("Missing element '%s' - check your GStreamer installation."),
2523               "input-selector"), (NULL));
2524     } else {
2525       g_object_set (select->selector, "sync-streams", TRUE, NULL);
2526
2527       g_signal_connect (select->selector, "notify::active-pad",
2528           G_CALLBACK (selector_active_pad_changed), playbin);
2529
2530       GST_DEBUG_OBJECT (playbin, "adding new selector %p", select->selector);
2531       gst_bin_add (GST_BIN_CAST (playbin), select->selector);
2532       gst_element_set_state (select->selector, GST_STATE_PAUSED);
2533     }
2534   }
2535
2536   if (select->srcpad == NULL) {
2537     if (select->selector) {
2538       /* save source pad of the selector */
2539       select->srcpad = gst_element_get_static_pad (select->selector, "src");
2540     } else {
2541       /* no selector, use the pad as the source pad then */
2542       select->srcpad = gst_object_ref (pad);
2543     }
2544
2545     /* block the selector srcpad. It's possible that multiple decodebins start
2546      * pushing data into the selectors before we have a chance to collect all
2547      * streams and connect the sinks, resulting in not-linked errors. After we
2548      * configured the sinks we will unblock them all. */
2549     GST_DEBUG_OBJECT (playbin, "blocking %" GST_PTR_FORMAT, select->srcpad);
2550     gst_pad_set_blocked_async (select->srcpad, TRUE, selector_blocked, NULL);
2551   }
2552
2553   /* get sinkpad for the new stream */
2554   if (select->selector) {
2555     if ((sinkpad = gst_element_get_request_pad (select->selector, "sink%d"))) {
2556       gulong notify_tags_handler = 0;
2557       NotifyTagsData *ntdata;
2558
2559       GST_DEBUG_OBJECT (playbin, "got pad %s:%s from selector",
2560           GST_DEBUG_PAD_NAME (sinkpad));
2561
2562       /* store the selector for the pad */
2563       g_object_set_data (G_OBJECT (sinkpad), "playbin2.select", select);
2564
2565       /* connect to the notify::tags signal for our
2566        * own *-tags-changed signals
2567        */
2568       ntdata = g_new0 (NotifyTagsData, 1);
2569       ntdata->playbin = playbin;
2570       ntdata->stream_id = select->channels->len;
2571       ntdata->type = select->type;
2572
2573       notify_tags_handler =
2574           g_signal_connect_data (G_OBJECT (sinkpad), "notify::tags",
2575           G_CALLBACK (notify_tags_cb), ntdata, (GClosureNotify) g_free,
2576           (GConnectFlags) 0);
2577       g_object_set_data (G_OBJECT (sinkpad), "playbin2.notify_tags_handler",
2578           (gpointer) notify_tags_handler);
2579
2580       /* store the pad in the array */
2581       GST_DEBUG_OBJECT (playbin, "pad %p added to array", sinkpad);
2582       g_ptr_array_add (select->channels, sinkpad);
2583
2584       res = gst_pad_link (pad, sinkpad);
2585       if (GST_PAD_LINK_FAILED (res))
2586         goto link_failed;
2587
2588       /* store selector pad so we can release it */
2589       g_object_set_data (G_OBJECT (pad), "playbin2.sinkpad", sinkpad);
2590
2591       changed = TRUE;
2592       GST_DEBUG_OBJECT (playbin, "linked pad %s:%s to selector %p",
2593           GST_DEBUG_PAD_NAME (pad), select->selector);
2594     }
2595   } else {
2596     /* no selector, don't configure anything, we'll link the new pad directly to
2597      * the sink. */
2598     changed = FALSE;
2599     sinkpad = NULL;
2600   }
2601   GST_SOURCE_GROUP_UNLOCK (group);
2602
2603   if (changed) {
2604     int signal;
2605     gboolean always_ok = (decodebin == group->suburidecodebin);
2606
2607     switch (select->type) {
2608       case GST_PLAY_SINK_TYPE_VIDEO:
2609       case GST_PLAY_SINK_TYPE_VIDEO_RAW:
2610         /* we want to return NOT_LINKED for unselected pads but only for pads
2611          * from the normal uridecodebin. This makes sure that subtitle streams
2612          * are not raced past audio/video from decodebin2's multiqueue.
2613          * For pads from suburidecodebin OK should always be returned, otherwise
2614          * it will most likely stop. */
2615         g_object_set (sinkpad, "always-ok", always_ok, NULL);
2616         signal = SIGNAL_VIDEO_CHANGED;
2617         break;
2618       case GST_PLAY_SINK_TYPE_AUDIO:
2619       case GST_PLAY_SINK_TYPE_AUDIO_RAW:
2620         g_object_set (sinkpad, "always-ok", always_ok, NULL);
2621         signal = SIGNAL_AUDIO_CHANGED;
2622         break;
2623       case GST_PLAY_SINK_TYPE_TEXT:
2624         g_object_set (sinkpad, "always-ok", always_ok, NULL);
2625         signal = SIGNAL_TEXT_CHANGED;
2626         break;
2627       default:
2628         signal = -1;
2629     }
2630
2631     if (signal >= 0)
2632       g_signal_emit (G_OBJECT (playbin), gst_play_bin_signals[signal], 0, NULL);
2633   }
2634
2635 done:
2636   gst_caps_unref (caps);
2637   return;
2638
2639   /* ERRORS */
2640 unknown_type:
2641   {
2642     GST_ERROR_OBJECT (playbin, "unknown type %s for pad %s:%s",
2643         name, GST_DEBUG_PAD_NAME (pad));
2644     goto done;
2645   }
2646 link_failed:
2647   {
2648     GST_ERROR_OBJECT (playbin,
2649         "failed to link pad %s:%s to selector, reason %d",
2650         GST_DEBUG_PAD_NAME (pad), res);
2651     GST_SOURCE_GROUP_UNLOCK (group);
2652     goto done;
2653   }
2654 }
2655
2656 /* called when a pad is removed from the uridecodebin. We unlink the pad from
2657  * the selector. This will make the selector select a new pad. */
2658 static void
2659 pad_removed_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
2660 {
2661   GstPlayBin *playbin;
2662   GstPad *peer;
2663   GstElement *selector;
2664   GstSourceSelect *select;
2665
2666   playbin = group->playbin;
2667
2668   GST_DEBUG_OBJECT (playbin,
2669       "pad %s:%s removed from group %p", GST_DEBUG_PAD_NAME (pad), group);
2670
2671   GST_SOURCE_GROUP_LOCK (group);
2672   /* get the selector sinkpad */
2673   if (!(peer = g_object_get_data (G_OBJECT (pad), "playbin2.sinkpad")))
2674     goto not_linked;
2675
2676   if ((select = g_object_get_data (G_OBJECT (peer), "playbin2.select"))) {
2677     gulong notify_tags_handler;
2678
2679     notify_tags_handler =
2680         (gulong) g_object_get_data (G_OBJECT (peer),
2681         "playbin2.notify_tags_handler");
2682     if (notify_tags_handler != 0)
2683       g_signal_handler_disconnect (G_OBJECT (peer), notify_tags_handler);
2684     g_object_set_data (G_OBJECT (peer), "playbin2.notify_tags_handler", NULL);
2685
2686     /* remove the pad from the array */
2687     g_ptr_array_remove (select->channels, peer);
2688     GST_DEBUG_OBJECT (playbin, "pad %p removed from array", peer);
2689   }
2690
2691   /* unlink the pad now (can fail, the pad is unlinked before it's removed) */
2692   gst_pad_unlink (pad, peer);
2693
2694   /* get selector, this can be NULL when the element is removing the pads
2695    * because it's being disposed. */
2696   selector = GST_ELEMENT_CAST (gst_pad_get_parent (peer));
2697   if (!selector) {
2698     gst_object_unref (peer);
2699     goto no_selector;
2700   }
2701
2702   /* release the pad to the selector, this will make the selector choose a new
2703    * pad. */
2704   gst_element_release_request_pad (selector, peer);
2705   gst_object_unref (peer);
2706
2707   gst_object_unref (selector);
2708   GST_SOURCE_GROUP_UNLOCK (group);
2709
2710   return;
2711
2712   /* ERRORS */
2713 not_linked:
2714   {
2715     GST_DEBUG_OBJECT (playbin, "pad not linked");
2716     GST_SOURCE_GROUP_UNLOCK (group);
2717     return;
2718   }
2719 no_selector:
2720   {
2721     GST_DEBUG_OBJECT (playbin, "selector not found");
2722     GST_SOURCE_GROUP_UNLOCK (group);
2723     return;
2724   }
2725 }
2726
2727 /* we get called when all pads are available and we must connect the sinks to
2728  * them.
2729  * The main purpose of the code is to see if we have video/audio and subtitles
2730  * and pick the right pipelines to display them.
2731  *
2732  * The selectors installed on the group tell us about the presence of
2733  * audio/video and subtitle streams. This allows us to see if we need
2734  * visualisation, video or/and audio.
2735  */
2736 static void
2737 no_more_pads_cb (GstElement * decodebin, GstSourceGroup * group)
2738 {
2739   GstPlayBin *playbin;
2740   GstPadLinkReturn res;
2741   gint i;
2742   gboolean configure;
2743
2744   playbin = group->playbin;
2745
2746   GST_DEBUG_OBJECT (playbin, "no more pads in group %p", group);
2747
2748   GST_PLAY_BIN_SHUTDOWN_LOCK (playbin, shutdown);
2749
2750   GST_SOURCE_GROUP_LOCK (group);
2751   for (i = 0; i < PLAYBIN_STREAM_LAST; i++) {
2752     GstSourceSelect *select = &group->selector[i];
2753
2754     /* check if the specific media type was detected and thus has a selector
2755      * created for it. If there is the media type, get a sinkpad from the sink
2756      * and link it. We only do this if we have not yet requested the sinkpad
2757      * before. */
2758     if (select->srcpad && select->sinkpad == NULL) {
2759       GST_DEBUG_OBJECT (playbin, "requesting new sink pad %d", select->type);
2760       select->sinkpad =
2761           gst_play_sink_request_pad (playbin->playsink, select->type);
2762
2763       res = gst_pad_link (select->srcpad, select->sinkpad);
2764       GST_DEBUG_OBJECT (playbin, "linked type %s, result: %d",
2765           select->media_list[0], res);
2766       if (res != GST_PAD_LINK_OK) {
2767         GST_ELEMENT_ERROR (playbin, CORE, PAD,
2768             ("Internal playbin error."),
2769             ("Failed to link selector to sink. Error %d", res));
2770       }
2771     }
2772   }
2773   GST_DEBUG_OBJECT (playbin, "pending %d > %d", group->pending,
2774       group->pending - 1);
2775
2776   if (group->pending > 0)
2777     group->pending--;
2778
2779   if (group->suburidecodebin == decodebin)
2780     group->sub_pending = FALSE;
2781
2782   if (group->pending == 0) {
2783     /* we are the last group to complete, we will configure the output and then
2784      * signal the other waiters. */
2785     GST_LOG_OBJECT (playbin, "last group complete");
2786     configure = TRUE;
2787   } else {
2788     GST_LOG_OBJECT (playbin, "have more pending groups");
2789     configure = FALSE;
2790   }
2791   GST_SOURCE_GROUP_UNLOCK (group);
2792
2793   if (configure) {
2794     /* if we have custom sinks, configure them now */
2795     GST_SOURCE_GROUP_LOCK (group);
2796
2797     GST_INFO_OBJECT (playbin, "setting custom audio sink %" GST_PTR_FORMAT,
2798         group->audio_sink);
2799     gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_AUDIO,
2800         group->audio_sink);
2801
2802     GST_INFO_OBJECT (playbin, "setting custom video sink %" GST_PTR_FORMAT,
2803         group->video_sink);
2804     gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_VIDEO,
2805         group->video_sink);
2806
2807     GST_INFO_OBJECT (playbin, "setting custom text sink %" GST_PTR_FORMAT,
2808         playbin->text_sink);
2809     gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_TEXT,
2810         playbin->text_sink);
2811
2812     GST_SOURCE_GROUP_UNLOCK (group);
2813
2814     /* signal the other decodebins that they can continue now. */
2815     GST_SOURCE_GROUP_LOCK (group);
2816     /* unblock all selectors */
2817     for (i = 0; i < PLAYBIN_STREAM_LAST; i++) {
2818       GstSourceSelect *select = &group->selector[i];
2819
2820       /* All streamsynchronizer streams should see stream-changed message,
2821        * to arrange for blocking unblocking. */
2822       if (select->sinkpad) {
2823         GstStructure *s;
2824         GstMessage *msg;
2825         GstEvent *event;
2826         guint32 seqnum;
2827
2828         s = gst_structure_new ("playbin2-stream-changed", "uri", G_TYPE_STRING,
2829             group->uri, NULL);
2830         if (group->suburi)
2831           gst_structure_set (s, "suburi", G_TYPE_STRING, group->suburi, NULL);
2832         msg = gst_message_new_element (GST_OBJECT_CAST (playbin), s);
2833         seqnum = gst_message_get_seqnum (msg);
2834         event = gst_event_new_sink_message (msg);
2835         g_mutex_lock (group->stream_changed_pending_lock);
2836         group->stream_changed_pending =
2837             g_list_prepend (group->stream_changed_pending,
2838             GUINT_TO_POINTER (seqnum));
2839
2840         /* remove any data probe we might have, and replace */
2841         if (select->sinkpad_delayed_event)
2842           gst_event_unref (select->sinkpad_delayed_event);
2843         select->sinkpad_delayed_event = event;
2844         if (select->sinkpad_data_probe)
2845           gst_pad_remove_data_probe (select->sinkpad,
2846               select->sinkpad_data_probe);
2847
2848         /* we go to the trouble of setting a probe on the pad to send
2849            the playbin2-stream-changed event as sending it here might
2850            find that the pad is blocked, so we'd block here, and the
2851            pad might not be linked yet. Additionally, sending it here
2852            apparently would be on the wrong thread */
2853         select->sinkpad_data_probe =
2854             gst_pad_add_data_probe (select->sinkpad,
2855             (GCallback) stream_changed_data_probe, (gpointer) select);
2856
2857         g_mutex_unlock (group->stream_changed_pending_lock);
2858         gst_message_unref (msg);
2859       }
2860
2861       if (select->srcpad) {
2862         GST_DEBUG_OBJECT (playbin, "unblocking %" GST_PTR_FORMAT,
2863             select->srcpad);
2864         gst_pad_set_blocked_async (select->srcpad, FALSE, selector_blocked,
2865             NULL);
2866       }
2867     }
2868     GST_SOURCE_GROUP_UNLOCK (group);
2869   }
2870
2871   GST_PLAY_BIN_SHUTDOWN_UNLOCK (playbin);
2872
2873   return;
2874
2875 shutdown:
2876   {
2877     GST_DEBUG ("ignoring, we are shutting down");
2878     /* Request a flushing pad from playsink that we then link to the selector.
2879      * Then we unblock the selectors so that they stop with a WRONG_STATE
2880      * instead of a NOT_LINKED error.
2881      */
2882     GST_SOURCE_GROUP_LOCK (group);
2883     for (i = 0; i < PLAYBIN_STREAM_LAST; i++) {
2884       GstSourceSelect *select = &group->selector[i];
2885
2886       if (select->srcpad) {
2887         if (select->sinkpad == NULL) {
2888           GST_DEBUG_OBJECT (playbin, "requesting new flushing sink pad");
2889           select->sinkpad =
2890               gst_play_sink_request_pad (playbin->playsink,
2891               GST_PLAY_SINK_TYPE_FLUSHING);
2892           res = gst_pad_link (select->srcpad, select->sinkpad);
2893           GST_DEBUG_OBJECT (playbin, "linked flushing, result: %d", res);
2894         }
2895         GST_DEBUG_OBJECT (playbin, "unblocking %" GST_PTR_FORMAT,
2896             select->srcpad);
2897         gst_pad_set_blocked_async (select->srcpad, FALSE, selector_blocked,
2898             NULL);
2899       }
2900     }
2901     GST_SOURCE_GROUP_UNLOCK (group);
2902     return;
2903   }
2904 }
2905
2906 static void
2907 drained_cb (GstElement * decodebin, GstSourceGroup * group)
2908 {
2909   GstPlayBin *playbin;
2910
2911   playbin = group->playbin;
2912
2913   GST_DEBUG_OBJECT (playbin, "about to finish in group %p", group);
2914
2915   /* after this call, we should have a next group to activate or we EOS */
2916   g_signal_emit (G_OBJECT (playbin),
2917       gst_play_bin_signals[SIGNAL_ABOUT_TO_FINISH], 0, NULL);
2918
2919   /* now activate the next group. If the app did not set a uri, this will
2920    * fail and we can do EOS */
2921   setup_next_source (playbin, GST_STATE_PAUSED);
2922 }
2923
2924 /* Called when we must provide a list of factories to plug to @pad with @caps.
2925  * We first check if we have a sink that can handle the format and if we do, we
2926  * return NULL, to expose the pad. If we have no sink (or the sink does not
2927  * work), we return the list of elements that can connect. */
2928 static GValueArray *
2929 autoplug_factories_cb (GstElement * decodebin, GstPad * pad,
2930     GstCaps * caps, GstSourceGroup * group)
2931 {
2932   GstPlayBin *playbin;
2933   GList *mylist, *tmp;
2934   GValueArray *result;
2935
2936   playbin = group->playbin;
2937
2938   GST_DEBUG_OBJECT (playbin, "factories group %p for %s:%s, %" GST_PTR_FORMAT,
2939       group, GST_DEBUG_PAD_NAME (pad), caps);
2940
2941   /* filter out the elements based on the caps. */
2942   g_mutex_lock (playbin->elements_lock);
2943   gst_play_bin_update_elements_list (playbin);
2944   mylist =
2945       gst_element_factory_list_filter (playbin->elements, caps, GST_PAD_SINK,
2946       FALSE);
2947   g_mutex_unlock (playbin->elements_lock);
2948
2949   GST_DEBUG_OBJECT (playbin, "found factories %p", mylist);
2950   GST_PLUGIN_FEATURE_LIST_DEBUG (mylist);
2951
2952   result = g_value_array_new (g_list_length (mylist));
2953
2954   for (tmp = mylist; tmp; tmp = tmp->next) {
2955     GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (tmp->data);
2956     GValue val = { 0, };
2957
2958     g_value_init (&val, G_TYPE_OBJECT);
2959     g_value_set_object (&val, factory);
2960     g_value_array_append (result, &val);
2961     g_value_unset (&val);
2962   }
2963   gst_plugin_feature_list_free (mylist);
2964
2965   return result;
2966 }
2967
2968 /* autoplug-continue decides, if a pad has raw caps that can be exposed
2969  * directly or if further decoding is necessary. We use this to expose
2970  * supported subtitles directly */
2971
2972 /* FIXME 0.11: Remove the checks for ANY caps, a sink should specify
2973  * explicitely the caps it supports and if it claims to support ANY
2974  * caps it really should support everything */
2975 static gboolean
2976 autoplug_continue_cb (GstElement * element, GstPad * pad, GstCaps * caps,
2977     GstSourceGroup * group)
2978 {
2979   gboolean ret = TRUE;
2980   GstElement *sink;
2981   GstPad *sinkpad = NULL;
2982
2983   GST_PLAY_BIN_LOCK (group->playbin);
2984   GST_SOURCE_GROUP_LOCK (group);
2985
2986   if ((sink = group->playbin->text_sink))
2987     sinkpad = gst_element_get_static_pad (sink, "sink");
2988   if (sinkpad) {
2989     GstCaps *sinkcaps;
2990
2991     /* Ignore errors here, if a custom sink fails to go
2992      * to READY things are wrong and will error out later
2993      */
2994     if (GST_STATE (sink) < GST_STATE_READY)
2995       gst_element_set_state (sink, GST_STATE_READY);
2996
2997     sinkcaps = gst_pad_get_caps (sinkpad, NULL);
2998     if (!gst_caps_is_any (sinkcaps))
2999       ret = !gst_pad_accept_caps (sinkpad, caps);
3000     gst_caps_unref (sinkcaps);
3001     gst_object_unref (sinkpad);
3002   } else {
3003     GstCaps *subcaps = gst_subtitle_overlay_create_factory_caps ();
3004     ret = !gst_caps_can_intersect (caps, subcaps);
3005     gst_caps_unref (subcaps);
3006   }
3007   /* If autoplugging can stop don't do additional checks */
3008   if (!ret)
3009     goto done;
3010
3011   /* If this is from the subtitle uridecodebin we don't need to
3012    * check the audio and video sink */
3013   if (group->suburidecodebin
3014       && gst_object_has_ancestor (GST_OBJECT_CAST (element),
3015           GST_OBJECT_CAST (group->suburidecodebin)))
3016     goto done;
3017
3018   if ((sink = group->audio_sink)) {
3019     sinkpad = gst_element_get_static_pad (sink, "sink");
3020     if (sinkpad) {
3021       GstCaps *sinkcaps;
3022
3023       /* Ignore errors here, if a custom sink fails to go
3024        * to READY things are wrong and will error out later
3025        */
3026       if (GST_STATE (sink) < GST_STATE_READY)
3027         gst_element_set_state (sink, GST_STATE_READY);
3028
3029       sinkcaps = gst_pad_get_caps (sinkpad, NULL);
3030       if (!gst_caps_is_any (sinkcaps))
3031         ret = !gst_pad_accept_caps (sinkpad, caps);
3032       gst_caps_unref (sinkcaps);
3033       gst_object_unref (sinkpad);
3034     }
3035   }
3036   if (!ret)
3037     goto done;
3038
3039   if ((sink = group->video_sink)) {
3040     sinkpad = gst_element_get_static_pad (sink, "sink");
3041     if (sinkpad) {
3042       GstCaps *sinkcaps;
3043
3044       /* Ignore errors here, if a custom sink fails to go
3045        * to READY things are wrong and will error out later
3046        */
3047       if (GST_STATE (sink) < GST_STATE_READY)
3048         gst_element_set_state (sink, GST_STATE_READY);
3049
3050       sinkcaps = gst_pad_get_caps (sinkpad, NULL);
3051       if (!gst_caps_is_any (sinkcaps))
3052         ret = !gst_pad_accept_caps (sinkpad, caps);
3053       gst_caps_unref (sinkcaps);
3054       gst_object_unref (sinkpad);
3055     }
3056   }
3057
3058 done:
3059   GST_SOURCE_GROUP_UNLOCK (group);
3060   GST_PLAY_BIN_UNLOCK (group->playbin);
3061
3062   GST_DEBUG_OBJECT (group->playbin,
3063       "continue autoplugging group %p for %s:%s, %" GST_PTR_FORMAT ": %d",
3064       group, GST_DEBUG_PAD_NAME (pad), caps, ret);
3065
3066   return ret;
3067 }
3068
3069 static gboolean
3070 sink_accepts_caps (GstElement * sink, GstCaps * caps)
3071 {
3072   GstPad *sinkpad;
3073
3074   /* ... activate it ... We do this before adding it to the bin so that we
3075    * don't accidentally make it post error messages that will stop
3076    * everything. */
3077   if (GST_STATE (sink) < GST_STATE_READY &&
3078       gst_element_set_state (sink,
3079           GST_STATE_READY) == GST_STATE_CHANGE_FAILURE) {
3080     return FALSE;
3081   }
3082
3083   if ((sinkpad = gst_element_get_static_pad (sink, "sink"))) {
3084     /* Got the sink pad, now let's see if the element actually does accept the
3085      * caps that we have */
3086     if (!gst_pad_accept_caps (sinkpad, caps)) {
3087       gst_object_unref (sinkpad);
3088       return FALSE;
3089     }
3090     gst_object_unref (sinkpad);
3091   }
3092
3093   return TRUE;
3094 }
3095
3096 /* We are asked to select an element. See if the next element to check
3097  * is a sink. If this is the case, we see if the sink works by setting it to
3098  * READY. If the sink works, we return SELECT_EXPOSE to make decodebin
3099  * expose the raw pad so that we can setup the mixers. */
3100 static GstAutoplugSelectResult
3101 autoplug_select_cb (GstElement * decodebin, GstPad * pad,
3102     GstCaps * caps, GstElementFactory * factory, GstSourceGroup * group)
3103 {
3104   GstPlayBin *playbin;
3105   GstElement *element;
3106   const gchar *klass;
3107   GstPlaySinkType type;
3108   GstElement **sinkp;
3109
3110   playbin = group->playbin;
3111
3112   GST_DEBUG_OBJECT (playbin, "select group %p for %s:%s, %" GST_PTR_FORMAT,
3113       group, GST_DEBUG_PAD_NAME (pad), caps);
3114
3115   GST_DEBUG_OBJECT (playbin, "checking factory %s", GST_OBJECT_NAME (factory));
3116
3117   /* if it's not a sink, we just make decodebin try it */
3118   if (!gst_element_factory_list_is_type (factory,
3119           GST_ELEMENT_FACTORY_TYPE_SINK))
3120     return GST_AUTOPLUG_SELECT_TRY;
3121
3122   /* it's a sink, see if an instance of it actually works */
3123   GST_DEBUG_OBJECT (playbin, "we found a sink");
3124
3125   klass = gst_element_factory_get_klass (factory);
3126
3127   /* figure out the klass */
3128   if (strstr (klass, "Audio")) {
3129     GST_DEBUG_OBJECT (playbin, "we found an audio sink");
3130     type = GST_PLAY_SINK_TYPE_AUDIO;
3131     sinkp = &group->audio_sink;
3132   } else if (strstr (klass, "Video")) {
3133     GST_DEBUG_OBJECT (playbin, "we found a video sink");
3134     type = GST_PLAY_SINK_TYPE_VIDEO;
3135     sinkp = &group->video_sink;
3136   } else {
3137     /* unknown klass, skip this element */
3138     GST_WARNING_OBJECT (playbin, "unknown sink klass %s found", klass);
3139     return GST_AUTOPLUG_SELECT_SKIP;
3140   }
3141
3142   /* if we are asked to do visualisations and it's an audio sink, skip the
3143    * element. We can only do visualisations with raw sinks */
3144   if (gst_play_sink_get_flags (playbin->playsink) & GST_PLAY_FLAG_VIS) {
3145     if (type == GST_PLAY_SINK_TYPE_AUDIO) {
3146       GST_DEBUG_OBJECT (playbin, "skip audio sink because of vis");
3147       return GST_AUTOPLUG_SELECT_SKIP;
3148     }
3149   }
3150
3151   /* now see if we already have a sink element */
3152   GST_SOURCE_GROUP_LOCK (group);
3153   if (*sinkp) {
3154     GstElement *sink = gst_object_ref (*sinkp);
3155
3156     if (sink_accepts_caps (sink, caps)) {
3157       GST_DEBUG_OBJECT (playbin,
3158           "Existing sink '%s' accepts caps: %" GST_PTR_FORMAT,
3159           GST_ELEMENT_NAME (sink), caps);
3160       gst_object_unref (sink);
3161       GST_SOURCE_GROUP_UNLOCK (group);
3162       return GST_AUTOPLUG_SELECT_EXPOSE;
3163     } else {
3164       GST_DEBUG_OBJECT (playbin,
3165           "Existing sink '%s' does not accept caps: %" GST_PTR_FORMAT,
3166           GST_ELEMENT_NAME (sink), caps);
3167       gst_object_unref (sink);
3168       GST_SOURCE_GROUP_UNLOCK (group);
3169       return GST_AUTOPLUG_SELECT_SKIP;
3170     }
3171   }
3172   GST_DEBUG_OBJECT (playbin, "we have no pending sink, try to create one");
3173
3174   if ((element = gst_element_factory_create (factory, NULL)) == NULL) {
3175     GST_WARNING_OBJECT (playbin, "Could not create an element from %s",
3176         gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
3177     GST_SOURCE_GROUP_UNLOCK (group);
3178     return GST_AUTOPLUG_SELECT_SKIP;
3179   }
3180
3181   /* Check if the selected sink actually supports the
3182    * caps and can be set to READY*/
3183   if (!sink_accepts_caps (element, caps)) {
3184     gst_element_set_state (element, GST_STATE_NULL);
3185     gst_object_unref (element);
3186     GST_SOURCE_GROUP_UNLOCK (group);
3187     return GST_AUTOPLUG_SELECT_SKIP;
3188   }
3189
3190   /* remember the sink in the group now, the element is floating, we take
3191    * ownership now 
3192    *
3193    * store the sink in the group, we will configure it later when we
3194    * reconfigure the sink */
3195   GST_DEBUG_OBJECT (playbin, "remember sink");
3196   gst_object_ref_sink (element);
3197   *sinkp = element;
3198   GST_SOURCE_GROUP_UNLOCK (group);
3199
3200   /* tell decodebin to expose the pad because we are going to use this
3201    * sink */
3202   GST_DEBUG_OBJECT (playbin, "we found a working sink, expose pad");
3203
3204   return GST_AUTOPLUG_SELECT_EXPOSE;
3205 }
3206
3207 static void
3208 notify_source_cb (GstElement * uridecodebin, GParamSpec * pspec,
3209     GstSourceGroup * group)
3210 {
3211   GstPlayBin *playbin;
3212   GstElement *source;
3213
3214   playbin = group->playbin;
3215
3216   g_object_get (group->uridecodebin, "source", &source, NULL);
3217
3218   GST_OBJECT_LOCK (playbin);
3219   if (playbin->source)
3220     gst_object_unref (playbin->source);
3221   playbin->source = source;
3222   GST_OBJECT_UNLOCK (playbin);
3223
3224   g_object_notify (G_OBJECT (playbin), "source");
3225
3226   g_signal_emit (playbin, gst_play_bin_signals[SIGNAL_SOURCE_SETUP],
3227       0, playbin->source);
3228 }
3229
3230 /* must be called with the group lock */
3231 static gboolean
3232 group_set_locked_state_unlocked (GstPlayBin * playbin, GstSourceGroup * group,
3233     gboolean locked)
3234 {
3235   GST_DEBUG_OBJECT (playbin, "locked_state %d on group %p", locked, group);
3236
3237   if (group->uridecodebin)
3238     gst_element_set_locked_state (group->uridecodebin, locked);
3239   if (group->suburidecodebin)
3240     gst_element_set_locked_state (group->suburidecodebin, locked);
3241
3242   return TRUE;
3243 }
3244
3245 /* must be called with PLAY_BIN_LOCK */
3246 static gboolean
3247 activate_group (GstPlayBin * playbin, GstSourceGroup * group, GstState target)
3248 {
3249   GstElement *uridecodebin;
3250   GstElement *suburidecodebin = NULL;
3251   GstPlayFlags flags;
3252
3253   g_return_val_if_fail (group->valid, FALSE);
3254   g_return_val_if_fail (!group->active, FALSE);
3255
3256   GST_DEBUG_OBJECT (playbin, "activating group %p", group);
3257
3258   GST_SOURCE_GROUP_LOCK (group);
3259
3260   /* First set up the custom sources */
3261   if (playbin->audio_sink)
3262     group->audio_sink = gst_object_ref (playbin->audio_sink);
3263   if (playbin->video_sink)
3264     group->video_sink = gst_object_ref (playbin->video_sink);
3265
3266   g_list_free (group->stream_changed_pending);
3267   group->stream_changed_pending = NULL;
3268   if (!group->stream_changed_pending_lock)
3269     group->stream_changed_pending_lock = g_mutex_new ();
3270
3271   if (group->uridecodebin) {
3272     GST_DEBUG_OBJECT (playbin, "reusing existing uridecodebin");
3273     uridecodebin = group->uridecodebin;
3274     gst_element_set_state (uridecodebin, GST_STATE_READY);
3275     gst_bin_add (GST_BIN_CAST (playbin), gst_object_ref (uridecodebin));
3276   } else {
3277     GST_DEBUG_OBJECT (playbin, "making new uridecodebin");
3278     uridecodebin = gst_element_factory_make ("uridecodebin", NULL);
3279     if (!uridecodebin)
3280       goto no_decodebin;
3281     gst_bin_add (GST_BIN_CAST (playbin), uridecodebin);
3282     group->uridecodebin = gst_object_ref (uridecodebin);
3283   }
3284
3285   flags = gst_play_sink_get_flags (playbin->playsink);
3286
3287   g_object_set (uridecodebin,
3288       /* configure connection speed */
3289       "connection-speed", playbin->connection_speed / 1000,
3290       /* configure uri */
3291       "uri", group->uri,
3292       /* configure download buffering */
3293       "download", ((flags & GST_PLAY_FLAG_DOWNLOAD) != 0),
3294       /* configure buffering of demuxed/parsed data */
3295       "use-buffering", ((flags & GST_PLAY_FLAG_BUFFERING) != 0),
3296       /* configure buffering parameters */
3297       "buffer-duration", playbin->buffer_duration,
3298       "buffer-size", playbin->buffer_size,
3299       "ring-buffer-max-size", playbin->ring_buffer_max_size, NULL);
3300
3301   /* connect pads and other things */
3302   group->pad_added_id = g_signal_connect (uridecodebin, "pad-added",
3303       G_CALLBACK (pad_added_cb), group);
3304   group->pad_removed_id = g_signal_connect (uridecodebin, "pad-removed",
3305       G_CALLBACK (pad_removed_cb), group);
3306   group->no_more_pads_id = g_signal_connect (uridecodebin, "no-more-pads",
3307       G_CALLBACK (no_more_pads_cb), group);
3308   group->notify_source_id = g_signal_connect (uridecodebin, "notify::source",
3309       G_CALLBACK (notify_source_cb), group);
3310
3311   /* we have 1 pending no-more-pads */
3312   group->pending = 1;
3313
3314   /* is called when the uridecodebin is out of data and we can switch to the
3315    * next uri */
3316   group->drained_id =
3317       g_signal_connect (uridecodebin, "drained", G_CALLBACK (drained_cb),
3318       group);
3319
3320   /* will be called when a new media type is found. We return a list of decoders
3321    * including sinks for decodebin to try */
3322   group->autoplug_factories_id =
3323       g_signal_connect (uridecodebin, "autoplug-factories",
3324       G_CALLBACK (autoplug_factories_cb), group);
3325   group->autoplug_select_id =
3326       g_signal_connect (uridecodebin, "autoplug-select",
3327       G_CALLBACK (autoplug_select_cb), group);
3328   group->autoplug_continue_id =
3329       g_signal_connect (uridecodebin, "autoplug-continue",
3330       G_CALLBACK (autoplug_continue_cb), group);
3331
3332   if (group->suburi) {
3333     /* subtitles */
3334     if (group->suburidecodebin) {
3335       GST_DEBUG_OBJECT (playbin, "reusing existing suburidecodebin");
3336       suburidecodebin = group->suburidecodebin;
3337       gst_element_set_state (suburidecodebin, GST_STATE_READY);
3338       gst_bin_add (GST_BIN_CAST (playbin), gst_object_ref (suburidecodebin));
3339     } else {
3340       GST_DEBUG_OBJECT (playbin, "making new suburidecodebin");
3341       suburidecodebin = gst_element_factory_make ("uridecodebin", NULL);
3342       if (!suburidecodebin)
3343         goto no_decodebin;
3344
3345       gst_bin_add (GST_BIN_CAST (playbin), suburidecodebin);
3346       group->suburidecodebin = gst_object_ref (suburidecodebin);
3347     }
3348
3349     g_object_set (suburidecodebin,
3350         /* configure connection speed */
3351         "connection-speed", playbin->connection_speed,
3352         /* configure uri */
3353         "uri", group->suburi, NULL);
3354
3355     /* connect pads and other things */
3356     group->sub_pad_added_id = g_signal_connect (suburidecodebin, "pad-added",
3357         G_CALLBACK (pad_added_cb), group);
3358     group->sub_pad_removed_id = g_signal_connect (suburidecodebin,
3359         "pad-removed", G_CALLBACK (pad_removed_cb), group);
3360     group->sub_no_more_pads_id = g_signal_connect (suburidecodebin,
3361         "no-more-pads", G_CALLBACK (no_more_pads_cb), group);
3362
3363     group->sub_autoplug_continue_id =
3364         g_signal_connect (suburidecodebin, "autoplug-continue",
3365         G_CALLBACK (autoplug_continue_cb), group);
3366
3367     /* we have 2 pending no-more-pads */
3368     group->pending = 2;
3369     group->sub_pending = TRUE;
3370   } else {
3371     group->sub_pending = FALSE;
3372   }
3373
3374   /* release the group lock before setting the state of the decodebins, they
3375    * might fire signals in this thread that we need to handle with the
3376    * group_lock taken. */
3377   GST_SOURCE_GROUP_UNLOCK (group);
3378
3379   if (suburidecodebin) {
3380     if (gst_element_set_state (suburidecodebin,
3381             target) == GST_STATE_CHANGE_FAILURE) {
3382       GST_DEBUG_OBJECT (playbin,
3383           "failed state change of subtitle uridecodebin");
3384       GST_SOURCE_GROUP_LOCK (group);
3385
3386       REMOVE_SIGNAL (group->suburidecodebin, group->sub_pad_added_id);
3387       REMOVE_SIGNAL (group->suburidecodebin, group->sub_pad_removed_id);
3388       REMOVE_SIGNAL (group->suburidecodebin, group->sub_no_more_pads_id);
3389       REMOVE_SIGNAL (group->suburidecodebin, group->sub_autoplug_continue_id);
3390       /* Might already be removed because of an error message */
3391       if (GST_OBJECT_PARENT (suburidecodebin) == GST_OBJECT_CAST (playbin))
3392         gst_bin_remove (GST_BIN_CAST (playbin), suburidecodebin);
3393       if (group->sub_pending) {
3394         group->pending--;
3395         group->sub_pending = FALSE;
3396       }
3397       gst_element_set_state (suburidecodebin, GST_STATE_READY);
3398       GST_SOURCE_GROUP_UNLOCK (group);
3399     }
3400   }
3401   if (gst_element_set_state (uridecodebin, target) == GST_STATE_CHANGE_FAILURE)
3402     goto uridecodebin_failure;
3403
3404   GST_SOURCE_GROUP_LOCK (group);
3405   /* alow state changes of the playbin2 affect the group elements now */
3406   group_set_locked_state_unlocked (playbin, group, FALSE);
3407   group->active = TRUE;
3408   GST_SOURCE_GROUP_UNLOCK (group);
3409
3410   return TRUE;
3411
3412   /* ERRORS */
3413 no_decodebin:
3414   {
3415     GstMessage *msg;
3416
3417     /* delete any custom sinks we might have */
3418     if (group->audio_sink) {
3419       /* If this is a automatically created sink set it to NULL */
3420       if (group->audio_sink != playbin->audio_sink)
3421         gst_element_set_state (group->audio_sink, GST_STATE_NULL);
3422       gst_object_unref (group->audio_sink);
3423     }
3424     group->audio_sink = NULL;
3425     if (group->video_sink) {
3426       /* If this is a automatically created sink set it to NULL */
3427       if (group->video_sink != playbin->video_sink)
3428         gst_element_set_state (group->video_sink, GST_STATE_NULL);
3429       gst_object_unref (group->video_sink);
3430     }
3431     group->video_sink = NULL;
3432
3433     GST_SOURCE_GROUP_UNLOCK (group);
3434     msg =
3435         gst_missing_element_message_new (GST_ELEMENT_CAST (playbin),
3436         "uridecodebin");
3437     gst_element_post_message (GST_ELEMENT_CAST (playbin), msg);
3438
3439     GST_ELEMENT_ERROR (playbin, CORE, MISSING_PLUGIN,
3440         (_("Could not create \"uridecodebin\" element.")), (NULL));
3441     return FALSE;
3442   }
3443 uridecodebin_failure:
3444   {
3445     /* delete any custom sinks we might have */
3446     if (group->audio_sink) {
3447       /* If this is a automatically created sink set it to NULL */
3448       if (group->audio_sink != playbin->audio_sink)
3449         gst_element_set_state (group->audio_sink, GST_STATE_NULL);
3450       gst_object_unref (group->audio_sink);
3451     }
3452     group->audio_sink = NULL;
3453     if (group->video_sink) {
3454       /* If this is a automatically created sink set it to NULL */
3455       if (group->video_sink != playbin->video_sink)
3456         gst_element_set_state (group->video_sink, GST_STATE_NULL);
3457       gst_object_unref (group->video_sink);
3458     }
3459     group->video_sink = NULL;
3460
3461     GST_DEBUG_OBJECT (playbin, "failed state change of uridecodebin");
3462     return FALSE;
3463   }
3464 }
3465
3466 /* unlink a group of uridecodebins from the sink.
3467  * must be called with PLAY_BIN_LOCK */
3468 static gboolean
3469 deactivate_group (GstPlayBin * playbin, GstSourceGroup * group)
3470 {
3471   gint i;
3472
3473   g_return_val_if_fail (group->valid, FALSE);
3474   g_return_val_if_fail (group->active, FALSE);
3475
3476   GST_DEBUG_OBJECT (playbin, "unlinking group %p", group);
3477
3478   GST_SOURCE_GROUP_LOCK (group);
3479   group->active = FALSE;
3480   for (i = 0; i < PLAYBIN_STREAM_LAST; i++) {
3481     GstSourceSelect *select = &group->selector[i];
3482
3483     GST_DEBUG_OBJECT (playbin, "unlinking selector %s", select->media_list[0]);
3484
3485     if (select->srcpad) {
3486       if (select->sinkpad) {
3487         GST_LOG_OBJECT (playbin, "unlinking from sink");
3488         gst_pad_unlink (select->srcpad, select->sinkpad);
3489
3490         /* release back */
3491         GST_LOG_OBJECT (playbin, "release sink pad");
3492         gst_play_sink_release_pad (playbin->playsink, select->sinkpad);
3493         select->sinkpad = NULL;
3494       }
3495
3496       gst_object_unref (select->srcpad);
3497       select->srcpad = NULL;
3498     }
3499
3500     if (select->selector) {
3501       gint n;
3502
3503       /* release and unref requests pad from the selector */
3504       for (n = 0; n < select->channels->len; n++) {
3505         GstPad *sinkpad = g_ptr_array_index (select->channels, n);
3506
3507         gst_element_release_request_pad (select->selector, sinkpad);
3508         gst_object_unref (sinkpad);
3509       }
3510       g_ptr_array_set_size (select->channels, 0);
3511
3512       gst_element_set_state (select->selector, GST_STATE_NULL);
3513       gst_bin_remove (GST_BIN_CAST (playbin), select->selector);
3514       select->selector = NULL;
3515     }
3516   }
3517   /* delete any custom sinks we might have */
3518   if (group->audio_sink) {
3519     /* If this is a automatically created sink set it to NULL */
3520     if (group->audio_sink != playbin->audio_sink)
3521       gst_element_set_state (group->audio_sink, GST_STATE_NULL);
3522     gst_object_unref (group->audio_sink);
3523   }
3524   group->audio_sink = NULL;
3525   if (group->video_sink) {
3526     /* If this is a automatically created sink set it to NULL */
3527     if (group->video_sink != playbin->video_sink)
3528       gst_element_set_state (group->video_sink, GST_STATE_NULL);
3529     gst_object_unref (group->video_sink);
3530   }
3531   group->video_sink = NULL;
3532
3533   if (group->uridecodebin) {
3534     REMOVE_SIGNAL (group->uridecodebin, group->pad_added_id);
3535     REMOVE_SIGNAL (group->uridecodebin, group->pad_removed_id);
3536     REMOVE_SIGNAL (group->uridecodebin, group->no_more_pads_id);
3537     REMOVE_SIGNAL (group->uridecodebin, group->notify_source_id);
3538     REMOVE_SIGNAL (group->uridecodebin, group->drained_id);
3539     REMOVE_SIGNAL (group->uridecodebin, group->autoplug_factories_id);
3540     REMOVE_SIGNAL (group->uridecodebin, group->autoplug_select_id);
3541     REMOVE_SIGNAL (group->uridecodebin, group->autoplug_continue_id);
3542     gst_bin_remove (GST_BIN_CAST (playbin), group->uridecodebin);
3543   }
3544
3545   if (group->suburidecodebin) {
3546     REMOVE_SIGNAL (group->suburidecodebin, group->sub_pad_added_id);
3547     REMOVE_SIGNAL (group->suburidecodebin, group->sub_pad_removed_id);
3548     REMOVE_SIGNAL (group->suburidecodebin, group->sub_no_more_pads_id);
3549     REMOVE_SIGNAL (group->suburidecodebin, group->sub_autoplug_continue_id);
3550
3551     /* Might already be removed because of errors */
3552     if (GST_OBJECT_PARENT (group->suburidecodebin) == GST_OBJECT_CAST (playbin))
3553       gst_bin_remove (GST_BIN_CAST (playbin), group->suburidecodebin);
3554   }
3555
3556   GST_SOURCE_GROUP_UNLOCK (group);
3557
3558   return TRUE;
3559 }
3560
3561 /* setup the next group to play, this assumes the next_group is valid and
3562  * configured. It swaps out the current_group and activates the valid
3563  * next_group. */
3564 static gboolean
3565 setup_next_source (GstPlayBin * playbin, GstState target)
3566 {
3567   GstSourceGroup *new_group, *old_group;
3568
3569   GST_DEBUG_OBJECT (playbin, "setup sources");
3570
3571   /* see if there is a next group */
3572   GST_PLAY_BIN_LOCK (playbin);
3573   new_group = playbin->next_group;
3574   if (!new_group || !new_group->valid)
3575     goto no_next_group;
3576
3577   /* first unlink the current source, if any */
3578   old_group = playbin->curr_group;
3579   if (old_group && old_group->valid && old_group->active) {
3580     gst_play_bin_update_cached_duration (playbin);
3581     /* unlink our pads with the sink */
3582     deactivate_group (playbin, old_group);
3583     old_group->valid = FALSE;
3584   }
3585
3586   /* swap old and new */
3587   playbin->curr_group = new_group;
3588   playbin->next_group = old_group;
3589
3590   /* activate the new group */
3591   if (!activate_group (playbin, new_group, target))
3592     goto activate_failed;
3593
3594   GST_PLAY_BIN_UNLOCK (playbin);
3595
3596   return TRUE;
3597
3598   /* ERRORS */
3599 no_next_group:
3600   {
3601     GST_DEBUG_OBJECT (playbin, "no next group");
3602     if (target == GST_STATE_READY && new_group && new_group->uri == NULL)
3603       GST_ELEMENT_ERROR (playbin, RESOURCE, NOT_FOUND, ("No URI set"), (NULL));
3604     GST_PLAY_BIN_UNLOCK (playbin);
3605     return FALSE;
3606   }
3607 activate_failed:
3608   {
3609     GST_DEBUG_OBJECT (playbin, "activate failed");
3610     GST_PLAY_BIN_UNLOCK (playbin);
3611     return FALSE;
3612   }
3613 }
3614
3615 /* The group that is currently playing is copied again to the
3616  * next_group so that it will start playing the next time.
3617  */
3618 static gboolean
3619 save_current_group (GstPlayBin * playbin)
3620 {
3621   GstSourceGroup *curr_group;
3622
3623   GST_DEBUG_OBJECT (playbin, "save current group");
3624
3625   /* see if there is a current group */
3626   GST_PLAY_BIN_LOCK (playbin);
3627   curr_group = playbin->curr_group;
3628   if (curr_group && curr_group->valid) {
3629     /* unlink our pads with the sink */
3630     deactivate_group (playbin, curr_group);
3631   }
3632   /* swap old and new */
3633   playbin->curr_group = playbin->next_group;
3634   playbin->next_group = curr_group;
3635   GST_PLAY_BIN_UNLOCK (playbin);
3636
3637   return TRUE;
3638 }
3639
3640 /* clear the locked state from all groups. This function is called before a
3641  * state change to NULL is performed on them. */
3642 static gboolean
3643 groups_set_locked_state (GstPlayBin * playbin, gboolean locked)
3644 {
3645   GST_DEBUG_OBJECT (playbin, "setting locked state to %d on all groups",
3646       locked);
3647
3648   GST_PLAY_BIN_LOCK (playbin);
3649   GST_SOURCE_GROUP_LOCK (playbin->curr_group);
3650   group_set_locked_state_unlocked (playbin, playbin->curr_group, locked);
3651   GST_SOURCE_GROUP_UNLOCK (playbin->curr_group);
3652   GST_SOURCE_GROUP_LOCK (playbin->next_group);
3653   group_set_locked_state_unlocked (playbin, playbin->next_group, locked);
3654   GST_SOURCE_GROUP_UNLOCK (playbin->next_group);
3655   GST_PLAY_BIN_UNLOCK (playbin);
3656
3657   return TRUE;
3658 }
3659
3660 static GstStateChangeReturn
3661 gst_play_bin_change_state (GstElement * element, GstStateChange transition)
3662 {
3663   GstStateChangeReturn ret;
3664   GstPlayBin *playbin;
3665   gboolean do_save = FALSE;
3666
3667   playbin = GST_PLAY_BIN (element);
3668
3669   switch (transition) {
3670     case GST_STATE_CHANGE_NULL_TO_READY:
3671       memset (&playbin->duration, 0, sizeof (playbin->duration));
3672       break;
3673     case GST_STATE_CHANGE_READY_TO_PAUSED:
3674       GST_LOG_OBJECT (playbin, "clearing shutdown flag");
3675       memset (&playbin->duration, 0, sizeof (playbin->duration));
3676       g_atomic_int_set (&playbin->shutdown, 0);
3677
3678       if (!setup_next_source (playbin, GST_STATE_READY)) {
3679         ret = GST_STATE_CHANGE_FAILURE;
3680         goto failure;
3681       }
3682       break;
3683     case GST_STATE_CHANGE_PAUSED_TO_READY:
3684     async_down:
3685       /* FIXME unlock our waiting groups */
3686       GST_LOG_OBJECT (playbin, "setting shutdown flag");
3687       g_atomic_int_set (&playbin->shutdown, 1);
3688       memset (&playbin->duration, 0, sizeof (playbin->duration));
3689
3690       /* wait for all callbacks to end by taking the lock.
3691        * No dynamic (critical) new callbacks will
3692        * be able to happen as we set the shutdown flag. */
3693       GST_PLAY_BIN_DYN_LOCK (playbin);
3694       GST_LOG_OBJECT (playbin, "dynamic lock taken, we can continue shutdown");
3695       GST_PLAY_BIN_DYN_UNLOCK (playbin);
3696       if (!do_save)
3697         break;
3698     case GST_STATE_CHANGE_READY_TO_NULL:
3699       /* we go async to PAUSED, so if that fails, we never make it to PAUSED
3700        * an no state change PAUSED to READY passes here,
3701        * though it is a nice-to-have ... */
3702       if (!g_atomic_int_get (&playbin->shutdown)) {
3703         do_save = TRUE;
3704         goto async_down;
3705       }
3706       memset (&playbin->duration, 0, sizeof (playbin->duration));
3707
3708       /* unlock so that all groups go to NULL */
3709       groups_set_locked_state (playbin, FALSE);
3710       break;
3711     default:
3712       break;
3713   }
3714
3715   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
3716   if (ret == GST_STATE_CHANGE_FAILURE)
3717     goto failure;
3718
3719   switch (transition) {
3720     case GST_STATE_CHANGE_READY_TO_PAUSED:
3721       break;
3722     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
3723       /* FIXME Release audio device when we implement that */
3724       break;
3725     case GST_STATE_CHANGE_PAUSED_TO_READY:
3726       save_current_group (playbin);
3727       break;
3728     case GST_STATE_CHANGE_READY_TO_NULL:
3729     {
3730       guint i;
3731
3732       /* also do missed state change down to READY */
3733       if (do_save)
3734         save_current_group (playbin);
3735       /* Deactive the groups, set the uridecodebins to NULL
3736        * and unref them.
3737        */
3738       for (i = 0; i < 2; i++) {
3739         if (playbin->groups[i].active && playbin->groups[i].valid) {
3740           deactivate_group (playbin, &playbin->groups[i]);
3741           playbin->groups[i].valid = FALSE;
3742         }
3743
3744         if (playbin->groups[i].uridecodebin) {
3745           gst_element_set_state (playbin->groups[i].uridecodebin,
3746               GST_STATE_NULL);
3747           gst_object_unref (playbin->groups[i].uridecodebin);
3748           playbin->groups[i].uridecodebin = NULL;
3749         }
3750
3751         if (playbin->groups[i].suburidecodebin) {
3752           gst_element_set_state (playbin->groups[i].suburidecodebin,
3753               GST_STATE_NULL);
3754           gst_object_unref (playbin->groups[i].suburidecodebin);
3755           playbin->groups[i].suburidecodebin = NULL;
3756         }
3757       }
3758
3759       /* Set our sinks back to NULL, they might not be child of playbin */
3760       if (playbin->audio_sink)
3761         gst_element_set_state (playbin->audio_sink, GST_STATE_NULL);
3762       if (playbin->video_sink)
3763         gst_element_set_state (playbin->video_sink, GST_STATE_NULL);
3764       if (playbin->text_sink)
3765         gst_element_set_state (playbin->text_sink, GST_STATE_NULL);
3766
3767       /* make sure the groups don't perform a state change anymore until we
3768        * enable them again */
3769       groups_set_locked_state (playbin, TRUE);
3770       break;
3771     }
3772     default:
3773       break;
3774   }
3775
3776   return ret;
3777
3778   /* ERRORS */
3779 failure:
3780   {
3781     if (transition == GST_STATE_CHANGE_READY_TO_PAUSED) {
3782       GstSourceGroup *curr_group;
3783
3784       curr_group = playbin->curr_group;
3785       if (curr_group && curr_group->active && curr_group->valid) {
3786         /* unlink our pads with the sink */
3787         deactivate_group (playbin, curr_group);
3788         curr_group->valid = FALSE;
3789       }
3790
3791       /* Swap current and next group back */
3792       playbin->curr_group = playbin->next_group;
3793       playbin->next_group = curr_group;
3794     }
3795     return ret;
3796   }
3797 }
3798
3799 gboolean
3800 gst_play_bin2_plugin_init (GstPlugin * plugin)
3801 {
3802   GST_DEBUG_CATEGORY_INIT (gst_play_bin_debug, "playbin2", 0, "play bin");
3803
3804   return gst_element_register (plugin, "playbin2", GST_RANK_NONE,
3805       GST_TYPE_PLAY_BIN);
3806 }