X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=macosx%2FController.mm;h=6ca4fdca2e3800fc78afa6685e5caf7bd097ddcb;hb=2d8b7ab0d3a16806f4c24870489b5f4b97afd0cf;hp=b2ddff7a5c1fcb1e4c24c72da9448fc6e6f14334;hpb=84f02ecb20bc560845994b666cf00a5eb3fbf8d9;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/macosx/Controller.mm b/macosx/Controller.mm index b2ddff7a..6ca4fdca 100644 --- a/macosx/Controller.mm +++ b/macosx/Controller.mm @@ -9,15 +9,18 @@ #import "HBPreferencesController.h" #import "HBDVDDetector.h" #import "HBPresets.h" +#import "HBPreviewController.h" #define DragDropSimplePboardType @"MyCustomOutlineViewPboardType" -/* We setup the toolbar values here */ +/* We setup the toolbar values here ShowPreviewIdentifier */ static NSString * ToggleDrawerIdentifier = @"Toggle Drawer Item Identifier"; static NSString * StartEncodingIdentifier = @"Start Encoding Item Identifier"; static NSString * PauseEncodingIdentifier = @"Pause Encoding Item Identifier"; static NSString * ShowQueueIdentifier = @"Show Queue Item Identifier"; static NSString * AddToQueueIdentifier = @"Add to Queue Item Identifier"; +static NSString * ShowPictureIdentifier = @"Show Picture Window Item Identifier"; +static NSString * ShowPreviewIdentifier = @"Show Preview Window Item Identifier"; static NSString * ShowActivityIdentifier = @"Debug Output Item Identifier"; static NSString * ChooseSourceIdentifier = @"Choose Source Item Identifier"; @@ -34,6 +37,15 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It { return nil; } + + /* replace bundled app icon with one which is 32/64-bit savvy */ +#if defined( __LP64__ ) + fApplicationIcon = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForImageResource:@"HandBrake-64.icns"]]; +#else + fApplicationIcon = [[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForImageResource:@"HandBrake.icns"]]; +#endif + if( fApplicationIcon != nil ) + [NSApp setApplicationIconImage:fApplicationIcon]; [HBPreferencesController registerUserDefaults]; fHandle = NULL; @@ -59,7 +71,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It attributes:nil]; } outputPanel = [[HBOutputPanelController alloc] init]; - fPictureController = [[PictureController alloc] initWithDelegate:self]; + fPictureController = [[PictureController alloc] init]; fQueueController = [[HBQueueController alloc] init]; fAdvancedOptions = [[HBAdvancedController alloc] init]; /* we init the HBPresets class which currently is only used @@ -69,7 +81,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It fPresetsBuiltin = [[HBPresets alloc] init]; fPreferencesController = [[HBPreferencesController alloc] init]; /* Lets report the HandBrake version number here to the activity log and text log file */ - NSString *versionStringFull = [[NSString stringWithFormat: @"Handbrake Version: %@", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleGetInfoString"]] stringByAppendingString: [NSString stringWithFormat: @" (%@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]]]; + NSString *versionStringFull = [[NSString stringWithFormat: @"Handbrake Version: %@", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]] stringByAppendingString: [NSString stringWithFormat: @" (%@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]]]; [self writeToActivityLog: "%s", [versionStringFull UTF8String]]; return self; @@ -81,6 +93,8 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It /* Init libhb with check for updates libhb style set to "0" so its ignored and lets sparkle take care of it */ int loggingLevel = [[[NSUserDefaults standardUserDefaults] objectForKey:@"LoggingLevel"] intValue]; fHandle = hb_init(loggingLevel, 0); + /* Optional dvd nav UseDvdNav*/ + hb_dvd_set_dvdnav([[[NSUserDefaults standardUserDefaults] objectForKey:@"UseDvdNav"] boolValue]); /* Init a separate instance of libhb for user scanning and setting up jobs */ fQueueEncodeLibhb = hb_init(loggingLevel, 0); @@ -88,18 +102,31 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [GrowlApplicationBridge setGrowlDelegate: self]; /* Init others controllers */ [fPictureController SetHandle: fHandle]; + [fPictureController setHBController: self]; + [fQueueController setHandle: fQueueEncodeLibhb]; [fQueueController setHBController: self]; fChapterTitlesDelegate = [[ChapterTitles alloc] init]; [fChapterTable setDataSource:fChapterTitlesDelegate]; [fChapterTable setDelegate:fChapterTitlesDelegate]; + + /* setup the subtitles delegate and connections to table */ + fSubtitlesDelegate = [[HBSubtitles alloc] init]; + [fSubtitlesTable setDataSource:fSubtitlesDelegate]; + [fSubtitlesTable setDelegate:fSubtitlesDelegate]; + [fSubtitlesTable setRowHeight:25.0]; + + [fPresetsOutlineView setAutosaveName:@"Presets View"]; + [fPresetsOutlineView setAutosaveExpandedItems:YES]; + + dockIconProgress = 0; /* Call UpdateUI every 1/2 sec */ [[NSRunLoop currentRunLoop] addTimer:[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(updateUI:) userInfo:nil repeats:YES] - forMode:NSEventTrackingRunLoopMode]; + forMode:NSDefaultRunLoopMode]; // Open debug output window now if it was visible when HB was closed if ([[NSUserDefaults standardUserDefaults] boolForKey:@"OutputPanelIsOpen"]) @@ -133,57 +160,122 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It /*On Screen Notification*/ NSString * alertTitle; - if (fWorkingCount > 0) + + /* 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 + */ + if ([self hbInstances] > 1) { - alertTitle = [NSString stringWithFormat: - NSLocalizedString(@"HandBrake Has Detected %d Previously Encoding Item and %d Pending Item(s) In Your Queue.", @""), - fWorkingCount,fPendingCount]; + alertTitle = [NSString stringWithFormat: + NSLocalizedString(@"There is already an instance of HandBrake running.", @"")]; + NSBeginCriticalAlertSheet( + alertTitle, + NSLocalizedString(@"Reload Queue", nil), + nil, + nil, + fWindow, self, + nil, @selector(didDimissReloadQueue:returnCode:contextInfo:), nil, + NSLocalizedString(@" HandBrake will now load up the existing queue.", nil)); } else { - alertTitle = [NSString stringWithFormat: - NSLocalizedString(@"HandBrake Has Detected %d Pending Item(s) In Your Queue.", @""), - fPendingCount]; + if (fWorkingCount > 0) + { + alertTitle = [NSString stringWithFormat: + NSLocalizedString(@"HandBrake Has Detected %d Previously Encoding Item and %d Pending Item(s) In Your Queue.", @""), + fWorkingCount,fPendingCount]; + } + else + { + alertTitle = [NSString stringWithFormat: + NSLocalizedString(@"HandBrake Has Detected %d Pending Item(s) In Your Queue.", @""), + fPendingCount]; + } + + NSBeginCriticalAlertSheet( + alertTitle, + NSLocalizedString(@"Reload Queue", nil), + nil, + NSLocalizedString(@"Empty Queue", nil), + fWindow, self, + nil, @selector(didDimissReloadQueue:returnCode:contextInfo:), nil, + NSLocalizedString(@" Do you want to reload them ?", nil)); } - NSBeginCriticalAlertSheet( - alertTitle, - NSLocalizedString(@"Reload Queue", nil), - nil, - NSLocalizedString(@"Empty Queue", nil), - fWindow, self, - nil, @selector(didDimissReloadQueue:returnCode:contextInfo:), nil, - NSLocalizedString(@" Do you want to reload them ?", nil)); + // call didDimissReloadQueue: (NSWindow *)sheet returnCode: (int)returnCode contextInfo: (void *)contextInfo // right below to either clear the old queue or keep it loaded up. } else { + /* We show whichever open source window specified in LaunchSourceBehavior preference key */ + if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"LaunchSourceBehavior"] isEqualToString: @"Open Source"]) + { + [self browseSources:nil]; + } - /* Show Browse Sources Window ASAP */ - [self performSelectorOnMainThread:@selector(browseSources:) - withObject:nil waitUntilDone:NO]; + if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"LaunchSourceBehavior"] isEqualToString: @"Open Source (Title Specific)"]) + { + [self browseSources:(id)fOpenSourceTitleMMenu]; + } } } +- (int) hbInstances +{ + /* check to see if another instance of HandBrake.app is running */ + NSArray *runningAppDictionaries = [[NSWorkspace sharedWorkspace] launchedApplications]; + NSDictionary *aDictionary; + int hbInstances = 0; + for (aDictionary in runningAppDictionaries) + { + // NSLog(@"Open App: %@", [aDictionary valueForKey:@"NSApplicationName"]); + + if ([[aDictionary valueForKey:@"NSApplicationName"] isEqualToString:@"HandBrake"]) + { + hbInstances++; + } + } + return hbInstances; +} + - (void) didDimissReloadQueue: (NSWindow *)sheet returnCode: (int)returnCode contextInfo: (void *)contextInfo { if (returnCode == NSAlertOtherReturn) { [self clearQueueAllItems]; - [self performSelectorOnMainThread:@selector(browseSources:) - withObject:nil waitUntilDone:NO]; + /* 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 { - [self setQueueEncodingItemsAsPending]; - [self showQueueWindow:NULL]; + if ([self hbInstances] == 1) + { + [self setQueueEncodingItemsAsPending]; + } + [self showQueueWindow:NULL]; } } - (NSApplicationTerminateReply) applicationShouldTerminate: (NSApplication *) app { + /* if we are in preview full screen mode, we need to go to + * windowed mode and release the display before we terminate. + * We do it here (instead of applicationWillTerminate) so we + * release the displays and can then see the alerts below. + */ + if ([fPictureController previewFullScreenMode] == YES) + { + [fPictureController previewGoWindowed:nil]; + } - // Warn if encoding a movie hb_state_t s; hb_get_state( fQueueEncodeLibhb, &s ); @@ -221,9 +313,14 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It - (void)applicationWillTerminate:(NSNotification *)aNotification { - [browsedSourceDisplayName release]; + + [browsedSourceDisplayName release]; [outputPanel release]; [fQueueController release]; + [fPreviewController release]; + [fPictureController release]; + [fApplicationIcon release]; + hb_close(&fHandle); hb_close(&fQueueEncodeLibhb); } @@ -234,17 +331,17 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [fWindow center]; [fWindow setExcludedFromWindowsMenu:YES]; [fAdvancedOptions setView:fAdvancedView]; - + /* lets setup our presets drawer for drag and drop here */ [fPresetsOutlineView registerForDraggedTypes: [NSArray arrayWithObject:DragDropSimplePboardType] ]; [fPresetsOutlineView setDraggingSourceOperationMask:NSDragOperationEvery forLocal:YES]; [fPresetsOutlineView setVerticalMotionCanBeginDrag: YES]; - + /* Initialize currentScanCount so HB can use it to - evaluate successive scans */ + evaluate successive scans */ currentScanCount = 0; - - + + /* Init UserPresets .plist */ [self loadPresets]; @@ -252,15 +349,38 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [self loadQueueFile]; fRipIndicatorShown = NO; // initially out of view in the nib + + /* 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/Dont Show Presets drawer upon launch based - on user preference DefaultPresetsDrawerShow*/ - if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPresetsDrawerShow"] > 0) + on user preference DefaultPresetsDrawerShow*/ + if( [[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPresetsDrawerShow"] > 0 ) { + [fPresetDrawer setDelegate:self]; + NSSize drawerSize = NSSizeFromString( [[NSUserDefaults standardUserDefaults] + stringForKey:@"Drawer Size"] ); + if( drawerSize.width ) + [fPresetDrawer setContentSize: drawerSize]; [fPresetDrawer open]; } - - + + /* Initially set the dvd angle widgets to hidden (dvdnav only) */ + [fSrcAngleLabel setHidden:YES]; + [fSrcAnglePopUp setHidden:YES]; /* Destination box*/ NSMenuItem *menuItem; @@ -271,43 +391,37 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It // MKV file menuItem = [[fDstFormatPopUp menu] addItemWithTitle:@"MKV file" action: NULL keyEquivalent: @""]; [menuItem setTag: HB_MUX_MKV]; - // AVI file - menuItem = [[fDstFormatPopUp menu] addItemWithTitle:@"AVI file" action: NULL keyEquivalent: @""]; - [menuItem setTag: HB_MUX_AVI]; - // OGM file - menuItem = [[fDstFormatPopUp menu] addItemWithTitle:@"OGM file" action: NULL keyEquivalent: @""]; - [menuItem setTag: HB_MUX_OGM]; + [fDstFormatPopUp selectItemAtIndex: 0]; - + [self formatPopUpChanged:nil]; - + /* We enable the create chapters checkbox here since we are .mp4 */ [fCreateChapterMarkers setEnabled: YES]; if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultChapterMarkers"] > 0) { [fCreateChapterMarkers setState: NSOnState]; } - - - - + + + + [fDstFile2Field setStringValue: [NSString stringWithFormat: - @"%@/Desktop/Movie.mp4", NSHomeDirectory()]]; - + @"%@/Desktop/Movie.mp4", NSHomeDirectory()]]; + /* Video encoder */ [fVidEncoderPopUp removeAllItems]; [fVidEncoderPopUp addItemWithTitle: @"FFmpeg"]; - [fVidEncoderPopUp addItemWithTitle: @"XviD"]; - - - + + + /* Video quality */ [fVidTargetSizeField setIntValue: 700]; [fVidBitrateField setIntValue: 1000]; - + [fVidQualityMatrix selectCell: fVidBitrateCell]; [self videoMatrixChanged:nil]; - + /* Video framerate */ [fVidRatePopUp removeAllItems]; [fVidRatePopUp addItemWithTitle: NSLocalizedString( @"Same as source", @"" )]; @@ -316,22 +430,22 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It if ([[NSString stringWithCString: hb_video_rates[i].string] isEqualToString: [NSString stringWithFormat: @"%.3f",23.976]]) { [fVidRatePopUp addItemWithTitle:[NSString stringWithFormat: @"%@%@", - [NSString stringWithCString: hb_video_rates[i].string], @" (NTSC Film)"]]; + [NSString stringWithCString: hb_video_rates[i].string], @" (NTSC Film)"]]; } else if ([[NSString stringWithCString: hb_video_rates[i].string] isEqualToString: [NSString stringWithFormat: @"%d",25]]) { [fVidRatePopUp addItemWithTitle:[NSString stringWithFormat: @"%@%@", - [NSString stringWithCString: hb_video_rates[i].string], @" (PAL Film/Video)"]]; + [NSString stringWithCString: hb_video_rates[i].string], @" (PAL Film/Video)"]]; } else if ([[NSString stringWithCString: hb_video_rates[i].string] isEqualToString: [NSString stringWithFormat: @"%.2f",29.97]]) { [fVidRatePopUp addItemWithTitle:[NSString stringWithFormat: @"%@%@", - [NSString stringWithCString: hb_video_rates[i].string], @" (NTSC Video)"]]; + [NSString stringWithCString: hb_video_rates[i].string], @" (NTSC Video)"]]; } else { [fVidRatePopUp addItemWithTitle: - [NSString stringWithCString: hb_video_rates[i].string]]; + [NSString stringWithCString: hb_video_rates[i].string]]; } } [fVidRatePopUp selectItemAtIndex: 0]; @@ -344,8 +458,8 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It for( int i = 0; i < hb_audio_bitrates_count; i++ ) { [fAudTrack1BitratePopUp addItemWithTitle: - [NSString stringWithCString: hb_audio_bitrates[i].string]]; - + [NSString stringWithCString: hb_audio_bitrates[i].string]]; + } [fAudTrack1BitratePopUp selectItemAtIndex: hb_audio_bitrates_default]; @@ -354,39 +468,38 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It for( int i = 0; i < hb_audio_rates_count; i++ ) { [fAudTrack1RatePopUp addItemWithTitle: - [NSString stringWithCString: hb_audio_rates[i].string]]; + [NSString stringWithCString: hb_audio_rates[i].string]]; } [fAudTrack1RatePopUp selectItemAtIndex: hb_audio_rates_default]; /* Bottom */ [fStatusField setStringValue: @""]; - + [self enableUI: NO]; [self setupToolbar]; - + /* We disable the Turbo 1st pass checkbox since we are not x264 */ [fVidTurboPassCheck setEnabled: NO]; [fVidTurboPassCheck setState: NSOffState]; - - + + /* lets get our default prefs here */ [self getDefaultPresets:nil]; /* lets initialize the current successful scancount here to 0 */ currentSuccessfulScanCount = 0; - - + + } - (void) enableUI: (bool) b { NSControl * controls[] = - { fSrcTitleField, fSrcTitlePopUp, + { fSrcTitleField, fSrcTitlePopUp, fSrcChapterField, fSrcChapterStartPopUp, fSrcChapterToField, fSrcChapterEndPopUp, fSrcDuration1Field, fSrcDuration2Field, fDstFormatField, fDstFormatPopUp, fDstFile1Field, fDstFile2Field, - fDstBrowseButton, fVidRateField, fVidRatePopUp, - fVidEncoderField, fVidEncoderPopUp, fVidQualityField, - fVidQualityMatrix, fVidGrayscaleCheck, fSubField, fSubPopUp, + fDstBrowseButton, fVidRateField, fVidRatePopUp,fVidEncoderField, fVidEncoderPopUp, fVidQualityField, + fPictureSizeField,fPictureCroppingField, fVideoFiltersField,fVidQualityMatrix, fSubField, fSubPopUp, fAudSourceLabel, fAudCodecLabel, fAudMixdownLabel, fAudSamplerateLabel, fAudBitrateLabel, fAudTrack1Label, fAudTrack2Label, fAudTrack3Label, fAudTrack4Label, fAudLang1PopUp, fAudLang2PopUp, fAudLang3PopUp, fAudLang4PopUp, @@ -396,16 +509,12 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It fAudTrack1BitratePopUp, fAudTrack2BitratePopUp, fAudTrack3BitratePopUp, fAudTrack4BitratePopUp, fAudDrcLabel, fAudTrack1DrcSlider, fAudTrack1DrcField, fAudTrack2DrcSlider, fAudTrack2DrcField, fAudTrack3DrcSlider, fAudTrack3DrcField, fAudTrack4DrcSlider,fAudTrack4DrcField, - fPictureButton,fQueueStatus,fPicSettingARkeep, fPicSettingDeinterlace,fPicLabelSettings,fPicLabelSrc, - fPicLabelOutp,fPicSettingsSrc,fPicSettingsOutp,fPicSettingsAnamorphic, - fPicLabelAr,fPicLabelDeinterlace,fPicSettingPAR,fPicLabelAnamorphic,fPresetsAdd,fPresetsDelete, - fCreateChapterMarkers,fVidTurboPassCheck,fDstMp4LargeFileCheck,fPicLabelAutoCrop, - fPicSettingAutoCrop,fPicSettingDetelecine,fPicLabelDetelecine,fPicLabelDenoise,fPicSettingDenoise, - fSubForcedCheck,fPicSettingDeblock,fPicLabelDeblock,fPicLabelDecomb,fPicSettingDecomb,fPresetsOutlineView, - fAudDrcLabel,fDstMp4HttpOptFileCheck,fDstMp4iPodFileCheck}; - + fQueueStatus,fPresetsAdd,fPresetsDelete,fSrcAngleLabel,fSrcAnglePopUp, + fCreateChapterMarkers,fVidTurboPassCheck,fDstMp4LargeFileCheck,fSubForcedCheck,fPresetsOutlineView, + fAudDrcLabel,fDstMp4HttpOptFileCheck,fDstMp4iPodFileCheck,fVidQualityRFField,fVidQualityRFLabel}; + for( unsigned i = 0; - i < sizeof( controls ) / sizeof( NSControl * ); i++ ) + i < sizeof( controls ) / sizeof( NSControl * ); i++ ) { if( [[controls[i] className] isEqualToString: @"NSTextField"] ) { @@ -413,28 +522,28 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It if( ![tf isBezeled] ) { [tf setTextColor: b ? [NSColor controlTextColor] : - [NSColor disabledControlTextColor]]; + [NSColor disabledControlTextColor]]; continue; } } [controls[i] setEnabled: b]; - + } - + if (b) { - + /* if we're enabling the interface, check if the audio mixdown controls need to be enabled or not */ /* these will have been enabled by the mass control enablement above anyway, so we're sense-checking it here */ [self setEnabledStateOfAudioMixdownControls:nil]; /* we also call calculatePictureSizing here to sense check if we already have vfr selected */ [self calculatePictureSizing:nil]; - + } else { - + [fPresetsOutlineView setEnabled: NO]; - + } - + [self videoMatrixChanged:nil]; [fAdvancedOptions enableUI:b]; } @@ -558,7 +667,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It NSLocalizedString( @"Scanning title %d of %d...", @"" ), p.title_cur, p.title_count]]; [fScanIndicator setHidden: NO]; - [fScanIndicator setDoubleValue: 100.0 * ( p.title_cur - 1 ) / p.title_count]; + [fScanIndicator setDoubleValue: 100.0 * ((double)( p.title_cur - 1 ) / p.title_count)]; break; } #undef p @@ -635,9 +744,6 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [fQueueController setQueueStatusString: [NSString stringWithFormat: NSLocalizedString( @"Queue Scanning title %d of %d...", @"" ), p.title_cur, p.title_count]]; - - [fRipIndicator setHidden: NO]; - [fRipIndicator setDoubleValue: 100.0 * ( p.title_cur - 1 ) / p.title_count]; break; } #undef p @@ -645,9 +751,6 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It #define p s.param.scandone case HB_STATE_SCANDONE: { - [fRipIndicator setIndeterminate: NO]; - [fRipIndicator setDoubleValue: 0.0]; - [self writeToActivityLog:"ScanDone state received from fQueueEncodeLibhb"]; [self processNewQueueEncode]; [[fWindow toolbar] validateVisibleItems]; @@ -659,7 +762,6 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It #define p s.param.working case HB_STATE_WORKING: { - float progress_total; NSMutableString * string; /* Update text field */ string = [NSMutableString stringWithFormat: NSLocalizedString( @"Encoding: pass %d of %d, %.2f %%", @"" ), p.job_cur, p.job_count, 100.0 * p.progress]; @@ -675,9 +777,9 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It /* Set the status string in fQueueController as well */ [fQueueController setQueueStatusString: string]; /* Update slider */ - progress_total = ( p.progress + p.job_cur - 1 ) / p.job_count; + CGFloat progress_total = ( p.progress + p.job_cur - 1 ) / p.job_count; [fRipIndicator setIndeterminate: NO]; - [fRipIndicator setDoubleValue: 100.0 * progress_total]; + [fRipIndicator setDoubleValue:100.0 * progress_total]; // If progress bar hasn't been revealed at the bottom of the window, do // that now. This code used to be in doRip. I moved it to here to handle @@ -694,10 +796,14 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It fRipIndicatorShown = YES; } - + /* Update dock icon */ - [self UpdateDockIcon: progress_total]; - + if( dockIconProgress < 100.0 * progress_total ) + { + [self UpdateDockIcon: progress_total]; + dockIconProgress += 5; + } + break; } #undef p @@ -737,11 +843,13 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It /* Set the status string in fQueueController as well */ [fQueueController setQueueStatusString: NSLocalizedString( @"Encode Finished.", @"" )]; [fRipIndicator setIndeterminate: NO]; + [fRipIndicator stopAnimation: nil]; [fRipIndicator setDoubleValue: 0.0]; [[fWindow toolbar] validateVisibleItems]; /* Restore dock icon */ [self UpdateDockIcon: -1.0]; + dockIconProgress = 0; if( fRipIndicatorShown ) { @@ -825,7 +933,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It } /* We use this to write messages to stderr from the macgui which show up in the activity window and log*/ -- (void) writeToActivityLog:(char *) format, ... +- (void) writeToActivityLog:(const char *) format, ... { va_list args; va_start(args, format); @@ -910,7 +1018,27 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [item setTarget: self]; [item setAction: @selector(Pause:)]; } - else if ([itemIdent isEqualToString: ShowActivityIdentifier]) { + else if ([itemIdent isEqualToString: ShowPictureIdentifier]) + { + [item setLabel: @"Picture Settings"]; + [item setPaletteLabel: @"Show Picture Settings"]; + [item setToolTip: @"Show Picture Settings"]; + [item setImage: [NSImage imageNamed: @"pref-picture"]]; + [item setTarget: self]; + [item setAction: @selector(showPicturePanel:)]; + } + else if ([itemIdent isEqualToString: ShowPreviewIdentifier]) + { + [item setLabel: @"Preview Window"]; + [item setPaletteLabel: @"Show Preview"]; + [item setToolTip: @"Show Preview"]; + //[item setImage: [NSImage imageNamed: @"pref-picture"]]; + [item setImage: [NSImage imageNamed: @"Brushed_Window"]]; + [item setTarget: self]; + [item setAction: @selector(showPreviewWindow:)]; + } + else if ([itemIdent isEqualToString: ShowActivityIdentifier]) + { [item setLabel: @"Activity Window"]; [item setPaletteLabel: @"Show Activity Window"]; [item setToolTip: @"Show Activity Window"]; @@ -940,13 +1068,13 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It { return [NSArray arrayWithObjects: ChooseSourceIdentifier, NSToolbarSeparatorItemIdentifier, StartEncodingIdentifier, PauseEncodingIdentifier, AddToQueueIdentifier, ShowQueueIdentifier, NSToolbarFlexibleSpaceItemIdentifier, - NSToolbarSpaceItemIdentifier, ShowActivityIdentifier, ToggleDrawerIdentifier, nil]; + NSToolbarSpaceItemIdentifier, ShowPictureIdentifier, ShowPreviewIdentifier, ShowActivityIdentifier, ToggleDrawerIdentifier, nil]; } - (NSArray *) toolbarAllowedItemIdentifiers: (NSToolbar *) toolbar { return [NSArray arrayWithObjects: StartEncodingIdentifier, PauseEncodingIdentifier, AddToQueueIdentifier, - ChooseSourceIdentifier, ShowQueueIdentifier, ShowActivityIdentifier, ToggleDrawerIdentifier, + ChooseSourceIdentifier, ShowQueueIdentifier, ShowPictureIdentifier, ShowPreviewIdentifier, ShowActivityIdentifier, ToggleDrawerIdentifier, NSToolbarCustomizeToolbarItemIdentifier, NSToolbarFlexibleSpaceItemIdentifier, NSToolbarSpaceItemIdentifier, NSToolbarSeparatorItemIdentifier, nil]; } @@ -979,8 +1107,14 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It return YES; } if (SuccessfulScan) + { if ([ident isEqualToString: AddToQueueIdentifier]) return YES; + if ([ident isEqualToString: ShowPictureIdentifier]) + return YES; + if ([ident isEqualToString: ShowPreviewIdentifier]) + return YES; + } } else if (s.state == HB_STATE_PAUSED) { @@ -996,6 +1130,10 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It return YES; if ([ident isEqualToString: AddToQueueIdentifier]) return YES; + if ([ident isEqualToString: ShowPictureIdentifier]) + return YES; + if ([ident isEqualToString: ShowPreviewIdentifier]) + return YES; } else if (s.state == HB_STATE_SCANNING) return NO; @@ -1014,6 +1152,10 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It } if ([ident isEqualToString: AddToQueueIdentifier]) return YES; + if ([ident isEqualToString: ShowPictureIdentifier]) + return YES; + if ([ident isEqualToString: ShowPreviewIdentifier]) + return YES; } } @@ -1299,6 +1441,16 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It } } +- (IBAction)showAboutPanel:(id)sender +{ + //[NSApp orderFrontStandardAboutPanel:sender]; + NSMutableDictionary* d = [[NSMutableDictionary alloc] initWithObjectsAndKeys: + fApplicationIcon, @"ApplicationIcon", + nil ]; + [NSApp orderFrontStandardAboutPanelWithOptions:d]; + [d release]; +} + /* Here we open the title selection sheet where we can specify an exact title to be scanned */ - (IBAction) showSourceTitleScanPanel: (id) sender { @@ -1339,22 +1491,49 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It BOOL cancelScanDecrypt = 0; NSString *path = scanPath; HBDVDDetector *detector = [HBDVDDetector detectorForPath:path]; - + // Notify ChapterTitles that there's no title [fChapterTitlesDelegate resetWithTitle:nil]; [fChapterTable reloadData]; - + + // Notify Subtitles that there's no title + [fSubtitlesDelegate resetWithTitle:nil]; + [fSubtitlesTable reloadData]; + [self enableUI: NO]; - + if( [detector isVideoDVD] ) { // The chosen path was actually on a DVD, so use the raw block // device path instead. path = [detector devicePath]; [self writeToActivityLog: "trying to open a physical dvd at: %s", [scanPath UTF8String]]; + +#if defined( __LP64__ ) + /* If we are 64 bit, we cannot read encrypted dvd's as vlc is 32 bit only */ + cancelScanDecrypt = 1; + [self writeToActivityLog: "64 bit mode cannot read dvd's, scan cancelled"]; + /*On Screen Notification*/ + int status; + NSBeep(); + status = NSRunAlertPanel(@"64-bit HandBrake cannot read encrypted dvds!",@"", @"Cancel Scan", @"Attempt Scan Anyway", nil); + [NSApp requestUserAttention:NSCriticalRequest]; + + if (status == NSAlertDefaultReturn) + { + /* User chose to cancel the scan */ + [self writeToActivityLog: "cannot open physical dvd , scan cancelled"]; + cancelScanDecrypt = 1; + } + else + { + [self writeToActivityLog: "user overrode 64-bit warning trying to open physical dvd without decryption"]; + cancelScanDecrypt = 0; + } +#else /* lets check for vlc here to make sure we have a dylib available to use for decrypting */ - NSString *vlcPath = @"/Applications/VLC.app"; + NSString *vlcPath = @"/Applications/VLC.app/Contents/MacOS/lib/libdvdcss.2.dylib"; NSFileManager * fileManager = [NSFileManager defaultManager]; if ([fileManager fileExistsAtPath:vlcPath] == 0) { @@ -1362,7 +1541,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It cancelScanDecrypt = 1; [self writeToActivityLog: "VLC app not found for decrypting physical dvd"]; int status; - status = NSRunAlertPanel(@"HandBrake could not find VLC.",@"Please download and install VLC media player in your /Applications folder if you wish to read encrypted DVDs.", @"Get VLC", @"Cancel Scan", @"Attempt Scan Anyway"); + status = NSRunAlertPanel(@"HandBrake could not find VLC or your VLC is out of date.",@"Please download and install VLC media player in your /Applications folder if you wish to read encrypted DVDs.", @"Get VLC", @"Cancel Scan", @"Attempt Scan Anyway"); [NSApp requestUserAttention:NSCriticalRequest]; if (status == NSAlertDefaultReturn) @@ -1372,24 +1551,25 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It } else if (status == NSAlertAlternateReturn) { - /* User chose to cancel the scan */ - [self writeToActivityLog: "cannot open physical dvd , scan cancelled"]; + /* User chose to cancel the scan */ + [self writeToActivityLog: "cannot open physical dvd , scan cancelled"]; } else { - /* User chose to override our warning and scan the physical dvd anyway, at their own peril. on an encrypted dvd this produces massive log files and fails */ - cancelScanDecrypt = 0; - [self writeToActivityLog: "user overrode vlc warning -trying to open physical dvd without decryption"]; + /* User chose to override our warning and scan the physical dvd anyway, at their own peril. on an encrypted dvd this produces massive log files and fails */ + cancelScanDecrypt = 0; + [self writeToActivityLog: "user overrode vlc warning -trying to open physical dvd without decryption"]; } - + } else { /* VLC was found in /Applications so all is well, we can carry on using vlc's libdvdcss.dylib for decrypting if needed */ [self writeToActivityLog: "VLC app found for decrypting physical dvd"]; } +#endif } - + if (cancelScanDecrypt == 0) { /* we actually pass the scan off to libhb here */ @@ -1406,6 +1586,8 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It } /* We use our advance pref to determine how many previews to scan */ int hb_num_previews = [[[NSUserDefaults standardUserDefaults] objectForKey:@"PreviewsNumber"] intValue]; + /* set title to NULL */ + //fTitle = NULL; hb_scan( fHandle, [path UTF8String], scanTitleNum, hb_num_previews, 1 ); [fSrcDVD2Field setStringValue:@"Scanning new source ..."]; } @@ -1428,6 +1610,10 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It SuccessfulScan = NO; // Notify ChapterTitles that there's no title + [fSubtitlesDelegate resetWithTitle:nil]; + [fSubtitlesTable reloadData]; + + // Notify Subtitles that there's no title [fChapterTitlesDelegate resetWithTitle:nil]; [fChapterTable reloadData]; } @@ -1485,18 +1671,20 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It SuccessfulScan = YES; [self enableUI: YES]; - /* if its the initial successful scan after awakeFromNib */ - if (currentSuccessfulScanCount == 1) - { - [self selectDefaultPreset:nil]; - /* initially set deinterlace to 0, will be overridden reset by the default preset anyway */ - //[fPictureController setDeinterlace:0]; - - /* lets set Denoise to index 0 or "None" since this is the first scan */ - //[fPictureController setDenoise:0]; - - [fPictureController setInitialPictureFilters]; - } + /* if its the initial successful scan after awakeFromNib */ + if (currentSuccessfulScanCount == 1) + { + [self selectDefaultPreset:nil]; + + // Open preview window now if it was visible when HB was closed + if ([[NSUserDefaults standardUserDefaults] boolForKey:@"PreviewWindowIsOpen"]) + [self showPreviewWindow:nil]; + + // Open picture sizing window now if it was visible when HB was closed + if ([[NSUserDefaults standardUserDefaults] boolForKey:@"PictureSizeWindowIsOpen"]) + [self showPicturePanel:nil]; + + } } @@ -1519,11 +1707,14 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It } - (void) browseFileDone: (NSSavePanel *) sheet - returnCode: (int) returnCode contextInfo: (void *) contextInfo + returnCode: (int) returnCode contextInfo: (void *) contextInfo { if( returnCode == NSOKButton ) { [fDstFile2Field setStringValue: [sheet filename]]; + /* Save this path to the prefs so that on next browse destination window it opens there */ + NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent]; + [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"]; } } @@ -1552,6 +1743,10 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It return NO; } +- (NSSize) drawerWillResizeContents:(NSDrawer *) drawer toSize:(NSSize) contentSize { + [[NSUserDefaults standardUserDefaults] setObject:NSStringFromSize( contentSize ) forKey:@"Drawer Size"]; + return contentSize; +} #pragma mark - #pragma mark Queue File @@ -1777,6 +1972,7 @@ fWorkingCount = 0; [queueFileJob setObject:[NSString stringWithUTF8String: title->dvd] forKey:@"SourcePath"]; [queueFileJob setObject:[fSrcDVD2Field stringValue] forKey:@"SourceName"]; [queueFileJob setObject:[NSNumber numberWithInt:title->index] forKey:@"TitleNumber"]; + [queueFileJob setObject:[NSNumber numberWithInt:[fSrcAnglePopUp indexOfSelectedItem] + 1] forKey:@"TitleAngle"]; [queueFileJob setObject:[NSNumber numberWithInt:[fSrcChapterStartPopUp indexOfSelectedItem] + 1] forKey:@"ChapterStart"]; [queueFileJob setObject:[NSNumber numberWithInt:[fSrcChapterEndPopUp indexOfSelectedItem] + 1] forKey:@"ChapterEnd"]; @@ -1788,8 +1984,16 @@ fWorkingCount = 0; [queueFileJob setObject:[NSNumber numberWithInt:[fPresetsOutlineView selectedRow]] forKey:@"PresetIndexNum"]; [queueFileJob setObject:[fDstFormatPopUp titleOfSelectedItem] forKey:@"FileFormat"]; - /* Chapter Markers fCreateChapterMarkers*/ - [queueFileJob setObject:[NSNumber numberWithInt:[fCreateChapterMarkers state]] forKey:@"ChapterMarkers"]; + /* Chapter Markers*/ + /* If we have only one chapter or a title without chapters, set chapter markers to off */ + if ([fSrcChapterStartPopUp indexOfSelectedItem] == [fSrcChapterEndPopUp indexOfSelectedItem]) + { + [queueFileJob setObject:[NSNumber numberWithInt:0] forKey:@"ChapterMarkers"]; + } + else + { + [queueFileJob setObject:[NSNumber numberWithInt:[fCreateChapterMarkers state]] forKey:@"ChapterMarkers"]; + } /* We need to get the list of chapter names to put into an array and store * in our queue, so they can be reapplied in prepareJob when this queue @@ -1825,12 +2029,10 @@ fWorkingCount = 0; [queueFileJob setObject:[NSNumber numberWithInt:[fVidQualityMatrix selectedRow]] forKey:@"VideoQualityType"]; [queueFileJob setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"]; [queueFileJob setObject:[fVidBitrateField stringValue] forKey:@"VideoAvgBitrate"]; - [queueFileJob setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"]; + [queueFileJob setObject:[NSNumber numberWithFloat:[fVidQualityRFField floatValue]] forKey:@"VideoQualitySlider"]; /* Framerate */ [queueFileJob setObject:[fVidRatePopUp titleOfSelectedItem] forKey:@"VideoFramerate"]; - /* GrayScale */ - [queueFileJob setObject:[NSNumber numberWithInt:[fVidGrayscaleCheck state]] forKey:@"VideoGrayScale"]; /* 2 Pass Encoding */ [queueFileJob setObject:[NSNumber numberWithInt:[fVidTwoPassCheck state]] forKey:@"VideoTwoPass"]; /* Turbo 2 pass Encoding fVidTurboPassCheck*/ @@ -1842,12 +2044,22 @@ fWorkingCount = 0; [queueFileJob setObject:[NSNumber numberWithInt:fTitle->job->width] forKey:@"PictureWidth"]; [queueFileJob setObject:[NSNumber numberWithInt:fTitle->job->height] forKey:@"PictureHeight"]; [queueFileJob setObject:[NSNumber numberWithInt:fTitle->job->keep_ratio] forKey:@"PictureKeepRatio"]; - [queueFileJob setObject:[NSNumber numberWithInt:fTitle->job->pixel_ratio] forKey:@"PicturePAR"]; + [queueFileJob setObject:[NSNumber numberWithInt:fTitle->job->anamorphic.mode] forKey:@"PicturePAR"]; + /* if we are custom anamorphic, store the exact storage, par and display dims */ + if (fTitle->job->anamorphic.mode == 3) + { + [queueFileJob setObject:[NSNumber numberWithInt:fTitle->job->width] forKey:@"PicturePARStorageWidth"]; + [queueFileJob setObject:[NSNumber numberWithInt:fTitle->job->height] forKey:@"PicturePARStorageHeight"]; + + [queueFileJob setObject:[NSNumber numberWithInt:fTitle->job->anamorphic.par_width] forKey:@"PicturePARPixelWidth"]; + [queueFileJob setObject:[NSNumber numberWithInt:fTitle->job->anamorphic.par_height] forKey:@"PicturePARPixelHeight"]; + + [queueFileJob setObject:[NSNumber numberWithFloat:fTitle->job->anamorphic.dar_width] forKey:@"PicturePARDisplayWidth"]; + [queueFileJob setObject:[NSNumber numberWithFloat:fTitle->job->anamorphic.dar_height] forKey:@"PicturePARDisplayHeight"]; + + } NSString * pictureSummary; - pictureSummary = [NSString stringWithFormat:@"Source: %@ Output: %@ Anamorphic: %@", - [fPicSettingsSrc stringValue], - [fPicSettingsOutp stringValue], - [fPicSettingsAnamorphic stringValue]]; + pictureSummary = [fPictureSizeField stringValue]; [queueFileJob setObject:pictureSummary forKey:@"PictureSizingSummary"]; /* Set crop settings here */ [queueFileJob setObject:[NSNumber numberWithInt:[fPictureController autoCrop]] forKey:@"PictureAutoCrop"]; @@ -1857,11 +2069,22 @@ fWorkingCount = 0; [queueFileJob setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"]; /* Picture Filters */ + [queueFileJob setObject:[NSNumber numberWithInt:[fPictureController detelecine]] forKey:@"PictureDetelecine"]; + [queueFileJob setObject:[fPictureController detelecineCustomString] forKey:@"PictureDetelecineCustom"]; + + [queueFileJob setObject:[NSNumber numberWithInt:[fPictureController useDecomb]] forKey:@"PictureDecombDeinterlace"]; + [queueFileJob setObject:[NSNumber numberWithInt:[fPictureController decomb]] forKey:@"PictureDecomb"]; + [queueFileJob setObject:[fPictureController decombCustomString] forKey:@"PictureDecombCustom"]; + [queueFileJob setObject:[NSNumber numberWithInt:[fPictureController deinterlace]] forKey:@"PictureDeinterlace"]; - [queueFileJob setObject:[NSNumber numberWithInt:[fPictureController detelecine]] forKey:@"PictureDetelecine"]; + [queueFileJob setObject:[fPictureController deinterlaceCustomString] forKey:@"PictureDeinterlaceCustom"]; + [queueFileJob setObject:[NSNumber numberWithInt:[fPictureController denoise]] forKey:@"PictureDenoise"]; - [queueFileJob setObject:[NSString stringWithFormat:@"%d",[fPictureController deblock]] forKey:@"PictureDeblock"]; - [queueFileJob setObject:[NSNumber numberWithInt:[fPictureController decomb]] forKey:@"PictureDecomb"]; + [queueFileJob setObject:[fPictureController denoiseCustomString] forKey:@"PictureDenoiseCustom"]; + + [queueFileJob setObject:[NSString stringWithFormat:@"%d",[fPictureController deblock]] forKey:@"PictureDeblock"]; + + [queueFileJob setObject:[NSNumber numberWithInt:[fPictureController grayscale]] forKey:@"VideoGrayScale"]; /*Audio*/ if ([fAudLang1PopUp indexOfSelectedItem] > 0) @@ -1906,13 +2129,10 @@ fWorkingCount = 0; } /* Subtitles*/ - [queueFileJob setObject:[fSubPopUp titleOfSelectedItem] forKey:@"Subtitles"]; - [queueFileJob setObject:[NSNumber numberWithInt:[fSubPopUp indexOfSelectedItem]] forKey:@"JobSubtitlesIndex"]; - /* Forced Subtitles */ - [queueFileJob setObject:[NSNumber numberWithInt:[fSubForcedCheck state]] forKey:@"SubtitlesForced"]; - - - + NSMutableArray *subtitlesArray = [[NSMutableArray alloc] init]; + [queueFileJob setObject:[NSArray arrayWithArray: [fSubtitlesDelegate getSubtitleArray: subtitlesArray]] forKey:@"SubtitleList"]; + [subtitlesArray autorelease]; + /* Now we go ahead and set the "job->values in the plist for passing right to fQueueEncodeLibhb */ [queueFileJob setObject:[NSNumber numberWithInt:[fSrcChapterStartPopUp indexOfSelectedItem] + 1] forKey:@"JobChapterStart"]; @@ -1937,7 +2157,7 @@ fWorkingCount = 0; [queueFileJob setObject:[NSNumber numberWithInt:fTitle->job->width] forKey:@"PictureWidth"]; [queueFileJob setObject:[NSNumber numberWithInt:fTitle->job->height] forKey:@"PictureHeight"]; [queueFileJob setObject:[NSNumber numberWithInt:fTitle->job->keep_ratio] forKey:@"PictureKeepRatio"]; - [queueFileJob setObject:[NSNumber numberWithInt:fTitle->job->pixel_ratio] forKey:@"PicturePAR"]; + [queueFileJob setObject:[NSNumber numberWithInt:fTitle->job->anamorphic.mode] forKey:@"PicturePAR"]; /* Set crop settings here */ [queueFileJob setObject:[NSNumber numberWithInt:[fPictureController autoCrop]] forKey:@"PictureAutoCrop"]; @@ -1946,8 +2166,6 @@ fWorkingCount = 0; [queueFileJob setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"]; [queueFileJob setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"]; - /* Picture Filters */ - [queueFileJob setObject:[fPicSettingDecomb stringValue] forKey:@"JobPictureDecomb"]; /*Audio*/ if ([fAudLang1PopUp indexOfSelectedItem] > 0) @@ -1982,10 +2200,7 @@ fWorkingCount = 0; [queueFileJob setObject:[NSNumber numberWithInt:[[fAudTrack4RatePopUp selectedItem] tag]] forKey:@"JobAudio4Samplerate"]; [queueFileJob setObject:[NSNumber numberWithInt:[[fAudTrack4BitratePopUp selectedItem] tag]] forKey:@"JobAudio4Bitrate"]; } - /* Subtitles*/ - [queueFileJob setObject:[fSubPopUp titleOfSelectedItem] forKey:@"Subtitles"]; - /* Forced Subtitles */ - [queueFileJob setObject:[NSNumber numberWithInt:[fSubForcedCheck state]] forKey:@"SubtitlesForced"]; + /* we need to auto relase the queueFileJob and return it */ [queueFileJob autorelease]; @@ -1994,33 +2209,32 @@ fWorkingCount = 0; } /* this is actually called from the queue controller to modify the queue array and return it back to the queue controller */ -- (void)moveObjectsInQueueArray:(NSMutableArray *)array fromIndexes:(NSIndexSet *)indexSet toIndex:(unsigned)insertIndex +- (void)moveObjectsInQueueArray:(NSMutableArray *)array fromIndexes:(NSIndexSet *)indexSet toIndex:(NSUInteger)insertIndex { - unsigned index = [indexSet lastIndex]; - unsigned aboveInsertIndexCount = 0; + NSUInteger index = [indexSet lastIndex]; + NSUInteger aboveInsertIndexCount = 0; - while (index != NSNotFound) - { - unsigned removeIndex; - - if (index >= insertIndex) - { - removeIndex = index + aboveInsertIndexCount; - aboveInsertIndexCount++; - } - else - { - removeIndex = index; - insertIndex--; - } - - id object = [[QueueFileArray objectAtIndex:removeIndex] retain]; - [QueueFileArray removeObjectAtIndex:removeIndex]; - [QueueFileArray insertObject:object atIndex:insertIndex]; - [object release]; + + NSUInteger removeIndex; - index = [indexSet indexLessThanIndex:index]; + if (index >= insertIndex) + { + removeIndex = index + aboveInsertIndexCount; + aboveInsertIndexCount++; + } + else + { + removeIndex = index; + insertIndex--; } + + id object = [[QueueFileArray objectAtIndex:removeIndex] retain]; + [QueueFileArray removeObjectAtIndex:removeIndex]; + [QueueFileArray insertObject:object atIndex:insertIndex]; + [object release]; + + index = [indexSet indexLessThanIndex:index]; + /* We save all of the Queue data here * and it also gets sent back to the queue controller*/ [self saveQueueFileItem]; @@ -2081,12 +2295,6 @@ fWorkingCount = 0; //status = NSRunAlertPanel(@"HandBrake is now loading up a new queue item...",@"Would You Like to wait until you add another encode?", @"Cancel", @"Okay", nil); //[NSApp requestUserAttention:NSCriticalRequest]; - // Notify ChapterTitles that there's no title - [fChapterTitlesDelegate resetWithTitle:nil]; - [fChapterTable reloadData]; - - //[self enableUI: NO]; - if( [detector isVideoDVD] ) { // The chosen path was actually on a DVD, so use the raw block @@ -2216,9 +2424,6 @@ fWorkingCount = 0; [fVidRatePopUp selectItemWithTitle:[queueToApply objectForKey:@"VideoFramerate"]]; } - /* GrayScale */ - [fVidGrayscaleCheck setState:[[queueToApply objectForKey:@"VideoGrayScale"] intValue]]; - /* 2 Pass Encoding */ [fVidTwoPassCheck setState:[[queueToApply objectForKey:@"VideoTwoPass"] intValue]]; [self twoPassCheckboxChanged:nil]; @@ -2357,7 +2562,7 @@ fWorkingCount = 0; hb_fix_aspect( job, HB_KEEP_HEIGHT ); } } - job->pixel_ratio = [[queueToApply objectForKey:@"PicturePAR"] intValue]; + job->anamorphic.mode = [[queueToApply objectForKey:@"PicturePAR"] intValue]; /* If Cropping is set to custom, then recall all four crop values from @@ -2396,6 +2601,8 @@ fWorkingCount = 0; [fPictureController setDeblock:[[queueToApply objectForKey:@"PictureDeblock"] intValue]]; /* Decomb */ [fPictureController setDecomb:[[queueToApply objectForKey:@"PictureDecomb"] intValue]]; + /* Grayscale */ + [fPictureController setGrayscale:[[queueToApply objectForKey:@"VideoGrayScale"] intValue]]; [self calculatePictureSizing:nil]; @@ -2445,10 +2652,6 @@ fWorkingCount = 0; { [self writeToActivityLog: "processNewQueueEncode WARNING nothing found in the title list"]; } - else - { - [self writeToActivityLog: "processNewQueueEncode title list is: %d", hb_list_count( list )]; - } NSMutableDictionary * queueToApply = [QueueFileArray objectAtIndex:currentQueueEncodeIndex]; [self writeToActivityLog: "Preset: %s", [[queueToApply objectForKey:@"PresetName"] UTF8String]]; @@ -2456,15 +2659,11 @@ fWorkingCount = 0; job->file = [[queueToApply objectForKey:@"DestinationPath"] UTF8String]; //[self writeToActivityLog: "processNewQueueEncode sending to prepareJob"]; [self prepareJob]; - if( [[queueToApply objectForKey:@"SubtitlesForced"] intValue] == 1 ) - job->subtitle_force = 1; - else - job->subtitle_force = 0; /* - * subtitle of -1 is a scan + * If scanning we need to do some extra setup of the job. */ - if( job->subtitle == -1 ) + if( job->indepth_scan == 1 ) { char *x264opts_tmp; @@ -2474,14 +2673,11 @@ fWorkingCount = 0; */ job->pass = -1; x264opts_tmp = job->x264opts; - job->subtitle = -1; job->x264opts = NULL; job->indepth_scan = 1; - - job->select_subtitle = (hb_subtitle_t**)malloc(sizeof(hb_subtitle_t*)); - *(job->select_subtitle) = NULL; + /* * Add the pre-scan job @@ -2489,24 +2685,13 @@ fWorkingCount = 0; hb_add( fQueueEncodeLibhb, job ); job->x264opts = x264opts_tmp; } - else - job->select_subtitle = NULL; - - /* No subtitle were selected, so reset the subtitle to -1 (which before - * this point meant we were scanning - */ - if( job->subtitle == -2 ) - job->subtitle = -1; + if( [[queueToApply objectForKey:@"VideoTwoPass"] intValue] == 1 ) { - hb_subtitle_t **subtitle_tmp = job->select_subtitle; job->indepth_scan = 0; - /* - * Do not autoselect subtitles on the first pass of a two pass - */ - job->select_subtitle = NULL; + job->pass = 1; @@ -2517,8 +2702,6 @@ fWorkingCount = 0; job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */ strcpy(job->x264opts, [[queueToApply objectForKey:@"x264Option"] UTF8String]); - job->select_subtitle = subtitle_tmp; - hb_add( fQueueEncodeLibhb, job ); } @@ -2535,6 +2718,21 @@ fWorkingCount = 0; /* Lets mark our new encode as 1 or "Encoding" */ [queueToApply setObject:[NSNumber numberWithInt:1] forKey:@"Status"]; [self saveQueueFileItem]; + + /* we need to clean up the subtitle tracks after the job(s) have been set */ + int num_subtitle_tracks = hb_list_count(job->list_subtitle); + int ii; + for(ii = 0; ii < num_subtitle_tracks; ii++) + { + hb_subtitle_t * subtitle; + subtitle = (hb_subtitle_t *)hb_list_item(job->list_subtitle, 0); + + + hb_list_rem(job->list_subtitle, subtitle); + free(subtitle); + } + + /* We should be all setup so let 'er rip */ [self doRip]; } @@ -2552,7 +2750,8 @@ fWorkingCount = 0; [fSrcTitlePopUp indexOfSelectedItem] ); hb_job_t * job = title->job; hb_audio_config_t * audio; - + /* set job->angle for libdvdnav */ + job->angle = [fSrcAnglePopUp indexOfSelectedItem] + 1; /* Chapter selection */ job->chapter_start = [fSrcChapterStartPopUp indexOfSelectedItem] + 1; job->chapter_end = [fSrcChapterEndPopUp indexOfSelectedItem] + 1; @@ -2561,56 +2760,10 @@ fWorkingCount = 0; job->mux = [[fDstFormatPopUp selectedItem] tag]; job->vcodec = [[fVidEncoderPopUp selectedItem] tag]; - - /* If mpeg-4, then set mpeg-4 specific options like chapters and > 4gb file sizes */ - if( [fDstFormatPopUp indexOfSelectedItem] == 0 ) - { - /* We set the largeFileSize (64 bit formatting) variable here to allow for > 4gb files based on the format being - mpeg4 and the checkbox being checked - *Note: this will break compatibility with some target devices like iPod, etc.!!!!*/ - if( [fDstMp4LargeFileCheck state] == NSOnState ) - { - job->largeFileSize = 1; - } - else - { - job->largeFileSize = 0; - } - /* We set http optimized mp4 here */ - if( [fDstMp4HttpOptFileCheck state] == NSOnState && [fDstMp4HttpOptFileCheck isEnabled] ) - { - job->mp4_optimize = 1; - } - else - { - job->mp4_optimize = 0; - } - } - if( [fDstFormatPopUp indexOfSelectedItem] == 0 || [fDstFormatPopUp indexOfSelectedItem] == 1 ) - { - /* We set the chapter marker extraction here based on the format being - mpeg4 or mkv and the checkbox being checked */ - if ([fCreateChapterMarkers state] == NSOnState) - { - job->chapter_markers = 1; - } - else - { - job->chapter_markers = 0; - } - } - - if( job->vcodec & HB_VCODEC_X264 ) + job->chapter_markers = 0; + + if( job->vcodec & HB_VCODEC_X264 ) { - if ([fDstMp4iPodFileCheck state] == NSOnState) - { - job->ipod_atom = 1; - } - else - { - job->ipod_atom = 0; - } - /* Set this flag to switch from Constant Quantizer(default) to Constant Rate Factor Thanks jbrjake Currently only used with Constant Quality setting*/ if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultCrf"] > 0 && [fVidQualityMatrix selectedRow] == 2) @@ -2670,16 +2823,131 @@ fWorkingCount = 0; job->vbitrate = [fVidBitrateField intValue]; break; case 2: - job->vquality = [fVidQualitySlider floatValue]; + job->vquality = [fVidQualityRFField floatValue]; job->vbitrate = 0; break; } - job->grayscale = ( [fVidGrayscaleCheck state] == NSOnState ); - /* Subtitle settings */ - job->subtitle = [fSubPopUp indexOfSelectedItem] - 2; + NSMutableArray *subtitlesArray = nil; + subtitlesArray = [[NSMutableArray alloc] initWithArray:[fSubtitlesDelegate getSubtitleArray: subtitlesArray]]; + + + + int subtitle = nil; +int force; +int burned; +int def; +bool one_burned = FALSE; + + int i = 0; + NSEnumerator *enumerator = [subtitlesArray objectEnumerator]; + id tempObject; + while (tempObject = [enumerator nextObject]) + { + + subtitle = [[tempObject objectForKey:@"subtitleSourceTrackNum"] intValue]; + force = [[tempObject objectForKey:@"subtitleTrackForced"] intValue]; + burned = [[tempObject objectForKey:@"subtitleTrackBurned"] intValue]; + def = [[tempObject objectForKey:@"subtitleTrackDefault"] intValue]; + + /* since the subtitleSourceTrackNum 0 is "None" in our array of the subtitle popups, + * we want to ignore it for display as well as encoding. + */ + if (subtitle > 0) + { + /* if i is 0, then we are in the first item of the subtitles which we need to + * check for the "Foreign Audio Search" which would be subtitleSourceTrackNum of 1 + * bearing in mind that for all tracks subtitleSourceTrackNum of 0 is None. + */ + + /* if we are on the first track and using "Foreign Audio Search" */ + if (i == 0 && subtitle == 1) + { + /* NOTE: Currently foreign language search is borked for preview. + * Commented out but left in for initial commit. */ + + /* + [self writeToActivityLog: "Foreign Language Search: %d", 1]; + + job->indepth_scan = 1; + if (burned == 1 || job->mux != HB_MUX_MP4) + { + if (burned != 1 && job->mux == HB_MUX_MKV) + { + job->select_subtitle_config.dest = hb_subtitle_config_s::PASSTHRUSUB; + } + + job->select_subtitle_config.force = force; + job->select_subtitle_config.default_track = def; + + } + */ + + } + else + { + + /* for the actual source tracks, we must subtract the non source entries so + * that the menu index matches the source subtitle_list index for convenience */ + if (i == 0) + { + /* for the first track, the source tracks start at menu index 2 ( None is 0, + * Foreign Language Search is 1) so subtract 2 */ + subtitle = subtitle - 2; + } + else + { + /* for all other tracks, the source tracks start at menu index 1 (None is 0) + * so subtract 1. */ + + subtitle = subtitle - 1; + } + + /* We are setting a source subtitle so access the source subtitle info */ + hb_subtitle_t * subt; + + subt = (hb_subtitle_t *)hb_list_item(title->list_subtitle, subtitle); + + if (subt != NULL) + { + [self writeToActivityLog: "Setting Subtitle: %s", subt]; + hb_subtitle_config_t sub_config = subt->config; + + if (!burned && job->mux == HB_MUX_MKV && + subt->format == hb_subtitle_s::PICTURESUB) + { + sub_config.dest = hb_subtitle_config_s::PASSTHRUSUB; + } + else if (!burned && job->mux == HB_MUX_MP4 && + subt->format == hb_subtitle_s::PICTURESUB) + { + // Skip any non-burned vobsubs when output is mp4 + continue; + } + else if ( burned && subt->format == hb_subtitle_s::PICTURESUB ) + { + // Only allow one subtitle to be burned into the video + if (one_burned) + continue; + one_burned = TRUE; + } + sub_config.force = force; + sub_config.default_track = def; + hb_subtitle_add( job, &sub_config, subtitle ); + } + + } + } + i++; + } + + + +[subtitlesArray autorelease]; + + /* Audio tracks and mixdowns */ /* Lets make sure there arent any erroneous audio tracks in the job list, so lets make sure its empty*/ int audiotrack_count = hb_list_count(job->list_audio); @@ -2761,7 +3029,22 @@ fWorkingCount = 0; - /* Filters */ + /* Filters */ + + /* Though Grayscale is not really a filter, per se + * we put it here since its in the filters panel + */ + + if ([fPictureController grayscale]) + { + job->grayscale = 1; + } + else + { + job->grayscale = 0; + } + + /* Initialize the filters list */ job->filters = hb_list_init(); /* Now lets call the filters if applicable. @@ -2769,42 +3052,63 @@ fWorkingCount = 0; */ /* Detelecine */ - if ([fPictureController detelecine]) + if ([fPictureController detelecine] == 1) { hb_list_add( job->filters, &hb_filter_detelecine ); } - - /* Decomb */ - if ([fPictureController decomb] > 0) - { - /* Run old deinterlacer fd by default */ - //fPicSettingDecomb - hb_filter_decomb.settings = (char *) [[fPicSettingDecomb stringValue] UTF8String]; - //hb_filter_decomb.settings = "4:10:15:9:10:35:9"; // <-- jbrjakes recommended parameters as of 5/23/08 - hb_list_add( job->filters, &hb_filter_decomb ); - } - - - /* Deinterlace */ - if ([fPictureController deinterlace] == 1) + if ([fPictureController detelecine] == 2) { - /* Run old deinterlacer fd by default */ - hb_filter_deinterlace.settings = "-1"; - hb_list_add( job->filters, &hb_filter_deinterlace ); + /* use a custom detelecine string */ + hb_filter_detelecine.settings = (char *) [[fPictureController detelecineCustomString] UTF8String]; + hb_list_add( job->filters, &hb_filter_detelecine ); } - else if ([fPictureController deinterlace] == 2) + if ([fPictureController useDecomb] == 1) { - /* Yadif mode 0 (without spatial deinterlacing.) */ - hb_filter_deinterlace.settings = "2"; - hb_list_add( job->filters, &hb_filter_deinterlace ); + /* Decomb */ + if ([fPictureController decomb] == 1) + { + /* Run old deinterlacer fd by default */ + //hb_filter_decomb.settings = (char *) [[fPicSettingDecomb stringValue] UTF8String]; + hb_list_add( job->filters, &hb_filter_decomb ); + } + /* we add the custom string if present */ + if ([fPictureController decomb] == 2) + { + /* use a custom decomb string */ + hb_filter_decomb.settings = (char *) [[fPictureController decombCustomString] UTF8String]; + hb_list_add( job->filters, &hb_filter_decomb ); + } } - else if ([fPictureController deinterlace] == 3) + else { - /* Yadif (with spatial deinterlacing) */ - hb_filter_deinterlace.settings = "0"; - hb_list_add( job->filters, &hb_filter_deinterlace ); - } - + + /* Deinterlace */ + if ([fPictureController deinterlace] == 1) + { + /* Run old deinterlacer fd by default */ + hb_filter_deinterlace.settings = "-1"; + hb_list_add( job->filters, &hb_filter_deinterlace ); + } + else if ([fPictureController deinterlace] == 2) + { + /* Yadif mode 0 (without spatial deinterlacing.) */ + hb_filter_deinterlace.settings = "2"; + hb_list_add( job->filters, &hb_filter_deinterlace ); + } + else if ([fPictureController deinterlace] == 3) + { + /* Yadif (with spatial deinterlacing) */ + hb_filter_deinterlace.settings = "0"; + hb_list_add( job->filters, &hb_filter_deinterlace ); + } + else if ([fPictureController deinterlace] == 4) + { + /* we add the custom string if present */ + hb_filter_deinterlace.settings = (char *) [[fPictureController deinterlaceCustomString] UTF8String]; + hb_list_add( job->filters, &hb_filter_deinterlace ); + } + } + /* Denoise */ if ([fPictureController denoise] == 1) // Weak in popup { @@ -2821,10 +3125,22 @@ fWorkingCount = 0; hb_filter_denoise.settings = "7:7:5:5"; hb_list_add( job->filters, &hb_filter_denoise ); } + else if ([fPictureController denoise] == 4) // custom in popup + { + /* we add the custom string if present */ + hb_filter_denoise.settings = (char *) [[fPictureController denoiseCustomString] UTF8String]; + hb_list_add( job->filters, &hb_filter_denoise ); + } /* Deblock (uses pp7 default) */ - if ([fPictureController deblock]) + /* NOTE: even though there is a valid deblock setting of 0 for the filter, for + * the macgui's purposes a value of 0 actually means to not even use the filter + * current hb_filter_deblock.settings valid ranges are from 5 - 15 + */ + if ([fPictureController deblock] != 0) { + NSString *deblockStringValue = [NSString stringWithFormat: @"%d",[fPictureController deblock]]; + hb_filter_deblock.settings = (char *) [deblockStringValue UTF8String]; hb_list_add( job->filters, &hb_filter_deblock ); } @@ -2843,6 +3159,8 @@ fWorkingCount = 0; hb_title_t * title = (hb_title_t *) hb_list_item( list,0 ); // is always zero since now its a single title scan hb_job_t * job = title->job; hb_audio_config_t * audio; + /* Title Angle for dvdnav */ + job->angle = [[queueToApply objectForKey:@"TitleAngle"] intValue]; /* Chapter selection */ job->chapter_start = [[queueToApply objectForKey:@"JobChapterStart"] intValue]; job->chapter_end = [[queueToApply objectForKey:@"JobChapterEnd"] intValue]; @@ -2853,11 +3171,6 @@ fWorkingCount = 0; /* If mpeg-4, then set mpeg-4 specific options like chapters and > 4gb file sizes */ - //if( [fDstFormatPopUp indexOfSelectedItem] == 0 ) - //{ - /* We set the largeFileSize (64 bit formatting) variable here to allow for > 4gb files based on the format being - mpeg4 and the checkbox being checked - *Note: this will break compatibility with some target devices like iPod, etc.!!!!*/ if( [[queueToApply objectForKey:@"Mp4LargeFile"] intValue] == 1) { job->largeFileSize = 1; @@ -2875,8 +3188,7 @@ fWorkingCount = 0; { job->mp4_optimize = 0; } - - //} + /* We set the chapter marker extraction here based on the format being mpeg4 or mkv and the checkbox being checked */ @@ -2955,8 +3267,19 @@ fWorkingCount = 0; job->height = [[queueToApply objectForKey:@"PictureHeight"] intValue]; job->keep_ratio = [[queueToApply objectForKey:@"PictureKeepRatio"] intValue]; - job->pixel_ratio = [[queueToApply objectForKey:@"PicturePAR"] intValue]; - + job->anamorphic.mode = [[queueToApply objectForKey:@"PicturePAR"] intValue]; + if ([[queueToApply objectForKey:@"PicturePAR"] intValue] == 3) + { + /* insert our custom values here for capuj */ + job->width = [[queueToApply objectForKey:@"PicturePARStorageWidth"] intValue]; + job->height = [[queueToApply objectForKey:@"PicturePARStorageHeight"] intValue]; + + job->anamorphic.par_width = [[queueToApply objectForKey:@"PicturePARPixelWidth"] intValue]; + job->anamorphic.par_height = [[queueToApply objectForKey:@"PicturePARPixelHeight"] intValue]; + + job->anamorphic.dar_width = [[queueToApply objectForKey:@"PicturePARDisplayWidth"] floatValue]; + job->anamorphic.dar_height = [[queueToApply objectForKey:@"PicturePARDisplayHeight"] floatValue]; + } /* Here we use the crop values saved at the time the preset was saved */ job->crop[0] = [[queueToApply objectForKey:@"PictureTopCrop"] intValue]; @@ -3014,9 +3337,131 @@ fWorkingCount = 0; } job->grayscale = [[queueToApply objectForKey:@"VideoGrayScale"] intValue]; - /* Subtitle settings */ - job->subtitle = [[queueToApply objectForKey:@"JobSubtitlesIndex"] intValue] - 2; + + +#pragma mark - +#pragma mark Process Subtitles to libhb + +/* Map the settings in the dictionaries for the SubtitleList array to match title->list_subtitle + * which means that we need to account for the offset of non source language settings in from + * the NSPopUpCell menu. For all of the objects in the SubtitleList array this means 0 is "None" + * from the popup menu, additionally the first track has "Foreign Audio Search" at 1. So we use + * an int to offset the index number for the objectForKey:@"subtitleSourceTrackNum" to map that + * to the source tracks position in title->list_subtitle. + */ + +int subtitle = nil; +int force; +int burned; +int def; +bool one_burned = FALSE; + + int i = 0; + NSEnumerator *enumerator = [[queueToApply objectForKey:@"SubtitleList"] objectEnumerator]; + id tempObject; + while (tempObject = [enumerator nextObject]) + { + + subtitle = [[tempObject objectForKey:@"subtitleSourceTrackNum"] intValue]; + force = [[tempObject objectForKey:@"subtitleTrackForced"] intValue]; + burned = [[tempObject objectForKey:@"subtitleTrackBurned"] intValue]; + def = [[tempObject objectForKey:@"subtitleTrackDefault"] intValue]; + + /* since the subtitleSourceTrackNum 0 is "None" in our array of the subtitle popups, + * we want to ignore it for display as well as encoding. + */ + if (subtitle > 0) + { + /* if i is 0, then we are in the first item of the subtitles which we need to + * check for the "Foreign Audio Search" which would be subtitleSourceTrackNum of 1 + * bearing in mind that for all tracks subtitleSourceTrackNum of 0 is None. + */ + + /* if we are on the first track and using "Foreign Audio Search" */ + if (i == 0 && subtitle == 1) + { + [self writeToActivityLog: "Foreign Language Search: %d", 1]; + + job->indepth_scan = 1; + if (burned == 1 || job->mux != HB_MUX_MP4) + { + if (burned != 1 && job->mux == HB_MUX_MKV) + { + job->select_subtitle_config.dest = hb_subtitle_config_s::PASSTHRUSUB; + } + else + { + job->select_subtitle_config.dest = hb_subtitle_config_s::RENDERSUB; + } + + job->select_subtitle_config.force = force; + job->select_subtitle_config.default_track = def; + } + + + } + else + { + + /* for the actual source tracks, we must subtract the non source entries so + * that the menu index matches the source subtitle_list index for convenience */ + if (i == 0) + { + /* for the first track, the source tracks start at menu index 2 ( None is 0, + * Foreign Language Search is 1) so subtract 2 */ + subtitle = subtitle - 2; + } + else + { + /* for all other tracks, the source tracks start at menu index 1 (None is 0) + * so subtract 1. */ + + subtitle = subtitle - 1; + } + + /* We are setting a source subtitle so access the source subtitle info */ + hb_subtitle_t * subt; + + subt = (hb_subtitle_t *)hb_list_item(title->list_subtitle, subtitle); + + if (subt != NULL) + { + [self writeToActivityLog: "Setting Subtitle: %s", subt]; + + hb_subtitle_config_t sub_config = subt->config; + + if (!burned && job->mux == HB_MUX_MKV && + subt->format == hb_subtitle_s::PICTURESUB) + { + sub_config.dest = hb_subtitle_config_s::PASSTHRUSUB; + } + else if (!burned && job->mux == HB_MUX_MP4 && + subt->format == hb_subtitle_s::PICTURESUB) + { + // Skip any non-burned vobsubs when output is mp4 + continue; + } + else if ( burned && subt->format == hb_subtitle_s::PICTURESUB ) + { + // Only allow one subtitle to be burned into the video + if (one_burned) + continue; + one_burned = TRUE; + } + sub_config.force = force; + sub_config.default_track = def; + hb_subtitle_add( job, &sub_config, subtitle ); + } + + } + } + i++; + } + +#pragma mark - + + /* Audio tracks and mixdowns */ /* Lets make sure there arent any erroneous audio tracks in the job list, so lets make sure its empty*/ int audiotrack_count = hb_list_count(job->list_audio); @@ -3092,7 +3537,8 @@ fWorkingCount = 0; audio->out.dynamic_range_compression = [[queueToApply objectForKey:@"Audio4TrackDRCSlider"] floatValue]; hb_audio_add( job, audio ); - free(audio); + + } /* Filters */ @@ -3104,37 +3550,64 @@ fWorkingCount = 0; /* Detelecine */ if ([[queueToApply objectForKey:@"PictureDetelecine"] intValue] == 1) { + //if ([queueToApply objectForKey:@"PictureDetelecineCustom"]) hb_list_add( job->filters, &hb_filter_detelecine ); } - - /* Decomb */ - if ([[queueToApply objectForKey:@"PictureDecomb"] intValue] == 1) + if ([[queueToApply objectForKey:@"PictureDetelecine"] intValue] == 2) { - /* Run old deinterlacer fd by default */ - hb_filter_decomb.settings = (char *) [[queueToApply objectForKey:@"JobPictureDecomb"] UTF8String]; - hb_list_add( job->filters, &hb_filter_decomb ); + /* use a custom detelecine string */ + hb_filter_detelecine.settings = (char *) [[queueToApply objectForKey:@"PictureDetelecineCustom"] UTF8String]; + hb_list_add( job->filters, &hb_filter_detelecine ); } - /* Deinterlace */ - if ([[queueToApply objectForKey:@"PictureDeinterlace"] intValue] == 1) + if ([[queueToApply objectForKey:@"PictureDecombDeinterlace"] intValue] == 1) { - /* Run old deinterlacer fd by default */ - hb_filter_deinterlace.settings = "-1"; - hb_list_add( job->filters, &hb_filter_deinterlace ); - } - else if ([[queueToApply objectForKey:@"PictureDeinterlace"] intValue] == 2) - { - /* Yadif mode 0 (without spatial deinterlacing.) */ - hb_filter_deinterlace.settings = "2"; - hb_list_add( job->filters, &hb_filter_deinterlace ); + /* Decomb */ + if ([[queueToApply objectForKey:@"PictureDecomb"] intValue] == 1) + { + /* Run old deinterlacer fd by default */ + hb_list_add( job->filters, &hb_filter_decomb ); + } + /* we add the custom string if present */ + if ([[queueToApply objectForKey:@"PictureDecomb"] intValue] == 2) + { + /* use a custom decomb string */ + hb_filter_decomb.settings = (char *) [[queueToApply objectForKey:@"PictureDecombCustom"] UTF8String]; + hb_list_add( job->filters, &hb_filter_decomb ); + } + } - else if ([[queueToApply objectForKey:@"PictureDeinterlace"] intValue] == 3) + else { - /* Yadif (with spatial deinterlacing) */ - hb_filter_deinterlace.settings = "0"; - hb_list_add( job->filters, &hb_filter_deinterlace ); + + /* Deinterlace */ + if ([[queueToApply objectForKey:@"PictureDeinterlace"] intValue] == 1) + { + /* Run old deinterlacer fd by default */ + hb_filter_deinterlace.settings = "-1"; + hb_list_add( job->filters, &hb_filter_deinterlace ); + } + else if ([[queueToApply objectForKey:@"PictureDeinterlace"] intValue] == 2) + { + /* Yadif mode 0 (without spatial deinterlacing.) */ + hb_filter_deinterlace.settings = "2"; + hb_list_add( job->filters, &hb_filter_deinterlace ); + } + else if ([[queueToApply objectForKey:@"PictureDeinterlace"] intValue] == 3) + { + /* Yadif (with spatial deinterlacing) */ + hb_filter_deinterlace.settings = "0"; + hb_list_add( job->filters, &hb_filter_deinterlace ); + } + else if ([[queueToApply objectForKey:@"PictureDeinterlace"] intValue] == 4) + { + /* we add the custom string if present */ + hb_filter_deinterlace.settings = (char *) [[queueToApply objectForKey:@"PictureDeinterlaceCustom"] UTF8String]; + hb_list_add( job->filters, &hb_filter_deinterlace ); + } + + } - /* Denoise */ if ([[queueToApply objectForKey:@"PictureDenoise"] intValue] == 1) // Weak in popup { @@ -3151,6 +3624,12 @@ fWorkingCount = 0; hb_filter_denoise.settings = "7:7:5:5"; hb_list_add( job->filters, &hb_filter_denoise ); } + else if ([[queueToApply objectForKey:@"PictureDenoise"] intValue] == 4) // Custom in popup + { + /* we add the custom string if present */ + hb_filter_denoise.settings = (char *) [[queueToApply objectForKey:@"PictureDenoiseCustom"] UTF8String]; + hb_list_add( job->filters, &hb_filter_denoise ); + } /* Deblock (uses pp7 default) */ /* NOTE: even though there is a valid deblock setting of 0 for the filter, for @@ -3179,18 +3658,51 @@ fWorkingCount = 0; NSRunAlertPanel(@"Warning!", @"This is not a valid destination directory!", @"OK", nil, nil); return; } - - /* We check for duplicate name here */ - if( [[NSFileManager defaultManager] fileExistsAtPath: - [fDstFile2Field stringValue]] ) + + BOOL fileExists; + fileExists = NO; + + BOOL fileExistsInQueue; + fileExistsInQueue = NO; + + /* We check for and existing file here */ + if([[NSFileManager defaultManager] fileExistsAtPath: [fDstFile2Field stringValue]]) { - NSBeginCriticalAlertSheet( NSLocalizedString( @"File already exists", @"" ), - NSLocalizedString( @"Cancel", @"" ), NSLocalizedString( @"Overwrite", @"" ), nil, fWindow, self, - @selector( overwriteAddToQueueAlertDone:returnCode:contextInfo: ), - NULL, NULL, [NSString stringWithFormat: - NSLocalizedString( @"Do you want to overwrite %@?", @"" ), - [fDstFile2Field stringValue]] ); - // overwriteAddToQueueAlertDone: will be called when the alert is dismissed. + fileExists = YES; + } + + /* We now run through the queue and make sure we are not overwriting an exisiting queue item */ + int i = 0; + NSEnumerator *enumerator = [QueueFileArray objectEnumerator]; + id tempObject; + while (tempObject = [enumerator nextObject]) + { + NSDictionary *thisQueueDict = tempObject; + if ([[thisQueueDict objectForKey:@"DestinationPath"] isEqualToString: [fDstFile2Field stringValue]]) + { + fileExistsInQueue = YES; + } + i++; + } + + + if(fileExists == YES) + { + NSBeginCriticalAlertSheet( NSLocalizedString( @"File already exists.", @"" ), + NSLocalizedString( @"Cancel", @"" ), NSLocalizedString( @"Overwrite", @"" ), nil, fWindow, self, + @selector( overwriteAddToQueueAlertDone:returnCode:contextInfo: ), + NULL, NULL, [NSString stringWithFormat: + NSLocalizedString( @"Do you want to overwrite %@?", @"" ), + [fDstFile2Field stringValue]] ); + } + else if (fileExistsInQueue == YES) + { + NSBeginCriticalAlertSheet( NSLocalizedString( @"There is already a queue item for this destination.", @"" ), + NSLocalizedString( @"Cancel", @"" ), NSLocalizedString( @"Overwrite", @"" ), nil, fWindow, self, + @selector( overwriteAddToQueueAlertDone:returnCode:contextInfo: ), + NULL, NULL, [NSString stringWithFormat: + NSLocalizedString( @"Do you want to overwrite %@?", @"" ), + [fDstFile2Field stringValue]] ); } else { @@ -3270,15 +3782,13 @@ fWorkingCount = 0; otherwise, just rip the queue */ if(fPendingCount == 0) { - [self writeToActivityLog: "Rip: No pending jobs, so sending this one to doAddToQueue"]; - [self doAddToQueue]; + [self writeToActivityLog: "Rip: No pending jobs, so sending this one to doAddToQueue"]; + [self doAddToQueue]; } - NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent]; - [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"]; /* go right to processing the new queue encode */ - [self writeToActivityLog: "Rip: Going right to performNewQueueScan"]; - [self performNewQueueScan:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SourcePath"] scanTitleNum:[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"TitleNumber"]intValue]]; + [self writeToActivityLog: "Rip: Going right to performNewQueueScan"]; + [self performNewQueueScan:[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SourcePath"] scanTitleNum:[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"TitleNumber"]intValue]]; } } @@ -3504,18 +4014,31 @@ fWorkingCount = 0; [fSrcChapterEndPopUp selectItemAtIndex: hb_list_count( title->list_chapter ) - 1]; [self chapterPopUpChanged:nil]; - + + /* if using dvd nav, show the angle widget */ + if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"UseDvdNav"] boolValue]) + { + [fSrcAngleLabel setHidden:NO]; + [fSrcAnglePopUp setHidden:NO]; + + [fSrcAnglePopUp removeAllItems]; + for( int i = 0; i < title->angle_count; i++ ) + { + [fSrcAnglePopUp addItemWithTitle: [NSString stringWithFormat: @"%d", i + 1]]; + } + [fSrcAnglePopUp selectItemAtIndex: 0]; + } + else + { + [fSrcAngleLabel setHidden:YES]; + [fSrcAnglePopUp setHidden:YES]; + } + /* Start Get and set the initial pic size for display */ hb_job_t * job = title->job; fTitle = title; - /* Reset the new title in fPictureController */ - [fPictureController SetTitle:title]; - - /*Set Source Size Field Here */ - [fPicSettingsSrc setStringValue: [NSString stringWithFormat: @"%d x %d", fTitle->width, fTitle->height]]; - - /* Set Auto Crop to on upon selecting a new title */ + /* Set Auto Crop to on upon selecting a new title */ [fPictureController setAutoCrop:YES]; /* We get the originial output picture width and height and put them @@ -3527,28 +4050,14 @@ fWorkingCount = 0; AutoCropLeft = job->crop[2]; AutoCropRight = job->crop[3]; - /* Run Through encoderPopUpChanged to see if there - needs to be any pic value modifications based on encoder settings */ - //[self encoderPopUpChanged: NULL]; - /* END Get and set the initial pic size for display */ - - /* Update subtitle popups */ - hb_subtitle_t * subtitle; - [fSubPopUp removeAllItems]; - [fSubPopUp addItemWithTitle: @"None"]; - [fSubPopUp addItemWithTitle: @"Autoselect"]; - for( int i = 0; i < hb_list_count( title->list_subtitle ); i++ ) - { - subtitle = (hb_subtitle_t *) hb_list_item( title->list_subtitle, i ); - - /* We cannot use NSPopUpButton's addItemWithTitle because - it checks for duplicate entries */ - [[fSubPopUp menu] addItemWithTitle: [NSString stringWithCString: - subtitle->lang] action: NULL keyEquivalent: @""]; - } - [fSubPopUp selectItemAtIndex: 0]; + /* Reset the new title in fPictureController && fPreviewController*/ + [fPictureController SetTitle:title]; - [self subtitleSelectionChanged:nil]; + + /* Update Subtitle Table */ + [fSubtitlesDelegate resetWithTitle:title]; + [fSubtitlesTable reloadData]; + /* Update chapter table */ [fChapterTitlesDelegate resetWithTitle:title]; @@ -3587,7 +4096,7 @@ fWorkingCount = 0; [self calculatePictureSizing:nil]; /* lets call tableViewSelected to make sure that any preset we have selected is enforced after a title change */ - [self selectPreset:nil]; + [self selectPreset:nil]; } - (IBAction) chapterPopUpChanged: (id) sender @@ -3620,6 +4129,17 @@ fWorkingCount = 0; duration % 60]]; [self calculateBitrate: sender]; + + if ( [fSrcChapterStartPopUp indexOfSelectedItem] == [fSrcChapterEndPopUp indexOfSelectedItem] ) + { + /* Disable chapter markers for any source with less than two chapters as it makes no sense. */ + [fCreateChapterMarkers setEnabled: NO]; + [fCreateChapterMarkers setState: NSOffState]; + } + else + { + [fCreateChapterMarkers setEnabled: YES]; + } } - (IBAction) formatPopUpChanged: (id) sender @@ -3633,6 +4153,10 @@ fWorkingCount = 0; [fDstMp4iPodFileCheck setHidden: YES]; /* Update the Video Codec PopUp */ + /* lets get the tag of the currently selected item first so we might reset it later */ + int selectedVidEncoderTag; + selectedVidEncoderTag = [[fVidEncoderPopUp selectedItem] tag]; + /* Note: we now store the video encoder int values from common.c in the tags of each popup for easy retrieval later */ [fVidEncoderPopUp removeAllItems]; NSMenuItem *menuItem; @@ -3640,8 +4164,6 @@ fWorkingCount = 0; menuItem = [[fVidEncoderPopUp menu] addItemWithTitle:@"MPEG-4 (FFmpeg)" action: NULL keyEquivalent: @""]; [menuItem setTag: HB_VCODEC_FFMPEG]; - menuItem = [[fVidEncoderPopUp menu] addItemWithTitle:@"MPEG-4 (XviD)" action: NULL keyEquivalent: @""]; - [menuItem setTag: HB_VCODEC_XVID]; switch( format ) { case 0: @@ -3675,27 +4197,21 @@ fWorkingCount = 0; [fCreateChapterMarkers setEnabled: YES]; break; - case 2: - ext = "avi"; - /* Add additional video encoders here */ - menuItem = [[fVidEncoderPopUp menu] addItemWithTitle:@"H.264 (x264)" action: NULL keyEquivalent: @""]; - [menuItem setTag: HB_VCODEC_X264]; - /* We disable the create chapters checkbox here and make sure it is unchecked*/ - [fCreateChapterMarkers setEnabled: NO]; - [fCreateChapterMarkers setState: NSOffState]; - break; - - case 3: - ext = "ogm"; - /* Add additional video encoders here */ - menuItem = [[fVidEncoderPopUp menu] addItemWithTitle:@"VP3 (Theora)" action: NULL keyEquivalent: @""]; - [menuItem setTag: HB_VCODEC_THEORA]; - /* We disable the create chapters checkbox here and make sure it is unchecked*/ - [fCreateChapterMarkers setEnabled: NO]; - [fCreateChapterMarkers setState: NSOffState]; - break; + + } + /* tell fSubtitlesDelegate we have a new video container */ + + [fSubtitlesDelegate containerChanged:[[fDstFormatPopUp selectedItem] tag]]; + [fSubtitlesTable reloadData]; + /* if we have a previously selected vid encoder tag, then try to select it */ + if (selectedVidEncoderTag) + { + [fVidEncoderPopUp selectItemWithTag: selectedVidEncoderTag]; + } + else + { + [fVidEncoderPopUp selectItemAtIndex: 0]; } - [fVidEncoderPopUp selectItemAtIndex: 0]; [self audioAddAudioTrackCodecs: fAudTrack1CodecPopUp]; [self audioAddAudioTrackCodecs: fAudTrack2CodecPopUp]; @@ -3795,9 +4311,9 @@ the user is using "Custom" settings by determining the sender*/ to use the index itself but this is easier */ if (videoEncoder == HB_VCODEC_FFMPEG) { - if (job->pixel_ratio == 2) + if (job->anamorphic.mode == 2) { - job->pixel_ratio = 0; + job->anamorphic.mode = 0; } [fPictureController setAllowLooseAnamorphic:NO]; /* We set the iPod atom checkbox to disabled and uncheck it as its only for x264 in the mp4 @@ -3812,7 +4328,7 @@ the user is using "Custom" settings by determining the sender*/ [fPictureController setAllowLooseAnamorphic:YES]; [fDstMp4iPodFileCheck setEnabled: YES]; } - + [self setupQualitySlider]; [self calculatePictureSizing: sender]; [self twoPassCheckboxChanged: sender]; } @@ -3879,6 +4395,8 @@ the user is using "Custom" settings by determining the sender*/ [fVidTargetSizeField setEnabled: target]; [fVidBitrateField setEnabled: bitrate]; [fVidQualitySlider setEnabled: quality]; + [fVidQualityRFField setEnabled: quality]; + [fVidQualityRFLabel setEnabled: quality]; [fVidTwoPassCheck setEnabled: !quality && [fVidQualityMatrix isEnabled]]; if( quality ) @@ -3893,12 +4411,88 @@ the user is using "Custom" settings by determining the sender*/ [self customSettingUsed: sender]; } +/* Use this method to setup the quality slider for cq/rf values depending on + * the video encoder selected. + */ +- (void) setupQualitySlider +{ + /* Get the current slider maxValue to check for a change in slider scale later + * so that we can choose a new similar value on the new slider scale */ + float previousMaxValue = [fVidQualitySlider maxValue]; + float previousPercentOfSliderScale = [fVidQualitySlider floatValue] / ([fVidQualitySlider maxValue] - [fVidQualitySlider minValue] + 1); + NSString * qpRFLabelString = @"QP:"; + /* x264 0-51 */ + if ([[fVidEncoderPopUp selectedItem] tag] == HB_VCODEC_X264) + { + [fVidQualitySlider setMinValue:0.0]; + [fVidQualitySlider setMaxValue:51.0]; + /* As x264 allows for qp/rf values that are fractional, we get the value from the preferences */ + int fractionalGranularity = 1 / [[NSUserDefaults standardUserDefaults] floatForKey:@"x264CqSliderFractional"]; + [fVidQualitySlider setNumberOfTickMarks:(([fVidQualitySlider maxValue] - [fVidQualitySlider minValue]) * fractionalGranularity) + 1]; + if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultCrf"] > 0) + { + qpRFLabelString = @"RF:"; + } + } + /* ffmpeg 1-31 */ + if ([[fVidEncoderPopUp selectedItem] tag] == HB_VCODEC_FFMPEG ) + { + [fVidQualitySlider setMinValue:1.0]; + [fVidQualitySlider setMaxValue:31.0]; + [fVidQualitySlider setNumberOfTickMarks:31]; + } + /* Theora 0-63 */ + if ([[fVidEncoderPopUp selectedItem] tag] == HB_VCODEC_THEORA) + { + [fVidQualitySlider setMinValue:0.0]; + [fVidQualitySlider setMaxValue:63.0]; + [fVidQualitySlider setNumberOfTickMarks:64]; + } + [fVidQualityRFLabel setStringValue:qpRFLabelString]; + + /* check to see if we have changed slider scales */ + if (previousMaxValue != [fVidQualitySlider maxValue]) + { + /* if so, convert the old setting to the new scale as close as possible based on percentages */ + float rf = ([fVidQualitySlider maxValue] - [fVidQualitySlider minValue] + 1) * previousPercentOfSliderScale; + [fVidQualitySlider setFloatValue:rf]; + } + + [self qualitySliderChanged:nil]; +} + - (IBAction) qualitySliderChanged: (id) sender { + /* Our constant quality slider is in a range based + * on each encoders qp/rf values. The range depends + * on the encoder. Also, the range is inverse of quality + * for all of the encoders *except* for theora + * (ie. as the "quality" goes up, the cq or rf value + * actually goes down). Since the IB sliders always set + * their max value at the right end of the slider, we + * will calculate the inverse, so as the slider floatValue + * goes up, we will show the inverse in the rf field + * so, the floatValue at the right for x264 would be 51 + * and our rf field needs to show 0 and vice versa. + */ + + float sliderRfInverse = ([fVidQualitySlider maxValue] - [fVidQualitySlider floatValue]) + [fVidQualitySlider minValue]; + /* If the encoder is theora, use the float, otherwise use the inverse float*/ + float sliderRfToPercent; + if ([[fVidEncoderPopUp selectedItem] tag] == HB_VCODEC_THEORA) + { + [fVidQualityRFField setStringValue: [NSString stringWithFormat: @"%.2f", [fVidQualitySlider floatValue]]]; + sliderRfToPercent = [fVidQualityRFField floatValue] / ([fVidQualitySlider maxValue] - [fVidQualitySlider minValue]); + } + else + { + [fVidQualityRFField setStringValue: [NSString stringWithFormat: @"%.2f", sliderRfInverse]]; + sliderRfToPercent = ( ([fVidQualitySlider maxValue] - [fVidQualitySlider minValue]) - ([fVidQualityRFField floatValue] - [fVidQualitySlider minValue])) / ([fVidQualitySlider maxValue] - [fVidQualitySlider minValue]); + } [fVidConstantCell setTitle: [NSString stringWithFormat: - NSLocalizedString( @"Constant quality: %.0f %%", @"" ), 100.0 * - [fVidQualitySlider floatValue]]]; - [self customSettingUsed: sender]; + NSLocalizedString( @"Constant quality: %.2f %%", @"" ), 100 * sliderRfToPercent]]; + + [self customSettingUsed: sender]; } - (void) controlTextDidChange: (NSNotification *) notification @@ -4021,9 +4615,9 @@ the user is using "Custom" settings by determining the sender*/ - (IBAction) revertPictureSizeToMax: (id) sender { hb_job_t * job = fTitle->job; - /* Here we apply the max source storage width and height */ - job->width = fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3]; - job->height = fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1]; + /* Here we apply the title source and height */ + job->width = fTitle->width; + job->height = fTitle->height; [self calculatePictureSizing: sender]; /* We call method to change UI to reflect whether a preset is used or not*/ @@ -4034,149 +4628,123 @@ the user is using "Custom" settings by determining the sender*/ * Registers changes made in the Picture Settings Window. */ -- (void)pictureSettingsDidChange { +- (void)pictureSettingsDidChange +{ [self calculatePictureSizing:nil]; } /* Get and Display Current Pic Settings in main window */ - (IBAction) calculatePictureSizing: (id) sender { - [fPicSettingsOutp setStringValue: [NSString stringWithFormat:@"%d x %d", fTitle->job->width, fTitle->job->height]]; - - if (fTitle->job->pixel_ratio == 1) + if (fTitle->job->anamorphic.mode > 0) { - int titlewidth = fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3]; - int arpwidth = fTitle->job->pixel_aspect_width; - int arpheight = fTitle->job->pixel_aspect_height; - int displayparwidth = titlewidth * arpwidth / arpheight; - int displayparheight = fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1]; - [fPicSettingsOutp setStringValue: [NSString stringWithFormat:@"%d x %d", titlewidth, displayparheight]]; - [fPicSettingsAnamorphic setStringValue: [NSString stringWithFormat:@"%d x %d Strict", displayparwidth, displayparheight]]; - fTitle->job->keep_ratio = 0; - } - else if (fTitle->job->pixel_ratio == 2) - { - hb_job_t * job = fTitle->job; - int output_width, output_height, output_par_width, output_par_height; - hb_set_anamorphic_size(job, &output_width, &output_height, &output_par_width, &output_par_height); - int display_width; - display_width = output_width * output_par_width / output_par_height; - - [fPicSettingsOutp setStringValue: [NSString stringWithFormat:@"%d x %d", output_width, output_height]]; - [fPicSettingsAnamorphic setStringValue: [NSString stringWithFormat:@"%d x %d Loose", display_width, output_height]]; - fTitle->job->keep_ratio = 0; - } - else - { - [fPicSettingsAnamorphic setStringValue:@"Off"]; } - - /* Set ON/Off values for the deinterlace/keep aspect ratio according to boolean */ - if (fTitle->job->keep_ratio > 0) + + [fPictureSizeField setStringValue: [NSString stringWithFormat:@"Picture Size: %@", [fPictureController getPictureSizeInfoString]]]; + + NSString *picCropping; + /* Set the display field for crop as per boolean */ + if (![fPictureController autoCrop]) { - [fPicSettingARkeep setStringValue: @"On"]; + picCropping = @"Custom"; } else { - [fPicSettingARkeep setStringValue: @"Off"]; - } + picCropping = @"Auto"; + } + picCropping = [picCropping stringByAppendingString:[NSString stringWithFormat:@" %d/%d/%d/%d",fTitle->job->crop[0],fTitle->job->crop[1],fTitle->job->crop[2],fTitle->job->crop[3]]]; + [fPictureCroppingField setStringValue: [NSString stringWithFormat:@"Picture Cropping: %@",picCropping]]; + + NSString *videoFilters; + videoFilters = @""; /* Detelecine */ - if ([fPictureController detelecine]) { - [fPicSettingDetelecine setStringValue: @"Yes"]; + if ([fPictureController detelecine] == 1) + { + videoFilters = [videoFilters stringByAppendingString:@" - Detelecine (Default)"]; } - else { - [fPicSettingDetelecine setStringValue: @"No"]; + else if ([fPictureController detelecine] == 2) + { + videoFilters = [videoFilters stringByAppendingString:[NSString stringWithFormat:@" - Detelecine (%@)",[fPictureController detelecineCustomString]]]; } - /* Decomb */ - if ([fPictureController decomb] == 0) - { - [fPicSettingDecomb setStringValue: @"Off"]; - } - else if ([fPictureController decomb] == 1) - { - [fPicSettingDecomb setStringValue: @"1:2:6:9:80:16:16"]; - } - else if ([fPictureController decomb] == 2) + + if ([fPictureController useDecomb] == 1) { - [fPicSettingDecomb setStringValue:[[NSUserDefaults standardUserDefaults] stringForKey:@"DecombCustomString"]]; + /* Decomb */ + if ([fPictureController decomb] == 1) + { + videoFilters = [videoFilters stringByAppendingString:@" - Decomb (Default)"]; + } + else if ([fPictureController decomb] == 2) + { + videoFilters = [videoFilters stringByAppendingString:[NSString stringWithFormat:@" - Decomb (%@)",[fPictureController decombCustomString]]]; + } } - - /* VFR (Variable Frame Rate) */ + else + { + /* Deinterlace */ + if ([fPictureController deinterlace] > 0) + { + fTitle->job->deinterlace = 1; + } + else + { + fTitle->job->deinterlace = 0; + } + + if ([fPictureController deinterlace] == 1) + { + videoFilters = [videoFilters stringByAppendingString:@" - Deinterlace (Fast)"]; + } + else if ([fPictureController deinterlace] == 2) + { + videoFilters = [videoFilters stringByAppendingString:@" - Deinterlace (Slow)"]; + } + else if ([fPictureController deinterlace] == 3) + { + videoFilters = [videoFilters stringByAppendingString:@" - Deinterlace (Slower)"]; + } + else if ([fPictureController deinterlace] == 4) + { + videoFilters = [videoFilters stringByAppendingString:[NSString stringWithFormat:@" - Deinterlace (%@)",[fPictureController deinterlaceCustomString]]]; + } + } - /* Deinterlace */ - if ([fPictureController deinterlace] == 0) - { - [fPicSettingDeinterlace setStringValue: @"Off"]; - } - else if ([fPictureController deinterlace] == 1) - { - [fPicSettingDeinterlace setStringValue: @"Fast"]; - } - else if ([fPictureController deinterlace] == 2) - { - [fPicSettingDeinterlace setStringValue: @"Slow"]; - } - else if ([fPictureController deinterlace] == 3) - { - [fPicSettingDeinterlace setStringValue: @"Slower"]; - } - /* Denoise */ - if ([fPictureController denoise] == 0) + if ([fPictureController denoise] == 1) { - [fPicSettingDenoise setStringValue: @"Off"]; - } - else if ([fPictureController denoise] == 1) - { - [fPicSettingDenoise setStringValue: @"Weak"]; - } + videoFilters = [videoFilters stringByAppendingString:@" - Denoise (Weak)"]; + } else if ([fPictureController denoise] == 2) { - [fPicSettingDenoise setStringValue: @"Medium"]; - } + videoFilters = [videoFilters stringByAppendingString:@" - Denoise (Medium)"]; + } else if ([fPictureController denoise] == 3) { - [fPicSettingDenoise setStringValue: @"Strong"]; + videoFilters = [videoFilters stringByAppendingString:@" - Denoise (Strong)"]; + } + else if ([fPictureController denoise] == 4) + { + videoFilters = [videoFilters stringByAppendingString:[NSString stringWithFormat:@" - Denoise (%@)",[fPictureController denoiseCustomString]]]; } /* Deblock */ - if ([fPictureController deblock] == 0) + if ([fPictureController deblock] > 0) { - [fPicSettingDeblock setStringValue: @"Off"]; + videoFilters = [videoFilters stringByAppendingString:[NSString stringWithFormat:@" - Deblock (%d)",[fPictureController deblock]]]; } - else + + /* Grayscale */ + if ([fPictureController grayscale]) { - [fPicSettingDeblock setStringValue: [NSString stringWithFormat:@"%d",[fPictureController deblock]]]; + videoFilters = [videoFilters stringByAppendingString:@" - Grayscale"]; } - - if (fTitle->job->pixel_ratio > 0) - { - [fPicSettingPAR setStringValue: @""]; - } - else - { - [fPicSettingPAR setStringValue: @"Off"]; - } - - /* Set the display field for crop as per boolean */ - if (![fPictureController autoCrop]) - { - [fPicSettingAutoCrop setStringValue: @"Custom"]; - } - else - { - [fPicSettingAutoCrop setStringValue: @"Auto"]; - } - -//[self showPicturePanel:self]; -hb_list_t * list = hb_get_titles( fHandle ); - hb_title_t * title = (hb_title_t *) hb_list_item( list, - [fSrcTitlePopUp indexOfSelectedItem] ); - [fPictureController SetTitle:title]; + [fVideoFiltersField setStringValue: [NSString stringWithFormat:@"Video Filters: %@", videoFilters]]; + + //[fPictureController reloadStillPreview]; } @@ -4278,7 +4846,7 @@ hb_list_t * list = hb_get_titles( fHandle ); [fAudTrack1DrcSlider setFloatValue: 1.00]; [self audioDRCSliderChanged: fAudTrack1DrcSlider]; } - else if ([[fAudTrack1MixPopUp selectedItem] tag] == HB_ACODEC_AC3) + else if ([[fAudTrack1MixPopUp selectedItem] tag] == HB_ACODEC_AC3 || [[fAudTrack1MixPopUp selectedItem] tag] == HB_ACODEC_DCA) { [fAudTrack1RatePopUp setEnabled: NO]; [fAudTrack1BitratePopUp setEnabled: NO]; @@ -4302,7 +4870,7 @@ hb_list_t * list = hb_get_titles( fHandle ); [fAudTrack2DrcSlider setFloatValue: 1.00]; [self audioDRCSliderChanged: fAudTrack2DrcSlider]; } - else if ([[fAudTrack2MixPopUp selectedItem] tag] == HB_ACODEC_AC3) + else if ([[fAudTrack2MixPopUp selectedItem] tag] == HB_ACODEC_AC3 || [[fAudTrack2MixPopUp selectedItem] tag] == HB_ACODEC_DCA) { [fAudTrack2RatePopUp setEnabled: NO]; [fAudTrack2BitratePopUp setEnabled: NO]; @@ -4326,7 +4894,7 @@ hb_list_t * list = hb_get_titles( fHandle ); [fAudTrack3DrcSlider setFloatValue: 1.00]; [self audioDRCSliderChanged: fAudTrack3DrcSlider]; } - else if ([[fAudTrack3MixPopUp selectedItem] tag] == HB_ACODEC_AC3) + else if ([[fAudTrack3MixPopUp selectedItem] tag] == HB_ACODEC_AC3 || [[fAudTrack3MixPopUp selectedItem] tag] == HB_ACODEC_DCA) { [fAudTrack3RatePopUp setEnabled: NO]; [fAudTrack3BitratePopUp setEnabled: NO]; @@ -4350,7 +4918,7 @@ hb_list_t * list = hb_get_titles( fHandle ); [fAudTrack4DrcSlider setFloatValue: 1.00]; [self audioDRCSliderChanged: fAudTrack4DrcSlider]; } - else if ([[fAudTrack4MixPopUp selectedItem] tag] == HB_ACODEC_AC3) + else if ([[fAudTrack4MixPopUp selectedItem] tag] == HB_ACODEC_AC3 || [[fAudTrack4MixPopUp selectedItem] tag] == HB_ACODEC_DCA) { [fAudTrack4RatePopUp setEnabled: NO]; [fAudTrack4BitratePopUp setEnabled: NO]; @@ -4453,10 +5021,14 @@ hb_list_t * list = hb_get_titles( fHandle ); { case 0: /* MP4 */ - // AAC + // FAAC menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"AAC (faac)" action: NULL keyEquivalent: @""]; [menuItem setTag: HB_ACODEC_FAAC]; - + + // CA_AAC + menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"AAC (CoreAudio)" action: NULL keyEquivalent: @""]; + [menuItem setTag: HB_ACODEC_CA_AAC]; + // AC3 Passthru menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"AC3 Passthru" action: NULL keyEquivalent: @""]; [menuItem setTag: HB_ACODEC_AC3]; @@ -4464,12 +5036,18 @@ hb_list_t * list = hb_get_titles( fHandle ); case 1: /* MKV */ - // AAC + // FAAC menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"AAC (faac)" action: NULL keyEquivalent: @""]; [menuItem setTag: HB_ACODEC_FAAC]; + // CA_AAC + menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"AAC (CoreAudio)" action: NULL keyEquivalent: @""]; + [menuItem setTag: HB_ACODEC_CA_AAC]; // AC3 Passthru menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"AC3 Passthru" action: NULL keyEquivalent: @""]; [menuItem setTag: HB_ACODEC_AC3]; + // DTS Passthru + menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"DTS Passthru" action: NULL keyEquivalent: @""]; + [menuItem setTag: HB_ACODEC_DCA]; // MP3 menuItem = [[audiocodecPopUp menu] addItemWithTitle:@"MP3 (lame)" action: NULL keyEquivalent: @""]; [menuItem setTag: HB_ACODEC_LAME]; @@ -4635,6 +5213,13 @@ hb_list_t * list = hb_get_titles( fHandle ); action: NULL keyEquivalent: @""]; [menuItem setTag: HB_ACODEC_AC3]; } + else if (audio->in.codec == HB_ACODEC_DCA && acodec == HB_ACODEC_DCA) + { + NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle: + [NSString stringWithCString: "DTS Passthru"] + action: NULL keyEquivalent: @""]; + [menuItem setTag: HB_ACODEC_DCA]; + } else { @@ -4717,6 +5302,17 @@ hb_list_t * list = hb_get_titles( fHandle ); maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[5].amixdown); } + /* do we want to add a DTS Passthru option ? HB_ACODEC_DCA*/ + if (audio->in.codec == HB_ACODEC_DCA && acodec == HB_ACODEC_DCA) + { + NSMenuItem *menuItem = [[mixdownPopUp menu] addItemWithTitle: + [NSString stringWithCString: hb_audio_mixdowns[5].human_readable_name] + action: NULL keyEquivalent: @""]; + [menuItem setTag: HB_ACODEC_DCA]; + if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[5].amixdown; + maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[5].amixdown); + } + /* auto-select the best mixdown based on our saved mixdown preference */ /* for now, this is hard-coded to a "best" mixdown of HB_AMIXDOWN_DOLBYPLII */ @@ -4765,6 +5361,24 @@ hb_list_t * list = hb_get_titles( fHandle ); [audiocodecPopUp selectItemWithTag: HB_ACODEC_FAAC]; } } + + /* In the case of a source track that is not DTS and the user tries to use DTS Passthru (which does not work) + * we force the Audio Codec choice back to a workable codec. We use MP3 for avi and aac for all + * other containers. + */ + if (audio->in.codec != HB_ACODEC_DCA && [[audiocodecPopUp selectedItem] tag] == HB_ACODEC_DCA) + { + /* If we are using the avi container, we select MP3 as there is no aac available*/ + if ([[fDstFormatPopUp selectedItem] tag] == HB_MUX_AVI) + { + [audiocodecPopUp selectItemWithTag: HB_ACODEC_LAME]; + } + else + { + [audiocodecPopUp selectItemWithTag: HB_ACODEC_FAAC]; + } + } + /* Setup our samplerate and bitrate popups we will need based on mixdown */ [self audioTrackMixdownChanged: mixdownPopUp]; } @@ -4856,7 +5470,22 @@ hb_list_t * list = hb_get_titles( fHandle ); maxbitrate = 160; break; } - + + case HB_ACODEC_CA_AAC: + /* check if we have a 6ch discrete conversion in either audio track */ + if ([[mixdownPopUp selectedItem] tag] == HB_AMIXDOWN_6CH) + { + minbitrate = 128; + maxbitrate = 768; + break; + } + else + { + minbitrate = 64; + maxbitrate = 320; + break; + } + case HB_ACODEC_LAME: /* Lame is happy using our min bitrate of 32 kbps */ minbitrate = 32; @@ -4897,7 +5526,7 @@ hb_list_t * list = hb_get_titles( fHandle ); int inputbitrate = audio->in.bitrate / 1000; int inputsamplerate = audio->in.samplerate; - if ([[mixdownPopUp selectedItem] tag] != HB_ACODEC_AC3) + if ([[mixdownPopUp selectedItem] tag] != HB_ACODEC_AC3 && [[mixdownPopUp selectedItem] tag] != HB_ACODEC_DCA) { [bitratePopUp removeAllItems]; @@ -4945,11 +5574,11 @@ hb_list_t * list = hb_get_titles( fHandle ); [sampleratePopUp selectItemWithTag: inputsamplerate]; - /* Since AC3 Pass Thru uses the input ac3 bitrate and sample rate, we get the input tracks - * bitrate and dispay it in the bitrate popup even though libhb happily ignores any bitrate input from + /* Since AC3 Pass Thru and DTS Pass Thru uses the input bitrate and sample rate, we get the input tracks + * bitrate and display it in the bitrate popup even though libhb happily ignores any bitrate input from * the gui. We do this for better user feedback in the audio tab as well as the queue for the most part */ - if ([[mixdownPopUp selectedItem] tag] == HB_ACODEC_AC3) + if ([[mixdownPopUp selectedItem] tag] == HB_ACODEC_AC3 || [[mixdownPopUp selectedItem] tag] == HB_ACODEC_DCA) { /* lets also set the bitrate popup to the input bitrate as thats what passthru will use */ @@ -5001,6 +5630,14 @@ hb_list_t * list = hb_get_titles( fHandle ); drcSlider = fAudTrack4DrcSlider; drcField = fAudTrack4DrcField; } + + /* If we are between 0.0 and 1.0 on the slider, snap it to 1.0 */ + if ([drcSlider floatValue] > 0.0 && [drcSlider floatValue] < 1.0) + { + [drcSlider setFloatValue:1.0]; + } + + [drcField setStringValue: [NSString stringWithFormat: @"%.2f", [drcSlider floatValue]]]; /* For now, do not call this until we have an intelligent way to determine audio track selections * compared to presets @@ -5008,22 +5645,6 @@ hb_list_t * list = hb_get_titles( fHandle ); //[self customSettingUsed: sender]; } -- (IBAction) subtitleSelectionChanged: (id) sender -{ - if ([fSubPopUp indexOfSelectedItem] == 0) - { - [fSubForcedCheck setState: NSOffState]; - [fSubForcedCheck setEnabled: NO]; - } - else - { - [fSubForcedCheck setEnabled: YES]; - } - -} - - - #pragma mark - #pragma mark Open New Windows @@ -5084,11 +5705,22 @@ hb_list_t * list = hb_get_titles( fHandle ); - (IBAction) showPicturePanel: (id) sender { - hb_list_t * list = hb_get_titles( fHandle ); - hb_title_t * title = (hb_title_t *) hb_list_item( list, - [fSrcTitlePopUp indexOfSelectedItem] ); - //[fPictureController SetTitle:title]; - [fPictureController showPreviewPanel:sender forTitle:title]; + [fPictureController showPictureWindow:sender]; +} + +- (void) picturePanelFullScreen +{ + [fPictureController setToFullScreenMode]; +} + +- (void) picturePanelWindowed +{ + [fPictureController setToWindowedMode]; +} + +- (IBAction) showPreviewWindow: (id) sender +{ + [fPictureController showPreviewWindow:sender]; } #pragma mark - @@ -5122,7 +5754,7 @@ hb_list_t * list = hb_get_titles( fHandle ); } /* We use this to deterimine children of an item */ -- (id)outlineView:(NSOutlineView *)fPresetsOutlineView child:(int)index ofItem:(id)item +- (id)outlineView:(NSOutlineView *)fPresetsOutlineView child:(NSInteger)index ofItem:(id)item { /* we need to return the count of the array in ChildrenArray for this folder */ @@ -5138,7 +5770,7 @@ hb_list_t * list = hb_get_titles( fHandle ); children = [item objectForKey:@"ChildrenArray"]; } } - if ((children == nil) || ([children count] <= index)) + if ((children == nil) || ( [children count] <= (NSUInteger) index)) { return nil; } @@ -5217,6 +5849,15 @@ return YES; } } +- (id)outlineView:(NSOutlineView *)outlineView itemForPersistentObject:(id)object +{ + return [NSKeyedUnarchiver unarchiveObjectWithData:object]; +} +- (id)outlineView:(NSOutlineView *)outlineView persistentObjectForItem:(id)item +{ + return [NSKeyedArchiver archivedDataWithRootObject:item]; +} + #pragma mark - Added Functionality (optional) /* Use to customize the font and display characteristics of the title cell */ - (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item @@ -5332,7 +5973,7 @@ return YES; return YES; } -- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id )info proposedItem:(id)item proposedChildIndex:(int)index +- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id )info proposedItem:(id)item proposedChildIndex:(NSInteger)index { // Don't allow dropping ONTO an item since they can't really contain any children. @@ -5361,7 +6002,7 @@ return YES; -- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id )info item:(id)item childIndex:(int)index +- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id )info item:(id)item childIndex:(NSInteger)index { /* first, lets see if we are dropping into a folder */ if ([[fPresetsOutlineView itemAtRow:index] objectForKey:@"Folder"] && [[[fPresetsOutlineView itemAtRow:index] objectForKey:@"Folder"] intValue] == 1) // if its a folder @@ -5389,33 +6030,30 @@ return YES; return YES; } -- (void)moveObjectsInPresetsArray:(NSMutableArray *)array fromIndexes:(NSIndexSet *)indexSet toIndex:(unsigned)insertIndex +- (void)moveObjectsInPresetsArray:(NSMutableArray *)array fromIndexes:(NSIndexSet *)indexSet toIndex:(NSUInteger)insertIndex { - unsigned index = [indexSet lastIndex]; - unsigned aboveInsertIndexCount = 0; + NSUInteger index = [indexSet lastIndex]; + NSUInteger aboveInsertIndexCount = 0; - while (index != NSNotFound) + NSUInteger removeIndex; + + if (index >= insertIndex) { - unsigned removeIndex; - - if (index >= insertIndex) - { - removeIndex = index + aboveInsertIndexCount; - aboveInsertIndexCount++; - } - else - { - removeIndex = index; - insertIndex--; - } - - id object = [[array objectAtIndex:removeIndex] retain]; - [array removeObjectAtIndex:removeIndex]; - [array insertObject:object atIndex:insertIndex]; - [object release]; - - index = [indexSet indexLessThanIndex:index]; + removeIndex = index + aboveInsertIndexCount; + aboveInsertIndexCount++; + } + else + { + removeIndex = index; + insertIndex--; } + + id object = [[array objectAtIndex:removeIndex] retain]; + [array removeObjectAtIndex:removeIndex]; + [array insertObject:object atIndex:insertIndex]; + [object release]; + + index = [indexSet indexLessThanIndex:index]; } @@ -5445,45 +6083,18 @@ return YES; /* Chapter Markers*/ [fCreateChapterMarkers setState:[[chosenPreset objectForKey:@"ChapterMarkers"] intValue]]; + /* check to see if we have only one chapter */ + [self chapterPopUpChanged:nil]; + /* Allow Mpeg4 64 bit formatting +4GB file sizes */ [fDstMp4LargeFileCheck setState:[[chosenPreset objectForKey:@"Mp4LargeFile"] intValue]]; /* Mux mp4 with http optimization */ [fDstMp4HttpOptFileCheck setState:[[chosenPreset objectForKey:@"Mp4HttpOptimize"] intValue]]; /* Video encoder */ + [fVidEncoderPopUp selectItemWithTitle:[chosenPreset objectForKey:@"VideoEncoder"]]; /* We set the advanced opt string here if applicable*/ [fAdvancedOptions setOptions:[chosenPreset objectForKey:@"x264Option"]]; - /* We use a conditional to account for the new x264 encoder dropdown as well as presets made using legacy x264 settings*/ - if ([[chosenPreset objectForKey:@"VideoEncoder"] isEqualToString:@"x264 (h.264 Main)"] || - [[chosenPreset objectForKey:@"VideoEncoder"] isEqualToString:@"x264 (h.264 iPod)"] || - [[chosenPreset objectForKey:@"VideoEncoder"] isEqualToString:@"x264"]) - { - [fVidEncoderPopUp selectItemWithTitle:@"H.264 (x264)"]; - /* special case for legacy preset to check the new fDstMp4HttpOptFileCheck checkbox to set the ipod atom */ - if ([[chosenPreset objectForKey:@"VideoEncoder"] isEqualToString:@"x264 (h.264 iPod)"]) - { - [fDstMp4iPodFileCheck setState:NSOnState]; - /* We also need to add "level=30:" to the advanced opts string to set the correct level for the iPod when - encountering a legacy preset as it used to be handled separately from the opt string*/ - [fAdvancedOptions setOptions:[@"level=30:" stringByAppendingString:[fAdvancedOptions optionsString]]]; - } - else - { - [fDstMp4iPodFileCheck setState:NSOffState]; - } - } - else if ([[chosenPreset objectForKey:@"VideoEncoder"] isEqualToString:@"FFmpeg"]) - { - [fVidEncoderPopUp selectItemWithTitle:@"MPEG-4 (FFmpeg)"]; - } - else if ([[chosenPreset objectForKey:@"VideoEncoder"] isEqualToString:@"XviD"]) - { - [fVidEncoderPopUp selectItemWithTitle:@"MPEG-4 (XviD)"]; - } - else - { - [fVidEncoderPopUp selectItemWithTitle:[chosenPreset objectForKey:@"VideoEncoder"]]; - } /* Lets run through the following functions to get variables set there */ [self videoEncoderPopUpChanged:nil]; @@ -5496,7 +6107,23 @@ return YES; [fVidTargetSizeField setStringValue:[chosenPreset objectForKey:@"VideoTargetSize"]]; [fVidBitrateField setStringValue:[chosenPreset objectForKey:@"VideoAvgBitrate"]]; - [fVidQualitySlider setFloatValue:[[chosenPreset objectForKey:@"VideoQualitySlider"] floatValue]]; + + /* Since we are now using RF Values for the slider, we detect if the preset uses an old quality float. + * So, check to see if the quality value is less than 1.0 which should indicate the old ".062" type + * quality preset. Caveat: in the case of x264, where the RF scale starts at 0, it would misinterpret + * a preset that uses 0.0 - 0.99 for RF as an old style preset. Not sure how to get around that one yet, + * though it should be a corner case since it would pretty much be a preset for lossless encoding. */ + if ([[chosenPreset objectForKey:@"VideoQualitySlider"] floatValue] < 1.0) + { + /* For the quality slider we need to convert the old percent's to the new rf scales */ + float rf = (([fVidQualitySlider maxValue] - [fVidQualitySlider minValue]) * [[chosenPreset objectForKey:@"VideoQualitySlider"] floatValue]); + [fVidQualitySlider setFloatValue:rf]; + + } + else + { + [fVidQualitySlider setFloatValue:([fVidQualitySlider maxValue] - [fVidQualitySlider minValue]) - [[chosenPreset objectForKey:@"VideoQualitySlider"] floatValue]]; + } [self videoMatrixChanged:nil]; @@ -5512,183 +6139,116 @@ return YES; [fVidRatePopUp selectItemWithTitle:[chosenPreset objectForKey:@"VideoFramerate"]]; } - /* GrayScale */ - [fVidGrayscaleCheck setState:[[chosenPreset objectForKey:@"VideoGrayScale"] intValue]]; /* 2 Pass Encoding */ [fVidTwoPassCheck setState:[[chosenPreset objectForKey:@"VideoTwoPass"] intValue]]; [self twoPassCheckboxChanged:nil]; + /* Turbo 1st pass for 2 Pass Encoding */ [fVidTurboPassCheck setState:[[chosenPreset objectForKey:@"VideoTurboTwoPass"] intValue]]; /*Audio*/ - if ([chosenPreset objectForKey:@"FileCodecs"]) + /* First we check to see if we are using the current audio track layout based on AudioList array */ + if ([chosenPreset objectForKey:@"AudioList"]) { - /* We need to handle the audio codec popup by determining what was chosen from the deprecated Codecs PopUp for past presets*/ - if ([[chosenPreset objectForKey:@"FileCodecs"] isEqualToString: @"AVC/H.264 Video / AAC + AC3 Audio"]) + /* Populate the audio widgets based on the contents of the AudioList array */ + int i = 0; + NSEnumerator *enumerator = [[chosenPreset objectForKey:@"AudioList"] objectEnumerator]; + id tempObject; + while (tempObject = [enumerator nextObject]) { - /* We need to address setting languages etc. here in the new multi track audio panel */ - /* Track One set here */ - /*for track one though a track should be selected but lets check here anyway and use track one if its not.*/ - if ([fAudLang1PopUp indexOfSelectedItem] == 0) + i++; + if( i == 1 ) { - [fAudLang1PopUp selectItemAtIndex: 1]; + if ([fAudLang1PopUp indexOfSelectedItem] == 0) + { + [fAudLang1PopUp selectItemAtIndex: 1]; + } [self audioTrackPopUpChanged: fAudLang1PopUp]; - } - [fAudTrack1CodecPopUp selectItemWithTitle: @"AAC (faac)"]; - [self audioTrackPopUpChanged: fAudTrack1CodecPopUp]; - /* Track Two, set source same as track one */ - [fAudLang2PopUp selectItemAtIndex: [fAudLang1PopUp indexOfSelectedItem]]; - [self audioTrackPopUpChanged: fAudLang2PopUp]; - [fAudTrack2CodecPopUp selectItemWithTitle: @"AC3 Passthru"]; - [self audioTrackPopUpChanged: fAudTrack2CodecPopUp]; - } - else if ([[chosenPreset objectForKey:@"FileCodecs"] isEqualToString:@"MPEG-4 Video / AAC Audio"] || - [[chosenPreset objectForKey:@"FileCodecs"] isEqualToString:@"AVC/H.264 Video / AAC Audio"]) - { - if ([fAudLang1PopUp indexOfSelectedItem] > 0) - { - [fAudTrack1CodecPopUp selectItemWithTitle: @"AAC (faac)"]; - [self audioTrackPopUpChanged: fAudTrack1CodecPopUp]; - } - if ([fAudLang2PopUp indexOfSelectedItem] > 0) - { - [fAudTrack2CodecPopUp selectItemWithTitle: @"AAC (faac)"]; - [self audioTrackPopUpChanged: fAudTrack2CodecPopUp]; - } - if ([fAudLang3PopUp indexOfSelectedItem] > 0) - { - [fAudTrack3CodecPopUp selectItemWithTitle: @"AAC (faac)"]; - [self audioTrackPopUpChanged: fAudTrack3CodecPopUp]; - } - if ([fAudLang4PopUp indexOfSelectedItem] > 0) - { - [fAudTrack4CodecPopUp selectItemWithTitle: @"AAC (faac)"]; - [self audioTrackPopUpChanged: fAudTrack4CodecPopUp]; - } - } - else if ([[chosenPreset objectForKey:@"FileCodecs"] isEqualToString:@"MPEG-4 Video / AC-3 Audio"] || - [[chosenPreset objectForKey:@"FileCodecs"] isEqualToString:@"AVC/H.264 Video / AC-3 Audio"]) - { - if ([fAudLang1PopUp indexOfSelectedItem] > 0) - { - [fAudTrack1CodecPopUp selectItemWithTitle: @"AC3 Passthru"]; - [self audioTrackPopUpChanged: fAudTrack1CodecPopUp]; - } - if ([fAudLang2PopUp indexOfSelectedItem] > 0) - { - [fAudTrack2CodecPopUp selectItemWithTitle: @"AC3 Passthru"]; - [self audioTrackPopUpChanged: fAudTrack2CodecPopUp]; - } - if ([fAudLang3PopUp indexOfSelectedItem] > 0) - { - [fAudTrack3CodecPopUp selectItemWithTitle: @"AC3 Passthru"]; - [self audioTrackPopUpChanged: fAudTrack3CodecPopUp]; - } - if ([fAudLang4PopUp indexOfSelectedItem] > 0) - { - [fAudTrack4CodecPopUp selectItemWithTitle: @"AC3 Passthru"]; - [self audioTrackPopUpChanged: fAudTrack4CodecPopUp]; - } - } - else if ([[chosenPreset objectForKey:@"FileCodecs"] isEqualToString:@"MPEG-4 Video / MP3 Audio"] || - [[chosenPreset objectForKey:@"FileCodecs"] isEqualToString:@"AVC/H.264 Video / MP3 Audio"]) - { - if ([fAudLang1PopUp indexOfSelectedItem] > 0) - { - [fAudTrack1CodecPopUp selectItemWithTitle: @"MP3 (lame)"]; - [self audioTrackPopUpChanged: fAudTrack1CodecPopUp]; - } - if ([fAudLang2PopUp indexOfSelectedItem] > 0) - { - [fAudTrack2CodecPopUp selectItemWithTitle: @"MP3 (lame)"]; - [self audioTrackPopUpChanged: fAudTrack2CodecPopUp]; - } - if ([fAudLang3PopUp indexOfSelectedItem] > 0) - { - [fAudTrack3CodecPopUp selectItemWithTitle: @"MP3 (lame)"]; - [self audioTrackPopUpChanged: fAudTrack3CodecPopUp]; - } - if ([fAudLang4PopUp indexOfSelectedItem] > 0) - { - [fAudTrack4CodecPopUp selectItemWithTitle: @"MP3 (lame)"]; - [self audioTrackPopUpChanged: fAudTrack4CodecPopUp]; - } - } - else if ([[chosenPreset objectForKey:@"FileCodecs"] isEqualToString:@"MPEG-4 Video / Vorbis Audio"]) - { - if ([fAudLang1PopUp indexOfSelectedItem] > 0) - { - [fAudTrack1CodecPopUp selectItemWithTitle: @"Vorbis (vorbis)"]; + [fAudTrack1CodecPopUp selectItemWithTitle:[tempObject objectForKey:@"AudioEncoder"]]; + /* check our pref for core audio and use it in place of faac if applicable */ + if ([[NSUserDefaults standardUserDefaults] boolForKey: @"UseCoreAudio"] == YES && + [[tempObject objectForKey:@"AudioEncoder"] isEqualToString: @"AAC (faac)"]) + { + [fAudTrack1CodecPopUp selectItemWithTitle:@"AAC (CoreAudio)"]; + } + [self audioTrackPopUpChanged: fAudTrack1CodecPopUp]; + [fAudTrack1MixPopUp selectItemWithTitle:[tempObject objectForKey:@"AudioMixdown"]]; + /* check to see if the selections was available, if not, rerun audioTrackPopUpChanged using the codec to just set the default + * mixdown*/ + if ([fAudTrack1MixPopUp selectedItem] == nil) + { + [self audioTrackPopUpChanged: fAudTrack1CodecPopUp]; + } + [fAudTrack1RatePopUp selectItemWithTitle:[tempObject objectForKey:@"AudioSamplerate"]]; + /* We set the presets bitrate if it is *not* an AC3 track since that uses the input bitrate */ + if (![[tempObject objectForKey:@"AudioEncoder"] isEqualToString:@"AC3 Passthru"]) + { + [fAudTrack1BitratePopUp selectItemWithTitle:[tempObject objectForKey:@"AudioBitrate"]]; + } + [fAudTrack1DrcSlider setFloatValue:[[tempObject objectForKey:@"AudioTrackDRCSlider"] floatValue]]; + [self audioDRCSliderChanged: fAudTrack1DrcSlider]; } - if ([fAudLang2PopUp indexOfSelectedItem] > 0) + + if( i == 2 ) { - [fAudTrack2CodecPopUp selectItemWithTitle: @"Vorbis (vorbis)"]; + + if ([fAudLang2PopUp indexOfSelectedItem] == 0) + { + [fAudLang2PopUp selectItemAtIndex: 1]; + } + [self audioTrackPopUpChanged: fAudLang2PopUp]; + [fAudTrack2CodecPopUp selectItemWithTitle:[tempObject objectForKey:@"AudioEncoder"]]; + /* check our pref for core audio and use it in place of faac if applicable */ + if ([[NSUserDefaults standardUserDefaults] boolForKey: @"UseCoreAudio"] == YES && + [[tempObject objectForKey:@"AudioEncoder"] isEqualToString: @"AAC (faac)"]) + { + [fAudTrack2CodecPopUp selectItemWithTitle:@"AAC (CoreAudio)"]; + } [self audioTrackPopUpChanged: fAudTrack2CodecPopUp]; + [fAudTrack2MixPopUp selectItemWithTitle:[tempObject objectForKey:@"AudioMixdown"]]; + /* check to see if the selections was available, if not, rerun audioTrackPopUpChanged using the codec to just set the default + * mixdown*/ + if ([fAudTrack2MixPopUp selectedItem] == nil) + { + [self audioTrackPopUpChanged: fAudTrack2CodecPopUp]; + } + [fAudTrack2RatePopUp selectItemWithTitle:[tempObject objectForKey:@"AudioSamplerate"]]; + /* We set the presets bitrate if it is *not* an AC3 track since that uses the input bitrate */ + if (![[tempObject objectForKey:@"AudioEncoder"] isEqualToString:@"AC3 Passthru"]) + { + [fAudTrack2BitratePopUp selectItemWithTitle:[tempObject objectForKey:@"AudioBitrate"]]; + } + [fAudTrack2DrcSlider setFloatValue:[[tempObject objectForKey:@"AudioTrackDRCSlider"] floatValue]]; + [self audioDRCSliderChanged: fAudTrack2DrcSlider]; + } - if ([fAudLang3PopUp indexOfSelectedItem] > 0) - { - [fAudTrack3CodecPopUp selectItemWithTitle: @"Vorbis (vorbis)"]; - [self audioTrackPopUpChanged: fAudTrack3CodecPopUp]; - } - if ([fAudLang4PopUp indexOfSelectedItem] > 0) - { - [fAudTrack4CodecPopUp selectItemWithTitle: @"Vorbis (vorbis)"]; - [self audioTrackPopUpChanged: fAudTrack4CodecPopUp]; - } - } - /* We detect here if we have the old audio sample rate and if so we apply samplerate and bitrate to the existing four tracks if chosen - * UNLESS the CodecPopUp is AC3 in which case the preset values are ignored in favor of rates set in audioTrackMixdownChanged*/ - if ([chosenPreset objectForKey:@"AudioSampleRate"]) - { - if ([fAudLang1PopUp indexOfSelectedItem] > 0 && [fAudTrack1CodecPopUp titleOfSelectedItem] != @"AC3 Passthru") - { - [fAudTrack1RatePopUp selectItemWithTitle:[chosenPreset objectForKey:@"AudioSampleRate"]]; - [fAudTrack1BitratePopUp selectItemWithTitle:[chosenPreset objectForKey:@"AudioBitRate"]]; - } - if ([fAudLang2PopUp indexOfSelectedItem] > 0 && [fAudTrack2CodecPopUp titleOfSelectedItem] != @"AC3 Passthru") - { - [fAudTrack2RatePopUp selectItemWithTitle:[chosenPreset objectForKey:@"AudioSampleRate"]]; - [fAudTrack2BitratePopUp selectItemWithTitle:[chosenPreset objectForKey:@"AudioBitRate"]]; - } - if ([fAudLang3PopUp indexOfSelectedItem] > 0 && [fAudTrack3CodecPopUp titleOfSelectedItem] != @"AC3 Passthru") - { - [fAudTrack3RatePopUp selectItemWithTitle:[chosenPreset objectForKey:@"AudioSampleRate"]]; - [fAudTrack3BitratePopUp selectItemWithTitle:[chosenPreset objectForKey:@"AudioBitRate"]]; - } - if ([fAudLang4PopUp indexOfSelectedItem] > 0 && [fAudTrack4CodecPopUp titleOfSelectedItem] != @"AC3 Passthru") - { - [fAudTrack4RatePopUp selectItemWithTitle:[chosenPreset objectForKey:@"AudioSampleRate"]]; - [fAudTrack4BitratePopUp selectItemWithTitle:[chosenPreset objectForKey:@"AudioBitRate"]]; - } + } - /* We detect here if we have the old DRC Slider and if so we apply it to the existing four tracks if chosen */ - if ([chosenPreset objectForKey:@"AudioDRCSlider"]) + + /* We now cleanup any extra audio tracks that may have been previously set if we need to */ + + if (i < 4) { - if ([fAudLang1PopUp indexOfSelectedItem] > 0) - { - [fAudTrack1DrcSlider setFloatValue:[[chosenPreset objectForKey:@"AudioDRCSlider"] floatValue]]; - [self audioDRCSliderChanged: fAudTrack1DrcSlider]; - } - if ([fAudLang2PopUp indexOfSelectedItem] > 0) - { - [fAudTrack2DrcSlider setFloatValue:[[chosenPreset objectForKey:@"AudioDRCSlider"] floatValue]]; - [self audioDRCSliderChanged: fAudTrack2DrcSlider]; - } - if ([fAudLang3PopUp indexOfSelectedItem] > 0) - { - [fAudTrack3DrcSlider setFloatValue:[[chosenPreset objectForKey:@"AudioDRCSlider"] floatValue]]; - [self audioDRCSliderChanged: fAudTrack3DrcSlider]; - } - if ([fAudLang4PopUp indexOfSelectedItem] > 0) + [fAudLang4PopUp selectItemAtIndex: 0]; + [self audioTrackPopUpChanged: fAudLang4PopUp]; + + if (i < 3) { - [fAudTrack4DrcSlider setFloatValue:[[chosenPreset objectForKey:@"AudioDRCSlider"] floatValue]]; - [self audioDRCSliderChanged: fAudTrack4DrcSlider]; + [fAudLang3PopUp selectItemAtIndex: 0]; + [self audioTrackPopUpChanged: fAudLang3PopUp]; + + if (i < 2) + { + [fAudLang2PopUp selectItemAtIndex: 0]; + [self audioTrackPopUpChanged: fAudLang2PopUp]; + } } } + } - else // since there was no codecs key in the preset we know we can use new multi-audio track presets + else { if ([chosenPreset objectForKey:@"Audio1Track"] > 0) { @@ -5698,6 +6258,12 @@ return YES; } [self audioTrackPopUpChanged: fAudLang1PopUp]; [fAudTrack1CodecPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio1Encoder"]]; + /* check our pref for core audio and use it in place of faac if applicable */ + if ([[NSUserDefaults standardUserDefaults] boolForKey: @"UseCoreAudio"] == YES && + [[chosenPreset objectForKey:@"Audio1Encoder"] isEqualToString: @"AAC (faac)"]) + { + [fAudTrack1CodecPopUp selectItemWithTitle:@"AAC (CoreAudio)"]; + } [self audioTrackPopUpChanged: fAudTrack1CodecPopUp]; [fAudTrack1MixPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio1Mixdown"]]; /* check to see if the selections was available, if not, rerun audioTrackPopUpChanged using the codec to just set the default @@ -5723,6 +6289,12 @@ return YES; } [self audioTrackPopUpChanged: fAudLang2PopUp]; [fAudTrack2CodecPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio2Encoder"]]; + /* check our pref for core audio and use it in place of faac if applicable */ + if ([[NSUserDefaults standardUserDefaults] boolForKey: @"UseCoreAudio"] == YES && + [[chosenPreset objectForKey:@"Audio2Encoder"] isEqualToString: @"AAC (faac)"]) + { + [fAudTrack2CodecPopUp selectItemWithTitle:@"AAC (CoreAudio)"]; + } [self audioTrackPopUpChanged: fAudTrack2CodecPopUp]; [fAudTrack2MixPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio2Mixdown"]]; /* check to see if the selections was available, if not, rerun audioTrackPopUpChanged using the codec to just set the default @@ -5748,6 +6320,12 @@ return YES; } [self audioTrackPopUpChanged: fAudLang3PopUp]; [fAudTrack3CodecPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio3Encoder"]]; + /* check our pref for core audio and use it in place of faac if applicable */ + if ([[NSUserDefaults standardUserDefaults] boolForKey: @"UseCoreAudio"] == YES && + [[chosenPreset objectForKey:@"Audio3Encoder"] isEqualToString: @"AAC (faac)"]) + { + [fAudTrack3CodecPopUp selectItemWithTitle:@"AAC (CoreAudio)"]; + } [self audioTrackPopUpChanged: fAudTrack3CodecPopUp]; [fAudTrack3MixPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio3Mixdown"]]; /* check to see if the selections was available, if not, rerun audioTrackPopUpChanged using the codec to just set the default @@ -5773,6 +6351,12 @@ return YES; } [self audioTrackPopUpChanged: fAudLang4PopUp]; [fAudTrack4CodecPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio4Encoder"]]; + /* check our pref for core audio and use it in place of faac if applicable */ + if ([[NSUserDefaults standardUserDefaults] boolForKey: @"UseCoreAudio"] == YES && + [[chosenPreset objectForKey:@"Audio4Encoder"] isEqualToString: @"AAC (faac)"]) + { + [fAudTrack4CodecPopUp selectItemWithTitle:@"AAC (CoreAudio)"]; + } [self audioTrackPopUpChanged: fAudTrack4CodecPopUp]; [fAudTrack4MixPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio4Mixdown"]]; /* check to see if the selections was available, if not, rerun audioTrackPopUpChanged using the codec to just set the default @@ -5791,21 +6375,8 @@ return YES; [self audioDRCSliderChanged: fAudTrack4DrcSlider]; } + /* We now cleanup any extra audio tracks that may have been previously set if we need to */ - } - - /* We now cleanup any extra audio tracks that may be previously set if we need to, we do it here so we don't have to - * duplicate any code for legacy presets.*/ - /* First we handle the legacy Codecs crazy AVC/H.264 Video / AAC + AC3 Audio atv hybrid */ - if ([chosenPreset objectForKey:@"FileCodecs"] && [[chosenPreset objectForKey:@"FileCodecs"] isEqualToString:@"AVC/H.264 Video / AAC + AC3 Audio"]) - { - [fAudLang3PopUp selectItemAtIndex: 0]; - [self audioTrackPopUpChanged: fAudLang3PopUp]; - [fAudLang4PopUp selectItemAtIndex: 0]; - [self audioTrackPopUpChanged: fAudLang4PopUp]; - } - else - { if (![chosenPreset objectForKey:@"Audio2Track"] || [chosenPreset objectForKey:@"Audio2Track"] == 0) { [fAudLang2PopUp selectItemAtIndex: 0]; @@ -5829,43 +6400,42 @@ return YES; [fSubForcedCheck setState:[[chosenPreset objectForKey:@"SubtitlesForced"] intValue]]; /* Picture Settings */ - /* Note: objectForKey:@"UsesPictureSettings" now refers to picture size, this encompasses: + /* Note: objectForKey:@"UsesPictureSettings" refers to picture size, which encompasses: * height, width, keep ar, anamorphic and crop settings. - * picture filters are now handled separately. - * We will be able to actually change the key names for legacy preset keys when preset file - * update code is done. But for now, lets hang onto the old legacy key name for backwards compatibility. + * picture filters are handled separately below. */ /* Check to see if the objectForKey:@"UsesPictureSettings is greater than 0, as 0 means use picture sizing "None" - * and the preset completely ignores any picture sizing values in the preset. + * ( 2 is use max for source and 1 is use exact size when the preset was created ) and the + * preset completely ignores any picture sizing values in the preset. */ if ([[chosenPreset objectForKey:@"UsesPictureSettings"] intValue] > 0) { hb_job_t * job = fTitle->job; /* If Cropping is set to custom, then recall all four crop values from - when the preset was created and apply them */ - if ([[chosenPreset objectForKey:@"PictureAutoCrop"] intValue] == 0) - { - [fPictureController setAutoCrop:NO]; - - /* Here we use the custom crop values saved at the time the preset was saved */ - job->crop[0] = [[chosenPreset objectForKey:@"PictureTopCrop"] intValue]; - job->crop[1] = [[chosenPreset objectForKey:@"PictureBottomCrop"] intValue]; - job->crop[2] = [[chosenPreset objectForKey:@"PictureLeftCrop"] intValue]; - job->crop[3] = [[chosenPreset objectForKey:@"PictureRightCrop"] intValue]; - - } - else /* if auto crop has been saved in preset, set to auto and use post scan auto crop */ - { - [fPictureController setAutoCrop:YES]; - /* Here we use the auto crop values determined right after scan */ - job->crop[0] = AutoCropTop; - job->crop[1] = AutoCropBottom; - job->crop[2] = AutoCropLeft; - job->crop[3] = AutoCropRight; - - } - + when the preset was created and apply them */ + if ([[chosenPreset objectForKey:@"PictureAutoCrop"] intValue] == 0) + { + [fPictureController setAutoCrop:NO]; + + /* Here we use the custom crop values saved at the time the preset was saved */ + job->crop[0] = [[chosenPreset objectForKey:@"PictureTopCrop"] intValue]; + job->crop[1] = [[chosenPreset objectForKey:@"PictureBottomCrop"] intValue]; + job->crop[2] = [[chosenPreset objectForKey:@"PictureLeftCrop"] intValue]; + job->crop[3] = [[chosenPreset objectForKey:@"PictureRightCrop"] intValue]; + + } + else /* if auto crop has been saved in preset, set to auto and use post scan auto crop */ + { + [fPictureController setAutoCrop:YES]; + /* Here we use the auto crop values determined right after scan */ + job->crop[0] = AutoCropTop; + job->crop[1] = AutoCropBottom; + job->crop[2] = AutoCropLeft; + job->crop[3] = AutoCropRight; + + } + /* Check to see if the objectForKey:@"UsesPictureSettings is 2 which is "Use Max for the source */ if ([[chosenPreset objectForKey:@"UsesPictureSettings"] intValue] == 2 || [[chosenPreset objectForKey:@"UsesMaxPictureSettings"] intValue] == 1) @@ -5882,7 +6452,7 @@ return YES; hb_fix_aspect( job, HB_KEEP_HEIGHT ); } } - job->pixel_ratio = [[chosenPreset objectForKey:@"PicturePAR"] intValue]; + job->anamorphic.mode = [[chosenPreset objectForKey:@"PicturePAR"] intValue]; } else // /* If not 0 or 2 we assume objectForKey:@"UsesPictureSettings is 1 which is "Use picture sizing from when the preset was set" */ { @@ -5890,8 +6460,9 @@ return YES; if (fTitle->width < [[chosenPreset objectForKey:@"PictureWidth"] intValue] || fTitle->height < [[chosenPreset objectForKey:@"PictureHeight"] intValue]) { /* if so, then we use the sources height and width to avoid scaling up */ - job->width = fTitle->width; - job->height = fTitle->height; + //job->width = fTitle->width; + //job->height = fTitle->height; + [self revertPictureSizeToMax:nil]; } else // source width/height is >= the preset height/width { @@ -5909,124 +6480,87 @@ return YES; hb_fix_aspect( job, HB_KEEP_HEIGHT ); } } - job->pixel_ratio = [[chosenPreset objectForKey:@"PicturePAR"] intValue]; - - - /* If the preset has no objectForKey:@"UsesPictureFilters", then we know it is a legacy preset - * and handle the filters here as before. - * NOTE: This should be removed when the update presets code is done as we can be assured that legacy - * presets are updated to work properly with new keys. - */ - if (![chosenPreset objectForKey:@"UsesPictureFilters"]) - { - /* Filters */ - /* Deinterlace */ - if ([chosenPreset objectForKey:@"PictureDeinterlace"]) - { - /* We check to see if the preset used the past fourth "Slowest" deinterlaceing and set that to "Slower - * since we no longer have a fourth "Slowest" deinterlacing due to the mcdeint bug */ - if ([[chosenPreset objectForKey:@"PictureDeinterlace"] intValue] == 4) - { - [fPictureController setDeinterlace:3]; - } - else - { - - [fPictureController setDeinterlace:[[chosenPreset objectForKey:@"PictureDeinterlace"] intValue]]; - } - } - else - { - [fPictureController setDeinterlace:0]; - } - /* VFR */ - if ([[chosenPreset objectForKey:@"VFR"] intValue] == 1) - { - // We make sure that framerate is set to Same as source variable - // detelecine will take care of itself right below - //[fPictureController setVFR:[[chosenPreset objectForKey:@"VFR"] intValue]]; - } - - /* Detelecine */ - if ([[chosenPreset objectForKey:@"PictureDetelecine"] intValue] == 1) - { - [fPictureController setDetelecine:[[chosenPreset objectForKey:@"PictureDetelecine"] intValue]]; - } - else - { - [fPictureController setDetelecine:0]; - } - /* Denoise */ - if ([chosenPreset objectForKey:@"PictureDenoise"]) - { - [fPictureController setDenoise:[[chosenPreset objectForKey:@"PictureDenoise"] intValue]]; - } - else - { - [fPictureController setDenoise:0]; - } - /* Deblock */ - if ([[chosenPreset objectForKey:@"PictureDeblock"] intValue] == 1) - { - /* since we used to use 1 to turn on deblock, we now use a 5 in our sliding scale */ - [fPictureController setDeblock:5]; - } - else - { - [fPictureController setDeblock:0]; - - } - - [self calculatePictureSizing:nil]; - } + job->anamorphic.mode = [[chosenPreset objectForKey:@"PicturePAR"] intValue]; } } - /* If the preset has an objectForKey:@"UsesPictureFilters", then we know it is a newer style filters preset - * and handle the filters here depending on whether or not the preset specifies applying the filter. - */ + /* If the preset has an objectForKey:@"UsesPictureFilters", and handle the filters here */ if ([chosenPreset objectForKey:@"UsesPictureFilters"] && [[chosenPreset objectForKey:@"UsesPictureFilters"] intValue] > 0) { /* Filters */ - /* Deinterlace */ - if ([chosenPreset objectForKey:@"PictureDeinterlace"]) + + /* We only allow *either* Decomb or Deinterlace. So check for the PictureDecombDeinterlace key. + * also, older presets may not have this key, in which case we also check to see if that preset had PictureDecomb + * specified, in which case we use decomb and ignore any possible Deinterlace settings as using both was less than + * sane. + */ + [fPictureController setUseDecomb:1]; + [fPictureController setDecomb:0]; + [fPictureController setDeinterlace:0]; + if ([[chosenPreset objectForKey:@"PictureDecombDeinterlace"] intValue] == 1 || [[chosenPreset objectForKey:@"PictureDecomb"] intValue] > 0) { - /* We check to see if the preset used the past fourth "Slowest" deinterlaceing and set that to "Slower - * since we no longer have a fourth "Slowest" deinterlacing due to the mcdeint bug */ - if ([[chosenPreset objectForKey:@"PictureDeinterlace"] intValue] == 4) + /* we are using decomb */ + /* Decomb */ + if ([[chosenPreset objectForKey:@"PictureDecomb"] intValue] > 0) { - [fPictureController setDeinterlace:3]; + [fPictureController setDecomb:[[chosenPreset objectForKey:@"PictureDecomb"] intValue]]; + + /* if we are using "Custom" in the decomb setting, also set the custom string*/ + if ([[chosenPreset objectForKey:@"PictureDecomb"] intValue] == 2) + { + [fPictureController setDecombCustomString:[chosenPreset objectForKey:@"PictureDecombCustom"]]; + } } - else + } + else + { + /* We are using Deinterlace */ + /* Deinterlace */ + if ([[chosenPreset objectForKey:@"PictureDeinterlace"] intValue] > 0) { + [fPictureController setUseDecomb:0]; [fPictureController setDeinterlace:[[chosenPreset objectForKey:@"PictureDeinterlace"] intValue]]; + /* if we are using "Custom" in the deinterlace setting, also set the custom string*/ + if ([[chosenPreset objectForKey:@"PictureDeinterlace"] intValue] == 4) + { + [fPictureController setDeinterlaceCustomString:[chosenPreset objectForKey:@"PictureDeinterlaceCustom"]]; + } } } - else - { - [fPictureController setDeinterlace:0]; - } + /* Detelecine */ - if ([[chosenPreset objectForKey:@"PictureDetelecine"] intValue] == 1) + if ([[chosenPreset objectForKey:@"PictureDetelecine"] intValue] > 0) { [fPictureController setDetelecine:[[chosenPreset objectForKey:@"PictureDetelecine"] intValue]]; + /* if we are using "Custom" in the detelecine setting, also set the custom string*/ + if ([[chosenPreset objectForKey:@"PictureDetelecine"] intValue] == 2) + { + [fPictureController setDetelecineCustomString:[chosenPreset objectForKey:@"PictureDetelecineCustom"]]; + } } else { [fPictureController setDetelecine:0]; } + /* Denoise */ - if ([chosenPreset objectForKey:@"PictureDenoise"]) + if ([[chosenPreset objectForKey:@"PictureDenoise"] intValue] > 0) { [fPictureController setDenoise:[[chosenPreset objectForKey:@"PictureDenoise"] intValue]]; + /* if we are using "Custom" in the denoise setting, also set the custom string*/ + if ([[chosenPreset objectForKey:@"PictureDenoise"] intValue] == 4) + { + [fPictureController setDenoiseCustomString:[chosenPreset objectForKey:@"PictureDenoiseCustom"]]; + } } else { [fPictureController setDenoise:0]; } + /* Deblock */ if ([[chosenPreset objectForKey:@"PictureDeblock"] intValue] == 1) { @@ -6038,18 +6572,19 @@ return YES; /* use the settings intValue */ [fPictureController setDeblock:[[chosenPreset objectForKey:@"PictureDeblock"] intValue]]; } - /* Decomb */ - /* Even though we currently allow for a custom setting for decomb, ultimately it will only have Off and - * Default so we just pay attention to anything greater than 0 as 1 (Default). 0 is Off. */ - if ([[chosenPreset objectForKey:@"PictureDecomb"] intValue] > 0) + + if ([[chosenPreset objectForKey:@"VideoGrayScale"] intValue] == 1) { - [fPictureController setDecomb:1]; + [fPictureController setGrayscale:1]; } else { - [fPictureController setDecomb:0]; + [fPictureController setGrayscale:0]; } } + /* we call SetTitle: in fPictureController so we get an instant update in the Picture Settings window */ + [fPictureController SetTitle:fTitle]; + [fPictureController SetTitle:fTitle]; [self calculatePictureSizing:nil]; } } @@ -6077,6 +6612,46 @@ return YES; [self addFactoryPresets:nil]; } [fPresetsOutlineView reloadData]; + + [self checkBuiltInsForUpdates]; +} + +- (void) checkBuiltInsForUpdates { + + BOOL updateBuiltInPresets = NO; + int i = 0; + NSEnumerator *enumerator = [UserPresets objectEnumerator]; + id tempObject; + while (tempObject = [enumerator nextObject]) + { + /* iterate through the built in presets to see if any have an old build number */ + NSMutableDictionary *thisPresetDict = tempObject; + /*Key Type == 0 is built in, and key PresetBuildNumber is the build number it was created with */ + if ([[thisPresetDict objectForKey:@"Type"] intValue] == 0) + { + if (![thisPresetDict objectForKey:@"PresetBuildNumber"] || [[thisPresetDict objectForKey:@"PresetBuildNumber"] intValue] < [[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"] intValue]) + { + updateBuiltInPresets = YES; + } + } + i++; + } + /* if we have built in presets to update, then do so AlertBuiltInPresetUpdate*/ + if ( updateBuiltInPresets == YES) + { + if( [[NSUserDefaults standardUserDefaults] boolForKey:@"AlertBuiltInPresetUpdate"] == YES) + { + /* Show an alert window that built in presets will be updated */ + /*On Screen Notification*/ + int status; + NSBeep(); + status = NSRunAlertPanel(@"HandBrake has determined your built in presets are out of date...",@"HandBrake will now update your built-in presets.", @"OK", nil, nil); + [NSApp requestUserAttention:NSCriticalRequest]; + } + /* when alert is dismissed, go ahead and update the built in presets */ + [self addFactoryPresets:nil]; + } + } @@ -6164,6 +6739,9 @@ return YES; - (NSDictionary *)createPreset { NSMutableDictionary *preset = [[NSMutableDictionary alloc] init]; + /* Preset build number */ + [preset setObject:[NSString stringWithFormat: @"%d", [[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"] intValue]] forKey:@"PresetBuildNumber"]; + [preset setObject:[fPresetNewName stringValue] forKey:@"PresetName"]; /* Get the New Preset Name from the field in the AddPresetPanel */ [preset setObject:[fPresetNewName stringValue] forKey:@"PresetName"]; /* Set whether or not this is to be a folder fPresetNewFolderCheck*/ @@ -6208,7 +6786,7 @@ return YES; [preset setObject:[NSNumber numberWithInt:[fVidQualityMatrix selectedRow]] forKey:@"VideoQualityType"]; [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"]; [preset setObject:[fVidBitrateField stringValue] forKey:@"VideoAvgBitrate"]; - [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"]; + [preset setObject:[NSNumber numberWithFloat:[fVidQualityRFField floatValue]] forKey:@"VideoQualitySlider"]; /* Video framerate */ if ([fVidRatePopUp indexOfSelectedItem] == 0) // Same as source is selected @@ -6219,8 +6797,7 @@ return YES; { [preset setObject:[fVidRatePopUp titleOfSelectedItem] forKey:@"VideoFramerate"]; } - /* GrayScale */ - [preset setObject:[NSNumber numberWithInt:[fVidGrayscaleCheck state]] forKey:@"VideoGrayScale"]; + /* 2 Pass Encoding */ [preset setObject:[NSNumber numberWithInt:[fVidTwoPassCheck state]] forKey:@"VideoTwoPass"]; /* Turbo 2 pass Encoding fVidTurboPassCheck*/ @@ -6233,7 +6810,7 @@ return YES; [preset setObject:[NSNumber numberWithInt:fTitle->job->width] forKey:@"PictureWidth"]; [preset setObject:[NSNumber numberWithInt:fTitle->job->height] forKey:@"PictureHeight"]; [preset setObject:[NSNumber numberWithInt:fTitle->job->keep_ratio] forKey:@"PictureKeepRatio"]; - [preset setObject:[NSNumber numberWithInt:fTitle->job->pixel_ratio] forKey:@"PicturePAR"]; + [preset setObject:[NSNumber numberWithInt:fTitle->job->anamorphic.mode] forKey:@"PicturePAR"]; /* Set crop settings here */ [preset setObject:[NSNumber numberWithInt:[fPictureController autoCrop]] forKey:@"PictureAutoCrop"]; @@ -6243,56 +6820,82 @@ return YES; [preset setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"]; /* Picture Filters */ + [preset setObject:[NSNumber numberWithInt:[fPictureController useDecomb]] forKey:@"PictureDecombDeinterlace"]; [preset setObject:[NSNumber numberWithInt:[fPictureController deinterlace]] forKey:@"PictureDeinterlace"]; + [preset setObject:[fPictureController deinterlaceCustomString] forKey:@"PictureDeinterlaceCustom"]; [preset setObject:[NSNumber numberWithInt:[fPictureController detelecine]] forKey:@"PictureDetelecine"]; - //[preset setObject:[NSNumber numberWithInt:[fPictureController vfr]] forKey:@"VFR"]; + [preset setObject:[fPictureController detelecineCustomString] forKey:@"PictureDetelecineCustom"]; [preset setObject:[NSNumber numberWithInt:[fPictureController denoise]] forKey:@"PictureDenoise"]; + [preset setObject:[fPictureController denoiseCustomString] forKey:@"PictureDenoiseCustom"]; [preset setObject:[NSNumber numberWithInt:[fPictureController deblock]] forKey:@"PictureDeblock"]; [preset setObject:[NSNumber numberWithInt:[fPictureController decomb]] forKey:@"PictureDecomb"]; - + [preset setObject:[fPictureController decombCustomString] forKey:@"PictureDecombCustom"]; + [preset setObject:[NSNumber numberWithInt:[fPictureController grayscale]] forKey:@"VideoGrayScale"]; /*Audio*/ + NSMutableArray *audioListArray = [[NSMutableArray alloc] init]; + /* we actually call the methods for the nests here */ if ([fAudLang1PopUp indexOfSelectedItem] > 0) { - [preset setObject:[NSNumber numberWithInt:[fAudLang1PopUp indexOfSelectedItem]] forKey:@"Audio1Track"]; - [preset setObject:[fAudLang1PopUp titleOfSelectedItem] forKey:@"Audio1TrackDescription"]; - [preset setObject:[fAudTrack1CodecPopUp titleOfSelectedItem] forKey:@"Audio1Encoder"]; - [preset setObject:[fAudTrack1MixPopUp titleOfSelectedItem] forKey:@"Audio1Mixdown"]; - [preset setObject:[fAudTrack1RatePopUp titleOfSelectedItem] forKey:@"Audio1Samplerate"]; - [preset setObject:[fAudTrack1BitratePopUp titleOfSelectedItem] forKey:@"Audio1Bitrate"]; - [preset setObject:[NSNumber numberWithFloat:[fAudTrack1DrcSlider floatValue]] forKey:@"Audio1TrackDRCSlider"]; + NSMutableDictionary *audioTrack1Array = [[NSMutableDictionary alloc] init]; + [audioTrack1Array setObject:[NSNumber numberWithInt:[fAudLang1PopUp indexOfSelectedItem]] forKey:@"AudioTrack"]; + [audioTrack1Array setObject:[fAudLang1PopUp titleOfSelectedItem] forKey:@"AudioTrackDescription"]; + [audioTrack1Array setObject:[fAudTrack1CodecPopUp titleOfSelectedItem] forKey:@"AudioEncoder"]; + [audioTrack1Array setObject:[fAudTrack1MixPopUp titleOfSelectedItem] forKey:@"AudioMixdown"]; + [audioTrack1Array setObject:[fAudTrack1RatePopUp titleOfSelectedItem] forKey:@"AudioSamplerate"]; + [audioTrack1Array setObject:[fAudTrack1BitratePopUp titleOfSelectedItem] forKey:@"AudioBitrate"]; + [audioTrack1Array setObject:[NSNumber numberWithFloat:[fAudTrack1DrcSlider floatValue]] forKey:@"AudioTrackDRCSlider"]; + [audioTrack1Array autorelease]; + [audioListArray addObject:audioTrack1Array]; } + if ([fAudLang2PopUp indexOfSelectedItem] > 0) { - [preset setObject:[NSNumber numberWithInt:[fAudLang2PopUp indexOfSelectedItem]] forKey:@"Audio2Track"]; - [preset setObject:[fAudLang2PopUp titleOfSelectedItem] forKey:@"Audio2TrackDescription"]; - [preset setObject:[fAudTrack2CodecPopUp titleOfSelectedItem] forKey:@"Audio2Encoder"]; - [preset setObject:[fAudTrack2MixPopUp titleOfSelectedItem] forKey:@"Audio2Mixdown"]; - [preset setObject:[fAudTrack2RatePopUp titleOfSelectedItem] forKey:@"Audio2Samplerate"]; - [preset setObject:[fAudTrack2BitratePopUp titleOfSelectedItem] forKey:@"Audio2Bitrate"]; - [preset setObject:[NSNumber numberWithFloat:[fAudTrack2DrcSlider floatValue]] forKey:@"Audio2TrackDRCSlider"]; + NSMutableDictionary *audioTrack2Array = [[NSMutableDictionary alloc] init]; + [audioTrack2Array setObject:[NSNumber numberWithInt:[fAudLang2PopUp indexOfSelectedItem]] forKey:@"AudioTrack"]; + [audioTrack2Array setObject:[fAudLang2PopUp titleOfSelectedItem] forKey:@"AudioTrackDescription"]; + [audioTrack2Array setObject:[fAudTrack2CodecPopUp titleOfSelectedItem] forKey:@"AudioEncoder"]; + [audioTrack2Array setObject:[fAudTrack2MixPopUp titleOfSelectedItem] forKey:@"AudioMixdown"]; + [audioTrack2Array setObject:[fAudTrack2RatePopUp titleOfSelectedItem] forKey:@"AudioSamplerate"]; + [audioTrack2Array setObject:[fAudTrack2BitratePopUp titleOfSelectedItem] forKey:@"AudioBitrate"]; + [audioTrack2Array setObject:[NSNumber numberWithFloat:[fAudTrack2DrcSlider floatValue]] forKey:@"AudioTrackDRCSlider"]; + [audioTrack2Array autorelease]; + [audioListArray addObject:audioTrack2Array]; } + if ([fAudLang3PopUp indexOfSelectedItem] > 0) { - [preset setObject:[NSNumber numberWithInt:[fAudLang3PopUp indexOfSelectedItem]] forKey:@"Audio3Track"]; - [preset setObject:[fAudLang3PopUp titleOfSelectedItem] forKey:@"Audio3TrackDescription"]; - [preset setObject:[fAudTrack3CodecPopUp titleOfSelectedItem] forKey:@"Audio3Encoder"]; - [preset setObject:[fAudTrack3MixPopUp titleOfSelectedItem] forKey:@"Audio3Mixdown"]; - [preset setObject:[fAudTrack3RatePopUp titleOfSelectedItem] forKey:@"Audio3Samplerate"]; - [preset setObject:[fAudTrack3BitratePopUp titleOfSelectedItem] forKey:@"Audio3Bitrate"]; - [preset setObject:[NSNumber numberWithFloat:[fAudTrack3DrcSlider floatValue]] forKey:@"Audio3TrackDRCSlider"]; + NSMutableDictionary *audioTrack3Array = [[NSMutableDictionary alloc] init]; + [audioTrack3Array setObject:[NSNumber numberWithInt:[fAudLang3PopUp indexOfSelectedItem]] forKey:@"AudioTrack"]; + [audioTrack3Array setObject:[fAudLang3PopUp titleOfSelectedItem] forKey:@"AudioTrackDescription"]; + [audioTrack3Array setObject:[fAudTrack3CodecPopUp titleOfSelectedItem] forKey:@"AudioEncoder"]; + [audioTrack3Array setObject:[fAudTrack3MixPopUp titleOfSelectedItem] forKey:@"AudioMixdown"]; + [audioTrack3Array setObject:[fAudTrack3RatePopUp titleOfSelectedItem] forKey:@"AudioSamplerate"]; + [audioTrack3Array setObject:[fAudTrack3BitratePopUp titleOfSelectedItem] forKey:@"AudioBitrate"]; + [audioTrack3Array setObject:[NSNumber numberWithFloat:[fAudTrack3DrcSlider floatValue]] forKey:@"AudioTrackDRCSlider"]; + [audioTrack3Array autorelease]; + [audioListArray addObject:audioTrack3Array]; } + if ([fAudLang4PopUp indexOfSelectedItem] > 0) { - [preset setObject:[NSNumber numberWithInt:[fAudLang4PopUp indexOfSelectedItem]] forKey:@"Audio4Track"]; - [preset setObject:[fAudLang4PopUp titleOfSelectedItem] forKey:@"Audio4TrackDescription"]; - [preset setObject:[fAudTrack4CodecPopUp titleOfSelectedItem] forKey:@"Audio4Encoder"]; - [preset setObject:[fAudTrack4MixPopUp titleOfSelectedItem] forKey:@"Audio4Mixdown"]; - [preset setObject:[fAudTrack4RatePopUp titleOfSelectedItem] forKey:@"Audio4Samplerate"]; - [preset setObject:[fAudTrack4BitratePopUp titleOfSelectedItem] forKey:@"Audio4Bitrate"]; - [preset setObject:[NSNumber numberWithFloat:[fAudTrack4DrcSlider floatValue]] forKey:@"Audio4TrackDRCSlider"]; + NSMutableDictionary *audioTrack4Array = [[NSMutableDictionary alloc] init]; + [audioTrack4Array setObject:[NSNumber numberWithInt:[fAudLang4PopUp indexOfSelectedItem]] forKey:@"AudioTrack"]; + [audioTrack4Array setObject:[fAudLang4PopUp titleOfSelectedItem] forKey:@"AudioTrackDescription"]; + [audioTrack4Array setObject:[fAudTrack4CodecPopUp titleOfSelectedItem] forKey:@"AudioEncoder"]; + [audioTrack4Array setObject:[fAudTrack4MixPopUp titleOfSelectedItem] forKey:@"AudioMixdown"]; + [audioTrack4Array setObject:[fAudTrack4RatePopUp titleOfSelectedItem] forKey:@"AudioSamplerate"]; + [audioTrack4Array setObject:[fAudTrack4BitratePopUp titleOfSelectedItem] forKey:@"AudioBitrate"]; + [audioTrack4Array setObject:[NSNumber numberWithFloat:[fAudTrack4DrcSlider floatValue]] forKey:@"AudioTrackDRCSlider"]; + [audioTrack4Array autorelease]; + [audioListArray addObject:audioTrack4Array]; } + + [preset setObject:[NSMutableArray arrayWithArray: audioListArray] forKey:@"AudioList"]; + + + /* Subtitles*/ [preset setObject:[fSubPopUp titleOfSelectedItem] forKey:@"Subtitles"]; /* Forced Subtitles */ @@ -6361,6 +6964,119 @@ return YES; } } + +#pragma mark - +#pragma mark Import Export Preset(s) + +- (IBAction) browseExportPresetFile: (id) sender +{ + /* 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 beginSheetForDirectory: defaultExportDirectory file: @"HB_Export.plist" + modalForWindow: fWindow modalDelegate: self + didEndSelector: @selector( browseExportPresetFileDone:returnCode:contextInfo: ) + contextInfo: NULL]; +} + +- (void) browseExportPresetFileDone: (NSSavePanel *) sheet + returnCode: (int) returnCode contextInfo: (void *) contextInfo +{ + if( returnCode == NSOKButton ) + { + NSString *presetExportDirectory = [[sheet filename] stringByDeletingLastPathComponent]; + NSString *exportPresetsFile = [sheet filename]; + [[NSUserDefaults standardUserDefaults] setObject:presetExportDirectory forKey:@"LastPresetExportDirectory"]; + /* We check for the presets.plist */ + if ([[NSFileManager defaultManager] fileExistsAtPath:exportPresetsFile] == 0) + { + [[NSFileManager defaultManager] createFileAtPath:exportPresetsFile contents:nil attributes:nil]; + } + NSMutableArray * presetsToExport = [[NSMutableArray alloc] initWithContentsOfFile:exportPresetsFile]; + if (nil == presetsToExport) + { + presetsToExport = [[NSMutableArray alloc] init]; + + /* now get and add selected presets to export */ + + } + if ([fPresetsOutlineView selectedRow] >= 0 && [[[fPresetsOutlineView itemAtRow:[fPresetsOutlineView selectedRow]] objectForKey:@"Folder"] intValue] != 1) + { + [presetsToExport addObject:[fPresetsOutlineView itemAtRow:[fPresetsOutlineView selectedRow]]]; + [presetsToExport writeToFile:exportPresetsFile atomically:YES]; + + } + + } +} + + +- (IBAction) browseImportPresetFile: (id) sender +{ + + NSOpenPanel * panel; + + panel = [NSOpenPanel openPanel]; + [panel setAllowsMultipleSelection: NO]; + [panel setCanChooseFiles: YES]; + [panel setCanChooseDirectories: NO ]; + NSString * sourceDirectory; + if ([[NSUserDefaults standardUserDefaults] stringForKey:@"LastPresetImportDirectory"]) + { + sourceDirectory = [[NSUserDefaults standardUserDefaults] stringForKey:@"LastPresetImportDirectory"]; + } + else + { + sourceDirectory = @"~/Desktop"; + sourceDirectory = [sourceDirectory stringByExpandingTildeInPath]; + } + /* 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 */ + NSArray *fileTypes = [NSArray arrayWithObjects:@"plist", @"xml", nil]; + [panel beginSheetForDirectory: sourceDirectory file: nil types: fileTypes + modalForWindow: fWindow modalDelegate: self + didEndSelector: @selector( browseImportPresetDone:returnCode:contextInfo: ) + contextInfo: sender]; +} + +- (void) browseImportPresetDone: (NSSavePanel *) sheet + returnCode: (int) returnCode contextInfo: (void *) contextInfo +{ + if( returnCode == NSOKButton ) + { + NSString *importPresetsDirectory = [[sheet filename] stringByDeletingLastPathComponent]; + NSString *importPresetsFile = [sheet filename]; + [[NSUserDefaults standardUserDefaults] setObject:importPresetsDirectory forKey:@"LastPresetImportDirectory"]; + /* NOTE: here we need to do some sanity checking to verify we do not hose up our presets file */ + NSMutableArray * presetsToImport = [[NSMutableArray alloc] initWithContentsOfFile:importPresetsFile]; + /* iterate though the new array of presets to import and add them to our presets array */ + int i = 0; + NSEnumerator *enumerator = [presetsToImport objectEnumerator]; + id tempObject; + while (tempObject = [enumerator nextObject]) + { + /* 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 */ + [UserPresets addObject:tempObject]; + i++; + } + [presetsToImport autorelease]; + [self sortPresets]; + [self addPreset]; + + } +} + #pragma mark - #pragma mark Manage Default Preset @@ -6619,25 +7335,39 @@ return YES; } - /* We use this method to recreate new, updated factory - presets */ + /* We use this method to recreate new, updated factory presets */ - (IBAction)addFactoryPresets:(id)sender { - - /* First, we delete any existing built in presets */ + + /* First, we delete any existing built in presets */ [self deleteFactoryPresets: sender]; /* Then we generate new built in presets programmatically with fPresetsBuiltin - * which is all setup in HBPresets.h and HBPresets.m*/ + * which is all setup in HBPresets.h and HBPresets.m*/ [fPresetsBuiltin generateBuiltinPresets:UserPresets]; + /* update build number for built in presets */ + /* iterate though the new array of presets to import and add them to our presets array */ + int i = 0; + NSEnumerator *enumerator = [UserPresets objectEnumerator]; + id tempObject; + while (tempObject = [enumerator nextObject]) + { + /* Record the apps current build number in the PresetBuildNumber key */ + if ([[tempObject objectForKey:@"Type"] intValue] == 0) // Type 0 is a built in preset + { + /* Preset build number */ + [[UserPresets objectAtIndex:i] setObject:[NSNumber numberWithInt:[[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"] intValue]] forKey:@"PresetBuildNumber"]; + } + i++; + } + /* report the built in preset updating to the activity log */ + [self writeToActivityLog: "built in presets updated to build number: %d", [[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"] intValue]]; + [self sortPresets]; [self addPreset]; } - - - @end /*******************************