1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/gst-gmyth/playbinmaemo/gstplaybinmaemo.c Sat Jul 14 17:20:54 2007 +0100
1.3 @@ -0,0 +1,841 @@
1.4 +/* GStreamer
1.5 + * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
1.6 + *
1.7 + * This library is free software; you can redistribute it and/or
1.8 + * modify it under the terms of the GNU Library General Public
1.9 + * License as published by the Free Software Foundation; either
1.10 + * version 2 of the License, or (at your option) any later version.
1.11 + *
1.12 + * This library is distributed in the hope that it will be useful,
1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1.15 + * Library General Public License for more details.
1.16 + *
1.17 + * You should have received a copy of the GNU Library General Public
1.18 + * License along with this library; if not, write to the
1.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
1.20 + * Boston, MA 02111-1307, USA.
1.21 + */
1.22 +
1.23 +#ifdef HAVE_CONFIG_H
1.24 +#include "config.h"
1.25 +#endif
1.26 +
1.27 +#include <glib/gi18n.h>
1.28 +#include <string.h>
1.29 +#include <gst/gst.h>
1.30 +#include <gst/gsterror.h>
1.31 +#include <gst/gstplugin.h>
1.32 +#include <gst/interfaces/xoverlay.h>
1.33 +#include <X11/Xlib.h>
1.34 +//#include <gst/pbutils/pbutils.h>
1.35 +#include "gstplaybinmaemo.h"
1.36 +
1.37 +
1.38 +GST_DEBUG_CATEGORY_STATIC (gst_play_bin_maemo_debug);
1.39 +#define GST_CAT_DEFAULT gst_play_bin_maemo_debug
1.40 +
1.41 +#define DEFAULT_VOLUME 10
1.42 +#define DEFAULT_XID -1
1.43 +
1.44 +/* props */
1.45 +enum
1.46 +{
1.47 + ARG_0,
1.48 + ARG_URI,
1.49 + ARG_QUEUE_SIZE,
1.50 + ARG_QUEUE_MIN_THRESHOLD,
1.51 + ARG_SOURCE,
1.52 + ARG_VOLUME,
1.53 + ARG_XID
1.54 +};
1.55 +
1.56 +static const GstElementDetails gst_play_bin_maemo_details =
1.57 + GST_ELEMENT_DETAILS("Nuv demuxer",
1.58 + "Generic/Bin/Player",
1.59 + "Autoplug and play media from an uri used on maemo plataform",
1.60 + "Renato Araujo Oliveira Filho <renato.filho@indt.org.br>");
1.61 +
1.62 +static void gst_play_bin_maemo_dispose (GObject * object);
1.63 +static void gst_play_bin_maemo_finalize (GObject * object);
1.64 +static void gst_play_bin_maemo_set_property (GObject * object, guint prop_id,
1.65 + const GValue * value, GParamSpec * spec);
1.66 +static void gst_play_bin_maemo_get_property (GObject * object, guint prop_id,
1.67 + GValue * value, GParamSpec * spec);
1.68 +static GstStateChangeReturn
1.69 + gst_play_bin_maemo_change_state (GstElement *element,
1.70 + GstStateChange transition);
1.71 +static gboolean factory_filter_sinks (GstPluginFeature *feature,
1.72 + GstPlayBinMaemo *pbm);
1.73 +static gint compare_ranks (GstPluginFeature * f1,
1.74 + GstPluginFeature * f2);
1.75 +static GList *find_compatibles (GstPlayBinMaemo *pbm,
1.76 + const GstCaps *caps);
1.77 +static GstPad *find_sink_pad (GstElement * element);
1.78 +static void update_volume (GstPlayBinMaemo *pbm);
1.79 +static void update_xid (GstPlayBinMaemo *pbm);
1.80 +static void new_decoded_pad_cb (GstElement *object,
1.81 + GstPad* pad,
1.82 + gboolean arg,
1.83 + gpointer user_data);
1.84 +static void unknown_type_cb (GstElement *object,
1.85 + GstPad *pad,
1.86 + GstCaps *casp,
1.87 + gpointer user_data);
1.88 +static gboolean autoplug_continue_cb (GstElement* object,
1.89 + GstCaps* caps,
1.90 + gpointer user_data);
1.91 +static void decode_new_pad_cb (GstElement *element,
1.92 + GObject *new_pad,
1.93 + gpointer user_data);
1.94 +static void queue_underrun_cb (GstElement* queue,
1.95 + gpointer user_data);
1.96 +static void queue_sink_underrun_cb (GstElement* queue,
1.97 + gpointer user_data);
1.98 +static void queue_sink_overrun_cb (GstElement* queue,
1.99 + gpointer user_data);
1.100 +
1.101 +
1.102 +
1.103 +
1.104 +
1.105 +GST_BOILERPLATE(GstPlayBinMaemo, gst_play_bin_maemo, GstPipeline, GST_TYPE_PIPELINE)
1.106 +
1.107 +
1.108 +static void
1.109 +gst_play_bin_maemo_base_init (gpointer klass)
1.110 +{
1.111 + GstElementClass *element_class = GST_ELEMENT_CLASS(klass);
1.112 +
1.113 + gst_element_class_set_details (element_class, &gst_play_bin_maemo_details);
1.114 +}
1.115 +
1.116 +static void
1.117 +gst_play_bin_maemo_class_init (GstPlayBinMaemoClass * klass)
1.118 +{
1.119 + GObjectClass *gobject_klass;
1.120 + GstElementClass *gstelement_klass;
1.121 + GstBinClass *gstbin_klass;
1.122 +
1.123 + gobject_klass = (GObjectClass *) klass;
1.124 + gstelement_klass = (GstElementClass *) klass;
1.125 + gstbin_klass = (GstBinClass *) klass;
1.126 +
1.127 + parent_class = g_type_class_peek_parent (klass);
1.128 +
1.129 + gobject_klass->set_property = gst_play_bin_maemo_set_property;
1.130 + gobject_klass->get_property = gst_play_bin_maemo_get_property;
1.131 +
1.132 + g_object_class_install_property (gobject_klass, ARG_URI,
1.133 + g_param_spec_string ("uri", "URI", "URI of the media to play",
1.134 + NULL, G_PARAM_READWRITE));
1.135 +
1.136 + g_object_class_install_property (gobject_klass, ARG_VOLUME,
1.137 + g_param_spec_uint ("volume", "Audio volume", "volume",
1.138 + 0, 10, (guint) DEFAULT_VOLUME, G_PARAM_READWRITE));
1.139 +
1.140 + g_object_class_install_property (gobject_klass, ARG_XID,
1.141 + g_param_spec_long ("xid", "xid", "X windown ID",
1.142 + -1, G_MAXLONG, DEFAULT_XID, G_PARAM_READWRITE));
1.143 +
1.144 + g_object_class_install_property (gobject_klass, ARG_SOURCE,
1.145 + g_param_spec_object ("source", "Source", "Source element",
1.146 + GST_TYPE_ELEMENT, G_PARAM_READABLE));
1.147 +
1.148 + GST_DEBUG_CATEGORY_INIT (gst_play_bin_maemo_debug, "playbinmaemo", 0,
1.149 + "playbinmaemo");
1.150 +
1.151 + gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_play_bin_maemo_dispose);
1.152 + gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_play_bin_maemo_finalize);
1.153 +
1.154 + gstelement_klass->change_state =
1.155 + GST_DEBUG_FUNCPTR (gst_play_bin_maemo_change_state);
1.156 +}
1.157 +
1.158 +static void
1.159 +gst_play_bin_maemo_init (GstPlayBinMaemo * play_bin_maemo, GstPlayBinMaemoClass *class)
1.160 +{
1.161 + GList *factories;
1.162 +
1.163 + play_bin_maemo->uri = NULL;
1.164 + play_bin_maemo->source = NULL;
1.165 +
1.166 + play_bin_maemo->volume = DEFAULT_VOLUME * 65535 / 10;
1.167 + play_bin_maemo->xid = DEFAULT_XID;
1.168 +
1.169 + factories = gst_default_registry_feature_filter ((GstPluginFeatureFilter) factory_filter_sinks,
1.170 + FALSE, play_bin_maemo);
1.171 +
1.172 + play_bin_maemo->factories = g_list_sort (factories, (GCompareFunc) compare_ranks);
1.173 +}
1.174 +
1.175 +static void
1.176 +gst_play_bin_maemo_dispose (GObject * object)
1.177 +{
1.178 + GstPlayBinMaemo *play_bin_maemo;
1.179 +
1.180 + play_bin_maemo = GST_PLAY_BIN_MAEMO (object);
1.181 + g_free (play_bin_maemo->uri);
1.182 + play_bin_maemo->uri = NULL;
1.183 +
1.184 + G_OBJECT_CLASS (parent_class)->dispose (object);
1.185 +}
1.186 +
1.187 +static void
1.188 +gst_play_bin_maemo_finalize (GObject * object)
1.189 +{
1.190 + G_OBJECT_CLASS (parent_class)->finalize (object);
1.191 +}
1.192 +
1.193 +static gboolean
1.194 +array_has_value (const gchar * values[], const gchar * value)
1.195 +{
1.196 + gint i;
1.197 +
1.198 + for (i = 0; values[i]; i++) {
1.199 + if (g_str_has_prefix (value, values[i]))
1.200 + return TRUE;
1.201 + }
1.202 + return FALSE;
1.203 +}
1.204 +
1.205 +/* list of URIs that we consider to be streams and that need buffering.
1.206 + * We have no mechanism yet to figure this out with a query. */
1.207 +static const gchar *stream_uris[] = { "http://", "mms://", "mmsh://",
1.208 + "mmsu://", "mmst://", NULL
1.209 +};
1.210 +
1.211 +/* blacklisted URIs, we know they will always fail. */
1.212 +static const gchar *blacklisted_uris[] = { NULL };
1.213 +
1.214 +/* mime types that we don't consider to be media types */
1.215 +static const gchar *no_media_mimes[] = {
1.216 + "application/x-executable", "application/x-bzip", "application/x-gzip",
1.217 + "application/zip", "application/x-compress", NULL
1.218 +};
1.219 +
1.220 +/* mime types we consider raw media */
1.221 +static const gchar *raw_mimes[] = {
1.222 + "audio/x-raw", "video/x-raw", NULL
1.223 +};
1.224 +
1.225 +#define IS_STREAM_URI(uri) (array_has_value (stream_uris, uri))
1.226 +#define IS_BLACKLISTED_URI(uri) (array_has_value (blacklisted_uris, uri))
1.227 +#define IS_NO_MEDIA_MIME(mime) (array_has_value (no_media_mimes, mime))
1.228 +#define IS_RAW_MIME(mime) (array_has_value (raw_mimes, mime))
1.229 +
1.230 +/*
1.231 + * Generate and configure a source element.
1.232 + */
1.233 +static GstElement *
1.234 +gen_source_element (GstPlayBinMaemo * play_bin_maemo)
1.235 +{
1.236 + GstElement *source;
1.237 +
1.238 + if (!play_bin_maemo->uri)
1.239 + goto no_uri;
1.240 +
1.241 + if (!gst_uri_is_valid (play_bin_maemo->uri))
1.242 + goto invalid_uri;
1.243 +
1.244 + if (IS_BLACKLISTED_URI (play_bin_maemo->uri))
1.245 + goto uri_blacklisted;
1.246 +
1.247 + source = gst_element_make_from_uri (GST_URI_SRC, play_bin_maemo->uri,
1.248 + "source");
1.249 + if (!source)
1.250 + goto no_source;
1.251 +
1.252 + play_bin_maemo->is_stream = IS_STREAM_URI (play_bin_maemo->uri);
1.253 +
1.254 + /* make HTTP sources send extra headers so we get icecast
1.255 + * metadata in case the stream is an icecast stream */
1.256 + if (!strncmp (play_bin_maemo->uri, "http://", 7) &&
1.257 + g_object_class_find_property (G_OBJECT_GET_CLASS (source),
1.258 + "iradio-mode")) {
1.259 + g_object_set (source, "iradio-mode", TRUE, NULL);
1.260 + }
1.261 + return source;
1.262 +
1.263 + /* ERRORS */
1.264 +no_uri:
1.265 + {
1.266 + GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, NOT_FOUND,
1.267 + (_("No URI specified to play from.")), (NULL));
1.268 + return NULL;
1.269 + }
1.270 +invalid_uri:
1.271 + {
1.272 + GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, NOT_FOUND,
1.273 + (_("Invalid URI \"%s\"."), play_bin_maemo->uri), (NULL));
1.274 + return NULL;
1.275 + }
1.276 +uri_blacklisted:
1.277 + {
1.278 + GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, FAILED,
1.279 + (_("RTSP streams cannot be played yet.")), (NULL));
1.280 + return NULL;
1.281 + }
1.282 +no_source:
1.283 + {
1.284 + gchar *prot = gst_uri_get_protocol (play_bin_maemo->uri);
1.285 +
1.286 + /* whoops, could not create the source element, dig a little deeper to
1.287 + * figure out what might be wrong. */
1.288 + if (prot) {
1.289 + gchar *desc;
1.290 +
1.291 + /*
1.292 + gst_element_post_message (GST_ELEMENT (play_bin_maemo),
1.293 + gst_missing_uri_source_message_new (GST_ELEMENT (play_bin_maemo),
1.294 + prot));
1.295 +
1.296 + desc = gst_pb_utils_get_source_description (prot);
1.297 + GST_ELEMENT_ERROR (play_bin_maemo, CORE, MISSING_PLUGIN,
1.298 + (_("A %s plugin is required to play this stream, but not installed."),
1.299 + desc), ("No URI handler for %s", prot));
1.300 + */
1.301 + g_free (desc);
1.302 + g_free (prot);
1.303 + } else
1.304 + goto invalid_uri;
1.305 +
1.306 + return NULL;
1.307 + }
1.308 +}
1.309 +
1.310 +static void
1.311 +remove_source (GstPlayBinMaemo *pbm)
1.312 +{
1.313 + GstElement *source = pbm->source;
1.314 +
1.315 + if (source) {
1.316 + GST_DEBUG_OBJECT (pbm, "removing old src element");
1.317 + gst_element_set_state (source, GST_STATE_NULL);
1.318 + gst_bin_remove (GST_BIN_CAST (pbm), source);
1.319 + pbm->source = NULL;
1.320 + }
1.321 +}
1.322 +
1.323 +static void
1.324 +remove_decoders (GstPlayBinMaemo *pbm)
1.325 +{
1.326 + if (pbm->queue != NULL) {
1.327 + gst_element_set_state (pbm->queue, GST_STATE_NULL);
1.328 + gst_bin_remove (GST_BIN_CAST (pbm), pbm->queue);
1.329 + pbm->queue = NULL;
1.330 + }
1.331 +
1.332 + if (pbm->decoder != NULL) {
1.333 + gst_element_set_state (pbm->decoder, GST_STATE_NULL);
1.334 + gst_bin_remove (GST_BIN_CAST (pbm), pbm->decoder);
1.335 + pbm->decoder = NULL;
1.336 + }
1.337 +}
1.338 +
1.339 +static void
1.340 +remove_sinks (GstPlayBinMaemo *pbm)
1.341 +{
1.342 + GSList *walk;
1.343 +
1.344 + for(walk=pbm->sinks; walk != NULL; walk = walk->next) {
1.345 + GstElement *element = (GstElement *) walk->data;
1.346 +
1.347 + gst_element_set_state (element, GST_STATE_NULL);
1.348 + gst_bin_remove (GST_BIN_CAST (pbm), element);
1.349 + }
1.350 +
1.351 + g_slist_free (pbm->sinks);
1.352 + pbm->sinks = NULL;
1.353 +}
1.354 +
1.355 +static void
1.356 +prepare_elements (GstPlayBinMaemo *pbm)
1.357 +{
1.358 + if (pbm->decoder == NULL) {
1.359 + pbm->decoder = gst_element_factory_make ("decodebin2", "decode");
1.360 + gst_bin_add (GST_BIN (pbm), pbm->decoder);
1.361 + g_signal_connect (G_OBJECT (pbm->decoder),
1.362 + "autoplug-continue",
1.363 + G_CALLBACK (autoplug_continue_cb),
1.364 + pbm);
1.365 + g_signal_connect (G_OBJECT (pbm->decoder),
1.366 + "unknown-type",
1.367 + G_CALLBACK (unknown_type_cb),
1.368 + pbm);
1.369 + g_signal_connect (G_OBJECT (pbm->decoder),
1.370 + "new-decoded-pad",
1.371 + G_CALLBACK (new_decoded_pad_cb),
1.372 + pbm);
1.373 + }
1.374 +
1.375 + if (pbm->queue == NULL) {
1.376 + pbm->queue = gst_element_factory_make ("queue", NULL);
1.377 + gst_bin_add (GST_BIN (pbm), pbm->queue);
1.378 + }
1.379 +
1.380 + if (gst_element_link_many (pbm->source, pbm->queue, pbm->decoder, NULL) == FALSE) {
1.381 + g_warning ("FAIL TO LINK SRC WITH DECODEBIN2");
1.382 + }
1.383 +}
1.384 +
1.385 +static gboolean
1.386 +setup_source (GstPlayBinMaemo *pbm)
1.387 +{
1.388 + if (!pbm->need_rebuild)
1.389 + return TRUE;
1.390 +
1.391 + GST_DEBUG_OBJECT (pbm, "setup source");
1.392 +
1.393 + /* delete old src */
1.394 + remove_source (pbm);
1.395 +
1.396 + /* create and configure an element that can handle the uri */
1.397 + if (!(pbm->source = gen_source_element (pbm)))
1.398 + goto no_source;
1.399 +
1.400 +
1.401 + gst_bin_add (GST_BIN_CAST (pbm), pbm->source);
1.402 +
1.403 + remove_decoders (pbm);
1.404 +
1.405 + remove_sinks (pbm);
1.406 +
1.407 +#if 0
1.408 + if (verify_src_have_sink (pbm)) {
1.409 + /* source can be linked with sinks directly */
1.410 + return TRUE;
1.411 + }
1.412 +#endif
1.413 +
1.414 + prepare_elements (pbm);
1.415 +
1.416 + return TRUE;
1.417 +
1.418 +no_source:
1.419 + return FALSE;
1.420 +}
1.421 +
1.422 +static void
1.423 +gst_play_bin_maemo_set_property (GObject *object,
1.424 + guint prop_id,
1.425 + const GValue *value,
1.426 + GParamSpec *pspec)
1.427 +{
1.428 + GstPlayBinMaemo *play_bin_maemo;
1.429 +
1.430 + g_return_if_fail (GST_IS_PLAY_BIN_MAEMO (object));
1.431 +
1.432 + play_bin_maemo = GST_PLAY_BIN_MAEMO (object);
1.433 +
1.434 + switch (prop_id) {
1.435 + case ARG_URI:
1.436 + {
1.437 + const gchar *uri = g_value_get_string (value);
1.438 +
1.439 + if (uri == NULL) {
1.440 + g_warning ("cannot set NULL uri");
1.441 + return;
1.442 + }
1.443 + /* if we have no previous uri, or the new uri is different from the
1.444 + * old one, replug */
1.445 + if (play_bin_maemo->uri == NULL || strcmp (play_bin_maemo->uri, uri) != 0) {
1.446 + g_free (play_bin_maemo->uri);
1.447 + play_bin_maemo->uri = g_strdup (uri);
1.448 +
1.449 + GST_DEBUG ("setting new uri to %s", uri);
1.450 +
1.451 + play_bin_maemo->need_rebuild = TRUE;
1.452 + }
1.453 + break;
1.454 + }
1.455 + case ARG_VOLUME:
1.456 + {
1.457 + guint volume;
1.458 + volume = g_value_get_uint (value);
1.459 + if (volume != 0) {
1.460 + volume = (guint) (65535 * volume / 10);
1.461 + }
1.462 +
1.463 + if (play_bin_maemo->volume != volume) {
1.464 + play_bin_maemo->volume = volume;
1.465 + update_volume (play_bin_maemo);
1.466 + }
1.467 + break;
1.468 + }
1.469 + case ARG_XID:
1.470 + {
1.471 + long xid;
1.472 + xid = g_value_get_long (value);
1.473 + if (play_bin_maemo->xid != xid) {
1.474 + play_bin_maemo->xid = xid;
1.475 + update_xid (play_bin_maemo);
1.476 + }
1.477 + break;
1.478 + }
1.479 + default:
1.480 + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1.481 + break;
1.482 + }
1.483 +}
1.484 +
1.485 +static void
1.486 +gst_play_bin_maemo_get_property (GObject * object, guint prop_id, GValue * value,
1.487 + GParamSpec * pspec)
1.488 +{
1.489 + GstPlayBinMaemo *play_bin_maemo;
1.490 +
1.491 + g_return_if_fail (GST_IS_PLAY_BIN_MAEMO (object));
1.492 +
1.493 + play_bin_maemo = GST_PLAY_BIN_MAEMO (object);
1.494 +
1.495 + switch (prop_id) {
1.496 + case ARG_URI:
1.497 + g_value_set_string (value, play_bin_maemo->uri);
1.498 + break;
1.499 + case ARG_SOURCE:
1.500 + g_value_set_object (value, play_bin_maemo->source);
1.501 + break;
1.502 + case ARG_VOLUME:
1.503 + g_value_set_uint (value, play_bin_maemo->volume);
1.504 + break;
1.505 + case ARG_XID:
1.506 + g_value_set_long (value, play_bin_maemo->xid);
1.507 + break;
1.508 + default:
1.509 + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1.510 + break;
1.511 + }
1.512 +}
1.513 +
1.514 +static GstStateChangeReturn
1.515 +gst_play_bin_maemo_change_state (GstElement * element, GstStateChange transition)
1.516 +{
1.517 + GstStateChangeReturn ret;
1.518 + GstPlayBinMaemo *play_bin_maemo;
1.519 +
1.520 + play_bin_maemo = GST_PLAY_BIN_MAEMO (element);
1.521 +
1.522 + switch (transition) {
1.523 + case GST_STATE_CHANGE_READY_TO_PAUSED:
1.524 + if (!setup_source (play_bin_maemo))
1.525 + goto source_failed;
1.526 + break;
1.527 + default:
1.528 + break;
1.529 + }
1.530 +
1.531 + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1.532 +
1.533 + switch (transition) {
1.534 + case GST_STATE_CHANGE_READY_TO_PAUSED:
1.535 + if (ret == GST_STATE_CHANGE_FAILURE) {
1.536 + play_bin_maemo->need_rebuild = TRUE;
1.537 + return GST_STATE_CHANGE_FAILURE;
1.538 + }
1.539 + break;
1.540 + /* clean-up in both cases, READY=>NULL clean-up is if there was an error */
1.541 + case GST_STATE_CHANGE_PAUSED_TO_READY:
1.542 + case GST_STATE_CHANGE_READY_TO_NULL:
1.543 + play_bin_maemo->need_rebuild = TRUE;
1.544 + remove_decoders (play_bin_maemo);
1.545 + remove_source (play_bin_maemo);
1.546 + break;
1.547 + default:
1.548 + break;
1.549 + }
1.550 + return ret;
1.551 +
1.552 + /* ERRORS */
1.553 +source_failed:
1.554 + {
1.555 + play_bin_maemo->need_rebuild = TRUE;
1.556 +
1.557 + return GST_STATE_CHANGE_FAILURE;
1.558 + }
1.559 +}
1.560 +
1.561 +static gboolean
1.562 +factory_filter_sinks (GstPluginFeature *feature,
1.563 + GstPlayBinMaemo *pbm)
1.564 +{
1.565 + guint rank;
1.566 + const gchar *klass;
1.567 +
1.568 + if (!GST_IS_ELEMENT_FACTORY (feature))
1.569 + return FALSE;
1.570 +
1.571 + klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature));
1.572 +
1.573 + if ((strstr (klass, "Sink/Video") == NULL) && (strstr (klass, "Sink/Audio") == NULL))
1.574 + return FALSE;
1.575 +
1.576 + g_debug ("Fitered: %s", gst_element_factory_get_longname ((GST_ELEMENT_FACTORY (feature))));
1.577 + rank = gst_plugin_feature_get_rank (feature);
1.578 + if (rank < GST_RANK_MARGINAL)
1.579 + return FALSE;
1.580 +
1.581 + return TRUE;
1.582 +}
1.583 +
1.584 +static gint
1.585 +compare_ranks (GstPluginFeature * f1, GstPluginFeature * f2)
1.586 +{
1.587 + gint diff;
1.588 + const gchar *rname1, *rname2;
1.589 +
1.590 + diff = gst_plugin_feature_get_rank (f2) - gst_plugin_feature_get_rank (f1);
1.591 + if (diff != 0)
1.592 + return diff;
1.593 +
1.594 + rname1 = gst_plugin_feature_get_name (f1);
1.595 + rname2 = gst_plugin_feature_get_name (f2);
1.596 +
1.597 + diff = strcmp (rname2, rname1);
1.598 +
1.599 + return diff;
1.600 +}
1.601 +
1.602 +
1.603 +static GList *
1.604 +find_compatibles (GstPlayBinMaemo *pbm, const GstCaps *caps)
1.605 +{
1.606 + GList *factories;
1.607 + GList *to_try = NULL;
1.608 +
1.609 + /* loop over all the factories */
1.610 + for (factories = pbm->factories; factories; factories = g_list_next (factories)) {
1.611 + GstElementFactory *factory = GST_ELEMENT_FACTORY (factories->data);
1.612 + const GList *templates;
1.613 + GList *walk;
1.614 +
1.615 + /* get the templates from the element factory */
1.616 + templates = gst_element_factory_get_static_pad_templates (factory);
1.617 + for (walk = (GList *) templates; walk; walk = g_list_next (walk)) {
1.618 + GstStaticPadTemplate *templ = walk->data;
1.619 +
1.620 + /* we only care about the sink templates */
1.621 + if (templ->direction == GST_PAD_SINK) {
1.622 + GstCaps *intersect;
1.623 + GstCaps *tmpl_caps;
1.624 +
1.625 + /* try to intersect the caps with the caps of the template */
1.626 + tmpl_caps = gst_static_caps_get (&templ->static_caps);
1.627 +
1.628 + intersect = gst_caps_intersect (caps, tmpl_caps);
1.629 + gst_caps_unref (tmpl_caps);
1.630 +
1.631 + /* check if the intersection is empty */
1.632 + if (!gst_caps_is_empty (intersect)) {
1.633 + /* non empty intersection, we can use this element */
1.634 + to_try = g_list_prepend (to_try, factory);
1.635 + gst_caps_unref (intersect);
1.636 + break;
1.637 + }
1.638 + gst_caps_unref (intersect);
1.639 + }
1.640 + }
1.641 + }
1.642 + to_try = g_list_reverse (to_try);
1.643 +
1.644 + return to_try;
1.645 +}
1.646 +
1.647 +
1.648 +static gboolean
1.649 +autoplug_continue_cb (GstElement* object,
1.650 + GstCaps* caps,
1.651 + gpointer user_data)
1.652 +{
1.653 + GList *comp = NULL;
1.654 + gboolean ret = TRUE;
1.655 +
1.656 + comp = find_compatibles (GST_PLAY_BIN_MAEMO (user_data), caps);
1.657 + if (comp != NULL) {
1.658 + g_list_free (comp);
1.659 + ret = FALSE;
1.660 + }
1.661 +
1.662 + return ret;
1.663 +}
1.664 +
1.665 +static void
1.666 +unknown_type_cb (GstElement *object,
1.667 + GstPad *pad,
1.668 + GstCaps *caps,
1.669 + gpointer user_data)
1.670 +{
1.671 + g_debug ("unknown_type_cb: %s", gst_caps_to_string (caps));
1.672 +}
1.673 +
1.674 +static GstPad *
1.675 +find_sink_pad (GstElement * element)
1.676 +{
1.677 + GstIterator *it;
1.678 + GstPad *pad = NULL;
1.679 + gpointer point;
1.680 +
1.681 + it = gst_element_iterate_sink_pads (element);
1.682 +
1.683 + if ((gst_iterator_next (it, &point)) == GST_ITERATOR_OK)
1.684 + pad = (GstPad *) point;
1.685 +
1.686 + gst_iterator_free (it);
1.687 +
1.688 + return pad;
1.689 +}
1.690 +
1.691 +static void
1.692 +new_decoded_pad_cb (GstElement *object,
1.693 + GstPad* pad,
1.694 + gboolean arg,
1.695 + gpointer user_data)
1.696 +{
1.697 + GList *comp = NULL;
1.698 + GList *walk;
1.699 + GstCaps *caps;
1.700 + gboolean linked;
1.701 + GstPlayBinMaemo *pbm;
1.702 +
1.703 + pbm = GST_PLAY_BIN_MAEMO (user_data);
1.704 + caps = gst_pad_get_caps (pad);
1.705 +
1.706 + g_debug ("new_decoded_pad_cb: %s", gst_caps_to_string (caps));
1.707 +
1.708 + comp = find_compatibles (GST_PLAY_BIN_MAEMO (user_data), caps);
1.709 +
1.710 +
1.711 + if (comp == NULL) {
1.712 + g_warning ("flow error: dont find comaptible");
1.713 + return;
1.714 + }
1.715 +
1.716 + GST_PAD_STREAM_LOCK (pad);
1.717 +
1.718 + linked = FALSE;
1.719 + for (walk=comp; walk != NULL; walk = walk->next) {
1.720 + GstElementFactory *factory = (GstElementFactory *) walk->data;
1.721 + GstElement *element;
1.722 + GstPad *sinkpad;
1.723 +
1.724 + if ((element = gst_element_factory_create (factory, NULL)) == NULL) {
1.725 + GST_WARNING_OBJECT (pbm, "Could not create an element from %s",
1.726 + gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
1.727 + continue;
1.728 + }
1.729 +
1.730 + if (strstr (gst_element_factory_get_klass (factory), "Sink/Video") != NULL) {
1.731 + pbm->sink_video = element;
1.732 + update_xid (pbm);
1.733 + } else if (strstr (gst_element_factory_get_klass (factory), "Sink/Audio") != NULL) {
1.734 + pbm->volume_element = element;
1.735 + update_volume (pbm);
1.736 + }
1.737 +
1.738 + if (!(gst_bin_add (GST_BIN (user_data), element))) {
1.739 + GST_WARNING_OBJECT (pbm, "Couldn't set %s to READY",
1.740 + GST_ELEMENT_NAME (element));
1.741 + gst_object_unref (element);
1.742 + continue;
1.743 + }
1.744 +
1.745 + if ((gst_element_set_state (element, GST_STATE_READY))
1.746 + == GST_STATE_CHANGE_FAILURE) {
1.747 + gst_element_set_state (element, GST_STATE_NULL);
1.748 + gst_object_unref (sinkpad);
1.749 + gst_bin_remove (GST_BIN (user_data), element);
1.750 + continue;
1.751 + }
1.752 +
1.753 + if (!(sinkpad = find_sink_pad (element))) {
1.754 + GST_WARNING_OBJECT (pbm, "Element %s doesn't have a sink pad", GST_ELEMENT_NAME (element));
1.755 + gst_object_unref (element);
1.756 + continue;
1.757 + }
1.758 +
1.759 +
1.760 + if ((gst_pad_link (pad, sinkpad)) != GST_PAD_LINK_OK) {
1.761 + GST_WARNING_OBJECT (pbm, "Link failed on pad %s:%s",
1.762 + GST_DEBUG_PAD_NAME (sinkpad));
1.763 + gst_element_set_state (element, GST_STATE_NULL);
1.764 + gst_object_unref (sinkpad);
1.765 + gst_bin_remove (GST_BIN (user_data), element);
1.766 + continue;
1.767 + }
1.768 +
1.769 + gst_object_unref (sinkpad);
1.770 +
1.771 + if ((gst_element_set_state (element, GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE) {
1.772 + gst_element_set_state (element, GST_STATE_NULL);
1.773 + gst_bin_remove (GST_BIN (user_data), element);
1.774 + continue;
1.775 + }
1.776 +
1.777 +
1.778 + pbm->sinks = g_slist_append (pbm->sinks, element);
1.779 + linked = TRUE;
1.780 + break;
1.781 + }
1.782 +
1.783 + g_list_free (comp);
1.784 + if (linked == FALSE) {
1.785 + g_warning ("GstFlow ERROR");
1.786 + }
1.787 + GST_PAD_STREAM_UNLOCK (pad);
1.788 +}
1.789 +
1.790 +static void
1.791 +update_volume (GstPlayBinMaemo *pbm)
1.792 +{
1.793 + if (pbm->volume_element != NULL) {
1.794 + if (pbm->volume > 0) {
1.795 + g_object_set (G_OBJECT (pbm->volume_element),
1.796 + "volume", pbm->volume,
1.797 + NULL);
1.798 + } else {
1.799 + g_object_set (G_OBJECT (pbm->volume_element),
1.800 + "mute", TRUE,
1.801 + NULL);
1.802 + }
1.803 + }
1.804 +}
1.805 +
1.806 +static void
1.807 +update_xid (GstPlayBinMaemo *pbm)
1.808 +{
1.809 + if ((pbm->sink_video != NULL) &&
1.810 + (pbm->xid != -1) &&
1.811 + (GST_IS_X_OVERLAY (pbm->sink_video))) {
1.812 + XGCValues values;
1.813 + Display *disp;
1.814 + g_object_set (G_OBJECT (pbm->sink_video),
1.815 + "force-aspect-ratio", TRUE, NULL);
1.816 + g_debug ("Update XID to %ld", pbm->xid);
1.817 +
1.818 + gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (pbm->sink_video),
1.819 + pbm->xid);
1.820 + }
1.821 +}
1.822 +
1.823 +static gboolean
1.824 +plugin_init(GstPlugin * plugin)
1.825 +{
1.826 +#ifdef ENABLE_NLS
1.827 + setlocale(LC_ALL, "");
1.828 + bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
1.829 +#endif /* ENABLE_NLS */
1.830 +
1.831 + if (!gst_element_register(plugin, "playbinmaemo", GST_RANK_SECONDARY,
1.832 + GST_TYPE_PLAY_BIN_MAEMO)) {
1.833 + return FALSE;
1.834 + }
1.835 +
1.836 + return TRUE;
1.837 +}
1.838 +
1.839 +GST_PLUGIN_DEFINE(GST_VERSION_MAJOR,
1.840 + GST_VERSION_MINOR,
1.841 + "playbinmaemo",
1.842 + "Demuxes and muxes audio and video",
1.843 + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME,
1.844 + GST_PACKAGE_ORIGIN)