1 /*****************************************************************************
2 * VideoView.m: MacOS X video output module
3 *****************************************************************************
4 * Copyright (C) 2002-2011 VLC authors and VideoLAN
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>
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.
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.
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 *****************************************************************************/
28 /*****************************************************************************
30 *****************************************************************************/
31 #import <stdlib.h> /* free() */
36 #import "CoreInteraction.h"
38 #import "MainWindow.h"
40 #import <vlc_common.h>
41 #import <vlc_vout_window.h>
42 #import <vlc_vout_display.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 )
51 vout_thread_t *p_vout = (vout_thread_t *)p_this;
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 );
58 var_Set( p_vout, "intf-change", val );
62 /*****************************************************************************
63 * VLCVoutView implementation
64 *****************************************************************************/
65 @implementation VLCVoutView
66 - (void)setVoutView:(id)theView
68 vout_thread_t * p_vout = getVout();
73 NSArray *o_screens = [NSScreen screens];
74 if( [o_screens count] <= 0 )
76 msg_Err( VLCIntf, "no OSX screens available" );
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 )
83 i_device = var_GetInteger( p_vout, "macosx-vdev" );
87 i_device = var_GetInteger( p_vout->p_libvlc, "video-device" );
90 /* Setup the menuitem for the multiple displays. */
91 if( var_Type( p_vout, "video-device" ) == 0 )
94 vlc_value_t val2, text;
97 var_Create( p_vout, "video-device", VLC_VAR_INTEGER |
99 text.psz_string = _("Fullscreen Video Device");
100 var_Change( p_vout, "video-device", VLC_VAR_SETTEXT, &text, NULL );
102 NSEnumerator * o_enumerator = [o_screens objectEnumerator];
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 );
109 while( (o_screen = [o_enumerator nextObject]) != NULL )
112 NSRect s_rect = [o_screen frame];
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 );
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 )
121 var_Set( p_vout, "video-device", val2 );
126 var_AddCallback( p_vout, "video-device", DeviceCallback,
130 var_Set( p_vout, "intf-change", val2 );
133 /* Add the view. It's automatically resized to fit the window */
135 [o_view removeFromSuperview];
140 [self addSubview: o_view];
141 [self setAutoresizesSubviews: YES];
143 /* make sure that we look alright */
144 [[self window] setAlphaValue: var_CreateGetFloat( p_vout, "macosx-opaqueness" )];
145 vlc_object_release( p_vout );
148 - (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize
150 [super resizeSubviewsWithOldSize: oldBoundsSize];
151 [o_view setFrameSize: [self frame].size];
156 vout_thread_t * p_vout = getVout();
159 var_DelCallback( p_vout, "video-device", DeviceCallback, NULL );
160 vlc_object_release( p_vout );
163 /* Make sure we don't see a white flash */
164 [o_view removeFromSuperview];
169 - (void)scrollWheel:(NSEvent *)theEvent
171 VLCControls * o_controls = (VLCControls *)[[NSApp delegate] controls];
172 [o_controls scrollWheel: theEvent];
175 - (void)keyDown:(NSEvent *)o_event
179 unsigned int i_pressed_modifiers = 0;
182 i_pressed_modifiers = [o_event modifierFlags];
184 if( i_pressed_modifiers & NSShiftKeyMask )
185 val.i_int |= KEY_MODIFIER_SHIFT;
186 if( i_pressed_modifiers & NSControlKeyMask )
187 val.i_int |= KEY_MODIFIER_CTRL;
188 if( i_pressed_modifiers & NSAlternateKeyMask )
189 val.i_int |= KEY_MODIFIER_ALT;
190 if( i_pressed_modifiers & NSCommandKeyMask )
191 val.i_int |= KEY_MODIFIER_COMMAND;
193 key = [[[o_event charactersIgnoringModifiers] lowercaseString] characterAtIndex: 0];
197 vout_thread_t * p_vout = getVout();
198 /* Escape should always get you out of fullscreen */
199 if( key == (unichar) 0x1b )
201 playlist_t * p_playlist = pl_Get( VLCIntf );
202 if( var_GetBool( p_playlist, "fullscreen") )
203 [[VLCCoreInteraction sharedInstance] toggleFullscreen];
208 val.i_int = config_GetInt( p_vout, "key-play-pause" );
210 val.i_int |= (int)CocoaKeyToVLC( key );
211 var_Set( p_vout->p_libvlc, "key-pressed", val );
212 vlc_object_release( p_vout );
215 msg_Dbg( VLCIntf, "could not send keyevent to VLC core" );
218 [super keyDown: o_event];
221 - (void)mouseDown:(NSEvent *)o_event
223 vout_thread_t * p_vout = getVout();
227 if( ( [o_event type] == NSLeftMouseDown ) &&
228 ( ! ( [o_event modifierFlags] & NSControlKeyMask ) ) )
230 if( [o_event clickCount] <= 1 )
232 /* single clicking */
233 var_Get( p_vout, "mouse-button-down", &val );
235 var_Set( p_vout, "mouse-button-down", val );
239 /* multiple clicking */
240 [[VLCCoreInteraction sharedInstance] toggleFullscreen];
243 else if( ( [o_event type] == NSRightMouseDown ) ||
244 ( ( [o_event type] == NSLeftMouseDown ) &&
245 ( [o_event modifierFlags] & NSControlKeyMask ) ) )
247 msg_Dbg( p_vout, "received NSRightMouseDown (generic method) or Ctrl clic" );
248 [NSMenu popUpContextMenu: [[VLCMainMenu sharedInstance] voutMenu] withEvent: o_event forView: self];
250 vlc_object_release( p_vout );
253 [super mouseDown: o_event];
256 - (void)otherMouseDown:(NSEvent *)o_event
258 if( [o_event type] == NSOtherMouseDown )
260 vout_thread_t * p_vout = getVout();
265 var_Get( p_vout, "mouse-button-down", &val );
267 var_Set( p_vout, "mouse-button-down", val );
269 vlc_object_release( p_vout );
272 [super mouseDown: o_event];
275 - (void)rightMouseDown:(NSEvent *)o_event
277 if( [o_event type] == NSRightMouseDown )
279 vout_thread_t * p_vout = getVout();
281 [NSMenu popUpContextMenu: [[VLCMainMenu sharedInstance] voutMenu] withEvent: o_event forView: self];
282 vlc_object_release( p_vout );
285 [super mouseDown: o_event];
288 - (void)mouseUp:(NSEvent *)o_event
290 if( [o_event type] == NSLeftMouseUp )
292 vout_thread_t * p_vout = getVout();
298 var_GetCoords( p_vout, "mouse-moved", &x, &y );
299 var_SetCoords( p_vout, "mouse-clicked", x, y );
301 var_Get( p_vout, "mouse-button-down", &val );
303 var_Set( p_vout, "mouse-button-down", val );
304 vlc_object_release( p_vout );
308 [super mouseUp: o_event];
311 - (void)otherMouseUp:(NSEvent *)o_event
313 if( [o_event type] == NSOtherMouseUp )
315 vout_thread_t * p_vout = getVout();
319 var_Get( p_vout, "mouse-button-down", &val );
321 var_Set( p_vout, "mouse-button-down", val );
322 vlc_object_release( p_vout );
326 [super mouseUp: o_event];
329 - (void)rightMouseUp:(NSEvent *)o_event
331 if( [o_event type] == NSRightMouseUp )
333 vout_thread_t * p_vout = getVout();
336 [NSMenu popUpContextMenu: [[VLCMainMenu sharedInstance] voutMenu] withEvent: o_event forView: self];
337 vlc_object_release( p_vout );
341 [super mouseUp: o_event];
344 - (void)mouseDragged:(NSEvent *)o_event
346 [self mouseMoved: o_event];
349 - (void)otherMouseDragged:(NSEvent *)o_event
351 [self mouseMoved: o_event];
354 - (void)rightMouseDragged:(NSEvent *)o_event
356 [self mouseMoved: o_event];
359 - (void)mouseMoved:(NSEvent *)o_event
361 vout_thread_t * p_vout = getVout();
368 s_rect = [o_view bounds];
369 ml = [o_view convertPoint: [o_event locationInWindow] fromView: nil];
370 b_inside = [o_view mouse: ml inRect: s_rect];
374 var_SetCoords( p_vout, "mouse-moved", ((int)ml.x), ((int)ml.y) );
376 vlc_object_release( p_vout );
377 [[VLCMain sharedInstance] showFullscreenController];
380 [super mouseMoved: o_event];
383 - (BOOL)mouseDownCanMoveWindow
388 - (BOOL)acceptsFirstResponder
393 - (BOOL)becomeFirstResponder
398 - (BOOL)resignFirstResponder
400 /* We need to stay the first responder or we'll miss some
407 [[self window] disableScreenUpdatesUntilFlush];