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"
9 #define _(a) NSLocalizedString(a,NULL)
11 static int FormatSettings[3][4] =
12 { { HB_MUX_MP4 | HB_VCODEC_FFMPEG | HB_ACODEC_FAAC,
13 HB_MUX_MP4 | HB_VCODEC_X264 | HB_ACODEC_FAAC,
16 { HB_MUX_AVI | HB_VCODEC_FFMPEG | HB_ACODEC_LAME,
17 HB_MUX_AVI | HB_VCODEC_FFMPEG | HB_ACODEC_AC3,
18 HB_MUX_AVI | HB_VCODEC_X264 | HB_ACODEC_LAME,
19 HB_MUX_AVI | HB_VCODEC_X264 | HB_ACODEC_AC3 },
20 { HB_MUX_OGM | HB_VCODEC_FFMPEG | HB_ACODEC_VORBIS,
21 HB_MUX_OGM | HB_VCODEC_FFMPEG | HB_ACODEC_LAME,
25 /*******************************
26 * HBController implementation *
27 *******************************/
28 @implementation HBController
37 - (void) applicationDidFinishLaunching: (NSNotification *) notification
43 fHandle = hb_init( HB_DEBUG_NONE, [[NSUserDefaults
44 standardUserDefaults] boolForKey:@"CheckForUpdates"] );
46 /* Init others controllers */
47 [fScanController SetHandle: fHandle];
48 [fPictureController SetHandle: fHandle];
49 [fQueueController SetHandle: fHandle];
52 /* Call UpdateUI every 2/10 sec */
53 [[NSRunLoop currentRunLoop] addTimer: [NSTimer
54 scheduledTimerWithTimeInterval: 0.2 target: self
55 selector: @selector( UpdateUI: ) userInfo: NULL repeats: FALSE]
56 forMode: NSModalPanelRunLoopMode];
58 if( ( build = hb_check_update( fHandle, &version ) ) > -1 )
60 /* Update available - tell the user */
62 NSBeginInformationalAlertSheet( _( @"Update is available" ),
63 _( @"Go get it!" ), _( @"Discard" ), NULL, fWindow, self,
64 @selector( UpdateAlertDone:returnCode:contextInfo: ),
65 NULL, NULL, [NSString stringWithFormat:
66 _( @"HandBrake %s (build %d) is now available for download." ),
72 /* Show scan panel ASAP */
73 [self performSelectorOnMainThread: @selector(ShowScanPanel:)
74 withObject: NULL waitUntilDone: NO];
77 - (NSApplicationTerminateReply) applicationShouldTerminate:
80 if( [[fRipButton title] isEqualToString: _( @"Cancel" )] )
83 return NSTerminateCancel;
88 return NSTerminateNow;
95 [self TranslateStrings];
97 /* Init User Presets .plist */
98 /* We declare the default NSFileManager into fileManager */
99 NSFileManager * fileManager = [NSFileManager defaultManager];
100 //presetPrefs = [[NSUserDefaults standardUserDefaults] retain];
101 /* we set the files and support paths here */
102 AppSupportDirectory = @"~/Library/Application Support/HandBrake";
103 AppSupportDirectory = [AppSupportDirectory stringByExpandingTildeInPath];
105 UserPresetsFile = @"~/Library/Application Support/HandBrake/UserPresets.plist";
106 UserPresetsFile = [UserPresetsFile stringByExpandingTildeInPath];
108 x264ProfilesFile = @"~/Library/Application Support/HandBrake/x264Profiles.plist";
109 x264ProfilesFile = [x264ProfilesFile stringByExpandingTildeInPath];
110 /* We check for the app support directory for media fork */
111 if ([fileManager fileExistsAtPath:AppSupportDirectory] == 0)
113 // If it doesnt exist yet, we create it here
114 [fileManager createDirectoryAtPath:AppSupportDirectory attributes:nil];
116 // We check for the presets.plist here
118 if ([fileManager fileExistsAtPath:UserPresetsFile] == 0)
121 [fileManager createFileAtPath:UserPresetsFile contents:nil attributes:nil];
124 // We check for the x264profiles.plist here
126 if ([fileManager fileExistsAtPath:x264ProfilesFile] == 0)
129 [fileManager createFileAtPath:x264ProfilesFile contents:nil attributes:nil];
133 UserPresetsFile = @"~/Library/Application Support/HandBrake/UserPresets.plist";
134 UserPresetsFile = [[UserPresetsFile stringByExpandingTildeInPath]retain];
136 UserPresets = [[NSMutableArray alloc] initWithContentsOfFile:UserPresetsFile];
137 if (nil == UserPresets)
139 UserPresets = [[NSMutableArray alloc] init];
140 [self AddFactoryPresets:NULL];
142 /* Show/Dont Show Presets drawer upon launch based
143 on user preference DefaultPresetsDrawerShow*/
144 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPresetsDrawerShow"] > 0)
146 [fPresetDrawer open];
152 [fDstFormatPopUp removeAllItems];
153 [fDstFormatPopUp addItemWithTitle: _( @"MP4 file" )];
154 [fDstFormatPopUp addItemWithTitle: _( @"AVI file" )];
155 [fDstFormatPopUp addItemWithTitle: _( @"OGM file" )];
156 [fDstFormatPopUp selectItemAtIndex: 0];
158 [self FormatPopUpChanged: NULL];
160 [fDstFile2Field setStringValue: [NSString stringWithFormat:
161 @"%@/Desktop/Movie.mp4", NSHomeDirectory()]];
164 [fVidEncoderPopUp removeAllItems];
165 [fVidEncoderPopUp addItemWithTitle: @"FFmpeg"];
166 [fVidEncoderPopUp addItemWithTitle: @"XviD"];
169 [fVidTargetSizeField setIntValue: 700];
170 [fVidBitrateField setIntValue: 1000];
172 [fVidQualityMatrix selectCell: fVidBitrateCell];
173 [self VideoMatrixChanged: NULL];
175 /* Video framerate */
176 [fVidRatePopUp removeAllItems];
177 [fVidRatePopUp addItemWithTitle: _( @"Same as source" )];
178 for( int i = 0; i < hb_video_rates_count; i++ )
180 [fVidRatePopUp addItemWithTitle:
181 [NSString stringWithCString: hb_video_rates[i].string]];
183 [fVidRatePopUp selectItemAtIndex: 0];
185 /* Picture Settings */
186 [fPicLabelPAROutp setStringValue: @""];
187 [fPicLabelPAROutputX setStringValue: @""];
188 [fPicSettingPARWidth setStringValue: @""];
189 [fPicSettingPARHeight setStringValue: @""];
192 [fAudBitratePopUp removeAllItems];
193 for( int i = 0; i < hb_audio_bitrates_count; i++ )
195 [fAudBitratePopUp addItemWithTitle:
196 [NSString stringWithCString: hb_audio_bitrates[i].string]];
198 [fAudBitratePopUp selectItemAtIndex: hb_audio_bitrates_default];
200 /* Audio samplerate */
201 [fAudRatePopUp removeAllItems];
202 for( int i = 0; i < hb_audio_rates_count; i++ )
204 [fAudRatePopUp addItemWithTitle:
205 [NSString stringWithCString: hb_audio_rates[i].string]];
207 [fAudRatePopUp selectItemAtIndex: hb_audio_rates_default];
210 [fStatusField setStringValue: @""];
213 [fPauseButton setEnabled: NO];
214 [fRipButton setEnabled: NO];
221 - (void) TranslateStrings
223 [fSrcDVD1Field setStringValue: _( @"DVD:" )];
224 [fSrcTitleField setStringValue: _( @"Title:" )];
225 [fSrcChapterField setStringValue: _( @"Chapters:" )];
226 [fSrcChapterToField setStringValue: _( @"to" )];
227 [fSrcDuration1Field setStringValue: _( @"Duration:" )];
229 [fDstFormatField setStringValue: _( @"File format:" )];
230 [fDstCodecsField setStringValue: _( @"Codecs:" )];
231 [fDstFile1Field setStringValue: _( @"File:" )];
232 [fDstBrowseButton setTitle: _( @"Browse" )];
234 [fVidRateField setStringValue: _( @"Framerate (fps):" )];
235 [fVidEncoderField setStringValue: _( @"Encoder:" )];
236 [fVidQualityField setStringValue: _( @"Quality:" )];
239 /***********************************************************************
241 ***********************************************************************
242 * Shows a progression bar on the dock icon, filled according to
243 * 'progress' (0.0 <= progress <= 1.0).
244 * Called with progress < 0.0 or progress > 1.0, restores the original
246 **********************************************************************/
247 - (void) UpdateDockIcon: (float) progress
251 NSBitmapImageRep * bmp;
253 uint32_t black = htonl( 0x000000FF );
254 uint32_t red = htonl( 0xFF0000FF );
255 uint32_t white = htonl( 0xFFFFFFFF );
256 int row_start, row_end;
259 /* Get application original icon */
260 icon = [NSImage imageNamed: @"NSApplicationIcon"];
262 if( progress < 0.0 || progress > 1.0 )
264 [NSApp setApplicationIconImage: icon];
268 /* Get it in a raw bitmap form */
269 tiff = [icon TIFFRepresentationUsingCompression:
270 NSTIFFCompressionNone factor: 1.0];
271 bmp = [NSBitmapImageRep imageRepWithData: tiff];
273 /* Draw the progression bar */
274 /* It's pretty simple (ugly?) now, but I'm no designer */
276 row_start = 3 * (int) [bmp size].height / 4;
277 row_end = 7 * (int) [bmp size].height / 8;
279 for( i = row_start; i < row_start + 2; i++ )
281 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
282 for( j = 0; j < (int) [bmp size].width; j++ )
287 for( i = row_start + 2; i < row_end - 2; i++ )
289 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
292 for( j = 2; j < (int) [bmp size].width - 2; j++ )
294 if( j < 2 + (int) ( ( [bmp size].width - 4.0 ) * progress ) )
306 for( i = row_end - 2; i < row_end; i++ )
308 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
309 for( j = 0; j < (int) [bmp size].width; j++ )
315 /* Now update the dock icon */
316 tiff = [bmp TIFFRepresentationUsingCompression:
317 NSTIFFCompressionNone factor: 1.0];
318 icon = [[NSImage alloc] initWithData: tiff];
319 [NSApp setApplicationIconImage: icon];
323 - (void) UpdateUI: (NSTimer *) timer
327 hb_get_state( fHandle, &s );
334 case HB_STATE_SCANNING:
335 [fScanController UpdateUI: &s];
338 #define p s.param.scandone
339 case HB_STATE_SCANDONE:
343 int indxpri=0; // Used to search the longuest title (default in combobox)
344 int longuestpri=0; // Used to search the longuest title (default in combobox)
346 [fScanController UpdateUI: &s];
348 list = hb_get_titles( fHandle );
350 if( !hb_list_count( list ) )
356 [fSrcTitlePopUp removeAllItems];
357 for( int i = 0; i < hb_list_count( list ); i++ )
359 title = (hb_title_t *) hb_list_item( list, i );
360 /*Set DVD Name at top of window*/
361 [fSrcDVD2Field setStringValue: [NSString
362 stringWithUTF8String: title->name]];
364 /* Use the dvd name in the default output field here
365 May want to add code to remove blank spaces for some dvd names*/
366 /* Check to see if the last destination has been set,use if so, if not, use Desktop */
367 if ([[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"])
369 [fDstFile2Field setStringValue: [NSString stringWithFormat:
370 @"%@/%@.mp4", [[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"],[NSString
371 stringWithUTF8String: title->name]]];
375 [fDstFile2Field setStringValue: [NSString stringWithFormat:
376 @"%@/Desktop/%@.mp4", NSHomeDirectory(),[NSString
377 stringWithUTF8String: title->name]]];
381 if (longuestpri < title->hours*60*60 + title->minutes *60 + title->seconds)
383 longuestpri=title->hours*60*60 + title->minutes *60 + title->seconds;
388 int format = [fDstFormatPopUp indexOfSelectedItem];
394 /*Get Default MP4 File Extension for mpeg4 (.mp4 or .m4v) from prefs*/
395 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultMpegName"] > 0)
413 NSString * string = [fDstFile2Field stringValue];
414 /* Add/replace File Output name to the correct extension*/
415 if( [string characterAtIndex: [string length] - 4] == '.' )
417 [fDstFile2Field setStringValue: [NSString stringWithFormat:
418 @"%@.%s", [string substringToIndex: [string length] - 4],
423 [fDstFile2Field setStringValue: [NSString stringWithFormat:
424 @"%@.%s", string, ext]];
428 [fSrcTitlePopUp addItemWithTitle: [NSString
429 stringWithFormat: @"%d - %02dh%02dm%02ds",
430 title->index, title->hours, title->minutes,
434 // Select the longuest title
435 [fSrcTitlePopUp selectItemAtIndex: indxpri];
439 [self TitlePopUpChanged: NULL];
440 [self EnableUI: YES];
441 [fPauseButton setEnabled: NO];
442 [fRipButton setEnabled: YES];
447 #define p s.param.working
448 case HB_STATE_WORKING:
450 float progress_total;
451 NSMutableString * string;
453 /* Update text field */
454 string = [NSMutableString stringWithFormat:
455 _( @"Encoding: task %d of %d, %.2f %%" ),
456 p.job_cur, p.job_count, 100.0 * p.progress];
459 [string appendFormat:
460 _( @" (%.2f fps, avg %.2f fps, ETA %02dh%02dm%02ds)" ),
461 p.rate_cur, p.rate_avg, p.hours, p.minutes, p.seconds];
463 [fStatusField setStringValue: string];
466 progress_total = ( p.progress + p.job_cur - 1 ) / p.job_count;
467 [fRipIndicator setIndeterminate: NO];
468 [fRipIndicator setDoubleValue: 100.0 * progress_total];
470 /* Update dock icon */
471 [self UpdateDockIcon: progress_total];
473 [fPauseButton setEnabled: YES];
474 [fPauseButton setTitle: _( @"Pause" )];
475 [fRipButton setEnabled: YES];
476 [fRipButton setTitle: _( @"Cancel" )];
481 #define p s.param.muxing
482 case HB_STATE_MUXING:
484 NSMutableString * string;
486 /* Update text field */
487 string = [NSMutableString stringWithFormat:
489 [fStatusField setStringValue: string];
492 [fRipIndicator setIndeterminate: YES];
493 [fRipIndicator startAnimation: nil];
495 /* Update dock icon */
496 [self UpdateDockIcon: 1.0];
498 [fPauseButton setEnabled: YES];
499 [fPauseButton setTitle: _( @"Pause" )];
500 [fRipButton setEnabled: YES];
501 [fRipButton setTitle: _( @"Cancel" )];
506 case HB_STATE_PAUSED:
507 [fStatusField setStringValue: _( @"Paused" )];
508 [fPauseButton setEnabled: YES];
509 [fPauseButton setTitle: _( @"Resume" )];
510 [fRipButton setEnabled: YES];
511 [fRipButton setTitle: _( @"Cancel" )];
514 case HB_STATE_WORKDONE:
516 [self EnableUI: YES];
517 [fStatusField setStringValue: _( @"Done." )];
518 [fRipIndicator setIndeterminate: NO];
519 [fRipIndicator setDoubleValue: 0.0];
520 [fRipButton setTitle: _( @"Rip" )];
522 /* Restore dock icon */
523 [self UpdateDockIcon: -1.0];
525 [fPauseButton setEnabled: NO];
526 [fPauseButton setTitle: _( @"Pause" )];
527 [fRipButton setEnabled: YES];
528 [fRipButton setTitle: _( @"Rip" )];
532 while( ( job = hb_job( fHandle, 0 ) ) )
534 hb_rem( fHandle, job );
540 /* FIXME: we should only do that when necessary */
541 if( [fQueueCheck state] == NSOnState )
543 int count = hb_count( fHandle );
546 [fQueueCheck setTitle: [NSString stringWithFormat:
547 @"Enable queue (%d task%s in queue)",
548 count, ( count > 1 ) ? "s" : ""]];
552 [fQueueCheck setTitle: @"Enable queue (no task in queue)"];
556 [[NSRunLoop currentRunLoop] addTimer: [NSTimer
557 scheduledTimerWithTimeInterval: 0.2 target: self
558 selector: @selector( UpdateUI: ) userInfo: NULL repeats: FALSE]
559 forMode: NSModalPanelRunLoopMode];
562 - (void) EnableUI: (bool) b
564 NSControl * controls[] =
565 { fSrcDVD1Field, fSrcDVD2Field, fSrcTitleField, fSrcTitlePopUp,
566 fSrcChapterField, fSrcChapterStartPopUp, fSrcChapterToField,
567 fSrcChapterEndPopUp, fSrcDuration1Field, fSrcDuration2Field,
568 fDstFormatField, fDstFormatPopUp, fDstCodecsField,
569 fDstCodecsPopUp, fDstFile1Field, fDstFile2Field,
570 fDstBrowseButton, fVidRateField, fVidRatePopUp,
571 fVidEncoderField, fVidEncoderPopUp, fVidQualityField,
572 fVidQualityMatrix, fVidGrayscaleCheck, fSubField, fSubPopUp,
573 fAudLang1Field, fAudLang1PopUp, fAudLang2Field, fAudLang2PopUp,
574 fAudRateField, fAudRatePopUp, fAudBitrateField,
575 fAudBitratePopUp, fPictureButton, fQueueCheck,
576 fPicSrcWidth,fPicSrcHeight,fPicSettingWidth,fPicSettingHeight,
577 fPicSettingARkeep,fPicSettingDeinterlace,fPicSettingARkeepDsply,
578 fPicSettingDeinterlaceDsply,fPicLabelSettings,fPicLabelSrc,fPicLabelOutp,
579 fPicLabelAr,fPicLabelDeinter,fPicLabelSrcX,fPicLabelOutputX,
580 fPicLabelPAROutp,fPicLabelPAROutputX,fPicSettingPARWidth,fPicSettingPARHeight,
581 fPicSettingPARDsply,fPicLabelAnamorphic,tableView,fPresetsAdd,fPresetsDelete,
582 fCreateChapterMarkers};
585 i < sizeof( controls ) / sizeof( NSControl * ); i++ )
587 if( [[controls[i] className] isEqualToString: @"NSTextField"] )
589 NSTextField * tf = (NSTextField *) controls[i];
590 if( ![tf isBezeled] )
592 [tf setTextColor: b ? [NSColor controlTextColor] :
593 [NSColor disabledControlTextColor]];
597 [controls[i] setEnabled: b];
602 /* if we're enabling the interface, check if we should / should't offer 6-channel AAC extraction */
603 [self Check6ChannelAACExtraction: NULL];
606 /* if we're disabling the interface, turn it off */
607 [fAudLang1SurroundCheck setEnabled: NO];
608 [tableView setEnabled: NO];
612 [self VideoMatrixChanged: NULL];
615 - (IBAction) ShowScanPanel: (id) sender
617 [fScanController Show];
620 - (BOOL) windowShouldClose: (id) sender
622 /* Stop the application when the user closes the window */
623 [NSApp terminate: self];
627 - (IBAction) VideoMatrixChanged: (id) sender;
629 bool target, bitrate, quality;
631 target = bitrate = quality = false;
632 if( [fVidQualityMatrix isEnabled] )
634 switch( [fVidQualityMatrix selectedRow] )
647 [fVidTargetSizeField setEnabled: target];
648 [fVidBitrateField setEnabled: bitrate];
649 [fVidQualitySlider setEnabled: quality];
650 [fVidTwoPassCheck setEnabled: !quality &&
651 [fVidQualityMatrix isEnabled]];
654 [fVidTwoPassCheck setState: NSOffState];
657 [self QualitySliderChanged: sender];
658 [self CalculateBitrate: sender];
661 - (IBAction) QualitySliderChanged: (id) sender
663 [fVidConstantCell setTitle: [NSString stringWithFormat:
664 _( @"Constant quality: %.0f %%" ), 100.0 *
665 [fVidQualitySlider floatValue]]];
668 - (IBAction) BrowseFile: (id) sender
670 /* Open a panel to let the user choose and update the text field */
671 NSSavePanel * panel = [NSSavePanel savePanel];
672 /* We get the current file name and path from the destination field here */
673 [panel beginSheetForDirectory: [[fDstFile2Field stringValue] stringByDeletingLastPathComponent] file: [[fDstFile2Field stringValue] lastPathComponent]
674 modalForWindow: fWindow modalDelegate: self
675 didEndSelector: @selector( BrowseFileDone:returnCode:contextInfo: )
679 - (void) BrowseFileDone: (NSSavePanel *) sheet
680 returnCode: (int) returnCode contextInfo: (void *) contextInfo
682 if( returnCode == NSOKButton )
684 [fDstFile2Field setStringValue: [sheet filename]];
685 [self FormatPopUpChanged: NULL];
689 - (IBAction) ShowPicturePanel: (id) sender
691 hb_list_t * list = hb_get_titles( fHandle );
692 hb_title_t * title = (hb_title_t *) hb_list_item( list,
693 [fSrcTitlePopUp indexOfSelectedItem] );
695 /* Resize the panel */
697 newSize.width = 246 + title->width;
698 newSize.height = 80 + title->height;
699 [fPicturePanel setContentSize: newSize];
701 [fPictureController SetTitle: title];
703 [NSApp beginSheet: fPicturePanel modalForWindow: fWindow
704 modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
705 [NSApp runModalForWindow: fPicturePanel];
706 [NSApp endSheet: fPicturePanel];
707 [fPicturePanel orderOut: self];
708 [self CalculatePictureSizing: sender];
711 - (IBAction) ShowQueuePanel: (id) sender
713 /* Update the OutlineView */
714 [fQueueController Update: sender];
717 [NSApp beginSheet: fQueuePanel modalForWindow: fWindow
718 modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
719 [NSApp runModalForWindow: fQueuePanel];
720 [NSApp endSheet: fQueuePanel];
721 [fQueuePanel orderOut: self];
726 hb_list_t * list = hb_get_titles( fHandle );
727 hb_title_t * title = (hb_title_t *) hb_list_item( list,
728 [fSrcTitlePopUp indexOfSelectedItem] );
729 hb_job_t * job = title->job;
731 /* Chapter selection */
732 job->chapter_start = [fSrcChapterStartPopUp indexOfSelectedItem] + 1;
733 job->chapter_end = [fSrcChapterEndPopUp indexOfSelectedItem] + 1;
737 /* Format and codecs */
738 int format = [fDstFormatPopUp indexOfSelectedItem];
739 int codecs = [fDstCodecsPopUp indexOfSelectedItem];
740 job->mux = FormatSettings[format][codecs] & HB_MUX_MASK;
741 job->vcodec = FormatSettings[format][codecs] & HB_VCODEC_MASK;
742 job->acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
743 /* We set the chapter marker extraction here based on the format being
744 mpeg4 and the checkbox being checked */
745 if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [fCreateChapterMarkers state] == NSOnState)
747 job->chapter_markers = 1;
749 if( ( job->vcodec & HB_VCODEC_FFMPEG ) &&
750 [fVidEncoderPopUp indexOfSelectedItem] > 0 )
752 job->vcodec = HB_VCODEC_XVID;
754 if( job->vcodec & HB_VCODEC_X264 )
756 if ([fVidEncoderPopUp indexOfSelectedItem] > 0 )
758 /* Just use new Baseline Level 3.0
759 Lets Deprecate Baseline Level 1.3*/
760 job->h264_level = 30;
761 job->mux = HB_MUX_IPOD;
762 /* move sanity check for iPod Encoding here */
763 job->pixel_ratio = 0 ;
767 /* Set this flag to switch from Constant Quantizer(default) to Constant Rate Factor Thanks jbrjake
768 Currently only used with Constant Quality setting*/
769 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultCrf"] > 0 && [fVidQualityMatrix selectedRow] == 2)
771 /* Can only be used with svn rev >= 89 */
775 /* Sends x264 options to the core library*/
776 job->x264opts = [[[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"] UTF8String];
779 job->h264_13 = [fVidEncoderPopUp indexOfSelectedItem];
783 if( [fVidRatePopUp indexOfSelectedItem] > 0 )
785 job->vrate = 27000000;
786 job->vrate_base = hb_video_rates[[fVidRatePopUp
787 indexOfSelectedItem]-1].rate;
791 job->vrate = title->rate;
792 job->vrate_base = title->rate_base;
795 switch( [fVidQualityMatrix selectedRow] )
799 Bitrate should already have been calculated and displayed
800 in fVidBitrateField, so let's just use it */
802 job->vquality = -1.0;
803 job->vbitrate = [fVidBitrateField intValue];
806 job->vquality = [fVidQualitySlider floatValue];
811 job->grayscale = ( [fVidGrayscaleCheck state] == NSOnState );
815 /* Subtitle settings */
816 job->subtitle = [fSubPopUp indexOfSelectedItem] - 1;
819 job->audios[0] = [fAudLang1PopUp indexOfSelectedItem] - 1;
820 job->audios[1] = [fAudLang2PopUp indexOfSelectedItem] - 1;
824 job->arate = hb_audio_rates[[fAudRatePopUp
825 indexOfSelectedItem]].rate;
826 job->abitrate = hb_audio_bitrates[[fAudBitratePopUp
827 indexOfSelectedItem]].rate;
828 /* have we selected that 5.1 should be extracted as AAC? */
829 if (job->acodec == HB_ACODEC_FAAC && [fAudLang1SurroundCheck isEnabled] && [fAudLang1SurroundCheck state] == NSOnState) {
837 - (IBAction) EnableQueue: (id) sender
839 bool e = ( [fQueueCheck state] == NSOnState );
840 [fQueueAddButton setHidden: !e];
841 [fQueueShowButton setHidden: !e];
842 [fRipButton setTitle: e ? @"Start" : @"Rip"];
845 - (IBAction) AddToQueue: (id) sender
847 /* We get the destination directory from the destingation field here */
848 NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent];
849 /* We check for a valid destination here */
850 if ([[NSFileManager defaultManager] fileExistsAtPath:destinationDirectory] == 0)
852 NSRunAlertPanel(@"Warning!", @"This is not a valid destination directory!", @"OK", nil, nil);
857 hb_list_t * list = hb_get_titles( fHandle );
858 hb_title_t * title = (hb_title_t *) hb_list_item( list,
859 [fSrcTitlePopUp indexOfSelectedItem] );
860 hb_job_t * job = title->job;
864 /* Destination file */
865 job->file = [[fDstFile2Field stringValue] UTF8String];
867 if( [fVidTwoPassCheck state] == NSOnState )
870 hb_add( fHandle, job );
872 job->x264opts = [[[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"] UTF8String];
873 hb_add( fHandle, job );
878 hb_add( fHandle, job );
881 [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"];
885 - (IBAction) Rip: (id) sender
889 /* Rip or Cancel ? */
890 if( [[fRipButton title] isEqualToString: _( @"Cancel" )] )
892 [self Cancel: sender];
896 if( [fQueueCheck state] == NSOffState )
899 [self AddToQueue: sender];
905 /* We check for duplicate name here */
906 if( [[NSFileManager defaultManager] fileExistsAtPath:
907 [fDstFile2Field stringValue]] )
909 NSBeginCriticalAlertSheet( _( @"File already exists" ),
910 _( @"Cancel" ), _( @"Overwrite" ), NULL, fWindow, self,
911 @selector( OverwriteAlertDone:returnCode:contextInfo: ),
912 NULL, NULL, [NSString stringWithFormat:
913 _( @"Do you want to overwrite %@?" ),
914 [fDstFile2Field stringValue]] );
917 /* We get the destination directory from the destingation field here */
918 NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent];
919 /* We check for a valid destination here */
920 if ([[NSFileManager defaultManager] fileExistsAtPath:destinationDirectory] == 0)
922 NSRunAlertPanel(@"Warning!", @"This is not a valid destination directory!", @"OK", nil, nil);
926 [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"];
934 - (void) OverwriteAlertDone: (NSWindow *) sheet
935 returnCode: (int) returnCode contextInfo: (void *) contextInfo
937 if( returnCode == NSAlertAlternateReturn )
943 - (void) UpdateAlertDone: (NSWindow *) sheet
944 returnCode: (int) returnCode contextInfo: (void *) contextInfo
946 if( returnCode == NSAlertAlternateReturn )
948 /* Show scan panel */
949 [self performSelectorOnMainThread: @selector(ShowScanPanel:)
950 withObject: NULL waitUntilDone: NO];
954 /* Go to HandBrake homepage and exit */
955 [self OpenHomepage: NULL];
956 [NSApp terminate: self];
961 /* Let libhb do the job */
964 /* Disable interface */
966 [fPauseButton setEnabled: NO];
967 [fRipButton setEnabled: NO];
970 - (IBAction) Cancel: (id) sender
972 NSBeginCriticalAlertSheet( _( @"Cancel - Are you sure?" ),
973 _( @"Keep working" ), _( @"Cancel encoding" ), NULL, fWindow, self,
974 @selector( _Cancel:returnCode:contextInfo: ), NULL, NULL,
975 _( @"Encoding won't be recoverable." ) );
978 - (void) _Cancel: (NSWindow *) sheet
979 returnCode: (int) returnCode contextInfo: (void *) contextInfo
981 if( returnCode == NSAlertAlternateReturn )
984 [fPauseButton setEnabled: NO];
985 [fRipButton setEnabled: NO];
989 - (IBAction) Pause: (id) sender
991 [fPauseButton setEnabled: NO];
992 [fRipButton setEnabled: NO];
994 if( [[fPauseButton title] isEqualToString: _( @"Resume" )] )
996 hb_resume( fHandle );
1000 hb_pause( fHandle );
1004 - (IBAction) TitlePopUpChanged: (id) sender
1006 hb_list_t * list = hb_get_titles( fHandle );
1007 hb_title_t * title = (hb_title_t*)
1008 hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
1009 /* If Auto Naming is on. We create an output filename of dvd name - title number */
1010 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultAutoNaming"] > 0)
1012 [fDstFile2Field setStringValue: [NSString stringWithFormat:
1013 @"%@/%@-%d.%@", [[fDstFile2Field stringValue] stringByDeletingLastPathComponent],
1014 [NSString stringWithUTF8String: title->name],
1015 [fSrcTitlePopUp indexOfSelectedItem] + 1,
1016 [[fDstFile2Field stringValue] pathExtension]]];
1019 /* Update chapter popups */
1020 [fSrcChapterStartPopUp removeAllItems];
1021 [fSrcChapterEndPopUp removeAllItems];
1022 for( int i = 0; i < hb_list_count( title->list_chapter ); i++ )
1024 [fSrcChapterStartPopUp addItemWithTitle: [NSString
1025 stringWithFormat: @"%d", i + 1]];
1026 [fSrcChapterEndPopUp addItemWithTitle: [NSString
1027 stringWithFormat: @"%d", i + 1]];
1029 [fSrcChapterStartPopUp selectItemAtIndex: 0];
1030 [fSrcChapterEndPopUp selectItemAtIndex:
1031 hb_list_count( title->list_chapter ) - 1];
1032 [self ChapterPopUpChanged: NULL];
1034 /* Start Get and set the initial pic size for display */
1035 hb_job_t * job = title->job;
1037 /*Set Source Size Fields Here */
1038 [fPicSrcWidth setStringValue: [NSString stringWithFormat:
1039 @"%d", fTitle->width]];
1040 [fPicSrcHeight setStringValue: [NSString stringWithFormat:
1041 @"%d", fTitle->height]];
1042 /* Turn Deinterlace on/off depending on the preference */
1043 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultDeinterlaceOn"] > 0)
1045 job->deinterlace = 1;
1049 job->deinterlace = 0;
1052 /* Pixel Ratio Setting */
1053 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"PixelRatio"])
1056 job->pixel_ratio = 1 ;
1060 job->pixel_ratio = 0 ;
1062 /* Run Through EncoderPopUpChanged to see if there
1063 needs to be any pic value modifications based on encoder settings */
1064 [self EncoderPopUpChanged: NULL];
1065 /* END Get and set the initial pic size for display */
1068 /* Update subtitle popups */
1069 hb_subtitle_t * subtitle;
1070 [fSubPopUp removeAllItems];
1071 [fSubPopUp addItemWithTitle: @"None"];
1072 for( int i = 0; i < hb_list_count( title->list_subtitle ); i++ )
1074 subtitle = (hb_subtitle_t *) hb_list_item( title->list_subtitle, i );
1076 /* We cannot use NSPopUpButton's addItemWithTitle because
1077 it checks for duplicate entries */
1078 [[fSubPopUp menu] addItemWithTitle: [NSString stringWithCString:
1079 subtitle->lang] action: NULL keyEquivalent: @""];
1081 [fSubPopUp selectItemAtIndex: 0];
1086 // PRI CHANGES 02/12/06
1087 NSString * audiotmppri;
1088 NSString * audiosearchpri=[[NSUserDefaults standardUserDefaults] stringForKey:@"DefaultLanguage"];
1090 // End of pri changes 02/12/06
1091 [fAudLang1PopUp removeAllItems];
1092 [fAudLang2PopUp removeAllItems];
1093 [fAudLang1PopUp addItemWithTitle: _( @"None" )];
1094 [fAudLang2PopUp addItemWithTitle: _( @"None" )];
1095 for( int i = 0; i < hb_list_count( title->list_audio ); i++ )
1097 audio = (hb_audio_t *) hb_list_item( title->list_audio, i );
1098 // PRI CHANGES 02/12/06
1099 if (audiosearchpri!= NULL)
1101 audiotmppri=(NSString *) [NSString stringWithCString: audio->lang];
1102 // Try to find the desired default language
1103 if ([audiotmppri hasPrefix:audiosearchpri] && indxpri==0)
1108 // End of pri changes 02/12/06
1110 [[fAudLang1PopUp menu] addItemWithTitle:
1111 [NSString stringWithCString: audio->lang]
1112 action: NULL keyEquivalent: @""];
1114 [[fAudLang2PopUp menu] addItemWithTitle:
1115 [NSString stringWithCString: audio->lang]
1116 action: NULL keyEquivalent: @""];
1119 // PRI CHANGES 02/12/06
1120 if (indxpri==0) { indxpri=1; }
1121 [fAudLang1PopUp selectItemAtIndex: indxpri];
1122 // End of pri changes 02/12/06
1123 [fAudLang2PopUp selectItemAtIndex: 0];
1127 /* changing the title may have changed the audio channels on offer, so */
1128 /* check if this change means we should / should't offer 6-channel AAC extraction */
1129 [self Check6ChannelAACExtraction: sender];
1135 - (IBAction) ChapterPopUpChanged: (id) sender
1137 hb_list_t * list = hb_get_titles( fHandle );
1138 hb_title_t * title = (hb_title_t *)
1139 hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
1141 hb_chapter_t * chapter;
1142 int64_t duration = 0;
1143 for( int i = [fSrcChapterStartPopUp indexOfSelectedItem];
1144 i <= [fSrcChapterEndPopUp indexOfSelectedItem]; i++ )
1146 chapter = (hb_chapter_t *) hb_list_item( title->list_chapter, i );
1147 duration += chapter->duration;
1150 duration /= 90000; /* pts -> seconds */
1151 [fSrcDuration2Field setStringValue: [NSString stringWithFormat:
1152 @"%02lld:%02lld:%02lld", duration / 3600, ( duration / 60 ) % 60,
1155 [self CalculateBitrate: sender];
1158 - (IBAction) FormatPopUpChanged: (id) sender
1160 NSString * string = [fDstFile2Field stringValue];
1161 int format = [fDstFormatPopUp indexOfSelectedItem];
1164 /* Update the codecs popup */
1165 [fDstCodecsPopUp removeAllItems];
1169 /*Get Default MP4 File Extension*/
1170 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultMpegName"] > 0)
1178 [fDstCodecsPopUp addItemWithTitle:
1179 _( @"MPEG-4 Video / AAC Audio" )];
1180 [fDstCodecsPopUp addItemWithTitle:
1181 _( @"AVC/H.264 Video / AAC Audio" )];
1182 /* We enable the create chapters checkbox here since we are .mp4 */
1183 [fCreateChapterMarkers setEnabled: YES];
1184 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultChapterMarkers"] > 0)
1186 [fCreateChapterMarkers setState: NSOnState];
1191 [fDstCodecsPopUp addItemWithTitle:
1192 _( @"MPEG-4 Video / MP3 Audio" )];
1193 [fDstCodecsPopUp addItemWithTitle:
1194 _( @"MPEG-4 Video / AC-3 Audio" )];
1195 [fDstCodecsPopUp addItemWithTitle:
1196 _( @"AVC/H.264 Video / MP3 Audio" )];
1197 [fDstCodecsPopUp addItemWithTitle:
1198 _( @"AVC/H.264 Video / AC-3 Audio" )];
1199 /* We disable the create chapters checkbox here since we are NOT .mp4
1200 and make sure it is unchecked*/
1201 [fCreateChapterMarkers setEnabled: NO];
1202 [fCreateChapterMarkers setState: NSOffState];
1206 [fDstCodecsPopUp addItemWithTitle:
1207 _( @"MPEG-4 Video / Vorbis Audio" )];
1208 [fDstCodecsPopUp addItemWithTitle:
1209 _( @"MPEG-4 Video / MP3 Audio" )];
1210 /* We disable the create chapters checkbox here since we are NOT .mp4
1211 and make sure it is unchecked*/
1212 [fCreateChapterMarkers setEnabled: NO];
1213 [fCreateChapterMarkers setState: NSOffState];
1216 [self CodecsPopUpChanged: NULL];
1218 /* Add/replace to the correct extension */
1219 if( [string characterAtIndex: [string length] - 4] == '.' )
1221 [fDstFile2Field setStringValue: [NSString stringWithFormat:
1222 @"%@.%s", [string substringToIndex: [string length] - 4],
1227 [fDstFile2Field setStringValue: [NSString stringWithFormat:
1228 @"%@.%s", string, ext]];
1231 /* changing the codecs on offer may mean that we are/aren't now offering AAC, so */
1232 /* check if this change means we should / should't offer 6-channel AAC extraction */
1233 [self Check6ChannelAACExtraction: sender];
1237 - (IBAction) CodecsPopUpChanged: (id) sender
1239 int format = [fDstFormatPopUp indexOfSelectedItem];
1240 int codecs = [fDstCodecsPopUp indexOfSelectedItem];
1242 /* Update the encoder popup */
1243 if( ( FormatSettings[format][codecs] & HB_VCODEC_X264 ) )
1245 /* MPEG-4 -> H.264 */
1246 [fVidEncoderPopUp removeAllItems];
1247 [fVidEncoderPopUp addItemWithTitle: @"x264 (h.264 Main)"];
1248 [fVidEncoderPopUp addItemWithTitle: @"x264 (h.264 iPod)"];
1252 else if( ( FormatSettings[format][codecs] & HB_VCODEC_FFMPEG ) )
1254 /* H.264 -> MPEG-4 */
1255 [fVidEncoderPopUp removeAllItems];
1256 [fVidEncoderPopUp addItemWithTitle: @"FFmpeg"];
1257 [fVidEncoderPopUp addItemWithTitle: @"XviD"];
1258 [fVidEncoderPopUp selectItemAtIndex: 0];
1261 if( FormatSettings[format][codecs] & HB_ACODEC_AC3 )
1263 /* AC-3 pass-through: disable samplerate and bitrate */
1264 [fAudRatePopUp setEnabled: NO];
1265 [fAudBitratePopUp setEnabled: NO];
1269 [fAudRatePopUp setEnabled: YES];
1270 [fAudBitratePopUp setEnabled: YES];
1273 /* check if this change means we should / should't offer 6-channel AAC extraction */
1274 [self Check6ChannelAACExtraction: sender];
1276 [self CalculateBitrate: sender];
1280 - (IBAction) EncoderPopUpChanged: (id) sender
1283 /* Check to see if we need to modify the job pic values based on x264 (iPod) encoder selection */
1284 if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [fDstCodecsPopUp indexOfSelectedItem] == 1 && [fVidEncoderPopUp indexOfSelectedItem] == 1)
1286 hb_job_t * job = fTitle->job;
1287 job->pixel_ratio = 0 ;
1289 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPicSizeAutoiPod"] > 0)
1292 if (fTitle->job->width > 640)
1294 fTitle->job->width = 640;
1296 fTitle->job->keep_ratio = 1;
1297 hb_fix_aspect( job, HB_KEEP_WIDTH );
1301 /* uncheck the "export 5.1 as 6-channel AAC" checkbox if it is checked */
1302 [fAudLang1SurroundCheck setState: NSOffState];
1306 [self CalculatePictureSizing: sender];
1310 - (IBAction) Check6ChannelAACExtraction: (id) sender
1313 /* make sure we have a selected title before continuing */
1314 if (fTitle == NULL) return;
1316 /* get the current title's job into a convenience variable */
1317 hb_job_t * job = fTitle->job;
1319 /* get the current audio tracks */
1320 /* this is done in PrepareJob too, but we want them here to check against below */
1321 job->audios[0] = [fAudLang1PopUp indexOfSelectedItem] - 1;
1322 job->audios[1] = [fAudLang2PopUp indexOfSelectedItem] - 1;
1323 job->audios[2] = -1;
1325 /* now, let's check if any selected audio track has 5.1 sound */
1327 bool foundfiveoneaudio = false;
1329 /* find out what the currently-selected audio codec is */
1330 int format = [fDstFormatPopUp indexOfSelectedItem];
1331 int codecs = [fDstCodecsPopUp indexOfSelectedItem];
1332 int acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
1334 /* we only offer the option to extract 5.1 to 6-channel if the selected audio codec is AAC */
1335 if (acodec == HB_ACODEC_FAAC) {
1337 bool doneaudios = false;
1340 while (!doneaudios) {
1342 if (job->audios[thisaudio] == -1) {
1345 audio = (hb_audio_t *) hb_list_item( fTitle->list_audio, job->audios[thisaudio] );
1346 if (audio != NULL) {
1347 if (audio->channels == 5 && audio->lfechannels == 1) {
1348 foundfiveoneaudio = true;
1349 doneaudios = true; /* as it doesn't matter if we find any more! */
1358 /* If we are extracting to AAC, and any of our soundtracks were 5.1, then enable the checkbox */
1359 if (foundfiveoneaudio) {
1360 [fAudLang1SurroundCheck setEnabled: YES];
1361 /* Check default surround sound pref and if it is YES, lets also check the checkbox */
1362 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultSurroundSound"] > 0)
1364 [fAudLang1SurroundCheck setState: NSOnState];
1367 [fAudLang1SurroundCheck setEnabled: NO];
1368 /* as well as disabling the checkbox, let's uncheck it if it is checked */
1369 [fAudLang1SurroundCheck setState: NSOffState];
1376 - (IBAction) LanguagePopUpChanged: (id) sender
1379 /* selecting a different language may mean we have a different number of channels, so */
1380 /* check if this change means we should / should't offer 6-channel AAC extraction */
1381 [self Check6ChannelAACExtraction: sender];
1383 /* see if the new language setting will change the bitrate we need */
1384 [self CalculateBitrate: sender];
1389 /* Get and Display Current Pic Settings in main window */
1390 - (IBAction) CalculatePictureSizing: (id) sender
1393 hb_job_t * job = fTitle->job;
1395 [fPicSettingWidth setStringValue: [NSString stringWithFormat:
1396 @"%d", fTitle->job->width]];
1397 [fPicSettingHeight setStringValue: [NSString stringWithFormat:
1398 @"%d", fTitle->job->height]];
1399 [fPicSettingARkeep setStringValue: [NSString stringWithFormat:
1400 @"%d", fTitle->job->keep_ratio]];
1401 [fPicSettingDeinterlace setStringValue: [NSString stringWithFormat:
1402 @"%d", fTitle->job->deinterlace]];
1403 [fPicSettingPAR setStringValue: [NSString stringWithFormat:
1404 @"%d", fTitle->job->pixel_ratio]];
1406 if (fTitle->job->pixel_ratio == 1)
1408 int titlewidth = fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3];
1409 int arpwidth = fTitle->job->pixel_aspect_width;
1410 int arpheight = fTitle->job->pixel_aspect_height;
1411 int displayparwidth = titlewidth * arpwidth / arpheight;
1412 int displayparheight = fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1];
1413 [fPicLabelPAROutp setStringValue: @"Anamorphic Output:"];
1414 [fPicLabelPAROutputX setStringValue: @"x"];
1415 [fPicSettingPARWidth setStringValue: [NSString stringWithFormat:
1416 @"%d", displayparwidth]];
1417 [fPicSettingPARHeight setStringValue: [NSString stringWithFormat:
1418 @"%d", displayparheight]];
1419 [fPicSettingHeight setStringValue: [NSString stringWithFormat:
1420 @"%d", displayparheight]];
1421 fTitle->job->keep_ratio = 0;
1425 [fPicLabelPAROutp setStringValue: @""];
1426 [fPicLabelPAROutputX setStringValue: @""];
1427 [fPicSettingPARWidth setStringValue: @""];
1428 [fPicSettingPARHeight setStringValue: @""];
1431 /* Set ON/Off values for the deinterlace/keep aspect ratio according to boolean */
1432 if (fTitle->job->keep_ratio > 0)
1434 [fPicSettingARkeepDsply setStringValue: @"On"];
1438 [fPicSettingARkeepDsply setStringValue: @"Off"];
1440 if (fTitle->job->deinterlace > 0)
1442 [fPicSettingDeinterlaceDsply setStringValue: @"On"];
1446 [fPicSettingDeinterlaceDsply setStringValue: @"Off"];
1448 if (fTitle->job->pixel_ratio > 0)
1450 [fPicSettingPARDsply setStringValue: @"On"];
1454 [fPicSettingPARDsply setStringValue: @"Off"];
1460 - (IBAction) CalculateBitrate: (id) sender
1462 if( !fHandle || [fVidQualityMatrix selectedRow] != 0 )
1467 hb_list_t * list = hb_get_titles( fHandle );
1468 hb_title_t * title = (hb_title_t *) hb_list_item( list,
1469 [fSrcTitlePopUp indexOfSelectedItem] );
1470 hb_job_t * job = title->job;
1474 [fVidBitrateField setIntValue: hb_calc_bitrate( job,
1475 [fVidTargetSizeField intValue] )];
1478 - (IBAction) ShowAddPresetPanel: (id) sender
1480 /* Show the panel */
1481 /* Temporarily disable until window hang bug is fixed */
1483 [NSApp beginSheet: fAddPresetPanel modalForWindow: fWindow
1484 modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
1485 [NSApp runModalForWindow: fAddPresetPanel];
1486 [NSApp endSheet: fAddPresetPanel];
1487 [fAddPresetPanel orderOut: self];
1490 - (IBAction) CloseAddPresetPanel: (id) sender
1495 - (IBAction)AddFactoryPresets:(id)sender
1497 /* Here we create each shipped preset */
1498 [UserPresets addObject:[self CreateIpodPreset]];
1499 [UserPresets addObject:[self CreateAppleTVPreset]];
1502 - (IBAction)AddUserPreset:(id)sender
1504 /* Here we create a custom user preset */
1505 [UserPresets addObject:[self CreatePreset]];
1513 /* We Sort the Presets By Factory or Custom */
1514 NSSortDescriptor * presetTypeDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"Type"
1515 ascending:YES] autorelease];
1516 /* We Sort the Presets Alphabetically by name */
1517 NSSortDescriptor * presetNameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"PresetName"
1518 ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease];
1519 NSArray *sortDescriptors=[NSArray arrayWithObjects:presetTypeDescriptor,presetNameDescriptor,nil];
1520 NSArray *sortedArray=[UserPresets sortedArrayUsingDescriptors:sortDescriptors];
1521 [UserPresets setArray:sortedArray];
1523 /* We stop the modal window for the new preset */
1524 [fPresetNewName setStringValue: @""];
1526 /* We Reload the New Table data for presets */
1527 [tableView reloadData];
1528 /* We save all of the preset data here */
1532 - (IBAction)InsertPreset:(id)sender
1534 int index = [tableView selectedRow];
1535 [UserPresets insertObject:[self CreatePreset] atIndex:index];
1536 [tableView reloadData];
1540 - (NSDictionary *)CreatePreset
1542 NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
1543 /* Get the New Preset Name from the field in the AddPresetPanel */
1544 [preset setObject:[fPresetNewName stringValue] forKey:@"PresetName"];
1545 /*Set whether or not this is a user preset or factory 0 is factory, 1 is user*/
1546 [preset setObject:[NSNumber numberWithInt:1] forKey:@"Type"];
1547 /*Set whether or not this is default, at creation set to 0*/
1548 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
1549 /*Get the whether or not to apply pic settings in the AddPresetPanel*/
1550 [preset setObject:[NSNumber numberWithInt:[fPresetNewPicSettingsApply state]] forKey:@"UsesPictureSettings"];
1552 [preset setObject:[fDstFormatPopUp titleOfSelectedItem] forKey:@"FileFormat"];
1554 [preset setObject:[fDstCodecsPopUp titleOfSelectedItem] forKey:@"FileCodecs"];
1556 [preset setObject:[fVidEncoderPopUp titleOfSelectedItem] forKey:@"VideoEncoder"];
1558 [preset setObject:[NSNumber numberWithInt:[fVidQualityMatrix selectedRow]] forKey:@"VideoQualityType"];
1559 [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
1560 [preset setObject:[fVidBitrateField stringValue] forKey:@"VideoAvgBitrate"];
1561 [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
1563 /* Video framerate */
1564 [preset setObject:[fVidRatePopUp titleOfSelectedItem] forKey:@"VideoFramerate"];
1566 [preset setObject:[NSNumber numberWithInt:[fVidGrayscaleCheck state]] forKey:@"VideoGrayScale"];
1567 /* 2 Pass Encoding */
1568 [preset setObject:[NSNumber numberWithInt:[fVidTwoPassCheck state]] forKey:@"VideoTwoPass"];
1570 /*Picture Settings*/
1571 hb_job_t * job = fTitle->job;
1572 /* Basic Picture Settings */
1573 [preset setObject:[NSNumber numberWithInt:fTitle->job->width] forKey:@"PictureWidth"];
1574 [preset setObject:[NSNumber numberWithInt:fTitle->job->height] forKey:@"PictureHeight"];
1575 [preset setObject:[NSNumber numberWithInt:fTitle->job->keep_ratio] forKey:@"PictureKeepRatio"];
1576 [preset setObject:[NSNumber numberWithInt:fTitle->job->deinterlace] forKey:@"PictureDeinterlace"];
1577 [preset setObject:[NSNumber numberWithInt:fTitle->job->pixel_ratio] forKey:@"PicturePAR"];
1578 /* Set crop settings here */
1579 /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
1580 [preset setObject:[NSNumber numberWithInt:job->crop[0]] forKey:@"PictureTopCrop"];
1581 [preset setObject:[NSNumber numberWithInt:job->crop[1]] forKey:@"PictureBottomCrop"];
1582 [preset setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"];
1583 [preset setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"];
1586 /* Audio Language One*/
1587 [preset setObject:[fAudLang1PopUp titleOfSelectedItem] forKey:@"AudioLang1"];
1588 /* Audio Language One Surround Sound Checkbox*/
1589 [preset setObject:[NSNumber numberWithInt:[fAudLang1SurroundCheck state]] forKey:@"AudioLang1Surround"];
1590 /* Audio Sample Rate*/
1591 [preset setObject:[fAudRatePopUp titleOfSelectedItem] forKey:@"AudioSampleRate"];
1592 /* Audio Bitrate Rate*/
1593 [preset setObject:[fAudBitratePopUp titleOfSelectedItem] forKey:@"AudioBitRate"];
1595 [preset setObject:[fSubPopUp titleOfSelectedItem] forKey:@"Subtitles"];
1598 [preset autorelease];
1603 - (NSDictionary *)CreateIpodPreset
1605 NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
1606 /* Get the New Preset Name from the field in the AddPresetPanel */
1607 [preset setObject:@"HB-iPod" forKey:@"PresetName"];
1608 /*Set whether or not this is a user preset or factory 0 is factory, 1 is user*/
1609 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
1610 /*Set whether or not this is default, at creation set to 0*/
1611 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
1612 /*Get the whether or not to apply pic settings in the AddPresetPanel*/
1613 [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesPictureSettings"];
1615 [preset setObject:@"MP4 file" forKey:@"FileFormat"];
1617 [preset setObject:@"AVC/H.264 Video / AAC Audio" forKey:@"FileCodecs"];
1619 [preset setObject:@"x264 (h.264 iPod)" forKey:@"VideoEncoder"];
1621 [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
1622 [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
1623 [preset setObject:@"1400" forKey:@"VideoAvgBitrate"];
1624 [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
1626 /* Video framerate */
1627 [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
1629 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
1630 /* 2 Pass Encoding */
1631 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
1633 /*Picture Settings*/
1634 //hb_job_t * job = fTitle->job;
1635 /* Basic Picture Settings */
1636 //[preset setObject:[NSNumber numberWithInt:fTitle->job->width] forKey:@"PictureWidth"];
1637 //[preset setObject:[NSNumber numberWithInt:fTitle->job->height] forKey:@"PictureHeight"];
1638 //[preset setObject:[NSNumber numberWithInt:fTitle->job->keep_ratio] forKey:@"PictureKeepRatio"];
1639 //[preset setObject:[NSNumber numberWithInt:fTitle->job->deinterlace] forKey:@"PictureDeinterlace"];
1640 //[preset setObject:[NSNumber numberWithInt:fTitle->job->pixel_ratio] forKey:@"PicturePAR"];
1641 /* Set crop settings here */
1642 /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
1643 //[preset setObject:[NSNumber numberWithInt:job->crop[0]] forKey:@"PictureTopCrop"];
1644 //[preset setObject:[NSNumber numberWithInt:job->crop[1]] forKey:@"PictureBottomCrop"];
1645 //[preset setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"];
1646 //[preset setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"];
1649 /* Audio Language One*/
1650 [preset setObject:[fAudLang1PopUp titleOfSelectedItem] forKey:@"AudioLang1"];
1651 /* Audio Language One Surround Sound Checkbox*/
1652 [preset setObject:[NSNumber numberWithInt:0] forKey:@"AudioLang1Surround"];
1653 /* Audio Sample Rate*/
1654 [preset setObject:@"44.1" forKey:@"AudioSampleRate"];
1655 /* Audio Bitrate Rate*/
1656 [preset setObject:@"128" forKey:@"AudioBitRate"];
1658 [preset setObject:@"None" forKey:@"Subtitles"];
1661 [preset autorelease];
1666 - (NSDictionary *)CreateAppleTVPreset
1668 NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
1669 /* Get the New Preset Name from the field in the AddPresetPanel */
1670 [preset setObject:@"HB-AppleTV" forKey:@"PresetName"];
1671 /*Set whether or not this is a user preset or factory 0 is factory, 1 is user*/
1672 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Type"];
1673 /*Set whether or not this is default, at creation set to 0*/
1674 [preset setObject:[NSNumber numberWithInt:0] forKey:@"Default"];
1675 /*Get the whether or not to apply pic settings in the AddPresetPanel*/
1676 [preset setObject:[NSNumber numberWithInt:0] forKey:@"UsesPictureSettings"];
1678 [preset setObject:@"MP4 file" forKey:@"FileFormat"];
1680 [preset setObject:@"AVC/H.264 Video / AAC Audio" forKey:@"FileCodecs"];
1682 [preset setObject:@"x264 (h.264 Main)" forKey:@"VideoEncoder"];
1684 [preset setObject:[NSNumber numberWithInt:1] forKey:@"VideoQualityType"];
1685 [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
1686 [preset setObject:@"3000" forKey:@"VideoAvgBitrate"];
1687 [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
1689 /* Video framerate */
1690 [preset setObject:@"Same as source" forKey:@"VideoFramerate"];
1692 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoGrayScale"];
1693 /* 2 Pass Encoding */
1694 [preset setObject:[NSNumber numberWithInt:0] forKey:@"VideoTwoPass"];
1696 /*Picture Settings*/
1697 //hb_job_t * job = fTitle->job;
1698 /* Basic Picture Settings */
1699 //[preset setObject:[NSNumber numberWithInt:fTitle->job->width] forKey:@"PictureWidth"];
1700 //[preset setObject:[NSNumber numberWithInt:fTitle->job->height] forKey:@"PictureHeight"];
1701 //[preset setObject:[NSNumber numberWithInt:fTitle->job->keep_ratio] forKey:@"PictureKeepRatio"];
1702 //[preset setObject:[NSNumber numberWithInt:fTitle->job->deinterlace] forKey:@"PictureDeinterlace"];
1703 //[preset setObject:[NSNumber numberWithInt:fTitle->job->pixel_ratio] forKey:@"PicturePAR"];
1704 /* Set crop settings here */
1705 /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
1706 //[preset setObject:[NSNumber numberWithInt:job->crop[0]] forKey:@"PictureTopCrop"];
1707 //[preset setObject:[NSNumber numberWithInt:job->crop[1]] forKey:@"PictureBottomCrop"];
1708 //[preset setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"];
1709 //[preset setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"];
1712 /* Audio Language One*/
1713 [preset setObject:[fAudLang1PopUp titleOfSelectedItem] forKey:@"AudioLang1"];
1714 /* Audio Language One Surround Sound Checkbox*/
1715 [preset setObject:[NSNumber numberWithInt:0] forKey:@"AudioLang1Surround"];
1716 /* Audio Sample Rate*/
1717 [preset setObject:@"44.1" forKey:@"AudioSampleRate"];
1718 /* Audio Bitrate Rate*/
1719 [preset setObject:@"320" forKey:@"AudioBitRate"];
1721 [preset setObject:@"None" forKey:@"Subtitles"];
1724 [preset autorelease];
1730 - (IBAction)DeletePreset:(id)sender
1733 NSEnumerator *enumerator;
1735 NSMutableArray *tempArray;
1738 if ( [tableView numberOfSelectedRows] == 0 )
1740 /* Alert user before deleting preset */
1741 /* Comment out for now, tie to user pref eventually */
1743 status = NSRunAlertPanel(@"Warning!", @"Are you sure that you want to delete the selected preset?", @"OK", @"Cancel", nil);
1745 if ( status == NSAlertDefaultReturn ) {
1746 enumerator = [tableView selectedRowEnumerator];
1747 tempArray = [NSMutableArray array];
1749 while ( (index = [enumerator nextObject]) ) {
1750 tempObject = [UserPresets objectAtIndex:[index intValue]];
1751 [tempArray addObject:tempObject];
1754 [UserPresets removeObjectsInArray:tempArray];
1755 [tableView reloadData];
1759 - (IBAction)tableViewSelected:(id)sender
1761 /* Since we cannot disable the presets tableView in terms of clickability
1762 we will use the enabled state of the add presets button to determine whether
1763 or not clicking on a preset will do anything */
1764 if ([fPresetsAdd isEnabled])
1767 /* we get the chosen preset from the UserPresets array */
1768 chosenPreset = [UserPresets objectAtIndex:[sender selectedRow]];
1769 /* we set the preset display field in main window here */
1770 //[fPresetSelectedDisplay setStringValue: [NSString stringWithFormat: @"%@", [chosenPreset valueForKey:@"PresetName"]]];
1772 [fDstFormatPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"FileFormat"]]];
1773 [self FormatPopUpChanged: NULL];
1775 [fDstCodecsPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"FileCodecs"]]];
1776 [self CodecsPopUpChanged: NULL];
1778 [fVidEncoderPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoEncoder"]]];
1779 /* Lets run through the following functions to get variables set there */
1780 [self EncoderPopUpChanged: sender];
1781 [self Check6ChannelAACExtraction: sender];
1782 [self CalculateBitrate: sender];
1785 [fVidQualityMatrix selectCellAtRow:[[chosenPreset objectForKey:@"VideoQualityType"] intValue] column:0];
1787 [fVidTargetSizeField setStringValue: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoTargetSize"]]];
1788 [fVidBitrateField setStringValue: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoAvgBitrate"]]];
1790 [fVidQualitySlider setFloatValue: [[chosenPreset valueForKey:@"VideoQualitySlider"] floatValue]];
1791 [self VideoMatrixChanged: sender];
1793 /* Video framerate */
1794 [fVidRatePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoFramerate"]]];
1797 [fVidGrayscaleCheck setState:[[chosenPreset objectForKey:@"VideoGrayScale"] intValue]];
1799 /* 2 Pass Encoding */
1800 [fVidTwoPassCheck setState:[[chosenPreset objectForKey:@"VideoTwoPass"] intValue]];
1804 /* Audio Language One*/
1805 [fAudLang1PopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"AudioLang1"]]];
1806 /* Audio Language One Surround Sound Checkbox*/
1807 [fAudLang1SurroundCheck setState:[[chosenPreset objectForKey:@"AudioLang1Surround"] intValue]];
1808 [self Check6ChannelAACExtraction: sender];
1809 /* Audio Sample Rate*/
1810 [fAudRatePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"AudioSampleRate"]]];
1811 /* Audio Bitrate Rate*/
1812 [fAudBitratePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"AudioBitRate"]]];
1814 [fSubPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"Subtitles"]]];
1816 /* Picture Settings */
1817 /* Look to see if we apply these here in objectForKey:@"UsesPictureSettings"] */
1818 if ([[chosenPreset objectForKey:@"UsesPictureSettings"] intValue] == 1)
1820 hb_job_t * job = fTitle->job;
1821 job->width = [[chosenPreset objectForKey:@"PictureWidth"] intValue];
1822 job->height = [[chosenPreset objectForKey:@"PictureHeight"] intValue];
1823 job->keep_ratio = [[chosenPreset objectForKey:@"PictureKeepRatio"] intValue];
1824 if (job->keep_ratio == 1)
1826 hb_fix_aspect( job, HB_KEEP_WIDTH );
1828 job->pixel_ratio = [[chosenPreset objectForKey:@"PicturePAR"] intValue];
1829 job->crop[0] = [[chosenPreset objectForKey:@"PictureTopCrop"] intValue];
1830 job->crop[1] = [[chosenPreset objectForKey:@"PictureBottomCrop"] intValue];
1831 job->crop[2] = [[chosenPreset objectForKey:@"PictureLeftCrop"] intValue];
1832 job->crop[3] = [[chosenPreset objectForKey:@"PictureRightCrop"] intValue];
1833 [self CalculatePictureSizing: sender];
1836 // Deselect the currently selected table //
1837 //[tableView deselectRow:[tableView selectedRow]];
1841 - (int)numberOfRowsInTableView:(NSTableView *)aTableView
1843 return [UserPresets count];
1846 - (id)tableView:(NSTableView *)aTableView
1847 objectValueForTableColumn:(NSTableColumn *)aTableColumn
1853 id theRecord, theValue;
1855 theRecord = [UserPresets objectAtIndex:rowIndex];
1856 theValue = [theRecord objectForKey:[aTableColumn identifier]];
1861 // NSTableDataSource method that we implement to edit values directly in the table...
1862 - (void)tableView:(NSTableView *)aTableView
1863 setObjectValue:(id)anObject
1864 forTableColumn:(NSTableColumn *)aTableColumn
1869 theRecord = [UserPresets objectAtIndex:rowIndex];
1870 [theRecord setObject:anObject forKey:[aTableColumn identifier]];
1872 /* We Sort the Presets Alphabetically by name */
1873 NSSortDescriptor * lastNameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"PresetName"
1874 ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease];
1875 NSArray *sortDescriptors=[NSArray arrayWithObject:lastNameDescriptor];
1876 NSArray *sortedArray=[UserPresets sortedArrayUsingDescriptors:sortDescriptors];
1877 [UserPresets setArray:sortedArray];
1878 /* We Reload the New Table data for presets */
1879 [tableView reloadData];
1880 /* We save all of the preset data here */
1887 [UserPresets writeToFile:UserPresetsFile atomically:YES];
1893 - (void) controlTextDidBeginEditing: (NSNotification *) notification
1895 [self CalculateBitrate: NULL];
1898 - (void) controlTextDidEndEditing: (NSNotification *) notification
1900 [self CalculateBitrate: NULL];
1903 - (void) controlTextDidChange: (NSNotification *) notification
1905 [self CalculateBitrate: NULL];
1908 - (IBAction) OpenHomepage: (id) sender
1910 [[NSWorkspace sharedWorkspace] openURL: [NSURL
1911 URLWithString:@"http://handbrake.m0k.org/"]];
1914 - (IBAction) OpenForums: (id) sender
1916 [[NSWorkspace sharedWorkspace] openURL: [NSURL
1917 URLWithString:@"http://handbrake.m0k.org/forum/"]];