1 /*****************************************************************************
2 * intf_controls.m: MacOS X interface plugin
3 *****************************************************************************
4 * Copyright (C) 2002 VideoLAN
5 * $Id: intf_controls.m,v 1.2 2002/07/16 20:41:48 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 */
35 #include <Cocoa/Cocoa.h>
36 #include <CoreAudio/AudioHardware.h>
38 #include "intf_macosx.h"
39 #include "vout_macosx.h"
41 /*****************************************************************************
42 * VLCControls interface
43 *****************************************************************************/
44 @interface VLCControls : NSObject
49 - (IBAction)play:(id)sender;
50 - (IBAction)pause:(id)sender;
51 - (IBAction)stop:(id)sender;
52 - (IBAction)faster:(id)sender;
53 - (IBAction)slower:(id)sender;
55 - (IBAction)prev:(id)sender;
56 - (IBAction)next:(id)sender;
57 - (IBAction)loop:(id)sender;
59 - (IBAction)volumeUp:(id)sender;
60 - (IBAction)volumeDown:(id)sender;
61 - (IBAction)mute:(id)sender;
62 - (IBAction)fullscreen:(id)sender;
63 - (IBAction)deinterlace:(id)sender;
65 - (IBAction)toggleProgram:(id)sender;
66 - (IBAction)toggleTitle:(id)sender;
67 - (IBAction)toggleChapter:(id)sender;
68 - (IBAction)toggleLanguage:(id)sender;
72 /*****************************************************************************
73 * VLCControls implementation
74 *****************************************************************************/
75 @implementation VLCControls
77 - (IBAction)play:(id)sender
79 intf_thread_t * p_intf = [NSApp getIntf];
80 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
82 if( p_playlist == NULL )
87 /* If the playlist is empty, open a file requester instead */
88 vlc_mutex_lock( &p_playlist->object_lock );
89 if( p_playlist->i_size )
91 vlc_mutex_unlock( &p_playlist->object_lock );
92 playlist_Play( p_playlist );
93 vlc_object_release( p_playlist );
97 vlc_mutex_unlock( &p_playlist->object_lock );
98 vlc_object_release( p_playlist );
100 [o_open openFile: nil];
104 - (IBAction)pause:(id)sender
106 intf_thread_t * p_intf = [NSApp getIntf];
108 if( p_intf->p_sys->p_input == NULL )
113 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PAUSE );
116 - (IBAction)stop:(id)sender
118 intf_thread_t * p_intf = [NSApp getIntf];
119 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
121 if( p_playlist == NULL )
126 playlist_Stop( p_playlist );
127 vlc_object_release( p_playlist );
130 - (IBAction)faster:(id)sender
132 intf_thread_t * p_intf = [NSApp getIntf];
134 if( p_intf->p_sys->p_input == NULL )
139 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_FASTER );
142 - (IBAction)slower:(id)sender
144 intf_thread_t * p_intf = [NSApp getIntf];
146 if( p_intf->p_sys->p_input == NULL )
151 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_SLOWER );
154 - (IBAction)prev:(id)sender
156 intf_thread_t * p_intf = [NSApp getIntf];
157 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
159 if( p_playlist == NULL )
164 playlist_Prev( p_playlist );
165 vlc_object_release( p_playlist );
168 - (IBAction)next:(id)sender
170 intf_thread_t * p_intf = [NSApp getIntf];
171 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
173 if( p_playlist == NULL )
178 playlist_Next( p_playlist );
179 vlc_object_release( p_playlist );
182 - (IBAction)loop:(id)sender
184 NSMenuItem * o_mi = (NSMenuItem *)sender;
185 intf_thread_t * p_intf = [NSApp getIntf];
186 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
188 if( p_playlist == NULL )
193 if( p_intf->p_sys->b_loop )
195 [o_mi setState: NSOffState];
196 playlist_Delete( p_playlist, p_playlist->i_size - 1 );
200 [o_mi setState: NSOnState];
201 playlist_Add( p_playlist, "vlc:loop",
202 PLAYLIST_APPEND, PLAYLIST_END );
205 p_intf->p_sys->b_loop = !p_intf->p_sys->b_loop;
207 vlc_object_release( p_playlist );
210 - (IBAction)volumeUp:(id)sender
213 intf_thread_t * p_intf = [NSApp getIntf];
216 /* TODO, kAudioDevicePropertyVolumeScalar */
219 - (IBAction)volumeDown:(id)sender
222 intf_thread_t * p_intf = [NSApp getIntf];
225 /* TODO, kAudioDevicePropertyVolumeScalar */
228 - (IBAction)mute:(id)sender
231 AudioDeviceID device;
232 UInt32 ui_param_size;
234 NSMenuItem * o_mi = (NSMenuItem *)sender;
235 intf_thread_t * p_intf = [NSApp getIntf];
236 UInt32 b_mute = !p_intf->p_sys->b_mute;
238 [o_mi setState: b_mute ? NSOnState : NSOffState];
239 p_intf->p_sys->b_mute = !p_intf->p_sys->b_mute;
241 ui_param_size = sizeof( device );
242 err = AudioHardwareGetProperty( kAudioHardwarePropertyDefaultOutputDevice,
243 &ui_param_size, (void *)&device );
246 msg_Err( p_intf, "AudioHardwareGetProperty failed (%d)", err );
250 ui_param_size = sizeof( b_mute );
251 err = AudioDeviceSetProperty( device, 0, 0, false,
252 kAudioDevicePropertyMute,
253 ui_param_size, (void *)&b_mute );
256 msg_Err( p_intf, "AudioDeviceSetProperty failed (%d)", err );
261 - (IBAction)fullscreen:(id)sender
263 id o_window = [NSApp keyWindow];
265 if( [[o_window className] isEqualToString: @"VLCWindow"] )
267 [o_window toggleFullscreen];
271 - (IBAction)deinterlace:(id)sender
273 intf_thread_t * p_intf = [NSApp getIntf];
274 BOOL bEnable = [sender state] == NSOffState;
278 config_PutPsz( p_intf, "filter", "deinterlace" );
279 config_PutPsz( p_intf, "deinterlace-mode",
280 [[sender title] lossyCString] );
284 config_PutPsz( p_intf, "filter", NULL );
288 - (IBAction)toggleProgram:(id)sender
290 NSMenuItem * o_mi = (NSMenuItem *)sender;
291 intf_thread_t * p_intf = [NSApp getIntf];
293 if( [o_mi state] == NSOffState )
295 u16 i_program_id = [o_mi tag];
297 input_ChangeProgram( p_intf->p_sys->p_input, i_program_id );
298 input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
302 - (IBAction)toggleTitle:(id)sender
304 NSMenuItem * o_mi = (NSMenuItem *)sender;
305 intf_thread_t * p_intf = [NSApp getIntf];
307 if( [o_mi state] == NSOffState )
309 int i_title = [o_mi tag];
311 #define p_input p_intf->p_sys->p_input
312 input_ChangeArea( p_input, p_input->stream.pp_areas[i_title] );
313 input_SetStatus( p_input, INPUT_STATUS_PLAY );
318 - (IBAction)toggleChapter:(id)sender
320 NSMenuItem * o_mi = (NSMenuItem *)sender;
321 intf_thread_t * p_intf = [NSApp getIntf];
323 if( [o_mi state] == NSOffState )
325 int i_chapter = [o_mi tag];
327 #define p_input p_intf->p_sys->p_input
328 p_input->stream.p_selected_area->i_part = i_chapter;
329 input_ChangeArea( p_input, p_input->stream.p_selected_area );
330 input_SetStatus( p_input, INPUT_STATUS_PLAY );
335 - (IBAction)toggleLanguage:(id)sender
337 NSMenuItem * o_mi = (NSMenuItem *)sender;
338 intf_thread_t * p_intf = [NSApp getIntf];
340 #define p_input p_intf->p_sys->p_input
342 if( !p_intf->p_sys->b_audio_update )
344 NSValue * o_value = [o_mi representedObject];
345 es_descriptor_t * p_es = [o_value pointerValue];
347 if( [o_mi state] == NSOnState )
349 /* we just have one ES to disable */
350 input_ToggleES( p_input, p_es, 0 );
355 int i_cat = [o_mi tag];
357 vlc_mutex_lock( &p_input->stream.stream_lock );
359 #define ES p_input->stream.pp_selected_es[i]
361 /* unselect the selected ES in the same class */
362 for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
364 if( ES->i_cat == i_cat )
366 vlc_mutex_unlock( &p_input->stream.stream_lock );
367 input_ToggleES( p_input, ES, 0 );
368 vlc_mutex_lock( &p_input->stream.stream_lock );
375 vlc_mutex_unlock( &p_input->stream.stream_lock );
377 input_ToggleES( p_input, p_es, 1 );
386 @implementation VLCControls (NSMenuValidation)
388 - (BOOL)validateMenuItem:(NSMenuItem *)o_mi
390 BOOL bEnabled = TRUE;
391 NSMenu * o_menu = [o_mi menu];
392 intf_thread_t * p_intf = [NSApp getIntf];
394 if( [[o_mi title] isEqualToString: _NS("Pause")] ||
395 [[o_mi title] isEqualToString: _NS("Faster")] ||
396 [[o_mi title] isEqualToString: _NS("Slower")] )
398 if( p_intf->p_sys->p_input != NULL )
400 #define p_input p_intf->p_sys->p_input
401 vlc_mutex_lock( &p_input->stream.stream_lock );
402 bEnabled = p_input->stream.b_pace_control;
403 vlc_mutex_unlock( &p_input->stream.stream_lock );
411 else if( [[o_mi title] isEqualToString: _NS("Stop")] )
413 bEnabled = p_intf->p_sys->p_input != NULL;
415 else if( [[o_mi title] isEqualToString: _NS("Prev")] ||
416 [[o_mi title] isEqualToString: _NS("Next")] )
418 playlist_t * p_playlist = vlc_object_find( p_intf,
421 if( p_playlist == NULL )
427 vlc_mutex_lock( &p_playlist->object_lock );
428 bEnabled = p_playlist->i_size > 1;
429 vlc_mutex_unlock( &p_playlist->object_lock );
430 vlc_object_release( p_playlist );
433 else if( [[o_mi title] isEqualToString: _NS("Volume Up")] ||
434 [[o_mi title] isEqualToString: _NS("Volume Down")] )
436 bEnabled = FALSE; /* not implemented yet */
438 else if( [[o_mi title] isEqualToString: _NS("Mute")] )
442 AudioDeviceID device;
443 UInt32 ui_param_size;
445 ui_param_size = sizeof( device );
446 err = AudioHardwareGetProperty(
447 kAudioHardwarePropertyDefaultOutputDevice,
448 &ui_param_size, (void *)&device );
451 msg_Err( p_intf, "AudioHardwareGetProperty failed (%d)", err );
455 ui_param_size = sizeof( b_mute );
456 err = AudioDeviceGetProperty( device, 0, 0,
457 kAudioDevicePropertyMute,
458 &ui_param_size, (void *)&b_mute );
461 msg_Err( p_intf, "AudioDeviceGetProperty failed (%d)", err );
465 [o_mi setState: b_mute ? NSOnState : NSOffState];
466 p_intf->p_sys->b_mute = (vlc_bool_t)b_mute ? 1 : 0;
470 else if( [[o_mi title] isEqualToString: _NS("Fullscreen")] )
472 id o_window = [NSApp keyWindow];
474 if( [[o_window className] isEqualToString: @"VLCWindow"] )
476 [o_mi setState: [o_window isFullscreen] ?
477 NSOnState : NSOffState];
484 else if( o_menu != nil &&
485 [[o_menu title] isEqualToString: _NS("Deinterlace")] )
487 char * psz_filter = config_GetPsz( p_intf, "filter" );
489 if( psz_filter != NULL )
493 psz_filter = config_GetPsz( p_intf, "deinterlace-mode" );
496 if( psz_filter != NULL )
498 if( strcmp( psz_filter, [[o_mi title] lossyCString] ) == 0 )
500 [o_mi setState: NSOnState];
504 [o_mi setState: NSOffState];
511 [o_mi setState: NSOffState];