1 /*****************************************************************************
2 * controls.m: MacOS X interface plugin
3 *****************************************************************************
4 * Copyright (C) 2002 VideoLAN
5 * $Id: controls.m,v 1.23 2003/02/08 19:10:21 massiot Exp $
7 * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8 * Christophe Massiot <massiot@via.ecp.fr>
9 * Derk-Jan Hartman <thedj@users.sourceforge.net>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
24 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
29 #include <stdlib.h> /* malloc(), free() */
30 #include <sys/param.h> /* for MAXPATHLEN */
36 /*****************************************************************************
37 * VLCControls interface
38 *****************************************************************************/
39 @interface VLCControls : NSObject
44 IBOutlet id o_volumeslider;
47 - (IBAction)play:(id)sender;
48 - (IBAction)stop:(id)sender;
49 - (IBAction)faster:(id)sender;
50 - (IBAction)slower:(id)sender;
52 - (IBAction)prev:(id)sender;
53 - (IBAction)next:(id)sender;
54 - (IBAction)loop:(id)sender;
56 - (IBAction)volumeUp:(id)sender;
57 - (IBAction)volumeDown:(id)sender;
58 - (IBAction)mute:(id)sender;
59 - (IBAction)volumeSliderUpdated:(id)sender;
60 - (void)updateVolumeSlider;
62 - (IBAction)halfWindow:(id)sender;
63 - (IBAction)normalWindow:(id)sender;
64 - (IBAction)doubleWindow:(id)sender;
65 - (IBAction)fullscreen:(id)sender;
66 - (IBAction)deinterlace:(id)sender;
68 - (IBAction)toggleProgram:(id)sender;
69 - (IBAction)toggleTitle:(id)sender;
70 - (IBAction)toggleChapter:(id)sender;
71 - (IBAction)toggleLanguage:(id)sender;
72 - (IBAction)toggleVar:(id)sender;
76 /*****************************************************************************
77 * VLCControls implementation
78 *****************************************************************************/
79 @implementation VLCControls
81 - (IBAction)play:(id)sender
83 intf_thread_t * p_intf = [NSApp getIntf];
85 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
87 if( p_playlist == NULL )
92 if( playlist_IsPlaying( p_playlist ) )
94 playlist_Pause( p_playlist );
95 vlc_object_release( p_playlist );
99 if( !playlist_IsEmpty( p_playlist ) )
101 playlist_Play( p_playlist );
102 vlc_object_release( p_playlist );
106 vlc_object_release( p_playlist );
107 [o_open openFile: nil];
112 - (IBAction)stop:(id)sender
114 intf_thread_t * p_intf = [NSApp getIntf];
116 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
118 if( p_playlist == NULL )
123 playlist_Stop( p_playlist );
124 vlc_object_release( p_playlist );
127 - (IBAction)faster:(id)sender
129 intf_thread_t * p_intf = [NSApp getIntf];
131 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
133 if( p_playlist == NULL )
138 vlc_mutex_lock( &p_playlist->object_lock );
139 if( p_playlist->p_input != NULL )
141 input_SetStatus( p_playlist->p_input, INPUT_STATUS_FASTER );
143 vlc_mutex_unlock( &p_playlist->object_lock );
145 vlc_object_release( p_playlist );
148 - (IBAction)slower:(id)sender
150 intf_thread_t * p_intf = [NSApp getIntf];
152 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
154 if( p_playlist == NULL )
159 vlc_mutex_lock( &p_playlist->object_lock );
160 if( p_playlist->p_input != NULL )
162 input_SetStatus( p_playlist->p_input, INPUT_STATUS_SLOWER );
164 vlc_mutex_unlock( &p_playlist->object_lock );
166 vlc_object_release( p_playlist );
169 - (IBAction)prev:(id)sender
171 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 vlc_mutex_lock( &p_playlist->object_lock );
182 if( p_playlist->p_input == NULL )
184 vlc_mutex_unlock( &p_playlist->object_lock );
185 vlc_object_release( p_playlist );
189 vlc_mutex_lock( &p_playlist->p_input->stream.stream_lock );
191 #define p_area p_playlist->p_input->stream.p_selected_area
193 if( p_area->i_part_nb > 1 && p_area->i_part > 1 )
197 vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
198 input_ChangeArea( p_playlist->p_input, p_area );
199 vlc_mutex_unlock( &p_playlist->object_lock );
201 p_intf->p_sys->b_chapter_update = VLC_TRUE;
205 vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
206 vlc_mutex_unlock( &p_playlist->object_lock );
207 playlist_Prev( p_playlist );
212 vlc_object_release( p_playlist );
215 - (IBAction)next:(id)sender
217 intf_thread_t * p_intf = [NSApp getIntf];
219 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
221 if( p_playlist == NULL )
226 vlc_mutex_lock( &p_playlist->object_lock );
228 if( p_playlist->p_input == NULL )
230 vlc_mutex_unlock( &p_playlist->object_lock );
231 vlc_object_release( p_playlist );
235 vlc_mutex_lock( &p_playlist->p_input->stream.stream_lock );
237 #define p_area p_playlist->p_input->stream.p_selected_area
239 if( p_area->i_part_nb > 1 && p_area->i_part + 1 < p_area->i_part_nb )
243 vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
244 input_ChangeArea( p_playlist->p_input, p_area );
245 vlc_mutex_unlock( &p_playlist->object_lock );
247 p_intf->p_sys->b_chapter_update = VLC_TRUE;
251 vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
252 vlc_mutex_unlock( &p_playlist->object_lock );
253 playlist_Next( p_playlist );
258 vlc_object_release( p_playlist );
261 - (IBAction)loop:(id)sender
263 intf_thread_t * p_intf = [NSApp getIntf];
265 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
267 if( p_playlist == NULL )
272 config_PutInt( p_playlist, "loop",
273 !config_GetInt( p_playlist, "loop" ) );
275 vlc_object_release( p_playlist );
278 - (IBAction)volumeUp:(id)sender
280 intf_thread_t * p_intf = [NSApp getIntf];
282 aout_instance_t * p_aout = vlc_object_find( p_intf, VLC_OBJECT_AOUT,
286 if( p_intf->p_sys->b_mute )
291 aout_VolumeUp( p_aout, 1, NULL );
292 vlc_object_release( (vlc_object_t *)p_aout );
295 [self updateVolumeSlider];
298 - (IBAction)volumeDown:(id)sender
300 intf_thread_t * p_intf = [NSApp getIntf];
302 aout_instance_t * p_aout = vlc_object_find( p_intf, VLC_OBJECT_AOUT,
306 if( p_intf->p_sys->b_mute )
311 aout_VolumeDown( p_aout, 1, NULL );
312 vlc_object_release( (vlc_object_t *)p_aout );
315 [self updateVolumeSlider];
318 - (IBAction)mute:(id)sender
320 intf_thread_t * p_intf = [NSApp getIntf];
322 aout_instance_t * p_aout = vlc_object_find( p_intf, VLC_OBJECT_AOUT,
325 if ( p_aout != NULL )
327 audio_volume_t i_volume;
329 aout_VolumeMute( p_aout, &i_volume );
330 vlc_object_release( (vlc_object_t *)p_aout );
332 p_intf->p_sys->b_mute = ( i_volume == 0 );
335 [self updateVolumeSlider];
338 - (IBAction)volumeSliderUpdated:(id)sender
340 intf_thread_t * p_intf = [NSApp getIntf];
342 aout_instance_t * p_aout = vlc_object_find( p_intf, VLC_OBJECT_AOUT,
346 audio_volume_t i_volume;
348 i_volume = (audio_volume_t)[sender intValue];
350 aout_VolumeSet( p_aout, i_volume * AOUT_VOLUME_STEP );
351 vlc_object_release( (vlc_object_t *)p_aout );
355 - (void)updateVolumeSlider
357 intf_thread_t * p_intf = [NSApp getIntf];
359 aout_instance_t * p_aout = vlc_object_find( p_intf, VLC_OBJECT_AOUT,
362 if ( p_aout != NULL )
364 audio_volume_t i_volume;
366 aout_VolumeGet( p_aout, &i_volume );
367 vlc_object_release( (vlc_object_t *)p_aout );
369 [o_volumeslider setFloatValue: (float)(i_volume / AOUT_VOLUME_STEP)];
373 - (IBAction)halfWindow:(id)sender
375 id o_window = [NSApp keyWindow];
376 NSArray *o_windows = [NSApp windows];
377 NSEnumerator *o_enumerator = [o_windows objectEnumerator];
379 while ((o_window = [o_enumerator nextObject]))
381 if( [[o_window className] isEqualToString: @"VLCWindow"] )
383 [o_window scaleWindowWithFactor: 0.5];
388 - (IBAction)normalWindow:(id)sender
390 id o_window = [NSApp keyWindow];
391 NSArray *o_windows = [NSApp windows];
392 NSEnumerator *o_enumerator = [o_windows objectEnumerator];
394 while ((o_window = [o_enumerator nextObject]))
396 if( [[o_window className] isEqualToString: @"VLCWindow"] )
398 [o_window scaleWindowWithFactor: 1];
403 - (IBAction)doubleWindow:(id)sender
405 id o_window = [NSApp keyWindow];
406 NSArray *o_windows = [NSApp windows];
407 NSEnumerator *o_enumerator = [o_windows objectEnumerator];
409 while ((o_window = [o_enumerator nextObject]))
411 if( [[o_window className] isEqualToString: @"VLCWindow"] )
413 [o_window scaleWindowWithFactor: 2];
419 - (IBAction)fullscreen:(id)sender
421 id o_window = [NSApp keyWindow];
422 NSArray *o_windows = [NSApp windows];
423 NSEnumerator *o_enumerator = [o_windows objectEnumerator];
425 while ((o_window = [o_enumerator nextObject]))
427 if( [[o_window className] isEqualToString: @"VLCWindow"] )
429 [o_window toggleFullscreen];
434 - (IBAction)deinterlace:(id)sender
439 - (IBAction)toggleProgram:(id)sender
441 NSMenuItem * o_mi = (NSMenuItem *)sender;
442 intf_thread_t * p_intf = [NSApp getIntf];
444 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
446 if( p_playlist == NULL )
451 vlc_mutex_lock( &p_playlist->object_lock );
453 if( p_playlist->p_input == NULL )
455 vlc_mutex_unlock( &p_playlist->object_lock );
456 vlc_object_release( p_playlist );
460 if( [o_mi state] == NSOffState )
462 u16 i_program_id = [o_mi tag];
464 input_ChangeProgram( p_playlist->p_input, i_program_id );
465 input_SetStatus( p_playlist->p_input, INPUT_STATUS_PLAY );
468 vlc_mutex_unlock( &p_playlist->object_lock );
469 vlc_object_release( p_playlist );
472 - (IBAction)toggleTitle:(id)sender
474 NSMenuItem * o_mi = (NSMenuItem *)sender;
475 intf_thread_t * p_intf = [NSApp getIntf];
477 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
479 if( p_playlist == NULL )
484 vlc_mutex_lock( &p_playlist->object_lock );
486 if( p_playlist->p_input == NULL )
488 vlc_mutex_unlock( &p_playlist->object_lock );
489 vlc_object_release( p_playlist );
493 if( [o_mi state] == NSOffState )
495 int i_title = [o_mi tag];
497 #define p_input p_playlist->p_input
498 input_ChangeArea( p_input, p_input->stream.pp_areas[i_title] );
499 input_SetStatus( p_input, INPUT_STATUS_PLAY );
503 vlc_mutex_unlock( &p_playlist->object_lock );
504 vlc_object_release( p_playlist );
507 - (IBAction)toggleChapter:(id)sender
509 NSMenuItem * o_mi = (NSMenuItem *)sender;
510 intf_thread_t * p_intf = [NSApp getIntf];
512 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
514 if( p_playlist == NULL )
519 vlc_mutex_lock( &p_playlist->object_lock );
521 if( p_playlist->p_input == NULL )
523 vlc_mutex_unlock( &p_playlist->object_lock );
524 vlc_object_release( p_playlist );
528 if( [o_mi state] == NSOffState )
530 int i_chapter = [o_mi tag];
532 #define p_input p_playlist->p_input
533 p_input->stream.p_selected_area->i_part = i_chapter;
534 input_ChangeArea( p_input, p_input->stream.p_selected_area );
535 input_SetStatus( p_input, INPUT_STATUS_PLAY );
539 vlc_mutex_unlock( &p_playlist->object_lock );
540 vlc_object_release( p_playlist );
543 - (IBAction)toggleLanguage:(id)sender
545 NSMenuItem * o_mi = (NSMenuItem *)sender;
546 intf_thread_t * p_intf = [NSApp getIntf];
548 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
550 if( p_playlist == NULL )
555 vlc_mutex_lock( &p_playlist->object_lock );
557 if( p_playlist->p_input == NULL )
559 vlc_mutex_unlock( &p_playlist->object_lock );
560 vlc_object_release( p_playlist );
565 /* We do not use this code, because you need to start stop .avi for
566 * it to work, so not very useful now --hartman */
567 if ( [o_mi state] == NSOffState && [o_mi tag] == 2000 )
569 NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
571 [o_open_panel setAllowsMultipleSelection: NO];
572 [o_open_panel setTitle: _NS("Open subtitle file")];
573 [o_open_panel setPrompt: _NS("Open")];
575 if( [o_open_panel runModalForDirectory: nil
576 file: nil types: nil] == NSOKButton )
578 NSString *o_filename = [[o_open_panel filenames] objectAtIndex: 0];
579 config_PutPsz( p_intf, "sub-file", strdup( [o_filename cString] ));
584 #define p_input p_playlist->p_input
586 if( !p_intf->p_sys->b_audio_update )
588 NSValue * o_value = [o_mi representedObject];
589 es_descriptor_t * p_es = [o_value pointerValue];
591 if( [o_mi state] == NSOnState )
593 /* we just have one ES to disable */
594 input_ToggleES( p_input, p_es, 0 );
599 int i_cat = [o_mi tag];
601 vlc_mutex_lock( &p_input->stream.stream_lock );
603 #define ES p_input->stream.pp_selected_es[i]
605 /* unselect the selected ES in the same class */
606 for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
608 if( ES->i_cat == i_cat )
610 vlc_mutex_unlock( &p_input->stream.stream_lock );
611 input_ToggleES( p_input, ES, 0 );
612 vlc_mutex_lock( &p_input->stream.stream_lock );
619 vlc_mutex_unlock( &p_input->stream.stream_lock );
621 input_ToggleES( p_input, p_es, 1 );
627 vlc_mutex_unlock( &p_playlist->object_lock );
628 vlc_object_release( p_playlist );
631 - (IBAction)toggleVar:(id)sender
633 NSMenuItem * o_mi = (NSMenuItem *)sender;
635 if( [o_mi state] == NSOffState )
637 const char * psz_variable = (const char *)[o_mi tag];
638 char * psz_value = [NSApp delocalizeString: [o_mi title]];
639 vlc_object_t * p_object = (vlc_object_t *)
640 [[o_mi representedObject] pointerValue];
642 /* psz_string sucks */
643 val.psz_string = (char *)psz_value;
645 if ( var_Set( p_object, psz_variable, val ) < 0 )
647 msg_Warn( p_object, "cannot set variable (%s)", psz_value );
656 @implementation VLCControls (NSMenuValidation)
658 - (BOOL)validateMenuItem:(NSMenuItem *)o_mi
660 BOOL bEnabled = TRUE;
661 NSMenu * o_menu = [o_mi menu];
662 intf_thread_t * p_intf = [NSApp getIntf];
664 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
667 if( p_playlist != NULL )
669 vlc_mutex_lock( &p_playlist->object_lock );
672 #define p_input p_playlist->p_input
674 if( [[o_mi title] isEqualToString: _NS("Faster")] ||
675 [[o_mi title] isEqualToString: _NS("Slower")] )
677 if( p_playlist != NULL && p_input != NULL )
679 vlc_mutex_lock( &p_input->stream.stream_lock );
680 bEnabled = p_input->stream.b_pace_control;
681 vlc_mutex_unlock( &p_input->stream.stream_lock );
688 else if( [[o_mi title] isEqualToString: _NS("Stop")] )
690 if( p_playlist == NULL || p_input == NULL )
695 else if( [[o_mi title] isEqualToString: _NS("Previous")] ||
696 [[o_mi title] isEqualToString: _NS("Next")] )
698 if( p_playlist == NULL )
704 bEnabled = p_playlist->i_size > 1;
706 if( p_input != NULL )
708 vlc_mutex_lock( &p_input->stream.stream_lock );
709 bEnabled |= p_input->stream.p_selected_area->i_part_nb > 1;
710 vlc_mutex_unlock( &p_input->stream.stream_lock );
714 else if( [[o_mi title] isEqualToString: _NS("Loop")] )
716 int i_state = config_GetInt( p_playlist, "loop" ) ?
717 NSOnState : NSOffState;
719 [o_mi setState: i_state];
721 else if( [[o_mi title] isEqualToString: _NS("Volume Up")] ||
722 [[o_mi title] isEqualToString: _NS("Volume Down")] )
724 aout_instance_t * p_aout;
726 p_aout = vlc_object_find( p_intf, VLC_OBJECT_AOUT,
730 vlc_object_release( (vlc_object_t *)p_aout );
737 else if( [[o_mi title] isEqualToString: _NS("Mute")] )
739 aout_instance_t * p_aout;
741 p_aout = vlc_object_find( p_intf, VLC_OBJECT_AOUT,
745 vlc_object_release( (vlc_object_t *)p_aout );
752 [o_mi setState: p_intf->p_sys->b_mute ? NSOnState : NSOffState];
754 else if( [[o_mi title] isEqualToString: _NS("Fullscreen")] ||
755 [[o_mi title] isEqualToString: _NS("Half Size")] ||
756 [[o_mi title] isEqualToString: _NS("Normal Size")] ||
757 [[o_mi title] isEqualToString: _NS("Double Size")])
760 NSArray *o_windows = [NSApp windows];
761 NSEnumerator *o_enumerator = [o_windows objectEnumerator];
764 while ((o_window = [o_enumerator nextObject]))
766 if( [[o_window className] isEqualToString: @"VLCWindow"] )
773 else if( o_menu != nil &&
774 [[o_menu title] isEqualToString: _NS("Deinterlace")] )
779 if( p_playlist != NULL )
781 vlc_mutex_unlock( &p_playlist->object_lock );
782 vlc_object_release( p_playlist );