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