[svn r851] Bug #1790620 fixed. COPYING file updated to the correct license (LGPL)
2 * Copyright (C) <2007> Renato Araujo Oliveira Filho <renato.filho@indt.org.br>
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.
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.
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.
24 #include <glib/gi18n.h>
27 #include <gst/gsterror.h>
28 #include <gst/gstplugin.h>
29 #include <gst/interfaces/xoverlay.h>
31 //#include <gst/pbutils/pbutils.h>
32 #include "gstplaybinmaemo.h"
35 GST_DEBUG_CATEGORY_STATIC (gst_play_bin_maemo_debug);
36 #define GST_CAT_DEFAULT gst_play_bin_maemo_debug
38 #define DEFAULT_VOLUME 1.0
39 #define DEFAULT_XID -1
47 ARG_QUEUE_MIN_THRESHOLD,
54 static const GstElementDetails gst_play_bin_maemo_details =
55 GST_ELEMENT_DETAILS("playbinmaemo",
57 "Autoplug and play media from an uri used on maemo plataform",
58 "Renato Araujo Oliveira Filho <renato.filho@indt.org.br>");
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,
75 static GstPad *find_sink_pad (GstElement * element);
76 static void update_volume (GstPlayBinMaemo *pbm,
78 static void update_xid (GstPlayBinMaemo *pbm);
79 static void new_decoded_pad_cb (GstElement *object,
83 static void removed_decoded_pad_cb (GstElement *object,
86 static void unknown_type_cb (GstElement *object,
90 static gboolean autoplug_continue_cb (GstElement* object,
93 static gboolean add_element (GstPlayBinMaemo *pbm,
95 static void clear_elements (GstPlayBinMaemo *pbm);
96 static int x_error_handler (Display *display,
99 GST_BOILERPLATE(GstPlayBinMaemo, gst_play_bin_maemo, GstPipeline, GST_TYPE_PIPELINE)
103 gst_play_bin_maemo_base_init (gpointer klass)
105 GstElementClass *element_class = GST_ELEMENT_CLASS(klass);
107 gst_element_class_set_details (element_class, &gst_play_bin_maemo_details);
111 gst_play_bin_maemo_class_init (GstPlayBinMaemoClass * klass)
113 GObjectClass *gobject_klass;
114 GstElementClass *gstelement_klass;
115 GstBinClass *gstbin_klass;
117 gobject_klass = (GObjectClass *) klass;
118 gstelement_klass = (GstElementClass *) klass;
119 gstbin_klass = (GstBinClass *) klass;
121 parent_class = g_type_class_peek_parent (klass);
123 gobject_klass->set_property = gst_play_bin_maemo_set_property;
124 gobject_klass->get_property = gst_play_bin_maemo_get_property;
126 g_object_class_install_property (gobject_klass, ARG_URI,
127 g_param_spec_string ("uri", "URI", "URI of the media to play",
128 NULL, G_PARAM_READWRITE));
130 g_object_class_install_property (gobject_klass, ARG_VOLUME,
131 g_param_spec_double ("volume", "Audio volume", "volume",
132 0.0, 10.0, DEFAULT_VOLUME, G_PARAM_READWRITE));
134 g_object_class_install_property (gobject_klass, ARG_XID,
135 g_param_spec_long ("xid", "xid", "X windown ID",
136 -1, G_MAXLONG, DEFAULT_XID, G_PARAM_READWRITE));
138 g_object_class_install_property (gobject_klass, ARG_SOURCE,
139 g_param_spec_object ("source", "Source", "Source element",
140 GST_TYPE_ELEMENT, G_PARAM_READABLE));
142 g_object_class_install_property (gobject_klass, ARG_PARSE_METADATA,
143 g_param_spec_boolean ("parse-metadata", "Parse Metadata", "Parse metadata info",
144 TRUE, G_PARAM_READWRITE));
147 GST_DEBUG_CATEGORY_INIT (gst_play_bin_maemo_debug, "playbinmaemo", 0,
150 gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_play_bin_maemo_dispose);
151 gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_play_bin_maemo_finalize);
153 gstelement_klass->change_state =
154 GST_DEBUG_FUNCPTR (gst_play_bin_maemo_change_state);
158 gst_play_bin_maemo_init (GstPlayBinMaemo * play_bin_maemo, GstPlayBinMaemoClass *class)
162 play_bin_maemo->uri = NULL;
163 play_bin_maemo->source = NULL;
165 play_bin_maemo->volume = DEFAULT_VOLUME;
166 play_bin_maemo->xid = DEFAULT_XID;
167 play_bin_maemo->parse_metadata = TRUE;
169 factories = gst_default_registry_feature_filter (
170 (GstPluginFeatureFilter) factory_filter_sinks,
171 FALSE, play_bin_maemo);
173 play_bin_maemo->factories = g_list_sort (factories,
174 (GCompareFunc) compare_ranks);
178 gst_play_bin_maemo_dispose (GObject * object)
180 GstPlayBinMaemo *play_bin_maemo;
182 play_bin_maemo = GST_PLAY_BIN_MAEMO (object);
183 g_free (play_bin_maemo->uri);
184 play_bin_maemo->uri = NULL;
186 G_OBJECT_CLASS (parent_class)->dispose (object);
190 gst_play_bin_maemo_finalize (GObject * object)
192 clear_elements (GST_PLAY_BIN_MAEMO (object));
193 G_OBJECT_CLASS (parent_class)->finalize (object);
197 array_has_value (const gchar * values[], const gchar * value)
201 for (i = 0; values[i]; i++) {
202 if (g_str_has_prefix (value, values[i]))
208 /* list of URIs that we consider to be streams and that need buffering.
209 * We have no mechanism yet to figure this out with a query. */
210 static const gchar *stream_uris[] = { "http://", "mms://", "mmsh://",
211 "mmsu://", "mmst://", NULL
214 /* blacklisted URIs, we know they will always fail. */
215 static const gchar *blacklisted_uris[] = { NULL };
217 /* 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
225 /* mime types we consider raw media */
226 static const gchar *raw_mimes[] = {
227 "audio/x-raw", "video/x-raw", NULL
230 #define IS_STREAM_URI(uri) (array_has_value (stream_uris, uri))
231 #define IS_BLACKLISTED_URI(uri) (array_has_value (blacklisted_uris, uri))
232 #define IS_NO_MEDIA_MIME(mime) (array_has_value (no_media_mimes, mime))
233 #define IS_RAW_MIME(mime) (array_has_value (raw_mimes, mime))
236 * Generate and configure a source element.
239 gen_source_element (GstPlayBinMaemo * play_bin_maemo)
243 if (!play_bin_maemo->uri)
246 if (!gst_uri_is_valid (play_bin_maemo->uri))
249 if (IS_BLACKLISTED_URI (play_bin_maemo->uri))
250 goto uri_blacklisted;
252 source = gst_element_make_from_uri (GST_URI_SRC, play_bin_maemo->uri, "source");
256 play_bin_maemo->is_stream = IS_STREAM_URI (play_bin_maemo->uri);
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),
263 g_object_set (source, "iradio-mode", TRUE, NULL);
270 GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, NOT_FOUND,
271 (_("No URI specified to play from.")), (NULL));
276 GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, NOT_FOUND,
277 (_("Invalid URI \"%s\"."), play_bin_maemo->uri), (NULL));
282 GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, FAILED,
283 (_("RTSP streams cannot be played yet.")), (NULL));
288 gchar *prot = gst_uri_get_protocol (play_bin_maemo->uri);
290 /* whoops, could not create the source element, dig a little deeper to
291 * figure out what might be wrong. */
296 gst_element_post_message (GST_ELEMENT (play_bin_maemo),
297 gst_missing_uri_source_message_new (GST_ELEMENT (play_bin_maemo),
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));
315 prepare_elements (GstPlayBinMaemo *pbm)
320 decoder = gst_element_factory_make ("decodebin2", "decode");
321 add_element (pbm, decoder);
322 g_signal_connect (G_OBJECT (decoder),
324 G_CALLBACK (autoplug_continue_cb),
327 g_signal_connect (G_OBJECT (decoder),
329 G_CALLBACK (unknown_type_cb),
332 g_signal_connect (G_OBJECT (decoder),
334 G_CALLBACK (new_decoded_pad_cb),
337 g_signal_connect (G_OBJECT (decoder),
338 "removed-decoded-pad",
339 G_CALLBACK (removed_decoded_pad_cb),
343 queue = gst_element_factory_make ("queue", NULL);
344 add_element (pbm, queue);
346 if (gst_element_link_many (pbm->source, queue, decoder, NULL) == FALSE) {
347 GST_WARNING ("FAIL TO LINK SRC WITH DECODEBIN2");
352 setup_source (GstPlayBinMaemo *pbm)
354 if (!pbm->need_rebuild)
357 clear_elements (pbm);
359 GST_DEBUG_OBJECT (pbm, "setup source");
361 pbm->has_metadata = FALSE;
363 /* create and configure an element that can handle the uri */
364 if (!(pbm->source = gen_source_element (pbm)))
367 add_element (pbm, pbm->source);
371 if (verify_src_have_sink (pbm)) {
372 /* source can be linked with sinks directly */
377 prepare_elements (pbm);
386 gst_play_bin_maemo_set_property (GObject *object,
391 GstPlayBinMaemo *play_bin_maemo;
393 g_return_if_fail (GST_IS_PLAY_BIN_MAEMO (object));
395 play_bin_maemo = GST_PLAY_BIN_MAEMO (object);
400 const gchar *uri = g_value_get_string (value);
403 GST_WARNING ("cannot set NULL uri");
406 /* if we have no previous uri, or the new uri is different from the
408 if (play_bin_maemo->uri == NULL || strcmp (play_bin_maemo->uri, uri) != 0) {
409 g_free (play_bin_maemo->uri);
410 play_bin_maemo->uri = g_strdup (uri);
412 GST_DEBUG ("setting new uri to %s", uri);
414 play_bin_maemo->need_rebuild = TRUE;
419 update_volume(play_bin_maemo, g_value_get_double (value));
424 xid = g_value_get_long (value);
425 if (play_bin_maemo->xid != xid)
427 play_bin_maemo->xid = xid;
428 update_xid (play_bin_maemo);
432 case ARG_PARSE_METADATA:
433 play_bin_maemo->parse_metadata = g_value_get_boolean (value);
436 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
442 gst_play_bin_maemo_get_property (GObject * object,
447 GstPlayBinMaemo *play_bin_maemo;
449 g_return_if_fail (GST_IS_PLAY_BIN_MAEMO (object));
451 play_bin_maemo = GST_PLAY_BIN_MAEMO (object);
455 g_value_set_string (value, play_bin_maemo->uri);
458 g_value_set_object (value, play_bin_maemo->source);
461 g_value_set_double (value, play_bin_maemo->volume);
464 g_value_set_long (value, play_bin_maemo->xid);
466 case ARG_PARSE_METADATA:
467 g_value_set_boolean (value, play_bin_maemo->parse_metadata);
470 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
475 static GstStateChangeReturn
476 gst_play_bin_maemo_change_state (GstElement * element,
477 GstStateChange transition)
479 GstStateChangeReturn ret;
480 GstPlayBinMaemo *play_bin_maemo;
482 play_bin_maemo = GST_PLAY_BIN_MAEMO (element);
484 switch (transition) {
485 case GST_STATE_CHANGE_READY_TO_PAUSED:
486 if (!setup_source (play_bin_maemo))
493 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
495 switch (transition) {
496 case GST_STATE_CHANGE_READY_TO_PAUSED:
497 if (ret == GST_STATE_CHANGE_FAILURE) {
498 play_bin_maemo->need_rebuild = TRUE;
499 return GST_STATE_CHANGE_FAILURE;
502 /* clean-up in both cases, READY=>NULL clean-up is if there was an error */
503 case GST_STATE_CHANGE_PAUSED_TO_READY:
504 case GST_STATE_CHANGE_READY_TO_NULL:
505 play_bin_maemo->need_rebuild = TRUE;
506 clear_elements (play_bin_maemo);
516 play_bin_maemo->need_rebuild = TRUE;
518 return GST_STATE_CHANGE_FAILURE;
523 factory_filter_sinks (GstPluginFeature *feature,
524 GstPlayBinMaemo *pbm)
529 if (!GST_IS_ELEMENT_FACTORY (feature))
532 klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature));
534 if ((strstr (klass, "Sink/Video") == NULL) && (strstr (klass, "Sink/Audio") == NULL))
537 GST_DEBUG_OBJECT (pbm, "Filtered: %s",
538 gst_element_factory_get_longname ((GST_ELEMENT_FACTORY (feature))));
539 rank = gst_plugin_feature_get_rank (feature);
540 if (rank < GST_RANK_MARGINAL)
547 compare_ranks (GstPluginFeature * f1,
548 GstPluginFeature * f2)
551 const gchar *rname1, *rname2;
553 diff = gst_plugin_feature_get_rank (f2) - gst_plugin_feature_get_rank (f1);
557 rname1 = gst_plugin_feature_get_name (f1);
558 rname2 = gst_plugin_feature_get_name (f2);
560 diff = strcmp (rname2, rname1);
567 find_compatibles (GstPlayBinMaemo *pbm,
571 GList *to_try = NULL;
573 /* loop over all the factories */
574 for (factories = pbm->factories; factories; factories = g_list_next (factories)) {
575 GstElementFactory *factory = GST_ELEMENT_FACTORY (factories->data);
576 const GList *templates;
579 /* get the templates from the element factory */
580 templates = gst_element_factory_get_static_pad_templates (factory);
581 for (walk = (GList *) templates; walk; walk = g_list_next (walk)) {
582 GstStaticPadTemplate *templ = walk->data;
584 /* we only care about the sink templates */
585 if (templ->direction == GST_PAD_SINK) {
589 /* try to intersect the caps with the caps of the template */
590 tmpl_caps = gst_static_caps_get (&templ->static_caps);
592 intersect = gst_caps_intersect (caps, tmpl_caps);
594 gst_caps_unref (tmpl_caps);
596 /* check if the intersection is empty */
597 if (!gst_caps_is_empty (intersect)) {
598 /* non empty intersection, we can use this element */
599 to_try = g_list_prepend (to_try, factory);
600 gst_caps_unref (intersect);
603 gst_caps_unref (intersect);
607 to_try = g_list_reverse (to_try);
613 autoplug_continue_cb (GstElement* object,
619 GstPlayBinMaemo *pbm;
621 pbm = GST_PLAY_BIN_MAEMO (user_data);
623 //TODO: fix this to work with all metadata elements
624 if (pbm->parse_metadata) {
625 gchar *caps_str = gst_caps_to_string (caps);
626 if ((strstr (caps_str, "id3") != NULL) &&
627 (pbm->has_metadata == FALSE)) {
630 pbm->has_metadata = TRUE;
636 comp = find_compatibles (GST_PLAY_BIN_MAEMO (user_data), caps);
646 unknown_type_cb (GstElement *object,
651 GST_DEBUG ("unknown_type_cb: %s", gst_caps_to_string (caps));
655 find_sink_pad (GstElement * element)
661 it = gst_element_iterate_sink_pads (element);
663 if ((gst_iterator_next (it, &point)) == GST_ITERATOR_OK)
664 pad = (GstPad *) point;
666 gst_iterator_free (it);
672 create_element (GstPlayBinMaemo *pbm,
673 GstElementFactory *factory)
676 GstElement *bin = NULL;
680 element = gst_element_factory_create (factory, NULL);
684 bin = gst_bin_new (NULL);
688 queue = gst_element_factory_make ("queue", NULL);
689 gst_bin_add (GST_BIN (bin), queue);
691 if (strstr (gst_element_factory_get_klass (factory), "Sink/Video") != NULL) {
692 GstElement *colorspace;
694 colorspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
695 if (colorspace == NULL)
698 gst_bin_add (GST_BIN (bin), colorspace);
699 if (gst_element_link (queue, colorspace) == FALSE) {
700 GST_WARNING_OBJECT (pbm, "Failed to link queue and colorspace");
701 gst_element_set_state (colorspace, GST_STATE_NULL);
702 gst_object_unref (colorspace);
706 gst_bin_add (GST_BIN (bin), element);
707 if (gst_element_link (colorspace, element) == FALSE) {
708 GST_WARNING_OBJECT (pbm, "Failed to link colorspace and sink video: %s",
709 GST_ELEMENT_NAME (element));
710 gst_element_set_state (colorspace, GST_STATE_NULL);
711 gst_object_unref (colorspace);
715 pbm->video_sink = element;
718 } else if (strstr (gst_element_factory_get_klass (factory), "Sink/Audio") != NULL) {
719 GParamSpec *vol_spec;
723 vol_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (element), "volume");
725 if (vol_spec == NULL) {
729 conv = gst_element_factory_make ("audioconvert", "aconv");
733 gst_bin_add (GST_BIN_CAST (bin), conv);
735 gst_element_link (queue, conv);
737 volume = gst_element_factory_make ("volume", "volume");
741 gst_bin_add (GST_BIN (bin), volume);
742 if (gst_element_link (conv, volume) == FALSE) {
743 GST_WARNING_OBJECT (pbm, "Failed to link queue and volume");
744 gst_element_set_state (volume, GST_STATE_NULL);
745 gst_object_unref (volume);
751 g_param_spec_unref (vol_spec);
754 gst_bin_add (GST_BIN (bin), element);
755 if (gst_element_link (prev, element) == FALSE) {
756 GST_WARNING_OBJECT (pbm, "Failed to link volume and sink audio: %s", GST_ELEMENT_NAME (element));
758 gst_element_set_state (prev, GST_STATE_NULL);
759 gst_object_unref (prev);
763 pbm->volume_element = (prev != queue) ? prev : element;
764 update_volume (pbm, pbm->volume);
767 pad = gst_element_get_pad (queue, "sink");
768 gst_element_add_pad (bin, gst_ghost_pad_new ("sink", pad));
769 gst_object_unref (pad);
774 GST_WARNING_OBJECT (pbm, "Error creating pipeline");
776 gst_element_set_state (bin, GST_STATE_NULL);
777 gst_object_unref (bin);
783 new_decoded_pad_cb (GstElement *object,
792 GstPlayBinMaemo *pbm;
794 pbm = GST_PLAY_BIN_MAEMO (user_data);
795 caps = gst_pad_get_caps (pad);
797 GST_DEBUG_OBJECT (pbm, "new_decoded_pad_cb: %s", gst_caps_to_string (caps));
799 comp = find_compatibles (GST_PLAY_BIN_MAEMO (user_data), caps);
802 GST_WARNING ("flow error: dont find comaptible");
806 GST_PAD_STREAM_LOCK (pad);
809 for (walk=comp; walk != NULL; walk = walk->next) {
810 GstElementFactory *factory = (GstElementFactory *) walk->data;
812 GstPad *sinkpad = NULL;
815 if ((element = create_element (pbm, factory)) == NULL) {
816 GST_WARNING_OBJECT (pbm, "Could not create an element from %s",
817 gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
821 if (!(sinkpad = find_sink_pad (element))) {
822 GST_WARNING_OBJECT (pbm, "Element %s doesn't have a sink pad", GST_ELEMENT_NAME (element));
823 gst_object_unref (element);
827 if (!(add_element (GST_PLAY_BIN_MAEMO (user_data), element))) {
828 GST_WARNING_OBJECT (pbm, "Couldn't add element %s to bin", GST_ELEMENT_NAME (element));
829 gst_object_unref (sinkpad);
830 gst_object_unref (element);
834 if ((gst_element_set_state (element, GST_STATE_READY))
835 == GST_STATE_CHANGE_FAILURE) {
836 GST_WARNING_OBJECT (pbm, "Couldn't set %s to READY", GST_ELEMENT_NAME (element));
837 gst_object_unref (sinkpad);
838 gst_bin_remove (GST_BIN (user_data), element);
842 if (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK) {
843 GST_WARNING_OBJECT (pbm, "Link failed on pad %s:%s", GST_DEBUG_PAD_NAME (sinkpad));
844 gst_element_set_state (element, GST_STATE_NULL);
845 gst_object_unref (sinkpad);
846 gst_bin_remove (GST_BIN (user_data), element);
850 gst_object_unref (sinkpad);
852 if ((gst_element_set_state (element, GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE) {
853 gst_element_set_state (element, GST_STATE_NULL);
854 gst_bin_remove (GST_BIN (user_data), element);
863 if (linked == FALSE) {
864 g_debug ("GstFlow Error");
865 GST_WARNING ("GstFlow ERROR");
867 GST_PAD_STREAM_UNLOCK (pad);
871 removed_decoded_pad_cb (GstElement *object,
877 GST_DEBUG("removed_decoded_pad_cb");
879 sink = gst_pad_get_parent_element (pad);
882 gst_bin_remove (GST_BIN (user_data), sink);
886 convert_volume_base (GstPlayBinMaemo *pbm, gfloat volume)
888 GValue value = { 0, };
889 GValue *converted_vol = g_new0(GValue, 1);
891 GParamSpec* vol_spec = g_object_class_find_property (
892 G_OBJECT_GET_CLASS (pbm->volume_element), "volume");
894 g_value_init (&value, vol_spec->value_type);
895 g_value_init (converted_vol, vol_spec->value_type);
897 g_object_get_property (G_OBJECT (pbm->volume_element), "volume", &value);
899 /* convert volume from double to int range if needed */
900 switch (G_VALUE_TYPE (&value)) {
903 GParamSpecUInt *puint = G_PARAM_SPEC_UINT (vol_spec);
904 guint scale = puint->maximum - puint->minimum;
905 guint vol_guint = (guint) ((scale * volume) + puint->minimum);
907 GST_WARNING ("Range: %u - %u, Converted: %u",
908 puint->minimum, puint->maximum, vol_guint);
909 g_value_set_uint (converted_vol, vol_guint);
914 GParamSpecInt *pint = G_PARAM_SPEC_INT (vol_spec);
915 gint scale = pint->maximum - pint->minimum;
916 gint vol_gint = (gint) ((scale * volume) + pint->minimum);
918 GST_WARNING ("Range: %d - %d, Converted: %d",
919 pint->minimum, pint->maximum, vol_gint);
920 g_value_set_int (converted_vol, vol_gint);
926 GST_WARNING ("Default converted to float: %f", volume);
927 g_value_set_double (converted_vol, volume);
931 GST_WARNING ("Dont know how to convert volume");
934 return converted_vol;
938 update_volume (GstPlayBinMaemo *pbm, gfloat volume)
940 pbm->volume = volume;
941 if (pbm->volume_element) {
942 GValue *converted_vol = convert_volume_base (pbm, volume);
943 g_object_set_property (G_OBJECT (pbm->volume_element), "volume",
945 g_value_unset (converted_vol);
950 update_xid (GstPlayBinMaemo *pbm)
952 if ((pbm->video_sink != NULL) && (pbm->xid != -1) &&
953 (GST_IS_X_OVERLAY (pbm->video_sink))) {
955 g_object_set (G_OBJECT (pbm->video_sink),
956 "force-aspect-ratio", TRUE, NULL);
958 display = XOpenDisplay(NULL);
960 XMapRaised(display, pbm->xid);
961 XSync (display, FALSE);
963 XSetErrorHandler(x_error_handler);
965 gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (pbm->video_sink),
971 x_error_handler(Display *display,
974 GST_DEBUG ("In x error handler:");
976 switch (event->error_code) {
978 GST_DEBUG ("got bad window");
981 GST_DEBUG ("got bad drawable");
984 GST_DEBUG ("got bad gc");
987 GST_DEBUG ("unhandled x error = %d", event->error_code);
994 add_element (GstPlayBinMaemo *pbm,
997 if (gst_bin_add (GST_BIN (pbm), child)) {
998 pbm->elements = g_list_append (pbm->elements, child);
1005 clear_elements (GstPlayBinMaemo *pbm)
1009 walk = pbm->elements;
1011 for (; walk != NULL; walk = walk->next) {
1012 GstElement *e = GST_ELEMENT (walk->data);
1014 gst_element_set_state (e, GST_STATE_NULL);
1015 gst_bin_remove (GST_BIN (pbm), e);
1018 g_list_free (pbm->elements);
1019 pbm->elements = NULL;
1021 pbm->volume_element = NULL;
1022 pbm->video_sink = NULL;
1026 plugin_init(GstPlugin * plugin)
1029 setlocale(LC_ALL, "");
1030 bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
1031 #endif /* ENABLE_NLS */
1033 if (!gst_element_register(plugin, "playbinmaemo", GST_RANK_SECONDARY,
1034 GST_TYPE_PLAY_BIN_MAEMO)) {
1041 GST_PLUGIN_DEFINE(GST_VERSION_MAJOR,
1044 "A playbin element that uses decodebin2 for automatic playback of audio and video",
1045 plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME,