]> git.sesse.net Git - vlc/blob - modules/gui/macosx/vout.m
macosx: fail the video output if Quartz Extreme isn't supported, removed specific...
[vlc] / modules / gui / macosx / vout.m
1 /*****************************************************************************
2  * vout.m: MacOS X video output module
3  *****************************************************************************
4  * Copyright (C) 2002-2011 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Derk-Jan Hartman <hartman at videolan dot org>
8  *          Eric Petit <titer@m0k.org>
9  *          Benjamin Pracht <bigben at videolan dot org>
10  *          Pierre d'Herbemont <pdherbemont # videolan org>
11  *          Felix Paul Kühne <fkuehne at videolan dot org>
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  * 
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26  *****************************************************************************/
27
28 /*****************************************************************************
29  * Preamble
30  *****************************************************************************/
31 #import <stdlib.h>                                                 /* free() */
32 #import <string.h>
33
34 #import "intf.h"
35 #import "vout.h"
36 #import "CoreInteraction.h"
37 #import "MainMenu.h"
38 #import "MainWindow.h"
39
40 #import <vlc_common.h>
41 #import <vlc_vout_window.h>
42 #import <vlc_vout_display.h>
43 #import <vlc_keys.h>
44 /*****************************************************************************
45  * DeviceCallback: Callback triggered when the video-device variable is changed
46  *****************************************************************************/
47 int DeviceCallback( vlc_object_t *p_this, const char *psz_variable,
48                      vlc_value_t old_val, vlc_value_t new_val, void *param )
49 {
50     vlc_value_t val;
51     vout_thread_t *p_vout = (vout_thread_t *)p_this;
52
53     msg_Dbg( p_vout, "set %"PRId64, new_val.i_int );
54     var_Create( p_vout->p_libvlc, "video-device", VLC_VAR_INTEGER );
55     var_Set( p_vout->p_libvlc, "video-device", new_val );
56
57     val.b_bool = true;
58     var_Set( p_vout, "intf-change", val );
59     return VLC_SUCCESS;
60 }
61
62 /*****************************************************************************
63  * VLCVoutView implementation
64  *****************************************************************************/
65 @implementation VLCVoutView
66 - (void)setVoutView:(id)theView
67 {
68     vout_thread_t * p_vout = getVout();
69     if( !p_vout )
70         return;
71
72     int i_device;
73     NSArray *o_screens = [NSScreen screens];
74     if( [o_screens count] <= 0 )
75     {
76         msg_Err( VLCIntf, "no OSX screens available" );
77         return;
78     }
79
80     /* Get the pref value when this is the first time, otherwise retrieve the device from the top level video-device var */
81     if( var_Type( p_vout->p_libvlc, "video-device" ) == 0 )
82     {
83         i_device = var_GetInteger( p_vout, "macosx-vdev" );
84     }
85     else
86     {
87         i_device = var_GetInteger( p_vout->p_libvlc, "video-device" );
88     }
89
90     /* Setup the menuitem for the multiple displays. */
91     if( var_Type( p_vout, "video-device" ) == 0 )
92     {
93         int i = 1;
94         vlc_value_t val2, text;
95         NSScreen * o_screen;
96
97         var_Create( p_vout, "video-device", VLC_VAR_INTEGER |
98                    VLC_VAR_HASCHOICE );
99         text.psz_string = _("Fullscreen Video Device");
100         var_Change( p_vout, "video-device", VLC_VAR_SETTEXT, &text, NULL );
101
102         NSEnumerator * o_enumerator = [o_screens objectEnumerator];
103
104         val2.i_int = 0;
105         text.psz_string = _("Default");
106         var_Change( p_vout, "video-device", VLC_VAR_ADDCHOICE, &val2, &text );
107         var_Set( p_vout, "video-device", val2 );
108
109         while( (o_screen = [o_enumerator nextObject]) != NULL )
110         {
111             char psz_temp[255];
112             NSRect s_rect = [o_screen frame];
113
114             snprintf( psz_temp, sizeof(psz_temp)/sizeof(psz_temp[0])-1, "%s %d (%dx%d)", _("Screen"), i, (int)s_rect.size.width, (int)s_rect.size.height );
115
116             text.psz_string = psz_temp;
117             val2.i_int = (int)[o_screen displayID];
118             var_Change( p_vout, "video-device", VLC_VAR_ADDCHOICE, &val2, &text );
119             if( (int)[o_screen displayID] == i_device )
120             {
121                 var_Set( p_vout, "video-device", val2 );
122             }
123             i++;
124         }
125
126         var_AddCallback( p_vout, "video-device", DeviceCallback,
127                         NULL );
128
129         val2.b_bool = true;
130         var_Set( p_vout, "intf-change", val2 );
131     }
132
133     /* Add the view. It's automatically resized to fit the window */
134     if (o_view) {
135         [o_view removeFromSuperview];
136         [o_view release];
137     }
138     o_view = theView;
139     [o_view retain];
140     [self addSubview: o_view];
141     [self setAutoresizesSubviews: YES];
142
143     /* make sure that we look alright */
144     [[self window] setAlphaValue: var_CreateGetFloat( p_vout, "macosx-opaqueness" )];
145     vlc_object_release( p_vout );
146 }
147
148 - (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize
149 {
150     [super resizeSubviewsWithOldSize: oldBoundsSize];
151     [o_view setFrameSize: [self frame].size];
152 }
153
154 - (void)closeVout
155 {
156     /* Make sure we don't see a white flash */
157     [o_view removeFromSuperview];
158     [o_view release];
159     o_view = nil;
160 }
161
162 - (void)scrollWheel:(NSEvent *)theEvent
163 {
164     VLCControls * o_controls = (VLCControls *)[[NSApp delegate] controls];
165     [o_controls scrollWheel: theEvent];
166 }
167
168 - (void)keyDown:(NSEvent *)o_event
169 {
170     unichar key = 0;
171     vlc_value_t val;
172     unsigned int i_pressed_modifiers = 0;
173     val.i_int = 0;
174
175     i_pressed_modifiers = [o_event modifierFlags];
176
177     if( i_pressed_modifiers & NSShiftKeyMask )
178         val.i_int |= KEY_MODIFIER_SHIFT;
179     if( i_pressed_modifiers & NSControlKeyMask )
180         val.i_int |= KEY_MODIFIER_CTRL;
181     if( i_pressed_modifiers & NSAlternateKeyMask )
182         val.i_int |= KEY_MODIFIER_ALT;
183     if( i_pressed_modifiers & NSCommandKeyMask )
184         val.i_int |= KEY_MODIFIER_COMMAND;
185
186     key = [[[o_event charactersIgnoringModifiers] lowercaseString] characterAtIndex: 0];
187
188     if( key )
189     {
190         vout_thread_t * p_vout = getVout();
191         /* Escape should always get you out of fullscreen */
192         if( key == (unichar) 0x1b )
193         {
194             playlist_t * p_playlist = pl_Get( VLCIntf );
195              if( var_GetBool( p_playlist, "fullscreen") )
196                  [[VLCCoreInteraction sharedInstance] toggleFullscreen];
197         }
198         else if ( p_vout )
199         {
200             if( key == ' ')
201                 val.i_int = config_GetInt( p_vout, "key-play-pause" );
202             else
203                 val.i_int |= (int)CocoaKeyToVLC( key );
204             var_Set( p_vout->p_libvlc, "key-pressed", val );
205             vlc_object_release( p_vout );
206         }
207         else
208             msg_Dbg( VLCIntf, "could not send keyevent to VLC core" );
209     }
210     else
211         [super keyDown: o_event];
212 }
213
214 - (void)mouseDown:(NSEvent *)o_event
215 {
216     vout_thread_t * p_vout = getVout();
217     vlc_value_t val;
218     if( p_vout )
219     {
220         if( ( [o_event type] == NSLeftMouseDown ) &&
221           ( ! ( [o_event modifierFlags] &  NSControlKeyMask ) ) )
222         {
223             if( [o_event clickCount] <= 1 )
224             {
225                 /* single clicking */
226                 var_Get( p_vout, "mouse-button-down", &val );
227                 val.i_int |= 1;
228                 var_Set( p_vout, "mouse-button-down", val );
229             }
230             else
231             {
232                 /* multiple clicking */
233                 [[VLCCoreInteraction sharedInstance] toggleFullscreen];
234             }
235         }
236         else if( ( [o_event type] == NSRightMouseDown ) ||
237                ( ( [o_event type] == NSLeftMouseDown ) &&
238                  ( [o_event modifierFlags] &  NSControlKeyMask ) ) )
239         {
240             msg_Dbg( p_vout, "received NSRightMouseDown (generic method) or Ctrl clic" );
241             [NSMenu popUpContextMenu: [[VLCMainMenu sharedInstance] voutMenu] withEvent: o_event forView: self];
242         }
243         vlc_object_release( p_vout );
244     }
245
246     [super mouseDown: o_event];
247 }
248
249 - (void)otherMouseDown:(NSEvent *)o_event
250 {
251     if( [o_event type] == NSOtherMouseDown )
252     {
253         vout_thread_t * p_vout = getVout();
254         vlc_value_t val;
255
256         if (p_vout)
257         {
258             var_Get( p_vout, "mouse-button-down", &val );
259             val.i_int |= 2;
260             var_Set( p_vout, "mouse-button-down", val );
261         }
262         vlc_object_release( p_vout );
263     }
264
265     [super mouseDown: o_event];
266 }
267
268 - (void)rightMouseDown:(NSEvent *)o_event
269 {
270     if( [o_event type] == NSRightMouseDown )
271     {
272         vout_thread_t * p_vout = getVout();
273         if (p_vout)
274             [NSMenu popUpContextMenu: [[VLCMainMenu sharedInstance] voutMenu] withEvent: o_event forView: self];
275         vlc_object_release( p_vout );
276     }
277
278     [super mouseDown: o_event];
279 }
280
281 - (void)mouseUp:(NSEvent *)o_event
282 {
283     if( [o_event type] == NSLeftMouseUp )
284     {
285         vout_thread_t * p_vout = getVout();
286         if (p_vout)
287         {
288             vlc_value_t val;
289             int x, y;
290
291             var_GetCoords( p_vout, "mouse-moved", &x, &y );
292             var_SetCoords( p_vout, "mouse-clicked", x, y );
293
294             var_Get( p_vout, "mouse-button-down", &val );
295             val.i_int &= ~1;
296             var_Set( p_vout, "mouse-button-down", val );
297             vlc_object_release( p_vout );
298         }
299     }
300
301     [super mouseUp: o_event];
302 }
303
304 - (void)otherMouseUp:(NSEvent *)o_event
305 {
306     if( [o_event type] == NSOtherMouseUp )
307     {
308         vout_thread_t * p_vout = getVout();
309         if (p_vout)
310         {
311             vlc_value_t val;
312             var_Get( p_vout, "mouse-button-down", &val );
313             val.i_int &= ~2;
314             var_Set( p_vout, "mouse-button-down", val );
315             vlc_object_release( p_vout );
316         }
317     }
318
319     [super mouseUp: o_event];
320 }
321
322 - (void)rightMouseUp:(NSEvent *)o_event
323 {
324     if( [o_event type] == NSRightMouseUp )
325     {
326         vout_thread_t * p_vout = getVout();
327         if (p_vout)
328         {
329             [NSMenu popUpContextMenu: [[VLCMainMenu sharedInstance] voutMenu] withEvent: o_event forView: self];
330             vlc_object_release( p_vout );
331         }
332     }
333
334     [super mouseUp: o_event];
335 }
336
337 - (void)mouseDragged:(NSEvent *)o_event
338 {
339     [self mouseMoved: o_event];
340 }
341
342 - (void)otherMouseDragged:(NSEvent *)o_event
343 {
344     [self mouseMoved: o_event];
345 }
346
347 - (void)rightMouseDragged:(NSEvent *)o_event
348 {
349     [self mouseMoved: o_event];
350 }
351
352 - (void)mouseMoved:(NSEvent *)o_event
353 {
354     vout_thread_t * p_vout = getVout();
355     if( p_vout )
356     {
357         NSPoint ml;
358         NSRect s_rect;
359         BOOL b_inside;
360
361         s_rect = [o_view bounds];
362         ml = [o_view convertPoint: [o_event locationInWindow] fromView: nil];
363         b_inside = [o_view mouse: ml inRect: s_rect];
364
365         if( b_inside )
366         {
367             var_SetCoords( p_vout, "mouse-moved", ((int)ml.x), ((int)ml.y) );
368         }
369         vlc_object_release( p_vout );
370         [[VLCMain sharedInstance] showFullscreenController];
371     }
372
373     [super mouseMoved: o_event];
374 }
375
376 - (BOOL)mouseDownCanMoveWindow
377 {
378     return YES;
379 }
380
381 - (BOOL)acceptsFirstResponder
382 {
383     return YES;
384 }
385
386 - (BOOL)becomeFirstResponder
387 {
388     return YES;
389 }
390
391 - (BOOL)resignFirstResponder
392 {
393     /* We need to stay the first responder or we'll miss some
394        events */
395     return NO;
396 }
397 @end