]> git.sesse.net Git - vlc/blob - modules/gui/macosx/controls.m
* aout_Volume* functions now do their own vlc_object_find() on the
[vlc] / modules / gui / macosx / controls.m
1 /*****************************************************************************
2  * controls.m: MacOS X interface plugin
3  *****************************************************************************
4  * Copyright (C) 2002 VideoLAN
5  * $Id: controls.m,v 1.24 2003/02/09 01:13:43 massiot Exp $
6  *
7  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8  *          Christophe Massiot <massiot@via.ecp.fr>
9  *          Derk-Jan Hartman <thedj@users.sourceforge.net>
10  *
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.
15  * 
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.
20  *
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  *****************************************************************************/
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29 #include <stdlib.h>                                      /* malloc(), free() */
30 #include <sys/param.h>                                    /* for MAXPATHLEN */
31 #include <string.h>
32
33 #include "intf.h"
34 #include "vout.h"
35
36 /*****************************************************************************
37  * VLCControls interface 
38  *****************************************************************************/
39 @interface VLCControls : NSObject
40 {
41     IBOutlet id o_open;
42     IBOutlet id o_main;
43
44     IBOutlet id o_volumeslider;
45 }
46
47 - (IBAction)play:(id)sender;
48 - (IBAction)stop:(id)sender;
49 - (IBAction)faster:(id)sender;
50 - (IBAction)slower:(id)sender;
51
52 - (IBAction)prev:(id)sender;
53 - (IBAction)next:(id)sender;
54 - (IBAction)loop:(id)sender;
55
56 - (IBAction)volumeUp:(id)sender;
57 - (IBAction)volumeDown:(id)sender;
58 - (IBAction)mute:(id)sender;
59 - (IBAction)volumeSliderUpdated:(id)sender;
60 - (void)updateVolumeSlider;
61
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;
67
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;
73
74 @end
75
76 /*****************************************************************************
77  * VLCControls implementation 
78  *****************************************************************************/
79 @implementation VLCControls
80
81 - (IBAction)play:(id)sender
82 {
83     intf_thread_t * p_intf = [NSApp getIntf];
84
85     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
86                                                        FIND_ANYWHERE );
87     if( p_playlist == NULL )
88     {
89         return;
90     }
91
92     if( playlist_IsPlaying( p_playlist ) )
93     {
94         playlist_Pause( p_playlist );
95         vlc_object_release( p_playlist );
96     }
97     else
98     {
99         if( !playlist_IsEmpty( p_playlist ) )
100         {
101             playlist_Play( p_playlist );
102             vlc_object_release( p_playlist );
103         }
104         else
105         {
106             vlc_object_release( p_playlist );
107             [o_open openFile: nil];
108         }
109     }
110 }
111
112 - (IBAction)stop:(id)sender
113 {
114     intf_thread_t * p_intf = [NSApp getIntf];
115
116     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
117                                                        FIND_ANYWHERE );
118     if( p_playlist == NULL )
119     {
120         return;
121     }
122
123     playlist_Stop( p_playlist );
124     vlc_object_release( p_playlist );
125 }
126
127 - (IBAction)faster:(id)sender
128 {
129     intf_thread_t * p_intf = [NSApp getIntf];
130
131     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
132                                                        FIND_ANYWHERE );
133     if( p_playlist == NULL )
134     {
135         return;
136     }
137
138     vlc_mutex_lock( &p_playlist->object_lock );
139     if( p_playlist->p_input != NULL )
140     {
141         input_SetStatus( p_playlist->p_input, INPUT_STATUS_FASTER );
142     } 
143     vlc_mutex_unlock( &p_playlist->object_lock );
144
145     vlc_object_release( p_playlist );
146 }
147
148 - (IBAction)slower:(id)sender
149 {
150     intf_thread_t * p_intf = [NSApp getIntf];
151
152     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
153                                                        FIND_ANYWHERE );
154     if( p_playlist == NULL )
155     {
156         return;
157     }
158
159     vlc_mutex_lock( &p_playlist->object_lock );
160     if( p_playlist->p_input != NULL )
161     {
162         input_SetStatus( p_playlist->p_input, INPUT_STATUS_SLOWER );
163     }
164     vlc_mutex_unlock( &p_playlist->object_lock );
165
166     vlc_object_release( p_playlist );
167 }
168
169 - (IBAction)prev:(id)sender
170 {
171     intf_thread_t * p_intf = [NSApp getIntf];
172
173     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
174                                                        FIND_ANYWHERE );
175     if( p_playlist == NULL )
176     {
177         return;
178     }
179
180     vlc_mutex_lock( &p_playlist->object_lock );
181
182     if( p_playlist->p_input == NULL )
183     {
184         vlc_mutex_unlock( &p_playlist->object_lock );
185         vlc_object_release( p_playlist );  
186         return;
187     }
188
189     vlc_mutex_lock( &p_playlist->p_input->stream.stream_lock );
190
191 #define p_area p_playlist->p_input->stream.p_selected_area
192
193     if( p_area->i_part_nb > 1 && p_area->i_part > 1 )
194     {
195         p_area->i_part--;
196
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 );
200
201         p_intf->p_sys->b_chapter_update = VLC_TRUE;
202     }
203     else
204     {
205         vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
206         vlc_mutex_unlock( &p_playlist->object_lock );
207         playlist_Prev( p_playlist );
208     }
209
210 #undef p_area
211
212     vlc_object_release( p_playlist );
213 }
214
215 - (IBAction)next:(id)sender
216 {
217     intf_thread_t * p_intf = [NSApp getIntf];
218
219     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
220                                                        FIND_ANYWHERE );
221     if( p_playlist == NULL )
222     {
223         return;
224     }
225
226     vlc_mutex_lock( &p_playlist->object_lock );
227
228     if( p_playlist->p_input == NULL )
229     {
230         vlc_mutex_unlock( &p_playlist->object_lock );
231         vlc_object_release( p_playlist );  
232         return;
233     }
234
235     vlc_mutex_lock( &p_playlist->p_input->stream.stream_lock );
236
237 #define p_area p_playlist->p_input->stream.p_selected_area
238
239     if( p_area->i_part_nb > 1 && p_area->i_part + 1 < p_area->i_part_nb )
240     {
241         p_area->i_part++;
242
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 );
246
247         p_intf->p_sys->b_chapter_update = VLC_TRUE;
248     }
249     else
250     {
251         vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
252         vlc_mutex_unlock( &p_playlist->object_lock );
253         playlist_Next( p_playlist );
254     }
255
256 #undef p_area
257
258     vlc_object_release( p_playlist );
259 }
260
261 - (IBAction)loop:(id)sender
262 {
263     intf_thread_t * p_intf = [NSApp getIntf];
264
265     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
266                                                        FIND_ANYWHERE );
267     if( p_playlist == NULL )
268     {
269         return;
270     }
271
272     config_PutInt( p_playlist, "loop",
273                    !config_GetInt( p_playlist, "loop" ) );
274
275     vlc_object_release( p_playlist );
276 }
277
278 - (IBAction)volumeUp:(id)sender
279 {
280     intf_thread_t * p_intf = [NSApp getIntf];
281
282     aout_VolumeUp( p_intf, 1, NULL );
283
284     if( p_intf->p_sys->b_mute )
285     {
286         [self mute: nil];
287     }
288
289     [self updateVolumeSlider];
290 }
291
292 - (IBAction)volumeDown:(id)sender
293 {
294     intf_thread_t * p_intf = [NSApp getIntf];
295
296     aout_VolumeDown( p_intf, 1, NULL );
297
298     if( p_intf->p_sys->b_mute )
299     {
300         [self mute: nil];
301     }
302
303     [self updateVolumeSlider];
304 }
305
306 - (IBAction)mute:(id)sender
307 {
308     intf_thread_t * p_intf = [NSApp getIntf];
309     audio_volume_t i_volume;
310
311     aout_VolumeMute( p_intf, &i_volume );
312     p_intf->p_sys->b_mute = ( i_volume == 0 );
313
314     [self updateVolumeSlider];
315 }
316
317 - (IBAction)volumeSliderUpdated:(id)sender
318 {
319     intf_thread_t * p_intf = [NSApp getIntf];
320     audio_volume_t i_volume = (audio_volume_t)[sender intValue];
321
322     aout_VolumeSet( p_intf, i_volume * AOUT_VOLUME_STEP );
323 }
324
325 - (void)updateVolumeSlider
326 {
327     intf_thread_t * p_intf = [NSApp getIntf];
328     audio_volume_t i_volume;
329
330     aout_VolumeGet( p_intf, &i_volume );
331
332     [o_volumeslider setFloatValue: (float)(i_volume / AOUT_VOLUME_STEP)]; 
333 }
334
335 - (IBAction)halfWindow:(id)sender
336 {
337     id o_window = [NSApp keyWindow];
338     NSArray *o_windows = [NSApp windows];
339     NSEnumerator *o_enumerator = [o_windows objectEnumerator];
340     
341     while ((o_window = [o_enumerator nextObject]))
342     {
343         if( [[o_window className] isEqualToString: @"VLCWindow"] )
344         {
345             [o_window scaleWindowWithFactor: 0.5];
346         }
347     }
348 }
349
350 - (IBAction)normalWindow:(id)sender
351 {
352     id o_window = [NSApp keyWindow];
353     NSArray *o_windows = [NSApp windows];
354     NSEnumerator *o_enumerator = [o_windows objectEnumerator];
355     
356     while ((o_window = [o_enumerator nextObject]))
357     {
358         if( [[o_window className] isEqualToString: @"VLCWindow"] )
359         {
360             [o_window scaleWindowWithFactor: 1];
361         }
362     }
363 }
364
365 - (IBAction)doubleWindow:(id)sender
366 {
367     id o_window = [NSApp keyWindow];
368     NSArray *o_windows = [NSApp windows];
369     NSEnumerator *o_enumerator = [o_windows objectEnumerator];
370     
371     while ((o_window = [o_enumerator nextObject]))
372     {
373         if( [[o_window className] isEqualToString: @"VLCWindow"] )
374         {
375             [o_window scaleWindowWithFactor: 2];
376         }
377     }
378 }
379
380
381 - (IBAction)fullscreen:(id)sender
382 {
383     id o_window = [NSApp keyWindow];
384     NSArray *o_windows = [NSApp windows];
385     NSEnumerator *o_enumerator = [o_windows objectEnumerator];
386     
387     while ((o_window = [o_enumerator nextObject]))
388     {
389         if( [[o_window className] isEqualToString: @"VLCWindow"] )
390         {
391             [o_window toggleFullscreen];
392         }
393     }
394 }
395
396 - (IBAction)deinterlace:(id)sender
397 {
398
399 }
400
401 - (IBAction)toggleProgram:(id)sender
402 {
403     NSMenuItem * o_mi = (NSMenuItem *)sender;
404     intf_thread_t * p_intf = [NSApp getIntf];
405
406     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
407                                                        FIND_ANYWHERE );
408     if( p_playlist == NULL )
409     {
410         return;
411     }
412
413     vlc_mutex_lock( &p_playlist->object_lock );
414
415     if( p_playlist->p_input == NULL )
416     {
417         vlc_mutex_unlock( &p_playlist->object_lock );
418         vlc_object_release( p_playlist );
419         return;
420     }
421
422     if( [o_mi state] == NSOffState )
423     {
424         u16 i_program_id = [o_mi tag];
425
426         input_ChangeProgram( p_playlist->p_input, i_program_id );
427         input_SetStatus( p_playlist->p_input, INPUT_STATUS_PLAY );
428     }
429
430     vlc_mutex_unlock( &p_playlist->object_lock );
431     vlc_object_release( p_playlist );
432 }
433
434 - (IBAction)toggleTitle:(id)sender
435 {
436     NSMenuItem * o_mi = (NSMenuItem *)sender;
437     intf_thread_t * p_intf = [NSApp getIntf];
438
439     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
440                                                        FIND_ANYWHERE );
441     if( p_playlist == NULL )
442     {
443         return;
444     }
445
446     vlc_mutex_lock( &p_playlist->object_lock );
447
448     if( p_playlist->p_input == NULL )
449     {
450         vlc_mutex_unlock( &p_playlist->object_lock );
451         vlc_object_release( p_playlist );
452         return;
453     }
454
455     if( [o_mi state] == NSOffState )
456     {
457         int i_title = [o_mi tag];
458
459 #define p_input p_playlist->p_input
460         input_ChangeArea( p_input, p_input->stream.pp_areas[i_title] );
461         input_SetStatus( p_input, INPUT_STATUS_PLAY );
462 #undef p_input
463     }
464
465     vlc_mutex_unlock( &p_playlist->object_lock );
466     vlc_object_release( p_playlist );
467 }
468
469 - (IBAction)toggleChapter:(id)sender
470 {
471     NSMenuItem * o_mi = (NSMenuItem *)sender;
472     intf_thread_t * p_intf = [NSApp getIntf];
473
474     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
475                                                        FIND_ANYWHERE );
476     if( p_playlist == NULL )
477     {
478         return;
479     }
480
481     vlc_mutex_lock( &p_playlist->object_lock );
482
483     if( p_playlist->p_input == NULL )
484     {
485         vlc_mutex_unlock( &p_playlist->object_lock );
486         vlc_object_release( p_playlist );
487         return;
488     }
489
490     if( [o_mi state] == NSOffState )
491     {
492         int i_chapter = [o_mi tag];
493
494 #define p_input p_playlist->p_input
495         p_input->stream.p_selected_area->i_part = i_chapter;
496         input_ChangeArea( p_input, p_input->stream.p_selected_area );
497         input_SetStatus( p_input, INPUT_STATUS_PLAY );
498 #undef p_input
499     }
500
501     vlc_mutex_unlock( &p_playlist->object_lock );
502     vlc_object_release( p_playlist );
503 }
504
505 - (IBAction)toggleLanguage:(id)sender
506 {
507     NSMenuItem * o_mi = (NSMenuItem *)sender;
508     intf_thread_t * p_intf = [NSApp getIntf];
509
510     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
511                                                        FIND_ANYWHERE );
512     if( p_playlist == NULL )
513     {
514         return;
515     }
516
517     vlc_mutex_lock( &p_playlist->object_lock );
518
519     if( p_playlist->p_input == NULL )
520     {
521         vlc_mutex_unlock( &p_playlist->object_lock );
522         vlc_object_release( p_playlist );
523         return;
524     }
525
526 #if 0
527     /* We do not use this code, because you need to start stop .avi for
528      * it to work, so not very useful now  --hartman */
529     if ( [o_mi state] == NSOffState && [o_mi tag] == 2000 )
530     {
531         NSOpenPanel *o_open_panel = [NSOpenPanel openPanel];
532         
533         [o_open_panel setAllowsMultipleSelection: NO];
534         [o_open_panel setTitle: _NS("Open subtitle file")];
535         [o_open_panel setPrompt: _NS("Open")];
536     
537         if( [o_open_panel runModalForDirectory: nil 
538                 file: nil types: nil] == NSOKButton )
539         {
540             NSString *o_filename = [[o_open_panel filenames] objectAtIndex: 0];
541             config_PutPsz( p_intf, "sub-file", strdup( [o_filename cString] ));
542         }
543     }
544 #endif
545
546 #define p_input p_playlist->p_input
547
548     if( !p_intf->p_sys->b_audio_update )
549     {
550         NSValue * o_value = [o_mi representedObject];
551         es_descriptor_t * p_es = [o_value pointerValue];
552
553         if( [o_mi state] == NSOnState )
554         {
555             /* we just have one ES to disable */
556             input_ToggleES( p_input, p_es, 0 );
557         }
558         else
559         {
560             unsigned int i;
561             int i_cat = [o_mi tag];
562
563             vlc_mutex_lock( &p_input->stream.stream_lock );
564
565 #define ES p_input->stream.pp_selected_es[i]
566
567             /* unselect the selected ES in the same class */
568             for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
569             {
570                 if( ES->i_cat == i_cat )
571                 {
572                     vlc_mutex_unlock( &p_input->stream.stream_lock );
573                     input_ToggleES( p_input, ES, 0 );
574                     vlc_mutex_lock( &p_input->stream.stream_lock );
575                     break;
576                 }
577             }
578
579 #undef ES
580
581             vlc_mutex_unlock( &p_input->stream.stream_lock );
582
583             input_ToggleES( p_input, p_es, 1 );
584         }
585     }
586
587 #undef p_input
588
589     vlc_mutex_unlock( &p_playlist->object_lock );
590     vlc_object_release( p_playlist );
591 }
592
593 - (IBAction)toggleVar:(id)sender
594 {
595     NSMenuItem * o_mi = (NSMenuItem *)sender;
596     
597     if( [o_mi state] == NSOffState )
598     {
599         const char * psz_variable = (const char *)[o_mi tag];
600         char * psz_value = [NSApp delocalizeString: [o_mi title]];
601         vlc_object_t * p_object = (vlc_object_t *)
602             [[o_mi representedObject] pointerValue];
603         vlc_value_t val;
604         /* psz_string sucks */
605         val.psz_string = (char *)psz_value;
606
607         if ( var_Set( p_object, psz_variable, val ) < 0 )
608         {
609             msg_Warn( p_object, "cannot set variable (%s)", psz_value );
610         }
611
612         free( psz_value );
613     }
614 }
615
616 @end
617
618 @implementation VLCControls (NSMenuValidation)
619  
620 - (BOOL)validateMenuItem:(NSMenuItem *)o_mi
621 {
622     BOOL bEnabled = TRUE;
623     NSMenu * o_menu = [o_mi menu];
624     intf_thread_t * p_intf = [NSApp getIntf];
625
626     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
627                                                        FIND_ANYWHERE );
628
629     if( p_playlist != NULL )
630     {
631         vlc_mutex_lock( &p_playlist->object_lock );
632     }
633
634 #define p_input p_playlist->p_input
635
636     if( [[o_mi title] isEqualToString: _NS("Faster")] ||
637         [[o_mi title] isEqualToString: _NS("Slower")] )
638     {
639         if( p_playlist != NULL && p_input != NULL )
640         {
641             vlc_mutex_lock( &p_input->stream.stream_lock );
642             bEnabled = p_input->stream.b_pace_control;
643             vlc_mutex_unlock( &p_input->stream.stream_lock );
644         }
645         else
646         {
647             bEnabled = FALSE;
648         }
649     }
650     else if( [[o_mi title] isEqualToString: _NS("Stop")] )
651     {
652         if( p_playlist == NULL || p_input == NULL )
653         {
654             bEnabled = FALSE;
655         }
656     }
657     else if( [[o_mi title] isEqualToString: _NS("Previous")] ||
658              [[o_mi title] isEqualToString: _NS("Next")] )
659     {
660         if( p_playlist == NULL )
661         {
662             bEnabled = FALSE;
663         }
664         else
665         {
666             bEnabled = p_playlist->i_size > 1;
667
668             if( p_input != NULL )
669             {
670                 vlc_mutex_lock( &p_input->stream.stream_lock );
671                 bEnabled |= p_input->stream.p_selected_area->i_part_nb > 1;
672                 vlc_mutex_unlock( &p_input->stream.stream_lock );
673             }
674         }
675     }
676     else if( [[o_mi title] isEqualToString: _NS("Loop")] )
677     {
678         int i_state = config_GetInt( p_playlist, "loop" ) ?
679                       NSOnState : NSOffState;
680
681         [o_mi setState: i_state];
682     }
683     else if( [[o_mi title] isEqualToString: _NS("Mute")] ) 
684     {
685         [o_mi setState: p_intf->p_sys->b_mute ? NSOnState : NSOffState];
686     }
687     else if( [[o_mi title] isEqualToString: _NS("Fullscreen")] ||
688                 [[o_mi title] isEqualToString: _NS("Half Size")] ||
689                 [[o_mi title] isEqualToString: _NS("Normal Size")] ||
690                 [[o_mi title] isEqualToString: _NS("Double Size")])    
691     {
692         id o_window;
693         NSArray *o_windows = [NSApp windows];
694         NSEnumerator *o_enumerator = [o_windows objectEnumerator];
695         bEnabled = FALSE;
696         
697         while ((o_window = [o_enumerator nextObject]))
698         {
699             if( [[o_window className] isEqualToString: @"VLCWindow"] )
700             {
701                 bEnabled = TRUE;
702                 break;
703             }
704         }
705     }
706     else if( o_menu != nil && 
707              [[o_menu title] isEqualToString: _NS("Deinterlace")] )
708     { 
709
710     } 
711
712     if( p_playlist != NULL )
713     {
714         vlc_mutex_unlock( &p_playlist->object_lock );
715         vlc_object_release( p_playlist );
716     }
717
718     return( bEnabled );
719 }
720
721 @end