]> git.sesse.net Git - vlc/blob - modules/gui/macosx/controls.m
* ./modules/*: moved plugins to the new tree. Yet untested builds include
[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.1 2002/08/04 17:23:43 sam 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
35 #include <Cocoa/Cocoa.h> 
36 #include <CoreAudio/AudioHardware.h>
37
38 #include "intf.h"
39 #include "vout.h"
40
41 /*****************************************************************************
42  * VLCControls interface 
43  *****************************************************************************/
44 @interface VLCControls : NSObject
45 {
46     IBOutlet id o_open;
47 }
48
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;
54
55 - (IBAction)prev:(id)sender;
56 - (IBAction)next:(id)sender;
57 - (IBAction)loop:(id)sender;
58
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;
64
65 - (IBAction)toggleProgram:(id)sender;
66 - (IBAction)toggleTitle:(id)sender;
67 - (IBAction)toggleChapter:(id)sender;
68 - (IBAction)toggleLanguage:(id)sender;
69
70 @end
71
72 /*****************************************************************************
73  * VLCControls implementation 
74  *****************************************************************************/
75 @implementation VLCControls
76
77 - (IBAction)play:(id)sender
78 {
79     intf_thread_t * p_intf = [NSApp getIntf];
80     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
81                                                        FIND_ANYWHERE );
82     if( p_playlist == NULL )
83     {
84         return;
85     }
86
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 )
90     {
91         vlc_mutex_unlock( &p_playlist->object_lock );
92         playlist_Play( p_playlist );
93         vlc_object_release( p_playlist );
94     }
95     else
96     {
97         vlc_mutex_unlock( &p_playlist->object_lock );
98         vlc_object_release( p_playlist );
99
100         [o_open openFile: nil];
101     }
102 }
103
104 - (IBAction)pause:(id)sender
105 {
106     intf_thread_t * p_intf = [NSApp getIntf];
107
108     if( p_intf->p_sys->p_input == NULL )
109     {
110         return;
111     }
112
113     input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PAUSE );
114 }
115
116 - (IBAction)stop:(id)sender
117 {
118     intf_thread_t * p_intf = [NSApp getIntf];
119     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
120                                                        FIND_ANYWHERE );
121     if( p_playlist == NULL )
122     {
123         return;
124     }
125
126     playlist_Stop( p_playlist );
127     vlc_object_release( p_playlist );
128 }
129
130 - (IBAction)faster:(id)sender
131 {
132     intf_thread_t * p_intf = [NSApp getIntf];
133
134     if( p_intf->p_sys->p_input == NULL )
135     {
136         return;
137     }
138
139     input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_FASTER );
140 }
141
142 - (IBAction)slower:(id)sender
143 {
144     intf_thread_t * p_intf = [NSApp getIntf];
145
146     if( p_intf->p_sys->p_input == NULL )
147     {
148         return;
149     }
150
151     input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_SLOWER );
152 }
153
154 - (IBAction)prev:(id)sender
155 {
156     intf_thread_t * p_intf = [NSApp getIntf];
157     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
158                                                        FIND_ANYWHERE );
159     if( p_playlist == NULL )
160     {
161         return;
162     }
163
164     playlist_Prev( p_playlist );
165     vlc_object_release( p_playlist );
166 }
167
168 - (IBAction)next:(id)sender
169 {
170     intf_thread_t * p_intf = [NSApp getIntf];
171     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
172                                                        FIND_ANYWHERE );
173     if( p_playlist == NULL )
174     {
175         return;
176     }
177
178     playlist_Next( p_playlist );
179     vlc_object_release( p_playlist );
180 }
181
182 - (IBAction)loop:(id)sender
183 {
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,
187                                                        FIND_ANYWHERE );
188     if( p_playlist == NULL )
189     {
190         return;
191     }
192
193     if( p_intf->p_sys->b_loop )
194     {
195         [o_mi setState: NSOffState];
196         playlist_Delete( p_playlist, p_playlist->i_size - 1 );
197     }
198     else
199     {
200         [o_mi setState: NSOnState];
201         playlist_Add( p_playlist, "vlc:loop",
202                       PLAYLIST_APPEND, PLAYLIST_END );
203     }
204
205     p_intf->p_sys->b_loop = !p_intf->p_sys->b_loop;
206
207     vlc_object_release( p_playlist );
208 }
209
210 - (IBAction)volumeUp:(id)sender
211 {
212     /*
213     intf_thread_t * p_intf = [NSApp getIntf];
214     */
215
216     /* TODO, kAudioDevicePropertyVolumeScalar */
217 }
218
219 - (IBAction)volumeDown:(id)sender
220 {
221     /*
222     intf_thread_t * p_intf = [NSApp getIntf];
223     */
224
225     /* TODO, kAudioDevicePropertyVolumeScalar */
226 }
227
228 - (IBAction)mute:(id)sender
229 {
230     OSStatus err;
231     AudioDeviceID device;
232     UInt32 ui_param_size;
233
234     NSMenuItem * o_mi = (NSMenuItem *)sender;
235     intf_thread_t * p_intf = [NSApp getIntf];
236     UInt32 b_mute = !p_intf->p_sys->b_mute;
237
238     [o_mi setState: b_mute ? NSOnState : NSOffState];
239     p_intf->p_sys->b_mute = !p_intf->p_sys->b_mute;
240
241     ui_param_size = sizeof( device );
242     err = AudioHardwareGetProperty( kAudioHardwarePropertyDefaultOutputDevice,
243                                     &ui_param_size, (void *)&device );
244     if( err != noErr )
245     {
246         msg_Err( p_intf, "AudioHardwareGetProperty failed (%d)", err );
247         return;
248     }
249
250     ui_param_size = sizeof( b_mute );
251     err = AudioDeviceSetProperty( device, 0, 0, false,
252                                   kAudioDevicePropertyMute,
253                                   ui_param_size, (void *)&b_mute );
254     if( err != noErr )
255     {
256         msg_Err( p_intf, "AudioDeviceSetProperty failed (%d)", err );
257         return;
258     }
259 }
260
261 - (IBAction)fullscreen:(id)sender
262 {
263     id o_window = [NSApp keyWindow];
264
265     if( [[o_window className] isEqualToString: @"VLCWindow"] )
266     {
267         [o_window toggleFullscreen];
268     }
269 }
270
271 - (IBAction)deinterlace:(id)sender
272 {
273     intf_thread_t * p_intf = [NSApp getIntf];
274     BOOL bEnable = [sender state] == NSOffState;
275
276     if( bEnable )
277     {
278         config_PutPsz( p_intf, "filter", "deinterlace" );
279         config_PutPsz( p_intf, "deinterlace-mode", 
280                        [[sender title] lossyCString] );
281     }
282     else
283     {
284         config_PutPsz( p_intf, "filter", NULL );
285     }
286 }
287
288 - (IBAction)toggleProgram:(id)sender
289 {
290     NSMenuItem * o_mi = (NSMenuItem *)sender;
291     intf_thread_t * p_intf = [NSApp getIntf];
292
293     if( [o_mi state] == NSOffState )
294     {
295         u16 i_program_id = [o_mi tag];
296
297         input_ChangeProgram( p_intf->p_sys->p_input, i_program_id );
298         input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PLAY );
299     }
300 }
301
302 - (IBAction)toggleTitle:(id)sender
303 {
304     NSMenuItem * o_mi = (NSMenuItem *)sender;
305     intf_thread_t * p_intf = [NSApp getIntf];
306
307     if( [o_mi state] == NSOffState )
308     {
309         int i_title = [o_mi tag];
310
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 );
314 #undef p_input
315     }
316 }
317
318 - (IBAction)toggleChapter:(id)sender
319 {
320     NSMenuItem * o_mi = (NSMenuItem *)sender;
321     intf_thread_t * p_intf = [NSApp getIntf];
322
323     if( [o_mi state] == NSOffState )
324     {
325         int i_chapter = [o_mi tag];
326
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 );
331 #undef p_input
332     }
333 }
334
335 - (IBAction)toggleLanguage:(id)sender
336 {
337     NSMenuItem * o_mi = (NSMenuItem *)sender;
338     intf_thread_t * p_intf = [NSApp getIntf];
339
340 #define p_input p_intf->p_sys->p_input
341
342     if( !p_intf->p_sys->b_audio_update )
343     {
344         NSValue * o_value = [o_mi representedObject];
345         es_descriptor_t * p_es = [o_value pointerValue];
346
347         if( [o_mi state] == NSOnState )
348         {
349             /* we just have one ES to disable */
350             input_ToggleES( p_input, p_es, 0 );
351         }
352         else
353         {
354             int i;
355             int i_cat = [o_mi tag];
356
357             vlc_mutex_lock( &p_input->stream.stream_lock );
358
359 #define ES p_input->stream.pp_selected_es[i]
360
361             /* unselect the selected ES in the same class */
362             for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
363             {
364                 if( ES->i_cat == i_cat )
365                 {
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 );
369                     break;
370                 }
371             }
372
373 #undef ES
374
375             vlc_mutex_unlock( &p_input->stream.stream_lock );
376
377             input_ToggleES( p_input, p_es, 1 );
378         }
379     }
380
381 #undef p_input
382 }
383
384 @end
385
386 @implementation VLCControls (NSMenuValidation)
387  
388 - (BOOL)validateMenuItem:(NSMenuItem *)o_mi
389 {
390     BOOL bEnabled = TRUE;
391     NSMenu * o_menu = [o_mi menu];
392     intf_thread_t * p_intf = [NSApp getIntf];
393
394     if( [[o_mi title] isEqualToString: _NS("Pause")] ||
395         [[o_mi title] isEqualToString: _NS("Faster")] ||
396         [[o_mi title] isEqualToString: _NS("Slower")] )
397     {
398         if( p_intf->p_sys->p_input != NULL )
399         {
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 );
404 #undef p_input
405         }
406         else
407         {
408             bEnabled = FALSE;
409         }
410     }
411     else if( [[o_mi title] isEqualToString: _NS("Stop")] )
412     {
413         bEnabled = p_intf->p_sys->p_input != NULL;
414     }
415     else if( [[o_mi title] isEqualToString: _NS("Prev")] ||
416              [[o_mi title] isEqualToString: _NS("Next")] )
417     {
418         playlist_t * p_playlist = vlc_object_find( p_intf, 
419                                                    VLC_OBJECT_PLAYLIST,
420                                                    FIND_ANYWHERE );
421         if( p_playlist == NULL )
422         {
423             bEnabled = FALSE;
424         }
425         else
426         {
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 );
431         }
432     }
433     else if( [[o_mi title] isEqualToString: _NS("Volume Up")] ||
434              [[o_mi title] isEqualToString: _NS("Volume Down")] )
435     {
436         bEnabled = FALSE; /* not implemented yet */
437     }
438     else if( [[o_mi title] isEqualToString: _NS("Mute")] )
439     {
440         OSStatus err;
441         UInt32 b_mute;
442         AudioDeviceID device;
443         UInt32 ui_param_size;
444
445         ui_param_size = sizeof( device );
446         err = AudioHardwareGetProperty( 
447                             kAudioHardwarePropertyDefaultOutputDevice,
448                             &ui_param_size, (void *)&device );
449         if( err != noErr )
450         {
451             msg_Err( p_intf, "AudioHardwareGetProperty failed (%d)", err );
452         }
453         else
454         {
455             ui_param_size = sizeof( b_mute );
456             err = AudioDeviceGetProperty( device, 0, 0,
457                                           kAudioDevicePropertyMute,
458                                           &ui_param_size, (void *)&b_mute );
459             if( err != noErr )
460             {
461                 msg_Err( p_intf, "AudioDeviceGetProperty failed (%d)", err );
462             }
463             else
464             {
465                 [o_mi setState: b_mute ? NSOnState : NSOffState];
466                 p_intf->p_sys->b_mute = (vlc_bool_t)b_mute ? 1 : 0;
467             }
468         }
469     }
470     else if( [[o_mi title] isEqualToString: _NS("Fullscreen")] )    
471     {
472         id o_window = [NSApp keyWindow];
473
474         if( [[o_window className] isEqualToString: @"VLCWindow"] )
475         {
476             [o_mi setState: [o_window isFullscreen] ? 
477                              NSOnState : NSOffState]; 
478         }
479         else
480         {
481             bEnabled = FALSE;
482         }
483     }
484     else if( o_menu != nil && 
485              [[o_menu title] isEqualToString: _NS("Deinterlace")] )
486     { 
487         char * psz_filter = config_GetPsz( p_intf, "filter" );
488
489         if( psz_filter != NULL )
490         {
491             free( psz_filter );
492
493             psz_filter = config_GetPsz( p_intf, "deinterlace-mode" );
494         }
495
496         if( psz_filter != NULL )
497         {
498             if( strcmp( psz_filter, [[o_mi title] lossyCString] ) == 0 )
499             {
500                 [o_mi setState: NSOnState]; 
501             }
502             else
503             {
504                 [o_mi setState: NSOffState];
505             }
506
507             free( psz_filter );
508         } 
509         else
510         {
511             [o_mi setState: NSOffState];
512         }
513     } 
514
515     return( bEnabled );
516 }
517
518 @end