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"
10 #import "HBPreferencesController.h"
12 #define _(a) NSLocalizedString(a,NULL)
14 static int FormatSettings[3][4] =
15 { { HB_MUX_MP4 | HB_VCODEC_FFMPEG | HB_ACODEC_FAAC,
16 HB_MUX_MP4 | HB_VCODEC_X264 | HB_ACODEC_FAAC,
19 { HB_MUX_AVI | HB_VCODEC_FFMPEG | HB_ACODEC_LAME,
20 HB_MUX_AVI | HB_VCODEC_FFMPEG | HB_ACODEC_AC3,
21 HB_MUX_AVI | HB_VCODEC_X264 | HB_ACODEC_LAME,
22 HB_MUX_AVI | HB_VCODEC_X264 | HB_ACODEC_AC3 },
23 { HB_MUX_OGM | HB_VCODEC_FFMPEG | HB_ACODEC_VORBIS,
24 HB_MUX_OGM | HB_VCODEC_FFMPEG | HB_ACODEC_LAME,
28 /*******************************
29 * HBController implementation *
30 *******************************/
31 @implementation HBController
36 [HBPreferencesController registerUserDefaults];
38 outputPanel = [[HBOutputPanelController alloc] init];
42 - (void) applicationDidFinishLaunching: (NSNotification *) notification
47 // Open debug output window now if it was visible when HB was closed
48 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"OutputPanelIsOpen"])
49 [self showDebugOutputPanel:nil];
52 int debugLevel = [[NSUserDefaults standardUserDefaults] boolForKey:@"ShowVerboseOutput"] ? HB_DEBUG_ALL : HB_DEBUG_NONE;
53 fHandle = hb_init(debugLevel, [[NSUserDefaults standardUserDefaults] boolForKey:@"CheckForUpdates"]);
55 // Set the Growl Delegate
56 HBController *hbGrowlDelegate = [[HBController alloc] init];
57 [GrowlApplicationBridge setGrowlDelegate: hbGrowlDelegate];
58 /* Init others controllers */
59 [fScanController SetHandle: fHandle];
60 [fPictureController SetHandle: fHandle];
61 [fQueueController SetHandle: fHandle];
63 fChapterTitlesDelegate = [[ChapterTitles alloc] init];
64 [fChapterTable setDataSource:fChapterTitlesDelegate];
66 /* Call UpdateUI every 2/10 sec */
67 [[NSRunLoop currentRunLoop] addTimer: [NSTimer
68 scheduledTimerWithTimeInterval: 0.2 target: self
69 selector: @selector( UpdateUI: ) userInfo: NULL repeats: FALSE]
70 forMode: NSModalPanelRunLoopMode];
72 if( ( build = hb_check_update( fHandle, &version ) ) > -1 )
74 /* Update available - tell the user */
76 NSBeginInformationalAlertSheet( _( @"Update is available" ),
77 _( @"Go get it!" ), _( @"Discard" ), NULL, fWindow, self,
78 @selector( UpdateAlertDone:returnCode:contextInfo: ),
79 NULL, NULL, [NSString stringWithFormat:
80 _( @"HandBrake %s (build %d) is now available for download." ),
86 /* Show scan panel ASAP */
87 [self performSelectorOnMainThread: @selector(ShowScanPanel:)
88 withObject: NULL waitUntilDone: NO];
91 - (NSApplicationTerminateReply) applicationShouldTerminate:
94 if( [[fRipButton title] isEqualToString: _( @"Cancel" )] )
97 return NSTerminateCancel;
99 return NSTerminateNow;
102 - (void)applicationWillTerminate:(NSNotification *)aNotification
104 [outputPanel release];
109 - (void) awakeFromNib
113 [self TranslateStrings];
114 currentScanCount = 0;
116 //[self registrationDictionaryForGrowl];
117 /* Init User Presets .plist */
118 /* We declare the default NSFileManager into fileManager */
119 NSFileManager * fileManager = [NSFileManager defaultManager];
120 //presetPrefs = [[NSUserDefaults standardUserDefaults] retain];
121 /* we set the files and support paths here */
122 AppSupportDirectory = @"~/Library/Application Support/HandBrake";
123 AppSupportDirectory = [AppSupportDirectory stringByExpandingTildeInPath];
125 UserPresetsFile = @"~/Library/Application Support/HandBrake/UserPresets.plist";
126 UserPresetsFile = [UserPresetsFile stringByExpandingTildeInPath];
128 x264ProfilesFile = @"~/Library/Application Support/HandBrake/x264Profiles.plist";
129 x264ProfilesFile = [x264ProfilesFile stringByExpandingTildeInPath];
130 /* We check for the app support directory for media fork */
131 if ([fileManager fileExistsAtPath:AppSupportDirectory] == 0)
133 // If it doesnt exist yet, we create it here
134 [fileManager createDirectoryAtPath:AppSupportDirectory attributes:nil];
136 // We check for the presets.plist here
138 if ([fileManager fileExistsAtPath:UserPresetsFile] == 0)
141 [fileManager createFileAtPath:UserPresetsFile contents:nil attributes:nil];
144 // We check for the x264profiles.plist here
146 if ([fileManager fileExistsAtPath:x264ProfilesFile] == 0)
149 [fileManager createFileAtPath:x264ProfilesFile contents:nil attributes:nil];
153 UserPresetsFile = @"~/Library/Application Support/HandBrake/UserPresets.plist";
154 UserPresetsFile = [[UserPresetsFile stringByExpandingTildeInPath]retain];
156 UserPresets = [[NSMutableArray alloc] initWithContentsOfFile:UserPresetsFile];
157 if (nil == UserPresets)
159 UserPresets = [[NSMutableArray alloc] init];
160 [self AddFactoryPresets:NULL];
162 /* Show/Dont Show Presets drawer upon launch based
163 on user preference DefaultPresetsDrawerShow*/
164 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPresetsDrawerShow"] > 0)
166 [fPresetDrawer open];
172 [fDstFormatPopUp removeAllItems];
173 [fDstFormatPopUp addItemWithTitle: _( @"MP4 file" )];
174 [fDstFormatPopUp addItemWithTitle: _( @"AVI file" )];
175 [fDstFormatPopUp addItemWithTitle: _( @"OGM file" )];
176 [fDstFormatPopUp selectItemAtIndex: 0];
178 [self FormatPopUpChanged: NULL];
180 /* We enable the create chapters checkbox here since we are .mp4 */
181 [fCreateChapterMarkers setEnabled: YES];
182 if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultChapterMarkers"] > 0)
184 [fCreateChapterMarkers setState: NSOnState];
190 [fDstFile2Field setStringValue: [NSString stringWithFormat:
191 @"%@/Desktop/Movie.mp4", NSHomeDirectory()]];
194 [fVidEncoderPopUp removeAllItems];
195 [fVidEncoderPopUp addItemWithTitle: @"FFmpeg"];
196 [fVidEncoderPopUp addItemWithTitle: @"XviD"];
201 [fVidTargetSizeField setIntValue: 700];
202 [fVidBitrateField setIntValue: 1000];
204 [fVidQualityMatrix selectCell: fVidBitrateCell];
205 [self VideoMatrixChanged: NULL];
207 /* Video framerate */
208 [fVidRatePopUp removeAllItems];
209 [fVidRatePopUp addItemWithTitle: _( @"Same as source" )];
210 for( int i = 0; i < hb_video_rates_count; i++ )
212 [fVidRatePopUp addItemWithTitle:
213 [NSString stringWithCString: hb_video_rates[i].string]];
215 [fVidRatePopUp selectItemAtIndex: 0];
217 /* Picture Settings */
218 [fPicLabelPAROutp setStringValue: @""];
219 [fPicLabelPAROutputX setStringValue: @""];
220 [fPicSettingPARWidth setStringValue: @""];
221 [fPicSettingPARHeight setStringValue: @""];
224 [fAudBitratePopUp removeAllItems];
225 for( int i = 0; i < hb_audio_bitrates_count; i++ )
227 [fAudBitratePopUp addItemWithTitle:
228 [NSString stringWithCString: hb_audio_bitrates[i].string]];
230 [fAudBitratePopUp selectItemAtIndex: hb_audio_bitrates_default];
232 /* Audio samplerate */
233 [fAudRatePopUp removeAllItems];
234 for( int i = 0; i < hb_audio_rates_count; i++ )
236 [fAudRatePopUp addItemWithTitle:
237 [NSString stringWithCString: hb_audio_rates[i].string]];
239 [fAudRatePopUp selectItemAtIndex: hb_audio_rates_default];
242 [fStatusField setStringValue: @""];
245 [fPauseButton setEnabled: NO];
246 [fRipButton setEnabled: NO];
249 /* We disable the Turbo 1st pass checkbox since we are not x264 */
250 [fVidTurboPassCheck setEnabled: NO];
251 [fVidTurboPassCheck setState: NSOffState];
254 // register a test notification and make
255 // it enabled by default
256 #define SERVICE_NAME @"Encode Done"
257 - (NSDictionary *)registrationDictionaryForGrowl
259 NSDictionary *registrationDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
260 [NSArray arrayWithObjects:SERVICE_NAME,nil], GROWL_NOTIFICATIONS_ALL,
261 [NSArray arrayWithObjects:SERVICE_NAME,nil], GROWL_NOTIFICATIONS_DEFAULT,
264 return registrationDictionary;
266 - (void) TranslateStrings
268 [fSrcDVD1Field setStringValue: _( @"DVD:" )];
269 [fSrcTitleField setStringValue: _( @"Title:" )];
270 [fSrcChapterField setStringValue: _( @"Chapters:" )];
271 [fSrcChapterToField setStringValue: _( @"to" )];
272 [fSrcDuration1Field setStringValue: _( @"Duration:" )];
274 [fDstFormatField setStringValue: _( @"File format:" )];
275 [fDstCodecsField setStringValue: _( @"Codecs:" )];
276 [fDstFile1Field setStringValue: _( @"File:" )];
277 [fDstBrowseButton setTitle: _( @"Browse" )];
279 [fVidRateField setStringValue: _( @"Framerate (fps):" )];
280 [fVidEncoderField setStringValue: _( @"Encoder:" )];
281 [fVidQualityField setStringValue: _( @"Quality:" )];
284 /***********************************************************************
286 ***********************************************************************
287 * Shows a progression bar on the dock icon, filled according to
288 * 'progress' (0.0 <= progress <= 1.0).
289 * Called with progress < 0.0 or progress > 1.0, restores the original
291 **********************************************************************/
292 - (void) UpdateDockIcon: (float) progress
296 NSBitmapImageRep * bmp;
298 uint32_t black = htonl( 0x000000FF );
299 uint32_t red = htonl( 0xFF0000FF );
300 uint32_t white = htonl( 0xFFFFFFFF );
301 int row_start, row_end;
304 /* Get application original icon */
305 icon = [NSImage imageNamed: @"NSApplicationIcon"];
307 if( progress < 0.0 || progress > 1.0 )
309 [NSApp setApplicationIconImage: icon];
313 /* Get it in a raw bitmap form */
314 tiff = [icon TIFFRepresentationUsingCompression:
315 NSTIFFCompressionNone factor: 1.0];
316 bmp = [NSBitmapImageRep imageRepWithData: tiff];
318 /* Draw the progression bar */
319 /* It's pretty simple (ugly?) now, but I'm no designer */
321 row_start = 3 * (int) [bmp size].height / 4;
322 row_end = 7 * (int) [bmp size].height / 8;
324 for( i = row_start; i < row_start + 2; i++ )
326 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
327 for( j = 0; j < (int) [bmp size].width; j++ )
332 for( i = row_start + 2; i < row_end - 2; i++ )
334 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
337 for( j = 2; j < (int) [bmp size].width - 2; j++ )
339 if( j < 2 + (int) ( ( [bmp size].width - 4.0 ) * progress ) )
351 for( i = row_end - 2; i < row_end; i++ )
353 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
354 for( j = 0; j < (int) [bmp size].width; j++ )
360 /* Now update the dock icon */
361 tiff = [bmp TIFFRepresentationUsingCompression:
362 NSTIFFCompressionNone factor: 1.0];
363 icon = [[NSImage alloc] initWithData: tiff];
364 [NSApp setApplicationIconImage: icon];
368 - (void) UpdateUI: (NSTimer *) timer
370 /* check to see if there has been a new scan done
371 this bypasses the constraints of HB_STATE_WORKING
372 not allowing setting a newly scanned source */
373 int checkScanCount = hb_get_scancount( fHandle );
374 if (checkScanCount > currentScanCount)
376 [fScanController Cancel: NULL];
377 [self ShowNewScan: NULL];
378 currentScanCount = checkScanCount;
385 hb_get_state( fHandle, &s );
393 case HB_STATE_SCANNING:
394 [fScanController UpdateUI: &s];
397 #define p s.param.scandone
398 case HB_STATE_SCANDONE:
400 [fScanController Cancel: NULL];
401 [self ShowNewScan: NULL];
406 #define p s.param.working
407 case HB_STATE_WORKING:
409 float progress_total;
410 NSMutableString * string;
411 /* Currently, p.job_cur and p.job_count get screwed up when adding
412 jobs during encoding, if they cannot be fixed in libhb, will implement a
413 nasty but working cocoa solution */
414 /* Update text field */
415 string = [NSMutableString stringWithFormat: _( @"Encoding: task %d of %d, %.2f %%" ), p.job_cur, p.job_count, 100.0 * p.progress];
419 [string appendFormat:
420 _( @" (%.2f fps, avg %.2f fps, ETA %02dh%02dm%02ds)" ),
421 p.rate_cur, p.rate_avg, p.hours, p.minutes, p.seconds];
423 [fStatusField setStringValue: string];
426 progress_total = ( p.progress + p.job_cur - 1 ) / p.job_count;
427 [fRipIndicator setIndeterminate: NO];
428 [fRipIndicator setDoubleValue: 100.0 * progress_total];
430 /* Update dock icon */
431 [self UpdateDockIcon: progress_total];
433 [fPauseButton setEnabled: YES];
434 [fPauseButton setTitle: _( @"Pause" )];
435 [fRipButton setEnabled: YES];
436 [fRipButton setTitle: _( @"Cancel" )];
444 #define p s.param.muxing
445 case HB_STATE_MUXING:
447 NSMutableString * string;
449 /* Update text field */
450 string = [NSMutableString stringWithFormat:
452 [fStatusField setStringValue: string];
455 [fRipIndicator setIndeterminate: YES];
456 [fRipIndicator startAnimation: nil];
458 /* Update dock icon */
459 [self UpdateDockIcon: 1.0];
461 [fPauseButton setEnabled: YES];
462 [fPauseButton setTitle: _( @"Pause" )];
463 [fRipButton setEnabled: YES];
464 [fRipButton setTitle: _( @"Cancel" )];
469 case HB_STATE_PAUSED:
470 [fStatusField setStringValue: _( @"Paused" )];
471 [fPauseButton setEnabled: YES];
472 [fPauseButton setTitle: _( @"Resume" )];
473 [fRipButton setEnabled: YES];
474 [fRipButton setTitle: _( @"Cancel" )];
477 case HB_STATE_WORKDONE:
479 [fStatusField setStringValue: _( @"Done." )];
480 [fRipIndicator setIndeterminate: NO];
481 [fRipIndicator setDoubleValue: 0.0];
482 [fRipButton setTitle: _( @"Start" )];
484 /* Restore dock icon */
485 [self UpdateDockIcon: -1.0];
487 [fPauseButton setEnabled: NO];
488 [fPauseButton setTitle: _( @"Pause" )];
489 [fRipButton setEnabled: YES];
490 [fRipButton setTitle: _( @"Start" )];
494 while( ( job = hb_job( fHandle, 0 ) ) )
496 hb_rem( fHandle, job );
498 /* Check to see if the encode state has not been cancelled
499 to determine if we should check for encode done notifications */
500 if (fEncodeState != 2) {
501 /* If Growl Notification or Window and Growl has been selected */
502 if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"AlertWhenDone"] isEqualToString: @"Growl Notification"] ||
503 [[[NSUserDefaults standardUserDefaults] stringForKey:@"AlertWhenDone"] isEqualToString: @"Alert Window And Growl"])
505 /*Growl Notification*/
506 [self showGrowlDoneNotification: NULL];
508 /* If Alert Window or Window and Growl has been selected */
509 if ([[[NSUserDefaults standardUserDefaults] stringForKey:@"AlertWhenDone"] isEqualToString: @"Alert Window"] ||
510 [[[NSUserDefaults standardUserDefaults] stringForKey:@"AlertWhenDone"] isEqualToString: @"Alert Window And Growl"])
512 /*On Screen Notification*/
515 status = NSRunAlertPanel(@"Put down that cocktail...",@"your HandBrake encode is done!", @"OK", nil, nil);
516 [NSApp requestUserAttention:NSCriticalRequest];
517 if ( status == NSAlertDefaultReturn )
519 [self EnableUI: YES];
524 [self EnableUI: YES];
529 [self EnableUI: YES];
535 /* Lets show the queue status
536 here in the main window*/
537 int queue_count = hb_count( fHandle );
540 [fQueueStatus setStringValue: [NSString stringWithFormat:
541 @"%d task%s in the queue",
542 queue_count, ( queue_count > 1 ) ? "s" : ""]];
546 [fQueueStatus setStringValue: @""];
549 [[NSRunLoop currentRunLoop] addTimer: [NSTimer
550 scheduledTimerWithTimeInterval: 0.2 target: self
551 selector: @selector( UpdateUI: ) userInfo: NULL repeats: FALSE]
552 forMode: NSModalPanelRunLoopMode];
554 - (IBAction) ShowNewScan:(id)sender
558 int indxpri=0; // Used to search the longuest title (default in combobox)
559 int longuestpri=0; // Used to search the longuest title (default in combobox)
561 //[fScanController UpdateUI: &s];
563 list = hb_get_titles( fHandle );
565 if( !hb_list_count( list ) )
567 /* We display a message if a valid dvd source was not chosen */
568 [fSrcDVD2Field setStringValue: @"No Valid DVD Source Chosen"];
569 currentSource = [fSrcDVD2Field stringValue];
573 [fSrcTitlePopUp removeAllItems];
574 for( int i = 0; i < hb_list_count( list ); i++ )
576 title = (hb_title_t *) hb_list_item( list, i );
577 /*Set DVD Name at top of window*/
578 [fSrcDVD2Field setStringValue:[NSString stringWithUTF8String: title->name]];
579 currentSource = [NSString stringWithUTF8String: title->dvd];
580 /* Use the dvd name in the default output field here
581 May want to add code to remove blank spaces for some dvd names*/
582 /* Check to see if the last destination has been set,use if so, if not, use Desktop */
583 if ([[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"])
585 [fDstFile2Field setStringValue: [NSString stringWithFormat:
586 @"%@/%@.mp4", [[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"],[NSString
587 stringWithUTF8String: title->name]]];
591 [fDstFile2Field setStringValue: [NSString stringWithFormat:
592 @"%@/Desktop/%@.mp4", NSHomeDirectory(),[NSString
593 stringWithUTF8String: title->name]]];
597 if (longuestpri < title->hours*60*60 + title->minutes *60 + title->seconds)
599 longuestpri=title->hours*60*60 + title->minutes *60 + title->seconds;
604 int format = [fDstFormatPopUp indexOfSelectedItem];
610 /*Get Default MP4 File Extension for mpeg4 (.mp4 or .m4v) from prefs*/
611 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultMpegName"] > 0)
629 NSString * string = [fDstFile2Field stringValue];
630 /* Add/replace File Output name to the correct extension*/
631 if( [string characterAtIndex: [string length] - 4] == '.' )
633 [fDstFile2Field setStringValue: [NSString stringWithFormat:
634 @"%@.%s", [string substringToIndex: [string length] - 4],
639 [fDstFile2Field setStringValue: [NSString stringWithFormat:
640 @"%@.%s", string, ext]];
644 [fSrcTitlePopUp addItemWithTitle: [NSString
645 stringWithFormat: @"%d - %02dh%02dm%02ds",
646 title->index, title->hours, title->minutes,
650 // Select the longuest title
651 [fSrcTitlePopUp selectItemAtIndex: indxpri];
652 /* We set the Settings Display to "Default" here
653 until we get default presets implemented */
654 [fPresetSelectedDisplay setStringValue: @"Default"];
655 /* We set the auto crop in the main window to value "1" just as in PictureController,
656 as it does not seem to be taken from any job-> variable */
657 [fPicSettingAutoCrop setStringValue: [NSString stringWithFormat:
660 [self TitlePopUpChanged: NULL];
661 [self EnableUI: YES];
662 [fPauseButton setEnabled: NO];
663 [fRipButton setEnabled: YES];
667 -(IBAction)showGrowlDoneNotification:(id)sender
671 [GrowlApplicationBridge
672 notifyWithTitle:@"Put down that cocktail..."
673 description:@"your HandBrake encode is done!"
674 notificationName:SERVICE_NAME
680 - (void) EnableUI: (bool) b
682 NSControl * controls[] =
683 { fSrcDVD1Field, fSrcDVD2Field, fSrcTitleField, fSrcTitlePopUp,
684 fSrcChapterField, fSrcChapterStartPopUp, fSrcChapterToField,
685 fSrcChapterEndPopUp, fSrcDuration1Field, fSrcDuration2Field,
686 fDstFormatField, fDstFormatPopUp, fDstCodecsField,
687 fDstCodecsPopUp, fDstFile1Field, fDstFile2Field,
688 fDstBrowseButton, fVidRateField, fVidRatePopUp,
689 fVidEncoderField, fVidEncoderPopUp, fVidQualityField,
690 fVidQualityMatrix, fVidGrayscaleCheck, fSubField, fSubPopUp,
691 fAudLang1Field, fAudLang1PopUp, fAudLang2Field, fAudLang2PopUp,
692 fAudTrack1MixLabel, fAudTrack1MixPopUp, fAudTrack2MixLabel, fAudTrack2MixPopUp,
693 fAudRateField, fAudRatePopUp, fAudBitrateField,
694 fAudBitratePopUp, fPictureButton,fQueueStatus,
695 fPicSrcWidth,fPicSrcHeight,fPicSettingWidth,fPicSettingHeight,
696 fPicSettingARkeep,fPicSettingDeinterlace,fPicSettingARkeepDsply,
697 fPicSettingDeinterlaceDsply,fPicLabelSettings,fPicLabelSrc,fPicLabelOutp,
698 fPicLabelAr,fPicLabelDeinter,fPicLabelSrcX,fPicLabelOutputX,
699 fPicLabelPAROutp,fPicLabelPAROutputX,fPicSettingPARWidth,fPicSettingPARHeight,
700 fPicSettingPARDsply,fPicLabelAnamorphic,tableView,fPresetsAdd,fPresetsDelete,
701 fCreateChapterMarkers,fX264optViewTitleLabel,fDisplayX264Options,fDisplayX264OptionsLabel,fX264optBframesLabel,
702 fX264optBframesPopUp,fX264optRefLabel,fX264optRefPopUp,fX264optNfpskipLabel,fX264optNfpskipSwitch,
703 fX264optNodctdcmtLabel,fX264optNodctdcmtSwitch,fX264optSubmeLabel,fX264optSubmePopUp,
704 fX264optTrellisLabel,fX264optTrellisPopUp,fX264optMixedRefsLabel,fX264optMixedRefsSwitch,
705 fX264optMotionEstLabel,fX264optMotionEstPopUp,fX264optMERangeLabel,fX264optMERangePopUp,
706 fX264optWeightBLabel,fX264optWeightBSwitch,fX264optBRDOLabel,fX264optBRDOSwitch,
707 fX264optBPyramidLabel,fX264optBPyramidSwitch,fX264optBiMELabel,fX264optBiMESwitch,
708 fX264optDirectPredLabel,fX264optDirectPredPopUp,fX264optDeblockLabel,
709 fX264optAlphaDeblockPopUp,fX264optBetaDeblockPopUp,fVidTurboPassCheck,fDstMpgLargeFileCheck,fPicSettingAutoCropLabel,
710 fPicSettingAutoCropDsply};
713 i < sizeof( controls ) / sizeof( NSControl * ); i++ )
715 if( [[controls[i] className] isEqualToString: @"NSTextField"] )
717 NSTextField * tf = (NSTextField *) controls[i];
718 if( ![tf isBezeled] )
720 [tf setTextColor: b ? [NSColor controlTextColor] :
721 [NSColor disabledControlTextColor]];
725 [controls[i] setEnabled: b];
731 /* if we're enabling the interface, check if the audio mixdown controls need to be enabled or not */
732 /* these will have been enabled by the mass control enablement above anyway, so we're sense-checking it here */
733 [self SetEnabledStateOfAudioMixdownControls: NULL];
737 [tableView setEnabled: NO];
741 [self VideoMatrixChanged: NULL];
744 - (IBAction) ShowScanPanel: (id) sender
746 [fScanController Show];
749 - (IBAction) OpenMainWindow: (id) sender
751 [fWindow makeKeyAndOrderFront:nil];
752 [fWindow setReleasedWhenClosed: YES];
754 - (BOOL) windowShouldClose: (id) sender
757 /* See if we are currently running */
759 hb_get_state( fHandle, &s );
760 if ( s.state == HB_STATE_WORKING)
762 /* If we are running, leave in memory when closing main window */
763 [fWindow setReleasedWhenClosed: NO];
769 /* Stop the application when the user closes the window */
770 [NSApp terminate: self];
776 - (IBAction) VideoMatrixChanged: (id) sender;
778 bool target, bitrate, quality;
780 target = bitrate = quality = false;
781 if( [fVidQualityMatrix isEnabled] )
783 switch( [fVidQualityMatrix selectedRow] )
796 [fVidTargetSizeField setEnabled: target];
797 [fVidBitrateField setEnabled: bitrate];
798 [fVidQualitySlider setEnabled: quality];
799 [fVidTwoPassCheck setEnabled: !quality &&
800 [fVidQualityMatrix isEnabled]];
803 [fVidTwoPassCheck setState: NSOffState];
806 [self QualitySliderChanged: sender];
807 [self CalculateBitrate: sender];
808 [self CustomSettingUsed: sender];
811 - (IBAction) QualitySliderChanged: (id) sender
813 [fVidConstantCell setTitle: [NSString stringWithFormat:
814 _( @"Constant quality: %.0f %%" ), 100.0 *
815 [fVidQualitySlider floatValue]]];
816 [self CustomSettingUsed: sender];
819 - (IBAction) BrowseFile: (id) sender
821 /* Open a panel to let the user choose and update the text field */
822 NSSavePanel * panel = [NSSavePanel savePanel];
823 /* We get the current file name and path from the destination field here */
824 [panel beginSheetForDirectory: [[fDstFile2Field stringValue] stringByDeletingLastPathComponent] file: [[fDstFile2Field stringValue] lastPathComponent]
825 modalForWindow: fWindow modalDelegate: self
826 didEndSelector: @selector( BrowseFileDone:returnCode:contextInfo: )
830 - (void) BrowseFileDone: (NSSavePanel *) sheet
831 returnCode: (int) returnCode contextInfo: (void *) contextInfo
833 if( returnCode == NSOKButton )
835 [fDstFile2Field setStringValue: [sheet filename]];
840 - (IBAction) ShowPicturePanel: (id) sender
842 hb_list_t * list = hb_get_titles( fHandle );
843 hb_title_t * title = (hb_title_t *) hb_list_item( list,
844 [fSrcTitlePopUp indexOfSelectedItem] );
846 /* Resize the panel */
848 newSize.width = 246 + title->width;
849 newSize.height = 80 + title->height;
850 [fPicturePanel setContentSize: newSize];
852 [fPictureController SetTitle: title];
854 [NSApp beginSheet: fPicturePanel modalForWindow: fWindow
855 modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
856 [NSApp runModalForWindow: fPicturePanel];
857 [NSApp endSheet: fPicturePanel];
858 [fPicturePanel orderOut: self];
859 [self CalculatePictureSizing: sender];
862 - (IBAction) ShowQueuePanel: (id) sender
864 /* Update the OutlineView */
865 [fQueueController Update: sender];
868 [NSApp beginSheet: fQueuePanel modalForWindow: fWindow
869 modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
870 [NSApp runModalForWindow: fQueuePanel];
871 [NSApp endSheet: fQueuePanel];
872 [fQueuePanel orderOut: self];
877 hb_list_t * list = hb_get_titles( fHandle );
878 hb_title_t * title = (hb_title_t *) hb_list_item( list,
879 [fSrcTitlePopUp indexOfSelectedItem] );
880 hb_job_t * job = title->job;
883 /* Chapter selection */
884 job->chapter_start = [fSrcChapterStartPopUp indexOfSelectedItem] + 1;
885 job->chapter_end = [fSrcChapterEndPopUp indexOfSelectedItem] + 1;
887 /* Format and codecs */
888 int format = [fDstFormatPopUp indexOfSelectedItem];
889 int codecs = [fDstCodecsPopUp indexOfSelectedItem];
890 job->mux = FormatSettings[format][codecs] & HB_MUX_MASK;
891 job->vcodec = FormatSettings[format][codecs] & HB_VCODEC_MASK;
892 job->acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
893 /* If mpeg-4, then set mpeg-4 specific options like chapters and > 4gb file sizes */
894 if ([fDstFormatPopUp indexOfSelectedItem] == 0)
896 /* We set the chapter marker extraction here based on the format being
897 mpeg4 and the checkbox being checked */
898 if ([fCreateChapterMarkers state] == NSOnState)
900 job->chapter_markers = 1;
904 job->chapter_markers = 0;
906 /* We set the largeFileSize (64 bit formatting) variable here to allow for > 4gb files based on the format being
907 mpeg4 and the checkbox being checked
908 *Note: this will break compatibility with some target devices like iPod, etc.!!!!*/
909 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"AllowLargeFiles"] > 0 && [fDstMpgLargeFileCheck state] == NSOnState)
911 job->largeFileSize = 1;
915 job->largeFileSize = 0;
920 if( ( job->vcodec & HB_VCODEC_FFMPEG ) &&
921 [fVidEncoderPopUp indexOfSelectedItem] > 0 )
923 job->vcodec = HB_VCODEC_XVID;
925 if( job->vcodec & HB_VCODEC_X264 )
927 if ([fVidEncoderPopUp indexOfSelectedItem] > 0 )
929 /* Just use new Baseline Level 3.0
930 Lets Deprecate Baseline Level 1.3h264_level*/
931 job->h264_level = 30;
932 job->mux = HB_MUX_IPOD;
933 /* move sanity check for iPod Encoding here */
934 job->pixel_ratio = 0 ;
938 /* Set this flag to switch from Constant Quantizer(default) to Constant Rate Factor Thanks jbrjake
939 Currently only used with Constant Quality setting*/
940 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultCrf"] > 0 && [fVidQualityMatrix selectedRow] == 2)
945 /* Below Sends x264 options to the core library if x264 is selected*/
946 /* Lets use this as per Nyx, Thanks Nyx!*/
947 job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */
948 /* Turbo first pass if two pass and Turbo First pass is selected */
949 if( [fVidTwoPassCheck state] == NSOnState && [fVidTurboPassCheck state] == NSOnState )
951 /* pass the "Turbo" string to be appended to the existing x264 opts string into a variable for the first pass */
952 NSString *firstPassOptStringTurbo = @":ref=1:subme=1:me=dia:analyse=none:weightb=0:trellis=0:no-fast-pskip=0:8x8dct=0";
953 /* append the "Turbo" string variable to the existing opts string.
954 Note: the "Turbo" string must be appended, not prepended to work properly*/
955 NSString *firstPassOptStringCombined = [[fDisplayX264Options stringValue] stringByAppendingString:firstPassOptStringTurbo];
956 strcpy(job->x264opts, [firstPassOptStringCombined UTF8String]);
960 strcpy(job->x264opts, [[fDisplayX264Options stringValue] UTF8String]);
963 job->h264_13 = [fVidEncoderPopUp indexOfSelectedItem];
967 if( [fVidRatePopUp indexOfSelectedItem] > 0 )
969 job->vrate = 27000000;
970 job->vrate_base = hb_video_rates[[fVidRatePopUp
971 indexOfSelectedItem]-1].rate;
975 job->vrate = title->rate;
976 job->vrate_base = title->rate_base;
979 switch( [fVidQualityMatrix selectedRow] )
983 Bitrate should already have been calculated and displayed
984 in fVidBitrateField, so let's just use it */
986 job->vquality = -1.0;
987 job->vbitrate = [fVidBitrateField intValue];
990 job->vquality = [fVidQualitySlider floatValue];
995 job->grayscale = ( [fVidGrayscaleCheck state] == NSOnState );
999 /* Subtitle settings */
1000 job->subtitle = [fSubPopUp indexOfSelectedItem] - 1;
1002 /* Audio tracks and mixdowns */
1003 /* check for the condition where track 2 has an audio selected, but track 1 does not */
1004 /* we will use track 2 as track 1 in this scenario */
1005 if ([fAudLang1PopUp indexOfSelectedItem] > 0)
1007 job->audios[0] = [fAudLang1PopUp indexOfSelectedItem] - 1;
1008 job->audios[1] = [fAudLang2PopUp indexOfSelectedItem] - 1; /* will be -1 if "none" is selected */
1009 job->audios[2] = -1;
1010 job->audio_mixdowns[0] = [[fAudTrack1MixPopUp selectedItem] tag];
1011 job->audio_mixdowns[1] = [[fAudTrack2MixPopUp selectedItem] tag];
1013 else if ([fAudLang2PopUp indexOfSelectedItem] > 0)
1015 job->audios[0] = [fAudLang2PopUp indexOfSelectedItem] - 1;
1016 job->audio_mixdowns[0] = [[fAudTrack2MixPopUp selectedItem] tag];
1017 job->audios[1] = -1;
1021 job->audios[0] = -1;
1024 /* Audio settings */
1025 job->arate = hb_audio_rates[[fAudRatePopUp
1026 indexOfSelectedItem]].rate;
1027 job->abitrate = [[fAudBitratePopUp selectedItem] tag];
1033 - (IBAction) AddToQueue: (id) sender
1035 /* We get the destination directory from the destingation field here */
1036 NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent];
1037 /* We check for a valid destination here */
1038 if ([[NSFileManager defaultManager] fileExistsAtPath:destinationDirectory] == 0)
1040 NSRunAlertPanel(@"Warning!", @"This is not a valid destination directory!", @"OK", nil, nil);
1045 hb_list_t * list = hb_get_titles( fHandle );
1046 hb_title_t * title = (hb_title_t *) hb_list_item( list,
1047 [fSrcTitlePopUp indexOfSelectedItem] );
1048 hb_job_t * job = title->job;
1052 /* Destination file */
1053 job->file = [[fDstFile2Field stringValue] UTF8String];
1055 if( [fVidTwoPassCheck state] == NSOnState )
1058 hb_add( fHandle, job );
1061 job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */
1062 strcpy(job->x264opts, [[fDisplayX264Options stringValue] UTF8String]);
1064 hb_add( fHandle, job );
1069 hb_add( fHandle, job );
1072 [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"];
1073 /* Lets try to update stuff, taken from remove in the queue controller */
1074 [fQueueController performSelectorOnMainThread: @selector( Update: )
1075 withObject: sender waitUntilDone: NO];
1079 - (IBAction) Rip: (id) sender
1081 /* Rip or Cancel ? */
1082 if( [[fRipButton title] isEqualToString: _( @"Cancel" )] )
1084 [self Cancel: sender];
1087 /* if there is no job in the queue, then add it to the queue and rip
1088 otherwise, there are already jobs in queue, so just rip the queue */
1089 int count = hb_count( fHandle );
1092 [self AddToQueue: sender];
1095 /* We check for duplicate name here */
1096 if( [[NSFileManager defaultManager] fileExistsAtPath:
1097 [fDstFile2Field stringValue]] )
1099 NSBeginCriticalAlertSheet( _( @"File already exists" ),
1100 _( @"Cancel" ), _( @"Overwrite" ), NULL, fWindow, self,
1101 @selector( OverwriteAlertDone:returnCode:contextInfo: ),
1102 NULL, NULL, [NSString stringWithFormat:
1103 _( @"Do you want to overwrite %@?" ),
1104 [fDstFile2Field stringValue]] );
1107 /* We get the destination directory from the destination field here */
1108 NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent];
1109 /* We check for a valid destination here */
1110 if ([[NSFileManager defaultManager] fileExistsAtPath:destinationDirectory] == 0)
1112 NSRunAlertPanel(@"Warning!", @"This is not a valid destination directory!", @"OK", nil, nil);
1116 [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"];
1124 - (void) OverwriteAlertDone: (NSWindow *) sheet
1125 returnCode: (int) returnCode contextInfo: (void *) contextInfo
1127 if( returnCode == NSAlertAlternateReturn )
1133 - (void) UpdateAlertDone: (NSWindow *) sheet
1134 returnCode: (int) returnCode contextInfo: (void *) contextInfo
1136 if( returnCode == NSAlertAlternateReturn )
1138 /* Show scan panel */
1139 [self performSelectorOnMainThread: @selector(ShowScanPanel:)
1140 withObject: NULL waitUntilDone: NO];
1144 /* Go to HandBrake homepage and exit */
1145 [self OpenHomepage: NULL];
1146 [NSApp terminate: self];
1151 /* Let libhb do the job */
1152 hb_start( fHandle );
1153 /*set the fEncodeState State */
1156 /* Disable interface */
1157 //[self EnableUI: NO];
1158 [fPauseButton setEnabled: NO];
1159 [fRipButton setEnabled: NO];
1162 - (IBAction) Cancel: (id) sender
1164 NSBeginCriticalAlertSheet( _( @"Cancel - Are you sure?" ),
1165 _( @"Keep working" ), _( @"Cancel encoding" ), NULL, fWindow, self,
1166 @selector( _Cancel:returnCode:contextInfo: ), NULL, NULL,
1167 _( @"Encoding won't be recoverable." ) );
1170 - (void) _Cancel: (NSWindow *) sheet
1171 returnCode: (int) returnCode contextInfo: (void *) contextInfo
1173 if( returnCode == NSAlertAlternateReturn )
1176 [fPauseButton setEnabled: NO];
1177 [fRipButton setEnabled: NO];
1178 /*set the fEncodeState State */
1183 - (IBAction) Pause: (id) sender
1185 [fPauseButton setEnabled: NO];
1186 [fRipButton setEnabled: NO];
1188 if( [[fPauseButton title] isEqualToString: _( @"Resume" )] )
1190 hb_resume( fHandle );
1194 hb_pause( fHandle );
1198 - (IBAction) TitlePopUpChanged: (id) sender
1200 hb_list_t * list = hb_get_titles( fHandle );
1201 hb_title_t * title = (hb_title_t*)
1202 hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
1205 /* If Auto Naming is on. We create an output filename of dvd name - title number */
1206 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultAutoNaming"] > 0)
1208 [fDstFile2Field setStringValue: [NSString stringWithFormat:
1209 @"%@/%@-%d.%@", [[fDstFile2Field stringValue] stringByDeletingLastPathComponent],
1210 [NSString stringWithUTF8String: title->name],
1211 [fSrcTitlePopUp indexOfSelectedItem] + 1,
1212 [[fDstFile2Field stringValue] pathExtension]]];
1215 /* Update chapter popups */
1216 [fSrcChapterStartPopUp removeAllItems];
1217 [fSrcChapterEndPopUp removeAllItems];
1218 for( int i = 0; i < hb_list_count( title->list_chapter ); i++ )
1220 [fSrcChapterStartPopUp addItemWithTitle: [NSString
1221 stringWithFormat: @"%d", i + 1]];
1222 [fSrcChapterEndPopUp addItemWithTitle: [NSString
1223 stringWithFormat: @"%d", i + 1]];
1225 [fSrcChapterStartPopUp selectItemAtIndex: 0];
1226 [fSrcChapterEndPopUp selectItemAtIndex:
1227 hb_list_count( title->list_chapter ) - 1];
1228 [self ChapterPopUpChanged: NULL];
1230 /* Start Get and set the initial pic size for display */
1231 hb_job_t * job = title->job;
1233 /* Turn Deinterlace on/off depending on the preference */
1234 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultDeinterlaceOn"] > 0)
1236 job->deinterlace = 1;
1240 job->deinterlace = 0;
1243 /* Pixel Ratio Setting */
1244 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"PixelRatio"])
1247 job->pixel_ratio = 1 ;
1251 job->pixel_ratio = 0 ;
1253 /*Set Source Size Fields Here */
1254 [fPicSrcWidth setStringValue: [NSString stringWithFormat:
1255 @"%d", fTitle->width]];
1256 [fPicSrcHeight setStringValue: [NSString stringWithFormat:
1257 @"%d", fTitle->height]];
1258 /* We get the originial output picture width and height and put them
1259 in variables for use with some presets later on */
1260 PicOrigOutputWidth = job->width;
1261 PicOrigOutputHeight = job->height;
1262 /* we test getting the max output value for pic sizing here to be used later*/
1263 [fPicSettingWidth setStringValue: [NSString stringWithFormat:
1264 @"%d", PicOrigOutputWidth]];
1265 [fPicSettingHeight setStringValue: [NSString stringWithFormat:
1266 @"%d", PicOrigOutputHeight]];
1267 /* we run the picture size values through
1268 CalculatePictureSizing to get all picture size
1270 [self CalculatePictureSizing: NULL];
1271 /* Run Through EncoderPopUpChanged to see if there
1272 needs to be any pic value modifications based on encoder settings */
1273 //[self EncoderPopUpChanged: NULL];
1274 /* END Get and set the initial pic size for display */
1276 /* Update subtitle popups */
1277 hb_subtitle_t * subtitle;
1278 [fSubPopUp removeAllItems];
1279 [fSubPopUp addItemWithTitle: @"None"];
1280 for( int i = 0; i < hb_list_count( title->list_subtitle ); i++ )
1282 subtitle = (hb_subtitle_t *) hb_list_item( title->list_subtitle, i );
1284 /* We cannot use NSPopUpButton's addItemWithTitle because
1285 it checks for duplicate entries */
1286 [[fSubPopUp menu] addItemWithTitle: [NSString stringWithCString:
1287 subtitle->lang] action: NULL keyEquivalent: @""];
1289 [fSubPopUp selectItemAtIndex: 0];
1291 /* Update chapter table */
1292 [fChapterTitlesDelegate resetWithTitle:title];
1293 [fChapterTable reloadData];
1295 /* Update audio popups */
1296 [self AddAllAudioTracksToPopUp: fAudLang1PopUp];
1297 [self AddAllAudioTracksToPopUp: fAudLang2PopUp];
1298 /* search for the first instance of our prefs default language for track 1, and set track 2 to "none" */
1299 NSString * audioSearchPrefix = [[NSUserDefaults standardUserDefaults] stringForKey:@"DefaultLanguage"];
1300 [self SelectAudioTrackInPopUp: fAudLang1PopUp searchPrefixString: audioSearchPrefix selectIndexIfNotFound: 1];
1301 [self SelectAudioTrackInPopUp: fAudLang2PopUp searchPrefixString: NULL selectIndexIfNotFound: 0];
1303 /* changing the title may have changed the audio channels on offer, */
1304 /* so call AudioTrackPopUpChanged for both audio tracks to update the mixdown popups */
1305 [self AudioTrackPopUpChanged: fAudLang1PopUp];
1306 [self AudioTrackPopUpChanged: fAudLang2PopUp];
1310 - (IBAction) ChapterPopUpChanged: (id) sender
1313 /* If start chapter popup is greater than end chapter popup,
1314 we set the end chapter popup to the same as start chapter popup */
1315 if ([fSrcChapterStartPopUp indexOfSelectedItem] > [fSrcChapterEndPopUp indexOfSelectedItem])
1317 [fSrcChapterEndPopUp selectItemAtIndex: [fSrcChapterStartPopUp indexOfSelectedItem]];
1322 hb_list_t * list = hb_get_titles( fHandle );
1323 hb_title_t * title = (hb_title_t *)
1324 hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
1326 hb_chapter_t * chapter;
1327 int64_t duration = 0;
1328 for( int i = [fSrcChapterStartPopUp indexOfSelectedItem];
1329 i <= [fSrcChapterEndPopUp indexOfSelectedItem]; i++ )
1331 chapter = (hb_chapter_t *) hb_list_item( title->list_chapter, i );
1332 duration += chapter->duration;
1335 duration /= 90000; /* pts -> seconds */
1336 [fSrcDuration2Field setStringValue: [NSString stringWithFormat:
1337 @"%02lld:%02lld:%02lld", duration / 3600, ( duration / 60 ) % 60,
1340 [self CalculateBitrate: sender];
1343 - (IBAction) FormatPopUpChanged: (id) sender
1345 NSString * string = [fDstFile2Field stringValue];
1346 int format = [fDstFormatPopUp indexOfSelectedItem];
1348 /* Initially set the large file (64 bit formatting) output checkbox to hidden */
1349 [fDstMpgLargeFileCheck setHidden: YES];
1350 /* Update the codecs popup */
1351 [fDstCodecsPopUp removeAllItems];
1355 /*Get Default MP4 File Extension*/
1356 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultMpegName"] > 0)
1364 [fDstCodecsPopUp addItemWithTitle:
1365 _( @"MPEG-4 Video / AAC Audio" )];
1366 [fDstCodecsPopUp addItemWithTitle:
1367 _( @"AVC/H.264 Video / AAC Audio" )];
1368 /* We enable the create chapters checkbox here since we are .mp4*/
1369 [fCreateChapterMarkers setEnabled: YES];
1370 /* We show the Large File (64 bit formatting) checkbox since we are .mp4
1371 if we have enabled the option in the global preferences*/
1372 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"AllowLargeFiles"] > 0)
1374 [fDstMpgLargeFileCheck setHidden: NO];
1378 /* if not enable in global preferences, we additionaly sanity check that the
1379 hidden checkbox is set to off. */
1380 [fDstMpgLargeFileCheck setState: NSOffState];
1385 [fDstCodecsPopUp addItemWithTitle:
1386 _( @"MPEG-4 Video / MP3 Audio" )];
1387 [fDstCodecsPopUp addItemWithTitle:
1388 _( @"MPEG-4 Video / AC-3 Audio" )];
1389 [fDstCodecsPopUp addItemWithTitle:
1390 _( @"AVC/H.264 Video / MP3 Audio" )];
1391 [fDstCodecsPopUp addItemWithTitle:
1392 _( @"AVC/H.264 Video / AC-3 Audio" )];
1393 /* We disable the create chapters checkbox here since we are NOT .mp4
1394 and make sure it is unchecked*/
1395 [fCreateChapterMarkers setEnabled: NO];
1396 [fCreateChapterMarkers setState: NSOffState];
1400 [fDstCodecsPopUp addItemWithTitle:
1401 _( @"MPEG-4 Video / Vorbis Audio" )];
1402 [fDstCodecsPopUp addItemWithTitle:
1403 _( @"MPEG-4 Video / MP3 Audio" )];
1404 /* We disable the create chapters checkbox here since we are NOT .mp4
1405 and make sure it is unchecked*/
1406 [fCreateChapterMarkers setEnabled: NO];
1407 [fCreateChapterMarkers setState: NSOffState];
1410 [self CodecsPopUpChanged: NULL];
1412 /* Add/replace to the correct extension */
1413 if( [string characterAtIndex: [string length] - 4] == '.' )
1415 [fDstFile2Field setStringValue: [NSString stringWithFormat:
1416 @"%@.%s", [string substringToIndex: [string length] - 4],
1421 [fDstFile2Field setStringValue: [NSString stringWithFormat:
1422 @"%@.%s", string, ext]];
1425 /* changing the format may mean that we can / can't offer mono or 6ch, */
1426 /* so call AudioTrackPopUpChanged for both audio tracks to update the mixdown popups */
1427 [self AudioTrackPopUpChanged: fAudLang1PopUp];
1428 [self AudioTrackPopUpChanged: fAudLang2PopUp];
1429 /* We call the method to properly enable/disable turbo 2 pass */
1430 [self TwoPassCheckboxChanged: sender];
1431 /* We call method method to change UI to reflect whether a preset is used or not*/
1432 [self CustomSettingUsed: sender];
1436 - (IBAction) CodecsPopUpChanged: (id) sender
1438 int format = [fDstFormatPopUp indexOfSelectedItem];
1439 int codecs = [fDstCodecsPopUp indexOfSelectedItem];
1440 [fX264optView setHidden: YES];
1441 [fX264optViewTitleLabel setStringValue: @"Only Used With The x264 (H.264) Codec"];
1444 /* Update the encoder popup*/
1445 if( ( FormatSettings[format][codecs] & HB_VCODEC_X264 ) )
1447 /* MPEG-4 -> H.264 */
1448 [fVidEncoderPopUp removeAllItems];
1449 [fVidEncoderPopUp addItemWithTitle: @"x264 (h.264 Main)"];
1450 [fVidEncoderPopUp addItemWithTitle: @"x264 (h.264 iPod)"];
1451 [fVidEncoderPopUp selectItemAtIndex: 0];
1452 [fX264optView setHidden: NO];
1453 [fX264optViewTitleLabel setStringValue: @""];
1458 else if( ( FormatSettings[format][codecs] & HB_VCODEC_FFMPEG ) )
1460 /* H.264 -> MPEG-4 */
1461 [fVidEncoderPopUp removeAllItems];
1462 [fVidEncoderPopUp addItemWithTitle: @"FFmpeg"];
1463 [fVidEncoderPopUp addItemWithTitle: @"XviD"];
1464 [fVidEncoderPopUp selectItemAtIndex: 0];
1468 if( FormatSettings[format][codecs] & HB_ACODEC_AC3 )
1470 /* AC-3 pass-through: disable samplerate and bitrate */
1471 [fAudRatePopUp setEnabled: NO];
1472 [fAudBitratePopUp setEnabled: NO];
1476 [fAudRatePopUp setEnabled: YES];
1477 [fAudBitratePopUp setEnabled: YES];
1479 /* changing the codecs on offer may mean that we can / can't offer mono or 6ch, */
1480 /* so call AudioTrackPopUpChanged for both audio tracks to update the mixdown popups */
1481 [self AudioTrackPopUpChanged: fAudLang1PopUp];
1482 [self AudioTrackPopUpChanged: fAudLang2PopUp];
1484 [self CalculateBitrate: sender];
1485 [self TwoPassCheckboxChanged: sender];
1488 - (IBAction) EncoderPopUpChanged: (id) sender
1491 /* Check to see if we need to modify the job pic values based on x264 (iPod) encoder selection */
1492 if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [fDstCodecsPopUp indexOfSelectedItem] == 1 && [fVidEncoderPopUp indexOfSelectedItem] == 1)
1494 hb_job_t * job = fTitle->job;
1495 job->pixel_ratio = 0 ;
1497 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPicSizeAutoiPod"] > 0)
1500 if (job->width > 640)
1504 job->keep_ratio = 1;
1505 hb_fix_aspect( job, HB_KEEP_WIDTH );
1508 /* Make sure the 64bit formatting checkbox is off */
1509 [fDstMpgLargeFileCheck setState: NSOffState];
1512 [self CalculatePictureSizing: sender];
1513 [self TwoPassCheckboxChanged: sender];
1516 - (IBAction) TwoPassCheckboxChanged: (id) sender
1518 /* check to see if x264 is chosen */
1519 if([fDstFormatPopUp indexOfSelectedItem] == 0 && [fDstCodecsPopUp indexOfSelectedItem] == 1)
1521 if( [fVidTwoPassCheck state] == NSOnState)
1523 [fVidTurboPassCheck setHidden: NO];
1527 [fVidTurboPassCheck setHidden: YES];
1528 [fVidTurboPassCheck setState: NSOffState];
1530 /* Make sure Two Pass is checked if Turbo is checked */
1531 if( [fVidTurboPassCheck state] == NSOnState)
1533 [fVidTwoPassCheck setState: NSOnState];
1538 [fVidTurboPassCheck setHidden: YES];
1539 [fVidTurboPassCheck setState: NSOffState];
1542 /* We call method method to change UI to reflect whether a preset is used or not*/
1543 [self CustomSettingUsed: sender];
1546 - (IBAction) SetEnabledStateOfAudioMixdownControls: (id) sender
1549 /* enable/disable the mixdown text and popupbutton for audio track 1 */
1550 [fAudTrack1MixPopUp setEnabled: ([fAudLang1PopUp indexOfSelectedItem] == 0) ? NO : YES];
1551 [fAudTrack1MixLabel setTextColor: ([fAudLang1PopUp indexOfSelectedItem] == 0) ?
1552 [NSColor disabledControlTextColor] : [NSColor controlTextColor]];
1554 /* enable/disable the mixdown text and popupbutton for audio track 2 */
1555 [fAudTrack2MixPopUp setEnabled: ([fAudLang2PopUp indexOfSelectedItem] == 0) ? NO : YES];
1556 [fAudTrack2MixLabel setTextColor: ([fAudLang2PopUp indexOfSelectedItem] == 0) ?
1557 [NSColor disabledControlTextColor] : [NSColor controlTextColor]];
1561 - (IBAction) AddAllAudioTracksToPopUp: (id) sender
1564 hb_list_t * list = hb_get_titles( fHandle );
1565 hb_title_t * title = (hb_title_t*)
1566 hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
1570 [sender removeAllItems];
1571 [sender addItemWithTitle: _( @"None" )];
1572 for( int i = 0; i < hb_list_count( title->list_audio ); i++ )
1574 audio = (hb_audio_t *) hb_list_item( title->list_audio, i );
1575 [[sender menu] addItemWithTitle:
1576 [NSString stringWithCString: audio->lang]
1577 action: NULL keyEquivalent: @""];
1579 [sender selectItemAtIndex: 0];
1583 - (IBAction) SelectAudioTrackInPopUp: (id) sender searchPrefixString: (NSString *) searchPrefixString selectIndexIfNotFound: (int) selectIndexIfNotFound
1586 /* this method can be used to find a language, or a language-and-source-format combination, by passing in the appropriate string */
1587 /* e.g. to find the first French track, pass in an NSString * of "Francais" */
1588 /* e.g. to find the first English 5.1 AC3 track, pass in an NSString * of "English (AC3) (5.1 ch)" */
1589 /* if no matching track is found, then selectIndexIfNotFound is used to choose which track to select instead */
1591 if (searchPrefixString != NULL)
1594 for( int i = 0; i < [sender numberOfItems]; i++ )
1596 /* Try to find the desired search string */
1597 if ([[[sender itemAtIndex: i] title] hasPrefix:searchPrefixString])
1599 [sender selectItemAtIndex: i];
1603 /* couldn't find the string, so select the requested "search string not found" item */
1604 /* index of 0 means select the "none" item */
1605 /* index of 1 means select the first audio track */
1606 [sender selectItemAtIndex: selectIndexIfNotFound];
1610 /* if no search string is provided, then select the selectIndexIfNotFound item */
1611 [sender selectItemAtIndex: selectIndexIfNotFound];
1616 - (IBAction) AudioTrackPopUpChanged: (id) sender
1618 /* utility function to call AudioTrackPopUpChanged without passing in a mixdown-to-use */
1619 [self AudioTrackPopUpChanged: sender mixdownToUse: 0];
1622 - (IBAction) AudioTrackPopUpChanged: (id) sender mixdownToUse: (int) mixdownToUse
1625 /* make sure we have a selected title before continuing */
1626 if (fTitle == NULL) return;
1628 /* find out if audio track 1 or 2 was changed - this is passed to us in the tag of the sender */
1629 /* the sender will have been either fAudLang1PopUp (tag = 0) or fAudLang2PopUp (tag = 1) */
1630 int thisAudio = [sender tag];
1632 /* get the index of the selected audio */
1633 int thisAudioIndex = [sender indexOfSelectedItem] - 1;
1635 /* Handbrake can't currently cope with ripping the same source track twice */
1636 /* So, if this audio is also selected in the other audio track popup, set that popup's selection to "none" */
1637 /* get a reference to the two audio track popups */
1638 NSPopUpButton * thisAudioPopUp = (thisAudio == 1 ? fAudLang2PopUp : fAudLang1PopUp);
1639 NSPopUpButton * otherAudioPopUp = (thisAudio == 1 ? fAudLang1PopUp : fAudLang2PopUp);
1640 /* if the same track is selected in the other audio popup, then select "none" in that popup */
1641 /* unless, of course, both are selected as "none!" */
1642 if ([thisAudioPopUp indexOfSelectedItem] != 0 && [thisAudioPopUp indexOfSelectedItem] == [otherAudioPopUp indexOfSelectedItem]) {
1643 [otherAudioPopUp selectItemAtIndex: 0];
1644 [self AudioTrackPopUpChanged: otherAudioPopUp];
1647 /* pointer for the hb_audio_s struct we will use later on */
1650 /* find out what the currently-selected output audio codec is */
1651 int format = [fDstFormatPopUp indexOfSelectedItem];
1652 int codecs = [fDstCodecsPopUp indexOfSelectedItem];
1653 int acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
1655 /* pointer to this track's mixdown NSPopUpButton */
1656 NSTextField * mixdownTextField;
1657 NSPopUpButton * mixdownPopUp;
1659 /* find our mixdown NSTextField and NSPopUpButton */
1662 mixdownTextField = fAudTrack1MixLabel;
1663 mixdownPopUp = fAudTrack1MixPopUp;
1667 mixdownTextField = fAudTrack2MixLabel;
1668 mixdownPopUp = fAudTrack2MixPopUp;
1671 /* delete the previous audio mixdown options */
1672 [mixdownPopUp removeAllItems];
1674 /* check if the audio mixdown controls need their enabled state changing */
1675 [self SetEnabledStateOfAudioMixdownControls: NULL];
1677 if (thisAudioIndex != -1)
1681 audio = (hb_audio_t *) hb_list_item( fTitle->list_audio, thisAudioIndex );
1685 /* find out if our selected output audio codec supports mono and / or 6ch */
1686 /* we also check for an input codec of AC3 or DCA,
1687 as they are the only libraries able to do the mixdown to mono / conversion to 6-ch */
1688 /* audioCodecsSupportMono and audioCodecsSupport6Ch are the same for now,
1689 but this may change in the future, so they are separated for flexibility */
1690 int audioCodecsSupportMono = ((audio->codec == HB_ACODEC_AC3 ||
1691 audio->codec == HB_ACODEC_DCA) && acodec == HB_ACODEC_FAAC);
1692 int audioCodecsSupport6Ch = ((audio->codec == HB_ACODEC_AC3 ||
1693 audio->codec == HB_ACODEC_DCA) && acodec == HB_ACODEC_FAAC);
1695 /* check for AC-3 passthru */
1696 if (audio->codec == HB_ACODEC_AC3 && acodec == HB_ACODEC_AC3)
1698 [[mixdownPopUp menu] addItemWithTitle:
1699 [NSString stringWithCString: "AC3 Passthru"]
1700 action: NULL keyEquivalent: @""];
1705 /* add the appropriate audio mixdown menuitems to the popupbutton */
1706 /* in each case, we set the new menuitem's tag to be the amixdown value for that mixdown,
1707 so that we can reference the mixdown later */
1709 /* keep a track of the min and max mixdowns we used, so we can select the best match later */
1710 int minMixdownUsed = 0;
1711 int maxMixdownUsed = 0;
1713 /* get the input channel layout without any lfe channels */
1714 int layout = audio->input_channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK;
1716 /* do we want to add a mono option? */
1717 if (audioCodecsSupportMono == 1) {
1718 id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
1719 [NSString stringWithCString: hb_audio_mixdowns[0].human_readable_name]
1720 action: NULL keyEquivalent: @""];
1721 [menuItem setTag: hb_audio_mixdowns[0].amixdown];
1722 if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[0].amixdown;
1723 maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[0].amixdown);
1726 /* do we want to add a stereo option? */
1727 /* offer stereo if we have a mono source and non-mono-supporting codecs, as otherwise we won't have a mixdown at all */
1728 /* also offer stereo if we have a stereo-or-better source */
1729 if ((layout == HB_INPUT_CH_LAYOUT_MONO && audioCodecsSupportMono == 0) || layout >= HB_INPUT_CH_LAYOUT_STEREO) {
1730 id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
1731 [NSString stringWithCString: hb_audio_mixdowns[1].human_readable_name]
1732 action: NULL keyEquivalent: @""];
1733 [menuItem setTag: hb_audio_mixdowns[1].amixdown];
1734 if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[1].amixdown;
1735 maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[1].amixdown);
1738 /* do we want to add a dolby surround (DPL1) option? */
1739 if (layout == HB_INPUT_CH_LAYOUT_3F1R || layout == HB_INPUT_CH_LAYOUT_3F2R || layout == HB_INPUT_CH_LAYOUT_DOLBY) {
1740 id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
1741 [NSString stringWithCString: hb_audio_mixdowns[2].human_readable_name]
1742 action: NULL keyEquivalent: @""];
1743 [menuItem setTag: hb_audio_mixdowns[2].amixdown];
1744 if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[2].amixdown;
1745 maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[2].amixdown);
1748 /* do we want to add a dolby pro logic 2 (DPL2) option? */
1749 if (layout == HB_INPUT_CH_LAYOUT_3F2R) {
1750 id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
1751 [NSString stringWithCString: hb_audio_mixdowns[3].human_readable_name]
1752 action: NULL keyEquivalent: @""];
1753 [menuItem setTag: hb_audio_mixdowns[3].amixdown];
1754 if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[3].amixdown;
1755 maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[3].amixdown);
1758 /* do we want to add a 6-channel discrete option? */
1759 if (audioCodecsSupport6Ch == 1 && layout == HB_INPUT_CH_LAYOUT_3F2R && (audio->input_channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE)) {
1760 id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
1761 [NSString stringWithCString: hb_audio_mixdowns[4].human_readable_name]
1762 action: NULL keyEquivalent: @""];
1763 [menuItem setTag: hb_audio_mixdowns[4].amixdown];
1764 if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[4].amixdown;
1765 maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[4].amixdown);
1768 /* auto-select the best mixdown based on our saved mixdown preference */
1770 /* for now, this is hard-coded to a "best" mixdown of HB_AMIXDOWN_DOLBYPLII */
1771 /* ultimately this should be a prefs option */
1774 /* if we passed in a mixdown to use - in order to load a preset - then try and use it */
1775 if (mixdownToUse > 0)
1777 useMixdown = mixdownToUse;
1781 useMixdown = HB_AMIXDOWN_DOLBYPLII;
1784 /* if useMixdown > maxMixdownUsed, then use maxMixdownUsed */
1785 if (useMixdown > maxMixdownUsed) useMixdown = maxMixdownUsed;
1787 /* if useMixdown < minMixdownUsed, then use minMixdownUsed */
1788 if (useMixdown < minMixdownUsed) useMixdown = minMixdownUsed;
1790 /* select the (possibly-amended) preferred mixdown */
1791 [mixdownPopUp selectItemWithTag: useMixdown];
1793 /* lets call the AudioTrackMixdownChanged method here to determine appropriate bitrates, etc. */
1794 [self AudioTrackMixdownChanged: NULL];
1801 /* see if the new audio track choice will change the bitrate we need */
1802 [self CalculateBitrate: sender];
1805 - (IBAction) AudioTrackMixdownChanged: (id) sender
1808 /* find out what the currently-selected output audio codec is */
1809 int format = [fDstFormatPopUp indexOfSelectedItem];
1810 int codecs = [fDstCodecsPopUp indexOfSelectedItem];
1811 int acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
1813 /* storage variable for the min and max bitrate allowed for this codec */
1819 case HB_ACODEC_FAAC:
1820 /* check if we have a 6ch discrete conversion in either audio track */
1821 if ([[fAudTrack1MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH || [[fAudTrack2MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH)
1823 /* FAAC is happy using our min bitrate of 32 kbps, even for 6ch */
1825 /* If either mixdown popup includes 6-channel discrete, then allow up to 384 kbps */
1831 /* FAAC is happy using our min bitrate of 32 kbps for stereo or mono */
1833 /* FAAC won't honour anything more than 160 for stereo, so let's not offer it */
1834 /* note: haven't dealt with mono separately here, FAAC will just use the max it can */
1839 case HB_ACODEC_LAME:
1840 /* Lame is happy using our min bitrate of 32 kbps */
1842 /* Lame won't encode if the bitrate is higher than 320 kbps */
1846 case HB_ACODEC_VORBIS:
1847 /* Vorbis causes a crash if we use a bitrate below 48 kbps */
1849 /* Vorbis can cope with 384 kbps quite happily, even for stereo */
1854 /* AC3 passthru disables the bitrate dropdown anyway, so we might as well just use the min and max bitrate */
1860 [fAudBitratePopUp removeAllItems];
1862 for( int i = 0; i < hb_audio_bitrates_count; i++ )
1864 if (hb_audio_bitrates[i].rate >= minbitrate && hb_audio_bitrates[i].rate <= maxbitrate)
1866 /* add a new menuitem for this bitrate */
1867 id<NSMenuItem> menuItem = [[fAudBitratePopUp menu] addItemWithTitle:
1868 [NSString stringWithCString: hb_audio_bitrates[i].string]
1869 action: NULL keyEquivalent: @""];
1870 /* set its tag to be the actual bitrate as an integer, so we can retrieve it later */
1871 [menuItem setTag: hb_audio_bitrates[i].rate];
1875 /* select the default bitrate (but use 384 for 6-ch AAC) */
1876 if ([[fAudTrack1MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH || [[fAudTrack2MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH)
1878 [fAudBitratePopUp selectItemWithTag: 384];
1882 [fAudBitratePopUp selectItemWithTag: hb_audio_bitrates[hb_audio_bitrates_default].rate];
1886 /* lets set the picture size back to the max from right after title scan
1887 Lets use an IBAction here as down the road we could always use a checkbox
1888 in the gui to easily take the user back to max. Remember, the compiler
1889 resolves IBActions down to -(void) during compile anyway */
1890 - (IBAction) RevertPictureSizeToMax: (id) sender
1892 hb_job_t * job = fTitle->job;
1893 /* We use the output picture width and height
1894 as calculated from libhb right after title is set
1895 in TitlePopUpChanged */
1896 job->width = PicOrigOutputWidth;
1897 job->height = PicOrigOutputHeight;
1901 [self CalculatePictureSizing: sender];
1902 /* We call method method to change UI to reflect whether a preset is used or not*/
1903 [self CustomSettingUsed: sender];
1907 /* Get and Display Current Pic Settings in main window */
1908 - (IBAction) CalculatePictureSizing: (id) sender
1912 [fPicSettingWidth setStringValue: [NSString stringWithFormat:
1913 @"%d", fTitle->job->width]];
1914 [fPicSettingHeight setStringValue: [NSString stringWithFormat:
1915 @"%d", fTitle->job->height]];
1916 [fPicSettingARkeep setStringValue: [NSString stringWithFormat:
1917 @"%d", fTitle->job->keep_ratio]];
1918 [fPicSettingDeinterlace setStringValue: [NSString stringWithFormat:
1919 @"%d", fTitle->job->deinterlace]];
1920 [fPicSettingPAR setStringValue: [NSString stringWithFormat:
1921 @"%d", fTitle->job->pixel_ratio]];
1923 if (fTitle->job->pixel_ratio == 1)
1925 int titlewidth = fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3];
1926 int arpwidth = fTitle->job->pixel_aspect_width;
1927 int arpheight = fTitle->job->pixel_aspect_height;
1928 int displayparwidth = titlewidth * arpwidth / arpheight;
1929 int displayparheight = fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1];
1930 [fPicSettingHeight setStringValue: [NSString stringWithFormat:
1931 @"%d", displayparheight]];
1932 [fPicLabelPAROutp setStringValue: @"Anamorphic Output:"];
1933 [fPicLabelPAROutputX setStringValue: @"x"];
1934 [fPicSettingPARWidth setStringValue: [NSString stringWithFormat:
1935 @"%d", displayparwidth]];
1936 [fPicSettingPARHeight setStringValue: [NSString stringWithFormat:
1937 @"%d", displayparheight]];
1939 fTitle->job->keep_ratio = 0;
1943 [fPicLabelPAROutp setStringValue: @""];
1944 [fPicLabelPAROutputX setStringValue: @""];
1945 [fPicSettingPARWidth setStringValue: @""];
1946 [fPicSettingPARHeight setStringValue: @""];
1949 /* Set ON/Off values for the deinterlace/keep aspect ratio according to boolean */
1950 if (fTitle->job->keep_ratio > 0)
1952 [fPicSettingARkeepDsply setStringValue: @"On"];
1956 [fPicSettingARkeepDsply setStringValue: @"Off"];
1958 if (fTitle->job->deinterlace > 0)
1960 [fPicSettingDeinterlaceDsply setStringValue: @"On"];
1964 [fPicSettingDeinterlaceDsply setStringValue: @"Off"];
1966 if (fTitle->job->pixel_ratio > 0)
1968 [fPicSettingPARDsply setStringValue: @"On"];
1972 [fPicSettingPARDsply setStringValue: @"Off"];
1974 /* Set the display field for crop as per boolean */
1975 if ([[fPicSettingAutoCrop stringValue] isEqualToString: @"0"])
1977 [fPicSettingAutoCropDsply setStringValue: @"Custom"];
1981 [fPicSettingAutoCropDsply setStringValue: @"Auto"];
1984 /* below will trigger the preset, if selected, to be
1985 changed to "Custom". Lets comment out for now until
1986 we figure out a way to determine if the picture values
1987 changed modify the preset values */
1988 //[self CustomSettingUsed: sender];
1991 - (IBAction) CalculateBitrate: (id) sender
1993 if( !fHandle || [fVidQualityMatrix selectedRow] != 0 )
1998 hb_list_t * list = hb_get_titles( fHandle );
1999 hb_title_t * title = (hb_title_t *) hb_list_item( list,
2000 [fSrcTitlePopUp indexOfSelectedItem] );
2001 hb_job_t * job = title->job;
2005 [fVidBitrateField setIntValue: hb_calc_bitrate( job,
2006 [fVidTargetSizeField intValue] )];
2011 /* Method to determine if we should change the UI
2012 To reflect whether or not a Preset is being used or if
2013 the user is using "Custom" settings by determining the sender*/
2014 - (IBAction) CustomSettingUsed: (id) sender
2016 if ([sender stringValue] != NULL)
2018 /* Deselect the currently selected Preset if there is one*/
2019 [tableView deselectRow:[tableView selectedRow]];
2020 /* Change UI to show "Custom" settings are being used */
2021 [fPresetSelectedDisplay setStringValue: @"Custom"];
2023 curUserPresetChosenNum = nil;
2030 - (IBAction) X264AdvancedOptionsSet: (id) sender
2032 /*Set opt widget values here*/
2034 /*B-Frames fX264optBframesPopUp*/
2036 [fX264optBframesPopUp removeAllItems];
2037 [fX264optBframesPopUp addItemWithTitle:@"Default (0)"];
2040 [fX264optBframesPopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
2043 /*Reference Frames fX264optRefPopUp*/
2044 [fX264optRefPopUp removeAllItems];
2045 [fX264optRefPopUp addItemWithTitle:@"Default (1)"];
2048 [fX264optRefPopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
2051 /*No Fast P-Skip fX264optNfpskipSwitch BOOLEAN*/
2052 [fX264optNfpskipSwitch setState:0];
2054 /*No Dict Decimate fX264optNodctdcmtSwitch BOOLEAN*/
2055 [fX264optNodctdcmtSwitch setState:0];
2057 /*Sub Me fX264optSubmePopUp*/
2058 [fX264optSubmePopUp removeAllItems];
2059 [fX264optSubmePopUp addItemWithTitle:@"Default (4)"];
2062 [fX264optSubmePopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
2065 /*Trellis fX264optTrellisPopUp*/
2066 [fX264optTrellisPopUp removeAllItems];
2067 [fX264optTrellisPopUp addItemWithTitle:@"Default (0)"];
2070 [fX264optTrellisPopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
2073 /*Mixed-references fX264optMixedRefsSwitch BOOLEAN*/
2074 [fX264optMixedRefsSwitch setState:0];
2076 /*Motion Estimation fX264optMotionEstPopUp*/
2077 [fX264optMotionEstPopUp removeAllItems];
2078 [fX264optMotionEstPopUp addItemWithTitle:@"Default (Hexagon)"];
2079 [fX264optMotionEstPopUp addItemWithTitle:@"Diamond"];
2080 [fX264optMotionEstPopUp addItemWithTitle:@"Hexagon"];
2081 [fX264optMotionEstPopUp addItemWithTitle:@"Uneven Multi-Hexagon"];
2082 [fX264optMotionEstPopUp addItemWithTitle:@"Exhaustive"];
2084 /*Motion Estimation range fX264optMERangePopUp*/
2085 [fX264optMERangePopUp removeAllItems];
2086 [fX264optMERangePopUp addItemWithTitle:@"Default (16)"];
2089 [fX264optMERangePopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
2092 /*Weighted B-Frame Prediction fX264optWeightBSwitch BOOLEAN*/
2093 [fX264optWeightBSwitch setState:0];
2095 /*B-Frame Rate Distortion Optimization fX264optBRDOSwitch BOOLEAN*/
2096 [fX264optBRDOSwitch setState:0];
2098 /*B-frame Pyramids fX264optBPyramidSwitch BOOLEAN*/
2099 [fX264optBPyramidSwitch setState:0];
2101 /*Bidirectional Motion Estimation Refinement fX264optBiMESwitch BOOLEAN*/
2102 [fX264optBiMESwitch setState:0];
2104 /*Direct B-Frame Prediction Mode fX264optDirectPredPopUp*/
2105 [fX264optDirectPredPopUp removeAllItems];
2106 [fX264optDirectPredPopUp addItemWithTitle:@"Default (Spatial)"];
2107 [fX264optDirectPredPopUp addItemWithTitle:@"None"];
2108 [fX264optDirectPredPopUp addItemWithTitle:@"Spatial"];
2109 [fX264optDirectPredPopUp addItemWithTitle:@"Temporal"];
2110 [fX264optDirectPredPopUp addItemWithTitle:@"Automatic"];
2113 [fX264optAlphaDeblockPopUp removeAllItems];
2114 [fX264optAlphaDeblockPopUp addItemWithTitle:@"Default (0)"];
2117 [fX264optAlphaDeblockPopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
2121 [fX264optBetaDeblockPopUp removeAllItems];
2122 [fX264optBetaDeblockPopUp addItemWithTitle:@"Default (0)"];
2125 [fX264optBetaDeblockPopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
2128 /* Standardize the option string */
2129 [self X264AdvancedOptionsStandardizeOptString: NULL];
2130 /* Set Current GUI Settings based on newly standardized string */
2131 [self X264AdvancedOptionsSetCurrentSettings: NULL];
2134 - (IBAction) X264AdvancedOptionsStandardizeOptString: (id) sender
2136 /* Set widgets depending on the opt string in field */
2137 NSString * thisOpt; // The separated option such as "bframes=3"
2138 NSString * optName = @""; // The option name such as "bframes"
2139 NSString * optValue = @"";// The option value such as "3"
2140 NSString * changedOptString = @"";
2141 NSArray *currentOptsArray;
2143 /*First, we get an opt string to process */
2144 NSString *currentOptString = [fDisplayX264Options stringValue];
2146 /*verify there is an opt string to process */
2147 NSRange currentOptRange = [currentOptString rangeOfString:@"="];
2148 if (currentOptRange.location != NSNotFound)
2150 /*Put individual options into an array based on the ":" separator for processing, result is "<opt>=<value>"*/
2151 currentOptsArray = [currentOptString componentsSeparatedByString:@":"];
2153 /*iterate through the array and get <opts> and <values*/
2154 //NSEnumerator * enumerator = [currentOptsArray objectEnumerator];
2156 int currentOptsArrayCount = [currentOptsArray count];
2157 for (loopcounter = 0; loopcounter < currentOptsArrayCount; loopcounter++)
2159 thisOpt = [currentOptsArray objectAtIndex:loopcounter];
2161 NSRange splitOptRange = [thisOpt rangeOfString:@"="];
2162 if (splitOptRange.location != NSNotFound)
2164 optName = [thisOpt substringToIndex:splitOptRange.location];
2165 optValue = [thisOpt substringFromIndex:splitOptRange.location + 1];
2167 /* Standardize the names here depending on whats in the string */
2168 optName = [self X264AdvancedOptionsStandardizeOptNames:optName];
2169 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,optValue];
2171 else // No value given so we use a default of "1"
2174 /* Standardize the names here depending on whats in the string */
2175 optName = [self X264AdvancedOptionsStandardizeOptNames:optName];
2176 thisOpt = [NSString stringWithFormat:@"%@=%d",optName,1];
2179 /* Construct New String for opts here */
2180 if ([thisOpt isEqualToString:@""])
2182 changedOptString = [NSString stringWithFormat:@"%@%@",changedOptString,thisOpt];
2186 if ([changedOptString isEqualToString:@""])
2188 changedOptString = [NSString stringWithFormat:@"%@",thisOpt];
2192 changedOptString = [NSString stringWithFormat:@"%@:%@",changedOptString,thisOpt];
2198 /* Change the option string to reflect the new standardized option string */
2199 [fDisplayX264Options setStringValue:[NSString stringWithFormat:changedOptString]];
2202 - (NSString *) X264AdvancedOptionsStandardizeOptNames:(NSString *) cleanOptNameString
2204 if ([cleanOptNameString isEqualToString:@"ref"] || [cleanOptNameString isEqualToString:@"frameref"])
2206 cleanOptNameString = @"ref";
2209 /*No Fast PSkip nofast_pskip*/
2210 if ([cleanOptNameString isEqualToString:@"no-fast-pskip"] || [cleanOptNameString isEqualToString:@"no_fast_pskip"] || [cleanOptNameString isEqualToString:@"nofast_pskip"])
2212 cleanOptNameString = @"no-fast-pskip";
2215 /*No Dict Decimate*/
2216 if ([cleanOptNameString isEqualToString:@"no-dct-decimate"] || [cleanOptNameString isEqualToString:@"no_dct_decimate"] || [cleanOptNameString isEqualToString:@"nodct_decimate"])
2218 cleanOptNameString = @"no-dct-decimate";
2222 if ([cleanOptNameString isEqualToString:@"subme"])
2224 cleanOptNameString = @"subq";
2228 if ([cleanOptNameString isEqualToString:@"me-range"] || [cleanOptNameString isEqualToString:@"me_range"])
2229 cleanOptNameString = @"merange";
2232 if ([cleanOptNameString isEqualToString:@"weight-b"] || [cleanOptNameString isEqualToString:@"weight_b"])
2234 cleanOptNameString = @"weightb";
2238 if ([cleanOptNameString isEqualToString:@"b-rdo"] || [cleanOptNameString isEqualToString:@"b_rdo"])
2240 cleanOptNameString = @"brdo";
2244 if ([cleanOptNameString isEqualToString:@"b_pyramid"])
2246 cleanOptNameString = @"b-pyramid";
2249 /*Direct Prediction*/
2250 if ([cleanOptNameString isEqualToString:@"direct-pred"] || [cleanOptNameString isEqualToString:@"direct_pred"])
2252 cleanOptNameString = @"direct";
2256 if ([cleanOptNameString isEqualToString:@"filter"])
2258 cleanOptNameString = @"deblock";
2261 return cleanOptNameString;
2264 - (IBAction) X264AdvancedOptionsSetCurrentSettings: (id) sender
2266 /* Set widgets depending on the opt string in field */
2267 NSString * thisOpt; // The separated option such as "bframes=3"
2268 NSString * optName = @""; // The option name such as "bframes"
2269 NSString * optValue = @"";// The option value such as "3"
2270 NSArray *currentOptsArray;
2272 /*First, we get an opt string to process */
2273 //NSString *currentOptString = @"bframes=3:ref=1:subme=5:me=umh:no-fast-pskip=1:no-dct-decimate=1:trellis=2";
2274 NSString *currentOptString = [fDisplayX264Options stringValue];
2276 /*verify there is an opt string to process */
2277 NSRange currentOptRange = [currentOptString rangeOfString:@"="];
2278 if (currentOptRange.location != NSNotFound)
2280 /* lets clean the opt string here to standardize any names*/
2281 /*Put individual options into an array based on the ":" separator for processing, result is "<opt>=<value>"*/
2282 currentOptsArray = [currentOptString componentsSeparatedByString:@":"];
2284 /*iterate through the array and get <opts> and <values*/
2285 //NSEnumerator * enumerator = [currentOptsArray objectEnumerator];
2287 int currentOptsArrayCount = [currentOptsArray count];
2289 /*iterate through the array and get <opts> and <values*/
2290 for (loopcounter = 0; loopcounter < currentOptsArrayCount; loopcounter++)
2292 thisOpt = [currentOptsArray objectAtIndex:loopcounter];
2293 NSRange splitOptRange = [thisOpt rangeOfString:@"="];
2295 if (splitOptRange.location != NSNotFound)
2297 optName = [thisOpt substringToIndex:splitOptRange.location];
2298 optValue = [thisOpt substringFromIndex:splitOptRange.location + 1];
2300 /*Run through the available widgets for x264 opts and set them, as you add widgets,
2301 they need to be added here. This should be moved to its own method probably*/
2303 /*bframes NSPopUpButton*/
2304 if ([optName isEqualToString:@"bframes"])
2306 [fX264optBframesPopUp selectItemAtIndex:[optValue intValue]+1];
2308 /*ref NSPopUpButton*/
2309 if ([optName isEqualToString:@"ref"])
2311 [fX264optRefPopUp selectItemAtIndex:[optValue intValue]+1];
2313 /*No Fast PSkip NSPopUpButton*/
2314 if ([optName isEqualToString:@"no-fast-pskip"])
2316 [fX264optNfpskipSwitch setState:[optValue intValue]];
2318 /*No Dict Decimate NSPopUpButton*/
2319 if ([optName isEqualToString:@"no-dct-decimate"])
2321 [fX264optNodctdcmtSwitch setState:[optValue intValue]];
2323 /*Sub Me NSPopUpButton*/
2324 if ([optName isEqualToString:@"subq"])
2326 [fX264optSubmePopUp selectItemAtIndex:[optValue intValue]+1];
2328 /*Trellis NSPopUpButton*/
2329 if ([optName isEqualToString:@"trellis"])
2331 [fX264optTrellisPopUp selectItemAtIndex:[optValue intValue]+1];
2333 /*Mixed Refs NSButton*/
2334 if ([optName isEqualToString:@"mixed-refs"])
2336 [fX264optMixedRefsSwitch setState:[optValue intValue]];
2338 /*Motion Estimation NSPopUpButton*/
2339 if ([optName isEqualToString:@"me"])
2341 if ([optValue isEqualToString:@"dia"])
2342 [fX264optMotionEstPopUp selectItemAtIndex:1];
2343 else if ([optValue isEqualToString:@"hex"])
2344 [fX264optMotionEstPopUp selectItemAtIndex:2];
2345 else if ([optValue isEqualToString:@"umh"])
2346 [fX264optMotionEstPopUp selectItemAtIndex:3];
2347 else if ([optValue isEqualToString:@"esa"])
2348 [fX264optMotionEstPopUp selectItemAtIndex:4];
2350 /*ME Range NSPopUpButton*/
2351 if ([optName isEqualToString:@"merange"])
2353 [fX264optMERangePopUp selectItemAtIndex:[optValue intValue]-3];
2355 /*Weighted B-Frames NSPopUpButton*/
2356 if ([optName isEqualToString:@"weightb"])
2358 [fX264optWeightBSwitch setState:[optValue intValue]];
2360 /*BRDO NSPopUpButton*/
2361 if ([optName isEqualToString:@"brdo"])
2363 [fX264optBRDOSwitch setState:[optValue intValue]];
2365 /*B Pyramid NSPopUpButton*/
2366 if ([optName isEqualToString:@"b-pyramid"])
2368 [fX264optBPyramidSwitch setState:[optValue intValue]];
2370 /*Bidirectional Motion Estimation Refinement NSPopUpButton*/
2371 if ([optName isEqualToString:@"bime"])
2373 [fX264optBiMESwitch setState:[optValue intValue]];
2375 /*Direct B-frame Prediction NSPopUpButton*/
2376 if ([optName isEqualToString:@"direct"])
2378 if ([optValue isEqualToString:@"none"])
2379 [fX264optDirectPredPopUp selectItemAtIndex:1];
2380 else if ([optValue isEqualToString:@"spatial"])
2381 [fX264optDirectPredPopUp selectItemAtIndex:2];
2382 else if ([optValue isEqualToString:@"temporal"])
2383 [fX264optDirectPredPopUp selectItemAtIndex:3];
2384 else if ([optValue isEqualToString:@"auto"])
2385 [fX264optDirectPredPopUp selectItemAtIndex:4];
2387 /*Deblocking NSPopUpButtons*/
2388 if ([optName isEqualToString:@"deblock"])
2390 NSString * alphaDeblock = @"";
2391 NSString * betaDeblock = @"";
2393 NSRange splitDeblock = [optValue rangeOfString:@","];
2394 alphaDeblock = [optValue substringToIndex:splitDeblock.location];
2395 betaDeblock = [optValue substringFromIndex:splitDeblock.location + 1];
2397 if ([alphaDeblock isEqualToString:@"0"] && [betaDeblock isEqualToString:@"0"])
2399 [fX264optAlphaDeblockPopUp selectItemAtIndex:0];
2400 [fX264optBetaDeblockPopUp selectItemAtIndex:0];
2404 if (![alphaDeblock isEqualToString:@"0"])
2406 [fX264optAlphaDeblockPopUp selectItemAtIndex:[alphaDeblock intValue]+7];
2410 [fX264optAlphaDeblockPopUp selectItemAtIndex:7];
2413 if (![betaDeblock isEqualToString:@"0"])
2415 [fX264optBetaDeblockPopUp selectItemAtIndex:[betaDeblock intValue]+7];
2419 [fX264optBetaDeblockPopUp selectItemAtIndex:7];
2428 - (IBAction) X264AdvancedOptionsChanged: (id) sender
2430 /*Determine which outlet is being used and set optName to process accordingly */
2431 NSString * optNameToChange = @""; // The option name such as "bframes"
2433 if (sender == fX264optBframesPopUp)
2435 optNameToChange = @"bframes";
2437 if (sender == fX264optRefPopUp)
2439 optNameToChange = @"ref";
2441 if (sender == fX264optNfpskipSwitch)
2443 optNameToChange = @"no-fast-pskip";
2445 if (sender == fX264optNodctdcmtSwitch)
2447 optNameToChange = @"no-dct-decimate";
2449 if (sender == fX264optSubmePopUp)
2451 optNameToChange = @"subq";
2453 if (sender == fX264optTrellisPopUp)
2455 optNameToChange = @"trellis";
2457 if (sender == fX264optMixedRefsSwitch)
2459 optNameToChange = @"mixed-refs";
2461 if (sender == fX264optMotionEstPopUp)
2463 optNameToChange = @"me";
2465 if (sender == fX264optMERangePopUp)
2467 optNameToChange = @"merange";
2469 if (sender == fX264optWeightBSwitch)
2471 optNameToChange = @"weightb";
2473 if (sender == fX264optBRDOSwitch)
2475 optNameToChange = @"brdo";
2477 if (sender == fX264optBPyramidSwitch)
2479 optNameToChange = @"b-pyramid";
2481 if (sender == fX264optBiMESwitch)
2483 optNameToChange = @"bime";
2485 if (sender == fX264optDirectPredPopUp)
2487 optNameToChange = @"direct";
2489 if (sender == fX264optAlphaDeblockPopUp)
2491 optNameToChange = @"deblock";
2493 if (sender == fX264optBetaDeblockPopUp)
2495 optNameToChange = @"deblock";
2498 /* Set widgets depending on the opt string in field */
2499 NSString * thisOpt; // The separated option such as "bframes=3"
2500 NSString * optName = @""; // The option name such as "bframes"
2501 NSString * optValue = @"";// The option value such as "3"
2502 NSArray *currentOptsArray;
2504 /*First, we get an opt string to process */
2505 //EXAMPLE: NSString *currentOptString = @"bframes=3:ref=1:subme=5:me=umh:no-fast-pskip=1:no-dct-decimate=1:trellis=2";
2506 NSString *currentOptString = [fDisplayX264Options stringValue];
2508 /*verify there is an occurrence of the opt specified by the sender to change */
2509 /*take care of any multi-value opt names here. This is extremely kludgy, but test for functionality
2510 and worry about pretty later */
2512 /*First, we create a pattern to check for ":"optNameToChange"=" to modify the option if the name falls after
2513 the first character of the opt string (hence the ":") */
2514 NSString *checkOptNameToChange = [NSString stringWithFormat:@":%@=",optNameToChange];
2515 NSRange currentOptRange = [currentOptString rangeOfString:checkOptNameToChange];
2516 /*Then we create a pattern to check for "<beginning of line>"optNameToChange"=" to modify the option to
2517 see if the name falls at the beginning of the line, where we would not have the ":" as a pattern to test against*/
2518 NSString *checkOptNameToChangeBeginning = [NSString stringWithFormat:@"%@=",optNameToChange];
2519 NSRange currentOptRangeBeginning = [currentOptString rangeOfString:checkOptNameToChangeBeginning];
2520 if (currentOptRange.location != NSNotFound || currentOptRangeBeginning.location == 0)
2522 /* Create new empty opt string*/
2523 NSString *changedOptString = @"";
2525 /*Put individual options into an array based on the ":" separator for processing, result is "<opt>=<value>"*/
2526 currentOptsArray = [currentOptString componentsSeparatedByString:@":"];
2528 /*iterate through the array and get <opts> and <values*/
2530 int currentOptsArrayCount = [currentOptsArray count];
2531 for (loopcounter = 0; loopcounter < currentOptsArrayCount; loopcounter++)
2533 thisOpt = [currentOptsArray objectAtIndex:loopcounter];
2534 NSRange splitOptRange = [thisOpt rangeOfString:@"="];
2536 if (splitOptRange.location != NSNotFound)
2538 optName = [thisOpt substringToIndex:splitOptRange.location];
2539 optValue = [thisOpt substringFromIndex:splitOptRange.location + 1];
2541 /*Run through the available widgets for x264 opts and set them, as you add widgets,
2542 they need to be added here. This should be moved to its own method probably*/
2544 /*If the optNameToChange is found, appropriately change the value or delete it if
2545 "Unspecified" is set.*/
2546 if ([optName isEqualToString:optNameToChange])
2548 if ([optNameToChange isEqualToString:@"deblock"])
2550 if ((([fX264optAlphaDeblockPopUp indexOfSelectedItem] == 0) || ([fX264optAlphaDeblockPopUp indexOfSelectedItem] == 7)) && (([fX264optBetaDeblockPopUp indexOfSelectedItem] == 0) || ([fX264optBetaDeblockPopUp indexOfSelectedItem] == 7)))
2556 thisOpt = [NSString stringWithFormat:@"%@=%d,%d",optName, ([fX264optAlphaDeblockPopUp indexOfSelectedItem] != 0) ? [fX264optAlphaDeblockPopUp indexOfSelectedItem]-7 : 0,([fX264optBetaDeblockPopUp indexOfSelectedItem] != 0) ? [fX264optBetaDeblockPopUp indexOfSelectedItem]-7 : 0];
2559 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"])
2561 if ([sender state] == 0)
2567 thisOpt = [NSString stringWithFormat:@"%@=%d",optName,1];
2570 else if (([sender indexOfSelectedItem] == 0) && (sender != fX264optAlphaDeblockPopUp) && (sender != fX264optBetaDeblockPopUp) ) // means that "unspecified" is chosen, lets then remove it from the string
2574 else if ([optNameToChange isEqualToString:@"me"])
2576 switch ([sender indexOfSelectedItem])
2579 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"dia"];
2583 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"hex"];
2587 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"umh"];
2591 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"esa"];
2598 else if ([optNameToChange isEqualToString:@"direct"])
2600 switch ([sender indexOfSelectedItem])
2603 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"none"];
2607 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"spatial"];
2611 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"temporal"];
2615 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"auto"];
2622 else if ([optNameToChange isEqualToString:@"merange"])
2624 thisOpt = [NSString stringWithFormat:@"%@=%d",optName,[sender indexOfSelectedItem]+3];
2626 else // we have a valid value to change, so change it
2628 thisOpt = [NSString stringWithFormat:@"%@=%d",optName,[sender indexOfSelectedItem]-1];
2633 /* Construct New String for opts here */
2634 if ([thisOpt isEqualToString:@""])
2636 changedOptString = [NSString stringWithFormat:@"%@%@",changedOptString,thisOpt];
2640 if ([changedOptString isEqualToString:@""])
2642 changedOptString = [NSString stringWithFormat:@"%@",thisOpt];
2646 changedOptString = [NSString stringWithFormat:@"%@:%@",changedOptString,thisOpt];
2651 /* Change the option string to reflect the new mod settings */
2652 [fDisplayX264Options setStringValue:[NSString stringWithFormat:changedOptString]];
2654 else // if none exists, add it to the string
2656 if ([[fDisplayX264Options stringValue] isEqualToString: @""])
2658 if ([optNameToChange isEqualToString:@"me"])
2660 switch ([sender indexOfSelectedItem])
2663 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2664 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"dia"]]];
2668 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2669 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"hex"]]];
2673 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2674 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"umh"]]];
2678 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2679 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"esa"]]];
2686 else if ([optNameToChange isEqualToString:@"direct"])
2688 switch ([sender indexOfSelectedItem])
2691 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2692 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"none"]]];
2696 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2697 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"spatial"]]];
2701 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2702 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"temporal"]]];
2706 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2707 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"auto"]]];
2715 else if ([optNameToChange isEqualToString:@"merange"])
2717 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2718 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"%d",[sender indexOfSelectedItem]+3]]];
2720 else if ([optNameToChange isEqualToString:@"deblock"])
2722 [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]]];
2724 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"]) {
2725 if ([sender state] == 0)
2727 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@""]];
2731 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2732 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"%d",[sender state]]]];
2737 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2738 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"%d",[sender indexOfSelectedItem]-1]]];
2743 if ([optNameToChange isEqualToString:@"me"])
2745 switch ([sender indexOfSelectedItem])
2748 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",
2749 [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2750 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"dia"]]];
2754 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",
2755 [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2756 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"hex"]]];
2760 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",
2761 [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2762 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"umh"]]];
2766 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",
2767 [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2768 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"esa"]]];
2775 else if ([optNameToChange isEqualToString:@"direct"])
2777 switch ([sender indexOfSelectedItem])
2780 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",
2781 [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2782 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"none"]]];
2786 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",
2787 [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2788 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"spatial"]]];
2792 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",
2793 [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2794 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"temporal"]]];
2798 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",
2799 [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2800 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"auto"]]];
2808 else if ([optNameToChange isEqualToString:@"merange"])
2810 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",[NSString stringWithFormat:[fDisplayX264Options stringValue]],
2811 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"%d",[sender indexOfSelectedItem]+3]]];
2813 else if ([optNameToChange isEqualToString:@"deblock"])
2815 [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]]];
2817 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"])
2819 if ([sender state] == 0)
2821 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@",[NSString stringWithFormat:[fDisplayX264Options stringValue]]]];
2825 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",[NSString stringWithFormat:[fDisplayX264Options stringValue]],
2826 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"%d",[sender state]]]];
2831 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",[NSString stringWithFormat:[fDisplayX264Options stringValue]],
2832 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"%d",[sender indexOfSelectedItem]-1]]];
2837 /* We now need to reset the opt widgets since we changed some stuff */
2838 [self X264AdvancedOptionsSet:NULL];
2842 /* We use this method to recreate new, updated factory
2844 - (IBAction)AddFactoryPresets:(id)sender
2846 /* First, we delete any existing built in presets */
2847 [self DeleteFactoryPresets: sender];
2848 /* Then, we re-create new built in presets programmatically CreateIpodOnlyPreset*/
2849 [UserPresets addObject:[self CreateIpodLowPreset]];
2850 [UserPresets addObject:[self CreateIpodHighPreset]];
2851 [UserPresets addObject:[self CreateAppleTVPreset]];
2852 [UserPresets addObject:[self CreatePSThreePreset]];
2853 [UserPresets addObject:[self CreatePSPPreset]];
2856 - (IBAction)DeleteFactoryPresets:(id)sender
2859 NSEnumerator *enumerator = [UserPresets objectEnumerator];
2863 NSMutableArray *tempArray;
2866 tempArray = [NSMutableArray array];
2867 /* we look here to see if the preset is we move on to the next one */
2868 while ( tempObject = [enumerator nextObject] )
2870 /* if the preset is "Factory" then we put it in the array of
2871 presets to delete */
2872 if ([[tempObject objectForKey:@"Type"] intValue] == 0)
2874 [tempArray addObject:tempObject];
2878 [UserPresets removeObjectsInArray:tempArray];
2879 [tableView reloadData];
2884 - (IBAction) ShowAddPresetPanel: (id) sender
2886 /* Deselect the currently selected Preset if there is one*/
2887 [tableView deselectRow:[tableView selectedRow]];
2889 /* Populate the preset picture settings popup here */
2890 [fPresetNewPicSettingsPopUp removeAllItems];
2891 [fPresetNewPicSettingsPopUp addItemWithTitle:@"None"];
2892 [fPresetNewPicSettingsPopUp addItemWithTitle:@"Current"];
2893 [fPresetNewPicSettingsPopUp addItemWithTitle:@"Source Maximum (post source scan)"];
2894 [fPresetNewPicSettingsPopUp selectItemAtIndex: 0];
2896 /* Erase info from the input fields fPresetNewDesc*/
2897 [fPresetNewName setStringValue: @""];
2898 [fPresetNewDesc setStringValue: @""];
2899 /* Show the panel */
2900 [NSApp beginSheet: fAddPresetPanel modalForWindow: fWindow
2901 modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
2902 [NSApp runModalForWindow: fAddPresetPanel];
2903 [NSApp endSheet: fAddPresetPanel];
2904 [fAddPresetPanel orderOut: self];
2908 - (IBAction) CloseAddPresetPanel: (id) sender
2914 - (IBAction)AddUserPreset:(id)sender
2917 /* Here we create a custom user preset */
2918 [UserPresets addObject:[self CreatePreset]];
2919 /* Erase info from the input fields */
2920 [fPresetNewName setStringValue: @""];
2921 [fPresetNewDesc setStringValue: @""];
2922 /* We stop the modal window for the new preset */
2932 /* We Sort the Presets By Factory or Custom */
2933 NSSortDescriptor * presetTypeDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"Type"
2934 ascending:YES] autorelease];
2935 /* We Sort the Presets Alphabetically by name */
2936 NSSortDescriptor * presetNameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"PresetName"
2937 ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease];
2938 NSArray *sortDescriptors=[NSArray arrayWithObjects:presetTypeDescriptor,presetNameDescriptor,nil];
2939 NSArray *sortedArray=[UserPresets sortedArrayUsingDescriptors:sortDescriptors];
2940 [UserPresets setArray:sortedArray];
2943 /* We Reload the New Table data for presets */
2944 [tableView reloadData];
2945 /* We save all of the preset data here */
2949 - (IBAction)InsertPreset:(id)sender
2951 int index = [tableView selectedRow];
2952 [UserPresets insertObject:[self CreatePreset] atIndex:index];
2953 [tableView reloadData];
2957 - (NSDictionary *)CreatePreset
2959 NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
2960 /* Get the New Preset Name from the field in the AddPresetPanel */
2961 [preset setObject:[fPresetNewName stringValue] forKey:@"PresetName"];
2962 /*Set whether or not this is a user preset or factory 0 is factory, 1 is user*/
2963 [preset setObject:[NSNumber numberWithInt:1] forKey:@"Type"];
2964 /*Set whether or not this is default, at creation set to 0*/
2965 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
2966 /*Get the whether or not to apply pic settings in the AddPresetPanel*/
2967 [preset setObject:[NSNumber numberWithInt:[fPresetNewPicSettingsPopUp indexOfSelectedItem]] forKey:@"UsesPictureSettings"];
2968 /* Get New Preset Description from the field in the AddPresetPanel*/
2969 [preset setObject:[fPresetNewDesc stringValue] forKey:@"PresetDescription"];
2971 [preset setObject:[fDstFormatPopUp titleOfSelectedItem] forKey:@"FileFormat"];
2972 /* Chapter Markers fCreateChapterMarkers*/
2973 [preset setObject:[NSNumber numberWithInt:[fCreateChapterMarkers state]] forKey:@"ChapterMarkers"];
2974 /* Allow Mpeg4 64 bit formatting +4GB file sizes */
2975 [preset setObject:[NSNumber numberWithInt:[fDstMpgLargeFileCheck state]] forKey:@"Mp4LargeFile"];
2977 [preset setObject:[fDstCodecsPopUp titleOfSelectedItem] forKey:@"FileCodecs"];
2979 [preset setObject:[fVidEncoderPopUp titleOfSelectedItem] forKey:@"VideoEncoder"];
2980 /* x264 Option String */
2981 [preset setObject:[fDisplayX264Options stringValue] forKey:@"x264Option"];
2983 [preset setObject:[NSNumber numberWithInt:[fVidQualityMatrix selectedRow]] forKey:@"VideoQualityType"];
2984 [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
2985 [preset setObject:[fVidBitrateField stringValue] forKey:@"VideoAvgBitrate"];
2986 [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
2988 /* Video framerate */
2989 [preset setObject:[fVidRatePopUp titleOfSelectedItem] forKey:@"VideoFramerate"];
2991 [preset setObject:[NSNumber numberWithInt:[fVidGrayscaleCheck state]] forKey:@"VideoGrayScale"];
2992 /* 2 Pass Encoding */
2993 [preset setObject:[NSNumber numberWithInt:[fVidTwoPassCheck state]] forKey:@"VideoTwoPass"];
2994 /* Turbo 2 pass Encoding fVidTurboPassCheck*/
2995 [preset setObject:[NSNumber numberWithInt:[fVidTurboPassCheck state]] forKey:@"VideoTurboTwoPass"];
2996 /*Picture Settings*/
2997 hb_job_t * job = fTitle->job;
2998 /* Basic Picture Settings */
2999 /* Use Max Picture settings for whatever the dvd is.*/
3000 [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesMaxPictureSettings"];
3001 [preset setObject:[NSNumber numberWithInt:fTitle->job->width] forKey:@"PictureWidth"];
3002 [preset setObject:[NSNumber numberWithInt:fTitle->job->height] forKey:@"PictureHeight"];
3003 [preset setObject:[NSNumber numberWithInt:fTitle->job->keep_ratio] forKey:@"PictureKeepRatio"];
3004 [preset setObject:[NSNumber numberWithInt:fTitle->job->deinterlace] forKey:@"PictureDeinterlace"];
3005 [preset setObject:[NSNumber numberWithInt:fTitle->job->pixel_ratio] forKey:@"PicturePAR"];
3006 /* Set crop settings here */
3007 /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
3008 //[preset setObject:[NSNumber numberWithInt:[[fPictureController fCropMatrix] selectedRow]] forKey:@"PictureAutoCrop"];
3010 [preset setObject:[NSNumber numberWithInt:job->crop[0]] forKey:@"PictureTopCrop"];
3011 [preset setObject:[NSNumber numberWithInt:job->crop[1]] forKey:@"PictureBottomCrop"];
3012 [preset setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"];
3013 [preset setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"];
3016 /* Audio Sample Rate*/
3017 [preset setObject:[fAudRatePopUp titleOfSelectedItem] forKey:@"AudioSampleRate"];
3018 /* Audio Bitrate Rate*/
3019 [preset setObject:[fAudBitratePopUp titleOfSelectedItem] forKey:@"AudioBitRate"];
3021 [preset setObject:[fSubPopUp titleOfSelectedItem] forKey:@"Subtitles"];
3024 [preset autorelease];
3029 - (NSDictionary *)CreateIpodLowPreset
3031 NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
3032 /* Get the New Preset Name from the field in the AddPresetPanel */
3033 [preset setObject:@"HB-iPod Low-Res" forKey:@"PresetName"];
3034 /*Set whether or not this is a user preset or factory 0 is factory, 1 is user*/
3035 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
3036 /*Set whether or not this is default, at creation set to 0*/
3037 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
3038 /*Get the whether or not to apply pic settings in the AddPresetPanel*/
3039 [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesPictureSettings"];
3040 /* Get the New Preset Description from the field in the AddPresetPanel */
3041 [preset setObject:@"HandBrakes Built in Low Resolution Preset for the iPod - Optimized for great playback on the iPod screen with smaller file size" forKey:@"PresetDescription"];
3043 [preset setObject:@"MP4 file" forKey:@"FileFormat"];
3044 /* Chapter Markers*/
3045 [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
3047 [preset setObject:@"AVC/H.264 Video / AAC Audio" forKey:@"FileCodecs"];
3049 [preset setObject:@"x264 (h.264 iPod)" forKey:@"VideoEncoder"];
3050 /* x264 Option String */
3051 [preset setObject:@"keyint=300:keyint-min=30:bframes=0:cabac=0:ref=1:vbv-maxrate=768:vbv-bufsize=2000:analyse=all:me=umh:subme=6:no-fast-pskip=1" forKey:@"x264Option"];
3053 [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
3054 [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
3055 [preset setObject:@"700" forKey:@"VideoAvgBitrate"];
3056 [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
3058 /* Video framerate */
3059 [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
3061 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
3062 /* 2 Pass Encoding */
3063 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
3065 /*Picture Settings*/
3066 //hb_job_t * job = fTitle->job;
3067 /* Basic Picture Settings */
3068 /* Use Max Picture settings for whatever the dvd is.*/
3069 [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesMaxPictureSettings"];
3070 [preset setObject:[NSNumber numberWithInt:1] forKey:@"PictureAutoCrop"];
3071 [preset setObject:[NSNumber numberWithInt:320] forKey:@"PictureWidth"];
3072 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureHeight"];
3073 [preset setObject:[NSNumber numberWithInt:1] forKey:@"PictureKeepRatio"];
3074 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
3075 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PicturePAR"];
3076 /* Set crop settings here */
3077 /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
3078 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureTopCrop"];
3079 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureBottomCrop"];
3080 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureLeftCrop"];
3081 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureRightCrop"];
3084 /* Audio Sample Rate*/
3085 [preset setObject:@"48" forKey:@"AudioSampleRate"];
3086 /* Audio Bitrate Rate*/
3087 [preset setObject:@"160" forKey:@"AudioBitRate"];
3089 [preset setObject:@"None" forKey:@"Subtitles"];
3092 [preset autorelease];
3098 - (NSDictionary *)CreateIpodHighPreset
3100 NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
3101 /* Get the New Preset Name from the field in the AddPresetPanel */
3102 [preset setObject:@"HB-iPod High-Res" forKey:@"PresetName"];
3103 /*Set whether or not this is a user preset or factory 0 is factory, 1 is user*/
3104 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
3105 /*Set whether or not this is default, at creation set to 0*/
3106 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
3107 /*Get the whether or not to apply pic settings in the AddPresetPanel*/
3108 [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesPictureSettings"];
3109 /* Get the New Preset Description from the field in the AddPresetPanel */
3110 [preset setObject:@"HandBrakes Built in High Resolution Preset for the iPod - Best iPod video quality, great for viewing on a tv using your iPod" forKey:@"PresetDescription"];
3112 [preset setObject:@"MP4 file" forKey:@"FileFormat"];
3113 /* Chapter Markers*/
3114 [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
3116 [preset setObject:@"AVC/H.264 Video / AAC Audio" forKey:@"FileCodecs"];
3118 [preset setObject:@"x264 (h.264 iPod)" forKey:@"VideoEncoder"];
3119 /* x264 Option String */
3120 [preset setObject:@"keyint=300:keyint-min=30:bframes=0:cabac=0:ref=1:vbv-maxrate=1500:vbv-bufsize=2000:analyse=all:me=umh:subme=6:no-fast-pskip=1" forKey:@"x264Option"];
3122 [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
3123 [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
3124 [preset setObject:@"1500" forKey:@"VideoAvgBitrate"];
3125 [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
3127 /* Video framerate */
3128 [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
3130 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
3131 /* 2 Pass Encoding */
3132 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
3134 /*Picture Settings*/
3135 //hb_job_t * job = fTitle->job;
3136 /* Basic Picture Settings */
3137 /* Use Max Picture settings for whatever the dvd is.*/
3138 [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesMaxPictureSettings"];
3139 [preset setObject:[NSNumber numberWithInt:640] forKey:@"PictureWidth"];
3140 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureHeight"];
3141 [preset setObject:[NSNumber numberWithInt:1] forKey:@"PictureKeepRatio"];
3142 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
3143 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PicturePAR"];
3144 /* Set crop settings here */
3145 /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
3146 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureTopCrop"];
3147 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureBottomCrop"];
3148 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureLeftCrop"];
3149 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureRightCrop"];
3152 /* Audio Sample Rate*/
3153 [preset setObject:@"48" forKey:@"AudioSampleRate"];
3154 /* Audio Bitrate Rate*/
3155 [preset setObject:@"160" forKey:@"AudioBitRate"];
3157 [preset setObject:@"None" forKey:@"Subtitles"];
3160 [preset autorelease];
3165 - (NSDictionary *)CreateAppleTVPreset
3167 NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
3168 /* Get the New Preset Name from the field in the AddPresetPanel */
3169 [preset setObject:@"HB-AppleTV" forKey:@"PresetName"];
3170 /*Set whether or not this is a user preset where 0 is factory, 1 is user*/
3171 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
3172 /*Set whether or not this is default, at creation set to 0*/
3173 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
3174 /*Get the whether or not to apply pic settings in the AddPresetPanel*/
3175 [preset setObject:[NSNumber numberWithInt:2] forKey:@"UsesPictureSettings"];
3176 /* Get the New Preset Description from the field in the AddPresetPanel */
3177 [preset setObject:@"HandBrakes Built in Preset for the AppleTV - Provides a good balance between quality, file size, and optimizes performance whether synching or streaming" forKey:@"PresetDescription"];
3179 [preset setObject:@"MP4 file" forKey:@"FileFormat"];
3180 /* Chapter Markers*/
3181 [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
3183 [preset setObject:@"AVC/H.264 Video / AAC Audio" forKey:@"FileCodecs"];
3185 [preset setObject:@"x264 (h.264 Main)" forKey:@"VideoEncoder"];
3186 /* x264 Option String (We can use this to tweak the appleTV output)*/
3187 [preset setObject:@"bframes=3:ref=1:subme=5:me=umh:no-fast-pskip=1:trellis=2" forKey:@"x264Option"];
3189 [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
3190 [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
3191 [preset setObject:@"2500" forKey:@"VideoAvgBitrate"];
3192 [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
3194 /* Video framerate */
3195 [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
3197 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
3198 /* 2 Pass Encoding */
3199 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
3201 /*Picture Settings*/
3202 /* For AppleTV we only want to retain UsesMaxPictureSettings
3203 which depend on the source dvd picture settings, so we don't
3204 record the current dvd's picture info since it will vary from
3206 //hb_job_t * job = fTitle->job;
3207 //hb_job_t * job = title->job;
3208 /* Basic Picture Settings */
3209 /* Use Max Picture settings for whatever the dvd is.*/
3210 [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesMaxPictureSettings"];
3211 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureWidth"];
3212 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureHeight"];
3213 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureKeepRatio"];
3214 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
3215 [preset setObject:[NSNumber numberWithInt:1] forKey:@"PicturePAR"];
3216 /* Set crop settings here */
3217 /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
3218 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureTopCrop"];
3219 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureBottomCrop"];
3220 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureLeftCrop"];
3221 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureRightCrop"];
3224 /* Audio Sample Rate*/
3225 [preset setObject:@"48" forKey:@"AudioSampleRate"];
3226 /* Audio Bitrate Rate*/
3227 [preset setObject:@"160" forKey:@"AudioBitRate"];
3229 [preset setObject:@"None" forKey:@"Subtitles"];
3232 [preset autorelease];
3237 - (NSDictionary *)CreatePSThreePreset
3239 NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
3240 /* Get the New Preset Name from the field in the AddPresetPanel */
3241 [preset setObject:@"HB-PS3" forKey:@"PresetName"];
3242 /*Set whether or not this is a user preset where 0 is factory, 1 is user*/
3243 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
3244 /*Set whether or not this is default, at creation set to 0*/
3245 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
3246 /*Get the whether or not to apply pic settings in the AddPresetPanel*/
3247 [preset setObject:[NSNumber numberWithInt:2] forKey:@"UsesPictureSettings"];
3248 /* Get the New Preset Description from the field in the AddPresetPanel */
3249 [preset setObject:@"HandBrakes Built in Preset for the Sony PS3" forKey:@"PresetDescription"];
3251 [preset setObject:@"MP4 file" forKey:@"FileFormat"];
3252 /* Chapter Markers*/
3253 [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
3255 [preset setObject:@"AVC/H.264 Video / AAC Audio" forKey:@"FileCodecs"];
3257 [preset setObject:@"x264 (h.264 Main)" forKey:@"VideoEncoder"];
3258 /* x264 Option String (We can use this to tweak the appleTV output)*/
3259 [preset setObject:@"level=41" forKey:@"x264Option"];
3261 [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
3262 [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
3263 [preset setObject:@"2500" forKey:@"VideoAvgBitrate"];
3264 [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
3266 /* Video framerate */
3267 [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
3269 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
3270 /* 2 Pass Encoding */
3271 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
3273 /*Picture Settings*/
3274 /* For PS3 we only want to retain UsesMaxPictureSettings
3275 which depend on the source dvd picture settings, so we don't
3276 record the current dvd's picture info since it will vary from
3278 /* Use Max Picture settings for whatever the dvd is.*/
3279 [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesMaxPictureSettings"];
3280 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureWidth"];
3281 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureHeight"];
3282 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureKeepRatio"];
3283 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
3284 [preset setObject:[NSNumber numberWithInt:1] forKey:@"PicturePAR"];
3285 /* Set crop settings here */
3286 /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
3287 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureTopCrop"];
3288 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureBottomCrop"];
3289 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureLeftCrop"];
3290 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureRightCrop"];
3293 /* Audio Sample Rate*/
3294 [preset setObject:@"48" forKey:@"AudioSampleRate"];
3295 /* Audio Bitrate Rate*/
3296 [preset setObject:@"160" forKey:@"AudioBitRate"];
3298 [preset setObject:@"None" forKey:@"Subtitles"];
3301 [preset autorelease];
3305 - (NSDictionary *)CreatePSPPreset
3307 NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
3308 /* Get the New Preset Name from the field in the AddPresetPanel */
3309 [preset setObject:@"HB-PSP" forKey:@"PresetName"];
3310 /*Set whether or not this is a user preset where 0 is factory, 1 is user*/
3311 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
3312 /*Set whether or not this is default, at creation set to 0*/
3313 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
3314 /*Get the whether or not to apply pic settings in the AddPresetPanel*/
3315 [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesPictureSettings"];
3316 /* Get the New Preset Description from the field in the AddPresetPanel */
3317 [preset setObject:@"HandBrakes Built in Preset for the Sony PSP" forKey:@"PresetDescription"];
3319 [preset setObject:@"MP4 file" forKey:@"FileFormat"];
3320 /* Chapter Markers*/
3321 [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
3323 [preset setObject:@"MPEG-4 Video / AAC Audio" forKey:@"FileCodecs"];
3325 [preset setObject:@"FFmpeg" forKey:@"VideoEncoder"];
3326 /* x264 Option String (We can use this to tweak the appleTV output)*/
3327 [preset setObject:@"" forKey:@"x264Option"];
3329 [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
3330 [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
3331 [preset setObject:@"1024" forKey:@"VideoAvgBitrate"];
3332 [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
3334 /* Video framerate */
3335 [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
3337 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
3338 /* 2 Pass Encoding */
3339 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
3341 /*Picture Settings*/
3342 /* For PS3 we only want to retain UsesMaxPictureSettings
3343 which depend on the source dvd picture settings, so we don't
3344 record the current dvd's picture info since it will vary from
3346 /* Use Max Picture settings for whatever the dvd is.*/
3347 [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesMaxPictureSettings"];
3348 [preset setObject:@"368" forKey:@"PictureWidth"];
3349 [preset setObject:@"208" forKey:@"PictureHeight"];
3350 [preset setObject:[NSNumber numberWithInt:1] forKey:@"PictureKeepRatio"];
3351 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
3352 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PicturePAR"];
3353 /* Set crop settings here */
3354 /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
3355 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureTopCrop"];
3356 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureBottomCrop"];
3357 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureLeftCrop"];
3358 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureRightCrop"];
3361 /* Audio Sample Rate*/
3362 [preset setObject:@"48" forKey:@"AudioSampleRate"];
3363 /* Audio Bitrate Rate*/
3364 [preset setObject:@"128" forKey:@"AudioBitRate"];
3366 [preset setObject:@"None" forKey:@"Subtitles"];
3369 [preset autorelease];
3375 - (IBAction)DeletePreset:(id)sender
3378 NSEnumerator *enumerator;
3380 NSMutableArray *tempArray;
3383 if ( [tableView numberOfSelectedRows] == 0 )
3385 /* Alert user before deleting preset */
3386 /* Comment out for now, tie to user pref eventually */
3389 status = NSRunAlertPanel(@"Warning!", @"Are you sure that you want to delete the selected preset?", @"OK", @"Cancel", nil);
3391 if ( status == NSAlertDefaultReturn ) {
3392 enumerator = [tableView selectedRowEnumerator];
3393 tempArray = [NSMutableArray array];
3395 while ( (index = [enumerator nextObject]) ) {
3396 tempObject = [UserPresets objectAtIndex:[index intValue]];
3397 [tempArray addObject:tempObject];
3400 [UserPresets removeObjectsInArray:tempArray];
3401 [tableView reloadData];
3405 - (IBAction)tableViewSelected:(id)sender
3407 /* Since we cannot disable the presets tableView in terms of clickability
3408 we will use the enabled state of the add presets button to determine whether
3409 or not clicking on a preset will do anything */
3410 if ([fPresetsAdd isEnabled])
3413 /* we get the chosen preset from the UserPresets array */
3414 chosenPreset = [UserPresets objectAtIndex:[sender selectedRow]];
3415 curUserPresetChosenNum = [sender selectedRow];
3416 /* we set the preset display field in main window here */
3417 [fPresetSelectedDisplay setStringValue: [NSString stringWithFormat: @"%@",[chosenPreset valueForKey:@"PresetName"]]];
3419 [fDstFormatPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"FileFormat"]]];
3420 [self FormatPopUpChanged: NULL];
3422 /* Chapter Markers*/
3423 [fCreateChapterMarkers setState:[[chosenPreset objectForKey:@"ChapterMarkers"] intValue]];
3424 /* Allow Mpeg4 64 bit formatting +4GB file sizes */
3425 [fDstMpgLargeFileCheck setState:[[chosenPreset objectForKey:@"Mp4LargeFile"] intValue]];
3427 [fDstCodecsPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"FileCodecs"]]];
3428 [self CodecsPopUpChanged: NULL];
3430 [fVidEncoderPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoEncoder"]]];
3432 /* We can show the preset options here in the gui if we want to
3433 so we check to see it the user has specified it in the prefs */
3434 [fDisplayX264Options setStringValue: [NSString stringWithFormat:[chosenPreset valueForKey:@"x264Option"]]];
3436 [self X264AdvancedOptionsSet:NULL];
3438 /* Lets run through the following functions to get variables set there */
3439 [self EncoderPopUpChanged: NULL];
3441 [self CalculateBitrate: NULL];
3444 [fVidQualityMatrix selectCellAtRow:[[chosenPreset objectForKey:@"VideoQualityType"] intValue] column:0];
3446 [fVidTargetSizeField setStringValue: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoTargetSize"]]];
3447 [fVidBitrateField setStringValue: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoAvgBitrate"]]];
3449 [fVidQualitySlider setFloatValue: [[chosenPreset valueForKey:@"VideoQualitySlider"] floatValue]];
3450 [self VideoMatrixChanged: NULL];
3452 /* Video framerate */
3453 [fVidRatePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoFramerate"]]];
3456 [fVidGrayscaleCheck setState:[[chosenPreset objectForKey:@"VideoGrayScale"] intValue]];
3458 /* 2 Pass Encoding */
3459 [fVidTwoPassCheck setState:[[chosenPreset objectForKey:@"VideoTwoPass"] intValue]];
3460 [self TwoPassCheckboxChanged: NULL];
3461 /* Turbo 1st pass for 2 Pass Encoding */
3462 [fVidTurboPassCheck setState:[[chosenPreset objectForKey:@"VideoTurboTwoPass"] intValue]];
3466 /* Audio Sample Rate*/
3467 [fAudRatePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"AudioSampleRate"]]];
3468 /* Audio Bitrate Rate*/
3469 [fAudBitratePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"AudioBitRate"]]];
3471 [fSubPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"Subtitles"]]];
3473 /* Picture Settings */
3474 /* Look to see if we apply these here in objectForKey:@"UsesPictureSettings"] */
3475 if ([[chosenPreset objectForKey:@"UsesPictureSettings"] intValue] > 0)
3477 hb_job_t * job = fTitle->job;
3478 /* Check to see if we should use the max picture setting for the current title*/
3479 if ([[chosenPreset objectForKey:@"UsesPictureSettings"] intValue] == 2 || [[chosenPreset objectForKey:@"UsesMaxPictureSettings"] intValue] == 1)
3481 /* Use Max Picture settings for whatever the dvd is.*/
3482 [self RevertPictureSizeToMax: NULL];
3483 job->keep_ratio = [[chosenPreset objectForKey:@"PictureKeepRatio"] intValue];
3484 if (job->keep_ratio == 1)
3486 hb_fix_aspect( job, HB_KEEP_WIDTH );
3488 job->pixel_ratio = [[chosenPreset objectForKey:@"PicturePAR"] intValue];
3492 job->width = [[chosenPreset objectForKey:@"PictureWidth"] intValue];
3493 job->height = [[chosenPreset objectForKey:@"PictureHeight"] intValue];
3494 job->keep_ratio = [[chosenPreset objectForKey:@"PictureKeepRatio"] intValue];
3495 if (job->keep_ratio == 1)
3497 hb_fix_aspect( job, HB_KEEP_WIDTH );
3499 job->pixel_ratio = [[chosenPreset objectForKey:@"PicturePAR"] intValue];
3500 /* AutoCrop is in preset, then use the autocrop settings for each dvd */
3501 if ([[chosenPreset objectForKey:@"PictureAutoCrop"] intValue] == 1)
3503 [fPicSettingAutoCrop setStringValue: [NSString stringWithFormat:
3505 job->crop[0] = [[chosenPreset objectForKey:@"PictureTopCrop"] intValue];
3506 job->crop[1] = [[chosenPreset objectForKey:@"PictureBottomCrop"] intValue];
3507 job->crop[2] = [[chosenPreset objectForKey:@"PictureLeftCrop"] intValue];
3508 job->crop[3] = [[chosenPreset objectForKey:@"PictureRightCrop"] intValue];
3510 else /* if custom crop has been saved in preset, use the saved custom cropping regardless of the source */
3512 [fPicSettingAutoCrop setStringValue: [NSString stringWithFormat:
3514 job->crop[0] = [[chosenPreset objectForKey:@"PictureTopCrop"] intValue];
3515 job->crop[1] = [[chosenPreset objectForKey:@"PictureBottomCrop"] intValue];
3516 job->crop[2] = [[chosenPreset objectForKey:@"PictureLeftCrop"] intValue];
3517 job->crop[3] = [[chosenPreset objectForKey:@"PictureRightCrop"] intValue];
3520 [self CalculatePictureSizing: NULL];
3531 - (int)numberOfRowsInTableView:(NSTableView *)aTableView
3533 return [UserPresets count];
3536 /* we use this to determine display characteristics for
3537 each table cell based on content currently only used to
3538 show the built in presets in a blue font. */
3539 - (void)tableView:(NSTableView *)aTableView
3540 willDisplayCell:(id)aCell
3541 forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
3543 NSDictionary *userPresetDict = [UserPresets objectAtIndex:rowIndex];
3545 NSColor *shadowColor;
3546 /* First, we check to see if its a selected row, if so, we use white since its highlighted in blue */
3547 if ([[aTableView selectedRowIndexes] containsIndex:rowIndex] && ([tableView editedRow] != rowIndex))
3550 fontColor = [NSColor whiteColor];
3551 shadowColor = [NSColor colorWithDeviceRed:(127.0/255.0) green:(140.0/255.0) blue:(160.0/255.0) alpha:1.0];
3555 /* We set the properties of unselected rows */
3556 /* if built-in preset (defined by "type" == 0) we use a blue font */
3557 if ([[userPresetDict objectForKey:@"Type"] intValue] == 0)
3559 fontColor = [NSColor blueColor];
3561 else // User created preset, use a black font
3563 fontColor = [NSColor blackColor];
3567 [aCell setTextColor:fontColor];
3568 /* this shadow stuff (like mail app) for some reason looks crappy, commented out
3569 temporarily in case we want to resurrect it */
3571 NSShadow *shadow = [[NSShadow alloc] init];
3572 NSSize shadowOffset = { width: 1.0, height: -1.5};
3573 [shadow setShadowOffset:shadowOffset];
3574 [shadow setShadowColor:shadowColor];
3579 /* Method to display tooltip with the description for each preset, if available */
3580 - (NSString *)tableView:(NSTableView *)aTableView toolTipForCell:(NSCell *)aCell
3581 rect:(NSRectPointer)aRect tableColumn:(NSTableColumn *)aTableColumn
3582 row:(int)rowIndex mouseLocation:(NSPoint)aPos
3584 /* initialize the tooltip contents variable */
3586 /* if there is a description for the preset, we show it in the tooltip */
3587 if ([[UserPresets objectAtIndex:rowIndex] valueForKey:@"PresetDescription"])
3589 loc_tip = [NSString stringWithFormat: @"%@",[[UserPresets objectAtIndex:rowIndex] valueForKey:@"PresetDescription"]];
3594 loc_tip = @"No description available";
3600 - (id)tableView:(NSTableView *)aTableView
3601 objectValueForTableColumn:(NSTableColumn *)aTableColumn
3604 id theRecord, theValue;
3606 theRecord = [UserPresets objectAtIndex:rowIndex];
3607 theValue = [theRecord objectForKey:[aTableColumn identifier]];
3611 // NSTableDataSource method that we implement to edit values directly in the table...
3612 - (void)tableView:(NSTableView *)aTableView
3613 setObjectValue:(id)anObject
3614 forTableColumn:(NSTableColumn *)aTableColumn
3619 theRecord = [UserPresets objectAtIndex:rowIndex];
3620 [theRecord setObject:anObject forKey:@"PresetName"];
3621 /* We Sort the Presets By Factory or Custom */
3622 NSSortDescriptor * presetTypeDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"Type"
3623 ascending:YES] autorelease];
3624 /* We Sort the Presets Alphabetically by name */
3625 NSSortDescriptor * presetNameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"PresetName"
3626 ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease];
3627 NSArray *sortDescriptors=[NSArray arrayWithObjects:presetTypeDescriptor,presetNameDescriptor,nil];
3628 NSArray *sortedArray=[UserPresets sortedArrayUsingDescriptors:sortDescriptors];
3629 [UserPresets setArray:sortedArray];
3630 /* We Reload the New Table data for presets */
3631 [tableView reloadData];
3632 /* We save all of the preset data here */
3639 [UserPresets writeToFile:UserPresetsFile atomically:YES];
3645 - (void) controlTextDidBeginEditing: (NSNotification *) notification
3647 [self CalculateBitrate: NULL];
3650 - (void) controlTextDidEndEditing: (NSNotification *) notification
3652 [self CalculateBitrate: NULL];
3655 - (void) controlTextDidChange: (NSNotification *) notification
3657 [self CalculateBitrate: NULL];
3660 - (IBAction) OpenHomepage: (id) sender
3662 [[NSWorkspace sharedWorkspace] openURL: [NSURL
3663 URLWithString:@"http://handbrake.m0k.org/"]];
3666 - (IBAction) OpenForums: (id) sender
3668 [[NSWorkspace sharedWorkspace] openURL: [NSURL
3669 URLWithString:@"http://handbrake.m0k.org/forum/"]];
3671 - (IBAction) OpenUserGuide: (id) sender
3673 [[NSWorkspace sharedWorkspace] openURL: [NSURL
3674 URLWithString:@"http://handbrake.m0k.org/trac/wiki/HandBrakeGuide"]];
3678 * Shows debug output window.
3680 - (IBAction)showDebugOutputPanel:(id)sender
3682 [outputPanel showOutputPanel:sender];
3686 * Creates preferences controller, shows preferences window modally, and
3687 * releases the controller after user has closed the window.
3689 - (IBAction)showPreferencesWindow:(id)sender
3691 HBPreferencesController *controller = [[HBPreferencesController alloc] init];
3692 [controller runModal:nil];
3693 [controller release];