summaryrefslogtreecommitdiffstats
path: root/macosx/InstantHandBrake
diff options
context:
space:
mode:
authorritsuka <[email protected]>2008-01-11 17:48:18 +0000
committerritsuka <[email protected]>2008-01-11 17:48:18 +0000
commit3caeaf135a8838fbc3f6a261bd7a66962a1bd5f5 (patch)
treefaf286fde0354e240e6d343f5268e7a0bb583216 /macosx/InstantHandBrake
parent709c565f9e47282236b01ba1eb980c31221659f1 (diff)
MacGUI: move IHB source code to his own folder.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@1185 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'macosx/InstantHandBrake')
-rw-r--r--macosx/InstantHandBrake/DriveDetector.h23
-rw-r--r--macosx/InstantHandBrake/DriveDetector.m142
-rw-r--r--macosx/InstantHandBrake/English.lproj/Express.nib/classes.nib132
-rw-r--r--macosx/InstantHandBrake/English.lproj/Express.nib/info.nib29
-rw-r--r--macosx/InstantHandBrake/English.lproj/Express.nib/keyedobjects.nibbin0 -> 36301 bytes
-rw-r--r--macosx/InstantHandBrake/Express.plist26
-rw-r--r--macosx/InstantHandBrake/ExpressController.h55
-rw-r--r--macosx/InstantHandBrake/ExpressController.m701
-rw-r--r--macosx/InstantHandBrake/WhiteBox.h8
-rw-r--r--macosx/InstantHandBrake/WhiteBox.m12
10 files changed, 1128 insertions, 0 deletions
diff --git a/macosx/InstantHandBrake/DriveDetector.h b/macosx/InstantHandBrake/DriveDetector.h
new file mode 100644
index 000000000..2018309b1
--- /dev/null
+++ b/macosx/InstantHandBrake/DriveDetector.h
@@ -0,0 +1,23 @@
+/* DriveDetector.h $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#import <Cocoa/Cocoa.h>
+
+@interface DriveDetector : NSObject
+{
+ id fTarget;
+ SEL fSelector;
+
+ int fCount;
+ NSMutableDictionary * fDrives;
+ NSTimer * fTimer;
+}
+
+- (id) initWithCallback: (id) target selector: (SEL) selector;
+- (void) run;
+- (void) stop;
+
+@end
diff --git a/macosx/InstantHandBrake/DriveDetector.m b/macosx/InstantHandBrake/DriveDetector.m
new file mode 100644
index 000000000..61f722960
--- /dev/null
+++ b/macosx/InstantHandBrake/DriveDetector.m
@@ -0,0 +1,142 @@
+/* DriveDetector.m $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://handbrake.m0k.org/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include <paths.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOBSD.h>
+#include <IOKit/storage/IOMedia.h>
+#include <IOKit/storage/IODVDMedia.h>
+
+#include "DriveDetector.h"
+#include "hb.h"
+
+@interface DriveDetector (Private)
+
+- (void) detectTimer: (NSTimer *) timer;
+
+@end
+
+@implementation DriveDetector
+
+- (void) dealloc
+{
+ [fDrives release];
+ [super dealloc];
+}
+
+- (id) initWithCallback: (id) target selector: (SEL) selector
+{
+ fTarget = target;
+ fSelector = selector;
+
+ fCount = -1;
+ fDrives = [[NSMutableDictionary alloc] initWithCapacity: 1];
+
+ return self;
+}
+
+- (void) run
+{
+ /* Set up a timer to check devices every second */
+ fTimer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target: self
+ selector: @selector( detectTimer: ) userInfo: nil repeats: YES];
+ [[NSRunLoop currentRunLoop] addTimer: fTimer forMode:
+ NSModalPanelRunLoopMode];
+
+ /* Do a first update right away */
+ [fTimer fire];
+}
+
+- (void) stop
+{
+ [fTimer invalidate];
+}
+
+- (void) detectTimer: (NSTimer *) timer
+{
+ /* 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;
+ }
+
+ [fDrives removeAllObjects];
+
+ next_media = IOIteratorNext( media_iterator );
+ if( next_media )
+ {
+ char * name;
+ 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 ) )
+ {
+ if( ( name = hb_dvd_name( psz_buf ) ) )
+ {
+ [fDrives setObject: [NSString stringWithCString: psz_buf]
+ forKey: [NSString stringWithCString: name]];
+ }
+ }
+
+ CFRelease( str_bsd_path );
+
+ IOObjectRelease( next_media );
+
+ } while( ( next_media = IOIteratorNext( media_iterator ) ) );
+ }
+
+ IOObjectRelease( media_iterator );
+
+ if( [fDrives count] != fCount )
+ {
+ [fTarget performSelector: fSelector withObject: fDrives];
+ fCount = [fDrives count];
+ }
+}
+
+@end
diff --git a/macosx/InstantHandBrake/English.lproj/Express.nib/classes.nib b/macosx/InstantHandBrake/English.lproj/Express.nib/classes.nib
new file mode 100644
index 000000000..3a057282c
--- /dev/null
+++ b/macosx/InstantHandBrake/English.lproj/Express.nib/classes.nib
@@ -0,0 +1,132 @@
+{
+ IBClasses = (
+ {
+ ACTIONS = {
+ convertGo = id;
+ openBrowse = id;
+ openGo = id;
+ openMatrixChanged = id;
+ openShow = id;
+ };
+ CLASS = EmbeddedController;
+ LANGUAGE = ObjC;
+ OUTLETS = {
+ fConvertFolderPopUp = NSPopUpButton;
+ fConvertIndicator = NSProgressIndicator;
+ fConvertTableView = NSTableView;
+ fConvertView = NSView;
+ fEmptyView = NSView;
+ fOpenBrowseButton = NSButton;
+ fOpenFolderField = NSTextField;
+ fOpenGoButton = NSButton;
+ fOpenIndicator = NSProgressIndicator;
+ fOpenMatrix = NSMatrix;
+ fOpenPopUp = NSPopUpButton;
+ fOpenView = NSView;
+ fWindow = NSWindow;
+ };
+ SUPERCLASS = NSObject;
+ },
+ {
+ ACTIONS = {
+ convertCancel = id;
+ convertGo = id;
+ openBrowse = id;
+ openGo = id;
+ openMatrixChanged = id;
+ openShow = id;
+ };
+ CLASS = ExpressController;
+ LANGUAGE = ObjC;
+ OUTLETS = {
+ fConvertAspectPopUp = NSPopUpButton;
+ fConvertAudioPopUp = NSPopUpButton;
+ fConvertFolderPopUp = NSPopUpButton;
+ fConvertFormatPopUp = NSPopUpButton;
+ fConvertGoButton = NSButton;
+ fConvertIndicator = NSProgressIndicator;
+ fConvertInfoString = NSTextField;
+ fConvertMaxWidthPopUp = NSPopUpButton;
+ fConvertOpenButton = NSButton;
+ fConvertSubtitlePopUp = NSPopUpButton;
+ fConvertTableView = NSTableView;
+ fConvertView = NSView;
+ fEmptyView = NSView;
+ fOpenBrowseButton = NSButton;
+ fOpenFolderField = NSTextField;
+ fOpenGoButton = NSButton;
+ fOpenIndicator = NSProgressIndicator;
+ fOpenMatrix = NSMatrix;
+ fOpenPopUp = NSPopUpButton;
+ fOpenProgressField = NSTextField;
+ fOpenView = NSView;
+ fWindow = NSWindow;
+ };
+ SUPERCLASS = NSObject;
+ },
+ {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
+ {
+ ACTIONS = {
+ ClosePanel = id;
+ NextPicture = id;
+ PreviousPicture = id;
+ SettingsChanged = id;
+ };
+ CLASS = PictureController;
+ LANGUAGE = ObjC;
+ OUTLETS = {
+ fCropBottomField = NSTextField;
+ fCropBottomStepper = NSStepper;
+ fCropLeftField = NSTextField;
+ fCropLeftStepper = NSStepper;
+ fCropMatrix = NSMatrix;
+ fCropRightField = NSTextField;
+ fCropRightStepper = NSStepper;
+ fCropTopField = NSTextField;
+ fCropTopStepper = NSStepper;
+ fDeinterlaceCheck = NSButton;
+ fEffectsCheck = NSButton;
+ fHeightField = NSTextField;
+ fHeightStepper = NSStepper;
+ fInfoField = NSTextField;
+ fNextButton = NSButton;
+ fPictureGLView = HBPictureGLView;
+ fPrevButton = NSButton;
+ fRatioCheck = NSButton;
+ fWidthField = NSTextField;
+ fWidthStepper = NSStepper;
+ };
+ SUPERCLASS = NSObject;
+ },
+ {
+ ACTIONS = {
+ convertGo = id;
+ openBrowse = id;
+ openGo = id;
+ openMatrixChanged = id;
+ openShow = id;
+ };
+ CLASS = PortableController;
+ LANGUAGE = ObjC;
+ OUTLETS = {
+ fConvertFolderPopUp = NSPopUpButton;
+ fConvertIndicator = NSProgressIndicator;
+ fConvertTableView = NSTableView;
+ fConvertView = NSView;
+ fEmptyView = NSView;
+ fOpenBrowseButton = NSButton;
+ fOpenFolderField = NSTextField;
+ fOpenGoButton = NSButton;
+ fOpenIndicator = NSProgressIndicator;
+ fOpenMatrix = NSMatrix;
+ fOpenPopUp = NSPopUpButton;
+ fOpenProgressField = NSTextField;
+ fOpenView = NSView;
+ fWindow = NSWindow;
+ };
+ SUPERCLASS = NSObject;
+ },
+ {CLASS = WhiteBox; LANGUAGE = ObjC; SUPERCLASS = NSBox; }
+ );
+ IBVersion = 1;
+} \ No newline at end of file
diff --git a/macosx/InstantHandBrake/English.lproj/Express.nib/info.nib b/macosx/InstantHandBrake/English.lproj/Express.nib/info.nib
new file mode 100644
index 000000000..f63c2715a
--- /dev/null
+++ b/macosx/InstantHandBrake/English.lproj/Express.nib/info.nib
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IBDocumentLocation</key>
+ <string>80 374 371 303 0 0 1440 878 </string>
+ <key>IBEditorPositions</key>
+ <dict>
+ <key>248</key>
+ <string>487 424 408 321 0 0 1440 878 </string>
+ <key>259</key>
+ <string>516 359 408 488 0 0 1440 878 </string>
+ <key>29</key>
+ <string>33 298 338 44 0 0 1280 832 </string>
+ <key>303</key>
+ <string>543 501 155 107 0 0 1280 832 </string>
+ </dict>
+ <key>IBFramework Version</key>
+ <string>446.1</string>
+ <key>IBOldestOS</key>
+ <integer>2</integer>
+ <key>IBOpenObjects</key>
+ <array>
+ <integer>259</integer>
+ </array>
+ <key>IBSystem Version</key>
+ <string>8L2127</string>
+</dict>
+</plist>
diff --git a/macosx/InstantHandBrake/English.lproj/Express.nib/keyedobjects.nib b/macosx/InstantHandBrake/English.lproj/Express.nib/keyedobjects.nib
new file mode 100644
index 000000000..b650bda9d
--- /dev/null
+++ b/macosx/InstantHandBrake/English.lproj/Express.nib/keyedobjects.nib
Binary files differ
diff --git a/macosx/InstantHandBrake/Express.plist b/macosx/InstantHandBrake/Express.plist
new file mode 100644
index 000000000..002ee8f88
--- /dev/null
+++ b/macosx/InstantHandBrake/Express.plist
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIconFile</key>
+ <string>MediaFork</string>
+ <key>CFBundleIdentifier</key>
+ <string>org.m0k.handbrake.instant</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0a2</string>
+ <key>NSMainNibFile</key>
+ <string>Express</string>
+ <key>NSPrincipalClass</key>
+ <string>NSApplication</string>
+</dict>
+</plist>
diff --git a/macosx/InstantHandBrake/ExpressController.h b/macosx/InstantHandBrake/ExpressController.h
new file mode 100644
index 000000000..5841f4e1f
--- /dev/null
+++ b/macosx/InstantHandBrake/ExpressController.h
@@ -0,0 +1,55 @@
+/* ExpressController */
+
+#import <Cocoa/Cocoa.h>
+#import "hb.h"
+
+@class DriveDetector;
+
+@interface ExpressController : NSObject
+
+{
+ hb_handle_t * fHandle;
+ hb_list_t * fList;
+
+ IBOutlet NSWindow * fWindow;
+ IBOutlet NSView * fEmptyView;
+
+ IBOutlet NSView * fOpenView;
+ IBOutlet NSMatrix * fOpenMatrix;
+ IBOutlet NSPopUpButton * fOpenPopUp;
+ IBOutlet NSTextField * fOpenFolderField;
+ IBOutlet NSButton * fOpenBrowseButton;
+ IBOutlet NSTextField * fOpenProgressField;
+ IBOutlet NSProgressIndicator * fOpenIndicator;
+ IBOutlet NSButton * fOpenGoButton;
+ NSString * fOpenFolderString;
+
+ IBOutlet NSView * fConvertView;
+ IBOutlet NSTableView * fConvertTableView;
+ IBOutlet NSPopUpButton * fConvertFolderPopUp;
+ IBOutlet NSPopUpButton * fConvertFormatPopUp;
+ IBOutlet NSPopUpButton * fConvertMaxWidthPopUp;
+ IBOutlet NSPopUpButton * fConvertAspectPopUp;
+ IBOutlet NSPopUpButton * fConvertAudioPopUp;
+ IBOutlet NSPopUpButton * fConvertSubtitlePopUp;
+ IBOutlet NSTextField * fConvertInfoString;
+ IBOutlet NSProgressIndicator * fConvertIndicator;
+ IBOutlet NSButton * fConvertOpenButton;
+ IBOutlet NSButton * fConvertGoButton;
+ NSMutableArray * fConvertCheckArray;
+ NSString * fConvertFolderString;
+
+ DriveDetector * fDriveDetector;
+ NSDictionary * fDrives;
+}
+
+- (void) openShow: (id) sender;
+- (void) openMatrixChanged: (id) sender;
+- (void) openBrowse: (id) sender;
+- (void) openGo: (id) sender;
+
+- (void) convertGo: (id) sender;
+- (void) convertCancel: (id) sender;
+
+@end
+
diff --git a/macosx/InstantHandBrake/ExpressController.m b/macosx/InstantHandBrake/ExpressController.m
new file mode 100644
index 000000000..c22912e06
--- /dev/null
+++ b/macosx/InstantHandBrake/ExpressController.m
@@ -0,0 +1,701 @@
+#import "ExpressController.h"
+#import "DriveDetector.h"
+
+#define INSERT_STRING @"Insert a DVD"
+
+@interface ExpressController (Private)
+
+- (void) openUpdateDrives: (NSDictionary *) drives;
+- (void) openBrowseDidEnd: (NSOpenPanel *) sheet returnCode: (int)
+ returnCode contextInfo: (void *) contextInfo;
+- (void) openEnable: (BOOL) b;
+- (void) openTimer: (NSTimer *) timer;
+
+- (void) convertShow;
+- (void) convertEnable: (BOOL) b;
+- (void) convertTimer: (NSTimer *) timer;
+
+@end
+
+@implementation ExpressController
+
+/***********************************************************************
+ * Application delegate methods
+ **********************************************************************/
+- (void) awakeFromNib
+{
+ NSEnumerator * enumerator;
+
+ /* Show the "Open DVD" interface */
+ fDriveDetector = [[DriveDetector alloc] initWithCallback: self
+ selector: @selector( openUpdateDrives: )];
+ [fDriveDetector run];
+ [self openEnable: YES];
+ [fWindow setContentSize: [fOpenView frame].size];
+ [fWindow setContentView: fOpenView];
+ [fWindow center];
+ [fWindow makeKeyAndOrderFront: nil];
+
+ /* NSTableView initializations */
+ NSButtonCell * buttonCell;
+ NSTableColumn * tableColumn;
+ enumerator = [[fConvertTableView tableColumns] objectEnumerator];
+ while( ( tableColumn = [enumerator nextObject] ) )
+ {
+ [tableColumn setEditable: NO];
+ }
+ tableColumn = [fConvertTableView tableColumnWithIdentifier: @"Check"];
+ buttonCell = [[[NSButtonCell alloc] initTextCell: @""] autorelease];
+ [buttonCell setEditable: YES];
+ [buttonCell setButtonType: NSSwitchButton];
+ [tableColumn setDataCell: buttonCell];
+
+ /* Preferences */
+ fConvertFolderString = [@"~/Movies" stringByExpandingTildeInPath];
+ [fConvertFolderString retain];
+}
+
+- (void) applicationWillFinishLaunching: (NSNotification *) n
+{
+ fHandle = hb_init_express( HB_DEBUG_NONE, 0 );
+ fList = hb_get_titles( fHandle );
+}
+
+- (void) applicationWillTerminate: (NSNotification *) n
+{
+ hb_close( &fHandle );
+}
+
+/***********************************************************************
+ * Tableview datasource methods
+ **********************************************************************/
+- (int) numberOfRowsInTableView: (NSTableView *) t
+{
+ if( !fHandle )
+ return 0;
+
+ return hb_list_count( fList );
+}
+
+- (id) tableView:(NSTableView *) t objectValueForTableColumn:
+ (NSTableColumn *) col row: (int) row
+{
+ if( [[col identifier] isEqualToString: @"Check"] )
+ {
+ return [fConvertCheckArray objectAtIndex: row];
+ }
+ else
+ {
+ hb_title_t * title = hb_list_item( fList, row );
+ if( [[col identifier] isEqualToString: @"Title"] )
+ {
+ return [@"Title " stringByAppendingFormat: @"%d",
+ title->index];
+ }
+ else if( [[col identifier] isEqualToString: @"Duration"] )
+ {
+ if( title->hours > 0 )
+ {
+ return [NSString stringWithFormat:
+ @"%d hour%s %d min%s", title->hours,
+ title->hours > 1 ? "s" : "", title->minutes,
+ title->minutes > 1 ? "s": ""];
+ }
+ else if( title->minutes > 0 )
+ {
+ return [NSString stringWithFormat:
+ @"%d min%s %d sec%s", title->minutes,
+ title->minutes > 1 ? "s" : "", title->seconds,
+ title->seconds > 1 ? "s": ""];
+ }
+ else
+ {
+ return [NSString stringWithFormat: @"%d seconds",
+ title->seconds];
+ }
+ }
+ }
+ return nil;
+}
+
+- (void) tableView: (NSTableView *) t setObjectValue: (id) object
+ forTableColumn: (NSTableColumn *) col row: (int) row
+{
+ if( [[col identifier] isEqualToString: @"Check"] )
+ {
+ [fConvertCheckArray replaceObjectAtIndex: row withObject: object];
+ }
+}
+
+/***********************************************************************
+ * User events methods
+ **********************************************************************/
+- (void) openShow: (id) sender
+{
+ NSRect frame = [fWindow frame];
+ float offset = [fConvertView frame].size.height -
+ [fOpenView frame].size.height;
+
+ frame.origin.y += offset;
+ frame.size.height -= offset;
+ [fWindow setContentView: fEmptyView];
+ [fWindow setFrame: frame display: YES animate: YES];
+ [fWindow setContentView: fOpenView];
+
+ [fDriveDetector run];
+}
+
+- (void) openMatrixChanged: (id) sender
+{
+ [self openEnable: YES];
+ if( [fOpenMatrix selectedRow] )
+ {
+ [self openBrowse: self];
+ }
+}
+
+- (void) openBrowse: (id) sender
+{
+ NSOpenPanel * panel = [NSOpenPanel openPanel];
+ [panel setAllowsMultipleSelection: NO];
+ [panel setCanChooseFiles: YES];
+ [panel setCanChooseDirectories: YES ];
+ [panel beginSheetForDirectory: nil file: nil types: nil
+ modalForWindow: fWindow modalDelegate: self
+ didEndSelector: @selector( openBrowseDidEnd:returnCode:contextInfo: )
+ contextInfo: nil];
+}
+
+- (void) openGo: (id) sender
+{
+ [self openEnable: NO];
+ [fOpenIndicator setIndeterminate: YES];
+ [fOpenIndicator startAnimation: nil];
+ [fOpenProgressField setStringValue: @"Opening..."];
+ [fDriveDetector stop];
+
+ if( [fOpenMatrix selectedRow] )
+ {
+ hb_scan( fHandle, [fOpenFolderString UTF8String], 0 );
+ }
+ else
+ {
+ hb_scan( fHandle, [[fDrives objectForKey: [fOpenPopUp
+ titleOfSelectedItem]] UTF8String], 0 );
+ }
+
+ NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval: 2.0
+ target: self selector: @selector( openTimer: ) userInfo: nil
+ repeats: YES];
+}
+
+- (void) convertGo: (id) sender
+{
+ int i, j;
+
+ for( i = 0; i < hb_list_count( fList ); i++ )
+ {
+ if( ![[fConvertCheckArray objectAtIndex: i] boolValue] )
+ continue;
+
+ hb_title_t * title = hb_list_item( fList, i );
+ hb_job_t * job = title->job;
+
+ int pixels = 307200;
+ int aspect = title->aspect;
+ if( [fConvertAspectPopUp indexOfSelectedItem] == 1)
+ {
+ aspect = 4 * HB_ASPECT_BASE / 3;
+ }
+
+ int maxwidth = 640;
+ job->vbitrate = 1000;
+ if( [fConvertMaxWidthPopUp indexOfSelectedItem] == 1)
+ {
+ maxwidth = 320;
+ job->vbitrate = 500;
+ }
+ job->deinterlace = 1;
+
+ do
+ {
+ hb_set_size( job, aspect, pixels );
+ pixels -= 10;
+ } while(job->width > maxwidth);
+
+ if( [fConvertFormatPopUp indexOfSelectedItem] == 0 )
+ {
+ /* iPod / H.264 */
+ job->mux = HB_MUX_IPOD;
+ job->vcodec = HB_VCODEC_X264;
+ job->h264_level = 30;
+ }
+ else if( [fConvertFormatPopUp indexOfSelectedItem] == 1 )
+ {
+ /* iPod / MPEG-4 */
+ job->mux = HB_MUX_MP4;
+ job->vcodec = HB_VCODEC_FFMPEG;
+ }
+ else
+ {
+ /* PSP / MPEG-4 */
+ job->mux = HB_MUX_PSP;
+ job->vrate = 27000000;
+ job->vrate_base = 900900; /* 29.97 fps */
+ job->vcodec = HB_VCODEC_FFMPEG;
+ job->vbitrate = 600;
+ pixels = 76800;
+ job->arate = 24000;
+ job->abitrate = 96;
+ aspect = 16 * HB_ASPECT_BASE / 9;
+
+ if( [fConvertAspectPopUp indexOfSelectedItem] )
+ {
+ aspect = -1;
+ }
+
+ hb_set_size( job, aspect, pixels );
+ }
+
+ job->vquality = -1.0;
+
+ const char * lang;
+
+ /* Audio selection */
+ hb_audio_t * audio;
+ lang = [[fConvertAudioPopUp titleOfSelectedItem] UTF8String];
+ job->audios[0] = -1;
+ for( j = 0; j < hb_list_count( title->list_audio ); j++ )
+ {
+ /* Choose the first track that matches the language */
+ audio = hb_list_item( title->list_audio, j );
+ if( !strcmp( lang, audio->lang_simple ) )
+ {
+ job->audios[0] = j;
+ break;
+ }
+ }
+ if( job->audios[0] == -1 )
+ {
+ /* If the language isn't available in this title, choose
+ the first track */
+ job->audios[0] = 0;
+ }
+ job->audios[1] = -1;
+
+ job->audio_mixdowns[0] = HB_AMIXDOWN_DOLBYPLII;
+
+ /* Subtitle selection */
+ hb_subtitle_t * subtitle;
+ lang = [[fConvertSubtitlePopUp titleOfSelectedItem] UTF8String];
+ job->subtitle = -1;
+ for( j = 0; j < hb_list_count( title->list_subtitle ); j++ )
+ {
+ /* Choose the first track that matches the language */
+ subtitle = hb_list_item( title->list_subtitle, j );
+ if( !strcmp( lang, subtitle->lang ) )
+ {
+ job->subtitle = j;
+ break;
+ }
+ }
+
+ job->file = strdup( [[NSString stringWithFormat:
+ @"%@/%s - Title %d.m4v", fConvertFolderString,
+ title->name, title->index] UTF8String] );
+ hb_add( fHandle, job );
+ }
+
+ hb_start( fHandle );
+
+ NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval: 2.0
+ target: self selector: @selector( convertTimer: ) userInfo: nil
+ repeats: YES];
+
+ [self convertEnable: NO];
+}
+
+- (void) convertCancel: (id) sender
+{
+ hb_stop( fHandle );
+ [self convertEnable: YES];
+}
+
+@end
+
+/***********************************************************************
+ * Private methods
+ **********************************************************************/
+
+@implementation ExpressController (Private)
+
+- (void) openUpdateDrives: (NSDictionary *) drives
+{
+ if( fDrives )
+ {
+ [fDrives release];
+ }
+ fDrives = [[NSDictionary alloc] initWithDictionary: drives];
+
+ NSString * device;
+ NSEnumerator * enumerator = [fDrives keyEnumerator];
+ [fOpenPopUp removeAllItems];
+ while( ( device = [enumerator nextObject] ) )
+ {
+ [fOpenPopUp addItemWithTitle: device];
+ }
+
+ if( ![fOpenPopUp numberOfItems] )
+ {
+ [fOpenPopUp addItemWithTitle: INSERT_STRING];
+ }
+ [fOpenPopUp selectItemAtIndex: 0];
+ if( [fOpenMatrix isEnabled] )
+ {
+ [self openEnable: YES];
+ }
+}
+
+- (void) openBrowseDidEnd: (NSOpenPanel *) sheet returnCode: (int)
+ returnCode contextInfo: (void *) contextInfo
+{
+ if( returnCode != NSOKButton )
+ return;
+
+ if( fOpenFolderString )
+ [fOpenFolderString release];
+ fOpenFolderString = [[[sheet filenames] objectAtIndex: 0] retain];
+ [fOpenFolderField setStringValue: [fOpenFolderString lastPathComponent]];
+ [self openGo: self];
+}
+
+- (void) openEnable: (BOOL) b
+{
+ [fOpenMatrix setEnabled: b];
+ [fOpenPopUp setEnabled: b];
+ [fOpenFolderField setEnabled: b];
+ [fOpenBrowseButton setEnabled: b];
+ [fOpenGoButton setEnabled: b];
+
+ if( b )
+ {
+ if( [fOpenMatrix selectedRow] )
+ {
+ [fOpenPopUp setEnabled: NO];
+ }
+ else
+ {
+ [fOpenFolderField setEnabled: NO];
+ [fOpenBrowseButton setEnabled: NO];
+ if( [[fOpenPopUp titleOfSelectedItem]
+ isEqualToString: INSERT_STRING] )
+ {
+ [fOpenGoButton setEnabled: NO];
+ }
+ }
+ }
+}
+
+- (void) openTimer: (NSTimer *) timer
+{
+ hb_state_t s;
+ hb_get_state( fHandle, &s );
+ switch( s.state )
+ {
+#define p s.param.scanning
+ case HB_STATE_SCANNING:
+ [fOpenIndicator setIndeterminate: NO];
+ [fOpenIndicator setDoubleValue: 100.0 *
+ ( (float) p.title_cur - 0.5 ) / p.title_count];
+ [fOpenProgressField setStringValue: [NSString
+ stringWithFormat: @"Scanning title %d of %d...",
+ p.title_cur, p.title_count]];
+ break;
+#undef p
+
+ case HB_STATE_SCANDONE:
+ [timer invalidate];
+
+ [fOpenIndicator setIndeterminate: NO];
+ [fOpenIndicator setDoubleValue: 0.0];
+ [self openEnable: YES];
+
+ if( hb_list_count( fList ) )
+ {
+ [self convertShow];
+ }
+ else
+ {
+ [fDriveDetector run];
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+- (void) convertShow
+{
+ int i, j;
+
+ fConvertCheckArray = [[NSMutableArray alloc] initWithCapacity:
+ hb_list_count( fList )];
+ [fConvertAudioPopUp removeAllItems];
+ [fConvertSubtitlePopUp removeAllItems];
+ [fConvertSubtitlePopUp addItemWithTitle: @"None"];
+ for( i = 0; i < hb_list_count( fList ); i++ )
+ {
+ /* Default is to convert titles longer than 30 minutes. */
+ hb_title_t * title = hb_list_item( fList, i );
+ [fConvertCheckArray addObject: [NSNumber numberWithBool:
+ ( 60 * title->hours + title->minutes > 30 )]];
+
+ /* Update audio popup */
+ hb_audio_t * audio;
+ for( j = 0; j < hb_list_count( title->list_audio ); j++ )
+ {
+ audio = hb_list_item( title->list_audio, j );
+ [fConvertAudioPopUp addItemWithTitle:
+ [NSString stringWithUTF8String: audio->lang_simple]];
+ }
+ [fConvertAudioPopUp selectItemWithTitle: @"English"];
+
+ /* Update subtitle popup */
+ hb_subtitle_t * subtitle;
+ for( j = 0; j < hb_list_count( title->list_subtitle ); j++ )
+ {
+ subtitle = hb_list_item( title->list_subtitle, j );
+ [fConvertSubtitlePopUp addItemWithTitle:
+ [NSString stringWithUTF8String: subtitle->lang]];
+ }
+ }
+ [fConvertTableView reloadData];
+
+ NSRect frame = [fWindow frame];
+ float offset = [fConvertView frame].size.height -
+ [fOpenView frame].size.height;
+ frame.origin.y -= offset;
+ frame.size.height += offset;
+ [fWindow setContentView: fEmptyView];
+ [fWindow setFrame: frame display: YES animate: YES];
+ [fWindow setContentView: fConvertView];
+
+ /* Folder popup */
+ NSMenuItem * item = [fConvertFolderPopUp itemAtIndex: 0];
+ [item setTitle: [fConvertFolderString lastPathComponent]];
+ NSImage * image32 = [[NSWorkspace sharedWorkspace] iconForFile:
+ fConvertFolderString];
+ NSImage * image16 = [[NSImage alloc] initWithSize:
+ NSMakeSize(16,16)];
+ [image16 lockFocus];
+ [[NSGraphicsContext currentContext]
+ setImageInterpolation: NSImageInterpolationHigh];
+ [image32 drawInRect: NSMakeRect(0,0,16,16)
+ fromRect: NSMakeRect(0,0,32,32) operation: NSCompositeCopy
+ fraction: 1.0];
+ [image16 unlockFocus];
+ [item setImage: image16];
+ [image16 release];
+
+ [self convertEnable: YES];
+}
+
+- (void) convertEnable: (BOOL) b
+{
+ [fConvertTableView setEnabled: b];
+ [fConvertFolderPopUp setEnabled: b];
+ [fConvertFormatPopUp setEnabled: b];
+ [fConvertAspectPopUp setEnabled: b];
+ [fConvertMaxWidthPopUp setEnabled: b];
+ [fConvertAudioPopUp setEnabled: b];
+ [fConvertSubtitlePopUp setEnabled: b];
+ [fConvertOpenButton setEnabled: b];
+ if( b )
+ {
+ [fConvertGoButton setTitle: @"Convert"];
+ [fConvertGoButton setAction: @selector(convertGo:)];
+ }
+ else
+ {
+ [fConvertGoButton setTitle: @"Cancel"];
+ [fConvertGoButton setAction: @selector(convertCancel:)];
+ }
+}
+
+/***********************************************************************
+* UpdateDockIcon
+***********************************************************************
+* Shows a progression bar on the dock icon, filled according to
+* 'progress' (0.0 <= progress <= 1.0).
+* Called with progress < 0.0 or progress > 1.0, restores the original
+* icon.
+**********************************************************************/
+- (void) UpdateDockIcon: (float) progress
+{
+ NSImage * icon;
+ NSData * tiff;
+ NSBitmapImageRep * bmp;
+ uint32_t * pen;
+ uint32_t black = htonl( 0x000000FF );
+ uint32_t red = htonl( 0xFF0000FF );
+ uint32_t white = htonl( 0xFFFFFFFF );
+ int row_start, row_end;
+ int i, j;
+
+ /* Get application original icon */
+ icon = [NSImage imageNamed: @"NSApplicationIcon"];
+
+ if( progress < 0.0 || progress > 1.0 )
+ {
+ [NSApp setApplicationIconImage: icon];
+ return;
+ }
+
+ /* Get it in a raw bitmap form */
+ tiff = [icon TIFFRepresentationUsingCompression:
+ NSTIFFCompressionNone factor: 1.0];
+ bmp = [NSBitmapImageRep imageRepWithData: tiff];
+
+ /* Draw the progression bar */
+ /* It's pretty simple (ugly?) now, but I'm no designer */
+
+ row_start = 3 * (int) [bmp size].height / 4;
+ row_end = 7 * (int) [bmp size].height / 8;
+
+ for( i = row_start; i < row_start + 2; i++ )
+ {
+ pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
+ for( j = 0; j < (int) [bmp size].width; j++ )
+ {
+ pen[j] = black;
+ }
+ }
+ for( i = row_start + 2; i < row_end - 2; i++ )
+ {
+ pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
+ pen[0] = black;
+ pen[1] = black;
+ for( j = 2; j < (int) [bmp size].width - 2; j++ )
+ {
+ if( j < 2 + (int) ( ( [bmp size].width - 4.0 ) * progress ) )
+ {
+ pen[j] = red;
+ }
+ else
+ {
+ pen[j] = white;
+ }
+ }
+ pen[j] = black;
+ pen[j+1] = black;
+ }
+ for( i = row_end - 2; i < row_end; i++ )
+ {
+ pen = (uint32_t *) ( [bmp bitmapData] + i * [bmp bytesPerRow] );
+ for( j = 0; j < (int) [bmp size].width; j++ )
+ {
+ pen[j] = black;
+ }
+ }
+
+ /* Now update the dock icon */
+ tiff = [bmp TIFFRepresentationUsingCompression:
+ NSTIFFCompressionNone factor: 1.0];
+ icon = [[NSImage alloc] initWithData: tiff];
+ [NSApp setApplicationIconImage: icon];
+ [icon release];
+}
+
+- (void) convertTimer: (NSTimer *) timer
+{
+ hb_state_t s;
+ hb_get_state( fHandle, &s );
+ switch( s.state )
+ {
+#define p s.param.working
+ case HB_STATE_WORKING:
+ {
+ float progress_total = ( p.progress + p.job_cur - 1 ) / p.job_count;
+ NSMutableString * string = [NSMutableString
+ stringWithFormat: @"Converting: %.1f %%",
+ 100.0 * progress_total];
+ if( p.seconds > -1 )
+ {
+ [string appendFormat: @" (%.1f fps, ", p.rate_avg];
+ if( p.hours > 0 )
+ {
+ [string appendFormat: @"%d hour%s %d min%s",
+ p.hours, p.hours == 1 ? "" : "s",
+ p.minutes, p.minutes == 1 ? "" : "s"];
+ }
+ else if( p.minutes > 0 )
+ {
+ [string appendFormat: @"%d min%s %d sec%s",
+ p.minutes, p.minutes == 1 ? "" : "s",
+ p.seconds, p.seconds == 1 ? "" : "s"];
+ }
+ else
+ {
+ [string appendFormat: @"%d second%s",
+ p.seconds, p.seconds == 1 ? "" : "s"];
+ }
+ [string appendString: @" left)"];
+ }
+ [fConvertInfoString setStringValue: string];
+ [fConvertIndicator setIndeterminate: NO];
+ [fConvertIndicator setDoubleValue: 100.0 * progress_total];
+ [self UpdateDockIcon: progress_total];
+ break;
+ }
+#undef p
+
+#define p s.param.muxing
+ case HB_STATE_MUXING:
+ {
+ NSMutableString * string = [NSMutableString
+ stringWithFormat: @"Muxing..."];
+ [fConvertInfoString setStringValue: string];
+ [fConvertIndicator setIndeterminate: YES];
+ [fConvertIndicator startAnimation: nil];
+ [self UpdateDockIcon: 1.0];
+ break;
+ }
+#undef p
+
+ case HB_STATE_WORKDONE:
+ {
+ [timer invalidate];
+ [fConvertIndicator setIndeterminate: NO];
+ [fConvertIndicator setDoubleValue: 0.0];
+ [self UpdateDockIcon: -1.0];
+ [self convertEnable: YES];
+
+#define p s.param.workdone
+ switch(p.error)
+ {
+ case HB_ERROR_NONE:
+ [fConvertInfoString setStringValue: @"Done."];
+ break;
+ case HB_ERROR_CANCELED:
+ [fConvertInfoString setStringValue: @"Canceled."];
+ break;
+ case HB_ERROR_UNKNOWN:
+ [fConvertInfoString setStringValue: @"Unknown Error."];
+ break;
+ }
+#undef p
+
+ hb_job_t * job;
+ while( ( job = hb_job( fHandle, 0 ) ) )
+ {
+ hb_rem( fHandle, job );
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+@end
diff --git a/macosx/InstantHandBrake/WhiteBox.h b/macosx/InstantHandBrake/WhiteBox.h
new file mode 100644
index 000000000..cb9ff37ee
--- /dev/null
+++ b/macosx/InstantHandBrake/WhiteBox.h
@@ -0,0 +1,8 @@
+/* WhiteBox */
+
+#import <Cocoa/Cocoa.h>
+
+@interface WhiteBox : NSBox
+{
+}
+@end
diff --git a/macosx/InstantHandBrake/WhiteBox.m b/macosx/InstantHandBrake/WhiteBox.m
new file mode 100644
index 000000000..64d5c3490
--- /dev/null
+++ b/macosx/InstantHandBrake/WhiteBox.m
@@ -0,0 +1,12 @@
+#import "WhiteBox.h"
+
+@implementation WhiteBox
+
+- (void) drawRect: (NSRect) rect
+{
+ [[NSColor whiteColor] set];
+ [[NSBezierPath bezierPathWithRect: rect] fill];
+ [super drawRect: rect];
+}
+
+@end