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