diff options
author | ritsuka <[email protected]> | 2008-01-11 17:48:18 +0000 |
---|---|---|
committer | ritsuka <[email protected]> | 2008-01-11 17:48:18 +0000 |
commit | 3caeaf135a8838fbc3f6a261bd7a66962a1bd5f5 (patch) | |
tree | faf286fde0354e240e6d343f5268e7a0bb583216 /macosx/InstantHandBrake | |
parent | 709c565f9e47282236b01ba1eb980c31221659f1 (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.h | 23 | ||||
-rw-r--r-- | macosx/InstantHandBrake/DriveDetector.m | 142 | ||||
-rw-r--r-- | macosx/InstantHandBrake/English.lproj/Express.nib/classes.nib | 132 | ||||
-rw-r--r-- | macosx/InstantHandBrake/English.lproj/Express.nib/info.nib | 29 | ||||
-rw-r--r-- | macosx/InstantHandBrake/English.lproj/Express.nib/keyedobjects.nib | bin | 0 -> 36301 bytes | |||
-rw-r--r-- | macosx/InstantHandBrake/Express.plist | 26 | ||||
-rw-r--r-- | macosx/InstantHandBrake/ExpressController.h | 55 | ||||
-rw-r--r-- | macosx/InstantHandBrake/ExpressController.m | 701 | ||||
-rw-r--r-- | macosx/InstantHandBrake/WhiteBox.h | 8 | ||||
-rw-r--r-- | macosx/InstantHandBrake/WhiteBox.m | 12 |
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 Binary files differnew file mode 100644 index 000000000..b650bda9d --- /dev/null +++ b/macosx/InstantHandBrake/English.lproj/Express.nib/keyedobjects.nib 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 |