1 /*****************************************************************************
2 * controls.m: MacOS X interface plugin
3 *****************************************************************************
4 * Copyright (C) 2002-2003 VideoLAN
5 * $Id: controls.m,v 1.29 2003/03/06 11:43:07 hartman 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 */
37 /*****************************************************************************
38 * VLCControls implementation
39 *****************************************************************************/
40 @implementation VLCControls
42 - (IBAction)play:(id)sender
44 intf_thread_t * p_intf = [NSApp getIntf];
46 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
48 if( p_playlist == NULL )
53 if( playlist_IsPlaying( p_playlist ) )
55 playlist_Pause( p_playlist );
56 vlc_object_release( p_playlist );
60 if( !playlist_IsEmpty( p_playlist ) )
62 playlist_Play( p_playlist );
63 vlc_object_release( p_playlist );
67 vlc_object_release( p_playlist );
68 [o_open openFile: nil];
73 - (IBAction)stop:(id)sender
75 intf_thread_t * p_intf = [NSApp getIntf];
77 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
79 if( p_playlist == NULL )
84 playlist_Stop( p_playlist );
85 vlc_object_release( p_playlist );
88 - (IBAction)faster:(id)sender
90 intf_thread_t * p_intf = [NSApp getIntf];
92 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
94 if( p_playlist == NULL )
99 vlc_mutex_lock( &p_playlist->object_lock );
100 if( p_playlist->p_input != NULL )
102 input_SetStatus( p_playlist->p_input, INPUT_STATUS_FASTER );
104 vlc_mutex_unlock( &p_playlist->object_lock );
106 vlc_object_release( p_playlist );
109 - (IBAction)slower:(id)sender
111 intf_thread_t * p_intf = [NSApp getIntf];
113 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
115 if( p_playlist == NULL )
120 vlc_mutex_lock( &p_playlist->object_lock );
121 if( p_playlist->p_input != NULL )
123 input_SetStatus( p_playlist->p_input, INPUT_STATUS_SLOWER );
125 vlc_mutex_unlock( &p_playlist->object_lock );
127 vlc_object_release( p_playlist );
130 - (IBAction)prev:(id)sender
132 intf_thread_t * p_intf = [NSApp getIntf];
134 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
136 if( p_playlist == NULL )
141 vlc_mutex_lock( &p_playlist->object_lock );
143 if( p_playlist->p_input == NULL )
145 vlc_mutex_unlock( &p_playlist->object_lock );
146 vlc_object_release( p_playlist );
150 vlc_mutex_lock( &p_playlist->p_input->stream.stream_lock );
152 #define p_area p_playlist->p_input->stream.p_selected_area
154 if( p_area->i_part_nb > 1 && p_area->i_part > 1 )
158 vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
159 input_ChangeArea( p_playlist->p_input, p_area );
160 vlc_mutex_unlock( &p_playlist->object_lock );
162 p_intf->p_sys->b_chapter_update = VLC_TRUE;
166 vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
167 vlc_mutex_unlock( &p_playlist->object_lock );
168 playlist_Prev( p_playlist );
173 vlc_object_release( p_playlist );
176 - (IBAction)next:(id)sender
178 intf_thread_t * p_intf = [NSApp getIntf];
180 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
182 if( p_playlist == NULL )
187 vlc_mutex_lock( &p_playlist->object_lock );
189 if( p_playlist->p_input == NULL )
191 vlc_mutex_unlock( &p_playlist->object_lock );
192 vlc_object_release( p_playlist );
196 vlc_mutex_lock( &p_playlist->p_input->stream.stream_lock );
198 #define p_area p_playlist->p_input->stream.p_selected_area
200 if( p_area->i_part_nb > 1 && p_area->i_part + 1 < p_area->i_part_nb )
204 vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
205 input_ChangeArea( p_playlist->p_input, p_area );
206 vlc_mutex_unlock( &p_playlist->object_lock );
208 p_intf->p_sys->b_chapter_update = VLC_TRUE;
212 vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
213 vlc_mutex_unlock( &p_playlist->object_lock );
214 playlist_Next( p_playlist );
219 vlc_object_release( p_playlist );
222 - (IBAction)loop:(id)sender
224 intf_thread_t * p_intf = [NSApp getIntf];
226 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
228 if( p_playlist == NULL )
233 config_PutInt( p_playlist, "loop",
234 !config_GetInt( p_playlist, "loop" ) );
236 vlc_object_release( p_playlist );
239 - (IBAction)forward:(id)sender
241 intf_thread_t * p_intf = [NSApp getIntf];
242 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
244 if( p_playlist == NULL || p_playlist->p_input == NULL )
246 if ( p_playlist != NULL ) vlc_object_release( p_playlist );
250 input_Seek( p_playlist->p_input, 5, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
251 vlc_object_release( p_playlist );
254 - (IBAction)backward:(id)sender
256 intf_thread_t * p_intf = [NSApp getIntf];
257 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
259 if( p_playlist == NULL || p_playlist->p_input == NULL )
261 if ( p_playlist != NULL ) vlc_object_release( p_playlist );
265 input_Seek( p_playlist->p_input, -5, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
266 vlc_object_release( p_playlist );
269 - (IBAction)volumeUp:(id)sender
271 intf_thread_t * p_intf = [NSApp getIntf];
273 if( p_intf->p_sys->b_mute )
278 aout_VolumeUp( p_intf, 1, NULL );
280 [self updateVolumeSlider];
283 - (IBAction)volumeDown:(id)sender
285 intf_thread_t * p_intf = [NSApp getIntf];
287 if( p_intf->p_sys->b_mute )
292 aout_VolumeDown( p_intf, 1, NULL );
294 [self updateVolumeSlider];
297 - (IBAction)mute:(id)sender
299 intf_thread_t * p_intf = [NSApp getIntf];
300 audio_volume_t i_volume;
302 aout_VolumeMute( p_intf, &i_volume );
303 p_intf->p_sys->b_mute = ( i_volume == 0 );
305 [self updateVolumeSlider];
308 - (IBAction)volumeSliderUpdated:(id)sender
310 intf_thread_t * p_intf = [NSApp getIntf];
311 audio_volume_t i_volume = (audio_volume_t)[sender intValue];
313 aout_VolumeSet( p_intf, i_volume * AOUT_VOLUME_STEP );
316 - (void)updateVolumeSlider
318 intf_thread_t * p_intf = [NSApp getIntf];
319 audio_volume_t i_volume;
321 aout_VolumeGet( p_intf, &i_volume );
323 [o_volumeslider setFloatValue: (float)(i_volume / AOUT_VOLUME_STEP)];
326 - (IBAction)halfWindow:(id)sender
328 id o_window = [NSApp keyWindow];
329 NSArray *o_windows = [NSApp windows];
330 NSEnumerator *o_enumerator = [o_windows objectEnumerator];
332 while ((o_window = [o_enumerator nextObject]))
334 if( [[o_window className] isEqualToString: @"VLCWindow"] )
336 [o_window scaleWindowWithFactor: 0.5];
341 - (IBAction)normalWindow:(id)sender
343 id o_window = [NSApp keyWindow];
344 NSArray *o_windows = [NSApp windows];
345 NSEnumerator *o_enumerator = [o_windows objectEnumerator];
347 while ((o_window = [o_enumerator nextObject]))
349 if( [[o_window className] isEqualToString: @"VLCWindow"] )
351 [o_window scaleWindowWithFactor: 1];
356 - (IBAction)doubleWindow:(id)sender
358 id o_window = [NSApp keyWindow];
359 NSArray *o_windows = [NSApp windows];
360 NSEnumerator *o_enumerator = [o_windows objectEnumerator];
362 while ((o_window = [o_enumerator nextObject]))
364 if( [[o_window className] isEqualToString: @"VLCWindow"] )
366 [o_window scaleWindowWithFactor: 2];
372 - (IBAction)fullscreen:(id)sender
374 id o_window = [NSApp keyWindow];
375 NSArray *o_windows = [NSApp windows];
376 NSEnumerator *o_enumerator = [o_windows objectEnumerator];
378 while ((o_window = [o_enumerator nextObject]))
380 if( [[o_window className] isEqualToString: @"VLCWindow"] )
382 [o_window toggleFullscreen];
387 - (IBAction)deinterlace:(id)sender
389 intf_thread_t * p_intf = [NSApp getIntf];
390 BOOL bEnable = [sender state] == NSOffState;
394 config_PutPsz( p_intf, "filter", "deinterlace" );
395 config_PutPsz( p_intf, "deinterlace-mode",
396 [[sender title] lossyCString] );
400 config_PutPsz( p_intf, "filter", NULL );
404 - (IBAction)toggleProgram:(id)sender
406 NSMenuItem * o_mi = (NSMenuItem *)sender;
407 intf_thread_t * p_intf = [NSApp getIntf];
409 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
411 if( p_playlist == NULL )
416 vlc_mutex_lock( &p_playlist->object_lock );
418 if( p_playlist->p_input == NULL )
420 vlc_mutex_unlock( &p_playlist->object_lock );
421 vlc_object_release( p_playlist );
425 if( [o_mi state] == NSOffState )
427 u16 i_program_id = [o_mi tag];
429 input_ChangeProgram( p_playlist->p_input, i_program_id );
430 input_SetStatus( p_playlist->p_input, INPUT_STATUS_PLAY );
433 vlc_mutex_unlock( &p_playlist->object_lock );
434 vlc_object_release( p_playlist );
437 - (IBAction)toggleTitle:(id)sender
439 NSMenuItem * o_mi = (NSMenuItem *)sender;
440 intf_thread_t * p_intf = [NSApp getIntf];
442 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
444 if( p_playlist == NULL )
449 vlc_mutex_lock( &p_playlist->object_lock );
451 if( p_playlist->p_input == NULL )
453 vlc_mutex_unlock( &p_playlist->object_lock );
454 vlc_object_release( p_playlist );
458 if( [o_mi state] == NSOffState )
460 int i_title = [o_mi tag];
462 #define p_input p_playlist->p_input
463 input_ChangeArea( p_input, p_input->stream.pp_areas[i_title] );
464 input_SetStatus( p_input, INPUT_STATUS_PLAY );
468 vlc_mutex_unlock( &p_playlist->object_lock );
469 vlc_object_release( p_playlist );
472 - (IBAction)toggleChapter:(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_chapter = [o_mi tag];
497 #define p_input p_playlist->p_input
498 p_input->stream.p_selected_area->i_part = i_chapter;
499 input_ChangeArea( p_input, p_input->stream.p_selected_area );
500 input_SetStatus( p_input, INPUT_STATUS_PLAY );
504 vlc_mutex_unlock( &p_playlist->object_lock );
505 vlc_object_release( p_playlist );
508 - (IBAction)toggleLanguage:(id)sender
510 NSMenuItem * o_mi = (NSMenuItem *)sender;
511 intf_thread_t * p_intf = [NSApp getIntf];
513 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
515 if( p_playlist == NULL )
520 vlc_mutex_lock( &p_playlist->object_lock );
522 if( p_playlist->p_input == NULL )
524 vlc_mutex_unlock( &p_playlist->object_lock );
525 vlc_object_release( p_playlist );
530 /* We do not use this code, because you need to start stop .avi for
531 * it to work, so not very useful now --hartman */
532 if ( [o_mi state] == NSOffState && [o_mi tag] == 2000 )
534 NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
536 [o_open_panel setAllowsMultipleSelection: NO];
537 [o_open_panel setTitle: _NS("Open subtitle file")];
538 [o_open_panel setPrompt: _NS("Open")];
540 if( [o_open_panel runModalForDirectory: nil
541 file: nil types: nil] == NSOKButton )
543 NSString *o_filename = [[o_open_panel filenames] objectAtIndex: 0];
544 config_PutPsz( p_intf, "sub-file", strdup( [o_filename cString] ));
549 #define p_input p_playlist->p_input
551 if( !p_intf->p_sys->b_audio_update )
553 NSValue * o_value = [o_mi representedObject];
554 es_descriptor_t * p_es = [o_value pointerValue];
556 if( [o_mi state] == NSOnState )
558 /* we just have one ES to disable */
559 input_ToggleES( p_input, p_es, 0 );
564 int i_cat = [o_mi tag];
566 vlc_mutex_lock( &p_input->stream.stream_lock );
568 #define ES p_input->stream.pp_selected_es[i]
570 /* unselect the selected ES in the same class */
571 for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
573 if( ES->i_cat == i_cat )
575 vlc_mutex_unlock( &p_input->stream.stream_lock );
576 input_ToggleES( p_input, ES, 0 );
577 vlc_mutex_lock( &p_input->stream.stream_lock );
584 vlc_mutex_unlock( &p_input->stream.stream_lock );
586 input_ToggleES( p_input, p_es, 1 );
592 vlc_mutex_unlock( &p_playlist->object_lock );
593 vlc_object_release( p_playlist );
596 - (IBAction)toggleVar:(id)sender
598 NSMenuItem * o_mi = (NSMenuItem *)sender;
600 if( [o_mi state] == NSOffState )
602 const char * psz_variable = (const char *)[o_mi tag];
603 char * psz_value = [NSApp delocalizeString: [o_mi title]];
604 vlc_object_t * p_object = (vlc_object_t *)
605 [[o_mi representedObject] pointerValue];
607 /* psz_string sucks */
608 val.psz_string = (char *)psz_value;
610 if ( var_Set( p_object, psz_variable, val ) < 0 )
612 msg_Warn( p_object, "cannot set variable (%s)", psz_value );
621 @implementation VLCControls (NSMenuValidation)
623 - (BOOL)validateMenuItem:(NSMenuItem *)o_mi
625 BOOL bEnabled = TRUE;
626 NSMenu * o_menu = [o_mi menu];
627 intf_thread_t * p_intf = [NSApp getIntf];
629 playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
632 if( p_playlist != NULL )
634 vlc_mutex_lock( &p_playlist->object_lock );
637 #define p_input p_playlist->p_input
639 if( [[o_mi title] isEqualToString: _NS("Faster")] ||
640 [[o_mi title] isEqualToString: _NS("Slower")] )
642 if( p_playlist != NULL && p_input != NULL )
644 vlc_mutex_lock( &p_input->stream.stream_lock );
645 bEnabled = p_input->stream.b_pace_control;
646 vlc_mutex_unlock( &p_input->stream.stream_lock );
653 else if( [[o_mi title] isEqualToString: _NS("Stop")] )
655 if( p_playlist == NULL || p_input == NULL )
660 else if( [[o_mi title] isEqualToString: _NS("Previous")] ||
661 [[o_mi title] isEqualToString: _NS("Next")] )
663 if( p_playlist == NULL )
669 bEnabled = p_playlist->i_size > 1;
671 if( p_input != NULL )
673 vlc_mutex_lock( &p_input->stream.stream_lock );
674 bEnabled |= p_input->stream.p_selected_area->i_part_nb > 1;
675 vlc_mutex_unlock( &p_input->stream.stream_lock );
679 else if( [[o_mi title] isEqualToString: _NS("Loop")] )
681 int i_state = config_GetInt( p_playlist, "loop" ) ?
682 NSOnState : NSOffState;
684 [o_mi setState: i_state];
686 else if( [[o_mi title] isEqualToString: _NS("Step Forward")] ||
687 [[o_mi title] isEqualToString: _NS("Step Backward")] )
689 if( p_playlist != NULL && p_input != NULL )
691 vlc_mutex_lock( &p_input->stream.stream_lock );
692 bEnabled = p_input->stream.b_seekable;
693 vlc_mutex_unlock( &p_input->stream.stream_lock );
700 else if( [[o_mi title] isEqualToString: _NS("Mute")] )
702 [o_mi setState: p_intf->p_sys->b_mute ? NSOnState : NSOffState];
704 else if( [[o_mi title] isEqualToString: _NS("Fullscreen")] ||
705 [[o_mi title] isEqualToString: _NS("Half Size")] ||
706 [[o_mi title] isEqualToString: _NS("Normal Size")] ||
707 [[o_mi title] isEqualToString: _NS("Double Size")])
710 NSArray *o_windows = [NSApp windows];
711 NSEnumerator *o_enumerator = [o_windows objectEnumerator];
714 while ((o_window = [o_enumerator nextObject]))
716 if( [[o_window className] isEqualToString: @"VLCWindow"] )
723 else if( o_menu != nil &&
724 [[o_menu title] isEqualToString: _NS("Deinterlace")] )
726 char * psz_filter = config_GetPsz( p_intf, "filter" );
728 if( psz_filter != NULL )
732 psz_filter = config_GetPsz( p_intf, "deinterlace-mode" );
735 if( psz_filter != NULL )
737 if( strcmp( psz_filter, [[o_mi title] lossyCString] ) == 0 )
739 [o_mi setState: NSOnState];
743 [o_mi setState: NSOffState];
750 [o_mi setState: NSOffState];
754 if( p_playlist != NULL )
756 vlc_mutex_unlock( &p_playlist->object_lock );
757 vlc_object_release( p_playlist );