gst_plugins_base/gst/playback/gstplaybasebin.c
changeset 0 0e761a78d257
child 8 4a7fac7dd34a
equal deleted inserted replaced
-1:000000000000 0:0e761a78d257
       
     1 /* GStreamer
       
     2  * Copyright (C) <2007> Wim Taymans <wim.taymans@gmail.com>
       
     3  *
       
     4  * This library is free software; you can redistribute it and/or
       
     5  * modify it under the terms of the GNU Library General Public
       
     6  * License as published by the Free Software Foundation; either
       
     7  * version 2 of the License, or (at your option) any later version.
       
     8  *
       
     9  * This library is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    12  * Library General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU Library General Public
       
    15  * License along with this library; if not, write to the
       
    16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    17  * Boston, MA 02111-1307, USA.
       
    18  */
       
    19 
       
    20 #ifdef HAVE_CONFIG_H
       
    21 #include "config.h"
       
    22 #endif
       
    23 
       
    24 #include <gst/gst-i18n-plugin.h>
       
    25 #include <string.h>
       
    26 #include "gstplaybasebin.h"
       
    27 #include "gststreamselector.h"
       
    28 #include "gstplay-marshal.h"
       
    29 
       
    30 #include <gst/pbutils/pbutils.h>
       
    31 
       
    32 #ifdef __SYMBIAN32__
       
    33 #include <glib_global.h>
       
    34 #endif
       
    35 
       
    36 GST_DEBUG_CATEGORY_STATIC (gst_play_base_bin_debug);
       
    37 #define GST_CAT_DEFAULT gst_play_base_bin_debug
       
    38 
       
    39 #define DEFAULT_QUEUE_SIZE          (3 * GST_SECOND)
       
    40 #define DEFAULT_QUEUE_MIN_THRESHOLD ((DEFAULT_QUEUE_SIZE * 30) / 100)
       
    41 #define DEFAULT_QUEUE_THRESHOLD     ((DEFAULT_QUEUE_SIZE * 95) / 100)
       
    42 #define DEFAULT_CONNECTION_SPEED    0
       
    43 
       
    44 #define GROUP_LOCK(pbb) g_mutex_lock (pbb->group_lock)
       
    45 #define GROUP_UNLOCK(pbb) g_mutex_unlock (pbb->group_lock)
       
    46 #define GROUP_WAIT(pbb) g_cond_wait (pbb->group_cond, pbb->group_lock)
       
    47 #define GROUP_SIGNAL(pbb) g_cond_signal (pbb->group_cond)
       
    48 
       
    49 /* props */
       
    50 enum
       
    51 {
       
    52   ARG_0,
       
    53   ARG_URI,
       
    54   ARG_SUBURI,
       
    55   ARG_QUEUE_SIZE,
       
    56   ARG_QUEUE_THRESHOLD,
       
    57   ARG_QUEUE_MIN_THRESHOLD,
       
    58   ARG_NSTREAMS,
       
    59   ARG_STREAMINFO,
       
    60   ARG_STREAMINFO_VALUES,
       
    61   ARG_SOURCE,
       
    62   ARG_VIDEO,
       
    63   ARG_AUDIO,
       
    64   ARG_TEXT,
       
    65   ARG_SUBTITLE_ENCODING,
       
    66   ARG_CONNECTION_SPEED
       
    67 };
       
    68 
       
    69 static void gst_play_base_bin_class_init (GstPlayBaseBinClass * klass);
       
    70 static void gst_play_base_bin_init (GstPlayBaseBin * play_base_bin);
       
    71 static void gst_play_base_bin_dispose (GObject * object);
       
    72 static void gst_play_base_bin_finalize (GObject * object);
       
    73 
       
    74 static void gst_play_base_bin_set_property (GObject * object, guint prop_id,
       
    75     const GValue * value, GParamSpec * spec);
       
    76 static void gst_play_base_bin_get_property (GObject * object, guint prop_id,
       
    77     GValue * value, GParamSpec * spec);
       
    78 static void gst_play_base_bin_handle_message_func (GstBin * bin,
       
    79     GstMessage * msg);
       
    80 
       
    81 static GstStateChangeReturn gst_play_base_bin_change_state (GstElement *
       
    82     element, GstStateChange transition);
       
    83 
       
    84 static const GList *gst_play_base_bin_get_streaminfo (GstPlayBaseBin * bin);
       
    85 static GValueArray *gst_play_base_bin_get_streaminfo_value_array (GstPlayBaseBin
       
    86     * play_base_bin);
       
    87 static void preroll_remove_overrun (GstElement * element,
       
    88     GstPlayBaseBin * play_base_bin);
       
    89 static void queue_remove_probe (GstElement * queue, GstPlayBaseBin
       
    90     * play_base_bin);
       
    91 
       
    92 static GstElement *make_decoder (GstPlayBaseBin * play_base_bin);
       
    93 static gboolean has_all_raw_caps (GstPad * pad, gboolean * all_raw);
       
    94 
       
    95 static gboolean prepare_output (GstPlayBaseBin * play_base_bin);
       
    96 static void set_active_source (GstPlayBaseBin * play_base_bin,
       
    97     GstStreamType type, gint source_num);
       
    98 static gboolean probe_triggered (GstPad * pad, GstEvent * event,
       
    99     gpointer user_data);
       
   100 static void setup_substreams (GstPlayBaseBin * play_base_bin);
       
   101 
       
   102 static GstPipelineClass *parent_class;
       
   103 
       
   104 /*
       
   105  * GObject playbasebin wrappers.
       
   106  */
       
   107 #ifdef __SYMBIAN32__
       
   108 EXPORT_C
       
   109 #endif
       
   110 
       
   111 
       
   112 GType
       
   113 gst_play_base_bin_get_type (void)
       
   114 {
       
   115   static GType gst_play_base_bin_type = 0;
       
   116 
       
   117   if (!gst_play_base_bin_type) {
       
   118     static const GTypeInfo gst_play_base_bin_info = {
       
   119       sizeof (GstPlayBaseBinClass),
       
   120       NULL,
       
   121       NULL,
       
   122       (GClassInitFunc) gst_play_base_bin_class_init,
       
   123       NULL,
       
   124       NULL,
       
   125       sizeof (GstPlayBaseBin),
       
   126       0,
       
   127       (GInstanceInitFunc) gst_play_base_bin_init,
       
   128       NULL
       
   129     };
       
   130 
       
   131     gst_play_base_bin_type = g_type_register_static (GST_TYPE_PIPELINE,
       
   132         "GstPlayBaseBin", &gst_play_base_bin_info, 0);
       
   133   }
       
   134 
       
   135   return gst_play_base_bin_type;
       
   136 }
       
   137 
       
   138 static void
       
   139 gst_play_base_bin_class_init (GstPlayBaseBinClass * klass)
       
   140 {
       
   141   GObjectClass *gobject_klass;
       
   142   GstElementClass *gstelement_klass;
       
   143   GstBinClass *gstbin_klass;
       
   144 
       
   145   gobject_klass = (GObjectClass *) klass;
       
   146   gstelement_klass = (GstElementClass *) klass;
       
   147   gstbin_klass = (GstBinClass *) klass;
       
   148 
       
   149   parent_class = g_type_class_peek_parent (klass);
       
   150 
       
   151   gobject_klass->set_property = gst_play_base_bin_set_property;
       
   152   gobject_klass->get_property = gst_play_base_bin_get_property;
       
   153 
       
   154   g_object_class_install_property (gobject_klass, ARG_URI,
       
   155       g_param_spec_string ("uri", "URI", "URI of the media to play",
       
   156           NULL, G_PARAM_READWRITE));
       
   157   g_object_class_install_property (gobject_klass, ARG_SUBURI,
       
   158       g_param_spec_string ("suburi", ".sub-URI", "Optional URI of a subtitle",
       
   159           NULL, G_PARAM_READWRITE));
       
   160 
       
   161   g_object_class_install_property (gobject_klass, ARG_QUEUE_SIZE,
       
   162       g_param_spec_uint64 ("queue-size", "Queue size",
       
   163           "Size of internal queues in nanoseconds", 0, G_MAXINT64,
       
   164           DEFAULT_QUEUE_SIZE, G_PARAM_READWRITE));
       
   165   g_object_class_install_property (gobject_klass, ARG_QUEUE_THRESHOLD,
       
   166       g_param_spec_uint64 ("queue-threshold", "Queue threshold",
       
   167           "Buffering threshold of internal queues in nanoseconds", 0,
       
   168           G_MAXINT64, DEFAULT_QUEUE_THRESHOLD, G_PARAM_READWRITE));
       
   169   g_object_class_install_property (gobject_klass, ARG_QUEUE_MIN_THRESHOLD,
       
   170       g_param_spec_uint64 ("queue-min-threshold", "Queue min threshold",
       
   171           "Buffering low threshold of internal queues in nanoseconds", 0,
       
   172           G_MAXINT64, DEFAULT_QUEUE_MIN_THRESHOLD, G_PARAM_READWRITE));
       
   173 
       
   174   g_object_class_install_property (gobject_klass, ARG_NSTREAMS,
       
   175       g_param_spec_int ("nstreams", "NStreams", "number of streams",
       
   176           0, G_MAXINT, 0, G_PARAM_READABLE));
       
   177   g_object_class_install_property (gobject_klass, ARG_STREAMINFO,
       
   178       g_param_spec_pointer ("stream-info", "Stream info", "List of streaminfo",
       
   179           G_PARAM_READABLE));
       
   180   g_object_class_install_property (gobject_klass, ARG_STREAMINFO_VALUES,
       
   181       g_param_spec_value_array ("stream-info-value-array",
       
   182           "StreamInfo GValueArray", "value array of streaminfo",
       
   183           g_param_spec_object ("streaminfo", "StreamInfo", "Streaminfo object",
       
   184               GST_TYPE_STREAM_INFO, G_PARAM_READABLE), G_PARAM_READABLE));
       
   185   g_object_class_install_property (gobject_klass, ARG_SOURCE,
       
   186       g_param_spec_object ("source", "Source", "Source element",
       
   187           GST_TYPE_ELEMENT, G_PARAM_READABLE));
       
   188 
       
   189   g_object_class_install_property (gobject_klass, ARG_VIDEO,
       
   190       g_param_spec_int ("current-video", "Current video",
       
   191           "Currently playing video stream (-1 = none)",
       
   192           -1, G_MAXINT, -1, G_PARAM_READWRITE));
       
   193   g_object_class_install_property (gobject_klass, ARG_AUDIO,
       
   194       g_param_spec_int ("current-audio", "Current audio",
       
   195           "Currently playing audio stream (-1 = none)",
       
   196           -1, G_MAXINT, -1, G_PARAM_READWRITE));
       
   197   g_object_class_install_property (gobject_klass, ARG_TEXT,
       
   198       g_param_spec_int ("current-text", "Current text",
       
   199           "Currently playing text stream (-1 = none)",
       
   200           -1, G_MAXINT, -1, G_PARAM_READWRITE));
       
   201   g_object_class_install_property (gobject_klass, ARG_SUBTITLE_ENCODING,
       
   202       g_param_spec_string ("subtitle-encoding", "subtitle encoding",
       
   203           "Encoding to assume if input subtitles are not in UTF-8 encoding. "
       
   204           "If not set, the GST_SUBTITLE_ENCODING environment variable will "
       
   205           "be checked for an encoding to use. If that is not set either, "
       
   206           "ISO-8859-15 will be assumed.", NULL, G_PARAM_READWRITE));
       
   207   /**
       
   208    * GstPlayBin::connection-speed
       
   209    *
       
   210    * Network connection speed in kbps (0 = unknown)
       
   211    *
       
   212    * Since: 0.10.10 at gstplaybin.c, 0.10.15 moved to gstplaybasebin
       
   213    **/
       
   214   g_object_class_install_property (gobject_klass, ARG_CONNECTION_SPEED,
       
   215       g_param_spec_uint ("connection-speed", "Connection Speed",
       
   216           "Network connection speed in kbps (0 = unknown)",
       
   217           0, G_MAXUINT, DEFAULT_CONNECTION_SPEED, G_PARAM_READWRITE));
       
   218 
       
   219   GST_DEBUG_CATEGORY_INIT (gst_play_base_bin_debug, "playbasebin", 0,
       
   220       "playbasebin");
       
   221 
       
   222   gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_play_base_bin_dispose);
       
   223   gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_play_base_bin_finalize);
       
   224 
       
   225   gstbin_klass->handle_message =
       
   226       GST_DEBUG_FUNCPTR (gst_play_base_bin_handle_message_func);
       
   227 
       
   228   gstelement_klass->change_state =
       
   229       GST_DEBUG_FUNCPTR (gst_play_base_bin_change_state);
       
   230 }
       
   231 
       
   232 static void
       
   233 gst_play_base_bin_init (GstPlayBaseBin * play_base_bin)
       
   234 {
       
   235   play_base_bin->uri = NULL;
       
   236   play_base_bin->suburi = NULL;
       
   237   play_base_bin->need_rebuild = TRUE;
       
   238   play_base_bin->is_stream = FALSE;
       
   239   play_base_bin->source = NULL;
       
   240   play_base_bin->decoders = NULL;
       
   241   play_base_bin->subtitle = NULL;
       
   242   play_base_bin->subencoding = NULL;
       
   243   play_base_bin->subtitle_elements = NULL;
       
   244   play_base_bin->sub_lock = g_mutex_new ();
       
   245 
       
   246   play_base_bin->group_lock = g_mutex_new ();
       
   247   play_base_bin->group_cond = g_cond_new ();
       
   248 
       
   249   play_base_bin->building_group = NULL;
       
   250   play_base_bin->queued_groups = NULL;
       
   251 
       
   252   play_base_bin->queue_size = DEFAULT_QUEUE_SIZE;
       
   253   play_base_bin->queue_threshold = DEFAULT_QUEUE_THRESHOLD;
       
   254   play_base_bin->queue_min_threshold = DEFAULT_QUEUE_MIN_THRESHOLD;
       
   255   play_base_bin->connection_speed = DEFAULT_CONNECTION_SPEED;
       
   256 }
       
   257 
       
   258 static void
       
   259 gst_play_base_bin_dispose (GObject * object)
       
   260 {
       
   261   GstPlayBaseBin *play_base_bin;
       
   262 
       
   263   play_base_bin = GST_PLAY_BASE_BIN (object);
       
   264   g_free (play_base_bin->uri);
       
   265   play_base_bin->uri = NULL;
       
   266   g_free (play_base_bin->suburi);
       
   267   play_base_bin->suburi = NULL;
       
   268   g_free (play_base_bin->subencoding);
       
   269   play_base_bin->subencoding = NULL;
       
   270   if (play_base_bin->subtitle_elements) {
       
   271     g_slist_free (play_base_bin->subtitle_elements);
       
   272     play_base_bin->subtitle_elements = NULL;
       
   273   }
       
   274   G_OBJECT_CLASS (parent_class)->dispose (object);
       
   275 }
       
   276 
       
   277 static void
       
   278 gst_play_base_bin_finalize (GObject * object)
       
   279 {
       
   280   GstPlayBaseBin *play_base_bin = GST_PLAY_BASE_BIN (object);
       
   281 
       
   282   g_mutex_free (play_base_bin->group_lock);
       
   283   g_cond_free (play_base_bin->group_cond);
       
   284 
       
   285   g_mutex_free (play_base_bin->sub_lock);
       
   286 
       
   287   G_OBJECT_CLASS (parent_class)->finalize (object);
       
   288 }
       
   289 
       
   290 /*
       
   291  * playbasebingroup stuff.
       
   292  */
       
   293 
       
   294 static GstPlayBaseGroup *
       
   295 group_create (GstPlayBaseBin * play_base_bin)
       
   296 {
       
   297   GstPlayBaseGroup *group;
       
   298 
       
   299   group = g_new0 (GstPlayBaseGroup, 1);
       
   300   group->bin = play_base_bin;
       
   301   group->streaminfo_value_array = g_value_array_new (0);
       
   302 
       
   303   GST_DEBUG_OBJECT (play_base_bin, "created new group %p", group);
       
   304 
       
   305   return group;
       
   306 }
       
   307 
       
   308 /*
       
   309  * Gets the currently playing group.
       
   310  *
       
   311  * Callers must have group-lock held when calling this.
       
   312  */
       
   313 
       
   314 static GstPlayBaseGroup *
       
   315 get_active_group (GstPlayBaseBin * play_base_bin)
       
   316 {
       
   317   GstPlayBaseGroup *group = NULL;
       
   318 
       
   319   if (play_base_bin->queued_groups)
       
   320     group = play_base_bin->queued_groups->data;
       
   321 
       
   322   return group;
       
   323 }
       
   324 
       
   325 /*
       
   326  * get the group used for discovering the different streams.
       
   327  * This function creates a group is there is none.
       
   328  *
       
   329  * Callers must have group-lock held when calling this.
       
   330  */
       
   331 static GstPlayBaseGroup *
       
   332 get_building_group (GstPlayBaseBin * play_base_bin)
       
   333 {
       
   334   GstPlayBaseGroup *group;
       
   335 
       
   336   group = play_base_bin->building_group;
       
   337   if (group == NULL) {
       
   338     group = group_create (play_base_bin);
       
   339     play_base_bin->building_group = group;
       
   340   }
       
   341 
       
   342   return group;
       
   343 }
       
   344 
       
   345 /*
       
   346  * Callers must have lock held when calling this!
       
   347  */
       
   348 
       
   349 static void
       
   350 group_destroy (GstPlayBaseGroup * group)
       
   351 {
       
   352   GstPlayBaseBin *play_base_bin = group->bin;
       
   353   gint n;
       
   354 
       
   355   GST_LOG ("removing group %p", group);
       
   356 
       
   357   /* remove the preroll queues */
       
   358   for (n = 0; n < NUM_TYPES; n++) {
       
   359     GstElement *element = group->type[n].preroll;
       
   360     GstElement *fakesrc;
       
   361     GstElement *sel;
       
   362     const GList *item;
       
   363 
       
   364     if (!element)
       
   365       continue;
       
   366 
       
   367     sel = group->type[n].selector;
       
   368 
       
   369     /* remove any fakesrc elements for this preroll element */
       
   370     for (item = sel->pads; item != NULL; item = item->next) {
       
   371       GstPad *pad = GST_PAD (item->data);
       
   372       guint sig_id;
       
   373 
       
   374       if (GST_PAD_DIRECTION (pad) != GST_PAD_SINK)
       
   375         continue;
       
   376 
       
   377       sig_id =
       
   378           GPOINTER_TO_INT (g_object_get_data (G_OBJECT (pad), "unlinked_id"));
       
   379 
       
   380       if (sig_id != 0) {
       
   381         GST_LOG ("removing unlink signal %s:%s", GST_DEBUG_PAD_NAME (pad));
       
   382         g_signal_handler_disconnect (G_OBJECT (pad), sig_id);
       
   383         g_object_set_data (G_OBJECT (pad), "unlinked_id", GINT_TO_POINTER (0));
       
   384       }
       
   385 
       
   386       fakesrc = (GstElement *) g_object_get_data (G_OBJECT (pad), "fakesrc");
       
   387       if (fakesrc != NULL) {
       
   388         GST_LOG ("removing fakesrc from %s:%s",
       
   389             GST_PAD_NAME (pad), GST_ELEMENT_NAME (GST_PAD_PARENT (pad)));
       
   390         gst_element_set_state (fakesrc, GST_STATE_NULL);
       
   391         gst_bin_remove (GST_BIN_CAST (play_base_bin), fakesrc);
       
   392       }
       
   393     }
       
   394 
       
   395     /* if the group is currently being played, we have to remove the element
       
   396      * from the thread */
       
   397     gst_element_set_state (element, GST_STATE_NULL);
       
   398     gst_element_set_state (group->type[n].selector, GST_STATE_NULL);
       
   399 
       
   400     GST_LOG ("removing preroll element %s", GST_ELEMENT_NAME (element));
       
   401 
       
   402     gst_bin_remove (group->type[n].bin, element);
       
   403     gst_bin_remove (group->type[n].bin, group->type[n].selector);
       
   404 
       
   405     group->type[n].preroll = NULL;
       
   406     group->type[n].selector = NULL;
       
   407     group->type[n].bin = NULL;
       
   408   }
       
   409 
       
   410   /* free the streaminfo too */
       
   411   g_list_foreach (group->streaminfo, (GFunc) g_object_unref, NULL);
       
   412   g_list_free (group->streaminfo);
       
   413   g_value_array_free (group->streaminfo_value_array);
       
   414   g_free (group);
       
   415 }
       
   416 
       
   417 /*
       
   418  * is called when the current building group is completely finished
       
   419  * and ready for playback
       
   420  *
       
   421  * This function grabs lock, so take care when calling.
       
   422  */
       
   423 static void
       
   424 group_commit (GstPlayBaseBin * play_base_bin, gboolean fatal, gboolean subtitle)
       
   425 {
       
   426   GstPlayBaseGroup *group;
       
   427   gboolean had_active_group;
       
   428   gboolean res;
       
   429 
       
   430   GROUP_LOCK (play_base_bin);
       
   431   group = play_base_bin->building_group;
       
   432   had_active_group = (get_active_group (play_base_bin) != NULL);
       
   433 
       
   434   GST_DEBUG_OBJECT (play_base_bin, "commit group %p, had active %d",
       
   435       group, had_active_group);
       
   436 
       
   437   /* if an element signalled a no-more-pads after we stopped due
       
   438    * to preroll, the group is NULL. This is not an error */
       
   439   if (group == NULL) {
       
   440     if (!fatal) {
       
   441       GROUP_UNLOCK (play_base_bin);
       
   442       return;
       
   443     } else {
       
   444       GST_DEBUG_OBJECT (play_base_bin, "Group loading failed, bailing out");
       
   445     }
       
   446   } else {
       
   447     if (!subtitle) {
       
   448       gint n;
       
   449 
       
   450       GST_DEBUG_OBJECT (play_base_bin, "group %p done", group);
       
   451 
       
   452       play_base_bin->queued_groups =
       
   453           g_list_append (play_base_bin->queued_groups, group);
       
   454 
       
   455       play_base_bin->building_group = NULL;
       
   456 
       
   457       /* remove signals. We don't want anymore signals from the preroll
       
   458        * elements at this stage. */
       
   459       for (n = 0; n < NUM_TYPES; n++) {
       
   460         GstElement *element = group->type[n].preroll;
       
   461 
       
   462         if (!element)
       
   463           continue;
       
   464 
       
   465         preroll_remove_overrun (element, play_base_bin);
       
   466         /* if overrun is removed, probe alse has to be removed */
       
   467         queue_remove_probe (element, play_base_bin);
       
   468       }
       
   469     } else {
       
   470       /* this is a special subtitle bin, we don't commit the group but
       
   471        * mark the subtitles as detected before we signal. */
       
   472       GST_DEBUG_OBJECT (play_base_bin, "marking subtitle bin as complete");
       
   473       play_base_bin->subtitle_done = TRUE;
       
   474     }
       
   475   }
       
   476 
       
   477   GST_DEBUG_OBJECT (play_base_bin, "signal group done");
       
   478   GROUP_SIGNAL (play_base_bin);
       
   479   GST_DEBUG_OBJECT (play_base_bin, "signaled group done");
       
   480 
       
   481   if (!subtitle && !had_active_group) {
       
   482     if (!prepare_output (play_base_bin)) {
       
   483       GROUP_UNLOCK (play_base_bin);
       
   484       return;
       
   485     }
       
   486 
       
   487     setup_substreams (play_base_bin);
       
   488     GST_DEBUG_OBJECT (play_base_bin, "Emitting signal");
       
   489     res = GST_PLAY_BASE_BIN_GET_CLASS (play_base_bin)->
       
   490         setup_output_pads (play_base_bin, group);
       
   491     GST_DEBUG_OBJECT (play_base_bin, "done");
       
   492 
       
   493     GROUP_UNLOCK (play_base_bin);
       
   494 
       
   495     g_object_notify (G_OBJECT (play_base_bin), "stream-info");
       
   496   } else {
       
   497     GROUP_UNLOCK (play_base_bin);
       
   498   }
       
   499 }
       
   500 
       
   501 /*
       
   502  * check if there are streams in the group that are not muted
       
   503  *
       
   504  * Callers must have group-lock held when calling this.
       
   505  */
       
   506 static gboolean
       
   507 group_is_muted (GstPlayBaseGroup * group)
       
   508 {
       
   509   gint n;
       
   510 
       
   511   for (n = 0; n < NUM_TYPES; n++) {
       
   512     if (group->type[n].preroll && !group->type[n].done)
       
   513       return FALSE;
       
   514   }
       
   515 
       
   516   return TRUE;
       
   517 }
       
   518 
       
   519 /*
       
   520  * Buffer/cache checking.
       
   521  */
       
   522 
       
   523 static inline void
       
   524 fill_buffer (GstPlayBaseBin * play_base_bin, gint percent)
       
   525 {
       
   526   GST_DEBUG_OBJECT (play_base_bin, "buffering %d", percent);
       
   527   gst_element_post_message (GST_ELEMENT_CAST (play_base_bin),
       
   528       gst_message_new_buffering (GST_OBJECT_CAST (play_base_bin), percent));
       
   529 }
       
   530 
       
   531 static gboolean
       
   532 check_queue_event (GstPad * pad, GstEvent * event, gpointer user_data)
       
   533 {
       
   534   GstElement *queue = GST_ELEMENT_CAST (user_data);
       
   535 
       
   536   switch (GST_EVENT_TYPE (event)) {
       
   537     case GST_EVENT_EOS:
       
   538       GST_DEBUG ("EOS event, mark EOS");
       
   539       g_object_set_data (G_OBJECT (queue), "eos", "1");
       
   540       break;
       
   541     case GST_EVENT_FLUSH_STOP:
       
   542       GST_DEBUG ("FLUSH_STOP event, remove EOS");
       
   543       g_object_set_data (G_OBJECT (queue), "eos", NULL);
       
   544       break;
       
   545     default:
       
   546       GST_DEBUG ("uninteresting event %s", GST_EVENT_TYPE_NAME (event));
       
   547       break;
       
   548   }
       
   549   return TRUE;
       
   550 }
       
   551 
       
   552 static gboolean
       
   553 check_queue (GstPad * pad, GstBuffer * data, gpointer user_data)
       
   554 {
       
   555   GstElement *queue = GST_ELEMENT_CAST (user_data);
       
   556   GstPlayBaseBin *play_base_bin = g_object_get_data (G_OBJECT (queue), "pbb");
       
   557   guint64 level = 0;
       
   558 
       
   559   GST_DEBUG_OBJECT (queue, "check queue triggered");
       
   560 
       
   561   g_object_get (G_OBJECT (queue), "current-level-time", &level, NULL);
       
   562   GST_DEBUG_OBJECT (play_base_bin, "Queue size: %" GST_TIME_FORMAT,
       
   563       GST_TIME_ARGS (level));
       
   564 
       
   565   if (play_base_bin->queue_threshold > 0) {
       
   566     level = level * 99 / play_base_bin->queue_threshold;
       
   567     if (level > 99)
       
   568       level = 99;
       
   569   } else
       
   570     level = 99;
       
   571 
       
   572   fill_buffer (play_base_bin, level);
       
   573 
       
   574   /* continue! */
       
   575   return TRUE;
       
   576 }
       
   577 
       
   578 /* If a queue overruns and we are buffer in streaming mode (we have a min-time)
       
   579  * we can potentially create a deadlock when:
       
   580  *
       
   581  *  1) the max-bytes is hit and
       
   582  *  2) the min-time is not hit.
       
   583  *
       
   584  * We recover from this situation in this callback by
       
   585  * setting the max-bytes to unlimited if we see that there is
       
   586  * a current-time-level (which means some sort of timestamping is
       
   587  * done).
       
   588  */
       
   589 static void
       
   590 queue_deadlock_check (GstElement * queue, GstPlayBaseBin * play_base_bin)
       
   591 {
       
   592   guint64 time, min_time;
       
   593   guint bytes;
       
   594 
       
   595   GST_DEBUG_OBJECT (play_base_bin, "overrun signal received from queue %s",
       
   596       GST_ELEMENT_NAME (queue));
       
   597 
       
   598   /* figure out where we are */
       
   599   g_object_get (G_OBJECT (queue), "current-level-time", &time,
       
   600       "current-level-bytes", &bytes, "min-threshold-time", &min_time, NULL);
       
   601 
       
   602   GST_DEBUG_OBJECT (play_base_bin, "streaming mode, queue %s current %"
       
   603       GST_TIME_FORMAT ", min %" GST_TIME_FORMAT
       
   604       ", bytes %d", GST_ELEMENT_NAME (queue),
       
   605       GST_TIME_ARGS (time), GST_TIME_ARGS (min_time), bytes);
       
   606 
       
   607   /* if the bytes in the queue represent time, we disable bytes
       
   608    * overrun checking to not cause deadlocks.
       
   609    */
       
   610   if (bytes && time != 0 && time < min_time) {
       
   611     GST_DEBUG_OBJECT (play_base_bin,
       
   612         "possible deadlock found, removing byte limit");
       
   613 
       
   614     /* queue knows about time but is filled with bytes that do
       
   615      * not represent min-threshold time, disable bytes checking so
       
   616      * the queue can grow some more. */
       
   617     g_object_set (G_OBJECT (queue), "max-size-bytes", 0, NULL);
       
   618 
       
   619     /* bytes limit is removed, we cannot deadlock anymore */
       
   620     g_signal_handlers_disconnect_by_func (queue,
       
   621         (gpointer) queue_deadlock_check, play_base_bin);
       
   622   } else {
       
   623     GST_DEBUG_OBJECT (play_base_bin, "no deadlock");
       
   624   }
       
   625 }
       
   626 
       
   627 static void
       
   628 queue_remove_probe (GstElement * queue, GstPlayBaseBin * play_base_bin)
       
   629 {
       
   630   gpointer data;
       
   631   GstPad *sinkpad;
       
   632 
       
   633   data = g_object_get_data (G_OBJECT (queue), "probe");
       
   634   sinkpad = gst_element_get_pad (queue, "sink");
       
   635 
       
   636   if (data) {
       
   637     GST_DEBUG_OBJECT (play_base_bin,
       
   638         "Removing buffer probe from pad %s:%s (%p)",
       
   639         GST_DEBUG_PAD_NAME (sinkpad), sinkpad);
       
   640 
       
   641     g_object_set_data (G_OBJECT (queue), "probe", NULL);
       
   642     gst_pad_remove_buffer_probe (sinkpad, GPOINTER_TO_INT (data));
       
   643   } else {
       
   644     GST_DEBUG_OBJECT (play_base_bin,
       
   645         "No buffer probe to remove from %s:%s (%p)",
       
   646         GST_DEBUG_PAD_NAME (sinkpad), sinkpad);
       
   647   }
       
   648   gst_object_unref (sinkpad);
       
   649 }
       
   650 
       
   651 /* Used for time-based buffering in streaming mode and is called when a queue
       
   652  * emits the running signal. This means that the high watermark threshold is
       
   653  * reached and the buffering is completed. */
       
   654 static void
       
   655 queue_threshold_reached (GstElement * queue, GstPlayBaseBin * play_base_bin)
       
   656 {
       
   657   GstPlayBaseGroup *group;
       
   658   gpointer data;
       
   659   gint n;
       
   660 
       
   661   GST_DEBUG_OBJECT (play_base_bin, "running signal received from queue %s",
       
   662       GST_ELEMENT_NAME (queue));
       
   663 
       
   664   /* we disconnect the signal so that we don't get called for every buffer. */
       
   665   g_signal_handlers_disconnect_by_func (queue,
       
   666       (gpointer) queue_threshold_reached, play_base_bin);
       
   667 
       
   668   data = g_object_get_data (G_OBJECT (queue), "eos");
       
   669   if (data) {
       
   670     GST_DEBUG_OBJECT (play_base_bin, "disable min threshold time, we are EOS");
       
   671     g_object_set (queue, "min-threshold-time", (guint64) 0, NULL);
       
   672   } else {
       
   673     /* now place the limits at the low threshold. When we hit this limit, the
       
   674      * underrun signal will be called. The underrun signal is always connected. */
       
   675     GST_DEBUG_OBJECT (play_base_bin,
       
   676         "setting min threshold time to %" G_GUINT64_FORMAT,
       
   677         play_base_bin->queue_min_threshold);
       
   678     g_object_set (queue, "min-threshold-time",
       
   679         play_base_bin->queue_min_threshold, NULL);
       
   680   }
       
   681 
       
   682   GROUP_LOCK (play_base_bin);
       
   683   group = get_active_group (play_base_bin);
       
   684   if (!group) {
       
   685     GROUP_UNLOCK (play_base_bin);
       
   686     return;
       
   687   }
       
   688 
       
   689   /* we remove the probe now because we don't need it anymore to give progress
       
   690    * about the buffering. */
       
   691   for (n = 0; n < NUM_TYPES; n++) {
       
   692     GstElement *element = group->type[n].preroll;
       
   693 
       
   694     if (!element)
       
   695       continue;
       
   696 
       
   697     queue_remove_probe (element, play_base_bin);
       
   698   }
       
   699 
       
   700   GROUP_UNLOCK (play_base_bin);
       
   701 
       
   702   /* we post a 100% buffering message to notify the app that buffering is
       
   703    * completed and playback can start/continue */
       
   704   if (play_base_bin->is_stream)
       
   705     fill_buffer (play_base_bin, 100);
       
   706 }
       
   707 
       
   708 /* this signal will be fired when one of the queues with raw
       
   709  * data is filled. This means that the group building stage is over 
       
   710  * and playback of the new queued group should start. This is a rather unusual
       
   711  * situation because normally the group is commited when the "no_more_pads"
       
   712  * signal is fired.
       
   713  */
       
   714 static void
       
   715 queue_overrun (GstElement * queue, GstPlayBaseBin * play_base_bin)
       
   716 {
       
   717   GST_DEBUG_OBJECT (play_base_bin, "queue %s overrun",
       
   718       GST_ELEMENT_NAME (queue));
       
   719 
       
   720   preroll_remove_overrun (queue, play_base_bin);
       
   721 
       
   722   group_commit (play_base_bin, FALSE,
       
   723       GST_OBJECT_PARENT (GST_OBJECT_CAST (queue)) ==
       
   724       GST_OBJECT_CAST (play_base_bin->subtitle));
       
   725 
       
   726   /* notify end of buffering */
       
   727   queue_threshold_reached (queue, play_base_bin);
       
   728 }
       
   729 
       
   730 /* this signal is only added when in streaming mode to catch underruns
       
   731  */
       
   732 static void
       
   733 queue_out_of_data (GstElement * queue, GstPlayBaseBin * play_base_bin)
       
   734 {
       
   735   GST_DEBUG_OBJECT (play_base_bin, "underrun signal received from queue %s",
       
   736       GST_ELEMENT_NAME (queue));
       
   737 
       
   738   /* On underrun, we want to temoprarily pause playback, set a "min-size"
       
   739    * threshold and wait for the running signal and then play again.
       
   740    *
       
   741    * This signal could never be called because the queue max-size limits are set
       
   742    * too low. We take care of this possible deadlock in the the overrun signal
       
   743    * handler. */
       
   744   g_signal_connect (G_OBJECT (queue), "pushing",
       
   745       G_CALLBACK (queue_threshold_reached), play_base_bin);
       
   746   GST_DEBUG_OBJECT (play_base_bin,
       
   747       "setting min threshold time to %" G_GUINT64_FORMAT,
       
   748       (guint64) play_base_bin->queue_threshold);
       
   749   g_object_set (queue, "min-threshold-time",
       
   750       (guint64) play_base_bin->queue_threshold, NULL);
       
   751 
       
   752   /* re-connect probe, this will fire feedback about the percentage that we
       
   753    * buffered and is posted in the BUFFERING message. */
       
   754   if (!g_object_get_data (G_OBJECT (queue), "probe")) {
       
   755     GstPad *sinkpad;
       
   756     guint id;
       
   757 
       
   758     sinkpad = gst_element_get_pad (queue, "sink");
       
   759     id = gst_pad_add_buffer_probe (sinkpad, G_CALLBACK (check_queue), queue);
       
   760     g_object_set_data (G_OBJECT (queue), "probe", GINT_TO_POINTER (id));
       
   761     GST_DEBUG_OBJECT (play_base_bin,
       
   762         "Re-attaching buffering probe to pad %s:%s %p",
       
   763         GST_DEBUG_PAD_NAME (sinkpad), sinkpad);
       
   764     gst_object_unref (sinkpad);
       
   765 
       
   766     fill_buffer (play_base_bin, 0);
       
   767   }
       
   768 }
       
   769 
       
   770 /*
       
   771  * generate a preroll element which is simply a queue. While there
       
   772  * are still dynamic elements in the pipeline, we wait for one
       
   773  * of the queues to fill. The assumption is that all the dynamic
       
   774  * streams will be detected by that time.
       
   775  *
       
   776  * Callers must have the group-lock held when calling this.
       
   777  */
       
   778 static void
       
   779 gen_preroll_element (GstPlayBaseBin * play_base_bin,
       
   780     GstPlayBaseGroup * group, GstStreamType type, GstPad * pad,
       
   781     GstStreamInfo * info)
       
   782 {
       
   783   GstElement *selector, *preroll;
       
   784   gchar *name, *padname;
       
   785   const gchar *prename;
       
   786   guint overrun_sig;
       
   787   GstPad *preroll_pad;
       
   788   GstBin *target;
       
   789   GstState state;
       
   790 
       
   791   if (type == GST_STREAM_TYPE_VIDEO)
       
   792     prename = "video";
       
   793   else if (type == GST_STREAM_TYPE_TEXT)
       
   794     prename = "text";
       
   795   else if (type == GST_STREAM_TYPE_AUDIO)
       
   796     prename = "audio";
       
   797   else
       
   798     g_return_if_reached ();
       
   799 
       
   800   /* create stream selector */
       
   801   selector = g_object_new (GST_TYPE_STREAM_SELECTOR, NULL);
       
   802   padname = gst_pad_get_name (pad);
       
   803   name = g_strdup_printf ("selector_%s_%s", prename, padname);
       
   804   gst_object_set_name (GST_OBJECT_CAST (selector), name);
       
   805   g_free (name);
       
   806 
       
   807   /* create preroll queue */
       
   808   name = g_strdup_printf ("preroll_%s_%s", prename, padname);
       
   809   preroll = gst_element_factory_make ("queue", name);
       
   810   g_free (name);
       
   811   g_free (padname);
       
   812 
       
   813   /* for buffering of raw data we ideally want to buffer a
       
   814    * very small amount of buffers since the memory used by
       
   815    * this raw data can be enormously huge.
       
   816    *
       
   817    * We use an upper limit of typically a few seconds here but
       
   818    * cap in case no timestamps are set on the raw data (bad!).
       
   819    *
       
   820    * FIXME: we abuse this buffer to do network buffering since
       
   821    * we can then easily do time-based buffering. The better
       
   822    * solution would be to add a specific network queue right
       
   823    * after the source that measures the datarate and scales this
       
   824    * queue of encoded data instead.
       
   825    */
       
   826   g_object_set (G_OBJECT (preroll),
       
   827       "max-size-buffers", 0, "max-size-bytes",
       
   828       ((type == GST_STREAM_TYPE_VIDEO) ? 25 : 2) * 1024 * 1024,
       
   829       "max-size-time", play_base_bin->queue_size, NULL);
       
   830 
       
   831   /* the overrun signal is always attached and serves two purposes:
       
   832    *
       
   833    *  1) when we are building a group and the overrun is called, we commit the 
       
   834    *     group. The reason being that if we fill the entire queue without a
       
   835    *     normal group commit (with _no_more_pads()) we can assume the
       
   836    *     audio/video is completely wacked or the element just does not know when
       
   837    *     it is ready with all the pads (mpeg).
       
   838    *  2) When we are doing network buffering, we keep track of low/high
       
   839    *     watermarks in the queue. It is possible that we set the high watermark
       
   840    *     higher than the max-size limits to trigger an overrun. In this case we
       
   841    *     will never get a running signal but we can use the overrun signal to
       
   842    *     detect this deadlock and correct it.
       
   843    */
       
   844   overrun_sig = g_signal_connect (G_OBJECT (preroll), "overrun",
       
   845       G_CALLBACK (queue_overrun), play_base_bin);
       
   846 
       
   847   /* keep a ref to the signal id so that we can disconnect the signal callback
       
   848    * when we are done with the preroll */
       
   849   g_object_set_data (G_OBJECT (preroll), "overrun_signal_id",
       
   850       GINT_TO_POINTER (overrun_sig));
       
   851 
       
   852   if (play_base_bin->is_stream &&
       
   853       ((type == GST_STREAM_TYPE_VIDEO &&
       
   854               group->type[GST_STREAM_TYPE_AUDIO - 1].npads == 0) ||
       
   855           (type == GST_STREAM_TYPE_AUDIO &&
       
   856               group->type[GST_STREAM_TYPE_VIDEO - 1].npads == 0))) {
       
   857     GstPad *sinkpad;
       
   858     guint id;
       
   859 
       
   860     /* catch deadlocks when we are network buffering in time but the max-limit
       
   861      * in bytes is hit. */
       
   862     g_signal_connect (G_OBJECT (preroll), "overrun",
       
   863         G_CALLBACK (queue_deadlock_check), play_base_bin);
       
   864 
       
   865     /* attach pointer to playbasebin */
       
   866     g_object_set_data (G_OBJECT (preroll), "pbb", play_base_bin);
       
   867 
       
   868     /* give updates on queue size */
       
   869     sinkpad = gst_element_get_pad (preroll, "sink");
       
   870     id = gst_pad_add_buffer_probe (sinkpad, G_CALLBACK (check_queue), preroll);
       
   871     GST_DEBUG_OBJECT (play_base_bin, "Attaching probe to pad %s:%s (%p)",
       
   872         GST_DEBUG_PAD_NAME (sinkpad), sinkpad);
       
   873     gst_object_unref (sinkpad);
       
   874     g_object_set_data (G_OBJECT (preroll), "probe", GINT_TO_POINTER (id));
       
   875 
       
   876     /* catch eos and flush events so that we can ignore underruns */
       
   877     id = gst_pad_add_event_probe (sinkpad, G_CALLBACK (check_queue_event),
       
   878         preroll);
       
   879     g_object_set_data (G_OBJECT (preroll), "eos_probe", GINT_TO_POINTER (id));
       
   880 
       
   881     /* When we connect this queue, it will start running and immediatly
       
   882      * fire an underrun. */
       
   883     g_signal_connect (G_OBJECT (preroll), "underrun",
       
   884         G_CALLBACK (queue_out_of_data), play_base_bin);
       
   885     /* configure threshold and callbacks */
       
   886     queue_out_of_data (preroll, play_base_bin);
       
   887   }
       
   888 
       
   889   /* listen for EOS so we can switch groups when one ended. */
       
   890   preroll_pad = gst_element_get_pad (preroll, "src");
       
   891   gst_pad_add_event_probe (preroll_pad, G_CALLBACK (probe_triggered), info);
       
   892   gst_object_unref (preroll_pad);
       
   893 
       
   894   /* add to group list */
       
   895   group->type[type - 1].selector = selector;
       
   896   group->type[type - 1].preroll = preroll;
       
   897 
       
   898   /* figure out where the preroll element should go */
       
   899   if (type == GST_STREAM_TYPE_TEXT && play_base_bin->subtitle)
       
   900     target = GST_BIN_CAST (play_base_bin->subtitle);
       
   901   else
       
   902     target = GST_BIN_CAST (play_base_bin);
       
   903 
       
   904   group->type[type - 1].bin = target;
       
   905   gst_bin_add (target, selector);
       
   906   gst_bin_add (target, preroll);
       
   907 
       
   908   gst_element_link (selector, preroll);
       
   909 
       
   910   /* figure out target state and set */
       
   911   state = (GST_STATE (play_base_bin) == GST_STATE_PLAYING ?
       
   912       GST_STATE_PLAYING : GST_STATE_PAUSED);
       
   913 
       
   914   gst_element_set_state (selector, state);
       
   915   gst_element_set_state (preroll, state);
       
   916 }
       
   917 
       
   918 static void
       
   919 preroll_remove_overrun (GstElement * element, GstPlayBaseBin * play_base_bin)
       
   920 {
       
   921   guint overrun_sig;
       
   922   GObject *obj = G_OBJECT (element);
       
   923 
       
   924   overrun_sig = GPOINTER_TO_INT (g_object_get_data (obj, "overrun_signal_id"));
       
   925   if (overrun_sig) {
       
   926     GST_LOG_OBJECT (play_base_bin, "removing preroll signal %s",
       
   927         GST_ELEMENT_NAME (element));
       
   928     g_signal_handler_disconnect (obj, overrun_sig);
       
   929     /* We have disconnected this signal, remove the signal_id from the object
       
   930      * data */
       
   931     g_object_set_data (obj, "overrun_signal_id", NULL);
       
   932   }
       
   933 }
       
   934 
       
   935 static void
       
   936 remove_groups (GstPlayBaseBin * play_base_bin)
       
   937 {
       
   938   GROUP_LOCK (play_base_bin);
       
   939 
       
   940   /* first destroy the group we were building if any */
       
   941   if (play_base_bin->building_group) {
       
   942     group_destroy (play_base_bin->building_group);
       
   943     play_base_bin->building_group = NULL;
       
   944   }
       
   945 
       
   946   /* remove the queued groups */
       
   947   g_list_foreach (play_base_bin->queued_groups, (GFunc) group_destroy, NULL);
       
   948   g_list_free (play_base_bin->queued_groups);
       
   949   play_base_bin->queued_groups = NULL;
       
   950 
       
   951   /* clear subs */
       
   952   if (play_base_bin->subtitle) {
       
   953     gst_element_set_state (play_base_bin->subtitle, GST_STATE_NULL);
       
   954     gst_bin_remove (GST_BIN_CAST (play_base_bin), play_base_bin->subtitle);
       
   955     play_base_bin->subtitle = NULL;
       
   956   }
       
   957 
       
   958   GROUP_UNLOCK (play_base_bin);
       
   959 }
       
   960 
       
   961 /*
       
   962  * Add/remove a single stream to current building group.
       
   963  *
       
   964  * Must be called with group-lock held.
       
   965  */
       
   966 static void
       
   967 add_stream (GstPlayBaseGroup * group, GstStreamInfo * info)
       
   968 {
       
   969   GValue v = { 0, };
       
   970   GST_DEBUG ("add stream to group %p", group);
       
   971 
       
   972   /* keep ref to the group */
       
   973   g_object_set_data (G_OBJECT (info), "group", group);
       
   974 
       
   975   g_value_init (&v, G_TYPE_OBJECT);
       
   976   g_value_set_object (&v, info);
       
   977   g_value_array_append (group->streaminfo_value_array, &v);
       
   978   g_value_unset (&v);
       
   979   group->streaminfo = g_list_append (group->streaminfo, info);
       
   980   if (info->type > 0 && info->type <= NUM_TYPES) {
       
   981     group->type[info->type - 1].npads++;
       
   982   }
       
   983 }
       
   984 
       
   985 static gboolean
       
   986 string_arr_has_str (const gchar * values[], const gchar * value)
       
   987 {
       
   988   if (values && value) {
       
   989     while (*values != NULL) {
       
   990       if (strcmp (value, *values) == 0)
       
   991         return TRUE;
       
   992       ++values;
       
   993     }
       
   994   }
       
   995   return FALSE;
       
   996 }
       
   997 
       
   998 /* mime types we are not handling on purpose right now, don't post a
       
   999  * missing-plugin message for these */
       
  1000 static const gchar *blacklisted_mimes[] = {
       
  1001   "video/x-dvd-subpicture", NULL
       
  1002 };
       
  1003 
       
  1004 #define IS_BLACKLISTED_MIME(type) (string_arr_has_str(blacklisted_mimes,type))
       
  1005 
       
  1006 static void
       
  1007 gst_play_base_bin_handle_message_func (GstBin * bin, GstMessage * msg)
       
  1008 {
       
  1009   if (gst_is_missing_plugin_message (msg)) {
       
  1010     gchar *detail;
       
  1011     guint i;
       
  1012 
       
  1013     detail = gst_missing_plugin_message_get_installer_detail (msg);
       
  1014     for (i = 0; detail != NULL && blacklisted_mimes[i] != NULL; ++i) {
       
  1015       if (strstr (detail, "|decoder-") && strstr (detail, blacklisted_mimes[i])) {
       
  1016         GST_LOG_OBJECT (bin, "suppressing message %" GST_PTR_FORMAT, msg);
       
  1017         gst_message_unref (msg);
       
  1018         g_free (detail);
       
  1019         return;
       
  1020       }
       
  1021     }
       
  1022     g_free (detail);
       
  1023   }
       
  1024   GST_BIN_CLASS (parent_class)->handle_message (bin, msg);
       
  1025 }
       
  1026 
       
  1027 /*
       
  1028  * signal fired when an unknown stream is found. We create a new
       
  1029  * UNKNOWN streaminfo object.
       
  1030  */
       
  1031 static void
       
  1032 unknown_type (GstElement * element, GstPad * pad, GstCaps * caps,
       
  1033     GstPlayBaseBin * play_base_bin)
       
  1034 {
       
  1035   const gchar *type_name;
       
  1036   GstStreamInfo *info;
       
  1037   GstPlayBaseGroup *group;
       
  1038 
       
  1039   type_name = gst_structure_get_name (gst_caps_get_structure (caps, 0));
       
  1040   if (type_name && !IS_BLACKLISTED_MIME (type_name)) {
       
  1041     gchar *capsstr;
       
  1042 
       
  1043     capsstr = gst_caps_to_string (caps);
       
  1044     GST_DEBUG_OBJECT (play_base_bin, "don't know how to handle %s", capsstr);
       
  1045     /* FIXME, g_message() ? */
       
  1046     g_message ("don't know how to handle %s", capsstr);
       
  1047     g_free (capsstr);
       
  1048   } else {
       
  1049     /* don't spew stuff to the terminal or send message if it's blacklisted */
       
  1050     GST_DEBUG_OBJECT (play_base_bin, "media type %s not handled on purpose, "
       
  1051         "not posting a missing-plugin message on the bus", type_name);
       
  1052   }
       
  1053 
       
  1054   GROUP_LOCK (play_base_bin);
       
  1055 
       
  1056   group = get_building_group (play_base_bin);
       
  1057 
       
  1058   /* add the stream to the list */
       
  1059   info = gst_stream_info_new (GST_OBJECT_CAST (pad), GST_STREAM_TYPE_UNKNOWN,
       
  1060       NULL, caps);
       
  1061   info->origin = GST_OBJECT_CAST (pad);
       
  1062   add_stream (group, info);
       
  1063 
       
  1064   GROUP_UNLOCK (play_base_bin);
       
  1065 }
       
  1066 
       
  1067 /* add a streaminfo that indicates that the stream is handled by the
       
  1068  * given element. This usually means that a stream without actual data is
       
  1069  * produced but one that is sunken by an element. Examples of this are:
       
  1070  * cdaudio, a hardware decoder/sink, dvd meta bins etc...
       
  1071  */
       
  1072 static void
       
  1073 add_element_stream (GstElement * element, GstPlayBaseBin * play_base_bin)
       
  1074 {
       
  1075   GstStreamInfo *info;
       
  1076   GstPlayBaseGroup *group;
       
  1077 
       
  1078   GROUP_LOCK (play_base_bin);
       
  1079 
       
  1080   group = get_building_group (play_base_bin);
       
  1081 
       
  1082   /* add the stream to the list */
       
  1083   info =
       
  1084       gst_stream_info_new (GST_OBJECT_CAST (element), GST_STREAM_TYPE_ELEMENT,
       
  1085       NULL, NULL);
       
  1086   info->origin = GST_OBJECT_CAST (element);
       
  1087   add_stream (group, info);
       
  1088 
       
  1089   GROUP_UNLOCK (play_base_bin);
       
  1090 }
       
  1091 
       
  1092 /* when the decoder element signals that no more pads will be generated, we
       
  1093  * can commit the current group.
       
  1094  */
       
  1095 static void
       
  1096 no_more_pads_full (GstElement * element, gboolean subs,
       
  1097     GstPlayBaseBin * play_base_bin)
       
  1098 {
       
  1099   /* setup phase */
       
  1100   GST_DEBUG_OBJECT (element, "no more pads, %d pending",
       
  1101       play_base_bin->pending);
       
  1102 
       
  1103   /* nothing pending, we can exit */
       
  1104   if (play_base_bin->pending == 0)
       
  1105     return;
       
  1106 
       
  1107   /* the object has no pending no_more_pads */
       
  1108   if (!g_object_get_data (G_OBJECT (element), "pending"))
       
  1109     return;
       
  1110 
       
  1111   g_object_set_data (G_OBJECT (element), "pending", NULL);
       
  1112 
       
  1113   play_base_bin->pending--;
       
  1114 
       
  1115   GST_DEBUG_OBJECT (element, "remove pending, now %d pending",
       
  1116       play_base_bin->pending);
       
  1117 
       
  1118   if (play_base_bin->pending == 0) {
       
  1119     /* we can commit this group for playback now */
       
  1120     group_commit (play_base_bin, play_base_bin->is_stream, subs);
       
  1121   }
       
  1122 }
       
  1123 
       
  1124 static void
       
  1125 no_more_pads (GstElement * element, GstPlayBaseBin * play_base_bin)
       
  1126 {
       
  1127   no_more_pads_full (element, FALSE, play_base_bin);
       
  1128 }
       
  1129 
       
  1130 static void
       
  1131 sub_no_more_pads (GstElement * element, GstPlayBaseBin * play_base_bin)
       
  1132 {
       
  1133   no_more_pads_full (element, TRUE, play_base_bin);
       
  1134 }
       
  1135 
       
  1136 static void
       
  1137 source_no_more_pads (GstElement * element, GstPlayBaseBin * bin)
       
  1138 {
       
  1139   GST_DEBUG_OBJECT (bin, "No more pads in source element %s.",
       
  1140       GST_ELEMENT_NAME (element));
       
  1141 
       
  1142   g_signal_handler_disconnect (G_OBJECT (element), bin->src_np_sig_id);
       
  1143   bin->src_np_sig_id = 0;
       
  1144   g_signal_handler_disconnect (G_OBJECT (element), bin->src_nmp_sig_id);
       
  1145   bin->src_nmp_sig_id = 0;
       
  1146 
       
  1147   no_more_pads_full (element, FALSE, bin);
       
  1148 }
       
  1149 
       
  1150 static gboolean
       
  1151 probe_triggered (GstPad * pad, GstEvent * event, gpointer user_data)
       
  1152 {
       
  1153   GstPlayBaseGroup *group;
       
  1154   GstPlayBaseBin *play_base_bin;
       
  1155   GstStreamInfo *info;
       
  1156   gboolean res;
       
  1157   GstEventType type;
       
  1158 
       
  1159   type = GST_EVENT_TYPE (event);
       
  1160 
       
  1161   GST_LOG ("probe triggered, (%d) %s", type, gst_event_type_get_name (type));
       
  1162 
       
  1163   /* we only care about EOS */
       
  1164   if (type != GST_EVENT_EOS)
       
  1165     return TRUE;
       
  1166 
       
  1167   info = GST_STREAM_INFO (user_data);
       
  1168   group = (GstPlayBaseGroup *) g_object_get_data (G_OBJECT (info), "group");
       
  1169   play_base_bin = group->bin;
       
  1170 
       
  1171   if (type == GST_EVENT_EOS) {
       
  1172     gint num_groups = 0;
       
  1173     gboolean have_left;
       
  1174 
       
  1175     GST_DEBUG_OBJECT (play_base_bin, "probe got EOS in group %p", group);
       
  1176 
       
  1177     GROUP_LOCK (play_base_bin);
       
  1178 
       
  1179     /* mute this stream */
       
  1180     g_object_set (G_OBJECT (info), "mute", TRUE, NULL);
       
  1181     if (info->type > 0 && info->type <= NUM_TYPES)
       
  1182       group->type[info->type - 1].done = TRUE;
       
  1183 
       
  1184     /* see if we have some more groups left to play */
       
  1185     num_groups = g_list_length (play_base_bin->queued_groups);
       
  1186     if (play_base_bin->building_group)
       
  1187       num_groups++;
       
  1188     have_left = (num_groups > 1);
       
  1189 
       
  1190     /* see if the complete group is muted */
       
  1191     if (!group_is_muted (group)) {
       
  1192       /* group is not completely muted, we remove the EOS event
       
  1193        * and continue, eventually the other streams will be EOSed and
       
  1194        * we can switch out this group. */
       
  1195       GST_DEBUG ("group %p not completely muted", group);
       
  1196 
       
  1197       GROUP_UNLOCK (play_base_bin);
       
  1198 
       
  1199       /* remove the EOS if we have something left */
       
  1200       return !have_left;
       
  1201     }
       
  1202 
       
  1203     if (have_left) {
       
  1204       /* ok, get rid of the current group then */
       
  1205       //group_destroy (group);
       
  1206       /* removing the current group brings the next group
       
  1207        * active */
       
  1208       play_base_bin->queued_groups =
       
  1209           g_list_remove (play_base_bin->queued_groups, group);
       
  1210       /* and wait for the next one to be ready */
       
  1211       while (!play_base_bin->queued_groups) {
       
  1212         GROUP_WAIT (play_base_bin);
       
  1213       }
       
  1214       group = play_base_bin->queued_groups->data;
       
  1215 
       
  1216       /* now activate the next one */
       
  1217       setup_substreams (play_base_bin);
       
  1218       GST_DEBUG ("switching to next group %p - emitting signal", group);
       
  1219       /* and signal the new group */
       
  1220       res = GST_PLAY_BASE_BIN_GET_CLASS (play_base_bin)->
       
  1221           setup_output_pads (play_base_bin, group);
       
  1222 
       
  1223       GROUP_UNLOCK (play_base_bin);
       
  1224 
       
  1225       g_object_notify (G_OBJECT (play_base_bin), "stream-info");
       
  1226 
       
  1227       /* get rid of the EOS event */
       
  1228       return FALSE;
       
  1229     } else {
       
  1230       GROUP_UNLOCK (play_base_bin);
       
  1231       GST_LOG ("Last group done, EOS");
       
  1232     }
       
  1233   }
       
  1234 
       
  1235   return TRUE;
       
  1236 }
       
  1237 
       
  1238 /* This function will be called when the sinkpad of the preroll element
       
  1239  * is unlinked, we have to connect something to the sinkpad or else the
       
  1240  * state change will fail.. 
       
  1241  */
       
  1242 static void
       
  1243 preroll_unlinked (GstPad * pad, GstPad * peerpad,
       
  1244     GstPlayBaseBin * play_base_bin)
       
  1245 {
       
  1246   GstElement *fakesrc;
       
  1247   guint sig_id;
       
  1248   GstPad *srcpad;
       
  1249 
       
  1250   /* make a fakesrc that will just emit one EOS */
       
  1251   fakesrc = gst_element_factory_make ("fakesrc", NULL);
       
  1252   g_object_set (G_OBJECT (fakesrc), "num_buffers", 0, NULL);
       
  1253 
       
  1254   GST_DEBUG ("patching unlinked pad %s:%s", GST_DEBUG_PAD_NAME (pad));
       
  1255 
       
  1256   srcpad = gst_element_get_pad (fakesrc, "src");
       
  1257   gst_bin_add (GST_BIN_CAST (play_base_bin), fakesrc);
       
  1258   gst_pad_link (srcpad, pad);
       
  1259   gst_object_unref (srcpad);
       
  1260 
       
  1261   /* keep track of these patch elements */
       
  1262   g_object_set_data (G_OBJECT (pad), "fakesrc", fakesrc);
       
  1263 
       
  1264   /* now unlink the unlinked signal so that it is not called again when
       
  1265    * we destroy the queue */
       
  1266   sig_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (pad), "unlinked_id"));
       
  1267   if (sig_id != 0) {
       
  1268     g_signal_handler_disconnect (G_OBJECT (pad), sig_id);
       
  1269     g_object_set_data (G_OBJECT (pad), "unlinked_id", GINT_TO_POINTER (0));
       
  1270   }
       
  1271 }
       
  1272 
       
  1273 /* Mute stream on first data - for header-is-in-stream-stuff
       
  1274  * (vorbis, ogmtext). */
       
  1275 static gboolean
       
  1276 mute_stream (GstPad * pad, GstBuffer * buf, gpointer data)
       
  1277 {
       
  1278   GstStreamInfo *info = GST_STREAM_INFO (data);
       
  1279   guint id;
       
  1280 
       
  1281   GST_DEBUG ("mute stream triggered");
       
  1282 
       
  1283   g_object_set (G_OBJECT (info), "mute", TRUE, NULL);
       
  1284   id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (info), "mute_probe"));
       
  1285   g_object_set_data (G_OBJECT (info), "mute_probe", NULL);
       
  1286   if (id > 0)
       
  1287     gst_pad_remove_buffer_probe (GST_PAD_CAST (info->object), id);
       
  1288 
       
  1289   /* no data */
       
  1290   return FALSE;
       
  1291 }
       
  1292 
       
  1293 /* Eat data. */
       
  1294 static gboolean
       
  1295 silence_stream (GstPad * pad, GstMiniObject * data, gpointer user_data)
       
  1296 {
       
  1297   GST_DEBUG ("silence stream triggered");
       
  1298 
       
  1299   /* no data */
       
  1300   return FALSE;
       
  1301 }
       
  1302 
       
  1303 /* Called by the signal handlers when a decodebin (main or subtitle) has 
       
  1304  * found a new raw pad.  We create a preroll element if needed and the 
       
  1305  * appropriate streaminfo. Commits the group if there will be no more pads
       
  1306  * from decodebin */
       
  1307 static void
       
  1308 new_decoded_pad_full (GstElement * element, GstPad * pad, gboolean last,
       
  1309     GstPlayBaseBin * play_base_bin, gboolean is_subs)
       
  1310 {
       
  1311   GstStructure *structure;
       
  1312   const gchar *mimetype;
       
  1313   GstCaps *caps;
       
  1314   GstStreamInfo *info;
       
  1315   GstStreamType type = GST_STREAM_TYPE_UNKNOWN;
       
  1316   GstPad *sinkpad;
       
  1317   GstPlayBaseGroup *group;
       
  1318   guint sig;
       
  1319   GstObject *parent;
       
  1320   gboolean first_pad;
       
  1321 
       
  1322   GST_DEBUG ("play base: new decoded pad. Last: %d", last);
       
  1323 
       
  1324   /* first see if this pad has interesting caps */
       
  1325   caps = gst_pad_get_caps (pad);
       
  1326   if (caps == NULL || gst_caps_is_empty (caps) || gst_caps_is_any (caps))
       
  1327     goto no_type;
       
  1328 
       
  1329   /* get the mime type */
       
  1330   structure = gst_caps_get_structure (caps, 0);
       
  1331   mimetype = gst_structure_get_name (structure);
       
  1332 
       
  1333   GROUP_LOCK (play_base_bin);
       
  1334 
       
  1335   group = get_building_group (play_base_bin);
       
  1336 
       
  1337   group->nstreams++;
       
  1338 
       
  1339   parent = gst_object_get_parent (GST_OBJECT_CAST (element));
       
  1340   if (g_str_has_prefix (mimetype, "audio/") &&
       
  1341       parent != GST_OBJECT_CAST (play_base_bin->subtitle)) {
       
  1342     type = GST_STREAM_TYPE_AUDIO;
       
  1343   } else if (g_str_has_prefix (mimetype, "video/") &&
       
  1344       parent != GST_OBJECT_CAST (play_base_bin->subtitle)) {
       
  1345     type = GST_STREAM_TYPE_VIDEO;
       
  1346   } else if (g_str_has_prefix (mimetype, "text/")) {
       
  1347     type = GST_STREAM_TYPE_TEXT;
       
  1348   }
       
  1349   gst_object_unref (parent);
       
  1350 
       
  1351   info = gst_stream_info_new (GST_OBJECT_CAST (pad), type, NULL, caps);
       
  1352   gst_caps_unref (caps);
       
  1353 
       
  1354   if (type == GST_STREAM_TYPE_UNKNOWN) {
       
  1355     /* Unknown streams get added to the group, but the data
       
  1356      * just gets ignored */
       
  1357     add_stream (group, info);
       
  1358 
       
  1359     GROUP_UNLOCK (play_base_bin);
       
  1360 
       
  1361     /* signal the no more pads after adding the stream */
       
  1362     if (last)
       
  1363       no_more_pads_full (element, is_subs, play_base_bin);
       
  1364 
       
  1365     return;
       
  1366   }
       
  1367 
       
  1368   /* first pad of each type gets a selector + preroll queue */
       
  1369   first_pad = (group->type[type - 1].npads == 0);
       
  1370 
       
  1371   if (first_pad) {
       
  1372     GST_DEBUG ("play base: pad needs new preroll");
       
  1373     gen_preroll_element (play_base_bin, group, type, pad, info);
       
  1374   }
       
  1375 
       
  1376   /* add to stream selector */
       
  1377   sinkpad =
       
  1378       gst_element_get_request_pad (group->type[type - 1].selector, "sink%d");
       
  1379 
       
  1380   /* make sure we catch unlink signals */
       
  1381   sig = g_signal_connect (G_OBJECT (sinkpad), "unlinked",
       
  1382       G_CALLBACK (preroll_unlinked), play_base_bin);
       
  1383   /* keep a ref to the signal id so that we can disconnect the signal callback */
       
  1384   g_object_set_data (G_OBJECT (sinkpad), "unlinked_id", GINT_TO_POINTER (sig));
       
  1385   /* Store a pointer to the stream selector pad for this stream */
       
  1386   g_object_set_data (G_OBJECT (pad), "pb_sel_pad", sinkpad);
       
  1387 
       
  1388   gst_pad_link (pad, sinkpad);
       
  1389   gst_object_unref (sinkpad);
       
  1390 
       
  1391   /* select 1st for now - we'll select a preferred one after preroll */
       
  1392   if (!first_pad) {
       
  1393     guint id;
       
  1394 
       
  1395     GST_DEBUG ("Adding silence_stream data probe on type %d (npads %d)", type,
       
  1396         group->type[type - 1].npads);
       
  1397 
       
  1398     id = gst_pad_add_data_probe (GST_PAD_CAST (pad),
       
  1399         G_CALLBACK (silence_stream), info);
       
  1400     g_object_set_data (G_OBJECT (pad), "eat_probe", GINT_TO_POINTER (id));
       
  1401   }
       
  1402 
       
  1403   /* add the stream to the list */
       
  1404   add_stream (group, info);
       
  1405 
       
  1406   GROUP_UNLOCK (play_base_bin);
       
  1407 
       
  1408   /* signal the no more pads after adding the stream */
       
  1409   if (last)
       
  1410     no_more_pads_full (element, is_subs, play_base_bin);
       
  1411 
       
  1412   return;
       
  1413 
       
  1414   /* ERRORS */
       
  1415 no_type:
       
  1416   {
       
  1417     g_warning ("no type on pad %s:%s", GST_DEBUG_PAD_NAME (pad));
       
  1418     if (caps)
       
  1419       gst_caps_unref (caps);
       
  1420     return;
       
  1421   }
       
  1422 }
       
  1423 
       
  1424 static void
       
  1425 new_decoded_pad (GstElement * element, GstPad * pad, gboolean last,
       
  1426     GstPlayBaseBin * play_base_bin)
       
  1427 {
       
  1428   new_decoded_pad_full (element, pad, last, play_base_bin, FALSE);
       
  1429 }
       
  1430 
       
  1431 static void
       
  1432 subs_new_decoded_pad (GstElement * element, GstPad * pad, gboolean last,
       
  1433     GstPlayBaseBin * play_base_bin)
       
  1434 {
       
  1435   new_decoded_pad_full (element, pad, last, play_base_bin, TRUE);
       
  1436 }
       
  1437 
       
  1438 static void
       
  1439 set_encoding_element (GstElement * element, gchar * encoding)
       
  1440 {
       
  1441   GST_DEBUG_OBJECT (element, "setting encoding to %s", GST_STR_NULL (encoding));
       
  1442   g_object_set (G_OBJECT (element), "subtitle-encoding", encoding, NULL);
       
  1443 }
       
  1444 
       
  1445 
       
  1446 static void
       
  1447 decodebin_element_added_cb (GstBin * decodebin, GstElement * element,
       
  1448     gpointer data)
       
  1449 {
       
  1450   GstPlayBaseBin *play_base_bin = GST_PLAY_BASE_BIN (data);
       
  1451   gchar *encoding;
       
  1452 
       
  1453   if (!g_object_class_find_property (G_OBJECT_GET_CLASS (element),
       
  1454           "subtitle-encoding")) {
       
  1455     return;
       
  1456   }
       
  1457 
       
  1458   g_mutex_lock (play_base_bin->sub_lock);
       
  1459   play_base_bin->subtitle_elements =
       
  1460       g_slist_append (play_base_bin->subtitle_elements, element);
       
  1461   encoding = g_strdup (play_base_bin->subencoding);
       
  1462   g_mutex_unlock (play_base_bin->sub_lock);
       
  1463 
       
  1464   set_encoding_element (element, encoding);
       
  1465   g_free (encoding);
       
  1466 }
       
  1467 
       
  1468 static void
       
  1469 decodebin_element_removed_cb (GstBin * decodebin, GstElement * element,
       
  1470     gpointer data)
       
  1471 {
       
  1472   GstPlayBaseBin *play_base_bin = GST_PLAY_BASE_BIN (data);
       
  1473 
       
  1474   g_mutex_lock (play_base_bin->sub_lock);
       
  1475   play_base_bin->subtitle_elements =
       
  1476       g_slist_remove (play_base_bin->subtitle_elements, element);
       
  1477   g_mutex_unlock (play_base_bin->sub_lock);
       
  1478 }
       
  1479 
       
  1480 
       
  1481 /*
       
  1482  * Generate source ! subparse bins.
       
  1483  */
       
  1484 
       
  1485 static GstElement *
       
  1486 setup_subtitle (GstPlayBaseBin * play_base_bin, gchar * sub_uri)
       
  1487 {
       
  1488   GstElement *source, *subdecodebin, *subbin;
       
  1489 
       
  1490   if (!gst_uri_is_valid (sub_uri))
       
  1491     goto invalid_uri;
       
  1492 
       
  1493   source = gst_element_make_from_uri (GST_URI_SRC, sub_uri, NULL);
       
  1494   if (!source)
       
  1495     goto unknown_uri;
       
  1496 
       
  1497   if (g_getenv ("USE_DECODEBIN2"))
       
  1498     subdecodebin = gst_element_factory_make ("decodebin2", "subtitle-decoder");
       
  1499   else
       
  1500     subdecodebin = gst_element_factory_make ("decodebin", "subtitle-decoder");
       
  1501   g_signal_connect (subdecodebin, "element-added",
       
  1502       G_CALLBACK (decodebin_element_added_cb), play_base_bin);
       
  1503   g_signal_connect (subdecodebin, "element-removed",
       
  1504       G_CALLBACK (decodebin_element_removed_cb), play_base_bin);
       
  1505   subbin = gst_bin_new ("subtitle-bin");
       
  1506   gst_bin_add_many (GST_BIN_CAST (subbin), source, subdecodebin, NULL);
       
  1507 
       
  1508   gst_element_link (source, subdecodebin);
       
  1509 
       
  1510   /* return the subtitle GstElement object */
       
  1511   return subbin;
       
  1512 
       
  1513   /* WARNINGS */
       
  1514 invalid_uri:
       
  1515   {
       
  1516     GST_ELEMENT_WARNING (play_base_bin, RESOURCE, NOT_FOUND,
       
  1517         (_("Invalid subtitle URI \"%s\", subtitles disabled."), sub_uri),
       
  1518         (NULL));
       
  1519     return NULL;
       
  1520   }
       
  1521 unknown_uri:
       
  1522   {
       
  1523     gchar *prot = gst_uri_get_protocol (sub_uri);
       
  1524 
       
  1525     if (prot) {
       
  1526       gchar *desc;
       
  1527 
       
  1528       gst_element_post_message (GST_ELEMENT (play_base_bin),
       
  1529           gst_missing_uri_source_message_new (GST_ELEMENT (play_base_bin),
       
  1530               prot));
       
  1531 
       
  1532       desc = gst_pb_utils_get_source_description (prot);
       
  1533       GST_ELEMENT_ERROR (play_base_bin, CORE, MISSING_PLUGIN,
       
  1534           (_("A %s plugin is required to play this stream, but not installed."),
       
  1535               desc), ("No URI handler to handle sub_uri: %s", sub_uri));
       
  1536       g_free (desc);
       
  1537       g_free (prot);
       
  1538     } else
       
  1539       goto invalid_uri;
       
  1540 
       
  1541     return NULL;
       
  1542   }
       
  1543 }
       
  1544 
       
  1545 /* helper function to lookup stuff in lists */
       
  1546 static gboolean
       
  1547 array_has_value (const gchar * values[], const gchar * value)
       
  1548 {
       
  1549   gint i;
       
  1550 
       
  1551   for (i = 0; values[i]; i++) {
       
  1552     if (g_str_has_prefix (value, values[i]))
       
  1553       return TRUE;
       
  1554   }
       
  1555   return FALSE;
       
  1556 }
       
  1557 
       
  1558 /* list of URIs that we consider to be streams and that need buffering.
       
  1559  * We have no mechanism yet to figure this out with a query. */
       
  1560 static const gchar *stream_uris[] = { "http://", "mms://", "mmsh://",
       
  1561   "mmsu://", "mmst://", "myth://", NULL
       
  1562 };
       
  1563 
       
  1564 /* blacklisted URIs, we know they will always fail. */
       
  1565 static const gchar *blacklisted_uris[] = { NULL };
       
  1566 
       
  1567 /* mime types that we don't consider to be media types */
       
  1568 static const gchar *no_media_mimes[] = {
       
  1569   "application/x-executable", "application/x-bzip", "application/x-gzip",
       
  1570   "application/zip", "application/x-compress", NULL
       
  1571 };
       
  1572 
       
  1573 /* mime types we consider raw media */
       
  1574 static const gchar *raw_mimes[] = {
       
  1575   "audio/x-raw", "video/x-raw", NULL
       
  1576 };
       
  1577 
       
  1578 #define IS_STREAM_URI(uri)          (array_has_value (stream_uris, uri))
       
  1579 #define IS_BLACKLISTED_URI(uri)     (array_has_value (blacklisted_uris, uri))
       
  1580 #define IS_NO_MEDIA_MIME(mime)      (array_has_value (no_media_mimes, mime))
       
  1581 #define IS_RAW_MIME(mime)           (array_has_value (raw_mimes, mime))
       
  1582 
       
  1583 /*
       
  1584  * Generate and configure a source element.
       
  1585  */
       
  1586 static GstElement *
       
  1587 gen_source_element (GstPlayBaseBin * play_base_bin, GstElement ** subbin)
       
  1588 {
       
  1589   GstElement *source;
       
  1590 
       
  1591   if (!play_base_bin->uri)
       
  1592     goto no_uri;
       
  1593 
       
  1594   if (!gst_uri_is_valid (play_base_bin->uri))
       
  1595     goto invalid_uri;
       
  1596 
       
  1597   if (IS_BLACKLISTED_URI (play_base_bin->uri))
       
  1598     goto uri_blacklisted;
       
  1599 
       
  1600   if (play_base_bin->suburi) {
       
  1601     GST_LOG_OBJECT (play_base_bin, "Creating decoder for subtitles URI %s",
       
  1602         play_base_bin->suburi);
       
  1603     /* subtitle specified */
       
  1604     *subbin = setup_subtitle (play_base_bin, play_base_bin->suburi);
       
  1605   } else {
       
  1606     /* no subtitle specified */
       
  1607     *subbin = NULL;
       
  1608   }
       
  1609 
       
  1610   source = gst_element_make_from_uri (GST_URI_SRC, play_base_bin->uri,
       
  1611       "source");
       
  1612   if (!source)
       
  1613     goto no_source;
       
  1614 
       
  1615   play_base_bin->is_stream = IS_STREAM_URI (play_base_bin->uri);
       
  1616 
       
  1617   /* make HTTP sources send extra headers so we get icecast
       
  1618    * metadata in case the stream is an icecast stream */
       
  1619   if (!strncmp (play_base_bin->uri, "http://", 7) &&
       
  1620       g_object_class_find_property (G_OBJECT_GET_CLASS (source),
       
  1621           "iradio-mode")) {
       
  1622     g_object_set (source, "iradio-mode", TRUE, NULL);
       
  1623   }
       
  1624 
       
  1625   if (g_object_class_find_property (G_OBJECT_GET_CLASS (source),
       
  1626           "connection-speed")) {
       
  1627     GST_DEBUG_OBJECT (play_base_bin,
       
  1628         "setting connection-speed=%d to source element",
       
  1629         play_base_bin->connection_speed / 1000);
       
  1630     g_object_set (source, "connection-speed",
       
  1631         play_base_bin->connection_speed / 1000, NULL);
       
  1632   }
       
  1633 
       
  1634   return source;
       
  1635 
       
  1636   /* ERRORS */
       
  1637 no_uri:
       
  1638   {
       
  1639     GST_ELEMENT_ERROR (play_base_bin, RESOURCE, NOT_FOUND,
       
  1640         (_("No URI specified to play from.")), (NULL));
       
  1641     return NULL;
       
  1642   }
       
  1643 invalid_uri:
       
  1644   {
       
  1645     GST_ELEMENT_ERROR (play_base_bin, RESOURCE, NOT_FOUND,
       
  1646         (_("Invalid URI \"%s\"."), play_base_bin->uri), (NULL));
       
  1647     return NULL;
       
  1648   }
       
  1649 uri_blacklisted:
       
  1650   {
       
  1651     GST_ELEMENT_ERROR (play_base_bin, RESOURCE, FAILED,
       
  1652         (_("RTSP streams cannot be played yet.")), (NULL));
       
  1653     return NULL;
       
  1654   }
       
  1655 no_source:
       
  1656   {
       
  1657     gchar *prot = gst_uri_get_protocol (play_base_bin->uri);
       
  1658 
       
  1659     /* whoops, could not create the source element, dig a little deeper to
       
  1660      * figure out what might be wrong. */
       
  1661     if (prot) {
       
  1662       gchar *desc;
       
  1663 
       
  1664       gst_element_post_message (GST_ELEMENT (play_base_bin),
       
  1665           gst_missing_uri_source_message_new (GST_ELEMENT (play_base_bin),
       
  1666               prot));
       
  1667 
       
  1668       desc = gst_pb_utils_get_source_description (prot);
       
  1669       GST_ELEMENT_ERROR (play_base_bin, CORE, MISSING_PLUGIN,
       
  1670           (_("A %s plugin is required to play this stream, but not installed."),
       
  1671               desc), ("No URI handler for %s", prot));
       
  1672       g_free (desc);
       
  1673       g_free (prot);
       
  1674     } else
       
  1675       goto invalid_uri;
       
  1676 
       
  1677     return NULL;
       
  1678   }
       
  1679 }
       
  1680 
       
  1681 /* is called when a dynamic source element created a new pad. */
       
  1682 static void
       
  1683 source_new_pad (GstElement * element, GstPad * pad, GstPlayBaseBin * bin)
       
  1684 {
       
  1685   GstElement *decoder;
       
  1686   gboolean is_raw;
       
  1687 
       
  1688   GST_DEBUG_OBJECT (bin, "Found new pad %s.%s in source element %s",
       
  1689       GST_DEBUG_PAD_NAME (pad), GST_ELEMENT_NAME (element));
       
  1690 
       
  1691   /* if this is a pad with all raw caps, we can expose it */
       
  1692   if (has_all_raw_caps (pad, &is_raw) && is_raw) {
       
  1693     /* it's all raw, create output pads. */
       
  1694     new_decoded_pad_full (element, pad, FALSE, bin, FALSE);
       
  1695     return;
       
  1696   }
       
  1697 
       
  1698   /* not raw, create decoder */
       
  1699   decoder = make_decoder (bin);
       
  1700   if (!decoder)
       
  1701     goto no_decodebin;
       
  1702 
       
  1703   /* and link to decoder */
       
  1704   if (!gst_element_link (bin->source, decoder))
       
  1705     goto could_not_link;
       
  1706 
       
  1707   gst_element_set_state (decoder, GST_STATE_PAUSED);
       
  1708 
       
  1709   return;
       
  1710 
       
  1711   /* ERRORS */
       
  1712 no_decodebin:
       
  1713   {
       
  1714     /* error was posted */
       
  1715     return;
       
  1716   }
       
  1717 could_not_link:
       
  1718   {
       
  1719     GST_ELEMENT_ERROR (bin, CORE, NEGOTIATION,
       
  1720         (NULL), ("Can't link source to decoder element"));
       
  1721     return;
       
  1722   }
       
  1723 }
       
  1724 
       
  1725 /*
       
  1726  * Setup the substreams (is called right after group_commit () when
       
  1727  * loading a new group, or after switching groups).
       
  1728  *
       
  1729  * Should be called with group-lock held.
       
  1730  */
       
  1731 static void
       
  1732 setup_substreams (GstPlayBaseBin * play_base_bin)
       
  1733 {
       
  1734   GstPlayBaseGroup *group;
       
  1735   gint n;
       
  1736   const GList *item;
       
  1737 
       
  1738   GST_DEBUG_OBJECT (play_base_bin, "setting up substreams");
       
  1739 
       
  1740   /* Remove the eat probes */
       
  1741   group = get_active_group (play_base_bin);
       
  1742   for (item = group->streaminfo; item; item = item->next) {
       
  1743     GstStreamInfo *info = item->data;
       
  1744     gpointer data;
       
  1745 
       
  1746     data = g_object_get_data (G_OBJECT (info->object), "eat_probe");
       
  1747     if (data) {
       
  1748       gst_pad_remove_data_probe (GST_PAD_CAST (info->object),
       
  1749           GPOINTER_TO_INT (data));
       
  1750       g_object_set_data (G_OBJECT (info->object), "eat_probe", NULL);
       
  1751     }
       
  1752 
       
  1753     /* now remove unknown pads */
       
  1754     if (info->type == GST_STREAM_TYPE_UNKNOWN) {
       
  1755       guint id;
       
  1756 
       
  1757       id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (info), "mute_probe"));
       
  1758       if (id == 0) {
       
  1759         id = gst_pad_add_buffer_probe (GST_PAD_CAST (info->object),
       
  1760             G_CALLBACK (mute_stream), info);
       
  1761         g_object_set_data (G_OBJECT (info), "mute_probe", GINT_TO_POINTER (id));
       
  1762       }
       
  1763     }
       
  1764   }
       
  1765 
       
  1766   /* now check if the requested current streams exist. If
       
  1767    * current >= num_streams, decrease current so at least
       
  1768    * we have output. Always keep it enabled. */
       
  1769   for (n = 0; n < NUM_TYPES; n++) {
       
  1770     if (play_base_bin->current[n] >= group->type[n].npads) {
       
  1771       GST_DEBUG_OBJECT (play_base_bin, "reset type %d to current 0", n);
       
  1772       play_base_bin->current[n] = 0;
       
  1773     }
       
  1774   }
       
  1775 
       
  1776   /* now activate the right sources. Don't forget that during preroll,
       
  1777    * we set the first source to forwarding and ignored the rest. */
       
  1778   for (n = 0; n < NUM_TYPES; n++) {
       
  1779     GST_DEBUG_OBJECT (play_base_bin, "setting type %d to current %d", n,
       
  1780         play_base_bin->current[n]);
       
  1781     set_active_source (play_base_bin, n + 1, play_base_bin->current[n]);
       
  1782   }
       
  1783 }
       
  1784 
       
  1785 /**
       
  1786  * has_all_raw_caps:
       
  1787  * @pad: a #GstPad
       
  1788  * @all_raw: pointer to hold the result
       
  1789  *
       
  1790  * check if the caps of the pad are all raw. The caps are all raw if
       
  1791  * all of its structures contain audio/x-raw or video/x-raw.
       
  1792  *
       
  1793  * Returns: %FALSE @pad has no caps. Else TRUE and @all_raw set t the result.
       
  1794  */
       
  1795 static gboolean
       
  1796 has_all_raw_caps (GstPad * pad, gboolean * all_raw)
       
  1797 {
       
  1798   GstCaps *caps;
       
  1799   gint capssize;
       
  1800   guint i, num_raw = 0;
       
  1801   gboolean res = FALSE;
       
  1802 
       
  1803   caps = gst_pad_get_caps (pad);
       
  1804   if (caps == NULL)
       
  1805     return FALSE;
       
  1806 
       
  1807   capssize = gst_caps_get_size (caps);
       
  1808   /* no caps, skip and move to the next pad */
       
  1809   if (capssize == 0 || gst_caps_is_empty (caps) || gst_caps_is_any (caps))
       
  1810     goto done;
       
  1811 
       
  1812   /* count the number of raw formats in the caps */
       
  1813   for (i = 0; i < capssize; ++i) {
       
  1814     GstStructure *s;
       
  1815     const gchar *mime_type;
       
  1816 
       
  1817     s = gst_caps_get_structure (caps, i);
       
  1818     mime_type = gst_structure_get_name (s);
       
  1819 
       
  1820     if (IS_RAW_MIME (mime_type))
       
  1821       ++num_raw;
       
  1822   }
       
  1823 
       
  1824   *all_raw = (num_raw == capssize);
       
  1825   res = TRUE;
       
  1826 
       
  1827 done:
       
  1828   gst_caps_unref (caps);
       
  1829   return res;
       
  1830 }
       
  1831 
       
  1832 /**
       
  1833  * analyse_source:
       
  1834  * @play_base_bin: a #GstPlayBaseBin
       
  1835  * @is_raw: are all pads raw data
       
  1836  * @have_out: does the source have output
       
  1837  * @is_dynamic: is this a dynamic source
       
  1838  *
       
  1839  * Check the source of @play_base_bin and collect information about it.
       
  1840  *
       
  1841  * @is_raw will be set to TRUE if the source only produces raw pads. When this
       
  1842  * function returns, all of the raw pad of the source will be added
       
  1843  * to @play_base_bin.
       
  1844  *
       
  1845  * @have_out: will be set to TRUE if the source has output pads.
       
  1846  *
       
  1847  * @is_dynamic: TRUE if the element will create (more) pads dynamically later
       
  1848  * on.
       
  1849  *
       
  1850  * Returns: FALSE if a fatal error occured while scanning.
       
  1851  */
       
  1852 static gboolean
       
  1853 analyse_source (GstPlayBaseBin * play_base_bin, gboolean * is_raw,
       
  1854     gboolean * have_out, gboolean * is_dynamic)
       
  1855 {
       
  1856   GstIterator *pads_iter;
       
  1857   gboolean done = FALSE;
       
  1858   gboolean res = TRUE;
       
  1859 
       
  1860   *have_out = FALSE;
       
  1861   *is_raw = FALSE;
       
  1862   *is_dynamic = FALSE;
       
  1863 
       
  1864   pads_iter = gst_element_iterate_src_pads (play_base_bin->source);
       
  1865   while (!done) {
       
  1866     GstPad *pad = NULL;
       
  1867 
       
  1868     switch (gst_iterator_next (pads_iter, (gpointer) & pad)) {
       
  1869       case GST_ITERATOR_ERROR:
       
  1870         res = FALSE;
       
  1871         /* FALLTROUGH */
       
  1872       case GST_ITERATOR_DONE:
       
  1873         done = TRUE;
       
  1874         break;
       
  1875       case GST_ITERATOR_RESYNC:
       
  1876         /* reset results and resync */
       
  1877         *have_out = FALSE;
       
  1878         *is_raw = FALSE;
       
  1879         *is_dynamic = FALSE;
       
  1880         gst_iterator_resync (pads_iter);
       
  1881         break;
       
  1882       case GST_ITERATOR_OK:
       
  1883         /* we now officially have an ouput pad */
       
  1884         *have_out = TRUE;
       
  1885 
       
  1886         /* if FALSE, this pad has no caps and we continue with the next pad. */
       
  1887         if (!has_all_raw_caps (pad, is_raw)) {
       
  1888           gst_object_unref (pad);
       
  1889           break;
       
  1890         }
       
  1891 
       
  1892         /* caps on source pad are all raw, we can add the pad */
       
  1893         if (*is_raw) {
       
  1894           new_decoded_pad_full (play_base_bin->source, pad, FALSE,
       
  1895               play_base_bin, FALSE);
       
  1896         }
       
  1897 
       
  1898         gst_object_unref (pad);
       
  1899         break;
       
  1900     }
       
  1901   }
       
  1902   gst_iterator_free (pads_iter);
       
  1903 
       
  1904   if (!*have_out) {
       
  1905     GstElementClass *elemclass;
       
  1906     GList *walk;
       
  1907 
       
  1908     /* element has no output pads, check for padtemplates that list SOMETIMES
       
  1909      * pads. */
       
  1910     elemclass = GST_ELEMENT_GET_CLASS (play_base_bin->source);
       
  1911 
       
  1912     walk = gst_element_class_get_pad_template_list (elemclass);
       
  1913     while (walk != NULL) {
       
  1914       GstPadTemplate *templ;
       
  1915 
       
  1916       templ = (GstPadTemplate *) walk->data;
       
  1917       if (GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC) {
       
  1918         if (GST_PAD_TEMPLATE_PRESENCE (templ) == GST_PAD_SOMETIMES) {
       
  1919           *is_dynamic = TRUE;
       
  1920           break;                /* only break out if we found a sometimes src pad 
       
  1921                                    continue walking through if say a request src pad is found
       
  1922                                    elements such as mpegtsparse and dvbbasebin have request
       
  1923                                    and sometimes src pads */
       
  1924         }
       
  1925       }
       
  1926       walk = g_list_next (walk);
       
  1927     }
       
  1928   }
       
  1929 
       
  1930   return res;
       
  1931 }
       
  1932 
       
  1933 static void
       
  1934 remove_decoders (GstPlayBaseBin * bin)
       
  1935 {
       
  1936   GSList *walk;
       
  1937 
       
  1938   for (walk = bin->decoders; walk; walk = g_slist_next (walk)) {
       
  1939     GstElement *decoder = GST_ELEMENT_CAST (walk->data);
       
  1940 
       
  1941     GST_DEBUG_OBJECT (bin, "removing old decoder element");
       
  1942     gst_element_set_state (decoder, GST_STATE_NULL);
       
  1943     gst_bin_remove (GST_BIN_CAST (bin), decoder);
       
  1944   }
       
  1945   g_slist_free (bin->decoders);
       
  1946   bin->decoders = NULL;
       
  1947 }
       
  1948 
       
  1949 static GstElement *
       
  1950 make_decoder (GstPlayBaseBin * play_base_bin)
       
  1951 {
       
  1952   GstElement *decoder;
       
  1953 
       
  1954   /* now create the decoder element */
       
  1955   if (g_getenv ("USE_DECODEBIN2"))
       
  1956     decoder = gst_element_factory_make ("decodebin2", NULL);
       
  1957   else
       
  1958     decoder = gst_element_factory_make ("decodebin", NULL);
       
  1959   if (!decoder)
       
  1960     goto no_decodebin;
       
  1961 
       
  1962   g_signal_connect (decoder, "element-added",
       
  1963       G_CALLBACK (decodebin_element_added_cb), play_base_bin);
       
  1964   g_signal_connect (decoder, "element-removed",
       
  1965       G_CALLBACK (decodebin_element_removed_cb), play_base_bin);
       
  1966 
       
  1967   gst_bin_add (GST_BIN_CAST (play_base_bin), decoder);
       
  1968 
       
  1969   /* set up callbacks to create the links between decoded data
       
  1970    * and video/audio/subtitle rendering/output. */
       
  1971   g_signal_connect (G_OBJECT (decoder),
       
  1972       "new-decoded-pad", G_CALLBACK (new_decoded_pad), play_base_bin);
       
  1973   g_signal_connect (G_OBJECT (decoder), "no-more-pads",
       
  1974       G_CALLBACK (no_more_pads), play_base_bin);
       
  1975   g_signal_connect (G_OBJECT (decoder),
       
  1976       "unknown-type", G_CALLBACK (unknown_type), play_base_bin);
       
  1977   g_object_set_data (G_OBJECT (decoder), "pending", "1");
       
  1978   play_base_bin->pending++;
       
  1979 
       
  1980   GST_DEBUG_OBJECT (play_base_bin, "created decodebin, %d pending",
       
  1981       play_base_bin->pending);
       
  1982 
       
  1983   play_base_bin->decoders = g_slist_prepend (play_base_bin->decoders, decoder);
       
  1984 
       
  1985   return decoder;
       
  1986 
       
  1987   /* ERRORS */
       
  1988 no_decodebin:
       
  1989   {
       
  1990     GST_ELEMENT_ERROR (play_base_bin, CORE, MISSING_PLUGIN,
       
  1991         (_("Could not create \"decodebin\" element.")), (NULL));
       
  1992     return NULL;
       
  1993   }
       
  1994 }
       
  1995 
       
  1996 static void
       
  1997 remove_source (GstPlayBaseBin * bin)
       
  1998 {
       
  1999   GstElement *source = bin->source;
       
  2000 
       
  2001   if (source) {
       
  2002     GST_DEBUG_OBJECT (bin, "removing old src element");
       
  2003     gst_element_set_state (source, GST_STATE_NULL);
       
  2004 
       
  2005     if (bin->src_np_sig_id) {
       
  2006       g_signal_handler_disconnect (G_OBJECT (source), bin->src_np_sig_id);
       
  2007       bin->src_np_sig_id = 0;
       
  2008     }
       
  2009     if (bin->src_nmp_sig_id) {
       
  2010       g_signal_handler_disconnect (G_OBJECT (source), bin->src_nmp_sig_id);
       
  2011       bin->src_nmp_sig_id = 0;
       
  2012     }
       
  2013     gst_bin_remove (GST_BIN_CAST (bin), source);
       
  2014     bin->source = NULL;
       
  2015   }
       
  2016 }
       
  2017 
       
  2018 static GstBusSyncReply
       
  2019 subbin_startup_sync_msg (GstBus * bus, GstMessage * msg, gpointer user_data)
       
  2020 {
       
  2021   if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
       
  2022     GstPlayBaseBin *play_base_bin;
       
  2023 
       
  2024     play_base_bin = GST_PLAY_BASE_BIN (user_data);
       
  2025     if (!play_base_bin->subtitle_done) {
       
  2026       GST_WARNING_OBJECT (play_base_bin, "error starting up subtitle bin: %"
       
  2027           GST_PTR_FORMAT, msg);
       
  2028       play_base_bin->subtitle_done = TRUE;
       
  2029       GST_DEBUG_OBJECT (play_base_bin, "signal group done");
       
  2030       GROUP_SIGNAL (play_base_bin);
       
  2031       GST_DEBUG_OBJECT (play_base_bin, "signaled group done");
       
  2032     }
       
  2033   }
       
  2034   return GST_BUS_PASS;
       
  2035 }
       
  2036 
       
  2037 /* construct and run the source and decoder elements until we found
       
  2038  * all the streams or until a preroll queue has been filled.
       
  2039 */
       
  2040 static gboolean
       
  2041 setup_source (GstPlayBaseBin * play_base_bin)
       
  2042 {
       
  2043   GstElement *subbin = NULL;
       
  2044   gboolean is_raw, have_out, is_dynamic;
       
  2045 
       
  2046   if (!play_base_bin->need_rebuild)
       
  2047     return TRUE;
       
  2048 
       
  2049   GST_DEBUG_OBJECT (play_base_bin, "setup source");
       
  2050 
       
  2051   /* delete old src */
       
  2052   remove_source (play_base_bin);
       
  2053 
       
  2054   /* create and configure an element that can handle the uri */
       
  2055   if (!(play_base_bin->source = gen_source_element (play_base_bin, &subbin)))
       
  2056     goto no_source;
       
  2057 
       
  2058   /* state will be merged later - if file is not found, error will be
       
  2059    * handled by the application right after. */
       
  2060   gst_bin_add (GST_BIN_CAST (play_base_bin), play_base_bin->source);
       
  2061   g_object_notify (G_OBJECT (play_base_bin), "source");
       
  2062 
       
  2063   /* remove the old decoders now, if any */
       
  2064   remove_decoders (play_base_bin);
       
  2065 
       
  2066   /* remove our previous preroll queues */
       
  2067   remove_groups (play_base_bin);
       
  2068 
       
  2069   /* clear pending dynamic elements */
       
  2070   play_base_bin->pending = 0;
       
  2071 
       
  2072   /* do subs */
       
  2073   if (subbin) {
       
  2074     GstElement *db;
       
  2075     GstBus *bus;
       
  2076 
       
  2077     play_base_bin->subtitle = subbin;
       
  2078     db = gst_bin_get_by_name (GST_BIN_CAST (subbin), "subtitle-decoder");
       
  2079 
       
  2080     /* do type detection, without adding (so no preroll) */
       
  2081     g_signal_connect (G_OBJECT (db), "new-decoded-pad",
       
  2082         G_CALLBACK (subs_new_decoded_pad), play_base_bin);
       
  2083     g_signal_connect (G_OBJECT (db), "no-more-pads",
       
  2084         G_CALLBACK (sub_no_more_pads), play_base_bin);
       
  2085     g_signal_connect (G_OBJECT (db), "unknown-type",
       
  2086         G_CALLBACK (unknown_type), play_base_bin);
       
  2087     g_object_set_data (G_OBJECT (db), "pending", "1");
       
  2088     play_base_bin->pending++;
       
  2089 
       
  2090     GST_DEBUG_OBJECT (play_base_bin, "we have subtitles, %d pending",
       
  2091         play_base_bin->pending);
       
  2092 
       
  2093     if (!play_base_bin->is_stream) {
       
  2094       GstStateChangeReturn sret;
       
  2095 
       
  2096       /* either when the queues are filled or when the decoder element
       
  2097        * has no more dynamic streams, the cond is unlocked. We can remove
       
  2098        * the signal handlers then
       
  2099        */
       
  2100       GST_DEBUG_OBJECT (play_base_bin, "starting subtitle bin");
       
  2101 
       
  2102       /* for subtitles in a separate bin we will not commit the
       
  2103        * current building group since we need to add the other
       
  2104        * audio/video streams to the group. We check if we managed
       
  2105        * to commit the subtitle group using an extra flag. */
       
  2106       play_base_bin->subtitle_done = FALSE;
       
  2107 
       
  2108       /* since subbin is still a stand-alone bin, we need to add a custom bus
       
  2109        * to intercept error messages, so we can stop waiting and continue */
       
  2110       bus = gst_bus_new ();
       
  2111       gst_element_set_bus (subbin, bus);
       
  2112       gst_bus_set_sync_handler (bus, subbin_startup_sync_msg, play_base_bin);
       
  2113 
       
  2114       sret = gst_element_set_state (subbin, GST_STATE_PAUSED);
       
  2115       if (sret != GST_STATE_CHANGE_FAILURE) {
       
  2116         GROUP_LOCK (play_base_bin);
       
  2117         GST_DEBUG ("waiting for subtitle to complete...");
       
  2118         while (!play_base_bin->subtitle_done)
       
  2119           GROUP_WAIT (play_base_bin);
       
  2120         GST_DEBUG ("group done !");
       
  2121         GROUP_UNLOCK (play_base_bin);
       
  2122 
       
  2123         if (!play_base_bin->building_group ||
       
  2124             play_base_bin->building_group->type[GST_STREAM_TYPE_TEXT -
       
  2125                 1].npads == 0) {
       
  2126 
       
  2127           GST_DEBUG ("No subtitle found - ignoring");
       
  2128           gst_element_set_state (subbin, GST_STATE_NULL);
       
  2129           gst_object_unref (play_base_bin->subtitle);
       
  2130           play_base_bin->subtitle = NULL;
       
  2131         } else {
       
  2132           GST_DEBUG_OBJECT (play_base_bin, "Subtitle set-up successful");
       
  2133         }
       
  2134       } else {
       
  2135         GST_WARNING_OBJECT (play_base_bin, "Failed to start subtitle bin");
       
  2136         gst_element_set_state (subbin, GST_STATE_NULL);
       
  2137         gst_object_unref (play_base_bin->subtitle);
       
  2138         play_base_bin->subtitle = NULL;
       
  2139       }
       
  2140 
       
  2141       gst_bus_set_sync_handler (bus, NULL, NULL);
       
  2142       gst_element_set_bus (subbin, NULL);
       
  2143       gst_object_unref (bus);
       
  2144     }
       
  2145     gst_object_unref (db);
       
  2146   }
       
  2147   /* see if the source element emits raw audio/video all by itself,
       
  2148    * if so, we can create streams for the pads and be done with it.
       
  2149    * Also check that is has source pads, if not, we assume it will
       
  2150    * do everything itself.  */
       
  2151   if (!analyse_source (play_base_bin, &is_raw, &have_out, &is_dynamic))
       
  2152     goto invalid_source;
       
  2153 
       
  2154   if (is_raw) {
       
  2155     GST_DEBUG_OBJECT (play_base_bin, "Source provides all raw data");
       
  2156     /* source provides raw data, we added the pads and we can now signal a
       
  2157      * no_more pads because we are done. */
       
  2158     group_commit (play_base_bin, play_base_bin->is_stream, FALSE);
       
  2159     return TRUE;
       
  2160   }
       
  2161   if (!have_out && !is_dynamic) {
       
  2162     GST_DEBUG_OBJECT (play_base_bin, "Source has no output pads");
       
  2163     /* create a stream to indicate that this uri is handled by a self
       
  2164      * contained element. We are now done. */
       
  2165     add_element_stream (play_base_bin->source, play_base_bin);
       
  2166     group_commit (play_base_bin, play_base_bin->is_stream, FALSE);
       
  2167     return TRUE;
       
  2168   }
       
  2169   if (is_dynamic) {
       
  2170     /* connect a handler for the new-pad signal */
       
  2171     play_base_bin->src_np_sig_id =
       
  2172         g_signal_connect (G_OBJECT (play_base_bin->source), "pad-added",
       
  2173         G_CALLBACK (source_new_pad), play_base_bin);
       
  2174     play_base_bin->src_nmp_sig_id =
       
  2175         g_signal_connect (G_OBJECT (play_base_bin->source), "no-more-pads",
       
  2176         G_CALLBACK (source_no_more_pads), play_base_bin);
       
  2177     g_object_set_data (G_OBJECT (play_base_bin->source), "pending", "1");
       
  2178     play_base_bin->pending++;
       
  2179     GST_DEBUG_OBJECT (play_base_bin,
       
  2180         "Source has dynamic output pads, %d pending", play_base_bin->pending);
       
  2181   } else {
       
  2182     GstElement *decoder;
       
  2183 
       
  2184     /* no dynamic source, we can link now */
       
  2185     decoder = make_decoder (play_base_bin);
       
  2186     if (!decoder)
       
  2187       goto no_decodebin;
       
  2188 
       
  2189     if (!gst_element_link (play_base_bin->source, decoder))
       
  2190       goto could_not_link;
       
  2191   }
       
  2192 
       
  2193   if (play_base_bin->subtitle)
       
  2194     gst_bin_add (GST_BIN_CAST (play_base_bin), play_base_bin->subtitle);
       
  2195 
       
  2196   play_base_bin->need_rebuild = FALSE;
       
  2197 
       
  2198   return TRUE;
       
  2199 
       
  2200   /* ERRORS */
       
  2201 no_source:
       
  2202   {
       
  2203     /* error message was already posted */
       
  2204     return FALSE;
       
  2205   }
       
  2206 invalid_source:
       
  2207   {
       
  2208     GST_ELEMENT_ERROR (play_base_bin, CORE, FAILED,
       
  2209         (_("Source element is invalid.")), (NULL));
       
  2210     return FALSE;
       
  2211   }
       
  2212 no_decodebin:
       
  2213   {
       
  2214     /* message was posted */
       
  2215     return FALSE;
       
  2216   }
       
  2217 could_not_link:
       
  2218   {
       
  2219     GST_ELEMENT_ERROR (play_base_bin, CORE, NEGOTIATION,
       
  2220         (NULL), ("Can't link source to decoder element"));
       
  2221     return FALSE;
       
  2222   }
       
  2223 }
       
  2224 
       
  2225 static void
       
  2226 finish_source (GstPlayBaseBin * play_base_bin)
       
  2227 {
       
  2228   /* FIXME: no need to grab the group lock here? (tpm) */
       
  2229   if (get_active_group (play_base_bin) != NULL) {
       
  2230     if (play_base_bin->subtitle) {
       
  2231       /* make subs iterate from now on */
       
  2232       gst_bin_add (GST_BIN_CAST (play_base_bin), play_base_bin->subtitle);
       
  2233     }
       
  2234   }
       
  2235 }
       
  2236 
       
  2237 /*
       
  2238  * Caller must have group-lock held.
       
  2239  *
       
  2240  * We iterate over all detected streams in the streaminfo and try to find
       
  2241  * impossible cases, like subtitles without video.
       
  2242  */
       
  2243 static gboolean
       
  2244 prepare_output (GstPlayBaseBin * play_base_bin)
       
  2245 {
       
  2246   const GList *item;
       
  2247   gboolean stream_found = FALSE, no_media = FALSE;
       
  2248   gboolean got_video = FALSE, got_subtitle = FALSE;
       
  2249   GstPlayBaseGroup *group;
       
  2250 
       
  2251   group = get_active_group (play_base_bin);
       
  2252 
       
  2253   /* check if we found any supported stream... if not, then
       
  2254    * we detected stream type (or the above would've failed),
       
  2255    * but linking/decoding failed - plugin probably missing. */
       
  2256   for (item = group ? group->streaminfo : NULL; item != NULL; item = item->next) {
       
  2257     GstStreamInfo *info = GST_STREAM_INFO (item->data);
       
  2258 
       
  2259     if (info->type == GST_STREAM_TYPE_VIDEO) {
       
  2260       stream_found = TRUE;
       
  2261       got_video = TRUE;
       
  2262       break;
       
  2263     } else if (info->type == GST_STREAM_TYPE_ELEMENT) {
       
  2264       stream_found = TRUE;
       
  2265     } else if (info->type == GST_STREAM_TYPE_AUDIO) {
       
  2266       stream_found = TRUE;
       
  2267     } else if (info->type == GST_STREAM_TYPE_TEXT ||
       
  2268         info->type == GST_STREAM_TYPE_SUBPICTURE) {
       
  2269       got_subtitle = TRUE;
       
  2270     } else if (!item->prev && !item->next) {
       
  2271       /* We're no audio/video and the only stream... We could
       
  2272        * be something not-media that's detected because then our
       
  2273        * typefind doesn't mess up with mp3 (bz2, gz, elf, ...) */
       
  2274       if (info->caps && !gst_caps_is_empty (info->caps)) {
       
  2275         const gchar *mime =
       
  2276             gst_structure_get_name (gst_caps_get_structure (info->caps, 0));
       
  2277 
       
  2278         no_media = IS_NO_MEDIA_MIME (mime);
       
  2279       }
       
  2280     }
       
  2281   }
       
  2282 
       
  2283   if (!stream_found) {
       
  2284     if (got_subtitle) {
       
  2285       GST_ELEMENT_ERROR (play_base_bin, STREAM, WRONG_TYPE,
       
  2286           (_("Only a subtitle stream was detected. "
       
  2287                   "Either you are loading a subtitle file or some other type of "
       
  2288                   "text file, or the media file was not recognized.")), (NULL));
       
  2289     } else if (!no_media) {
       
  2290       GST_ELEMENT_ERROR (play_base_bin, STREAM, CODEC_NOT_FOUND,
       
  2291           (_("You do not have a decoder installed to handle this file. "
       
  2292                   "You might need to install the necessary plugins.")), (NULL));
       
  2293     } else {
       
  2294       GST_ELEMENT_ERROR (play_base_bin, STREAM, WRONG_TYPE,
       
  2295           (_("This is not a media file")), (NULL));
       
  2296     }
       
  2297     return FALSE;
       
  2298   } else if (got_subtitle && !got_video) {
       
  2299     GST_ELEMENT_ERROR (play_base_bin, STREAM, WRONG_TYPE,
       
  2300         (_("A subtitle stream was detected, but no video stream.")), (NULL));
       
  2301     return FALSE;
       
  2302   }
       
  2303 
       
  2304   return TRUE;
       
  2305 }
       
  2306 
       
  2307 /*
       
  2308  * Multi-stream management. -1 = none.
       
  2309  *
       
  2310  * Caller has group-lock held.
       
  2311  */
       
  2312 static gint
       
  2313 get_active_source (GstPlayBaseBin * play_base_bin, GstStreamType type)
       
  2314 {
       
  2315   GstPlayBaseGroup *group;
       
  2316   GList *s;
       
  2317   gint num = 0;
       
  2318 
       
  2319   group = get_active_group (play_base_bin);
       
  2320   if (!group)
       
  2321     return -1;
       
  2322 
       
  2323   for (s = group->streaminfo; s; s = s->next) {
       
  2324     GstStreamInfo *info = s->data;
       
  2325 
       
  2326     if (info->type == type) {
       
  2327       if (!info->mute && !g_object_get_data (G_OBJECT (info), "mute_probe")) {
       
  2328         return num;
       
  2329       } else {
       
  2330         num++;
       
  2331       }
       
  2332     }
       
  2333   }
       
  2334 
       
  2335   return -1;
       
  2336 }
       
  2337 
       
  2338 /* Kill pad reactivation on state change. */
       
  2339 
       
  2340 #if 0
       
  2341 static void muted_group_change_state (GstElement * element,
       
  2342     gint old_state, gint new_state, gpointer data);
       
  2343 #endif
       
  2344 
       
  2345 static void
       
  2346 mute_group_type (GstPlayBaseGroup * group, GstStreamType type, gboolean mute)
       
  2347 {
       
  2348   gboolean active = !mute;
       
  2349   GstPad *pad;
       
  2350 
       
  2351   pad = gst_element_get_pad (group->type[type - 1].preroll, "src");
       
  2352   gst_pad_set_active (pad, active);
       
  2353   gst_object_unref (pad);
       
  2354   pad = gst_element_get_pad (group->type[type - 1].preroll, "sink");
       
  2355   gst_pad_set_active (pad, active);
       
  2356   gst_object_unref (pad);
       
  2357   pad = gst_element_get_pad (group->type[type - 1].selector, "src");
       
  2358   gst_pad_set_active (pad, active);
       
  2359   gst_object_unref (pad);
       
  2360 
       
  2361 #if 0
       
  2362   if (mute) {
       
  2363     g_signal_connect (group->type[type - 1].preroll, "state-changed",
       
  2364         G_CALLBACK (muted_group_change_state), group);
       
  2365   } else {
       
  2366     g_signal_handlers_disconnect_by_func (group->type[type - 1].preroll,
       
  2367         G_CALLBACK (muted_group_change_state), group);
       
  2368   }
       
  2369 #endif
       
  2370 }
       
  2371 
       
  2372 #if 0
       
  2373 static void
       
  2374 muted_group_change_state (GstElement * element,
       
  2375     gint old_state, gint new_state, gpointer data)
       
  2376 {
       
  2377   GstPlayBaseGroup *group = data;
       
  2378 
       
  2379   GROUP_LOCK (group->bin);
       
  2380 
       
  2381   if (new_state == GST_STATE_PLAYING) {
       
  2382     gint n;
       
  2383 
       
  2384     for (n = 0; n < NUM_TYPES; n++) {
       
  2385       if (group->type[n].selector == element) {
       
  2386         mute_group_type (group, n + 1, TRUE);
       
  2387       }
       
  2388     }
       
  2389   }
       
  2390 
       
  2391   GROUP_UNLOCK (group->bin);
       
  2392 }
       
  2393 #endif
       
  2394 
       
  2395 static void
       
  2396 set_subtitles_visible (GstPlayBaseBin * play_base_bin, gboolean visible)
       
  2397 {
       
  2398   GstPlayBaseBinClass *klass = GST_PLAY_BASE_BIN_GET_CLASS (play_base_bin);
       
  2399 
       
  2400   /* we use a vfunc for this since we don't have a reference to the
       
  2401    * textoverlay element, but playbin does */
       
  2402   if (klass != NULL && klass->set_subtitles_visible != NULL)
       
  2403     klass->set_subtitles_visible (play_base_bin, visible);
       
  2404 }
       
  2405 
       
  2406 /*
       
  2407  * Caller has group-lock held.
       
  2408  */
       
  2409 
       
  2410 static void
       
  2411 set_active_source (GstPlayBaseBin * play_base_bin,
       
  2412     GstStreamType type, gint source_num)
       
  2413 {
       
  2414   GstPlayBaseGroup *group;
       
  2415   GList *s;
       
  2416   gint num = 0;
       
  2417   gboolean have_active = FALSE;
       
  2418   GstElement *sel;
       
  2419 
       
  2420   GST_LOG ("Changing active source of type %d to %d", type, source_num);
       
  2421   play_base_bin->current[type - 1] = source_num;
       
  2422 
       
  2423   group = get_active_group (play_base_bin);
       
  2424   if (!group || !group->type[type - 1].preroll) {
       
  2425     GST_LOG ("No active group, or group for type %d has no preroll", type);
       
  2426     return;
       
  2427   }
       
  2428 
       
  2429   /* HACK: instead of unlinking the subtitle input (= lots of hassle,
       
  2430    * especially if subtitles come from an external source), just tell
       
  2431    * textoverlay not to render them */
       
  2432   if (type == GST_STREAM_TYPE_TEXT) {
       
  2433     gboolean visible = (source_num != -1);
       
  2434 
       
  2435     set_subtitles_visible (play_base_bin, visible);
       
  2436     if (!visible)
       
  2437       return;
       
  2438   }
       
  2439 
       
  2440   sel = group->type[type - 1].selector;
       
  2441 
       
  2442   for (s = group->streaminfo; s; s = s->next) {
       
  2443     GstStreamInfo *info = s->data;
       
  2444 
       
  2445     if (info->type == type) {
       
  2446       if (num == source_num) {
       
  2447         GstPad *sel_pad;
       
  2448 
       
  2449         GST_LOG ("Unmuting (if already muted) source %d of type %d", source_num,
       
  2450             type);
       
  2451         g_object_set (info, "mute", FALSE, NULL);
       
  2452 
       
  2453         /* Tell the stream selector which pad to accept */
       
  2454         sel_pad = GST_PAD_CAST (g_object_get_data (G_OBJECT (info->object),
       
  2455                 "pb_sel_pad"));
       
  2456 
       
  2457         if (sel && sel_pad != NULL) {
       
  2458           g_object_set (G_OBJECT (sel), "active-pad", sel_pad, NULL);
       
  2459         }
       
  2460 
       
  2461         have_active = TRUE;
       
  2462       } else {
       
  2463         guint id;
       
  2464 
       
  2465         GST_LOG_OBJECT (info->object, "Muting source %d of type %d", num, type);
       
  2466 
       
  2467         id = gst_pad_add_buffer_probe (GST_PAD_CAST (info->object),
       
  2468             G_CALLBACK (mute_stream), info);
       
  2469         g_object_set_data (G_OBJECT (info), "mute_probe", GINT_TO_POINTER (id));
       
  2470       }
       
  2471       num++;
       
  2472     }
       
  2473   }
       
  2474 
       
  2475   if (!have_active) {
       
  2476     GST_LOG ("Muting group type: %d", type);
       
  2477     g_object_set (sel, "active-pad", NULL, NULL);
       
  2478   } else {
       
  2479     GST_LOG ("Unmuting group type: %d", type);
       
  2480   }
       
  2481   mute_group_type (group, type, !have_active);
       
  2482 }
       
  2483 
       
  2484 static void
       
  2485 gst_play_base_bin_set_property (GObject * object, guint prop_id,
       
  2486     const GValue * value, GParamSpec * pspec)
       
  2487 {
       
  2488   GstPlayBaseBin *play_base_bin;
       
  2489 
       
  2490   g_return_if_fail (GST_IS_PLAY_BASE_BIN (object));
       
  2491 
       
  2492   play_base_bin = GST_PLAY_BASE_BIN (object);
       
  2493 
       
  2494   switch (prop_id) {
       
  2495     case ARG_URI:
       
  2496     {
       
  2497       const gchar *uri = g_value_get_string (value);
       
  2498 
       
  2499       if (uri == NULL) {
       
  2500         g_warning ("cannot set NULL uri");
       
  2501         return;
       
  2502       }
       
  2503       /* if we have no previous uri, or the new uri is different from the
       
  2504        * old one, replug */
       
  2505       if (play_base_bin->uri == NULL || strcmp (play_base_bin->uri, uri) != 0) {
       
  2506         g_free (play_base_bin->uri);
       
  2507         play_base_bin->uri = g_strdup (uri);
       
  2508 
       
  2509         GST_DEBUG ("setting new uri to %s", uri);
       
  2510 
       
  2511         play_base_bin->need_rebuild = TRUE;
       
  2512       }
       
  2513       break;
       
  2514     }
       
  2515     case ARG_SUBURI:{
       
  2516       const gchar *suburi = g_value_get_string (value);
       
  2517 
       
  2518       if ((!suburi && !play_base_bin->suburi) ||
       
  2519           (suburi && play_base_bin->suburi &&
       
  2520               !strcmp (play_base_bin->suburi, suburi)))
       
  2521         return;
       
  2522       g_free (play_base_bin->suburi);
       
  2523       play_base_bin->suburi = g_strdup (suburi);
       
  2524       GST_DEBUG ("setting new .sub uri to %s", suburi);
       
  2525       play_base_bin->need_rebuild = TRUE;
       
  2526       break;
       
  2527     }
       
  2528     case ARG_QUEUE_SIZE:
       
  2529       play_base_bin->queue_size = g_value_get_uint64 (value);
       
  2530       break;
       
  2531     case ARG_QUEUE_THRESHOLD:
       
  2532       play_base_bin->queue_threshold = g_value_get_uint64 (value);
       
  2533       break;
       
  2534     case ARG_QUEUE_MIN_THRESHOLD:
       
  2535       play_base_bin->queue_min_threshold = g_value_get_uint64 (value);
       
  2536       break;
       
  2537     case ARG_CONNECTION_SPEED:
       
  2538       play_base_bin->connection_speed = g_value_get_uint (value) * 1000;
       
  2539       break;
       
  2540     case ARG_VIDEO:
       
  2541       GROUP_LOCK (play_base_bin);
       
  2542       set_active_source (play_base_bin,
       
  2543           GST_STREAM_TYPE_VIDEO, g_value_get_int (value));
       
  2544       GROUP_UNLOCK (play_base_bin);
       
  2545       break;
       
  2546     case ARG_AUDIO:
       
  2547       GROUP_LOCK (play_base_bin);
       
  2548       set_active_source (play_base_bin,
       
  2549           GST_STREAM_TYPE_AUDIO, g_value_get_int (value));
       
  2550       GROUP_UNLOCK (play_base_bin);
       
  2551       break;
       
  2552     case ARG_TEXT:
       
  2553       GROUP_LOCK (play_base_bin);
       
  2554       set_active_source (play_base_bin,
       
  2555           GST_STREAM_TYPE_TEXT, g_value_get_int (value));
       
  2556       GROUP_UNLOCK (play_base_bin);
       
  2557       break;
       
  2558     case ARG_SUBTITLE_ENCODING:
       
  2559     {
       
  2560       const gchar *encoding;
       
  2561       GSList *list;
       
  2562 
       
  2563       encoding = g_value_get_string (value);
       
  2564       if (encoding && play_base_bin->subencoding &&
       
  2565           !strcmp (play_base_bin->subencoding, encoding)) {
       
  2566         return;
       
  2567       }
       
  2568       if (encoding == NULL && play_base_bin->subencoding == NULL)
       
  2569         return;
       
  2570 
       
  2571       g_mutex_lock (play_base_bin->sub_lock);
       
  2572       g_free (play_base_bin->subencoding);
       
  2573       play_base_bin->subencoding = g_strdup (encoding);
       
  2574       list = g_slist_copy (play_base_bin->subtitle_elements);
       
  2575       g_slist_foreach (list, (GFunc) gst_object_ref, NULL);
       
  2576       g_mutex_unlock (play_base_bin->sub_lock);
       
  2577 
       
  2578       /* we can't hold a lock when calling g_object_set() on a child, since
       
  2579        * the notify event will trigger GstObject to send a deep-notify event
       
  2580        * which will try to take the lock ... */
       
  2581       g_slist_foreach (list, (GFunc) set_encoding_element, (gpointer) encoding);
       
  2582       g_slist_foreach (list, (GFunc) gst_object_unref, NULL);
       
  2583       g_slist_free (list);
       
  2584       break;
       
  2585     }
       
  2586     default:
       
  2587       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
  2588       break;
       
  2589   }
       
  2590 }
       
  2591 
       
  2592 static void
       
  2593 gst_play_base_bin_get_property (GObject * object, guint prop_id, GValue * value,
       
  2594     GParamSpec * pspec)
       
  2595 {
       
  2596   GstPlayBaseBin *play_base_bin;
       
  2597 
       
  2598   g_return_if_fail (GST_IS_PLAY_BASE_BIN (object));
       
  2599 
       
  2600   play_base_bin = GST_PLAY_BASE_BIN (object);
       
  2601 
       
  2602   switch (prop_id) {
       
  2603     case ARG_URI:
       
  2604       g_value_set_string (value, play_base_bin->uri);
       
  2605       break;
       
  2606     case ARG_SUBURI:
       
  2607       g_value_set_string (value, play_base_bin->suburi);
       
  2608       break;
       
  2609     case ARG_NSTREAMS:
       
  2610     {
       
  2611       GstPlayBaseGroup *group;
       
  2612 
       
  2613       GROUP_LOCK (play_base_bin);
       
  2614       group = get_active_group (play_base_bin);
       
  2615       if (group) {
       
  2616         g_value_set_int (value, group->nstreams);
       
  2617       } else {
       
  2618         g_value_set_int (value, 0);
       
  2619       }
       
  2620       GROUP_UNLOCK (play_base_bin);
       
  2621       break;
       
  2622     }
       
  2623     case ARG_QUEUE_SIZE:
       
  2624       g_value_set_uint64 (value, play_base_bin->queue_size);
       
  2625       break;
       
  2626     case ARG_QUEUE_THRESHOLD:
       
  2627       g_value_set_uint64 (value, play_base_bin->queue_threshold);
       
  2628       break;
       
  2629     case ARG_QUEUE_MIN_THRESHOLD:
       
  2630       g_value_set_uint64 (value, play_base_bin->queue_min_threshold);
       
  2631       break;
       
  2632     case ARG_CONNECTION_SPEED:
       
  2633       g_value_set_uint (value, play_base_bin->connection_speed / 1000);
       
  2634       break;
       
  2635     case ARG_STREAMINFO:
       
  2636       /* FIXME: hold some kind of lock here, use iterator */
       
  2637       g_value_set_pointer (value,
       
  2638           (gpointer) gst_play_base_bin_get_streaminfo (play_base_bin));
       
  2639       break;
       
  2640     case ARG_STREAMINFO_VALUES:{
       
  2641       GValueArray *copy;
       
  2642 
       
  2643       copy = gst_play_base_bin_get_streaminfo_value_array (play_base_bin);
       
  2644       g_value_take_boxed (value, copy);
       
  2645       break;
       
  2646     }
       
  2647     case ARG_SOURCE:
       
  2648       g_value_set_object (value, play_base_bin->source);
       
  2649       break;
       
  2650     case ARG_VIDEO:
       
  2651       GROUP_LOCK (play_base_bin);
       
  2652       g_value_set_int (value, get_active_source (play_base_bin,
       
  2653               GST_STREAM_TYPE_VIDEO));
       
  2654       GROUP_UNLOCK (play_base_bin);
       
  2655       break;
       
  2656     case ARG_AUDIO:
       
  2657       GROUP_LOCK (play_base_bin);
       
  2658       g_value_set_int (value, get_active_source (play_base_bin,
       
  2659               GST_STREAM_TYPE_AUDIO));
       
  2660       GROUP_UNLOCK (play_base_bin);
       
  2661       break;
       
  2662     case ARG_TEXT:
       
  2663       GROUP_LOCK (play_base_bin);
       
  2664       g_value_set_int (value, get_active_source (play_base_bin,
       
  2665               GST_STREAM_TYPE_TEXT));
       
  2666       GROUP_UNLOCK (play_base_bin);
       
  2667       break;
       
  2668     case ARG_SUBTITLE_ENCODING:
       
  2669       GST_OBJECT_LOCK (play_base_bin);
       
  2670       g_value_set_string (value, play_base_bin->subencoding);
       
  2671       GST_OBJECT_UNLOCK (play_base_bin);
       
  2672       break;
       
  2673     default:
       
  2674       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
  2675       break;
       
  2676   }
       
  2677 }
       
  2678 
       
  2679 static GstStateChangeReturn
       
  2680 gst_play_base_bin_change_state (GstElement * element, GstStateChange transition)
       
  2681 {
       
  2682   GstStateChangeReturn ret;
       
  2683   GstPlayBaseBin *play_base_bin;
       
  2684 
       
  2685   play_base_bin = GST_PLAY_BASE_BIN (element);
       
  2686 
       
  2687   switch (transition) {
       
  2688     case GST_STATE_CHANGE_READY_TO_PAUSED:
       
  2689       if (!setup_source (play_base_bin))
       
  2690         goto source_failed;
       
  2691       break;
       
  2692     default:
       
  2693       break;
       
  2694   }
       
  2695 
       
  2696   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
       
  2697 
       
  2698   switch (transition) {
       
  2699     case GST_STATE_CHANGE_READY_TO_PAUSED:
       
  2700       if (ret == GST_STATE_CHANGE_FAILURE)
       
  2701         goto cleanup_groups;
       
  2702 
       
  2703       finish_source (play_base_bin);
       
  2704       break;
       
  2705       /* clean-up in both cases, READY=>NULL clean-up is if there was an error */
       
  2706     case GST_STATE_CHANGE_PAUSED_TO_READY:
       
  2707     case GST_STATE_CHANGE_READY_TO_NULL:
       
  2708       play_base_bin->need_rebuild = TRUE;
       
  2709       remove_decoders (play_base_bin);
       
  2710       remove_groups (play_base_bin);
       
  2711       remove_source (play_base_bin);
       
  2712       break;
       
  2713     default:
       
  2714       break;
       
  2715   }
       
  2716   return ret;
       
  2717 
       
  2718   /* ERRORS */
       
  2719 source_failed:
       
  2720   {
       
  2721     play_base_bin->need_rebuild = TRUE;
       
  2722 
       
  2723     return GST_STATE_CHANGE_FAILURE;
       
  2724   }
       
  2725 cleanup_groups:
       
  2726   {
       
  2727     /* clean up leftover groups */
       
  2728     remove_groups (play_base_bin);
       
  2729     play_base_bin->need_rebuild = TRUE;
       
  2730 
       
  2731     return GST_STATE_CHANGE_FAILURE;
       
  2732   }
       
  2733 }
       
  2734 
       
  2735 static const GList *
       
  2736 gst_play_base_bin_get_streaminfo (GstPlayBaseBin * play_base_bin)
       
  2737 {
       
  2738   GstPlayBaseGroup *group = get_active_group (play_base_bin);
       
  2739   GList *info = NULL;
       
  2740 
       
  2741   if (group) {
       
  2742     info = group->streaminfo;
       
  2743   }
       
  2744   return info;
       
  2745 }
       
  2746 
       
  2747 static GValueArray *
       
  2748 gst_play_base_bin_get_streaminfo_value_array (GstPlayBaseBin * play_base_bin)
       
  2749 {
       
  2750   GstPlayBaseGroup *group;
       
  2751   GValueArray *array = NULL;
       
  2752 
       
  2753   GROUP_LOCK (play_base_bin);
       
  2754   group = get_active_group (play_base_bin);
       
  2755   if (group) {
       
  2756     array = g_value_array_copy (group->streaminfo_value_array);
       
  2757   } else {
       
  2758     array = g_value_array_new (0);
       
  2759   }
       
  2760   GROUP_UNLOCK (play_base_bin);
       
  2761 
       
  2762   return array;
       
  2763 }