From dfa1f8dd4bbaed3fba144a5afead99a1ea102c44 Mon Sep 17 00:00:00 2001 From: ritsuka Date: Thu, 22 Jan 2015 10:30:26 +0000 Subject: [PATCH] MacGui: move the application delegate to its own class. Removed the "Open Source (Title Specific)" menu item, now integrated in the standard open panel. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@6784 b64f7644-9d1e-0410-96f1-a4d463321fa5 --- macosx/Controller.h | 64 +- macosx/Controller.m | 1448 +++++++------------- macosx/English.lproj/MainMenu.xib | 830 +---------- macosx/English.lproj/MainWindow.xib | 724 ++++++++++ macosx/English.lproj/Preferences.xib | 11 +- macosx/HBAppDelegate.h | 14 + macosx/HBAppDelegate.m | 482 +++++++ macosx/HBQueueController.h | 4 + macosx/HBQueueController.mm | 44 +- macosx/HandBrake.xcodeproj/project.pbxproj | 18 + macosx/main.mm | 21 - 11 files changed, 1817 insertions(+), 1843 deletions(-) create mode 100644 macosx/English.lproj/MainWindow.xib create mode 100644 macosx/HBAppDelegate.h create mode 100644 macosx/HBAppDelegate.m diff --git a/macosx/Controller.h b/macosx/Controller.h index 49074f322..83a47e434 100644 --- a/macosx/Controller.h +++ b/macosx/Controller.h @@ -18,15 +18,13 @@ @class HBPreviewController; @class HBPreferencesController; -@class HBOutputPanelController; @class HBPresetsViewController; @class HBPresetsManager; @class HBJob; -@interface HBController : NSObject +@interface HBController : NSWindowController { - IBOutlet NSWindow *fWindow; IBOutlet NSTabView *fMainTabView; // Video view controller @@ -49,17 +47,6 @@ HBAdvancedController * fAdvancedOptions; IBOutlet NSTabViewItem * fAdvancedTab; - // Main Menu Outlets - NSMenuItem * fOpenSourceTitleMMenu; - - // Source Title Scan Outlets - IBOutlet NSPanel * fScanSrcTitlePanel; - IBOutlet NSTextField * fScanSrcTitlePathField; - IBOutlet NSTextField * fSrcDsplyNameTitleScan; - IBOutlet NSTextField * fScanSrcTitleNumField; - IBOutlet NSButton * fScanSrcTitleCancelButton; - IBOutlet NSButton * fScanSrcTitleOpenButton; - // Picture Settings HBPictureController * fPictureController; // Picture Preview @@ -68,9 +55,6 @@ // Queue panel HBQueueController * fQueueController; - - // Output panel - HBOutputPanelController * outputPanel; // Source box IBOutlet NSProgressIndicator * fScanIndicator; @@ -94,33 +78,23 @@ IBOutlet NSTextField * fQueueStatus; IBOutlet NSProgressIndicator * fRipIndicator; BOOL fRipIndicatorShown; - + // User Preset HBPresetsManager * presetManager; HBPresetsViewController * fPresetsView; - IBOutlet NSMenu * presetsMenu; IBOutlet NSDrawer * fPresetDrawer; } -@property (nonatomic, readonly) NSWindow *window; +- (instancetype)initWithQueue:(HBQueueController *)queueController presetsManager:(HBPresetsManager *)manager; -- (IBAction) browseSources: (id) sender; -- (IBAction) showSourceTitleScanPanel: (id) sender; -- (IBAction) closeSourceTitleScanPanel: (id) sender; -- (void) performScan:(NSURL *)scanURL scanTitleNum:(NSInteger)scanTitleNum; +- (void)launchAction; +- (void)openFile:(NSURL *)fileURL; -- (IBAction) titlePopUpChanged: (id) sender; -- (IBAction) chapterPopUpChanged: (id) sender; +- (IBAction)browseSources:(id)sender; -- (IBAction) autoSetM4vExtension: (id) sender; - -- (IBAction) browseFile: (id) sender; - -- (IBAction) showPicturePanel: (id) sender; -- (IBAction) showPreviewWindow: (id) sender; -- (void)pictureSettingsDidChange; -- (IBAction) openMainWindow: (id) sender; +- (IBAction)showPicturePanel:(id)sender; +- (IBAction)showPreviewWindow:(id)sender; // Queue - (IBAction)addToQueue:(id)sender; @@ -130,26 +104,18 @@ - (void)setQueueState:(NSString *)info; - (void)setQueueInfo:(NSString *)info progress:(double)progress hidden:(BOOL)hidden; -- (IBAction)showQueueWindow:(id)sender; - -- (IBAction)showPreferencesWindow:(id)sender; - - (IBAction)rip:(id)sender; - (IBAction)pause:(id)sender; -- (IBAction) openHomepage: (id) sender; -- (IBAction) openForums: (id) sender; -- (IBAction) openUserGuide: (id) sender; +// Preset Methods +// Export / Import Presets +- (IBAction)browseExportPresetFile:(id)sender; +- (IBAction)browseImportPresetFile:(id)sender; -// Preset Methods Here -/* Export / Import Presets */ -- (IBAction) browseExportPresetFile: (id) sender; -- (IBAction) browseImportPresetFile: (id) sender; +- (IBAction)selectPresetFromMenu:(id)sender; -/* Manage User presets */ -- (IBAction) showAddPresetPanel: (id) sender; +// Manage User presets +- (IBAction)showAddPresetPanel:(id)sender; - (IBAction)selectDefaultPreset:(id)sender; -- (IBAction)addFactoryPresets:(id)sender; -- (IBAction)showDebugOutputPanel:(id)sender; @end diff --git a/macosx/Controller.m b/macosx/Controller.m index 0f729eb57..bed4b5280 100644 --- a/macosx/Controller.m +++ b/macosx/Controller.m @@ -9,7 +9,6 @@ #import "HBQueueController.h" #import "HBOutputPanelController.h" -#import "HBPreferencesController.h" #import "HBPresetsManager.h" #import "HBPreset.h" #import "HBUtilities.h" @@ -31,6 +30,14 @@ @interface HBController () +@property (assign) IBOutlet NSView *openTitleView; +@property (nonatomic, readwrite) BOOL scanSpecificTitle; +@property (nonatomic, readwrite) NSInteger scanSpecificTitleIdx; + +/** + * The name of the source, it might differ from the source + * last path component if it's a package or a folder. + */ @property (nonatomic, copy) NSString *browsedSourceDisplayName; /// The current job. @@ -52,45 +59,28 @@ @implementation HBController -- (instancetype)init +- (instancetype)initWithQueue:(HBQueueController *)queueController presetsManager:(HBPresetsManager *)manager; { - self = [super init]; + self = [super initWithWindowNibName:@"MainWindow"]; if (self) { - // Register the defaults preferences - [HBPreferencesController registerUserDefaults]; - - // Inits the controllers - outputPanel = [[HBOutputPanelController alloc] init]; - fPictureController = [[HBPictureController alloc] init]; - fPreviewController = [[HBPreviewController alloc] initWithDelegate:self]; - fQueueController = [[HBQueueController alloc] init]; - fQueueController.controller = self; - fQueueController.outputPanel = outputPanel; - - // we init the HBPresetsManager - NSURL *presetsURL = [NSURL fileURLWithPath:[[HBUtilities appSupportPath] stringByAppendingPathComponent:@"UserPresets.plist"]]; - presetManager = [[HBPresetsManager alloc] initWithURL:presetsURL]; - _selectedPreset = [presetManager.defaultPreset retain]; - - // Lets report the HandBrake version number here to the activity log and text log file - NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary]; - NSString *versionStringFull = [NSString stringWithFormat:@"Handbrake Version: %@ (%@)", infoDict[@"CFBundleShortVersionString"], infoDict[@"CFBundleVersion"]]; - [HBUtilities writeToActivityLog: "%s", versionStringFull.UTF8String]; - - // Optionally use dvd nav - [HBCore setDVDNav:[[[NSUserDefaults standardUserDefaults] objectForKey:@"UseDvdNav"] boolValue]]; - // Init libhb int loggingLevel = [[[NSUserDefaults standardUserDefaults] objectForKey:@"LoggingLevel"] intValue]; _core = [[HBCore alloc] initWithLoggingLevel:loggingLevel]; _core.name = @"ScanCore"; + // Inits the controllers + fPictureController = [[HBPictureController alloc] init]; [fPictureController setDelegate:self]; + + fPreviewController = [[HBPreviewController alloc] initWithDelegate:self]; [fPreviewController setCore:self.core]; - // Set the Growl Delegate - [GrowlApplicationBridge setGrowlDelegate:fQueueController]; + fQueueController = queueController; + fQueueController.controller = self; + + presetManager = manager; + _selectedPreset = [presetManager.defaultPreset retain]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(autoSetM4vExtension:) name:HBMixdownChangedNotification object:nil]; } @@ -98,221 +88,106 @@ return self; } -- (void) applicationDidFinishLaunching: (NSNotification *) notification +- (void)dealloc +{ + [[NSNotificationCenter defaultCenter] removeObserver:self]; + + [fPreviewController release]; + [fPictureController release]; + + [_browsedSourceDisplayName release]; + [_job release]; + [_jobFromQueue release]; + [_selectedPreset release]; + [_labelColor release]; + [_core release]; + + [super dealloc]; +} + +- (void)windowDidLoad { [self enableUI:NO]; - // Checks for presets updates - [self checkBuiltInsForUpdates]; + /* For 64 bit builds, the threaded animation in the progress + * indicators conflicts with the animation in the advanced tab + * for reasons not completely clear. jbrjake found a note in the + * 10.5 dev notes regarding this possiblility. It was also noted + * that unless specified, setUsesThreadedAnimation defaults to true. + * So, at least for now we set the indicator animation to NO for + * both the scan and regular progress indicators for both 32 and 64 bit + * as it test out fine on both and there is no reason our progress indicators + * should require their own thread. + */ + [fScanIndicator setUsesThreadedAnimation:NO]; + [fRipIndicator setUsesThreadedAnimation:NO]; - // Show/Hide the Presets drawer upon launch based - // on user preference DefaultPresetsDrawerShow - if ([[NSUserDefaults standardUserDefaults] boolForKey:@"HBDefaultPresetsDrawerShow"]) + NSSize drawerSize = NSSizeFromString([[NSUserDefaults standardUserDefaults] + stringForKey:@"HBDrawerSize"]); + if (drawerSize.width) { - [fPresetDrawer open:self]; + [fPresetDrawer setContentSize: drawerSize]; } - // Get the number of HandBrake instances currently running - NSUInteger hbInstanceNum = [NSRunningApplication runningApplicationsWithBundleIdentifier:[[NSBundle mainBundle] bundleIdentifier]].count; + // Align the start / stop widgets with the chapter popups + NSPoint startPoint = [fSrcChapterStartPopUp frame].origin; + startPoint.y += 2; - // If we are a single instance it is safe to clean up the previews if there are any - // left over. This is a bit of a kludge but will prevent a build up of old instance - // live preview cruft. No danger of removing an active preview directory since they - // are created later in HBPreviewController if they don't exist at the moment a live - // preview encode is initiated. - if (hbInstanceNum == 1) - { - NSString *previewDirectory = [[HBUtilities appSupportPath] stringByAppendingPathComponent:@"Previews"]; - NSError *error = nil; - NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:previewDirectory error:&error]; - for (NSString *file in files) - { - BOOL result = [[NSFileManager defaultManager] removeItemAtPath:[previewDirectory stringByAppendingPathComponent:file] error:&error]; - if (result == NO && error) - { - [HBUtilities writeToActivityLog: "Could not remove existing preview at : %s", file.UTF8String]; - } - } - } + NSPoint endPoint = [fSrcChapterEndPopUp frame].origin; + endPoint.y += 2; - // Open debug output window now if it was visible when HB was closed - if ([[NSUserDefaults standardUserDefaults] boolForKey:@"OutputPanelIsOpen"]) - [self showDebugOutputPanel:nil]; + [fSrcTimeStartEncodingField setFrameOrigin:startPoint]; + [fSrcTimeEndEncodingField setFrameOrigin:endPoint]; - // Open queue window now if it was visible when HB was closed - if ([[NSUserDefaults standardUserDefaults] boolForKey:@"QueueWindowIsOpen"]) - [self showQueueWindow:nil]; + [fSrcFrameStartEncodingField setFrameOrigin:startPoint]; + [fSrcFrameEndEncodingField setFrameOrigin:endPoint]; - [self openMainWindow:nil]; + // Bottom + [fStatusField setStringValue:@""]; - // Now we re-check the queue array to see if there are - // any remaining encodes to be done in it and ask the - // user if they want to reload the queue */ - if (fQueueController.count) - { - // On Screen Notification - // We check to see if there is already another instance of hb running. - // Note: hbInstances == 1 means we are the only instance of HandBrake.app - NSAlert *alert = nil; - if (hbInstanceNum > 1) - { - alert = [[NSAlert alloc] init]; - [alert setMessageText:NSLocalizedString(@"There is already an instance of HandBrake running.", @"")]; - [alert setInformativeText:NSLocalizedString(@"HandBrake will now load up the existing queue.", nil)]; - [alert addButtonWithTitle:NSLocalizedString(@"Reload Queue", nil)]; - } - else - { - if (fQueueController.workingItemsCount > 0 || fQueueController.pendingItemsCount > 0) - { - NSString *alertTitle; + // Register HBController's Window as a receiver for files/folders drag & drop operations + [self.window registerForDraggedTypes:@[NSFilenamesPboardType]]; - if (fQueueController.workingItemsCount > 0) - { - alertTitle = [NSString stringWithFormat: - NSLocalizedString(@"HandBrake Has Detected %d Previously Encoding Item(s) and %d Pending Item(s) In Your Queue.", @""), - fQueueController.workingItemsCount, fQueueController.pendingItemsCount]; - } - else - { - alertTitle = [NSString stringWithFormat: - NSLocalizedString(@"HandBrake Has Detected %d Pending Item(s) In Your Queue.", @""), - fQueueController.pendingItemsCount]; - } + // Set up the preset drawer + fPresetsView = [[HBPresetsViewController alloc] initWithPresetManager:presetManager]; + [fPresetDrawer setContentView:[fPresetsView view]]; + fPresetsView.delegate = self; + [[fPresetDrawer contentView] setAutoresizingMask:( NSViewWidthSizable | NSViewHeightSizable )]; - alert = [[NSAlert alloc] init]; - [alert setMessageText:alertTitle]; - [alert setInformativeText:NSLocalizedString(@"Do you want to reload them ?", nil)]; - [alert addButtonWithTitle:NSLocalizedString(@"Reload Queue", nil)]; - [alert addButtonWithTitle:NSLocalizedString(@"Empty Queue", nil)]; - [alert setAlertStyle:NSCriticalAlertStyle]; - } - else - { - // Since we addressed any pending or previously encoding items above, we go ahead and make sure - // the queue is empty of any finished items or cancelled items. - [fQueueController removeAllJobs]; + // Set up the chapters title view + fChapterTitlesController = [[HBChapterTitlesController alloc] init]; + [fChaptersTitlesTab setView:[fChapterTitlesController view]]; - if (self.core.state != HBStateScanning && !self.job) - { - // We show whichever open source window specified in LaunchSourceBehavior preference key - if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"LaunchSourceBehavior"] isEqualToString: @"Open Source"]) - { - [self browseSources:nil]; - } + // setup the subtitles view + fSubtitlesViewController = [[HBSubtitlesController alloc] init]; + [fSubtitlesTab setView:[fSubtitlesViewController view]]; - if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"LaunchSourceBehavior"] isEqualToString: @"Open Source (Title Specific)"]) - { - [self browseSources:(id)fOpenSourceTitleMMenu]; - } - } - } - } + // setup the audio controller + fAudioController = [[HBAudioController alloc] init]; + [fAudioTab setView:[fAudioController view]]; - if (alert) - { - NSModalResponse response = [alert runModal]; + // setup the advanced view controller + fAdvancedOptions = [[HBAdvancedController alloc] init]; + [fAdvancedTab setView:[fAdvancedOptions view]]; - if (response == NSAlertSecondButtonReturn) - { - [HBUtilities writeToActivityLog: "didDimissReloadQueue NSAlertSecondButtonReturn Chosen"]; - [fQueueController removeAllJobs]; + // setup the video view controller + fVideoController = [[HBVideoController alloc] initWithAdvancedController:fAdvancedOptions]; + [fVideoTab setView:[fVideoController view]]; - // We show whichever open source window specified in LaunchSourceBehavior preference key - if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"LaunchSourceBehavior"] isEqualToString: @"Open Source"]) - { - [self browseSources:nil]; - } - - if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"LaunchSourceBehavior"] isEqualToString: @"Open Source (Title Specific)"]) - { - [self browseSources:(id)fOpenSourceTitleMMenu]; - } - } - else - { - [HBUtilities writeToActivityLog: "didDimissReloadQueue NSAlertFirstButtonReturn Chosen"]; - if (hbInstanceNum == 1) - { - [fQueueController setEncodingJobsAsPending]; - } - - [self showQueueWindow:nil]; - } - - [alert release]; - } - } - else - { - if (self.core.state != HBStateScanning && !self.job) - { - // We show whichever open source window specified in LaunchSourceBehavior preference key - if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"LaunchSourceBehavior"] isEqualToString: @"Open Source"]) - { - [self browseSources:nil]; - } - - if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"LaunchSourceBehavior"] isEqualToString: @"Open Source (Title Specific)"]) - { - [self browseSources:(id)fOpenSourceTitleMMenu]; - } - } - } -} - -- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames -{ - [self openFile:[NSURL fileURLWithPath:filenames.firstObject]]; - [NSApp replyToOpenOrPrint:NSApplicationDelegateReplySuccess]; -} - -- (void)openFile:(NSURL *)fileURL -{ - if (self.core.state != HBStateScanning) - { - self.browsedSourceDisplayName = fileURL.lastPathComponent; - [self performScan:fileURL scanTitleNum:0]; - } -} - -- (void)setJob:(HBJob *)job -{ - // Set the jobs info to the view controllers - fPictureController.picture = job.picture; - fPictureController.filters = job.filters; - fPreviewController.job = job; - - fVideoController.job = job; - fAudioController.audio = job.audio; - fSubtitlesViewController.subtitles = job.subtitles; - fChapterTitlesController.job = job; - - if (job) - { - [[NSNotificationCenter defaultCenter] removeObserver:_job]; - [[NSNotificationCenter defaultCenter] removeObserver:_job.picture]; - [[NSNotificationCenter defaultCenter] removeObserver:_job.filters]; - [[NSNotificationCenter defaultCenter] removeObserver:_job.video]; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pictureSettingsDidChange) name:HBPictureChangedNotification object:job.picture]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pictureSettingsDidChange) name:HBFiltersChangedNotification object:job.filters]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(formatChanged:) name:HBContainerChangedNotification object:job]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(customSettingUsed) name:HBVideoChangedNotification object:job.video]; - } - - // Retain the new job - [_job autorelease]; - _job = [job retain]; - - [self enableUI:(job != nil)]; + [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self + forKeyPath:@"values.HBShowAdvancedTab" + options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial + context:NULL]; + + [self.window recalculateKeyViewLoop]; } #pragma mark - #pragma mark Drag & drop handling -// This method is used by OSX to know what kind of files can be drag & drop on the NSWindow -// We only want filenames (and so folders too) +/** This method is used by OSX to know what kind of files can be drag & drop on the NSWindow + * We only want filenames (and so folders too) + */ - (NSDragOperation)draggingEntered:(id )sender { NSPasteboard *pboard = [sender draggingPasteboard]; @@ -340,158 +215,7 @@ return YES; } -#pragma mark - - -- (NSApplicationTerminateReply) applicationShouldTerminate: (NSApplication *) app -{ - if (fQueueController.core.state != HBStateIdle) - { - NSAlert *alert = [[NSAlert alloc] init]; - [alert setMessageText:NSLocalizedString(@"Are you sure you want to quit HandBrake?", nil)]; - [alert setInformativeText:NSLocalizedString(@"If you quit HandBrake your current encode will be reloaded into your queue at next launch. Do you want to quit anyway?", nil)]; - [alert addButtonWithTitle:NSLocalizedString(@"Quit", nil)]; - [alert addButtonWithTitle:NSLocalizedString(@"Don't Quit", nil)]; - [alert setAlertStyle:NSCriticalAlertStyle]; - - NSInteger result = [alert runModal]; - [alert release]; - - if (result == NSAlertFirstButtonReturn) - { - return NSTerminateNow; - } - else - { - return NSTerminateCancel; - } - } - - // Warn if items still in the queue - else if (fQueueController.pendingItemsCount > 0) - { - NSAlert *alert = [[NSAlert alloc] init]; - [alert setMessageText:NSLocalizedString(@"Are you sure you want to quit HandBrake?", nil)]; - [alert setInformativeText:NSLocalizedString(@"There are pending encodes in your queue. Do you want to quit anyway?",nil)]; - [alert addButtonWithTitle:NSLocalizedString(@"Quit", nil)]; - [alert addButtonWithTitle:NSLocalizedString(@"Don't Quit", nil)]; - [alert setAlertStyle:NSCriticalAlertStyle]; - NSInteger result = [alert runModal]; - [alert release]; - if (result == NSAlertFirstButtonReturn) - { - return NSTerminateNow; - } - else - { - return NSTerminateCancel; - } - } - - return NSTerminateNow; -} - -- (void)applicationWillTerminate:(NSNotification *)aNotification -{ - [presetManager savePresets]; - [presetManager release]; - - [[NSNotificationCenter defaultCenter] removeObserver:self]; - - [outputPanel release]; - [fQueueController release]; - [fQueueController release]; - [fPreviewController release]; - [fPictureController release]; - - self.core = nil; - self.browsedSourceDisplayName = nil; - - [HBCore closeGlobal]; -} - -- (void) awakeFromNib -{ - /* For 64 bit builds, the threaded animation in the progress - * indicators conflicts with the animation in the advanced tab - * for reasons not completely clear. jbrjake found a note in the - * 10.5 dev notes regarding this possiblility. It was also noted - * that unless specified, setUsesThreadedAnimation defaults to true. - * So, at least for now we set the indicator animation to NO for - * both the scan and regular progress indicators for both 32 and 64 bit - * as it test out fine on both and there is no reason our progress indicators - * should require their own thread. - */ - - _window = fWindow; - - [fScanIndicator setUsesThreadedAnimation:NO]; - [fRipIndicator setUsesThreadedAnimation:NO]; - - // Presets initialization - [self buildPresetsMenu]; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(buildPresetsMenu) name:HBPresetsChangedNotification object:nil]; - - [fPresetDrawer setDelegate:self]; - NSSize drawerSize = NSSizeFromString([[NSUserDefaults standardUserDefaults] - stringForKey:@"HBDrawerSize"]); - if (drawerSize.width) - { - [fPresetDrawer setContentSize: drawerSize]; - } - - // Align the start / stop widgets with the chapter popups - NSPoint startPoint = [fSrcChapterStartPopUp frame].origin; - startPoint.y += 2; - - NSPoint endPoint = [fSrcChapterEndPopUp frame].origin; - endPoint.y += 2; - - [fSrcTimeStartEncodingField setFrameOrigin:startPoint]; - [fSrcTimeEndEncodingField setFrameOrigin:endPoint]; - - [fSrcFrameStartEncodingField setFrameOrigin:startPoint]; - [fSrcFrameEndEncodingField setFrameOrigin:endPoint]; - - // Bottom - [fStatusField setStringValue:@""]; - - // Register HBController's Window as a receiver for files/folders drag & drop operations - [fWindow registerForDraggedTypes:@[NSFilenamesPboardType]]; - - // Set up the preset drawer - fPresetsView = [[HBPresetsViewController alloc] initWithPresetManager:presetManager]; - [fPresetDrawer setContentView:[fPresetsView view]]; - fPresetsView.delegate = self; - [[fPresetDrawer contentView] setAutoresizingMask:( NSViewWidthSizable | NSViewHeightSizable )]; - - // Set up the chapters title view - fChapterTitlesController = [[HBChapterTitlesController alloc] init]; - [fChaptersTitlesTab setView:[fChapterTitlesController view]]; - - // setup the subtitles view - fSubtitlesViewController = [[HBSubtitlesController alloc] init]; - [fSubtitlesTab setView:[fSubtitlesViewController view]]; - - // setup the audio controller - fAudioController = [[HBAudioController alloc] init]; - [fAudioTab setView:[fAudioController view]]; - - // setup the advanced view controller - fAdvancedOptions = [[HBAdvancedController alloc] init]; - [fAdvancedTab setView:[fAdvancedOptions view]]; - - // setup the video view controller - fVideoController = [[HBVideoController alloc] initWithAdvancedController:fAdvancedOptions]; - [fVideoTab setView:[fVideoController view]]; - - [[NSUserDefaultsController sharedUserDefaultsController] addObserver:self - forKeyPath:@"values.HBShowAdvancedTab" - options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial - context:NULL]; - - [fWindow recalculateKeyViewLoop]; -} +#pragma mark - KVO - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { @@ -534,10 +258,14 @@ fPresetsView.enabled = enabled; } -#pragma mark - -#pragma mark Toolbar +- (NSSize)drawerWillResizeContents:(NSDrawer *) drawer toSize:(NSSize)contentSize { + [[NSUserDefaults standardUserDefaults] setObject:NSStringFromSize(contentSize) forKey:@"HBDrawerSize"]; + return contentSize; +} -- (BOOL) validateToolbarItem: (NSToolbarItem *) toolbarItem +#pragma mark - UI Validation + +- (BOOL)validateToolbarItem:(NSToolbarItem *)toolbarItem { SEL action = toolbarItem.action; @@ -617,89 +345,73 @@ if (self.job) { - if (action == @selector(showPicturePanel:)) - return YES; - if (action == @selector(showPreviewWindow:)) - return YES; - if (action == @selector(addToQueue:)) + if (action == @selector(showPicturePanel:) || + action == @selector(showPreviewWindow:) || + action == @selector(addToQueue:)) + { return YES; + } } else { - if (action == @selector(showPicturePanel:)) - return NO; - if (action == @selector(showPreviewWindow:)) - return NO; - if (action == @selector(addToQueue:)) + if (action == @selector(showPicturePanel:) || + action == @selector(showPreviewWindow:) || + action == @selector(addToQueue:)) + { return NO; + } } // If there are any pending queue items, make sure the start/stop button is active. if (action == @selector(rip:) && (fQueueController.pendingItemsCount > 0 || self.job)) + { return YES; - if (action == @selector(showQueueWindow:)) - return YES; - if (action == @selector(toggleDrawer:)) - return YES; - if (action == @selector(browseSources:)) - return YES; - if (action == @selector(showDebugOutputPanel:)) - return YES; + } - return NO; + return YES; } -- (BOOL) validateMenuItem: (NSMenuItem *) menuItem +- (BOOL)validateMenuItem:(NSMenuItem *)menuItem { SEL action = [menuItem action]; - HBState queueState = fQueueController.core.state; - - if (action == @selector(addToQueue:) || action == @selector(addAllTitlesToQueue:) || action == @selector(showPicturePanel:) || action == @selector(showAddPresetPanel:)) - return self.job && [fWindow attachedSheet] == nil; + if (action == @selector(addToQueue:) || action == @selector(addAllTitlesToQueue:) || + action == @selector(showPicturePanel:) || action == @selector(showAddPresetPanel:) || + action == @selector(showPreviewWindow:)) + { + return self.job && self.window.attachedSheet == nil; + } if (action == @selector(selectDefaultPreset:)) - return [fWindow attachedSheet] == nil; - + { + return self.window.attachedSheet == nil; + } if (action == @selector(pause:)) { - if (queueState == HBStateWorking) - { - if(![[menuItem title] isEqualToString:@"Pause Encoding"]) - [menuItem setTitle:@"Pause Encoding"]; - return YES; - } - else if (queueState == HBStatePaused) - { - if(![[menuItem title] isEqualToString:@"Resume Encoding"]) - [menuItem setTitle:@"Resume Encoding"]; - return YES; - } - else - return NO; + return [fQueueController validateMenuItem:menuItem]; } if (action == @selector(rip:)) { - if (queueState == HBStateWorking || queueState == HBStateMuxing || queueState == HBStatePaused) + BOOL result = [fQueueController validateMenuItem:menuItem]; + + if ([menuItem.title isEqualToString:NSLocalizedString(@"Start Encoding", nil)]) { - if(![[menuItem title] isEqualToString:@"Stop Encoding"]) - [menuItem setTitle:@"Stop Encoding"]; - return YES; + if (!result && self.job) + { + return YES; + } } - else if (self.job) - { - if(![[menuItem title] isEqualToString:@"Start Encoding"]) - [menuItem setTitle:@"Start Encoding"]; - return [fWindow attachedSheet] == nil; - } - else - return NO; + + return result; } if (action == @selector(browseSources:)) { - if (self.core.state == HBStateScanning) + if (self.core.state == HBStateScanning) { return NO; + } else - return [fWindow attachedSheet] == nil; + { + return self.window.attachedSheet == nil; + } } if (action == @selector(selectPresetFromMenu:)) { @@ -711,13 +423,67 @@ { menuItem.state = NSOffState; } + return (self.job != nil); } return YES; } -#pragma mark - -#pragma mark Get New Source +#pragma mark - Get New Source + +- (void)launchAction +{ + if (self.core.state != HBStateScanning && !self.job) + { + // We show whichever open source window specified in LaunchSourceBehavior preference key + if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"LaunchSourceBehavior"] isEqualToString: @"Open Source"]) + { + [self browseSources:nil]; + } + } + +} + +- (void)openFile:(NSURL *)fileURL +{ + if (self.core.state != HBStateScanning) + { + self.browsedSourceDisplayName = fileURL.lastPathComponent; + [self performScan:fileURL scanTitleNum:0]; + } +} + +- (void)setJob:(HBJob *)job +{ + // Set the jobs info to the view controllers + fPictureController.picture = job.picture; + fPictureController.filters = job.filters; + fPreviewController.job = job; + + fVideoController.job = job; + fAudioController.audio = job.audio; + fSubtitlesViewController.subtitles = job.subtitles; + fChapterTitlesController.job = job; + + if (job) + { + [[NSNotificationCenter defaultCenter] removeObserver:_job]; + [[NSNotificationCenter defaultCenter] removeObserver:_job.picture]; + [[NSNotificationCenter defaultCenter] removeObserver:_job.filters]; + [[NSNotificationCenter defaultCenter] removeObserver:_job.video]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pictureSettingsDidChange) name:HBPictureChangedNotification object:job.picture]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pictureSettingsDidChange) name:HBFiltersChangedNotification object:job.filters]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(formatChanged:) name:HBContainerChangedNotification object:job]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(customSettingUsed) name:HBVideoChangedNotification object:job.video]; + } + + // Retain the new job + [_job autorelease]; + _job = [job retain]; + + [self enableUI:(job != nil)]; +} /** * Opens the source browse window, called from Open Source widgets @@ -746,150 +512,86 @@ } [panel setDirectoryURL:sourceDirectory]; + [panel setAccessoryView:self.openTitleView]; - [panel beginSheetModalForWindow:fWindow completionHandler: ^(NSInteger result) + [panel beginSheetModalForWindow:self.window completionHandler: ^(NSInteger result) { - if (result == NSOKButton) - { - NSURL *scanURL = panel.URL; - // we set the last searched source directory in the prefs here - [[NSUserDefaults standardUserDefaults] setURL:scanURL.URLByDeletingLastPathComponent forKey:@"HBLastSourceDirectoryURL"]; + if (result == NSOKButton) + { + NSURL *scanURL = panel.URL; + // we set the last searched source directory in the prefs here + [[NSUserDefaults standardUserDefaults] setURL:scanURL.URLByDeletingLastPathComponent forKey:@"HBLastSourceDirectoryURL"]; - // we order out sheet, which is the browse window as we need to open - // the title selection sheet right away - [panel orderOut:self]; + NSURL *url = panel.URL; - if (sender == fOpenSourceTitleMMenu || [[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask) - { - // We put the chosen source path in the source display text field for the - // source title selection sheet in which the user specifies the specific title to be - // scanned as well as the short source name in fSrcDsplyNameTitleScan just for display - // purposes in the title panel + // We check to see if the chosen file at path is a package + if ([[NSWorkspace sharedWorkspace] isFilePackageAtPath:url.path]) + { + [HBUtilities writeToActivityLog:"trying to open a package at: %s", url.path.UTF8String]; + // We check to see if this is an .eyetv package + if ([url.pathExtension isEqualToString:@"eyetv"]) + { + [HBUtilities writeToActivityLog:"trying to open eyetv package"]; + // We're looking at an EyeTV package - try to open its enclosed .mpg media file + self.browsedSourceDisplayName = url.URLByDeletingPathExtension.lastPathComponent; + NSString *mpgname; + NSUInteger n = [[url.path stringByAppendingString: @"/"] + completePathIntoString: &mpgname caseSensitive: YES + matchesIntoArray: nil + filterTypes: @[@"mpg"]]; + if (n > 0) + { + // Found an mpeg inside the eyetv package, make it our scan path + [HBUtilities writeToActivityLog:"found mpeg in eyetv package"]; + url = [NSURL fileURLWithPath:mpgname]; + } + else + { + // We did not find an mpeg file in our package, so we do not call performScan + [HBUtilities writeToActivityLog:"no valid mpeg in eyetv package"]; + } + } + // We check to see if this is a .dvdmedia package + else if ([url.pathExtension isEqualToString:@"dvdmedia"]) + { + // path IS a package - but dvdmedia packages can be treaded like normal directories + self.browsedSourceDisplayName = url.URLByDeletingPathExtension.lastPathComponent; + [HBUtilities writeToActivityLog:"trying to open dvdmedia package"]; + } + else + { + // The package is not an eyetv package, try to open it anyway + self.browsedSourceDisplayName = url.lastPathComponent; + [HBUtilities writeToActivityLog:"not a known to package"]; + } + } + else + { + // path is not a package, so we call perform scan directly on our file + if ([url.lastPathComponent isEqualToString:@"VIDEO_TS"]) + { + [HBUtilities writeToActivityLog:"trying to open video_ts folder (video_ts folder chosen)"]; + // If VIDEO_TS Folder is chosen, choose its parent folder for the source display name + url = url.URLByDeletingLastPathComponent; + self.browsedSourceDisplayName = url.lastPathComponent; + } + else + { + [HBUtilities writeToActivityLog:"trying to open a folder or file"]; + // if not the VIDEO_TS Folder, we can assume the chosen folder is the source name + // make sure we remove any path extension + self.browsedSourceDisplayName = url.lastPathComponent; + } + } - // Full Path - [fScanSrcTitlePathField setStringValue:scanURL.path]; - NSString *displayTitlescanSourceName; - - if ([scanURL.lastPathComponent isEqualToString:@"VIDEO_TS"]) - { - // If VIDEO_TS Folder is chosen, choose its parent folder for the source display name - // we have to use the title->path value so we get the proper name of the volume if a physical dvd is the source - displayTitlescanSourceName = scanURL.URLByDeletingLastPathComponent.lastPathComponent; - } - else - { - // if not the VIDEO_TS Folder, we can assume the chosen folder is the source name - displayTitlescanSourceName = scanURL.lastPathComponent; - } - // we set the source display name in the title selection dialogue - [fSrcDsplyNameTitleScan setStringValue:displayTitlescanSourceName]; - // we set the attempted scans display name for main window to displayTitlescanSourceName - self.browsedSourceDisplayName = displayTitlescanSourceName; - // We show the actual sheet where the user specifies the title to be scanned - // as we are going to do a title specific scan - - [self showSourceTitleScanPanel:nil]; - } - else - { - // We are just doing a standard full source scan, so we specify "0" to libhb - NSURL *url = panel.URL; - - // We check to see if the chosen file at path is a package - if ([[NSWorkspace sharedWorkspace] isFilePackageAtPath:url.path]) - { - [HBUtilities writeToActivityLog:"trying to open a package at: %s", url.path.UTF8String]; - // We check to see if this is an .eyetv package - if ([url.pathExtension isEqualToString:@"eyetv"]) - { - [HBUtilities writeToActivityLog:"trying to open eyetv package"]; - // We're looking at an EyeTV package - try to open its enclosed .mpg media file - self.browsedSourceDisplayName = url.URLByDeletingPathExtension.lastPathComponent; - NSString *mpgname; - NSUInteger n = [[url.path stringByAppendingString: @"/"] - completePathIntoString: &mpgname caseSensitive: YES - matchesIntoArray: nil - filterTypes: @[@"mpg"]]; - if (n > 0) - { - // Found an mpeg inside the eyetv package, make it our scan path - [HBUtilities writeToActivityLog:"found mpeg in eyetv package"]; - url = [NSURL fileURLWithPath:mpgname]; - } - else - { - // We did not find an mpeg file in our package, so we do not call performScan - [HBUtilities writeToActivityLog:"no valid mpeg in eyetv package"]; - } - } - // We check to see if this is a .dvdmedia package - else if ([url.pathExtension isEqualToString:@"dvdmedia"]) - { - // path IS a package - but dvdmedia packages can be treaded like normal directories - self.browsedSourceDisplayName = url.URLByDeletingPathExtension.lastPathComponent; - [HBUtilities writeToActivityLog:"trying to open dvdmedia package"]; - } - else - { - // The package is not an eyetv package, try to open it anyway - self.browsedSourceDisplayName = url.lastPathComponent; - [HBUtilities writeToActivityLog:"not a known to package"]; - } - } - else - { - // path is not a package, so we call perform scan directly on our file - if ([url.lastPathComponent isEqualToString:@"VIDEO_TS"]) - { - [HBUtilities writeToActivityLog:"trying to open video_ts folder (video_ts folder chosen)"]; - // If VIDEO_TS Folder is chosen, choose its parent folder for the source display name - url = url.URLByDeletingLastPathComponent; - self.browsedSourceDisplayName = url.lastPathComponent; - } - else - { - [HBUtilities writeToActivityLog:"trying to open a folder or file"]; - // if not the VIDEO_TS Folder, we can assume the chosen folder is the source name - // make sure we remove any path extension - self.browsedSourceDisplayName = url.lastPathComponent; - } - } - - [self performScan:url scanTitleNum:0]; - } - } - }]; -} - -/* Here we open the title selection sheet where we can specify an exact title to be scanned */ -- (IBAction) showSourceTitleScanPanel: (id) sender -{ - /* We default the title number to be scanned to "0" which results in a full source scan, unless the - * user changes it - */ - [fScanSrcTitleNumField setStringValue: @"0"]; - /* Show the panel */ - [NSApp beginSheet:fScanSrcTitlePanel modalForWindow:fWindow modalDelegate:nil didEndSelector:NULL contextInfo:NULL]; -} - -- (IBAction) closeSourceTitleScanPanel: (id) sender -{ - [NSApp endSheet: fScanSrcTitlePanel]; - [fScanSrcTitlePanel orderOut: self]; - - if (sender == fScanSrcTitleOpenButton) - { - // We setup the scan status in the main window to indicate a source title scan - [fSrcDVD2Field setStringValue: @"Opening a new source title…"]; - [fScanIndicator setHidden: NO]; - [fScanHorizontalLine setHidden: YES]; - [fScanIndicator setIndeterminate: YES]; - [fScanIndicator startAnimation: nil]; - - // We use the performScan method to actually perform the specified scan passing the path and the title - // to be scanned - [self performScan:[NSURL fileURLWithPath:fScanSrcTitlePathField.stringValue] scanTitleNum:fScanSrcTitleNumField.intValue]; - } + NSInteger titleIdx = 0; + if (self.scanSpecificTitle) + { + titleIdx = self.scanSpecificTitleIdx; + } + [self performScan:url scanTitleNum:titleIdx]; + } + }]; } /* Here we actually tell hb_scan to perform the source scan, using the path to source and title number*/ @@ -902,6 +604,7 @@ } self.job = nil; + [fSrcTitlePopUp removeAllItems]; NSError *outError = NULL; BOOL suppressWarning = [[NSUserDefaults standardUserDefaults] boolForKey:@"suppresslibdvdcss"]; @@ -992,7 +695,7 @@ // We display a message if a valid source was not chosen fSrcDVD2Field.stringValue = NSLocalizedString(@"No Valid Source Found", @""); } - [fWindow.toolbar validateVisibleItems]; + [self.window.toolbar validateVisibleItems]; }]; } } @@ -1009,8 +712,6 @@ [HBUtilities writeToActivityLog: "showNewScan: This is a new source item scan"]; } - [fSrcTitlePopUp removeAllItems]; - for (HBTitle *title in self.core.titles) { // Set Source Name at top of window with the browsedSourceDisplayName grokked right before -performScan @@ -1049,64 +750,187 @@ } } -#pragma mark - -#pragma mark New Output Destination +#pragma mark - GUI Controls Changed Methods -- (IBAction)browseFile:(id)sender +- (IBAction)browseDestination:(id)sender { // Open a panel to let the user choose and update the text field NSSavePanel *panel = [NSSavePanel savePanel]; panel.directoryURL = self.job.destURL.URLByDeletingLastPathComponent; panel.nameFieldStringValue = self.job.destURL.lastPathComponent; - [panel beginSheetModalForWindow:fWindow completionHandler:^(NSInteger result) { - if (result == NSFileHandlingPanelOKButton) - { - self.job.destURL = panel.URL; + [panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) + { + if (result == NSFileHandlingPanelOKButton) + { + self.job.destURL = panel.URL; - // Save this path to the prefs so that on next browse destination window it opens there - [[NSUserDefaults standardUserDefaults] setURL:panel.URL.URLByDeletingLastPathComponent - forKey:@"HBLastDestinationDirectory"]; - } - }]; + // Save this path to the prefs so that on next browse destination window it opens there + [[NSUserDefaults standardUserDefaults] setURL:panel.URL.URLByDeletingLastPathComponent + forKey:@"HBLastDestinationDirectory"]; + } + }]; } -#pragma mark - -#pragma mark Main Window Control - -- (IBAction) openMainWindow: (id) sender +- (void)updateFileName { - [fWindow makeKeyAndOrderFront:nil]; + HBTitle *title = self.job.title; + + // Generate a new file name + NSString *fileName = [HBUtilities automaticNameForSource:title.name + title:title.hb_title->index + chapters:NSMakeRange(self.job.range.chapterStart + 1, self.job.range.chapterStop + 1) + quality:self.job.video.qualityType ? self.job.video.quality : 0 + bitrate:!self.job.video.qualityType ? self.job.video.avgBitrate : 0 + videoCodec:self.job.video.encoder]; + + // Swap the old one with the new one + self.job.destURL = [[self.job.destURL URLByDeletingLastPathComponent] URLByAppendingPathComponent: + [NSString stringWithFormat:@"%@.%@", fileName, self.job.destURL.pathExtension]]; } -- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag +- (NSURL *)destURLForJob:(HBJob *)job { - if( !flag ) { - [fWindow makeKeyAndOrderFront:nil]; + // Check to see if the last destination has been set,use if so, if not, use Desktop + NSURL *destURL = [[NSUserDefaults standardUserDefaults] URLForKey:@"HBLastDestinationDirectory"]; + if (!destURL || ![[NSFileManager defaultManager] fileExistsAtPath:destURL.path]) + { + destURL = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDesktopDirectory, NSUserDomainMask, YES) firstObject] + isDirectory:YES]; } - return YES; + + destURL = [destURL URLByAppendingPathComponent:job.title.name]; + // use the correct extension based on the container + const char *ext = hb_container_get_default_extension(self.job.container); + destURL = [destURL URLByAppendingPathExtension:@(ext)]; + + return destURL; } -- (NSSize) drawerWillResizeContents:(NSDrawer *) drawer toSize:(NSSize) contentSize { - [[NSUserDefaults standardUserDefaults] setObject:NSStringFromSize( contentSize ) forKey:@"HBDrawerSize"]; - return contentSize; +- (IBAction)titlePopUpChanged:(id)sender +{ + // If there is already a title load, save the current settings to a preset + if (self.job) + { + self.selectedPreset = [self createPresetFromCurrentSettings]; + } + + HBTitle *title = self.core.titles[fSrcTitlePopUp.indexOfSelectedItem]; + + // Check if we are reapplying a job from the queue, or creating a new one + if (self.jobFromQueue) + { + self.jobFromQueue.title = title; + self.job = self.jobFromQueue; + } + else + { + self.job = [[[HBJob alloc] initWithTitle:title andPreset:self.selectedPreset] autorelease]; + self.job.destURL = [self destURLForJob:self.job]; + + // set m4v extension if necessary - do not override user-specified .mp4 extension + if (self.job.container & HB_MUX_MASK_MP4) + { + [self autoSetM4vExtension:nil]; + } + } + + // If we are a stream type and a batch scan, grok the output file name from title->name upon title change + if ((title.hb_title->type == HB_STREAM_TYPE || title.hb_title->type == HB_FF_STREAM_TYPE) && self.core.titles.count > 1) + { + // Change the source to read out the parent folder also + fSrcDVD2Field.stringValue = [NSString stringWithFormat:@"%@/%@", self.browsedSourceDisplayName, title.name]; + } + + // apply the current preset + if (!self.jobFromQueue) + { + [self applyPreset:self.selectedPreset]; + } } -#pragma mark - Queue Item Editing +- (void)chapterPopUpChanged:(NSNotification *)notification +{ + // We're changing the chapter range - we may need to flip the m4v/mp4 extension + if (self.job.container & HB_MUX_MASK_MP4) + { + [self autoSetM4vExtension:notification]; + } + + // If Auto Naming is on it might need to be update if it includes the chapters range + if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultAutoNaming"]) + { + [self updateFileName]; + } +} + +- (void)formatChanged:(NSNotification *)notification +{ + if (self.job) + { + int videoContainer = self.job.container; + + // set the file extension + const char *ext = hb_container_get_default_extension(videoContainer); + self.job.destURL = [[self.job.destURL URLByDeletingPathExtension] URLByAppendingPathExtension:@(ext)]; + + if (videoContainer & HB_MUX_MASK_MP4) + { + [self autoSetM4vExtension:notification]; + } + } +} + +- (void)autoSetM4vExtension:(NSNotification *)notification +{ + if (!(self.job.container & HB_MUX_MASK_MP4)) + return; + + NSString *extension = @"mp4"; + + BOOL anyCodecAC3 = [self.job.audio anyCodecMatches:HB_ACODEC_AC3] || [self.job.audio anyCodecMatches:HB_ACODEC_AC3_PASS]; + // Chapter markers are enabled if the checkbox is ticked and we are doing p2p or we have > 1 chapter + BOOL chapterMarkers = (self.job.chaptersEnabled) && + (self.job.range.type != HBRangeTypeChapters || + self.job.range.chapterStart < self.job.range.chapterStop); + + if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"DefaultMpegExtension"] isEqualToString: @".m4v"] || + ((YES == anyCodecAC3 || YES == chapterMarkers) && + [[[NSUserDefaults standardUserDefaults] objectForKey:@"DefaultMpegExtension"] isEqualToString: @"Auto"])) + { + extension = @"m4v"; + } + + if ([extension isEqualTo:self.job.destURL.pathExtension]) + { + return; + } + else + { + self.job.destURL = [[self.job.destURL URLByDeletingPathExtension] URLByAppendingPathExtension:extension]; + } +} /** - * Rescans the chosen queue item back into the main window + * Method to determine if we should change the UI + * To reflect whether or not a Preset is being used or if + * the user is using "Custom" settings by determining the sender */ -- (void)rescanJobToMainWindow:(HBJob *)queueItem +- (void)customSettingUsed { - // Set the browsedSourceDisplayName for showNewScan - self.jobFromQueue = queueItem; - self.browsedSourceDisplayName = self.jobFromQueue.fileURL.lastPathComponent; + // Deselect the currently selected Preset if there is one + [fPresetsView deselect]; + // Change UI to show "Custom" settings are being used + self.job.presetName = NSLocalizedString(@"Custom", @""); - [self performScan:self.jobFromQueue.fileURL scanTitleNum:self.jobFromQueue.titleIdx]; + // If Auto Naming is on it might need to be update if it includes the quality token + if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultAutoNaming"]) + { + [self updateFileName]; + } } -#pragma mark - Queue +#pragma mark - Queue progress - (void)setQueueState:(NSString *)info { @@ -1125,16 +949,16 @@ { if (fRipIndicatorShown) { - NSRect frame = fWindow.frame; + NSRect frame = self.window.frame; if (frame.size.width <= WINDOW_HEIGHT) frame.size.width = WINDOW_HEIGHT; frame.size.height += -WINDOW_HEIGHT_OFFSET; frame.origin.y -= -WINDOW_HEIGHT_OFFSET; - [fWindow setFrame:frame display:YES animate:YES]; + [self.window setFrame:frame display:YES animate:YES]; fRipIndicatorShown = NO; // Refresh the toolbar buttons - [fWindow.toolbar validateVisibleItems]; + [self.window.toolbar validateVisibleItems]; } } else @@ -1143,16 +967,16 @@ // that now. if (!fRipIndicatorShown) { - NSRect frame = fWindow.frame; + NSRect frame = self.window.frame; if (frame.size.width <= WINDOW_HEIGHT) frame.size.width = WINDOW_HEIGHT; frame.size.height += WINDOW_HEIGHT_OFFSET; frame.origin.y -= WINDOW_HEIGHT_OFFSET; - [fWindow setFrame:frame display:YES animate:YES]; + [self.window setFrame:frame display:YES animate:YES]; fRipIndicatorShown = YES; // Refresh the toolbar buttons - [fWindow.toolbar validateVisibleItems]; + [self.window.toolbar validateVisibleItems]; } } } @@ -1195,7 +1019,7 @@ [alert addButtonWithTitle:NSLocalizedString(@"Overwrite", @"")]; [alert setAlertStyle:NSCriticalAlertStyle]; - [alert beginSheetModalForWindow:fWindow modalDelegate:self didEndSelector:@selector(overwriteAddToQueueAlertDone:returnCode:contextInfo:) contextInfo:NULL]; + [alert beginSheetModalForWindow:self.window modalDelegate:self didEndSelector:@selector(overwriteAddToQueueAlertDone:returnCode:contextInfo:) contextInfo:NULL]; [alert release]; } else if ([fQueueController jobExistAtURL:self.job.destURL]) @@ -1208,7 +1032,7 @@ [alert addButtonWithTitle:NSLocalizedString(@"Overwrite", @"")]; [alert setAlertStyle:NSCriticalAlertStyle]; - [alert beginSheetModalForWindow:fWindow modalDelegate:self didEndSelector:@selector(overwriteAddToQueueAlertDone:returnCode:contextInfo:) contextInfo:NULL]; + [alert beginSheetModalForWindow:self.window modalDelegate:self didEndSelector:@selector(overwriteAddToQueueAlertDone:returnCode:contextInfo:) contextInfo:NULL]; [alert release]; } else @@ -1231,6 +1055,18 @@ } } +/** + * Rescans the chosen queue item back into the main window + */ +- (void)rescanJobToMainWindow:(HBJob *)queueItem +{ + // Set the browsedSourceDisplayName for showNewScan + self.jobFromQueue = queueItem; + self.browsedSourceDisplayName = self.jobFromQueue.fileURL.lastPathComponent; + + [self performScan:self.jobFromQueue.fileURL scanTitleNum:self.jobFromQueue.titleIdx]; +} + - (void)doRip { // if there are no jobs in the queue, then add this one to the queue and rip @@ -1285,7 +1121,7 @@ [alert addButtonWithTitle:NSLocalizedString(@"Overwrite", @"")]; [alert setAlertStyle:NSCriticalAlertStyle]; - [alert beginSheetModalForWindow:fWindow modalDelegate:self didEndSelector:@selector(overWriteAlertDone:returnCode:contextInfo:) contextInfo:NULL]; + [alert beginSheetModalForWindow:self.window modalDelegate:self didEndSelector:@selector(overWriteAlertDone:returnCode:contextInfo:) contextInfo:NULL]; // overWriteAlertDone: will be called when the alert is dismissed. It will call doRip. [alert release]; } @@ -1333,7 +1169,7 @@ [alert addButtonWithTitle:NSLocalizedString(@"Yes, I want to add all titles to the queue", @"")]; [alert setAlertStyle:NSCriticalAlertStyle]; - [alert beginSheetModalForWindow:fWindow modalDelegate:self didEndSelector:@selector(addAllTitlesToQueueAlertDone:returnCode:contextInfo:) contextInfo:NULL]; + [alert beginSheetModalForWindow:self.window modalDelegate:self didEndSelector:@selector(addAllTitlesToQueueAlertDone:returnCode:contextInfo:) contextInfo:NULL]; [alert release]; } @@ -1363,168 +1199,6 @@ [jobs release]; } -#pragma mark - -#pragma mark GUI Controls Changed Methods - -- (void)updateFileName -{ - HBTitle *title = self.job.title; - - // Generate a new file name - NSString *fileName = [HBUtilities automaticNameForSource:title.name - title:title.hb_title->index - chapters:NSMakeRange(self.job.range.chapterStart + 1, self.job.range.chapterStop + 1) - quality:self.job.video.qualityType ? self.job.video.quality : 0 - bitrate:!self.job.video.qualityType ? self.job.video.avgBitrate : 0 - videoCodec:self.job.video.encoder]; - - // Swap the old one with the new one - self.job.destURL = [[self.job.destURL URLByDeletingLastPathComponent] URLByAppendingPathComponent: - [NSString stringWithFormat:@"%@.%@", fileName, self.job.destURL.pathExtension]]; -} - -- (NSURL *)destURLForJob:(HBJob *)job -{ - // Check to see if the last destination has been set,use if so, if not, use Desktop - NSURL *destURL = [[NSUserDefaults standardUserDefaults] URLForKey:@"HBLastDestinationDirectory"]; - if (!destURL || ![[NSFileManager defaultManager] fileExistsAtPath:destURL.path]) - { - destURL = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDesktopDirectory, NSUserDomainMask, YES) firstObject] - isDirectory:YES]; - } - - destURL = [destURL URLByAppendingPathComponent:job.title.name]; - // use the correct extension based on the container - const char *ext = hb_container_get_default_extension(self.job.container); - destURL = [destURL URLByAppendingPathExtension:@(ext)]; - - return destURL; -} - -- (IBAction) titlePopUpChanged: (id) sender -{ - // If there is already a title load, save the current settings to a preset - if (self.job) - { - self.selectedPreset = [self createPresetFromCurrentSettings]; - } - - HBTitle *title = self.core.titles[fSrcTitlePopUp.indexOfSelectedItem]; - - // Check if we are reapplying a job from the queue, or creating a new one - if (self.jobFromQueue) - { - self.jobFromQueue.title = title; - self.job = self.jobFromQueue; - } - else - { - self.job = [[[HBJob alloc] initWithTitle:title andPreset:self.selectedPreset] autorelease]; - self.job.destURL = [self destURLForJob:self.job]; - - // set m4v extension if necessary - do not override user-specified .mp4 extension - if (self.job.container & HB_MUX_MASK_MP4) - { - [self autoSetM4vExtension:nil]; - } - } - - // If we are a stream type and a batch scan, grok the output file name from title->name upon title change - if ((title.hb_title->type == HB_STREAM_TYPE || title.hb_title->type == HB_FF_STREAM_TYPE) && self.core.titles.count > 1) - { - // Change the source to read out the parent folder also - fSrcDVD2Field.stringValue = [NSString stringWithFormat:@"%@/%@", self.browsedSourceDisplayName, title.name]; - } - - // apply the current preset - if (!self.jobFromQueue) - { - [self applyPreset:self.selectedPreset]; - } -} - -- (void)chapterPopUpChanged:(NSNotification *)notification -{ - // We're changing the chapter range - we may need to flip the m4v/mp4 extension - if (self.job.container & HB_MUX_MASK_MP4) - { - [self autoSetM4vExtension:notification]; - } - - // If Auto Naming is on it might need to be update if it includes the chapters range - if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultAutoNaming"]) - { - [self updateFileName]; - } -} - -- (void)formatChanged:(NSNotification *)notification -{ - if (self.job) - { - int videoContainer = self.job.container; - - // set the file extension - const char *ext = hb_container_get_default_extension(videoContainer); - self.job.destURL = [[self.job.destURL URLByDeletingPathExtension] URLByAppendingPathExtension:@(ext)]; - - if (videoContainer & HB_MUX_MASK_MP4) - { - [self autoSetM4vExtension:notification]; - } - } -} - -- (void) autoSetM4vExtension:(NSNotification *)notification -{ - if (!(self.job.container & HB_MUX_MASK_MP4)) - return; - - NSString *extension = @"mp4"; - - BOOL anyCodecAC3 = [self.job.audio anyCodecMatches:HB_ACODEC_AC3] || [self.job.audio anyCodecMatches:HB_ACODEC_AC3_PASS]; - // Chapter markers are enabled if the checkbox is ticked and we are doing p2p or we have > 1 chapter - BOOL chapterMarkers = (self.job.chaptersEnabled) && - (self.job.range.type != HBRangeTypeChapters || - self.job.range.chapterStart < self.job.range.chapterStop); - - if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"DefaultMpegExtension"] isEqualToString: @".m4v"] || - ((YES == anyCodecAC3 || YES == chapterMarkers) && - [[[NSUserDefaults standardUserDefaults] objectForKey:@"DefaultMpegExtension"] isEqualToString: @"Auto"])) - { - extension = @"m4v"; - } - - if ([extension isEqualTo:self.job.destURL.pathExtension]) - { - return; - } - else - { - self.job.destURL = [[self.job.destURL URLByDeletingPathExtension] URLByAppendingPathExtension:extension]; - } -} - -/** - * Method to determine if we should change the UI - * To reflect whether or not a Preset is being used or if - * the user is using "Custom" settings by determining the sender - */ -- (void)customSettingUsed -{ - // Deselect the currently selected Preset if there is one - [fPresetsView deselect]; - // Change UI to show "Custom" settings are being used - self.job.presetName = NSLocalizedString(@"Custom", @""); - - // If Auto Naming is on it might need to be update if it includes the quality token - if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultAutoNaming"]) - { - [self updateFileName]; - } -} - -#pragma mark - #pragma mark - Picture /** @@ -1536,62 +1210,9 @@ [self customSettingUsed]; } -#pragma mark - -#pragma mark Open New Windows - -- (IBAction) openHomepage: (id) sender +- (IBAction)toggleDrawer:(id)sender { - [[NSWorkspace sharedWorkspace] openURL: [NSURL - URLWithString:@"http://handbrake.fr/"]]; -} - -- (IBAction) openForums: (id) sender -{ - [[NSWorkspace sharedWorkspace] openURL: [NSURL - URLWithString:@"http://forum.handbrake.fr/"]]; -} -- (IBAction) openUserGuide: (id) sender -{ - [[NSWorkspace sharedWorkspace] openURL: [NSURL - URLWithString:@"http://trac.handbrake.fr/wiki/HandBrakeGuide"]]; -} - -/** - * Shows debug output window. - */ -- (IBAction)showDebugOutputPanel:(id)sender -{ - [outputPanel showOutputPanel:sender]; -} - -/** - * Shows preferences window. - */ -- (IBAction) showPreferencesWindow: (id) sender -{ - if (fPreferencesController == nil) - { - fPreferencesController = [[HBPreferencesController alloc] init]; - } - - NSWindow *window = [fPreferencesController window]; - if (![window isVisible]) - [window center]; - - [window makeKeyAndOrderFront: nil]; -} - -/** - * Shows queue window. - */ -- (IBAction) showQueueWindow:(id)sender -{ - [fQueueController showWindow:sender]; -} - -- (IBAction) toggleDrawer:(id)sender -{ - if ([fPresetDrawer state] == NSDrawerClosedState) + if (fPresetDrawer.state == NSDrawerClosedState) { [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"HBDefaultPresetsDrawerShow"]; } @@ -1606,17 +1227,24 @@ /** * Shows Picture Settings Window. */ -- (IBAction) showPicturePanel: (id) sender +- (IBAction)showPicturePanel:(id)sender { [fPictureController showPictureWindow]; } -- (IBAction) showPreviewWindow: (id) sender +- (IBAction)showPreviewWindow:(id)sender { [fPreviewController showWindow:sender]; } -#pragma mark - Preset Methods +#pragma mark - Presets View Controller Delegate + +- (void)selectionDidChange +{ + [self applyPreset:fPresetsView.selectedPreset]; +} + +#pragma mark - Presets - (void)applyPreset:(HBPreset *)preset { @@ -1637,44 +1265,13 @@ } } -#pragma mark - Presets View Controller Delegate - -- (void)selectionDidChange -{ - [self applyPreset:fPresetsView.selectedPreset]; -} - -#pragma mark - -#pragma mark Manage Presets - -- (void) checkBuiltInsForUpdates -{ - /* if we have built in presets to update, then do so AlertBuiltInPresetUpdate*/ - if ([presetManager checkBuiltInsForUpdates]) - { - if( [[NSUserDefaults standardUserDefaults] boolForKey:@"AlertBuiltInPresetUpdate"] == YES) - { - /* Show an alert window that built in presets will be updated */ - /*On Screen Notification*/ - [NSApp requestUserAttention:NSCriticalRequest]; - NSAlert *alert = [[NSAlert alloc] init]; - [alert setMessageText:@"HandBrake has determined your built in presets are out of date…"]; - [alert setInformativeText:@"HandBrake will now update your built-in presets."]; - [alert runModal]; - [alert release]; - } - /* when alert is dismissed, go ahead and update the built in presets */ - [presetManager generateBuiltInPresets]; - } -} - - (IBAction)showAddPresetPanel:(id)sender { - /* Show the add panel */ + // Show the add panel HBAddPresetController *addPresetController = [[HBAddPresetController alloc] initWithPreset:[self createPresetFromCurrentSettings] videoSize:NSMakeSize(self.job.picture.width, self.job.picture.height)]; - [NSApp beginSheet:addPresetController.window modalForWindow:fWindow modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:addPresetController]; + [NSApp beginSheet:addPresetController.window modalForWindow:self.window modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:addPresetController]; } - (void)sheetDidEnd:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo @@ -1722,20 +1319,20 @@ - (IBAction) browseExportPresetFile: (id) sender { - /* Open a panel to let the user choose where and how to save the export file */ + // Open a panel to let the user choose where and how to save the export file NSSavePanel *panel = [NSSavePanel savePanel]; - /* We get the current file name and path from the destination field here */ - NSString *defaultExportDirectory = [NSString stringWithFormat: @"%@/Desktop/", NSHomeDirectory()]; - [panel setDirectoryURL:[NSURL fileURLWithPath:defaultExportDirectory]]; + // We get the current file name and path from the destination field here + NSURL *defaultExportDirectory = [[NSURL fileURLWithPath:NSHomeDirectory()] URLByAppendingPathComponent:@"Desktop"]; + [panel setDirectoryURL:defaultExportDirectory]; [panel setNameFieldStringValue:@"HB_Export.plist"]; - [panel beginSheetModalForWindow:fWindow completionHandler:^(NSInteger result) { + [panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) { if( result == NSOKButton ) { NSURL *exportPresetsFile = [panel URL]; NSURL *presetExportDirectory = [exportPresetsFile URLByDeletingLastPathComponent]; [[NSUserDefaults standardUserDefaults] setURL:presetExportDirectory forKey:@"LastPresetExportDirectoryURL"]; - /* We check for the presets.plist */ + // We check for the presets.plist if ([[NSFileManager defaultManager] fileExistsAtPath:[exportPresetsFile path]] == 0) { [[NSFileManager defaultManager] createFileAtPath:[exportPresetsFile path] contents:nil attributes:nil]; @@ -1745,7 +1342,7 @@ if (presetsToExport == nil) { presetsToExport = [[NSMutableArray alloc] init]; - /* now get and add selected presets to export */ + // now get and add selected presets to export } if (fPresetsView.selectedPreset != nil) { @@ -1758,9 +1355,7 @@ - (IBAction)browseImportPresetFile:(id)sender { - NSOpenPanel *panel; - - panel = [NSOpenPanel openPanel]; + NSOpenPanel *panel = [NSOpenPanel openPanel]; [panel setAllowsMultipleSelection:NO]; [panel setCanChooseFiles:YES]; [panel setCanChooseDirectories:NO]; @@ -1775,31 +1370,29 @@ { sourceDirectory = [[NSURL fileURLWithPath:NSHomeDirectory()] URLByAppendingPathComponent:@"Desktop"]; } - /* we open up the browse sources sheet here and call for browseSourcesDone after the sheet is closed - * to evaluate whether we want to specify a title, we pass the sender in the contextInfo variable - */ - /* set this for allowed file types, not sure if we should allow xml or not */ + + // set this for allowed file types, not sure if we should allow xml or not. [panel setDirectoryURL:sourceDirectory]; - [panel beginSheetModalForWindow:fWindow completionHandler:^(NSInteger result) + [panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) { NSURL *importPresetsFile = [panel URL]; NSURL *importPresetsDirectory = nil;//[importPresetsFile URLByDeletingLastPathComponent]; [[NSUserDefaults standardUserDefaults] setURL:importPresetsDirectory forKey:@"LastPresetImportDirectoryURL"]; - /* NOTE: here we need to do some sanity checking to verify we do not hose up our presets file */ + // NOTE: here we need to do some sanity checking to verify we do not hose up our presets file NSMutableArray *presetsToImport = [[NSMutableArray alloc] initWithContentsOfURL:importPresetsFile]; - /* iterate though the new array of presets to import and add them to our presets array */ - for (NSMutableDictionary *tempObject in presetsToImport) + // iterate though the new array of presets to import and add them to our presets array + for (NSMutableDictionary *dict in presetsToImport) { - /* make any changes to the incoming preset we see fit */ - /* make sure the incoming preset is not tagged as default */ - [tempObject setObject:[NSNumber numberWithInt:0] forKey:@"Default"]; - /* prepend "(imported) to the name of the incoming preset for clarification since it can be changed */ - NSString *prependedName = [@"(import) " stringByAppendingString:[tempObject objectForKey:@"PresetName"]] ; - [tempObject setObject:prependedName forKey:@"PresetName"]; - - /* actually add the new preset to our presets array */ - [presetManager addPresetFromDictionary:tempObject]; + // make any changes to the incoming preset we see fit + // make sure the incoming preset is not tagged as default + dict[@"Default"] = @0; + // prepend "(imported) to the name of the incoming preset for clarification since it can be changed + NSString *prependedName = [@"(import) " stringByAppendingString:dict[@"PresetName"]] ; + dict[@"PresetName"] = prependedName; + + // actually add the new preset to our presets array + [presetManager addPresetFromDictionary:dict]; } [presetsToImport autorelease]; }]; @@ -1828,69 +1421,4 @@ [fPresetsView setSelection:preset]; } -/** - * Adds the presets list to the menu. - */ -- (void)buildPresetsMenu -{ - // First we remove all the preset menu items - // inserted previosly - NSArray *menuItems = [presetsMenu.itemArray copy]; - for (NSMenuItem *item in menuItems) - { - if (item.tag != -1) - { - [presetsMenu removeItem:item]; - } - } - [menuItems release]; - - __block NSUInteger i = 0; - __block BOOL builtInEnded = NO; - [presetManager.root enumerateObjectsUsingBlock:^(id obj, NSIndexPath *idx, BOOL *stop) - { - if (idx.length) - { - NSMenuItem *item = [[NSMenuItem alloc] init]; - item.title = [obj name]; - item.tag = i++; - - // Set an action only to the actual presets, - // not on the folders. - if ([obj isLeaf]) - { - item.action = @selector(selectPresetFromMenu:); - item.representedObject = obj; - } - // Make the default preset font bold. - if ([obj isDefault]) - { - NSAttributedString *newTitle = [[NSAttributedString alloc] initWithString:[obj name] - attributes:@{NSFontAttributeName: [NSFont boldSystemFontOfSize:14]}]; - [item setAttributedTitle:newTitle]; - [newTitle release]; - } - // Add a separator line after the last builtIn preset - if ([obj isBuiltIn] == NO && builtInEnded == NO) - { - [presetsMenu addItem:[NSMenuItem separatorItem]]; - builtInEnded = YES; - } - - item.indentationLevel = idx.length - 1; - - [presetsMenu addItem:item]; - [item release]; - } - }]; -} - -/** - * We use this method to recreate new, updated factory presets - */ -- (IBAction)addFactoryPresets:(id)sender -{ - [presetManager generateBuiltInPresets]; -} - @end diff --git a/macosx/English.lproj/MainMenu.xib b/macosx/English.lproj/MainMenu.xib index 5675c4a56..112c27a1f 100644 --- a/macosx/English.lproj/MainMenu.xib +++ b/macosx/English.lproj/MainMenu.xib @@ -1,5 +1,5 @@ - + @@ -8,637 +8,11 @@ - + - - - - - - - - - - - - - - - - - DO NOT TRANSLATE THIS NIB FILE, - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - NSIsNotNil - - - - - - - - - - - - - - - - NSIsNotNil - - - - - - - - - - - - - - - - - - - NSNegateBoolean - - - - - - - - - - - - - - - - - - - - - NSIsNotNil - - - - - - NSNegateBoolean - - - - - - - - - - - - - - - - - - - - - - - - - - - - NSIsNil - - - - - - - - - - - - - - - - NSIsNil - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - NSIsNotNil - - - - - HBContainerTransformer - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - NSIsNotNil - - - - - - HBURLTransformer - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - NSIsNil - - - - - - - - - - - - - - - - - - - - - - - NSNegateBoolean - - - - - - - - - - - - - - - - - - - - - - - NSNegateBoolean - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -660,7 +34,7 @@ - + @@ -704,12 +78,7 @@ - - - - - - + @@ -725,12 +94,12 @@ - + - + @@ -738,12 +107,12 @@ - + - + @@ -875,7 +244,7 @@ - + @@ -888,7 +257,7 @@ - + @@ -897,18 +266,18 @@ - + - + - + @@ -935,12 +304,12 @@ - + - + @@ -948,23 +317,23 @@ - + - + - + - + @@ -975,17 +344,17 @@ - + - + - + @@ -993,161 +362,12 @@ - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - diff --git a/macosx/English.lproj/MainWindow.xib b/macosx/English.lproj/MainWindow.xib new file mode 100644 index 000000000..1ecae028c --- /dev/null +++ b/macosx/English.lproj/MainWindow.xib @@ -0,0 +1,724 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + DO NOT TRANSLATE THIS NIB FILE, + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NSIsNotNil + + + + + + + + + + + + + + + + NSIsNotNil + + + + + + + + + + + + + + + + + + + NSNegateBoolean + + + + + + + + + + + + + + + + + + + + + NSIsNotNil + + + + + + NSNegateBoolean + + + + + + + + + + + + + + + + + + + + + + + + + + + + NSIsNil + + + + + + + + + + + + + + + + NSIsNil + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NSIsNotNil + + + + + HBContainerTransformer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NSIsNotNil + + + + + + HBURLTransformer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + NSIsNil + + + + + + + + + + + + + + + + + + + + + + + NSNegateBoolean + + + + + + + + + + + + + + + + + + + + + + + NSNegateBoolean + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macosx/English.lproj/Preferences.xib b/macosx/English.lproj/Preferences.xib index c2e0f97c5..f6abd81a0 100644 --- a/macosx/English.lproj/Preferences.xib +++ b/macosx/English.lproj/Preferences.xib @@ -1,9 +1,9 @@ - + - + @@ -49,7 +49,6 @@ - @@ -212,13 +211,13 @@ - + - - + + diff --git a/macosx/HBAppDelegate.h b/macosx/HBAppDelegate.h new file mode 100644 index 000000000..a115696e7 --- /dev/null +++ b/macosx/HBAppDelegate.h @@ -0,0 +1,14 @@ +/* HBAppDelegate.h $ + + This file is part of the HandBrake source code. + Homepage: . + It may be used under the terms of the GNU General Public License. */ + +#import + +@interface HBAppDelegate : NSObject + +- (IBAction)showPreferencesWindow:(id)sender; +- (IBAction)showOutputPanel:(id)sender; + +@end diff --git a/macosx/HBAppDelegate.m b/macosx/HBAppDelegate.m new file mode 100644 index 000000000..09b294b9d --- /dev/null +++ b/macosx/HBAppDelegate.m @@ -0,0 +1,482 @@ +/* HBAppDelegate.m $ + + This file is part of the HandBrake source code. + Homepage: . + It may be used under the terms of the GNU General Public License. */ + +#import "HBAppDelegate.h" + +#import "HBUtilities.h" +#import "HBPresetsManager.h" +#import "HBPreset.h" + +#import "HBPreferencesController.h" +#import "HBQueueController.h" +#import "HBOutputPanelController.h" +#import "HBCore.h" +#import "Controller.h" + +static void hb_error_handler(const char *errmsg) +{ + NSString *error = @(errmsg); + + if (error && [[NSUserDefaults standardUserDefaults] boolForKey:@"HBDebugAlert"]) + { + dispatch_async(dispatch_get_main_queue(), ^{ + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:NSLocalizedString(@"Internal Error.", @"")]; + [alert runModal]; + [alert release]; + }); + } + + fprintf(stderr, "error: %s\n", errmsg); +} + +@interface HBAppDelegate () + +@property (nonatomic, retain) HBPresetsManager *presetsManager; +@property (assign) IBOutlet NSMenu *presetsMenu; + +@property (nonatomic, retain) HBPreferencesController *preferencesController; +@property (nonatomic, retain) HBQueueController *queueController; + +@property (nonatomic, retain) HBOutputPanelController *outputPanel; + +@property (nonatomic, retain) HBController *mainController; + +@end + +@implementation HBAppDelegate + +- (instancetype)init +{ + self = [super init]; + if (self) + { + hb_global_init(); + hb_register_error_handler(&hb_error_handler); + + // Optionally use dvd nav + [HBCore setDVDNav:[[[NSUserDefaults standardUserDefaults] objectForKey:@"UseDvdNav"] boolValue]]; + + // Register the defaults preferences + [HBPreferencesController registerUserDefaults]; + + _outputPanel = [[HBOutputPanelController alloc] init]; + + // Lets report the HandBrake version number here to the activity log and text log file + NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary]; + NSString *versionStringFull = [NSString stringWithFormat:@"Handbrake Version: %@ (%@)", infoDict[@"CFBundleShortVersionString"], infoDict[@"CFBundleVersion"]]; + [HBUtilities writeToActivityLog: "%s", versionStringFull.UTF8String]; + + // we init the HBPresetsManager + NSURL *presetsURL = [NSURL fileURLWithPath:[[HBUtilities appSupportPath] stringByAppendingPathComponent:@"UserPresets.plist"]]; + _presetsManager = [[HBPresetsManager alloc] initWithURL:presetsURL]; + + _queueController = [[HBQueueController alloc] init]; + _queueController.outputPanel = _outputPanel; + _queueController.delegate = self; + _mainController = [[HBController alloc] initWithQueue:_queueController presetsManager:_presetsManager]; + + // Set the Growl Delegate + [GrowlApplicationBridge setGrowlDelegate:_queueController]; + } + return self; +} + +#pragma mark - NSApplicationDelegate + +- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag +{ + if (!flag) + { + [self.mainController showWindow:nil]; + } + return YES; +} + +- (void)applicationDidFinishLaunching:(NSNotification *)notification +{ + // Updates built-ins presets if needed + [self checkBuiltInsForUpdates]; + [self buildPresetsMenu]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(buildPresetsMenu) name:HBPresetsChangedNotification object:nil]; + + // Get the number of HandBrake instances currently running + NSUInteger instances = [NSRunningApplication runningApplicationsWithBundleIdentifier:[[NSBundle mainBundle] bundleIdentifier]].count; + + // If we are a single instance it is safe to clean up the previews if there are any + // left over. This is a bit of a kludge but will prevent a build up of old instance + // live preview cruft. No danger of removing an active preview directory since they + // are created later in HBPreviewController if they don't exist at the moment a live + // preview encode is initiated. + if (instances == 1) + { + NSString *previewDirectory = [[HBUtilities appSupportPath] stringByAppendingPathComponent:@"Previews"]; + NSError *error = nil; + NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:previewDirectory error:&error]; + for (NSString *file in files) + { + BOOL result = [[NSFileManager defaultManager] removeItemAtPath:[previewDirectory stringByAppendingPathComponent:file] error:&error]; + if (result == NO && error) + { + [HBUtilities writeToActivityLog: "Could not remove existing preview at : %s", file.UTF8String]; + } + } + } + + [self showMainWindow:self]; + + // Now we re-check the queue array to see if there are + // any remaining encodes to be done in it and ask the + // user if they want to reload the queue + if (self.queueController.count) + { + // On Screen Notification + // We check to see if there is already another instance of hb running. + // Note: hbInstances == 1 means we are the only instance of HandBrake.app + NSAlert *alert = nil; + if (instances > 1) + { + alert = [[NSAlert alloc] init]; + [alert setMessageText:NSLocalizedString(@"There is already an instance of HandBrake running.", @"")]; + [alert setInformativeText:NSLocalizedString(@"HandBrake will now load up the existing queue.", nil)]; + [alert addButtonWithTitle:NSLocalizedString(@"Reload Queue", nil)]; + } + else + { + if (self.queueController.workingItemsCount > 0 || self.queueController.pendingItemsCount > 0) + { + NSString *alertTitle; + + if (self.queueController.workingItemsCount > 0) + { + alertTitle = [NSString stringWithFormat: + NSLocalizedString(@"HandBrake Has Detected %d Previously Encoding Item(s) and %d Pending Item(s) In Your Queue.", @""), + self.queueController.workingItemsCount, self.queueController.pendingItemsCount]; + } + else + { + alertTitle = [NSString stringWithFormat: + NSLocalizedString(@"HandBrake Has Detected %d Pending Item(s) In Your Queue.", @""), + self.queueController.pendingItemsCount]; + } + + alert = [[NSAlert alloc] init]; + [alert setMessageText:alertTitle]; + [alert setInformativeText:NSLocalizedString(@"Do you want to reload them ?", nil)]; + [alert addButtonWithTitle:NSLocalizedString(@"Reload Queue", nil)]; + [alert addButtonWithTitle:NSLocalizedString(@"Empty Queue", nil)]; + [alert setAlertStyle:NSCriticalAlertStyle]; + } + else + { + // Since we addressed any pending or previously encoding items above, we go ahead and make sure + // the queue is empty of any finished items or cancelled items. + [self.queueController removeAllJobs]; + [self.mainController launchAction]; + } + } + + if (alert) + { + NSModalResponse response = [alert runModal]; + + if (response == NSAlertSecondButtonReturn) + { + [HBUtilities writeToActivityLog:"didDimissReloadQueue NSAlertSecondButtonReturn Chosen"]; + [self.queueController removeAllJobs]; + [self.mainController launchAction]; + } + else + { + [HBUtilities writeToActivityLog:"didDimissReloadQueue NSAlertFirstButtonReturn Chosen"]; + if (instances == 1) + { + [self.queueController setEncodingJobsAsPending]; + } + + [self showQueueWindow:nil]; + } + + [alert release]; + } + } + else + { + [self.mainController launchAction]; + } + + // Open debug output window now if it was visible when HB was closed + if ([[NSUserDefaults standardUserDefaults] boolForKey:@"OutputPanelIsOpen"]) + [self showOutputPanel:nil]; + + // Open queue window now if it was visible when HB was closed + if ([[NSUserDefaults standardUserDefaults] boolForKey:@"QueueWindowIsOpen"]) + [self showQueueWindow:nil]; +} + +- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)app +{ + if (self.queueController.core.state != HBStateIdle) + { + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:NSLocalizedString(@"Are you sure you want to quit HandBrake?", nil)]; + [alert setInformativeText:NSLocalizedString(@"If you quit HandBrake your current encode will be reloaded into your queue at next launch. Do you want to quit anyway?", nil)]; + [alert addButtonWithTitle:NSLocalizedString(@"Quit", nil)]; + [alert addButtonWithTitle:NSLocalizedString(@"Don't Quit", nil)]; + [alert setAlertStyle:NSCriticalAlertStyle]; + + NSInteger result = [alert runModal]; + [alert release]; + + if (result == NSAlertFirstButtonReturn) + { + return NSTerminateNow; + } + else + { + return NSTerminateCancel; + } + } + + // Warn if items still in the queue + else if (self.queueController.pendingItemsCount > 0) + { + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:NSLocalizedString(@"Are you sure you want to quit HandBrake?", nil)]; + [alert setInformativeText:NSLocalizedString(@"There are pending encodes in your queue. Do you want to quit anyway?",nil)]; + [alert addButtonWithTitle:NSLocalizedString(@"Quit", nil)]; + [alert addButtonWithTitle:NSLocalizedString(@"Don't Quit", nil)]; + [alert setAlertStyle:NSCriticalAlertStyle]; + NSInteger result = [alert runModal]; + [alert release]; + if (result == NSAlertFirstButtonReturn) + { + return NSTerminateNow; + } + else + { + return NSTerminateCancel; + } + } + + return NSTerminateNow; +} + +- (void)applicationWillTerminate:(NSNotification *)notification +{ + [self.presetsManager savePresets]; + + [_mainController release]; + _mainController = nil; + [_queueController release]; + _queueController = nil; + + [HBCore closeGlobal]; +} + +- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames +{ + [self.mainController openFile:[NSURL fileURLWithPath:filenames.firstObject]]; + [NSApp replyToOpenOrPrint:NSApplicationDelegateReplySuccess]; +} + +- (BOOL)validateMenuItem:(NSMenuItem *)menuItem +{ + SEL action = menuItem.action; + + if (action == @selector(rip:) || action == @selector(pause:)) + { + // Delegate the validation to the queue controller + return [self.queueController validateMenuItem:menuItem]; + } + else if (action == @selector(showPicturePanel:) || action == @selector(showAddPresetPanel:) || + action == @selector(showPreviewWindow:) || action == @selector(browseSources:)) + { + // Delegate the validation to the main controller + return [self.mainController validateMenuItem:menuItem]; + } + + return YES; +} + +#pragma mark - Menu actions + +- (IBAction)rip:(id)sender +{ + [self.queueController rip:self]; +} + +- (IBAction)pause:(id)sender +{ + [self.queueController togglePauseResume:self]; +} + +- (IBAction)browseSources:(id)sender +{ + [self.mainController browseSources:self]; +} + +#pragma mark - Presets Menu actions + +- (void)checkBuiltInsForUpdates +{ + // if we have built in presets to update, then do so AlertBuiltInPresetUpdate + if ([self.presetsManager checkBuiltInsForUpdates]) + { + if( [[NSUserDefaults standardUserDefaults] boolForKey:@"AlertBuiltInPresetUpdate"] == YES) + { + // Show an alert window that built in presets will be updated + [NSApp requestUserAttention:NSCriticalRequest]; + NSAlert *alert = [[NSAlert alloc] init]; + [alert setMessageText:@"HandBrake has determined your built in presets are out of date…"]; + [alert setInformativeText:@"HandBrake will now update your built-in presets."]; + [alert runModal]; + [alert release]; + } + // when alert is dismissed, go ahead and update the built in presets + [self.presetsManager generateBuiltInPresets]; + } +} + +/** + * Adds the presets list to the menu. + */ +- (void)buildPresetsMenu +{ + // First we remove all the preset menu items + // inserted previosly + NSArray *menuItems = [self.presetsMenu.itemArray copy]; + for (NSMenuItem *item in menuItems) + { + if (item.tag != -1) + { + [self.presetsMenu removeItem:item]; + } + } + [menuItems release]; + + __block NSUInteger i = 0; + __block BOOL builtInEnded = NO; + [self.presetsManager.root enumerateObjectsUsingBlock:^(id obj, NSIndexPath *idx, BOOL *stop) + { + if (idx.length) + { + NSMenuItem *item = [[NSMenuItem alloc] init]; + item.title = [obj name]; + item.tag = i++; + + // Set an action only to the actual presets, + // not on the folders. + if ([obj isLeaf]) + { + item.action = @selector(selectPresetFromMenu:); + item.representedObject = obj; + } + // Make the default preset font bold. + if ([obj isDefault]) + { + NSAttributedString *newTitle = [[NSAttributedString alloc] initWithString:[obj name] + attributes:@{NSFontAttributeName: [NSFont boldSystemFontOfSize:14]}]; + [item setAttributedTitle:newTitle]; + [newTitle release]; + } + // Add a separator line after the last builtIn preset + if ([obj isBuiltIn] == NO && builtInEnded == NO) + { + [self.presetsMenu addItem:[NSMenuItem separatorItem]]; + builtInEnded = YES; + } + + item.indentationLevel = idx.length - 1; + + [self.presetsMenu addItem:item]; + [item release]; + } + }]; +} + +/** + * We use this method to recreate new, updated factory presets + */ +- (IBAction)addFactoryPresets:(id)sender +{ + [self.presetsManager generateBuiltInPresets]; +} + +#pragma mark - Show Window Menu Items + +/** + * Shows preferences window. + */ +- (IBAction)showPreferencesWindow:(id)sender +{ + if (_preferencesController == nil) + { + _preferencesController = [[HBPreferencesController alloc] init]; + } + + NSWindow *window = [_preferencesController window]; + if (![window isVisible]) + { + [window center]; + } + + [window makeKeyAndOrderFront:nil]; +} + +/** + * Shows queue window. + */ +- (IBAction)showQueueWindow:(id)sender +{ + [self.queueController showWindow:sender]; +} + +/** + * Shows debug output window. + */ +- (IBAction)showOutputPanel:(id)sender +{ + [self.outputPanel showOutputPanel:sender]; +} + +- (IBAction)showPicturePanel:(id)sender +{ + [self.mainController showPicturePanel:self]; +} + +- (IBAction)showPreviewWindow:(id)sender +{ + [self.mainController showPreviewWindow:self]; +} + +/** + * Shows main window. + */ +- (IBAction)showMainWindow:(id)sender +{ + [self.mainController showWindow:sender]; +} + +- (IBAction)openHomepage:(id)sender +{ + [[NSWorkspace sharedWorkspace] openURL:[NSURL + URLWithString:@"http://handbrake.fr/"]]; +} + +- (IBAction)openForums:(id)sender +{ + [[NSWorkspace sharedWorkspace] openURL:[NSURL + URLWithString:@"http://forum.handbrake.fr/"]]; +} +- (IBAction)openUserGuide:(id)sender +{ + [[NSWorkspace sharedWorkspace] openURL:[NSURL + URLWithString:@"http://trac.handbrake.fr/wiki/HandBrakeGuide"]]; +} + +@end diff --git a/macosx/HBQueueController.h b/macosx/HBQueueController.h index 73cdc2a21..0a48dff66 100644 --- a/macosx/HBQueueController.h +++ b/macosx/HBQueueController.h @@ -7,6 +7,7 @@ #import #import +@class HBAppDelegate; @class HBController; @class HBOutputPanelController; @class HBCore; @@ -18,6 +19,7 @@ @property (nonatomic, readonly) HBCore *core; @property (nonatomic, assign) HBController *controller; +@property (nonatomic, assign) HBAppDelegate *delegate; @property (nonatomic, assign) HBOutputPanelController *outputPanel; @property (nonatomic, readonly) NSUInteger count; @@ -35,4 +37,6 @@ - (IBAction)rip:(id)sender; - (IBAction)cancelRip:(id)sender; +- (IBAction)togglePauseResume:(id)sender; + @end diff --git a/macosx/HBQueueController.mm b/macosx/HBQueueController.mm index b835599a9..1a8712653 100644 --- a/macosx/HBQueueController.mm +++ b/macosx/HBQueueController.mm @@ -9,6 +9,7 @@ #import "HBCore.h" #import "Controller.h" +#import "HBAppDelegate.h" #import "HBOutputPanelController.h" #import "HBQueueOutlineView.h" @@ -136,6 +137,45 @@ #pragma mark Toolbar +- (BOOL)validateMenuItem:(NSMenuItem *)menuItem +{ + SEL action = menuItem.action; + + if (action == @selector(rip:)) + { + if (self.core.state == HBStateIdle) + { + menuItem.title = NSLocalizedString(@"Start Encoding", nil); + menuItem.keyEquivalent = @"s"; + + return (self.pendingItemsCount > 0); + } + else if (self.core.state != HBStateIdle) + { + menuItem.title = NSLocalizedString(@"Stop Encoding", nil); + menuItem.keyEquivalent = @"."; + + return YES; + } + } + + if (action == @selector(pause:)) + { + if (self.core.state != HBStatePaused) + { + menuItem.title = NSLocalizedString(@"Pause Encoding", nil); + } + else + { + menuItem.title = NSLocalizedString(@"Resume Encoding", nil); + } + + return (self.core.state == HBStateWorking || self.core.state == HBStatePaused); + } + + return YES; +} + - (BOOL)validateToolbarItem:(NSToolbarItem *)theItem { SEL action = theItem.action; @@ -898,7 +938,7 @@ NSInteger response = [alert runModal]; if (response == NSAlertSecondButtonReturn) { - [self.controller showPreferencesWindow:nil]; + [self.delegate showPreferencesWindow:nil]; } [alert release]; } @@ -917,7 +957,7 @@ NSInteger response = [alert runModal]; if (response == NSAlertSecondButtonReturn) { - [self.controller showPreferencesWindow:nil]; + [self.delegate showPreferencesWindow:nil]; } [alert release]; } diff --git a/macosx/HandBrake.xcodeproj/project.pbxproj b/macosx/HandBrake.xcodeproj/project.pbxproj index 48805d713..6410bdb02 100644 --- a/macosx/HandBrake.xcodeproj/project.pbxproj +++ b/macosx/HandBrake.xcodeproj/project.pbxproj @@ -127,6 +127,8 @@ A9204DC51A16C5AB007CA74C /* Delete@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A9204DC21A16C5AB007CA74C /* Delete@2x.png */; }; A9204DC61A16C5AB007CA74C /* DeleteHighlightPressed@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A9204DC31A16C5AB007CA74C /* DeleteHighlightPressed@2x.png */; }; A9204DC71A16C5AB007CA74C /* DeletePressed@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A9204DC41A16C5AB007CA74C /* DeletePressed@2x.png */; }; + A92268781A6E555500A8D5C5 /* HBAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A92268771A6E555500A8D5C5 /* HBAppDelegate.m */; }; + A922687B1A6E569B00A8D5C5 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = A92268791A6E569B00A8D5C5 /* MainWindow.xib */; }; A9252C041A17343500B8B7F8 /* DeleteHighlight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A9252C031A17343500B8B7F8 /* DeleteHighlight@2x.png */; }; A9252C091A173D4800B8B7F8 /* Reveal@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A9252C051A173D4800B8B7F8 /* Reveal@2x.png */; }; A9252C0A1A173D4800B8B7F8 /* RevealHighlight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A9252C061A173D4800B8B7F8 /* RevealHighlight@2x.png */; }; @@ -375,6 +377,9 @@ A9204DC21A16C5AB007CA74C /* Delete@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Delete@2x.png"; sourceTree = ""; }; A9204DC31A16C5AB007CA74C /* DeleteHighlightPressed@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "DeleteHighlightPressed@2x.png"; sourceTree = ""; }; A9204DC41A16C5AB007CA74C /* DeletePressed@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "DeletePressed@2x.png"; sourceTree = ""; }; + A92268761A6E555500A8D5C5 /* HBAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HBAppDelegate.h; sourceTree = ""; }; + A92268771A6E555500A8D5C5 /* HBAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HBAppDelegate.m; sourceTree = ""; }; + A922687A1A6E569B00A8D5C5 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = MainWindow.xib; sourceTree = ""; }; A9252C031A17343500B8B7F8 /* DeleteHighlight@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "DeleteHighlight@2x.png"; sourceTree = ""; }; A9252C051A173D4800B8B7F8 /* Reveal@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Reveal@2x.png"; sourceTree = ""; }; A9252C061A173D4800B8B7F8 /* RevealHighlight@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "RevealHighlight@2x.png"; sourceTree = ""; }; @@ -789,6 +794,7 @@ children = ( 273F217C14ADDDA10021BE6D /* InfoPlist.strings */, 273F217E14ADDDA10021BE6D /* MainMenu.xib */, + A92268791A6E569B00A8D5C5 /* MainWindow.xib */, A9CF25EF1990D62C0023F727 /* Presets.xib */, A9E2FD291A21BC6F000E8D3F /* AddPreset.xib */, A93E0ED51972958C00FD67FB /* Video.xib */, @@ -958,6 +964,8 @@ A9B34D6F197683FE00871B7D /* Controllers */ = { isa = PBXGroup; children = ( + A92268761A6E555500A8D5C5 /* HBAppDelegate.h */, + A92268771A6E555500A8D5C5 /* HBAppDelegate.m */, 273F208E14ADBE670021BE6D /* Controller.h */, 273F208F14ADBE670021BE6D /* Controller.m */, A9B34D701976841800871B7D /* Main Window View Controllers */, @@ -1150,6 +1158,7 @@ 273F218E14ADDDA10021BE6D /* PicturePreview.xib in Resources */, 273F218F14ADDDA10021BE6D /* PictureSettings.xib in Resources */, 273F219014ADDDA10021BE6D /* Preferences.xib in Resources */, + A922687B1A6E569B00A8D5C5 /* MainWindow.xib in Resources */, 273F219114ADDDA10021BE6D /* Queue.xib in Resources */, 3490BCB41614CF8D002A5AD7 /* HandBrake.icns in Resources */, A9E1468016BC2AD800C307BC /* next-p.pdf in Resources */, @@ -1223,6 +1232,7 @@ A98C29C41977B10600AF5DED /* HBLanguagesSelection.m in Sources */, A9BB0F2719A0ECE40079F1C1 /* HBHUDButtonCell.m in Sources */, A932E273198834130047D13E /* HBAudioDefaults.m in Sources */, + A92268781A6E555500A8D5C5 /* HBAppDelegate.m in Sources */, A91806711A4807B000FC9BED /* HBRange.m in Sources */, A9DEC8771A23C88D00C79B48 /* HBVideo.m in Sources */, A9523937199A6AAE00588AEF /* HBFilters.m in Sources */, @@ -1353,6 +1363,14 @@ name = Queue.xib; sourceTree = ""; }; + A92268791A6E569B00A8D5C5 /* MainWindow.xib */ = { + isa = PBXVariantGroup; + children = ( + A922687A1A6E569B00A8D5C5 /* English */, + ); + name = MainWindow.xib; + sourceTree = ""; + }; A932E26A1988334B0047D13E /* AudioDefaults.xib */ = { isa = PBXVariantGroup; children = ( diff --git a/macosx/main.mm b/macosx/main.mm index 1d7d6ed69..961d1fa78 100644 --- a/macosx/main.mm +++ b/macosx/main.mm @@ -5,24 +5,6 @@ It may be used under the terms of the GNU General Public License. */ #import -#include "hb.h" - -static void hb_error_handler(const char *errmsg) -{ - NSString *error = @(errmsg); - - if (error && [[NSUserDefaults standardUserDefaults] boolForKey:@"HBDebugAlert"]) - { - dispatch_async(dispatch_get_main_queue(), ^{ - NSAlert *alert = [[NSAlert alloc] init]; - [alert setMessageText:NSLocalizedString(@"Internal Error.", @"")]; - [alert runModal]; - [alert release]; - }); - } - - fprintf(stderr, "error: %s\n", errmsg); -} int main(int argc, const char **argv) { @@ -39,8 +21,5 @@ int main(int argc, const char **argv) action.sa_handler = SIG_IGN; sigaction(SIGINT, &action, NULL); - hb_global_init(); - hb_register_error_handler(&hb_error_handler); - return NSApplicationMain(argc, argv); }