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