1 /* $Id: Controller.mm,v 1.79 2005/11/04 19:41:32 titer Exp $
3 This file is part of the HandBrake source code.
4 Homepage: <http://handbrake.m0k.org/>.
5 It may be used under the terms of the GNU General Public License. */
7 #include "Controller.h"
8 #include "a52dec/a52.h"
9 #import "HBOutputPanelController.h"
11 #define _(a) NSLocalizedString(a,NULL)
17 static int FormatSettings[3][4] =
18 { { HB_MUX_MP4 | HB_VCODEC_FFMPEG | HB_ACODEC_FAAC,
19 HB_MUX_MP4 | HB_VCODEC_X264 | HB_ACODEC_FAAC,
22 { HB_MUX_AVI | HB_VCODEC_FFMPEG | HB_ACODEC_LAME,
23 HB_MUX_AVI | HB_VCODEC_FFMPEG | HB_ACODEC_AC3,
24 HB_MUX_AVI | HB_VCODEC_X264 | HB_ACODEC_LAME,
25 HB_MUX_AVI | HB_VCODEC_X264 | HB_ACODEC_AC3 },
26 { HB_MUX_OGM | HB_VCODEC_FFMPEG | HB_ACODEC_VORBIS,
27 HB_MUX_OGM | HB_VCODEC_FFMPEG | HB_ACODEC_LAME,
31 /*******************************
32 * HBController implementation *
33 *******************************/
34 @implementation HBController
40 outputPanel = [[HBOutputPanelController alloc] init];
44 - (void) applicationDidFinishLaunching: (NSNotification *) notification
50 int debugLevel = [[NSUserDefaults standardUserDefaults] boolForKey:@"ShowVerboseOutput"] ? HB_DEBUG_ALL : HB_DEBUG_NONE;
51 fHandle = hb_init(debugLevel, [[NSUserDefaults standardUserDefaults] boolForKey:@"CheckForUpdates"]);
53 // Set the Growl Delegate
54 HBController *hbGrowlDelegate = [[HBController alloc] init];
55 [GrowlApplicationBridge setGrowlDelegate: hbGrowlDelegate];
56 /* Init others controllers */
57 [fScanController SetHandle: fHandle];
58 [fPictureController SetHandle: fHandle];
59 [fQueueController SetHandle: fHandle];
61 fChapterTitlesDelegate = [[ChapterTitles alloc] init];
62 [fChapterTable setDataSource:fChapterTitlesDelegate];
64 /* Call UpdateUI every 2/10 sec */
65 [[NSRunLoop currentRunLoop] addTimer: [NSTimer
66 scheduledTimerWithTimeInterval: 0.2 target: self
67 selector: @selector( UpdateUI: ) userInfo: NULL repeats: FALSE]
68 forMode: NSModalPanelRunLoopMode];
70 if( ( build = hb_check_update( fHandle, &version ) ) > -1 )
72 /* Update available - tell the user */
74 NSBeginInformationalAlertSheet( _( @"Update is available" ),
75 _( @"Go get it!" ), _( @"Discard" ), NULL, fWindow, self,
76 @selector( UpdateAlertDone:returnCode:contextInfo: ),
77 NULL, NULL, [NSString stringWithFormat:
78 _( @"HandBrake %s (build %d) is now available for download." ),
84 /* Show scan panel ASAP */
85 [self performSelectorOnMainThread: @selector(ShowScanPanel:)
86 withObject: NULL waitUntilDone: NO];
89 - (NSApplicationTerminateReply) applicationShouldTerminate:
92 if( [[fRipButton title] isEqualToString: _( @"Cancel" )] )
95 return NSTerminateCancel;
97 return NSTerminateNow;
100 - (void)applicationWillTerminate:(NSNotification *)aNotification
102 [outputPanel release];
107 - (void) awakeFromNib
111 [self TranslateStrings];
114 //[self registrationDictionaryForGrowl];
115 /* Init User Presets .plist */
116 /* We declare the default NSFileManager into fileManager */
117 NSFileManager * fileManager = [NSFileManager defaultManager];
118 //presetPrefs = [[NSUserDefaults standardUserDefaults] retain];
119 /* we set the files and support paths here */
120 AppSupportDirectory = @"~/Library/Application Support/HandBrake";
121 AppSupportDirectory = [AppSupportDirectory stringByExpandingTildeInPath];
123 UserPresetsFile = @"~/Library/Application Support/HandBrake/UserPresets.plist";
124 UserPresetsFile = [UserPresetsFile stringByExpandingTildeInPath];
126 x264ProfilesFile = @"~/Library/Application Support/HandBrake/x264Profiles.plist";
127 x264ProfilesFile = [x264ProfilesFile stringByExpandingTildeInPath];
128 /* We check for the app support directory for media fork */
129 if ([fileManager fileExistsAtPath:AppSupportDirectory] == 0)
131 // If it doesnt exist yet, we create it here
132 [fileManager createDirectoryAtPath:AppSupportDirectory attributes:nil];
134 // We check for the presets.plist here
136 if ([fileManager fileExistsAtPath:UserPresetsFile] == 0)
139 [fileManager createFileAtPath:UserPresetsFile contents:nil attributes:nil];
142 // We check for the x264profiles.plist here
144 if ([fileManager fileExistsAtPath:x264ProfilesFile] == 0)
147 [fileManager createFileAtPath:x264ProfilesFile contents:nil attributes:nil];
151 UserPresetsFile = @"~/Library/Application Support/HandBrake/UserPresets.plist";
152 UserPresetsFile = [[UserPresetsFile stringByExpandingTildeInPath]retain];
154 UserPresets = [[NSMutableArray alloc] initWithContentsOfFile:UserPresetsFile];
155 if (nil == UserPresets)
157 UserPresets = [[NSMutableArray alloc] init];
158 [self AddFactoryPresets:NULL];
160 /* Show/Dont Show Presets drawer upon launch based
161 on user preference DefaultPresetsDrawerShow*/
162 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPresetsDrawerShow"] > 0)
164 [fPresetDrawer open];
170 [fDstFormatPopUp removeAllItems];
171 [fDstFormatPopUp addItemWithTitle: _( @"MP4 file" )];
172 [fDstFormatPopUp addItemWithTitle: _( @"AVI file" )];
173 [fDstFormatPopUp addItemWithTitle: _( @"OGM file" )];
174 [fDstFormatPopUp selectItemAtIndex: 0];
176 [self FormatPopUpChanged: NULL];
177 /* We enable the create chapters checkbox here since we are .mp4 */
178 [fCreateChapterMarkers setEnabled: YES];
179 if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultChapterMarkers"] > 0)
181 [fCreateChapterMarkers setState: NSOnState];
183 [fDstFile2Field setStringValue: [NSString stringWithFormat:
184 @"%@/Desktop/Movie.mp4", NSHomeDirectory()]];
187 [fVidEncoderPopUp removeAllItems];
188 [fVidEncoderPopUp addItemWithTitle: @"FFmpeg"];
189 [fVidEncoderPopUp addItemWithTitle: @"XviD"];
192 [fVidTargetSizeField setIntValue: 700];
193 [fVidBitrateField setIntValue: 1000];
195 [fVidQualityMatrix selectCell: fVidBitrateCell];
196 [self VideoMatrixChanged: NULL];
198 /* Video framerate */
199 [fVidRatePopUp removeAllItems];
200 [fVidRatePopUp addItemWithTitle: _( @"Same as source" )];
201 for( int i = 0; i < hb_video_rates_count; i++ )
203 [fVidRatePopUp addItemWithTitle:
204 [NSString stringWithCString: hb_video_rates[i].string]];
206 [fVidRatePopUp selectItemAtIndex: 0];
208 /* Picture Settings */
209 [fPicLabelPAROutp setStringValue: @""];
210 [fPicLabelPAROutputX setStringValue: @""];
211 [fPicSettingPARWidth setStringValue: @""];
212 [fPicSettingPARHeight setStringValue: @""];
215 [fAudBitratePopUp removeAllItems];
216 for( int i = 0; i < hb_audio_bitrates_count; i++ )
218 [fAudBitratePopUp addItemWithTitle:
219 [NSString stringWithCString: hb_audio_bitrates[i].string]];
221 [fAudBitratePopUp selectItemAtIndex: hb_audio_bitrates_default];
223 /* Audio samplerate */
224 [fAudRatePopUp removeAllItems];
225 for( int i = 0; i < hb_audio_rates_count; i++ )
227 [fAudRatePopUp addItemWithTitle:
228 [NSString stringWithCString: hb_audio_rates[i].string]];
230 [fAudRatePopUp selectItemAtIndex: hb_audio_rates_default];
233 [fStatusField setStringValue: @""];
236 [fPauseButton setEnabled: NO];
237 [fRipButton setEnabled: NO];
243 // register a test notification and make
244 // it enabled by default
245 #define SERVICE_NAME @"Encode Done"
246 - (NSDictionary *)registrationDictionaryForGrowl
248 NSDictionary *registrationDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
249 [NSArray arrayWithObjects:SERVICE_NAME,nil], GROWL_NOTIFICATIONS_ALL,
250 [NSArray arrayWithObjects:SERVICE_NAME,nil], GROWL_NOTIFICATIONS_DEFAULT,
253 return registrationDictionary;
255 - (void) TranslateStrings
257 [fSrcDVD1Field setStringValue: _( @"DVD:" )];
258 [fSrcTitleField setStringValue: _( @"Title:" )];
259 [fSrcChapterField setStringValue: _( @"Chapters:" )];
260 [fSrcChapterToField setStringValue: _( @"to" )];
261 [fSrcDuration1Field setStringValue: _( @"Duration:" )];
263 [fDstFormatField setStringValue: _( @"File format:" )];
264 [fDstCodecsField setStringValue: _( @"Codecs:" )];
265 [fDstFile1Field setStringValue: _( @"File:" )];
266 [fDstBrowseButton setTitle: _( @"Browse" )];
268 [fVidRateField setStringValue: _( @"Framerate (fps):" )];
269 [fVidEncoderField setStringValue: _( @"Encoder:" )];
270 [fVidQualityField setStringValue: _( @"Quality:" )];
273 /***********************************************************************
275 ***********************************************************************
276 * Shows a progression bar on the dock icon, filled according to
277 * 'progress' (0.0 <= progress <= 1.0).
278 * Called with progress < 0.0 or progress > 1.0, restores the original
280 **********************************************************************/
281 - (void) UpdateDockIcon: (float) progress
285 NSBitmapImageRep * bmp;
287 uint32_t black = htonl( 0x000000FF );
288 uint32_t red = htonl( 0xFF0000FF );
289 uint32_t white = htonl( 0xFFFFFFFF );
290 int row_start, row_end;
293 /* Get application original icon */
294 icon = [NSImage imageNamed: @"NSApplicationIcon"];
296 if( progress < 0.0 || progress > 1.0 )
298 [NSApp setApplicationIconImage: icon];
302 /* Get it in a raw bitmap form */
303 tiff = [icon TIFFRepresentationUsingCompression:
304 NSTIFFCompressionNone factor: 1.0];
305 bmp = [NSBitmapImageRep imageRepWithData: tiff];
307 /* Draw the progression bar */
308 /* It's pretty simple (ugly?) now, but I'm no designer */
310 row_start = 3 * (int) [bmp size].height / 4;
311 row_end = 7 * (int) [bmp size].height / 8;
313 for( i = row_start; i < row_start + 2; i++ )
315 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
316 for( j = 0; j < (int) [bmp size].width; j++ )
321 for( i = row_start + 2; i < row_end - 2; i++ )
323 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
326 for( j = 2; j < (int) [bmp size].width - 2; j++ )
328 if( j < 2 + (int) ( ( [bmp size].width - 4.0 ) * progress ) )
340 for( i = row_end - 2; i < row_end; i++ )
342 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
343 for( j = 0; j < (int) [bmp size].width; j++ )
349 /* Now update the dock icon */
350 tiff = [bmp TIFFRepresentationUsingCompression:
351 NSTIFFCompressionNone factor: 1.0];
352 icon = [[NSImage alloc] initWithData: tiff];
353 [NSApp setApplicationIconImage: icon];
357 - (void) UpdateUI: (NSTimer *) timer
361 hb_get_state( fHandle, &s );
368 case HB_STATE_SCANNING:
369 [fScanController UpdateUI: &s];
372 #define p s.param.scandone
373 case HB_STATE_SCANDONE:
377 int indxpri=0; // Used to search the longuest title (default in combobox)
378 int longuestpri=0; // Used to search the longuest title (default in combobox)
380 [fScanController UpdateUI: &s];
382 list = hb_get_titles( fHandle );
384 if( !hb_list_count( list ) )
390 [fSrcTitlePopUp removeAllItems];
391 for( int i = 0; i < hb_list_count( list ); i++ )
393 title = (hb_title_t *) hb_list_item( list, i );
394 /*Set DVD Name at top of window*/
395 [fSrcDVD2Field setStringValue: [NSString
396 stringWithUTF8String: title->name]];
398 /* Use the dvd name in the default output field here
399 May want to add code to remove blank spaces for some dvd names*/
400 /* Check to see if the last destination has been set,use if so, if not, use Desktop */
401 if ([[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"])
403 [fDstFile2Field setStringValue: [NSString stringWithFormat:
404 @"%@/%@.mp4", [[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"],[NSString
405 stringWithUTF8String: title->name]]];
409 [fDstFile2Field setStringValue: [NSString stringWithFormat:
410 @"%@/Desktop/%@.mp4", NSHomeDirectory(),[NSString
411 stringWithUTF8String: title->name]]];
415 if (longuestpri < title->hours*60*60 + title->minutes *60 + title->seconds)
417 longuestpri=title->hours*60*60 + title->minutes *60 + title->seconds;
422 int format = [fDstFormatPopUp indexOfSelectedItem];
428 /*Get Default MP4 File Extension for mpeg4 (.mp4 or .m4v) from prefs*/
429 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultMpegName"] > 0)
447 NSString * string = [fDstFile2Field stringValue];
448 /* Add/replace File Output name to the correct extension*/
449 if( [string characterAtIndex: [string length] - 4] == '.' )
451 [fDstFile2Field setStringValue: [NSString stringWithFormat:
452 @"%@.%s", [string substringToIndex: [string length] - 4],
457 [fDstFile2Field setStringValue: [NSString stringWithFormat:
458 @"%@.%s", string, ext]];
462 [fSrcTitlePopUp addItemWithTitle: [NSString
463 stringWithFormat: @"%d - %02dh%02dm%02ds",
464 title->index, title->hours, title->minutes,
468 // Select the longuest title
469 [fSrcTitlePopUp selectItemAtIndex: indxpri];
470 /* We set the Settings Display to "Default" here
471 until we get default presets implemented */
472 [fPresetSelectedDisplay setStringValue: @"Default"];
474 [self TitlePopUpChanged: NULL];
475 [self EnableUI: YES];
476 [fPauseButton setEnabled: NO];
477 [fRipButton setEnabled: YES];
482 #define p s.param.working
483 case HB_STATE_WORKING:
485 float progress_total;
486 NSMutableString * string;
488 /* Update text field */
489 string = [NSMutableString stringWithFormat:
490 _( @"Encoding: task %d of %d, %.2f %%" ),
491 p.job_cur, p.job_count, 100.0 * p.progress];
494 [string appendFormat:
495 _( @" (%.2f fps, avg %.2f fps, ETA %02dh%02dm%02ds)" ),
496 p.rate_cur, p.rate_avg, p.hours, p.minutes, p.seconds];
498 [fStatusField setStringValue: string];
501 progress_total = ( p.progress + p.job_cur - 1 ) / p.job_count;
502 [fRipIndicator setIndeterminate: NO];
503 [fRipIndicator setDoubleValue: 100.0 * progress_total];
505 /* Update dock icon */
506 [self UpdateDockIcon: progress_total];
508 [fPauseButton setEnabled: YES];
509 [fPauseButton setTitle: _( @"Pause" )];
510 [fRipButton setEnabled: YES];
511 [fRipButton setTitle: _( @"Cancel" )];
516 #define p s.param.muxing
517 case HB_STATE_MUXING:
519 NSMutableString * string;
521 /* Update text field */
522 string = [NSMutableString stringWithFormat:
524 [fStatusField setStringValue: string];
527 [fRipIndicator setIndeterminate: YES];
528 [fRipIndicator startAnimation: nil];
530 /* Update dock icon */
531 [self UpdateDockIcon: 1.0];
533 [fPauseButton setEnabled: YES];
534 [fPauseButton setTitle: _( @"Pause" )];
535 [fRipButton setEnabled: YES];
536 [fRipButton setTitle: _( @"Cancel" )];
541 case HB_STATE_PAUSED:
542 [fStatusField setStringValue: _( @"Paused" )];
543 [fPauseButton setEnabled: YES];
544 [fPauseButton setTitle: _( @"Resume" )];
545 [fRipButton setEnabled: YES];
546 [fRipButton setTitle: _( @"Cancel" )];
549 case HB_STATE_WORKDONE:
551 //[self EnableUI: YES];
552 [fStatusField setStringValue: _( @"Done." )];
553 [fRipIndicator setIndeterminate: NO];
554 [fRipIndicator setDoubleValue: 0.0];
555 [fRipButton setTitle: _( @"Start" )];
557 /* Restore dock icon */
558 [self UpdateDockIcon: -1.0];
560 [fPauseButton setEnabled: NO];
561 [fPauseButton setTitle: _( @"Pause" )];
562 [fRipButton setEnabled: YES];
563 [fRipButton setTitle: _( @"Start" )];
567 while( ( job = hb_job( fHandle, 0 ) ) )
569 hb_rem( fHandle, job );
572 if (fEncodeState != 2) // if the encode has not been cancelled
574 /* Lets alert the user that the encode has finished */
575 /*Growl Notification*/
576 [self showGrowlDoneNotification: NULL];
577 /*On Screen Notification*/
580 status = NSRunAlertPanel(@"Put down that cocktail...",@"your HandBrake encode is done!", @"OK", nil, nil);
581 //[NSApp requestUserAttention:NSInformationalRequest];
582 [NSApp requestUserAttention:NSCriticalRequest];
583 if ( status == NSAlertDefaultReturn )
585 [self EnableUI: YES];
590 [self EnableUI: YES];
596 /* Lets show the queue status
597 here in the main window*/
599 int count = hb_count( fHandle );
602 [fQueueStatus setStringValue: [NSString stringWithFormat:
603 @"%d task%s in the queue",
604 count, ( count > 1 ) ? "s" : ""]];
608 [fQueueStatus setStringValue: @""];
611 [[NSRunLoop currentRunLoop] addTimer: [NSTimer
612 scheduledTimerWithTimeInterval: 0.2 target: self
613 selector: @selector( UpdateUI: ) userInfo: NULL repeats: FALSE]
614 forMode: NSModalPanelRunLoopMode];
617 -(IBAction)showGrowlDoneNotification:(id)sender
621 [GrowlApplicationBridge
622 notifyWithTitle:@"Put down that cocktail..."
623 description:@"your HandBrake encode is done!"
624 notificationName:SERVICE_NAME
631 - (void) EnableUI: (bool) b
633 NSControl * controls[] =
634 { fSrcDVD1Field, fSrcDVD2Field, fSrcTitleField, fSrcTitlePopUp,
635 fSrcChapterField, fSrcChapterStartPopUp, fSrcChapterToField,
636 fSrcChapterEndPopUp, fSrcDuration1Field, fSrcDuration2Field,
637 fDstFormatField, fDstFormatPopUp, fDstCodecsField,
638 fDstCodecsPopUp, fDstFile1Field, fDstFile2Field,
639 fDstBrowseButton, fVidRateField, fVidRatePopUp,
640 fVidEncoderField, fVidEncoderPopUp, fVidQualityField,
641 fVidQualityMatrix, fVidGrayscaleCheck, fSubField, fSubPopUp,
642 fAudLang1Field, fAudLang1PopUp, fAudLang2Field, fAudLang2PopUp,
643 fAudTrack1MixLabel, fAudTrack1MixPopUp, fAudTrack2MixLabel, fAudTrack2MixPopUp,
644 fAudRateField, fAudRatePopUp, fAudBitrateField,
645 fAudBitratePopUp, fPictureButton,fQueueStatus,
646 fPicSrcWidth,fPicSrcHeight,fPicSettingWidth,fPicSettingHeight,
647 fPicSettingARkeep,fPicSettingDeinterlace,fPicSettingARkeepDsply,
648 fPicSettingDeinterlaceDsply,fPicLabelSettings,fPicLabelSrc,fPicLabelOutp,
649 fPicLabelAr,fPicLabelDeinter,fPicLabelSrcX,fPicLabelOutputX,
650 fPicLabelPAROutp,fPicLabelPAROutputX,fPicSettingPARWidth,fPicSettingPARHeight,
651 fPicSettingPARDsply,fPicLabelAnamorphic,tableView,fPresetsAdd,fPresetsDelete,
652 fCreateChapterMarkers,fX264optViewTitleLabel,fDisplayX264Options,fDisplayX264OptionsLabel,fX264optBframesLabel,
653 fX264optBframesPopUp,fX264optRefLabel,fX264optRefPopUp,fX264optNfpskipLabel,fX264optNfpskipSwitch,
654 fX264optNodctdcmtLabel,fX264optNodctdcmtSwitch,fX264optSubmeLabel,fX264optSubmePopUp,
655 fX264optTrellisLabel,fX264optTrellisPopUp,fX264optMixedRefsLabel,fX264optMixedRefsSwitch,
656 fX264optMotionEstLabel,fX264optMotionEstPopUp,fX264optMERangeLabel,fX264optMERangePopUp,
657 fX264optWeightBLabel,fX264optWeightBSwitch,fX264optBRDOLabel,fX264optBRDOSwitch,
658 fX264optBPyramidLabel,fX264optBPyramidSwitch,fX264optBiMELabel,fX264optBiMESwitch,
659 fX264optDirectPredLabel,fX264optDirectPredPopUp,fX264optDeblockLabel,
660 fX264optAlphaDeblockPopUp,fX264optBetaDeblockPopUp};
663 i < sizeof( controls ) / sizeof( NSControl * ); i++ )
665 if( [[controls[i] className] isEqualToString: @"NSTextField"] )
667 NSTextField * tf = (NSTextField *) controls[i];
668 if( ![tf isBezeled] )
670 [tf setTextColor: b ? [NSColor controlTextColor] :
671 [NSColor disabledControlTextColor]];
675 [controls[i] setEnabled: b];
681 /* if we're enabling the interface, check if the audio mixdown controls need to be enabled or not */
682 /* these will have been enabled by the mass control enablement above anyway, so we're sense-checking it here */
683 [self SetEnabledStateOfAudioMixdownControls: NULL];
687 [tableView setEnabled: NO];
691 [self VideoMatrixChanged: NULL];
694 - (IBAction) ShowScanPanel: (id) sender
696 [fScanController Show];
699 - (BOOL) windowShouldClose: (id) sender
701 /* Stop the application when the user closes the window */
702 [NSApp terminate: self];
706 - (IBAction) VideoMatrixChanged: (id) sender;
708 bool target, bitrate, quality;
710 target = bitrate = quality = false;
711 if( [fVidQualityMatrix isEnabled] )
713 switch( [fVidQualityMatrix selectedRow] )
726 [fVidTargetSizeField setEnabled: target];
727 [fVidBitrateField setEnabled: bitrate];
728 [fVidQualitySlider setEnabled: quality];
729 [fVidTwoPassCheck setEnabled: !quality &&
730 [fVidQualityMatrix isEnabled]];
733 [fVidTwoPassCheck setState: NSOffState];
736 [self QualitySliderChanged: sender];
737 [self CalculateBitrate: sender];
738 [self CustomSettingUsed: sender];
741 - (IBAction) QualitySliderChanged: (id) sender
743 [fVidConstantCell setTitle: [NSString stringWithFormat:
744 _( @"Constant quality: %.0f %%" ), 100.0 *
745 [fVidQualitySlider floatValue]]];
746 [self CustomSettingUsed: sender];
749 - (IBAction) BrowseFile: (id) sender
751 /* Open a panel to let the user choose and update the text field */
752 NSSavePanel * panel = [NSSavePanel savePanel];
753 /* We get the current file name and path from the destination field here */
754 [panel beginSheetForDirectory: [[fDstFile2Field stringValue] stringByDeletingLastPathComponent] file: [[fDstFile2Field stringValue] lastPathComponent]
755 modalForWindow: fWindow modalDelegate: self
756 didEndSelector: @selector( BrowseFileDone:returnCode:contextInfo: )
760 - (void) BrowseFileDone: (NSSavePanel *) sheet
761 returnCode: (int) returnCode contextInfo: (void *) contextInfo
763 if( returnCode == NSOKButton )
765 [fDstFile2Field setStringValue: [sheet filename]];
770 - (IBAction) ShowPicturePanel: (id) sender
772 hb_list_t * list = hb_get_titles( fHandle );
773 hb_title_t * title = (hb_title_t *) hb_list_item( list,
774 [fSrcTitlePopUp indexOfSelectedItem] );
776 /* Resize the panel */
778 newSize.width = 246 + title->width;
779 newSize.height = 80 + title->height;
780 [fPicturePanel setContentSize: newSize];
782 [fPictureController SetTitle: title];
784 [NSApp beginSheet: fPicturePanel modalForWindow: fWindow
785 modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
786 [NSApp runModalForWindow: fPicturePanel];
787 [NSApp endSheet: fPicturePanel];
788 [fPicturePanel orderOut: self];
789 [self CalculatePictureSizing: sender];
792 - (IBAction) ShowQueuePanel: (id) sender
794 /* Update the OutlineView */
795 [fQueueController Update: sender];
798 [NSApp beginSheet: fQueuePanel modalForWindow: fWindow
799 modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
800 [NSApp runModalForWindow: fQueuePanel];
801 [NSApp endSheet: fQueuePanel];
802 [fQueuePanel orderOut: self];
807 hb_list_t * list = hb_get_titles( fHandle );
808 hb_title_t * title = (hb_title_t *) hb_list_item( list,
809 [fSrcTitlePopUp indexOfSelectedItem] );
810 hb_job_t * job = title->job;
813 /* Chapter selection */
814 job->chapter_start = [fSrcChapterStartPopUp indexOfSelectedItem] + 1;
815 job->chapter_end = [fSrcChapterEndPopUp indexOfSelectedItem] + 1;
817 /* Format and codecs */
818 int format = [fDstFormatPopUp indexOfSelectedItem];
819 int codecs = [fDstCodecsPopUp indexOfSelectedItem];
820 job->mux = FormatSettings[format][codecs] & HB_MUX_MASK;
821 job->vcodec = FormatSettings[format][codecs] & HB_VCODEC_MASK;
822 job->acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
823 /* We set the chapter marker extraction here based on the format being
824 mpeg4 and the checkbox being checked */
825 if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [fCreateChapterMarkers state] == NSOnState)
827 job->chapter_markers = 1;
831 job->chapter_markers = 0;
833 if( ( job->vcodec & HB_VCODEC_FFMPEG ) &&
834 [fVidEncoderPopUp indexOfSelectedItem] > 0 )
836 job->vcodec = HB_VCODEC_XVID;
838 if( job->vcodec & HB_VCODEC_X264 )
840 if ([fVidEncoderPopUp indexOfSelectedItem] > 0 )
842 /* Just use new Baseline Level 3.0
843 Lets Deprecate Baseline Level 1.3*/
844 job->h264_level = 30;
845 job->mux = HB_MUX_IPOD;
846 /* move sanity check for iPod Encoding here */
847 job->pixel_ratio = 0 ;
851 /* Set this flag to switch from Constant Quantizer(default) to Constant Rate Factor Thanks jbrjake
852 Currently only used with Constant Quality setting*/
853 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultCrf"] > 0 && [fVidQualityMatrix selectedRow] == 2)
855 /* Can only be used with svn rev >= 89 */
859 /* Below Sends x264 options to the core library if x264 is selected*/
860 /* First we look to see if a user preset has been selected that contains a x264 optional string CurUserPresetChosenNum = nil */
861 //if (curUserPresetChosenNum != nil)
864 /* Lets use this as per Nyx, Thanks Nyx! fDisplayX264Options*/
865 job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */
866 strcpy(job->x264opts, [[fDisplayX264Options stringValue] UTF8String]);
867 //strcpy(job->x264opts, [[chosenPreset valueForKey:@"x264Option"] UTF8String]);
868 //job->x264opts = [[chosenPreset valueForKey:@"x264Option"] cString];
872 /* if not, then we check to see if there is a x264 opt in the preferences and use that if we want */
873 //job->x264opts = [[[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"] UTF8String];
874 /* Lets use this as per Nyx, Thanks Nyx! */
875 //job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */
876 //strcpy(job->x264opts, [[[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"] UTF8String]);
881 job->h264_13 = [fVidEncoderPopUp indexOfSelectedItem];
885 if( [fVidRatePopUp indexOfSelectedItem] > 0 )
887 job->vrate = 27000000;
888 job->vrate_base = hb_video_rates[[fVidRatePopUp
889 indexOfSelectedItem]-1].rate;
893 job->vrate = title->rate;
894 job->vrate_base = title->rate_base;
897 switch( [fVidQualityMatrix selectedRow] )
901 Bitrate should already have been calculated and displayed
902 in fVidBitrateField, so let's just use it */
904 job->vquality = -1.0;
905 job->vbitrate = [fVidBitrateField intValue];
908 job->vquality = [fVidQualitySlider floatValue];
913 job->grayscale = ( [fVidGrayscaleCheck state] == NSOnState );
917 /* Subtitle settings */
918 job->subtitle = [fSubPopUp indexOfSelectedItem] - 1;
920 /* Audio tracks and mixdowns */
921 /* check for the condition where track 2 has an audio selected, but track 1 does not */
922 /* we will use track 2 as track 1 in this scenario */
923 if ([fAudLang1PopUp indexOfSelectedItem] > 0)
925 job->audios[0] = [fAudLang1PopUp indexOfSelectedItem] - 1;
926 job->audios[1] = [fAudLang2PopUp indexOfSelectedItem] - 1; /* will be -1 if "none" is selected */
928 job->audio_mixdowns[0] = [[fAudTrack1MixPopUp selectedItem] tag];
929 job->audio_mixdowns[1] = [[fAudTrack2MixPopUp selectedItem] tag];
931 else if ([fAudLang2PopUp indexOfSelectedItem] > 0)
933 job->audios[0] = [fAudLang2PopUp indexOfSelectedItem] - 1;
934 job->audio_mixdowns[0] = [[fAudTrack2MixPopUp selectedItem] tag];
943 job->arate = hb_audio_rates[[fAudRatePopUp
944 indexOfSelectedItem]].rate;
945 job->abitrate = [[fAudBitratePopUp selectedItem] tag];
951 - (IBAction) AddToQueue: (id) sender
953 /* We get the destination directory from the destingation field here */
954 NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent];
955 /* We check for a valid destination here */
956 if ([[NSFileManager defaultManager] fileExistsAtPath:destinationDirectory] == 0)
958 NSRunAlertPanel(@"Warning!", @"This is not a valid destination directory!", @"OK", nil, nil);
963 hb_list_t * list = hb_get_titles( fHandle );
964 hb_title_t * title = (hb_title_t *) hb_list_item( list,
965 [fSrcTitlePopUp indexOfSelectedItem] );
966 hb_job_t * job = title->job;
970 /* Destination file */
971 job->file = [[fDstFile2Field stringValue] UTF8String];
973 if( [fVidTwoPassCheck state] == NSOnState )
976 hb_add( fHandle, job );
979 job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */
980 strcpy(job->x264opts, [[fDisplayX264Options stringValue] UTF8String]);
982 hb_add( fHandle, job );
987 hb_add( fHandle, job );
990 [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"];
994 - (IBAction) Rip: (id) sender
996 /* Rip or Cancel ? */
997 if( [[fRipButton title] isEqualToString: _( @"Cancel" )] )
999 [self Cancel: sender];
1002 /* if there is no job in the queue, then add it to the queue and rip
1003 otherwise, there are already jobs in queue, so just rip the queue */
1004 int count = hb_count( fHandle );
1007 [self AddToQueue: sender];
1010 /* We check for duplicate name here */
1011 if( [[NSFileManager defaultManager] fileExistsAtPath:
1012 [fDstFile2Field stringValue]] )
1014 NSBeginCriticalAlertSheet( _( @"File already exists" ),
1015 _( @"Cancel" ), _( @"Overwrite" ), NULL, fWindow, self,
1016 @selector( OverwriteAlertDone:returnCode:contextInfo: ),
1017 NULL, NULL, [NSString stringWithFormat:
1018 _( @"Do you want to overwrite %@?" ),
1019 [fDstFile2Field stringValue]] );
1022 /* We get the destination directory from the destination field here */
1023 NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent];
1024 /* We check for a valid destination here */
1025 if ([[NSFileManager defaultManager] fileExistsAtPath:destinationDirectory] == 0)
1027 NSRunAlertPanel(@"Warning!", @"This is not a valid destination directory!", @"OK", nil, nil);
1031 [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"];
1039 - (void) OverwriteAlertDone: (NSWindow *) sheet
1040 returnCode: (int) returnCode contextInfo: (void *) contextInfo
1042 if( returnCode == NSAlertAlternateReturn )
1048 - (void) UpdateAlertDone: (NSWindow *) sheet
1049 returnCode: (int) returnCode contextInfo: (void *) contextInfo
1051 if( returnCode == NSAlertAlternateReturn )
1053 /* Show scan panel */
1054 [self performSelectorOnMainThread: @selector(ShowScanPanel:)
1055 withObject: NULL waitUntilDone: NO];
1059 /* Go to HandBrake homepage and exit */
1060 [self OpenHomepage: NULL];
1061 [NSApp terminate: self];
1066 /* Let libhb do the job */
1067 hb_start( fHandle );
1068 /*set the fEncodeState State */
1071 /* Disable interface */
1072 [self EnableUI: NO];
1073 [fPauseButton setEnabled: NO];
1074 [fRipButton setEnabled: NO];
1077 - (IBAction) Cancel: (id) sender
1079 NSBeginCriticalAlertSheet( _( @"Cancel - Are you sure?" ),
1080 _( @"Keep working" ), _( @"Cancel encoding" ), NULL, fWindow, self,
1081 @selector( _Cancel:returnCode:contextInfo: ), NULL, NULL,
1082 _( @"Encoding won't be recoverable." ) );
1085 - (void) _Cancel: (NSWindow *) sheet
1086 returnCode: (int) returnCode contextInfo: (void *) contextInfo
1088 if( returnCode == NSAlertAlternateReturn )
1091 [fPauseButton setEnabled: NO];
1092 [fRipButton setEnabled: NO];
1093 /*set the fEncodeState State */
1098 - (IBAction) Pause: (id) sender
1100 [fPauseButton setEnabled: NO];
1101 [fRipButton setEnabled: NO];
1103 if( [[fPauseButton title] isEqualToString: _( @"Resume" )] )
1105 hb_resume( fHandle );
1109 hb_pause( fHandle );
1113 - (IBAction) TitlePopUpChanged: (id) sender
1115 hb_list_t * list = hb_get_titles( fHandle );
1116 hb_title_t * title = (hb_title_t*)
1117 hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
1120 /* If Auto Naming is on. We create an output filename of dvd name - title number */
1121 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultAutoNaming"] > 0)
1123 [fDstFile2Field setStringValue: [NSString stringWithFormat:
1124 @"%@/%@-%d.%@", [[fDstFile2Field stringValue] stringByDeletingLastPathComponent],
1125 [NSString stringWithUTF8String: title->name],
1126 [fSrcTitlePopUp indexOfSelectedItem] + 1,
1127 [[fDstFile2Field stringValue] pathExtension]]];
1130 /* Update chapter popups */
1131 [fSrcChapterStartPopUp removeAllItems];
1132 [fSrcChapterEndPopUp removeAllItems];
1133 for( int i = 0; i < hb_list_count( title->list_chapter ); i++ )
1135 [fSrcChapterStartPopUp addItemWithTitle: [NSString
1136 stringWithFormat: @"%d", i + 1]];
1137 [fSrcChapterEndPopUp addItemWithTitle: [NSString
1138 stringWithFormat: @"%d", i + 1]];
1140 [fSrcChapterStartPopUp selectItemAtIndex: 0];
1141 [fSrcChapterEndPopUp selectItemAtIndex:
1142 hb_list_count( title->list_chapter ) - 1];
1143 [self ChapterPopUpChanged: NULL];
1145 /* Start Get and set the initial pic size for display */
1146 hb_job_t * job = title->job;
1148 /* Turn Deinterlace on/off depending on the preference */
1149 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultDeinterlaceOn"] > 0)
1151 job->deinterlace = 1;
1155 job->deinterlace = 0;
1158 /* Pixel Ratio Setting */
1159 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"PixelRatio"])
1162 job->pixel_ratio = 1 ;
1166 job->pixel_ratio = 0 ;
1168 /*Set Source Size Fields Here */
1169 [fPicSrcWidth setStringValue: [NSString stringWithFormat:
1170 @"%d", fTitle->width]];
1171 [fPicSrcHeight setStringValue: [NSString stringWithFormat:
1172 @"%d", fTitle->height]];
1173 /* We get the originial output picture width and height and put them
1174 in variables for use with some presets later on */
1175 PicOrigOutputWidth = job->width;
1176 PicOrigOutputHeight = job->height;
1177 /* we test getting the max output value for pic sizing here to be used later*/
1178 [fPicSettingWidth setStringValue: [NSString stringWithFormat:
1179 @"%d", PicOrigOutputWidth]];
1180 [fPicSettingHeight setStringValue: [NSString stringWithFormat:
1181 @"%d", PicOrigOutputHeight]];
1182 /* we run the picture size values through
1183 CalculatePictureSizing to get all picture size
1185 [self CalculatePictureSizing: NULL];
1186 /* Run Through EncoderPopUpChanged to see if there
1187 needs to be any pic value modifications based on encoder settings */
1188 //[self EncoderPopUpChanged: NULL];
1189 /* END Get and set the initial pic size for display */
1191 /* Update subtitle popups */
1192 hb_subtitle_t * subtitle;
1193 [fSubPopUp removeAllItems];
1194 [fSubPopUp addItemWithTitle: @"None"];
1195 for( int i = 0; i < hb_list_count( title->list_subtitle ); i++ )
1197 subtitle = (hb_subtitle_t *) hb_list_item( title->list_subtitle, i );
1199 /* We cannot use NSPopUpButton's addItemWithTitle because
1200 it checks for duplicate entries */
1201 [[fSubPopUp menu] addItemWithTitle: [NSString stringWithCString:
1202 subtitle->lang] action: NULL keyEquivalent: @""];
1204 [fSubPopUp selectItemAtIndex: 0];
1206 /* Update chapter table */
1207 [fChapterTitlesDelegate resetWithTitle:title];
1208 [fChapterTable reloadData];
1210 /* Update audio popups */
1211 [self AddAllAudioTracksToPopUp: fAudLang1PopUp];
1212 [self AddAllAudioTracksToPopUp: fAudLang2PopUp];
1213 /* search for the first instance of our prefs default language for track 1, and set track 2 to "none" */
1214 NSString * audioSearchPrefix = [[NSUserDefaults standardUserDefaults] stringForKey:@"DefaultLanguage"];
1215 [self SelectAudioTrackInPopUp: fAudLang1PopUp searchPrefixString: audioSearchPrefix selectIndexIfNotFound: 1];
1216 [self SelectAudioTrackInPopUp: fAudLang2PopUp searchPrefixString: NULL selectIndexIfNotFound: 0];
1218 /* changing the title may have changed the audio channels on offer, */
1219 /* so call AudioTrackPopUpChanged for both audio tracks to update the mixdown popups */
1220 [self AudioTrackPopUpChanged: fAudLang1PopUp];
1221 [self AudioTrackPopUpChanged: fAudLang2PopUp];
1225 - (IBAction) ChapterPopUpChanged: (id) sender
1227 hb_list_t * list = hb_get_titles( fHandle );
1228 hb_title_t * title = (hb_title_t *)
1229 hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
1231 hb_chapter_t * chapter;
1232 int64_t duration = 0;
1233 for( int i = [fSrcChapterStartPopUp indexOfSelectedItem];
1234 i <= [fSrcChapterEndPopUp indexOfSelectedItem]; i++ )
1236 chapter = (hb_chapter_t *) hb_list_item( title->list_chapter, i );
1237 duration += chapter->duration;
1240 duration /= 90000; /* pts -> seconds */
1241 [fSrcDuration2Field setStringValue: [NSString stringWithFormat:
1242 @"%02lld:%02lld:%02lld", duration / 3600, ( duration / 60 ) % 60,
1245 [self CalculateBitrate: sender];
1248 - (IBAction) FormatPopUpChanged: (id) sender
1250 NSString * string = [fDstFile2Field stringValue];
1251 int format = [fDstFormatPopUp indexOfSelectedItem];
1254 /* Update the codecs popup */
1255 [fDstCodecsPopUp removeAllItems];
1259 /*Get Default MP4 File Extension*/
1260 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultMpegName"] > 0)
1268 [fDstCodecsPopUp addItemWithTitle:
1269 _( @"MPEG-4 Video / AAC Audio" )];
1270 [fDstCodecsPopUp addItemWithTitle:
1271 _( @"AVC/H.264 Video / AAC Audio" )];
1272 /* We enable the create chapters checkbox here since we are .mp4*/
1273 [fCreateChapterMarkers setEnabled: YES];
1277 [fDstCodecsPopUp addItemWithTitle:
1278 _( @"MPEG-4 Video / MP3 Audio" )];
1279 [fDstCodecsPopUp addItemWithTitle:
1280 _( @"MPEG-4 Video / AC-3 Audio" )];
1281 [fDstCodecsPopUp addItemWithTitle:
1282 _( @"AVC/H.264 Video / MP3 Audio" )];
1283 [fDstCodecsPopUp addItemWithTitle:
1284 _( @"AVC/H.264 Video / AC-3 Audio" )];
1285 /* We disable the create chapters checkbox here since we are NOT .mp4
1286 and make sure it is unchecked*/
1287 [fCreateChapterMarkers setEnabled: NO];
1288 [fCreateChapterMarkers setState: NSOffState];
1292 [fDstCodecsPopUp addItemWithTitle:
1293 _( @"MPEG-4 Video / Vorbis Audio" )];
1294 [fDstCodecsPopUp addItemWithTitle:
1295 _( @"MPEG-4 Video / MP3 Audio" )];
1296 /* We disable the create chapters checkbox here since we are NOT .mp4
1297 and make sure it is unchecked*/
1298 [fCreateChapterMarkers setEnabled: NO];
1299 [fCreateChapterMarkers setState: NSOffState];
1302 [self CodecsPopUpChanged: NULL];
1304 /* Add/replace to the correct extension */
1305 if( [string characterAtIndex: [string length] - 4] == '.' )
1307 [fDstFile2Field setStringValue: [NSString stringWithFormat:
1308 @"%@.%s", [string substringToIndex: [string length] - 4],
1313 [fDstFile2Field setStringValue: [NSString stringWithFormat:
1314 @"%@.%s", string, ext]];
1317 /* changing the format may mean that we can / can't offer mono or 6ch, */
1318 /* so call AudioTrackPopUpChanged for both audio tracks to update the mixdown popups */
1319 [self AudioTrackPopUpChanged: fAudLang1PopUp];
1320 [self AudioTrackPopUpChanged: fAudLang2PopUp];
1322 /* We call method method to change UI to reflect whether a preset is used or not*/
1323 [self CustomSettingUsed: sender];
1327 - (IBAction) CodecsPopUpChanged: (id) sender
1329 int format = [fDstFormatPopUp indexOfSelectedItem];
1330 int codecs = [fDstCodecsPopUp indexOfSelectedItem];
1331 [fX264optView setHidden: YES];
1332 [fX264optViewTitleLabel setStringValue: @"Only Used With The x264 (H.264) Codec"];
1335 /* Update the encoder popup*/
1336 if( ( FormatSettings[format][codecs] & HB_VCODEC_X264 ) )
1338 /* MPEG-4 -> H.264 */
1339 [fVidEncoderPopUp removeAllItems];
1340 [fVidEncoderPopUp addItemWithTitle: @"x264 (h.264 Main)"];
1341 [fVidEncoderPopUp addItemWithTitle: @"x264 (h.264 iPod)"];
1342 [fX264optView setHidden: NO];
1343 [fX264optViewTitleLabel setStringValue: @""];
1346 else if( ( FormatSettings[format][codecs] & HB_VCODEC_FFMPEG ) )
1348 /* H.264 -> MPEG-4 */
1349 [fVidEncoderPopUp removeAllItems];
1350 [fVidEncoderPopUp addItemWithTitle: @"FFmpeg"];
1351 [fVidEncoderPopUp addItemWithTitle: @"XviD"];
1352 [fVidEncoderPopUp selectItemAtIndex: 0];
1356 if( FormatSettings[format][codecs] & HB_ACODEC_AC3 )
1358 /* AC-3 pass-through: disable samplerate and bitrate */
1359 [fAudRatePopUp setEnabled: NO];
1360 [fAudBitratePopUp setEnabled: NO];
1364 [fAudRatePopUp setEnabled: YES];
1365 [fAudBitratePopUp setEnabled: YES];
1368 /* changing the codecs on offer may mean that we can / can't offer mono or 6ch, */
1369 /* so call AudioTrackPopUpChanged for both audio tracks to update the mixdown popups */
1370 [self AudioTrackPopUpChanged: fAudLang1PopUp];
1371 [self AudioTrackPopUpChanged: fAudLang2PopUp];
1373 [self CalculateBitrate: sender];
1374 /* We call method method to change UI to reflect whether a preset is used or not*/
1375 [self CustomSettingUsed: sender];
1378 - (IBAction) EncoderPopUpChanged: (id) sender
1381 /* Check to see if we need to modify the job pic values based on x264 (iPod) encoder selection */
1382 if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [fDstCodecsPopUp indexOfSelectedItem] == 1 && [fVidEncoderPopUp indexOfSelectedItem] == 1)
1384 hb_job_t * job = fTitle->job;
1385 job->pixel_ratio = 0 ;
1387 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPicSizeAutoiPod"] > 0)
1390 if (job->width > 640)
1394 job->keep_ratio = 1;
1395 hb_fix_aspect( job, HB_KEEP_WIDTH );
1401 [self CalculatePictureSizing: sender];
1402 /* We call method method to change UI to reflect whether a preset is used or not*/
1403 [self CustomSettingUsed: sender];
1406 - (IBAction) SetEnabledStateOfAudioMixdownControls: (id) sender
1409 /* enable/disable the mixdown text and popupbutton for audio track 1 */
1410 [fAudTrack1MixPopUp setEnabled: ([fAudLang1PopUp indexOfSelectedItem] == 0) ? NO : YES];
1411 [fAudTrack1MixLabel setTextColor: ([fAudLang1PopUp indexOfSelectedItem] == 0) ?
1412 [NSColor disabledControlTextColor] : [NSColor controlTextColor]];
1414 /* enable/disable the mixdown text and popupbutton for audio track 2 */
1415 [fAudTrack2MixPopUp setEnabled: ([fAudLang2PopUp indexOfSelectedItem] == 0) ? NO : YES];
1416 [fAudTrack2MixLabel setTextColor: ([fAudLang2PopUp indexOfSelectedItem] == 0) ?
1417 [NSColor disabledControlTextColor] : [NSColor controlTextColor]];
1421 - (IBAction) AddAllAudioTracksToPopUp: (id) sender
1424 hb_list_t * list = hb_get_titles( fHandle );
1425 hb_title_t * title = (hb_title_t*)
1426 hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
1430 [sender removeAllItems];
1431 [sender addItemWithTitle: _( @"None" )];
1432 for( int i = 0; i < hb_list_count( title->list_audio ); i++ )
1434 audio = (hb_audio_t *) hb_list_item( title->list_audio, i );
1435 [[sender menu] addItemWithTitle:
1436 [NSString stringWithCString: audio->lang]
1437 action: NULL keyEquivalent: @""];
1439 [sender selectItemAtIndex: 0];
1443 - (IBAction) SelectAudioTrackInPopUp: (id) sender searchPrefixString: (NSString *) searchPrefixString selectIndexIfNotFound: (int) selectIndexIfNotFound
1446 /* this method can be used to find a language, or a language-and-source-format combination, by passing in the appropriate string */
1447 /* e.g. to find the first French track, pass in an NSString * of "Francais" */
1448 /* e.g. to find the first English 5.1 AC3 track, pass in an NSString * of "English (AC3) (5.1 ch)" */
1449 /* if no matching track is found, then selectIndexIfNotFound is used to choose which track to select instead */
1451 if (searchPrefixString != NULL)
1454 for( int i = 0; i < [sender numberOfItems]; i++ )
1456 /* Try to find the desired search string */
1457 if ([[[sender itemAtIndex: i] title] hasPrefix:searchPrefixString])
1459 [sender selectItemAtIndex: i];
1463 /* couldn't find the string, so select the requested "search string not found" item */
1464 /* index of 0 means select the "none" item */
1465 /* index of 1 means select the first audio track */
1466 [sender selectItemAtIndex: selectIndexIfNotFound];
1470 /* if no search string is provided, then select the selectIndexIfNotFound item */
1471 [sender selectItemAtIndex: selectIndexIfNotFound];
1476 - (IBAction) AudioTrackPopUpChanged: (id) sender
1478 /* utility function to call AudioTrackPopUpChanged without passing in a mixdown-to-use */
1479 [self AudioTrackPopUpChanged: sender mixdownToUse: 0];
1482 - (IBAction) AudioTrackPopUpChanged: (id) sender mixdownToUse: (int) mixdownToUse
1485 /* make sure we have a selected title before continuing */
1486 if (fTitle == NULL) return;
1488 /* find out if audio track 1 or 2 was changed - this is passed to us in the tag of the sender */
1489 /* the sender will have been either fAudLang1PopUp (tag = 0) or fAudLang2PopUp (tag = 1) */
1490 int thisAudio = [sender tag];
1492 /* get the index of the selected audio */
1493 int thisAudioIndex = [sender indexOfSelectedItem] - 1;
1495 /* Handbrake can't currently cope with ripping the same source track twice */
1496 /* So, if this audio is also selected in the other audio track popup, set that popup's selection to "none" */
1497 /* get a reference to the two audio track popups */
1498 NSPopUpButton * thisAudioPopUp = (thisAudio == 1 ? fAudLang2PopUp : fAudLang1PopUp);
1499 NSPopUpButton * otherAudioPopUp = (thisAudio == 1 ? fAudLang1PopUp : fAudLang2PopUp);
1500 /* if the same track is selected in the other audio popup, then select "none" in that popup */
1501 /* unless, of course, both are selected as "none!" */
1502 if ([thisAudioPopUp indexOfSelectedItem] != 0 && [thisAudioPopUp indexOfSelectedItem] == [otherAudioPopUp indexOfSelectedItem]) {
1503 [otherAudioPopUp selectItemAtIndex: 0];
1504 [self AudioTrackPopUpChanged: otherAudioPopUp];
1507 /* pointer for the hb_audio_s struct we will use later on */
1510 /* find out what the currently-selected output audio codec is */
1511 int format = [fDstFormatPopUp indexOfSelectedItem];
1512 int codecs = [fDstCodecsPopUp indexOfSelectedItem];
1513 int acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
1515 /* pointer to this track's mixdown NSPopUpButton */
1516 NSTextField * mixdownTextField;
1517 NSPopUpButton * mixdownPopUp;
1519 /* find our mixdown NSTextField and NSPopUpButton */
1522 mixdownTextField = fAudTrack1MixLabel;
1523 mixdownPopUp = fAudTrack1MixPopUp;
1527 mixdownTextField = fAudTrack2MixLabel;
1528 mixdownPopUp = fAudTrack2MixPopUp;
1531 /* delete the previous audio mixdown options */
1532 [mixdownPopUp removeAllItems];
1534 /* check if the audio mixdown controls need their enabled state changing */
1535 [self SetEnabledStateOfAudioMixdownControls: NULL];
1537 if (thisAudioIndex != -1)
1541 audio = (hb_audio_t *) hb_list_item( fTitle->list_audio, thisAudioIndex );
1545 /* find out if our selected output audio codec supports mono and / or 6ch */
1546 /* we also check for an input codec of AC3 or DCA,
1547 as they are the only libraries able to do the mixdown to mono / conversion to 6-ch */
1548 /* audioCodecsSupportMono and audioCodecsSupport6Ch are the same for now,
1549 but this may change in the future, so they are separated for flexibility */
1550 int audioCodecsSupportMono = ((audio->codec == HB_ACODEC_AC3 ||
1551 audio->codec == HB_ACODEC_DCA) && acodec == HB_ACODEC_FAAC);
1552 int audioCodecsSupport6Ch = ((audio->codec == HB_ACODEC_AC3 ||
1553 audio->codec == HB_ACODEC_DCA) && acodec == HB_ACODEC_FAAC);
1555 /* check for AC-3 passthru */
1556 if (audio->codec == HB_ACODEC_AC3 && acodec == HB_ACODEC_AC3)
1558 [[mixdownPopUp menu] addItemWithTitle:
1559 [NSString stringWithCString: "AC3 Passthru"]
1560 action: NULL keyEquivalent: @""];
1565 /* add the appropriate audio mixdown menuitems to the popupbutton */
1566 /* in each case, we set the new menuitem's tag to be the amixdown value for that mixdown,
1567 so that we can reference the mixdown later */
1569 /* keep a track of the min and max mixdowns we used, so we can select the best match later */
1570 int minMixdownUsed = 0;
1571 int maxMixdownUsed = 0;
1573 /* get the input channel layout without any lfe channels */
1574 int layout = audio->input_channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK;
1576 /* do we want to add a mono option? */
1577 if (audioCodecsSupportMono == 1) {
1578 id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
1579 [NSString stringWithCString: hb_audio_mixdowns[0].human_readable_name]
1580 action: NULL keyEquivalent: @""];
1581 [menuItem setTag: hb_audio_mixdowns[0].amixdown];
1582 if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[0].amixdown;
1583 maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[0].amixdown);
1586 /* do we want to add a stereo option? */
1587 /* offer stereo if we have a mono source and non-mono-supporting codecs, as otherwise we won't have a mixdown at all */
1588 /* also offer stereo if we have a stereo-or-better source */
1589 if ((layout == HB_INPUT_CH_LAYOUT_MONO && audioCodecsSupportMono == 0) || layout >= HB_INPUT_CH_LAYOUT_STEREO) {
1590 id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
1591 [NSString stringWithCString: hb_audio_mixdowns[1].human_readable_name]
1592 action: NULL keyEquivalent: @""];
1593 [menuItem setTag: hb_audio_mixdowns[1].amixdown];
1594 if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[1].amixdown;
1595 maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[1].amixdown);
1598 /* do we want to add a dolby surround (DPL1) option? */
1599 if (layout == HB_INPUT_CH_LAYOUT_3F1R || layout == HB_INPUT_CH_LAYOUT_3F2R || layout == HB_INPUT_CH_LAYOUT_DOLBY) {
1600 id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
1601 [NSString stringWithCString: hb_audio_mixdowns[2].human_readable_name]
1602 action: NULL keyEquivalent: @""];
1603 [menuItem setTag: hb_audio_mixdowns[2].amixdown];
1604 if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[2].amixdown;
1605 maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[2].amixdown);
1608 /* do we want to add a dolby pro logic 2 (DPL2) option? */
1609 if (layout == HB_INPUT_CH_LAYOUT_3F2R) {
1610 id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
1611 [NSString stringWithCString: hb_audio_mixdowns[3].human_readable_name]
1612 action: NULL keyEquivalent: @""];
1613 [menuItem setTag: hb_audio_mixdowns[3].amixdown];
1614 if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[3].amixdown;
1615 maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[3].amixdown);
1618 /* do we want to add a 6-channel discrete option? */
1619 if (audioCodecsSupport6Ch == 1 && layout == HB_INPUT_CH_LAYOUT_3F2R && (audio->input_channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE)) {
1620 id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
1621 [NSString stringWithCString: hb_audio_mixdowns[4].human_readable_name]
1622 action: NULL keyEquivalent: @""];
1623 [menuItem setTag: hb_audio_mixdowns[4].amixdown];
1624 if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[4].amixdown;
1625 maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[4].amixdown);
1628 /* auto-select the best mixdown based on our saved mixdown preference */
1630 /* for now, this is hard-coded to a "best" mixdown of HB_AMIXDOWN_DOLBYPLII */
1631 /* ultimately this should be a prefs option */
1634 /* if we passed in a mixdown to use - in order to load a preset - then try and use it */
1635 if (mixdownToUse > 0)
1637 useMixdown = mixdownToUse;
1641 useMixdown = HB_AMIXDOWN_DOLBYPLII;
1644 /* if useMixdown > maxMixdownUsed, then use maxMixdownUsed */
1645 if (useMixdown > maxMixdownUsed) useMixdown = maxMixdownUsed;
1647 /* if useMixdown < minMixdownUsed, then use minMixdownUsed */
1648 if (useMixdown < minMixdownUsed) useMixdown = minMixdownUsed;
1650 /* select the (possibly-amended) preferred mixdown */
1651 [mixdownPopUp selectItemWithTag: useMixdown];
1653 /* lets call the AudioTrackMixdownChanged method here to determine appropriate bitrates, etc. */
1654 [self AudioTrackMixdownChanged: NULL];
1661 /* see if the new audio track choice will change the bitrate we need */
1662 [self CalculateBitrate: sender];
1665 - (IBAction) AudioTrackMixdownChanged: (id) sender
1668 /* find out what the currently-selected output audio codec is */
1669 int format = [fDstFormatPopUp indexOfSelectedItem];
1670 int codecs = [fDstCodecsPopUp indexOfSelectedItem];
1671 int acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
1673 /* storage variable for the min and max bitrate allowed for this codec */
1679 case HB_ACODEC_FAAC:
1680 /* check if we have a 6ch discrete conversion in either audio track */
1681 if ([[fAudTrack1MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH || [[fAudTrack2MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH)
1683 /* FAAC is happy using our min bitrate of 32 kbps, even for 6ch */
1685 /* If either mixdown popup includes 6-channel discrete, then allow up to 384 kbps */
1691 /* FAAC is happy using our min bitrate of 32 kbps for stereo or mono */
1693 /* FAAC won't honour anything more than 160 for stereo, so let's not offer it */
1694 /* note: haven't dealt with mono separately here, FAAC will just use the max it can */
1699 case HB_ACODEC_LAME:
1700 /* Lame is happy using our min bitrate of 32 kbps */
1702 /* Lame won't encode if the bitrate is higher than 320 kbps */
1706 case HB_ACODEC_VORBIS:
1707 /* Vorbis causes a crash if we use a bitrate below 48 kbps */
1709 /* Vorbis can cope with 384 kbps quite happily, even for stereo */
1714 /* AC3 passthru disables the bitrate dropdown anyway, so we might as well just use the min and max bitrate */
1720 [fAudBitratePopUp removeAllItems];
1722 for( int i = 0; i < hb_audio_bitrates_count; i++ )
1724 if (hb_audio_bitrates[i].rate >= minbitrate && hb_audio_bitrates[i].rate <= maxbitrate)
1726 /* add a new menuitem for this bitrate */
1727 id<NSMenuItem> menuItem = [[fAudBitratePopUp menu] addItemWithTitle:
1728 [NSString stringWithCString: hb_audio_bitrates[i].string]
1729 action: NULL keyEquivalent: @""];
1730 /* set its tag to be the actual bitrate as an integer, so we can retrieve it later */
1731 [menuItem setTag: hb_audio_bitrates[i].rate];
1735 /* select the default bitrate (but use 384 for 6-ch AAC) */
1736 if ([[fAudTrack1MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH || [[fAudTrack2MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH)
1738 [fAudBitratePopUp selectItemWithTag: 384];
1742 [fAudBitratePopUp selectItemWithTag: hb_audio_bitrates[hb_audio_bitrates_default].rate];
1746 /* lets set the picture size back to the max from right after title scan
1747 Lets use an IBAction here as down the road we could always use a checkbox
1748 in the gui to easily take the user back to max. Remember, the compiler
1749 resolves IBActions down to -(void) during compile anyway */
1750 - (IBAction) RevertPictureSizeToMax: (id) sender
1752 hb_job_t * job = fTitle->job;
1753 /* We use the output picture width and height
1754 as calculated from libhb right after title is set
1755 in TitlePopUpChanged */
1756 job->width = PicOrigOutputWidth;
1757 job->height = PicOrigOutputHeight;
1761 [self CalculatePictureSizing: sender];
1762 /* We call method method to change UI to reflect whether a preset is used or not*/
1763 [self CustomSettingUsed: sender];
1767 /* Get and Display Current Pic Settings in main window */
1768 - (IBAction) CalculatePictureSizing: (id) sender
1772 [fPicSettingWidth setStringValue: [NSString stringWithFormat:
1773 @"%d", fTitle->job->width]];
1774 [fPicSettingHeight setStringValue: [NSString stringWithFormat:
1775 @"%d", fTitle->job->height]];
1776 [fPicSettingARkeep setStringValue: [NSString stringWithFormat:
1777 @"%d", fTitle->job->keep_ratio]];
1778 [fPicSettingDeinterlace setStringValue: [NSString stringWithFormat:
1779 @"%d", fTitle->job->deinterlace]];
1780 [fPicSettingPAR setStringValue: [NSString stringWithFormat:
1781 @"%d", fTitle->job->pixel_ratio]];
1783 if (fTitle->job->pixel_ratio == 1)
1785 int titlewidth = fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3];
1786 int arpwidth = fTitle->job->pixel_aspect_width;
1787 int arpheight = fTitle->job->pixel_aspect_height;
1788 int displayparwidth = titlewidth * arpwidth / arpheight;
1789 int displayparheight = fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1];
1790 [fPicSettingHeight setStringValue: [NSString stringWithFormat:
1791 @"%d", displayparheight]];
1792 [fPicLabelPAROutp setStringValue: @"Anamorphic Output:"];
1793 [fPicLabelPAROutputX setStringValue: @"x"];
1794 [fPicSettingPARWidth setStringValue: [NSString stringWithFormat:
1795 @"%d", displayparwidth]];
1796 [fPicSettingPARHeight setStringValue: [NSString stringWithFormat:
1797 @"%d", displayparheight]];
1799 fTitle->job->keep_ratio = 0;
1803 [fPicLabelPAROutp setStringValue: @""];
1804 [fPicLabelPAROutputX setStringValue: @""];
1805 [fPicSettingPARWidth setStringValue: @""];
1806 [fPicSettingPARHeight setStringValue: @""];
1809 /* Set ON/Off values for the deinterlace/keep aspect ratio according to boolean */
1810 if (fTitle->job->keep_ratio > 0)
1812 [fPicSettingARkeepDsply setStringValue: @"On"];
1816 [fPicSettingARkeepDsply setStringValue: @"Off"];
1818 if (fTitle->job->deinterlace > 0)
1820 [fPicSettingDeinterlaceDsply setStringValue: @"On"];
1824 [fPicSettingDeinterlaceDsply setStringValue: @"Off"];
1826 if (fTitle->job->pixel_ratio > 0)
1828 [fPicSettingPARDsply setStringValue: @"On"];
1832 [fPicSettingPARDsply setStringValue: @"Off"];
1834 /* below will trigger the preset, if selected, to be
1835 changed to "Custom". Lets comment out for now until
1836 we figure out a way to determine if the picture values
1837 changed modify the preset values */
1838 //[self CustomSettingUsed: sender];
1841 - (IBAction) CalculateBitrate: (id) sender
1843 if( !fHandle || [fVidQualityMatrix selectedRow] != 0 )
1848 hb_list_t * list = hb_get_titles( fHandle );
1849 hb_title_t * title = (hb_title_t *) hb_list_item( list,
1850 [fSrcTitlePopUp indexOfSelectedItem] );
1851 hb_job_t * job = title->job;
1855 [fVidBitrateField setIntValue: hb_calc_bitrate( job,
1856 [fVidTargetSizeField intValue] )];
1861 /* Method to determine if we should change the UI
1862 To reflect whether or not a Preset is being used or if
1863 the user is using "Custom" settings by determining the sender*/
1864 - (IBAction) CustomSettingUsed: (id) sender
1866 if ([sender stringValue] != NULL)
1868 /* Deselect the currently selected Preset if there is one*/
1869 [tableView deselectRow:[tableView selectedRow]];
1870 /* Change UI to show "Custom" settings are being used */
1871 [fPresetSelectedDisplay setStringValue: @"Custom"];
1873 curUserPresetChosenNum = nil;
1874 /* If we have MP4, AVC H.264 and x264 Main then we look to see
1875 if there are any x264 options from the preferences to use */
1876 if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [fDstCodecsPopUp indexOfSelectedItem] == 1)
1878 /* Lets check to see there is a specified string in the prefs, and use that if need be */
1879 if ([[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"] != @"")
1881 [fDisplayX264Options setStringValue: [NSString stringWithFormat:[[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"]]];
1886 /* Empty the field to display custom x264 preset options*/
1887 [fDisplayX264Options setStringValue: @""];
1891 [self X264AdvancedOptionsSet:NULL];
1894 - (IBAction) X264AdvancedOptionsSet: (id) sender
1896 /*Set opt widget values here*/
1898 /*B-Frames fX264optBframesPopUp*/
1900 [fX264optBframesPopUp removeAllItems];
1901 [fX264optBframesPopUp addItemWithTitle:@"Default (0)"];
1904 [fX264optBframesPopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
1907 /*Reference Frames fX264optRefPopUp*/
1908 [fX264optRefPopUp removeAllItems];
1909 [fX264optRefPopUp addItemWithTitle:@"Default (1)"];
1912 [fX264optRefPopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
1915 /*No Fast P-Skip fX264optNfpskipSwitch BOOLEAN*/
1916 [fX264optNfpskipSwitch setState:0];
1918 /*No Dict Decimate fX264optNodctdcmtSwitch BOOLEAN*/
1919 [fX264optNodctdcmtSwitch setState:0];
1921 /*Sub Me fX264optSubmePopUp*/
1922 [fX264optSubmePopUp removeAllItems];
1923 [fX264optSubmePopUp addItemWithTitle:@"Default (4)"];
1926 [fX264optSubmePopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
1929 /*Trellis fX264optTrellisPopUp*/
1930 [fX264optTrellisPopUp removeAllItems];
1931 [fX264optTrellisPopUp addItemWithTitle:@"Default (0)"];
1934 [fX264optTrellisPopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
1937 /*Mixed-references fX264optMixedRefsSwitch BOOLEAN*/
1938 [fX264optMixedRefsSwitch setState:0];
1940 /*Motion Estimation fX264optMotionEstPopUp*/
1941 [fX264optMotionEstPopUp removeAllItems];
1942 [fX264optMotionEstPopUp addItemWithTitle:@"Default (Hexagon)"];
1943 [fX264optMotionEstPopUp addItemWithTitle:@"Diamond"];
1944 [fX264optMotionEstPopUp addItemWithTitle:@"Hexagon"];
1945 [fX264optMotionEstPopUp addItemWithTitle:@"Uneven Multi-Hexagon"];
1946 [fX264optMotionEstPopUp addItemWithTitle:@"Exhaustive"];
1948 /*Motion Estimation range fX264optMERangePopUp*/
1949 [fX264optMERangePopUp removeAllItems];
1950 [fX264optMERangePopUp addItemWithTitle:@"Default (16)"];
1953 [fX264optMERangePopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
1956 /*Weighted B-Frame Prediction fX264optWeightBSwitch BOOLEAN*/
1957 [fX264optWeightBSwitch setState:0];
1959 /*B-Frame Rate Distortion Optimization fX264optBRDOSwitch BOOLEAN*/
1960 [fX264optBRDOSwitch setState:0];
1962 /*B-frame Pyramids fX264optBPyramidSwitch BOOLEAN*/
1963 [fX264optBPyramidSwitch setState:0];
1965 /*Bidirectional Motion Estimation Refinement fX264optBiMESwitch BOOLEAN*/
1966 [fX264optBiMESwitch setState:0];
1968 /*Direct B-Frame Prediction Mode fX264optDirectPredPopUp*/
1969 [fX264optDirectPredPopUp removeAllItems];
1970 [fX264optDirectPredPopUp addItemWithTitle:@"Default (Spatial)"];
1971 [fX264optDirectPredPopUp addItemWithTitle:@"None"];
1972 [fX264optDirectPredPopUp addItemWithTitle:@"Spatial"];
1973 [fX264optDirectPredPopUp addItemWithTitle:@"Temporal"];
1974 [fX264optDirectPredPopUp addItemWithTitle:@"Automatic"];
1977 [fX264optAlphaDeblockPopUp removeAllItems];
1978 [fX264optAlphaDeblockPopUp addItemWithTitle:@"Default (0)"];
1981 [fX264optAlphaDeblockPopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
1985 [fX264optBetaDeblockPopUp removeAllItems];
1986 [fX264optBetaDeblockPopUp addItemWithTitle:@"Default (0)"];
1989 [fX264optBetaDeblockPopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
1992 /* Standardize the option string */
1993 [self X264AdvancedOptionsStandardizeOptString: NULL];
1994 /* Set Current GUI Settings based on newly standardized string */
1995 [self X264AdvancedOptionsSetCurrentSettings: NULL];
1998 - (IBAction) X264AdvancedOptionsStandardizeOptString: (id) sender
2000 /* Set widgets depending on the opt string in field */
2001 NSString * thisOpt; // The separated option such as "bframes=3"
2002 NSString * optName = @""; // The option name such as "bframes"
2003 NSString * optValue = @"";// The option value such as "3"
2004 NSString * changedOptString = @"";
2005 NSArray *currentOptsArray;
2007 /*First, we get an opt string to process */
2008 NSString *currentOptString = [fDisplayX264Options stringValue];
2010 /*verify there is an opt string to process */
2011 NSRange currentOptRange = [currentOptString rangeOfString:@"="];
2012 if (currentOptRange.location != NSNotFound)
2014 /*Put individual options into an array based on the ":" separator for processing, result is "<opt>=<value>"*/
2015 currentOptsArray = [currentOptString componentsSeparatedByString:@":"];
2017 /*iterate through the array and get <opts> and <values*/
2018 //NSEnumerator * enumerator = [currentOptsArray objectEnumerator];
2020 int currentOptsArrayCount = [currentOptsArray count];
2021 for (loopcounter = 0; loopcounter < currentOptsArrayCount; loopcounter++)
2023 thisOpt = [currentOptsArray objectAtIndex:loopcounter];
2025 NSRange splitOptRange = [thisOpt rangeOfString:@"="];
2026 if (splitOptRange.location != NSNotFound)
2028 optName = [thisOpt substringToIndex:splitOptRange.location];
2029 optValue = [thisOpt substringFromIndex:splitOptRange.location + 1];
2031 /* Standardize the names here depending on whats in the string */
2032 optName = [self X264AdvancedOptionsStandardizeOptNames:optName];
2033 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,optValue];
2035 else // No value given so we use a default of "1"
2038 /* Standardize the names here depending on whats in the string */
2039 optName = [self X264AdvancedOptionsStandardizeOptNames:optName];
2040 thisOpt = [NSString stringWithFormat:@"%@=%d",optName,1];
2043 /* Construct New String for opts here */
2044 if ([thisOpt isEqualToString:@""])
2046 changedOptString = [NSString stringWithFormat:@"%@%@",changedOptString,thisOpt];
2050 if ([changedOptString isEqualToString:@""])
2052 changedOptString = [NSString stringWithFormat:@"%@",thisOpt];
2056 changedOptString = [NSString stringWithFormat:@"%@:%@",changedOptString,thisOpt];
2062 /* Change the option string to reflect the new standardized option string */
2063 [fDisplayX264Options setStringValue:[NSString stringWithFormat:changedOptString]];
2066 - (NSString *) X264AdvancedOptionsStandardizeOptNames:(NSString *) cleanOptNameString
2068 if ([cleanOptNameString isEqualToString:@"ref"] || [cleanOptNameString isEqualToString:@"frameref"])
2070 cleanOptNameString = @"ref";
2073 /*No Fast PSkip nofast_pskip*/
2074 if ([cleanOptNameString isEqualToString:@"no-fast-pskip"] || [cleanOptNameString isEqualToString:@"no_fast_pskip"] || [cleanOptNameString isEqualToString:@"nofast_pskip"])
2076 cleanOptNameString = @"no-fast-pskip";
2079 /*No Dict Decimate*/
2080 if ([cleanOptNameString isEqualToString:@"no-dct-decimate"] || [cleanOptNameString isEqualToString:@"no_dct_decimate"] || [cleanOptNameString isEqualToString:@"nodct_decimate"])
2082 cleanOptNameString = @"no-dct-decimate";
2086 if ([cleanOptNameString isEqualToString:@"subme"])
2088 cleanOptNameString = @"subq";
2092 if ([cleanOptNameString isEqualToString:@"me-range"] || [cleanOptNameString isEqualToString:@"me_range"])
2093 cleanOptNameString = @"merange";
2096 if ([cleanOptNameString isEqualToString:@"weight-b"] || [cleanOptNameString isEqualToString:@"weight_b"])
2098 cleanOptNameString = @"weightb";
2102 if ([cleanOptNameString isEqualToString:@"b-rdo"] || [cleanOptNameString isEqualToString:@"b_rdo"])
2104 cleanOptNameString = @"brdo";
2108 if ([cleanOptNameString isEqualToString:@"b_pyramid"])
2110 cleanOptNameString = @"b-pyramid";
2113 /*Direct Prediction*/
2114 if ([cleanOptNameString isEqualToString:@"direct-pred"] || [cleanOptNameString isEqualToString:@"direct_pred"])
2116 cleanOptNameString = @"direct";
2120 if ([cleanOptNameString isEqualToString:@"filter"])
2122 cleanOptNameString = @"deblock";
2125 return cleanOptNameString;
2128 - (IBAction) X264AdvancedOptionsSetCurrentSettings: (id) sender
2130 /* Set widgets depending on the opt string in field */
2131 NSString * thisOpt; // The separated option such as "bframes=3"
2132 NSString * optName = @""; // The option name such as "bframes"
2133 NSString * optValue = @"";// The option value such as "3"
2134 NSArray *currentOptsArray;
2136 /*First, we get an opt string to process */
2137 //NSString *currentOptString = @"bframes=3:ref=1:subme=5:me=umh:no-fast-pskip=1:no-dct-decimate=1:trellis=2";
2138 NSString *currentOptString = [fDisplayX264Options stringValue];
2140 /*verify there is an opt string to process */
2141 NSRange currentOptRange = [currentOptString rangeOfString:@"="];
2142 if (currentOptRange.location != NSNotFound)
2144 /* lets clean the opt string here to standardize any names*/
2145 /*Put individual options into an array based on the ":" separator for processing, result is "<opt>=<value>"*/
2146 currentOptsArray = [currentOptString componentsSeparatedByString:@":"];
2148 /*iterate through the array and get <opts> and <values*/
2149 //NSEnumerator * enumerator = [currentOptsArray objectEnumerator];
2151 int currentOptsArrayCount = [currentOptsArray count];
2153 /*iterate through the array and get <opts> and <values*/
2154 for (loopcounter = 0; loopcounter < currentOptsArrayCount; loopcounter++)
2156 thisOpt = [currentOptsArray objectAtIndex:loopcounter];
2157 NSRange splitOptRange = [thisOpt rangeOfString:@"="];
2159 if (splitOptRange.location != NSNotFound)
2161 optName = [thisOpt substringToIndex:splitOptRange.location];
2162 optValue = [thisOpt substringFromIndex:splitOptRange.location + 1];
2164 /*Run through the available widgets for x264 opts and set them, as you add widgets,
2165 they need to be added here. This should be moved to its own method probably*/
2167 /*bframes NSPopUpButton*/
2168 if ([optName isEqualToString:@"bframes"])
2170 [fX264optBframesPopUp selectItemAtIndex:[optValue intValue]+1];
2172 /*ref NSPopUpButton*/
2173 if ([optName isEqualToString:@"ref"])
2175 [fX264optRefPopUp selectItemAtIndex:[optValue intValue]+1];
2177 /*No Fast PSkip NSPopUpButton*/
2178 if ([optName isEqualToString:@"no-fast-pskip"])
2180 [fX264optNfpskipSwitch setState:[optValue intValue]];
2182 /*No Dict Decimate NSPopUpButton*/
2183 if ([optName isEqualToString:@"no-dct-decimate"])
2185 [fX264optNodctdcmtSwitch setState:[optValue intValue]];
2187 /*Sub Me NSPopUpButton*/
2188 if ([optName isEqualToString:@"subq"])
2190 [fX264optSubmePopUp selectItemAtIndex:[optValue intValue]+1];
2192 /*Trellis NSPopUpButton*/
2193 if ([optName isEqualToString:@"trellis"])
2195 [fX264optTrellisPopUp selectItemAtIndex:[optValue intValue]+1];
2197 /*Mixed Refs NSButton*/
2198 if ([optName isEqualToString:@"mixed-refs"])
2200 [fX264optMixedRefsSwitch setState:[optValue intValue]];
2202 /*Motion Estimation NSPopUpButton*/
2203 if ([optName isEqualToString:@"me"])
2205 if ([optValue isEqualToString:@"dia"])
2206 [fX264optMotionEstPopUp selectItemAtIndex:1];
2207 else if ([optValue isEqualToString:@"hex"])
2208 [fX264optMotionEstPopUp selectItemAtIndex:2];
2209 else if ([optValue isEqualToString:@"umh"])
2210 [fX264optMotionEstPopUp selectItemAtIndex:3];
2211 else if ([optValue isEqualToString:@"esa"])
2212 [fX264optMotionEstPopUp selectItemAtIndex:4];
2214 /*ME Range NSPopUpButton*/
2215 if ([optName isEqualToString:@"merange"])
2217 [fX264optMERangePopUp selectItemAtIndex:[optValue intValue]-3];
2219 /*Weighted B-Frames NSPopUpButton*/
2220 if ([optName isEqualToString:@"weightb"])
2222 [fX264optWeightBSwitch setState:[optValue intValue]];
2224 /*BRDO NSPopUpButton*/
2225 if ([optName isEqualToString:@"brdo"])
2227 [fX264optBRDOSwitch setState:[optValue intValue]];
2229 /*B Pyramid NSPopUpButton*/
2230 if ([optName isEqualToString:@"b-pyramid"])
2232 [fX264optBPyramidSwitch setState:[optValue intValue]];
2234 /*Bidirectional Motion Estimation Refinement NSPopUpButton*/
2235 if ([optName isEqualToString:@"bime"])
2237 [fX264optBiMESwitch setState:[optValue intValue]];
2239 /*Direct B-frame Prediction NSPopUpButton*/
2240 if ([optName isEqualToString:@"direct"])
2242 if ([optValue isEqualToString:@"none"])
2243 [fX264optDirectPredPopUp selectItemAtIndex:1];
2244 else if ([optValue isEqualToString:@"spatial"])
2245 [fX264optDirectPredPopUp selectItemAtIndex:2];
2246 else if ([optValue isEqualToString:@"temporal"])
2247 [fX264optDirectPredPopUp selectItemAtIndex:3];
2248 else if ([optValue isEqualToString:@"auto"])
2249 [fX264optDirectPredPopUp selectItemAtIndex:4];
2251 /*Deblocking NSPopUpButtons*/
2252 if ([optName isEqualToString:@"deblock"])
2254 NSString * alphaDeblock = @"";
2255 NSString * betaDeblock = @"";
2257 NSRange splitDeblock = [optValue rangeOfString:@","];
2258 alphaDeblock = [optValue substringToIndex:splitDeblock.location];
2259 betaDeblock = [optValue substringFromIndex:splitDeblock.location + 1];
2261 if ([alphaDeblock isEqualToString:@"0"] && [betaDeblock isEqualToString:@"0"])
2263 [fX264optAlphaDeblockPopUp selectItemAtIndex:0];
2264 [fX264optBetaDeblockPopUp selectItemAtIndex:0];
2268 if (![alphaDeblock isEqualToString:@"0"])
2270 [fX264optAlphaDeblockPopUp selectItemAtIndex:[alphaDeblock intValue]+7];
2274 [fX264optAlphaDeblockPopUp selectItemAtIndex:7];
2277 if (![betaDeblock isEqualToString:@"0"])
2279 [fX264optBetaDeblockPopUp selectItemAtIndex:[betaDeblock intValue]+7];
2283 [fX264optBetaDeblockPopUp selectItemAtIndex:7];
2292 - (IBAction) X264AdvancedOptionsChanged: (id) sender
2294 /*Determine which outlet is being used and set optName to process accordingly */
2295 NSString * optNameToChange = @""; // The option name such as "bframes"
2297 if (sender == fX264optBframesPopUp)
2299 optNameToChange = @"bframes";
2301 if (sender == fX264optRefPopUp)
2303 optNameToChange = @"ref";
2305 if (sender == fX264optNfpskipSwitch)
2307 optNameToChange = @"no-fast-pskip";
2309 if (sender == fX264optNodctdcmtSwitch)
2311 optNameToChange = @"no-dct-decimate";
2313 if (sender == fX264optSubmePopUp)
2315 optNameToChange = @"subq";
2317 if (sender == fX264optTrellisPopUp)
2319 optNameToChange = @"trellis";
2321 if (sender == fX264optMixedRefsSwitch)
2323 optNameToChange = @"mixed-refs";
2325 if (sender == fX264optMotionEstPopUp)
2327 optNameToChange = @"me";
2329 if (sender == fX264optMERangePopUp)
2331 optNameToChange = @"merange";
2333 if (sender == fX264optWeightBSwitch)
2335 optNameToChange = @"weightb";
2337 if (sender == fX264optBRDOSwitch)
2339 optNameToChange = @"brdo";
2341 if (sender == fX264optBPyramidSwitch)
2343 optNameToChange = @"b-pyramid";
2345 if (sender == fX264optBiMESwitch)
2347 optNameToChange = @"bime";
2349 if (sender == fX264optDirectPredPopUp)
2351 optNameToChange = @"direct";
2353 if (sender == fX264optAlphaDeblockPopUp)
2355 optNameToChange = @"deblock";
2357 if (sender == fX264optBetaDeblockPopUp)
2359 optNameToChange = @"deblock";
2362 /* Set widgets depending on the opt string in field */
2363 NSString * thisOpt; // The separated option such as "bframes=3"
2364 NSString * optName = @""; // The option name such as "bframes"
2365 NSString * optValue = @"";// The option value such as "3"
2366 NSArray *currentOptsArray;
2368 /*First, we get an opt string to process */
2369 //EXAMPLE: NSString *currentOptString = @"bframes=3:ref=1:subme=5:me=umh:no-fast-pskip=1:no-dct-decimate=1:trellis=2";
2370 NSString *currentOptString = [fDisplayX264Options stringValue];
2372 /*verify there is an occurrence of the opt specified by the sender to change */
2373 /*take care of any multi-value opt names here. This is extremely kludgy, but test for functionality
2374 and worry about pretty later */
2376 /*First, we create a pattern to check for ":"optNameToChange"=" to modify the option if the name falls after
2377 the first character of the opt string (hence the ":") */
2378 NSString *checkOptNameToChange = [NSString stringWithFormat:@":%@=",optNameToChange];
2379 NSRange currentOptRange = [currentOptString rangeOfString:checkOptNameToChange];
2380 /*Then we create a pattern to check for "<beginning of line>"optNameToChange"=" to modify the option to
2381 see if the name falls at the beginning of the line, where we would not have the ":" as a pattern to test against*/
2382 NSString *checkOptNameToChangeBeginning = [NSString stringWithFormat:@"%@=",optNameToChange];
2383 NSRange currentOptRangeBeginning = [currentOptString rangeOfString:checkOptNameToChangeBeginning];
2384 if (currentOptRange.location != NSNotFound || currentOptRangeBeginning.location == 0)
2386 /* Create new empty opt string*/
2387 NSString *changedOptString = @"";
2389 /*Put individual options into an array based on the ":" separator for processing, result is "<opt>=<value>"*/
2390 currentOptsArray = [currentOptString componentsSeparatedByString:@":"];
2392 /*iterate through the array and get <opts> and <values*/
2394 int currentOptsArrayCount = [currentOptsArray count];
2395 for (loopcounter = 0; loopcounter < currentOptsArrayCount; loopcounter++)
2397 thisOpt = [currentOptsArray objectAtIndex:loopcounter];
2398 NSRange splitOptRange = [thisOpt rangeOfString:@"="];
2400 if (splitOptRange.location != NSNotFound)
2402 optName = [thisOpt substringToIndex:splitOptRange.location];
2403 optValue = [thisOpt substringFromIndex:splitOptRange.location + 1];
2405 /*Run through the available widgets for x264 opts and set them, as you add widgets,
2406 they need to be added here. This should be moved to its own method probably*/
2408 /*If the optNameToChange is found, appropriately change the value or delete it if
2409 "Unspecified" is set.*/
2410 if ([optName isEqualToString:optNameToChange])
2412 if ([optNameToChange isEqualToString:@"deblock"])
2414 if ((([fX264optAlphaDeblockPopUp indexOfSelectedItem] == 0) || ([fX264optAlphaDeblockPopUp indexOfSelectedItem] == 7)) && (([fX264optBetaDeblockPopUp indexOfSelectedItem] == 0) || ([fX264optBetaDeblockPopUp indexOfSelectedItem] == 7)))
2420 thisOpt = [NSString stringWithFormat:@"%@=%d,%d",optName, ([fX264optAlphaDeblockPopUp indexOfSelectedItem] != 0) ? [fX264optAlphaDeblockPopUp indexOfSelectedItem]-7 : 0,([fX264optBetaDeblockPopUp indexOfSelectedItem] != 0) ? [fX264optBetaDeblockPopUp indexOfSelectedItem]-7 : 0];
2423 else if /*Boolean Switches*/ ([optNameToChange isEqualToString:@"mixed-refs"] || [optNameToChange isEqualToString:@"weightb"] || [optNameToChange isEqualToString:@"brdo"] || [optNameToChange isEqualToString:@"bime"] || [optNameToChange isEqualToString:@"b-pyramid"] || [optNameToChange isEqualToString:@"no-fast-pskip"] || [optNameToChange isEqualToString:@"no-dct-decimate"])
2425 if ([sender state] == 0)
2431 thisOpt = [NSString stringWithFormat:@"%@=%d",optName,1];
2434 else if (([sender indexOfSelectedItem] == 0) && (sender != fX264optAlphaDeblockPopUp) && (sender != fX264optBetaDeblockPopUp) ) // means that "unspecified" is chosen, lets then remove it from the string
2438 else if ([optNameToChange isEqualToString:@"me"])
2440 switch ([sender indexOfSelectedItem])
2443 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"dia"];
2447 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"hex"];
2451 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"umh"];
2455 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"esa"];
2462 else if ([optNameToChange isEqualToString:@"direct"])
2464 switch ([sender indexOfSelectedItem])
2467 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"none"];
2471 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"spatial"];
2475 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"temporal"];
2479 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"auto"];
2486 else if ([optNameToChange isEqualToString:@"merange"])
2488 thisOpt = [NSString stringWithFormat:@"%@=%d",optName,[sender indexOfSelectedItem]+3];
2490 else // we have a valid value to change, so change it
2492 thisOpt = [NSString stringWithFormat:@"%@=%d",optName,[sender indexOfSelectedItem]-1];
2497 /* Construct New String for opts here */
2498 if ([thisOpt isEqualToString:@""])
2500 changedOptString = [NSString stringWithFormat:@"%@%@",changedOptString,thisOpt];
2504 if ([changedOptString isEqualToString:@""])
2506 changedOptString = [NSString stringWithFormat:@"%@",thisOpt];
2510 changedOptString = [NSString stringWithFormat:@"%@:%@",changedOptString,thisOpt];
2515 /* Change the option string to reflect the new mod settings */
2516 [fDisplayX264Options setStringValue:[NSString stringWithFormat:changedOptString]];
2518 else // if none exists, add it to the string
2520 if ([[fDisplayX264Options stringValue] isEqualToString: @""])
2522 if ([optNameToChange isEqualToString:@"me"])
2524 switch ([sender indexOfSelectedItem])
2527 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2528 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"dia"]]];
2532 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2533 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"hex"]]];
2537 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2538 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"umh"]]];
2542 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2543 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"esa"]]];
2550 else if ([optNameToChange isEqualToString:@"direct"])
2552 switch ([sender indexOfSelectedItem])
2555 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2556 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"none"]]];
2560 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2561 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"spatial"]]];
2565 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2566 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"temporal"]]];
2570 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2571 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"auto"]]];
2579 else if ([optNameToChange isEqualToString:@"merange"])
2581 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2582 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"%d",[sender indexOfSelectedItem]+3]]];
2584 else if ([optNameToChange isEqualToString:@"deblock"])
2586 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@", [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"%d,%d", ([fX264optAlphaDeblockPopUp indexOfSelectedItem] != 0) ? [fX264optAlphaDeblockPopUp indexOfSelectedItem]-7 : 0, ([fX264optBetaDeblockPopUp indexOfSelectedItem] != 0) ? [fX264optBetaDeblockPopUp indexOfSelectedItem]-7 : 0]]];
2588 else if /*Boolean Switches*/ ([optNameToChange isEqualToString:@"mixed-refs"] || [optNameToChange isEqualToString:@"weightb"] || [optNameToChange isEqualToString:@"brdo"] || [optNameToChange isEqualToString:@"bime"] || [optNameToChange isEqualToString:@"b-pyramid"] || [optNameToChange isEqualToString:@"no-fast-pskip"] || [optNameToChange isEqualToString:@"no-dct-decimate"]) {
2589 if ([sender state] == 0)
2591 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@""]];
2595 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2596 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"%d",[sender state]]]];
2601 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2602 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"%d",[sender indexOfSelectedItem]-1]]];
2607 if ([optNameToChange isEqualToString:@"me"])
2609 switch ([sender indexOfSelectedItem])
2612 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",
2613 [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2614 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"dia"]]];
2618 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",
2619 [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2620 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"hex"]]];
2624 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",
2625 [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2626 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"umh"]]];
2630 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",
2631 [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2632 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"esa"]]];
2639 else if ([optNameToChange isEqualToString:@"direct"])
2641 switch ([sender indexOfSelectedItem])
2644 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",
2645 [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2646 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"none"]]];
2650 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",
2651 [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2652 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"spatial"]]];
2656 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",
2657 [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2658 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"temporal"]]];
2662 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",
2663 [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2664 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"auto"]]];
2672 else if ([optNameToChange isEqualToString:@"merange"])
2674 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",[NSString stringWithFormat:[fDisplayX264Options stringValue]],
2675 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"%d",[sender indexOfSelectedItem]+3]]];
2677 else if ([optNameToChange isEqualToString:@"deblock"])
2679 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@", [NSString stringWithFormat:[fDisplayX264Options stringValue]], [NSString stringWithFormat:optNameToChange], [NSString stringWithFormat:@"%d,%d", ([fX264optAlphaDeblockPopUp indexOfSelectedItem] != 0) ? [fX264optAlphaDeblockPopUp indexOfSelectedItem]-7 : 0, ([fX264optBetaDeblockPopUp indexOfSelectedItem] != 0) ? [fX264optBetaDeblockPopUp indexOfSelectedItem]-7 : 0]]];
2681 else if /*Boolean Switches*/ ([optNameToChange isEqualToString:@"mixed-refs"] || [optNameToChange isEqualToString:@"weightb"] || [optNameToChange isEqualToString:@"brdo"] || [optNameToChange isEqualToString:@"bime"] || [optNameToChange isEqualToString:@"b-pyramid"] || [optNameToChange isEqualToString:@"no-fast-pskip"] || [optNameToChange isEqualToString:@"no-dct-decimate"])
2683 if ([sender state] == 0)
2685 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@",[NSString stringWithFormat:[fDisplayX264Options stringValue]]]];
2689 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",[NSString stringWithFormat:[fDisplayX264Options stringValue]],
2690 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"%d",[sender state]]]];
2695 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",[NSString stringWithFormat:[fDisplayX264Options stringValue]],
2696 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"%d",[sender indexOfSelectedItem]-1]]];
2701 /* We now need to reset the opt widgets since we changed some stuff */
2702 [self X264AdvancedOptionsSet:NULL];
2706 /* We use this method to recreate new, updated factory
2708 - (IBAction)AddFactoryPresets:(id)sender
2710 /* First, we delete any existing built in presets */
2711 [self DeleteFactoryPresets: sender];
2712 /* Then, we re-create new built in presets programmatically CreatePSPPreset*/
2713 [UserPresets addObject:[self CreateIpodPreset]];
2714 [UserPresets addObject:[self CreateAppleTVPreset]];
2715 [UserPresets addObject:[self CreatePSThreePreset]];
2716 [UserPresets addObject:[self CreatePSPPreset]];
2719 - (IBAction)DeleteFactoryPresets:(id)sender
2722 NSEnumerator *enumerator = [UserPresets objectEnumerator];
2726 NSMutableArray *tempArray;
2729 tempArray = [NSMutableArray array];
2730 /* we look here to see if the preset is we move on to the next one */
2731 while ( tempObject = [enumerator nextObject] )
2733 /* if the preset is "Factory" then we put it in the array of
2734 presets to delete */
2735 if ([[tempObject objectForKey:@"Type"] intValue] == 0)
2737 [tempArray addObject:tempObject];
2741 [UserPresets removeObjectsInArray:tempArray];
2742 [tableView reloadData];
2747 - (IBAction) ShowAddPresetPanel: (id) sender
2749 /* Deselect the currently selected Preset if there is one*/
2750 [tableView deselectRow:[tableView selectedRow]];
2752 /* Populate the preset picture settings popup here */
2753 [fPresetNewPicSettingsPopUp removeAllItems];
2754 [fPresetNewPicSettingsPopUp addItemWithTitle:@"None"];
2755 [fPresetNewPicSettingsPopUp addItemWithTitle:@"Current"];
2756 [fPresetNewPicSettingsPopUp addItemWithTitle:@"Source Maximum (post source scan)"];
2757 [fPresetNewPicSettingsPopUp selectItemAtIndex: 0];
2759 /* Erase info from the input fields */
2760 [fPresetNewName setStringValue: @""];
2761 /* Show the panel */
2762 [NSApp beginSheet: fAddPresetPanel modalForWindow: fWindow
2763 modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
2764 [NSApp runModalForWindow: fAddPresetPanel];
2765 [NSApp endSheet: fAddPresetPanel];
2766 [fAddPresetPanel orderOut: self];
2770 - (IBAction) CloseAddPresetPanel: (id) sender
2776 - (IBAction)AddUserPreset:(id)sender
2779 /* Here we create a custom user preset */
2780 [UserPresets addObject:[self CreatePreset]];
2781 /* Erase info from the input fields */
2782 [fPresetNewName setStringValue: @""];
2783 /* We stop the modal window for the new preset */
2793 /* We Sort the Presets By Factory or Custom */
2794 NSSortDescriptor * presetTypeDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"Type"
2795 ascending:YES] autorelease];
2796 /* We Sort the Presets Alphabetically by name */
2797 NSSortDescriptor * presetNameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"PresetName"
2798 ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease];
2799 NSArray *sortDescriptors=[NSArray arrayWithObjects:presetTypeDescriptor,presetNameDescriptor,nil];
2800 NSArray *sortedArray=[UserPresets sortedArrayUsingDescriptors:sortDescriptors];
2801 [UserPresets setArray:sortedArray];
2804 /* We Reload the New Table data for presets */
2805 [tableView reloadData];
2806 /* We save all of the preset data here */
2810 - (IBAction)InsertPreset:(id)sender
2812 int index = [tableView selectedRow];
2813 [UserPresets insertObject:[self CreatePreset] atIndex:index];
2814 [tableView reloadData];
2818 - (NSDictionary *)CreatePreset
2820 NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
2821 /* Get the New Preset Name from the field in the AddPresetPanel */
2822 [preset setObject:[fPresetNewName stringValue] forKey:@"PresetName"];
2823 /*Set whether or not this is a user preset or factory 0 is factory, 1 is user*/
2824 [preset setObject:[NSNumber numberWithInt:1] forKey:@"Type"];
2825 /*Set whether or not this is default, at creation set to 0*/
2826 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
2827 /*Get the whether or not to apply pic settings in the AddPresetPanel*/
2828 [preset setObject:[NSNumber numberWithInt:[fPresetNewPicSettingsPopUp indexOfSelectedItem]] forKey:@"UsesPictureSettings"];
2830 [preset setObject:[fDstFormatPopUp titleOfSelectedItem] forKey:@"FileFormat"];
2831 /* Chapter Markers fCreateChapterMarkers*/
2832 [preset setObject:[NSNumber numberWithInt:[fCreateChapterMarkers state]] forKey:@"ChapterMarkers"];
2834 [preset setObject:[fDstCodecsPopUp titleOfSelectedItem] forKey:@"FileCodecs"];
2836 [preset setObject:[fVidEncoderPopUp titleOfSelectedItem] forKey:@"VideoEncoder"];
2837 /* x264 Option String */
2838 [preset setObject:[fDisplayX264Options stringValue] forKey:@"x264Option"];
2840 [preset setObject:[NSNumber numberWithInt:[fVidQualityMatrix selectedRow]] forKey:@"VideoQualityType"];
2841 [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
2842 [preset setObject:[fVidBitrateField stringValue] forKey:@"VideoAvgBitrate"];
2843 [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
2845 /* Video framerate */
2846 [preset setObject:[fVidRatePopUp titleOfSelectedItem] forKey:@"VideoFramerate"];
2848 [preset setObject:[NSNumber numberWithInt:[fVidGrayscaleCheck state]] forKey:@"VideoGrayScale"];
2849 /* 2 Pass Encoding */
2850 [preset setObject:[NSNumber numberWithInt:[fVidTwoPassCheck state]] forKey:@"VideoTwoPass"];
2852 /*Picture Settings*/
2853 hb_job_t * job = fTitle->job;
2854 /* Basic Picture Settings */
2855 /* Use Max Picture settings for whatever the dvd is.*/
2856 [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesMaxPictureSettings"];
2857 [preset setObject:[NSNumber numberWithInt:fTitle->job->width] forKey:@"PictureWidth"];
2858 [preset setObject:[NSNumber numberWithInt:fTitle->job->height] forKey:@"PictureHeight"];
2859 [preset setObject:[NSNumber numberWithInt:fTitle->job->keep_ratio] forKey:@"PictureKeepRatio"];
2860 [preset setObject:[NSNumber numberWithInt:fTitle->job->deinterlace] forKey:@"PictureDeinterlace"];
2861 [preset setObject:[NSNumber numberWithInt:fTitle->job->pixel_ratio] forKey:@"PicturePAR"];
2862 /* Set crop settings here */
2863 /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
2864 [preset setObject:[NSNumber numberWithInt:job->crop[0]] forKey:@"PictureTopCrop"];
2865 [preset setObject:[NSNumber numberWithInt:job->crop[1]] forKey:@"PictureBottomCrop"];
2866 [preset setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"];
2867 [preset setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"];
2870 /* Audio Sample Rate*/
2871 [preset setObject:[fAudRatePopUp titleOfSelectedItem] forKey:@"AudioSampleRate"];
2872 /* Audio Bitrate Rate*/
2873 [preset setObject:[fAudBitratePopUp titleOfSelectedItem] forKey:@"AudioBitRate"];
2875 [preset setObject:[fSubPopUp titleOfSelectedItem] forKey:@"Subtitles"];
2878 [preset autorelease];
2883 - (NSDictionary *)CreateIpodPreset
2885 NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
2886 /* Get the New Preset Name from the field in the AddPresetPanel */
2887 [preset setObject:@"HB-iPod" forKey:@"PresetName"];
2888 /*Set whether or not this is a user preset or factory 0 is factory, 1 is user*/
2889 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
2890 /*Set whether or not this is default, at creation set to 0*/
2891 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
2892 /*Get the whether or not to apply pic settings in the AddPresetPanel*/
2893 [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesPictureSettings"];
2895 [preset setObject:@"MP4 file" forKey:@"FileFormat"];
2896 /* Chapter Markers*/
2897 [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
2899 [preset setObject:@"AVC/H.264 Video / AAC Audio" forKey:@"FileCodecs"];
2901 [preset setObject:@"x264 (h.264 iPod)" forKey:@"VideoEncoder"];
2902 /* x264 Option String */
2903 [preset setObject:@"frameref=1:bframes=0:nofast_pskip:subq=6:partitions=p8x8,p8x4,p4x8,i4x4:qcomp=0:me=umh" forKey:@"x264Option"];
2905 [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
2906 [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
2907 [preset setObject:@"1500" forKey:@"VideoAvgBitrate"];
2908 [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
2910 /* Video framerate */
2911 [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
2913 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
2914 /* 2 Pass Encoding */
2915 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
2917 /*Picture Settings*/
2918 //hb_job_t * job = fTitle->job;
2919 /* Basic Picture Settings */
2920 /* Use Max Picture settings for whatever the dvd is.*/
2921 [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesMaxPictureSettings"];
2922 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureWidth"];
2923 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureHeight"];
2924 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureKeepRatio"];
2925 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
2926 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PicturePAR"];
2927 /* Set crop settings here */
2928 /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
2929 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureTopCrop"];
2930 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureBottomCrop"];
2931 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureLeftCrop"];
2932 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureRightCrop"];
2935 /* Audio Sample Rate*/
2936 [preset setObject:@"48" forKey:@"AudioSampleRate"];
2937 /* Audio Bitrate Rate*/
2938 [preset setObject:@"160" forKey:@"AudioBitRate"];
2940 [preset setObject:@"None" forKey:@"Subtitles"];
2943 [preset autorelease];
2948 - (NSDictionary *)CreateAppleTVPreset
2950 NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
2951 /* Get the New Preset Name from the field in the AddPresetPanel */
2952 [preset setObject:@"HB-AppleTV" forKey:@"PresetName"];
2953 /*Set whether or not this is a user preset where 0 is factory, 1 is user*/
2954 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
2955 /*Set whether or not this is default, at creation set to 0*/
2956 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
2957 /*Get the whether or not to apply pic settings in the AddPresetPanel*/
2958 [preset setObject:[NSNumber numberWithInt:2] forKey:@"UsesPictureSettings"];
2960 [preset setObject:@"MP4 file" forKey:@"FileFormat"];
2961 /* Chapter Markers*/
2962 [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
2964 [preset setObject:@"AVC/H.264 Video / AAC Audio" forKey:@"FileCodecs"];
2966 [preset setObject:@"x264 (h.264 Main)" forKey:@"VideoEncoder"];
2967 /* x264 Option String (We can use this to tweak the appleTV output)*/
2968 [preset setObject:@"bframes=3:ref=1:subme=5:me=umh:no-fast-pskip=1:trellis=2" forKey:@"x264Option"];
2970 [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
2971 [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
2972 [preset setObject:@"2500" forKey:@"VideoAvgBitrate"];
2973 [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
2975 /* Video framerate */
2976 [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
2978 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
2979 /* 2 Pass Encoding */
2980 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
2982 /*Picture Settings*/
2983 /* For AppleTV we only want to retain UsesMaxPictureSettings
2984 which depend on the source dvd picture settings, so we don't
2985 record the current dvd's picture info since it will vary from
2987 //hb_job_t * job = fTitle->job;
2988 //hb_job_t * job = title->job;
2989 /* Basic Picture Settings */
2990 /* Use Max Picture settings for whatever the dvd is.*/
2991 [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesMaxPictureSettings"];
2992 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureWidth"];
2993 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureHeight"];
2994 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureKeepRatio"];
2995 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
2996 [preset setObject:[NSNumber numberWithInt:1] forKey:@"PicturePAR"];
2997 /* Set crop settings here */
2998 /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
2999 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureTopCrop"];
3000 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureBottomCrop"];
3001 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureLeftCrop"];
3002 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureRightCrop"];
3005 /* Audio Sample Rate*/
3006 [preset setObject:@"48" forKey:@"AudioSampleRate"];
3007 /* Audio Bitrate Rate*/
3008 [preset setObject:@"160" forKey:@"AudioBitRate"];
3010 [preset setObject:@"None" forKey:@"Subtitles"];
3013 [preset autorelease];
3018 - (NSDictionary *)CreatePSThreePreset
3020 NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
3021 /* Get the New Preset Name from the field in the AddPresetPanel */
3022 [preset setObject:@"HB-PS3" forKey:@"PresetName"];
3023 /*Set whether or not this is a user preset where 0 is factory, 1 is user*/
3024 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
3025 /*Set whether or not this is default, at creation set to 0*/
3026 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
3027 /*Get the whether or not to apply pic settings in the AddPresetPanel*/
3028 [preset setObject:[NSNumber numberWithInt:2] forKey:@"UsesPictureSettings"];
3030 [preset setObject:@"MP4 file" forKey:@"FileFormat"];
3031 /* Chapter Markers*/
3032 [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
3034 [preset setObject:@"AVC/H.264 Video / AAC Audio" forKey:@"FileCodecs"];
3036 [preset setObject:@"x264 (h.264 Main)" forKey:@"VideoEncoder"];
3037 /* x264 Option String (We can use this to tweak the appleTV output)*/
3038 [preset setObject:@"level=41" forKey:@"x264Option"];
3040 [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
3041 [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
3042 [preset setObject:@"2500" forKey:@"VideoAvgBitrate"];
3043 [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
3045 /* Video framerate */
3046 [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
3048 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
3049 /* 2 Pass Encoding */
3050 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
3052 /*Picture Settings*/
3053 /* For PS3 we only want to retain UsesMaxPictureSettings
3054 which depend on the source dvd picture settings, so we don't
3055 record the current dvd's picture info since it will vary from
3057 /* Use Max Picture settings for whatever the dvd is.*/
3058 [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesMaxPictureSettings"];
3059 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureWidth"];
3060 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureHeight"];
3061 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureKeepRatio"];
3062 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
3063 [preset setObject:[NSNumber numberWithInt:1] forKey:@"PicturePAR"];
3064 /* Set crop settings here */
3065 /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
3066 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureTopCrop"];
3067 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureBottomCrop"];
3068 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureLeftCrop"];
3069 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureRightCrop"];
3072 /* Audio Sample Rate*/
3073 [preset setObject:@"48" forKey:@"AudioSampleRate"];
3074 /* Audio Bitrate Rate*/
3075 [preset setObject:@"160" forKey:@"AudioBitRate"];
3077 [preset setObject:@"None" forKey:@"Subtitles"];
3080 [preset autorelease];
3084 - (NSDictionary *)CreatePSPPreset
3086 NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
3087 /* Get the New Preset Name from the field in the AddPresetPanel */
3088 [preset setObject:@"HB-PSP" forKey:@"PresetName"];
3089 /*Set whether or not this is a user preset where 0 is factory, 1 is user*/
3090 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
3091 /*Set whether or not this is default, at creation set to 0*/
3092 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
3093 /*Get the whether or not to apply pic settings in the AddPresetPanel*/
3094 [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesPictureSettings"];
3096 [preset setObject:@"MP4 file" forKey:@"FileFormat"];
3097 /* Chapter Markers*/
3098 [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
3100 [preset setObject:@"MPEG-4 Video / AAC Audio" forKey:@"FileCodecs"];
3102 [preset setObject:@"FFmpeg" forKey:@"VideoEncoder"];
3103 /* x264 Option String (We can use this to tweak the appleTV output)*/
3104 [preset setObject:@"" forKey:@"x264Option"];
3106 [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
3107 [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
3108 [preset setObject:@"1024" forKey:@"VideoAvgBitrate"];
3109 [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
3111 /* Video framerate */
3112 [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
3114 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
3115 /* 2 Pass Encoding */
3116 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
3118 /*Picture Settings*/
3119 /* For PS3 we only want to retain UsesMaxPictureSettings
3120 which depend on the source dvd picture settings, so we don't
3121 record the current dvd's picture info since it will vary from
3123 /* Use Max Picture settings for whatever the dvd is.*/
3124 [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesMaxPictureSettings"];
3125 [preset setObject:@"368" forKey:@"PictureWidth"];
3126 [preset setObject:@"208" forKey:@"PictureHeight"];
3127 [preset setObject:[NSNumber numberWithInt:1] forKey:@"PictureKeepRatio"];
3128 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
3129 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PicturePAR"];
3130 /* Set crop settings here */
3131 /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
3132 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureTopCrop"];
3133 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureBottomCrop"];
3134 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureLeftCrop"];
3135 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureRightCrop"];
3138 /* Audio Sample Rate*/
3139 [preset setObject:@"48" forKey:@"AudioSampleRate"];
3140 /* Audio Bitrate Rate*/
3141 [preset setObject:@"128" forKey:@"AudioBitRate"];
3143 [preset setObject:@"None" forKey:@"Subtitles"];
3146 [preset autorelease];
3152 - (IBAction)DeletePreset:(id)sender
3155 NSEnumerator *enumerator;
3157 NSMutableArray *tempArray;
3160 if ( [tableView numberOfSelectedRows] == 0 )
3162 /* Alert user before deleting preset */
3163 /* Comment out for now, tie to user pref eventually */
3166 status = NSRunAlertPanel(@"Warning!", @"Are you sure that you want to delete the selected preset?", @"OK", @"Cancel", nil);
3168 if ( status == NSAlertDefaultReturn ) {
3169 enumerator = [tableView selectedRowEnumerator];
3170 tempArray = [NSMutableArray array];
3172 while ( (index = [enumerator nextObject]) ) {
3173 tempObject = [UserPresets objectAtIndex:[index intValue]];
3174 [tempArray addObject:tempObject];
3177 [UserPresets removeObjectsInArray:tempArray];
3178 [tableView reloadData];
3182 - (IBAction)tableViewSelected:(id)sender
3184 /* Since we cannot disable the presets tableView in terms of clickability
3185 we will use the enabled state of the add presets button to determine whether
3186 or not clicking on a preset will do anything */
3187 if ([fPresetsAdd isEnabled])
3190 /* we get the chosen preset from the UserPresets array */
3191 chosenPreset = [UserPresets objectAtIndex:[sender selectedRow]];
3192 curUserPresetChosenNum = [sender selectedRow];
3193 /* we set the preset display field in main window here */
3194 [fPresetSelectedDisplay setStringValue: [NSString stringWithFormat: @"%@",[chosenPreset valueForKey:@"PresetName"]]];
3196 [fDstFormatPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"FileFormat"]]];
3197 [self FormatPopUpChanged: NULL];
3198 /* Chapter Markers*/
3199 [fCreateChapterMarkers setState:[[chosenPreset objectForKey:@"ChapterMarkers"] intValue]];
3201 [fDstCodecsPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"FileCodecs"]]];
3202 [self CodecsPopUpChanged: NULL];
3204 [fVidEncoderPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoEncoder"]]];
3206 /* We can show the preset options here in the gui if we want to
3207 so we check to see it the user has specified it in the prefs */
3208 [fDisplayX264Options setStringValue: [NSString stringWithFormat:[chosenPreset valueForKey:@"x264Option"]]];
3210 [self X264AdvancedOptionsSet:NULL];
3212 /* Lets run through the following functions to get variables set there */
3213 [self EncoderPopUpChanged: NULL];
3214 [self CalculateBitrate: NULL];
3217 [fVidQualityMatrix selectCellAtRow:[[chosenPreset objectForKey:@"VideoQualityType"] intValue] column:0];
3219 [fVidTargetSizeField setStringValue: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoTargetSize"]]];
3220 [fVidBitrateField setStringValue: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoAvgBitrate"]]];
3222 [fVidQualitySlider setFloatValue: [[chosenPreset valueForKey:@"VideoQualitySlider"] floatValue]];
3223 [self VideoMatrixChanged: NULL];
3225 /* Video framerate */
3226 [fVidRatePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoFramerate"]]];
3229 [fVidGrayscaleCheck setState:[[chosenPreset objectForKey:@"VideoGrayScale"] intValue]];
3231 /* 2 Pass Encoding */
3232 [fVidTwoPassCheck setState:[[chosenPreset objectForKey:@"VideoTwoPass"] intValue]];
3237 /* Audio Sample Rate*/
3238 [fAudRatePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"AudioSampleRate"]]];
3239 /* Audio Bitrate Rate*/
3240 [fAudBitratePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"AudioBitRate"]]];
3242 [fSubPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"Subtitles"]]];
3244 /* Picture Settings */
3245 /* Look to see if we apply these here in objectForKey:@"UsesPictureSettings"] */
3246 if ([[chosenPreset objectForKey:@"UsesPictureSettings"] intValue] > 0)
3248 hb_job_t * job = fTitle->job;
3249 /* Check to see if we should use the max picture setting for the current title*/
3250 if ([[chosenPreset objectForKey:@"UsesPictureSettings"] intValue] == 2 || [[chosenPreset objectForKey:@"UsesMaxPictureSettings"] intValue] == 1)
3252 /* Use Max Picture settings for whatever the dvd is.*/
3253 [self RevertPictureSizeToMax: NULL];
3254 job->keep_ratio = [[chosenPreset objectForKey:@"PictureKeepRatio"] intValue];
3255 if (job->keep_ratio == 1)
3257 hb_fix_aspect( job, HB_KEEP_WIDTH );
3259 job->pixel_ratio = [[chosenPreset objectForKey:@"PicturePAR"] intValue];
3263 job->width = [[chosenPreset objectForKey:@"PictureWidth"] intValue];
3264 job->height = [[chosenPreset objectForKey:@"PictureHeight"] intValue];
3265 job->keep_ratio = [[chosenPreset objectForKey:@"PictureKeepRatio"] intValue];
3266 if (job->keep_ratio == 1)
3268 hb_fix_aspect( job, HB_KEEP_WIDTH );
3270 job->pixel_ratio = [[chosenPreset objectForKey:@"PicturePAR"] intValue];
3271 job->crop[0] = [[chosenPreset objectForKey:@"PictureTopCrop"] intValue];
3272 job->crop[1] = [[chosenPreset objectForKey:@"PictureBottomCrop"] intValue];
3273 job->crop[2] = [[chosenPreset objectForKey:@"PictureLeftCrop"] intValue];
3274 job->crop[3] = [[chosenPreset objectForKey:@"PictureRightCrop"] intValue];
3276 [self CalculatePictureSizing: NULL];
3287 - (int)numberOfRowsInTableView:(NSTableView *)aTableView
3289 return [UserPresets count];
3292 /* we use this to determine display characteristics for
3293 each table cell based on content currently only used to
3294 show the built in presets in a blue font. */
3295 - (void)tableView:(NSTableView *)aTableView
3296 willDisplayCell:(id)aCell
3297 forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
3299 NSDictionary *userPresetDict = [UserPresets objectAtIndex:rowIndex];
3300 if ([[userPresetDict objectForKey:@"Type"] intValue] == 0)
3302 [aCell setTextColor:[NSColor blueColor]];
3306 [aCell setTextColor:[NSColor blackColor]];
3311 - (id)tableView:(NSTableView *)aTableView
3312 objectValueForTableColumn:(NSTableColumn *)aTableColumn
3315 id theRecord, theValue;
3317 theRecord = [UserPresets objectAtIndex:rowIndex];
3318 theValue = [theRecord objectForKey:[aTableColumn identifier]];
3322 // NSTableDataSource method that we implement to edit values directly in the table...
3323 - (void)tableView:(NSTableView *)aTableView
3324 setObjectValue:(id)anObject
3325 forTableColumn:(NSTableColumn *)aTableColumn
3330 theRecord = [UserPresets objectAtIndex:rowIndex];
3331 [theRecord setObject:anObject forKey:@"PresetName"];
3332 /* We Sort the Presets By Factory or Custom */
3333 NSSortDescriptor * presetTypeDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"Type"
3334 ascending:YES] autorelease];
3335 /* We Sort the Presets Alphabetically by name */
3336 NSSortDescriptor * presetNameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"PresetName"
3337 ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease];
3338 NSArray *sortDescriptors=[NSArray arrayWithObjects:presetTypeDescriptor,presetNameDescriptor,nil];
3339 NSArray *sortedArray=[UserPresets sortedArrayUsingDescriptors:sortDescriptors];
3340 [UserPresets setArray:sortedArray];
3341 /* We Reload the New Table data for presets */
3342 [tableView reloadData];
3343 /* We save all of the preset data here */
3350 [UserPresets writeToFile:UserPresetsFile atomically:YES];
3356 - (void) controlTextDidBeginEditing: (NSNotification *) notification
3358 [self CalculateBitrate: NULL];
3361 - (void) controlTextDidEndEditing: (NSNotification *) notification
3363 [self CalculateBitrate: NULL];
3366 - (void) controlTextDidChange: (NSNotification *) notification
3368 [self CalculateBitrate: NULL];
3371 - (IBAction) OpenHomepage: (id) sender
3373 [[NSWorkspace sharedWorkspace] openURL: [NSURL
3374 URLWithString:@"http://handbrake.m0k.org/"]];
3377 - (IBAction) OpenForums: (id) sender
3379 [[NSWorkspace sharedWorkspace] openURL: [NSURL
3380 URLWithString:@"http://handbrake.m0k.org/forum/"]];
3382 - (IBAction) OpenUserGuide: (id) sender
3384 [[NSWorkspace sharedWorkspace] openURL: [NSURL
3385 URLWithString:@"http://handbrake.m0k.org/trac/wiki/HandBrakeGuide"]];
3388 - (IBAction)showDebugOutputPanel:(id)sender
3390 [outputPanel showOutputPanel:nil];