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