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 */
61 /* TEMPORARILY COMMENT OUT AS UPDATE CHECK IS NOT ACCURATE */
63 NSBeginInformationalAlertSheet( _( @"Update is available" ),
64 _( @"Go get it!" ), _( @"Discard" ), NULL, fWindow, self,
65 @selector( UpdateAlertDone:returnCode:contextInfo: ),
66 NULL, NULL, [NSString stringWithFormat:
67 _( @"HandBrake %s (build %d) is now available for download." ),
73 /* Show scan panel ASAP */
74 [self performSelectorOnMainThread: @selector(ShowScanPanel:)
75 withObject: NULL waitUntilDone: NO];
78 - (NSApplicationTerminateReply) applicationShouldTerminate:
81 if( [[fRipButton title] isEqualToString: _( @"Cancel" )] )
84 return NSTerminateCancel;
89 return NSTerminateNow;
96 [self TranslateStrings];
99 [fDstFormatPopUp removeAllItems];
100 [fDstFormatPopUp addItemWithTitle: _( @"MP4 file" )];
101 [fDstFormatPopUp addItemWithTitle: _( @"AVI file" )];
102 [fDstFormatPopUp addItemWithTitle: _( @"OGM file" )];
103 [fDstFormatPopUp selectItemAtIndex: 0];
105 [self FormatPopUpChanged: NULL];
107 [fDstFile2Field setStringValue: [NSString stringWithFormat:
108 @"%@/Desktop/Movie.mp4", NSHomeDirectory()]];
111 [fVidEncoderPopUp removeAllItems];
112 [fVidEncoderPopUp addItemWithTitle: @"FFmpeg"];
113 [fVidEncoderPopUp addItemWithTitle: @"XviD"];
116 [fVidTargetSizeField setIntValue: 700];
117 [fVidBitrateField setIntValue: 1000];
118 /* Do we want to force the quality settings if PAR is on ?
119 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"PixelRatio"])
121 [fVidBitrateField setIntValue: 1500];
122 [fVidTwoPassCheck setState: NSOnState];
126 [fVidBitrateField setIntValue: 1000];
129 [fVidQualityMatrix selectCell: fVidBitrateCell];
130 [self VideoMatrixChanged: NULL];
132 /* Video framerate */
133 [fVidRatePopUp removeAllItems];
134 [fVidRatePopUp addItemWithTitle: _( @"Same as source" )];
135 for( int i = 0; i < hb_video_rates_count; i++ )
137 [fVidRatePopUp addItemWithTitle:
138 [NSString stringWithCString: hb_video_rates[i].string]];
140 [fVidRatePopUp selectItemAtIndex: 0];
142 /* Picture Settings */
143 [fPicLabelPAROutp setStringValue: @""];
144 [fPicLabelPAROutputX setStringValue: @""];
145 [fPicSettingPARWidth setStringValue: @""];
146 [fPicSettingPARHeight setStringValue: @""];
149 [fAudBitratePopUp removeAllItems];
150 for( int i = 0; i < hb_audio_bitrates_count; i++ )
152 [fAudBitratePopUp addItemWithTitle:
153 [NSString stringWithCString: hb_audio_bitrates[i].string]];
155 [fAudBitratePopUp selectItemAtIndex: hb_audio_bitrates_default];
157 /* Audio samplerate */
158 [fAudRatePopUp removeAllItems];
159 for( int i = 0; i < hb_audio_rates_count; i++ )
161 [fAudRatePopUp addItemWithTitle:
162 [NSString stringWithCString: hb_audio_rates[i].string]];
164 [fAudRatePopUp selectItemAtIndex: hb_audio_rates_default];
167 [fStatusField setStringValue: @""];
170 [fPauseButton setEnabled: NO];
171 [fRipButton setEnabled: NO];
174 - (void) TranslateStrings
176 [fSrcDVD1Field setStringValue: _( @"DVD:" )];
177 [fSrcTitleField setStringValue: _( @"Title:" )];
178 [fSrcChapterField setStringValue: _( @"Chapters:" )];
179 [fSrcChapterToField setStringValue: _( @"to" )];
180 [fSrcDuration1Field setStringValue: _( @"Duration:" )];
182 [fDstFormatField setStringValue: _( @"File format:" )];
183 [fDstCodecsField setStringValue: _( @"Codecs:" )];
184 [fDstFile1Field setStringValue: _( @"File:" )];
185 [fDstBrowseButton setTitle: _( @"Browse" )];
187 [fVidRateField setStringValue: _( @"Framerate (fps):" )];
188 [fVidEncoderField setStringValue: _( @"Encoder:" )];
189 [fVidQualityField setStringValue: _( @"Quality:" )];
192 /***********************************************************************
194 ***********************************************************************
195 * Shows a progression bar on the dock icon, filled according to
196 * 'progress' (0.0 <= progress <= 1.0).
197 * Called with progress < 0.0 or progress > 1.0, restores the original
199 **********************************************************************/
200 - (void) UpdateDockIcon: (float) progress
204 NSBitmapImageRep * bmp;
206 uint32_t black = htonl( 0x000000FF );
207 uint32_t red = htonl( 0xFF0000FF );
208 uint32_t white = htonl( 0xFFFFFFFF );
209 int row_start, row_end;
212 /* Get application original icon */
213 icon = [NSImage imageNamed: @"NSApplicationIcon"];
215 if( progress < 0.0 || progress > 1.0 )
217 [NSApp setApplicationIconImage: icon];
221 /* Get it in a raw bitmap form */
222 tiff = [icon TIFFRepresentationUsingCompression:
223 NSTIFFCompressionNone factor: 1.0];
224 bmp = [NSBitmapImageRep imageRepWithData: tiff];
226 /* Draw the progression bar */
227 /* It's pretty simple (ugly?) now, but I'm no designer */
229 row_start = 3 * (int) [bmp size].height / 4;
230 row_end = 7 * (int) [bmp size].height / 8;
232 for( i = row_start; i < row_start + 2; i++ )
234 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
235 for( j = 0; j < (int) [bmp size].width; j++ )
240 for( i = row_start + 2; i < row_end - 2; i++ )
242 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
245 for( j = 2; j < (int) [bmp size].width - 2; j++ )
247 if( j < 2 + (int) ( ( [bmp size].width - 4.0 ) * progress ) )
259 for( i = row_end - 2; i < row_end; i++ )
261 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
262 for( j = 0; j < (int) [bmp size].width; j++ )
268 /* Now update the dock icon */
269 tiff = [bmp TIFFRepresentationUsingCompression:
270 NSTIFFCompressionNone factor: 1.0];
271 icon = [[NSImage alloc] initWithData: tiff];
272 [NSApp setApplicationIconImage: icon];
276 - (void) UpdateUI: (NSTimer *) timer
280 hb_get_state( fHandle, &s );
287 case HB_STATE_SCANNING:
288 [fScanController UpdateUI: &s];
291 #define p s.param.scandone
292 case HB_STATE_SCANDONE:
296 int indxpri=0; // Used to search the longuest title (default in combobox)
297 int longuestpri=0; // Used to search the longuest title (default in combobox)
299 [fScanController UpdateUI: &s];
301 list = hb_get_titles( fHandle );
303 if( !hb_list_count( list ) )
309 [fSrcTitlePopUp removeAllItems];
310 for( int i = 0; i < hb_list_count( list ); i++ )
312 title = (hb_title_t *) hb_list_item( list, i );
313 /*Set DVD Name at top of window*/
314 [fSrcDVD2Field setStringValue: [NSString
315 stringWithUTF8String: title->name]];
317 /* Use the dvd name in the default output field here
318 May want to add code to remove blank spaces for some dvd names*/
320 [fDstFile2Field setStringValue: [NSString stringWithFormat:
321 @"%@/Desktop/%@.mp4", NSHomeDirectory(),[NSString
322 stringWithUTF8String: title->name]]];
323 /* Temporarily comment out to fix title selection*/
324 if (longuestpri < title->hours*60*60 + title->minutes *60 + title->seconds)
326 longuestpri=title->hours*60*60 + title->minutes *60 + title->seconds;
331 int format = [fDstFormatPopUp indexOfSelectedItem];
337 /*Get Default MP4 File Extension for mpeg4 (.mp4 or .m4v) from prefs*/
338 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultMpegName"] > 0)
356 NSString * string = [fDstFile2Field stringValue];
357 /* Add/replace File Output name to the correct extension*/
358 if( [string characterAtIndex: [string length] - 4] == '.' )
360 [fDstFile2Field setStringValue: [NSString stringWithFormat:
361 @"%@.%s", [string substringToIndex: [string length] - 4],
366 [fDstFile2Field setStringValue: [NSString stringWithFormat:
367 @"%@.%s", string, ext]];
371 [fSrcTitlePopUp addItemWithTitle: [NSString
372 stringWithFormat: @"%d - %02dh%02dm%02ds",
373 title->index, title->hours, title->minutes,
377 // Select the longuest title
378 [fSrcTitlePopUp selectItemAtIndex: indxpri];
380 [self TitlePopUpChanged: NULL];
381 [self EnableUI: YES];
382 [fPauseButton setEnabled: NO];
383 [fRipButton setEnabled: YES];
388 #define p s.param.working
389 case HB_STATE_WORKING:
391 float progress_total;
392 NSMutableString * string;
394 /* Update text field */
395 string = [NSMutableString stringWithFormat:
396 _( @"Encoding: task %d of %d, %.2f %%" ),
397 p.job_cur, p.job_count, 100.0 * p.progress];
400 [string appendFormat:
401 _( @" (%.2f fps, avg %.2f fps, ETA %02dh%02dm%02ds)" ),
402 p.rate_cur, p.rate_avg, p.hours, p.minutes, p.seconds];
404 [fStatusField setStringValue: string];
407 progress_total = ( p.progress + p.job_cur - 1 ) / p.job_count;
408 [fRipIndicator setIndeterminate: NO];
409 [fRipIndicator setDoubleValue: 100.0 * progress_total];
411 /* Update dock icon */
412 [self UpdateDockIcon: progress_total];
414 [fPauseButton setEnabled: YES];
415 [fPauseButton setTitle: _( @"Pause" )];
416 [fRipButton setEnabled: YES];
417 [fRipButton setTitle: _( @"Cancel" )];
422 #define p s.param.muxing
423 case HB_STATE_MUXING:
425 NSMutableString * string;
427 /* Update text field */
428 string = [NSMutableString stringWithFormat:
430 [fStatusField setStringValue: string];
433 [fRipIndicator setIndeterminate: YES];
434 [fRipIndicator startAnimation: nil];
436 /* Update dock icon */
437 [self UpdateDockIcon: 1.0];
439 [fPauseButton setEnabled: YES];
440 [fPauseButton setTitle: _( @"Pause" )];
441 [fRipButton setEnabled: YES];
442 [fRipButton setTitle: _( @"Cancel" )];
447 case HB_STATE_PAUSED:
448 [fStatusField setStringValue: _( @"Paused" )];
449 [fPauseButton setEnabled: YES];
450 [fPauseButton setTitle: _( @"Resume" )];
451 [fRipButton setEnabled: YES];
452 [fRipButton setTitle: _( @"Cancel" )];
455 case HB_STATE_WORKDONE:
457 [self EnableUI: YES];
458 [fStatusField setStringValue: _( @"Done." )];
459 [fRipIndicator setIndeterminate: NO];
460 [fRipIndicator setDoubleValue: 0.0];
461 [fRipButton setTitle: _( @"Rip" )];
463 /* Restore dock icon */
464 [self UpdateDockIcon: -1.0];
466 [fPauseButton setEnabled: NO];
467 [fPauseButton setTitle: _( @"Pause" )];
468 [fRipButton setEnabled: YES];
469 [fRipButton setTitle: _( @"Rip" )];
473 while( ( job = hb_job( fHandle, 0 ) ) )
475 hb_rem( fHandle, job );
481 /* FIXME: we should only do that when necessary */
482 if( [fQueueCheck state] == NSOnState )
484 int count = hb_count( fHandle );
487 [fQueueCheck setTitle: [NSString stringWithFormat:
488 @"Enable queue (%d task%s in queue)",
489 count, ( count > 1 ) ? "s" : ""]];
493 [fQueueCheck setTitle: @"Enable queue (no task in queue)"];
497 [[NSRunLoop currentRunLoop] addTimer: [NSTimer
498 scheduledTimerWithTimeInterval: 0.2 target: self
499 selector: @selector( UpdateUI: ) userInfo: NULL repeats: FALSE]
500 forMode: NSModalPanelRunLoopMode];
503 - (void) EnableUI: (bool) b
505 NSControl * controls[] =
506 { fSrcDVD1Field, fSrcDVD2Field, fSrcTitleField, fSrcTitlePopUp,
507 fSrcChapterField, fSrcChapterStartPopUp, fSrcChapterToField,
508 fSrcChapterEndPopUp, fSrcDuration1Field, fSrcDuration2Field,
509 fDstFormatField, fDstFormatPopUp, fDstCodecsField,
510 fDstCodecsPopUp, fDstFile1Field, fDstFile2Field,
511 fDstBrowseButton, fVidRateField, fVidRatePopUp,
512 fVidEncoderField, fVidEncoderPopUp, fVidQualityField,
513 fVidQualityMatrix, fVidGrayscaleCheck, fSubField, fSubPopUp,
514 fAudLang1Field, fAudLang1PopUp, fAudLang2Field, fAudLang2PopUp,
515 fAudRateField, fAudRatePopUp, fAudBitrateField,
516 fAudBitratePopUp, fPictureButton, fQueueCheck,
517 fPicSrcWidth,fPicSrcHeight,fPicSettingWidth,fPicSettingHeight,
518 fPicSettingARkeep,fPicSettingDeinterlace,fPicSettingARkeepDsply,
519 fPicSettingDeinterlaceDsply,fPicLabelSettings,fPicLabelSrc,fPicLabelOutp,
520 fPicLabelAr,fPicLabelDeinter,fPicLabelSrcX,fPicLabelOutputX,
521 fPicLabelPAROutp,fPicLabelPAROutputX,fPicSettingPARWidth,fPicSettingPARHeight,
522 fPicSettingPARDsply,fPicLabelAnamorphic};
525 i < sizeof( controls ) / sizeof( NSControl * ); i++ )
527 if( [[controls[i] className] isEqualToString: @"NSTextField"] )
529 NSTextField * tf = (NSTextField *) controls[i];
530 if( ![tf isBezeled] )
532 [tf setTextColor: b ? [NSColor controlTextColor] :
533 [NSColor disabledControlTextColor]];
537 [controls[i] setEnabled: b];
538 /* Temporarily disable Lang2 until crash is fixed */
539 [fAudLang2PopUp setEnabled: NO];
540 [fAudLang2Field setEnabled: NO];
544 [self VideoMatrixChanged: NULL];
547 - (IBAction) ShowScanPanel: (id) sender
549 [fScanController Show];
552 - (BOOL) windowShouldClose: (id) sender
554 /* Stop the application when the user closes the window */
555 [NSApp terminate: self];
559 - (IBAction) VideoMatrixChanged: (id) sender;
561 bool target, bitrate, quality;
563 target = bitrate = quality = false;
564 if( [fVidQualityMatrix isEnabled] )
566 switch( [fVidQualityMatrix selectedRow] )
579 [fVidTargetSizeField setEnabled: target];
580 [fVidBitrateField setEnabled: bitrate];
581 [fVidQualitySlider setEnabled: quality];
582 [fVidTwoPassCheck setEnabled: !quality &&
583 [fVidQualityMatrix isEnabled]];
586 [fVidTwoPassCheck setState: NSOffState];
589 [self QualitySliderChanged: sender];
590 [self CalculateBitrate: sender];
593 - (IBAction) QualitySliderChanged: (id) sender
595 [fVidConstantCell setTitle: [NSString stringWithFormat:
596 _( @"Constant quality: %.0f %%" ), 100.0 *
597 [fVidQualitySlider floatValue]]];
600 - (IBAction) BrowseFile: (id) sender
602 /* Open a panel to let the user choose and update the text field */
603 NSSavePanel * panel = [NSSavePanel savePanel];
605 [panel beginSheetForDirectory: NULL file: NULL
606 modalForWindow: fWindow modalDelegate: self
607 didEndSelector: @selector( BrowseFileDone:returnCode:contextInfo: )
611 - (void) BrowseFileDone: (NSSavePanel *) sheet
612 returnCode: (int) returnCode contextInfo: (void *) contextInfo
614 if( returnCode == NSOKButton )
616 [fDstFile2Field setStringValue: [sheet filename]];
617 [self FormatPopUpChanged: NULL];
621 - (IBAction) ShowPicturePanel: (id) sender
623 hb_list_t * list = hb_get_titles( fHandle );
624 hb_title_t * title = (hb_title_t *) hb_list_item( list,
625 [fSrcTitlePopUp indexOfSelectedItem] );
627 /* Resize the panel */
629 newSize.width = 246 + title->width;
630 newSize.height = 80 + title->height;
631 [fPicturePanel setContentSize: newSize];
633 [fPictureController SetTitle: title];
635 [NSApp beginSheet: fPicturePanel modalForWindow: fWindow
636 modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
637 [NSApp runModalForWindow: fPicturePanel];
638 [NSApp endSheet: fPicturePanel];
639 [fPicturePanel orderOut: self];
640 [self CalculatePictureSizing: sender];
643 - (IBAction) ShowQueuePanel: (id) sender
645 /* Update the OutlineView */
646 [fQueueController Update: sender];
649 [NSApp beginSheet: fQueuePanel modalForWindow: fWindow
650 modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
651 [NSApp runModalForWindow: fQueuePanel];
652 [NSApp endSheet: fQueuePanel];
653 [fQueuePanel orderOut: self];
658 hb_list_t * list = hb_get_titles( fHandle );
659 hb_title_t * title = (hb_title_t *) hb_list_item( list,
660 [fSrcTitlePopUp indexOfSelectedItem] );
661 hb_job_t * job = title->job;
663 /* Chapter selection */
664 job->chapter_start = [fSrcChapterStartPopUp indexOfSelectedItem] + 1;
665 job->chapter_end = [fSrcChapterEndPopUp indexOfSelectedItem] + 1;
669 /* Format and codecs */
670 int format = [fDstFormatPopUp indexOfSelectedItem];
671 int codecs = [fDstCodecsPopUp indexOfSelectedItem];
672 job->mux = FormatSettings[format][codecs] & HB_MUX_MASK;
673 job->vcodec = FormatSettings[format][codecs] & HB_VCODEC_MASK;
674 job->acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
676 if( ( job->vcodec & HB_VCODEC_FFMPEG ) &&
677 [fVidEncoderPopUp indexOfSelectedItem] > 0 )
679 job->vcodec = HB_VCODEC_XVID;
681 if( job->vcodec & HB_VCODEC_X264 )
683 if ([fVidEncoderPopUp indexOfSelectedItem] > 0 )
685 /* Just use new Baseline Level 3.0
686 Lets Deprecate Baseline Level 1.3*/
687 job->h264_level = 30;
688 job->mux = HB_MUX_IPOD;
689 /* move sanity check for iPod Encoding here */
690 job->pixel_ratio = 0 ;
694 /* Set this flag to switch from Constant Quantizer(default) to Constant Rate Factor Thanks jbrjake
695 Currently only used with Constant Quality setting*/
696 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultCrf"] > 0 && [fVidQualityMatrix selectedRow] == 2)
698 /* Can only be used with svn rev >= 89 */
702 job->h264_13 = [fVidEncoderPopUp indexOfSelectedItem];
706 if( [fVidRatePopUp indexOfSelectedItem] > 0 )
708 job->vrate = 27000000;
709 job->vrate_base = hb_video_rates[[fVidRatePopUp
710 indexOfSelectedItem]-1].rate;
714 job->vrate = title->rate;
715 job->vrate_base = title->rate_base;
718 switch( [fVidQualityMatrix selectedRow] )
722 Bitrate should already have been calculated and displayed
723 in fVidBitrateField, so let's just use it */
725 job->vquality = -1.0;
726 job->vbitrate = [fVidBitrateField intValue];
729 job->vquality = [fVidQualitySlider floatValue];
734 job->grayscale = ( [fVidGrayscaleCheck state] == NSOnState );
738 /* Subtitle settings */
739 job->subtitle = [fSubPopUp indexOfSelectedItem] - 1;
742 job->audios[0] = [fAudLang1PopUp indexOfSelectedItem] - 1;
743 job->audios[1] = [fAudLang2PopUp indexOfSelectedItem] - 1;
747 job->arate = hb_audio_rates[[fAudRatePopUp
748 indexOfSelectedItem]].rate;
749 job->abitrate = hb_audio_bitrates[[fAudBitratePopUp
750 indexOfSelectedItem]].rate;
753 - (IBAction) EnableQueue: (id) sender
755 bool e = ( [fQueueCheck state] == NSOnState );
756 [fQueueAddButton setHidden: !e];
757 [fQueueShowButton setHidden: !e];
758 [fRipButton setTitle: e ? @"Start" : @"Rip"];
761 - (IBAction) AddToQueue: (id) sender
763 hb_list_t * list = hb_get_titles( fHandle );
764 hb_title_t * title = (hb_title_t *) hb_list_item( list,
765 [fSrcTitlePopUp indexOfSelectedItem] );
766 hb_job_t * job = title->job;
770 /* Destination file */
771 job->file = strdup( [[fDstFile2Field stringValue] UTF8String] );
773 if( [fVidTwoPassCheck state] == NSOnState )
776 hb_add( fHandle, job );
778 hb_add( fHandle, job );
783 hb_add( fHandle, job );
787 - (IBAction) Rip: (id) sender
789 /* Rip or Cancel ? */
790 if( [[fRipButton title] isEqualToString: _( @"Cancel" )] )
792 [self Cancel: sender];
796 if( [fQueueCheck state] == NSOffState )
798 [self AddToQueue: sender];
801 if( [[NSFileManager defaultManager] fileExistsAtPath:
802 [fDstFile2Field stringValue]] )
804 NSBeginCriticalAlertSheet( _( @"File already exists" ),
805 _( @"Cancel" ), _( @"Overwrite" ), NULL, fWindow, self,
806 @selector( OverwriteAlertDone:returnCode:contextInfo: ),
807 NULL, NULL, [NSString stringWithFormat:
808 _( @"Do you want to overwrite %@?" ),
809 [fDstFile2Field stringValue]] );
816 - (void) OverwriteAlertDone: (NSWindow *) sheet
817 returnCode: (int) returnCode contextInfo: (void *) contextInfo
819 if( returnCode == NSAlertAlternateReturn )
825 - (void) UpdateAlertDone: (NSWindow *) sheet
826 returnCode: (int) returnCode contextInfo: (void *) contextInfo
828 if( returnCode == NSAlertAlternateReturn )
830 /* Show scan panel */
831 [self performSelectorOnMainThread: @selector(ShowScanPanel:)
832 withObject: NULL waitUntilDone: NO];
836 /* Go to HandBrake homepage and exit */
837 [self OpenHomepage: NULL];
838 [NSApp terminate: self];
843 /* Let libhb do the job */
846 /* Disable interface */
848 [fPauseButton setEnabled: NO];
849 [fRipButton setEnabled: NO];
852 - (IBAction) Cancel: (id) sender
854 NSBeginCriticalAlertSheet( _( @"Cancel - Are you sure?" ),
855 _( @"Keep working" ), _( @"Cancel encoding" ), NULL, fWindow, self,
856 @selector( _Cancel:returnCode:contextInfo: ), NULL, NULL,
857 _( @"Encoding won't be recoverable." ) );
860 - (void) _Cancel: (NSWindow *) sheet
861 returnCode: (int) returnCode contextInfo: (void *) contextInfo
863 if( returnCode == NSAlertAlternateReturn )
866 [fPauseButton setEnabled: NO];
867 [fRipButton setEnabled: NO];
871 - (IBAction) Pause: (id) sender
873 [fPauseButton setEnabled: NO];
874 [fRipButton setEnabled: NO];
876 if( [[fPauseButton title] isEqualToString: _( @"Resume" )] )
878 hb_resume( fHandle );
886 - (IBAction) TitlePopUpChanged: (id) sender
888 hb_list_t * list = hb_get_titles( fHandle );
889 hb_title_t * title = (hb_title_t*)
890 hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
893 /* Update chapter popups */
894 [fSrcChapterStartPopUp removeAllItems];
895 [fSrcChapterEndPopUp removeAllItems];
896 for( int i = 0; i < hb_list_count( title->list_chapter ); i++ )
898 [fSrcChapterStartPopUp addItemWithTitle: [NSString
899 stringWithFormat: @"%d", i + 1]];
900 [fSrcChapterEndPopUp addItemWithTitle: [NSString
901 stringWithFormat: @"%d", i + 1]];
903 [fSrcChapterStartPopUp selectItemAtIndex: 0];
904 [fSrcChapterEndPopUp selectItemAtIndex:
905 hb_list_count( title->list_chapter ) - 1];
906 [self ChapterPopUpChanged: NULL];
908 /* Start Get and set the initial pic size for display */
909 hb_job_t * job = title->job;
911 /*Set Source Size Fields Here */
912 [fPicSrcWidth setStringValue: [NSString stringWithFormat:
913 @"%d", fTitle->width]];
914 [fPicSrcHeight setStringValue: [NSString stringWithFormat:
915 @"%d", fTitle->height]];
916 /* Turn Deinterlace on/off depending on the preference */
917 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultDeinterlaceOn"] > 0)
919 job->deinterlace = 1;
923 job->deinterlace = 0;
926 /* Pixel Ratio Setting */
927 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"PixelRatio"])
930 job->pixel_ratio = 1 ;
934 job->pixel_ratio = 0 ;
936 /* Run Through EncoderPopUpChanged to see if there
937 needs to be any pic value modifications based on encoder settings */
938 [self EncoderPopUpChanged: NULL];
939 /* END Get and set the initial pic size for display */
942 /* Update subtitle popups */
943 hb_subtitle_t * subtitle;
944 [fSubPopUp removeAllItems];
945 [fSubPopUp addItemWithTitle: @"None"];
946 for( int i = 0; i < hb_list_count( title->list_subtitle ); i++ )
948 subtitle = (hb_subtitle_t *) hb_list_item( title->list_subtitle, i );
950 /* We cannot use NSPopUpButton's addItemWithTitle because
951 it checks for duplicate entries */
952 [[fSubPopUp menu] addItemWithTitle: [NSString stringWithCString:
953 subtitle->lang] action: NULL keyEquivalent: @""];
955 [fSubPopUp selectItemAtIndex: 0];
960 // PRI CHANGES 02/12/06
961 NSString * audiotmppri;
962 NSString * audiosearchpri=[[NSUserDefaults standardUserDefaults] stringForKey:@"DefaultLanguage"];
964 // End of pri changes 02/12/06
965 [fAudLang1PopUp removeAllItems];
966 /* Disable second audio language until crashing is resolved*/
967 [fAudLang2Field setEnabled: NO];
968 [fAudLang2PopUp setEnabled: NO];
969 [fAudLang2PopUp removeAllItems];
970 [fAudLang1PopUp addItemWithTitle: _( @"None" )];
971 /* Display Currently Unavailable until crash is fixed */
972 [fAudLang2PopUp addItemWithTitle: _( @"Currently Unavailable" )];
973 //[fAudLang2PopUp addItemWithTitle: _( @"None" )];
974 for( int i = 0; i < hb_list_count( title->list_audio ); i++ )
976 audio = (hb_audio_t *) hb_list_item( title->list_audio, i );
977 // PRI CHANGES 02/12/06
978 if (audiosearchpri!= NULL)
980 audiotmppri=(NSString *) [NSString stringWithCString: audio->lang];
981 // Try to find the desired default language
982 if ([audiotmppri hasPrefix:audiosearchpri] && indxpri==0)
987 // End of pri changes 02/12/06
989 [[fAudLang1PopUp menu] addItemWithTitle:
990 [NSString stringWithCString: audio->lang]
991 action: NULL keyEquivalent: @""];
993 [[fAudLang2PopUp menu] addItemWithTitle:
994 [NSString stringWithCString: audio->lang]
995 action: NULL keyEquivalent: @""];
998 // PRI CHANGES 02/12/06
999 if (indxpri==0) { indxpri=1; }
1000 [fAudLang1PopUp selectItemAtIndex: indxpri];
1001 // End of pri changes 02/12/06
1002 [fAudLang2PopUp selectItemAtIndex: 0];
1007 - (IBAction) ChapterPopUpChanged: (id) sender
1009 hb_list_t * list = hb_get_titles( fHandle );
1010 hb_title_t * title = (hb_title_t *)
1011 hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
1013 hb_chapter_t * chapter;
1014 int64_t duration = 0;
1015 for( int i = [fSrcChapterStartPopUp indexOfSelectedItem];
1016 i <= [fSrcChapterEndPopUp indexOfSelectedItem]; i++ )
1018 chapter = (hb_chapter_t *) hb_list_item( title->list_chapter, i );
1019 duration += chapter->duration;
1022 duration /= 90000; /* pts -> seconds */
1023 [fSrcDuration2Field setStringValue: [NSString stringWithFormat:
1024 @"%02lld:%02lld:%02lld", duration / 3600, ( duration / 60 ) % 60,
1027 [self CalculateBitrate: sender];
1030 - (IBAction) FormatPopUpChanged: (id) sender
1032 NSString * string = [fDstFile2Field stringValue];
1033 int format = [fDstFormatPopUp indexOfSelectedItem];
1036 /* Update the codecs popup */
1037 [fDstCodecsPopUp removeAllItems];
1041 /*Get Default MP4 File Extension*/
1042 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultMpegName"] > 0)
1050 [fDstCodecsPopUp addItemWithTitle:
1051 _( @"MPEG-4 Video / AAC Audio" )];
1052 [fDstCodecsPopUp addItemWithTitle:
1053 _( @"AVC/H.264 Video / AAC Audio" )];
1057 [fDstCodecsPopUp addItemWithTitle:
1058 _( @"MPEG-4 Video / MP3 Audio" )];
1059 [fDstCodecsPopUp addItemWithTitle:
1060 _( @"MPEG-4 Video / AC-3 Audio" )];
1061 [fDstCodecsPopUp addItemWithTitle:
1062 _( @"AVC/H.264 Video / MP3 Audio" )];
1063 [fDstCodecsPopUp addItemWithTitle:
1064 _( @"AVC/H.264 Video / AC-3 Audio" )];
1068 [fDstCodecsPopUp addItemWithTitle:
1069 _( @"MPEG-4 Video / Vorbis Audio" )];
1070 [fDstCodecsPopUp addItemWithTitle:
1071 _( @"MPEG-4 Video / MP3 Audio" )];
1074 [self CodecsPopUpChanged: NULL];
1076 /* Add/replace to the correct extension */
1077 if( [string characterAtIndex: [string length] - 4] == '.' )
1079 [fDstFile2Field setStringValue: [NSString stringWithFormat:
1080 @"%@.%s", [string substringToIndex: [string length] - 4],
1085 [fDstFile2Field setStringValue: [NSString stringWithFormat:
1086 @"%@.%s", string, ext]];
1090 - (IBAction) CodecsPopUpChanged: (id) sender
1092 int format = [fDstFormatPopUp indexOfSelectedItem];
1093 int codecs = [fDstCodecsPopUp indexOfSelectedItem];
1095 /* Update the encoder popup */
1096 if( ( FormatSettings[format][codecs] & HB_VCODEC_X264 ) )
1098 /* MPEG-4 -> H.264 */
1099 [fVidEncoderPopUp removeAllItems];
1100 [fVidEncoderPopUp addItemWithTitle: @"x264 (h.264 Main)"];
1101 [fVidEncoderPopUp addItemWithTitle: @"x264 (h.264 iPod)"];
1105 else if( ( FormatSettings[format][codecs] & HB_VCODEC_FFMPEG ) )
1107 /* H.264 -> MPEG-4 */
1108 [fVidEncoderPopUp removeAllItems];
1109 [fVidEncoderPopUp addItemWithTitle: @"FFmpeg"];
1110 [fVidEncoderPopUp addItemWithTitle: @"XviD"];
1111 [fVidEncoderPopUp selectItemAtIndex: 0];
1114 if( FormatSettings[format][codecs] & HB_ACODEC_AC3 )
1116 /* AC-3 pass-through: disable samplerate and bitrate */
1117 [fAudRatePopUp setEnabled: NO];
1118 [fAudBitratePopUp setEnabled: NO];
1122 [fAudRatePopUp setEnabled: YES];
1123 [fAudBitratePopUp setEnabled: YES];
1126 [self CalculateBitrate: sender];
1129 - (IBAction) EncoderPopUpChanged: (id) sender
1132 /* Check to see if we need to modify the job pic values based on x264 (iPod) encoder selection */
1133 if ([fDstFormatPopUp indexOfSelectedItem] == 0 && [fVidEncoderPopUp indexOfSelectedItem] == 1)
1135 hb_job_t * job = fTitle->job;
1136 job->pixel_ratio = 0 ;
1138 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"DefaultPicSizeAutoiPod"] > 0)
1141 if (fTitle->job->width > 640)
1143 fTitle->job->width = 640;
1145 fTitle->job->keep_ratio = 1;
1146 hb_fix_aspect( job, HB_KEEP_WIDTH );
1151 [self CalculatePictureSizing: sender];
1155 /* Get and Display Current Pic Settings in main window */
1156 - (IBAction) CalculatePictureSizing: (id) sender
1159 hb_job_t * job = fTitle->job;
1161 [fPicSettingWidth setStringValue: [NSString stringWithFormat:
1162 @"%d", fTitle->job->width]];
1163 [fPicSettingHeight setStringValue: [NSString stringWithFormat:
1164 @"%d", fTitle->job->height]];
1165 [fPicSettingARkeep setStringValue: [NSString stringWithFormat:
1166 @"%d", fTitle->job->keep_ratio]];
1167 [fPicSettingDeinterlace setStringValue: [NSString stringWithFormat:
1168 @"%d", fTitle->job->deinterlace]];
1169 [fPicSettingPAR setStringValue: [NSString stringWithFormat:
1170 @"%d", fTitle->job->pixel_ratio]];
1172 if (fTitle->job->pixel_ratio == 1)
1174 int titlewidth = fTitle->width-fTitle->job->crop[2]-fTitle->job->crop[3];
1175 int arpwidth = fTitle->job->pixel_aspect_width;
1176 int arpheight = fTitle->job->pixel_aspect_height;
1177 int displayparwidth = titlewidth * arpwidth / arpheight;
1178 int displayparheight = fTitle->height-fTitle->job->crop[0]-fTitle->job->crop[1];
1179 [fPicLabelPAROutp setStringValue: @"Anamorphic Output:"];
1180 [fPicLabelPAROutputX setStringValue: @"x"];
1181 [fPicSettingPARWidth setStringValue: [NSString stringWithFormat:
1182 @"%d", displayparwidth]];
1183 [fPicSettingPARHeight setStringValue: [NSString stringWithFormat:
1184 @"%d", displayparheight]];
1185 [fPicSettingHeight setStringValue: [NSString stringWithFormat:
1186 @"%d", displayparheight]];
1187 fTitle->job->keep_ratio = 0;
1191 [fPicLabelPAROutp setStringValue: @""];
1192 [fPicLabelPAROutputX setStringValue: @""];
1193 [fPicSettingPARWidth setStringValue: @""];
1194 [fPicSettingPARHeight setStringValue: @""];
1197 /* Set ON/Off values for the deinterlace/keep aspect ratio according to boolean */
1198 if (fTitle->job->keep_ratio > 0)
1200 [fPicSettingARkeepDsply setStringValue: @"On"];
1204 [fPicSettingARkeepDsply setStringValue: @"Off"];
1206 if (fTitle->job->deinterlace > 0)
1208 [fPicSettingDeinterlaceDsply setStringValue: @"On"];
1212 [fPicSettingDeinterlaceDsply setStringValue: @"Off"];
1214 if (fTitle->job->pixel_ratio > 0)
1216 [fPicSettingPARDsply setStringValue: @"On"];
1220 [fPicSettingPARDsply setStringValue: @"Off"];
1226 - (IBAction) CalculateBitrate: (id) sender
1228 if( !fHandle || [fVidQualityMatrix selectedRow] != 0 )
1233 hb_list_t * list = hb_get_titles( fHandle );
1234 hb_title_t * title = (hb_title_t *) hb_list_item( list,
1235 [fSrcTitlePopUp indexOfSelectedItem] );
1236 hb_job_t * job = title->job;
1240 [fVidBitrateField setIntValue: hb_calc_bitrate( job,
1241 [fVidTargetSizeField intValue] )];
1244 - (void) controlTextDidBeginEditing: (NSNotification *) notification
1246 [self CalculateBitrate: NULL];
1249 - (void) controlTextDidEndEditing: (NSNotification *) notification
1251 [self CalculateBitrate: NULL];
1254 - (void) controlTextDidChange: (NSNotification *) notification
1256 [self CalculateBitrate: NULL];
1259 - (IBAction) OpenHomepage: (id) sender
1261 [[NSWorkspace sharedWorkspace] openURL: [NSURL
1262 URLWithString:@"http://mediafork.dynalias.com/"]];
1265 - (IBAction) OpenForums: (id) sender
1267 [[NSWorkspace sharedWorkspace] openURL: [NSURL
1268 URLWithString:@"http://mediafork.dynalias.com/forum/"]];