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