1 /*****************************************************************************
2 * controls.m: MacOS X interface plugin
3 *****************************************************************************
4 * Copyright (C) 2002 VideoLAN
5 * $Id: controls.m,v 1.5 2003/01/04 04:11:08 jlj Exp $
7 * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8 * Christophe Massiot <massiot@via.ecp.fr>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
28 #include <stdlib.h> /* malloc(), free() */
29 #include <sys/param.h> /* for MAXPATHLEN */
36 #include <Cocoa/Cocoa.h>
37 #include <CoreAudio/AudioHardware.h>
42 /*****************************************************************************
43 * VLCControls interface
44 *****************************************************************************/
45 @interface VLCControls : NSObject
50 - (IBAction)play:(id)sender;
51 - (IBAction)pause:(id)sender;
52 - (IBAction)stop:(id)sender;
53 - (IBAction)faster:(id)sender;
54 - (IBAction)slower:(id)sender;
56 - (IBAction)prev:(id)sender;
57 - (IBAction)next:(id)sender;
58 - (IBAction)loop:(id)sender;
60 - (IBAction)volumeUp:(id)sender;
61 - (IBAction)volumeDown:(id)sender;
62 - (IBAction)mute:(id)sender;
63 - (IBAction)fullscreen:(id)sender;
64 - (IBAction)deinterlace:(id)sender;
66 - (IBAction)toggleProgram:(id)sender;
67 - (IBAction)toggleTitle:(id)sender;
68 - (IBAction)toggleChapter:(id)sender;
69 - (IBAction)toggleLanguage:(id)sender;
70 - (IBAction)toggleVar:(id)sender;
74 /*****************************************************************************
75 * VLCControls implementation
76 *****************************************************************************/
77 @implementation VLCControls
79 - (IBAction)play:(id)sender
81 intf_thread_t * p_intf = [NSApp getIntf];
82 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
84 if( p_playlist == NULL )
89 /* If the playlist is empty, open a file requester instead */
90 vlc_mutex_lock( &p_playlist->object_lock );
91 if( p_playlist->i_size )
93 vlc_mutex_unlock( &p_playlist->object_lock );
94 playlist_Play( p_playlist );
95 vlc_object_release( p_playlist );
99 vlc_mutex_unlock( &p_playlist->object_lock );
100 vlc_object_release( p_playlist );
102 [o_open openFile: nil];
106 - (IBAction)pause:(id)sender
108 intf_thread_t * p_intf = [NSApp getIntf];
110 if( p_intf->p_sys->p_input == NULL )
115 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PAUSE );
118 - (IBAction)stop:(id)sender
120 intf_thread_t * p_intf = [NSApp getIntf];
121 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
123 if( p_playlist == NULL )
128 playlist_Stop( p_playlist );
129 vlc_object_release( p_playlist );
132 - (IBAction)faster:(id)sender
134 intf_thread_t * p_intf = [NSApp getIntf];
136 if( p_intf->p_sys->p_input == NULL )
141 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_FASTER );
144 - (IBAction)slower:(id)sender
146 intf_thread_t * p_intf = [NSApp getIntf];
148 if( p_intf->p_sys->p_input == NULL )
153 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_SLOWER );
156 - (IBAction)prev:(id)sender
158 intf_thread_t * p_intf = [NSApp getIntf];
159 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
161 if( p_playlist == NULL )
166 playlist_Prev( p_playlist );
167 vlc_object_release( p_playlist );
170 - (IBAction)next:(id)sender
172 intf_thread_t * p_intf = [NSApp getIntf];
173 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
175 if( p_playlist == NULL )
180 playlist_Next( p_playlist );
181 vlc_object_release( p_playlist );
184 - (IBAction)loop:(id)sender
186 NSMenuItem * o_mi = (NSMenuItem *)sender;
187 intf_thread_t * p_intf = [NSApp getIntf];
188 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
190 if( p_playlist == NULL )
195 if( p_intf->p_sys->b_loop )
197 [o_mi setState: NSOffState];
198 config_PutInt( p_playlist, "loop", 0 );
202 [o_mi setState: NSOnState];
203 config_PutInt( p_playlist, "loop", 1 );
206 p_intf->p_sys->b_loop = !p_intf->p_sys->b_loop;
208 vlc_object_release( p_playlist );
211 - (IBAction)volumeUp:(id)sender
213 intf_thread_t * p_intf = [NSApp getIntf];
214 aout_instance_t * p_aout = vlc_object_find( p_intf, VLC_OBJECT_AOUT,
217 if ( p_aout != NULL )
219 aout_VolumeUp( p_aout, 1, NULL );
220 vlc_object_release( (vlc_object_t *)p_aout );
224 - (IBAction)volumeDown:(id)sender
226 intf_thread_t * p_intf = [NSApp getIntf];
227 aout_instance_t * p_aout = vlc_object_find( p_intf, VLC_OBJECT_AOUT,
230 if ( p_aout != NULL )
232 aout_VolumeDown( p_aout, 1, NULL );
233 vlc_object_release( (vlc_object_t *)p_aout );
237 - (IBAction)mute:(id)sender
239 intf_thread_t * p_intf = [NSApp getIntf];
240 aout_instance_t * p_aout = vlc_object_find( p_intf, VLC_OBJECT_AOUT,
243 if ( p_aout != NULL )
245 aout_VolumeMute( p_aout, NULL );
246 vlc_object_release( (vlc_object_t *)p_aout );
249 NSMenuItem * o_mi = (NSMenuItem *)sender;
250 p_intf->p_sys->b_mute = !p_intf->p_sys->b_mute;
251 [o_mi setState: p_intf->p_sys->b_mute ? NSOnState : NSOffState];
254 - (IBAction)fullscreen:(id)sender
256 id o_window = [NSApp keyWindow];
258 if( [[o_window className] isEqualToString: @"VLCWindow"] )
260 [o_window toggleFullscreen];
264 - (IBAction)deinterlace:(id)sender
266 intf_thread_t * p_intf = [NSApp getIntf];
267 BOOL bEnable = [sender state] == NSOffState;
271 config_PutPsz( p_intf, "filter", "deinterlace" );
272 config_PutPsz( p_intf, "deinterlace-mode",
273 [[sender title] lossyCString] );
277 config_PutPsz( p_intf, "filter", NULL );
281 - (IBAction)toggleProgram:(id)sender
283 NSMenuItem * o_mi = (NSMenuItem *)sender;
284 intf_thread_t * p_intf = [NSApp getIntf];
286 if( [o_mi state] == NSOffState )
288 u16 i_program_id = [o_mi tag];
290 input_ChangeProgram( p_intf->p_sys->p_input, i_program_id );
291 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
295 - (IBAction)toggleTitle:(id)sender
297 NSMenuItem * o_mi = (NSMenuItem *)sender;
298 intf_thread_t * p_intf = [NSApp getIntf];
300 if( [o_mi state] == NSOffState )
302 int i_title = [o_mi tag];
304 #define p_input p_intf->p_sys->p_input
305 input_ChangeArea( p_input, p_input->stream.pp_areas[i_title] );
306 input_SetStatus( p_input, INPUT_STATUS_PLAY );
311 - (IBAction)toggleChapter:(id)sender
313 NSMenuItem * o_mi = (NSMenuItem *)sender;
314 intf_thread_t * p_intf = [NSApp getIntf];
316 if( [o_mi state] == NSOffState )
318 int i_chapter = [o_mi tag];
320 #define p_input p_intf->p_sys->p_input
321 p_input->stream.p_selected_area->i_part = i_chapter;
322 input_ChangeArea( p_input, p_input->stream.p_selected_area );
323 input_SetStatus( p_input, INPUT_STATUS_PLAY );
328 - (IBAction)toggleLanguage:(id)sender
330 NSMenuItem * o_mi = (NSMenuItem *)sender;
331 intf_thread_t * p_intf = [NSApp getIntf];
333 #define p_input p_intf->p_sys->p_input
335 if( !p_intf->p_sys->b_audio_update )
337 NSValue * o_value = [o_mi representedObject];
338 es_descriptor_t * p_es = [o_value pointerValue];
340 if( [o_mi state] == NSOnState )
342 /* we just have one ES to disable */
343 input_ToggleES( p_input, p_es, 0 );
348 int i_cat = [o_mi tag];
350 vlc_mutex_lock( &p_input->stream.stream_lock );
352 #define ES p_input->stream.pp_selected_es[i]
354 /* unselect the selected ES in the same class */
355 for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
357 if( ES->i_cat == i_cat )
359 vlc_mutex_unlock( &p_input->stream.stream_lock );
360 input_ToggleES( p_input, ES, 0 );
361 vlc_mutex_lock( &p_input->stream.stream_lock );
368 vlc_mutex_unlock( &p_input->stream.stream_lock );
370 input_ToggleES( p_input, p_es, 1 );
377 - (IBAction)toggleVar:(id)sender
379 NSMenuItem * o_mi = (NSMenuItem *)sender;
381 if( [o_mi state] == NSOffState )
383 const char * psz_variable = (const char *)[o_mi tag];
384 const char * psz_value = [[o_mi title] cString];
385 vlc_object_t * p_object = (vlc_object_t *)
386 [[o_mi representedObject] pointerValue];
388 /* psz_string sucks */
389 val.psz_string = (char *)psz_value;
391 if ( var_Set( p_object, psz_variable, val ) < 0 )
393 msg_Warn( p_object, "cannot set variable (%s)", psz_value );
400 @implementation VLCControls (NSMenuValidation)
402 - (BOOL)validateMenuItem:(NSMenuItem *)o_mi
404 BOOL bEnabled = TRUE;
405 NSMenu * o_menu = [o_mi menu];
406 intf_thread_t * p_intf = [NSApp getIntf];
408 if( [[o_mi title] isEqualToString: _NS("Pause")] ||
409 [[o_mi title] isEqualToString: _NS("Faster")] ||
410 [[o_mi title] isEqualToString: _NS("Slower")] )
412 if( p_intf->p_sys->p_input != NULL )
414 #define p_input p_intf->p_sys->p_input
415 vlc_mutex_lock( &p_input->stream.stream_lock );
416 bEnabled = p_input->stream.b_pace_control;
417 vlc_mutex_unlock( &p_input->stream.stream_lock );
425 else if( [[o_mi title] isEqualToString: _NS("Stop")] )
427 bEnabled = p_intf->p_sys->p_input != NULL;
429 else if( [[o_mi title] isEqualToString: _NS("Previous")] ||
430 [[o_mi title] isEqualToString: _NS("Next")] )
432 playlist_t * p_playlist = vlc_object_find( p_intf,
435 if( p_playlist == NULL )
441 vlc_mutex_lock( &p_playlist->object_lock );
442 bEnabled = p_playlist->i_size > 1;
443 vlc_mutex_unlock( &p_playlist->object_lock );
444 vlc_object_release( p_playlist );
447 else if( [[o_mi title] isEqualToString: _NS("Volume Up")] ||
448 [[o_mi title] isEqualToString: _NS("Volume Down")] ||
449 [[o_mi title] isEqualToString: _NS("Mute")] )
451 aout_instance_t * p_aout = vlc_object_find( p_intf, VLC_OBJECT_AOUT,
454 if ( p_aout != NULL )
456 vlc_object_release( (vlc_object_t *)p_aout );
463 else if( [[o_mi title] isEqualToString: _NS("Fullscreen")] )
465 id o_window = [NSApp keyWindow];
467 if( [[o_window className] isEqualToString: @"VLCWindow"] )
469 [o_mi setState: [o_window isFullscreen] ?
470 NSOnState : NSOffState];
477 else if( o_menu != nil &&
478 [[o_menu title] isEqualToString: _NS("Deinterlace")] )
480 char * psz_filter = config_GetPsz( p_intf, "filter" );
482 if( psz_filter != NULL )
486 psz_filter = config_GetPsz( p_intf, "deinterlace-mode" );
489 if( psz_filter != NULL )
491 if( strcmp( psz_filter, [[o_mi title] lossyCString] ) == 0 )
493 [o_mi setState: NSOnState];
497 [o_mi setState: NSOffState];
504 [o_mi setState: NSOffState];