OSDN Git Service

MacGui: Better implementation of the new scan controller for reading physical dvds.
authordynaflash <dynaflash@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Sat, 18 Aug 2007 06:43:57 +0000 (06:43 +0000)
committerdynaflash <dynaflash@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Sat, 18 Aug 2007 06:43:57 +0000 (06:43 +0000)
- This one is all blindjimmy's doing, Thanks!
- adds a VIDEO_TS check for reading random vobs off of a general purpose dvd.
- uses a new cocoa class instead of the old c functions for drive detection.

git-svn-id: svn://localhost/HandBrake/trunk@829 b64f7644-9d1e-0410-96f1-a4d463321fa5

macosx/HBDVDDetector.h [new file with mode: 0644]
macosx/HBDriveDetector.m [new file with mode: 0644]
macosx/HandBrake.xcodeproj/project.pbxproj
macosx/ScanController.h
macosx/ScanController.mm

diff --git a/macosx/HBDVDDetector.h b/macosx/HBDVDDetector.h
new file mode 100644 (file)
index 0000000..935dd06
--- /dev/null
@@ -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 (file)
index 0000000..2b57237
--- /dev/null
@@ -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
index d9276af..40f8843 100644 (file)
                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 */; };
                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>"; };
                                4D2AE78A09CCB24C007E18F6 /* DriveDetector.h */,
                                593034E90BBA39A100172349 /* ChapterTitles.h */,
                                593034EA0BBA39A100172349 /* ChapterTitles.m */,
+                               A2A1EC300C76C35E00827E0D /* HBDVDDetector.h */,
+                               A2A1EC390C76C58400827E0D /* HBDriveDetector.m */,
                                253885FF0BFE0A5B0064E995 /* HBOutputRedirect.h */,
                                253886000BFE0A5B0064E995 /* HBOutputRedirect.m */,
                                253886150BFE0C160064E995 /* HBOutputPanelController.h */,
                                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 */,
                                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 */,
index 1b31ec1..5bd72cd 100644 (file)
     
     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
index 7fab46e..81b2723 100644 (file)
@@ -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"
 
         
         
         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