#include <sys/param.h> /* for MAXPATHLEN */
#include <string.h>
#include <vlc_keys.h>
+#include <unistd.h> /* execl() */
#ifdef HAVE_CONFIG_H
# include "config.h"
#import <vlc_input.h>
#import <vlc_interface.h>
+#import <AddressBook/AddressBook.h>
/*****************************************************************************
* 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
{
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];
/* 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];
[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
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 },
- { NSHomeFunctionKey, KEY_HOME },
- { NSEndFunctionKey, KEY_END },
- { NSPageUpFunctionKey, KEY_PAGEUP },
- { NSPageDownFunctionKey, KEY_PAGEDOWN },
- { 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
[o_msgs_panel setExcludedFromWindowsMenu: YES];
[o_msgs_panel setDelegate: self];
+ /* In code and not in Nib for 10.4 compat */
+ NSToolbar * toolbar = [[[NSToolbar alloc] initWithIdentifier:@"mainControllerToolbar"] autorelease];
+ [toolbar setDelegate:self];
+ [toolbar setShowsBaselineSeparator:NO];
+ [toolbar setAllowsUserCustomization:NO];
+ [toolbar setDisplayMode:NSToolbarDisplayModeIconOnly];
+ [toolbar setAutosavesConfiguration:YES];
+ [o_window setToolbar:toolbar];
+
i_key = config_GetInt( p_intf, "key-quit" );
[o_mi_quit setKeyEquivalent: [NSString stringWithFormat:@"%C", VLCKeyToCocoa( i_key )]];
[o_mi_quit setKeyEquivalentModifierMask: VLCModifiersToCocoa(i_key)];
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
{
- [o_window setTitle: _NS("VLC")];
+ [o_window setTitle: _NS("VLC media player")];
[self setScrollField:_NS("VLC media player") stopAfter:-1];
/* button controls */
[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")];
[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
+#pragma mark -
+#pragma mark Termination
+
+- (void)applicationWillTerminate:(NSNotification *)notification
{
- o_msg_lock = [[NSLock alloc] init];
- o_msg_arr = [[NSMutableArray arrayWithCapacity: 200] retain];
+ playlist_t * p_playlist;
+ vout_thread_t * p_vout;
+ int returnedValue = 0;
+
+ msg_Dbg( p_intf, "Terminating" );
- /* FIXME: don't poll */
- interfaceTimer = [[NSTimer scheduledTimerWithTimeInterval: 0.5
- target: self selector: @selector(manageIntf:)
- userInfo: nil repeats: FALSE] retain];
+ /* Make sure the manage_thread won't call -terminate: again */
+ pthread_cancel( manage_thread );
- /* Note: we use the pthread API to support pre-10.5 */
- pthread_create( &manage_thread, NULL, ManageThread, self );
+ /* Make sure the intf object is getting killed */
+ vlc_object_kill( p_intf );
- [o_controls setupVarMenuItem: o_mi_add_intf target: (vlc_object_t *)p_intf
- var: "intf-add" selector: @selector(toggleVar:)];
+ /* Make sure our manage_thread ends */
+ pthread_join( manage_thread, NULL );
- /* check whether the user runs a valid version of OSX; alert is auto-released */
- if( MACOS_VERSION < 10.4f )
+ /* 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
}
}
+#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
}
}
+#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
}
+#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,
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 )
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 );
var_AddCallback( p_playlist, "item-append", PlaylistChanged, self );
var_AddCallback( p_playlist, "item-deleted", PlaylistChanged, self );
- pl_Release( p_intf );
+ struct manage_cleanup_stack stack = { p_intf, &p_input, p_playlist, self };
+ pthread_cleanup_push(manage_cleanup, &stack);
- vlc_object_lock( p_intf );
- while( vlc_object_alive( p_intf ) )
+ while( true )
{
+ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
vlc_mutex_lock( &p_intf->change_lock );
if( !p_input )
vlc_object_release( p_input );
p_input = NULL;
}
+ else if( cachedInputState != input_GetState( p_input ) )
+ {
+ p_intf->p_sys->b_intf_update = true;
+ }
/* Manage volume status */
[self manageVolumeSlider];
vlc_mutex_unlock( &p_intf->change_lock );
- vlc_object_timedwait( p_intf, 100000 + mdate());
- }
- vlc_object_unlock( p_intf );
- [o_pool release];
+ pthread_testcancel(); /* In 10.5 nanosleep is not a cancellation point */
+ msleep( INTF_IDLE_SLEEP );
- if( p_input ) vlc_object_release( p_input );
-
- 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" );
[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;
if( ( b_input = ( p_input != NULL ) ) )
{
/* seekable streams */
- int state = input_GetState( p_input );
- if ( state == INIT_S ||
- state == OPENING_S ||
- state == BUFFERING_S )
+ cachedInputState = input_GetState( p_input );
+ if ( cachedInputState == INIT_S ||
+ cachedInputState == OPENING_S ||
+ cachedInputState == BUFFERING_S )
{
b_buffering = YES;
}
userInfo: nil repeats: FALSE] retain];
}
+#pragma mark -
+#pragma mark Interface update
+
- (void)setupMenus
{
playlist_t * p_playlist = pl_Yield( p_intf );
[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 )
[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
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
{
[self application: nil openFile: [sender title]];
}
+#pragma mark -
+#pragma mark Panels
+
- (IBAction)intfOpenFile:(id)sender
{
if( !nib_open_loaded )
[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 )
[o_sprefs showSimplePrefs];
}
+#pragma mark -
+#pragma mark Update
+
- (IBAction)checkForUpdate:(id)sender
{
#ifdef UPDATE_CHECK
#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 )
[[NSWorkspace sharedWorkspace] openURL: o_url];
}
+#pragma mark -
#pragma mark Crash Log
-- (void)mailCrashLog:(NSString *)crashLog withUserComment:(NSString *)userComment
-{
- static char mail[] =
- "From: vlcuser <vlcuser@videolan.org>\n"
- "To: VideoLAN Crash Report <apple-bugreport@videolan.org>\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
{
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])
{
- (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 has previously crashed"),
- _NS("VLC has previously crashed, do you want to send an email with the crash to VLC's team?"),
- _NS("Send"), _NS("Don't Send"), nil, nil);
- if( ret == NSAlertDefaultReturn )
- {
- [self mailCrashLog:[NSString stringWithContentsOfFile:crashLogPath] withUserComment:_NS("<Explain here what you were doing when VLC crashed, with possibly a link to the failing video>")];
- }
+ 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
}
#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
{
}
}
+- (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
- (void)windowDidResize:(NSNotification *)notif
{
- if( [o_window frame].size.height > 200 && b_small_window )
+ if( [o_window contentRectForFrameRect:[o_window frame]].size.height > 169. && b_small_window )
{
/* If large and coming from small then show */
[o_playlist_view setAutoresizesSubviews: YES];