gst_plugins_base/gst/playback/gstplaybin2.c
branchRCL_3
changeset 30 7e817e7e631c
parent 29 567bb019e3e3
equal deleted inserted replaced
29:567bb019e3e3 30:7e817e7e631c
    18  */
    18  */
    19 
    19 
    20 /**
    20 /**
    21  * SECTION:element-playbin2
    21  * SECTION:element-playbin2
    22  *
    22  *
    23  * Playbin2 provides a stand-alone everything-in-one abstraction for an
    23  * <refsect2>
       
    24  * <para>
       
    25  * Playbin provides a stand-alone everything-in-one abstraction for an
    24  * audio and/or video player.
    26  * audio and/or video player.
    25  *
    27  * </para>
    26  * At this stage, playbin2 is considered UNSTABLE. The API provided in the
    28  * <para>
    27  * signals and properties may yet change in the near future. When playbin2
       
    28  * is stable, it will probably replace #playbin
       
    29  *
       
    30  * It can handle both audio and video files and features
    29  * It can handle both audio and video files and features
    31  * <itemizedlist>
    30  * <itemizedlist>
    32  * <listitem>
    31  * <listitem>
    33  * automatic file type recognition and based on that automatic
    32  * automatic file type recognition and based on that automatic
    34  * selection and usage of the right audio/video/subtitle demuxers/decoders
    33  * selection and usage of the right audio/video/subtitle demuxers/decoders
    35  * </listitem>
    34  * </listitem>
    36  * <listitem>
    35  * <listitem>
    37  * visualisations for audio files
    36  * visualisations for audio files
    38  * </listitem>
    37  * </listitem>
    39  * <listitem>
    38  * <listitem>
    40  * subtitle support for video files. Subtitles can be store in external
    39  * subtitle support for video files
    41  * files.
       
    42  * </listitem>
    40  * </listitem>
    43  * <listitem>
    41  * <listitem>
    44  * stream selection between different video/audio/subtitles streams
    42  * stream selection between different audio/subtitles streams
    45  * </listitem>
    43  * </listitem>
    46  * <listitem>
    44  * <listitem>
    47  * meta info (tag) extraction
    45  * meta info (tag) extraction
    48  * </listitem>
    46  * </listitem>
    49  * <listitem>
    47  * <listitem>
    51  * </listitem>
    49  * </listitem>
    52  * <listitem>
    50  * <listitem>
    53  * buffering when playing streams over a network
    51  * buffering when playing streams over a network
    54  * </listitem>
    52  * </listitem>
    55  * <listitem>
    53  * <listitem>
    56  * volume control with mute option
    54  * volume control
    57  * </listitem>
    55  * </listitem>
    58  * </itemizedlist>
    56  * </itemizedlist>
    59  *
    57  * </para>
    60  * <refsect2>
       
    61  * <title>Usage</title>
    58  * <title>Usage</title>
    62  * <para>
    59  * <para>
    63  * A playbin element can be created just like any other element using
    60  * A playbin element can be created just like any other element using
    64  * gst_element_factory_make(). The file/URI to play should be set via the #GstPlayBin2:uri
    61  * gst_element_factory_make(). The file/URI to play should be set via the "uri"
    65  * property. This must be an absolute URI, relative file paths are not allowed.
    62  * property. This must be an absolute URI, relative file paths are not allowed.
    66  * Example URIs are file:///home/joe/movie.avi or http://www.joedoe.com/foo.ogg
    63  * Example URIs are file:///home/joe/movie.avi or http://www.joedoe.com/foo.ogg
    67  *
    64  * </para>
       
    65  * <para>
    68  * Playbin is a #GstPipeline. It will notify the application of everything
    66  * Playbin is a #GstPipeline. It will notify the application of everything
    69  * that's happening (errors, end of stream, tags found, state changes, etc.)
    67  * that's happening (errors, end of stream, tags found, state changes, etc.)
    70  * by posting messages on its #GstBus. The application needs to watch the
    68  * by posting messages on its #GstBus. The application needs to watch the
    71  * bus.
    69  * bus.
    72  *
    70  * </para>
       
    71  * <para>
    73  * Playback can be initiated by setting the element to PLAYING state using
    72  * Playback can be initiated by setting the element to PLAYING state using
    74  * gst_element_set_state(). Note that the state change will take place in
    73  * gst_element_set_state(). Note that the state change will take place in
    75  * the background in a separate thread, when the function returns playback
    74  * the background in a separate thread, when the function returns playback
    76  * is probably not happening yet and any errors might not have occured yet.
    75  * is probably not happening yet and any errors might not have occured yet.
    77  * Applications using playbin should ideally be written to deal with things
    76  * Applications using playbin should ideally be written to deal with things
    78  * completely asynchroneous.
    77  * completely asynchroneous.
    79  *
    78  * </para>
       
    79  * <para>
    80  * When playback has finished (an EOS message has been received on the bus)
    80  * When playback has finished (an EOS message has been received on the bus)
    81  * or an error has occured (an ERROR message has been received on the bus) or
    81  * or an error has occured (an ERROR message has been received on the bus) or
    82  * the user wants to play a different track, playbin should be set back to
    82  * the user wants to play a different track, playbin should be set back to
    83  * READY or NULL state, then the #GstPlayBin2:uri property should be set to the 
    83  * READY or NULL state, then the "uri" property should be set to the new
    84  * new location and then playbin be set to PLAYING state again.
    84  * location and then playbin be set to PLAYING state again.
    85  *
    85  * </para>
       
    86  * <para>
    86  * Seeking can be done using gst_element_seek_simple() or gst_element_seek()
    87  * Seeking can be done using gst_element_seek_simple() or gst_element_seek()
    87  * on the playbin element. Again, the seek will not be executed
    88  * on the playbin element. Again, the seek will not be executed
    88  * instantaneously, but will be done in a background thread. When the seek
    89  * instantaneously, but will be done in a background thread. When the seek
    89  * call returns the seek will most likely still be in process. An application
    90  * call returns the seek will most likely still be in process. An application
    90  * may wait for the seek to finish (or fail) using gst_element_get_state() with
    91  * may wait for the seek to finish (or fail) using gst_element_get_state() with
    91  * -1 as the timeout, but this will block the user interface and is not
    92  * -1 as the timeout, but this will block the user interface and is not
    92  * recommended at all.
    93  * recommended at all.
    93  *
    94  * </para>
       
    95  * <para>
    94  * Applications may query the current position and duration of the stream
    96  * Applications may query the current position and duration of the stream
    95  * via gst_element_query_position() and gst_element_query_duration() and
    97  * via gst_element_query_position() and gst_element_query_duration() and
    96  * setting the format passed to GST_FORMAT_TIME. If the query was successful,
    98  * setting the format passed to GST_FORMAT_TIME. If the query was successful,
    97  * the duration or position will have been returned in units of nanoseconds.
    99  * the duration or position will have been returned in units of nanoseconds.
    98  * </para>
   100  * </para>
    99  * </refsect2>
       
   100  * <refsect2>
       
   101  * <title>Advanced Usage: specifying the audio and video sink</title>
   101  * <title>Advanced Usage: specifying the audio and video sink</title>
   102  * <para>
   102  * <para>
   103  * By default, if no audio sink or video sink has been specified via the
   103  * By default, if no audio sink or video sink has been specified via the
   104  * #GstPlayBin2:audio-sink or #GstPlayBin2:video-sink property, playbin will use the autoaudiosink
   104  * "audio-sink" or "video-sink" property, playbin will use the autoaudiosink
   105  * and autovideosink elements to find the first-best available output method.
   105  * and autovideosink elements to find the first-best available output method.
   106  * This should work in most cases, but is not always desirable. Often either
   106  * This should work in most cases, but is not always desirable. Often either
   107  * the user or application might want to specify more explicitly what to use
   107  * the user or application might want to specify more explicitly what to use
   108  * for audio and video output.
   108  * for audio and video output.
   109  *
   109  * </para>
       
   110  * <para>
   110  * If the application wants more control over how audio or video should be
   111  * If the application wants more control over how audio or video should be
   111  * output, it may create the audio/video sink elements itself (for example
   112  * output, it may create the audio/video sink elements itself (for example
   112  * using gst_element_factory_make()) and provide them to playbin using the
   113  * using gst_element_factory_make()) and provide them to playbin using the
   113  * #GstPlayBin2:audio-sink or #GstPlayBin2:video-sink property.
   114  * "audio-sink" or "video-sink" property.
   114  *
   115  * </para>
       
   116  * <para>
   115  * GNOME-based applications, for example, will usually want to create
   117  * GNOME-based applications, for example, will usually want to create
   116  * gconfaudiosink and gconfvideosink elements and make playbin use those,
   118  * gconfaudiosink and gconfvideosink elements and make playbin use those,
   117  * so that output happens to whatever the user has configured in the GNOME
   119  * so that output happens to whatever the user has configured in the GNOME
   118  * Multimedia System Selector configuration dialog.
   120  * Multimedia System Selector confinguration dialog.
   119  *
   121  * </para>
       
   122  * <para>
   120  * The sink elements do not necessarily need to be ready-made sinks. It is
   123  * The sink elements do not necessarily need to be ready-made sinks. It is
   121  * possible to create container elements that look like a sink to playbin,
   124  * possible to create container elements that look like a sink to playbin,
   122  * but in reality contain a number of custom elements linked together. This
   125  * but in reality contain a number of custom elements linked together. This
   123  * can be achieved by creating a #GstBin and putting elements in there and
   126  * can be achieved by creating a #GstBin and putting elements in there and
   124  * linking them, and then creating a sink #GstGhostPad for the bin and pointing
   127  * linking them, and then creating a sink #GstGhostPad for the bin and pointing
   125  * it to the sink pad of the first element within the bin. This can be used
   128  * it to the sink pad of the first element within the bin. This can be used
   126  * for a number of purposes, for example to force output to a particular
   129  * for a number of purposes, for example to force output to a particular
   127  * format or to modify or observe the data before it is output.
   130  * format or to modify or observe the data before it is output.
   128  *
   131  * </para>
       
   132  * <para>
   129  * It is also possible to 'suppress' audio and/or video output by using
   133  * It is also possible to 'suppress' audio and/or video output by using
   130  * 'fakesink' elements (or capture it from there using the fakesink element's
   134  * 'fakesink' elements (or capture it from there using the fakesink element's
   131  * "handoff" signal, which, nota bene, is fired from the streaming thread!).
   135  * "handoff" signal, which, nota bene, is fired from the streaming thread!).
   132  * </para>
   136  * </para>
   133  * </refsect2>
       
   134  * <refsect2>
       
   135  * <title>Retrieving Tags and Other Meta Data</title>
   137  * <title>Retrieving Tags and Other Meta Data</title>
   136  * <para>
   138  * <para>
   137  * Most of the common meta data (artist, title, etc.) can be retrieved by
   139  * Most of the common meta data (artist, title, etc.) can be retrieved by
   138  * watching for TAG messages on the pipeline's bus (see above).
   140  * watching for TAG messages on the pipeline's bus (see above).
   139  *
   141  * </para>
       
   142  * <para>
   140  * Other more specific meta information like width/height/framerate of video
   143  * Other more specific meta information like width/height/framerate of video
   141  * streams or samplerate/number of channels of audio streams can be obtained
   144  * streams or samplerate/number of channels of audio streams can be obtained
   142  * from the negotiated caps on the sink pads of the sinks.
   145  * using the "stream-info" property, which will return a GList of stream info
   143  * </para>
   146  * objects, one for each stream. These are opaque objects that can only be
   144  * </refsect2>
   147  * accessed via the standard GObject property interface, ie. g_object_get().
   145  * <refsect2>
   148  * Each stream info object has the following properties:
       
   149  * <itemizedlist>
       
   150  * <listitem>"object" (GstObject) (the decoder source pad usually)</listitem>
       
   151  * <listitem>"type" (enum) (if this is an audio/video/subtitle stream)</listitem>
       
   152  * <listitem>"decoder" (string) (name of decoder used to decode this stream)</listitem>
       
   153  * <listitem>"mute" (boolean) (to mute or unmute this stream)</listitem>
       
   154  * <listitem>"caps" (GstCaps) (caps of the decoded stream)</listitem>
       
   155  * <listitem>"language-code" (string) (ISO-639 language code for this stream, mostly used for audio/subtitle streams)</listitem>
       
   156  * <listitem>"codec" (string) (format this stream was encoded in)</listitem>
       
   157  * </itemizedlist>
       
   158  * Stream information from the stream-info properties is best queried once
       
   159  * playbin has changed into PAUSED or PLAYING state (which can be detected
       
   160  * via a state-changed message on the bus where old_state=READY and
       
   161  * new_state=PAUSED), since before that the list might not be complete yet or
       
   162  * not contain all available information (like language-codes).
       
   163  * </para>
   146  * <title>Buffering</title>
   164  * <title>Buffering</title>
       
   165  * <para>
   147  * Playbin handles buffering automatically for the most part, but applications
   166  * Playbin handles buffering automatically for the most part, but applications
   148  * need to handle parts of the buffering process as well. Whenever playbin is
   167  * need to handle parts of the buffering process as well. Whenever playbin is
   149  * buffering, it will post BUFFERING messages on the bus with a percentage
   168  * buffering, it will post BUFFERING messages on the bus with a percentage
   150  * value that shows the progress of the buffering process. Applications need
   169  * value that shows the progress of the buffering process. Applications need
   151  * to set playbin to PLAYING or PAUSED state in response to these messages.
   170  * to set playbin to PLAYING or PAUSED state in response to these messages.
   152  * They may also want to convey the buffering progress to the user in some
   171  * They may also want to convey the buffering progress to the user in some
   153  * way. Here is how to extract the percentage information from the message
   172  * way. Here is how to extract the percentage information from the message
   154  * (requires GStreamer >= 0.10.11):
   173  * (requires GStreamer >= 0.10.11):
   155  * |[
   174  * </para>
       
   175  * <para>
       
   176  * <programlisting>
   156  * switch (GST_MESSAGE_TYPE (msg)) {
   177  * switch (GST_MESSAGE_TYPE (msg)) {
   157  *   case GST_MESSAGE_BUFFERING: {
   178  *   case GST_MESSAGE_BUFFERING: {
   158  *     gint percent = 0;
   179  *     gint percent = 0;
   159  *     gst_message_parse_buffering (msg, &amp;percent);
   180  *     gst_message_parse_buffering (msg, &amp;percent);
   160  *     g_print ("Buffering (%%u percent done)", percent);
   181  *     g_print ("Buffering (%%u percent done)", percent);
   161  *     break;
   182  *     break;
   162  *   }
   183  *   }
   163  *   ...
   184  *   ...
   164  * }
   185  * }
   165  * ]|
   186  * </programlisting>
   166  * Note that applications should keep/set the pipeline in the PAUSED state when
   187  * Note that applications should keep/set the pipeline in the PAUSED state when
   167  * a BUFFERING message is received with a buffer percent value < 100 and set
   188  * a BUFFERING message is received with a buffer percent value < 100 and set
   168  * the pipeline back to PLAYING state when a BUFFERING message with a value
   189  * the pipeline back to PLAYING state when a BUFFERING message with a value
   169  * of 100 percent is received (if PLAYING is the desired state, that is).
   190  * of 100 percent is received (if PLAYING is the desired state, that is).
   170  * </refsect2>
   191  * </para>
   171  * <refsect2>
       
   172  * <title>Embedding the video window in your application</title>
   192  * <title>Embedding the video window in your application</title>
       
   193  * <para>
   173  * By default, playbin (or rather the video sinks used) will create their own
   194  * By default, playbin (or rather the video sinks used) will create their own
   174  * window. Applications will usually want to force output to a window of their
   195  * window. Applications will usually want to force output to a window of their
   175  * own, however. This can be done using the #GstXOverlay interface, which most
   196  * own, however. This can be done using the GstXOverlay interface, which most
   176  * video sinks implement. See the documentation there for more details.
   197  * video sinks implement. See the documentation there for more details.
   177  * </refsect2>
   198  * </para>
   178  * <refsect2>
       
   179  * <title>Specifying which CD/DVD device to use</title>
   199  * <title>Specifying which CD/DVD device to use</title>
       
   200  * <para>
   180  * The device to use for CDs/DVDs needs to be set on the source element
   201  * The device to use for CDs/DVDs needs to be set on the source element
   181  * playbin creates before it is opened. The only way to do this at the moment
   202  * playbin creates before it is opened. The only way to do this at the moment
   182  * is to connect to playbin's "notify::source" signal, which will be emitted
   203  * is to connect to playbin's "notify::source" signal, which will be emitted
   183  * by playbin when it has created the source element for a particular URI.
   204  * by playbin when it has created the source element for a particular URI.
   184  * In the signal callback you can check if the source element has a "device"
   205  * In the signal callback you can check if the source element has a "device"
   185  * property and set it appropriately. In future ways might be added to specify
   206  * property and set it appropriately. In future ways might be added to specify
   186  * the device as part of the URI, but at the time of writing this is not
   207  * the device as part of the URI, but at the time of writing this is not
   187  * possible yet.
   208  * possible yet.
   188  * </refsect2>
   209  * </para>
   189  * <refsect2>
       
   190  * <title>Handling redirects</title>
       
   191  * <para>
       
   192  * Some elements may post 'redirect' messages on the bus to tell the
       
   193  * application to open another location. These are element messages containing
       
   194  * a structure named 'redirect' along with a 'new-location' field of string
       
   195  * type. The new location may be a relative or an absolute URI. Examples
       
   196  * for such redirects can be found in many quicktime movie trailers.
       
   197  * </para>
       
   198  * </refsect2>
       
   199  * <refsect2>
       
   200  * <title>Examples</title>
   210  * <title>Examples</title>
   201  * |[
   211  * <para>
       
   212  * Here is a simple pipeline to play back a video or audio file:
       
   213  * <programlisting>
   202  * gst-launch -v playbin uri=file:///path/to/somefile.avi
   214  * gst-launch -v playbin uri=file:///path/to/somefile.avi
   203  * ]| This will play back the given AVI video file, given that the video and
   215  * </programlisting>
       
   216  * This will play back the given AVI video file, given that the video and
   204  * audio decoders required to decode the content are installed. Since no
   217  * audio decoders required to decode the content are installed. Since no
   205  * special audio sink or video sink is supplied (not possible via gst-launch),
   218  * special audio sink or video sink is supplied (not possible via gst-launch),
   206  * playbin will try to find a suitable audio and video sink automatically
   219  * playbin will try to find a suitable audio and video sink automatically
   207  * using the autoaudiosink and autovideosink elements.
   220  * using the autoaudiosink and autovideosink elements.
   208  * |[
   221  * </para>
       
   222  * <para>
       
   223  * Here is a another pipeline to play track 4 of an audio CD:
       
   224  * <programlisting>
   209  * gst-launch -v playbin uri=cdda://4
   225  * gst-launch -v playbin uri=cdda://4
   210  * ]| This will play back track 4 on an audio CD in your disc drive (assuming
   226  * </programlisting>
       
   227  * This will play back track 4 on an audio CD in your disc drive (assuming
   211  * the drive is detected automatically by the plugin).
   228  * the drive is detected automatically by the plugin).
   212  * |[
   229  * </para>
       
   230  * <para>
       
   231  * Here is a another pipeline to play title 1 of a DVD:
       
   232  * <programlisting>
   213  * gst-launch -v playbin uri=dvd://1
   233  * gst-launch -v playbin uri=dvd://1
   214  * ]| This will play back title 1 of a DVD in your disc drive (assuming
   234  * </programlisting>
       
   235  * This will play back title 1 of a DVD in your disc drive (assuming
   215  * the drive is detected automatically by the plugin).
   236  * the drive is detected automatically by the plugin).
       
   237  * </para>
   216  * </refsect2>
   238  * </refsect2>
   217  */
   239  */
   218 
   240 
   219 #ifdef HAVE_CONFIG_H
   241 #ifdef HAVE_CONFIG_H
   220 #include "config.h"
   242 #include "config.h"
   228 
   250 
   229 #include "gstplay-enum.h"
   251 #include "gstplay-enum.h"
   230 #include "gstplay-marshal.h"
   252 #include "gstplay-marshal.h"
   231 #include "gstplaysink.h"
   253 #include "gstplaysink.h"
   232 #include "gstfactorylists.h"
   254 #include "gstfactorylists.h"
   233 #include "gstinputselector.h"
       
   234 #include "gstscreenshot.h"
   255 #include "gstscreenshot.h"
   235 
   256 #include "gststreaminfo.h"
       
   257 #include "gststreamselector.h"
       
   258 
       
   259 #ifdef __SYMBIAN32__
       
   260 #include <glib_global.h>
       
   261 #endif
   236 GST_DEBUG_CATEGORY_STATIC (gst_play_bin_debug);
   262 GST_DEBUG_CATEGORY_STATIC (gst_play_bin_debug);
   237 #define GST_CAT_DEFAULT gst_play_bin_debug
   263 #define GST_CAT_DEFAULT gst_play_bin_debug
   238 
   264 
   239 #define GST_TYPE_PLAY_BIN               (gst_play_bin_get_type())
   265 #define GST_TYPE_PLAY_BIN               (gst_play_bin_get_type())
   240 #define GST_PLAY_BIN(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PLAY_BIN,GstPlayBin))
   266 #define GST_PLAY_BIN(obj)               (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PLAY_BIN,GstPlayBin))
   250 typedef struct _GstSourceSelect GstSourceSelect;
   276 typedef struct _GstSourceSelect GstSourceSelect;
   251 
   277 
   252 /* has the info for a selector and provides the link to the sink */
   278 /* has the info for a selector and provides the link to the sink */
   253 struct _GstSourceSelect
   279 struct _GstSourceSelect
   254 {
   280 {
   255   const gchar *media_list[3];   /* the media types for the selector */
   281   const gchar *media;           /* the media type of the selector */
   256   GstPlaySinkType type;         /* the sink pad type of the selector */
   282   GstPlaySinkType type;         /* the sink pad type of the selector */
   257 
   283 
   258   GstElement *selector;         /* the selector */
   284   GstElement *selector;         /* the selector */
   259   GPtrArray *channels;
   285   GPtrArray *channels;
   260   GstPad *srcpad;               /* the source pad of the selector */
   286   GstPad *srcpad;               /* the source pad of the selector */
   261   GstPad *sinkpad;              /* the sinkpad of the sink when the selector is linked */
   287   GstPad *sinkpad;              /* the sinkpad of the sink when the selector is linked */
   262 };
   288 };
   263 
   289 
   264 #define GST_SOURCE_GROUP_GET_LOCK(group) (((GstSourceGroup*)(group))->lock)
       
   265 #define GST_SOURCE_GROUP_LOCK(group) (g_mutex_lock (GST_SOURCE_GROUP_GET_LOCK(group)))
       
   266 #define GST_SOURCE_GROUP_UNLOCK(group) (g_mutex_unlock (GST_SOURCE_GROUP_GET_LOCK(group)))
       
   267 
       
   268 /* a structure to hold the objects for decoding a uri and the subtitle uri
   290 /* a structure to hold the objects for decoding a uri and the subtitle uri
   269  */
   291  */
   270 struct _GstSourceGroup
   292 struct _GstSourceGroup
   271 {
   293 {
   272   GstPlayBin *playbin;
   294   GstPlayBin *playbin;
   273 
       
   274   GMutex *lock;
       
   275 
   295 
   276   gboolean valid;               /* the group has valid info to start playback */
   296   gboolean valid;               /* the group has valid info to start playback */
   277   gboolean active;              /* the group is active */
   297   gboolean active;              /* the group is active */
   278 
   298 
   279   /* properties */
   299   /* properties */
   280   gchar *uri;
   300   gchar *uri;
   281   gchar *suburi;
   301   gchar *suburi;
   282   GValueArray *streaminfo;
   302   GValueArray *streaminfo;
   283   GstElement *source;
   303   GstElement *source;
       
   304   gchar *subencoding;           /* encoding to propagate to the subtitle elements */
   284 
   305 
   285   GPtrArray *video_channels;    /* links to selector pads */
   306   GPtrArray *video_channels;    /* links to selector pads */
   286   GPtrArray *audio_channels;    /* links to selector pads */
   307   GPtrArray *audio_channels;    /* links to selector pads */
   287   GPtrArray *text_channels;     /* links to selector pads */
   308   GPtrArray *text_channels;     /* links to selector pads */
   288   GPtrArray *subp_channels;     /* links to selector pads */
       
   289 
       
   290   GstElement *audio_sink;       /* autoplugged audio and video sinks */
       
   291   GstElement *video_sink;
       
   292 
   309 
   293   /* uridecodebins for uri and subtitle uri */
   310   /* uridecodebins for uri and subtitle uri */
   294   GstElement *uridecodebin;
   311   GstElement *uridecodebin;
   295   GstElement *suburidecodebin;
   312   GstElement *suburidecodebin;
   296   gint pending;
       
   297 
       
   298   gulong pad_added_id;
       
   299   gulong pad_removed_id;
       
   300   gulong no_more_pads_id;
       
   301   gulong notify_source_id;
       
   302   gulong drained_id;
       
   303   gulong autoplug_factories_id;
       
   304   gulong autoplug_select_id;
       
   305 
       
   306   gulong sub_pad_added_id;
       
   307   gulong sub_pad_removed_id;
       
   308   gulong sub_no_more_pads_id;
       
   309 
   313 
   310   /* selectors for different streams */
   314   /* selectors for different streams */
   311   GstSourceSelect selector[GST_PLAY_SINK_TYPE_LAST];
   315   GstSourceSelect selector[GST_PLAY_SINK_TYPE_LAST];
   312 };
   316 };
   313 
   317 
   314 #define GST_PLAY_BIN_GET_LOCK(bin) (((GstPlayBin*)(bin))->lock)
       
   315 #define GST_PLAY_BIN_LOCK(bin) (g_mutex_lock (GST_PLAY_BIN_GET_LOCK(bin)))
       
   316 #define GST_PLAY_BIN_UNLOCK(bin) (g_mutex_unlock (GST_PLAY_BIN_GET_LOCK(bin)))
       
   317 
       
   318 /* lock to protect dynamic callbacks, like no-more-pads */
       
   319 #define GST_PLAY_BIN_DYN_LOCK(bin)    g_mutex_lock ((bin)->dyn_lock)
       
   320 #define GST_PLAY_BIN_DYN_UNLOCK(bin)  g_mutex_unlock ((bin)->dyn_lock)
       
   321 
       
   322 /* lock for shutdown */
       
   323 #define GST_PLAY_BIN_SHUTDOWN_LOCK(bin,label)           \
       
   324 G_STMT_START {                                          \
       
   325   if (G_UNLIKELY (g_atomic_int_get (&bin->shutdown)))   \
       
   326     goto label;                                         \
       
   327   GST_PLAY_BIN_DYN_LOCK (bin);                          \
       
   328   if (G_UNLIKELY (g_atomic_int_get (&bin->shutdown))) { \
       
   329     GST_PLAY_BIN_DYN_UNLOCK (bin);                      \
       
   330     goto label;                                         \
       
   331   }                                                     \
       
   332 } G_STMT_END
       
   333 
       
   334 /* unlock for shutdown */
       
   335 #define GST_PLAY_BIN_SHUTDOWN_UNLOCK(bin)         \
       
   336   GST_PLAY_BIN_DYN_UNLOCK (bin);                  \
       
   337 
       
   338 /**
       
   339  * GstPlayBin2:
       
   340  *
       
   341  * playbin element structure
       
   342  */
       
   343 struct _GstPlayBin
   318 struct _GstPlayBin
   344 {
   319 {
   345   GstPipeline parent;
   320   GstPipeline parent;
   346 
       
   347   GMutex *lock;                 /* to protect group switching */
       
   348 
   321 
   349   /* the groups, we use a double buffer to switch between current and next */
   322   /* the groups, we use a double buffer to switch between current and next */
   350   GstSourceGroup groups[2];     /* array with group info */
   323   GstSourceGroup groups[2];     /* array with group info */
   351   GstSourceGroup *curr_group;   /* pointer to the currently playing group */
   324   GstSourceGroup *curr_group;   /* pointer to the currently playing group */
   352   GstSourceGroup *next_group;   /* pointer to the next group */
   325   GstSourceGroup *next_group;   /* pointer to the next group */
       
   326 
       
   327   gboolean about_to_finish;     /* the about-to-finish signal is emited */
   353 
   328 
   354   /* properties */
   329   /* properties */
   355   guint connection_speed;       /* connection speed in bits/sec (0 = unknown) */
   330   guint connection_speed;       /* connection speed in bits/sec (0 = unknown) */
   356   gint current_video;           /* the currently selected stream */
   331   gint current_video;           /* the currently selected stream */
   357   gint current_audio;           /* the currently selected stream */
   332   gint current_audio;           /* the currently selected stream */
   358   gint current_text;            /* the currently selected stream */
   333   gint current_text;            /* the currently selected stream */
   359   gchar *encoding;              /* subtitle encoding */
       
   360 
       
   361   guint64 buffer_duration;      /* When buffering, the max buffer duration (ns) */
       
   362   guint buffer_size;            /* When buffering, the max buffer size (bytes) */
       
   363 
   334 
   364   /* our play sink */
   335   /* our play sink */
   365   GstPlaySink *playsink;
   336   GstPlaySink *playsink;
   366 
   337 
   367   /* the last activated source */
       
   368   GstElement *source;
       
   369 
       
   370   /* lock protecting dynamic adding/removing */
       
   371   GMutex *dyn_lock;
       
   372   /* if we are shutting down or not */
       
   373   gint shutdown;
       
   374 
       
   375   GValueArray *elements;        /* factories we can use for selecting elements */
   338   GValueArray *elements;        /* factories we can use for selecting elements */
   376 
       
   377   gboolean have_selector;       /* set to FALSE when we fail to create an
       
   378                                  * input-selector, so that we only post a
       
   379                                  * warning once */
       
   380 
       
   381   GstElement *audio_sink;       /* configured audio sink, or NULL      */
       
   382   GstElement *video_sink;       /* configured video sink, or NULL      */
       
   383   GstElement *subpic_sink;      /* configured subpicture sink, or NULL */
       
   384   GstElement *text_sink;        /* configured text sink, or NULL       */
       
   385 };
   339 };
   386 
   340 
   387 struct _GstPlayBinClass
   341 struct _GstPlayBinClass
   388 {
   342 {
   389   GstPipelineClass parent_class;
   343   GstPipelineClass parent_class;
   395   /* notify app that number of audio/video/text streams changed */
   349   /* notify app that number of audio/video/text streams changed */
   396   void (*video_changed) (GstPlayBin * playbin);
   350   void (*video_changed) (GstPlayBin * playbin);
   397   void (*audio_changed) (GstPlayBin * playbin);
   351   void (*audio_changed) (GstPlayBin * playbin);
   398   void (*text_changed) (GstPlayBin * playbin);
   352   void (*text_changed) (GstPlayBin * playbin);
   399 
   353 
   400   /* notify app that the tags of audio/video/text streams changed */
       
   401   void (*video_tags_changed) (GstPlayBin * playbin, gint stream);
       
   402   void (*audio_tags_changed) (GstPlayBin * playbin, gint stream);
       
   403   void (*text_tags_changed) (GstPlayBin * playbin, gint stream);
       
   404 
       
   405   /* get audio/video/text tags for a stream */
   354   /* get audio/video/text tags for a stream */
   406   GstTagList *(*get_video_tags) (GstPlayBin * playbin, gint stream);
   355   GstTagList *(*get_video_tags) (GstPlayBin * playbin, gint stream);
   407   GstTagList *(*get_audio_tags) (GstPlayBin * playbin, gint stream);
   356   GstTagList *(*get_audio_tags) (GstPlayBin * playbin, gint stream);
   408   GstTagList *(*get_text_tags) (GstPlayBin * playbin, gint stream);
   357   GstTagList *(*get_text_tags) (GstPlayBin * playbin, gint stream);
   409 
   358 
   410   /* get the last video frame and convert it to the given caps */
   359   /* get the last video frame and convert it to the given caps */
   411   GstBuffer *(*convert_frame) (GstPlayBin * playbin, GstCaps * caps);
   360   GstBuffer *(*convert_frame) (GstPlayBin * playbin, GstCaps * caps);
   412 
       
   413   /* get audio/video/text pad for a stream */
       
   414   GstPad *(*get_video_pad) (GstPlayBin * playbin, gint stream);
       
   415   GstPad *(*get_audio_pad) (GstPlayBin * playbin, gint stream);
       
   416   GstPad *(*get_text_pad) (GstPlayBin * playbin, gint stream);
       
   417 };
   361 };
   418 
   362 
   419 /* props */
   363 /* props */
   420 #define DEFAULT_URI               NULL
   364 #define DEFAULT_URI               NULL
   421 #define DEFAULT_SUBURI            NULL
   365 #define DEFAULT_SUBURI            NULL
   430 #define DEFAULT_CURRENT_TEXT      -1
   374 #define DEFAULT_CURRENT_TEXT      -1
   431 #define DEFAULT_SUBTITLE_ENCODING NULL
   375 #define DEFAULT_SUBTITLE_ENCODING NULL
   432 #define DEFAULT_AUDIO_SINK        NULL
   376 #define DEFAULT_AUDIO_SINK        NULL
   433 #define DEFAULT_VIDEO_SINK        NULL
   377 #define DEFAULT_VIDEO_SINK        NULL
   434 #define DEFAULT_VIS_PLUGIN        NULL
   378 #define DEFAULT_VIS_PLUGIN        NULL
   435 #define DEFAULT_TEXT_SINK         NULL
       
   436 #define DEFAULT_SUBPIC_SINK       NULL
       
   437 #define DEFAULT_VOLUME            1.0
   379 #define DEFAULT_VOLUME            1.0
   438 #define DEFAULT_MUTE              FALSE
   380 #define DEFAULT_MUTE              FALSE
   439 #define DEFAULT_FRAME             NULL
   381 #define DEFAULT_FRAME             NULL
   440 #define DEFAULT_FONT_DESC         NULL
   382 #define DEFAULT_FONT_DESC         NULL
   441 #define DEFAULT_CONNECTION_SPEED  0
   383 #define DEFAULT_CONNECTION_SPEED  0
   442 #define DEFAULT_BUFFER_DURATION   -1
       
   443 #define DEFAULT_BUFFER_SIZE       -1
       
   444 
   384 
   445 enum
   385 enum
   446 {
   386 {
   447   PROP_0,
   387   PROP_0,
   448   PROP_URI,
   388   PROP_URI,
   457   PROP_CURRENT_TEXT,
   397   PROP_CURRENT_TEXT,
   458   PROP_SUBTITLE_ENCODING,
   398   PROP_SUBTITLE_ENCODING,
   459   PROP_AUDIO_SINK,
   399   PROP_AUDIO_SINK,
   460   PROP_VIDEO_SINK,
   400   PROP_VIDEO_SINK,
   461   PROP_VIS_PLUGIN,
   401   PROP_VIS_PLUGIN,
   462   PROP_TEXT_SINK,
       
   463   PROP_SUBPIC_SINK,
       
   464   PROP_VOLUME,
   402   PROP_VOLUME,
   465   PROP_MUTE,
   403   PROP_MUTE,
   466   PROP_FRAME,
   404   PROP_FRAME,
   467   PROP_FONT_DESC,
   405   PROP_FONT_DESC,
   468   PROP_CONNECTION_SPEED,
   406   PROP_CONNECTION_SPEED
   469   PROP_BUFFER_SIZE,
       
   470   PROP_BUFFER_DURATION,
       
   471   PROP_LAST
       
   472 };
   407 };
   473 
   408 
   474 /* signals */
   409 /* signals */
   475 enum
   410 enum
   476 {
   411 {
   477   SIGNAL_ABOUT_TO_FINISH,
   412   SIGNAL_ABOUT_TO_FINISH,
   478   SIGNAL_CONVERT_FRAME,
       
   479   SIGNAL_VIDEO_CHANGED,
   413   SIGNAL_VIDEO_CHANGED,
   480   SIGNAL_AUDIO_CHANGED,
   414   SIGNAL_AUDIO_CHANGED,
   481   SIGNAL_TEXT_CHANGED,
   415   SIGNAL_TEXT_CHANGED,
   482   SIGNAL_VIDEO_TAGS_CHANGED,
       
   483   SIGNAL_AUDIO_TAGS_CHANGED,
       
   484   SIGNAL_TEXT_TAGS_CHANGED,
       
   485   SIGNAL_GET_VIDEO_TAGS,
   416   SIGNAL_GET_VIDEO_TAGS,
   486   SIGNAL_GET_AUDIO_TAGS,
   417   SIGNAL_GET_AUDIO_TAGS,
   487   SIGNAL_GET_TEXT_TAGS,
   418   SIGNAL_GET_TEXT_TAGS,
   488   SIGNAL_GET_VIDEO_PAD,
       
   489   SIGNAL_GET_AUDIO_PAD,
       
   490   SIGNAL_GET_TEXT_PAD,
       
   491   LAST_SIGNAL
   419   LAST_SIGNAL
   492 };
   420 };
   493 
   421 
   494 static void gst_play_bin_class_init (GstPlayBinClass * klass);
   422 static void gst_play_bin_class_init (GstPlayBinClass * klass);
   495 static void gst_play_bin_init (GstPlayBin * playbin);
   423 static void gst_play_bin_init (GstPlayBin * playbin);
   513     gint stream);
   441     gint stream);
   514 
   442 
   515 static GstBuffer *gst_play_bin_convert_frame (GstPlayBin * playbin,
   443 static GstBuffer *gst_play_bin_convert_frame (GstPlayBin * playbin,
   516     GstCaps * caps);
   444     GstCaps * caps);
   517 
   445 
   518 static GstPad *gst_play_bin_get_video_pad (GstPlayBin * playbin, gint stream);
   446 static gboolean setup_next_source (GstPlayBin * playbin);
   519 static GstPad *gst_play_bin_get_audio_pad (GstPlayBin * playbin, gint stream);
       
   520 static GstPad *gst_play_bin_get_text_pad (GstPlayBin * playbin, gint stream);
       
   521 
       
   522 static gboolean setup_next_source (GstPlayBin * playbin, GstState target);
       
   523 
   447 
   524 static GstElementClass *parent_class;
   448 static GstElementClass *parent_class;
   525 
   449 
   526 static guint gst_play_bin_signals[LAST_SIGNAL] = { 0 };
   450 static guint gst_play_bin_signals[LAST_SIGNAL] = { 0 };
   527 
   451 
   606   gobject_klass->get_property = gst_play_bin_get_property;
   530   gobject_klass->get_property = gst_play_bin_get_property;
   607 
   531 
   608   gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_play_bin_finalize);
   532   gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_play_bin_finalize);
   609 
   533 
   610   /**
   534   /**
   611    * GstPlayBin2:uri
   535    * GstPlayBin:uri
   612    *
   536    *
   613    * Set the next URI that playbin will play. This property can be set from the
   537    * Set the next URI that playbin will play. This property can be set from the
   614    * about-to-finish signal to queue the next media file.
   538    * about-to-finish signal to queue the next media file.
   615    */
   539    */
   616   g_object_class_install_property (gobject_klass, PROP_URI,
   540   g_object_class_install_property (gobject_klass, PROP_URI,
   617       g_param_spec_string ("uri", "URI", "URI of the media to play",
   541       g_param_spec_string ("uri", "URI", "URI of the media to play",
   618           NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   542           NULL, G_PARAM_READWRITE));
   619 
   543 
   620   /**
   544   /**
   621    * GstPlayBin2:suburi
   545    * GstPlayBin:suburi
   622    *
   546    *
   623    * Set the next subtitle URI that playbin will play. This property can be
   547    * Set the next subtitle URI that playbin will play. This property can be
   624    * set from the about-to-finish signal to queue the next subtitle media file.
   548    * set from the about-to-finish signal to queue the next subtitle media file.
   625    */
   549    */
   626   g_object_class_install_property (gobject_klass, PROP_SUBURI,
   550   g_object_class_install_property (gobject_klass, PROP_SUBURI,
   627       g_param_spec_string ("suburi", ".sub-URI", "Optional URI of a subtitle",
   551       g_param_spec_string ("suburi", ".sub-URI", "Optional URI of a subtitle",
   628           NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   552           NULL, G_PARAM_READWRITE));
   629 
   553 
   630   g_object_class_install_property (gobject_klass, PROP_SOURCE,
   554   g_object_class_install_property (gobject_klass, PROP_SOURCE,
   631       g_param_spec_object ("source", "Source", "Source element",
   555       g_param_spec_object ("source", "Source", "Source element",
   632           GST_TYPE_ELEMENT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   556           GST_TYPE_ELEMENT, G_PARAM_READABLE));
       
   557 
   633 
   558 
   634   /**
   559   /**
   635    * GstPlayBin2:flags
   560    * GstPlayBin:flags
   636    *
   561    *
   637    * Control the behaviour of playbin.
   562    * Control the behaviour of playbin.
   638    */
   563    */
   639   g_object_class_install_property (gobject_klass, PROP_FLAGS,
   564   g_object_class_install_property (gobject_klass, PROP_FLAGS,
   640       g_param_spec_flags ("flags", "Flags", "Flags to control behaviour",
   565       g_param_spec_flags ("flags", "Flags", "Flags to control behaviour",
   641           GST_TYPE_PLAY_FLAGS, DEFAULT_FLAGS,
   566           GST_TYPE_PLAY_FLAGS, DEFAULT_FLAGS, G_PARAM_READWRITE));
   642           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
       
   643 
   567 
   644   /**
   568   /**
   645    * GstPlayBin2:n-video
   569    * GstPlayBin:n-video
   646    *
   570    *
   647    * Get the total number of available video streams. 
   571    * Get the total number of available video streams. 
   648    */
   572    */
   649   g_object_class_install_property (gobject_klass, PROP_N_VIDEO,
   573   g_object_class_install_property (gobject_klass, PROP_N_VIDEO,
   650       g_param_spec_int ("n-video", "Number Video",
   574       g_param_spec_int ("n-video", "Number Video",
   651           "Total number of video streams", 0, G_MAXINT, 0,
   575           "Total number of video streams", 0, G_MAXINT, 0, G_PARAM_READABLE));
   652           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
       
   653   /**
   576   /**
   654    * GstPlayBin2:current-video
   577    * GstPlayBin:current-video
   655    *
   578    *
   656    * Get or set the currently playing video stream. By default the first video
   579    * Get or set the currently playing video stream. By default the first video
   657    * stream with data is played.
   580    * stream with data is played.
   658    */
   581    */
   659   g_object_class_install_property (gobject_klass, PROP_CURRENT_VIDEO,
   582   g_object_class_install_property (gobject_klass, PROP_CURRENT_VIDEO,
   660       g_param_spec_int ("current-video", "Current Video",
   583       g_param_spec_int ("current-video", "Current Video",
   661           "Currently playing video stream (-1 = auto)",
   584           "Currently playing video stream (-1 = auto)",
   662           -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   585           -1, G_MAXINT, -1, G_PARAM_READWRITE));
   663   /**
   586   /**
   664    * GstPlayBin2:n-audio
   587    * GstPlayBin:n-audio
   665    *
   588    *
   666    * Get the total number of available audio streams. 
   589    * Get the total number of available audio streams. 
   667    */
   590    */
   668   g_object_class_install_property (gobject_klass, PROP_N_AUDIO,
   591   g_object_class_install_property (gobject_klass, PROP_N_AUDIO,
   669       g_param_spec_int ("n-audio", "Number Audio",
   592       g_param_spec_int ("n-audio", "Number Audio",
   670           "Total number of audio streams", 0, G_MAXINT, 0,
   593           "Total number of audio streams", 0, G_MAXINT, 0, G_PARAM_READABLE));
   671           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
       
   672   /**
   594   /**
   673    * GstPlayBin2:current-audio
   595    * GstPlayBin:current-audio
   674    *
   596    *
   675    * Get or set the currently playing audio stream. By default the first audio
   597    * Get or set the currently playing audio stream. By default the first audio
   676    * stream with data is played.
   598    * stream with data is played.
   677    */
   599    */
   678   g_object_class_install_property (gobject_klass, PROP_CURRENT_AUDIO,
   600   g_object_class_install_property (gobject_klass, PROP_CURRENT_AUDIO,
   679       g_param_spec_int ("current-audio", "Current audio",
   601       g_param_spec_int ("current-audio", "Current audio",
   680           "Currently playing audio stream (-1 = auto)",
   602           "Currently playing audio stream (-1 = auto)",
   681           -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   603           -1, G_MAXINT, -1, G_PARAM_READWRITE));
   682   /**
   604   /**
   683    * GstPlayBin2:n-text
   605    * GstPlayBin:n-text
   684    *
   606    *
   685    * Get the total number of available subtitle streams. 
   607    * Get the total number of available subtitle streams. 
   686    */
   608    */
   687   g_object_class_install_property (gobject_klass, PROP_N_TEXT,
   609   g_object_class_install_property (gobject_klass, PROP_N_TEXT,
   688       g_param_spec_int ("n-text", "Number Text",
   610       g_param_spec_int ("n-text", "Number Text",
   689           "Total number of text streams", 0, G_MAXINT, 0,
   611           "Total number of text streams", 0, G_MAXINT, 0, G_PARAM_READABLE));
   690           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
       
   691   /**
   612   /**
   692    * GstPlayBin2:current-text:
   613    * GstPlayBin:current-text
   693    *
   614    *
   694    * Get or set the currently playing subtitle stream. By default the first
   615    * Get or set the currently playing subtitle stream. By default the first
   695    * subtitle stream with data is played.
   616    * subtitle stream with data is played.
   696    */
   617    */
   697   g_object_class_install_property (gobject_klass, PROP_CURRENT_TEXT,
   618   g_object_class_install_property (gobject_klass, PROP_CURRENT_TEXT,
   698       g_param_spec_int ("current-text", "Current Text",
   619       g_param_spec_int ("current-text", "Current Text",
   699           "Currently playing text stream (-1 = auto)",
   620           "Currently playing text stream (-1 = auto)",
   700           -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   621           -1, G_MAXINT, -1, G_PARAM_READWRITE));
   701 
   622 
   702   g_object_class_install_property (gobject_klass, PROP_SUBTITLE_ENCODING,
   623   g_object_class_install_property (gobject_klass, PROP_SUBTITLE_ENCODING,
   703       g_param_spec_string ("subtitle-encoding", "subtitle encoding",
   624       g_param_spec_string ("subtitle-encoding", "subtitle encoding",
   704           "Encoding to assume if input subtitles are not in UTF-8 encoding. "
   625           "Encoding to assume if input subtitles are not in UTF-8 encoding. "
   705           "If not set, the GST_SUBTITLE_ENCODING environment variable will "
   626           "If not set, the GST_SUBTITLE_ENCODING environment variable will "
   706           "be checked for an encoding to use. If that is not set either, "
   627           "be checked for an encoding to use. If that is not set either, "
   707           "ISO-8859-15 will be assumed.", NULL,
   628           "ISO-8859-15 will be assumed.", NULL, G_PARAM_READWRITE));
   708           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
       
   709 
   629 
   710   g_object_class_install_property (gobject_klass, PROP_VIDEO_SINK,
   630   g_object_class_install_property (gobject_klass, PROP_VIDEO_SINK,
   711       g_param_spec_object ("video-sink", "Video Sink",
   631       g_param_spec_object ("video-sink", "Video Sink",
   712           "the video output element to use (NULL = default sink)",
   632           "the video output element to use (NULL = default sink)",
   713           GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   633           GST_TYPE_ELEMENT, G_PARAM_READWRITE));
   714   g_object_class_install_property (gobject_klass, PROP_AUDIO_SINK,
   634   g_object_class_install_property (gobject_klass, PROP_AUDIO_SINK,
   715       g_param_spec_object ("audio-sink", "Audio Sink",
   635       g_param_spec_object ("audio-sink", "Audio Sink",
   716           "the audio output element to use (NULL = default sink)",
   636           "the audio output element to use (NULL = default sink)",
   717           GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   637           GST_TYPE_ELEMENT, G_PARAM_READWRITE));
   718   g_object_class_install_property (gobject_klass, PROP_VIS_PLUGIN,
   638   g_object_class_install_property (gobject_klass, PROP_VIS_PLUGIN,
   719       g_param_spec_object ("vis-plugin", "Vis plugin",
   639       g_param_spec_object ("vis-plugin", "Vis plugin",
   720           "the visualization element to use (NULL = default)",
   640           "the visualization element to use (NULL = none)",
   721           GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   641           GST_TYPE_ELEMENT, G_PARAM_READWRITE));
   722   g_object_class_install_property (gobject_klass, PROP_TEXT_SINK,
       
   723       g_param_spec_object ("text-sink", "Text plugin",
       
   724           "the text output element to use (NULL = default textoverlay)",
       
   725           GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
       
   726   g_object_class_install_property (gobject_klass, PROP_SUBPIC_SINK,
       
   727       g_param_spec_object ("subpic-sink", "Subpicture plugin",
       
   728           "the subpicture output element to use (NULL = default dvdspu)",
       
   729           GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
       
   730 
   642 
   731   g_object_class_install_property (gobject_klass, PROP_VOLUME,
   643   g_object_class_install_property (gobject_klass, PROP_VOLUME,
   732       g_param_spec_double ("volume", "Volume", "The audio volume, 1.0=100%",
   644       g_param_spec_double ("volume", "Volume", "The audio volume",
   733           0.0, VOLUME_MAX_DOUBLE, 1.0,
   645           0.0, VOLUME_MAX_DOUBLE, 1.0, G_PARAM_READWRITE));
   734           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
       
   735   g_object_class_install_property (gobject_klass, PROP_MUTE,
   646   g_object_class_install_property (gobject_klass, PROP_MUTE,
   736       g_param_spec_boolean ("mute", "Mute",
   647       g_param_spec_boolean ("mute", "Mute",
   737           "Mute the audio channel without changing the volume", FALSE,
   648           "Mute the audio channel without changing the volume", FALSE,
   738           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
   649           G_PARAM_READWRITE));
   739 
   650 
   740   /**
   651   /**
   741    * GstPlayBin2:frame:
   652    * GstPlayBin::frame
   742    * @playbin: a #GstPlayBin2
   653    * @playbin: a #GstPlayBin
   743    *
   654    *
   744    * Get the currently rendered or prerolled frame in the sink.
   655    * Get the currently rendered or prerolled frame in the sink.
   745    * The #GstCaps on the buffer will describe the format of the buffer.
   656    * The #GstCaps on the buffer will describe the format of the buffer.
   746    */
   657    */
   747   g_object_class_install_property (gobject_klass, PROP_FRAME,
   658   g_object_class_install_property (gobject_klass, PROP_FRAME,
   748       gst_param_spec_mini_object ("frame", "Frame",
   659       gst_param_spec_mini_object ("frame", "Frame",
   749           "The last frame (NULL = no video available)",
   660           "The last frame (NULL = no video available)",
   750           GST_TYPE_BUFFER, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
   661           GST_TYPE_BUFFER, G_PARAM_READABLE));
   751   g_object_class_install_property (gobject_klass, PROP_FONT_DESC,
   662   g_object_class_install_property (gobject_klass, PROP_FONT_DESC,
   752       g_param_spec_string ("subtitle-font-desc",
   663       g_param_spec_string ("subtitle-font-desc",
   753           "Subtitle font description",
   664           "Subtitle font description",
   754           "Pango font description of font "
   665           "Pango font description of font "
   755           "to be used for subtitle rendering", NULL,
   666           "to be used for subtitle rendering", NULL, G_PARAM_WRITABLE));
   756           G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
       
   757 
   667 
   758   g_object_class_install_property (gobject_klass, PROP_CONNECTION_SPEED,
   668   g_object_class_install_property (gobject_klass, PROP_CONNECTION_SPEED,
   759       g_param_spec_uint ("connection-speed", "Connection Speed",
   669       g_param_spec_uint ("connection-speed", "Connection Speed",
   760           "Network connection speed in kbps (0 = unknown)",
   670           "Network connection speed in kbps (0 = unknown)",
   761           0, G_MAXUINT / 1000, DEFAULT_CONNECTION_SPEED,
   671           0, G_MAXUINT, DEFAULT_CONNECTION_SPEED, G_PARAM_READWRITE));
   762           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
       
   763 
       
   764   g_object_class_install_property (gobject_klass, PROP_BUFFER_SIZE,
       
   765       g_param_spec_int ("buffer-size", "Buffer size (bytes)",
       
   766           "Buffer size when buffering network streams",
       
   767           -1, G_MAXINT, DEFAULT_BUFFER_SIZE,
       
   768           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
       
   769   g_object_class_install_property (gobject_klass, PROP_BUFFER_DURATION,
       
   770       g_param_spec_int64 ("buffer-duration", "Buffer duration (ns)",
       
   771           "Buffer duration when buffering network streams",
       
   772           -1, G_MAXINT64, DEFAULT_BUFFER_DURATION,
       
   773           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
       
   774 
       
   775   /**
   672   /**
   776    * GstPlayBin2::about-to-finish
   673    * GstPlayBin::about-to-finish:
   777    * @playbin: a #GstPlayBin2
   674    * @playbin: a #GstPlayBin
   778    *
   675    *
   779    * This signal is emitted when the current uri is about to finish. You can
   676    * This signal is emitted when the current uri is about to finish. You can
   780    * set the uri and suburi to make sure that playback continues.
   677    * set the next-uri and next-suburi to make sure that playback continues.
   781    */
   678    */
   782   gst_play_bin_signals[SIGNAL_ABOUT_TO_FINISH] =
   679   gst_play_bin_signals[SIGNAL_ABOUT_TO_FINISH] =
   783       g_signal_new ("about-to-finish", G_TYPE_FROM_CLASS (klass),
   680       g_signal_new ("about-to-finish", G_TYPE_FROM_CLASS (klass),
   784       G_SIGNAL_RUN_LAST,
   681       G_SIGNAL_RUN_LAST,
   785       G_STRUCT_OFFSET (GstPlayBinClass, about_to_finish), NULL, NULL,
   682       G_STRUCT_OFFSET (GstPlayBinClass, about_to_finish), NULL, NULL,
   786       gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
   683       gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
   787 
   684 
   788   /**
   685   /**
   789    * GstPlayBin2::video-changed
   686    * GstPlayBin::video-changed
   790    * @playbin: a #GstPlayBin2
   687    * @playbin: a #GstPlayBin
   791    *
   688    *
   792    * This signal is emitted whenever the number or order of the video
   689    * This signal is emited whenever the number or order of the video
   793    * streams has changed. The application will most likely want to select
   690    * streams has changed. The application will most likely want to select
   794    * a new video stream.
   691    * a new video stream.
   795    */
   692    */
   796   gst_play_bin_signals[SIGNAL_VIDEO_CHANGED] =
   693   gst_play_bin_signals[SIGNAL_VIDEO_CHANGED] =
   797       g_signal_new ("video-changed", G_TYPE_FROM_CLASS (klass),
   694       g_signal_new ("video-changed", G_TYPE_FROM_CLASS (klass),
   798       G_SIGNAL_RUN_LAST,
   695       G_SIGNAL_RUN_LAST,
   799       G_STRUCT_OFFSET (GstPlayBinClass, video_changed), NULL, NULL,
   696       G_STRUCT_OFFSET (GstPlayBinClass, video_changed), NULL, NULL,
   800       gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
   697       gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
   801   /**
   698   /**
   802    * GstPlayBin2::audio-changed
   699    * GstPlayBin::audio-changed
   803    * @playbin: a #GstPlayBin2
   700    * @playbin: a #GstPlayBin
   804    *
   701    *
   805    * This signal is emitted whenever the number or order of the audio
   702    * This signal is emited whenever the number or order of the audio
   806    * streams has changed. The application will most likely want to select
   703    * streams has changed. The application will most likely want to select
   807    * a new audio stream.
   704    * a new audio stream.
   808    */
   705    */
   809   gst_play_bin_signals[SIGNAL_AUDIO_CHANGED] =
   706   gst_play_bin_signals[SIGNAL_AUDIO_CHANGED] =
   810       g_signal_new ("audio-changed", G_TYPE_FROM_CLASS (klass),
   707       g_signal_new ("audio-changed", G_TYPE_FROM_CLASS (klass),
   811       G_SIGNAL_RUN_LAST,
   708       G_SIGNAL_RUN_LAST,
   812       G_STRUCT_OFFSET (GstPlayBinClass, audio_changed), NULL, NULL,
   709       G_STRUCT_OFFSET (GstPlayBinClass, audio_changed), NULL, NULL,
   813       gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
   710       gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
   814   /**
   711   /**
   815    * GstPlayBin2::text-changed
   712    * GstPlayBin::text-changed
   816    * @playbin: a #GstPlayBin2
   713    * @playbin: a #GstPlayBin
   817    *
   714    *
   818    * This signal is emitted whenever the number or order of the text
   715    * This signal is emited whenever the number or order of the text
   819    * streams has changed. The application will most likely want to select
   716    * streams has changed. The application will most likely want to select
   820    * a new text stream.
   717    * a new text stream.
   821    */
   718    */
   822   gst_play_bin_signals[SIGNAL_TEXT_CHANGED] =
   719   gst_play_bin_signals[SIGNAL_TEXT_CHANGED] =
   823       g_signal_new ("text-changed", G_TYPE_FROM_CLASS (klass),
   720       g_signal_new ("text-changed", G_TYPE_FROM_CLASS (klass),
   824       G_SIGNAL_RUN_LAST,
   721       G_SIGNAL_RUN_LAST,
   825       G_STRUCT_OFFSET (GstPlayBinClass, text_changed), NULL, NULL,
   722       G_STRUCT_OFFSET (GstPlayBinClass, text_changed), NULL, NULL,
   826       gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
   723       gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
   827 
   724 
   828   /**
   725   /**
   829    * GstPlayBin2::video-tags-changed
   726    * GstPlayBin::get-video-tags
   830    * @playbin: a #GstPlayBin2
   727    * @playbin: a #GstPlayBin
   831    * @stream: stream index with changed tags
       
   832    *
       
   833    * This signal is emitted whenever the tags of a video stream have changed.
       
   834    * The application will most likely want to get the new tags.
       
   835    *
       
   836    * Since: 0.10.24
       
   837    */
       
   838   gst_play_bin_signals[SIGNAL_VIDEO_TAGS_CHANGED] =
       
   839       g_signal_new ("video-tags-changed", G_TYPE_FROM_CLASS (klass),
       
   840       G_SIGNAL_RUN_LAST,
       
   841       G_STRUCT_OFFSET (GstPlayBinClass, video_tags_changed), NULL, NULL,
       
   842       gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
       
   843 
       
   844   /**
       
   845    * GstPlayBin2::audio-tags-changed
       
   846    * @playbin: a #GstPlayBin2
       
   847    * @stream: stream index with changed tags
       
   848    *
       
   849    * This signal is emitted whenever the tags of an audio stream have changed.
       
   850    * The application will most likely want to get the new tags.
       
   851    *
       
   852    * Since: 0.10.24
       
   853    */
       
   854   gst_play_bin_signals[SIGNAL_AUDIO_TAGS_CHANGED] =
       
   855       g_signal_new ("audio-tags-changed", G_TYPE_FROM_CLASS (klass),
       
   856       G_SIGNAL_RUN_LAST,
       
   857       G_STRUCT_OFFSET (GstPlayBinClass, audio_tags_changed), NULL, NULL,
       
   858       gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
       
   859 
       
   860   /**
       
   861    * GstPlayBin2::text-tags-changed
       
   862    * @playbin: a #GstPlayBin2
       
   863    * @stream: stream index with changed tags
       
   864    *
       
   865    * This signal is emitted whenever the tags of a text stream have changed.
       
   866    * The application will most likely want to get the new tags.
       
   867    *
       
   868    * Since: 0.10.24
       
   869    */
       
   870   gst_play_bin_signals[SIGNAL_TEXT_TAGS_CHANGED] =
       
   871       g_signal_new ("text-tags-changed", G_TYPE_FROM_CLASS (klass),
       
   872       G_SIGNAL_RUN_LAST,
       
   873       G_STRUCT_OFFSET (GstPlayBinClass, text_tags_changed), NULL, NULL,
       
   874       gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
       
   875 
       
   876   /**
       
   877    * GstPlayBin2::get-video-tags
       
   878    * @playbin: a #GstPlayBin2
       
   879    * @stream: a video stream number
   728    * @stream: a video stream number
   880    *
   729    *
   881    * Action signal to retrieve the tags of a specific video stream number.
   730    * Action signal to retrieve the tags of a specific video stream number.
   882    * This information can be used to select a stream.
   731    * This information can be used to select a stream.
   883    *
   732    *
   888       g_signal_new ("get-video-tags", G_TYPE_FROM_CLASS (klass),
   737       g_signal_new ("get-video-tags", G_TYPE_FROM_CLASS (klass),
   889       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
   738       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
   890       G_STRUCT_OFFSET (GstPlayBinClass, get_video_tags), NULL, NULL,
   739       G_STRUCT_OFFSET (GstPlayBinClass, get_video_tags), NULL, NULL,
   891       gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
   740       gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
   892   /**
   741   /**
   893    * GstPlayBin2::get-audio-tags
   742    * GstPlayBin::get-audio-tags
   894    * @playbin: a #GstPlayBin2
   743    * @playbin: a #GstPlayBin
   895    * @stream: an audio stream number
   744    * @stream: an audio stream number
   896    *
   745    *
   897    * Action signal to retrieve the tags of a specific audio stream number.
   746    * Action signal to retrieve the tags of a specific audio stream number.
   898    * This information can be used to select a stream.
   747    * This information can be used to select a stream.
   899    *
   748    *
   904       g_signal_new ("get-audio-tags", G_TYPE_FROM_CLASS (klass),
   753       g_signal_new ("get-audio-tags", G_TYPE_FROM_CLASS (klass),
   905       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
   754       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
   906       G_STRUCT_OFFSET (GstPlayBinClass, get_audio_tags), NULL, NULL,
   755       G_STRUCT_OFFSET (GstPlayBinClass, get_audio_tags), NULL, NULL,
   907       gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
   756       gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
   908   /**
   757   /**
   909    * GstPlayBin2::get-text-tags
   758    * GstPlayBin::get-text-tags
   910    * @playbin: a #GstPlayBin2
   759    * @playbin: a #GstPlayBin
   911    * @stream: a text stream number
   760    * @stream: a text stream number
   912    *
   761    *
   913    * Action signal to retrieve the tags of a specific text stream number.
   762    * Action signal to retrieve the tags of a specific text stream number.
   914    * This information can be used to select a stream.
   763    * This information can be used to select a stream.
   915    *
   764    *
   920       g_signal_new ("get-text-tags", G_TYPE_FROM_CLASS (klass),
   769       g_signal_new ("get-text-tags", G_TYPE_FROM_CLASS (klass),
   921       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
   770       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
   922       G_STRUCT_OFFSET (GstPlayBinClass, get_text_tags), NULL, NULL,
   771       G_STRUCT_OFFSET (GstPlayBinClass, get_text_tags), NULL, NULL,
   923       gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
   772       gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
   924   /**
   773   /**
   925    * GstPlayBin2::convert-frame
   774    * GstPlayBin::convert-frame
   926    * @playbin: a #GstPlayBin2
   775    * @playbin: a #GstPlayBin
   927    * @caps: the target format of the frame
   776    * @caps: the target format of the frame
   928    *
   777    *
   929    * Action signal to retrieve the currently playing video frame in the format
   778    * Action signal to retrieve the currently playing video frame in the format
   930    * specified by @caps.
   779    * specified by @caps.
   931    * If @caps is %NULL, no conversion will be performed and this function is
   780    * If @caps is %NULL, no conversion will be performed and this function is
   934    * Returns: a #GstBuffer of the current video frame converted to #caps. 
   783    * Returns: a #GstBuffer of the current video frame converted to #caps. 
   935    * The caps on the buffer will describe the final layout of the buffer data.
   784    * The caps on the buffer will describe the final layout of the buffer data.
   936    * %NULL is returned when no current buffer can be retrieved or when the
   785    * %NULL is returned when no current buffer can be retrieved or when the
   937    * conversion failed.
   786    * conversion failed.
   938    */
   787    */
   939   gst_play_bin_signals[SIGNAL_CONVERT_FRAME] =
   788   gst_play_bin_signals[SIGNAL_GET_TEXT_TAGS] =
   940       g_signal_new ("convert-frame", G_TYPE_FROM_CLASS (klass),
   789       g_signal_new ("convert-frame", G_TYPE_FROM_CLASS (klass),
   941       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
   790       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
   942       G_STRUCT_OFFSET (GstPlayBinClass, convert_frame), NULL, NULL,
   791       G_STRUCT_OFFSET (GstPlayBinClass, convert_frame), NULL, NULL,
   943       gst_play_marshal_BUFFER__BOXED, GST_TYPE_BUFFER, 1, GST_TYPE_CAPS);
   792       gst_play_marshal_BUFFER__BOXED, GST_TYPE_BUFFER, 1, GST_TYPE_CAPS);
   944 
   793 
   945   /**
       
   946    * GstPlayBin2::get-video-pad
       
   947    * @playbin: a #GstPlayBin2
       
   948    * @stream: a video stream number
       
   949    *
       
   950    * Action signal to retrieve the stream-selector sinkpad for a specific 
       
   951    * video stream.
       
   952    * This pad can be used for notifications of caps changes, stream-specific
       
   953    * queries, etc.
       
   954    *
       
   955    * Returns: a #GstPad, or NULL when the stream number does not exist.
       
   956    */
       
   957   gst_play_bin_signals[SIGNAL_GET_VIDEO_PAD] =
       
   958       g_signal_new ("get-video-pad", G_TYPE_FROM_CLASS (klass),
       
   959       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
       
   960       G_STRUCT_OFFSET (GstPlayBinClass, get_video_pad), NULL, NULL,
       
   961       gst_play_marshal_OBJECT__INT, GST_TYPE_PAD, 1, G_TYPE_INT);
       
   962   /**
       
   963    * GstPlayBin2::get-audio-pad
       
   964    * @playbin: a #GstPlayBin2
       
   965    * @stream: an audio stream number
       
   966    *
       
   967    * Action signal to retrieve the stream-selector sinkpad for a specific 
       
   968    * audio stream.
       
   969    * This pad can be used for notifications of caps changes, stream-specific
       
   970    * queries, etc.
       
   971    *
       
   972    * Returns: a #GstPad, or NULL when the stream number does not exist.
       
   973    */
       
   974   gst_play_bin_signals[SIGNAL_GET_AUDIO_PAD] =
       
   975       g_signal_new ("get-audio-pad", G_TYPE_FROM_CLASS (klass),
       
   976       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
       
   977       G_STRUCT_OFFSET (GstPlayBinClass, get_audio_pad), NULL, NULL,
       
   978       gst_play_marshal_OBJECT__INT, GST_TYPE_PAD, 1, G_TYPE_INT);
       
   979   /**
       
   980    * GstPlayBin2::get-text-pad
       
   981    * @playbin: a #GstPlayBin2
       
   982    * @stream: a text stream number
       
   983    *
       
   984    * Action signal to retrieve the stream-selector sinkpad for a specific 
       
   985    * text stream.
       
   986    * This pad can be used for notifications of caps changes, stream-specific
       
   987    * queries, etc.
       
   988    *
       
   989    * Returns: a #GstPad, or NULL when the stream number does not exist.
       
   990    */
       
   991   gst_play_bin_signals[SIGNAL_GET_TEXT_PAD] =
       
   992       g_signal_new ("get-text-pad", G_TYPE_FROM_CLASS (klass),
       
   993       G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
       
   994       G_STRUCT_OFFSET (GstPlayBinClass, get_text_pad), NULL, NULL,
       
   995       gst_play_marshal_OBJECT__INT, GST_TYPE_PAD, 1, G_TYPE_INT);
       
   996 
       
   997   klass->get_video_tags = gst_play_bin_get_video_tags;
   794   klass->get_video_tags = gst_play_bin_get_video_tags;
   998   klass->get_audio_tags = gst_play_bin_get_audio_tags;
   795   klass->get_audio_tags = gst_play_bin_get_audio_tags;
   999   klass->get_text_tags = gst_play_bin_get_text_tags;
   796   klass->get_text_tags = gst_play_bin_get_text_tags;
  1000 
   797 
  1001   klass->convert_frame = gst_play_bin_convert_frame;
   798   klass->convert_frame = gst_play_bin_convert_frame;
  1002 
       
  1003   klass->get_video_pad = gst_play_bin_get_video_pad;
       
  1004   klass->get_audio_pad = gst_play_bin_get_audio_pad;
       
  1005   klass->get_text_pad = gst_play_bin_get_text_pad;
       
  1006 
   799 
  1007   gst_element_class_set_details (gstelement_klass, &gst_play_bin_details);
   800   gst_element_class_set_details (gstelement_klass, &gst_play_bin_details);
  1008 
   801 
  1009   gstelement_klass->change_state =
   802   gstelement_klass->change_state =
  1010       GST_DEBUG_FUNCPTR (gst_play_bin_change_state);
   803       GST_DEBUG_FUNCPTR (gst_play_bin_change_state);
  1018 {
   811 {
  1019   /* store the array for the different channels */
   812   /* store the array for the different channels */
  1020   group->video_channels = g_ptr_array_new ();
   813   group->video_channels = g_ptr_array_new ();
  1021   group->audio_channels = g_ptr_array_new ();
   814   group->audio_channels = g_ptr_array_new ();
  1022   group->text_channels = g_ptr_array_new ();
   815   group->text_channels = g_ptr_array_new ();
  1023   group->subp_channels = g_ptr_array_new ();
   816   /* init selectors */
  1024   group->lock = g_mutex_new ();
       
  1025   /* init selectors. The selector is found by finding the first prefix that
       
  1026    * matches the media. */
       
  1027   group->playbin = playbin;
   817   group->playbin = playbin;
  1028   /* If you add any items to these lists, check that media_list[] is defined
   818   group->selector[0].media = "audio/x-raw-";
  1029    * above to be large enough to hold MAX(items)+1, so as to accomodate a
       
  1030    * NULL terminator (set when the memory is zeroed on allocation) */
       
  1031   group->selector[0].media_list[0] = "audio/x-raw-";
       
  1032   group->selector[0].type = GST_PLAY_SINK_TYPE_AUDIO_RAW;
   819   group->selector[0].type = GST_PLAY_SINK_TYPE_AUDIO_RAW;
  1033   group->selector[0].channels = group->audio_channels;
   820   group->selector[0].channels = group->audio_channels;
  1034   group->selector[1].media_list[0] = "audio/";
   821   group->selector[1].media = "audio/";
  1035   group->selector[1].type = GST_PLAY_SINK_TYPE_AUDIO;
   822   group->selector[1].type = GST_PLAY_SINK_TYPE_AUDIO;
  1036   group->selector[1].channels = group->audio_channels;
   823   group->selector[1].channels = group->audio_channels;
  1037   group->selector[2].media_list[0] = "video/x-raw-";
   824   group->selector[2].media = "video/x-raw-";
  1038   group->selector[2].type = GST_PLAY_SINK_TYPE_VIDEO_RAW;
   825   group->selector[2].type = GST_PLAY_SINK_TYPE_VIDEO_RAW;
  1039   group->selector[2].channels = group->video_channels;
   826   group->selector[2].channels = group->video_channels;
  1040   group->selector[3].media_list[0] = "video/x-dvd-subpicture";
   827   group->selector[3].media = "video/";
  1041   group->selector[3].media_list[1] = "subpicture/x-pgs";
   828   group->selector[3].type = GST_PLAY_SINK_TYPE_VIDEO;
  1042   group->selector[3].type = GST_PLAY_SINK_TYPE_SUBPIC;
   829   group->selector[3].channels = group->video_channels;
  1043   group->selector[3].channels = group->subp_channels;
   830   group->selector[4].media = "text/";
  1044   group->selector[4].media_list[0] = "video/";
   831   group->selector[4].type = GST_PLAY_SINK_TYPE_TEXT;
  1045   group->selector[4].type = GST_PLAY_SINK_TYPE_VIDEO;
   832   group->selector[4].channels = group->text_channels;
  1046   group->selector[4].channels = group->video_channels;
       
  1047   group->selector[5].media_list[0] = "text/";
       
  1048   group->selector[5].type = GST_PLAY_SINK_TYPE_TEXT;
       
  1049   group->selector[5].channels = group->text_channels;
       
  1050 }
       
  1051 
       
  1052 static void
       
  1053 free_group (GstPlayBin * playbin, GstSourceGroup * group)
       
  1054 {
       
  1055   g_free (group->uri);
       
  1056   g_ptr_array_free (group->video_channels, TRUE);
       
  1057   g_ptr_array_free (group->audio_channels, TRUE);
       
  1058   g_ptr_array_free (group->text_channels, TRUE);
       
  1059   g_ptr_array_free (group->subp_channels, TRUE);
       
  1060   g_mutex_free (group->lock);
       
  1061   if (group->audio_sink)
       
  1062     gst_object_unref (group->audio_sink);
       
  1063   group->audio_sink = NULL;
       
  1064   if (group->video_sink)
       
  1065     gst_object_unref (group->video_sink);
       
  1066   group->video_sink = NULL;
       
  1067 }
   833 }
  1068 
   834 
  1069 static void
   835 static void
  1070 gst_play_bin_init (GstPlayBin * playbin)
   836 gst_play_bin_init (GstPlayBin * playbin)
  1071 {
   837 {
  1072   GstFactoryListType type;
   838   GstFactoryListType type;
  1073 
       
  1074   playbin->lock = g_mutex_new ();
       
  1075   playbin->dyn_lock = g_mutex_new ();
       
  1076 
       
  1077   /* assume we can create a selector */
       
  1078   playbin->have_selector = TRUE;
       
  1079 
   839 
  1080   /* init groups */
   840   /* init groups */
  1081   playbin->curr_group = &playbin->groups[0];
   841   playbin->curr_group = &playbin->groups[0];
  1082   playbin->next_group = &playbin->groups[1];
   842   playbin->next_group = &playbin->groups[1];
  1083   init_group (playbin, &playbin->groups[0]);
   843   init_group (playbin, &playbin->groups[0]);
  1091   /* add sink */
   851   /* add sink */
  1092   playbin->playsink = g_object_new (GST_TYPE_PLAY_SINK, NULL);
   852   playbin->playsink = g_object_new (GST_TYPE_PLAY_SINK, NULL);
  1093   gst_bin_add (GST_BIN_CAST (playbin), GST_ELEMENT_CAST (playbin->playsink));
   853   gst_bin_add (GST_BIN_CAST (playbin), GST_ELEMENT_CAST (playbin->playsink));
  1094   gst_play_sink_set_flags (playbin->playsink, DEFAULT_FLAGS);
   854   gst_play_sink_set_flags (playbin->playsink, DEFAULT_FLAGS);
  1095 
   855 
  1096   playbin->encoding = g_strdup (DEFAULT_SUBTITLE_ENCODING);
       
  1097 
       
  1098   playbin->current_video = DEFAULT_CURRENT_VIDEO;
   856   playbin->current_video = DEFAULT_CURRENT_VIDEO;
  1099   playbin->current_audio = DEFAULT_CURRENT_AUDIO;
   857   playbin->current_audio = DEFAULT_CURRENT_AUDIO;
  1100   playbin->current_text = DEFAULT_CURRENT_TEXT;
   858   playbin->current_text = DEFAULT_CURRENT_TEXT;
  1101 
       
  1102   playbin->buffer_duration = DEFAULT_BUFFER_DURATION;
       
  1103   playbin->buffer_size = DEFAULT_BUFFER_SIZE;
       
  1104 }
   859 }
  1105 
   860 
  1106 static void
   861 static void
  1107 gst_play_bin_finalize (GObject * object)
   862 gst_play_bin_finalize (GObject * object)
  1108 {
   863 {
  1109   GstPlayBin *playbin;
   864   GstPlayBin *playbin;
  1110 
   865 
  1111   playbin = GST_PLAY_BIN (object);
   866   playbin = GST_PLAY_BIN (object);
  1112 
   867 
  1113   free_group (playbin, &playbin->groups[0]);
       
  1114   free_group (playbin, &playbin->groups[1]);
       
  1115 
       
  1116   if (playbin->source)
       
  1117     gst_object_unref (playbin->source);
       
  1118   if (playbin->video_sink)
       
  1119     gst_object_unref (playbin->video_sink);
       
  1120   if (playbin->audio_sink)
       
  1121     gst_object_unref (playbin->audio_sink);
       
  1122   if (playbin->text_sink)
       
  1123     gst_object_unref (playbin->text_sink);
       
  1124   if (playbin->subpic_sink)
       
  1125     gst_object_unref (playbin->subpic_sink);
       
  1126 
       
  1127   g_value_array_free (playbin->elements);
   868   g_value_array_free (playbin->elements);
  1128   g_free (playbin->encoding);
       
  1129   g_mutex_free (playbin->lock);
       
  1130   g_mutex_free (playbin->dyn_lock);
       
  1131 
   869 
  1132   G_OBJECT_CLASS (parent_class)->finalize (object);
   870   G_OBJECT_CLASS (parent_class)->finalize (object);
  1133 }
   871 }
  1134 
   872 
  1135 static void
   873 static void
  1140   if (uri == NULL) {
   878   if (uri == NULL) {
  1141     g_warning ("cannot set NULL uri");
   879     g_warning ("cannot set NULL uri");
  1142     return;
   880     return;
  1143   }
   881   }
  1144 
   882 
  1145   GST_PLAY_BIN_LOCK (playbin);
   883   GST_OBJECT_LOCK (playbin);
  1146   group = playbin->next_group;
   884   group = playbin->next_group;
  1147 
   885 
  1148   GST_SOURCE_GROUP_LOCK (group);
   886   /* if we have no previous uri, or the new uri is different from the
  1149   /* store the uri in the next group we will play */
   887    * old one, replug */
  1150   g_free (group->uri);
   888   g_free (group->uri);
  1151   group->uri = g_strdup (uri);
   889   group->uri = g_strdup (uri);
  1152   group->valid = TRUE;
   890   group->valid = TRUE;
  1153   GST_SOURCE_GROUP_UNLOCK (group);
   891 
  1154 
   892   GST_DEBUG ("setting new uri to %s", uri);
  1155   GST_DEBUG ("set new uri to %s", uri);
   893   GST_OBJECT_UNLOCK (playbin);
  1156   GST_PLAY_BIN_UNLOCK (playbin);
       
  1157 }
   894 }
  1158 
   895 
  1159 static void
   896 static void
  1160 gst_play_bin_set_suburi (GstPlayBin * playbin, const gchar * suburi)
   897 gst_play_bin_set_suburi (GstPlayBin * playbin, const gchar * suburi)
  1161 {
   898 {
  1162   GstSourceGroup *group;
   899   GstSourceGroup *group;
  1163 
   900 
  1164   GST_PLAY_BIN_LOCK (playbin);
   901   GST_OBJECT_LOCK (playbin);
  1165   group = playbin->next_group;
   902   group = playbin->next_group;
  1166 
   903 
  1167   GST_SOURCE_GROUP_LOCK (group);
   904   if ((!suburi && !group->suburi) ||
       
   905       (suburi && group->suburi && !strcmp (group->suburi, suburi)))
       
   906     goto done;
       
   907 
  1168   g_free (group->suburi);
   908   g_free (group->suburi);
  1169   group->suburi = g_strdup (suburi);
   909   group->suburi = g_strdup (suburi);
  1170   GST_SOURCE_GROUP_UNLOCK (group);
       
  1171 
   910 
  1172   GST_DEBUG ("setting new .sub uri to %s", suburi);
   911   GST_DEBUG ("setting new .sub uri to %s", suburi);
  1173 
   912 
  1174   GST_PLAY_BIN_UNLOCK (playbin);
   913 done:
  1175 }
   914   GST_OBJECT_UNLOCK (playbin);
  1176 
       
  1177 static void
       
  1178 gst_play_bin_set_flags (GstPlayBin * playbin, GstPlayFlags flags)
       
  1179 {
       
  1180   gst_play_sink_set_flags (playbin->playsink, flags);
       
  1181   gst_play_sink_reconfigure (playbin->playsink);
       
  1182 }
       
  1183 
       
  1184 static GstPlayFlags
       
  1185 gst_play_bin_get_flags (GstPlayBin * playbin)
       
  1186 {
       
  1187   GstPlayFlags flags;
       
  1188 
       
  1189   flags = gst_play_sink_get_flags (playbin->playsink);
       
  1190 
       
  1191   return flags;
       
  1192 }
   915 }
  1193 
   916 
  1194 /* get the currently playing group or if nothing is playing, the next
   917 /* get the currently playing group or if nothing is playing, the next
  1195  * group. Must be called with the PLAY_BIN_LOCK. */
   918  * group. Must be called with the LOCK. */
  1196 static GstSourceGroup *
   919 static GstSourceGroup *
  1197 get_group (GstPlayBin * playbin)
   920 get_group (GstPlayBin * playbin)
  1198 {
   921 {
  1199   GstSourceGroup *result;
   922   GstSourceGroup *result;
  1200 
   923 
  1202     result = playbin->next_group;
   925     result = playbin->next_group;
  1203 
   926 
  1204   return result;
   927   return result;
  1205 }
   928 }
  1206 
   929 
  1207 static GstPad *
       
  1208 gst_play_bin_get_video_pad (GstPlayBin * playbin, gint stream)
       
  1209 {
       
  1210   GstPad *sinkpad = NULL;
       
  1211   GstSourceGroup *group;
       
  1212 
       
  1213   GST_PLAY_BIN_LOCK (playbin);
       
  1214   group = get_group (playbin);
       
  1215   if (stream < group->video_channels->len) {
       
  1216     sinkpad = g_ptr_array_index (group->video_channels, stream);
       
  1217     gst_object_ref (sinkpad);
       
  1218   }
       
  1219   GST_PLAY_BIN_UNLOCK (playbin);
       
  1220 
       
  1221   return sinkpad;
       
  1222 }
       
  1223 
       
  1224 static GstPad *
       
  1225 gst_play_bin_get_audio_pad (GstPlayBin * playbin, gint stream)
       
  1226 {
       
  1227   GstPad *sinkpad = NULL;
       
  1228   GstSourceGroup *group;
       
  1229 
       
  1230   GST_PLAY_BIN_LOCK (playbin);
       
  1231   group = get_group (playbin);
       
  1232   if (stream < group->audio_channels->len) {
       
  1233     sinkpad = g_ptr_array_index (group->audio_channels, stream);
       
  1234     gst_object_ref (sinkpad);
       
  1235   }
       
  1236   GST_PLAY_BIN_UNLOCK (playbin);
       
  1237 
       
  1238   return sinkpad;
       
  1239 }
       
  1240 
       
  1241 static GstPad *
       
  1242 gst_play_bin_get_text_pad (GstPlayBin * playbin, gint stream)
       
  1243 {
       
  1244   GstPad *sinkpad = NULL;
       
  1245   GstSourceGroup *group;
       
  1246 
       
  1247   GST_PLAY_BIN_LOCK (playbin);
       
  1248   group = get_group (playbin);
       
  1249   if (stream < group->text_channels->len) {
       
  1250     sinkpad = g_ptr_array_index (group->text_channels, stream);
       
  1251     gst_object_ref (sinkpad);
       
  1252   }
       
  1253   GST_PLAY_BIN_UNLOCK (playbin);
       
  1254 
       
  1255   return sinkpad;
       
  1256 }
       
  1257 
       
  1258 
       
  1259 static GstTagList *
   930 static GstTagList *
  1260 get_tags (GstPlayBin * playbin, GPtrArray * channels, gint stream)
   931 get_tags (GstPlayBin * playbin, GPtrArray * channels, gint stream)
  1261 {
   932 {
  1262   GstTagList *result;
   933   GstTagList *result;
  1263   GstPad *sinkpad;
   934   GstPad *sinkpad;
  1264 
   935 
  1265   if (!channels || stream >= channels->len)
   936   if (!channels || channels->len < stream)
  1266     return NULL;
   937     return NULL;
  1267 
   938 
  1268   sinkpad = g_ptr_array_index (channels, stream);
   939   sinkpad = g_ptr_array_index (channels, stream);
  1269   g_object_get (sinkpad, "tags", &result, NULL);
   940   g_object_get (sinkpad, "tags", &result, NULL);
  1270 
   941 
  1275 gst_play_bin_get_video_tags (GstPlayBin * playbin, gint stream)
   946 gst_play_bin_get_video_tags (GstPlayBin * playbin, gint stream)
  1276 {
   947 {
  1277   GstTagList *result;
   948   GstTagList *result;
  1278   GstSourceGroup *group;
   949   GstSourceGroup *group;
  1279 
   950 
  1280   GST_PLAY_BIN_LOCK (playbin);
   951   GST_OBJECT_LOCK (playbin);
  1281   group = get_group (playbin);
   952   group = get_group (playbin);
  1282   result = get_tags (playbin, group->video_channels, stream);
   953   result = get_tags (playbin, group->video_channels, stream);
  1283   GST_PLAY_BIN_UNLOCK (playbin);
   954   GST_OBJECT_UNLOCK (playbin);
  1284 
   955 
  1285   return result;
   956   return result;
  1286 }
   957 }
  1287 
   958 
  1288 static GstTagList *
   959 static GstTagList *
  1289 gst_play_bin_get_audio_tags (GstPlayBin * playbin, gint stream)
   960 gst_play_bin_get_audio_tags (GstPlayBin * playbin, gint stream)
  1290 {
   961 {
  1291   GstTagList *result;
   962   GstTagList *result;
  1292   GstSourceGroup *group;
   963   GstSourceGroup *group;
  1293 
   964 
  1294   GST_PLAY_BIN_LOCK (playbin);
   965   GST_OBJECT_LOCK (playbin);
  1295   group = get_group (playbin);
   966   group = get_group (playbin);
  1296   result = get_tags (playbin, group->audio_channels, stream);
   967   result = get_tags (playbin, group->audio_channels, stream);
  1297   GST_PLAY_BIN_UNLOCK (playbin);
   968   GST_OBJECT_UNLOCK (playbin);
  1298 
   969 
  1299   return result;
   970   return result;
  1300 }
   971 }
  1301 
   972 
  1302 static GstTagList *
   973 static GstTagList *
  1303 gst_play_bin_get_text_tags (GstPlayBin * playbin, gint stream)
   974 gst_play_bin_get_text_tags (GstPlayBin * playbin, gint stream)
  1304 {
   975 {
  1305   GstTagList *result;
   976   GstTagList *result;
  1306   GstSourceGroup *group;
   977   GstSourceGroup *group;
  1307 
   978 
  1308   GST_PLAY_BIN_LOCK (playbin);
   979   GST_OBJECT_LOCK (playbin);
  1309   group = get_group (playbin);
   980   group = get_group (playbin);
  1310   result = get_tags (playbin, group->text_channels, stream);
   981   result = get_tags (playbin, group->text_channels, stream);
  1311   GST_PLAY_BIN_UNLOCK (playbin);
   982   GST_OBJECT_UNLOCK (playbin);
  1312 
   983 
  1313   return result;
   984   return result;
  1314 }
   985 }
  1315 
   986 
  1316 static GstBuffer *
   987 static GstBuffer *
  1327     result = temp;
   998     result = temp;
  1328   }
   999   }
  1329   return result;
  1000   return result;
  1330 }
  1001 }
  1331 
  1002 
  1332 /* Returns current stream number, or -1 if none has been selected yet */
       
  1333 static int
       
  1334 get_current_stream_number (GstPlayBin * playbin, GPtrArray * channels)
       
  1335 {
       
  1336   /* Internal API cleanup would make this easier... */
       
  1337   int i;
       
  1338   GstPad *pad, *current;
       
  1339   GstObject *selector = NULL;
       
  1340   int ret = -1;
       
  1341 
       
  1342   for (i = 0; i < channels->len; i++) {
       
  1343     pad = g_ptr_array_index (channels, i);
       
  1344     if ((selector = gst_pad_get_parent (pad))) {
       
  1345       g_object_get (selector, "active-pad", &current, NULL);
       
  1346       gst_object_unref (selector);
       
  1347 
       
  1348       if (pad == current) {
       
  1349         gst_object_unref (current);
       
  1350         ret = i;
       
  1351         break;
       
  1352       }
       
  1353 
       
  1354       if (current)
       
  1355         gst_object_unref (current);
       
  1356     }
       
  1357   }
       
  1358 
       
  1359   return ret;
       
  1360 }
       
  1361 
       
  1362 static gboolean
  1003 static gboolean
  1363 gst_play_bin_set_current_video_stream (GstPlayBin * playbin, gint stream)
  1004 gst_play_bin_set_current_video_stream (GstPlayBin * playbin, gint stream)
  1364 {
  1005 {
  1365   GstSourceGroup *group;
  1006   GstSourceGroup *group;
  1366   GPtrArray *channels;
  1007   GPtrArray *channels;
  1367   GstPad *sinkpad;
  1008   GstPad *sinkpad;
  1368 
  1009 
  1369   GST_PLAY_BIN_LOCK (playbin);
  1010   GST_OBJECT_LOCK (playbin);
  1370   group = get_group (playbin);
  1011   group = get_group (playbin);
  1371   if (!(channels = group->video_channels))
  1012   if (!(channels = group->video_channels))
  1372     goto no_channels;
  1013     goto no_channels;
  1373 
  1014 
  1374   if (stream == -1 || channels->len <= stream) {
  1015   if (stream == -1 || channels->len < stream) {
  1375     sinkpad = NULL;
  1016     sinkpad = NULL;
  1376   } else {
  1017   } else {
  1377     /* take channel from selected stream */
  1018     /* take channel from selected stream */
  1378     sinkpad = g_ptr_array_index (channels, stream);
  1019     sinkpad = g_ptr_array_index (channels, stream);
  1379   }
  1020   }
  1380 
  1021 
  1381   if (sinkpad)
  1022   if (sinkpad)
  1382     gst_object_ref (sinkpad);
  1023     gst_object_ref (sinkpad);
  1383   GST_PLAY_BIN_UNLOCK (playbin);
  1024   GST_OBJECT_UNLOCK (playbin);
  1384 
  1025 
  1385   if (sinkpad) {
  1026   if (sinkpad) {
  1386     GstObject *selector;
  1027     GstObject *selector;
  1387 
  1028 
  1388     if ((selector = gst_pad_get_parent (sinkpad))) {
  1029     if ((selector = gst_pad_get_parent (sinkpad))) {
  1394   }
  1035   }
  1395   return TRUE;
  1036   return TRUE;
  1396 
  1037 
  1397 no_channels:
  1038 no_channels:
  1398   {
  1039   {
  1399     GST_PLAY_BIN_UNLOCK (playbin);
  1040     GST_OBJECT_UNLOCK (playbin);
  1400     return FALSE;
  1041     return FALSE;
  1401   }
  1042   }
  1402 }
  1043 }
  1403 
  1044 
  1404 static gboolean
  1045 static gboolean
  1406 {
  1047 {
  1407   GstSourceGroup *group;
  1048   GstSourceGroup *group;
  1408   GPtrArray *channels;
  1049   GPtrArray *channels;
  1409   GstPad *sinkpad;
  1050   GstPad *sinkpad;
  1410 
  1051 
  1411   GST_PLAY_BIN_LOCK (playbin);
  1052   GST_OBJECT_LOCK (playbin);
  1412   group = get_group (playbin);
  1053   group = get_group (playbin);
  1413   if (!(channels = group->audio_channels))
  1054   if (!(channels = group->audio_channels))
  1414     goto no_channels;
  1055     goto no_channels;
  1415 
  1056 
  1416   if (stream == -1 || channels->len <= stream) {
  1057   if (stream == -1 || channels->len < stream) {
  1417     sinkpad = NULL;
  1058     sinkpad = NULL;
  1418   } else {
  1059   } else {
  1419     /* take channel from selected stream */
  1060     /* take channel from selected stream */
  1420     sinkpad = g_ptr_array_index (channels, stream);
  1061     sinkpad = g_ptr_array_index (channels, stream);
  1421   }
  1062   }
  1422 
  1063 
  1423   if (sinkpad)
  1064   if (sinkpad)
  1424     gst_object_ref (sinkpad);
  1065     gst_object_ref (sinkpad);
  1425   GST_PLAY_BIN_UNLOCK (playbin);
  1066   GST_OBJECT_UNLOCK (playbin);
  1426 
  1067 
  1427   if (sinkpad) {
  1068   if (sinkpad) {
  1428     GstObject *selector;
  1069     GstObject *selector;
  1429 
  1070 
  1430     if ((selector = gst_pad_get_parent (sinkpad))) {
  1071     if ((selector = gst_pad_get_parent (sinkpad))) {
  1436   }
  1077   }
  1437   return TRUE;
  1078   return TRUE;
  1438 
  1079 
  1439 no_channels:
  1080 no_channels:
  1440   {
  1081   {
  1441     GST_PLAY_BIN_UNLOCK (playbin);
  1082     GST_OBJECT_UNLOCK (playbin);
  1442     return FALSE;
  1083     return FALSE;
  1443   }
  1084   }
  1444 }
  1085 }
  1445 
  1086 
  1446 static gboolean
  1087 static gboolean
  1448 {
  1089 {
  1449   GstSourceGroup *group;
  1090   GstSourceGroup *group;
  1450   GPtrArray *channels;
  1091   GPtrArray *channels;
  1451   GstPad *sinkpad;
  1092   GstPad *sinkpad;
  1452 
  1093 
  1453   GST_PLAY_BIN_LOCK (playbin);
  1094   GST_OBJECT_LOCK (playbin);
  1454   group = get_group (playbin);
  1095   group = get_group (playbin);
  1455   if (!(channels = group->text_channels))
  1096   if (!(channels = group->text_channels))
  1456     goto no_channels;
  1097     goto no_channels;
  1457 
  1098 
  1458   if (stream == -1 || channels->len <= stream) {
  1099   if (stream == -1 || channels->len < stream) {
  1459     sinkpad = NULL;
  1100     sinkpad = NULL;
  1460   } else {
  1101   } else {
  1461     /* take channel from selected stream */
  1102     /* take channel from selected stream */
  1462     sinkpad = g_ptr_array_index (channels, stream);
  1103     sinkpad = g_ptr_array_index (channels, stream);
  1463   }
  1104   }
  1464 
  1105 
  1465   if (sinkpad)
  1106   if (sinkpad)
  1466     gst_object_ref (sinkpad);
  1107     gst_object_ref (sinkpad);
  1467   GST_PLAY_BIN_UNLOCK (playbin);
  1108   GST_OBJECT_UNLOCK (playbin);
  1468 
  1109 
  1469   if (sinkpad) {
  1110   if (sinkpad) {
  1470     GstObject *selector;
  1111     GstObject *selector;
  1471 
  1112 
  1472     if ((selector = gst_pad_get_parent (sinkpad))) {
  1113     if ((selector = gst_pad_get_parent (sinkpad))) {
  1478   }
  1119   }
  1479   return TRUE;
  1120   return TRUE;
  1480 
  1121 
  1481 no_channels:
  1122 no_channels:
  1482   {
  1123   {
  1483     GST_PLAY_BIN_UNLOCK (playbin);
  1124     GST_OBJECT_UNLOCK (playbin);
  1484     return FALSE;
  1125     return FALSE;
  1485   }
  1126   }
  1486 }
       
  1487 
       
  1488 static void
       
  1489 gst_play_bin_set_encoding (GstPlayBin * playbin, const gchar * encoding)
       
  1490 {
       
  1491   GstElement *elem;
       
  1492 
       
  1493   GST_PLAY_BIN_LOCK (playbin);
       
  1494   g_free (playbin->encoding);
       
  1495   playbin->encoding = g_strdup (encoding);
       
  1496 
       
  1497   /* set subtitles on all current and next decodebins. */
       
  1498   if ((elem = playbin->groups[0].uridecodebin))
       
  1499     g_object_set (G_OBJECT (elem), "subtitle-encoding", encoding, NULL);
       
  1500   if ((elem = playbin->groups[0].suburidecodebin))
       
  1501     g_object_set (G_OBJECT (elem), "subtitle-encoding", encoding, NULL);
       
  1502   if ((elem = playbin->groups[1].uridecodebin))
       
  1503     g_object_set (G_OBJECT (elem), "subtitle-encoding", encoding, NULL);
       
  1504   if ((elem = playbin->groups[1].suburidecodebin))
       
  1505     g_object_set (G_OBJECT (elem), "subtitle-encoding", encoding, NULL);
       
  1506   GST_PLAY_BIN_UNLOCK (playbin);
       
  1507 }
       
  1508 
       
  1509 static void
       
  1510 gst_play_bin_set_sink (GstPlayBin * playbin, GstElement ** elem,
       
  1511     const gchar * dbg, GstElement * sink)
       
  1512 {
       
  1513   GST_INFO_OBJECT (playbin, "Setting %s sink to %" GST_PTR_FORMAT, dbg, sink);
       
  1514 
       
  1515   GST_PLAY_BIN_LOCK (playbin);
       
  1516   if (*elem != sink) {
       
  1517     GstElement *old;
       
  1518 
       
  1519     old = *elem;
       
  1520     if (sink) {
       
  1521       gst_object_ref (sink);
       
  1522       gst_object_sink (sink);
       
  1523     }
       
  1524     *elem = sink;
       
  1525     if (old)
       
  1526       gst_object_unref (old);
       
  1527   }
       
  1528   GST_LOG_OBJECT (playbin, "%s sink now %" GST_PTR_FORMAT, dbg, *elem);
       
  1529   GST_PLAY_BIN_UNLOCK (playbin);
       
  1530 }
  1127 }
  1531 
  1128 
  1532 static void
  1129 static void
  1533 gst_play_bin_set_property (GObject * object, guint prop_id,
  1130 gst_play_bin_set_property (GObject * object, guint prop_id,
  1534     const GValue * value, GParamSpec * pspec)
  1131     const GValue * value, GParamSpec * pspec)
  1543       break;
  1140       break;
  1544     case PROP_SUBURI:
  1141     case PROP_SUBURI:
  1545       gst_play_bin_set_suburi (playbin, g_value_get_string (value));
  1142       gst_play_bin_set_suburi (playbin, g_value_get_string (value));
  1546       break;
  1143       break;
  1547     case PROP_FLAGS:
  1144     case PROP_FLAGS:
  1548       gst_play_bin_set_flags (playbin, g_value_get_flags (value));
  1145       gst_play_sink_set_flags (playbin->playsink, g_value_get_flags (value));
  1549       break;
  1146       break;
  1550     case PROP_CURRENT_VIDEO:
  1147     case PROP_CURRENT_VIDEO:
  1551       gst_play_bin_set_current_video_stream (playbin, g_value_get_int (value));
  1148       gst_play_bin_set_current_video_stream (playbin, g_value_get_int (value));
  1552       break;
  1149       break;
  1553     case PROP_CURRENT_AUDIO:
  1150     case PROP_CURRENT_AUDIO:
  1555       break;
  1152       break;
  1556     case PROP_CURRENT_TEXT:
  1153     case PROP_CURRENT_TEXT:
  1557       gst_play_bin_set_current_text_stream (playbin, g_value_get_int (value));
  1154       gst_play_bin_set_current_text_stream (playbin, g_value_get_int (value));
  1558       break;
  1155       break;
  1559     case PROP_SUBTITLE_ENCODING:
  1156     case PROP_SUBTITLE_ENCODING:
  1560       gst_play_bin_set_encoding (playbin, g_value_get_string (value));
       
  1561       break;
  1157       break;
  1562     case PROP_VIDEO_SINK:
  1158     case PROP_VIDEO_SINK:
  1563       gst_play_bin_set_sink (playbin, &playbin->video_sink, "video",
       
  1564           g_value_get_object (value));
       
  1565       break;
  1159       break;
  1566     case PROP_AUDIO_SINK:
  1160     case PROP_AUDIO_SINK:
  1567       gst_play_bin_set_sink (playbin, &playbin->audio_sink, "audio",
       
  1568           g_value_get_object (value));
       
  1569       break;
  1161       break;
  1570     case PROP_VIS_PLUGIN:
  1162     case PROP_VIS_PLUGIN:
  1571       gst_play_sink_set_vis_plugin (playbin->playsink,
  1163       gst_play_sink_set_vis_plugin (playbin->playsink,
  1572           g_value_get_object (value));
  1164           g_value_get_object (value));
  1573       break;
  1165       break;
  1574     case PROP_TEXT_SINK:
       
  1575       gst_play_bin_set_sink (playbin, &playbin->text_sink, "text",
       
  1576           g_value_get_object (value));
       
  1577       break;
       
  1578     case PROP_SUBPIC_SINK:
       
  1579       gst_play_bin_set_sink (playbin, &playbin->subpic_sink, "subpicture",
       
  1580           g_value_get_object (value));
       
  1581       break;
       
  1582     case PROP_VOLUME:
  1166     case PROP_VOLUME:
  1583       gst_play_sink_set_volume (playbin->playsink, g_value_get_double (value));
  1167       gst_play_sink_set_volume (playbin->playsink, g_value_get_double (value));
  1584       break;
  1168       break;
  1585     case PROP_MUTE:
  1169     case PROP_MUTE:
  1586       gst_play_sink_set_mute (playbin->playsink, g_value_get_boolean (value));
  1170       gst_play_sink_set_mute (playbin->playsink, g_value_get_boolean (value));
  1587       break;
  1171       break;
  1588     case PROP_FONT_DESC:
  1172     case PROP_FONT_DESC:
  1589       gst_play_sink_set_font_desc (playbin->playsink,
       
  1590           g_value_get_string (value));
       
  1591       break;
  1173       break;
  1592     case PROP_CONNECTION_SPEED:
  1174     case PROP_CONNECTION_SPEED:
  1593       GST_PLAY_BIN_LOCK (playbin);
  1175       GST_OBJECT_LOCK (playbin);
  1594       playbin->connection_speed = g_value_get_uint (value) * 1000;
  1176       playbin->connection_speed = g_value_get_uint (value) * 1000;
  1595       GST_PLAY_BIN_UNLOCK (playbin);
  1177       GST_OBJECT_UNLOCK (playbin);
  1596       break;
       
  1597     case PROP_BUFFER_SIZE:
       
  1598       playbin->buffer_size = g_value_get_int (value);
       
  1599       break;
       
  1600     case PROP_BUFFER_DURATION:
       
  1601       playbin->buffer_duration = g_value_get_int64 (value);
       
  1602       break;
  1178       break;
  1603     default:
  1179     default:
  1604       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  1180       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  1605       break;
  1181       break;
  1606   }
  1182   }
  1607 }
       
  1608 
       
  1609 static GstElement *
       
  1610 gst_play_bin_get_current_sink (GstPlayBin * playbin, GstElement ** elem,
       
  1611     const gchar * dbg, GstPlaySinkType type)
       
  1612 {
       
  1613   GstElement *sink;
       
  1614 
       
  1615   sink = gst_play_sink_get_sink (playbin->playsink, type);
       
  1616 
       
  1617   GST_LOG_OBJECT (playbin, "play_sink_get_sink() returned %s sink %"
       
  1618       GST_PTR_FORMAT ", the originally set %s sink is %" GST_PTR_FORMAT,
       
  1619       dbg, sink, dbg, *elem);
       
  1620 
       
  1621   if (sink == NULL)
       
  1622     sink = *elem;
       
  1623 
       
  1624   return sink;
       
  1625 }
  1183 }
  1626 
  1184 
  1627 static void
  1185 static void
  1628 gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value,
  1186 gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value,
  1629     GParamSpec * pspec)
  1187     GParamSpec * pspec)
  1635   switch (prop_id) {
  1193   switch (prop_id) {
  1636     case PROP_URI:
  1194     case PROP_URI:
  1637     {
  1195     {
  1638       GstSourceGroup *group;
  1196       GstSourceGroup *group;
  1639 
  1197 
  1640       GST_PLAY_BIN_LOCK (playbin);
  1198       GST_OBJECT_LOCK (playbin);
  1641       group = get_group (playbin);
  1199       group = get_group (playbin);
  1642       g_value_set_string (value, group->uri);
  1200       g_value_set_string (value, group->uri);
  1643       GST_PLAY_BIN_UNLOCK (playbin);
  1201       GST_OBJECT_UNLOCK (playbin);
  1644       break;
  1202       break;
  1645     }
  1203     }
  1646     case PROP_SUBURI:
  1204     case PROP_SUBURI:
  1647     {
  1205     {
  1648       GstSourceGroup *group;
  1206       GstSourceGroup *group;
  1649 
  1207 
  1650       GST_PLAY_BIN_LOCK (playbin);
  1208       GST_OBJECT_LOCK (playbin);
  1651       group = get_group (playbin);
  1209       group = get_group (playbin);
  1652       g_value_set_string (value, group->suburi);
  1210       g_value_set_string (value, group->suburi);
  1653       GST_PLAY_BIN_UNLOCK (playbin);
  1211       GST_OBJECT_UNLOCK (playbin);
  1654       break;
  1212       break;
  1655     }
  1213     }
  1656     case PROP_SOURCE:
  1214     case PROP_SOURCE:
  1657     {
  1215       break;
  1658       GST_OBJECT_LOCK (playbin);
       
  1659       g_value_set_object (value, playbin->source);
       
  1660       GST_OBJECT_UNLOCK (playbin);
       
  1661       break;
       
  1662     }
       
  1663     case PROP_FLAGS:
  1216     case PROP_FLAGS:
  1664       g_value_set_flags (value, gst_play_bin_get_flags (playbin));
  1217       g_value_set_flags (value, gst_play_sink_get_flags (playbin->playsink));
  1665       break;
  1218       break;
  1666     case PROP_N_VIDEO:
  1219     case PROP_N_VIDEO:
  1667     {
  1220     {
  1668       GstSourceGroup *group;
  1221       GstSourceGroup *group;
  1669       gint n_video;
  1222       gint n_video;
  1670 
  1223 
  1671       GST_PLAY_BIN_LOCK (playbin);
  1224       GST_OBJECT_LOCK (playbin);
  1672       group = get_group (playbin);
  1225       group = get_group (playbin);
  1673       n_video = (group->video_channels ? group->video_channels->len : 0);
  1226       n_video = (group->video_channels ? group->video_channels->len : 0);
  1674       g_value_set_int (value, n_video);
  1227       g_value_set_int (value, n_video);
  1675       GST_PLAY_BIN_UNLOCK (playbin);
  1228       GST_OBJECT_UNLOCK (playbin);
  1676       break;
  1229       break;
  1677     }
  1230     }
  1678     case PROP_CURRENT_VIDEO:
  1231     case PROP_CURRENT_VIDEO:
  1679       GST_PLAY_BIN_LOCK (playbin);
  1232       GST_OBJECT_LOCK (playbin);
  1680       g_value_set_int (value, playbin->current_video);
  1233       g_value_set_int (value, playbin->current_video);
  1681       GST_PLAY_BIN_UNLOCK (playbin);
  1234       GST_OBJECT_UNLOCK (playbin);
  1682       break;
  1235       break;
  1683     case PROP_N_AUDIO:
  1236     case PROP_N_AUDIO:
  1684     {
  1237     {
  1685       GstSourceGroup *group;
  1238       GstSourceGroup *group;
  1686       gint n_audio;
  1239       gint n_audio;
  1687 
  1240 
  1688       GST_PLAY_BIN_LOCK (playbin);
  1241       GST_OBJECT_LOCK (playbin);
  1689       group = get_group (playbin);
  1242       group = get_group (playbin);
  1690       n_audio = (group->audio_channels ? group->audio_channels->len : 0);
  1243       n_audio = (group->audio_channels ? group->audio_channels->len : 0);
  1691       g_value_set_int (value, n_audio);
  1244       g_value_set_int (value, n_audio);
  1692       GST_PLAY_BIN_UNLOCK (playbin);
  1245       GST_OBJECT_UNLOCK (playbin);
  1693       break;
  1246       break;
  1694     }
  1247     }
  1695     case PROP_CURRENT_AUDIO:
  1248     case PROP_CURRENT_AUDIO:
  1696       GST_PLAY_BIN_LOCK (playbin);
  1249       GST_OBJECT_LOCK (playbin);
  1697       g_value_set_int (value, playbin->current_audio);
  1250       g_value_set_int (value, playbin->current_audio);
  1698       GST_PLAY_BIN_UNLOCK (playbin);
  1251       GST_OBJECT_UNLOCK (playbin);
  1699       break;
  1252       break;
  1700     case PROP_N_TEXT:
  1253     case PROP_N_TEXT:
  1701     {
  1254     {
  1702       GstSourceGroup *group;
  1255       GstSourceGroup *group;
  1703       gint n_text;
  1256       gint n_text;
  1704 
  1257 
  1705       GST_PLAY_BIN_LOCK (playbin);
  1258       GST_OBJECT_LOCK (playbin);
  1706       group = get_group (playbin);
  1259       group = get_group (playbin);
  1707       n_text = (group->text_channels ? group->text_channels->len : 0);
  1260       n_text = (group->text_channels ? group->text_channels->len : 0);
  1708       g_value_set_int (value, n_text);
  1261       g_value_set_int (value, n_text);
  1709       GST_PLAY_BIN_UNLOCK (playbin);
  1262       GST_OBJECT_UNLOCK (playbin);
  1710       break;
  1263       break;
  1711     }
  1264     }
  1712     case PROP_CURRENT_TEXT:
  1265     case PROP_CURRENT_TEXT:
  1713       GST_PLAY_BIN_LOCK (playbin);
  1266       GST_OBJECT_LOCK (playbin);
  1714       g_value_set_int (value, playbin->current_text);
  1267       g_value_set_int (value, playbin->current_text);
  1715       GST_PLAY_BIN_UNLOCK (playbin);
  1268       GST_OBJECT_UNLOCK (playbin);
  1716       break;
  1269       break;
  1717     case PROP_SUBTITLE_ENCODING:
  1270     case PROP_SUBTITLE_ENCODING:
  1718       GST_PLAY_BIN_LOCK (playbin);
       
  1719       g_value_set_string (value, playbin->encoding);
       
  1720       GST_PLAY_BIN_UNLOCK (playbin);
       
  1721       break;
  1271       break;
  1722     case PROP_VIDEO_SINK:
  1272     case PROP_VIDEO_SINK:
  1723       g_value_set_object (value,
       
  1724           gst_play_bin_get_current_sink (playbin, &playbin->video_sink,
       
  1725               "video", GST_PLAY_SINK_TYPE_VIDEO));
       
  1726       break;
  1273       break;
  1727     case PROP_AUDIO_SINK:
  1274     case PROP_AUDIO_SINK:
  1728       g_value_set_object (value,
       
  1729           gst_play_bin_get_current_sink (playbin, &playbin->audio_sink,
       
  1730               "audio", GST_PLAY_SINK_TYPE_AUDIO));
       
  1731       break;
  1275       break;
  1732     case PROP_VIS_PLUGIN:
  1276     case PROP_VIS_PLUGIN:
  1733       g_value_set_object (value,
       
  1734           gst_play_sink_get_vis_plugin (playbin->playsink));
       
  1735       break;
       
  1736     case PROP_TEXT_SINK:
       
  1737       g_value_set_object (value,
       
  1738           gst_play_bin_get_current_sink (playbin, &playbin->text_sink,
       
  1739               "text", GST_PLAY_SINK_TYPE_TEXT));
       
  1740       break;
       
  1741     case PROP_SUBPIC_SINK:
       
  1742       g_value_set_object (value,
       
  1743           gst_play_bin_get_current_sink (playbin, &playbin->subpic_sink,
       
  1744               "subpicture", GST_PLAY_SINK_TYPE_SUBPIC));
       
  1745       break;
  1277       break;
  1746     case PROP_VOLUME:
  1278     case PROP_VOLUME:
  1747       g_value_set_double (value, gst_play_sink_get_volume (playbin->playsink));
  1279       g_value_set_double (value, gst_play_sink_get_volume (playbin->playsink));
  1748       break;
  1280       break;
  1749     case PROP_MUTE:
  1281     case PROP_MUTE:
  1751       break;
  1283       break;
  1752     case PROP_FRAME:
  1284     case PROP_FRAME:
  1753       gst_value_take_buffer (value, gst_play_bin_convert_frame (playbin, NULL));
  1285       gst_value_take_buffer (value, gst_play_bin_convert_frame (playbin, NULL));
  1754       break;
  1286       break;
  1755     case PROP_FONT_DESC:
  1287     case PROP_FONT_DESC:
  1756       g_value_take_string (value,
       
  1757           gst_play_sink_get_font_desc (playbin->playsink));
       
  1758       break;
  1288       break;
  1759     case PROP_CONNECTION_SPEED:
  1289     case PROP_CONNECTION_SPEED:
  1760       GST_PLAY_BIN_LOCK (playbin);
  1290       GST_OBJECT_LOCK (playbin);
  1761       g_value_set_uint (value, playbin->connection_speed / 1000);
  1291       g_value_set_uint (value, playbin->connection_speed / 1000);
  1762       GST_PLAY_BIN_UNLOCK (playbin);
       
  1763       break;
       
  1764     case PROP_BUFFER_SIZE:
       
  1765       GST_OBJECT_LOCK (playbin);
       
  1766       g_value_set_int (value, playbin->buffer_size);
       
  1767       GST_OBJECT_UNLOCK (playbin);
       
  1768       break;
       
  1769     case PROP_BUFFER_DURATION:
       
  1770       GST_OBJECT_LOCK (playbin);
       
  1771       g_value_set_int64 (value, playbin->buffer_duration);
       
  1772       GST_OBJECT_UNLOCK (playbin);
  1292       GST_OBJECT_UNLOCK (playbin);
  1773       break;
  1293       break;
  1774     default:
  1294     default:
  1775       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  1295       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
  1776       break;
  1296       break;
  1778 }
  1298 }
  1779 
  1299 
  1780 /* mime types we are not handling on purpose right now, don't post a
  1300 /* mime types we are not handling on purpose right now, don't post a
  1781  * missing-plugin message for these */
  1301  * missing-plugin message for these */
  1782 static const gchar *blacklisted_mimes[] = {
  1302 static const gchar *blacklisted_mimes[] = {
  1783   "video/x-dvd-subpicture", "subpicture/x-pgs", NULL
  1303   "video/x-dvd-subpicture", NULL
  1784 };
  1304 };
  1785 
  1305 
  1786 static void
  1306 static void
  1787 gst_play_bin_handle_message (GstBin * bin, GstMessage * msg)
  1307 gst_play_bin_handle_message (GstBin * bin, GstMessage * msg)
  1788 {
  1308 {
  1802     g_free (detail);
  1322     g_free (detail);
  1803   }
  1323   }
  1804   GST_BIN_CLASS (parent_class)->handle_message (bin, msg);
  1324   GST_BIN_CLASS (parent_class)->handle_message (bin, msg);
  1805 }
  1325 }
  1806 
  1326 
  1807 static void
       
  1808 selector_active_pad_changed (GObject * selector, GParamSpec * pspec,
       
  1809     GstPlayBin * playbin)
       
  1810 {
       
  1811   gchar *property;
       
  1812   GstSourceGroup *group;
       
  1813   GstSourceSelect *select = NULL;
       
  1814   int i;
       
  1815 
       
  1816   GST_PLAY_BIN_LOCK (playbin);
       
  1817   group = get_group (playbin);
       
  1818 
       
  1819   for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
       
  1820     if (selector == G_OBJECT (group->selector[i].selector)) {
       
  1821       select = &group->selector[i];
       
  1822     }
       
  1823   }
       
  1824 
       
  1825   /* We got a pad-change after our group got switched out; no need to notify */
       
  1826   if (!select) {
       
  1827     GST_PLAY_BIN_UNLOCK (playbin);
       
  1828     return;
       
  1829   }
       
  1830 
       
  1831   switch (select->type) {
       
  1832     case GST_PLAY_SINK_TYPE_VIDEO:
       
  1833     case GST_PLAY_SINK_TYPE_VIDEO_RAW:
       
  1834       property = "current-video";
       
  1835       playbin->current_video = get_current_stream_number (playbin,
       
  1836           group->video_channels);
       
  1837       break;
       
  1838     case GST_PLAY_SINK_TYPE_AUDIO:
       
  1839     case GST_PLAY_SINK_TYPE_AUDIO_RAW:
       
  1840       property = "current-audio";
       
  1841       playbin->current_audio = get_current_stream_number (playbin,
       
  1842           group->audio_channels);
       
  1843       break;
       
  1844     case GST_PLAY_SINK_TYPE_TEXT:
       
  1845       property = "current-text";
       
  1846       playbin->current_text = get_current_stream_number (playbin,
       
  1847           group->text_channels);
       
  1848       break;
       
  1849     default:
       
  1850       property = NULL;
       
  1851   }
       
  1852   GST_PLAY_BIN_UNLOCK (playbin);
       
  1853 
       
  1854   if (property)
       
  1855     g_object_notify (G_OBJECT (playbin), property);
       
  1856 }
       
  1857 
       
  1858 static void
       
  1859 selector_blocked (GstPad * pad, gboolean blocked, gpointer user_data)
       
  1860 {
       
  1861   /* no nothing */
       
  1862   GST_DEBUG_OBJECT (pad, "blocked callback, blocked: %d", blocked);
       
  1863 }
       
  1864 
       
  1865 /* helper function to lookup stuff in lists */
       
  1866 static gboolean
       
  1867 array_has_value (const gchar * values[], const gchar * value)
       
  1868 {
       
  1869   gint i;
       
  1870 
       
  1871   for (i = 0; values[i]; i++) {
       
  1872     if (g_str_has_prefix (value, values[i]))
       
  1873       return TRUE;
       
  1874   }
       
  1875   return FALSE;
       
  1876 }
       
  1877 
       
  1878 typedef struct
       
  1879 {
       
  1880   GstPlayBin *playbin;
       
  1881   gint stream_id;
       
  1882   GstPlaySinkType type;
       
  1883 } NotifyTagsData;
       
  1884 
       
  1885 static void
       
  1886 notify_tags_cb (GObject * object, GParamSpec * pspec, gpointer user_data)
       
  1887 {
       
  1888   NotifyTagsData *ntdata = (NotifyTagsData *) user_data;
       
  1889   gint signal;
       
  1890 
       
  1891   GST_DEBUG_OBJECT (ntdata->playbin, "Tags on pad %" GST_PTR_FORMAT
       
  1892       " with stream id %d and type %d have changed",
       
  1893       object, ntdata->stream_id, ntdata->type);
       
  1894 
       
  1895   switch (ntdata->type) {
       
  1896     case GST_PLAY_SINK_TYPE_VIDEO:
       
  1897     case GST_PLAY_SINK_TYPE_VIDEO_RAW:
       
  1898       signal = SIGNAL_VIDEO_TAGS_CHANGED;
       
  1899       break;
       
  1900     case GST_PLAY_SINK_TYPE_AUDIO:
       
  1901     case GST_PLAY_SINK_TYPE_AUDIO_RAW:
       
  1902       signal = SIGNAL_AUDIO_TAGS_CHANGED;
       
  1903       break;
       
  1904     case GST_PLAY_SINK_TYPE_TEXT:
       
  1905       signal = SIGNAL_TEXT_TAGS_CHANGED;
       
  1906       break;
       
  1907     default:
       
  1908       signal = -1;
       
  1909       break;
       
  1910   }
       
  1911 
       
  1912   if (signal >= 0)
       
  1913     g_signal_emit (G_OBJECT (ntdata->playbin), gst_play_bin_signals[signal], 0,
       
  1914         ntdata->stream_id);
       
  1915 }
       
  1916 
       
  1917 /* this function is called when a new pad is added to decodebin. We check the
  1327 /* this function is called when a new pad is added to decodebin. We check the
  1918  * type of the pad and add it to the selector element of the group. 
  1328  * type of the pad and add it to the selecter element of the group. 
  1919  */
  1329  */
  1920 static void
  1330 static void
  1921 pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
  1331 pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
  1922 {
  1332 {
  1923   GstPlayBin *playbin;
  1333   GstPlayBin *playbin;
  1926   const gchar *name;
  1336   const gchar *name;
  1927   GstPad *sinkpad;
  1337   GstPad *sinkpad;
  1928   GstPadLinkReturn res;
  1338   GstPadLinkReturn res;
  1929   GstSourceSelect *select = NULL;
  1339   GstSourceSelect *select = NULL;
  1930   gint i;
  1340   gint i;
  1931   gboolean changed = FALSE;
       
  1932 
  1341 
  1933   playbin = group->playbin;
  1342   playbin = group->playbin;
  1934 
  1343 
  1935   caps = gst_pad_get_caps (pad);
  1344   caps = gst_pad_get_caps (pad);
  1936   s = gst_caps_get_structure (caps, 0);
  1345   s = gst_caps_get_structure (caps, 0);
  1940       "pad %s:%s with caps %" GST_PTR_FORMAT " added in group %p",
  1349       "pad %s:%s with caps %" GST_PTR_FORMAT " added in group %p",
  1941       GST_DEBUG_PAD_NAME (pad), caps, group);
  1350       GST_DEBUG_PAD_NAME (pad), caps, group);
  1942 
  1351 
  1943   /* major type of the pad, this determines the selector to use */
  1352   /* major type of the pad, this determines the selector to use */
  1944   for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
  1353   for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
  1945     if (array_has_value (group->selector[i].media_list, name)) {
  1354     if (g_str_has_prefix (name, group->selector[i].media)) {
  1946       select = &group->selector[i];
  1355       select = &group->selector[i];
  1947       break;
  1356       break;
  1948     }
  1357     }
  1949   }
  1358   }
  1950   /* no selector found for the media type, don't bother linking it to a
  1359   /* no selector found for the media type, don't bother linking it to a
  1951    * selector. This will leave the pad unlinked and thus ignored. */
  1360    * selector. This will leave the pad unlinked and thus ignored. */
  1952   if (select == NULL)
  1361   if (select == NULL)
  1953     goto unknown_type;
  1362     goto unknown_type;
  1954 
  1363 
  1955   GST_SOURCE_GROUP_LOCK (group);
  1364   if (select->selector == NULL) {
  1956   if (select->selector == NULL && playbin->have_selector) {
       
  1957     /* no selector, create one */
  1365     /* no selector, create one */
  1958     GST_DEBUG_OBJECT (playbin, "creating new selector");
  1366     GST_DEBUG_OBJECT (playbin, "creating new selector");
  1959     select->selector = g_object_new (GST_TYPE_INPUT_SELECTOR, NULL);
  1367     select->selector = g_object_new (GST_TYPE_STREAM_SELECTOR, NULL);
  1960     /* the above can't fail, but we keep the error handling around for when
  1368     if (select->selector == NULL)
  1961      * the selector plugin has moved to -base or -good and we stop using an
  1369       goto no_selector;
  1962      * internal copy of input-selector */
  1370 
  1963     if (select->selector == NULL) {
  1371     GST_DEBUG_OBJECT (playbin, "adding new selector %p", select->selector);
  1964       /* post the missing selector message only once */
  1372     gst_bin_add (GST_BIN_CAST (playbin), select->selector);
  1965       playbin->have_selector = FALSE;
  1373     gst_element_set_state (select->selector, GST_STATE_PAUSED);
  1966       gst_element_post_message (GST_ELEMENT_CAST (playbin),
  1374 
  1967           gst_missing_element_message_new (GST_ELEMENT_CAST (playbin),
  1375     /* save source pad */
  1968               "input-selector"));
  1376     select->srcpad = gst_element_get_pad (select->selector, "src");
  1969       GST_ELEMENT_WARNING (playbin, CORE, MISSING_PLUGIN,
       
  1970           (_("Missing element '%s' - check your GStreamer installation."),
       
  1971               "input-selector"), (NULL));
       
  1972     } else {
       
  1973       g_signal_connect (select->selector, "notify::active-pad",
       
  1974           G_CALLBACK (selector_active_pad_changed), playbin);
       
  1975 
       
  1976       GST_DEBUG_OBJECT (playbin, "adding new selector %p", select->selector);
       
  1977       gst_bin_add (GST_BIN_CAST (playbin), select->selector);
       
  1978       gst_element_set_state (select->selector, GST_STATE_PAUSED);
       
  1979     }
       
  1980   }
       
  1981 
       
  1982   if (select->srcpad == NULL) {
       
  1983     if (select->selector) {
       
  1984       /* save source pad of the selector */
       
  1985       select->srcpad = gst_element_get_static_pad (select->selector, "src");
       
  1986     } else {
       
  1987       /* no selector, use the pad as the source pad then */
       
  1988       select->srcpad = gst_object_ref (pad);
       
  1989     }
       
  1990     /* block the selector srcpad. It's possible that multiple decodebins start
       
  1991      * pushing data into the selectors before we have a chance to collect all
       
  1992      * streams and connect the sinks, resulting in not-linked errors. After we
       
  1993      * configured the sinks we will unblock them all. */
       
  1994     gst_pad_set_blocked_async (select->srcpad, TRUE, selector_blocked, NULL);
       
  1995   }
  1377   }
  1996 
  1378 
  1997   /* get sinkpad for the new stream */
  1379   /* get sinkpad for the new stream */
  1998   if (select->selector) {
  1380   if ((sinkpad = gst_element_get_request_pad (select->selector, "sink%d"))) {
  1999     if ((sinkpad = gst_element_get_request_pad (select->selector, "sink%d"))) {
  1381     GST_DEBUG_OBJECT (playbin, "got pad %s:%s from selector",
  2000       gulong notify_tags_handler = 0;
  1382         GST_DEBUG_PAD_NAME (sinkpad));
  2001       NotifyTagsData *ntdata;
  1383 
  2002 
  1384     /* store the selector for the pad */
  2003       GST_DEBUG_OBJECT (playbin, "got pad %s:%s from selector",
  1385     g_object_set_data (G_OBJECT (sinkpad), "playbin2.select", select);
  2004           GST_DEBUG_PAD_NAME (sinkpad));
  1386 
  2005 
  1387     /* store the pad in the array */
  2006       /* store the selector for the pad */
  1388     GST_DEBUG_OBJECT (playbin, "pad %p added to array", sinkpad);
  2007       g_object_set_data (G_OBJECT (sinkpad), "playbin2.select", select);
  1389     g_ptr_array_add (select->channels, sinkpad);
  2008 
  1390 
  2009       /* connect to the notify::tags signal for our
  1391     res = gst_pad_link (pad, sinkpad);
  2010        * own *-tags-changed signals
  1392     if (GST_PAD_LINK_FAILED (res))
  2011        */
  1393       goto link_failed;
  2012       ntdata = g_new0 (NotifyTagsData, 1);
  1394 
  2013       ntdata->playbin = playbin;
  1395     /* store selector pad so we can release it */
  2014       ntdata->stream_id = select->channels->len;
  1396     g_object_set_data (G_OBJECT (pad), "playbin2.sinkpad", sinkpad);
  2015       ntdata->type = select->type;
  1397   }
  2016 
  1398   GST_DEBUG_OBJECT (playbin, "linked pad %s:%s to selector %p",
  2017       notify_tags_handler =
  1399       GST_DEBUG_PAD_NAME (pad), select->selector);
  2018           g_signal_connect_data (G_OBJECT (sinkpad), "notify::tags",
  1400 
  2019           G_CALLBACK (notify_tags_cb), ntdata, (GClosureNotify) g_free,
       
  2020           (GConnectFlags) 0);
       
  2021       g_object_set_data (G_OBJECT (sinkpad), "playbin2.notify_tags_handler",
       
  2022           (gpointer) notify_tags_handler);
       
  2023 
       
  2024       /* store the pad in the array */
       
  2025       GST_DEBUG_OBJECT (playbin, "pad %p added to array", sinkpad);
       
  2026       g_ptr_array_add (select->channels, sinkpad);
       
  2027 
       
  2028       res = gst_pad_link (pad, sinkpad);
       
  2029       if (GST_PAD_LINK_FAILED (res))
       
  2030         goto link_failed;
       
  2031 
       
  2032       /* store selector pad so we can release it */
       
  2033       g_object_set_data (G_OBJECT (pad), "playbin2.sinkpad", sinkpad);
       
  2034 
       
  2035       changed = TRUE;
       
  2036       GST_DEBUG_OBJECT (playbin, "linked pad %s:%s to selector %p",
       
  2037           GST_DEBUG_PAD_NAME (pad), select->selector);
       
  2038     }
       
  2039   } else {
       
  2040     /* no selector, don't configure anything, we'll link the new pad directly to
       
  2041      * the sink. */
       
  2042     changed = FALSE;
       
  2043     sinkpad = NULL;
       
  2044   }
       
  2045   GST_SOURCE_GROUP_UNLOCK (group);
       
  2046 
       
  2047   if (changed) {
       
  2048     int signal;
       
  2049     switch (select->type) {
       
  2050       case GST_PLAY_SINK_TYPE_VIDEO:
       
  2051       case GST_PLAY_SINK_TYPE_VIDEO_RAW:
       
  2052         /* we want to return NOT_LINKED for unselected pads but only for audio
       
  2053          * and video pads because text pads might come from an external file. */
       
  2054         g_object_set (sinkpad, "always-ok", FALSE, NULL);
       
  2055         signal = SIGNAL_VIDEO_CHANGED;
       
  2056         break;
       
  2057       case GST_PLAY_SINK_TYPE_AUDIO:
       
  2058       case GST_PLAY_SINK_TYPE_AUDIO_RAW:
       
  2059         g_object_set (sinkpad, "always-ok", FALSE, NULL);
       
  2060         signal = SIGNAL_AUDIO_CHANGED;
       
  2061         break;
       
  2062       case GST_PLAY_SINK_TYPE_TEXT:
       
  2063         signal = SIGNAL_TEXT_CHANGED;
       
  2064         break;
       
  2065       case GST_PLAY_SINK_TYPE_SUBPIC:
       
  2066       default:
       
  2067         signal = -1;
       
  2068     }
       
  2069 
       
  2070     if (signal >= 0)
       
  2071       g_signal_emit (G_OBJECT (playbin), gst_play_bin_signals[signal], 0, NULL);
       
  2072   }
       
  2073 
       
  2074 done:
       
  2075   gst_caps_unref (caps);
       
  2076   return;
  1401   return;
  2077 
  1402 
  2078   /* ERRORS */
  1403   /* ERRORS */
  2079 unknown_type:
  1404 unknown_type:
  2080   {
  1405   {
  2081     GST_ERROR_OBJECT (playbin, "unknown type %s for pad %s:%s",
  1406     GST_ERROR_OBJECT (playbin, "unknown type %s for pad %s:%s",
  2082         name, GST_DEBUG_PAD_NAME (pad));
  1407         name, GST_DEBUG_PAD_NAME (pad));
  2083     goto done;
  1408     return;
       
  1409   }
       
  1410 no_selector:
       
  1411   {
       
  1412     GST_ERROR_OBJECT (playbin, "could not create selector for pad %s:%s",
       
  1413         GST_DEBUG_PAD_NAME (pad));
       
  1414     return;
  2084   }
  1415   }
  2085 link_failed:
  1416 link_failed:
  2086   {
  1417   {
  2087     GST_ERROR_OBJECT (playbin,
  1418     GST_ERROR_OBJECT (playbin,
  2088         "failed to link pad %s:%s to selector, reason %d",
  1419         "failed to link pad %s:%s to selector, reason %d",
  2089         GST_DEBUG_PAD_NAME (pad), res);
  1420         GST_DEBUG_PAD_NAME (pad), res);
  2090     GST_SOURCE_GROUP_UNLOCK (group);
  1421     return;
  2091     goto done;
  1422   }
  2092   }
  1423 }
  2093 }
  1424 
  2094 
  1425 /* called when a pad is removed form the uridecodebin. We unlink the pad from
  2095 /* called when a pad is removed from the uridecodebin. We unlink the pad from
       
  2096  * the selector. This will make the selector select a new pad. */
  1426  * the selector. This will make the selector select a new pad. */
  2097 static void
  1427 static void
  2098 pad_removed_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
  1428 pad_removed_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
  2099 {
  1429 {
  2100   GstPlayBin *playbin;
  1430   GstPlayBin *playbin;
  2105   playbin = group->playbin;
  1435   playbin = group->playbin;
  2106 
  1436 
  2107   GST_DEBUG_OBJECT (playbin,
  1437   GST_DEBUG_OBJECT (playbin,
  2108       "pad %s:%s removed from group %p", GST_DEBUG_PAD_NAME (pad), group);
  1438       "pad %s:%s removed from group %p", GST_DEBUG_PAD_NAME (pad), group);
  2109 
  1439 
  2110   GST_SOURCE_GROUP_LOCK (group);
       
  2111   /* get the selector sinkpad */
  1440   /* get the selector sinkpad */
  2112   if (!(peer = g_object_get_data (G_OBJECT (pad), "playbin2.sinkpad")))
  1441   if (!(peer = g_object_get_data (G_OBJECT (pad), "playbin2.sinkpad")))
  2113     goto not_linked;
  1442     goto not_linked;
  2114 
  1443 
  2115   if ((select = g_object_get_data (G_OBJECT (peer), "playbin2.select"))) {
  1444   if ((select = g_object_get_data (G_OBJECT (peer), "playbin2.select"))) {
  2116     gulong notify_tags_handler;
       
  2117 
       
  2118     notify_tags_handler =
       
  2119         (gulong) g_object_get_data (G_OBJECT (peer),
       
  2120         "playbin2.notify_tags_handler");
       
  2121     if (notify_tags_handler != 0)
       
  2122       g_signal_handler_disconnect (G_OBJECT (peer), notify_tags_handler);
       
  2123     g_object_set_data (G_OBJECT (peer), "playbin2.notify_tags_handler", NULL);
       
  2124 
       
  2125     /* remove the pad from the array */
  1445     /* remove the pad from the array */
  2126     g_ptr_array_remove (select->channels, peer);
  1446     g_ptr_array_remove (select->channels, peer);
  2127     GST_DEBUG_OBJECT (playbin, "pad %p removed from array", peer);
  1447     GST_DEBUG_OBJECT (playbin, "pad %p removed from array", peer);
  2128   }
  1448   }
  2129 
  1449 
  2131   gst_pad_unlink (pad, peer);
  1451   gst_pad_unlink (pad, peer);
  2132 
  1452 
  2133   /* get selector, this can be NULL when the element is removing the pads
  1453   /* get selector, this can be NULL when the element is removing the pads
  2134    * because it's being disposed. */
  1454    * because it's being disposed. */
  2135   selector = GST_ELEMENT_CAST (gst_pad_get_parent (peer));
  1455   selector = GST_ELEMENT_CAST (gst_pad_get_parent (peer));
  2136   if (!selector) {
  1456   if (!selector)
  2137     gst_object_unref (peer);
       
  2138     goto no_selector;
  1457     goto no_selector;
  2139   }
       
  2140 
  1458 
  2141   /* release the pad to the selector, this will make the selector choose a new
  1459   /* release the pad to the selector, this will make the selector choose a new
  2142    * pad. */
  1460    * pad. */
  2143   gst_element_release_request_pad (selector, peer);
  1461   gst_element_release_request_pad (selector, peer);
  2144   gst_object_unref (peer);
       
  2145 
  1462 
  2146   gst_object_unref (selector);
  1463   gst_object_unref (selector);
  2147   GST_SOURCE_GROUP_UNLOCK (group);
       
  2148 
  1464 
  2149   return;
  1465   return;
  2150 
  1466 
  2151   /* ERRORS */
  1467   /* ERRORS */
  2152 not_linked:
  1468 not_linked:
  2153   {
  1469   {
  2154     GST_DEBUG_OBJECT (playbin, "pad not linked");
  1470     GST_DEBUG_OBJECT (playbin, "pad not linked");
  2155     GST_SOURCE_GROUP_UNLOCK (group);
       
  2156     return;
  1471     return;
  2157   }
  1472   }
  2158 no_selector:
  1473 no_selector:
  2159   {
  1474   {
  2160     GST_DEBUG_OBJECT (playbin, "selector not found");
  1475     GST_DEBUG_OBJECT (playbin, "selector not found");
  2161     GST_SOURCE_GROUP_UNLOCK (group);
       
  2162     return;
  1476     return;
  2163   }
  1477   }
  2164 }
  1478 }
  2165 
  1479 
  2166 /* we get called when all pads are available and we must connect the sinks to
  1480 /* we get called when all pads are available and we must connect the sinks to
  2176 no_more_pads_cb (GstElement * decodebin, GstSourceGroup * group)
  1490 no_more_pads_cb (GstElement * decodebin, GstSourceGroup * group)
  2177 {
  1491 {
  2178   GstPlayBin *playbin;
  1492   GstPlayBin *playbin;
  2179   GstPadLinkReturn res;
  1493   GstPadLinkReturn res;
  2180   gint i;
  1494   gint i;
  2181   gboolean configure;
       
  2182 
  1495 
  2183   playbin = group->playbin;
  1496   playbin = group->playbin;
  2184 
  1497 
  2185   GST_DEBUG_OBJECT (playbin, "no more pads in group %p", group);
  1498   GST_DEBUG_OBJECT (playbin, "no more pads in group %p", group);
  2186 
  1499 
  2187   GST_PLAY_BIN_SHUTDOWN_LOCK (playbin, shutdown);
       
  2188 
       
  2189   GST_SOURCE_GROUP_LOCK (group);
       
  2190   for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
  1500   for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
  2191     GstSourceSelect *select = &group->selector[i];
  1501     GstSourceSelect *select = &group->selector[i];
  2192 
  1502 
  2193     /* check if the specific media type was detected and thus has a selector
  1503     if (select->selector) {
  2194      * created for it. If there is the media type, get a sinkpad from the sink
       
  2195      * and link it. We only do this if we have not yet requested the sinkpad
       
  2196      * before. */
       
  2197     if (select->srcpad && select->sinkpad == NULL) {
       
  2198       GST_DEBUG_OBJECT (playbin, "requesting new sink pad %d", select->type);
       
  2199       select->sinkpad =
  1504       select->sinkpad =
  2200           gst_play_sink_request_pad (playbin->playsink, select->type);
  1505           gst_play_sink_request_pad (playbin->playsink, select->type);
  2201       res = gst_pad_link (select->srcpad, select->sinkpad);
  1506       res = gst_pad_link (select->srcpad, select->sinkpad);
  2202       GST_DEBUG_OBJECT (playbin, "linked type %s, result: %d",
  1507       GST_DEBUG_OBJECT (playbin, "linked type %s, result: %d", select->media,
  2203           select->media_list[0], res);
  1508           res);
  2204       if (res != GST_PAD_LINK_OK) {
       
  2205         GST_ELEMENT_ERROR (playbin, CORE, PAD,
       
  2206             ("Internal playbin error."),
       
  2207             ("Failed to link selector to sink. Error %d", res));
       
  2208       }
       
  2209     }
  1509     }
  2210   }
  1510   }
  2211   GST_DEBUG_OBJECT (playbin, "pending %d > %d", group->pending,
  1511   /* configure the modes now */
  2212       group->pending - 1);
  1512   gst_play_sink_reconfigure (playbin->playsink);
  2213 
  1513 }
  2214   if (group->pending > 0)
  1514 
  2215     group->pending--;
  1515 /* send an EOS event to all of the selectors */
  2216 
  1516 static void
  2217   if (group->pending == 0) {
  1517 perform_eos (GstPlayBin * playbin, GstSourceGroup * group)
  2218     /* we are the last group to complete, we will configure the output and then
  1518 {
  2219      * signal the other waiters. */
  1519   GstEvent *event;
  2220     GST_LOG_OBJECT (playbin, "last group complete");
  1520   gint i;
  2221     configure = TRUE;
  1521 
  2222   } else {
  1522   GST_DEBUG_OBJECT (playbin, "doing EOS in group %p", group);
  2223     GST_LOG_OBJECT (playbin, "have more pending groups");
  1523 
  2224     configure = FALSE;
  1524   event = gst_event_new_eos ();
  2225   }
  1525   for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
  2226   GST_SOURCE_GROUP_UNLOCK (group);
  1526     GstSourceSelect *select = &group->selector[i];
  2227 
  1527 
  2228   if (configure) {
  1528     if (select->selector) {
  2229     /* if we have custom sinks, configure them now */
  1529       GST_DEBUG_OBJECT (playbin, "send EOS in selector %s", select->media);
  2230     GST_SOURCE_GROUP_LOCK (group);
  1530       gst_event_ref (event);
  2231     if (group->audio_sink) {
  1531       gst_pad_push_event (select->srcpad, event);
  2232       GST_INFO_OBJECT (playbin, "setting custom audio sink %" GST_PTR_FORMAT,
       
  2233           group->audio_sink);
       
  2234       gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_AUDIO,
       
  2235           group->audio_sink);
       
  2236     } else {
       
  2237       GST_INFO_OBJECT (playbin, "setting default audio sink %" GST_PTR_FORMAT,
       
  2238           playbin->audio_sink);
       
  2239       gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_AUDIO,
       
  2240           playbin->audio_sink);
       
  2241     }
  1532     }
  2242     if (group->video_sink) {
  1533   }
  2243       GST_INFO_OBJECT (playbin, "setting custom video sink %" GST_PTR_FORMAT,
  1534   gst_event_unref (event);
  2244           group->video_sink);
       
  2245       gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_VIDEO,
       
  2246           group->video_sink);
       
  2247     } else {
       
  2248       GST_INFO_OBJECT (playbin, "setting default video sink %" GST_PTR_FORMAT,
       
  2249           playbin->video_sink);
       
  2250       gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_VIDEO,
       
  2251           playbin->video_sink);
       
  2252     }
       
  2253     gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_TEXT,
       
  2254         playbin->text_sink);
       
  2255     gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_SUBPIC,
       
  2256         playbin->subpic_sink);
       
  2257     GST_SOURCE_GROUP_UNLOCK (group);
       
  2258 
       
  2259     GST_LOG_OBJECT (playbin, "reconfigure sink");
       
  2260     /* we configure the modes if we were the last decodebin to complete. */
       
  2261     gst_play_sink_reconfigure (playbin->playsink);
       
  2262 
       
  2263     /* signal the other decodebins that they can continue now. */
       
  2264     GST_SOURCE_GROUP_LOCK (group);
       
  2265     /* unblock all selectors */
       
  2266     for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
       
  2267       GstSourceSelect *select = &group->selector[i];
       
  2268 
       
  2269       if (select->srcpad) {
       
  2270         GST_DEBUG_OBJECT (playbin, "unblocking %" GST_PTR_FORMAT,
       
  2271             select->srcpad);
       
  2272         gst_pad_set_blocked_async (select->srcpad, FALSE, selector_blocked,
       
  2273             NULL);
       
  2274       }
       
  2275     }
       
  2276     GST_SOURCE_GROUP_UNLOCK (group);
       
  2277   }
       
  2278 
       
  2279   GST_PLAY_BIN_SHUTDOWN_UNLOCK (playbin);
       
  2280 
       
  2281   return;
       
  2282 
       
  2283 shutdown:
       
  2284   {
       
  2285     GST_DEBUG ("ignoring, we are shutting down");
       
  2286     /* Request a flushing pad from playsink that we then link to the selector.
       
  2287      * Then we unblock the selectors so that they stop with a WRONG_STATE
       
  2288      * instead of a NOT_LINKED error.
       
  2289      */
       
  2290     GST_SOURCE_GROUP_LOCK (group);
       
  2291     for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
       
  2292       GstSourceSelect *select = &group->selector[i];
       
  2293 
       
  2294       if (select->srcpad) {
       
  2295         if (select->sinkpad == NULL) {
       
  2296           GST_DEBUG_OBJECT (playbin, "requesting new flushing sink pad");
       
  2297           select->sinkpad =
       
  2298               gst_play_sink_request_pad (playbin->playsink,
       
  2299               GST_PLAY_SINK_TYPE_FLUSHING);
       
  2300           res = gst_pad_link (select->srcpad, select->sinkpad);
       
  2301           GST_DEBUG_OBJECT (playbin, "linked flushing, result: %d", res);
       
  2302         }
       
  2303         GST_DEBUG_OBJECT (playbin, "unblocking %" GST_PTR_FORMAT,
       
  2304             select->srcpad);
       
  2305         gst_pad_set_blocked_async (select->srcpad, FALSE, selector_blocked,
       
  2306             NULL);
       
  2307       }
       
  2308     }
       
  2309     GST_SOURCE_GROUP_UNLOCK (group);
       
  2310     return;
       
  2311   }
       
  2312 }
  1535 }
  2313 
  1536 
  2314 static void
  1537 static void
  2315 drained_cb (GstElement * decodebin, GstSourceGroup * group)
  1538 drained_cb (GstElement * decodebin, GstSourceGroup * group)
  2316 {
  1539 {
  2317   GstPlayBin *playbin;
  1540   GstPlayBin *playbin;
  2318 
  1541 
  2319   playbin = group->playbin;
  1542   playbin = group->playbin;
  2320 
  1543 
  2321   GST_DEBUG_OBJECT (playbin, "about to finish in group %p", group);
  1544   GST_DEBUG_OBJECT (playbin, "about to finish in group %p", group);
       
  1545 
       
  1546   /* mark use as sending out the about-to-finish signal. When the app sets a URI
       
  1547    * when this signal is emited, we're marking it as next-uri */
       
  1548   playbin->about_to_finish = TRUE;
  2322 
  1549 
  2323   /* after this call, we should have a next group to activate or we EOS */
  1550   /* after this call, we should have a next group to activate or we EOS */
  2324   g_signal_emit (G_OBJECT (playbin),
  1551   g_signal_emit (G_OBJECT (playbin),
  2325       gst_play_bin_signals[SIGNAL_ABOUT_TO_FINISH], 0, NULL);
  1552       gst_play_bin_signals[SIGNAL_ABOUT_TO_FINISH], 0, NULL);
  2326 
  1553 
  2327   /* now activate the next group. If the app did not set a uri, this will
  1554   playbin->about_to_finish = FALSE;
       
  1555 
       
  1556   /* now activate the next group. If the app did not set a next-uri, this will
  2328    * fail and we can do EOS */
  1557    * fail and we can do EOS */
  2329   setup_next_source (playbin, GST_STATE_PAUSED);
  1558   if (!setup_next_source (playbin)) {
       
  1559     perform_eos (playbin, group);
       
  1560   }
  2330 }
  1561 }
  2331 
  1562 
  2332 /* Called when we must provide a list of factories to plug to @pad with @caps.
  1563 /* Called when we must provide a list of factories to plug to @pad with @caps.
  2333  * We first check if we have a sink that can handle the format and if we do, we
  1564  * We first check if we have a sink that can handle the format and if we do, we
  2334  * return NULL, to expose the pad. If we have no sink (or the sink does not
  1565  * return NULL, to expose the pad. If we have no sink (or the sink does not
  2354   return result;
  1585   return result;
  2355 }
  1586 }
  2356 
  1587 
  2357 /* We are asked to select an element. See if the next element to check
  1588 /* We are asked to select an element. See if the next element to check
  2358  * is a sink. If this is the case, we see if the sink works by setting it to
  1589  * is a sink. If this is the case, we see if the sink works by setting it to
  2359  * READY. If the sink works, we return SELECT_EXPOSE to make decodebin
  1590  * READY. If the sink works, we return -2 to make decodebin expose the raw pad
  2360  * expose the raw pad so that we can setup the mixers. */
  1591  * so that we can setup the mixers. */
  2361 static GstAutoplugSelectResult
  1592 static GstAutoplugSelectResult
  2362 autoplug_select_cb (GstElement * decodebin, GstPad * pad,
  1593 autoplug_select_cb (GstElement * decodebin, GstPad * pad,
  2363     GstCaps * caps, GstElementFactory * factory, GstSourceGroup * group)
  1594     GstCaps * caps, GstElementFactory * factory, GstSourceGroup * group)
  2364 {
  1595 {
  2365   GstPlayBin *playbin;
  1596   GstPlayBin *playbin;
  2366   GstElement *element;
  1597   GstElement *element;
  2367   const gchar *klass;
  1598   const gchar *klass;
  2368   GstPlaySinkType type;
       
  2369   GstElement **sinkp;
       
  2370 
  1599 
  2371   playbin = group->playbin;
  1600   playbin = group->playbin;
  2372 
  1601 
  2373   GST_DEBUG_OBJECT (playbin, "select group %p for %s:%s, %" GST_PTR_FORMAT,
  1602   GST_DEBUG_OBJECT (playbin, "select group %p for %s:%s, %" GST_PTR_FORMAT,
  2374       group, GST_DEBUG_PAD_NAME (pad), caps);
  1603       group, GST_DEBUG_PAD_NAME (pad), caps);
  2380   if (!gst_factory_list_is_type (factory, GST_FACTORY_LIST_SINK))
  1609   if (!gst_factory_list_is_type (factory, GST_FACTORY_LIST_SINK))
  2381     return GST_AUTOPLUG_SELECT_TRY;
  1610     return GST_AUTOPLUG_SELECT_TRY;
  2382 
  1611 
  2383   /* it's a sink, see if an instance of it actually works */
  1612   /* it's a sink, see if an instance of it actually works */
  2384   GST_DEBUG_OBJECT (playbin, "we found a sink");
  1613   GST_DEBUG_OBJECT (playbin, "we found a sink");
  2385 
       
  2386   klass = gst_element_factory_get_klass (factory);
       
  2387 
       
  2388   /* figure out the klass */
       
  2389   if (strstr (klass, "Audio")) {
       
  2390     GST_DEBUG_OBJECT (playbin, "we found an audio sink");
       
  2391     type = GST_PLAY_SINK_TYPE_AUDIO;
       
  2392     sinkp = &group->audio_sink;
       
  2393   } else if (strstr (klass, "Video")) {
       
  2394     GST_DEBUG_OBJECT (playbin, "we found a video sink");
       
  2395     type = GST_PLAY_SINK_TYPE_VIDEO;
       
  2396     sinkp = &group->video_sink;
       
  2397   } else {
       
  2398     /* unknown klass, skip this element */
       
  2399     GST_WARNING_OBJECT (playbin, "unknown sink klass %s found", klass);
       
  2400     return GST_AUTOPLUG_SELECT_SKIP;
       
  2401   }
       
  2402 
       
  2403   /* if we are asked to do visualisations and it's an audio sink, skip the
       
  2404    * element. We can only do visualisations with raw sinks */
       
  2405   if (gst_play_sink_get_flags (playbin->playsink) & GST_PLAY_FLAG_VIS) {
       
  2406     if (type == GST_PLAY_SINK_TYPE_AUDIO) {
       
  2407       GST_DEBUG_OBJECT (playbin, "skip audio sink because of vis");
       
  2408       return GST_AUTOPLUG_SELECT_SKIP;
       
  2409     }
       
  2410   }
       
  2411 
       
  2412   /* now see if we already have a sink element */
       
  2413   GST_SOURCE_GROUP_LOCK (group);
       
  2414   if (*sinkp) {
       
  2415     GST_DEBUG_OBJECT (playbin, "we already have a pending sink, expose pad");
       
  2416     /* for now, just assume that we can link the pad to this same sink. FIXME,
       
  2417      * check that we can link this new pad to this sink as well. */
       
  2418     GST_SOURCE_GROUP_UNLOCK (group);
       
  2419     return GST_AUTOPLUG_SELECT_EXPOSE;
       
  2420   }
       
  2421   GST_DEBUG_OBJECT (playbin, "we have no pending sink, try to create one");
       
  2422   GST_SOURCE_GROUP_UNLOCK (group);
       
  2423 
  1614 
  2424   if ((element = gst_element_factory_create (factory, NULL)) == NULL) {
  1615   if ((element = gst_element_factory_create (factory, NULL)) == NULL) {
  2425     GST_WARNING_OBJECT (playbin, "Could not create an element from %s",
  1616     GST_WARNING_OBJECT (playbin, "Could not create an element from %s",
  2426         gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
  1617         gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
  2427     return GST_AUTOPLUG_SELECT_SKIP;
  1618     return GST_AUTOPLUG_SELECT_SKIP;
  2436         GST_ELEMENT_NAME (element));
  1627         GST_ELEMENT_NAME (element));
  2437     gst_object_unref (element);
  1628     gst_object_unref (element);
  2438     return GST_AUTOPLUG_SELECT_SKIP;
  1629     return GST_AUTOPLUG_SELECT_SKIP;
  2439   }
  1630   }
  2440 
  1631 
  2441   /* remember the sink in the group now, the element is floating, we take
  1632   /* at this point, we have the sink working, configure it in playsink */
  2442    * ownership now */
  1633   klass = gst_element_factory_get_klass (factory);
  2443   GST_SOURCE_GROUP_LOCK (group);
  1634 
  2444   if (*sinkp == NULL) {
  1635   /* get klass to figure out if it's audio or video */
  2445     /* store the sink in the group, we will configure it later when we
  1636   if (strstr (klass, "Audio")) {
  2446      * reconfigure the sink */
  1637     GST_DEBUG_OBJECT (playbin, "configure audio sink");
  2447     GST_DEBUG_OBJECT (playbin, "remember sink");
  1638     gst_play_sink_set_audio_sink (playbin->playsink, element);
  2448     gst_object_ref (element);
  1639   } else if (strstr (klass, "Video")) {
  2449     gst_object_sink (element);
  1640     GST_DEBUG_OBJECT (playbin, "configure video sink");
  2450     *sinkp = element;
  1641     gst_play_sink_set_video_sink (playbin->playsink, element);
  2451   } else {
  1642   } else {
  2452     /* some other thread configured a sink while we were testing the sink, set
  1643     GST_WARNING_OBJECT (playbin, "unknown sink klass %s found", klass);
  2453      * the sink back to NULL and assume we can use the other sink */
  1644   }
  2454     GST_DEBUG_OBJECT (playbin, "another sink was found, expose pad");
       
  2455     gst_element_set_state (element, GST_STATE_NULL);
       
  2456     gst_object_unref (element);
       
  2457   }
       
  2458   GST_SOURCE_GROUP_UNLOCK (group);
       
  2459 
  1645 
  2460   /* tell decodebin to expose the pad because we are going to use this
  1646   /* tell decodebin to expose the pad because we are going to use this
  2461    * sink */
  1647    * sink */
  2462   GST_DEBUG_OBJECT (playbin, "we found a working sink, expose pad");
  1648   GST_DEBUG_OBJECT (playbin, "we found a working sink, expose pad");
  2463 
  1649 
  2464   return GST_AUTOPLUG_SELECT_EXPOSE;
  1650   return GST_AUTOPLUG_SELECT_EXPOSE;
  2465 }
  1651 }
  2466 
  1652 
  2467 static void
       
  2468 notify_source_cb (GstElement * uridecodebin, GParamSpec * pspec,
       
  2469     GstSourceGroup * group)
       
  2470 {
       
  2471   GstPlayBin *playbin;
       
  2472   GstElement *source;
       
  2473 
       
  2474   playbin = group->playbin;
       
  2475 
       
  2476   g_object_get (group->uridecodebin, "source", &source, NULL);
       
  2477 
       
  2478   GST_OBJECT_LOCK (playbin);
       
  2479   if (playbin->source)
       
  2480     gst_object_unref (playbin->source);
       
  2481   playbin->source = source;
       
  2482   GST_OBJECT_UNLOCK (playbin);
       
  2483 
       
  2484   g_object_notify (G_OBJECT (playbin), "source");
       
  2485 }
       
  2486 
       
  2487 /* must be called with the group lock */
       
  2488 static gboolean
  1653 static gboolean
  2489 group_set_locked_state_unlocked (GstPlayBin * playbin, GstSourceGroup * group,
  1654 activate_group (GstPlayBin * playbin, GstSourceGroup * group)
  2490     gboolean locked)
       
  2491 {
       
  2492   GST_DEBUG_OBJECT (playbin, "locked_state %d on group %p", locked, group);
       
  2493 
       
  2494   if (group->uridecodebin)
       
  2495     gst_element_set_locked_state (group->uridecodebin, locked);
       
  2496   if (group->suburidecodebin)
       
  2497     gst_element_set_locked_state (group->suburidecodebin, locked);
       
  2498 
       
  2499   return TRUE;
       
  2500 }
       
  2501 
       
  2502 #define REMOVE_SIGNAL(obj,id)            \
       
  2503 if (id) {                                \
       
  2504   g_signal_handler_disconnect (obj, id); \
       
  2505   id = 0;                                \
       
  2506 }
       
  2507 
       
  2508 /* must be called with PLAY_BIN_LOCK */
       
  2509 static gboolean
       
  2510 activate_group (GstPlayBin * playbin, GstSourceGroup * group, GstState target)
       
  2511 {
  1655 {
  2512   GstElement *uridecodebin;
  1656   GstElement *uridecodebin;
  2513   GstElement *suburidecodebin = NULL;
       
  2514 
  1657 
  2515   g_return_val_if_fail (group->valid, FALSE);
  1658   g_return_val_if_fail (group->valid, FALSE);
  2516   g_return_val_if_fail (!group->active, FALSE);
  1659   g_return_val_if_fail (!group->active, FALSE);
  2517 
  1660 
  2518   GST_DEBUG_OBJECT (playbin, "activating group %p", group);
       
  2519 
       
  2520   GST_SOURCE_GROUP_LOCK (group);
       
  2521   if (group->uridecodebin) {
  1661   if (group->uridecodebin) {
  2522     GST_DEBUG_OBJECT (playbin, "reusing existing uridecodebin");
       
  2523     REMOVE_SIGNAL (group->uridecodebin, group->pad_added_id);
       
  2524     REMOVE_SIGNAL (group->uridecodebin, group->pad_removed_id);
       
  2525     REMOVE_SIGNAL (group->uridecodebin, group->no_more_pads_id);
       
  2526     REMOVE_SIGNAL (group->uridecodebin, group->notify_source_id);
       
  2527     REMOVE_SIGNAL (group->uridecodebin, group->drained_id);
       
  2528     REMOVE_SIGNAL (group->uridecodebin, group->autoplug_factories_id);
       
  2529     REMOVE_SIGNAL (group->uridecodebin, group->autoplug_select_id);
       
  2530     gst_element_set_state (group->uridecodebin, GST_STATE_NULL);
  1662     gst_element_set_state (group->uridecodebin, GST_STATE_NULL);
  2531     uridecodebin = group->uridecodebin;
  1663     gst_bin_remove (GST_BIN_CAST (playbin), group->uridecodebin);
  2532   } else {
  1664     group->uridecodebin = NULL;
  2533     GST_DEBUG_OBJECT (playbin, "making new uridecodebin");
  1665   }
  2534     uridecodebin = gst_element_factory_make ("uridecodebin", NULL);
  1666 
  2535     if (!uridecodebin)
  1667   uridecodebin = gst_element_factory_make ("uridecodebin", NULL);
  2536       goto no_decodebin;
  1668   if (!uridecodebin)
  2537     gst_bin_add (GST_BIN_CAST (playbin), uridecodebin);
  1669     goto no_decodebin;
  2538     group->uridecodebin = uridecodebin;
       
  2539   }
       
  2540 
  1670 
  2541   /* configure connection speed */
  1671   /* configure connection speed */
  2542   g_object_set (uridecodebin, "connection-speed",
  1672   g_object_set (uridecodebin, "connection-speed", playbin->connection_speed,
  2543       playbin->connection_speed / 1000, NULL);
  1673       NULL);
  2544   if (gst_play_sink_get_flags (playbin->playsink) & GST_PLAY_FLAG_DOWNLOAD)
       
  2545     g_object_set (uridecodebin, "download", TRUE, NULL);
       
  2546   else
       
  2547     g_object_set (uridecodebin, "download", FALSE, NULL);
       
  2548   /* configure subtitle encoding */
       
  2549   g_object_set (uridecodebin, "subtitle-encoding", playbin->encoding, NULL);
       
  2550   /* configure uri */
  1674   /* configure uri */
  2551   g_object_set (uridecodebin, "uri", group->uri, NULL);
  1675   g_object_set (uridecodebin, "uri", group->uri, NULL);
  2552   g_object_set (uridecodebin, "buffer-duration", playbin->buffer_duration,
       
  2553       NULL);
       
  2554   g_object_set (uridecodebin, "buffer-size", playbin->buffer_size, NULL);
       
  2555 
  1676 
  2556   /* connect pads and other things */
  1677   /* connect pads and other things */
  2557   group->pad_added_id = g_signal_connect (uridecodebin, "pad-added",
  1678   g_signal_connect (uridecodebin, "pad-added", G_CALLBACK (pad_added_cb),
  2558       G_CALLBACK (pad_added_cb), group);
  1679       group);
  2559   group->pad_removed_id = g_signal_connect (uridecodebin, "pad-removed",
  1680   g_signal_connect (uridecodebin, "pad-removed", G_CALLBACK (pad_removed_cb),
  2560       G_CALLBACK (pad_removed_cb), group);
  1681       group);
  2561   group->no_more_pads_id = g_signal_connect (uridecodebin, "no-more-pads",
  1682   g_signal_connect (uridecodebin, "no-more-pads", G_CALLBACK (no_more_pads_cb),
  2562       G_CALLBACK (no_more_pads_cb), group);
  1683       group);
  2563   group->notify_source_id = g_signal_connect (uridecodebin, "notify::source",
       
  2564       G_CALLBACK (notify_source_cb), group);
       
  2565   /* we have 1 pending no-more-pads */
       
  2566   group->pending = 1;
       
  2567 
       
  2568   /* is called when the uridecodebin is out of data and we can switch to the
  1684   /* is called when the uridecodebin is out of data and we can switch to the
  2569    * next uri */
  1685    * next uri */
  2570   group->drained_id =
  1686   g_signal_connect (uridecodebin, "drained", G_CALLBACK (drained_cb), group);
  2571       g_signal_connect (uridecodebin, "drained", G_CALLBACK (drained_cb),
       
  2572       group);
       
  2573 
  1687 
  2574   /* will be called when a new media type is found. We return a list of decoders
  1688   /* will be called when a new media type is found. We return a list of decoders
  2575    * including sinks for decodebin to try */
  1689    * including sinks for decodebin to try */
  2576   group->autoplug_factories_id =
  1690   g_signal_connect (uridecodebin, "autoplug-factories",
  2577       g_signal_connect (uridecodebin, "autoplug-factories",
       
  2578       G_CALLBACK (autoplug_factories_cb), group);
  1691       G_CALLBACK (autoplug_factories_cb), group);
  2579   group->autoplug_select_id = g_signal_connect (uridecodebin, "autoplug-select",
  1692 
       
  1693   g_signal_connect (uridecodebin, "autoplug-select",
  2580       G_CALLBACK (autoplug_select_cb), group);
  1694       G_CALLBACK (autoplug_select_cb), group);
  2581 
  1695 
  2582   if (group->suburi) {
  1696   /*  */
  2583     /* subtitles */
  1697   gst_bin_add (GST_BIN_CAST (playbin), uridecodebin);
  2584     if (group->suburidecodebin) {
  1698   group->uridecodebin = uridecodebin;
  2585       GST_DEBUG_OBJECT (playbin, "reusing existing suburidecodebin");
  1699 
  2586       REMOVE_SIGNAL (group->suburidecodebin, group->sub_pad_added_id);
  1700   gst_element_set_state (uridecodebin, GST_STATE_PAUSED);
  2587       REMOVE_SIGNAL (group->suburidecodebin, group->sub_pad_removed_id);
  1701 
  2588       REMOVE_SIGNAL (group->suburidecodebin, group->sub_no_more_pads_id);
       
  2589       gst_element_set_state (group->suburidecodebin, GST_STATE_NULL);
       
  2590       suburidecodebin = group->suburidecodebin;
       
  2591     } else {
       
  2592       GST_DEBUG_OBJECT (playbin, "making new suburidecodebin");
       
  2593       suburidecodebin = gst_element_factory_make ("uridecodebin", NULL);
       
  2594       if (!suburidecodebin)
       
  2595         goto no_decodebin;
       
  2596 
       
  2597       gst_bin_add (GST_BIN_CAST (playbin), suburidecodebin);
       
  2598       group->suburidecodebin = suburidecodebin;
       
  2599     }
       
  2600 
       
  2601     /* configure connection speed */
       
  2602     g_object_set (suburidecodebin, "connection-speed",
       
  2603         playbin->connection_speed, NULL);
       
  2604     /* configure subtitle encoding */
       
  2605     g_object_set (suburidecodebin, "subtitle-encoding", playbin->encoding,
       
  2606         NULL);
       
  2607     /* configure uri */
       
  2608     g_object_set (suburidecodebin, "uri", group->suburi, NULL);
       
  2609 
       
  2610     /* connect pads and other things */
       
  2611     group->sub_pad_added_id = g_signal_connect (suburidecodebin, "pad-added",
       
  2612         G_CALLBACK (pad_added_cb), group);
       
  2613     group->sub_pad_removed_id = g_signal_connect (suburidecodebin,
       
  2614         "pad-removed", G_CALLBACK (pad_removed_cb), group);
       
  2615     group->sub_no_more_pads_id = g_signal_connect (suburidecodebin,
       
  2616         "no-more-pads", G_CALLBACK (no_more_pads_cb), group);
       
  2617 
       
  2618     /* we have 2 pending no-more-pads */
       
  2619     group->pending = 2;
       
  2620   }
       
  2621 
       
  2622   /* release the group lock before setting the state of the decodebins, they
       
  2623    * might fire signals in this thread that we need to handle with the
       
  2624    * group_lock taken. */
       
  2625   GST_SOURCE_GROUP_UNLOCK (group);
       
  2626 
       
  2627   if (suburidecodebin) {
       
  2628     if (gst_element_set_state (suburidecodebin,
       
  2629             target) == GST_STATE_CHANGE_FAILURE)
       
  2630       goto suburidecodebin_failure;
       
  2631   }
       
  2632   if (gst_element_set_state (uridecodebin, target) == GST_STATE_CHANGE_FAILURE)
       
  2633     goto uridecodebin_failure;
       
  2634 
       
  2635   GST_SOURCE_GROUP_LOCK (group);
       
  2636   /* alow state changes of the playbin2 affect the group elements now */
       
  2637   group_set_locked_state_unlocked (playbin, group, FALSE);
       
  2638   group->active = TRUE;
  1702   group->active = TRUE;
  2639   GST_SOURCE_GROUP_UNLOCK (group);
       
  2640 
  1703 
  2641   return TRUE;
  1704   return TRUE;
  2642 
  1705 
  2643   /* ERRORS */
  1706   /* ERRORS */
  2644 no_decodebin:
  1707 no_decodebin:
  2645   {
  1708   {
  2646     GST_SOURCE_GROUP_UNLOCK (group);
       
  2647     return FALSE;
  1709     return FALSE;
  2648   }
  1710   }
  2649 suburidecodebin_failure:
  1711 }
  2650   {
  1712 
  2651     GST_DEBUG_OBJECT (playbin, "failed state change of subtitle uridecodebin");
  1713 /* unlink a group of uridecodebins from the sink */
  2652     return FALSE;
       
  2653   }
       
  2654 uridecodebin_failure:
       
  2655   {
       
  2656     GST_DEBUG_OBJECT (playbin, "failed state change of uridecodebin");
       
  2657     return FALSE;
       
  2658   }
       
  2659 }
       
  2660 
       
  2661 /* unlink a group of uridecodebins from the sink.
       
  2662  * must be called with PLAY_BIN_LOCK */
       
  2663 static gboolean
  1714 static gboolean
  2664 deactivate_group (GstPlayBin * playbin, GstSourceGroup * group)
  1715 deactivate_group (GstPlayBin * playbin, GstSourceGroup * group)
  2665 {
  1716 {
  2666   gint i;
  1717   gint i;
  2667 
  1718 
  2668   g_return_val_if_fail (group->valid, FALSE);
  1719   g_return_val_if_fail (group->valid, FALSE);
  2669   g_return_val_if_fail (group->active, FALSE);
  1720   g_return_val_if_fail (group->active, FALSE);
  2670 
  1721 
  2671   GST_DEBUG_OBJECT (playbin, "unlinking group %p", group);
  1722   GST_DEBUG_OBJECT (playbin, "unlinking group %p", group);
  2672 
  1723 
  2673   GST_SOURCE_GROUP_LOCK (group);
       
  2674   group->active = FALSE;
       
  2675   for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
  1724   for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
  2676     GstSourceSelect *select = &group->selector[i];
  1725     GstSourceSelect *select = &group->selector[i];
  2677 
  1726 
  2678     GST_DEBUG_OBJECT (playbin, "unlinking selector %s", select->media_list[0]);
  1727     if (!select->selector)
  2679 
  1728       continue;
  2680     if (select->srcpad) {
  1729 
  2681       if (select->sinkpad) {
  1730     GST_DEBUG_OBJECT (playbin, "unlinking selector %s", select->media);
  2682         GST_LOG_OBJECT (playbin, "unlinking from sink");
  1731     gst_pad_unlink (select->srcpad, select->sinkpad);
  2683         gst_pad_unlink (select->srcpad, select->sinkpad);
  1732 
  2684 
  1733     /* release back */
  2685         /* release back */
  1734     gst_play_sink_release_pad (playbin->playsink, select->sinkpad);
  2686         GST_LOG_OBJECT (playbin, "release sink pad");
  1735     select->sinkpad = NULL;
  2687         gst_play_sink_release_pad (playbin->playsink, select->sinkpad);
  1736 
  2688         select->sinkpad = NULL;
  1737     gst_object_unref (select->srcpad);
  2689       }
  1738     select->srcpad = NULL;
  2690       gst_object_unref (select->srcpad);
  1739 
  2691       select->srcpad = NULL;
  1740     gst_element_set_state (select->selector, GST_STATE_NULL);
  2692     }
  1741     gst_bin_remove (GST_BIN_CAST (playbin), select->selector);
  2693 
  1742     select->selector = NULL;
  2694     if (select->selector) {
  1743   }
  2695       gst_element_set_state (select->selector, GST_STATE_NULL);
  1744   group->active = FALSE;
  2696       gst_bin_remove (GST_BIN_CAST (playbin), select->selector);
       
  2697       select->selector = NULL;
       
  2698     }
       
  2699   }
       
  2700   /* delete any custom sinks we might have */
       
  2701   if (group->audio_sink)
       
  2702     gst_object_unref (group->audio_sink);
       
  2703   group->audio_sink = NULL;
       
  2704   if (group->video_sink)
       
  2705     gst_object_unref (group->video_sink);
       
  2706   group->video_sink = NULL;
       
  2707   /* we still have the decodebins added to the playbin2 but we can't remove them
       
  2708    * yet or change their state because this function might be called from the
       
  2709    * streaming threads, instead block the state so that state changes on the
       
  2710    * playbin2 don't affect us anymore */
       
  2711   group_set_locked_state_unlocked (playbin, group, TRUE);
       
  2712   GST_SOURCE_GROUP_UNLOCK (group);
       
  2713 
  1745 
  2714   return TRUE;
  1746   return TRUE;
  2715 }
  1747 }
  2716 
  1748 
  2717 /* setup the next group to play, this assumes the next_group is valid and
  1749 /* setup the next group to play, this assumes the next_group is valid and
  2718  * configured. It swaps out the current_group and activates the valid 
  1750  * configured. It swaps out the current_group and activates the valid 
  2719  * next_group. */
  1751  * next_group. */
  2720 static gboolean
  1752 static gboolean
  2721 setup_next_source (GstPlayBin * playbin, GstState target)
  1753 setup_next_source (GstPlayBin * playbin)
  2722 {
  1754 {
  2723   GstSourceGroup *new_group, *old_group;
  1755   GstSourceGroup *new_group, *old_group;
  2724 
  1756 
  2725   GST_DEBUG_OBJECT (playbin, "setup sources");
  1757   GST_DEBUG_OBJECT (playbin, "setup sources");
  2726 
  1758 
  2727   /* see if there is a next group */
  1759   /* see if there is a next group */
  2728   GST_PLAY_BIN_LOCK (playbin);
       
  2729   new_group = playbin->next_group;
  1760   new_group = playbin->next_group;
  2730   if (!new_group || !new_group->valid)
  1761   if (!new_group || !new_group->valid)
  2731     goto no_next_group;
  1762     goto no_next_group;
  2732 
  1763 
  2733   /* first unlink the current source, if any */
  1764   /* first unlink the current source, if any */
  2737     deactivate_group (playbin, old_group);
  1768     deactivate_group (playbin, old_group);
  2738     old_group->valid = FALSE;
  1769     old_group->valid = FALSE;
  2739   }
  1770   }
  2740 
  1771 
  2741   /* activate the new group */
  1772   /* activate the new group */
  2742   if (!activate_group (playbin, new_group, target))
  1773   if (!activate_group (playbin, new_group))
  2743     goto activate_failed;
  1774     goto activate_failed;
  2744 
  1775 
  2745   /* swap old and new */
  1776   /* swap old and new */
  2746   playbin->curr_group = new_group;
  1777   playbin->curr_group = new_group;
  2747   playbin->next_group = old_group;
  1778   playbin->next_group = old_group;
  2748   GST_PLAY_BIN_UNLOCK (playbin);
       
  2749 
  1779 
  2750   return TRUE;
  1780   return TRUE;
  2751 
  1781 
  2752   /* ERRORS */
  1782   /* ERRORS */
  2753 no_next_group:
  1783 no_next_group:
  2754   {
  1784   {
  2755     GST_DEBUG_OBJECT (playbin, "no next group");
  1785     GST_DEBUG_OBJECT (playbin, "no next group");
  2756     GST_PLAY_BIN_UNLOCK (playbin);
       
  2757     return FALSE;
  1786     return FALSE;
  2758   }
  1787   }
  2759 activate_failed:
  1788 activate_failed:
  2760   {
  1789   {
  2761     GST_DEBUG_OBJECT (playbin, "activate failed");
  1790     GST_DEBUG_OBJECT (playbin, "activate failed");
  2762     GST_PLAY_BIN_UNLOCK (playbin);
       
  2763     return FALSE;
  1791     return FALSE;
  2764   }
  1792   }
  2765 }
  1793 }
  2766 
  1794 
  2767 /* The group that is currently playing is copied again to the
  1795 /* The group that is currently playing is copied again to the
  2768  * next_group so that it will start playing the next time.
  1796  * next_group.
  2769  */
  1797  */
  2770 static gboolean
  1798 static gboolean
  2771 save_current_group (GstPlayBin * playbin)
  1799 save_current_group (GstPlayBin * playbin)
  2772 {
  1800 {
  2773   GstSourceGroup *curr_group;
  1801   GstSourceGroup *curr_group;
  2774 
  1802 
  2775   GST_DEBUG_OBJECT (playbin, "save current group");
  1803   GST_DEBUG_OBJECT (playbin, "save current group");
  2776 
  1804 
  2777   /* see if there is a current group */
  1805   /* see if there is a current group */
  2778   GST_PLAY_BIN_LOCK (playbin);
       
  2779   curr_group = playbin->curr_group;
  1806   curr_group = playbin->curr_group;
  2780   if (curr_group && curr_group->valid) {
  1807   if (curr_group && curr_group->valid) {
  2781     /* unlink our pads with the sink */
  1808     /* unlink our pads with the sink */
  2782     deactivate_group (playbin, curr_group);
  1809     deactivate_group (playbin, curr_group);
  2783   }
  1810   }
  2784   /* swap old and new */
  1811   /* swap old and new */
  2785   playbin->curr_group = playbin->next_group;
  1812   playbin->curr_group = playbin->next_group;
  2786   playbin->next_group = curr_group;
  1813   playbin->next_group = curr_group;
  2787   GST_PLAY_BIN_UNLOCK (playbin);
       
  2788 
       
  2789   return TRUE;
       
  2790 }
       
  2791 
       
  2792 /* clear the locked state from all groups. This function is called before a
       
  2793  * state change to NULL is performed on them. */
       
  2794 static gboolean
       
  2795 groups_set_locked_state (GstPlayBin * playbin, gboolean locked)
       
  2796 {
       
  2797   GST_DEBUG_OBJECT (playbin, "setting locked state to %d on all groups",
       
  2798       locked);
       
  2799 
       
  2800   GST_PLAY_BIN_LOCK (playbin);
       
  2801   GST_SOURCE_GROUP_LOCK (playbin->curr_group);
       
  2802   group_set_locked_state_unlocked (playbin, playbin->curr_group, locked);
       
  2803   GST_SOURCE_GROUP_UNLOCK (playbin->curr_group);
       
  2804   GST_SOURCE_GROUP_LOCK (playbin->next_group);
       
  2805   group_set_locked_state_unlocked (playbin, playbin->next_group, locked);
       
  2806   GST_SOURCE_GROUP_UNLOCK (playbin->next_group);
       
  2807   GST_PLAY_BIN_UNLOCK (playbin);
       
  2808 
  1814 
  2809   return TRUE;
  1815   return TRUE;
  2810 }
  1816 }
  2811 
  1817 
  2812 static GstStateChangeReturn
  1818 static GstStateChangeReturn
  2817 
  1823 
  2818   playbin = GST_PLAY_BIN (element);
  1824   playbin = GST_PLAY_BIN (element);
  2819 
  1825 
  2820   switch (transition) {
  1826   switch (transition) {
  2821     case GST_STATE_CHANGE_READY_TO_PAUSED:
  1827     case GST_STATE_CHANGE_READY_TO_PAUSED:
  2822       GST_LOG_OBJECT (playbin, "clearing shutdown flag");
  1828       if (!setup_next_source (playbin))
  2823       g_atomic_int_set (&playbin->shutdown, 0);
       
  2824       if (!setup_next_source (playbin, GST_STATE_READY))
       
  2825         goto source_failed;
  1829         goto source_failed;
  2826       break;
  1830       break;
  2827     case GST_STATE_CHANGE_PAUSED_TO_READY:
       
  2828       /* FIXME unlock our waiting groups */
       
  2829       GST_LOG_OBJECT (playbin, "setting shutdown flag");
       
  2830       g_atomic_int_set (&playbin->shutdown, 1);
       
  2831 
       
  2832       /* wait for all callbacks to end by taking the lock.
       
  2833        * No dynamic (critical) new callbacks will
       
  2834        * be able to happen as we set the shutdown flag. */
       
  2835       GST_PLAY_BIN_DYN_LOCK (playbin);
       
  2836       GST_LOG_OBJECT (playbin, "dynamic lock taken, we can continue shutdown");
       
  2837       GST_PLAY_BIN_DYN_UNLOCK (playbin);
       
  2838       break;
       
  2839     case GST_STATE_CHANGE_READY_TO_NULL:
       
  2840       /* unlock so that all groups go to NULL */
       
  2841       groups_set_locked_state (playbin, FALSE);
       
  2842       break;
       
  2843     default:
  1831     default:
  2844       break;
  1832       break;
  2845   }
  1833   }
  2846 
  1834 
  2847   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
  1835   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
  2848   if (ret == GST_STATE_CHANGE_FAILURE) {
  1836   if (ret == GST_STATE_CHANGE_FAILURE)
  2849     if (transition == GST_STATE_CHANGE_READY_TO_PAUSED) {
       
  2850       GstSourceGroup *curr_group;
       
  2851 
       
  2852       curr_group = playbin->curr_group;
       
  2853       if (curr_group && curr_group->valid) {
       
  2854         /* unlink our pads with the sink */
       
  2855         deactivate_group (playbin, curr_group);
       
  2856       }
       
  2857 
       
  2858       /* Swap current and next group back */
       
  2859       playbin->curr_group = playbin->next_group;
       
  2860       playbin->next_group = curr_group;
       
  2861     }
       
  2862     return ret;
  1837     return ret;
  2863   }
       
  2864 
  1838 
  2865   switch (transition) {
  1839   switch (transition) {
  2866     case GST_STATE_CHANGE_READY_TO_PAUSED:
  1840     case GST_STATE_CHANGE_READY_TO_PAUSED:
  2867       break;
  1841       break;
  2868     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
  1842     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
  2869       /* FIXME Release audio device when we implement that */
  1843       /* FIXME Release audio device when we implement that */
  2870       break;
  1844       break;
  2871     case GST_STATE_CHANGE_PAUSED_TO_READY:
  1845     case GST_STATE_CHANGE_PAUSED_TO_READY:
  2872       save_current_group (playbin);
  1846       save_current_group (playbin);
  2873       break;
       
  2874     case GST_STATE_CHANGE_READY_TO_NULL:
       
  2875       /* make sure the groups don't perform a state change anymore until we
       
  2876        * enable them again */
       
  2877       groups_set_locked_state (playbin, TRUE);
       
  2878       break;
  1847       break;
  2879     default:
  1848     default:
  2880       break;
  1849       break;
  2881   }
  1850   }
  2882 
  1851 
  2896 gboolean
  1865 gboolean
  2897 gst_play_bin2_plugin_init (GstPlugin * plugin)
  1866 gst_play_bin2_plugin_init (GstPlugin * plugin)
  2898 {
  1867 {
  2899   GST_DEBUG_CATEGORY_INIT (gst_play_bin_debug, "playbin2", 0, "play bin");
  1868   GST_DEBUG_CATEGORY_INIT (gst_play_bin_debug, "playbin2", 0, "play bin");
  2900 
  1869 
  2901   g_type_class_ref (gst_input_selector_get_type ());
       
  2902   g_type_class_ref (gst_selector_pad_get_type ());
       
  2903 
       
  2904   return gst_element_register (plugin, "playbin2", GST_RANK_NONE,
  1870   return gst_element_register (plugin, "playbin2", GST_RANK_NONE,
  2905       GST_TYPE_PLAY_BIN);
  1871       GST_TYPE_PLAY_BIN);
  2906 }
  1872 }