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"
29 #import <vlc_playlist.h>
33 #import <vlc_aout_intf.h>
35 #import <vlc_strings.h>
38 @implementation VLCCoreInteraction
39 static VLCCoreInteraction *_o_sharedInstance = nil;
41 + (VLCCoreInteraction *)sharedInstance
43 return _o_sharedInstance ? _o_sharedInstance : [[self alloc] init];
47 #pragma mark Initialization
51 if (_o_sharedInstance) {
53 return _o_sharedInstance;
55 _o_sharedInstance = [super init];
57 return _o_sharedInstance;
62 [[NSNotificationCenter defaultCenter] removeObserver: self];
68 [[NSNotificationCenter defaultCenter] addObserver: self
69 selector: @selector(applicationWillFinishLaunching:)
70 name: NSApplicationWillFinishLaunchingNotification
75 #pragma mark Playback Controls
79 input_thread_t * p_input;
80 p_input = pl_CurrentInput(VLCIntf);
82 var_SetInteger(VLCIntf->p_libvlc, "key-action", ACTIONID_PLAY_PAUSE);
83 vlc_object_release(p_input);
85 playlist_t * p_playlist = pl_Get(VLCIntf);
89 empty = playlist_IsEmpty(p_playlist);
92 if ([[[VLCMain sharedInstance] playlist] isSelectionEmpty] && ([[[VLCMain sharedInstance] playlist] currentPlaylistRoot] == p_playlist->p_local_category || [[[VLCMain sharedInstance] playlist] currentPlaylistRoot] == p_playlist->p_ml_category))
93 [[[VLCMain sharedInstance] open] openFileGeneric];
95 [[[VLCMain sharedInstance] playlist] playItem:nil];
101 var_SetInteger(VLCIntf->p_libvlc, "key-action", ACTIONID_PAUSE);
106 var_SetInteger(VLCIntf->p_libvlc, "key-action", ACTIONID_STOP);
111 var_SetInteger(VLCIntf->p_libvlc, "key-action", ACTIONID_FASTER);
116 var_SetInteger(VLCIntf->p_libvlc, "key-action", ACTIONID_SLOWER);
121 var_SetInteger(VLCIntf->p_libvlc, "key-action", ACTIONID_RATE_NORMAL);
126 intf_thread_t *p_intf = VLCIntf;
130 input_thread_t * p_input;
131 p_input = pl_CurrentInput(p_intf);
133 var_ToggleBool(p_input, "record");
134 vlc_object_release(p_input);
138 - (void)setPlaybackRate:(int)i_value
140 playlist_t * p_playlist = pl_Get(VLCIntf);
142 double speed = pow(2, (double)i_value / 17);
143 int rate = INPUT_RATE_DEFAULT / speed;
144 if (i_currentPlaybackRate != rate)
145 var_SetFloat(p_playlist, "rate", (float)INPUT_RATE_DEFAULT / (float)rate);
146 i_currentPlaybackRate = rate;
153 intf_thread_t *p_intf = VLCIntf;
157 input_thread_t * p_input;
158 p_input = pl_CurrentInput(p_intf);
160 f_rate = var_GetFloat(p_input, "rate");
161 vlc_object_release(p_input);
165 playlist_t * p_playlist = pl_Get(VLCIntf);
166 f_rate = var_GetFloat(p_playlist, "rate");
169 double value = 17 * log(f_rate) / log(2.);
170 int returnValue = (int) ((value > 0) ? value + .5 : value - .5);
172 if (returnValue < -34)
174 else if (returnValue > 34)
177 i_currentPlaybackRate = returnValue;
183 var_SetInteger(VLCIntf->p_libvlc, "key-action", ACTIONID_PREV);
188 var_SetInteger(VLCIntf->p_libvlc, "key-action", ACTIONID_NEXT);
191 - (int)durationOfCurrentPlaylistItem
193 intf_thread_t *p_intf = VLCIntf;
197 input_thread_t * p_input = pl_CurrentInput(p_intf);
198 int64_t i_duration = -1;
202 input_Control(p_input, INPUT_GET_LENGTH, &i_duration);
203 vlc_object_release(p_input);
205 return (int)(i_duration / 1000000);
208 - (NSURL*)URLOfCurrentPlaylistItem
210 intf_thread_t *p_intf = VLCIntf;
214 input_thread_t *p_input = pl_CurrentInput(p_intf);
218 input_item_t *p_item = input_GetItem(p_input);
220 vlc_object_release(p_input);
224 char *psz_uri = input_item_GetURI(p_item);
226 vlc_object_release(p_input);
231 o_url = [NSURL URLWithString:[NSString stringWithUTF8String:psz_uri]];
232 vlc_object_release(p_input);
237 - (NSString*)nameOfCurrentPlaylistItem
239 intf_thread_t *p_intf = VLCIntf;
243 input_thread_t *p_input = pl_CurrentInput(p_intf);
247 input_item_t *p_item = input_GetItem(p_input);
249 vlc_object_release(p_input);
253 char *psz_uri = input_item_GetURI(p_item);
255 vlc_object_release(p_input);
260 char *format = var_InheritString(VLCIntf, "input-title-format");
261 char *formated = str_format_meta(pl_Get(VLCIntf), format);
263 o_name = [NSString stringWithUTF8String:formated];
266 NSURL * o_url = [NSURL URLWithString: [NSString stringWithUTF8String: psz_uri]];
269 if ([o_name isEqualToString:@""]) {
270 if ([o_url isFileURL])
271 o_name = [[NSFileManager defaultManager] displayNameAtPath: [o_url path]];
273 o_name = [o_url absoluteString];
275 vlc_object_release(p_input);
288 [self backwardShort];
291 - (void)forwardExtraShort
293 var_SetInteger(VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_FORWARD_EXTRASHORT);
296 - (void)backwardExtraShort
298 var_SetInteger(VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_BACKWARD_EXTRASHORT);
303 var_SetInteger(VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_FORWARD_SHORT);
306 - (void)backwardShort
308 var_SetInteger(VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_BACKWARD_SHORT);
311 - (void)forwardMedium
313 var_SetInteger(VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_FORWARD_MEDIUM);
316 - (void)backwardMedium
318 var_SetInteger(VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_BACKWARD_MEDIUM);
323 var_SetInteger(VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_FORWARD_LONG);
328 var_SetInteger(VLCIntf->p_libvlc, "key-action", ACTIONID_JUMP_BACKWARD_LONG);
333 intf_thread_t *p_intf = VLCIntf;
338 playlist_t * p_playlist = pl_Get(p_intf);
339 vout_thread_t *p_vout = getVout();
341 var_Get(p_playlist, "random", &val);
342 val.b_bool = !val.b_bool;
343 var_Set(p_playlist, "random", val);
346 vout_OSDMessage(p_vout, SPU_DEFAULT_CHANNEL, "%s", _("Random On"));
347 vlc_object_release(p_vout);
349 config_PutInt(p_playlist, "random", 1);
354 vout_OSDMessage(p_vout, SPU_DEFAULT_CHANNEL, "%s", _("Random Off"));
355 vlc_object_release(p_vout);
357 config_PutInt(p_playlist, "random", 0);
363 intf_thread_t *p_intf = VLCIntf;
367 playlist_t * p_playlist = pl_Get(p_intf);
369 var_SetBool(p_playlist, "repeat", NO);
370 var_SetBool(p_playlist, "loop", YES);
371 config_PutInt(p_playlist, "repeat", NO);
372 config_PutInt(p_playlist, "loop", YES);
374 vout_thread_t *p_vout = getVout();
376 vout_OSDMessage(p_vout, SPU_DEFAULT_CHANNEL, "%s", _("Repeat All"));
377 vlc_object_release(p_vout);
383 intf_thread_t *p_intf = VLCIntf;
387 playlist_t * p_playlist = pl_Get(p_intf);
389 var_SetBool(p_playlist, "repeat", YES);
390 var_SetBool(p_playlist, "loop", NO);
391 config_PutInt(p_playlist, "repeat", YES);
392 config_PutInt(p_playlist, "loop", NO);
394 vout_thread_t *p_vout = getVout();
396 vout_OSDMessage(p_vout, SPU_DEFAULT_CHANNEL, "%s", _("Repeat One"));
397 vlc_object_release(p_vout);
403 intf_thread_t *p_intf = VLCIntf;
407 playlist_t * p_playlist = pl_Get(p_intf);
409 var_SetBool(p_playlist, "repeat", NO);
410 var_SetBool(p_playlist, "loop", NO);
411 config_PutInt(p_playlist, "repeat", NO);
412 config_PutInt(p_playlist, "loop", NO);
414 vout_thread_t *p_vout = getVout();
416 vout_OSDMessage(p_vout, SPU_DEFAULT_CHANNEL, "%s", _("Repeat Off"));
417 vlc_object_release(p_vout);
423 intf_thread_t *p_intf = VLCIntf;
427 aout_VolumeUp(pl_Get(p_intf), 1, NULL);
432 intf_thread_t *p_intf = VLCIntf;
436 aout_VolumeDown(pl_Get(p_intf), 1, NULL);
441 intf_thread_t *p_intf = VLCIntf;
445 aout_MuteToggle(pl_Get(p_intf));
448 - (void)setMute:(BOOL)b_value
450 intf_thread_t *p_intf = VLCIntf;
454 aout_MuteSet(pl_Get(p_intf), b_value);
459 intf_thread_t *p_intf = VLCIntf;
463 BOOL b_is_muted = NO;
464 b_is_muted = aout_MuteGet(pl_Get(p_intf)) > 0;
471 intf_thread_t *p_intf = VLCIntf;
475 float volume = aout_VolumeGet(pl_Get(p_intf));
477 return lroundf(volume * AOUT_VOLUME_DEFAULT);
480 - (void)setVolume: (int)i_value
482 intf_thread_t *p_intf = VLCIntf;
486 aout_VolumeSet(pl_Get(p_intf), i_value / (float)AOUT_VOLUME_DEFAULT);
490 #pragma mark drag and drop support for VLCVoutView, VLBrushedMetalImageView and VLCThreePartDropView
491 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
493 NSPasteboard *o_paste = [sender draggingPasteboard];
494 NSArray *o_types = [NSArray arrayWithObject: NSFilenamesPboardType];
495 NSString *o_desired_type = [o_paste availableTypeFromArray:o_types];
496 NSData *o_carried_data = [o_paste dataForType:o_desired_type];
497 BOOL b_autoplay = config_GetInt(VLCIntf, "macosx-autoplay");
499 if (o_carried_data) {
500 if ([o_desired_type isEqualToString:NSFilenamesPboardType]) {
501 NSArray *o_array = [NSArray array];
502 NSArray *o_values = [[o_paste propertyListForType: NSFilenamesPboardType] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
503 NSUInteger count = [o_values count];
505 input_thread_t * p_input = pl_CurrentInput(VLCIntf);
506 BOOL b_returned = NO;
508 if (count == 1 && p_input) {
509 b_returned = input_AddSubtitle(p_input, vlc_path2uri([[o_values objectAtIndex:0] UTF8String], NULL), true);
510 vlc_object_release(p_input);
515 vlc_object_release(p_input);
517 for (NSUInteger i = 0; i < count; i++) {
519 char *psz_uri = vlc_path2uri([[o_values objectAtIndex:i] UTF8String], NULL);
523 o_dic = [NSDictionary dictionaryWithObject:[NSString stringWithCString:psz_uri encoding:NSUTF8StringEncoding] forKey:@"ITEM_URL"];
526 o_array = [o_array arrayByAddingObject: o_dic];
529 [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:NO];
531 [[[VLCMain sharedInstance] playlist] appendArray: o_array atPos: -1 enqueue:YES];
540 #pragma mark video output stuff
542 - (void)setAspectRatioIsLocked:(BOOL)b_value
544 config_PutInt(VLCIntf, "macosx-lock-aspect-ratio", b_value);
547 - (BOOL)aspectRatioIsLocked
549 return config_GetInt(VLCIntf, "macosx-lock-aspect-ratio");
552 - (void)toggleFullscreen
554 intf_thread_t *p_intf = VLCIntf;
558 BOOL b_fs = var_ToggleBool(pl_Get(p_intf), "fullscreen");
560 vout_thread_t *p_vout = getVout();
562 var_SetBool(p_vout, "fullscreen", b_fs);
563 vlc_object_release(p_vout);
568 #pragma mark uncommon stuff
570 - (BOOL)fixPreferences
572 NSMutableString * o_workString;
573 NSRange returnedRange;
575 BOOL b_needsRestart = NO;
577 #define fixpref(pref) \
578 o_workString = [[NSMutableString alloc] initWithFormat:@"%s", config_GetPsz(VLCIntf, pref)]; \
579 if ([o_workString length] > 0) \
581 returnedRange = [o_workString rangeOfString:@"macosx" options: NSCaseInsensitiveSearch]; \
582 if (returnedRange.location != NSNotFound) \
584 if ([o_workString isEqualToString:@"macosx"]) \
585 [o_workString setString:@""]; \
586 fullRange = NSMakeRange(0, [o_workString length]); \
587 [o_workString replaceOccurrencesOfString:@":macosx" withString:@"" options: NSCaseInsensitiveSearch range: fullRange]; \
588 fullRange = NSMakeRange(0, [o_workString length]); \
589 [o_workString replaceOccurrencesOfString:@"macosx:" withString:@"" options: NSCaseInsensitiveSearch range: fullRange]; \
591 config_PutPsz(VLCIntf, pref, [o_workString UTF8String]); \
592 b_needsRestart = YES; \
595 [o_workString release]
598 fixpref("extraintf");
601 return b_needsRestart;