summaryrefslogtreecommitdiffstats
path: root/macosx/ScanController.mm
diff options
context:
space:
mode:
Diffstat (limited to 'macosx/ScanController.mm')
-rw-r--r--macosx/ScanController.mm272
1 files changed, 272 insertions, 0 deletions
diff --git a/macosx/ScanController.mm b/macosx/ScanController.mm
new file mode 100644
index 000000000..5a4075416
--- /dev/null
+++ b/macosx/ScanController.mm
@@ -0,0 +1,272 @@
+/* $Id: ScanController.mm,v 1.10 2005/04/27 21:05:24 titer Exp $
+
+ 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 "ScanController.h"
+
+#define _(a) NSLocalizedString(a,nil)
+
+@implementation ScanController
+
+- (void) TranslateStrings
+{
+ [fSelectString setStringValue: _( @"Select a DVD:" )];
+ [fDetectedCell setTitle: _( @"Detected volume" )];
+ [fFolderCell setTitle: _( @"DVD Folder / Image" )];
+ [fBrowseButton setTitle: _( @"Browse" )];
+ [fCancelButton setTitle: _( @"Cancel" )];
+ [fOpenButton setTitle: _( @"Open" )];
+}
+
+- (void) SetHandle: (hb_handle_t *) handle
+{
+ fHandle = handle;
+ fLastCheck = 0;
+
+ [self TranslateStrings];
+
+ [fStatusField setStringValue: @""];
+}
+
+- (void) DetectDrives: (NSNotification *) notification
+{
+ if( [fMatrix isEnabled] == NO )
+ {
+ /* We're scanning */
+ return;
+ }
+ if( hb_get_date() < fLastCheck + 1000 )
+ {
+ /* Don't check more than every second */
+ return;
+ }
+ fLastCheck = hb_get_date();
+
+ /* 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 )
+ {
+ 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 ) ) );
+ }
+
+ IOObjectRelease( media_iterator );
+
+ [fDetectedPopUp removeAllItems];
+ for( unsigned i = 0; i < [drivesList count]; i++ )
+ {
+ [[fDetectedPopUp menu] addItemWithTitle:
+ [drivesList objectAtIndex: i] action: nil
+ keyEquivalent: @""];
+ }
+ [self MatrixChanged: self];
+}
+
+- (void) EnableUI: (bool) b
+{
+ [fMatrix setEnabled: b];
+ [fDetectedCell setEnabled: b];
+ [fDetectedPopUp setEnabled: b];
+ [fFolderCell setEnabled: b];
+ [fFolderField setEnabled: b];
+ [fBrowseButton setEnabled: b];
+ [fOpenButton setEnabled: b];
+
+ if( b )
+ {
+ [self MatrixChanged: nil];
+ }
+}
+
+- (void) UpdateUI: (hb_state_t *) s
+{
+ switch( s->state )
+ {
+#define p s->param.scanning
+ case HB_STATE_SCANNING:
+ [fStatusField setStringValue: [NSString stringWithFormat:
+ _( @"Scanning title %d of %d..." ),
+ p.title_cur, p.title_count]];
+ [fIndicator setDoubleValue: 100.0 * ( p.title_cur - 1 ) /
+ p.title_count];
+ break;
+#undef p
+
+ case HB_STATE_SCANDONE:
+ [self EnableUI: YES];
+ [fIndicator setDoubleValue: 0.0];
+
+ if( hb_list_count( hb_get_titles( fHandle ) ) )
+ {
+ /* Success */
+ [fStatusField setStringValue: @""];
+ [NSApp abortModal];
+ }
+ else
+ {
+ [fStatusField setStringValue:
+ _( @"No valid title found." )];
+ }
+ break;
+ }
+}
+
+- (IBAction) MatrixChanged: (id) sender
+{
+ /* Do we have detected drives */
+ if( [fDetectedPopUp numberOfItems] > 0 )
+ {
+ [fDetectedCell setEnabled: YES];
+ }
+ else
+ {
+ [fMatrix selectCell: fFolderCell];
+ [fDetectedCell setEnabled: NO];
+ }
+
+ /* Enable controls related to the current choice */
+ bool foo;
+ foo = ( [fMatrix selectedRow] == 0 );
+ [fDetectedPopUp setEnabled: foo];
+ [fFolderField setEnabled: !foo];
+ [fBrowseButton setEnabled: !foo];
+}
+
+/* Browse:
+ Remove the current sheet (the scan panel) and show an OpenPanel.
+ Because we can't open the new sheet before the other one is
+ completely gone, we use performSelectorOnMainThread so it will be
+ done right afterwards */
+- (IBAction) Browse: (id) sender
+{
+ [NSApp stopModal];
+ [self performSelectorOnMainThread: @selector( Browse2: )
+ withObject: nil waitUntilDone: NO];
+}
+- (void) Browse2: (id) sender
+{
+ NSOpenPanel * panel;
+
+ panel = [NSOpenPanel openPanel];
+ [panel setAllowsMultipleSelection: NO];
+ [panel setCanChooseFiles: YES];
+ [panel setCanChooseDirectories: YES ];
+
+ [panel beginSheetForDirectory: nil file: nil types: nil
+ modalForWindow: [NSApp mainWindow] modalDelegate: self
+ didEndSelector: @selector( BrowseDone:returnCode:contextInfo: )
+ contextInfo: nil];
+}
+
+/* Get the folder and switch sheets again. Use the same trick as
+ above */
+- (void) BrowseDone: (NSOpenPanel *) sheet
+ returnCode: (int) returnCode contextInfo: (void *) contextInfo
+{
+ if( returnCode == NSOKButton )
+ {
+ [fFolderField setStringValue:
+ [[sheet filenames] objectAtIndex: 0]];
+ [self Open: nil];
+ }
+
+ [self performSelectorOnMainThread: @selector( BrowseDone2: )
+ withObject: nil waitUntilDone: NO];
+}
+- (void) BrowseDone2: (id) sender
+{
+ [NSApp beginSheet: fPanel modalForWindow: fWindow
+ modalDelegate: nil didEndSelector: nil contextInfo: nil];
+ [NSApp runModalForWindow: fWindow];
+ [NSApp endSheet: fPanel];
+ [fPanel orderOut: self];
+}
+
+- (IBAction) Open: (id) sender
+{
+ NSString * path;
+
+ [self EnableUI: NO];
+ [fStatusField setStringValue: _( @"Opening..." )];
+
+ path = [fMatrix selectedRow] ? [fFolderField stringValue] :
+ [fDetectedPopUp titleOfSelectedItem];
+ hb_scan( fHandle, [path UTF8String], 0 );
+}
+
+- (IBAction) Cancel: (id) sender
+{
+ [NSApp stopModal];
+}
+
+@end