Files
yoctor-layers/meta-st/meta-st-openstlinux/recipes-samples/event-gtk-player/files/0001-touch-player-cleanup-and-port-to-gtkwaylandsink.patch
2024-07-11 14:16:35 +02:00

1016 lines
31 KiB
Diff

From 5a4ef8928f587f702e92dbeb75280232719c5df4 Mon Sep 17 00:00:00 2001
From: George Kiagiadakis <george.kiagiadakis@collabora.com>
Date: Mon, 13 Dec 2021 17:23:38 +0200
Subject: [PATCH 1/7] touch-player: cleanup and port to gtkwaylandsink
---
main.c | 754 +++++++---------------------------
1 file changed, 144 insertions(+), 610 deletions(-)
diff --git a/main.c b/main.c
index f1861de..0f254e0 100644
--- a/main.c
+++ b/main.c
@@ -6,40 +6,19 @@
*
* SPDX-License-Identufier: GPL-2.0+
*
- * NOTE: inspirated from https://github.com/GStreamer/gst-plugins-bad/tree/master/tests/examples/waylandsink
+ * NOTE: inspired from https://github.com/GStreamer/gst-plugins-bad/tree/master/tests/examples/waylandsink
*/
#include <gst/gst.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef GDK_WINDOWING_WAYLAND
-#include <gdk/gdkwayland.h>
-#else
-#error "Wayland is not supported in GTK+"
-#endif
-
-#include <gst/video/videooverlay.h>
-#include <wayland/wayland.h> // for gst/wayland/wayland.h
-
-gboolean local_kb_set_key_handler(gpointer user_data);
-
static gchar *graph = NULL;
static gchar *shader_file = NULL;
static gboolean nofullscreen = FALSE;
-static guint32 last_touch_tap = 0;
-static guint32 last_pointer_tap = 0;
-static gint window_width = 480;
-static gint window_height = 272;
-
-static GMainLoop *loop;
static GOptionEntry entries[] = {
- {"No Fullscreen", 'F', 0, G_OPTION_ARG_NONE, &nofullscreen,
+ {"nofullscreen", 'F', 0, G_OPTION_ARG_NONE, &nofullscreen,
"Do not put video on fullscreeen", NULL},
{"width", 'w', 0, G_OPTION_ARG_INT, &window_width, "Windows Width", NULL},
{"height", 'h', 0, G_OPTION_ARG_INT, &window_height, "Windows Height", NULL},
@@ -52,17 +31,17 @@ static GOptionEntry entries[] = {
typedef struct
{
GtkWidget *window_widget;
- GtkWidget *video_widget;
- GtkWidget *box_widget;
GstElement *pipeline;
- GstVideoOverlay *overlay;
+
+ GMainLoop *loop;
+ guint io_watch_id;
gchar **argv;
gint current_uri; /* index for argv */
- gboolean to_start;
- gint video_width;
- gint video_height;
+
+ guint32 last_touch_tap;
+ guint32 last_pointer_tap;
} DemoApp;
static void
@@ -75,295 +54,6 @@ on_about_to_finish (GstElement * playbin, DemoApp * d)
g_object_set (playbin, "uri", d->argv[d->current_uri], NULL);
}
-// ---------------------------------------------------
-// ---------------------------------------------------
-struct _gtk_wayland_for_event {
- DemoApp *d;
-
- struct wl_display *wl_display;
- struct wl_registry *wl_registry;
- struct wl_seat *wl_seat;
- struct wl_pointer *wl_pointer;
- struct wl_touch *wl_touch;
-};
-struct _gtk_wayland_for_event wayland_support;
-
-static void
-pointer_handle_enter(void *data, struct wl_pointer *pointer,
- uint32_t serial, struct wl_surface *surface,
- wl_fixed_t sx, wl_fixed_t sy)
-{
-}
-
-static void
-pointer_handle_leave(void *data, struct wl_pointer *pointer,
- uint32_t serial, struct wl_surface *surface)
-{
-}
-
-static void
-pointer_handle_motion(void *data, struct wl_pointer *pointer,
- uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
-{
-}
-
-static void
-pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
- uint32_t serial, uint32_t time, uint32_t button,
- uint32_t state)
-{
- struct _gtk_wayland_for_event* this = (struct _gtk_wayland_for_event*) data;
- guint32 diff;
- GstState actual_state;
-
- //g_print("Pointer button %d \n", state);
-
- if (WL_POINTER_BUTTON_STATE_RELEASED == state) return;
-
- if (last_pointer_tap == 0) {
- last_pointer_tap = time;
- //g_print("--> SIMPLE TAP\n");
- gst_element_get_state(this->d->pipeline, &actual_state, NULL, -1);
- if (actual_state == GST_STATE_PAUSED)
- gst_element_set_state (this->d->pipeline, GST_STATE_PLAYING);
- else
- gst_element_set_state (this->d->pipeline, GST_STATE_PAUSED);
- } else {
- diff = time - last_pointer_tap;
- if (last_pointer_tap != 0) {
- last_pointer_tap = time;
- if (diff < 600) {
- //g_print("--> DOUBLE TAP\n");
- gst_element_set_state (this->d->pipeline, GST_STATE_NULL);
- g_main_loop_quit (loop);
- exit(1);
- last_pointer_tap = 0;
- } else {
- gst_element_get_state(this->d->pipeline, &actual_state, NULL, -1);
- if (actual_state == GST_STATE_PAUSED)
- gst_element_set_state (this->d->pipeline, GST_STATE_PLAYING);
- else
- gst_element_set_state (this->d->pipeline, GST_STATE_PAUSED);
- //g_print("--> SIMPLE TAP\n");
- }
- //g_print("--> BEGIN diff = %d\n", diff);
- }
- }
-}
-
-static void
-pointer_handle_axis(void *data, struct wl_pointer *wl_pointer,
- uint32_t time, uint32_t axis, wl_fixed_t value)
-{
-}
-
-static const struct wl_pointer_listener pointer_listener = {
- pointer_handle_enter,
- pointer_handle_leave,
- pointer_handle_motion,
- pointer_handle_button,
- pointer_handle_axis,
-};
-static void
-touch_handle_down(void *data, struct wl_touch *wl_touch,
- uint32_t serial, uint32_t time, struct wl_surface *surface,
- int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
-{
- struct _gtk_wayland_for_event* this = (struct _gtk_wayland_for_event*) data;
- guint32 diff;
- GstState actual_state;
-
- g_print("TOUCH down\n");
- if (last_touch_tap == 0) {
- last_touch_tap = time;
- gst_element_get_state(this->d->pipeline, &actual_state, NULL, -1);
- if (actual_state == GST_STATE_PAUSED)
- gst_element_set_state (this->d->pipeline, GST_STATE_PLAYING);
- else
- gst_element_set_state (this->d->pipeline, GST_STATE_PAUSED);
- } else {
- diff = time - last_touch_tap;
- if (last_touch_tap != 0) {
- last_touch_tap = time;
- if (diff < 600) {
- //g_print("--> DOUBLE TAP\n");
- gst_element_set_state (this->d->pipeline, GST_STATE_NULL);
- g_main_loop_quit (loop);
- exit(1); //force to quit application
- } else {
- gst_element_get_state(this->d->pipeline, &actual_state, NULL, -1);
- if (actual_state == GST_STATE_PAUSED)
- gst_element_set_state (this->d->pipeline, GST_STATE_PLAYING);
- else
- gst_element_set_state (this->d->pipeline, GST_STATE_PAUSED);
- //g_print("--> SIMPLE TAP\n");
- }
- //g_print("--> BEGIN diff = %d\n", diff);
- }
- }
-}
-
-static void
-touch_handle_up(void *data, struct wl_touch *wl_touch,
- uint32_t serial, uint32_t time, int32_t id)
-{
-}
-
-static void
-touch_handle_motion(void *data, struct wl_touch *wl_touch,
- uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
-{
-}
-
-static void
-touch_handle_frame(void *data, struct wl_touch *wl_touch)
-{
-}
-static void
-touch_handle_cancel(void *data, struct wl_touch *wl_touch)
-{
-}
-static const struct wl_touch_listener touch_listener = {
- touch_handle_down,
- touch_handle_up,
- touch_handle_motion,
- touch_handle_frame,
- touch_handle_cancel,
-};
-static void
-seat_handle_capabilities(void *data, struct wl_seat *seat,
- enum wl_seat_capability caps)
-{
- struct _gtk_wayland_for_event* this = (struct _gtk_wayland_for_event*) data;
-
- //g_print("seat_handle_capabilities %d\n", caps);
-
- if ((caps & WL_SEAT_CAPABILITY_POINTER) && !this->wl_pointer) {
- this->wl_pointer = wl_seat_get_pointer(seat);
- wl_pointer_add_listener(this->wl_pointer, &pointer_listener, this);
- } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && this->wl_pointer) {
- wl_pointer_destroy(this->wl_pointer);
- this->wl_pointer = NULL;
- }
-
- if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !this->wl_touch) {
- this->wl_touch = wl_seat_get_touch(seat);
- wl_touch_set_user_data(this->wl_touch, this);
- wl_touch_add_listener(this->wl_touch, &touch_listener, this);
- } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && this->wl_touch) {
- wl_touch_destroy(this->wl_touch);
- this->wl_touch = NULL;
- }
-}
-
-static const struct wl_seat_listener seat_listener =
-{
- seat_handle_capabilities,
-};
-static void
-global_registry_handler(void *data, struct wl_registry *registry, uint32_t id,
- const char *interface, uint32_t version)
-{
- struct _gtk_wayland_for_event* this = (struct _gtk_wayland_for_event*) data;
-
- //g_print("registry event for %s id, %d data %p\n", interface, id, data);
- if (strcmp(interface, "wl_seat") == 0) {
- this->wl_seat = wl_registry_bind(registry, id, &wl_seat_interface, 1);
- wl_seat_add_listener(this->wl_seat, &seat_listener, this);
- }
-}
-
-static void
-global_registry_remover(void *data, struct wl_registry *registry, uint32_t id)
-{
- //g_print("registry lost for %d\n", id);
-}
-
-static const struct wl_registry_listener registry_listener = {
- global_registry_handler,
- global_registry_remover
-};
-
-void init_wl_event(GtkWidget *widget, DemoApp *d) {
- GdkDisplay *display;
-
- wayland_support.d = d;
-
- display = gtk_widget_get_display (widget);
- wayland_support.wl_display = gdk_wayland_display_get_wl_display (display);
- if (wayland_support.wl_display == NULL)
- return;
- wayland_support.wl_registry = wl_display_get_registry(wayland_support.wl_display);
- wl_registry_add_listener(wayland_support.wl_registry, &registry_listener, &wayland_support);
- wl_display_dispatch(wayland_support.wl_display);
- wl_display_roundtrip(wayland_support.wl_display);
-}
-// ---------------------------------------------------
-// ---------------------------------------------------
-struct _gst_caps_video_size {
- gint width;
- gint height;
-};
-
-static gboolean print_field (GQuark field, const GValue * value, gpointer pfx) {
- gchar *str = gst_value_serialize (value);
- const gchar *sfield = g_quark_to_string (field);
- struct _gst_caps_video_size *size = pfx;
- //g_print("--%s: %s\n", sfield, str);
-
- if (!strncmp(sfield, "width", 5) && (G_VALUE_TYPE(value) == G_TYPE_INT)) {
- size->width = g_value_get_int (value);
- } else if (!strncmp(sfield, "height", 6) && (G_VALUE_TYPE(value) == G_TYPE_INT)) {
- size->height = g_value_get_int (value);
- }
- g_free (str);
- return TRUE;
-}
-
-static gboolean msg_cb(GstBus * bus, GstMessage * message, gpointer data)
-{
- g_print ("*******message: %s\n", GST_MESSAGE_TYPE_NAME (message));
- return TRUE;
-}
-static void
-msg_structure_change (DemoApp *d)
-{
- const GstStructure *s;
- gint width, height;
- gint i;
- GstElement *sink;
- GstPad *pad = NULL;
- GstCaps *caps = NULL;
- struct _gst_caps_video_size video_size;
- video_size.width = video_size.height = 0;
-
- sink = gst_bin_get_by_name(GST_BIN(d->pipeline), "waylandsink0");
- pad = gst_element_get_static_pad (GST_ELEMENT(sink), "sink");
-
- caps = gst_pad_get_current_caps (GST_PAD(pad));
- if (!caps)
- caps = gst_pad_query_caps (GST_PAD(pad), NULL);
-
- for (i = 0; i < gst_caps_get_size(caps); i++) {
- GstStructure *structure = gst_caps_get_structure(caps, i);
- g_print ("******%s\n", gst_structure_get_name (structure));
- gst_structure_foreach (structure, print_field, &video_size);
- }
- if (nofullscreen) {
- if( (200 >= video_size.width) || (200 >= video_size.height) ) {
- video_size.width = 640;
- video_size.height = 480;
- }
- gtk_widget_set_size_request (d->window_widget, video_size.width, video_size.height);
- }
- g_print("-----------main:set size to %d %d \n", video_size.width, video_size.height );
- d->video_width = video_size.width;
- d->video_height = video_size.height;
-
- gst_caps_unref (caps);
- gst_object_unref (pad);
-}
-
static void
msg_state_changed (GstBus * bus, GstMessage * message, gpointer user_data)
{
@@ -380,13 +70,13 @@ msg_state_changed (GstBus * bus, GstMessage * message, gpointer user_data)
switch (new){
case GST_STATE_VOID_PENDING:
- g_print("new state: GST_STATE_VOID_PENDING\n");break;
+ g_print("new state: GST_STATE_VOID_PENDING\n");
+ break;
case GST_STATE_NULL:
- g_print("new state: GST_STATE_NULL\n");break;
+ g_print("new state: GST_STATE_NULL\n");
+ break;
case GST_STATE_READY:
g_print("new state: GST_STATE_READY\n");
- if (d->to_start)
- gst_element_set_state (d->pipeline, GST_STATE_PLAYING);
break;
case GST_STATE_PAUSED:
g_print("new state: GST_STATE_PAUSED\n");
@@ -400,8 +90,8 @@ msg_state_changed (GstBus * bus, GstMessage * message, gpointer user_data)
}
}
-int
-gstreamer_bus_callback (struct _GstBus * bus, GstMessage * message, void *data)
+static gboolean
+gstreamer_bus_callback (GstBus * bus, GstMessage * message, void *data)
{
DemoApp *d = data;
@@ -421,22 +111,18 @@ gstreamer_bus_callback (struct _GstBus * bus, GstMessage * message, void *data)
g_print ("Debug details: %s\n", debug);
g_free (debug);
}
- gst_element_set_state (d->pipeline, GST_STATE_NULL);
+ g_main_loop_quit (d->loop);
break;
}
case GST_MESSAGE_STATE_CHANGED:
- g_print ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message));
msg_state_changed (bus, message, data);
break;
case GST_MESSAGE_EOS:
/* end-of-stream */
- g_print ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message));
g_print ("EOS\n");
- gst_element_set_state (d->pipeline, GST_STATE_NULL);
- g_main_loop_quit (loop);
- exit(1);
+ g_main_loop_quit (d->loop);
break;
default:
@@ -446,34 +132,31 @@ gstreamer_bus_callback (struct _GstBus * bus, GstMessage * message, void *data)
return TRUE;
}
-
-
static gboolean
-button_notify_event_cb (GtkWidget *widget,
- GdkEventButton *event,
- gpointer data)
+button_notify_event_cb (GtkWidget * widget, GdkEventButton * event,
+ gpointer data)
{
DemoApp *d = data;
guint32 diff;
GstState actual_state;
+ g_print("--> %s\n", __FUNCTION__);
+
if (event->button == GDK_BUTTON_PRIMARY) {
- if (last_touch_tap == 0) {
- last_touch_tap = event->time;
+ if (d->last_pointer_tap == 0) {
+ d->last_pointer_tap = event->time;
gst_element_get_state(d->pipeline, &actual_state, NULL, -1);
if (actual_state == GST_STATE_PAUSED)
gst_element_set_state (d->pipeline, GST_STATE_PLAYING);
else
gst_element_set_state (d->pipeline, GST_STATE_PAUSED);
} else {
- diff = event->time - last_touch_tap;
- if (last_touch_tap != 0) {
- last_touch_tap = event->time;
+ diff = event->time - d->last_pointer_tap;
+ if (d->last_pointer_tap != 0) {
+ d->last_pointer_tap = event->time;
if (diff < 600) {
//g_print("--> DOUBLE TAP\n");
- gst_element_set_state (d->pipeline, GST_STATE_NULL);
- g_main_loop_quit (loop);
- exit(1); //force to quit application
+ g_main_loop_quit (d->loop);
} else {
gst_element_get_state(d->pipeline, &actual_state, NULL, -1);
if (actual_state == GST_STATE_PAUSED)
@@ -492,9 +175,7 @@ button_notify_event_cb (GtkWidget *widget,
}
static gboolean
-touch_notify_event_cb (GtkWidget *widget,
- GdkEvent *event,
- gpointer data)
+touch_notify_event_cb (GtkWidget * widget, GdkEvent * event, gpointer data)
{
DemoApp *d = data;
guint32 diff;
@@ -503,22 +184,20 @@ touch_notify_event_cb (GtkWidget *widget,
g_print("--> %s\n", __FUNCTION__);
switch(event->touch.type) {
case GDK_TOUCH_BEGIN:
- if (last_touch_tap == 0) {
- last_touch_tap = event->touch.time;
+ if (d->last_touch_tap == 0) {
+ d->last_touch_tap = event->touch.time;
gst_element_get_state(d->pipeline, &actual_state, NULL, -1);
if (actual_state == GST_STATE_PAUSED)
gst_element_set_state (d->pipeline, GST_STATE_PLAYING);
else
gst_element_set_state (d->pipeline, GST_STATE_PAUSED);
} else {
- diff = event->touch.time - last_touch_tap;
- if (last_touch_tap != 0) {
- last_touch_tap = event->touch.time;
+ diff = event->touch.time - d->last_touch_tap;
+ if (d->last_touch_tap != 0) {
+ d->last_touch_tap = event->touch.time;
if (diff < 600) {
g_print("--> DOUBLE TAP\n");
- gst_element_set_state (d->pipeline, GST_STATE_NULL);
- g_main_loop_quit (loop);
- exit(1); //force to quit application
+ g_main_loop_quit (d->loop);
} else {
gst_element_get_state(d->pipeline, &actual_state, NULL, -1);
if (actual_state == GST_STATE_PAUSED)
@@ -548,112 +227,21 @@ touch_notify_event_cb (GtkWidget *widget,
return TRUE;
}
-static GstBusSyncReply
-bus_sync_handler (GstBus * bus, GstMessage * message, gpointer user_data)
-{
- DemoApp *d = user_data;
-
- if (gst_is_wayland_display_handle_need_context_message (message)) {
- GstContext *context;
- GdkDisplay *display;
- struct wl_display *display_handle;
-
- msg_structure_change(d);
-
- display = gtk_widget_get_display (d->video_widget);
- display_handle = gdk_wayland_display_get_wl_display (display);
- context = gst_wayland_display_handle_context_new (display_handle);
- gst_element_set_context (GST_ELEMENT (GST_MESSAGE_SRC (message)), context);
-
- goto drop;
- } else if (gst_is_video_overlay_prepare_window_handle_message (message)) {
- GtkAllocation allocation;
- GdkWindow *window;
- struct wl_surface *window_handle;
-
- /* GST_MESSAGE_SRC (message) will be the overlay object that we have to
- * use. This may be waylandsink, but it may also be playbin. In the latter
- * case, we must make sure to use playbin instead of waylandsink, because
- * playbin resets the window handle and render_rectangle after restarting
- * playback and the actual window size is lost */
- d->overlay = GST_VIDEO_OVERLAY (GST_MESSAGE_SRC (message));
-
- msg_structure_change(d);
-
- gtk_widget_get_allocation (d->video_widget, &allocation);
- window = gtk_widget_get_window (d->video_widget);
- window_handle = gdk_wayland_window_get_wl_surface (window);
-
- init_wl_event(d->video_widget, d);
-
- g_print ("setting window handle and size (%d x %d)\n",
- allocation.width, allocation.height);
-
- gst_video_overlay_set_window_handle (d->overlay, (guintptr) window_handle);
- gst_video_overlay_set_render_rectangle (d->overlay, allocation.x,
- allocation.y, allocation.width, allocation.height);
-
- if (d->to_start) {
- gst_element_set_state (d->pipeline, GST_STATE_PLAYING);
- }
-
- goto drop;
- }
-
- return GST_BUS_PASS;
-
-drop:
- gst_message_unref (message);
- return GST_BUS_DROP;
-}
-
-/* We use the "draw" callback to change the size of the sink
- * because the "configure-event" is only sent to top-level widgets. */
-static gboolean
-video_widget_draw_cb (GtkWidget * widget, cairo_t * cr, gpointer user_data)
-{
- DemoApp *d = user_data;
- GtkAllocation allocation;
-
- gtk_widget_get_allocation (widget, &allocation);
-
- g_print ("draw_cb x %d, y %d, w %d, h %d\n",
- allocation.x, allocation.y, allocation.width, allocation.height);
-
- if (d->overlay) {
-
-// gst_video_overlay_set_render_rectangle (d->overlay, allocation.x,
-// allocation.y, allocation.width, allocation.height);
- if (nofullscreen) {
- int x, y;
- x = allocation.x + (allocation.width - d->video_width)/2;
- y = allocation.y + (allocation.height - d->video_height)/2;
- gst_video_overlay_set_render_rectangle (d->overlay, x,
- y, d->video_width, d->video_height);
- }
- else
- gst_video_overlay_set_render_rectangle (d->overlay, allocation.x,
- allocation.y, allocation.width, allocation.height);
- }
-
- /* There is no need to call gst_video_overlay_expose().
- * The wayland compositor can always re-draw the window
- * based on its last contents if necessary */
-
- return FALSE;
-}
-
static void
build_window (DemoApp * d)
{
- GtkWidget *box;
+ GtkCssProvider* provider;
+ GstElement *sink;
+ GtkWidget *video_widget;
/* windows */
d->window_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW(d->window_widget), "GStreamer Wayland GTK ");
- gtk_window_set_default_size (GTK_WINDOW (d->window_widget), window_width, window_height);
- gtk_window_set_transient_for (GTK_WINDOW(d->window_widget), NULL);
- g_signal_connect (GTK_WINDOW(d->window_widget), "destroy", G_CALLBACK (g_main_loop_quit), loop);
+ g_signal_connect (d->window_widget, "destroy",
+ G_CALLBACK (gtk_widget_destroyed), &d->window_widget);
+ g_signal_connect_swapped (d->window_widget, "destroy",
+ G_CALLBACK (g_main_loop_quit), d->loop);
+
if (!nofullscreen)
gtk_window_fullscreen(GTK_WINDOW(d->window_widget));
//else {
@@ -661,12 +249,11 @@ build_window (DemoApp * d)
//}
/* styling background color to black */
- GtkCssProvider* provider = gtk_css_provider_new();
-
- char *data = "#transparent_bg,GtkDrawingArea {\n"
+ const char *data = "#transparent_bg,GtkDrawingArea {\n"
" background-color: rgba (88%, 88%, 88%, 1.0);\n"
"}";
+ provider = gtk_css_provider_new();
gtk_css_provider_load_from_data(provider, data, -1, NULL);
gtk_style_context_add_provider(gtk_widget_get_style_context(d->window_widget),
GTK_STYLE_PROVIDER(provider),
@@ -675,19 +262,25 @@ build_window (DemoApp * d)
gtk_widget_set_name(d->window_widget, "transparent_bg");
-
- d->video_widget = gtk_event_box_new ();
- gtk_widget_set_support_multidevice (d->video_widget, TRUE);
- gtk_widget_set_app_paintable (d->video_widget, TRUE);
- gtk_event_box_set_above_child (GTK_EVENT_BOX(d->video_widget), TRUE);
- gtk_widget_set_vexpand (d->video_widget, TRUE);
- g_signal_connect (d->video_widget, "draw",
- G_CALLBACK (video_widget_draw_cb), d);
-
-
- gtk_container_add(GTK_CONTAINER (d->window_widget), d->video_widget);
- gtk_widget_show (d->video_widget);
+ sink = gst_bin_get_by_name (GST_BIN (d->pipeline), "gtkwsink");
+ if (!sink && !g_strcmp0 (G_OBJECT_TYPE_NAME (d->pipeline), "GstPlayBin"))
+ g_object_get (d->pipeline, "video-sink", &sink, NULL);
+ g_assert (sink);
+ g_assert (!g_strcmp0 (G_OBJECT_TYPE_NAME (sink), "GstGtkWaylandSink"));
+
+ g_object_get (sink, "widget", &video_widget, NULL);
+ gtk_widget_set_support_multidevice (video_widget, TRUE);
+ gtk_widget_set_vexpand (video_widget, TRUE);
+ g_signal_connect (video_widget, "touch-event",
+ G_CALLBACK (touch_notify_event_cb), d);
+ g_signal_connect (video_widget, "button-press-event",
+ G_CALLBACK (button_notify_event_cb), d);
+
+ gtk_container_add(GTK_CONTAINER (d->window_widget), video_widget);
gtk_widget_show_all (d->window_widget);
+
+ g_object_unref (video_widget);
+ gst_object_unref (sink);
}
static void
@@ -699,7 +292,6 @@ print_keyboard_help (void)
g_print ("\n");
}
-static gulong io_watch_id;
static void
keyboard_cb (const gchar key_input, gpointer user_data)
{
@@ -709,25 +301,25 @@ keyboard_cb (const gchar key_input, gpointer user_data)
/* only want to switch/case on single char, not first char of string */
if (key_input != '\0')
key = g_ascii_tolower (key_input);
+
switch (key) {
case 'h':
print_keyboard_help ();
- break;
+ break;
case 'p':
{
GstState actual_state;
gst_element_get_state(d->pipeline, &actual_state, NULL, -1);
- if (actual_state == GST_STATE_PAUSED)
- gst_element_set_state (d->pipeline, GST_STATE_PLAYING);
- else
+ if (actual_state == GST_STATE_PLAYING)
gst_element_set_state (d->pipeline, GST_STATE_PAUSED);
+ else
+ gst_element_set_state (d->pipeline, GST_STATE_PLAYING);
+ break;
}
- break;
case 'q':
- gst_element_set_state (d->pipeline, GST_STATE_NULL);
- local_kb_set_key_handler (NULL);
- g_main_loop_quit(loop);
- exit(1); //force to quit application
+ g_main_loop_quit(d->loop);
+ break;
+ default:
break;
}
}
@@ -739,7 +331,6 @@ io_callback (GIOChannel * io, GIOCondition condition, gpointer data)
GError *error = NULL;
switch (g_io_channel_read_chars (io, &in, 1, NULL, &error)) {
-
case G_IO_STATUS_NORMAL:
keyboard_cb(in, data);
return TRUE;
@@ -759,27 +350,31 @@ io_callback (GIOChannel * io, GIOCondition condition, gpointer data)
return FALSE;
}
-gboolean
-local_kb_set_key_handler(gpointer user_data)
+
+static void
+local_kb_set_key_handler (DemoApp *d, gboolean enable)
{
GIOChannel *io;
- if (io_watch_id > 0) {
- g_source_remove (io_watch_id);
- io_watch_id = 0;
+ if (d->io_watch_id > 0) {
+ g_source_remove (d->io_watch_id);
+ d->io_watch_id = 0;
+ }
+ if (enable) {
+ io = g_io_channel_unix_new (STDIN_FILENO);
+ d->io_watch_id = g_io_add_watch (io, G_IO_IN, io_callback, d);
+ g_io_channel_unref (io);
}
- io = g_io_channel_unix_new (STDIN_FILENO);
- io_watch_id = g_io_add_watch (io, G_IO_IN, io_callback, user_data);
- g_io_channel_unref (io);
- return TRUE;
}
+
int
main (int argc, char **argv)
{
- DemoApp *d;
+ DemoApp app = {NULL}, *d = &app;
GOptionContext *context;
GstBus *bus;
GError *error = NULL;
- guint bus_watch_id;
+ guint bus_watch_id = 0;
+ int ret = 0;
gtk_init (&argc, &argv);
gst_init (&argc, &argv);
@@ -787,22 +382,18 @@ main (int argc, char **argv)
context = g_option_context_new ("- waylandsink gtk demo");
g_option_context_add_main_entries (context, entries, NULL);
if (!g_option_context_parse (context, &argc, &argv, &error)) {
- g_printerr ("option parsing failed: %s\n", error->message);
- return 1;
+ g_option_context_free (context);
+ goto out;
}
-
- d = g_slice_new0 (DemoApp);
- build_window (d);
+ g_option_context_free (context);
if (argc > 1) {
d->argv = argv;
d->current_uri = 1;
- d->to_start = TRUE;
- if (!nofullscreen)
- d->pipeline = gst_parse_launch ("playbin video-sink='waylandsink fullscreen=true'", NULL);
- else
- d->pipeline = gst_parse_launch ("playbin video-sink='waylandsink'", NULL);
+ d->pipeline = gst_parse_launch ("playbin video-sink=gtkwaylandsink", &error);
+ if (error)
+ goto out;
g_object_set (d->pipeline, "uri", argv[d->current_uri], NULL);
@@ -811,146 +402,89 @@ main (int argc, char **argv)
G_CALLBACK (on_about_to_finish), d);
} else {
if (graph != NULL) {
- d->to_start = TRUE;
- if (strstr(graph, "waylandsink") != NULL) {
+ if (strstr(graph, "gtkwaylandsink") != NULL) {
d->pipeline = gst_parse_launch (graph, NULL);
} else {
- g_print("ERROR: grap does not contains waylandsink !!!\n");
- g_free(graph);
- return 1;
+ g_print("ERROR: graph does not contain gtkwaylandsink !!!\n");
+ ret = 1;
+ goto out;
}
} else if (shader_file != NULL) {
- gchar *shader_graph;
- gchar fragment_content[8096];
- FILE *fp;
- size_t nread, data_read, len=0;
- char *line;
+ gchar *fragment_content;
+ GFile *file;
GstElement *customshader;
- d->to_start = TRUE;
- shader_graph = g_strdup_printf("v4l2src ! video/x-raw, format=YUY2, width=320, height=240, framerate=(fraction)15/1 ! videorate ! video/x-raw,framerate=(fraction)5/1 ! queue ! videoconvert ! video/x-raw,format=RGBA ! queue ! glupload ! queue ! glshader name=customshader ! queue ! gldownload ! queue ! videoconvert ! queue ! waylandsink sync=false fullscreen=true");
- d->pipeline = gst_parse_launch (shader_graph, NULL);
+ d->pipeline = gst_parse_launch ("v4l2src ! "
+ "video/x-raw, format=YUY2, width=320, height=240, framerate=(fraction)15/1 ! "
+ "videorate ! video/x-raw,framerate=(fraction)5/1 ! "
+ "queue ! videoconvert ! video/x-raw,format=RGBA ! "
+ "queue ! glupload ! queue ! glshader name=customshader ! queue ! gldownload ! "
+ "queue ! videoconvert ! "
+ "queue ! gtkwaylandsink name=gtkwsink", &error);
+ if (error)
+ goto out;
+
+ file = g_file_new_for_path (shader_file);
+ g_file_load_contents (file, NULL, &fragment_content, NULL, NULL, &error);
+ g_object_unref (file);
+ if (error)
+ goto out;
customshader = gst_bin_get_by_name(GST_BIN(d->pipeline), "customshader");
g_assert(customshader);
- fp = fopen(shader_file, "r");
- if (fp == NULL) {
- g_print("ERROR: file cannot be openned, please specify absolute path!!\n");
- g_free(shader_file);
- return 1;
- } else {
- data_read = 0;
- bzero(fragment_content, sizeof fragment_content);
- while ((nread = getline(&line, &len, fp) ) != -1) {
- snprintf(fragment_content + data_read, 8096 - data_read, "%s", line);
- data_read += nread;
- }
- free(line);
- fclose(fp);
- //g_print("content: \n%s\n", fragment_content);
- }
- if (customshader) {
- //g_print("set fragment\n");
- g_object_set(customshader, "fragment", fragment_content, NULL);
- }
+ //g_print("set fragment, content: \n%s\n", fragment_content);
+ g_object_set(customshader, "fragment", fragment_content, NULL);
+ gst_object_unref (customshader);
+ g_free (fragment_content);
} else {
d->pipeline = gst_parse_launch ("videotestsrc pattern=18 "
- "background-color=0x000062FF ! waylandsink fullscreen=true", NULL);
+ "background-color=0x000062FF ! gtkwaylandsink name=gtkwsink",
+ &error);
+ if (error)
+ goto out;
}
}
+ d->loop = g_main_loop_new (NULL, FALSE);
+ build_window (d);
+
bus = gst_pipeline_get_bus (GST_PIPELINE (d->pipeline));
bus_watch_id = gst_bus_add_watch (bus, gstreamer_bus_callback, d);
- gst_bus_set_sync_handler (bus, bus_sync_handler, d, NULL);
gst_object_unref (bus);
- if (nofullscreen) {
- GstState state;
- GstElement *sink;
+ local_kb_set_key_handler (d, TRUE);
+ g_print ("Press 'h' to see a list of keyboard shortcuts.\n");
- gint i;
- struct _gst_caps_video_size video_size;
- video_size.width = video_size.height = 0;
+ gst_element_set_state (d->pipeline, GST_STATE_PLAYING);
- gst_element_set_state (d->pipeline, GST_STATE_PAUSED);
- gst_element_seek_simple (d->pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_FLUSH, GST_SECOND * 1);
- gst_element_get_state (d->pipeline, &state, NULL, GST_SECOND * 5);
+ g_main_loop_run (d->loop);
- switch (state){
- case GST_STATE_VOID_PENDING:
- g_print("state: GST_STATE_VOID_PENDING\n");break;
- case GST_STATE_NULL:
- g_print("state: GST_STATE_NULL\n");break;
- case GST_STATE_READY:
- g_print("state: GST_STATE_READY\n");
- break;
- case GST_STATE_PAUSED:
- g_print("state: GST_STATE_PAUSED\n");
- break;
- case GST_STATE_PLAYING:
- g_print("state: GST_STATE_PLAYING\n");
- break;
- default:
- break;
- }
+ local_kb_set_key_handler (d, FALSE);
- gst_element_seek_simple (d->pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_FLUSH, 0);
- gst_element_set_state (d->pipeline, GST_STATE_NULL);
- gst_element_set_state (d->pipeline, GST_STATE_PAUSED);
- }
+ gst_element_set_state (d->pipeline, GST_STATE_NULL);
- if (local_kb_set_key_handler (d)) {
- g_print ("Press 'h' to see a list of keyboard shortcuts.\n");
- } else {
- g_print ("Interactive keyboard handling in terminal not available.\n");
+out:
+ if (error) {
+ g_printerr ("ERROR: %s\n", error->message);
+ ret = 1;
}
+ g_clear_error (&error);
- gst_element_set_state (d->pipeline, GST_STATE_PLAYING);
- {
- GstState actual_state;
+ if (bus_watch_id)
+ g_source_remove (bus_watch_id);
- while (TRUE) {
- gst_element_get_state(d->pipeline, &actual_state, NULL, 2);
- switch (actual_state){
- case GST_STATE_VOID_PENDING:
- g_print("main state: GST_STATE_VOID_PENDING\n");
- break;
- case GST_STATE_NULL:
- g_print("main state: GST_STATE_NULL\n");
- break;
- case GST_STATE_READY:
- g_print("main state: GST_STATE_READY\n");
- break;
- case GST_STATE_PAUSED:
- g_print("main state: GST_STATE_PAUSED\n");
- break;
- case GST_STATE_PLAYING:
- g_print("main state: GST_STATE_PLAYING\n");
- break;
- default:
- break;
- }
- if (actual_state == GST_STATE_PLAYING)
- break;
-
- sleep(1);
- }
+ gst_clear_object (&d->pipeline);
+ if (d->window_widget) {
+ g_print ("destroy window\n");
+ g_signal_handlers_disconnect_by_data (d->window_widget, d->loop);
+ gtk_widget_destroy (d->window_widget);
}
- loop = g_main_loop_new (NULL, FALSE);
- g_main_loop_run (loop);
-
- local_kb_set_key_handler (NULL);
-
- gst_element_set_state (d->pipeline, GST_STATE_NULL);
- gst_object_unref (d->pipeline);
- g_object_unref (d->window_widget);
- g_source_remove (bus_watch_id);
- g_slice_free (DemoApp, d);
- g_main_loop_unref (loop);
+ g_clear_pointer (&d->loop, g_main_loop_unref);
g_free(graph);
+ g_free(shader_file);
- return 0;
+ return ret;
}
--
2.25.1