diff options
author | Andre Pang <athp@users.sourceforge.net> | 2004-10-22 06:29:45 +0000 |
---|---|---|
committer | Andre Pang <athp@users.sourceforge.net> | 2004-10-22 06:29:45 +0000 |
commit | c82596c62aa4b61795106ec56e29925829c54a4c (patch) | |
tree | 8e36a8e581c0c744bb978b9c31bc6dd64fccd63d /src/video_out/macosx | |
parent | 9c6378122e9bffab0f2d1b4daf71f5ba2889e15e (diff) | |
download | xine-lib-c82596c62aa4b61795106ec56e29925829c54a4c.tar.gz xine-lib-c82596c62aa4b61795106ec56e29925829c54a4c.tar.bz2 |
Split Mac OS X video_window.[mh] files into XineOpenGLView.h and XineOpenGLView.m: we still keep a video_window.h file for backward compatibility
CVS patchset: 7064
CVS date: 2004/10/22 06:29:45
Diffstat (limited to 'src/video_out/macosx')
-rw-r--r-- | src/video_out/macosx/Makefile.am | 12 | ||||
-rw-r--r-- | src/video_out/macosx/XineOpenGLView.h | 99 | ||||
-rw-r--r-- | src/video_out/macosx/XineOpenGLView.m (renamed from src/video_out/macosx/video_window.m) | 611 | ||||
-rw-r--r-- | src/video_out/macosx/XineVideoWindow.h | 58 | ||||
-rw-r--r-- | src/video_out/macosx/XineVideoWindow.m | 186 | ||||
-rw-r--r-- | src/video_out/macosx/video_window.h | 105 |
6 files changed, 614 insertions, 457 deletions
diff --git a/src/video_out/macosx/Makefile.am b/src/video_out/macosx/Makefile.am index 2a3bfa308..028c52eeb 100644 --- a/src/video_out/macosx/Makefile.am +++ b/src/video_out/macosx/Makefile.am @@ -1,12 +1,17 @@ include $(top_srcdir)/misc/Makefile.common -EXTRA_DIST = video_window.m video_window.h +EXTRA_DIST = \ + video_window.h \ + XineOpenGLView.m \ + XineOpenGLView.h \ + XineVideoWindow.m \ + XineVideoWindow.h if HAVE_MACOSX_VIDEO lib_LTLIBRARIES = libxine_macosx_video.la -libxine_macosx_video_la_SOURCES = video_window.m +libxine_macosx_video_la_SOURCES = XineOpenGLView.m XineVideoWindow.m # The "-Wl,-framework -Wl,..." is needed for libtool versions before # 1.5.x (1.257): the default version that ships with Mac OS X is 1.5 (1.1220) libxine_macosx_video_la_LDFLAGS = -version-info \ @@ -15,6 +20,7 @@ libxine_macosx_video_la_LDFLAGS = -version-info \ -Wl,-framework -Wl,OpenGL -framework OpenGL libxine_macosx_video_la_OBJCFLAGS = $(OBJCFLAGS) -include_HEADERS = video_window.h +include_HEADERS = video_window.h XineOpenGLView.h XineVideoWindow.h endif + diff --git a/src/video_out/macosx/XineOpenGLView.h b/src/video_out/macosx/XineOpenGLView.h new file mode 100644 index 000000000..9e53a6c69 --- /dev/null +++ b/src/video_out/macosx/XineOpenGLView.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2004 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + */ + +#ifndef __HAVE_XINE_OPENGL_VIEW_H__ +#define __HAVE_XINE_OPENGL_VIEW_H__ + +#import <Cocoa/Cocoa.h> + +#import "XineVideoWindow.h" + +@protocol XineOpenGLViewDelegate; + +extern NSString *XineViewDidResizeNotification; + +@interface XineOpenGLView : NSOpenGLView +{ + IBOutlet id <NSObject, XineOpenGLViewDelegate> delegate; + int video_width, video_height; + char *texture_buffer; + unsigned long i_texture; + BOOL initDone; + BOOL isFullScreen; + XineVideoWindowFullScreenMode fullscreen_mode; + NSOpenGLContext *fullScreenContext; + NSOpenGLContext *currentContext; + NSLock *mutex; + BOOL keepsVideoAspectRatio; + BOOL resizeViewOnVideoSizeChange; + NSCursor *currentCursor; + id <NSObject, XineOpenGLViewDelegate> _xineController; +} + +- (void) displayTexture; +- (void) drawQuad; +- (void) drawRect: (NSRect) rect; +- (void) goFullScreen: (XineVideoWindowFullScreenMode) mode; +- (void) exitFullScreen; +- (BOOL) isFullScreen; +- (void) reshape; +- (void) initTextures; +- (void) reloadTexture; +- (char *) getTextureBuffer; +- (void) setVideoSize:(NSSize)size; +- (void) setViewSizeInMainThread:(NSSize)size; +// TODO: replace set...Size below with setSize:(double)videoSizeMultiplier +- (void) setNormalSize; +- (void) setHalfSize; +- (void) setDoubleSize; +- (NSSize) videoSize; +- (void) setKeepsVideoAspectRatio:(BOOL)flag; +- (BOOL) keepsVideoAspectRatio; +- (void) setResizeViewOnVideoSizeChange:(BOOL)flag; +- (BOOL) resizeViewOnVideoSizeChange; +- (void) setCurrentCursor:(NSCursor *)cursor; +- (NSCursor *) currentCursor; +- (void) resetCursorRectsInMainThread; +- (void) setXineController:(id)controller; +- (id) xineController; + +// Delegate Methods +- (id) delegate; +- (void) setDelegate:(id)aDelegate; + +@end + +/* XineOpenGLView delegate methods */ + +@interface NSObject (XineOpenGLViewDelegate) + +- (NSSize) xineViewWillResize:(NSSize)oldSize toSize:(NSSize)proposedSize; +- (void) xineViewDidResize:(NSNotification *)aNotification; +- (void) mouseDown:(NSEvent *)theEvent inXineView:(XineOpenGLView *)theView; +- (void) mouseMoved:(NSEvent *)theEvent inXineView:(XineOpenGLView *)theView; +- (void) otherMouseDown:(NSEvent *)theEvent + inXineView:(XineOpenGLView *)theView; +- (void) rightMouseDown:(NSEvent *)theEvent + inXineView:(XineOpenGLView *)theView; + +@end + +#endif /* __HAVE_XINE_OPENGL_VIEW_H__ */ diff --git a/src/video_out/macosx/video_window.m b/src/video_out/macosx/XineOpenGLView.m index 4d9f84ebe..d8155dd55 100644 --- a/src/video_out/macosx/video_window.m +++ b/src/video_out/macosx/XineOpenGLView.m @@ -17,10 +17,11 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * Written by Daniel Mack <xine@zonque.org> - * - * Most parts of this code were taken from VLC, http://www.videolan.org - * Thanks for the good research! + */ + + +/* +#define LOG */ #import <Cocoa/Cocoa.h> @@ -28,16 +29,13 @@ #import <OpenGL/gl.h> #import <OpenGL/glext.h> -#import "video_window.h" +#import "XineOpenGLView.h" + NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; -#define DEFAULT_VIDEO_WINDOW_SIZE (NSMakeSize(320, 200)) -/* -#define LOG -*/ -#undef LOG_MOUSE +/* XineOpenGLView delegate methods */ @protocol XineOpenGLViewDelegate @@ -50,128 +48,6 @@ NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; @end -@implementation XineVideoWindow - -- (void) setContentSize: (NSSize) size { -#ifdef LOG - NSLog(@"setContent called with new size w:%d h:%d", size.width, size.height); -#endif - [xineView setViewSizeInMainThread:size]; - - [super setContentSize: size]; -} - -- (id) init -{ - return [self initWithContentSize:DEFAULT_VIDEO_WINDOW_SIZE]; -} - -- (id) initWithContentSize:(NSSize)size -{ - NSScreen *screen = [NSScreen mainScreen]; - NSSize screen_size = [screen frame].size; - - /* make a centered window */ - NSRect frame; - frame.size = size; - frame.origin.x = (screen_size.width - frame.size.width) / 2; - frame.origin.y = (screen_size.height - frame.size.height) / 2; - - unsigned int style_mask = NSTitledWindowMask | NSMiniaturizableWindowMask | - NSClosableWindowMask | NSResizableWindowMask; - - return ([self initWithContentRect:frame styleMask:style_mask - backing:NSBackingStoreBuffered defer:NO - screen:screen]); -} - -- (id) initWithContentRect: (NSRect)rect - styleMask:(unsigned int)styleMask - backing:(NSBackingStoreType)bufferingType - defer:(BOOL)flag - screen:(NSScreen *)aScreen { - self = [super initWithContentRect: rect - styleMask: styleMask - backing: bufferingType - defer: flag - screen: aScreen]; - -#ifdef LOG - NSLog(@"initWithContentRect called with rect x:%d y:%d w:%d h:%d", - rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); -#endif - - xineView = [[XineOpenGLView alloc] initWithFrame:rect]; - [xineView setResizeViewOnVideoSizeChange:YES]; - - /* receive notifications about window resizing from the xine view */ - NSNotificationCenter *noticeBoard = [NSNotificationCenter defaultCenter]; - [noticeBoard addObserver:self - selector:@selector(xineViewDidResize:) - name:XineViewDidResizeNotification - object:xineView]; - - [self setContentView: xineView]; - [self setTitle: @"xine video output"]; - - return self; -} - -- (void) dealloc -{ - [xineView release]; - xineView = nil; - - [super dealloc]; -} - - -- (XineOpenGLView *) xineView { - return xineView; -} - -- (NSRect)windowWillUseStandardFrame:(NSWindow *)sender - defaultFrame:(NSRect)defaultFrame -{ - NSSize screen_size, video_size; - NSRect standard_frame; - - if ([xineView isFullScreen]) - return defaultFrame; - - screen_size = defaultFrame.size; - video_size = [xineView videoSize]; - - if (screen_size.width / screen_size.height > - video_size.width / video_size.height) { - standard_frame.size.width = video_size.width * - (screen_size.height / video_size.height); - standard_frame.size.height = screen_size.height; - } else { - standard_frame.size.width = screen_size.width; - standard_frame.size.height = video_size.height * - (screen_size.width / video_size.width); - } - - standard_frame.origin.x = - (screen_size.width - standard_frame.size.width) / 2; - standard_frame.origin.y = - (screen_size.height - standard_frame.size.height) / 2; - - return standard_frame; -} - -/* Notifications */ - -- (void) xineViewDidResize:(NSNotification *)note { - NSRect frame = [self frame]; - frame.size = [[self contentView] frame].size; - - [self setFrame:[self frameRectForContentRect:frame] display:YES]; -} - -@end /* XineVideoWindow */ - @implementation XineOpenGLView @@ -195,7 +71,8 @@ NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; return resizeViewOnVideoSizeChange; } -- (BOOL)mouseDownCanMoveWindow { +- (BOOL)mouseDownCanMoveWindow +{ return YES; } @@ -203,17 +80,19 @@ NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; { NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil]; - + if (!NSMouseInRect(point, [self bounds], [self isFlipped])) return; - - if ([delegate respondsToSelector:selector]) { + + if ([delegate respondsToSelector:selector]) + { [delegate performSelector:selector withObject:theEvent withObject:self]; return; } - - if ([_xineController respondsToSelector:selector]) { + + if ([_xineController respondsToSelector:selector]) + { [_xineController performSelector:selector withObject:theEvent withObject:self]; @@ -225,7 +104,7 @@ NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; { [self passEventToDelegate:theEvent withSelector:@selector(mouseMoved:inXineView:)]; - + [super mouseMoved:theEvent]; } @@ -233,7 +112,7 @@ NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; { [self passEventToDelegate:theEvent withSelector:@selector(mouseDown:inXineView:)]; - + [super mouseDown:theEvent]; } @@ -241,7 +120,7 @@ NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; { [self passEventToDelegate:theEvent withSelector:@selector(rightMouseDown:inXineView:)]; - + [super rightMouseDown:theEvent]; } @@ -249,24 +128,26 @@ NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; { [self passEventToDelegate:theEvent withSelector:@selector(otherMouseDown:inXineView:)]; - + [super otherMouseDown:theEvent]; } -- (NSSize)videoSize { +- (NSSize)videoSize +{ return NSMakeSize(video_width, video_height); } - (void) displayTexture { - if ([self lockFocusIfCanDraw]) { + if ([self lockFocusIfCanDraw]) + { [self drawRect: [self bounds]]; [self reloadTexture]; [self unlockFocus]; } } -- (id) initWithFrame: (NSRect) frame { - +- (id) initWithFrame: (NSRect) frame +{ NSOpenGLPixelFormatAttribute attribs[] = { NSOpenGLPFAAccelerated, NSOpenGLPFANoRecovery, @@ -277,23 +158,24 @@ NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; NSOpenGLPFAWindow, 0 }; - + NSOpenGLPixelFormat * fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs]; - - if (!fmt) { - printf ("Cannot create NSOpenGLPixelFormat\n"); + + if (!fmt) + { + NSLog (@"Cannot create NSOpenGLPixelFormat\n"); return nil; } - + self = [super initWithFrame:frame pixelFormat:fmt]; - + currentContext = [self openGLContext]; [currentContext makeCurrentContext]; [mutex lock]; [currentContext update]; [mutex unlock]; - + i_texture = 0; initDone = NO; isFullScreen = NO; @@ -303,16 +185,16 @@ NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; mutex = [[NSLock alloc] init]; currentCursor = [NSCursor arrowCursor]; _xineController = nil; - + [self initTextures]; - + /* Black background */ glClearColor (0.0, 0.0, 0.0, 0.0); - + #ifdef LOG NSLog(@"XineOpenGLView: initWithFrame called"); #endif - + return self; } @@ -321,44 +203,51 @@ NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; #ifdef LOG NSLog(@"XineOpenGLView: initWithCoder called"); #endif - + self = [super initWithCoder:coder]; - + self = [self initWithFrame:[self frame]]; - - if ([coder allowsKeyedCoding]) { + + if ([coder allowsKeyedCoding]) + { keepsVideoAspectRatio = [coder decodeBoolForKey:@"keepsVideoAspectRatio"]; resizeViewOnVideoSizeChange = [coder decodeBoolForKey: @"resizeViewOnVideoSizeChange"]; - } else { + } + else + { /* Must decode values in the same order as encodeWithCoder: */ [coder decodeValueOfObjCType:@encode(BOOL) at:&keepsVideoAspectRatio]; [coder decodeValueOfObjCType:@encode(BOOL) at:&resizeViewOnVideoSizeChange]; } - + return self; } - (void) encodeWithCoder:(NSCoder *)coder { [super encodeWithCoder:coder]; - - if ([coder allowsKeyedCoding]) { + + if ([coder allowsKeyedCoding]) + { [coder encodeBool:keepsVideoAspectRatio forKey:@"keepsVideoAspectRatio"]; [coder encodeBool:resizeViewOnVideoSizeChange forKey:@"resizeViewOnVideoSizeChange"]; - } else { + } + else + { [coder encodeValueOfObjCType:@encode(BOOL) at:&keepsVideoAspectRatio]; [coder encodeValueOfObjCType:@encode(BOOL) at:&resizeViewOnVideoSizeChange]; } - + } - (void) dealloc { if (texture_buffer) free (texture_buffer); - - if (fullScreenContext) { + + if (fullScreenContext) + { [NSOpenGLContext clearCurrentContext]; [mutex lock]; [fullScreenContext clearDrawable]; @@ -367,8 +256,9 @@ NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; if (currentContext == fullScreenContext) currentContext = nil; fullScreenContext = nil; } - - if (currentContext) { + + if (currentContext) + { [NSOpenGLContext clearCurrentContext]; [mutex lock]; [currentContext clearDrawable]; @@ -376,9 +266,9 @@ NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; [mutex unlock]; currentContext = nil; } - + [mutex dealloc]; - + // Enabling the [super dealloc] below (which should be correct behaviour) // crashes -- not sure why ... // @@ -387,23 +277,26 @@ NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; // Maybe dealloc in main thread? } -- (void) reshape { +- (void) reshape +{ [mutex lock]; - - if (!initDone) { + + if (!initDone) + { [mutex unlock]; return; } - + [currentContext makeCurrentContext]; - + NSRect bounds = [self bounds]; glViewport (0, 0, bounds.size.width, bounds.size.height); - + [mutex unlock]; } -- (void) setNormalSize { +- (void) setNormalSize +{ NSSize size; if (isFullScreen) @@ -411,11 +304,12 @@ NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; size.width = video_width; size.height = video_height; - + [self setViewSizeInMainThread:size]; } -- (void) setHalfSize { +- (void) setHalfSize +{ NSSize size; if (isFullScreen) @@ -423,11 +317,12 @@ NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; size.width = video_width / 2; size.height = video_height / 2; - + [self setViewSizeInMainThread:size]; } -- (void) setDoubleSize { +- (void) setDoubleSize +{ NSSize size; if (isFullScreen) @@ -435,140 +330,155 @@ NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; size.width = video_width * 2; size.height = video_height * 2; - + [self setViewSizeInMainThread:size]; } -- (void) initTextures { +- (void) initTextures +{ [mutex lock]; - + [currentContext makeCurrentContext]; - + /* Free previous texture if any */ if (i_texture) glDeleteTextures (1, &i_texture); - + if (texture_buffer) + { texture_buffer = realloc (texture_buffer, sizeof (char) * video_width * video_height * 3); + } else + { texture_buffer = malloc (sizeof (char) * video_width * video_height * 3); - + } + /* Create textures */ glGenTextures (1, &i_texture); - + glEnable (GL_TEXTURE_RECTANGLE_EXT); glEnable (GL_UNPACK_CLIENT_STORAGE_APPLE); - + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); glPixelStorei (GL_UNPACK_ROW_LENGTH, video_width); - + glBindTexture (GL_TEXTURE_RECTANGLE_EXT, i_texture); glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - + /* Use VRAM texturing */ glTexParameteri (GL_TEXTURE_RECTANGLE_EXT, - GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_CACHED_APPLE); - + GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_CACHED_APPLE); + /* Tell the driver not to make a copy of the texture but to use - our buffer */ + our buffer */ glPixelStorei (GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); - + /* Linear interpolation */ glTexParameteri (GL_TEXTURE_RECTANGLE_EXT, - GL_TEXTURE_MIN_FILTER, GL_LINEAR); + GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_RECTANGLE_EXT, - GL_TEXTURE_MAG_FILTER, GL_LINEAR); - + GL_TEXTURE_MAG_FILTER, GL_LINEAR); + /* I have no idea what this exactly does, but it seems to be - necessary for scaling */ + necessary for scaling */ glTexParameteri (GL_TEXTURE_RECTANGLE_EXT, - GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_RECTANGLE_EXT, - GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - + GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D (GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, - video_width, video_height, 0, - GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, - texture_buffer); - + video_width, video_height, 0, + GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, + texture_buffer); + initDone = YES; [mutex unlock]; } -- (void) reloadTexture { - if (!initDone) { +- (void) reloadTexture +{ + if (!initDone) + { return; } [mutex lock]; - + [currentContext makeCurrentContext]; - + glBindTexture (GL_TEXTURE_RECTANGLE_EXT, i_texture); glPixelStorei (GL_UNPACK_ROW_LENGTH, video_width); - - /* glTexSubImage2D is faster than glTexImage2D - * http://developer.apple.com/samplecode/Sample_Code/Graphics_3D/TextureRange/MainOpenGLView.m.htm - */ + + // glTexSubImage2D is faster than glTexImage2D + // http://developer.apple.com/samplecode/Sample_Code/Graphics_3D/TextureRange/MainOpenGLView.m.htm glTexSubImage2D (GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, - video_width, video_height, - GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, - texture_buffer); - + video_width, video_height, + GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, + texture_buffer); + [mutex unlock]; } -- (void) calcFullScreenAspect { +- (void) calcFullScreenAspect +{ int fs_width, fs_height, x = 0, y = 0, w = 0, h = 0; - + fs_width = CGDisplayPixelsWide (kCGDirectMainDisplay); fs_height = CGDisplayPixelsHigh (kCGDirectMainDisplay); - + switch (fullscreen_mode) { - case XINE_FULLSCREEN_OVERSCAN: - if (((float) fs_width / (float) fs_height) > ((float) video_width / (float) video_height)) { - w = (float) video_width * ((float) fs_height / (float) video_height); - h = fs_height; - x = (fs_width - w) / 2; - y = 0; - } else { - w = fs_width; - h = (float) video_height * ((float) fs_width / (float) video_width); - x = 0; - y = (fs_height - h) / 2; - } - break; - - case XINE_FULLSCREEN_CROP: - if (((float) fs_width / (float) fs_height) > ((float) video_width / (float) video_height)) { - w = fs_width; - h = (float) video_height * ((float) fs_width / (float) video_width); - x = 0; - y = (fs_height - h) / 2; - } else { - w = (float) video_width * ((float) fs_height / (float) video_height); - h = fs_height; - x = (fs_width - w) / 2; - y = 0; - } - break; + case XINE_FULLSCREEN_OVERSCAN: + if (((float) fs_width / (float) fs_height) > ((float) video_width / (float) video_height)) + { + w = (float) video_width * ((float) fs_height / (float) video_height); + h = fs_height; + x = (fs_width - w) / 2; + y = 0; + } + else + { + w = fs_width; + h = (float) video_height * ((float) fs_width / (float) video_width); + x = 0; + y = (fs_height - h) / 2; + } + break; + + case XINE_FULLSCREEN_CROP: + if (((float) fs_width / (float) fs_height) > ((float) video_width / (float) video_height)) + { + w = fs_width; + h = (float) video_height * ((float) fs_width / (float) video_width); + x = 0; + y = (fs_height - h) / 2; + } + else + { + w = (float) video_width * ((float) fs_height / (float) video_height); + h = fs_height; + x = (fs_width - w) / 2; + y = 0; + } + break; } - - printf ("MacOSX fullscreen mode: %dx%d => %dx%d @ %d,%d\n", - video_width, video_height, w, h, x, y); - + + NSLog(@"MacOSX fullscreen mode: %dx%d => %dx%d @ %d,%d\n", + video_width, video_height, w, h, x, y); + [mutex lock]; glViewport (x, y, w, h); [mutex unlock]; } -- (void) goFullScreen: (XineVideoWindowFullScreenMode) mode { +- (void) goFullScreen: (XineVideoWindowFullScreenMode) mode +{ [mutex lock]; /* Create the new pixel format */ - NSOpenGLPixelFormatAttribute attribs[] = { + NSOpenGLPixelFormatAttribute attribs[] = + { NSOpenGLPFAAccelerated, NSOpenGLPFANoRecovery, NSOpenGLPFADoubleBuffer, @@ -582,42 +492,49 @@ NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; }; NSOpenGLPixelFormat * fmt = [[NSOpenGLPixelFormat alloc] - initWithAttributes: attribs]; - if (!fmt) { - printf ("Cannot create NSOpenGLPixelFormat\n"); + initWithAttributes: attribs]; + + if (!fmt) + { + NSLog (@"Cannot create NSOpenGLPixelFormat\n"); return; } - + /* Create the new OpenGL context */ fullScreenContext = [[NSOpenGLContext alloc] initWithFormat: fmt shareContext: nil]; - if (!fullScreenContext) { - printf ("Failed to create new NSOpenGLContext\n"); + + if (!fullScreenContext) + { + NSLog(@"Failed to create new NSOpenGLContext\n"); return; } currentContext = fullScreenContext; - + /* Capture display, switch to fullscreen */ - if (CGCaptureAllDisplays() != CGDisplayNoErr) { - printf ("CGCaptureAllDisplays() failed\n"); + if (CGCaptureAllDisplays() != CGDisplayNoErr) + { + NSLog(@"CGCaptureAllDisplays() failed\n"); return; } + [fullScreenContext setFullScreen]; [fullScreenContext makeCurrentContext]; [mutex unlock]; - + fullscreen_mode = mode; - + [self initTextures]; [self calcFullScreenAspect]; - + /* Redraw the last picture */ [self setNeedsDisplay: YES]; - + isFullScreen = YES; } -- (void) exitFullScreen { +- (void) exitFullScreen +{ initDone = NO; currentContext = [self openGLContext]; @@ -630,65 +547,67 @@ NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; [fullScreenContext release]; fullScreenContext = nil; CGReleaseAllDisplays(); - + [self reshape]; [self initTextures]; - + /* Redraw the last picture */ [self setNeedsDisplay: YES]; - + isFullScreen = NO; initDone = YES; } -- (void) drawQuad { +- (void) drawQuad +{ float f_x = 1.0, f_y = 1.0; glBegin (GL_QUADS); - /* Top left */ - glTexCoord2f (0.0, 0.0); - glVertex2f (-f_x, f_y); - /* Bottom left */ - glTexCoord2f (0.0, (float) video_height); - glVertex2f (-f_x, -f_y); - /* Bottom right */ - glTexCoord2f ((float) video_width, (float) video_height); - glVertex2f (f_x, -f_y); - /* Top right */ - glTexCoord2f ((float) video_width, 0.0); - glVertex2f (f_x, f_y); + /* Top left */ + glTexCoord2f (0.0, 0.0); + glVertex2f (-f_x, f_y); + /* Bottom left */ + glTexCoord2f (0.0, (float) video_height); + glVertex2f (-f_x, -f_y); + /* Bottom right */ + glTexCoord2f ((float) video_width, (float) video_height); + glVertex2f (f_x, -f_y); + /* Top right */ + glTexCoord2f ((float) video_width, 0.0); + glVertex2f (f_x, f_y); glEnd(); } -- (void) drawRect: (NSRect) rect { +- (void) drawRect: (NSRect) rect +{ [currentContext makeCurrentContext]; - if (!initDone) { + if (!initDone) return; - } - + [mutex lock]; - - /* Swap buffers only during the vertical retrace of the monitor. - http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL/chap5/chapter_5_section_44.html */ - + + // Swap buffers only during the vertical retrace of the monitor. + // http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL/chap5/chapter_5_section_44.html + long params[] = { 1 }; CGLSetParameter (CGLGetCurrentContext(), kCGLCPSwapInterval, params); - + /* Black background */ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - + /* Draw */ glBindTexture (GL_TEXTURE_RECTANGLE_EXT, i_texture); [self drawQuad]; - + /* Wait for the job to be done */ [currentContext flushBuffer]; - + [mutex unlock]; } -- (char *) getTextureBuffer { +- (char *) getTextureBuffer +{ return texture_buffer; } @@ -696,94 +615,97 @@ NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; { video_width = size.width; video_height = size.height; - + if (resizeViewOnVideoSizeChange) - [self setViewSizeInMainThread:size]; - + [self setViewSizeInMainThread:size]; + #ifdef LOG NSLog(@"setVideoSize called"); #endif - + [self initTextures]; } - (void) setViewSizeInMainThread:(NSSize)size { - /* create an autorelease pool, since we're running in a xine thread that - * may not have a pool of its own */ + // Create an autorelease pool, since we're running in a xine thread that + // may not have a pool of its own */ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + NSValue *sizeWrapper = [NSValue valueWithBytes:&size objCType:@encode(NSSize)]; [self performSelectorOnMainThread:@selector(setViewSize:) withObject:sizeWrapper - waitUntilDone:NO]; - + waitUntilDone:NO]; + #ifdef LOG NSLog(@"setViewSizeInMainThread called"); #endif - + [pool release]; } - (void) setViewSize:(NSValue *)sizeWrapper { NSSize proposedSize, newSize, currentSize; - + [sizeWrapper getValue:&proposedSize]; newSize = proposedSize; - + currentSize = [self frame].size; if (proposedSize.width == currentSize.width && - proposedSize.height == currentSize.height) { + proposedSize.height == currentSize.height) + { return; } - + /* If our controller handles xineViewWillResize:toSize:, send the - * message to him first. Note that the delegate still has a chance - * to override the controller's resize preference ... */ - if ([_xineController respondsToSelector:@selector(xineViewWillResize:toSize:)]) { + * message to him first. Note that the delegate still has a chance + * to override the controller's resize preference ... */ + if ([_xineController respondsToSelector:@selector(xineViewWillResize:toSize:)]) + { NSSize oldSize = [self frame].size; newSize = [_xineController xineViewWillResize:oldSize toSize:proposedSize]; } - + /* If our delegate handles xineViewWillResize:toSize:, send the - * message to him; otherwise, just resize ourselves */ - if ([delegate respondsToSelector:@selector(xineViewWillResize:toSize:)]) { + * message to him; otherwise, just resize ourselves */ + if ([delegate respondsToSelector:@selector(xineViewWillResize:toSize:)]) + { NSSize oldSize = [self frame].size; newSize = [delegate xineViewWillResize:oldSize toSize:proposedSize]; } - + [self setFrameSize:newSize]; [self setBoundsSize:newSize]; - + /* Post a notification that we resized and also notify our controller */ /* and delegate */ NSNotification *note = [NSNotification notificationWithName:XineViewDidResizeNotification object:self]; [[NSNotificationCenter defaultCenter] postNotification:note]; - - if ([_xineController respondsToSelector:@selector(xineViewDidResize:)]) { + + if ([_xineController respondsToSelector:@selector(xineViewDidResize:)]) [_xineController xineViewDidResize:note]; - } - - if ([delegate respondsToSelector:@selector(xineViewDidResize:)]) { + + if ([delegate respondsToSelector:@selector(xineViewDidResize:)]) [delegate xineViewDidResize:note]; - } - + if (isFullScreen) [self calcFullScreenAspect]; - + [self initTextures]; } -- (BOOL) isFullScreen { +- (BOOL) isFullScreen +{ return isFullScreen; } -- (id) delegate { +- (id) delegate +{ return delegate; } @@ -831,28 +753,3 @@ NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; } @end /* XineOpenGLView */ - - -@implementation NSWindow (AspectRatioAdditions) - -- (void) setKeepsAspectRatio: (BOOL) flag { - if (flag) { - NSSize size = [self frame].size; - [self setAspectRatio:size]; - } - else { - [self setResizeIncrements:NSMakeSize(1.0, 1.0)]; - } -} - -/* XXX: This is 100% untested ... */ -- (BOOL) keepsAspectRatio { - NSSize size = [self aspectRatio]; - if (size.width == 0 && size.height == 0) - return false; - else - return true; -} - -@end /* NSWindow (AspectRatioAdditions) */ - diff --git a/src/video_out/macosx/XineVideoWindow.h b/src/video_out/macosx/XineVideoWindow.h new file mode 100644 index 000000000..2ff617242 --- /dev/null +++ b/src/video_out/macosx/XineVideoWindow.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2004 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + */ + +#ifndef __HAVE_XINE_VIDEO_WINDOW_H__ +#define __HAVE_XINE_VIDEO_WINDOW_H__ + + +#import <Cocoa/Cocoa.h> + + +typedef enum +{ + XINE_FULLSCREEN_OVERSCAN, + XINE_FULLSCREEN_CROP +} XineVideoWindowFullScreenMode; + + +@interface XineVideoWindow : NSWindow +{ + int width, height; + id /* XineOpenGLView * */ xineView; +} + +- (id) initWithContentSize:(NSSize)size; +- (id /* XineOpenGLView * */) xineView; + +@end + + +/* NSWindow aspect ratio convenience methods */ + +@interface NSWindow (AspectRatioAdditions) + +- (void) setKeepsAspectRatio:(BOOL)flag; +- (BOOL) keepsAspectRatio; + +@end + + +#endif /* __HAVE_XINE_VIDEO_WINDOW_H__ */ diff --git a/src/video_out/macosx/XineVideoWindow.m b/src/video_out/macosx/XineVideoWindow.m new file mode 100644 index 000000000..b61a5b418 --- /dev/null +++ b/src/video_out/macosx/XineVideoWindow.m @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2004 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * Written by Daniel Mack <xine@zonque.org> + * + * Most parts of this code were taken from VLC, http://www.videolan.org + * Thanks for the good research! + */ + + +#import "XineOpenGLView.h" +#import "XineVideoWindow.h" + + +#define DEFAULT_VIDEO_WINDOW_SIZE (NSMakeSize(320, 200)) + +@implementation XineVideoWindow + +- (void) setContentSize: (NSSize) size +{ +#ifdef LOG + NSLog(@"setContent called with new size w:%d h:%d", size.width, size.height); +#endif + [xineView setViewSizeInMainThread:size]; + + [super setContentSize: size]; +} + +- (id) init +{ + return [self initWithContentSize:DEFAULT_VIDEO_WINDOW_SIZE]; +} + +- (id) initWithContentSize:(NSSize)size +{ + NSScreen *screen = [NSScreen mainScreen]; + NSSize screen_size = [screen frame].size; + + /* make a centered window */ + NSRect frame; + frame.size = size; + frame.origin.x = (screen_size.width - frame.size.width) / 2; + frame.origin.y = (screen_size.height - frame.size.height) / 2; + + unsigned int style_mask = NSTitledWindowMask | NSMiniaturizableWindowMask | + NSClosableWindowMask | NSResizableWindowMask; + + return ([self initWithContentRect:frame styleMask:style_mask + backing:NSBackingStoreBuffered defer:NO + screen:screen]); +} + +- (id) initWithContentRect: (NSRect)rect + styleMask:(unsigned int)styleMask + backing:(NSBackingStoreType)bufferingType + defer:(BOOL)flag + screen:(NSScreen *)aScreen +{ + self = [super initWithContentRect: rect + styleMask: styleMask + backing: bufferingType + defer: flag + screen: aScreen]; + +#ifdef LOG + NSLog(@"initWithContentRect called with rect x:%d y:%d w:%d h:%d", + rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); +#endif + + xineView = [[XineOpenGLView alloc] initWithFrame:rect]; + [xineView setResizeViewOnVideoSizeChange:YES]; + + /* receive notifications about window resizing from the xine view */ + NSNotificationCenter *noticeBoard = [NSNotificationCenter defaultCenter]; + [noticeBoard addObserver:self + selector:@selector(xineViewDidResize:) + name:XineViewDidResizeNotification + object:xineView]; + + [self setContentView: xineView]; + [self setTitle: @"xine video output"]; + + return self; +} + +- (void) dealloc +{ + [xineView release]; + xineView = nil; + + [super dealloc]; +} + + +- (XineOpenGLView *) xineView +{ + return xineView; +} + +- (NSRect)windowWillUseStandardFrame:(NSWindow *)sender + defaultFrame:(NSRect)defaultFrame +{ + NSSize screen_size, video_size; + NSRect standard_frame; + + if ([xineView isFullScreen]) + return defaultFrame; + + screen_size = defaultFrame.size; + video_size = [xineView videoSize]; + + if (screen_size.width / screen_size.height > + video_size.width / video_size.height) + { + standard_frame.size.width = video_size.width * + (screen_size.height / video_size.height); + standard_frame.size.height = screen_size.height; + } + else + { + standard_frame.size.width = screen_size.width; + standard_frame.size.height = video_size.height * + (screen_size.width / video_size.width); + } + + standard_frame.origin.x = + (screen_size.width - standard_frame.size.width) / 2; + standard_frame.origin.y = + (screen_size.height - standard_frame.size.height) / 2; + + return standard_frame; +} + + +/* Notifications */ + +- (void) xineViewDidResize:(NSNotification *)note +{ + NSRect frame = [self frame]; + frame.size = [[self contentView] frame].size; + + [self setFrame:[self frameRectForContentRect:frame] display:YES]; +} + +@end /* XineVideoWindow */ + + +@implementation NSWindow (AspectRatioAdditions) + +- (void) setKeepsAspectRatio: (BOOL) flag { + if (flag) { + NSSize size = [self frame].size; + [self setAspectRatio:size]; + } + else { + [self setResizeIncrements:NSMakeSize(1.0, 1.0)]; + } +} + +/* XXX: This is 100% untested ... */ +- (BOOL) keepsAspectRatio { + NSSize size = [self aspectRatio]; + if (size.width == 0 && size.height == 0) + return false; + else + return true; +} + +@end /* NSWindow (AspectRatioAdditions) */ + diff --git a/src/video_out/macosx/video_window.h b/src/video_out/macosx/video_window.h index b1874672a..07405b8fe 100644 --- a/src/video_out/macosx/video_window.h +++ b/src/video_out/macosx/video_window.h @@ -17,106 +17,17 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * + * Written by Daniel Mack <xine@zonque.org> + * + * Most parts of this code were taken from VLC, http://www.videolan.org + * Thanks for the good research! */ + #ifndef HAVE_VIDEO_WINDOW_H #define HAVE_VIDEO_WINDOW_H -#import <Cocoa/Cocoa.h> - -@protocol XineOpenGLViewDelegate; - -typedef enum { - XINE_FULLSCREEN_OVERSCAN, - XINE_FULLSCREEN_CROP -} XineVideoWindowFullScreenMode; - -@interface XineOpenGLView : NSOpenGLView { - IBOutlet id <NSObject, XineOpenGLViewDelegate> delegate; - int video_width, video_height; - char *texture_buffer; - unsigned long i_texture; - BOOL initDone; - BOOL isFullScreen; - XineVideoWindowFullScreenMode fullscreen_mode; - NSOpenGLContext *fullScreenContext; - NSOpenGLContext *currentContext; - NSLock *mutex; - BOOL keepsVideoAspectRatio; - BOOL resizeViewOnVideoSizeChange; - NSCursor *currentCursor; - id <NSObject, XineOpenGLViewDelegate> _xineController; -} - -- (void) displayTexture; -- (void) drawQuad; -- (void) drawRect: (NSRect) rect; -- (void) goFullScreen: (XineVideoWindowFullScreenMode) mode; -- (void) exitFullScreen; -- (BOOL) isFullScreen; -- (void) reshape; -- (void) initTextures; -- (void) reloadTexture; -- (char *) getTextureBuffer; -- (void) setVideoSize:(NSSize)size; -- (void) setViewSizeInMainThread:(NSSize)size; -/* TODO: replace set...Size below with setSize:(double)videoSizeMultiplier */ -- (void) setNormalSize; -- (void) setHalfSize; -- (void) setDoubleSize; -- (NSSize) videoSize; -- (void) setKeepsVideoAspectRatio:(BOOL)flag; -- (BOOL) keepsVideoAspectRatio; -- (void) setResizeViewOnVideoSizeChange:(BOOL)flag; -- (BOOL) resizeViewOnVideoSizeChange; -- (void) setCurrentCursor:(NSCursor *)cursor; -- (NSCursor *) currentCursor; -- (void) resetCursorRectsInMainThread; -- (void) setXineController:(id)controller; -- (id) xineController; - -/* Delegate methods */ -- (id) delegate; -- (void) setDelegate:(id)aDelegate; - -@end - - -@interface XineVideoWindow : NSWindow { - int width, height; - XineOpenGLView * xineView; -} - -- (id) initWithContentSize:(NSSize)size; -- (XineOpenGLView *) xineView; -@end - - -/* XineOpenGLView delegate methods */ - -@interface NSObject (XineOpenGLViewDelegate) - -- (NSSize)xineViewWillResize:(NSSize)previousSize - toSize:(NSSize)proposedFrameSize; -- (void)xineViewDidResize:(NSNotification *)aNotification; - -@end - - -/* XineOpenGLView notifications */ - -extern NSString *XineViewDidResizeNotification; - - -/* NSWindow aspect ratio convenience methods */ - -@interface NSWindow (AspectRatioAdditions) - -- (void) setKeepsAspectRatio:(BOOL)flag; -- (BOOL) keepsAspectRatio; - -@end - - -#endif /* HAVE_VIDEO_WINDOW_H */ +#include "XineOpenGLView.h" +#include "XineVideoWindow.h" +#endif |