diff --git a/modules/gui/minimal_macosx/Modules.am b/modules/gui/minimal_macosx/Modules.am new file mode 100644 index 0000000000000000000000000000000000000000..2d59924efab34a8f6294d19521612f6ea81b0cf8 --- /dev/null +++ b/modules/gui/minimal_macosx/Modules.am @@ -0,0 +1,14 @@ +# Automake forgets to add a proper tag to libtool with Objective-C files. +# Moreocer Libtool should default tag to CC when none is specified but +# obviously does not. Here is a fix for that. +LIBTOOL=@LIBTOOL@ --tag=CC + +SOURCES_minimal_macosx = \ + intf.m \ + macosx.c \ + VLCMinimalVoutWindow.m \ + VLCOpenGLVoutView.m \ + voutgl.m \ + voutagl.m \ + $(NULL) + diff --git a/modules/gui/minimal_macosx/VLCMinimalVoutWindow.h b/modules/gui/minimal_macosx/VLCMinimalVoutWindow.h new file mode 100644 index 0000000000000000000000000000000000000000..4d889d28794cfde352478dd19dc83105ae939d15 --- /dev/null +++ b/modules/gui/minimal_macosx/VLCMinimalVoutWindow.h @@ -0,0 +1,42 @@ +/***************************************************************************** + * VLCMinimalVoutWindow.h: MacOS X Minimal window for a vout + ***************************************************************************** + * Copyright (C) 2001-2004 the VideoLAN team + * $Id$ + * + * Authors: Pierre d'Herbemont <pdherbemont # videolan.org> + * + * This program 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. + * + * This program 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#import <Cocoa/Cocoa.h> + +#include <vlc/vlc.h> + +@interface VLCMinimalVoutWindow : NSWindow +{ + NSRect rect; +} + +- (id)initWithContentRect:(NSRect)contentRect; + +/* @protocol VLCOpenGLVoutEmbedding */ +- (void)addVoutSubview:(NSView *)view; +- (void)removeVoutSubview:(NSView *)view; +- (void)enterFullscreen; +- (void)leaveFullscreen; +- (BOOL)stretchesVideo; +- (void)setOnTop: (BOOL)ontop; +@end diff --git a/modules/gui/minimal_macosx/VLCMinimalVoutWindow.m b/modules/gui/minimal_macosx/VLCMinimalVoutWindow.m new file mode 100644 index 0000000000000000000000000000000000000000..8a69fdc298ef27c37a4cdb605b3d8b0cd3bb8c03 --- /dev/null +++ b/modules/gui/minimal_macosx/VLCMinimalVoutWindow.m @@ -0,0 +1,82 @@ +/***************************************************************************** + * VLCMinimalVoutWindow.m: MacOS X Minimal interface window + ***************************************************************************** + * Copyright (C) 2001-2004 the VideoLAN team + * $Id$ + * + * Authors: Pierre d'Herbemont <pdherbemont # videolan.org> + * + * This program 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. + * + * This program 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ +#include "intf.h" +#include "voutgl.h" +#include "VLCOpenGLVoutView.h" +#include "VLCMinimalVoutWindow.h" + +/* SetSystemUIMode, ... */ +#import <QuickTime/QuickTime.h> + +#import <Cocoa/Cocoa.h> + +@implementation VLCMinimalVoutWindow +- (id)initWithContentRect:(NSRect)contentRect +{ + if( self = [super initWithContentRect:contentRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]) + { + rect = contentRect; + [self setBackgroundColor:[NSColor blackColor]]; + [self setMovableByWindowBackground: YES]; + } + return self; +} +- (void)addVoutSubview:(NSView *)view +{ + [[self contentView] addSubview:view]; + [view setFrame:[[self contentView] bounds]]; +} + +- (void)removeVoutSubview:(NSView *)view +{ + [self close]; + [self release]; +} + +- (void)enterFullscreen +{ + SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar); + [self setFrame:[[self screen] frame] display: YES]; +} + +- (void)leaveFullscreen +{ + SetSystemUIMode( kUIModeNormal, kUIOptionAutoShowMenuBar); + [self setFrame:rect display: YES]; +} + +- (BOOL)stretchesVideo +{ + return NO; +} + +- (void)setOnTop: (BOOL)ontop +{ + +} +@end + diff --git a/modules/gui/minimal_macosx/VLCOpenGLVoutView.h b/modules/gui/minimal_macosx/VLCOpenGLVoutView.h new file mode 100644 index 0000000000000000000000000000000000000000..df1b05f45515b404f6278279f28bd22a350cba8d --- /dev/null +++ b/modules/gui/minimal_macosx/VLCOpenGLVoutView.h @@ -0,0 +1,79 @@ +/***************************************************************************** + * VLCOpenGLVoutView.h: MacOS X OpenGL provider + ***************************************************************************** + * Copyright (C) 2001-2004 the VideoLAN team + * $Id$ + * + * Authors: Colin Delacroix <colin@zoy.org> + * Florian G. Pflug <fgp@phlo.org> + * Jon Lech Johansen <jon-vl@nanocrew.net> + * Derk-Jan Hartman <hartman at videolan dot org> + * Eric Petit <titer@m0k.org> + * Benjamin Pracht <bigben at videolan dot org> + * Damien Fouilleul <damienf at videolan dot org> + * + * This program 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. + * + * This program 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#import <Cocoa/Cocoa.h> + +#include <OpenGL/OpenGL.h> +#include <OpenGL/gl.h> + +#include <vlc/vlc.h> + +/* Entry point */ +int cocoaglvoutviewInit( vout_thread_t * p_vout ); +void cocoaglvoutviewEnd( vout_thread_t * p_vout ); +int cocoaglvoutviewManage( vout_thread_t * p_vout ); +int cocoaglvoutviewControl( vout_thread_t *p_vout, int i_query, va_list args ); +void cocoaglvoutviewSwap( vout_thread_t * p_vout ); +int cocoaglvoutviewLock( vout_thread_t * p_vout ); +void cocoaglvoutviewUnlock( vout_thread_t * p_vout ); + +/* To commmunicate with the VLC.framework */ +@protocol VLCOpenGLVoutEmbedding +- (void)addVoutSubview:(NSView *)view; +- (void)removeVoutSubview:(NSView *)view; + +- (void)enterFullscreen; +- (void)leaveFullscreen; + +- (BOOL)stretchesVideo; + +- (void)setOnTop: (BOOL)ontop; /* Do we really want that in protocol? */ +@end + +/* VLCOpenGLVoutView */ +@interface VLCOpenGLVoutView : NSOpenGLView +{ + id <VLCOpenGLVoutEmbedding> container; + vout_thread_t * p_vout; + NSLock * objectLock; +} +/* Init a new gl view and register it to both the framework and the + * vout_thread_t. Must be called from main thread */ ++ (void) autoinitOpenGLVoutViewIntVoutWithContainer: (NSData *) args; + +- (id) initWithVout: (vout_thread_t *) vout container: (id <VLCOpenGLVoutEmbedding>) container; + +- (void) detachFromVout; +- (id <VLCOpenGLVoutEmbedding>) container; + +- (void) reshape; +- (void) update; +- (void) drawRect: (NSRect) rect; +@end + diff --git a/modules/gui/minimal_macosx/VLCOpenGLVoutView.m b/modules/gui/minimal_macosx/VLCOpenGLVoutView.m new file mode 100644 index 0000000000000000000000000000000000000000..aa7fe067586617c77213718e1eeaee7c01ad5e87 --- /dev/null +++ b/modules/gui/minimal_macosx/VLCOpenGLVoutView.m @@ -0,0 +1,369 @@ +/***************************************************************************** + * VLCOpenGLVoutView.m: MacOS X OpenGL provider + ***************************************************************************** + * Copyright (C) 2001-2004 the VideoLAN team + * $Id$ + * + * Authors: Colin Delacroix <colin@zoy.org> + * Florian G. Pflug <fgp@phlo.org> + * Jon Lech Johansen <jon-vl@nanocrew.net> + * Derk-Jan Hartman <hartman at videolan dot org> + * Eric Petit <titer@m0k.org> + * Benjamin Pracht <bigben at videolan dot org> + * Damien Fouilleul <damienf at videolan dot org> + * Pierr d'Herbemont <pdherbemont at videolan dot org> + * + * This program 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. + * + * This program 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ +#include "intf.h" +#include "voutgl.h" +#include "VLCOpenGLVoutView.h" +#include "VLCMinimalVoutWindow.h" + +#include <OpenGL/OpenGL.h> +#include <OpenGL/gl.h> + +/***************************************************************************** + * cocoaglvoutviewInit + *****************************************************************************/ +int cocoaglvoutviewInit( vout_thread_t * p_vout ) +{ + vlc_value_t value_drawable; + id <VLCOpenGLVoutEmbedding> o_cocoaglview_container; + + msg_Dbg( p_vout, "Mac OS X Vout is opening" ); + + var_Create( p_vout, "drawable", VLC_VAR_DOINHERIT ); + var_Get( p_vout, "drawable", &value_drawable ); + + o_cocoaglview_container = (id) value_drawable.i_int; + if (!o_cocoaglview_container) + { + msg_Warn( p_vout, "No drawable!, spawing a window" ); + o_cocoaglview_container = [[VLCMinimalVoutWindow alloc] initWithContentRect: NSMakeRect( 0, 0, 200, 200 )]; + } + + p_vout->p_sys->b_embedded = VLC_FALSE; + + p_vout->p_sys->o_pool = [[NSAutoreleasePool alloc] init]; + + /* Create the GL view */ + struct args { vout_thread_t * p_vout; id <VLCOpenGLVoutEmbedding> container; } args = { p_vout, o_cocoaglview_container }; + + [VLCOpenGLVoutView performSelectorOnMainThread:@selector(autoinitOpenGLVoutViewIntVoutWithContainer:) + withObject:[NSData dataWithBytes: &args length: sizeof(struct args)] waitUntilDone:YES]; + + [[p_vout->p_sys->o_glview openGLContext] makeCurrentContext]; + return VLC_SUCCESS; +} + +/***************************************************************************** + * cocoaglvoutviewEnd + *****************************************************************************/ +void cocoaglvoutviewEnd( vout_thread_t * p_vout ) +{ + id <VLCOpenGLVoutEmbedding> o_cocoaglview_container; + + msg_Dbg( p_vout, "Mac OS X Vout is closing" ); + var_Destroy( p_vout, "drawable" ); + + o_cocoaglview_container = [p_vout->p_sys->o_glview container]; + + /* Make sure our view won't request the vout now */ + [p_vout->p_sys->o_glview detachFromVout]; + msg_Dbg( p_vout, "Mac OS X Vout is closing" ); + + /* Let the view go, _without_blocking_ */ + [p_vout->p_sys->o_glview performSelectorOnMainThread:@selector(removeFromSuperview) withObject:NULL waitUntilDone:NO]; + + if( [(id)o_cocoaglview_container respondsToSelector:@selector(removeVoutSubview:)] ) + [o_cocoaglview_container removeVoutSubview: p_vout->p_sys->o_glview]; + + [p_vout->p_sys->o_pool release]; + +} + +/***************************************************************************** + * cocoaglvoutviewManage + *****************************************************************************/ +int cocoaglvoutviewManage( vout_thread_t * p_vout ) +{ + if( p_vout->i_changes & VOUT_ASPECT_CHANGE ) + { + [p_vout->p_sys->o_glview reshape]; + p_vout->i_changes &= ~VOUT_ASPECT_CHANGE; + } + if( p_vout->i_changes & VOUT_CROP_CHANGE ) + { + [p_vout->p_sys->o_glview reshape]; + p_vout->i_changes &= ~VOUT_CROP_CHANGE; + } + + if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE ) + { + NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init]; + + p_vout->b_fullscreen = !p_vout->b_fullscreen; + + if( p_vout->b_fullscreen ) + [[p_vout->p_sys->o_glview container] enterFullscreen]; + else + [[p_vout->p_sys->o_glview container] leaveFullscreen]; + + [o_pool release]; + + p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE; + } + + //[[p_vout->p_sys->o_glview container] manage]; + return VLC_SUCCESS; +} + +/***************************************************************************** + * cocoaglvoutviewControl: control facility for the vout + *****************************************************************************/ +int cocoaglvoutviewControl( vout_thread_t *p_vout, int i_query, va_list args ) +{ + vlc_bool_t b_arg; + + switch( i_query ) + { + case VOUT_SET_STAY_ON_TOP: + b_arg = va_arg( args, vlc_bool_t ); + [[p_vout->p_sys->o_glview container] setOnTop: b_arg]; + return VLC_SUCCESS; + + case VOUT_CLOSE: + case VOUT_REPARENT: + default: + return vout_vaControlDefault( p_vout, i_query, args ); + } +} + +/***************************************************************************** + * cocoaglvoutviewSwap + *****************************************************************************/ +void cocoaglvoutviewSwap( vout_thread_t * p_vout ) +{ + p_vout->p_sys->b_got_frame = VLC_TRUE; + [[p_vout->p_sys->o_glview openGLContext] flushBuffer]; +} + +/***************************************************************************** + * cocoaglvoutviewLock + *****************************************************************************/ +int cocoaglvoutviewLock( vout_thread_t * p_vout ) +{ + if( kCGLNoError == CGLLockContext([[p_vout->p_sys->o_glview openGLContext] CGLContextObj]) ) + { + [[p_vout->p_sys->o_glview openGLContext] makeCurrentContext]; + return 0; + } + return 1; +} + +/***************************************************************************** + * cocoaglvoutviewUnlock + *****************************************************************************/ +void cocoaglvoutviewUnlock( vout_thread_t * p_vout ) +{ + CGLUnlockContext([[p_vout->p_sys->o_glview openGLContext] CGLContextObj]); +} + +/***************************************************************************** + * VLCOpenGLVoutView implementation + *****************************************************************************/ +@implementation VLCOpenGLVoutView + +/* Init a new gl view and register it to both the framework and the + * vout_thread_t. Must be called from main thread. */ ++ (void) autoinitOpenGLVoutViewIntVoutWithContainer: (NSData *) argsAsData +{ + struct args { vout_thread_t * p_vout; id <VLCOpenGLVoutEmbedding> container; } * + args = (struct args *)[argsAsData bytes]; + VLCOpenGLVoutView * oglview; + + oglview = [[VLCOpenGLVoutView alloc] initWithVout: args->p_vout container: args->container]; + + args->p_vout->p_sys->o_glview = [oglview autorelease]; + + [args->container addVoutSubview: oglview]; +} + +- (void)dealloc +{ + [objectLock dealloc]; + [super dealloc]; +} + +- (void)removeFromSuperview +{ + [super removeFromSuperview]; +} + + +- (id) initWithVout: (vout_thread_t *) vout container: (id <VLCOpenGLVoutEmbedding>) aContainer +{ + NSOpenGLPixelFormatAttribute attribs[] = + { + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAAccelerated, + NSOpenGLPFANoRecovery, + NSOpenGLPFAColorSize, 24, + NSOpenGLPFAAlphaSize, 8, + NSOpenGLPFADepthSize, 24, + NSOpenGLPFAWindow, + 0 + }; + + NSOpenGLPixelFormat * fmt = [[NSOpenGLPixelFormat alloc] + initWithAttributes: attribs]; + + if( !fmt ) + { + msg_Warn( p_vout, "could not create OpenGL video output" ); + return nil; + } + + if( self = [super initWithFrame: NSMakeRect(0,0,10,10) pixelFormat: fmt] ) + { + p_vout = vout; + container = aContainer; + objectLock = [[NSLock alloc] init]; + + [fmt release]; + + [[self openGLContext] makeCurrentContext]; + [[self openGLContext] update]; + + /* 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 ); + } + return self; +} + +- (void) detachFromVout +{ + [objectLock lock]; + p_vout = NULL; + [objectLock unlock]; +} + +- (id <VLCOpenGLVoutEmbedding>) container +{ + return container; +} + +- (void) destroyVout +{ + [objectLock lock]; + if( p_vout ) + { + vlc_object_detach( p_vout ); + vlc_object_release( p_vout ); + vout_Destroy( (vout_thread_t *)p_vout ); + } + [objectLock unlock]; +} + +- (void) reshape +{ + int x, y; + vlc_value_t val; + + [objectLock lock]; + if( !p_vout ) + { + [objectLock unlock]; + return; + } + + cocoaglvoutviewLock( p_vout ); + NSRect bounds = [self bounds]; + + if( [[self container] stretchesVideo] ) + { + x = bounds.size.width; + y = bounds.size.height; + } + else if( bounds.size.height * p_vout->fmt_in.i_visible_width * + p_vout->fmt_in.i_sar_num < + bounds.size.width * p_vout->fmt_in.i_visible_height * + p_vout->fmt_in.i_sar_den ) + { + x = ( bounds.size.height * p_vout->fmt_in.i_visible_width * + p_vout->fmt_in.i_sar_num ) / + ( p_vout->fmt_in.i_visible_height * p_vout->fmt_in.i_sar_den); + + y = bounds.size.height; + } + else + { + x = bounds.size.width; + y = ( bounds.size.width * p_vout->fmt_in.i_visible_height * + p_vout->fmt_in.i_sar_den) / + ( p_vout->fmt_in.i_visible_width * p_vout->fmt_in.i_sar_num ); + } + + glViewport( ( bounds.size.width - x ) / 2, + ( bounds.size.height - y ) / 2, x, y ); + + if( p_vout->p_sys->b_got_frame ) + { + /* Ask the opengl module to redraw */ + vout_thread_t * p_parent; + p_parent = (vout_thread_t *) p_vout->p_parent; + cocoaglvoutviewUnlock( p_vout ); + if( p_parent && p_parent->pf_display ) + { + p_parent->pf_display( p_parent, NULL ); + } + } + else + { + glClear( GL_COLOR_BUFFER_BIT ); + cocoaglvoutviewUnlock( p_vout ); + } + [objectLock unlock]; + [super reshape]; +} + +- (void) update +{ + if( kCGLNoError != CGLLockContext([[self openGLContext] CGLContextObj]) ) + return; + [super update]; + CGLUnlockContext([[p_vout->p_sys->o_glview openGLContext] CGLContextObj]); +} + +- (void) drawRect: (NSRect) rect +{ + if( kCGLNoError != CGLLockContext([[self openGLContext] CGLContextObj]) ) + return; + [[self openGLContext] flushBuffer]; + [super drawRect:rect]; + CGLUnlockContext([[p_vout->p_sys->o_glview openGLContext] CGLContextObj]); +} + +@end + diff --git a/modules/gui/minimal_macosx/intf.h b/modules/gui/minimal_macosx/intf.h new file mode 100644 index 0000000000000000000000000000000000000000..a43b902f022ec1c3e84331a5a68439ca8e6cc9e9 --- /dev/null +++ b/modules/gui/minimal_macosx/intf.h @@ -0,0 +1,50 @@ +/***************************************************************************** + * intf.h: MacOS X interface module + ***************************************************************************** + * Copyright (C) 2002-2006 the VideoLAN team + * $Id$ + * + * Authors: Jon Lech Johansen <jon-vl@nanocrew.net> + * Christophe Massiot <massiot@via.ecp.fr> + * Derk-Jan Hartman <hartman at videolan dot org> + * Felix KŸhne <fkuehne at videolan dot org> + * + * This program 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. + * + * This program 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#include <vlc/vlc.h> +#include <vlc_interface.h> +#include <vlc_playlist.h> +#include <vlc_vout.h> +#include <vlc_aout.h> +#include <vlc_input.h> + +#include <Cocoa/Cocoa.h> + +/***************************************************************************** + * Local prototypes. + *****************************************************************************/ + +/* switch this to 1, if you want to use Obj-C with GC */ +#define GC_ENABLED 0 + +/***************************************************************************** + * intf_sys_t: description and status of the interface + *****************************************************************************/ +struct intf_sys_t +{ + NSAutoreleasePool * o_pool; +}; + diff --git a/modules/gui/minimal_macosx/intf.m b/modules/gui/minimal_macosx/intf.m new file mode 100644 index 0000000000000000000000000000000000000000..62638e7f2950f3d36194497cbeace83468f48a80 --- /dev/null +++ b/modules/gui/minimal_macosx/intf.m @@ -0,0 +1,101 @@ +/***************************************************************************** + * intf.m: MacOS X interface module + ***************************************************************************** + * Copyright (C) 2002-2007 the VideoLAN team + * $Id$ + * + * Authors: Jon Lech Johansen <jon-vl@nanocrew.net> + * Christophe Massiot <massiot@via.ecp.fr> + * Derk-Jan Hartman <hartman at videolan.org> + * Felix KŸhne <fkuehne at videolan dot org> + * + * This program 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. + * + * This program 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ +#include <stdlib.h> /* malloc(), free() */ +#include <sys/param.h> /* for MAXPATHLEN */ +#include <string.h> +#include <vlc/vlc.h> + +#include <vlc_keys.h> + +#include <vlc_input.h> + +#import <intf.h> + +/***************************************************************************** + * Local prototypes. + *****************************************************************************/ +static void Run ( intf_thread_t *p_intf ); + +/***************************************************************************** + * OpenIntf: initialize interface + *****************************************************************************/ +int E_(OpenIntf) ( vlc_object_t *p_this ) +{ + intf_thread_t *p_intf = (intf_thread_t*) p_this; + + p_intf->p_sys = malloc( sizeof( intf_sys_t ) ); + if( p_intf->p_sys == NULL ) + { + return( 1 ); + } + + memset( p_intf->p_sys, 0, sizeof( *p_intf->p_sys ) ); + + p_intf->p_sys->o_pool = [[NSAutoreleasePool alloc] init]; + + p_intf->b_play = VLC_TRUE; + p_intf->pf_run = Run; + + return( 0 ); +} + +/***************************************************************************** + * CloseIntf: destroy interface + *****************************************************************************/ +void E_(CloseIntf) ( vlc_object_t *p_this ) +{ + intf_thread_t *p_intf = (intf_thread_t*) p_this; + + free( p_intf->p_sys ); +} + +/***************************************************************************** + * Run: main loop + *****************************************************************************/ +static void Run( intf_thread_t *p_intf ) +{ + sigset_t set; + + /* Do it again - for some unknown reason, vlc_thread_create() often + * fails to go to real-time priority with the first launched thread + * (???) --Meuuh */ + vlc_thread_set_priority( p_intf, VLC_THREAD_PRIORITY_LOW ); + + /* Make sure the "force quit" menu item does quit instantly. + * VLC overrides SIGTERM which is sent by the "force quit" + * menu item to make sure deamon mode quits gracefully, so + * we un-override SIGTERM here. */ + sigemptyset( &set ); + sigaddset( &set, SIGTERM ); + pthread_sigmask( SIG_UNBLOCK, &set, NULL ); + + [NSApp run]; +} + diff --git a/modules/gui/minimal_macosx/macosx.c b/modules/gui/minimal_macosx/macosx.c new file mode 100644 index 0000000000000000000000000000000000000000..80722bf3d6391ef61d12b3fe99556452249bdcfb --- /dev/null +++ b/modules/gui/minimal_macosx/macosx.c @@ -0,0 +1,64 @@ +/***************************************************************************** + * macosx.m: Mac OS X module for vlc + ***************************************************************************** + * Copyright (C) 2001-2006 the VideoLAN team + * $Id$ + * + * Authors: Colin Delacroix <colin@zoy.org> + * Eugenio Jarosiewicz <ej0@cise.ufl.edu> + * Florian G. Pflug <fgp@phlo.org> + * Jon Lech Johansen <jon-vl@nanocrew.net> + * + * This program 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. + * + * This program 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ +#include <stdlib.h> /* malloc(), free() */ +#include <string.h> + +#include <vlc/vlc.h> + +/***************************************************************************** + * External prototypes + *****************************************************************************/ +int E_(OpenIntf) ( vlc_object_t * ); +void E_(CloseIntf) ( vlc_object_t * ); + +int E_(OpenVideoGL) ( vlc_object_t * ); +void E_(CloseVideoGL) ( vlc_object_t * ); + +/***************************************************************************** + * Module descriptor + *****************************************************************************/ + +vlc_module_begin(); + /* Minimal interface. see intf.m */ + set_description( _("Mac OS X interface") ); + set_capability( "interface", 100 ); + set_callbacks( E_(OpenIntf), E_(CloseIntf) ); + set_category( CAT_INTERFACE ); + set_subcategory( SUBCAT_INTERFACE_MAIN ); + + add_submodule(); + /* Will be loaded even without interface module. see voutgl.m */ + set_description( "Mac OS X OpenGL" ); + set_capability( "opengl provider", 100 ); + set_category( CAT_VIDEO); + set_subcategory( SUBCAT_VIDEO_VOUT ); + set_callbacks( E_(OpenVideoGL), E_(CloseVideoGL) ); +vlc_module_end(); + diff --git a/modules/gui/minimal_macosx/voutagl.h b/modules/gui/minimal_macosx/voutagl.h new file mode 100644 index 0000000000000000000000000000000000000000..013a307ddb3a30335a51b69bfd612f5dcacb9292 --- /dev/null +++ b/modules/gui/minimal_macosx/voutagl.h @@ -0,0 +1,43 @@ +/***************************************************************************** + * voutagl.c: MacOS X agl OpenGL provider (used by webbrowser.plugin) + ***************************************************************************** + * Copyright (C) 2001-2004 the VideoLAN team + * $Id$ + * + * Authors: Colin Delacroix <colin@zoy.org> + * Florian G. Pflug <fgp@phlo.org> + * Jon Lech Johansen <jon-vl@nanocrew.net> + * Derk-Jan Hartman <hartman at videolan dot org> + * Eric Petit <titer@m0k.org> + * Benjamin Pracht <bigben at videolan dot org> + * Damien Fouilleul <damienf at videolan dot org> + * + * This program 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. + * + * This program 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#include <OpenGL/OpenGL.h> +#include <OpenGL/gl.h> + +#include <AGL/agl.h> + +#include <vlc/vlc.h> + +int aglInit ( vout_thread_t * p_vout ); +void aglEnd ( vout_thread_t * p_vout ); +int aglManage ( vout_thread_t * p_vout ); +int aglControl( vout_thread_t *, int, va_list ); +void aglSwap ( vout_thread_t * p_vout ); +int aglLock ( vout_thread_t * p_vout ); +void aglUnlock ( vout_thread_t * p_vout ); diff --git a/modules/gui/minimal_macosx/voutagl.m b/modules/gui/minimal_macosx/voutagl.m new file mode 100644 index 0000000000000000000000000000000000000000..9c6af42d1d4f023be6008ad0111a32f29c4a0967 --- /dev/null +++ b/modules/gui/minimal_macosx/voutagl.m @@ -0,0 +1,684 @@ +/***************************************************************************** + * voutagl.c: MacOS X agl OpenGL provider (used by webbrowser.plugin) + ***************************************************************************** + * Copyright (C) 2001-2004 the VideoLAN team + * $Id$ + * + * Authors: Colin Delacroix <colin@zoy.org> + * Florian G. Pflug <fgp@phlo.org> + * Jon Lech Johansen <jon-vl@nanocrew.net> + * Derk-Jan Hartman <hartman at videolan dot org> + * Eric Petit <titer@m0k.org> + * Benjamin Pracht <bigben at videolan dot org> + * Damien Fouilleul <damienf at videolan dot org> + * + * This program 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. + * + * This program 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#include "intf.h" +#include "voutgl.h" +#include "voutagl.h" + +/***************************************************************************** + * embedded AGL context implementation + *****************************************************************************/ + +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); + +int aglInit( vout_thread_t * p_vout ) +{ + vlc_value_t val; + + Rect viewBounds; + Rect clipBounds; + + static const GLint ATTRIBUTES[] = { + AGL_WINDOW, + AGL_RGBA, + AGL_NO_RECOVERY, + AGL_ACCELERATED, + AGL_DOUBLEBUFFER, + AGL_RED_SIZE, 8, + AGL_GREEN_SIZE, 8, + AGL_BLUE_SIZE, 8, + AGL_ALPHA_SIZE, 8, + AGL_DEPTH_SIZE, 24, + AGL_NONE }; + + AGLPixelFormat pixFormat; + + p_vout->p_sys->b_embedded = VLC_TRUE; + + pixFormat = aglChoosePixelFormat(NULL, 0, ATTRIBUTES); + if( NULL == pixFormat ) + { + msg_Err( p_vout, "no screen renderer available for required attributes." ); + 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." ); + return VLC_EGENERIC; + } + 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); + aglEnable(p_vout->p_sys->agl_ctx, AGL_SWAP_INTERVAL); + } + + var_Get( p_vout->p_libvlc, "drawable", &val ); + p_vout->p_sys->agl_drawable = (AGLDrawable)val.i_int; + 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; + + p_vout->p_sys->b_clipped_out = (clipBounds.top == clipBounds.bottom) + || (clipBounds.left == clipBounds.right); + if( ! p_vout->p_sys->b_clipped_out ) + { + aglLock(p_vout); + aglSetViewport(p_vout, viewBounds, clipBounds); + aglReshape(p_vout); + aglUnlock(p_vout); + } + p_vout->p_sys->clipBounds = clipBounds; + p_vout->p_sys->viewBounds = viewBounds; + + return VLC_SUCCESS; +} + +void aglEnd( vout_thread_t * p_vout ) +{ + aglSetCurrentContext(NULL); + if( p_vout->p_sys->theWindow ) DisposeWindow( p_vout->p_sys->theWindow ); + aglDestroyContext(p_vout->p_sys->agl_ctx); +} + +void aglReshape( vout_thread_t * p_vout ) +{ + unsigned int x, y; + unsigned int i_height = p_vout->p_sys->i_height; + unsigned int i_width = p_vout->p_sys->i_width; + + vout_PlacePicture(p_vout, i_width, i_height, &x, &y, &i_width, &i_height); + + glViewport( p_vout->p_sys->i_offx + x, p_vout->p_sys->i_offy + y, i_width, i_height ); + + if( p_vout->p_sys->b_got_frame ) + { + /* Ask the opengl module to redraw */ + vout_thread_t * p_parent; + p_parent = (vout_thread_t *) p_vout->p_parent; + if( p_parent && p_parent->pf_display ) + { + p_parent->pf_display( p_parent, NULL ); + } + } + else + { + glClear( GL_COLOR_BUFFER_BIT ); + } +} + +/* private event class */ +enum +{ + kEventClassVLCPlugin = 'vlcp', +}; +/* private event kinds */ +enum +{ + kEventVLCPluginShowFullscreen = 32768, + kEventVLCPluginHideFullscreen, +}; + +static void sendEventToMainThread(EventTargetRef target, UInt32 class, UInt32 kind) +{ + EventRef myEvent; + if( noErr == CreateEvent(NULL, class, kind, 0, kEventAttributeNone, &myEvent) ) + { + if( noErr == SetEventParameter(myEvent, kEventParamPostTarget, typeEventTargetRef, sizeof(EventTargetRef), &target) ) + { + PostEventToQueue(GetMainEventQueue(), myEvent, kEventPriorityStandard); + } + ReleaseEvent(myEvent); + } +} + +int aglManage( vout_thread_t * p_vout ) +{ + if( p_vout->i_changes & VOUT_ASPECT_CHANGE ) + { + aglLock( p_vout ); + aglReshape(p_vout); + aglUnlock( p_vout ); + p_vout->i_changes &= ~VOUT_ASPECT_CHANGE; + } + if( p_vout->i_changes & VOUT_CROP_CHANGE ) + { + aglLock( p_vout ); + aglReshape(p_vout); + aglUnlock( p_vout ); + p_vout->i_changes &= ~VOUT_CROP_CHANGE; + } + if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE ) + { + aglSetDrawable(p_vout->p_sys->agl_ctx, NULL); + aglLock( 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; + 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; + + 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); + } + else + { + Rect deviceRect; + + GDHandle deviceHdl = GetMainDevice(); + deviceRect = (*deviceHdl)->gdRect; + + if( !p_vout->p_sys->theWindow ) + { + /* Create a window */ + WindowAttributes windowAttrs; + + windowAttrs = kWindowStandardDocumentAttributes + | kWindowStandardHandlerAttribute + | kWindowLiveResizeAttribute + | kWindowNoShadowAttribute; + + windowAttrs &= (~kWindowResizableAttribute); + + CreateNewWindow(kDocumentWindowClass, windowAttrs, &deviceRect, &p_vout->p_sys->theWindow); + if( !p_vout->p_sys->winGroup ) + { + CreateWindowGroup(0, &p_vout->p_sys->winGroup); + 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 }, + { kEventClassMouse, kEventMouseMoved }, + { kEventClassMouse, kEventMouseUp }, + { kEventClassWindow, kEventWindowClosed }, + { kEventClassWindow, kEventWindowBoundsChanged }, + { kEventClassCommand, kEventCommandProcess }, + { kEventClassVLCPlugin, kEventVLCPluginShowFullscreen }, + { kEventClassVLCPlugin, kEventVLCPluginHideFullscreen }, + }; + InstallWindowEventHandler (p_vout->p_sys->theWindow, NewEventHandlerUPP (WindowEventHandler), GetEventTypeCount(win_events), win_events, p_vout, NULL); + } + else + { + /* just in case device resolution changed */ + SetWindowBounds(p_vout->p_sys->theWindow, kWindowContentRgn, &deviceRect); + } + glClear( GL_COLOR_BUFFER_BIT ); + p_vout->p_sys->agl_drawable = (AGLDrawable)GetWindowPort(p_vout->p_sys->theWindow); + aglSetDrawable(p_vout->p_sys->agl_ctx, p_vout->p_sys->agl_drawable); + aglSetCurrentContext(p_vout->p_sys->agl_ctx); + 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); + } + aglReshape(p_vout); + aglUnlock( p_vout ); + p_vout->b_fullscreen = !p_vout->b_fullscreen; + p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE; + } + return VLC_SUCCESS; +} + +int aglControl( vout_thread_t *p_vout, int i_query, va_list args ) +{ + switch( i_query ) + { + case VOUT_SET_VIEWPORT: + { + Rect viewBounds, clipBounds; + viewBounds.top = va_arg( args, int); + viewBounds.left = va_arg( args, int); + viewBounds.bottom = va_arg( args, int); + viewBounds.right = va_arg( args, int); + clipBounds.top = va_arg( args, int); + clipBounds.left = va_arg( args, int); + clipBounds.bottom = va_arg( args, int); + clipBounds.right = va_arg( args, int); + + if( !p_vout->b_fullscreen ) + { + /* + ** check that the clip rect is not empty, as this is used + ** by Firefox to prevent a plugin from displaying during + ** a scrolling event. In this case we just prevent buffers + ** from being swapped and ignore clipping as this is less + ** disruptive than a GL geometry change + */ + + p_vout->p_sys->b_clipped_out = (clipBounds.top == clipBounds.bottom) + || (clipBounds.left == clipBounds.right); + if( ! p_vout->p_sys->b_clipped_out ) + { + /* ignore consecutive viewport update with identical parameters */ + if( memcmp(&clipBounds, &(p_vout->p_sys->clipBounds), sizeof(clipBounds) ) + && memcmp(&viewBounds, &(p_vout->p_sys->viewBounds), sizeof(viewBounds)) ) + { + aglLock( p_vout ); + aglSetViewport(p_vout, viewBounds, clipBounds); + aglReshape( p_vout ); + aglUnlock( p_vout ); + p_vout->p_sys->clipBounds = clipBounds; + p_vout->p_sys->viewBounds = viewBounds; + } + } + } + return VLC_SUCCESS; + } + + case VOUT_REDRAW_RECT: + { + vout_thread_t * p_parent; + Rect areaBounds; + + areaBounds.top = va_arg( args, int); + areaBounds.left = va_arg( args, int); + areaBounds.bottom = va_arg( args, int); + areaBounds.right = va_arg( args, int); + + /* Ask the opengl module to redraw */ + p_parent = (vout_thread_t *) p_vout->p_parent; + if( p_parent && p_parent->pf_display ) + { + p_parent->pf_display( p_parent, NULL ); + } + 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 ); + } +} + +void aglSwap( vout_thread_t * p_vout ) +{ + if( ! p_vout->p_sys->b_clipped_out ) + { + p_vout->p_sys->b_got_frame = VLC_TRUE; + aglSwapBuffers(p_vout->p_sys->agl_ctx); + } + else + { + /* drop frame */ + glFlush(); + } +} + +/* Enter this function with the p_vout locked */ +static void aglSetViewport( vout_thread_t *p_vout, Rect viewBounds, Rect clipBounds ) +{ + // mozilla plugin provides coordinates based on port bounds + // however AGL coordinates are based on window structure region + // and are vertically flipped + GLint rect[4]; + CGrafPtr port = (CGrafPtr)p_vout->p_sys->agl_drawable; + Rect winBounds, clientBounds; + + GetWindowBounds(GetWindowFromPort(port), + kWindowStructureRgn, &winBounds); + GetWindowBounds(GetWindowFromPort(port), + kWindowContentRgn, &clientBounds); + + /* update video clipping bounds in drawable */ + rect[0] = (clientBounds.left-winBounds.left) + + clipBounds.left; // from window left edge + rect[1] = (winBounds.bottom-winBounds.top) + - (clientBounds.top-winBounds.top) + - 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); + + /* update video internal bounds in drawable */ + p_vout->p_sys->i_width = viewBounds.right-viewBounds.left; + p_vout->p_sys->i_height = viewBounds.bottom-viewBounds.top; + p_vout->p_sys->i_offx = -clipBounds.left - viewBounds.left; + p_vout->p_sys->i_offy = clipBounds.bottom + viewBounds.top + - p_vout->p_sys->i_height; + + aglUpdateContext(p_vout->p_sys->agl_ctx); +} + +//default window event handler +static pascal OSStatus WindowEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData) +{ + OSStatus result = noErr; + UInt32 class = GetEventClass (event); + UInt32 kind = GetEventKind (event); + vout_thread_t *p_vout = (vout_thread_t *)userData; + + result = CallNextEventHandler(nextHandler, event); + if(class == kEventClassCommand) + { + HICommand theHICommand; + GetEventParameter( event, kEventParamDirectObject, typeHICommand, NULL, sizeof( HICommand ), NULL, &theHICommand ); + + switch ( theHICommand.commandID ) + { + default: + result = eventNotHandledErr; + } + } + else if(class == kEventClassWindow) + { + WindowRef window; + Rect rectPort = {0,0,0,0}; + + GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &window); + + if(window) + { + GetPortBounds(GetWindowPort(window), &rectPort); + } + + switch (kind) + { + case kEventWindowClosed: + case kEventWindowZoomed: + case kEventWindowBoundsChanged: + break; + + default: + result = eventNotHandledErr; + } + } + else if(class == kEventClassMouse) + { + switch (kind) + { + case kEventMouseDown: + { + UInt16 button; + + GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button); + switch (button) + { + case kEventMouseButtonPrimary: + { + vlc_value_t val; + + var_Get( p_vout, "mouse-button-down", &val ); + val.i_int |= 1; + var_Set( p_vout, "mouse-button-down", val ); + break; + } + case kEventMouseButtonSecondary: + { + vlc_value_t val; + + var_Get( p_vout, "mouse-button-down", &val ); + val.i_int |= 2; + var_Set( p_vout, "mouse-button-down", val ); + break; + } + case kEventMouseButtonTertiary: + { + vlc_value_t val; + + var_Get( p_vout, "mouse-button-down", &val ); + val.i_int |= 4; + var_Set( p_vout, "mouse-button-down", val ); + break; + } + default: + result = eventNotHandledErr; + } + break; + } + + case kEventMouseUp: + { + UInt16 button; + + GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button); + switch (button) + { + case kEventMouseButtonPrimary: + { + UInt32 clickCount = 0; + GetEventParameter(event, kEventParamClickCount, typeUInt32, NULL, sizeof(clickCount), NULL, &clickCount); + if( clickCount > 1 ) + { + vlc_value_t val; + + val.b_bool = VLC_FALSE; + var_Set((vout_thread_t *) p_vout->p_parent, "fullscreen", val); + } + else + { + vlc_value_t val; + + val.b_bool = VLC_TRUE; + var_Set( p_vout, "mouse-clicked", val ); + + var_Get( p_vout, "mouse-button-down", &val ); + val.i_int &= ~1; + var_Set( p_vout, "mouse-button-down", val ); + } + break; + } + case kEventMouseButtonSecondary: + { + vlc_value_t val; + + var_Get( p_vout, "mouse-button-down", &val ); + val.i_int &= ~2; + var_Set( p_vout, "mouse-button-down", val ); + break; + } + case kEventMouseButtonTertiary: + { + vlc_value_t val; + + var_Get( p_vout, "mouse-button-down", &val ); + val.i_int &= ~2; + var_Set( p_vout, "mouse-button-down", val ); + break; + } + default: + result = eventNotHandledErr; + } + break; + } + + case kEventMouseMoved: + { + Point ml; + vlc_value_t val; + + 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; + + 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 = VLC_TRUE; + var_Set( p_vout, "mouse-moved", val ); + + break; + } + + default: + result = eventNotHandledErr; + } + } + else if(class == kEventClassTextInput) + { + switch (kind) + { + case kEventTextInputUnicodeForKeyEvent: + { + break; + } + default: + result = eventNotHandledErr; + } + } + else if(class == kEventClassVLCPlugin) + { + switch (kind) + { + case kEventVLCPluginShowFullscreen: + ShowWindow (p_vout->p_sys->theWindow); + SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar); + //CGDisplayHideCursor(kCGDirectMainDisplay); + break; + case kEventVLCPluginHideFullscreen: + HideWindow (p_vout->p_sys->theWindow); + SetSystemUIMode( kUIModeNormal, 0); + CGDisplayShowCursor(kCGDirectMainDisplay); + break; + default: + result = eventNotHandledErr; + break; + } + } + return result; +} + +int aglLock( vout_thread_t * p_vout ) +{ +#ifdef __ppc__ + /* + * before 10.4, we set the AGL context as current and + * then we retrieve and use the matching CGL context + */ + aglSetCurrentContext(p_vout->p_sys->agl_ctx); + return kCGLNoError != CGLLockContext( CGLGetCurrentContext() ); +#else + /* since 10.4, this is the safe way to get the underlying CGL context */ + CGLContextObj cglContext; + if( aglGetCGLContext(p_vout->p_sys->agl_ctx, (void**)&cglContext) ) + { + if( kCGLNoError == CGLLockContext( cglContext ) ) + { + aglSetCurrentContext(p_vout->p_sys->agl_ctx); + return 0; + } + } + return 1; +#endif +} + +void aglUnlock( vout_thread_t * p_vout ) +{ +#ifdef __ppc__ + /* + * before 10.4, we assume that the AGL context is current. + * therefore, we use the current CGL context + */ + CGLUnlockContext( CGLGetCurrentContext() ); +#else + /* since 10.4, this is the safe way to get the underlying CGL context */ + CGLContextObj cglContext; + if( aglGetCGLContext(p_vout->p_sys->agl_ctx, (void**)&cglContext) ) + { + CGLUnlockContext( cglContext ); + } +#endif +} diff --git a/modules/gui/minimal_macosx/voutgl.h b/modules/gui/minimal_macosx/voutgl.h new file mode 100644 index 0000000000000000000000000000000000000000..7dea3f133a8d14b110af25fa6832b34da574a27d --- /dev/null +++ b/modules/gui/minimal_macosx/voutgl.h @@ -0,0 +1,50 @@ +/***************************************************************************** + * voutgl.h: MacOS X OpenGL provider + ***************************************************************************** + * Copyright (C) 2001-2006 the VideoLAN team + * $Id$ + * + * Authors: Colin Delacroix <colin@zoy.org> + * Florian G. Pflug <fgp@phlo.org> + * Jon Lech Johansen <jon-vl@nanocrew.net> + * Eric Petit <titer@m0k.org> + * Benjamin Pracht <bigben at videolan dot org> + * + * This program 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. + * + * This program 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +#import <Cocoa/Cocoa.h> +#import "VLCOpenGLVoutView.h" +#import "voutagl.h" + +struct vout_sys_t +{ + NSAutoreleasePool * o_pool; + VLCOpenGLVoutView * o_glview; + vlc_bool_t b_saved_frame; + NSRect s_frame; + vlc_bool_t b_got_frame; + + /* Mozilla plugin-related variables */ + vlc_bool_t b_embedded; + AGLContext agl_ctx; + AGLDrawable agl_drawable; + int i_offx, i_offy; + int i_width, i_height; + WindowRef theWindow; + WindowGroupRef winGroup; + vlc_bool_t b_clipped_out; + Rect clipBounds, viewBounds; +}; diff --git a/modules/gui/minimal_macosx/voutgl.m b/modules/gui/minimal_macosx/voutgl.m new file mode 100644 index 0000000000000000000000000000000000000000..67d17c9a5ebe6a0c0a0dab0880cda1fe9bc06565 --- /dev/null +++ b/modules/gui/minimal_macosx/voutgl.m @@ -0,0 +1,92 @@ +/***************************************************************************** + * voutgl.m: MacOS X OpenGL provider + ***************************************************************************** + * Copyright (C) 2001-2004 the VideoLAN team + * $Id$ + * + * Authors: Colin Delacroix <colin@zoy.org> + * Florian G. Pflug <fgp@phlo.org> + * Jon Lech Johansen <jon-vl@nanocrew.net> + * Derk-Jan Hartman <hartman at videolan dot org> + * Eric Petit <titer@m0k.org> + * Benjamin Pracht <bigben at videolan dot org> + * Damien Fouilleul <damienf at videolan dot org> + * + * This program 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. + * + * This program 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + *****************************************************************************/ + +/***************************************************************************** + * Preamble + *****************************************************************************/ +#include "intf.h" +#include "voutgl.h" + +int E_(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 ); + } + + 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 ); + } + + memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) ); + + var_Get( p_vout->p_libvlc, "drawable", &value_drawable ); + + if( 0 /* Are we in the mozilla plugin ? XXX: get that from drawable */ ) + { + p_vout->pf_init = aglInit; + p_vout->pf_end = aglEnd; + p_vout->pf_manage = aglManage; + p_vout->pf_control = aglControl; + p_vout->pf_swap = aglSwap; + p_vout->pf_lock = aglLock; + p_vout->pf_unlock = aglUnlock; + } + else + { + /* Let's use the VLCOpenGLVoutView.m class */ + p_vout->pf_init = cocoaglvoutviewInit; + p_vout->pf_end = cocoaglvoutviewEnd; + p_vout->pf_manage = cocoaglvoutviewManage; + p_vout->pf_control= cocoaglvoutviewControl; + p_vout->pf_swap = cocoaglvoutviewSwap; + p_vout->pf_lock = cocoaglvoutviewLock; + p_vout->pf_unlock = cocoaglvoutviewUnlock; + } + p_vout->p_sys->b_got_frame = VLC_FALSE; + + return VLC_SUCCESS; +} + +void E_(CloseVideoGL) ( vlc_object_t * p_this ) +{ + vout_thread_t * p_vout = (vout_thread_t *) p_this; + /* Clean up */ + free( p_vout->p_sys ); +}