X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=macosx%2FController.mm;h=f7e79c4844b3489dc014d297558b898b5d538754;hb=83588c143bb574905fc23be31d1ab3b99ba5e791;hp=13179e8d3fae4280ea5ec8f2fbadb60dcb37f3cc;hpb=852a264fa8159793e799e45525b485fff207e616;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/macosx/Controller.mm b/macosx/Controller.mm index 13179e8d..f7e79c48 100644 --- a/macosx/Controller.mm +++ b/macosx/Controller.mm @@ -13,13 +13,14 @@ #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"; @@ -36,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; @@ -83,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); @@ -98,7 +110,13 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It 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]; @@ -108,7 +126,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [[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"]) @@ -142,26 +160,48 @@ 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. } @@ -180,6 +220,24 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It } } +- (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) @@ -198,8 +256,11 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It } else { - [self setQueueEncodingItemsAsPending]; - [self showQueueWindow:NULL]; + if ([self hbInstances] == 1) + { + [self setQueueEncodingItemsAsPending]; + } + [self showQueueWindow:NULL]; } } @@ -258,7 +319,8 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [fQueueController release]; [fPreviewController release]; [fPictureController release]; - + [fApplicationIcon release]; + hb_close(&fHandle); hb_close(&fQueueEncodeLibhb); } @@ -269,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]; @@ -287,19 +349,39 @@ 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*/ + on user preference DefaultPresetsDrawerShow*/ if( [[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPresetsDrawerShow"] > 0 ) { [fPresetDrawer setDelegate:self]; NSSize drawerSize = NSSizeFromString( [[NSUserDefaults standardUserDefaults] - stringForKey:@"Drawer Size"] ); + 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; [fDstFormatPopUp removeAllItems]; @@ -309,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", @"" )]; @@ -354,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]; @@ -382,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]; @@ -392,27 +468,27 @@ 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 @@ -433,7 +509,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It fAudTrack1BitratePopUp, fAudTrack2BitratePopUp, fAudTrack3BitratePopUp, fAudTrack4BitratePopUp, fAudDrcLabel, fAudTrack1DrcSlider, fAudTrack1DrcField, fAudTrack2DrcSlider, fAudTrack2DrcField, fAudTrack3DrcSlider, fAudTrack3DrcField, fAudTrack4DrcSlider,fAudTrack4DrcField, - fQueueStatus,fPresetsAdd,fPresetsDelete, + fQueueStatus,fPresetsAdd,fPresetsDelete,fSrcAngleLabel,fSrcAnglePopUp, fCreateChapterMarkers,fVidTurboPassCheck,fDstMp4LargeFileCheck,fSubForcedCheck,fPresetsOutlineView, fAudDrcLabel,fDstMp4HttpOptFileCheck,fDstMp4iPodFileCheck,fVidQualityRFField,fVidQualityRFLabel}; @@ -483,7 +559,6 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It **********************************************************************/ - (void) UpdateDockIcon: (float) progress { - NSImage * icon; NSData * tiff; NSBitmapImageRep * bmp; uint32_t * pen; @@ -493,17 +568,14 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It int row_start, row_end; int i, j; - /* Get application original icon */ - icon = [NSImage imageNamed: @"NSApplicationIcon"]; - if( progress < 0.0 || progress > 1.0 ) { - [NSApp setApplicationIconImage: icon]; + [NSApp setApplicationIconImage: fApplicationIcon]; return; } /* Get it in a raw bitmap form */ - tiff = [icon TIFFRepresentationUsingCompression: + tiff = [fApplicationIcon TIFFRepresentationUsingCompression: NSTIFFCompressionNone factor: 1.0]; bmp = [NSBitmapImageRep imageRepWithData: tiff]; @@ -552,7 +624,7 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It /* Now update the dock icon */ tiff = [bmp TIFFRepresentationUsingCompression: NSTIFFCompressionNone factor: 1.0]; - icon = [[NSImage alloc] initWithData: tiff]; + NSImage* icon = [[NSImage alloc] initWithData: tiff]; [NSApp setApplicationIconImage: icon]; [icon release]; } @@ -591,8 +663,6 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It NSLocalizedString( @"Scanning title %d of %d...", @"" ), p.title_cur, p.title_count]]; [fScanIndicator setHidden: NO]; - double scanProgress = ( p.title_cur - 1 ) / p.title_count; - //[fScanIndicator setDoubleValue: 100.0 * scanProgress]; [fScanIndicator setDoubleValue: 100.0 * ((double)( p.title_cur - 1 ) / p.title_count)]; break; } @@ -649,7 +719,6 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It if( checkScanCount > currentScanCount ) { currentScanCount = checkScanCount; - [self writeToActivityLog:"currentScanCount received from fQueueEncodeLibhb"]; } //hb_state_t s; @@ -689,8 +758,25 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It case HB_STATE_WORKING: { NSMutableString * string; + NSString * pass_desc; /* Update text field */ - string = [NSMutableString stringWithFormat: NSLocalizedString( @"Encoding: pass %d of %d, %.2f %%", @"" ), p.job_cur, p.job_count, 100.0 * p.progress]; + if (p.job_cur == 1 && p.job_count > 1) + { + if ([[QueueFileArray objectAtIndex:currentQueueEncodeIndex] objectForKey:@"SubtitleList"] && [[[[[QueueFileArray objectAtIndex:currentQueueEncodeIndex]objectForKey:@"SubtitleList"] objectAtIndex:0] objectForKey:@"subtitleSourceTrackNum"] intValue] == 1) + { + pass_desc = @"(subtitle scan)"; + } + else + { + pass_desc = @""; + } + } + else + { + pass_desc = @""; + } + + string = [NSMutableString stringWithFormat: NSLocalizedString( @"Encoding: pass %d %@ of %d, %.2f %%", @"" ), p.job_cur, pass_desc, p.job_count, 100.0 * p.progress]; if( p.seconds > -1 ) { @@ -953,6 +1039,16 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [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"]; @@ -984,13 +1080,13 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It { return [NSArray arrayWithObjects: ChooseSourceIdentifier, NSToolbarSeparatorItemIdentifier, StartEncodingIdentifier, PauseEncodingIdentifier, AddToQueueIdentifier, ShowQueueIdentifier, NSToolbarFlexibleSpaceItemIdentifier, - NSToolbarSpaceItemIdentifier, ShowPictureIdentifier, ShowActivityIdentifier, ToggleDrawerIdentifier, nil]; + NSToolbarSpaceItemIdentifier, ShowPictureIdentifier, ShowPreviewIdentifier, ShowActivityIdentifier, ToggleDrawerIdentifier, nil]; } - (NSArray *) toolbarAllowedItemIdentifiers: (NSToolbar *) toolbar { return [NSArray arrayWithObjects: StartEncodingIdentifier, PauseEncodingIdentifier, AddToQueueIdentifier, - ChooseSourceIdentifier, ShowQueueIdentifier, ShowPictureIdentifier, ShowActivityIdentifier, ToggleDrawerIdentifier, + ChooseSourceIdentifier, ShowQueueIdentifier, ShowPictureIdentifier, ShowPreviewIdentifier, ShowActivityIdentifier, ToggleDrawerIdentifier, NSToolbarCustomizeToolbarItemIdentifier, NSToolbarFlexibleSpaceItemIdentifier, NSToolbarSpaceItemIdentifier, NSToolbarSeparatorItemIdentifier, nil]; } @@ -1028,6 +1124,8 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It return YES; if ([ident isEqualToString: ShowPictureIdentifier]) return YES; + if ([ident isEqualToString: ShowPreviewIdentifier]) + return YES; } } else if (s.state == HB_STATE_PAUSED) @@ -1046,6 +1144,8 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It return YES; if ([ident isEqualToString: ShowPictureIdentifier]) return YES; + if ([ident isEqualToString: ShowPreviewIdentifier]) + return YES; } else if (s.state == HB_STATE_SCANNING) return NO; @@ -1066,6 +1166,8 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It return YES; if ([ident isEqualToString: ShowPictureIdentifier]) return YES; + if ([ident isEqualToString: ShowPreviewIdentifier]) + return YES; } } @@ -1351,6 +1453,15 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It } } +- (IBAction)showAboutPanel:(id)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 { @@ -1396,6 +1507,10 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [fChapterTitlesDelegate resetWithTitle:nil]; [fChapterTable reloadData]; + // Notify Subtitles that there's no title + [fSubtitlesDelegate resetWithTitle:nil]; + [fSubtitlesTable reloadData]; + [self enableUI: NO]; if( [detector isVideoDVD] ) @@ -1405,15 +1520,28 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It path = [detector devicePath]; [self writeToActivityLog: "trying to open a physical dvd at: %s", [scanPath UTF8String]]; -#ifdef __LP64__ +#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!",@"This scan will be cancelled!", @"OK", nil, nil); + 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/Contents/MacOS/lib/libdvdcss.2.dylib"; @@ -1469,6 +1597,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 ..."]; } @@ -1491,6 +1621,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]; } @@ -1849,6 +1983,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"]; @@ -1860,8 +1995,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 @@ -1913,6 +2056,19 @@ fWorkingCount = 0; [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->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 = [fPictureSizeField stringValue]; [queueFileJob setObject:pictureSummary forKey:@"PictureSizingSummary"]; @@ -1984,13 +2140,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"]; @@ -2024,8 +2177,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) @@ -2060,10 +2211,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]; @@ -2515,10 +2663,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]]; @@ -2526,15 +2670,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; @@ -2544,14 +2684,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 @@ -2559,24 +2696,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; @@ -2587,8 +2713,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 ); } @@ -2605,6 +2729,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]; } @@ -2622,7 +2761,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; @@ -2700,8 +2840,147 @@ fWorkingCount = 0; } /* 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; + } + 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 we are getting the subtitles from an external srt file */ + if ([[tempObject objectForKey:@"subtitleSourceTrackType"] isEqualToString:@"SRT"]) + { + hb_subtitle_config_t sub_config; + + sub_config.offset = [[tempObject objectForKey:@"subtitleTrackSrtOffset"] intValue]; + + /* we need to srncpy file path and char code */ + strncpy(sub_config.src_filename, [[tempObject objectForKey:@"subtitleSourceSrtFilePath"] UTF8String], 128); + strncpy(sub_config.src_codeset, [[tempObject objectForKey:@"subtitleTrackSrtCharCode"] UTF8String], 40); + + sub_config.force = 0; + sub_config.dest = hb_subtitle_config_s::PASSTHRUSUB; + sub_config.default_track = def; + + hb_srt_add( job, &sub_config, [[tempObject objectForKey:@"subtitleTrackSrtLanguageIso3"] UTF8String]); + } + + 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); @@ -2913,6 +3192,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]; @@ -2923,11 +3204,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; @@ -2945,8 +3221,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 */ @@ -3026,7 +3301,18 @@ fWorkingCount = 0; job->keep_ratio = [[queueToApply objectForKey:@"PictureKeepRatio"] 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]; @@ -3084,25 +3370,168 @@ fWorkingCount = 0; } job->grayscale = [[queueToApply objectForKey:@"VideoGrayScale"] intValue]; - /* Subtitle settings */ - job->subtitle = [[queueToApply objectForKey:@"JobSubtitlesIndex"] intValue] - 2; - /* 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); - for( int i = 0; i < audiotrack_count;i++) - { - hb_audio_t * temp_audio = (hb_audio_t*) hb_list_item( job->list_audio, 0 ); - hb_list_rem(job->list_audio, temp_audio); - } - /* Now lets add our new tracks to the audio list here */ - if ([[queueToApply objectForKey:@"Audio1Track"] intValue] > 0) + + +#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]) { - audio = (hb_audio_config_t *) calloc(1, sizeof(*audio)); - hb_audio_config_init(audio); - audio->in.track = [[queueToApply objectForKey:@"Audio1Track"] intValue] - 1; - /* We go ahead and assign values to our audio->out. */ - audio->out.track = [[queueToApply objectForKey:@"Audio1Track"] intValue] - 1; + + 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 we are getting the subtitles from an external srt file */ + if ([[tempObject objectForKey:@"subtitleSourceTrackType"] isEqualToString:@"SRT"]) + { + hb_subtitle_config_t sub_config; + + sub_config.offset = [[tempObject objectForKey:@"subtitleTrackSrtOffset"] intValue]; + + /* we need to srncpy file name and codeset */ + //sub_config.src_filename = [[tempObject objectForKey:@"subtitleSourceSrtFilePath"] UTF8String]; + strncpy(sub_config.src_filename, [[tempObject objectForKey:@"subtitleSourceSrtFilePath"] UTF8String], 128); + //sub_config.src_codeset = [[tempObject objectForKey:@"subtitleTrackSrtCharCode"] UTF8String]; + strncpy(sub_config.src_codeset, [[tempObject objectForKey:@"subtitleTrackSrtCharCode"] UTF8String], 40); + + sub_config.force = 0; + sub_config.dest = hb_subtitle_config_s::PASSTHRUSUB; + sub_config.default_track = def; + + hb_srt_add( job, &sub_config, [[tempObject objectForKey:@"subtitleTrackSrtLanguageIso3"] UTF8String]); + } + + + 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); + for( int i = 0; i < audiotrack_count;i++) + { + hb_audio_t * temp_audio = (hb_audio_t*) hb_list_item( job->list_audio, 0 ); + hb_list_rem(job->list_audio, temp_audio); + } + /* Now lets add our new tracks to the audio list here */ + if ([[queueToApply objectForKey:@"Audio1Track"] intValue] > 0) + { + audio = (hb_audio_config_t *) calloc(1, sizeof(*audio)); + hb_audio_config_init(audio); + audio->in.track = [[queueToApply objectForKey:@"Audio1Track"] intValue] - 1; + /* We go ahead and assign values to our audio->out. */ + audio->out.track = [[queueToApply objectForKey:@"Audio1Track"] intValue] - 1; audio->out.codec = [[queueToApply objectForKey:@"JobAudio1Encoder"] intValue]; audio->out.mixdown = [[queueToApply objectForKey:@"JobAudio1Mixdown"] intValue]; audio->out.bitrate = [[queueToApply objectForKey:@"JobAudio1Bitrate"] intValue]; @@ -3162,7 +3591,8 @@ fWorkingCount = 0; audio->out.dynamic_range_compression = [[queueToApply objectForKey:@"Audio4TrackDRCSlider"] floatValue]; hb_audio_add( job, audio ); - free(audio); + + } /* Filters */ @@ -3638,7 +4068,26 @@ 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; @@ -3657,24 +4106,12 @@ fWorkingCount = 0; /* Reset the new title in fPictureController && fPreviewController*/ [fPictureController SetTitle:title]; - //[fPictureController SetTitle:title]; - /* 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]; - - [self subtitleSelectionChanged:nil]; + + /* Update Subtitle Table */ + [fSubtitlesDelegate resetWithTitle:title]; + [fSubtitlesTable reloadData]; + /* Update chapter table */ [fChapterTitlesDelegate resetWithTitle:title]; @@ -3713,7 +4150,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 @@ -3746,6 +4183,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 @@ -3770,8 +4218,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: @@ -3805,26 +4251,12 @@ 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) { @@ -4056,8 +4488,8 @@ the user is using "Custom" settings by determining the sender*/ qpRFLabelString = @"RF:"; } } - /* ffmpeg and xvid 1-31 */ - if ([[fVidEncoderPopUp selectedItem] tag] == HB_VCODEC_FFMPEG || [[fVidEncoderPopUp selectedItem] tag] == HB_VCODEC_XVID) + /* ffmpeg 1-31 */ + if ([[fVidEncoderPopUp selectedItem] tag] == HB_VCODEC_FFMPEG ) { [fVidQualitySlider setMinValue:1.0]; [fVidQualitySlider setMaxValue:31.0]; @@ -4366,7 +4798,7 @@ the user is using "Custom" settings by determining the sender*/ } [fVideoFiltersField setStringValue: [NSString stringWithFormat:@"Video Filters: %@", videoFilters]]; - [fPictureController reloadStillPreview]; + //[fPictureController reloadStillPreview]; } @@ -4468,7 +4900,7 @@ the user is using "Custom" settings by determining the sender*/ [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]; @@ -4492,7 +4924,7 @@ the user is using "Custom" settings by determining the sender*/ [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]; @@ -4516,7 +4948,7 @@ the user is using "Custom" settings by determining the sender*/ [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]; @@ -4540,7 +4972,7 @@ the user is using "Custom" settings by determining the sender*/ [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]; @@ -4643,10 +5075,14 @@ the user is using "Custom" settings by determining the sender*/ { 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]; @@ -4654,12 +5090,18 @@ the user is using "Custom" settings by determining the sender*/ 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]; @@ -4825,6 +5267,13 @@ the user is using "Custom" settings by determining the sender*/ 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 { @@ -4907,6 +5356,17 @@ the user is using "Custom" settings by determining the sender*/ 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 */ @@ -4955,6 +5415,24 @@ the user is using "Custom" settings by determining the sender*/ [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]; } @@ -5046,7 +5524,22 @@ the user is using "Custom" settings by determining the sender*/ 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; @@ -5087,7 +5580,7 @@ the user is using "Custom" settings by determining the sender*/ 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]; @@ -5135,11 +5628,11 @@ the user is using "Custom" settings by determining the sender*/ [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 */ @@ -5206,22 +5699,51 @@ the user is using "Custom" settings by determining the sender*/ //[self customSettingUsed: sender]; } -- (IBAction) subtitleSelectionChanged: (id) sender +#pragma mark - + +- (IBAction) browseImportSrtFile: (id) sender { - if ([fSubPopUp indexOfSelectedItem] == 0) + + NSOpenPanel * panel; + + panel = [NSOpenPanel openPanel]; + [panel setAllowsMultipleSelection: NO]; + [panel setCanChooseFiles: YES]; + [panel setCanChooseDirectories: NO ]; + NSString * sourceDirectory; + if ([[NSUserDefaults standardUserDefaults] stringForKey:@"LastSrtImportDirectory"]) { - [fSubForcedCheck setState: NSOffState]; - [fSubForcedCheck setEnabled: NO]; + sourceDirectory = [[NSUserDefaults standardUserDefaults] stringForKey:@"LastSrtImportDirectory"]; } else { - [fSubForcedCheck setEnabled: YES]; + sourceDirectory = @"~/Desktop"; + sourceDirectory = [sourceDirectory stringByExpandingTildeInPath]; } - + /* we open up the browse srt sheet here and call for browseImportSrtFileDone after the sheet is closed */ + NSArray *fileTypes = [NSArray arrayWithObjects:@"plist", @"srt", nil]; + [panel beginSheetForDirectory: sourceDirectory file: nil types: fileTypes + modalForWindow: fWindow modalDelegate: self + didEndSelector: @selector( browseImportSrtFileDone:returnCode:contextInfo: ) + contextInfo: sender]; } - - +- (void) browseImportSrtFileDone: (NSSavePanel *) sheet + returnCode: (int) returnCode contextInfo: (void *) contextInfo +{ + if( returnCode == NSOKButton ) + { + NSString *importSrtDirectory = [[sheet filename] stringByDeletingLastPathComponent]; + NSString *importSrtFilePath = [sheet filename]; + [[NSUserDefaults standardUserDefaults] setObject:importSrtDirectory forKey:@"LastSrtImportDirectory"]; + + /* now pass the string off to fSubtitlesDelegate to add the srt file to the dropdown */ + [fSubtitlesDelegate createSubtitleSrtTrack:importSrtFilePath]; + + [fSubtitlesTable reloadData]; + + } +} #pragma mark - #pragma mark Open New Windows @@ -5660,6 +6182,9 @@ 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 */ @@ -5696,7 +6221,16 @@ return YES; } else { - [fVidQualitySlider setFloatValue:([fVidQualitySlider maxValue] - [fVidQualitySlider minValue]) - [[chosenPreset objectForKey:@"VideoQualitySlider"] floatValue]]; + /* Since theora's qp value goes up from left to right, we can just set the slider float value */ + if ([[fVidEncoderPopUp selectedItem] tag] == HB_VCODEC_THEORA) + { + [fVidQualitySlider setFloatValue:[[chosenPreset objectForKey:@"VideoQualitySlider"] floatValue]]; + } + else + { + /* since ffmpeg and x264 use an "inverted" slider (lower qp/rf values indicate a higher quality) we invert the value on the slider */ + [fVidQualitySlider setFloatValue:([fVidQualitySlider maxValue] + [fVidQualitySlider minValue]) - [[chosenPreset objectForKey:@"VideoQualitySlider"] floatValue]]; + } } [self videoMatrixChanged:nil]; @@ -5722,124 +6256,250 @@ return YES; [fVidTurboPassCheck setState:[[chosenPreset objectForKey:@"VideoTurboTwoPass"] intValue]]; /*Audio*/ - - if ([chosenPreset objectForKey:@"Audio1Track"] > 0) + /* First we check to see if we are using the current audio track layout based on AudioList array */ + if ([chosenPreset objectForKey:@"AudioList"]) { - if ([fAudLang1PopUp indexOfSelectedItem] == 0) - { - [fAudLang1PopUp selectItemAtIndex: 1]; - } - [self audioTrackPopUpChanged: fAudLang1PopUp]; - [fAudTrack1CodecPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio1Encoder"]]; - [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 - * mixdown*/ - if ([fAudTrack1MixPopUp selectedItem] == nil) + /* 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]) { - [self audioTrackPopUpChanged: fAudTrack1CodecPopUp]; + i++; + if( i == 1 ) + { + if ([fAudLang1PopUp indexOfSelectedItem] == 0) + { + [fAudLang1PopUp selectItemAtIndex: 1]; + } + [self audioTrackPopUpChanged: fAudLang1PopUp]; + [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( i == 2 ) + { + + 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]; + + } + } - [fAudTrack1RatePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio1Samplerate"]]; - /* We set the presets bitrate if it is *not* an AC3 track since that uses the input bitrate */ - if (![[chosenPreset objectForKey:@"Audio1Encoder"] isEqualToString:@"AC3 Passthru"]) + + /* We now cleanup any extra audio tracks that may have been previously set if we need to */ + + if (i < 4) { - [fAudTrack1BitratePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio1Bitrate"]]; + [fAudLang4PopUp selectItemAtIndex: 0]; + [self audioTrackPopUpChanged: fAudLang4PopUp]; + + if (i < 3) + { + [fAudLang3PopUp selectItemAtIndex: 0]; + [self audioTrackPopUpChanged: fAudLang3PopUp]; + + if (i < 2) + { + [fAudLang2PopUp selectItemAtIndex: 0]; + [self audioTrackPopUpChanged: fAudLang2PopUp]; + } + } } - [fAudTrack1DrcSlider setFloatValue:[[chosenPreset objectForKey:@"Audio1TrackDRCSlider"] floatValue]]; - [self audioDRCSliderChanged: fAudTrack1DrcSlider]; + } - if ([chosenPreset objectForKey:@"Audio2Track"] > 0) + else { - if ([fAudLang2PopUp indexOfSelectedItem] == 0) + if ([chosenPreset objectForKey:@"Audio1Track"] > 0) { - [fAudLang2PopUp selectItemAtIndex: 1]; + if ([fAudLang1PopUp indexOfSelectedItem] == 0) + { + [fAudLang1PopUp selectItemAtIndex: 1]; + } + [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 + * mixdown*/ + if ([fAudTrack1MixPopUp selectedItem] == nil) + { + [self audioTrackPopUpChanged: fAudTrack1CodecPopUp]; + } + [fAudTrack1RatePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio1Samplerate"]]; + /* We set the presets bitrate if it is *not* an AC3 track since that uses the input bitrate */ + if (![[chosenPreset objectForKey:@"Audio1Encoder"] isEqualToString:@"AC3 Passthru"]) + { + [fAudTrack1BitratePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio1Bitrate"]]; + } + [fAudTrack1DrcSlider setFloatValue:[[chosenPreset objectForKey:@"Audio1TrackDRCSlider"] floatValue]]; + [self audioDRCSliderChanged: fAudTrack1DrcSlider]; } - [self audioTrackPopUpChanged: fAudLang2PopUp]; - [fAudTrack2CodecPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio2Encoder"]]; - [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 - * mixdown*/ - if ([fAudTrack2MixPopUp selectedItem] == nil) + if ([chosenPreset objectForKey:@"Audio2Track"] > 0) { + if ([fAudLang2PopUp indexOfSelectedItem] == 0) + { + [fAudLang2PopUp selectItemAtIndex: 1]; + } + [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 + * mixdown*/ + if ([fAudTrack2MixPopUp selectedItem] == nil) + { + [self audioTrackPopUpChanged: fAudTrack2CodecPopUp]; + } + [fAudTrack2RatePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio2Samplerate"]]; + /* We set the presets bitrate if it is *not* an AC3 track since that uses the input bitrate */ + if (![[chosenPreset objectForKey:@"Audio2Encoder"] isEqualToString:@"AC3 Passthru"]) + { + [fAudTrack2BitratePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio2Bitrate"]]; + } + [fAudTrack2DrcSlider setFloatValue:[[chosenPreset objectForKey:@"Audio2TrackDRCSlider"] floatValue]]; + [self audioDRCSliderChanged: fAudTrack2DrcSlider]; } - [fAudTrack2RatePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio2Samplerate"]]; - /* We set the presets bitrate if it is *not* an AC3 track since that uses the input bitrate */ - if (![[chosenPreset objectForKey:@"Audio2Encoder"] isEqualToString:@"AC3 Passthru"]) - { - [fAudTrack2BitratePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio2Bitrate"]]; - } - [fAudTrack2DrcSlider setFloatValue:[[chosenPreset objectForKey:@"Audio2TrackDRCSlider"] floatValue]]; - [self audioDRCSliderChanged: fAudTrack2DrcSlider]; - } - if ([chosenPreset objectForKey:@"Audio3Track"] > 0) - { - if ([fAudLang3PopUp indexOfSelectedItem] == 0) - { - [fAudLang3PopUp selectItemAtIndex: 1]; - } - [self audioTrackPopUpChanged: fAudLang3PopUp]; - [fAudTrack3CodecPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio3Encoder"]]; - [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 - * mixdown*/ - if ([fAudTrack3MixPopUp selectedItem] == nil) + if ([chosenPreset objectForKey:@"Audio3Track"] > 0) { + if ([fAudLang3PopUp indexOfSelectedItem] == 0) + { + [fAudLang3PopUp selectItemAtIndex: 1]; + } + [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 + * mixdown*/ + if ([fAudTrack3MixPopUp selectedItem] == nil) + { + [self audioTrackPopUpChanged: fAudTrack3CodecPopUp]; + } + [fAudTrack3RatePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio3Samplerate"]]; + /* We set the presets bitrate if it is *not* an AC3 track since that uses the input bitrate */ + if (![[chosenPreset objectForKey:@"Audio3Encoder"] isEqualToString: @"AC3 Passthru"]) + { + [fAudTrack3BitratePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio3Bitrate"]]; + } + [fAudTrack3DrcSlider setFloatValue:[[chosenPreset objectForKey:@"Audio3TrackDRCSlider"] floatValue]]; + [self audioDRCSliderChanged: fAudTrack3DrcSlider]; } - [fAudTrack3RatePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio3Samplerate"]]; - /* We set the presets bitrate if it is *not* an AC3 track since that uses the input bitrate */ - if (![[chosenPreset objectForKey:@"Audio3Encoder"] isEqualToString: @"AC3 Passthru"]) + if ([chosenPreset objectForKey:@"Audio4Track"] > 0) { - [fAudTrack3BitratePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio3Bitrate"]]; + if ([fAudLang4PopUp indexOfSelectedItem] == 0) + { + [fAudLang4PopUp selectItemAtIndex: 1]; + } + [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 + * mixdown*/ + if ([fAudTrack4MixPopUp selectedItem] == nil) + { + [self audioTrackPopUpChanged: fAudTrack4CodecPopUp]; + } + [fAudTrack4RatePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio4Samplerate"]]; + /* We set the presets bitrate if it is *not* an AC3 track since that uses the input bitrate */ + if (![[chosenPreset objectForKey:@"Audio4Encoder"] isEqualToString:@"AC3 Passthru"]) + { + [fAudTrack4BitratePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio4Bitrate"]]; + } + [fAudTrack4DrcSlider setFloatValue:[[chosenPreset objectForKey:@"Audio4TrackDRCSlider"] floatValue]]; + [self audioDRCSliderChanged: fAudTrack4DrcSlider]; } - [fAudTrack3DrcSlider setFloatValue:[[chosenPreset objectForKey:@"Audio3TrackDRCSlider"] floatValue]]; - [self audioDRCSliderChanged: fAudTrack3DrcSlider]; - } - if ([chosenPreset objectForKey:@"Audio4Track"] > 0) - { - if ([fAudLang4PopUp indexOfSelectedItem] == 0) + + /* We now cleanup any extra audio tracks that may have been previously set if we need to */ + + if (![chosenPreset objectForKey:@"Audio2Track"] || [chosenPreset objectForKey:@"Audio2Track"] == 0) { - [fAudLang4PopUp selectItemAtIndex: 1]; + [fAudLang2PopUp selectItemAtIndex: 0]; + [self audioTrackPopUpChanged: fAudLang2PopUp]; } - [self audioTrackPopUpChanged: fAudLang4PopUp]; - [fAudTrack4CodecPopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio4Encoder"]]; - [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 - * mixdown*/ - if ([fAudTrack4MixPopUp selectedItem] == nil) + if (![chosenPreset objectForKey:@"Audio3Track"] || [chosenPreset objectForKey:@"Audio3Track"] > 0) { - [self audioTrackPopUpChanged: fAudTrack4CodecPopUp]; + [fAudLang3PopUp selectItemAtIndex: 0]; + [self audioTrackPopUpChanged: fAudLang3PopUp]; } - [fAudTrack4RatePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio4Samplerate"]]; - /* We set the presets bitrate if it is *not* an AC3 track since that uses the input bitrate */ - if (![[chosenPreset objectForKey:@"Audio4Encoder"] isEqualToString:@"AC3 Passthru"]) + if (![chosenPreset objectForKey:@"Audio4Track"] || [chosenPreset objectForKey:@"Audio4Track"] > 0) { - [fAudTrack4BitratePopUp selectItemWithTitle:[chosenPreset objectForKey:@"Audio4Bitrate"]]; + [fAudLang4PopUp selectItemAtIndex: 0]; + [self audioTrackPopUpChanged: fAudLang4PopUp]; } - [fAudTrack4DrcSlider setFloatValue:[[chosenPreset objectForKey:@"Audio4TrackDRCSlider"] floatValue]]; - [self audioDRCSliderChanged: fAudTrack4DrcSlider]; - } - - /* We now cleanup any extra audio tracks that may have been previously set if we need to */ - - if (![chosenPreset objectForKey:@"Audio2Track"] || [chosenPreset objectForKey:@"Audio2Track"] == 0) - { - [fAudLang2PopUp selectItemAtIndex: 0]; - [self audioTrackPopUpChanged: fAudLang2PopUp]; - } - if (![chosenPreset objectForKey:@"Audio3Track"] || [chosenPreset objectForKey:@"Audio3Track"] > 0) - { - [fAudLang3PopUp selectItemAtIndex: 0]; - [self audioTrackPopUpChanged: fAudLang3PopUp]; - } - if (![chosenPreset objectForKey:@"Audio4Track"] || [chosenPreset objectForKey:@"Audio4Track"] > 0) - { - [fAudLang4PopUp selectItemAtIndex: 0]; - [self audioTrackPopUpChanged: fAudLang4PopUp]; } /*Subtitles*/ @@ -6060,6 +6720,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]; + } + } @@ -6147,6 +6847,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*/ @@ -6237,53 +6940,75 @@ return YES; [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"]; + + + /* Temporarily remove subtitles from creating a new preset as it has to be converted over to use the new + * subititle array code. */ /* Subtitles*/ - [preset setObject:[fSubPopUp titleOfSelectedItem] forKey:@"Subtitles"]; + //[preset setObject:[fSubPopUp titleOfSelectedItem] forKey:@"Subtitles"]; /* Forced Subtitles */ - [preset setObject:[NSNumber numberWithInt:[fSubForcedCheck state]] forKey:@"SubtitlesForced"]; + //[preset setObject:[NSNumber numberWithInt:[fSubForcedCheck state]] forKey:@"SubtitlesForced"]; } [preset autorelease]; return preset; @@ -6348,6 +7073,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 @@ -6606,25 +7444,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 /*******************************