summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--macosx/HBDVDDetector.h25
-rw-r--r--macosx/HBDriveDetector.m240
-rw-r--r--macosx/HandBrake.xcodeproj/project.pbxproj8
-rw-r--r--macosx/ScanController.h5
-rw-r--r--macosx/ScanController.mm199
5 files changed, 281 insertions, 196 deletions
diff --git a/macosx/HBDVDDetector.h b/macosx/HBDVDDetector.h
new file mode 100644
index 000000000..935dd065c
--- /dev/null
+++ b/macosx/HBDVDDetector.h
@@ -0,0 +1,25 @@
+ /**
+ * HBDVDDetector.h
+ * 8/17/2007
+ *
+ * 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 HBDVDDetector : NSObject
+{
+ NSString *path;
+ NSString *bsdName;
+}
+
++ (HBDVDDetector *)detectorForPath: (NSString *)aPath;
+- (HBDVDDetector *)initWithPath: (NSString *)aPath;
+
+- (BOOL)isVideoDVD;
+- (NSString *)devicePath;
+
+@end \ No newline at end of file
diff --git a/macosx/HBDriveDetector.m b/macosx/HBDriveDetector.m
new file mode 100644
index 000000000..2b57237d9
--- /dev/null
+++ b/macosx/HBDriveDetector.m
@@ -0,0 +1,240 @@
+/**
+ * HBDriveDetector.m
+ * 8/17/2007
+ *
+ * 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 <IOKit/IOKitLib.h>
+#include <IOKit/storage/IOMedia.h>
+#include <IOKit/storage/IODVDMedia.h>
+
+#import "HBDVDDetector.h"
+
+
+@interface HBDVDDetector (Private)
+
+- (NSString *)bsdNameForPath;
+- (BOOL)pathHasVideoTS;
+- (BOOL)deviceIsDVD;
+- (io_service_t)getIOKitServiceForBSDName;
+- (BOOL)isDVDService: (io_service_t)service;
+- (BOOL)isWholeMediaService: (io_service_t)service;
+
+@end
+
+
+@implementation HBDVDDetector
+
++ (HBDVDDetector *)detectorForPath: (NSString *)aPath
+{
+ return [[[self alloc] initWithPath:aPath] autorelease];
+}
+
+
+- (HBDVDDetector *)initWithPath: (NSString *)aPath
+{
+ NSAssert(aPath, @"nil string passed to drive detector.");
+ if( self = [super init] )
+ {
+ path = [aPath retain];
+ bsdName = nil;
+ }
+ return self;
+}
+
+
+- (void)dealloc
+{
+ [path release];
+ path = nil;
+ [bsdName release];
+ bsdName = nil;
+ [super dealloc];
+}
+
+
+- (BOOL)isVideoDVD
+{
+ if( !bsdName )
+ {
+ bsdName = [[self bsdNameForPath] retain];
+ }
+ return ( [self pathHasVideoTS] && [self deviceIsDVD] );
+}
+
+
+- (NSString *)devicePath
+{
+ if( !bsdName )
+ {
+ bsdName = [[self bsdNameForPath] retain];
+ }
+ return [NSString stringWithFormat:@"/dev/%@", bsdName];
+}
+
+@end
+
+
+@implementation HBDVDDetector (Private)
+
+- (NSString *)bsdNameForPath
+{
+ OSStatus err;
+ FSRef ref;
+ err = FSPathMakeRef( (const UInt8 *) [path fileSystemRepresentation],
+ &ref, NULL );
+ if( err != noErr )
+ {
+ return nil;
+ }
+
+ // Get the volume reference number.
+ FSCatalogInfo catalogInfo;
+ err = FSGetCatalogInfo( &ref, kFSCatInfoVolume, &catalogInfo, NULL, NULL,
+ NULL);
+ if( err != noErr )
+ {
+ return nil;
+ }
+ FSVolumeRefNum volRefNum = catalogInfo.volume;
+
+ // Mow let's get the device name
+ GetVolParmsInfoBuffer volumeParms;
+ HParamBlockRec pb;
+ pb.ioParam.ioNamePtr = NULL;
+ pb.ioParam.ioVRefNum = volRefNum;
+ pb.ioParam.ioBuffer = (Ptr) &volumeParms;
+ pb.ioParam.ioReqCount = sizeof( volumeParms );
+ err = PBHGetVolParmsSync( &pb );
+ if( err != noErr )
+ {
+ return nil;
+ }
+
+ // A version 4 GetVolParmsInfoBuffer contains the BSD node name in the vMDeviceID field.
+ // It is actually a char * value. This is mentioned in the header CoreServices/CarbonCore/Files.h.
+ return [NSString stringWithCString:(char *)volumeParms.vMDeviceID];
+}
+
+
+- (BOOL)pathHasVideoTS
+{
+ // Check one level under the path
+ if( [[NSFileManager defaultManager] fileExistsAtPath:
+ [path stringByAppendingPathComponent:@"VIDEO_TS"]] )
+ {
+ return YES;
+ }
+
+ // Now check above the path
+ return [[path pathComponents] containsObject:@"VIDEO_TS"];
+}
+
+
+- (BOOL)deviceIsDVD
+{
+ io_service_t service = [self getIOKitServiceForBSDName];
+ if( service == IO_OBJECT_NULL )
+ {
+ return NO;
+ }
+ BOOL result = [self isDVDService:service];
+ IOObjectRelease(service);
+ return result;
+}
+
+
+- (io_service_t)getIOKitServiceForBSDName
+{
+ CFMutableDictionaryRef matchingDict;
+ matchingDict = IOBSDNameMatching( kIOMasterPortDefault, 0, [bsdName cString] );
+ if( matchingDict == NULL )
+ {
+ return IO_OBJECT_NULL;
+ }
+
+ // Fetch the object with the matching BSD node name. There should only be
+ // one match, so IOServiceGetMatchingService is used instead of
+ // IOServiceGetMatchingServices to simplify the code.
+ return IOServiceGetMatchingService( kIOMasterPortDefault, matchingDict );
+}
+
+
+- (BOOL)isDVDService: (io_service_t)service
+{
+ // Find the IOMedia object that represents the entire (whole) media that the
+ // volume is on.
+ //
+ // If the volume is on partitioned media, the whole media object will be a
+ // parent of the volume's media object. If the media is not partitioned, the
+ // volume's media object will be the whole media object.
+ //
+ // The whole media object is indicated in the IORegistry by the presence of
+ // a property with the key "Whole" and value "Yes".
+
+ // Create an iterator across all parents of the service object passed in.
+ kern_return_t kernResult;
+ io_iterator_t iter;
+ kernResult = IORegistryEntryCreateIterator( service,
+ kIOServicePlane,
+ kIORegistryIterateRecursively | kIORegistryIterateParents,
+ &iter );
+ if( kernResult != KERN_SUCCESS )
+ {
+ return NO;
+ }
+ if( iter == IO_OBJECT_NULL )
+ {
+ return NO;
+ }
+
+
+ // A reference on the initial service object is released in the do-while loop below,
+ // so add a reference to balance.
+ IOObjectRetain( service );
+
+ BOOL isDVD = NO;
+ do
+ {
+ isDVD = ( [self isWholeMediaService:service] &&
+ IOObjectConformsTo(service, kIODVDMediaClass) );
+ IOObjectRelease(service);
+ } while( !isDVD && (service = IOIteratorNext(iter)) );
+ IOObjectRelease( iter );
+
+ return isDVD;
+}
+
+
+- (BOOL)isWholeMediaService: (io_service_t)service
+{
+ //
+ // Determine if the object passed in represents an IOMedia (or subclass) object.
+ // If it does, test the "Whole" property.
+ //
+
+ Boolean isWholeMedia = NO;
+
+ if( IOObjectConformsTo(service, kIOMediaClass) )
+ {
+ CFTypeRef wholeMedia;
+ wholeMedia = IORegistryEntryCreateCFProperty( service,
+ CFSTR(kIOMediaWholeKey),
+ kCFAllocatorDefault,
+ 0);
+ if( !wholeMedia )
+ {
+ return NO;
+ }
+ isWholeMedia = CFBooleanGetValue( (CFBooleanRef)wholeMedia );
+ CFRelease(wholeMedia);
+ }
+
+ return isWholeMedia;
+}
+
+
+@end \ No newline at end of file
diff --git a/macosx/HandBrake.xcodeproj/project.pbxproj b/macosx/HandBrake.xcodeproj/project.pbxproj
index d9276afd3..40f88438a 100644
--- a/macosx/HandBrake.xcodeproj/project.pbxproj
+++ b/macosx/HandBrake.xcodeproj/project.pbxproj
@@ -124,6 +124,8 @@
A28468680C5A43D900EF9A98 /* Disc.tiff in Resources */ = {isa = PBXBuildFile; fileRef = A28468670C5A43D900EF9A98 /* Disc.tiff */; };
A29E05800BE1283E000533F5 /* Growl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A29E057F0BE1283E000533F5 /* Growl.framework */; };
A29E058B0BE12889000533F5 /* Growl.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = A29E057F0BE1283E000533F5 /* Growl.framework */; };
+ A2A1EC310C76C35E00827E0D /* HBDVDDetector.h in Headers */ = {isa = PBXBuildFile; fileRef = A2A1EC300C76C35E00827E0D /* HBDVDDetector.h */; };
+ A2A1EC3A0C76C58400827E0D /* HBDriveDetector.m in Sources */ = {isa = PBXBuildFile; fileRef = A2A1EC390C76C58400827E0D /* HBDriveDetector.m */; };
A2DFC66E0C6196D900E66E89 /* actionWidget.png in Resources */ = {isa = PBXBuildFile; fileRef = A2DFC66C0C6196D900E66E89 /* actionWidget.png */; };
A2DFC66F0C6196D900E66E89 /* actionWidgetPressed.png in Resources */ = {isa = PBXBuildFile; fileRef = A2DFC66D0C6196D900E66E89 /* actionWidgetPressed.png */; };
A2DFC6750C6197C600E66E89 /* MVMenuButton.h in Headers */ = {isa = PBXBuildFile; fileRef = A2DFC6740C6197C600E66E89 /* MVMenuButton.h */; };
@@ -264,6 +266,8 @@
A273E0950C57C19500493A45 /* muxmkv.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = muxmkv.c; path = ../libhb/muxmkv.c; sourceTree = SOURCE_ROOT; };
A28468670C5A43D900EF9A98 /* Disc.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = Disc.tiff; sourceTree = "<group>"; };
A29E057F0BE1283E000533F5 /* Growl.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Growl.framework; sourceTree = "<group>"; };
+ A2A1EC300C76C35E00827E0D /* HBDVDDetector.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HBDVDDetector.h; sourceTree = "<group>"; };
+ A2A1EC390C76C58400827E0D /* HBDriveDetector.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = HBDriveDetector.m; sourceTree = "<group>"; };
A2DFC66C0C6196D900E66E89 /* actionWidget.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = actionWidget.png; sourceTree = "<group>"; };
A2DFC66D0C6196D900E66E89 /* actionWidgetPressed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = actionWidgetPressed.png; sourceTree = "<group>"; };
A2DFC6740C6197C600E66E89 /* MVMenuButton.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MVMenuButton.h; sourceTree = "<group>"; };
@@ -460,6 +464,8 @@
4D2AE78A09CCB24C007E18F6 /* DriveDetector.h */,
593034E90BBA39A100172349 /* ChapterTitles.h */,
593034EA0BBA39A100172349 /* ChapterTitles.m */,
+ A2A1EC300C76C35E00827E0D /* HBDVDDetector.h */,
+ A2A1EC390C76C58400827E0D /* HBDriveDetector.m */,
253885FF0BFE0A5B0064E995 /* HBOutputRedirect.h */,
253886000BFE0A5B0064E995 /* HBOutputRedirect.m */,
253886150BFE0C160064E995 /* HBOutputPanelController.h */,
@@ -526,6 +532,7 @@
4DD93F92082036E8008E1322 /* PictureController.h in Headers */,
4DD93F93082036E8008E1322 /* QueueController.h in Headers */,
4D2AEA2A09CCB8FC007E18F6 /* DriveDetector.h in Headers */,
+ A2A1EC310C76C35E00827E0D /* HBDVDDetector.h in Headers */,
253886010BFE0A5B0064E995 /* HBOutputRedirect.h in Headers */,
253886170BFE0C160064E995 /* HBOutputPanelController.h in Headers */,
25DE1FB60C169A0C00F01FC8 /* HBPreferencesController.h in Headers */,
@@ -799,6 +806,7 @@
4DD93F9E082036E8008E1322 /* PictureController.mm in Sources */,
4DD93F9F082036E8008E1322 /* QueueController.mm in Sources */,
4D2AEA2909CCB8F9007E18F6 /* DriveDetector.m in Sources */,
+ A2A1EC3A0C76C58400827E0D /* HBDriveDetector.m in Sources */,
253886020BFE0A5B0064E995 /* HBOutputRedirect.m in Sources */,
253886180BFE0C160064E995 /* HBOutputPanelController.m in Sources */,
25DE1FB70C169A0C00F01FC8 /* HBPreferencesController.m in Sources */,
diff --git a/macosx/ScanController.h b/macosx/ScanController.h
index 1b31ec1e4..5bd72cd38 100644
--- a/macosx/ScanController.h
+++ b/macosx/ScanController.h
@@ -18,10 +18,7 @@
IBOutlet NSTextField * fStatusField;
IBOutlet NSProgressIndicator * fIndicator;
-
- // DriveDetector * fDriveDetector;
- // NSDictionary * fDrives;
}
- (void) SetHandle: (hb_handle_t *) handle;
@@ -30,6 +27,6 @@
- (IBAction) Cancel: (id) sender;
- (void) BrowseDone: (NSOpenPanel *) sheet
returnCode: (int) returnCode contextInfo: (void *) contextInfo;
-- (NSString *)dvdDevicePathForVolume: (NSString *)volumePath;;
+
@end
diff --git a/macosx/ScanController.mm b/macosx/ScanController.mm
index 7fab46eaa..81b27236c 100644
--- a/macosx/ScanController.mm
+++ b/macosx/ScanController.mm
@@ -15,8 +15,8 @@
#include <IOKit/storage/IOMedia.h>
#include <IOKit/storage/IODVDMedia.h>
+#include "HBDVDDetector.h"
#include "ScanController.h"
-//#include "DriveDetector.h"
#include "dvdread/dvd_reader.h"
@@ -81,215 +81,30 @@
NSString *path = [[sheet filenames] objectAtIndex: 0];
- NSString *dvdPath = [self dvdDevicePathForVolume: path];
- if (dvdPath)
+ HBDVDDetector *detector = [HBDVDDetector detectorForPath:path];
+ if( [detector isVideoDVD] )
{
- // The chosen path was actually a mount point for a DVD, so use the
- // raw block device instead.
- path = dvdPath;
+ // The chosen path was actually on a DVD, so use the raw block
+ // device path instead.
+ path = [detector devicePath];
}
-
+
hb_scan( fHandle, [path UTF8String], 0 );
[self Cancel: nil];
}
else // User clicked Cancel in browse window
{
-
[self Cancel: nil];
-
}
}
-
- (IBAction) Cancel: (id) sender
{
[NSApp endSheet:fPanel];
[fPanel orderOut:self];
}
-
-Boolean IsDVD(io_service_t service)
-{
- //
- // Determine if the object passed in represents an IOMedia (or subclass) object.
- // If it does, retrieve the "Whole" property.
- // If this is the whole media object, find out if it is a DVD.
- // If it isn't the whole media object, iterate across its parents in the IORegistry
- // until the whole media object is found.
- //
-
- Boolean isWholeMedia = NO;
-
- if (IOObjectConformsTo(service, kIOMediaClass))
- {
- CFTypeRef wholeMedia;
-
- wholeMedia = IORegistryEntryCreateCFProperty(service,
- CFSTR(kIOMediaWholeKey),
- kCFAllocatorDefault,
- 0);
-
- if (!wholeMedia)
- {
- return NO;
- }
- else
- {
- isWholeMedia = CFBooleanGetValue((CFBooleanRef)wholeMedia);
- CFRelease(wholeMedia);
- }
- }
-
- if (isWholeMedia && IOObjectConformsTo(service, kIODVDMediaClass))
- {
- return YES;
- }
-
- return NO;
-}
-
-Boolean FindDVD(io_service_t service)
-{
- kern_return_t kernResult;
- io_iterator_t iter;
-
- // Create an iterator across all parents of the service object passed in.
- kernResult = IORegistryEntryCreateIterator(service,
- kIOServicePlane,
- kIORegistryIterateRecursively | kIORegistryIterateParents,
- &iter);
-
- if (kernResult != KERN_SUCCESS)
- {
- return NO;
- }
-
- if (iter == IO_OBJECT_NULL)
- {
- return NO;
- }
-
- Boolean isDVD;
-
- // A reference on the initial service object is released in the do-while loop below,
- // so add a reference to balance
- IOObjectRetain(service);
-
- do
- {
- isDVD = IsDVD(service);
- IOObjectRelease(service);
- } while (!isDVD && (service = IOIteratorNext(iter)));
-
- IOObjectRelease(iter);
-
- return isDVD;
-}
-
-Boolean DeviceIsDVD(char *bsdName)
-{
- // The idea is that given the BSD node name corresponding to a volume,
- // I/O Kit can be used to find the information about the media, drive, bus, and so on
- // that is maintained in the IORegistry.
- //
- // In this sample, we find out if the volume is on a CD, DVD, or some other media.
- // This is done as follows:
- //
- // 1. Find the IOMedia object that represents the entire (whole) media that the volume is on.
- //
- // If the volume is on partitioned media, the whole media object will be a parent of the volume's
- // media object. If the media is not partitioned, (a floppy disk, for example) the volume's media
- // object will be the whole media object.
- //
- // The whole media object is indicated in the IORegistry by the presence of a property with the key
- // "Whole" and value "Yes".
- //
- // 2. Determine which I/O Kit class the whole media object belongs to.
- //
- // 3. For DVD media, return YES;
- //
-
- CFMutableDictionaryRef matchingDict;
- io_service_t service;
-
- matchingDict = IOBSDNameMatching(kIOMasterPortDefault, 0, bsdName);
- if (matchingDict == NULL)
- {
- return NO;
- }
-
- // Fetch the object with the matching BSD node name. // Note that there should only be one match, so IOServiceGetMatchingService is used instead of
- // IOServiceGetMatchingServices to simplify the code.
- service = IOServiceGetMatchingService(kIOMasterPortDefault, matchingDict);
-
- if (service == IO_OBJECT_NULL) {
- return NO;
- }
-
- Boolean isDVD = FindDVD(service);
- IOObjectRelease(service);
- return isDVD;
-}
-
-
-- (NSString *)dvdDevicePathForVolume: (NSString *)volumePath
-{
- OSStatus err;
- FSRef ref;
- FSVolumeRefNum actualVolume;
- err = FSPathMakeRef ( (const UInt8 *) [volumePath fileSystemRepresentation], &ref, NULL );
-
- // get a FSVolumeRefNum from mountPath
- if ( err != noErr )
- {
- return nil;
- }
-
- FSCatalogInfo catalogInfo;
- err = FSGetCatalogInfo ( &ref,
- kFSCatInfoVolume,
- &catalogInfo,
- NULL,
- NULL,
- NULL
- );
- if ( err != noErr )
- {
- return nil;
- }
-
- actualVolume = catalogInfo.volume;
-
- // now let's get the device name
- GetVolParmsInfoBuffer volumeParms;
- HParamBlockRec pb;
-
- // Use the volume reference number to retrieve the volume parameters. See the documentation
- // on PBHGetVolParmsSync for other possible ways to specify a volume.
- pb.ioParam.ioNamePtr = NULL;
- pb.ioParam.ioVRefNum = actualVolume;
- pb.ioParam.ioBuffer = (Ptr) &volumeParms;
- pb.ioParam.ioReqCount = sizeof(volumeParms);
-
- // A version 4 GetVolParmsInfoBuffer contains the BSD node name in the vMDeviceID field.
- // It is actually a char * value. This is mentioned in the header CoreServices/CarbonCore/Files.h.
- err = PBHGetVolParmsSync(&pb);
-
- // Now that we have the device name, check to see if is a DVD or not.
- //[self DeviceIsDVD: ((char *)volumeParms.vMDeviceID)] // cocoa
- //if (!DeviceIsDVD)
- char *deviceID = (char *)volumeParms.vMDeviceID;
- //if (!DeviceIsDVD((char *)volumeParms.vMDeviceID)) // c
- if (!DeviceIsDVD(deviceID))
- {
- return nil;
- }
- return [NSString stringWithFormat: @"/dev/%s", deviceID];
-}
-
-
-
@end