X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fmacosx%2Fintf.m;h=250981ffbefc31bd9269ebbf21f28e4cf7e85e8c;hb=204fbab2fb255358ee238ddd42a332b691190389;hp=f31abc8092ae6f8a3f6eb56d0ae70b8c4aadbdf1;hpb=52638891205fe3fc4df1b69dd4d969d52faaeb71;p=vlc diff --git a/modules/gui/macosx/intf.m b/modules/gui/macosx/intf.m index f31abc8092..250981ffbe 100644 --- a/modules/gui/macosx/intf.m +++ b/modules/gui/macosx/intf.m @@ -31,6 +31,7 @@ #include /* for MAXPATHLEN */ #include #include +#include /* execl() */ #ifdef HAVE_CONFIG_H # include "config.h" @@ -57,36 +58,20 @@ #import #import +#import /***************************************************************************** * Local prototypes. *****************************************************************************/ static void Run ( intf_thread_t *p_intf ); -/* Quick hack */ -/***************************************************************************** - * VLCApplication implementation (this hack is really disgusting now, - * feel free to fix.) - *****************************************************************************/ -@interface VLCApplication : NSApplication -{ - libvlc_int_t *o_libvlc; -} -- (void)setVLC: (libvlc_int_t *)p_libvlc; -@end +static void * ManageThread( void *user_data ); +static unichar VLCKeyToCocoa( unsigned int i_key ); +static unsigned int VLCModifiersToCocoa( unsigned int i_key ); -@implementation VLCApplication -- (void)setVLC: (libvlc_int_t *) p_libvlc -{ - o_libvlc = p_libvlc; -} -- (void)terminate: (id)sender -{ - vlc_object_kill( o_libvlc ); - [super terminate: sender]; -} -@end +#pragma mark - +#pragma mark VLC Interface Object Callbacks /***************************************************************************** * OpenIntf: initialize interface @@ -119,8 +104,6 @@ void CloseIntf ( vlc_object_t *p_this ) { intf_thread_t *p_intf = (intf_thread_t*) p_this; - [[VLCMain sharedInstance] setIntf: nil]; - msg_Unsubscribe( p_intf, p_intf->p_sys->p_sub ); [p_intf->p_sys->o_pool release]; @@ -154,9 +137,7 @@ static void Run( intf_thread_t *p_intf ) /* Install a jmpbuffer to where we can go back before the NSApp exit * see applicationWillTerminate: */ - /* We need that code to run on main thread */ - [VLCApplication sharedApplication]; - [NSApp setVLC: p_intf->p_libvlc]; + [NSApplication sharedApplication]; [[VLCMain sharedInstance] setIntf: p_intf]; [NSBundle loadNibNamed: @"MainMenu" owner: NSApp]; @@ -169,17 +150,8 @@ static void Run( intf_thread_t *p_intf ) [o_pool release]; } -/***************************************************************************** - * ManageThread: An ugly thread that polls - *****************************************************************************/ -static void * ManageThread( void *user_data ) -{ - id self = user_data; - - [self manage]; - - return NULL; -} +#pragma mark - +#pragma mark Variables Callback /***************************************************************************** * playlistChanged: Callback triggered by the intf-change playlist @@ -240,90 +212,21 @@ static int InteractCallback( vlc_object_t *p_this, const char *psz_variable, return VLC_SUCCESS; } -static struct -{ - unichar i_nskey; - unsigned int i_vlckey; -} nskeys_to_vlckeys[] = -{ - { NSUpArrowFunctionKey, KEY_UP }, - { NSDownArrowFunctionKey, KEY_DOWN }, - { NSLeftArrowFunctionKey, KEY_LEFT }, - { NSRightArrowFunctionKey, KEY_RIGHT }, - { NSF1FunctionKey, KEY_F1 }, - { NSF2FunctionKey, KEY_F2 }, - { NSF3FunctionKey, KEY_F3 }, - { NSF4FunctionKey, KEY_F4 }, - { NSF5FunctionKey, KEY_F5 }, - { NSF6FunctionKey, KEY_F6 }, - { NSF7FunctionKey, KEY_F7 }, - { NSF8FunctionKey, KEY_F8 }, - { NSF9FunctionKey, KEY_F9 }, - { NSF10FunctionKey, KEY_F10 }, - { NSF11FunctionKey, KEY_F11 }, - { NSF12FunctionKey, KEY_F12 }, - { NSInsertFunctionKey, KEY_INSERT }, - { NSHomeFunctionKey, KEY_HOME }, - { NSEndFunctionKey, KEY_END }, - { NSPageUpFunctionKey, KEY_PAGEUP }, - { NSPageDownFunctionKey, KEY_PAGEDOWN }, - { NSMenuFunctionKey, KEY_MENU }, - { NSTabCharacter, KEY_TAB }, - { NSCarriageReturnCharacter, KEY_ENTER }, - { NSEnterCharacter, KEY_ENTER }, - { NSBackspaceCharacter, KEY_BACKSPACE }, - { (unichar) ' ', KEY_SPACE }, - { (unichar) 0x1b, KEY_ESC }, - {0,0} -}; - -unichar VLCKeyToCocoa( unsigned int i_key ) -{ - unsigned int i; - - for( i = 0; nskeys_to_vlckeys[i].i_vlckey != 0; i++ ) - { - if( nskeys_to_vlckeys[i].i_vlckey == (i_key & ~KEY_MODIFIER) ) - { - return nskeys_to_vlckeys[i].i_nskey; - } - } - return (unichar)(i_key & ~KEY_MODIFIER); -} - -unsigned int CocoaKeyToVLC( unichar i_key ) -{ - unsigned int i; - - for( i = 0; nskeys_to_vlckeys[i].i_nskey != 0; i++ ) - { - if( nskeys_to_vlckeys[i].i_nskey == i_key ) - { - return nskeys_to_vlckeys[i].i_vlckey; - } - } - return (unsigned int)i_key; -} +#pragma mark - +#pragma mark Private -unsigned int VLCModifiersToCocoa( unsigned int i_key ) -{ - unsigned int new = 0; - if( i_key & KEY_MODIFIER_COMMAND ) - new |= NSCommandKeyMask; - if( i_key & KEY_MODIFIER_ALT ) - new |= NSAlternateKeyMask; - if( i_key & KEY_MODIFIER_SHIFT ) - new |= NSShiftKeyMask; - if( i_key & KEY_MODIFIER_CTRL ) - new |= NSControlKeyMask; - return new; -} +@interface VLCMain () +- (void)_removeOldPreferences; +@end /***************************************************************************** * VLCMain implementation *****************************************************************************/ @implementation VLCMain +#pragma mark - +#pragma mark Initialization + static VLCMain *_o_sharedMainInstance = nil; + (VLCMain *)sharedInstance @@ -527,107 +430,58 @@ static VLCMain *_o_sharedMainInstance = nil; nib_main_loaded = TRUE; } -#pragma mark Toolbar delegate -/* Our item identifiers */ -static NSString * VLCToolbarMediaControl = @"VLCToolbarMediaControl"; - -- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar -{ - return [NSArray arrayWithObjects: -// NSToolbarCustomizeToolbarItemIdentifier, -// NSToolbarFlexibleSpaceItemIdentifier, -// NSToolbarSpaceItemIdentifier, -// NSToolbarSeparatorItemIdentifier, - VLCToolbarMediaControl, - nil ]; -} - -- (NSArray *) toolbarDefaultItemIdentifiers: (NSToolbar *) toolbar -{ - return [NSArray arrayWithObjects: - VLCToolbarMediaControl, - nil ]; -} - -- (NSToolbarItem *) toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag +- (void)applicationWillFinishLaunching:(NSNotification *)o_notification { - NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdentifier] autorelease]; + o_msg_lock = [[NSLock alloc] init]; + o_msg_arr = [[NSMutableArray arrayWithCapacity: 200] retain]; - - if( [itemIdentifier isEqual: VLCToolbarMediaControl] ) - { - [toolbarItem setLabel:@"Media Controls"]; - [toolbarItem setPaletteLabel:@"Media Controls"]; + /* FIXME: don't poll */ + interfaceTimer = [[NSTimer scheduledTimerWithTimeInterval: 0.5 + target: self selector: @selector(manageIntf:) + userInfo: nil repeats: FALSE] retain]; - NSSize size = toolbarMediaControl.frame.size; - [toolbarItem setView:toolbarMediaControl]; - [toolbarItem setMinSize:size]; - size.width += 1000.; - [toolbarItem setMaxSize:size]; + /* Note: we use the pthread API to support pre-10.5 */ + pthread_create( &manage_thread, NULL, ManageThread, self ); - // Hack: For some reason we need to make sure - // that the those element are on top - // Add them again will put them frontmost - [toolbarMediaControl addSubview:o_scrollfield]; - [toolbarMediaControl addSubview:o_timeslider]; - [toolbarMediaControl addSubview:o_timefield]; - [toolbarMediaControl addSubview:o_main_pgbar]; + [o_controls setupVarMenuItem: o_mi_add_intf target: (vlc_object_t *)p_intf + var: "intf-add" selector: @selector(toggleVar:)]; - /* TODO: setup a menu */ - } - else + /* check whether the user runs a valid version of OSX; alert is auto-released */ + if( MACOS_VERSION < 10.4f ) { - /* itemIdentifier referred to a toolbar item that is not - * provided or supported by us or Cocoa - * Returning nil will inform the toolbar - * that this kind of item is not supported */ - toolbarItem = nil; + NSAlert *ourAlert; + int i_returnValue; + ourAlert = [NSAlert alertWithMessageText: _NS("Your version of Mac OS X is not supported") + defaultButton: _NS("Quit") + alternateButton: NULL + otherButton: NULL + informativeTextWithFormat: _NS("VLC media player requires Mac OS X 10.4 or higher.")]; + [ourAlert setAlertStyle: NSCriticalAlertStyle]; + i_returnValue = [ourAlert runModal]; + [NSApp terminate: self]; } - return toolbarItem; -} -#pragma mark - + vlc_thread_set_priority( p_intf, VLC_THREAD_PRIORITY_LOW ); +} -- (void)controlTintChanged +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { - BOOL b_playing = NO; - - if( [o_btn_play alternateImage] == o_img_play_pressed ) - b_playing = YES; - - if( [NSColor currentControlTint] == NSGraphiteControlTint ) - { - o_img_play_pressed = [NSImage imageNamed: @"play_graphite"]; - o_img_pause_pressed = [NSImage imageNamed: @"pause_graphite"]; - - [o_btn_prev setAlternateImage: [NSImage imageNamed: @"previous_graphite"]]; - [o_btn_rewind setAlternateImage: [NSImage imageNamed: @"skip_previous_graphite"]]; - [o_btn_stop setAlternateImage: [NSImage imageNamed: @"stop_graphite"]]; - [o_btn_ff setAlternateImage: [NSImage imageNamed: @"skip_forward_graphite"]]; - [o_btn_next setAlternateImage: [NSImage imageNamed: @"next_graphite"]]; - [o_btn_fullscreen setAlternateImage: [NSImage imageNamed: @"fullscreen_graphite"]]; - [o_btn_playlist setAlternateImage: [NSImage imageNamed: @"playlistdrawer_graphite"]]; - [o_btn_equalizer setAlternateImage: [NSImage imageNamed: @"equalizerdrawer_graphite"]]; - } - else - { - o_img_play_pressed = [NSImage imageNamed: @"play_blue"]; - o_img_pause_pressed = [NSImage imageNamed: @"pause_blue"]; - - [o_btn_prev setAlternateImage: [NSImage imageNamed: @"previous_blue"]]; - [o_btn_rewind setAlternateImage: [NSImage imageNamed: @"skip_previous_blue"]]; - [o_btn_stop setAlternateImage: [NSImage imageNamed: @"stop_blue"]]; - [o_btn_ff setAlternateImage: [NSImage imageNamed: @"skip_forward_blue"]]; - [o_btn_next setAlternateImage: [NSImage imageNamed: @"next_blue"]]; - [o_btn_fullscreen setAlternateImage: [NSImage imageNamed: @"fullscreen_blue"]]; - [o_btn_playlist setAlternateImage: [NSImage imageNamed: @"playlistdrawer_blue"]]; - [o_btn_equalizer setAlternateImage: [NSImage imageNamed: @"equalizerdrawer_blue"]]; - } - - if( b_playing ) - [o_btn_play setAlternateImage: o_img_play_pressed]; - else - [o_btn_play setAlternateImage: o_img_pause_pressed]; + [self _removeOldPreferences]; + +#ifdef UPDATE_CHECK + /* Check for update silently on startup */ + if( !nib_update_loaded ) + nib_update_loaded = [NSBundle loadNibNamed:@"Update" owner:self]; + + if([o_update shouldCheckForUpdate]) + [NSThread detachNewThreadSelector:@selector(checkForUpdate) toTarget:o_update withObject:nil]; +#endif + + /* Handle sleep notification */ + [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(computerWillSleep:) + name:NSWorkspaceWillSleepNotification object:nil]; + + [NSThread detachNewThreadSelector:@selector(lookForCrashLog) toTarget:self withObject:nil]; } - (void)initStrings @@ -736,6 +590,13 @@ static NSString * VLCToolbarMediaControl = @"VLCToolbarMediaControl"; [o_mu_deinterlace setTitle: _NS("Deinterlace")]; [o_mi_ffmpeg_pp setTitle: _NS("Post processing")]; [o_mu_ffmpeg_pp setTitle: _NS("Post processing")]; + [o_mi_teletext setTitle: _NS("Teletext")]; + [o_mi_teletext_transparent setTitle: _NS("Transparent")]; + [o_mi_teletext_index setTitle: _NS("Index")]; + [o_mi_teletext_red setTitle: _NS("Red")]; + [o_mi_teletext_green setTitle: _NS("Green")]; + [o_mi_teletext_yellow setTitle: _NS("Yellow")]; + [o_mi_teletext_blue setTitle: _NS("Blue")]; [o_mu_window setTitle: _NS("Window")]; [o_mi_minimize setTitle: _NS("Minimize Window")]; @@ -777,102 +638,231 @@ static NSString * VLCToolbarMediaControl = @"VLCToolbarMediaControl"; [o_vmi_mute setTitle: _NS("Mute")]; [o_vmi_fullscreen setTitle: _NS("Fullscreen")]; [o_vmi_snapshot setTitle: _NS("Snapshot")]; + + /* crash reporter panel */ + [o_crashrep_send_btn setTitle: _NS("Send")]; + [o_crashrep_dontSend_btn setTitle: _NS("Don't Send")]; + [o_crashrep_title_txt setStringValue: _NS("VLC crashed previously")]; + [o_crashrep_win setTitle: _NS("VLC crashed previously")]; + [o_crashrep_desc_txt setStringValue: _NS("Do you want to send details on the crash to VLC's development team?\n\nIf you want, you can enter a few lines on what you did before VLC crashed along with other helpful information: a link to download a sample file, a URL of a network stream, ...")]; + [o_crashrep_includeEmail_ckb setTitle: _NS("I agree to be possibly contacted about this bugreport.")]; + [o_crashrep_includeEmail_txt setStringValue: _NS("Only your default E-Mail address will be submitted, including no further information.")]; } -- (void)applicationWillFinishLaunching:(NSNotification *)o_notification -{ - o_msg_lock = [[NSLock alloc] init]; - o_msg_arr = [[NSMutableArray arrayWithCapacity: 200] retain]; +#pragma mark - +#pragma mark Termination - /* FIXME: don't poll */ - interfaceTimer = [[NSTimer scheduledTimerWithTimeInterval: 0.5 - target: self selector: @selector(manageIntf:) - userInfo: nil repeats: FALSE] retain]; +- (void)applicationWillTerminate:(NSNotification *)notification +{ + playlist_t * p_playlist; + vout_thread_t * p_vout; + int returnedValue = 0; + + msg_Dbg( p_intf, "Terminating" ); - /* Note: we use the pthread API to support pre-10.5 */ - pthread_create( &manage_thread, NULL, ManageThread, self ); + /* Make sure the manage_thread won't call -terminate: again */ + pthread_cancel( manage_thread ); - [o_controls setupVarMenuItem: o_mi_add_intf target: (vlc_object_t *)p_intf - var: "intf-add" selector: @selector(toggleVar:)]; + /* Make sure the intf object is getting killed */ + vlc_object_kill( p_intf ); - /* check whether the user runs a valid version of OSX; alert is auto-released */ - if( MACOS_VERSION < 10.4f ) + /* Make sure our manage_thread ends */ + pthread_join( manage_thread, NULL ); + + /* Make sure the interfaceTimer is destroyed */ + [interfaceTimer invalidate]; + [interfaceTimer release]; + interfaceTimer = nil; + + /* make sure that the current volume is saved */ + config_PutInt( p_intf->p_libvlc, "volume", i_lastShownVolume ); + + /* save the prefs if they were changed in the extended panel */ + if(o_extended && [o_extended getConfigChanged]) { - NSAlert *ourAlert; - int i_returnValue; - ourAlert = [NSAlert alertWithMessageText: _NS("Your version of Mac OS X is not supported") - defaultButton: _NS("Quit") - alternateButton: NULL - otherButton: NULL - informativeTextWithFormat: _NS("VLC media player requires Mac OS X 10.4 or higher.")]; - [ourAlert setAlertStyle: NSCriticalAlertStyle]; - i_returnValue = [ourAlert runModal]; - [NSApp terminate: self]; + [o_extended savePrefs]; } + + p_intf->b_interaction = false; + var_DelCallback( p_intf, "interaction", InteractCallback, self ); - vlc_thread_set_priority( p_intf, VLC_THREAD_PRIORITY_LOW ); -} + /* remove global observer watching for vout device changes correctly */ + [[NSNotificationCenter defaultCenter] removeObserver: self]; -- (BOOL)application:(NSApplication *)o_app openFile:(NSString *)o_filename -{ - BOOL b_autoplay = config_GetInt( VLCIntf, "macosx-autoplay" ); - NSDictionary *o_dic = [NSDictionary dictionaryWithObjectsAndKeys: o_filename, @"ITEM_URL", nil]; - if( b_autoplay ) - [o_playlist appendArray: [NSArray arrayWithObject: o_dic] atPos: -1 enqueue: NO]; - else - [o_playlist appendArray: [NSArray arrayWithObject: o_dic] atPos: -1 enqueue: YES]; + [o_update end]; - return( TRUE ); -} + /* release some other objects here, because it isn't sure whether dealloc + * will be called later on */ -- (NSString *)localizedString:(const char *)psz -{ - NSString * o_str = nil; + if( nib_about_loaded ) + [o_about release]; - if( psz != NULL ) + if( nib_prefs_loaded ) { - o_str = [[[NSString alloc] initWithUTF8String: psz] autorelease]; + [o_sprefs release]; + [o_prefs release]; + } - if( o_str == NULL ) - { - msg_Err( VLCIntf, "could not translate: %s", psz ); - return( @"" ); - } + if( nib_open_loaded ) + [o_open release]; + + if( nib_extended_loaded ) + { + [o_extended release]; } - else + + if( nib_bookmarks_loaded ) + [o_bookmarks release]; + + if( o_info ) { - msg_Warn( VLCIntf, "can't translate empty strings" ); - return( @"" ); + [o_info stopTimers]; + [o_info release]; } - return( o_str ); + if( nib_wizard_loaded ) + [o_wizard release]; + + [crashLogURLConnection cancel]; + [crashLogURLConnection release]; + + [o_embedded_list release]; + [o_interaction_list release]; + [o_eyetv release]; + + [o_img_pause_pressed release]; + [o_img_play_pressed release]; + [o_img_pause release]; + [o_img_play release]; + + [o_msg_arr removeAllObjects]; + [o_msg_arr release]; + + [o_msg_lock release]; + + /* write cached user defaults to disk */ + [[NSUserDefaults standardUserDefaults] synchronize]; + + /* Kill the playlist, so that it doesn't accept new request + * such as the play request from vlc.c (we are a blocking interface). */ + p_playlist = pl_Yield( p_intf ); + vlc_object_kill( p_playlist ); + pl_Release( p_intf ); + + vlc_object_kill( p_intf->p_libvlc ); + + [self setIntf:nil]; + + /* Go back to Run() and make libvlc exit properly */ + if( jmpbuffer ) + longjmp( jmpbuffer, 1 ); + /* not reached */ } -/* When user click in the Dock icon our double click in the finder */ -- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)hasVisibleWindows -{ - if(!hasVisibleWindows) - [o_window makeKeyAndOrderFront:self]; +#pragma mark - +#pragma mark Toolbar delegate - return YES; +/* Our item identifiers */ +static NSString * VLCToolbarMediaControl = @"VLCToolbarMediaControl"; + +- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar +{ + return [NSArray arrayWithObjects: +// NSToolbarCustomizeToolbarItemIdentifier, +// NSToolbarFlexibleSpaceItemIdentifier, +// NSToolbarSpaceItemIdentifier, +// NSToolbarSeparatorItemIdentifier, + VLCToolbarMediaControl, + nil ]; } -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification +- (NSArray *) toolbarDefaultItemIdentifiers: (NSToolbar *) toolbar { -#ifdef UPDATE_CHECK - /* Check for update silently on startup */ - if( !nib_update_loaded ) - nib_update_loaded = [NSBundle loadNibNamed:@"Update" owner:self]; + return [NSArray arrayWithObjects: + VLCToolbarMediaControl, + nil ]; +} - if([o_update shouldCheckForUpdate]) - [NSThread detachNewThreadSelector:@selector(checkForUpdate) toTarget:o_update withObject:nil]; -#endif +- (NSToolbarItem *) toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag +{ + NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdentifier] autorelease]; - /* Handle sleep notification */ - [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(computerWillSleep:) - name:NSWorkspaceWillSleepNotification object:nil]; + + if( [itemIdentifier isEqual: VLCToolbarMediaControl] ) + { + [toolbarItem setLabel:@"Media Controls"]; + [toolbarItem setPaletteLabel:@"Media Controls"]; - [NSThread detachNewThreadSelector:@selector(lookForCrashLog) toTarget:self withObject:nil]; + NSSize size = toolbarMediaControl.frame.size; + [toolbarItem setView:toolbarMediaControl]; + [toolbarItem setMinSize:size]; + size.width += 1000.; + [toolbarItem setMaxSize:size]; + + // Hack: For some reason we need to make sure + // that the those element are on top + // Add them again will put them frontmost + [toolbarMediaControl addSubview:o_scrollfield]; + [toolbarMediaControl addSubview:o_timeslider]; + [toolbarMediaControl addSubview:o_timefield]; + [toolbarMediaControl addSubview:o_main_pgbar]; + + /* TODO: setup a menu */ + } + else + { + /* itemIdentifier referred to a toolbar item that is not + * provided or supported by us or Cocoa + * Returning nil will inform the toolbar + * that this kind of item is not supported */ + toolbarItem = nil; + } + return toolbarItem; +} + +#pragma mark - +#pragma mark Other notification + +- (void)controlTintChanged +{ + BOOL b_playing = NO; + + if( [o_btn_play alternateImage] == o_img_play_pressed ) + b_playing = YES; + + if( [NSColor currentControlTint] == NSGraphiteControlTint ) + { + o_img_play_pressed = [NSImage imageNamed: @"play_graphite"]; + o_img_pause_pressed = [NSImage imageNamed: @"pause_graphite"]; + + [o_btn_prev setAlternateImage: [NSImage imageNamed: @"previous_graphite"]]; + [o_btn_rewind setAlternateImage: [NSImage imageNamed: @"skip_previous_graphite"]]; + [o_btn_stop setAlternateImage: [NSImage imageNamed: @"stop_graphite"]]; + [o_btn_ff setAlternateImage: [NSImage imageNamed: @"skip_forward_graphite"]]; + [o_btn_next setAlternateImage: [NSImage imageNamed: @"next_graphite"]]; + [o_btn_fullscreen setAlternateImage: [NSImage imageNamed: @"fullscreen_graphite"]]; + [o_btn_playlist setAlternateImage: [NSImage imageNamed: @"playlistdrawer_graphite"]]; + [o_btn_equalizer setAlternateImage: [NSImage imageNamed: @"equalizerdrawer_graphite"]]; + } + else + { + o_img_play_pressed = [NSImage imageNamed: @"play_blue"]; + o_img_pause_pressed = [NSImage imageNamed: @"pause_blue"]; + + [o_btn_prev setAlternateImage: [NSImage imageNamed: @"previous_blue"]]; + [o_btn_rewind setAlternateImage: [NSImage imageNamed: @"skip_previous_blue"]]; + [o_btn_stop setAlternateImage: [NSImage imageNamed: @"stop_blue"]]; + [o_btn_ff setAlternateImage: [NSImage imageNamed: @"skip_forward_blue"]]; + [o_btn_next setAlternateImage: [NSImage imageNamed: @"next_blue"]]; + [o_btn_fullscreen setAlternateImage: [NSImage imageNamed: @"fullscreen_blue"]]; + [o_btn_playlist setAlternateImage: [NSImage imageNamed: @"playlistdrawer_blue"]]; + [o_btn_equalizer setAlternateImage: [NSImage imageNamed: @"equalizerdrawer_blue"]]; + } + + if( b_playing ) + [o_btn_play setAlternateImage: o_img_play_pressed]; + else + [o_btn_play setAlternateImage: o_img_pause_pressed]; } /* Listen to the remote in exclusive mode, only when VLC is the active @@ -898,6 +888,33 @@ static NSString * VLCToolbarMediaControl = @"VLCToolbarMediaControl"; } } +#pragma mark - +#pragma mark File opening + +- (BOOL)application:(NSApplication *)o_app openFile:(NSString *)o_filename +{ + BOOL b_autoplay = config_GetInt( VLCIntf, "macosx-autoplay" ); + NSDictionary *o_dic = [NSDictionary dictionaryWithObjectsAndKeys: o_filename, @"ITEM_URL", nil]; + if( b_autoplay ) + [o_playlist appendArray: [NSArray arrayWithObject: o_dic] atPos: -1 enqueue: NO]; + else + [o_playlist appendArray: [NSArray arrayWithObject: o_dic] atPos: -1 enqueue: YES]; + + return( TRUE ); +} + +/* When user click in the Dock icon our double click in the finder */ +- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)hasVisibleWindows +{ + if(!hasVisibleWindows) + [o_window makeKeyAndOrderFront:self]; + + return YES; +} + +#pragma mark - +#pragma mark Apple Remote Control + /* Helper method for the remote control interface in order to trigger forward/backward and volume increase/decrease as long as the user holds the left/right, plus/minus button */ - (void) executeHoldActionForRemoteButton: (NSNumber*) buttonIdentifierNumber @@ -977,6 +994,35 @@ static NSString * VLCToolbarMediaControl = @"VLCToolbarMediaControl"; } } +#pragma mark - +#pragma mark String utility +// FIXME: this has nothing to do here + +- (NSString *)localizedString:(const char *)psz +{ + NSString * o_str = nil; + + if( psz != NULL ) + { + o_str = [[[NSString alloc] initWithUTF8String: psz] autorelease]; + + if( o_str == NULL ) + { + msg_Err( VLCIntf, "could not translate: %s", psz ); + return( @"" ); + } + } + else + { + msg_Warn( VLCIntf, "can't translate empty strings" ); + return( @"" ); + } + + return( o_str ); +} + + + - (char *)delocalizeString:(NSString *)id { NSData * o_data = [id dataUsingEncoding: NSUTF8StringEncoding @@ -1047,6 +1093,88 @@ static NSString * VLCToolbarMediaControl = @"VLCToolbarMediaControl"; } +#pragma mark - +#pragma mark Key Shortcuts + +static struct +{ + unichar i_nskey; + unsigned int i_vlckey; +} nskeys_to_vlckeys[] = +{ + { NSUpArrowFunctionKey, KEY_UP }, + { NSDownArrowFunctionKey, KEY_DOWN }, + { NSLeftArrowFunctionKey, KEY_LEFT }, + { NSRightArrowFunctionKey, KEY_RIGHT }, + { NSF1FunctionKey, KEY_F1 }, + { NSF2FunctionKey, KEY_F2 }, + { NSF3FunctionKey, KEY_F3 }, + { NSF4FunctionKey, KEY_F4 }, + { NSF5FunctionKey, KEY_F5 }, + { NSF6FunctionKey, KEY_F6 }, + { NSF7FunctionKey, KEY_F7 }, + { NSF8FunctionKey, KEY_F8 }, + { NSF9FunctionKey, KEY_F9 }, + { NSF10FunctionKey, KEY_F10 }, + { NSF11FunctionKey, KEY_F11 }, + { NSF12FunctionKey, KEY_F12 }, + { NSInsertFunctionKey, KEY_INSERT }, + { NSHomeFunctionKey, KEY_HOME }, + { NSEndFunctionKey, KEY_END }, + { NSPageUpFunctionKey, KEY_PAGEUP }, + { NSPageDownFunctionKey, KEY_PAGEDOWN }, + { NSMenuFunctionKey, KEY_MENU }, + { NSTabCharacter, KEY_TAB }, + { NSCarriageReturnCharacter, KEY_ENTER }, + { NSEnterCharacter, KEY_ENTER }, + { NSBackspaceCharacter, KEY_BACKSPACE }, + { (unichar) ' ', KEY_SPACE }, + { (unichar) 0x1b, KEY_ESC }, + {0,0} +}; + +static unichar VLCKeyToCocoa( unsigned int i_key ) +{ + unsigned int i; + + for( i = 0; nskeys_to_vlckeys[i].i_vlckey != 0; i++ ) + { + if( nskeys_to_vlckeys[i].i_vlckey == (i_key & ~KEY_MODIFIER) ) + { + return nskeys_to_vlckeys[i].i_nskey; + } + } + return (unichar)(i_key & ~KEY_MODIFIER); +} + +unsigned int CocoaKeyToVLC( unichar i_key ) +{ + unsigned int i; + + for( i = 0; nskeys_to_vlckeys[i].i_nskey != 0; i++ ) + { + if( nskeys_to_vlckeys[i].i_nskey == i_key ) + { + return nskeys_to_vlckeys[i].i_vlckey; + } + } + return (unsigned int)i_key; +} + +static unsigned int VLCModifiersToCocoa( unsigned int i_key ) +{ + unsigned int new = 0; + if( i_key & KEY_MODIFIER_COMMAND ) + new |= NSCommandKeyMask; + if( i_key & KEY_MODIFIER_ALT ) + new |= NSAlternateKeyMask; + if( i_key & KEY_MODIFIER_SHIFT ) + new |= NSShiftKeyMask; + if( i_key & KEY_MODIFIER_CTRL ) + new |= NSControlKeyMask; + return new; +} + /***************************************************************************** * hasDefinedShortcutKey: Check to see if the key press is a defined VLC * shortcut key. If it is, pass it off to VLC for handling and return YES, @@ -1105,6 +1233,10 @@ static NSString * VLCToolbarMediaControl = @"VLCToolbarMediaControl"; return NO; } +#pragma mark - +#pragma mark Other objects getters +// FIXME: this is ugly and does not respect cocoa naming scheme + - (id)getControls { if( o_controls ) @@ -1211,13 +1343,54 @@ static NSString * VLCToolbarMediaControl = @"VLCToolbarMediaControl"; return nil; } +#pragma mark - +#pragma mark Polling + +/***************************************************************************** + * ManageThread: An ugly thread that polls + *****************************************************************************/ +static void * ManageThread( void *user_data ) +{ + id self = user_data; + + [self manage]; + + return NULL; +} + +struct manage_cleanup_stack { + intf_thread_t * p_intf; + input_thread_t ** p_input; + playlist_t * p_playlist; + id self; +}; + +static void * manage_cleanup( void * args ) +{ + struct manage_cleanup_stack * manage_cleanup_stack = args; + intf_thread_t * p_intf = manage_cleanup_stack->p_intf; + input_thread_t * p_input = *manage_cleanup_stack->p_input; + id self = manage_cleanup_stack->self; + playlist_t * p_playlist = manage_cleanup_stack->p_playlist; + + var_AddCallback( p_playlist, "playlist-current", PlaylistChanged, self ); + var_AddCallback( p_playlist, "intf-change", PlaylistChanged, self ); + var_AddCallback( p_playlist, "item-change", PlaylistChanged, self ); + var_AddCallback( p_playlist, "item-append", PlaylistChanged, self ); + var_AddCallback( p_playlist, "item-deleted", PlaylistChanged, self ); + + pl_Release( p_intf ); + + if( p_input ) vlc_object_release( p_input ); + return NULL; +} + - (void)manage { playlist_t * p_playlist; input_thread_t * p_input = NULL; /* new thread requires a new pool */ - NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init]; vlc_thread_set_priority( p_intf, VLC_THREAD_PRIORITY_LOW ); @@ -1229,12 +1402,12 @@ static NSString * VLCToolbarMediaControl = @"VLCToolbarMediaControl"; var_AddCallback( p_playlist, "item-append", PlaylistChanged, self ); var_AddCallback( p_playlist, "item-deleted", PlaylistChanged, self ); - pl_Release( p_intf ); - - vlc_object_lock( p_intf ); + struct manage_cleanup_stack stack = { p_intf, &p_input, p_playlist, self }; + pthread_cleanup_push(manage_cleanup, &stack); - while( vlc_object_alive( p_intf ) ) + while( true ) { + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; vlc_mutex_lock( &p_intf->change_lock ); if( !p_input ) @@ -1267,20 +1440,13 @@ static NSString * VLCToolbarMediaControl = @"VLCToolbarMediaControl"; vlc_mutex_unlock( &p_intf->change_lock ); - vlc_object_timedwait( p_intf, 100000 + mdate()); - } - vlc_object_unlock( p_intf ); - [o_pool release]; - - if( p_input ) vlc_object_release( p_input ); + pthread_testcancel(); /* In 10.5 nanosleep is not a cancellation point */ + msleep( INTF_IDLE_SLEEP ); - var_DelCallback( p_playlist, "playlist-current", PlaylistChanged, self ); - var_DelCallback( p_playlist, "intf-change", PlaylistChanged, self ); - var_DelCallback( p_playlist, "item-change", PlaylistChanged, self ); - var_DelCallback( p_playlist, "item-append", PlaylistChanged, self ); - var_DelCallback( p_playlist, "item-deleted", PlaylistChanged, self ); + [pool release]; + } - pthread_testcancel(); /* If we were cancelled stop here */ + pthread_cleanup_pop(1); msg_Dbg( p_intf, "Killing the Mac OS X module" ); @@ -1288,6 +1454,18 @@ static NSString * VLCToolbarMediaControl = @"VLCToolbarMediaControl"; [NSApp performSelectorOnMainThread: @selector(terminate:) withObject:nil waitUntilDone:NO]; } +- (void)manageVolumeSlider +{ + audio_volume_t i_volume; + aout_VolumeGet( p_intf, &i_volume ); + + if( i_volume != i_lastShownVolume ) + { + i_lastShownVolume = i_volume; + p_intf->p_sys->b_volume_update = TRUE; + } +} + - (void)manageIntf:(NSTimer *)o_timer { vlc_value_t val; @@ -1493,6 +1671,9 @@ end: userInfo: nil repeats: FALSE] retain]; } +#pragma mark - +#pragma mark Interface update + - (void)setupMenus { playlist_t * p_playlist = pl_Yield( p_intf ); @@ -1631,70 +1812,6 @@ end: [self setScrollField: _NS("VLC media player") stopAfter:-1]; } -- (void)updateMessageArray -{ - int i_start, i_stop; - - vlc_mutex_lock( p_intf->p_sys->p_sub->p_lock ); - i_stop = *p_intf->p_sys->p_sub->pi_stop; - vlc_mutex_unlock( p_intf->p_sys->p_sub->p_lock ); - - if( p_intf->p_sys->p_sub->i_start != i_stop ) - { - NSColor *o_white = [NSColor whiteColor]; - NSColor *o_red = [NSColor redColor]; - NSColor *o_yellow = [NSColor yellowColor]; - NSColor *o_gray = [NSColor grayColor]; - - NSColor * pp_color[4] = { o_white, o_red, o_yellow, o_gray }; - static const char * ppsz_type[4] = { ": ", " error: ", - " warning: ", " debug: " }; - - for( i_start = p_intf->p_sys->p_sub->i_start; - i_start != i_stop; - i_start = (i_start+1) % VLC_MSG_QSIZE ) - { - NSString *o_msg; - NSDictionary *o_attr; - NSAttributedString *o_msg_color; - - int i_type = p_intf->p_sys->p_sub->p_msg[i_start].i_type; - - [o_msg_lock lock]; - - if( [o_msg_arr count] + 2 > 400 ) - { - unsigned rid[] = { 0, 1 }; - [o_msg_arr removeObjectsFromIndices: (unsigned *)&rid - numIndices: sizeof(rid)/sizeof(rid[0])]; - } - - o_attr = [NSDictionary dictionaryWithObject: o_gray - forKey: NSForegroundColorAttributeName]; - o_msg = [NSString stringWithFormat: @"%s%s", - p_intf->p_sys->p_sub->p_msg[i_start].psz_module, - ppsz_type[i_type]]; - o_msg_color = [[NSAttributedString alloc] - initWithString: o_msg attributes: o_attr]; - [o_msg_arr addObject: [o_msg_color autorelease]]; - - o_attr = [NSDictionary dictionaryWithObject: pp_color[i_type] - forKey: NSForegroundColorAttributeName]; - o_msg = [NSString stringWithFormat: @"%s\n", - p_intf->p_sys->p_sub->p_msg[i_start].psz_msg]; - o_msg_color = [[NSAttributedString alloc] - initWithString: o_msg attributes: o_attr]; - [o_msg_arr addObject: [o_msg_color autorelease]]; - - [o_msg_lock unlock]; - } - - vlc_mutex_lock( p_intf->p_sys->p_sub->p_lock ); - p_intf->p_sys->p_sub->i_start = i_start; - vlc_mutex_unlock( p_intf->p_sys->p_sub->p_lock ); - } -} - - (void)playStatusUpdated:(int)i_status { if( i_status == PLAYING_S ) @@ -1725,28 +1842,16 @@ end: [o_mi_title setEnabled: b_enabled]; [o_mi_chapter setEnabled: b_enabled]; [o_mi_audiotrack setEnabled: b_enabled]; - [o_mi_visual setEnabled: b_enabled]; - [o_mi_videotrack setEnabled: b_enabled]; - [o_mi_subtitle setEnabled: b_enabled]; - [o_mi_channels setEnabled: b_enabled]; - [o_mi_deinterlace setEnabled: b_enabled]; - [o_mi_ffmpeg_pp setEnabled: b_enabled]; - [o_mi_device setEnabled: b_enabled]; - [o_mi_screen setEnabled: b_enabled]; - [o_mi_aspect_ratio setEnabled: b_enabled]; - [o_mi_crop setEnabled: b_enabled]; -} - -- (void)manageVolumeSlider -{ - audio_volume_t i_volume; - aout_VolumeGet( p_intf, &i_volume ); - - if( i_volume != i_lastShownVolume ) - { - i_lastShownVolume = i_volume; - p_intf->p_sys->b_volume_update = TRUE; - } + [o_mi_visual setEnabled: b_enabled]; + [o_mi_videotrack setEnabled: b_enabled]; + [o_mi_subtitle setEnabled: b_enabled]; + [o_mi_channels setEnabled: b_enabled]; + [o_mi_deinterlace setEnabled: b_enabled]; + [o_mi_ffmpeg_pp setEnabled: b_enabled]; + [o_mi_device setEnabled: b_enabled]; + [o_mi_screen setEnabled: b_enabled]; + [o_mi_aspect_ratio setEnabled: b_enabled]; + [o_mi_crop setEnabled: b_enabled]; } - (IBAction)timesliderUpdate:(id)sender @@ -1790,111 +1895,8 @@ end: pl_Release( p_intf ); } -- (void)applicationWillTerminate:(NSNotification *)notification -{ - playlist_t * p_playlist; - vout_thread_t * p_vout; - int returnedValue = 0; - - msg_Dbg( p_intf, "Terminating" ); - - /* Make sure the manage_thread won't call -terminate: again */ - pthread_cancel( manage_thread ); - - /* Make sure the intf object is getting killed */ - vlc_object_kill( p_intf ); - - /* Make sure our manage_thread ends */ - pthread_join( manage_thread, NULL ); - - /* Make sure the interfaceTimer is destroyed */ - [interfaceTimer invalidate]; - [interfaceTimer release]; - interfaceTimer = nil; - - /* make sure that the current volume is saved */ - config_PutInt( p_intf->p_libvlc, "volume", i_lastShownVolume ); - returnedValue = config_SaveConfigFile( p_intf->p_libvlc, "main" ); - if( returnedValue != 0 ) - msg_Err( p_intf, - "error while saving volume in osx's terminate method (%i)", - returnedValue ); - - /* save the prefs if they were changed in the extended panel */ - if(o_extended && [o_extended getConfigChanged]) - { - [o_extended savePrefs]; - } - - p_intf->b_interaction = false; - var_DelCallback( p_intf, "interaction", InteractCallback, self ); - - /* remove global observer watching for vout device changes correctly */ - [[NSNotificationCenter defaultCenter] removeObserver: self]; - - /* release some other objects here, because it isn't sure whether dealloc - * will be called later on */ - - if( nib_about_loaded ) - [o_about release]; - - if( nib_prefs_loaded ) - { - [o_sprefs release]; - [o_prefs release]; - } - - if( nib_open_loaded ) - [o_open release]; - - if( nib_extended_loaded ) - { - [o_extended release]; - } - - if( nib_bookmarks_loaded ) - [o_bookmarks release]; - - if( o_info ) - { - [o_info stopTimers]; - [o_info release]; - } - - if( nib_wizard_loaded ) - [o_wizard release]; - - [o_embedded_list release]; - [o_interaction_list release]; - [o_eyetv release]; - - [o_img_pause_pressed release]; - [o_img_play_pressed release]; - [o_img_pause release]; - [o_img_play release]; - - [o_msg_arr removeAllObjects]; - [o_msg_arr release]; - - [o_msg_lock release]; - - /* write cached user defaults to disk */ - [[NSUserDefaults standardUserDefaults] synchronize]; - - /* Kill the playlist, so that it doesn't accept new request - * such as the play request from vlc.c (we are a blocking interface). */ - p_playlist = pl_Yield( p_intf ); - vlc_object_kill( p_playlist ); - pl_Release( p_intf ); - - vlc_object_kill( p_intf->p_libvlc ); - - /* Go back to Run() and make libvlc exit properly */ - if( jmpbuffer ) - longjmp( jmpbuffer, 1 ); - /* not reached */ -} - +#pragma mark - +#pragma mark Recent Items - (IBAction)clearRecentItems:(id)sender { @@ -1907,6 +1909,9 @@ end: [self application: nil openFile: [sender title]]; } +#pragma mark - +#pragma mark Panels + - (IBAction)intfOpenFile:(id)sender { if( !nib_open_loaded ) @@ -2007,22 +2012,6 @@ end: [o_bookmarks showBookmarks]; } -- (IBAction)viewAbout:(id)sender -{ - if( !nib_about_loaded ) - nib_about_loaded = [NSBundle loadNibNamed:@"About" owner:self]; - - [o_about showAbout]; -} - -- (IBAction)showLicense:(id)sender -{ - if( !nib_about_loaded ) - nib_about_loaded = [NSBundle loadNibNamed:@"About" owner:self]; - - [o_about showGPL: sender]; -} - - (IBAction)viewPreferences:(id)sender { if( !nib_prefs_loaded ) @@ -2035,6 +2024,9 @@ end: [o_sprefs showSimplePrefs]; } +#pragma mark - +#pragma mark Update + - (IBAction)checkForUpdate:(id)sender { #ifdef UPDATE_CHECK @@ -2047,6 +2039,25 @@ end: #endif } +#pragma mark - +#pragma mark Help and Docs + +- (IBAction)viewAbout:(id)sender +{ + if( !nib_about_loaded ) + nib_about_loaded = [NSBundle loadNibNamed:@"About" owner:self]; + + [o_about showAbout]; +} + +- (IBAction)showLicense:(id)sender +{ + if( !nib_about_loaded ) + nib_about_loaded = [NSBundle loadNibNamed:@"About" owner:self]; + + [o_about showGPL: sender]; +} + - (IBAction)viewHelp:(id)sender { if( !nib_about_loaded ) @@ -2096,37 +2107,54 @@ end: [[NSWorkspace sharedWorkspace] openURL: o_url]; } +#pragma mark - #pragma mark Crash Log -- (void)mailCrashLog:(NSString *)crashLog withUserComment:(NSString *)userComment -{ - static char mail[] = - "From: vlcuser \n" - "To: VideoLAN Crash Report \n" - "Subject: %@\n" - "Content-Type: text/plain; charset=ISO-8859-1; format=flowed\n" - "Content-Transfer-Encoding: 7bit\n" - "\n" - "%@\n\n" - "User Comment:\n%@\n--------------\n" - "\n" - "Crash log:\n%@\n--------------\n" - "\n" - "\n"; - NSString * mailPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"vlc_crash_mail.eml"]; - NSString * mailContent = [NSString stringWithFormat:[NSString stringWithUTF8String:mail], - _NS("Crash Report (Type Command-shift-D and hit send)"), - _NS("Type Command-shift-D (or in Menu \"Message\">\"Send Again\") and hit the \"Send Mail\" button."), - userComment, crashLog]; - BOOL ret = [mailContent writeToFile:mailPath atomically:YES encoding:NSUTF8StringEncoding error:nil]; - if( !ret ) - { - NSRunAlertPanel(_NS("Error when generating crash report mail."), _NS("Can't prepare crash log mail"), _NS("OK"), nil, nil, nil ); - return; +- (void)sendCrashLog:(NSString *)crashLog withUserComment:(NSString *)userComment +{ + NSString *urlStr = @"http://jones.videolan.org/crashlog/sendcrashreport.php"; + NSURL *url = [NSURL URLWithString:urlStr]; + + NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url]; + [req setHTTPMethod:@"POST"]; + + NSString * email; + if( [o_crashrep_includeEmail_ckb state] == NSOnState ) + { + ABPerson * contact = [[ABAddressBook sharedAddressBook] me]; + ABMultiValue *emails = [contact valueForProperty:kABEmailProperty]; + email = [emails valueAtIndex:[emails indexForIdentifier: + [emails primaryIdentifier]]]; } + else + email = [NSString string]; + + NSString *postBody; + postBody = [NSString stringWithFormat:@"CrashLog=%@&Comment=%@&Email=%@\r\n", + [crashLog stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding], + [userComment stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding], + [email stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + + [req setHTTPBody:[postBody dataUsingEncoding:NSUTF8StringEncoding]]; + + /* Released from delegate */ + crashLogURLConnection = [[NSURLConnection alloc] initWithRequest:req delegate:self]; +} - [[NSWorkspace sharedWorkspace] openFile:mailPath]; +- (void)connectionDidFinishLoading:(NSURLConnection *)connection +{ + NSRunInformationalAlertPanel(_NS("Crash Report successfully sent"), + _NS("Thanks for your report!"), + _NS("OK"), nil, nil, nil); + [crashLogURLConnection release]; + crashLogURLConnection = nil; } +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error +{ + NSRunCriticalAlertPanel(_NS("Error when sending the Crash Report"), [error localizedDescription], @"OK", nil, nil); + [crashLogURLConnection release]; + crashLogURLConnection = nil; +} - (NSString *)latestCrashLogPathPreviouslySeen:(BOOL)previouslySeen { @@ -2134,10 +2162,10 @@ end: NSDirectoryEnumerator *direnum = [[NSFileManager defaultManager] enumeratorAtPath:crashReporter]; NSString *fname; NSString * latestLog = nil; - NSInteger year = !previouslySeen ? [[NSUserDefaults standardUserDefaults] integerForKey:@"LatestCrashReportYear"] : 0; - NSInteger month = !previouslySeen ? [[NSUserDefaults standardUserDefaults] integerForKey:@"LatestCrashReportMonth"]: 0; - NSInteger day = !previouslySeen ? [[NSUserDefaults standardUserDefaults] integerForKey:@"LatestCrashReportDay"] : 0; - NSInteger hours = !previouslySeen ? [[NSUserDefaults standardUserDefaults] integerForKey:@"LatestCrashReportHours"]: 0; + int year = !previouslySeen ? [[NSUserDefaults standardUserDefaults] integerForKey:@"LatestCrashReportYear"] : 0; + int month = !previouslySeen ? [[NSUserDefaults standardUserDefaults] integerForKey:@"LatestCrashReportMonth"]: 0; + int day = !previouslySeen ? [[NSUserDefaults standardUserDefaults] integerForKey:@"LatestCrashReportDay"] : 0; + int hours = !previouslySeen ? [[NSUserDefaults standardUserDefaults] integerForKey:@"LatestCrashReportHours"]: 0; while (fname = [direnum nextObject]) { @@ -2187,26 +2215,22 @@ end: - (void)lookForCrashLog { - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - + NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init]; // This pref key doesn't exists? this VLC is an upgrade, and this crash log come from previous version BOOL areCrashLogsTooOld = ![[NSUserDefaults standardUserDefaults] integerForKey:@"LatestCrashReportYear"]; NSString * latestLog = [self latestCrashLogPathPreviouslySeen:NO]; if( latestLog && !areCrashLogsTooOld ) - [self performSelectorOnMainThread:@selector(notifyCrashLogToUser:) withObject:latestLog waitUntilDone:NO]; - - [pool release]; + [NSApp runModalForWindow: o_crashrep_win]; + [o_pool release]; } -- (void)notifyCrashLogToUser:(NSString *)crashLogPath +- (IBAction)crashReporterAction:(id)sender { - int ret = NSRunInformationalAlertPanel(_NS("VLC crashed previously"), - _NS("VLC crashed previously. Do you want to send an email with details on the crash to VLC's development team?"), - _NS("Send"), _NS("Don't Send"), nil, nil); - if( ret == NSAlertDefaultReturn ) - { - [self mailCrashLog:[NSString stringWithContentsOfFile:crashLogPath] withUserComment:_NS("")]; - } + if( sender == o_crashrep_send_btn ) + [self sendCrashLog:[NSString stringWithContentsOfFile: [self latestCrashLogPath]] withUserComment: [o_crashrep_fld string]]; + + [NSApp stopModal]; + [o_crashrep_win orderOut: sender]; } - (IBAction)openCrashLog:(id)sender @@ -2223,6 +2247,62 @@ end: } #pragma mark - +#pragma mark Remove old prefs + +- (void)_removeOldPreferences +{ + static NSString * kVLCPreferencesVersion = @"VLCPreferencesVersion"; + static const int kCurrentPreferencesVersion = 1; + 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"]] ) + { + [[NSUserDefaults standardUserDefaults] setInteger:kCurrentPreferencesVersion forKey:kVLCPreferencesVersion]; + return; + } + + 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; + } + + NSArray * ourPreferences = [NSArray arrayWithObjects:@"org.videolan.vlc.plist", @"VLC"]; + + /* Move the file to trash so that user can find them later */ + [[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation source:preferences destination:nil files:ourPreferences tag:0]; + + /* 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]; + + /* 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); +} + +#pragma mark - +#pragma mark Errors, warnings and messages - (IBAction)viewErrorsAndWarnings:(id)sender { @@ -2264,6 +2344,70 @@ end: } } +- (void)updateMessageArray +{ + int i_start, i_stop; + + vlc_mutex_lock( p_intf->p_sys->p_sub->p_lock ); + i_stop = *p_intf->p_sys->p_sub->pi_stop; + vlc_mutex_unlock( p_intf->p_sys->p_sub->p_lock ); + + if( p_intf->p_sys->p_sub->i_start != i_stop ) + { + NSColor *o_white = [NSColor whiteColor]; + NSColor *o_red = [NSColor redColor]; + NSColor *o_yellow = [NSColor yellowColor]; + NSColor *o_gray = [NSColor grayColor]; + + NSColor * pp_color[4] = { o_white, o_red, o_yellow, o_gray }; + static const char * ppsz_type[4] = { ": ", " error: ", + " warning: ", " debug: " }; + + for( i_start = p_intf->p_sys->p_sub->i_start; + i_start != i_stop; + i_start = (i_start+1) % VLC_MSG_QSIZE ) + { + NSString *o_msg; + NSDictionary *o_attr; + NSAttributedString *o_msg_color; + + int i_type = p_intf->p_sys->p_sub->p_msg[i_start].i_type; + + [o_msg_lock lock]; + + if( [o_msg_arr count] + 2 > 400 ) + { + unsigned rid[] = { 0, 1 }; + [o_msg_arr removeObjectsFromIndices: (unsigned *)&rid + numIndices: sizeof(rid)/sizeof(rid[0])]; + } + + o_attr = [NSDictionary dictionaryWithObject: o_gray + forKey: NSForegroundColorAttributeName]; + o_msg = [NSString stringWithFormat: @"%s%s", + p_intf->p_sys->p_sub->p_msg[i_start].psz_module, + ppsz_type[i_type]]; + o_msg_color = [[NSAttributedString alloc] + initWithString: o_msg attributes: o_attr]; + [o_msg_arr addObject: [o_msg_color autorelease]]; + + o_attr = [NSDictionary dictionaryWithObject: pp_color[i_type] + forKey: NSForegroundColorAttributeName]; + o_msg = [[NSString stringWithUTF8String: p_intf->p_sys->p_sub->p_msg[i_start].psz_msg] stringByAppendingString: @"\n"]; + o_msg_color = [[NSAttributedString alloc] + initWithString: o_msg attributes: o_attr]; + [o_msg_arr addObject: [o_msg_color autorelease]]; + + [o_msg_lock unlock]; + } + + vlc_mutex_lock( p_intf->p_sys->p_sub->p_lock ); + p_intf->p_sys->p_sub->i_start = i_start; + vlc_mutex_unlock( p_intf->p_sys->p_sub->p_lock ); + } +} + +#pragma mark - #pragma mark Playlist toggling - (IBAction)togglePlaylist:(id)sender