summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorjbrjake <[email protected]>2008-04-24 21:56:39 +0000
committerjbrjake <[email protected]>2008-04-24 21:56:39 +0000
commit3702f58d3e9d2912c8ab342a793cb1275f7a96dd (patch)
treefc10cf68ae38e485663c8c93502d77ec35cc56f2 /test
parent73b40603172f00dc3ad0aac546f40e1e30c737e6 (diff)
CLI: Fixes optical scan reading in OS X by mirroring the MacGui work from r821. Thanks, blindjimmy!
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@1436 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'test')
-rw-r--r--test/test.c186
1 files changed, 186 insertions, 0 deletions
diff --git a/test/test.c b/test/test.c
index 90a95e3dc..bfcd87539 100644
--- a/test/test.c
+++ b/test/test.c
@@ -13,6 +13,13 @@
#include "hb.h"
#include "parsecsv.h"
+#ifdef __APPLE_CC__
+#import <CoreServices/CoreServices.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/storage/IOMedia.h>
+#include <IOKit/storage/IODVDMedia.h>
+#endif
+
/* Options */
static int debug = HB_DEBUG_NONE;
static int update = 0;
@@ -95,6 +102,14 @@ static int HandleEvents( hb_handle_t * h );
static int get_acodec_for_string( char *codec );
static int is_sample_rate_valid(int rate);
+#ifdef __APPLE_CC__
+static char* bsd_name_for_path(char *path);
+static int device_is_dvd(char *device);
+static io_service_t get_iokit_service( char *device );
+static int is_dvd_service( io_service_t service );
+static is_whole_media_service( io_service_t service );
+#endif
+
/* Only print the "Muxing..." message once */
static int show_mux_warning = 1;
@@ -1641,6 +1656,20 @@ static int ParseOptions( int argc, char ** argv )
break;
case 'i':
input = strdup( optarg );
+ #ifdef __APPLE_CC__
+ char *devName = bsd_name_for_path( input );
+ if( devName == NULL )
+ {
+ return 0;
+ }
+ if( device_is_dvd( devName ) )
+ {
+ char *newInput = malloc( strlen("/dev/") + strlen( devName ) + 1);
+ sprintf( newInput, "/dev/%s", devName );
+ free(input);
+ input = newInput;
+ }
+ #endif
break;
case 'o':
output = strdup( optarg );
@@ -2098,3 +2127,160 @@ static int is_sample_rate_valid(int rate)
}
return 0;
}
+
+#ifdef __APPLE_CC__
+/****************************************************************************
+ * bsd_name_for_path
+ *
+ * Returns the BSD device name for the block device that contains the
+ * passed-in path. Returns NULL on failure.
+ ****************************************************************************/
+static char* bsd_name_for_path(char *path)
+{
+ OSStatus err;
+ FSRef ref;
+ err = FSPathMakeRef( (const UInt8 *) input, &ref, NULL );
+ if( err != noErr )
+ {
+ return NULL;
+ }
+
+ // Get the volume reference number.
+ FSCatalogInfo catalogInfo;
+ err = FSGetCatalogInfo( &ref, kFSCatInfoVolume, &catalogInfo, NULL, NULL,
+ NULL);
+ if( err != noErr )
+ {
+ return NULL;
+ }
+ FSVolumeRefNum volRefNum = catalogInfo.volume;
+
+ // Now let's get the device name
+ GetVolParmsInfoBuffer volumeParms;
+ err = FSGetVolumeParms( volRefNum, &volumeParms, sizeof( volumeParms ) );
+ if( err != noErr )
+ {
+ return NULL;
+ }
+
+ // 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 volumeParms.vMDeviceID;
+}
+
+/****************************************************************************
+ * device_is_dvd
+ *
+ * Returns whether or not the passed in BSD device represents a DVD, or other
+ * optical media.
+ ****************************************************************************/
+static int device_is_dvd(char *device)
+{
+ io_service_t service = get_iokit_service(device);
+ if( service == IO_OBJECT_NULL )
+ {
+ return 0;
+ }
+ int result = is_dvd_service(service);
+ IOObjectRelease(service);
+ return result;
+}
+
+/****************************************************************************
+ * get_iokit_service
+ *
+ * Returns the IOKit service object for the passed in BSD device name.
+ ****************************************************************************/
+static io_service_t get_iokit_service( char *device )
+{
+ CFMutableDictionaryRef matchingDict;
+ matchingDict = IOBSDNameMatching( kIOMasterPortDefault, 0, device );
+ 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 );
+}
+
+/****************************************************************************
+ * is_dvd_service
+ *
+ * Returns whether or not the service passed in is a DVD.
+ *
+ * Searches for an 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.
+ ****************************************************************************/
+static int is_dvd_service( 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 0;
+ }
+ if( iter == IO_OBJECT_NULL )
+ {
+ return 0;
+ }
+
+ // A reference on the initial service object is released in the do-while
+ // loop below, so add a reference to balance.
+ IOObjectRetain( service );
+
+ int result = 0;
+ do
+ {
+ if( is_whole_media_service( service ) &&
+ IOObjectConformsTo( service, kIODVDMediaClass) )
+ {
+ result = 1;
+ }
+ IOObjectRelease( service );
+ } while( !result && (service = IOIteratorNext( iter )) );
+ IOObjectRelease( iter );
+
+ return result;
+}
+
+/****************************************************************************
+ * is_whole_media_service
+ *
+ * Returns whether or not the service passed in is an IOMedia service and
+ * represents the "whole" media instead of just a partition.
+ *
+ * The whole media object is indicated in the IORegistry by the presence of a
+ * property with the key "Whole" and value "Yes".
+ ****************************************************************************/
+static is_whole_media_service( io_service_t service )
+{
+ int result = 0;
+
+ if( IOObjectConformsTo( service, kIOMediaClass ) )
+ {
+ CFTypeRef wholeMedia = IORegistryEntryCreateCFProperty( service,
+ CFSTR( kIOMediaWholeKey ),
+ kCFAllocatorDefault,
+ 0 );
+ if ( !wholeMedia )
+ {
+ return 0;
+ }
+ result = CFBooleanGetValue( (CFBooleanRef)wholeMedia );
+ CFRelease( wholeMedia );
+ }
+
+ return result;
+}
+#endif // __APPLE_CC__