/* $Id: Controller.mm,v 1.9 2003/11/09 22:06:15 titer Exp $
This file is part of the HandBrake source code.
Homepage: .
It may be used under the terms of the GNU General Public License. */
#include
#include
#include
#include
#include
#include "Controller.h"
@implementation HBController
- (void) applicationDidFinishLaunching: (NSNotification *) notification
{
/* Init libhb */
fHandle = HBInit( 1, 0 );
[fPictureGLView SetHandle: fHandle];
/* Update the GUI every 1/10 sec */
fDie = false;
[NSTimer scheduledTimerWithTimeInterval: 0.1
target: self selector: @selector( UpdateIntf: )
userInfo: nil repeats: YES];
/* Detect drives mounted after the app is started */
[[[NSWorkspace sharedWorkspace] notificationCenter]
addObserver: self selector: @selector( DetectDrives: )
name: NSWorkspaceDidMountNotification object: nil];
}
- (NSApplicationTerminateReply) applicationShouldTerminate:
(NSApplication *) app
{
/* Clean up */
fDie = true;
HBClose( &fHandle );
return NSTerminateNow;
}
- (void) awakeFromNib
{
[fDVDPopUp removeAllItems];
[fScanProgress setStyle: NSProgressIndicatorSpinningStyle];
[fScanProgress setDisplayedWhenStopped: NO];
[fVideoCodecPopUp removeAllItems];
[fVideoCodecPopUp addItemWithTitle: @"MPEG-4 (Ffmpeg)"];
[fVideoCodecPopUp addItemWithTitle: @"MPEG-4 (XviD)"];
[fVideoCodecPopUp selectItemWithTitle: @"MPEG-4 (Ffmpeg)"];
[fAudioBitratePopUp removeAllItems];
[fAudioBitratePopUp addItemWithTitle: @"32"];
[fAudioBitratePopUp addItemWithTitle: @"64"];
[fAudioBitratePopUp addItemWithTitle: @"96"];
[fAudioBitratePopUp addItemWithTitle: @"128"];
[fAudioBitratePopUp addItemWithTitle: @"160"];
[fAudioBitratePopUp addItemWithTitle: @"192"];
[fAudioBitratePopUp addItemWithTitle: @"224"];
[fAudioBitratePopUp addItemWithTitle: @"256"];
[fAudioBitratePopUp addItemWithTitle: @"288"];
[fAudioBitratePopUp addItemWithTitle: @"320"];
[fAudioBitratePopUp selectItemWithTitle: @"128"];
char string[1024]; memset( string, 0, 1024 );
snprintf( string, 1024, "%s/Desktop/Movie.avi", getenv( "HOME" ) );
[fFileField setStringValue: [NSString stringWithCString: string]];
/* Show the scan view */
[fWindow setContentSize: [fScanView frame].size];
[fWindow setContentView: fScanView];
[fWindow center];
/* Detect DVD drives */
[self DetectDrives: nil];
[self ScanMatrixChanged: self];
}
- (BOOL) windowShouldClose: (id) sender
{
/* Stop the application when the user closes the window */
[NSApp terminate: self];
return YES;
}
- (IBAction) BrowseDVD: (id) sender
{
/* Open a panel to let the user choose and update the text field */
NSOpenPanel * panel = [NSOpenPanel openPanel];
[panel setAllowsMultipleSelection: NO];
[panel setCanChooseFiles: NO];
[panel setCanChooseDirectories: YES ];
[panel beginSheetForDirectory: nil file: nil types: nil
modalForWindow: fWindow modalDelegate: self
didEndSelector: @selector( BrowseDVDDone:returnCode:contextInfo: )
contextInfo: nil];
}
- (void) BrowseDVDDone: (NSOpenPanel *) sheet
returnCode: (int) returnCode contextInfo: (void *) contextInfo
{
if( returnCode == NSOKButton )
{
[fDVDFolderField setStringValue:
[[sheet filenames] objectAtIndex: 0]];
}
}
- (IBAction) VideoMatrixChanged: (id) sender;
{
if( ![fVideoMatrix selectedRow] )
{
[fCustomBitrateField setEnabled: YES];
[fTargetSizeField setEnabled: NO];
}
else
{
[fCustomBitrateField setEnabled: NO];
[fTargetSizeField setEnabled: YES];
[fTargetSizeField UpdateBitrate];
}
}
- (IBAction) BrowseFile: (id) sender
{
/* Open a panel to let the user choose and update the text field */
NSSavePanel * panel = [NSSavePanel savePanel];
[panel beginSheetForDirectory: nil file: nil
modalForWindow: fWindow modalDelegate: self
didEndSelector: @selector( BrowseFileDone:returnCode:contextInfo: )
contextInfo: nil];
}
- (void) BrowseFileDone: (NSSavePanel *) sheet
returnCode: (int) returnCode contextInfo: (void *) contextInfo
{
if( returnCode == NSOKButton )
{
[fFileField setStringValue: [sheet filename]];
}
}
- (IBAction) Scan: (id) sender
{
/* Ask libhb to start scanning the specified volume */
if( ![fScanMatrix selectedRow] )
{
/* DVD drive */
HBScanDevice( fHandle,
(char*) [[fDVDPopUp titleOfSelectedItem] cString],
0 );
}
else
{
/* DVD folder */
HBScanDevice( fHandle,
(char*) [[fDVDFolderField stringValue] cString],
0 );
}
}
- (IBAction) ShowPicturePanel: (id) sender
{
HBTitle * title = (HBTitle*)
HBListItemAt( fTitleList, [fTitlePopUp indexOfSelectedItem] );
[fPictureGLView SetTitle: title];
fPicture = 0;
[fPictureGLView ShowPicture: fPicture animate: HB_ANIMATE_NONE];
[fWidthStepper setValueWraps: NO];
[fWidthStepper setIncrement: 16];
[fWidthStepper setMinValue: 16];
[fWidthStepper setMaxValue: title->outWidthMax];
[fWidthStepper setIntValue: title->outWidth];
[fWidthField setIntValue: title->outWidth];
[fDeinterlaceCheck setState:
title->deinterlace ? NSOnState : NSOffState];
[fTopStepper setValueWraps: NO];
[fTopStepper setIncrement: 2];
[fTopStepper setMinValue: 0];
[fTopStepper setMaxValue: title->inHeight / 4];
[fTopStepper setIntValue: title->topCrop];
[fTopField setIntValue: title->topCrop];
[fBottomStepper setValueWraps: NO];
[fBottomStepper setIncrement: 2];
[fBottomStepper setMinValue: 0];
[fBottomStepper setMaxValue: title->inHeight / 4];
[fBottomStepper setIntValue: title->bottomCrop];
[fBottomField setIntValue: title->bottomCrop];
[fLeftStepper setValueWraps: NO];
[fLeftStepper setIncrement: 2];
[fLeftStepper setMinValue: 0];
[fLeftStepper setMaxValue: title->inWidth / 4];
[fLeftStepper setIntValue: title->leftCrop];
[fLeftField setIntValue: title->leftCrop];
[fRightStepper setValueWraps: NO];
[fRightStepper setIncrement: 2];
[fRightStepper setMinValue: 0];
[fRightStepper setMaxValue: title->inWidth / 4];
[fRightStepper setIntValue: title->rightCrop];
[fRightField setIntValue: title->rightCrop];
[fPreviousButton setEnabled: NO];
[fNextButton setEnabled: YES];
char string[1024]; memset( string, 0, 1024 );
sprintf( string, "Final size: %dx%d",
title->outWidth, title->outHeight );
[fInfoField setStringValue: [NSString stringWithCString: string]];
/* Resize the panel */
NSSize newSize;
/* XXX */
newSize.width = 762 /*fPicturePanelSize.width*/ +
title->outWidthMax - 720;
newSize.height = 740 /*fPicturePanelSize.height*/ +
title->outHeightMax - 576;
[fPicturePanel setContentSize: newSize];
[NSApp beginSheet: fPicturePanel modalForWindow: fWindow
modalDelegate: nil didEndSelector: nil contextInfo: nil];
[NSApp runModalForWindow: fPicturePanel];
[NSApp endSheet: fPicturePanel];
[fPicturePanel orderOut: self];
}
- (IBAction) ClosePanel: (id) sender
{
[NSApp stopModal];
}
- (IBAction) Rip: (id) sender
{
/* Rip or Cancel ? */
if( [[fRipButton title] compare: @"Cancel" ] == NSOrderedSame )
{
[self Cancel: self];
return;
}
if( [fCustomBitrateField intValue] < 256 )
{
NSBeginCriticalAlertSheet( @"Invalid video bitrate", @"Ooops",
nil, nil, fWindow, self, nil, nil, nil,
@"Video bitrate is too low !" );
return;
}
if( [fCustomBitrateField intValue] > 8192 )
{
NSBeginCriticalAlertSheet( @"Invalid video bitrate", @"Ooops",
nil, nil, fWindow, self, nil, nil, nil,
@"Video bitrate is too high !" );
return;
}
if( [fLanguagePopUp indexOfSelectedItem] ==
[fSecondaryLanguagePopUp indexOfSelectedItem] )
{
NSBeginCriticalAlertSheet( @"Invalid secondary language",
@"Ooops", nil, nil, fWindow, self, nil, nil, nil,
@"Do you _really_ want to encode the same audio track twice?" );
return;
}
FILE * file;
if( ( file = fopen( [[fFileField stringValue] cString], "r" ) ) )
{
fclose( file );
NSBeginCriticalAlertSheet( @"File already exists",
@"Nooo!", @"Yes, go ahead", nil, fWindow, self,
@selector( OverwriteAlertDone:returnCode:contextInfo: ),
nil, nil,
[NSString stringWithFormat: @"Do you want to overwrite %s?",
[[fFileField stringValue] cString]] );
return;
}
[self _Rip];
}
- (void) OverwriteAlertDone: (NSWindow *) sheet
returnCode: (int) returnCode contextInfo: (void *) contextInfo
{
if( returnCode == NSAlertAlternateReturn )
{
[self _Rip];
}
}
- (void) _Rip
{
/* Get the specified title & audio track(s) */
HBTitle * title = (HBTitle*)
HBListItemAt( fTitleList, [fTitlePopUp indexOfSelectedItem] );
HBAudio * audio1 = (HBAudio*)
HBListItemAt( title->audioList,
[fLanguagePopUp indexOfSelectedItem] );
HBAudio * audio2 = (HBAudio*)
HBListItemAt( title->audioList,
[fSecondaryLanguagePopUp indexOfSelectedItem] );
/* Use user settings */
title->file = strdup( [[fFileField stringValue] cString] );
title->bitrate = [fCustomBitrateField intValue];
title->twoPass = ( [fTwoPassCheck state] == NSOnState );
title->codec = ( [[fVideoCodecPopUp titleOfSelectedItem] compare:
@"MPEG-4 (Ffmpeg)"] == NSOrderedSame ) ?
HB_CODEC_FFMPEG : HB_CODEC_XVID;
audio1->outBitrate = [[fAudioBitratePopUp titleOfSelectedItem]
intValue];
if( audio2 )
{
audio2->outBitrate =
[[fAudioBitratePopUp titleOfSelectedItem] intValue];
}
/* Let libhb do the job */
HBStartRip( fHandle, title, audio1, audio2 );
}
- (IBAction) Cancel: (id) sender
{
HBStopRip( fHandle );
}
- (IBAction) Suspend: (id) sender
{
if( [[fSuspendButton title] compare: @"Resume" ] == NSOrderedSame )
{
[self Resume: self];
return;
}
HBPauseRip( fHandle );
}
- (IBAction) Resume: (id) sender
{
HBResumeRip( fHandle );
}
- (IBAction) PreviousPicture: (id) sender
{
fPicture--;
if( [fOpenGLCheck state] == NSOnState )
{
[fPictureGLView ShowPicture: fPicture
animate: HB_ANIMATE_LEFT];
}
else
{
[fPictureGLView ShowPicture: fPicture
animate: HB_ANIMATE_NONE];
}
[fPreviousButton setEnabled: ( fPicture > 0 )];
[fNextButton setEnabled: YES];
}
- (IBAction) NextPicture: (id) sender
{
fPicture++;
if( [fOpenGLCheck state] == NSOnState )
{
[fPictureGLView ShowPicture: fPicture
animate: HB_ANIMATE_RIGHT];
}
else
{
[fPictureGLView ShowPicture: fPicture
animate: HB_ANIMATE_NONE];
}
[fPreviousButton setEnabled: YES];
[fNextButton setEnabled: ( fPicture < 9 )];
}
- (IBAction) UpdatePicture: (id) sender
{
HBTitle * title = (HBTitle*)
HBListItemAt( fTitleList, [fTitlePopUp indexOfSelectedItem] );
title->outWidth = [fWidthStepper intValue];
title->deinterlace = ( [fDeinterlaceCheck state] == NSOnState );
title->topCrop = [fTopStepper intValue];
title->bottomCrop = [fBottomStepper intValue];
title->leftCrop = [fLeftStepper intValue];
title->rightCrop = [fRightStepper intValue];
[fPictureGLView ShowPicture: fPicture animate: HB_ANIMATE_NONE];
[fWidthStepper setIntValue: title->outWidth];
[fTopStepper setIntValue: title->topCrop];
[fBottomStepper setIntValue: title->bottomCrop];
[fLeftStepper setIntValue: title->leftCrop];
[fRightStepper setIntValue: title->rightCrop];
[fWidthField setIntValue: [fWidthStepper intValue]];
[fTopField setIntValue: [fTopStepper intValue]];
[fBottomField setIntValue: [fBottomStepper intValue]];
[fLeftField setIntValue: [fLeftStepper intValue]];
[fRightField setIntValue: [fRightStepper intValue]];
char string[1024]; memset( string, 0, 1024 );
sprintf( string, "Final size: %dx%d",
title->outWidth, title->outHeight );
[fInfoField setStringValue: [NSString stringWithCString: string]];
}
- (void) UpdateIntf: (NSTimer *) timer
{
if( fDie )
{
[timer invalidate];
return;
}
int modeChanged;
HBStatus status;
modeChanged = HBGetStatus( fHandle, &status );
switch( status.mode )
{
case HB_MODE_NEED_DEVICE:
break;
case HB_MODE_SCANNING:
{
if( modeChanged )
{
[fScanMatrix setEnabled: NO];
[fDVDPopUp setEnabled: NO];
[fDVDFolderField setEnabled: NO];
[fScanBrowseButton setEnabled: NO];
[fScanProgress startAnimation: self];
[fScanButton setEnabled: NO];
}
char string[1024]; memset( string, 0, 1024 );
if( status.scannedTitle )
{
sprintf( string, "Scanning title %d...",
status.scannedTitle );
}
else
{
sprintf( string, "Opening device..." );
}
[fScanStatusField setStringValue:
[NSString stringWithCString: string]];
break;
}
case HB_MODE_INVALID_DEVICE:
{
if( !modeChanged )
break;
[fScanMatrix setEnabled: YES];
[self ScanMatrixChanged: self];
[fScanProgress stopAnimation: self];
[fScanButton setEnabled: YES];
[fScanStatusField setStringValue:
@"Invalid volume, try again" ];
break;
}
case HB_MODE_READY_TO_RIP:
{
if( !modeChanged )
break;
fTitleList = status.titleList;
/* Show a temporary empty view while the window
resizing animation */
[fWindow setContentView: fTempView ];
/* Actually resize it */
NSRect newFrame;
newFrame = [NSWindow contentRectForFrameRect: [fWindow frame]
styleMask: [fWindow styleMask]];
newFrame.origin.y += newFrame.size.height -
[fRipView frame].size.height;
newFrame.size.height = [fRipView frame].size.height;
newFrame.size.width = [fRipView frame].size.width;
newFrame = [NSWindow frameRectForContentRect: newFrame
styleMask: [fWindow styleMask]];
[fWindow setFrame: newFrame display: YES animate: YES];
/* Show the new GUI */
[fWindow setContentView: fRipView ];
[fSuspendButton setEnabled: NO];
[fTitlePopUp removeAllItems];
HBTitle * title;
for( int i = 0; i < HBListCountItems( fTitleList ); i++ )
{
title = (HBTitle*) HBListItemAt( fTitleList, i );
char string[1024]; memset( string, 0, 1024 );
sprintf( string, "%d - %02dh%02dm%02ds",
title->index, title->length / 3600,
( title->length % 3600 ) / 60,
title->length % 60 );
[[fTitlePopUp menu] addItemWithTitle:
[NSString stringWithCString: string]
action: nil keyEquivalent: @""];
}
[self TitlePopUpChanged: self];
break;
}
case HB_MODE_ENCODING:
{
if( modeChanged )
{
[fTitlePopUp setEnabled: NO];
[fVideoCodecPopUp setEnabled: NO];
[fVideoMatrix setEnabled: NO];
[fCustomBitrateField setEnabled: NO];
[fTargetSizeField setEnabled: NO];
[fTwoPassCheck setEnabled: NO];
[fCropButton setEnabled: NO];
[fLanguagePopUp setEnabled: NO];
[fSecondaryLanguagePopUp setEnabled: NO];
[fAudioCodecPopUp setEnabled: NO];
[fAudioBitratePopUp setEnabled: NO];
[fFileFormatPopUp setEnabled: NO];
[fFileField setEnabled: NO];
[fFileBrowseButton setEnabled: NO];
[fSuspendButton setEnabled: YES];
[fSuspendButton setTitle: @"Suspend"];
[fRipButton setTitle: @"Cancel"];
}
if( !status.position )
{
[fRipStatusField setStringValue: @"Starting..."];
[fRipProgress setIndeterminate: YES];
[fRipProgress startAnimation: self];;
}
else
{
char string[1024];
memset( string, 0, 1024 );
sprintf( string, "Encoding: %.2f %% (pass %d of %d)",
100 * status.position, status.pass,
status.passCount );
[fRipStatusField setStringValue:
[NSString stringWithCString: string]];
memset( string, 0, 1024 );
sprintf( string, "Speed: %.2f fps (avg %.2f fps, "
"%02dh%02dm%02ds remaining)",
status.frameRate, status.avFrameRate,
status.remainingTime / 3600,
( status.remainingTime / 60 ) % 60,
status.remainingTime % 60 );
[fRipInfoField setStringValue:
[NSString stringWithCString: string]];
[fRipProgress setIndeterminate: NO];
[fRipProgress setDoubleValue: 100 * status.position];
}
break;
}
case HB_MODE_PAUSED:
{
if( !modeChanged )
break;
char string[1024]; memset( string, 0, 1024 );
sprintf( string, "Encoding: %.2f %% (PAUSED)",
100 * status.position ) ;
[fRipStatusField setStringValue:
[NSString stringWithCString: string]];
[fRipInfoField setStringValue: @""];
[fRipProgress setDoubleValue: 100 * status.position];
[fSuspendButton setTitle: @"Resume"];
break;
}
case HB_MODE_STOPPING:
if( !modeChanged )
break;
[fRipStatusField setStringValue: @"Stopping..."];
[fRipInfoField setStringValue: @""];
[fRipProgress setIndeterminate: YES];
[fRipProgress startAnimation: self];;
break;
case HB_MODE_DONE:
case HB_MODE_CANCELED:
case HB_MODE_ERROR:
if( !modeChanged )
break;
/* Warn the finder to update itself */
[[NSWorkspace sharedWorkspace] noteFileSystemChanged:
[fFileField stringValue]];
[fRipProgress setIndeterminate: NO];
[fRipInfoField setStringValue: @""];
if( status.mode == HB_MODE_DONE )
{
[fRipProgress setDoubleValue: 100];
[fRipStatusField setStringValue: @"Done." ];
NSBeep();
[NSApp requestUserAttention: NSInformationalRequest];
[NSApp beginSheet: fDonePanel
modalForWindow: fWindow modalDelegate: nil
didEndSelector: nil contextInfo: nil];
[NSApp runModalForWindow: fDonePanel];
[NSApp endSheet: fDonePanel];
[fDonePanel orderOut: self];
}
else if( status.mode == HB_MODE_CANCELED )
{
[fRipProgress setDoubleValue: 0];
[fRipStatusField setStringValue: @"Canceled." ];
}
else
{
[fRipProgress setDoubleValue: 0];
switch( status.error )
{
case HB_ERROR_A52_SYNC:
[fRipStatusField setStringValue:
@"An error occured (corrupted AC3 data)." ];
break;
case HB_ERROR_AVI_WRITE:
[fRipStatusField setStringValue:
@"An error occured (could not write to file)." ];
break;
case HB_ERROR_DVD_OPEN:
[fRipStatusField setStringValue:
@"An error occured (could not open device)." ];
break;
case HB_ERROR_DVD_READ:
[fRipStatusField setStringValue:
@"An error occured (DVD read failed)." ];
break;
case HB_ERROR_MP3_INIT:
[fRipStatusField setStringValue:
@"An error occured (could not init MP3 encoder)." ];
break;
case HB_ERROR_MP3_ENCODE:
[fRipStatusField setStringValue:
@"An error occured (MP3 encoder failed)." ];
break;
case HB_ERROR_MPEG4_INIT:
[fRipStatusField setStringValue:
@"An error occured (could not init MPEG4 encoder)." ];
break;
}
}
[fTitlePopUp setEnabled: YES];
[fVideoCodecPopUp setEnabled: YES];
[fVideoMatrix setEnabled: YES];
[fTwoPassCheck setEnabled: YES];
[fCropButton setEnabled: YES];
[fLanguagePopUp setEnabled: YES];
[fSecondaryLanguagePopUp setEnabled: YES];
[fAudioCodecPopUp setEnabled: YES];
[fAudioBitratePopUp setEnabled: YES];
[fFileFormatPopUp setEnabled: YES];
[fFileField setEnabled: YES];
[fFileBrowseButton setEnabled: YES];
[fSuspendButton setEnabled: NO];
[fSuspendButton setTitle: @"Suspend"];
[fRipButton setTitle: @"Rip"];
[self VideoMatrixChanged: self];
break;
default:
break;
}
}
- (void) DetectDrives: (NSNotification *) notification
{
/* Scan DVD drives (stolen from VLC) */
io_object_t next_media;
mach_port_t master_port;
kern_return_t kern_result;
io_iterator_t media_iterator;
CFMutableDictionaryRef classes_to_match;
kern_result = IOMasterPort( MACH_PORT_NULL, &master_port );
if( kern_result != KERN_SUCCESS )
{
return;
}
classes_to_match = IOServiceMatching( kIODVDMediaClass );
if( classes_to_match == NULL )
{
return;
}
CFDictionarySetValue( classes_to_match, CFSTR( kIOMediaEjectableKey ),
kCFBooleanTrue );
kern_result =
IOServiceGetMatchingServices( master_port, classes_to_match,
&media_iterator );
if( kern_result != KERN_SUCCESS )
{
return;
}
NSMutableArray * drivesList;
drivesList = [NSMutableArray arrayWithCapacity: 1];
next_media = IOIteratorNext( media_iterator );
if( next_media != NULL )
{
char psz_buf[0x32];
size_t dev_path_length;
CFTypeRef str_bsd_path;
do
{
str_bsd_path =
IORegistryEntryCreateCFProperty( next_media,
CFSTR( kIOBSDNameKey ),
kCFAllocatorDefault,
0 );
if( str_bsd_path == NULL )
{
IOObjectRelease( next_media );
continue;
}
snprintf( psz_buf, sizeof(psz_buf), "%s%c", _PATH_DEV, 'r' );
dev_path_length = strlen( psz_buf );
if( CFStringGetCString( (CFStringRef) str_bsd_path,
(char*)&psz_buf + dev_path_length,
sizeof(psz_buf) - dev_path_length,
kCFStringEncodingASCII ) )
{
[drivesList addObject:
[NSString stringWithCString: psz_buf]];
}
CFRelease( str_bsd_path );
IOObjectRelease( next_media );
} while( ( next_media = IOIteratorNext( media_iterator ) ) != NULL );
}
IOObjectRelease( media_iterator );
[fDVDPopUp removeAllItems];
for( unsigned i = 0; i < [drivesList count]; i++ )
{
[[fDVDPopUp menu] addItemWithTitle:
[drivesList objectAtIndex: i] action: nil
keyEquivalent: @""];
}
[self ScanMatrixChanged: self];
}
- (IBAction) ScanMatrixChanged: (id) sender
{
if( ![fScanMatrix selectedRow] )
{
[fDVDPopUp setEnabled: YES];
[fDVDFolderField setEnabled: NO];
[fScanBrowseButton setEnabled: NO];
[fScanButton setEnabled: ( [fDVDPopUp selectedItem] != nil )];
}
else
{
[fDVDPopUp setEnabled: NO];
[fDVDFolderField setEnabled: YES];
[fScanBrowseButton setEnabled: YES];
[fScanButton setEnabled: YES];
}
}
- (IBAction) TitlePopUpChanged: (id) sender
{
HBTitle * title = (HBTitle*)
HBListItemAt( fTitleList, [fTitlePopUp indexOfSelectedItem] );
[fLanguagePopUp removeAllItems];
[fSecondaryLanguagePopUp removeAllItems];
HBAudio * audio;
for( int i = 0; i < HBListCountItems( title->audioList ); i++ )
{
audio = (HBAudio*) HBListItemAt( title->audioList, i );
/* We cannot use NSPopUpButton's addItemWithTitle because
it checks for duplicate entries */
[[fLanguagePopUp menu] addItemWithTitle:
[NSString stringWithCString: audio->language]
action: nil keyEquivalent: @""];
[[fSecondaryLanguagePopUp menu] addItemWithTitle:
[NSString stringWithCString: audio->language]
action: nil keyEquivalent: @""];
}
[fSecondaryLanguagePopUp addItemWithTitle: @"None"];
[fSecondaryLanguagePopUp selectItemWithTitle: @"None"];
[fSecondaryLanguagePopUp setEnabled:
( HBListCountItems( title->audioList ) > 1 )];
[fTargetSizeField SetHBTitle: title];
if( [fVideoMatrix selectedRow] )
{
[fTargetSizeField UpdateBitrate];
}
}
- (IBAction) AudioPopUpChanged: (id) sender
{
if( [fVideoMatrix selectedRow] )
{
[fTargetSizeField UpdateBitrate];
}
}
@end