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