]> git.sesse.net Git - vlc/blob - modules/gui/minimal_macosx/VLCOpenGLVoutView.m
Remove unneeded VOUT_CLOSE.
[vlc] / modules / gui / minimal_macosx / VLCOpenGLVoutView.m
1 /*****************************************************************************
2  * VLCOpenGLVoutView.m: MacOS X OpenGL provider
3  *****************************************************************************
4  * Copyright (C) 2001-2007 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Colin Delacroix <colin@zoy.org>
8  *          Florian G. Pflug <fgp@phlo.org>
9  *          Jon Lech Johansen <jon-vl@nanocrew.net>
10  *          Derk-Jan Hartman <hartman at videolan dot org>
11  *          Eric Petit <titer@m0k.org>
12  *          Benjamin Pracht <bigben at videolan dot org>
13  *          Damien Fouilleul <damienf at videolan dot org>
14  *          Pierre d'Herbemont <pdherbemont at videolan dot org>
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 2 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
29  *****************************************************************************/
30
31 /*****************************************************************************
32  * Preamble
33  *****************************************************************************/
34 #include "intf.h"
35 #include "voutgl.h"
36 #include "VLCOpenGLVoutView.h"
37 #include "VLCMinimalVoutWindow.h"
38
39 #include <OpenGL/OpenGL.h>
40 #include <OpenGL/gl.h>
41
42 /*****************************************************************************
43  * cocoaglvoutviewInit
44  *****************************************************************************/
45 int cocoaglvoutviewInit( vout_thread_t * p_vout )
46 {
47     vlc_value_t value_drawable;
48     id <VLCOpenGLVoutEmbedding> o_cocoaglview_container;
49
50     msg_Dbg( p_vout, "Mac OS X Vout is opening" );
51
52     var_Create( p_vout, "drawable", VLC_VAR_DOINHERIT );
53     var_Get( p_vout, "drawable", &value_drawable );
54
55     p_vout->p_sys->o_pool = [[NSAutoreleasePool alloc] init];
56
57     o_cocoaglview_container = (id) value_drawable.i_int;
58     if (!o_cocoaglview_container)
59     {
60         msg_Warn( p_vout, "No drawable!, spawing a window" );
61     }
62
63     p_vout->p_sys->b_embedded = false;
64
65
66     /* Create the GL view */
67     struct args { vout_thread_t * p_vout; id <VLCOpenGLVoutEmbedding> container; } args = { p_vout, o_cocoaglview_container };
68
69     [VLCOpenGLVoutView performSelectorOnMainThread:@selector(autoinitOpenGLVoutViewIntVoutWithContainer:)
70                         withObject:[NSData dataWithBytes: &args length: sizeof(struct args)] waitUntilDone:YES];
71
72     [[p_vout->p_sys->o_glview openGLContext] makeCurrentContext];
73     return VLC_SUCCESS;
74 }
75
76 /*****************************************************************************
77  * cocoaglvoutviewEnd
78  *****************************************************************************/
79 void cocoaglvoutviewEnd( vout_thread_t * p_vout )
80 {
81     id <VLCOpenGLVoutEmbedding> o_cocoaglview_container;
82
83     msg_Dbg( p_vout, "Mac OS X Vout is closing" );
84     var_Destroy( p_vout, "drawable" );
85
86     o_cocoaglview_container = [p_vout->p_sys->o_glview container];
87
88     /* Make sure our view won't request the vout now */
89     [p_vout->p_sys->o_glview detachFromVout];
90     msg_Dbg( p_vout, "Mac OS X Vout is closing" );
91
92     /* Let the view go, _without_blocking_ */
93     [p_vout->p_sys->o_glview performSelectorOnMainThread:@selector(removeFromSuperview) withObject:NULL waitUntilDone:NO];
94
95     if( [(id)o_cocoaglview_container respondsToSelector:@selector(removeVoutSubview:)] )
96         [o_cocoaglview_container removeVoutSubview: p_vout->p_sys->o_glview];
97
98     [p_vout->p_sys->o_glview release];
99
100     [p_vout->p_sys->o_pool release];
101  
102 }
103
104 /*****************************************************************************
105  * cocoaglvoutviewManage
106  *****************************************************************************/
107 int cocoaglvoutviewManage( vout_thread_t * p_vout )
108 {
109     if( p_vout->i_changes & VOUT_ASPECT_CHANGE )
110     {
111         [p_vout->p_sys->o_glview reshape];
112         p_vout->i_changes &= ~VOUT_ASPECT_CHANGE;
113     }
114     if( p_vout->i_changes & VOUT_CROP_CHANGE )
115     {
116         [p_vout->p_sys->o_glview reshape];
117         p_vout->i_changes &= ~VOUT_CROP_CHANGE;
118     }
119
120     if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
121     {
122         NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
123
124         p_vout->b_fullscreen = !p_vout->b_fullscreen;
125
126         if( p_vout->b_fullscreen )
127             [[p_vout->p_sys->o_glview container] enterFullscreen];
128         else
129             [[p_vout->p_sys->o_glview container] leaveFullscreen];
130
131         [o_pool release];
132
133         p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
134     }
135
136     //[[p_vout->p_sys->o_glview container] manage];
137     return VLC_SUCCESS;
138 }
139
140 /*****************************************************************************
141  * cocoaglvoutviewControl: control facility for the vout
142  *****************************************************************************/
143 int cocoaglvoutviewControl( vout_thread_t *p_vout, int i_query, va_list args )
144 {
145     bool b_arg;
146
147     switch( i_query )
148     {
149         case VOUT_SET_STAY_ON_TOP:
150             b_arg = (bool) va_arg( args, int );
151             [[p_vout->p_sys->o_glview container] setOnTop: b_arg];
152             return VLC_SUCCESS;
153
154         case VOUT_REPARENT:
155         default:
156             return vout_vaControlDefault( p_vout, i_query, args );
157     }
158 }
159
160 /*****************************************************************************
161  * cocoaglvoutviewSwap
162  *****************************************************************************/
163 void cocoaglvoutviewSwap( vout_thread_t * p_vout )
164 {
165     p_vout->p_sys->b_got_frame = true;
166     [[p_vout->p_sys->o_glview openGLContext] flushBuffer];
167 }
168
169 /*****************************************************************************
170  * cocoaglvoutviewLock
171  *****************************************************************************/
172 int cocoaglvoutviewLock( vout_thread_t * p_vout )
173 {
174     if( kCGLNoError == CGLLockContext([[p_vout->p_sys->o_glview openGLContext] CGLContextObj]) )
175     {
176         [[p_vout->p_sys->o_glview openGLContext] makeCurrentContext];
177         return 0;
178     }
179     return 1;
180 }
181
182 /*****************************************************************************
183  * cocoaglvoutviewUnlock
184  *****************************************************************************/
185 void cocoaglvoutviewUnlock( vout_thread_t * p_vout )
186 {
187     CGLUnlockContext([[p_vout->p_sys->o_glview openGLContext] CGLContextObj]);
188 }
189
190 /*****************************************************************************
191  * VLCOpenGLVoutView implementation
192  *****************************************************************************/
193 @implementation VLCOpenGLVoutView
194
195 /* Init a new gl view and register it to both the framework and the
196  * vout_thread_t. Must be called from main thread. */
197 + (void) autoinitOpenGLVoutViewIntVoutWithContainer: (NSData *) argsAsData
198 {
199     NSAutoreleasePool   *pool = [[NSAutoreleasePool alloc] init];
200     struct args { vout_thread_t * p_vout; id <VLCOpenGLVoutEmbedding> container; } *
201         args = (struct args *)[argsAsData bytes];
202     VLCOpenGLVoutView * oglview;
203
204     if( !args->container )
205     {
206         args->container = [[VLCMinimalVoutWindow alloc] initWithContentRect: NSMakeRect( 0, 0, args->p_vout->i_window_width, args->p_vout->i_window_height )];
207         [(VLCMinimalVoutWindow *)args->container makeKeyAndOrderFront: nil];
208     }
209     oglview = [[VLCOpenGLVoutView alloc] initWithVout: args->p_vout container: args->container];
210
211     args->p_vout->p_sys->o_glview = oglview;
212     [args->container addVoutSubview: oglview];
213
214     [pool release];
215 }
216
217 - (void)dealloc
218 {
219     [objectLock dealloc];
220     [super dealloc];
221 }
222
223 - (void)removeFromSuperview
224 {
225     [super removeFromSuperview];
226 }
227
228
229 - (id) initWithVout: (vout_thread_t *) vout container: (id <VLCOpenGLVoutEmbedding>) aContainer
230 {
231     NSOpenGLPixelFormatAttribute attribs[] =
232     {
233         NSOpenGLPFADoubleBuffer,
234         NSOpenGLPFAAccelerated,
235         NSOpenGLPFANoRecovery,
236         NSOpenGLPFAColorSize, 24,
237         NSOpenGLPFAAlphaSize, 8,
238         NSOpenGLPFADepthSize, 24,
239         NSOpenGLPFAWindow,
240         0
241     };
242
243     NSOpenGLPixelFormat * fmt = [[NSOpenGLPixelFormat alloc]
244         initWithAttributes: attribs];
245
246     if( !fmt )
247     {
248         msg_Warn( p_vout, "could not create OpenGL video output" );
249         return nil;
250     }
251
252     if( self = [super initWithFrame: NSMakeRect(0,0,10,10) pixelFormat: fmt] )
253     {
254         p_vout = vout;
255         container = aContainer;
256         objectLock = [[NSLock alloc] init];
257
258         [fmt release];
259
260         [[self openGLContext] makeCurrentContext];
261         [[self openGLContext] update];
262
263         /* Swap buffers only during the vertical retrace of the monitor.
264         http://developer.apple.com/documentation/GraphicsImaging/
265         Conceptual/OpenGL/chap5/chapter_5_section_44.html */
266         GLint params[] = { 1 };
267         CGLSetParameter( CGLGetCurrentContext(), kCGLCPSwapInterval,
268                      params );
269     }
270     return self;
271 }
272
273 - (void) detachFromVout
274 {
275     [objectLock lock];
276     p_vout = NULL;
277     [objectLock unlock];
278 }
279
280 - (id <VLCOpenGLVoutEmbedding>) container
281 {
282     return container;
283 }
284
285 - (void) destroyVout
286 {
287     [objectLock lock];
288     if( p_vout )
289     {
290         vlc_object_detach( p_vout );
291         vlc_object_release( p_vout );
292         vlc_object_release( p_vout );
293     }
294     [objectLock unlock];
295 }
296
297 - (void) reshape
298 {
299     int x, y;
300     vlc_value_t val;
301
302     [objectLock lock];
303     if( !p_vout )
304     {
305         [objectLock unlock];
306         return;
307     }
308
309     cocoaglvoutviewLock( p_vout );
310     NSRect bounds = [self bounds];
311
312     if( [[self container] stretchesVideo] )
313     {
314         x = bounds.size.width;
315         y = bounds.size.height;
316     }
317     else if( bounds.size.height * p_vout->fmt_in.i_visible_width *
318              p_vout->fmt_in.i_sar_num <
319              bounds.size.width * p_vout->fmt_in.i_visible_height *
320              p_vout->fmt_in.i_sar_den )
321     {
322         x = ( bounds.size.height * p_vout->fmt_in.i_visible_width *
323               p_vout->fmt_in.i_sar_num ) /
324             ( p_vout->fmt_in.i_visible_height * p_vout->fmt_in.i_sar_den);
325
326         y = bounds.size.height;
327     }
328     else
329     {
330         x = bounds.size.width;
331         y = ( bounds.size.width * p_vout->fmt_in.i_visible_height *
332               p_vout->fmt_in.i_sar_den) /
333             ( p_vout->fmt_in.i_visible_width * p_vout->fmt_in.i_sar_num  );
334     }
335
336     glViewport( ( bounds.size.width - x ) / 2,
337                 ( bounds.size.height - y ) / 2, x, y );
338
339     if( p_vout->p_sys->b_got_frame )
340     {
341         /* Ask the opengl module to redraw */
342         vout_thread_t * p_parent;
343         p_parent = (vout_thread_t *) p_vout->p_parent;
344         cocoaglvoutviewUnlock( p_vout );
345         if( p_parent && p_parent->pf_display )
346         {
347             p_parent->pf_display( p_parent, NULL );
348         }
349     }
350     else
351     {
352         glClear( GL_COLOR_BUFFER_BIT );
353         cocoaglvoutviewUnlock( p_vout );
354     }
355     [objectLock unlock];
356     [super reshape];
357 }
358
359 - (void) update
360 {
361     if( kCGLNoError != CGLLockContext([[self openGLContext] CGLContextObj]) )
362         return;
363     [super update];
364     CGLUnlockContext([[p_vout->p_sys->o_glview openGLContext] CGLContextObj]);
365 }
366
367 - (void) drawRect: (NSRect) rect
368 {
369     if( kCGLNoError != CGLLockContext([[self openGLContext] CGLContextObj]) )
370         return;
371     [[self openGLContext] flushBuffer];
372     [super drawRect:rect];
373     CGLUnlockContext([[p_vout->p_sys->o_glview openGLContext] CGLContextObj]);
374 }
375
376 - (BOOL)mouseDownCanMoveWindow
377 {
378     return YES;
379 }
380 @end
381