It may be used under the terms of the GNU General Public License. */
#include "Controller.h"
+#include "a52dec/a52.h"
#define _(a) NSLocalizedString(a,NULL)
+
+
+
+
static int FormatSettings[3][4] =
{ { HB_MUX_MP4 | HB_VCODEC_FFMPEG | HB_ACODEC_FAAC,
HB_MUX_MP4 | HB_VCODEC_X264 | HB_ACODEC_FAAC,
- (void) applicationDidFinishLaunching: (NSNotification *) notification
{
+
+
int build;
char * version;
+
/* Init libhb */
fHandle = hb_init( HB_DEBUG_NONE, [[NSUserDefaults
standardUserDefaults] boolForKey:@"CheckForUpdates"] );
-
+ /* Set the Growl Delegate */
+ HBController *hbGrowlDelegate = [[HBController alloc] init];
+ [GrowlApplicationBridge setGrowlDelegate: hbGrowlDelegate];
/* Init others controllers */
[fScanController SetHandle: fHandle];
[fPictureController SetHandle: fHandle];
[fQueueController SetHandle: fHandle];
+
+ fChapterTitlesDelegate = [[ChapterTitles alloc] init];
+ [fChapterTable setDataSource:fChapterTitlesDelegate];
- /* Call UpdateUI every 2/10 sec */
+ /* Call UpdateUI every 2/10 sec */
[[NSRunLoop currentRunLoop] addTimer: [NSTimer
scheduledTimerWithTimeInterval: 0.2 target: self
selector: @selector( UpdateUI: ) userInfo: NULL repeats: FALSE]
if( ( build = hb_check_update( fHandle, &version ) ) > -1 )
{
/* Update available - tell the user */
- /* TEMPORARILY COMMENT OUT AS UPDATE CHECK IS NOT ACCURATE */
- /*
+
NSBeginInformationalAlertSheet( _( @"Update is available" ),
_( @"Go get it!" ), _( @"Discard" ), NULL, fWindow, self,
@selector( UpdateAlertDone:returnCode:contextInfo: ),
_( @"HandBrake %s (build %d) is now available for download." ),
version, build] );
return;
- */
+
}
/* Show scan panel ASAP */
[self TranslateStrings];
- /* Destination box */
+
+//[self registrationDictionaryForGrowl];
+/* Init User Presets .plist */
+ /* We declare the default NSFileManager into fileManager */
+ NSFileManager * fileManager = [NSFileManager defaultManager];
+ //presetPrefs = [[NSUserDefaults standardUserDefaults] retain];
+ /* we set the files and support paths here */
+ AppSupportDirectory = @"~/Library/Application Support/HandBrake";
+ AppSupportDirectory = [AppSupportDirectory stringByExpandingTildeInPath];
+
+ UserPresetsFile = @"~/Library/Application Support/HandBrake/UserPresets.plist";
+ UserPresetsFile = [UserPresetsFile stringByExpandingTildeInPath];
+
+ x264ProfilesFile = @"~/Library/Application Support/HandBrake/x264Profiles.plist";
+ x264ProfilesFile = [x264ProfilesFile stringByExpandingTildeInPath];
+ /* We check for the app support directory for media fork */
+ if ([fileManager fileExistsAtPath:AppSupportDirectory] == 0)
+ {
+ // If it doesnt exist yet, we create it here
+ [fileManager createDirectoryAtPath:AppSupportDirectory attributes:nil];
+ }
+ // We check for the presets.plist here
+
+ if ([fileManager fileExistsAtPath:UserPresetsFile] == 0)
+ {
+
+ [fileManager createFileAtPath:UserPresetsFile contents:nil attributes:nil];
+
+ }
+ // We check for the x264profiles.plist here
+
+ if ([fileManager fileExistsAtPath:x264ProfilesFile] == 0)
+ {
+
+ [fileManager createFileAtPath:x264ProfilesFile contents:nil attributes:nil];
+ }
+
+
+ UserPresetsFile = @"~/Library/Application Support/HandBrake/UserPresets.plist";
+ UserPresetsFile = [[UserPresetsFile stringByExpandingTildeInPath]retain];
+
+ UserPresets = [[NSMutableArray alloc] initWithContentsOfFile:UserPresetsFile];
+ if (nil == UserPresets)
+ {
+ UserPresets = [[NSMutableArray alloc] init];
+ [self AddFactoryPresets:NULL];
+ }
+ /* Show/Dont Show Presets drawer upon launch based
+ on user preference DefaultPresetsDrawerShow*/
+ if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPresetsDrawerShow"] > 0)
+ {
+ [fPresetDrawer open];
+ }
+
+
+
+ /* Destination box*/
[fDstFormatPopUp removeAllItems];
[fDstFormatPopUp addItemWithTitle: _( @"MP4 file" )];
[fDstFormatPopUp addItemWithTitle: _( @"AVI file" )];
[fDstFormatPopUp selectItemAtIndex: 0];
[self FormatPopUpChanged: NULL];
-
+ /* We enable the create chapters checkbox here since we are .mp4 */
+ [fCreateChapterMarkers setEnabled: YES];
+ if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultChapterMarkers"] > 0)
+ {
+ [fCreateChapterMarkers setState: NSOnState];
+ }
[fDstFile2Field setStringValue: [NSString stringWithFormat:
@"%@/Desktop/Movie.mp4", NSHomeDirectory()]];
/* Video quality */
[fVidTargetSizeField setIntValue: 700];
- [fVidBitrateField setIntValue: 1000];
+ [fVidBitrateField setIntValue: 1000];
+
[fVidQualityMatrix selectCell: fVidBitrateCell];
[self VideoMatrixChanged: NULL];
/* Video framerate */
[fVidRatePopUp removeAllItems];
- [fVidRatePopUp addItemWithTitle: _( @"Same as source" )];
+ [fVidRatePopUp addItemWithTitle: _( @"Same as source" )];
for( int i = 0; i < hb_video_rates_count; i++ )
{
[fVidRatePopUp addItemWithTitle:
[NSString stringWithCString: hb_video_rates[i].string]];
}
[fVidRatePopUp selectItemAtIndex: 0];
-
+
+ /* Picture Settings */
+ [fPicLabelPAROutp setStringValue: @""];
+ [fPicLabelPAROutputX setStringValue: @""];
+ [fPicSettingPARWidth setStringValue: @""];
+ [fPicSettingPARHeight setStringValue: @""];
+
/* Audio bitrate */
[fAudBitratePopUp removeAllItems];
for( int i = 0; i < hb_audio_bitrates_count; i++ )
[self EnableUI: NO];
[fPauseButton setEnabled: NO];
[fRipButton setEnabled: NO];
+
+
+
}
+// register a test notification and make
+// it enabled by default
+#define SERVICE_NAME @"Encode Done"
+- (NSDictionary *)registrationDictionaryForGrowl
+{
+NSDictionary *registrationDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
+[NSArray arrayWithObjects:SERVICE_NAME,nil], GROWL_NOTIFICATIONS_ALL,
+[NSArray arrayWithObjects:SERVICE_NAME,nil], GROWL_NOTIFICATIONS_DEFAULT,
+nil];
+
+return registrationDictionary;
+}
- (void) TranslateStrings
{
[fSrcDVD1Field setStringValue: _( @"DVD:" )];
{
hb_list_t * list;
hb_title_t * title;
+ int indxpri=0; // Used to search the longuest title (default in combobox)
+ int longuestpri=0; // Used to search the longuest title (default in combobox)
[fScanController UpdateUI: &s];
break;
}
+
[fSrcTitlePopUp removeAllItems];
for( int i = 0; i < hb_list_count( list ); i++ )
{
/* Use the dvd name in the default output field here
May want to add code to remove blank spaces for some dvd names*/
+ /* Check to see if the last destination has been set,use if so, if not, use Desktop */
+ if ([[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"])
+ {
+ [fDstFile2Field setStringValue: [NSString stringWithFormat:
+ @"%@/%@.mp4", [[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"],[NSString
+ stringWithUTF8String: title->name]]];
+ }
+ else
+ {
[fDstFile2Field setStringValue: [NSString stringWithFormat:
@"%@/Desktop/%@.mp4", NSHomeDirectory(),[NSString
stringWithUTF8String: title->name]]];
+ }
+
+
+ if (longuestpri < title->hours*60*60 + title->minutes *60 + title->seconds)
+ {
+ longuestpri=title->hours*60*60 + title->minutes *60 + title->seconds;
+ indxpri=i;
+ }
+
+
+ int format = [fDstFormatPopUp indexOfSelectedItem];
+ char * ext = NULL;
+ switch( format )
+ {
+ case 0:
+
+ /*Get Default MP4 File Extension for mpeg4 (.mp4 or .m4v) from prefs*/
+ if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultMpegName"] > 0)
+ {
+ ext = "m4v";
+ }
+ else
+ {
+ ext = "mp4";
+ }
+ break;
+ case 1:
+ ext = "avi";
+ case 2:
+ break;
+ ext = "ogm";
+ break;
+ }
+
+
+ NSString * string = [fDstFile2Field stringValue];
+ /* Add/replace File Output name to the correct extension*/
+ if( [string characterAtIndex: [string length] - 4] == '.' )
+ {
+ [fDstFile2Field setStringValue: [NSString stringWithFormat:
+ @"%@.%s", [string substringToIndex: [string length] - 4],
+ ext]];
+ }
+ else
+ {
+ [fDstFile2Field setStringValue: [NSString stringWithFormat:
+ @"%@.%s", string, ext]];
+ }
+
[fSrcTitlePopUp addItemWithTitle: [NSString
stringWithFormat: @"%d - %02dh%02dm%02ds",
title->seconds]];
}
-
+ // Select the longuest title
+ [fSrcTitlePopUp selectItemAtIndex: indxpri];
+ /* We set the Settings Display to "Default" here
+ until we get default presets implemented */
+ [fPresetSelectedDisplay setStringValue: @"Default"];
+
[self TitlePopUpChanged: NULL];
[self EnableUI: YES];
[fPauseButton setEnabled: NO];
/* Update slider */
progress_total = ( p.progress + p.job_cur - 1 ) / p.job_count;
+ [fRipIndicator setIndeterminate: NO];
[fRipIndicator setDoubleValue: 100.0 * progress_total];
/* Update dock icon */
#define p s.param.muxing
case HB_STATE_MUXING:
{
- float progress_total;
NSMutableString * string;
/* Update text field */
string = [NSMutableString stringWithFormat:
- _( @"Muxing: %.2f %%" ), 100.0 * p.progress];
+ _( @"Muxing..." )];
[fStatusField setStringValue: string];
/* Update slider */
- [fRipIndicator setDoubleValue: 100.0 * p.progress];
+ [fRipIndicator setIndeterminate: YES];
+ [fRipIndicator startAnimation: nil];
/* Update dock icon */
- [self UpdateDockIcon: 100.0 * p.progress];
+ [self UpdateDockIcon: 1.0];
[fPauseButton setEnabled: YES];
[fPauseButton setTitle: _( @"Pause" )];
#undef p
case HB_STATE_PAUSED:
- [fStatusField setStringValue: _( @"Paused" )];
+ [fStatusField setStringValue: _( @"Paused" )];
[fPauseButton setEnabled: YES];
[fPauseButton setTitle: _( @"Resume" )];
[fRipButton setEnabled: YES];
case HB_STATE_WORKDONE:
{
- [self EnableUI: YES];
+ //[self EnableUI: YES];
[fStatusField setStringValue: _( @"Done." )];
+ [fRipIndicator setIndeterminate: NO];
[fRipIndicator setDoubleValue: 0.0];
- [fRipButton setTitle: _( @"Rip" )];
-
+ [fRipButton setTitle: _( @"Start" )];
+
/* Restore dock icon */
[self UpdateDockIcon: -1.0];
-
+
[fPauseButton setEnabled: NO];
[fPauseButton setTitle: _( @"Pause" )];
[fRipButton setEnabled: YES];
- [fRipButton setTitle: _( @"Rip" )];
-
+ [fRipButton setTitle: _( @"Start" )];
+
/* FIXME */
hb_job_t * job;
while( ( job = hb_job( fHandle, 0 ) ) )
{
hb_rem( fHandle, job );
}
+
+ if (fEncodeState != 2) // if the encode has not been cancelled
+ {
+ /* Lets alert the user that the encode has finished */
+ /*Growl Notification*/
+ [self showGrowlDoneNotification: NULL];
+ /*On Screen Notification*/
+ int status;
+ NSBeep();
+ status = NSRunAlertPanel(@"Put down that cocktail...",@"your HandBrake encode is done!", @"OK", nil, nil);
+ //[NSApp requestUserAttention:NSInformationalRequest];
+ [NSApp requestUserAttention:NSCriticalRequest];
+ if ( status == NSAlertDefaultReturn )
+ {
+ [self EnableUI: YES];
+ }
+ }
+ else
+ {
+ [self EnableUI: YES];
+ }
break;
}
}
- /* FIXME: we should only do that when necessary */
- if( [fQueueCheck state] == NSOnState )
- {
+ /* Lets show the queue status
+ here in the main window*/
+
int count = hb_count( fHandle );
if( count )
{
- [fQueueCheck setTitle: [NSString stringWithFormat:
- @"Enable queue (%d task%s in queue)",
+ [fQueueStatus setStringValue: [NSString stringWithFormat:
+ @"%d task%s in the queue",
count, ( count > 1 ) ? "s" : ""]];
}
else
{
- [fQueueCheck setTitle: @"Enable queue (no task in queue)"];
+ [fQueueStatus setStringValue: @""];
}
- }
[[NSRunLoop currentRunLoop] addTimer: [NSTimer
scheduledTimerWithTimeInterval: 0.2 target: self
forMode: NSModalPanelRunLoopMode];
}
+-(IBAction)showGrowlDoneNotification:(id)sender
+{
+
+
+ [GrowlApplicationBridge
+ notifyWithTitle:@"Put down that cocktail..."
+ description:@"Thank You for using HandBrake"
+ notificationName:SERVICE_NAME
+ iconData:nil
+ priority:0
+ isSticky:1
+ clickContext:nil];
+}
+
- (void) EnableUI: (bool) b
{
NSControl * controls[] =
fVidEncoderField, fVidEncoderPopUp, fVidQualityField,
fVidQualityMatrix, fVidGrayscaleCheck, fSubField, fSubPopUp,
fAudLang1Field, fAudLang1PopUp, fAudLang2Field, fAudLang2PopUp,
+ fAudTrack1MixLabel, fAudTrack1MixPopUp, fAudTrack2MixLabel, fAudTrack2MixPopUp,
fAudRateField, fAudRatePopUp, fAudBitrateField,
- fAudBitratePopUp, fPictureButton, fQueueCheck };
+ fAudBitratePopUp, fPictureButton,fQueueStatus,
+ fPicSrcWidth,fPicSrcHeight,fPicSettingWidth,fPicSettingHeight,
+ fPicSettingARkeep,fPicSettingDeinterlace,fPicSettingARkeepDsply,
+ fPicSettingDeinterlaceDsply,fPicLabelSettings,fPicLabelSrc,fPicLabelOutp,
+ fPicLabelAr,fPicLabelDeinter,fPicLabelSrcX,fPicLabelOutputX,
+ fPicLabelPAROutp,fPicLabelPAROutputX,fPicSettingPARWidth,fPicSettingPARHeight,
+ fPicSettingPARDsply,fPicLabelAnamorphic,tableView,fPresetsAdd,fPresetsDelete,
+ fCreateChapterMarkers,fPresetNewX264OptLabel,fDisplayX264Options};
for( unsigned i = 0;
i < sizeof( controls ) / sizeof( NSControl * ); i++ )
}
}
[controls[i] setEnabled: b];
+
}
+
+ if (b) {
+
+ /* if we're enabling the interface, check if the audio mixdown controls need to be enabled or not */
+ /* these will have been enabled by the mass control enablement above anyway, so we're sense-checking it here */
+ [self SetEnabledStateOfAudioMixdownControls: NULL];
+
+ } else {
+
+ [tableView setEnabled: NO];
+
+ }
[self VideoMatrixChanged: NULL];
}
[self QualitySliderChanged: sender];
[self CalculateBitrate: sender];
+ [self CustomSettingUsed: sender];
}
- (IBAction) QualitySliderChanged: (id) sender
[fVidConstantCell setTitle: [NSString stringWithFormat:
_( @"Constant quality: %.0f %%" ), 100.0 *
[fVidQualitySlider floatValue]]];
+ [self CustomSettingUsed: sender];
}
- (IBAction) BrowseFile: (id) sender
{
/* Open a panel to let the user choose and update the text field */
NSSavePanel * panel = [NSSavePanel savePanel];
-
- [panel beginSheetForDirectory: NULL file: NULL
- modalForWindow: fWindow modalDelegate: self
- didEndSelector: @selector( BrowseFileDone:returnCode:contextInfo: )
- contextInfo: NULL];
+ /* We get the current file name and path from the destination field here */
+ [panel beginSheetForDirectory: [[fDstFile2Field stringValue] stringByDeletingLastPathComponent] file: [[fDstFile2Field stringValue] lastPathComponent]
+ modalForWindow: fWindow modalDelegate: self
+ didEndSelector: @selector( BrowseFileDone:returnCode:contextInfo: )
+ contextInfo: NULL];
}
- (void) BrowseFileDone: (NSSavePanel *) sheet
if( returnCode == NSOKButton )
{
[fDstFile2Field setStringValue: [sheet filename]];
- [self FormatPopUpChanged: NULL];
+
}
}
[NSApp runModalForWindow: fPicturePanel];
[NSApp endSheet: fPicturePanel];
[fPicturePanel orderOut: self];
+ [self CalculatePictureSizing: sender];
}
- (IBAction) ShowQueuePanel: (id) sender
hb_title_t * title = (hb_title_t *) hb_list_item( list,
[fSrcTitlePopUp indexOfSelectedItem] );
hb_job_t * job = title->job;
+ //int i;
/* Chapter selection */
job->chapter_start = [fSrcChapterStartPopUp indexOfSelectedItem] + 1;
job->chapter_end = [fSrcChapterEndPopUp indexOfSelectedItem] + 1;
-
+
/* Format and codecs */
int format = [fDstFormatPopUp indexOfSelectedItem];
int codecs = [fDstCodecsPopUp indexOfSelectedItem];
job->mux = FormatSettings[format][codecs] & HB_MUX_MASK;
job->vcodec = FormatSettings[format][codecs] & HB_VCODEC_MASK;
job->acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
-
+ /* We set the chapter marker extraction here based on the format being
+ mpeg4 and the checkbox being checked */
+ if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [fCreateChapterMarkers state] == NSOnState)
+ {
+ job->chapter_markers = 1;
+ }
+ else
+ {
+ job->chapter_markers = 0;
+ }
if( ( job->vcodec & HB_VCODEC_FFMPEG ) &&
[fVidEncoderPopUp indexOfSelectedItem] > 0 )
{
Lets Deprecate Baseline Level 1.3*/
job->h264_level = 30;
job->mux = HB_MUX_IPOD;
+ /* move sanity check for iPod Encoding here */
+ job->pixel_ratio = 0 ;
+
}
- /* Set this flag to switch from Constant Quantizer(default) to Constant Rate Factor */
- // job->crf = 1;
+ /* Set this flag to switch from Constant Quantizer(default) to Constant Rate Factor Thanks jbrjake
+ Currently only used with Constant Quality setting*/
+ if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultCrf"] > 0 && [fVidQualityMatrix selectedRow] == 2)
+ {
+ /* Can only be used with svn rev >= 89 */
+ job->crf = 1;
+ }
+
+ /* Below Sends x264 options to the core library if x264 is selected*/
+ /* First we look to see if a user preset has been selected that contains a x264 optional string CurUserPresetChosenNum = nil */
+ if (curUserPresetChosenNum != nil)
+ {
+
+ /* Lets use this as per Nyx, Thanks Nyx! */
+ job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */
+ strcpy(job->x264opts, [[chosenPreset valueForKey:@"x264Option"] UTF8String]);
+ //job->x264opts = [[chosenPreset valueForKey:@"x264Option"] cString];
+ }
+ else
+ {
+ /* if not, then we check to see if there is a x264 opt in the preferences and use that if we want */
+ //job->x264opts = [[[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"] UTF8String];
+ /* Lets use this as per Nyx, Thanks Nyx! */
+ job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */
+ strcpy(job->x264opts, [[[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"] UTF8String]);
+ }
+
+
job->h264_13 = [fVidEncoderPopUp indexOfSelectedItem];
}
}
job->grayscale = ( [fVidGrayscaleCheck state] == NSOnState );
+
+
/* Subtitle settings */
job->subtitle = [fSubPopUp indexOfSelectedItem] - 1;
- /* Audio tracks */
- job->audios[0] = [fAudLang1PopUp indexOfSelectedItem] - 1;
- job->audios[1] = [fAudLang2PopUp indexOfSelectedItem] - 1;
- job->audios[2] = -1;
+ /* Audio tracks and mixdowns */
+ /* check for the condition where track 2 has an audio selected, but track 1 does not */
+ /* we will use track 2 as track 1 in this scenario */
+ if ([fAudLang1PopUp indexOfSelectedItem] > 0)
+ {
+ job->audios[0] = [fAudLang1PopUp indexOfSelectedItem] - 1;
+ job->audios[1] = [fAudLang2PopUp indexOfSelectedItem] - 1; /* will be -1 if "none" is selected */
+ job->audios[2] = -1;
+ job->audio_mixdowns[0] = [[fAudTrack1MixPopUp selectedItem] tag];
+ job->audio_mixdowns[1] = [[fAudTrack2MixPopUp selectedItem] tag];
+ }
+ else if ([fAudLang2PopUp indexOfSelectedItem] > 0)
+ {
+ job->audios[0] = [fAudLang2PopUp indexOfSelectedItem] - 1;
+ job->audio_mixdowns[0] = [[fAudTrack2MixPopUp selectedItem] tag];
+ job->audios[1] = -1;
+ }
+ else
+ {
+ job->audios[0] = -1;
+ }
/* Audio settings */
job->arate = hb_audio_rates[[fAudRatePopUp
indexOfSelectedItem]].rate;
- job->abitrate = hb_audio_bitrates[[fAudBitratePopUp
- indexOfSelectedItem]].rate;
-}
+ job->abitrate = [[fAudBitratePopUp selectedItem] tag];
-- (IBAction) EnableQueue: (id) sender
-{
- bool e = ( [fQueueCheck state] == NSOnState );
- [fQueueAddButton setHidden: !e];
- [fQueueShowButton setHidden: !e];
- [fRipButton setTitle: e ? @"Start" : @"Rip"];
}
-- (IBAction) AddToQueue: (id) sender
-{
- hb_list_t * list = hb_get_titles( fHandle );
- hb_title_t * title = (hb_title_t *) hb_list_item( list,
- [fSrcTitlePopUp indexOfSelectedItem] );
- hb_job_t * job = title->job;
-
- [self PrepareJob];
- /* Destination file */
- job->file = strdup( [[fDstFile2Field stringValue] UTF8String] );
- if( [fVidTwoPassCheck state] == NSOnState )
- {
- job->pass = 1;
- hb_add( fHandle, job );
- job->pass = 2;
- hb_add( fHandle, job );
- }
- else
- {
- job->pass = 0;
- hb_add( fHandle, job );
- }
+- (IBAction) AddToQueue: (id) sender
+{
+/* We get the destination directory from the destingation field here */
+ NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent];
+ /* We check for a valid destination here */
+ if ([[NSFileManager defaultManager] fileExistsAtPath:destinationDirectory] == 0)
+ {
+ NSRunAlertPanel(@"Warning!", @"This is not a valid destination directory!", @"OK", nil, nil);
+ }
+ else
+ {
+
+ hb_list_t * list = hb_get_titles( fHandle );
+ hb_title_t * title = (hb_title_t *) hb_list_item( list,
+ [fSrcTitlePopUp indexOfSelectedItem] );
+ hb_job_t * job = title->job;
+
+ [self PrepareJob];
+
+ /* Destination file */
+ job->file = [[fDstFile2Field stringValue] UTF8String];
+
+ if( [fVidTwoPassCheck state] == NSOnState )
+ {
+ job->pass = 1;
+ hb_add( fHandle, job );
+ job->pass = 2;
+ /* First we look to see if a user preset has been selected that contains a x264 optional string CurUserPresetChosenNum = nil */
+ if (curUserPresetChosenNum != nil)
+ {
+
+ /* Lets use this as per Nyx, Thanks Nyx! */
+ job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */
+ strcpy(job->x264opts, [[chosenPreset valueForKey:@"x264Option"] UTF8String]);
+ //job->x264opts = [[chosenPreset valueForKey:@"x264Option"] cString];
+ }
+ else
+ {
+ //job->x264opts = [[[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"] UTF8String];
+ /* Lets use this as per Nyx, Thanks Nyx! */
+ job->x264opts = (char *)calloc(1024,1); /* Fixme, this just leaks */
+ strcpy(job->x264opts, [[[NSUserDefaults standardUserDefaults]stringForKey:@"DefAdvancedx264Flags"] UTF8String]);
+ }
+ hb_add( fHandle, job );
+ }
+ else
+ {
+ job->pass = 0;
+ hb_add( fHandle, job );
+ }
+
+ [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"];
+ }
}
- (IBAction) Rip: (id) sender
[self Cancel: sender];
return;
}
-
- if( [fQueueCheck state] == NSOffState )
- {
- [self AddToQueue: sender];
- }
-
- if( [[NSFileManager defaultManager] fileExistsAtPath:
+ /* if there is no job in the queue, then add it to the queue and rip
+ otherwise, there are already jobs in queue, so just rip the queue */
+ int count = hb_count( fHandle );
+ if( count < 1 )
+ {
+ [self AddToQueue: sender];
+ }
+
+ /* We check for duplicate name here */
+ if( [[NSFileManager defaultManager] fileExistsAtPath:
[fDstFile2Field stringValue]] )
{
NSBeginCriticalAlertSheet( _( @"File already exists" ),
[fDstFile2Field stringValue]] );
return;
}
+ /* We get the destination directory from the destination field here */
+ NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent];
+ /* We check for a valid destination here */
+ if ([[NSFileManager defaultManager] fileExistsAtPath:destinationDirectory] == 0)
+ {
+ NSRunAlertPanel(@"Warning!", @"This is not a valid destination directory!", @"OK", nil, nil);
+ }
+ else
+ {
+ [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"];
+ [self _Rip];
+ }
+
+
- [self _Rip];
}
- (void) OverwriteAlertDone: (NSWindow *) sheet
{
/* Let libhb do the job */
hb_start( fHandle );
+ /*set the fEncodeState State */
+ fEncodeState = 1;
/* Disable interface */
- [self EnableUI: NO];
+ [self EnableUI: NO];
[fPauseButton setEnabled: NO];
[fRipButton setEnabled: NO];
}
hb_stop( fHandle );
[fPauseButton setEnabled: NO];
[fRipButton setEnabled: NO];
+ /*set the fEncodeState State */
+ fEncodeState = 2;
}
}
hb_list_t * list = hb_get_titles( fHandle );
hb_title_t * title = (hb_title_t*)
hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
+
+
+ /* If Auto Naming is on. We create an output filename of dvd name - title number */
+ if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultAutoNaming"] > 0)
+ {
+ [fDstFile2Field setStringValue: [NSString stringWithFormat:
+ @"%@/%@-%d.%@", [[fDstFile2Field stringValue] stringByDeletingLastPathComponent],
+ [NSString stringWithUTF8String: title->name],
+ [fSrcTitlePopUp indexOfSelectedItem] + 1,
+ [[fDstFile2Field stringValue] pathExtension]]];
+ }
/* Update chapter popups */
[fSrcChapterStartPopUp removeAllItems];
hb_list_count( title->list_chapter ) - 1];
[self ChapterPopUpChanged: NULL];
+/* Start Get and set the initial pic size for display */
+ hb_job_t * job = title->job;
+ fTitle = title;
+ /* Turn Deinterlace on/off depending on the preference */
+ if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultDeinterlaceOn"] > 0)
+ {
+ job->deinterlace = 1;
+ }
+ else
+ {
+ job->deinterlace = 0;
+ }
+
+ /* Pixel Ratio Setting */
+ if ([[NSUserDefaults standardUserDefaults] boolForKey:@"PixelRatio"])
+ {
+
+ job->pixel_ratio = 1 ;
+ }
+ else
+ {
+ job->pixel_ratio = 0 ;
+ }
+ /*Set Source Size Fields Here */
+ [fPicSrcWidth setStringValue: [NSString stringWithFormat:
+ @"%d", fTitle->width]];
+ [fPicSrcHeight setStringValue: [NSString stringWithFormat:
+ @"%d", fTitle->height]];
+ /* We get the originial output picture width and height and put them
+ in variables for use with some presets later on */
+ PicOrigOutputWidth = job->width;
+ PicOrigOutputHeight = job->height;
+ /* we test getting the max output value for pic sizing here to be used later*/
+ [fPicSettingWidth setStringValue: [NSString stringWithFormat:
+ @"%d", PicOrigOutputWidth]];
+ [fPicSettingHeight setStringValue: [NSString stringWithFormat:
+ @"%d", PicOrigOutputHeight]];
+ /* we run the picture size values through
+ CalculatePictureSizing to get all picture size
+ information*/
+ [self CalculatePictureSizing: NULL];
+ /* Run Through EncoderPopUpChanged to see if there
+ needs to be any pic value modifications based on encoder settings */
+ //[self EncoderPopUpChanged: NULL];
+ /* END Get and set the initial pic size for display */
+
/* Update subtitle popups */
hb_subtitle_t * subtitle;
[fSubPopUp removeAllItems];
subtitle->lang] action: NULL keyEquivalent: @""];
}
[fSubPopUp selectItemAtIndex: 0];
+
+ /* Update chapter table */
+ [fChapterTitlesDelegate resetWithTitle:title];
+ [fChapterTable reloadData];
+
+ /* Update audio popups */
+ [self AddAllAudioTracksToPopUp: fAudLang1PopUp];
+ [self AddAllAudioTracksToPopUp: fAudLang2PopUp];
+ /* search for the first instance of our prefs default language for track 1, and set track 2 to "none" */
+ NSString * audioSearchPrefix = [[NSUserDefaults standardUserDefaults] stringForKey:@"DefaultLanguage"];
+ [self SelectAudioTrackInPopUp: fAudLang1PopUp searchPrefixString: audioSearchPrefix selectIndexIfNotFound: 1];
+ [self SelectAudioTrackInPopUp: fAudLang2PopUp searchPrefixString: NULL selectIndexIfNotFound: 0];
+
+ /* changing the title may have changed the audio channels on offer, */
+ /* so call AudioTrackPopUpChanged for both audio tracks to update the mixdown popups */
+ [self AudioTrackPopUpChanged: fAudLang1PopUp];
+ [self AudioTrackPopUpChanged: fAudLang2PopUp];
- /* Update lang popups */
- hb_audio_t * audio;
- // PRI CHANGES 02/12/06
- NSString * audiotmppri;
- NSString * audiosearchpri=[[NSUserDefaults standardUserDefaults] stringForKey:@"DefaultLanguage"];
- int indxpri=0;
- // End of pri changes 02/12/06
- [fAudLang1PopUp removeAllItems];
- [fAudLang2PopUp removeAllItems];
- [fAudLang1PopUp addItemWithTitle: _( @"None" )];
- [fAudLang2PopUp addItemWithTitle: _( @"None" )];
- for( int i = 0; i < hb_list_count( title->list_audio ); i++ )
- {
- audio = (hb_audio_t *) hb_list_item( title->list_audio, i );
- // PRI CHANGES 02/12/06
- audiotmppri=(NSString *) [NSString stringWithCString: audio->lang];
- // Try to find the desired default language
- if ([audiotmppri hasPrefix:audiosearchpri] && indxpri==0)
- {
- indxpri=i+1;
- }
- // End of pri changes 02/12/06
-
- [[fAudLang1PopUp menu] addItemWithTitle:
- [NSString stringWithCString: audio->lang]
- action: NULL keyEquivalent: @""];
- [[fAudLang2PopUp menu] addItemWithTitle:
- [NSString stringWithCString: audio->lang]
- action: NULL keyEquivalent: @""];
- }
- // PRI CHANGES 02/12/06
- if (indxpri==0) { indxpri=1; }
- [fAudLang1PopUp selectItemAtIndex: indxpri];
- // End of pri changes 02/12/06
- [fAudLang2PopUp selectItemAtIndex: 0];
}
- (IBAction) ChapterPopUpChanged: (id) sender
switch( format )
{
case 0:
- ext = "mp4";
+ /*Get Default MP4 File Extension*/
+ if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultMpegName"] > 0)
+ {
+ ext = "m4v";
+ }
+ else
+ {
+ ext = "mp4";
+ }
[fDstCodecsPopUp addItemWithTitle:
_( @"MPEG-4 Video / AAC Audio" )];
[fDstCodecsPopUp addItemWithTitle:
_( @"AVC/H.264 Video / AAC Audio" )];
- break;
+ /* We enable the create chapters checkbox here since we are .mp4*/
+ [fCreateChapterMarkers setEnabled: YES];
+ break;
case 1:
ext = "avi";
[fDstCodecsPopUp addItemWithTitle:
_( @"AVC/H.264 Video / MP3 Audio" )];
[fDstCodecsPopUp addItemWithTitle:
_( @"AVC/H.264 Video / AC-3 Audio" )];
+ /* We disable the create chapters checkbox here since we are NOT .mp4
+ and make sure it is unchecked*/
+ [fCreateChapterMarkers setEnabled: NO];
+ [fCreateChapterMarkers setState: NSOffState];
break;
case 2:
ext = "ogm";
_( @"MPEG-4 Video / Vorbis Audio" )];
[fDstCodecsPopUp addItemWithTitle:
_( @"MPEG-4 Video / MP3 Audio" )];
- break;
+ /* We disable the create chapters checkbox here since we are NOT .mp4
+ and make sure it is unchecked*/
+ [fCreateChapterMarkers setEnabled: NO];
+ [fCreateChapterMarkers setState: NSOffState];
+ break;
}
[self CodecsPopUpChanged: NULL];
[fDstFile2Field setStringValue: [NSString stringWithFormat:
@"%@.%s", string, ext]];
}
+
+ /* changing the format may mean that we can / can't offer mono or 6ch, */
+ /* so call AudioTrackPopUpChanged for both audio tracks to update the mixdown popups */
+ [self AudioTrackPopUpChanged: fAudLang1PopUp];
+ [self AudioTrackPopUpChanged: fAudLang2PopUp];
+
+ /* We call method method to change UI to reflect whether a preset is used or not*/
+ [self CustomSettingUsed: sender];
+
}
- (IBAction) CodecsPopUpChanged: (id) sender
[fAudBitratePopUp setEnabled: YES];
}
+ /* changing the codecs on offer may mean that we can / can't offer mono or 6ch, */
+ /* so call AudioTrackPopUpChanged for both audio tracks to update the mixdown popups */
+ [self AudioTrackPopUpChanged: fAudLang1PopUp];
+ [self AudioTrackPopUpChanged: fAudLang2PopUp];
+
[self CalculateBitrate: sender];
+ /* We call method method to change UI to reflect whether a preset is used or not*/
+ [self CustomSettingUsed: sender];
+}
+
+- (IBAction) EncoderPopUpChanged: (id) sender
+{
+
+ /* Check to see if we need to modify the job pic values based on x264 (iPod) encoder selection */
+ if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [fDstCodecsPopUp indexOfSelectedItem] == 1 && [fVidEncoderPopUp indexOfSelectedItem] == 1)
+ {
+ hb_job_t * job = fTitle->job;
+ job->pixel_ratio = 0 ;
+
+ if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPicSizeAutoiPod"] > 0)
+ {
+
+ if (job->width > 640)
+ {
+ job->width = 640;
+ }
+ job->keep_ratio = 1;
+ hb_fix_aspect( job, HB_KEEP_WIDTH );
+
+ }
+
+ }
+
+ [self CalculatePictureSizing: sender];
+ /* We call method method to change UI to reflect whether a preset is used or not*/
+ [self CustomSettingUsed: sender];
+}
+
+- (IBAction) SetEnabledStateOfAudioMixdownControls: (id) sender
+{
+
+ /* enable/disable the mixdown text and popupbutton for audio track 1 */
+ [fAudTrack1MixPopUp setEnabled: ([fAudLang1PopUp indexOfSelectedItem] == 0) ? NO : YES];
+ [fAudTrack1MixLabel setTextColor: ([fAudLang1PopUp indexOfSelectedItem] == 0) ?
+ [NSColor disabledControlTextColor] : [NSColor controlTextColor]];
+
+ /* enable/disable the mixdown text and popupbutton for audio track 2 */
+ [fAudTrack2MixPopUp setEnabled: ([fAudLang2PopUp indexOfSelectedItem] == 0) ? NO : YES];
+ [fAudTrack2MixLabel setTextColor: ([fAudLang2PopUp indexOfSelectedItem] == 0) ?
+ [NSColor disabledControlTextColor] : [NSColor controlTextColor]];
+
+}
+
+- (IBAction) AddAllAudioTracksToPopUp: (id) sender
+{
+
+ hb_list_t * list = hb_get_titles( fHandle );
+ hb_title_t * title = (hb_title_t*)
+ hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
+
+ hb_audio_t * audio;
+
+ [sender removeAllItems];
+ [sender addItemWithTitle: _( @"None" )];
+ for( int i = 0; i < hb_list_count( title->list_audio ); i++ )
+ {
+ audio = (hb_audio_t *) hb_list_item( title->list_audio, i );
+ [[sender menu] addItemWithTitle:
+ [NSString stringWithCString: audio->lang]
+ action: NULL keyEquivalent: @""];
+ }
+ [sender selectItemAtIndex: 0];
+
+}
+
+- (IBAction) SelectAudioTrackInPopUp: (id) sender searchPrefixString: (NSString *) searchPrefixString selectIndexIfNotFound: (int) selectIndexIfNotFound
+{
+
+ /* this method can be used to find a language, or a language-and-source-format combination, by passing in the appropriate string */
+ /* e.g. to find the first French track, pass in an NSString * of "Francais" */
+ /* e.g. to find the first English 5.1 AC3 track, pass in an NSString * of "English (AC3) (5.1 ch)" */
+ /* if no matching track is found, then selectIndexIfNotFound is used to choose which track to select instead */
+
+ if (searchPrefixString != NULL)
+ {
+
+ for( int i = 0; i < [sender numberOfItems]; i++ )
+ {
+ /* Try to find the desired search string */
+ if ([[[sender itemAtIndex: i] title] hasPrefix:searchPrefixString])
+ {
+ [sender selectItemAtIndex: i];
+ return;
+ }
+ }
+ /* couldn't find the string, so select the requested "search string not found" item */
+ /* index of 0 means select the "none" item */
+ /* index of 1 means select the first audio track */
+ [sender selectItemAtIndex: selectIndexIfNotFound];
+ }
+ else
+ {
+ /* if no search string is provided, then select the selectIndexIfNotFound item */
+ [sender selectItemAtIndex: selectIndexIfNotFound];
+ }
+
+}
+
+- (IBAction) AudioTrackPopUpChanged: (id) sender
+{
+ /* utility function to call AudioTrackPopUpChanged without passing in a mixdown-to-use */
+ [self AudioTrackPopUpChanged: sender mixdownToUse: 0];
+}
+
+- (IBAction) AudioTrackPopUpChanged: (id) sender mixdownToUse: (int) mixdownToUse
+{
+
+ /* make sure we have a selected title before continuing */
+ if (fTitle == NULL) return;
+
+ /* find out if audio track 1 or 2 was changed - this is passed to us in the tag of the sender */
+ /* the sender will have been either fAudLang1PopUp (tag = 0) or fAudLang2PopUp (tag = 1) */
+ int thisAudio = [sender tag];
+
+ /* get the index of the selected audio */
+ int thisAudioIndex = [sender indexOfSelectedItem] - 1;
+
+ /* Handbrake can't currently cope with ripping the same source track twice */
+ /* So, if this audio is also selected in the other audio track popup, set that popup's selection to "none" */
+ /* get a reference to the two audio track popups */
+ NSPopUpButton * thisAudioPopUp = (thisAudio == 1 ? fAudLang2PopUp : fAudLang1PopUp);
+ NSPopUpButton * otherAudioPopUp = (thisAudio == 1 ? fAudLang1PopUp : fAudLang2PopUp);
+ /* if the same track is selected in the other audio popup, then select "none" in that popup */
+ /* unless, of course, both are selected as "none!" */
+ if ([thisAudioPopUp indexOfSelectedItem] != 0 && [thisAudioPopUp indexOfSelectedItem] == [otherAudioPopUp indexOfSelectedItem]) {
+ [otherAudioPopUp selectItemAtIndex: 0];
+ [self AudioTrackPopUpChanged: otherAudioPopUp];
+ }
+
+ /* pointer for the hb_audio_s struct we will use later on */
+ hb_audio_t * audio;
+
+ /* find out what the currently-selected output audio codec is */
+ int format = [fDstFormatPopUp indexOfSelectedItem];
+ int codecs = [fDstCodecsPopUp indexOfSelectedItem];
+ int acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
+
+ /* pointer to this track's mixdown NSPopUpButton */
+ NSTextField * mixdownTextField;
+ NSPopUpButton * mixdownPopUp;
+
+ /* find our mixdown NSTextField and NSPopUpButton */
+ if (thisAudio == 0)
+ {
+ mixdownTextField = fAudTrack1MixLabel;
+ mixdownPopUp = fAudTrack1MixPopUp;
+ }
+ else
+ {
+ mixdownTextField = fAudTrack2MixLabel;
+ mixdownPopUp = fAudTrack2MixPopUp;
+ }
+
+ /* delete the previous audio mixdown options */
+ [mixdownPopUp removeAllItems];
+
+ /* check if the audio mixdown controls need their enabled state changing */
+ [self SetEnabledStateOfAudioMixdownControls: NULL];
+
+ if (thisAudioIndex != -1)
+ {
+
+ /* get the audio */
+ audio = (hb_audio_t *) hb_list_item( fTitle->list_audio, thisAudioIndex );
+ if (audio != NULL)
+ {
+
+ /* find out if our selected output audio codec supports mono and / or 6ch */
+ /* we also check for an input codec of AC3,
+ as it is the only library able to do the mixdown to mono / conversion to 6-ch */
+ /* audioCodecsSupportMono and audioCodecsSupport6Ch are the same for now,
+ but this may change in the future, so they are separated for flexibility */
+ int audioCodecsSupportMono = (audio->codec == HB_ACODEC_AC3 && acodec == HB_ACODEC_FAAC);
+ int audioCodecsSupport6Ch = (audio->codec == HB_ACODEC_AC3 && acodec == HB_ACODEC_FAAC);
+
+ /* check for AC-3 passthru */
+ if (audio->codec == HB_ACODEC_AC3 && acodec == HB_ACODEC_AC3)
+ {
+ [[mixdownPopUp menu] addItemWithTitle:
+ [NSString stringWithCString: "AC3 Passthru"]
+ action: NULL keyEquivalent: @""];
+ }
+ else
+ {
+
+ /* find out the audio channel layout for our input audio */
+ /* we'll cheat and use the liba52 layouts, even if the source isn't AC3 */
+ int channel_layout;
+ int audio_has_lfe;
+ if (audio->codec == HB_ACODEC_AC3)
+ {
+ channel_layout = (audio->ac3flags & A52_CHANNEL_MASK);
+ audio_has_lfe = (audio->ac3flags & A52_LFE);
+ }
+ else
+ {
+ /* assume a stereo input for all other input codecs */
+ /* we're cheating and using liba52's A52_STEREO layout here, even though the source isn't AC3 */
+ channel_layout = A52_STEREO;
+ audio_has_lfe = 0;
+ }
+
+ /* add the appropriate audio mixdown menuitems to the popupbutton */
+ /* in each case, we set the new menuitem's tag to be the amixdown value for that mixdown,
+ so that we can reference the mixdown later */
+
+ /* keep a track of the min and max mixdowns we used, so we can select the best match later */
+ int minMixdownUsed = 0;
+ int maxMixdownUsed = 0;
+
+ /* do we want to add a mono option? */
+ if (audioCodecsSupportMono == 1) {
+ id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
+ [NSString stringWithCString: hb_audio_mixdowns[0].human_readable_name]
+ action: NULL keyEquivalent: @""];
+ [menuItem setTag: hb_audio_mixdowns[0].amixdown];
+ if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[0].amixdown;
+ maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[0].amixdown);
+ }
+
+ /* do we want to add a stereo option? */
+ /* offer stereo if we have a mono source and non-mono-supporting codecs, as otherwise we won't have a mixdown at all */
+ /* also offer stereo if we have a stereo-or-better source */
+ if (((channel_layout == A52_MONO || channel_layout == A52_CHANNEL1 || channel_layout == A52_CHANNEL2) && audioCodecsSupportMono == 0) ||
+ (channel_layout >= A52_STEREO && channel_layout != A52_CHANNEL1 && channel_layout != A52_CHANNEL2)) {
+ id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
+ [NSString stringWithCString: hb_audio_mixdowns[1].human_readable_name]
+ action: NULL keyEquivalent: @""];
+ [menuItem setTag: hb_audio_mixdowns[1].amixdown];
+ if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[1].amixdown;
+ maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[1].amixdown);
+ }
+
+ /* do we want to add a dolby surround (DPL1) option? */
+ if (channel_layout == A52_3F1R || channel_layout == A52_3F2R || channel_layout == A52_DOLBY) {
+ id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
+ [NSString stringWithCString: hb_audio_mixdowns[2].human_readable_name]
+ action: NULL keyEquivalent: @""];
+ [menuItem setTag: hb_audio_mixdowns[2].amixdown];
+ if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[2].amixdown;
+ maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[2].amixdown);
+ }
+
+ /* do we want to add a dolby pro logic 2 (DPL2) option? */
+ if (channel_layout == A52_3F2R) {
+ id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
+ [NSString stringWithCString: hb_audio_mixdowns[3].human_readable_name]
+ action: NULL keyEquivalent: @""];
+ [menuItem setTag: hb_audio_mixdowns[3].amixdown];
+ if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[3].amixdown;
+ maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[3].amixdown);
+ }
+
+ /* do we want to add a 6-channel discrete option? */
+ if (audioCodecsSupport6Ch == 1 && channel_layout == A52_3F2R && audio_has_lfe == A52_LFE) {
+ id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
+ [NSString stringWithCString: hb_audio_mixdowns[4].human_readable_name]
+ action: NULL keyEquivalent: @""];
+ [menuItem setTag: hb_audio_mixdowns[4].amixdown];
+ if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[4].amixdown;
+ maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[4].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 */
+ /* ultimately this should be a prefs option */
+ int useMixdown;
+
+ /* if we passed in a mixdown to use - in order to load a preset - then try and use it */
+ if (mixdownToUse > 0)
+ {
+ useMixdown = mixdownToUse;
+ }
+ else
+ {
+ useMixdown = HB_AMIXDOWN_DOLBYPLII;
+ }
+
+ /* if useMixdown > maxMixdownUsed, then use maxMixdownUsed */
+ if (useMixdown > maxMixdownUsed) useMixdown = maxMixdownUsed;
+
+ /* if useMixdown < minMixdownUsed, then use minMixdownUsed */
+ if (useMixdown < minMixdownUsed) useMixdown = minMixdownUsed;
+
+ /* select the (possibly-amended) preferred mixdown */
+ [mixdownPopUp selectItemWithTag: useMixdown];
+
+ /* lets call the AudioTrackMixdownChanged method here to determine appropriate bitrates, etc. */
+ [self AudioTrackMixdownChanged: NULL];
+ }
+
+ }
+
+ }
+
+ /* see if the new audio track choice will change the bitrate we need */
+ [self CalculateBitrate: sender];
+
+}
+- (IBAction) AudioTrackMixdownChanged: (id) sender
+{
+
+ /* find out what the currently-selected output audio codec is */
+ int format = [fDstFormatPopUp indexOfSelectedItem];
+ int codecs = [fDstCodecsPopUp indexOfSelectedItem];
+ int acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
+
+ /* storage variable for the min and max bitrate allowed for this codec */
+ int minbitrate;
+ int maxbitrate;
+
+ switch( acodec )
+ {
+ case HB_ACODEC_FAAC:
+ /* check if we have a 6ch discrete conversion in either audio track */
+ if ([[fAudTrack1MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH || [[fAudTrack2MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH)
+ {
+ /* FAAC is happy using our min bitrate of 32 kbps, even for 6ch */
+ minbitrate = 32;
+ /* If either mixdown popup includes 6-channel discrete, then allow up to 384 kbps */
+ maxbitrate = 384;
+ break;
+ }
+ else
+ {
+ /* FAAC is happy using our min bitrate of 32 kbps for stereo or mono */
+ minbitrate = 32;
+ /* FAAC won't honour anything more than 160 for stereo, so let's not offer it */
+ /* note: haven't dealt with mono separately here, FAAC will just use the max it can */
+ maxbitrate = 160;
+ break;
+ }
+
+ case HB_ACODEC_LAME:
+ /* Lame is happy using our min bitrate of 32 kbps */
+ minbitrate = 32;
+ /* Lame won't encode if the bitrate is higher than 320 kbps */
+ maxbitrate = 320;
+ break;
+
+ case HB_ACODEC_VORBIS:
+ /* Vorbis causes a crash if we use a bitrate below 48 kbps */
+ minbitrate = 48;
+ /* Vorbis can cope with 384 kbps quite happily, even for stereo */
+ maxbitrate = 384;
+ break;
+
+ default:
+ /* AC3 passthru disables the bitrate dropdown anyway, so we might as well just use the min and max bitrate */
+ minbitrate = 32;
+ maxbitrate = 384;
+
+ }
+
+ [fAudBitratePopUp removeAllItems];
+
+ for( int i = 0; i < hb_audio_bitrates_count; i++ )
+ {
+ if (hb_audio_bitrates[i].rate >= minbitrate && hb_audio_bitrates[i].rate <= maxbitrate)
+ {
+ /* add a new menuitem for this bitrate */
+ id<NSMenuItem> menuItem = [[fAudBitratePopUp menu] addItemWithTitle:
+ [NSString stringWithCString: hb_audio_bitrates[i].string]
+ action: NULL keyEquivalent: @""];
+ /* set its tag to be the actual bitrate as an integer, so we can retrieve it later */
+ [menuItem setTag: hb_audio_bitrates[i].rate];
+ }
+ }
+
+ /* select the default bitrate (but use 384 for 6-ch AAC) */
+ if ([[fAudTrack1MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH || [[fAudTrack2MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH)
+ {
+ [fAudBitratePopUp selectItemWithTag: 384];
+ }
+ else
+ {
+ [fAudBitratePopUp selectItemWithTag: hb_audio_bitrates[hb_audio_bitrates_default].rate];
+ }
+
+}
+/* lets set the picture size back to the max from right after title scan
+ Lets use an IBAction here as down the road we could always use a checkbox
+ in the gui to easily take the user back to max. Remember, the compiler
+ resolves IBActions down to -(void) during compile anyway */
+- (IBAction) RevertPictureSizeToMax: (id) sender
+{
+ hb_job_t * job = fTitle->job;
+ /* We use the output picture width and height
+ as calculated from libhb right after title is set
+ in TitlePopUpChanged */
+ job->width = PicOrigOutputWidth;
+ job->height = PicOrigOutputHeight;
+
+
+
+ [self CalculatePictureSizing: sender];
+ /* We call method method to change UI to reflect whether a preset is used or not*/
+ [self CustomSettingUsed: sender];
+}
+
+
+/* Get and Display Current Pic Settings in main window */
+- (IBAction) CalculatePictureSizing: (id) sender
+{
+
+
+ [fPicSettingWidth setStringValue: [NSString stringWithFormat:
+ @"%d", fTitle->job->width]];
+ [fPicSettingHeight setStringValue: [NSString stringWithFormat:
+ @"%d", fTitle->job->height]];
+ [fPicSettingARkeep setStringValue: [NSString stringWithFormat:
+ @"%d", fTitle->job->keep_ratio]];
+ [fPicSettingDeinterlace setStringValue: [NSString stringWithFormat:
+ @"%d", fTitle->job->deinterlace]];
+ [fPicSettingPAR setStringValue: [NSString stringWithFormat:
+ @"%d", fTitle->job->pixel_ratio]];
+
+ if (fTitle->job->pixel_ratio == 1)
+ {
+ int titlewidth = fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3];
+ int arpwidth = fTitle->job->pixel_aspect_width;
+ int arpheight = fTitle->job->pixel_aspect_height;
+ int displayparwidth = titlewidth * arpwidth / arpheight;
+ int displayparheight = fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1];
+ [fPicSettingHeight setStringValue: [NSString stringWithFormat:
+ @"%d", displayparheight]];
+ [fPicLabelPAROutp setStringValue: @"Anamorphic Output:"];
+ [fPicLabelPAROutputX setStringValue: @"x"];
+ [fPicSettingPARWidth setStringValue: [NSString stringWithFormat:
+ @"%d", displayparwidth]];
+ [fPicSettingPARHeight setStringValue: [NSString stringWithFormat:
+ @"%d", displayparheight]];
+
+ fTitle->job->keep_ratio = 0;
+ }
+ else
+ {
+ [fPicLabelPAROutp setStringValue: @""];
+ [fPicLabelPAROutputX setStringValue: @""];
+ [fPicSettingPARWidth setStringValue: @""];
+ [fPicSettingPARHeight setStringValue: @""];
+ }
+
+ /* Set ON/Off values for the deinterlace/keep aspect ratio according to boolean */
+ if (fTitle->job->keep_ratio > 0)
+ {
+ [fPicSettingARkeepDsply setStringValue: @"On"];
+ }
+ else
+ {
+ [fPicSettingARkeepDsply setStringValue: @"Off"];
+ }
+ if (fTitle->job->deinterlace > 0)
+ {
+ [fPicSettingDeinterlaceDsply setStringValue: @"On"];
+ }
+ else
+ {
+ [fPicSettingDeinterlaceDsply setStringValue: @"Off"];
+ }
+ if (fTitle->job->pixel_ratio > 0)
+ {
+ [fPicSettingPARDsply setStringValue: @"On"];
+ }
+ else
+ {
+ [fPicSettingPARDsply setStringValue: @"Off"];
+ }
+ /* below will trigger the preset, if selected, to be
+ changed to "Custom". Lets comment out for now until
+ we figure out a way to determine if the picture values
+ changed modify the preset values */
+ //[self CustomSettingUsed: sender];
}
- (IBAction) CalculateBitrate: (id) sender
[fVidBitrateField setIntValue: hb_calc_bitrate( job,
[fVidTargetSizeField intValue] )];
+
+
+}
+
+/* Method to determine if we should change the UI
+To reflect whether or not a Preset is being used or if
+the user is using "Custom" settings by determining the sender*/
+- (IBAction) CustomSettingUsed: (id) sender
+{
+ if ([sender stringValue] != NULL)
+ {
+ /* Deselect the currently selected Preset if there is one*/
+ [tableView deselectRow:[tableView selectedRow]];
+ /* Change UI to show "Custom" settings are being used */
+ [fPresetSelectedDisplay setStringValue: @"Custom"];
+ /* Empty the field to display custom x264 preset options*/
+ [fDisplayX264Options setStringValue: @""];
+ curUserPresetChosenNum = nil;
+ /* If we have MP4, AVC H.264 and x264 Main then we look to see
+ if there are any x264 options from the preferences to use */
+ if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [fDstCodecsPopUp indexOfSelectedItem] == 1)
+ {
+ /* Lets check to see if the user wants them displayed from the preferences */
+ if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefAdvancedx264FlagsShow"] > 0)
+ {
+ [fDisplayX264Options setStringValue: [NSString stringWithFormat:[[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"]]];
+ }
+ }
+
+ }
+}
+
+
+ /* We use this method to recreate new, updated factory
+ presets */
+- (IBAction)AddFactoryPresets:(id)sender
+{
+ /* First, we delete any existing built in presets */
+ [self DeleteFactoryPresets: sender];
+ /* Then, we re-create new built in presets programmatically CreatePSPPreset*/
+ [UserPresets addObject:[self CreateIpodPreset]];
+ [UserPresets addObject:[self CreateAppleTVPreset]];
+ [UserPresets addObject:[self CreatePSThreePreset]];
+ [UserPresets addObject:[self CreatePSPPreset]];
+ [self AddPreset];
+}
+- (IBAction)DeleteFactoryPresets:(id)sender
+{
+ //int status;
+ NSEnumerator *enumerator = [UserPresets objectEnumerator];
+ id tempObject;
+
+ //NSNumber *index;
+ NSMutableArray *tempArray;
+
+
+ tempArray = [NSMutableArray array];
+ /* we look here to see if the preset is we move on to the next one */
+ while ( tempObject = [enumerator nextObject] )
+ {
+ /* if the preset is "Factory" then we put it in the array of
+ presets to delete */
+ if ([[tempObject objectForKey:@"Type"] intValue] == 0)
+ {
+ [tempArray addObject:tempObject];
+ }
+ }
+
+ [UserPresets removeObjectsInArray:tempArray];
+ [tableView reloadData];
+ [self savePreset];
+
+}
+
+- (IBAction) ShowAddPresetPanel: (id) sender
+{
+ /* Deselect the currently selected Preset if there is one*/
+ [tableView deselectRow:[tableView selectedRow]];
+ /* If we have MP4, AVC H.264 and Main then we enable the x264 Options field for the
+ Add Preset window we are about to open. We do this before we actually open the panel,
+ as doing it after causes it to stick from the last selection for some reason. */
+ if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [fDstCodecsPopUp indexOfSelectedItem] == 1)
+ {
+ [fPresetNewX264Opt setEditable: YES];
+ [fPresetNewX264OptLabel setEnabled: YES];
+ }
+ else
+ {
+ [fPresetNewX264Opt setEditable: NO];
+ [fPresetNewX264OptLabel setEnabled: NO];
+ }
+ /* Erase info from the input fields */
+ [fPresetNewName setStringValue: @""];
+ [fPresetNewX264Opt setStringValue:@""];
+ /* Show the panel */
+ [NSApp beginSheet: fAddPresetPanel modalForWindow: fWindow
+ modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
+ [NSApp runModalForWindow: fAddPresetPanel];
+ [NSApp endSheet: fAddPresetPanel];
+ [fAddPresetPanel orderOut: self];
+
+
+}
+- (IBAction) CloseAddPresetPanel: (id) sender
+{
+ [NSApp stopModal];
+}
+
+
+- (IBAction)AddUserPreset:(id)sender
+{
+
+ /* Here we create a custom user preset */
+ [UserPresets addObject:[self CreatePreset]];
+ /* Erase info from the input fields */
+ [fPresetNewName setStringValue: @""];
+ [fPresetNewX264Opt setStringValue:@""];
+ /* We stop the modal window for the new preset */
+ [NSApp stopModal];
+ [self AddPreset];
+
+
+}
+- (void)AddPreset
+{
+
+
+ /* We Sort the Presets By Factory or Custom */
+ NSSortDescriptor * presetTypeDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"Type"
+ ascending:YES] autorelease];
+ /* We Sort the Presets Alphabetically by name */
+ NSSortDescriptor * presetNameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"PresetName"
+ ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease];
+ NSArray *sortDescriptors=[NSArray arrayWithObjects:presetTypeDescriptor,presetNameDescriptor,nil];
+ NSArray *sortedArray=[UserPresets sortedArrayUsingDescriptors:sortDescriptors];
+ [UserPresets setArray:sortedArray];
+
+
+ /* We Reload the New Table data for presets */
+ [tableView reloadData];
+ /* We save all of the preset data here */
+ [self savePreset];
+}
+
+- (IBAction)InsertPreset:(id)sender
+{
+ int index = [tableView selectedRow];
+ [UserPresets insertObject:[self CreatePreset] atIndex:index];
+ [tableView reloadData];
+ [self savePreset];
+}
+
+- (NSDictionary *)CreatePreset
+{
+ NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
+ /* Get the New Preset Name from the field in the AddPresetPanel */
+ [preset setObject:[fPresetNewName stringValue] forKey:@"PresetName"];
+ /*Set whether or not this is a user preset or factory 0 is factory, 1 is user*/
+ [preset setObject:[NSNumber numberWithInt:1] forKey:@"Type"];
+ /*Set whether or not this is default, at creation set to 0*/
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
+ /*Get the whether or not to apply pic settings in the AddPresetPanel*/
+ [preset setObject:[NSNumber numberWithInt:[fPresetNewPicSettingsApply state]] forKey:@"UsesPictureSettings"];
+ /* File Format */
+ [preset setObject:[fDstFormatPopUp titleOfSelectedItem] forKey:@"FileFormat"];
+ /* Chapter Markers fCreateChapterMarkers*/
+ [preset setObject:[NSNumber numberWithInt:[fCreateChapterMarkers state]] forKey:@"ChapterMarkers"];
+ /* Codecs */
+ [preset setObject:[fDstCodecsPopUp titleOfSelectedItem] forKey:@"FileCodecs"];
+ /* Video encoder */
+ [preset setObject:[fVidEncoderPopUp titleOfSelectedItem] forKey:@"VideoEncoder"];
+ /* x264 Option String */
+ [preset setObject:[fPresetNewX264Opt stringValue] forKey:@"x264Option"];
+
+ [preset setObject:[NSNumber numberWithInt:[fVidQualityMatrix selectedRow]] forKey:@"VideoQualityType"];
+ [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
+ [preset setObject:[fVidBitrateField stringValue] forKey:@"VideoAvgBitrate"];
+ [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
+
+ /* Video framerate */
+ [preset setObject:[fVidRatePopUp titleOfSelectedItem] forKey:@"VideoFramerate"];
+ /* GrayScale */
+ [preset setObject:[NSNumber numberWithInt:[fVidGrayscaleCheck state]] forKey:@"VideoGrayScale"];
+ /* 2 Pass Encoding */
+ [preset setObject:[NSNumber numberWithInt:[fVidTwoPassCheck state]] forKey:@"VideoTwoPass"];
+
+ /*Picture Settings*/
+ hb_job_t * job = fTitle->job;
+ /* Basic Picture Settings */
+ /* Use Max Picture settings for whatever the dvd is.*/
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesMaxPictureSettings"];
+ [preset setObject:[NSNumber numberWithInt:fTitle->job->width] forKey:@"PictureWidth"];
+ [preset setObject:[NSNumber numberWithInt:fTitle->job->height] forKey:@"PictureHeight"];
+ [preset setObject:[NSNumber numberWithInt:fTitle->job->keep_ratio] forKey:@"PictureKeepRatio"];
+ [preset setObject:[NSNumber numberWithInt:fTitle->job->deinterlace] forKey:@"PictureDeinterlace"];
+ [preset setObject:[NSNumber numberWithInt:fTitle->job->pixel_ratio] forKey:@"PicturePAR"];
+ /* Set crop settings here */
+ /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
+ [preset setObject:[NSNumber numberWithInt:job->crop[0]] forKey:@"PictureTopCrop"];
+ [preset setObject:[NSNumber numberWithInt:job->crop[1]] forKey:@"PictureBottomCrop"];
+ [preset setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"];
+ [preset setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"];
+
+ /*Audio*/
+ /* Audio Sample Rate*/
+ [preset setObject:[fAudRatePopUp titleOfSelectedItem] forKey:@"AudioSampleRate"];
+ /* Audio Bitrate Rate*/
+ [preset setObject:[fAudBitratePopUp titleOfSelectedItem] forKey:@"AudioBitRate"];
+ /* Subtitles*/
+ [preset setObject:[fSubPopUp titleOfSelectedItem] forKey:@"Subtitles"];
+
+
+ [preset autorelease];
+ return preset;
+
+}
+
+- (NSDictionary *)CreateIpodPreset
+{
+ NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
+ /* Get the New Preset Name from the field in the AddPresetPanel */
+ [preset setObject:@"HB-iPod" forKey:@"PresetName"];
+ /*Set whether or not this is a user preset or factory 0 is factory, 1 is user*/
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
+ /*Set whether or not this is default, at creation set to 0*/
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
+ /*Get the whether or not to apply pic settings in the AddPresetPanel*/
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesPictureSettings"];
+ /* File Format */
+ [preset setObject:@"MP4 file" forKey:@"FileFormat"];
+ /* Chapter Markers*/
+ [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
+ /* Codecs */
+ [preset setObject:@"AVC/H.264 Video / AAC Audio" forKey:@"FileCodecs"];
+ /* Video encoder */
+ [preset setObject:@"x264 (h.264 iPod)" forKey:@"VideoEncoder"];
+ /* x264 Option String */
+ [preset setObject:@"frameref=1:bframes=0:nofast_pskip:subq=6:partitions=p8x8,p8x4,p4x8,i4x4:qcomp=0:me=umh:nodct_decimate" forKey:@"x264Option"];
+ /* Video quality */
+ [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
+ [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
+ [preset setObject:@"1500" forKey:@"VideoAvgBitrate"];
+ [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
+
+ /* Video framerate */
+ [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
+ /* GrayScale */
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
+ /* 2 Pass Encoding */
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
+
+ /*Picture Settings*/
+ //hb_job_t * job = fTitle->job;
+ /* Basic Picture Settings */
+ /* Use Max Picture settings for whatever the dvd is.*/
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesMaxPictureSettings"];
+ //[preset setObject:[NSNumber numberWithInt:fTitle->job->width] forKey:@"PictureWidth"];
+ //[preset setObject:[NSNumber numberWithInt:fTitle->job->height] forKey:@"PictureHeight"];
+ //[preset setObject:[NSNumber numberWithInt:fTitle->job->keep_ratio] forKey:@"PictureKeepRatio"];
+ //[preset setObject:[NSNumber numberWithInt:fTitle->job->deinterlace] forKey:@"PictureDeinterlace"];
+ //[preset setObject:[NSNumber numberWithInt:fTitle->job->pixel_ratio] forKey:@"PicturePAR"];
+ /* Set crop settings here */
+ /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
+ //[preset setObject:[NSNumber numberWithInt:job->crop[0]] forKey:@"PictureTopCrop"];
+ //[preset setObject:[NSNumber numberWithInt:job->crop[1]] forKey:@"PictureBottomCrop"];
+ //[preset setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"];
+ //[preset setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"];
+
+ /*Audio*/
+ /* Audio Sample Rate*/
+ [preset setObject:@"48" forKey:@"AudioSampleRate"];
+ /* Audio Bitrate Rate*/
+ [preset setObject:@"160" forKey:@"AudioBitRate"];
+ /* Subtitles*/
+ [preset setObject:@"None" forKey:@"Subtitles"];
+
+
+ [preset autorelease];
+ return preset;
+
+}
+
+- (NSDictionary *)CreateAppleTVPreset
+{
+ NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
+ /* Get the New Preset Name from the field in the AddPresetPanel */
+ [preset setObject:@"HB-AppleTV" forKey:@"PresetName"];
+ /*Set whether or not this is a user preset where 0 is factory, 1 is user*/
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
+ /*Set whether or not this is default, at creation set to 0*/
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
+ /*Get the whether or not to apply pic settings in the AddPresetPanel*/
+ [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesPictureSettings"];
+ /* File Format */
+ [preset setObject:@"MP4 file" forKey:@"FileFormat"];
+ /* Chapter Markers*/
+ [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
+ /* Codecs */
+ [preset setObject:@"AVC/H.264 Video / AAC Audio" forKey:@"FileCodecs"];
+ /* Video encoder */
+ [preset setObject:@"x264 (h.264 Main)" forKey:@"VideoEncoder"];
+ /* x264 Option String (We can use this to tweak the appleTV output)*/
+ [preset setObject:@"bframes=3:ref=1:subme=5:me=umh:no-fast-pskip=1:no-dct-decimate=1:trellis=2" forKey:@"x264Option"];
+ /* Video quality */
+ [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
+ [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
+ [preset setObject:@"2500" forKey:@"VideoAvgBitrate"];
+ [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
+
+ /* Video framerate */
+ [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
+ /* GrayScale */
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
+ /* 2 Pass Encoding */
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
+
+ /*Picture Settings*/
+ /* For AppleTV we only want to retain UsesMaxPictureSettings
+ which depend on the source dvd picture settings, so we don't
+ record the current dvd's picture info since it will vary from
+ source to source*/
+ //hb_job_t * job = fTitle->job;
+ //hb_job_t * job = title->job;
+ /* Basic Picture Settings */
+ /* Use Max Picture settings for whatever the dvd is.*/
+ [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesMaxPictureSettings"];
+ //[preset setObject:[NSNumber numberWithInt:PicOrigOutputWidth] forKey:@"PictureWidth"];
+ //[preset setObject:[NSNumber numberWithInt:PicOrigOutputHeight] forKey:@"PictureHeight"];
+ //[preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureKeepRatio"];
+ //[preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
+ [preset setObject:[NSNumber numberWithInt:1] forKey:@"PicturePAR"];
+ /* Set crop settings here */
+ /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
+ //[preset setObject:[NSNumber numberWithInt:job->crop[0]] forKey:@"PictureTopCrop"];
+ //[preset setObject:[NSNumber numberWithInt:job->crop[1]] forKey:@"PictureBottomCrop"];
+ //[preset setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"];
+ //[preset setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"];
+
+ /*Audio*/
+ /* Audio Sample Rate*/
+ [preset setObject:@"48" forKey:@"AudioSampleRate"];
+ /* Audio Bitrate Rate*/
+ [preset setObject:@"160" forKey:@"AudioBitRate"];
+ /* Subtitles*/
+ [preset setObject:@"None" forKey:@"Subtitles"];
+
+
+ [preset autorelease];
+ return preset;
+
}
+- (NSDictionary *)CreatePSThreePreset
+{
+ NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
+ /* Get the New Preset Name from the field in the AddPresetPanel */
+ [preset setObject:@"HB-PS3" forKey:@"PresetName"];
+ /*Set whether or not this is a user preset where 0 is factory, 1 is user*/
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
+ /*Set whether or not this is default, at creation set to 0*/
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
+ /*Get the whether or not to apply pic settings in the AddPresetPanel*/
+ [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesPictureSettings"];
+ /* File Format */
+ [preset setObject:@"MP4 file" forKey:@"FileFormat"];
+ /* Chapter Markers*/
+ [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
+ /* Codecs */
+ [preset setObject:@"AVC/H.264 Video / AAC Audio" forKey:@"FileCodecs"];
+ /* Video encoder */
+ [preset setObject:@"x264 (h.264 Main)" forKey:@"VideoEncoder"];
+ /* x264 Option String (We can use this to tweak the appleTV output)*/
+ [preset setObject:@"level=41" forKey:@"x264Option"];
+ /* Video quality */
+ [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
+ [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
+ [preset setObject:@"2500" forKey:@"VideoAvgBitrate"];
+ [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
+
+ /* Video framerate */
+ [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
+ /* GrayScale */
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
+ /* 2 Pass Encoding */
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
+
+ /*Picture Settings*/
+ /* For PS3 we only want to retain UsesMaxPictureSettings
+ which depend on the source dvd picture settings, so we don't
+ record the current dvd's picture info since it will vary from
+ source to source*/
+ /* Use Max Picture settings for whatever the dvd is.*/
+ [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesMaxPictureSettings"];
+ //[preset setObject:[NSNumber numberWithInt:PicOrigOutputWidth] forKey:@"PictureWidth"];
+ //[preset setObject:[NSNumber numberWithInt:PicOrigOutputHeight] forKey:@"PictureHeight"];
+ //[preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureKeepRatio"];
+ //[preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
+ [preset setObject:[NSNumber numberWithInt:1] forKey:@"PicturePAR"];
+ /* Set crop settings here */
+ /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
+ //[preset setObject:[NSNumber numberWithInt:job->crop[0]] forKey:@"PictureTopCrop"];
+ //[preset setObject:[NSNumber numberWithInt:job->crop[1]] forKey:@"PictureBottomCrop"];
+ //[preset setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"];
+ //[preset setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"];
+
+ /*Audio*/
+ /* Audio Sample Rate*/
+ [preset setObject:@"48" forKey:@"AudioSampleRate"];
+ /* Audio Bitrate Rate*/
+ [preset setObject:@"160" forKey:@"AudioBitRate"];
+ /* Subtitles*/
+ [preset setObject:@"None" forKey:@"Subtitles"];
+
+
+ [preset autorelease];
+ return preset;
+
+}
+- (NSDictionary *)CreatePSPPreset
+{
+ NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
+ /* Get the New Preset Name from the field in the AddPresetPanel */
+ [preset setObject:@"HB-PSP" forKey:@"PresetName"];
+ /*Set whether or not this is a user preset where 0 is factory, 1 is user*/
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
+ /*Set whether or not this is default, at creation set to 0*/
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
+ /*Get the whether or not to apply pic settings in the AddPresetPanel*/
+ [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesPictureSettings"];
+ /* File Format */
+ [preset setObject:@"MP4 file" forKey:@"FileFormat"];
+ /* Chapter Markers*/
+ [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
+ /* Codecs */
+ [preset setObject:@"MPEG-4 Video / AAC Audio" forKey:@"FileCodecs"];
+ /* Video encoder */
+ [preset setObject:@"FFmpeg" forKey:@"VideoEncoder"];
+ /* x264 Option String (We can use this to tweak the appleTV output)*/
+ [preset setObject:@"" forKey:@"x264Option"];
+ /* Video quality */
+ [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
+ [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
+ [preset setObject:@"1024" forKey:@"VideoAvgBitrate"];
+ [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
+
+ /* Video framerate */
+ [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
+ /* GrayScale */
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
+ /* 2 Pass Encoding */
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
+
+ /*Picture Settings*/
+ /* For PS3 we only want to retain UsesMaxPictureSettings
+ which depend on the source dvd picture settings, so we don't
+ record the current dvd's picture info since it will vary from
+ source to source*/
+ /* Use Max Picture settings for whatever the dvd is.*/
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesMaxPictureSettings"];
+ [preset setObject:@"368" forKey:@"PictureWidth"];
+ [preset setObject:@"208" forKey:@"PictureHeight"];
+ [preset setObject:[NSNumber numberWithInt:1] forKey:@"PictureKeepRatio"];
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"PicturePAR"];
+ /* Set crop settings here */
+ /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
+ //[preset setObject:[NSNumber numberWithInt:job->crop[0]] forKey:@"PictureTopCrop"];
+ //[preset setObject:[NSNumber numberWithInt:job->crop[1]] forKey:@"PictureBottomCrop"];
+ //[preset setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"];
+ //[preset setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"];
+
+ /*Audio*/
+ /* Audio Sample Rate*/
+ [preset setObject:@"48" forKey:@"AudioSampleRate"];
+ /* Audio Bitrate Rate*/
+ [preset setObject:@"128" forKey:@"AudioBitRate"];
+ /* Subtitles*/
+ [preset setObject:@"None" forKey:@"Subtitles"];
+
+
+ [preset autorelease];
+ return preset;
+
+}
+
+
+- (IBAction)DeletePreset:(id)sender
+{
+ int status;
+ NSEnumerator *enumerator;
+ NSNumber *index;
+ NSMutableArray *tempArray;
+ id tempObject;
+
+ if ( [tableView numberOfSelectedRows] == 0 )
+ return;
+ /* Alert user before deleting preset */
+ /* Comment out for now, tie to user pref eventually */
+
+ //NSBeep();
+ status = NSRunAlertPanel(@"Warning!", @"Are you sure that you want to delete the selected preset?", @"OK", @"Cancel", nil);
+
+ if ( status == NSAlertDefaultReturn ) {
+ enumerator = [tableView selectedRowEnumerator];
+ tempArray = [NSMutableArray array];
+
+ while ( (index = [enumerator nextObject]) ) {
+ tempObject = [UserPresets objectAtIndex:[index intValue]];
+ [tempArray addObject:tempObject];
+ }
+
+ [UserPresets removeObjectsInArray:tempArray];
+ [tableView reloadData];
+ [self savePreset];
+ }
+}
+- (IBAction)tableViewSelected:(id)sender
+{
+ /* Since we cannot disable the presets tableView in terms of clickability
+ we will use the enabled state of the add presets button to determine whether
+ or not clicking on a preset will do anything */
+ if ([fPresetsAdd isEnabled])
+ {
+
+ /* we get the chosen preset from the UserPresets array */
+ chosenPreset = [UserPresets objectAtIndex:[sender selectedRow]];
+ curUserPresetChosenNum = [sender selectedRow];
+ /* we set the preset display field in main window here */
+ [fPresetSelectedDisplay setStringValue: [NSString stringWithFormat: @"%@",[chosenPreset valueForKey:@"PresetName"]]];
+ /* File Format */
+ [fDstFormatPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"FileFormat"]]];
+ [self FormatPopUpChanged: NULL];
+ /* Chapter Markers*/
+ [fCreateChapterMarkers setState:[[chosenPreset objectForKey:@"ChapterMarkers"] intValue]];
+ /* Codecs */
+ [fDstCodecsPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"FileCodecs"]]];
+ [self CodecsPopUpChanged: NULL];
+ /* Video encoder */
+ [fVidEncoderPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoEncoder"]]];
+
+ /* We can show the preset options here in the gui if we want to
+ so we check to see it the user has specified it in the prefs */
+ if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefAdvancedx264FlagsShow"] > 0)
+ {
+ [fDisplayX264Options setStringValue: [NSString stringWithFormat:[chosenPreset valueForKey:@"x264Option"]]];
+ }
+
+ /* Lets run through the following functions to get variables set there */
+ [self EncoderPopUpChanged: NULL];
+ [self CalculateBitrate: NULL];
+
+ /* Video quality */
+ [fVidQualityMatrix selectCellAtRow:[[chosenPreset objectForKey:@"VideoQualityType"] intValue] column:0];
+
+ [fVidTargetSizeField setStringValue: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoTargetSize"]]];
+ [fVidBitrateField setStringValue: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoAvgBitrate"]]];
+
+ [fVidQualitySlider setFloatValue: [[chosenPreset valueForKey:@"VideoQualitySlider"] floatValue]];
+ [self VideoMatrixChanged: NULL];
+
+ /* Video framerate */
+ [fVidRatePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoFramerate"]]];
+
+ /* GrayScale */
+ [fVidGrayscaleCheck setState:[[chosenPreset objectForKey:@"VideoGrayScale"] intValue]];
+
+ /* 2 Pass Encoding */
+ [fVidTwoPassCheck setState:[[chosenPreset objectForKey:@"VideoTwoPass"] intValue]];
+
+
+ /*Audio*/
+
+ /* Audio Sample Rate*/
+ [fAudRatePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"AudioSampleRate"]]];
+ /* Audio Bitrate Rate*/
+ [fAudBitratePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"AudioBitRate"]]];
+ /*Subtitles*/
+ [fSubPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"Subtitles"]]];
+
+ /* Picture Settings */
+ /* Look to see if we apply these here in objectForKey:@"UsesPictureSettings"] */
+ if ([[chosenPreset objectForKey:@"UsesPictureSettings"] intValue] == 1)
+ {
+ hb_job_t * job = fTitle->job;
+ /* Check to see if we should use the max picture setting for the current title*/
+ if ([[chosenPreset objectForKey:@"UsesMaxPictureSettings"] intValue] == 1)
+ {
+ /* Use Max Picture settings for whatever the dvd is.*/
+ [self RevertPictureSizeToMax: NULL];
+ job->keep_ratio = [[chosenPreset objectForKey:@"PictureKeepRatio"] intValue];
+ if (job->keep_ratio == 1)
+ {
+ hb_fix_aspect( job, HB_KEEP_WIDTH );
+ }
+ job->pixel_ratio = [[chosenPreset objectForKey:@"PicturePAR"] intValue];
+ }
+ else
+ {
+ job->width = [[chosenPreset objectForKey:@"PictureWidth"] intValue];
+ job->height = [[chosenPreset objectForKey:@"PictureHeight"] intValue];
+ job->keep_ratio = [[chosenPreset objectForKey:@"PictureKeepRatio"] intValue];
+ if (job->keep_ratio == 1)
+ {
+ hb_fix_aspect( job, HB_KEEP_WIDTH );
+ }
+ job->pixel_ratio = [[chosenPreset objectForKey:@"PicturePAR"] intValue];
+ job->crop[0] = [[chosenPreset objectForKey:@"PictureTopCrop"] intValue];
+ job->crop[1] = [[chosenPreset objectForKey:@"PictureBottomCrop"] intValue];
+ job->crop[2] = [[chosenPreset objectForKey:@"PictureLeftCrop"] intValue];
+ job->crop[3] = [[chosenPreset objectForKey:@"PictureRightCrop"] intValue];
+ }
+ [self CalculatePictureSizing: NULL];
+ }
+
+
+
+
+}
+}
+
+
+
+- (int)numberOfRowsInTableView:(NSTableView *)aTableView
+{
+ return [UserPresets count];
+}
+
+/* we use this to determine display characteristics for
+each table cell based on content currently only used to
+show the built in presets in a blue font. */
+- (void)tableView:(NSTableView *)aTableView
+ willDisplayCell:(id)aCell
+ forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
+{
+ NSDictionary *userPresetDict = [UserPresets objectAtIndex:rowIndex];
+ if ([[userPresetDict objectForKey:@"Type"] intValue] == 0)
+ {
+ [aCell setTextColor:[NSColor blueColor]];
+ }
+ else
+ {
+ [aCell setTextColor:[NSColor blackColor]];
+ }
+
+}
+
+- (id)tableView:(NSTableView *)aTableView
+ objectValueForTableColumn:(NSTableColumn *)aTableColumn
+ row:(int)rowIndex
+{
+id theRecord, theValue;
+
+ theRecord = [UserPresets objectAtIndex:rowIndex];
+ theValue = [theRecord objectForKey:[aTableColumn identifier]];
+ return theValue;
+}
+
+// NSTableDataSource method that we implement to edit values directly in the table...
+- (void)tableView:(NSTableView *)aTableView
+ setObjectValue:(id)anObject
+ forTableColumn:(NSTableColumn *)aTableColumn
+ row:(int)rowIndex
+{
+ id theRecord;
+
+ theRecord = [UserPresets objectAtIndex:rowIndex];
+ [theRecord setObject:anObject forKey:@"PresetName"];
+ /* We Sort the Presets By Factory or Custom */
+ NSSortDescriptor * presetTypeDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"Type"
+ ascending:YES] autorelease];
+ /* We Sort the Presets Alphabetically by name */
+ NSSortDescriptor * presetNameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"PresetName"
+ ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease];
+ NSArray *sortDescriptors=[NSArray arrayWithObjects:presetTypeDescriptor,presetNameDescriptor,nil];
+ NSArray *sortedArray=[UserPresets sortedArrayUsingDescriptors:sortDescriptors];
+ [UserPresets setArray:sortedArray];
+ /* We Reload the New Table data for presets */
+ [tableView reloadData];
+ /* We save all of the preset data here */
+ [self savePreset];
+}
+
+
+- (void)savePreset
+{
+ [UserPresets writeToFile:UserPresetsFile atomically:YES];
+
+}
+
+
+
- (void) controlTextDidBeginEditing: (NSNotification *) notification
{
[self CalculateBitrate: NULL];
[[NSWorkspace sharedWorkspace] openURL: [NSURL
URLWithString:@"http://handbrake.m0k.org/forum/"]];
}
+- (IBAction) OpenUserGuide: (id) sender
+{
+ [[NSWorkspace sharedWorkspace] openURL: [NSURL
+ URLWithString:@"http://handbrake.m0k.org/trac/wiki/HandBrakeGuide"]];
+}
+
@end