From 21ccab1cc2130054a6289a340c1a55d125a81389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Wed, 16 Jun 2021 15:34:36 +0200 Subject: [PATCH] Add option to keep showing last video frame after playback Previously Clapper showed last frame, now it defaults to black screen, so add an option for users to choose what they like better --- data/com.github.rafostar.Clapper.gschema.xml | 4 ++ lib/gst/clapper/gtk4/gstclapperglsink.c | 46 +++++++++++++++++--- lib/gst/clapper/gtk4/gstclapperglsink.h | 7 ++- lib/gst/clapper/gtk4/gstgtkutils.c | 7 +++ lib/gst/clapper/gtk4/gstgtkutils.h | 2 + lib/gst/clapper/gtk4/gtkclapperglwidget.c | 7 +++ lib/gst/clapper/gtk4/gtkclapperglwidget.h | 1 + src/player.js | 3 +- src/prefs.js | 1 + 9 files changed, 68 insertions(+), 10 deletions(-) diff --git a/data/com.github.rafostar.Clapper.gschema.xml b/data/com.github.rafostar.Clapper.gschema.xml index 5e4ef144..ed1c57e2 100644 --- a/data/com.github.rafostar.Clapper.gschema.xml +++ b/data/com.github.rafostar.Clapper.gschema.xml @@ -14,6 +14,10 @@ 100 Custom initial volume value in percentage after startup + + false + Keep showing last video frame after playback finishes + false Automatically close the app after playback finishes diff --git a/lib/gst/clapper/gtk4/gstclapperglsink.c b/lib/gst/clapper/gtk4/gstclapperglsink.c index 73ef41dc..57511c50 100644 --- a/lib/gst/clapper/gtk4/gstclapperglsink.c +++ b/lib/gst/clapper/gtk4/gstclapperglsink.c @@ -58,6 +58,7 @@ static gboolean gst_clapper_gl_sink_propose_allocation (GstBaseSink * bsink, static gboolean gst_clapper_gl_sink_query (GstBaseSink * bsink, GstQuery * query); static gboolean gst_clapper_gl_sink_start (GstBaseSink * bsink); static gboolean gst_clapper_gl_sink_stop (GstBaseSink * bsink); +static GstFlowReturn gst_clapper_gl_sink_wait_event (GstBaseSink * bsink, GstEvent * event); static GstStateChangeReturn gst_clapper_gl_sink_change_state (GstElement * element, @@ -119,6 +120,7 @@ gst_clapper_gl_sink_class_init (GstClapperGLSinkClass * klass) gstbasesink_class->query = gst_clapper_gl_sink_query; gstbasesink_class->start = gst_clapper_gl_sink_start; gstbasesink_class->stop = gst_clapper_gl_sink_stop; + gstbasesink_class->wait_event = gst_clapper_gl_sink_wait_event; gstvideosink_class->show_frame = gst_clapper_gl_sink_show_frame; @@ -143,6 +145,9 @@ gst_clapper_gl_sink_init (GstClapperGLSink * clapper_sink) clapper_sink->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO; clapper_sink->par_n = DEFAULT_PAR_N; clapper_sink->par_d = DEFAULT_PAR_D; + clapper_sink->keep_last_frame = DEFAULT_KEEP_LAST_FRAME; + + clapper_sink->had_eos = FALSE; } static void @@ -205,12 +210,12 @@ gst_clapper_gl_sink_get_widget (GstClapperGLSink * clapper_sink) clapper_sink->widget = (GtkClapperGLWidget *) GST_CLAPPER_GL_SINK_GET_CLASS (clapper_sink)->create_widget (); - clapper_sink->bind_aspect_ratio = - g_object_bind_property (clapper_sink, "force-aspect-ratio", clapper_sink->widget, + g_object_bind_property (clapper_sink, "force-aspect-ratio", clapper_sink->widget, "force-aspect-ratio", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); - clapper_sink->bind_pixel_aspect_ratio = - g_object_bind_property (clapper_sink, "pixel-aspect-ratio", clapper_sink->widget, + g_object_bind_property (clapper_sink, "pixel-aspect-ratio", clapper_sink->widget, "pixel-aspect-ratio", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); + g_object_bind_property (clapper_sink, "keep-last-frame", clapper_sink->widget, + "keep-last-frame", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); /* Take the floating ref, other wise the destruction of the container will * make this widget disappear possibly before we are done. */ @@ -256,6 +261,9 @@ gst_clapper_gl_sink_get_property (GObject * object, guint prop_id, case PROP_PIXEL_ASPECT_RATIO: gst_value_set_fraction (value, clapper_sink->par_n, clapper_sink->par_d); break; + case PROP_KEEP_LAST_FRAME: + g_value_set_boolean (value, clapper_sink->keep_last_frame); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -276,6 +284,9 @@ gst_clapper_gl_sink_set_property (GObject * object, guint prop_id, clapper_sink->par_n = gst_value_get_fraction_numerator (value); clapper_sink->par_d = gst_value_get_fraction_denominator (value); break; + case PROP_KEEP_LAST_FRAME: + clapper_sink->keep_last_frame = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -566,6 +577,7 @@ gst_clapper_gl_sink_change_state (GstElement * element, GstStateChange transitio switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: GST_OBJECT_LOCK (clapper_sink); + clapper_sink->had_eos = FALSE; if (clapper_sink->widget) { GTK_CLAPPER_GL_WIDGET_LOCK (clapper_sink->widget); clapper_sink->widget->ignore_buffers = FALSE; @@ -591,7 +603,8 @@ gst_clapper_gl_sink_change_state (GstElement * element, GstStateChange transitio GST_OBJECT_LOCK (clapper_sink); if (clapper_sink->widget) { GTK_CLAPPER_GL_WIDGET_LOCK (clapper_sink->widget); - clapper_sink->widget->ignore_buffers = TRUE; + clapper_sink->widget->ignore_buffers = + !clapper_sink->had_eos || !clapper_sink->keep_last_frame; GTK_CLAPPER_GL_WIDGET_UNLOCK (clapper_sink->widget); } GST_OBJECT_UNLOCK (clapper_sink); @@ -683,6 +696,29 @@ gst_clapper_gl_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) return TRUE; } +static GstFlowReturn +gst_clapper_gl_sink_wait_event (GstBaseSink * bsink, GstEvent * event) +{ + GstClapperGLSink *clapper_sink = GST_CLAPPER_GL_SINK (bsink); + GstFlowReturn ret; + + ret = GST_BASE_SINK_CLASS (parent_class)->wait_event (bsink, event); + + switch (event->type) { + case GST_EVENT_EOS: + if (ret == GST_FLOW_OK) { + GST_OBJECT_LOCK (clapper_sink); + clapper_sink->had_eos = TRUE; + GST_OBJECT_UNLOCK (clapper_sink); + } + break; + default: + break; + } + + return ret; +} + static GstFlowReturn gst_clapper_gl_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf) { diff --git a/lib/gst/clapper/gtk4/gstclapperglsink.h b/lib/gst/clapper/gtk4/gstclapperglsink.h index 32796dbc..d277ab7b 100644 --- a/lib/gst/clapper/gtk4/gstclapperglsink.h +++ b/lib/gst/clapper/gtk4/gstclapperglsink.h @@ -58,15 +58,14 @@ struct _GstClapperGLSink GtkClapperGLWidget *widget; + gboolean had_eos; + /* properties */ gboolean force_aspect_ratio; - GBinding *bind_aspect_ratio; - gint par_n, par_d; - GBinding *bind_pixel_aspect_ratio; + gboolean keep_last_frame; gboolean ignore_textures; - GBinding *bind_ignore_textures; GtkWidget *window; gulong widget_destroy_id; diff --git a/lib/gst/clapper/gtk4/gstgtkutils.c b/lib/gst/clapper/gtk4/gstgtkutils.c index c658a3eb..10e9d720 100644 --- a/lib/gst/clapper/gtk4/gstgtkutils.c +++ b/lib/gst/clapper/gtk4/gstgtkutils.c @@ -85,4 +85,11 @@ gst_gtk_install_shared_properties (GObjectClass *gobject_class) gst_param_spec_fraction ("pixel-aspect-ratio", "Pixel Aspect Ratio", "The pixel aspect ratio of the device", DEFAULT_PAR_N, DEFAULT_PAR_D, G_MAXINT, 1, 1, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_KEEP_LAST_FRAME, + g_param_spec_boolean ("keep-last-frame", + "Keep last frame", + "Keep showing last video frame after playback instead of black screen", + DEFAULT_KEEP_LAST_FRAME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } diff --git a/lib/gst/clapper/gtk4/gstgtkutils.h b/lib/gst/clapper/gtk4/gstgtkutils.h index 4fce7449..ced23142 100644 --- a/lib/gst/clapper/gtk4/gstgtkutils.h +++ b/lib/gst/clapper/gtk4/gstgtkutils.h @@ -25,6 +25,7 @@ #define DEFAULT_FORCE_ASPECT_RATIO TRUE #define DEFAULT_PAR_N 0 #define DEFAULT_PAR_D 1 +#define DEFAULT_KEEP_LAST_FRAME FALSE #include #include @@ -35,6 +36,7 @@ enum PROP_WIDGET, PROP_FORCE_ASPECT_RATIO, PROP_PIXEL_ASPECT_RATIO, + PROP_KEEP_LAST_FRAME }; gpointer gst_gtk_invoke_on_main (GThreadFunc func, gpointer data); diff --git a/lib/gst/clapper/gtk4/gtkclapperglwidget.c b/lib/gst/clapper/gtk4/gtkclapperglwidget.c index ff25433b..bb1cfcd5 100644 --- a/lib/gst/clapper/gtk4/gtkclapperglwidget.c +++ b/lib/gst/clapper/gtk4/gtkclapperglwidget.c @@ -163,6 +163,9 @@ gtk_clapper_gl_widget_set_property (GObject * object, guint prop_id, clapper_widget->par_n = gst_value_get_fraction_numerator (value); clapper_widget->par_d = gst_value_get_fraction_denominator (value); break; + case PROP_KEEP_LAST_FRAME: + clapper_widget->keep_last_frame = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -182,6 +185,9 @@ gtk_clapper_gl_widget_get_property (GObject * object, guint prop_id, case PROP_PIXEL_ASPECT_RATIO: gst_value_set_fraction (value, clapper_widget->par_n, clapper_widget->par_d); break; + case PROP_KEEP_LAST_FRAME: + g_value_set_boolean (value, clapper_widget->keep_last_frame); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -924,6 +930,7 @@ gtk_clapper_gl_widget_init (GtkClapperGLWidget * clapper_widget) clapper_widget->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO; clapper_widget->par_n = DEFAULT_PAR_N; clapper_widget->par_d = DEFAULT_PAR_D; + clapper_widget->keep_last_frame = DEFAULT_KEEP_LAST_FRAME; clapper_widget->ignore_buffers = FALSE; clapper_widget->last_pos_x = 0; clapper_widget->last_pos_y = 0; diff --git a/lib/gst/clapper/gtk4/gtkclapperglwidget.h b/lib/gst/clapper/gtk4/gtkclapperglwidget.h index 4f61aaba..acfbe412 100644 --- a/lib/gst/clapper/gtk4/gtkclapperglwidget.h +++ b/lib/gst/clapper/gtk4/gtkclapperglwidget.h @@ -52,6 +52,7 @@ struct _GtkClapperGLWidget /* properties */ gboolean force_aspect_ratio; gint par_n, par_d; + gboolean keep_last_frame; gint display_width; gint display_height; diff --git a/src/player.js b/src/player.js index c230f9c1..d75b94d0 100644 --- a/src/player.js +++ b/src/player.js @@ -81,7 +81,8 @@ class ClapperPlayer extends GstClapper.Clapper this._onSettingsKeyChanged(settings, key); const flag = Gio.SettingsBindFlags.GET; - settings.bind('subtitle-font', this.pipeline, 'subtitle_font_desc', flag); + settings.bind('keep-last-frame', this.widget, 'keep-last-frame', flag); + settings.bind('subtitle-font', this.pipeline, 'subtitle-font-desc', flag); } set_initial_config() diff --git a/src/prefs.js b/src/prefs.js index 2c0fb907..6d4047fb 100644 --- a/src/prefs.js +++ b/src/prefs.js @@ -41,6 +41,7 @@ class ClapperGeneralPage extends PrefsBase.Grid comboBox.connect('changed', this._onVolumeInitialChanged.bind(this, spinButton)); this.addTitle('Finish'); + this.addCheckButton('Keep showing last frame', 'keep-last-frame'); this.addCheckButton('Close after playback', 'close-auto'); }