Borrow the eject code for OSX from xine-lib-1.2-macos branch, as contributed
by Matt Messier. This allows to eject disks on Mac OS X without having to call an external utility. Incidentally this fixes libcdio eject function on Mac OS X 10.4 and later, as hditool was moved from /usr/sbin to /usr/bin.
This commit is contained in:
18
configure.ac
18
configure.ac
@@ -19,7 +19,7 @@ define(RELEASE_NUM, 79cvs)
|
|||||||
define(CDIO_VERSION_STR, 0.$1)
|
define(CDIO_VERSION_STR, 0.$1)
|
||||||
|
|
||||||
AC_PREREQ(2.52)
|
AC_PREREQ(2.52)
|
||||||
AC_REVISION([$Id: configure.ac,v 1.210 2007/05/16 10:00:50 rocky Exp $])dnl
|
AC_REVISION([$Id: configure.ac,v 1.211 2007/08/09 02:19:40 flameeyes Exp $])dnl
|
||||||
AC_INIT(libcdio, CDIO_VERSION_STR(RELEASE_NUM))
|
AC_INIT(libcdio, CDIO_VERSION_STR(RELEASE_NUM))
|
||||||
AC_CONFIG_SRCDIR(src/cd-info.c)
|
AC_CONFIG_SRCDIR(src/cd-info.c)
|
||||||
|
|
||||||
@@ -298,7 +298,7 @@ dnl AM_PROG_LIBTOOL tests whether we have GNU ld
|
|||||||
dnl this must come before checking --with-versioned-libs
|
dnl this must come before checking --with-versioned-libs
|
||||||
dnl which requires GNU ld.
|
dnl which requires GNU ld.
|
||||||
AM_PROG_LIBTOOL
|
AM_PROG_LIBTOOL
|
||||||
|
|
||||||
dnl system
|
dnl system
|
||||||
|
|
||||||
# FIXME:
|
# FIXME:
|
||||||
@@ -380,6 +380,20 @@ case $host_os in
|
|||||||
AC_DEFINE([HAVE_DARWIN_CDROM], [1],
|
AC_DEFINE([HAVE_DARWIN_CDROM], [1],
|
||||||
[Define 1 if you have Darwin OS X-type CD-ROM support])
|
[Define 1 if you have Darwin OS X-type CD-ROM support])
|
||||||
DARWIN_PKG_LIB_HACK="-Wl,-framework,CoreFoundation -Wl,-framework,IOKit"
|
DARWIN_PKG_LIB_HACK="-Wl,-framework,CoreFoundation -Wl,-framework,IOKit"
|
||||||
|
|
||||||
|
dnl Prior to Mac OS X 10.4 (Tiger), DiskArbitration was a private framework.
|
||||||
|
dnl It's now public, and it's needed to do cd/dvd unmount/eject.
|
||||||
|
AC_MSG_CHECKING([for DiskArbitration framework])
|
||||||
|
ac_save_LIBS="$LIBS" LIBS="$LIBS -framework CoreFoundation -framework DiskArbitration"
|
||||||
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <DiskArbitration/DiskArbitration.h>]], [[]])],
|
||||||
|
[have_diskarbitration_framework=yes], [have_diskarbitration_framework=no])
|
||||||
|
LIBS="$ac_save_LIBS"
|
||||||
|
AC_MSG_RESULT([$have_diskarbitration_framework])
|
||||||
|
if test x"$have_diskarbitration_framework" = x"yes"; then
|
||||||
|
AC_DEFINE([HAVE_DISKARBITRATION], 1, [Define to 1 if you have the Apple DiskArbitration framework])
|
||||||
|
DARWIN_PKG_LIB_HACK="$DARWIN_PKG_LIB_HACK -Wl,-framework,DiskArbitration"
|
||||||
|
fi
|
||||||
|
|
||||||
AC_SUBST(DARWIN_PKG_LIB_HACK)
|
AC_SUBST(DARWIN_PKG_LIB_HACK)
|
||||||
LIBCDIO_LIBS="$LIBCDIO_LIBS $DARWIN_PKG_LIB_HACK"
|
LIBCDIO_LIBS="$LIBCDIO_LIBS $DARWIN_PKG_LIB_HACK"
|
||||||
cd_drivers="${cd_drivers}, Darwin"
|
cd_drivers="${cd_drivers}, Darwin"
|
||||||
|
|||||||
124
lib/driver/osx.c
124
lib/driver/osx.c
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
$Id: osx.c,v 1.9 2006/03/26 02:34:41 rocky Exp $
|
$Id: osx.c,v 1.10 2007/08/09 02:19:40 flameeyes Exp $
|
||||||
|
|
||||||
Copyright (C) 2003, 2004, 2005, 2006 Rocky Bernstein
|
Copyright (C) 2003, 2004, 2005, 2006 Rocky Bernstein
|
||||||
<rockyb@users.sourceforge.net>
|
<rockyb@users.sourceforge.net>
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const char _rcsid[] = "$Id: osx.c,v 1.9 2006/03/26 02:34:41 rocky Exp $";
|
static const char _rcsid[] = "$Id: osx.c,v 1.10 2007/08/09 02:19:40 flameeyes Exp $";
|
||||||
|
|
||||||
#include <cdio/logging.h>
|
#include <cdio/logging.h>
|
||||||
#include <cdio/sector.h>
|
#include <cdio/sector.h>
|
||||||
@@ -87,6 +87,10 @@ static const char _rcsid[] = "$Id: osx.c,v 1.9 2006/03/26 02:34:41 rocky Exp $";
|
|||||||
#include <IOKit/storage/IODVDMediaBSDClient.h>
|
#include <IOKit/storage/IODVDMediaBSDClient.h>
|
||||||
#include <IOKit/storage/IOStorageDeviceCharacteristics.h>
|
#include <IOKit/storage/IOStorageDeviceCharacteristics.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_DISKARBITRATION
|
||||||
|
#include <DiskArbitration/DiskArbitration.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* FIXME */
|
/* FIXME */
|
||||||
#define MAX_BIG_BUFF_SIZE 65535
|
#define MAX_BIG_BUFF_SIZE 65535
|
||||||
|
|
||||||
@@ -1316,13 +1320,17 @@ get_track_lba_osx(void *p_user_data, track_t i_track)
|
|||||||
/*!
|
/*!
|
||||||
Eject media . Return DRIVER_OP_SUCCESS if successful.
|
Eject media . Return DRIVER_OP_SUCCESS if successful.
|
||||||
|
|
||||||
The only way to cleanly unmount the disc under MacOS X is to use the
|
The only way to cleanly unmount the disc under MacOS X (before
|
||||||
'disktool' command line utility. It uses the non-public Disk
|
Tiger) is to use the 'disktool' command line utility. It uses the
|
||||||
Arbitration API, which can not be used by Cocoa or Carbon
|
non-public DiskArbitration API, which can not be used by Cocoa or
|
||||||
applications.
|
Carbon applications.
|
||||||
|
|
||||||
|
Since Tiger (MacOS X 10.4), DiskArbitration is a public framework
|
||||||
|
and we can use it as needed.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef HAVE_DISKARBITRATION
|
||||||
static driver_return_code_t
|
static driver_return_code_t
|
||||||
_eject_media_osx (void *user_data) {
|
_eject_media_osx (void *user_data) {
|
||||||
|
|
||||||
@@ -1363,6 +1371,110 @@ _eject_media_osx (void *user_data) {
|
|||||||
|
|
||||||
return DRIVER_OP_ERROR;
|
return DRIVER_OP_ERROR;
|
||||||
}
|
}
|
||||||
|
#else /* HAVE_DISKARBITRATION */
|
||||||
|
typedef struct dacontext_s {
|
||||||
|
int result;
|
||||||
|
Boolean completed;
|
||||||
|
DASessionRef session;
|
||||||
|
CFRunLoopRef runloop;
|
||||||
|
CFRunLoopSourceRef cancel;
|
||||||
|
} dacontext_t;
|
||||||
|
|
||||||
|
static void cancel_runloop(void *info) { /* do nothing */ }
|
||||||
|
|
||||||
|
static CFRunLoopSourceContext cancelRunLoopSourceContext = {
|
||||||
|
.perform = cancel_runloop
|
||||||
|
};
|
||||||
|
|
||||||
|
static void media_eject_callback(DADiskRef disk, DADissenterRef dissenter, void *context)
|
||||||
|
{
|
||||||
|
dacontext_t *dacontext = (dacontext_t *)context;
|
||||||
|
|
||||||
|
dacontext->result = (dissenter ? DRIVER_OP_ERROR : DRIVER_OP_SUCCESS);
|
||||||
|
dacontext->completed = TRUE;
|
||||||
|
CFRunLoopSourceSignal(dacontext->cancel);
|
||||||
|
CFRunLoopWakeUp(dacontext->runloop);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void media_unmount_callback(DADiskRef disk, DADissenterRef dissenter, void *context)
|
||||||
|
{
|
||||||
|
dacontext_t *dacontext = (dacontext_t *)context;
|
||||||
|
|
||||||
|
if (!dissenter) {
|
||||||
|
DADiskEject(disk, kDADiskEjectOptionDefault, media_eject_callback, context);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dacontext->result = DRIVER_OP_ERROR;
|
||||||
|
dacontext->completed = TRUE;
|
||||||
|
CFRunLoopSourceSignal(dacontext->cancel);
|
||||||
|
CFRunLoopWakeUp(dacontext->runloop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static driver_return_code_t
|
||||||
|
_eject_media_osx (void *user_data) {
|
||||||
|
|
||||||
|
_img_private_t *p_env = user_data;
|
||||||
|
char *psz_drive;
|
||||||
|
|
||||||
|
DADiskRef disk;
|
||||||
|
dacontext_t dacontext;
|
||||||
|
CFDictionaryRef description;
|
||||||
|
|
||||||
|
if( ( psz_drive = (char *)strstr( p_env->gen.source_name, "disk" ) ) == NULL ||
|
||||||
|
strlen( psz_drive ) <= 4 )
|
||||||
|
{
|
||||||
|
return DRIVER_OP_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
dacontext.result = DRIVER_OP_SUCCESS;
|
||||||
|
dacontext.completed = FALSE;
|
||||||
|
dacontext.runloop = CFRunLoopGetCurrent();
|
||||||
|
dacontext.cancel = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &cancelRunLoopSourceContext);
|
||||||
|
|
||||||
|
if (!dacontext.cancel)
|
||||||
|
{
|
||||||
|
return DRIVER_OP_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(dacontext.session = DASessionCreate(kCFAllocatorDefault)))
|
||||||
|
{
|
||||||
|
CFRelease(dacontext.cancel);
|
||||||
|
return DRIVER_OP_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((disk = DADiskCreateFromBSDName(kCFAllocatorDefault, dacontext.session, psz_drive)) != NULL)
|
||||||
|
{
|
||||||
|
if ((description = DADiskCopyDescription(disk)) != NULL)
|
||||||
|
{
|
||||||
|
/* Does the device need to be unmounted first? */
|
||||||
|
DASessionScheduleWithRunLoop(dacontext.session, dacontext.runloop, kCFRunLoopDefaultMode);
|
||||||
|
if (CFDictionaryGetValueIfPresent(description, kDADiskDescriptionVolumePathKey, NULL))
|
||||||
|
{
|
||||||
|
DADiskUnmount(disk, kDADiskUnmountOptionDefault, media_unmount_callback, &dacontext);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DADiskEject(disk, kDADiskEjectOptionDefault, media_eject_callback, &dacontext);
|
||||||
|
}
|
||||||
|
CFRunLoopAddSource(dacontext.runloop, dacontext.cancel, kCFRunLoopDefaultMode);
|
||||||
|
if (!dacontext.completed)
|
||||||
|
{
|
||||||
|
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 30.0, TRUE); /* timeout after 30 seconds */
|
||||||
|
}
|
||||||
|
CFRunLoopRemoveSource(dacontext.runloop, dacontext.cancel, kCFRunLoopDefaultMode);
|
||||||
|
DASessionUnscheduleFromRunLoop(dacontext.session, dacontext.runloop, kCFRunLoopDefaultMode);
|
||||||
|
CFRelease(description);
|
||||||
|
}
|
||||||
|
CFRelease(disk);
|
||||||
|
}
|
||||||
|
|
||||||
|
CFRunLoopSourceInvalidate(dacontext.cancel);
|
||||||
|
CFRelease(dacontext.cancel);
|
||||||
|
CFRelease(dacontext.session);
|
||||||
|
return dacontext.result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Return the size of the CD in logical block address (LBA) units.
|
Return the size of the CD in logical block address (LBA) units.
|
||||||
|
|||||||
Reference in New Issue
Block a user