/* 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 }; 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]; /*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) { [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]; [[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]; [[fX264optDirectPredPopUp animator] setHidden:NO]; [[fX264optDirectPredLabel 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