/* 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,fX264optBRDOLabel,fX264optBRDOSwitch,
fX264optBPyramidLabel,fX264optBPyramidSwitch,fX264optBiMELabel,fX264optBiMESwitch,
fX264optDirectPredLabel,fX264optDirectPredPopUp,fX264optDeblockLabel,fX264optAnalyseLabel,
fX264optAnalysePopUp,fX264opt8x8dctLabel,fX264opt8x8dctSwitch,fX264optCabacLabel,fX264optCabacSwitch,
fX264optAlphaDeblockPopUp,fX264optBetaDeblockPopUp};
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<8;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"];
/*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 Rate Distortion Optimization fX264optBRDOSwitch BOOLEAN*/
[fX264optBRDOSwitch setState:0];
[fX264optBRDOSwitch setWantsLayer:YES];
/*B-frame Pyramids fX264optBPyramidSwitch BOOLEAN*/
[fX264optBPyramidSwitch setState:0];
[fX264optBPyramidSwitch setWantsLayer:YES];
/*Bidirectional Motion Estimation Refinement fX264optBiMESwitch BOOLEAN*/
[fX264optBiMESwitch setState:0];
[fX264optBiMESwitch 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];
/*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];
/* 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 != fX264optBRDOSwitch && sender != fX264optBPyramidSwitch && sender != fX264optBiMESwitch && sender != fX264optDirectPredPopUp)
{
[fX264optDirectPredPopUp selectItemAtIndex: 0];
[[fX264optDirectPredPopUp 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];
[[fX264optBiMESwitch animator] setHidden:NO];
[[fX264optBiMELabel animator] setHidden:NO];
if ( [fX264optSubmePopUp indexOfSelectedItem] >= 7 || [fX264optSubmePopUp indexOfSelectedItem] == 0 )
{
/* Only show B-RDO if both bframes and subme allow it. */
[[fX264optBRDOSwitch animator] setHidden:NO];
[[fX264optBRDOLabel animator] setHidden:NO];
}
[[fX264optDirectPredPopUp animator] setHidden:NO];
[[fX264optDirectPredLabel animator] setHidden:NO];
}
else
{
[[fX264optWeightBSwitch animator] setHidden:NO];
[[fX264optWeightBLabel animator] setHidden:NO];
[[fX264optBPyramidSwitch animator] setHidden:NO];
[[fX264optBPyramidLabel animator] setHidden:NO];
[[fX264optBiMESwitch animator] setHidden:NO];
[[fX264optBiMELabel animator] setHidden:NO];
if ( [fX264optSubmePopUp indexOfSelectedItem] >= 7 || [fX264optSubmePopUp indexOfSelectedItem] == 0 )
{
/* Only show B-RDO if both bframes and subme allow it. */
[[fX264optBRDOSwitch animator] setHidden:NO];
[[fX264optBRDOLabel animator] setHidden:NO];
}
[[fX264optDirectPredPopUp animator] setHidden:NO];
[[fX264optDirectPredLabel animator] setHidden:NO];
}
if ( [fX264optCabacSwitch state] == false)
{
/* Without CABAC entropy coding, trellis doesn't run. */
[[fX264optTrellisPopUp animator] setHidden:YES];
[[fX264optTrellisLabel animator] setHidden:YES];
[fX264optTrellisPopUp selectItemAtIndex:0];
if (sender != fX264optTrellisPopUp)
[[fX264optTrellisPopUp cell] performClick:self];
}
else
{
[[fX264optTrellisPopUp animator] setHidden:NO];
[[fX264optTrellisLabel animator] setHidden:NO];
}
if ( [fX264optSubmePopUp indexOfSelectedItem] < 7 && [fX264optSubmePopUp indexOfSelectedItem] != 0 )
{
/* When subme < 6, B-RDO doesn't work. */
[[fX264optBRDOSwitch animator] setHidden:YES];
[[fX264optBRDOLabel animator] setHidden:YES];
if ( [fX264optBRDOSwitch state] == 1 && sender != fX264optBRDOSwitch )
[fX264optBRDOSwitch performClick:self];
}
else if ( [fX264optBframesPopUp indexOfSelectedItem ] >= 2 )
{
/* Make sure to only display B-RDO if allowed by both
the subme and bframe option settings. */
[[fX264optBRDOSwitch animator] setHidden:NO];
[[fX264optBRDOLabel 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];
}
}
/**
* 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