diff -r 000000000000 -r e42706ada231 gst-gmyth/playbinmaemo/gstplaybinmaemo.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gst-gmyth/playbinmaemo/gstplaybinmaemo.c Sat Jul 14 17:20:54 2007 +0100 @@ -0,0 +1,841 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +//#include +#include "gstplaybinmaemo.h" + + +GST_DEBUG_CATEGORY_STATIC (gst_play_bin_maemo_debug); +#define GST_CAT_DEFAULT gst_play_bin_maemo_debug + +#define DEFAULT_VOLUME 10 +#define DEFAULT_XID -1 + +/* props */ +enum +{ + ARG_0, + ARG_URI, + ARG_QUEUE_SIZE, + ARG_QUEUE_MIN_THRESHOLD, + ARG_SOURCE, + ARG_VOLUME, + ARG_XID +}; + +static const GstElementDetails gst_play_bin_maemo_details = + GST_ELEMENT_DETAILS("Nuv demuxer", + "Generic/Bin/Player", + "Autoplug and play media from an uri used on maemo plataform", + "Renato Araujo Oliveira Filho "); + +static void gst_play_bin_maemo_dispose (GObject * object); +static void gst_play_bin_maemo_finalize (GObject * object); +static void gst_play_bin_maemo_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * spec); +static void gst_play_bin_maemo_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * spec); +static GstStateChangeReturn + gst_play_bin_maemo_change_state (GstElement *element, + GstStateChange transition); +static gboolean factory_filter_sinks (GstPluginFeature *feature, + GstPlayBinMaemo *pbm); +static gint compare_ranks (GstPluginFeature * f1, + GstPluginFeature * f2); +static GList *find_compatibles (GstPlayBinMaemo *pbm, + const GstCaps *caps); +static GstPad *find_sink_pad (GstElement * element); +static void update_volume (GstPlayBinMaemo *pbm); +static void update_xid (GstPlayBinMaemo *pbm); +static void new_decoded_pad_cb (GstElement *object, + GstPad* pad, + gboolean arg, + gpointer user_data); +static void unknown_type_cb (GstElement *object, + GstPad *pad, + GstCaps *casp, + gpointer user_data); +static gboolean autoplug_continue_cb (GstElement* object, + GstCaps* caps, + gpointer user_data); +static void decode_new_pad_cb (GstElement *element, + GObject *new_pad, + gpointer user_data); +static void queue_underrun_cb (GstElement* queue, + gpointer user_data); +static void queue_sink_underrun_cb (GstElement* queue, + gpointer user_data); +static void queue_sink_overrun_cb (GstElement* queue, + gpointer user_data); + + + + + +GST_BOILERPLATE(GstPlayBinMaemo, gst_play_bin_maemo, GstPipeline, GST_TYPE_PIPELINE) + + +static void +gst_play_bin_maemo_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS(klass); + + gst_element_class_set_details (element_class, &gst_play_bin_maemo_details); +} + +static void +gst_play_bin_maemo_class_init (GstPlayBinMaemoClass * klass) +{ + GObjectClass *gobject_klass; + GstElementClass *gstelement_klass; + GstBinClass *gstbin_klass; + + gobject_klass = (GObjectClass *) klass; + gstelement_klass = (GstElementClass *) klass; + gstbin_klass = (GstBinClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + gobject_klass->set_property = gst_play_bin_maemo_set_property; + gobject_klass->get_property = gst_play_bin_maemo_get_property; + + g_object_class_install_property (gobject_klass, ARG_URI, + g_param_spec_string ("uri", "URI", "URI of the media to play", + NULL, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_klass, ARG_VOLUME, + g_param_spec_uint ("volume", "Audio volume", "volume", + 0, 10, (guint) DEFAULT_VOLUME, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_klass, ARG_XID, + g_param_spec_long ("xid", "xid", "X windown ID", + -1, G_MAXLONG, DEFAULT_XID, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_klass, ARG_SOURCE, + g_param_spec_object ("source", "Source", "Source element", + GST_TYPE_ELEMENT, G_PARAM_READABLE)); + + GST_DEBUG_CATEGORY_INIT (gst_play_bin_maemo_debug, "playbinmaemo", 0, + "playbinmaemo"); + + gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_play_bin_maemo_dispose); + gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_play_bin_maemo_finalize); + + gstelement_klass->change_state = + GST_DEBUG_FUNCPTR (gst_play_bin_maemo_change_state); +} + +static void +gst_play_bin_maemo_init (GstPlayBinMaemo * play_bin_maemo, GstPlayBinMaemoClass *class) +{ + GList *factories; + + play_bin_maemo->uri = NULL; + play_bin_maemo->source = NULL; + + play_bin_maemo->volume = DEFAULT_VOLUME * 65535 / 10; + play_bin_maemo->xid = DEFAULT_XID; + + factories = gst_default_registry_feature_filter ((GstPluginFeatureFilter) factory_filter_sinks, + FALSE, play_bin_maemo); + + play_bin_maemo->factories = g_list_sort (factories, (GCompareFunc) compare_ranks); +} + +static void +gst_play_bin_maemo_dispose (GObject * object) +{ + GstPlayBinMaemo *play_bin_maemo; + + play_bin_maemo = GST_PLAY_BIN_MAEMO (object); + g_free (play_bin_maemo->uri); + play_bin_maemo->uri = NULL; + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_play_bin_maemo_finalize (GObject * object) +{ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +array_has_value (const gchar * values[], const gchar * value) +{ + gint i; + + for (i = 0; values[i]; i++) { + if (g_str_has_prefix (value, values[i])) + return TRUE; + } + return FALSE; +} + +/* list of URIs that we consider to be streams and that need buffering. + * We have no mechanism yet to figure this out with a query. */ +static const gchar *stream_uris[] = { "http://", "mms://", "mmsh://", + "mmsu://", "mmst://", NULL +}; + +/* blacklisted URIs, we know they will always fail. */ +static const gchar *blacklisted_uris[] = { NULL }; + +/* mime types that we don't consider to be media types */ +static const gchar *no_media_mimes[] = { + "application/x-executable", "application/x-bzip", "application/x-gzip", + "application/zip", "application/x-compress", NULL +}; + +/* mime types we consider raw media */ +static const gchar *raw_mimes[] = { + "audio/x-raw", "video/x-raw", NULL +}; + +#define IS_STREAM_URI(uri) (array_has_value (stream_uris, uri)) +#define IS_BLACKLISTED_URI(uri) (array_has_value (blacklisted_uris, uri)) +#define IS_NO_MEDIA_MIME(mime) (array_has_value (no_media_mimes, mime)) +#define IS_RAW_MIME(mime) (array_has_value (raw_mimes, mime)) + +/* + * Generate and configure a source element. + */ +static GstElement * +gen_source_element (GstPlayBinMaemo * play_bin_maemo) +{ + GstElement *source; + + if (!play_bin_maemo->uri) + goto no_uri; + + if (!gst_uri_is_valid (play_bin_maemo->uri)) + goto invalid_uri; + + if (IS_BLACKLISTED_URI (play_bin_maemo->uri)) + goto uri_blacklisted; + + source = gst_element_make_from_uri (GST_URI_SRC, play_bin_maemo->uri, + "source"); + if (!source) + goto no_source; + + play_bin_maemo->is_stream = IS_STREAM_URI (play_bin_maemo->uri); + + /* make HTTP sources send extra headers so we get icecast + * metadata in case the stream is an icecast stream */ + if (!strncmp (play_bin_maemo->uri, "http://", 7) && + g_object_class_find_property (G_OBJECT_GET_CLASS (source), + "iradio-mode")) { + g_object_set (source, "iradio-mode", TRUE, NULL); + } + return source; + + /* ERRORS */ +no_uri: + { + GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, NOT_FOUND, + (_("No URI specified to play from.")), (NULL)); + return NULL; + } +invalid_uri: + { + GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, NOT_FOUND, + (_("Invalid URI \"%s\"."), play_bin_maemo->uri), (NULL)); + return NULL; + } +uri_blacklisted: + { + GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, FAILED, + (_("RTSP streams cannot be played yet.")), (NULL)); + return NULL; + } +no_source: + { + gchar *prot = gst_uri_get_protocol (play_bin_maemo->uri); + + /* whoops, could not create the source element, dig a little deeper to + * figure out what might be wrong. */ + if (prot) { + gchar *desc; + + /* + gst_element_post_message (GST_ELEMENT (play_bin_maemo), + gst_missing_uri_source_message_new (GST_ELEMENT (play_bin_maemo), + prot)); + + desc = gst_pb_utils_get_source_description (prot); + GST_ELEMENT_ERROR (play_bin_maemo, CORE, MISSING_PLUGIN, + (_("A %s plugin is required to play this stream, but not installed."), + desc), ("No URI handler for %s", prot)); + */ + g_free (desc); + g_free (prot); + } else + goto invalid_uri; + + return NULL; + } +} + +static void +remove_source (GstPlayBinMaemo *pbm) +{ + GstElement *source = pbm->source; + + if (source) { + GST_DEBUG_OBJECT (pbm, "removing old src element"); + gst_element_set_state (source, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (pbm), source); + pbm->source = NULL; + } +} + +static void +remove_decoders (GstPlayBinMaemo *pbm) +{ + if (pbm->queue != NULL) { + gst_element_set_state (pbm->queue, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (pbm), pbm->queue); + pbm->queue = NULL; + } + + if (pbm->decoder != NULL) { + gst_element_set_state (pbm->decoder, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (pbm), pbm->decoder); + pbm->decoder = NULL; + } +} + +static void +remove_sinks (GstPlayBinMaemo *pbm) +{ + GSList *walk; + + for(walk=pbm->sinks; walk != NULL; walk = walk->next) { + GstElement *element = (GstElement *) walk->data; + + gst_element_set_state (element, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (pbm), element); + } + + g_slist_free (pbm->sinks); + pbm->sinks = NULL; +} + +static void +prepare_elements (GstPlayBinMaemo *pbm) +{ + if (pbm->decoder == NULL) { + pbm->decoder = gst_element_factory_make ("decodebin2", "decode"); + gst_bin_add (GST_BIN (pbm), pbm->decoder); + g_signal_connect (G_OBJECT (pbm->decoder), + "autoplug-continue", + G_CALLBACK (autoplug_continue_cb), + pbm); + g_signal_connect (G_OBJECT (pbm->decoder), + "unknown-type", + G_CALLBACK (unknown_type_cb), + pbm); + g_signal_connect (G_OBJECT (pbm->decoder), + "new-decoded-pad", + G_CALLBACK (new_decoded_pad_cb), + pbm); + } + + if (pbm->queue == NULL) { + pbm->queue = gst_element_factory_make ("queue", NULL); + gst_bin_add (GST_BIN (pbm), pbm->queue); + } + + if (gst_element_link_many (pbm->source, pbm->queue, pbm->decoder, NULL) == FALSE) { + g_warning ("FAIL TO LINK SRC WITH DECODEBIN2"); + } +} + +static gboolean +setup_source (GstPlayBinMaemo *pbm) +{ + if (!pbm->need_rebuild) + return TRUE; + + GST_DEBUG_OBJECT (pbm, "setup source"); + + /* delete old src */ + remove_source (pbm); + + /* create and configure an element that can handle the uri */ + if (!(pbm->source = gen_source_element (pbm))) + goto no_source; + + + gst_bin_add (GST_BIN_CAST (pbm), pbm->source); + + remove_decoders (pbm); + + remove_sinks (pbm); + +#if 0 + if (verify_src_have_sink (pbm)) { + /* source can be linked with sinks directly */ + return TRUE; + } +#endif + + prepare_elements (pbm); + + return TRUE; + +no_source: + return FALSE; +} + +static void +gst_play_bin_maemo_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GstPlayBinMaemo *play_bin_maemo; + + g_return_if_fail (GST_IS_PLAY_BIN_MAEMO (object)); + + play_bin_maemo = GST_PLAY_BIN_MAEMO (object); + + switch (prop_id) { + case ARG_URI: + { + const gchar *uri = g_value_get_string (value); + + if (uri == NULL) { + g_warning ("cannot set NULL uri"); + return; + } + /* if we have no previous uri, or the new uri is different from the + * old one, replug */ + if (play_bin_maemo->uri == NULL || strcmp (play_bin_maemo->uri, uri) != 0) { + g_free (play_bin_maemo->uri); + play_bin_maemo->uri = g_strdup (uri); + + GST_DEBUG ("setting new uri to %s", uri); + + play_bin_maemo->need_rebuild = TRUE; + } + break; + } + case ARG_VOLUME: + { + guint volume; + volume = g_value_get_uint (value); + if (volume != 0) { + volume = (guint) (65535 * volume / 10); + } + + if (play_bin_maemo->volume != volume) { + play_bin_maemo->volume = volume; + update_volume (play_bin_maemo); + } + break; + } + case ARG_XID: + { + long xid; + xid = g_value_get_long (value); + if (play_bin_maemo->xid != xid) { + play_bin_maemo->xid = xid; + update_xid (play_bin_maemo); + } + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_play_bin_maemo_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstPlayBinMaemo *play_bin_maemo; + + g_return_if_fail (GST_IS_PLAY_BIN_MAEMO (object)); + + play_bin_maemo = GST_PLAY_BIN_MAEMO (object); + + switch (prop_id) { + case ARG_URI: + g_value_set_string (value, play_bin_maemo->uri); + break; + case ARG_SOURCE: + g_value_set_object (value, play_bin_maemo->source); + break; + case ARG_VOLUME: + g_value_set_uint (value, play_bin_maemo->volume); + break; + case ARG_XID: + g_value_set_long (value, play_bin_maemo->xid); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstStateChangeReturn +gst_play_bin_maemo_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret; + GstPlayBinMaemo *play_bin_maemo; + + play_bin_maemo = GST_PLAY_BIN_MAEMO (element); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + if (!setup_source (play_bin_maemo)) + goto source_failed; + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + if (ret == GST_STATE_CHANGE_FAILURE) { + play_bin_maemo->need_rebuild = TRUE; + return GST_STATE_CHANGE_FAILURE; + } + break; + /* clean-up in both cases, READY=>NULL clean-up is if there was an error */ + case GST_STATE_CHANGE_PAUSED_TO_READY: + case GST_STATE_CHANGE_READY_TO_NULL: + play_bin_maemo->need_rebuild = TRUE; + remove_decoders (play_bin_maemo); + remove_source (play_bin_maemo); + break; + default: + break; + } + return ret; + + /* ERRORS */ +source_failed: + { + play_bin_maemo->need_rebuild = TRUE; + + return GST_STATE_CHANGE_FAILURE; + } +} + +static gboolean +factory_filter_sinks (GstPluginFeature *feature, + GstPlayBinMaemo *pbm) +{ + guint rank; + const gchar *klass; + + if (!GST_IS_ELEMENT_FACTORY (feature)) + return FALSE; + + klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature)); + + if ((strstr (klass, "Sink/Video") == NULL) && (strstr (klass, "Sink/Audio") == NULL)) + return FALSE; + + g_debug ("Fitered: %s", gst_element_factory_get_longname ((GST_ELEMENT_FACTORY (feature)))); + rank = gst_plugin_feature_get_rank (feature); + if (rank < GST_RANK_MARGINAL) + return FALSE; + + return TRUE; +} + +static gint +compare_ranks (GstPluginFeature * f1, GstPluginFeature * f2) +{ + gint diff; + const gchar *rname1, *rname2; + + diff = gst_plugin_feature_get_rank (f2) - gst_plugin_feature_get_rank (f1); + if (diff != 0) + return diff; + + rname1 = gst_plugin_feature_get_name (f1); + rname2 = gst_plugin_feature_get_name (f2); + + diff = strcmp (rname2, rname1); + + return diff; +} + + +static GList * +find_compatibles (GstPlayBinMaemo *pbm, const GstCaps *caps) +{ + GList *factories; + GList *to_try = NULL; + + /* loop over all the factories */ + for (factories = pbm->factories; factories; factories = g_list_next (factories)) { + GstElementFactory *factory = GST_ELEMENT_FACTORY (factories->data); + const GList *templates; + GList *walk; + + /* get the templates from the element factory */ + templates = gst_element_factory_get_static_pad_templates (factory); + for (walk = (GList *) templates; walk; walk = g_list_next (walk)) { + GstStaticPadTemplate *templ = walk->data; + + /* we only care about the sink templates */ + if (templ->direction == GST_PAD_SINK) { + GstCaps *intersect; + GstCaps *tmpl_caps; + + /* try to intersect the caps with the caps of the template */ + tmpl_caps = gst_static_caps_get (&templ->static_caps); + + intersect = gst_caps_intersect (caps, tmpl_caps); + gst_caps_unref (tmpl_caps); + + /* check if the intersection is empty */ + if (!gst_caps_is_empty (intersect)) { + /* non empty intersection, we can use this element */ + to_try = g_list_prepend (to_try, factory); + gst_caps_unref (intersect); + break; + } + gst_caps_unref (intersect); + } + } + } + to_try = g_list_reverse (to_try); + + return to_try; +} + + +static gboolean +autoplug_continue_cb (GstElement* object, + GstCaps* caps, + gpointer user_data) +{ + GList *comp = NULL; + gboolean ret = TRUE; + + comp = find_compatibles (GST_PLAY_BIN_MAEMO (user_data), caps); + if (comp != NULL) { + g_list_free (comp); + ret = FALSE; + } + + return ret; +} + +static void +unknown_type_cb (GstElement *object, + GstPad *pad, + GstCaps *caps, + gpointer user_data) +{ + g_debug ("unknown_type_cb: %s", gst_caps_to_string (caps)); +} + +static GstPad * +find_sink_pad (GstElement * element) +{ + GstIterator *it; + GstPad *pad = NULL; + gpointer point; + + it = gst_element_iterate_sink_pads (element); + + if ((gst_iterator_next (it, &point)) == GST_ITERATOR_OK) + pad = (GstPad *) point; + + gst_iterator_free (it); + + return pad; +} + +static void +new_decoded_pad_cb (GstElement *object, + GstPad* pad, + gboolean arg, + gpointer user_data) +{ + GList *comp = NULL; + GList *walk; + GstCaps *caps; + gboolean linked; + GstPlayBinMaemo *pbm; + + pbm = GST_PLAY_BIN_MAEMO (user_data); + caps = gst_pad_get_caps (pad); + + g_debug ("new_decoded_pad_cb: %s", gst_caps_to_string (caps)); + + comp = find_compatibles (GST_PLAY_BIN_MAEMO (user_data), caps); + + + if (comp == NULL) { + g_warning ("flow error: dont find comaptible"); + return; + } + + GST_PAD_STREAM_LOCK (pad); + + linked = FALSE; + for (walk=comp; walk != NULL; walk = walk->next) { + GstElementFactory *factory = (GstElementFactory *) walk->data; + GstElement *element; + GstPad *sinkpad; + + if ((element = gst_element_factory_create (factory, NULL)) == NULL) { + GST_WARNING_OBJECT (pbm, "Could not create an element from %s", + gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory))); + continue; + } + + if (strstr (gst_element_factory_get_klass (factory), "Sink/Video") != NULL) { + pbm->sink_video = element; + update_xid (pbm); + } else if (strstr (gst_element_factory_get_klass (factory), "Sink/Audio") != NULL) { + pbm->volume_element = element; + update_volume (pbm); + } + + if (!(gst_bin_add (GST_BIN (user_data), element))) { + GST_WARNING_OBJECT (pbm, "Couldn't set %s to READY", + GST_ELEMENT_NAME (element)); + gst_object_unref (element); + continue; + } + + if ((gst_element_set_state (element, GST_STATE_READY)) + == GST_STATE_CHANGE_FAILURE) { + gst_element_set_state (element, GST_STATE_NULL); + gst_object_unref (sinkpad); + gst_bin_remove (GST_BIN (user_data), element); + continue; + } + + if (!(sinkpad = find_sink_pad (element))) { + GST_WARNING_OBJECT (pbm, "Element %s doesn't have a sink pad", GST_ELEMENT_NAME (element)); + gst_object_unref (element); + continue; + } + + + if ((gst_pad_link (pad, sinkpad)) != GST_PAD_LINK_OK) { + GST_WARNING_OBJECT (pbm, "Link failed on pad %s:%s", + GST_DEBUG_PAD_NAME (sinkpad)); + gst_element_set_state (element, GST_STATE_NULL); + gst_object_unref (sinkpad); + gst_bin_remove (GST_BIN (user_data), element); + continue; + } + + gst_object_unref (sinkpad); + + if ((gst_element_set_state (element, GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE) { + gst_element_set_state (element, GST_STATE_NULL); + gst_bin_remove (GST_BIN (user_data), element); + continue; + } + + + pbm->sinks = g_slist_append (pbm->sinks, element); + linked = TRUE; + break; + } + + g_list_free (comp); + if (linked == FALSE) { + g_warning ("GstFlow ERROR"); + } + GST_PAD_STREAM_UNLOCK (pad); +} + +static void +update_volume (GstPlayBinMaemo *pbm) +{ + if (pbm->volume_element != NULL) { + if (pbm->volume > 0) { + g_object_set (G_OBJECT (pbm->volume_element), + "volume", pbm->volume, + NULL); + } else { + g_object_set (G_OBJECT (pbm->volume_element), + "mute", TRUE, + NULL); + } + } +} + +static void +update_xid (GstPlayBinMaemo *pbm) +{ + if ((pbm->sink_video != NULL) && + (pbm->xid != -1) && + (GST_IS_X_OVERLAY (pbm->sink_video))) { + XGCValues values; + Display *disp; + g_object_set (G_OBJECT (pbm->sink_video), + "force-aspect-ratio", TRUE, NULL); + g_debug ("Update XID to %ld", pbm->xid); + + gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (pbm->sink_video), + pbm->xid); + } +} + +static gboolean +plugin_init(GstPlugin * plugin) +{ +#ifdef ENABLE_NLS + setlocale(LC_ALL, ""); + bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); +#endif /* ENABLE_NLS */ + + if (!gst_element_register(plugin, "playbinmaemo", GST_RANK_SECONDARY, + GST_TYPE_PLAY_BIN_MAEMO)) { + return FALSE; + } + + return TRUE; +} + +GST_PLUGIN_DEFINE(GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "playbinmaemo", + "Demuxes and muxes audio and video", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, + GST_PACKAGE_ORIGIN)