diff -r 215c45290ce3 -r c517a78bf7bf gst-gmyth/playbinmaemo/gstplaybinmaemo.c --- a/gst-gmyth/playbinmaemo/gstplaybinmaemo.c Thu Aug 16 15:24:01 2007 +0100 +++ b/gst-gmyth/playbinmaemo/gstplaybinmaemo.c Wed Aug 22 17:57:16 2007 +0100 @@ -35,7 +35,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_play_bin_maemo_debug); #define GST_CAT_DEFAULT gst_play_bin_maemo_debug -#define DEFAULT_VOLUME 10 +#define DEFAULT_VOLUME 1.0 #define DEFAULT_XID -1 /* props */ @@ -73,12 +73,16 @@ 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_volume (GstPlayBinMaemo *pbm, + gfloat volume); static void update_xid (GstPlayBinMaemo *pbm); static void new_decoded_pad_cb (GstElement *object, GstPad* pad, gboolean arg, gpointer user_data); +static void removed_decoded_pad_cb (GstElement *object, + GstPad* pad, + gpointer user_data); static void unknown_type_cb (GstElement *object, GstPad *pad, GstCaps *casp, @@ -125,7 +129,7 @@ g_object_class_install_property (gobject_klass, ARG_VOLUME, g_param_spec_double ("volume", "Audio volume", "volume", - 0.0, 10.0, (gdouble) DEFAULT_VOLUME, G_PARAM_READWRITE)); + 0.0, 10.0, DEFAULT_VOLUME, G_PARAM_READWRITE)); g_object_class_install_property (gobject_klass, ARG_XID, g_param_spec_long ("xid", "xid", "X windown ID", @@ -158,14 +162,16 @@ play_bin_maemo->uri = NULL; play_bin_maemo->source = NULL; - play_bin_maemo->volume = DEFAULT_VOLUME * 65535 / 10; + play_bin_maemo->volume = DEFAULT_VOLUME; play_bin_maemo->xid = DEFAULT_XID; play_bin_maemo->parse_metadata = TRUE; - factories = gst_default_registry_feature_filter ((GstPluginFeatureFilter) factory_filter_sinks, - FALSE, play_bin_maemo); + 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); + play_bin_maemo->factories = g_list_sort (factories, + (GCompareFunc) compare_ranks); } static void @@ -328,11 +334,17 @@ G_CALLBACK (new_decoded_pad_cb), pbm); + g_signal_connect (G_OBJECT (decoder), + "removed-decoded-pad", + G_CALLBACK (removed_decoded_pad_cb), + pbm); + + queue = gst_element_factory_make ("queue", NULL); add_element (pbm, queue); if (gst_element_link_many (pbm->source, queue, decoder, NULL) == FALSE) { - g_warning ("FAIL TO LINK SRC WITH DECODEBIN2"); + GST_WARNING ("FAIL TO LINK SRC WITH DECODEBIN2"); } } @@ -388,7 +400,7 @@ const gchar *uri = g_value_get_string (value); if (uri == NULL) { - g_warning ("cannot set NULL uri"); + GST_WARNING ("cannot set NULL uri"); return; } /* if we have no previous uri, or the new uri is different from the @@ -404,23 +416,8 @@ break; } case ARG_VOLUME: - { - gdouble d_volume = 0; - guint u_volume = 0; - d_volume = g_value_get_double (value); - - g_debug ("Getting : %5.2f", d_volume); - if (d_volume != 0) { - u_volume = (guint) (65535 * d_volume); - } - - g_debug ("Converting : %d", u_volume); - if (play_bin_maemo->volume != u_volume) { - play_bin_maemo->volume = u_volume; - update_volume (play_bin_maemo); - } + update_volume(play_bin_maemo, g_value_get_double (value)); break; - } case ARG_XID: { long xid; @@ -442,8 +439,10 @@ } static void -gst_play_bin_maemo_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) +gst_play_bin_maemo_get_property (GObject * object, + guint prop_id, + GValue * value, + GParamSpec * pspec) { GstPlayBinMaemo *play_bin_maemo; @@ -459,14 +458,8 @@ g_value_set_object (value, play_bin_maemo->source); break; case ARG_VOLUME: - { - gdouble volume = 0; - if (play_bin_maemo->volume > 0) { - volume = play_bin_maemo->volume / 65535; - } - g_value_set_double (value, volume); + g_value_set_double (value, play_bin_maemo->volume); break; - } case ARG_XID: g_value_set_long (value, play_bin_maemo->xid); break; @@ -480,7 +473,8 @@ } static GstStateChangeReturn -gst_play_bin_maemo_change_state (GstElement * element, GstStateChange transition) +gst_play_bin_maemo_change_state (GstElement * element, + GstStateChange transition) { GstStateChangeReturn ret; GstPlayBinMaemo *play_bin_maemo; @@ -540,7 +534,8 @@ if ((strstr (klass, "Sink/Video") == NULL) && (strstr (klass, "Sink/Audio") == NULL)) return FALSE; - g_debug ("Filtered: %s", gst_element_factory_get_longname ((GST_ELEMENT_FACTORY (feature)))); + GST_DEBUG_OBJECT (pbm, "Filtered: %s", + gst_element_factory_get_longname ((GST_ELEMENT_FACTORY (feature)))); rank = gst_plugin_feature_get_rank (feature); if (rank < GST_RANK_MARGINAL) return FALSE; @@ -549,7 +544,8 @@ } static gint -compare_ranks (GstPluginFeature * f1, GstPluginFeature * f2) +compare_ranks (GstPluginFeature * f1, + GstPluginFeature * f2) { gint diff; const gchar *rname1, *rname2; @@ -568,7 +564,8 @@ static GList * -find_compatibles (GstPlayBinMaemo *pbm, const GstCaps *caps) +find_compatibles (GstPlayBinMaemo *pbm, + const GstCaps *caps) { GList *factories; GList *to_try = NULL; @@ -593,6 +590,7 @@ 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 */ @@ -611,7 +609,6 @@ return to_try; } - static gboolean autoplug_continue_cb (GstElement* object, GstCaps* caps, @@ -623,7 +620,7 @@ pbm = GST_PLAY_BIN_MAEMO (user_data); - //TODO: fix this for work with all metada elements + //TODO: fix this to work with all metadata elements if (pbm->parse_metadata) { gchar *caps_str = gst_caps_to_string (caps); if ((strstr (caps_str, "id3") != NULL) && @@ -651,10 +648,10 @@ GstCaps *caps, gpointer user_data) { - g_debug ("unknown_type_cb: %s", gst_caps_to_string (caps)); + GST_DEBUG ("unknown_type_cb: %s", gst_caps_to_string (caps)); } -static GstPad * +static GstPad* find_sink_pad (GstElement * element) { GstIterator *it; @@ -672,7 +669,8 @@ } static GstElement* -create_element (GstPlayBinMaemo *pbm, GstElementFactory *factory) +create_element (GstPlayBinMaemo *pbm, + GstElementFactory *factory) { GstElement *queue; GstElement *bin = NULL; @@ -681,10 +679,11 @@ element = gst_element_factory_create (factory, NULL); if (element == NULL) - return NULL; - + goto error; bin = gst_bin_new (NULL); + if (bin == NULL) + goto error; queue = gst_element_factory_make ("queue", NULL); gst_bin_add (GST_BIN (bin), queue); @@ -693,10 +692,12 @@ GstElement *colorspace; colorspace = gst_element_factory_make ("ffmpegcolorspace", NULL); + if (colorspace == NULL) + goto error; gst_bin_add (GST_BIN (bin), colorspace); if (gst_element_link (queue, colorspace) == FALSE) { - GST_WARNING_OBJECT (pbm, "Fail to link queue and colorspace"); + GST_WARNING_OBJECT (pbm, "Failed to link queue and colorspace"); gst_element_set_state (colorspace, GST_STATE_NULL); gst_object_unref (colorspace); goto error; @@ -704,7 +705,8 @@ gst_bin_add (GST_BIN (bin), element); if (gst_element_link (colorspace, element) == FALSE) { - GST_WARNING_OBJECT (pbm, "Fail to link colorspace and sink video: %s", GST_ELEMENT_NAME (element)); + GST_WARNING_OBJECT (pbm, "Failed to link colorspace and sink video: %s", + GST_ELEMENT_NAME (element)); gst_element_set_state (colorspace, GST_STATE_NULL); gst_object_unref (colorspace); goto error; @@ -719,35 +721,47 @@ prev = queue; vol_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (element), "volume"); + if (vol_spec == NULL) { + GstElement *conv; GstElement *volume; - bin = gst_bin_new (NULL); + conv = gst_element_factory_make ("audioconvert", "aconv"); + if (conv == NULL) + goto error; + + gst_bin_add (GST_BIN_CAST (bin), conv); + + gst_element_link (queue, conv); + volume = gst_element_factory_make ("volume", "volume"); + if (volume == NULL) + goto error; + gst_bin_add (GST_BIN (bin), volume); - if (gst_element_link (queue, volume) == FALSE) { - GST_WARNING_OBJECT (pbm, "Fail to link queue and volume"); + if (gst_element_link (conv, volume) == FALSE) { + GST_WARNING_OBJECT (pbm, "Failed to link queue and volume"); gst_element_set_state (volume, GST_STATE_NULL); gst_object_unref (volume); goto error; } prev = volume; + } else { g_param_spec_unref (vol_spec); } gst_bin_add (GST_BIN (bin), element); if (gst_element_link (prev, element) == FALSE) { - GST_WARNING_OBJECT (pbm, "Fail to link volume and sink audio: %s", GST_ELEMENT_NAME (element)); + GST_WARNING_OBJECT (pbm, "Failed to link volume and sink audio: %s", GST_ELEMENT_NAME (element)); if (prev != queue) { gst_element_set_state (prev, GST_STATE_NULL); gst_object_unref (prev); } goto error; } - pbm->volume_element = (prev != queue) ? prev : element; - update_volume (pbm); + update_volume (pbm, pbm->volume); } pad = gst_element_get_pad (queue, "sink"); @@ -755,7 +769,9 @@ gst_object_unref (pad); return bin; + error: + GST_WARNING_OBJECT (pbm, "Error creating pipeline"); gst_element_set_state (bin, GST_STATE_NULL); gst_object_unref (bin); @@ -778,13 +794,12 @@ 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)); + GST_DEBUG_OBJECT (pbm, "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"); + GST_WARNING ("flow error: dont find comaptible"); return; } @@ -795,51 +810,48 @@ GstElementFactory *factory = (GstElementFactory *) walk->data; GstElement *element; GstPad *sinkpad = NULL; + gint result; if ((element = create_element (pbm, factory)) == NULL) { GST_WARNING_OBJECT (pbm, "Could not create an element from %s", gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory))); - g_debug ("Could not create an element from %s", - gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory))); + 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 (!(add_element (GST_PLAY_BIN_MAEMO (user_data), element))) { - GST_WARNING_OBJECT (pbm, "Couldn't set %s to READY", GST_ELEMENT_NAME (element)); + GST_WARNING_OBJECT (pbm, "Couldn't add element %s to bin", GST_ELEMENT_NAME (element)); + gst_object_unref (sinkpad); gst_object_unref (element); continue; } if ((gst_element_set_state (element, GST_STATE_READY)) == GST_STATE_CHANGE_FAILURE) { + GST_WARNING_OBJECT (pbm, "Couldn't set %s to READY", GST_ELEMENT_NAME (element)); + gst_object_unref (sinkpad); + gst_bin_remove (GST_BIN (user_data), 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; } - if (!(sinkpad = find_sink_pad (element))) { - GST_WARNING_OBJECT (pbm, "Element %s doesn't have a sink pad", GST_ELEMENT_NAME (element)); - g_debug ("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); + gst_element_set_state (element, GST_STATE_NULL); + gst_bin_remove (GST_BIN (user_data), element); continue; } @@ -849,40 +861,106 @@ g_list_free (comp); if (linked == FALSE) { - g_warning ("GstFlow ERROR"); + g_debug ("GstFlow Error"); + GST_WARNING ("GstFlow ERROR"); } GST_PAD_STREAM_UNLOCK (pad); } static void -update_volume (GstPlayBinMaemo *pbm) +removed_decoded_pad_cb (GstElement *object, + GstPad* pad, + gpointer user_data) { - 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); + GstElement *sink; + + GST_DEBUG("removed_decoded_pad_cb"); + + sink = gst_pad_get_parent_element (pad); + + if (sink) + gst_bin_remove (GST_BIN (user_data), sink); +} + +static GValue* +convert_volume_base (GstPlayBinMaemo *pbm, gfloat volume) +{ + GValue value = { 0, }; + GValue *converted_vol = g_new0(GValue, 1); + + GParamSpec* vol_spec = g_object_class_find_property ( + G_OBJECT_GET_CLASS (pbm->volume_element), "volume"); + + g_value_init (&value, vol_spec->value_type); + g_value_init (converted_vol, vol_spec->value_type); + + g_object_get_property (G_OBJECT (pbm->volume_element), "volume", &value); + + /* convert volume from double to int range if needed */ + switch (G_VALUE_TYPE (&value)) { + case G_TYPE_UINT: + { + GParamSpecUInt *puint = G_PARAM_SPEC_UINT (vol_spec); + guint scale = puint->maximum - puint->minimum; + guint vol_guint = (guint) ((scale * volume) + puint->minimum); + + GST_WARNING ("Range: %u - %u, Converted: %u", + puint->minimum, puint->maximum, vol_guint); + g_value_set_uint (converted_vol, vol_guint); + break; } + case G_TYPE_INT: + { + GParamSpecInt *pint = G_PARAM_SPEC_INT (vol_spec); + gint scale = pint->maximum - pint->minimum; + gint vol_gint = (gint) ((scale * volume) + pint->minimum); + + GST_WARNING ("Range: %d - %d, Converted: %d", + pint->minimum, pint->maximum, vol_gint); + g_value_set_int (converted_vol, vol_gint); + break; + } + case G_TYPE_DOUBLE: + case G_TYPE_FLOAT: + { + GST_WARNING ("Default converted to float: %f", volume); + g_value_set_double (converted_vol, volume); + break; + } + default: + GST_WARNING ("Dont know how to convert volume"); + } + + return converted_vol; +} + +static void +update_volume (GstPlayBinMaemo *pbm, gfloat volume) +{ + pbm->volume = volume; + if (pbm->volume_element) { + GValue *converted_vol = convert_volume_base (pbm, volume); + g_object_set_property (G_OBJECT (pbm->volume_element), "volume", + converted_vol); + g_value_unset (converted_vol); } } static void update_xid (GstPlayBinMaemo *pbm) { - if ((pbm->video_sink != NULL) && - (pbm->xid != -1) && - (GST_IS_X_OVERLAY (pbm->video_sink))) { + if ((pbm->video_sink != NULL) && (pbm->xid != -1) && + (GST_IS_X_OVERLAY (pbm->video_sink))) { Display *display; g_object_set (G_OBJECT (pbm->video_sink), "force-aspect-ratio", TRUE, NULL); + display = XOpenDisplay(NULL); + XMapRaised(display, pbm->xid); + XSync (display, FALSE); + XSetErrorHandler(x_error_handler); - XSync (display, FALSE); gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (pbm->video_sink), pbm->xid); @@ -890,22 +968,23 @@ } static int -x_error_handler(Display *display, XErrorEvent *event) +x_error_handler(Display *display, + XErrorEvent *event) { - g_debug ("In x error handler:"); + GST_DEBUG ("In x error handler:"); switch (event->error_code) { case BadWindow: - g_debug ("got bad window"); + GST_DEBUG ("got bad window"); break; case BadDrawable: - g_debug ("got bad drawable"); + GST_DEBUG ("got bad drawable"); break; case BadGC: - g_debug ("got bad gc"); + GST_DEBUG ("got bad gc"); break; default: - g_debug ("unhandled x error = %d", event->error_code); + GST_DEBUG ("unhandled x error = %d", event->error_code); } return 0;