diff --git a/ChangeLog b/ChangeLog index 3fcf558d50..399c4f4dc5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2008-02-14 Wim Taymans + + * gst/playback/gstplaybin2.c: (gst_play_bin_class_init), + (gst_play_bin_set_property), (gst_play_bin_get_property), + (pad_added_cb), (pad_removed_cb), (no_more_pads_cb): + * gst/playback/gstplaysink.c: (gst_play_sink_set_mute), + (gst_play_sink_get_mute), (gen_audio_chain): + * gst/playback/gstplaysink.h: + Add mute property. + + * gst/playback/gststreamselector.c: (gst_selector_pad_event), + (gst_selector_pad_chain): + * gst/playback/gststreamselector.h: + Make sure we forward the event only once. + + * tests/examples/seek/seek.c: (stop_cb), (mute_toggle_cb), (main): + Add and implement the mute button for playbin2. + 2008-02-13 Wim Taymans Patch by: Tommi Myöhänen diff --git a/gst/playback/gstplaybin2.c b/gst/playback/gstplaybin2.c index 51d3fa8538..1ca65fc22b 100644 --- a/gst/playback/gstplaybin2.c +++ b/gst/playback/gstplaybin2.c @@ -366,6 +366,7 @@ struct _GstPlayBinClass #define DEFAULT_VIDEO_SINK NULL #define DEFAULT_VIS_PLUGIN NULL #define DEFAULT_VOLUME 1.0 +#define DEFAULT_MUTE FALSE #define DEFAULT_FRAME NULL #define DEFAULT_FONT_DESC NULL #define DEFAULT_CONNECTION_SPEED 0 @@ -388,6 +389,7 @@ enum PROP_VIDEO_SINK, PROP_VIS_PLUGIN, PROP_VOLUME, + PROP_MUTE, PROP_FRAME, PROP_FONT_DESC, PROP_CONNECTION_SPEED @@ -587,8 +589,13 @@ gst_play_bin_class_init (GstPlayBinClass * klass) GST_TYPE_ELEMENT, G_PARAM_READWRITE)); g_object_class_install_property (gobject_klass, PROP_VOLUME, - g_param_spec_double ("volume", "volume", "volume", + g_param_spec_double ("volume", "Volume", "The audio volume", 0.0, VOLUME_MAX_DOUBLE, 1.0, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_klass, PROP_MUTE, + g_param_spec_boolean ("mute", "Mute", + "Mute the audio channel without changing the volume", FALSE, + G_PARAM_READWRITE)); + g_object_class_install_property (gobject_klass, PROP_FRAME, gst_param_spec_mini_object ("frame", "Frame", "The last frame (NULL = no video available)", @@ -1060,6 +1067,9 @@ gst_play_bin_set_property (GObject * object, guint prop_id, case PROP_VOLUME: gst_play_sink_set_volume (playbin->playsink, g_value_get_double (value)); break; + case PROP_MUTE: + gst_play_sink_set_mute (playbin->playsink, g_value_get_boolean (value)); + break; case PROP_FONT_DESC: break; case PROP_CONNECTION_SPEED: @@ -1169,6 +1179,9 @@ gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value, case PROP_VOLUME: g_value_set_double (value, gst_play_sink_get_volume (playbin->playsink)); break; + case PROP_MUTE: + g_value_set_boolean (value, gst_play_sink_get_mute (playbin->playsink)); + break; case PROP_FRAME: break; case PROP_FONT_DESC: @@ -1248,9 +1261,6 @@ pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group) if (select == NULL) goto unknown_type; - /* store the selector for the pad */ - g_object_set_data (G_OBJECT (pad), "playbin2.select", select); - if (select->selector == NULL) { /* no selector, create one */ GST_DEBUG_OBJECT (playbin, "creating new selector"); @@ -1271,6 +1281,9 @@ pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group) GST_DEBUG_OBJECT (playbin, "got pad %s:%s from selector", GST_DEBUG_PAD_NAME (sinkpad)); + /* store the selector for the pad */ + g_object_set_data (G_OBJECT (sinkpad), "playbin2.select", select); + /* store the pad in the array */ g_ptr_array_add (select->channels, sinkpad); @@ -1326,6 +1339,7 @@ pad_removed_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group) if ((select = g_object_get_data (G_OBJECT (pad), "playbin2.select"))) { /* remove the pad from the array */ g_ptr_array_remove (select->channels, pad); + GST_DEBUG_OBJECT (playbin, "pad removed from array"); } /* get the selector sinkpad */ @@ -1389,7 +1403,8 @@ no_more_pads_cb (GstElement * decodebin, GstSourceGroup * group) select->sinkpad = gst_play_sink_request_pad (playbin->playsink, select->type); res = gst_pad_link (select->srcpad, select->sinkpad); - GST_DEBUG_OBJECT (playbin, "linked type %s: %d", select->media, res); + GST_DEBUG_OBJECT (playbin, "linked type %s, result: %d", select->media, + res); } } /* configure the modes now */ diff --git a/gst/playback/gstplaysink.c b/gst/playback/gstplaysink.c index a4da99cca7..d39253b8c7 100644 --- a/gst/playback/gstplaysink.c +++ b/gst/playback/gstplaysink.c @@ -52,7 +52,8 @@ typedef struct GstPad *teesrc; GstElement *conv; GstElement *resample; - GstElement *volume; + GstElement *volume; /* element with the volume property */ + GstElement *mute; /* element with the mute property */ GstElement *sink; } GstPlayAudioChain; @@ -103,6 +104,7 @@ struct _GstPlaySink GstElement *video_sink; GstElement *visualisation; gfloat volume; + gboolean mute; gchar *font_desc; /* font description */ guint connection_speed; /* connection speed in bits/sec (0 = unknown) */ @@ -551,6 +553,39 @@ gst_play_sink_get_volume (GstPlaySink * playsink) return result; } +void +gst_play_sink_set_mute (GstPlaySink * playsink, gboolean mute) +{ + GstPlayAudioChain *chain; + + GST_PLAY_SINK_LOCK (playsink); + playsink->mute = mute; + chain = (GstPlayAudioChain *) playsink->audiochain; + if (chain && chain->mute) { + g_object_set (chain->mute, "mute", mute, NULL); + } + GST_PLAY_SINK_UNLOCK (playsink); +} + +gboolean +gst_play_sink_get_mute (GstPlaySink * playsink) +{ + gboolean result; + GstPlayAudioChain *chain; + + GST_PLAY_SINK_LOCK (playsink); + chain = (GstPlayAudioChain *) playsink->audiochain; + if (chain && chain->mute) { + g_object_get (chain->mute, "mute", &result, NULL); + playsink->mute = result; + } else { + result = playsink->mute; + } + GST_PLAY_SINK_UNLOCK (playsink); + + return result; +} + static void gst_play_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -948,6 +983,10 @@ gen_audio_chain (GstPlaySink * playsink, gboolean raw) chain->volume = gst_element_factory_make ("volume", "volume"); if (chain->volume == NULL) goto no_volume; + + /* volume also has the mute property */ + chain->mute = gst_object_ref (chain->volume); + /* configure with the latest volume */ g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, NULL); gst_bin_add (bin, chain->volume); diff --git a/gst/playback/gstplaysink.h b/gst/playback/gstplaysink.h index ec89f41386..b585de554d 100644 --- a/gst/playback/gstplaysink.h +++ b/gst/playback/gstplaysink.h @@ -72,6 +72,9 @@ void gst_play_sink_set_vis_plugin (GstPlaySink * playsink, GstElemen void gst_play_sink_set_volume (GstPlaySink *playsink, gdouble volume); gdouble gst_play_sink_get_volume (GstPlaySink *playsink); +void gst_play_sink_set_mute (GstPlaySink *playsink, gboolean mute); +gboolean gst_play_sink_get_mute (GstPlaySink *playsink); + gboolean gst_play_sink_set_flags (GstPlaySink * playsink, GstPlayFlags flags); GstPlayFlags gst_play_sink_get_flags (GstPlaySink * playsink); diff --git a/gst/playback/gststreamselector.c b/gst/playback/gststreamselector.c index 87604b9736..74fd2e3838 100644 --- a/gst/playback/gststreamselector.c +++ b/gst/playback/gststreamselector.c @@ -274,7 +274,7 @@ gst_selector_pad_event (GstPad * pad, GstEvent * event) gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, &start, &stop, &time); - GST_DEBUG_OBJECT (sel, + GST_DEBUG_OBJECT (selpad, "configured NEWSEGMENT update %d, rate %lf, applied rate %lf, " "format %d, " "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %" @@ -282,10 +282,10 @@ gst_selector_pad_event (GstPad * pad, GstEvent * event) gst_segment_set_newsegment_full (&selpad->segment, update, rate, arate, format, start, stop, time); - /* if we are not going to forward the segment, mark the segment as - * pending */ + /* mark pending segment if we are not forwarding, we assume all pads share + * the same segment so we only forward once. */ if (!forward) - selpad->segment_pending = TRUE; + sel->segment_pending = TRUE; break; } case GST_EVENT_TAG: @@ -407,12 +407,12 @@ gst_selector_pad_chain (GstPad * pad, GstBuffer * buf) goto ignore; /* if we have a pending segment, push it out now */ - if (selpad->segment_pending) { + if (sel->segment_pending) { gst_pad_push_event (sel->srcpad, gst_event_new_new_segment_full (FALSE, seg->rate, seg->applied_rate, seg->format, seg->start, seg->stop, seg->time)); - selpad->segment_pending = FALSE; + sel->segment_pending = FALSE; } /* forward */ diff --git a/gst/playback/gststreamselector.h b/gst/playback/gststreamselector.h index 5200a0b0ce..5f01e645b7 100644 --- a/gst/playback/gststreamselector.h +++ b/gst/playback/gststreamselector.h @@ -49,6 +49,7 @@ struct _GstStreamSelector { guint padcount; GstSegment segment; + gboolean segment_pending; }; struct _GstStreamSelectorClass { diff --git a/tests/examples/seek/seek.c b/tests/examples/seek/seek.c index fcc262844d..460f3feb02 100644 --- a/tests/examples/seek/seek.c +++ b/tests/examples/seek/seek.c @@ -88,7 +88,7 @@ static gulong changed_id; static gint n_video = 0, n_audio = 0, n_text = 0; static GtkWidget *video_combo, *audio_combo, *text_combo; static GtkWidget *vis_checkbox, *video_checkbox, *audio_checkbox; -static GtkWidget *text_checkbox, *volume_spinbutton; +static GtkWidget *text_checkbox, *mute_checkbox, *volume_spinbutton; static void clear_streams (GstElement * pipeline); @@ -1364,6 +1364,7 @@ stop_cb (GtkButton * button, gpointer data) set_update_scale (FALSE); set_scale (0.0); + if (pipeline_type == 16) clear_streams (pipeline); @@ -1505,6 +1506,15 @@ text_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) update_flag (pipeline, 2, gtk_toggle_button_get_active (button)); } +static void +mute_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + gboolean mute; + + mute = gtk_toggle_button_get_active (button); + g_object_set (pipeline, "mute", mute, NULL); +} + static void clear_streams (GstElement * pipeline) { @@ -1879,17 +1889,20 @@ main (int argc, char **argv) video_checkbox = gtk_check_button_new_with_label ("Video"); audio_checkbox = gtk_check_button_new_with_label ("Audio"); text_checkbox = gtk_check_button_new_with_label ("Text"); + mute_checkbox = gtk_check_button_new_with_label ("Mute"); volume_spinbutton = gtk_spin_button_new_with_range (0, 2.0, 0.1); gtk_spin_button_set_value (GTK_SPIN_BUTTON (volume_spinbutton), 1.0); gtk_box_pack_start (GTK_BOX (boxes), vis_checkbox, TRUE, TRUE, 2); gtk_box_pack_start (GTK_BOX (boxes), audio_checkbox, TRUE, TRUE, 2); gtk_box_pack_start (GTK_BOX (boxes), video_checkbox, TRUE, TRUE, 2); gtk_box_pack_start (GTK_BOX (boxes), text_checkbox, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (boxes), mute_checkbox, TRUE, TRUE, 2); gtk_box_pack_start (GTK_BOX (boxes), volume_spinbutton, TRUE, TRUE, 2); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (vis_checkbox), TRUE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (audio_checkbox), TRUE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (video_checkbox), TRUE); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_checkbox), TRUE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mute_checkbox), FALSE); g_signal_connect (G_OBJECT (vis_checkbox), "toggled", G_CALLBACK (vis_toggle_cb), pipeline); g_signal_connect (G_OBJECT (audio_checkbox), "toggled", @@ -1898,6 +1911,8 @@ main (int argc, char **argv) G_CALLBACK (video_toggle_cb), pipeline); g_signal_connect (G_OBJECT (text_checkbox), "toggled", G_CALLBACK (text_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (mute_checkbox), "toggled", + G_CALLBACK (mute_toggle_cb), pipeline); g_signal_connect (G_OBJECT (volume_spinbutton), "value_changed", G_CALLBACK (volume_spinbutton_changed_cb), pipeline); } else {