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