From d12b9b611aa7030047e6556714e859dd2bfd38fc Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sun, 11 Dec 2011 12:26:00 +0100 Subject: vo_corevideo: use cocoa_common to display the window Change vo_corevideo to use cocoa_common to create and manage the window. This doesn't affect external OSX GUIs, since they don't use vo_corevideo window management, but only read the image data from the shared buffer. --- configure | 44 ++- libvo/cocoa_common.h | 3 + libvo/cocoa_common.m | 15 +- libvo/vo_corevideo.h | 73 ---- libvo/vo_corevideo.m | 913 +++++++++------------------------------------------ 5 files changed, 185 insertions(+), 863 deletions(-) diff --git a/configure b/configure index 27dde1a754..f9a4bbaafe 100755 --- a/configure +++ b/configure @@ -4187,21 +4187,35 @@ else fi echores $quicktime -echocheck "CoreVideo" -if test "$_corevideo" = auto ; then +echocheck "Cocoa" +if test "$_cocoa" = auto ; then cat > $TMPC < #include #include +int main(void) { + NSApplicationLoad(); +} +EOF + _cocoa=no + cc_check -framework Cocoa -framework OpenGL && _cocoa=yes +fi +if test "$_cocoa" = yes ; then + libs_mplayer="$libs_mplayer -framework Cocoa -framework OpenGL" +fi +echores "$_cocoa" + +echocheck "CoreVideo" +if test "$_cocoa" = yes && test "$_corevideo" = auto ; then + cat > $TMPC < int main(void) { return 0; } EOF _corevideo=no - cc_check -framework Carbon -framework Cocoa -framework QuartzCore -framework OpenGL && _corevideo=yes + cc_check -framework Cocoa -framework QuartzCore -framework OpenGL && _corevideo=yes fi if test "$_corevideo" = yes ; then vomodules="corevideo $vomodules" - libs_mplayer="$libs_mplayer -framework Carbon -framework Cocoa -framework QuartzCore -framework OpenGL" + libs_mplayer="$libs_mplayer -framework QuartzCore" def_corevideo='#define CONFIG_COREVIDEO 1' else novomodules="corevideo $novomodules" @@ -4209,26 +4223,6 @@ else fi echores "$_corevideo" -echocheck "Cocoa" -if test "$_gl" = no ; then - # if _gl is not enabled there is no point to add potentially unused linker flags - _cocoa=no -fi -if test "$_cocoa" = auto ; then - cat > $TMPC < -#include -#include -int main(void) { return 0; } -EOF - _cocoa=no - cc_check -framework Cocoa -framework QuartzCore -framework OpenGL && _cocoa=yes -fi -if test "$_cocoa" = yes ; then - libs_mplayer="$libs_mplayer -framework Cocoa -framework QuartzCore -framework OpenGL" -fi -echores "$_cocoa" - fi #if darwin diff --git a/libvo/cocoa_common.h b/libvo/cocoa_common.h index 16f9a2f1f9..a118f37149 100644 --- a/libvo/cocoa_common.h +++ b/libvo/cocoa_common.h @@ -39,4 +39,7 @@ void vo_cocoa_ontop(struct vo *vo); // returns an int to conform to the gl extensions from other platforms int vo_cocoa_swap_interval(int enabled); +void *vo_cocoa_cgl_context(void); +void *vo_cocoa_cgl_pixel_format(void); + #endif /* MPLAYER_COCOA_COMMON_H */ diff --git a/libvo/cocoa_common.m b/libvo/cocoa_common.m index f5ad7a0943..af2f4adaaf 100644 --- a/libvo/cocoa_common.m +++ b/libvo/cocoa_common.m @@ -54,6 +54,7 @@ struct vo_cocoa_state { NSAutoreleasePool *pool; GLMPlayerWindow *window; NSOpenGLContext *glContext; + NSOpenGLPixelFormat *pixelFormat; NSSize current_video_size; NSSize previous_video_size; @@ -212,8 +213,8 @@ int vo_cocoa_create_window(struct vo *vo, uint32_t d_width, (NSOpenGLPixelFormatAttribute)0 }; - NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]; - s->glContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil]; + s->pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attrs] autorelease]; + s->glContext = [[NSOpenGLContext alloc] initWithFormat:s->pixelFormat shareContext:nil]; create_menu(); @@ -345,6 +346,16 @@ int vo_cocoa_swap_interval(int enabled) return 0; } +void *vo_cocoa_cgl_context(void) +{ + return [s->glContext CGLContextObj]; +} + +void *vo_cocoa_cgl_pixel_format(void) +{ + return [s->pixelFormat CGLPixelFormatObj]; +} + void create_menu() { NSMenu *menu; diff --git a/libvo/vo_corevideo.h b/libvo/vo_corevideo.h index 926399053f..28b3807376 100644 --- a/libvo/vo_corevideo.h +++ b/libvo/vo_corevideo.h @@ -39,77 +39,4 @@ - (void) ontop; @end -@interface MPlayerOpenGLView : NSOpenGLView -{ - //Cocoa - NSWindow *window; - - //CoreVideo - CVPixelBufferRef frameBuffers[2]; - CVOpenGLTextureCacheRef textureCache; - CVOpenGLTextureRef texture; - NSRect textureFrame; - - GLfloat lowerLeft[2]; - GLfloat lowerRight[2]; - GLfloat upperRight[2]; - GLfloat upperLeft[2]; - - BOOL mouseHide; - - //menu command id - NSMenuItem *kHalfScreenCmd; - NSMenuItem *kNormalScreenCmd; - NSMenuItem *kDoubleScreenCmd; - NSMenuItem *kFullScreenCmd; - NSMenuItem *kKeepAspectCmd; - NSMenuItem *kAspectOrgCmd; - NSMenuItem *kAspectFullCmd; - NSMenuItem *kAspectWideCmd; - NSMenuItem *kPanScanCmd; - - //timestamps for disabling screensaver and mouse hiding - int lastMouseHide; - int lastScreensaverUpdate; -@public - float winSizeMult; -} - -- (BOOL) acceptsFirstResponder; -- (BOOL) becomeFirstResponder; -- (BOOL) resignFirstResponder; - -//window & rendering -- (void) preinit; -- (void) config; -- (void) prepareOpenGL; -- (void) render; -- (void) reshape; -- (void) setCurrentTexture; -- (void) drawRect: (NSRect *) bounds; - -//vo control -- (void) fullscreen: (BOOL) animate; -- (void) ontop; -- (void) panscan; -- (void) rootwin; - -//menu -- (void) initMenu; -- (void) menuAction:(id)sender; - -//event -- (void) keyDown: (NSEvent *) theEvent; -- (void) mouseMoved: (NSEvent *) theEvent; -- (void) mouseDown: (NSEvent *) theEvent; -- (void) mouseUp: (NSEvent *) theEvent; -- (void) rightMouseDown: (NSEvent *) theEvent; -- (void) rightMouseUp: (NSEvent *) theEvent; -- (void) otherMouseDown: (NSEvent *) theEvent; -- (void) otherMouseUp: (NSEvent *) theEvent; -- (void) scrollWheel: (NSEvent *) theEvent; -- (void) mouseEvent: (NSEvent *) theEvent; -- (void) check_events; -@end - #endif /* MPLAYER_VO_COREVIDEO_H */ diff --git a/libvo/vo_corevideo.m b/libvo/vo_corevideo.m index 5e1dd71259..7506a8d108 100644 --- a/libvo/vo_corevideo.m +++ b/libvo/vo_corevideo.m @@ -25,11 +25,6 @@ #include #include #include -//special workaround for Apple bug #6267445 -//(OSServices Power API disabled in OSServices.h for 64bit systems) -#ifndef __POWER__ -#include -#endif //MPLAYER #include "config.h" @@ -45,12 +40,12 @@ #include "input/input.h" #include "input/keycodes.h" -#include "osx_common.h" + +#import "cocoa_common.h" //Cocoa NSDistantObject *mplayerosxProxy; id mplayerosxProto; -MPlayerOpenGLView *mpGLView; NSAutoreleasePool *autoreleasepool; OSType pixelFormat; @@ -59,11 +54,18 @@ BOOL shared_buffer = false; #define DEFAULT_BUFFER_NAME "mplayerosx" static char *buffer_name; -//Screen -int screen_id = -1; -NSRect screen_frame; -NSScreen *screen_handle; -NSArray *screen_array; +int screen_id; + +//CoreVideo +CVPixelBufferRef frameBuffers[2]; +CVOpenGLTextureCacheRef textureCache; +CVOpenGLTextureRef texture; +NSRect textureFrame; + +GLfloat lowerLeft[2]; +GLfloat lowerRight[2]; +GLfloat upperRight[2]; +GLfloat upperLeft[2]; //image unsigned char *image_data; @@ -77,24 +79,11 @@ static uint32_t image_depth; static uint32_t image_bytes; static uint32_t image_format; -//vo -static int isFullscreen; -static int isOntop; -static int isRootwin; - -static float winAlpha = 1; -static int int_pause = 0; - -static BOOL isLeopardOrLater; - -#define NSLeftAlternateKeyMask (0x000020 | NSAlternateKeyMask) -#define NSRightAlternateKeyMask (0x000040 | NSAlternateKeyMask) - static vo_info_t info = { "Mac OS X Core Video", "corevideo", - "Nicolas Plourde ", + "Nicolas Plourde and others", "" }; @@ -117,29 +106,6 @@ static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, unsigne } } -static void update_screen_info(void) -{ - if (screen_id == -1 && xinerama_screen > -1) - screen_id = xinerama_screen; - - screen_array = [NSScreen screens]; - if(screen_id >= (int)[screen_array count]) - { - mp_msg(MSGT_VO, MSGL_INFO, "[vo_corevideo] Device ID %d does not exist, falling back to main device\n", screen_id); - screen_id = -1; - } - if (screen_id < 0 && [mpGLView window]) - screen_handle = [[mpGLView window] screen]; - else - screen_handle = [screen_array objectAtIndex:(screen_id < 0 ? 0 : screen_id)]; - - screen_frame = [screen_handle frame]; - vo_screenwidth = screen_frame.size.width; - vo_screenheight = screen_frame.size.height; - xinerama_x = xinerama_y = 0; - aspect_save_screenres(vo_screenwidth, vo_screenheight); -} - static void free_file_specific(void) { if(shared_buffer) @@ -164,6 +130,32 @@ static void free_file_specific(void) } } +static void resize(int width, int height) +{ + int d_width, d_height; + + mp_msg(MSGT_VO, MSGL_V, "[vo_corevideo] New OpenGL Viewport (0, 0, %d, %d)\n", width, height); + + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, width, height, 0, -1.0, 1.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + aspect(&d_width, &d_height, A_WINZOOM); + textureFrame = NSMakeRect((vo_dwidth - d_width) / 2, (vo_dheight - d_height) / 2, d_width, d_height); +} + +static void prepare_opengl(void) +{ + glEnable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + glDisable(GL_CULL_FACE); + resize(global_vo->dwidth, global_vo->dheight); +} + static int config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t flags, char *title, uint32_t format) { free_file_specific(); @@ -171,8 +163,7 @@ static int config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_ //misc mplayer setup image_width = width; image_height = height; - switch (image_format) - { + switch (image_format) { case IMGFMT_RGB24: image_depth = 24; break; @@ -184,14 +175,11 @@ static int config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_ image_depth = 16; break; } - image_bytes = (image_depth + 7) / 8; - if(!shared_buffer) - { - config_movie_aspect((float)d_width/d_height); + image_bytes = (image_depth ? image_depth : 16 + 7) / 8; - vo_dwidth = d_width *= mpGLView->winSizeMult; - vo_dheight = d_height *= mpGLView->winSizeMult; + if (!shared_buffer) { + CVReturn error; image_data = malloc(image_width*image_height*image_bytes); image_datas[0] = image_data; @@ -199,30 +187,50 @@ static int config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_ image_datas[1] = malloc(image_width*image_height*image_bytes); image_page = 0; - vo_fs = flags & VOFLAG_FULLSCREEN; + CVPixelBufferRelease(frameBuffers[0]); + frameBuffers[0] = NULL; + CVPixelBufferRelease(frameBuffers[1]); + frameBuffers[1] = NULL; + CVOpenGLTextureRelease(texture); + texture = NULL; - //config OpenGL View - [mpGLView config]; - [mpGLView reshape]; - } - else - { + vo_cocoa_create_window(global_vo, d_width, d_height, flags); + prepare_opengl(); + vo_cocoa_swap_interval(1); + + error = CVOpenGLTextureCacheCreate(NULL, 0, vo_cocoa_cgl_context(), vo_cocoa_cgl_pixel_format(), 0, &textureCache); + if(error != kCVReturnSuccess) + mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create OpenGL texture Cache(%d)\n", error); + + error = CVPixelBufferCreateWithBytes(NULL, image_width, image_height, pixelFormat, + image_datas[0], image_width*image_bytes, NULL, NULL, NULL, &frameBuffers[0]); + if(error != kCVReturnSuccess) + mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create Pixel Buffer(%d)\n", error); + + if (vo_doublebuffering) { + error = CVPixelBufferCreateWithBytes(NULL, image_width, image_height, pixelFormat, + image_datas[1], image_width*image_bytes, NULL, NULL, NULL, &frameBuffers[1]); + if(error != kCVReturnSuccess) + mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create Pixel Double Buffer(%d)\n", error); + } + + error = CVOpenGLTextureCacheCreateTextureFromImage(NULL, textureCache, frameBuffers[image_page], 0, &texture); + if(error != kCVReturnSuccess) + mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create OpenGL texture(%d)\n", error); + } else { int shm_fd; mp_msg(MSGT_VO, MSGL_INFO, "[vo_corevideo] writing output to a shared buffer " "named \"%s\"\n",buffer_name); // create shared memory shm_fd = shm_open(buffer_name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); - if (shm_fd == -1) - { + if (shm_fd == -1) { mp_msg(MSGT_VO, MSGL_FATAL, "[vo_corevideo] failed to open shared memory. Error: %s\n", strerror(errno)); return 1; } - - if (ftruncate(shm_fd, image_width*image_height*image_bytes) == -1) - { + if (ftruncate(shm_fd, image_width*image_height*image_bytes) == -1) { mp_msg(MSGT_VO, MSGL_FATAL, "[vo_corevideo] failed to size shared memory, possibly already in use. Error: %s\n", strerror(errno)); close(shm_fd); @@ -234,8 +242,7 @@ static int config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_ PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); close(shm_fd); - if (image_data == MAP_FAILED) - { + if (image_data == MAP_FAILED) { mp_msg(MSGT_VO, MSGL_FATAL, "[vo_corevideo] failed to map shared memory. Error: %s\n", strerror(errno)); shm_unlink(buffer_name); @@ -243,13 +250,12 @@ static int config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_ } //connect to mplayerosx - mplayerosxProxy=[NSConnection rootProxyForConnectionWithRegisteredName:[NSString stringWithCString:buffer_name] host:nil]; + mplayerosxProxy=[NSConnection rootProxyForConnectionWithRegisteredName:[NSString stringWithUTF8String:buffer_name] host:nil]; if ([mplayerosxProxy conformsToProtocol:@protocol(MPlayerOSXVOProto)]) { [mplayerosxProxy setProtocolForProxy:@protocol(MPlayerOSXVOProto)]; mplayerosxProto = (id )mplayerosxProxy; [mplayerosxProto startWithWidth: image_width withHeight: image_height withBytes: image_bytes withAspect:d_width*100/d_height]; - } - else { + } else { [mplayerosxProxy release]; mplayerosxProxy = nil; mplayerosxProto = nil; @@ -260,8 +266,11 @@ static int config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_ static void check_events(void) { - if (mpGLView) - [mpGLView check_events]; + if (!shared_buffer) { + int e = vo_cocoa_check_events(global_vo); + if (e & VO_EVENT_RESIZE) + resize(global_vo->dwidth, global_vo->dheight); + } } static void draw_osd(void) @@ -269,6 +278,34 @@ static void draw_osd(void) vo_draw_text(image_width, image_height, draw_alpha); } +static void prepare_texture(void) +{ + CVReturn error; + CVOpenGLTextureRelease(texture); + error = CVOpenGLTextureCacheCreateTextureFromImage(NULL, textureCache, frameBuffers[image_page], 0, &texture); + if(error != kCVReturnSuccess) + mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create OpenGL texture(%d)\n", error); + + CVOpenGLTextureGetCleanTexCoords(texture, lowerLeft, lowerRight, upperRight, upperLeft); +} + +static void do_render(void) +{ + glClear(GL_COLOR_BUFFER_BIT); + + glEnable(CVOpenGLTextureGetTarget(texture)); + glBindTexture(CVOpenGLTextureGetTarget(texture), CVOpenGLTextureGetName(texture)); + + glColor3f(1,1,1); + glBegin(GL_QUADS); + glTexCoord2f(upperLeft[0], upperLeft[1]); glVertex2i(textureFrame.origin.x-(vo_panscan_x >> 1), textureFrame.origin.y-(vo_panscan_y >> 1)); + glTexCoord2f(lowerLeft[0], lowerLeft[1]); glVertex2i(textureFrame.origin.x-(vo_panscan_x >> 1), NSMaxY(textureFrame)+(vo_panscan_y >> 1)); + glTexCoord2f(lowerRight[0], lowerRight[1]); glVertex2i(NSMaxX(textureFrame)+(vo_panscan_x >> 1), NSMaxY(textureFrame)+(vo_panscan_y >> 1)); + glTexCoord2f(upperRight[0], upperRight[1]); glVertex2i(NSMaxX(textureFrame)+(vo_panscan_x >> 1), textureFrame.origin.y-(vo_panscan_y >> 1)); + glEnd(); + glDisable(CVOpenGLTextureGetTarget(texture)); +} + static void flip_page(void) { if(shared_buffer) { @@ -276,12 +313,13 @@ static void flip_page(void) [mplayerosxProto render]; [pool release]; } else { - [mpGLView setCurrentTexture]; - [mpGLView render]; + prepare_texture(); + do_render(); if (vo_doublebuffering) { image_page = 1 - image_page; image_data = image_datas[image_page]; } + vo_cocoa_swap_buffers(); } } @@ -331,20 +369,13 @@ static int query_format(uint32_t format) static void uninit(void) { - SetSystemUIMode( kUIModeNormal, 0); + SetSystemUIMode(kUIModeNormal, 0); CGDisplayShowCursor(kCGDirectMainDisplay); free_file_specific(); - if(mpGLView) - { - NSAutoreleasePool *finalPool; - mpGLView = nil; - [autoreleasepool release]; - finalPool = [[NSAutoreleasePool alloc] init]; - [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:nil inMode:NSDefaultRunLoopMode dequeue:YES]; - [finalPool release]; - } + if (!shared_buffer) + vo_cocoa_uninit(global_vo); free(buffer_name); buffer_name = NULL; @@ -359,7 +390,6 @@ static const opt_t subopts[] = { static int preinit(const char *arg) { - // set defaults screen_id = -1; shared_buffer = false; @@ -389,688 +419,45 @@ static int preinit(const char *arg) else shared_buffer = true; - if(!shared_buffer) - { - NSApplicationLoad(); - NSApp = [NSApplication sharedApplication]; - isLeopardOrLater = floor(NSAppKitVersionNumber) > 824; - - osx_foreground_hack(); - - if(!mpGLView) - { - mpGLView = [[MPlayerOpenGLView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) pixelFormat:[MPlayerOpenGLView defaultPixelFormat]]; - [mpGLView autorelease]; - } - // Install an event handler so the Quit menu entry works - // The proper way using NSApp setDelegate: and - // applicationShouldTerminate: does not work, - // probably NSApplication never installs its handler. - [[NSAppleEventManager sharedAppleEventManager] - setEventHandler:mpGLView - andSelector:@selector(handleQuitEvent:withReplyEvent:) - forEventClass:kCoreEventClass - andEventID:kAEQuitApplication]; - - [mpGLView display]; - [mpGLView preinit]; - } + if (!shared_buffer) + vo_cocoa_init(global_vo); return 0; } static int control(uint32_t request, void *data) { - switch (request) - { + switch (request) { case VOCTRL_DRAW_IMAGE: return draw_image(data); - case VOCTRL_PAUSE: return int_pause = 1; - case VOCTRL_RESUME: return int_pause = 0; case VOCTRL_QUERY_FORMAT: return query_format(*(uint32_t*)data); - case VOCTRL_ONTOP: vo_ontop = !vo_ontop; if(!shared_buffer){ [mpGLView ontop]; } else { [mplayerosxProto ontop]; } return VO_TRUE; - case VOCTRL_ROOTWIN: vo_rootwin = !vo_rootwin; [mpGLView rootwin]; return VO_TRUE; - case VOCTRL_FULLSCREEN: vo_fs = !vo_fs; if(!shared_buffer){ [mpGLView fullscreen: NO]; } else { [mplayerosxProto toggleFullscreen]; } return VO_TRUE; - case VOCTRL_GET_PANSCAN: return VO_TRUE; - case VOCTRL_SET_PANSCAN: [mpGLView panscan]; return VO_TRUE; - case VOCTRL_UPDATE_SCREENINFO: update_screen_info(); return VO_TRUE; + case VOCTRL_ONTOP: + if (!shared_buffer) { + vo_cocoa_ontop(global_vo); + } else { + vo_ontop = !vo_ontop; + [mplayerosxProto ontop]; + } + return VO_TRUE; + case VOCTRL_FULLSCREEN: + if (!shared_buffer) { + vo_cocoa_fullscreen(global_vo); + resize(global_vo->dwidth, global_vo->dheight); + } else { + [mplayerosxProto toggleFullscreen]; + } + return VO_TRUE; + case VOCTRL_GET_PANSCAN: + return VO_TRUE; + case VOCTRL_SET_PANSCAN: + panscan_calc_windowed(); + return VO_TRUE; + case VOCTRL_UPDATE_SCREENINFO: + if (!shared_buffer) { + vo_cocoa_update_xinerama_info(global_vo); + return VO_TRUE; + } else { + return VO_NOTIMPL; + } } return VO_NOTIMPL; } - -////////////////////////////////////////////////////////////////////////// -// NSOpenGLView Subclass -////////////////////////////////////////////////////////////////////////// -@implementation MPlayerOpenGLView -- (void) preinit -{ - NSOpenGLContext *glContext; - GLint swapInterval = 1; - CVReturn error; - - //init menu - [self initMenu]; - - //create window - window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100) - styleMask:NSTitledWindowMask|NSTexturedBackgroundWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask - backing:NSBackingStoreBuffered defer:NO]; - - [window autorelease]; - [window setDelegate:mpGLView]; - [window setContentView:mpGLView]; - [window setInitialFirstResponder:mpGLView]; - [window setAcceptsMouseMovedEvents:YES]; - [window setTitle:@"MPlayer - The Movie Player"]; - - isFullscreen = 0; - winSizeMult = 1; - - //create OpenGL Context - glContext = [[NSOpenGLContext alloc] initWithFormat:[NSOpenGLView defaultPixelFormat] shareContext:nil]; - - [self setOpenGLContext:glContext]; - [glContext setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; - [glContext setView:self]; - [glContext makeCurrentContext]; - [glContext release]; - - error = CVOpenGLTextureCacheCreate(NULL, 0, [glContext CGLContextObj], [[self pixelFormat] CGLPixelFormatObj], 0, &textureCache); - if(error != kCVReturnSuccess) - mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create OpenGL texture Cache(%d)\n", error); -} - -- (void) releaseVideoSpecific -{ - CVPixelBufferRelease(frameBuffers[0]); - frameBuffers[0] = NULL; - CVPixelBufferRelease(frameBuffers[1]); - frameBuffers[1] = NULL; - CVOpenGLTextureRelease(texture); - texture = NULL; -} - -- (void) dealloc -{ - [self releaseVideoSpecific]; - CVOpenGLTextureCacheRelease(textureCache); - textureCache = NULL; - [self setOpenGLContext:nil]; - [super dealloc]; -} - -- (void) config -{ - NSRect visibleFrame; - CVReturn error = kCVReturnSuccess; - - //config window - [window setContentSize:NSMakeSize(vo_dwidth, vo_dheight)]; - - // Use visibleFrame to position the window taking the menu bar and dock into account. - // Also flip vo_dy since the screen origin is in the bottom left on OSX. - update_screen_info(); - visibleFrame = [screen_handle visibleFrame]; - [window setFrameTopLeftPoint:NSMakePoint( - visibleFrame.origin.x + vo_dx, - visibleFrame.origin.y + visibleFrame.size.height - vo_dy)]; - - [self releaseVideoSpecific]; - error = CVPixelBufferCreateWithBytes(NULL, image_width, image_height, pixelFormat, image_datas[0], image_width*image_bytes, NULL, NULL, NULL, &frameBuffers[0]); - if(error != kCVReturnSuccess) - mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create Pixel Buffer(%d)\n", error); - if (vo_doublebuffering) { - error = CVPixelBufferCreateWithBytes(NULL, image_width, image_height, pixelFormat, image_datas[1], image_width*image_bytes, NULL, NULL, NULL, &frameBuffers[1]); - if(error != kCVReturnSuccess) - mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create Pixel Double Buffer(%d)\n", error); - } - - error = CVOpenGLTextureCacheCreateTextureFromImage(NULL, textureCache, frameBuffers[image_page], 0, &texture); - if(error != kCVReturnSuccess) - mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create OpenGL texture(%d)\n", error); - - //show window - [window makeKeyAndOrderFront:mpGLView]; - - if(vo_rootwin) - [mpGLView rootwin]; - - if(vo_fs) - [mpGLView fullscreen: NO]; - - if(vo_ontop) - [mpGLView ontop]; -} - -/* - Init Menu -*/ -- (void)initMenu -{ - NSMenu *menu, *aspectMenu; - NSMenuItem *menuItem; - - menu = [[NSMenu new] autorelease]; - menuItem = [[NSMenuItem new] autorelease]; - [menu addItem: menuItem]; - [NSApp setMainMenu: menu]; - -//Create Movie Menu - menu = [[NSMenu alloc] initWithTitle:@"Movie"]; - menuItem = [[NSMenuItem alloc] initWithTitle:@"Half Size" action:@selector(menuAction:) keyEquivalent:@"0"]; [menu addItem:menuItem]; - kHalfScreenCmd = menuItem; - menuItem = [[NSMenuItem alloc] initWithTitle:@"Normal Size" action:@selector(menuAction:) keyEquivalent:@"1"]; [menu addItem:menuItem]; - kNormalScreenCmd = menuItem; - menuItem = [[NSMenuItem alloc] initWithTitle:@"Double Size" action:@selector(menuAction:) keyEquivalent:@"2"]; [menu addItem:menuItem]; - kDoubleScreenCmd = menuItem; - menuItem = [[NSMenuItem alloc] initWithTitle:@"Full Size" action:@selector(menuAction:) keyEquivalent:@"f"]; [menu addItem:menuItem]; - kFullScreenCmd = menuItem; - menuItem = [NSMenuItem separatorItem]; [menu addItem:menuItem]; - - aspectMenu = [[NSMenu alloc] initWithTitle:@"Aspect Ratio"]; - menuItem = [[NSMenuItem alloc] initWithTitle:@"Keep" action:@selector(menuAction:) keyEquivalent:@""]; [aspectMenu addItem:menuItem]; - if(vo_keepaspect) [menuItem setState:NSOnState]; - kKeepAspectCmd = menuItem; - menuItem = [[NSMenuItem alloc] initWithTitle:@"Pan-Scan" action:@selector(menuAction:) keyEquivalent:@""]; [aspectMenu addItem:menuItem]; - if(vo_panscan) [menuItem setState:NSOnState]; - kPanScanCmd = menuItem; - menuItem = [NSMenuItem separatorItem]; [aspectMenu addItem:menuItem]; - menuItem = [[NSMenuItem alloc] initWithTitle:@"Original" action:@selector(menuAction:) keyEquivalent:@""]; [aspectMenu addItem:menuItem]; - kAspectOrgCmd = menuItem; - menuItem = [[NSMenuItem alloc] initWithTitle:@"4:3" action:@selector(menuAction:) keyEquivalent:@""]; [aspectMenu addItem:menuItem]; - kAspectFullCmd = menuItem; - menuItem = [[NSMenuItem alloc] initWithTitle:@"16:9" action:@selector(menuAction:) keyEquivalent:@""]; [aspectMenu addItem:menuItem]; - kAspectWideCmd = menuItem; - menuItem = [[NSMenuItem alloc] initWithTitle:@"Aspect Ratio" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:aspectMenu]; - [menu addItem:menuItem]; - [aspectMenu release]; - - //Add to menubar - menuItem = [[NSMenuItem alloc] initWithTitle:@"Movie" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:menu]; - [[NSApp mainMenu] addItem:menuItem]; - -//Create Window Menu - menu = [[NSMenu alloc] initWithTitle:@"Window"]; - - menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; [menu addItem:menuItem]; - menuItem = [[NSMenuItem alloc] initWithTitle:@"Zoom" action:@selector(performZoom:) keyEquivalent:@""]; [menu addItem:menuItem]; - - //Add to menubar - menuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:menu]; - [[NSApp mainMenu] addItem:menuItem]; - [NSApp setWindowsMenu:menu]; - - [menu release]; - [menuItem release]; -} - -- (void)set_winSizeMult:(float)mult -{ - NSRect frame; - int d_width, d_height; - aspect(&d_width, &d_height, A_NOZOOM); - - if (isFullscreen) { - vo_fs = !vo_fs; - [self fullscreen:NO]; - } - - winSizeMult = mult; - frame.size.width = d_width * mult; - frame.size.height = d_height * mult; - [window setContentSize: frame.size]; - [self reshape]; -} - -/* - Menu Action - */ -- (void)menuAction:(id)sender -{ - if(sender == kHalfScreenCmd) - [self set_winSizeMult: 0.5]; - if(sender == kNormalScreenCmd) - [self set_winSizeMult: 1]; - if(sender == kDoubleScreenCmd) - [self set_winSizeMult: 2]; - if(sender == kFullScreenCmd) - { - vo_fs = !vo_fs; - [self fullscreen:NO]; - } - - if(sender == kKeepAspectCmd) - { - vo_keepaspect = !vo_keepaspect; - if(vo_keepaspect) - [kKeepAspectCmd setState:NSOnState]; - else - [kKeepAspectCmd setState:NSOffState]; - - [self reshape]; - } - - if(sender == kPanScanCmd) - { - vo_panscan = !vo_panscan; - if(vo_panscan) - [kPanScanCmd setState:NSOnState]; - else - [kPanScanCmd setState:NSOffState]; - - [self panscan]; - } - - if(sender == kAspectOrgCmd) - change_movie_aspect(-1); - - if(sender == kAspectFullCmd) - change_movie_aspect(4.0f/3.0f); - - if(sender == kAspectWideCmd) - change_movie_aspect(16.0f/9.0f); -} - -/* - Setup OpenGL -*/ -- (void)prepareOpenGL -{ - glEnable(GL_BLEND); - glDisable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); - glDisable(GL_CULL_FACE); - [self reshape]; -} - -/* - reshape OpenGL viewport -*/ -- (void)reshape -{ - int d_width, d_height; - - NSRect frame = [self frame]; - vo_dwidth = frame.size.width; - vo_dheight = frame.size.height; - - glViewport(0, 0, frame.size.width, frame.size.height); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, frame.size.width, frame.size.height, 0, -1.0, 1.0); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - //set texture frame - if(vo_keepaspect) - { - aspect(&d_width, &d_height, A_WINZOOM); - - textureFrame = NSMakeRect((vo_dwidth - d_width) / 2, (vo_dheight - d_height) / 2, d_width, d_height); - } - else - { - textureFrame = frame; - } -} - -/* - Render frame -*/ -- (void) render -{ - glClear(GL_COLOR_BUFFER_BIT); - - glEnable(CVOpenGLTextureGetTarget(texture)); - glBindTexture(CVOpenGLTextureGetTarget(texture), CVOpenGLTextureGetName(texture)); - - glColor3f(1,1,1); - glBegin(GL_QUADS); - glTexCoord2f(upperLeft[0], upperLeft[1]); glVertex2i( textureFrame.origin.x-(vo_panscan_x >> 1), textureFrame.origin.y-(vo_panscan_y >> 1)); - glTexCoord2f(lowerLeft[0], lowerLeft[1]); glVertex2i(textureFrame.origin.x-(vo_panscan_x >> 1), NSMaxY(textureFrame)+(vo_panscan_y >> 1)); - glTexCoord2f(lowerRight[0], lowerRight[1]); glVertex2i(NSMaxX(textureFrame)+(vo_panscan_x >> 1), NSMaxY(textureFrame)+(vo_panscan_y >> 1)); - glTexCoord2f(upperRight[0], upperRight[1]); glVertex2i(NSMaxX(textureFrame)+(vo_panscan_x >> 1), textureFrame.origin.y-(vo_panscan_y >> 1)); - glEnd(); - glDisable(CVOpenGLTextureGetTarget(texture)); - - //render resize box - if(!isFullscreen) - { - NSRect frame = [self frame]; - - glBegin(GL_LINES); - glColor4f(0.2, 0.2, 0.2, 0.5); - glVertex2i(frame.size.width-1, frame.size.height-1); glVertex2i(frame.size.width-1, frame.size.height-1); - glVertex2i(frame.size.width-1, frame.size.height-5); glVertex2i(frame.size.width-5, frame.size.height-1); - glVertex2i(frame.size.width-1, frame.size.height-9); glVertex2i(frame.size.width-9, frame.size.height-1); - - glColor4f(0.4, 0.4, 0.4, 0.5); - glVertex2i(frame.size.width-1, frame.size.height-2); glVertex2i(frame.size.width-2, frame.size.height-1); - glVertex2i(frame.size.width-1, frame.size.height-6); glVertex2i(frame.size.width-6, frame.size.height-1); - glVertex2i(frame.size.width-1, frame.size.height-10); glVertex2i(frame.size.width-10, frame.size.height-1); - - glColor4f(0.6, 0.6, 0.6, 0.5); - glVertex2i(frame.size.width-1, frame.size.height-3); glVertex2i(frame.size.width-3, frame.size.height-1); - glVertex2i(frame.size.width-1, frame.size.height-7); glVertex2i(frame.size.width-7, frame.size.height-1); - glVertex2i(frame.size.width-1, frame.size.height-11); glVertex2i(frame.size.width-11, frame.size.height-1); - glEnd(); - } - - glFlush(); -} - -/* - Create OpenGL texture from current frame & set texco -*/ -- (void) setCurrentTexture -{ - CVReturn error = kCVReturnSuccess; - - CVOpenGLTextureRelease(texture); - error = CVOpenGLTextureCacheCreateTextureFromImage(NULL, textureCache, frameBuffers[image_page], 0, &texture); - if(error != kCVReturnSuccess) - mp_msg(MSGT_VO, MSGL_ERR,"[vo_corevideo] Failed to create OpenGL texture(%d)\n", error); - - CVOpenGLTextureGetCleanTexCoords(texture, lowerLeft, lowerRight, upperRight, upperLeft); -} - -/* - redraw win rect -*/ -- (void) drawRect: (NSRect *) bounds -{ - [self render]; -} - -/* - Toggle Fullscreen -*/ -- (void) fullscreen: (BOOL) animate -{ - static NSRect old_frame; - static NSRect old_view_frame; - - panscan_calc(); - - //go fullscreen - if(vo_fs) - { - if(!isRootwin) - { - SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar); - CGDisplayHideCursor(kCGDirectMainDisplay); - mouseHide = YES; - } - - old_frame = [window frame]; //save main window size & position - update_screen_info(); - - [window setFrame:screen_frame display:YES animate:animate]; //zoom-in window with nice useless sfx - old_view_frame = [self bounds]; - - //fix origin for multi screen setup - screen_frame.origin.x = 0; - screen_frame.origin.y = 0; - [self setFrame:screen_frame]; - [self setNeedsDisplay:YES]; - [window setHasShadow:NO]; - isFullscreen = 1; - } - else - { - SetSystemUIMode( kUIModeNormal, 0); - - isFullscreen = 0; - CGDisplayShowCursor(kCGDirectMainDisplay); - mouseHide = NO; - - //revert window to previous setting - [self setFrame:old_view_frame]; - [self setNeedsDisplay:YES]; - [window setHasShadow:YES]; - [window setFrame:old_frame display:YES animate:animate];//zoom-out window with nice useless sfx - } -} - -/* - Toggle ontop -*/ -- (void) ontop -{ - if(vo_ontop) - { - [window setLevel:NSScreenSaverWindowLevel]; - isOntop = YES; - } - else - { - [window setLevel:NSNormalWindowLevel]; - isOntop = NO; - } -} - -/* - Toggle panscan -*/ -- (void) panscan -{ - panscan_calc(); -} - -/* - Toggle rootwin - */ -- (void) rootwin -{ - if(vo_rootwin) - { - [window setLevel:CGWindowLevelForKey(kCGDesktopWindowLevelKey)]; - [window orderBack:self]; - isRootwin = YES; - } - else - { - [window setLevel:NSNormalWindowLevel]; - isRootwin = NO; - } -} - -/* - Check event for new event -*/ -- (void) check_events -{ - NSEvent *event; - int curTime = TickCount()/60; - - //automatically hide mouse cursor (and future on-screen control?) - if(isFullscreen && !mouseHide && !isRootwin) - { - if(curTime - lastMouseHide >= 5 || lastMouseHide == 0) - { - CGDisplayHideCursor(kCGDirectMainDisplay); - mouseHide = TRUE; - lastMouseHide = curTime; - } - } - - //update activity every 30 seconds to prevent - //screensaver from starting up. - if(curTime - lastScreensaverUpdate >= 30 || lastScreensaverUpdate == 0) - { - UpdateSystemActivity(UsrActivity); - lastScreensaverUpdate = curTime; - } - - event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:nil inMode:NSEventTrackingRunLoopMode dequeue:YES]; - if (event == nil) - return; - [NSApp sendEvent:event]; - // Without SDL's bootstrap code (include SDL.h in mplayer.c), - // on Leopard, we have trouble to get the play window automatically focused - // when the app is actived. The Following code fix this problem. -#ifndef CONFIG_SDL - if (isLeopardOrLater && [event type] == NSAppKitDefined - && [event subtype] == NSApplicationActivatedEventType) { - [window makeMainWindow]; - [window makeKeyAndOrderFront:mpGLView]; - } -#endif -} - -/* - From NSView, respond to key equivalents. -*/ -- (BOOL)performKeyEquivalent:(NSEvent *)theEvent -{ - switch([theEvent keyCode]) - { - case 0x21: [window setAlphaValue: winAlpha-=0.05]; return YES; - case 0x1e: [window setAlphaValue: winAlpha+=0.05]; return YES; - } - return NO; -} - -/* - Process key event -*/ -- (void) keyDown: (NSEvent *) theEvent -{ - unsigned char charcode; - if (([theEvent modifierFlags] & NSRightAlternateKeyMask) == NSRightAlternateKeyMask) - charcode = *[[theEvent characters] UTF8String]; - else - charcode = [[theEvent charactersIgnoringModifiers] characterAtIndex:0]; - - int key = convert_key([theEvent keyCode], charcode); - - if (key > -1) { - if([theEvent modifierFlags] & NSShiftKeyMask) - key |= KEY_MODIFIER_SHIFT; - if([theEvent modifierFlags] & NSControlKeyMask) - key |= KEY_MODIFIER_CTRL; - if(([theEvent modifierFlags] & NSLeftAlternateKeyMask) == NSLeftAlternateKeyMask) - key |= KEY_MODIFIER_ALT; - if([theEvent modifierFlags] & NSCommandKeyMask) - key |= KEY_MODIFIER_META; - mplayer_put_key(key); - } -} - -/* - Process mouse button event -*/ -- (void) mouseMoved: (NSEvent *) theEvent -{ - if(isFullscreen && !isRootwin) - { - CGDisplayShowCursor(kCGDirectMainDisplay); - mouseHide = NO; - } - if (enable_mouse_movements && !isRootwin) { - NSPoint p =[self convertPoint:[theEvent locationInWindow] fromView:nil]; - if ([self mouse:p inRect:textureFrame]) { - vo_mouse_movement(global_vo, vo_fs ? p.x : p.x - textureFrame.origin.x, - vo_fs ? [self frame].size.height - p.y : NSMaxY(textureFrame) - p.y); - } - } -} - -- (void) mouseDown: (NSEvent *) theEvent -{ - [self mouseEvent: theEvent]; -} - -- (void) mouseUp: (NSEvent *) theEvent -{ - [self mouseEvent: theEvent]; -} - -- (void) rightMouseDown: (NSEvent *) theEvent -{ - [self mouseEvent: theEvent]; -} - -- (void) rightMouseUp: (NSEvent *) theEvent -{ - [self mouseEvent: theEvent]; -} - -- (void) otherMouseDown: (NSEvent *) theEvent -{ - [self mouseEvent: theEvent]; -} - -- (void) otherMouseUp: (NSEvent *) theEvent -{ - [self mouseEvent: theEvent]; -} - -- (void) scrollWheel: (NSEvent *) theEvent -{ - if([theEvent deltaY] > 0) - mplayer_put_key(MOUSE_BTN3); - else - mplayer_put_key(MOUSE_BTN4); -} - -- (void) mouseEvent: (NSEvent *) theEvent -{ - if ( [theEvent buttonNumber] >= 0 && [theEvent buttonNumber] <= 9 ) - { - int buttonNumber = [theEvent buttonNumber]; - // Fix to mplayer defined button order: left, middle, right - if (buttonNumber == 1) - buttonNumber = 2; - else if (buttonNumber == 2) - buttonNumber = 1; - switch([theEvent type]) - { - case NSLeftMouseDown: - case NSRightMouseDown: - case NSOtherMouseDown: - mplayer_put_key((MOUSE_BTN0 + buttonNumber) | MP_KEY_DOWN); - break; - case NSLeftMouseUp: - case NSRightMouseUp: - case NSOtherMouseUp: - mplayer_put_key(MOUSE_BTN0 + buttonNumber); - break; - } - } -} - -/* - NSResponder -*/ -- (BOOL) acceptsFirstResponder -{ - return YES; -} - -- (BOOL) becomeFirstResponder -{ - return YES; -} - -- (BOOL) resignFirstResponder -{ - return YES; -} - -- (BOOL)windowShouldClose:(id)sender -{ - mplayer_put_key(KEY_CLOSE_WIN); - // We have to wait for MPlayer to handle this, - // otherwise we are in trouble if the - // KEY_CLOSE_WIN handler is disabled - return NO; -} - -- (void)handleQuitEvent:(NSAppleEventDescriptor*)e withReplyEvent:(NSAppleEventDescriptor*)r -{ - mplayer_put_key(KEY_CLOSE_WIN); -} -@end -- cgit v1.2.3