]> git.sesse.net Git - vlc/blob - modules/gui/macosx/controls.m
0fcc0707dedcff2e02346763cba4dc7b002bbeed
[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.5 2003/01/04 04:11:08 jlj Exp $
6  *
7  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
8  *          Christophe Massiot <massiot@via.ecp.fr>
9  *
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.
14  * 
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.
19  *
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  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>                                      /* malloc(), free() */
29 #include <sys/param.h>                                    /* for MAXPATHLEN */
30 #include <string.h>
31
32 #include <vlc/vlc.h>
33 #include <vlc/intf.h>
34 #include <vlc/aout.h>
35
36 #include <Cocoa/Cocoa.h> 
37 #include <CoreAudio/AudioHardware.h>
38
39 #include "intf.h"
40 #include "vout.h"
41
42 /*****************************************************************************
43  * VLCControls interface 
44  *****************************************************************************/
45 @interface VLCControls : NSObject
46 {
47     IBOutlet id o_open;
48 }
49
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;
55
56 - (IBAction)prev:(id)sender;
57 - (IBAction)next:(id)sender;
58 - (IBAction)loop:(id)sender;
59
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;
65
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;
71
72 @end
73
74 /*****************************************************************************
75  * VLCControls implementation 
76  *****************************************************************************/
77 @implementation VLCControls
78
79 - (IBAction)play:(id)sender
80 {
81     intf_thread_t * p_intf = [NSApp getIntf];
82     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
83                                                        FIND_ANYWHERE );
84     if( p_playlist == NULL )
85     {
86         return;
87     }
88
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 )
92     {
93         vlc_mutex_unlock( &p_playlist->object_lock );
94         playlist_Play( p_playlist );
95         vlc_object_release( p_playlist );
96     }
97     else
98     {
99         vlc_mutex_unlock( &p_playlist->object_lock );
100         vlc_object_release( p_playlist );
101
102         [o_open openFile: nil];
103     }
104 }
105
106 - (IBAction)pause:(id)sender
107 {
108     intf_thread_t * p_intf = [NSApp getIntf];
109
110     if( p_intf->p_sys->p_input == NULL )
111     {
112         return;
113     }
114
115     input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PAUSE );
116 }
117
118 - (IBAction)stop:(id)sender
119 {
120     intf_thread_t * p_intf = [NSApp getIntf];
121     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
122                                                        FIND_ANYWHERE );
123     if( p_playlist == NULL )
124     {
125         return;
126     }
127
128     playlist_Stop( p_playlist );
129     vlc_object_release( p_playlist );
130 }
131
132 - (IBAction)faster:(id)sender
133 {
134     intf_thread_t * p_intf = [NSApp getIntf];
135
136     if( p_intf->p_sys->p_input == NULL )
137     {
138         return;
139     }
140
141     input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_FASTER );
142 }
143
144 - (IBAction)slower:(id)sender
145 {
146     intf_thread_t * p_intf = [NSApp getIntf];
147
148     if( p_intf->p_sys->p_input == NULL )
149     {
150         return;
151     }
152
153     input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_SLOWER );
154 }
155
156 - (IBAction)prev:(id)sender
157 {
158     intf_thread_t * p_intf = [NSApp getIntf];
159     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
160                                                        FIND_ANYWHERE );
161     if( p_playlist == NULL )
162     {
163         return;
164     }
165
166     playlist_Prev( p_playlist );
167     vlc_object_release( p_playlist );
168 }
169
170 - (IBAction)next:(id)sender
171 {
172     intf_thread_t * p_intf = [NSApp getIntf];
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     playlist_Next( p_playlist );
181     vlc_object_release( p_playlist );
182 }
183
184 - (IBAction)loop:(id)sender
185 {
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,
189                                                        FIND_ANYWHERE );
190     if( p_playlist == NULL )
191     {
192         return;
193     }
194
195     if( p_intf->p_sys->b_loop )
196     {
197         [o_mi setState: NSOffState];
198         config_PutInt( p_playlist, "loop", 0 );
199     }
200     else
201     {
202         [o_mi setState: NSOnState];
203         config_PutInt( p_playlist, "loop", 1 );
204     }
205
206     p_intf->p_sys->b_loop = !p_intf->p_sys->b_loop;
207
208     vlc_object_release( p_playlist );
209 }
210
211 - (IBAction)volumeUp:(id)sender
212 {
213     intf_thread_t * p_intf = [NSApp getIntf];
214     aout_instance_t * p_aout = vlc_object_find( p_intf, VLC_OBJECT_AOUT,
215                                                 FIND_ANYWHERE );
216
217     if ( p_aout != NULL )
218     {
219         aout_VolumeUp( p_aout, 1, NULL );
220         vlc_object_release( (vlc_object_t *)p_aout );
221     }
222 }
223
224 - (IBAction)volumeDown:(id)sender
225 {
226     intf_thread_t * p_intf = [NSApp getIntf];
227     aout_instance_t * p_aout = vlc_object_find( p_intf, VLC_OBJECT_AOUT,
228                                                 FIND_ANYWHERE );
229
230     if ( p_aout != NULL )
231     {
232         aout_VolumeDown( p_aout, 1, NULL );
233         vlc_object_release( (vlc_object_t *)p_aout );
234     }
235 }
236
237 - (IBAction)mute:(id)sender
238 {
239     intf_thread_t * p_intf = [NSApp getIntf];
240     aout_instance_t * p_aout = vlc_object_find( p_intf, VLC_OBJECT_AOUT,
241                                                 FIND_ANYWHERE );
242
243     if ( p_aout != NULL )
244     {
245         aout_VolumeMute( p_aout, NULL );
246         vlc_object_release( (vlc_object_t *)p_aout );
247     }
248
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];
252 }
253
254 - (IBAction)fullscreen:(id)sender
255 {
256     id o_window = [NSApp keyWindow];
257
258     if( [[o_window className] isEqualToString: @"VLCWindow"] )
259     {
260         [o_window toggleFullscreen];
261     }
262 }
263
264 - (IBAction)deinterlace:(id)sender
265 {
266     intf_thread_t * p_intf = [NSApp getIntf];
267     BOOL bEnable = [sender state] == NSOffState;
268
269     if( bEnable )
270     {
271         config_PutPsz( p_intf, "filter", "deinterlace" );
272         config_PutPsz( p_intf, "deinterlace-mode", 
273                        [[sender title] lossyCString] );
274     }
275     else
276     {
277         config_PutPsz( p_intf, "filter", NULL );
278     }
279 }
280
281 - (IBAction)toggleProgram:(id)sender
282 {
283     NSMenuItem * o_mi = (NSMenuItem *)sender;
284     intf_thread_t * p_intf = [NSApp getIntf];
285
286     if( [o_mi state] == NSOffState )
287     {
288         u16 i_program_id = [o_mi tag];
289
290         input_ChangeProgram( p_intf->p_sys->p_input, i_program_id );
291         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
292     }
293 }
294
295 - (IBAction)toggleTitle:(id)sender
296 {
297     NSMenuItem * o_mi = (NSMenuItem *)sender;
298     intf_thread_t * p_intf = [NSApp getIntf];
299
300     if( [o_mi state] == NSOffState )
301     {
302         int i_title = [o_mi tag];
303
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 );
307 #undef p_input
308     }
309 }
310
311 - (IBAction)toggleChapter:(id)sender
312 {
313     NSMenuItem * o_mi = (NSMenuItem *)sender;
314     intf_thread_t * p_intf = [NSApp getIntf];
315
316     if( [o_mi state] == NSOffState )
317     {
318         int i_chapter = [o_mi tag];
319
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 );
324 #undef p_input
325     }
326 }
327
328 - (IBAction)toggleLanguage:(id)sender
329 {
330     NSMenuItem * o_mi = (NSMenuItem *)sender;
331     intf_thread_t * p_intf = [NSApp getIntf];
332
333 #define p_input p_intf->p_sys->p_input
334
335     if( !p_intf->p_sys->b_audio_update )
336     {
337         NSValue * o_value = [o_mi representedObject];
338         es_descriptor_t * p_es = [o_value pointerValue];
339
340         if( [o_mi state] == NSOnState )
341         {
342             /* we just have one ES to disable */
343             input_ToggleES( p_input, p_es, 0 );
344         }
345         else
346         {
347             unsigned int i;
348             int i_cat = [o_mi tag];
349
350             vlc_mutex_lock( &p_input->stream.stream_lock );
351
352 #define ES p_input->stream.pp_selected_es[i]
353
354             /* unselect the selected ES in the same class */
355             for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
356             {
357                 if( ES->i_cat == i_cat )
358                 {
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 );
362                     break;
363                 }
364             }
365
366 #undef ES
367
368             vlc_mutex_unlock( &p_input->stream.stream_lock );
369
370             input_ToggleES( p_input, p_es, 1 );
371         }
372     }
373
374 #undef p_input
375 }
376
377 - (IBAction)toggleVar:(id)sender
378 {
379     NSMenuItem * o_mi = (NSMenuItem *)sender;
380
381     if( [o_mi state] == NSOffState )
382     {
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];
387         vlc_value_t val;
388         /* psz_string sucks */
389         val.psz_string = (char *)psz_value;
390
391         if ( var_Set( p_object, psz_variable, val ) < 0 )
392         {
393             msg_Warn( p_object, "cannot set variable (%s)", psz_value );
394         }
395     }
396 }
397
398 @end
399
400 @implementation VLCControls (NSMenuValidation)
401  
402 - (BOOL)validateMenuItem:(NSMenuItem *)o_mi
403 {
404     BOOL bEnabled = TRUE;
405     NSMenu * o_menu = [o_mi menu];
406     intf_thread_t * p_intf = [NSApp getIntf];
407
408     if( [[o_mi title] isEqualToString: _NS("Pause")] ||
409         [[o_mi title] isEqualToString: _NS("Faster")] ||
410         [[o_mi title] isEqualToString: _NS("Slower")] )
411     {
412         if( p_intf->p_sys->p_input != NULL )
413         {
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 );
418 #undef p_input
419         }
420         else
421         {
422             bEnabled = FALSE;
423         }
424     }
425     else if( [[o_mi title] isEqualToString: _NS("Stop")] )
426     {
427         bEnabled = p_intf->p_sys->p_input != NULL;
428     }
429     else if( [[o_mi title] isEqualToString: _NS("Previous")] ||
430              [[o_mi title] isEqualToString: _NS("Next")] )
431     {
432         playlist_t * p_playlist = vlc_object_find( p_intf, 
433                                                    VLC_OBJECT_PLAYLIST,
434                                                    FIND_ANYWHERE );
435         if( p_playlist == NULL )
436         {
437             bEnabled = FALSE;
438         }
439         else
440         {
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 );
445         }
446     }
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")] )
450     {
451         aout_instance_t * p_aout = vlc_object_find( p_intf, VLC_OBJECT_AOUT,
452                                                     FIND_ANYWHERE );
453  
454         if ( p_aout != NULL )
455         { 
456             vlc_object_release( (vlc_object_t *)p_aout );
457         }
458         else
459         {
460             bEnabled = FALSE;
461         }
462     }
463     else if( [[o_mi title] isEqualToString: _NS("Fullscreen")] )    
464     {
465         id o_window = [NSApp keyWindow];
466
467         if( [[o_window className] isEqualToString: @"VLCWindow"] )
468         {
469             [o_mi setState: [o_window isFullscreen] ? 
470                              NSOnState : NSOffState]; 
471         }
472         else
473         {
474             bEnabled = FALSE;
475         }
476     }
477     else if( o_menu != nil && 
478              [[o_menu title] isEqualToString: _NS("Deinterlace")] )
479     { 
480         char * psz_filter = config_GetPsz( p_intf, "filter" );
481
482         if( psz_filter != NULL )
483         {
484             free( psz_filter );
485
486             psz_filter = config_GetPsz( p_intf, "deinterlace-mode" );
487         }
488
489         if( psz_filter != NULL )
490         {
491             if( strcmp( psz_filter, [[o_mi title] lossyCString] ) == 0 )
492             {
493                 [o_mi setState: NSOnState]; 
494             }
495             else
496             {
497                 [o_mi setState: NSOffState];
498             }
499
500             free( psz_filter );
501         } 
502         else
503         {
504             [o_mi setState: NSOffState];
505         }
506     } 
507
508     return( bEnabled );
509 }
510
511 @end