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];
51 /* Call UpdateUI every 2/10 sec */
52 [[NSRunLoop currentRunLoop] addTimer: [NSTimer
53 scheduledTimerWithTimeInterval: 0.2 target: self
54 selector: @selector( UpdateUI: ) userInfo: NULL repeats: FALSE]
55 forMode: NSModalPanelRunLoopMode];
57 if( ( build = hb_check_update( fHandle, &version ) ) > -1 )
59 /* Update available - tell the user */
60 /* TEMPORARILY COMMENT OUT AS UPDATE CHECK IS NOT ACCURATE */
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];
98 [fDstFormatPopUp removeAllItems];
99 [fDstFormatPopUp addItemWithTitle: _( @"MP4 file" )];
100 [fDstFormatPopUp addItemWithTitle: _( @"AVI file" )];
101 [fDstFormatPopUp addItemWithTitle: _( @"OGM file" )];
102 [fDstFormatPopUp selectItemAtIndex: 0];
104 [self FormatPopUpChanged: NULL];
106 [fDstFile2Field setStringValue: [NSString stringWithFormat:
107 @"%@/Desktop/Movie.mp4", NSHomeDirectory()]];
110 [fVidEncoderPopUp removeAllItems];
111 [fVidEncoderPopUp addItemWithTitle: @"FFmpeg"];
112 [fVidEncoderPopUp addItemWithTitle: @"XviD"];
115 [fVidTargetSizeField setIntValue: 700];
116 [fVidBitrateField setIntValue: 1000];
117 [fVidQualityMatrix selectCell: fVidBitrateCell];
118 [self VideoMatrixChanged: NULL];
120 /* Video framerate */
121 [fVidRatePopUp removeAllItems];
122 [fVidRatePopUp addItemWithTitle: _( @"Same as source" )];
123 for( int i = 0; i < hb_video_rates_count; i++ )
125 [fVidRatePopUp addItemWithTitle:
126 [NSString stringWithCString: hb_video_rates[i].string]];
128 [fVidRatePopUp selectItemAtIndex: 0];
131 [fAudBitratePopUp removeAllItems];
132 for( int i = 0; i < hb_audio_bitrates_count; i++ )
134 [fAudBitratePopUp addItemWithTitle:
135 [NSString stringWithCString: hb_audio_bitrates[i].string]];
137 [fAudBitratePopUp selectItemAtIndex: hb_audio_bitrates_default];
139 /* Audio samplerate */
140 [fAudRatePopUp removeAllItems];
141 for( int i = 0; i < hb_audio_rates_count; i++ )
143 [fAudRatePopUp addItemWithTitle:
144 [NSString stringWithCString: hb_audio_rates[i].string]];
146 [fAudRatePopUp selectItemAtIndex: hb_audio_rates_default];
149 [fStatusField setStringValue: @""];
152 [fPauseButton setEnabled: NO];
153 [fRipButton setEnabled: NO];
156 - (void) TranslateStrings
158 [fSrcDVD1Field setStringValue: _( @"DVD:" )];
159 [fSrcTitleField setStringValue: _( @"Title:" )];
160 [fSrcChapterField setStringValue: _( @"Chapters:" )];
161 [fSrcChapterToField setStringValue: _( @"to" )];
162 [fSrcDuration1Field setStringValue: _( @"Duration:" )];
164 [fDstFormatField setStringValue: _( @"File format:" )];
165 [fDstCodecsField setStringValue: _( @"Codecs:" )];
166 [fDstFile1Field setStringValue: _( @"File:" )];
167 [fDstBrowseButton setTitle: _( @"Browse" )];
169 [fVidRateField setStringValue: _( @"Framerate (fps):" )];
170 [fVidEncoderField setStringValue: _( @"Encoder:" )];
171 [fVidQualityField setStringValue: _( @"Quality:" )];
174 /***********************************************************************
176 ***********************************************************************
177 * Shows a progression bar on the dock icon, filled according to
178 * 'progress' (0.0 <= progress <= 1.0).
179 * Called with progress < 0.0 or progress > 1.0, restores the original
181 **********************************************************************/
182 - (void) UpdateDockIcon: (float) progress
186 NSBitmapImageRep * bmp;
188 uint32_t black = htonl( 0x000000FF );
189 uint32_t red = htonl( 0xFF0000FF );
190 uint32_t white = htonl( 0xFFFFFFFF );
191 int row_start, row_end;
194 /* Get application original icon */
195 icon = [NSImage imageNamed: @"NSApplicationIcon"];
197 if( progress < 0.0 || progress > 1.0 )
199 [NSApp setApplicationIconImage: icon];
203 /* Get it in a raw bitmap form */
204 tiff = [icon TIFFRepresentationUsingCompression:
205 NSTIFFCompressionNone factor: 1.0];
206 bmp = [NSBitmapImageRep imageRepWithData: tiff];
208 /* Draw the progression bar */
209 /* It's pretty simple (ugly?) now, but I'm no designer */
211 row_start = 3 * (int) [bmp size].height / 4;
212 row_end = 7 * (int) [bmp size].height / 8;
214 for( i = row_start; i < row_start + 2; i++ )
216 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
217 for( j = 0; j < (int) [bmp size].width; j++ )
222 for( i = row_start + 2; i < row_end - 2; i++ )
224 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
227 for( j = 2; j < (int) [bmp size].width - 2; j++ )
229 if( j < 2 + (int) ( ( [bmp size].width - 4.0 ) * progress ) )
241 for( i = row_end - 2; i < row_end; i++ )
243 pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
244 for( j = 0; j < (int) [bmp size].width; j++ )
250 /* Now update the dock icon */
251 tiff = [bmp TIFFRepresentationUsingCompression:
252 NSTIFFCompressionNone factor: 1.0];
253 icon = [[NSImage alloc] initWithData: tiff];
254 [NSApp setApplicationIconImage: icon];
258 - (void) UpdateUI: (NSTimer *) timer
262 hb_get_state( fHandle, &s );
269 case HB_STATE_SCANNING:
270 [fScanController UpdateUI: &s];
273 #define p s.param.scandone
274 case HB_STATE_SCANDONE:
279 [fScanController UpdateUI: &s];
281 list = hb_get_titles( fHandle );
283 if( !hb_list_count( list ) )
288 [fSrcTitlePopUp removeAllItems];
289 for( int i = 0; i < hb_list_count( list ); i++ )
291 title = (hb_title_t *) hb_list_item( list, i );
292 /*Set DVD Name at top of window*/
293 [fSrcDVD2Field setStringValue: [NSString
294 stringWithUTF8String: title->name]];
296 /* Use the dvd name in the default output field here
297 May want to add code to remove blank spaces for some dvd names*/
298 [fDstFile2Field setStringValue: [NSString stringWithFormat:
299 @"%@/Desktop/%@.mp4", NSHomeDirectory(),[NSString
300 stringWithUTF8String: title->name]]];
302 [fSrcTitlePopUp addItemWithTitle: [NSString
303 stringWithFormat: @"%d - %02dh%02dm%02ds",
304 title->index, title->hours, title->minutes,
309 [self TitlePopUpChanged: NULL];
310 [self EnableUI: YES];
311 [fPauseButton setEnabled: NO];
312 [fRipButton setEnabled: YES];
317 #define p s.param.working
318 case HB_STATE_WORKING:
320 float progress_total;
321 NSMutableString * string;
323 /* Update text field */
324 string = [NSMutableString stringWithFormat:
325 _( @"Encoding: task %d of %d, %.2f %%" ),
326 p.job_cur, p.job_count, 100.0 * p.progress];
329 [string appendFormat:
330 _( @" (%.2f fps, avg %.2f fps, ETA %02dh%02dm%02ds)" ),
331 p.rate_cur, p.rate_avg, p.hours, p.minutes, p.seconds];
333 [fStatusField setStringValue: string];
336 progress_total = ( p.progress + p.job_cur - 1 ) / p.job_count;
337 [fRipIndicator setDoubleValue: 100.0 * progress_total];
339 /* Update dock icon */
340 [self UpdateDockIcon: progress_total];
342 [fPauseButton setEnabled: YES];
343 [fPauseButton setTitle: _( @"Pause" )];
344 [fRipButton setEnabled: YES];
345 [fRipButton setTitle: _( @"Cancel" )];
350 #define p s.param.muxing
351 case HB_STATE_MUXING:
353 float progress_total;
354 NSMutableString * string;
356 /* Update text field */
357 string = [NSMutableString stringWithFormat:
358 _( @"Muxing: %.2f %%" ), 100.0 * p.progress];
359 [fStatusField setStringValue: string];
362 [fRipIndicator setDoubleValue: 100.0 * p.progress];
364 /* Update dock icon */
365 [self UpdateDockIcon: 100.0 * p.progress];
367 [fPauseButton setEnabled: YES];
368 [fPauseButton setTitle: _( @"Pause" )];
369 [fRipButton setEnabled: YES];
370 [fRipButton setTitle: _( @"Cancel" )];
375 case HB_STATE_PAUSED:
376 [fStatusField setStringValue: _( @"Paused" )];
377 [fPauseButton setEnabled: YES];
378 [fPauseButton setTitle: _( @"Resume" )];
379 [fRipButton setEnabled: YES];
380 [fRipButton setTitle: _( @"Cancel" )];
383 case HB_STATE_WORKDONE:
385 [self EnableUI: YES];
386 [fStatusField setStringValue: _( @"Done." )];
387 [fRipIndicator setDoubleValue: 0.0];
388 [fRipButton setTitle: _( @"Rip" )];
390 /* Restore dock icon */
391 [self UpdateDockIcon: -1.0];
393 [fPauseButton setEnabled: NO];
394 [fPauseButton setTitle: _( @"Pause" )];
395 [fRipButton setEnabled: YES];
396 [fRipButton setTitle: _( @"Rip" )];
400 while( ( job = hb_job( fHandle, 0 ) ) )
402 hb_rem( fHandle, job );
408 /* FIXME: we should only do that when necessary */
409 if( [fQueueCheck state] == NSOnState )
411 int count = hb_count( fHandle );
414 [fQueueCheck setTitle: [NSString stringWithFormat:
415 @"Enable queue (%d task%s in queue)",
416 count, ( count > 1 ) ? "s" : ""]];
420 [fQueueCheck setTitle: @"Enable queue (no task in queue)"];
424 [[NSRunLoop currentRunLoop] addTimer: [NSTimer
425 scheduledTimerWithTimeInterval: 0.2 target: self
426 selector: @selector( UpdateUI: ) userInfo: NULL repeats: FALSE]
427 forMode: NSModalPanelRunLoopMode];
430 - (void) EnableUI: (bool) b
432 NSControl * controls[] =
433 { fSrcDVD1Field, fSrcDVD2Field, fSrcTitleField, fSrcTitlePopUp,
434 fSrcChapterField, fSrcChapterStartPopUp, fSrcChapterToField,
435 fSrcChapterEndPopUp, fSrcDuration1Field, fSrcDuration2Field,
436 fDstFormatField, fDstFormatPopUp, fDstCodecsField,
437 fDstCodecsPopUp, fDstFile1Field, fDstFile2Field,
438 fDstBrowseButton, fVidRateField, fVidRatePopUp,
439 fVidEncoderField, fVidEncoderPopUp, fVidQualityField,
440 fVidQualityMatrix, fVidGrayscaleCheck, fSubField, fSubPopUp,
441 fAudLang1Field, fAudLang1PopUp, fAudLang2Field, fAudLang2PopUp,
442 fAudRateField, fAudRatePopUp, fAudBitrateField,
443 fAudBitratePopUp, fPictureButton, fQueueCheck };
446 i < sizeof( controls ) / sizeof( NSControl * ); i++ )
448 if( [[controls[i] className] isEqualToString: @"NSTextField"] )
450 NSTextField * tf = (NSTextField *) controls[i];
451 if( ![tf isBezeled] )
453 [tf setTextColor: b ? [NSColor controlTextColor] :
454 [NSColor disabledControlTextColor]];
458 [controls[i] setEnabled: b];
461 [self VideoMatrixChanged: NULL];
464 - (IBAction) ShowScanPanel: (id) sender
466 [fScanController Show];
469 - (BOOL) windowShouldClose: (id) sender
471 /* Stop the application when the user closes the window */
472 [NSApp terminate: self];
476 - (IBAction) VideoMatrixChanged: (id) sender;
478 bool target, bitrate, quality;
480 target = bitrate = quality = false;
481 if( [fVidQualityMatrix isEnabled] )
483 switch( [fVidQualityMatrix selectedRow] )
496 [fVidTargetSizeField setEnabled: target];
497 [fVidBitrateField setEnabled: bitrate];
498 [fVidQualitySlider setEnabled: quality];
499 [fVidTwoPassCheck setEnabled: !quality &&
500 [fVidQualityMatrix isEnabled]];
503 [fVidTwoPassCheck setState: NSOffState];
506 [self QualitySliderChanged: sender];
507 [self CalculateBitrate: sender];
510 - (IBAction) QualitySliderChanged: (id) sender
512 [fVidConstantCell setTitle: [NSString stringWithFormat:
513 _( @"Constant quality: %.0f %%" ), 100.0 *
514 [fVidQualitySlider floatValue]]];
517 - (IBAction) BrowseFile: (id) sender
519 /* Open a panel to let the user choose and update the text field */
520 NSSavePanel * panel = [NSSavePanel savePanel];
522 [panel beginSheetForDirectory: NULL file: NULL
523 modalForWindow: fWindow modalDelegate: self
524 didEndSelector: @selector( BrowseFileDone:returnCode:contextInfo: )
528 - (void) BrowseFileDone: (NSSavePanel *) sheet
529 returnCode: (int) returnCode contextInfo: (void *) contextInfo
531 if( returnCode == NSOKButton )
533 [fDstFile2Field setStringValue: [sheet filename]];
534 [self FormatPopUpChanged: NULL];
538 - (IBAction) ShowPicturePanel: (id) sender
540 hb_list_t * list = hb_get_titles( fHandle );
541 hb_title_t * title = (hb_title_t *) hb_list_item( list,
542 [fSrcTitlePopUp indexOfSelectedItem] );
544 /* Resize the panel */
546 newSize.width = 246 + title->width;
547 newSize.height = 80 + title->height;
548 [fPicturePanel setContentSize: newSize];
550 [fPictureController SetTitle: title];
552 [NSApp beginSheet: fPicturePanel modalForWindow: fWindow
553 modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
554 [NSApp runModalForWindow: fPicturePanel];
555 [NSApp endSheet: fPicturePanel];
556 [fPicturePanel orderOut: self];
559 - (IBAction) ShowQueuePanel: (id) sender
561 /* Update the OutlineView */
562 [fQueueController Update: sender];
565 [NSApp beginSheet: fQueuePanel modalForWindow: fWindow
566 modalDelegate: NULL didEndSelector: NULL contextInfo: NULL];
567 [NSApp runModalForWindow: fQueuePanel];
568 [NSApp endSheet: fQueuePanel];
569 [fQueuePanel orderOut: self];
574 hb_list_t * list = hb_get_titles( fHandle );
575 hb_title_t * title = (hb_title_t *) hb_list_item( list,
576 [fSrcTitlePopUp indexOfSelectedItem] );
577 hb_job_t * job = title->job;
579 /* Chapter selection */
580 job->chapter_start = [fSrcChapterStartPopUp indexOfSelectedItem] + 1;
581 job->chapter_end = [fSrcChapterEndPopUp indexOfSelectedItem] + 1;
583 /* Format and codecs */
584 int format = [fDstFormatPopUp indexOfSelectedItem];
585 int codecs = [fDstCodecsPopUp indexOfSelectedItem];
586 job->mux = FormatSettings[format][codecs] & HB_MUX_MASK;
587 job->vcodec = FormatSettings[format][codecs] & HB_VCODEC_MASK;
588 job->acodec = FormatSettings[format][codecs] & HB_ACODEC_MASK;
590 if( ( job->vcodec & HB_VCODEC_FFMPEG ) &&
591 [fVidEncoderPopUp indexOfSelectedItem] > 0 )
593 job->vcodec = HB_VCODEC_XVID;
595 if( job->vcodec & HB_VCODEC_X264 )
597 if ([fVidEncoderPopUp indexOfSelectedItem] > 0 )
599 /* Just use new Baseline Level 3.0
600 Lets Deprecate Baseline Level 1.3*/
601 job->h264_level = 30;
602 job->mux = HB_MUX_IPOD;
605 /* Set this flag to switch from Constant Quantizer(default) to Constant Rate Factor */
608 job->h264_13 = [fVidEncoderPopUp indexOfSelectedItem];
612 if( [fVidRatePopUp indexOfSelectedItem] > 0 )
614 job->vrate = 27000000;
615 job->vrate_base = hb_video_rates[[fVidRatePopUp
616 indexOfSelectedItem]-1].rate;
620 job->vrate = title->rate;
621 job->vrate_base = title->rate_base;
624 switch( [fVidQualityMatrix selectedRow] )
628 Bitrate should already have been calculated and displayed
629 in fVidBitrateField, so let's just use it */
631 job->vquality = -1.0;
632 job->vbitrate = [fVidBitrateField intValue];
635 job->vquality = [fVidQualitySlider floatValue];
640 job->grayscale = ( [fVidGrayscaleCheck state] == NSOnState );
642 /* Subtitle settings */
643 job->subtitle = [fSubPopUp indexOfSelectedItem] - 1;
646 job->audios[0] = [fAudLang1PopUp indexOfSelectedItem] - 1;
647 job->audios[1] = [fAudLang2PopUp indexOfSelectedItem] - 1;
651 job->arate = hb_audio_rates[[fAudRatePopUp
652 indexOfSelectedItem]].rate;
653 job->abitrate = hb_audio_bitrates[[fAudBitratePopUp
654 indexOfSelectedItem]].rate;
657 - (IBAction) EnableQueue: (id) sender
659 bool e = ( [fQueueCheck state] == NSOnState );
660 [fQueueAddButton setHidden: !e];
661 [fQueueShowButton setHidden: !e];
662 [fRipButton setTitle: e ? @"Start" : @"Rip"];
665 - (IBAction) AddToQueue: (id) sender
667 hb_list_t * list = hb_get_titles( fHandle );
668 hb_title_t * title = (hb_title_t *) hb_list_item( list,
669 [fSrcTitlePopUp indexOfSelectedItem] );
670 hb_job_t * job = title->job;
674 /* Destination file */
675 job->file = strdup( [[fDstFile2Field stringValue] UTF8String] );
677 if( [fVidTwoPassCheck state] == NSOnState )
680 hb_add( fHandle, job );
682 hb_add( fHandle, job );
687 hb_add( fHandle, job );
691 - (IBAction) Rip: (id) sender
693 /* Rip or Cancel ? */
694 if( [[fRipButton title] isEqualToString: _( @"Cancel" )] )
696 [self Cancel: sender];
700 if( [fQueueCheck state] == NSOffState )
702 [self AddToQueue: sender];
705 if( [[NSFileManager defaultManager] fileExistsAtPath:
706 [fDstFile2Field stringValue]] )
708 NSBeginCriticalAlertSheet( _( @"File already exists" ),
709 _( @"Cancel" ), _( @"Overwrite" ), NULL, fWindow, self,
710 @selector( OverwriteAlertDone:returnCode:contextInfo: ),
711 NULL, NULL, [NSString stringWithFormat:
712 _( @"Do you want to overwrite %@?" ),
713 [fDstFile2Field stringValue]] );
720 - (void) OverwriteAlertDone: (NSWindow *) sheet
721 returnCode: (int) returnCode contextInfo: (void *) contextInfo
723 if( returnCode == NSAlertAlternateReturn )
729 - (void) UpdateAlertDone: (NSWindow *) sheet
730 returnCode: (int) returnCode contextInfo: (void *) contextInfo
732 if( returnCode == NSAlertAlternateReturn )
734 /* Show scan panel */
735 [self performSelectorOnMainThread: @selector(ShowScanPanel:)
736 withObject: NULL waitUntilDone: NO];
740 /* Go to HandBrake homepage and exit */
741 [self OpenHomepage: NULL];
742 [NSApp terminate: self];
747 /* Let libhb do the job */
750 /* Disable interface */
752 [fPauseButton setEnabled: NO];
753 [fRipButton setEnabled: NO];
756 - (IBAction) Cancel: (id) sender
758 NSBeginCriticalAlertSheet( _( @"Cancel - Are you sure?" ),
759 _( @"Keep working" ), _( @"Cancel encoding" ), NULL, fWindow, self,
760 @selector( _Cancel:returnCode:contextInfo: ), NULL, NULL,
761 _( @"Encoding won't be recoverable." ) );
764 - (void) _Cancel: (NSWindow *) sheet
765 returnCode: (int) returnCode contextInfo: (void *) contextInfo
767 if( returnCode == NSAlertAlternateReturn )
770 [fPauseButton setEnabled: NO];
771 [fRipButton setEnabled: NO];
775 - (IBAction) Pause: (id) sender
777 [fPauseButton setEnabled: NO];
778 [fRipButton setEnabled: NO];
780 if( [[fPauseButton title] isEqualToString: _( @"Resume" )] )
782 hb_resume( fHandle );
790 - (IBAction) TitlePopUpChanged: (id) sender
792 hb_list_t * list = hb_get_titles( fHandle );
793 hb_title_t * title = (hb_title_t*)
794 hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
796 /* Update chapter popups */
797 [fSrcChapterStartPopUp removeAllItems];
798 [fSrcChapterEndPopUp removeAllItems];
799 for( int i = 0; i < hb_list_count( title->list_chapter ); i++ )
801 [fSrcChapterStartPopUp addItemWithTitle: [NSString
802 stringWithFormat: @"%d", i + 1]];
803 [fSrcChapterEndPopUp addItemWithTitle: [NSString
804 stringWithFormat: @"%d", i + 1]];
806 [fSrcChapterStartPopUp selectItemAtIndex: 0];
807 [fSrcChapterEndPopUp selectItemAtIndex:
808 hb_list_count( title->list_chapter ) - 1];
809 [self ChapterPopUpChanged: NULL];
811 /* Update subtitle popups */
812 hb_subtitle_t * subtitle;
813 [fSubPopUp removeAllItems];
814 [fSubPopUp addItemWithTitle: @"None"];
815 for( int i = 0; i < hb_list_count( title->list_subtitle ); i++ )
817 subtitle = (hb_subtitle_t *) hb_list_item( title->list_subtitle, i );
819 /* We cannot use NSPopUpButton's addItemWithTitle because
820 it checks for duplicate entries */
821 [[fSubPopUp menu] addItemWithTitle: [NSString stringWithCString:
822 subtitle->lang] action: NULL keyEquivalent: @""];
824 [fSubPopUp selectItemAtIndex: 0];
826 /* Update lang popups */
828 // PRI CHANGES 02/12/06
829 NSString * audiotmppri;
830 NSString * audiosearchpri=[[NSUserDefaults standardUserDefaults] stringForKey:@"DefaultLanguage"];
832 // End of pri changes 02/12/06
833 [fAudLang1PopUp removeAllItems];
834 [fAudLang2PopUp removeAllItems];
835 [fAudLang1PopUp addItemWithTitle: _( @"None" )];
836 [fAudLang2PopUp addItemWithTitle: _( @"None" )];
837 for( int i = 0; i < hb_list_count( title->list_audio ); i++ )
839 audio = (hb_audio_t *) hb_list_item( title->list_audio, i );
840 // PRI CHANGES 02/12/06
841 audiotmppri=(NSString *) [NSString stringWithCString: audio->lang];
842 // Try to find the desired default language
843 if ([audiotmppri hasPrefix:audiosearchpri] && indxpri==0)
847 // End of pri changes 02/12/06
849 [[fAudLang1PopUp menu] addItemWithTitle:
850 [NSString stringWithCString: audio->lang]
851 action: NULL keyEquivalent: @""];
852 [[fAudLang2PopUp menu] addItemWithTitle:
853 [NSString stringWithCString: audio->lang]
854 action: NULL keyEquivalent: @""];
856 // PRI CHANGES 02/12/06
857 if (indxpri==0) { indxpri=1; }
858 [fAudLang1PopUp selectItemAtIndex: indxpri];
859 // End of pri changes 02/12/06
860 [fAudLang2PopUp selectItemAtIndex: 0];
863 - (IBAction) ChapterPopUpChanged: (id) sender
865 hb_list_t * list = hb_get_titles( fHandle );
866 hb_title_t * title = (hb_title_t *)
867 hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] );
869 hb_chapter_t * chapter;
870 int64_t duration = 0;
871 for( int i = [fSrcChapterStartPopUp indexOfSelectedItem];
872 i <= [fSrcChapterEndPopUp indexOfSelectedItem]; i++ )
874 chapter = (hb_chapter_t *) hb_list_item( title->list_chapter, i );
875 duration += chapter->duration;
878 duration /= 90000; /* pts -> seconds */
879 [fSrcDuration2Field setStringValue: [NSString stringWithFormat:
880 @"%02lld:%02lld:%02lld", duration / 3600, ( duration / 60 ) % 60,
883 [self CalculateBitrate: sender];
886 - (IBAction) FormatPopUpChanged: (id) sender
888 NSString * string = [fDstFile2Field stringValue];
889 int format = [fDstFormatPopUp indexOfSelectedItem];
892 /* Update the codecs popup */
893 [fDstCodecsPopUp removeAllItems];
898 [fDstCodecsPopUp addItemWithTitle:
899 _( @"MPEG-4 Video / AAC Audio" )];
900 [fDstCodecsPopUp addItemWithTitle:
901 _( @"AVC/H.264 Video / AAC Audio" )];
905 [fDstCodecsPopUp addItemWithTitle:
906 _( @"MPEG-4 Video / MP3 Audio" )];
907 [fDstCodecsPopUp addItemWithTitle:
908 _( @"MPEG-4 Video / AC-3 Audio" )];
909 [fDstCodecsPopUp addItemWithTitle:
910 _( @"AVC/H.264 Video / MP3 Audio" )];
911 [fDstCodecsPopUp addItemWithTitle:
912 _( @"AVC/H.264 Video / AC-3 Audio" )];
916 [fDstCodecsPopUp addItemWithTitle:
917 _( @"MPEG-4 Video / Vorbis Audio" )];
918 [fDstCodecsPopUp addItemWithTitle:
919 _( @"MPEG-4 Video / MP3 Audio" )];
922 [self CodecsPopUpChanged: NULL];
924 /* Add/replace to the correct extension */
925 if( [string characterAtIndex: [string length] - 4] == '.' )
927 [fDstFile2Field setStringValue: [NSString stringWithFormat:
928 @"%@.%s", [string substringToIndex: [string length] - 4],
933 [fDstFile2Field setStringValue: [NSString stringWithFormat:
934 @"%@.%s", string, ext]];
938 - (IBAction) CodecsPopUpChanged: (id) sender
940 int format = [fDstFormatPopUp indexOfSelectedItem];
941 int codecs = [fDstCodecsPopUp indexOfSelectedItem];
943 /* Update the encoder popup */
944 if( ( FormatSettings[format][codecs] & HB_VCODEC_X264 ) )
946 /* MPEG-4 -> H.264 */
947 [fVidEncoderPopUp removeAllItems];
948 [fVidEncoderPopUp addItemWithTitle: @"x264 (h.264 Main)"];
949 [fVidEncoderPopUp addItemWithTitle: @"x264 (h.264 iPod)"];
953 else if( ( FormatSettings[format][codecs] & HB_VCODEC_FFMPEG ) )
955 /* H.264 -> MPEG-4 */
956 [fVidEncoderPopUp removeAllItems];
957 [fVidEncoderPopUp addItemWithTitle: @"FFmpeg"];
958 [fVidEncoderPopUp addItemWithTitle: @"XviD"];
959 [fVidEncoderPopUp selectItemAtIndex: 0];
962 if( FormatSettings[format][codecs] & HB_ACODEC_AC3 )
964 /* AC-3 pass-through: disable samplerate and bitrate */
965 [fAudRatePopUp setEnabled: NO];
966 [fAudBitratePopUp setEnabled: NO];
970 [fAudRatePopUp setEnabled: YES];
971 [fAudBitratePopUp setEnabled: YES];
974 [self CalculateBitrate: sender];
977 - (IBAction) CalculateBitrate: (id) sender
979 if( !fHandle || [fVidQualityMatrix selectedRow] != 0 )
984 hb_list_t * list = hb_get_titles( fHandle );
985 hb_title_t * title = (hb_title_t *) hb_list_item( list,
986 [fSrcTitlePopUp indexOfSelectedItem] );
987 hb_job_t * job = title->job;
991 [fVidBitrateField setIntValue: hb_calc_bitrate( job,
992 [fVidTargetSizeField intValue] )];
995 - (void) controlTextDidBeginEditing: (NSNotification *) notification
997 [self CalculateBitrate: NULL];
1000 - (void) controlTextDidEndEditing: (NSNotification *) notification
1002 [self CalculateBitrate: NULL];
1005 - (void) controlTextDidChange: (NSNotification *) notification
1007 [self CalculateBitrate: NULL];
1010 - (IBAction) OpenHomepage: (id) sender
1012 [[NSWorkspace sharedWorkspace] openURL: [NSURL
1013 URLWithString:@"http://handbrake.m0k.org/"]];
1016 - (IBAction) OpenForums: (id) sender
1018 [[NSWorkspace sharedWorkspace] openURL: [NSURL
1019 URLWithString:@"http://handbrake.m0k.org/forum/"]];