]> git.sesse.net Git - vlc/commitdiff
modules/gui/minimal_macosx: Add a minimal_macosx interface and vout that is used...
authorPierre d'Herbemont <pdherbemont@videolan.org>
Wed, 29 Aug 2007 23:13:06 +0000 (23:13 +0000)
committerPierre d'Herbemont <pdherbemont@videolan.org>
Wed, 29 Aug 2007 23:13:06 +0000 (23:13 +0000)
12 files changed:
modules/gui/minimal_macosx/Modules.am [new file with mode: 0644]
modules/gui/minimal_macosx/VLCMinimalVoutWindow.h [new file with mode: 0644]
modules/gui/minimal_macosx/VLCMinimalVoutWindow.m [new file with mode: 0644]
modules/gui/minimal_macosx/VLCOpenGLVoutView.h [new file with mode: 0644]
modules/gui/minimal_macosx/VLCOpenGLVoutView.m [new file with mode: 0644]
modules/gui/minimal_macosx/intf.h [new file with mode: 0644]
modules/gui/minimal_macosx/intf.m [new file with mode: 0644]
modules/gui/minimal_macosx/macosx.c [new file with mode: 0644]
modules/gui/minimal_macosx/voutagl.h [new file with mode: 0644]
modules/gui/minimal_macosx/voutagl.m [new file with mode: 0644]
modules/gui/minimal_macosx/voutgl.h [new file with mode: 0644]
modules/gui/minimal_macosx/voutgl.m [new file with mode: 0644]

diff --git a/modules/gui/minimal_macosx/Modules.am b/modules/gui/minimal_macosx/Modules.am
new file mode 100644 (file)
index 0000000..2d59924
--- /dev/null
@@ -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 (file)
index 0000000..4d889d2
--- /dev/null
@@ -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 (file)
index 0000000..8a69fdc
--- /dev/null
@@ -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 (file)
index 0000000..df1b05f
--- /dev/null
@@ -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 (file)
index 0000000..aa7fe06
--- /dev/null
@@ -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 (file)
index 0000000..a43b902
--- /dev/null
@@ -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\9fhne <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 (file)
index 0000000..62638e7
--- /dev/null
@@ -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\9fhne <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 (file)
index 0000000..80722bf
--- /dev/null
@@ -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 (file)
index 0000000..013a307
--- /dev/null
@@ -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 (file)
index 0000000..9c6af42
--- /dev/null
@@ -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, &param);
+        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 (file)
index 0000000..7dea3f1
--- /dev/null
@@ -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 (file)
index 0000000..67d17c9
--- /dev/null
@@ -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 );
+}