]> git.sesse.net Git - vlc/blob - modules/gui/macosx/controls.m
macosx: clean up
[vlc] / modules / gui / macosx / controls.m
1 /*****************************************************************************
2  * controls.m: MacOS X interface module
3  *****************************************************************************
4  * Copyright (C) 2002-2011 the VideoLAN team
5  * $Id$
6  *
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>
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 #include <stdlib.h>                                      /* malloc(), free() */
32 #include <sys/param.h>                                    /* for MAXPATHLEN */
33 #include <string.h>
34
35 #import "intf.h"
36 #import "VideoView.h"
37 #import "open.h"
38 #import "controls.h"
39 #import "playlist.h"
40 #import "CoreInteraction.h"
41 #import <vlc_keys.h>
42
43 #pragma mark -
44 /*****************************************************************************
45  * VLCControls implementation
46  *****************************************************************************/
47 @implementation VLCControls
48
49 - (void)awakeFromNib
50 {
51     [o_specificTime_mi setTitle: _NS("Jump To Time")];
52     [o_specificTime_cancel_btn setTitle: _NS("Cancel")];
53     [o_specificTime_ok_btn setTitle: _NS("OK")];
54     [o_specificTime_sec_lbl setStringValue: _NS("sec.")];
55     [o_specificTime_goTo_lbl setStringValue: _NS("Jump to time")];
56 }
57
58
59 - (void)dealloc
60 {
61     [[NSNotificationCenter defaultCenter] removeObserver: self];
62
63     [super dealloc];
64 }
65
66 - (IBAction)play:(id)sender
67 {
68     [[VLCCoreInteraction sharedInstance] play];
69 }
70
71 - (IBAction)stop:(id)sender
72 {
73     [[VLCCoreInteraction sharedInstance] stop];
74 }
75
76 - (IBAction)prev:(id)sender
77 {
78     [[VLCCoreInteraction sharedInstance] previous];
79 }
80
81 - (IBAction)next:(id)sender
82 {
83     [[VLCCoreInteraction sharedInstance] next];
84 }
85
86 - (IBAction)random:(id)sender
87 {
88     [[VLCCoreInteraction sharedInstance] shuffle];
89 }
90
91 - (IBAction)repeat:(id)sender
92 {
93     vlc_value_t val;
94     intf_thread_t * p_intf = VLCIntf;
95     playlist_t * p_playlist = pl_Get( p_intf );
96
97     var_Get( p_playlist, "repeat", &val );
98     if(! val.b_bool )
99         [[VLCCoreInteraction sharedInstance] repeatOne];
100     else
101         [[VLCCoreInteraction sharedInstance] repeatOff];
102 }
103
104 - (IBAction)loop:(id)sender
105 {
106     vlc_value_t val;
107     intf_thread_t * p_intf = VLCIntf;
108     playlist_t * p_playlist = pl_Get( p_intf );
109
110     var_Get( p_playlist, "loop", &val );
111     if(! val.b_bool )
112         [[VLCCoreInteraction sharedInstance] repeatAll];
113     else
114         [[VLCCoreInteraction sharedInstance] repeatOff];
115 }
116
117 - (IBAction)quitAfterPlayback:(id)sender
118 {
119     vlc_value_t val;
120     playlist_t * p_playlist = pl_Get( VLCIntf );
121     var_ToggleBool( p_playlist, "play-and-exit" );
122 }
123
124 - (IBAction)forward:(id)sender
125 {
126     [[VLCCoreInteraction sharedInstance] forward];
127 }
128
129 - (IBAction)backward:(id)sender
130 {
131     [[VLCCoreInteraction sharedInstance] backward];
132 }
133
134 - (IBAction)volumeUp:(id)sender
135 {
136     [[VLCCoreInteraction sharedInstance] volumeUp];
137 }
138
139 - (IBAction)volumeDown:(id)sender
140 {
141     [[VLCCoreInteraction sharedInstance] volumeDown];
142 }
143
144 - (IBAction)mute:(id)sender
145 {
146     [[VLCCoreInteraction sharedInstance] mute];
147 }
148
149 - (IBAction)volumeSliderUpdated:(id)sender
150 {
151     [[VLCCoreInteraction sharedInstance] setVolume: [sender intValue]];
152 }
153
154 - (IBAction)showPosition: (id)sender
155 {
156     input_thread_t * p_input = pl_CurrentInput( VLCIntf );
157     if( p_input != NULL )
158     {
159         vout_thread_t *p_vout = input_GetVout( p_input );
160         if( p_vout != NULL )
161         {
162             var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_POSITION );
163             vlc_object_release( (vlc_object_t *)p_vout );
164         }
165         vlc_object_release( p_input );
166     }
167 }
168
169 - (IBAction)telxTransparent:(id)sender
170 {
171     vlc_object_t *p_vbi;
172     p_vbi = (vlc_object_t *) vlc_object_find_name( pl_Get( VLCIntf ), "zvbi" );
173     if( p_vbi )
174     {
175         var_SetBool( p_vbi, "vbi-opaque", [sender state] );
176         [sender setState: ![sender state]];
177         vlc_object_release( p_vbi );
178     }
179 }
180
181 - (IBAction)telxNavLink:(id)sender
182 {
183     intf_thread_t * p_intf = VLCIntf;
184     vlc_object_t *p_vbi;
185     int i_page = 0;
186
187     if( [[sender title] isEqualToString: _NS("Index")] )
188         i_page = 'i' << 16;
189     else if( [[sender title] isEqualToString: _NS("Red")] )
190         i_page = 'r' << 16;
191     else if( [[sender title] isEqualToString: _NS("Green")] )
192         i_page = 'g' << 16;
193     else if( [[sender title] isEqualToString: _NS("Yellow")] )
194         i_page = 'y' << 16;
195     else if( [[sender title] isEqualToString: _NS("Blue")] )
196         i_page = 'b' << 16;
197     if( i_page == 0 ) return;
198
199     p_vbi = (vlc_object_t *) vlc_object_find_name( pl_Get( VLCIntf ), "zvbi" );
200     if( p_vbi )
201     {
202         var_SetInteger( p_vbi, "vbi-page", i_page );
203         vlc_object_release( p_vbi );
204     }
205 }
206
207 - (IBAction)lockVideosAspectRatio:(id)sender
208 {
209     [[VLCCoreInteraction sharedInstance] setAspectRatioLocked: [sender state]];
210     [sender setState: [[VLCCoreInteraction sharedInstance] aspectRatioIsLocked]];
211 }
212
213 - (IBAction)addSubtitleFile:(id)sender
214 {
215     NSInteger i_returnValue = 0;
216     input_thread_t * p_input = pl_CurrentInput( VLCIntf );
217     if( !p_input ) return;
218
219     input_item_t *p_item = input_GetItem( p_input );
220     if( !p_item ) return;
221
222     char *path = input_item_GetURI( p_item );
223     if( !path ) path = strdup( "" );
224
225     NSOpenPanel * openPanel = [NSOpenPanel openPanel];
226     [openPanel setCanChooseFiles: YES];
227     [openPanel setCanChooseDirectories: NO];
228     [openPanel setAllowsMultipleSelection: YES];
229     [openPanel setAllowedFileTypes: [NSArray arrayWithObjects: @"cdg",@"@idx",@"srt",@"sub",@"utf",@"ass",@"ssa",@"aqt",@"jss",@"psb",@"rt",@"smi",@"txt",@"smil", nil]];
230     [openPanel setDirectoryURL:[NSURL fileURLWithPath:[[NSString stringWithUTF8String:path] stringByExpandingTildeInPath]]];
231     i_returnValue = [openPanel runModal];
232     free( path );
233
234     if( i_returnValue == NSOKButton )
235     {
236         NSUInteger c = 0;
237         if( !p_input ) return;
238
239         c = [[openPanel URLs] count];
240
241         for (int i = 0; i < c ; i++)
242         {
243             msg_Dbg( VLCIntf, "loading subs from %s", [[[[openPanel URLs] objectAtIndex: i] path] UTF8String] );
244             if( input_AddSubtitle( p_input, [[[[openPanel URLs] objectAtIndex: i] path] UTF8String], TRUE ) )
245                 msg_Warn( VLCIntf, "unable to load subtitles from '%s'",
246                          [[[[openPanel URLs] objectAtIndex: i] path] UTF8String] );
247         }
248     }
249 }
250
251 - (void)scrollWheel:(NSEvent *)theEvent
252 {
253     intf_thread_t * p_intf = VLCIntf;
254     BOOL b_invertedEventFromDevice = NO;
255     if (OSX_LION)
256     {
257         if ([theEvent isDirectionInvertedFromDevice])
258             b_invertedEventFromDevice = YES;
259     }
260
261     float f_yabsvalue = [theEvent deltaY] > 0.0f ? [theEvent deltaY] : -[theEvent deltaY];
262     float f_xabsvalue = [theEvent deltaX] > 0.0f ? [theEvent deltaX] : -[theEvent deltaX];
263     int i, i_yvlckey, i_xvlckey;
264
265     if (b_invertedEventFromDevice)
266     {
267         if ([theEvent deltaY] > 0.0f)
268             i_yvlckey = KEY_MOUSEWHEELDOWN;
269         else
270             i_yvlckey = KEY_MOUSEWHEELUP;
271
272         if ([theEvent deltaX] > 0.0f)
273             i_xvlckey = KEY_MOUSEWHEELRIGHT;
274         else
275             i_xvlckey = KEY_MOUSEWHEELLEFT;
276     }
277     else
278     {
279         if ([theEvent deltaY] < 0.0f)
280             i_yvlckey = KEY_MOUSEWHEELDOWN;
281         else
282             i_yvlckey = KEY_MOUSEWHEELUP;
283
284         if ([theEvent deltaX] < 0.0f)
285             i_xvlckey = KEY_MOUSEWHEELRIGHT;
286         else
287             i_xvlckey = KEY_MOUSEWHEELLEFT;
288     }
289
290     /* Send multiple key event, depending on the intensity of the event */
291     for (i = 0; i < (int)(f_yabsvalue/4.+1.) && f_yabsvalue > 0.05 ; i++)
292         var_SetInteger( p_intf->p_libvlc, "key-pressed", i_yvlckey );
293
294     /* Prioritize Y event (sound volume) over X event */
295     if (f_yabsvalue < 0.05)
296     {
297         for (i = 0; i < (int)(f_xabsvalue/6.+1.) && f_xabsvalue > 0.05; i++)
298          var_SetInteger( p_intf->p_libvlc, "key-pressed", i_xvlckey );
299     }
300 }
301
302 - (BOOL)keyEvent:(NSEvent *)o_event
303 {
304     BOOL eventHandled = NO;
305     unichar key = [[o_event charactersIgnoringModifiers] characterAtIndex: 0];
306
307     if( key )
308     {
309         input_thread_t * p_input = pl_CurrentInput( VLCIntf );
310         if( p_input != NULL )
311         {
312             vout_thread_t *p_vout = input_GetVout( p_input );
313
314             if( p_vout != NULL )
315             {
316                 /* Escape */
317                 if( key == (unichar) 0x1b )
318                 {
319                     vout_thread_t *p_vout = getVout();
320                     if (p_vout)
321                     {
322                         if (var_GetBool( p_vout, "fullscreen" ))
323                         {
324                             [[VLCCoreInteraction sharedInstance] toggleFullscreen];
325                             eventHandled = YES;
326                         }
327                     }
328                 }
329                 else if( key == ' ' )
330                 {
331                     [self play:self];
332                     eventHandled = YES;
333                 }
334                 vlc_object_release( (vlc_object_t *)p_vout );
335             }
336             vlc_object_release( p_input );
337         }
338     }
339     return eventHandled;
340 }
341
342 - (IBAction)goToSpecificTime:(id)sender
343 {
344     if( sender == o_specificTime_cancel_btn )
345     {
346         [NSApp endSheet: o_specificTime_win];
347         [o_specificTime_win close];
348     }
349     else if( sender == o_specificTime_ok_btn )
350     {
351         input_thread_t * p_input = pl_CurrentInput( VLCIntf );
352         if( p_input )
353         {
354             int64_t timeInSec = 0;
355             NSString * fieldContent = [o_specificTime_enter_fld stringValue];
356             if( [[fieldContent componentsSeparatedByString: @":"] count] > 1 &&
357                 [[fieldContent componentsSeparatedByString: @":"] count] <= 3 )
358             {
359                 NSArray * ourTempArray = \
360                     [fieldContent componentsSeparatedByString: @":"];
361
362                 if( [[fieldContent componentsSeparatedByString: @":"] count] == 3 )
363                 {
364                     timeInSec += ([[ourTempArray objectAtIndex: 0] intValue] * 3600); //h
365                     timeInSec += ([[ourTempArray objectAtIndex: 1] intValue] * 60); //m
366                     timeInSec += [[ourTempArray objectAtIndex: 2] intValue];        //s
367                 }
368                 else
369                 {
370                     timeInSec += ([[ourTempArray objectAtIndex: 0] intValue] * 60); //m
371                     timeInSec += [[ourTempArray objectAtIndex: 1] intValue]; //s
372                 }
373             }
374             else
375                 timeInSec = [fieldContent intValue];
376
377             input_Control( p_input, INPUT_SET_TIME, (int64_t)(timeInSec * 1000000));
378             vlc_object_release( p_input );
379         }
380
381         [NSApp endSheet: o_specificTime_win];
382         [o_specificTime_win close];
383     }
384     else
385     {
386         input_thread_t * p_input = pl_CurrentInput( VLCIntf );
387         if( p_input )
388         {
389             /* we can obviously only do that if an input is available */
390             vlc_value_t pos, length;
391             var_Get( p_input, "time", &pos );
392             [o_specificTime_enter_fld setIntValue: (pos.i_time / 1000000)];
393             var_Get( p_input, "length", &length );
394             [o_specificTime_stepper setMaxValue: (length.i_time / 1000000)];
395
396             [NSApp beginSheet: o_specificTime_win modalForWindow: \
397                 [NSApp mainWindow] modalDelegate: self didEndSelector: nil \
398                 contextInfo: nil];
399             [o_specificTime_win makeKeyWindow];
400             vlc_object_release( p_input );
401         }
402     }
403 }
404
405 @end