1 /*****************************************************************************
2 * CoreInteraction.m: MacOS X interface module
3 *****************************************************************************
4 * Copyright (C) 2011-2012 Felix Paul Kühne
7 * Authors: Felix Paul Kühne <fkuehne -at- videolan -dot- org>
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.
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.
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 *****************************************************************************/
24 #import "CoreInteraction.h"
28 #import <vlc_playlist.h>
32 #import <vlc_aout_intf.h>
34 #import <vlc_strings.h>
37 @implementation VLCCoreInteraction
38 static VLCCoreInteraction *_o_sharedInstance = nil;
40 + (VLCCoreInteraction *)sharedInstance
42 return _o_sharedInstance ? _o_sharedInstance : [[self alloc] init];
46 #pragma mark Initialization
50 if( _o_sharedInstance )
53 return _o_sharedInstance;
57 _o_sharedInstance = [super init];
60 return _o_sharedInstance;
65 [[NSNotificationCenter defaultCenter] removeObserver: self];
71 [[NSNotificationCenter defaultCenter] addObserver: self
72 selector: @selector(applicationWillFinishLaunching:)
73 name: NSApplicationWillFinishLaunchingNotification
78 #pragma mark Playback Controls
82 playlist_t * p_playlist = pl_Get( VLCIntf );
86 empty = playlist_IsEmpty( p_playlist );
90 [[[VLCMain sharedInstance] open] openFileGeneric];
92 var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_PLAY_PAUSE );
97 var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_PAUSE );
102 var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_STOP );
107 var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_FASTER );
112 var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_SLOWER );
117 var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_RATE_NORMAL );
122 intf_thread_t *p_intf = VLCIntf;
126 input_thread_t * p_input;
127 p_input = pl_CurrentInput( p_intf );
130 var_ToggleBool( p_input, "record" );
131 vlc_object_release( p_input );
135 - (void)setPlaybackRate:(int)i_value
137 playlist_t * p_playlist = pl_Get( VLCIntf );
139 double speed = pow( 2, (double)i_value / 17 );
140 int rate = INPUT_RATE_DEFAULT / speed;
141 if( i_currentPlaybackRate != rate )
142 var_SetFloat( p_playlist, "rate", (float)INPUT_RATE_DEFAULT / (float)rate );
143 i_currentPlaybackRate = rate;
150 intf_thread_t *p_intf = VLCIntf;
154 input_thread_t * p_input;
155 p_input = pl_CurrentInput( p_intf );
158 f_rate = var_GetFloat( p_input, "rate" );
159 vlc_object_release( p_input );
163 playlist_t * p_playlist = pl_Get( VLCIntf );
164 f_rate = var_GetFloat( p_playlist, "rate" );
167 double value = 17 * log( f_rate ) / log( 2. );
168 int returnValue = (int) ( ( value > 0 ) ? value + .5 : value - .5 );
170 if( returnValue < -34 )
172 else if( returnValue > 34 )
175 i_currentPlaybackRate = returnValue;
181 var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_PREV );
186 var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_NEXT );
191 intf_thread_t *p_intf = VLCIntf;
195 input_thread_t * p_input = pl_CurrentInput( p_intf );
199 input_state_e i_state = ERROR_S;
200 input_Control( p_input, INPUT_GET_STATE, &i_state );
201 vlc_object_release( p_input );
203 return ( ( i_state == OPENING_S ) || ( i_state == PLAYING_S ) );
208 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
209 int64_t i_currentTime = -1;
212 return i_currentTime;
214 input_Control( p_input, INPUT_GET_TIME, &i_currentTime );
215 vlc_object_release( p_input );
217 return (int)( i_currentTime / 1000000 );
220 - (void)setCurrentTime:(int)i_value
222 int64_t i64_value = (int64_t)i_value;
223 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
228 input_Control( p_input, INPUT_SET_TIME, (int64_t)(i64_value * 1000000) );
229 vlc_object_release( p_input );
232 - (int)durationOfCurrentPlaylistItem
234 intf_thread_t *p_intf = VLCIntf;
238 input_thread_t * p_input = pl_CurrentInput( p_intf );
239 int64_t i_duration = -1;
243 input_Control( p_input, INPUT_GET_LENGTH, &i_duration );
244 vlc_object_release( p_input );
246 return (int)( i_duration / 1000000 );
249 - (NSURL*)URLOfCurrentPlaylistItem
251 intf_thread_t *p_intf = VLCIntf;
255 input_thread_t *p_input = pl_CurrentInput( p_intf );
259 input_item_t *p_item = input_GetItem( p_input );
262 vlc_object_release( p_input );
266 char *psz_uri = input_item_GetURI( p_item );
269 vlc_object_release( p_input );
274 o_url = [NSURL URLWithString:[NSString stringWithUTF8String:psz_uri]];
275 vlc_object_release( p_input );
280 - (NSString*)nameOfCurrentPlaylistItem
282 intf_thread_t *p_intf = VLCIntf;
286 input_thread_t *p_input = pl_CurrentInput( p_intf );
290 input_item_t *p_item = input_GetItem( p_input );
293 vlc_object_release( p_input );
297 char *psz_uri = input_item_GetURI( p_item );
300 vlc_object_release( p_input );
305 char *format = var_InheritString( VLCIntf, "input-title-format" );
306 char *formated = str_format_meta( p_input, format );
308 o_name = [NSString stringWithUTF8String:formated];
311 NSURL * o_url = [NSURL URLWithString: [NSString stringWithUTF8String: psz_uri]];
314 if( [o_name isEqualToString:@""] )
316 if( [o_url isFileURL] )
317 o_name = [[NSFileManager defaultManager] displayNameAtPath: [o_url path]];
319 o_name = [o_url absoluteString];
321 vlc_object_release( p_input );
334 [self backwardShort];
337 - (void)forwardExtraShort
339 var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_FORWARD_EXTRASHORT );
342 - (void)backwardExtraShort
344 var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_BACKWARD_EXTRASHORT );
349 var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_FORWARD_SHORT );
352 - (void)backwardShort
354 var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_BACKWARD_SHORT );
357 - (void)forwardMedium
359 var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_FORWARD_MEDIUM );
362 - (void)backwardMedium
364 var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_BACKWARD_MEDIUM );
369 var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_FORWARD_LONG );
374 var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_BACKWARD_LONG );
379 intf_thread_t *p_intf = VLCIntf;
384 playlist_t * p_playlist = pl_Get( p_intf );
385 vout_thread_t *p_vout = getVout();
387 var_Get( p_playlist, "random", &val );
388 val.b_bool = !val.b_bool;
389 var_Set( p_playlist, "random", val );
394 vout_OSDMessage( p_vout, SPU_DEFAULT_CHANNEL, "%s", _( "Random On" ) );
395 vlc_object_release( p_vout );
397 config_PutInt( p_playlist, "random", 1 );
403 vout_OSDMessage( p_vout, SPU_DEFAULT_CHANNEL, "%s", _( "Random Off" ) );
404 vlc_object_release( p_vout );
406 config_PutInt( p_playlist, "random", 0 );
412 intf_thread_t *p_intf = VLCIntf;
416 playlist_t * p_playlist = pl_Get( p_intf );
418 var_SetBool( p_playlist, "repeat", NO );
419 var_SetBool( p_playlist, "loop", YES );
420 config_PutInt( p_playlist, "repeat", NO );
421 config_PutInt( p_playlist, "loop", YES );
423 vout_thread_t *p_vout = getVout();
426 vout_OSDMessage( p_vout, SPU_DEFAULT_CHANNEL, "%s", _( "Repeat All" ) );
427 vlc_object_release( p_vout );
433 intf_thread_t *p_intf = VLCIntf;
437 playlist_t * p_playlist = pl_Get( p_intf );
439 var_SetBool( p_playlist, "repeat", YES );
440 var_SetBool( p_playlist, "loop", NO );
441 config_PutInt( p_playlist, "repeat", YES );
442 config_PutInt( p_playlist, "loop", NO );
444 vout_thread_t *p_vout = getVout();
447 vout_OSDMessage( p_vout, SPU_DEFAULT_CHANNEL, "%s", _( "Repeat One" ) );
448 vlc_object_release( p_vout );
454 intf_thread_t *p_intf = VLCIntf;
458 playlist_t * p_playlist = pl_Get( p_intf );
460 var_SetBool( p_playlist, "repeat", NO );
461 var_SetBool( p_playlist, "loop", NO );
462 config_PutInt( p_playlist, "repeat", NO );
463 config_PutInt( p_playlist, "loop", NO );
465 vout_thread_t *p_vout = getVout();
468 vout_OSDMessage( p_vout, SPU_DEFAULT_CHANNEL, "%s", _( "Repeat Off" ) );
469 vlc_object_release( p_vout );
475 intf_thread_t *p_intf = VLCIntf;
479 aout_VolumeUp( pl_Get( p_intf ), 1, NULL );
484 intf_thread_t *p_intf = VLCIntf;
488 aout_VolumeDown( pl_Get( p_intf ), 1, NULL );
493 intf_thread_t *p_intf = VLCIntf;
497 aout_ToggleMute( pl_Get( p_intf ), NULL );
502 intf_thread_t *p_intf = VLCIntf;
506 BOOL b_is_muted = NO;
507 b_is_muted = aout_IsMuted( VLC_OBJECT(pl_Get( p_intf )) );
514 intf_thread_t *p_intf = VLCIntf;
518 audio_volume_t i_volume = aout_VolumeGet( pl_Get( p_intf ) );
520 return (int)i_volume;
523 - (void)setVolume: (int)i_value
525 intf_thread_t *p_intf = VLCIntf;
529 aout_VolumeSet( pl_Get( p_intf ), i_value );
533 #pragma mark drag and drop support for VLCVoutView, VLBrushedMetalImageView and VLCThreePartDropView
534 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
536 NSPasteboard *o_paste = [sender draggingPasteboard];
537 NSArray *o_types = [NSArray arrayWithObject: NSFilenamesPboardType];
538 NSString *o_desired_type = [o_paste availableTypeFromArray:o_types];
539 NSData *o_carried_data = [o_paste dataForType:o_desired_type];
540 BOOL b_autoplay = config_GetInt( VLCIntf, "macosx-autoplay" );
544 if( [o_desired_type isEqualToString:NSFilenamesPboardType] )
546 NSArray *o_array = [NSArray array];
547 NSArray *o_values = [[o_paste propertyListForType: NSFilenamesPboardType] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
548 NSUInteger count = [o_values count];
550 input_thread_t * p_input = pl_CurrentInput( VLCIntf );
551 BOOL b_returned = NO;
553 if( count == 1 && p_input )
555 b_returned = input_AddSubtitle( p_input, make_URI([[o_values objectAtIndex:0] UTF8String], NULL), true );
556 vlc_object_release( p_input );
561 vlc_object_release( p_input );
563 for( NSUInteger i = 0; i < count; i++)
566 char *psz_uri = make_URI([[o_values objectAtIndex:i] UTF8String], NULL);
570 o_dic = [NSDictionary dictionaryWithObject:[NSString stringWithCString:psz_uri encoding:NSUTF8StringEncoding] forKey:@"ITEM_URL"];
573 o_array = [o_array arrayByAddingObject: o_dic];
576 [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:NO];
578 [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:YES];
587 #pragma mark video output stuff
589 - (void)setAspectRatioLocked:(BOOL)b_value
591 config_PutInt( VLCIntf, "macosx-lock-aspect-ratio", b_value );
594 - (BOOL)aspectRatioIsLocked
596 return config_GetInt( VLCIntf, "macosx-lock-aspect-ratio" );
599 - (void)toggleFullscreen
601 intf_thread_t *p_intf = VLCIntf;
605 BOOL b_fs = var_ToggleBool( pl_Get( p_intf ), "fullscreen" );
607 vout_thread_t *p_vout = getVout();
610 var_SetBool( p_vout, "fullscreen", b_fs );
611 vlc_object_release( p_vout );
616 #pragma mark uncommon stuff
618 - (BOOL)fixPreferences
620 NSMutableString * o_workString;
621 NSRange returnedRange;
623 BOOL b_needsRestart = NO;
625 #define fixpref( pref ) \
626 o_workString = [[NSMutableString alloc] initWithFormat:@"%s", config_GetPsz( VLCIntf, pref )]; \
627 if ([o_workString length] > 0) \
629 returnedRange = [o_workString rangeOfString:@"macosx" options: NSCaseInsensitiveSearch]; \
630 if (returnedRange.location != NSNotFound) \
632 if ([o_workString isEqualToString:@"macosx"]) \
633 [o_workString setString:@""]; \
634 fullRange = NSMakeRange( 0, [o_workString length] ); \
635 [o_workString replaceOccurrencesOfString:@":macosx" withString:@"" options: NSCaseInsensitiveSearch range: fullRange]; \
636 fullRange = NSMakeRange( 0, [o_workString length] ); \
637 [o_workString replaceOccurrencesOfString:@"macosx:" withString:@"" options: NSCaseInsensitiveSearch range: fullRange]; \
639 config_PutPsz( VLCIntf, pref, [o_workString UTF8String] ); \
640 b_needsRestart = YES; \
643 [o_workString release]
645 fixpref( "control" );
646 fixpref( "extraintf" );
649 return b_needsRestart;