gst-gmyth/playbinmaemo/gstplaybinmaemo.c
author renatofilho
Thu Aug 02 14:49:26 2007 +0100 (2007-08-02)
branchtrunk
changeset 791 cdafc5e948b8
parent 787 e42706ada231
child 792 a6ac25bf88a7
permissions -rw-r--r--
[svn r797] create debian scripts to playbinmaemo package
     1 /* GStreamer
     2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
     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 <glib/gi18n.h>
    25 #include <string.h>
    26 #include <gst/gst.h>
    27 #include <gst/gsterror.h>
    28 #include <gst/gstplugin.h>
    29 #include <gst/interfaces/xoverlay.h>
    30 #include <X11/Xlib.h>
    31 //#include <gst/pbutils/pbutils.h>
    32 #include "gstplaybinmaemo.h"
    33 
    34 
    35 GST_DEBUG_CATEGORY_STATIC (gst_play_bin_maemo_debug);
    36 #define GST_CAT_DEFAULT gst_play_bin_maemo_debug
    37 
    38 #define DEFAULT_VOLUME               10
    39 #define DEFAULT_XID                 -1
    40 
    41 /* props */
    42 enum
    43 {
    44   ARG_0,
    45   ARG_URI,
    46   ARG_QUEUE_SIZE,
    47   ARG_QUEUE_MIN_THRESHOLD,
    48   ARG_SOURCE,
    49   ARG_VOLUME,
    50   ARG_PARSE_METADATA,
    51   ARG_XID
    52 };
    53 
    54 static const GstElementDetails gst_play_bin_maemo_details =
    55         GST_ELEMENT_DETAILS("Nuv demuxer",
    56                             "Generic/Bin/Player",
    57                             "Autoplug and play media from an uri used on maemo plataform",
    58                             "Renato Araujo Oliveira Filho <renato.filho@indt.org.br>");
    59 
    60 static void     gst_play_bin_maemo_dispose          (GObject * object);
    61 static void     gst_play_bin_maemo_finalize         (GObject * object);
    62 static void     gst_play_bin_maemo_set_property     (GObject * object, guint prop_id,
    63                                                     const GValue * value, GParamSpec * spec);
    64 static void     gst_play_bin_maemo_get_property     (GObject * object, guint prop_id,
    65                                                     GValue * value, GParamSpec * spec);
    66 static GstStateChangeReturn
    67                 gst_play_bin_maemo_change_state     (GstElement *element,
    68                                                     GstStateChange transition);
    69 static gboolean factory_filter_sinks                (GstPluginFeature *feature,
    70                                                     GstPlayBinMaemo *pbm);
    71 static gint     compare_ranks                       (GstPluginFeature * f1,
    72                                                     GstPluginFeature * f2);
    73 static GList    *find_compatibles                   (GstPlayBinMaemo *pbm,
    74                                                      const GstCaps *caps);
    75 static GstPad   *find_sink_pad                      (GstElement * element);
    76 static void     update_volume                       (GstPlayBinMaemo *pbm);
    77 static void     update_xid                          (GstPlayBinMaemo *pbm);
    78 static void     new_decoded_pad_cb                  (GstElement *object,
    79                                                      GstPad* pad,
    80                                                      gboolean arg,
    81                                                      gpointer user_data);
    82 static void     unknown_type_cb                     (GstElement *object,
    83                                                      GstPad *pad,
    84                                                      GstCaps *casp,
    85                                                      gpointer user_data);
    86 static gboolean autoplug_continue_cb                (GstElement* object,
    87                                                      GstCaps* caps,
    88                                                      gpointer user_data);
    89 static void     decode_new_pad_cb                   (GstElement *element,
    90                                                      GObject    *new_pad,
    91                                                      gpointer   user_data);
    92 static void     queue_underrun_cb                   (GstElement* queue,
    93                                                      gpointer user_data);
    94 static void     queue_sink_underrun_cb              (GstElement* queue,
    95                                                      gpointer user_data);
    96 static void     queue_sink_overrun_cb               (GstElement* queue,
    97                                                      gpointer user_data);
    98 
    99 
   100 
   101 
   102 
   103 GST_BOILERPLATE(GstPlayBinMaemo, gst_play_bin_maemo, GstPipeline, GST_TYPE_PIPELINE)
   104 
   105 
   106 static void
   107 gst_play_bin_maemo_base_init (gpointer klass)
   108 {
   109     GstElementClass *element_class = GST_ELEMENT_CLASS(klass);
   110 
   111     gst_element_class_set_details (element_class, &gst_play_bin_maemo_details);
   112 }
   113 
   114 static void
   115 gst_play_bin_maemo_class_init (GstPlayBinMaemoClass * klass)
   116 {
   117   GObjectClass *gobject_klass;
   118   GstElementClass *gstelement_klass;
   119   GstBinClass *gstbin_klass;
   120 
   121   gobject_klass = (GObjectClass *) klass;
   122   gstelement_klass = (GstElementClass *) klass;
   123   gstbin_klass = (GstBinClass *) klass;
   124 
   125   parent_class = g_type_class_peek_parent (klass);
   126 
   127   gobject_klass->set_property = gst_play_bin_maemo_set_property;
   128   gobject_klass->get_property = gst_play_bin_maemo_get_property;
   129 
   130   g_object_class_install_property (gobject_klass, ARG_URI,
   131       g_param_spec_string ("uri", "URI", "URI of the media to play",
   132           NULL, G_PARAM_READWRITE));
   133 
   134   g_object_class_install_property (gobject_klass, ARG_VOLUME,
   135       g_param_spec_uint ("volume", "Audio volume", "volume",
   136                          0, 10, (guint) DEFAULT_VOLUME, G_PARAM_READWRITE));
   137 
   138   g_object_class_install_property (gobject_klass, ARG_XID,
   139       g_param_spec_long ("xid", "xid", "X windown ID",
   140                          -1, G_MAXLONG, DEFAULT_XID, G_PARAM_READWRITE));
   141 
   142   g_object_class_install_property (gobject_klass, ARG_SOURCE,
   143       g_param_spec_object ("source", "Source", "Source element",
   144           GST_TYPE_ELEMENT, G_PARAM_READABLE));
   145 
   146   g_object_class_install_property (gobject_klass, ARG_PARSE_METADATA,
   147       g_param_spec_boolean ("parse-metadata", "Parse Metadata", "Parse metadata info",
   148           TRUE, G_PARAM_READWRITE));
   149 
   150 
   151   GST_DEBUG_CATEGORY_INIT (gst_play_bin_maemo_debug, "playbinmaemo", 0,
   152       "playbinmaemo");
   153 
   154   gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_play_bin_maemo_dispose);
   155   gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_play_bin_maemo_finalize);
   156 
   157   gstelement_klass->change_state =
   158       GST_DEBUG_FUNCPTR (gst_play_bin_maemo_change_state);
   159 }
   160 
   161 static void
   162 gst_play_bin_maemo_init (GstPlayBinMaemo * play_bin_maemo, GstPlayBinMaemoClass *class)
   163 {
   164   GList *factories;
   165 
   166   play_bin_maemo->uri = NULL;
   167   play_bin_maemo->source = NULL;
   168 
   169   play_bin_maemo->volume = DEFAULT_VOLUME * 65535 / 10;
   170   play_bin_maemo->xid = DEFAULT_XID;
   171   play_bin_maemo->parse_metadata = TRUE;
   172 
   173   factories = gst_default_registry_feature_filter ((GstPluginFeatureFilter) factory_filter_sinks,
   174                                                    FALSE, play_bin_maemo);
   175 
   176   play_bin_maemo->factories = g_list_sort (factories, (GCompareFunc) compare_ranks);
   177 }
   178 
   179 static void
   180 gst_play_bin_maemo_dispose (GObject * object)
   181 {
   182   GstPlayBinMaemo *play_bin_maemo;
   183 
   184   play_bin_maemo = GST_PLAY_BIN_MAEMO (object);
   185   g_free (play_bin_maemo->uri);
   186   play_bin_maemo->uri = NULL;
   187 
   188   G_OBJECT_CLASS (parent_class)->dispose (object);
   189 }
   190 
   191 static void
   192 gst_play_bin_maemo_finalize (GObject * object)
   193 {
   194   G_OBJECT_CLASS (parent_class)->finalize (object);
   195 }
   196 
   197 static gboolean
   198 array_has_value (const gchar * values[], const gchar * value)
   199 {
   200   gint i;
   201 
   202   for (i = 0; values[i]; i++) {
   203     if (g_str_has_prefix (value, values[i]))
   204       return TRUE;
   205   }
   206   return FALSE;
   207 }
   208 
   209 /* list of URIs that we consider to be streams and that need buffering.
   210  * We have no mechanism yet to figure this out with a query. */
   211 static const gchar *stream_uris[] = { "http://", "mms://", "mmsh://",
   212   "mmsu://", "mmst://", NULL
   213 };
   214 
   215 /* blacklisted URIs, we know they will always fail. */
   216 static const gchar *blacklisted_uris[] = { NULL };
   217 
   218 /* mime types that we don't consider to be media types */
   219 static const gchar *no_media_mimes[] = {
   220   "application/x-executable", "application/x-bzip", "application/x-gzip",
   221   "application/zip", "application/x-compress", NULL
   222 };
   223 
   224 /* mime types we consider raw media */
   225 static const gchar *raw_mimes[] = {
   226   "audio/x-raw", "video/x-raw", NULL
   227 };
   228 
   229 #define IS_STREAM_URI(uri)          (array_has_value (stream_uris, uri))
   230 #define IS_BLACKLISTED_URI(uri)     (array_has_value (blacklisted_uris, uri))
   231 #define IS_NO_MEDIA_MIME(mime)      (array_has_value (no_media_mimes, mime))
   232 #define IS_RAW_MIME(mime)           (array_has_value (raw_mimes, mime))
   233 
   234 /*
   235  * Generate and configure a source element.
   236  */
   237 static GstElement *
   238 gen_source_element (GstPlayBinMaemo * play_bin_maemo)
   239 {
   240   GstElement *source;
   241 
   242   if (!play_bin_maemo->uri)
   243     goto no_uri;
   244 
   245   if (!gst_uri_is_valid (play_bin_maemo->uri))
   246     goto invalid_uri;
   247 
   248   if (IS_BLACKLISTED_URI (play_bin_maemo->uri))
   249     goto uri_blacklisted;
   250 
   251   source = gst_element_make_from_uri (GST_URI_SRC, play_bin_maemo->uri,
   252       "source");
   253   if (!source)
   254     goto no_source;
   255 
   256   play_bin_maemo->is_stream = IS_STREAM_URI (play_bin_maemo->uri);
   257 
   258   /* make HTTP sources send extra headers so we get icecast
   259    * metadata in case the stream is an icecast stream */
   260   if (!strncmp (play_bin_maemo->uri, "http://", 7) &&
   261       g_object_class_find_property (G_OBJECT_GET_CLASS (source),
   262           "iradio-mode")) {
   263     g_object_set (source, "iradio-mode", TRUE, NULL);
   264   }
   265   return source;
   266 
   267   /* ERRORS */
   268 no_uri:
   269   {
   270     GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, NOT_FOUND,
   271         (_("No URI specified to play from.")), (NULL));
   272     return NULL;
   273   }
   274 invalid_uri:
   275   {
   276     GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, NOT_FOUND,
   277         (_("Invalid URI \"%s\"."), play_bin_maemo->uri), (NULL));
   278     return NULL;
   279   }
   280 uri_blacklisted:
   281   {
   282     GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, FAILED,
   283         (_("RTSP streams cannot be played yet.")), (NULL));
   284     return NULL;
   285   }
   286 no_source:
   287   {
   288     gchar *prot = gst_uri_get_protocol (play_bin_maemo->uri);
   289 
   290     /* whoops, could not create the source element, dig a little deeper to
   291      * figure out what might be wrong. */
   292     if (prot) {
   293       gchar *desc;
   294 
   295       /*
   296       gst_element_post_message (GST_ELEMENT (play_bin_maemo),
   297           gst_missing_uri_source_message_new (GST_ELEMENT (play_bin_maemo),
   298               prot));
   299 
   300       desc = gst_pb_utils_get_source_description (prot);
   301       GST_ELEMENT_ERROR (play_bin_maemo, CORE, MISSING_PLUGIN,
   302           (_("A %s plugin is required to play this stream, but not installed."),
   303               desc), ("No URI handler for %s", prot));
   304               */
   305       g_free (desc);
   306       g_free (prot);
   307     } else
   308       goto invalid_uri;
   309 
   310     return NULL;
   311   }
   312 }
   313 
   314 static void
   315 remove_source (GstPlayBinMaemo *pbm)
   316 {
   317   GstElement *source = pbm->source;
   318 
   319   if (source) {
   320     GST_DEBUG_OBJECT (pbm, "removing old src element");
   321     gst_element_set_state (source, GST_STATE_NULL);
   322     gst_bin_remove (GST_BIN_CAST (pbm), source);
   323     pbm->source = NULL;
   324   }
   325 }
   326 
   327 static void
   328 remove_decoders (GstPlayBinMaemo *pbm)
   329 {
   330     if (pbm->queue != NULL) {
   331         gst_element_set_state (pbm->queue, GST_STATE_NULL);
   332         gst_bin_remove (GST_BIN_CAST (pbm), pbm->queue);
   333         pbm->queue = NULL;
   334     }
   335 
   336     if (pbm->decoder != NULL) {
   337         gst_element_set_state (pbm->decoder, GST_STATE_NULL);
   338         gst_bin_remove (GST_BIN_CAST (pbm), pbm->decoder);
   339         pbm->decoder = NULL;
   340     }
   341 }
   342 
   343 static void
   344 remove_sinks (GstPlayBinMaemo *pbm)
   345 {
   346     GSList *walk;
   347 
   348     for(walk=pbm->sinks; walk != NULL; walk = walk->next) {
   349         GstElement *element = (GstElement *) walk->data;
   350 
   351         gst_element_set_state (element, GST_STATE_NULL);
   352         gst_bin_remove (GST_BIN_CAST (pbm), element);
   353     }
   354 
   355     g_slist_free (pbm->sinks);
   356     pbm->sinks = NULL;
   357 }
   358 
   359 static void
   360 prepare_elements (GstPlayBinMaemo *pbm)
   361 {
   362     if (pbm->decoder == NULL) {
   363         pbm->decoder = gst_element_factory_make ("decodebin2", "decode");
   364         gst_bin_add (GST_BIN (pbm), pbm->decoder);
   365         g_signal_connect (G_OBJECT (pbm->decoder),
   366                           "autoplug-continue",
   367                           G_CALLBACK (autoplug_continue_cb),
   368                           pbm);
   369         g_signal_connect (G_OBJECT (pbm->decoder),
   370                           "unknown-type",
   371                           G_CALLBACK (unknown_type_cb),
   372                           pbm);
   373         g_signal_connect (G_OBJECT (pbm->decoder),
   374                           "new-decoded-pad",
   375                           G_CALLBACK (new_decoded_pad_cb),
   376                           pbm);
   377     }
   378 
   379     if (pbm->queue == NULL) {
   380         pbm->queue = gst_element_factory_make ("queue", NULL);
   381         gst_bin_add (GST_BIN (pbm), pbm->queue);
   382     }
   383 
   384     if (gst_element_link_many (pbm->source, pbm->queue, pbm->decoder, NULL) == FALSE) {
   385         g_warning ("FAIL TO LINK SRC WITH DECODEBIN2");
   386     }
   387 }
   388 
   389 static gboolean
   390 setup_source (GstPlayBinMaemo *pbm)
   391 {
   392     if (!pbm->need_rebuild)
   393         return TRUE;
   394 
   395     GST_DEBUG_OBJECT (pbm, "setup source");
   396 
   397     pbm->has_metadata = FALSE;
   398 
   399     /* delete old src */
   400     remove_source (pbm);
   401 
   402     /* create and configure an element that can handle the uri */
   403     if (!(pbm->source = gen_source_element (pbm)))
   404         goto no_source;
   405 
   406 
   407     gst_bin_add (GST_BIN_CAST (pbm), pbm->source);
   408 
   409     remove_decoders (pbm);
   410 
   411     remove_sinks (pbm);
   412 
   413 #if 0
   414     if (verify_src_have_sink (pbm)) {
   415         /* source can be linked with sinks directly */
   416         return TRUE;
   417     }
   418 #endif
   419 
   420     prepare_elements (pbm);
   421 
   422     return TRUE;
   423 
   424 no_source:
   425     return FALSE;
   426 }
   427 
   428 static void
   429 gst_play_bin_maemo_set_property (GObject *object,
   430                                  guint prop_id,
   431                                  const GValue *value,
   432                                  GParamSpec *pspec)
   433 {
   434   GstPlayBinMaemo *play_bin_maemo;
   435 
   436   g_return_if_fail (GST_IS_PLAY_BIN_MAEMO (object));
   437 
   438   play_bin_maemo = GST_PLAY_BIN_MAEMO (object);
   439 
   440   switch (prop_id) {
   441     case ARG_URI:
   442     {
   443       const gchar *uri = g_value_get_string (value);
   444 
   445       if (uri == NULL) {
   446         g_warning ("cannot set NULL uri");
   447         return;
   448       }
   449       /* if we have no previous uri, or the new uri is different from the
   450        * old one, replug */
   451       if (play_bin_maemo->uri == NULL || strcmp (play_bin_maemo->uri, uri) != 0) {
   452         g_free (play_bin_maemo->uri);
   453         play_bin_maemo->uri = g_strdup (uri);
   454 
   455         GST_DEBUG ("setting new uri to %s", uri);
   456 
   457         play_bin_maemo->need_rebuild = TRUE;
   458       }
   459       break;
   460     }
   461     case ARG_VOLUME:
   462     {
   463       guint volume;
   464       volume = g_value_get_uint (value);
   465       if (volume != 0) {
   466         volume = (guint) (65535 * volume / 10);
   467       }
   468 
   469       if (play_bin_maemo->volume != volume) {
   470           play_bin_maemo->volume = volume;
   471           update_volume (play_bin_maemo);
   472       }
   473       break;
   474     }
   475     case ARG_XID:
   476     {
   477       long xid;
   478       xid = g_value_get_long (value);
   479       if (play_bin_maemo->xid != xid) {
   480           play_bin_maemo->xid = xid;
   481           update_xid (play_bin_maemo);
   482       }
   483       break;
   484     }
   485     case ARG_PARSE_METADATA:
   486         play_bin_maemo->parse_metadata = g_value_get_boolean (value);
   487         break;
   488     default:
   489       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   490       break;
   491   }
   492 }
   493 
   494 static void
   495 gst_play_bin_maemo_get_property (GObject * object, guint prop_id, GValue * value,
   496     GParamSpec * pspec)
   497 {
   498   GstPlayBinMaemo *play_bin_maemo;
   499 
   500   g_return_if_fail (GST_IS_PLAY_BIN_MAEMO (object));
   501 
   502   play_bin_maemo = GST_PLAY_BIN_MAEMO (object);
   503 
   504   switch (prop_id) {
   505     case ARG_URI:
   506       g_value_set_string (value, play_bin_maemo->uri);
   507       break;
   508     case ARG_SOURCE:
   509       g_value_set_object (value, play_bin_maemo->source);
   510       break;
   511     case ARG_VOLUME:
   512       g_value_set_uint (value, play_bin_maemo->volume);
   513       break;
   514     case ARG_XID:
   515       g_value_set_long (value, play_bin_maemo->xid);
   516       break;
   517     case ARG_PARSE_METADATA:
   518       g_value_set_boolean (value, play_bin_maemo->parse_metadata);
   519       break;
   520     default:
   521       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   522       break;
   523   }
   524 }
   525 
   526 static GstStateChangeReturn
   527 gst_play_bin_maemo_change_state (GstElement * element, GstStateChange transition)
   528 {
   529   GstStateChangeReturn ret;
   530   GstPlayBinMaemo *play_bin_maemo;
   531 
   532   play_bin_maemo = GST_PLAY_BIN_MAEMO (element);
   533 
   534   switch (transition) {
   535     case GST_STATE_CHANGE_READY_TO_PAUSED:
   536       if (!setup_source (play_bin_maemo))
   537         goto source_failed;
   538       break;
   539     default:
   540       break;
   541   }
   542 
   543   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
   544 
   545   switch (transition) {
   546     case GST_STATE_CHANGE_READY_TO_PAUSED:
   547       if (ret == GST_STATE_CHANGE_FAILURE) {
   548         play_bin_maemo->need_rebuild = TRUE;
   549         return GST_STATE_CHANGE_FAILURE;
   550       }
   551       break;
   552       /* clean-up in both cases, READY=>NULL clean-up is if there was an error */
   553     case GST_STATE_CHANGE_PAUSED_TO_READY:
   554     case GST_STATE_CHANGE_READY_TO_NULL:
   555       play_bin_maemo->need_rebuild = TRUE;
   556       remove_decoders (play_bin_maemo);
   557       remove_source (play_bin_maemo);
   558       break;
   559     default:
   560       break;
   561   }
   562   return ret;
   563 
   564   /* ERRORS */
   565 source_failed:
   566   {
   567     play_bin_maemo->need_rebuild = TRUE;
   568 
   569     return GST_STATE_CHANGE_FAILURE;
   570   }
   571 }
   572 
   573 static gboolean
   574 factory_filter_sinks (GstPluginFeature *feature,
   575                       GstPlayBinMaemo *pbm)
   576 {
   577     guint rank;
   578     const gchar *klass;
   579 
   580     if (!GST_IS_ELEMENT_FACTORY (feature))
   581         return FALSE;
   582 
   583     klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature));
   584 
   585     if ((strstr (klass, "Sink/Video") == NULL) && (strstr (klass, "Sink/Audio") == NULL))
   586         return FALSE;
   587 
   588     g_debug ("Fitered: %s", gst_element_factory_get_longname ((GST_ELEMENT_FACTORY (feature))));
   589     rank = gst_plugin_feature_get_rank (feature);
   590     if (rank < GST_RANK_MARGINAL)
   591         return FALSE;
   592 
   593     return TRUE;
   594 }
   595 
   596 static gint
   597 compare_ranks (GstPluginFeature * f1, GstPluginFeature * f2)
   598 {
   599   gint diff;
   600   const gchar *rname1, *rname2;
   601 
   602   diff = gst_plugin_feature_get_rank (f2) - gst_plugin_feature_get_rank (f1);
   603   if (diff != 0)
   604     return diff;
   605 
   606   rname1 = gst_plugin_feature_get_name (f1);
   607   rname2 = gst_plugin_feature_get_name (f2);
   608 
   609   diff = strcmp (rname2, rname1);
   610 
   611   return diff;
   612 }
   613 
   614 
   615 static GList *
   616 find_compatibles (GstPlayBinMaemo *pbm, const GstCaps *caps)
   617 {
   618   GList *factories;
   619   GList *to_try = NULL;
   620 
   621   /* loop over all the factories */
   622   for (factories = pbm->factories; factories; factories = g_list_next (factories)) {
   623     GstElementFactory *factory = GST_ELEMENT_FACTORY (factories->data);
   624     const GList *templates;
   625     GList *walk;
   626 
   627     /* get the templates from the element factory */
   628     templates = gst_element_factory_get_static_pad_templates (factory);
   629     for (walk = (GList *) templates; walk; walk = g_list_next (walk)) {
   630       GstStaticPadTemplate *templ = walk->data;
   631 
   632       /* we only care about the sink templates */
   633       if (templ->direction == GST_PAD_SINK) {
   634         GstCaps *intersect;
   635         GstCaps *tmpl_caps;
   636 
   637         /* try to intersect the caps with the caps of the template */
   638         tmpl_caps = gst_static_caps_get (&templ->static_caps);
   639 
   640         intersect = gst_caps_intersect (caps, tmpl_caps);
   641         gst_caps_unref (tmpl_caps);
   642 
   643         /* check if the intersection is empty */
   644         if (!gst_caps_is_empty (intersect)) {
   645           /* non empty intersection, we can use this element */
   646           to_try = g_list_prepend (to_try, factory);
   647           gst_caps_unref (intersect);
   648           break;
   649         }
   650         gst_caps_unref (intersect);
   651       }
   652     }
   653   }
   654   to_try = g_list_reverse (to_try);
   655 
   656   return to_try;
   657 }
   658 
   659 
   660 static gboolean
   661 autoplug_continue_cb (GstElement* object,
   662                       GstCaps* caps,
   663                       gpointer user_data)
   664 {
   665     GList *comp = NULL;
   666     gboolean ret = TRUE;
   667     GstPlayBinMaemo *pbm;
   668 
   669     pbm = GST_PLAY_BIN_MAEMO (user_data);
   670 
   671     //TODO: fix this for work with all metada elements
   672     if (pbm->parse_metadata) {
   673         gchar *caps_str = gst_caps_to_string (caps);
   674         if ((strstr (caps_str, "id3") != NULL) &&
   675             (pbm->has_metadata == FALSE)) {
   676 
   677             g_free (caps_str);
   678             pbm->has_metadata = TRUE;
   679             return ret;
   680         }
   681         g_free (caps_str);
   682     }
   683 
   684     comp = find_compatibles (GST_PLAY_BIN_MAEMO (user_data), caps);
   685     if (comp != NULL) {
   686         g_list_free (comp);
   687         ret = FALSE;
   688     }
   689 
   690     return ret;
   691 }
   692 
   693 static void
   694 unknown_type_cb (GstElement *object,
   695                  GstPad *pad,
   696                  GstCaps *caps,
   697                  gpointer user_data)
   698 {
   699     g_debug ("unknown_type_cb: %s", gst_caps_to_string (caps));
   700 }
   701 
   702 static GstPad *
   703 find_sink_pad (GstElement * element)
   704 {
   705   GstIterator *it;
   706   GstPad *pad = NULL;
   707   gpointer point;
   708 
   709   it = gst_element_iterate_sink_pads (element);
   710 
   711   if ((gst_iterator_next (it, &point)) == GST_ITERATOR_OK)
   712     pad = (GstPad *) point;
   713 
   714   gst_iterator_free (it);
   715 
   716   return pad;
   717 }
   718 
   719 static GstElement*
   720 create_element (GstPlayBinMaemo *pbm, GstElementFactory *factory)
   721 {
   722     GstElement *ret = NULL;
   723     GstElement *element;
   724 
   725     element = gst_element_factory_create (factory, NULL);
   726     if (element == NULL)
   727         return NULL;
   728 
   729     if (strstr (gst_element_factory_get_klass (factory), "Sink/Video") != NULL) {
   730         update_xid (pbm);
   731         pbm->sink_video = element;
   732         ret = element;
   733     } else if (strstr (gst_element_factory_get_klass (factory), "Sink/Audio") != NULL) {
   734         GParamSpec *vol_spec;
   735 
   736         vol_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (element), "volume");
   737         if (vol_spec == NULL) {
   738             GstElement *bin;
   739             GstElement *volume;
   740 
   741             bin = gst_bin_new (NULL);
   742             volume = gst_element_factory_make ("volume", "volume");
   743             gst_bin_add (GST_BIN (bin), volume);
   744             gst_bin_add (GST_BIN (bin), element);
   745             if (gst_element_link (volume, element) == FALSE) {
   746                 GST_WARNING_OBJECT (pbm, "Fail to link volume and sink audio: %s", GST_ELEMENT_NAME (element));
   747                 gst_element_set_state (bin, GST_STATE_NULL);
   748                 gst_object_unref (bin);
   749                 return NULL;
   750             }
   751             pbm->volume_element = volume;
   752             ret = bin;
   753         } else {
   754             ret = element;
   755             pbm->volume_element = element;
   756             g_param_spec_unref (vol_spec);
   757         }
   758 
   759         update_volume (pbm);
   760     }
   761 
   762     return ret;
   763 }
   764 
   765 static void
   766 new_decoded_pad_cb (GstElement *object,
   767                     GstPad* pad,
   768                     gboolean arg,
   769                     gpointer user_data)
   770 {
   771     GList *comp = NULL;
   772     GList *walk;
   773     GstCaps *caps;
   774     gboolean linked;
   775     GstPlayBinMaemo *pbm;
   776 
   777     pbm = GST_PLAY_BIN_MAEMO (user_data);
   778     caps = gst_pad_get_caps (pad);
   779 
   780     g_debug ("new_decoded_pad_cb: %s", gst_caps_to_string (caps));
   781 
   782     comp = find_compatibles (GST_PLAY_BIN_MAEMO (user_data), caps);
   783 
   784 
   785     if (comp == NULL) {
   786         g_warning ("flow error: dont find comaptible");
   787         return;
   788     }
   789 
   790     GST_PAD_STREAM_LOCK (pad);
   791 
   792     linked = FALSE;
   793     for (walk=comp; walk != NULL; walk = walk->next) {
   794         GstElementFactory *factory = (GstElementFactory *) walk->data;
   795         GstElement *element;
   796         GstPad *sinkpad;
   797 
   798         if ((element = create_element (pbm, factory)) == NULL) {
   799             GST_WARNING_OBJECT (pbm, "Could not create an element from %s",
   800                 gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
   801             continue;
   802         }
   803 
   804         if (!(gst_bin_add (GST_BIN (user_data), element))) {
   805             GST_WARNING_OBJECT (pbm, "Couldn't set %s to READY", GST_ELEMENT_NAME (element));
   806             gst_object_unref (element);
   807             continue;
   808         }
   809 
   810         if ((gst_element_set_state (element, GST_STATE_READY))
   811                          == GST_STATE_CHANGE_FAILURE) {
   812             gst_element_set_state (element, GST_STATE_NULL);
   813             gst_object_unref (sinkpad);
   814             gst_bin_remove (GST_BIN (user_data), element);
   815             continue;
   816         }
   817 
   818         if (!(sinkpad = find_sink_pad (element))) {
   819             GST_WARNING_OBJECT (pbm, "Element %s doesn't have a sink pad", GST_ELEMENT_NAME (element));
   820             gst_object_unref (element);
   821             continue;
   822         }
   823 
   824 
   825         if ((gst_pad_link (pad, sinkpad)) != GST_PAD_LINK_OK) {
   826             GST_WARNING_OBJECT (pbm, "Link failed on pad %s:%s", GST_DEBUG_PAD_NAME (sinkpad));
   827             gst_element_set_state (element, GST_STATE_NULL);
   828             gst_object_unref (sinkpad);
   829             gst_bin_remove (GST_BIN (user_data), element);
   830             continue;
   831         }
   832 
   833         gst_object_unref (sinkpad);
   834 
   835         if ((gst_element_set_state (element, GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE) {
   836             gst_element_set_state (element, GST_STATE_NULL);
   837             gst_bin_remove (GST_BIN (user_data), element);
   838             continue;
   839         }
   840 
   841 
   842         pbm->sinks = g_slist_append (pbm->sinks, element);
   843         linked = TRUE;
   844         break;
   845     }
   846 
   847     g_list_free (comp);
   848     if (linked == FALSE) {
   849         g_warning ("GstFlow ERROR");
   850     }
   851     GST_PAD_STREAM_UNLOCK (pad);
   852 }
   853 
   854 static void
   855 update_volume (GstPlayBinMaemo *pbm)
   856 {
   857     if (pbm->volume_element != NULL) {
   858         if (pbm->volume > 0) {
   859             g_object_set (G_OBJECT (pbm->volume_element),
   860                           "volume", pbm->volume,
   861                           NULL);
   862         } else {
   863             g_object_set (G_OBJECT (pbm->volume_element),
   864                           "mute", TRUE,
   865                           NULL);
   866         }
   867     }
   868 }
   869 
   870 static void
   871 update_xid (GstPlayBinMaemo *pbm)
   872 {
   873     if ((pbm->sink_video != NULL) &&
   874         (pbm->xid != -1) &&
   875         (GST_IS_X_OVERLAY (pbm->sink_video))) {
   876 
   877         g_object_set (G_OBJECT (pbm->sink_video),
   878                       "force-aspect-ratio", TRUE, NULL);
   879         gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (pbm->sink_video),
   880                                       pbm->xid);
   881     }
   882 }
   883 
   884 static gboolean
   885 plugin_init(GstPlugin * plugin)
   886 {
   887 #ifdef ENABLE_NLS
   888     setlocale(LC_ALL, "");
   889     bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
   890 #endif                          /* ENABLE_NLS */
   891 
   892     if (!gst_element_register(plugin, "playbinmaemo", GST_RANK_SECONDARY,
   893                               GST_TYPE_PLAY_BIN_MAEMO)) {
   894         return FALSE;
   895     }
   896 
   897     return TRUE;
   898 }
   899 
   900 GST_PLUGIN_DEFINE(GST_VERSION_MAJOR,
   901                   GST_VERSION_MINOR,
   902                   "playbinmaemo",
   903                   "Demuxes and muxes audio and video",
   904                   plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME,
   905                   GST_PACKAGE_ORIGIN)