Flatpak: remove patches that are now part of the app

This commit is contained in:
Rafał Dzięgiel
2021-02-05 20:01:09 +01:00
parent 8ca73fd56b
commit a6b2b9dd0a
8 changed files with 0 additions and 2026 deletions

View File

@@ -1,26 +0,0 @@
From 5c500284dd8c12a383098d9227a22146d0aa8417 Mon Sep 17 00:00:00 2001
From: Rafostar <rafostar.github@gmail.com>
Date: Wed, 4 Nov 2020 21:16:42 +0100
Subject: [PATCH] GstPlayer: call ref_sink on pipeline
As discussed in #1450
---
gst-libs/gst/player/gstplayer.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/gst-libs/gst/player/gstplayer.c b/gst-libs/gst/player/gstplayer.c
index b2e318fc3..04148fa1d 100644
--- a/gst-libs/gst/player/gstplayer.c
+++ b/gst-libs/gst/player/gstplayer.c
@@ -2907,6 +2907,8 @@ gst_player_main (gpointer data)
g_assert_not_reached ();
}
+ gst_object_ref_sink (self->playbin);
+
if (self->video_renderer) {
GstElement *video_sink =
gst_player_video_renderer_create_video_sink (self->video_renderer,
--
2.26.2

View File

@@ -1,188 +0,0 @@
From e2170cbdc7d6f0b6dd0693f683a1ada76ffda2bf Mon Sep 17 00:00:00 2001
From: Rafostar <rafostar.github@gmail.com>
Date: Tue, 12 Jan 2021 13:23:19 +0100
Subject: [PATCH] player: add TOC support
Retrive and store TOC data as part of global MediaInfo object.
This is useful for obtaining various video info stored in TOC (e.g. chapters).
---
.../gst/player/gstplayer-media-info-private.h | 1 +
gst-libs/gst/player/gstplayer-media-info.c | 19 ++++++++
gst-libs/gst/player/gstplayer-media-info.h | 3 ++
gst-libs/gst/player/gstplayer.c | 46 +++++++++++++++++++
4 files changed, 69 insertions(+)
diff --git a/gst-libs/gst/player/gstplayer-media-info-private.h b/gst-libs/gst/player/gstplayer-media-info-private.h
index 70aaea925..5c9902287 100644
--- a/gst-libs/gst/player/gstplayer-media-info-private.h
+++ b/gst-libs/gst/player/gstplayer-media-info-private.h
@@ -99,6 +99,7 @@ struct _GstPlayerMediaInfo
gchar *container;
gboolean seekable, is_live;
GstTagList *tags;
+ GstToc *toc;
GstSample *image_sample;
GList *stream_list;
diff --git a/gst-libs/gst/player/gstplayer-media-info.c b/gst-libs/gst/player/gstplayer-media-info.c
index 6c9a4a887..4b31e8a3e 100644
--- a/gst-libs/gst/player/gstplayer-media-info.c
+++ b/gst-libs/gst/player/gstplayer-media-info.c
@@ -430,6 +430,9 @@ gst_player_media_info_finalize (GObject * object)
g_free (info->container);
+ if (info->toc)
+ gst_toc_unref (info->toc);
+
if (info->image_sample)
gst_sample_unref (info->image_sample);
@@ -566,6 +569,8 @@ gst_player_media_info_copy (GstPlayerMediaInfo * ref)
info->is_live = ref->is_live;
if (ref->tags)
info->tags = gst_tag_list_ref (ref->tags);
+ if (ref->toc)
+ info->toc = gst_toc_ref (ref->toc);
if (ref->title)
info->title = g_strdup (ref->title);
if (ref->container)
@@ -751,6 +756,20 @@ gst_player_media_info_get_tags (const GstPlayerMediaInfo * info)
return info->tags;
}
+/**
+ * gst_player_media_info_get_toc:
+ * @info: a #GstPlayerMediaInfo
+ *
+ * Returns: (transfer none): the toc contained in media info.
+ */
+GstToc *
+gst_player_media_info_get_toc (const GstPlayerMediaInfo * info)
+{
+ g_return_val_if_fail (GST_IS_PLAYER_MEDIA_INFO (info), NULL);
+
+ return info->toc;
+}
+
/**
* gst_player_media_info_get_title:
* @info: a #GstPlayerMediaInfo
diff --git a/gst-libs/gst/player/gstplayer-media-info.h b/gst-libs/gst/player/gstplayer-media-info.h
index ab034b158..8f6220ad9 100644
--- a/gst-libs/gst/player/gstplayer-media-info.h
+++ b/gst-libs/gst/player/gstplayer-media-info.h
@@ -232,6 +232,9 @@ guint gst_player_media_info_get_number_of_subtitle_streams (const GstPla
GST_PLAYER_API
GstTagList* gst_player_media_info_get_tags (const GstPlayerMediaInfo *info);
+GST_PLAYER_API
+GstToc* gst_player_media_info_get_toc (const GstPlayerMediaInfo *info);
+
GST_PLAYER_API
const gchar* gst_player_media_info_get_title (const GstPlayerMediaInfo *info);
diff --git a/gst-libs/gst/player/gstplayer.c b/gst-libs/gst/player/gstplayer.c
index 62d5cb487..76c2341ba 100644
--- a/gst-libs/gst/player/gstplayer.c
+++ b/gst-libs/gst/player/gstplayer.c
@@ -182,6 +182,7 @@ struct _GstPlayer
gint buffering;
GstTagList *global_tags;
+ GstToc *global_toc;
GstPlayerMediaInfo *media_info;
GstElement *current_vis_element;
@@ -542,6 +543,8 @@ gst_player_finalize (GObject * object)
g_free (self->subtitle_sid);
if (self->global_tags)
gst_tag_list_unref (self->global_tags);
+ if (self->global_toc)
+ gst_toc_unref (self->global_toc);
if (self->video_renderer)
g_object_unref (self->video_renderer);
if (self->signal_dispatcher)
@@ -1120,6 +1123,11 @@ emit_error (GstPlayer * self, GError * err)
self->global_tags = NULL;
}
+ if (self->global_toc) {
+ gst_toc_unref (self->global_toc);
+ self->global_toc = NULL;
+ }
+
self->seek_pending = FALSE;
remove_seek_source (self);
self->seek_position = GST_CLOCK_TIME_NONE;
@@ -1819,6 +1827,37 @@ tags_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg, gpointer user_data)
gst_tag_list_unref (tags);
}
+static void
+toc_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg, gpointer user_data)
+{
+ GstPlayer *self = GST_PLAYER (user_data);
+ GstToc *toc = NULL;
+
+ gst_message_parse_toc (msg, &toc, NULL);
+
+ GST_DEBUG_OBJECT (self, "received %s toc",
+ gst_toc_get_scope (toc) == GST_TOC_SCOPE_GLOBAL ? "global" : "stream");
+
+ if (gst_toc_get_scope (toc) == GST_TOC_SCOPE_GLOBAL) {
+ g_mutex_lock (&self->lock);
+ if (self->media_info) {
+ if (self->media_info->toc)
+ gst_toc_unref (self->media_info->toc);
+ self->media_info->toc = gst_toc_ref (toc);
+ media_info_update (self, self->media_info);
+ g_mutex_unlock (&self->lock);
+ emit_media_info_updated_signal (self);
+ } else {
+ if (self->global_toc)
+ gst_toc_unref (self->global_toc);
+ self->global_toc = gst_toc_ref (toc);
+ g_mutex_unlock (&self->lock);
+ }
+ }
+
+ gst_toc_unref (toc);
+}
+
static void
element_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg, gpointer user_data)
{
@@ -2743,8 +2782,10 @@ gst_player_media_info_create (GstPlayer * self)
media_info = gst_player_media_info_new (self->uri);
media_info->duration = gst_player_get_duration (self);
media_info->tags = self->global_tags;
+ media_info->toc = self->global_toc;
media_info->is_live = self->is_live;
self->global_tags = NULL;
+ self->global_toc = NULL;
query = gst_query_new_seeking (GST_FORMAT_TIME);
if (gst_element_query (self->playbin, query))
@@ -2969,6 +3010,7 @@ gst_player_main (gpointer data)
g_signal_connect (G_OBJECT (bus), "message::element",
G_CALLBACK (element_cb), self);
g_signal_connect (G_OBJECT (bus), "message::tag", G_CALLBACK (tags_cb), self);
+ g_signal_connect (G_OBJECT (bus), "message::toc", G_CALLBACK (toc_cb), self);
if (self->use_playbin3) {
g_signal_connect (G_OBJECT (bus), "message::stream-collection",
@@ -3273,6 +3315,10 @@ gst_player_stop_internal (GstPlayer * self, gboolean transient)
gst_tag_list_unref (self->global_tags);
self->global_tags = NULL;
}
+ if (self->global_toc) {
+ gst_toc_unref (self->global_toc);
+ self->global_toc = NULL;
+ }
self->seek_pending = FALSE;
remove_seek_source (self);
self->seek_position = GST_CLOCK_TIME_NONE;
--
2.28.0

View File

@@ -1,310 +0,0 @@
From bb4191a149108cda6d8a34814c1a3acdcfc74f56 Mon Sep 17 00:00:00 2001
From: Rafostar <40623528+Rafostar@users.noreply.github.com>
Date: Mon, 9 Nov 2020 11:22:32 +0100
Subject: [PATCH] player: set seek mode without stopping playback
Move seek mode setting outside of "config" object, so it can be changed without stopping playback.
---
gst-libs/gst/player/gstplayer.c | 117 ++++++++++++++++++++------------
gst-libs/gst/player/gstplayer.h | 30 ++++++--
2 files changed, 98 insertions(+), 49 deletions(-)
diff --git a/gst-libs/gst/player/gstplayer.c b/gst-libs/gst/player/gstplayer.c
index 45705c671..d13c0cc63 100644
--- a/gst-libs/gst/player/gstplayer.c
+++ b/gst-libs/gst/player/gstplayer.c
@@ -70,6 +70,7 @@ GST_DEBUG_CATEGORY_STATIC (gst_player_debug);
#define DEFAULT_POSITION_UPDATE_INTERVAL_MS 100
#define DEFAULT_AUDIO_VIDEO_OFFSET 0
#define DEFAULT_SUBTITLE_VIDEO_OFFSET 0
+#define DEFAULT_SEEK_MODE GST_PLAYER_SEEK_MODE_DEFAULT
/**
* gst_player_error_quark:
@@ -87,7 +88,6 @@ typedef enum
{
CONFIG_QUARK_USER_AGENT = 0,
CONFIG_QUARK_POSITION_INTERVAL_UPDATE,
- CONFIG_QUARK_ACCURATE_SEEK,
CONFIG_QUARK_MAX
} ConfigQuarkId;
@@ -95,7 +95,6 @@ typedef enum
static const gchar *_config_quark_strings[] = {
"user-agent",
"position-interval-update",
- "accurate-seek",
};
GQuark _config_quark_table[CONFIG_QUARK_MAX];
@@ -123,6 +122,7 @@ enum
PROP_VIDEO_MULTIVIEW_FLAGS,
PROP_AUDIO_VIDEO_OFFSET,
PROP_SUBTITLE_VIDEO_OFFSET,
+ PROP_SEEK_MODE,
PROP_LAST
};
@@ -188,6 +188,8 @@ struct _GstPlayer
GstStructure *config;
+ GstPlayerSeekMode seek_mode;
+
/* Protected by lock */
gboolean seek_pending; /* Only set from main context */
GstClockTime last_seek_time; /* Only set from main context */
@@ -294,7 +296,6 @@ gst_player_init (GstPlayer * self)
/* *INDENT-OFF* */
self->config = gst_structure_new_id (QUARK_CONFIG,
CONFIG_QUARK (POSITION_INTERVAL_UPDATE), G_TYPE_UINT, DEFAULT_POSITION_UPDATE_INTERVAL_MS,
- CONFIG_QUARK (ACCURATE_SEEK), G_TYPE_BOOLEAN, FALSE,
NULL);
/* *INDENT-ON* */
@@ -424,6 +425,12 @@ gst_player_class_init (GstPlayerClass * klass)
"The synchronisation offset between text and video in nanoseconds",
G_MININT64, G_MAXINT64, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ param_specs[PROP_SEEK_MODE] =
+ g_param_spec_enum ("seek-mode", "Player Seek Mode",
+ "Selected player seek mode to use when performing seeks",
+ GST_TYPE_PLAYER_SEEK_MODE, DEFAULT_SEEK_MODE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
g_object_class_install_properties (gobject_class, PROP_LAST, param_specs);
signals[SIGNAL_URI_LOADED] =
@@ -747,6 +754,11 @@ gst_player_set_property (GObject * object, guint prop_id,
case PROP_SUBTITLE_VIDEO_OFFSET:
g_object_set_property (G_OBJECT (self->playbin), "text-offset", value);
break;
+ case PROP_SEEK_MODE:
+ g_mutex_lock (&self->lock);
+ self->seek_mode = g_value_get_enum (value);
+ g_mutex_unlock (&self->lock);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -847,6 +859,11 @@ gst_player_get_property (GObject * object, guint prop_id,
case PROP_SUBTITLE_VIDEO_OFFSET:
g_object_get_property (G_OBJECT (self->playbin), "text-offset", value);
break;
+ case PROP_SEEK_MODE:
+ g_mutex_lock (&self->lock);
+ g_value_set_enum (value, self->seek_mode);
+ g_mutex_unlock (&self->lock);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -2988,6 +3005,7 @@ gst_player_main (gpointer data)
self->is_eos = FALSE;
self->is_live = FALSE;
self->rate = 1.0;
+ self->seek_mode = DEFAULT_SEEK_MODE;
GST_TRACE_OBJECT (self, "Starting main loop");
g_main_loop_run (self->loop);
@@ -3316,8 +3334,8 @@ gst_player_seek_internal_locked (GstPlayer * self)
gdouble rate;
GstStateChangeReturn state_ret;
GstEvent *s_event;
+ GstPlayerSeekMode seek_mode;
GstSeekFlags flags = 0;
- gboolean accurate = FALSE;
remove_seek_source (self);
@@ -3330,8 +3348,6 @@ gst_player_seek_internal_locked (GstPlayer * self)
if (state_ret == GST_STATE_CHANGE_FAILURE) {
emit_error (self, g_error_new (GST_PLAYER_ERROR, GST_PLAYER_ERROR_FAILED,
"Failed to seek"));
- g_mutex_lock (&self->lock);
- return;
}
g_mutex_lock (&self->lock);
return;
@@ -3342,6 +3358,7 @@ gst_player_seek_internal_locked (GstPlayer * self)
self->seek_position = GST_CLOCK_TIME_NONE;
self->seek_pending = TRUE;
rate = self->rate;
+ seek_mode = self->seek_mode;
g_mutex_unlock (&self->lock);
remove_tick_source (self);
@@ -3349,12 +3366,15 @@ gst_player_seek_internal_locked (GstPlayer * self)
flags |= GST_SEEK_FLAG_FLUSH;
- accurate = gst_player_config_get_seek_accurate (self->config);
-
- if (accurate) {
- flags |= GST_SEEK_FLAG_ACCURATE;
- } else {
- flags &= ~GST_SEEK_FLAG_ACCURATE;
+ switch (seek_mode) {
+ case GST_PLAYER_SEEK_MODE_ACCURATE:
+ flags |= GST_SEEK_FLAG_ACCURATE;
+ break;
+ case GST_PLAYER_SEEK_MODE_FAST:
+ flags |= GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_SNAP_AFTER;
+ break;
+ default:
+ break;
}
if (rate != 1.0) {
@@ -4692,51 +4712,62 @@ gst_player_config_get_position_update_interval (const GstStructure * config)
return interval;
}
+GType
+gst_player_seek_mode_get_type (void)
+{
+ static gsize id = 0;
+ static const GEnumValue values[] = {
+ {C_ENUM (GST_PLAYER_SEEK_MODE_DEFAULT), "GST_PLAYER_SEEK_MODE_DEFAULT",
+ "default"},
+ {C_ENUM (GST_PLAYER_SEEK_MODE_ACCURATE), "GST_PLAYER_SEEK_MODE_ACCURATE",
+ "accurate"},
+ {C_ENUM (GST_PLAYER_SEEK_MODE_FAST), "GST_PLAYER_SEEK_MODE_FAST", "fast"},
+ {0, NULL, NULL}
+ };
+
+ if (g_once_init_enter (&id)) {
+ GType tmp = g_enum_register_static ("GstPlayerSeekMode", values);
+ g_once_init_leave (&id, tmp);
+ }
+
+ return (GType) id;
+}
+
/**
- * gst_player_config_set_seek_accurate:
- * @config: a #GstPlayer configuration
- * @accurate: accurate seek or not
- *
- * Enable or disable accurate seeking. When enabled, elements will try harder
- * to seek as accurately as possible to the requested seek position. Generally
- * it will be slower especially for formats that don't have any indexes or
- * timestamp markers in the stream.
- *
- * If accurate seeking is disabled, elements will seek as close as the request
- * position without slowing down seeking too much.
+ * gst_player_get_seek_mode:
+ * @player: #GstPlayer instance
*
- * Accurate seeking is disabled by default.
+ * Returns: The currently used seek mode, Default: 0 "default"
*
- * Since: 1.12
+ * Since: 1.20
*/
-void
-gst_player_config_set_seek_accurate (GstStructure * config, gboolean accurate)
+GstPlayerSeekMode
+gst_player_get_seek_mode (GstPlayer * self)
{
- g_return_if_fail (config != NULL);
+ GstPlayerSeekMode mode;
- gst_structure_id_set (config,
- CONFIG_QUARK (ACCURATE_SEEK), G_TYPE_BOOLEAN, accurate, NULL);
+ g_return_val_if_fail (GST_IS_PLAYER (self), DEFAULT_SEEK_MODE);
+
+ g_object_get (self, "seek-mode", &mode, NULL);
+
+ return mode;
}
/**
- * gst_player_config_get_seek_accurate:
- * @config: a #GstPlayer configuration
+ * gst_player_set_seek_mode:
+ * @player: #GstPlayer instance
+ * @mode: #GstPlayerSeekMode
*
- * Returns: %TRUE if accurate seeking is enabled
+ * Changes currently used player seek mode to the one of @mode
*
- * Since: 1.12
+ * Since: 1.20
*/
-gboolean
-gst_player_config_get_seek_accurate (const GstStructure * config)
+void
+gst_player_set_seek_mode (GstPlayer * self, GstPlayerSeekMode mode)
{
- gboolean accurate = FALSE;
-
- g_return_val_if_fail (config != NULL, FALSE);
-
- gst_structure_id_get (config,
- CONFIG_QUARK (ACCURATE_SEEK), G_TYPE_BOOLEAN, &accurate, NULL);
+ g_return_if_fail (GST_IS_PLAYER (self));
- return accurate;
+ g_object_set (self, "seek-mode", mode, NULL);
}
/**
diff --git a/gst-libs/gst/player/gstplayer.h b/gst-libs/gst/player/gstplayer.h
index e853ed875..9c0ab5a60 100644
--- a/gst-libs/gst/player/gstplayer.h
+++ b/gst-libs/gst/player/gstplayer.h
@@ -96,6 +96,23 @@ typedef enum
GST_PLAYER_API
const gchar *gst_player_color_balance_type_get_name (GstPlayerColorBalanceType type);
+GST_PLAYER_API
+GType gst_player_seek_mode_get_type (void);
+#define GST_TYPE_PLAYER_SEEK_MODE (gst_player_seek_mode_get_type ())
+
+/**
+ * GstPlayerSeekMode:
+ * @GST_PLAYER_SEEK_MODE_DEFAULT: default seek method (flush only).
+ * @GST_PLAYER_SEEK_MODE_ACCURATE: accurate seek method.
+ * @GST_PLAYER_SEEK_MODE_FAST: fast seek method (next keyframe).
+ */
+typedef enum
+{
+ GST_PLAYER_SEEK_MODE_DEFAULT,
+ GST_PLAYER_SEEK_MODE_ACCURATE,
+ GST_PLAYER_SEEK_MODE_FAST,
+} GstPlayerSeekMode;
+
#define GST_TYPE_PLAYER (gst_player_get_type ())
#define GST_IS_PLAYER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PLAYER))
#define GST_IS_PLAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PLAYER))
@@ -127,6 +144,13 @@ GST_PLAYER_API
void gst_player_seek (GstPlayer * player,
GstClockTime position);
+GST_PLAYER_API
+GstPlayerSeekMode gst_player_get_seek_mode (GstPlayer * player);
+
+GST_PLAYER_API
+void gst_player_set_seek_mode (GstPlayer * player,
+ GstPlayerSeekMode mode);
+
GST_PLAYER_API
void gst_player_set_rate (GstPlayer * player,
gdouble rate);
@@ -282,12 +306,6 @@ void gst_player_config_set_position_update_interval (GstStructure * c
GST_PLAYER_API
guint gst_player_config_get_position_update_interval (const GstStructure * config);
-GST_PLAYER_API
-void gst_player_config_set_seek_accurate (GstStructure * config, gboolean accurate);
-
-GST_PLAYER_API
-gboolean gst_player_config_get_seek_accurate (const GstStructure * config);
-
typedef enum
{
GST_PLAYER_THUMBNAIL_RAW_NATIVE = 0,
--
2.26.2

View File

@@ -25,18 +25,6 @@
"tag": "1.18.1",
"commit": "e5c3c106a2da607953fea36e3a253b382c939684"
},
{
"type": "patch",
"path": "gst-plugins-bad-gstplayer-ref-sink.patch"
},
{
"type": "patch",
"path": "gst-plugins-bad-set-seeking-method-without-stopping-playback.patch"
},
{
"type": "patch",
"path": "gst-plugins-bad-player-add-toc-support.patch"
},
{
"type": "patch",
"path": "gst-plugins-bad-vah264dec-fix-seeking-errors.patch"

View File

@@ -1,108 +0,0 @@
From 7808862454aa50afde85462c1b55a256096bfdef Mon Sep 17 00:00:00 2001
From: Rafostar <rafostar.github@gmail.com>
Date: Thu, 12 Nov 2020 18:16:23 +0100
Subject: [PATCH] gtk4: do not depend on "destroy" signal for cleanup
In GTK4 the "destroy" signal will not be emitted
as long as someone is holding a ref on an object.
We cannot use it to do the unref anymore.
This commit removes the floating ref and "destroy"
signal connection used to do the unref.
---
ext/gtk/gstgtkbasesink.c | 27 ++++++---------------------
ext/gtk/gstgtkbasesink.h | 1 -
2 files changed, 6 insertions(+), 22 deletions(-)
diff --git a/ext/gtk/gstgtkbasesink.c b/ext/gtk/gstgtkbasesink.c
index 1f5319089..ea11bec40 100644
--- a/ext/gtk/gstgtkbasesink.c
+++ b/ext/gtk/gstgtkbasesink.c
@@ -153,21 +153,12 @@ gst_gtk_base_sink_finalize (GObject * object)
GST_OBJECT_LOCK (gtk_sink);
if (gtk_sink->window && gtk_sink->window_destroy_id)
g_signal_handler_disconnect (gtk_sink->window, gtk_sink->window_destroy_id);
- if (gtk_sink->widget && gtk_sink->widget_destroy_id)
- g_signal_handler_disconnect (gtk_sink->widget, gtk_sink->widget_destroy_id);
- g_clear_object (&gtk_sink->widget);
+ gtk_sink->widget = NULL;
GST_OBJECT_UNLOCK (gtk_sink);
G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-widget_destroy_cb (GtkWidget * widget, GstGtkBaseSink * gtk_sink)
-{
- GST_OBJECT_LOCK (gtk_sink);
- g_clear_object (&gtk_sink->widget);
- GST_OBJECT_UNLOCK (gtk_sink);
+ GST_DEBUG ("finalized base sink");
}
static void
@@ -211,12 +202,6 @@ gst_gtk_base_sink_get_widget (GstGtkBaseSink * gtk_sink)
"ignore-alpha", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
#endif
- /* Take the floating ref, other wise the destruction of the container will
- * make this widget disappear possibly before we are done. */
- gst_object_ref_sink (gtk_sink->widget);
- gtk_sink->widget_destroy_id = g_signal_connect (gtk_sink->widget, "destroy",
- G_CALLBACK (widget_destroy_cb), gtk_sink);
-
/* back pointer */
gtk_gst_base_widget_set_element (GTK_GST_BASE_WIDGET (gtk_sink->widget),
GST_ELEMENT (gtk_sink));
@@ -236,7 +221,7 @@ gst_gtk_base_sink_get_property (GObject * object, guint prop_id,
GObject *widget = NULL;
GST_OBJECT_LOCK (gtk_sink);
- if (gtk_sink->widget != NULL)
+ if (GTK_IS_WIDGET (gtk_sink->widget))
widget = G_OBJECT (gtk_sink->widget);
GST_OBJECT_UNLOCK (gtk_sink);
@@ -457,7 +442,7 @@ gst_gtk_base_sink_change_state (GstElement * element, GstStateChange transition)
}
case GST_STATE_CHANGE_PAUSED_TO_READY:
GST_OBJECT_LOCK (gtk_sink);
- if (gtk_sink->widget)
+ if (GTK_IS_WIDGET (gtk_sink->widget))
gtk_gst_base_widget_set_buffer (gtk_sink->widget, NULL);
GST_OBJECT_UNLOCK (gtk_sink);
break;
@@ -503,7 +488,7 @@ gst_gtk_base_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
GST_OBJECT_LOCK (gtk_sink);
- if (gtk_sink->widget == NULL) {
+ if (!GTK_IS_WIDGET (gtk_sink->widget)) {
GST_OBJECT_UNLOCK (gtk_sink);
GST_ELEMENT_ERROR (gtk_sink, RESOURCE, NOT_FOUND,
("%s", "Output widget was destroyed"), (NULL));
@@ -530,7 +515,7 @@ gst_gtk_base_sink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
GST_OBJECT_LOCK (vsink);
- if (gtk_sink->widget == NULL) {
+ if (!GTK_IS_WIDGET (gtk_sink->widget)) {
GST_OBJECT_UNLOCK (gtk_sink);
GST_ELEMENT_ERROR (gtk_sink, RESOURCE, NOT_FOUND,
("%s", "Output widget was destroyed"), (NULL));
diff --git a/ext/gtk/gstgtkbasesink.h b/ext/gtk/gstgtkbasesink.h
index 650175036..f2668fabc 100644
--- a/ext/gtk/gstgtkbasesink.h
+++ b/ext/gtk/gstgtkbasesink.h
@@ -69,7 +69,6 @@ struct _GstGtkBaseSink
GBinding *bind_ignore_alpha;
GtkWidget *window;
- gulong widget_destroy_id;
gulong window_destroy_id;
};
--
2.26.2

View File

@@ -1,419 +0,0 @@
From 55cd1534d09228f14bcea14848ef226b6d88edfd Mon Sep 17 00:00:00 2001
From: Rafostar <40623528+Rafostar@users.noreply.github.com>
Date: Mon, 16 Nov 2020 13:32:50 +0100
Subject: [PATCH 1/6] gtk(4): draw black before priv contexts are available
---
ext/gtk/gtkgstglwidget.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/ext/gtk/gtkgstglwidget.c b/ext/gtk/gtkgstglwidget.c
index 186144a1c..3d6fe05a2 100644
--- a/ext/gtk/gtkgstglwidget.c
+++ b/ext/gtk/gtkgstglwidget.c
@@ -225,6 +225,14 @@ _draw_black (GstGLContext * context)
gl->Clear (GL_COLOR_BUFFER_BIT);
}
+static inline void
+_draw_black_with_gdk (GdkGLContext * gdk_context)
+{
+ GST_DEBUG ("rendering empty frame with gdk context %p", gdk_context);
+ glClearColor (0.0, 0.0, 0.0, 1.0);
+ glClear (GL_COLOR_BUFFER_BIT);
+}
+
static gboolean
gtk_gst_gl_widget_render (GtkGLArea * widget, GdkGLContext * context)
{
@@ -233,8 +241,13 @@ gtk_gst_gl_widget_render (GtkGLArea * widget, GdkGLContext * context)
GTK_GST_BASE_WIDGET_LOCK (widget);
- if (!priv->context || !priv->other_context)
+ /* Draw black with GDK context when priv is not available yet.
+ GTK calls render with GDK context already active. */
+ if (!priv->context || !priv->other_context) {
+ GdkGLContext *gdk_context = gtk_gl_area_get_context (widget);
+ _draw_black_with_gdk (gdk_context);
goto done;
+ }
gst_gl_context_activate (priv->other_context, TRUE);
--
2.26.2
From c477954dd41ff506b07fe89aa241769809efdeb8 Mon Sep 17 00:00:00 2001
From: Rafostar <40623528+Rafostar@users.noreply.github.com>
Date: Mon, 16 Nov 2020 16:04:45 +0100
Subject: [PATCH 2/6] gtk(4): draw black when not initiated
---
ext/gtk/gtkgstglwidget.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/ext/gtk/gtkgstglwidget.c b/ext/gtk/gtkgstglwidget.c
index 3d6fe05a2..d1422f8bb 100644
--- a/ext/gtk/gtkgstglwidget.c
+++ b/ext/gtk/gtkgstglwidget.c
@@ -62,7 +62,7 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
struct _GtkGstGLWidgetPrivate
{
- gboolean initted;
+ gboolean initiated;
GstGLDisplay *display;
GdkGLContext *gdk_context;
GstGLContext *other_context;
@@ -159,7 +159,7 @@ gtk_gst_gl_widget_init_redisplay (GtkGstGLWidget * gst_widget)
priv->overlay_compositor =
gst_gl_overlay_compositor_new (priv->other_context);
- priv->initted = TRUE;
+ priv->initiated = TRUE;
}
static void
@@ -251,10 +251,10 @@ gtk_gst_gl_widget_render (GtkGLArea * widget, GdkGLContext * context)
gst_gl_context_activate (priv->other_context, TRUE);
- if (!priv->initted)
- gtk_gst_gl_widget_init_redisplay (GTK_GST_GL_WIDGET (widget));
+ if (!priv->initiated || !base_widget->negotiated) {
+ if (!priv->initiated)
+ gtk_gst_gl_widget_init_redisplay (GTK_GST_GL_WIDGET (widget));
- if (!priv->initted || !base_widget->negotiated) {
_draw_black (priv->other_context);
goto done;
}
--
2.26.2
From eb407306f30e13e7a6ada116e8b4b5812da67b72 Mon Sep 17 00:00:00 2001
From: Rafostar <40623528+Rafostar@users.noreply.github.com>
Date: Mon, 16 Nov 2020 22:13:46 +0100
Subject: [PATCH 3/6] gtk(4): add ignore textures property for glsink
---
ext/gtk/gstgtkbasesink.c | 18 ++++++++++++++++++
ext/gtk/gstgtkbasesink.h | 10 +++++++---
ext/gtk/gtkgstbasewidget.c | 14 ++++++++++++++
ext/gtk/gtkgstbasewidget.h | 1 +
ext/gtk/gtkgstglwidget.c | 3 ++-
5 files changed, 42 insertions(+), 4 deletions(-)
diff --git a/ext/gtk/gstgtkbasesink.c b/ext/gtk/gstgtkbasesink.c
index ea11bec40..666bbef54 100644
--- a/ext/gtk/gstgtkbasesink.c
+++ b/ext/gtk/gstgtkbasesink.c
@@ -39,6 +39,7 @@ GST_DEBUG_CATEGORY (gst_debug_gtk_base_sink);
#define DEFAULT_PAR_N 0
#define DEFAULT_PAR_D 1
#define DEFAULT_IGNORE_ALPHA TRUE
+#define DEFAULT_IGNORE_TEXTURES FALSE
static void gst_gtk_base_sink_finalize (GObject * object);
static void gst_gtk_base_sink_set_property (GObject * object, guint prop_id,
@@ -70,6 +71,7 @@ enum
PROP_FORCE_ASPECT_RATIO,
PROP_PIXEL_ASPECT_RATIO,
PROP_IGNORE_ALPHA,
+ PROP_IGNORE_TEXTURES,
};
#define gst_gtk_base_sink_parent_class parent_class
@@ -123,6 +125,11 @@ gst_gtk_base_sink_class_init (GstGtkBaseSinkClass * klass)
DEFAULT_IGNORE_ALPHA, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
#endif
+ g_object_class_install_property (gobject_class, PROP_IGNORE_TEXTURES,
+ g_param_spec_boolean ("ignore-textures", "Ignore Textures",
+ "When enabled, textures will be ignored and not drawn",
+ DEFAULT_IGNORE_TEXTURES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
gobject_class->finalize = gst_gtk_base_sink_finalize;
gstelement_class->change_state = gst_gtk_base_sink_change_state;
@@ -143,6 +150,7 @@ gst_gtk_base_sink_init (GstGtkBaseSink * gtk_sink)
gtk_sink->par_n = DEFAULT_PAR_N;
gtk_sink->par_d = DEFAULT_PAR_D;
gtk_sink->ignore_alpha = DEFAULT_IGNORE_ALPHA;
+ gtk_sink->ignore_textures = DEFAULT_IGNORE_TEXTURES;
}
static void
@@ -202,6 +210,10 @@ gst_gtk_base_sink_get_widget (GstGtkBaseSink * gtk_sink)
"ignore-alpha", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
#endif
+ gtk_sink->bind_ignore_textures =
+ g_object_bind_property (gtk_sink, "ignore-textures", gtk_sink->widget,
+ "ignore-textures", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+
/* back pointer */
gtk_gst_base_widget_set_element (GTK_GST_BASE_WIDGET (gtk_sink->widget),
GST_ELEMENT (gtk_sink));
@@ -242,6 +254,9 @@ gst_gtk_base_sink_get_property (GObject * object, guint prop_id,
case PROP_IGNORE_ALPHA:
g_value_set_boolean (value, gtk_sink->ignore_alpha);
break;
+ case PROP_IGNORE_TEXTURES:
+ g_value_set_boolean (value, gtk_sink->ignore_textures);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -265,6 +280,9 @@ gst_gtk_base_sink_set_property (GObject * object, guint prop_id,
case PROP_IGNORE_ALPHA:
gtk_sink->ignore_alpha = g_value_get_boolean (value);
break;
+ case PROP_IGNORE_TEXTURES:
+ gtk_sink->ignore_textures = g_value_get_boolean (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
diff --git a/ext/gtk/gstgtkbasesink.h b/ext/gtk/gstgtkbasesink.h
index f2668fabc..a13729f7b 100644
--- a/ext/gtk/gstgtkbasesink.h
+++ b/ext/gtk/gstgtkbasesink.h
@@ -1,6 +1,7 @@
/*
* GStreamer
* Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
+ * Copyright (C) 2020 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -61,13 +62,16 @@ struct _GstGtkBaseSink
gboolean force_aspect_ratio;
GBinding *bind_aspect_ratio;
- gint par_n;
- gint par_d;
+ gint par_n;
+ gint par_d;
GBinding *bind_pixel_aspect_ratio;
- gboolean ignore_alpha;
+ gboolean ignore_alpha;
GBinding *bind_ignore_alpha;
+ gboolean ignore_textures;
+ GBinding *bind_ignore_textures;
+
GtkWidget *window;
gulong window_destroy_id;
};
diff --git a/ext/gtk/gtkgstbasewidget.c b/ext/gtk/gtkgstbasewidget.c
index 5335478cb..91fc1105f 100644
--- a/ext/gtk/gtkgstbasewidget.c
+++ b/ext/gtk/gtkgstbasewidget.c
@@ -34,6 +34,7 @@ GST_DEBUG_CATEGORY (gst_debug_gtk_base_widget);
#define DEFAULT_PAR_N 0
#define DEFAULT_PAR_D 1
#define DEFAULT_IGNORE_ALPHA TRUE
+#define DEFAULT_IGNORE_TEXTURES FALSE
enum
{
@@ -41,6 +42,7 @@ enum
PROP_FORCE_ASPECT_RATIO,
PROP_PIXEL_ASPECT_RATIO,
PROP_IGNORE_ALPHA,
+ PROP_IGNORE_TEXTURES,
};
static void
@@ -108,6 +110,9 @@ gtk_gst_base_widget_set_property (GObject * object, guint prop_id,
case PROP_IGNORE_ALPHA:
gtk_widget->ignore_alpha = g_value_get_boolean (value);
break;
+ case PROP_IGNORE_TEXTURES:
+ gtk_widget->ignore_textures = g_value_get_boolean (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -130,6 +135,9 @@ gtk_gst_base_widget_get_property (GObject * object, guint prop_id,
case PROP_IGNORE_ALPHA:
g_value_set_boolean (value, gtk_widget->ignore_alpha);
break;
+ case PROP_IGNORE_TEXTURES:
+ g_value_set_boolean (value, gtk_widget->ignore_textures);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -468,6 +476,11 @@ gtk_gst_base_widget_class_init (GtkGstBaseWidgetClass * klass)
"When enabled, alpha will be ignored and converted to black",
DEFAULT_IGNORE_ALPHA, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_klass, PROP_IGNORE_TEXTURES,
+ g_param_spec_boolean ("ignore-textures", "Ignore Textures",
+ "When enabled, textures will be ignored and not drawn",
+ DEFAULT_IGNORE_TEXTURES, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
#if defined(BUILD_FOR_GTK4)
widget_klass->measure = gtk_gst_base_widget_measure;
#else
@@ -494,6 +507,7 @@ gtk_gst_base_widget_init (GtkGstBaseWidget * widget)
widget->par_n = DEFAULT_PAR_N;
widget->par_d = DEFAULT_PAR_D;
widget->ignore_alpha = DEFAULT_IGNORE_ALPHA;
+ widget->ignore_textures = DEFAULT_IGNORE_TEXTURES;
gst_video_info_init (&widget->v_info);
gst_video_info_init (&widget->pending_v_info);
diff --git a/ext/gtk/gtkgstbasewidget.h b/ext/gtk/gtkgstbasewidget.h
index 640a1c742..651999a55 100644
--- a/ext/gtk/gtkgstbasewidget.h
+++ b/ext/gtk/gtkgstbasewidget.h
@@ -57,6 +57,7 @@ struct _GtkGstBaseWidget
gint display_width;
gint display_height;
+ gboolean ignore_textures;
gboolean negotiated;
GstBuffer *pending_buffer;
GstBuffer *buffer;
diff --git a/ext/gtk/gtkgstglwidget.c b/ext/gtk/gtkgstglwidget.c
index d1422f8bb..1553a5255 100644
--- a/ext/gtk/gtkgstglwidget.c
+++ b/ext/gtk/gtkgstglwidget.c
@@ -243,8 +243,9 @@ gtk_gst_gl_widget_render (GtkGLArea * widget, GdkGLContext * context)
/* Draw black with GDK context when priv is not available yet.
GTK calls render with GDK context already active. */
- if (!priv->context || !priv->other_context) {
+ if (!priv->context || !priv->other_context || base_widget->ignore_textures) {
GdkGLContext *gdk_context = gtk_gl_area_get_context (widget);
+
_draw_black_with_gdk (gdk_context);
goto done;
}
--
2.26.2
From ec8a37b4d7723af564d4e790ff38279c1e2ea531 Mon Sep 17 00:00:00 2001
From: Rafostar <40623528+Rafostar@users.noreply.github.com>
Date: Tue, 17 Nov 2020 11:42:45 +0100
Subject: [PATCH 4/6] gtk(4): do not reconnect signal handlers when already
connected
---
ext/gtk/gstgtkglsink.c | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/ext/gtk/gstgtkglsink.c b/ext/gtk/gstgtkglsink.c
index 3b0059906..2c92f8574 100644
--- a/ext/gtk/gstgtkglsink.c
+++ b/ext/gtk/gstgtkglsink.c
@@ -186,15 +186,19 @@ gst_gtk_gl_sink_start (GstBaseSink * bsink)
gst_widget = GTK_GST_GL_WIDGET (base_sink->widget);
#if !defined(BUILD_FOR_GTK4)
- /* Track the allocation size */
- gtk_sink->size_allocate_sig_handler =
- g_signal_connect (gst_widget, "size-allocate",
- G_CALLBACK (_size_changed_cb), gtk_sink);
+ if (!gtk_sink->size_allocate_sig_handler) {
+ /* Track the allocation size */
+ gtk_sink->size_allocate_sig_handler =
+ g_signal_connect (gst_widget, "size-allocate",
+ G_CALLBACK (_size_changed_cb), gtk_sink);
+ }
#endif
- gtk_sink->widget_destroy_sig_handler =
- g_signal_connect (gst_widget, "destroy", G_CALLBACK (destroy_cb),
- gtk_sink);
+ if (!gtk_sink->widget_destroy_sig_handler) {
+ gtk_sink->widget_destroy_sig_handler =
+ g_signal_connect (gst_widget, "destroy", G_CALLBACK (destroy_cb),
+ gtk_sink);
+ }
if (!gtk_gst_gl_widget_init_winsys (gst_widget)) {
GST_ELEMENT_ERROR (bsink, RESOURCE, NOT_FOUND, ("%s",
--
2.26.2
From fe243f7bff2b223fcbeaf2171f47bc4fce0aff78 Mon Sep 17 00:00:00 2001
From: Rafostar <40623528+Rafostar@users.noreply.github.com>
Date: Tue, 17 Nov 2020 11:44:06 +0100
Subject: [PATCH 5/6] gtk(4): use context passed to render vfunc for debug log
---
ext/gtk/gtkgstglwidget.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/ext/gtk/gtkgstglwidget.c b/ext/gtk/gtkgstglwidget.c
index 1553a5255..09d709091 100644
--- a/ext/gtk/gtkgstglwidget.c
+++ b/ext/gtk/gtkgstglwidget.c
@@ -220,7 +220,7 @@ _draw_black (GstGLContext * context)
{
const GstGLFuncs *gl = context->gl_vtable;
- gst_gl_insert_debug_marker (context, "no buffer. rendering black");
+ gst_gl_insert_debug_marker (context, "rendering black");
gl->ClearColor (0.0, 0.0, 0.0, 0.0);
gl->Clear (GL_COLOR_BUFFER_BIT);
}
@@ -244,9 +244,8 @@ gtk_gst_gl_widget_render (GtkGLArea * widget, GdkGLContext * context)
/* Draw black with GDK context when priv is not available yet.
GTK calls render with GDK context already active. */
if (!priv->context || !priv->other_context || base_widget->ignore_textures) {
- GdkGLContext *gdk_context = gtk_gl_area_get_context (widget);
+ _draw_black_with_gdk (context);
- _draw_black_with_gdk (gdk_context);
goto done;
}
--
2.26.2
From 78945426ee3976dc75d6761fd67b756af33c0302 Mon Sep 17 00:00:00 2001
From: Rafostar <40623528+Rafostar@users.noreply.github.com>
Date: Tue, 17 Nov 2020 13:16:38 +0100
Subject: [PATCH 6/6] gtk(4): always clear color to black
---
ext/gtk/gtkgstglwidget.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/ext/gtk/gtkgstglwidget.c b/ext/gtk/gtkgstglwidget.c
index 09d709091..638c80588 100644
--- a/ext/gtk/gtkgstglwidget.c
+++ b/ext/gtk/gtkgstglwidget.c
@@ -173,7 +173,7 @@ _redraw_texture (GtkGstGLWidget * gst_widget, guint tex)
GstVideoRectangle src, dst, result;
gint widget_width, widget_height, widget_scale;
- gl->ClearColor (0.0, 0.0, 0.0, 0.0);
+ gl->ClearColor (0.0, 0.0, 0.0, 1.0);
gl->Clear (GL_COLOR_BUFFER_BIT);
widget_scale = gtk_widget_get_scale_factor ((GtkWidget *) gst_widget);
@@ -221,7 +221,7 @@ _draw_black (GstGLContext * context)
const GstGLFuncs *gl = context->gl_vtable;
gst_gl_insert_debug_marker (context, "rendering black");
- gl->ClearColor (0.0, 0.0, 0.0, 0.0);
+ gl->ClearColor (0.0, 0.0, 0.0, 1.0);
gl->Clear (GL_COLOR_BUFFER_BIT);
}
--
2.26.2

View File

@@ -1,949 +0,0 @@
From 72435a6ce36b1304a8da40bd65bf0978d88b6557 Mon Sep 17 00:00:00 2001
From: Rafostar <rafostar.github@gmail.com>
Date: Wed, 14 Oct 2020 15:44:54 +0200
Subject: [PATCH] gtkglsink: add GTK4 support
This commit adds required changes to compile the "gtk" plugin against GTK4 from the same source code. The output "gtk4" plugin includes new "gtk4glsink".
---
ext/gtk/gstgtkbasesink.c | 70 ++++++++++++---
ext/gtk/gstgtkglsink.c | 32 +++++--
ext/gtk/gstplugin.c | 19 ++--
ext/gtk/gtkconfig.h | 29 ++++++
ext/gtk/gtkgstbasewidget.c | 176 ++++++++++++++++++++++++++++++-------
ext/gtk/gtkgstbasewidget.h | 17 +++-
ext/gtk/gtkgstglwidget.c | 15 +++-
ext/gtk/meson.build | 100 +++++++++++++++------
meson.build | 2 +-
meson_options.txt | 4 +
10 files changed, 372 insertions(+), 92 deletions(-)
create mode 100644 ext/gtk/gtkconfig.h
diff --git a/ext/gtk/gstgtkbasesink.c b/ext/gtk/gstgtkbasesink.c
index 0c48f54d6..1f5319089 100644
--- a/ext/gtk/gstgtkbasesink.c
+++ b/ext/gtk/gstgtkbasesink.c
@@ -1,6 +1,7 @@
/*
* GStreamer
* Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
+ * Copyright (C) 2020 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -77,7 +78,7 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstGtkBaseSink, gst_gtk_base_sink,
G_IMPLEMENT_INTERFACE (GST_TYPE_NAVIGATION,
gst_gtk_base_sink_navigation_interface_init);
GST_DEBUG_CATEGORY_INIT (gst_debug_gtk_base_sink,
- "gtkbasesink", 0, "Gtk Video Sink base class"));
+ "gtkbasesink", 0, "GTK Video Sink base class"));
static void
@@ -97,7 +98,7 @@ gst_gtk_base_sink_class_init (GstGtkBaseSinkClass * klass)
gobject_class->get_property = gst_gtk_base_sink_get_property;
g_object_class_install_property (gobject_class, PROP_WIDGET,
- g_param_spec_object ("widget", "Gtk Widget",
+ g_param_spec_object ("widget", "GTK Widget",
"The GtkWidget to place in the widget hierarchy "
"(must only be get from the GTK main thread)",
GTK_TYPE_WIDGET, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
@@ -114,10 +115,13 @@ gst_gtk_base_sink_class_init (GstGtkBaseSinkClass * klass)
"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));
+ /* Disabling alpha was removed in GTK4 */
+#if !defined(BUILD_FOR_GTK4)
g_object_class_install_property (gobject_class, PROP_IGNORE_ALPHA,
g_param_spec_boolean ("ignore-alpha", "Ignore Alpha",
"When enabled, alpha will be ignored and converted to black",
DEFAULT_IGNORE_ALPHA, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+#endif
gobject_class->finalize = gst_gtk_base_sink_finalize;
@@ -182,7 +186,11 @@ gst_gtk_base_sink_get_widget (GstGtkBaseSink * gtk_sink)
/* Ensure GTK is initialized, this has no side effect if it was already
* initialized. Also, we do that lazily, so the application can be first */
- if (!gtk_init_check (NULL, NULL)) {
+ if (!gtk_init_check (
+#if !defined(BUILD_FOR_GTK4)
+ NULL, NULL
+#endif
+ )) {
GST_ERROR_OBJECT (gtk_sink, "Could not ensure GTK initialization.");
return NULL;
}
@@ -197,9 +205,11 @@ gst_gtk_base_sink_get_widget (GstGtkBaseSink * gtk_sink)
gtk_sink->bind_pixel_aspect_ratio =
g_object_bind_property (gtk_sink, "pixel-aspect-ratio", gtk_sink->widget,
"pixel-aspect-ratio", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+#if !defined(BUILD_FOR_GTK4)
gtk_sink->bind_ignore_alpha =
g_object_bind_property (gtk_sink, "ignore-alpha", gtk_sink->widget,
"ignore-alpha", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
+#endif
/* Take the floating ref, other wise the destruction of the container will
* make this widget disappear possibly before we are done. */
@@ -313,25 +323,55 @@ gst_gtk_base_sink_start_on_main (GstBaseSink * bsink)
GstGtkBaseSink *gst_sink = GST_GTK_BASE_SINK (bsink);
GstGtkBaseSinkClass *klass = GST_GTK_BASE_SINK_GET_CLASS (bsink);
GtkWidget *toplevel;
+#if defined(BUILD_FOR_GTK4)
+ GtkRoot *root;
+#endif
if (gst_gtk_base_sink_get_widget (gst_sink) == NULL)
return FALSE;
/* After this point, gtk_sink->widget will always be set */
+#if defined(BUILD_FOR_GTK4)
+ root = gtk_widget_get_root (GTK_WIDGET (gst_sink->widget));
+ if (!GTK_IS_ROOT (root)) {
+ GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (gst_sink->widget));
+ if (parent) {
+ GtkWidget *temp_parent;
+ while ((temp_parent = gtk_widget_get_parent (parent)))
+ parent = temp_parent;
+ }
+ toplevel = (parent) ? parent : GTK_WIDGET (gst_sink->widget);
+#else
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (gst_sink->widget));
if (!gtk_widget_is_toplevel (toplevel)) {
+#endif
/* sanity check */
g_assert (klass->window_title);
/* User did not add widget its own UI, let's popup a new GtkWindow to
* make gst-launch-1.0 work. */
- gst_sink->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gst_sink->window = gtk_window_new (
+#if !defined(BUILD_FOR_GTK4)
+ GTK_WINDOW_TOPLEVEL
+#endif
+ );
gtk_window_set_default_size (GTK_WINDOW (gst_sink->window), 640, 480);
gtk_window_set_title (GTK_WINDOW (gst_sink->window), klass->window_title);
- gtk_container_add (GTK_CONTAINER (gst_sink->window), toplevel);
- gst_sink->window_destroy_id = g_signal_connect (gst_sink->window, "destroy",
- G_CALLBACK (window_destroy_cb), gst_sink);
+#if defined(BUILD_FOR_GTK4)
+ gtk_window_set_child (GTK_WINDOW (
+#else
+ gtk_container_add (GTK_CONTAINER (
+#endif
+ gst_sink->window), toplevel);
+
+ gst_sink->window_destroy_id = g_signal_connect (
+#if defined(BUILD_FOR_GTK4)
+ GTK_WINDOW (gst_sink->window),
+#else
+ gst_sink->window,
+#endif
+ "destroy", G_CALLBACK (window_destroy_cb), gst_sink);
}
return TRUE;
@@ -350,7 +390,11 @@ gst_gtk_base_sink_stop_on_main (GstBaseSink * bsink)
GstGtkBaseSink *gst_sink = GST_GTK_BASE_SINK (bsink);
if (gst_sink->window) {
+#if defined(BUILD_FOR_GTK4)
+ gtk_window_destroy (GTK_WINDOW (gst_sink->window));
+#else
gtk_widget_destroy (gst_sink->window);
+#endif
gst_sink->window = NULL;
gst_sink->widget = NULL;
}
@@ -371,10 +415,14 @@ gst_gtk_base_sink_stop (GstBaseSink * bsink)
}
static void
-gst_gtk_widget_show_all_and_unref (GtkWidget * widget)
+gst_gtk_window_show_all_and_unref (GtkWidget * window)
{
- gtk_widget_show_all (widget);
- g_object_unref (widget);
+#if defined(BUILD_FOR_GTK4)
+ gtk_window_present (GTK_WINDOW (window));
+#else
+ gtk_widget_show_all (window);
+#endif
+ g_object_unref (window);
}
static GstStateChangeReturn
@@ -402,7 +450,7 @@ gst_gtk_base_sink_change_state (GstElement * element, GstStateChange transition)
GST_OBJECT_UNLOCK (gtk_sink);
if (window)
- gst_gtk_invoke_on_main ((GThreadFunc) gst_gtk_widget_show_all_and_unref,
+ gst_gtk_invoke_on_main ((GThreadFunc) gst_gtk_window_show_all_and_unref,
window);
break;
diff --git a/ext/gtk/gstgtkglsink.c b/ext/gtk/gstgtkglsink.c
index 1102d47c9..3b0059906 100644
--- a/ext/gtk/gstgtkglsink.c
+++ b/ext/gtk/gstgtkglsink.c
@@ -1,6 +1,7 @@
/*
* GStreamer
* Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
+ * Copyright (C) 2020 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -23,12 +24,18 @@
* @title: gtkglsink
*/
+/**
+ * SECTION:element-gtk4glsink
+ * @title: gtk4glsink
+ */
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gst/gl/gstglfuncs.h>
+#include "gtkconfig.h"
#include "gstgtkglsink.h"
#include "gtkgstglwidget.h"
@@ -58,7 +65,7 @@ static GstStaticPadTemplate gst_gtk_gl_sink_template =
#define gst_gtk_gl_sink_parent_class parent_class
G_DEFINE_TYPE_WITH_CODE (GstGtkGLSink, gst_gtk_gl_sink,
GST_TYPE_GTK_BASE_SINK, GST_DEBUG_CATEGORY_INIT (gst_debug_gtk_gl_sink,
- "gtkglsink", 0, "Gtk GL Video Sink"));
+ GTKCONFIG_GLSINK, 0, GTKCONFIG_NAME " GL Video Sink"));
static void
gst_gtk_gl_sink_class_init (GstGtkGLSinkClass * klass)
@@ -82,11 +89,16 @@ gst_gtk_gl_sink_class_init (GstGtkGLSinkClass * klass)
gstbasesink_class->get_caps = gst_gtk_gl_sink_get_caps;
gstgtkbasesink_class->create_widget = gtk_gst_gl_widget_new;
- gstgtkbasesink_class->window_title = "Gtk+ GL renderer";
+ gstgtkbasesink_class->window_title = GTKCONFIG_NAME " GL Renderer";
- gst_element_class_set_metadata (gstelement_class, "Gtk GL Video Sink",
+ gst_element_class_set_metadata (gstelement_class,
+ GTKCONFIG_NAME " GL Video Sink",
"Sink/Video", "A video sink that renders to a GtkWidget using OpenGL",
- "Matthew Waters <matthew@centricular.com>");
+ "Matthew Waters <matthew@centricular.com>"
+#if defined(BUILD_FOR_GTK4)
+ ", Rafał Dzięgiel <rafostar.github@gmail.com>"
+#endif
+ );
gst_element_class_add_static_pad_template (gstelement_class,
&gst_gtk_gl_sink_template);
@@ -119,6 +131,7 @@ gst_gtk_gl_sink_query (GstBaseSink * bsink, GstQuery * query)
return res;
}
+#if !defined(BUILD_FOR_GTK4)
static void
_size_changed_cb (GtkWidget * widget, GdkRectangle * rectangle,
GstGtkGLSink * gtk_sink)
@@ -138,11 +151,12 @@ _size_changed_cb (GtkWidget * widget, GdkRectangle * rectangle,
GST_OBJECT_UNLOCK (gtk_sink);
if (reconfigure) {
- GST_DEBUG_OBJECT (gtk_sink, "Sending reconfigure event on sinkpad.");
+ GST_DEBUG_OBJECT (gtk_sink, "Sending reconfigure event on sinkpad");
gst_pad_push_event (GST_BASE_SINK (gtk_sink)->sinkpad,
gst_event_new_reconfigure ());
}
}
+#endif
static void
destroy_cb (GtkWidget * widget, GstGtkGLSink * gtk_sink)
@@ -171,20 +185,20 @@ gst_gtk_gl_sink_start (GstBaseSink * bsink)
/* After this point, gtk_sink->widget will always be set */
gst_widget = GTK_GST_GL_WIDGET (base_sink->widget);
+#if !defined(BUILD_FOR_GTK4)
/* Track the allocation size */
gtk_sink->size_allocate_sig_handler =
g_signal_connect (gst_widget, "size-allocate",
G_CALLBACK (_size_changed_cb), gtk_sink);
+#endif
gtk_sink->widget_destroy_sig_handler =
g_signal_connect (gst_widget, "destroy", G_CALLBACK (destroy_cb),
gtk_sink);
- _size_changed_cb (GTK_WIDGET (gst_widget), NULL, gtk_sink);
-
if (!gtk_gst_gl_widget_init_winsys (gst_widget)) {
GST_ELEMENT_ERROR (bsink, RESOURCE, NOT_FOUND, ("%s",
- "Failed to initialize OpenGL with Gtk"), (NULL));
+ "Failed to initialize OpenGL with GTK"), (NULL));
return FALSE;
}
@@ -194,7 +208,7 @@ gst_gtk_gl_sink_start (GstBaseSink * bsink)
if (!gtk_sink->display || !gtk_sink->context || !gtk_sink->gtk_context) {
GST_ELEMENT_ERROR (bsink, RESOURCE, NOT_FOUND, ("%s",
- "Failed to retrieve OpenGL context from Gtk"), (NULL));
+ "Failed to retrieve OpenGL context from GTK"), (NULL));
return FALSE;
}
diff --git a/ext/gtk/gstplugin.c b/ext/gtk/gstplugin.c
index ed275785b..788f4f9dd 100644
--- a/ext/gtk/gstplugin.c
+++ b/ext/gtk/gstplugin.c
@@ -1,6 +1,7 @@
/*
* GStreamer
* Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
+ * Copyright (C) 2020 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -22,31 +23,37 @@
#include "config.h"
#endif
+#include "gtkconfig.h"
+
+#if !defined(BUILD_FOR_GTK4)
#include "gstgtksink.h"
-#if defined(HAVE_GTK3_GL)
+#endif
+
+#if defined(HAVE_GTK_GL)
#include "gstgtkglsink.h"
#endif
static gboolean
plugin_init (GstPlugin * plugin)
{
+#if !defined(BUILD_FOR_GTK4)
if (!gst_element_register (plugin, "gtksink",
GST_RANK_NONE, GST_TYPE_GTK_SINK)) {
return FALSE;
}
-#if defined(HAVE_GTK3_GL)
- if (!gst_element_register (plugin, "gtkglsink",
+#endif
+
+#if defined(HAVE_GTK_GL)
+ if (!gst_element_register (plugin, GTKCONFIG_GLSINK,
GST_RANK_NONE, GST_TYPE_GTK_GL_SINK)) {
return FALSE;
}
#endif
-
return TRUE;
}
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
GST_VERSION_MINOR,
- gtk,
- "Gtk+ sink",
+ GTKCONFIG_PLUGIN, GTKCONFIG_NAME " sink",
plugin_init, PACKAGE_VERSION, GST_LICENSE, GST_PACKAGE_NAME,
GST_PACKAGE_ORIGIN)
diff --git a/ext/gtk/gtkconfig.h b/ext/gtk/gtkconfig.h
new file mode 100644
index 000000000..8dd28dc00
--- /dev/null
+++ b/ext/gtk/gtkconfig.h
@@ -0,0 +1,29 @@
+/*
+ * GStreamer
+ * Copyright (C) 2020 Rafał Dzięgiel <rafostar.github@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#if defined(BUILD_FOR_GTK4)
+#define GTKCONFIG_PLUGIN gtk4
+#define GTKCONFIG_NAME "GTK4"
+#define GTKCONFIG_GLSINK "gtk4glsink"
+#else
+#define GTKCONFIG_PLUGIN gtk
+#define GTKCONFIG_NAME "GTK"
+#define GTKCONFIG_GLSINK "gtkglsink"
+#endif
diff --git a/ext/gtk/gtkgstbasewidget.c b/ext/gtk/gtkgstbasewidget.c
index 4858f2764..5335478cb 100644
--- a/ext/gtk/gtkgstbasewidget.c
+++ b/ext/gtk/gtkgstbasewidget.c
@@ -1,6 +1,7 @@
/*
* GStreamer
* Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
+ * Copyright (C) 2020 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -74,6 +75,22 @@ gtk_gst_base_widget_get_preferred_height (GtkWidget * widget, gint * min,
*natural = video_height;
}
+#if defined(BUILD_FOR_GTK4)
+static void
+gtk_gst_base_widget_measure (GtkWidget * widget, GtkOrientation orientation,
+ int for_size, int *min, int *natural,
+ int *minimum_baseline, int *natural_baseline)
+{
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ gtk_gst_base_widget_get_preferred_width (widget, min, natural);
+ else
+ gtk_gst_base_widget_get_preferred_height (widget, min, natural);
+
+ *minimum_baseline = -1;
+ *natural_baseline = -1;
+}
+#endif
+
static void
gtk_gst_base_widget_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
@@ -235,22 +252,46 @@ _gdk_key_to_navigation_string (guint keyval)
}
}
+static GdkEvent *
+_get_current_event (GtkEventController * controller)
+{
+#if defined(BUILD_FOR_GTK4)
+ return gtk_event_controller_get_current_event (controller);
+#else
+ return gtk_get_current_event ();
+#endif
+}
+
+static void
+_gdk_event_free (GdkEvent * event)
+{
+#if !defined(BUILD_FOR_GTK4)
+ if (event)
+ gdk_event_free (event);
+#endif
+}
+
static gboolean
-gtk_gst_base_widget_key_event (GtkWidget * widget, GdkEventKey * event)
+gtk_gst_base_widget_key_event (GtkEventControllerKey * key_controller,
+ guint keyval, guint keycode, GdkModifierType state)
{
+ GtkEventController *controller = GTK_EVENT_CONTROLLER (key_controller);
+ GtkWidget *widget = gtk_event_controller_get_widget (controller);
GtkGstBaseWidget *base_widget = GTK_GST_BASE_WIDGET (widget);
GstElement *element;
if ((element = g_weak_ref_get (&base_widget->element))) {
if (GST_IS_NAVIGATION (element)) {
- const gchar *str = _gdk_key_to_navigation_string (event->keyval);
- const gchar *key_type =
- event->type == GDK_KEY_PRESS ? "key-press" : "key-release";
-
- if (!str)
- str = event->string;
-
- gst_navigation_send_key_event (GST_NAVIGATION (element), key_type, str);
+ GdkEvent *event = _get_current_event (controller);
+ const gchar *str = _gdk_key_to_navigation_string (keyval);
+
+ if (str) {
+ const gchar *key_type =
+ gdk_event_get_event_type (event) ==
+ GDK_KEY_PRESS ? "key-press" : "key-release";
+ gst_navigation_send_key_event (GST_NAVIGATION (element), key_type, str);
+ }
+ _gdk_event_free (event);
}
g_object_unref (element);
}
@@ -325,22 +366,43 @@ _display_size_to_stream_size (GtkGstBaseWidget * base_widget, gdouble x,
}
static gboolean
-gtk_gst_base_widget_button_event (GtkWidget * widget, GdkEventButton * event)
+gtk_gst_base_widget_button_event (
+#if defined(BUILD_FOR_GTK4)
+ GtkGestureClick * gesture,
+#else
+ GtkGestureMultiPress * gesture,
+#endif
+ int n_press, double x, double y)
{
+ GtkEventController *controller = GTK_EVENT_CONTROLLER (gesture);
+ GtkWidget *widget = gtk_event_controller_get_widget (controller);
GtkGstBaseWidget *base_widget = GTK_GST_BASE_WIDGET (widget);
GstElement *element;
if ((element = g_weak_ref_get (&base_widget->element))) {
if (GST_IS_NAVIGATION (element)) {
+ GdkEvent *event = _get_current_event (controller);
const gchar *key_type =
- event->type ==
- GDK_BUTTON_PRESS ? "mouse-button-press" : "mouse-button-release";
- gdouble x, y;
+ gdk_event_get_event_type (event) == GDK_BUTTON_PRESS
+ ? "mouse-button-press" : "mouse-button-release";
+ gdouble stream_x, stream_y;
+#if !defined(BUILD_FOR_GTK4)
+ guint button;
+ gdk_event_get_button (event, &button);
+#endif
- _display_size_to_stream_size (base_widget, event->x, event->y, &x, &y);
+ _display_size_to_stream_size (base_widget, x, y, &stream_x, &stream_y);
gst_navigation_send_mouse_event (GST_NAVIGATION (element), key_type,
- event->button, x, y);
+#if defined(BUILD_FOR_GTK4)
+ /* Gesture is set to ignore other buttons so we do not have to check */
+ GDK_BUTTON_PRIMARY,
+#else
+ button,
+#endif
+ stream_x, stream_y);
+
+ _gdk_event_free (event);
}
g_object_unref (element);
}
@@ -349,19 +411,30 @@ gtk_gst_base_widget_button_event (GtkWidget * widget, GdkEventButton * event)
}
static gboolean
-gtk_gst_base_widget_motion_event (GtkWidget * widget, GdkEventMotion * event)
+gtk_gst_base_widget_motion_event (GtkEventControllerMotion * motion_controller,
+ double x, double y)
{
+ GtkEventController *controller = GTK_EVENT_CONTROLLER (motion_controller);
+ GtkWidget *widget = gtk_event_controller_get_widget (controller);
GtkGstBaseWidget *base_widget = GTK_GST_BASE_WIDGET (widget);
GstElement *element;
+ /* Sometimes GTK might generate motion events with the same coords during
+ * window redraws, so we check for the differences to prevent that */
+ if (base_widget->cursor_coords_x == x && base_widget->cursor_coords_y == y)
+ return FALSE;
+
+ base_widget->cursor_coords_x = x;
+ base_widget->cursor_coords_y = y;
+
if ((element = g_weak_ref_get (&base_widget->element))) {
if (GST_IS_NAVIGATION (element)) {
- gdouble x, y;
+ gdouble stream_x, stream_y;
- _display_size_to_stream_size (base_widget, event->x, event->y, &x, &y);
+ _display_size_to_stream_size (base_widget, x, y, &stream_x, &stream_y);
gst_navigation_send_mouse_event (GST_NAVIGATION (element), "mouse-move",
- 0, x, y);
+ 0, stream_x, stream_y);
}
g_object_unref (element);
}
@@ -395,22 +468,27 @@ gtk_gst_base_widget_class_init (GtkGstBaseWidgetClass * klass)
"When enabled, alpha will be ignored and converted to black",
DEFAULT_IGNORE_ALPHA, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+#if defined(BUILD_FOR_GTK4)
+ widget_klass->measure = gtk_gst_base_widget_measure;
+#else
widget_klass->get_preferred_width = gtk_gst_base_widget_get_preferred_width;
widget_klass->get_preferred_height = gtk_gst_base_widget_get_preferred_height;
- widget_klass->key_press_event = gtk_gst_base_widget_key_event;
- widget_klass->key_release_event = gtk_gst_base_widget_key_event;
- widget_klass->button_press_event = gtk_gst_base_widget_button_event;
- widget_klass->button_release_event = gtk_gst_base_widget_button_event;
- widget_klass->motion_notify_event = gtk_gst_base_widget_motion_event;
+#endif
GST_DEBUG_CATEGORY_INIT (gst_debug_gtk_base_widget, "gtkbasewidget", 0,
- "Gtk Video Base Widget");
+ "GTK Video Base Widget");
}
void
gtk_gst_base_widget_init (GtkGstBaseWidget * widget)
{
- int event_mask;
+ /* Event controllers were added in GTK 3.24 */
+ GtkEventController *key_controller;
+ GtkEventController *motion_controller;
+ GtkGesture *click_gesture;
+
+ widget->cursor_coords_x = 0;
+ widget->cursor_coords_y = 0;
widget->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO;
widget->par_n = DEFAULT_PAR_N;
@@ -423,14 +501,46 @@ gtk_gst_base_widget_init (GtkGstBaseWidget * widget)
g_weak_ref_init (&widget->element, NULL);
g_mutex_init (&widget->lock);
+ key_controller = gtk_event_controller_key_new (
+#if !defined(BUILD_FOR_GTK4)
+ GTK_WIDGET (widget)
+#endif
+ );
+ g_signal_connect (key_controller, "key-pressed",
+ G_CALLBACK (gtk_gst_base_widget_key_event), NULL);
+ g_signal_connect (key_controller, "key-released",
+ G_CALLBACK (gtk_gst_base_widget_key_event), NULL);
+
+ motion_controller = gtk_event_controller_motion_new (
+#if !defined(BUILD_FOR_GTK4)
+ GTK_WIDGET (widget)
+#endif
+ );
+ g_signal_connect (motion_controller, "motion",
+ G_CALLBACK (gtk_gst_base_widget_motion_event), NULL);
+
+ click_gesture =
+#if defined(BUILD_FOR_GTK4)
+ gtk_gesture_click_new ();
+#else
+ gtk_gesture_multi_press_new (GTK_WIDGET (widget));
+#endif
+ g_signal_connect (click_gesture, "pressed",
+ G_CALLBACK (gtk_gst_base_widget_button_event), NULL);
+ g_signal_connect (click_gesture, "released",
+ G_CALLBACK (gtk_gst_base_widget_button_event), NULL);
+
+#if defined(BUILD_FOR_GTK4)
+ gtk_widget_set_focusable (GTK_WIDGET (widget), TRUE);
+ gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (click_gesture),
+ GDK_BUTTON_PRIMARY);
+
+ gtk_widget_add_controller (GTK_WIDGET (widget), key_controller);
+ gtk_widget_add_controller (GTK_WIDGET (widget), motion_controller);
+ gtk_widget_add_controller (GTK_WIDGET (widget),
+ GTK_EVENT_CONTROLLER (click_gesture));
+#endif
gtk_widget_set_can_focus (GTK_WIDGET (widget), TRUE);
- event_mask = gtk_widget_get_events (GTK_WIDGET (widget));
- event_mask |= GDK_KEY_PRESS_MASK
- | GDK_KEY_RELEASE_MASK
- | GDK_BUTTON_PRESS_MASK
- | GDK_BUTTON_RELEASE_MASK
- | GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK;
- gtk_widget_set_events (GTK_WIDGET (widget), event_mask);
}
void
diff --git a/ext/gtk/gtkgstbasewidget.h b/ext/gtk/gtkgstbasewidget.h
index 13737c632..640a1c742 100644
--- a/ext/gtk/gtkgstbasewidget.h
+++ b/ext/gtk/gtkgstbasewidget.h
@@ -1,6 +1,7 @@
/*
* GStreamer
* Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
+ * Copyright (C) 2020 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -25,6 +26,10 @@
#include <gst/gst.h>
#include <gst/video/video.h>
+#if !defined(BUILD_FOR_GTK4)
+#include <gdk/gdk.h>
+#endif
+
#define GTK_GST_BASE_WIDGET(w) ((GtkGstBaseWidget *)(w))
#define GTK_GST_BASE_WIDGET_CLASS(k) ((GtkGstBaseWidgetClass *)(k))
#define GTK_GST_BASE_WIDGET_LOCK(w) g_mutex_lock(&((GtkGstBaseWidget*)(w))->lock)
@@ -38,10 +43,10 @@ typedef struct _GtkGstBaseWidgetClass GtkGstBaseWidgetClass;
struct _GtkGstBaseWidget
{
union {
+#if !defined(BUILD_FOR_GTK4)
GtkDrawingArea drawing_area;
-#if GTK_CHECK_VERSION(3, 15, 0)
- GtkGLArea gl_area;
#endif
+ GtkGLArea gl_area;
} parent;
/* properties */
@@ -63,6 +68,10 @@ struct _GtkGstBaseWidget
guint display_ratio_num;
guint display_ratio_den;
+ /* cursor motion coords */
+ gdouble cursor_coords_x;
+ gdouble cursor_coords_y;
+
/*< private >*/
GMutex lock;
GWeakRef element;
@@ -74,10 +83,10 @@ struct _GtkGstBaseWidget
struct _GtkGstBaseWidgetClass
{
union {
+#if !defined(BUILD_FOR_GTK4)
GtkDrawingAreaClass drawing_area_class;
-#if GTK_CHECK_VERSION(3, 15, 0)
- GtkGLAreaClass gl_area_class;
#endif
+ GtkGLAreaClass gl_area_class;
} parent_class;
};
diff --git a/ext/gtk/gtkgstglwidget.c b/ext/gtk/gtkgstglwidget.c
index 6c423ad89..186144a1c 100644
--- a/ext/gtk/gtkgstglwidget.c
+++ b/ext/gtk/gtkgstglwidget.c
@@ -1,6 +1,7 @@
/*
* GStreamer
* Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
+ * Copyright (C) 2020 Rafał Dzięgiel <rafostar.github@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -30,12 +31,20 @@
#include <gst/video/video.h>
#if GST_GL_HAVE_WINDOW_X11 && defined (GDK_WINDOWING_X11)
+#if defined(BUILD_FOR_GTK4)
+#include <gdk/x11/gdkx.h>
+#else
#include <gdk/gdkx.h>
+#endif
#include <gst/gl/x11/gstgldisplay_x11.h>
#endif
#if GST_GL_HAVE_WINDOW_WAYLAND && defined (GDK_WINDOWING_WAYLAND)
+#if defined(BUILD_FOR_GTK4)
+#include <gdk/wayland/gdkwayland.h>
+#else
#include <gdk/gdkwayland.h>
+#endif
#include <gst/gl/wayland/gstgldisplay_wayland.h>
#endif
@@ -78,8 +87,7 @@ static const GLfloat vertices[] = {
G_DEFINE_TYPE_WITH_CODE (GtkGstGLWidget, gtk_gst_gl_widget, GTK_TYPE_GL_AREA,
G_ADD_PRIVATE (GtkGstGLWidget)
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "gtkgstglwidget", 0,
- "Gtk Gst GL Widget");
- );
+ "GTK Gst GL Widget"));
static void
gtk_gst_gl_widget_bind_buffer (GtkGstGLWidget * gst_widget)
@@ -407,8 +415,11 @@ gtk_gst_gl_widget_init (GtkGstGLWidget * gst_widget)
GST_INFO ("Created %" GST_PTR_FORMAT, priv->display);
+ /* GTK4 always has alpha */
+#if !defined(BUILD_FOR_GTK4)
gtk_gl_area_set_has_alpha (GTK_GL_AREA (gst_widget),
!base_widget->ignore_alpha);
+#endif
}
static void
diff --git a/ext/gtk/meson.build b/ext/gtk/meson.build
index 3a30017e7..6f7fd6a67 100644
--- a/ext/gtk/meson.build
+++ b/ext/gtk/meson.build
@@ -1,59 +1,107 @@
+gtk_versions = [3, 4]
gtk_sources = [
'gstgtkbasesink.c',
- 'gstgtksink.c',
'gstgtkutils.c',
'gstplugin.c',
'gtkgstbasewidget.c',
- 'gtkgstwidget.c',
]
+gtk_lib_added = false
+gtk_dep = dependency('gtk+-3.0', required : get_option('gtk3'))
+gtk4_dep = dependency('gtk4', required : get_option('gtk4'))
-gtk_defines = []
-optional_deps = []
+foreach gtk_ver : gtk_versions
+ gtkv = 'gtk' + gtk_ver.to_string()
-gtk_dep = dependency('gtk+-3.0', required : get_option('gtk3'))
-if gtk_dep.found()
- # FIXME: automagic
- if have_gstgl and gtk_dep.version().version_compare('>=3.15.0')
- have_gtk3_gl_windowing = false
+ if gtk_ver > 3
+ allow_experiments = get_option(gtkv + '-experiments')
+ if not allow_experiments
+ continue
+ endif
+ endif
+
+ gtk_state = get_option(gtkv)
+ if gtk_state.disabled()
+ continue
+ endif
+
+ min_ver = gtk_ver >= 4 ? '3.99.2' : '3.24.0'
+ x11_dep = gtk_ver >= 4 ? gtkv + '-x11' : 'gtk+-x11-3.0'
+ way_dep = gtk_ver >= 4 ? gtkv + '-wayland' : 'gtk+-wayland-3.0'
+ lib_dep = gtk_ver >= 4 ? gtk4_dep : gtk_dep
+
+ if not lib_dep.found() or not lib_dep.version().version_compare('>=' + min_ver)
+ continue
+ endif
+
+ lib_sources = []
+ gtk_defines = []
+ optional_deps = []
+ have_gtk_gl_windowing = false
+ lib_sources += gtk_sources
+ if gtk_ver == 3
+ lib_sources += [
+ 'gstgtksink.c',
+ 'gtkgstwidget.c',
+ ]
+ endif
+
+ if have_gstgl
if gst_gl_have_window_x11 and gst_gl_have_platform_glx
# FIXME: automagic
- gtk_x11_dep = dependency('gtk+-x11-3.0', required : false)
+ gtk_x11_dep = dependency(x11_dep, required : false)
if gtk_x11_dep.found()
optional_deps += [gtk_x11_dep, gstglx11_dep]
- have_gtk3_gl_windowing = true
+ have_gtk_gl_windowing = true
endif
endif
if gst_gl_have_window_wayland and gst_gl_have_platform_egl
# FIXME: automagic
- gtk_wayland_dep = dependency('gtk+-wayland-3.0', required : false)
+ gtk_wayland_dep = dependency(way_dep, required : false)
if gtk_wayland_dep.found()
optional_deps += [gtk_wayland_dep, gstglegl_dep, gstglwayland_dep]
- have_gtk3_gl_windowing = true
+ have_gtk_gl_windowing = true
endif
endif
+ endif
+
+ if gtk_ver > 3 and not have_gtk_gl_windowing
+ continue
+ endif
- if have_gtk3_gl_windowing
- gtk_sources += [
- 'gstgtkglsink.c',
- 'gtkgstglwidget.c',
- ]
- optional_deps += [gstgl_dep, gstglproto_dep]
- gtk_defines += ['-DGST_USE_UNSTABLE_API', '-DHAVE_GTK3_GL']
+ if have_gtk_gl_windowing
+ lib_sources += [
+ 'gstgtkglsink.c',
+ 'gtkgstglwidget.c',
+ ]
+ optional_deps += [gstgl_dep, gstglproto_dep]
+ gtk_defines += ['-DGST_USE_UNSTABLE_API', '-DHAVE_GTK_GL']
+ if gtk_ver == 4
+ gtk_defines += '-DBUILD_FOR_GTK4'
endif
endif
- gstgtk = library('gstgtk',
- gtk_sources,
+ lib_name = 'gstgtk'
+ if gtk_ver > 3
+ lib_name += gtk_ver.to_string()
+ endif
+
+ # GStreamer loads all plugins at once. To avoid GTK versions conflicts,
+ # do not install more than one plugin version on "auto".
+ # The "gtk4" option should be set to "enabled" for packaging.
+ is_gstgtk_install = not gtk_lib_added or not gtk_state.auto()
+
+ gstgtk = library(lib_name,
+ lib_sources,
c_args : gst_plugins_good_args + gtk_defines,
link_args : noseh_link_args,
include_directories : [configinc],
- dependencies : [gtk_dep, gstvideo_dep, gstbase_dep, libm] + optional_deps,
- install : true,
+ dependencies : [lib_dep, gstvideo_dep, gstbase_dep, libm] + optional_deps,
+ install : is_gstgtk_install,
install_dir : plugins_install_dir,
)
pkgconfig.generate(gstgtk, install_dir : plugins_pkgconfig_install_dir)
plugins += [gstgtk]
-endif
-
+ gtk_lib_added = true
+endforeach
diff --git a/meson.build b/meson.build
index 77ab1a7d2..e6973b318 100644
--- a/meson.build
+++ b/meson.build
@@ -1,6 +1,6 @@
project('gst-plugins-good', 'c',
version : '1.18.1',
- meson_version : '>= 0.48',
+ meson_version : '>= 0.49',
default_options : [ 'warning_level=1',
'buildtype=debugoptimized' ])
diff --git a/meson_options.txt b/meson_options.txt
index 5c96f6542..772628cd5 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -53,6 +53,7 @@ option('dv1394', type : 'feature', value : 'auto', description : 'Digital IEEE13
option('flac', type : 'feature', value : 'auto', description : 'FLAC audio codec plugin')
option('gdk-pixbuf', type : 'feature', value : 'auto', description : 'gdk-pixbuf image decoder, overlay, and sink plugin')
option('gtk3', type : 'feature', value : 'auto', description : 'GTK+ video sink plugin')
+option('gtk4', type : 'feature', value : 'auto', description : 'GTK4 video sink plugin')
option('jack', type : 'feature', value : 'auto', description : 'JACK audio source/sink plugin')
option('jpeg', type : 'feature', value : 'auto', description : 'JPEG image codec plugin')
option('lame', type : 'feature', value : 'auto', description : 'LAME mp3 audio encoder plugin')
@@ -74,6 +75,9 @@ option('vpx', type : 'feature', value : 'auto', description : 'VP8 and VP9 video
option('waveform', type : 'feature', value : 'auto', description : 'Windows waveform audio sink plugin')
option('wavpack', type : 'feature', value : 'auto', description : 'Wavpack audio codec plugin')
+# gtk plugin options
+option('gtk4-experiments', type : 'boolean', value : false, description : 'Allow compiling experimental GTK4 plugin')
+
# rpicamsrc plugin options
option('rpicamsrc', type : 'feature', value : 'auto', description : 'Raspberry Pi camera module plugin')
option('rpi-header-dir', type : 'string', value : '/opt/vc/include', description : 'Directory where VideoCore/MMAL headers and bcm_host.h can be found')
--
2.26.2

View File

@@ -10,9 +10,7 @@
"-Dglib-asserts=disabled",
"-Dglib-checks=disabled",
"-Dgtk4-experiments=true",
"-Dgtk3=disabled",
"-Dgtk4=enabled"
],
"sources": [
{
@@ -21,18 +19,6 @@
"tag": "1.18.1",
"commit": "7c44cdb0e00dd1c9932d8e5194b09fcf4e1e6fc1"
},
{
"type": "patch",
"path": "gst-plugins-good-gtk4glsink.patch"
},
{
"type": "patch",
"path": "gst-plugins-good-gtk4-do-not-depend-on-destroy-signal-for-cleanup.patch"
},
{
"type": "patch",
"path": "gst-plugins-good-gtk4glsink-render-black.patch"
},
{
"type": "patch",
"path": "gst-plugins-good-matroska-fix-attachments-detection.patch"