1 /*****************************************************************************
2 * controls.m: MacOS X interface module
3 *****************************************************************************
4 * Copyright (C) 2002-2012 VLC authors and VideoLAN
7 * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8 * Christophe Massiot <massiot@via.ecp.fr>
9 * Derk-Jan Hartman <hartman at videolan dot org>
10 * Benjamin Pracht <bigben at videolan doit 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 #include <stdlib.h> /* malloc(), free() */
32 #include <sys/param.h> /* for MAXPATHLEN */
41 #import "CoreInteraction.h"
45 /*****************************************************************************
46 * VLCControls implementation
47 *****************************************************************************/
48 @implementation VLCControls
52 [o_specificTime_mi setTitle: _NS("Jump To Time")];
53 [o_specificTime_cancel_btn setTitle: _NS("Cancel")];
54 [o_specificTime_ok_btn setTitle: _NS("OK")];
55 [o_specificTime_sec_lbl setStringValue: _NS("sec.")];
56 [o_specificTime_goTo_lbl setStringValue: _NS("Jump to time")];
58 i_lastScrollWheelDirection = 0;
64 [[NSNotificationCenter defaultCenter] removeObserver: self];
69 - (IBAction)play:(id)sender
71 [[VLCCoreInteraction sharedInstance] play];
74 - (IBAction)stop:(id)sender
76 [[VLCCoreInteraction sharedInstance] stop];
79 - (IBAction)prev:(id)sender
81 [[VLCCoreInteraction sharedInstance] previous];
84 - (IBAction)next:(id)sender
86 [[VLCCoreInteraction sharedInstance] next];
89 - (IBAction)random:(id)sender
91 [[VLCCoreInteraction sharedInstance] shuffle];
94 - (IBAction)repeat:(id)sender
97 intf_thread_t * p_intf = VLCIntf;
98 playlist_t * p_playlist = pl_Get( p_intf );
100 var_Get( p_playlist, "repeat", &val );
102 [[VLCCoreInteraction sharedInstance] repeatOne];
104 [[VLCCoreInteraction sharedInstance] repeatOff];
107 - (IBAction)loop:(id)sender
110 intf_thread_t * p_intf = VLCIntf;
111 playlist_t * p_playlist = pl_Get( p_intf );
113 var_Get( p_playlist, "loop", &val );
115 [[VLCCoreInteraction sharedInstance] repeatAll];
117 [[VLCCoreInteraction sharedInstance] repeatOff];
120 - (IBAction)quitAfterPlayback:(id)sender
123 playlist_t * p_playlist = pl_Get( VLCIntf );
124 var_ToggleBool( p_playlist, "play-and-exit" );
127 - (IBAction)forward:(id)sender
129 [[VLCCoreInteraction sharedInstance] forward];
132 - (IBAction)backward:(id)sender
134 [[VLCCoreInteraction sharedInstance] backward];
137 - (IBAction)volumeUp:(id)sender
139 [[VLCCoreInteraction sharedInstance] volumeUp];
142 - (IBAction)volumeDown:(id)sender
144 [[VLCCoreInteraction sharedInstance] volumeDown];
147 - (IBAction)mute:(id)sender
149 [[VLCCoreInteraction sharedInstance] mute];
152 - (IBAction)volumeSliderUpdated:(id)sender
154 [[VLCCoreInteraction sharedInstance] setVolume: [sender intValue]];
157 - (IBAction)showPosition: (id)sender
159 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
160 if( p_input != NULL )
162 vout_thread_t *p_vout = input_GetVout( p_input );
165 var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_POSITION );
166 vlc_object_release( p_vout );
168 vlc_object_release( p_input );
172 - (IBAction)telxTransparent:(id)sender
175 p_vbi = (vlc_object_t *) vlc_object_find_name( pl_Get( VLCIntf ), "zvbi" );
178 var_SetBool( p_vbi, "vbi-opaque", [sender state] );
179 [sender setState: ![sender state]];
180 vlc_object_release( p_vbi );
184 - (IBAction)telxNavLink:(id)sender
186 intf_thread_t * p_intf = VLCIntf;
190 if( [[sender title] isEqualToString: _NS("Index")] )
192 else if( [[sender title] isEqualToString: _NS("Red")] )
194 else if( [[sender title] isEqualToString: _NS("Green")] )
196 else if( [[sender title] isEqualToString: _NS("Yellow")] )
198 else if( [[sender title] isEqualToString: _NS("Blue")] )
200 if( i_page == 0 ) return;
202 p_vbi = (vlc_object_t *) vlc_object_find_name( pl_Get( VLCIntf ), "zvbi" );
205 var_SetInteger( p_vbi, "vbi-page", i_page );
206 vlc_object_release( p_vbi );
210 - (IBAction)lockVideosAspectRatio:(id)sender
212 [[VLCCoreInteraction sharedInstance] setAspectRatioLocked: ![sender state]];
213 [sender setState: [[VLCCoreInteraction sharedInstance] aspectRatioIsLocked]];
216 - (IBAction)addSubtitleFile:(id)sender
218 NSInteger i_returnValue = 0;
219 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
220 if( !p_input ) return;
222 input_item_t *p_item = input_GetItem( p_input );
225 vlc_object_release( p_input );
229 char *path = input_item_GetURI( p_item );
230 if( !path ) path = strdup( "" );
232 NSOpenPanel * openPanel = [NSOpenPanel openPanel];
233 [openPanel setCanChooseFiles: YES];
234 [openPanel setCanChooseDirectories: NO];
235 [openPanel setAllowsMultipleSelection: YES];
236 [openPanel setAllowedFileTypes: [NSArray arrayWithObjects: @"cdg",@"@idx",@"srt",@"sub",@"utf",@"ass",@"ssa",@"aqt",@"jss",@"psb",@"rt",@"smi",@"txt",@"smil", nil]];
237 [openPanel setDirectoryURL:[NSURL fileURLWithPath:[[NSString stringWithUTF8String:path] stringByExpandingTildeInPath]]];
238 i_returnValue = [openPanel runModal];
241 if( i_returnValue == NSOKButton )
244 if( !p_input ) return;
246 c = [[openPanel URLs] count];
248 for (int i = 0; i < c ; i++)
250 msg_Dbg( VLCIntf, "loading subs from %s", [[[[openPanel URLs] objectAtIndex: i] path] UTF8String] );
251 if( input_AddSubtitle( p_input, [[[[openPanel URLs] objectAtIndex: i] path] UTF8String], TRUE ) )
252 msg_Warn( VLCIntf, "unable to load subtitles from '%s'",
253 [[[[openPanel URLs] objectAtIndex: i] path] UTF8String] );
256 vlc_object_release( p_input );
259 - (void)resetScrollWheelDirection
261 /* release the scroll direction 0.8 secs after the last event */
262 if (([NSDate timeIntervalSinceReferenceDate] - t_lastScrollEvent) >= 0.80)
263 i_lastScrollWheelDirection = 0;
266 - (void)scrollWheel:(NSEvent *)theEvent
268 intf_thread_t * p_intf = VLCIntf;
269 BOOL b_invertedEventFromDevice = NO;
270 CGFloat f_deltaY, f_deltaX = .0;
274 if ([theEvent isDirectionInvertedFromDevice])
275 b_invertedEventFromDevice = YES;
278 f_deltaY = [theEvent deltaY];
279 f_deltaX = [theEvent deltaX];
281 CGFloat f_yabsvalue = f_deltaY > 0.0f ? f_deltaY : -f_deltaY;
282 CGFloat f_xabsvalue = f_deltaX > 0.0f ? f_deltaX : -f_deltaX;
284 int i_yvlckey, i_xvlckey = 0;
286 if (b_invertedEventFromDevice)
289 i_yvlckey = KEY_MOUSEWHEELDOWN;
291 i_yvlckey = KEY_MOUSEWHEELUP;
294 i_xvlckey = KEY_MOUSEWHEELRIGHT;
296 i_xvlckey = KEY_MOUSEWHEELLEFT;
301 i_yvlckey = KEY_MOUSEWHEELDOWN;
303 i_yvlckey = KEY_MOUSEWHEELUP;
306 i_xvlckey = KEY_MOUSEWHEELRIGHT;
308 i_xvlckey = KEY_MOUSEWHEELLEFT;
311 /* in the following, we're forwarding either a x or a y event */
312 /* Multiple key events are send depending on the intensity of the event */
313 /* the opposite direction is being blocked for 0.8 secs */
314 if (f_yabsvalue > 0.05)
316 if (i_lastScrollWheelDirection < 0) // last was a X
319 i_lastScrollWheelDirection = 1; // Y
320 for (NSUInteger i = 0; i < (int)(f_yabsvalue/4.+1.) && f_yabsvalue > 0.05 ; i++)
321 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_yvlckey );
323 t_lastScrollEvent = [NSDate timeIntervalSinceReferenceDate];
324 [self performSelector:@selector(resetScrollWheelDirection)
329 if (f_xabsvalue > 0.05)
331 if (i_lastScrollWheelDirection > 0) // last was a Y
334 i_lastScrollWheelDirection = -1; // X
335 for (NSUInteger i = 0; i < (int)(f_xabsvalue/6.+1.) && f_xabsvalue > 0.05; i++)
336 var_SetInteger( p_intf->p_libvlc, "key-pressed", i_xvlckey );
338 t_lastScrollEvent = [NSDate timeIntervalSinceReferenceDate];
339 [self performSelector:@selector(resetScrollWheelDirection)
345 - (BOOL)keyEvent:(NSEvent *)o_event
347 BOOL eventHandled = NO;
348 unichar key = [[o_event charactersIgnoringModifiers] characterAtIndex: 0];
352 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
353 if( p_input != NULL )
355 vout_thread_t *p_vout = input_GetVout( p_input );
360 if( key == (unichar) 0x1b )
362 if (var_GetBool( p_vout, "fullscreen" ))
364 [[VLCCoreInteraction sharedInstance] toggleFullscreen];
368 else if( key == ' ' )
373 vlc_object_release( p_vout );
375 vlc_object_release( p_input );
381 - (IBAction)goToSpecificTime:(id)sender
383 if( sender == o_specificTime_cancel_btn )
385 [NSApp endSheet: o_specificTime_win];
386 [o_specificTime_win close];
388 else if( sender == o_specificTime_ok_btn )
390 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
393 int64_t timeInSec = 0;
394 NSString * fieldContent = [o_specificTime_enter_fld stringValue];
395 if( [[fieldContent componentsSeparatedByString: @":"] count] > 1 &&
396 [[fieldContent componentsSeparatedByString: @":"] count] <= 3 )
398 NSArray * ourTempArray = \
399 [fieldContent componentsSeparatedByString: @":"];
401 if( [[fieldContent componentsSeparatedByString: @":"] count] == 3 )
403 timeInSec += ([[ourTempArray objectAtIndex: 0] intValue] * 3600); //h
404 timeInSec += ([[ourTempArray objectAtIndex: 1] intValue] * 60); //m
405 timeInSec += [[ourTempArray objectAtIndex: 2] intValue]; //s
409 timeInSec += ([[ourTempArray objectAtIndex: 0] intValue] * 60); //m
410 timeInSec += [[ourTempArray objectAtIndex: 1] intValue]; //s
414 timeInSec = [fieldContent intValue];
416 input_Control( p_input, INPUT_SET_TIME, (int64_t)(timeInSec * 1000000));
417 vlc_object_release( p_input );
420 [NSApp endSheet: o_specificTime_win];
421 [o_specificTime_win close];
425 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
428 /* we can obviously only do that if an input is available */
429 vlc_value_t pos, length;
430 var_Get( p_input, "time", &pos );
431 [o_specificTime_enter_fld setIntValue: (pos.i_time / 1000000)];
432 var_Get( p_input, "length", &length );
433 [o_specificTime_stepper setMaxValue: (length.i_time / 1000000)];
435 [NSApp beginSheet: o_specificTime_win modalForWindow: \
436 [NSApp mainWindow] modalDelegate: self didEndSelector: nil \
438 [o_specificTime_win makeKeyWindow];
439 vlc_object_release( p_input );
446 @implementation VLCControls (NSMenuValidation)
448 - (BOOL)validateMenuItem:(NSMenuItem *)o_mi
450 return [[VLCMainMenu sharedInstance] validateMenuItem:o_mi];