]> git.sesse.net Git - vlc/blob - modules/gui/macosx/CoreInteraction.m
macosx: implement visual feedback for volume changes (close #5837)
[vlc] / modules / gui / macosx / CoreInteraction.m
1 /*****************************************************************************
2  * CoreInteraction.m: MacOS X interface module
3  *****************************************************************************
4  * Copyright (C) 2011-2012 Felix Paul Kühne
5  * $Id$
6  *
7  * Authors: Felix Paul Kühne <fkuehne -at- videolan -dot- org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #import "CoreInteraction.h"
25 #import "intf.h"
26 #import "open.h"
27 #import <vlc_playlist.h>
28 #import <vlc_input.h>
29 #import <vlc_keys.h>
30 #import <vlc_osd.h>
31 #import <vlc_aout_intf.h>
32 #import <vlc/vlc.h>
33 #import <vlc_strings.h>
34
35 @implementation VLCCoreInteraction
36 static VLCCoreInteraction *_o_sharedInstance = nil;
37
38 + (VLCCoreInteraction *)sharedInstance
39 {
40     return _o_sharedInstance ? _o_sharedInstance : [[self alloc] init];
41 }
42
43 #pragma mark -
44 #pragma mark Initialization
45
46 - (id)init
47 {
48     if( _o_sharedInstance)
49     {
50         [self dealloc];
51         return _o_sharedInstance;
52     }
53     else
54     {
55         _o_sharedInstance = [super init];
56         b_lockAspectRatio = YES;
57     }
58     
59     return _o_sharedInstance;
60 }
61
62 - (void)dealloc
63 {
64     [[NSNotificationCenter defaultCenter] removeObserver: self];
65     [super dealloc];
66 }
67
68 - (void)awakeFromNib
69 {
70     [[NSNotificationCenter defaultCenter] addObserver: self 
71                                              selector: @selector(applicationWillFinishLaunching:)
72                                                  name: NSApplicationWillFinishLaunchingNotification
73                                                object: nil];
74 }
75
76 #pragma mark -
77 #pragma mark Playback Controls
78
79 - (void)play
80 {
81     playlist_t * p_playlist = pl_Get( VLCIntf );
82     bool empty;
83     
84     PL_LOCK;
85     empty = playlist_IsEmpty( p_playlist );
86     PL_UNLOCK;
87     
88     if( empty )
89         [[[VLCMain sharedInstance] open] openFileGeneric];
90     
91     var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_PLAY_PAUSE );
92 }
93
94 - (void)pause
95 {
96     var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_PAUSE );
97 }
98
99 - (void)stop
100 {
101     var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_STOP );
102 }
103
104 - (void)faster
105 {
106     var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_FASTER );
107 }
108
109 - (void)slower
110 {
111     var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_SLOWER );
112 }
113
114 - (void)normalSpeed
115 {
116     var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_RATE_NORMAL );
117 }
118
119 - (void)toggleRecord
120 {
121     intf_thread_t *p_intf = VLCIntf;
122     if (!p_intf)
123         return;
124
125     input_thread_t * p_input;
126     p_input = pl_CurrentInput( p_intf );
127     if( p_input )
128     {
129         var_ToggleBool( p_input, "record" );
130         vlc_object_release( p_input );
131     }
132 }
133
134 - (void)setPlaybackRate:(int)i_value
135 {
136     playlist_t * p_playlist = pl_Get( VLCIntf );
137
138     double speed = pow( 2, (double)i_value / 17 );
139     int rate = INPUT_RATE_DEFAULT / speed;
140     if( i_currentPlaybackRate != rate )
141         var_SetFloat( p_playlist, "rate", (float)INPUT_RATE_DEFAULT / (float)rate );
142     i_currentPlaybackRate = rate;
143 }
144
145 - (int)playbackRate
146 {
147     float f_rate;
148
149     intf_thread_t *p_intf = VLCIntf;
150     if (!p_intf)
151         return 0;
152
153     input_thread_t * p_input;
154     p_input = pl_CurrentInput( p_intf );
155     if (p_input)
156     {
157         f_rate = var_GetFloat( p_input, "rate" );
158         vlc_object_release( p_input );
159     }
160     else
161     {
162         playlist_t * p_playlist = pl_Get( VLCIntf );
163         f_rate = var_GetFloat( p_playlist, "rate" );
164     }
165
166     double value = 17 * log( f_rate ) / log( 2. );
167     int returnValue = (int) ( ( value > 0 ) ? value + .5 : value - .5 );
168
169     if( returnValue < -34 )
170         returnValue = -34;
171     else if( returnValue > 34 )
172         returnValue = 34;
173
174     i_currentPlaybackRate = returnValue;
175     return returnValue;
176 }
177
178 - (void)previous
179 {
180     var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_PREV );
181 }
182
183 - (void)next
184 {
185     var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_NEXT );
186 }
187
188 - (BOOL)isPlaying
189 {
190     intf_thread_t *p_intf = VLCIntf;
191     if (!p_intf)
192         return NO;
193
194     input_thread_t * p_input = pl_CurrentInput( p_intf );
195
196     if (!p_input) return NO;
197
198     input_state_e i_state = ERROR_S;
199     input_Control( p_input, INPUT_GET_STATE, &i_state);
200     vlc_object_release( p_input );
201
202     return ((i_state == OPENING_S) || (i_state == PLAYING_S));
203 }
204
205 - (int)currentTime
206 {
207     input_thread_t * p_input = pl_CurrentInput( VLCIntf );
208     int64_t i_currentTime = -1;
209
210     if (!p_input) return i_currentTime;
211
212     input_Control( p_input, INPUT_GET_TIME, &i_currentTime);
213     vlc_object_release( p_input );
214
215     return (int)( i_currentTime / 1000000 );
216 }
217
218 - (void)setCurrentTime:(int)i_value
219 {
220     int64_t i64_value = (int64_t)i_value;
221     input_thread_t * p_input = pl_CurrentInput( VLCIntf );
222
223     if (!p_input) return;
224
225     input_Control( p_input, INPUT_SET_TIME, (int64_t)(i64_value * 1000000));
226     vlc_object_release( p_input );
227 }
228
229 - (int)durationOfCurrentPlaylistItem
230 {
231     intf_thread_t *p_intf = VLCIntf;
232     if (!p_intf)
233         return 0;
234
235     input_thread_t * p_input = pl_CurrentInput( p_intf );
236     int64_t i_duration = -1;
237     if (!p_input) return i_duration;
238
239
240     input_Control( p_input, INPUT_GET_LENGTH, &i_duration);
241     vlc_object_release( p_input );
242
243     return (int)(i_duration / 1000000);
244 }
245
246 - (NSURL*)URLOfCurrentPlaylistItem
247 {
248     intf_thread_t *p_intf = VLCIntf;
249     if (!p_intf)
250         return nil;
251
252     input_thread_t *p_input = pl_CurrentInput( p_intf );
253     if (!p_input) return nil;
254
255     input_item_t *p_item = input_GetItem( p_input );
256     if (!p_item)
257     {
258         vlc_object_release( p_input );
259         return nil;
260     }
261
262     char *psz_uri = input_item_GetURI( p_item );
263     if (!psz_uri)
264     {
265         vlc_object_release( p_input );
266         return nil;
267     }
268
269     NSURL *o_url;
270     o_url = [NSURL URLWithString:[NSString stringWithUTF8String:psz_uri]];
271     vlc_object_release( p_input );
272
273     return o_url;
274 }
275
276 - (NSString*)nameOfCurrentPlaylistItem
277 {
278     intf_thread_t *p_intf = VLCIntf;
279     if (!p_intf)
280         return nil;
281
282     input_thread_t *p_input = pl_CurrentInput( p_intf );
283     if (!p_input) return nil;
284
285     input_item_t *p_item = input_GetItem( p_input );
286     if (!p_item)
287     {
288         vlc_object_release( p_input );
289         return nil;
290     }
291
292     char *psz_uri = input_item_GetURI( p_item );
293     if (!psz_uri)
294     {
295         vlc_object_release( p_input );
296         return nil;
297     }
298
299     NSString *o_name;
300     char *format = var_InheritString( VLCIntf, "input-title-format" );
301     char *formated = str_format_meta( p_input, format );
302     free( format );
303     o_name = [NSString stringWithUTF8String:formated];
304     free( formated );
305
306     NSURL * o_url = [NSURL URLWithString: [NSString stringWithUTF8String: psz_uri]];
307     free( psz_uri );
308
309     if ([o_name isEqualToString:@""])
310     {
311         if ([o_url isFileURL]) 
312             o_name = [[NSFileManager defaultManager] displayNameAtPath: [o_url path]];
313         else
314             o_name = [o_url absoluteString];
315     }
316     vlc_object_release( p_input );
317     return o_name;
318 }
319
320 - (void)forward
321 {
322     //LEGACY SUPPORT
323     [self forwardShort];
324 }
325
326 - (void)backward
327 {
328     //LEGACY SUPPORT
329     [self backwardShort];
330 }
331
332 - (void)forwardExtraShort
333 {
334     var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_FORWARD_EXTRASHORT );
335 }
336
337 - (void)backwardExtraShort
338 {
339     var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_BACKWARD_EXTRASHORT );
340 }
341
342 - (void)forwardShort
343 {
344     var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_FORWARD_SHORT );
345 }
346
347 - (void)backwardShort
348 {
349     var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_BACKWARD_SHORT );
350 }
351
352 - (void)forwardMedium
353 {
354     var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_FORWARD_MEDIUM );
355 }
356
357 - (void)backwardMedium
358 {
359     var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_BACKWARD_MEDIUM );
360 }
361
362 - (void)forwardLong
363 {
364     var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_FORWARD_LONG );
365 }
366
367 - (void)backwardLong
368 {
369     var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_BACKWARD_LONG );
370 }
371
372 - (void)shuffle
373 {
374     intf_thread_t *p_intf = VLCIntf;
375     if (!p_intf)
376         return;
377
378     vlc_value_t val;
379     playlist_t * p_playlist = pl_Get( p_intf );
380     vout_thread_t *p_vout = getVout();
381
382     var_Get( p_playlist, "random", &val );
383     val.b_bool = !val.b_bool;
384     var_Set( p_playlist, "random", val );
385     if( val.b_bool )
386     {
387         if (p_vout)
388         {
389             vout_OSDMessage( p_vout, SPU_DEFAULT_CHANNEL, "%s", _( "Random On" ) );
390             vlc_object_release( p_vout );
391         }
392         config_PutInt( p_playlist, "random", 1 );
393     }
394     else
395     {
396         if (p_vout)
397         {
398             vout_OSDMessage( p_vout, SPU_DEFAULT_CHANNEL, "%s", _( "Random Off" ) );
399             vlc_object_release( p_vout );
400         }
401         config_PutInt( p_playlist, "random", 0 );
402     }
403 }
404
405 - (void)repeatAll
406 {
407     intf_thread_t *p_intf = VLCIntf;
408     if (!p_intf)
409         return;
410
411     playlist_t * p_playlist = pl_Get( p_intf );
412
413     var_SetBool( p_playlist, "repeat", NO );
414     var_SetBool( p_playlist, "loop", YES );
415     config_PutInt( p_playlist, "repeat", NO );
416     config_PutInt( p_playlist, "loop", YES );
417
418     vout_thread_t *p_vout = getVout();
419     if (p_vout)
420     {
421         vout_OSDMessage( p_vout, SPU_DEFAULT_CHANNEL, "%s", _( "Repeat All" ) );
422         vlc_object_release( p_vout );
423     }
424 }
425
426 - (void)repeatOne
427 {
428     intf_thread_t *p_intf = VLCIntf;
429     if (!p_intf)
430         return;
431
432     playlist_t * p_playlist = pl_Get( p_intf );
433
434     var_SetBool( p_playlist, "repeat", YES );
435     var_SetBool( p_playlist, "loop", NO );
436     config_PutInt( p_playlist, "repeat", YES );
437     config_PutInt( p_playlist, "loop", NO );
438
439     vout_thread_t *p_vout = getVout();
440     if (p_vout)
441     {
442         vout_OSDMessage( p_vout, SPU_DEFAULT_CHANNEL, "%s", _( "Repeat One" ) );
443         vlc_object_release( p_vout );
444     }
445 }
446
447 - (void)repeatOff
448 {
449     intf_thread_t *p_intf = VLCIntf;
450     if (!p_intf)
451         return;
452
453     playlist_t * p_playlist = pl_Get( p_intf );
454
455     var_SetBool( p_playlist, "repeat", NO );
456     var_SetBool( p_playlist, "loop", NO );
457     config_PutInt( p_playlist, "repeat", NO );
458     config_PutInt( p_playlist, "loop", NO );
459
460     vout_thread_t *p_vout = getVout();
461     if (p_vout)
462     {
463         vout_OSDMessage( p_vout, SPU_DEFAULT_CHANNEL, "%s", _( "Repeat Off" ) );
464         vlc_object_release( p_vout );
465     }
466 }
467
468 - (void)displayVolume
469 {
470     vout_thread_t *p_vout = getVout();
471     if (p_vout)
472     {
473         vout_OSDSlider( p_vout, SPU_DEFAULT_CHANNEL,
474                        [self volume]*100/AOUT_VOLUME_MAX, OSD_VERT_SLIDER );
475         vout_OSDMessage( p_vout, SPU_DEFAULT_CHANNEL, _( "Volume %d%%" ),
476                        [self volume]*100/AOUT_VOLUME_DEFAULT );
477         vlc_object_release( p_vout );
478     }
479 }
480
481 - (void)volumeUp
482 {
483     intf_thread_t *p_intf = VLCIntf;
484     if (!p_intf)
485         return;
486
487     aout_VolumeUp( pl_Get( p_intf ), 1, NULL );
488     [self displayVolume];
489 }
490
491 - (void)volumeDown
492 {
493     intf_thread_t *p_intf = VLCIntf;
494     if (!p_intf)
495         return;
496
497     aout_VolumeDown( pl_Get( p_intf ), 1, NULL );
498     [self displayVolume];
499 }
500
501 - (void)mute
502 {
503     intf_thread_t *p_intf = VLCIntf;
504     if (!p_intf)
505         return;
506
507     aout_ToggleMute( pl_Get( p_intf ), NULL );
508
509     vout_thread_t *p_vout = getVout();
510     if( p_vout )
511     {
512         if( [self isMuted] )
513         {
514             vout_OSDIcon( p_vout, SPU_DEFAULT_CHANNEL, OSD_MUTE_ICON );
515         }
516         else
517             [self displayVolume];
518
519         vlc_object_release( p_vout );
520     }
521 }
522
523 - (BOOL)isMuted
524 {
525     intf_thread_t *p_intf = VLCIntf;
526     if (!p_intf)
527         return NO;
528
529     BOOL b_is_muted = NO;
530     b_is_muted = aout_IsMuted( VLC_OBJECT(pl_Get( p_intf )) );
531
532     return b_is_muted;
533 }
534
535 - (int)volume
536 {
537     intf_thread_t *p_intf = VLCIntf;
538     if (!p_intf)
539         return 0;
540
541     audio_volume_t i_volume = aout_VolumeGet( pl_Get( p_intf ) );
542
543     return (int)i_volume;
544 }
545
546 - (void)setVolume: (int)i_value
547 {
548     intf_thread_t *p_intf = VLCIntf;
549     if (!p_intf)
550         return;
551
552     aout_VolumeSet( pl_Get( p_intf ), i_value );
553 }
554
555 #pragma mark -
556 #pragma mark video output stuff
557
558 - (void)setAspectRatioLocked:(BOOL)b_value
559 {
560     b_lockAspectRatio = b_value;
561 }
562
563 - (BOOL)aspectRatioIsLocked
564 {
565     return b_lockAspectRatio;
566 }
567
568 - (void)toggleFullscreen
569 {
570     intf_thread_t *p_intf = VLCIntf;
571     if (!p_intf)
572         return;
573
574     var_ToggleBool( pl_Get( p_intf ), "fullscreen" );
575 }
576
577 @end