diff --git a/ChangeLog b/ChangeLog index e9a45393d9..5f7ff442aa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +2007-12-28 Wim Taymans + + * gst/playback/gstplaybin2.c: (gst_play_bin_class_init), + (gst_play_bin_finalize), (gst_play_bin_set_uri), + (gst_play_bin_set_suburi), (gst_play_bin_set_property), + (gst_play_bin_get_property), (pad_removed_cb), (drained_cb), + (autoplug_select_cb), (activate_group), (deactivate_group), + (setup_next_source), (save_current_group), + (gst_play_bin_change_state): + Code cleanups. + Remove next-uri, we can use the uri property just fine. + Fix some crasher. + Unref uridecodebin when switching. + Fix going to READY. + + * gst/playback/gstplaysink.c: (gst_play_sink_class_init), + (gst_play_sink_init), (gst_play_sink_dispose), + (gst_play_sink_finalize), (gst_play_sink_vis_unblocked), + (gst_play_sink_vis_blocked), (gst_play_sink_set_video_sink), + (gst_play_sink_set_audio_sink), (gst_play_sink_set_vis_plugin), + (gst_play_sink_set_property), (gst_play_sink_get_property), + (gen_video_chain), (gen_text_element), (gen_audio_chain), + (gen_vis_element), (gst_play_sink_get_mode), + (gst_play_sink_set_mode), (gst_play_sink_set_flags), + (gst_play_sink_get_flags), (gst_play_sink_request_pad), + (gst_play_sink_release_pad), (gst_play_sink_send_event_to_sink), + (gst_play_sink_change_state): + * gst/playback/gstplaysink.h: + Add some locking to make things threadsafe. + + * gst/playback/test7.c: (about_to_finish_cb): + Fix test. + 2007-12-22 Tim-Philipp Müller * gst/videoscale/gstvideoscale.c: (gst_video_scale_set_property), diff --git a/gst/playback/gstplaybin2.c b/gst/playback/gstplaybin2.c index 8cb00f6c1d..ff374cc426 100644 --- a/gst/playback/gstplaybin2.c +++ b/gst/playback/gstplaybin2.c @@ -291,6 +291,7 @@ struct _GstSourceGroup GstPlayBin *playbin; gboolean valid; /* the group has valid info to start playback */ + gboolean active; /* the group is active */ /* properties */ gchar *uri; @@ -316,6 +317,8 @@ struct _GstPlayBin GstSourceGroup *curr_group; /* pointer to the currently playing group */ GstSourceGroup *next_group; /* pointer to the next group */ + gboolean about_to_finish; /* the about-to-finish signal is emited */ + /* properties */ guint connection_speed; /* connection speed in bits/sec (0 = unknown) */ @@ -338,8 +341,6 @@ enum PROP_0, PROP_URI, PROP_SUBURI, - PROP_NEXT_URI, - PROP_NEXT_SUBURI, PROP_STREAMINFO, PROP_SOURCE, PROP_CURRENT_VIDEO, @@ -363,7 +364,7 @@ enum }; static void gst_play_bin_class_init (GstPlayBinClass * klass); -static void gst_play_bin_init (GstPlayBin * play_bin); +static void gst_play_bin_init (GstPlayBin * playbin); static void gst_play_bin_finalize (GObject * object); static void gst_play_bin_set_property (GObject * object, guint prop_id, @@ -438,12 +439,6 @@ gst_play_bin_class_init (GstPlayBinClass * klass) g_object_class_install_property (gobject_klass, PROP_SUBURI, g_param_spec_string ("suburi", ".sub-URI", "Optional URI of a subtitle", NULL, G_PARAM_READWRITE)); - g_object_class_install_property (gobject_klass, PROP_NEXT_URI, - g_param_spec_string ("next-uri", "Next URI", - "URI of the next media to play", NULL, G_PARAM_READWRITE)); - g_object_class_install_property (gobject_klass, PROP_NEXT_SUBURI, - g_param_spec_string ("next-suburi", "Next .sub-URI", - "Optional URI of a next subtitle", NULL, G_PARAM_READWRITE)); g_object_class_install_property (gobject_klass, PROP_STREAMINFO, g_param_spec_value_array ("stream-info", @@ -569,17 +564,17 @@ gst_play_bin_init (GstPlayBin * playbin) static void gst_play_bin_finalize (GObject * object) { - GstPlayBin *play_bin; + GstPlayBin *playbin; - play_bin = GST_PLAY_BIN (object); + playbin = GST_PLAY_BIN (object); - g_value_array_free (play_bin->elements); + g_value_array_free (playbin->elements); G_OBJECT_CLASS (parent_class)->finalize (object); } static void -gst_play_bin_set_uri (GstPlayBin * play_bin, const gchar * uri) +gst_play_bin_set_uri (GstPlayBin * playbin, const gchar * uri) { GstSourceGroup *group; @@ -588,8 +583,8 @@ gst_play_bin_set_uri (GstPlayBin * play_bin, const gchar * uri) return; } - GST_OBJECT_LOCK (play_bin); - group = play_bin->next_group; + GST_OBJECT_LOCK (playbin); + group = playbin->next_group; /* if we have no previous uri, or the new uri is different from the * old one, replug */ @@ -598,16 +593,16 @@ gst_play_bin_set_uri (GstPlayBin * play_bin, const gchar * uri) group->valid = TRUE; GST_DEBUG ("setting new uri to %s", uri); - GST_OBJECT_UNLOCK (play_bin); + GST_OBJECT_UNLOCK (playbin); } static void -gst_play_bin_set_suburi (GstPlayBin * play_bin, const gchar * suburi) +gst_play_bin_set_suburi (GstPlayBin * playbin, const gchar * suburi) { GstSourceGroup *group; - GST_OBJECT_LOCK (play_bin); - group = play_bin->next_group; + GST_OBJECT_LOCK (playbin); + group = playbin->next_group; if ((!suburi && !group->suburi) || (suburi && group->suburi && !strcmp (group->suburi, suburi))) @@ -619,29 +614,23 @@ gst_play_bin_set_suburi (GstPlayBin * play_bin, const gchar * suburi) GST_DEBUG ("setting new .sub uri to %s", suburi); done: - GST_OBJECT_UNLOCK (play_bin); + GST_OBJECT_UNLOCK (playbin); } static void gst_play_bin_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GstPlayBin *play_bin; + GstPlayBin *playbin; - play_bin = GST_PLAY_BIN (object); + playbin = GST_PLAY_BIN (object); switch (prop_id) { case PROP_URI: - gst_play_bin_set_uri (play_bin, g_value_get_string (value)); + gst_play_bin_set_uri (playbin, g_value_get_string (value)); break; case PROP_SUBURI: - gst_play_bin_set_suburi (play_bin, g_value_get_string (value)); - break; - case PROP_NEXT_URI: - gst_play_bin_set_uri (play_bin, g_value_get_string (value)); - break; - case PROP_NEXT_SUBURI: - gst_play_bin_set_suburi (play_bin, g_value_get_string (value)); + gst_play_bin_set_suburi (playbin, g_value_get_string (value)); break; case PROP_VIDEO_SINK: break; @@ -654,9 +643,9 @@ gst_play_bin_set_property (GObject * object, guint prop_id, case PROP_FONT_DESC: break; case PROP_CONNECTION_SPEED: - GST_OBJECT_LOCK (play_bin); - play_bin->connection_speed = g_value_get_uint (value) * 1000; - GST_OBJECT_UNLOCK (play_bin); + GST_OBJECT_LOCK (playbin); + playbin->connection_speed = g_value_get_uint (value) * 1000; + GST_OBJECT_UNLOCK (playbin); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -668,38 +657,29 @@ static void gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstPlayBin *play_bin; + GstPlayBin *playbin; - play_bin = GST_PLAY_BIN (object); + playbin = GST_PLAY_BIN (object); switch (prop_id) { case PROP_URI: - GST_OBJECT_LOCK (play_bin); - /* get the currently playing group first, then the queued one */ - if (play_bin->curr_group) - g_value_set_string (value, play_bin->curr_group->uri); + GST_OBJECT_LOCK (playbin); + /* get the currently playing group first, then the queued one, just in + * case we did not yet start playback. */ + if (playbin->curr_group) + g_value_set_string (value, playbin->curr_group->uri); else - g_value_set_string (value, play_bin->next_group->uri); - GST_OBJECT_UNLOCK (play_bin); + g_value_set_string (value, playbin->next_group->uri); + GST_OBJECT_UNLOCK (playbin); break; case PROP_SUBURI: - GST_OBJECT_LOCK (play_bin); + GST_OBJECT_LOCK (playbin); /* get the currently playing group first, then the queued one */ - if (play_bin->curr_group) - g_value_set_string (value, play_bin->curr_group->suburi); + if (playbin->curr_group) + g_value_set_string (value, playbin->curr_group->suburi); else - g_value_set_string (value, play_bin->next_group->suburi); - GST_OBJECT_UNLOCK (play_bin); - break; - case PROP_NEXT_URI: - GST_OBJECT_LOCK (play_bin); - g_value_set_string (value, play_bin->next_group->uri); - GST_OBJECT_UNLOCK (play_bin); - break; - case PROP_NEXT_SUBURI: - GST_OBJECT_LOCK (play_bin); - g_value_set_string (value, play_bin->next_group->suburi); - GST_OBJECT_UNLOCK (play_bin); + g_value_set_string (value, playbin->next_group->suburi); + GST_OBJECT_UNLOCK (playbin); break; case PROP_VIDEO_SINK: break; @@ -712,9 +692,9 @@ gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value, case PROP_FRAME: break; case PROP_CONNECTION_SPEED: - GST_OBJECT_LOCK (play_bin); - g_value_set_uint (value, play_bin->connection_speed / 1000); - GST_OBJECT_UNLOCK (play_bin); + GST_OBJECT_LOCK (playbin); + g_value_set_uint (value, playbin->connection_speed / 1000); + GST_OBJECT_UNLOCK (playbin); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -861,8 +841,11 @@ pad_removed_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group) /* unlink the pad now (can fail, the pad is unlinked before it's removed) */ gst_pad_unlink (pad, peer); - /* get selector */ + /* get selector, this can be NULL when the element is removing the pads + * because it's being disposed. */ selector = GST_ELEMENT_CAST (gst_pad_get_parent (peer)); + if (!selector) + goto no_selector; /* release the pad to the selector, this will make the selector choose a new * pad. */ @@ -878,6 +861,11 @@ not_linked: GST_DEBUG_OBJECT (playbin, "pad not linked"); return; } +no_selector: + { + GST_DEBUG_OBJECT (playbin, "selector not found"); + return; + } } /* we get called when all pads are available and we must connect the sinks to @@ -947,10 +935,16 @@ drained_cb (GstElement * decodebin, GstSourceGroup * group) GST_DEBUG_OBJECT (playbin, "about to finish in group %p", group); + /* mark use as sending out the about-to-finish signal. When the app sets a URI + * when this signal is emited, we're marking it as next-uri */ + playbin->about_to_finish = TRUE; + /* after this call, we should have a next group to activate or we EOS */ g_signal_emit (G_OBJECT (playbin), gst_play_bin_signals[SIGNAL_ABOUT_TO_FINISH], 0, NULL); + playbin->about_to_finish = FALSE; + /* now activate the next group. If the app did not set a next-uri, this will * fail and we can do EOS */ if (!setup_next_source (playbin)) { @@ -1048,42 +1042,20 @@ autoplug_select_cb (GstElement * decodebin, GstPad * pad, return GST_AUTOPLUG_SELECT_EXPOSE; } -/* unlink a group of uridecodebins from the sink */ -static void -unlink_group (GstPlayBin * playbin, GstSourceGroup * group) -{ - gint i; - - GST_DEBUG_OBJECT (playbin, "unlinking group %p", group); - - for (i = 0; i < 3; i++) { - GstSourceSelect *select = &group->selector[i]; - - if (!select->selector) - continue; - - GST_DEBUG_OBJECT (playbin, "unlinking selector %s", select->media); - gst_pad_unlink (select->srcpad, select->sinkpad); - - /* release back */ - gst_play_sink_release_pad (playbin->playsink, select->sinkpad); - select->sinkpad = NULL; - - gst_object_unref (select->srcpad); - select->srcpad = NULL; - - gst_element_set_state (select->selector, GST_STATE_NULL); - gst_bin_remove (GST_BIN_CAST (playbin), select->selector); - select->selector = NULL; - } - group->valid = FALSE; -} - static gboolean activate_group (GstPlayBin * playbin, GstSourceGroup * group) { GstElement *uridecodebin; + g_return_val_if_fail (group->valid, FALSE); + g_return_val_if_fail (!group->active, FALSE); + + if (group->uridecodebin) { + gst_element_set_state (group->uridecodebin, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (playbin), group->uridecodebin); + group->uridecodebin = NULL; + } + uridecodebin = gst_element_factory_make ("uridecodebin", NULL); if (!uridecodebin) goto no_decodebin; @@ -1116,6 +1088,8 @@ activate_group (GstPlayBin * playbin, GstSourceGroup * group) gst_element_set_state (uridecodebin, GST_STATE_PAUSED); + group->active = TRUE; + return TRUE; /* ERRORS */ @@ -1125,7 +1099,45 @@ no_decodebin: } } -/* setup the next group to play */ +/* unlink a group of uridecodebins from the sink */ +static gboolean +deactivate_group (GstPlayBin * playbin, GstSourceGroup * group) +{ + gint i; + + g_return_val_if_fail (group->valid, FALSE); + g_return_val_if_fail (group->active, FALSE); + + GST_DEBUG_OBJECT (playbin, "unlinking group %p", group); + + for (i = 0; i < 3; i++) { + GstSourceSelect *select = &group->selector[i]; + + if (!select->selector) + continue; + + GST_DEBUG_OBJECT (playbin, "unlinking selector %s", select->media); + gst_pad_unlink (select->srcpad, select->sinkpad); + + /* release back */ + gst_play_sink_release_pad (playbin->playsink, select->sinkpad); + select->sinkpad = NULL; + + gst_object_unref (select->srcpad); + select->srcpad = NULL; + + gst_element_set_state (select->selector, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (playbin), select->selector); + select->selector = NULL; + } + group->active = FALSE; + + return TRUE; +} + +/* setup the next group to play, this assumes the next_group is valid and + * configured. It swaps out the current_group and activates the valid + * next_group. */ static gboolean setup_next_source (GstPlayBin * playbin) { @@ -1142,7 +1154,8 @@ setup_next_source (GstPlayBin * playbin) old_group = playbin->curr_group; if (old_group && old_group->valid) { /* unlink our pads with the sink */ - unlink_group (playbin, old_group); + deactivate_group (playbin, old_group); + old_group->valid = FALSE; } /* activate the new group */ @@ -1168,22 +1181,45 @@ activate_failed: } } +/* The group that is currently playing is copied again to the + * next_group. + */ +static gboolean +save_current_group (GstPlayBin * playbin) +{ + GstSourceGroup *curr_group; + + GST_DEBUG_OBJECT (playbin, "save current group"); + + /* see if there is a current group */ + curr_group = playbin->curr_group; + if (curr_group && curr_group->valid) { + /* unlink our pads with the sink */ + deactivate_group (playbin, curr_group); + } + /* swap old and new */ + playbin->curr_group = playbin->next_group; + playbin->next_group = curr_group; + + return TRUE; +} + static GstStateChangeReturn gst_play_bin_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn ret; - GstPlayBin *play_bin; + GstPlayBin *playbin; - play_bin = GST_PLAY_BIN (element); + playbin = GST_PLAY_BIN (element); switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: - if (play_bin->playsink == NULL) { - play_bin->playsink = g_object_new (GST_TYPE_PLAY_SINK, NULL); - gst_bin_add (GST_BIN_CAST (play_bin), - GST_ELEMENT_CAST (play_bin->playsink)); + if (playbin->playsink == NULL) { + playbin->playsink = g_object_new (GST_TYPE_PLAY_SINK, NULL); + gst_bin_add (GST_BIN_CAST (playbin), + GST_ELEMENT_CAST (playbin->playsink)); } - if (!setup_next_source (play_bin)) + if (!setup_next_source (playbin)) goto source_failed; break; default: @@ -1201,10 +1237,13 @@ gst_play_bin_change_state (GstElement * element, GstStateChange transition) /* FIXME Release audio device when we implement that */ break; case GST_STATE_CHANGE_PAUSED_TO_READY: - if (play_bin->playsink) { - gst_bin_remove (GST_BIN_CAST (play_bin), - GST_ELEMENT_CAST (play_bin->playsink)); - play_bin->playsink = NULL; + save_current_group (playbin); + if (playbin->playsink) { + gst_element_set_state (GST_ELEMENT_CAST (playbin->playsink), + GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (playbin), + GST_ELEMENT_CAST (playbin->playsink)); + playbin->playsink = NULL; } break; default: diff --git a/gst/playback/gstplaysink.c b/gst/playback/gstplaysink.c index bdc2217e2b..21798554d6 100644 --- a/gst/playback/gstplaysink.c +++ b/gst/playback/gstplaysink.c @@ -64,11 +64,18 @@ typedef struct GstElement *sink; } GstPlayVideoChain; +#define GST_PLAY_SINK_GET_LOCK(playsink) (((GstPlaySink *)playsink)->lock) +#define GST_PLAY_SINK_LOCK(playsink) g_mutex_lock (GST_PLAY_SINK_GET_LOCK (playsink)) +#define GST_PLAY_SINK_UNLOCK(playsink) g_mutex_unlock (GST_PLAY_SINK_GET_LOCK (playsink)) + struct _GstPlaySink { GstBin bin; + GMutex *lock; + GstPlaySinkMode mode; + GstPlaySinkFlags flags; GstPlayChain *audiochain; GstPlayChain *videochain; @@ -120,8 +127,9 @@ enum }; static void gst_play_sink_class_init (GstPlaySinkClass * klass); -static void gst_play_sink_init (GstPlaySink * play_sink); +static void gst_play_sink_init (GstPlaySink * playsink); static void gst_play_sink_dispose (GObject * object); +static void gst_play_sink_finalize (GObject * object); static void gst_play_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * spec); @@ -186,6 +194,7 @@ gst_play_sink_class_init (GstPlaySinkClass * klass) gobject_klass->get_property = gst_play_sink_get_property; gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_play_sink_dispose); + gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_play_sink_finalize); g_object_class_install_property (gobject_klass, PROP_VIDEO_SINK, g_param_spec_object ("video-sink", "Video Sink", @@ -222,97 +231,112 @@ gst_play_sink_class_init (GstPlaySinkClass * klass) } static void -gst_play_sink_init (GstPlaySink * play_sink) +gst_play_sink_init (GstPlaySink * playsink) { /* init groups */ - play_sink->video_sink = NULL; - play_sink->audio_sink = NULL; - play_sink->visualisation = NULL; - play_sink->pending_visualisation = NULL; - play_sink->textoverlay_element = NULL; - play_sink->volume = 1.0; - play_sink->font_desc = NULL; + playsink->video_sink = NULL; + playsink->audio_sink = NULL; + playsink->visualisation = NULL; + playsink->pending_visualisation = NULL; + playsink->textoverlay_element = NULL; + playsink->volume = 1.0; + playsink->font_desc = NULL; + playsink->flags = GST_PLAY_SINK_FLAG_SOFT_VOLUME; + + playsink->lock = g_mutex_new (); } static void gst_play_sink_dispose (GObject * object) { - GstPlaySink *play_sink; + GstPlaySink *playsink; - play_sink = GST_PLAY_SINK (object); + playsink = GST_PLAY_SINK (object); - if (play_sink->audio_sink != NULL) { - gst_element_set_state (play_sink->audio_sink, GST_STATE_NULL); - gst_object_unref (play_sink->audio_sink); - play_sink->audio_sink = NULL; + if (playsink->audio_sink != NULL) { + gst_element_set_state (playsink->audio_sink, GST_STATE_NULL); + gst_object_unref (playsink->audio_sink); + playsink->audio_sink = NULL; } - if (play_sink->video_sink != NULL) { - gst_element_set_state (play_sink->video_sink, GST_STATE_NULL); - gst_object_unref (play_sink->video_sink); - play_sink->video_sink = NULL; + if (playsink->video_sink != NULL) { + gst_element_set_state (playsink->video_sink, GST_STATE_NULL); + gst_object_unref (playsink->video_sink); + playsink->video_sink = NULL; } - if (play_sink->visualisation != NULL) { - gst_element_set_state (play_sink->visualisation, GST_STATE_NULL); - gst_object_unref (play_sink->visualisation); - play_sink->visualisation = NULL; + if (playsink->visualisation != NULL) { + gst_element_set_state (playsink->visualisation, GST_STATE_NULL); + gst_object_unref (playsink->visualisation); + playsink->visualisation = NULL; } - if (play_sink->pending_visualisation != NULL) { - gst_element_set_state (play_sink->pending_visualisation, GST_STATE_NULL); - gst_object_unref (play_sink->pending_visualisation); - play_sink->pending_visualisation = NULL; + if (playsink->pending_visualisation != NULL) { + gst_element_set_state (playsink->pending_visualisation, GST_STATE_NULL); + gst_object_unref (playsink->pending_visualisation); + playsink->pending_visualisation = NULL; } - if (play_sink->textoverlay_element != NULL) { - gst_object_unref (play_sink->textoverlay_element); - play_sink->textoverlay_element = NULL; + if (playsink->textoverlay_element != NULL) { + gst_object_unref (playsink->textoverlay_element); + playsink->textoverlay_element = NULL; } - g_free (play_sink->font_desc); - play_sink->font_desc = NULL; + g_free (playsink->font_desc); + playsink->font_desc = NULL; G_OBJECT_CLASS (parent_class)->dispose (object); } +static void +gst_play_sink_finalize (GObject * object) +{ + GstPlaySink *playsink; + + playsink = GST_PLAY_SINK (object); + + g_mutex_free (playsink->lock); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + static void gst_play_sink_vis_unblocked (GstPad * tee_pad, gboolean blocked, gpointer user_data) { - GstPlaySink *play_sink = GST_PLAY_SINK (user_data); + GstPlaySink *playsink = GST_PLAY_SINK (user_data); - if (play_sink->pending_visualisation) + if (playsink->pending_visualisation) gst_pad_set_blocked_async (tee_pad, FALSE, gst_play_sink_vis_unblocked, - play_sink); + playsink); } static void gst_play_sink_vis_blocked (GstPad * tee_pad, gboolean blocked, gpointer user_data) { - GstPlaySink *play_sink = GST_PLAY_SINK (user_data); + GstPlaySink *playsink = GST_PLAY_SINK (user_data); GstBin *vis_bin = NULL; GstPad *vis_sink_pad = NULL, *vis_src_pad = NULL, *vqueue_pad = NULL; GstState bin_state; GstElement *pending_visualisation; - GST_OBJECT_LOCK (play_sink); - pending_visualisation = play_sink->pending_visualisation; - play_sink->pending_visualisation = NULL; - GST_OBJECT_UNLOCK (play_sink); + GST_OBJECT_LOCK (playsink); + pending_visualisation = playsink->pending_visualisation; + playsink->pending_visualisation = NULL; + GST_OBJECT_UNLOCK (playsink); /* We want to disable visualisation */ if (!GST_IS_ELEMENT (pending_visualisation)) { /* Set visualisation element to READY */ - gst_element_set_state (play_sink->visualisation, GST_STATE_READY); + gst_element_set_state (playsink->visualisation, GST_STATE_READY); goto beach; } vis_bin = - GST_BIN_CAST (gst_object_get_parent (GST_OBJECT_CAST (play_sink-> + GST_BIN_CAST (gst_object_get_parent (GST_OBJECT_CAST (playsink-> visualisation))); if (!GST_IS_BIN (vis_bin) || !GST_IS_PAD (tee_pad)) { goto beach; } - vis_src_pad = gst_element_get_pad (play_sink->visualisation, "src"); + vis_src_pad = gst_element_get_pad (playsink->visualisation, "src"); vis_sink_pad = gst_pad_get_peer (tee_pad); /* Can be fakesink */ @@ -341,11 +365,11 @@ gst_play_sink_vis_blocked (GstPad * tee_pad, gboolean blocked, } /* Remove from vis_bin */ - gst_bin_remove (vis_bin, play_sink->visualisation); + gst_bin_remove (vis_bin, playsink->visualisation); /* Set state to NULL */ - gst_element_set_state (play_sink->visualisation, GST_STATE_NULL); + gst_element_set_state (playsink->visualisation, GST_STATE_NULL); /* And loose our ref */ - gst_object_unref (play_sink->visualisation); + gst_object_unref (playsink->visualisation); if (pending_visualisation) { /* Ref this new visualisation element before adding to the bin */ @@ -368,8 +392,8 @@ gst_play_sink_vis_blocked (GstPad * tee_pad, gboolean blocked, } /* We are done */ - gst_object_unref (play_sink->visualisation); - play_sink->visualisation = pending_visualisation; + gst_object_unref (playsink->visualisation); + playsink->visualisation = pending_visualisation; beach: if (vis_sink_pad) { @@ -387,41 +411,41 @@ beach: /* Unblock the pad */ gst_pad_set_blocked_async (tee_pad, FALSE, gst_play_sink_vis_unblocked, - play_sink); + playsink); } void -gst_play_sink_set_video_sink (GstPlaySink * play_sink, GstElement * sink) +gst_play_sink_set_video_sink (GstPlaySink * playsink, GstElement * sink) { - GST_OBJECT_LOCK (play_sink); - if (play_sink->video_sink) - gst_object_unref (play_sink->video_sink); + GST_OBJECT_LOCK (playsink); + if (playsink->video_sink) + gst_object_unref (playsink->video_sink); if (sink) { gst_object_ref (sink); gst_object_sink (sink); } - play_sink->video_sink = sink; - GST_OBJECT_UNLOCK (play_sink); + playsink->video_sink = sink; + GST_OBJECT_UNLOCK (playsink); } void -gst_play_sink_set_audio_sink (GstPlaySink * play_sink, GstElement * sink) +gst_play_sink_set_audio_sink (GstPlaySink * playsink, GstElement * sink) { - GST_OBJECT_LOCK (play_sink); - if (play_sink->audio_sink) - gst_object_unref (play_sink->audio_sink); + GST_OBJECT_LOCK (playsink); + if (playsink->audio_sink) + gst_object_unref (playsink->audio_sink); if (sink) { gst_object_ref (sink); gst_object_sink (sink); } - play_sink->audio_sink = sink; - GST_OBJECT_UNLOCK (play_sink); + playsink->audio_sink = sink; + GST_OBJECT_UNLOCK (playsink); } void -gst_play_sink_set_vis_plugin (GstPlaySink * play_sink, +gst_play_sink_set_vis_plugin (GstPlaySink * playsink, GstElement * pending_visualisation) { /* Take ownership */ @@ -432,19 +456,19 @@ gst_play_sink_set_vis_plugin (GstPlaySink * play_sink, /* Do we already have a visualisation change pending? If yes, change the * pending vis with the new one. */ - GST_OBJECT_LOCK (play_sink); - if (play_sink->pending_visualisation) { - gst_object_unref (play_sink->pending_visualisation); - play_sink->pending_visualisation = pending_visualisation; - GST_OBJECT_UNLOCK (play_sink); + GST_OBJECT_LOCK (playsink); + if (playsink->pending_visualisation) { + gst_object_unref (playsink->pending_visualisation); + playsink->pending_visualisation = pending_visualisation; + GST_OBJECT_UNLOCK (playsink); } else { - GST_OBJECT_UNLOCK (play_sink); + GST_OBJECT_UNLOCK (playsink); /* Was there a visualisation already set ? */ - if (play_sink->visualisation != NULL) { + if (playsink->visualisation != NULL) { GstBin *vis_bin = NULL; vis_bin = - GST_BIN_CAST (gst_object_get_parent (GST_OBJECT_CAST (play_sink-> + GST_BIN_CAST (gst_object_get_parent (GST_OBJECT_CAST (playsink-> visualisation))); /* Check if the visualisation is already in a bin */ @@ -452,7 +476,7 @@ gst_play_sink_set_vis_plugin (GstPlaySink * play_sink, GstPad *vis_sink_pad = NULL, *tee_pad = NULL; /* Now get tee pad and block it async */ - vis_sink_pad = gst_element_get_pad (play_sink->visualisation, "sink"); + vis_sink_pad = gst_element_get_pad (playsink->visualisation, "sink"); if (!GST_IS_PAD (vis_sink_pad)) { goto beach; } @@ -461,10 +485,10 @@ gst_play_sink_set_vis_plugin (GstPlaySink * play_sink, goto beach; } - play_sink->pending_visualisation = pending_visualisation; + playsink->pending_visualisation = pending_visualisation; /* Block with callback */ gst_pad_set_blocked_async (tee_pad, TRUE, gst_play_sink_vis_blocked, - play_sink); + playsink); beach: if (vis_sink_pad) { gst_object_unref (vis_sink_pad); @@ -474,10 +498,10 @@ gst_play_sink_set_vis_plugin (GstPlaySink * play_sink, } gst_object_unref (vis_bin); } else { - play_sink->visualisation = pending_visualisation; + playsink->visualisation = pending_visualisation; } } else { - play_sink->visualisation = pending_visualisation; + playsink->visualisation = pending_visualisation; } } } @@ -486,34 +510,34 @@ static void gst_play_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GstPlaySink *play_sink; + GstPlaySink *playsink; - play_sink = GST_PLAY_SINK (object); + playsink = GST_PLAY_SINK (object); switch (prop_id) { case PROP_VIDEO_SINK: - gst_play_sink_set_video_sink (play_sink, g_value_get_object (value)); + gst_play_sink_set_video_sink (playsink, g_value_get_object (value)); break; case PROP_AUDIO_SINK: - gst_play_sink_set_audio_sink (play_sink, g_value_get_object (value)); + gst_play_sink_set_audio_sink (playsink, g_value_get_object (value)); break; case PROP_VIS_PLUGIN: - gst_play_sink_set_vis_plugin (play_sink, g_value_get_object (value)); + gst_play_sink_set_vis_plugin (playsink, g_value_get_object (value)); break; case PROP_VOLUME: - GST_OBJECT_LOCK (play_sink); - play_sink->volume = g_value_get_double (value); - GST_OBJECT_UNLOCK (play_sink); + GST_OBJECT_LOCK (playsink); + playsink->volume = g_value_get_double (value); + GST_OBJECT_UNLOCK (playsink); break; case PROP_FONT_DESC: - GST_OBJECT_LOCK (play_sink); - g_free (play_sink->font_desc); - play_sink->font_desc = g_strdup (g_value_get_string (value)); - if (play_sink->textoverlay_element) { - g_object_set (G_OBJECT (play_sink->textoverlay_element), + GST_OBJECT_LOCK (playsink); + g_free (playsink->font_desc); + playsink->font_desc = g_strdup (g_value_get_string (value)); + if (playsink->textoverlay_element) { + g_object_set (G_OBJECT (playsink->textoverlay_element), "font-desc", g_value_get_string (value), NULL); } - GST_OBJECT_UNLOCK (play_sink); + GST_OBJECT_UNLOCK (playsink); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -525,30 +549,30 @@ static void gst_play_sink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstPlaySink *play_sink; + GstPlaySink *playsink; - play_sink = GST_PLAY_SINK (object); + playsink = GST_PLAY_SINK (object); switch (prop_id) { case PROP_VIDEO_SINK: - GST_OBJECT_LOCK (play_sink); - g_value_set_object (value, play_sink->video_sink); - GST_OBJECT_UNLOCK (play_sink); + GST_OBJECT_LOCK (playsink); + g_value_set_object (value, playsink->video_sink); + GST_OBJECT_UNLOCK (playsink); break; case PROP_AUDIO_SINK: - GST_OBJECT_LOCK (play_sink); - g_value_set_object (value, play_sink->audio_sink); - GST_OBJECT_UNLOCK (play_sink); + GST_OBJECT_LOCK (playsink); + g_value_set_object (value, playsink->audio_sink); + GST_OBJECT_UNLOCK (playsink); break; case PROP_VIS_PLUGIN: - GST_OBJECT_LOCK (play_sink); - g_value_set_object (value, play_sink->visualisation); - GST_OBJECT_UNLOCK (play_sink); + GST_OBJECT_LOCK (playsink); + g_value_set_object (value, playsink->visualisation); + GST_OBJECT_UNLOCK (playsink); break; case PROP_VOLUME: - GST_OBJECT_LOCK (play_sink); - g_value_set_double (value, play_sink->volume); - GST_OBJECT_UNLOCK (play_sink); + GST_OBJECT_LOCK (playsink); + g_value_set_double (value, playsink->volume); + GST_OBJECT_UNLOCK (playsink); break; case PROP_FRAME: { @@ -624,17 +648,17 @@ activate_chain (GstPlayChain * chain, gboolean activate) * */ static GstPlayChain * -gen_video_chain (GstPlaySink * play_sink, gboolean raw) +gen_video_chain (GstPlaySink * playsink, gboolean raw) { GstPlayVideoChain *chain; GstBin *bin; GstPad *pad; chain = g_new0 (GstPlayVideoChain, 1); - chain->chain.playsink = gst_object_ref (play_sink); + chain->chain.playsink = gst_object_ref (playsink); - if (play_sink->video_sink) { - chain->sink = play_sink->video_sink; + if (playsink->video_sink) { + chain->sink = playsink->video_sink; } else { chain->sink = gst_element_factory_make ("autovideosink", "videosink"); if (chain->sink == NULL) { @@ -697,8 +721,8 @@ gen_video_chain (GstPlaySink * play_sink, gboolean raw) /* ERRORS */ no_sinks: { - post_missing_element_message (play_sink, "autovideosink"); - GST_ELEMENT_ERROR (play_sink, CORE, MISSING_PLUGIN, + post_missing_element_message (playsink, "autovideosink"); + GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN, (_("Both autovideosink and xvimagesink elements are missing.")), (NULL)); free_chain ((GstPlayChain *) chain); @@ -706,8 +730,8 @@ no_sinks: } no_colorspace: { - post_missing_element_message (play_sink, "ffmpegcolorspace"); - GST_ELEMENT_ERROR (play_sink, CORE, MISSING_PLUGIN, + post_missing_element_message (playsink, "ffmpegcolorspace"); + GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN, (_("Missing element '%s' - check your GStreamer installation."), "ffmpegcolorspace"), (NULL)); free_chain ((GstPlayChain *) chain); @@ -716,8 +740,8 @@ no_colorspace: no_videoscale: { - post_missing_element_message (play_sink, "videoscale"); - GST_ELEMENT_ERROR (play_sink, CORE, MISSING_PLUGIN, + post_missing_element_message (playsink, "videoscale"); + GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN, (_("Missing element '%s' - check your GStreamer installation."), "videoscale"), ("possibly a liboil version mismatch?")); free_chain ((GstPlayChain *) chain); @@ -725,7 +749,7 @@ no_videoscale: } link_failed: { - GST_ELEMENT_ERROR (play_sink, CORE, PAD, + GST_ELEMENT_ERROR (playsink, CORE, PAD, (NULL), ("Failed to configure the video sink.")); free_chain ((GstPlayChain *) chain); return NULL; @@ -748,13 +772,13 @@ link_failed: * videosink without the text_sink pad. */ static GstElement * -gen_text_element (GstPlaySink * play_sink) +gen_text_element (GstPlaySink * playsink) { GstElement *element, *csp, *overlay, *vbin; GstPad *pad; /* Create the video rendering bin, error is posted when this fails. */ - vbin = gen_video_element (play_sink); + vbin = gen_video_element (playsink); if (!vbin) return NULL; @@ -771,12 +795,12 @@ gen_text_element (GstPlaySink * play_sink) /* Set some parameters */ g_object_set (G_OBJECT (overlay), "halign", "center", "valign", "bottom", NULL); - if (play_sink->font_desc) { - g_object_set (G_OBJECT (overlay), "font-desc", play_sink->font_desc, NULL); + if (playsink->font_desc) { + g_object_set (G_OBJECT (overlay), "font-desc", playsink->font_desc, NULL); } /* Take a ref */ - play_sink->textoverlay_element = GST_ELEMENT_CAST (gst_object_ref (overlay)); + playsink->textoverlay_element = GST_ELEMENT_CAST (gst_object_ref (overlay)); /* we know this will succeed, as the video bin already created one before */ csp = gst_element_factory_make ("ffmpegcolorspace", "subtitlecsp"); @@ -805,8 +829,8 @@ gen_text_element (GstPlaySink * play_sink) /* ERRORS */ no_overlay: { - post_missing_element_message (play_sink, "textoverlay"); - GST_WARNING_OBJECT (play_sink, + post_missing_element_message (playsink, "textoverlay"); + GST_WARNING_OBJECT (playsink, "No overlay (pango) element, subtitles disabled"); return vbin; } @@ -827,7 +851,7 @@ no_overlay: * +-------------------------------------------------------------+ */ static GstPlayChain * -gen_audio_chain (GstPlaySink * play_sink, gboolean raw) +gen_audio_chain (GstPlaySink * playsink, gboolean raw) { GstPlayAudioChain *chain; GstBin *bin; @@ -835,10 +859,10 @@ gen_audio_chain (GstPlaySink * play_sink, gboolean raw) GstPad *pad; chain = g_new0 (GstPlayAudioChain, 1); - chain->chain.playsink = gst_object_ref (play_sink); + chain->chain.playsink = gst_object_ref (playsink); - if (play_sink->audio_sink) { - chain->sink = play_sink->audio_sink; + if (playsink->audio_sink) { + chain->sink = playsink->audio_sink; } else { chain->sink = gst_element_factory_make ("autoaudiosink", "audiosink"); if (chain->sink == NULL) { @@ -864,14 +888,19 @@ gen_audio_chain (GstPlaySink * play_sink, gboolean raw) goto no_audioresample; gst_bin_add (bin, chain->resample); - chain->volume = gst_element_factory_make ("volume", "volume"); - g_object_set (G_OBJECT (chain->volume), "volume", play_sink->volume, NULL); - gst_bin_add (bin, chain->volume); - res = gst_element_link_pads (chain->conv, "src", chain->resample, "sink"); - res &= - gst_element_link_pads (chain->resample, "src", chain->volume, "sink"); - res &= gst_element_link_pads (chain->volume, "src", chain->sink, NULL); + + if (playsink->flags & GST_PLAY_SINK_FLAG_SOFT_VOLUME) { + chain->volume = gst_element_factory_make ("volume", "volume"); + g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, NULL); + gst_bin_add (bin, chain->volume); + + res &= + gst_element_link_pads (chain->resample, "src", chain->volume, "sink"); + res &= gst_element_link_pads (chain->volume, "src", chain->sink, NULL); + } else { + res &= gst_element_link_pads (chain->resample, "src", chain->sink, NULL); + } if (!res) goto link_failed; @@ -888,16 +917,16 @@ gen_audio_chain (GstPlaySink * play_sink, gboolean raw) /* ERRORS */ no_sinks: { - post_missing_element_message (play_sink, "autoaudiosink"); - GST_ELEMENT_ERROR (play_sink, CORE, MISSING_PLUGIN, + post_missing_element_message (playsink, "autoaudiosink"); + GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN, (_("Both autoaudiosink and alsasink elements are missing.")), (NULL)); free_chain ((GstPlayChain *) chain); return NULL; } no_audioconvert: { - post_missing_element_message (play_sink, "audioconvert"); - GST_ELEMENT_ERROR (play_sink, CORE, MISSING_PLUGIN, + post_missing_element_message (playsink, "audioconvert"); + GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN, (_("Missing element '%s' - check your GStreamer installation."), "audioconvert"), ("possibly a liboil version mismatch?")); free_chain ((GstPlayChain *) chain); @@ -906,8 +935,8 @@ no_audioconvert: no_audioresample: { - post_missing_element_message (play_sink, "audioresample"); - GST_ELEMENT_ERROR (play_sink, CORE, MISSING_PLUGIN, + post_missing_element_message (playsink, "audioresample"); + GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN, (_("Missing element '%s' - check your GStreamer installation."), "audioresample"), ("possibly a liboil version mismatch?")); free_chain ((GstPlayChain *) chain); @@ -915,7 +944,7 @@ no_audioresample: } link_failed: { - GST_ELEMENT_ERROR (play_sink, CORE, PAD, + GST_ELEMENT_ERROR (playsink, CORE, PAD, (NULL), ("Failed to configure the audio sink.")); free_chain ((GstPlayChain *) chain); return NULL; @@ -947,7 +976,7 @@ link_failed: * +-----------------------------------------------------------------------+ */ static GstElement * -gen_vis_element (GstPlaySink * play_sink) +gen_vis_element (GstPlaySink * playsink) { gboolean res; GstElement *element; @@ -962,10 +991,10 @@ gen_vis_element (GstPlaySink * play_sink) GstPad *pad, *rpad; /* errors are already posted when these fail. */ - asink = gen_audio_element (play_sink); + asink = gen_audio_element (playsink); if (!asink) return NULL; - vsink = gen_video_element (play_sink); + vsink = gen_video_element (playsink); if (!vsink) { gst_object_unref (asink); return NULL; @@ -998,9 +1027,9 @@ gen_vis_element (GstPlaySink * play_sink) goto no_audioconvert; gst_bin_add (GST_BIN_CAST (element), conv2); - if (play_sink->visualisation) { - gst_object_ref (play_sink->visualisation); - vis = play_sink->visualisation; + if (playsink->visualisation) { + gst_object_ref (playsink->visualisation); + vis = playsink->visualisation; } else { vis = gst_element_factory_make ("goom", "vis"); if (!vis) @@ -1038,8 +1067,8 @@ gen_vis_element (GstPlaySink * play_sink) /* ERRORS */ no_audioconvert: { - post_missing_element_message (play_sink, "audioconvert"); - GST_ELEMENT_ERROR (play_sink, CORE, MISSING_PLUGIN, + post_missing_element_message (playsink, "audioconvert"); + GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN, (_("Missing element '%s' - check your GStreamer installation."), "audioconvert"), ("possibly a liboil version mismatch?")); gst_object_unref (element); @@ -1047,8 +1076,8 @@ no_audioconvert: } no_audioresample: { - post_missing_element_message (play_sink, "audioresample"); - GST_ELEMENT_ERROR (play_sink, CORE, MISSING_PLUGIN, + post_missing_element_message (playsink, "audioresample"); + GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN, (_("Missing element '%s' - check your GStreamer installation."), "audioresample"), (NULL)); gst_object_unref (element); @@ -1056,8 +1085,8 @@ no_audioresample: } no_goom: { - post_missing_element_message (play_sink, "goom"); - GST_ELEMENT_ERROR (play_sink, CORE, MISSING_PLUGIN, + post_missing_element_message (playsink, "goom"); + GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN, (_("Missing element '%s' - check your GStreamer installation."), "goom"), (NULL)); gst_object_unref (element); @@ -1065,7 +1094,7 @@ no_goom: } link_failed: { - GST_ELEMENT_ERROR (play_sink, CORE, PAD, + GST_ELEMENT_ERROR (playsink, CORE, PAD, (NULL), ("Failed to configure the visualisation element.")); gst_object_unref (element); return NULL; @@ -1078,9 +1107,9 @@ gst_play_sink_get_mode (GstPlaySink * playsink) { GstPlaySinkMode res; - GST_OBJECT_LOCK (playsink); + GST_PLAY_SINK_LOCK (playsink); res = playsink->mode; - GST_OBJECT_LOCK (playsink); + GST_PLAY_SINK_UNLOCK (playsink); return res; } @@ -1091,6 +1120,9 @@ gst_play_sink_get_mode (GstPlaySink * playsink) gboolean gst_play_sink_set_mode (GstPlaySink * playsink, GstPlaySinkMode mode) { + GST_DEBUG_OBJECT (playsink, "setting mode to %d", mode); + + GST_PLAY_SINK_LOCK (playsink); if (mode & GST_PLAY_SINK_MODE_AUDIO && playsink->audio_pad) { if (!playsink->audiochain) playsink->audiochain = @@ -1126,10 +1158,38 @@ gst_play_sink_set_mode (GstPlaySink * playsink, GstPlaySinkMode mode) } playsink->mode = mode; + GST_PLAY_SINK_UNLOCK (playsink); return TRUE; } +gboolean +gst_play_sink_set_flags (GstPlaySink * playsink, GstPlaySinkFlags flags) +{ + g_return_val_if_fail (GST_IS_PLAY_SINK (playsink), FALSE); + + GST_OBJECT_LOCK (playsink); + playsink->flags = flags; + GST_OBJECT_LOCK (playsink); + + return TRUE; +} + +GstPlaySinkFlags +gst_play_sink_get_flags (GstPlaySink * playsink) +{ + GstPlaySinkFlags res; + + g_return_val_if_fail (GST_IS_PLAY_SINK (playsink), 0); + + GST_OBJECT_LOCK (playsink); + res = playsink->flags; + GST_OBJECT_LOCK (playsink); + + return res; +} + + GstPad * gst_play_sink_request_pad (GstPlaySink * playsink, GstPlaySinkType type) { @@ -1137,6 +1197,7 @@ gst_play_sink_request_pad (GstPlaySink * playsink, GstPlaySinkType type) gboolean created = FALSE; gboolean raw = FALSE; + GST_PLAY_SINK_LOCK (playsink); switch (type) { case GST_PLAY_SINK_TYPE_AUDIO_RAW: raw = TRUE; @@ -1172,10 +1233,13 @@ gst_play_sink_request_pad (GstPlaySink * playsink, GstPlaySinkType type) res = NULL; break; } + GST_PLAY_SINK_UNLOCK (playsink); + if (created && res) { gst_pad_set_active (res, TRUE); gst_element_add_pad (GST_ELEMENT_CAST (playsink), res); } + return res; } @@ -1184,6 +1248,7 @@ gst_play_sink_release_pad (GstPlaySink * playsink, GstPad * pad) { GstPad **res = NULL; + GST_PLAY_SINK_LOCK (playsink); if (pad == playsink->video_pad) { res = &playsink->video_pad; } else if (pad == playsink->audio_pad) { @@ -1191,6 +1256,7 @@ gst_play_sink_release_pad (GstPlaySink * playsink, GstPad * pad) } else if (pad == playsink->text_pad) { res = &playsink->text_pad; } + GST_PLAY_SINK_UNLOCK (playsink); if (*res) { gst_pad_set_active (*res, FALSE); @@ -1203,25 +1269,25 @@ gst_play_sink_release_pad (GstPlaySink * playsink, GstPad * pad) * remaining sinks (unlike GstBin) */ static gboolean -gst_play_sink_send_event_to_sink (GstPlaySink * play_sink, GstEvent * event) +gst_play_sink_send_event_to_sink (GstPlaySink * playsink, GstEvent * event) { gboolean res = TRUE; - if (play_sink->audiochain) { + if (playsink->audiochain) { gst_event_ref (event); - if ((res = gst_element_send_event (play_sink->audiochain->bin, event))) { - GST_DEBUG_OBJECT (play_sink, "Sent event succesfully to audio sink"); + if ((res = gst_element_send_event (playsink->audiochain->bin, event))) { + GST_DEBUG_OBJECT (playsink, "Sent event succesfully to audio sink"); goto done; } - GST_DEBUG_OBJECT (play_sink, "Event failed when sent to audio sink"); + GST_DEBUG_OBJECT (playsink, "Event failed when sent to audio sink"); } - if (play_sink->videochain) { + if (playsink->videochain) { gst_event_ref (event); - if ((res = gst_element_send_event (play_sink->videochain->bin, event))) { - GST_DEBUG_OBJECT (play_sink, "Sent event succesfully to video sink"); + if ((res = gst_element_send_event (playsink->videochain->bin, event))) { + GST_DEBUG_OBJECT (playsink, "Sent event succesfully to video sink"); goto done; } - GST_DEBUG_OBJECT (play_sink, "Event failed when sent to video sink"); + GST_DEBUG_OBJECT (playsink, "Event failed when sent to video sink"); } done: gst_event_unref (event); @@ -1253,9 +1319,9 @@ static GstStateChangeReturn gst_play_sink_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn ret; - GstPlaySink *play_sink; + GstPlaySink *playsink; - play_sink = GST_PLAY_SINK (element); + playsink = GST_PLAY_SINK (element); switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: diff --git a/gst/playback/gstplaysink.h b/gst/playback/gstplaysink.h index 50da18e521..5c1f1e46c4 100644 --- a/gst/playback/gstplaysink.h +++ b/gst/playback/gstplaysink.h @@ -71,6 +71,22 @@ typedef enum { GST_PLAY_SINK_TYPE_LAST = 5 } GstPlaySinkType; +/** + * GstPlaySinkFlags: + * @GST_PLAY_SINK_FLAG_SOFT_VOLUME: Use software volume in the sink + * @GST_PLAY_SINK_FLAG_NATIVE_AUDIO: only allow native audio formats, this omits + * configuration of audioconvert and audioresample. + * @GST_PLAY_SINK_FLAG_NATIVE_VIDEO: only allow native video formats, this omits + * configuration of ffmpegcolorspace and videoscale. + * + * Extra flags to configure the behaviour of the sinks. + */ +typedef enum { + GST_PLAY_SINK_FLAG_SOFT_VOLUME = (1 << 0), + GST_PLAY_SINK_FLAG_NATIVE_AUDIO = (1 << 1), + GST_PLAY_SINK_FLAG_NATIVE_VIDEO = (1 << 2) +} GstPlaySinkFlags; + typedef struct _GstPlaySink GstPlaySink; typedef struct _GstPlaySinkClass GstPlaySinkClass; @@ -79,12 +95,15 @@ GType gst_play_sink_get_type (void); GstPad * gst_play_sink_request_pad (GstPlaySink *playsink, GstPlaySinkType type); void gst_play_sink_release_pad (GstPlaySink *playsink, GstPad *pad); -void gst_play_sink_set_video_sink (GstPlaySink * play_sink, GstElement * sink); -void gst_play_sink_set_audio_sink (GstPlaySink * play_sink, GstElement * sink); -void gst_play_sink_set_vis_plugin (GstPlaySink * play_sink, GstElement * vis); +void gst_play_sink_set_video_sink (GstPlaySink * playsink, GstElement * sink); +void gst_play_sink_set_audio_sink (GstPlaySink * playsink, GstElement * sink); +void gst_play_sink_set_vis_plugin (GstPlaySink * playsink, GstElement * vis); + +gboolean gst_play_sink_set_flags (GstPlaySink * playsink, GstPlaySinkFlags flags); +GstPlaySinkFlags gst_play_sink_get_flags (GstPlaySink * playsink); -GstPlaySinkMode gst_play_sink_get_mode (GstPlaySink *playsink); gboolean gst_play_sink_set_mode (GstPlaySink *playsink, GstPlaySinkMode mode); +GstPlaySinkMode gst_play_sink_get_mode (GstPlaySink *playsink); G_END_DECLS diff --git a/gst/playback/test7.c b/gst/playback/test7.c index 81083e08c3..b39d74f441 100644 --- a/gst/playback/test7.c +++ b/gst/playback/test7.c @@ -92,7 +92,7 @@ static void about_to_finish_cb (GstElement * element, gchar * uri[]) { if (arg_count < max_count) { - g_object_set (G_OBJECT (element), "next-uri", uri[arg_count], NULL); + g_object_set (G_OBJECT (element), "uri", uri[arg_count], NULL); arg_count++; } }