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,
91 static gboolean autoplug_continue_cb (GstElement* object,
95 static gboolean add_element (GstPlayBinMaemo *pbm,
97 static void clear_elements (GstPlayBinMaemo *pbm);
98 static int x_error_handler (Display *display,
101 GST_BOILERPLATE(GstPlayBinMaemo, gst_play_bin_maemo, GstPipeline, GST_TYPE_PIPELINE)
105 gst_play_bin_maemo_base_init (gpointer klass)
107 GstElementClass *element_class = GST_ELEMENT_CLASS(klass);
109 gst_element_class_set_details (element_class, &gst_play_bin_maemo_details);
113 gst_play_bin_maemo_class_init (GstPlayBinMaemoClass * klass)
115 GObjectClass *gobject_klass;
116 GstElementClass *gstelement_klass;
117 GstBinClass *gstbin_klass;
119 gobject_klass = (GObjectClass *) klass;
120 gstelement_klass = (GstElementClass *) klass;
121 gstbin_klass = (GstBinClass *) klass;
123 parent_class = g_type_class_peek_parent (klass);
125 gobject_klass->set_property = gst_play_bin_maemo_set_property;
126 gobject_klass->get_property = gst_play_bin_maemo_get_property;
128 g_object_class_install_property (gobject_klass, ARG_URI,
129 g_param_spec_string ("uri", "URI", "URI of the media to play",
130 NULL, G_PARAM_READWRITE));
132 g_object_class_install_property (gobject_klass, ARG_VOLUME,
133 g_param_spec_double ("volume", "Audio volume", "volume",
134 0.0, 10.0, DEFAULT_VOLUME, G_PARAM_READWRITE));
136 g_object_class_install_property (gobject_klass, ARG_XID,
137 g_param_spec_long ("xid", "xid", "X windown ID",
138 -1, G_MAXLONG, DEFAULT_XID, G_PARAM_READWRITE));
140 g_object_class_install_property (gobject_klass, ARG_SOURCE,
141 g_param_spec_object ("source", "Source", "Source element",
142 GST_TYPE_ELEMENT, G_PARAM_READABLE));
144 g_object_class_install_property (gobject_klass, ARG_PARSE_METADATA,
145 g_param_spec_boolean ("parse-metadata", "Parse Metadata", "Parse metadata info",
146 TRUE, G_PARAM_READWRITE));
149 GST_DEBUG_CATEGORY_INIT (gst_play_bin_maemo_debug, "playbinmaemo", 0,
152 gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_play_bin_maemo_dispose);
153 gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_play_bin_maemo_finalize);
155 gstelement_klass->change_state =
156 GST_DEBUG_FUNCPTR (gst_play_bin_maemo_change_state);
160 gst_play_bin_maemo_init (GstPlayBinMaemo * play_bin_maemo, GstPlayBinMaemoClass *class)
164 play_bin_maemo->uri = NULL;
165 play_bin_maemo->source = NULL;
167 play_bin_maemo->volume = DEFAULT_VOLUME;
168 play_bin_maemo->xid = DEFAULT_XID;
169 play_bin_maemo->parse_metadata = TRUE;
171 factories = gst_default_registry_feature_filter (
172 (GstPluginFeatureFilter) factory_filter_sinks,
173 FALSE, play_bin_maemo);
175 play_bin_maemo->factories = g_list_sort (factories,
176 (GCompareFunc) compare_ranks);
180 gst_play_bin_maemo_dispose (GObject * object)
182 GstPlayBinMaemo *play_bin_maemo;
184 play_bin_maemo = GST_PLAY_BIN_MAEMO (object);
185 g_free (play_bin_maemo->uri);
186 play_bin_maemo->uri = NULL;
187 clear_elements (GST_PLAY_BIN_MAEMO (object));
189 G_OBJECT_CLASS (parent_class)->dispose (object);
193 gst_play_bin_maemo_finalize (GObject * object)
195 G_OBJECT_CLASS (parent_class)->finalize (object);
199 array_has_value (const gchar * values[], const gchar * value)
203 for (i = 0; values[i]; i++) {
204 if (g_str_has_prefix (value, values[i]))
210 /* list of URIs that we consider to be streams and that need buffering.
211 * We have no mechanism yet to figure this out with a query. */
212 static const gchar *stream_uris[] = { "http://", "mms://", "mmsh://",
213 "mmsu://", "mmst://", NULL
216 /* blacklisted URIs, we know they will always fail. */
217 static const gchar *blacklisted_uris[] = { NULL };
219 /* mime types that we don't consider to be media types */
221 static const gchar *no_media_mimes[] = {
222 "application/x-executable", "application/x-bzip", "application/x-gzip",
223 "application/zip", "application/x-compress", NULL
227 /* mime types we consider raw media */
228 static const gchar *raw_mimes[] = {
229 "audio/x-raw", "video/x-raw", NULL
232 #define IS_STREAM_URI(uri) (array_has_value (stream_uris, uri))
233 #define IS_BLACKLISTED_URI(uri) (array_has_value (blacklisted_uris, uri))
234 #define IS_NO_MEDIA_MIME(mime) (array_has_value (no_media_mimes, mime))
235 #define IS_RAW_MIME(mime) (array_has_value (raw_mimes, mime))
238 * Generate and configure a source element.
241 gen_source_element (GstPlayBinMaemo * play_bin_maemo)
245 if (!play_bin_maemo->uri)
248 if (!gst_uri_is_valid (play_bin_maemo->uri))
251 if (IS_BLACKLISTED_URI (play_bin_maemo->uri))
252 goto uri_blacklisted;
254 source = gst_element_make_from_uri (GST_URI_SRC, play_bin_maemo->uri, "source");
258 play_bin_maemo->is_stream = IS_STREAM_URI (play_bin_maemo->uri);
260 /* make HTTP sources send extra headers so we get icecast
261 * metadata in case the stream is an icecast stream */
262 if (!strncmp (play_bin_maemo->uri, "http://", 7) &&
263 g_object_class_find_property (G_OBJECT_GET_CLASS (source),
265 g_object_set (source, "iradio-mode", TRUE, NULL);
272 GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, NOT_FOUND,
273 (_("No URI specified to play from.")), (NULL));
278 GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, NOT_FOUND,
279 (_("Invalid URI \"%s\"."), play_bin_maemo->uri), (NULL));
284 GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, FAILED,
285 (_("RTSP streams cannot be played yet.")), (NULL));
290 gchar *prot = gst_uri_get_protocol (play_bin_maemo->uri);
292 /* whoops, could not create the source element, dig a little deeper to
293 * figure out what might be wrong. */
298 gst_element_post_message (GST_ELEMENT (play_bin_maemo),
299 gst_missing_uri_source_message_new (GST_ELEMENT (play_bin_maemo),
302 desc = gst_pb_utils_get_source_description (prot);
303 GST_ELEMENT_ERROR (play_bin_maemo, CORE, MISSING_PLUGIN,
304 (_("A %s plugin is required to play this stream, but not installed."),
305 desc), ("No URI handler for %s", prot));
317 _setup_decoder (GstPlayBinMaemo *pbm, GstElement *element)
321 //GstCaps *decode_caps;
324 // all_caps = gst_caps_new_empty ();
325 g_object_get (element, "caps", &all_caps, NULL);
326 all_caps = gst_caps_copy (all_caps);
327 // gst_caps_append (all_caps, decode_caps);
329 /* loop over all the factories */
330 for (factories = pbm->factories; factories; factories = g_list_next (factories)) {
331 GstElementFactory *factory = GST_ELEMENT_FACTORY (factories->data);
332 const GList *templates;
335 /* get the templates from the element factory */
336 templates = gst_element_factory_get_static_pad_templates (factory);
337 for (walk = (GList *) templates; walk; walk = g_list_next (walk)) {
338 GstStaticPadTemplate *templ = walk->data;
340 /* we only care about the sink templates */
341 if (templ->direction == GST_PAD_SINK) {
344 /* try to intersect the caps with the caps of the template */
345 tmpl_caps = gst_static_caps_get (&templ->static_caps);
346 gst_caps_append (all_caps, gst_caps_copy (tmpl_caps));
347 gst_caps_ref (tmpl_caps);
352 g_object_set (element, "caps", all_caps, NULL);
356 prepare_elements (GstPlayBinMaemo *pbm)
361 queue = gst_element_factory_make ("queue", NULL);
362 add_element (pbm, queue);
364 decoder = gst_element_factory_make ("decodebin2", "decode");
365 _setup_decoder (pbm, decoder);
366 add_element (pbm, decoder);
368 g_signal_connect (G_OBJECT (decoder),
370 G_CALLBACK (autoplug_continue_cb),
374 g_signal_connect (G_OBJECT (decoder),
376 G_CALLBACK (unknown_type_cb),
379 g_signal_connect (G_OBJECT (decoder),
381 G_CALLBACK (new_decoded_pad_cb),
384 g_signal_connect (G_OBJECT (decoder),
385 "removed-decoded-pad",
386 G_CALLBACK (removed_decoded_pad_cb),
390 if (gst_element_link_many (pbm->source, queue, decoder, NULL) == FALSE) {
391 GST_WARNING ("FAIL TO LINK SRC WITH DECODEBIN2");
396 setup_source (GstPlayBinMaemo *pbm)
398 if (!pbm->need_rebuild)
401 clear_elements (pbm);
403 GST_DEBUG_OBJECT (pbm, "setup source");
405 pbm->has_metadata = FALSE;
407 /* create and configure an element that can handle the uri */
408 if (!(pbm->source = gen_source_element (pbm)))
411 add_element (pbm, pbm->source);
415 if (verify_src_have_sink (pbm)) {
416 /* source can be linked with sinks directly */
421 prepare_elements (pbm);
430 gst_play_bin_maemo_set_property (GObject *object,
435 GstPlayBinMaemo *play_bin_maemo;
437 g_return_if_fail (GST_IS_PLAY_BIN_MAEMO (object));
439 play_bin_maemo = GST_PLAY_BIN_MAEMO (object);
444 const gchar *uri = g_value_get_string (value);
447 GST_WARNING ("cannot set NULL uri");
450 /* if we have no previous uri, or the new uri is different from the
452 if (play_bin_maemo->uri == NULL || strcmp (play_bin_maemo->uri, uri) != 0) {
453 g_free (play_bin_maemo->uri);
454 play_bin_maemo->uri = g_strdup (uri);
456 GST_DEBUG ("setting new uri to %s", uri);
458 play_bin_maemo->need_rebuild = TRUE;
463 update_volume(play_bin_maemo, g_value_get_double (value));
468 xid = g_value_get_long (value);
469 if (play_bin_maemo->xid != xid)
471 play_bin_maemo->xid = xid;
472 update_xid (play_bin_maemo);
476 case ARG_PARSE_METADATA:
477 play_bin_maemo->parse_metadata = g_value_get_boolean (value);
480 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
486 gst_play_bin_maemo_get_property (GObject * object,
491 GstPlayBinMaemo *play_bin_maemo;
493 g_return_if_fail (GST_IS_PLAY_BIN_MAEMO (object));
495 play_bin_maemo = GST_PLAY_BIN_MAEMO (object);
499 g_value_set_string (value, play_bin_maemo->uri);
502 g_value_set_object (value, play_bin_maemo->source);
505 g_value_set_double (value, play_bin_maemo->volume);
508 g_value_set_long (value, play_bin_maemo->xid);
510 case ARG_PARSE_METADATA:
511 g_value_set_boolean (value, play_bin_maemo->parse_metadata);
514 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
519 static GstStateChangeReturn
520 gst_play_bin_maemo_change_state (GstElement * element,
521 GstStateChange transition)
523 GstStateChangeReturn ret;
524 GstPlayBinMaemo *play_bin_maemo;
526 play_bin_maemo = GST_PLAY_BIN_MAEMO (element);
528 switch (transition) {
529 case GST_STATE_CHANGE_READY_TO_PAUSED:
530 if (!setup_source (play_bin_maemo))
537 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
539 switch (transition) {
540 case GST_STATE_CHANGE_READY_TO_PAUSED:
541 if (ret == GST_STATE_CHANGE_FAILURE) {
542 play_bin_maemo->need_rebuild = TRUE;
543 return GST_STATE_CHANGE_FAILURE;
546 /* clean-up in both cases, READY=>NULL clean-up is if there was an error */
547 case GST_STATE_CHANGE_PAUSED_TO_READY:
548 case GST_STATE_CHANGE_READY_TO_NULL:
549 play_bin_maemo->need_rebuild = TRUE;
550 clear_elements (play_bin_maemo);
560 play_bin_maemo->need_rebuild = TRUE;
562 return GST_STATE_CHANGE_FAILURE;
567 factory_filter_sinks (GstPluginFeature *feature,
568 GstPlayBinMaemo *pbm)
573 if (!GST_IS_ELEMENT_FACTORY (feature))
576 klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature));
578 if ((strstr (klass, "Sink/Video") == NULL) && (strstr (klass, "Sink/Audio") == NULL))
581 GST_DEBUG_OBJECT (pbm, "Filtered: %s",
582 gst_element_factory_get_longname ((GST_ELEMENT_FACTORY (feature))));
583 rank = gst_plugin_feature_get_rank (feature);
584 if (rank < GST_RANK_MARGINAL)
591 compare_ranks (GstPluginFeature * f1,
592 GstPluginFeature * f2)
595 const gchar *rname1, *rname2;
597 diff = gst_plugin_feature_get_rank (f2) - gst_plugin_feature_get_rank (f1);
601 rname1 = gst_plugin_feature_get_name (f1);
602 rname2 = gst_plugin_feature_get_name (f2);
604 diff = strcmp (rname2, rname1);
611 find_compatibles (GstPlayBinMaemo *pbm,
615 GList *to_try = NULL;
617 /* loop over all the factories */
618 for (factories = pbm->factories; factories; factories = g_list_next (factories)) {
619 GstElementFactory *factory = GST_ELEMENT_FACTORY (factories->data);
620 const GList *templates;
623 /* get the templates from the element factory */
624 templates = gst_element_factory_get_static_pad_templates (factory);
625 for (walk = (GList *) templates; walk; walk = g_list_next (walk)) {
626 GstStaticPadTemplate *templ = walk->data;
628 /* we only care about the sink templates */
629 if (templ->direction == GST_PAD_SINK) {
633 /* try to intersect the caps with the caps of the template */
634 tmpl_caps = gst_static_caps_get (&templ->static_caps);
636 intersect = gst_caps_intersect (caps, tmpl_caps);
638 gst_caps_unref (tmpl_caps);
640 /* check if the intersection is empty */
641 if (!gst_caps_is_empty (intersect)) {
642 /* non empty intersection, we can use this element */
643 to_try = g_list_prepend (to_try, factory);
644 gst_caps_unref (intersect);
647 gst_caps_unref (intersect);
651 to_try = g_list_reverse (to_try);
658 autoplug_continue_cb (GstElement* object,
664 GstPlayBinMaemo *pbm;
666 pbm = GST_PLAY_BIN_MAEMO (user_data);
668 //TODO: fix this to work with all metadata elements
669 if (pbm->parse_metadata) {
670 gchar *caps_str = gst_caps_to_string (caps);
671 if ((strstr (caps_str, "id3") != NULL) &&
672 (pbm->has_metadata == FALSE)) {
675 pbm->has_metadata = TRUE;
681 comp = find_compatibles (GST_PLAY_BIN_MAEMO (user_data), caps);
692 unknown_type_cb (GstElement *object,
697 GST_DEBUG ("unknown_type_cb: %s", gst_caps_to_string (caps));
701 find_sink_pad (GstElement * element)
707 it = gst_element_iterate_sink_pads (element);
709 if ((gst_iterator_next (it, &point)) == GST_ITERATOR_OK)
710 pad = (GstPad *) point;
712 gst_iterator_free (it);
718 create_element (GstPlayBinMaemo *pbm,
719 GstElementFactory *factory)
722 GstElement *bin = NULL;
726 element = gst_element_factory_create (factory, NULL);
730 bin = gst_bin_new (NULL);
734 queue = gst_element_factory_make ("queue", NULL);
735 gst_bin_add (GST_BIN (bin), queue);
737 if (strstr (gst_element_factory_get_klass (factory), "Sink/Video") != NULL) {
738 GstElement *colorspace;
740 colorspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
741 if (colorspace == NULL)
744 gst_bin_add (GST_BIN (bin), colorspace);
745 if (gst_element_link (queue, colorspace) == FALSE) {
746 GST_WARNING_OBJECT (pbm, "Failed to link queue and colorspace");
747 gst_element_set_state (colorspace, GST_STATE_NULL);
748 gst_object_unref (colorspace);
752 gst_bin_add (GST_BIN (bin), element);
753 if (gst_element_link (colorspace, element) == FALSE) {
754 GST_WARNING_OBJECT (pbm, "Failed to link colorspace and sink video: %s",
755 GST_ELEMENT_NAME (element));
756 gst_element_set_state (colorspace, GST_STATE_NULL);
757 gst_object_unref (colorspace);
761 pbm->video_sink = element;
764 } else if (strstr (gst_element_factory_get_klass (factory), "Sink/Audio") != NULL) {
765 GParamSpec *vol_spec;
766 GstElement *prev = NULL;
769 vol_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (element), "volume");
771 if (vol_spec == NULL) {
775 conv = gst_element_factory_make ("audioconvert", "aconv");
779 gst_bin_add (GST_BIN_CAST (bin), conv);
781 gst_element_link (queue, conv);
783 volume = gst_element_factory_make ("volume", "volume");
787 gst_bin_add (GST_BIN (bin), volume);
788 if (gst_element_link (conv, volume) == FALSE) {
789 GST_WARNING_OBJECT (pbm, "Failed to link queue and volume");
790 gst_element_set_state (volume, GST_STATE_NULL);
791 gst_object_unref (volume);
798 gst_bin_add (GST_BIN (bin), element);
799 if (gst_element_link (prev, element) == FALSE) {
800 GST_WARNING_OBJECT (pbm, "Failed to link volume and sink audio: %s", GST_ELEMENT_NAME (element));
802 gst_element_set_state (prev, GST_STATE_NULL);
803 gst_object_unref (prev);
807 pbm->volume_element = (prev != queue) ? prev : element;
808 update_volume (pbm, pbm->volume);
811 pad = gst_element_get_pad (queue, "sink");
812 gst_element_add_pad (bin, gst_ghost_pad_new ("sink", pad));
813 gst_object_unref (pad);
819 GST_WARNING_OBJECT (pbm, "Error creating pipeline");
821 gst_element_set_state (bin, GST_STATE_NULL);
822 gst_object_unref (bin);
828 new_decoded_pad_cb (GstElement *object,
837 GstPlayBinMaemo *pbm;
839 pbm = GST_PLAY_BIN_MAEMO (user_data);
840 caps = gst_pad_get_caps (pad);
842 GST_DEBUG_OBJECT (pbm, "new_decoded_pad_cb: %s", gst_caps_to_string (caps));
844 comp = find_compatibles (GST_PLAY_BIN_MAEMO (user_data), caps);
847 GST_WARNING ("flow error: dont find comaptible");
851 GST_PAD_STREAM_LOCK (pad);
854 for (walk=comp; walk != NULL; walk = walk->next) {
855 GstElementFactory *factory = (GstElementFactory *) walk->data;
857 GstPad *sinkpad = NULL;
860 if ((element = create_element (pbm, factory)) == NULL) {
861 GST_WARNING_OBJECT (pbm, "Could not create an element from %s",
862 gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
866 if (!(sinkpad = find_sink_pad (element))) {
867 GST_WARNING_OBJECT (pbm, "Element %s doesn't have a sink pad", GST_ELEMENT_NAME (element));
868 gst_object_unref (element);
872 if (!(add_element (GST_PLAY_BIN_MAEMO (user_data), element))) {
873 GST_WARNING_OBJECT (pbm, "Couldn't add element %s to bin", GST_ELEMENT_NAME (element));
874 gst_object_unref (sinkpad);
875 gst_object_unref (element);
879 if ((gst_element_set_state (element, GST_STATE_READY))
880 == GST_STATE_CHANGE_FAILURE) {
881 GST_WARNING_OBJECT (pbm, "Couldn't set %s to READY", GST_ELEMENT_NAME (element));
882 gst_object_unref (sinkpad);
883 gst_bin_remove (GST_BIN (user_data), element);
887 if (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK) {
888 GST_WARNING_OBJECT (pbm, "Link failed on pad %s:%s", GST_DEBUG_PAD_NAME (sinkpad));
889 gst_element_set_state (element, GST_STATE_NULL);
890 gst_object_unref (sinkpad);
891 gst_bin_remove (GST_BIN (user_data), element);
895 gst_object_unref (sinkpad);
897 if ((gst_element_set_state (element, GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE) {
898 gst_element_set_state (element, GST_STATE_NULL);
899 gst_bin_remove (GST_BIN (user_data), element);
908 if (linked == FALSE) {
909 GST_WARNING ("GstFlow ERROR");
911 GST_PAD_STREAM_UNLOCK (pad);
915 removed_decoded_pad_cb (GstElement *object,
921 GST_DEBUG("removed_decoded_pad_cb");
923 sink = gst_pad_get_parent_element (pad);
926 gst_bin_remove (GST_BIN (user_data), sink);
930 convert_volume_base (GstPlayBinMaemo *pbm, gfloat volume)
932 GValue value = { 0, };
933 GValue *converted_vol = g_new0(GValue, 1);
935 GParamSpec* vol_spec = g_object_class_find_property (
936 G_OBJECT_GET_CLASS (pbm->volume_element), "volume");
938 g_value_init (&value, vol_spec->value_type);
939 g_value_init (converted_vol, vol_spec->value_type);
941 g_object_get_property (G_OBJECT (pbm->volume_element), "volume", &value);
943 /* convert volume from double to int range if needed */
944 switch (G_VALUE_TYPE (&value)) {
947 GParamSpecUInt *puint = G_PARAM_SPEC_UINT (vol_spec);
948 guint scale = puint->maximum - puint->minimum;
949 guint vol_guint = (guint) ((scale * volume) + puint->minimum);
951 GST_WARNING ("Range: %u - %u, Converted: %u",
952 puint->minimum, puint->maximum, vol_guint);
953 g_value_set_uint (converted_vol, vol_guint);
958 GParamSpecInt *pint = G_PARAM_SPEC_INT (vol_spec);
959 gint scale = pint->maximum - pint->minimum;
960 gint vol_gint = (gint) ((scale * volume) + pint->minimum);
962 GST_WARNING ("Range: %d - %d, Converted: %d",
963 pint->minimum, pint->maximum, vol_gint);
964 g_value_set_int (converted_vol, vol_gint);
970 GST_WARNING ("Default converted to float: %f", volume);
971 g_value_set_double (converted_vol, volume);
975 GST_WARNING ("Dont know how to convert volume");
978 return converted_vol;
982 update_volume (GstPlayBinMaemo *pbm, gdouble volume)
984 pbm->volume = volume;
985 if (pbm->volume_element) {
986 GValue *converted_vol = convert_volume_base (pbm, volume);
987 g_object_set_property (G_OBJECT (pbm->volume_element), "volume",
989 g_value_unset (converted_vol);
994 update_xid (GstPlayBinMaemo *pbm)
996 if ((pbm->video_sink != NULL) && (pbm->xid != -1) &&
997 (GST_IS_X_OVERLAY (pbm->video_sink))) {
999 g_object_set (G_OBJECT (pbm->video_sink),
1000 "force-aspect-ratio", TRUE, NULL);
1002 display = XOpenDisplay(NULL);
1004 XMapRaised(display, pbm->xid);
1005 XSync (display, FALSE);
1007 XSetErrorHandler(x_error_handler);
1009 gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (pbm->video_sink),
1015 x_error_handler(Display *display,
1018 GST_DEBUG ("In x error handler:");
1020 switch (event->error_code) {
1022 GST_DEBUG ("got bad window");
1025 GST_DEBUG ("got bad drawable");
1028 GST_DEBUG ("got bad gc");
1031 GST_DEBUG ("unhandled x error = %d", event->error_code);
1038 add_element (GstPlayBinMaemo *pbm,
1041 if (gst_bin_add (GST_BIN (pbm), child)) {
1042 pbm->elements = g_list_append (pbm->elements, child);
1049 clear_elements (GstPlayBinMaemo *pbm)
1053 walk = pbm->elements;
1055 for (; walk != NULL; walk = walk->next) {
1056 GstElement *e = GST_ELEMENT (walk->data);
1058 gst_element_set_state (e, GST_STATE_NULL);
1059 gst_bin_remove (GST_BIN (pbm), e);
1062 g_list_free (pbm->elements);
1063 pbm->elements = NULL;
1065 pbm->volume_element = NULL;
1066 pbm->video_sink = NULL;
1070 plugin_init(GstPlugin * plugin)
1073 setlocale(LC_ALL, "");
1074 bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
1075 #endif /* ENABLE_NLS */
1077 if (!gst_element_register(plugin, "playbinmaemo", GST_RANK_SECONDARY,
1078 GST_TYPE_PLAY_BIN_MAEMO)) {
1085 GST_PLUGIN_DEFINE(GST_VERSION_MAJOR,
1088 "A playbin element that uses decodebin2 for automatic playback of audio and video",
1089 plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME,