#include <vlc_dialog.h>
#include <vlc_url.h>
#include <vlc_modules.h>
+#include <vlc_plugin.h>
#include <vlc_aout_intf.h>
#include <vlc_vout_window.h>
#include <unistd.h> /* execl() */
{
NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
[VLCApplication sharedApplication];
+
intf_thread_t *p_intf = (intf_thread_t*) p_this;
p_intf->p_sys = malloc( sizeof( intf_sys_t ) );
memset( p_intf->p_sys, 0, sizeof( *p_intf->p_sys ) );
/* subscribe to LibVLCCore's messages */
- p_intf->p_sys->p_sub = vlc_Subscribe( MsgCallback, NULL );
- p_intf->pf_run = Run;
- p_intf->b_should_run_on_first_thread = true;
+ vlc_Subscribe( &p_intf->p_sys->sub, MsgCallback, NULL );
+
+ Run( p_intf );
[o_pool release];
return VLC_SUCCESS;
else if( i_query == VOUT_WINDOW_SET_FULLSCREEN )
{
NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
- [[VLCMain sharedInstance] fullscreenChanged];
+ // we already have our playlist "fullscreen" callback, do not repeat the same call here
+ //[[VLCMain sharedInstance] performSelectorOnMainThread:@selector(fullscreenChanged) withObject: nil waitUntilDone: NO];
[o_pool release];
}
else
[[VLCMain sharedInstance] applicationWillTerminate:nil];
[o_appLock release];
[o_pool release];
+
+ raise(SIGTERM);
}
#pragma mark -
case INPUT_EVENT_ITEM_META:
case INPUT_EVENT_ITEM_INFO:
[[VLCMain sharedInstance] performSelectorOnMainThread:@selector(updateMainMenu) withObject: nil waitUntilDone:NO];
- [[VLCMain sharedInstance] updateName];
+ [[VLCMain sharedInstance] performSelectorOnMainThread:@selector(updateName) withObject: nil waitUntilDone:NO];
[[VLCMain sharedInstance] performSelectorOnMainThread:@selector(updateInfoandMetaPanel) withObject: nil waitUntilDone:NO];
break;
case INPUT_EVENT_BOOKMARK:
_o_sharedMainInstance = [super init];
p_intf = NULL;
+ p_current_input = NULL;
o_msg_lock = [[NSLock alloc] init];
o_msg_arr = [[NSMutableArray arrayWithCapacity: 600] retain];
if (OSX_LION)
{
- if ([NSApp currentSystemPresentationOptions] == NSApplicationPresentationFullScreen)
+ if ([NSApp currentSystemPresentationOptions] & NSApplicationPresentationFullScreen)
var_SetBool( p_playlist, "fullscreen", YES );
}
/* yeah, we are done */
b_nativeFullscreenMode = NO;
#ifdef MAC_OS_X_VERSION_10_7
- if( config_GetInt( VLCIntf, "embedded-video" ))
+ if( OSX_LION )
b_nativeFullscreenMode = config_GetInt( p_intf, "macosx-nativefullscreenmode" );
#endif
+
+ /* recover stored audio device, if set
+ * in case it was unplugged in the meantime, auhal will fall back on the default */
+ int i_value = config_GetInt( p_intf, "macosx-audio-device" );
+ if (i_value > 0)
+ var_SetInteger( pl_Get( VLCIntf ), "audio-device", i_value );
+
+ if (config_GetInt( VLCIntf, "macosx-icon-change"))
+ {
+ /* After day 354 of the year, the usual VLC cone is replaced by another cone
+ * wearing a Father Xmas hat.
+ * Note: this icon doesn't represent an endorsement of The Coca-Cola Company.
+ */
+ NSCalendar *gregorian =
+ [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
+ NSUInteger dayOfYear = [gregorian ordinalityOfUnit:NSDayCalendarUnit inUnit:NSYearCalendarUnit forDate:[NSDate date]];
+ [gregorian release];
+
+ if (dayOfYear >= 354)
+ [[VLCApplication sharedApplication] setApplicationIconImage: [NSImage imageNamed:@"vlc-xmas"]];
+ }
+
nib_main_loaded = TRUE;
}
{
if( !p_intf ) return;
+ [self updateCurrentlyUsedHotkeys];
+
[o_mainwindow updateWindow];
[o_mainwindow updateTimeSlider];
[o_mainwindow updateVolumeSlider];
- (void)applicationWillTerminate:(NSNotification *)notification
{
- if( !p_intf )
- return;
-
/* don't allow a double termination call. If the user has
* already invoked the quit then simply return this time. */
static bool f_appExit = false;
playlist_t * p_playlist = pl_Get( p_intf );
int returnedValue = 0;
+ /* always exit fullscreen on quit, otherwise we get ugly artifacts on the next launch */
+ if (b_nativeFullscreenMode)
+ {
+ [o_mainwindow toggleFullScreen: self];
+ [NSApp setPresentationOptions:(NSApplicationPresentationDefault)];
+ }
+
/* Save some interface state in configuration, at module quit */
config_PutInt( p_intf, "random", var_GetBool( p_playlist, "random" ) );
config_PutInt( p_intf, "loop", var_GetBool( p_playlist, "loop" ) );
var_DelCallback(p_intf->p_libvlc, "intf-toggle-fscontrol", ShowController, self);
var_DelCallback(p_intf->p_libvlc, "intf-show", ShowController, self);
- input_thread_t * p_input = playlist_CurrentInput( p_playlist );
- if( p_input )
+ if( p_current_input )
{
- var_DelCallback( p_input, "intf-event", InputEvent, [VLCMain sharedInstance] );
- vlc_object_release( p_input );
+ var_DelCallback( p_current_input, "intf-event", InputEvent, [VLCMain sharedInstance] );
+ vlc_object_release( p_current_input );
+ p_current_input = NULL;
}
/* remove global observer watching for vout device changes correctly */
[o_embedded_list release];
[o_coredialogs release];
[o_eyetv release];
- [o_mainwindow release];
/* unsubscribe from libvlc's debug messages */
- vlc_Unsubscribe( p_intf->p_sys->p_sub );
+ vlc_Unsubscribe( &p_intf->p_sys->sub );
[o_msg_arr removeAllObjects];
[o_msg_arr release];
+ o_msg_arr = NULL;
[o_msg_lock release];
libvlc_Quit( p_intf->p_libvlc );
+ [o_mainwindow release];
+ o_mainwindow = NULL;
+
[self setIntf:nil];
}
int keyRepeat = (keyFlags & 0x1);
if( keyCode == NX_KEYTYPE_PLAY && keyState == 0 )
- var_SetInteger( p_intf->p_libvlc, "key-action", ACTIONID_PLAY_PAUSE );
+ [[VLCCoreInteraction sharedInstance] play];
- if( keyCode == NX_KEYTYPE_FAST && !b_mediakeyJustJumped )
+ if( (keyCode == NX_KEYTYPE_FAST || keyCode == NX_KEYTYPE_NEXT) && !b_mediakeyJustJumped )
{
if( keyState == 0 && keyRepeat == 0 )
- var_SetInteger( p_intf->p_libvlc, "key-action", ACTIONID_NEXT );
+ [[VLCCoreInteraction sharedInstance] next];
else if( keyRepeat == 1 )
{
- var_SetInteger( p_intf->p_libvlc, "key-action", ACTIONID_JUMP_FORWARD_SHORT );
+ [[VLCCoreInteraction sharedInstance] forwardShort];
b_mediakeyJustJumped = YES;
[self performSelector:@selector(resetMediaKeyJump)
withObject: NULL
}
}
- if( keyCode == NX_KEYTYPE_REWIND && !b_mediakeyJustJumped )
+ if( (keyCode == NX_KEYTYPE_REWIND || keyCode == NX_KEYTYPE_PREVIOUS) && !b_mediakeyJustJumped )
{
if( keyState == 0 && keyRepeat == 0 )
- var_SetInteger( p_intf->p_libvlc, "key-action", ACTIONID_PREV );
+ [[VLCCoreInteraction sharedInstance] previous];
else if( keyRepeat == 1 )
{
- var_SetInteger( p_intf->p_libvlc, "key-action", ACTIONID_JUMP_BACKWARD_SHORT );
+ [[VLCCoreInteraction sharedInstance] backwardShort];
b_mediakeyJustJumped = YES;
[self performSelector:@selector(resetMediaKeyJump)
withObject: NULL
if( !psz_uri )
return( FALSE );
+ input_thread_t * p_input = pl_CurrentInput( VLCIntf );
+ BOOL b_returned = NO;
+
+ if (p_input)
+ {
+ b_returned = input_AddSubtitle( p_input, psz_uri, true );
+ vlc_object_release( p_input );
+ if(!b_returned)
+ {
+ free( psz_uri );
+ return YES;
+ }
+ }
+ else if( p_input )
+ vlc_object_release( p_input );
+
NSDictionary *o_dic = [NSDictionary dictionaryWithObject:[NSString stringWithCString:psz_uri encoding:NSUTF8StringEncoding] forKey:@"ITEM_URL"];
free( psz_uri );
unsigned int i_pressed_modifiers = 0;
const struct hotkey *p_hotkeys;
int i;
- NSMutableString *tempString = [[[NSMutableString alloc] init] autorelease];
- NSMutableString *tempStringPlus = [[[NSMutableString alloc] init] autorelease];
+ NSMutableString *tempString = [[NSMutableString alloc] init];
+ NSMutableString *tempStringPlus = [[NSMutableString alloc] init];
val.i_int = 0;
p_hotkeys = p_intf->p_libvlc->p_hotkeys;
key = [[o_event charactersIgnoringModifiers] characterAtIndex: 0];
+ /* handle Lion's default key combo for fullscreen-toggle in addition to our own hotkeys */
+ if( key == 'f' && i_pressed_modifiers & NSControlKeyMask && i_pressed_modifiers & NSCommandKeyMask )
+ {
+ [[VLCCoreInteraction sharedInstance] toggleFullscreen];
+ [tempString release];
+ [tempStringPlus release];
+ return YES;
+ }
+
switch( key )
{
case NSDeleteCharacter:
case NSLeftArrowFunctionKey:
case NSEnterCharacter:
case NSCarriageReturnCharacter:
+ [tempString release];
+ [tempStringPlus release];
return NO;
}
if( key == 0x0020 ) // space key
{
[[VLCCoreInteraction sharedInstance] play];
+ [tempString release];
+ [tempStringPlus release];
return YES;
}
if( [o_usedHotkeys indexOfObject: tempString] != NSNotFound || [o_usedHotkeys indexOfObject: tempStringPlus] != NSNotFound )
{
var_SetInteger( p_intf->p_libvlc, "key-pressed", val.i_int );
+ [tempString release];
+ [tempStringPlus release];
return YES;
}
+ [tempString release];
+ [tempStringPlus release];
return NO;
}
}
}
module_config_free (p_config);
- o_usedHotkeys = [[NSArray alloc] initWithArray: o_usedHotkeys copyItems: YES];
+ o_usedHotkeys = [[NSArray alloc] initWithArray: o_tempArray copyItems: YES];
+ [o_tempArray release];
}
#pragma mark -
playlist_t * p_playlist = pl_Get( VLCIntf );
BOOL b_fullscreen = var_GetBool( p_playlist, "fullscreen" );
- if (OSX_LION && b_nativeFullscreenMode)
+ if (b_nativeFullscreenMode)
{
- [o_mainwindow toggleFullScreen: self];
+ // this is called twice in certain situations, so only toogle if we really need to
+ if( ( b_fullscreen && !([NSApp currentSystemPresentationOptions] & NSApplicationPresentationFullScreen) ) ||
+ ( !b_fullscreen && ([NSApp currentSystemPresentationOptions] & NSApplicationPresentationFullScreen) ) )
+ [o_mainwindow toggleFullScreen: self];
+
if(b_fullscreen)
[NSApp setPresentationOptions:(NSApplicationPresentationFullScreen | NSApplicationPresentationAutoHideDock | NSApplicationPresentationAutoHideMenuBar)];
else
- (void)PlaylistItemChanged
{
- input_thread_t * p_input;
+ if( p_current_input && ( p_current_input->b_dead || !vlc_object_alive( p_current_input ) ))
+ {
+ var_DelCallback( p_current_input, "intf-event", InputEvent, [VLCMain sharedInstance] );
+ vlc_object_release( p_current_input );
+ p_current_input = NULL;
- p_input = playlist_CurrentInput( pl_Get(VLCIntf) );
- if( p_input && !( p_input->b_dead || !vlc_object_alive(p_input) ) )
+ [o_mainmenu setRateControlsEnabled: NO];
+ }
+ else if( !p_current_input )
{
- var_AddCallback( p_input, "intf-event", InputEvent, [VLCMain sharedInstance] );
- [o_mainmenu setRateControlsEnabled: YES];
+ // object is hold here and released then it is dead
+ p_current_input = playlist_CurrentInput( pl_Get( VLCIntf ));
+ if( p_current_input )
+ {
+ var_AddCallback( p_current_input, "intf-event", InputEvent, [VLCMain sharedInstance] );
+ [self playbackStatusUpdated];
+ [o_mainmenu setRateControlsEnabled: YES];
+ if ( [self activeVideoPlayback] && [[o_mainwindow videoView] isHidden] )
+ [o_mainwindow performSelectorOnMainThread:@selector(togglePlaylist:) withObject: nil waitUntilDone:NO];
+ }
}
- else
- [o_mainmenu setRateControlsEnabled: NO];
-
- if (p_input)
- vlc_object_release( p_input );
[o_playlist updateRowSelection];
[o_mainwindow updateWindow];
+ [self updateDelays];
[self updateMainMenu];
}
p_input = pl_CurrentInput( p_intf );
if( p_input )
{
- if( var_GetInteger( p_input, "state" ) == PLAYING_S )
+ if( var_GetInteger( p_input, "state" ) == PLAYING_S && [self activeVideoPlayback] )
UpdateSystemActivity( UsrActivity );
vlc_object_release( p_input );
}
return o_mainmenu;
}
+- (id)mainWindow
+{
+ return o_mainwindow;
+}
+
- (id)controls
{
if( o_controls )
- (id)getVideoViewAtPositionX: (int *)pi_x Y: (int *)pi_y withWidth: (unsigned int*)pi_width andHeight: (unsigned int*)pi_height
{
- id videoView = [o_mainwindow videoView];
+ id videoView = [o_mainwindow setupVideoView];
NSRect videoRect = [videoView frame];
int i_x = (int)videoRect.origin.x;
int i_y = (int)videoRect.origin.y;
- (void)setActiveVideoPlayback:(BOOL)b_value
{
b_active_videoplayback = b_value;
- [o_mainwindow setVideoplayEnabled];
- [o_mainwindow performSelectorOnMainThread:@selector(togglePlaylist:) withObject: nil waitUntilDone:NO];
+ if( o_mainwindow )
+ {
+ [o_mainwindow performSelectorOnMainThread:@selector(setVideoplayEnabled) withObject:nil waitUntilDone:YES];
+ [o_mainwindow performSelectorOnMainThread:@selector(togglePlaylist:) withObject:nil waitUntilDone:NO];
+ }
}
- (BOOL)activeVideoPlayback
- (void)_removeOldPreferences
{
static NSString * kVLCPreferencesVersion = @"VLCPreferencesVersion";
- static const int kCurrentPreferencesVersion = 1;
+ static const int kCurrentPreferencesVersion = 2;
int version = [[NSUserDefaults standardUserDefaults] integerForKey:kVLCPreferencesVersion];
if( version >= kCurrentPreferencesVersion ) return;
- NSArray *libraries = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
- NSUserDomainMask, YES);
- if( !libraries || [libraries count] == 0) return;
- NSString * preferences = [[libraries objectAtIndex:0] stringByAppendingPathComponent:@"Preferences"];
-
- /* File not found, don't attempt anything */
- if(![[NSFileManager defaultManager] fileExistsAtPath:[preferences stringByAppendingPathComponent:@"VLC"]] &&
- ![[NSFileManager defaultManager] fileExistsAtPath:[preferences stringByAppendingPathComponent:@"org.videolan.vlc.plist"]] )
+ if( version == 1 )
{
[[NSUserDefaults standardUserDefaults] setInteger:kCurrentPreferencesVersion forKey:kVLCPreferencesVersion];
- return;
- }
+ [[NSUserDefaults standardUserDefaults] synchronize];
- int res = NSRunInformationalAlertPanel(_NS("Remove old preferences?"),
- _NS("We just found an older version of VLC's preferences files."),
- _NS("Move To Trash and Relaunch VLC"), _NS("Ignore"), nil, nil);
- if( res != NSOKButton )
- {
- [[NSUserDefaults standardUserDefaults] setInteger:kCurrentPreferencesVersion forKey:kVLCPreferencesVersion];
- return;
+ if (![[VLCCoreInteraction sharedInstance] fixPreferences])
+ return;
+ else
+ config_SaveConfigFile( VLCIntf ); // we need to do manually, since we won't quit libvlc cleanly
}
+ else
+ {
+ NSArray *libraries = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory,
+ NSUserDomainMask, YES);
+ if( !libraries || [libraries count] == 0) return;
+ NSString * preferences = [[libraries objectAtIndex:0] stringByAppendingPathComponent:@"Preferences"];
+
+ /* File not found, don't attempt anything */
+ if(![[NSFileManager defaultManager] fileExistsAtPath:[preferences stringByAppendingPathComponent:@"org.videolan.vlc"]] &&
+ ![[NSFileManager defaultManager] fileExistsAtPath:[preferences stringByAppendingPathComponent:@"org.videolan.vlc.plist"]] )
+ {
+ [[NSUserDefaults standardUserDefaults] setInteger:kCurrentPreferencesVersion forKey:kVLCPreferencesVersion];
+ return;
+ }
- NSArray * ourPreferences = [NSArray arrayWithObjects:@"org.videolan.vlc.plist", @"VLC", nil];
+ int res = NSRunInformationalAlertPanel(_NS("Remove old preferences?"),
+ _NS("We just found an older version of VLC's preferences files."),
+ _NS("Move To Trash and Relaunch VLC"), _NS("Ignore"), nil, nil);
+ if( res != NSOKButton )
+ {
+ [[NSUserDefaults standardUserDefaults] setInteger:kCurrentPreferencesVersion forKey:kVLCPreferencesVersion];
+ return;
+ }
- /* Move the file to trash so that user can find them later */
- [[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation source:preferences destination:nil files:ourPreferences tag:0];
+ NSArray * ourPreferences = [NSArray arrayWithObjects:@"org.videolan.vlc.plist", @"VLC", @"org.videolan.vlc", nil];
- /* really reset the defaults from now on */
- [NSUserDefaults resetStandardUserDefaults];
+ /* Move the file to trash so that user can find them later */
+ [[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation source:preferences destination:nil files:ourPreferences tag:0];
- [[NSUserDefaults standardUserDefaults] setInteger:kCurrentPreferencesVersion forKey:kVLCPreferencesVersion];
- [[NSUserDefaults standardUserDefaults] synchronize];
+ /* really reset the defaults from now on */
+ [NSUserDefaults resetStandardUserDefaults];
+
+ [[NSUserDefaults standardUserDefaults] setInteger:kCurrentPreferencesVersion forKey:kVLCPreferencesVersion];
+ [[NSUserDefaults standardUserDefaults] synchronize];
+ }
/* Relaunch now */
const char * path = [[[NSBundle mainBundle] executablePath] UTF8String];
- (void)processReceivedlibvlcMessage:(const msg_item_t *) item ofType: (int)i_type withStr: (char *)str
{
- NSColor *o_white = [NSColor whiteColor];
- NSColor *o_red = [NSColor redColor];
- NSColor *o_yellow = [NSColor yellowColor];
- NSColor *o_gray = [NSColor grayColor];
- NSString * firstString, * secondString;
+ if (o_msg_arr)
+ {
+ NSColor *o_white = [NSColor whiteColor];
+ NSColor *o_red = [NSColor redColor];
+ NSColor *o_yellow = [NSColor yellowColor];
+ NSColor *o_gray = [NSColor grayColor];
+ NSString * firstString, * secondString;
- NSColor * pp_color[4] = { o_white, o_red, o_yellow, o_gray };
- static const char * ppsz_type[4] = { ": ", " error: ", " warning: ", " debug: " };
+ NSColor * pp_color[4] = { o_white, o_red, o_yellow, o_gray };
+ static const char * ppsz_type[4] = { ": ", " error: ", " warning: ", " debug: " };
- NSDictionary *o_attr;
- NSMutableAttributedString *o_msg_color;
+ NSDictionary *o_attr;
+ NSMutableAttributedString *o_msg_color;
- [o_msg_lock lock];
+ [o_msg_lock lock];
- if( [o_msg_arr count] + 2 > 600 )
- {
- [o_msg_arr removeObjectAtIndex: 0];
- [o_msg_arr removeObjectAtIndex: 1];
- }
- firstString = [NSString stringWithFormat:@"%s%s", item->psz_module, ppsz_type[i_type]];
- secondString = [NSString stringWithFormat:@"%@%s\n", firstString, str];
+ if( [o_msg_arr count] + 2 > 600 )
+ {
+ [o_msg_arr removeObjectAtIndex: 0];
+ [o_msg_arr removeObjectAtIndex: 1];
+ }
+ firstString = [NSString stringWithFormat:@"%s%s", item->psz_module, ppsz_type[i_type]];
+ secondString = [NSString stringWithFormat:@"%@%s\n", firstString, str];
- o_attr = [NSDictionary dictionaryWithObject: pp_color[i_type] forKey: NSForegroundColorAttributeName];
- o_msg_color = [[NSMutableAttributedString alloc] initWithString: secondString attributes: o_attr];
- o_attr = [NSDictionary dictionaryWithObject: pp_color[3] forKey: NSForegroundColorAttributeName];
- [o_msg_color setAttributes: o_attr range: NSMakeRange( 0, [firstString length] )];
- [o_msg_arr addObject: [o_msg_color autorelease]];
+ o_attr = [NSDictionary dictionaryWithObject: pp_color[i_type] forKey: NSForegroundColorAttributeName];
+ o_msg_color = [[NSMutableAttributedString alloc] initWithString: secondString attributes: o_attr];
+ o_attr = [NSDictionary dictionaryWithObject: pp_color[3] forKey: NSForegroundColorAttributeName];
+ [o_msg_color setAttributes: o_attr range: NSMakeRange( 0, [firstString length] )];
+ [o_msg_arr addObject: [o_msg_color autorelease]];
- b_msg_arr_changed = YES;
- [o_msg_lock unlock];
+ b_msg_arr_changed = YES;
+ [o_msg_lock unlock];
+ }
}
- (IBAction)saveDebugLog:(id)sender
- (void)coreChangedMediaKeySupportSetting: (NSNotification *)o_notification
{
b_mediaKeySupport = config_GetInt( VLCIntf, "macosx-mediakeys" );
- if (b_mediaKeySupport) {
+ if (b_mediaKeySupport)
+ {
if (!o_mediaKeyController)
o_mediaKeyController = [[SPMediaKeyTap alloc] initWithDelegate:self];
[o_mediaKeyController startWatchingMediaKeys];
}
else if (!b_mediaKeySupport && o_mediaKeyController)
- {
- int returnedValue = NSRunInformationalAlertPanel(_NS("Relaunch required"),
- _NS("To make sure that VLC no longer listens to your media key events, it needs to be restarted."),
- _NS("Relaunch VLC"), _NS("Ignore"), nil, nil);
- if( returnedValue == NSOKButton )
- {
- /* Relaunch now */
- const char * path = [[[NSBundle mainBundle] executablePath] UTF8String];
-
- /* For some reason we need to fork(), not just execl(), which reports a ENOTSUP then. */
- if(fork() != 0)
- {
- exit(0);
- return;
- }
- execl(path, path, NULL);
- }
- }
+ [o_mediaKeyController stopWatchingMediaKeys];
}
@end
// when user selects the quit menu from dock it sends a terminate:
// but we need to send a stop: to properly exits libvlc.
// However, we are not able to change the action-method sent by this standard menu item.
-// thus we override terminat: to send a stop:
+// thus we override terminate: to send a stop:
// see [af97f24d528acab89969d6541d83f17ce1ecd580] that introduced the removal of setjmp() and longjmp()
- (void)terminate:(id)sender
{