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