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"
10 #define _(a) NSLocalizedString(a,NULL)
16 static int FormatSettings[3][4] =
17 { { HB_MUX_MP4 | HB_VCODEC_FFMPEG | HB_ACODEC_FAAC,
18 HB_MUX_MP4 | HB_VCODEC_X264 | HB_ACODEC_FAAC,
21 { HB_MUX_AVI | HB_VCODEC_FFMPEG | HB_ACODEC_LAME,
22 HB_MUX_AVI | HB_VCODEC_FFMPEG | HB_ACODEC_AC3,
23 HB_MUX_AVI | HB_VCODEC_X264 | HB_ACODEC_LAME,
24 HB_MUX_AVI | HB_VCODEC_X264 | HB_ACODEC_AC3 },
25 { HB_MUX_OGM | HB_VCODEC_FFMPEG | HB_ACODEC_VORBIS,
26 HB_MUX_OGM | HB_VCODEC_FFMPEG | HB_ACODEC_LAME,
30 /*******************************
31 * HBController implementation *
32 *******************************/
33 @implementation HBController
42 - (void) applicationDidFinishLaunching: (NSNotification *) notification
51 fHandle = hb_init( HB_DEBUG_NONE, [[NSUserDefaults
52 standardUserDefaults] boolForKey:@"CheckForUpdates"] );
53 /* Set the Growl Delegate */
54 HBController *hbGrowlDelegate = [[HBController alloc] init];
55 [GrowlApplicationBridge setGrowlDelegate: hbGrowlDelegate];
56 /* Init others controllers */
57 [fScanController SetHandle: fHandle];
58 [fPictureController SetHandle: fHandle];
59 [fQueueController SetHandle: fHandle];
61 fChapterTitlesDelegate = [[ChapterTitles alloc] init];
62 [fChapterTable setDataSource:fChapterTitlesDelegate];
64 /* Call UpdateUI every 2/10 sec */
65 [[NSRunLoop currentRunLoop] addTimer: [NSTimer
66 scheduledTimerWithTimeInterval: 0.2 target: self
67 selector: @selector( UpdateUI: ) userInfo: NULL repeats: FALSE]
68 forMode: NSModalPanelRunLoopMode];
70 if( ( build = hb_check_update( fHandle, &version ) ) > -1 )
72 /* Update available - tell the user */
74 NSBeginInformationalAlertSheet( _( @"Update is available" ),
75 _( @"Go get it!" ), _( @"Discard" ), NULL, fWindow, self,
76 @selector( UpdateAlertDone:returnCode:contextInfo: ),
77 NULL, NULL, [NSString stringWithFormat:
78 _( @"HandBrake %s (build %d) is now available for download." ),
84 /* Show scan panel ASAP */
85 [self performSelectorOnMainThread: @selector(ShowScanPanel:)
86 withObject: NULL waitUntilDone: NO];
89 - (NSApplicationTerminateReply) applicationShouldTerminate:
92 if( [[fRipButton title] isEqualToString: _( @"Cancel" )] )
95 return NSTerminateCancel;
100 return NSTerminateNow;
103 - (void) awakeFromNib
107 [self TranslateStrings];
110 //[self registrationDictionaryForGrowl];
111 /* Init User Presets .plist */
112 /* We declare the default NSFileManager into fileManager */
113 NSFileManager * fileManager = [NSFileManager defaultManager];
114 //presetPrefs = [[NSUserDefaults standardUserDefaults] retain];
115 /* we set the files and support paths here */
116 AppSupportDirectory = @"~/Library/Application Support/HandBrake";
117 AppSupportDirectory = [AppSupportDirectory stringByExpandingTildeInPath];
119 UserPresetsFile = @"~/Library/Application Support/HandBrake/UserPresets.plist";
120 UserPresetsFile = [UserPresetsFile stringByExpandingTildeInPath];
122 x264ProfilesFile = @"~/Library/Application Support/HandBrake/x264Profiles.plist";
123 x264ProfilesFile = [x264ProfilesFile stringByExpandingTildeInPath];
124 /* We check for the app support directory for media fork */
125 if ([fileManager fileExistsAtPath:AppSupportDirectory] == 0)
127 // If it doesnt exist yet, we create it here
128 [fileManager createDirectoryAtPath:AppSupportDirectory attributes:nil];
130 // We check for the presets.plist here
132 if ([fileManager fileExistsAtPath:UserPresetsFile] == 0)
135 [fileManager createFileAtPath:UserPresetsFile contents:nil attributes:nil];
138 // We check for the x264profiles.plist here
140 if ([fileManager fileExistsAtPath:x264ProfilesFile] == 0)
143 [fileManager createFileAtPath:x264ProfilesFile contents:nil attributes:nil];
147 UserPresetsFile = @"~/Library/Application Support/HandBrake/UserPresets.plist";
148 UserPresetsFile = [[UserPresetsFile stringByExpandingTildeInPath]retain];
150 UserPresets = [[NSMutableArray alloc] initWithContentsOfFile:UserPresetsFile];
151 if (nil == UserPresets)
153 UserPresets = [[NSMutableArray alloc] init];
154 [self AddFactoryPresets:NULL];
156 /* Show/Dont Show Presets drawer upon launch based
157 on user preference DefaultPresetsDrawerShow*/
158 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPresetsDrawerShow"] > 0)
160 [fPresetDrawer open];
166 [fDstFormatPopUp removeAllItems];
167 [fDstFormatPopUp addItemWithTitle: _( @"MP4 file" )];
168 [fDstFormatPopUp addItemWithTitle: _( @"AVI file" )];
169 [fDstFormatPopUp addItemWithTitle: _( @"OGM file" )];
170 [fDstFormatPopUp selectItemAtIndex: 0];
172 [self FormatPopUpChanged: NULL];
173 /* We enable the create chapters checkbox here since we are .mp4 */
174 [fCreateChapterMarkers setEnabled: YES];
175 if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultChapterMarkers"] > 0)
177 [fCreateChapterMarkers setState: NSOnState];
179 [fDstFile2Field setStringValue: [NSString stringWithFormat:
180 @"%@/Desktop/Movie.mp4", NSHomeDirectory()]];
183 [fVidEncoderPopUp removeAllItems];
184 [fVidEncoderPopUp addItemWithTitle: @"FFmpeg"];
185 [fVidEncoderPopUp addItemWithTitle: @"XviD"];
188 [fVidTargetSizeField setIntValue: 700];
189 [fVidBitrateField setIntValue: 1000];
191 [fVidQualityMatrix selectCell: fVidBitrateCell];
192 [self VideoMatrixChanged: NULL];
194 /* Video framerate */
195 [fVidRatePopUp removeAllItems];
196 [fVidRatePopUp addItemWithTitle: _( @"Same as source" )];
197 for( int i = 0; i < hb_video_rates_count; i++ )
199 [fVidRatePopUp addItemWithTitle:
200 [NSString stringWithCString: hb_video_rates[i].string]];
202 [fVidRatePopUp selectItemAtIndex: 0];
204 /* Picture Settings */
205 [fPicLabelPAROutp setStringValue: @""];
206 [fPicLabelPAROutputX setStringValue: @""];
207 [fPicSettingPARWidth setStringValue: @""];
208 [fPicSettingPARHeight setStringValue: @""];
211 [fAudBitratePopUp removeAllItems];
212 for( int i = 0; i < hb_audio_bitrates_count; i++ )
214 [fAudBitratePopUp addItemWithTitle:
215 [NSString stringWithCString: hb_audio_bitrates[i].string]];
217 [fAudBitratePopUp selectItemAtIndex: hb_audio_bitrates_default];
219 /* Audio samplerate */
220 [fAudRatePopUp removeAllItems];
221 for( int i = 0; i < hb_audio_rates_count; i++ )
223 [fAudRatePopUp addItemWithTitle:
224 [NSString stringWithCString: hb_audio_rates[i].string]];
226 [fAudRatePopUp selectItemAtIndex: hb_audio_rates_default];
229 [fStatusField setStringValue: @""];
232 [fPauseButton setEnabled: NO];
233 [fRipButton setEnabled: NO];
239 // register a test notification and make
240 // it enabled by default
241 #define SERVICE_NAME @"Encode Done"
242 - (NSDictionary *)registrationDictionaryForGrowl
244 NSDictionary *registrationDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
245 [NSArray arrayWithObjects:SERVICE_NAME,nil], GROWL_NOTIFICATIONS_ALL,
246 [NSArray arrayWithObjects:SERVICE_NAME,nil], GROWL_NOTIFICATIONS_DEFAULT,
249 return registrationDictionary;
251 - (void) TranslateStrings
253 [fSrcDVD1Field setStringValue: _( @"DVD:" )];
254 [fSrcTitleField setStringValue: _( @"Title:" )];
255 [fSrcChapterField setStringValue: _( @"Chapters:" )];
256 [fSrcChapterToField setStringValue: _( @"to" )];
257 [fSrcDuration1Field setStringValue: _( @"Duration:" )];
259 [fDstFormatField setStringValue: _( @"File format:" )];
260 [fDstCodecsField setStringValue: _( @"Codecs:" )];
261 [fDstFile1Field setStringValue: _( @"File:" )];
262 [fDstBrowseButton setTitle: _( @"Browse" )];
264 [fVidRateField setStringValue: _( @"Framerate (fps):" )];
265 [fVidEncoderField setStringValue: _( @"Encoder:" )];
266 [fVidQualityField setStringValue: _( @"Quality:" )];
269 /***********************************************************************
271 ***********************************************************************
272 * Shows a progression bar on the dock icon, filled according to
273 * 'progress' (0.0 <= progress <= 1.0).
274 * Called with progress < 0.0 or progress > 1.0, restores the original
276 **********************************************************************/
277 - (void) UpdateDockIcon: (float) progress
281 NSBitmapImageRep * bmp;
283 uint32_t black = htonl( 0x000000FF );
284 uint32_t red = htonl( 0xFF0000FF );
285 uint32_t white = htonl( 0xFFFFFFFF );
286 int row_start, row_end;
289 /* Get application original icon */
290 icon = [NSImage imageNamed: @"NSApplicationIcon"];
292 if( progress < 0.0 || progress > 1.0 )
294 [NSApp setApplicationIconImage: icon];
298 /* Get it in a raw bitmap form */
299 tiff = [icon TIFFRepresentationUsingCompression:
300 NSTIFFCompressionNone factor: 1.0];
301 bmp = [NSBitmapImageRep imageRepWithData: tiff];
303 /* Draw the progression bar */
304 /* It's pretty simple (ugly?) now, but I'm no designer */
306 row_start = 3 * (int) [bmp size].height / 4;
307 row_end = 7 * (int) [bmp size].height / 8;
309 for( i = row_start; i < row_start + 2; i++ )
311 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
312 for( j = 0; j < (int) [bmp size].width; j++ )
317 for( i = row_start + 2; i < row_end - 2; i++ )
319 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
322 for( j = 2; j < (int) [bmp size].width - 2; j++ )
324 if( j < 2 + (int) ( ( [bmp size].width - 4.0 ) * progress ) )
336 for( i = row_end - 2; i < row_end; i++ )
338 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
339 for( j = 0; j < (int) [bmp size].width; j++ )
345 /* Now update the dock icon */
346 tiff = [bmp TIFFRepresentationUsingCompression:
347 NSTIFFCompressionNone factor: 1.0];
348 icon = [[NSImage alloc] initWithData: tiff];
349 [NSApp setApplicationIconImage: icon];
353 - (void) UpdateUI: (NSTimer *) timer
357 hb_get_state( fHandle, &s );
364 case HB_STATE_SCANNING:
365 [fScanController UpdateUI: &s];
368 #define p s.param.scandone
369 case HB_STATE_SCANDONE:
373 int indxpri=0; // Used to search the longuest title (default in combobox)
374 int longuestpri=0; // Used to search the longuest title (default in combobox)
376 [fScanController UpdateUI: &s];
378 list = hb_get_titles( fHandle );
380 if( !hb_list_count( list ) )
386 [fSrcTitlePopUp removeAllItems];
387 for( int i = 0; i < hb_list_count( list ); i++ )
389 title = (hb_title_t *) hb_list_item( list, i );
390 /*Set DVD Name at top of window*/
391 [fSrcDVD2Field setStringValue: [NSString
392 stringWithUTF8String: title->name]];
394 /* Use the dvd name in the default output field here
395 May want to add code to remove blank spaces for some dvd names*/
396 /* Check to see if the last destination has been set,use if so, if not, use Desktop */
397 if ([[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"])
399 [fDstFile2Field setStringValue: [NSString stringWithFormat:
400 @"%@/%@.mp4", [[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"],[NSString
401 stringWithUTF8String: title->name]]];
405 [fDstFile2Field setStringValue: [NSString stringWithFormat:
406 @"%@/Desktop/%@.mp4", NSHomeDirectory(),[NSString
407 stringWithUTF8String: title->name]]];
411 if (longuestpri < title->hours*60*60 + title->minutes *60 + title->seconds)
413 longuestpri=title->hours*60*60 + title->minutes *60 + title->seconds;
418 int format = [fDstFormatPopUp indexOfSelectedItem];
424 /*Get Default MP4 File Extension for mpeg4 (.mp4 or .m4v) from prefs*/
425 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultMpegName"] > 0)
443 NSString * string = [fDstFile2Field stringValue];
444 /* Add/replace File Output name to the correct extension*/
445 if( [string characterAtIndex: [string length] - 4] == '.' )
447 [fDstFile2Field setStringValue: [NSString stringWithFormat:
448 @"%@.%s", [string substringToIndex: [string length] - 4],
453 [fDstFile2Field setStringValue: [NSString stringWithFormat:
454 @"%@.%s", string, ext]];
458 [fSrcTitlePopUp addItemWithTitle: [NSString
459 stringWithFormat: @"%d - %02dh%02dm%02ds",
460 title->index, title->hours, title->minutes,
464 // Select the longuest title
465 [fSrcTitlePopUp selectItemAtIndex: indxpri];
466 /* We set the Settings Display to "Default" here
467 until we get default presets implemented */
468 [fPresetSelectedDisplay setStringValue: @"Default"];
470 [self TitlePopUpChanged: NULL];
471 [self EnableUI: YES];
472 [fPauseButton setEnabled: NO];
473 [fRipButton setEnabled: YES];
478 #define p s.param.working
479 case HB_STATE_WORKING:
481 float progress_total;
482 NSMutableString * string;
484 /* Update text field */
485 string = [NSMutableString stringWithFormat:
486 _( @"Encoding: task %d of %d, %.2f %%" ),
487 p.job_cur, p.job_count, 100.0 * p.progress];
490 [string appendFormat:
491 _( @" (%.2f fps, avg %.2f fps, ETA %02dh%02dm%02ds)" ),
492 p.rate_cur, p.rate_avg, p.hours, p.minutes, p.seconds];
494 [fStatusField setStringValue: string];
497 progress_total = ( p.progress + p.job_cur - 1 ) / p.job_count;
498 [fRipIndicator setIndeterminate: NO];
499 [fRipIndicator setDoubleValue: 100.0 * progress_total];
501 /* Update dock icon */
502 [self UpdateDockIcon: progress_total];
504 [fPauseButton setEnabled: YES];
505 [fPauseButton setTitle: _( @"Pause" )];
506 [fRipButton setEnabled: YES];
507 [fRipButton setTitle: _( @"Cancel" )];
512 #define p s.param.muxing
513 case HB_STATE_MUXING:
515 NSMutableString * string;
517 /* Update text field */
518 string = [NSMutableString stringWithFormat:
520 [fStatusField setStringValue: string];
523 [fRipIndicator setIndeterminate: YES];
524 [fRipIndicator startAnimation: nil];
526 /* Update dock icon */
527 [self UpdateDockIcon: 1.0];
529 [fPauseButton setEnabled: YES];
530 [fPauseButton setTitle: _( @"Pause" )];
531 [fRipButton setEnabled: YES];
532 [fRipButton setTitle: _( @"Cancel" )];
537 case HB_STATE_PAUSED:
538 [fStatusField setStringValue: _( @"Paused" )];
539 [fPauseButton setEnabled: YES];
540 [fPauseButton setTitle: _( @"Resume" )];
541 [fRipButton setEnabled: YES];
542 [fRipButton setTitle: _( @"Cancel" )];
545 case HB_STATE_WORKDONE:
547 //[self EnableUI: YES];
548 [fStatusField setStringValue: _( @"Done." )];
549 [fRipIndicator setIndeterminate: NO];
550 [fRipIndicator setDoubleValue: 0.0];
551 [fRipButton setTitle: _( @"Start" )];
553 /* Restore dock icon */
554 [self UpdateDockIcon: -1.0];
556 [fPauseButton setEnabled: NO];
557 [fPauseButton setTitle: _( @"Pause" )];
558 [fRipButton setEnabled: YES];
559 [fRipButton setTitle: _( @"Start" )];
563 while( ( job = hb_job( fHandle, 0 ) ) )
565 hb_rem( fHandle, job );
568 if (fEncodeState != 2) // if the encode has not been cancelled
570 /* Lets alert the user that the encode has finished */
571 /*Growl Notification*/
572 [self showGrowlDoneNotification: NULL];
573 /*On Screen Notification*/
576 status = NSRunAlertPanel(@"Put down that cocktail...",@"your HandBrake encode is done!", @"OK", nil, nil);
577 //[NSApp requestUserAttention:NSInformationalRequest];
578 [NSApp requestUserAttention:NSCriticalRequest];
579 if ( status == NSAlertDefaultReturn )
581 [self EnableUI: YES];
586 [self EnableUI: YES];
592 /* Lets show the queue status
593 here in the main window*/
595 int count = hb_count( fHandle );
598 [fQueueStatus setStringValue: [NSString stringWithFormat:
599 @"%d task%s in the queue",
600 count, ( count > 1 ) ? "s" : ""]];
604 [fQueueStatus setStringValue: @""];
607 [[NSRunLoop currentRunLoop] addTimer: [NSTimer
608 scheduledTimerWithTimeInterval: 0.2 target: self
609 selector: @selector( UpdateUI: ) userInfo: NULL repeats: FALSE]
610 forMode: NSModalPanelRunLoopMode];
613 -(IBAction)showGrowlDoneNotification:(id)sender
617 [GrowlApplicationBridge
618 notifyWithTitle:@"Put down that cocktail..."
619 description:@"your HandBrake encode is done!"
620 notificationName:SERVICE_NAME
627 - (void) EnableUI: (bool) b
629 NSControl * controls[] =
630 { fSrcDVD1Field, fSrcDVD2Field, fSrcTitleField, fSrcTitlePopUp,
631 fSrcChapterField, fSrcChapterStartPopUp, fSrcChapterToField,
632 fSrcChapterEndPopUp, fSrcDuration1Field, fSrcDuration2Field,
633 fDstFormatField, fDstFormatPopUp, fDstCodecsField,
634 fDstCodecsPopUp, fDstFile1Field, fDstFile2Field,
635 fDstBrowseButton, fVidRateField, fVidRatePopUp,
636 fVidEncoderField, fVidEncoderPopUp, fVidQualityField,
637 fVidQualityMatrix, fVidGrayscaleCheck, fSubField, fSubPopUp,
638 fAudLang1Field, fAudLang1PopUp, fAudLang2Field, fAudLang2PopUp,
639 fAudTrack1MixLabel, fAudTrack1MixPopUp, fAudTrack2MixLabel, fAudTrack2MixPopUp,
640 fAudRateField, fAudRatePopUp, fAudBitrateField,
641 fAudBitratePopUp, fPictureButton,fQueueStatus,
642 fPicSrcWidth,fPicSrcHeight,fPicSettingWidth,fPicSettingHeight,
643 fPicSettingARkeep,fPicSettingDeinterlace,fPicSettingARkeepDsply,
644 fPicSettingDeinterlaceDsply,fPicLabelSettings,fPicLabelSrc,fPicLabelOutp,
645 fPicLabelAr,fPicLabelDeinter,fPicLabelSrcX,fPicLabelOutputX,
646 fPicLabelPAROutp,fPicLabelPAROutputX,fPicSettingPARWidth,fPicSettingPARHeight,
647 fPicSettingPARDsply,fPicLabelAnamorphic,tableView,fPresetsAdd,fPresetsDelete,
648 fCreateChapterMarkers,fX264optViewTitleLabel,fDisplayX264Options,fDisplayX264OptionsLabel,fX264optBframesLabel,
649 fX264optBframesPopUp,fX264optRefLabel,fX264optRefPopUp,fX264optNfpskipLabel,fX264optNfpskipPopUp,
650 fX264optNodctdcmtLabel,fX264optNodctdcmtPopUp,fX264optSubmeLabel,fX264optSubmePopUp,
651 fX264optTrellisLabel,fX264optTrellisPopUp,fX264optMixedRefsLabel,fX264optMixedRefsPopUp,
652 fX264optMotionEstLabel,fX264optMotionEstPopUp,fX264optMERangeLabel,fX264optMERangePopUp,
653 fX264optWeightBLabel,fX264optWeightBPopUp,fX264optBRDOLabel,fX264optBRDOPopUp,
654 fX264optBPyramidLabel,fX264optBPyramidPopUp};
657 i < sizeof( controls ) / sizeof( NSControl * ); i++ )
659 if( [[controls[i] className] isEqualToString: @"NSTextField"] )
661 NSTextField * tf = (NSTextField *) controls[i];
662 if( ![tf isBezeled] )
664 [tf setTextColor: b ? [NSColor controlTextColor] :
665 [NSColor disabledControlTextColor]];
669 [controls[i] setEnabled: b];
675 /* if we're enabling the interface, check if the audio mixdown controls need to be enabled or not */
676 /* these will have been enabled by the mass control enablement above anyway, so we're sense-checking it here */
677 [self SetEnabledStateOfAudioMixdownControls: NULL];
681 [tableView setEnabled: NO];
685 [self VideoMatrixChanged: NULL];
688 - (IBAction) ShowScanPanel: (id) sender
690 [fScanController Show];
693 - (BOOL) windowShouldClose: (id) sender
695 /* Stop the application when the user closes the window */
696 [NSApp terminate: self];
700 - (IBAction) VideoMatrixChanged: (id) sender;
702 bool target, bitrate, quality;
704 target = bitrate = quality = false;
705 if( [fVidQualityMatrix isEnabled] )
707 switch( [fVidQualityMatrix selectedRow] )
720 [fVidTargetSizeField setEnabled: target];
721 [fVidBitrateField setEnabled: bitrate];
722 [fVidQualitySlider setEnabled: quality];
723 [fVidTwoPassCheck setEnabled: !quality &&
724 [fVidQualityMatrix isEnabled]];
727 [fVidTwoPassCheck setState: NSOffState];
730 [self QualitySliderChanged: sender];
731 [self CalculateBitrate: sender];
732 [self CustomSettingUsed: sender];
735 - (IBAction) QualitySliderChanged: (id) sender
737 [fVidConstantCell setTitle: [NSString stringWithFormat:
738 _( @"Constant quality: %.0f %%" ), 100.0 *
739 [fVidQualitySlider floatValue]]];
740 [self CustomSettingUsed: sender];
743 - (IBAction) BrowseFile: (id) sender
745 /* Open a panel to let the user choose and update the text field */
746 NSSavePanel * panel = [NSSavePanel savePanel];
747 /* We get the current file name and path from the destination field here */
748 [panel beginSheetForDirectory: [[fDstFile2Field stringValue] stringByDeletingLastPathComponent] file: [[fDstFile2Field stringValue] lastPathComponent]
749 modalForWindow: fWindow modalDelegate: self
750 didEndSelector: @selector( BrowseFileDone:returnCode:contextInfo: )
754 - (void) BrowseFileDone: (NSSavePanel *) sheet
755 returnCode: (int) returnCode contextInfo: (void *) contextInfo
757 if( returnCode == NSOKButton )
759 [fDstFile2Field setStringValue: [sheet filename]];
764 - (IBAction) ShowPicturePanel: (id) sender
766 hb_list_t * list = hb_get_titles( fHandle );
767 hb_title_t * title = (hb_title_t *) hb_list_item( list,
768 [fSrcTitlePopUp indexOfSelectedItem] );
770 /* Resize the panel */
772 newSize.width = 246 + title->width;
773 newSize.height = 80 + title->height;
774 [fPicturePanel setContentSize: newSize];
776 [fPictureController SetTitle: title];
778 [NSApp beginSheet: fPicturePanel modalForWindow: fWindow
779 modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
780 [NSApp runModalForWindow: fPicturePanel];
781 [NSApp endSheet: fPicturePanel];
782 [fPicturePanel orderOut: self];
783 [self CalculatePictureSizing: sender];
786 - (IBAction) ShowQueuePanel: (id) sender
788 /* Update the OutlineView */
789 [fQueueController Update: sender];
792 [NSApp beginSheet: fQueuePanel modalForWindow: fWindow
793 modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
794 [NSApp runModalForWindow: fQueuePanel];
795 [NSApp endSheet: fQueuePanel];
796 [fQueuePanel orderOut: self];
801 hb_list_t * list = hb_get_titles( fHandle );
802 hb_title_t * title = (hb_title_t *) hb_list_item( list,
803 [fSrcTitlePopUp indexOfSelectedItem] );
804 hb_job_t * job = title->job;
807 /* Chapter selection */
808 job->chapter_start = [fSrcChapterStartPopUp indexOfSelectedItem] + 1;
809 job->chapter_end = [fSrcChapterEndPopUp indexOfSelectedItem] + 1;
811 /* Format and codecs */
812 int format = [fDstFormatPopUp indexOfSelectedItem];
813 int codecs = [fDstCodecsPopUp indexOfSelectedItem];
814 job->mux = FormatSettings[format][codecs] & HB_MUX_MASK;
815 job->vcodec = FormatSettings[format][codecs] & HB_VCODEC_MASK;
816 job->acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
817 /* We set the chapter marker extraction here based on the format being
818 mpeg4 and the checkbox being checked */
819 if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [fCreateChapterMarkers state] == NSOnState)
821 job->chapter_markers = 1;
825 job->chapter_markers = 0;
827 if( ( job->vcodec & HB_VCODEC_FFMPEG ) &&
828 [fVidEncoderPopUp indexOfSelectedItem] > 0 )
830 job->vcodec = HB_VCODEC_XVID;
832 if( job->vcodec & HB_VCODEC_X264 )
834 if ([fVidEncoderPopUp indexOfSelectedItem] > 0 )
836 /* Just use new Baseline Level 3.0
837 Lets Deprecate Baseline Level 1.3*/
838 job->h264_level = 30;
839 job->mux = HB_MUX_IPOD;
840 /* move sanity check for iPod Encoding here */
841 job->pixel_ratio = 0 ;
845 /* Set this flag to switch from Constant Quantizer(default) to Constant Rate Factor Thanks jbrjake
846 Currently only used with Constant Quality setting*/
847 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultCrf"] > 0 && [fVidQualityMatrix selectedRow] == 2)
849 /* Can only be used with svn rev >= 89 */
853 /* Below Sends x264 options to the core library if x264 is selected*/
854 /* First we look to see if a user preset has been selected that contains a x264 optional string CurUserPresetChosenNum = nil */
855 //if (curUserPresetChosenNum != nil)
858 /* Lets use this as per Nyx, Thanks Nyx! fDisplayX264Options*/
859 job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */
860 strcpy(job->x264opts, [[fDisplayX264Options stringValue] UTF8String]);
861 //strcpy(job->x264opts, [[chosenPreset valueForKey:@"x264Option"] UTF8String]);
862 //job->x264opts = [[chosenPreset valueForKey:@"x264Option"] cString];
866 /* if not, then we check to see if there is a x264 opt in the preferences and use that if we want */
867 //job->x264opts = [[[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"] UTF8String];
868 /* Lets use this as per Nyx, Thanks Nyx! */
869 //job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */
870 //strcpy(job->x264opts, [[[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"] UTF8String]);
875 job->h264_13 = [fVidEncoderPopUp indexOfSelectedItem];
879 if( [fVidRatePopUp indexOfSelectedItem] > 0 )
881 job->vrate = 27000000;
882 job->vrate_base = hb_video_rates[[fVidRatePopUp
883 indexOfSelectedItem]-1].rate;
887 job->vrate = title->rate;
888 job->vrate_base = title->rate_base;
891 switch( [fVidQualityMatrix selectedRow] )
895 Bitrate should already have been calculated and displayed
896 in fVidBitrateField, so let's just use it */
898 job->vquality = -1.0;
899 job->vbitrate = [fVidBitrateField intValue];
902 job->vquality = [fVidQualitySlider floatValue];
907 job->grayscale = ( [fVidGrayscaleCheck state] == NSOnState );
911 /* Subtitle settings */
912 job->subtitle = [fSubPopUp indexOfSelectedItem] - 1;
914 /* Audio tracks and mixdowns */
915 /* check for the condition where track 2 has an audio selected, but track 1 does not */
916 /* we will use track 2 as track 1 in this scenario */
917 if ([fAudLang1PopUp indexOfSelectedItem] > 0)
919 job->audios[0] = [fAudLang1PopUp indexOfSelectedItem] - 1;
920 job->audios[1] = [fAudLang2PopUp indexOfSelectedItem] - 1; /* will be -1 if "none" is selected */
922 job->audio_mixdowns[0] = [[fAudTrack1MixPopUp selectedItem] tag];
923 job->audio_mixdowns[1] = [[fAudTrack2MixPopUp selectedItem] tag];
925 else if ([fAudLang2PopUp indexOfSelectedItem] > 0)
927 job->audios[0] = [fAudLang2PopUp indexOfSelectedItem] - 1;
928 job->audio_mixdowns[0] = [[fAudTrack2MixPopUp selectedItem] tag];
937 job->arate = hb_audio_rates[[fAudRatePopUp
938 indexOfSelectedItem]].rate;
939 job->abitrate = [[fAudBitratePopUp selectedItem] tag];
945 - (IBAction) AddToQueue: (id) sender
947 /* We get the destination directory from the destingation field here */
948 NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent];
949 /* We check for a valid destination here */
950 if ([[NSFileManager defaultManager] fileExistsAtPath:destinationDirectory] == 0)
952 NSRunAlertPanel(@"Warning!", @"This is not a valid destination directory!", @"OK", nil, nil);
957 hb_list_t * list = hb_get_titles( fHandle );
958 hb_title_t * title = (hb_title_t *) hb_list_item( list,
959 [fSrcTitlePopUp indexOfSelectedItem] );
960 hb_job_t * job = title->job;
964 /* Destination file */
965 job->file = [[fDstFile2Field stringValue] UTF8String];
967 if( [fVidTwoPassCheck state] == NSOnState )
970 hb_add( fHandle, job );
973 job->x264opts = (char *)calloc(1024, 1); /* Fixme, this just leaks */
974 strcpy(job->x264opts, [[fDisplayX264Options stringValue] UTF8String]);
976 hb_add( fHandle, job );
981 hb_add( fHandle, job );
984 [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"];
988 - (IBAction) Rip: (id) sender
990 /* Rip or Cancel ? */
991 if( [[fRipButton title] isEqualToString: _( @"Cancel" )] )
993 [self Cancel: sender];
996 /* if there is no job in the queue, then add it to the queue and rip
997 otherwise, there are already jobs in queue, so just rip the queue */
998 int count = hb_count( fHandle );
1001 [self AddToQueue: sender];
1004 /* We check for duplicate name here */
1005 if( [[NSFileManager defaultManager] fileExistsAtPath:
1006 [fDstFile2Field stringValue]] )
1008 NSBeginCriticalAlertSheet( _( @"File already exists" ),
1009 _( @"Cancel" ), _( @"Overwrite" ), NULL, fWindow, self,
1010 @selector( OverwriteAlertDone:returnCode:contextInfo: ),
1011 NULL, NULL, [NSString stringWithFormat:
1012 _( @"Do you want to overwrite %@?" ),
1013 [fDstFile2Field stringValue]] );
1016 /* We get the destination directory from the destination field here */
1017 NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent];
1018 /* We check for a valid destination here */
1019 if ([[NSFileManager defaultManager] fileExistsAtPath:destinationDirectory] == 0)
1021 NSRunAlertPanel(@"Warning!", @"This is not a valid destination directory!", @"OK", nil, nil);
1025 [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"];
1033 - (void) OverwriteAlertDone: (NSWindow *) sheet
1034 returnCode: (int) returnCode contextInfo: (void *) contextInfo
1036 if( returnCode == NSAlertAlternateReturn )
1042 - (void) UpdateAlertDone: (NSWindow *) sheet
1043 returnCode: (int) returnCode contextInfo: (void *) contextInfo
1045 if( returnCode == NSAlertAlternateReturn )
1047 /* Show scan panel */
1048 [self performSelectorOnMainThread: @selector(ShowScanPanel:)
1049 withObject: NULL waitUntilDone: NO];
1053 /* Go to HandBrake homepage and exit */
1054 [self OpenHomepage: NULL];
1055 [NSApp terminate: self];
1060 /* Let libhb do the job */
1061 hb_start( fHandle );
1062 /*set the fEncodeState State */
1065 /* Disable interface */
1066 [self EnableUI: NO];
1067 [fPauseButton setEnabled: NO];
1068 [fRipButton setEnabled: NO];
1071 - (IBAction) Cancel: (id) sender
1073 NSBeginCriticalAlertSheet( _( @"Cancel - Are you sure?" ),
1074 _( @"Keep working" ), _( @"Cancel encoding" ), NULL, fWindow, self,
1075 @selector( _Cancel:returnCode:contextInfo: ), NULL, NULL,
1076 _( @"Encoding won't be recoverable." ) );
1079 - (void) _Cancel: (NSWindow *) sheet
1080 returnCode: (int) returnCode contextInfo: (void *) contextInfo
1082 if( returnCode == NSAlertAlternateReturn )
1085 [fPauseButton setEnabled: NO];
1086 [fRipButton setEnabled: NO];
1087 /*set the fEncodeState State */
1092 - (IBAction) Pause: (id) sender
1094 [fPauseButton setEnabled: NO];
1095 [fRipButton setEnabled: NO];
1097 if( [[fPauseButton title] isEqualToString: _( @"Resume" )] )
1099 hb_resume( fHandle );
1103 hb_pause( fHandle );
1107 - (IBAction) TitlePopUpChanged: (id) sender
1109 hb_list_t * list = hb_get_titles( fHandle );
1110 hb_title_t * title = (hb_title_t*)
1111 hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
1114 /* If Auto Naming is on. We create an output filename of dvd name - title number */
1115 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultAutoNaming"] > 0)
1117 [fDstFile2Field setStringValue: [NSString stringWithFormat:
1118 @"%@/%@-%d.%@", [[fDstFile2Field stringValue] stringByDeletingLastPathComponent],
1119 [NSString stringWithUTF8String: title->name],
1120 [fSrcTitlePopUp indexOfSelectedItem] + 1,
1121 [[fDstFile2Field stringValue] pathExtension]]];
1124 /* Update chapter popups */
1125 [fSrcChapterStartPopUp removeAllItems];
1126 [fSrcChapterEndPopUp removeAllItems];
1127 for( int i = 0; i < hb_list_count( title->list_chapter ); i++ )
1129 [fSrcChapterStartPopUp addItemWithTitle: [NSString
1130 stringWithFormat: @"%d", i + 1]];
1131 [fSrcChapterEndPopUp addItemWithTitle: [NSString
1132 stringWithFormat: @"%d", i + 1]];
1134 [fSrcChapterStartPopUp selectItemAtIndex: 0];
1135 [fSrcChapterEndPopUp selectItemAtIndex:
1136 hb_list_count( title->list_chapter ) - 1];
1137 [self ChapterPopUpChanged: NULL];
1139 /* Start Get and set the initial pic size for display */
1140 hb_job_t * job = title->job;
1142 /* Turn Deinterlace on/off depending on the preference */
1143 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultDeinterlaceOn"] > 0)
1145 job->deinterlace = 1;
1149 job->deinterlace = 0;
1152 /* Pixel Ratio Setting */
1153 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"PixelRatio"])
1156 job->pixel_ratio = 1 ;
1160 job->pixel_ratio = 0 ;
1162 /*Set Source Size Fields Here */
1163 [fPicSrcWidth setStringValue: [NSString stringWithFormat:
1164 @"%d", fTitle->width]];
1165 [fPicSrcHeight setStringValue: [NSString stringWithFormat:
1166 @"%d", fTitle->height]];
1167 /* We get the originial output picture width and height and put them
1168 in variables for use with some presets later on */
1169 PicOrigOutputWidth = job->width;
1170 PicOrigOutputHeight = job->height;
1171 /* we test getting the max output value for pic sizing here to be used later*/
1172 [fPicSettingWidth setStringValue: [NSString stringWithFormat:
1173 @"%d", PicOrigOutputWidth]];
1174 [fPicSettingHeight setStringValue: [NSString stringWithFormat:
1175 @"%d", PicOrigOutputHeight]];
1176 /* we run the picture size values through
1177 CalculatePictureSizing to get all picture size
1179 [self CalculatePictureSizing: NULL];
1180 /* Run Through EncoderPopUpChanged to see if there
1181 needs to be any pic value modifications based on encoder settings */
1182 //[self EncoderPopUpChanged: NULL];
1183 /* END Get and set the initial pic size for display */
1185 /* Update subtitle popups */
1186 hb_subtitle_t * subtitle;
1187 [fSubPopUp removeAllItems];
1188 [fSubPopUp addItemWithTitle: @"None"];
1189 for( int i = 0; i < hb_list_count( title->list_subtitle ); i++ )
1191 subtitle = (hb_subtitle_t *) hb_list_item( title->list_subtitle, i );
1193 /* We cannot use NSPopUpButton's addItemWithTitle because
1194 it checks for duplicate entries */
1195 [[fSubPopUp menu] addItemWithTitle: [NSString stringWithCString:
1196 subtitle->lang] action: NULL keyEquivalent: @""];
1198 [fSubPopUp selectItemAtIndex: 0];
1200 /* Update chapter table */
1201 [fChapterTitlesDelegate resetWithTitle:title];
1202 [fChapterTable reloadData];
1204 /* Update audio popups */
1205 [self AddAllAudioTracksToPopUp: fAudLang1PopUp];
1206 [self AddAllAudioTracksToPopUp: fAudLang2PopUp];
1207 /* search for the first instance of our prefs default language for track 1, and set track 2 to "none" */
1208 NSString * audioSearchPrefix = [[NSUserDefaults standardUserDefaults] stringForKey:@"DefaultLanguage"];
1209 [self SelectAudioTrackInPopUp: fAudLang1PopUp searchPrefixString: audioSearchPrefix selectIndexIfNotFound: 1];
1210 [self SelectAudioTrackInPopUp: fAudLang2PopUp searchPrefixString: NULL selectIndexIfNotFound: 0];
1212 /* changing the title may have changed the audio channels on offer, */
1213 /* so call AudioTrackPopUpChanged for both audio tracks to update the mixdown popups */
1214 [self AudioTrackPopUpChanged: fAudLang1PopUp];
1215 [self AudioTrackPopUpChanged: fAudLang2PopUp];
1219 - (IBAction) ChapterPopUpChanged: (id) sender
1221 hb_list_t * list = hb_get_titles( fHandle );
1222 hb_title_t * title = (hb_title_t *)
1223 hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
1225 hb_chapter_t * chapter;
1226 int64_t duration = 0;
1227 for( int i = [fSrcChapterStartPopUp indexOfSelectedItem];
1228 i <= [fSrcChapterEndPopUp indexOfSelectedItem]; i++ )
1230 chapter = (hb_chapter_t *) hb_list_item( title->list_chapter, i );
1231 duration += chapter->duration;
1234 duration /= 90000; /* pts -> seconds */
1235 [fSrcDuration2Field setStringValue: [NSString stringWithFormat:
1236 @"%02lld:%02lld:%02lld", duration / 3600, ( duration / 60 ) % 60,
1239 [self CalculateBitrate: sender];
1242 - (IBAction) FormatPopUpChanged: (id) sender
1244 NSString * string = [fDstFile2Field stringValue];
1245 int format = [fDstFormatPopUp indexOfSelectedItem];
1248 /* Update the codecs popup */
1249 [fDstCodecsPopUp removeAllItems];
1253 /*Get Default MP4 File Extension*/
1254 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultMpegName"] > 0)
1262 [fDstCodecsPopUp addItemWithTitle:
1263 _( @"MPEG-4 Video / AAC Audio" )];
1264 [fDstCodecsPopUp addItemWithTitle:
1265 _( @"AVC/H.264 Video / AAC Audio" )];
1266 /* We enable the create chapters checkbox here since we are .mp4*/
1267 [fCreateChapterMarkers setEnabled: YES];
1271 [fDstCodecsPopUp addItemWithTitle:
1272 _( @"MPEG-4 Video / MP3 Audio" )];
1273 [fDstCodecsPopUp addItemWithTitle:
1274 _( @"MPEG-4 Video / AC-3 Audio" )];
1275 [fDstCodecsPopUp addItemWithTitle:
1276 _( @"AVC/H.264 Video / MP3 Audio" )];
1277 [fDstCodecsPopUp addItemWithTitle:
1278 _( @"AVC/H.264 Video / AC-3 Audio" )];
1279 /* We disable the create chapters checkbox here since we are NOT .mp4
1280 and make sure it is unchecked*/
1281 [fCreateChapterMarkers setEnabled: NO];
1282 [fCreateChapterMarkers setState: NSOffState];
1286 [fDstCodecsPopUp addItemWithTitle:
1287 _( @"MPEG-4 Video / Vorbis Audio" )];
1288 [fDstCodecsPopUp addItemWithTitle:
1289 _( @"MPEG-4 Video / MP3 Audio" )];
1290 /* We disable the create chapters checkbox here since we are NOT .mp4
1291 and make sure it is unchecked*/
1292 [fCreateChapterMarkers setEnabled: NO];
1293 [fCreateChapterMarkers setState: NSOffState];
1296 [self CodecsPopUpChanged: NULL];
1298 /* Add/replace to the correct extension */
1299 if( [string characterAtIndex: [string length] - 4] == '.' )
1301 [fDstFile2Field setStringValue: [NSString stringWithFormat:
1302 @"%@.%s", [string substringToIndex: [string length] - 4],
1307 [fDstFile2Field setStringValue: [NSString stringWithFormat:
1308 @"%@.%s", string, ext]];
1311 /* changing the format may mean that we can / can't offer mono or 6ch, */
1312 /* so call AudioTrackPopUpChanged for both audio tracks to update the mixdown popups */
1313 [self AudioTrackPopUpChanged: fAudLang1PopUp];
1314 [self AudioTrackPopUpChanged: fAudLang2PopUp];
1316 /* We call method method to change UI to reflect whether a preset is used or not*/
1317 [self CustomSettingUsed: sender];
1321 - (IBAction) CodecsPopUpChanged: (id) sender
1323 int format = [fDstFormatPopUp indexOfSelectedItem];
1324 int codecs = [fDstCodecsPopUp indexOfSelectedItem];
1325 [fX264optView setHidden: YES];
1326 [fX264optViewTitleLabel setStringValue: @"Only Used With The x264 (H.264) Codec"];
1329 /* Update the encoder popup*/
1330 if( ( FormatSettings[format][codecs] & HB_VCODEC_X264 ) )
1332 /* MPEG-4 -> H.264 */
1333 [fVidEncoderPopUp removeAllItems];
1334 [fVidEncoderPopUp addItemWithTitle: @"x264 (h.264 Main)"];
1335 [fVidEncoderPopUp addItemWithTitle: @"x264 (h.264 iPod)"];
1336 [fX264optView setHidden: NO];
1337 [fX264optViewTitleLabel setStringValue: @""];
1340 else if( ( FormatSettings[format][codecs] & HB_VCODEC_FFMPEG ) )
1342 /* H.264 -> MPEG-4 */
1343 [fVidEncoderPopUp removeAllItems];
1344 [fVidEncoderPopUp addItemWithTitle: @"FFmpeg"];
1345 [fVidEncoderPopUp addItemWithTitle: @"XviD"];
1346 [fVidEncoderPopUp selectItemAtIndex: 0];
1350 if( FormatSettings[format][codecs] & HB_ACODEC_AC3 )
1352 /* AC-3 pass-through: disable samplerate and bitrate */
1353 [fAudRatePopUp setEnabled: NO];
1354 [fAudBitratePopUp setEnabled: NO];
1358 [fAudRatePopUp setEnabled: YES];
1359 [fAudBitratePopUp setEnabled: YES];
1362 /* changing the codecs on offer may mean that we can / can't offer mono or 6ch, */
1363 /* so call AudioTrackPopUpChanged for both audio tracks to update the mixdown popups */
1364 [self AudioTrackPopUpChanged: fAudLang1PopUp];
1365 [self AudioTrackPopUpChanged: fAudLang2PopUp];
1367 [self CalculateBitrate: sender];
1368 /* We call method method to change UI to reflect whether a preset is used or not*/
1369 [self CustomSettingUsed: sender];
1372 - (IBAction) EncoderPopUpChanged: (id) sender
1375 /* Check to see if we need to modify the job pic values based on x264 (iPod) encoder selection */
1376 if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [fDstCodecsPopUp indexOfSelectedItem] == 1 && [fVidEncoderPopUp indexOfSelectedItem] == 1)
1378 hb_job_t * job = fTitle->job;
1379 job->pixel_ratio = 0 ;
1381 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPicSizeAutoiPod"] > 0)
1384 if (job->width > 640)
1388 job->keep_ratio = 1;
1389 hb_fix_aspect( job, HB_KEEP_WIDTH );
1395 [self CalculatePictureSizing: sender];
1396 /* We call method method to change UI to reflect whether a preset is used or not*/
1397 [self CustomSettingUsed: sender];
1400 - (IBAction) SetEnabledStateOfAudioMixdownControls: (id) sender
1403 /* enable/disable the mixdown text and popupbutton for audio track 1 */
1404 [fAudTrack1MixPopUp setEnabled: ([fAudLang1PopUp indexOfSelectedItem] == 0) ? NO : YES];
1405 [fAudTrack1MixLabel setTextColor: ([fAudLang1PopUp indexOfSelectedItem] == 0) ?
1406 [NSColor disabledControlTextColor] : [NSColor controlTextColor]];
1408 /* enable/disable the mixdown text and popupbutton for audio track 2 */
1409 [fAudTrack2MixPopUp setEnabled: ([fAudLang2PopUp indexOfSelectedItem] == 0) ? NO : YES];
1410 [fAudTrack2MixLabel setTextColor: ([fAudLang2PopUp indexOfSelectedItem] == 0) ?
1411 [NSColor disabledControlTextColor] : [NSColor controlTextColor]];
1415 - (IBAction) AddAllAudioTracksToPopUp: (id) sender
1418 hb_list_t * list = hb_get_titles( fHandle );
1419 hb_title_t * title = (hb_title_t*)
1420 hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
1424 [sender removeAllItems];
1425 [sender addItemWithTitle: _( @"None" )];
1426 for( int i = 0; i < hb_list_count( title->list_audio ); i++ )
1428 audio = (hb_audio_t *) hb_list_item( title->list_audio, i );
1429 [[sender menu] addItemWithTitle:
1430 [NSString stringWithCString: audio->lang]
1431 action: NULL keyEquivalent: @""];
1433 [sender selectItemAtIndex: 0];
1437 - (IBAction) SelectAudioTrackInPopUp: (id) sender searchPrefixString: (NSString *) searchPrefixString selectIndexIfNotFound: (int) selectIndexIfNotFound
1440 /* this method can be used to find a language, or a language-and-source-format combination, by passing in the appropriate string */
1441 /* e.g. to find the first French track, pass in an NSString * of "Francais" */
1442 /* e.g. to find the first English 5.1 AC3 track, pass in an NSString * of "English (AC3) (5.1 ch)" */
1443 /* if no matching track is found, then selectIndexIfNotFound is used to choose which track to select instead */
1445 if (searchPrefixString != NULL)
1448 for( int i = 0; i < [sender numberOfItems]; i++ )
1450 /* Try to find the desired search string */
1451 if ([[[sender itemAtIndex: i] title] hasPrefix:searchPrefixString])
1453 [sender selectItemAtIndex: i];
1457 /* couldn't find the string, so select the requested "search string not found" item */
1458 /* index of 0 means select the "none" item */
1459 /* index of 1 means select the first audio track */
1460 [sender selectItemAtIndex: selectIndexIfNotFound];
1464 /* if no search string is provided, then select the selectIndexIfNotFound item */
1465 [sender selectItemAtIndex: selectIndexIfNotFound];
1470 - (IBAction) AudioTrackPopUpChanged: (id) sender
1472 /* utility function to call AudioTrackPopUpChanged without passing in a mixdown-to-use */
1473 [self AudioTrackPopUpChanged: sender mixdownToUse: 0];
1476 - (IBAction) AudioTrackPopUpChanged: (id) sender mixdownToUse: (int) mixdownToUse
1479 /* make sure we have a selected title before continuing */
1480 if (fTitle == NULL) return;
1482 /* find out if audio track 1 or 2 was changed - this is passed to us in the tag of the sender */
1483 /* the sender will have been either fAudLang1PopUp (tag = 0) or fAudLang2PopUp (tag = 1) */
1484 int thisAudio = [sender tag];
1486 /* get the index of the selected audio */
1487 int thisAudioIndex = [sender indexOfSelectedItem] - 1;
1489 /* Handbrake can't currently cope with ripping the same source track twice */
1490 /* So, if this audio is also selected in the other audio track popup, set that popup's selection to "none" */
1491 /* get a reference to the two audio track popups */
1492 NSPopUpButton * thisAudioPopUp = (thisAudio == 1 ? fAudLang2PopUp : fAudLang1PopUp);
1493 NSPopUpButton * otherAudioPopUp = (thisAudio == 1 ? fAudLang1PopUp : fAudLang2PopUp);
1494 /* if the same track is selected in the other audio popup, then select "none" in that popup */
1495 /* unless, of course, both are selected as "none!" */
1496 if ([thisAudioPopUp indexOfSelectedItem] != 0 && [thisAudioPopUp indexOfSelectedItem] == [otherAudioPopUp indexOfSelectedItem]) {
1497 [otherAudioPopUp selectItemAtIndex: 0];
1498 [self AudioTrackPopUpChanged: otherAudioPopUp];
1501 /* pointer for the hb_audio_s struct we will use later on */
1504 /* find out what the currently-selected output audio codec is */
1505 int format = [fDstFormatPopUp indexOfSelectedItem];
1506 int codecs = [fDstCodecsPopUp indexOfSelectedItem];
1507 int acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
1509 /* pointer to this track's mixdown NSPopUpButton */
1510 NSTextField * mixdownTextField;
1511 NSPopUpButton * mixdownPopUp;
1513 /* find our mixdown NSTextField and NSPopUpButton */
1516 mixdownTextField = fAudTrack1MixLabel;
1517 mixdownPopUp = fAudTrack1MixPopUp;
1521 mixdownTextField = fAudTrack2MixLabel;
1522 mixdownPopUp = fAudTrack2MixPopUp;
1525 /* delete the previous audio mixdown options */
1526 [mixdownPopUp removeAllItems];
1528 /* check if the audio mixdown controls need their enabled state changing */
1529 [self SetEnabledStateOfAudioMixdownControls: NULL];
1531 if (thisAudioIndex != -1)
1535 audio = (hb_audio_t *) hb_list_item( fTitle->list_audio, thisAudioIndex );
1539 /* find out if our selected output audio codec supports mono and / or 6ch */
1540 /* we also check for an input codec of AC3 or DCA,
1541 as they are the only libraries able to do the mixdown to mono / conversion to 6-ch */
1542 /* audioCodecsSupportMono and audioCodecsSupport6Ch are the same for now,
1543 but this may change in the future, so they are separated for flexibility */
1544 int audioCodecsSupportMono = ((audio->codec == HB_ACODEC_AC3 ||
1545 audio->codec == HB_ACODEC_DCA) && acodec == HB_ACODEC_FAAC);
1546 int audioCodecsSupport6Ch = ((audio->codec == HB_ACODEC_AC3 ||
1547 audio->codec == HB_ACODEC_DCA) && acodec == HB_ACODEC_FAAC);
1549 /* check for AC-3 passthru */
1550 if (audio->codec == HB_ACODEC_AC3 && acodec == HB_ACODEC_AC3)
1552 [[mixdownPopUp menu] addItemWithTitle:
1553 [NSString stringWithCString: "AC3 Passthru"]
1554 action: NULL keyEquivalent: @""];
1559 /* add the appropriate audio mixdown menuitems to the popupbutton */
1560 /* in each case, we set the new menuitem's tag to be the amixdown value for that mixdown,
1561 so that we can reference the mixdown later */
1563 /* keep a track of the min and max mixdowns we used, so we can select the best match later */
1564 int minMixdownUsed = 0;
1565 int maxMixdownUsed = 0;
1567 /* get the input channel layout without any lfe channels */
1568 int layout = audio->input_channel_layout & HB_INPUT_CH_LAYOUT_DISCRETE_NO_LFE_MASK;
1570 /* do we want to add a mono option? */
1571 if (audioCodecsSupportMono == 1) {
1572 id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
1573 [NSString stringWithCString: hb_audio_mixdowns[0].human_readable_name]
1574 action: NULL keyEquivalent: @""];
1575 [menuItem setTag: hb_audio_mixdowns[0].amixdown];
1576 if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[0].amixdown;
1577 maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[0].amixdown);
1580 /* do we want to add a stereo option? */
1581 /* offer stereo if we have a mono source and non-mono-supporting codecs, as otherwise we won't have a mixdown at all */
1582 /* also offer stereo if we have a stereo-or-better source */
1583 if ((layout == HB_INPUT_CH_LAYOUT_MONO && audioCodecsSupportMono == 0) || layout >= HB_INPUT_CH_LAYOUT_STEREO) {
1584 id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
1585 [NSString stringWithCString: hb_audio_mixdowns[1].human_readable_name]
1586 action: NULL keyEquivalent: @""];
1587 [menuItem setTag: hb_audio_mixdowns[1].amixdown];
1588 if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[1].amixdown;
1589 maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[1].amixdown);
1592 /* do we want to add a dolby surround (DPL1) option? */
1593 if (layout == HB_INPUT_CH_LAYOUT_3F1R || layout == HB_INPUT_CH_LAYOUT_3F2R || layout == HB_INPUT_CH_LAYOUT_DOLBY) {
1594 id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
1595 [NSString stringWithCString: hb_audio_mixdowns[2].human_readable_name]
1596 action: NULL keyEquivalent: @""];
1597 [menuItem setTag: hb_audio_mixdowns[2].amixdown];
1598 if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[2].amixdown;
1599 maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[2].amixdown);
1602 /* do we want to add a dolby pro logic 2 (DPL2) option? */
1603 if (layout == HB_INPUT_CH_LAYOUT_3F2R) {
1604 id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
1605 [NSString stringWithCString: hb_audio_mixdowns[3].human_readable_name]
1606 action: NULL keyEquivalent: @""];
1607 [menuItem setTag: hb_audio_mixdowns[3].amixdown];
1608 if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[3].amixdown;
1609 maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[3].amixdown);
1612 /* do we want to add a 6-channel discrete option? */
1613 if (audioCodecsSupport6Ch == 1 && layout == HB_INPUT_CH_LAYOUT_3F2R && (audio->input_channel_layout & HB_INPUT_CH_LAYOUT_HAS_LFE)) {
1614 id<NSMenuItem> menuItem = [[mixdownPopUp menu] addItemWithTitle:
1615 [NSString stringWithCString: hb_audio_mixdowns[4].human_readable_name]
1616 action: NULL keyEquivalent: @""];
1617 [menuItem setTag: hb_audio_mixdowns[4].amixdown];
1618 if (minMixdownUsed == 0) minMixdownUsed = hb_audio_mixdowns[4].amixdown;
1619 maxMixdownUsed = MAX(maxMixdownUsed, hb_audio_mixdowns[4].amixdown);
1622 /* auto-select the best mixdown based on our saved mixdown preference */
1624 /* for now, this is hard-coded to a "best" mixdown of HB_AMIXDOWN_DOLBYPLII */
1625 /* ultimately this should be a prefs option */
1628 /* if we passed in a mixdown to use - in order to load a preset - then try and use it */
1629 if (mixdownToUse > 0)
1631 useMixdown = mixdownToUse;
1635 useMixdown = HB_AMIXDOWN_DOLBYPLII;
1638 /* if useMixdown > maxMixdownUsed, then use maxMixdownUsed */
1639 if (useMixdown > maxMixdownUsed) useMixdown = maxMixdownUsed;
1641 /* if useMixdown < minMixdownUsed, then use minMixdownUsed */
1642 if (useMixdown < minMixdownUsed) useMixdown = minMixdownUsed;
1644 /* select the (possibly-amended) preferred mixdown */
1645 [mixdownPopUp selectItemWithTag: useMixdown];
1647 /* lets call the AudioTrackMixdownChanged method here to determine appropriate bitrates, etc. */
1648 [self AudioTrackMixdownChanged: NULL];
1655 /* see if the new audio track choice will change the bitrate we need */
1656 [self CalculateBitrate: sender];
1659 - (IBAction) AudioTrackMixdownChanged: (id) sender
1662 /* find out what the currently-selected output audio codec is */
1663 int format = [fDstFormatPopUp indexOfSelectedItem];
1664 int codecs = [fDstCodecsPopUp indexOfSelectedItem];
1665 int acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
1667 /* storage variable for the min and max bitrate allowed for this codec */
1673 case HB_ACODEC_FAAC:
1674 /* check if we have a 6ch discrete conversion in either audio track */
1675 if ([[fAudTrack1MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH || [[fAudTrack2MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH)
1677 /* FAAC is happy using our min bitrate of 32 kbps, even for 6ch */
1679 /* If either mixdown popup includes 6-channel discrete, then allow up to 384 kbps */
1685 /* FAAC is happy using our min bitrate of 32 kbps for stereo or mono */
1687 /* FAAC won't honour anything more than 160 for stereo, so let's not offer it */
1688 /* note: haven't dealt with mono separately here, FAAC will just use the max it can */
1693 case HB_ACODEC_LAME:
1694 /* Lame is happy using our min bitrate of 32 kbps */
1696 /* Lame won't encode if the bitrate is higher than 320 kbps */
1700 case HB_ACODEC_VORBIS:
1701 /* Vorbis causes a crash if we use a bitrate below 48 kbps */
1703 /* Vorbis can cope with 384 kbps quite happily, even for stereo */
1708 /* AC3 passthru disables the bitrate dropdown anyway, so we might as well just use the min and max bitrate */
1714 [fAudBitratePopUp removeAllItems];
1716 for( int i = 0; i < hb_audio_bitrates_count; i++ )
1718 if (hb_audio_bitrates[i].rate >= minbitrate && hb_audio_bitrates[i].rate <= maxbitrate)
1720 /* add a new menuitem for this bitrate */
1721 id<NSMenuItem> menuItem = [[fAudBitratePopUp menu] addItemWithTitle:
1722 [NSString stringWithCString: hb_audio_bitrates[i].string]
1723 action: NULL keyEquivalent: @""];
1724 /* set its tag to be the actual bitrate as an integer, so we can retrieve it later */
1725 [menuItem setTag: hb_audio_bitrates[i].rate];
1729 /* select the default bitrate (but use 384 for 6-ch AAC) */
1730 if ([[fAudTrack1MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH || [[fAudTrack2MixPopUp selectedItem] tag] == HB_AMIXDOWN_6CH)
1732 [fAudBitratePopUp selectItemWithTag: 384];
1736 [fAudBitratePopUp selectItemWithTag: hb_audio_bitrates[hb_audio_bitrates_default].rate];
1740 /* lets set the picture size back to the max from right after title scan
1741 Lets use an IBAction here as down the road we could always use a checkbox
1742 in the gui to easily take the user back to max. Remember, the compiler
1743 resolves IBActions down to -(void) during compile anyway */
1744 - (IBAction) RevertPictureSizeToMax: (id) sender
1746 hb_job_t * job = fTitle->job;
1747 /* We use the output picture width and height
1748 as calculated from libhb right after title is set
1749 in TitlePopUpChanged */
1750 job->width = PicOrigOutputWidth;
1751 job->height = PicOrigOutputHeight;
1755 [self CalculatePictureSizing: sender];
1756 /* We call method method to change UI to reflect whether a preset is used or not*/
1757 [self CustomSettingUsed: sender];
1761 /* Get and Display Current Pic Settings in main window */
1762 - (IBAction) CalculatePictureSizing: (id) sender
1766 [fPicSettingWidth setStringValue: [NSString stringWithFormat:
1767 @"%d", fTitle->job->width]];
1768 [fPicSettingHeight setStringValue: [NSString stringWithFormat:
1769 @"%d", fTitle->job->height]];
1770 [fPicSettingARkeep setStringValue: [NSString stringWithFormat:
1771 @"%d", fTitle->job->keep_ratio]];
1772 [fPicSettingDeinterlace setStringValue: [NSString stringWithFormat:
1773 @"%d", fTitle->job->deinterlace]];
1774 [fPicSettingPAR setStringValue: [NSString stringWithFormat:
1775 @"%d", fTitle->job->pixel_ratio]];
1777 if (fTitle->job->pixel_ratio == 1)
1779 int titlewidth = fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3];
1780 int arpwidth = fTitle->job->pixel_aspect_width;
1781 int arpheight = fTitle->job->pixel_aspect_height;
1782 int displayparwidth = titlewidth * arpwidth / arpheight;
1783 int displayparheight = fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1];
1784 [fPicSettingHeight setStringValue: [NSString stringWithFormat:
1785 @"%d", displayparheight]];
1786 [fPicLabelPAROutp setStringValue: @"Anamorphic Output:"];
1787 [fPicLabelPAROutputX setStringValue: @"x"];
1788 [fPicSettingPARWidth setStringValue: [NSString stringWithFormat:
1789 @"%d", displayparwidth]];
1790 [fPicSettingPARHeight setStringValue: [NSString stringWithFormat:
1791 @"%d", displayparheight]];
1793 fTitle->job->keep_ratio = 0;
1797 [fPicLabelPAROutp setStringValue: @""];
1798 [fPicLabelPAROutputX setStringValue: @""];
1799 [fPicSettingPARWidth setStringValue: @""];
1800 [fPicSettingPARHeight setStringValue: @""];
1803 /* Set ON/Off values for the deinterlace/keep aspect ratio according to boolean */
1804 if (fTitle->job->keep_ratio > 0)
1806 [fPicSettingARkeepDsply setStringValue: @"On"];
1810 [fPicSettingARkeepDsply setStringValue: @"Off"];
1812 if (fTitle->job->deinterlace > 0)
1814 [fPicSettingDeinterlaceDsply setStringValue: @"On"];
1818 [fPicSettingDeinterlaceDsply setStringValue: @"Off"];
1820 if (fTitle->job->pixel_ratio > 0)
1822 [fPicSettingPARDsply setStringValue: @"On"];
1826 [fPicSettingPARDsply setStringValue: @"Off"];
1828 /* below will trigger the preset, if selected, to be
1829 changed to "Custom". Lets comment out for now until
1830 we figure out a way to determine if the picture values
1831 changed modify the preset values */
1832 //[self CustomSettingUsed: sender];
1835 - (IBAction) CalculateBitrate: (id) sender
1837 if( !fHandle || [fVidQualityMatrix selectedRow] != 0 )
1842 hb_list_t * list = hb_get_titles( fHandle );
1843 hb_title_t * title = (hb_title_t *) hb_list_item( list,
1844 [fSrcTitlePopUp indexOfSelectedItem] );
1845 hb_job_t * job = title->job;
1849 [fVidBitrateField setIntValue: hb_calc_bitrate( job,
1850 [fVidTargetSizeField intValue] )];
1855 /* Method to determine if we should change the UI
1856 To reflect whether or not a Preset is being used or if
1857 the user is using "Custom" settings by determining the sender*/
1858 - (IBAction) CustomSettingUsed: (id) sender
1860 if ([sender stringValue] != NULL)
1862 /* Deselect the currently selected Preset if there is one*/
1863 [tableView deselectRow:[tableView selectedRow]];
1864 /* Change UI to show "Custom" settings are being used */
1865 [fPresetSelectedDisplay setStringValue: @"Custom"];
1867 curUserPresetChosenNum = nil;
1868 /* If we have MP4, AVC H.264 and x264 Main then we look to see
1869 if there are any x264 options from the preferences to use */
1870 if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [fDstCodecsPopUp indexOfSelectedItem] == 1)
1872 /* Lets check to see there is a specified string in the prefs, and use that if need be */
1873 if ([[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"] != @"")
1875 [fDisplayX264Options setStringValue: [NSString stringWithFormat:[[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"]]];
1880 /* Empty the field to display custom x264 preset options*/
1881 [fDisplayX264Options setStringValue: @""];
1885 [self X264AdvancedOptionsSet:NULL];
1888 - (IBAction) X264AdvancedOptionsSet: (id) sender
1890 /*Set opt widget values here*/
1892 /*B-Frames fX264optBframesPopUp*/
1894 [fX264optBframesPopUp removeAllItems];
1895 [fX264optBframesPopUp addItemWithTitle:@"Default (0)"];
1898 [fX264optBframesPopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
1901 /*Reference Frames fX264optRefPopUp*/
1902 [fX264optRefPopUp removeAllItems];
1903 [fX264optRefPopUp addItemWithTitle:@"Default (1)"];
1906 [fX264optRefPopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
1909 /*No Fast P-Skip fX264optNfpskipPopUp BOOLEAN*/
1910 [fX264optNfpskipPopUp removeAllItems];
1911 [fX264optNfpskipPopUp addItemWithTitle:@"Default (No)"];
1916 [fX264optNfpskipPopUp addItemWithTitle:[NSString stringWithFormat:@"No"]];
1920 [fX264optNfpskipPopUp addItemWithTitle:[NSString stringWithFormat:@"Yes"]];
1924 /*No Dict Decimate fX264optNodctdcmtPopUp BOOLEAN*/
1925 [fX264optNodctdcmtPopUp removeAllItems];
1926 [fX264optNodctdcmtPopUp addItemWithTitle:@"Default (No)"];
1931 [fX264optNodctdcmtPopUp addItemWithTitle:[NSString stringWithFormat:@"No"]];
1935 [fX264optNodctdcmtPopUp addItemWithTitle:[NSString stringWithFormat:@"Yes"]];
1939 /*Sub Me fX264optSubmePopUp*/
1940 [fX264optSubmePopUp removeAllItems];
1941 [fX264optSubmePopUp addItemWithTitle:@"Default (4)"];
1944 [fX264optSubmePopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
1947 /*Trellis fX264optTrellisPopUp*/
1948 [fX264optTrellisPopUp removeAllItems];
1949 [fX264optTrellisPopUp addItemWithTitle:@"Default (0)"];
1952 [fX264optTrellisPopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
1955 /*Mixed-references fX264optMixedRefsPopUp BOOLEAN*/
1956 [fX264optMixedRefsPopUp removeAllItems];
1957 [fX264optMixedRefsPopUp addItemWithTitle:@"Default (No)"];
1962 [fX264optMixedRefsPopUp addItemWithTitle:[NSString stringWithFormat:@"No"]];
1966 [fX264optMixedRefsPopUp addItemWithTitle:[NSString stringWithFormat:@"Yes"]];
1970 /*Motion Estimation fX264optMotionEstPopUp*/
1971 [fX264optMotionEstPopUp removeAllItems];
1972 [fX264optMotionEstPopUp addItemWithTitle:@"Default (Hexagon)"];
1973 [fX264optMotionEstPopUp addItemWithTitle:@"Diamond"];
1974 [fX264optMotionEstPopUp addItemWithTitle:@"Hexagon"];
1975 [fX264optMotionEstPopUp addItemWithTitle:@"Uneven Multi-Hexagon"];
1976 [fX264optMotionEstPopUp addItemWithTitle:@"Exhaustive"];
1978 /*Motion Estimation range fX264optMERangePopUp*/
1979 [fX264optMERangePopUp removeAllItems];
1980 [fX264optMERangePopUp addItemWithTitle:@"Default (16)"];
1983 [fX264optMERangePopUp addItemWithTitle:[NSString stringWithFormat:@"%d",i]];
1986 /*Weighted B-Frame Prediction fX264optWeightBPopUp BOOLEAN*/
1987 [fX264optWeightBPopUp removeAllItems];
1988 [fX264optWeightBPopUp addItemWithTitle:@"Default (No)"];
1993 [fX264optWeightBPopUp addItemWithTitle:[NSString stringWithFormat:@"No"]];
1997 [fX264optWeightBPopUp addItemWithTitle:[NSString stringWithFormat:@"Yes"]];
2001 /*B-Frame Rate Distortion Optimization fX264optBRDOPopUp BOOLEAN*/
2002 [fX264optBRDOPopUp removeAllItems];
2003 [fX264optBRDOPopUp addItemWithTitle:@"Default (No)"];
2008 [fX264optBRDOPopUp addItemWithTitle:[NSString stringWithFormat:@"No"]];
2012 [fX264optBRDOPopUp addItemWithTitle:[NSString stringWithFormat:@"Yes"]];
2016 /*B-frame Pyramids fX264optBPyramidPopUp BOOLEAN*/
2017 [fX264optBPyramidPopUp removeAllItems];
2018 [fX264optBPyramidPopUp addItemWithTitle:@"Default (No)"];
2023 [fX264optBPyramidPopUp addItemWithTitle:[NSString stringWithFormat:@"No"]];
2027 [fX264optBPyramidPopUp addItemWithTitle:[NSString stringWithFormat:@"Yes"]];
2031 /* Standardize the option string */
2032 [self X264AdvancedOptionsStandardizeOptString: NULL];
2033 /* Set Current GUI Settings based on newly standardized string */
2034 [self X264AdvancedOptionsSetCurrentSettings: NULL];
2037 - (IBAction) X264AdvancedOptionsStandardizeOptString: (id) sender
2039 /* Set widgets depending on the opt string in field */
2040 NSString * thisOpt; // The separated option such as "bframes=3"
2041 NSString * optName = @""; // The option name such as "bframes"
2042 NSString * optValue = @"";// The option value such as "3"
2043 NSString * changedOptString = @"";
2044 NSArray *currentOptsArray;
2046 /*First, we get an opt string to process */
2047 NSString *currentOptString = [fDisplayX264Options stringValue];
2049 /*verify there is an opt string to process */
2050 NSRange currentOptRange = [currentOptString rangeOfString:@"="];
2051 if (currentOptRange.location != NSNotFound)
2053 /*Put individual options into an array based on the ":" separator for processing, result is "<opt>=<value>"*/
2054 currentOptsArray = [currentOptString componentsSeparatedByString:@":"];
2056 /*iterate through the array and get <opts> and <values*/
2057 //NSEnumerator * enumerator = [currentOptsArray objectEnumerator];
2059 int currentOptsArrayCount = [currentOptsArray count];
2060 for (loopcounter = 0; loopcounter < currentOptsArrayCount; loopcounter++)
2062 thisOpt = [currentOptsArray objectAtIndex:loopcounter];
2064 NSRange splitOptRange = [thisOpt rangeOfString:@"="];
2065 if (splitOptRange.location != NSNotFound)
2067 optName = [thisOpt substringToIndex:splitOptRange.location];
2068 optValue = [thisOpt substringFromIndex:splitOptRange.location + 1];
2070 /* Standardize the names here depending on whats in the string */
2071 optName = [self X264AdvancedOptionsStandardizeOptNames:optName];
2072 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,optValue];
2074 else // No value given so we use a default of "1"
2077 /* Standardize the names here depending on whats in the string */
2078 optName = [self X264AdvancedOptionsStandardizeOptNames:optName];
2079 thisOpt = [NSString stringWithFormat:@"%@=%d",optName,1];
2082 /* Construct New String for opts here */
2083 if ([thisOpt isEqualToString:@""])
2085 changedOptString = [NSString stringWithFormat:@"%@%@",changedOptString,thisOpt];
2089 if ([changedOptString isEqualToString:@""])
2091 changedOptString = [NSString stringWithFormat:@"%@",thisOpt];
2095 changedOptString = [NSString stringWithFormat:@"%@:%@",changedOptString,thisOpt];
2101 /* Change the option string to reflect the new standardized option string */
2102 [fDisplayX264Options setStringValue:[NSString stringWithFormat:changedOptString]];
2105 - (NSString *) X264AdvancedOptionsStandardizeOptNames:(NSString *) cleanOptNameString
2107 if ([cleanOptNameString isEqualToString:@"ref"] || [cleanOptNameString isEqualToString:@"frameref"])
2109 cleanOptNameString = @"ref";
2112 /*No Fast PSkip nofast_pskip*/
2113 if ([cleanOptNameString isEqualToString:@"no-fast-pskip"] || [cleanOptNameString isEqualToString:@"no_fast_pskip"] || [cleanOptNameString isEqualToString:@"nofast_pskip"])
2115 cleanOptNameString = @"no-fast-pskip";
2118 /*No Dict Decimate*/
2119 if ([cleanOptNameString isEqualToString:@"no-dct-decimate"] || [cleanOptNameString isEqualToString:@"no_dct_decimate"] || [cleanOptNameString isEqualToString:@"nodct_decimate"])
2121 cleanOptNameString = @"no-dct-decimate";
2125 if ([cleanOptNameString isEqualToString:@"subme"])
2127 cleanOptNameString = @"subq";
2131 if ([cleanOptNameString isEqualToString:@"me-range"] || [cleanOptNameString isEqualToString:@"me_range"])
2132 cleanOptNameString = @"merange";
2135 if ([cleanOptNameString isEqualToString:@"weight-b"] || [cleanOptNameString isEqualToString:@"weight_b"])
2137 cleanOptNameString = @"weightb";
2141 if ([cleanOptNameString isEqualToString:@"b-rdo"] || [cleanOptNameString isEqualToString:@"b_rdo"])
2143 cleanOptNameString = @"brdo";
2147 if ([cleanOptNameString isEqualToString:@"b_pyramid"])
2149 cleanOptNameString = @"b-pyramid";
2152 return cleanOptNameString;
2155 - (IBAction) X264AdvancedOptionsSetCurrentSettings: (id) sender
2157 /* Set widgets depending on the opt string in field */
2158 NSString * thisOpt; // The separated option such as "bframes=3"
2159 NSString * optName = @""; // The option name such as "bframes"
2160 NSString * optValue = @"";// The option value such as "3"
2161 NSArray *currentOptsArray;
2163 /*First, we get an opt string to process */
2164 //NSString *currentOptString = @"bframes=3:ref=1:subme=5:me=umh:no-fast-pskip=1:no-dct-decimate=1:trellis=2";
2165 NSString *currentOptString = [fDisplayX264Options stringValue];
2167 /*verify there is an opt string to process */
2168 NSRange currentOptRange = [currentOptString rangeOfString:@"="];
2169 if (currentOptRange.location != NSNotFound)
2171 /* lets clean the opt string here to standardize any names*/
2172 /*Put individual options into an array based on the ":" separator for processing, result is "<opt>=<value>"*/
2173 currentOptsArray = [currentOptString componentsSeparatedByString:@":"];
2175 /*iterate through the array and get <opts> and <values*/
2176 //NSEnumerator * enumerator = [currentOptsArray objectEnumerator];
2178 int currentOptsArrayCount = [currentOptsArray count];
2180 /*iterate through the array and get <opts> and <values*/
2181 for (loopcounter = 0; loopcounter < currentOptsArrayCount; loopcounter++)
2183 thisOpt = [currentOptsArray objectAtIndex:loopcounter];
2184 NSRange splitOptRange = [thisOpt rangeOfString:@"="];
2186 if (splitOptRange.location != NSNotFound)
2188 optName = [thisOpt substringToIndex:splitOptRange.location];
2189 optValue = [thisOpt substringFromIndex:splitOptRange.location + 1];
2191 /*Run through the available widgets for x264 opts and set them, as you add widgets,
2192 they need to be added here. This should be moved to its own method probably*/
2194 /*bframes NSPopUpButton*/
2195 if ([optName isEqualToString:@"bframes"])
2197 [fX264optBframesPopUp selectItemAtIndex:[optValue intValue]+1];
2199 /*ref NSPopUpButton*/
2200 if ([optName isEqualToString:@"ref"])
2202 [fX264optRefPopUp selectItemAtIndex:[optValue intValue]+1];
2204 /*No Fast PSkip NSPopUpButton*/
2205 if ([optName isEqualToString:@"no-fast-pskip"])
2207 [fX264optNfpskipPopUp selectItemAtIndex:[optValue intValue]+1];
2209 /*No Dict Decimate NSPopUpButton*/
2210 if ([optName isEqualToString:@"no-dct-decimate"])
2212 [fX264optNodctdcmtPopUp selectItemAtIndex:[optValue intValue]+1];
2214 /*Sub Me NSPopUpButton*/
2215 if ([optName isEqualToString:@"subq"])
2217 [fX264optSubmePopUp selectItemAtIndex:[optValue intValue]+1];
2219 /*Trellis NSPopUpButton*/
2220 if ([optName isEqualToString:@"trellis"])
2222 [fX264optTrellisPopUp selectItemAtIndex:[optValue intValue]+1];
2224 /*Mixed Refs NSPopUpButton*/
2225 if ([optName isEqualToString:@"mixed-refs"])
2227 [fX264optMixedRefsPopUp selectItemAtIndex:[optValue intValue]+1];
2229 /*Motion Estimation NSPopUpButton*/
2230 if ([optName isEqualToString:@"me"])
2232 if ([optValue isEqualToString:@"dia"])
2233 [fX264optMotionEstPopUp selectItemAtIndex:1];
2234 else if ([optValue isEqualToString:@"hex"])
2235 [fX264optMotionEstPopUp selectItemAtIndex:2];
2236 else if ([optValue isEqualToString:@"umh"])
2237 [fX264optMotionEstPopUp selectItemAtIndex:3];
2238 else if ([optValue isEqualToString:@"esa"])
2239 [fX264optMotionEstPopUp selectItemAtIndex:4];
2241 /*ME Range NSPopUpButton*/
2242 if ([optName isEqualToString:@"merange"])
2244 [fX264optMERangePopUp selectItemAtIndex:[optValue intValue]-3];
2246 /*Weighted B-Frames NSPopUpButton*/
2247 if ([optName isEqualToString:@"weightb"])
2249 [fX264optWeightBPopUp selectItemAtIndex:[optValue intValue]+1];
2251 /*BRDO NSPopUpButton*/
2252 if ([optName isEqualToString:@"brdo"])
2254 [fX264optBRDOPopUp selectItemAtIndex:[optValue intValue]+1];
2256 /*B Pyramid NSPopUpButton*/
2257 if ([optName isEqualToString:@"b-pyramid"])
2259 [fX264optBPyramidPopUp selectItemAtIndex:[optValue intValue]+1];
2268 - (IBAction) X264AdvancedOptionsChanged: (id) sender
2270 /*Determine which outlet is being used and set optName to process accordingly */
2271 NSString * optNameToChange = @""; // The option name such as "bframes"
2273 if (sender == fX264optBframesPopUp)
2275 optNameToChange = @"bframes";
2277 if (sender == fX264optRefPopUp)
2279 optNameToChange = @"ref";
2281 if (sender == fX264optNfpskipPopUp)
2283 optNameToChange = @"no-fast-pskip";
2285 if (sender == fX264optNodctdcmtPopUp)
2287 optNameToChange = @"no-dct-decimate";
2289 if (sender == fX264optSubmePopUp)
2291 optNameToChange = @"subq";
2293 if (sender == fX264optTrellisPopUp)
2295 optNameToChange = @"trellis";
2297 if (sender == fX264optMixedRefsPopUp)
2299 optNameToChange = @"mixed-refs";
2301 if (sender == fX264optMotionEstPopUp)
2303 optNameToChange = @"me";
2305 if (sender == fX264optMERangePopUp)
2307 optNameToChange = @"merange";
2309 if (sender == fX264optWeightBPopUp)
2311 optNameToChange = @"weightb";
2313 if (sender == fX264optBRDOPopUp)
2315 optNameToChange = @"brdo";
2317 if (sender == fX264optBPyramidPopUp)
2319 optNameToChange = @"b-pyramid";
2322 /* Set widgets depending on the opt string in field */
2323 NSString * thisOpt; // The separated option such as "bframes=3"
2324 NSString * optName = @""; // The option name such as "bframes"
2325 NSString * optValue = @"";// The option value such as "3"
2326 NSArray *currentOptsArray;
2328 /*First, we get an opt string to process */
2329 //EXAMPLE: NSString *currentOptString = @"bframes=3:ref=1:subme=5:me=umh:no-fast-pskip=1:no-dct-decimate=1:trellis=2";
2330 NSString *currentOptString = [fDisplayX264Options stringValue];
2332 /*verify there is an occurrence of the opt specified by the sender to change */
2333 /*take care of any multi-value opt names here. This is extremely kludgy, but test for functionality
2334 and worry about pretty later */
2336 /*First, we create a pattern to check for ":"optNameToChange"=" to modify the option if the name falls after
2337 the first character of the opt string (hence the ":") */
2338 NSString *checkOptNameToChange = [NSString stringWithFormat:@":%@=",optNameToChange];
2339 NSRange currentOptRange = [currentOptString rangeOfString:checkOptNameToChange];
2340 /*Then we create a pattern to check for "<beginning of line>"optNameToChange"=" to modify the option to
2341 see if the name falls at the beginning of the line, where we would not have the ":" as a pattern to test against*/
2342 NSString *checkOptNameToChangeBeginning = [NSString stringWithFormat:@"%@=",optNameToChange];
2343 NSRange currentOptRangeBeginning = [currentOptString rangeOfString:checkOptNameToChangeBeginning];
2344 if (currentOptRange.location != NSNotFound || currentOptRangeBeginning.location == 0)
2346 /* Create new empty opt string*/
2347 NSString *changedOptString = @"";
2349 /*Put individual options into an array based on the ":" separator for processing, result is "<opt>=<value>"*/
2350 currentOptsArray = [currentOptString componentsSeparatedByString:@":"];
2352 /*iterate through the array and get <opts> and <values*/
2354 int currentOptsArrayCount = [currentOptsArray count];
2355 for (loopcounter = 0; loopcounter < currentOptsArrayCount; loopcounter++)
2357 thisOpt = [currentOptsArray objectAtIndex:loopcounter];
2358 NSRange splitOptRange = [thisOpt rangeOfString:@"="];
2360 if (splitOptRange.location != NSNotFound)
2362 optName = [thisOpt substringToIndex:splitOptRange.location];
2363 optValue = [thisOpt substringFromIndex:splitOptRange.location + 1];
2365 /*Run through the available widgets for x264 opts and set them, as you add widgets,
2366 they need to be added here. This should be moved to its own method probably*/
2368 /*If the optNameToChange is found, appropriately change the value or delete it if
2369 "Unspecified" is set.*/
2370 if ([optName isEqualToString:optNameToChange])
2372 if ([sender indexOfSelectedItem] == 0) // means that "unspecified" is chosen, lets then remove it from the string
2376 else if ([optNameToChange isEqualToString:@"me"])
2378 switch ([sender indexOfSelectedItem])
2381 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"dia"];
2385 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"hex"];
2389 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"umh"];
2393 thisOpt = [NSString stringWithFormat:@"%@=%@",optName,@"esa"];
2400 else if ([optNameToChange isEqualToString:@"merange"])
2402 thisOpt = [NSString stringWithFormat:@"%@=%d",optName,[sender indexOfSelectedItem]+3];
2404 else // we have a valid value to change, so change it
2406 thisOpt = [NSString stringWithFormat:@"%@=%d",optName,[sender indexOfSelectedItem]-1];
2411 /* Construct New String for opts here */
2412 if ([thisOpt isEqualToString:@""])
2414 changedOptString = [NSString stringWithFormat:@"%@%@",changedOptString,thisOpt];
2418 if ([changedOptString isEqualToString:@""])
2420 changedOptString = [NSString stringWithFormat:@"%@",thisOpt];
2424 changedOptString = [NSString stringWithFormat:@"%@:%@",changedOptString,thisOpt];
2429 /* Change the option string to reflect the new mod settings */
2430 [fDisplayX264Options setStringValue:[NSString stringWithFormat:changedOptString]];
2432 else // if none exists, add it to the string
2434 if ([[fDisplayX264Options stringValue] isEqualToString: @""])
2436 if ([optNameToChange isEqualToString:@"me"])
2438 switch ([sender indexOfSelectedItem])
2441 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2442 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"dia"]]];
2446 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2447 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"hex"]]];
2451 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2452 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"umh"]]];
2456 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2457 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"esa"]]];
2464 else if ([optNameToChange isEqualToString:@"merange"])
2466 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2467 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"%d",[sender indexOfSelectedItem]+3]]];
2471 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@=%@",
2472 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"%d",[sender indexOfSelectedItem]-1]]];
2477 if ([optNameToChange isEqualToString:@"me"])
2479 switch ([sender indexOfSelectedItem])
2482 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",
2483 [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2484 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"dia"]]];
2488 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",
2489 [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2490 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"hex"]]];
2494 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",
2495 [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2496 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"umh"]]];
2500 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",
2501 [NSString stringWithFormat:[fDisplayX264Options stringValue]],
2502 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"esa"]]];
2509 else if ([optNameToChange isEqualToString:@"merange"])
2511 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",[NSString stringWithFormat:[fDisplayX264Options stringValue]],
2512 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"%d",[sender indexOfSelectedItem]+3]]];
2516 [fDisplayX264Options setStringValue:[NSString stringWithFormat:@"%@:%@=%@",[NSString stringWithFormat:[fDisplayX264Options stringValue]],
2517 [NSString stringWithFormat:optNameToChange],[NSString stringWithFormat:@"%d",[sender indexOfSelectedItem]-1]]];
2522 /* We now need to reset the opt widgets since we changed some stuff */
2523 [self X264AdvancedOptionsSet:NULL];
2527 /* We use this method to recreate new, updated factory
2529 - (IBAction)AddFactoryPresets:(id)sender
2531 /* First, we delete any existing built in presets */
2532 [self DeleteFactoryPresets: sender];
2533 /* Then, we re-create new built in presets programmatically CreatePSPPreset*/
2534 [UserPresets addObject:[self CreateIpodPreset]];
2535 [UserPresets addObject:[self CreateAppleTVPreset]];
2536 [UserPresets addObject:[self CreatePSThreePreset]];
2537 [UserPresets addObject:[self CreatePSPPreset]];
2540 - (IBAction)DeleteFactoryPresets:(id)sender
2543 NSEnumerator *enumerator = [UserPresets objectEnumerator];
2547 NSMutableArray *tempArray;
2550 tempArray = [NSMutableArray array];
2551 /* we look here to see if the preset is we move on to the next one */
2552 while ( tempObject = [enumerator nextObject] )
2554 /* if the preset is "Factory" then we put it in the array of
2555 presets to delete */
2556 if ([[tempObject objectForKey:@"Type"] intValue] == 0)
2558 [tempArray addObject:tempObject];
2562 [UserPresets removeObjectsInArray:tempArray];
2563 [tableView reloadData];
2568 - (IBAction) ShowAddPresetPanel: (id) sender
2570 /* Deselect the currently selected Preset if there is one*/
2571 [tableView deselectRow:[tableView selectedRow]];
2573 /* Populate the preset picture settings popup here */
2574 [fPresetNewPicSettingsPopUp removeAllItems];
2575 [fPresetNewPicSettingsPopUp addItemWithTitle:@"None"];
2576 [fPresetNewPicSettingsPopUp addItemWithTitle:@"Current"];
2577 [fPresetNewPicSettingsPopUp addItemWithTitle:@"Source Maximum (post source scan)"];
2578 [fPresetNewPicSettingsPopUp selectItemAtIndex: 0];
2580 /* Erase info from the input fields */
2581 [fPresetNewName setStringValue: @""];
2582 /* Show the panel */
2583 [NSApp beginSheet: fAddPresetPanel modalForWindow: fWindow
2584 modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
2585 [NSApp runModalForWindow: fAddPresetPanel];
2586 [NSApp endSheet: fAddPresetPanel];
2587 [fAddPresetPanel orderOut: self];
2591 - (IBAction) CloseAddPresetPanel: (id) sender
2597 - (IBAction)AddUserPreset:(id)sender
2600 /* Here we create a custom user preset */
2601 [UserPresets addObject:[self CreatePreset]];
2602 /* Erase info from the input fields */
2603 [fPresetNewName setStringValue: @""];
2604 /* We stop the modal window for the new preset */
2614 /* We Sort the Presets By Factory or Custom */
2615 NSSortDescriptor * presetTypeDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"Type"
2616 ascending:YES] autorelease];
2617 /* We Sort the Presets Alphabetically by name */
2618 NSSortDescriptor * presetNameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"PresetName"
2619 ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease];
2620 NSArray *sortDescriptors=[NSArray arrayWithObjects:presetTypeDescriptor,presetNameDescriptor,nil];
2621 NSArray *sortedArray=[UserPresets sortedArrayUsingDescriptors:sortDescriptors];
2622 [UserPresets setArray:sortedArray];
2625 /* We Reload the New Table data for presets */
2626 [tableView reloadData];
2627 /* We save all of the preset data here */
2631 - (IBAction)InsertPreset:(id)sender
2633 int index = [tableView selectedRow];
2634 [UserPresets insertObject:[self CreatePreset] atIndex:index];
2635 [tableView reloadData];
2639 - (NSDictionary *)CreatePreset
2641 NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
2642 /* Get the New Preset Name from the field in the AddPresetPanel */
2643 [preset setObject:[fPresetNewName stringValue] forKey:@"PresetName"];
2644 /*Set whether or not this is a user preset or factory 0 is factory, 1 is user*/
2645 [preset setObject:[NSNumber numberWithInt:1] forKey:@"Type"];
2646 /*Set whether or not this is default, at creation set to 0*/
2647 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
2648 /*Get the whether or not to apply pic settings in the AddPresetPanel*/
2649 [preset setObject:[NSNumber numberWithInt:[fPresetNewPicSettingsPopUp indexOfSelectedItem]] forKey:@"UsesPictureSettings"];
2651 [preset setObject:[fDstFormatPopUp titleOfSelectedItem] forKey:@"FileFormat"];
2652 /* Chapter Markers fCreateChapterMarkers*/
2653 [preset setObject:[NSNumber numberWithInt:[fCreateChapterMarkers state]] forKey:@"ChapterMarkers"];
2655 [preset setObject:[fDstCodecsPopUp titleOfSelectedItem] forKey:@"FileCodecs"];
2657 [preset setObject:[fVidEncoderPopUp titleOfSelectedItem] forKey:@"VideoEncoder"];
2658 /* x264 Option String */
2659 [preset setObject:[fDisplayX264Options stringValue] forKey:@"x264Option"];
2661 [preset setObject:[NSNumber numberWithInt:[fVidQualityMatrix selectedRow]] forKey:@"VideoQualityType"];
2662 [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
2663 [preset setObject:[fVidBitrateField stringValue] forKey:@"VideoAvgBitrate"];
2664 [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
2666 /* Video framerate */
2667 [preset setObject:[fVidRatePopUp titleOfSelectedItem] forKey:@"VideoFramerate"];
2669 [preset setObject:[NSNumber numberWithInt:[fVidGrayscaleCheck state]] forKey:@"VideoGrayScale"];
2670 /* 2 Pass Encoding */
2671 [preset setObject:[NSNumber numberWithInt:[fVidTwoPassCheck state]] forKey:@"VideoTwoPass"];
2673 /*Picture Settings*/
2674 hb_job_t * job = fTitle->job;
2675 /* Basic Picture Settings */
2676 /* Use Max Picture settings for whatever the dvd is.*/
2677 [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesMaxPictureSettings"];
2678 [preset setObject:[NSNumber numberWithInt:fTitle->job->width] forKey:@"PictureWidth"];
2679 [preset setObject:[NSNumber numberWithInt:fTitle->job->height] forKey:@"PictureHeight"];
2680 [preset setObject:[NSNumber numberWithInt:fTitle->job->keep_ratio] forKey:@"PictureKeepRatio"];
2681 [preset setObject:[NSNumber numberWithInt:fTitle->job->deinterlace] forKey:@"PictureDeinterlace"];
2682 [preset setObject:[NSNumber numberWithInt:fTitle->job->pixel_ratio] forKey:@"PicturePAR"];
2683 /* Set crop settings here */
2684 /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
2685 [preset setObject:[NSNumber numberWithInt:job->crop[0]] forKey:@"PictureTopCrop"];
2686 [preset setObject:[NSNumber numberWithInt:job->crop[1]] forKey:@"PictureBottomCrop"];
2687 [preset setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"];
2688 [preset setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"];
2691 /* Audio Sample Rate*/
2692 [preset setObject:[fAudRatePopUp titleOfSelectedItem] forKey:@"AudioSampleRate"];
2693 /* Audio Bitrate Rate*/
2694 [preset setObject:[fAudBitratePopUp titleOfSelectedItem] forKey:@"AudioBitRate"];
2696 [preset setObject:[fSubPopUp titleOfSelectedItem] forKey:@"Subtitles"];
2699 [preset autorelease];
2704 - (NSDictionary *)CreateIpodPreset
2706 NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
2707 /* Get the New Preset Name from the field in the AddPresetPanel */
2708 [preset setObject:@"HB-iPod" forKey:@"PresetName"];
2709 /*Set whether or not this is a user preset or factory 0 is factory, 1 is user*/
2710 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
2711 /*Set whether or not this is default, at creation set to 0*/
2712 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
2713 /*Get the whether or not to apply pic settings in the AddPresetPanel*/
2714 [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesPictureSettings"];
2716 [preset setObject:@"MP4 file" forKey:@"FileFormat"];
2717 /* Chapter Markers*/
2718 [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
2720 [preset setObject:@"AVC/H.264 Video / AAC Audio" forKey:@"FileCodecs"];
2722 [preset setObject:@"x264 (h.264 iPod)" forKey:@"VideoEncoder"];
2723 /* x264 Option String */
2724 [preset setObject:@"frameref=1:bframes=0:nofast_pskip:subq=6:partitions=p8x8,p8x4,p4x8,i4x4:qcomp=0:me=umh:nodct_decimate" forKey:@"x264Option"];
2726 [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
2727 [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
2728 [preset setObject:@"1500" forKey:@"VideoAvgBitrate"];
2729 [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
2731 /* Video framerate */
2732 [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
2734 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
2735 /* 2 Pass Encoding */
2736 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
2738 /*Picture Settings*/
2739 //hb_job_t * job = fTitle->job;
2740 /* Basic Picture Settings */
2741 /* Use Max Picture settings for whatever the dvd is.*/
2742 [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesMaxPictureSettings"];
2743 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureWidth"];
2744 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureHeight"];
2745 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureKeepRatio"];
2746 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
2747 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PicturePAR"];
2748 /* Set crop settings here */
2749 /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
2750 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureTopCrop"];
2751 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureBottomCrop"];
2752 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureLeftCrop"];
2753 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureRightCrop"];
2756 /* Audio Sample Rate*/
2757 [preset setObject:@"48" forKey:@"AudioSampleRate"];
2758 /* Audio Bitrate Rate*/
2759 [preset setObject:@"160" forKey:@"AudioBitRate"];
2761 [preset setObject:@"None" forKey:@"Subtitles"];
2764 [preset autorelease];
2769 - (NSDictionary *)CreateAppleTVPreset
2771 NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
2772 /* Get the New Preset Name from the field in the AddPresetPanel */
2773 [preset setObject:@"HB-AppleTV" forKey:@"PresetName"];
2774 /*Set whether or not this is a user preset where 0 is factory, 1 is user*/
2775 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
2776 /*Set whether or not this is default, at creation set to 0*/
2777 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
2778 /*Get the whether or not to apply pic settings in the AddPresetPanel*/
2779 [preset setObject:[NSNumber numberWithInt:2] forKey:@"UsesPictureSettings"];
2781 [preset setObject:@"MP4 file" forKey:@"FileFormat"];
2782 /* Chapter Markers*/
2783 [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
2785 [preset setObject:@"AVC/H.264 Video / AAC Audio" forKey:@"FileCodecs"];
2787 [preset setObject:@"x264 (h.264 Main)" forKey:@"VideoEncoder"];
2788 /* x264 Option String (We can use this to tweak the appleTV output)*/
2789 [preset setObject:@"bframes=3:ref=1:subme=5:me=umh:no-fast-pskip=1:no-dct-decimate=1:trellis=2" forKey:@"x264Option"];
2791 [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
2792 [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
2793 [preset setObject:@"2500" forKey:@"VideoAvgBitrate"];
2794 [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
2796 /* Video framerate */
2797 [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
2799 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
2800 /* 2 Pass Encoding */
2801 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
2803 /*Picture Settings*/
2804 /* For AppleTV we only want to retain UsesMaxPictureSettings
2805 which depend on the source dvd picture settings, so we don't
2806 record the current dvd's picture info since it will vary from
2808 //hb_job_t * job = fTitle->job;
2809 //hb_job_t * job = title->job;
2810 /* Basic Picture Settings */
2811 /* Use Max Picture settings for whatever the dvd is.*/
2812 [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesMaxPictureSettings"];
2813 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureWidth"];
2814 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureHeight"];
2815 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureKeepRatio"];
2816 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
2817 [preset setObject:[NSNumber numberWithInt:1] forKey:@"PicturePAR"];
2818 /* Set crop settings here */
2819 /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
2820 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureTopCrop"];
2821 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureBottomCrop"];
2822 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureLeftCrop"];
2823 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureRightCrop"];
2826 /* Audio Sample Rate*/
2827 [preset setObject:@"48" forKey:@"AudioSampleRate"];
2828 /* Audio Bitrate Rate*/
2829 [preset setObject:@"160" forKey:@"AudioBitRate"];
2831 [preset setObject:@"None" forKey:@"Subtitles"];
2834 [preset autorelease];
2839 - (NSDictionary *)CreatePSThreePreset
2841 NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
2842 /* Get the New Preset Name from the field in the AddPresetPanel */
2843 [preset setObject:@"HB-PS3" forKey:@"PresetName"];
2844 /*Set whether or not this is a user preset where 0 is factory, 1 is user*/
2845 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
2846 /*Set whether or not this is default, at creation set to 0*/
2847 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
2848 /*Get the whether or not to apply pic settings in the AddPresetPanel*/
2849 [preset setObject:[NSNumber numberWithInt:2] forKey:@"UsesPictureSettings"];
2851 [preset setObject:@"MP4 file" forKey:@"FileFormat"];
2852 /* Chapter Markers*/
2853 [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
2855 [preset setObject:@"AVC/H.264 Video / AAC Audio" forKey:@"FileCodecs"];
2857 [preset setObject:@"x264 (h.264 Main)" forKey:@"VideoEncoder"];
2858 /* x264 Option String (We can use this to tweak the appleTV output)*/
2859 [preset setObject:@"level=41" forKey:@"x264Option"];
2861 [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
2862 [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
2863 [preset setObject:@"2500" forKey:@"VideoAvgBitrate"];
2864 [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
2866 /* Video framerate */
2867 [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
2869 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
2870 /* 2 Pass Encoding */
2871 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
2873 /*Picture Settings*/
2874 /* For PS3 we only want to retain UsesMaxPictureSettings
2875 which depend on the source dvd picture settings, so we don't
2876 record the current dvd's picture info since it will vary from
2878 /* Use Max Picture settings for whatever the dvd is.*/
2879 [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesMaxPictureSettings"];
2880 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureWidth"];
2881 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureHeight"];
2882 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureKeepRatio"];
2883 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
2884 [preset setObject:[NSNumber numberWithInt:1] forKey:@"PicturePAR"];
2885 /* Set crop settings here */
2886 /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
2887 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureTopCrop"];
2888 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureBottomCrop"];
2889 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureLeftCrop"];
2890 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureRightCrop"];
2893 /* Audio Sample Rate*/
2894 [preset setObject:@"48" forKey:@"AudioSampleRate"];
2895 /* Audio Bitrate Rate*/
2896 [preset setObject:@"160" forKey:@"AudioBitRate"];
2898 [preset setObject:@"None" forKey:@"Subtitles"];
2901 [preset autorelease];
2905 - (NSDictionary *)CreatePSPPreset
2907 NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
2908 /* Get the New Preset Name from the field in the AddPresetPanel */
2909 [preset setObject:@"HB-PSP" forKey:@"PresetName"];
2910 /*Set whether or not this is a user preset where 0 is factory, 1 is user*/
2911 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
2912 /*Set whether or not this is default, at creation set to 0*/
2913 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
2914 /*Get the whether or not to apply pic settings in the AddPresetPanel*/
2915 [preset setObject:[NSNumber numberWithInt:1] forKey:@"UsesPictureSettings"];
2917 [preset setObject:@"MP4 file" forKey:@"FileFormat"];
2918 /* Chapter Markers*/
2919 [preset setObject:[NSNumber numberWithInt:1] forKey:@"ChapterMarkers"];
2921 [preset setObject:@"MPEG-4 Video / AAC Audio" forKey:@"FileCodecs"];
2923 [preset setObject:@"FFmpeg" forKey:@"VideoEncoder"];
2924 /* x264 Option String (We can use this to tweak the appleTV output)*/
2925 [preset setObject:@"" forKey:@"x264Option"];
2927 [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
2928 [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
2929 [preset setObject:@"1024" forKey:@"VideoAvgBitrate"];
2930 [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
2932 /* Video framerate */
2933 [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
2935 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
2936 /* 2 Pass Encoding */
2937 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
2939 /*Picture Settings*/
2940 /* For PS3 we only want to retain UsesMaxPictureSettings
2941 which depend on the source dvd picture settings, so we don't
2942 record the current dvd's picture info since it will vary from
2944 /* Use Max Picture settings for whatever the dvd is.*/
2945 [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesMaxPictureSettings"];
2946 [preset setObject:@"368" forKey:@"PictureWidth"];
2947 [preset setObject:@"208" forKey:@"PictureHeight"];
2948 [preset setObject:[NSNumber numberWithInt:1] forKey:@"PictureKeepRatio"];
2949 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureDeinterlace"];
2950 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PicturePAR"];
2951 /* Set crop settings here */
2952 /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
2953 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureTopCrop"];
2954 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureBottomCrop"];
2955 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureLeftCrop"];
2956 [preset setObject:[NSNumber numberWithInt:0] forKey:@"PictureRightCrop"];
2959 /* Audio Sample Rate*/
2960 [preset setObject:@"48" forKey:@"AudioSampleRate"];
2961 /* Audio Bitrate Rate*/
2962 [preset setObject:@"128" forKey:@"AudioBitRate"];
2964 [preset setObject:@"None" forKey:@"Subtitles"];
2967 [preset autorelease];
2973 - (IBAction)DeletePreset:(id)sender
2976 NSEnumerator *enumerator;
2978 NSMutableArray *tempArray;
2981 if ( [tableView numberOfSelectedRows] == 0 )
2983 /* Alert user before deleting preset */
2984 /* Comment out for now, tie to user pref eventually */
2987 status = NSRunAlertPanel(@"Warning!", @"Are you sure that you want to delete the selected preset?", @"OK", @"Cancel", nil);
2989 if ( status == NSAlertDefaultReturn ) {
2990 enumerator = [tableView selectedRowEnumerator];
2991 tempArray = [NSMutableArray array];
2993 while ( (index = [enumerator nextObject]) ) {
2994 tempObject = [UserPresets objectAtIndex:[index intValue]];
2995 [tempArray addObject:tempObject];
2998 [UserPresets removeObjectsInArray:tempArray];
2999 [tableView reloadData];
3003 - (IBAction)tableViewSelected:(id)sender
3005 /* Since we cannot disable the presets tableView in terms of clickability
3006 we will use the enabled state of the add presets button to determine whether
3007 or not clicking on a preset will do anything */
3008 if ([fPresetsAdd isEnabled])
3011 /* we get the chosen preset from the UserPresets array */
3012 chosenPreset = [UserPresets objectAtIndex:[sender selectedRow]];
3013 curUserPresetChosenNum = [sender selectedRow];
3014 /* we set the preset display field in main window here */
3015 [fPresetSelectedDisplay setStringValue: [NSString stringWithFormat: @"%@",[chosenPreset valueForKey:@"PresetName"]]];
3017 [fDstFormatPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"FileFormat"]]];
3018 [self FormatPopUpChanged: NULL];
3019 /* Chapter Markers*/
3020 [fCreateChapterMarkers setState:[[chosenPreset objectForKey:@"ChapterMarkers"] intValue]];
3022 [fDstCodecsPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"FileCodecs"]]];
3023 [self CodecsPopUpChanged: NULL];
3025 [fVidEncoderPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoEncoder"]]];
3027 /* We can show the preset options here in the gui if we want to
3028 so we check to see it the user has specified it in the prefs */
3029 [fDisplayX264Options setStringValue: [NSString stringWithFormat:[chosenPreset valueForKey:@"x264Option"]]];
3031 [self X264AdvancedOptionsSet:NULL];
3033 /* Lets run through the following functions to get variables set there */
3034 [self EncoderPopUpChanged: NULL];
3035 [self CalculateBitrate: NULL];
3038 [fVidQualityMatrix selectCellAtRow:[[chosenPreset objectForKey:@"VideoQualityType"] intValue] column:0];
3040 [fVidTargetSizeField setStringValue: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoTargetSize"]]];
3041 [fVidBitrateField setStringValue: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoAvgBitrate"]]];
3043 [fVidQualitySlider setFloatValue: [[chosenPreset valueForKey:@"VideoQualitySlider"] floatValue]];
3044 [self VideoMatrixChanged: NULL];
3046 /* Video framerate */
3047 [fVidRatePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoFramerate"]]];
3050 [fVidGrayscaleCheck setState:[[chosenPreset objectForKey:@"VideoGrayScale"] intValue]];
3052 /* 2 Pass Encoding */
3053 [fVidTwoPassCheck setState:[[chosenPreset objectForKey:@"VideoTwoPass"] intValue]];
3058 /* Audio Sample Rate*/
3059 [fAudRatePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"AudioSampleRate"]]];
3060 /* Audio Bitrate Rate*/
3061 [fAudBitratePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"AudioBitRate"]]];
3063 [fSubPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"Subtitles"]]];
3065 /* Picture Settings */
3066 /* Look to see if we apply these here in objectForKey:@"UsesPictureSettings"] */
3067 if ([[chosenPreset objectForKey:@"UsesPictureSettings"] intValue] > 0)
3069 hb_job_t * job = fTitle->job;
3070 /* Check to see if we should use the max picture setting for the current title*/
3071 if ([[chosenPreset objectForKey:@"UsesPictureSettings"] intValue] == 2 || [[chosenPreset objectForKey:@"UsesMaxPictureSettings"] intValue] == 1)
3073 /* Use Max Picture settings for whatever the dvd is.*/
3074 [self RevertPictureSizeToMax: NULL];
3075 job->keep_ratio = [[chosenPreset objectForKey:@"PictureKeepRatio"] intValue];
3076 if (job->keep_ratio == 1)
3078 hb_fix_aspect( job, HB_KEEP_WIDTH );
3080 job->pixel_ratio = [[chosenPreset objectForKey:@"PicturePAR"] intValue];
3084 job->width = [[chosenPreset objectForKey:@"PictureWidth"] intValue];
3085 job->height = [[chosenPreset objectForKey:@"PictureHeight"] intValue];
3086 job->keep_ratio = [[chosenPreset objectForKey:@"PictureKeepRatio"] intValue];
3087 if (job->keep_ratio == 1)
3089 hb_fix_aspect( job, HB_KEEP_WIDTH );
3091 job->pixel_ratio = [[chosenPreset objectForKey:@"PicturePAR"] intValue];
3092 job->crop[0] = [[chosenPreset objectForKey:@"PictureTopCrop"] intValue];
3093 job->crop[1] = [[chosenPreset objectForKey:@"PictureBottomCrop"] intValue];
3094 job->crop[2] = [[chosenPreset objectForKey:@"PictureLeftCrop"] intValue];
3095 job->crop[3] = [[chosenPreset objectForKey:@"PictureRightCrop"] intValue];
3097 [self CalculatePictureSizing: NULL];
3108 - (int)numberOfRowsInTableView:(NSTableView *)aTableView
3110 return [UserPresets count];
3113 /* we use this to determine display characteristics for
3114 each table cell based on content currently only used to
3115 show the built in presets in a blue font. */
3116 - (void)tableView:(NSTableView *)aTableView
3117 willDisplayCell:(id)aCell
3118 forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
3120 NSDictionary *userPresetDict = [UserPresets objectAtIndex:rowIndex];
3121 if ([[userPresetDict objectForKey:@"Type"] intValue] == 0)
3123 [aCell setTextColor:[NSColor blueColor]];
3127 [aCell setTextColor:[NSColor blackColor]];
3132 - (id)tableView:(NSTableView *)aTableView
3133 objectValueForTableColumn:(NSTableColumn *)aTableColumn
3136 id theRecord, theValue;
3138 theRecord = [UserPresets objectAtIndex:rowIndex];
3139 theValue = [theRecord objectForKey:[aTableColumn identifier]];
3143 // NSTableDataSource method that we implement to edit values directly in the table...
3144 - (void)tableView:(NSTableView *)aTableView
3145 setObjectValue:(id)anObject
3146 forTableColumn:(NSTableColumn *)aTableColumn
3151 theRecord = [UserPresets objectAtIndex:rowIndex];
3152 [theRecord setObject:anObject forKey:@"PresetName"];
3153 /* We Sort the Presets By Factory or Custom */
3154 NSSortDescriptor * presetTypeDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"Type"
3155 ascending:YES] autorelease];
3156 /* We Sort the Presets Alphabetically by name */
3157 NSSortDescriptor * presetNameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"PresetName"
3158 ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease];
3159 NSArray *sortDescriptors=[NSArray arrayWithObjects:presetTypeDescriptor,presetNameDescriptor,nil];
3160 NSArray *sortedArray=[UserPresets sortedArrayUsingDescriptors:sortDescriptors];
3161 [UserPresets setArray:sortedArray];
3162 /* We Reload the New Table data for presets */
3163 [tableView reloadData];
3164 /* We save all of the preset data here */
3171 [UserPresets writeToFile:UserPresetsFile atomically:YES];
3177 - (void) controlTextDidBeginEditing: (NSNotification *) notification
3179 [self CalculateBitrate: NULL];
3182 - (void) controlTextDidEndEditing: (NSNotification *) notification
3184 [self CalculateBitrate: NULL];
3187 - (void) controlTextDidChange: (NSNotification *) notification
3189 [self CalculateBitrate: NULL];
3192 - (IBAction) OpenHomepage: (id) sender
3194 [[NSWorkspace sharedWorkspace] openURL: [NSURL
3195 URLWithString:@"http://handbrake.m0k.org/"]];
3198 - (IBAction) OpenForums: (id) sender
3200 [[NSWorkspace sharedWorkspace] openURL: [NSURL
3201 URLWithString:@"http://handbrake.m0k.org/forum/"]];
3203 - (IBAction) OpenUserGuide: (id) sender
3205 [[NSWorkspace sharedWorkspace] openURL: [NSURL
3206 URLWithString:@"http://handbrake.m0k.org/trac/wiki/HandBrakeGuide"]];