gtk: implement GstNavigation interface

Now we can push key/mouse input into the pipeline for DVD use cases.
This commit is contained in:
Matthew Waters 2015-08-11 13:34:59 +02:00
parent 711589ebde
commit 988643eb43
3 changed files with 142 additions and 1 deletions

View file

@ -56,6 +56,9 @@ static gboolean gst_gtk_base_sink_set_caps (GstBaseSink * bsink,
static GstFlowReturn gst_gtk_base_sink_show_frame (GstVideoSink * bsink,
GstBuffer * buf);
static void
gst_gtk_base_sink_navigation_interface_init (GstNavigationInterface * iface);
enum
{
PROP_0,
@ -67,7 +70,10 @@ enum
#define gst_gtk_base_sink_parent_class parent_class
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstGtkBaseSink, gst_gtk_base_sink,
GST_TYPE_VIDEO_SINK, GST_DEBUG_CATEGORY_INIT (gst_debug_gtk_base_sink,
GST_TYPE_VIDEO_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"));
static void
@ -179,6 +185,10 @@ gst_gtk_base_sink_get_widget (GstGtkBaseSink * gtk_sink)
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));
return gtk_sink->widget;
}
@ -230,6 +240,31 @@ gst_gtk_base_sink_set_property (GObject * object, guint prop_id,
}
}
static void
gst_gtk_base_sink_navigation_send_event (GstNavigation * navigation,
GstStructure * structure)
{
GstGtkBaseSink *sink = GST_GTK_BASE_SINK (navigation);
GstEvent *event;
GstPad *pad;
event = gst_event_new_navigation (structure);
pad = gst_pad_get_peer (GST_VIDEO_SINK_PAD (sink));
GST_TRACE_OBJECT (sink, "navigation event %" GST_PTR_FORMAT, structure);
if (GST_IS_PAD (pad) && GST_IS_EVENT (event))
gst_pad_send_event (pad, event);
gst_object_unref (pad);
}
static void
gst_gtk_base_sink_navigation_interface_init (GstNavigationInterface * iface)
{
iface->send_event = gst_gtk_base_sink_navigation_send_event;
}
static gboolean
gst_gtk_base_sink_start (GstBaseSink * bsink)
{

View file

@ -219,6 +219,85 @@ _queue_draw (GtkGstBaseWidget * widget)
return G_SOURCE_REMOVE;
}
static const gchar *
_gdk_key_to_navigation_string (guint keyval)
{
/* TODO: expand */
switch (keyval) {
#define KEY(key) case GDK_KEY_ ## key: return G_STRINGIFY(key)
KEY (Up);
KEY (Down);
KEY (Left);
KEY (Right);
KEY (Home);
KEY (End);
#undef KEY
default:
return NULL;
}
}
static gboolean
gtk_gst_base_widget_key_event (GtkWidget * widget, GdkEventKey * event)
{
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);
}
g_object_unref (element);
}
return TRUE;
}
static gboolean
gtk_gst_base_widget_button_event (GtkWidget * widget, GdkEventButton * event)
{
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 *key_type =
event->type ==
GDK_BUTTON_PRESS ? "mouse-button-press" : "mouse-button-release";
gst_navigation_send_mouse_event (GST_NAVIGATION (element), key_type,
event->button, event->x, event->y);
}
g_object_unref (element);
}
return TRUE;
}
static gboolean
gtk_gst_base_widget_motion_event (GtkWidget * widget, GdkEventMotion * event)
{
GtkGstBaseWidget *base_widget = GTK_GST_BASE_WIDGET (widget);
GstElement *element;
if ((element = g_weak_ref_get (&base_widget->element))) {
if (GST_IS_NAVIGATION (element)) {
gst_navigation_send_mouse_event (GST_NAVIGATION (element), "motion-move",
0, event->x, event->y);
}
g_object_unref (element);
}
return TRUE;
}
void
gtk_gst_base_widget_class_init (GtkGstBaseWidgetClass * klass)
{
@ -247,11 +326,18 @@ gtk_gst_base_widget_class_init (GtkGstBaseWidgetClass * klass)
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;
}
void
gtk_gst_base_widget_init (GtkGstBaseWidget * widget)
{
int event_mask;
widget->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO;
widget->par_n = DEFAULT_PAR_N;
widget->par_d = DEFAULT_PAR_D;
@ -260,7 +346,17 @@ gtk_gst_base_widget_init (GtkGstBaseWidget * widget)
gst_video_info_init (&widget->v_info);
gst_video_info_init (&widget->pending_v_info);
g_weak_ref_init (&widget->element, NULL);
g_mutex_init (&widget->lock);
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
@ -270,11 +366,19 @@ gtk_gst_base_widget_finalize (GObject * object)
gst_buffer_replace (&widget->buffer, NULL);
g_mutex_clear (&widget->lock);
g_weak_ref_clear (&widget->element);
if (widget->draw_id)
g_source_remove (widget->draw_id);
}
void
gtk_gst_base_widget_set_element (GtkGstBaseWidget * widget,
GstElement * element)
{
g_weak_ref_set (&widget->element, element);
}
gboolean
gtk_gst_base_widget_set_format (GtkGstBaseWidget * widget,
GstVideoInfo * v_info)

View file

@ -68,6 +68,7 @@ struct _GtkGstBaseWidget
/*< private >*/
GMutex lock;
GWeakRef element;
/* Pending draw idles callback */
guint draw_id;
@ -92,6 +93,7 @@ void gtk_gst_base_widget_finalize (GObject * object);
/* API */
gboolean gtk_gst_base_widget_set_format (GtkGstBaseWidget * widget, GstVideoInfo * v_info);
void gtk_gst_base_widget_set_buffer (GtkGstBaseWidget * widget, GstBuffer * buffer);
void gtk_gst_base_widget_set_element (GtkGstBaseWidget * widget, GstElement * element);
G_END_DECLS