summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordynaflash <[email protected]>2007-08-16 19:10:11 +0000
committerdynaflash <[email protected]>2007-08-16 19:10:11 +0000
commit332f66902d4d5ff350b1925ab8e2f501d361022b (patch)
treef68fb1576e275a36e5d864d061f3bc6ccbb73838
parent3f1f0e0db601b683901aee9e6ba2a763eabbdba2 (diff)
MacGui: fix scancontroller to use mount point instead of file path for physical commercial dvds.
- thanks for the work on this one blindjimmy ! - needs to be prettier, but wanted it checked in asap before release for testing. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@821 b64f7644-9d1e-0410-96f1-a4d463321fa5
-rw-r--r--macosx/ScanController.h8
-rw-r--r--macosx/ScanController.mm204
2 files changed, 205 insertions, 7 deletions
diff --git a/macosx/ScanController.h b/macosx/ScanController.h
index 9e31f3ce2..1b31ec1e4 100644
--- a/macosx/ScanController.h
+++ b/macosx/ScanController.h
@@ -7,7 +7,7 @@
#include <Cocoa/Cocoa.h>
#include "hb.h"
-@class DriveDetector;
+//@class DriveDetector;
@interface ScanController : NSObject
{
hb_handle_t * fHandle;
@@ -20,8 +20,8 @@
IBOutlet NSProgressIndicator * fIndicator;
- DriveDetector * fDriveDetector;
- NSDictionary * fDrives;
+ // DriveDetector * fDriveDetector;
+ // NSDictionary * fDrives;
}
- (void) SetHandle: (hb_handle_t *) handle;
@@ -30,6 +30,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 f894cf2a6..7fab46eaa 100644
--- a/macosx/ScanController.mm
+++ b/macosx/ScanController.mm
@@ -11,8 +11,14 @@
#include <IOKit/storage/IODVDMedia.h>
*/
+#include <IOKit/IOKitLib.h>
+#include <IOKit/storage/IOMedia.h>
+#include <IOKit/storage/IODVDMedia.h>
+
#include "ScanController.h"
-#include "DriveDetector.h"
+//#include "DriveDetector.h"
+
+#include "dvdread/dvd_reader.h"
#define _(a) NSLocalizedString(a,nil)
#define INSERT_STRING @"Insert a DVD"
@@ -66,13 +72,24 @@
[fIndicator setHidden: NO];
[fIndicator setIndeterminate: YES];
[fIndicator startAnimation: nil];
- [fDriveDetector stop];
+
/* we set the last source directory in the prefs here */
NSString *sourceDirectory = [[[sheet filenames] objectAtIndex: 0] stringByDeletingLastPathComponent];
[[NSUserDefaults standardUserDefaults] setObject:sourceDirectory forKey:@"LastSourceDirectory"];
- hb_scan( fHandle, [[[sheet filenames] objectAtIndex: 0] UTF8String], 0 );
+
+
+ NSString *path = [[sheet filenames] objectAtIndex: 0];
+ NSString *dvdPath = [self dvdDevicePathForVolume: path];
+ if (dvdPath)
+ {
+ // The chosen path was actually a mount point for a DVD, so use the
+ // raw block device instead.
+ path = dvdPath;
+ }
+
+ hb_scan( fHandle, [path UTF8String], 0 );
[self Cancel: nil];
}
@@ -94,4 +111,185 @@
[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