summaryrefslogtreecommitdiffstats
path: root/macosx/HBVideoController.m
diff options
context:
space:
mode:
authorritsuka <[email protected]>2014-07-15 18:30:51 +0000
committerritsuka <[email protected]>2014-07-15 18:30:51 +0000
commit31283b442713147dc5edb5135cb6dbcbb95635e8 (patch)
treea779647bf655c11b4ba5d1c0a3839202cf17a2a4 /macosx/HBVideoController.m
parent076704ec10c392851673856eeaf071eb79f90075 (diff)
MacGUI: Refactored the controller code for the video/audio/subtitles/chapters view:
Added a xib file and a NSViewController subclass for each tab of the main HandBrake window. Each view controller now to responds to the HBContainerChangedNotification and HBTitleChangedNotification notifications instead of using a custom way to notify changes. Converted the modified .xibs to the Xcode 5.1 format. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@6231 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'macosx/HBVideoController.m')
-rw-r--r--macosx/HBVideoController.m1339
1 files changed, 1339 insertions, 0 deletions
diff --git a/macosx/HBVideoController.m b/macosx/HBVideoController.m
new file mode 100644
index 000000000..e602e3f8d
--- /dev/null
+++ b/macosx/HBVideoController.m
@@ -0,0 +1,1339 @@
+/* HBVideoController.m $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.fr/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#import "HBVideoController.h"
+
+#include "hb.h"
+
+#import "Controller.h"
+#import "HBAdvancedController.h"
+
+NSString *HBVideoEncoderChangedNotification = @"HBVideoEncoderChangedNotification";
+
+@interface HBVideoController () {
+ /* Framerate */
+ /* Radio Button Framerate Controls */
+ IBOutlet NSMatrix * fFramerateMatrix;
+ IBOutlet NSButtonCell * fFramerateVfrPfrCell;
+ IBOutlet NSButtonCell * fFramerateCfrCell;
+
+ /* Video Encoder */
+ IBOutlet NSTextField * fVidRateField;
+ IBOutlet NSPopUpButton * fVidRatePopUp;
+ IBOutlet NSTextField * fVidEncoderField;
+ IBOutlet NSPopUpButton * fVidEncoderPopUp;
+ IBOutlet NSTextField * fVidQualityField;
+ IBOutlet NSTextField * fVidQualityRFLabel;
+ IBOutlet NSTextField * fVidQualityRFField;
+ IBOutlet NSMatrix * fVidQualityMatrix;
+ IBOutlet NSButtonCell * fVidBitrateCell;
+ IBOutlet NSTextField * fVidBitrateField;
+ IBOutlet NSButtonCell * fVidConstantCell;
+ IBOutlet NSSlider * fVidQualitySlider;
+ IBOutlet NSButton * fVidTwoPassCheck;
+ IBOutlet NSButton * fVidTurboPassCheck;
+
+ /* Status read out fields for picture settings and video filters */
+ IBOutlet NSTextField * fPictureSettingsField;
+ IBOutlet NSTextField * fPictureFiltersField;
+
+ /* x264 Presets Box */
+ NSArray * fX264PresetNames;
+ NSUInteger fX264MediumPresetIndex;
+ IBOutlet NSButton * fX264UseAdvancedOptionsCheck;
+ IBOutlet NSBox * fX264PresetsBox;
+ IBOutlet NSSlider * fX264PresetsSlider;
+ IBOutlet NSTextField * fX264PresetSliderLabel;
+ IBOutlet NSTextField * fX264PresetSelectedTextField;
+ IBOutlet NSPopUpButton * fX264TunePopUp;
+ IBOutlet NSTextField * fX264TunePopUpLabel;
+ IBOutlet NSPopUpButton * fX264ProfilePopUp;
+ IBOutlet NSTextField * fX264ProfilePopUpLabel;
+ IBOutlet NSPopUpButton * fX264LevelPopUp;
+ IBOutlet NSTextField * fX264LevelPopUpLabel;
+ IBOutlet NSButton * fX264FastDecodeCheck;
+ IBOutlet NSTextField * fDisplayX264PresetsAdditonalOptionsTextField;
+ IBOutlet NSTextField * fDisplayX264PresetsAdditonalOptionsLabel;
+ // Text Field to show the expanded opts from unparse()
+ IBOutlet NSTextField * fDisplayX264PresetsUnparseTextField;
+ char * fX264PresetsUnparsedUTF8String;
+ NSUInteger _fX264PresetsHeightForUnparse;
+ NSUInteger _fX264PresetsWidthForUnparse;
+}
+
+@end
+
+@implementation HBVideoController
+
+@synthesize fX264PresetsHeightForUnparse = _fX264PresetsHeightForUnparse;
+@synthesize fX264PresetsWidthForUnparse = _fX264PresetsWidthForUnparse;
+
+- (void)setPictureSettingsField:(NSString *)string
+{
+ if (string)
+ {
+ [_pictureSettingsField autorelease];
+ _pictureSettingsField = [[NSString stringWithFormat:@"Picture Settings: %@", string] retain];
+ }
+}
+
+- (void)setPictureFiltersField:(NSString *)string
+{
+ if (string)
+ {
+ [_pictureFiltersField autorelease];
+ _pictureFiltersField = [[NSString stringWithFormat:@"Picture Filters: %@", string] retain];
+ }
+}
+
+- (int)selectedCodec
+{
+ return (int)[[fVidEncoderPopUp selectedItem] tag];
+}
+
+- (int)selectedQualityType
+{
+ return (int)[[fVidQualityMatrix selectedCell] tag];
+}
+
+- (NSString *)selectedBitrate
+{
+ return [fVidBitrateField stringValue];
+}
+
+- (NSString *)selectedQuality
+{
+ return [fVidQualityRFField stringValue];
+}
+
+
+- (instancetype)init
+{
+ self = [super initWithNibName:@"Video" bundle:nil];
+ if (self)
+ {
+ /*
+ * initialize fX264PresetsUnparsedUTF8String as early as possible
+ * avoids an invalid free
+ */
+ fX264PresetsUnparsedUTF8String = NULL;
+ _pictureFiltersField = @"Pictures Filters:";
+ _pictureSettingsField = @"Pictures Settings:";
+
+ NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+
+ /* register that we are interested in changes made to the video container */
+ [center addObserver:self selector: @selector(containerChanged:) name:HBContainerChangedNotification object:nil];
+ [center addObserver:self selector: @selector(titleChanged:) name:HBTitleChangedNotification object:nil];
+ }
+
+ return self;
+}
+
+- (void)loadView {
+ [super loadView];
+
+ /* Video encoder */
+ [fVidEncoderPopUp removeAllItems];
+ [fVidEncoderPopUp addItemWithTitle: @"FFmpeg"];
+
+ /* setup our x264 presets widgets - this only needs to be done once */
+ [self setupX264PresetsWidgets];
+
+ /* Video quality */
+ [fVidBitrateField setIntValue: 1000];
+ [fVidQualityMatrix selectCell: fVidBitrateCell];
+ [self videoMatrixChanged:nil];
+
+ /* Video framerate */
+ [fVidRatePopUp removeAllItems];
+ NSMenuItem *menuItem = [[fVidRatePopUp menu] addItemWithTitle:@"Same as source"
+ action:nil
+ keyEquivalent:@""];
+ [menuItem setTag:hb_video_framerate_get_from_name("Same as source")];
+ for (const hb_rate_t *video_framerate = hb_video_framerate_get_next(NULL);
+ video_framerate != NULL;
+ video_framerate = hb_video_framerate_get_next(video_framerate))
+ {
+ NSString *itemTitle;
+ if (!strcmp(video_framerate->name, "23.976"))
+ {
+ itemTitle = @"23.976 (NTSC Film)";
+ }
+ else if (!strcmp(video_framerate->name, "25"))
+ {
+ itemTitle = @"25 (PAL Film/Video)";
+ }
+ else if (!strcmp(video_framerate->name, "29.97"))
+ {
+ itemTitle = @"29.97 (NTSC Video)";
+ }
+ else
+ {
+ itemTitle = [NSString stringWithUTF8String:video_framerate->name];
+ }
+ menuItem = [[fVidRatePopUp menu] addItemWithTitle:itemTitle
+ action:nil
+ keyEquivalent:@""];
+ [menuItem setTag:video_framerate->rate];
+ }
+ [fVidRatePopUp selectItemAtIndex:0];
+
+ /* We disable the Turbo 1st pass checkbox since we are not x264 */
+ [fVidTurboPassCheck setEnabled: NO];
+ [fVidTurboPassCheck setState: NSOffState];
+}
+
+- (void)enableUI:(BOOL)b {
+ NSControl *controls[] =
+ {
+ fFramerateMatrix,
+ fVidRateField,
+ fVidRatePopUp,
+ fVidEncoderField,
+ fVidEncoderPopUp,
+ fVidQualityField,
+ fVidQualityRFLabel,
+ fVidQualityRFField,
+ fVidQualityMatrix,
+ fVidBitrateField,
+ fVidQualitySlider,
+ fVidTwoPassCheck,
+ fVidTurboPassCheck,
+ fPictureSettingsField,
+ fPictureFiltersField
+ };
+
+ for (unsigned 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];
+ }
+
+ [self videoMatrixChanged:nil];
+ [self enableX264Widgets:b];
+}
+
+- (void)containerChanged:(NSNotification *)aNotification
+{
+ NSDictionary *notDict = [aNotification userInfo];
+
+ int videoContainer = [[notDict objectForKey: keyContainerTag] intValue];
+
+ /* lets get the tag of the currently selected item first so we might reset it later */
+ int selectedVidEncoderTag = (int)[[fVidEncoderPopUp selectedItem] tag];
+
+ /* Note: we now store the video encoder int values from common.c in the tags of each popup for easy retrieval later */
+ [fVidEncoderPopUp removeAllItems];
+ for (const hb_encoder_t *video_encoder = hb_video_encoder_get_next(NULL);
+ video_encoder != NULL;
+ video_encoder = hb_video_encoder_get_next(video_encoder))
+ {
+ if (video_encoder->muxers & videoContainer)
+ {
+ NSMenuItem *menuItem = [[fVidEncoderPopUp menu] addItemWithTitle:[NSString stringWithUTF8String:video_encoder->name]
+ action:nil
+ keyEquivalent:@""];
+ [menuItem setTag:video_encoder->codec];
+ }
+ }
+
+ /*
+ * item 0 will be selected by default
+ * deselect it so that we can detect whether the video encoder has changed
+ */
+ [fVidEncoderPopUp selectItem:nil];
+ if (selectedVidEncoderTag)
+ {
+ // if we have a tag for previously selected encoder, try to select it
+ // if this fails, [fVidEncoderPopUp selectedItem] will be nil
+ // we'll handle that scenario further down
+ [fVidEncoderPopUp selectItemWithTag:selectedVidEncoderTag];
+ }
+
+ if ([fVidEncoderPopUp selectedItem] == nil)
+ {
+ /* this means the above call to selectItemWithTag failed */
+ [fVidEncoderPopUp selectItemAtIndex:0];
+ [self videoEncoderPopUpChanged:nil];
+ }
+}
+
+- (void)titleChanged:(NSNotification *)aNotification
+{
+ [fVidRatePopUp selectItemAtIndex: 0];
+}
+
+#pragma mark - apply settings
+
+- (void)applyVideoSettingsFromQueue:(NSDictionary *)queueToApply
+{
+ /* video encoder */
+ [fVidEncoderPopUp selectItemWithTitle:[queueToApply objectForKey:@"VideoEncoder"]];
+ [self.fAdvancedOptions setLavcOptions: [queueToApply objectForKey:@"lavcOption"]];
+ /* advanced x264 options */
+ if ([[queueToApply objectForKey:@"x264UseAdvancedOptions"] intValue])
+ {
+ // we are using the advanced panel
+ [self.fAdvancedOptions setOptions:[queueToApply objectForKey:@"x264Option"]];
+ // preset does not use the x264 preset system, reset the widgets
+ [self setX264Preset: nil];
+ [self setX264Tune: nil];
+ [self setX264OptionExtra:[queueToApply objectForKey:@"x264Option"]];
+ [self setH264Profile: nil];
+ [self setH264Level: nil];
+ // enable the advanced panel and update the widgets
+ [fX264UseAdvancedOptionsCheck setState:NSOnState];
+ [self updateX264Widgets:nil];
+ }
+ else
+ {
+ // we are using the x264 preset system
+ [self setX264Preset: [queueToApply objectForKey:@"x264Preset"]];
+ [self setX264Tune: [queueToApply objectForKey:@"x264Tune"]];
+ [self setX264OptionExtra:[queueToApply objectForKey:@"x264OptionExtra"]];
+ [self setH264Profile: [queueToApply objectForKey:@"h264Profile"]];
+ [self setH264Level: [queueToApply objectForKey:@"h264Level"]];
+ // preset does not use the advanced panel, reset it
+ [self.fAdvancedOptions setOptions:@""];
+ // disable the advanced panel and update the widgets
+ [fX264UseAdvancedOptionsCheck setState:NSOffState];
+ [self updateX264Widgets:nil];
+ }
+
+ /* Lets run through the following functions to get variables set there */
+ [self videoEncoderPopUpChanged:nil];
+
+ /* Video quality */
+ [fVidQualityMatrix selectCellAtRow:[[queueToApply objectForKey:@"VideoQualityType"] intValue] column:0];
+
+ [fVidBitrateField setStringValue:[queueToApply objectForKey:@"VideoAvgBitrate"]];
+
+ int direction;
+ float minValue, maxValue, granularity;
+ hb_video_quality_get_limits((int)[[fVidEncoderPopUp selectedItem] tag],
+ &minValue, &maxValue, &granularity, &direction);
+ if (!direction)
+ {
+ [fVidQualitySlider setFloatValue:[[queueToApply objectForKey:@"VideoQualitySlider"] floatValue]];
+ }
+ else
+ {
+ /*
+ * Since ffmpeg and x264 use an "inverted" slider (lower values
+ * indicate a higher quality) we invert the value on the slider
+ */
+ [fVidQualitySlider setFloatValue:([fVidQualitySlider minValue] +
+ [fVidQualitySlider maxValue] -
+ [[queueToApply objectForKey:@"VideoQualitySlider"] floatValue])];
+ }
+
+ [self videoMatrixChanged:nil];
+
+ /* Video framerate */
+ if ([[queueToApply objectForKey:@"VideoFramerate"] isEqualToString:@"Same as source"])
+ {
+ /* Now set the Video Frame Rate Mode to either vfr or cfr according to the preset */
+ if ([[queueToApply objectForKey:@"VideoFramerateMode"] isEqualToString:@"vfr"])
+ {
+ [fFramerateMatrix selectCellAtRow:0 column:0]; // we want vfr
+ }
+ else
+ {
+ [fFramerateMatrix selectCellAtRow:1 column:0]; // we want cfr
+ }
+ }
+ else
+ {
+ /* Now set the Video Frame Rate Mode to either pfr or cfr according to the preset */
+ if ([[queueToApply objectForKey:@"VideoFramerateMode"] isEqualToString:@"pfr"])
+ {
+ [fFramerateMatrix selectCellAtRow:0 column:0]; // we want pfr
+ }
+ else
+ {
+ [fFramerateMatrix selectCellAtRow:1 column:0]; // we want cfr
+ }
+ }
+ [fVidRatePopUp selectItemWithTitle:[queueToApply objectForKey:@"VideoFramerate"]];
+ [self videoFrameRateChanged:nil];
+
+ /* 2 Pass Encoding */
+ [fVidTwoPassCheck setState:[[queueToApply objectForKey:@"VideoTwoPass"] intValue]];
+ [self twoPassCheckboxChanged:nil];
+ /* Turbo 1st pass for 2 Pass Encoding */
+ [fVidTurboPassCheck setState:[[queueToApply objectForKey:@"VideoTurboTwoPass"] intValue]];
+}
+
+- (void)applySettingsFromPreset:(NSDictionary *)preset
+{
+ /* map legacy encoder names via libhb */
+ const char *strValue = hb_video_encoder_sanitize_name([[preset objectForKey:@"VideoEncoder"] UTF8String]);
+ [fVidEncoderPopUp selectItemWithTitle:[NSString stringWithFormat:@"%s", strValue]];
+ [self videoEncoderPopUpChanged:nil];
+
+ if ([[fVidEncoderPopUp selectedItem] tag] == HB_VCODEC_X264)
+ {
+ if (![preset objectForKey:@"x264UseAdvancedOptions"] ||
+ [[preset objectForKey:@"x264UseAdvancedOptions"] intValue])
+ {
+ /*
+ * x264UseAdvancedOptions is not set (legacy preset)
+ * or set to 1 (enabled), so we use the old advanced panel
+ */
+ if ([preset objectForKey:@"x264Option"])
+ {
+ /* we set the advanced options string here if applicable */
+ [self.fAdvancedOptions setOptions:[preset objectForKey:@"x264Option"]];
+ [self setX264OptionExtra:[preset objectForKey:@"x264Option"]];
+ }
+ else
+ {
+ [self.fAdvancedOptions setOptions: @""];
+ [self setX264OptionExtra:nil];
+ }
+ /* preset does not use the x264 preset system, reset the widgets */
+ [self setX264Preset: nil];
+ [self setX264Tune: nil];
+ [self setH264Profile:nil];
+ [self setH264Level: nil];
+ /* we enable the advanced panel and update the widgets */
+ [fX264UseAdvancedOptionsCheck setState:NSOnState];
+ [self updateX264Widgets:nil];
+ }
+ else
+ {
+ /*
+ * x264UseAdvancedOptions is set to 0 (disabled),
+ * so we use the x264 preset system
+ */
+ [self setX264Preset: [preset objectForKey:@"x264Preset"]];
+ [self setX264Tune: [preset objectForKey:@"x264Tune"]];
+ [self setX264OptionExtra:[preset objectForKey:@"x264OptionExtra"]];
+ [self setH264Profile: [preset objectForKey:@"h264Profile"]];
+ [self setH264Level: [preset objectForKey:@"h264Level"]];
+ /* preset does not use the advanced panel, reset it */
+ [self.fAdvancedOptions setOptions:@""];
+ /* we disable the advanced panel and update the widgets */
+ [fX264UseAdvancedOptionsCheck setState:NSOffState];
+ [self updateX264Widgets:nil];
+ }
+ }
+
+ int qualityType = [[preset objectForKey:@"VideoQualityType"] intValue] - 1;
+ /* Note since the removal of Target Size encoding, the possible values for VideoQuality type are 0 - 1.
+ * Therefore any preset that uses the old 2 for Constant Quality would now use 1 since there is one less index
+ * for the fVidQualityMatrix. It should also be noted that any preset that used the deprecated Target Size
+ * setting of 0 would set us to 0 or ABR since ABR is now tagged 0. Fortunately this does not affect any built-in
+ * presets since they all use Constant Quality or Average Bitrate.*/
+ if (qualityType == -1)
+ {
+ qualityType = 0;
+ }
+ [fVidQualityMatrix selectCellWithTag:qualityType];
+
+ [fVidBitrateField setStringValue:[preset objectForKey:@"VideoAvgBitrate"]];
+
+ int direction;
+ float minValue, maxValue, granularity;
+ hb_video_quality_get_limits((int)[[fVidEncoderPopUp selectedItem] tag],
+ &minValue, &maxValue, &granularity, &direction);
+ if (!direction)
+ {
+ [fVidQualitySlider setFloatValue:[[preset objectForKey:@"VideoQualitySlider"] floatValue]];
+ }
+ else
+ {
+ /*
+ * Since ffmpeg and x264 use an "inverted" slider (lower values
+ * indicate a higher quality) we invert the value on the slider
+ */
+ [fVidQualitySlider setFloatValue:([fVidQualitySlider minValue] +
+ [fVidQualitySlider maxValue] -
+ [[preset objectForKey:@"VideoQualitySlider"] floatValue])];
+ }
+
+ [self videoMatrixChanged:nil];
+
+ /* Video framerate */
+ if ([[preset objectForKey:@"VideoFramerate"] isEqualToString:@"Same as source"])
+ {
+ /* Now set the Video Frame Rate Mode to either vfr or cfr according to the preset */
+ if (![preset objectForKey:@"VideoFramerateMode"] ||
+ [[preset objectForKey:@"VideoFramerateMode"] isEqualToString:@"vfr"])
+ {
+ [fFramerateMatrix selectCellAtRow:0 column:0]; // we want vfr
+ }
+ else
+ {
+ [fFramerateMatrix selectCellAtRow:1 column:0]; // we want cfr
+ }
+ }
+ else
+ {
+ /* Now set the Video Frame Rate Mode to either pfr or cfr according to the preset */
+ if ([[preset objectForKey:@"VideoFramerateMode"] isEqualToString:@"pfr"] ||
+ [[preset objectForKey:@"VideoFrameratePFR"] intValue] == 1)
+ {
+ [fFramerateMatrix selectCellAtRow:0 column:0]; // we want pfr
+ }
+ else
+ {
+ [fFramerateMatrix selectCellAtRow:1 column:0]; // we want cfr
+ }
+ }
+ /* map legacy names via libhb */
+ int intValue = hb_video_framerate_get_from_name([[preset objectForKey:@"VideoFramerate"] UTF8String]);
+ [fVidRatePopUp selectItemWithTag:intValue];
+ [self videoFrameRateChanged:nil];
+
+ /* 2 Pass Encoding */
+ [fVidTwoPassCheck setState:[[preset objectForKey:@"VideoTwoPass"] intValue]];
+ [self twoPassCheckboxChanged:nil];
+
+ /* Turbo 1st pass for 2 Pass Encoding */
+ [fVidTurboPassCheck setState:[[preset objectForKey:@"VideoTurboTwoPass"] intValue]];
+}
+
+- (void)prepareVideoForQueueFileJob:(NSMutableDictionary *)queueFileJob
+{
+ [queueFileJob setObject:[fVidEncoderPopUp titleOfSelectedItem] forKey:@"VideoEncoder"];
+
+ /* x264 advanced options */
+ if ([fX264UseAdvancedOptionsCheck state])
+ {
+ // we are using the advanced panel
+ [queueFileJob setObject:[NSNumber numberWithInt:1] forKey: @"x264UseAdvancedOptions"];
+ [queueFileJob setObject:[self.fAdvancedOptions optionsString] forKey:@"x264Option"];
+ }
+ else
+ {
+ // we are using the x264 preset system
+ [queueFileJob setObject:[NSNumber numberWithInt:0] forKey: @"x264UseAdvancedOptions"];
+ [queueFileJob setObject:[self x264Preset] forKey: @"x264Preset"];
+ [queueFileJob setObject:[self x264Tune] forKey: @"x264Tune"];
+ [queueFileJob setObject:[self x264OptionExtra] forKey: @"x264OptionExtra"];
+ [queueFileJob setObject:[self h264Profile] forKey: @"h264Profile"];
+ [queueFileJob setObject:[self h264Level] forKey: @"h264Level"];
+ }
+
+ /* FFmpeg (lavc) Option String */
+ [queueFileJob setObject:[self.fAdvancedOptions optionsStringLavc] forKey:@"lavcOption"];
+
+ [queueFileJob setObject:[NSNumber numberWithInteger:[[fVidQualityMatrix selectedCell] tag] + 1] forKey:@"VideoQualityType"];
+ [queueFileJob setObject:[fVidBitrateField stringValue] forKey:@"VideoAvgBitrate"];
+ [queueFileJob setObject:[NSNumber numberWithFloat:[fVidQualityRFField floatValue]] forKey:@"VideoQualitySlider"];
+ /* Framerate */
+ [queueFileJob setObject:[fVidRatePopUp titleOfSelectedItem] forKey:@"VideoFramerate"];
+ /* Frame Rate Mode */
+ if ([fFramerateMatrix selectedRow] == 1) // if selected we are cfr regardless of the frame rate popup
+ {
+ [queueFileJob setObject:@"cfr" forKey:@"VideoFramerateMode"];
+ }
+ else
+ {
+ if ([fVidRatePopUp indexOfSelectedItem] == 0) // Same as source frame rate
+ {
+ [queueFileJob setObject:@"vfr" forKey:@"VideoFramerateMode"];
+ }
+ else
+ {
+ [queueFileJob setObject:@"pfr" forKey:@"VideoFramerateMode"];
+ }
+
+ }
+
+ /* 2 Pass Encoding */
+ [queueFileJob setObject:[NSNumber numberWithInteger:[fVidTwoPassCheck state]] forKey:@"VideoTwoPass"];
+ /* Turbo 2 pass Encoding fVidTurboPassCheck*/
+ [queueFileJob setObject:[NSNumber numberWithInteger:[fVidTurboPassCheck state]] forKey:@"VideoTurboTwoPass"];
+
+ /* Video encoder */
+ [queueFileJob setObject:[NSNumber numberWithInteger:[[fVidEncoderPopUp selectedItem] tag]] forKey:@"JobVideoEncoderVcodec"];
+
+ /* Framerate */
+ [queueFileJob setObject:[NSNumber numberWithInteger:[[fVidRatePopUp selectedItem] tag]] forKey:@"JobIndexVideoFramerate"];
+}
+
+- (void)prepareVideoForJobPreview:(hb_job_t *)job andTitle:(hb_title_t *)title
+{
+ job->vcodec = (int)[[fVidEncoderPopUp selectedItem] tag];
+ job->fastfirstpass = 0;
+
+ job->chapter_markers = 0;
+
+ if (job->vcodec == HB_VCODEC_X264)
+ {
+ /* advanced x264 options */
+ NSString *tmpString;
+ // translate zero-length strings to NULL for libhb
+ const char *encoder_preset = NULL;
+ const char *encoder_tune = NULL;
+ const char *encoder_options = NULL;
+ const char *encoder_profile = NULL;
+ const char *encoder_level = NULL;
+ if ([fX264UseAdvancedOptionsCheck state])
+ {
+ // we are using the advanced panel
+ if ([(tmpString = [self.fAdvancedOptions optionsString]) length])
+ {
+ encoder_options = [tmpString UTF8String];
+ }
+ }
+ else
+ {
+ // we are using the x264 preset system
+ if ([(tmpString = [self x264Tune]) length])
+ {
+ encoder_tune = [tmpString UTF8String];
+ }
+ if ([(tmpString = [self x264OptionExtra]) length])
+ {
+ encoder_options = [tmpString UTF8String];
+ }
+ if ([(tmpString = [self h264Profile]) length])
+ {
+ encoder_profile = [tmpString UTF8String];
+ }
+ if ([(tmpString = [self h264Level]) length])
+ {
+ encoder_level = [tmpString UTF8String];
+ }
+ encoder_preset = [[self x264Preset] UTF8String];
+ }
+ hb_job_set_encoder_preset (job, encoder_preset);
+ hb_job_set_encoder_tune (job, encoder_tune);
+ hb_job_set_encoder_options(job, encoder_options);
+ hb_job_set_encoder_profile(job, encoder_profile);
+ hb_job_set_encoder_level (job, encoder_level);
+ }
+ else if (job->vcodec & HB_VCODEC_FFMPEG_MASK)
+ {
+ hb_job_set_encoder_options(job,
+ [[self.fAdvancedOptions optionsStringLavc]
+ UTF8String]);
+ }
+
+ /* Video settings */
+ int fps_mode, fps_num, fps_den;
+ if( [fVidRatePopUp indexOfSelectedItem] > 0 )
+ {
+ /* a specific framerate has been chosen */
+ fps_num = 27000000;
+ fps_den = (int)[[fVidRatePopUp selectedItem] tag];
+ if ([fFramerateMatrix selectedRow] == 1)
+ {
+ // CFR
+ fps_mode = 1;
+ }
+ else
+ {
+ // PFR
+ fps_mode = 2;
+ }
+ }
+ else
+ {
+ /* same as source */
+ fps_num = title->rate;
+ fps_den = title->rate_base;
+ if ([fFramerateMatrix selectedRow] == 1)
+ {
+ // CFR
+ fps_mode = 1;
+ }
+ else
+ {
+ // VFR
+ fps_mode = 0;
+ }
+ }
+
+ switch( [[fVidQualityMatrix selectedCell] tag] )
+ {
+ case 0:
+ /* ABR */
+ job->vquality = -1.0;
+ job->vbitrate = [fVidBitrateField intValue];
+ break;
+ case 1:
+ /* Constant Quality */
+ job->vquality = [fVidQualityRFField floatValue];
+ job->vbitrate = 0;
+ break;
+ }
+
+ /* Add framerate shaping filter */
+ hb_filter_object_t *filter = hb_filter_init(HB_FILTER_VFR);
+ hb_add_filter(job, filter, [[NSString stringWithFormat:@"%d:%d:%d",
+ fps_mode, fps_num, fps_den] UTF8String]);
+}
+
+- (void)prepareVideoForPreset:(NSMutableDictionary *)preset
+{
+ [preset setObject:[fVidEncoderPopUp titleOfSelectedItem] forKey:@"VideoEncoder"];
+ /* x264 Options, this will either be advanced panel or the video tabs x264 presets panel with modded option string */
+
+ if ([fX264UseAdvancedOptionsCheck state] == NSOnState)
+ {
+ /* use the old advanced panel */
+ [preset setObject:[NSNumber numberWithInt:1] forKey:@"x264UseAdvancedOptions"];
+ [preset setObject:[self.fAdvancedOptions optionsString] forKey:@"x264Option"];
+ }
+ else
+ {
+ /* use the x264 preset system */
+ [preset setObject:[NSNumber numberWithInt:0] forKey:@"x264UseAdvancedOptions"];
+ [preset setObject:[self x264Preset] forKey:@"x264Preset"];
+ [preset setObject:[self x264Tune] forKey:@"x264Tune"];
+ [preset setObject:[self x264OptionExtra] forKey:@"x264OptionExtra"];
+ [preset setObject:[self h264Profile] forKey:@"h264Profile"];
+ [preset setObject:[self h264Level] forKey:@"h264Level"];
+ /*
+ * bonus: set the unparsed options to make the preset compatible
+ * with old HB versions
+ */
+ if (fX264PresetsUnparsedUTF8String != NULL)
+ {
+ [preset setObject:[NSString stringWithUTF8String:fX264PresetsUnparsedUTF8String]
+ forKey:@"x264Option"];
+ }
+ else
+ {
+ [preset setObject:@"" forKey:@"x264Option"];
+ }
+ }
+
+ /* FFmpeg (lavc) Option String */
+ [preset setObject:[self.fAdvancedOptions optionsStringLavc] forKey:@"lavcOption"];
+
+ /* though there are actually only 0 - 1 types available in the ui we need to map to the old 0 - 2
+ * set of indexes from when we had 0 == Target , 1 == Abr and 2 == Constant Quality for presets
+ * to take care of any legacy presets. */
+ [preset setObject:[NSNumber numberWithInteger:[[fVidQualityMatrix selectedCell] tag] +1 ] forKey:@"VideoQualityType"];
+ [preset setObject:[fVidBitrateField stringValue] forKey:@"VideoAvgBitrate"];
+ [preset setObject:[NSNumber numberWithFloat:[fVidQualityRFField floatValue]] forKey:@"VideoQualitySlider"];
+
+ /* Video framerate and framerate mode */
+ if ([fFramerateMatrix selectedRow] == 1)
+ {
+ [preset setObject:@"cfr" forKey:@"VideoFramerateMode"];
+ }
+ if ([fVidRatePopUp indexOfSelectedItem] == 0) // Same as source is selected
+ {
+ [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
+
+ if ([fFramerateMatrix selectedRow] == 0)
+ {
+ [preset setObject:@"vfr" forKey:@"VideoFramerateMode"];
+ }
+ }
+ else // translate the rate (selected item's tag) to the official libhb name
+ {
+ [preset setObject:[NSString stringWithFormat:@"%s",
+ hb_video_framerate_get_name((int)[[fVidRatePopUp selectedItem] tag])]
+ forKey:@"VideoFramerate"];
+
+ if ([fFramerateMatrix selectedRow] == 0)
+ {
+ [preset setObject:@"pfr" forKey:@"VideoFramerateMode"];
+ }
+ }
+
+
+
+ /* 2 Pass Encoding */
+ [preset setObject:[NSNumber numberWithInteger:[fVidTwoPassCheck state]] forKey:@"VideoTwoPass"];
+ /* Turbo 2 pass Encoding fVidTurboPassCheck*/
+ [preset setObject:[NSNumber numberWithInteger:[fVidTurboPassCheck state]] forKey:@"VideoTurboTwoPass"];
+}
+
+#pragma mark - Video
+
+- (IBAction) videoEncoderPopUpChanged: (id) sender
+{
+ /* if no valid encoder is selected, use the first one */
+ if ([fVidEncoderPopUp selectedItem] == nil)
+ {
+ [fVidEncoderPopUp selectItemAtIndex:0];
+ }
+
+ int videoEncoder = (int)[[fVidEncoderPopUp selectedItem] tag];
+
+ [self.fAdvancedOptions setHidden:YES];
+ /* If we are using x264 then show the x264 advanced panel and the x264 presets box */
+ if (videoEncoder == HB_VCODEC_X264)
+ {
+ [self.fAdvancedOptions setHidden:NO];
+
+ // show the x264 presets box
+ [fX264PresetsBox setHidden:NO];
+ }
+ else // we are FFmpeg (lavc) or Theora
+ {
+ [self.fAdvancedOptions setHidden:YES];
+ [fX264PresetsBox setHidden:YES];
+
+ // We Are Lavc
+ if ([[fVidEncoderPopUp selectedItem] tag] & HB_VCODEC_FFMPEG_MASK)
+ {
+ [self.fAdvancedOptions setLavcOptsEnabled:YES];
+ }
+ else /// We are Theora
+ {
+ [self.fAdvancedOptions setLavcOptsEnabled:NO];
+ }
+ }
+
+ [[NSNotificationCenter defaultCenter] postNotificationName:HBVideoEncoderChangedNotification object:self];
+
+ [self setupQualitySlider];
+ [self twoPassCheckboxChanged: sender];
+}
+
+
+- (IBAction) twoPassCheckboxChanged: (id) sender
+{
+ /* check to see if x264 is chosen */
+ if([[fVidEncoderPopUp selectedItem] tag] == HB_VCODEC_X264)
+ {
+ if( [fVidTwoPassCheck state] == NSOnState)
+ {
+ [fVidTurboPassCheck setHidden: NO];
+ }
+ else
+ {
+ [fVidTurboPassCheck setHidden: YES];
+ [fVidTurboPassCheck setState: NSOffState];
+ }
+ /* Make sure Two Pass is checked if Turbo is checked */
+ if( [fVidTurboPassCheck state] == NSOnState)
+ {
+ [fVidTwoPassCheck setState: NSOnState];
+ }
+ }
+ else
+ {
+ [fVidTurboPassCheck setHidden: YES];
+ [fVidTurboPassCheck setState: NSOffState];
+ }
+
+ /* We call method method to change UI to reflect whether a preset is used or not*/
+ [self.fHBController customSettingUsed: sender];
+}
+
+- (IBAction ) videoFrameRateChanged: (id) sender
+{
+ /* if no valid framerate is selected, use "Same as source" */
+ if ([fVidRatePopUp selectedItem] == nil)
+ {
+ [fVidRatePopUp selectItemAtIndex:0];
+ }
+
+ /* Hide and set the PFR Checkbox to OFF if we are set to Same as Source */
+ /* Depending on whether or not Same as source is selected modify the title for
+ * fFramerateVfrPfrCell*/
+ if ([fVidRatePopUp indexOfSelectedItem] == 0) // We are Same as Source
+ {
+ [fFramerateVfrPfrCell setTitle:@"Variable Framerate"];
+ }
+ else
+ {
+ [fFramerateVfrPfrCell setTitle:@"Peak Framerate (VFR)"];
+
+
+ }
+
+ /* We call method method to change UI to reflect whether a preset is used or not*/
+ [self.fHBController customSettingUsed: sender];
+}
+
+- (IBAction) videoMatrixChanged: (id) sender;
+{
+ /* We use the selectedCell: tag of the fVidQualityMatrix instead of selectedRow
+ * so that the order of the video controls can be switched around.
+ * Constant quality is 1 and Average bitrate is 0 for reference. */
+ bool bitrate, quality;
+ bitrate = quality = false;
+ if( [fVidQualityMatrix isEnabled] )
+ {
+ switch( [[fVidQualityMatrix selectedCell] tag] )
+ {
+ case 0:
+ bitrate = true;
+ break;
+ case 1:
+ quality = true;
+ break;
+ }
+ }
+
+ [fVidBitrateField setEnabled: bitrate];
+ [fVidQualitySlider setEnabled: quality];
+ [fVidQualityRFField setEnabled: quality];
+ [fVidQualityRFLabel setEnabled: quality];
+ [fVidTwoPassCheck setEnabled: !quality &&
+ [fVidQualityMatrix isEnabled]];
+ if( quality )
+ {
+ [fVidTwoPassCheck setState: NSOffState];
+ [fVidTurboPassCheck setHidden: YES];
+ [fVidTurboPassCheck setState: NSOffState];
+ }
+
+ [self qualitySliderChanged: sender];
+ [self.fHBController customSettingUsed: sender];
+}
+
+/* Use this method to setup the quality slider for cq/rf values depending on
+ * the video encoder selected.
+ */
+- (void) setupQualitySlider
+{
+ /*
+ * Get the current slider maxValue to check for a change in slider scale
+ * later so that we can choose a new similar value on the new slider scale
+ */
+ float previousMaxValue = [fVidQualitySlider maxValue];
+ float previousPercentOfSliderScale = ([fVidQualitySlider floatValue] /
+ ([fVidQualitySlider maxValue] -
+ [fVidQualitySlider minValue] + 1));
+ [fVidQualityRFLabel setStringValue:[NSString stringWithFormat:@"%s",
+ hb_video_quality_get_name((int)[[fVidEncoderPopUp
+ selectedItem] tag])]];
+ int direction;
+ float minValue, maxValue, granularity;
+ hb_video_quality_get_limits((int)[[fVidEncoderPopUp selectedItem] tag],
+ &minValue, &maxValue, &granularity, &direction);
+ if (granularity < 1.0f)
+ {
+ /*
+ * Encoders that allow fractional CQ values often have a low granularity
+ * which makes the slider hard to use, so use a value from preferences.
+ */
+ granularity = [[NSUserDefaults standardUserDefaults]
+ floatForKey:@"x264CqSliderFractional"];
+ }
+ [fVidQualitySlider setMinValue:minValue];
+ [fVidQualitySlider setMaxValue:maxValue];
+ [fVidQualitySlider setNumberOfTickMarks:((maxValue - minValue) *
+ (1.0f / granularity)) + 1];
+
+ /* check to see if we have changed slider scales */
+ if (previousMaxValue != maxValue)
+ {
+ /*
+ * if so, convert the old setting to the new scale as close as possible
+ * based on percentages
+ */
+ [fVidQualitySlider setFloatValue:((maxValue - minValue + 1.) *
+ (previousPercentOfSliderScale))];
+ }
+
+ [self qualitySliderChanged:nil];
+}
+
+- (IBAction) qualitySliderChanged: (id) sender
+{
+ /*
+ * Our constant quality slider is in a range based
+ * on each encoders qp/rf values. The range depends
+ * on the encoder. Also, the range is inverse of quality
+ * for all of the encoders *except* for theora
+ * (ie. as the "quality" goes up, the cq or rf value
+ * actually goes down). Since the IB sliders always set
+ * their max value at the right end of the slider, we
+ * will calculate the inverse, so as the slider floatValue
+ * goes up, we will show the inverse in the rf field
+ * so, the floatValue at the right for x264 would be 51
+ * and our rf field needs to show 0 and vice versa.
+ */
+ int direction;
+ float minValue, maxValue, granularity;
+ float inverseValue = ([fVidQualitySlider minValue] +
+ [fVidQualitySlider maxValue] -
+ [fVidQualitySlider floatValue]);
+ hb_video_quality_get_limits((int)[[fVidEncoderPopUp selectedItem] tag],
+ &minValue, &maxValue, &granularity, &direction);
+ if (!direction)
+ {
+ [fVidQualityRFField setStringValue:[NSString stringWithFormat:@"%.2f",
+ [fVidQualitySlider floatValue]]];
+ }
+ else
+ {
+ [fVidQualityRFField setStringValue:[NSString stringWithFormat:@"%.2f",
+ inverseValue]];
+ }
+ /* Show a warning if x264 and rf 0 which is lossless */
+ if ([[fVidEncoderPopUp selectedItem] tag] == HB_VCODEC_X264 && inverseValue == 0.0)
+ {
+ [fVidQualityRFField setStringValue:[NSString stringWithFormat:@"%.2f (Warning: Lossless)",
+ inverseValue]];
+ }
+
+ [self.fHBController customSettingUsed: sender];
+}
+
+#pragma mark - Video x264 Presets
+
+- (void) setupX264PresetsWidgets
+{
+ NSUInteger i;
+ // populate the preset system widgets via hb_video_encoder_get_* functions.
+ // store x264 preset names
+ const char* const *x264_presets = hb_video_encoder_get_presets(HB_VCODEC_X264);
+ NSMutableArray *tmp_array = [[NSMutableArray alloc] init];
+ for (i = 0; x264_presets[i] != NULL; i++)
+ {
+ [tmp_array addObject:[NSString stringWithUTF8String:x264_presets[i]]];
+ if (!strcasecmp(x264_presets[i], "medium"))
+ {
+ fX264MediumPresetIndex = i;
+ }
+ }
+ fX264PresetNames = [[NSArray alloc] initWithArray:tmp_array];
+ [tmp_array release];
+ // setup the x264 preset slider
+ [fX264PresetsSlider setMinValue:0];
+ [fX264PresetsSlider setMaxValue:[fX264PresetNames count]-1];
+ [fX264PresetsSlider setNumberOfTickMarks:[fX264PresetNames count]];
+ [fX264PresetsSlider setIntegerValue:fX264MediumPresetIndex];
+ [fX264PresetsSlider setTickMarkPosition:NSTickMarkAbove];
+ [fX264PresetsSlider setAllowsTickMarkValuesOnly:YES];
+ [self x264PresetsSliderChanged: nil];
+ // setup the x264 tune popup
+ [fX264TunePopUp removeAllItems];
+ [fX264TunePopUp addItemWithTitle: @"none"];
+ const char* const *x264_tunes = hb_video_encoder_get_tunes(HB_VCODEC_X264);
+ for (int i = 0; x264_tunes[i] != NULL; i++)
+ {
+ // we filter out "fastdecode" as we have a dedicated checkbox for it
+ if (strcasecmp(x264_tunes[i], "fastdecode") != 0)
+ {
+ [fX264TunePopUp addItemWithTitle: [NSString stringWithUTF8String:x264_tunes[i]]];
+ }
+ }
+ // the fastdecode checkbox is off by default
+ [fX264FastDecodeCheck setState: NSOffState];
+ // setup the h264 profile popup
+ [fX264ProfilePopUp removeAllItems];
+ const char* const *h264_profiles = hb_video_encoder_get_profiles(HB_VCODEC_X264);
+ for (int i = 0; h264_profiles[i] != NULL; i++)
+ {
+ [fX264ProfilePopUp addItemWithTitle: [NSString stringWithUTF8String:h264_profiles[i]]];
+ }
+ // setup the h264 level popup
+ [fX264LevelPopUp removeAllItems];
+ const char* const *h264_levels = hb_video_encoder_get_levels(HB_VCODEC_X264);
+ for (int i = 0; h264_levels[i] != NULL; i++)
+ {
+ [fX264LevelPopUp addItemWithTitle: [NSString stringWithUTF8String:h264_levels[i]]];
+ }
+ // clear the additional x264 options
+ [fDisplayX264PresetsAdditonalOptionsTextField setStringValue:@""];
+}
+
+- (void) enableX264Widgets: (bool) enable
+{
+ NSControl *controls[] =
+ {
+ fX264PresetsSlider, fX264PresetSliderLabel, fX264PresetSelectedTextField,
+ fX264TunePopUp, fX264TunePopUpLabel, fX264FastDecodeCheck,
+ fDisplayX264PresetsAdditonalOptionsTextField, fDisplayX264PresetsAdditonalOptionsLabel,
+ fX264ProfilePopUp, fX264ProfilePopUpLabel,
+ fX264LevelPopUp, fX264LevelPopUpLabel,
+ fDisplayX264PresetsUnparseTextField,
+ };
+
+ // check whether the x264 preset system and the advanced panel should be enabled
+ BOOL enable_x264_controls = (enable && [fX264UseAdvancedOptionsCheck state] == NSOffState);
+ BOOL enable_advanced_panel = (enable && [fX264UseAdvancedOptionsCheck state] == NSOnState);
+
+ // enable/disable the checkbox and advanced panel
+ [fX264UseAdvancedOptionsCheck setEnabled:enable];
+ [self.fAdvancedOptions enableUI:enable_advanced_panel];
+
+ // enable/disable the x264 preset system controls
+ for (unsigned i = 0; i < (sizeof(controls) / sizeof(NSControl*)); i++)
+ {
+ if ([[controls[i] className] isEqualToString: @"NSTextField"])
+ {
+ NSTextField *tf = (NSTextField*)controls[i];
+ if (![tf isBezeled])
+ {
+ [tf setTextColor:(enable_x264_controls ?
+ [NSColor controlTextColor] :
+ [NSColor disabledControlTextColor])];
+ continue;
+ }
+ }
+ [controls[i] setEnabled:enable_x264_controls];
+ }
+}
+
+- (IBAction) updateX264Widgets: (id) sender
+{
+ if ([fX264UseAdvancedOptionsCheck state] == NSOnState)
+ {
+ /*
+ * we are using or switching to the advanced panel
+ *
+ * if triggered by selectPreset or applyQueueSettingToMainWindow,
+ * the options string will have been specified explicitly - leave it.
+ *
+ * if triggered by the advanced panel on/off checkbox, set the options
+ * string to the value of the unparsed x264 preset system string.
+ */
+ if (sender == fX264UseAdvancedOptionsCheck)
+ {
+ if (fX264PresetsUnparsedUTF8String != NULL)
+ {
+ [self.fAdvancedOptions setOptions:
+ [NSString stringWithUTF8String:fX264PresetsUnparsedUTF8String]];
+ }
+ else
+ {
+ [self.fAdvancedOptions setOptions:@""];
+ }
+ }
+ }
+ // enable/disable, populate and update the various widgets
+ [self enableX264Widgets: YES];
+ [self x264PresetsSliderChanged:nil];
+ [self.fAdvancedOptions X264AdvancedOptionsSet: nil];
+}
+
+#pragma mark -
+#pragma mark x264 preset system
+
+- (NSString *) x264Preset
+{
+ return (NSString *)[fX264PresetNames objectAtIndex:[fX264PresetsSlider intValue]];
+}
+
+- (NSString *) x264Tune
+{
+ NSString *x264Tune = @"";
+ if ([fX264TunePopUp indexOfSelectedItem])
+ {
+ x264Tune = [x264Tune stringByAppendingString:
+ [fX264TunePopUp titleOfSelectedItem]];
+ }
+ if ([fX264FastDecodeCheck state])
+ {
+ if ([x264Tune length])
+ {
+ x264Tune = [x264Tune stringByAppendingString: @","];
+ }
+ x264Tune = [x264Tune stringByAppendingString: @"fastdecode"];
+ }
+ return x264Tune;
+}
+
+- (NSString*) x264OptionExtra
+{
+ return [fDisplayX264PresetsAdditonalOptionsTextField stringValue];
+}
+
+- (NSString*) h264Profile
+{
+ if ([fX264ProfilePopUp indexOfSelectedItem])
+ {
+ return [fX264ProfilePopUp titleOfSelectedItem];
+ }
+ return @"";
+}
+
+- (NSString*) h264Level
+{
+ if ([fX264LevelPopUp indexOfSelectedItem])
+ {
+ return [fX264LevelPopUp titleOfSelectedItem];
+ }
+ return @"";
+}
+
+- (void) setX264Preset: (NSString*)x264Preset
+{
+ if (x264Preset)
+ {
+ NSString *name;
+ NSEnumerator *enumerator = [fX264PresetNames objectEnumerator];
+ while ((name = (NSString *)[enumerator nextObject]))
+ {
+ if ([name isEqualToString:x264Preset])
+ {
+ [fX264PresetsSlider setIntegerValue:
+ [fX264PresetNames indexOfObject:name]];
+ return;
+ }
+ }
+ }
+ [fX264PresetsSlider setIntegerValue:fX264MediumPresetIndex];
+}
+
+- (void) setX264Tune: (NSString*)x264Tune
+{
+ if (!x264Tune)
+ {
+ [fX264TunePopUp selectItemAtIndex:0];
+ [fX264FastDecodeCheck setState:NSOffState];
+ return;
+ }
+ // handle fastdecode
+ if ([x264Tune rangeOfString:@"fastdecode"].location != NSNotFound)
+ {
+ [fX264FastDecodeCheck setState:NSOnState];
+ }
+ else
+ {
+ [fX264FastDecodeCheck setState:NSOffState];
+ }
+ // filter out fastdecode
+ x264Tune = [x264Tune stringByReplacingOccurrencesOfString:@","
+ withString:@""];
+ x264Tune = [x264Tune stringByReplacingOccurrencesOfString:@"fastdecode"
+ withString:@""];
+ // set the tune
+ [fX264TunePopUp selectItemWithTitle:x264Tune];
+ // fallback
+ if ([fX264TunePopUp indexOfSelectedItem] == -1)
+ {
+ [fX264TunePopUp selectItemAtIndex:0];
+ }
+}
+
+- (void) setX264OptionExtra: (NSString*)x264OptionExtra
+{
+ if (!x264OptionExtra)
+ {
+ [fDisplayX264PresetsAdditonalOptionsTextField setStringValue:@""];
+ return;
+ }
+ [fDisplayX264PresetsAdditonalOptionsTextField setStringValue:x264OptionExtra];
+}
+
+- (void) setH264Profile: (NSString*)h264Profile
+{
+ if (!h264Profile)
+ {
+ [fX264ProfilePopUp selectItemAtIndex:0];
+ return;
+ }
+ // set the profile
+ [fX264ProfilePopUp selectItemWithTitle:h264Profile];
+ // fallback
+ if ([fX264ProfilePopUp indexOfSelectedItem] == -1)
+ {
+ [fX264ProfilePopUp selectItemAtIndex:0];
+ }
+}
+
+- (void) setH264Level: (NSString*)h264Level
+{
+ if (!h264Level)
+ {
+ [fX264LevelPopUp selectItemAtIndex:0];
+ return;
+ }
+ // set the level
+ [fX264LevelPopUp selectItemWithTitle:h264Level];
+ // fallback
+ if ([fX264LevelPopUp indexOfSelectedItem] == -1)
+ {
+ [fX264LevelPopUp selectItemAtIndex:0];
+ }
+}
+
+
+- (IBAction) x264PresetsSliderChanged: (id) sender
+{
+ // we assume the preset names and slider were setup properly
+ [fX264PresetSelectedTextField setStringValue: [self x264Preset]];
+ [self x264PresetsChangedDisplayExpandedOptions:nil];
+
+}
+
+/* This is called everytime a x264 widget in the video tab is changed to
+ display the expanded options in a text field via outlet fDisplayX264PresetsUnparseTextField
+ */
+- (IBAction) x264PresetsChangedDisplayExpandedOptions: (id) sender
+
+{
+ /* API reference:
+ *
+ * char * hb_x264_param_unparse(const char *x264_preset,
+ * const char *x264_tune,
+ * const char *x264_encopts,
+ * const char *h264_profile,
+ * const char *h264_level,
+ * int width, int height);
+ */
+ NSString *tmpString;
+ const char *x264_preset = [[self x264Preset] UTF8String];
+ const char *x264_tune = NULL;
+ const char *advanced_opts = NULL;
+ const char *h264_profile = NULL;
+ const char *h264_level = NULL;
+ int width = 1;
+ int height = 1;
+ // prepare the tune, advanced options, profile and level
+ if ([(tmpString = [self x264Tune]) length])
+ {
+ x264_tune = [tmpString UTF8String];
+ }
+ if ([(tmpString = [self x264OptionExtra]) length])
+ {
+ advanced_opts = [tmpString UTF8String];
+ }
+ if ([(tmpString = [self h264Profile]) length])
+ {
+ h264_profile = [tmpString UTF8String];
+ }
+ if ([(tmpString = [self h264Level]) length])
+ {
+ h264_level = [tmpString UTF8String];
+ }
+ // width and height must be non-zero
+ if (_fX264PresetsWidthForUnparse && _fX264PresetsHeightForUnparse)
+ {
+ width = (int)_fX264PresetsWidthForUnparse;
+ height = (int)_fX264PresetsHeightForUnparse;
+ }
+ // free the previous unparsed string
+ free(fX264PresetsUnparsedUTF8String);
+ // now, unparse
+ fX264PresetsUnparsedUTF8String = hb_x264_param_unparse(x264_preset,
+ x264_tune,
+ advanced_opts,
+ h264_profile,
+ h264_level,
+ width, height);
+ // update the text field
+ if (fX264PresetsUnparsedUTF8String != NULL)
+ {
+ [fDisplayX264PresetsUnparseTextField setStringValue:
+ [NSString stringWithFormat:@"x264 Unparse: %s",
+ fX264PresetsUnparsedUTF8String]];
+ }
+ else
+ {
+ [fDisplayX264PresetsUnparseTextField setStringValue:@"x264 Unparse:"];
+ }
+}
+
+@end