/*****************************************************************************
* voutgl.m: MacOS X OpenGL provider
*****************************************************************************
- * Copyright (C) 2001-2004, 2007 the VideoLAN team
+ * Copyright (C) 2001-2004, 2007-2009 the VideoLAN team
* $Id$
*
* Authors: Colin Delacroix <colin@zoy.org>
/*****************************************************************************
* Preamble
*****************************************************************************/
-#include <errno.h> /* ENOMEM */
#include <stdlib.h> /* free() */
#include <string.h>
+#include <vlc_common.h>
#include <vlc_keys.h>
#include "intf.h"
vout_thread_t * p_vout;
}
-+ (void)resetVout: (vout_thread_t *) p_vout;
++ (void)resetVout: (NSValue *) voutValue;
- (id) initWithVout: (vout_thread_t *) p_vout;
@end
struct vout_sys_t
{
- NSAutoreleasePool * o_pool;
VLCGLView * o_glview;
VLCVoutView * o_vout_view;
- bool b_saved_frame;
+ bool b_saved_frame;
NSRect s_frame;
- bool b_got_frame;
- /* Mozilla plugin-related variables */
- bool b_embedded;
+ bool b_got_frame;
+
+ /* Mozilla plugin-related variables (not 64bit compatible) */
+ bool b_embedded;
+#ifndef __x86_64__
AGLContext agl_ctx;
AGLDrawable agl_drawable;
int i_offx, i_offy;
int i_width, i_height;
WindowRef theWindow;
WindowGroupRef winGroup;
- bool b_clipped_out;
+ bool b_clipped_out;
Rect clipBounds, viewBounds;
+#endif
};
/*****************************************************************************
static int Lock ( vout_thread_t * p_vout );
static void Unlock ( vout_thread_t * p_vout );
+#ifndef __x86_64__
static int aglInit ( vout_thread_t * p_vout );
static void aglEnd ( vout_thread_t * p_vout );
static int aglManage ( vout_thread_t * p_vout );
static void aglSwap ( vout_thread_t * p_vout );
static int aglLock ( vout_thread_t * p_vout );
static void aglUnlock ( vout_thread_t * p_vout );
+#endif
-int E_(OpenVideoGL) ( vlc_object_t * p_this )
+int OpenVideoGL ( vlc_object_t * p_this )
{
vout_thread_t * p_vout = (vout_thread_t *) p_this;
- vlc_value_t value_drawable;
if( !CGDisplayUsesOpenGLAcceleration( kCGDirectMainDisplay ) )
{
msg_Warn( p_vout, "no OpenGL hardware acceleration found. "
- "Video display will be slow" );
- return( 1 );
+ "Video display might be slow" );
}
msg_Dbg( p_vout, "display is Quartz Extreme accelerated" );
p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
if( p_vout->p_sys == NULL )
- {
- msg_Err( p_vout, "out of memory" );
- return( 1 );
- }
+ return VLC_ENOMEM;
memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );
- var_Get( p_vout->p_libvlc, "drawable", &value_drawable );
- if( value_drawable.i_int != 0 )
+#ifndef __x86_64__
+ int i_drawable_agl;
+ i_drawable_agl = var_GetInteger( p_vout->p_libvlc, "drawable-agl" );
+ if( i_drawable_agl > 0 )
{
static const GLint ATTRIBUTES[] = {
AGL_WINDOW,
if( NULL == pixFormat )
{
msg_Err( p_vout, "no screen renderer available for required attributes." );
+ free( p_vout->p_sys );
return VLC_EGENERIC;
}
-
+
p_vout->p_sys->agl_ctx = aglCreateContext(pixFormat, NULL);
aglDestroyPixelFormat(pixFormat);
if( NULL == p_vout->p_sys->agl_ctx )
{
msg_Err( p_vout, "cannot create AGL context." );
+ free( p_vout->p_sys );
return VLC_EGENERIC;
}
- else {
+ else
+ {
// tell opengl not to sync buffer swap with vertical retrace (too inefficient)
GLint param = 0;
aglSetInteger(p_vout->p_sys->agl_ctx, AGL_SWAP_INTERVAL, ¶m);
}
else
{
+#endif
NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
p_vout->p_sys->b_embedded = false;
[o_pool release];
/* Check to see if initVout: was successfull */
-
if( !p_vout->p_sys->o_vout_view )
{
+ free( p_vout->p_sys );
return VLC_EGENERIC;
}
p_vout->pf_swap = Swap;
p_vout->pf_lock = Lock;
p_vout->pf_unlock = Unlock;
+#ifndef __x86_64__
}
+#endif
p_vout->p_sys->b_got_frame = false;
return VLC_SUCCESS;
}
-void E_(CloseVideoGL) ( vlc_object_t * p_this )
+void CloseVideoGL ( vlc_object_t * p_this )
{
vout_thread_t * p_vout = (vout_thread_t *) p_this;
+
+
+#ifndef __x86_64__
if( p_vout->p_sys->b_embedded )
{
- aglDestroyContext(p_vout->p_sys->agl_ctx);
+ /* If the fullscreen window is still open, close it */
+ if( p_vout->b_fullscreen )
+ {
+ p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
+ aglManage( p_vout );
+ var_SetBool( p_vout->p_parent, "fullscreen", false );
+ }
+ if( p_vout->p_sys->agl_ctx )
+ {
+ aglEnd( p_vout );
+ aglDestroyContext(p_vout->p_sys->agl_ctx);
+ }
}
- else if(VLCIntf && !VLCIntf->b_die)
+ else
+#endif
+ if(VLCIntf && vlc_object_alive (VLCIntf))
{
NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
}
- [p_vout->p_sys->o_vout_view manage];
+ if( p_vout->p_sys->o_vout_view )
+ [p_vout->p_sys->o_vout_view manage];
return VLC_SUCCESS;
}
[p_vout->p_sys->o_vout_view setOnTop: b_arg];
return VLC_SUCCESS;
- case VOUT_CLOSE:
- case VOUT_REPARENT:
default:
- return vout_vaControlDefault( p_vout, i_query, args );
+ return VLC_EGENERIC;
}
}
[p_vout->p_sys->o_glview autorelease];
/* Spawn the window */
- p_vout->p_sys->o_vout_view = [VLCVoutView getVoutView: p_vout
- subView: p_vout->p_sys->o_glview frame: nil];
+ id old_vout = p_vout->p_sys->o_vout_view;
+ p_vout->p_sys->o_vout_view = [[VLCVoutView voutView: p_vout
+ subView: p_vout->p_sys->o_glview frame: nil] retain];
+ [old_vout release];
}
/* This function will reset the o_vout_view. It's useful to go fullscreen. */
-+ (void)resetVout:(vout_thread_t *) p_vout
++ (void)resetVout:(NSValue *) voutValue
{
+ vout_thread_t * p_vout = [voutValue pointerValue];
if( p_vout->b_fullscreen )
{
/* Save window size and position */
p_vout->p_sys->s_frame.size =
[p_vout->p_sys->o_vout_view frame].size;
p_vout->p_sys->s_frame.origin =
- [[p_vout->p_sys->o_vout_view getWindow ]frame].origin;
+ [[p_vout->p_sys->o_vout_view voutWindow]frame].origin;
p_vout->p_sys->b_saved_frame = true;
}
#define o_glview p_vout->p_sys->o_glview
o_glview = [[VLCGLView alloc] initWithVout: p_vout];
[o_glview autorelease];
-
+
if( p_vout->p_sys->b_saved_frame )
{
- p_vout->p_sys->o_vout_view = [VLCVoutView getVoutView: p_vout
- subView: o_glview
- frame: &p_vout->p_sys->s_frame];
+ id old_vout = p_vout->p_sys->o_vout_view;
+ p_vout->p_sys->o_vout_view = [[VLCVoutView voutView: p_vout
+ subView: o_glview
+ frame: &p_vout->p_sys->s_frame] retain];
+ [old_vout release];
}
else
{
- p_vout->p_sys->o_vout_view = [VLCVoutView getVoutView: p_vout
- subView: o_glview frame: nil];
-
+ id old_vout = p_vout->p_sys->o_vout_view;
+ p_vout->p_sys->o_vout_view = [[VLCVoutView voutView: p_vout
+ subView: o_glview frame: nil] retain];
+ [old_vout release];
}
#undef o_glview
}
return self;
}
+- (BOOL)mouseDownCanMoveWindow
+{
+ return YES;
+}
+
- (void) reshape
{
int x, y;
- vlc_value_t val;
Lock( p_vout );
NSRect bounds = [self bounds];
- var_Get( p_vout, "macosx-stretch", &val );
- if( val.b_bool )
+ if( var_GetBool( p_vout, "macosx-stretch" ) )
{
x = bounds.size.width;
y = bounds.size.height;
Unlock( p_vout );
}
+- (void) renewGState
+{
+ NSWindow *window = [self window];
+
+ if ([window respondsToSelector:@selector(disableScreenUpdatesUntilFlush)])
+ {
+ [window disableScreenUpdatesUntilFlush];
+ }
+
+ [super renewGState];
+}
+
@end
/*****************************************************************************
* embedded AGL context implementation
*****************************************************************************/
+#ifndef __x86_64__
+
static void aglSetViewport( vout_thread_t *p_vout, Rect viewBounds, Rect clipBounds );
static void aglReshape( vout_thread_t * p_vout );
static OSStatus WindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
static int aglInit( vout_thread_t * p_vout )
{
- vlc_value_t val;
-
Rect viewBounds;
Rect clipBounds;
-
- var_Get( p_vout->p_libvlc, "drawable", &val );
- p_vout->p_sys->agl_drawable = (AGLDrawable)val.i_int;
+
+ p_vout->p_sys->agl_drawable = (AGLDrawable)
+ var_GetInteger( p_vout->p_libvlc, "drawable-agl" );
aglSetDrawable(p_vout->p_sys->agl_ctx, p_vout->p_sys->agl_drawable);
- var_Get( p_vout->p_libvlc, "drawable-view-top", &val );
- viewBounds.top = val.i_int;
- var_Get( p_vout->p_libvlc, "drawable-view-left", &val );
- viewBounds.left = val.i_int;
- var_Get( p_vout->p_libvlc, "drawable-view-bottom", &val );
- viewBounds.bottom = val.i_int;
- var_Get( p_vout->p_libvlc, "drawable-view-right", &val );
- viewBounds.right = val.i_int;
- var_Get( p_vout->p_libvlc, "drawable-clip-top", &val );
- clipBounds.top = val.i_int;
- var_Get( p_vout->p_libvlc, "drawable-clip-left", &val );
- clipBounds.left = val.i_int;
- var_Get( p_vout->p_libvlc, "drawable-clip-bottom", &val );
- clipBounds.bottom = val.i_int;
- var_Get( p_vout->p_libvlc, "drawable-clip-right", &val );
- clipBounds.right = val.i_int;
+ viewBounds.top = var_GetInteger( p_vout->p_libvlc, "drawable-view-top" );
+ viewBounds.left = var_GetInteger( p_vout->p_libvlc, "drawable-view-left" );
+ viewBounds.bottom = var_GetInteger( p_vout->p_libvlc, "drawable-view-bottom" );
+ viewBounds.right = var_GetInteger( p_vout->p_libvlc, "drawable-view-right" );
+ clipBounds.top = var_GetInteger( p_vout->p_libvlc, "drawable-clip-top" );
+ clipBounds.left = var_GetInteger( p_vout->p_libvlc, "drawable-clip-left" );
+ clipBounds.bottom = var_GetInteger( p_vout->p_libvlc, "drawable-clip-bottom" );
+ clipBounds.right = var_GetInteger( p_vout->p_libvlc, "drawable-clip-right" );
p_vout->p_sys->b_clipped_out = (clipBounds.top == clipBounds.bottom)
|| (clipBounds.left == clipBounds.right);
static void aglEnd( vout_thread_t * p_vout )
{
aglSetCurrentContext(NULL);
- if( p_vout->p_sys->theWindow ) DisposeWindow( p_vout->p_sys->theWindow );
+ if( p_vout->p_sys->theWindow )
+ {
+ DisposeWindow( p_vout->p_sys->theWindow );
+ p_vout->p_sys->theWindow = NULL;
+ }
}
static void aglReshape( vout_thread_t * p_vout )
if( p_vout->b_fullscreen )
{
/* Close the fullscreen window and resume normal drawing */
- vlc_value_t val;
Rect viewBounds;
Rect clipBounds;
- var_Get( p_vout->p_libvlc, "drawable", &val );
- p_vout->p_sys->agl_drawable = (AGLDrawable)val.i_int;
+ p_vout->p_sys->agl_drawable = (AGLDrawable)
+ var_GetInteger( p_vout->p_libvlc, "drawable-agl" );
+
aglSetDrawable(p_vout->p_sys->agl_ctx, p_vout->p_sys->agl_drawable);
- var_Get( p_vout->p_libvlc, "drawable-view-top", &val );
- viewBounds.top = val.i_int;
- var_Get( p_vout->p_libvlc, "drawable-view-left", &val );
- viewBounds.left = val.i_int;
- var_Get( p_vout->p_libvlc, "drawable-view-bottom", &val );
- viewBounds.bottom = val.i_int;
- var_Get( p_vout->p_libvlc, "drawable-view-right", &val );
- viewBounds.right = val.i_int;
- var_Get( p_vout->p_libvlc, "drawable-clip-top", &val );
- clipBounds.top = val.i_int;
- var_Get( p_vout->p_libvlc, "drawable-clip-left", &val );
- clipBounds.left = val.i_int;
- var_Get( p_vout->p_libvlc, "drawable-clip-bottom", &val );
- clipBounds.bottom = val.i_int;
- var_Get( p_vout->p_libvlc, "drawable-clip-right", &val );
- clipBounds.right = val.i_int;
+ viewBounds.top = var_GetInteger( p_vout->p_libvlc, "drawable-view-top" );
+ viewBounds.left = var_GetInteger( p_vout->p_libvlc, "drawable-view-left" );
+ viewBounds.bottom = var_GetInteger( p_vout->p_libvlc, "drawable-view-bottom" );
+ viewBounds.right = var_GetInteger( p_vout->p_libvlc, "drawable-view-right" );
+ clipBounds.top = var_GetInteger( p_vout->p_libvlc, "drawable-clip-top" );
+ clipBounds.left = var_GetInteger( p_vout->p_libvlc, "drawable-clip-left" );
+ clipBounds.bottom = var_GetInteger( p_vout->p_libvlc, "drawable-clip-bottom" );
+ clipBounds.right = var_GetInteger( p_vout->p_libvlc, "drawable-clip-right" );
aglSetCurrentContext(p_vout->p_sys->agl_ctx);
aglSetViewport(p_vout, viewBounds, clipBounds);
- /* Most Carbon APIs are not thread-safe, therefore delagate some GUI visibilty update to the main thread */
- sendEventToMainThread(GetWindowEventTarget(p_vout->p_sys->theWindow), kEventClassVLCPlugin, kEventVLCPluginHideFullscreen);
+ if( p_vout->p_sys->theWindow )
+ {
+ /* Most Carbon APIs are not thread-safe, therefore delagate some GUI visibilty
+ * update to the main thread */
+ sendEventToMainThread(GetWindowEventTarget(p_vout->p_sys->theWindow),
+ kEventClassVLCPlugin, kEventVLCPluginHideFullscreen);
+ }
}
else
{
+ /* Go into fullscreen */
Rect deviceRect;
-
+
GDHandle deviceHdl = GetMainDevice();
deviceRect = (*deviceHdl)->gdRect;
-
+
if( !p_vout->p_sys->theWindow )
{
/* Create a window */
- WindowAttributes windowAttrs;
+ WindowAttributes windowAttrs;
windowAttrs = kWindowStandardDocumentAttributes
| kWindowStandardHandlerAttribute
| kWindowLiveResizeAttribute
| kWindowNoShadowAttribute;
-
+
windowAttrs &= (~kWindowResizableAttribute);
CreateNewWindow(kDocumentWindowClass, windowAttrs, &deviceRect, &p_vout->p_sys->theWindow);
SetWindowGroup(p_vout->p_sys->theWindow, p_vout->p_sys->winGroup);
SetWindowGroupParent( p_vout->p_sys->winGroup, GetWindowGroupOfClass(kDocumentWindowClass) ) ;
}
-
+
// Window title
CFStringRef titleKey = CFSTR("Fullscreen VLC media plugin");
CFStringRef windowTitle = CFCopyLocalizedString(titleKey, NULL);
SetWindowTitleWithCFString(p_vout->p_sys->theWindow, windowTitle);
CFRelease(titleKey);
CFRelease(windowTitle);
-
+
//Install event handler
static const EventTypeSpec win_events[] = {
{ kEventClassMouse, kEventMouseDown },
aglSetViewport(p_vout, deviceRect, deviceRect);
//aglSetFullScreen(p_vout->p_sys->agl_ctx, device_width, device_height, 0, 0);
- /* Most Carbon APIs are not thread-safe, therefore delagate some GUI visibilty update to the main thread */
- sendEventToMainThread(GetWindowEventTarget(p_vout->p_sys->theWindow), kEventClassVLCPlugin, kEventVLCPluginShowFullscreen);
+ if( p_vout->p_sys->theWindow )
+ {
+ /* Most Carbon APIs are not thread-safe, therefore delagate some GUI visibilty
+ * update to the main thread */
+ sendEventToMainThread(GetWindowEventTarget(p_vout->p_sys->theWindow),
+ kEventClassVLCPlugin, kEventVLCPluginShowFullscreen);
+ }
}
aglReshape(p_vout);
aglUnlock( p_vout );
clipBounds.left = va_arg( args, int);
clipBounds.bottom = va_arg( args, int);
clipBounds.right = va_arg( args, int);
-
+
if( !p_vout->b_fullscreen )
{
/*
return VLC_SUCCESS;
}
- case VOUT_REPARENT:
- {
- AGLDrawable drawable = (AGLDrawable)va_arg( args, int);
- if( !p_vout->b_fullscreen && drawable != p_vout->p_sys->agl_drawable )
- {
- p_vout->p_sys->agl_drawable = drawable;
- aglSetDrawable(p_vout->p_sys->agl_ctx, drawable);
- }
- return VLC_SUCCESS;
- }
-
default:
- return vout_vaControlDefault( p_vout, i_query, args );
+ return VLC_EGENERIC;
}
}
- clipBounds.bottom; // from window bottom edge
rect[2] = clipBounds.right-clipBounds.left; // width
rect[3] = clipBounds.bottom-clipBounds.top; // height
+
aglSetInteger(p_vout->p_sys->agl_ctx, AGL_BUFFER_RECT, rect);
aglEnable(p_vout->p_sys->agl_ctx, AGL_BUFFER_RECT);
{
HICommand theHICommand;
GetEventParameter( event, kEventParamDirectObject, typeHICommand, NULL, sizeof( HICommand ), NULL, &theHICommand );
-
+
switch ( theHICommand.commandID )
{
default:
{
WindowRef window;
Rect rectPort = {0,0,0,0};
-
+
GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &window);
if(window)
case kEventWindowZoomed:
case kEventWindowBoundsChanged:
break;
-
+
default:
result = eventNotHandledErr;
}
case kEventMouseDown:
{
UInt16 button;
-
+
GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button);
switch (button)
{
case kEventMouseUp:
{
UInt16 button;
-
+
GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button);
switch (button)
{
else
{
vlc_value_t val;
+ int x, y;
- val.b_bool = true;
- var_Set( p_vout, "mouse-clicked", val );
+ var_GetCoords( p_vout, "mouse-moved", &x, &y );
+ var_SetCoords( p_vout, "mouse-clicked", x, y );
var_Get( p_vout, "mouse-button-down", &val );
val.i_int &= ~1;
unsigned int i_x, i_y;
unsigned int i_height = p_vout->p_sys->i_height;
unsigned int i_width = p_vout->p_sys->i_width;
+ int x, y;
vout_PlacePicture(p_vout, i_width, i_height, &i_x, &i_y, &i_width, &i_height);
GetEventParameter(event, kEventParamWindowMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &ml);
-
- val.i_int = ( ((int)ml.h) - i_x ) *
- p_vout->render.i_width / i_width;
- var_Set( p_vout, "mouse-x", val );
-
- val.i_int = ( ((int)ml.v) - i_y ) *
- p_vout->render.i_height / i_height;
-
- var_Set( p_vout, "mouse-y", val );
-
- val.b_bool = true;
- var_Set( p_vout, "mouse-moved", val );
+ x = (((int)ml.h) - i_x) * p_vout->render.i_width / i_width;
+ y = (((int)ml.v) - i_y) * p_vout->render.i_height / i_height;
+ var_SetCoords( p_vout, "mouse-moved", x, y );
break;
}
-
+
default:
result = eventNotHandledErr;
}
}
}
-
+#endif