#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";
{
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;
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];
[fQueueController release];
[fPreviewController release];
[fPictureController release];
-
+ [fApplicationIcon release];
+
hb_close(&fHandle);
hb_close(&fQueueEncodeLibhb);
}
/* Video encoder */
[fVidEncoderPopUp removeAllItems];
[fVidEncoderPopUp addItemWithTitle: @"FFmpeg"];
- [fVidEncoderPopUp addItemWithTitle: @"XviD"];
**********************************************************************/
- (void) UpdateDockIcon: (float) progress
{
- NSImage * icon;
NSData * tiff;
NSBitmapImageRep * bmp;
uint32_t * pen;
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];
/* 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];
}
if( checkScanCount > currentScanCount )
{
currentScanCount = checkScanCount;
- [self writeToActivityLog:"currentScanCount received from fQueueEncodeLibhb"];
}
//hb_state_t s;
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 )
{
[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"];
{
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];
}
return YES;
if ([ident isEqualToString: ShowPictureIdentifier])
return YES;
+ if ([ident isEqualToString: ShowPreviewIdentifier])
+ return YES;
}
}
else if (s.state == HB_STATE_PAUSED)
return YES;
if ([ident isEqualToString: ShowPictureIdentifier])
return YES;
+ if ([ident isEqualToString: ShowPreviewIdentifier])
+ return YES;
}
else if (s.state == HB_STATE_SCANNING)
return NO;
return YES;
if ([ident isEqualToString: ShowPictureIdentifier])
return YES;
+ if ([ident isEqualToString: ShowPreviewIdentifier])
+ return YES;
}
}
}
}
+- (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
{
[fChapterTitlesDelegate resetWithTitle:nil];
[fChapterTable reloadData];
+ // Notify Subtitles that there's no title
+ [fSubtitlesDelegate resetWithTitle:nil];
+ [fSubtitlesTable reloadData];
+
[self enableUI: NO];
if( [detector isVideoDVD] )
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"];
}
/* 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 ..."];
}
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];
}
}
/* 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"];
[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)
[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];
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.
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
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;
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 );
}
/* 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];
}
}
/* 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 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);
}
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 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);
audio->out.dynamic_range_compression = [[queueToApply objectForKey:@"Audio4TrackDRCSlider"] floatValue];
hb_audio_add( job, audio );
- free(audio);
+
+
}
/* Filters */
/* 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];
}
+ /* 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)
{
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];
[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];
[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];
[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];
[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];
{
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];
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];
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
{
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 */
[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];
}
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;
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];
[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 */
//[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
}
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];
}
[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
}
[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
}
[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
}
[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
}
[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
}
[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
[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];
+ }
+
}
- (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*/
[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;
}
}
+
+#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
}
- /* 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
/*******************************