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];
141 /* Show/Dont Show Presets drawer upon launch based
142 on user preference DefaultPresetsDrawerShow*/
143 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPresetsDrawerShow"] > 0)
145 [fPresetDrawer open];
151 [fDstFormatPopUp removeAllItems];
152 [fDstFormatPopUp addItemWithTitle: _( @"MP4 file" )];
153 [fDstFormatPopUp addItemWithTitle: _( @"AVI file" )];
154 [fDstFormatPopUp addItemWithTitle: _( @"OGM file" )];
155 [fDstFormatPopUp selectItemAtIndex: 0];
157 [self FormatPopUpChanged: NULL];
159 [fDstFile2Field setStringValue: [NSString stringWithFormat:
160 @"%@/Desktop/Movie.mp4", NSHomeDirectory()]];
163 [fVidEncoderPopUp removeAllItems];
164 [fVidEncoderPopUp addItemWithTitle: @"FFmpeg"];
165 [fVidEncoderPopUp addItemWithTitle: @"XviD"];
168 [fVidTargetSizeField setIntValue: 700];
169 [fVidBitrateField setIntValue: 1000];
170 /* Do we want to force the quality settings if PAR is on ?
171 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"PixelRatio"])
173 [fVidBitrateField setIntValue: 1500];
174 [fVidTwoPassCheck setState: NSOnState];
178 [fVidBitrateField setIntValue: 1000];
181 [fVidQualityMatrix selectCell: fVidBitrateCell];
182 [self VideoMatrixChanged: NULL];
184 /* Video framerate */
185 [fVidRatePopUp removeAllItems];
186 [fVidRatePopUp addItemWithTitle: _( @"Same as source" )];
187 for( int i = 0; i < hb_video_rates_count; i++ )
189 [fVidRatePopUp addItemWithTitle:
190 [NSString stringWithCString: hb_video_rates[i].string]];
192 [fVidRatePopUp selectItemAtIndex: 0];
194 /* Picture Settings */
195 [fPicLabelPAROutp setStringValue: @""];
196 [fPicLabelPAROutputX setStringValue: @""];
197 [fPicSettingPARWidth setStringValue: @""];
198 [fPicSettingPARHeight setStringValue: @""];
201 [fAudBitratePopUp removeAllItems];
202 for( int i = 0; i < hb_audio_bitrates_count; i++ )
204 [fAudBitratePopUp addItemWithTitle:
205 [NSString stringWithCString: hb_audio_bitrates[i].string]];
207 [fAudBitratePopUp selectItemAtIndex: hb_audio_bitrates_default];
209 /* Audio samplerate */
210 [fAudRatePopUp removeAllItems];
211 for( int i = 0; i < hb_audio_rates_count; i++ )
213 [fAudRatePopUp addItemWithTitle:
214 [NSString stringWithCString: hb_audio_rates[i].string]];
216 [fAudRatePopUp selectItemAtIndex: hb_audio_rates_default];
219 [fStatusField setStringValue: @""];
222 [fPauseButton setEnabled: NO];
223 [fRipButton setEnabled: NO];
230 - (void) TranslateStrings
232 [fSrcDVD1Field setStringValue: _( @"DVD:" )];
233 [fSrcTitleField setStringValue: _( @"Title:" )];
234 [fSrcChapterField setStringValue: _( @"Chapters:" )];
235 [fSrcChapterToField setStringValue: _( @"to" )];
236 [fSrcDuration1Field setStringValue: _( @"Duration:" )];
238 [fDstFormatField setStringValue: _( @"File format:" )];
239 [fDstCodecsField setStringValue: _( @"Codecs:" )];
240 [fDstFile1Field setStringValue: _( @"File:" )];
241 [fDstBrowseButton setTitle: _( @"Browse" )];
243 [fVidRateField setStringValue: _( @"Framerate (fps):" )];
244 [fVidEncoderField setStringValue: _( @"Encoder:" )];
245 [fVidQualityField setStringValue: _( @"Quality:" )];
248 /***********************************************************************
250 ***********************************************************************
251 * Shows a progression bar on the dock icon, filled according to
252 * 'progress' (0.0 <= progress <= 1.0).
253 * Called with progress < 0.0 or progress > 1.0, restores the original
255 **********************************************************************/
256 - (void) UpdateDockIcon: (float) progress
260 NSBitmapImageRep * bmp;
262 uint32_t black = htonl( 0x000000FF );
263 uint32_t red = htonl( 0xFF0000FF );
264 uint32_t white = htonl( 0xFFFFFFFF );
265 int row_start, row_end;
268 /* Get application original icon */
269 icon = [NSImage imageNamed: @"NSApplicationIcon"];
271 if( progress < 0.0 || progress > 1.0 )
273 [NSApp setApplicationIconImage: icon];
277 /* Get it in a raw bitmap form */
278 tiff = [icon TIFFRepresentationUsingCompression:
279 NSTIFFCompressionNone factor: 1.0];
280 bmp = [NSBitmapImageRep imageRepWithData: tiff];
282 /* Draw the progression bar */
283 /* It's pretty simple (ugly?) now, but I'm no designer */
285 row_start = 3 * (int) [bmp size].height / 4;
286 row_end = 7 * (int) [bmp size].height / 8;
288 for( i = row_start; i < row_start + 2; i++ )
290 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
291 for( j = 0; j < (int) [bmp size].width; j++ )
296 for( i = row_start + 2; i < row_end - 2; i++ )
298 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
301 for( j = 2; j < (int) [bmp size].width - 2; j++ )
303 if( j < 2 + (int) ( ( [bmp size].width - 4.0 ) * progress ) )
315 for( i = row_end - 2; i < row_end; i++ )
317 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
318 for( j = 0; j < (int) [bmp size].width; j++ )
324 /* Now update the dock icon */
325 tiff = [bmp TIFFRepresentationUsingCompression:
326 NSTIFFCompressionNone factor: 1.0];
327 icon = [[NSImage alloc] initWithData: tiff];
328 [NSApp setApplicationIconImage: icon];
332 - (void) UpdateUI: (NSTimer *) timer
336 hb_get_state( fHandle, &s );
343 case HB_STATE_SCANNING:
344 [fScanController UpdateUI: &s];
347 #define p s.param.scandone
348 case HB_STATE_SCANDONE:
352 int indxpri=0; // Used to search the longuest title (default in combobox)
353 int longuestpri=0; // Used to search the longuest title (default in combobox)
355 [fScanController UpdateUI: &s];
357 list = hb_get_titles( fHandle );
359 if( !hb_list_count( list ) )
365 [fSrcTitlePopUp removeAllItems];
366 for( int i = 0; i < hb_list_count( list ); i++ )
368 title = (hb_title_t *) hb_list_item( list, i );
369 /*Set DVD Name at top of window*/
370 [fSrcDVD2Field setStringValue: [NSString
371 stringWithUTF8String: title->name]];
373 /* Use the dvd name in the default output field here
374 May want to add code to remove blank spaces for some dvd names*/
375 /* Check to see if the last destination has been set,use if so, if not, use Desktop */
376 if ([[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"])
378 [fDstFile2Field setStringValue: [NSString stringWithFormat:
379 @"%@/%@.mp4", [[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"],[NSString
380 stringWithUTF8String: title->name]]];
384 [fDstFile2Field setStringValue: [NSString stringWithFormat:
385 @"%@/Desktop/%@.mp4", NSHomeDirectory(),[NSString
386 stringWithUTF8String: title->name]]];
390 if (longuestpri < title->hours*60*60 + title->minutes *60 + title->seconds)
392 longuestpri=title->hours*60*60 + title->minutes *60 + title->seconds;
397 int format = [fDstFormatPopUp indexOfSelectedItem];
403 /*Get Default MP4 File Extension for mpeg4 (.mp4 or .m4v) from prefs*/
404 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultMpegName"] > 0)
422 NSString * string = [fDstFile2Field stringValue];
423 /* Add/replace File Output name to the correct extension*/
424 if( [string characterAtIndex: [string length] - 4] == '.' )
426 [fDstFile2Field setStringValue: [NSString stringWithFormat:
427 @"%@.%s", [string substringToIndex: [string length] - 4],
432 [fDstFile2Field setStringValue: [NSString stringWithFormat:
433 @"%@.%s", string, ext]];
437 [fSrcTitlePopUp addItemWithTitle: [NSString
438 stringWithFormat: @"%d - %02dh%02dm%02ds",
439 title->index, title->hours, title->minutes,
443 // Select the longuest title
444 [fSrcTitlePopUp selectItemAtIndex: indxpri];
446 [self TitlePopUpChanged: NULL];
447 [self EnableUI: YES];
448 [fPauseButton setEnabled: NO];
449 [fRipButton setEnabled: YES];
454 #define p s.param.working
455 case HB_STATE_WORKING:
457 float progress_total;
458 NSMutableString * string;
460 /* Update text field */
461 string = [NSMutableString stringWithFormat:
462 _( @"Encoding: task %d of %d, %.2f %%" ),
463 p.job_cur, p.job_count, 100.0 * p.progress];
466 [string appendFormat:
467 _( @" (%.2f fps, avg %.2f fps, ETA %02dh%02dm%02ds)" ),
468 p.rate_cur, p.rate_avg, p.hours, p.minutes, p.seconds];
470 [fStatusField setStringValue: string];
473 progress_total = ( p.progress + p.job_cur - 1 ) / p.job_count;
474 [fRipIndicator setIndeterminate: NO];
475 [fRipIndicator setDoubleValue: 100.0 * progress_total];
477 /* Update dock icon */
478 [self UpdateDockIcon: progress_total];
480 [fPauseButton setEnabled: YES];
481 [fPauseButton setTitle: _( @"Pause" )];
482 [fRipButton setEnabled: YES];
483 [fRipButton setTitle: _( @"Cancel" )];
488 #define p s.param.muxing
489 case HB_STATE_MUXING:
491 NSMutableString * string;
493 /* Update text field */
494 string = [NSMutableString stringWithFormat:
496 [fStatusField setStringValue: string];
499 [fRipIndicator setIndeterminate: YES];
500 [fRipIndicator startAnimation: nil];
502 /* Update dock icon */
503 [self UpdateDockIcon: 1.0];
505 [fPauseButton setEnabled: YES];
506 [fPauseButton setTitle: _( @"Pause" )];
507 [fRipButton setEnabled: YES];
508 [fRipButton setTitle: _( @"Cancel" )];
513 case HB_STATE_PAUSED:
514 [fStatusField setStringValue: _( @"Paused" )];
515 [fPauseButton setEnabled: YES];
516 [fPauseButton setTitle: _( @"Resume" )];
517 [fRipButton setEnabled: YES];
518 [fRipButton setTitle: _( @"Cancel" )];
521 case HB_STATE_WORKDONE:
523 [self EnableUI: YES];
524 [fStatusField setStringValue: _( @"Done." )];
525 [fRipIndicator setIndeterminate: NO];
526 [fRipIndicator setDoubleValue: 0.0];
527 [fRipButton setTitle: _( @"Rip" )];
529 /* Restore dock icon */
530 [self UpdateDockIcon: -1.0];
532 [fPauseButton setEnabled: NO];
533 [fPauseButton setTitle: _( @"Pause" )];
534 [fRipButton setEnabled: YES];
535 [fRipButton setTitle: _( @"Rip" )];
539 while( ( job = hb_job( fHandle, 0 ) ) )
541 hb_rem( fHandle, job );
547 /* FIXME: we should only do that when necessary */
548 if( [fQueueCheck state] == NSOnState )
550 int count = hb_count( fHandle );
553 [fQueueCheck setTitle: [NSString stringWithFormat:
554 @"Enable queue (%d task%s in queue)",
555 count, ( count > 1 ) ? "s" : ""]];
559 [fQueueCheck setTitle: @"Enable queue (no task in queue)"];
563 [[NSRunLoop currentRunLoop] addTimer: [NSTimer
564 scheduledTimerWithTimeInterval: 0.2 target: self
565 selector: @selector( UpdateUI: ) userInfo: NULL repeats: FALSE]
566 forMode: NSModalPanelRunLoopMode];
569 - (void) EnableUI: (bool) b
571 NSControl * controls[] =
572 { fSrcDVD1Field, fSrcDVD2Field, fSrcTitleField, fSrcTitlePopUp,
573 fSrcChapterField, fSrcChapterStartPopUp, fSrcChapterToField,
574 fSrcChapterEndPopUp, fSrcDuration1Field, fSrcDuration2Field,
575 fDstFormatField, fDstFormatPopUp, fDstCodecsField,
576 fDstCodecsPopUp, fDstFile1Field, fDstFile2Field,
577 fDstBrowseButton, fVidRateField, fVidRatePopUp,
578 fVidEncoderField, fVidEncoderPopUp, fVidQualityField,
579 fVidQualityMatrix, fVidGrayscaleCheck, fSubField, fSubPopUp,
580 fAudLang1Field, fAudLang1PopUp, fAudLang2Field, fAudLang2PopUp,
581 fAudRateField, fAudRatePopUp, fAudBitrateField,
582 fAudBitratePopUp, fPictureButton, fQueueCheck,
583 fPicSrcWidth,fPicSrcHeight,fPicSettingWidth,fPicSettingHeight,
584 fPicSettingARkeep,fPicSettingDeinterlace,fPicSettingARkeepDsply,
585 fPicSettingDeinterlaceDsply,fPicLabelSettings,fPicLabelSrc,fPicLabelOutp,
586 fPicLabelAr,fPicLabelDeinter,fPicLabelSrcX,fPicLabelOutputX,
587 fPicLabelPAROutp,fPicLabelPAROutputX,fPicSettingPARWidth,fPicSettingPARHeight,
588 fPicSettingPARDsply,fPicLabelAnamorphic,tableView,fPresetsAdd,fPresetsDelete};
591 i < sizeof( controls ) / sizeof( NSControl * ); i++ )
593 if( [[controls[i] className] isEqualToString: @"NSTextField"] )
595 NSTextField * tf = (NSTextField *) controls[i];
596 if( ![tf isBezeled] )
598 [tf setTextColor: b ? [NSColor controlTextColor] :
599 [NSColor disabledControlTextColor]];
603 [controls[i] setEnabled: b];
607 /* Temporarily disable Lang2 until crash is fixed */
608 [fAudLang2PopUp setEnabled: NO];
609 [fAudLang2Field setEnabled: NO];
612 /* if we're enabling the interface, check if we should / should't offer 6-channel AAC extraction */
613 [self Check6ChannelAACExtraction: NULL];
615 /* if we're disabling the interface, turn it off */
616 [fAudLang1SurroundCheck setEnabled: NO];
619 [self VideoMatrixChanged: NULL];
622 - (IBAction) ShowScanPanel: (id) sender
624 [fScanController Show];
627 - (BOOL) windowShouldClose: (id) sender
629 /* Stop the application when the user closes the window */
630 [NSApp terminate: self];
634 - (IBAction) VideoMatrixChanged: (id) sender;
636 bool target, bitrate, quality;
638 target = bitrate = quality = false;
639 if( [fVidQualityMatrix isEnabled] )
641 switch( [fVidQualityMatrix selectedRow] )
654 [fVidTargetSizeField setEnabled: target];
655 [fVidBitrateField setEnabled: bitrate];
656 [fVidQualitySlider setEnabled: quality];
657 [fVidTwoPassCheck setEnabled: !quality &&
658 [fVidQualityMatrix isEnabled]];
661 [fVidTwoPassCheck setState: NSOffState];
664 [self QualitySliderChanged: sender];
665 [self CalculateBitrate: sender];
668 - (IBAction) QualitySliderChanged: (id) sender
670 [fVidConstantCell setTitle: [NSString stringWithFormat:
671 _( @"Constant quality: %.0f %%" ), 100.0 *
672 [fVidQualitySlider floatValue]]];
675 - (IBAction) BrowseFile: (id) sender
677 /* Open a panel to let the user choose and update the text field */
678 NSSavePanel * panel = [NSSavePanel savePanel];
680 [panel beginSheetForDirectory: NULL file: NULL
681 modalForWindow: fWindow modalDelegate: self
682 didEndSelector: @selector( BrowseFileDone:returnCode:contextInfo: )
686 - (void) BrowseFileDone: (NSSavePanel *) sheet
687 returnCode: (int) returnCode contextInfo: (void *) contextInfo
689 if( returnCode == NSOKButton )
691 [fDstFile2Field setStringValue: [sheet filename]];
692 [self FormatPopUpChanged: NULL];
696 - (IBAction) ShowPicturePanel: (id) sender
698 hb_list_t * list = hb_get_titles( fHandle );
699 hb_title_t * title = (hb_title_t *) hb_list_item( list,
700 [fSrcTitlePopUp indexOfSelectedItem] );
702 /* Resize the panel */
704 newSize.width = 246 + title->width;
705 newSize.height = 80 + title->height;
706 [fPicturePanel setContentSize: newSize];
708 [fPictureController SetTitle: title];
710 [NSApp beginSheet: fPicturePanel modalForWindow: fWindow
711 modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
712 [NSApp runModalForWindow: fPicturePanel];
713 [NSApp endSheet: fPicturePanel];
714 [fPicturePanel orderOut: self];
715 [self CalculatePictureSizing: sender];
718 - (IBAction) ShowQueuePanel: (id) sender
720 /* Update the OutlineView */
721 [fQueueController Update: sender];
724 [NSApp beginSheet: fQueuePanel modalForWindow: fWindow
725 modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
726 [NSApp runModalForWindow: fQueuePanel];
727 [NSApp endSheet: fQueuePanel];
728 [fQueuePanel orderOut: self];
733 hb_list_t * list = hb_get_titles( fHandle );
734 hb_title_t * title = (hb_title_t *) hb_list_item( list,
735 [fSrcTitlePopUp indexOfSelectedItem] );
736 hb_job_t * job = title->job;
738 /* Chapter selection */
739 job->chapter_start = [fSrcChapterStartPopUp indexOfSelectedItem] + 1;
740 job->chapter_end = [fSrcChapterEndPopUp indexOfSelectedItem] + 1;
744 /* Format and codecs */
745 int format = [fDstFormatPopUp indexOfSelectedItem];
746 int codecs = [fDstCodecsPopUp indexOfSelectedItem];
747 job->mux = FormatSettings[format][codecs] & HB_MUX_MASK;
748 job->vcodec = FormatSettings[format][codecs] & HB_VCODEC_MASK;
749 job->acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
751 if( ( job->vcodec & HB_VCODEC_FFMPEG ) &&
752 [fVidEncoderPopUp indexOfSelectedItem] > 0 )
754 job->vcodec = HB_VCODEC_XVID;
756 if( job->vcodec & HB_VCODEC_X264 )
758 if ([fVidEncoderPopUp indexOfSelectedItem] > 0 )
760 /* Just use new Baseline Level 3.0
761 Lets Deprecate Baseline Level 1.3*/
762 job->h264_level = 30;
763 job->mux = HB_MUX_IPOD;
764 /* move sanity check for iPod Encoding here */
765 job->pixel_ratio = 0 ;
769 /* Set this flag to switch from Constant Quantizer(default) to Constant Rate Factor Thanks jbrjake
770 Currently only used with Constant Quality setting*/
771 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultCrf"] > 0 && [fVidQualityMatrix selectedRow] == 2)
773 /* Can only be used with svn rev >= 89 */
777 /* Sends x264 options to the core library*/
778 job->x264opts = [[[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"] UTF8String];
781 job->h264_13 = [fVidEncoderPopUp indexOfSelectedItem];
785 if( [fVidRatePopUp indexOfSelectedItem] > 0 )
787 job->vrate = 27000000;
788 job->vrate_base = hb_video_rates[[fVidRatePopUp
789 indexOfSelectedItem]-1].rate;
793 job->vrate = title->rate;
794 job->vrate_base = title->rate_base;
797 switch( [fVidQualityMatrix selectedRow] )
801 Bitrate should already have been calculated and displayed
802 in fVidBitrateField, so let's just use it */
804 job->vquality = -1.0;
805 job->vbitrate = [fVidBitrateField intValue];
808 job->vquality = [fVidQualitySlider floatValue];
813 job->grayscale = ( [fVidGrayscaleCheck state] == NSOnState );
817 /* Subtitle settings */
818 job->subtitle = [fSubPopUp indexOfSelectedItem] - 1;
821 job->audios[0] = [fAudLang1PopUp indexOfSelectedItem] - 1;
822 job->audios[1] = [fAudLang2PopUp indexOfSelectedItem] - 1;
826 job->arate = hb_audio_rates[[fAudRatePopUp
827 indexOfSelectedItem]].rate;
828 job->abitrate = hb_audio_bitrates[[fAudBitratePopUp
829 indexOfSelectedItem]].rate;
830 /* have we selected that 5.1 should be extracted as AAC? */
831 if (job->acodec == HB_ACODEC_FAAC && [fAudLang1SurroundCheck isEnabled] && [fAudLang1SurroundCheck state] == NSOnState) {
839 - (IBAction) EnableQueue: (id) sender
841 bool e = ( [fQueueCheck state] == NSOnState );
842 [fQueueAddButton setHidden: !e];
843 [fQueueShowButton setHidden: !e];
844 [fRipButton setTitle: e ? @"Start" : @"Rip"];
847 - (IBAction) AddToQueue: (id) sender
849 /* We get the destination directory from the destingation field here */
850 NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent];
851 /* We check for a valid destination here */
852 if ([[NSFileManager defaultManager] fileExistsAtPath:destinationDirectory] == 0)
854 NSRunAlertPanel(@"Warning!", @"This is not a valid destination directory!", @"OK", nil, nil);
859 hb_list_t * list = hb_get_titles( fHandle );
860 hb_title_t * title = (hb_title_t *) hb_list_item( list,
861 [fSrcTitlePopUp indexOfSelectedItem] );
862 hb_job_t * job = title->job;
866 /* Destination file */
867 job->file = strdup( [[fDstFile2Field stringValue] UTF8String] );
869 if( [fVidTwoPassCheck state] == NSOnState )
872 hb_add( fHandle, job );
874 job->x264opts = [[[NSUserDefaults standardUserDefaults] stringForKey:@"DefAdvancedx264Flags"] UTF8String];
875 hb_add( fHandle, job );
880 hb_add( fHandle, job );
883 [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"];
887 - (IBAction) Rip: (id) sender
891 /* Rip or Cancel ? */
892 if( [[fRipButton title] isEqualToString: _( @"Cancel" )] )
894 [self Cancel: sender];
898 if( [fQueueCheck state] == NSOffState )
901 [self AddToQueue: sender];
907 /* We check for duplicate name here */
908 if( [[NSFileManager defaultManager] fileExistsAtPath:
909 [fDstFile2Field stringValue]] )
911 NSBeginCriticalAlertSheet( _( @"File already exists" ),
912 _( @"Cancel" ), _( @"Overwrite" ), NULL, fWindow, self,
913 @selector( OverwriteAlertDone:returnCode:contextInfo: ),
914 NULL, NULL, [NSString stringWithFormat:
915 _( @"Do you want to overwrite %@?" ),
916 [fDstFile2Field stringValue]] );
919 /* We get the destination directory from the destingation field here */
920 NSString *destinationDirectory = [[fDstFile2Field stringValue] stringByDeletingLastPathComponent];
921 /* We check for a valid destination here */
922 if ([[NSFileManager defaultManager] fileExistsAtPath:destinationDirectory] == 0)
924 NSRunAlertPanel(@"Warning!", @"This is not a valid destination directory!", @"OK", nil, nil);
928 [[NSUserDefaults standardUserDefaults] setObject:destinationDirectory forKey:@"LastDestinationDirectory"];
936 - (void) OverwriteAlertDone: (NSWindow *) sheet
937 returnCode: (int) returnCode contextInfo: (void *) contextInfo
939 if( returnCode == NSAlertAlternateReturn )
945 - (void) UpdateAlertDone: (NSWindow *) sheet
946 returnCode: (int) returnCode contextInfo: (void *) contextInfo
948 if( returnCode == NSAlertAlternateReturn )
950 /* Show scan panel */
951 [self performSelectorOnMainThread: @selector(ShowScanPanel:)
952 withObject: NULL waitUntilDone: NO];
956 /* Go to HandBrake homepage and exit */
957 [self OpenHomepage: NULL];
958 [NSApp terminate: self];
963 /* Let libhb do the job */
966 /* Disable interface */
968 [fPauseButton setEnabled: NO];
969 [fRipButton setEnabled: NO];
972 - (IBAction) Cancel: (id) sender
974 NSBeginCriticalAlertSheet( _( @"Cancel - Are you sure?" ),
975 _( @"Keep working" ), _( @"Cancel encoding" ), NULL, fWindow, self,
976 @selector( _Cancel:returnCode:contextInfo: ), NULL, NULL,
977 _( @"Encoding won't be recoverable." ) );
980 - (void) _Cancel: (NSWindow *) sheet
981 returnCode: (int) returnCode contextInfo: (void *) contextInfo
983 if( returnCode == NSAlertAlternateReturn )
986 [fPauseButton setEnabled: NO];
987 [fRipButton setEnabled: NO];
991 - (IBAction) Pause: (id) sender
993 [fPauseButton setEnabled: NO];
994 [fRipButton setEnabled: NO];
996 if( [[fPauseButton title] isEqualToString: _( @"Resume" )] )
998 hb_resume( fHandle );
1002 hb_pause( fHandle );
1006 - (IBAction) TitlePopUpChanged: (id) sender
1008 hb_list_t * list = hb_get_titles( fHandle );
1009 hb_title_t * title = (hb_title_t*)
1010 hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
1013 /* Update chapter popups */
1014 [fSrcChapterStartPopUp removeAllItems];
1015 [fSrcChapterEndPopUp removeAllItems];
1016 for( int i = 0; i < hb_list_count( title->list_chapter ); i++ )
1018 [fSrcChapterStartPopUp addItemWithTitle: [NSString
1019 stringWithFormat: @"%d", i + 1]];
1020 [fSrcChapterEndPopUp addItemWithTitle: [NSString
1021 stringWithFormat: @"%d", i + 1]];
1023 [fSrcChapterStartPopUp selectItemAtIndex: 0];
1024 [fSrcChapterEndPopUp selectItemAtIndex:
1025 hb_list_count( title->list_chapter ) - 1];
1026 [self ChapterPopUpChanged: NULL];
1028 /* Start Get and set the initial pic size for display */
1029 hb_job_t * job = title->job;
1031 /*Set Source Size Fields Here */
1032 [fPicSrcWidth setStringValue: [NSString stringWithFormat:
1033 @"%d", fTitle->width]];
1034 [fPicSrcHeight setStringValue: [NSString stringWithFormat:
1035 @"%d", fTitle->height]];
1036 /* Turn Deinterlace on/off depending on the preference */
1037 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultDeinterlaceOn"] > 0)
1039 job->deinterlace = 1;
1043 job->deinterlace = 0;
1046 /* Pixel Ratio Setting */
1047 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"PixelRatio"])
1050 job->pixel_ratio = 1 ;
1054 job->pixel_ratio = 0 ;
1056 /* Run Through EncoderPopUpChanged to see if there
1057 needs to be any pic value modifications based on encoder settings */
1058 [self EncoderPopUpChanged: NULL];
1059 /* END Get and set the initial pic size for display */
1062 /* Update subtitle popups */
1063 hb_subtitle_t * subtitle;
1064 [fSubPopUp removeAllItems];
1065 [fSubPopUp addItemWithTitle: @"None"];
1066 for( int i = 0; i < hb_list_count( title->list_subtitle ); i++ )
1068 subtitle = (hb_subtitle_t *) hb_list_item( title->list_subtitle, i );
1070 /* We cannot use NSPopUpButton's addItemWithTitle because
1071 it checks for duplicate entries */
1072 [[fSubPopUp menu] addItemWithTitle: [NSString stringWithCString:
1073 subtitle->lang] action: NULL keyEquivalent: @""];
1075 [fSubPopUp selectItemAtIndex: 0];
1080 // PRI CHANGES 02/12/06
1081 NSString * audiotmppri;
1082 NSString * audiosearchpri=[[NSUserDefaults standardUserDefaults] stringForKey:@"DefaultLanguage"];
1084 // End of pri changes 02/12/06
1085 [fAudLang1PopUp removeAllItems];
1086 /* Disable second audio language until crashing is resolved*/
1087 [fAudLang2Field setEnabled: NO];
1088 [fAudLang2PopUp setEnabled: NO];
1089 [fAudLang2PopUp removeAllItems];
1090 [fAudLang1PopUp addItemWithTitle: _( @"None" )];
1091 /* Display Currently Unavailable until crash is fixed */
1092 [fAudLang2PopUp addItemWithTitle: _( @"Currently Unavailable" )];
1093 //[fAudLang2PopUp addItemWithTitle: _( @"None" )];
1094 for( int i = 0; i < hb_list_count( title->list_audio ); i++ )
1096 audio = (hb_audio_t *) hb_list_item( title->list_audio, i );
1097 // PRI CHANGES 02/12/06
1098 if (audiosearchpri!= NULL)
1100 audiotmppri=(NSString *) [NSString stringWithCString: audio->lang];
1101 // Try to find the desired default language
1102 if ([audiotmppri hasPrefix:audiosearchpri] && indxpri==0)
1107 // End of pri changes 02/12/06
1109 [[fAudLang1PopUp menu] addItemWithTitle:
1110 [NSString stringWithCString: audio->lang]
1111 action: NULL keyEquivalent: @""];
1113 [[fAudLang2PopUp menu] addItemWithTitle:
1114 [NSString stringWithCString: audio->lang]
1115 action: NULL keyEquivalent: @""];
1118 // PRI CHANGES 02/12/06
1119 if (indxpri==0) { indxpri=1; }
1120 [fAudLang1PopUp selectItemAtIndex: indxpri];
1121 // End of pri changes 02/12/06
1122 [fAudLang2PopUp selectItemAtIndex: 0];
1126 /* changing the title may have changed the audio channels on offer, so */
1127 /* check if this change means we should / should't offer 6-channel AAC extraction */
1128 [self Check6ChannelAACExtraction: sender];
1132 - (IBAction) ChapterPopUpChanged: (id) sender
1134 hb_list_t * list = hb_get_titles( fHandle );
1135 hb_title_t * title = (hb_title_t *)
1136 hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
1138 hb_chapter_t * chapter;
1139 int64_t duration = 0;
1140 for( int i = [fSrcChapterStartPopUp indexOfSelectedItem];
1141 i <= [fSrcChapterEndPopUp indexOfSelectedItem]; i++ )
1143 chapter = (hb_chapter_t *) hb_list_item( title->list_chapter, i );
1144 duration += chapter->duration;
1147 duration /= 90000; /* pts -> seconds */
1148 [fSrcDuration2Field setStringValue: [NSString stringWithFormat:
1149 @"%02lld:%02lld:%02lld", duration / 3600, ( duration / 60 ) % 60,
1152 [self CalculateBitrate: sender];
1155 - (IBAction) FormatPopUpChanged: (id) sender
1157 NSString * string = [fDstFile2Field stringValue];
1158 int format = [fDstFormatPopUp indexOfSelectedItem];
1161 /* Update the codecs popup */
1162 [fDstCodecsPopUp removeAllItems];
1166 /*Get Default MP4 File Extension*/
1167 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultMpegName"] > 0)
1175 [fDstCodecsPopUp addItemWithTitle:
1176 _( @"MPEG-4 Video / AAC Audio" )];
1177 [fDstCodecsPopUp addItemWithTitle:
1178 _( @"AVC/H.264 Video / AAC Audio" )];
1182 [fDstCodecsPopUp addItemWithTitle:
1183 _( @"MPEG-4 Video / MP3 Audio" )];
1184 [fDstCodecsPopUp addItemWithTitle:
1185 _( @"MPEG-4 Video / AC-3 Audio" )];
1186 [fDstCodecsPopUp addItemWithTitle:
1187 _( @"AVC/H.264 Video / MP3 Audio" )];
1188 [fDstCodecsPopUp addItemWithTitle:
1189 _( @"AVC/H.264 Video / AC-3 Audio" )];
1193 [fDstCodecsPopUp addItemWithTitle:
1194 _( @"MPEG-4 Video / Vorbis Audio" )];
1195 [fDstCodecsPopUp addItemWithTitle:
1196 _( @"MPEG-4 Video / MP3 Audio" )];
1199 [self CodecsPopUpChanged: NULL];
1201 /* Add/replace to the correct extension */
1202 if( [string characterAtIndex: [string length] - 4] == '.' )
1204 [fDstFile2Field setStringValue: [NSString stringWithFormat:
1205 @"%@.%s", [string substringToIndex: [string length] - 4],
1210 [fDstFile2Field setStringValue: [NSString stringWithFormat:
1211 @"%@.%s", string, ext]];
1214 /* changing the codecs on offer may mean that we are/aren't now offering AAC, so */
1215 /* check if this change means we should / should't offer 6-channel AAC extraction */
1216 [self Check6ChannelAACExtraction: sender];
1220 - (IBAction) CodecsPopUpChanged: (id) sender
1222 int format = [fDstFormatPopUp indexOfSelectedItem];
1223 int codecs = [fDstCodecsPopUp indexOfSelectedItem];
1225 /* Update the encoder popup */
1226 if( ( FormatSettings[format][codecs] & HB_VCODEC_X264 ) )
1228 /* MPEG-4 -> H.264 */
1229 [fVidEncoderPopUp removeAllItems];
1230 [fVidEncoderPopUp addItemWithTitle: @"x264 (h.264 Main)"];
1231 [fVidEncoderPopUp addItemWithTitle: @"x264 (h.264 iPod)"];
1235 else if( ( FormatSettings[format][codecs] & HB_VCODEC_FFMPEG ) )
1237 /* H.264 -> MPEG-4 */
1238 [fVidEncoderPopUp removeAllItems];
1239 [fVidEncoderPopUp addItemWithTitle: @"FFmpeg"];
1240 [fVidEncoderPopUp addItemWithTitle: @"XviD"];
1241 [fVidEncoderPopUp selectItemAtIndex: 0];
1244 if( FormatSettings[format][codecs] & HB_ACODEC_AC3 )
1246 /* AC-3 pass-through: disable samplerate and bitrate */
1247 [fAudRatePopUp setEnabled: NO];
1248 [fAudBitratePopUp setEnabled: NO];
1252 [fAudRatePopUp setEnabled: YES];
1253 [fAudBitratePopUp setEnabled: YES];
1256 /* check if this change means we should / should't offer 6-channel AAC extraction */
1257 [self Check6ChannelAACExtraction: sender];
1259 [self CalculateBitrate: sender];
1263 - (IBAction) EncoderPopUpChanged: (id) sender
1266 /* Check to see if we need to modify the job pic values based on x264 (iPod) encoder selection */
1267 if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [fDstCodecsPopUp indexOfSelectedItem] == 1 && [fVidEncoderPopUp indexOfSelectedItem] == 1)
1269 hb_job_t * job = fTitle->job;
1270 job->pixel_ratio = 0 ;
1272 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPicSizeAutoiPod"] > 0)
1275 if (fTitle->job->width > 640)
1277 fTitle->job->width = 640;
1279 fTitle->job->keep_ratio = 1;
1280 hb_fix_aspect( job, HB_KEEP_WIDTH );
1284 /* uncheck the "export 5.1 as 6-channel AAC" checkbox if it is checked */
1285 [fAudLang1SurroundCheck setState: NSOffState];
1289 [self CalculatePictureSizing: sender];
1293 - (IBAction) Check6ChannelAACExtraction: (id) sender
1296 /* make sure we have a selected title before continuing */
1297 if (fTitle == NULL) return;
1299 /* get the current title's job into a convenience variable */
1300 hb_job_t * job = fTitle->job;
1302 /* get the current audio tracks */
1303 /* this is done in PrepareJob too, but we want them here to check against below */
1304 job->audios[0] = [fAudLang1PopUp indexOfSelectedItem] - 1;
1305 job->audios[1] = [fAudLang2PopUp indexOfSelectedItem] - 1;
1306 job->audios[2] = -1;
1308 /* now, let's check if any selected audio track has 5.1 sound */
1310 bool foundfiveoneaudio = false;
1312 /* find out what the currently-selected audio codec is */
1313 int format = [fDstFormatPopUp indexOfSelectedItem];
1314 int codecs = [fDstCodecsPopUp indexOfSelectedItem];
1315 int acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
1317 /* we only offer the option to extract 5.1 to 6-channel if the selected audio codec is AAC */
1318 if (acodec == HB_ACODEC_FAAC) {
1320 bool doneaudios = false;
1323 while (!doneaudios) {
1325 if (job->audios[thisaudio] == -1) {
1328 audio = (hb_audio_t *) hb_list_item( fTitle->list_audio, job->audios[thisaudio] );
1329 if (audio != NULL) {
1330 if (audio->channels == 5 && audio->lfechannels == 1) {
1331 foundfiveoneaudio = true;
1332 doneaudios = true; /* as it doesn't matter if we find any more! */
1341 /* If we are extracting to AAC, and any of our soundtracks were 5.1, then enable the checkbox */
1342 if (foundfiveoneaudio) {
1343 [fAudLang1SurroundCheck setEnabled: YES];
1344 /* Check default surround sound pref and if it is YES, lets also check the checkbox */
1345 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultSurroundSound"] > 0)
1347 [fAudLang1SurroundCheck setState: NSOnState];
1350 [fAudLang1SurroundCheck setEnabled: NO];
1351 /* as well as disabling the checkbox, let's uncheck it if it is checked */
1352 [fAudLang1SurroundCheck setState: NSOffState];
1358 - (IBAction) LanguagePopUpChanged: (id) sender
1361 /* selecting a different language may mean we have a different number of channels, so */
1362 /* check if this change means we should / should't offer 6-channel AAC extraction */
1363 [self Check6ChannelAACExtraction: sender];
1365 /* see if the new language setting will change the bitrate we need */
1366 [self CalculateBitrate: sender];
1371 /* Get and Display Current Pic Settings in main window */
1372 - (IBAction) CalculatePictureSizing: (id) sender
1375 hb_job_t * job = fTitle->job;
1377 [fPicSettingWidth setStringValue: [NSString stringWithFormat:
1378 @"%d", fTitle->job->width]];
1379 [fPicSettingHeight setStringValue: [NSString stringWithFormat:
1380 @"%d", fTitle->job->height]];
1381 [fPicSettingARkeep setStringValue: [NSString stringWithFormat:
1382 @"%d", fTitle->job->keep_ratio]];
1383 [fPicSettingDeinterlace setStringValue: [NSString stringWithFormat:
1384 @"%d", fTitle->job->deinterlace]];
1385 [fPicSettingPAR setStringValue: [NSString stringWithFormat:
1386 @"%d", fTitle->job->pixel_ratio]];
1388 if (fTitle->job->pixel_ratio == 1)
1390 int titlewidth = fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3];
1391 int arpwidth = fTitle->job->pixel_aspect_width;
1392 int arpheight = fTitle->job->pixel_aspect_height;
1393 int displayparwidth = titlewidth * arpwidth / arpheight;
1394 int displayparheight = fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1];
1395 [fPicLabelPAROutp setStringValue: @"Anamorphic Output:"];
1396 [fPicLabelPAROutputX setStringValue: @"x"];
1397 [fPicSettingPARWidth setStringValue: [NSString stringWithFormat:
1398 @"%d", displayparwidth]];
1399 [fPicSettingPARHeight setStringValue: [NSString stringWithFormat:
1400 @"%d", displayparheight]];
1401 [fPicSettingHeight setStringValue: [NSString stringWithFormat:
1402 @"%d", displayparheight]];
1403 fTitle->job->keep_ratio = 0;
1407 [fPicLabelPAROutp setStringValue: @""];
1408 [fPicLabelPAROutputX setStringValue: @""];
1409 [fPicSettingPARWidth setStringValue: @""];
1410 [fPicSettingPARHeight setStringValue: @""];
1413 /* Set ON/Off values for the deinterlace/keep aspect ratio according to boolean */
1414 if (fTitle->job->keep_ratio > 0)
1416 [fPicSettingARkeepDsply setStringValue: @"On"];
1420 [fPicSettingARkeepDsply setStringValue: @"Off"];
1422 if (fTitle->job->deinterlace > 0)
1424 [fPicSettingDeinterlaceDsply setStringValue: @"On"];
1428 [fPicSettingDeinterlaceDsply setStringValue: @"Off"];
1430 if (fTitle->job->pixel_ratio > 0)
1432 [fPicSettingPARDsply setStringValue: @"On"];
1436 [fPicSettingPARDsply setStringValue: @"Off"];
1442 - (IBAction) CalculateBitrate: (id) sender
1444 if( !fHandle || [fVidQualityMatrix selectedRow] != 0 )
1449 hb_list_t * list = hb_get_titles( fHandle );
1450 hb_title_t * title = (hb_title_t *) hb_list_item( list,
1451 [fSrcTitlePopUp indexOfSelectedItem] );
1452 hb_job_t * job = title->job;
1456 [fVidBitrateField setIntValue: hb_calc_bitrate( job,
1457 [fVidTargetSizeField intValue] )];
1460 - (IBAction) ShowAddPresetPanel: (id) sender
1462 /* Show the panel */
1463 [NSApp beginSheet: fAddPresetPanel modalForWindow: fWindow
1464 modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
1465 [NSApp runModalForWindow: fAddPresetPanel];
1466 [NSApp endSheet: fAddPresetPanel];
1467 [fAddPresetPanel orderOut: self];
1469 - (IBAction) CloseAddPresetPanel: (id) sender
1474 - (IBAction)addPreset:(id)sender
1476 [UserPresets addObject:[self CreatePreset]];
1477 /* We Sort the Presets Alphabetically by name */
1478 NSSortDescriptor * lastNameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"PresetName"
1479 ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease];
1480 NSArray *sortDescriptors=[NSArray arrayWithObject:lastNameDescriptor];
1481 NSArray *sortedArray=[UserPresets sortedArrayUsingDescriptors:sortDescriptors];
1482 [UserPresets setArray:sortedArray];
1484 /* We stop the modal window for the new preset */
1485 [fPresetNewName setStringValue: @""];
1487 /* We Reload the New Table data for presets */
1488 [tableView reloadData];
1489 /* We save all of the preset data here */
1493 - (IBAction)insertPreset:(id)sender
1495 int index = [tableView selectedRow];
1496 [UserPresets insertObject:[self CreatePreset] atIndex:index];
1497 [tableView reloadData];
1501 - (NSDictionary *)CreatePreset
1503 NSMutableDictionary *preset = [[NSMutableDictionary alloc] init];
1504 /* Get the New Preset Name from the field in the AddPresetPanel */
1505 [preset setObject:[fPresetNewName stringValue] forKey:@"PresetName"];
1506 /*Get the whether or not to apply pic settings in the AddPresetPanel*/
1507 [preset setObject:[NSNumber numberWithInt:[fPresetNewPicSettingsApply state]] forKey:@"UsesPictureSettings"];
1509 [preset setObject:[fDstFormatPopUp titleOfSelectedItem] forKey:@"FileFormat"];
1511 [preset setObject:[fDstCodecsPopUp titleOfSelectedItem] forKey:@"FileCodecs"];
1513 [preset setObject:[fVidEncoderPopUp titleOfSelectedItem] forKey:@"VideoEncoder"];
1515 [preset setObject:[NSNumber numberWithInt:[fVidQualityMatrix selectedRow]] forKey:@"VideoQualityType"];
1516 [preset setObject:[fVidTargetSizeField stringValue] forKey:@"VideoTargetSize"];
1517 [preset setObject:[fVidBitrateField stringValue] forKey:@"VideoAvgBitrate"];
1518 [preset setObject:[NSNumber numberWithFloat:[fVidQualitySlider floatValue]] forKey:@"VideoQualitySlider"];
1520 /* Video framerate */
1521 [preset setObject:[fVidRatePopUp titleOfSelectedItem] forKey:@"VideoFramerate"];
1523 [preset setObject:[NSNumber numberWithInt:[fVidGrayscaleCheck state]] forKey:@"VideoGrayScale"];
1524 /* 2 Pass Encoding */
1525 [preset setObject:[NSNumber numberWithInt:[fVidTwoPassCheck state]] forKey:@"VideoTwoPass"];
1527 /*Picture Settings*/
1528 hb_job_t * job = fTitle->job;
1529 /* Basic Picture Settings */
1530 [preset setObject:[NSNumber numberWithInt:fTitle->job->width] forKey:@"PictureWidth"];
1531 [preset setObject:[NSNumber numberWithInt:fTitle->job->height] forKey:@"PictureHeight"];
1532 [preset setObject:[NSNumber numberWithInt:fTitle->job->keep_ratio] forKey:@"PictureKeepRatio"];
1533 [preset setObject:[NSNumber numberWithInt:fTitle->job->deinterlace] forKey:@"PictureDeinterlace"];
1534 [preset setObject:[NSNumber numberWithInt:fTitle->job->pixel_ratio] forKey:@"PicturePAR"];
1535 /* Set crop settings here */
1536 /* The Auto Crop Matrix in the Picture Window autodetects differences in crop settings */
1537 [preset setObject:[NSNumber numberWithInt:job->crop[0]] forKey:@"PictureTopCrop"];
1538 [preset setObject:[NSNumber numberWithInt:job->crop[1]] forKey:@"PictureBottomCrop"];
1539 [preset setObject:[NSNumber numberWithInt:job->crop[2]] forKey:@"PictureLeftCrop"];
1540 [preset setObject:[NSNumber numberWithInt:job->crop[3]] forKey:@"PictureRightCrop"];
1543 /* Audio Language One*/
1544 [preset setObject:[fAudLang1PopUp titleOfSelectedItem] forKey:@"AudioLang1"];
1545 /* Audio Language One Surround Sound Checkbox*/
1546 [preset setObject:[NSNumber numberWithInt:[fAudLang1SurroundCheck state]] forKey:@"AudioLang1Surround"];
1547 /* Audio Sample Rate*/
1548 [preset setObject:[fAudRatePopUp titleOfSelectedItem] forKey:@"AudioSampleRate"];
1549 /* Audio Bitrate Rate*/
1550 [preset setObject:[fAudBitratePopUp titleOfSelectedItem] forKey:@"AudioBitRate"];
1552 [preset setObject:[fSubPopUp titleOfSelectedItem] forKey:@"Subtitles"];
1555 [preset autorelease];
1560 - (IBAction)deletePreset:(id)sender
1563 NSEnumerator *enumerator;
1565 NSMutableArray *tempArray;
1568 if ( [tableView numberOfSelectedRows] == 0 )
1570 /* Alert user before deleting preset */
1571 /* Comment out for now, tie to user pref eventually */
1573 status = NSRunAlertPanel(@"Warning!", @"Are you sure that you want to delete the selected preset?", @"OK", @"Cancel", nil);
1575 if ( status == NSAlertDefaultReturn ) {
1576 enumerator = [tableView selectedRowEnumerator];
1577 tempArray = [NSMutableArray array];
1579 while ( (index = [enumerator nextObject]) ) {
1580 tempObject = [UserPresets objectAtIndex:[index intValue]];
1581 [tempArray addObject:tempObject];
1584 [UserPresets removeObjectsInArray:tempArray];
1585 [tableView reloadData];
1589 - (IBAction)tableViewSelected:(id)sender
1592 /* we get the chosen preset from the UserPresets array */
1593 chosenPreset = [UserPresets objectAtIndex:[sender selectedRow]];
1594 /* we set the preset display field in main window here */
1595 //[fPresetSelectedDisplay setStringValue: [NSString stringWithFormat: @"%@", [chosenPreset valueForKey:@"PresetName"]]];
1597 [fDstFormatPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"FileFormat"]]];
1598 [self FormatPopUpChanged: NULL];
1600 [fDstCodecsPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"FileCodecs"]]];
1601 [self CodecsPopUpChanged: NULL];
1603 [fVidEncoderPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoEncoder"]]];
1604 /* Lets run through the following functions to get variables set there */
1605 [self EncoderPopUpChanged: sender];
1606 [self Check6ChannelAACExtraction: sender];
1607 [self CalculateBitrate: sender];
1610 [fVidQualityMatrix selectCellAtRow:[[chosenPreset objectForKey:@"VideoQualityType"] intValue] column:0];
1612 [fVidTargetSizeField setStringValue: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoTargetSize"]]];
1613 [fVidBitrateField setStringValue: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoAvgBitrate"]]];
1615 [fVidQualitySlider setFloatValue: [[chosenPreset valueForKey:@"VideoQualitySlider"] floatValue]];
1616 [self VideoMatrixChanged: sender];
1618 /* Video framerate */
1619 [fVidRatePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"VideoFramerate"]]];
1622 [fVidGrayscaleCheck setState:[[chosenPreset objectForKey:@"VideoGrayScale"] intValue]];
1624 /* 2 Pass Encoding */
1625 [fVidTwoPassCheck setState:[[chosenPreset objectForKey:@"VideoTwoPass"] intValue]];
1629 /* Audio Language One*/
1630 [fAudLang1PopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"AudioLang1"]]];
1631 /* Audio Language One Surround Sound Checkbox*/
1632 [fAudLang1SurroundCheck setState:[[chosenPreset objectForKey:@"AudioLang1Surround"] intValue]];
1633 [self Check6ChannelAACExtraction: sender];
1634 /* Audio Sample Rate*/
1635 [fAudRatePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"AudioSampleRate"]]];
1636 /* Audio Bitrate Rate*/
1637 [fAudBitratePopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"AudioBitRate"]]];
1639 [fSubPopUp selectItemWithTitle: [NSString stringWithFormat:[chosenPreset valueForKey:@"Subtitles"]]];
1641 /* Picture Settings */
1642 /* Look to see if we apply these here in objectForKey:@"UsesPictureSettings"] */
1643 if ([[chosenPreset objectForKey:@"UsesPictureSettings"] intValue] == 1)
1645 hb_job_t * job = fTitle->job;
1646 job->width = [[chosenPreset objectForKey:@"PictureWidth"] intValue];
1647 job->height = [[chosenPreset objectForKey:@"PictureHeight"] intValue];
1648 job->keep_ratio = [[chosenPreset objectForKey:@"PictureKeepRatio"] intValue];
1649 if (job->keep_ratio == 1)
1651 hb_fix_aspect( job, HB_KEEP_WIDTH );
1653 job->pixel_ratio = [[chosenPreset objectForKey:@"PicturePAR"] intValue];
1654 job->crop[0] = [[chosenPreset objectForKey:@"PictureTopCrop"] intValue];
1655 job->crop[1] = [[chosenPreset objectForKey:@"PictureBottomCrop"] intValue];
1656 job->crop[2] = [[chosenPreset objectForKey:@"PictureLeftCrop"] intValue];
1657 job->crop[3] = [[chosenPreset objectForKey:@"PictureRightCrop"] intValue];
1658 [self CalculatePictureSizing: sender];
1661 // Deselect the currently selected table //
1662 //[tableView deselectRow:[tableView selectedRow]];
1665 - (int)numberOfRowsInTableView:(NSTableView *)aTableView
1667 return [UserPresets count];
1670 - (id)tableView:(NSTableView *)aTableView
1671 objectValueForTableColumn:(NSTableColumn *)aTableColumn
1677 id theRecord, theValue;
1679 theRecord = [UserPresets objectAtIndex:rowIndex];
1680 theValue = [theRecord objectForKey:[aTableColumn identifier]];
1685 // NSTableDataSource method that we implement to edit values directly in the table...
1686 - (void)tableView:(NSTableView *)aTableView
1687 setObjectValue:(id)anObject
1688 forTableColumn:(NSTableColumn *)aTableColumn
1693 theRecord = [UserPresets objectAtIndex:rowIndex];
1694 [theRecord setObject:anObject forKey:[aTableColumn identifier]];
1696 /* We Sort the Presets Alphabetically by name */
1697 NSSortDescriptor * lastNameDescriptor=[[[NSSortDescriptor alloc] initWithKey:@"PresetName"
1698 ascending:YES selector:@selector(caseInsensitiveCompare:)] autorelease];
1699 NSArray *sortDescriptors=[NSArray arrayWithObject:lastNameDescriptor];
1700 NSArray *sortedArray=[UserPresets sortedArrayUsingDescriptors:sortDescriptors];
1701 [UserPresets setArray:sortedArray];
1702 /* We Reload the New Table data for presets */
1703 [tableView reloadData];
1704 /* We save all of the preset data here */
1711 [UserPresets writeToFile:UserPresetsFile atomically:YES];
1717 - (void) controlTextDidBeginEditing: (NSNotification *) notification
1719 [self CalculateBitrate: NULL];
1722 - (void) controlTextDidEndEditing: (NSNotification *) notification
1724 [self CalculateBitrate: NULL];
1727 - (void) controlTextDidChange: (NSNotification *) notification
1729 [self CalculateBitrate: NULL];
1732 - (IBAction) OpenHomepage: (id) sender
1734 [[NSWorkspace sharedWorkspace] openURL: [NSURL
1735 URLWithString:@"http://handbrake.m0k.org/"]];
1738 - (IBAction) OpenForums: (id) sender
1740 [[NSWorkspace sharedWorkspace] openURL: [NSURL
1741 URLWithString:@"http://handbrake.m0k.org/forum/"]];