X-Git-Url: http://git.osdn.jp/view?a=blobdiff_plain;f=macosx%2FController.mm;h=712622aaa3375bb6cbad1d888f7c39fe4bd41d46;hb=ac24fef71ded1f1884000fb9ce039b71587a8f30;hp=b38ade9a0fefaf387ee304d8cb7eddb2c4b660ea;hpb=7471b791f073ddfded5f3f1cd6b622f656b97505;p=handbrake-jp%2Fhandbrake-jp-git.git diff --git a/macosx/Controller.mm b/macosx/Controller.mm index b38ade9a..712622aa 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; @@ -100,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]; @@ -303,7 +319,8 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It [fQueueController release]; [fPreviewController release]; [fPictureController release]; - + [fApplicationIcon release]; + hb_close(&fHandle); hb_close(&fQueueEncodeLibhb); } @@ -395,7 +412,6 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It /* Video encoder */ [fVidEncoderPopUp removeAllItems]; [fVidEncoderPopUp addItemWithTitle: @"FFmpeg"]; - [fVidEncoderPopUp addItemWithTitle: @"XviD"]; @@ -543,7 +559,6 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It **********************************************************************/ - (void) UpdateDockIcon: (float) progress { - NSImage * icon; NSData * tiff; NSBitmapImageRep * bmp; uint32_t * pen; @@ -553,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]; @@ -612,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]; } @@ -707,7 +719,6 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It if( checkScanCount > currentScanCount ) { currentScanCount = checkScanCount; - [self writeToActivityLog:"currentScanCount received from fQueueEncodeLibhb"]; } //hb_state_t s; @@ -747,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 ) { @@ -1011,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"]; @@ -1042,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]; } @@ -1086,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) @@ -1104,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; @@ -1124,6 +1166,8 @@ static NSString * ChooseSourceIdentifier = @"Choose Source It return YES; if ([ident isEqualToString: ShowPictureIdentifier]) return YES; + if ([ident isEqualToString: ShowPreviewIdentifier]) + return YES; } } @@ -1409,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 { @@ -1454,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] ) @@ -1463,7 +1520,7 @@ 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"]; @@ -1540,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 ..."]; } @@ -1562,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]; } @@ -2077,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"]; @@ -2117,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) @@ -2153,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]; @@ -2608,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]]; @@ -2619,10 +2670,6 @@ 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; /* * If scanning we need to do some extra setup of the job. @@ -2641,9 +2688,7 @@ fWorkingCount = 0; 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 @@ -2651,18 +2696,13 @@ fWorkingCount = 0; hb_add( fQueueEncodeLibhb, job ); job->x264opts = x264opts_tmp; } - else - job->select_subtitle = NULL; + 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; @@ -2673,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 ); } @@ -2691,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]; } @@ -2787,29 +2840,129 @@ fWorkingCount = 0; } /* Subtitle settings */ - switch( [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]) { - case -2: - /* - * No subtitles selected - */ - break; - case -1: - /* - * Subtitle scan selected - */ - job->indepth_scan = 1; - break; - default: - /* - * Subtitle selected, add it into the job from the title. + + 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. */ - job->indepth_scan = 0; - hb_subtitle_t *subtitle = (hb_subtitle_t *) hb_list_item( title->list_subtitle, [fSubPopUp indexOfSelectedItem] - 2 ); - hb_list_add( job->list_subtitle, subtitle ); - break; - } + 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 (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); @@ -3033,11 +3186,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; @@ -3055,8 +3203,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 */ @@ -3205,32 +3352,131 @@ fWorkingCount = 0; } job->grayscale = [[queueToApply objectForKey:@"VideoGrayScale"] intValue]; - /* Subtitle settings */ - switch( [[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]) { - case -2: - /* - * No subtitles selected - */ - break; - case -1: - /* - * Subtitle scan selected - */ - job->indepth_scan = 1; - break; - default: - /* - * Subtitle selected, add it into the job from the title. + + 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. */ - job->indepth_scan = 0; - hb_subtitle_t *subtitle = (hb_subtitle_t *) hb_list_item( title->list_subtitle, - [[queueToApply objectForKey:@"JobSubtitlesIndex"] intValue] - 2 ); - hb_list_add( job->list_subtitle, subtitle ); - break; + 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); @@ -3306,7 +3552,8 @@ fWorkingCount = 0; audio->out.dynamic_range_compression = [[queueToApply objectForKey:@"Audio4TrackDRCSlider"] floatValue]; hb_audio_add( job, audio ); - free(audio); + + } /* Filters */ @@ -3821,23 +4068,11 @@ fWorkingCount = 0; /* Reset the new title in fPictureController && fPreviewController*/ [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]; @@ -3979,6 +4214,10 @@ fWorkingCount = 0; } + /* 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) { @@ -4210,8 +4449,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]; @@ -4622,7 +4861,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]; @@ -4646,7 +4885,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]; @@ -4670,7 +4909,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]; @@ -4694,7 +4933,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]; @@ -4797,10 +5036,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]; @@ -4808,12 +5051,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]; @@ -4979,6 +5228,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 { @@ -5061,6 +5317,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 */ @@ -5109,6 +5376,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]; } @@ -5200,7 +5485,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; @@ -5241,7 +5541,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]; @@ -5289,11 +5589,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 */ @@ -5360,22 +5660,6 @@ the user is using "Custom" settings by determining the sender*/ //[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 @@ -5853,7 +6137,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]; @@ -5879,124 +6172,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*/ @@ -6217,6 +6636,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]; + } + } @@ -6304,6 +6763,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*/ @@ -6394,53 +6856,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; @@ -6505,6 +6989,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 @@ -6763,25 +7360,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 /*******************************