1 /* $Id: Controller.mm,v 1.7 2003/11/07 21:22:17 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. */
8 #include <IOKit/IOKitLib.h>
9 #include <IOKit/IOBSD.h>
10 #include <IOKit/storage/IOMedia.h>
11 #include <IOKit/storage/IODVDMedia.h>
13 #include "Controller.h"
15 @implementation HBController
17 - (void) applicationDidFinishLaunching: (NSNotification *) notification
20 fHandle = HBInit( 1, 0 );
21 [fPictureGLView SetHandle: fHandle];
23 /* Update the GUI every 1/10 sec */
25 [NSTimer scheduledTimerWithTimeInterval: 0.1
26 target: self selector: @selector( UpdateIntf: )
27 userInfo: nil repeats: YES];
29 /* Detect drives mounted after the app is started */
30 [[[NSWorkspace sharedWorkspace] notificationCenter]
31 addObserver: self selector: @selector( DetectDrives: )
32 name: NSWorkspaceDidMountNotification object: nil];
35 - (NSApplicationTerminateReply) applicationShouldTerminate:
42 return NSTerminateNow;
47 [fDVDPopUp removeAllItems];
48 [fScanProgress setStyle: NSProgressIndicatorSpinningStyle];
49 [fScanProgress setDisplayedWhenStopped: NO];
50 [fVideoCodecPopUp removeAllItems];
51 [fVideoCodecPopUp addItemWithTitle: @"MPEG-4 (Ffmpeg)"];
52 [fVideoCodecPopUp addItemWithTitle: @"MPEG-4 (XviD)"];
53 [fVideoCodecPopUp selectItemWithTitle: @"MPEG-4 (Ffmpeg)"];
54 [fAudioBitratePopUp removeAllItems];
55 [fAudioBitratePopUp addItemWithTitle: @"32"];
56 [fAudioBitratePopUp addItemWithTitle: @"64"];
57 [fAudioBitratePopUp addItemWithTitle: @"96"];
58 [fAudioBitratePopUp addItemWithTitle: @"128"];
59 [fAudioBitratePopUp addItemWithTitle: @"160"];
60 [fAudioBitratePopUp addItemWithTitle: @"192"];
61 [fAudioBitratePopUp addItemWithTitle: @"224"];
62 [fAudioBitratePopUp addItemWithTitle: @"256"];
63 [fAudioBitratePopUp addItemWithTitle: @"288"];
64 [fAudioBitratePopUp addItemWithTitle: @"320"];
65 [fAudioBitratePopUp selectItemWithTitle: @"128"];
67 char string[1024]; memset( string, 0, 1024 );
68 snprintf( string, 1024, "%s/Desktop/Movie.avi", getenv( "HOME" ) );
69 [fFileField setStringValue: [NSString stringWithCString: string]];
71 /* Show the scan view */
72 [fWindow setContentSize: [fScanView frame].size];
73 [fWindow setContentView: fScanView];
76 /* Detect DVD drives */
77 [self DetectDrives: nil];
78 [self ScanMatrixChanged: self];
81 - (BOOL) windowShouldClose: (id) sender
83 /* Stop the application when the user closes the window */
84 [NSApp terminate: self];
88 - (IBAction) BrowseDVD: (id) sender
90 /* Open a panel to let the user choose and update the text field */
91 NSOpenPanel * panel = [NSOpenPanel openPanel];
93 [panel setAllowsMultipleSelection: NO];
94 [panel setCanChooseFiles: NO];
95 [panel setCanChooseDirectories: YES ];
97 [panel beginSheetForDirectory: nil file: nil types: nil
98 modalForWindow: fWindow modalDelegate: self
99 didEndSelector: @selector( BrowseDVDDone:returnCode:contextInfo: )
103 - (void) BrowseDVDDone: (NSOpenPanel *) sheet
104 returnCode: (int) returnCode contextInfo: (void *) contextInfo
106 if( returnCode == NSOKButton )
108 [fDVDFolderField setStringValue:
109 [[sheet filenames] objectAtIndex: 0]];
113 - (IBAction) VideoMatrixChanged: (id) sender;
115 if( ![fVideoMatrix selectedRow] )
117 [fCustomBitrateField setEnabled: YES];
118 [fTargetSizeField setEnabled: NO];
122 [fCustomBitrateField setEnabled: NO];
123 [fTargetSizeField setEnabled: YES];
124 [fTargetSizeField UpdateBitrate];
128 - (IBAction) BrowseFile: (id) sender
130 /* Open a panel to let the user choose and update the text field */
131 NSSavePanel * panel = [NSSavePanel savePanel];
133 [panel beginSheetForDirectory: nil file: nil
134 modalForWindow: fWindow modalDelegate: self
135 didEndSelector: @selector( BrowseFileDone:returnCode:contextInfo: )
139 - (void) BrowseFileDone: (NSSavePanel *) sheet
140 returnCode: (int) returnCode contextInfo: (void *) contextInfo
142 if( returnCode == NSOKButton )
144 [fFileField setStringValue: [sheet filename]];
148 - (IBAction) Scan: (id) sender
150 /* Ask libhb to start scanning the specified volume */
152 if( ![fScanMatrix selectedRow] )
155 HBScanDevice( fHandle,
156 (char*) [[fDVDPopUp titleOfSelectedItem] cString],
162 HBScanDevice( fHandle,
163 (char*) [[fDVDFolderField stringValue] cString],
168 - (IBAction) ShowPicturePanel: (id) sender
170 HBTitle * title = (HBTitle*)
171 HBListItemAt( fTitleList, [fTitlePopUp indexOfSelectedItem] );
173 [fPictureGLView SetTitle: title];
176 [fPictureGLView ShowPicture: fPicture animate: HB_ANIMATE_NONE];
178 [fWidthStepper setValueWraps: NO];
179 [fWidthStepper setIncrement: 16];
180 [fWidthStepper setMinValue: 16];
181 [fWidthStepper setMaxValue: title->outWidthMax];
182 [fWidthStepper setIntValue: title->outWidth];
183 [fWidthField setIntValue: title->outWidth];
184 [fDeinterlaceCheck setState:
185 title->deinterlace ? NSOnState : NSOffState];
186 [fTopStepper setValueWraps: NO];
187 [fTopStepper setIncrement: 2];
188 [fTopStepper setMinValue: 0];
189 [fTopStepper setMaxValue: title->inHeight / 4];
190 [fTopStepper setIntValue: title->topCrop];
191 [fTopField setIntValue: title->topCrop];
192 [fBottomStepper setValueWraps: NO];
193 [fBottomStepper setIncrement: 2];
194 [fBottomStepper setMinValue: 0];
195 [fBottomStepper setMaxValue: title->inHeight / 4];
196 [fBottomStepper setIntValue: title->bottomCrop];
197 [fBottomField setIntValue: title->bottomCrop];
198 [fLeftStepper setValueWraps: NO];
199 [fLeftStepper setIncrement: 2];
200 [fLeftStepper setMinValue: 0];
201 [fLeftStepper setMaxValue: title->inWidth / 4];
202 [fLeftStepper setIntValue: title->leftCrop];
203 [fLeftField setIntValue: title->leftCrop];
204 [fRightStepper setValueWraps: NO];
205 [fRightStepper setIncrement: 2];
206 [fRightStepper setMinValue: 0];
207 [fRightStepper setMaxValue: title->inWidth / 4];
208 [fRightStepper setIntValue: title->rightCrop];
209 [fRightField setIntValue: title->rightCrop];
211 [fPreviousButton setEnabled: NO];
212 [fNextButton setEnabled: YES];
214 char string[1024]; memset( string, 0, 1024 );
215 sprintf( string, "Final size: %dx%d",
216 title->outWidth, title->outHeight );
217 [fInfoField setStringValue: [NSString stringWithCString: string]];
219 /* Resize the panel */
222 newSize.width = 762 /*fPicturePanelSize.width*/ +
223 title->outWidthMax - 720;
224 newSize.height = 740 /*fPicturePanelSize.height*/ +
225 title->outHeightMax - 576;
226 [fPicturePanel setContentSize: newSize];
228 [NSApp beginSheet: fPicturePanel modalForWindow: fWindow
229 modalDelegate: nil didEndSelector: nil contextInfo: nil];
230 [NSApp runModalForWindow: fPicturePanel];
231 [NSApp endSheet: fPicturePanel];
232 [fPicturePanel orderOut: self];
235 - (IBAction) ClosePanel: (id) sender
240 - (IBAction) Rip: (id) sender
242 /* Rip or Cancel ? */
243 if( [[fRipButton title] compare: @"Cancel" ] == NSOrderedSame )
249 if( [fCustomBitrateField intValue] < 256 )
251 NSBeginCriticalAlertSheet( @"Invalid video bitrate", @"Ooops",
252 nil, nil, fWindow, self, nil, nil, nil,
253 @"Video bitrate is too low !" );
256 if( [fCustomBitrateField intValue] > 8192 )
258 NSBeginCriticalAlertSheet( @"Invalid video bitrate", @"Ooops",
259 nil, nil, fWindow, self, nil, nil, nil,
260 @"Video bitrate is too high !" );
263 if( [fLanguagePopUp indexOfSelectedItem] ==
264 [fSecondaryLanguagePopUp indexOfSelectedItem] )
266 NSBeginCriticalAlertSheet( @"Invalid secondary language",
267 @"Ooops", nil, nil, fWindow, self, nil, nil, nil,
268 @"Do you _really_ want to encode the same audio track twice?" );
273 if( ( file = fopen( [[fFileField stringValue] cString], "r" ) ) )
276 NSBeginCriticalAlertSheet( @"File already exists",
277 @"Nooo!", @"Yes, go ahead", nil, fWindow, self,
278 @selector( OverwriteAlertDone:returnCode:contextInfo: ),
280 [NSString stringWithFormat: @"Do you want to overwrite %s?",
281 [[fFileField stringValue] cString]] );
288 - (void) OverwriteAlertDone: (NSWindow *) sheet
289 returnCode: (int) returnCode contextInfo: (void *) contextInfo
291 if( returnCode == NSAlertAlternateReturn )
299 /* Get the specified title & audio track(s) */
300 HBTitle * title = (HBTitle*)
301 HBListItemAt( fTitleList, [fTitlePopUp indexOfSelectedItem] );
302 HBAudio * audio1 = (HBAudio*)
303 HBListItemAt( title->audioList,
304 [fLanguagePopUp indexOfSelectedItem] );
305 HBAudio * audio2 = (HBAudio*)
306 HBListItemAt( title->audioList,
307 [fSecondaryLanguagePopUp indexOfSelectedItem] );
309 /* Use user settings */
310 title->file = strdup( [[fFileField stringValue] cString] );
311 title->bitrate = [fCustomBitrateField intValue];
312 title->twoPass = ( [fTwoPassCheck state] == NSOnState );
313 title->codec = ( [[fVideoCodecPopUp titleOfSelectedItem] compare:
314 @"MPEG-4 (Ffmpeg)"] == NSOrderedSame ) ?
315 HB_CODEC_FFMPEG : HB_CODEC_XVID;
316 audio1->outBitrate = [[fAudioBitratePopUp titleOfSelectedItem]
321 [[fAudioBitratePopUp titleOfSelectedItem] intValue];
324 /* Let libhb do the job */
325 HBStartRip( fHandle, title, audio1, audio2 );
328 - (IBAction) Cancel: (id) sender
330 HBStopRip( fHandle );
333 - (IBAction) Suspend: (id) sender
335 if( [[fSuspendButton title] compare: @"Resume" ] == NSOrderedSame )
341 HBPauseRip( fHandle );
344 - (IBAction) Resume: (id) sender
346 HBResumeRip( fHandle );
349 - (IBAction) PreviousPicture: (id) sender
352 if( [fOpenGLCheck state] == NSOnState )
354 [fPictureGLView ShowPicture: fPicture
355 animate: HB_ANIMATE_LEFT];
359 [fPictureGLView ShowPicture: fPicture
360 animate: HB_ANIMATE_NONE];
363 [fPreviousButton setEnabled: ( fPicture > 0 )];
364 [fNextButton setEnabled: YES];
367 - (IBAction) NextPicture: (id) sender
370 if( [fOpenGLCheck state] == NSOnState )
372 [fPictureGLView ShowPicture: fPicture
373 animate: HB_ANIMATE_RIGHT];
377 [fPictureGLView ShowPicture: fPicture
378 animate: HB_ANIMATE_NONE];
381 [fPreviousButton setEnabled: YES];
382 [fNextButton setEnabled: ( fPicture < 9 )];
385 - (IBAction) UpdatePicture: (id) sender
387 HBTitle * title = (HBTitle*)
388 HBListItemAt( fTitleList, [fTitlePopUp indexOfSelectedItem] );
389 title->outWidth = [fWidthStepper intValue];
390 title->deinterlace = ( [fDeinterlaceCheck state] == NSOnState );
391 title->topCrop = [fTopStepper intValue];
392 title->bottomCrop = [fBottomStepper intValue];
393 title->leftCrop = [fLeftStepper intValue];
394 title->rightCrop = [fRightStepper intValue];
396 [fPictureGLView ShowPicture: fPicture animate: HB_ANIMATE_NONE];
398 [fWidthStepper setIntValue: title->outWidth];
399 [fTopStepper setIntValue: title->topCrop];
400 [fBottomStepper setIntValue: title->bottomCrop];
401 [fLeftStepper setIntValue: title->leftCrop];
402 [fRightStepper setIntValue: title->rightCrop];
403 [fWidthField setIntValue: [fWidthStepper intValue]];
404 [fTopField setIntValue: [fTopStepper intValue]];
405 [fBottomField setIntValue: [fBottomStepper intValue]];
406 [fLeftField setIntValue: [fLeftStepper intValue]];
407 [fRightField setIntValue: [fRightStepper intValue]];
409 char string[1024]; memset( string, 0, 1024 );
410 sprintf( string, "Final size: %dx%d",
411 title->outWidth, title->outHeight );
412 [fInfoField setStringValue: [NSString stringWithCString: string]];
415 - (void) UpdateIntf: (NSTimer *) timer
426 modeChanged = HBGetStatus( fHandle, &status );
428 switch( status.mode )
430 case HB_MODE_NEED_DEVICE:
433 case HB_MODE_SCANNING:
437 [fScanMatrix setEnabled: NO];
438 [fDVDPopUp setEnabled: NO];
439 [fDVDFolderField setEnabled: NO];
440 [fScanBrowseButton setEnabled: NO];
441 [fScanProgress startAnimation: self];
442 [fScanButton setEnabled: NO];
445 char string[1024]; memset( string, 0, 1024 );
446 if( status.scannedTitle )
448 sprintf( string, "Scanning title %d...",
449 status.scannedTitle );
453 sprintf( string, "Opening device..." );
455 [fScanStatusField setStringValue:
456 [NSString stringWithCString: string]];
461 case HB_MODE_INVALID_DEVICE:
466 [fScanMatrix setEnabled: YES];
467 [self ScanMatrixChanged: self];
468 [fScanProgress stopAnimation: self];
469 [fScanButton setEnabled: YES];
471 [fScanStatusField setStringValue:
472 @"Invalid volume, try again" ];
476 case HB_MODE_READY_TO_RIP:
481 fTitleList = status.titleList;
483 /* Show a temporary empty view while the window
484 resizing animation */
485 [fWindow setContentView: fTempView ];
487 /* Actually resize it */
489 newFrame = [NSWindow contentRectForFrameRect: [fWindow frame]
490 styleMask: [fWindow styleMask]];
491 newFrame.origin.y += newFrame.size.height -
492 [fRipView frame].size.height;
493 newFrame.size.height = [fRipView frame].size.height;
494 newFrame.size.width = [fRipView frame].size.width;
495 newFrame = [NSWindow frameRectForContentRect: newFrame
496 styleMask: [fWindow styleMask]];
497 [fWindow setFrame: newFrame display: YES animate: YES];
499 /* Show the new GUI */
500 [fWindow setContentView: fRipView ];
501 [fSuspendButton setEnabled: NO];
503 [fTitlePopUp removeAllItems];
505 for( int i = 0; i < HBListCountItems( fTitleList ); i++ )
507 title = (HBTitle*) HBListItemAt( fTitleList, i );
508 char string[1024]; memset( string, 0, 1024 );
509 sprintf( string, "%d - %02dh%02dm%02ds",
510 title->index, title->length / 3600,
511 ( title->length % 3600 ) / 60,
512 title->length % 60 );
513 [[fTitlePopUp menu] addItemWithTitle:
514 [NSString stringWithCString: string]
515 action: nil keyEquivalent: @""];
517 [self TitlePopUpChanged: self];
522 case HB_MODE_ENCODING:
526 [fTitlePopUp setEnabled: NO];
527 [fVideoCodecPopUp setEnabled: NO];
528 [fVideoMatrix setEnabled: NO];
529 [fCustomBitrateField setEnabled: NO];
530 [fTargetSizeField setEnabled: NO];
531 [fTwoPassCheck setEnabled: NO];
532 [fCropButton setEnabled: NO];
533 [fLanguagePopUp setEnabled: NO];
534 [fSecondaryLanguagePopUp setEnabled: NO];
535 [fAudioCodecPopUp setEnabled: NO];
536 [fAudioBitratePopUp setEnabled: NO];
537 [fFileFormatPopUp setEnabled: NO];
538 [fFileBrowseButton setEnabled: NO];
539 [fSuspendButton setEnabled: YES];
540 [fSuspendButton setTitle: @"Suspend"];
541 [fRipButton setTitle: @"Cancel"];
544 if( !status.position )
546 [fRipStatusField setStringValue: @"Starting..."];
547 [fRipProgress setIndeterminate: YES];
548 [fRipProgress startAnimation: self];;
553 memset( string, 0, 1024 );
554 sprintf( string, "Encoding: %.2f %% (pass %d of %d)",
555 100 * status.position, status.pass,
557 [fRipStatusField setStringValue:
558 [NSString stringWithCString: string]];
559 memset( string, 0, 1024 );
560 sprintf( string, "Speed: %.2f fps (avg %.2f fps, "
561 "%02dh%02dm%02ds remaining)",
562 status.frameRate, status.avFrameRate,
563 status.remainingTime / 3600,
564 ( status.remainingTime / 60 ) % 60,
565 status.remainingTime % 60 );
566 [fRipInfoField setStringValue:
567 [NSString stringWithCString: string]];
569 [fRipProgress setIndeterminate: NO];
570 [fRipProgress setDoubleValue: 100 * status.position];
581 char string[1024]; memset( string, 0, 1024 );
582 sprintf( string, "Encoding: %.2f %% (PAUSED)",
583 100 * status.position ) ;
584 [fRipStatusField setStringValue:
585 [NSString stringWithCString: string]];
586 [fRipInfoField setStringValue: @""];
588 [fRipProgress setDoubleValue: 100 * status.position];
590 [fSuspendButton setTitle: @"Resume"];
594 case HB_MODE_STOPPING:
598 [fRipStatusField setStringValue: @"Stopping..."];
599 [fRipInfoField setStringValue: @""];
600 [fRipProgress setIndeterminate: YES];
601 [fRipProgress startAnimation: self];;
605 case HB_MODE_CANCELED:
610 /* Warn the finder to update itself */
611 [[NSWorkspace sharedWorkspace] noteFileSystemChanged:
612 [fFileField stringValue]];
614 [fRipProgress setIndeterminate: NO];
615 [fRipInfoField setStringValue: @""];
617 if( status.mode == HB_MODE_DONE )
619 [fRipProgress setDoubleValue: 100];
620 [fRipStatusField setStringValue: @"Done." ];
622 [NSApp requestUserAttention: NSInformationalRequest];
623 [NSApp beginSheet: fDonePanel
624 modalForWindow: fWindow modalDelegate: nil
625 didEndSelector: nil contextInfo: nil];
626 [NSApp runModalForWindow: fDonePanel];
627 [NSApp endSheet: fDonePanel];
628 [fDonePanel orderOut: self];
630 else if( status.mode == HB_MODE_CANCELED )
632 [fRipProgress setDoubleValue: 0];
633 [fRipStatusField setStringValue: @"Canceled." ];
637 [fRipProgress setDoubleValue: 0];
638 switch( status.error )
640 case HB_ERROR_A52_SYNC:
641 [fRipStatusField setStringValue:
642 @"An error occured (corrupted AC3 data)." ];
644 case HB_ERROR_AVI_WRITE:
645 [fRipStatusField setStringValue:
646 @"An error occured (could not write to file)." ];
648 case HB_ERROR_DVD_OPEN:
649 [fRipStatusField setStringValue:
650 @"An error occured (could not open device)." ];
652 case HB_ERROR_DVD_READ:
653 [fRipStatusField setStringValue:
654 @"An error occured (DVD read failed)." ];
656 case HB_ERROR_MP3_INIT:
657 [fRipStatusField setStringValue:
658 @"An error occured (could not init MP3 encoder)." ];
660 case HB_ERROR_MP3_ENCODE:
661 [fRipStatusField setStringValue:
662 @"An error occured (MP3 encoder failed)." ];
664 case HB_ERROR_MPEG4_INIT:
665 [fRipStatusField setStringValue:
666 @"An error occured (could not init MPEG4 encoder)." ];
671 [fTitlePopUp setEnabled: YES];
672 [fVideoCodecPopUp setEnabled: YES];
673 [fVideoMatrix setEnabled: YES];
674 [fTwoPassCheck setEnabled: YES];
675 [fCropButton setEnabled: YES];
676 [fLanguagePopUp setEnabled: YES];
677 [fSecondaryLanguagePopUp setEnabled: YES];
678 [fAudioCodecPopUp setEnabled: YES];
679 [fAudioBitratePopUp setEnabled: YES];
680 [fFileFormatPopUp setEnabled: YES];
681 [fFileBrowseButton setEnabled: YES];
682 [fSuspendButton setEnabled: NO];
683 [fSuspendButton setTitle: @"Suspend"];
684 [fRipButton setTitle: @"Rip"];
686 [self VideoMatrixChanged: self];
687 [self VideoCodecPopUpChanged: self];
696 - (void) DetectDrives: (NSNotification *) notification
698 /* Scan DVD drives (stolen from VLC) */
699 io_object_t next_media;
700 mach_port_t master_port;
701 kern_return_t kern_result;
702 io_iterator_t media_iterator;
703 CFMutableDictionaryRef classes_to_match;
705 kern_result = IOMasterPort( MACH_PORT_NULL, &master_port );
706 if( kern_result != KERN_SUCCESS )
711 classes_to_match = IOServiceMatching( kIODVDMediaClass );
712 if( classes_to_match == NULL )
717 CFDictionarySetValue( classes_to_match, CFSTR( kIOMediaEjectableKey ),
721 IOServiceGetMatchingServices( master_port, classes_to_match,
723 if( kern_result != KERN_SUCCESS )
728 NSMutableArray * drivesList;
729 drivesList = [NSMutableArray arrayWithCapacity: 1];
731 next_media = IOIteratorNext( media_iterator );
732 if( next_media != NULL )
735 size_t dev_path_length;
736 CFTypeRef str_bsd_path;
740 IORegistryEntryCreateCFProperty( next_media,
741 CFSTR( kIOBSDNameKey ),
744 if( str_bsd_path == NULL )
746 IOObjectRelease( next_media );
750 snprintf( psz_buf, sizeof(psz_buf), "%s%c", _PATH_DEV, 'r' );
751 dev_path_length = strlen( psz_buf );
753 if( CFStringGetCString( (CFStringRef) str_bsd_path,
754 (char*)&psz_buf + dev_path_length,
755 sizeof(psz_buf) - dev_path_length,
756 kCFStringEncodingASCII ) )
758 [drivesList addObject:
759 [NSString stringWithCString: psz_buf]];
762 CFRelease( str_bsd_path );
764 IOObjectRelease( next_media );
766 } while( ( next_media = IOIteratorNext( media_iterator ) ) != NULL );
769 IOObjectRelease( media_iterator );
771 [fDVDPopUp removeAllItems];
772 for( unsigned i = 0; i < [drivesList count]; i++ )
774 [[fDVDPopUp menu] addItemWithTitle:
775 [drivesList objectAtIndex: i] action: nil
778 [self ScanMatrixChanged: self];
781 - (IBAction) ScanMatrixChanged: (id) sender
783 if( ![fScanMatrix selectedRow] )
785 [fDVDPopUp setEnabled: YES];
786 [fDVDFolderField setEnabled: NO];
787 [fScanBrowseButton setEnabled: NO];
788 [fScanButton setEnabled: ( [fDVDPopUp selectedItem] != nil )];
792 [fDVDPopUp setEnabled: NO];
793 [fDVDFolderField setEnabled: YES];
794 [fScanBrowseButton setEnabled: YES];
795 [fScanButton setEnabled: YES];
799 - (IBAction) TitlePopUpChanged: (id) sender
801 HBTitle * title = (HBTitle*)
802 HBListItemAt( fTitleList, [fTitlePopUp indexOfSelectedItem] );
804 [fLanguagePopUp removeAllItems];
805 [fSecondaryLanguagePopUp removeAllItems];
808 for( int i = 0; i < HBListCountItems( title->audioList ); i++ )
810 audio = (HBAudio*) HBListItemAt( title->audioList, i );
812 /* We cannot use NSPopUpButton's addItemWithTitle because
813 it checks for duplicate entries */
814 [[fLanguagePopUp menu] addItemWithTitle:
815 [NSString stringWithCString: audio->language]
816 action: nil keyEquivalent: @""];
817 [[fSecondaryLanguagePopUp menu] addItemWithTitle:
818 [NSString stringWithCString: audio->language]
819 action: nil keyEquivalent: @""];
821 [fSecondaryLanguagePopUp addItemWithTitle: @"None"];
822 [fSecondaryLanguagePopUp selectItemWithTitle: @"None"];
823 [fSecondaryLanguagePopUp setEnabled:
824 ( HBListCountItems( title->audioList ) > 1 )];
826 [fTargetSizeField SetHBTitle: title];
827 if( [fVideoMatrix selectedRow] )
829 [fTargetSizeField UpdateBitrate];
833 - (IBAction) VideoCodecPopUpChanged: (id) sender
835 if( [[fVideoCodecPopUp titleOfSelectedItem]
836 compare: @"MPEG-4 (Ffmpeg)"] == NSOrderedSame )
838 [fTwoPassCheck setEnabled: YES];
842 [fTwoPassCheck setState: NSOffState];
843 [fTwoPassCheck setEnabled: NO];
847 - (IBAction) AudioPopUpChanged: (id) sender
849 if( [fVideoMatrix selectedRow] )
851 [fTargetSizeField UpdateBitrate];