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