mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-02 04:22:27 +00:00
osxvideosink: implement the navigation interface
This commit is contained in:
parent
088bc6b056
commit
ba5d55dd69
3 changed files with 199 additions and 16 deletions
|
@ -29,6 +29,7 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
#import <QuickTime/QuickTime.h>
|
||||
#import <glib.h>
|
||||
#import <gst/interfaces/navigation.h>
|
||||
|
||||
struct _GstOSXImage;
|
||||
|
||||
|
@ -44,6 +45,8 @@ struct _GstOSXImage;
|
|||
BOOL fullscreen;
|
||||
NSOpenGLContext* fullScreenContext;
|
||||
NSOpenGLContext* actualContext;
|
||||
NSTrackingArea *trackingArea;
|
||||
GstNavigation *navigation;
|
||||
}
|
||||
- (void) drawQuad;
|
||||
- (void) drawRect: (NSRect) rect;
|
||||
|
@ -60,6 +63,7 @@ struct _GstOSXImage;
|
|||
- (void) haveSuperviewReal: (NSMutableArray *)closure;
|
||||
- (void) addToSuperview: (NSView *)superview;
|
||||
- (void) removeFromSuperview: (id)unused;
|
||||
- (void) setNavigation: (GstNavigation *) nav;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -82,21 +82,6 @@
|
|||
[self setAcceptsMouseMovedEvents:YES];
|
||||
}
|
||||
|
||||
- (void) sendEvent:(NSEvent *) event {
|
||||
BOOL taken = NO;
|
||||
|
||||
GST_DEBUG ("event %p type:%d", event,(gint)[event type]);
|
||||
|
||||
if ([event type] == NSKeyDown) {
|
||||
}
|
||||
/*taken = [gstview keyDown:event]; */
|
||||
|
||||
if (!taken) {
|
||||
[super sendEvent:event];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
@ -144,6 +129,13 @@
|
|||
|
||||
GST_LOG ("Width: %d Height: %d", width, height);
|
||||
|
||||
trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
|
||||
options: (NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveInKeyWindow)
|
||||
owner:self
|
||||
userInfo:nil];
|
||||
|
||||
[self addTrackingArea:trackingArea];
|
||||
|
||||
[self initTextures];
|
||||
return self;
|
||||
}
|
||||
|
@ -429,4 +421,119 @@
|
|||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)updateTrackingAreas {
|
||||
[self removeTrackingArea:trackingArea];
|
||||
[trackingArea release];
|
||||
trackingArea = [[NSTrackingArea alloc] initWithRect: [self bounds]
|
||||
options: (NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveInKeyWindow)
|
||||
owner:self userInfo:nil];
|
||||
[self addTrackingArea:trackingArea];
|
||||
}
|
||||
|
||||
- (BOOL)acceptsFirstResponder {
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void) setNavigation:(GstNavigation *)nav
|
||||
{
|
||||
navigation = nav;
|
||||
}
|
||||
|
||||
- (void)sendMouseEvent:(NSEvent *)event: (const char *)event_name
|
||||
{
|
||||
NSPoint location;
|
||||
NSRect bounds;
|
||||
gint button;
|
||||
gint view_width, view_height;
|
||||
gdouble x, y;
|
||||
|
||||
if (!navigation)
|
||||
return;
|
||||
|
||||
switch ([event type]) {
|
||||
case NSMouseMoved:
|
||||
button = 0;
|
||||
break;
|
||||
case NSLeftMouseDown:
|
||||
case NSLeftMouseUp:
|
||||
button = 1;
|
||||
break;
|
||||
case NSRightMouseDown:
|
||||
case NSRightMouseUp:
|
||||
button = 2;
|
||||
break;
|
||||
default:
|
||||
button = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
location = [self convertPoint:[event locationInWindow] fromView:nil];
|
||||
|
||||
/* scale X and Y locations to the frame size */
|
||||
bounds = [self bounds];
|
||||
view_width = bounds.size.width;
|
||||
view_height = bounds.size.height;
|
||||
|
||||
x = ((gdouble) location.x / view_width) * width;
|
||||
y = ((gdouble) location.y / view_height) * height;
|
||||
|
||||
/* invert Y */
|
||||
y = (1 - y / height) * height;
|
||||
|
||||
gst_navigation_send_mouse_event (navigation, event_name, button,
|
||||
x, y);
|
||||
}
|
||||
|
||||
- (void)sendKeyEvent:(NSEvent *)event: (const char *)event_name
|
||||
{
|
||||
NSString *keyCharStr = [event charactersIgnoringModifiers];
|
||||
gchar * key_str;
|
||||
|
||||
if (!navigation)
|
||||
return;
|
||||
|
||||
if ( [keyCharStr length] == 0 )
|
||||
return;
|
||||
|
||||
if ( [keyCharStr length] == 1 ) {
|
||||
key_str = g_strdup_printf("%c", [keyCharStr characterAtIndex:0]);
|
||||
gst_navigation_send_key_event(navigation, event_name, (const gchar *) key_str);
|
||||
g_free(key_str);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)keyDown:(NSEvent *) event;
|
||||
{
|
||||
[self sendKeyEvent: event: "key-press"];
|
||||
}
|
||||
|
||||
- (void)keyUp:(NSEvent *) event;
|
||||
{
|
||||
[self sendKeyEvent: event: "key-release"];
|
||||
}
|
||||
|
||||
- (void)mouseDown:(NSEvent *) event;
|
||||
{
|
||||
[self sendMouseEvent:event: "mouse-button-press"];
|
||||
}
|
||||
|
||||
- (void)mouseUp:(NSEvent *) event;
|
||||
{
|
||||
[self sendMouseEvent:event: "mouse-button-release"];
|
||||
}
|
||||
|
||||
- (void)mouseMoved:(NSEvent *)event;
|
||||
{
|
||||
[self sendMouseEvent:event: "mouse-move"];
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(NSEvent *)event;
|
||||
{
|
||||
}
|
||||
|
||||
- (void)mouseExited:(NSEvent *)event;
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -148,6 +148,7 @@ gst_osx_video_sink_osxwindow_create (GstOSXVideoSink * osxvideosink, gint width,
|
|||
GST_INFO_OBJECT (osxvideosink, "no superview");
|
||||
}
|
||||
}
|
||||
[osxwindow->gstview setNavigation: GST_NAVIGATION(osxvideosink)];
|
||||
|
||||
[pool release];
|
||||
|
||||
|
@ -416,7 +417,7 @@ gst_osx_video_sink_class_init (GstOSXVideoSinkClass * klass)
|
|||
static gboolean
|
||||
gst_osx_video_sink_interface_supported (GstImplementsInterface * iface, GType type)
|
||||
{
|
||||
g_assert (type == GST_TYPE_X_OVERLAY);
|
||||
g_assert (type == GST_TYPE_X_OVERLAY || type == GST_TYPE_NAVIGATION);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -426,6 +427,72 @@ gst_osx_video_sink_interface_init (GstImplementsInterfaceClass * klass)
|
|||
klass->supported = gst_osx_video_sink_interface_supported;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_osx_video_sink_navigation_send_event (GstNavigation * navigation,
|
||||
GstStructure * structure)
|
||||
{
|
||||
GstOSXVideoSink *osxvideosink = GST_OSX_VIDEO_SINK (navigation);
|
||||
GstPad *peer;
|
||||
GstEvent *event;
|
||||
GstVideoRectangle src, dst, result;
|
||||
gdouble x, y, xscale = 1.0, yscale = 1.0;
|
||||
|
||||
peer = gst_pad_get_peer (GST_VIDEO_SINK_PAD (osxvideosink));
|
||||
|
||||
if (!peer || !osxvideosink->osxwindow)
|
||||
return;
|
||||
|
||||
event = gst_event_new_navigation (structure);
|
||||
|
||||
/* FIXME: Use this when this sink is capable of keeping the display
|
||||
* aspect ratio */
|
||||
if (0) { //(osxvideosink->keep_aspect) {
|
||||
/* We get the frame position using the calculated geometry from _setcaps
|
||||
that respect pixel aspect ratios */
|
||||
src.w = GST_VIDEO_SINK_WIDTH (osxvideosink);
|
||||
src.h = GST_VIDEO_SINK_HEIGHT (osxvideosink);
|
||||
//dst.w = osxvideosink->osxwindow->gstview->width;
|
||||
//dst.w = osxvideosink->osxwindow->gstview->height;
|
||||
|
||||
gst_video_sink_center_rect (src, dst, &result, TRUE);
|
||||
//result.x += osxvideosink->gstview->x;
|
||||
//result.y += osxvideosink->gstview->y;
|
||||
} else {
|
||||
result.x = 0;
|
||||
result.y = 0;
|
||||
result.w = osxvideosink->osxwindow->width;
|
||||
result.h = osxvideosink->osxwindow->height;
|
||||
}
|
||||
|
||||
/* We calculate scaling using the original video frames geometry to include
|
||||
pixel aspect ratio scaling. */
|
||||
xscale = (gdouble) osxvideosink->osxwindow->width / result.w;
|
||||
yscale = (gdouble) osxvideosink->osxwindow->height / result.h;
|
||||
|
||||
/* Converting pointer coordinates to the non scaled geometry */
|
||||
if (gst_structure_get_double (structure, "pointer_x", &x)) {
|
||||
x = MIN (x, result.x + result.w);
|
||||
x = MAX (x - result.x, 0);
|
||||
gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE,
|
||||
(gdouble) x * xscale, NULL);
|
||||
}
|
||||
if (gst_structure_get_double (structure, "pointer_y", &y)) {
|
||||
y = MIN (y, result.y + result.h);
|
||||
y = MAX (y - result.y, 0);
|
||||
gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE,
|
||||
(gdouble) y * yscale, NULL);
|
||||
}
|
||||
|
||||
gst_pad_send_event (peer, event);
|
||||
gst_object_unref (peer);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_osx_video_sink_navigation_init (GstNavigationInterface * iface)
|
||||
{
|
||||
iface->send_event = gst_osx_video_sink_navigation_send_event;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_osx_video_sink_set_window_handle (GstXOverlay * overlay, guintptr handle_id)
|
||||
{
|
||||
|
@ -500,6 +567,11 @@ gst_osx_video_sink_get_type (void)
|
|||
NULL,
|
||||
};
|
||||
|
||||
static const GInterfaceInfo navigation_info = {
|
||||
(GInterfaceInitFunc) gst_osx_video_sink_navigation_init,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
osxvideosink_type = g_type_register_static (GST_TYPE_VIDEO_SINK,
|
||||
"GstOSXVideoSink", &osxvideosink_info, 0);
|
||||
|
||||
|
|
Loading…
Reference in a new issue