Commit 9400b572 authored by Jon Lech Johansen's avatar Jon Lech Johansen

* MacOS X VCD support.

parent ff619dd6
......@@ -96,6 +96,7 @@ LIB_QNX = @LIB_QNX@
LIB_QT = @LIB_QT@
LIB_RC = @LIB_RC@
LIB_SDL = @LIB_SDL@
LIB_VCD = @LIB_VCD@
LIB_WAVEOUT = @LIB_WAVEOUT@
LIB_WIN32 = @LIB_WIN32@
LIB_X11 = @LIB_X11@
......
......@@ -6494,6 +6494,12 @@ then
BUILTINS="${BUILTINS} vcd"
fi
if test x$enable_vcd != xno -a "${SYS}" = "darwin"
then
BUILTINS="${BUILTINS} vcd"
LIB_VCD="${LIB_VCD} -framework IOKit"
fi
# Check whether --enable-dummy or --disable-dummy was given.
if test "${enable_dummy+set}" = set; then
enableval="$enable_dummy"
......@@ -8331,6 +8337,7 @@ s%@LIB_QNX@%$LIB_QNX%g
s%@LIB_QT@%$LIB_QT%g
s%@LIB_RC@%$LIB_RC%g
s%@LIB_SDL@%$LIB_SDL%g
s%@LIB_VCD@%$LIB_VCD%g
s%@LIB_WAVEOUT@%$LIB_WAVEOUT%g
s%@LIB_WIN32@%$LIB_WIN32%g
s%@LIB_X11@%$LIB_X11%g
......
......@@ -903,6 +903,12 @@ then
BUILTINS="${BUILTINS} vcd"
fi
if test x$enable_vcd != xno -a "${SYS}" = "darwin"
then
BUILTINS="${BUILTINS} vcd"
LIB_VCD="${LIB_VCD} -framework IOKit"
fi
dnl
dnl dummy plugin
dnl
......@@ -1541,6 +1547,7 @@ AC_SUBST(LIB_QNX)
AC_SUBST(LIB_QT)
AC_SUBST(LIB_RC)
AC_SUBST(LIB_SDL)
AC_SUBST(LIB_VCD)
AC_SUBST(LIB_WAVEOUT)
AC_SUBST(LIB_WIN32)
AC_SUBST(LIB_X11)
......
vcd_SOURCES = vcd.c input_vcd.c linux_cdrom_tools.c
vcd_SOURCES = vcd.c input_vcd.c cdrom_tools.c
/****************************************************************************
* linux_cdrom_tools.c: linux cdrom tools
* cdrom_tools.c: cdrom tools
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id: cdrom_tools.c,v 1.1 2002/02/20 05:50:00 jlj Exp $
*
* Author: Johan Bilien <jobi@via.ecp.fr>
* Jon Lech Johansen <jon-vl@nanocrew.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -39,13 +41,57 @@
#include <sys/ioctl.h>
#include "linux_cdrom_tools.h"
#if defined(HAVE_BSD_DVD_STRUCT) || \
defined(DVD_STRUCT_IN_BSDI_DVDIOCTL_DVD_H) || \
defined(DVD_STRUCT_IN_DVD_H)
# include <dvd.h>
#elif defined ( SYS_DARWIN )
# include <CoreFoundation/CFBase.h>
# include <IOKit/IOKitLib.h>
# include <IOKit/storage/IOCDTypes.h>
# include <IOKit/storage/IOCDMedia.h>
# include <IOKit/storage/IOCDMediaBSDClient.h>
#else
# include <linux/cdrom.h>
#endif
#include "cdrom_tools.h"
/*****************************************************************************
* Platform specific
*****************************************************************************/
#if defined( SYS_DARWIN )
CDTOC *getTOC( const char * );
#define freeTOC( p ) free( (void*)p )
int getNumberOfDescriptors( CDTOC * );
int getNumberOfTracks( CDTOC *, int );
#define CD_MIN_TRACK_NO 01
#define CD_MAX_TRACK_NO 99
#endif
/*****************************************************************************
* ioctl_ReadTocHeader: Read the TOC header and return the track number.
*****************************************************************************/
int ioctl_GetTrackCount( int i_fd )
int ioctl_GetTrackCount( int i_fd, const char *psz_dev )
{
int i_count = -1;
#if defined( SYS_DARWIN )
CDTOC *pTOC;
int i_descriptors;
if( ( pTOC = getTOC( psz_dev ) ) == NULL )
{
intf_ErrMsg( "vcd error: failed to get the TOC" );
return( -1 );
}
i_descriptors = getNumberOfDescriptors( pTOC );
i_count = getNumberOfTracks( pTOC, i_descriptors );
freeTOC( pTOC );
#else
struct cdrom_tochdr tochdr;
/* First we read the TOC header */
......@@ -55,16 +101,75 @@ int ioctl_GetTrackCount( int i_fd )
return -1;
}
return tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1;
i_count = tochdr.cdth_trk1 - tochdr.cdth_trk0 + 1;
#endif
return( i_count );
}
/*****************************************************************************
* ioctl_GetSectors: Read the Table of Contents and fill p_vcd.
*****************************************************************************/
int * ioctl_GetSectors( int i_fd )
int * ioctl_GetSectors( int i_fd, const char *psz_dev )
{
int i, i_tracks;
int *p_sectors;
int i, i_tracks;
int *p_sectors = NULL;
#if defined( SYS_DARWIN )
CDTOC *pTOC;
u_char track;
int i_descriptors;
int i_leadout = -1;
CDTOCDescriptor *pTrackDescriptors;
if( ( pTOC = getTOC( psz_dev ) ) == NULL )
{
intf_ErrMsg( "vcd error: failed to get the TOC" );
return( NULL );
}
i_descriptors = getNumberOfDescriptors( pTOC );
i_tracks = getNumberOfTracks( pTOC, i_descriptors );
p_sectors = malloc( (i_tracks + 1) * sizeof(int) );
if( p_sectors == NULL )
{
intf_ErrMsg( "vcd error: could not allocate p_sectors" );
freeTOC( pTOC );
return NULL;
}
pTrackDescriptors = pTOC->descriptors;
for( i_tracks = 0, i = 0; i <= i_descriptors; i++ )
{
track = pTrackDescriptors[i].point;
if( track == 0xA2 )
i_leadout = i;
if( track > CD_MAX_TRACK_NO || track < CD_MIN_TRACK_NO )
continue;
p_sectors[i_tracks++] =
CDConvertMSFToLBA( pTrackDescriptors[i].p );
}
if( i_leadout == -1 )
{
intf_ErrMsg( "vcd error: leadout not found" );
free( p_sectors );
freeTOC( pTOC );
return( NULL );
}
/* set leadout sector */
p_sectors[i_tracks] =
CDConvertMSFToLBA( pTrackDescriptors[i_leadout].p );
freeTOC( pTOC );
#else
struct cdrom_tochdr tochdr;
struct cdrom_tocentry tocent;
......@@ -100,6 +205,7 @@ int * ioctl_GetSectors( int i_fd )
p_sectors[ i ] = tocent.cdte_addr.lba;
}
#endif
return p_sectors;
}
......@@ -110,7 +216,29 @@ int * ioctl_GetSectors( int i_fd )
int ioctl_ReadSector( int i_fd, int i_sector, byte_t * p_buffer )
{
byte_t p_block[ VCD_SECTOR_SIZE ];
int i_dummy = i_sector + 2 * CD_FRAMES;
#if defined( SYS_DARWIN )
dk_cd_read_t cd_read;
memset( &cd_read, 0, sizeof(cd_read) );
cd_read.offset = i_sector * VCD_SECTOR_SIZE;
cd_read.sectorArea = kCDSectorAreaSync | kCDSectorAreaHeader |
kCDSectorAreaSubHeader | kCDSectorAreaUser |
kCDSectorAreaAuxiliary;
cd_read.sectorType = kCDSectorTypeUnknown;
cd_read.buffer = p_block;
cd_read.bufferLength = sizeof(p_block);
if( ioctl( i_fd, DKIOCCDREAD, &cd_read ) == -1 )
{
intf_ErrMsg( "vcd error: could not read block %d", i_sector );
return( -1 );
}
#else
int i_dummy = i_sector + 2 * CD_FRAMES;
#define p_msf ((struct cdrom_msf0 *)p_block)
p_msf->minute = i_dummy / (CD_FRAMES * CD_SECS);
......@@ -122,12 +250,167 @@ int ioctl_ReadSector( int i_fd, int i_sector, byte_t * p_buffer )
{
intf_ErrMsg( "vcd error: could not read block %i from disc",
i_sector );
return -1;
return( -1 );
}
#endif
/* We don't want to keep the header of the read sector */
FAST_MEMCPY( p_buffer, p_block + VCD_DATA_START, VCD_DATA_SIZE );
return 0;
return( 0 );
}
#if defined( SYS_DARWIN )
/****************************************************************************
* getTOC: get the TOC
****************************************************************************/
CDTOC *getTOC( const char *psz_dev )
{
mach_port_t port;
char *psz_devname;
kern_return_t ret;
CDTOC *pTOC = NULL;
io_iterator_t iterator;
io_registry_entry_t service;
CFDictionaryRef properties;
CFDataRef data;
if( psz_dev == NULL )
{
intf_ErrMsg( "vcd error: invalid device path" );
return( NULL );
}
/* get the device name */
if( ( psz_devname = strrchr( psz_dev, '/') ) != NULL )
++psz_devname;
else
psz_devname = (char *)psz_dev;
/* unraw the device name */
if( *psz_devname == 'r' )
++psz_devname;
/* get port for IOKit communication */
if( ( ret = IOMasterPort( MACH_PORT_NULL, &port ) ) != KERN_SUCCESS )
{
intf_ErrMsg( "vcd error: IOMasterPort: 0x%08x", ret );
return( NULL );
}
/* get service iterator for the device */
if( ( ret = IOServiceGetMatchingServices(
port, IOBSDNameMatching( port, 0, psz_devname ),
&iterator ) ) != KERN_SUCCESS )
{
intf_ErrMsg( "vcd error: IOServiceGetMatchingServices: 0x%08x", ret );
return( NULL );
}
/* first service */
service = IOIteratorNext( iterator );
IOObjectRelease( iterator );
/* search for kIOCDMediaClass */
while( service && !IOObjectConformsTo( service, kIOCDMediaClass ) )
{
if( ( ret = IORegistryEntryGetParentIterator( service,
kIOServicePlane, &iterator ) ) != KERN_SUCCESS )
{
intf_ErrMsg( "vcd error: " \
"IORegistryEntryGetParentIterator: 0x%08x", ret );
IOObjectRelease( service );
return( NULL );
}
IOObjectRelease( service );
service = IOIteratorNext( iterator );
IOObjectRelease( iterator );
}
if( service == NULL )
{
intf_ErrMsg( "vcd error: search for kIOCDMediaClass came up empty" );
return( NULL );
}
/* create a CF dictionary containing the TOC */
if( ( ret = IORegistryEntryCreateCFProperties( service, &properties,
kCFAllocatorDefault, kNilOptions ) ) != KERN_SUCCESS )
{
intf_ErrMsg( "vcd error: " \
" IORegistryEntryCreateCFProperties: 0x%08x", ret );
IOObjectRelease( service );
return( NULL );
}
/* get the TOC from the dictionary */
if( ( data = (CFDataRef) CFDictionaryGetValue( properties,
CFSTR(kIOCDMediaTOCKey) ) ) != NULL )
{
CFRange range;
CFIndex buf_len;
buf_len = CFDataGetLength( data ) + 1;
range = CFRangeMake( 0, buf_len );
if( ( pTOC = (CDTOC *)malloc( buf_len ) ) != NULL )
{
CFDataGetBytes( data, range, (u_char *)pTOC );
}
}
else
{
intf_ErrMsg( "vcd error: CFDictionaryGetValue failed" );
}
CFRelease( properties );
IOObjectRelease( service );
return( pTOC );
}
/****************************************************************************
* getNumberOfDescriptors: get number of descriptors in TOC
****************************************************************************/
int getNumberOfDescriptors( CDTOC *pTOC )
{
int i_descriptors;
/* get TOC length */
i_descriptors = pTOC->length;
/* remove the first and last session */
i_descriptors -= ( sizeof(pTOC->sessionFirst) +
sizeof(pTOC->sessionLast) );
/* divide the length by the size of a single descriptor */
i_descriptors /= sizeof(CDTOCDescriptor);
return( i_descriptors );
}
/****************************************************************************
* getNumberOfTracks: get number of tracks in TOC
****************************************************************************/
int getNumberOfTracks( CDTOC *pTOC, int i_descriptors )
{
u_char track;
int i, i_tracks = 0;
CDTOCDescriptor *pTrackDescriptors;
pTrackDescriptors = pTOC->descriptors;
for( i = i_descriptors; i >= 0; i-- )
{
track = pTrackDescriptors[i].point;
if( track > CD_MAX_TRACK_NO || track < CD_MIN_TRACK_NO )
continue;
i_tracks++;
}
return( i_tracks );
}
#endif
/****************************************************************************
* linux_cdrom_tools.h: linux cdrom tools header
* cdrom_tools.h: cdrom tools header
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id: cdrom_tools.h,v 1.1 2002/02/20 05:50:00 jlj Exp $
*
* Author: Johan Bilien <jobi@via.ecp.fr>
*
......@@ -20,12 +21,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#if defined(HAVE_BSD_DVD_STRUCT) || defined(DVD_STRUCT_IN_BSDI_DVDIOCTL_DVD_H) || defined(DVD_STRUCT_IN_DVD_H)
# include <dvd.h>
#else
# include <linux/cdrom.h>
#endif
/* where the data start on a VCD sector */
#define VCD_DATA_START 24
/* size of the availablr data on a VCD sector */
......@@ -36,7 +31,7 @@
/******************************************************************************
* Prototypes *
******************************************************************************/
int ioctl_GetTrackCount ( int );
int * ioctl_GetSectors ( int );
int ioctl_GetTrackCount ( int, const char *psz_dev );
int * ioctl_GetSectors ( int, const char *psz_dev );
int ioctl_ReadSector ( int, int, byte_t * );
......@@ -59,7 +59,7 @@
#include "debug.h"
#include "input_vcd.h"
#include "linux_cdrom_tools.h"
#include "cdrom_tools.h"
/* how many blocks VCDRead will read in each loop */
#define VCD_BLOCKS_ONCE 4
......@@ -217,7 +217,8 @@ static void VCDInit( input_thread_t * p_input )
p_vcd->i_handle = p_input->i_handle;
/* We read the Table Of Content information */
p_vcd->nb_tracks = ioctl_GetTrackCount( p_input->i_handle );
p_vcd->nb_tracks = ioctl_GetTrackCount( p_input->i_handle,
p_input->p_source );
if( p_vcd->nb_tracks < 0 )
{
input_BuffersEnd( p_input->p_method_data );
......@@ -234,7 +235,8 @@ static void VCDInit( input_thread_t * p_input )
return;
}
p_vcd->p_sectors = ioctl_GetSectors( p_input->i_handle );
p_vcd->p_sectors = ioctl_GetSectors( p_input->i_handle,
p_input->p_source );
if ( p_vcd->p_sectors == NULL )
{
input_BuffersEnd( p_input->p_method_data );
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment