/* HBAdvancedController
This file is part of the HandBrake source code.
Homepage: .
It may be used under the terms of the GNU General Public License. */
#import "HBAdvancedController.h"
@implementation HBAdvancedController
- (id)init
{
[super init];
[self loadMyNibFile];
return self;
}
- (void) setView: (NSBox *) box
{
fOptionsBox = box;
[fOptionsBox setContentView:fX264optView];
}
- (BOOL) loadMyNibFile
{
if(![NSBundle loadNibNamed:@"AdvancedView" owner:self])
{
NSLog(@"Warning! Could not load myNib file.\n");
return NO;
}
return YES;
}
- (NSString *) optionsString
{
return [fDisplayX264Options stringValue];
}
- (void) setOptions: (NSString *)string
{
[fDisplayX264Options setStringValue:string];
[self X264AdvancedOptionsSet:nil];
}
- (void) setHidden: (BOOL) hide
{
if(hide)
{
[fOptionsBox setContentView:fEmptyView];
[fX264optViewTitleLabel setStringValue: @"Only Used With The x264 (H.264) Codec"];
}
else
{
[fOptionsBox setContentView:fX264optView];
[fX264optViewTitleLabel setStringValue: @""];
}
return;
}
- (void) enableUI: (bool) b
{
unsigned i;
NSControl * controls[] =
{ fX264optViewTitleLabel,fDisplayX264Options,fDisplayX264OptionsLabel,fX264optBframesLabel,
fX264optBframesPopUp,fX264optRefLabel,fX264optRefPopUp,fX264optNfpskipLabel,fX264optNfpskipSwitch,
fX264optNodctdcmtLabel,fX264optNodctdcmtSwitch,fX264optSubmeLabel,fX264optSubmePopUp,
fX264optTrellisLabel,fX264optTrellisPopUp,fX264optMixedRefsLabel,fX264optMixedRefsSwitch,
fX264optMotionEstLabel,fX264optMotionEstPopUp,fX264optMERangeLabel,fX264optMERangePopUp,
fX264optWeightBLabel,fX264optWeightBSwitch, fX264optBPyramidLabel,fX264optBPyramidSwitch,
fX264optDirectPredLabel,fX264optDirectPredPopUp,fX264optDeblockLabel,fX264optAnalyseLabel,
fX264optAnalysePopUp,fX264opt8x8dctLabel,fX264opt8x8dctSwitch,fX264optCabacLabel,fX264optCabacSwitch,
fX264optAlphaDeblockPopUp,fX264optBetaDeblockPopUp, fX264optPsyRDSlider, fX264optPsyRDLabel, fX264optPsyTrellisSlider, fX264optPsyTrellisLabel, fX264optBAdaptPopUp, fX264optBAdaptLabel };
for( i = 0; i < sizeof( controls ) / sizeof( NSControl * ); i++ )
{
if( [[controls[i] className] isEqualToString: @"NSTextField"] )
{
NSTextField * tf = (NSTextField *) controls[i];
if( ![tf isBezeled] )
{
[tf setTextColor: b ? [NSColor controlTextColor] :
[NSColor disabledControlTextColor]];
continue;
}
}
[controls[i] setEnabled: b];
}
[fX264optView setWantsLayer:YES];
}
- (void)dealloc
{
[super dealloc];
}
/**
* Populates the option widgets
*/
- (IBAction) X264AdvancedOptionsSet: (id) sender
{
/*Set opt widget values here*/
/*B-Frames fX264optBframesPopUp*/
int i;
[fX264optBframesPopUp removeAllItems];
[fX264optBframesPopUp addItemWithTitle:@"Default (0)"];
for (i=0; i<17;i++)
{
[fX264optBframesPopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
}
/*Reference Frames fX264optRefPopUp*/
[fX264optRefPopUp removeAllItems];
[fX264optRefPopUp addItemWithTitle:@"Default (1)"];
for (i=0; i<17;i++)
{
[fX264optRefPopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
}
/*No Fast P-Skip fX264optNfpskipSwitch BOOLEAN*/
[fX264optNfpskipSwitch setState:0];
/*No Dict Decimate fX264optNodctdcmtSwitch BOOLEAN*/
[fX264optNodctdcmtSwitch setState:0];
/*Sub Me fX264optSubmePopUp*/
[fX264optSubmePopUp removeAllItems];
[fX264optSubmePopUp addItemWithTitle:@"Default (6)"];
for (i=0; i<10;i++)
{
[fX264optSubmePopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
}
/*Trellis fX264optTrellisPopUp*/
[fX264optTrellisPopUp removeAllItems];
[fX264optTrellisPopUp addItemWithTitle:@"Default (0)"];
for (i=0; i<3;i++)
{
[fX264optTrellisPopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
}
[fX264optTrellisPopUp setWantsLayer:YES];
/*Mixed-references fX264optMixedRefsSwitch BOOLEAN*/
[fX264optMixedRefsSwitch setState:0];
[fX264optMixedRefsSwitch setWantsLayer:YES];
/*Motion Estimation fX264optMotionEstPopUp*/
[fX264optMotionEstPopUp removeAllItems];
[fX264optMotionEstPopUp addItemWithTitle:@"Default (Hexagon)"];
[fX264optMotionEstPopUp addItemWithTitle:@"Diamond"];
[fX264optMotionEstPopUp addItemWithTitle:@"Hexagon"];
[fX264optMotionEstPopUp addItemWithTitle:@"Uneven Multi-Hexagon"];
[fX264optMotionEstPopUp addItemWithTitle:@"Exhaustive"];
[fX264optMotionEstPopUp addItemWithTitle:@"Transformed Exhaustive"];
/*Motion Estimation range fX264optMERangePopUp*/
[fX264optMERangePopUp removeAllItems];
[fX264optMERangePopUp addItemWithTitle:@"Default (16)"];
for (i=4; i<65;i++)
{
[fX264optMERangePopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
}
/*Weighted B-Frame Prediction fX264optWeightBSwitch BOOLEAN*/
[fX264optWeightBSwitch setState:0];
[fX264optWeightBSwitch setWantsLayer:YES];
/*B-frame Pyramids fX264optBPyramidSwitch BOOLEAN*/
[fX264optBPyramidSwitch setState:0];
[fX264optBPyramidSwitch setWantsLayer:YES];
/*Direct B-Frame Prediction Mode fX264optDirectPredPopUp*/
[fX264optDirectPredPopUp removeAllItems];
[fX264optDirectPredPopUp addItemWithTitle:@"Default (Spatial)"];
[fX264optDirectPredPopUp addItemWithTitle:@"None"];
[fX264optDirectPredPopUp addItemWithTitle:@"Spatial"];
[fX264optDirectPredPopUp addItemWithTitle:@"Temporal"];
[fX264optDirectPredPopUp addItemWithTitle:@"Automatic"];
[fX264optDirectPredPopUp setWantsLayer:YES];
/* Adaptive B-Frames Mode fX264optBAdaptPopUp */
[fX264optBAdaptPopUp removeAllItems];
[fX264optBAdaptPopUp addItemWithTitle:@"Default (1)"];
[fX264optBAdaptPopUp addItemWithTitle:@"0"];
[fX264optBAdaptPopUp addItemWithTitle:@"1"];
[fX264optBAdaptPopUp addItemWithTitle:@"2"];
[fX264optBAdaptPopUp setWantsLayer:YES];
/*Alpha Deblock*/
[fX264optAlphaDeblockPopUp removeAllItems];
[fX264optAlphaDeblockPopUp addItemWithTitle:@"Default (0)"];
for (i=-6; i<7;i++)
{
[fX264optAlphaDeblockPopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
}
/*Beta Deblock*/
[fX264optBetaDeblockPopUp removeAllItems];
[fX264optBetaDeblockPopUp addItemWithTitle:@"Default (0)"];
for (i=-6; i<7;i++)
{
[fX264optBetaDeblockPopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
}
/* Analysis fX264optAnalysePopUp */
[fX264optAnalysePopUp removeAllItems];
[fX264optAnalysePopUp addItemWithTitle:@"Default (some)"]; /* 0=default */
[fX264optAnalysePopUp addItemWithTitle:[NSString stringWithFormat:@"None"]]; /* 1=none */
[fX264optAnalysePopUp addItemWithTitle:[NSString stringWithFormat:@"All"]]; /* 2=all */
/* 8x8 DCT fX264op8x8dctSwitch */
[fX264opt8x8dctSwitch setState:0];
[fX264opt8x8dctSwitch setWantsLayer:YES];
/* CABAC fX264opCabacSwitch */
[fX264optCabacSwitch setState:1];
/* PsyRDO fX264optPsyRDSlider */
[fX264optPsyRDSlider setMinValue:0.0];
[fX264optPsyRDSlider setMaxValue:1.0];
[fX264optPsyRDSlider setTickMarkPosition:NSTickMarkBelow];
[fX264optPsyRDSlider setNumberOfTickMarks:10];
[fX264optPsyRDSlider setAllowsTickMarkValuesOnly:YES];
[fX264optPsyRDSlider setFloatValue:1.0];
/* PsyTrellis fX264optPsyRDSlider */
[fX264optPsyTrellisSlider setMinValue:0.0];
[fX264optPsyTrellisSlider setMaxValue:1.0];
[fX264optPsyTrellisSlider setTickMarkPosition:NSTickMarkBelow];
[fX264optPsyTrellisSlider setNumberOfTickMarks:10];
[fX264optPsyTrellisSlider setAllowsTickMarkValuesOnly:YES];
[fX264optPsyTrellisSlider setFloatValue:0.0];
/* Standardize the option string */
[self X264AdvancedOptionsStandardizeOptString:nil];
/* Set Current GUI Settings based on newly standardized string */
[self X264AdvancedOptionsSetCurrentSettings:nil];
/* Fade out options that don't apply */
[self X264AdvancedOptionsAnimate: sender];
}
/**
* Cleans the option string to use a standard format of option=value
*/
- (IBAction) X264AdvancedOptionsStandardizeOptString: (id) sender
{
/* Set widgets depending on the opt string in field */
NSString * thisOpt; // The separated option such as "bframes=3"
NSString * optName = @""; // The option name such as "bframes"
NSString * optValue = @"";// The option value such as "3"
NSString * changedOptString = @"";
NSArray *currentOptsArray;
/*First, we get an opt string to process */
NSString *currentOptString = [fDisplayX264Options stringValue];
/* Verify there is an opt string to process by making sure an
option is getting its value set. If so, start to process it. */
NSRange currentOptRange = [currentOptString rangeOfString:@"="];
if (currentOptRange.location != NSNotFound)
{
/*Put individual options into an array based on the ":" separator for processing, result is "="*/
currentOptsArray = [currentOptString componentsSeparatedByString:@":"];
/*iterate through the array and get and 0 && sender != fX264optWeightBSwitch && sender != fX264optBPyramidSwitch && sender != fX264optDirectPredPopUp && sender != fX264optBAdaptPopUp )
{
[fX264optDirectPredPopUp selectItemAtIndex: 0];
[[fX264optDirectPredPopUp cell] performClick:self];
}
[[fX264optBAdaptPopUp animator] setHidden:YES];
[[fX264optBAdaptLabel animator] setHidden:YES];
if ( [fX264optDirectPredPopUp indexOfSelectedItem] > 0 && sender != fX264optWeightBSwitch && sender != fX264optBPyramidSwitch && sender != fX264optDirectPredPopUp && sender != fX264optBAdaptPopUp )
{
[fX264optBAdaptPopUp selectItemAtIndex: 0];
[[fX264optBAdaptPopUp cell] performClick:self];
}
}
else if ( [fX264optBframesPopUp indexOfSelectedItem ] == 2)
{
/* Only 1 b-frame? Disable b-pyramid. */
[[fX264optBPyramidSwitch animator] setHidden:YES];
[[fX264optBPyramidLabel animator] setHidden:YES];
if ( [fX264optBPyramidSwitch state] == 1 && sender != fX264optBPyramidSwitch)
[fX264optBPyramidSwitch performClick:self];
[[fX264optWeightBSwitch animator] setHidden:NO];
[[fX264optWeightBLabel animator] setHidden:NO];
[[fX264optDirectPredPopUp animator] setHidden:NO];
[[fX264optDirectPredLabel animator] setHidden:NO];
[[fX264optBAdaptPopUp animator] setHidden:NO];
[[fX264optBAdaptLabel animator] setHidden:NO];
}
else
{
[[fX264optWeightBSwitch animator] setHidden:NO];
[[fX264optWeightBLabel animator] setHidden:NO];
[[fX264optBPyramidSwitch animator] setHidden:NO];
[[fX264optBPyramidLabel animator] setHidden:NO];
[[fX264optDirectPredPopUp animator] setHidden:NO];
[[fX264optDirectPredLabel animator] setHidden:NO];
[[fX264optBAdaptPopUp animator] setHidden:NO];
[[fX264optBAdaptLabel animator] setHidden:NO];
}
if ( [fX264optCabacSwitch state] == false)
{
if( [fX264optTrellisPopUp isHidden] == false )
{
/* Without CABAC entropy coding, trellis doesn't run. */
[[fX264optTrellisPopUp animator] setHidden:YES];
[[fX264optTrellisLabel animator] setHidden:YES];
[fX264optTrellisPopUp selectItemAtIndex:0];
if ( (sender != fX264optTrellisPopUp) && (sender != fX264optPsyTrellisSlider) )
{
[[fX264optTrellisPopUp cell] performClick:self];
}
}
}
else if( [fX264optTrellisPopUp isHidden] == true)
{
[[fX264optTrellisPopUp animator] setHidden:NO];
[[fX264optTrellisLabel animator] setHidden:NO];
}
if ( [fX264optAnalysePopUp indexOfSelectedItem] == 1)
{
/* No analysis? Disable 8x8dct */
[[fX264opt8x8dctSwitch animator] setHidden:YES];
[[fX264opt8x8dctLabel animator] setHidden:YES];
if ( [fX264opt8x8dctSwitch state] == 1 && sender != fX264opt8x8dctSwitch )
[fX264opt8x8dctSwitch performClick:self];
}
else
{
[[fX264opt8x8dctSwitch animator] setHidden:NO];
[[fX264opt8x8dctLabel animator] setHidden:NO];
}
if ( [fX264optRefPopUp indexOfSelectedItem] < 3)
{
/* Only do mixed-refs when there are at least 2 refs to mix. */
[[fX264optMixedRefsSwitch animator] setHidden:YES];
[[fX264optMixedRefsLabel animator] setHidden:YES];
if ( [fX264optMixedRefsSwitch state] == 1 && sender != fX264optMixedRefsSwitch )
[fX264optMixedRefsSwitch performClick:self];
}
else
{
[[fX264optMixedRefsSwitch animator] setHidden:NO];
[[fX264optMixedRefsLabel animator] setHidden:NO];
}
if ( [fX264optMotionEstPopUp indexOfSelectedItem] < 3 )
{
/* ME-range can only be above 16 if me >= umh
and changing it to < 16 is idiotic so hide it . */
[[fX264optMERangePopUp animator] setHidden:YES];
[[fX264optMERangeLabel animator] setHidden:YES];
if (sender != fX264optMERangePopUp && [fX264optMERangePopUp indexOfSelectedItem] > 0 )
{
[fX264optMERangePopUp selectItemAtIndex:0];
[[fX264optMERangePopUp cell] performClick:self];
}
}
else
{
[[fX264optMERangePopUp animator] setHidden:NO];
[[fX264optMERangeLabel animator] setHidden:NO];
}
if( [fX264optSubmePopUp indexOfSelectedItem] != 0 && [fX264optSubmePopUp indexOfSelectedItem] < 7 )
{
/* No Psy-RDO or Psy=trel if subme < 6. */
if( [fX264optPsyRDSlider isHidden] == false )
{
[[fX264optPsyRDSlider animator] setHidden:YES];
[[fX264optPsyRDLabel animator] setHidden:YES];
[[fX264optPsyRDSlider animator] setFloatValue:1];
if ( (sender != fX264optPsyRDSlider) && (sender != fX264optPsyTrellisSlider) )
{
[[fX264optPsyRDSlider cell] performClick:self];
}
}
if( [fX264optPsyTrellisSlider isHidden] == false)
{
[[fX264optPsyTrellisSlider animator] setHidden:YES];
[[fX264optPsyTrellisLabel animator] setHidden:YES];
[[fX264optPsyTrellisSlider animator] setFloatValue:0];
if ( (sender != fX264optPsyTrellisSlider) && (sender != fX264optPsyRDSlider) )
{
[[fX264optPsyTrellisSlider cell] performClick:self];
}
}
}
else
{
if( [fX264optPsyRDSlider isHidden] == true )
{
[[fX264optPsyRDSlider animator] setHidden:NO];
[[fX264optPsyRDLabel animator] setHidden:NO];
}
if( [fX264optTrellisPopUp indexOfSelectedItem] >= 2 && [fX264optCabacSwitch state] == true && [fX264optPsyTrellisSlider isHidden] == true )
{
[[fX264optPsyTrellisSlider animator] setHidden:NO];
[[fX264optPsyTrellisLabel animator] setHidden:NO];
}
}
if( [fX264optTrellisPopUp indexOfSelectedItem] < 2 )
{
if( [fX264optPsyTrellisSlider isHidden] == false )
{
/* No Psy-trellis without trellis. */
[[fX264optPsyTrellisSlider animator] setHidden:YES];
[[fX264optPsyTrellisLabel animator] setHidden:YES];
[[fX264optPsyTrellisSlider animator] setFloatValue:0];
if ( (sender != fX264optTrellisPopUp) && (sender != fX264optPsyTrellisSlider) )
{
[[fX264optPsyTrellisSlider cell] performClick:self];
}
}
}
else
{
if( ( [fX264optSubmePopUp indexOfSelectedItem] == 0 || [fX264optSubmePopUp indexOfSelectedItem] >= 7 ) && [fX264optCabacSwitch state] == true && [fX264optPsyTrellisSlider isHidden] == true )
{
[[fX264optPsyTrellisSlider animator] setHidden:NO];
[[fX264optPsyTrellisLabel animator] setHidden:NO];
}
}
}
/**
* Resets the GUI widgets to the contents of the option string.
*/
- (IBAction) X264AdvancedOptionsSetCurrentSettings: (id) sender
{
/* Set widgets depending on the opt string in field */
NSString * thisOpt; // The separated option such as "bframes=3"
NSString * optName = @""; // The option name such as "bframes"
NSString * optValue = @"";// The option value such as "3"
NSArray *currentOptsArray;
/*First, we get an opt string to process */
NSString *currentOptString = [fDisplayX264Options stringValue];
/* Verify there is an opt string to process by making sure an
option is getting its value set. If so, start to process it. */
NSRange currentOptRange = [currentOptString rangeOfString:@"="];
if (currentOptRange.location != NSNotFound)
{
/*Put individual options into an array based on the ":" separator for processing, result is "="*/
currentOptsArray = [currentOptString componentsSeparatedByString:@":"];
/*iterate through the array and get and ="*/
currentOptsArray = [currentOptString componentsSeparatedByString:@":"];
/*iterate through the array and get and