osxvideosink: implement the navigation interface

This commit is contained in:
Andoni Morales Alastruey 2012-05-14 14:27:58 +02:00 committed by Sebastian Dröge
parent 088bc6b056
commit ba5d55dd69
3 changed files with 199 additions and 16 deletions

View file

@ -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

View file

@ -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

View file

@ -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);