diff options
85 files changed, 14192 insertions, 6035 deletions
@@ -128,6 +128,10 @@ xine is using VCD interpretation code in the extended VCD plugin from VCDImager by Herbert Valerio Riedel http://vcdimager.org + CD I/O routines for the above from GNU libcdio + by Rocky Bernstein and Herbert Valerio Riedel + http://www.gnu.org/software/libcdio + Goom - visual effects generator Written by Jean-Christophe Hoelt et. al. http://ios.free.fr/?page=projet&quoi=1 @@ -22,7 +22,8 @@ libdvdnav 0.1.10 Michael Roitzsch libfaad 2.0 Miguel Freitas libmad 0.15.1b Miguel Freitas libmpeg2 0.2.1 [*] -libvcd 0.7.20 +libcdio 0.71 [o] +libvcd 0.7.21 [o] nosefart 1.92 Mike Melanson tvtime 0.9.8.4 Miguel Freitas wine @@ -54,3 +55,9 @@ note that we have also backported some fixes/improvements from libmpeg2 cvs (eg. motion vector clipping for broken streams). if you need any specific change or fix feel free to send us a patch or discuss the issue at xine-devel. + + +[o] These libraries are not well maintained and subsetted from the + packages where they come from. The external versions of libcdio + and libvcdinfo are preferred. You also get regression tests and + CD/VCD diagnostic tools. diff --git a/src/input/vcd/libcdio/FreeBSD/freebsd.c b/src/input/vcd/libcdio/FreeBSD/freebsd.c new file mode 100644 index 000000000..daea9b3f5 --- /dev/null +++ b/src/input/vcd/libcdio/FreeBSD/freebsd.c @@ -0,0 +1,638 @@ +/* + $Id: freebsd.c,v 1.1 2005/01/01 02:43:57 rockyb Exp $ + + Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* This file contains FreeBSD-specific code and implements low-level + control of the CD drive. Culled initially I think from xine's or + mplayer's FreeBSD code with lots of modifications. +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +static const char _rcsid[] = "$Id: freebsd.c,v 1.1 2005/01/01 02:43:57 rockyb Exp $"; + +#include "freebsd.h" + +#ifdef HAVE_FREEBSD_CDROM + +#include <cdio/sector.h> + +static access_mode_t +str_to_access_mode_freebsd(const char *psz_access_mode) +{ + const access_mode_t default_access_mode = DEFAULT_FREEBSD_AM; + + if (NULL==psz_access_mode) return default_access_mode; + + if (!strcmp(psz_access_mode, "ioctl")) + return _AM_IOCTL; + else if (!strcmp(psz_access_mode, "CAM")) + return _AM_CAM; + else { + cdio_warn ("unknown access type: %s. Default ioctl used.", + psz_access_mode); + return default_access_mode; + } +} + +static void +_free_freebsd (void *obj) +{ + _img_private_t *env = obj; + + if (NULL == env) return; + + if (NULL != env->device) free(env->device); + + if (_AM_CAM == env->access_mode) + return free_freebsd_cam(env); + else + return cdio_generic_free(obj); +} + +/* Check a drive to see if it is a CD-ROM + Return 1 if a CD-ROM. 0 if it exists but isn't a CD-ROM drive + and -1 if no device exists . +*/ +static bool +cdio_is_cdrom(char *drive, char *mnttype) +{ + return cdio_is_cdrom_freebsd_ioctl(drive, mnttype); +} + +/*! + Reads nblocks of audio sectors from cd device into data starting from lsn. + Returns 0 if no error. + */ +static int +_read_audio_sectors_freebsd (void *user_data, void *data, lsn_t lsn, + unsigned int nblocks) +{ + return read_audio_sectors_freebsd_ioctl(user_data, data, lsn, nblocks); +} + +/*! + Reads a single mode2 sector from cd device into data starting + from lsn. Returns 0 if no error. + */ +static int +_read_mode2_sector_freebsd (void *user_data, void *data, lsn_t lsn, + bool b_form2) +{ + _img_private_t *env = user_data; + + if ( env->access_mode == _AM_CAM ) + return read_mode2_sector_freebsd_cam(env, data, lsn, b_form2); + else + return read_mode2_sector_freebsd_ioctl(env, data, lsn, b_form2); +} + +/*! + Reads nblocks of mode2 sectors from cd device into data starting + from lsn. + Returns 0 if no error. + */ +static int +_read_mode2_sectors_freebsd (void *user_data, void *data, lsn_t lsn, + bool b_form2, unsigned int nblocks) +{ + _img_private_t *env = user_data; + + if ( env->access_mode == _AM_CAM && b_form2) { + /* We have a routine that covers this case without looping. */ + return read_mode2_sectors_freebsd_cam(env, data, lsn, nblocks); + } else { + unsigned int i; + unsigned int i_blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE; + + /* For each frame, pick out the data part we need */ + for (i = 0; i < nblocks; i++) { + int retval = _read_mode2_sector_freebsd (env, + ((char *)data) + + (i_blocksize * i), + lsn + i, b_form2); + if (retval) return retval; + } + } + return 0; +} + +/*! + Return the size of the CD in logical block address (LBA) units. + */ +static uint32_t +_stat_size_freebsd (void *obj) +{ + _img_private_t *env = obj; + + if (NULL == env) return CDIO_INVALID_LBA; + + if (_AM_CAM == env->access_mode) + return stat_size_freebsd_cam(env); + else + return stat_size_freebsd_ioctl(env); +} + +/*! + Set the key "arg" to "value" in source device. +*/ +static int +_set_arg_freebsd (void *user_data, const char key[], const char value[]) +{ + _img_private_t *env = user_data; + + if (!strcmp (key, "source")) + { + if (!value) + return -2; + + free (env->gen.source_name); + + env->gen.source_name = strdup (value); + } + else if (!strcmp (key, "access-mode")) + { + env->access_mode = str_to_access_mode_freebsd(value); + if (env->access_mode == _AM_CAM && !env->b_cam_init) + return init_freebsd_cam(env) ? 1 : -3; + return 0; + } + else + return -1; + + return 0; +} + +/*! + Read and cache the CD's Track Table of Contents and track info. + Return false if unsuccessful; +*/ +static bool +read_toc_freebsd (void *p_user_data) +{ + _img_private_t *p_env = p_user_data; + track_t i, j; + + /* read TOC header */ + if ( ioctl(p_env->gen.fd, CDIOREADTOCHEADER, &p_env->tochdr) == -1 ) { + cdio_warn("error in ioctl(CDIOREADTOCHEADER): %s\n", strerror(errno)); + return false; + } + + p_env->gen.i_first_track = p_env->tochdr.starting_track; + p_env->gen.i_tracks = p_env->tochdr.ending_track - + p_env->gen.i_first_track + 1; + + j=0; + for (i=p_env->gen.i_first_track; i<=p_env->gen.i_tracks; i++, j++) { + p_env->tocent[j].track = i; + p_env->tocent[j].address_format = CD_LBA_FORMAT; + + if ( ioctl(p_env->gen.fd, CDIOREADTOCENTRY, &(p_env->tocent[j]) ) ) { + cdio_warn("%s %d: %s\n", + "error in ioctl CDROMREADTOCENTRY for track", + i, strerror(errno)); + return false; + } + } + + p_env->tocent[j].track = CDIO_CDROM_LEADOUT_TRACK; + p_env->tocent[j].address_format = CD_LBA_FORMAT; + if ( ioctl(p_env->gen.fd, CDIOREADTOCENTRY, &(p_env->tocent[j]) ) ){ + cdio_warn("%s: %s\n", + "error in ioctl CDROMREADTOCENTRY for leadout track", + strerror(errno)); + return false; + } + + p_env->gen.toc_init = true; + return true; +} + +/*! + Eject media. Return 1 if successful, 0 otherwise. + */ +static int +_eject_media_freebsd (void *user_data) +{ + _img_private_t *p_env = user_data; + + return (p_env->access_mode == _AM_IOCTL) + ? eject_media_freebsd_ioctl(p_env) + : eject_media_freebsd_cam(p_env); +} + +/*! + Return the value associated with the key "arg". +*/ +static const char * +_get_arg_freebsd (void *user_data, const char key[]) +{ + _img_private_t *env = user_data; + + if (!strcmp (key, "source")) { + return env->gen.source_name; + } else if (!strcmp (key, "access-mode")) { + switch (env->access_mode) { + case _AM_IOCTL: + return "ioctl"; + case _AM_CAM: + return "CAM"; + case _AM_NONE: + return "no access method"; + } + } + return NULL; +} + +/*! + Return the media catalog number MCN. + + Note: string is malloc'd so caller should free() then returned + string when done with it. + + FIXME: This is just a guess. + + */ +static char * +_get_mcn_freebsd (const void *p_user_data) { + + const _img_private_t *p_env = p_user_data; + + return (p_env->access_mode == _AM_IOCTL) + ? get_mcn_freebsd_ioctl(p_env) + : scsi_mmc_get_mcn(p_env->gen.cdio); + +} + +static void +get_drive_cap_freebsd (const void *p_user_data, + cdio_drive_read_cap_t *p_read_cap, + cdio_drive_write_cap_t *p_write_cap, + cdio_drive_misc_cap_t *p_misc_cap) +{ + const _img_private_t *p_env = p_user_data; + + if (p_env->access_mode == _AM_CAM) + scsi_mmc_get_drive_cap_generic (p_user_data, p_read_cap, p_write_cap, + p_misc_cap); + +} + +/*! + Run a SCSI MMC command. + + p_user_data internal CD structure. + i_timeout_ms time in milliseconds we will wait for the command + to complete. If this value is -1, use the default + time-out value. + i_cdb Size of p_cdb + p_cdb CDB bytes. + e_direction direction the transfer is to go. + i_buf Size of buffer + p_buf Buffer for data, both sending and receiving + + Return 0 if no error. + */ +static int +run_scsi_cmd_freebsd( const void *p_user_data, unsigned int i_timeout_ms, + unsigned int i_cdb, const scsi_mmc_cdb_t *p_cdb, + scsi_mmc_direction_t e_direction, + unsigned int i_buf, /*in/out*/ void *p_buf ) +{ + const _img_private_t *p_env = p_user_data; + + if (p_env->access_mode == _AM_CAM) + return run_scsi_cmd_freebsd_cam( p_user_data, i_timeout_ms, i_cdb, p_cdb, + e_direction, i_buf, p_buf ); + else + return 2; +} + +/*! + Get format of track. + + FIXME: We're just guessing this from the GNU/Linux code. + +*/ +static track_format_t +_get_track_format_freebsd(void *p_user_data, track_t i_track) +{ + _img_private_t *p_env = p_user_data; + + if (!p_env->gen.toc_init) read_toc_freebsd (p_user_data) ; + + if (i_track > TOTAL_TRACKS || i_track == 0) + return TRACK_FORMAT_ERROR; + + i_track -= FIRST_TRACK_NUM; + + /* This is pretty much copied from the "badly broken" cdrom_count_tracks + in linux/cdrom.c. + */ + if (p_env->tocent[i_track].entry.control & CDIO_CDROM_DATA_TRACK) { + if (p_env->tocent[i_track].address_format == CDIO_CDROM_CDI_TRACK) + return TRACK_FORMAT_CDI; + else if (p_env->tocent[i_track].address_format == CDIO_CDROM_XA_TRACK) + return TRACK_FORMAT_XA; + else + return TRACK_FORMAT_DATA; + } else + return TRACK_FORMAT_AUDIO; + +} + +/*! + Return true if we have XA data (green, mode2 form1) or + XA data (green, mode2 form2). That is track begins: + sync - header - subheader + 12 4 - 8 + + FIXME: there's gotta be a better design for this and get_track_format? +*/ +static bool +_get_track_green_freebsd(void *user_data, track_t i_track) +{ + _img_private_t *p_env = user_data; + + if (i_track == CDIO_CDROM_LEADOUT_TRACK) i_track = TOTAL_TRACKS+1; + + if (i_track > TOTAL_TRACKS+1 || i_track == 0) + return false; + + /* FIXME: Dunno if this is the right way, but it's what + I was using in cdinfo for a while. + */ + return ((p_env->tocent[i_track-FIRST_TRACK_NUM].entry.control & 2) != 0); +} + +/*! + Return the starting LSN track number + i_track in obj. Track numbers start at 1. + The "leadout" track is specified either by + using i_track LEADOUT_TRACK or the total tracks+1. + CDIO_INVALID_LBA is returned if there is no track entry. +*/ +static lba_t +_get_track_lba_freebsd(void *user_data, track_t i_track) +{ + _img_private_t *p_env = user_data; + + if (!p_env->gen.toc_init) read_toc_freebsd (p_env) ; + + if (i_track == CDIO_CDROM_LEADOUT_TRACK) i_track = TOTAL_TRACKS+1; + + if (i_track > TOTAL_TRACKS+1 || i_track == 0 || !p_env->gen.toc_init) { + return CDIO_INVALID_LBA; + } else { + return cdio_lsn_to_lba(ntohl(p_env->tocent[i_track-FIRST_TRACK_NUM].entry.addr.lba)); + } +} + +#endif /* HAVE_FREEBSD_CDROM */ + +/*! + Return an array of strings giving possible CD devices. + */ +char ** +cdio_get_devices_freebsd (void) +{ +#ifndef HAVE_FREEBSD_CDROM + return NULL; +#else + char drive[40]; + char **drives = NULL; + unsigned int num_drives=0; + bool exists=true; + char c; + + /* Scan the system for CD-ROM drives. + */ + +#ifdef USE_ETC_FSTAB + + struct fstab *fs; + setfsent(); + + /* Check what's in /etc/fstab... */ + while ( (fs = getfsent()) ) + { + if (strncmp(fs->fs_spec, "/dev/sr", 7)) + cdio_add_device_list(&drives, fs->fs_spec, &num_drives); + } + +#endif + + /* Scan the system for CD-ROM drives. + Not always 100% reliable, so use the USE_MNTENT code above first. + */ + + /* Scan SCSI and CAM devices */ + for ( c='0'; exists && c <='9'; c++ ) { + sprintf(drive, "/dev/cd%c%s", c, DEVICE_POSTFIX); + exists = cdio_is_cdrom(drive, NULL); + if ( exists ) { + cdio_add_device_list(&drives, drive, &num_drives); + } + } + + /* Scan are ATAPI devices */ + for ( c='0'; exists && c <='9'; c++ ) { + sprintf(drive, "/dev/acd%c%s", c, DEVICE_POSTFIX); + exists = cdio_is_cdrom(drive, NULL); + if ( exists ) { + cdio_add_device_list(&drives, drive, &num_drives); + } + } + cdio_add_device_list(&drives, NULL, &num_drives); + return drives; +#endif /*HAVE_FREEBSD_CDROM*/ +} + +/*! + Return a string containing the default CD device if none is specified. + */ +char * +cdio_get_default_device_freebsd() +{ +#ifndef HAVE_FREEBSD_CDROM + return NULL; +#else + char drive[40]; + bool exists=true; + char c; + + /* Scan the system for CD-ROM drives. + */ + +#ifdef USE_ETC_FSTAB + + struct fstab *fs; + setfsent(); + + /* Check what's in /etc/fstab... */ + while ( (fs = getfsent()) ) + { + if (strncmp(fs->fs_spec, "/dev/sr", 7)) + return strdup(fs->fs_spec); + } + +#endif + + /* Scan the system for CD-ROM drives. + Not always 100% reliable, so use the USE_MNTENT code above first. + */ + + /* Scan SCSI and CAM devices */ + for ( c='0'; exists && c <='9'; c++ ) { + sprintf(drive, "/dev/cd%c%s", c, DEVICE_POSTFIX); + exists = cdio_is_cdrom(drive, NULL); + if ( exists ) { + return strdup(drive); + } + } + + /* Scan are ATAPI devices */ + for ( c='0'; exists && c <='9'; c++ ) { + sprintf(drive, "/dev/acd%c%s", c, DEVICE_POSTFIX); + exists = cdio_is_cdrom(drive, NULL); + if ( exists ) { + return strdup(drive); + } + } + return NULL; +#endif /*HAVE_FREEBSD_CDROM*/ +} + +/*! + Initialization routine. This is the only thing that doesn't + get called via a function pointer. In fact *we* are the + ones to set that up. + */ +CdIo * +cdio_open_freebsd (const char *psz_source_name) +{ + return cdio_open_am_freebsd(psz_source_name, NULL); +} + + +/*! + Initialization routine. This is the only thing that doesn't + get called via a function pointer. In fact *we* are the + ones to set that up. + */ +CdIo * +cdio_open_am_freebsd (const char *psz_orig_source_name, + const char *psz_access_mode) +{ + +#ifdef HAVE_FREEBSD_CDROM + CdIo *ret; + _img_private_t *_data; + char *psz_source_name; + + cdio_funcs _funcs = { + .eject_media = _eject_media_freebsd, + .free = _free_freebsd, + .get_arg = _get_arg_freebsd, + .get_cdtext = get_cdtext_generic, + .get_default_device = cdio_get_default_device_freebsd, + .get_devices = cdio_get_devices_freebsd, + .get_discmode = get_discmode_generic, + .get_drive_cap = get_drive_cap_freebsd, + .get_first_track_num= get_first_track_num_generic, + .get_mcn = _get_mcn_freebsd, + .get_num_tracks = get_num_tracks_generic, + .get_track_format = _get_track_format_freebsd, + .get_track_green = _get_track_green_freebsd, + .get_track_lba = _get_track_lba_freebsd, + .get_track_msf = NULL, + .lseek = cdio_generic_lseek, + .read = cdio_generic_read, + .read_audio_sectors = _read_audio_sectors_freebsd, + .read_mode2_sector = _read_mode2_sector_freebsd, + .read_mode2_sectors = _read_mode2_sectors_freebsd, + .read_toc = read_toc_freebsd, + .run_scsi_mmc_cmd = run_scsi_cmd_freebsd, + .set_arg = _set_arg_freebsd, + .stat_size = _stat_size_freebsd + }; + + _data = _cdio_malloc (sizeof (_img_private_t)); + _data->access_mode = str_to_access_mode_freebsd(psz_access_mode); + _data->gen.init = false; + _data->gen.fd = -1; + _data->gen.toc_init = false; + _data->gen.b_cdtext_init = false; + _data->gen.b_cdtext_error = false; + + if (NULL == psz_orig_source_name) { + psz_source_name=cdio_get_default_device_freebsd(); + if (NULL == psz_source_name) return NULL; + _data->device = psz_source_name; + _set_arg_freebsd(_data, "source", psz_source_name); + } else { + if (cdio_is_device_generic(psz_orig_source_name)) { + _set_arg_freebsd(_data, "source", psz_orig_source_name); + _data->device = strdup(psz_orig_source_name); + } else { + /* The below would be okay if all device drivers worked this way. */ +#if 0 + cdio_info ("source %s is a not a device", psz_orig_source_name); +#endif + return NULL; + } + } + + ret = cdio_new ((void *)_data, &_funcs); + if (ret == NULL) return NULL; + + if (cdio_generic_init(_data)) + if ( _data->access_mode == _AM_IOCTL ) { + return ret; + } else { + if (init_freebsd_cam(_data)) + return ret; + else { + cdio_generic_free (_data); + return NULL; + } + } + else { + cdio_generic_free (_data); + return NULL; + } + +#else + return NULL; +#endif /* HAVE_FREEBSD_CDROM */ + +} + +bool +cdio_have_freebsd (void) +{ +#ifdef HAVE_FREEBSD_CDROM + return true; +#else + return false; +#endif /* HAVE_FREEBSD_CDROM */ +} diff --git a/src/input/vcd/libcdio/FreeBSD/freebsd.h b/src/input/vcd/libcdio/FreeBSD/freebsd.h new file mode 100644 index 000000000..50894c912 --- /dev/null +++ b/src/input/vcd/libcdio/FreeBSD/freebsd.h @@ -0,0 +1,232 @@ +/* + $Id: freebsd.h,v 1.1 2005/01/01 02:43:57 rockyb Exp $ + + Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* This file contains FreeBSD-specific code and implements low-level + control of the CD drive. Culled initially I think from xine's or + mplayer's FreeBSD code with lots of modifications. +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <cdio/sector.h> +#include "cdio_assert.h" +#include "cdio_private.h" + +/*! + For ioctl access /dev/acd0c is preferred over /dev/cd0c. + For cam access /dev/cd0c is preferred. DEFAULT_CDIO_DEVICE and + DEFAULT_FREEBSD_AM should be consistent. + */ + +#ifndef DEFAULT_CDIO_DEVICE +#define DEFAULT_CDIO_DEVICE "/dev/cd0c" +#endif + +#ifndef DEFUALT_FREEBSD_AM +#define DEFAULT_FREEBSD_AM _AM_CAM +#endif + +#include <string.h> + +#ifdef HAVE_FREEBSD_CDROM + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> + +#ifdef HAVE_SYS_CDIO_H +# include <sys/cdio.h> +#endif + +#ifndef CDIOCREADAUDIO +struct ioc_read_audio +{ + u_char address_format; + union msf_lba address; + int nframes; + u_char* buffer; +}; + +#define CDIOCREADAUDIO _IOWR('c',31,struct ioc_read_audio) +#endif + +#include <sys/cdrio.h> + +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/param.h> /* for __FreeBSD_version */ + +#if __FreeBSD_version < 500000 +#define DEVICE_POSTFIX "c" +#else +#define DEVICE_POSTFIX "" +#endif + +#define HAVE_FREEBSD_CAM +#ifdef HAVE_FREEBSD_CAM +#include <camlib.h> + +#include <cam/scsi/scsi_message.h> +#include <cam/scsi/scsi_pass.h> +#include <errno.h> +#define ERRCODE(s) ((((s)[2]&0x0F)<<16)|((s)[12]<<8)|((s)[13])) +#define EMEDIUMTYPE EINVAL +#define ENOMEDIUM ENODEV +#define CREAM_ON_ERRNO(s) do { \ + switch ((s)[12]) \ + { case 0x04: errno=EAGAIN; break; \ + case 0x20: errno=ENODEV; break; \ + case 0x21: if ((s)[13]==0) errno=ENOSPC; \ + else errno=EINVAL; \ + break; \ + case 0x30: errno=EMEDIUMTYPE; break; \ + case 0x3A: errno=ENOMEDIUM; break; \ + } \ +} while(0) +#endif /*HAVE_FREEBSD_CAM*/ + +#include <cdio/util.h> + +#define TOTAL_TRACKS ( p_env->tochdr.ending_track \ + - p_env->tochdr.starting_track + 1) +#define FIRST_TRACK_NUM (p_env->tochdr.starting_track) + +typedef enum { + _AM_NONE, + _AM_IOCTL, + _AM_CAM +} access_mode_t; + +typedef struct { + /* Things common to all drivers like this. + This must be first. */ + generic_img_private_t gen; + +#ifdef HAVE_FREEBSD_CAM + char *device; + struct cam_device *cam; + union ccb ccb; +#endif + + access_mode_t access_mode; + + bool b_ioctl_init; + bool b_cam_init; + + /* Track information */ + struct ioc_toc_header tochdr; + + /* Entry info for each track. Add 1 for leadout. */ + struct ioc_read_toc_single_entry tocent[CDIO_CD_MAX_TRACKS+1]; + +} _img_private_t; + +bool cdio_is_cdrom_freebsd_ioctl(char *drive, char *mnttype); + +track_format_t get_track_format_freebsd_ioctl(const _img_private_t *env, + track_t i_track); +bool get_track_green_freebsd_ioctl(const _img_private_t *env, + track_t i_track); + +int eject_media_freebsd_ioctl (_img_private_t *env); +int eject_media_freebsd_cam (_img_private_t *env); + +void get_drive_cap_freebsd_cam (const _img_private_t *p_env, + cdio_drive_read_cap_t *p_read_cap, + cdio_drive_write_cap_t *p_write_cap, + cdio_drive_misc_cap_t *p_misc_cap); + +char *get_mcn_freebsd_ioctl (const _img_private_t *p_env); + +void free_freebsd_cam (void *obj); + +/*! + Using the ioctl method, r nblocks of audio sectors from cd device + into data starting from lsn. Returns 0 if no error. + */ +int read_audio_sectors_freebsd_ioctl (_img_private_t *env, void *data, + lsn_t lsn, unsigned int nblocks); +/*! + Using the CAM method, reads nblocks of mode2 sectors from + cd device using into data starting from lsn. Returns 0 if no + error. +*/ +int read_mode2_sector_freebsd_cam (_img_private_t *env, void *data, + lsn_t lsn, bool b_form2); + +/*! + Using the ioctl method, reads nblocks of mode2 sectors from + cd device using into data starting from lsn. Returns 0 if no + error. +*/ +int read_mode2_sector_freebsd_ioctl (_img_private_t *env, void *data, + lsn_t lsn, bool b_form2); + +/*! + Using the CAM method, reads nblocks of mode2 form2 sectors from + cd device using into data starting from lsn. Returns 0 if no + error. + + Note: if you want form1 sectors, the caller has to pick out the + appropriate piece. +*/ +int read_mode2_sectors_freebsd_cam (_img_private_t *env, void *buf, + lsn_t lsn, unsigned int nblocks); + +bool read_toc_freebsd_ioctl (_img_private_t *env); + +/*! + Run a SCSI MMC command. + + p_user_data internal CD structure. + i_timeout time in milliseconds we will wait for the command + to complete. If this value is -1, use the default + time-out value. + i_cdb Size of p_cdb + p_cdb CDB bytes. + e_direction direction the transfer is to go. + i_buf Size of buffer + p_buf Buffer for data, both sending and receiving + + Return 0 if no error. + */ +int run_scsi_cmd_freebsd_cam( const void *p_user_data, + unsigned int i_timeout_ms, + unsigned int i_cdb, + const scsi_mmc_cdb_t *p_cdb, + scsi_mmc_direction_t e_direction, + unsigned int i_buf, + /*in/out*/ void *p_buf ); + +/*! + Return the size of the CD in logical block address (LBA) units. + */ +uint32_t stat_size_freebsd_cam (_img_private_t *env); +uint32_t stat_size_freebsd_ioctl (_img_private_t *env); + +bool init_freebsd_cam (_img_private_t *env); +void free_freebsd_cam (void *user_data); + +#endif /*HAVE_FREEBSD_CDROM*/ diff --git a/src/input/vcd/libcdio/FreeBSD/freebsd_cam.c b/src/input/vcd/libcdio/FreeBSD/freebsd_cam.c new file mode 100644 index 000000000..68e38ccae --- /dev/null +++ b/src/input/vcd/libcdio/FreeBSD/freebsd_cam.c @@ -0,0 +1,346 @@ +/* + $Id: freebsd_cam.c,v 1.1 2005/01/01 02:43:57 rockyb Exp $ + + Copyright (C) 2004 Rocky Bernstein <rocky@panix.com> + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* This file contains FreeBSD-specific code and implements low-level + control of the CD drive via SCSI emulation. +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +static const char _rcsid[] = "$Id: freebsd_cam.c,v 1.1 2005/01/01 02:43:57 rockyb Exp $"; + +#ifdef HAVE_FREEBSD_CDROM + +#include "freebsd.h" +#include <cdio/scsi_mmc.h> + +/* Default value in seconds we will wait for a command to + complete. */ +#define DEFAULT_TIMEOUT_MSECS 10000 + +/*! + Run a SCSI MMC command. + + p_user_data internal CD structure. + i_timeout_ms time in milliseconds we will wait for the command + to complete. If this value is -1, use the default + time-out value. + i_cdb Size of p_cdb + p_cdb CDB bytes. + e_direction direction the transfer is to go. + i_buf Size of buffer + p_buf Buffer for data, both sending and receiving + + Return 0 if no error. + */ +int +run_scsi_cmd_freebsd_cam( const void *p_user_data, unsigned int i_timeout_ms, + unsigned int i_cdb, const scsi_mmc_cdb_t *p_cdb, + scsi_mmc_direction_t e_direction, + unsigned int i_buf, /*in/out*/ void *p_buf ) +{ + const _img_private_t *p_env = p_user_data; + int i_status; + int direction = CAM_DEV_QFRZDIS; + union ccb ccb; + + if (!p_env || !p_env->cam) return -2; + + memset(&ccb, 0, sizeof(ccb)); + + ccb.ccb_h.path_id = p_env->cam->path_id; + ccb.ccb_h.target_id = p_env->cam->target_id; + ccb.ccb_h.target_lun = p_env->cam->target_lun; + ccb.ccb_h.timeout = i_timeout_ms; + + if (!i_cdb) + direction |= CAM_DIR_NONE; + else + direction |= (e_direction == SCSI_MMC_DATA_READ)?CAM_DIR_IN : CAM_DIR_OUT; + cam_fill_csio (&(ccb.csio), 1, NULL, + direction | CAM_DEV_QFRZDIS, MSG_SIMPLE_Q_TAG, p_buf, i_buf, + sizeof(ccb.csio.sense_data), 0, 30*1000); + + memcpy(ccb.csio.cdb_io.cdb_bytes, p_cdb, i_cdb); + + ccb.csio.cdb_len = + scsi_mmc_get_cmd_len(ccb.csio.cdb_io.cdb_bytes[0]); + + if ((i_status = cam_send_ccb(p_env->cam, &ccb)) < 0) + { + cdio_warn ("transport failed: %d", i_status); + return -1; + } + if ((ccb.ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) + { + return 0; + } + errno = EIO; + i_status = ERRCODE(((unsigned char *)&ccb.csio.sense_data)); + if (i_status == 0) + i_status = -1; + else + CREAM_ON_ERRNO(((unsigned char *)&ccb.csio.sense_data)); + cdio_warn ("transport failed: %d", i_status); + return i_status; +} + +bool +init_freebsd_cam (_img_private_t *p_env) +{ + char pass[100]; + + p_env->cam=NULL; + memset (&p_env->ccb, 0, sizeof(p_env->ccb)); + p_env->ccb.ccb_h.func_code = XPT_GDEVLIST; + + if (-1 == p_env->gen.fd) + p_env->gen.fd = open (p_env->device, O_RDONLY, 0); + + if (p_env->gen.fd < 0) + { + cdio_warn ("open (%s): %s", p_env->device, strerror (errno)); + return false; + } + + if (ioctl (p_env->gen.fd, CAMGETPASSTHRU, &p_env->ccb) < 0) + { + cdio_warn ("open: %s", strerror (errno)); + return false; + } + sprintf (pass,"/dev/%.15s%u", + p_env->ccb.cgdl.periph_name, + p_env->ccb.cgdl.unit_number); + p_env->cam = cam_open_pass (pass,O_RDWR,NULL); + if (!p_env->cam) return false; + + p_env->gen.init = true; + p_env->b_cam_init = true; + return true; +} + +void +free_freebsd_cam (void *user_data) +{ + _img_private_t *p_env = user_data; + + if (NULL == p_env) return; + + if (p_env->gen.fd > 0) + close (p_env->gen.fd); + p_env->gen.fd = -1; + + if(p_env->cam) + cam_close_device(p_env->cam); + + free (p_env); +} + +static int +_set_bsize (_img_private_t *p_env, unsigned int bsize) +{ + scsi_mmc_cdb_t cdb = {{0, }}; + + struct + { + uint8_t reserved1; + uint8_t medium; + uint8_t reserved2; + uint8_t block_desc_length; + uint8_t density; + uint8_t number_of_blocks_hi; + uint8_t number_of_blocks_med; + uint8_t number_of_blocks_lo; + uint8_t reserved3; + uint8_t block_length_hi; + uint8_t block_length_med; + uint8_t block_length_lo; + } mh; + + memset (&mh, 0, sizeof (mh)); + mh.block_desc_length = 0x08; + mh.block_length_hi = (bsize >> 16) & 0xff; + mh.block_length_med = (bsize >> 8) & 0xff; + mh.block_length_lo = (bsize >> 0) & 0xff; + + memset (&cdb, 0, sizeof (cdb)); + + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_MODE_SELECT_6); + + cdb.field[1] = 1 << 4; + cdb.field[4] = 12; + + return run_scsi_cmd_freebsd_cam (p_env, DEFAULT_TIMEOUT_MSECS, + scsi_mmc_get_cmd_len(cdb.field[0]), + &cdb, SCSI_MMC_DATA_WRITE, + sizeof(mh), &mh); +} + +int +read_mode2_sector_freebsd_cam (_img_private_t *p_env, void *data, lsn_t lsn, + bool b_form2) +{ + if ( b_form2 ) + return read_mode2_sectors_freebsd_cam(p_env, data, lsn, 1); + else { + /* Need to pick out the data portion from a mode2 form2 frame */ + char buf[M2RAW_SECTOR_SIZE] = { 0, }; + int retval = read_mode2_sectors_freebsd_cam(p_env, buf, lsn, 1); + if ( retval ) return retval; + memcpy (((char *)data), buf + CDIO_CD_SUBHEADER_SIZE, CDIO_CD_FRAMESIZE); + return 0; + } +} + +/*! + Reads nblocks of mode2 sectors from cd device into data starting + from lsn. + Returns 0 if no error. + */ +int +read_mode2_sectors_freebsd_cam (_img_private_t *p_env, void *p_buf, + lsn_t lsn, unsigned int nblocks) +{ + scsi_mmc_cdb_t cdb = {{0, }}; + + bool b_read_10 = false; + + CDIO_MMC_SET_READ_LBA(cdb.field, lsn); + + if (b_read_10) { + int retval; + + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_10); + CDIO_MMC_SET_READ_LENGTH16(cdb.field, nblocks); + if ((retval = _set_bsize (p_env, M2RAW_SECTOR_SIZE))) + return retval; + + if ((retval = run_scsi_cmd_freebsd_cam (p_env, 0, + scsi_mmc_get_cmd_len(cdb.field[0]), + &cdb, + SCSI_MMC_DATA_READ, + M2RAW_SECTOR_SIZE * nblocks, + p_buf))) + { + _set_bsize (p_env, CDIO_CD_FRAMESIZE); + return retval; + } + + if ((retval = _set_bsize (p_env, CDIO_CD_FRAMESIZE))) + return retval; + } else + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_CD); + CDIO_MMC_SET_READ_LENGTH24(cdb.field, nblocks); + cdb.field[1] = 0; /* sector size mode2 */ + cdb.field[9] = 0x58; /* 2336 mode2 */ + return run_scsi_cmd_freebsd_cam (p_env, 0, + scsi_mmc_get_cmd_len(cdb.field[0]), + &cdb, + SCSI_MMC_DATA_READ, + M2RAW_SECTOR_SIZE * nblocks, p_buf); + + return 0; +} + +/*! + Return the size of the CD in logical block address (LBA) units. + */ +uint32_t +stat_size_freebsd_cam (_img_private_t *p_env) +{ + scsi_mmc_cdb_t cdb = {{0, }}; + uint8_t buf[12] = { 0, }; + + uint32_t retval; + int i_status; + + /* Operation code */ + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_TOC); + + cdb.field[1] = 0; /* lba; msf: 0x2 */ + + /* Format */ + cdb.field[2] = CDIO_MMC_READTOC_FMT_TOC; + + CDIO_MMC_SET_START_TRACK(cdb.field, CDIO_CDROM_LEADOUT_TRACK); + + CDIO_MMC_SET_READ_LENGTH16(cdb.field, sizeof(buf)); + + p_env->ccb.csio.data_ptr = buf; + p_env->ccb.csio.dxfer_len = sizeof (buf); + + i_status = run_scsi_cmd_freebsd_cam(p_env, DEFAULT_TIMEOUT_MSECS, + scsi_mmc_get_cmd_len(cdb.field[0]), + &cdb, SCSI_MMC_DATA_READ, + sizeof(buf), buf); + if (0 != i_status) + return 0; + + { + int i; + + retval = 0; + for (i = 8; i < 12; i++) + { + retval <<= 8; + retval += buf[i]; + } + } + + return retval; +} + +/*! + * Eject using SCSI MMC commands. Return 0 if successful. + */ +int +eject_media_freebsd_cam (_img_private_t *p_env) +{ + int i_status; + scsi_mmc_cdb_t cdb = {{0, }}; + uint8_t buf[1]; + + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_ALLOW_MEDIUM_REMOVAL); + + i_status = run_scsi_cmd_freebsd_cam (p_env, DEFAULT_TIMEOUT_MSECS, + scsi_mmc_get_cmd_len(cdb.field[0]), + &cdb, SCSI_MMC_DATA_WRITE, 0, &buf); + if (0 != i_status) + return i_status; + + cdb.field[4] = 1; + i_status = run_scsi_cmd_freebsd_cam (p_env, DEFAULT_TIMEOUT_MSECS, + scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, + SCSI_MMC_DATA_WRITE, 0, &buf); + if (0 != i_status) + return i_status; + + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_START_STOP); + cdb.field[4] = 2; /* eject */ + + return run_scsi_cmd_freebsd_cam (p_env, DEFAULT_TIMEOUT_MSECS, + scsi_mmc_get_cmd_len(cdb.field[0]), + &cdb, + SCSI_MMC_DATA_WRITE, 0, &buf); +} + +#endif /* HAVE_FREEBSD_CDROM */ diff --git a/src/input/vcd/libcdio/FreeBSD/freebsd_ioctl.c b/src/input/vcd/libcdio/FreeBSD/freebsd_ioctl.c new file mode 100644 index 000000000..be9835c95 --- /dev/null +++ b/src/input/vcd/libcdio/FreeBSD/freebsd_ioctl.c @@ -0,0 +1,267 @@ +/* + $Id: freebsd_ioctl.c,v 1.1 2005/01/01 02:43:57 rockyb Exp $ + + Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* This file contains FreeBSD-specific code and implements low-level + control of the CD drive. Culled initially I think from xine's or + mplayer's FreeBSD code with lots of modifications. +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +static const char _rcsid[] = "$Id: freebsd_ioctl.c,v 1.1 2005/01/01 02:43:57 rockyb Exp $"; + +#ifdef HAVE_FREEBSD_CDROM + +#include "freebsd.h" + +/* Check a drive to see if it is a CD-ROM + Return 1 if a CD-ROM. 0 if it exists but isn't a CD-ROM drive + and -1 if no device exists . +*/ +bool +cdio_is_cdrom_freebsd_ioctl(char *drive, char *mnttype) +{ + bool is_cd=false; + int cdfd; + struct ioc_toc_header tochdr; + + /* If it doesn't exist, return -1 */ + if ( !cdio_is_device_quiet_generic(drive) ) { + return(false); + } + + /* If it does exist, verify that it's an available CD-ROM */ + cdfd = open(drive, (O_RDONLY|O_EXCL|O_NONBLOCK), 0); + + /* Should we want to test the condition in more detail: + ENOENT is the error for /dev/xxxxx does not exist; + ENODEV means there's no drive present. */ + + if ( cdfd >= 0 ) { + if ( ioctl(cdfd, CDIOREADTOCHEADER, &tochdr) != -1 ) { + is_cd = true; + } + close(cdfd); + } + /* Even if we can't read it, it might be mounted */ + else if ( mnttype && (strcmp(mnttype, "iso9660") == 0) ) { + is_cd = true; + } + return(is_cd); +} + +/*! + Reads a single mode2 sector from cd device into data starting from lsn. + Returns 0 if no error. + */ +int +read_audio_sectors_freebsd_ioctl (_img_private_t *_obj, void *data, lsn_t lsn, + unsigned int nblocks) +{ + unsigned char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; + struct ioc_read_audio cdda; + + cdda.address.lba = lsn; + cdda.buffer = buf; + cdda.nframes = nblocks; + cdda.address_format = CDIO_CDROM_LBA; + + /* read a frame */ + if(ioctl(_obj->gen.fd, CDIOCREADAUDIO, &cdda) < 0) { + perror("CDIOCREADAUDIO"); + return 1; + } + memcpy (data, buf, CDIO_CD_FRAMESIZE_RAW); + + return 0; +} + +/*! + Reads a single mode2 sector from cd device into data starting + from lsn. Returns 0 if no error. + */ +int +read_mode2_sector_freebsd_ioctl (_img_private_t *env, void *data, lsn_t lsn, + bool b_form2) +{ + char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; + int retval; + + if ( !b_form2 ) + return cdio_generic_read_form1_sector (env, buf, lsn); + + if ( (retval = read_audio_sectors_freebsd_ioctl (env, buf, lsn, 1)) ) + return retval; + + memcpy (data, buf + CDIO_CD_XA_SYNC_HEADER, M2RAW_SECTOR_SIZE); + + return 0; +} + +/*! + Return the size of the CD in logical block address (LBA) units. + */ +uint32_t +stat_size_freebsd_ioctl (_img_private_t *_obj) +{ + struct ioc_read_toc_single_entry tocent; + uint32_t size; + + tocent.track = CDIO_CDROM_LEADOUT_TRACK; + tocent.address_format = CDIO_CDROM_LBA; + if (ioctl (_obj->gen.fd, CDIOREADTOCENTRY, &tocent) == -1) + { + perror ("ioctl(CDROMREADTOCENTRY)"); + exit (EXIT_FAILURE); + } + + size = tocent.entry.addr.lba; + + return size; +} + +/*! + Eject media. Return 1 if successful, 0 otherwise. + */ +int +eject_media_freebsd_ioctl (_img_private_t *env) +{ + _img_private_t *_obj = env; + int ret=2; + int fd; + + if ((fd = open(_obj->gen.source_name, O_RDONLY|O_NONBLOCK)) > -1) { + ret = 1; + if (ioctl(fd, CDIOCALLOW) == -1) { + cdio_warn("ioctl(fd, CDIOCALLOW) failed: %s\n", strerror(errno)); + } else if (ioctl(fd, CDIOCEJECT) == -1) { + cdio_warn("ioctl(CDIOCEJECT) failed: %s\n", strerror(errno)); + } else { + ret = 0; + } + close(fd); + } + + return ret; +} + +/*! + Return the media catalog number MCN. + + Note: string is malloc'd so caller should free() then returned + string when done with it. + + FIXME: This is just a guess. + + */ +char * +get_mcn_freebsd_ioctl (const _img_private_t *env) { + + struct ioc_read_subchannel subchannel; + struct cd_sub_channel_info subchannel_info; + + subchannel.address_format = CDIO_CDROM_MSF; + subchannel.data_format = CDIO_SUBCHANNEL_MEDIA_CATALOG; + subchannel.track = 0; + subchannel.data_len = sizeof(subchannel_info); + subchannel.data = &subchannel_info; + + if(ioctl(env->gen.fd, CDIOCREADSUBCHANNEL, &subchannel) < 0) { + perror("CDIOCREADSUBCHANNEL"); + return NULL; + } + + /* Probably need a loop over tracks rather than give up if we + can't find in track 0. + */ + if (subchannel_info.what.media_catalog.mc_valid) + return strdup(subchannel_info.what.media_catalog.mc_number); + else + return NULL; +} + +/*! + Get format of track. + + FIXME: We're just guessing this from the GNU/Linux code. + +*/ +track_format_t +get_track_format_freebsd_ioctl(const _img_private_t *env, track_t i_track) +{ + struct ioc_read_subchannel subchannel; + struct cd_sub_channel_info subchannel_info; + + subchannel.address_format = CDIO_CDROM_LBA; + subchannel.data_format = CDIO_SUBCHANNEL_CURRENT_POSITION; + subchannel.track = i_track; + subchannel.data_len = 1; + subchannel.data = &subchannel_info; + + if(ioctl(env->gen.fd, CDIOCREADSUBCHANNEL, &subchannel) < 0) { + perror("CDIOCREADSUBCHANNEL"); + return 1; + } + + if (subchannel_info.what.position.control == 0x04) { + if (subchannel_info.what.position.data_format == 0x10) + return TRACK_FORMAT_CDI; + else if (subchannel_info.what.position.data_format == 0x20) + return TRACK_FORMAT_XA; + else + return TRACK_FORMAT_DATA; + } else + return TRACK_FORMAT_AUDIO; +} + +/*! + Return true if we have XA data (green, mode2 form1) or + XA data (green, mode2 form2). That is track begins: + sync - header - subheader + 12 4 - 8 + + FIXME: there's gotta be a better design for this and get_track_format? +*/ +bool +get_track_green_freebsd_ioctl(const _img_private_t *env, track_t i_track) +{ + struct ioc_read_subchannel subchannel; + struct cd_sub_channel_info subchannel_info; + + subchannel.address_format = CDIO_CDROM_LBA; + subchannel.data_format = CDIO_SUBCHANNEL_CURRENT_POSITION; + subchannel.track = i_track; + subchannel.data_len = 1; + subchannel.data = &subchannel_info; + + if(ioctl(env->gen.fd, CDIOCREADSUBCHANNEL, &subchannel) < 0) { + perror("CDIOCREADSUBCHANNEL"); + return 1; + } + + /* FIXME: Dunno if this is the right way, but it's what + I was using in cdinfo for a while. + */ + return (subchannel_info.what.position.control & 2) != 0; +} + +#endif /* HAVE_FREEBSD_CDROM */ diff --git a/src/input/vcd/libcdio/MSWindows/aspi32.c b/src/input/vcd/libcdio/MSWindows/aspi32.c index bb568fcc7..238a4b4e9 100644 --- a/src/input/vcd/libcdio/MSWindows/aspi32.c +++ b/src/input/vcd/libcdio/MSWindows/aspi32.c @@ -1,5 +1,5 @@ /* - $Id: aspi32.c,v 1.1 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: aspi32.c,v 1.2 2005/01/01 02:43:58 rockyb Exp $ Copyright (C) 2004 Rocky Bernstein <rocky@panix.com> @@ -23,17 +23,17 @@ Inspired by vlc's cdrom.h code */ -#ifdef HAVE_CONFIG_H +#ifdef HAVE_CONFIG_H # include "config.h" #endif -static const char _rcsid[] = "$Id: aspi32.c,v 1.1 2004/04/11 12:20:31 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: aspi32.c,v 1.2 2005/01/01 02:43:58 rockyb Exp $"; #include <cdio/cdio.h> #include <cdio/sector.h> #include <cdio/util.h> +#include <cdio/scsi_mmc.h> #include "cdio_assert.h" -#include "scsi_mmc.h" #include <string.h> @@ -52,10 +52,86 @@ static const char _rcsid[] = "$Id: aspi32.c,v 1.1 2004/04/11 12:20:31 miguelfrei #include <sys/stat.h> #include <sys/types.h> #include "aspi32.h" +#include "cdtext_private.h" + +/* Amount of time we are willing to wait for an operation to complete. + 10 seconds? +*/ +#define OP_TIMEOUT_MS 10000 + +static const +char *aspierror(int nErrorCode) +{ + switch (nErrorCode) + { + case SS_PENDING: + return "SRB being processed"; + break; + case SS_COMP: + return "SRB completed without error"; + break; + case SS_ABORTED: + return "SRB aborted"; + break; + case SS_ABORT_FAIL: + return "Unable to abort SRB"; + break; + case SS_ERR: + return "SRB completed with error"; + break; + case SS_INVALID_CMD: + return "Invalid ASPI command"; + break; + case SS_INVALID_HA: + return "Invalid host adapter number"; + break; + case SS_NO_DEVICE: + return "SCSI device not installed"; + break; + case SS_INVALID_SRB: + return "Invalid parameter set in SRB"; + break; + case SS_OLD_MANAGER: + return "ASPI manager doesn't support"; + break; + case SS_ILLEGAL_MODE: + return "Unsupported MS Windows mode"; + break; + case SS_NO_ASPI: + return "No ASPI managers"; + break; + case SS_FAILED_INIT: + return "ASPI for windows failed init"; + break; + case SS_ASPI_IS_BUSY: + return "No resources available to execute command."; + break; + case SS_BUFFER_TOO_BIG: + return "Buffer size is too big to handle."; + break; + case SS_MISMATCHED_COMPONENTS: + return "The DLLs/EXEs of ASPI don't version check"; + break; + case SS_NO_ADAPTERS: + return "No host adapters found"; + break; + case SS_INSUFFICIENT_RESOURCES: + return "Couldn't allocate resources needed to init"; + break; + case SS_ASPI_IS_SHUTDOWN: + return "Call came to ASPI after PROCESS_DETACH"; + break; + case SS_BAD_INSTALL: + return "The DLL or other components are installed wrong."; + break; + default: + return "Unknown ASPI error."; + } +} /* General ioctl() CD-ROM command function */ static bool -wnaspi32_mciSendCommand(int id, UINT msg, DWORD flags, void *arg) +mciSendCommand_aspi(int id, UINT msg, DWORD flags, void *arg) { MCIERROR mci_error; @@ -69,56 +145,164 @@ wnaspi32_mciSendCommand(int id, UINT msg, DWORD flags, void *arg) return(mci_error == 0); } +/* + See if the ASPI DLL is loadable. If so pointers are returned + and we return true. Return false if there was a problem. + */ +static bool +have_aspi( HMODULE *hASPI, + long (**lpGetSupport)( void ), + long (**lpSendCommand)( void* ) ) +{ + /* check if aspi is available */ + *hASPI = LoadLibrary( "wnaspi32.dll" ); + + if( *hASPI == NULL ) { + cdio_debug("Unable to load ASPI DLL"); + return false; + } + + (FARPROC) *lpGetSupport = GetProcAddress( *hASPI, + "GetASPI32SupportInfo" ); + (FARPROC) *lpSendCommand = GetProcAddress( *hASPI, + "SendASPI32Command" ); + + /* make sure that we've got both function addresses */ + if( *lpGetSupport == NULL || *lpSendCommand == NULL ) { + cdio_debug("Unable to get ASPI function pointers"); + FreeLibrary( *hASPI ); + return false; + } + + return true; +} + +/*! + Get disc type associated with cd object. +*/ +discmode_t +get_discmode_aspi (_img_private_t *p_env) +{ + track_t i_track; + discmode_t discmode=CDIO_DISC_MODE_NO_INFO; + + /* See if this is a DVD. */ + cdio_dvd_struct_t dvd; /* DVD READ STRUCT for layer 0. */ + + dvd.physical.type = CDIO_DVD_STRUCT_PHYSICAL; + dvd.physical.layer_num = 0; + if (0 == scsi_mmc_get_dvd_struct_physical_private (p_env, + &run_scsi_cmd_aspi, + &dvd)) { + switch(dvd.physical.layer[0].book_type) { + case CDIO_DVD_BOOK_DVD_ROM: return CDIO_DISC_MODE_DVD_ROM; + case CDIO_DVD_BOOK_DVD_RAM: return CDIO_DISC_MODE_DVD_RAM; + case CDIO_DVD_BOOK_DVD_R: return CDIO_DISC_MODE_DVD_R; + case CDIO_DVD_BOOK_DVD_RW: return CDIO_DISC_MODE_DVD_RW; + case CDIO_DVD_BOOK_DVD_PR: return CDIO_DISC_MODE_DVD_PR; + case CDIO_DVD_BOOK_DVD_PRW: return CDIO_DISC_MODE_DVD_PRW; + default: return CDIO_DISC_MODE_DVD_OTHER; + } + } + + if (!p_env->gen.toc_init) + read_toc_aspi (p_env); + + if (!p_env->gen.toc_init) + return CDIO_DISC_MODE_NO_INFO; + + for (i_track = p_env->gen.i_first_track; + i_track < p_env->gen.i_first_track + p_env->gen.i_tracks ; + i_track ++) { + track_format_t track_fmt=get_track_format_aspi(p_env, i_track); + + switch(track_fmt) { + case TRACK_FORMAT_AUDIO: + switch(discmode) { + case CDIO_DISC_MODE_NO_INFO: + discmode = CDIO_DISC_MODE_CD_DA; + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* No change*/ + break; + default: + discmode = CDIO_DISC_MODE_CD_MIXED; + } + break; + case TRACK_FORMAT_XA: + switch(discmode) { + case CDIO_DISC_MODE_NO_INFO: + discmode = CDIO_DISC_MODE_CD_XA; + break; + case CDIO_DISC_MODE_CD_XA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* No change*/ + break; + default: + discmode = CDIO_DISC_MODE_CD_MIXED; + } + break; + case TRACK_FORMAT_DATA: + switch(discmode) { + case CDIO_DISC_MODE_NO_INFO: + discmode = CDIO_DISC_MODE_CD_DATA; + break; + case CDIO_DISC_MODE_CD_DATA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* No change*/ + break; + default: + discmode = CDIO_DISC_MODE_CD_MIXED; + } + break; + case TRACK_FORMAT_ERROR: + default: + discmode = CDIO_DISC_MODE_ERROR; + } + } + return discmode; +} + const char * -wnaspi32_is_cdrom(const char drive_letter) +is_cdrom_aspi(const char drive_letter) { static char psz_win32_drive[7]; HMODULE hASPI = NULL; long (*lpGetSupport)( void ) = NULL; long (*lpSendCommand)( void* ) = NULL; DWORD dwSupportInfo; - int i_adapter, i_num_adapters; + int i_adapter, i_hostadapters; char c_drive; - - hASPI = LoadLibrary( "wnaspi32.dll" ); - if( hASPI != NULL ) { - (FARPROC) lpGetSupport = GetProcAddress( hASPI, - "GetASPI32SupportInfo" ); - (FARPROC) lpSendCommand = GetProcAddress( hASPI, - "SendASPI32Command" ); - } - - if( hASPI == NULL || lpGetSupport == NULL || lpSendCommand == NULL ) { - cdio_debug("Unable to load ASPI or get ASPI function pointers"); - if( hASPI ) FreeLibrary( hASPI ); + int i_rc; + + if ( !have_aspi(&hASPI, &lpGetSupport, &lpSendCommand) ) return NULL; - } - - /* ASPI support seems to be there */ + + /* ASPI support seems to be there. */ dwSupportInfo = lpGetSupport(); - - if( HIBYTE( LOWORD ( dwSupportInfo ) ) == SS_NO_ADAPTERS ) { - cdio_debug("no host adapters found (ASPI)"); - FreeLibrary( hASPI ); - return NULL; - } - - if( HIBYTE( LOWORD ( dwSupportInfo ) ) != SS_COMP ) { - cdio_debug("Unable to initalize ASPI layer"); + + i_rc = HIBYTE( LOWORD ( dwSupportInfo ) ); + + if( SS_COMP != i_rc ) { + cdio_debug("ASPI: %s", aspierror(i_rc)); FreeLibrary( hASPI ); return NULL; } - i_num_adapters = LOBYTE( LOWORD( dwSupportInfo ) ); - if( i_num_adapters == 0 ) { + i_hostadapters = LOBYTE( LOWORD( dwSupportInfo ) ); + if( i_hostadapters == 0 ) { FreeLibrary( hASPI ); return NULL; } c_drive = toupper(drive_letter) - 'A'; - for( i_adapter = 0; i_adapter < i_num_adapters; i_adapter++ ) { + for( i_adapter = 0; i_adapter < i_hostadapters; i_adapter++ ) { struct SRB_GetDiskInfo srbDiskInfo; int i_target; SRB_HAInquiry srbInquiry; @@ -147,13 +331,14 @@ wnaspi32_is_cdrom(const char drive_letter) if( (srbDiskInfo.SRB_Status == SS_COMP) && (srbDiskInfo.SRB_Int13HDriveInfo == c_drive) ) { - /* Make sure this is a cdrom device */ + /* Make sure this is a CD-ROM device. */ struct SRB_GDEVBlock srbGDEVBlock; memset( &srbGDEVBlock, 0, sizeof(struct SRB_GDEVBlock) ); srbGDEVBlock.SRB_Cmd = SC_GET_DEV_TYPE; srbDiskInfo.SRB_HaId = i_adapter; srbGDEVBlock.SRB_Target = i_target; + srbGDEVBlock.SRB_Lun = i_lun; lpSendCommand( (void*) &srbGDEVBlock ); @@ -175,100 +360,109 @@ wnaspi32_is_cdrom(const char drive_letter) Initialize CD device. */ bool -wnaspi32_init_win32 (_img_private_t *env) +init_aspi (_img_private_t *env) { HMODULE hASPI = NULL; long (*lpGetSupport)( void ) = NULL; long (*lpSendCommand)( void* ) = NULL; DWORD dwSupportInfo; - int i, j, i_num_adapters; - char c_drive = env->gen.source_name[0]; - - hASPI = LoadLibrary( "wnaspi32.dll" ); - if( hASPI != NULL ) { - (FARPROC) lpGetSupport = GetProcAddress( hASPI, - "GetASPI32SupportInfo" ); - (FARPROC) lpSendCommand = GetProcAddress( hASPI, - "SendASPI32Command" ); + int i_adapter, i_hostadapters; + char c_drive; + int i_rc; + + if (2 == strlen(env->gen.source_name) && isalpha(env->gen.source_name[0]) ) + { + c_drive = env->gen.source_name[0]; + } else if ( 6 == strlen(env->gen.source_name) + && isalpha(env->gen.source_name[4] )) { + c_drive = env->gen.source_name[4]; + } else { + c_drive = 'C'; } - if( hASPI == NULL || lpGetSupport == NULL || lpSendCommand == NULL ) { - cdio_debug("Unable to load ASPI or get ASPI function pointers"); - if( hASPI ) FreeLibrary( hASPI ); + if ( !have_aspi(&hASPI, &lpGetSupport, &lpSendCommand) ) return false; - } - - /* ASPI support seems to be there */ + + /* ASPI support seems to be there. */ dwSupportInfo = lpGetSupport(); - if( HIBYTE( LOWORD ( dwSupportInfo ) ) == SS_NO_ADAPTERS ) { - cdio_debug("no host adapters found (ASPI)"); - FreeLibrary( hASPI ); - return -1; - } - - if( HIBYTE( LOWORD ( dwSupportInfo ) ) != SS_COMP ) { - cdio_debug("unable to initalize ASPI layer"); + i_rc = HIBYTE( LOWORD ( dwSupportInfo ) ); + + if( SS_COMP != i_rc ) { + cdio_info("ASPI: %s", aspierror(i_rc)); FreeLibrary( hASPI ); - return -1; + return false; } - i_num_adapters = LOBYTE( LOWORD( dwSupportInfo ) ); - if( i_num_adapters == 0 ) { + i_hostadapters = LOBYTE( LOWORD( dwSupportInfo ) ); + if( i_hostadapters == 0 ) { FreeLibrary( hASPI ); - return -1; + return false; } c_drive = toupper(c_drive) - 'A'; - for( i = 0; i < i_num_adapters; i++ ) { - for( j = 0; j < 15; j++ ) { - struct SRB_GetDiskInfo srbDiskInfo; - int lun; - - for (lun = 0; lun < 8; lun++ ) { - srbDiskInfo.SRB_Cmd = SC_GET_DISK_INFO; - srbDiskInfo.SRB_HaId = i; - srbDiskInfo.SRB_Flags = 0; - srbDiskInfo.SRB_Hdr_Rsvd = 0; - srbDiskInfo.SRB_Target = j; - srbDiskInfo.SRB_Lun = lun; - - lpSendCommand( (void*) &srbDiskInfo ); - - if( (srbDiskInfo.SRB_Status == SS_COMP) ) { + for( i_adapter = 0; i_adapter < i_hostadapters; i_adapter++ ) { + struct SRB_GetDiskInfo srbDiskInfo; + int i_target; + SRB_HAInquiry srbInquiry; + + srbInquiry.SRB_Cmd = SC_HA_INQUIRY; + srbInquiry.SRB_HaId = i_adapter; + + lpSendCommand( (void*) &srbInquiry ); + + if( srbInquiry.SRB_Status != SS_COMP ) continue; + if( !srbInquiry.HA_Unique[3]) srbInquiry.HA_Unique[3]=8; + + for(i_target=0; i_target < srbInquiry.HA_Unique[3]; i_target++) + { + int i_lun; + for (i_lun = 0; i_lun < 8; i_lun++ ) { + srbDiskInfo.SRB_Cmd = SC_GET_DISK_INFO; + srbDiskInfo.SRB_Flags = 0; + srbDiskInfo.SRB_Hdr_Rsvd = 0; + srbDiskInfo.SRB_HaId = i_adapter; + srbDiskInfo.SRB_Target = i_target; + srbDiskInfo.SRB_Lun = i_lun; - if (srbDiskInfo.SRB_Int13HDriveInfo != c_drive) - { - continue; - } else { - /* Make sure this is a cdrom device */ - struct SRB_GDEVBlock srbGDEVBlock; - - memset( &srbGDEVBlock, 0, sizeof(struct SRB_GDEVBlock) ); - srbGDEVBlock.SRB_Cmd = SC_GET_DEV_TYPE; - srbGDEVBlock.SRB_HaId = i; - srbGDEVBlock.SRB_Target = j; - - lpSendCommand( (void*) &srbGDEVBlock ); - - if( ( srbGDEVBlock.SRB_Status == SS_COMP ) && - ( srbGDEVBlock.SRB_DeviceType == DTYPE_CDROM ) ) { - env->i_sid = MAKEWORD( i, j ); - env->hASPI = (long)hASPI; - env->lpSendCommand = lpSendCommand; - cdio_debug("Using ASPI layer"); - - return true; + lpSendCommand( (void*) &srbDiskInfo ); + + if( (srbDiskInfo.SRB_Status == SS_COMP) ) { + + if (srbDiskInfo.SRB_Int13HDriveInfo != c_drive) + { + continue; } else { - FreeLibrary( hASPI ); - cdio_debug( "%c: is not a CD-ROM drive", - env->gen.source_name[0] ); - return false; + /* Make sure this is a CD-ROM device. */ + struct SRB_GDEVBlock srbGDEVBlock; + + memset( &srbGDEVBlock, 0, sizeof(struct SRB_GDEVBlock) ); + srbGDEVBlock.SRB_Cmd = SC_GET_DEV_TYPE; + srbGDEVBlock.SRB_HaId = i_adapter; + srbGDEVBlock.SRB_Target = i_target; + + lpSendCommand( (void*) &srbGDEVBlock ); + + if( ( srbGDEVBlock.SRB_Status == SS_COMP ) && + ( srbGDEVBlock.SRB_DeviceType == DTYPE_CDROM ) ) { + env->i_sid = MAKEWORD( i_adapter, i_target ); + env->hASPI = (long)hASPI; + env->lpSendCommand = lpSendCommand; + env->b_aspi_init = true; + env->i_lun = i_lun; + cdio_debug("Using ASPI layer"); + + return true; + } else { + FreeLibrary( hASPI ); + cdio_debug( "%c: is not a CD-ROM drive", + env->gen.source_name[0] ); + return false; + } } - } - } + } } } } @@ -279,89 +473,138 @@ wnaspi32_init_win32 (_img_private_t *env) } /*! - Reads a single mode2 sector from cd device into data starting from lsn. - Returns 0 if no error. + Run a SCSI MMC command. + + env private CD structure + i_timeout_ms time in milliseconds we will wait for the command + to complete. If this value is -1, use the default + time-out value. + p_buf Buffer for data, both sending and receiving + i_buf Size of buffer + e_direction direction the transfer is to go. + cdb CDB bytes. All values that are needed should be set on + input. We'll figure out what the right CDB length should be. + + We return 0 if command completed successfully. */ -static int -wnaspi32_mmc_read_sectors (_img_private_t *env, void *data, lsn_t lsn, - int sector_type, unsigned int nblocks) +int +run_scsi_cmd_aspi( const void *p_user_data, unsigned int i_timeout_ms, + unsigned int i_cdb, const scsi_mmc_cdb_t * p_cdb, + scsi_mmc_direction_t e_direction, + unsigned int i_buf, /*in/out*/ void *p_buf ) { - unsigned char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; + const _img_private_t *p_env = p_user_data; HANDLE hEvent; struct SRB_ExecSCSICmd ssc; - -#if 1 - sector_type = 0; /*all types */ - int sync = 0; - int header_code = 2; - int i_user_data = 1; - int edc_ecc = 0; - int error_field = 0; -#endif - - + /* Create the transfer completion event */ hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); if( hEvent == NULL ) { + cdio_info("CreateEvent failed"); return 1; } - /* Data selection */ - memset( &ssc, 0, sizeof( ssc ) ); - + ssc.SRB_Cmd = SC_EXEC_SCSI_CMD; - ssc.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - ssc.SRB_HaId = LOBYTE( env->i_sid ); - ssc.SRB_Target = HIBYTE( env->i_sid ); + + ssc.SRB_Flags = SCSI_MMC_DATA_READ == e_direction ? + SRB_DIR_IN | SRB_EVENT_NOTIFY : SRB_DIR_OUT | SRB_EVENT_NOTIFY; + + ssc.SRB_HaId = LOBYTE( p_env->i_sid ); + ssc.SRB_Target = HIBYTE( p_env->i_sid ); + ssc.SRB_Lun = p_env->i_lun; ssc.SRB_SenseLen = SENSE_LEN; ssc.SRB_PostProc = (LPVOID) hEvent; - ssc.SRB_CDBLen = 12; - - /* Operation code */ - ssc.CDBByte[ 0 ] = CDIO_MMC_GPCMD_READ_CD; - - CDIO_MMC_SET_READ_TYPE(ssc.CDBByte, sector_type); - CDIO_MMC_SET_READ_LBA(ssc.CDBByte, lsn); - CDIO_MMC_SET_READ_LENGTH(ssc.CDBByte, nblocks); - -#if 1 - ssc.CDBByte[ 9 ] = (sync << 7) | - (header_code << 5) | - (i_user_data << 4) | - (edc_ecc << 3) | - (error_field << 1); - /* ssc.CDBByte[ 9 ] = READ_CD_USERDATA_MODE2; */ -#else - CDIO_MMC_SET_MAIN_CHANNEL_SELECTION_BITS(ssc.CDBByte, - CDIO_MMC_MCSB_ALL_HEADERS); -#endif + ssc.SRB_CDBLen = i_cdb; /* Result buffer */ - ssc.SRB_BufPointer = buf; - ssc.SRB_BufLen = CDIO_CD_FRAMESIZE_RAW; + ssc.SRB_BufPointer = p_buf; + ssc.SRB_BufLen = i_buf; + + memcpy( ssc.CDBByte, p_cdb, i_cdb ); - /* Initiate transfer */ ResetEvent( hEvent ); - env->lpSendCommand( (void*) &ssc ); + p_env->lpSendCommand( (void*) &ssc ); /* If the command has still not been processed, wait until it's * finished */ if( ssc.SRB_Status == SS_PENDING ) { - WaitForSingleObject( hEvent, INFINITE ); + WaitForSingleObject( hEvent, msecs2secs(i_timeout_ms) ); } CloseHandle( hEvent ); /* check that the transfer went as planned */ if( ssc.SRB_Status != SS_COMP ) { - return 1; + cdio_info("ASPI: %s", aspierror(ssc.SRB_Status)); + return 2; } + + return 0; +} + + +/*! + Reads nblocks sectors from cd device into data starting from lsn. + Returns 0 if no error. + */ +static int +read_sectors_aspi (const _img_private_t *env, void *data, lsn_t lsn, + int sector_type, unsigned int nblocks) +{ + scsi_mmc_cdb_t cdb = {{0, }}; + unsigned int i_buf; + + int sync = 0; + int header_code = 2; + int i_user_data = 1; + int edc_ecc = 0; + int error_field = 0; - /* FIXME! remove the 8 (SUBHEADER size) below... */ - memcpy (data, buf, CDIO_CD_FRAMESIZE_RAW); +#if 0 + sector_type = 0; /*all types */ +#endif - return 0; + /* Set up passthrough command */ + CDIO_MMC_SET_COMMAND (cdb.field, CDIO_MMC_GPCMD_READ_CD); + CDIO_MMC_SET_READ_TYPE (cdb.field, sector_type); + CDIO_MMC_SET_READ_LBA (cdb.field, lsn); + CDIO_MMC_SET_READ_LENGTH24(cdb.field, nblocks); + +#if 1 + cdb.field[ 9 ] = (sync << 7) | + (header_code << 5) | + (i_user_data << 4) | + (edc_ecc << 3) | + (error_field << 1); + /* ssc.CDBByte[ 9 ] = READ_CD_USERDATA_MODE2; */ +#else + CDIO_MMC_SET_MAIN_CHANNEL_SELECTION_BITS(cmd, + CDIO_MMC_MCSB_ALL_HEADERS); +#endif + + switch (sector_type) { + case CDIO_MMC_READ_TYPE_ANY: + case CDIO_MMC_READ_TYPE_CDDA: + i_buf = CDIO_CD_FRAMESIZE_RAW; + break; + case CDIO_MMC_READ_TYPE_M2F1: + i_buf = CDIO_CD_FRAMESIZE; + break; + case CDIO_MMC_READ_TYPE_M2F2: + i_buf = 2324; + break; + case CDIO_MMC_READ_TYPE_MODE1: + i_buf = CDIO_CD_FRAMESIZE; + break; + default: + i_buf = CDIO_CD_FRAMESIZE_RAW; + } + + return run_scsi_cmd_aspi(env, OP_TIMEOUT_MS, + scsi_mmc_get_cmd_len(cdb.field[0]), + &cdb, SCSI_MMC_DATA_READ, i_buf*nblocks, data); } /*! @@ -369,11 +612,27 @@ wnaspi32_mmc_read_sectors (_img_private_t *env, void *data, lsn_t lsn, Returns 0 if no error. */ int -wnaspi32_read_audio_sectors (_img_private_t *env, void *data, lsn_t lsn, +read_audio_sectors_aspi (_img_private_t *env, void *data, lsn_t lsn, unsigned int nblocks) { - return wnaspi32_mmc_read_sectors( env, data, lsn, CDIO_MMC_READ_TYPE_CDDA, - nblocks ); + if (read_sectors_aspi(env, data, lsn, CDIO_MMC_READ_TYPE_CDDA, 1)) { + return read_sectors_aspi(env, data, lsn, CDIO_MMC_READ_TYPE_ANY, 1); + } + return 0; +} + +/*! + Reads a single mode2 sector from cd device into data starting + from lsn. Returns 0 if no error. + */ +int +read_mode2_sector_aspi (const _img_private_t *env, void *data, lsn_t lsn, + bool b_form2) +{ + return read_sectors_aspi(env, data, lsn, b_form2 + ? CDIO_MMC_READ_TYPE_M2F2 + : CDIO_MMC_READ_TYPE_M2F1, + 1); } /*! @@ -381,10 +640,10 @@ wnaspi32_read_audio_sectors (_img_private_t *env, void *data, lsn_t lsn, from lsn. Returns 0 if no error. */ int -wnaspi32_read_mode2_sector (_img_private_t *env, void *data, lsn_t lsn) +read_mode1_sector_aspi (const _img_private_t *env, void *data, lsn_t lsn, + bool b_form2) { - return wnaspi32_mmc_read_sectors(env, data, lsn, CDIO_MMC_READ_TYPE_ANY, - 1); + return read_sectors_aspi(env, data, lsn, CDIO_MMC_READ_TYPE_MODE1, 1); } /*! @@ -392,113 +651,73 @@ wnaspi32_read_mode2_sector (_img_private_t *env, void *data, lsn_t lsn) Return true if successful or false if an error. */ bool -wnaspi32_read_toc (_img_private_t *env) +read_toc_aspi (_img_private_t *p_env) { - HANDLE hEvent; - struct SRB_ExecSCSICmd ssc; - unsigned char p_tocheader[ 4 ]; - - /* Create the transfer completion event */ - hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); - if( hEvent == NULL ) { - return false; - } - - memset( &ssc, 0, sizeof( ssc ) ); - - ssc.SRB_Cmd = SC_EXEC_SCSI_CMD; - ssc.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - ssc.SRB_HaId = LOBYTE( env->i_sid ); - ssc.SRB_Target = HIBYTE( env->i_sid ); - ssc.SRB_SenseLen = SENSE_LEN; - - ssc.SRB_PostProc = (LPVOID) hEvent; - ssc.SRB_CDBLen = 10; + scsi_mmc_cdb_t cdb = {{0, }}; + unsigned char tocheader[ 4 ]; + int i_status; /* Operation code */ - ssc.CDBByte[ 0 ] = READ_TOC; + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_TOC); /* Format */ - ssc.CDBByte[ 2 ] = READ_TOC_FORMAT_TOC; + cdb.field[ 2 ] = CDIO_MMC_READTOC_FMT_TOC; /* Starting track */ - ssc.CDBByte[ 6 ] = 0; - - /* Allocation length and buffer */ - ssc.SRB_BufLen = sizeof( p_tocheader ); - ssc.SRB_BufPointer = p_tocheader; - ssc.CDBByte[ 7 ] = ( ssc.SRB_BufLen >> 8 ) & 0xff; - ssc.CDBByte[ 8 ] = ( ssc.SRB_BufLen ) & 0xff; - - /* Initiate transfer */ - ResetEvent( hEvent ); - env->lpSendCommand( (void*) &ssc ); + CDIO_MMC_SET_START_TRACK(cdb.field, 0); - /* If the command has still not been processed, wait until it's - * finished */ - if( ssc.SRB_Status == SS_PENDING ) - WaitForSingleObject( hEvent, INFINITE ); + CDIO_MMC_SET_READ_LENGTH16(cdb.field, sizeof(tocheader)); + + i_status = run_scsi_cmd_aspi (p_env, OP_TIMEOUT_MS, + scsi_mmc_get_cmd_len(cdb.field[0]), + &cdb, SCSI_MMC_DATA_READ, + sizeof(tocheader), &tocheader); - /* check that the transfer went as planned */ - if( ssc.SRB_Status != SS_COMP ) { - CloseHandle( hEvent ); - return false; - } + if (0 != i_status) return false; - env->first_track_num = p_tocheader[2]; - env->total_tracks = p_tocheader[3] - p_tocheader[2] + 1; + p_env->gen.i_first_track = tocheader[2]; + p_env->gen.i_tracks = tocheader[3] - tocheader[2] + 1; { int i, i_toclength; unsigned char *p_fulltoc; - i_toclength = 4 /* header */ + p_tocheader[0] + - ((unsigned int)p_tocheader[1] << 8); + i_toclength = 4 /* header */ + tocheader[0] + + ((unsigned int) tocheader[1] << 8); p_fulltoc = malloc( i_toclength ); if( p_fulltoc == NULL ) { cdio_error( "out of memory" ); - CloseHandle( hEvent ); return false; } - /* Allocation length and buffer */ - ssc.SRB_BufLen = i_toclength; - ssc.SRB_BufPointer = p_fulltoc; - ssc.CDBByte[ 7 ] = ( ssc.SRB_BufLen >> 8 ) & 0xff; - ssc.CDBByte[ 8 ] = ( ssc.SRB_BufLen ) & 0xff; - - /* Initiate transfer */ - ResetEvent( hEvent ); - env->lpSendCommand( (void*) &ssc ); - - /* If the command has still not been processed, wait until it's - * finished */ - if( ssc.SRB_Status == SS_PENDING ) - WaitForSingleObject( hEvent, INFINITE ); - - /* check that the transfer went as planned */ - if( ssc.SRB_Status != SS_COMP ) - env->total_tracks = 0; + CDIO_MMC_SET_READ_LENGTH16(cdb.field, i_toclength); + + i_status = run_scsi_cmd_aspi (p_env, OP_TIMEOUT_MS, + scsi_mmc_get_cmd_len(cdb.field[0]), + &cdb, SCSI_MMC_DATA_READ, + i_toclength, p_fulltoc); + if( 0 != i_status ) { + p_env->gen.i_tracks = 0; + } - for( i = 0 ; i <= env->total_tracks ; i++ ) { + for( i = 0 ; i <= p_env->gen.i_tracks ; i++ ) { int i_index = 8 + 8 * i; - env->tocent[ i ].start_lsn = ((int)p_fulltoc[ i_index ] << 24) + + p_env->tocent[ i ].start_lsn = ((int)p_fulltoc[ i_index ] << 24) + ((int)p_fulltoc[ i_index+1 ] << 16) + ((int)p_fulltoc[ i_index+2 ] << 8) + (int)p_fulltoc[ i_index+3 ]; - env->tocent[ i ].Control = (UCHAR)p_fulltoc[ 1 + 8 * i ]; + p_env->tocent[ i ].Control = (UCHAR)p_fulltoc[ 1 + 8 * i ]; cdio_debug( "p_sectors: %i %lu", - i, (unsigned long int) env->tocent[i].start_lsn ); + i, (unsigned long int) p_env->tocent[i].start_lsn ); } free( p_fulltoc ); } - CloseHandle( hEvent ); - env->gen.toc_init = true; + p_env->gen.toc_init = true; return true; } @@ -529,13 +748,13 @@ wnaspi32_eject_media (void *user_data) { i_flags = MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID | MCI_OPEN_ELEMENT | MCI_OPEN_SHAREABLE; - if( wnaspi32_mciSendCommand( 0, MCI_OPEN, i_flags, &op ) ) { + if( mciSendCommand_aspi( 0, MCI_OPEN, i_flags, &op ) ) { st.dwItem = MCI_STATUS_READY; /* Eject disc */ - ret = wnaspi32_mciSendCommand( op.wDeviceID, MCI_SET, + ret = mciSendCommand_aspi( op.wDeviceID, MCI_SET, MCI_SET_DOOR_OPEN, 0 ) != 0; /* Release access to the device */ - wnaspi32_mciSendCommand( op.wDeviceID, MCI_CLOSE, MCI_WAIT, 0 ); + mciSendCommand_aspi( op.wDeviceID, MCI_CLOSE, MCI_WAIT, 0 ); } else ret = 0; @@ -547,7 +766,7 @@ wnaspi32_eject_media (void *user_data) { Get format of track. */ track_format_t -wnaspi32_get_track_format(_img_private_t *env, track_t track_num) +get_track_format_aspi(const _img_private_t *p_env, track_t track_num) { MCI_OPEN_PARMS op; MCI_STATUS_PARMS st; @@ -556,20 +775,20 @@ wnaspi32_get_track_format(_img_private_t *env, track_t track_num) memset( &op, 0, sizeof(MCI_OPEN_PARMS) ); op.lpstrDeviceType = (LPCSTR)MCI_DEVTYPE_CD_AUDIO; - op.lpstrElementName = env->gen.source_name; + op.lpstrElementName = p_env->gen.source_name; /* Set the flags for the device type */ i_flags = MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID | MCI_OPEN_ELEMENT | MCI_OPEN_SHAREABLE; - if( wnaspi32_mciSendCommand( 0, MCI_OPEN, i_flags, &op ) ) { + if( mciSendCommand_aspi( 0, MCI_OPEN, i_flags, &op ) ) { st.dwItem = MCI_CDA_STATUS_TYPE_TRACK; st.dwTrack = track_num; i_flags = MCI_TRACK | MCI_STATUS_ITEM ; - ret = wnaspi32_mciSendCommand( op.wDeviceID, MCI_STATUS, i_flags, &st ); + ret = mciSendCommand_aspi( op.wDeviceID, MCI_STATUS, i_flags, &st ); /* Release access to the device */ - wnaspi32_mciSendCommand( op.wDeviceID, MCI_CLOSE, MCI_WAIT, 0 ); + mciSendCommand_aspi( op.wDeviceID, MCI_CLOSE, MCI_WAIT, 0 ); switch(st.dwReturn) { case MCI_CDA_TRACK_AUDIO: @@ -584,5 +803,3 @@ wnaspi32_get_track_format(_img_private_t *env, track_t track_num) } #endif /* HAVE_WIN32_CDROM */ - - diff --git a/src/input/vcd/libcdio/MSWindows/aspi32.h b/src/input/vcd/libcdio/MSWindows/aspi32.h index 381d6c154..8742c0794 100644 --- a/src/input/vcd/libcdio/MSWindows/aspi32.h +++ b/src/input/vcd/libcdio/MSWindows/aspi32.h @@ -1,6 +1,6 @@ /* Win32 aspi specific */ /* - $Id: aspi32.h,v 1.1 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: aspi32.h,v 1.2 2005/01/01 02:43:58 rockyb Exp $ Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> @@ -28,8 +28,59 @@ #define SC_GET_DEV_TYPE 0x01 #define SC_EXEC_SCSI_CMD 0x02 #define SC_GET_DISK_INFO 0x06 -#define SS_COMP 0x01 -#define SS_PENDING 0x00 + +//***************************************************************************** +// %%% SRB Status %%% +//***************************************************************************** + +#define SS_PENDING 0x00 // SRB being processed +#define SS_COMP 0x01 // SRB completed without error +#define SS_ABORTED 0x02 // SRB aborted +#define SS_ABORT_FAIL 0x03 // Unable to abort SRB +#define SS_ERR 0x04 // SRB completed with error + +#define SS_INVALID_CMD 0x80 // Invalid ASPI command +#define SS_INVALID_HA 0x81 // Invalid host adapter number +#define SS_NO_DEVICE 0x82 // SCSI device not installed + +#define SS_INVALID_SRB 0xE0 // Invalid parameter set in SRB +#define SS_OLD_MANAGER 0xE1 // ASPI manager doesn't support Windows +#define SS_BUFFER_ALIGN 0xE1 // Buffer not aligned (replaces + // OLD_MANAGER in Win32) +#define SS_ILLEGAL_MODE 0xE2 // Unsupported Windows mode +#define SS_NO_ASPI 0xE3 // No ASPI managers resident +#define SS_FAILED_INIT 0xE4 // ASPI for windows failed init +#define SS_ASPI_IS_BUSY 0xE5 // No resources available to execute + // cmd +#define SS_BUFFER_TOO_BIG 0xE6 // Buffer size to big to handle! +#define SS_MISMATCHED_COMPONENTS 0xE7 // The DLLs/EXEs of ASPI don't version + // check +#define SS_NO_ADAPTERS 0xE8 // No host adapters to manage +#define SS_INSUFFICIENT_RESOURCES 0xE9 // Couldn't allocate resources needed + // to init +#define SS_ASPI_IS_SHUTDOWN 0xEA // Call came to ASPI after + // PROCESS_DETACH +#define SS_BAD_INSTALL 0xEB // The DLL or other components are installed wrong + +//***************************************************************************** +// %%% Host Adapter Status %%% +//***************************************************************************** + +#define HASTAT_OK 0x00 // Host adapter did not detect an + // error +#define HASTAT_SEL_TO 0x11 // Selection Timeout +#define HASTAT_DO_DU 0x12 // Data overrun data underrun +#define HASTAT_BUS_FREE 0x13 // Unexpected bus free +#define HASTAT_PHASE_ERR 0x14 // Target bus phase sequence + // failure +#define HASTAT_TIMEOUT 0x09 // Timed out while SRB was + // waiting to beprocessed. +#define HASTAT_COMMAND_TIMEOUT 0x0B // Adapter timed out processing SRB. +#define HASTAT_MESSAGE_REJECT 0x0D // While processing SRB, the + // adapter received a MESSAGE +#define HASTAT_BUS_RESET 0x0E // A bus reset was detected. +#define HASTAT_PARITY_ERROR 0x0F // A parity error was detected. +#define HASTAT_REQUEST_SENSE_FAILED 0x10 // The adapter failed in issuing #define SS_NO_ADAPTERS 0xE8 #define SRB_DIR_IN 0x08 #define SRB_DIR_OUT 0x10 @@ -114,33 +165,85 @@ typedef struct // Offset } SRB_HAInquiry; -const char * wnaspi32_is_cdrom(const char drive_letter); +/*! + Get disc type associated with cd object. +*/ +discmode_t get_discmode_aspi (_img_private_t *p_env); + +/*! + Return the the kind of drive capabilities of device. + + Note: string is malloc'd so caller should free() then returned + string when done with it. + + */ +char * get_mcn_aspi (const _img_private_t *env); + +/*! + Get the format (XA, DATA, AUDIO) of a track. +*/ +track_format_t get_track_format_aspi(const _img_private_t *env, + track_t i_track); /*! - Initialize CD device. + Initialize internal structures for CD device. */ -bool wnaspi32_init_win32 (_img_private_t *env); +bool init_aspi (_img_private_t *env); +/* + Read cdtext information for a CdIo object . + + return true on success, false on error or CD-TEXT information does + not exist. +*/ +bool init_cdtext_aspi (_img_private_t *env); + +const char *is_cdrom_aspi(const char drive_letter); + +/*! + Reads an audio device using the DeviceIoControl method into data + starting from lsn. Returns 0 if no error. + */ +int read_audio_sectors_aspi (_img_private_t *obj, void *data, lsn_t lsn, + unsigned int nblocks); /*! - Reads an audio device into data starting from lsn. - Returns 0 if no error. + Reads a single mode1 sector using the DeviceIoControl method into + data starting from lsn. Returns 0 if no error. */ -int wnaspi32_read_audio_sectors (_img_private_t *env, void *data, lsn_t lsn, - unsigned int nblocks); +int read_mode1_sector_aspi (const _img_private_t *env, void *data, + lsn_t lsn, bool b_form2); /*! Reads a single mode2 sector from cd device into data starting from lsn. Returns 0 if no error. */ -int wnaspi32_read_mode2_sector (_img_private_t *env, void *data, lsn_t lsn); +int read_mode2_sector_aspi (const _img_private_t *env, void *data, lsn_t lsn, + bool b_form2); /*! Read and cache the CD's Track Table of Contents and track info. Return true if successful or false if an error. */ -bool wnaspi32_read_toc (_img_private_t *env); +bool read_toc_aspi (_img_private_t *env); + +/*! + Run a SCSI MMC command. + + env private CD structure + i_timeout time in milliseconds we will wait for the command + to complete. If this value is -1, use the default + time-out value. + p_buf Buffer for data, both sending and receiving + i_buf Size of buffer + e_direction direction the transfer is to go. + cdb CDB bytes. All values that are needed should be set on + input. We'll figure out what the right CDB length should be. + + Return 0 if command completed successfully. + */ +int run_scsi_cmd_aspi( const void *p_user_data, + unsigned int i_timeout, + unsigned int i_cdb, + const scsi_mmc_cdb_t * p_cdb, + scsi_mmc_direction_t e_direction, + unsigned int i_buf, /*in/out*/ void *p_buf ); -/*! - Get format of track. -*/ -track_format_t wnaspi32_get_track_format(_img_private_t *env, - track_t track_num); diff --git a/src/input/vcd/libcdio/MSWindows/ioctl.c b/src/input/vcd/libcdio/MSWindows/ioctl.c deleted file mode 100644 index 1d2f99420..000000000 --- a/src/input/vcd/libcdio/MSWindows/ioctl.c +++ /dev/null @@ -1,472 +0,0 @@ -/*
- $Id: ioctl.c,v 1.1 2004/04/11 12:20:31 miguelfreitas Exp $
-
- Copyright (C) 2004 Rocky Bernstein <rocky@panix.com>
-
- 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
-
-/* This file contains Win32-specific code using the DeviceIoControl
- access method.
-*/
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-static const char _rcsid[] = "$Id: ioctl.c,v 1.1 2004/04/11 12:20:31 miguelfreitas Exp $";
-
-#include <cdio/cdio.h>
-#include <cdio/sector.h>
-#include "cdio_assert.h"
-
-#ifdef HAVE_WIN32_CDROM
-
-#include <windows.h>
-#include <winioctl.h>
-
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "scsi_mmc.h"
-
-/* Win32 DeviceIoControl specifics */
-/***** FIXME: #include ntddcdrm.h from Wine, but probably need to
- modify it a little.
-*/
-
-#define SCSI_IOCTL_DATA_OUT 0 //Give data to SCSI device (e.g. for writing)
-#define SCSI_IOCTL_DATA_IN 1 //Get data from SCSI device (e.g. for reading)
-#define SCSI_IOCTL_DATA_UNSPECIFIED 2 //No data (e.g. for ejecting)
-
-#define IOCTL_SCSI_PASS_THROUGH 0x4D004
-typedef struct ScsiPassThrough {
- unsigned short Length;
- unsigned char ScsiStatus;
- unsigned char PathId;
- unsigned char TargetId;
- unsigned char Lun;
- unsigned char CdbLength;
- unsigned char SenseInfoLength;
- unsigned char DataIn;
- unsigned int DataTransferLength;
- unsigned int TimeOutValue;
- unsigned int DataBufferOffset;
- unsigned int SenseInfoOffset;
- unsigned char Cdb[16];
-} SCSI_PASS_THROUGH;
-
-#define IOCTL_SCSI_PASS_THROUGH_DIRECT 0x4D014
-typedef struct _SCSI_PASS_THROUGH_DIRECT {
- USHORT Length;
- UCHAR ScsiStatus;
- UCHAR PathId;
- UCHAR TargetId;
- UCHAR Lun;
- UCHAR CdbLength;
- UCHAR SenseInfoLength;
- UCHAR DataIn;
- ULONG DataTransferLength;
- ULONG TimeOutValue;
- PVOID DataBuffer;
- ULONG SenseInfoOffset;
- UCHAR Cdb[16];
-} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT;
-
-#ifndef IOCTL_CDROM_BASE
-# define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM
-#endif
-#ifndef IOCTL_CDROM_RAW_READ
-#define IOCTL_CDROM_RAW_READ CTL_CODE(IOCTL_CDROM_BASE, 0x000F, \
- METHOD_OUT_DIRECT, FILE_READ_ACCESS)
-#endif
-
-#ifndef IOCTL_CDROM_BASE
-# define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM
-#endif
-#ifndef IOCTL_CDROM_READ_TOC
-#define IOCTL_CDROM_READ_TOC \
- CTL_CODE(IOCTL_CDROM_BASE, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS)
-#endif
-#ifndef IOCTL_CDROM_RAW_READ
-#define IOCTL_CDROM_RAW_READ \
- CTL_CODE(IOCTL_CDROM_BASE, 0x000F, METHOD_OUT_DIRECT, FILE_READ_ACCESS)
-#endif
-
-#ifndef IOCTL_CDROM_READ_Q_CHANNEL
-#define IOCTL_CDROM_READ_Q_CHANNEL \
- CTL_CODE(IOCTL_CDROM_BASE, 0x000B, METHOD_BUFFERED, FILE_READ_ACCESS)
-#endif
-
-typedef struct _TRACK_DATA {
- UCHAR Format;
- UCHAR Control : 4;
- UCHAR Adr : 4;
- UCHAR TrackNumber;
- UCHAR Reserved1;
- UCHAR Address[4];
-} TRACK_DATA, *PTRACK_DATA;
-
-typedef struct _CDROM_TOC {
- UCHAR Length[2];
- UCHAR FirstTrack;
- UCHAR LastTrack;
- TRACK_DATA TrackData[CDIO_CD_MAX_TRACKS+1];
-} CDROM_TOC, *PCDROM_TOC;
-
-#define IOCTL_CDROM_SUB_Q_CHANNEL 0x00
-#define IOCTL_CDROM_CURRENT_POSITION 0x01
-#define IOCTL_CDROM_MEDIA_CATALOG 0x02
-#define IOCTL_CDROM_TRACK_ISRC 0x03
-
-typedef enum _TRACK_MODE_TYPE {
- YellowMode2,
- XAForm2,
- CDDA
-} TRACK_MODE_TYPE, *PTRACK_MODE_TYPE;
-
-typedef struct __RAW_READ_INFO {
- LARGE_INTEGER DiskOffset;
- ULONG SectorCount;
- TRACK_MODE_TYPE TrackMode;
-} RAW_READ_INFO, *PRAW_READ_INFO;
-
-typedef struct _CDROM_SUB_Q_DATA_FORMAT {
- UCHAR Format;
- UCHAR Track;
-} CDROM_SUB_Q_DATA_FORMAT, *PCDROM_SUB_Q_DATA_FORMAT;
-
-typedef struct _SUB_Q_HEADER {
- UCHAR Reserved;
- UCHAR AudioStatus;
- UCHAR DataLength[2];
-} SUB_Q_HEADER, *PSUB_Q_HEADER;
-
-typedef struct _SUB_Q_MEDIA_CATALOG_NUMBER {
- SUB_Q_HEADER Header;
- UCHAR FormatCode;
- UCHAR Reserved[3];
- UCHAR Reserved1 : 7;
- UCHAR Mcval :1;
- UCHAR MediaCatalog[15];
-} SUB_Q_MEDIA_CATALOG_NUMBER, *PSUB_Q_MEDIA_CATALOG_NUMBER;
-
-#include "win32.h"
-
-/*
- Returns a string that can be used in a CreateFile call if
- c_drive letter is a character. If not NULL is returned.
- */
-
-const char *
-win32ioctl_is_cdrom(const char c_drive_letter)
-{
-
- UINT uDriveType;
- char sz_win32_drive[4];
-
- sz_win32_drive[0]= c_drive_letter;
- sz_win32_drive[1]=':';
- sz_win32_drive[2]='\\';
- sz_win32_drive[3]='\0';
-
- uDriveType = GetDriveType(sz_win32_drive);
-
- switch(uDriveType) {
- case DRIVE_CDROM: {
- char sz_win32_drive_full[] = "\\\\.\\X:";
- sz_win32_drive_full[4] = c_drive_letter;
- return strdup(sz_win32_drive_full);
- }
- default:
- cdio_debug("Drive %c is not a CD-ROM", c_drive_letter);
- return NULL;
- }
-}
-
-/*!
- Reads an audio device using the DeviceIoControl method into data
- starting from lsn. Returns 0 if no error.
- */
-int
-win32ioctl_read_audio_sectors (_img_private_t *env, void *data, lsn_t lsn,
- unsigned int nblocks)
-{
- DWORD dwBytesReturned;
- RAW_READ_INFO cdrom_raw;
-
- /* Initialize CDROM_RAW_READ structure */
- cdrom_raw.DiskOffset.QuadPart = CDIO_CD_FRAMESIZE_RAW * lsn;
- cdrom_raw.SectorCount = nblocks;
- cdrom_raw.TrackMode = CDDA;
-
- if( DeviceIoControl( env->h_device_handle,
- IOCTL_CDROM_RAW_READ, &cdrom_raw,
- sizeof(RAW_READ_INFO), data,
- CDIO_CD_FRAMESIZE_RAW * nblocks,
- &dwBytesReturned, NULL ) == 0 ) {
- cdio_info("Error reading audio-mode %lu (%ld)\n",
- (long unsigned int) lsn, GetLastError());
- return 1;
- }
- return 0;
-}
-
-/*!
- Reads a single raw sector using the DeviceIoControl method into
- data starting from lsn. Returns 0 if no error.
- */
-static int
-win32ioctl_read_raw_sector (_img_private_t *env, void *buf, lsn_t lsn)
-{
- SCSI_PASS_THROUGH_DIRECT sptd;
- BOOL success;
- DWORD dwBytesReturned;
-
- sptd.Length=sizeof(sptd);
- sptd.PathId=0; /* SCSI card ID will be filled in automatically */
- sptd.TargetId=0; /* SCSI target ID will also be filled in */
- sptd.Lun=0; /* SCSI lun ID will also be filled in */
- sptd.CdbLength=12; /* CDB size is 12 for ReadCD MMC1 command */
- sptd.SenseInfoLength=0; /* Don't return any sense data */
- sptd.DataIn=SCSI_IOCTL_DATA_IN; //There will be data from drive
- sptd.DataTransferLength=CDIO_CD_FRAMESIZE_RAW;
- sptd.TimeOutValue=60; /*SCSI timeout value (60 seconds -
- maybe it should be longer) */
- sptd.DataBuffer= (PVOID) buf;
- sptd.SenseInfoOffset=0;
-
- /* ReadCD CDB12 command. The values were taken from MMC1 draft paper. */
- sptd.Cdb[0]=CDIO_MMC_GPCMD_READ_CD;
- sptd.Cdb[1]=0;
-
- CDIO_MMC_SET_READ_LBA(sptd.Cdb, lsn);
-
- CDIO_MMC_SET_READ_LENGTH(sptd.Cdb, 1);
-
- sptd.Cdb[9]=0xF8; /* Raw read, 2352 bytes per sector */
- sptd.Cdb[10]=0;
- sptd.Cdb[11]=0;
- sptd.Cdb[12]=0;
- sptd.Cdb[13]=0;
- sptd.Cdb[14]=0;
- sptd.Cdb[15]=0;
-
- /* Send the command to drive */
- success=DeviceIoControl(env->h_device_handle,
- IOCTL_SCSI_PASS_THROUGH_DIRECT,
- (PVOID)&sptd,
- (DWORD)sizeof(SCSI_PASS_THROUGH_DIRECT),
- NULL, 0,
- &dwBytesReturned,
- NULL);
-
- if(! success) {
- cdio_info("Error reading %lu (%ld)\n", (long unsigned) lsn,
- GetLastError());
- return 1;
- }
-
- return 0;
-}
-
-/*!
- Reads a single mode2 sector using the DeviceIoControl method into
- data starting from lsn. Returns 0 if no error.
- */
-int
-win32ioctl_read_mode2_sector (_img_private_t *env, void *data, lsn_t lsn,
- bool mode2_form2)
-{
- char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, };
- int ret = win32ioctl_read_raw_sector (env, buf, lsn);
-
- if ( 0 != ret) return ret;
-
- memcpy (data,
- buf + CDIO_CD_SYNC_SIZE + CDIO_CD_XA_HEADER,
- mode2_form2 ? M2RAW_SECTOR_SIZE: CDIO_CD_FRAMESIZE);
-
- return 0;
-
-}
-
-/*!
- Reads a single mode2 sector using the DeviceIoControl method into
- data starting from lsn. Returns 0 if no error.
- */
-int
-win32ioctl_read_mode1_sector (_img_private_t *env, void *data, lsn_t lsn,
- bool mode2_form2)
-{
- char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, };
- int ret = win32ioctl_read_raw_sector (env, buf, lsn);
-
- if ( 0 != ret) return ret;
-
- memcpy (data,
- buf + CDIO_CD_SYNC_SIZE+CDIO_CD_HEADER_SIZE,
- mode2_form2 ? M2RAW_SECTOR_SIZE: CDIO_CD_FRAMESIZE);
-
- return 0;
-
-}
-
-/*!
- Initialize internal structures for CD device.
- */
-bool
-win32ioctl_init_win32 (_img_private_t *env)
-{
- char psz_win32_drive[7];
- unsigned int len=strlen(env->gen.source_name);
- OSVERSIONINFO ov;
- DWORD dw_access_flags;
-
- cdio_debug("using winNT/2K/XP ioctl layer");
-
- memset(&ov,0,sizeof(OSVERSIONINFO));
- ov.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
- GetVersionEx(&ov);
-
- if((ov.dwPlatformId==VER_PLATFORM_WIN32_NT) &&
- (ov.dwMajorVersion>4))
- dw_access_flags = GENERIC_READ|GENERIC_WRITE; /* add gen write on W2k/XP */
- else dw_access_flags = GENERIC_READ;
-
- if (cdio_is_device_win32(env->gen.source_name)) {
- sprintf( psz_win32_drive, "\\\\.\\%c:", env->gen.source_name[len-2] );
-
- env->h_device_handle = CreateFile( psz_win32_drive,
- dw_access_flags,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- NULL );
- if( env->h_device_handle == INVALID_HANDLE_VALUE )
- {
- /* No good. try toggle write. */
- dw_access_flags ^= GENERIC_WRITE;
- env->h_device_handle = CreateFile( psz_win32_drive,
- dw_access_flags,
- FILE_SHARE_READ,
- NULL,
- OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL,
- NULL );
- return (env->h_device_handle == NULL) ? false : true;
- }
- return true;
- }
- return false;
-}
-
-#define MSF_TO_LBA2(min, sec, frame) \
- ((int) frame + CDIO_CD_FRAMES_PER_SEC * (CDIO_CD_SECS_PER_MIN*min + sec) \
- - CDIO_PREGAP_SECTORS )
-
-/*!
- Read and cache the CD's Track Table of Contents and track info.
- Return true if successful or false if an error.
-*/
-bool
-win32ioctl_read_toc (_img_private_t *env)
-{
-
- DWORD dwBytesReturned;
- CDROM_TOC cdrom_toc;
- int i;
-
- if( DeviceIoControl( env->h_device_handle,
- IOCTL_CDROM_READ_TOC,
- NULL, 0, &cdrom_toc, sizeof(CDROM_TOC),
- &dwBytesReturned, NULL ) == 0 ) {
- cdio_warn( "could not read TOCHDR: %ld" , (long int) GetLastError());
- return false;
- }
-
- env->first_track_num = cdrom_toc.FirstTrack;
- env->total_tracks = cdrom_toc.LastTrack - cdrom_toc.FirstTrack + 1;
-
-
- for( i = 0 ; i <= env->total_tracks ; i++ ) {
- env->tocent[ i ].start_lsn = MSF_TO_LBA2(
- cdrom_toc.TrackData[i].Address[1],
- cdrom_toc.TrackData[i].Address[2],
- cdrom_toc.TrackData[i].Address[3] );
- env->tocent[ i ].Control = cdrom_toc.TrackData[i].Control;
- env->tocent[ i ].Format = cdrom_toc.TrackData[i].Format;
- cdio_debug("p_sectors: %i, %lu", i,
- (unsigned long int) (env->tocent[i].start_lsn));
- }
- env->gen.toc_init = true;
- return true;
-}
-
-/*!
- Return the media catalog number MCN.
-
- Note: string is malloc'd so caller should free() then returned
- string when done with it.
-
- */
-char *
-win32ioctl_get_mcn (_img_private_t *env) {
-
- DWORD dwBytesReturned;
- SUB_Q_MEDIA_CATALOG_NUMBER mcn;
- CDROM_SUB_Q_DATA_FORMAT q_data_format;
-
- memset( &mcn, 0, sizeof(mcn) );
-
- q_data_format.Format = IOCTL_CDROM_MEDIA_CATALOG;
-
- q_data_format.Track=1;
-
- if( DeviceIoControl( env->h_device_handle,
- IOCTL_CDROM_READ_Q_CHANNEL,
- &q_data_format, sizeof(q_data_format),
- &mcn, sizeof(mcn),
- &dwBytesReturned, NULL ) == 0 ) {
- cdio_warn( "could not read Q Channel at track %d", 1);
- } else if (mcn.Mcval)
- return strdup(mcn.MediaCatalog);
- return NULL;
-}
-
-/*!
- Get the format (XA, DATA, AUDIO) of a track.
-*/
-track_format_t
-win32ioctl_get_track_format(_img_private_t *env, track_t track_num)
-{
- /* This is pretty much copied from the "badly broken" cdrom_count_tracks
- in linux/cdrom.c.
- */
- if (env->tocent[track_num-1].Control & 0x04) {
- if (env->tocent[track_num-1].Format == 0x10)
- return TRACK_FORMAT_CDI;
- else if (env->tocent[track_num-1].Format == 0x20)
- return TRACK_FORMAT_XA;
- else
- return TRACK_FORMAT_DATA;
- } else
- return TRACK_FORMAT_AUDIO;
-}
-
-
-#endif /*HAVE_WIN32_CDROM*/
diff --git a/src/input/vcd/libcdio/MSWindows/win32.c b/src/input/vcd/libcdio/MSWindows/win32.c index 13ccb9131..9635161fb 100644 --- a/src/input/vcd/libcdio/MSWindows/win32.c +++ b/src/input/vcd/libcdio/MSWindows/win32.c @@ -1,5 +1,5 @@ /* - $Id: win32.c,v 1.1 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: win32.c,v 1.2 2005/01/01 02:43:58 rockyb Exp $ Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> @@ -26,14 +26,14 @@ # include "config.h" #endif -static const char _rcsid[] = "$Id: win32.c,v 1.1 2004/04/11 12:20:31 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: win32.c,v 1.2 2005/01/01 02:43:58 rockyb Exp $"; #include <cdio/cdio.h> #include <cdio/sector.h> #include <cdio/util.h> +#include <cdio/scsi_mmc.h> #include "cdio_assert.h" #include "cdio_private.h" /* protoype for cdio_is_device_win32 */ -#include "scsi_mmc.h" #include <string.h> @@ -41,25 +41,56 @@ static const char _rcsid[] = "$Id: win32.c,v 1.1 2004/04/11 12:20:31 miguelfreit #include <ctype.h> #include <stdio.h> + +#ifdef HAVE_STDLIB_H #include <stdlib.h> +#endif + +#ifdef HAVE_ERRNO_H #include <errno.h> +#endif + +#ifdef HAVE_UNISTD_H #include <unistd.h> +#endif + +#ifdef HAVE_FCNTL_H #include <fcntl.h> +#endif #include <windows.h> #include <winioctl.h> #include "win32.h" +#ifdef HAVE_SYS_STAT_H #include <sys/stat.h> +#endif + +#ifdef HAVE_SYS_TYPES_H #include <sys/types.h> +#endif + +#if defined (MSVC) || defined (_XBOX) +#undef IN +#else #include "aspi32.h" +#endif +#ifdef _XBOX +#include "stdint.h" +#include <xtl.h> +#define WIN_NT 1 +#else #define WIN_NT ( GetVersion() < 0x80000000 ) +#endif /* General ioctl() CD-ROM command function */ static bool _cdio_mciSendCommand(int id, UINT msg, DWORD flags, void *arg) { +#ifdef _XBOX + return false; +#else MCIERROR mci_error; mci_error = mciSendCommand(id, msg, flags, (DWORD)arg); @@ -70,14 +101,84 @@ _cdio_mciSendCommand(int id, UINT msg, DWORD flags, void *arg) cdio_warn("mciSendCommand() error: %s", error); } return(mci_error == 0); +#endif +} + +static access_mode_t +str_to_access_mode_win32(const char *psz_access_mode) +{ + const access_mode_t default_access_mode = + WIN_NT ? _AM_IOCTL : _AM_ASPI; + + if (NULL==psz_access_mode) return default_access_mode; + + if (!strcmp(psz_access_mode, "ioctl")) + return _AM_IOCTL; + else if (!strcmp(psz_access_mode, "ASPI")) { +#ifdef _XBOX + return _AM_ASPI; +#else + cdio_warn ("XBOX doesn't support access type: %s. Default used instead.", + psz_access_mode); + return default_access_mode; +#endif + } else { + cdio_warn ("unknown access type: %s. Default used instead.", + psz_access_mode); + return default_access_mode; + } +} + +static discmode_t +get_discmode_win32(void *p_user_data) +{ + _img_private_t *p_env = p_user_data; + + if (p_env->hASPI) { + return get_discmode_aspi (p_env); + } else { + return get_discmode_win32ioctl (p_env); + } } static const char * -cdio_is_cdrom(const char drive_letter) { +is_cdrom_win32(const char drive_letter) { if ( WIN_NT ) { - return win32ioctl_is_cdrom(drive_letter); + return is_cdrom_win32ioctl (drive_letter); + } else { + return is_cdrom_aspi(drive_letter); + } +} + +/*! + Run a SCSI MMC command. + + env private CD structure + i_timeout_ms time in milliseconds we will wait for the command + to complete. If this value is -1, use the default + time-out value. + p_buf Buffer for data, both sending and receiving + i_buf Size of buffer + e_direction direction the transfer is to go. + cdb CDB bytes. All values that are needed should be set on + input. We'll figure out what the right CDB length should be. + + Return 0 if command completed successfully. + */ +static int +run_scsi_cmd_win32( const void *p_user_data, unsigned int i_timeout_ms, + unsigned int i_cdb, const scsi_mmc_cdb_t *p_cdb, + scsi_mmc_direction_t e_direction, + unsigned int i_buf, /*in/out*/ void *p_buf ) +{ + const _img_private_t *p_env = p_user_data; + + if (p_env->hASPI) { + return run_scsi_cmd_aspi( p_env, i_timeout_ms, i_cdb, p_cdb, + e_direction, i_buf, p_buf ); } else { - return wnaspi32_is_cdrom(drive_letter); + return run_scsi_cmd_win32ioctl( p_env, i_timeout_ms, i_cdb, p_cdb, + e_direction, i_buf, p_buf ); } } @@ -87,26 +188,29 @@ cdio_is_cdrom(const char drive_letter) { static bool _cdio_init_win32 (void *user_data) { - _img_private_t *env = user_data; - if (env->gen.init) { + _img_private_t *p_env = user_data; + if (p_env->gen.init) { cdio_error ("init called more than once"); return false; } - env->gen.init = true; - env->toc_init = false; - + p_env->gen.init = true; + p_env->gen.toc_init = false; + p_env->gen.b_cdtext_init = false; + p_env->gen.b_cdtext_error = false; /* Initializations */ - env->h_device_handle = NULL; - env->i_sid = 0; - env->hASPI = 0; - env->lpSendCommand = 0; - - if ( WIN_NT ) { - return win32ioctl_init_win32(env); + p_env->h_device_handle = NULL; + p_env->i_sid = 0; + p_env->hASPI = 0; + p_env->lpSendCommand = 0; + p_env->b_aspi_init = false; + p_env->b_ioctl_init = false; + + if ( _AM_IOCTL == p_env->access_mode ) { + return init_win32ioctl(p_env); } else { - return wnaspi32_init_win32(env); + return init_aspi(p_env); } } @@ -114,19 +218,19 @@ _cdio_init_win32 (void *user_data) Release and free resources associated with cd. */ static void -_cdio_win32_free (void *user_data) +_free_win32 (void *user_data) { - _img_private_t *env = user_data; + _img_private_t *p_env = user_data; - if (NULL == env) return; - free (env->gen.source_name); + if (NULL == p_env) return; + free (p_env->gen.source_name); - if( env->h_device_handle ) - CloseHandle( env->h_device_handle ); - if( env->hASPI ) - FreeLibrary( (HMODULE)env->hASPI ); + if( p_env->h_device_handle ) + CloseHandle( p_env->h_device_handle ); + if( p_env->hASPI ) + FreeLibrary( (HMODULE)p_env->hASPI ); - free (env); + free (p_env); } /*! @@ -137,11 +241,11 @@ static int _cdio_read_audio_sectors (void *user_data, void *data, lsn_t lsn, unsigned int nblocks) { - _img_private_t *env = user_data; - if ( env->hASPI ) { - return wnaspi32_read_audio_sectors( env, data, lsn, nblocks ); + _img_private_t *p_env = user_data; + if ( p_env->hASPI ) { + return read_audio_sectors_aspi( p_env, data, lsn, nblocks ); } else { - return win32ioctl_read_audio_sectors( env, data, lsn, nblocks ); + return read_audio_sectors_win32ioctl( p_env, data, lsn, nblocks ); } } @@ -153,26 +257,26 @@ static int _cdio_read_mode1_sector (void *user_data, void *data, lsn_t lsn, bool b_form2) { - _img_private_t *env = user_data; + _img_private_t *p_env = user_data; - if (env->gen.ioctls_debugged == 75) + if (p_env->gen.ioctls_debugged == 75) cdio_debug ("only displaying every 75th ioctl from now on"); - if (env->gen.ioctls_debugged == 30 * 75) + if (p_env->gen.ioctls_debugged == 30 * 75) cdio_debug ("only displaying every 30*75th ioctl from now on"); - if (env->gen.ioctls_debugged < 75 - || (env->gen.ioctls_debugged < (30 * 75) - && env->gen.ioctls_debugged % 75 == 0) - || env->gen.ioctls_debugged % (30 * 75) == 0) + if (p_env->gen.ioctls_debugged < 75 + || (p_env->gen.ioctls_debugged < (30 * 75) + && p_env->gen.ioctls_debugged % 75 == 0) + || p_env->gen.ioctls_debugged % (30 * 75) == 0) cdio_debug ("reading %lu", (unsigned long int) lsn); - env->gen.ioctls_debugged++; + p_env->gen.ioctls_debugged++; - if ( env->hASPI ) { - return 1; + if ( p_env->hASPI ) { + return read_mode1_sector_aspi( p_env, data, lsn, b_form2 ); } else { - return win32ioctl_read_mode1_sector( env, data, lsn, b_form2 ); + return read_mode1_sector_win32ioctl( p_env, data, lsn, b_form2 ); } } @@ -185,19 +289,19 @@ static int _cdio_read_mode1_sectors (void *user_data, void *data, lsn_t lsn, bool b_form2, unsigned int nblocks) { - _img_private_t *env = user_data; + _img_private_t *p_env = user_data; int i; int retval; for (i = 0; i < nblocks; i++) { if (b_form2) { - if ( (retval = _cdio_read_mode1_sector (env, + if ( (retval = _cdio_read_mode1_sector (p_env, ((char *)data) + (M2RAW_SECTOR_SIZE * i), lsn + i, true)) ) return retval; } else { char buf[M2RAW_SECTOR_SIZE] = { 0, }; - if ( (retval = _cdio_read_mode1_sector (env, buf, lsn + i, false)) ) + if ( (retval = _cdio_read_mode1_sector (p_env, buf, lsn + i, false)) ) return retval; memcpy (((char *)data) + (CDIO_CD_FRAMESIZE * i), @@ -216,25 +320,25 @@ _cdio_read_mode2_sector (void *user_data, void *data, lsn_t lsn, bool b_form2) { char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; - _img_private_t *env = user_data; + _img_private_t *p_env = user_data; - if (env->gen.ioctls_debugged == 75) + if (p_env->gen.ioctls_debugged == 75) cdio_debug ("only displaying every 75th ioctl from now on"); - if (env->gen.ioctls_debugged == 30 * 75) + if (p_env->gen.ioctls_debugged == 30 * 75) cdio_debug ("only displaying every 30*75th ioctl from now on"); - if (env->gen.ioctls_debugged < 75 - || (env->gen.ioctls_debugged < (30 * 75) - && env->gen.ioctls_debugged % 75 == 0) - || env->gen.ioctls_debugged % (30 * 75) == 0) + if (p_env->gen.ioctls_debugged < 75 + || (p_env->gen.ioctls_debugged < (30 * 75) + && p_env->gen.ioctls_debugged % 75 == 0) + || p_env->gen.ioctls_debugged % (30 * 75) == 0) cdio_debug ("reading %lu", (unsigned long int) lsn); - env->gen.ioctls_debugged++; + p_env->gen.ioctls_debugged++; - if ( env->hASPI ) { + if ( p_env->hASPI ) { int ret; - ret = wnaspi32_read_mode2_sector(user_data, buf, lsn); + ret = read_mode2_sector_aspi(user_data, buf, lsn, 1); if( ret != 0 ) return ret; if (b_form2) memcpy (data, buf, M2RAW_SECTOR_SIZE); @@ -242,7 +346,7 @@ _cdio_read_mode2_sector (void *user_data, void *data, lsn_t lsn, memcpy (((char *)data), buf + CDIO_CD_SUBHEADER_SIZE, CDIO_CD_FRAMESIZE); return 0; } else { - return win32ioctl_read_mode2_sector( env, data, lsn, b_form2 ); + return read_mode2_sector_win32ioctl( p_env, data, lsn, b_form2 ); } } @@ -272,29 +376,40 @@ _cdio_read_mode2_sectors (void *user_data, void *data, lsn_t lsn, Return the size of the CD in logical block address (LBA) units. */ static uint32_t -_cdio_stat_size (void *user_data) +stat_size_win32 (void *user_data) { - _img_private_t *env = user_data; + _img_private_t *p_env = user_data; - return env->tocent[env->total_tracks].start_lsn; + return p_env->tocent[p_env->gen.i_tracks].start_lsn; } /*! Set the key "arg" to "value" in source device. */ static int -_cdio_set_arg (void *user_data, const char key[], const char value[]) +set_arg_win32 (void *user_data, const char key[], const char value[]) { - _img_private_t *env = user_data; + _img_private_t *p_env = user_data; if (!strcmp (key, "source")) { if (!value) return -2; - free (env->gen.source_name); + free (p_env->gen.source_name); - env->gen.source_name = strdup (value); + p_env->gen.source_name = strdup (value); + } + else if (!strcmp (key, "access-mode")) + { + p_env->access_mode = str_to_access_mode_win32(value); + if (p_env->access_mode == _AM_ASPI && !p_env->b_aspi_init) + return init_aspi(p_env) ? 1 : -3; + else if (p_env->access_mode == _AM_IOCTL && !p_env->b_ioctl_init) + return init_win32ioctl(p_env) ? 1 : -3; + else + return -4; + return 0; } else return -1; @@ -307,15 +422,16 @@ _cdio_set_arg (void *user_data, const char key[], const char value[]) Return true if successful or false if an error. */ static bool -_cdio_read_toc (_img_private_t *env) +read_toc_win32 (void *p_user_data) { + _img_private_t *p_env = p_user_data; bool ret; - if( env->hASPI ) { - ret = wnaspi32_read_toc( env ); + if( p_env->hASPI ) { + ret = read_toc_aspi( p_env ); } else { - ret =win32ioctl_read_toc(env); + ret = read_toc_win32ioctl( p_env ); } - if (ret) env->gen.toc_init = true ; + if (ret) p_env->gen.toc_init = true ; return true; } @@ -324,7 +440,9 @@ _cdio_read_toc (_img_private_t *env) */ static int _cdio_eject_media (void *user_data) { - +#ifdef _XBOX + return -1; +#else _img_private_t *env = user_data; @@ -354,13 +472,14 @@ _cdio_eject_media (void *user_data) { ret = 0; return ret; +#endif } /*! Return the value associated with the key "arg". */ static const char * -_cdio_get_arg (void *user_data, const char key[]) +_get_arg_win32 (void *user_data, const char key[]) { _img_private_t *env = user_data; @@ -369,29 +488,13 @@ _cdio_get_arg (void *user_data, const char key[]) } else if (!strcmp (key, "access-mode")) { if (env->hASPI) return "ASPI"; - else if ( WIN_NT ) - return "winNT/2K/XP ioctl"; else - return "undefined WIN32"; + return "ioctl"; } return NULL; } /*! - Return the number of of the first track. - CDIO_INVALID_TRACK is returned on error. -*/ -static track_t -_cdio_get_first_track_num(void *user_data) -{ - _img_private_t *env = user_data; - - if (!env->toc_init) _cdio_read_toc (env) ; - - return env->first_track_num; -} - -/*! Return the media catalog number MCN. Note: string is malloc'd so caller should free() then returned @@ -399,47 +502,36 @@ _cdio_get_first_track_num(void *user_data) */ static char * -_cdio_get_mcn (void *env) { - - _img_private_t *_env = env; +_cdio_get_mcn (const void *p_user_data) { + const _img_private_t *p_env = p_user_data; - if( ! _env->hASPI ) { - win32ioctl_get_mcn(_env); + if( p_env->hASPI ) { + return scsi_mmc_get_mcn( p_env->gen.cdio ); + } else { + return get_mcn_win32ioctl(p_env); } - return NULL; -} - -/*! - Return the number of tracks in the current medium. - CDIO_INVALID_TRACK is returned on error. -*/ -static track_t -_cdio_get_num_tracks(void *user_data) -{ - _img_private_t *env = user_data; - - if (!env->toc_init) _cdio_read_toc (env) ; - - return env->total_tracks; } /*! Get format of track. */ static track_format_t -_cdio_get_track_format(void *obj, track_t track_num) +_cdio_get_track_format(void *p_obj, track_t i_track) { - _img_private_t *env = obj; + _img_private_t *p_env = p_obj; - if (!env->gen.toc_init) _cdio_read_toc (env) ; + if ( !p_env ) return TRACK_FORMAT_ERROR; + + if (!p_env->gen.toc_init) read_toc_win32 (p_env) ; - if (track_num > env->total_tracks || track_num == 0) + if ( i_track < p_env->gen.i_first_track + || i_track >= p_env->gen.i_tracks + p_env->gen.i_first_track ) return TRACK_FORMAT_ERROR; - if( env->hASPI ) { - return wnaspi32_get_track_format(env, track_num); + if( p_env->hASPI ) { + return get_track_format_aspi(p_env, i_track); } else { - return win32ioctl_get_track_format(env, track_num); + return get_track_format_win32ioctl(p_env, i_track); } } @@ -452,22 +544,20 @@ _cdio_get_track_format(void *obj, track_t track_num) FIXME: there's gotta be a better design for this and get_track_format? */ static bool -_cdio_get_track_green(void *obj, track_t track_num) +_cdio_get_track_green(void *obj, track_t i_track) { - _img_private_t *env = obj; + _img_private_t *p_env = obj; - if (!env->toc_init) _cdio_read_toc (env) ; - - if (track_num == CDIO_CDROM_LEADOUT_TRACK) track_num = env->total_tracks+1; - - if (track_num > env->total_tracks+1 || track_num == 0) - return false; - - switch (_cdio_get_track_format(env, track_num)) { + switch (_cdio_get_track_format(p_env, i_track)) { + case TRACK_FORMAT_XA: + return true; case TRACK_FORMAT_ERROR: case TRACK_FORMAT_CDI: case TRACK_FORMAT_AUDIO: return false; + case TRACK_FORMAT_DATA: + if (_AM_ASPI == p_env->access_mode ) + return ((p_env->tocent[i_track-p_env->gen.i_first_track].Control & 8) != 0); default: break; } @@ -475,31 +565,31 @@ _cdio_get_track_green(void *obj, track_t track_num) /* FIXME: Dunno if this is the right way, but it's what I was using in cd-info for a while. */ - return ((env->tocent[track_num-1].Control & 2) != 0); + return ((p_env->tocent[i_track-p_env->gen.i_first_track].Control & 2) != 0); } /*! Return the starting MSF (minutes/secs/frames) for track number - track_num in obj. Track numbers start at 1. + i_tracks in obj. Track numbers start at 1. The "leadout" track is specified either by - using track_num LEADOUT_TRACK or the total tracks+1. + using i_tracks LEADOUT_TRACK or the total tracks+1. False is returned if there is no track entry. */ static bool -_cdio_get_track_msf(void *env, track_t track_num, msf_t *msf) +_cdio_get_track_msf(void *p_user_data, track_t i_tracks, msf_t *msf) { - _img_private_t *_obj = env; + _img_private_t *p_env = p_user_data; if (NULL == msf) return false; - if (!_obj->toc_init) _cdio_read_toc (_obj) ; + if (!p_env->gen.toc_init) read_toc_win32 (p_env) ; - if (track_num == CDIO_CDROM_LEADOUT_TRACK) track_num = _obj->total_tracks+1; + if (i_tracks == CDIO_CDROM_LEADOUT_TRACK) i_tracks = p_env->gen.i_tracks+1; - if (track_num > _obj->total_tracks+1 || track_num == 0) { + if (i_tracks > p_env->gen.i_tracks+1 || i_tracks == 0) { return false; } else { - cdio_lsn_to_msf(_obj->tocent[track_num-1].start_lsn, msf); + cdio_lsn_to_msf(p_env->tocent[i_tracks-1].start_lsn, msf); return true; } } @@ -538,7 +628,7 @@ cdio_get_devices_win32 (void) Not always 100% reliable, so use the USE_MNTENT code above first. */ for (drive_letter='A'; drive_letter <= 'Z'; drive_letter++) { - const char *drive_str=cdio_is_cdrom(drive_letter); + const char *drive_str=is_cdrom_win32(drive_letter); if (drive_str != NULL) { cdio_add_device_list(&drives, drive_str, &num_drives); } @@ -563,7 +653,7 @@ cdio_get_default_device_win32(void) char drive_letter; for (drive_letter='A'; drive_letter <= 'Z'; drive_letter++) { - const char *drive_str=cdio_is_cdrom(drive_letter); + const char *drive_str=is_cdrom_win32(drive_letter); if (drive_str != NULL) { return strdup(drive_str); } @@ -579,8 +669,8 @@ bool cdio_is_device_win32(const char *source_name) { unsigned int len; - len = strlen(source_name); + len = strlen(source_name); if (NULL == source_name) return false; #ifdef HAVE_WIN32_CDROM @@ -607,51 +697,94 @@ cdio_is_device_win32(const char *source_name) ones to set that up. */ CdIo * -cdio_open_win32 (const char *source_name) +cdio_open_win32 (const char *psz_source_name) +{ +#ifdef HAVE_WIN32_CDROM + if ( WIN_NT ) { + return cdio_open_am_win32(psz_source_name, "ioctl"); + } else { + return cdio_open_am_win32(psz_source_name, "ASPI"); + } +#else + return NULL; +#endif /* HAVE_WIN32_CDROM */ +} + +/*! + Initialization routine. This is the only thing that doesn't + get called via a function pointer. In fact *we* are the + ones to set that up. + */ +CdIo * +cdio_open_am_win32 (const char *psz_orig_source, const char *psz_access_mode) { #ifdef HAVE_WIN32_CDROM CdIo *ret; _img_private_t *_data; - - cdio_funcs _funcs = { - .eject_media = _cdio_eject_media, - .free = _cdio_win32_free, - .get_arg = _cdio_get_arg, - .get_default_device = cdio_get_default_device_win32, - .get_devices = cdio_get_devices_win32, - .get_first_track_num= _cdio_get_first_track_num, - .get_mcn = _cdio_get_mcn, - .get_num_tracks = _cdio_get_num_tracks, - .get_track_format = _cdio_get_track_format, - .get_track_green = _cdio_get_track_green, - .get_track_lba = NULL, /* This could be implemented if need be. */ - .get_track_msf = _cdio_get_track_msf, - .lseek = NULL, - .read = NULL, - .read_audio_sectors = _cdio_read_audio_sectors, - .read_mode1_sector = _cdio_read_mode1_sector, - .read_mode1_sectors = _cdio_read_mode1_sectors, - .read_mode2_sector = _cdio_read_mode2_sector, - .read_mode2_sectors = _cdio_read_mode2_sectors, - .set_arg = _cdio_set_arg, - .stat_size = _cdio_stat_size - }; + char *psz_source; + + cdio_funcs _funcs; + + memset( &_funcs, 0, sizeof(_funcs) ); + + _funcs.eject_media = _cdio_eject_media; + _funcs.free = _free_win32; + _funcs.get_arg = _get_arg_win32; + _funcs.get_cdtext = get_cdtext_generic; + _funcs.get_default_device = cdio_get_default_device_win32; + _funcs.get_devices = cdio_get_devices_win32; + _funcs.get_discmode = get_discmode_win32; + _funcs.get_drive_cap = scsi_mmc_get_drive_cap_generic; + _funcs.get_first_track_num= get_first_track_num_generic; + _funcs.get_hwinfo = NULL; + _funcs.get_mcn = _cdio_get_mcn; + _funcs.get_num_tracks = get_num_tracks_generic; + _funcs.get_track_format = _cdio_get_track_format; + _funcs.get_track_green = _cdio_get_track_green; + _funcs.get_track_lba = NULL; /* This could be implemented if need be. */ + _funcs.get_track_msf = _cdio_get_track_msf; + _funcs.lseek = NULL; + _funcs.read = NULL; + _funcs.read_audio_sectors = _cdio_read_audio_sectors; + _funcs.read_mode1_sector = _cdio_read_mode1_sector; + _funcs.read_mode1_sectors = _cdio_read_mode1_sectors; + _funcs.read_mode2_sector = _cdio_read_mode2_sector; + _funcs.read_mode2_sectors = _cdio_read_mode2_sectors; + _funcs.read_toc = &read_toc_win32; + _funcs.run_scsi_mmc_cmd = &run_scsi_cmd_win32; + _funcs.set_arg = set_arg_win32; + _funcs.stat_size = stat_size_win32; _data = _cdio_malloc (sizeof (_img_private_t)); + _data->access_mode = str_to_access_mode_win32(psz_access_mode); _data->gen.init = false; _data->gen.fd = -1; - _cdio_set_arg(_data, "source", (NULL == source_name) - ? cdio_get_default_device_win32(): source_name); + if (NULL == psz_orig_source) { + psz_source=cdio_get_default_device_win32(); + if (NULL == psz_source) return NULL; + set_arg_win32(_data, "source", psz_source); + free(psz_source); + } else { + if (cdio_is_device_win32(psz_orig_source)) + set_arg_win32(_data, "source", psz_orig_source); + else { + /* The below would be okay if all device drivers worked this way. */ +#if 0 + cdio_info ("source %s is a not a device", psz_orig_source); +#endif + return NULL; + } + } - ret = cdio_new (_data, &_funcs); + ret = cdio_new ((void *)_data, &_funcs); if (ret == NULL) return NULL; if (_cdio_init_win32(_data)) return ret; else { - _cdio_win32_free (_data); + _free_win32 (_data); return NULL; } diff --git a/src/input/vcd/libcdio/MSWindows/win32.h b/src/input/vcd/libcdio/MSWindows/win32.h index d70797c08..84f3b67b3 100644 --- a/src/input/vcd/libcdio/MSWindows/win32.h +++ b/src/input/vcd/libcdio/MSWindows/win32.h @@ -1,5 +1,5 @@ /*
- $Id: win32.h,v 1.1 2004/04/11 12:20:31 miguelfreitas Exp $
+ $Id: win32.h,v 1.2 2005/01/01 02:43:58 rockyb Exp $
Copyright (C) 2004 Rocky Bernstein <rocky@panix.com>
@@ -26,65 +26,145 @@ typedef struct { lsn_t start_lsn;
UCHAR Control : 4;
UCHAR Format;
+ cdtext_t cdtext; /* CD-TEXT */
} track_info_t;
+typedef enum {
+ _AM_NONE,
+ _AM_IOCTL,
+ _AM_ASPI,
+} access_mode_t;
+
typedef struct {
/* Things common to all drivers like this.
This must be first. */
generic_img_private_t gen;
+ access_mode_t access_mode;
+
+ /* Some of the more OS specific things. */
+ /* Entry info for each track, add 1 for leadout. */
+ track_info_t tocent[CDIO_CD_MAX_TRACKS+1];
+
HANDLE h_device_handle; /* device descriptor */
long hASPI;
short i_sid;
+ short i_lun;
long (*lpSendCommand)( void* );
- /* Track information */
- bool toc_init; /* if true, info below is valid. */
- track_info_t tocent[100]; /* entry info for each track */
- track_t total_tracks; /* number of tracks in image */
- track_t first_track_num; /* track number of first track */
+ bool b_ioctl_init;
+ bool b_aspi_init;
} _img_private_t;
+/*!
+ Get disc type associated with cd object.
+*/
+discmode_t get_discmode_win32ioctl (_img_private_t *p_env);
+
/*!
Reads an audio device using the DeviceIoControl method into data
starting from lsn. Returns 0 if no error.
- */
-int win32ioctl_read_audio_sectors (_img_private_t *obj, void *data, lsn_t lsn,
+*/
+int read_audio_sectors_win32ioctl (_img_private_t *obj, void *data, lsn_t lsn,
unsigned int nblocks);
/*!
Reads a single mode2 sector using the DeviceIoControl method into
data starting from lsn. Returns 0 if no error.
*/
-int
-win32ioctl_read_mode2_sector (_img_private_t *env, void *data, lsn_t lsn,
- bool mode2_form2);
+int read_mode2_sector_win32ioctl (const _img_private_t *env, void *data,
+ lsn_t lsn, bool b_form2);
/*!
Reads a single mode1 sector using the DeviceIoControl method into
data starting from lsn. Returns 0 if no error.
*/
-int
-win32ioctl_read_mode1_sector (_img_private_t *env, void *data, lsn_t lsn,
- bool mode2_form2);
+int read_mode1_sector_win32ioctl (const _img_private_t *env, void *data,
+ lsn_t lsn, bool b_form2);
-const char *win32ioctl_is_cdrom(const char drive_letter);
+const char *is_cdrom_win32ioctl (const char drive_letter);
+
+/*!
+ Run a SCSI MMC command.
+
+ env private CD structure
+ i_timeout_ms time in milliseconds we will wait for the command
+ to complete. If this value is -1, use the default
+ time-out value.
+ p_buf Buffer for data, both sending and receiving
+ i_buf Size of buffer
+ e_direction direction the transfer is to go.
+ cdb CDB bytes. All values that are needed should be set on
+ input. We'll figure out what the right CDB length should be.
+
+ Return 0 if command completed successfully.
+ */
+int run_scsi_cmd_win32ioctl( const void *p_user_data,
+ unsigned int i_timeout,
+ unsigned int i_cdb,
+ const scsi_mmc_cdb_t * p_cdb,
+ scsi_mmc_direction_t e_direction,
+ unsigned int i_buf, /*in/out*/ void *p_buf );
/*!
Initialize internal structures for CD device.
*/
-bool win32ioctl_init_win32 (_img_private_t *env);
+bool init_win32ioctl (_img_private_t *env);
/*!
Read and cache the CD's Track Table of Contents and track info.
Return true if successful or false if an error.
*/
-bool win32ioctl_read_toc (_img_private_t *env);
+bool read_toc_win32ioctl (_img_private_t *env);
+
+/*!
+ Return the media catalog number MCN.
+
+ Note: string is malloc'd so caller should free() then returned
+ string when done with it.
+
+ */
+char *get_mcn_win32ioctl (const _img_private_t *env);
+
+/*
+ Read cdtext information for a CdIo object .
+
+ return true on success, false on error or CD-TEXT information does
+ not exist.
+*/
+bool init_cdtext_win32ioctl (_img_private_t *env);
-char *win32ioctl_get_mcn (_img_private_t *env);
+/*!
+ Return the the kind of drive capabilities of device.
+
+ Note: string is malloc'd so caller should free() then returned
+ string when done with it.
+
+ */
+void get_drive_cap_aspi (const _img_private_t *env,
+ cdio_drive_read_cap_t *p_read_cap,
+ cdio_drive_write_cap_t *p_write_cap,
+ cdio_drive_misc_cap_t *p_misc_cap);
+
+/*!
+ Return the the kind of drive capabilities of device.
+
+ Note: string is malloc'd so caller should free() then returned
+ string when done with it.
+
+ */
+void get_drive_cap_win32ioctl (const _img_private_t *env,
+ cdio_drive_read_cap_t *p_read_cap,
+ cdio_drive_write_cap_t *p_write_cap,
+ cdio_drive_misc_cap_t *p_misc_cap);
/*!
Get the format (XA, DATA, AUDIO) of a track.
*/
-track_format_t win32ioctl_get_track_format(_img_private_t *env,
- track_t track_num);
+track_format_t get_track_format_win32ioctl(const _img_private_t *env,
+ track_t i_track);
+
+void set_cdtext_field_win32(void *user_data, track_t i_track,
+ track_t i_first_track,
+ cdtext_field_t e_field, const char *psz_value);
+
diff --git a/src/input/vcd/libcdio/MSWindows/win32_ioctl.c b/src/input/vcd/libcdio/MSWindows/win32_ioctl.c new file mode 100644 index 000000000..dec24e785 --- /dev/null +++ b/src/input/vcd/libcdio/MSWindows/win32_ioctl.c @@ -0,0 +1,739 @@ +/* + $Id: win32_ioctl.c,v 1.1 2005/01/01 02:43:58 rockyb Exp $ + + Copyright (C) 2004 Rocky Bernstein <rocky@panix.com> + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* This file contains Win32-specific code using the DeviceIoControl + access method. +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +static const char _rcsid[] = "$Id: win32_ioctl.c,v 1.1 2005/01/01 02:43:58 rockyb Exp $"; + +#ifdef HAVE_WIN32_CDROM + +#if defined (_XBOX) +#include "inttypes.h" +#include "NtScsi.h" +#include "undocumented.h" +#define FORMAT_ERROR(i_err, psz_msg) \ + psz_msg=(char *)LocalAlloc(LMEM_ZEROINIT, 255); \ + sprintf(psz_msg, "error file %s: line %d (%s) %d\n", + _FILE__, __LINE__, __PRETTY_FUNCTION__, i_err) +#else +#include <ddk/ntddstor.h> +#include <ddk/ntddscsi.h> +#include <ddk/scsi.h> +#define FORMAT_ERROR(i_err, psz_msg) \ + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, \ + NULL, i_err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), \ + (LPSTR) psz_msg, 0, NULL) +#endif + +#ifdef WIN32 +#include <windows.h> +#endif + +#include <stdio.h> +#include <stddef.h> /* offsetof() macro */ +#include <sys/stat.h> +#include <errno.h> +#include <sys/types.h> + +#include <cdio/cdio.h> +#include <cdio/sector.h> +#include "cdio_assert.h" +#include <cdio/scsi_mmc.h> +#include "cdtext_private.h" +#include "cdio/logging.h" + +/* Win32 DeviceIoControl specifics */ +/***** FIXME: #include ntddcdrm.h from Wine, but probably need to + modify it a little. +*/ + +#ifndef IOCTL_CDROM_BASE +# define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM +#endif +#ifndef IOCTL_CDROM_READ_TOC +#define IOCTL_CDROM_READ_TOC \ + CTL_CODE(IOCTL_CDROM_BASE, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS) +#endif +#ifndef IOCTL_CDROM_RAW_READ +#define IOCTL_CDROM_RAW_READ CTL_CODE(IOCTL_CDROM_BASE, 0x000F, \ + METHOD_OUT_DIRECT, FILE_READ_ACCESS) +#endif + +#ifndef IOCTL_CDROM_READ_Q_CHANNEL +#define IOCTL_CDROM_READ_Q_CHANNEL \ + CTL_CODE(IOCTL_CDROM_BASE, 0x000B, METHOD_BUFFERED, FILE_READ_ACCESS) +#endif + +typedef struct { + SCSI_PASS_THROUGH Spt; + ULONG Filler; + UCHAR SenseBuf[32]; + UCHAR DataBuf[512]; +} SCSI_PASS_THROUGH_WITH_BUFFERS; + +typedef struct _TRACK_DATA { + UCHAR Format; + UCHAR Control : 4; + UCHAR Adr : 4; + UCHAR TrackNumber; + UCHAR Reserved1; + UCHAR Address[4]; +} TRACK_DATA, *PTRACK_DATA; + +typedef struct _CDROM_TOC { + UCHAR Length[2]; + UCHAR FirstTrack; + UCHAR LastTrack; + TRACK_DATA TrackData[CDIO_CD_MAX_TRACKS+1]; +} CDROM_TOC, *PCDROM_TOC; + +typedef struct _TRACK_DATA_FULL { + UCHAR SessionNumber; + UCHAR Control : 4; + UCHAR Adr : 4; + UCHAR TNO; + UCHAR POINT; /* Tracknumber (of session?) or lead-out/in (0xA0, 0xA1, 0xA2) */ + UCHAR Min; /* Only valid if disctype is CDDA ? */ + UCHAR Sec; /* Only valid if disctype is CDDA ? */ + UCHAR Frame; /* Only valid if disctype is CDDA ? */ + UCHAR Zero; /* Always zero */ + UCHAR PMIN; /* start min, if POINT is a track; if lead-out/in 0xA0: First Track */ + UCHAR PSEC; + UCHAR PFRAME; +} TRACK_DATA_FULL, *PTRACK_DATA_FULL; + +typedef struct _CDROM_TOC_FULL { + UCHAR Length[2]; + UCHAR FirstSession; + UCHAR LastSession; + TRACK_DATA_FULL TrackData[CDIO_CD_MAX_TRACKS+3]; +} CDROM_TOC_FULL, *PCDROM_TOC_FULL; + +typedef enum _TRACK_MODE_TYPE { + YellowMode2, + XAForm2, + CDDA +} TRACK_MODE_TYPE, *PTRACK_MODE_TYPE; + +typedef struct __RAW_READ_INFO { + LARGE_INTEGER DiskOffset; + ULONG SectorCount; + TRACK_MODE_TYPE TrackMode; +} RAW_READ_INFO, *PRAW_READ_INFO; + +typedef struct _CDROM_SUB_Q_DATA_FORMAT { + UCHAR Format; + UCHAR Track; +} CDROM_SUB_Q_DATA_FORMAT, *PCDROM_SUB_Q_DATA_FORMAT; + +typedef struct _SUB_Q_HEADER { + UCHAR Reserved; + UCHAR AudioStatus; + UCHAR DataLength[2]; +} SUB_Q_HEADER, *PSUB_Q_HEADER; + +typedef struct _SUB_Q_MEDIA_CATALOG_NUMBER { + SUB_Q_HEADER Header; + UCHAR FormatCode; + UCHAR Reserved[3]; + UCHAR Reserved1 : 7; + UCHAR Mcval :1; + UCHAR MediaCatalog[15]; +} SUB_Q_MEDIA_CATALOG_NUMBER, *PSUB_Q_MEDIA_CATALOG_NUMBER; + +#include "win32.h" + +#define OP_TIMEOUT_MS 60 + +/*! + Run a SCSI MMC command. + + env private CD structure + i_timeout time in milliseconds we will wait for the command + to complete. If this value is -1, use the default + time-out value. + p_buf Buffer for data, both sending and receiving + i_buf Size of buffer + e_direction direction the transfer is to go. + cdb CDB bytes. All values that are needed should be set on + input. We'll figure out what the right CDB length should be. + + Return 0 if command completed successfully. + */ +int +run_scsi_cmd_win32ioctl( const void *p_user_data, + unsigned int i_timeout_ms, + unsigned int i_cdb, const scsi_mmc_cdb_t * p_cdb, + scsi_mmc_direction_t e_direction, + unsigned int i_buf, /*in/out*/ void *p_buf ) +{ + const _img_private_t *p_env = p_user_data; + SCSI_PASS_THROUGH_DIRECT sptd; + bool success; + DWORD dwBytesReturned; + + sptd.Length = sizeof(sptd); + sptd.PathId = 0; /* SCSI card ID will be filled in automatically */ + sptd.TargetId= 0; /* SCSI target ID will also be filled in */ + sptd.Lun=0; /* SCSI lun ID will also be filled in */ + sptd.CdbLength = i_cdb; + sptd.SenseInfoLength = 0; /* Don't return any sense data */ + sptd.DataIn = SCSI_MMC_DATA_READ == e_direction ? + SCSI_IOCTL_DATA_IN : SCSI_IOCTL_DATA_OUT; + sptd.DataTransferLength= i_buf; + sptd.TimeOutValue = msecs2secs(i_timeout_ms); + sptd.DataBuffer = (void *) p_buf; + sptd.SenseInfoOffset = 0; + + memcpy(sptd.Cdb, p_cdb, i_cdb); + + /* Send the command to drive */ + success=DeviceIoControl(p_env->h_device_handle, + IOCTL_SCSI_PASS_THROUGH_DIRECT, + (void *)&sptd, + (DWORD)sizeof(SCSI_PASS_THROUGH_DIRECT), + NULL, 0, + &dwBytesReturned, + NULL); + + if(! success) { + char *psz_msg = NULL; + long int i_err = GetLastError(); + FORMAT_ERROR(i_err, psz_msg); + cdio_info("Error: %s", psz_msg); + LocalFree(psz_msg); + return 1; + } + return 0; +} + +/*! + Get disc type associated with cd object. +*/ +discmode_t +get_discmode_win32ioctl (_img_private_t *p_env) +{ + track_t i_track; + discmode_t discmode=CDIO_DISC_MODE_NO_INFO; + + /* See if this is a DVD. */ + cdio_dvd_struct_t dvd; /* DVD READ STRUCT for layer 0. */ + + dvd.physical.type = CDIO_DVD_STRUCT_PHYSICAL; + dvd.physical.layer_num = 0; + if (0 == scsi_mmc_get_dvd_struct_physical_private (p_env, + &run_scsi_cmd_win32ioctl, + &dvd)) { + switch(dvd.physical.layer[0].book_type) { + case CDIO_DVD_BOOK_DVD_ROM: return CDIO_DISC_MODE_DVD_ROM; + case CDIO_DVD_BOOK_DVD_RAM: return CDIO_DISC_MODE_DVD_RAM; + case CDIO_DVD_BOOK_DVD_R: return CDIO_DISC_MODE_DVD_R; + case CDIO_DVD_BOOK_DVD_RW: return CDIO_DISC_MODE_DVD_RW; + case CDIO_DVD_BOOK_DVD_PR: return CDIO_DISC_MODE_DVD_PR; + case CDIO_DVD_BOOK_DVD_PRW: return CDIO_DISC_MODE_DVD_PRW; + default: return CDIO_DISC_MODE_DVD_OTHER; + } + } + + if (!p_env->gen.toc_init) + read_toc_win32ioctl (p_env); + + if (!p_env->gen.toc_init) + return CDIO_DISC_MODE_NO_INFO; + + for (i_track = p_env->gen.i_first_track; + i_track < p_env->gen.i_first_track + p_env->gen.i_tracks ; + i_track ++) { + track_format_t track_fmt=get_track_format_win32ioctl(p_env, i_track); + + switch(track_fmt) { + case TRACK_FORMAT_AUDIO: + switch(discmode) { + case CDIO_DISC_MODE_NO_INFO: + discmode = CDIO_DISC_MODE_CD_DA; + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* No change*/ + break; + default: + discmode = CDIO_DISC_MODE_CD_MIXED; + } + break; + case TRACK_FORMAT_XA: + switch(discmode) { + case CDIO_DISC_MODE_NO_INFO: + discmode = CDIO_DISC_MODE_CD_XA; + break; + case CDIO_DISC_MODE_CD_XA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* No change*/ + break; + default: + discmode = CDIO_DISC_MODE_CD_MIXED; + } + break; + case TRACK_FORMAT_DATA: + switch(discmode) { + case CDIO_DISC_MODE_NO_INFO: + discmode = CDIO_DISC_MODE_CD_DATA; + break; + case CDIO_DISC_MODE_CD_DATA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* No change*/ + break; + default: + discmode = CDIO_DISC_MODE_CD_MIXED; + } + break; + case TRACK_FORMAT_ERROR: + default: + discmode = CDIO_DISC_MODE_ERROR; + } + } + return discmode; +} + +/* + Returns a string that can be used in a CreateFile call if + c_drive letter is a character. If not NULL is returned. + */ + +const char * +is_cdrom_win32ioctl(const char c_drive_letter) +{ +#ifdef _XBOX + char sz_win32_drive_full[] = "\\\\.\\X:"; + sz_win32_drive_full[4] = c_drive_letter; + return strdup(sz_win32_drive_full); +#else + UINT uDriveType; + char sz_win32_drive[4]; + + sz_win32_drive[0]= c_drive_letter; + sz_win32_drive[1]=':'; + sz_win32_drive[2]='\\'; + sz_win32_drive[3]='\0'; + + uDriveType = GetDriveType(sz_win32_drive); + + switch(uDriveType) { + case DRIVE_CDROM: { + char sz_win32_drive_full[] = "\\\\.\\X:"; + sz_win32_drive_full[4] = c_drive_letter; + return strdup(sz_win32_drive_full); + } + default: + cdio_debug("Drive %c is not a CD-ROM", c_drive_letter); + return NULL; + } +#endif +} + +/*! + Reads an audio device using the DeviceIoControl method into data + starting from lsn. Returns 0 if no error. + */ +int +read_audio_sectors_win32ioctl (_img_private_t *env, void *data, lsn_t lsn, + unsigned int nblocks) +{ + DWORD dwBytesReturned; + RAW_READ_INFO cdrom_raw; + + /* Initialize CDROM_RAW_READ structure */ + cdrom_raw.DiskOffset.QuadPart = CDIO_CD_FRAMESIZE_RAW * lsn; + cdrom_raw.SectorCount = nblocks; + cdrom_raw.TrackMode = CDDA; + + if( DeviceIoControl( env->h_device_handle, + IOCTL_CDROM_RAW_READ, &cdrom_raw, + sizeof(RAW_READ_INFO), data, + CDIO_CD_FRAMESIZE_RAW * nblocks, + &dwBytesReturned, NULL ) == 0 ) { + char *psz_msg = NULL; + long int i_err = GetLastError(); + FORMAT_ERROR(i_err, psz_msg); + cdio_info("Error reading audio-mode %lu\n%s)", + (long unsigned int) lsn, psz_msg); + LocalFree(psz_msg); + return 1; + } + return 0; +} + +/*! + Reads a single raw sector using the DeviceIoControl method into + data starting from lsn. Returns 0 if no error. + */ +static int +read_raw_sector (const _img_private_t *p_env, void *p_buf, lsn_t lsn) +{ + scsi_mmc_cdb_t cdb = {{0, }}; + + /* ReadCD CDB12 command. The values were taken from MMC1 draft paper. */ + CDIO_MMC_SET_COMMAND (cdb.field, CDIO_MMC_GPCMD_READ_CD); + CDIO_MMC_SET_READ_LBA (cdb.field, lsn); + CDIO_MMC_SET_READ_LENGTH24(cdb.field, 1); + + cdb.field[9]=0xF8; /* Raw read, 2352 bytes per sector */ + + return run_scsi_cmd_win32ioctl(p_env, OP_TIMEOUT_MS, + scsi_mmc_get_cmd_len(cdb.field[0]), + &cdb, SCSI_MMC_DATA_READ, + CDIO_CD_FRAMESIZE_RAW, p_buf); +} + +/*! + Reads a single mode2 sector using the DeviceIoControl method into + data starting from lsn. Returns 0 if no error. + */ +int +read_mode2_sector_win32ioctl (const _img_private_t *p_env, void *p_data, + lsn_t lsn, bool b_form2) +{ + char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; + int ret = read_raw_sector (p_env, buf, lsn); + + if ( 0 != ret) return ret; + + memcpy (p_data, + buf + CDIO_CD_SYNC_SIZE + CDIO_CD_XA_HEADER, + b_form2 ? M2RAW_SECTOR_SIZE: CDIO_CD_FRAMESIZE); + + return 0; + +} + +/*! + Reads a single mode2 sector using the DeviceIoControl method into + data starting from lsn. Returns 0 if no error. + */ +int +read_mode1_sector_win32ioctl (const _img_private_t *env, void *data, + lsn_t lsn, bool b_form2) +{ + char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; + int ret = read_raw_sector (env, buf, lsn); + + if ( 0 != ret) return ret; + + memcpy (data, + buf + CDIO_CD_SYNC_SIZE+CDIO_CD_HEADER_SIZE, + b_form2 ? M2RAW_SECTOR_SIZE: CDIO_CD_FRAMESIZE); + + return 0; + +} + +/*! + Initialize internal structures for CD device. + */ +bool +init_win32ioctl (_img_private_t *env) +{ +#ifdef WIN32 + OSVERSIONINFO ov; +#endif + +#ifdef _XBOX + ANSI_STRING filename; + OBJECT_ATTRIBUTES attributes; + IO_STATUS_BLOCK status; + HANDLE hDevice; + NTSTATUS error; +#else + unsigned int len=strlen(env->gen.source_name); + char psz_win32_drive[7]; + DWORD dw_access_flags; +#endif + + cdio_debug("using winNT/2K/XP ioctl layer"); + +#ifdef WIN32 + memset(&ov,0,sizeof(OSVERSIONINFO)); + ov.dwOSVersionInfoSize=sizeof(OSVERSIONINFO); + GetVersionEx(&ov); + + if((ov.dwPlatformId==VER_PLATFORM_WIN32_NT) && + (ov.dwMajorVersion>4)) + dw_access_flags = GENERIC_READ|GENERIC_WRITE; /* add gen write on W2k/XP */ + else dw_access_flags = GENERIC_READ; +#endif + + if (cdio_is_device_win32(env->gen.source_name)) + { +#ifdef _XBOX + // Use XBOX cdrom, no matter what drive letter is given. + RtlInitAnsiString(&filename,"\\Device\\Cdrom0"); + InitializeObjectAttributes(&attributes, &filename, OBJ_CASE_INSENSITIVE, + NULL); + error = NtCreateFile( &hDevice, + GENERIC_READ |SYNCHRONIZE | FILE_READ_ATTRIBUTES, + &attributes, + &status, + NULL, + 0, + FILE_SHARE_READ, + FILE_OPEN, + FILE_NON_DIRECTORY_FILE + | FILE_SYNCHRONOUS_IO_NONALERT ); + + if (!NT_SUCCESS(error)) + { + return false; + } + env->h_device_handle = hDevice; +#else + sprintf( psz_win32_drive, "\\\\.\\%c:", env->gen.source_name[len-2] ); + + env->h_device_handle = CreateFile( psz_win32_drive, + dw_access_flags, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL ); + + if( env->h_device_handle == INVALID_HANDLE_VALUE ) + { + /* No good. try toggle write. */ + dw_access_flags ^= GENERIC_WRITE; + env->h_device_handle = CreateFile( psz_win32_drive, + dw_access_flags, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL ); + if (env->h_device_handle == NULL) + return false; + } +#endif + env->b_ioctl_init = true; + return true; + } + return false; +} + +/*! + Read and cache the CD's Track Table of Contents and track info. + via a SCSI MMC READ_TOC (FULTOC). Return true if successful or + false if an error. +*/ +static bool +read_fulltoc_win32mmc (_img_private_t *p_env) +{ + scsi_mmc_cdb_t cdb = {{0, }}; + CDROM_TOC_FULL cdrom_toc_full; + int i_status, i, i_track_format, i_seen_flag; + + /* Operation code */ + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_TOC); + + cdb.field[1] = 0x00; + + /* Format */ + cdb.field[2] = CDIO_MMC_READTOC_FMT_FULTOC; + + memset(&cdrom_toc_full, 0, sizeof(cdrom_toc_full)); + + /* Setup to read header, to get length of data */ + CDIO_MMC_SET_READ_LENGTH16(cdb.field, sizeof(cdrom_toc_full)); + + i_status = run_scsi_cmd_win32ioctl (p_env, 1000*60*3, + scsi_mmc_get_cmd_len(cdb.field[0]), + &cdb, SCSI_MMC_DATA_READ, + sizeof(cdrom_toc_full), &cdrom_toc_full); + + if ( 0 != i_status ) { + cdio_debug ("SCSI MMC READ_TOC failed\n"); + return false; + } + + i_seen_flag=0; + for( i = 0 ; i <= CDIO_CD_MAX_TRACKS+3; i++ ) { + + if ( 0xA0 == cdrom_toc_full.TrackData[i].POINT ) { + /* First track number */ + p_env->gen.i_first_track = cdrom_toc_full.TrackData[i].PMIN; + i_track_format = cdrom_toc_full.TrackData[i].PSEC; + i_seen_flag|=0x01; + } + + if ( 0xA1 == cdrom_toc_full.TrackData[i].POINT ) { + /* Last track number */ + p_env->gen.i_tracks = + cdrom_toc_full.TrackData[i].PMIN - p_env->gen.i_first_track + 1; + i_seen_flag|=0x02; + } + + if ( 0xA2 == cdrom_toc_full.TrackData[i].POINT ) { + /* Start position of the lead out */ + p_env->tocent[ p_env->gen.i_tracks ].start_lsn = + cdio_msf3_to_lba( + cdrom_toc_full.TrackData[i].PMIN, + cdrom_toc_full.TrackData[i].PSEC, + cdrom_toc_full.TrackData[i].PFRAME ); + p_env->tocent[ p_env->gen.i_tracks ].Control + = cdrom_toc_full.TrackData[i].Control; + p_env->tocent[ p_env->gen.i_tracks ].Format = i_track_format; + i_seen_flag|=0x04; + } + + if (cdrom_toc_full.TrackData[i].POINT > 0 + && cdrom_toc_full.TrackData[i].POINT <= p_env->gen.i_tracks) { + p_env->tocent[ cdrom_toc_full.TrackData[i].POINT - 1 ].start_lsn = + cdio_msf3_to_lba( + cdrom_toc_full.TrackData[i].PMIN, + cdrom_toc_full.TrackData[i].PSEC, + cdrom_toc_full.TrackData[i].PFRAME ); + p_env->tocent[ cdrom_toc_full.TrackData[i].POINT - 1 ].Control = + cdrom_toc_full.TrackData[i].Control; + p_env->tocent[ cdrom_toc_full.TrackData[i].POINT - 1 ].Format = + i_track_format; + + cdio_debug("p_sectors: %i, %lu", i, + (unsigned long int) (p_env->tocent[i].start_lsn)); + + if (cdrom_toc_full.TrackData[i].POINT == p_env->gen.i_tracks) + i_seen_flag|=0x08; + } + + if ( 0x0F == i_seen_flag ) break; + } + if ( 0x0F == i_seen_flag ) { + p_env->gen.toc_init = true; + return true; + } + return false; +} + +/*! + Read and cache the CD's Track Table of Contents and track info. + Return true if successful or false if an error. +*/ +bool +read_toc_win32ioctl (_img_private_t *p_env) +{ + CDROM_TOC cdrom_toc; + DWORD dwBytesReturned; + unsigned int i; + + if ( ! p_env ) return false; + + if ( read_fulltoc_win32mmc(p_env) ) return true; + + /* SCSI-MMC READ_TOC (FULTOC) read failed. Try reading TOC via + DeviceIoControl instead */ + if( DeviceIoControl( p_env->h_device_handle, + IOCTL_CDROM_READ_TOC, + NULL, 0, &cdrom_toc, sizeof(CDROM_TOC), + &dwBytesReturned, NULL ) == 0 ) { + char *psz_msg = NULL; + long int i_err = GetLastError(); + FORMAT_ERROR(i_err, psz_msg); + if (psz_msg) { + cdio_warn("could not read TOC (%ld): %s", i_err, psz_msg); + LocalFree(psz_msg); + } else + cdio_warn("could not read TOC (%ld)", i_err); + return false; + } + + p_env->gen.i_first_track = cdrom_toc.FirstTrack; + p_env->gen.i_tracks = cdrom_toc.LastTrack - cdrom_toc.FirstTrack + 1; + + for( i = 0 ; i <= p_env->gen.i_tracks ; i++ ) { + p_env->tocent[ i ].start_lsn = + cdio_msf3_to_lba( cdrom_toc.TrackData[i].Address[1], + cdrom_toc.TrackData[i].Address[2], + cdrom_toc.TrackData[i].Address[3] ); + p_env->tocent[ i ].Control = cdrom_toc.TrackData[i].Control; + p_env->tocent[ i ].Format = cdrom_toc.TrackData[i].Format; + cdio_debug("p_sectors: %i, %lu", i, + (unsigned long int) (p_env->tocent[i].start_lsn)); + } + p_env->gen.toc_init = true; + return true; +} + +/*! + Return the media catalog number MCN. + + Note: string is malloc'd so caller should free() then returned + string when done with it. + + */ +char * +get_mcn_win32ioctl (const _img_private_t *env) { + + DWORD dwBytesReturned; + SUB_Q_MEDIA_CATALOG_NUMBER mcn; + CDROM_SUB_Q_DATA_FORMAT q_data_format; + + memset( &mcn, 0, sizeof(mcn) ); + + q_data_format.Format = CDIO_SUBCHANNEL_MEDIA_CATALOG; + + q_data_format.Track=1; + + if( DeviceIoControl( env->h_device_handle, + IOCTL_CDROM_READ_Q_CHANNEL, + &q_data_format, sizeof(q_data_format), + &mcn, sizeof(mcn), + &dwBytesReturned, NULL ) == 0 ) { + cdio_warn( "could not read Q Channel at track %d", 1); + } else if (mcn.Mcval) + return strdup(mcn.MediaCatalog); + return NULL; +} + +/*! + Get the format (XA, DATA, AUDIO) of a track. +*/ +track_format_t +get_track_format_win32ioctl(const _img_private_t *env, track_t i_track) +{ + /* This is pretty much copied from the "badly broken" cdrom_count_tracks + in linux/cdrom.c. + */ + + if (env->tocent[i_track - env->gen.i_first_track].Control & 0x04) { + if (env->tocent[i_track - env->gen.i_first_track].Format == 0x10) + return TRACK_FORMAT_CDI; + else if (env->tocent[i_track - env->gen.i_first_track].Format == 0x20) + return TRACK_FORMAT_XA; + else + return TRACK_FORMAT_DATA; + } else + return TRACK_FORMAT_AUDIO; +} + +#endif /*HAVE_WIN32_CDROM*/ diff --git a/src/input/vcd/libcdio/Makefile.am b/src/input/vcd/libcdio/Makefile.am index 134397e30..84bdaabd3 100644 --- a/src/input/vcd/libcdio/Makefile.am +++ b/src/input/vcd/libcdio/Makefile.am @@ -5,29 +5,45 @@ SUBDIRS = cdio MSWindows image INCLUDES = $(LIBCDIO_CFLAGS) -I$(top_srcdir)/include -I$(top_srcdir)/lib libcdio_SRCS = \ - image/bincue.c \ - image/nrg.c \ - MSWindows/aspi32.c \ - MSWindows/aspi32.h \ - MSWindows/ioctl.c \ - MSWindows/win32.c \ - MSWindows/win32.h \ _cdio_bsdi.c \ - _cdio_freebsd.c \ _cdio_generic.c \ _cdio_linux.c \ _cdio_osx.c \ _cdio_stdio.c \ + _cdio_stdio.h \ _cdio_stream.c \ + _cdio_stream.h \ _cdio_sunos.c \ - cdio.c \ cd_types.c \ + cdio.c \ + cdtext.c \ + cdtext_private.h \ ds.c \ + FreeBSD/freebsd.c \ + FreeBSD/freebsd.h \ + FreeBSD/freebsd_cam.c \ + FreeBSD/freebsd_ioctl.c \ + generic.h \ + image.h \ + image/bincue.c \ + image/cdrdao.c \ + image_common.h \ + image/nrg.c \ + image/nrg.h \ + MSWindows/aspi32.c \ + MSWindows/aspi32.h \ + MSWindows/win32_ioctl.c \ + MSWindows/win32.c \ + MSWindows/win32.h \ logging.c \ + scsi_mmc.c \ + scsi_mmc_private.h \ sector.c \ util.c + libiso9660_SRCS = \ iso9660.c \ + iso9660_private.h \ iso9660_fs.c \ xa.c @@ -45,12 +61,9 @@ endif endif noinst_HEADERS = \ - bytesex_asm.h \ cdio_assert.h \ _cdio_stdio.h \ - ds.h \ scsi_mmc.h \ - bytesex.h \ cdio_private.h \ _cdio_stream.h \ iso9660_private.h diff --git a/src/input/vcd/libcdio/_cdio_bsdi.c b/src/input/vcd/libcdio/_cdio_bsdi.c index 7fd60a9d9..aef535752 100644 --- a/src/input/vcd/libcdio/_cdio_bsdi.c +++ b/src/input/vcd/libcdio/_cdio_bsdi.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_bsdi.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: _cdio_bsdi.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $ Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com> @@ -27,8 +27,9 @@ # include "config.h" #endif -static const char _rcsid[] = "$Id: _cdio_bsdi.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: _cdio_bsdi.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $"; +#include <cdio/logging.h> #include <cdio/sector.h> #include <cdio/util.h> #include "cdio_assert.h" @@ -54,31 +55,109 @@ static const char _rcsid[] = "$Id: _cdio_bsdi.c,v 1.2 2004/04/11 12:20:31 miguel #include <sys/stat.h> #include <sys/types.h> #include <sys/ioctl.h> +#include </sys/dev/scsi/scsi.h> +#include </sys/dev/scsi/scsi_ioctl.h> +#include "cdtext_private.h" -#define TOTAL_TRACKS (_obj->tochdr.cdth_trk1) -#define FIRST_TRACK_NUM (_obj->tochdr.cdth_trk0) +typedef enum { + _AM_NONE, + _AM_IOCTL, +} access_mode_t; typedef struct { /* Things common to all drivers like this. This must be first. */ generic_img_private_t gen; - enum { - _AM_NONE, - _AM_IOCTL, - } access_mode; - - char *source_name; - - bool init; + access_mode_t access_mode; + /* Some of the more OS specific things. */ /* Track information */ - bool toc_init; /* if true, info below is valid. */ struct cdrom_tochdr tochdr; - struct cdrom_tocentry tocent[100]; /* entry info for each track */ + struct cdrom_tocentry tocent[CDIO_CD_MAX_TRACKS+1]; } _img_private_t; +/* Define the Cdrom Generic Command structure */ +typedef struct cgc +{ + scsi_mmc_cdb_t cdb; + u_char *buf; + int buflen; + int rw; + unsigned int timeout; + scsi_user_sense_t *sus; +} cgc_t; + + +/* + This code adapted from Steven M. Schultz's libdvd +*/ +static int +run_scsi_cmd_bsdi(const void *p_user_data, unsigned int i_timeout_ms, + unsigned int i_cdb, const scsi_mmc_cdb_t *p_cdb, + scsi_mmc_direction_t e_direction, + unsigned int i_buf, /*in/out*/ void *p_buf ) +{ + const _img_private_t *p_env = p_user_data; + int i_status, i_asc; + struct scsi_user_cdb suc; + struct scsi_sense *sp; + + again: + suc.suc_flags = SCSI_MMC_DATA_READ == e_direction ? + SUC_READ : SUC_WRITE; + suc.suc_cdblen = i_cdb; + memcpy(suc.suc_cdb, p_cdb, i_cdb); + suc.suc_data = p_buf; + suc.suc_datalen = i_buf; + suc.suc_timeout = msecs2secs(i_timeout_ms); + if (ioctl(p_env->gen.fd, SCSIRAWCDB, &suc) == -1) + return(errno); + i_status = suc.suc_sus.sus_status; + +#if 0 + /* + * If the device returns a scsi sense error and debugging is enabled print + * some hopefully useful information on stderr. + */ + if (i_status && debug) + { + unsigned char *cp; + int i; + cp = suc.suc_sus.sus_sense; + fprintf(stderr,"i_status = %x cdb =", + i_status); + for (i = 0; i < cdblen; i++) + fprintf(stderr, " %x", cgc->cdb[i]); + fprintf(stderr, "\nsense ="); + for (i = 0; i < 16; i++) + fprintf(stderr, " %x", cp[i]); + fprintf(stderr, "\n"); + } +#endif + + /* + * HACK! Some drives return a silly "medium changed" on the first + * command AND a non-zero i_status which gets turned into a fatal + * (EIO) error even though the operation was a success. Retrying + * the operation clears the media changed status and gets the + * answer. */ + + sp = (struct scsi_sense *)&suc.suc_sus.sus_sense; + i_asc = XSENSE_ASC(sp); + if (i_status == STS_CHECKCOND && i_asc == 0x28) + goto again; +#if 0 + if (cgc->sus) + memcpy(cgc->sus, &suc.suc_sus, sizeof (struct scsi_user_sense)); +#endif + + return(i_status); +} + + + /* Check a drive to see if it is a CD-ROM Return 1 if a CD-ROM. 0 if it exists but isn't a CD-ROM drive and -1 if no device exists . @@ -119,68 +198,68 @@ cdio_is_cdrom(char *drive, char *mnttype) Initialize CD device. */ static bool -_cdio_init (_img_private_t *_obj) +_cdio_init (_img_private_t *p_env) { - if (_obj->gen.init) { - cdio_error ("init called more than once"); + if (p_env->gen.init) { + cdio_warn ("init called more than once"); return false; } - _obj->gen.fd = open (_obj->source_name, O_RDONLY, 0); + p_env->gen.fd = open (p_env->gen.source_name, O_RDONLY, 0); - if (_obj->gen.fd < 0) + if (p_env->gen.fd < 0) { - cdio_error ("open (%s): %s", _obj->source_name, strerror (errno)); + cdio_warn ("open (%s): %s", p_env->gen.source_name, strerror (errno)); return false; } - _obj->gen.init = true; - _obj->toc_init = false; + p_env->gen.init = true; + p_env->gen.toc_init = false; return true; } /* Read audio sectors */ static int -_read_audio_sectors (void *env, void *data, lsn_t lsn, - unsigned int nblocks) +_read_audio_sectors_bsdi (void *user_data, void *data, lsn_t lsn, + unsigned int nblocks) { char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; struct cdrom_msf *msf = (struct cdrom_msf *) &buf; msf_t _msf; - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; cdio_lba_to_msf (cdio_lsn_to_lba(lsn), &_msf); - msf->cdmsf_min0 = from_bcd8(_msf.m); - msf->cdmsf_sec0 = from_bcd8(_msf.s); - msf->cdmsf_frame0 = from_bcd8(_msf.f); + msf->cdmsf_min0 = cdio_from_bcd8(_msf.m); + msf->cdmsf_sec0 = cdio_from_bcd8(_msf.s); + msf->cdmsf_frame0 = cdio_from_bcd8(_msf.f); - if (_obj->gen.ioctls_debugged == 75) + if (p_env->gen.ioctls_debugged == 75) cdio_debug ("only displaying every 75th ioctl from now on"); - if (_obj->gen.ioctls_debugged == 30 * 75) + if (p_env->gen.ioctls_debugged == 30 * 75) cdio_debug ("only displaying every 30*75th ioctl from now on"); - if (_obj->gen.ioctls_debugged < 75 - || (_obj->gen.ioctls_debugged < (30 * 75) - && _obj->gen.ioctls_debugged % 75 == 0) - || _obj->gen.ioctls_debugged % (30 * 75) == 0) + if (p_env->gen.ioctls_debugged < 75 + || (p_env->gen.ioctls_debugged < (30 * 75) + && p_env->gen.ioctls_debugged % 75 == 0) + || p_env->gen.ioctls_debugged % (30 * 75) == 0) cdio_debug ("reading %2.2d:%2.2d:%2.2d", msf->cdmsf_min0, msf->cdmsf_sec0, msf->cdmsf_frame0); - _obj->gen.ioctls_debugged++; + p_env->gen.ioctls_debugged++; - switch (_obj->access_mode) { + switch (p_env->access_mode) { case _AM_NONE: - cdio_error ("no way to read audio"); + cdio_warn ("no way to read audio"); return 1; break; case _AM_IOCTL: { unsigned int i; for (i=0; i < nblocks; i++) { - if (ioctl (_obj->gen.fd, CDROMREADRAW, &buf) == -1) { + if (ioctl (p_env->gen.fd, CDROMREADRAW, &buf) == -1) { perror ("ioctl()"); return 1; /* exit (EXIT_FAILURE); */ @@ -200,19 +279,15 @@ _read_audio_sectors (void *env, void *data, lsn_t lsn, from lsn. Returns 0 if no error. */ static int -_cdio_read_mode1_sector (void *env, void *data, lsn_t lsn, +_read_mode1_sector_bsdi (void *user_data, void *data, lsn_t lsn, bool b_form2) { - char buf[M2RAW_SECTOR_SIZE] = { 0, }; #if FIXED + char buf[M2RAW_SECTOR_SIZE] = { 0, }; do something here. #else - if (0 > cdio_generic_lseek(env, CDIO_CD_FRAMESIZE*lsn, SEEK_SET)) - return -1; - if (0 > cdio_generic_read(env, buf, CDIO_CD_FRAMESIZE)) - return -1; - memcpy (data, buf, b_form2 ? M2RAW_SECTOR_SIZE: CDIO_CD_FRAMESIZE); + return cdio_generic_read_form1_sector(user_data, data, lsn); #endif return 0; } @@ -223,16 +298,16 @@ _cdio_read_mode1_sector (void *env, void *data, lsn_t lsn, Returns 0 if no error. */ static int -_cdio_read_mode1_sectors (void *env, void *data, lsn_t lsn, +_read_mode1_sectors_bsdi (void *user_data, void *data, lsn_t lsn, bool b_form2, unsigned int nblocks) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; unsigned int i; int retval; unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE; for (i = 0; i < nblocks; i++) { - if ( (retval = _cdio_read_mode1_sector (_obj, + if ( (retval = _read_mode1_sector_bsdi (p_env, ((char *)data) + (blocksize * i), lsn + i, b_form2)) ) return retval; @@ -245,44 +320,44 @@ _cdio_read_mode1_sectors (void *env, void *data, lsn_t lsn, from lsn. Returns 0 if no error. */ static int -_cdio_read_mode2_sector (void *env, void *data, lsn_t lsn, +_read_mode2_sector_bsdi (void *user_data, void *data, lsn_t lsn, bool b_form2) { char buf[M2RAW_SECTOR_SIZE] = { 0, }; struct cdrom_msf *msf = (struct cdrom_msf *) &buf; msf_t _msf; - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; cdio_lba_to_msf (cdio_lsn_to_lba(lsn), &_msf); - msf->cdmsf_min0 = from_bcd8(_msf.m); - msf->cdmsf_sec0 = from_bcd8(_msf.s); - msf->cdmsf_frame0 = from_bcd8(_msf.f); + msf->cdmsf_min0 = cdio_from_bcd8(_msf.m); + msf->cdmsf_sec0 = cdio_from_bcd8(_msf.s); + msf->cdmsf_frame0 = cdio_from_bcd8(_msf.f); - if (_obj->gen.ioctls_debugged == 75) + if (p_env->gen.ioctls_debugged == 75) cdio_debug ("only displaying every 75th ioctl from now on"); - if (_obj->gen.ioctls_debugged == 30 * 75) + if (p_env->gen.ioctls_debugged == 30 * 75) cdio_debug ("only displaying every 30*75th ioctl from now on"); - if (_obj->gen.ioctls_debugged < 75 - || (_obj->gen.ioctls_debugged < (30 * 75) - && _obj->gen.ioctls_debugged % 75 == 0) - || _obj->gen.ioctls_debugged % (30 * 75) == 0) + if (p_env->gen.ioctls_debugged < 75 + || (p_env->gen.ioctls_debugged < (30 * 75) + && p_env->gen.ioctls_debugged % 75 == 0) + || p_env->gen.ioctls_debugged % (30 * 75) == 0) cdio_debug ("reading %2.2d:%2.2d:%2.2d", msf->cdmsf_min0, msf->cdmsf_sec0, msf->cdmsf_frame0); - _obj->gen.ioctls_debugged++; + p_env->gen.ioctls_debugged++; - switch (_obj->access_mode) + switch (p_env->access_mode) { case _AM_NONE: - cdio_error ("no way to read mode2"); + cdio_warn ("no way to read mode2"); return 1; break; case _AM_IOCTL: - if (ioctl (_obj->gen.fd, CDROMREADMODE2, &buf) == -1) + if (ioctl (p_env->gen.fd, CDROMREADMODE2, &buf) == -1) { perror ("ioctl()"); return 1; @@ -305,27 +380,20 @@ _cdio_read_mode2_sector (void *env, void *data, lsn_t lsn, Returns 0 if no error. */ static int -_cdio_read_mode2_sectors (void *env, void *data, lsn_t lsn, +_read_mode2_sectors_bsdi (void *user_data, void *data, lsn_t lsn, bool b_form2, unsigned int nblocks) { - _img_private_t *_obj = env; - int i; - int retval; + _img_private_t *p_env = user_data; + unsigned int i; + unsigned int i_blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE; + /* For each frame, pick out the data part we need */ for (i = 0; i < nblocks; i++) { - if (b_form2) { - if ( (retval = _cdio_read_mode2_sector (_obj, - ((char *)data) + (M2RAW_SECTOR_SIZE * i), - lsn + i, true)) ) - return retval; - } else { - char buf[M2RAW_SECTOR_SIZE] = { 0, }; - if ( (retval = _cdio_read_mode2_sector (_obj, buf, lsn + i, true)) ) - return retval; - - memcpy (((char *)data) + (CDIO_CD_FRAMESIZE * i), - buf + CDIO_CD_SUBHEADER_SIZE, CDIO_CD_FRAMESIZE); - } + int retval = _read_mode2_sector_bsdi(p_env, + ((char *)data) + + (i_blocksize * i), + lsn + i, b_form2); + if (retval) return retval; } return 0; } @@ -334,16 +402,16 @@ _cdio_read_mode2_sectors (void *env, void *data, lsn_t lsn, Return the size of the CD in logical block address (LBA) units. */ static uint32_t -_cdio_stat_size (void *env) +_stat_size_bsdi (void *user_data) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; struct cdrom_tocentry tocent; uint32_t size; tocent.cdte_track = CDIO_CDROM_LEADOUT_TRACK; tocent.cdte_format = CDROM_LBA; - if (ioctl (_obj->gen.fd, CDROMREADTOCENTRY, &tocent) == -1) + if (ioctl (p_env->gen.fd, CDROMREADTOCENTRY, &tocent) == -1) { perror ("ioctl(CDROMREADTOCENTRY)"); exit (EXIT_FAILURE); @@ -358,25 +426,25 @@ _cdio_stat_size (void *env) Set the key "arg" to "value" in source device. */ static int -_cdio_set_arg (void *env, const char key[], const char value[]) +_set_arg_bsdi (void *user_data, const char key[], const char value[]) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; if (!strcmp (key, "source")) { if (!value) return -2; - free (_obj->source_name); + free (p_env->gen.source_name); - _obj->source_name = strdup (value); + p_env->gen.source_name = strdup (value); } else if (!strcmp (key, "access-mode")) { if (!strcmp(value, "IOCTL")) - _obj->access_mode = _AM_IOCTL; + p_env->access_mode = _AM_IOCTL; else - cdio_error ("unknown access type: %s. ignored.", value); + cdio_warn ("unknown access type: %s. ignored.", value); } else return -1; @@ -389,29 +457,33 @@ _cdio_set_arg (void *env, const char key[], const char value[]) Return false if successful or true if an error. */ static bool -_cdio_read_toc (_img_private_t *_obj) +read_toc_bsdi (void *p_user_data) { + _img_private_t *p_env = p_user_data; int i; /* read TOC header */ - if ( ioctl(_obj->gen.fd, CDROMREADTOCHDR, &_obj->tochdr) == -1 ) { - cdio_error("%s: %s\n", + if ( ioctl(p_env->gen.fd, CDROMREADTOCHDR, &p_env->tochdr) == -1 ) { + cdio_warn("%s: %s\n", "error in ioctl CDROMREADTOCHDR", strerror(errno)); return false; } + p_env->gen.i_first_track = p_env->tochdr.cdth_trk0; + p_env->gen.i_tracks = p_env->tochdr.cdth_trk1; + /* read individual tracks */ - for (i= FIRST_TRACK_NUM; i<=TOTAL_TRACKS; i++) { - _obj->tocent[i-1].cdte_track = i; - _obj->tocent[i-1].cdte_format = CDROM_MSF; - if ( ioctl(_obj->gen.fd, CDROMREADTOCENTRY, &_obj->tocent[i-1]) == -1 ) { - cdio_error("%s %d: %s\n", + for (i= p_env->gen.i_first_track; i<=p_env->gen.i_tracks; i++) { + p_env->tocent[i-1].cdte_track = i; + p_env->tocent[i-1].cdte_format = CDROM_MSF; + if (ioctl(p_env->gen.fd, CDROMREADTOCENTRY, &p_env->tocent[i-1]) == -1) { + cdio_warn("%s %d: %s\n", "error in ioctl CDROMREADTOCENTRY for track", i, strerror(errno)); return false; } /**** - struct cdrom_msf0 *msf= &_obj->tocent[i-1].cdte_addr.msf; + struct cdrom_msf0 *msf= &p_env->tocent[i-1].cdte_addr.msf; fprintf (stdout, "--- track# %d (msf %2.2x:%2.2x:%2.2x)\n", i, msf->minute, msf->second, msf->frame); @@ -420,24 +492,25 @@ _cdio_read_toc (_img_private_t *_obj) } /* read the lead-out track */ - _obj->tocent[TOTAL_TRACKS].cdte_track = CDIO_CDROM_LEADOUT_TRACK; - _obj->tocent[TOTAL_TRACKS].cdte_format = CDROM_MSF; + p_env->tocent[p_env->gen.i_tracks].cdte_track = CDIO_CDROM_LEADOUT_TRACK; + p_env->tocent[p_env->gen.i_tracks].cdte_format = CDROM_MSF; - if (ioctl(_obj->gen.fd, CDROMREADTOCENTRY, - &_obj->tocent[TOTAL_TRACKS]) == -1 ) { - cdio_error("%s: %s\n", + if (ioctl(p_env->gen.fd, CDROMREADTOCENTRY, + &p_env->tocent[p_env->gen.i_tracks]) == -1 ) { + cdio_warn("%s: %s\n", "error in ioctl CDROMREADTOCENTRY for lead-out", strerror(errno)); return false; } /* - struct cdrom_msf0 *msf= &_obj->tocent[TOTAL_TRACKS].cdte_addr.msf; + struct cdrom_msf0 *msf= &p_env->tocent[p_env->gen.i_tracks].cdte_addr.msf; fprintf (stdout, "--- track# %d (msf %2.2x:%2.2x:%2.2x)\n", i, msf->minute, msf->second, msf->frame); */ + p_env->gen.toc_init = true; return true; } @@ -446,32 +519,32 @@ _cdio_read_toc (_img_private_t *_obj) also free obj. */ static int -_cdio_eject_media (void *env) { +_eject_media_bsdi (void *user_data) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; int ret=2; int status; int fd; - close(_obj->gen.fd); - _obj->gen.fd = -1; - if ((fd = open (_obj->source_name, O_RDONLY|O_NONBLOCK)) > -1) { + close(p_env->gen.fd); + p_env->gen.fd = -1; + if ((fd = open (p_env->gen.source_name, O_RDONLY|O_NONBLOCK)) > -1) { if((status = ioctl(fd, CDROM_DRIVE_STATUS, (void *) CDSL_CURRENT)) > 0) { switch(status) { case CDS_TRAY_OPEN: if((ret = ioctl(fd, CDROMCLOSETRAY, 0)) != 0) { - cdio_error ("ioctl CDROMCLOSETRAY failed: %s\n", strerror(errno)); + cdio_warn ("ioctl CDROMCLOSETRAY failed: %s\n", strerror(errno)); } break; case CDS_DISC_OK: if((ret = ioctl(fd, CDROMEJECT, 0)) != 0) { - cdio_error("ioctl CDROMEJECT failed: %s\n", strerror(errno)); + cdio_warn("ioctl CDROMEJECT failed: %s\n", strerror(errno)); } break; } ret=0; } else { - cdio_error ("CDROM_DRIVE_STATUS failed: %s\n", strerror(errno)); + cdio_warn ("CDROM_DRIVE_STATUS failed: %s\n", strerror(errno)); ret=1; } close(fd); @@ -483,14 +556,14 @@ _cdio_eject_media (void *env) { Return the value associated with the key "arg". */ static const char * -_cdio_get_arg (void *env, const char key[]) +_get_arg_bsdi (void *user_data, const char key[]) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; if (!strcmp (key, "source")) { - return _obj->source_name; + return p_env->gen.source_name; } else if (!strcmp (key, "access-mode")) { - switch (_obj->access_mode) { + switch (p_env->access_mode) { case _AM_IOCTL: return "ioctl"; case _AM_NONE: @@ -501,68 +574,42 @@ _cdio_get_arg (void *env, const char key[]) } /*! - Return the number of of the first track. - CDIO_INVALID_TRACK is returned on error. -*/ -static track_t -_cdio_get_first_track_num(void *env) -{ - _img_private_t *_obj = env; - - if (!_obj->toc_init) _cdio_read_toc (_obj) ; - - return FIRST_TRACK_NUM; -} - -/*! Return the media catalog number MCN. Note: string is malloc'd so caller should free() then returned string when done with it. */ static char * -_cdio_get_mcn (void *env) { +_get_mcn_bsdi (const void *user_data) { struct cdrom_mcn mcn; - _img_private_t *_obj = env; - if (ioctl(_obj->gen.fd, CDROM_GET_MCN, &mcn) != 0) + const _img_private_t *p_env = user_data; + if (ioctl(p_env->gen.fd, CDROM_GET_MCN, &mcn) != 0) return NULL; return strdup(mcn.medium_catalog_number); } -/*! - Return the number of tracks in the current medium. - CDIO_INVALID_TRACK is returned on error. -*/ -static track_t -_cdio_get_num_tracks(void *env) -{ - _img_private_t *_obj = env; - - if (!_obj->toc_init) _cdio_read_toc (_obj) ; - - return TOTAL_TRACKS; -} - /*! Get format of track. */ static track_format_t -_cdio_get_track_format(void *env, track_t track_num) +get_track_format_bsdi(void *user_data, track_t i_track) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; - if (!_obj->toc_init) _cdio_read_toc (_obj) ; + if (!p_env->gen.toc_init) read_toc_bsdi (p_env) ; - if (track_num > TOTAL_TRACKS || track_num == 0) + if (i_track > p_env->gen.i_tracks || i_track == 0) return TRACK_FORMAT_ERROR; + i_track -= p_env->gen.i_first_track; + /* This is pretty much copied from the "badly broken" cdrom_count_tracks in linux/cdrom.c. */ - if (_obj->tocent[track_num-1].cdte_ctrl & CDROM_DATA_TRACK) { - if (_obj->tocent[track_num-1].cdte_format == 0x10) + if (p_env->tocent[i_track].cdte_ctrl & CDROM_DATA_TRACK) { + if (p_env->tocent[i_track].cdte_format == CDIO_CDROM_CDI_TRACK) return TRACK_FORMAT_CDI; - else if (_obj->tocent[track_num-1].cdte_format == 0x20) + else if (p_env->tocent[i_track].cdte_format == CDIO_CDROM_XA_TRACK) return TRACK_FORMAT_XA; else return TRACK_FORMAT_DATA; @@ -580,48 +627,52 @@ _cdio_get_track_format(void *env, track_t track_num) FIXME: there's gotta be a better design for this and get_track_format? */ static bool -_cdio_get_track_green(void *env, track_t track_num) +_get_track_green_bsdi(void *user_data, track_t i_track) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; - if (!_obj->toc_init) _cdio_read_toc (_obj) ; + if (!p_env->gen.toc_init) read_toc_bsdi (p_env) ; - if (track_num == CDIO_CDROM_LEADOUT_TRACK) track_num = TOTAL_TRACKS+1; + if (i_track == CDIO_CDROM_LEADOUT_TRACK) i_track = p_env->gen.i_tracks+1; - if (track_num > TOTAL_TRACKS+1 || track_num == 0) + if (i_track > p_env->gen.i_tracks+1 || i_track == 0) return false; /* FIXME: Dunno if this is the right way, but it's what I was using in cdinfo for a while. */ - return ((_obj->tocent[track_num-1].cdte_ctrl & 2) != 0); + return ((p_env->tocent[i_track-1].cdte_ctrl & 2) != 0); } /*! Return the starting MSF (minutes/secs/frames) for track number - track_num in obj. Track numbers start at 1. + i_track in obj. Track numbers start at 1. The "leadout" track is specified either by - using track_num LEADOUT_TRACK or the total tracks+1. + using i_track LEADOUT_TRACK or the total tracks+1. False is returned if there is no track entry. */ static bool -_cdio_get_track_msf(void *env, track_t track_num, msf_t *msf) +_get_track_msf_bsdi(void *user_data, track_t i_track, msf_t *msf) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; if (NULL == msf) return false; - if (!_obj->toc_init) _cdio_read_toc (_obj) ; + if (!p_env->gen.toc_init) read_toc_bsdi (p_env) ; - if (track_num == CDIO_CDROM_LEADOUT_TRACK) track_num = TOTAL_TRACKS+1; + if (i_track == CDIO_CDROM_LEADOUT_TRACK) i_track = p_env->gen.i_tracks+1; - if (track_num > TOTAL_TRACKS+1 || track_num == 0) { + if (i_track > p_env->gen.i_tracks+1 || i_track == 0) { return false; - } else { - struct cdrom_msf0 *msf0= &_obj->tocent[track_num-1].cdte_addr.msf; - msf->m = to_bcd8(msf0->minute); - msf->s = to_bcd8(msf0->second); - msf->f = to_bcd8(msf0->frame); + } + + i_track -= p_env->gen.i_first_track; + + { + struct cdrom_msf0 *msf0= &p_env->tocent[i_track].cdte_addr.msf; + msf->m = cdio_to_bcd8(msf0->minute); + msf->s = cdio_to_bcd8(msf0->second); + msf->f = cdio_to_bcd8(msf0->frame); return true; } } @@ -690,46 +741,85 @@ cdio_get_default_device_bsdi(void) ones to set that up. */ CdIo * -cdio_open_bsdi (const char *source_name) +cdio_open_am_bsdi (const char *psz_source_name, const char *psz_access_mode) +{ + if (psz_access_mode != NULL) + cdio_warn ("there is only one access mode for bsdi. Arg %s ignored", + psz_access_mode); + return cdio_open_bsdi(psz_source_name); +} + + +/*! + Initialization routine. This is the only thing that doesn't + get called via a function pointer. In fact *we* are the + ones to set that up. + */ +CdIo * +cdio_open_bsdi (const char *psz_orig_source) { #ifdef HAVE_BSDI_CDROM CdIo *ret; _img_private_t *_data; + char *psz_source; cdio_funcs _funcs = { - .eject_media = _cdio_eject_media, + .eject_media = _eject_media_bsdi, .free = cdio_generic_free, - .get_arg = _cdio_get_arg, + .get_arg = _get_arg_bsdi, + .get_cdtext = get_cdtext_generic, .get_default_device = cdio_get_default_device_bsdi, .get_devices = cdio_get_devices_bsdi, - .get_first_track_num= _cdio_get_first_track_num, - .get_mcn = _cdio_get_mcn, - .get_num_tracks = _cdio_get_num_tracks, - .get_track_format = _cdio_get_track_format, - .get_track_green = _cdio_get_track_green, + .get_drive_cap = scsi_mmc_get_drive_cap_generic, + .get_discmode = get_discmode_generic, + .get_first_track_num= get_first_track_num_generic, + .get_hwinfo = NULL, + .get_mcn = _get_mcn_bsdi, + .get_num_tracks = get_num_tracks_generic, + .get_track_format = get_track_format_bsdi, + .get_track_green = _get_track_green_bsdi, .get_track_lba = NULL, /* This could be implemented if need be. */ - .get_track_msf = _cdio_get_track_msf, + .get_track_msf = _get_track_msf_bsdi, .lseek = cdio_generic_lseek, .read = cdio_generic_read, - .read_audio_sectors = _read_audio_sectors, - .read_mode1_sector = _cdio_read_mode1_sector, - .read_mode1_sectors = _cdio_read_mode1_sectors, - .read_mode2_sector = _cdio_read_mode2_sector, - .read_mode2_sectors = _cdio_read_mode2_sectors, - .set_arg = _cdio_set_arg, - .stat_size = _cdio_stat_size + .read_audio_sectors = _read_audio_sectors_bsdi, + .read_mode1_sector = _read_mode1_sector_bsdi, + .read_mode1_sectors = _read_mode1_sectors_bsdi, + .read_mode2_sector = _read_mode2_sector_bsdi, + .read_mode2_sectors = _read_mode2_sectors_bsdi, + .read_toc = &read_toc_bsdi, + .run_scsi_mmc_cmd = &run_scsi_cmd_bsdi, + .set_arg = _set_arg_bsdi, + .stat_size = _stat_size_bsdi }; _data = _cdio_malloc (sizeof (_img_private_t)); _data->access_mode = _AM_IOCTL; _data->gen.init = false; _data->gen.fd = -1; + _data->gen.toc_init = false; + _data->gen.b_cdtext_init = false; + _data->gen.b_cdtext_error = false; + + if (NULL == psz_orig_source) { + psz_source=cdio_get_default_device_linux(); + if (NULL == psz_source) return NULL; + _set_arg_bsdi(_data, "source", psz_source); + free(psz_source); + } else { + if (cdio_is_device_generic(psz_orig_source)) + _set_arg_bsdi(_data, "source", psz_orig_source); + else { + /* The below would be okay if all device drivers worked this way. */ +#if 0 + cdio_info ("source %s is not a device", psz_orig_source); +#endif + return NULL; + } + } - _cdio_set_arg(_data, "source", (NULL == source_name) - ? DEFAULT_CDIO_DEVICE: source_name); - - ret = cdio_new (_data, &_funcs); + ret = cdio_new ( (void *) _data, &_funcs); if (ret == NULL) return NULL; if (_cdio_init(_data)) @@ -754,4 +844,3 @@ cdio_have_bsdi (void) return false; #endif /* HAVE_BSDI_CDROM */ } - diff --git a/src/input/vcd/libcdio/_cdio_freebsd.c b/src/input/vcd/libcdio/_cdio_freebsd.c deleted file mode 100644 index 0aae6a6a8..000000000 --- a/src/input/vcd/libcdio/_cdio_freebsd.c +++ /dev/null @@ -1,635 +0,0 @@ -/* - $Id: _cdio_freebsd.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ - - Copyright (C) 2003 Rocky Bernstein <rocky@panix.com> - - 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* This file contains FreeBSD-specific code and implements low-level - control of the CD drive. Culled I think from xine's or mplayer's - FreeBSD code. -*/ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -static const char _rcsid[] = "$Id: _cdio_freebsd.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $"; - -#include <cdio/sector.h> -#include <cdio/util.h> -#include "cdio_assert.h" -#include "cdio_private.h" - -/* Is this the right default? */ -#define DEFAULT_CDIO_DEVICE "/dev/acd0c" - -#include <string.h> - -#ifdef HAVE_FREEBSD_CDROM - -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <unistd.h> -#include <fcntl.h> - -#ifdef HAVE_SYS_CDIO_H -# include <sys/cdio.h> -#endif -#include <sys/cdrio.h> - -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/ioctl.h> - -#define TOTAL_TRACKS ( _obj->tochdr.ending_track \ - - _obj->tochdr.starting_track + 1) -#define FIRST_TRACK_NUM (_obj->tochdr.starting_track) - -typedef struct { - /* Things common to all drivers like this. - This must be first. */ - generic_img_private_t gen; - - enum { - _AM_NONE, - _AM_IOCTL, - } access_mode; - - char *source_name; - - bool init; - - /* Track information */ - bool toc_init; /* if true, info below is valid. */ - struct ioc_toc_header tochdr; - struct cd_toc_entry tocent[100]; /* entry info for each track */ - -} _img_private_t; - -/* Check a drive to see if it is a CD-ROM - Return 1 if a CD-ROM. 0 if it exists but isn't a CD-ROM drive - and -1 if no device exists . -*/ -static bool -cdio_is_cdrom(char *drive, char *mnttype) -{ - bool is_cd=false; - int cdfd; - struct ioc_toc_header tochdr; - - /* If it doesn't exist, return -1 */ - if ( !cdio_is_device_quiet_generic(drive) ) { - return(false); - } - - /* If it does exist, verify that it's an available CD-ROM */ - cdfd = open(drive, (O_RDONLY|O_EXCL|O_NONBLOCK), 0); - - /* Should we want to test the condition in more detail: - ENOENT is the error for /dev/xxxxx does not exist; - ENODEV means there's no drive present. */ - - if ( cdfd >= 0 ) { - if ( ioctl(cdfd, CDIOREADTOCHEADER, &tochdr) != -1 ) { - is_cd = true; - } - close(cdfd); - } - /* Even if we can't read it, it might be mounted */ - else if ( mnttype && (strcmp(mnttype, "iso9660") == 0) ) { - is_cd = true; - } - return(is_cd); -} - -static int -_read_mode2 (int fd, void *buf, lba_t lba, unsigned int nblocks, - bool _workaround) -{ - unsigned int l = 0; - int retval = 0; - - while (nblocks > 0) - { - const unsigned int nblocks2 = (nblocks > 25) ? 25 : nblocks; - void *buf2 = ((char *)buf ) + (l * M2RAW_SECTOR_SIZE); - - retval |= _read_mode2 (fd, buf2, lba + l, nblocks2, _workaround); - - if (retval) - break; - - nblocks -= nblocks2; - l += nblocks2; - } - - return retval; -} - -/*! - Reads a single mode2 sector from cd device into data starting from lsn. - Returns 0 if no error. - */ -static int -_cdio_read_audio_sectors (void *env, void *data, lsn_t lsn, - unsigned int nblocks) -{ - _img_private_t *_obj = env; - unsigned char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; - struct ioc_read_audio cdda; - - cdda.address.lba = lsn; - cdda.buffer = buf; - cdda.nframes = nblocks; - cdda.address_format = CD_LBA_FORMAT; - - /* read a frame */ - if(ioctl(_obj->gen.fd, CDIOCREADAUDIO, &cdda) < 0) { - perror("CDIOCREADAUDIO"); - return 1; - } - memcpy (data, buf, CDIO_CD_FRAMESIZE_RAW); - - return 0; -} - -/*! - Reads a single mode2 sector from cd device into data starting - from lsn. Returns 0 if no error. - */ -static int -_cdio_read_mode2_sector (void *env, void *data, lsn_t lsn, - bool mode2_form2) -{ - char buf[M2RAW_SECTOR_SIZE] = { 0, }; - int retval; - - if ( (retval = _cdio_read_audio_sectors (env, buf, lsn, 1)) ) - return retval; - - if (mode2_form2) - memcpy (data, buf + CDIO_CD_XA_SYNC_HEADER, M2RAW_SECTOR_SIZE); - else - memcpy (data, buf + CDIO_CD_XA_SYNC_HEADER, CDIO_CD_FRAMESIZE); - - return 0; -} - -/*! - Reads nblocks of mode2 sectors from cd device into data starting - from lsn. - Returns 0 if no error. - */ -static int -_cdio_read_mode2_sectors (void *env, void *data, lsn_t lsn, - bool mode2_form2, unsigned int nblocks) -{ - _img_private_t *_obj = env; - int i; - int retval; - - for (i = 0; i < nblocks; i++) { - if (mode2_form2) { - if ( (retval = _cdio_read_mode2_sector (_obj, - ((char *)data) + (M2RAW_SECTOR_SIZE * i), - lsn + i, true)) ) - return retval; - } else { - char buf[M2RAW_SECTOR_SIZE] = { 0, }; - if ( (retval = _cdio_read_mode2_sector (_obj, buf, lsn + i, true)) ) - return retval; - - memcpy (((char *)data) + (CDIO_CD_FRAMESIZE * i), - buf + CDIO_CD_SUBHEADER_SIZE, CDIO_CD_FRAMESIZE); - } - } - return 0; -} - -/*! - Return the size of the CD in logical block address (LBA) units. - */ -static uint32_t -_cdio_stat_size (void *env) -{ - _img_private_t *_obj = env; - - struct ioc_read_toc_single_entry tocent; - uint32_t size; - - tocent.track = CDIO_CDROM_LEADOUT_TRACK; - tocent.address_format = CD_LBA_FORMAT; - if (ioctl (_obj->gen.fd, CDIOREADTOCENTRY, &tocent) == -1) - { - perror ("ioctl(CDROMREADTOCENTRY)"); - exit (EXIT_FAILURE); - } - - size = tocent.entry.addr.lba; - - return size; -} - -/*! - Set the key "arg" to "value" in source device. -*/ -static int -_cdio_set_arg (void *env, const char key[], const char value[]) -{ - _img_private_t *_obj = env; - - if (!strcmp (key, "source")) - { - if (!value) - return -2; - - free (_obj->gen.source_name); - - _obj->gen.source_name = strdup (value); - } - else if (!strcmp (key, "access-mode")) - { - if (!strcmp(value, "IOCTL")) - _obj->access_mode = _AM_IOCTL; - else - cdio_error ("unknown access type: %s. ignored.", value); - } - else - return -1; - - return 0; -} - -/*! - Read and cache the CD's Track Table of Contents and track info. - Return false if successful or true if an error. -*/ -static bool -_cdio_read_toc (_img_private_t *_obj) -{ - int i; - struct ioc_read_toc_entry te; - - /* read TOC header */ - if ( ioctl(_obj->gen.fd, CDIOREADTOCHEADER, &_obj->tochdr) == -1 ) { - cdio_error("error in ioctl(CDIOREADTOCHEADER): %s\n", strerror(errno)); - return false; - } - - te.address_format = CD_LBA_FORMAT; - te.starting_track = 0; - te.data_len = (TOTAL_TRACKS+1) * sizeof(struct cd_toc_entry); - - te.data = _obj->tocent; - - if ( ioctl(_obj->gen.fd, CDIOREADTOCENTRYS, &te) == -1 ) { - cdio_error("%s %d: %s\n", - "error in ioctl CDROMREADTOCENTRYS for track", - i, strerror(errno)); - return false; - } - - return true; -} - -/*! - Eject media. Return 1 if successful, 0 otherwise. - */ -static int -_cdio_eject_media (void *env) { - - _img_private_t *_obj = env; - int ret=2; - int fd; - - if ((fd = open(_obj->gen.source_name, O_RDONLY|O_NONBLOCK)) > -1) { - ret = 1; - if (ioctl(fd, CDIOCALLOW) == -1) { - cdio_error("ioctl(fd, CDIOCALLOW) failed: %s\n", strerror(errno)); - } else if (ioctl(fd, CDIOCEJECT) == -1) { - cdio_error("ioctl(CDIOCEJECT) failed: %s\n", strerror(errno)); - } else { - ret = 0; - } - close(fd); - } - - return ret; -} - -/*! - Return the value associated with the key "arg". -*/ -static const char * -_cdio_get_arg (void *env, const char key[]) -{ - _img_private_t *_obj = env; - - if (!strcmp (key, "source")) { - return _obj->gen.source_name; - } else if (!strcmp (key, "access-mode")) { - switch (_obj->access_mode) { - case _AM_IOCTL: - return "ioctl"; - case _AM_NONE: - return "no access method"; - } - } - return NULL; -} - -/*! - Return the number of of the first track. - CDIO_INVALID_TRACK is returned on error. -*/ -static track_t -_cdio_get_first_track_num(void *env) -{ - _img_private_t *_obj = env; - - if (!_obj->toc_init) _cdio_read_toc (_obj) ; - - return FIRST_TRACK_NUM; -} - -/*! - Return the media catalog number MCN. - - Note: string is malloc'd so caller should free() then returned - string when done with it. - - FIXME: This is just a guess. - - */ -static char * -_cdio_get_mcn (void *env) { - - _img_private_t *_obj = env; - struct ioc_read_subchannel subchannel; - struct cd_sub_channel_info subchannel_info; - - subchannel.address_format = CD_LBA_FORMAT; - subchannel.data_format = CD_MEDIA_CATALOG; - subchannel.track = 0; - subchannel.data_len = 1; - subchannel.data = &subchannel_info; - - if(ioctl(_obj->gen.fd, CDIOCREADSUBCHANNEL, &subchannel) < 0) { - perror("CDIOCREADSUBCHANNEL"); - return NULL; - } - - /* Probably need a loop over tracks rather than give up if we - can't find in track 0. - */ - if (subchannel_info.what.media_catalog.mc_valid) - return strdup(subchannel_info.what.media_catalog.mc_number); - else - return NULL; -} - -/*! - Return the number of tracks in the current medium. - CDIO_INVALID_TRACK is returned on error. -*/ -static track_t -_cdio_get_num_tracks(void *env) -{ - _img_private_t *_obj = env; - - if (!_obj->toc_init) _cdio_read_toc (_obj) ; - - return TOTAL_TRACKS; -} - -/*! - Get format of track. - - FIXME: We're just guessing this from the GNU/Linux code. - -*/ -static track_format_t -_cdio_get_track_format(void *env, track_t track_num) -{ - _img_private_t *_obj = env; - struct ioc_read_subchannel subchannel; - struct cd_sub_channel_info subchannel_info; - - subchannel.address_format = CD_LBA_FORMAT; - subchannel.data_format = CD_CURRENT_POSITION; - subchannel.track = track_num; - subchannel.data_len = 1; - subchannel.data = &subchannel_info; - - if(ioctl(_obj->gen.fd, CDIOCREADSUBCHANNEL, &subchannel) < 0) { - perror("CDIOCREADSUBCHANNEL"); - return 1; - } - - if (subchannel_info.what.position.control == 0x04) { - if (subchannel_info.what.position.data_format == 0x10) - return TRACK_FORMAT_CDI; - else if (subchannel_info.what.position.data_format == 0x20) - return TRACK_FORMAT_XA; - else - return TRACK_FORMAT_DATA; - } else - return TRACK_FORMAT_AUDIO; -} - -/*! - Return true if we have XA data (green, mode2 form1) or - XA data (green, mode2 form2). That is track begins: - sync - header - subheader - 12 4 - 8 - - FIXME: there's gotta be a better design for this and get_track_format? -*/ -static bool -_cdio_get_track_green(void *env, track_t track_num) -{ - _img_private_t *_obj = env; - struct ioc_read_subchannel subchannel; - struct cd_sub_channel_info subchannel_info; - - subchannel.address_format = CD_LBA_FORMAT; - subchannel.data_format = CD_CURRENT_POSITION; - subchannel.track = track_num; - subchannel.data_len = 1; - subchannel.data = &subchannel_info; - - if(ioctl(_obj->gen.fd, CDIOCREADSUBCHANNEL, &subchannel) < 0) { - perror("CDIOCREADSUBCHANNEL"); - return 1; - } - - /* FIXME: Dunno if this is the right way, but it's what - I was using in cdinfo for a while. - */ - return (subchannel_info.what.position.control & 2) != 0; -} - -/*! - Return the starting LSN track number - track_num in obj. Track numbers start at 1. - The "leadout" track is specified either by - using track_num LEADOUT_TRACK or the total tracks+1. - False is returned if there is no track entry. -*/ -static lba_t -_cdio_get_track_lba(void *env, track_t track_num) -{ - _img_private_t *_obj = env; - - if (!_obj->toc_init) _cdio_read_toc (_obj) ; - - if (track_num == CDIO_CDROM_LEADOUT_TRACK) track_num = TOTAL_TRACKS+1; - - if (track_num > TOTAL_TRACKS+1 || track_num == 0) { - return CDIO_INVALID_LBA; - } else { - return _obj->tocent[track_num-1].addr.lba; - } -} - -#endif /* HAVE_FREEBSD_CDROM */ - -/*! - Return an array of strings giving possible CD devices. - */ -char ** -cdio_get_devices_freebsd (void) -{ -#ifndef HAVE_FREEBSD_CDROM - return NULL; -#else - char drive[40]; - char **drives = NULL; - unsigned int num_drives=0; - bool exists=true; - char c; - - /* Scan the system for CD-ROM drives. - */ - -#ifdef USE_ETC_FSTAB - - struct fstab *fs; - setfsent(); - - /* Check what's in /etc/fstab... */ - while ( (fs = getfsent()) ) - { - if (strncmp(fs->fs_spec, "/dev/sr", 7)) - cdio_add_device_list(&drives, fs->fs_spec, &num_drives); - } - -#endif - - /* Scan the system for CD-ROM drives. - Not always 100% reliable, so use the USE_MNTENT code above first. - */ - for ( c='0'; exists && c <='9'; c++ ) { - sprintf(drive, "/dev/acd%cc", c); - exists = cdio_is_cdrom(drive, NULL); - if ( exists ) { - cdio_add_device_list(&drives, drive, &num_drives); - } - } - cdio_add_device_list(&drives, NULL, &num_drives); - return drives; -#endif /*HAVE_FREEBSD_CDROM*/ -} - -/*! - Return a string containing the default CD device if none is specified. - */ -char * -cdio_get_default_device_freebsd() -{ - return strdup(DEFAULT_CDIO_DEVICE); -} - -/*! - Initialization routine. This is the only thing that doesn't - get called via a function pointer. In fact *we* are the - ones to set that up. - */ -CdIo * -cdio_open_freebsd (const char *source_name) -{ - -#ifdef HAVE_FREEBSD_CDROM - CdIo *ret; - _img_private_t *_data; - - cdio_funcs _funcs = { - .eject_media = _cdio_eject_media, - .free = cdio_generic_free, - .get_arg = _cdio_get_arg, - .get_default_device = cdio_get_default_device_freebsd, - .get_devices = cdio_get_devices_freebsd, - .get_first_track_num= _cdio_get_first_track_num, - .get_mcn = _cdio_get_mcn, - .get_num_tracks = _cdio_get_num_tracks, - .get_track_format = _cdio_get_track_format, - .get_track_green = _cdio_get_track_green, - .get_track_lba = _cdio_get_track_lba, - .get_track_msf = NULL, - .lseek = cdio_generic_lseek, - .read = cdio_generic_read, - .read_audio_sectors = _cdio_read_audio_sectors, - .read_mode2_sector = _cdio_read_mode2_sector, - .read_mode2_sectors = _cdio_read_mode2_sectors, - .set_arg = _cdio_set_arg, - .stat_size = _cdio_stat_size - }; - - _data = _cdio_malloc (sizeof (_img_private_t)); - _data->access_mode = _AM_IOCTL; - _data->gen.init = false; - _data->gen.fd = -1; - - _cdio_set_arg(_data, "source", (NULL == source_name) - ? DEFAULT_CDIO_DEVICE: source_name); - - ret = cdio_new (_data, &_funcs); - if (ret == NULL) return NULL; - - if (cdio_generic_init(_data)) - return ret; - else { - cdio_generic_free (_data); - return NULL; - } - -#else - return NULL; -#endif /* HAVE_FREEBSD_CDROM */ - -} - -bool -cdio_have_freebsd (void) -{ -#ifdef HAVE_FREEBSD_CDROM - return true; -#else - return false; -#endif /* HAVE_FREEBSD_CDROM */ -} diff --git a/src/input/vcd/libcdio/_cdio_generic.c b/src/input/vcd/libcdio/_cdio_generic.c index 1328fb2a7..fb3ed5a9c 100644 --- a/src/input/vcd/libcdio/_cdio_generic.c +++ b/src/input/vcd/libcdio/_cdio_generic.c @@ -1,8 +1,7 @@ /* - $Id: _cdio_generic.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: _cdio_generic.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $ - Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> - Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com> + Copyright (C) 2004 Rocky Bernstein <rocky@panix.com> 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 @@ -19,21 +18,24 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* This file contains Linux-specific code and implements low-level - control of the CD drive. +/* This file contains generic implementations of device-dirver routines. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif -static const char _rcsid[] = "$Id: _cdio_generic.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: _cdio_generic.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $"; #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> -#include <unistd.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif /*HAVE_UNISTD_H*/ + #include <fcntl.h> #include <sys/stat.h> @@ -41,9 +43,11 @@ static const char _rcsid[] = "$Id: _cdio_generic.c,v 1.2 2004/04/11 12:20:31 mig #include <cdio/sector.h> #include <cdio/util.h> +#include <cdio/logging.h> #include "cdio_assert.h" #include "cdio_private.h" #include "_cdio_stdio.h" +#include "portable.h" /*! Eject media -- there's nothing to do here. We always return 2. @@ -60,17 +64,22 @@ cdio_generic_bogus_eject_media (void *user_data) { Release and free resources associated with cd. */ void -cdio_generic_free (void *user_data) +cdio_generic_free (void *p_user_data) { - generic_img_private_t *_obj = user_data; + generic_img_private_t *p_env = p_user_data; + track_t i_track; - if (NULL == _obj) return; - free (_obj->source_name); + if (NULL == p_env) return; + free (p_env->source_name); - if (_obj->fd >= 0) - close (_obj->fd); + for (i_track=0; i_track < p_env->i_tracks; i_track++) { + cdtext_destroy(&(p_env->cdtext_track[i_track])); + } - free (_obj); + if (p_env->fd >= 0) + close (p_env->fd); + + free (p_env); } /*! @@ -79,35 +88,52 @@ cdio_generic_free (void *user_data) bool cdio_generic_init (void *user_data) { - generic_img_private_t *_obj = user_data; - if (_obj->init) { - cdio_error ("init called more than once"); + generic_img_private_t *p_env = user_data; + if (p_env->init) { + cdio_warn ("init called more than once"); return false; } - _obj->fd = open (_obj->source_name, O_RDONLY, 0); + p_env->fd = open (p_env->source_name, O_RDONLY, 0); - if (_obj->fd < 0) + if (p_env->fd < 0) { - cdio_warn ("open (%s): %s", _obj->source_name, strerror (errno)); + cdio_warn ("open (%s): %s", p_env->source_name, strerror (errno)); return false; } - _obj->init = true; - _obj->toc_init = false; + p_env->init = true; + p_env->toc_init = false; + p_env->b_cdtext_init = false; + p_env->b_cdtext_error = false; + p_env->i_joliet_level = 0; /* Assume no Joliet extensions initally */ return true; } /*! + Reads a single form1 sector from cd device into data starting + from lsn. Returns 0 if no error. + */ +int +cdio_generic_read_form1_sector (void * user_data, void *data, lsn_t lsn) +{ + if (0 > cdio_generic_lseek(user_data, CDIO_CD_FRAMESIZE*lsn, SEEK_SET)) + return -1; + if (0 > cdio_generic_read(user_data, data, CDIO_CD_FRAMESIZE)) + return -1; + return 0; +} + +/*! Reads into buf the next size bytes. Returns -1 on error. - Is in fact libc's read(). + Is in fact libc's lseek(). */ off_t cdio_generic_lseek (void *user_data, off_t offset, int whence) { - generic_img_private_t *_obj = user_data; - return lseek(_obj->fd, offset, whence); + generic_img_private_t *p_env = user_data; + return lseek(p_env->fd, offset, whence); } /*! @@ -118,8 +144,8 @@ cdio_generic_lseek (void *user_data, off_t offset, int whence) ssize_t cdio_generic_read (void *user_data, void *buf, size_t size) { - generic_img_private_t *_obj = user_data; - return read(_obj->fd, buf, size); + generic_img_private_t *p_env = user_data; + return read(p_env->fd, buf, size); } /*! @@ -128,13 +154,14 @@ cdio_generic_read (void *user_data, void *buf, size_t size) void cdio_generic_stdio_free (void *user_data) { - generic_img_private_t *_obj = user_data; + generic_img_private_t *p_env = user_data; - if (NULL == _obj) return; - free (_obj->source_name); + if (NULL == p_env) return; + if (NULL != p_env->source_name) + free (p_env->source_name); - if (_obj->data_source) - cdio_stdio_destroy (_obj->data_source); + if (p_env->data_source) + cdio_stdio_destroy (p_env->data_source); } @@ -171,7 +198,8 @@ cdio_is_device_quiet_generic(const char *source_name) Use cdio_free_device_list() to free this device_list. */ void -cdio_add_device_list(char **device_list[], const char *drive, int *num_drives) +cdio_add_device_list(char **device_list[], const char *drive, + unsigned int *num_drives) { if (NULL != drive) { unsigned int j; @@ -205,3 +233,194 @@ cdio_add_device_list(char **device_list[], const char *drive, int *num_drives) } +/*! + Get cdtext information for a CdIo object . + + @param obj the CD object that may contain CD-TEXT information. + @return the CD-TEXT object or NULL if obj is NULL + or CD-TEXT information does not exist. +*/ +const cdtext_t * +get_cdtext_generic (void *p_user_data, track_t i_track) +{ + generic_img_private_t *p_env = p_user_data; + + if ( NULL == p_env || + (0 != i_track + && i_track >= p_env->i_tracks+p_env->i_first_track ) ) + return NULL; + + if (!p_env->b_cdtext_init) + init_cdtext_generic(p_env); + if (!p_env->b_cdtext_init) return NULL; + + if (0 == i_track) + return &(p_env->cdtext); + else + return &(p_env->cdtext_track[i_track-p_env->i_first_track]); + +} + +/*! + Get disc type associated with cd object. +*/ +discmode_t +get_discmode_generic (void *p_user_data ) +{ + generic_img_private_t *p_env = p_user_data; + + /* See if this is a DVD. */ + cdio_dvd_struct_t dvd; /* DVD READ STRUCT for layer 0. */ + + dvd.physical.type = CDIO_DVD_STRUCT_PHYSICAL; + dvd.physical.layer_num = 0; + if (0 == scsi_mmc_get_dvd_struct_physical (p_env->cdio, &dvd)) { + switch(dvd.physical.layer[0].book_type) { + case CDIO_DVD_BOOK_DVD_ROM: return CDIO_DISC_MODE_DVD_ROM; + case CDIO_DVD_BOOK_DVD_RAM: return CDIO_DISC_MODE_DVD_RAM; + case CDIO_DVD_BOOK_DVD_R: return CDIO_DISC_MODE_DVD_R; + case CDIO_DVD_BOOK_DVD_RW: return CDIO_DISC_MODE_DVD_RW; + case CDIO_DVD_BOOK_DVD_PR: return CDIO_DISC_MODE_DVD_PR; + case CDIO_DVD_BOOK_DVD_PRW: return CDIO_DISC_MODE_DVD_PRW; + default: return CDIO_DISC_MODE_DVD_OTHER; + } + } + + return get_discmode_cd_generic(p_user_data); +} + +/*! + Get disc type associated with cd object. +*/ +discmode_t +get_discmode_cd_generic (void *p_user_data ) +{ + generic_img_private_t *p_env = p_user_data; + track_t i_track; + discmode_t discmode=CDIO_DISC_MODE_NO_INFO; + + if (!p_env->toc_init) + p_env->cdio->op.read_toc (p_user_data); + + if (!p_env->toc_init) + return CDIO_DISC_MODE_NO_INFO; + + for (i_track = p_env->i_first_track; + i_track < p_env->i_first_track + p_env->i_tracks ; + i_track ++) { + track_format_t track_fmt = + p_env->cdio->op.get_track_format(p_env, i_track); + + switch(track_fmt) { + case TRACK_FORMAT_AUDIO: + switch(discmode) { + case CDIO_DISC_MODE_NO_INFO: + discmode = CDIO_DISC_MODE_CD_DA; + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* No change*/ + break; + default: + discmode = CDIO_DISC_MODE_CD_MIXED; + } + break; + case TRACK_FORMAT_XA: + switch(discmode) { + case CDIO_DISC_MODE_NO_INFO: + discmode = CDIO_DISC_MODE_CD_XA; + break; + case CDIO_DISC_MODE_CD_XA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* No change*/ + break; + default: + discmode = CDIO_DISC_MODE_CD_MIXED; + } + break; + case TRACK_FORMAT_DATA: + switch(discmode) { + case CDIO_DISC_MODE_NO_INFO: + discmode = CDIO_DISC_MODE_CD_DATA; + break; + case CDIO_DISC_MODE_CD_DATA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* No change*/ + break; + default: + discmode = CDIO_DISC_MODE_CD_MIXED; + } + break; + case TRACK_FORMAT_ERROR: + default: + discmode = CDIO_DISC_MODE_ERROR; + } + } + return discmode; +} + +/*! + Return the number of of the first track. + CDIO_INVALID_TRACK is returned on error. +*/ +track_t +get_first_track_num_generic(void *p_user_data) +{ + generic_img_private_t *p_env = p_user_data; + + if (!p_env->toc_init) + p_env->cdio->op.read_toc (p_user_data); + + return p_env->toc_init ? p_env->i_first_track : CDIO_INVALID_TRACK; +} + + +/*! + Return the number of tracks in the current medium. +*/ + track_t +get_num_tracks_generic(void *p_user_data) +{ + generic_img_private_t *p_env = p_user_data; + + if (!p_env->toc_init) + p_env->cdio->op.read_toc (p_user_data); + + return p_env->toc_init ? p_env->i_tracks : CDIO_INVALID_TRACK; +} + +void +set_cdtext_field_generic(void *user_data, track_t i_track, + track_t i_first_track, + cdtext_field_t e_field, const char *psz_value) +{ + char **pp_field; + generic_img_private_t *env = user_data; + + if( i_track == 0 ) + pp_field = &(env->cdtext.field[e_field]); + + else + pp_field = &(env->cdtext_track[i_track-i_first_track].field[e_field]); + + *pp_field = strdup(psz_value); +} + +/*! + Read CD-Text information for a CdIo object . + + return true on success, false on error or CD-TEXT information does + not exist. +*/ +bool +init_cdtext_generic (generic_img_private_t *p_env) +{ + return scsi_mmc_init_cdtext_private( p_env, + p_env->cdio->op.run_scsi_mmc_cmd, + set_cdtext_field_generic + ); +} + diff --git a/src/input/vcd/libcdio/_cdio_linux.c b/src/input/vcd/libcdio/_cdio_linux.c index e5dd47551..86a34133f 100644 --- a/src/input/vcd/libcdio/_cdio_linux.c +++ b/src/input/vcd/libcdio/_cdio_linux.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_linux.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: _cdio_linux.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $ Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com> @@ -27,15 +27,18 @@ # include "config.h" #endif -static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $"; #include <string.h> #include <cdio/sector.h> #include <cdio/util.h> +#include <cdio/types.h> +#include <cdio/scsi_mmc.h> +#include <cdio/cdtext.h> +#include "cdtext_private.h" #include "cdio_assert.h" #include "cdio_private.h" -#include "scsi_mmc.h" #ifdef HAVE_LINUX_CDROM @@ -67,24 +70,25 @@ static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.2 2004/04/11 12:20:31 migue #include <sys/types.h> #include <sys/ioctl.h> -#define TOTAL_TRACKS (_obj->tochdr.cdth_trk1) -#define FIRST_TRACK_NUM (_obj->tochdr.cdth_trk0) +typedef enum { + _AM_NONE, + _AM_IOCTL, + _AM_READ_CD, + _AM_READ_10 +} access_mode_t; typedef struct { /* Things common to all drivers like this. This must be first. */ generic_img_private_t gen; - enum { - _AM_NONE, - _AM_IOCTL, - _AM_READ_CD, - _AM_READ_10 - } access_mode; + access_mode_t access_mode; + + /* Some of the more OS specific things. */ + /* Entry info for each track, add 1 for leadout. */ + struct cdrom_tocentry tocent[CDIO_CD_MAX_TRACKS+1]; - /* Track information */ struct cdrom_tochdr tochdr; - struct cdrom_tocentry tocent[100]; /* entry info for each track */ } _img_private_t; @@ -92,40 +96,39 @@ typedef struct { #define ERRNO_TRAYEMPTY(errno) \ ((errno == EIO) || (errno == ENOENT) || (errno == EINVAL)) - -/* Check a drive to see if it is a CD-ROM - Return 1 if a CD-ROM. 0 if it exists but isn't a CD-ROM drive - and -1 if no device exists . -*/ -static bool -cdio_is_cdrom(char *drive, char *mnttype) +/**** prototypes for static functions ****/ +static bool is_cdrom_linux(const char *drive, char *mnttype); +static bool read_toc_linux (void *p_user_data); +static int run_scsi_cmd_linux( const void *p_user_data, + unsigned int i_timeout, + unsigned int i_cdb, + const scsi_mmc_cdb_t *p_cdb, + scsi_mmc_direction_t e_direction, + unsigned int i_buf, + /*in/out*/ void *p_buf ); +static access_mode_t + +str_to_access_mode_linux(const char *psz_access_mode) { - bool is_cd=false; - int cdfd; - struct cdrom_tochdr tochdr; - - /* If it doesn't exist, return -1 */ - if ( !cdio_is_device_quiet_generic(drive) ) { - return(false); - } + const access_mode_t default_access_mode = _AM_IOCTL; + + if (NULL==psz_access_mode) return default_access_mode; - /* If it does exist, verify that it's an available CD-ROM */ - cdfd = open(drive, (O_RDONLY|O_NONBLOCK), 0); - if ( cdfd >= 0 ) { - if ( ioctl(cdfd, CDROMREADTOCHDR, &tochdr) != -1 ) { - is_cd = true; - } - close(cdfd); - } - /* Even if we can't read it, it might be mounted */ - else if ( mnttype && (strcmp(mnttype, "iso9660") == 0) ) { - is_cd = true; + if (!strcmp(psz_access_mode, "IOCTL")) + return _AM_IOCTL; + else if (!strcmp(psz_access_mode, "READ_CD")) + return _AM_READ_CD; + else if (!strcmp(psz_access_mode, "READ_10")) + return _AM_READ_10; + else { + cdio_warn ("unknown access type: %s. Default IOCTL used.", + psz_access_mode); + return default_access_mode; } - return(is_cd); } static char * -cdio_check_mounts(const char *mtab) +check_mounts_linux(const char *mtab) { FILE *mntfp; struct mntent *mntent; @@ -176,7 +179,7 @@ cdio_check_mounts(const char *mtab) } } if ( strcmp(mnt_type, "iso9660") == 0 ) { - if (cdio_is_cdrom(mnt_dev, mnt_type) > 0) { + if (is_cdrom_linux(mnt_dev, mnt_type) > 0) { free(mnt_type); endmntent(mntfp); return mnt_dev; @@ -190,146 +193,408 @@ cdio_check_mounts(const char *mtab) return NULL; } -static int -_set_bsize (int fd, unsigned int bsize) +/*! + Return the value associated with the key "arg". +*/ +static const char * +get_arg_linux (void *env, const char key[]) { - struct cdrom_generic_command cgc; + _img_private_t *_obj = env; - struct - { - uint8_t reserved1; - uint8_t medium; - uint8_t reserved2; - uint8_t block_desc_length; - uint8_t density; - uint8_t number_of_blocks_hi; - uint8_t number_of_blocks_med; - uint8_t number_of_blocks_lo; - uint8_t reserved3; - uint8_t block_length_hi; - uint8_t block_length_med; - uint8_t block_length_lo; - } mh; - - memset (&mh, 0, sizeof (mh)); - memset (&cgc, 0, sizeof (struct cdrom_generic_command)); + if (!strcmp (key, "source")) { + return _obj->gen.source_name; + } else if (!strcmp (key, "access-mode")) { + switch (_obj->access_mode) { + case _AM_IOCTL: + return "ioctl"; + case _AM_READ_CD: + return "READ_CD"; + case _AM_READ_10: + return "READ_10"; + case _AM_NONE: + return "no access method"; + } + } + return NULL; +} + +#undef USE_LINUX_CAP +#ifdef USE_LINUX_CAP +/*! + Return the the kind of drive capabilities of device. + + Note: string is malloc'd so caller should free() then returned + string when done with it. + + */ +static void +get_drive_cap_linux (const void *p_user_data, + /*out*/ cdio_drive_read_cap_t *p_read_cap, + /*out*/ cdio_drive_write_cap_t *p_write_cap, + /*out*/ cdio_drive_misc_cap_t *p_misc_cap) +{ + const _img_private_t *p_env = p_user_data; + int32_t i_drivetype; + + i_drivetype = ioctl (p_env->gen.fd, CDROM_GET_CAPABILITY, CDSL_CURRENT); + + if (i_drivetype < 0) { + *p_read_cap = CDIO_DRIVE_CAP_ERROR; + *p_write_cap = CDIO_DRIVE_CAP_ERROR; + *p_misc_cap = CDIO_DRIVE_CAP_ERROR; + return; + } - cgc.cmd[0] = 0x15; - cgc.cmd[1] = 1 << 4; - cgc.cmd[4] = 12; + *p_read_cap = 0; + *p_write_cap = 0; + *p_misc_cap = 0; + + /* Reader */ + if (i_drivetype & CDC_PLAY_AUDIO) + *p_read_cap |= CDIO_DRIVE_CAP_READ_AUDIO; + if (i_drivetype & CDC_CD_R) + *p_read_cap |= CDIO_DRIVE_CAP_READ_CD_R; + if (i_drivetype & CDC_CD_RW) + *p_read_cap |= CDIO_DRIVE_CAP_READ_CD_RW; + if (i_drivetype & CDC_DVD) + *p_read_cap |= CDIO_DRIVE_CAP_READ_DVD_ROM; + + /* Writer */ + if (i_drivetype & CDC_CD_RW) + *p_read_cap |= CDIO_DRIVE_CAP_WRITE_CD_RW; + if (i_drivetype & CDC_DVD_R) + *p_read_cap |= CDIO_DRIVE_CAP_WRITE_DVD_R; + if (i_drivetype & CDC_DVD_RAM) + *p_read_cap |= CDIO_DRIVE_CAP_WRITE_DVD_RAM; + + /* Misc */ + if (i_drivetype & CDC_CLOSE_TRAY) + *p_misc_cap |= CDIO_DRIVE_CAP_MISC_CLOSE_TRAY; + if (i_drivetype & CDC_OPEN_TRAY) + *p_misc_cap |= CDIO_DRIVE_CAP_MISC_EJECT; + if (i_drivetype & CDC_LOCK) + *p_misc_cap |= CDIO_DRIVE_CAP_MISC_LOCK; + if (i_drivetype & CDC_SELECT_SPEED) + *p_misc_cap |= CDIO_DRIVE_CAP_MISC_SELECT_SPEED; + if (i_drivetype & CDC_SELECT_DISC) + *p_misc_cap |= CDIO_DRIVE_CAP_MISC_SELECT_DISC; + if (i_drivetype & CDC_MULTI_SESSION) + *p_misc_cap |= CDIO_DRIVE_CAP_MISC_MULTI_SESSION; + if (i_drivetype & CDC_MEDIA_CHANGED) + *p_misc_cap |= CDIO_DRIVE_CAP_MISC_MEDIA_CHANGED; + if (i_drivetype & CDC_RESET) + *p_misc_cap |= CDIO_DRIVE_CAP_MISC_RESET; +} +#endif + +/*! + Return the media catalog number MCN. + + Note: string is malloc'd so caller should free() then returned + string when done with it. + + */ +static char * +get_mcn_linux (const void *p_user_data) { + + struct cdrom_mcn mcn; + const _img_private_t *p_env = p_user_data; + memset(&mcn, 0, sizeof(mcn)); + if (ioctl(p_env->gen.fd, CDROM_GET_MCN, &mcn) != 0) + return NULL; + return strdup(mcn.medium_catalog_number); +} + +/*! + Get format of track. +*/ +static track_format_t +get_track_format_linux(void *p_user_data, track_t i_track) +{ + _img_private_t *p_env = p_user_data; - cgc.buflen = sizeof (mh); - cgc.buffer = (void *) &mh; + if ( !p_env ) return TRACK_FORMAT_ERROR; - cgc.data_direction = CGC_DATA_WRITE; + if (!p_env->gen.toc_init) read_toc_linux (p_user_data) ; - mh.block_desc_length = 0x08; - mh.block_length_hi = (bsize >> 16) & 0xff; - mh.block_length_med = (bsize >> 8) & 0xff; - mh.block_length_lo = (bsize >> 0) & 0xff; + if (i_track > (p_env->gen.i_tracks+p_env->gen.i_first_track) + || i_track < p_env->gen.i_first_track) + return TRACK_FORMAT_ERROR; + + i_track -= p_env->gen.i_first_track; - return ioctl (fd, CDROM_SEND_PACKET, &cgc); + /* This is pretty much copied from the "badly broken" cdrom_count_tracks + in linux/cdrom.c. + */ + if (p_env->tocent[i_track].cdte_ctrl & CDIO_CDROM_DATA_TRACK) { + if (p_env->tocent[i_track].cdte_format == CDIO_CDROM_CDI_TRACK) + return TRACK_FORMAT_CDI; + else if (p_env->tocent[i_track].cdte_format == CDIO_CDROM_XA_TRACK) + return TRACK_FORMAT_XA; + else + return TRACK_FORMAT_DATA; + } else + return TRACK_FORMAT_AUDIO; + } -/* Packet driver to read mode2 sectors. - Can read only up to 25 blocks. +/*! + Return true if we have XA data (green, mode2 form1) or + XA data (green, mode2 form2). That is track begins: + sync - header - subheader + 12 4 - 8 + + FIXME: there's gotta be a better design for this and get_track_format? */ -static int -_cdio_mmc_read_sectors (int fd, void *buf, lba_t lba, int sector_type, - unsigned int nblocks) +static bool +get_track_green_linux(void *p_user_data, track_t i_track) { - typedef struct cdrom_generic_command cgc_t; - cgc_t cgc; + _img_private_t *p_env = p_user_data; + + if (!p_env->gen.toc_init) read_toc_linux (p_user_data) ; - memset (&cgc, 0, sizeof (cgc_t)); + if (i_track >= (p_env->gen.i_tracks+p_env->gen.i_first_track) + || i_track < p_env->gen.i_first_track) + return false; - cgc.cmd[0] = CDIO_MMC_GPCMD_READ_CD; - CDIO_MMC_SET_READ_TYPE (cgc.cmd, sector_type); - CDIO_MMC_SET_READ_LBA (cgc.cmd, lba); - CDIO_MMC_SET_READ_LENGTH(cgc.cmd, nblocks); - CDIO_MMC_SET_MAIN_CHANNEL_SELECTION_BITS(cgc.cmd, CDIO_MMC_MCSB_ALL_HEADERS); + i_track -= p_env->gen.i_first_track; - cgc.buflen = CDIO_CD_FRAMESIZE_RAW * nblocks; - cgc.buffer = buf; + /* FIXME: Dunno if this is the right way, but it's what + I was using in cd-info for a while. + */ + return ((p_env->tocent[i_track].cdte_ctrl & 2) != 0); +} -#ifdef HAVE_LINUX_CDROM_TIMEOUT - cgc.timeout = 500; -#endif - cgc.data_direction = CGC_DATA_READ; +/*! + Return the starting MSF (minutes/secs/frames) for track number + track_num in obj. Track numbers usually start at something + greater than 0, usually 1. - return ioctl (fd, CDROM_SEND_PACKET, &cgc); + The "leadout" track is specified either by + using i_track LEADOUT_TRACK or the total tracks+1. + False is returned if there is no track entry. +*/ +static bool +get_track_msf_linux(void *p_user_data, track_t i_track, msf_t *msf) +{ + _img_private_t *p_env = p_user_data; - return 0; + if (NULL == msf) return false; + + if (!p_env->gen.toc_init) read_toc_linux (p_user_data) ; + + if (i_track == CDIO_CDROM_LEADOUT_TRACK) + i_track = p_env->gen.i_tracks + p_env->gen.i_first_track; + + if (i_track > (p_env->gen.i_tracks+p_env->gen.i_first_track) + || i_track < p_env->gen.i_first_track) { + return false; + } else { + struct cdrom_msf0 *msf0= + &p_env->tocent[i_track-p_env->gen.i_first_track].cdte_addr.msf; + msf->m = cdio_to_bcd8(msf0->minute); + msf->s = cdio_to_bcd8(msf0->second); + msf->f = cdio_to_bcd8(msf0->frame); + return true; + } +} + +/*! + Eject media in CD drive. + Return 0 if success and 1 for failure, and 2 if no routine. + */ +static int +eject_media_linux (void *p_user_data) { + + _img_private_t *p_env = p_user_data; + int ret=2; + int status; + int fd; + + if ((fd = open (p_env->gen.source_name, O_RDONLY|O_NONBLOCK)) > -1) { + if((status = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT)) > 0) { + switch(status) { + case CDS_TRAY_OPEN: + if((ret = ioctl(fd, CDROMCLOSETRAY)) != 0) { + cdio_warn ("ioctl CDROMCLOSETRAY failed: %s\n", strerror(errno)); + ret = 1; + } + break; + case CDS_DISC_OK: + if((ret = ioctl(fd, CDROMEJECT)) != 0) { + int eject_error = errno; + /* Try ejecting the MMC way... */ + ret = scsi_mmc_eject_media(p_env->gen.cdio); + if (0 != ret) { + cdio_warn("ioctl CDROMEJECT failed: %s\n", + strerror(eject_error)); + ret = 1; + } + } + /* force kernel to reread partition table when new disc inserted */ + ret = ioctl(p_env->gen.fd, BLKRRPART); + break; + default: + cdio_warn ("Unknown CD-ROM (%d)\n", status); + ret = 1; + } + } else { + cdio_warn ("CDROM_DRIVE_STATUS failed: %s\n", strerror(errno)); + ret=1; + } + close(fd); + } else + ret = 2; + close(p_env->gen.fd); + p_env->gen.fd = -1; + return ret; +} + +/*! + Get disc type associated with the cd object. +*/ +static discmode_t +get_discmode_linux (void *p_user_data) +{ + _img_private_t *p_env = p_user_data; + + int32_t i_discmode; + + /* See if this is a DVD. */ + cdio_dvd_struct_t dvd; /* DVD READ STRUCT for layer 0. */ + + dvd.physical.type = CDIO_DVD_STRUCT_PHYSICAL; + dvd.physical.layer_num = 0; + if (0 == ioctl (p_env->gen.fd, DVD_READ_STRUCT, &dvd)) { + switch(dvd.physical.layer[0].book_type) { + case CDIO_DVD_BOOK_DVD_ROM: return CDIO_DISC_MODE_DVD_ROM; + case CDIO_DVD_BOOK_DVD_RAM: return CDIO_DISC_MODE_DVD_RAM; + case CDIO_DVD_BOOK_DVD_R: return CDIO_DISC_MODE_DVD_R; + case CDIO_DVD_BOOK_DVD_RW: return CDIO_DISC_MODE_DVD_RW; + case CDIO_DVD_BOOK_DVD_PR: return CDIO_DISC_MODE_DVD_PR; + case CDIO_DVD_BOOK_DVD_PRW: return CDIO_DISC_MODE_DVD_PRW; + default: return CDIO_DISC_MODE_DVD_OTHER; + } + } + + i_discmode = ioctl (p_env->gen.fd, CDROM_DISC_STATUS); + + if (i_discmode < 0) return CDIO_DISC_MODE_ERROR; + + /* FIXME Need to add getting DVD types. */ + switch(i_discmode) { + case CDS_AUDIO: + return CDIO_DISC_MODE_CD_DA; + case CDS_DATA_1: + case CDS_DATA_2: + return CDIO_DISC_MODE_CD_DATA; + case CDS_MIXED: + return CDIO_DISC_MODE_CD_MIXED; + case CDS_XA_2_1: + case CDS_XA_2_2: + return CDIO_DISC_MODE_CD_XA; + case CDS_NO_INFO: + return CDIO_DISC_MODE_NO_INFO; + default: + return CDIO_DISC_MODE_ERROR; + } +} + +/* Check a drive to see if it is a CD-ROM + Return 1 if a CD-ROM. 0 if it exists but isn't a CD-ROM drive + and -1 if no device exists . +*/ +static bool +is_cdrom_linux(const char *drive, char *mnttype) +{ + bool is_cd=false; + int cdfd; + struct cdrom_tochdr tochdr; + + /* If it doesn't exist, return -1 */ + if ( !cdio_is_device_quiet_generic(drive) ) { + return(false); + } + + /* If it does exist, verify that it's an available CD-ROM */ + cdfd = open(drive, (O_RDONLY|O_NONBLOCK), 0); + if ( cdfd >= 0 ) { + if ( ioctl(cdfd, CDROMREADTOCHDR, &tochdr) != -1 ) { + is_cd = true; + } + close(cdfd); + } + /* Even if we can't read it, it might be mounted */ + else if ( mnttype && (strcmp(mnttype, "iso9660") == 0) ) { + is_cd = true; + } + return(is_cd); } /* MMC driver to read audio sectors. Can read only up to 25 blocks. */ static int -_cdio_read_audio_sectors (void *env, void *buf, lsn_t lsn, - unsigned int nblocks) +_read_audio_sectors_linux (void *p_user_data, void *buf, lsn_t lsn, + unsigned int nblocks) { - _img_private_t *_obj = env; - return _cdio_mmc_read_sectors( _obj->gen.fd, buf, lsn, - CDIO_MMC_READ_TYPE_CDDA, nblocks); + _img_private_t *p_env = p_user_data; + return scsi_mmc_read_sectors( p_env->gen.cdio, buf, lsn, + CDIO_MMC_READ_TYPE_CDDA, nblocks); } /* Packet driver to read mode2 sectors. Can read only up to 25 blocks. */ static int -__read_packet_mode2_sectors (int fd, void *buf, lba_t lba, - unsigned int nblocks, bool use_read_10) +_read_mode2_sectors_mmc (_img_private_t *p_env, void *p_buf, lba_t lba, + unsigned int nblocks, bool b_read_10) { - struct cdrom_generic_command cgc; - - memset (&cgc, 0, sizeof (struct cdrom_generic_command)); - - cgc.cmd[0] = use_read_10 ? GPCMD_READ_10 : CDIO_MMC_GPCMD_READ_CD; - - CDIO_MMC_SET_READ_LBA(cgc.cmd, lba); - CDIO_MMC_SET_READ_LENGTH(cgc.cmd, nblocks); - - if (!use_read_10) - { - cgc.cmd[1] = 0; /* sector size mode2 */ - - cgc.cmd[9] = 0x58; /* 2336 mode2 */ - } + scsi_mmc_cdb_t cdb = {{0, }}; - cgc.buflen = 2336 * nblocks; - cgc.buffer = buf; + CDIO_MMC_SET_READ_LBA(cdb.field, lba); -#ifdef HAVE_LINUX_CDROM_TIMEOUT - cgc.timeout = 500; -#endif - cgc.data_direction = CGC_DATA_READ; - - if (use_read_10) - { - int retval; + if (b_read_10) { + int retval; + + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_10); + CDIO_MMC_SET_READ_LENGTH16(cdb.field, nblocks); - if ((retval = _set_bsize (fd, 2336))) + if ((retval = scsi_mmc_set_blocksize (p_env->gen.cdio, M2RAW_SECTOR_SIZE))) + return retval; + + if ((retval = run_scsi_cmd_linux (p_env, 0, + scsi_mmc_get_cmd_len(cdb.field[0]), + &cdb, + SCSI_MMC_DATA_READ, + M2RAW_SECTOR_SIZE * nblocks, + p_buf))) + { + scsi_mmc_set_blocksize (p_env->gen.cdio, CDIO_CD_FRAMESIZE); return retval; + } + + if ((retval = scsi_mmc_set_blocksize (p_env->gen.cdio, CDIO_CD_FRAMESIZE))) + return retval; + } else - if ((retval = ioctl (fd, CDROM_SEND_PACKET, &cgc))) - { - _set_bsize (fd, 2048); - return retval; - } + cdb.field[1] = 0; /* sector size mode2 */ + cdb.field[9] = 0x58; /* 2336 mode2 */ - if ((retval = _set_bsize (fd, 2048))) - return retval; - } - else - return ioctl (fd, CDROM_SEND_PACKET, &cgc); + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_CD); + CDIO_MMC_SET_READ_LENGTH24(cdb.field, nblocks); + return run_scsi_cmd_linux (p_env, 0, + scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, + SCSI_MMC_DATA_READ, + M2RAW_SECTOR_SIZE * nblocks, p_buf); + return 0; } static int -_read_packet_mode2_sectors (int fd, void *buf, lba_t lba, - unsigned int nblocks, bool use_read_10) +_read_mode2_sectors (_img_private_t *p_env, void *p_buf, lba_t lba, + unsigned int nblocks, bool b_read_10) { unsigned int l = 0; int retval = 0; @@ -337,10 +602,10 @@ _read_packet_mode2_sectors (int fd, void *buf, lba_t lba, while (nblocks > 0) { const unsigned nblocks2 = (nblocks > 25) ? 25 : nblocks; - void *buf2 = ((char *)buf ) + (l * 2336); + void *p_buf2 = ((char *)p_buf ) + (l * M2RAW_SECTOR_SIZE); - retval |= __read_packet_mode2_sectors (fd, buf2, lba + l, nblocks2, - use_read_10); + retval |= _read_mode2_sectors_mmc (p_env, p_buf2, lba + l, + nblocks2, b_read_10); if (retval) break; @@ -357,32 +622,32 @@ _read_packet_mode2_sectors (int fd, void *buf, lba_t lba, from lsn. Returns 0 if no error. */ static int -_cdio_read_mode1_sector (void *env, void *data, lsn_t lsn, +_read_mode1_sector_linux (void *p_user_data, void *p_data, lsn_t lsn, bool b_form2) { - char buf[M2RAW_SECTOR_SIZE] = { 0, }; #if FIXED - struct cdrom_msf *msf = (struct cdrom_msf *) &buf; + char buf[M2RAW_SECTOR_SIZE] = { 0, }; + struct cdrom_msf *p_msf = (struct cdrom_msf *) &buf; msf_t _msf; - _img_private_t *_obj = env; + _img_private_t *p_env = p_user_data; cdio_lba_to_msf (cdio_lsn_to_lba(lsn), &_msf); - msf->cdmsf_min0 = from_bcd8(_msf.m); - msf->cdmsf_sec0 = from_bcd8(_msf.s); - msf->cdmsf_frame0 = from_bcd8(_msf.f); + msf->cdmsf_min0 = cdio_from_bcd8(_msf.m); + msf->cdmsf_sec0 = cdio_from_bcd8(_msf.s); + msf->cdmsf_frame0 = cdio_from_bcd8(_msf.f); retry: - switch (_obj->access_mode) + switch (p_env->access_mode) { case _AM_NONE: - cdio_error ("no way to read mode1"); + cdio_warn ("no way to read mode1"); return 1; break; case _AM_IOCTL: - if (ioctl (_obj->gen.fd, CDROMREADMODE1, &buf) == -1) + if (ioctl (p_env->gen.fd, CDROMREADMODE1, &buf) == -1) { perror ("ioctl()"); return 1; @@ -392,20 +657,20 @@ _cdio_read_mode1_sector (void *env, void *data, lsn_t lsn, case _AM_READ_CD: case _AM_READ_10: - if (_read_packet_mode2_sectors (_obj->gen.fd, buf, lsn, 1, - (_obj->access_mode == _AM_READ_10))) + if (_read_mode2_sectors (p_env->gen.fd, buf, lsn, 1, + (p_env->access_mode == _AM_READ_10))) { perror ("ioctl()"); - if (_obj->access_mode == _AM_READ_CD) + if (p_env->access_mode == _AM_READ_CD) { cdio_info ("READ_CD failed; switching to READ_10 mode..."); - _obj->access_mode = _AM_READ_10; + p_env->access_mode = _AM_READ_10; goto retry; } else { cdio_info ("READ_10 failed; switching to ioctl(CDROMREADMODE2) mode..."); - _obj->access_mode = _AM_IOCTL; + p_env->access_mode = _AM_IOCTL; goto retry; } return 1; @@ -417,11 +682,7 @@ _cdio_read_mode1_sector (void *env, void *data, lsn_t lsn, b_form2 ? M2RAW_SECTOR_SIZE: CDIO_CD_FRAMESIZE); #else - if (0 > cdio_generic_lseek(env, CDIO_CD_FRAMESIZE*lsn, SEEK_SET)) - return -1; - if (0 > cdio_generic_read(env, buf, CDIO_CD_FRAMESIZE)) - return -1; - memcpy (data, buf, b_form2 ? M2RAW_SECTOR_SIZE: CDIO_CD_FRAMESIZE); + return cdio_generic_read_form1_sector(p_user_data, p_data, lsn); #endif return 0; } @@ -432,17 +693,17 @@ _cdio_read_mode1_sector (void *env, void *data, lsn_t lsn, Returns 0 if no error. */ static int -_cdio_read_mode1_sectors (void *env, void *data, lsn_t lsn, +_read_mode1_sectors_linux (void *p_user_data, void *p_data, lsn_t lsn, bool b_form2, unsigned int nblocks) { - _img_private_t *_obj = env; + _img_private_t *p_env = p_user_data; unsigned int i; int retval; unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE; for (i = 0; i < nblocks; i++) { - if ( (retval = _cdio_read_mode1_sector (_obj, - ((char *)data) + (blocksize * i), + if ( (retval = _read_mode1_sector_linux (p_env, + ((char *)p_data) + (blocksize*i), lsn + i, b_form2)) ) return retval; } @@ -454,30 +715,30 @@ _cdio_read_mode1_sectors (void *env, void *data, lsn_t lsn, from lsn. Returns 0 if no error. */ static int -_cdio_read_mode2_sector (void *env, void *data, lsn_t lsn, - bool b_form2) +_read_mode2_sector_linux (void *p_user_data, void *p_data, lsn_t lsn, + bool b_form2) { char buf[M2RAW_SECTOR_SIZE] = { 0, }; struct cdrom_msf *msf = (struct cdrom_msf *) &buf; msf_t _msf; - _img_private_t *_obj = env; + _img_private_t *p_env = p_user_data; cdio_lba_to_msf (cdio_lsn_to_lba(lsn), &_msf); - msf->cdmsf_min0 = from_bcd8(_msf.m); - msf->cdmsf_sec0 = from_bcd8(_msf.s); - msf->cdmsf_frame0 = from_bcd8(_msf.f); + msf->cdmsf_min0 = cdio_from_bcd8(_msf.m); + msf->cdmsf_sec0 = cdio_from_bcd8(_msf.s); + msf->cdmsf_frame0 = cdio_from_bcd8(_msf.f); retry: - switch (_obj->access_mode) + switch (p_env->access_mode) { case _AM_NONE: - cdio_error ("no way to read mode2"); + cdio_warn ("no way to read mode2"); return 1; break; case _AM_IOCTL: - if (ioctl (_obj->gen.fd, CDROMREADMODE2, &buf) == -1) + if (ioctl (p_env->gen.fd, CDROMREADMODE2, &buf) == -1) { perror ("ioctl()"); return 1; @@ -487,20 +748,20 @@ _cdio_read_mode2_sector (void *env, void *data, lsn_t lsn, case _AM_READ_CD: case _AM_READ_10: - if (_read_packet_mode2_sectors (_obj->gen.fd, buf, lsn, 1, - (_obj->access_mode == _AM_READ_10))) + if (_read_mode2_sectors (p_env, buf, lsn, 1, + (p_env->access_mode == _AM_READ_10))) { perror ("ioctl()"); - if (_obj->access_mode == _AM_READ_CD) + if (p_env->access_mode == _AM_READ_CD) { cdio_info ("READ_CD failed; switching to READ_10 mode..."); - _obj->access_mode = _AM_READ_10; + p_env->access_mode = _AM_READ_10; goto retry; } else { cdio_info ("READ_10 failed; switching to ioctl(CDROMREADMODE2) mode..."); - _obj->access_mode = _AM_IOCTL; + p_env->access_mode = _AM_IOCTL; goto retry; } return 1; @@ -509,9 +770,9 @@ _cdio_read_mode2_sector (void *env, void *data, lsn_t lsn, } if (b_form2) - memcpy (data, buf, M2RAW_SECTOR_SIZE); + memcpy (p_data, buf, M2RAW_SECTOR_SIZE); else - memcpy (((char *)data), buf + CDIO_CD_SUBHEADER_SIZE, CDIO_CD_FRAMESIZE); + memcpy (((char *)p_data), buf + CDIO_CD_SUBHEADER_SIZE, CDIO_CD_FRAMESIZE); return 0; } @@ -522,115 +783,57 @@ _cdio_read_mode2_sector (void *env, void *data, lsn_t lsn, Returns 0 if no error. */ static int -_cdio_read_mode2_sectors (void *env, void *data, lsn_t lsn, +_read_mode2_sectors_linux (void *p_user_data, void *data, lsn_t lsn, bool b_form2, unsigned int nblocks) { - _img_private_t *_obj = env; + _img_private_t *p_env = p_user_data; unsigned int i; - int retval; - unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE; + unsigned int i_blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE; + /* For each frame, pick out the data part we need */ for (i = 0; i < nblocks; i++) { - if ( (retval = _cdio_read_mode2_sector (_obj, - ((char *)data) + (blocksize * i), + int retval; + if ( (retval = _read_mode2_sector_linux (p_env, + ((char *)data) + (i_blocksize*i), lsn + i, b_form2)) ) return retval; } return 0; } -/*! - Return the size of the CD in logical block address (LBA) units. - */ -static uint32_t -_cdio_stat_size (void *env) -{ - _img_private_t *_obj = env; - - struct cdrom_tocentry tocent; - uint32_t size; - - tocent.cdte_track = CDIO_CDROM_LEADOUT_TRACK; - tocent.cdte_format = CDROM_LBA; - if (ioctl (_obj->gen.fd, CDROMREADTOCENTRY, &tocent) == -1) - { - perror ("ioctl(CDROMREADTOCENTRY)"); - exit (EXIT_FAILURE); - } - - size = tocent.cdte_addr.lba; - - return size; -} - -/*! - Set the arg "key" with "value" in the source device. - Currently "source" and "access-mode" are valid keys. - "source" sets the source device in I/O operations - "access-mode" sets the the method of CD access - - 0 is returned if no error was found, and nonzero if there as an error. -*/ -static int -_cdio_set_arg (void *env, const char key[], const char value[]) -{ - _img_private_t *_obj = env; - - if (!strcmp (key, "source")) - { - if (!value) - return -2; - - free (_obj->gen.source_name); - - _obj->gen.source_name = strdup (value); - } - else if (!strcmp (key, "access-mode")) - { - if (!strcmp(value, "IOCTL")) - _obj->access_mode = _AM_IOCTL; - else if (!strcmp(value, "READ_CD")) - _obj->access_mode = _AM_READ_CD; - else if (!strcmp(value, "READ_10")) - _obj->access_mode = _AM_READ_10; - else { - cdio_warn ("unknown access type: %s. ignored.", value); - } - } - else - return -1; - - return 0; -} - /*! Read and cache the CD's Track Table of Contents and track info. Return false if successful or true if an error. */ static bool -_cdio_read_toc (_img_private_t *_obj) +read_toc_linux (void *p_user_data) { + _img_private_t *p_env = p_user_data; int i; /* read TOC header */ - if ( ioctl(_obj->gen.fd, CDROMREADTOCHDR, &_obj->tochdr) == -1 ) { - cdio_error("%s: %s\n", + if ( ioctl(p_env->gen.fd, CDROMREADTOCHDR, &p_env->tochdr) == -1 ) { + cdio_warn("%s: %s\n", "error in ioctl CDROMREADTOCHDR", strerror(errno)); return false; } + p_env->gen.i_first_track = p_env->tochdr.cdth_trk0; + p_env->gen.i_tracks = p_env->tochdr.cdth_trk1; + /* read individual tracks */ - for (i= FIRST_TRACK_NUM; i<=TOTAL_TRACKS; i++) { - _obj->tocent[i-1].cdte_track = i; - _obj->tocent[i-1].cdte_format = CDROM_MSF; - if ( ioctl(_obj->gen.fd, CDROMREADTOCENTRY, &_obj->tocent[i-1]) == -1 ) { - cdio_error("%s %d: %s\n", + for (i= p_env->gen.i_first_track; i<=p_env->gen.i_tracks; i++) { + p_env->tocent[i-p_env->gen.i_first_track].cdte_track = i; + p_env->tocent[i-p_env->gen.i_first_track].cdte_format = CDROM_MSF; + if ( ioctl(p_env->gen.fd, CDROMREADTOCENTRY, + &p_env->tocent[i-p_env->gen.i_first_track]) == -1 ) { + cdio_warn("%s %d: %s\n", "error in ioctl CDROMREADTOCENTRY for track", i, strerror(errno)); return false; } /**** - struct cdrom_msf0 *msf= &_obj->tocent[i-1].cdte_addr.msf; + struct cdrom_msf0 *msf= &env->tocent[i-1].cdte_addr.msf; fprintf (stdout, "--- track# %d (msf %2.2x:%2.2x:%2.2x)\n", i, msf->minute, msf->second, msf->frame); @@ -639,282 +842,120 @@ _cdio_read_toc (_img_private_t *_obj) } /* read the lead-out track */ - _obj->tocent[TOTAL_TRACKS].cdte_track = CDIO_CDROM_LEADOUT_TRACK; - _obj->tocent[TOTAL_TRACKS].cdte_format = CDROM_MSF; + p_env->tocent[p_env->gen.i_tracks].cdte_track = CDIO_CDROM_LEADOUT_TRACK; + p_env->tocent[p_env->gen.i_tracks].cdte_format = CDROM_MSF; - if (ioctl(_obj->gen.fd, CDROMREADTOCENTRY, - &_obj->tocent[TOTAL_TRACKS]) == -1 ) { - cdio_error("%s: %s\n", + if (ioctl(p_env->gen.fd, CDROMREADTOCENTRY, + &p_env->tocent[p_env->gen.i_tracks]) == -1 ) { + cdio_warn("%s: %s\n", "error in ioctl CDROMREADTOCENTRY for lead-out", strerror(errno)); return false; } /* - struct cdrom_msf0 *msf= &_obj->tocent[TOTAL_TRACKS].cdte_addr.msf; + struct cdrom_msf0 *msf= &env->tocent[p_env->gen.i_tracks].cdte_addr.msf; fprintf (stdout, "--- track# %d (msf %2.2x:%2.2x:%2.2x)\n", i, msf->minute, msf->second, msf->frame); */ - _obj->gen.toc_init = true; + p_env->gen.toc_init = true; return true; } -/* - * Eject using SCSI commands. Return 1 if successful, 0 otherwise. - */ -static int -_cdio_eject_scsi(int fd) -{ - int status; - struct sdata { - int inlen; - int outlen; - char cmd[256]; - } scsi_cmd; - - scsi_cmd.inlen = 0; - scsi_cmd.outlen = 0; - scsi_cmd.cmd[0] = ALLOW_MEDIUM_REMOVAL; - scsi_cmd.cmd[1] = 0; - scsi_cmd.cmd[2] = 0; - scsi_cmd.cmd[3] = 0; - scsi_cmd.cmd[4] = 0; - scsi_cmd.cmd[5] = 0; - status = ioctl(fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd); - if (status != 0) - return 0; - - scsi_cmd.inlen = 0; - scsi_cmd.outlen = 0; - scsi_cmd.cmd[0] = START_STOP; - scsi_cmd.cmd[1] = 0; - scsi_cmd.cmd[2] = 0; - scsi_cmd.cmd[3] = 0; - scsi_cmd.cmd[4] = 1; - scsi_cmd.cmd[5] = 0; - status = ioctl(fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd); - if (status != 0) - return 0; - - scsi_cmd.inlen = 0; - scsi_cmd.outlen = 0; - scsi_cmd.cmd[0] = START_STOP; - scsi_cmd.cmd[1] = 0; - scsi_cmd.cmd[2] = 0; - scsi_cmd.cmd[3] = 0; - scsi_cmd.cmd[4] = 2; - scsi_cmd.cmd[5] = 0; - status = ioctl(fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd); - if (status != 0) - return 0; - - /* force kernel to reread partition table when new disc inserted */ - status = ioctl(fd, BLKRRPART); - return (status == 0); -} - /*! - Eject media in CD drive. - Return 0 if success and 1 for failure, and 2 if no routine. + Run a SCSI MMC command. + + cdio CD structure set by cdio_open(). + i_timeout time in milliseconds we will wait for the command + to complete. If this value is -1, use the default + time-out value. + p_buf Buffer for data, both sending and receiving + i_buf Size of buffer + e_direction direction the transfer is to go. + cdb CDB bytes. All values that are needed should be set on + input. We'll figure out what the right CDB length should be. + + We return true if command completed successfully and false if not. */ -static int -_cdio_eject_media (void *env) { - - _img_private_t *_obj = env; - int ret=2; - int status; - int fd; - - close(_obj->gen.fd); - _obj->gen.fd = -1; - if ((fd = open (_obj->gen.source_name, O_RDONLY|O_NONBLOCK)) > -1) { - if((status = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT)) > 0) { - switch(status) { - case CDS_TRAY_OPEN: - if((ret = ioctl(fd, CDROMCLOSETRAY)) != 0) { - cdio_error ("ioctl CDROMCLOSETRAY failed: %s\n", strerror(errno)); - ret = 1; - } - break; - case CDS_DISC_OK: - if((ret = ioctl(fd, CDROMEJECT)) != 0) { - int eject_error = errno; - /* Try ejecting the SCSI way... */ - ret = _cdio_eject_scsi(fd); - if (0 != ret) { - cdio_error("ioctl CDROMEJECT failed: %s\n", strerror(eject_error)); - ret = 1; - } - } - break; - default: - cdio_error ("Unknown CD-ROM (%d)\n", status); - ret = 1; - } - } else { - cdio_error ("CDROM_DRIVE_STATUS failed: %s\n", strerror(errno)); - ret=1; - } - close(fd); - return ret; - } - return 2; -} - -/*! - Return the value associated with the key "arg". -*/ -static const char * -_cdio_get_arg (void *env, const char key[]) +static int +run_scsi_cmd_linux( const void *p_user_data, + unsigned int i_timeout_ms, + unsigned int i_cdb, const scsi_mmc_cdb_t *p_cdb, + scsi_mmc_direction_t e_direction, + unsigned int i_buf, /*in/out*/ void *p_buf ) { - _img_private_t *_obj = env; - - if (!strcmp (key, "source")) { - return _obj->gen.source_name; - } else if (!strcmp (key, "access-mode")) { - switch (_obj->access_mode) { - case _AM_IOCTL: - return "ioctl"; - case _AM_READ_CD: - return "READ_CD"; - case _AM_READ_10: - return "READ_10"; - case _AM_NONE: - return "no access method"; - } - } - return NULL; -} + const _img_private_t *p_env = p_user_data; + struct cdrom_generic_command cgc; + memset (&cgc, 0, sizeof (struct cdrom_generic_command)); + memcpy(&cgc.cmd, p_cdb, i_cdb); + cgc.buflen = i_buf; + cgc.buffer = p_buf; + cgc.data_direction = (SCSI_MMC_DATA_READ == cgc.data_direction) + ? CGC_DATA_READ : CGC_DATA_WRITE; -/*! - Return the number of of the first track. - CDIO_INVALID_TRACK is returned on error. -*/ -static track_t -_cdio_get_first_track_num(void *env) -{ - _img_private_t *_obj = env; - - if (!_obj->gen.toc_init) _cdio_read_toc (_obj) ; +#ifdef HAVE_LINUX_CDROM_TIMEOUT + cgc.timeout = i_timeout_ms; +#endif - return FIRST_TRACK_NUM; + return ioctl (p_env->gen.fd, CDROM_SEND_PACKET, &cgc); } /*! - Return the media catalog number MCN. - - Note: string is malloc'd so caller should free() then returned - string when done with it. - + Return the size of the CD in logical block address (LBA) units. */ -static char * -_cdio_get_mcn (void *env) { - - struct cdrom_mcn mcn; - _img_private_t *_obj = env; - memset(&mcn, 0, sizeof(mcn)); - if (ioctl(_obj->gen.fd, CDROM_GET_MCN, &mcn) != 0) - return NULL; - return strdup(mcn.medium_catalog_number); -} - -/*! - Return the number of tracks in the current medium. - CDIO_INVALID_TRACK is returned on error. -*/ -static track_t -_cdio_get_num_tracks(void *env) +static uint32_t +stat_size_linux (void *p_user_data) { - _img_private_t *_obj = env; - - if (!_obj->gen.toc_init) _cdio_read_toc (_obj) ; + _img_private_t *p_env = p_user_data; - return TOTAL_TRACKS; -} + struct cdrom_tocentry tocent; + uint32_t size; -/*! - Get format of track. -*/ -static track_format_t -_cdio_get_track_format(void *env, track_t track_num) -{ - _img_private_t *_obj = env; - - if (!_obj->gen.toc_init) _cdio_read_toc (_obj) ; + tocent.cdte_track = CDIO_CDROM_LEADOUT_TRACK; + tocent.cdte_format = CDROM_LBA; + if (ioctl (p_env->gen.fd, CDROMREADTOCENTRY, &tocent) == -1) + { + perror ("ioctl(CDROMREADTOCENTRY)"); + exit (EXIT_FAILURE); + } - if (track_num > TOTAL_TRACKS || track_num == 0) - return TRACK_FORMAT_ERROR; + size = tocent.cdte_addr.lba; - /* This is pretty much copied from the "badly broken" cdrom_count_tracks - in linux/cdrom.c. - */ - if (_obj->tocent[track_num-1].cdte_ctrl & CDROM_DATA_TRACK) { - if (_obj->tocent[track_num-1].cdte_format == 0x10) - return TRACK_FORMAT_CDI; - else if (_obj->tocent[track_num-1].cdte_format == 0x20) - return TRACK_FORMAT_XA; - else - return TRACK_FORMAT_DATA; - } else - return TRACK_FORMAT_AUDIO; - + return size; } /*! - Return true if we have XA data (green, mode2 form1) or - XA data (green, mode2 form2). That is track begins: - sync - header - subheader - 12 4 - 8 - - FIXME: there's gotta be a better design for this and get_track_format? -*/ -static bool -_cdio_get_track_green(void *env, track_t track_num) -{ - _img_private_t *_obj = env; - - if (!_obj->gen.toc_init) _cdio_read_toc (_obj) ; - - if (track_num == CDIO_CDROM_LEADOUT_TRACK) track_num = TOTAL_TRACKS+1; - - if (track_num > TOTAL_TRACKS+1 || track_num == 0) - return false; - - /* FIXME: Dunno if this is the right way, but it's what - I was using in cdinfo for a while. - */ - return ((_obj->tocent[track_num-1].cdte_ctrl & 2) != 0); -} + Set the arg "key" with "value" in the source device. + Currently "source" and "access-mode" are valid keys. + "source" sets the source device in I/O operations + "access-mode" sets the the method of CD access -/*! - Return the starting MSF (minutes/secs/frames) for track number - track_num in obj. Track numbers start at 1. - The "leadout" track is specified either by - using track_num LEADOUT_TRACK or the total tracks+1. - False is returned if there is no track entry. + 0 is returned if no error was found, and nonzero if there as an error. */ -static bool -_cdio_get_track_msf(void *env, track_t track_num, msf_t *msf) +static int +set_arg_linux (void *p_user_data, const char key[], const char value[]) { - _img_private_t *_obj = env; - - if (NULL == msf) return false; + _img_private_t *p_env = p_user_data; - if (!_obj->gen.toc_init) _cdio_read_toc (_obj) ; + if (!strcmp (key, "source")) + { + if (!value) + return -2; - if (track_num == CDIO_CDROM_LEADOUT_TRACK) track_num = TOTAL_TRACKS+1; + free (p_env->gen.source_name); + + p_env->gen.source_name = strdup (value); + } + else if (!strcmp (key, "access-mode")) + { + return str_to_access_mode_linux(value); + } + else + return -1; - if (track_num > TOTAL_TRACKS+1 || track_num == 0) { - return false; - } else { - struct cdrom_msf0 *msf0= &_obj->tocent[track_num-1].cdte_addr.msf; - msf->m = to_bcd8(msf0->minute); - msf->s = to_bcd8(msf0->second); - msf->f = to_bcd8(msf0->frame); - return true; - } + return 0; } /* checklist: /dev/cdrom, /dev/dvd /dev/hd?, /dev/scd? /dev/sr? */ @@ -947,19 +988,19 @@ cdio_get_devices_linux (void) */ for ( i=0; strlen(checklist1[i]) > 0; ++i ) { sprintf(drive, "/dev/%s", checklist1[i]); - if ( (exists=cdio_is_cdrom(drive, NULL)) > 0 ) { + if ( (exists=is_cdrom_linux(drive, NULL)) > 0 ) { cdio_add_device_list(&drives, drive, &num_drives); } } /* Now check the currently mounted CD drives */ - if (NULL != (ret_drive = cdio_check_mounts("/etc/mtab"))) { + if (NULL != (ret_drive = check_mounts_linux("/etc/mtab"))) { cdio_add_device_list(&drives, ret_drive, &num_drives); free(ret_drive); } /* Finally check possible mountable drives in /etc/fstab */ - if (NULL != (ret_drive = cdio_check_mounts("/etc/fstab"))) { + if (NULL != (ret_drive = check_mounts_linux("/etc/fstab"))) { cdio_add_device_list(&drives, ret_drive, &num_drives); free(ret_drive); } @@ -977,7 +1018,7 @@ cdio_get_devices_linux (void) if ( insert != NULL ) { *insert = j; } - if ( (exists=cdio_is_cdrom(drive, NULL)) > 0 ) { + if ( (exists=is_cdrom_linux(drive, NULL)) > 0 ) { cdio_add_device_list(&drives, drive, &num_drives); } } @@ -1006,17 +1047,17 @@ cdio_get_default_device_linux(void) */ for ( i=0; strlen(checklist1[i]) > 0; ++i ) { sprintf(drive, "/dev/%s", checklist1[i]); - if ( (exists=cdio_is_cdrom(drive, NULL)) > 0 ) { + if ( (exists=is_cdrom_linux(drive, NULL)) > 0 ) { return strdup(drive); } } /* Now check the currently mounted CD drives */ - if (NULL != (ret_drive = cdio_check_mounts("/etc/mtab"))) + if (NULL != (ret_drive = check_mounts_linux("/etc/mtab"))) return ret_drive; /* Finally check possible mountable drives in /etc/fstab */ - if (NULL != (ret_drive = cdio_check_mounts("/etc/fstab"))) + if (NULL != (ret_drive = check_mounts_linux("/etc/fstab"))) return ret_drive; /* Scan the system for CD-ROM drives. @@ -1032,7 +1073,7 @@ cdio_get_default_device_linux(void) if ( insert != NULL ) { *insert = j; } - if ( (exists=cdio_is_cdrom(drive, NULL)) > 0 ) { + if ( (exists=is_cdrom_linux(drive, NULL)) > 0 ) { return(strdup(drive)); } } @@ -1046,57 +1087,91 @@ cdio_get_default_device_linux(void) ones to set that up. */ CdIo * -cdio_open_linux (const char *orig_source_name) +cdio_open_linux (const char *psz_source_name) +{ + return cdio_open_am_linux(psz_source_name, NULL); +} + +/*! + Initialization routine. This is the only thing that doesn't + get called via a function pointer. In fact *we* are the + ones to set that up. + */ +CdIo * +cdio_open_am_linux (const char *psz_orig_source, const char *access_mode) { #ifdef HAVE_LINUX_CDROM CdIo *ret; _img_private_t *_data; - char *source_name; + char *psz_source; cdio_funcs _funcs = { - .eject_media = _cdio_eject_media, + .eject_media = eject_media_linux, .free = cdio_generic_free, - .get_arg = _cdio_get_arg, - .get_devices = cdio_get_devices_linux, + .get_arg = get_arg_linux, + .get_cdtext = get_cdtext_generic, .get_default_device = cdio_get_default_device_linux, - .get_first_track_num= _cdio_get_first_track_num, - .get_mcn = _cdio_get_mcn, - .get_num_tracks = _cdio_get_num_tracks, - .get_track_format = _cdio_get_track_format, - .get_track_green = _cdio_get_track_green, + .get_devices = cdio_get_devices_linux, + .get_discmode = get_discmode_linux, +#if USE_LINUX_CAP + .get_drive_cap = get_drive_cap_linux, +#else + .get_drive_cap = scsi_mmc_get_drive_cap_generic, +#endif + .get_first_track_num= get_first_track_num_generic, + .get_hwinfo = NULL, + .get_mcn = get_mcn_linux, + .get_num_tracks = get_num_tracks_generic, + .get_track_format = get_track_format_linux, + .get_track_green = get_track_green_linux, .get_track_lba = NULL, /* This could be implemented if need be. */ - .get_track_msf = _cdio_get_track_msf, + .get_track_msf = get_track_msf_linux, .lseek = cdio_generic_lseek, .read = cdio_generic_read, - .read_audio_sectors = _cdio_read_audio_sectors, - .read_mode1_sector = _cdio_read_mode1_sector, - .read_mode1_sectors = _cdio_read_mode1_sectors, - .read_mode2_sector = _cdio_read_mode2_sector, - .read_mode2_sectors = _cdio_read_mode2_sectors, - .set_arg = _cdio_set_arg, - .stat_size = _cdio_stat_size + .read_audio_sectors = _read_audio_sectors_linux, + .read_mode1_sector = _read_mode1_sector_linux, + .read_mode1_sectors = _read_mode1_sectors_linux, + .read_mode2_sector = _read_mode2_sector_linux, + .read_mode2_sectors = _read_mode2_sectors_linux, + .read_toc = read_toc_linux, + .run_scsi_mmc_cmd = run_scsi_cmd_linux, + .set_arg = set_arg_linux, + .stat_size = stat_size_linux }; _data = _cdio_malloc (sizeof (_img_private_t)); - _data->access_mode = _AM_READ_CD; + + _data->access_mode = str_to_access_mode_linux(access_mode); _data->gen.init = false; + _data->gen.toc_init = false; _data->gen.fd = -1; + _data->gen.b_cdtext_init = false; + _data->gen.b_cdtext_error = false; + + if (NULL == psz_orig_source) { + psz_source=cdio_get_default_device_linux(); + if (NULL == psz_source) return NULL; + set_arg_linux(_data, "source", psz_source); + free(psz_source); + } else { + if (cdio_is_device_generic(psz_orig_source)) + set_arg_linux(_data, "source", psz_orig_source); + else { + /* The below would be okay if all device drivers worked this way. */ +#if 0 + cdio_info ("source %s is not a device", psz_orig_source); +#endif + return NULL; + } + } - if (NULL == orig_source_name) { - source_name=cdio_get_default_device_linux(); - if (NULL == source_name) return NULL; - _cdio_set_arg(_data, "source", source_name); - free(source_name); - } else - _cdio_set_arg(_data, "source", orig_source_name); - - ret = cdio_new (_data, &_funcs); + ret = cdio_new ((void *)_data, &_funcs); if (ret == NULL) return NULL; - if (cdio_generic_init(_data)) + if (cdio_generic_init(_data)) { return ret; - else { + } else { cdio_generic_free (_data); return NULL; } @@ -1116,5 +1191,3 @@ cdio_have_linux (void) return false; #endif /* HAVE_LINUX_CDROM */ } - - diff --git a/src/input/vcd/libcdio/_cdio_osx.c b/src/input/vcd/libcdio/_cdio_osx.c index 3e479f76d..f754933c6 100644 --- a/src/input/vcd/libcdio/_cdio_osx.c +++ b/src/input/vcd/libcdio/_cdio_osx.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_osx.c,v 1.3 2004/10/20 05:04:00 athp Exp $ + $Id: _cdio_osx.c,v 1.4 2005/01/01 02:43:57 rockyb Exp $ Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> from vcdimager code: @@ -9,6 +9,7 @@ Gildas Bazin <gbazin@netcourrier.com> Jon Lech Johansen <jon-vl@nanocrew.net> Derk-Jan Hartman <hartman at videolan.org> + Justin F. Hallett <thesin@southofheaven.org> 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 @@ -30,11 +31,12 @@ */ #ifdef HAVE_CONFIG_H -# include "config.h" +#include "config.h" #endif -static const char _rcsid[] = "$Id: _cdio_osx.c,v 1.3 2004/10/20 05:04:00 athp Exp $"; +static const char _rcsid[] = "$Id: _cdio_osx.c,v 1.4 2005/01/01 02:43:57 rockyb Exp $"; +#include <cdio/logging.h> #include <cdio/sector.h> #include <cdio/util.h> #include "cdio_assert.h" @@ -43,6 +45,17 @@ static const char _rcsid[] = "$Id: _cdio_osx.c,v 1.3 2004/10/20 05:04:00 athp Ex #include <string.h> #ifdef HAVE_DARWIN_CDROM +#undef VERSION + +#include <CoreFoundation/CoreFoundation.h> +#include <IOKit/IOKitLib.h> +#include <IOKit/storage/IOStorageDeviceCharacteristics.h> + +#include <mach/mach.h> +#include <Carbon/Carbon.h> +#include <IOKit/scsi-commands/SCSITaskLib.h> +#include <IOKit/IOCFPlugIn.h> +#include <mach/mach_error.h> #include <stdio.h> #include <stdlib.h> @@ -54,72 +67,575 @@ static const char _rcsid[] = "$Id: _cdio_osx.c,v 1.3 2004/10/20 05:04:00 athp Ex #include <sys/types.h> #include <sys/ioctl.h> + #include <paths.h> -#include <CoreFoundation/CFBase.h> -#include <CoreFoundation/CFString.h> -#include <CoreFoundation/CFNumber.h> +#include <CoreFoundation/CoreFoundation.h> #include <IOKit/IOKitLib.h> #include <IOKit/IOBSD.h> +#include <IOKit/scsi-commands/IOSCSIMultimediaCommandsDevice.h> #include <IOKit/storage/IOCDTypes.h> +#include <IOKit/storage/IODVDTypes.h> #include <IOKit/storage/IOMedia.h> #include <IOKit/storage/IOCDMedia.h> +#include <IOKit/storage/IODVDMedia.h> #include <IOKit/storage/IOCDMediaBSDClient.h> +#include <IOKit/storage/IODVDMediaBSDClient.h> +#include <IOKit/storage/IOStorageDeviceCharacteristics.h> + +#define kIOCDBlockStorageDeviceClassString "IOCDBlockStorageDevice" + +/* Note leadout is normally defined 0xAA, But on OSX 0xA0 is "lead in" while + 0xA2 is "lead out". Don't ask me why. */ +#define OSX_CDROM_LEADOUT_TRACK 0xA2 -#define TOTAL_TRACKS (_obj->num_tracks) +#define TOTAL_TRACKS (p_env->i_last_track - p_env->gen.i_first_track + 1) +#define CDROM_CDI_TRACK 0x1 +#define CDROM_XA_TRACK 0x2 + +typedef enum { + _AM_NONE, + _AM_OSX, +} access_mode_t; + +#define MAX_SERVICE_NAME 1000 typedef struct { /* Things common to all drivers like this. This must be first. */ generic_img_private_t gen; - enum { - _AM_NONE, - _AM_OSX, - } access_mode; + access_mode_t access_mode; /* Track information */ - bool toc_init; /* if true, info below is valid. */ CDTOC *pTOC; int i_descriptors; - track_t num_tracks; + track_t i_last_track; /* highest track number */ + track_t i_last_session; /* highest session number */ + track_t i_first_session; /* first session number */ lsn_t *pp_lba; + io_service_t MediaClass_service; + char psz_MediaClass_service[MAX_SERVICE_NAME]; + SCSITaskDeviceInterface **pp_scsiTaskDeviceInterface; } _img_private_t; -static void -_cdio_osx_free (void *env) { - _img_private_t *_obj = env; - if (NULL == _obj) return; - cdio_generic_free(_obj); - if (NULL != _obj->pp_lba) free((void *) _obj->pp_lba); - if (NULL != _obj->pTOC) free((void *) _obj->pTOC); +static bool read_toc_osx (void *p_user_data); + +/**** + * GetRegistryEntryProperties - Gets the registry entry properties for + * an io_service_t. + *****/ + +static CFMutableDictionaryRef +GetRegistryEntryProperties ( io_service_t service ) +{ + IOReturn err = kIOReturnSuccess; + CFMutableDictionaryRef dict = 0; + + err = IORegistryEntryCreateCFProperties (service, &dict, kCFAllocatorDefault, 0); + if ( err != kIOReturnSuccess ) + cdio_warn( "IORegistryEntryCreateCFProperties: 0x%08x", err ); + + return dict; } -/**************************************************************************** - cdio_getNumberOfTracks: get number of tracks in TOC - This is an internal routine and is called once per CD open. - ****************************************************************************/ -static track_t -_cdio_getNumberOfTracks( CDTOC *pTOC, int i_descriptors ) + +static bool +init_osx(_img_private_t *p_env) { + mach_port_t port; + char *psz_devname; + kern_return_t ret; + io_iterator_t iterator; + + p_env->gen.fd = open( p_env->gen.source_name, O_RDONLY | O_NONBLOCK ); + if (-1 == p_env->gen.fd) { + cdio_warn("Failed to open %s: %s", p_env->gen.source_name, + strerror(errno)); + return false; + } + + /* get the device name */ + psz_devname = strrchr( p_env->gen.source_name, '/'); + if( NULL != psz_devname ) + ++psz_devname; + else + psz_devname = p_env->gen.source_name; + + /* unraw the device name */ + if( *psz_devname == 'r' ) + ++psz_devname; + + /* get port for IOKit communication */ + ret = IOMasterPort( MACH_PORT_NULL, &port ); + + if( ret != KERN_SUCCESS ) + { + cdio_warn( "IOMasterPort: 0x%08x", ret ); + return false; + } + + ret = IOServiceGetMatchingServices( port, + IOBSDNameMatching(port, 0, psz_devname), + &iterator ); + + /* get service iterator for the device */ + if( ret != KERN_SUCCESS ) + { + cdio_warn( "IOServiceGetMatchingServices: 0x%08x", ret ); + return false; + } + + /* first service */ + p_env->MediaClass_service = IOIteratorNext( iterator ); + IOObjectRelease( iterator ); + + /* search for kIOCDMediaClass or kIOCDVDMediaClass */ + while( p_env->MediaClass_service && + (!IOObjectConformsTo(p_env->MediaClass_service, kIOCDMediaClass)) && + (!IOObjectConformsTo(p_env->MediaClass_service, kIODVDMediaClass)) ) + { + + ret = IORegistryEntryGetParentIterator( p_env->MediaClass_service, + kIOServicePlane, + &iterator ); + if( ret != KERN_SUCCESS ) + { + cdio_warn( "IORegistryEntryGetParentIterator: 0x%08x", ret ); + IOObjectRelease( p_env->MediaClass_service ); + return false; + } + + IOObjectRelease( p_env->MediaClass_service ); + p_env->MediaClass_service = IOIteratorNext( iterator ); + IOObjectRelease( iterator ); + } + + if ( 0 == p_env->MediaClass_service ) { + cdio_warn( "search for kIOCDMediaClass/kIODVDMediaClass came up empty" ); + return false; + } + + /* Save the name so we can compare against this in case we have to do + another scan. FIXME: this is hoaky and there's got to be a better + variable to test or way to do. + */ + IORegistryEntryGetPath(p_env->MediaClass_service, kIOServicePlane, + p_env->psz_MediaClass_service); + return true; +} + +/*! + Run a SCSI MMC command. + + cdio CD structure set by cdio_open(). + i_timeout time in milliseconds we will wait for the command + to complete. If this value is -1, use the default + time-out value. + p_buf Buffer for data, both sending and receiving + i_buf Size of buffer + e_direction direction the transfer is to go. + cdb CDB bytes. All values that are needed should be set on + input. We'll figure out what the right CDB length should be. + + We return true if command completed successfully and false if not. + */ +static int +run_scsi_cmd_osx( const void *p_user_data, + unsigned int i_timeout_ms, + unsigned int i_cdb, const scsi_mmc_cdb_t *p_cdb, + scsi_mmc_direction_t e_direction, + unsigned int i_buf, /*in/out*/ void *p_buf ) { - track_t track = CDIO_INVALID_TRACK; - int i; - int i_tracks = 0; - CDTOCDescriptor *pTrackDescriptors; - pTrackDescriptors = pTOC->descriptors; +#ifndef SCSI_MMC_FIXED + return 2; +#else + const _img_private_t *p_env = p_user_data; + SCSITaskDeviceInterface **sc; + SCSITaskInterface **cmd = NULL; + IOVirtualRange iov; + SCSI_Sense_Data senseData; + SCSITaskStatus status; + UInt64 bytesTransferred; + IOReturn ioReturnValue; + int ret = 0; + + if (NULL == p_user_data) return 2; + + /* Make sure pp_scsiTaskDeviceInterface is initialized. FIXME: The code + should probably be reorganized better for this. */ + if (!p_env->gen.toc_init) read_toc_osx (p_user_data) ; + + sc = p_env->pp_scsiTaskDeviceInterface; + + if (NULL == sc) return 3; + + cmd = (*sc)->CreateSCSITask(sc); + if (cmd == NULL) { + cdio_warn("Failed to create SCSI task"); + return -1; + } + + iov.address = (IOVirtualAddress) p_buf; + iov.length = i_buf; + + ioReturnValue = (*cmd)->SetCommandDescriptorBlock(cmd, (UInt8 *) p_cdb, + i_cdb); + if (ioReturnValue != kIOReturnSuccess) { + cdio_warn("SetCommandDescriptorBlock failed with status %x", + ioReturnValue); + return -1; + } + + ioReturnValue = (*cmd)->SetScatterGatherEntries(cmd, &iov, 1, i_buf, + (SCSI_MMC_DATA_READ == e_direction ) ? + kSCSIDataTransfer_FromTargetToInitiator : + kSCSIDataTransfer_FromInitiatorToTarget); + if (ioReturnValue != kIOReturnSuccess) { + cdio_warn("SetScatterGatherEntries failed with status %x", ioReturnValue); + return -1; + } + + ioReturnValue = (*cmd)->SetTimeoutDuration(cmd, i_timeout_ms ); + if (ioReturnValue != kIOReturnSuccess) { + cdio_warn("SetTimeoutDuration failed with status %x", ioReturnValue); + return -1; + } + + memset(&senseData, 0, sizeof(senseData)); - for( i = i_descriptors; i >= 0; i-- ) + ioReturnValue = (*cmd)->ExecuteTaskSync(cmd,&senseData, &status, & + bytesTransferred); + + if (ioReturnValue != kIOReturnSuccess) { + cdio_warn("Command execution failed with status %x", ioReturnValue); + return -1; + } + + if (cmd != NULL) { + (*cmd)->Release(cmd); + } + + return (ret); +#endif +} + +/*************************************************************************** + * GetDeviceIterator - Gets an io_iterator_t for our class type + ***************************************************************************/ + +static io_iterator_t +GetDeviceIterator ( const char * deviceClass ) +{ + + IOReturn err = kIOReturnSuccess; + io_iterator_t iterator = MACH_PORT_NULL; + + err = IOServiceGetMatchingServices ( kIOMasterPortDefault, + IOServiceMatching ( deviceClass ), + &iterator ); + check ( err == kIOReturnSuccess ); + + return iterator; + +} + +/*************************************************************************** + * GetFeaturesFlagsForDrive -Gets the bitfield which represents the + * features flags. + ***************************************************************************/ + +static bool +GetFeaturesFlagsForDrive ( CFDictionaryRef dict, + uint32_t *i_cdFlags, + uint32_t *i_dvdFlags ) +{ + CFDictionaryRef propertiesDict = 0; + CFNumberRef flagsNumberRef = 0; + + *i_cdFlags = 0; + *i_dvdFlags= 0; + + propertiesDict = ( CFDictionaryRef ) + CFDictionaryGetValue ( dict, + CFSTR ( kIOPropertyDeviceCharacteristicsKey ) ); + + if ( propertiesDict == 0 ) return false; + + /* Get the CD features */ + flagsNumberRef = ( CFNumberRef ) + CFDictionaryGetValue ( propertiesDict, + CFSTR ( kIOPropertySupportedCDFeatures ) ); + if ( flagsNumberRef != 0 ) { + CFNumberGetValue ( flagsNumberRef, kCFNumberLongType, i_cdFlags ); + } + + /* Get the DVD features */ + flagsNumberRef = ( CFNumberRef ) + CFDictionaryGetValue ( propertiesDict, + CFSTR ( kIOPropertySupportedDVDFeatures ) ); + if ( flagsNumberRef != 0 ) { + CFNumberGetValue ( flagsNumberRef, kCFNumberLongType, i_dvdFlags ); + } + + return true; +} + +/*! + Get disc type associated with the cd object. +*/ +static discmode_t +get_discmode_osx (void *p_user_data) +{ + _img_private_t *p_env = p_user_data; + char str[10]; + int32_t i_discmode = CDIO_DISC_MODE_ERROR; + CFDictionaryRef propertiesDict = 0; + CFStringRef data; + + propertiesDict = GetRegistryEntryProperties ( p_env->MediaClass_service ); + + if ( propertiesDict == 0 ) return i_discmode; + + data = ( CFStringRef ) + CFDictionaryGetValue ( propertiesDict, CFSTR ( kIODVDMediaTypeKey ) ); + + if( CFStringGetCString( data, str, sizeof(str), + kCFStringEncodingASCII ) ) { + if (0 == strncmp(str, "DVD+R", strlen(str)) ) + i_discmode = CDIO_DISC_MODE_DVD_PR; + else if (0 == strncmp(str, "DVD+RW", strlen(str)) ) + i_discmode = CDIO_DISC_MODE_DVD_PRW; + else if (0 == strncmp(str, "DVD-R", strlen(str)) ) + i_discmode = CDIO_DISC_MODE_DVD_R; + else if (0 == strncmp(str, "DVD-RW", strlen(str)) ) + i_discmode = CDIO_DISC_MODE_DVD_RW; + else if (0 == strncmp(str, "DVD-ROM", strlen(str)) ) + i_discmode = CDIO_DISC_MODE_DVD_ROM; + else if (0 == strncmp(str, "DVD-RAM", strlen(str)) ) + i_discmode = CDIO_DISC_MODE_DVD_RAM; + else if (0 == strncmp(str, "CD-ROM", strlen(str)) ) + i_discmode = CDIO_DISC_MODE_CD_DATA; + else if (0 == strncmp(str, "CDR", strlen(str)) ) + i_discmode = CDIO_DISC_MODE_CD_DATA; + else if (0 == strncmp(str, "CDRW", strlen(str)) ) + i_discmode = CDIO_DISC_MODE_CD_DATA; + //?? Handled by below? CFRelease( data ); + } + CFRelease( propertiesDict ); + if (CDIO_DISC_MODE_CD_DATA == i_discmode) { + /* Need to do more classification */ + return get_discmode_cd_generic(p_user_data); + } + return i_discmode; + +} + +static io_service_t +get_drive_service_osx(const _img_private_t *p_env) +{ + io_service_t service; + io_iterator_t service_iterator; + + service_iterator = GetDeviceIterator ( kIOCDBlockStorageDeviceClassString ); + + if( service_iterator == MACH_PORT_NULL ) return 0; + + service = IOIteratorNext( service_iterator ); + if( service == 0 ) return 0; + + do { - track = pTrackDescriptors[i].point; + char psz_service[MAX_SERVICE_NAME]; + IORegistryEntryGetPath(service, kIOServicePlane, psz_service); + psz_service[MAX_SERVICE_NAME-1] = '\0'; + + /* FIXME: This is all hoaky. Here we need info from a parent class, + psz_service of what we opened above. We are relying on the + fact that the name will be a substring of the name we + openned with. + */ + if (0 == strncmp(psz_service, p_env->psz_MediaClass_service, + strlen(psz_service))) { + /* Found our device */ + IOObjectRelease( service_iterator ); + return service; + } + + IOObjectRelease( service ); + + } while( ( service = IOIteratorNext( service_iterator ) ) != 0 ); - if( track > CDIO_CD_MAX_TRACKS || track < CDIO_CD_MIN_TRACK_NO ) - continue; + IOObjectRelease( service_iterator ); + return service; +} - i_tracks++; +static void +get_drive_cap_osx(const void *p_user_data, + /*out*/ cdio_drive_read_cap_t *p_read_cap, + /*out*/ cdio_drive_write_cap_t *p_write_cap, + /*out*/ cdio_drive_misc_cap_t *p_misc_cap) +{ + const _img_private_t *p_env = p_user_data; + uint32_t i_cdFlags; + uint32_t i_dvdFlags; + + io_service_t service = get_drive_service_osx(p_env); + + if( service == 0 ) goto err_exit; + + /* Found our device */ + { + CFDictionaryRef properties = GetRegistryEntryProperties ( service ); + + if (! GetFeaturesFlagsForDrive ( properties, &i_cdFlags, + &i_dvdFlags ) ) { + IOObjectRelease( service ); + goto err_exit; } + + /* Reader */ + + if ( 0 != (i_cdFlags & kCDFeaturesAnalogAudioMask) ) + *p_read_cap |= CDIO_DRIVE_CAP_READ_AUDIO; + + if ( 0 != (i_cdFlags & kCDFeaturesWriteOnceMask) ) + *p_write_cap |= CDIO_DRIVE_CAP_WRITE_CD_R; + + if ( 0 != (i_cdFlags & kCDFeaturesCDDAStreamAccurateMask) ) + *p_read_cap |= CDIO_DRIVE_CAP_READ_CD_DA; + + if ( 0 != (i_dvdFlags & kDVDFeaturesReadStructuresMask) ) + *p_read_cap |= CDIO_DRIVE_CAP_READ_DVD_ROM; + + if ( 0 != (i_cdFlags & kCDFeaturesReWriteableMask) ) + *p_write_cap |= CDIO_DRIVE_CAP_WRITE_CD_RW; + + if ( 0 != (i_dvdFlags & kDVDFeaturesWriteOnceMask) ) + *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_R; + + if ( 0 != (i_dvdFlags & kDVDFeaturesRandomWriteableMask) ) + *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_RAM; + + if ( 0 != (i_dvdFlags & kDVDFeaturesReWriteableMask) ) + *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_RW; + + /*** + if ( 0 != (i_dvdFlags & kDVDFeaturesPlusRMask) ) + *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_PR; + + if ( 0 != (i_dvdFlags & kDVDFeaturesPlusRWMask ) + *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_PRW; + ***/ + + /* FIXME: fill out. For now assume CD-ROM is relatively modern. */ + *p_misc_cap = ( + CDIO_DRIVE_CAP_MISC_CLOSE_TRAY + | CDIO_DRIVE_CAP_MISC_EJECT + | CDIO_DRIVE_CAP_MISC_LOCK + | CDIO_DRIVE_CAP_MISC_SELECT_SPEED + | CDIO_DRIVE_CAP_MISC_MULTI_SESSION + | CDIO_DRIVE_CAP_MISC_MEDIA_CHANGED + | CDIO_DRIVE_CAP_MISC_RESET + | CDIO_DRIVE_CAP_MCN + | CDIO_DRIVE_CAP_ISRC + ); + + IOObjectRelease( service ); + } + + return; + + err_exit: + *p_misc_cap = *p_write_cap = *p_read_cap = CDIO_DRIVE_CAP_UNKNOWN; + return; +} + +#if 1 +/**************************************************************************** + * GetDriveDescription - Gets drive description. + ****************************************************************************/ + +static bool +get_hwinfo_osx ( const CdIo *p_cdio, /*out*/ cdio_hwinfo_t *hw_info) +{ + _img_private_t *p_env = (_img_private_t *) p_cdio->env; + io_service_t service = get_drive_service_osx(p_env); + + if ( service == 0 ) return false; + + /* Found our device */ + { + CFStringRef vendor = NULL; + CFStringRef product = NULL; + CFStringRef revision = NULL; + + CFDictionaryRef properties = GetRegistryEntryProperties ( service ); + CFDictionaryRef deviceDict = ( CFDictionaryRef ) + CFDictionaryGetValue ( properties, + CFSTR ( kIOPropertyDeviceCharacteristicsKey ) ); + + if ( deviceDict == 0 ) return false; + + vendor = ( CFStringRef ) + CFDictionaryGetValue ( deviceDict, CFSTR ( kIOPropertyVendorNameKey ) ); + + if ( CFStringGetCString( vendor, + (char *) &(hw_info->psz_vendor), + sizeof(hw_info->psz_vendor), + kCFStringEncodingASCII ) ) + CFRelease( vendor ); + + product = ( CFStringRef ) + CFDictionaryGetValue ( deviceDict, CFSTR ( kIOPropertyProductNameKey ) ); + + if ( CFStringGetCString( product, + (char *) &(hw_info->psz_model), + sizeof(hw_info->psz_model), + kCFStringEncodingASCII ) ) + CFRelease( product ); + + revision = ( CFStringRef ) + CFDictionaryGetValue ( deviceDict, + CFSTR ( kIOPropertyProductRevisionLevelKey ) ); + + if ( CFStringGetCString( product, + (char *) &(hw_info->psz_revision), + sizeof(hw_info->psz_revision), + kCFStringEncodingASCII ) ) + CFRelease( revision ); + } + return true; + +} +#endif + +/*! + Return the media catalog number MCN. + + Note: string is malloc'd so caller should free() then returned + string when done with it. + + */ +static const cdtext_t * +get_cdtext_osx (void *p_user_data, track_t i_track) +{ + return NULL; +} + +static void +_free_osx (void *p_user_data) { + _img_private_t *p_env = p_user_data; + if (NULL == p_env) return; + cdio_generic_free(p_env); + if (NULL != p_env->pp_lba) free((void *) p_env->pp_lba); + if (NULL != p_env->pTOC) free((void *) p_env->pTOC); + IOObjectRelease( p_env->MediaClass_service ); + + if (NULL != p_env->pp_scsiTaskDeviceInterface) + ( *(p_env->pp_scsiTaskDeviceInterface) )-> + Release ( (p_env->pp_scsiTaskDeviceInterface) ); - return( i_tracks ); } /*! @@ -128,10 +644,10 @@ _cdio_getNumberOfTracks( CDTOC *pTOC, int i_descriptors ) Returns 0 if no error. */ static int -_cdio_read_mode1_sectors (void *env, void *data, lsn_t lsn, - bool is_form2, unsigned int nblocks) +_get_read_mode1_sectors_osx (void *user_data, void *data, lsn_t lsn, + bool b_form2, unsigned int nblocks) { - _img_private_t *_obj = env; + _img_private_t *env = user_data; dk_cd_read_t cd_read; memset( &cd_read, 0, sizeof(cd_read) ); @@ -140,7 +656,7 @@ _cdio_read_mode1_sectors (void *env, void *data, lsn_t lsn, cd_read.buffer = data; cd_read.sectorType = kCDSectorTypeMode1; - if (is_form2) { + if (b_form2) { cd_read.offset = lsn * kCDSectorSizeMode2; cd_read.bufferLength = kCDSectorSizeMode2 * nblocks; } else { @@ -148,9 +664,9 @@ _cdio_read_mode1_sectors (void *env, void *data, lsn_t lsn, cd_read.bufferLength = kCDSectorSizeMode1 * nblocks; } - if( ioctl( _obj->gen.fd, DKIOCCDREAD, &cd_read ) == -1 ) + if( ioctl( env->gen.fd, DKIOCCDREAD, &cd_read ) == -1 ) { - cdio_error( "could not read block %d, %s", lsn, strerror(errno) ); + cdio_info( "could not read block %d, %s", lsn, strerror(errno) ); return -1; } return 0; @@ -163,10 +679,10 @@ _cdio_read_mode1_sectors (void *env, void *data, lsn_t lsn, Returns 0 if no error. */ static int -_cdio_read_mode2_sectors (void *env, void *data, lsn_t lsn, - bool is_form2, unsigned int nblocks) +_get_read_mode2_sectors_osx (void *user_data, void *data, lsn_t lsn, + bool b_form2, unsigned int nblocks) { - _img_private_t *_obj = env; + _img_private_t *env = user_data; dk_cd_read_t cd_read; memset( &cd_read, 0, sizeof(cd_read) ); @@ -174,7 +690,7 @@ _cdio_read_mode2_sectors (void *env, void *data, lsn_t lsn, cd_read.sectorArea = kCDSectorAreaUser; cd_read.buffer = data; - if (is_form2) { + if (b_form2) { cd_read.offset = lsn * kCDSectorSizeMode2Form2; cd_read.sectorType = kCDSectorTypeMode2Form2; cd_read.bufferLength = kCDSectorSizeMode2Form2 * nblocks; @@ -184,9 +700,9 @@ _cdio_read_mode2_sectors (void *env, void *data, lsn_t lsn, cd_read.bufferLength = kCDSectorSizeMode2Form1 * nblocks; } - if( ioctl( _obj->gen.fd, DKIOCCDREAD, &cd_read ) == -1 ) + if( ioctl( env->gen.fd, DKIOCCDREAD, &cd_read ) == -1 ) { - cdio_error( "could not read block %d, %s", lsn, strerror(errno) ); + cdio_info( "could not read block %d, %s", lsn, strerror(errno) ); return -1; } return 0; @@ -198,24 +714,24 @@ _cdio_read_mode2_sectors (void *env, void *data, lsn_t lsn, Returns 0 if no error. */ static int -_cdio_read_audio_sectors (void *env, void *data, lsn_t lsn, - unsigned int nblocks) +_get_read_audio_sectors_osx (void *user_data, void *data, lsn_t lsn, + unsigned int nblocks) { - _img_private_t *_obj = env; + _img_private_t *env = user_data; dk_cd_read_t cd_read; memset( &cd_read, 0, sizeof(cd_read) ); - cd_read.offset = lsn * kCDSectorSizeCDDA; - cd_read.sectorArea = kCDSectorAreaUser; - cd_read.sectorType = kCDSectorTypeCDDA; + cd_read.offset = lsn * kCDSectorSizeCDDA; + cd_read.sectorArea = kCDSectorAreaUser; + cd_read.sectorType = kCDSectorTypeCDDA; - cd_read.buffer = data; + cd_read.buffer = data; cd_read.bufferLength = kCDSectorSizeCDDA * nblocks; - if( ioctl( _obj->gen.fd, DKIOCCDREAD, &cd_read ) == -1 ) + if( ioctl( env->gen.fd, DKIOCCDREAD, &cd_read ) == -1 ) { - cdio_error( "could not read block %d", lsn ); + cdio_info( "could not read block %d", lsn ); return -1; } return 0; @@ -226,10 +742,10 @@ _cdio_read_audio_sectors (void *env, void *data, lsn_t lsn, from lsn. Returns 0 if no error. */ static int -_cdio_read_mode1_sector (void *env, void *data, lsn_t lsn, - bool is_form2) +_get_read_mode1_sector_osx (void *user_data, void *data, lsn_t lsn, + bool b_form2) { - return _cdio_read_mode1_sectors(env, data, lsn, is_form2, 1); + return _get_read_mode1_sectors_osx(user_data, data, lsn, b_form2, 1); } /*! @@ -237,35 +753,35 @@ _cdio_read_mode1_sector (void *env, void *data, lsn_t lsn, from lsn. Returns 0 if no error. */ static int -_cdio_read_mode2_sector (void *env, void *data, lsn_t lsn, - bool is_form2) +_get_read_mode2_sector_osx (void *user_data, void *data, lsn_t lsn, + bool b_form2) { - return _cdio_read_mode2_sectors(env, data, lsn, is_form2, 1); + return _get_read_mode2_sectors_osx(user_data, data, lsn, b_form2, 1); } /*! Set the key "arg" to "value" in source device. */ static int -_cdio_set_arg (void *env, const char key[], const char value[]) +_set_arg_osx (void *user_data, const char key[], const char value[]) { - _img_private_t *_obj = env; + _img_private_t *env = user_data; if (!strcmp (key, "source")) { if (!value) return -2; - free (_obj->gen.source_name); + free (env->gen.source_name); - _obj->gen.source_name = strdup (value); + env->gen.source_name = strdup (value); } else if (!strcmp (key, "access-mode")) { if (!strcmp(value, "OSX")) - _obj->access_mode = _AM_OSX; + env->access_mode = _AM_OSX; else - cdio_error ("unknown access type: %s. ignored.", value); + cdio_warn ("unknown access type: %s. ignored.", value); } else return -1; @@ -273,168 +789,194 @@ _cdio_set_arg (void *env, const char key[], const char value[]) return 0; } +#if 0 +static void TestDevice(_img_private_t *p_env, io_service_t service) +{ + SInt32 score; + HRESULT herr; + kern_return_t err; + IOCFPlugInInterface **plugInInterface = NULL; + MMCDeviceInterface **mmcInterface = NULL; + + /* Create the IOCFPlugIn interface so we can query it. */ + + err = IOCreatePlugInInterfaceForService ( service, + kIOMMCDeviceUserClientTypeID, + kIOCFPlugInInterfaceID, + &plugInInterface, + &score ); + if ( err != noErr ) { + printf("IOCreatePlugInInterfaceForService returned %d\n", err); + return; + } + + /* Query the interface for the MMCDeviceInterface. */ + + herr = ( *plugInInterface )->QueryInterface ( plugInInterface, + CFUUIDGetUUIDBytes ( kIOMMCDeviceInterfaceID ), + ( LPVOID ) &mmcInterface ); + + if ( herr != S_OK ) { + printf("QueryInterface returned %ld\n", herr); + return; + } + + p_env->pp_scsiTaskDeviceInterface = + ( *mmcInterface )->GetSCSITaskDeviceInterface ( mmcInterface ); + + if ( NULL == p_env->pp_scsiTaskDeviceInterface ) { + printf("GetSCSITaskDeviceInterface returned NULL\n"); + return; + } + + ( *mmcInterface )->Release ( mmcInterface ); + IODestroyPlugInInterface ( plugInInterface ); +} +#endif + /*! Read and cache the CD's Track Table of Contents and track info. Return false if successful or true if an error. */ static bool -_cdio_read_toc (_img_private_t *_obj) +read_toc_osx (void *p_user_data) { - mach_port_t port; - char *psz_devname; - kern_return_t ret; - io_iterator_t iterator; - io_registry_entry_t service; - CFMutableDictionaryRef properties; + _img_private_t *p_env = p_user_data; + CFDictionaryRef propertiesDict = 0; CFDataRef data; - - _obj->gen.fd = open( _obj->gen.source_name, O_RDONLY | O_NONBLOCK ); - if (-1 == _obj->gen.fd) { - cdio_error("Failed to open %s: %s", _obj->gen.source_name, - strerror(errno)); + + /* create a CF dictionary containing the TOC */ + propertiesDict = GetRegistryEntryProperties( p_env->MediaClass_service ); + + if ( 0 == propertiesDict ) { return false; } - /* get the device name */ - if( ( psz_devname = strrchr( _obj->gen.source_name, '/') ) != NULL ) - ++psz_devname; - else - psz_devname = _obj->gen.source_name; - - /* unraw the device name */ - if( *psz_devname == 'r' ) - ++psz_devname; - - /* get port for IOKit communication */ - if( ( ret = IOMasterPort( MACH_PORT_NULL, &port ) ) != KERN_SUCCESS ) - { - cdio_error( "IOMasterPort: 0x%08x", ret ); - return false; - } - - /* get service iterator for the device */ - if( ( ret = IOServiceGetMatchingServices( - port, IOBSDNameMatching( port, 0, psz_devname ), - &iterator ) ) != KERN_SUCCESS ) - { - cdio_error( "IOServiceGetMatchingServices: 0x%08x", ret ); - return false; - } - - /* first service */ - service = IOIteratorNext( iterator ); - IOObjectRelease( iterator ); - - /* search for kIOCDMediaClass */ - while( service && !IOObjectConformsTo( service, kIOCDMediaClass ) ) - { - - ret = IORegistryEntryGetParentIterator( service, kIOServicePlane, - &iterator ); - if( ret != KERN_SUCCESS ) - { - cdio_error( "IORegistryEntryGetParentIterator: 0x%08x", ret ); - IOObjectRelease( service ); - return false; - } - - IOObjectRelease( service ); - service = IOIteratorNext( iterator ); - IOObjectRelease( iterator ); - } - - if( service == 0 ) - { - cdio_error( "search for kIOCDMediaClass came up empty" ); - return false; - } - - /* create a CF dictionary containing the TOC */ - ret = IORegistryEntryCreateCFProperties( service, &properties, - kCFAllocatorDefault, kNilOptions ); - - if( ret != KERN_SUCCESS ) - { - cdio_error( "IORegistryEntryCreateCFProperties: 0x%08x", ret ); - IOObjectRelease( service ); - return false; - } - /* get the TOC from the dictionary */ - data = (CFDataRef) CFDictionaryGetValue( properties, + data = (CFDataRef) CFDictionaryGetValue( propertiesDict, CFSTR(kIOCDMediaTOCKey) ); - if( data != NULL ) - { - CFRange range; - CFIndex buf_len; - - buf_len = CFDataGetLength( data ) + 1; - range = CFRangeMake( 0, buf_len ); - - if( ( _obj->pTOC = (CDTOC *)malloc( buf_len ) ) != NULL ) { - CFDataGetBytes( data, range, (u_char *) _obj->pTOC ); - } else { - cdio_error( "Trouble allocating CDROM TOC" ); - return false; - } - } - else - { - cdio_error( "CFDictionaryGetValue failed" ); + if ( data != NULL ) { + CFRange range; + CFIndex buf_len; + + buf_len = CFDataGetLength( data ) + 1; + range = CFRangeMake( 0, buf_len ); + + if( ( p_env->pTOC = (CDTOC *)malloc( buf_len ) ) != NULL ) { + CFDataGetBytes( data, range, (u_char *) p_env->pTOC ); + } else { + cdio_warn( "Trouble allocating CDROM TOC" ); + return false; } - - CFRelease( properties ); - IOObjectRelease( service ); + } else { + cdio_warn( "Trouble reading TOC" ); + return false; + } - _obj->i_descriptors = CDTOCGetDescriptorCount ( _obj->pTOC ); - _obj->num_tracks = _cdio_getNumberOfTracks(_obj->pTOC, _obj->i_descriptors); + /* TestDevice(p_env, service); */ + CFRelease( propertiesDict ); - /* Read in starting sectors */ + p_env->i_descriptors = CDTOCGetDescriptorCount ( p_env->pTOC ); + + /* Read in starting sectors. There may be non-tracks mixed in with + the real tracks. So find the first and last track number by + scanning. Also find the lead-out track position. + */ { int i, i_leadout = -1; + CDTOCDescriptor *pTrackDescriptors; - track_t track; - int i_tracks; - _obj->pp_lba = malloc( (_obj->num_tracks + 1) * sizeof(int) ); - if( _obj->pp_lba == NULL ) + p_env->pp_lba = malloc( p_env->i_descriptors * sizeof(int) ); + if( p_env->pp_lba == NULL ) { - cdio_error("Out of memory in allocating track starting LSNs" ); - free( _obj->pTOC ); + cdio_warn("Out of memory in allocating track starting LSNs" ); + free( p_env->pTOC ); return false; } - pTrackDescriptors = _obj->pTOC->descriptors; + pTrackDescriptors = p_env->pTOC->descriptors; + + p_env->gen.i_first_track = CDIO_CD_MAX_TRACKS+1; + p_env->i_last_track = CDIO_CD_MIN_TRACK_NO; + p_env->i_first_session = CDIO_CD_MAX_TRACKS+1; + p_env->i_last_session = CDIO_CD_MIN_TRACK_NO; - for( i_tracks = 0, i = 0; i <= _obj->i_descriptors; i++ ) + for( i = 0; i <= p_env->i_descriptors; i++ ) { - track = pTrackDescriptors[i].point; + track_t i_track = pTrackDescriptors[i].point; + session_t i_session = pTrackDescriptors[i].session; + + cdio_debug( "point: %d, tno: %d, session: %d, adr: %d, control:%d, " + "address: %d:%d:%d, p: %d:%d:%d", + i_track, + pTrackDescriptors[i].tno, i_session, + pTrackDescriptors[i].adr, pTrackDescriptors[i].control, + pTrackDescriptors[i].address.minute, + pTrackDescriptors[i].address.second, + pTrackDescriptors[i].address.frame, + pTrackDescriptors[i].p.minute, + pTrackDescriptors[i].p.second, + pTrackDescriptors[i].p.frame ); + + /* track information has adr = 1 */ + if ( 0x01 != pTrackDescriptors[i].adr ) + continue; - if( track == 0xA2 ) - /* Note leadout should be 0xAA, But OSX seems to use 0xA2. */ + if( i_track == OSX_CDROM_LEADOUT_TRACK ) i_leadout = i; - - if( track > CDIO_CD_MAX_TRACKS || track < CDIO_CD_MIN_TRACK_NO ) + + if( i_track > CDIO_CD_MAX_TRACKS || i_track < CDIO_CD_MIN_TRACK_NO ) continue; + + if (p_env->gen.i_first_track > i_track) + p_env->gen.i_first_track = i_track; + + if (p_env->i_last_track < i_track) + p_env->i_last_track = i_track; - _obj->pp_lba[i_tracks++] = + if (p_env->i_first_session > i_session) + p_env->i_first_session = i_session; + + if (p_env->i_last_session < i_session) + p_env->i_last_session = i_session; + } + + /* Now that we know what the first track number is, we can make sure + index positions are ordered starting at 0. + */ + for( i = 0; i <= p_env->i_descriptors; i++ ) + { + track_t i_track = pTrackDescriptors[i].point; + + if( i_track > CDIO_CD_MAX_TRACKS || i_track < CDIO_CD_MIN_TRACK_NO ) + continue; + + /* Note what OSX calls a LBA we call an LSN. So below re we + really have have MSF -> LSN -> LBA. + */ + p_env->pp_lba[i_track - p_env->gen.i_first_track] = cdio_lsn_to_lba(CDConvertMSFToLBA( pTrackDescriptors[i].p )); } if( i_leadout == -1 ) { - cdio_error( "CD leadout not found" ); - free( _obj->pp_lba ); - free( (void *) _obj->pTOC ); + cdio_warn( "CD leadout not found" ); + free( p_env->pp_lba ); + free( (void *) p_env->pTOC ); return false; } - /* set leadout sector */ - _obj->pp_lba[i_tracks] = + /* Set leadout sector. + Note what OSX calls a LBA we call an LSN. So below re we + really have have MSF -> LSN -> LBA. + */ + p_env->pp_lba[TOTAL_TRACKS] = cdio_lsn_to_lba(CDConvertMSFToLBA( pTrackDescriptors[i_leadout].p )); + p_env->gen.i_tracks = TOTAL_TRACKS; } - _obj->toc_init = true; + p_env->gen.toc_init = true; return( true ); @@ -442,24 +984,25 @@ _cdio_read_toc (_img_private_t *_obj) /*! Return the starting LSN track number - track_num in obj. Track numbers start at 1. + i_track in obj. Track numbers start at 1. The "leadout" track is specified either by - using track_num LEADOUT_TRACK or the total tracks+1. + using i_track LEADOUT_TRACK or the total tracks+1. False is returned if there is no track entry. */ static lsn_t -_cdio_get_track_lba(void *env, track_t track_num) +get_track_lba_osx(void *p_user_data, track_t i_track) { - _img_private_t *_obj = env; + _img_private_t *p_env = p_user_data; - if (!_obj->toc_init) _cdio_read_toc (_obj) ; + if (!p_env->gen.toc_init) read_toc_osx (p_env) ; + if (!p_env->gen.toc_init) return CDIO_INVALID_LSN; - if (track_num == CDIO_CDROM_LEADOUT_TRACK) track_num = TOTAL_TRACKS+1; + if (i_track == CDIO_CDROM_LEADOUT_TRACK) i_track = p_env->i_last_track+1; - if (track_num > TOTAL_TRACKS+1 || track_num == 0) { + if (i_track > p_env->i_last_track + 1 || i_track < p_env->gen.i_first_track) { return CDIO_INVALID_LSN; } else { - return _obj->pp_lba[track_num-1]; + return p_env->pp_lba[i_track - p_env->gen.i_first_track]; } } @@ -474,18 +1017,18 @@ _cdio_get_track_lba(void *env, track_t track_num) */ static int -_cdio_eject_media (void *env) { +_eject_media_osx (void *user_data) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; FILE *p_eject; char *psz_disk; char sz_cmd[32]; - if( ( psz_disk = (char *)strstr( _obj->gen.source_name, "disk" ) ) != NULL && + if( ( psz_disk = (char *)strstr( p_env->gen.source_name, "disk" ) ) != NULL && strlen( psz_disk ) > 4 ) { -#define EJECT_CMD "/usr/sbin/disktool -e %s 0" +#define EJECT_CMD "/usr/sbin/hdiutil eject %s" snprintf( sz_cmd, sizeof(sz_cmd), EJECT_CMD, psz_disk ); #undef EJECT_CMD @@ -518,23 +1061,23 @@ _cdio_eject_media (void *env) { Return the size of the CD in logical block address (LBA) units. */ static uint32_t -_cdio_stat_size (void *env) +_stat_size_osx (void *user_data) { - return _cdio_get_track_lba(env, CDIO_CDROM_LEADOUT_TRACK); + return get_track_lba_osx(user_data, CDIO_CDROM_LEADOUT_TRACK); } /*! Return the value associated with the key "arg". */ static const char * -_cdio_get_arg (void *env, const char key[]) +_get_arg_osx (void *user_data, const char key[]) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; if (!strcmp (key, "source")) { - return _obj->gen.source_name; + return p_env->gen.source_name; } else if (!strcmp (key, "access-mode")) { - switch (_obj->access_mode) { + switch (p_env->access_mode) { case _AM_OSX: return "OS X"; case _AM_NONE: @@ -545,101 +1088,67 @@ _cdio_get_arg (void *env, const char key[]) } /*! - Return the number of the first track. - CDIO_INVALID_TRACK is returned on error. -*/ -static track_t -_cdio_get_first_track_num(void *env) -{ - _img_private_t *_obj = env; - - if (!_obj->toc_init) _cdio_read_toc (_obj) ; - - { - track_t track = CDIO_INVALID_TRACK; - int i; - CDTOCDescriptor *pTrackDescriptors; - - pTrackDescriptors = _obj->pTOC->descriptors; - - for( i = 0; i < _obj->i_descriptors; i++ ) - { - track = pTrackDescriptors[i].point; - - if( track > CDIO_CD_MAX_TRACKS || track < CDIO_CD_MIN_TRACK_NO ) - continue; - return ( track ); - } - } - - return CDIO_INVALID_TRACK; -} - -/*! Return the media catalog number MCN. */ static char * -_cdio_get_mcn (void *env) { - _img_private_t *_obj = env; +get_mcn_osx (const void *user_data) { + const _img_private_t *p_env = user_data; dk_cd_read_mcn_t cd_read; memset( &cd_read, 0, sizeof(cd_read) ); - if( ioctl( _obj->gen.fd, DKIOCCDREADMCN, &cd_read ) < 0 ) + if( ioctl( p_env->gen.fd, DKIOCCDREADMCN, &cd_read ) < 0 ) { - cdio_error( "could not read MCN, %s", strerror(errno) ); + cdio_debug( "could not read MCN, %s", strerror(errno) ); return NULL; } return strdup((char*)cd_read.mcn); } -/*! - Return the number of tracks in the current medium. - CDIO_INVALID_TRACK is returned on error. - This is the externally called interface. -*/ -static track_t -_cdio_get_num_tracks(void *env) -{ - _img_private_t *_obj = env; - - if (!_obj->toc_init) _cdio_read_toc (_obj) ; - return( _obj->num_tracks ); -} - /*! Get format of track. */ static track_format_t -_cdio_get_track_format(void *env, track_t track_num) +get_track_format_osx(void *user_data, track_t i_track) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; + dk_cd_read_track_info_t cd_read; CDTrackInfo a_track; - - if (!_obj->toc_init) _cdio_read_toc (_obj) ; - if (track_num > TOTAL_TRACKS || track_num == 0) + if (!p_env->gen.toc_init) read_toc_osx (p_env) ; + + if (i_track > p_env->i_last_track || i_track < p_env->gen.i_first_track) return TRACK_FORMAT_ERROR; - dk_cd_read_track_info_t cd_read; memset( &cd_read, 0, sizeof(cd_read) ); - cd_read.address = track_num; + cd_read.address = i_track; cd_read.addressType = kCDTrackInfoAddressTypeTrackNumber; cd_read.buffer = &a_track; cd_read.bufferLength = sizeof(CDTrackInfo); - if( ioctl( _obj->gen.fd, DKIOCCDREADTRACKINFO, &cd_read ) == -1 ) + if( ioctl( p_env->gen.fd, DKIOCCDREADTRACKINFO, &cd_read ) == -1 ) { - cdio_error( "could not read trackinfo for track %d", track_num ); - return -1; + cdio_warn( "could not read trackinfo for track %d", i_track ); + return TRACK_FORMAT_ERROR; } - cdio_warn( "trackinfo trackMode: %x dataMode: %x", a_track.trackMode, a_track.dataMode ); + cdio_debug( "%d: trackinfo trackMode: %x dataMode: %x", i_track, a_track.trackMode, a_track.dataMode ); + + if (a_track.trackMode == CDIO_CDROM_DATA_TRACK) { + if (a_track.dataMode == CDROM_CDI_TRACK) { + return TRACK_FORMAT_CDI; + } else if (a_track.dataMode == CDROM_XA_TRACK) { + return TRACK_FORMAT_XA; + } else { + return TRACK_FORMAT_DATA; + } + } else { + return TRACK_FORMAT_AUDIO; + } - return TRACK_FORMAT_AUDIO; } /*! @@ -651,25 +1160,34 @@ _cdio_get_track_format(void *env, track_t track_num) FIXME: there's gotta be a better design for this and get_track_format? */ static bool -_cdio_get_track_green(void *env, track_t track_num) +get_track_green_osx(void *user_data, track_t i_track) { + _img_private_t *p_env = user_data; + CDTrackInfo a_track; -#if 0 - if (!_obj->toc_init) _cdio_read_toc (_obj) ; - - if (track_num == CDIO_LEADOUT_TRACK) track_num = TOTAL_TRACKS+1; + if (!p_env->gen.toc_init) read_toc_osx (p_env) ; - if (track_num > TOTAL_TRACKS+1 || track_num == 0) + if ( i_track > p_env->i_last_track || i_track < p_env->gen.i_first_track ) return false; - /* FIXME: Dunno if this is the right way, but it's what - I was using in cdinfo for a while. - */ - return ((_obj->tocent[track_num-1].cdte_ctrl & 2) != 0); -#else - /* FIXME! Figure out how to do. */ - return true; -#endif + else { + + dk_cd_read_track_info_t cd_read; + + memset( &cd_read, 0, sizeof(cd_read) ); + + cd_read.address = i_track; + cd_read.addressType = kCDTrackInfoAddressTypeTrackNumber; + + cd_read.buffer = &a_track; + cd_read.bufferLength = sizeof(CDTrackInfo); + + if( ioctl( p_env->gen.fd, DKIOCCDREADTRACKINFO, &cd_read ) == -1 ) { + cdio_warn( "could not read trackinfo for track %d", i_track ); + return false; + } + return ((a_track.trackMode & CDIO_CDROM_DATA_TRACK) != 0); + } } #endif /* HAVE_DARWIN_CDROM */ @@ -694,13 +1212,13 @@ cdio_get_devices_osx(void) kern_result = IOMasterPort( MACH_PORT_NULL, &master_port ); if( kern_result != KERN_SUCCESS ) { - return( nil ); + return( NULL ); } classes_to_match = IOServiceMatching( kIOCDMediaClass ); if( classes_to_match == NULL ) { - return( nil ); + return( NULL ); } CFDictionarySetValue( classes_to_match, CFSTR(kIOMediaEjectableKey), @@ -711,7 +1229,7 @@ cdio_get_devices_osx(void) &media_iterator ); if( kern_result != KERN_SUCCESS ) { - return( nil ); + return( NULL ); } next_media = IOIteratorNext( media_iterator ); @@ -744,7 +1262,7 @@ cdio_get_devices_osx(void) CFRelease( str_bsd_path ); IOObjectRelease( next_media ); IOObjectRelease( media_iterator ); - cdio_add_device_list(&drives, psz_buf, &num_drives); + cdio_add_device_list(&drives, strdup(psz_buf), &num_drives); } CFRelease( str_bsd_path ); @@ -776,13 +1294,13 @@ cdio_get_default_device_osx(void) kern_result = IOMasterPort( MACH_PORT_NULL, &master_port ); if( kern_result != KERN_SUCCESS ) { - return( nil ); + return( NULL ); } classes_to_match = IOServiceMatching( kIOCDMediaClass ); if( classes_to_match == NULL ) { - return( nil ); + return( NULL ); } CFDictionarySetValue( classes_to_match, CFSTR(kIOMediaEjectableKey), @@ -793,7 +1311,7 @@ cdio_get_default_device_osx(void) &media_iterator ); if( kern_result != KERN_SUCCESS ) { - return( nil ); + return( NULL ); } next_media = IOIteratorNext( media_iterator ); @@ -845,55 +1363,90 @@ cdio_get_default_device_osx(void) ones to set that up. */ CdIo * -cdio_open_osx (const char *orig_source_name) +cdio_open_am_osx (const char *psz_source_name, const char *psz_access_mode) +{ + + if (psz_access_mode != NULL) + cdio_warn ("there is only one access mode for OS X. Arg %s ignored", + psz_access_mode); + return cdio_open_osx(psz_source_name); +} + + +/*! + Initialization routine. This is the only thing that doesn't + get called via a function pointer. In fact *we* are the + ones to set that up. + */ +CdIo * +cdio_open_osx (const char *psz_orig_source) { #ifdef HAVE_DARWIN_CDROM CdIo *ret; _img_private_t *_data; - char *source_name; + char *psz_source; cdio_funcs _funcs = { - .eject_media = _cdio_eject_media, - .free = _cdio_osx_free, - .get_arg = _cdio_get_arg, + .eject_media = _eject_media_osx, + .free = _free_osx, + .get_arg = _get_arg_osx, + .get_cdtext = get_cdtext_osx, .get_default_device = cdio_get_default_device_osx, .get_devices = cdio_get_devices_osx, - .get_first_track_num= _cdio_get_first_track_num, - .get_mcn = _cdio_get_mcn, - .get_num_tracks = _cdio_get_num_tracks, - .get_track_format = _cdio_get_track_format, - .get_track_green = _cdio_get_track_green, - .get_track_lba = _cdio_get_track_lba, + .get_discmode = get_discmode_osx, + .get_drive_cap = get_drive_cap_osx, + .get_first_track_num= get_first_track_num_generic, + .get_hwinfo = get_hwinfo_osx, + .get_mcn = get_mcn_osx, + .get_num_tracks = get_num_tracks_generic, + .get_track_format = get_track_format_osx, + .get_track_green = get_track_green_osx, + .get_track_lba = get_track_lba_osx, .get_track_msf = NULL, .lseek = cdio_generic_lseek, .read = cdio_generic_read, - .read_audio_sectors = _cdio_read_audio_sectors, - .read_mode1_sector = _cdio_read_mode1_sector, - .read_mode1_sectors = _cdio_read_mode1_sectors, - .read_mode2_sector = _cdio_read_mode2_sector, - .read_mode2_sectors = _cdio_read_mode2_sectors, - .set_arg = _cdio_set_arg, - .stat_size = _cdio_stat_size + .read_audio_sectors = _get_read_audio_sectors_osx, + .read_mode1_sector = _get_read_mode1_sector_osx, + .read_mode1_sectors = _get_read_mode1_sectors_osx, + .read_mode2_sector = _get_read_mode2_sector_osx, + .read_mode2_sectors = _get_read_mode2_sectors_osx, + .read_toc = read_toc_osx, + .run_scsi_mmc_cmd = run_scsi_cmd_osx, + .set_arg = _set_arg_osx, + .stat_size = _stat_size_osx }; _data = _cdio_malloc (sizeof (_img_private_t)); _data->access_mode = _AM_OSX; - _data->gen.init = false; - _data->gen.fd = -1; - - if (NULL == orig_source_name) { - source_name=cdio_get_default_device_linux(); - if (NULL == source_name) return NULL; - _cdio_set_arg(_data, "source", source_name); - free(source_name); - } else - _cdio_set_arg(_data, "source", orig_source_name); - - ret = cdio_new (_data, &_funcs); + _data->MediaClass_service = 0; + _data->gen.init = false; + _data->gen.fd = -1; + _data->gen.toc_init = false; + _data->gen.b_cdtext_init = false; + _data->gen.b_cdtext_error = false; + + if (NULL == psz_orig_source) { + psz_source=cdio_get_default_device_osx(); + if (NULL == psz_source) return NULL; + _set_arg_osx(_data, "source", psz_source); + free(psz_source); + } else { + if (cdio_is_device_generic(psz_orig_source)) + _set_arg_osx(_data, "source", psz_orig_source); + else { + /* The below would be okay if all device drivers worked this way. */ +#if 0 + cdio_info ("source %s is a not a device", psz_orig_source); +#endif + return NULL; + } + } + + ret = cdio_new ((void *)_data, &_funcs); if (ret == NULL) return NULL; - if (cdio_generic_init(_data)) + if (cdio_generic_init(_data) && init_osx(_data)) return ret; else { cdio_generic_free (_data); diff --git a/src/input/vcd/libcdio/_cdio_sunos.c b/src/input/vcd/libcdio/_cdio_sunos.c index 795ba6184..245d1e319 100644 --- a/src/input/vcd/libcdio/_cdio_sunos.c +++ b/src/input/vcd/libcdio/_cdio_sunos.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_sunos.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: _cdio_sunos.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $ Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com> @@ -26,22 +26,23 @@ #ifdef HAVE_STRING_H #include <string.h> #endif -#ifdef HAVE_GLOB_H -#include <glob.h> -#endif #include <cdio/logging.h> #include <cdio/sector.h> #include <cdio/util.h> +#include <cdio/scsi_mmc.h> #include "cdio_assert.h" #include "cdio_private.h" -#include "scsi_mmc.h" #define DEFAULT_CDIO_DEVICE "/vol/dev/aliases/cdrom0" #ifdef HAVE_SOLARIS_CDROM -static const char _rcsid[] = "$Id: _cdio_sunos.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: _cdio_sunos.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $"; + +#ifdef HAVE_GLOB_H +#include <glob.h> +#endif #include <stdio.h> #include <stdlib.h> @@ -62,18 +63,14 @@ static const char _rcsid[] = "$Id: _cdio_sunos.c,v 1.2 2004/04/11 12:20:31 migue #include <sys/stat.h> #include <sys/types.h> #include <sys/ioctl.h> +#include "cdtext_private.h" -#define TOTAL_TRACKS (_obj->tochdr.cdth_trk1) -#define FIRST_TRACK_NUM (_obj->tochdr.cdth_trk0) +/* not defined in dkio.h yet */ +#define DK_DVDRW 0x13 /* reader */ -typedef struct { - /* Things common to all drivers like this. - This must be first. */ - generic_img_private_t gen; - - enum { +typedef enum { _AM_NONE, _AM_SUN_CTRL_ATAPI, _AM_SUN_CTRL_SCSI @@ -81,30 +78,98 @@ typedef struct { _AM_READ_CD, _AM_READ_10 #endif - } access_mode; +} access_mode_t; +typedef struct { + /* Things common to all drivers like this. + This must be first. */ + generic_img_private_t gen; + + access_mode_t access_mode; + + /* Some of the more OS specific things. */ + /* Entry info for each track, add 1 for leadout. */ + struct cdrom_tocentry tocent[CDIO_CD_MAX_TRACKS+1]; + /* Track information */ struct cdrom_tochdr tochdr; - struct cdrom_tocentry tocent[100]; /* entry info for each track */ - } _img_private_t; +static track_format_t get_track_format_solaris(void *p_user_data, + track_t i_track); + +static access_mode_t +str_to_access_mode_sunos(const char *psz_access_mode) +{ + const access_mode_t default_access_mode = _AM_SUN_CTRL_SCSI; + + if (NULL==psz_access_mode) return default_access_mode; + + if (!strcmp(psz_access_mode, "ATAPI")) + return _AM_SUN_CTRL_SCSI; /* force ATAPI to be SCSI */ + else if (!strcmp(psz_access_mode, "SCSI")) + return _AM_SUN_CTRL_SCSI; + else { + cdio_warn ("unknown access type: %s. Default SCSI used.", + psz_access_mode); + return default_access_mode; + } +} + + /*! Initialize CD device. */ static bool -_cdio_init (_img_private_t *_obj) +init_solaris (_img_private_t *p_env) { - if (!cdio_generic_init(_obj)) return false; + if (!cdio_generic_init(p_env)) return false; - _obj->access_mode = _AM_SUN_CTRL_SCSI; + p_env->access_mode = _AM_SUN_CTRL_SCSI; return true; } /*! + Run a SCSI MMC command. + + p_user_data internal CD structure. + i_timeout_ms time in milliseconds we will wait for the command + to complete. + i_cdb Size of p_cdb + p_cdb CDB bytes. + e_direction direction the transfer is to go. + i_buf Size of buffer + p_buf Buffer for data, both sending and receiving + + Return 0 if no error. + */ +static int +run_scsi_cmd_solaris( const void *p_user_data, unsigned int i_timeout_ms, + unsigned int i_cdb, const scsi_mmc_cdb_t *p_cdb, + scsi_mmc_direction_t e_direction, + unsigned int i_buf, /*in/out*/ void *p_buf ) +{ + const _img_private_t *p_env = p_user_data; + struct uscsi_cmd cgc; + + memset (&cgc, 0, sizeof (struct uscsi_cmd)); + cgc.uscsi_cdb = (caddr_t) p_cdb; + + cgc.uscsi_flags = SCSI_MMC_DATA_READ == e_direction ? + USCSI_READ : USCSI_WRITE; + + cgc.uscsi_timeout = msecs2secs(i_timeout_ms); + cgc.uscsi_bufaddr = p_buf; + cgc.uscsi_buflen = i_buf; + cgc.uscsi_cdblen = i_cdb; + + return ioctl(p_env->gen.fd, USCSICMD, &cgc); +} + +/*! Reads audio sectors from CD device into data starting from lsn. Returns 0 if no error. @@ -113,44 +178,44 @@ _cdio_init (_img_private_t *_obj) */ static int -_cdio_read_audio_sectors (void *env, void *data, lsn_t lsn, +_read_audio_sectors_solaris (void *p_user_data, void *data, lsn_t lsn, unsigned int nblocks) { - char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; - struct cdrom_msf *msf = (struct cdrom_msf *) &buf; + struct cdrom_msf solaris_msf; msf_t _msf; struct cdrom_cdda cdda; - _img_private_t *_obj = env; + _img_private_t *p_env = p_user_data; cdio_lba_to_msf (cdio_lsn_to_lba(lsn), &_msf); - msf->cdmsf_min0 = from_bcd8(_msf.m); - msf->cdmsf_sec0 = from_bcd8(_msf.s); - msf->cdmsf_frame0 = from_bcd8(_msf.f); + solaris_msf.cdmsf_min0 = cdio_from_bcd8(_msf.m); + solaris_msf.cdmsf_sec0 = cdio_from_bcd8(_msf.s); + solaris_msf.cdmsf_frame0 = cdio_from_bcd8(_msf.f); - if (_obj->gen.ioctls_debugged == 75) + if (p_env->gen.ioctls_debugged == 75) cdio_debug ("only displaying every 75th ioctl from now on"); - if (_obj->gen.ioctls_debugged == 30 * 75) + if (p_env->gen.ioctls_debugged == 30 * 75) cdio_debug ("only displaying every 30*75th ioctl from now on"); - if (_obj->gen.ioctls_debugged < 75 - || (_obj->gen.ioctls_debugged < (30 * 75) - && _obj->gen.ioctls_debugged % 75 == 0) - || _obj->gen.ioctls_debugged % (30 * 75) == 0) + if (p_env->gen.ioctls_debugged < 75 + || (p_env->gen.ioctls_debugged < (30 * 75) + && p_env->gen.ioctls_debugged % 75 == 0) + || p_env->gen.ioctls_debugged % (30 * 75) == 0) cdio_debug ("reading %d", lsn); - _obj->gen.ioctls_debugged++; + p_env->gen.ioctls_debugged++; + + cdda.cdda_addr = lsn; + cdda.cdda_length = nblocks; + cdda.cdda_data = (caddr_t) data; + cdda.cdda_subcode = CDROM_DA_NO_SUBCODE; - cdda.cdda_addr = lsn; - cdda.cdda_length = nblocks; - cdda.cdda_data = (caddr_t) data; - if (ioctl (_obj->gen.fd, CDROMCDDA, &cdda) == -1) { + if (ioctl (p_env->gen.fd, CDROMCDDA, &cdda) == -1) { perror ("ioctl(..,CDROMCDDA,..)"); return 1; /* exit (EXIT_FAILURE); */ } - memcpy (data, buf, CDIO_CD_FRAMESIZE_RAW); return 0; } @@ -160,21 +225,15 @@ _cdio_read_audio_sectors (void *env, void *data, lsn_t lsn, from lsn. Returns 0 if no error. */ static int -_cdio_read_mode1_sector (void *env, void *data, lsn_t lsn, - bool b_form2) +_read_mode1_sector_solaris (void *env, void *data, lsn_t lsn, + bool b_form2) { - char buf[M2RAW_SECTOR_SIZE] = { 0, }; #if FIXED do something here. #else - if (0 > cdio_generic_lseek(env, CDIO_CD_FRAMESIZE*lsn, SEEK_SET)) - return -1; - if (0 > cdio_generic_read(env, buf, CDIO_CD_FRAMESIZE)) - return -1; - memcpy (data, buf, b_form2 ? M2RAW_SECTOR_SIZE: CDIO_CD_FRAMESIZE); + return cdio_generic_read_form1_sector(env, data, lsn); #endif - return 0; } /*! @@ -183,18 +242,18 @@ _cdio_read_mode1_sector (void *env, void *data, lsn_t lsn, Returns 0 if no error. */ static int -_cdio_read_mode1_sectors (void *env, void *data, lsn_t lsn, - bool b_form2, unsigned int nblocks) +_read_mode1_sectors_solaris (void *p_user_data, void *p_data, lsn_t lsn, + bool b_form2, unsigned int nblocks) { - _img_private_t *_obj = env; + _img_private_t *p_env = p_user_data; unsigned int i; int retval; unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE; for (i = 0; i < nblocks; i++) { - if ( (retval = _cdio_read_mode1_sector (_obj, - ((char *)data) + (blocksize * i), - lsn + i, b_form2)) ) + if ( (retval = _read_mode1_sector_solaris (p_env, + ((char *)p_data) + (blocksize * i), + lsn + i, b_form2)) ) return retval; } return 0; @@ -205,36 +264,37 @@ _cdio_read_mode1_sectors (void *env, void *data, lsn_t lsn, Returns 0 if no error. */ static int -_cdio_read_mode2_sector (void *env, void *data, lsn_t lsn, - bool b_form2) +_read_mode2_sector_solaris (void *p_user_data, void *p_data, lsn_t lsn, + bool b_form2) { char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; - struct cdrom_msf *msf = (struct cdrom_msf *) &buf; + struct cdrom_msf solaris_msf; msf_t _msf; int offset = 0; struct cdrom_cdxa cd_read; - _img_private_t *_obj = env; + _img_private_t *p_env = p_user_data; cdio_lba_to_msf (cdio_lsn_to_lba(lsn), &_msf); - msf->cdmsf_min0 = from_bcd8(_msf.m); - msf->cdmsf_sec0 = from_bcd8(_msf.s); - msf->cdmsf_frame0 = from_bcd8(_msf.f); + solaris_msf.cdmsf_min0 = cdio_from_bcd8(_msf.m); + solaris_msf.cdmsf_sec0 = cdio_from_bcd8(_msf.s); + solaris_msf.cdmsf_frame0 = cdio_from_bcd8(_msf.f); - if (_obj->gen.ioctls_debugged == 75) + if (p_env->gen.ioctls_debugged == 75) cdio_debug ("only displaying every 75th ioctl from now on"); - if (_obj->gen.ioctls_debugged == 30 * 75) + if (p_env->gen.ioctls_debugged == 30 * 75) cdio_debug ("only displaying every 30*75th ioctl from now on"); - if (_obj->gen.ioctls_debugged < 75 - || (_obj->gen.ioctls_debugged < (30 * 75) - && _obj->gen.ioctls_debugged % 75 == 0) - || _obj->gen.ioctls_debugged % (30 * 75) == 0) + if (p_env->gen.ioctls_debugged < 75 + || (p_env->gen.ioctls_debugged < (30 * 75) + && p_env->gen.ioctls_debugged % 75 == 0) + || p_env->gen.ioctls_debugged % (30 * 75) == 0) cdio_debug ("reading %2.2d:%2.2d:%2.2d", - msf->cdmsf_min0, msf->cdmsf_sec0, msf->cdmsf_frame0); + solaris_msf.cdmsf_min0, solaris_msf.cdmsf_sec0, + solaris_msf.cdmsf_frame0); - _obj->gen.ioctls_debugged++; + p_env->gen.ioctls_debugged++; /* Using CDROMXA ioctl will actually use the same uscsi command * as ATAPI, except we don't need to be root @@ -244,16 +304,16 @@ _cdio_read_mode2_sector (void *env, void *data, lsn_t lsn, cd_read.cdxa_data = buf; cd_read.cdxa_length = 1; cd_read.cdxa_format = CDROM_XA_SECTOR_DATA; - if (ioctl (_obj->gen.fd, CDROMCDXA, &cd_read) == -1) { + if (ioctl (p_env->gen.fd, CDROMCDXA, &cd_read) == -1) { perror ("ioctl(..,CDROMCDXA,..)"); return 1; /* exit (EXIT_FAILURE); */ } if (b_form2) - memcpy (data, buf + (offset-CDIO_CD_SUBHEADER_SIZE), M2RAW_SECTOR_SIZE); + memcpy (p_data, buf + (offset-CDIO_CD_SUBHEADER_SIZE), M2RAW_SECTOR_SIZE); else - memcpy (((char *)data), buf + offset, CDIO_CD_FRAMESIZE); + memcpy (((char *)p_data), buf + offset, CDIO_CD_FRAMESIZE); return 0; } @@ -264,18 +324,18 @@ _cdio_read_mode2_sector (void *env, void *data, lsn_t lsn, Returns 0 if no error. */ static int -_cdio_read_mode2_sectors (void *env, void *data, lsn_t lsn, - bool b_form2, unsigned int nblocks) +_read_mode2_sectors_solaris (void *p_user_data, void *data, lsn_t lsn, + bool b_form2, unsigned int nblocks) { - _img_private_t *_obj = env; + _img_private_t *env = p_user_data; unsigned int i; int retval; unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE; for (i = 0; i < nblocks; i++) { - if ( (retval = _cdio_read_mode2_sector (_obj, + if ( (retval = _read_mode2_sector_solaris (env, ((char *)data) + (blocksize * i), - lsn + i, b_form2)) ) + lsn + i, b_form2)) ) return retval; } return 0; @@ -286,16 +346,16 @@ _cdio_read_mode2_sectors (void *env, void *data, lsn_t lsn, Return the size of the CD in logical block address (LBA) units. */ static uint32_t -_cdio_stat_size (void *env) +_cdio_stat_size (void *p_user_data) { - _img_private_t *_obj = env; + _img_private_t *env = p_user_data; struct cdrom_tocentry tocent; uint32_t size; - tocent.cdte_track = CDIO_CDROM_LEADOUT_TRACK; - tocent.cdte_format = CDROM_LBA; - if (ioctl (_obj->gen.fd, CDROMREADTOCENTRY, &tocent) == -1) + tocent.cdte_track = CDIO_CDROM_LEADOUT_TRACK; + tocent.cdte_format = CDIO_CDROM_LBA; + if (ioctl (env->gen.fd, CDROMREADTOCENTRY, &tocent) == -1) { perror ("ioctl(CDROMREADTOCENTRY)"); exit (EXIT_FAILURE); @@ -315,27 +375,22 @@ _cdio_stat_size (void *env) 0 is returned if no error was found, and nonzero if there as an error. */ static int -_cdio_set_arg (void *env, const char key[], const char value[]) +_set_arg_solaris (void *p_user_data, const char key[], const char value[]) { - _img_private_t *_obj = env; + _img_private_t *env = p_user_data; if (!strcmp (key, "source")) { if (!value) return -2; - free (_obj->gen.source_name); + free (env->gen.source_name); - _obj->gen.source_name = strdup (value); + env->gen.source_name = strdup (value); } else if (!strcmp (key, "access-mode")) { - if (!strcmp(value, "ATAPI")) - _obj->access_mode = _AM_SUN_CTRL_SCSI; /* force ATAPI to be SCSI */ - else if (!strcmp(value, "SCSI")) - _obj->access_mode = _AM_SUN_CTRL_SCSI; - else - cdio_warn ("unknown access type: %s. ignored.", value); + env->access_mode = str_to_access_mode_sunos(key); } else return -1; @@ -348,23 +403,27 @@ _cdio_set_arg (void *env, const char key[], const char value[]) Return true if successful or false if an error. */ static bool -_cdio_read_toc (_img_private_t *_obj) +read_toc_solaris (void *p_user_data) { + _img_private_t *p_env = p_user_data; int i; /* read TOC header */ - if ( ioctl(_obj->gen.fd, CDROMREADTOCHDR, &_obj->tochdr) == -1 ) { - cdio_error("%s: %s\n", + if ( ioctl(p_env->gen.fd, CDROMREADTOCHDR, &p_env->tochdr) == -1 ) { + cdio_warn("%s: %s\n", "error in ioctl CDROMREADTOCHDR", strerror(errno)); return false; } + p_env->gen.i_first_track = p_env->tochdr.cdth_trk0; + p_env->gen.i_tracks = p_env->tochdr.cdth_trk1; + /* read individual tracks */ - for (i=_obj->tochdr.cdth_trk0; i<=_obj->tochdr.cdth_trk1; i++) { - _obj->tocent[i-1].cdte_track = i; - _obj->tocent[i-1].cdte_format = CDROM_MSF; - if ( ioctl(_obj->gen.fd, CDROMREADTOCENTRY, &_obj->tocent[i-1]) == -1 ) { - cdio_error("%s %d: %s\n", + for (i=p_env->gen.i_first_track; i<=p_env->gen.i_tracks; i++) { + p_env->tocent[i-1].cdte_track = i; + p_env->tocent[i-1].cdte_format = CDIO_CDROM_MSF; + if ( ioctl(p_env->gen.fd, CDROMREADTOCENTRY, &p_env->tocent[i-1]) == -1 ) { + cdio_warn("%s %d: %s\n", "error in ioctl CDROMREADTOCENTRY for track", i, strerror(errno)); return false; @@ -372,18 +431,18 @@ _cdio_read_toc (_img_private_t *_obj) } /* read the lead-out track */ - _obj->tocent[_obj->tochdr.cdth_trk1].cdte_track = CDIO_CDROM_LEADOUT_TRACK; - _obj->tocent[_obj->tochdr.cdth_trk1].cdte_format = CDROM_MSF; + p_env->tocent[p_env->tochdr.cdth_trk1].cdte_track = CDIO_CDROM_LEADOUT_TRACK; + p_env->tocent[p_env->tochdr.cdth_trk1].cdte_format = CDIO_CDROM_MSF; - if (ioctl(_obj->gen.fd, CDROMREADTOCENTRY, - &_obj->tocent[_obj->tochdr.cdth_trk1]) == -1 ) { - cdio_error("%s: %s\n", + if (ioctl(p_env->gen.fd, CDROMREADTOCENTRY, + &p_env->tocent[p_env->tochdr.cdth_trk1]) == -1 ) { + cdio_warn("%s: %s\n", "error in ioctl CDROMREADTOCENTRY for lead-out", strerror(errno)); return false; } - _obj->gen.toc_init = true; + p_env->gen.toc_init = true; return true; } @@ -392,17 +451,17 @@ _cdio_read_toc (_img_private_t *_obj) also free obj. */ static int -_cdio_eject_media (void *env) { +eject_media_solaris (void *p_user_data) { - _img_private_t *_obj = env; + _img_private_t *env = p_user_data; int ret; - close(_obj->gen.fd); - _obj->gen.fd = -1; - if (_obj->gen.fd > -1) { - if ((ret = ioctl(_obj->gen.fd, CDROMEJECT)) != 0) { - cdio_generic_free((void *) _obj); - cdio_error ("CDROMEJECT failed: %s\n", strerror(errno)); + close(env->gen.fd); + env->gen.fd = -1; + if (env->gen.fd > -1) { + if ((ret = ioctl(env->gen.fd, CDROMEJECT)) != 0) { + cdio_generic_free((void *) env); + cdio_warn ("CDROMEJECT failed: %s\n", strerror(errno)); return 1; } else { return 0; @@ -419,7 +478,7 @@ _cdio_malloc_and_zero(size_t size) { if( !size ) size++; if((ptr = malloc(size)) == NULL) { - cdio_error("malloc() failed: %s", strerror(errno)); + cdio_warn("malloc() failed: %s", strerror(errno)); return NULL; } @@ -431,14 +490,14 @@ _cdio_malloc_and_zero(size_t size) { Return the value associated with the key "arg". */ static const char * -_cdio_get_arg (void *env, const char key[]) +get_arg_solaris (void *p_user_data, const char key[]) { - _img_private_t *_obj = env; + _img_private_t *env = p_user_data; if (!strcmp (key, "source")) { - return _obj->gen.source_name; + return env->gen.source_name; } else if (!strcmp (key, "access-mode")) { - switch (_obj->access_mode) { + switch (env->access_mode) { case _AM_SUN_CTRL_ATAPI: return "ATAPI"; case _AM_SUN_CTRL_SCSI: @@ -478,57 +537,147 @@ cdio_get_default_device_solaris(void) } return device; } + /* Check if it could be a Solaris media*/ + if((stat(DEFAULT_CDIO_DEVICE, &stb) == 0) && S_ISDIR(stb.st_mode)) { + device = _cdio_malloc_and_zero(strlen(DEFAULT_CDIO_DEVICE) + 4); + sprintf(device, "%s/s0", DEFAULT_CDIO_DEVICE); + return device; + } return strdup(DEFAULT_CDIO_DEVICE); } -/*! - Return the number of of the first track. - CDIO_INVALID_TRACK is returned on error. +/*! + Get disc type associated with cd object. */ -static track_t -_cdio_get_first_track_num(void *env) + +static discmode_t +get_discmode_solaris (void *p_user_data) { - _img_private_t *_obj = env; - - if (!_obj->gen.toc_init) _cdio_read_toc (_obj) ; + _img_private_t *p_env = p_user_data; + track_t i_track; + discmode_t discmode=CDIO_DISC_MODE_NO_INFO; + struct dk_minfo media; + int ret; - return FIRST_TRACK_NUM; -} + /* Get the media info */ + if((ret = ioctl(p_env->gen.fd, DKIOCGMEDIAINFO, &media)) != 0) { + cdio_warn ("DKIOCGMEDIAINFO failed: %s\n", strerror(errno)); + return CDIO_DISC_MODE_NO_INFO; + } + switch(media.dki_media_type) { + case DK_CDROM: + case DK_CDR: + case DK_CDRW: + /* Do cdrom detection */ + break; + case DK_DVDROM: return CDIO_DISC_MODE_DVD_ROM; + case DK_DVDR: discmode = CDIO_DISC_MODE_DVD_R; + break; + case DK_DVDRAM: discmode = CDIO_DISC_MODE_DVD_RAM; + break; + case DK_DVDRW: + case DK_DVDRW+1: discmode = CDIO_DISC_MODE_DVD_RW; + break; + default: /* no valid match */ + return CDIO_DISC_MODE_NO_INFO; + } -/*! - Return the number of tracks in the current medium. -*/ -static track_t -_cdio_get_num_tracks(void *env) -{ - _img_private_t *_obj = env; - - if (!_obj->gen.toc_init) _cdio_read_toc (_obj) ; + if((discmode == CDIO_DISC_MODE_DVD_RAM || + discmode == CDIO_DISC_MODE_DVD_RW || + discmode == CDIO_DISC_MODE_DVD_R)) { + /* Fallback to uscsi if we can */ + if(geteuid() == 0) + return get_discmode_solaris(p_user_data); + return discmode; + } - return TOTAL_TRACKS; + if (!p_env->gen.toc_init) + read_toc_solaris (p_env); + + if (!p_env->gen.toc_init) + return CDIO_DISC_MODE_NO_INFO; + + for (i_track = p_env->gen.i_first_track; + i_track < p_env->gen.i_first_track + p_env->tochdr.cdth_trk1 ; + i_track ++) { + track_format_t track_fmt=get_track_format_solaris(p_env, i_track); + + switch(track_fmt) { + case TRACK_FORMAT_AUDIO: + switch(discmode) { + case CDIO_DISC_MODE_NO_INFO: + discmode = CDIO_DISC_MODE_CD_DA; + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* No change*/ + break; + default: + discmode = CDIO_DISC_MODE_CD_MIXED; + } + break; + case TRACK_FORMAT_XA: + switch(discmode) { + case CDIO_DISC_MODE_NO_INFO: + discmode = CDIO_DISC_MODE_CD_XA; + break; + case CDIO_DISC_MODE_CD_XA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* No change*/ + break; + default: + discmode = CDIO_DISC_MODE_CD_MIXED; + } + break; + case TRACK_FORMAT_DATA: + switch(discmode) { + case CDIO_DISC_MODE_NO_INFO: + discmode = CDIO_DISC_MODE_CD_DATA; + break; + case CDIO_DISC_MODE_CD_DATA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* No change*/ + break; + default: + discmode = CDIO_DISC_MODE_CD_MIXED; + } + break; + case TRACK_FORMAT_ERROR: + default: + discmode = CDIO_DISC_MODE_ERROR; + } + } + return discmode; } /*! Get format of track. */ static track_format_t -_cdio_get_track_format(void *env, track_t track_num) +get_track_format_solaris(void *p_user_data, track_t i_track) { - _img_private_t *_obj = env; + _img_private_t *p_env = p_user_data; - if (!_obj->gen.init) _cdio_init(_obj); - if (!_obj->gen.toc_init) _cdio_read_toc (_obj) ; + if ( !p_env ) return TRACK_FORMAT_ERROR; + if (!p_env->gen.init) init_solaris(p_env); + if (!p_env->gen.toc_init) read_toc_solaris (p_user_data) ; - if (track_num > TOTAL_TRACKS || track_num == 0) + if ( (i_track > p_env->gen.i_tracks+p_env->gen.i_first_track) + || i_track < p_env->gen.i_first_track) return TRACK_FORMAT_ERROR; + i_track -= p_env->gen.i_first_track; + /* This is pretty much copied from the "badly broken" cdrom_count_tracks in linux/cdrom.c. */ - if (_obj->tocent[track_num-1].cdte_ctrl & CDROM_DATA_TRACK) { - if (_obj->tocent[track_num-1].cdte_format == 0x10) + if (p_env->tocent[i_track].cdte_ctrl & CDROM_DATA_TRACK) { + if (p_env->tocent[i_track].cdte_format == CDIO_CDROM_CDI_TRACK) return TRACK_FORMAT_CDI; - else if (_obj->tocent[track_num-1].cdte_format == 0x20) + else if (p_env->tocent[i_track].cdte_format == CDIO_CDROM_XA_TRACK) return TRACK_FORMAT_XA; else return TRACK_FORMAT_DATA; @@ -546,50 +695,56 @@ _cdio_get_track_format(void *env, track_t track_num) FIXME: there's gotta be a better design for this and get_track_format? */ static bool -_cdio_get_track_green(void *env, track_t track_num) +_cdio_get_track_green(void *p_user_data, track_t i_track) { - _img_private_t *_obj = env; + _img_private_t *p_env = p_user_data; - if (!_obj->gen.init) _cdio_init(_obj); - if (!_obj->gen.toc_init) _cdio_read_toc (_obj) ; + if ( !p_env ) return false; + if (!p_env->gen.init) init_solaris(p_env); + if (!p_env->gen.toc_init) read_toc_solaris (p_env) ; - if (track_num == CDIO_CDROM_LEADOUT_TRACK) track_num = TOTAL_TRACKS+1; - - if (track_num > TOTAL_TRACKS+1 || track_num == 0) + if (i_track >= p_env->gen.i_tracks+p_env->gen.i_first_track + || i_track < p_env->gen.i_first_track) return false; + i_track -= p_env->gen.i_first_track; + /* FIXME: Dunno if this is the right way, but it's what - I was using in cdinfo for a while. + I was using in cd-info for a while. */ - return ((_obj->tocent[track_num-1].cdte_ctrl & 2) != 0); + return ((p_env->tocent[i_track].cdte_ctrl & 2) != 0); } /*! Return the starting MSF (minutes/secs/frames) for track number - track_num in obj. Tracks numbers start at 1. + track_num in obj. Track numbers usually start at something + greater than 0, usually 1. + The "leadout" track is specified either by using track_num LEADOUT_TRACK or the total tracks+1. False is returned if there is no entry. */ static bool -_cdio_get_track_msf(void *env, track_t track_num, msf_t *msf) +_cdio_get_track_msf(void *p_user_data, track_t i_track, msf_t *msf) { - _img_private_t *_obj = env; + _img_private_t *p_env = p_user_data; if (NULL == msf) return false; - if (!_obj->gen.init) _cdio_init(_obj); - if (!_obj->gen.toc_init) _cdio_read_toc (_obj) ; + if (!p_env->gen.init) init_solaris(p_env); + if (!p_env->gen.toc_init) read_toc_solaris (p_env) ; - if (track_num == CDIO_CDROM_LEADOUT_TRACK) track_num = TOTAL_TRACKS+1; + if (i_track == CDIO_CDROM_LEADOUT_TRACK) + i_track = p_env->gen.i_tracks + p_env->gen.i_first_track; - if (track_num > TOTAL_TRACKS+1 || track_num == 0) { + if (i_track > (p_env->gen.i_tracks+p_env->gen.i_first_track) + || i_track < p_env->gen.i_first_track) { return false; } else { - struct cdrom_tocentry *msf0 = &_obj->tocent[track_num-1]; - msf->m = to_bcd8(msf0->cdte_addr.msf.minute); - msf->s = to_bcd8(msf0->cdte_addr.msf.second); - msf->f = to_bcd8(msf0->cdte_addr.msf.frame); + struct cdrom_tocentry *msf0 = &p_env->tocent[i_track-1]; + msf->m = cdio_to_bcd8(msf0->cdte_addr.msf.minute); + msf->s = cdio_to_bcd8(msf0->cdte_addr.msf.second); + msf->f = cdio_to_bcd8(msf0->cdte_addr.msf.frame); return true; } } @@ -603,6 +758,7 @@ cdio_get_default_device_solaris(void) { return strdup(DEFAULT_CDIO_DEVICE); } + #endif /* HAVE_SOLARIS_CDROM */ /*! @@ -614,21 +770,41 @@ cdio_get_devices_solaris (void) #ifndef HAVE_SOLARIS_CDROM return NULL; #else + char volpath[256]; + struct stat st; char **drives = NULL; - unsigned int num_files=0; + unsigned int i_files=0; #ifdef HAVE_GLOB_H unsigned int i; glob_t globbuf; + globbuf.gl_offs = 0; glob("/vol/dev/aliases/cdrom*", GLOB_DOOFFS, NULL, &globbuf); for (i=0; i<globbuf.gl_pathc; i++) { - cdio_add_device_list(&drives, globbuf.gl_pathv[i], &num_files); + if(stat(globbuf.gl_pathv[i], &st) < 0) + continue; + + /* Check if this is a directory, if so it's probably Solaris media */ + if(S_ISDIR(st.st_mode)) { + sprintf(volpath, "%s/s0", globbuf.gl_pathv[i]); + if(stat(volpath, &st) == 0) + cdio_add_device_list(&drives, volpath, &i_files); + }else + cdio_add_device_list(&drives, globbuf.gl_pathv[i], &i_files); } globfree(&globbuf); #else - cdio_add_device_list(&drives, DEFAULT_CDIO_DEVICE, &num_files); + if(stat(DEFAULT_CDIO_DEVICE, &st) == 0) { + /* Check if this is a directory, if so it's probably Solaris media */ + if(S_ISDIR(st.st_mode)) { + sprintf(volpath, "%s/s0", DEFAULT_CDIO_DEVICE); + if(stat(volpath, &st) == 0) + cdio_add_device_list(&drives, volpath, &i_files); + }else + cdio_add_device_list(&drives, DEFAULT_CDIO_DEVICE, &i_files); + } #endif /*HAVE_GLOB_H*/ - cdio_add_device_list(&drives, NULL, &num_files); + cdio_add_device_list(&drives, NULL, &i_files); return drives; #endif /*HAVE_SOLARIS_CDROM*/ } @@ -639,47 +815,85 @@ cdio_get_devices_solaris (void) ones to set that up. */ CdIo * -cdio_open_solaris (const char *source_name) +cdio_open_solaris (const char *psz_source_name) +{ + return cdio_open_am_solaris(psz_source_name, NULL); +} + +/*! + Initialization routine. This is the only thing that doesn't + get called via a function pointer. In fact *we* are the + ones to set that up. + */ +CdIo * +cdio_open_am_solaris (const char *psz_orig_source, const char *access_mode) { #ifdef HAVE_SOLARIS_CDROM CdIo *ret; _img_private_t *_data; - - cdio_funcs _funcs = { - .eject_media = _cdio_eject_media, - .free = cdio_generic_free, - .get_arg = _cdio_get_arg, - .get_devices = cdio_get_devices_solaris, - .get_default_device = cdio_get_default_device_solaris, - .get_first_track_num= _cdio_get_first_track_num, - .get_mcn = NULL, - .get_num_tracks = _cdio_get_num_tracks, - .get_track_format = _cdio_get_track_format, - .get_track_green = _cdio_get_track_green, - .get_track_lba = NULL, /* This could be implemented if need be. */ - .get_track_msf = _cdio_get_track_msf, - .lseek = cdio_generic_lseek, - .read = cdio_generic_read, - .read_audio_sectors = _cdio_read_audio_sectors, - .read_mode1_sector = _cdio_read_mode1_sector, - .read_mode1_sectors = _cdio_read_mode1_sectors, - .read_mode2_sector = _cdio_read_mode2_sector, - .read_mode2_sectors = _cdio_read_mode2_sectors, - .stat_size = _cdio_stat_size, - .set_arg = _cdio_set_arg - }; + char *psz_source; + + cdio_funcs _funcs; + + _funcs.eject_media = eject_media_solaris; + _funcs.free = cdio_generic_free; + _funcs.get_arg = get_arg_solaris; + _funcs.get_cdtext = get_cdtext_generic; + _funcs.get_default_device = cdio_get_default_device_solaris; + _funcs.get_devices = cdio_get_devices_solaris; + _funcs.get_discmode = get_discmode_solaris; + _funcs.get_drive_cap = scsi_mmc_get_drive_cap_generic; + _funcs.get_first_track_num= get_first_track_num_generic; + _funcs.get_hwinfo = NULL; + _funcs.get_mcn = scsi_mmc_get_mcn_generic, + _funcs.get_num_tracks = get_num_tracks_generic; + _funcs.get_track_format = get_track_format_solaris; + _funcs.get_track_green = _cdio_get_track_green; + _funcs.get_track_lba = NULL; /* This could be implemented if need be. */ + _funcs.get_track_msf = _cdio_get_track_msf; + _funcs.lseek = cdio_generic_lseek; + _funcs.read = cdio_generic_read; + _funcs.read_audio_sectors = _read_audio_sectors_solaris; + _funcs.read_mode1_sector = _read_mode1_sector_solaris; + _funcs.read_mode1_sectors = _read_mode1_sectors_solaris; + _funcs.read_mode2_sector = _read_mode2_sector_solaris; + _funcs.read_mode2_sectors = _read_mode2_sectors_solaris; + _funcs.read_toc = read_toc_solaris; + _funcs.run_scsi_mmc_cmd = run_scsi_cmd_solaris; + _funcs.stat_size = _cdio_stat_size; + _funcs.set_arg = _set_arg_solaris; _data = _cdio_malloc (sizeof (_img_private_t)); - _data->gen.fd = -1; - _cdio_set_arg(_data, "source", (NULL == source_name) - ? DEFAULT_CDIO_DEVICE: source_name); + _data->access_mode = _AM_SUN_CTRL_SCSI; + _data->gen.init = false; + _data->gen.fd = -1; + _data->gen.toc_init = false; + _data->gen.b_cdtext_init = false; + _data->gen.b_cdtext_error = false; + + if (NULL == psz_orig_source) { + psz_source = cdio_get_default_device_solaris(); + if (NULL == psz_source) return NULL; + _set_arg_solaris(_data, "source", psz_source); + free(psz_source); + } else { + if (cdio_is_device_generic(psz_orig_source)) + _set_arg_solaris(_data, "source", psz_orig_source); + else { + /* The below would be okay if all device drivers worked this way. */ +#if 0 + cdio_info ("source %s is not a device", psz_orig_source); +#endif + return NULL; + } + } - ret = cdio_new (_data, &_funcs); + ret = cdio_new ( (void *) _data, &_funcs ); if (ret == NULL) return NULL; - if (_cdio_init(_data)) + if (init_solaris(_data)) return ret; else { cdio_generic_free (_data); @@ -701,4 +915,3 @@ cdio_have_solaris (void) return false; #endif /* HAVE_SOLARIS_CDROM */ } - diff --git a/src/input/vcd/libcdio/bytesex.h b/src/input/vcd/libcdio/bytesex.h deleted file mode 100644 index a94a8129e..000000000 --- a/src/input/vcd/libcdio/bytesex.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - $Id: bytesex.h,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ - - Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> - - 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef __CDIO_BYTESEX_H__ -#define __CDIO_BYTESEX_H__ - -#include <cdio/logging.h> -#include <cdio/types.h> -#include "bytesex_asm.h" - -/* generic byteswap routines */ - -#define UINT16_SWAP_LE_BE_C(val) ((uint16_t) ( \ - (((uint16_t) (val) & (uint16_t) 0x00ffU) << 8) | \ - (((uint16_t) (val) & (uint16_t) 0xff00U) >> 8))) - -#define UINT32_SWAP_LE_BE_C(val) ((uint32_t) ( \ - (((uint32_t) (val) & (uint32_t) 0x000000ffU) << 24) | \ - (((uint32_t) (val) & (uint32_t) 0x0000ff00U) << 8) | \ - (((uint32_t) (val) & (uint32_t) 0x00ff0000U) >> 8) | \ - (((uint32_t) (val) & (uint32_t) 0xff000000U) >> 24))) - -#define UINT64_SWAP_LE_BE_C(val) ((uint64_t) ( \ - (((uint64_t) (val) & (uint64_t) UINT64_C(0x00000000000000ff)) << 56) | \ - (((uint64_t) (val) & (uint64_t) UINT64_C(0x000000000000ff00)) << 40) | \ - (((uint64_t) (val) & (uint64_t) UINT64_C(0x0000000000ff0000)) << 24) | \ - (((uint64_t) (val) & (uint64_t) UINT64_C(0x00000000ff000000)) << 8) | \ - (((uint64_t) (val) & (uint64_t) UINT64_C(0x000000ff00000000)) >> 8) | \ - (((uint64_t) (val) & (uint64_t) UINT64_C(0x0000ff0000000000)) >> 24) | \ - (((uint64_t) (val) & (uint64_t) UINT64_C(0x00ff000000000000)) >> 40) | \ - (((uint64_t) (val) & (uint64_t) UINT64_C(0xff00000000000000)) >> 56))) - -#ifndef UINT16_SWAP_LE_BE -# define UINT16_SWAP_LE_BE UINT16_SWAP_LE_BE_C -#endif - -#ifndef UINT32_SWAP_LE_BE -# define UINT32_SWAP_LE_BE UINT32_SWAP_LE_BE_C -#endif - -#ifndef UINT64_SWAP_LE_BE -# define UINT64_SWAP_LE_BE UINT64_SWAP_LE_BE_C -#endif - -inline static -uint16_t uint16_swap_le_be (const uint16_t val) -{ - return UINT16_SWAP_LE_BE (val); -} - -inline static -uint32_t uint32_swap_le_be (const uint32_t val) -{ - return UINT32_SWAP_LE_BE (val); -} - -inline static -uint64_t uint64_swap_le_be (const uint64_t val) -{ - return UINT64_SWAP_LE_BE (val); -} - -# define UINT8_TO_BE(val) ((uint8_t) (val)) -# define UINT8_TO_LE(val) ((uint8_t) (val)) -#ifdef WORDS_BIGENDIAN -# define UINT16_TO_BE(val) ((uint16_t) (val)) -# define UINT16_TO_LE(val) ((uint16_t) UINT16_SWAP_LE_BE(val)) - -# define UINT32_TO_BE(val) ((uint32_t) (val)) -# define UINT32_TO_LE(val) ((uint32_t) UINT32_SWAP_LE_BE(val)) - -# define UINT64_TO_BE(val) ((uint64_t) (val)) -# define UINT64_TO_LE(val) ((uint64_t) UINT64_SWAP_LE_BE(val)) -#else -# define UINT16_TO_BE(val) ((uint16_t) UINT16_SWAP_LE_BE(val)) -# define UINT16_TO_LE(val) ((uint16_t) (val)) - -# define UINT32_TO_BE(val) ((uint32_t) UINT32_SWAP_LE_BE(val)) -# define UINT32_TO_LE(val) ((uint32_t) (val)) - -# define UINT64_TO_BE(val) ((uint64_t) UINT64_SWAP_LE_BE(val)) -# define UINT64_TO_LE(val) ((uint64_t) (val)) -#endif - -/* symmetric conversions */ -#define UINT8_FROM_BE(val) (UINT8_TO_BE (val)) -#define UINT8_FROM_LE(val) (UINT8_TO_LE (val)) -#define UINT16_FROM_BE(val) (UINT16_TO_BE (val)) -#define UINT16_FROM_LE(val) (UINT16_TO_LE (val)) -#define UINT32_FROM_BE(val) (UINT32_TO_BE (val)) -#define UINT32_FROM_LE(val) (UINT32_TO_LE (val)) -#define UINT64_FROM_BE(val) (UINT64_TO_BE (val)) -#define UINT64_FROM_LE(val) (UINT64_TO_LE (val)) - -/* converter function template */ -#define CVT_TO_FUNC(bits) \ - static inline uint ## bits ## _t \ - uint ## bits ## _to_be (uint ## bits ## _t val) \ - { return UINT ## bits ## _TO_BE (val); } \ - static inline uint ## bits ## _t \ - uint ## bits ## _to_le (uint ## bits ## _t val) \ - { return UINT ## bits ## _TO_LE (val); } \ - -CVT_TO_FUNC(8) -CVT_TO_FUNC(16) -CVT_TO_FUNC(32) -CVT_TO_FUNC(64) - -#undef CVT_TO_FUNC - -#define uint8_from_be(val) (uint8_to_be (val)) -#define uint8_from_le(val) (uint8_to_le (val)) -#define uint16_from_be(val) (uint16_to_be (val)) -#define uint16_from_le(val) (uint16_to_le (val)) -#define uint32_from_be(val) (uint32_to_be (val)) -#define uint32_from_le(val) (uint32_to_le (val)) -#define uint64_from_be(val) (uint64_to_be (val)) -#define uint64_from_le(val) (uint64_to_le (val)) - -/* ISO9660 related stuff */ - -#define to_711(i) uint8_to_le(i) -#define from_711(i) uint8_from_le(i) - -#define to_721(i) uint16_to_le(i) -#define from_721(i) uint16_from_le(i) - -#define to_721(i) uint16_to_le(i) -#define from_721(i) uint16_from_le(i) - -#define to_722(i) uint16_to_be(i) -#define from_722(i) uint16_from_be(i) - -static inline uint32_t -to_723(uint16_t i) -{ - return uint32_swap_le_be(i) | i; -} - -static inline uint16_t -from_723 (uint32_t p) -{ - if (uint32_swap_le_be (p) != p) - cdio_warn ("from_723: broken byte order"); - - return (0xFFFF & p); -} - -#define to_731(i) uint32_to_le(i) -#define from_731(i) uint32_from_le(i) - -#define to_732(i) uint32_to_be(i) -#define from_732(i) uint32_from_be(i) - -static inline uint64_t -to_733(uint32_t i) -{ - return uint64_swap_le_be(i) | i; -} - -static inline uint32_t -from_733 (uint64_t p) -{ - if (uint64_swap_le_be (p) != p) - cdio_warn ("from_733: broken byte order"); - - return (UINT32_C(0xFFFFFFFF) & p); -} - -#endif /* __CDIO_BYTESEX_H__ */ - - -/* - * Local variables: - * c-file-style: "gnu" - * tab-width: 8 - * indent-tabs-mode: nil - * End: - */ diff --git a/src/input/vcd/libcdio/bytesex_asm.h b/src/input/vcd/libcdio/bytesex_asm.h deleted file mode 100644 index 03cb3cd98..000000000 --- a/src/input/vcd/libcdio/bytesex_asm.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - $Id: bytesex_asm.h,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ - - Copyright (C) 2001 Sven Ottemann <ac-logic@freenet.de> - 2001 Herbert Valerio Riedel <hvr@gnu.org> - - 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef __CDIO_BYTESEX_ASM_H__ -#define __CDIO_BYTESEX_ASM_H__ -#if !defined(DISABLE_ASM_OPTIMIZE) - -#include <cdio/types.h> - -#if defined(__powerpc__) && defined(__GNUC__) - -inline static -uint32_t uint32_swap_le_be_asm(const uint32_t a) -{ - uint32_t b; - - __asm__ ("lwbrx %0,0,%1" - :"=r"(b) - :"r"(&a), "m"(a)); - - return b; -} - -inline static -uint16_t uint16_swap_le_be_asm(const uint16_t a) -{ - uint32_t b; - - __asm__ ("lhbrx %0,0,%1" - :"=r"(b) - :"r"(&a), "m"(a)); - - return b; -} - -#define UINT16_SWAP_LE_BE uint16_swap_le_be_asm -#define UINT32_SWAP_LE_BE uint32_swap_le_be_asm - -#elif defined(__mc68000__) && defined(__STORMGCC__) - -inline static -uint32_t uint32_swap_le_be_asm(uint32_t a __asm__("d0")) -{ - /* __asm__("rolw #8,%0; swap %0; rolw #8,%0" : "=d" (val) : "0" (val)); */ - - __asm__("move.l %1,d0;rol.w #8,d0;swap d0;rol.w #8,d0;move.l d0,%0" - :"=r"(a) - :"r"(a)); - - return(a); -} - -inline static -uint16_t uint16_swap_le_be_asm(uint16_t a __asm__("d0")) -{ - __asm__("move.l %1,d0;rol.w #8,d0;move.l d0,%0" - :"=r"(a) - :"r"(a)); - - return(a); -} - -#define UINT16_SWAP_LE_BE uint16_swap_le_be_asm -#define UINT32_SWAP_LE_BE uint32_swap_le_be_asm - -#elif 0 && defined(__i386__) && defined(__GNUC__) - -inline static -uint32_t uint32_swap_le_be_asm(uint32_t a) -{ - __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */ - "rorl $16,%0\n\t" /* swap words */ - "xchgb %b0,%h0" /* swap higher bytes */ - :"=q" (a) - : "0" (a)); - - return(a); -} - -inline static -uint16_t uint16_swap_le_be_asm(uint16_t a) -{ - __asm__("xchgb %b0,%h0" /* swap bytes */ - : "=q" (a) - : "0" (a)); - - return(a); -} - -#define UINT16_SWAP_LE_BE uint16_swap_le_be_asm -#define UINT32_SWAP_LE_BE uint32_swap_le_be_asm - -#endif - -#endif /* !defined(DISABLE_ASM_OPTIMIZE) */ -#endif /* __CDIO_BYTESEX_ASM_H__ */ - - -/* - * Local variables: - * c-file-style: "gnu" - * tab-width: 8 - * indent-tabs-mode: nil - * End: - */ diff --git a/src/input/vcd/libcdio/cd_types.c b/src/input/vcd/libcdio/cd_types.c index 49ffc79e0..b983f9899 100644 --- a/src/input/vcd/libcdio/cd_types.c +++ b/src/input/vcd/libcdio/cd_types.c @@ -1,7 +1,7 @@ /* - $Id: cd_types.c,v 1.3 2004/07/22 14:15:19 mroi Exp $ + $Id: cd_types.c,v 1.4 2005/01/01 02:43:57 rockyb Exp $ - Copyright (C) 2003 Rocky Bernstein <rocky@panix.com> + Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> 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 @@ -63,9 +63,13 @@ and static char buffer[6][CDIO_CD_FRAMESIZE_RAW]; /* for CD-Data */ /* Some interesting sector numbers stored in the above buffer. */ +#define ISO_SUPERBLOCK_SECTOR 16 /* buffer[0] */ #define UFS_SUPERBLOCK_SECTOR 4 /* buffer[2] */ #define BOOT_SECTOR 17 /* buffer[3] */ #define VCD_INFO_SECTOR 150 /* buffer[4] */ +#define XISO_SECTOR 32 /* buffer[4] */ +#define UDFX_SECTOR 32 /* buffer[4] */ +#define UDF_ANCHOR_SECTOR 256 /* buffer[5] */ typedef struct signature @@ -79,6 +83,8 @@ typedef struct signature static signature_t sigs[] = { /*buffer[x] off look for description */ + {0, 0, "MICROSOFT*XBOX*MEDIA", "XBOX CD"}, + {0, 1, "BEA01", "UDF"}, {0, 1, ISO_STANDARD_ID, "ISO 9660"}, {0, 1, "CD-I", "CD-I"}, {0, 8, "CDTV", "CDTV"}, @@ -97,19 +103,21 @@ static signature_t sigs[] = /* The below index into the above sigs array. Make sure things match. */ -#define INDEX_ISOFS 0 -#define INDEX_CD_I 1 -#define INDEX_CDTV 2 -#define INDEX_CD_RTOS 3 -#define INDEX_HS 4 -#define INDEX_BRIDGE 5 -#define INDEX_XA 6 -#define INDEX_PHOTO_CD 7 -#define INDEX_EXT2 8 -#define INDEX_UFS 9 -#define INDEX_BOOTABLE 10 -#define INDEX_VIDEO_CD 11 /* Video CD */ -#define INDEX_SVCD 12 /* CVD *or* SVCD */ +#define INDEX_XISO 0 /* Microsoft X-BOX filesystem */ +#define INDEX_UDF 1 +#define INDEX_ISOFS 2 +#define INDEX_CD_I 3 +#define INDEX_CDTV 4 +#define INDEX_CD_RTOS 5 +#define INDEX_HS 6 +#define INDEX_BRIDGE 7 +#define INDEX_XA 8 +#define INDEX_PHOTO_CD 9 +#define INDEX_EXT2 10 +#define INDEX_UFS 11 +#define INDEX_BOOTABLE 12 +#define INDEX_VIDEO_CD 13 /* Video CD */ +#define INDEX_SVCD 14 /* CVD *or* SVCD */ /* @@ -118,21 +126,21 @@ static signature_t sigs[] = */ static int _cdio_read_block(const CdIo *cdio, int superblock, uint32_t offset, - uint8_t bufnum, track_t track_num) + uint8_t bufnum, track_t i_track) { - unsigned int track_sec_count = cdio_get_track_sec_count(cdio, track_num); + unsigned int track_sec_count = cdio_get_track_sec_count(cdio, i_track); memset(buffer[bufnum], 0, CDIO_CD_FRAMESIZE); if ( track_sec_count < superblock) { cdio_debug("reading block %u skipped track %d has only %u sectors\n", - superblock, track_num, track_sec_count); + superblock, i_track, track_sec_count); return -1; } cdio_debug("about to read sector %lu\n", (long unsigned int) offset+superblock); - if (cdio_get_track_green(cdio, track_num)) { + if (cdio_get_track_green(cdio, i_track)) { if (0 > cdio_read_mode2_sector(cdio, buffer[bufnum], offset+superblock, false)) return -1; @@ -180,6 +188,12 @@ _cdio_is_joliet(void) return 2 == buffer[3][0] && buffer[3][88] == 0x25 && buffer[3][89] == 0x2f; } +static int +_cdio_is_UDF(void) +{ + return 2 == ((uint16_t)buffer[5][0] | ((uint16_t)buffer[5][1] << 8)); +} + /* ISO 9660 volume space in M2F1_SECTOR_SIZE byte units */ static int _cdio_get_iso9660_fs_sec_count(void) @@ -203,23 +217,47 @@ _cdio_get_joliet_level( void ) /* Try to determine what kind of CD-image and/or filesystem we - have at track track_num. Return information about the CD image + have at track i_track. Return information about the CD image is returned in cdio_analysis and the return value. */ cdio_fs_anal_t -cdio_guess_cd_type(const CdIo *cdio, int start_session, track_t track_num, +cdio_guess_cd_type(const CdIo *cdio, int start_session, track_t i_track, /*out*/ cdio_iso_analysis_t *iso_analysis) { - int ret = 0; + int ret = CDIO_FS_UNKNOWN; bool sector0_read_ok; - if (TRACK_FORMAT_AUDIO == cdio_get_track_format(cdio, track_num)) + if (TRACK_FORMAT_AUDIO == cdio_get_track_format(cdio, i_track)) return CDIO_FS_AUDIO; if ( _cdio_read_block(cdio, ISO_PVD_SECTOR, start_session, - 0, track_num) < 0 ) + 0, i_track) < 0 ) return CDIO_FS_UNKNOWN; + if ( _cdio_is_it(INDEX_XISO) ) + return CDIO_FS_ANAL_XISO; + + if (_cdio_read_block(cdio, ISO_SUPERBLOCK_SECTOR, start_session, 0, + i_track) < 0) + return ret; + + if ( _cdio_is_it(INDEX_UDF) ) { + /* Detect UDF version + Test if we have a valid version of UDF the xbox can read natively */ + if (_cdio_read_block(cdio, 35, start_session, 5, i_track) < 0) + return CDIO_FS_UNKNOWN; + + iso_analysis->UDFVerMinor=(unsigned int)buffer[5][240]; + iso_analysis->UDFVerMajor=(unsigned int)buffer[5][241]; + /* Read disc label */ + if (_cdio_read_block(cdio, 32, start_session, 5, i_track) < 0) + return CDIO_FS_UDF; + + strncpy(iso_analysis->iso_label, buffer[5]+25, 33); + iso_analysis->iso_label[32] = '\0'; + return CDIO_FS_UDF; + } + /* We have something that smells of a filesystem. */ if (_cdio_is_it(INDEX_CD_I) && _cdio_is_it(INDEX_CD_RTOS) && !_cdio_is_it(INDEX_BRIDGE) && !_cdio_is_it(INDEX_XA)) { @@ -228,7 +266,7 @@ cdio_guess_cd_type(const CdIo *cdio, int start_session, track_t track_num, /* read sector 0 ONLY, when NO greenbook CD-I !!!! */ sector0_read_ok = - _cdio_read_block(cdio, 0, start_session, 1, track_num) == 0; + _cdio_read_block(cdio, 0, start_session, 1, i_track) == 0; if (_cdio_is_it(INDEX_HS)) ret |= CDIO_FS_HIGH_SIERRA; @@ -240,14 +278,40 @@ cdio_guess_cd_type(const CdIo *cdio, int start_session, track_t track_num, else ret = CDIO_FS_ISO_9660; iso_analysis->isofs_size = _cdio_get_iso9660_fs_sec_count(); - snprintf(iso_analysis->iso_label, 33, "%s", buffer[0]+40); + strncpy(iso_analysis->iso_label, buffer[0]+40,33); + iso_analysis->iso_label[32] = '\0'; + if ( _cdio_read_block(cdio, UDF_ANCHOR_SECTOR, start_session, 5, + i_track) < 0) + return ret; + + /* Maybe there is an UDF anchor in IOS session + so its ISO/UDF session and we prefere UDF */ + if ( _cdio_is_UDF() ) { + /* Detect UDF version. + Test if we have a valid version of UDF the xbox can read natively */ + if ( _cdio_read_block(cdio, 35, start_session, 5, i_track) < 0) + return ret; + + iso_analysis->UDFVerMinor=(unsigned int)buffer[5][240]; + iso_analysis->UDFVerMajor=(unsigned int)buffer[5][241]; +#if 0 + /* We are using ISO/UDF cd's as iso, + no need to get UDF disc label */ + if (_cdio_read_block(cdio, 32, start_session, 5, i_track) < 0) + return ret; + stnrcpy(iso_analysis->iso_label, buffer[5]+25, 33); + iso_analysis->iso_label[32] = '\0'; +#endif + ret=CDIO_FS_ISO_UDF; + } + #if 0 if (_cdio_is_rockridge()) ret |= CDIO_FS_ANAL_ROCKRIDGE; #endif - if (_cdio_read_block(cdio, BOOT_SECTOR, start_session, 3, track_num) < 0) + if (_cdio_read_block(cdio, BOOT_SECTOR, start_session, 3, i_track) < 0) return ret; if (_cdio_is_joliet()) { @@ -261,7 +325,7 @@ cdio_guess_cd_type(const CdIo *cdio, int start_session, track_t track_num, && !(sector0_read_ok && _cdio_is_it(INDEX_PHOTO_CD)) ) { if ( _cdio_read_block(cdio, VCD_INFO_SECTOR, start_session, 4, - track_num) < 0 ) + i_track) < 0 ) return ret; if (_cdio_is_it(INDEX_BRIDGE) && _cdio_is_it(INDEX_CD_RTOS)) { @@ -276,7 +340,7 @@ cdio_guess_cd_type(const CdIo *cdio, int start_session, track_t track_num, else if (_cdio_is_3do()) ret |= CDIO_FS_3DO; else { if ( _cdio_read_block(cdio, UFS_SUPERBLOCK_SECTOR, start_session, 2, - track_num) < 0 ) + i_track) < 0 ) return ret; if (sector0_read_ok && _cdio_is_it(INDEX_UFS)) diff --git a/src/input/vcd/libcdio/cdio.c b/src/input/vcd/libcdio/cdio.c index 2a814141b..fc18add91 100644 --- a/src/input/vcd/libcdio/cdio.c +++ b/src/input/vcd/libcdio/cdio.c @@ -1,5 +1,5 @@ /* - $Id: cdio.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: cdio.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $ Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> @@ -26,7 +26,9 @@ #include <sys/types.h> #include <sys/stat.h> +#ifdef HAVE_UNISTD_H #include <unistd.h> +#endif #include <errno.h> #include <string.h> @@ -37,7 +39,7 @@ #include <cdio/logging.h> #include "cdio_private.h" -static const char _rcsid[] = "$Id: cdio.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: cdio.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $"; const char *track_format2str[6] = @@ -45,6 +47,24 @@ const char *track_format2str[6] = "audio", "CD-i", "XA", "data", "PSX", "error" }; +/* Must match discmode enumeration */ +const char *discmode2str[] = { + "CD-DA", + "CD-DATA Form 1", + "CD DATA Form 2", + "CD-ROM Mixed", + "DVD-ROM", + "DVD-RAM", + "DVD-R", + "DVD-RW", + "DVD+R", + "DVD+RW", + "Unknown/unclassified DVD", + "No information", + "Error in getting information" +}; + + /* The below array gives of the drivers that are currently available for on a particular host. */ @@ -58,13 +78,28 @@ CdIo_driver_t CdIo_driver[CDIO_MAX_DRIVER] = { {0} }; #define CDIO_DRIVER_UNINIT -1 int CdIo_last_driver = CDIO_DRIVER_UNINIT; +#ifdef HAVE_BSDI_CDROM +const driver_id_t cdio_os_driver = DRIVER_BSDI; +#elif HAVE_FREEBSD_CDROM +const driver_id_t cdio_os_driver = DRIVER_FREEBSD; +#elif HAVE_LINUX_CDROM +const driver_id_t cdio_os_driver = DRIVER_LINUX; +#elif HAVE_DARWIN_CDROM +const driver_id_t cdio_os_driver = DRIVER_OSX; +#elif HAVE_DARWIN_SOLARIS +const driver_id_t cdio_os_driver = DRIVER_SOLARIS; +#elif HAVE_DARWIN_WIN32 +const driver_id_t cdio_os_driver = DRIVER_WIN32; +#else +const driver_id_t cdio_os_driver = DRIVER_UNKNOWN; +#endif + static bool cdio_have_false(void) { return false; } - /* The below array gives all drivers that can possibly appear. on a particular host. */ @@ -77,6 +112,7 @@ CdIo_driver_t CdIo_all_drivers[CDIO_MAX_DRIVER+1] = { NULL, NULL, NULL, + NULL, NULL }, @@ -86,6 +122,7 @@ CdIo_driver_t CdIo_all_drivers[CDIO_MAX_DRIVER+1] = { "BSDI ATAPI and SCSI driver", &cdio_have_bsdi, &cdio_open_bsdi, + &cdio_open_am_bsdi, &cdio_get_default_device_bsdi, &cdio_is_device_generic, &cdio_get_devices_bsdi @@ -97,6 +134,7 @@ CdIo_driver_t CdIo_all_drivers[CDIO_MAX_DRIVER+1] = { "FreeBSD driver", &cdio_have_freebsd, &cdio_open_freebsd, + &cdio_open_am_freebsd, &cdio_get_default_device_freebsd, &cdio_is_device_generic, NULL @@ -108,6 +146,7 @@ CdIo_driver_t CdIo_all_drivers[CDIO_MAX_DRIVER+1] = { "GNU/Linux ioctl and MMC driver", &cdio_have_linux, &cdio_open_linux, + &cdio_open_am_linux, &cdio_get_default_device_linux, &cdio_is_device_generic, &cdio_get_devices_linux @@ -119,6 +158,7 @@ CdIo_driver_t CdIo_all_drivers[CDIO_MAX_DRIVER+1] = { "Solaris ATAPI and SCSI driver", &cdio_have_solaris, &cdio_open_solaris, + &cdio_open_am_solaris, &cdio_get_default_device_solaris, &cdio_is_device_generic, &cdio_get_devices_solaris @@ -130,6 +170,7 @@ CdIo_driver_t CdIo_all_drivers[CDIO_MAX_DRIVER+1] = { "Apple Darwin OS X driver", &cdio_have_osx, &cdio_open_osx, + &cdio_open_am_osx, &cdio_get_default_device_osx, &cdio_is_device_generic, &cdio_get_devices_osx @@ -138,20 +179,34 @@ CdIo_driver_t CdIo_all_drivers[CDIO_MAX_DRIVER+1] = { {DRIVER_WIN32, CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK, "WIN32", - "Windows 32-bit ASPI and winNT/2K/XP ioctl driver", + "MS Windows ASPI and ioctl driver", &cdio_have_win32, &cdio_open_win32, + &cdio_open_am_win32, &cdio_get_default_device_win32, &cdio_is_device_win32, &cdio_get_devices_win32 }, + {DRIVER_CDRDAO, + CDIO_SRC_IS_DISK_IMAGE_MASK, + "CDRDAO", + "cdrdao (TOC) disk image driver", + &cdio_have_cdrdao, + &cdio_open_cdrdao, + &cdio_open_am_cdrdao, + &cdio_get_default_device_cdrdao, + NULL, + &cdio_get_devices_cdrdao + }, + {DRIVER_BINCUE, CDIO_SRC_IS_DISK_IMAGE_MASK, "BIN/CUE", "bin/cuesheet disk image driver", &cdio_have_bincue, &cdio_open_bincue, + &cdio_open_am_bincue, &cdio_get_default_device_bincue, NULL, &cdio_get_devices_bincue @@ -163,6 +218,7 @@ CdIo_driver_t CdIo_all_drivers[CDIO_MAX_DRIVER+1] = { "Nero NRG disk image driver", &cdio_have_nrg, &cdio_open_nrg, + &cdio_open_am_nrg, &cdio_get_default_device_nrg, NULL, &cdio_get_devices_nrg @@ -171,13 +227,15 @@ CdIo_driver_t CdIo_all_drivers[CDIO_MAX_DRIVER+1] = { }; static CdIo * -scan_for_driver(driver_id_t start, driver_id_t end, const char *source_name) +scan_for_driver(driver_id_t start, driver_id_t end, + const char *psz_source, const char *access_mode) { driver_id_t driver_id; for (driver_id=start; driver_id<=end; driver_id++) { if ((*CdIo_all_drivers[driver_id].have_driver)()) { - CdIo *ret=(*CdIo_all_drivers[driver_id].driver_open)(source_name); + CdIo *ret= + (*CdIo_all_drivers[driver_id].driver_open_am)(psz_source, access_mode); if (ret != NULL) { ret->driver_id = driver_id; return ret; @@ -246,6 +304,25 @@ cdio_get_arg (const CdIo *obj, const char key[]) } } +/*! + Get cdtext information for a CdIo object . + + @param obj the CD object that may contain CD-TEXT information. + @return the CD-TEXT object or NULL if obj is NULL + or CD-TEXT information does not exist. +*/ +const cdtext_t * +cdio_get_cdtext (CdIo *obj, track_t i_track) +{ + if (obj == NULL) return NULL; + + if (obj->op.get_cdtext) { + return obj->op.get_cdtext (obj->env, i_track); + } else { + return NULL; + } +} + /*! Return a string containing the default CD device if none is specified. if CdIo is NULL (we haven't initialized a specific device driver), @@ -285,22 +362,31 @@ cdio_get_default_device (const CdIo *obj) char ** cdio_get_devices (driver_id_t driver_id) { - CdIo *cdio; + /* Probably could get away with &driver_id below. */ + driver_id_t driver_id_temp = driver_id; + return cdio_get_devices_ret (&driver_id_temp); +} - switch (driver_id) { +char ** +cdio_get_devices_ret (/*in/out*/ driver_id_t *p_driver_id) +{ + CdIo *p_cdio; + + switch (*p_driver_id) { /* FIXME: spit out unknown to give image drivers as well. */ case DRIVER_UNKNOWN: case DRIVER_DEVICE: - cdio = scan_for_driver(DRIVER_UNKNOWN, CDIO_MAX_DRIVER, NULL); + p_cdio = scan_for_driver(DRIVER_UNKNOWN, CDIO_MAX_DRIVER, NULL, NULL); + *p_driver_id = cdio_get_driver_id(p_cdio); break; default: - return (*CdIo_all_drivers[driver_id].get_devices)(); + return (*CdIo_all_drivers[*p_driver_id].get_devices)(); } - if (cdio == NULL) return NULL; - if (cdio->op.get_devices) { - char **devices = cdio->op.get_devices (); - cdio_destroy(cdio); + if (p_cdio == NULL) return NULL; + if (p_cdio->op.get_devices) { + char **devices = p_cdio->op.get_devices (); + cdio_destroy(p_cdio); return devices; } else { return NULL; @@ -324,14 +410,26 @@ cdio_get_devices (driver_id_t driver_id) the value is NULL. This also means nothing was found. */ char ** -cdio_get_devices_with_cap (char* search_devices[], +cdio_get_devices_with_cap (/*out*/ char* search_devices[], cdio_fs_anal_t capabilities, bool any) { + driver_id_t p_driver_id; + return cdio_get_devices_with_cap_ret (search_devices, capabilities, any, + &p_driver_id); +} + +char ** +cdio_get_devices_with_cap_ret (/*out*/ char* search_devices[], + cdio_fs_anal_t capabilities, bool any, + /*out*/ driver_id_t *p_driver_id) +{ char **drives=search_devices; char **drives_ret=NULL; - int num_drives=0; + unsigned int i_drives=0; + + *p_driver_id = DRIVER_DEVICE; - if (NULL == drives) drives=cdio_get_devices(DRIVER_DEVICE); + if (NULL == drives) drives=cdio_get_devices_ret(p_driver_id); if (NULL == drives) return NULL; if (capabilities == CDIO_FS_MATCH_ALL) { @@ -339,7 +437,7 @@ cdio_get_devices_with_cap (char* search_devices[], char **d = drives; for( ; *d != NULL; d++ ) { - cdio_add_device_list(&drives_ret, *d, &num_drives); + cdio_add_device_list(&drives_ret, *d, &i_drives); } } else { cdio_fs_anal_t got_fs=0; @@ -349,7 +447,7 @@ cdio_get_devices_with_cap (char* search_devices[], need_fs_ext = capabilities & ~CDIO_FS_MASK; for( ; *d != NULL; d++ ) { - CdIo *cdio = cdio_open(*d, DRIVER_UNKNOWN); + CdIo *cdio = cdio_open(*d, *p_driver_id); if (NULL != cdio) { track_t first_track = cdio_get_first_track_num(cdio); @@ -363,19 +461,84 @@ cdio_get_devices_with_cap (char* search_devices[], ? (got_fs & need_fs_ext) != 0 : (got_fs | ~need_fs_ext) == -1; if (doit) - cdio_add_device_list(&drives_ret, *drives, &num_drives); + cdio_add_device_list(&drives_ret, *d, &i_drives); } cdio_destroy(cdio); } } } - cdio_add_device_list(&drives_ret, NULL, &num_drives); + cdio_add_device_list(&drives_ret, NULL, &i_drives); cdio_free_device_list(drives); free(drives); return drives_ret; } +/*! + Get medium associated with cd_obj. +*/ +discmode_t +cdio_get_discmode (CdIo *cd_obj) +{ + if (cd_obj == NULL) return CDIO_DISC_MODE_ERROR; + + if (cd_obj->op.get_discmode) { + return cd_obj->op.get_discmode (cd_obj->env); + } else { + return CDIO_DISC_MODE_NO_INFO; + } +} + +/*! + Return the the kind of drive capabilities of device. + + Note: string is malloc'd so caller should free() then returned + string when done with it. + + */ +void +cdio_get_drive_cap (const CdIo *p_cdio, + cdio_drive_read_cap_t *p_read_cap, + cdio_drive_write_cap_t *p_write_cap, + cdio_drive_misc_cap_t *p_misc_cap) +{ + /* This seems like a safe bet. */ + *p_read_cap = CDIO_DRIVE_CAP_UNKNOWN; + *p_write_cap = CDIO_DRIVE_CAP_UNKNOWN; + *p_misc_cap = CDIO_DRIVE_CAP_UNKNOWN; + + if (p_cdio && p_cdio->op.get_drive_cap) { + p_cdio->op.get_drive_cap(p_cdio->env, p_read_cap, p_write_cap, p_misc_cap); + } +} + +/*! + Return the the kind of drive capabilities of device. + + Note: string is malloc'd so caller should free() then returned + string when done with it. + + */ +void +cdio_get_drive_cap_dev (const char *device, + cdio_drive_read_cap_t *p_read_cap, + cdio_drive_write_cap_t *p_write_cap, + cdio_drive_misc_cap_t *p_misc_cap) +{ + /* This seems like a safe bet. */ + CdIo *cdio=scan_for_driver(CDIO_MIN_DRIVER, CDIO_MAX_DRIVER, + device, NULL); + if (cdio) { + cdio_get_drive_cap(cdio, p_read_cap, p_write_cap, p_misc_cap); + cdio_destroy(cdio); + } else { + *p_read_cap = CDIO_DRIVE_CAP_UNKNOWN; + *p_write_cap = CDIO_DRIVE_CAP_UNKNOWN; + *p_misc_cap = CDIO_DRIVE_CAP_UNKNOWN; + } +} + + /*! Return a string containing the name of the driver in use. if CdIo is NULL (we haven't initialized a specific device driver), @@ -384,21 +547,34 @@ cdio_get_devices_with_cap (char* search_devices[], const char * cdio_get_driver_name (const CdIo *cdio) { + if (NULL==cdio) return NULL; return CdIo_all_drivers[cdio->driver_id].name; } + /*! + Return the driver id. + if CdIo is NULL (we haven't initialized a specific device driver), + then return DRIVER_UNKNOWN. + */ +driver_id_t +cdio_get_driver_id (const CdIo *cdio) +{ + if (NULL==cdio) return DRIVER_UNKNOWN; + return cdio->driver_id; +} + /*! - Return the number of of the first track. + Return the number of the first track. CDIO_INVALID_TRACK is returned on error. */ track_t -cdio_get_first_track_num (const CdIo *cdio) +cdio_get_first_track_num (const CdIo *p_cdio) { - cdio_assert (cdio != NULL); + if (NULL == p_cdio) return CDIO_INVALID_TRACK; - if (cdio->op.get_first_track_num) { - return cdio->op.get_first_track_num (cdio->env); + if (p_cdio->op.get_first_track_num) { + return p_cdio->op.get_first_track_num (p_cdio->env); } else { return CDIO_INVALID_TRACK; } @@ -409,11 +585,29 @@ cdio_get_first_track_num (const CdIo *cdio) if CdIo is NULL (we haven't initialized a specific device driver), then return NULL. */ +bool +cdio_get_hwinfo (const CdIo *p_cdio, cdio_hwinfo_t *hw_info) +{ + if (!p_cdio) return false; + if (p_cdio->op.get_hwinfo) { + return p_cdio->op.get_hwinfo (p_cdio, hw_info); + } else { + /* Perhaps driver forgot to initialize. We are no worse off Using + scsi_mmc than returning false here. */ + return scsi_mmc_get_hwinfo(p_cdio, hw_info); + } +} + +/*! + Return a string containing the name of the driver in use. + if CdIo is NULL (we haven't initialized a specific device driver), + then return NULL. +*/ char * -cdio_get_mcn (const CdIo *cdio) +cdio_get_mcn (const CdIo *p_cdio) { - if (cdio->op.get_mcn) { - return cdio->op.get_mcn (cdio->env); + if (p_cdio->op.get_mcn) { + return p_cdio->op.get_mcn (p_cdio->env); } else { return NULL; } @@ -424,12 +618,12 @@ cdio_get_mcn (const CdIo *cdio) CDIO_INVALID_TRACK is returned on error. */ track_t -cdio_get_num_tracks (const CdIo *cdio) +cdio_get_num_tracks (const CdIo *p_cdio) { - if (cdio == NULL) return CDIO_INVALID_TRACK; + if (p_cdio == NULL) return CDIO_INVALID_TRACK; - if (cdio->op.get_num_tracks) { - return cdio->op.get_num_tracks (cdio->env); + if (p_cdio->op.get_num_tracks) { + return p_cdio->op.get_num_tracks (p_cdio->env); } else { return CDIO_INVALID_TRACK; } @@ -439,12 +633,12 @@ cdio_get_num_tracks (const CdIo *cdio) Get format of track. */ track_format_t -cdio_get_track_format(const CdIo *cdio, track_t track_num) +cdio_get_track_format(const CdIo *p_cdio, track_t i_track) { - cdio_assert (cdio != NULL); + cdio_assert (p_cdio != NULL); - if (cdio->op.get_track_format) { - return cdio->op.get_track_format (cdio->env, track_num); + if (p_cdio->op.get_track_format) { + return p_cdio->op.get_track_format (p_cdio->env, i_track); } else { return TRACK_FORMAT_ERROR; } @@ -562,11 +756,25 @@ cdio_have_driver(driver_id_t driver_id) return (*CdIo_all_drivers[driver_id].have_driver)(); } +/*! + Return the Joliet level recognized for p_cdio. +*/ +uint8_t +cdio_get_joliet_level(const CdIo *p_cdio) +{ + if (!p_cdio) return 0; + { + const generic_img_private_t *p_env + = (generic_img_private_t *) (p_cdio->env); + return p_env->i_joliet_level; + } +} + bool -cdio_is_device(const char *source_name, driver_id_t driver_id) +cdio_is_device(const char *psz_source, driver_id_t driver_id) { if (CdIo_all_drivers[driver_id].is_device == NULL) return false; - return (*CdIo_all_drivers[driver_id].is_device)(source_name); + return (*CdIo_all_drivers[driver_id].is_device)(psz_source); } @@ -599,16 +807,19 @@ cdio_init(void) } CdIo * -cdio_new (void *env, const cdio_funcs *funcs) +cdio_new (generic_img_private_t *p_env, cdio_funcs *p_funcs) { - CdIo *new_cdio; - - new_cdio = _cdio_malloc (sizeof (CdIo)); + CdIo *p_new_cdio = _cdio_malloc (sizeof (CdIo)); - new_cdio->env = env; - new_cdio->op = *funcs; - - return new_cdio; + if (NULL == p_new_cdio) return NULL; + + p_new_cdio->env = p_env; /* This is the private "environment" that + driver-dependent routines use. */ + p_new_cdio->op = *p_funcs; + p_env->cdio = p_new_cdio; /* A way for the driver-dependent routines + to access the higher-level general cdio + object. */ + return p_new_cdio; } /*! @@ -646,35 +857,44 @@ cdio_lseek (const CdIo *cdio, off_t offset, int whence) Similar to (if not the same as) libc's read() */ ssize_t -cdio_read (const CdIo *cdio, void *buf, size_t size) +cdio_read (const CdIo *p_cdio, void *buf, size_t size) { - if (cdio == NULL) return -1; + if (p_cdio == NULL) return -1; - if (cdio->op.read) - return cdio->op.read (cdio->env, buf, size); + if (p_cdio->op.read) + return p_cdio->op.read (p_cdio->env, buf, size); return -1; } +/*! + Reads an audio sector from cd device into data starting + from lsn. Returns 0 if no error. +*/ int -cdio_read_audio_sector (const CdIo *cdio, void *buf, lsn_t lsn) +cdio_read_audio_sector (const CdIo *p_cdio, void *buf, lsn_t lsn) { - cdio_assert (cdio != NULL); - cdio_assert (buf != NULL); - if (cdio->op.read_audio_sectors != NULL) - return cdio->op.read_audio_sectors (cdio->env, buf, lsn, 1); + if (NULL == p_cdio || NULL == buf || CDIO_INVALID_LSN == lsn ) + return 0; + + if (p_cdio->op.read_audio_sectors != NULL) + return p_cdio->op.read_audio_sectors (p_cdio->env, buf, lsn, 1); return -1; } +/*! + Reads audio sectors from cd device into data starting + from lsn. Returns 0 if no error. +*/ int -cdio_read_audio_sectors (const CdIo *cdio, void *buf, lsn_t lsn, +cdio_read_audio_sectors (const CdIo *p_cdio, void *buf, lsn_t lsn, unsigned int nblocks) { - cdio_assert (cdio != NULL); - cdio_assert (buf != NULL); + if ( NULL == p_cdio || NULL == buf || CDIO_INVALID_LSN == lsn ) + return 0; - if (cdio->op.read_audio_sectors != NULL) - return cdio->op.read_audio_sectors (cdio->env, buf, lsn, nblocks); + if (p_cdio->op.read_audio_sectors != NULL) + return p_cdio->op.read_audio_sectors (p_cdio->env, buf, lsn, nblocks); return -1; } @@ -687,20 +907,21 @@ cdio_read_audio_sectors (const CdIo *cdio, void *buf, lsn_t lsn, into data starting from lsn. Returns 0 if no error. */ int -cdio_read_mode1_sector (const CdIo *cdio, void *data, lsn_t lsn, bool b_form2) +cdio_read_mode1_sector (const CdIo *p_cdio, void *data, lsn_t lsn, + bool b_form2) { uint32_t size = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE ; - char buf[M2RAW_SECTOR_SIZE] = { 0, }; - cdio_assert (cdio != NULL); - cdio_assert (data != NULL); + if (NULL == p_cdio || NULL == data || CDIO_INVALID_LSN == lsn ) + return 0; - if (cdio->op.read_mode1_sector && cdio->op.read_mode1_sector) { - return cdio->op.read_mode1_sector(cdio->env, data, lsn, b_form2); - } else if (cdio->op.lseek && cdio->op.read) { - if (0 > cdio_lseek(cdio, CDIO_CD_FRAMESIZE*lsn, SEEK_SET)) + if (p_cdio->op.read_mode1_sector) { + return p_cdio->op.read_mode1_sector(p_cdio->env, data, lsn, b_form2); + } else if (p_cdio->op.lseek && p_cdio->op.read) { + char buf[CDIO_CD_FRAMESIZE] = { 0, }; + if (0 > cdio_lseek(p_cdio, CDIO_CD_FRAMESIZE*lsn, SEEK_SET)) return -1; - if (0 > cdio_read(cdio, buf, CDIO_CD_FRAMESIZE)) + if (0 > cdio_read(p_cdio, buf, CDIO_CD_FRAMESIZE)) return -1; memcpy (data, buf, size); return 0; @@ -714,8 +935,10 @@ int cdio_read_mode1_sectors (const CdIo *cdio, void *buf, lsn_t lsn, bool b_form2, unsigned int num_sectors) { - cdio_assert (cdio != NULL); - cdio_assert (buf != NULL); + + if (NULL == cdio || NULL == buf || CDIO_INVALID_LSN == lsn ) + return 0; + cdio_assert (cdio->op.read_mode1_sectors != NULL); return cdio->op.read_mode1_sectors (cdio->env, buf, lsn, b_form2, @@ -730,8 +953,9 @@ int cdio_read_mode2_sector (const CdIo *cdio, void *buf, lsn_t lsn, bool b_form2) { - cdio_assert (cdio != NULL); - cdio_assert (buf != NULL); + if (NULL == cdio || NULL == buf || CDIO_INVALID_LSN == lsn ) + return 0; + cdio_assert (cdio->op.read_mode2_sector != NULL || cdio->op.read_mode2_sectors != NULL); @@ -748,8 +972,10 @@ int cdio_read_mode2_sectors (const CdIo *cdio, void *buf, lsn_t lsn, bool b_form2, unsigned int num_sectors) { - cdio_assert (cdio != NULL); - cdio_assert (buf != NULL); + + if (NULL == cdio || NULL == buf || CDIO_INVALID_LSN == lsn ) + return 0; + cdio_assert (cdio->op.read_mode2_sectors != NULL); return cdio->op.read_mode2_sectors (cdio->env, buf, lsn, @@ -787,58 +1013,42 @@ cdio_set_arg (CdIo *cdio, const char key[], const char value[]) CdIo * cdio_open (const char *orig_source_name, driver_id_t driver_id) { - char *source_name; + return cdio_open_am(orig_source_name, driver_id, NULL); +} + +/*! Sets up to read from place specified by source_name and + driver_id. This should be called before using any other routine, + except cdio_init. This will call cdio_init, if that hasn't been + done previously. + + NULL is returned on error. +*/ +CdIo * +cdio_open_am (const char *psz_orig_source, driver_id_t driver_id, + const char *psz_access_mode) +{ + char *psz_source; if (CdIo_last_driver == -1) cdio_init(); - if (NULL == orig_source_name || strlen(orig_source_name)==0) - source_name = cdio_get_default_device(NULL); + if (NULL == psz_orig_source || strlen(psz_orig_source)==0) + psz_source = cdio_get_default_device(NULL); else - source_name = strdup(orig_source_name); + psz_source = strdup(psz_orig_source); - retry: switch (driver_id) { case DRIVER_UNKNOWN: { CdIo *cdio=scan_for_driver(CDIO_MIN_DRIVER, CDIO_MAX_DRIVER, - source_name); - if (cdio != NULL && cdio_is_device(source_name, cdio->driver_id)) { - driver_id = cdio->driver_id; - } else { - struct stat buf; - if (0 != stat(source_name, &buf)) { - return NULL; - } - if (S_ISREG(buf.st_mode)) { - /* FIXME: check to see if is a text file. If so, then - set SOURCE_CUE. */ - int i=strlen(source_name)-strlen("bin"); - if (i > 0 - && ( (source_name)[i] =='n' || (source_name)[i] =='N' ) - && ( (source_name)[i+1] =='r' || (source_name)[i+1] =='R' ) - && ( (source_name)[i+2] =='g' || (source_name)[i+2] =='G' ) ) - driver_id = DRIVER_NRG; - else if (i > 0 - && ( (source_name)[i] =='c' || (source_name)[i] =='C') - && ( (source_name)[i+1] =='u' || (source_name)[i+1] =='U') - && ( (source_name)[i+2] =='e' || (source_name)[i+2] =='E') ) - driver_id = DRIVER_BINCUE; - else - driver_id = DRIVER_BINCUE; - } else { - cdio_destroy(cdio); - return NULL; - } - - } - cdio_destroy(cdio); - goto retry; + psz_source, psz_access_mode); + free(psz_source); + return cdio; } case DRIVER_DEVICE: { /* Scan for a driver. */ - CdIo *ret = cdio_open_cd(source_name); - free(source_name); + CdIo *ret = cdio_open_am_cd(psz_source, psz_access_mode); + free(psz_source); return ret; } break; @@ -850,19 +1060,42 @@ cdio_open (const char *orig_source_name, driver_id_t driver_id) case DRIVER_OSX: case DRIVER_NRG: case DRIVER_BINCUE: + case DRIVER_CDRDAO: if ((*CdIo_all_drivers[driver_id].have_driver)()) { - CdIo *ret = (*CdIo_all_drivers[driver_id].driver_open)(source_name); + CdIo *ret = + (*CdIo_all_drivers[driver_id].driver_open_am)(psz_source, + psz_access_mode); if (ret) ret->driver_id = driver_id; - free(source_name); + free(psz_source); return ret; } } - free(source_name); + free(psz_source); return NULL; } +/*! + Set up CD-ROM for reading. The device_name is + the some sort of device name. + + @return the cdio object for subsequent operations. + NULL on error or there is no driver for a some sort of hardware CD-ROM. +*/ +CdIo * +cdio_open_cd (const char *psz_source) +{ + return cdio_open_am_cd(psz_source, NULL); +} + +/*! + Set up CD-ROM for reading. The device_name is + the some sort of device name. + + @return the cdio object for subsequent operations. + NULL on error or there is no driver for a some sort of hardware CD-ROM. +*/ /* In the future we'll have more complicated code to allow selection of an I/O routine as well as code to find an appropriate default routine among the "registered" routines. Possibly classes too @@ -872,13 +1105,13 @@ cdio_open (const char *orig_source_name, driver_id_t driver_id) For now though, we'll start more simply... */ CdIo * -cdio_open_cd (const char *source_name) +cdio_open_am_cd (const char *psz_source, const char *psz_access_mode) { if (CdIo_last_driver == -1) cdio_init(); /* Scan for a driver. */ return scan_for_driver(CDIO_MIN_DEVICE_DRIVER, CDIO_MAX_DEVICE_DRIVER, - source_name); + psz_source, psz_access_mode); } diff --git a/src/input/vcd/libcdio/cdio/Makefile.am b/src/input/vcd/libcdio/cdio/Makefile.am index 8381d9c31..0910d60e5 100644 --- a/src/input/vcd/libcdio/cdio/Makefile.am +++ b/src/input/vcd/libcdio/cdio/Makefile.am @@ -1,3 +1,19 @@ include $(top_srcdir)/misc/Makefile.common -noinst_HEADERS = cdio.h cd_types.h iso9660.h logging.h sector.h types.h util.h version.h xa.h +noinst_HEADERS = \ + bytesex.h \ + bytesex_asm.h \ + cdio.h \ + cdtext.h \ + cdtext.h \ + cd_types.h \ + ds.h \ + dvd.h \ + iso9660.h \ + logging.h \ + sector.h \ + scsi_mmc.h \ + types.h \ + util.h \ + version.h \ + xa.h diff --git a/src/input/vcd/libcdio/cdio/cd_types.h b/src/input/vcd/libcdio/cdio/cd_types.h index 1117171ae..b03cc9f72 100644 --- a/src/input/vcd/libcdio/cdio/cd_types.h +++ b/src/input/vcd/libcdio/cdio/cd_types.h @@ -1,5 +1,5 @@ /* - $Id: cd_types.h,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: cd_types.h,v 1.3 2005/01/01 02:43:58 rockyb Exp $ Copyright (C) 2003 Rocky Bernstein <rocky@panix.com> Copyright (C) 1996,1997,1998 Gerd Knorr <kraxel@bytesex.org> @@ -67,6 +67,15 @@ extern "C" { */ #define CDIO_FS_3DO 10 +/** + Microsoft X-BOX CD. + */ +#define CDIO_FS_XISO 11 +#define CDIO_FS_UDFX 12 +#define CDIO_FS_UDF 13 +#define CDIO_FS_ISO_UDF 14 + + #define CDIO_FS_MASK 15 /**< Note: this should be 2**n-1 and and greater than the highest CDIO_FS number above */ @@ -82,20 +91,21 @@ extern "C" { * higher-level than the fs-type information above and may be determined * based of the fs type information. */ -#define CDIO_FS_ANAL_XA 16 /**< eXtended Architecture format */ -#define CDIO_FS_ANAL_MULTISESSION 32 /**< CD has multisesion */ -#define CDIO_FS_ANAL_PHOTO_CD 64 /**< Is a Kodak Photo CD */ -#define CDIO_FS_ANAL_HIDDEN_TRACK 128 /**< Hidden track at the +#define CDIO_FS_ANAL_XA 0x0010 /**< eXtended Architecture format */ +#define CDIO_FS_ANAL_MULTISESSION 0x0020 /**< CD has multisesion */ +#define CDIO_FS_ANAL_PHOTO_CD 0x0040 /**< Is a Kodak Photo CD */ +#define CDIO_FS_ANAL_HIDDEN_TRACK 0x0080 /**< Hidden track at the beginning of the CD */ -#define CDIO_FS_ANAL_CDTV 256 -#define CDIO_FS_ANAL_BOOTABLE 512 /**< CD is bootable */ -#define CDIO_FS_ANAL_VIDEOCD 1024 /**< VCD 1.1 */ -#define CDIO_FS_ANAL_ROCKRIDGE 2048 /**< Has Rock Ridge Extensions to +#define CDIO_FS_ANAL_CDTV 0x0100 +#define CDIO_FS_ANAL_BOOTABLE 0x0200 /**< CD is bootable */ +#define CDIO_FS_ANAL_VIDEOCD 0x0400 /**< VCD 1.1 */ +#define CDIO_FS_ANAL_ROCKRIDGE 0x0800 /**< Has Rock Ridge Extensions to ISO 9660 */ -#define CDIO_FS_ANAL_JOLIET 4096 /**< Microsoft Joliet extensions +#define CDIO_FS_ANAL_JOLIET 0x1000 /**< Microsoft Joliet extensions to ISO 9660 */ -#define CDIO_FS_ANAL_SVCD 8192 /**< Super VCD or Choiji Video CD */ -#define CDIO_FS_ANAL_CVD 16384 /**< Choiji Video CD */ +#define CDIO_FS_ANAL_SVCD 0x2000 /**< Super VCD or Choiji Video CD */ +#define CDIO_FS_ANAL_CVD 0x4000 /**< Choiji Video CD */ +#define CDIO_FS_ANAL_XISO 0x8000 /**< XBOX CD */ /** * Pattern which can be used by cdio_get_devices to specify matching @@ -117,6 +127,8 @@ typedef struct char iso_label[33]; /**< This is 32 + 1 for null byte at the end in formatting the string */ unsigned int isofs_size; + uint8_t UDFVerMinor; /**< For UDF filesystems only */ + uint8_t UDFVerMajor; /**< For UDF filesystems only */ } cdio_iso_analysis_t; /** diff --git a/src/input/vcd/libcdio/cdio/cdio.h b/src/input/vcd/libcdio/cdio/cdio.h index a9fa4b02e..e0d8ae311 100644 --- a/src/input/vcd/libcdio/cdio/cdio.h +++ b/src/input/vcd/libcdio/cdio/cdio.h @@ -1,5 +1,5 @@ /* -*- c -*- - $Id: cdio.h,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: cdio.h,v 1.3 2005/01/01 02:43:58 rockyb Exp $ Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> @@ -30,7 +30,7 @@ /** Application Interface or Protocol version number. If the public * interface changes, we increase this number. */ -#define CDIO_API_VERSION 1 +#define CDIO_API_VERSION 2 #include <cdio/version.h> @@ -44,26 +44,43 @@ #include <cdio/types.h> #include <cdio/sector.h> -/* Flags specifying the category of device to open or is opened. */ +/**! Flags specifying the category of device to open or is opened. */ #define CDIO_SRC_IS_DISK_IMAGE_MASK 0x0001 /**< Read source is a CD image. */ #define CDIO_SRC_IS_DEVICE_MASK 0x0002 /**< Read source is a CD device. */ -#define CDIO_SRC_IS_SCSI_MASK 0x0004 +#define CDIO_SRC_IS_SCSI_MASK 0x0004 /**< Read source SCSI device. */ #define CDIO_SRC_IS_NATIVE_MASK 0x0008 #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ - /** This is an opaque structure. */ +/*! Size of fields returned by an INQUIRY command */ +#define CDIO_MMC_HW_VENDOR_LEN 8 /**< length of vendor field */ +#define CDIO_MMC_HW_MODEL_LEN 16 /**< length of model field */ +#define CDIO_MMC_HW_REVISION_LEN 4 /**< length of revision field */ + + /*! \brief Structure to return CD vendor, model, and revision-level + strings obtained via the INQUIRY command */ + typedef struct cdio_hwinfo + { + char psz_vendor [CDIO_MMC_HW_VENDOR_LEN+1]; + char psz_model [CDIO_MMC_HW_MODEL_LEN+1]; + char psz_revision[CDIO_MMC_HW_REVISION_LEN+1]; + } cdio_hwinfo_t; + + /** This is an opaque structure for the CD object. */ typedef struct _CdIo CdIo; + /** This is an opaque structure for the CD-Text object. */ + typedef struct cdtext cdtext_t; + /** The driver_id_t enumerations may be used to tag a specific driver * that is opened or is desired to be opened. Note that this is * different than what is available on a given host. * * Order is a little significant since the order is used in scans. - * We have to start with UNKNOWN and devices should come before + * We have to start with DRIVER_UNKNOWN and devices should come before * disk-image readers. By putting something towards the top (a lower * enumeration number), in an iterative scan we prefer that to * something with a higher enumeration number. @@ -72,20 +89,33 @@ extern "C" { * */ typedef enum { - DRIVER_UNKNOWN, + DRIVER_UNKNOWN, /**< Used as input when we don't care what kind + of driver to use. */ DRIVER_BSDI, /**< BSDI driver */ - DRIVER_FREEBSD, /**< FreeBSD driver */ + DRIVER_FREEBSD, /**< FreeBSD driver - includes CAM and ioctl access */ DRIVER_LINUX, /**< GNU/Linux Driver */ DRIVER_SOLARIS, /**< Sun Solaris Driver */ DRIVER_OSX, /**< Apple OSX Driver */ - DRIVER_WIN32, /**< Microsoft Windows Driver */ - DRIVER_BINCUE, /**< BIN/CUE format CD image. This is listed before NRG, - to make the code prefer BINCUE over NRG when both - exist. */ + DRIVER_WIN32, /**< Microsoft Windows Driver. Includes ASPI and + ioctl acces. */ + DRIVER_CDRDAO, /**< cdrdao format CD image. This is listed + before BIN/CUE, to make the code prefer cdrdao + over BIN/CUE when both exist. */ + DRIVER_BINCUE, /**< CDRWIN BIN/CUE format CD image. This is + listed before NRG, to make the code prefer + BIN/CUE over NRG when both exist. */ DRIVER_NRG, /**< Nero NRG format CD image. */ DRIVER_DEVICE /**< Is really a set of the above; should come last */ } driver_id_t; + /** There will generally be only one hardware for a given + build/platform from the list above. You can use the variable + below to determine which you've got. If the build doesn't make an + hardware driver, then the value will be DRIVER_UNKNOWN. + */ + extern const driver_id_t cdio_os_driver; + + /** Make sure what's listed for CDIO_MIN_DRIVER is the last enumeration in driver_id_t. Since we have a bogus (but useful) 0th entry above we don't have to add one. @@ -106,51 +136,77 @@ extern "C" { TRACK_FORMAT_ERROR /**< Dunno what is, or some other error. */ } track_format_t; + extern const char *discmode2str[]; + /*! Printable tags for track_format_t enumeration. */ extern const char *track_format2str[6]; /*! Eject media in CD drive if there is a routine to do so. - Return 0 if success and 1 for failure, and 2 if no routine. - If the CD is ejected *obj is freed and obj set to NULL. + + @param p_cdio the CD object to be acted upon. + @return 0 if success and 1 for failure, and 2 if no routine. + If the CD is ejected *p_cdio is freed and p_cdio set to NULL. */ - int cdio_eject_media (CdIo **obj); + int cdio_eject_media (CdIo **p_cdio); /*! - Free any resources associated with obj. + Free any resources associated with p_cdio. Call this when done using p_cdio + and using CD reading/control operations. + + @param p_cdio the CD object to eliminated. */ - void cdio_destroy (CdIo *obj); + void cdio_destroy (CdIo *p_cdio); /*! Free device list returned by cdio_get_devices or cdio_get_devices_with_cap. + + @param device_list list returned by cdio_get_devices or + cdio_get_devices_with_cap + + @see cdio_get_devices, cdio_get_devices_with_cap + */ void cdio_free_device_list (char * device_list[]); /*! - Return the value associatied with key. NULL is returned if obj is NULL + Get the value associatied with key. + + @param p_cdio the CD object queried + @param key the key to retrieve + @return the value associatd with "key" or NULL if p_cdio is NULL or "key" does not exist. */ - const char * cdio_get_arg (const CdIo *obj, const char key[]); + const char * cdio_get_arg (const CdIo *p_cdio, const char key[]); + + /*! + Get CD-Text information for a CdIo object. + + @param p_cdio the CD object that may contain CD-Text information. + @param i_track track for which we are requesting CD-Text information. + @return the CD-Text object or NULL if obj is NULL + or CD-Text information does not exist. + + If i_track is 0 or CDIO_CDROM_LEADOUT_TRACK the track returned + is the information assocated with the CD. + */ + const cdtext_t *cdio_get_cdtext (CdIo *p_cdio, track_t i_track); /*! - Return an array of device names in search_devices that have at - least the capabilities listed by cap. If search_devices is NULL, - then we'll search all possible CD drives. + Get the default CD device. + if p_cdio is NULL (we haven't initialized a specific device driver), + then find a suitable one and return the default device for that. - If "any" is set false then every capability listed in the extended - portion of capabilities (i.e. not the basic filesystem) must be - satisified. If "any" is set true, then if any of the capabilities - matches, we call that a success. + @param p_cdio the CD object queried + @return a string containing the default CD device or NULL is + if we couldn't get a default device. - To find a CD-drive of any type, use the mask CDIO_FS_MATCH_ALL. - - NULL is returned if we couldn't get a default device. - It is also possible to return a non NULL but after dereferencing the - the value is NULL. This also means nothing was found. + In some situations of drivers or OS's we can't find a CD device if + there is no media in it and it is possible for this routine to return + NULL even though there may be a hardware CD-ROM. */ - char ** cdio_get_devices_with_cap (char* search_devices[], - cdio_fs_anal_t capabilities, bool any); + char * cdio_get_default_device (const CdIo *p_cdio); /*! Return an array of device names. If you want a specific devices for a driver, give that device. If you want hardware @@ -158,49 +214,153 @@ extern "C" { image drivers and hardware drivers give DRIVER_UNKNOWN. NULL is returned if we couldn't return a list of devices. + + In some situations of drivers or OS's we can't find a CD device if + there is no media in it and it is possible for this routine to return + NULL even though there may be a hardware CD-ROM. */ - char ** cdio_get_devices (driver_id_t driver); + char ** cdio_get_devices (driver_id_t driver_id); /*! - Return a string containing the default CD device. - if obj is NULL (we haven't initialized a specific device driver), - then find a suitable one and return the default device for that. + Get an array of device names in search_devices that have at least + the capabilities listed by the capabities parameter. If + search_devices is NULL, then we'll search all possible CD drives. - NULL is returned if we couldn't get a default device. + If "b_any" is set false then every capability listed in the + extended portion of capabilities (i.e. not the basic filesystem) + must be satisified. If "any" is set true, then if any of the + capabilities matches, we call that a success. + + To find a CD-drive of any type, use the mask CDIO_FS_MATCH_ALL. + + @return the array of device names or NULL if we couldn't get a + default device. It is also possible to return a non NULL but + after dereferencing the the value is NULL. This also means nothing + was found. */ - char * cdio_get_default_device (const CdIo *obj); + char ** cdio_get_devices_with_cap (char* ppsz_search_devices[], + cdio_fs_anal_t capabilities, bool b_any); /*! - Return the media catalog number (MCN) from the CD or NULL if there - is none or we don't have the ability to get it. + Like cdio_get_devices_with_cap but we return the driver we found + as well. This is because often one wants to search for kind of drive + and then *open* it afterwards. Giving the driver back facilitates this, + and speeds things up for libcdio as well. + */ + char ** cdio_get_devices_with_cap_ret (/*out*/ char* ppsz_search_devices[], + cdio_fs_anal_t capabilities, + bool b_any, + /*out*/ driver_id_t *p_driver_id); + + /*! Like cdio_get_devices, but we may change the p_driver_id if we + were given DRIVER_DEVICE or DRIVER_UNKNOWN. This is because + often one wants to get a drive name and then *open* it + afterwards. Giving the driver back facilitates this, and speeds + things up for libcdio as well. + */ + + char ** cdio_get_devices_ret (/*in/out*/ driver_id_t *p_driver_id); - Note: string is malloc'd so caller has to free() the returned - string when done with it. + /*! + Get disc mode - the kind of CD (CD-DA, CD-ROM mode 1, CD-MIXED, etc. + that we've got. The notion of "CD" is extended a little to include + DVD's. + */ + discmode_t cdio_get_discmode (CdIo *p_cdio); + + /*! + Get the what kind of device we've got. + + @param p_cdio the CD object queried + @param p_read_cap pointer to return read capabilities + @param p_write_cap pointer to return write capabilities + @param p_misc_cap pointer to return miscellaneous other capabilities + + In some situations of drivers or OS's we can't find a CD device if + there is no media in it and it is possible for this routine to return + NULL even though there may be a hardware CD-ROM. + */ + void cdio_get_drive_cap (const CdIo *p_cdio, + cdio_drive_read_cap_t *p_read_cap, + cdio_drive_write_cap_t *p_write_cap, + cdio_drive_misc_cap_t *p_misc_cap); + + /*! + Get the drive capabilities for a specified device. + + @return a list of device capabilities. + + In some situations of drivers or OS's we can't find a CD device if + there is no media in it and it is possible for this routine to return + NULL even though there may be a hardware CD-ROM. */ - char *cdio_get_mcn (const CdIo *obj); + void cdio_get_drive_cap_dev (const char *device, + cdio_drive_read_cap_t *p_read_cap, + cdio_drive_write_cap_t *p_write_cap, + cdio_drive_misc_cap_t *p_misc_cap); /*! - Return a string containing the name of the driver in use. + Get a string containing the name of the driver in use. + + @return a string with driver name or NULL if CdIo is NULL (we + haven't initialized a specific device. + */ + const char * cdio_get_driver_name (const CdIo *p_cdio); + + /*! + Get the driver id. if CdIo is NULL (we haven't initialized a specific device driver), - then return NULL. + then return DRIVER_UNKNOWN. + + @return the driver id.. */ - const char * cdio_get_driver_name (const CdIo *obj); + driver_id_t cdio_get_driver_id (const CdIo *p_cdio); /*! - Return the number of the first track. - CDIO_INVALID_TRACK is returned on error. + Get the number of the first track. + + @return the track number or CDIO_INVALID_TRACK + on error. */ - track_t cdio_get_first_track_num(const CdIo *obj); + track_t cdio_get_first_track_num(const CdIo *p_cdio); + /*! + Get the CD-ROM hardware info via a SCSI MMC INQUIRY command. + False is returned if we had an error getting the information. + */ + bool cdio_get_hwinfo ( const CdIo *p_cdio, + /* out*/ cdio_hwinfo_t *p_hw_info ); + + + /*! + Return the Joliet level recognized for p_cdio. + */ + uint8_t cdio_get_joliet_level(const CdIo *p_cdio); + /*! - Return a string containing the default CD device if none is specified. + Get the media catalog number (MCN) from the CD. + + @return the media catalog number r NULL if there is none or we + don't have the ability to get it. + + Note: string is malloc'd so caller has to free() the returned + string when done with it. + */ - track_t cdio_get_num_tracks (const CdIo *obj); + char * cdio_get_mcn (const CdIo *p_cdio); + + /*! + Get the number of tracks on the CD. + + @return the number of tracks, or CDIO_INVALID_TRACK if there is + an error. + */ + track_t cdio_get_num_tracks (const CdIo *p_cdio); /*! Get the format (audio, mode2, mode1) of track. */ - track_format_t cdio_get_track_format(const CdIo *obj, track_t track_num); + track_format_t cdio_get_track_format(const CdIo *p_cdio, track_t i_track); /*! Return true if we have XA data (green, mode2 form1) or @@ -210,110 +370,178 @@ extern "C" { FIXME: there's gotta be a better design for this and get_track_format? */ - bool cdio_get_track_green(const CdIo *obj, track_t track_num); + bool cdio_get_track_green(const CdIo *p_cdio, track_t i_track); /*! - Return the starting LBA for track number - track_num in obj. Tracks numbers start at 1. + Get the starting LBA for track number + i_track in p_cdio. Track numbers usually start at something + greater than 0, usually 1. + The "leadout" track is specified either by - using track_num LEADOUT_TRACK or the total tracks+1. - CDIO_INVALID_LBA is returned on error. + using i_track CDIO_CDROM_LEADOUT_TRACK or the total tracks+1. + + @param p_cdio object to get information from + @param i_track the track number we want the LSN for + @return the starting LBA or CDIO_INVALID_LBA on error. */ - lba_t cdio_get_track_lba(const CdIo *obj, track_t track_num); + lba_t cdio_get_track_lba(const CdIo *p_cdio, track_t i_track); /*! - Return the starting LSN for track number - track_num in obj. Tracks numbers start at 1. + Return the starting MSF (minutes/secs/frames) for track number + i_track in p_cdio. Track numbers usually start at something + greater than 0, usually 1. + The "leadout" track is specified either by - using track_num LEADOUT_TRACK or the total tracks+1. - CDIO_INVALID_LBA is returned on error. + using i_track CDIO_CDROM_LEADOUT_TRACK or the total tracks+1. + + @param p_cdio object to get information from + @param i_track the track number we want the LSN for + @return the starting LSN or CDIO_INVALID_LSN on error. */ - lsn_t cdio_get_track_lsn(const CdIo *obj, track_t track_num); + lsn_t cdio_get_track_lsn(const CdIo *p_cdio, track_t i_track); /*! Return the starting MSF (minutes/secs/frames) for track number - track_num in obj. Track numbers start at 1. + i_track in p_cdio. Track numbers usually start at something + greater than 0, usually 1. + The "leadout" track is specified either by - using track_num LEADOUT_TRACK or the total tracks+1. - False is returned if there is no track entry. + using i_track CDIO_CDROM_LEADOUT_TRACK or the total tracks+1. + + @return true if things worked or false if there is no track entry. */ - bool cdio_get_track_msf(const CdIo *obj, track_t track_num, + bool cdio_get_track_msf(const CdIo *p_cdio, track_t i_track, /*out*/ msf_t *msf); /*! - Return the number of sectors between this track an the next. This + Get the number of sectors between this track an the next. This includes any pregap sectors before the start of the next track. - Tracks start at 1. - 0 is returned if there is an error. + Track numbers usually start at something + greater than 0, usually 1. + + @return the number of sectors or 0 if there is an error. */ - unsigned int cdio_get_track_sec_count(const CdIo *obj, track_t track_num); + unsigned int cdio_get_track_sec_count(const CdIo *p_cdio, track_t i_track); /*! - lseek - reposition read/write file offset - Returns (off_t) -1 on error. + Reposition read offset Similar to (if not the same as) libc's lseek() + + @param p_cdio object to get information from + @param offset amount to seek + @param whence like corresponding parameter in libc's lseek, e.g. + SEEK_SET or SEEK_END. + @return (off_t) -1 on error. */ - off_t cdio_lseek(const CdIo *obj, off_t offset, int whence); + off_t cdio_lseek(const CdIo *p_cdio, off_t offset, int whence); /*! Reads into buf the next size bytes. - Returns -1 on error. Similar to (if not the same as) libc's read() + + @return (ssize_t) -1 on error. */ - ssize_t cdio_read(const CdIo *obj, void *buf, size_t size); + ssize_t cdio_read(const CdIo *p_cdio, void *buf, size_t size); /*! - Reads a audio sector from cd device into data starting - from lsn. Returns 0 if no error. + Read an audio sector + + @param p_cdio object to read from + @param buf place to read data into + @param lsn sector to read + + @return 0 if no error, nonzero otherwise. */ - int cdio_read_audio_sector (const CdIo *obj, void *buf, lsn_t lsn); + int cdio_read_audio_sector (const CdIo *p_cdio, void *buf, lsn_t lsn); /*! - Reads a audio sector from cd device into data starting - from lsn. Returns 0 if no error. + Reads audio sectors + + @param p_cdio object to read from + @param buf place to read data into + @param lsn sector to read + @param i_sectors number of sectors to read + + @return 0 if no error, nonzero otherwise. */ - int cdio_read_audio_sectors (const CdIo *obj, void *buf, lsn_t lsn, - unsigned int nblocks); + int cdio_read_audio_sectors (const CdIo *p_cdio, void *buf, lsn_t lsn, + unsigned int i_sectors); /*! - Reads a single mode1 sector from cd device into data starting - from lsn. Returns 0 if no error. + Reads a mode1 sector + + @param p_cdio object to read from + @param buf place to read data into + @param lsn sector to read + @param b_form2 true for reading mode1 form2 sectors or false for + mode1 form1 sectors. + + @return 0 if no error, nonzero otherwise. */ - int cdio_read_mode1_sector (const CdIo *obj, void *buf, lsn_t lsn, + int cdio_read_mode1_sector (const CdIo *p_cdio, void *buf, lsn_t lsn, bool b_form2); /*! - Reads nblocks of mode1 sectors from cd device into data starting - from lsn. Returns 0 if no error. + Reads mode1 sectors + + @param p_cdio object to read from + @param buf place to read data into + @param lsn sector to read + @param b_form2 true for reading mode1 form2 sectors or false for + mode1 form1 sectors. + @param i_sectors number of sectors to read + + @return 0 if no error, nonzero otherwise. */ - int cdio_read_mode1_sectors (const CdIo *obj, void *buf, lsn_t lsn, - bool b_form2, unsigned int num_sectors); + int cdio_read_mode1_sectors (const CdIo *p_cdio, void *buf, lsn_t lsn, + bool b_form2, unsigned int i_sectors); /*! - Reads a single mode2 sector from cd device into data starting - from lsn. Returns 0 if no error. + Reads a mode1 sector + + @param p_cdio object to read from + @param buf place to read data into + @param lsn sector to read + @param b_form2 true for reading mode1 form2 sectors or false for + mode1 form1 sectors. + + @return 0 if no error, nonzero otherwise. */ - int cdio_read_mode2_sector (const CdIo *obj, void *buf, lsn_t lsn, + int cdio_read_mode2_sector (const CdIo *p_cdio, void *buf, lsn_t lsn, bool b_form2); /*! - Reads nblocks of mode2 sectors from cd device into data starting - from lsn. - Returns 0 if no error. + Reads mode2 sectors + + @param p_cdio object to read from + @param buf place to read data into + @param lsn sector to read + @param b_form2 true for reading mode1 form2 sectors or false for + mode1 form1 sectors. + @param i_sectors number of sectors to read + + @return 0 if no error, nonzero otherwise. */ - int cdio_read_mode2_sectors (const CdIo *obj, void *buf, lsn_t lsn, - bool b_form2, unsigned int num_sectors); + int cdio_read_mode2_sectors (const CdIo *p_cdio, void *buf, lsn_t lsn, + bool b_form2, unsigned int i_sectors); /*! - Set the arg "key" with "value" in the source device. - 0 is returned if no error was found, and nonzero if there as an error. + Set the arg "key" with "value" in "obj". + + @param p_cdio the CD object to set + @param key the key to set + @param value the value to assocaiate with key + @return 0 if no error was found, and nonzero otherwise. */ - int cdio_set_arg (CdIo *obj, const char key[], const char value[]); + int cdio_set_arg (CdIo *p_cdio, const char key[], const char value[]); /*! - Return the size of the CD in logical block address (LBA) units. + Get the size of the CD in logical block address (LBA) units. + + @param p_cdio the CD object queried + @return the size */ - uint32_t cdio_stat_size (const CdIo *obj); + uint32_t cdio_stat_size (const CdIo *p_cdio); /*! Initialize CD Reading and control routines. Should be called first. @@ -347,72 +575,148 @@ extern "C" { /*! True if BIN/CUE driver is available. */ bool cdio_have_bincue (void); + /*! True if cdrdao CDRDAO driver is available. */ + bool cdio_have_cdrdao (void); + /*! Like cdio_have_xxx but uses an enumeration instead. */ bool cdio_have_driver (driver_id_t driver_id); - /*! Return a string decribing driver_id. */ + /*! + Get a string decribing driver_id. + + @param driver_id the driver you want the description for + @return a sring of driver description + */ const char *cdio_driver_describe (driver_id_t driver_id); /*! Sets up to read from place specified by source_name and - driver_id This should be called before using any other routine, - except cdio_init. This will call cdio_init, if that hasn't been - done previously. to call one of the specific cdio_open_xxx - routines. + driver_id. This or cdio_open_* should be called before using any + other routine, except cdio_init. This will call cdio_init, if + that hasn't been done previously. to call one of the specific + cdio_open_xxx routines. - NULL is returned on error. + @return the cdio object or NULL on error or no device. */ CdIo * cdio_open (const char *source_name, driver_id_t driver_id); + /*! Sets up to read from place specified by source_name, driver_id + and access mode. This or cdio_open should be called before using + any other routine, except cdio_init. This will call cdio_init, if + that hasn't been done previously. to call one of the specific + cdio_open_xxx routines. + + @return the cdio object or NULL on error or no device. + */ + CdIo * cdio_open_am (const char *psz_source_name, + driver_id_t driver_id, const char *psz_access_mode); + + /*! Set up BIN/CUE CD disk-image for reading. Source is the .bin or + .cue file + + @return the cdio object or NULL on error or no device. + */ + CdIo * cdio_open_bincue (const char *psz_cue_name); + /*! Set up BIN/CUE CD disk-image for reading. Source is the .bin or .cue file - NULL is returned on error. + @return the cdio object or NULL on error or no device.. + */ + CdIo * cdio_open_am_bincue (const char *psz_cue_name, + const char *psz_access_mode); + + /*! Set up cdrdao CD disk-image for reading. Source is the .toc file + + @return the cdio object or NULL on error or no device. + */ + CdIo * cdio_open_cdrdao (const char *psz_toc_name); + + /*! Set up cdrdao CD disk-image for reading. Source is the .toc file + + @return the cdio object or NULL on error or no device.. */ - CdIo * cdio_open_bincue (const char *bin_name); + CdIo * cdio_open_am_cdrdao (const char *psz_toc_name, + const char *psz_access_mode); /*! Return a string containing the default CUE file that would be used when none is specified. - NULL is returned on error or there is no device. + @return the cdio object or NULL on error or no device. */ char * cdio_get_default_device_bincue(void); char **cdio_get_devices_bincue(void); + /*! Return a string containing the default CUE file that would + be used when none is specified. + + NULL is returned on error or there is no device. + */ + char * cdio_get_default_device_cdrdao(void); + + char **cdio_get_devices_cdrdao(void); + /*! Set up CD-ROM for reading. The device_name is the some sort of device name. - NULL is returned on error. + @return the cdio object for subsequent operations. + NULL on error or there is no driver for a some sort of hardware CD-ROM. */ CdIo * cdio_open_cd (const char *device_name); - /*! cdrao BIN/CUE CD disk-image routines. Source is the .cue file + /*! Set up CD-ROM for reading. The device_name is + the some sort of device name. + + @return the cdio object for subsequent operations. + NULL on error or there is no driver for a some sort of hardware CD-ROM. + */ + CdIo * cdio_open_am_cd (const char *psz_device, + const char *psz_access_mode); + + /*! CDRWIN BIN/CUE CD disc-image routines. Source is the .cue file - NULL is returned on error. + @return the cdio object for subsequent operations. + NULL on error. */ CdIo * cdio_open_cue (const char *cue_name); /*! Set up CD-ROM for reading using the BSDI driver. The device_name is the some sort of device name. - NULL is returned on error or there is no BSDI driver. + @return the cdio object for subsequent operations. + NULL on error or there is no BSDI driver. @see cdio_open */ - CdIo * cdio_open_bsdi (const char *source_name); + CdIo * cdio_open_bsdi (const char *psz_source_name); + + /*! Set up CD-ROM for reading using the BSDI driver. The device_name is + the some sort of device name. + + @return the cdio object for subsequent operations. + NULL on error or there is no BSDI driver. + + @see cdio_open + */ + CdIo * cdio_open_am_bsdi (const char *psz_source_name, + const char *psz_access_mode); /*! Return a string containing the default device name that the BSDI driver would use when none is specified. - NULL is returned on error or there is no CD-ROM device. + @return the cdio object for subsequent operations. + NULL on error or there is no BSDI driver. - @see cdio_open_cd - @see cdio_open + @see cdio_open_cd, cdio_open */ char * cdio_get_default_device_bsdi(void); /*! Return a list of all of the CD-ROM devices that the BSDI driver can find. + + In some situations of drivers or OS's we can't find a CD device if + there is no media in it and it is possible for this routine to return + NULL even though there may be a hardware CD-ROM. */ char **cdio_get_devices_bsdi(void); @@ -421,10 +725,19 @@ extern "C" { NULL is returned on error or there is no FreeBSD driver. - @see cdio_open_cd - @see cdio_open + @see cdio_open_cd, cdio_open */ - CdIo * cdio_open_freebsd (const char *source_name); + CdIo * cdio_open_freebsd (const char *paz_source_name); + + /*! Set up CD-ROM for reading using the FreeBSD driver. The device_name is + the some sort of device name. + + NULL is returned on error or there is no FreeBSD driver. + + @see cdio_open_cd, cdio_open + */ + CdIo * cdio_open_am_freebsd (const char *psz_source_name, + const char *psz_access_mode); /*! Return a string containing the default device name that the FreeBSD driver would use when none is specified. @@ -441,18 +754,35 @@ extern "C" { /*! Set up CD-ROM for reading using the GNU/Linux driver. The device_name is the some sort of device name. - NULL is returned on error or there is no GNU/Linux driver. + @return the cdio object for subsequent operations. + NULL on error or there is no GNU/Linux driver. + + In some situations of drivers or OS's we can't find a CD device if + there is no media in it and it is possible for this routine to return + NULL even though there may be a hardware CD-ROM. */ CdIo * cdio_open_linux (const char *source_name); + /*! Set up CD-ROM for reading using the GNU/Linux driver. The + device_name is the some sort of device name. + + @return the cdio object for subsequent operations. + NULL on error or there is no GNU/Linux driver. + */ + CdIo * cdio_open_am_linux (const char *source_name, + const char *access_mode); + /*! Return a string containing the default device name that the GNU/Linux driver would use when none is specified. A scan is made for CD-ROM drives with CDs in them. NULL is returned on error or there is no CD-ROM device. - @see cdio_open_cd - @see cdio_open + In some situations of drivers or OS's we can't find a CD device if + there is no media in it and it is possible for this routine to return + NULL even though there may be a hardware CD-ROM. + + @see cdio_open_cd, cdio_open */ char * cdio_get_default_device_linux(void); @@ -464,18 +794,31 @@ extern "C" { /*! Set up CD-ROM for reading using the Sun Solaris driver. The device_name is the some sort of device name. - NULL is returned on error or there is no Solaris driver. + @return the cdio object for subsequent operations. + NULL on error or there is no Solaris driver. */ CdIo * cdio_open_solaris (const char *source_name); + /*! Set up CD-ROM for reading using the Sun Solaris driver. The + device_name is the some sort of device name. + + @return the cdio object for subsequent operations. + NULL on error or there is no Solaris driver. + */ + CdIo * cdio_open_am_solaris (const char *psz_source_name, + const char *psz_access_mode); + /*! Return a string containing the default device name that the Solaris driver would use when none is specified. A scan is made for CD-ROM drives with CDs in them. NULL is returned on error or there is no CD-ROM device. - @see cdio_open_cd - @see cdio_open + In some situations of drivers or OS's we can't find a CD device if + there is no media in it and it is possible for this routine to return + NULL even though there may be a hardware CD-ROM. + + @see cdio_open_cd, cdio_open */ char * cdio_get_default_device_solaris(void); @@ -489,16 +832,31 @@ extern "C" { NULL is returned on error or there is no OSX driver. - @see cdio_open_cd - @see cdio_open + In some situations of drivers or OS's we can't find a CD device if + there is no media in it and it is possible for this routine to return + NULL even though there may be a hardware CD-ROM. + + @see cdio_open_cd, cdio_open */ - CdIo * cdio_open_osx (const char *source_name); + CdIo * cdio_open_osx (const char *psz_source_name); + + /*! Set up CD-ROM for reading using the Apple OSX driver. The + device_name is the some sort of device name. + + NULL is returned on error or there is no OSX driver. + + @see cdio_open_cd, cdio_open + */ + CdIo * cdio_open_am_osx (const char *psz_source_name, + const char *psz_access_mode); /*! Return a string containing the default device name that the OSX driver would use when none is specified. A scan is made for CD-ROM drives with CDs in them. - NULL is returned on error or there is no CD-ROM device + In some situations of drivers or OS's we can't find a CD device if + there is no media in it and it is possible for this routine to return + NULL even though there may be a hardware CD-ROM. */ char * cdio_get_default_device_osx(void); @@ -510,18 +868,29 @@ extern "C" { /*! Set up CD-ROM for reading using the Microsoft Windows driver. The device_name is the some sort of device name. - NULL is returned on error or there is no Microsof Windows driver. + In some situations of drivers or OS's we can't find a CD device if + there is no media in it and it is possible for this routine to return + NULL even though there may be a hardware CD-ROM. */ CdIo * cdio_open_win32 (const char *source_name); + /*! Set up CD-ROM for reading using the Microsoft Windows driver. The + device_name is the some sort of device name. + + NULL is returned on error or there is no Microsof Windows driver. + */ + CdIo * cdio_open_am_win32 (const char *psz_source_name, + const char *psz_access_mode); + /*! Return a string containing the default device name that the Win32 driver would use when none is specified. A scan is made for CD-ROM drives with CDs in them. - NULL is returned on error or there is no CD-ROM device. + In some situations of drivers or OS's we can't find a CD device if + there is no media in it and it is possible for this routine to return + NULL even though there may be a hardware CD-ROM. - @see cdio_open_cd - @see cdio_open + @see cdio_open_cd, cdio_open */ char * cdio_get_default_device_win32(void); @@ -530,10 +899,18 @@ extern "C" { /*! Set up CD-ROM for reading using the Nero driver. The device_name is the some sort of device name. - NULL is returned on error or there is no Nero driver. + @return true on success; NULL on error or there is no Nero driver. */ CdIo * cdio_open_nrg (const char *source_name); + /*! Set up CD-ROM for reading using the Nero driver. The + device_name is the some sort of device name. + + @return true on success; NULL on error or there is no Nero driver. + */ + CdIo * cdio_open_am_nrg (const char *psz_source_name, + const char *psz_access_mode); + /*! Return a string containing the default device name that the NRG driver would use when none is specified. A scan is made for NRG disk images in the current directory.. @@ -544,18 +921,50 @@ extern "C" { char **cdio_get_devices_nrg(void); - /*! Return corresponding BIN file if cue_name is a cue file or NULL - if not a CUE file. + /*! + + Determine if bin_name is the bin file part of a CDRWIN CD disk image. + + @param bin_name location of presumed CDRWIN bin image file. + @return the corresponding CUE file if bin_name is a BIN file or + NULL if not a BIN file. + */ + char *cdio_is_binfile(const char *bin_name); + + /*! + Determine if cue_name is the cue sheet for a CDRWIN CD disk image. + + @return corresponding BIN file if cue_name is a CDRWIN cue file or + NULL if not a CUE file. */ char *cdio_is_cuefile(const char *cue_name); - /*! Return corresponding CUE file if bin_name is a fin file or NULL - if not a BIN file. NOTE: when we handle TOC something will have to - change here.... + /*! + Determine if psg_nrg is a Nero CD disk image. + + @param psz_nrg location of presumed NRG image file. + @return true if psz_nrg is a Nero NRG image or false + if not a NRG image. */ - char *cdio_is_binfile(const char *bin_name); + bool cdio_is_nrg(const char *psz_nrg); - /*! Return true if source name is a device. + /*! + Determine if psg_toc is a TOC file for a cdrdao CD disk image. + + @param psz_toc location of presumed TOC image file. + @return true if toc_name is a cdrdao TOC file or false + if not a TOC file. + */ + bool cdio_is_tocfile(const char *psz_toc); + + /*! + Determine if source_name refers to a real hardware CD-ROM. + + @param source_name location name of object + @param driver_id driver for reading object. Use DRIVER_UNKNOWN if you + don't know what driver to use. + @return true if source_name is a device; If false is returned we + could have a CD disk image. */ bool cdio_is_device(const char *source_name, driver_id_t driver_id); diff --git a/src/input/vcd/libcdio/cdio/cdtext.h b/src/input/vcd/libcdio/cdio/cdtext.h new file mode 100644 index 000000000..4b397a3ff --- /dev/null +++ b/src/input/vcd/libcdio/cdio/cdtext.h @@ -0,0 +1,108 @@ +/* + $Id: cdtext.h,v 1.1 2005/01/01 02:43:58 rockyb Exp $ + + Copyright (C) 2004 Rocky Bernstein <rocky@panix.com> + adapted from cuetools + Copyright (C) 2003 Svend Sanjay Sorensen <ssorensen@fastmail.fm> + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/*! + * \file cdtext.h + * \brief Header CD-Text information +*/ + + +#ifndef __CDIO_CDTEXT_H__ +#define __CDIO_CDTEXT_H__ + +#include <cdio/cdio.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define MAX_CDTEXT_FIELDS 13 + + /*! \brief structure for holding CD-Text information + + @see cdtext_init, cdtext_destroy, cdtext_get, and cdtext_set. + */ + struct cdtext { + char *field[MAX_CDTEXT_FIELDS]; + }; + + /*! \brief A list of all of the CD-Text fields */ + typedef enum { + CDTEXT_ARRANGER = 0, /**< name(s) of the arranger(s) */ + CDTEXT_COMPOSER = 1, /**< name(s) of the composer(s) */ + CDTEXT_DISCID = 2, /**< disc identification information */ + CDTEXT_GENRE = 3, /**< genre identification and genre information */ + CDTEXT_MESSAGE = 4, /**< ISRC code of each track */ + CDTEXT_ISRC = 5, /**< message(s) from the content provider or artist */ + CDTEXT_PERFORMER = 6, /**< name(s) of the performer(s) */ + CDTEXT_SIZE_INFO = 7, /**< size information of the block */ + CDTEXT_SONGWRITER = 8, /**< name(s) of the songwriter(s) */ + CDTEXT_TITLE = 9, /**< title of album name or track titles */ + CDTEXT_TOC_INFO = 10, /**< table of contents information */ + CDTEXT_TOC_INFO2 = 11, /**< second table of contents information */ + CDTEXT_UPC_EAN = 12, + CDTEXT_INVALID = MAX_CDTEXT_FIELDS + } cdtext_field_t; + + /*! Return string representation of the enum values above */ + const char *cdtext_field2str (cdtext_field_t i); + + /*! Initialize a new cdtext structure. + When the structure is no longer needed, release the + resources using cdtext_delete. + */ + void cdtext_init (cdtext_t *cdtext); + + /*! Free memory assocated with cdtext*/ + void cdtext_destroy (cdtext_t *cdtext); + + /*! returns the string associated with the given field. NULL is + returned if key is CDTEXT_INVALID or the field is not set. + + @see cdio_get_cdtext to retrieve the cdtext structure used as + input here. + */ + const char *cdtext_get (cdtext_field_t key, const cdtext_t *cdtext); + + /*! + returns enum of keyword if key is a CD-Text keyword, + returns MAX_CDTEXT_FIELDS non-zero otherwise. + */ + cdtext_field_t cdtext_is_keyword (const char *key); + + /*! + sets cdtext's keyword entry to field + */ + void cdtext_set (cdtext_field_t key, const char *value, cdtext_t *cdtext); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __CDIO_CDTEXT_H__ */ + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/input/vcd/libcdio/ds.h b/src/input/vcd/libcdio/cdio/ds.h index 24805840e..c811cadd4 100644 --- a/src/input/vcd/libcdio/ds.h +++ b/src/input/vcd/libcdio/cdio/ds.h @@ -1,5 +1,5 @@ /* - $Id: ds.h,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: ds.h,v 1.1 2005/01/01 02:43:58 rockyb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> diff --git a/src/input/vcd/libcdio/cdio/dvd.h b/src/input/vcd/libcdio/cdio/dvd.h new file mode 100644 index 000000000..df58c4322 --- /dev/null +++ b/src/input/vcd/libcdio/cdio/dvd.h @@ -0,0 +1,113 @@ +/* + $Id: dvd.h,v 1.1 2005/01/01 02:43:58 rockyb Exp $ + + Copyright (C) 2004 Rocky Bernstein <rocky@panix.com> + Modeled after GNU/Linux definitions in linux/cdrom.h + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/*! + \file dvd.h + \brief Definitions for DVD access. +*/ + +#ifndef __CDIO_DVD_H__ +#define __CDIO_DVD_H__ + +#include <cdio/types.h> + +/*! Values used in a READ DVD STRUCTURE */ + +#define CDIO_DVD_STRUCT_PHYSICAL 0x00 +#define CDIO_DVD_STRUCT_COPYRIGHT 0x01 +#define CDIO_DVD_STRUCT_DISCKEY 0x02 +#define CDIO_DVD_STRUCT_BCA 0x03 +#define CDIO_DVD_STRUCT_MANUFACT 0x04 + +/*! Media definitions for "Book Type" */ +#define CDIO_DVD_BOOK_DVD_ROM 0 +#define CDIO_DVD_BOOK_DVD_RAM 1 +#define CDIO_DVD_BOOK_DVD_R 2 /**< DVD-R */ +#define CDIO_DVD_BOOK_DVD_RW 3 /**< DVD-RW */ +#define CDIO_DVD_BOOK_DVD_PR 8 /**< DVD+R */ +#define CDIO_DVD_BOOK_DVD_PRW 9 /**< DVD+RW */ + +typedef struct cdio_dvd_layer { + uint8_t book_version : 4; + uint8_t book_type : 4; + uint8_t min_rate : 4; + uint8_t disc_size : 4; + uint8_t layer_type : 4; + uint8_t track_path : 1; + uint8_t nlayers : 2; + uint8_t track_density : 4; + uint8_t linear_density: 4; + uint8_t bca : 1; + uint32_t start_sector; + uint32_t end_sector; + uint32_t end_sector_l0; +} cdio_dvd_layer_t; + +/*! Maximum number of layers in a DVD. */ +#define CDIO_DVD_MAX_LAYERS 4 + +typedef struct cdio_dvd_physical { + uint8_t type; + uint8_t layer_num; + cdio_dvd_layer_t layer[CDIO_DVD_MAX_LAYERS]; +} cdio_dvd_physical_t; + +typedef struct cdio_dvd_copyright { + uint8_t type; + + uint8_t layer_num; + uint8_t cpst; + uint8_t rmi; +} cdio_dvd_copyright_t; + +typedef struct cdio_dvd_disckey { + uint8_t type; + + unsigned agid : 2; + uint8_t value[2048]; +} cdio_dvd_disckey_t; + +typedef struct cdio_dvd_bca { + uint8_t type; + + int len; + uint8_t value[188]; +} cdio_dvd_bca_t; + +typedef struct cdio_dvd_manufact { + uint8_t type; + + uint8_t layer_num; + int len; + uint8_t value[2048]; +} cdio_dvd_manufact_t; + +typedef union { + uint8_t type; + + cdio_dvd_physical_t physical; + cdio_dvd_copyright_t copyright; + cdio_dvd_disckey_t disckey; + cdio_dvd_bca_t bca; + cdio_dvd_manufact_t manufact; +} cdio_dvd_struct_t; + +#endif /* __SCSI_MMC_H__ */ diff --git a/src/input/vcd/libcdio/cdio/iso9660.h b/src/input/vcd/libcdio/cdio/iso9660.h index 78f78ef81..104b6ba62 100644 --- a/src/input/vcd/libcdio/cdio/iso9660.h +++ b/src/input/vcd/libcdio/cdio/iso9660.h @@ -1,5 +1,5 @@ /* - $Id: iso9660.h,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: iso9660.h,v 1.3 2005/01/01 02:43:58 rockyb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> @@ -33,6 +33,7 @@ #define __CDIO_ISO9660_H__ #include <cdio/cdio.h> +#include <cdio/ds.h> #include <cdio/xa.h> #include <time.h> @@ -56,14 +57,35 @@ = 38 chars \endverbatim */ -#define LEN_ISONAME 31 -#define MAX_ISONAME 37 +/*! size in bytes of the filename portion + null byte */ +#define LEN_ISONAME 31 + +/*! Max # characters in the entire ISO 9660 filename. */ +#define MAX_ISONAME 37 + +/*! Max # characters in the entire ISO 9660 filename. */ #define MAX_ISOPATHNAME 255 -/* - * ISO 9660 directory flags. - */ +/*! Max # characters in an perparer id. */ +#define ISO_MAX_PREPARER_ID 128 + +/*! Max # characters in an publisher id. */ +#define ISO_MAX_PUBLISHER_ID 128 + +/*! Max # characters in an application id. */ +#define ISO_MAX_APPLICATION_ID 128 + +/*! Max # characters in an system id. */ +#define ISO_MAX_SYSTEM_ID 32 + +/*! Max # characters in an volume id. */ +#define ISO_MAX_VOLUME_ID 32 + +/*! Max # characters in an volume-set id. */ +#define ISO_MAX_VOLUMESET_ID 128 + +/**! ISO 9660 directory flags. */ #define ISO_FILE 0 /**< Not really a flag... */ #define ISO_EXISTENCE 1 /**< Do not make existence known (hidden) */ #define ISO_DIRECTORY 2 /**< This file is a directory */ @@ -74,18 +96,23 @@ #define ISO_DRESERVED2 64 /**< Reserved bit 6 */ #define ISO_MULTIEXTENT 128 /**< Not final entry of a mult. ext. file */ -/* Volume descriptor types */ +/**! Volume descriptor types */ #define ISO_VD_PRIMARY 1 #define ISO_VD_SUPPLEMENTARY 2 /**< Used by Joliet */ #define ISO_VD_END 255 -#define ISO_PVD_SECTOR 16 /**< Sector of Primary Volume Descriptor */ -#define ISO_EVD_SECTOR 17 /**< Sector of End Volume Descriptor */ +/*! Sector of Primary Volume Descriptor */ +#define ISO_PVD_SECTOR 16 + +/*! Sector of End Volume Descriptor */ +#define ISO_EVD_SECTOR 17 -#define ISO_STANDARD_ID "CD001" /**< String inside track identifying an - ISO 9660 filesystem. */ -#define ISO_BLOCKSIZE 2048 /**< Number of bytes in an ISO - 9660 block */ +/*! String inside track identifying an ISO 9660 filesystem. */ +#define ISO_STANDARD_ID "CD001" + + +/*! Number of bytes in an ISO 9660 block */ +#define ISO_BLOCKSIZE 2048 #ifdef __cplusplus extern "C" { @@ -98,6 +125,10 @@ enum strncpy_pad_check { ISO9660_DCHARS }; +#ifndef EMPTY_ARRAY_SIZE +#define EMPTY_ARRAY_SIZE 0 +#endif + PRAGMA_BEGIN_PACKED /*! @@ -144,33 +175,62 @@ struct iso9660_ltime { typedef struct iso9660_ltime iso9660_ltime_t; +/*! \brief Format of an ISO-9660 directory record + + This structure may have an odd length depending on how many + characters there are in the filename! Some compilers (e.g. on + Sun3/mc68020) pad the structures to an even length. For this reason, + we cannot use sizeof (struct iso_path_table) or sizeof (struct + iso_directory_record) to compute on disk sizes. Instead, we use + offsetof(..., name) and add the name size. See mkisofs.h of the + cdrtools package. + + @see iso9660_stat +*/ +struct iso9660_dir { + uint8_t length; /*! 711 encoded */ + uint8_t xa_length; /*! 711 encoded */ + uint64_t extent; /*! 733 encoded */ + uint64_t size; /*! 733 encoded */ + iso9660_dtime_t recording_time; /*! 7 711-encoded units */ + uint8_t file_flags; + uint8_t file_unit_size; /*! 711 encoded */ + uint8_t interleave_gap; /*! 711 encoded */ + uint32_t volume_sequence_number; /*! 723 encoded */ + uint8_t filename_len; /*! 711 encoded */ + char filename[EMPTY_ARRAY_SIZE]; +} GNUC_PACKED; + +typedef struct iso9660_dir iso9660_dir_t; + /*! \brief ISO-9660 Primary Volume Descriptor. */ struct iso9660_pvd { - uint8_t type; /**< 711 encoded */ + uint8_t type; /**< 711 encoded */ char id[5]; - uint8_t version; /**< 711 encoded */ + uint8_t version; /**< 711 encoded */ char unused1[1]; - char system_id[32]; /**< each char is an achar */ - char volume_id[32]; /**< each char is a dchar */ + char system_id[ISO_MAX_SYSTEM_ID]; /**< each char is an achar */ + char volume_id[ISO_MAX_VOLUME_ID]; /**< each char is a dchar */ char unused2[8]; - uint64_t volume_space_size; /**< 733 encoded */ - char escape_sequences[32]; - uint32_t volume_set_size; /**< 723 encoded */ - uint32_t volume_sequence_number; /**< 723 encoded */ - uint32_t logical_block_size; /**< 723 encoded */ - uint64_t path_table_size; /**< 733 encoded */ - uint32_t type_l_path_table; /**< 731 encoded */ - uint32_t opt_type_l_path_table; /**< 731 encoded */ - uint32_t type_m_path_table; /**< 732 encoded */ - uint32_t opt_type_m_path_table; /**< 732 encoded */ - char root_directory_record[34]; /**< See section 9.1 of - ISO 9660 spec. */ - char volume_set_id[128]; /**< dchars */ - char publisher_id[128]; /**< achars */ - char preparer_id[128]; /**< achars */ - char application_id[128]; /**< achars */ + uint64_t volume_space_size; /**< 733 encoded */ + char unused3[32]; + uint32_t volume_set_size; /**< 723 encoded */ + uint32_t volume_sequence_number; /**< 723 encoded */ + uint32_t logical_block_size; /**< 723 encoded */ + uint64_t path_table_size; /**< 733 encoded */ + uint32_t type_l_path_table; /**< 731 encoded */ + uint32_t opt_type_l_path_table; /**< 731 encoded */ + uint32_t type_m_path_table; /**< 732 encoded */ + uint32_t opt_type_m_path_table; /**< 732 encoded */ + iso9660_dir_t root_directory_record; /**< See section 9.1 of + ISO 9660 spec. */ + char root_directory_filename; /**< Is \0 */ + char volume_set_id[ISO_MAX_VOLUMESET_ID]; /**< dchars */ + char publisher_id[ISO_MAX_PUBLISHER_ID]; /**< achars */ + char preparer_id[ISO_MAX_PREPARER_ID]; /**< achars */ + char application_id[ISO_MAX_APPLICATION_ID]; /**< achars */ char copyright_file_id[37]; /**< See section 7.5 of ISO 9660 spec. Each char is a dchar */ @@ -194,41 +254,63 @@ struct iso9660_pvd { char unused5[653]; } GNUC_PACKED; -typedef struct iso9660_dir iso9660_dir_t; typedef struct iso9660_pvd iso9660_pvd_t; -typedef struct iso9660_stat iso9660_stat_t; - -#ifndef EMPTY_ARRAY_SIZE -#define EMPTY_ARRAY_SIZE 0 -#endif - - -/*! \brief Format of an ISO-9660 directory record - This structure may have an odd length depending on how many - characters there are in the filename! Some compilers (e.g. on - Sun3/mc68020) pad the structures to an even length. For this reason, - we cannot use sizeof (struct iso_path_table) or sizeof (struct - iso_directory_record) to compute on disk sizes. Instead, we use - offsetof(..., name) and add the name size. See mkisofs.h of the - cdrtools package. +/*! + \brief ISO-9660 Supplementary Volume Descriptor. - @see iso9660_stat + This is used for Joliet Extentions and is almost the same as the + the primary descriptor but two unused fields, "unused1" and "unused3 + become "flags and "escape_sequences" respectively. */ -struct iso9660_dir { - uint8_t length; /*! 711 encoded */ - uint8_t xa_length; /*! 711 encoded */ - uint64_t extent; /*! 733 encoded */ - uint64_t size; /*! 733 encoded */ - iso9660_dtime_t recording_time; /*! 7 711-encoded units */ - uint8_t file_flags; - uint8_t file_unit_size; /*! 711 encoded */ - uint8_t interleave_gap; /*! 711 encoded */ - uint32_t volume_sequence_number; /*! 723 encoded */ - uint8_t filename_len; /*! 711 encoded */ - char filename[EMPTY_ARRAY_SIZE]; +struct iso9660_svd { + uint8_t type; /**< 711 encoded */ + char id[5]; + uint8_t version; /**< 711 encoded */ + char flags; /**< 853 */ + char system_id[ISO_MAX_SYSTEM_ID]; /**< each char is an achar */ + char volume_id[ISO_MAX_VOLUME_ID]; /**< each char is a dchar */ + char unused2[8]; + uint64_t volume_space_size; /**< 733 encoded */ + char escape_sequences[32]; /**< 856 */ + uint32_t volume_set_size; /**< 723 encoded */ + uint32_t volume_sequence_number; /**< 723 encoded */ + uint32_t logical_block_size; /**< 723 encoded */ + uint64_t path_table_size; /**< 733 encoded */ + uint32_t type_l_path_table; /**< 731 encoded */ + uint32_t opt_type_l_path_table; /**< 731 encoded */ + uint32_t type_m_path_table; /**< 732 encoded */ + uint32_t opt_type_m_path_table; /**< 732 encoded */ + iso9660_dir_t root_directory_record; /**< See section 9.1 of + ISO 9660 spec. */ + char volume_set_id[ISO_MAX_VOLUMESET_ID]; /**< dchars */ + char publisher_id[ISO_MAX_PUBLISHER_ID]; /**< achars */ + char preparer_id[ISO_MAX_PREPARER_ID]; /**< achars */ + char application_id[ISO_MAX_APPLICATION_ID]; /**< achars */ + char copyright_file_id[37]; /**< See section 7.5 of + ISO 9660 spec. Each char is + a dchar */ + char abstract_file_id[37]; /**< See section 7.5 of + ISO 9660 spec. Each char is + a dchar */ + char bibliographic_file_id[37]; /**< See section 7.5 of + ISO 9660 spec. Each char is + a dchar. */ + iso9660_ltime_t creation_date; /**< See section 8.4.26.1 of + ISO 9660 spec. */ + iso9660_ltime_t modification_date; /**< See section 8.4.26.1 of + ISO 9660 spec. */ + iso9660_ltime_t expiration_date; /**< See section 8.4.26.1 of + ISO 9660 spec. */ + iso9660_ltime_t effective_date; /**< See section 8.4.26.1 of + ISO 9660 spec. */ + uint8_t file_structure_version; /**< 711 encoded */ + char unused4[1]; + char application_data[512]; + char unused5[653]; } GNUC_PACKED; +typedef struct iso9660_svd iso9660_svd_t; PRAGMA_END_PACKED @@ -251,29 +333,88 @@ struct iso9660_stat { /* big endian!! */ char filename[EMPTY_ARRAY_SIZE]; /**< filename */ }; +typedef struct iso9660_stat iso9660_stat_t; + + +/** A mask used in iso9660_ifs_read_vd which allows what kinds + of extensions we allow, eg. Joliet, Rock Ridge, etc. */ +typedef uint8_t iso_extension_mask_t; + +#define ISO_EXTENSION_JOLIET_LEVEL1 0x01 +#define ISO_EXTENSION_JOLIET_LEVEL2 0x02 +#define ISO_EXTENSION_JOLIET_LEVEL3 0x04 +#define ISO_EXTENSION_ROCK_RIDGE 0x08 +#define ISO_EXTENSION_HIGH_SIERRA 0x10 + +#define ISO_EXTENSION_ALL 0xFF +#define ISO_EXTENSION_NONE 0x00 +#define ISO_EXTENSION_JOLIET \ + (ISO_EXTENSION_JOLIET_LEVEL1 | \ + ISO_EXTENSION_JOLIET_LEVEL2 | \ + ISO_EXTENSION_JOLIET_LEVEL3 ) + /** This is an opaque structure. */ typedef struct _iso9660 iso9660_t; /*! Open an ISO 9660 image for reading. Maybe in the future we will have - flags and mode. NULL is returned on error. + a mode. NULL is returned on error. */ - iso9660_t *iso9660_open (const char *pathname /*flags, mode */); + iso9660_t *iso9660_open (const char *psz_pathname /*flags, mode */); + +/*! + Open an ISO 9660 image for reading allowing various ISO 9660 + extensions. Maybe in the future we will have a mode. NULL is + returned on error. +*/ + iso9660_t *iso9660_open_ext (const char *psz_pathname, + iso_extension_mask_t iso_extension_mask); /*! Close previously opened ISO 9660 image. True is unconditionally returned. If there was an error false would be returned. */ - bool iso9660_close (iso9660_t * iso); + bool iso9660_close (iso9660_t * p_iso); /*! Seek to a position and then read n bytes. Size read is returned. */ - long int iso9660_iso_seek_read (iso9660_t *iso, void *ptr, lsn_t start, - long int size); + long int iso9660_iso_seek_read (const iso9660_t *p_iso, void *ptr, + lsn_t start, long int i_size); + +/*! + Read the Primary Volume Descriptor for a CD. + True is returned if read, and false if there was an error. +*/ + bool iso9660_fs_read_pvd ( const CdIo *p_cdio, + /*out*/ iso9660_pvd_t *p_pvd ); + +/*! + Read the Primary Volume Descriptor for an ISO 9660 image. + True is returned if read, and false if there was an error. +*/ + bool iso9660_ifs_read_pvd (const iso9660_t *p_iso, + /*out*/ iso9660_pvd_t *p_pvd); + +/*! + Read the Super block of an ISO 9660 image. This is the + Primary Volume Descriptor (PVD) and perhaps a Supplemental Volume + Descriptor if (Joliet) extensions are acceptable. +*/ + bool iso9660_fs_read_superblock (CdIo *p_cdio, + iso_extension_mask_t iso_extension_mask); + +/*! + Read the Supper block of an ISO 9660 image. This is the + Primary Volume Descriptor (PVD) and perhaps a Supplemental Volume + Descriptor if (Joliet) extensions are acceptable. +*/ + bool iso9660_ifs_read_superblock (iso9660_t *p_iso, + iso_extension_mask_t iso_extension_mask); + /*==================================================== Time conversion @@ -289,7 +430,7 @@ typedef struct _iso9660 iso9660_t; Set "long" time in format used in ISO 9660 primary volume descriptor from a Unix time structure. */ void iso9660_set_ltime (const struct tm *_tm, - /*out*/ iso9660_ltime_t *pvd_date); + /*out*/ iso9660_ltime_t *p_pvd_date); /*! Get Unix time structure from format use in an ISO 9660 directory index @@ -323,13 +464,24 @@ bool iso9660_isachar (int c); /*! Convert ISO-9660 file name that stored in a directory entry into what's usually listed as the file name in a listing. - Lowercase name, and drop deal with trailing ;1's or .;1's or - ; version numbers. + Lowercase name, and remove trailing ;1's or .;1's and + turn the other ;'s into version numbers. The length of the translated string is returned. */ -int iso9660_name_translate(const char *old, char *new); +int iso9660_name_translate(const char *psz_oldname, char *psz_newname); + +/*! + Convert ISO-9660 file name that stored in a directory entry into + what's usually listed as the file name in a listing. Lowercase + name if not using Joliet extension. Remove trailing ;1's or .;1's and + turn the other ;'s into version numbers. + The length of the translated string is returned. +*/ +int iso9660_name_translate_ext(const char *old, char *new, + uint8_t i_joliet_level); + /*! Pad string src with spaces to size len and copy this to dst. If len is less than the length of src, dst will be truncated to the @@ -366,7 +518,7 @@ bool iso9660_dirname_valid_p (const char pathname[]); number. For example, mydir/file.ext -> MYDIR/FILE.EXT;1 for version 1. The resulting ISO-9660 pathname is returned. */ -char *iso9660_pathname_isofy (const char pathname[], uint16_t version); +char *iso9660_pathname_isofy (const char pathname[], uint16_t i_version); /*! Check that pathname is a valid ISO-9660 pathname. @@ -412,7 +564,7 @@ iso9660_dir_calc_record_size (unsigned int namelen, unsigned int su_len); Returns stat_t of entry if we found lsn, or NULL otherwise. */ -iso9660_stat_t *iso9660_find_fs_lsn(const CdIo *cdio, lsn_t lsn); +iso9660_stat_t *iso9660_find_fs_lsn(CdIo *p_cdio, lsn_t i_lsn); /*! @@ -421,14 +573,14 @@ iso9660_stat_t *iso9660_find_fs_lsn(const CdIo *cdio, lsn_t lsn); Returns stat_t of entry if we found lsn, or NULL otherwise. */ -iso9660_stat_t *iso9660_find_ifs_lsn(const iso9660_t *iso, lsn_t lsn); +iso9660_stat_t *iso9660_find_ifs_lsn(const iso9660_t *p_iso, lsn_t i_lsn); /*! Get file status for pathname into stat. NULL is returned on error. */ -iso9660_stat_t *iso9660_fs_stat (const CdIo *obj, const char pathname[], - bool is_mode2); +iso9660_stat_t *iso9660_fs_stat (CdIo *p_cdio, const char pathname[]); + /*! Get file status for pathname into stat. NULL is returned on error. @@ -436,14 +588,14 @@ iso9660_stat_t *iso9660_fs_stat (const CdIo *obj, const char pathname[], name are dropped, i.e. ;1 is removed and if level 1 ISO-9660 names are lowercased. */ -iso9660_stat_t *iso9660_fs_stat_translate (const CdIo *obj, +iso9660_stat_t *iso9660_fs_stat_translate (CdIo *p_cdio, const char pathname[], - bool is_mode2); + bool b_mode2); /*! Get file status for pathname into stat. NULL is returned on error. */ -void *iso9660_ifs_stat (iso9660_t *iso, const char pathname[]); +iso9660_stat_t *iso9660_ifs_stat (iso9660_t *p_iso, const char pathname[]); /*! @@ -452,28 +604,46 @@ void *iso9660_ifs_stat (iso9660_t *iso, const char pathname[]); name are dropped, i.e. ;1 is removed and if level 1 ISO-9660 names are lowercased. */ -void *iso9660_ifs_stat_translate (iso9660_t *iso, const char pathname[]); - - +iso9660_stat_t *iso9660_ifs_stat_translate (iso9660_t *p_iso, + const char pathname[]); /*! Read pathname (a directory) and return a list of iso9660_stat_t of the files inside that. The caller must free the returned result. */ -void * iso9660_fs_readdir (const CdIo *obj, const char pathname[], bool mode2); +CdioList * iso9660_fs_readdir (CdIo *p_cdio, const char pathname[], + bool b_mode2); /*! Read pathname (a directory) and return a list of iso9660_stat_t of the files inside that. The caller must free the returned result. */ -void * iso9660_ifs_readdir (iso9660_t *iso, const char pathname[]); +CdioList * iso9660_ifs_readdir (iso9660_t *p_iso, const char pathname[]); + +/*! + Return the PVD's application ID. + NULL is returned if there is some problem in getting this. +*/ +char * iso9660_get_application_id(iso9660_pvd_t *p_pvd); + +/*! + Get the application ID. psz_app_id is set to NULL if there + is some problem in getting this and false is returned. +*/ +bool iso9660_ifs_get_application_id(iso9660_t *p_iso, + /*out*/ char **p_psz_app_id); -uint8_t iso9660_get_dir_len(const iso9660_dir_t *idr); +/*! + Return the Joliet level recognized for p_iso. +*/ +uint8_t iso9660_ifs_get_joliet_level(iso9660_t *p_iso); + +uint8_t iso9660_get_dir_len(const iso9660_dir_t *p_idr); #if FIXME -uint8_t iso9660_get_dir_size(const iso9660_dir_t *idr); +uint8_t iso9660_get_dir_size(const iso9660_dir_t *p_idr); -lsn_t iso9660_get_dir_extent(const iso9660_dir_t *idr); +lsn_t iso9660_get_dir_extent(const iso9660_dir_t *p_idr); #endif /*! @@ -481,25 +651,90 @@ lsn_t iso9660_get_dir_extent(const iso9660_dir_t *idr); A string is allocated: the caller must deallocate. */ -char * iso9660_dir_to_name (const iso9660_dir_t *iso9660_dir); +char * iso9660_dir_to_name (const iso9660_dir_t *p_iso9660_dir); + +/*! + Return a string containing the preparer id with trailing + blanks removed. +*/ +char *iso9660_get_preparer_id(const iso9660_pvd_t *p_pvd); -uint8_t iso9660_get_pvd_type(const iso9660_pvd_t *pvd); +/*! + Get the preparer ID. psz_preparer_id is set to NULL if there + is some problem in getting this and false is returned. +*/ +bool iso9660_ifs_get_preparer_id(iso9660_t *p_iso, + /*out*/ char **p_psz_preparer_id); + +/*! + Return a string containing the PVD's publisher id with trailing + blanks removed. +*/ +char *iso9660_get_publisher_id(const iso9660_pvd_t *p_pvd); -const char * iso9660_get_pvd_id(const iso9660_pvd_t *pvd); +/*! + Get the publisher ID. psz_publisher_id is set to NULL if there + is some problem in getting this and false is returned. +*/ +bool iso9660_ifs_get_publisher_id(iso9660_t *p_iso, + /*out*/ char **p_psz_publisher_id); + +uint8_t iso9660_get_pvd_type(const iso9660_pvd_t *p_pvd); + +const char * iso9660_get_pvd_id(const iso9660_pvd_t *p_pvd); -int iso9660_get_pvd_space_size(const iso9660_pvd_t *pvd); +int iso9660_get_pvd_space_size(const iso9660_pvd_t *p_pvd); -int iso9660_get_pvd_block_size(const iso9660_pvd_t *pvd) ; +int iso9660_get_pvd_block_size(const iso9660_pvd_t *p_pvd) ; /*! Return the primary volume id version number (of pvd). If there is an error 0 is returned. */ int iso9660_get_pvd_version(const iso9660_pvd_t *pvd) ; +/*! + Return a string containing the PVD's system id with trailing + blanks removed. +*/ +char *iso9660_get_system_id(const iso9660_pvd_t *p_pvd); + +/*! + Get the system ID. psz_system_id is set to NULL if there + is some problem in getting this and false is returned. +*/ +bool iso9660_ifs_get_system_id(iso9660_t *p_iso, + /*out*/ char **p_psz_system_id); + + /*! Return the LSN of the root directory for pvd. If there is an error CDIO_INVALID_LSN is returned. */ -lsn_t iso9660_get_root_lsn(const iso9660_pvd_t *pvd); +lsn_t iso9660_get_root_lsn(const iso9660_pvd_t *p_pvd); + +/*! + Return the PVD's volume ID. +*/ +char *iso9660_get_volume_id(const iso9660_pvd_t *p_pvd); + +/*! + Get the system ID. psz_system_id is set to NULL if there + is some problem in getting this and false is returned. +*/ +bool iso9660_ifs_get_volume_id(iso9660_t *p_iso, + /*out*/ char **p_psz_volume_id); + +/*! + Return the PVD's volumeset ID. + NULL is returned if there is some problem in getting this. +*/ +char *iso9660_get_volumeset_id(const iso9660_pvd_t *p_pvd); + +/*! + Get the systemset ID. psz_systemset_id is set to NULL if there + is some problem in getting this and false is returned. +*/ +bool iso9660_ifs_get_volumeset_id(iso9660_t *p_iso, + /*out*/ char **p_psz_volumeset_id); /* pathtable */ @@ -530,6 +765,12 @@ iso9660_set_pvd (void *pd, const char volume_id[], const char application_id[], void iso9660_set_evd (void *pd); +/*! + Return true if ISO 9660 image has extended attrributes (XA). +*/ +bool iso9660_ifs_is_xa (const iso9660_t * p_iso); + + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/input/vcd/libcdio/cdio/logging.h b/src/input/vcd/libcdio/cdio/logging.h index aec981ad4..8c78259ea 100644 --- a/src/input/vcd/libcdio/cdio/logging.h +++ b/src/input/vcd/libcdio/cdio/logging.h @@ -1,8 +1,8 @@ /* - $Id: logging.h,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: logging.h,v 1.3 2005/01/01 02:43:58 rockyb Exp $ Copyright (C) 2000, Herbert Valerio Riedel <hvr@gnu.org> - Copyright (C) 2003, Rocky Bernstein <rocky@panix.com> + Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> 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 @@ -29,6 +29,10 @@ #include <cdio/types.h> +#ifdef __cplusplus +extern "C" { +#endif + /** * The different log levels supported. */ @@ -75,7 +79,7 @@ typedef void (*cdio_log_handler_t) (cdio_log_level_t level, cdio_log_handler_t cdio_log_set_handler (cdio_log_handler_t new_handler); /** - * Handle an message with the given log level + * Handle an message with the given log level. * * @see cdio_debug * @see cdio_info @@ -111,12 +115,16 @@ void cdio_info (const char format[], ...) GNUC_PRINTF(1,2); void cdio_warn (const char format[], ...) GNUC_PRINTF(1,2); /** - * Handle an error message. + * Handle an error message. Execution is terminated. * * @see cdio_log for a more generic routine. */ void cdio_error (const char format[], ...) GNUC_PRINTF(1,2); +#ifdef __cplusplus +} +#endif + #endif /* __LOGGING_H__ */ diff --git a/src/input/vcd/libcdio/cdio/scsi_mmc.h b/src/input/vcd/libcdio/cdio/scsi_mmc.h new file mode 100644 index 000000000..12860247e --- /dev/null +++ b/src/input/vcd/libcdio/cdio/scsi_mmc.h @@ -0,0 +1,415 @@ +/* + $Id: scsi_mmc.h,v 1.1 2005/01/01 02:43:58 rockyb Exp $ + + Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/*! + \file scsi_mmc.h + \brief Common definitions for SCSI MMC (Multi-Media Commands). +*/ + +#ifndef __SCSI_MMC_H__ +#define __SCSI_MMC_H__ + +#include <cdio/cdio.h> +#include <cdio/types.h> +#include <cdio/dvd.h> + +/*! The generic packet command opcodes for CD/DVD Logical Units. */ + +#define CDIO_MMC_GPCMD_INQUIRY 0x12 +#define CDIO_MMC_GPCMD_MODE_SELECT_6 0x15 +#define CDIO_MMC_GPCMD_MODE_SENSE 0x1a +#define CDIO_MMC_GPCMD_START_STOP 0x1b +#define CDIO_MMC_GPCMD_ALLOW_MEDIUM_REMOVAL 0x1e +#define CDIO_MMC_GPCMD_READ_10 0x28 + +/*! + Group 2 Commands + */ +#define CDIO_MMC_GPCMD_READ_SUBCHANNEL 0x42 +#define CDIO_MMC_GPCMD_READ_TOC 0x43 +#define CDIO_MMC_GPCMD_READ_HEADER 0x44 +#define CDIO_MMC_GPCMD_PLAY_AUDIO_10 0x45 +#define CDIO_MMC_GPCMD_GET_CONFIGURATION 0x46 +#define CDIO_MMC_GPCMD_PLAY_AUDIO_MSF 0x47 +#define CDIO_MMC_GPCMD_PLAY_AUDIO_TI 0x48 +#define CDIO_MMC_GPCMD_PLAY_TRACK_REL_10 0x49 +#define CDIO_MMC_GPCMD_PAUSE_RESUME 0x4b + +#define CDIO_MMC_GPCMD_READ_DISC_INFO 0x51 +#define CDIO_MMC_GPCMD_MODE_SELECT 0x55 +#define CDIO_MMC_GPCMD_MODE_SENSE_10 0x5a + +/*! + Group 5 Commands + */ +#define CDIO_MMC_GPCMD_PLAY_AUDIO_12 0xa5 +#define CDIO_MMC_GPCMD_READ_12 0xa8 +#define CDIO_MMC_GPCMD_PLAY_TRACK_REL_12 0xa9 +#define CDIO_MMC_GPCMD_READ_DVD_STRUCTURE 0xad +#define CDIO_MMC_GPCMD_READ_CD 0xbe +#define CDIO_MMC_GPCMD_READ_MSF 0xb9 + +/*! + Group 6 Commands + */ + +#define CDIO_MMC_GPCMD_CD_PLAYBACK_STATUS 0xc4 /**< SONY unique command */ +#define CDIO_MMC_GPCMD_PLAYBACK_CONTROL 0xc9 /**< SONY unique command */ +#define CDIO_MMC_GPCMD_READ_CDDA 0xd8 /**< Vendor unique command */ +#define CDIO_MMC_GPCMD_READ_CDXA 0xdb /**< Vendor unique command */ +#define CDIO_MMC_GPCMD_READ_ALL_SUBCODES 0xdf /**< Vendor unique command */ + + + +/*! Level values that can go into READ_CD */ +#define CDIO_MMC_READ_TYPE_ANY 0 /**< All types */ +#define CDIO_MMC_READ_TYPE_CDDA 1 /**< Only CD-DA sectors */ +#define CDIO_MMC_READ_TYPE_MODE1 2 /**< mode1 sectors (user data = 2048) */ +#define CDIO_MMC_READ_TYPE_MODE2 3 /**< mode2 sectors form1 or form2 */ +#define CDIO_MMC_READ_TYPE_M2F1 4 /**< mode2 sectors form1 */ +#define CDIO_MMC_READ_TYPE_M2F2 5 /**< mode2 sectors form2 */ + +/*! Format values for READ_TOC */ +#define CDIO_MMC_READTOC_FMT_TOC 0 +#define CDIO_MMC_READTOC_FMT_SESSION 1 +#define CDIO_MMC_READTOC_FMT_FULTOC 2 +#define CDIO_MMC_READTOC_FMT_PMA 3 /**< Q subcode data */ +#define CDIO_MMC_READTOC_FMT_ATIP 4 /**< includes media type */ +#define CDIO_MMC_READTOC_FMT_CDTEXT 5 /**< CD-TEXT info */ + +/*! Page codes for MODE SENSE and MODE SET. */ +#define CDIO_MMC_R_W_ERROR_PAGE 0x01 +#define CDIO_MMC_WRITE_PARMS_PAGE 0x05 +#define CDIO_MMC_AUDIO_CTL_PAGE 0x0e +#define CDIO_MMC_CDR_PARMS_PAGE 0x0d +#define CDIO_MMC_POWER_PAGE 0x1a +#define CDIO_MMC_FAULT_FAIL_PAGE 0x1c +#define CDIO_MMC_TO_PROTECT_PAGE 0x1d +#define CDIO_MMC_CAPABILITIES_PAGE 0x2a +#define CDIO_MMC_ALL_PAGES 0x3f + +/*! Return type codes for GET_CONFIGURATION. */ +#define CDIO_MMC_GET_CONF_ALL_FEATURES 0 /**< all features without regard + to currency. */ +#define CDIO_MMC_GET_CONF_CURRENT_FEATURES 1 /**< features which are currently + in effect (e.g. based on + medium inserted). */ +#define CDIO_MMC_GET_CONF_NAMED_FEATURE 2 /**< just the feature named in + the GET_CONFIGURATION + cdb. */ + +/*! FEATURE codes used in GET CONFIGURATION. */ + +#define CDIO_MMC_FEATURE_PROFILE_LIST 0x000 /**< Profile List Feature */ +#define CDIO_MMC_FEATURE_CORE 0x001 +#define CDIO_MMC_FEATURE_REMOVABLE_MEDIUM 0x002 /**< Removable Medium + Feature */ +#define CDIO_MMC_FEATURE_WRITE_PROTECT 0x003 /**< Write Protect + Feature */ +#define CDIO_MMC_FEATURE_RANDOM_READABLE 0x010 /**< Random Readable + Feature */ +#define CDIO_MMC_FEATURE_MULTI_READ 0x01D /**< Multi-Read + Feature */ +#define CDIO_MMC_FEATURE_CD_READ 0x01E /**< CD Read + Feature */ +#define CDIO_MMC_FEATURE_DVD_READ 0x01F /**< DVD Read + Feature */ +#define CDIO_MMC_FEATURE_RANDOM_WRITABLE 0x020 /**< Random Writable + Feature */ +#define CDIO_MMC_FEATURE_INCR_WRITE 0x021 /**< Incremental + Streaming Writable + Feature */ +#define CDIO_MMC_FEATURE_SECTOR_ERASE 0x022 /**< Sector Erasable + Feature */ +#define CDIO_MMC_FEATURE_FORMATABLE 0x023 /**< Formattable + Feature */ +#define CDIO_MMC_FEATURE_DEFECT_MGMT 0x024 /**< Management + Ability of the + Logical Unit/media + system to provide + an apparently + defect-free + space.*/ +#define CDIO_MMC_FEATURE_WRITE_ONCE 0x025 /**< Write Once + Feature */ +#define CDIO_MMC_FEATURE_RESTRICT_OVERW 0x026 /**< Restricted + Overwrite + Feature */ +#define CDIO_MMC_FEATURE_CD_RW_CAV 0x027 /**< CD-RW CAV Write + Feature */ +#define CDIO_MMC_FEATURE_MRW 0x028 /**< MRW Feature */ +#define CDIO_MMC_FEATURE_DVD_PRW 0x02A /**< DVD+RW Feature */ +#define CDIO_MMC_FEATURE_DVD_PR 0x02B /**< DVD+R Feature */ +#define CDIO_MMC_FEATURE_CD_TAO 0x02D +#define CDIO_MMC_FEATURE_CD_SAO 0x02E +#define CDIO_MMC_FEATURE_POWER_MGMT 0x100 /**< Initiator and + device directed + power management */ +#define CDIO_MMC_FEATURE_CDDA_EXT_PLAY 0x103 /**< Ability to play + audio CDs via the + Logical Unit s own + analog output */ +#define CDIO_MMC_FEATURE_MCODE_UPGRADE 0x104 /* Ability for the + device to accept + new microcode via + the interface */ +#define CDIO_MMC_FEATURE_TIME_OUT 0x105 /**< Ability to + respond to all + commands within a + specific time */ +#define CDIO_MMC_FEATURE_DVD_CSS 0x106 /**< Ability to + perform DVD + CSS/CPPM + authentication and + RPC */ +#define CDIO_MMC_FEATURE_RT_STREAMING 0x107 /**< Ability to read + and write using + Initiator requested + performance + parameters + */ +#define CDIO_MMC_FEATURE_LU_SN 0x108 /**< The Logical Unit + has a unique + identifier. */ +#define CDIO_MMC_FEATURE_FIRMWARE_DATE 0x1FF /**< Firmware creation + date report */ + +/*! Profile codes used in GET_CONFIGURATION - PROFILE LIST. */ +#define CDIO_MMC_FEATURE_PROF_NON_REMOVABLE 0x0001 /**< Re-writable + disk, capable of + changing + behavior */ +#define CDIO_MMC_FEATURE_PROF_REMOVABLE 0x0002 /**< disk + Re-writable; + with removable + media */ +#define CDIO_MMC_FEATURE_PROF_MO_ERASABLE 0x0003 /**< Erasable + Magneto-Optical + disk with sector + erase + capability */ +#define CDIO_MMC_FEATURE_PROF_MO_WRITE_ONCE 0x0004 /**< Write Once + Magneto-Optical + write once */ +#define CDIO_MMC_FEATURE_PROF_AS_MO 0x0005 /**< Advance + Storage + Magneto-Optical */ +#define CDIO_MMC_FEATURE_PROF_CD_ROM 0x0008 /**< Read only + Compact Disc + capable */ +#define CDIO_MMC_FEATURE_PROF_CD_R 0x0009 /**< Write once + Compact Disc + capable */ +#define CDIO_MMC_FEATURE_PROF_CD_RW 0x000A /**< CD-RW + Re-writable + Compact Disc + capable */ +#define CDIO_MMC_FEATURE_PROF_DVD_ROM 0x0010 /**< Read only + DVD */ +#define CDIO_MMC_FEATURE_PROF_DVD_R_SEQ 0x0011 /**< Re-recordable + DVD using + Sequential + recording */ +#define CDIO_MMC_FEATURE_PROF_DVD_RAM 0x0012 /**< Re-writable + DVD */ +#define CDIO_MMC_FEATURE_PROF_DVD_RW_RO 0x0013 /**< Re-recordable + DVD using + Restricted + Overwrite */ +#define CDIO_MMC_FEATURE_PROF_DVD_RW_SEQ 0x0014 /**< Re-recordable + DVD using + Sequential + recording */ +#define CDIO_MMC_FEATURE_PROF_DVD_PRW 0x001A /**< DVD+RW - DVD + ReWritable */ +#define CDIO_MMC_FEATURE_PROF_DVD_PR 0x001B /**< DVD+R - DVD + Recordable */ +#define CDIO_MMC_FEATURE_PROF_DDCD_ROM 0x0020 /**< Read only + DDCD */ +#define CDIO_MMC_FEATURE_PROF_DDCD_R 0x0021 /**< DDCD-R Write + only DDCD */ +#define CDIO_MMC_FEATURE_PROF_DDCD_RW 0x0022 /**< Re-Write only + DDCD */ +#define CDIO_MMC_FEATURE_PROF_NON_CONFORM 0xFFFF /**< The Logical + Unit does not + conform to any + Profile. */ + +/*! This is listed as optional in ATAPI 2.6, but is (curiously) + missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji + Table 377 as an MMC command for SCSi devices though... Most ATAPI + drives support it. */ +#define CDIO_MMC_GPCMD_SET_SPEED 0xbb + + +/*! The largest Command Descriptor Buffer (CDB) size. + The possible sizes are 6, 10, and 12 bytes. + */ +#define MAX_CDB_LEN 12 + +/*! \brief A Command Descriptor Buffer (CDB) used in sending SCSI MMC + commands. + */ +typedef struct scsi_mmc_cdb { + uint8_t field[MAX_CDB_LEN]; +} scsi_mmc_cdb_t; + +/*! \brief Format of header block in data returned from a SCSI-MMC + GET_CONFIGURATION command. + */ +typedef struct scsi_mmc_feature_list_header { + unsigned char length_msb; + unsigned char length_1sb; + unsigned char length_2sb; + unsigned char length_lsb; + unsigned char reserved1; + unsigned char reserved2; + unsigned char profile_msb; + unsigned char profile_lsb; +} scs_mmc_feature_list_header_t; + +/*! An enumeration indicating whether a SCSI MMC command is sending + data or getting data. + */ +typedef enum scsi_mmc_direction { + SCSI_MMC_DATA_READ, + SCSI_MMC_DATA_WRITE +} scsi_mmc_direction_t; + +#define CDIO_MMC_SET_COMMAND(cdb, command) \ + cdb[0] = command + +#define CDIO_MMC_SET_READ_TYPE(cdb, sector_type) \ + cdb[1] = (sector_type << 2) + +#define CDIO_MMC_GET_LEN16(p) \ + (p[0]<<8) + p[1] + +#define CDIO_MMC_GET_LEN32(p) \ + (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3]; + +#define CDIO_MMC_SET_LEN16(cdb, pos, len) \ + cdb[pos ] = (len >> 8) & 0xff; \ + cdb[pos+1] = (len ) & 0xff + +#define CDIO_MMC_SET_READ_LBA(cdb, lba) \ + cdb[2] = (lba >> 24) & 0xff; \ + cdb[3] = (lba >> 16) & 0xff; \ + cdb[4] = (lba >> 8) & 0xff; \ + cdb[5] = (lba ) & 0xff + +#define CDIO_MMC_SET_START_TRACK(cdb, command) \ + cdb[6] = command + +#define CDIO_MMC_SET_READ_LENGTH24(cdb, len) \ + cdb[6] = (len >> 16) & 0xff; \ + cdb[7] = (len >> 8) & 0xff; \ + cdb[8] = (len ) & 0xff + +#define CDIO_MMC_SET_READ_LENGTH16(cdb, len) \ + CDIO_MMC_SET_LEN16(cdb, 7, len) + +#define CDIO_MMC_SET_READ_LENGTH8(cdb, len) \ + cdb[8] = (len ) & 0xff + +#define CDIO_MMC_MCSB_ALL_HEADERS 0x78 + +#define CDIO_MMC_SET_MAIN_CHANNEL_SELECTION_BITS(cdb, val) \ + cdb[9] = val; + +/*! + Return the number of length in bytes of the Command Descriptor + buffer (CDB) for a given SCSI MMC command. The length will be + either 6, 10, or 12. +*/ +uint8_t scsi_mmc_get_cmd_len(uint8_t scsi_cmd); + + +/*! + Run a SCSI MMC command. + + cdio CD structure set by cdio_open(). + i_timeout_ms time in milliseconds we will wait for the command + to complete. + p_cdb CDB bytes. All values that are needed should be set on + input. We'll figure out what the right CDB length should be. + e_direction direction the transfer is to go. + i_buf Size of buffer + p_buf Buffer for data, both sending and receiving. + + Returns 0 if command completed successfully. + */ +int scsi_mmc_run_cmd( const CdIo *p_cdio, unsigned int i_timeout_ms, + const scsi_mmc_cdb_t *p_cdb, + scsi_mmc_direction_t e_direction, unsigned int i_buf, + /*in/out*/ void *p_buf ); + +/*! + * Eject using SCSI MMC commands. Return 0 if successful. + */ +int scsi_mmc_eject_media( const CdIo *p_cdio); + +/*! Packet driver to read mode2 sectors. + Can read only up to 25 blocks. +*/ +int scsi_mmc_read_sectors ( const CdIo *p_cdio, void *p_buf, lba_t lba, + int sector_type, unsigned int nblocks); + +/*! + Set the block size for subsequest read requests, via a SCSI MMC + MODE_SELECT 6 command. + */ +int scsi_mmc_set_blocksize ( const CdIo *p_cdio, unsigned int bsize); + +/*! + Return the the kind of drive capabilities of device. + */ +void scsi_mmc_get_drive_cap (const CdIo *p_cdio, + /*out*/ cdio_drive_read_cap_t *p_read_cap, + /*out*/ cdio_drive_write_cap_t *p_write_cap, + /*out*/ cdio_drive_misc_cap_t *p_misc_cap); + +/*! + Get the DVD type associated with cd object. +*/ +discmode_t scsi_mmc_get_dvd_struct_physical ( const CdIo *p_cdio, + cdio_dvd_struct_t *s); + +/*! + Get the CD-ROM hardware info via a SCSI MMC INQUIRY command. + False is returned if we had an error getting the information. +*/ +bool scsi_mmc_get_hwinfo ( const CdIo *p_cdio, + /* out*/ cdio_hwinfo_t *p_hw_info ); + + +/*! + Get the media catalog number (MCN) from the CD via MMC. + + @return the media catalog number r NULL if there is none or we + don't have the ability to get it. + + Note: string is malloc'd so caller has to free() the returned + string when done with it. + +*/ +char *scsi_mmc_get_mcn ( const CdIo *p_cdio ); + +#endif /* __SCSI_MMC_H__ */ diff --git a/src/input/vcd/libcdio/cdio/sector.h b/src/input/vcd/libcdio/cdio/sector.h index 939515543..826883aea 100644 --- a/src/input/vcd/libcdio/cdio/sector.h +++ b/src/input/vcd/libcdio/cdio/sector.h @@ -1,8 +1,8 @@ /* - $Id: sector.h,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: sector.h,v 1.3 2005/01/01 02:43:58 rockyb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> - Copyright (C) 2003 Rocky Bernstein <rocky@panix.com> + Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> 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 @@ -67,7 +67,60 @@ #include <cdio/types.h> -#define CDIO_PREGAP_SECTORS 150 +/*! track modes (Table 350) + reference: MMC-3 draft revsion - 10g +*/ +typedef enum { + AUDIO, /**< 2352 byte block length */ + MODE1, /**< 2048 byte block length */ + MODE1_RAW, /**< 2352 byte block length */ + MODE2, /**< 2336 byte block length */ + MODE2_FORM1, /**< 2048 byte block length */ + MODE2_FORM2, /**< 2324 byte block length */ + MODE2_FORM_MIX, /**< 2336 byte block length */ + MODE2_RAW /**< 2352 byte block length */ +} trackmode_t; + +/*! disc modes. The first combined from MMC-3 5.29.2.8 (Send CUESHEET) + and GNU/Linux /usr/include/linux/cdrom.h and we've added DVD. + */ +typedef enum { + CDIO_DISC_MODE_CD_DA, /**< CD-DA */ + CDIO_DISC_MODE_CD_DATA, /**< CD-ROM form 1 */ + CDIO_DISC_MODE_CD_XA, /**< CD-ROM XA form2 */ + CDIO_DISC_MODE_CD_MIXED, /**< Some combo of above. */ + CDIO_DISC_MODE_DVD_ROM, /**< DVD ROM (e.g. movies) */ + CDIO_DISC_MODE_DVD_RAM, /**< DVD-RAM */ + CDIO_DISC_MODE_DVD_R, /**< DVD-R */ + CDIO_DISC_MODE_DVD_RW, /**< DVD-RW */ + CDIO_DISC_MODE_DVD_PR, /**< DVD+R */ + CDIO_DISC_MODE_DVD_PRW, /**< DVD+RW */ + CDIO_DISC_MODE_DVD_OTHER, /**< Unknown/unclassified DVD type */ + CDIO_DISC_MODE_NO_INFO, + CDIO_DISC_MODE_ERROR +} discmode_t; + +/*! Information that can be obtained through a Read Subchannel + command. + */ +#define CDIO_SUBCHANNEL_SUBQ_DATA 0 +#define CDIO_SUBCHANNEL_CURRENT_POSITION 1 +#define CDIO_SUBCHANNEL_MEDIA_CATALOG 2 +#define CDIO_SUBCHANNEL_TRACK_ISRC 3 + +/*! track flags + * Q Sub-channel Control Field (4.2.3.3) + */ +typedef enum { + NONE = 0x00, /* no flags set */ + PRE_EMPHASIS = 0x01, /* audio track recorded with pre-emphasis */ + COPY_PERMITTED = 0x02, /* digital copy permitted */ + DATA = 0x04, /* data track */ + FOUR_CHANNEL_AUDIO = 0x08, /* 4 audio channels */ + SCMS = 0x10 /* SCMS (5.29.2.7) */ +} flag_t; + +#define CDIO_PREGAP_SECTORS 150 #define CDIO_POSTGAP_SECTORS 150 /* @@ -75,25 +128,28 @@ This is from linux.h - not to slight other OS's. This was the first place I came across such useful stuff. */ -#define CDIO_CD_MINS 74 /**< max. minutes per CD, not really - a limit */ -#define CDIO_CD_SECS_PER_MIN 60 /**< seconds per minute */ -#define CDIO_CD_FRAMES_PER_SEC 75 /**< frames per second */ -#define CDIO_CD_SYNC_SIZE 12 /**< 12 sync bytes per raw data frame */ -#define CDIO_CD_CHUNK_SIZE 24 /**< lowest-level "data bytes piece" */ -#define CDIO_CD_NUM_OF_CHUNKS 98 /**< chunks per frame */ -#define CDIO_CD_FRAMESIZE_SUB 96 /**< subchannel data "frame" size */ -#define CDIO_CD_HEADER_SIZE 4 /**< header (address) bytes per raw - data frame */ -#define CDIO_CD_SUBHEADER_SIZE 8 /**< subheader bytes per raw XA data frame */ -#define CDIO_CD_EDC_SIZE 4 /**< bytes EDC per most raw data - frame types */ -#define CDIO_CD_M1F1_ZERO_SIZE 8 /**< bytes zero per yellow book mode - 1 frame */ -#define CDIO_CD_ECC_SIZE 276 /**< bytes ECC per most raw data frame types */ -#define CDIO_CD_FRAMESIZE 2048 /**< bytes per frame, "cooked" mode */ -#define CDIO_CD_FRAMESIZE_RAW 2352/**< bytes per frame, "raw" mode */ -#define CDIO_CD_FRAMESIZE_RAWER 2646 /**< The maximum possible returned bytes */ +#define CDIO_CD_MINS 74 /**< max. minutes per CD, not really + a limit */ +#define CDIO_CD_SECS_PER_MIN 60 /**< seconds per minute */ +#define CDIO_CD_FRAMES_PER_SEC 75 /**< frames per second */ +#define CDIO_CD_SYNC_SIZE 12 /**< 12 sync bytes per raw data frame */ +#define CDIO_CD_CHUNK_SIZE 24 /**< lowest-level "data bytes piece" */ +#define CDIO_CD_NUM_OF_CHUNKS 98 /**< chunks per frame */ +#define CDIO_CD_FRAMESIZE_SUB 96 /**< subchannel data "frame" size */ +#define CDIO_CD_HEADER_SIZE 4 /**< header (address) bytes per raw + data frame */ +#define CDIO_CD_SUBHEADER_SIZE 8 /**< subheader bytes per raw XA data + frame */ +#define CDIO_CD_EDC_SIZE 4 /**< bytes EDC per most raw data + frame types */ +#define CDIO_CD_M1F1_ZERO_SIZE 8 /**< bytes zero per yellow book mode + 1 frame */ +#define CDIO_CD_ECC_SIZE 276 /**< bytes ECC per most raw data frame + types */ +#define CDIO_CD_FRAMESIZE 2048 /**< bytes per frame, "cooked" mode */ +#define CDIO_CD_FRAMESIZE_RAW 2352 /**< bytes per frame, "raw" mode */ +#define CDIO_CD_FRAMESIZE_RAWER 2646 /**< The maximum possible returned + bytes */ #define CDIO_CD_FRAMESIZE_RAW1 (CDIO_CD_CD_FRAMESIZE_RAW-CDIO_CD_SYNC_SIZE) /*2340*/ #define CDIO_CD_FRAMESIZE_RAW0 (CDIO_CD_FRAMESIZE_RAW-CDIO_CD_SYNC_SIZE-CDIO_CD__HEAD_SIZE) /*2336*/ @@ -106,22 +162,43 @@ /*! "before data" sync bytes + header of XA (green, mode2) frame */ #define CDIO_CD_XA_SYNC_HEADER (CDIO_CD_SYNC_SIZE+CDIO_CD_XA_HEADER) -/* CD-ROM address types (Linux cdrom_tocentry.cdte_format) */ +/*! CD-ROM address types (GNU/Linux e.g. cdrom_tocentry.cdte_format) */ #define CDIO_CDROM_LBA 0x01 /**< "logical block": first frame is #0 */ #define CDIO_CDROM_MSF 0x02 /**< "minute-second-frame": binary, not BCD here! */ +/*! CD-ROM track format types (GNU/Linux cdte_ctrl) */ #define CDIO_CDROM_DATA_TRACK 0x04 - -/*! The leadout track is always 0xAA, regardless of # of tracks on disc */ +#define CDIO_CDROM_CDI_TRACK 0x10 +#define CDIO_CDROM_XA_TRACK 0x20 + +/*! The leadout track is always 0xAA, regardless of # of tracks on + disc, or what value may be used internally. For example although + OS X uses a different value for the lead-out track internally than + given below, programmers should use CDIO_CDROM_LEADOUT_TRACK and + not worry about this. + */ #define CDIO_CDROM_LEADOUT_TRACK 0xAA #define M2F2_SECTOR_SIZE 2324 #define M2SUB_SECTOR_SIZE 2332 #define M2RAW_SECTOR_SIZE 2336 -#define CDIO_CD_MAX_TRACKS 99 -#define CDIO_CD_MIN_TRACK_NO 1 +/*! Largest CD track number */ +#define CDIO_CD_MAX_TRACKS 99 +/*! Smallest CD track number */ +#define CDIO_CD_MIN_TRACK_NO 1 + +/*! Largest CD session number */ +#define CDIO_CD_MAX_SESSIONS 99 +/*! Smallest CD session number */ +#define CDIO_CD_MIN_SESSION_NO 1 + +/*! Largest LSN in a CD */ +#define CDIO_CD_MAX_LSN 450150 +/*! Smallest LSN in a CD */ +#define CDIO_CD_MIN_LSN -450150 + #define CDIO_CD_FRAMES_PER_MIN \ (CDIO_CD_FRAMES_PER_SEC*CDIO_CD_SECS_PER_MIN) @@ -141,6 +218,11 @@ char *cdio_lba_to_msf_str (lba_t lba); /*! + Convert an MSF into a string representation of the MSF. + \warning cdio_msf_to_msf_str returns new allocated string */ +char *cdio_msf_to_str (const msf_t *msf); + +/*! Convert an LBA into the corresponding LSN. */ lba_t cdio_lba_to_lsn (lba_t lba); @@ -152,6 +234,7 @@ void cdio_lba_to_msf(lba_t lba, msf_t *msf); /*! Convert an LSN into the corresponding LBA. + CDIO_INVALID_LBA is returned if there is an error. */ lba_t cdio_lsn_to_lba (lsn_t lsn); @@ -162,20 +245,75 @@ void cdio_lsn_to_msf (lsn_t lsn, msf_t *msf); /*! Convert a MSF into the corresponding LBA. + CDIO_INVALID_LBA is returned if there is an error. */ -lba_t -cdio_msf_to_lba (const msf_t *msf); +lba_t cdio_msf_to_lba (const msf_t *msf); /*! Convert a MSF into the corresponding LSN. + CDIO_INVALID_LSN is returned if there is an error. */ -lsn_t -cdio_msf_to_lsn (const msf_t *msf); +lsn_t cdio_msf_to_lsn (const msf_t *msf); + +/*! + Convert a MSF - broken out as 3 integer components into the + corresponding LBA. + CDIO_INVALID_LBA is returned if there is an error. +*/ +lba_t cdio_msf3_to_lba (unsigned int minutes, unsigned int seconds, + unsigned int frames); + +/*! + Convert a string of the form MM:SS:FF into the corresponding LBA. + CDIO_INVALID_LBA is returned if there is an error. +*/ +lba_t cdio_mmssff_to_lba (const char *psz_mmssff); + +/*! + Return true if discmode is some sort of CD. +*/ +bool cdio_is_discmode_cdrom (discmode_t discmode); + +/*! + Return true if discmode is some sort of DVD. +*/ +bool cdio_is_discmode_dvd (discmode_t discmode); + #ifdef __cplusplus } #endif +static inline bool discmode_is_cd(discmode_t discmode) +{ + switch (discmode) { + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_DATA: + case CDIO_DISC_MODE_CD_XA: + case CDIO_DISC_MODE_CD_MIXED: + return true; + default: + return false; + } +} + +static inline bool discmode_is_dvd(discmode_t discmode) +{ + switch (discmode) { + case CDIO_DISC_MODE_DVD_ROM: + case CDIO_DISC_MODE_DVD_RAM: + case CDIO_DISC_MODE_DVD_R: + case CDIO_DISC_MODE_DVD_RW: + case CDIO_DISC_MODE_DVD_PR: + case CDIO_DISC_MODE_DVD_PRW: + case CDIO_DISC_MODE_DVD_OTHER: + return true; + default: + return false; + } +} + + #endif /* _CDIO_SECTOR_H_ */ diff --git a/src/input/vcd/libcdio/cdio/types.h b/src/input/vcd/libcdio/cdio/types.h index c4b0b0934..ec84a142b 100644 --- a/src/input/vcd/libcdio/cdio/types.h +++ b/src/input/vcd/libcdio/cdio/types.h @@ -1,5 +1,5 @@ /* - $Id: types.h,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: types.h,v 1.3 2005/01/01 02:43:58 rockyb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com> @@ -106,11 +106,11 @@ extern "C" { { false = 0, true = 1 - } _Bool; + } _cdio_Bool; # define false false # define true true -# define bool _Bool +# define bool _cdio_Bool # endif #endif @@ -204,16 +204,21 @@ extern "C" { typedef uint8_t bitfield_t; #endif - /*! The type of a Logical Block Address. + /*! The type of a Logical Block Address. We allow for an lba to be + negative to be consistent with an lba, although I'm not sure this + this is possible. + + */ + typedef int32_t lba_t; + + /*! The type of a Logical Sector Number. Note that an lba lsn be negative + and the MMC3 specs allow for a conversion of a negative lba @see msf_t */ - typedef uint32_t lba_t; - - /*! The type of an Logical Sector Number. */ - typedef uint32_t lsn_t; + typedef int32_t lsn_t; - /*! The type of an track number 0..99. */ + /*! The type of a track number 0..99. */ typedef uint8_t track_t; /*! @@ -221,17 +226,142 @@ extern "C" { */ #define CDIO_INVALID_TRACK 0xFF + /*! The type of a session number 0..99. */ + typedef uint8_t session_t; + /*! - Constant for invalid LBA + Constant for invalid session number */ -#define CDIO_INVALID_LBA 0xFFFFFFFF +#define CDIO_INVALID_SESSION 0xFF + + /*! + Constant for invalid LBA. It is 151 less than the most negative + LBA -45150. This provide slack for the 150-frame offset in + LBA to LSN 150 conversions + */ +#define CDIO_INVALID_LBA -45301 /*! Constant for invalid LSN */ -#define CDIO_INVALID_LSN 0xFFFFFFFF +#define CDIO_INVALID_LSN CDIO_INVALID_LBA + + /*! + Number of ASCII bytes in a media catalog number (MCN). + */ +#define CDIO_MCN_SIZE 13 + + /*! + Type to hold ASCII bytes in a media catalog number (MCN). + We include an extra 0 byte so these can be used as C strings. + */ + typedef char cdio_mcn_t[CDIO_MCN_SIZE+1]; + + + /*! + Number of ASCII bytes in International Standard Recording Codes (ISRC) + */ +#define CDIO_ISRC_SIZE 12 -typedef int cdio_fs_anal_t; + /*! + Type to hold ASCII bytes in a media catalog number (MCN). + We include an extra 0 byte so these can be used as C strings. + */ + typedef char cdio_isrc_t[CDIO_ISRC_SIZE+1]; + + typedef int cdio_fs_anal_t; + + /*! The type of an drive capability bit mask. See below for values*/ + typedef uint32_t cdio_drive_read_cap_t; + typedef uint32_t cdio_drive_write_cap_t; + typedef uint32_t cdio_drive_misc_cap_t; + + /*! + \brief Drive types returned by cdio_get_drive_cap() + + NOTE: Setting a bit here means the presence of a capability. + */ + +#define CDIO_DRIVE_CAP_ERROR 0x40000 /**< Error */ +#define CDIO_DRIVE_CAP_UNKNOWN 0x80000 /**< Dunno. It can be on if we + have only partial information + or are not completely certain + */ + +#define CDIO_DRIVE_CAP_MISC_CLOSE_TRAY 0x00001 /**< caddy systems can't + close... */ +#define CDIO_DRIVE_CAP_MISC_EJECT 0x00002 /**< but can eject. */ +#define CDIO_DRIVE_CAP_MISC_LOCK 0x00004 /**< disable manual eject */ +#define CDIO_DRIVE_CAP_MISC_SELECT_SPEED 0x00008 /**< programmable speed */ +#define CDIO_DRIVE_CAP_MISC_SELECT_DISC 0x00010 /**< select disc from + juke-box */ +#define CDIO_DRIVE_CAP_MISC_MULTI_SESSION 0x00020 /**< read sessions>1 */ +#define CDIO_DRIVE_CAP_MISC_MEDIA_CHANGED 0x00080 /**< media changed */ +#define CDIO_DRIVE_CAP_MISC_RESET 0x00100 /**< hard reset device */ +#define CDIO_DRIVE_CAP_MCN 0x00200 /**< can read MCN */ +#define CDIO_DRIVE_CAP_ISRC 0x00200 /**< can read ISRC */ +#define CDIO_DRIVE_CAP_MISC_FILE 0x20000 /**< drive is really a file, + i.e a CD file image */ + + /*! Reading masks.. */ +#define CDIO_DRIVE_CAP_READ_AUDIO 0x00001 /**< drive can play CD audio */ +#define CDIO_DRIVE_CAP_READ_CD_DA 0x00002 /**< drive can read CD-DA */ +#define CDIO_DRIVE_CAP_READ_CD_G 0x00004 /**< drive can read CD+G */ +#define CDIO_DRIVE_CAP_READ_CD_R 0x00008 /**< drive can read CD-R */ +#define CDIO_DRIVE_CAP_READ_CD_RW 0x00010 /**< drive can read CD-RW */ +#define CDIO_DRIVE_CAP_READ_DVD_R 0x00020 /**< drive can read DVD-R */ +#define CDIO_DRIVE_CAP_READ_DVD_PR 0x00040 /**< drive can read DVD+R */ +#define CDIO_DRIVE_CAP_READ_DVD_RAM 0x00080 /**< drive can read DVD-RAM */ +#define CDIO_DRIVE_CAP_READ_DVD_ROM 0x00100 /**< drive can read DVD-ROM */ +#define CDIO_DRIVE_CAP_READ_DVD_RW 0x00200 /**< drive can read DVD-RW */ +#define CDIO_DRIVE_CAP_READ_DVD_RPW 0x00400 /**< drive can read DVD+RW */ +#define CDIO_DRIVE_CAP_READ_C2_ERRS 0x00800 /**< has C2 error correction */ + + /*! Writing masks.. */ +#define CDIO_DRIVE_CAP_WRITE_CD_R 0x00001 /**< drive can write CD-R */ +#define CDIO_DRIVE_CAP_WRITE_CD_RW 0x00002 /**< drive can write CD-R */ +#define CDIO_DRIVE_CAP_WRITE_DVD_R 0x00004 /**< drive can write DVD-R */ +#define CDIO_DRIVE_CAP_WRITE_DVD_PR 0x00008 /**< drive can write DVD+R */ +#define CDIO_DRIVE_CAP_WRITE_DVD_RAM 0x00010 /**< drive can write DVD-RAM */ +#define CDIO_DRIVE_CAP_WRITE_DVD_RW 0x00020 /**< drive can write DVD-RW */ +#define CDIO_DRIVE_CAP_WRITE_DVD_RPW 0x00040 /**< drive can write DVD+RW */ +#define CDIO_DRIVE_CAP_WRITE_MT_RAINIER 0x00080 /**< Mount Rainier */ +#define CDIO_DRIVE_CAP_WRITE_BURN_PROOF 0x00100 /**< burn proof */ + +/**< Masks derived from above... */ +#define CDIO_DRIVE_CAP_WRITE_CD ( \ + CDIO_DRIVE_CAP_WRITE_CD_R \ + | CDIO_DRIVE_CAP_WRITE_CD_RW \ + ) +/**< Has some sort of CD writer ability */ + +/**< Masks derived from above... */ +#define CDIO_DRIVE_CAP_WRITE_DVD ( \ + | CDIO_DRIVE_CAP_WRITE_DVD_R \ + | CDIO_DRIVE_CAP_WRITE_DVD_PR \ + | CDIO_DRIVE_CAP_WRITE_DVD_RAM \ + | CDIO_DRIVE_CAP_WRITE_DVD_RW \ + | CDIO_DRIVE_CAP_WRITE_DVD_RPW \ + ) +/**< Has some sort of DVD writer ability */ + +#define CDIO_DRIVE_CAP_WRITE \ + (CDIO_DRIVE_CAP_WRITE_CD | CDIO_DRIVE_CAP_WRITE_DVD) +/**< Has some sort of DVD or CD writing ability */ + + /*! + track flags + Q Sub-channel Control Field (4.2.3.3) + */ + typedef enum { + CDIO_TRACK_FLAG_NONE = 0x00, /**< no flags set */ + CDIO_TRACK_FLAG_PRE_EMPHASIS = 0x01, /**< audio track recorded with + pre-emphasis */ + CDIO_TRACK_FLAG_COPY_PERMITTED = 0x02, /**< digital copy permitted */ + CDIO_TRACK_FLAG_DATA = 0x04, /**< data track */ + CDIO_TRACK_FLAG_FOUR_CHANNEL_AUDIO = 0x08, /**< 4 audio channels */ + CDIO_TRACK_FLAG_SCMS = 0x10 /**< SCMS (5.29.2.7) */ +} cdio_track_flag; #ifdef __cplusplus } diff --git a/src/input/vcd/libcdio/cdio/util.h b/src/input/vcd/libcdio/cdio/util.h index 5142653ad..3cea313b4 100644 --- a/src/input/vcd/libcdio/cdio/util.h +++ b/src/input/vcd/libcdio/cdio/util.h @@ -1,7 +1,8 @@ /* - $Id: util.h,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: util.h,v 1.3 2005/01/01 02:43:58 rockyb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> + Copyright (C) 2004 Rocky Bernstein <rocky@panix.com> 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 @@ -71,6 +72,16 @@ _cdio_ofs_add (unsigned offset, unsigned length, int blocksize) return offset; } +static inline const char * +_cdio_bool_str (bool b) +{ + return b ? "yes" : "no"; +} + +#ifdef __cplusplus +extern "C" { +#endif + void * _cdio_malloc (size_t size); @@ -92,16 +103,26 @@ _cdio_strlenv(char **str_array); char ** _cdio_strsplit(const char str[], char delim); -static inline const char * -_cdio_bool_str (bool b) -{ - return b ? "yes" : "no"; -} +uint8_t cdio_to_bcd8(uint8_t n); +uint8_t cdio_from_bcd8(uint8_t p); -/* BCD */ +#if defined(__GNUC__) && __GNUC__ >= 3 +static inline __attribute__((deprecated)) +uint8_t to_bcd8(uint8_t n) { + return cdio_to_bcd8(n); +} +static inline __attribute__((deprecated)) +uint8_t from_bcd8(uint8_t p) { + return cdio_from_bcd8(p); +} +#else +#define to_bcd8 cdio_to_bcd8 +#define from_bcd8 cdio_from_bcd8 +#endif -uint8_t to_bcd8(uint8_t n); -uint8_t from_bcd8(uint8_t p); +#ifdef __cplusplus +} +#endif #endif /* __CDIO_UTIL_H__ */ diff --git a/src/input/vcd/libcdio/cdio/xa.h b/src/input/vcd/libcdio/cdio/xa.h index 5ff7addd4..3af27eab5 100644 --- a/src/input/vcd/libcdio/cdio/xa.h +++ b/src/input/vcd/libcdio/cdio/xa.h @@ -1,5 +1,5 @@ /* - $Id: xa.h,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: xa.h,v 1.3 2005/01/01 02:43:58 rockyb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> @@ -66,7 +66,7 @@ #define XA_FORM1_FILE (XA_ATTR_MODE2FORM1 | XA_PERM_ALL_ALL) #define XA_FORM2_FILE (XA_ATTR_MODE2FORM2 | XA_PERM_ALL_ALL) -/*! \brief "Extended Architecture according t the Philips Yellow Book. +/*! \brief "Extended Architecture according to the Philips Yellow Book. CD-ROM EXtended Architecture is a modification to the CD-ROM specification that defines two new types of sectors. CD-ROM XA was diff --git a/src/input/vcd/libcdio/cdio_private.h b/src/input/vcd/libcdio/cdio_private.h index c1106e694..b1e2777ed 100644 --- a/src/input/vcd/libcdio/cdio_private.h +++ b/src/input/vcd/libcdio/cdio_private.h @@ -1,5 +1,5 @@ /* - $Id: cdio_private.h,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: cdio_private.h,v 1.3 2005/01/01 02:43:57 rockyb Exp $ Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> @@ -29,6 +29,8 @@ #endif #include <cdio/cdio.h> +#include <cdio/cdtext.h> +#include "scsi_mmc_private.h" #ifdef __cplusplus extern "C" { @@ -37,6 +39,18 @@ extern "C" { /* Opaque type */ typedef struct _CdioDataSource CdioDataSource; +#ifdef __cplusplus +} + +#endif /* __cplusplus */ + +#include "generic.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + typedef struct { /*! @@ -55,6 +69,18 @@ extern "C" { */ const char * (*get_arg) (void *env, const char key[]); + /*! + Get cdtext information for a CdIo object. + + @param obj the CD object that may contain CD-TEXT information. + @return the CD-TEXT object or NULL if obj is NULL + or CD-TEXT information does not exist. + + If i_track is 0 or CDIO_CDROM_LEADOUT_TRACK the track returned + is the information assocated with the CD. + */ + const cdtext_t * (*get_cdtext) (void *env, track_t i_track); + /*! Return an array of device names. if CdIo is NULL (we haven't initialized a specific device driver), then find a suitable device @@ -69,19 +95,40 @@ extern "C" { */ char * (*get_default_device)(void); - /*! - Return the media catalog number MCN from the CD or NULL if - there is none or we don't have the ability to get it. + /*! + Get disc mode associated with cd_obj. */ - char * (*get_mcn) (void *env); + discmode_t (*get_discmode) (void *p_env); /*! + Return the what kind of device we've got. + + See cd_types.h for a list of bitmasks for the drive type; + */ + void (*get_drive_cap) (const void *env, + cdio_drive_read_cap_t *p_read_cap, + cdio_drive_write_cap_t *p_write_cap, + cdio_drive_misc_cap_t *p_misc_cap); + /*! Return the number of of the first track. CDIO_INVALID_TRACK is returned on error. */ - track_t (*get_first_track_num) (void *env); + track_t (*get_first_track_num) (void *p_env); /*! + Get the CD-ROM hardware info via a SCSI MMC INQUIRY command. + False is returned if we had an error getting the information. + */ + bool (*get_hwinfo) ( const CdIo *p_cdio, + /* out*/ cdio_hwinfo_t *p_hw_info ); + + /*! + Return the media catalog number MCN from the CD or NULL if + there is none or we don't have the ability to get it. + */ + char * (*get_mcn) (const void *env); + + /*! Return the number of tracks in the current medium. CDIO_INVALID_TRACK is returned on error. */ @@ -153,14 +200,14 @@ extern "C" { from lsn. Returns 0 if no error. */ - int (*read_mode2_sectors) (void *env, void *buf, lsn_t lsn, + int (*read_mode2_sectors) (void *p_env, void *p_buf, lsn_t lsn, bool mode2_form2, unsigned int nblocks); /*! Reads a single mode1 sector from cd device into buf starting from lsn. Returns 0 if no error. */ - int (*read_mode1_sector) (void *env, void *buf, lsn_t lsn, + int (*read_mode1_sector) (void *p_env, void *p_buf, lsn_t lsn, bool mode1_form2); /*! @@ -168,9 +215,29 @@ extern "C" { from lsn. Returns 0 if no error. */ - int (*read_mode1_sectors) (void *env, void *buf, lsn_t lsn, + int (*read_mode1_sectors) (void *p_env, void *p_buf, lsn_t lsn, bool mode1_form2, unsigned int nblocks); + bool (*read_toc) ( void *p_env ) ; + + /*! + Run a SCSI MMC command. + + cdio CD structure set by cdio_open(). + i_timeout_ms time in milliseconds we will wait for the command + to complete. + cdb_len number of bytes in cdb (6, 10, or 12). + cdb CDB bytes. All values that are needed should be set on + input. + b_return_data TRUE if the command expects data to be returned in + the buffer + len Size of buffer + buf Buffer for data, both sending and receiving + + Returns 0 if command completed successfully. + */ + scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd; + /*! Set the arg "key" with "value" in the source device. */ @@ -180,36 +247,18 @@ extern "C" { Return the size of the CD in logical block address (LBA) units. */ uint32_t (*stat_size) (void *env); - + } cdio_funcs; - /* Implementation of CdIo type */ + /*! Implementation of CdIo type */ struct _CdIo { - driver_id_t driver_id; /* Particular driver opened. */ - cdio_funcs op; /* driver-specific routines handling implimentatin*/ - void *env; /* environment. Passed to routine above. */ + driver_id_t driver_id; /**< Particular driver opened. */ + cdio_funcs op; /**< driver-specific routines handling + implementation*/ + void *env; /**< environment. Passed to routine above. */ }; - /*! - Things common to private device structures. Even though not all - devices may have some of these fields, by listing common ones - we facilitate writing generic routines and even cut-and-paste - code. - */ - typedef struct { - char *source_name; /* Name used in open. */ - bool init; /* True if structure has been initialized */ - bool toc_init; /* True TOC read in */ - int ioctls_debugged; /* for debugging */ - - /* Only one of the below is used. The first is for CD-ROM devices - and the second for stream reading (bincue, nrg, toc, network). - */ - int fd; /* File descriptor of device */ - CdioDataSource *data_source; - } generic_img_private_t; - /* This is used in drivers that must keep their own internal position pointer for doing seeks. Stream-based drivers (like bincue, nrg, toc, network) would use this. @@ -221,7 +270,7 @@ extern "C" { lba_t lba; /* Current LBA */ } internal_position_t; - CdIo * cdio_new (void *env, const cdio_funcs *funcs); + CdIo * cdio_new (generic_img_private_t *p_env, cdio_funcs *funcs); /* The below structure describes a specific CD Input driver */ typedef struct @@ -231,9 +280,11 @@ extern "C" { const char *name; const char *describe; bool (*have_driver) (void); - CdIo *(*driver_open) (const char *source_name); + CdIo *(*driver_open) (const char *psz_source_name); + CdIo *(*driver_open_am) (const char *psz_source_name, + const char *psz_access_mode); char *(*get_default_device) (void); - bool (*is_device) (const char *source_name); + bool (*is_device) (const char *psz_source_name); char **(*get_devices) (void); } CdIo_driver_t; @@ -255,63 +306,8 @@ extern "C" { Use cdio_free_device_list() to free this device_list. */ void cdio_add_device_list(char **device_list[], const char *drive, - int *num_drives); - - /*! - Bogus eject media when there is no ejectable media, e.g. a disk image - We always return 2. Should we also free resources? - */ - int cdio_generic_bogus_eject_media (void *env); - - /*! - Release and free resources associated with cd. - */ - void cdio_generic_free (void *env); - - /*! - Initialize CD device. - */ - bool cdio_generic_init (void *env); + unsigned int *i_drives); - /*! - Reads into buf the next size bytes. - Returns -1 on error. - Is in fact libc's read(). - */ - off_t cdio_generic_lseek (void *env, off_t offset, int whence); - - /*! - Reads into buf the next size bytes. - Returns -1 on error. - Is in fact libc's read(). - */ - ssize_t cdio_generic_read (void *env, void *buf, size_t size); - - /*! - Release and free resources associated with stream or disk image. - */ - void cdio_generic_stdio_free (void *env); - - /*! - Return true if source_name could be a device containing a CD-ROM on - Win32 - */ - bool cdio_is_device_win32(const char *source_name); - - - /*! - Return true if source_name could be a device containing a CD-ROM on - most Unix servers with block and character devices. - */ - bool cdio_is_device_generic(const char *source_name); - - - /*! - Like above, but don't give a warning device doesn't exist. - */ - bool cdio_is_device_quiet_generic(const char *source_name); - - #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/input/vcd/libcdio/cdtext.c b/src/input/vcd/libcdio/cdtext.c new file mode 100644 index 000000000..5842641f7 --- /dev/null +++ b/src/input/vcd/libcdio/cdtext.c @@ -0,0 +1,228 @@ +/* + $Id: cdtext.c,v 1.1 2005/01/01 02:43:57 rockyb Exp $ + + Copyright (C) 2004 Rocky Bernstein <rocky@panix.com> + toc reading routine adapted from cuetools + Copyright (C) 2003 Svend Sanjay Sorensen <ssorensen@fastmail.fm> + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <cdio/cdtext.h> +#include <cdio/logging.h> +#include "cdtext_private.h" + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif + +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +/*! Note: the order and number items (except CDTEXT_INVALID) should + match the cdtext_field_t enumeration. */ +const char *cdtext_keywords[] = + { + "ARRANGER", + "COMPOSER", + "DISC_ID", + "GENRE", + "ISRC", + "MESSAGE", + "PERFORMER", + "SIZE_INFO", + "SONGWRITER", + "TITLE", + "TOC_INFO", + "TOC_INFO2", + "UPC_EAN", + }; + + +/*! Return string representation of the enum values above */ +const char * +cdtext_field2str (cdtext_field_t i) +{ + if (i >= MAX_CDTEXT_FIELDS) + return "Invalid CDTEXT field index"; + else + return cdtext_keywords[i]; +} + + +/*! Free memory assocated with cdtext*/ +void +cdtext_destroy (cdtext_t *cdtext) +{ + cdtext_field_t i; + + for (i=0; i < MAX_CDTEXT_FIELDS; i++) { + if (cdtext->field[i]) free(cdtext->field[i]); + } +} + +/*! + returns the CDTEXT value associated with key. NULL is returned + if key is CDTEXT_INVALID or the field is not set. + */ +const char * +cdtext_get (cdtext_field_t key, const cdtext_t *cdtext) +{ + if (key == CDTEXT_INVALID) return NULL; + return cdtext->field[key]; +} + +/*! Initialize a new cdtext structure. + When the structure is no longer needed, release the + resources using cdtext_delete. +*/ +void +cdtext_init (cdtext_t *cdtext) +{ + cdtext_field_t i; + + for (i=0; i < MAX_CDTEXT_FIELDS; i++) { + cdtext->field[i] = NULL; + } +} + +/*! + returns 0 if field is a CD-TEXT keyword, returns non-zero otherwise +*/ +cdtext_field_t +cdtext_is_keyword (const char *key) +{ +#if 0 + char *item; + + item = bsearch(key, + cdtext_keywords, 12, + sizeof (char *), + (int (*)(const void *, const void *)) + strcmp); + return (NULL != item) ? 0 : 1; +#else + unsigned int i; + + for (i = 0; i < 13 ; i++) + if (0 == strcmp (cdtext_keywords[i], key)) { + return i; + } + return CDTEXT_INVALID; +#endif +} + +/*! sets cdtext's keyword entry to field. + */ +void +cdtext_set (cdtext_field_t key, const char *value, cdtext_t *cdtext) +{ + if (NULL == value || key == CDTEXT_INVALID) return; + + if (cdtext->field[key]) free (cdtext->field[key]); + cdtext->field[key] = strdup (value); + +} + +#define SET_CDTEXT_FIELD(FIELD) \ + (*set_cdtext_field_fn)(user_data, i_track, i_first_track, FIELD, buffer); + +/* + parse all CD-TEXT data retrieved. +*/ +bool +cdtext_data_init(void *user_data, track_t i_first_track, + unsigned char *wdata, + set_cdtext_field_fn_t set_cdtext_field_fn) +{ + CDText_data_t *pdata; + int i; + int j; + char buffer[256]; + int idx; + int i_track; + bool b_ret = false; + + memset( buffer, 0x00, sizeof(buffer) ); + idx = 0; + + pdata = (CDText_data_t *) (&wdata[4]); + for( i=0; i < CDIO_CDTEXT_MAX_PACK_DATA; i++ ) { + +#if TESTED + if ( pdata->bDBC ) { + cdio_warn("Double-byte characters not supported"); + return false; + } +#endif + + if( pdata->seq != i ) + break; + + if( (pdata->type >= 0x80) + && (pdata->type <= 0x85) && (pdata->block == 0) ) { + i_track = pdata->i_track; + + for( j=0; j < CDIO_CDTEXT_MAX_TEXT_DATA; j++ ) { + if( pdata->text[j] == 0x00 ) { + bool b_field_set=true; + switch( pdata->type) { + case CDIO_CDTEXT_TITLE: + SET_CDTEXT_FIELD(CDTEXT_TITLE); + break; + case CDIO_CDTEXT_PERFORMER: + SET_CDTEXT_FIELD(CDTEXT_PERFORMER); + break; + case CDIO_CDTEXT_SONGWRITER: + SET_CDTEXT_FIELD(CDTEXT_SONGWRITER); + break; + case CDIO_CDTEXT_COMPOSER: + SET_CDTEXT_FIELD(CDTEXT_COMPOSER); + break; + case CDIO_CDTEXT_ARRANGER: + SET_CDTEXT_FIELD(CDTEXT_ARRANGER); + break; + case CDIO_CDTEXT_MESSAGE: + SET_CDTEXT_FIELD(CDTEXT_MESSAGE); + break; + case CDIO_CDTEXT_DISCID: + SET_CDTEXT_FIELD(CDTEXT_DISCID); + break; + case CDIO_CDTEXT_GENRE: + SET_CDTEXT_FIELD(CDTEXT_GENRE); + break; + default : b_field_set = false; + } + if (b_field_set) { + b_ret = true; + i_track++; + idx = 0; + } + } else { + buffer[idx++] = pdata->text[j]; + } + buffer[idx] = 0x00; + } + } + pdata++; + } + return b_ret; +} + diff --git a/src/input/vcd/libcdio/cdtext_private.h b/src/input/vcd/libcdio/cdtext_private.h new file mode 100644 index 000000000..03a9c4945 --- /dev/null +++ b/src/input/vcd/libcdio/cdtext_private.h @@ -0,0 +1,119 @@ +/* + $Id: cdtext_private.h,v 1.1 2005/01/01 02:43:57 rockyb Exp $ + + Copyright (C) 2004 Rocky Bernstein <rocky@panix.com> + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __CDIO_CDTEXT_PRIVATE_H__ +#define __CDIO_CDTEXT_PRIVATE_H__ + +#include <cdio/cdio.h> +#include <cdio/cdtext.h> + +#define CDIO_CDTEXT_MAX_PACK_DATA 255 +#define CDIO_CDTEXT_MAX_TEXT_DATA 12 + +/* From table J.2 - Pack Type Indicator Definitions from + Working Draft NCITS XXX T10/1364-D Revision 10G. November 12, 2001. +*/ +/* Title of Alubm name (ID=0) or Track Titles (ID != 0) */ +#define CDIO_CDTEXT_TITLE 0x80 + +/* Name(s) of the performer(s) in ASCII */ +#define CDIO_CDTEXT_PERFORMER 0x81 + +/* Name(s) of the songwriter(s) in ASCII */ +#define CDIO_CDTEXT_SONGWRITER 0x82 + +/* Name(s) of the Composers in ASCII */ +#define CDIO_CDTEXT_COMPOSER 0x83 + +/* Name(s) of the Arrangers in ASCII */ +#define CDIO_CDTEXT_ARRANGER 0x84 + +/* Message(s) from content provider and/or artist in ASCII */ +#define CDIO_CDTEXT_MESSAGE 0x85 + +/* Disc Identificatin information */ +#define CDIO_CDTEXT_DISCID 0x86 + +/* Genre Identification and Genre Information */ +#define CDIO_CDTEXT_GENRE 0x87 + +/* Table of Content Information */ +#define CDIO_CDTEXT_TOC 0x88 + +/* Second Table of Content Information */ +#define CDIO_CDTEXT_TOC2 0x89 + +/* 0x8A, 0x8B, 0x8C are reserved + 0x8D Reserved for content provider only. + */ + +/* UPC/EAN code of the album and ISRC code of each track */ +#define CDIO_CDTEXT_UPC 0x8E + +/* Size information of the Block */ +#define CDIO_CDTEXT_BLOCKSIZE 0x8F + + +PRAGMA_BEGIN_PACKED + +struct CDText_data +{ + uint8_t type; + track_t i_track; + uint8_t seq; +#ifdef WORDS_BIGENDIAN + uint8_t bDBC: 1; /* double byte character */ + uint8_t block: 3; /* block number 0..7 */ + uint8_t characterPosition:4; /* character position */ +#else + uint8_t characterPosition:4; /* character position */ + uint8_t block :3; /* block number 0..7 */ + uint8_t bDBC :1; /* double byte character */ +#endif + char text[CDIO_CDTEXT_MAX_TEXT_DATA]; + uint8_t crc[2]; +} GNUC_PACKED; + +PRAGMA_END_PACKED + +typedef struct CDText_data CDText_data_t; + +typedef void (*set_cdtext_field_fn_t) (void *user_data, track_t i_track, + track_t i_first_track, + cdtext_field_t field, + const char *buffer); + +/* + Internal routine to parse all CD-TEXT data retrieved. +*/ +bool cdtext_data_init(void *user_data, track_t i_first_track, + unsigned char *wdata, + set_cdtext_field_fn_t set_cdtext_field_fn); + + +#endif /* __CDIO_CDTEXT_PRIVATE_H__ */ + +/* + * Local variables: + * c-file-style: "gnu" + * tab-width: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/input/vcd/libcdio/ds.c b/src/input/vcd/libcdio/ds.c index bc015d79f..381c0f00c 100644 --- a/src/input/vcd/libcdio/ds.c +++ b/src/input/vcd/libcdio/ds.c @@ -1,5 +1,5 @@ /* - $Id: ds.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: ds.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> @@ -25,12 +25,12 @@ #include <stdlib.h> #include <string.h> -#include "ds.h" +#include <cdio/ds.h> #include <cdio/util.h> #include <cdio/types.h> #include "cdio_assert.h" -static const char _rcsid[] = "$Id: ds.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: ds.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $"; struct _CdioList { diff --git a/src/input/vcd/libcdio/generic.h b/src/input/vcd/libcdio/generic.h new file mode 100644 index 000000000..9deb77254 --- /dev/null +++ b/src/input/vcd/libcdio/generic.h @@ -0,0 +1,179 @@ +/* + $Id: generic.h,v 1.1 2005/01/01 02:43:57 rockyb Exp $ + + Copyright (C) 2004 Rocky Bernstein <rocky@panix.com> + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* Internal routines for CD I/O drivers. */ + + +#ifndef __CDIO_GENERIC_H__ +#define __CDIO_GENERIC_H__ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <cdio/cdio.h> +#include <cdio/cdtext.h> +#include <cdio/iso9660.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*! + Things common to private device structures. Even though not all + devices may have some of these fields, by listing common ones + we facilitate writing generic routines and even cut-and-paste + code. + */ + typedef struct { + char *source_name; /**< Name used in open. */ + bool init; /**< True if structure has been initialized */ + bool toc_init; /**< True if TOC read in */ + bool b_cdtext_init; /**< True if CD-Text read in */ + bool b_cdtext_error; /**< True if trouble reading CD-Text */ + + int ioctls_debugged; /**< for debugging */ + + /* Only one of data_source or fd is used; fd is for CD-ROM + devices and the data_source for stream reading (bincue, nrg, toc, + network). + */ + CdioDataSource *data_source; + int fd; /**< File descriptor of device */ + track_t i_first_track; /**< The starting track number. */ + track_t i_tracks; /**< The number of tracks. */ + + uint8_t i_joliet_level; /**< 0 = no Joliet extensions. + 1-3: Joliet level. */ + iso9660_pvd_t pvd; + iso9660_svd_t svd; + CdIo *cdio; /**< a way to call general cdio routines. */ + cdtext_t cdtext; /**< CD-Text for disc. */ + cdtext_t cdtext_track[CDIO_CD_MAX_TRACKS+1]; /*CD-TEXT for each track*/ + + } generic_img_private_t; + + /*! + Bogus eject media when there is no ejectable media, e.g. a disk image + We always return 2. Should we also free resources? + */ + int cdio_generic_bogus_eject_media (void *env); + + /*! + Release and free resources associated with cd. + */ + void cdio_generic_free (void *env); + + /*! + Initialize CD device. + */ + bool cdio_generic_init (void *env); + + /*! + Reads into buf the next size bytes. + Returns -1 on error. + Is in fact libc's read(). + */ + off_t cdio_generic_lseek (void *env, off_t offset, int whence); + + /*! + Reads into buf the next size bytes. + Returns -1 on error. + Is in fact libc's read(). + */ + ssize_t cdio_generic_read (void *env, void *buf, size_t size); + + /*! + Reads a single form1 sector from cd device into data starting + from lsn. Returns 0 if no error. + */ + int cdio_generic_read_form1_sector (void * user_data, void *data, + lsn_t lsn); + + /*! + Release and free resources associated with stream or disk image. + */ + void cdio_generic_stdio_free (void *env); + + /*! + Return true if source_name could be a device containing a CD-ROM on + Win32 + */ + bool cdio_is_device_win32(const char *source_name); + + + /*! + Return true if source_name could be a device containing a CD-ROM on + most Unix servers with block and character devices. + */ + bool cdio_is_device_generic(const char *source_name); + + + /*! + Like above, but don't give a warning device doesn't exist. + */ + bool cdio_is_device_quiet_generic(const char *source_name); + + /*! + Get cdtext information for a CdIo object . + + @param obj the CD object that may contain CD-TEXT information. + @return the CD-TEXT object or NULL if obj is NULL + or CD-TEXT information does not exist. + */ + const cdtext_t *get_cdtext_generic (void *p_user_data, track_t i_track); + + /*! + Return the number of of the first track. + CDIO_INVALID_TRACK is returned on error. + */ + track_t get_first_track_num_generic(void *p_user_data); + + /*! + Return the number of tracks in the current medium. + */ + track_t get_num_tracks_generic(void *p_user_data); + + /*! + Get disc type associated with cd object. + */ + discmode_t get_discmode_generic (void *p_user_data ); + + /*! + Same as above but only handles CD cases + */ + discmode_t get_discmode_cd_generic (void *p_user_data ); + + void set_cdtext_field_generic(void *user_data, track_t i_track, + track_t i_first_track, + cdtext_field_t e_field, const char *psz_value); + /*! + Read cdtext information for a CdIo object . + + return true on success, false on error or CD-Text information does + not exist. + */ + bool init_cdtext_generic (generic_img_private_t *p_env); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __CDIO_GENERIC_H__ */ diff --git a/src/input/vcd/libcdio/image.h b/src/input/vcd/libcdio/image.h new file mode 100644 index 000000000..79c836d32 --- /dev/null +++ b/src/input/vcd/libcdio/image.h @@ -0,0 +1,75 @@ +/* + $Id: image.h,v 1.1 2005/01/01 02:43:57 rockyb Exp $ + + Copyright (C) 2004 Rocky Bernstein <rocky@panix.com> + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/*! + Header for image drivers. In contrast to image_common.h which contains + routines, this header like most C headers does not depend on anything + defined before it is included. +*/ + +#ifndef __CDIO_IMAGE_H__ +#define __CDIO_IMAGE_H__ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <cdio/types.h> +#include <cdio/cdtext.h> +#include "cdio_private.h" +#include <cdio/sector.h> + +/*! + The universal format for information about a track for CD image readers + It may be that some fields can be derived from other fields. + Over time this structure may get cleaned up. Possibly this can be + expanded/reused for real CD formats. +*/ + +typedef struct { + track_t track_num; /**< Probably is index+1 */ + msf_t start_msf; + lba_t start_lba; + int start_index; + lba_t length; + lba_t pregap; /**< pre-gap with zero audio data */ + int sec_count; /**< Number of sectors in this track. Does not + include pregap */ + int num_indices; + flag_t flags; /**< "[NO] COPY", "4CH", "[NO] PREMPAHSIS" */ + char *isrc; /**< IRSC Code (5.22.4) exactly 12 bytes */ + char *filename; + CdioDataSource *data_source; + track_format_t track_format; + bool track_green; + cdtext_t cdtext; /**< CD-TEXT */ + + trackmode_t mode; + uint16_t datasize; /**< How much is in the portion we return + back? */ + uint16_t datastart; /**< Offset from begining that data starts */ + uint16_t endsize; /**< How much stuff at the end to skip over. + This stuff may have error correction + (EDC, or ECC).*/ + uint16_t blocksize; /**< total block size = start + size + end */ +} track_info_t; + + +#endif /* __CDIO_IMAGE_H__ */ diff --git a/src/input/vcd/libcdio/image/bincue.c b/src/input/vcd/libcdio/image/bincue.c index d0ca9b240..56f0e151c 100644 --- a/src/input/vcd/libcdio/image/bincue.c +++ b/src/input/vcd/libcdio/image/bincue.c @@ -1,8 +1,10 @@ /* - $Id: bincue.c,v 1.1 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: bincue.c,v 1.2 2005/01/01 02:43:58 rockyb Exp $ - Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com> + Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> + cue parsing routine adapted from cuetools + Copyright (C) 2003 Svend Sanjay Sorensen <ssorensen@fastmail.fm> 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 @@ -24,15 +26,16 @@ (*.cue). */ -static const char _rcsid[] = "$Id: bincue.c,v 1.1 2004/04/11 12:20:32 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: bincue.c,v 1.2 2005/01/01 02:43:58 rockyb Exp $"; +#include "image.h" #include "cdio_assert.h" #include "cdio_private.h" #include "_cdio_stdio.h" #include <cdio/logging.h> -#include <cdio/sector.h> #include <cdio/util.h> +#include <cdio/version.h> #ifdef HAVE_STDIO_H #include <stdio.h> @@ -46,124 +49,81 @@ static const char _rcsid[] = "$Id: bincue.c,v 1.1 2004/04/11 12:20:32 miguelfrei #ifdef HAVE_STRINGS_H #include <strings.h> #endif +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif #ifdef HAVE_GLOB_H #include <glob.h> #endif #include <ctype.h> -/* FIXME: should put in a common definition somewhere. */ -#ifdef HAVE_MEMSET -#define BZERO(ptr, size) memset(ptr, 0, size) -#elif HAVE_BZERO -#define BZERO(ptr, size) bzero(ptr, size) -#else - Error -- you need either memset or bzero -#endif - +#include "portable.h" /* reader */ #define DEFAULT_CDIO_DEVICE "videocd.bin" #define DEFAULT_CDIO_CUE "videocd.cue" typedef struct { - track_t track_num; /* Probably is index+1 */ - msf_t start_msf; - lba_t start_lba; - int start_index; - int sec_count; /* Number of sectors in this track. Does not - include pregap */ - int num_indices; - int flags; /* "DCP", "4CH", "PRE" */ - track_format_t track_format; - bool track_green; - uint16_t datasize; /* How much is in the portion we return back? */ - uint16_t datastart; /* Offset from begining that data starts */ - uint16_t endsize; /* How much stuff at the end to skip over. This - stuff may have error correction (EDC, or ECC).*/ - uint16_t blocksize; /* total block size = start + size + end */ - - -} track_info_t; - -typedef struct { /* Things common to all drivers like this. This must be first. */ generic_img_private_t gen; internal_position_t pos; - bool sector_2336; /* Playstation (PSX) uses 2336-byte sectors */ - - char *cue_name; - char *mcn; /* Media catalog number. */ - track_info_t tocent[100]; /* entry info for each track */ - track_t total_tracks; /* number of tracks in image */ - track_t first_track_num; /* track number of first track */ - bool have_cue; + char *psz_cue_name; + char *psz_mcn; /* Media Catalog Number (5.22.3) + exactly 13 bytes */ + track_info_t tocent[CDIO_CD_MAX_TRACKS+1]; /* entry info for each track + add 1 for leadout. */ + discmode_t disc_mode; } _img_private_t; -static bool _cdio_image_read_cue (_img_private_t *_obj); -static uint32_t _cdio_stat_size (void *env); +static uint32_t _stat_size_bincue (void *user_data); +static bool parse_cuefile (_img_private_t *cd, const char *toc_name); + +#define NEED_MEDIA_EJECT_IMAGE +#include "image_common.h" /*! Initialize image structures. */ static bool -_cdio_init (_img_private_t *_obj) +_init_bincue (_img_private_t *env) { lsn_t lead_lsn; - if (_obj->gen.init) + if (env->gen.init) return false; - if (!(_obj->gen.data_source = cdio_stdio_new (_obj->gen.source_name))) { + if (!(env->gen.data_source = cdio_stdio_new (env->gen.source_name))) { cdio_warn ("init failed"); return false; } - /* Have to set init before calling _cdio_stat_size() or we will + /* Have to set init before calling _stat_size_bincue() or we will get into infinite recursion calling passing right here. */ - _obj->gen.init = true; + env->gen.init = true; + env->gen.i_first_track = 1; + env->psz_mcn = NULL; + env->disc_mode = CDIO_DISC_MODE_NO_INFO; - lead_lsn = _cdio_stat_size( (_img_private_t *) _obj); + cdtext_init (&(env->gen.cdtext)); - if (-1 == lead_lsn) - return false; + lead_lsn = _stat_size_bincue( (_img_private_t *) env); + + if (-1 == lead_lsn) return false; + + if ((env->psz_cue_name == NULL)) return false; /* Read in CUE sheet. */ - if ((_obj->cue_name != NULL)) { - _obj->have_cue = _cdio_image_read_cue(_obj); - } + if ( !parse_cuefile(env, env->psz_cue_name) ) return false; - if (!_obj->have_cue ) { - /* Time to fake things... - Make one big track, track 0 and 1 are the same. - We are guessing stuff starts at msf 00:04:00 - 2 for the 150 - sector pregap and 2 for the cue information. - */ - track_info_t *this_track=&(_obj->tocent[0]); - int blocksize = _obj->sector_2336 - ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE_RAW; - - _obj->total_tracks = 2; - _obj->first_track_num = 1; - this_track->start_msf.m = to_bcd8(0); - this_track->start_msf.s = to_bcd8(4); - this_track->start_msf.f = to_bcd8(0); - this_track->start_lba = cdio_msf_to_lba(&this_track->start_msf); - this_track->blocksize = blocksize; - this_track->track_format= TRACK_FORMAT_XA; - this_track->track_green = true; - - - _obj->tocent[1] = _obj->tocent[0]; - } - /* Fake out leadout track and sector count for last track*/ - cdio_lsn_to_msf (lead_lsn, &_obj->tocent[_obj->total_tracks].start_msf); - _obj->tocent[_obj->total_tracks].start_lba = cdio_lsn_to_lba(lead_lsn); - _obj->tocent[_obj->total_tracks-1].sec_count = - cdio_lsn_to_lba(lead_lsn - _obj->tocent[_obj->total_tracks-1].start_lba); + cdio_lsn_to_msf (lead_lsn, &env->tocent[env->gen.i_tracks].start_msf); + env->tocent[env->gen.i_tracks].start_lba = cdio_lsn_to_lba(lead_lsn); + env->tocent[env->gen.i_tracks - env->gen.i_first_track].sec_count = + cdio_lsn_to_lba(lead_lsn - + env->tocent[env->gen.i_tracks - env->gen.i_first_track].start_lba); return true; } @@ -175,9 +135,9 @@ _cdio_init (_img_private_t *_obj) information in each sector. */ static off_t -_cdio_lseek (void *env, off_t offset, int whence) +_lseek_bincue (void *user_data, off_t offset, int whence) { - _img_private_t *_obj = env; + _img_private_t *env = user_data; /* real_offset is the real byte offset inside the disk image The number below was determined empirically. I'm guessing @@ -187,30 +147,30 @@ _cdio_lseek (void *env, off_t offset, int whence) unsigned int i; - _obj->pos.lba = 0; - for (i=0; i<_obj->total_tracks; i++) { - track_info_t *this_track=&(_obj->tocent[i]); - _obj->pos.index = i; + env->pos.lba = 0; + for (i=0; i<env->gen.i_tracks; i++) { + track_info_t *this_track=&(env->tocent[i]); + env->pos.index = i; if ( (this_track->sec_count*this_track->datasize) >= offset) { int blocks = offset / this_track->datasize; int rem = offset % this_track->datasize; int block_offset = blocks * this_track->blocksize; real_offset += block_offset + rem; - _obj->pos.buff_offset = rem; - _obj->pos.lba += blocks; + env->pos.buff_offset = rem; + env->pos.lba += blocks; break; } real_offset += this_track->sec_count*this_track->blocksize; offset -= this_track->sec_count*this_track->datasize; - _obj->pos.lba += this_track->sec_count; + env->pos.lba += this_track->sec_count; } - if (i==_obj->total_tracks) { + if (i==env->gen.i_tracks) { cdio_warn ("seeking outside range of disk image"); return -1; } else { - real_offset += _obj->tocent[i].datastart; - return cdio_stream_seek(_obj->gen.data_source, real_offset, whence); + real_offset += env->tocent[i].datastart; + return cdio_stream_seek(env->gen.data_source, real_offset, whence); } } @@ -222,20 +182,20 @@ _cdio_lseek (void *env, off_t offset, int whence) boundaries. */ static ssize_t -_cdio_read (void *env, void *data, size_t size) +_read_bincue (void *user_data, void *data, size_t size) { - _img_private_t *_obj = env; + _img_private_t *env = user_data; char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; char *p = data; ssize_t final_size=0; ssize_t this_size; - track_info_t *this_track=&(_obj->tocent[_obj->pos.index]); + track_info_t *this_track=&(env->tocent[env->pos.index]); ssize_t skip_size = this_track->datastart + this_track->endsize; while (size > 0) { - int rem = this_track->datasize - _obj->pos.buff_offset; - if (size <= rem) { - this_size = cdio_stream_read(_obj->gen.data_source, buf, size, 1); + long int rem = this_track->datasize - env->pos.buff_offset; + if ((long int) size <= rem) { + this_size = cdio_stream_read(env->gen.data_source, buf, size, 1); final_size += this_size; memcpy (p, buf, this_size); break; @@ -245,24 +205,24 @@ _cdio_read (void *env, void *data, size_t size) cdio_warn ("Reading across block boundaries not finished"); size -= rem; - this_size = cdio_stream_read(_obj->gen.data_source, buf, rem, 1); + this_size = cdio_stream_read(env->gen.data_source, buf, rem, 1); final_size += this_size; memcpy (p, buf, this_size); p += this_size; - this_size = cdio_stream_read(_obj->gen.data_source, buf, rem, 1); + this_size = cdio_stream_read(env->gen.data_source, buf, rem, 1); /* Skip over stuff at end of this sector and the beginning of the next. */ - cdio_stream_read(_obj->gen.data_source, buf, skip_size, 1); + cdio_stream_read(env->gen.data_source, buf, skip_size, 1); /* Get ready to read another sector. */ - _obj->pos.buff_offset=0; - _obj->pos.lba++; + env->pos.buff_offset=0; + env->pos.lba++; /* Have gone into next track. */ - if (_obj->pos.lba >= _obj->tocent[_obj->pos.index+1].start_lba) { - _obj->pos.index++; - this_track=&(_obj->tocent[_obj->pos.index]); + if (env->pos.lba >= env->tocent[env->pos.index+1].start_lba) { + env->pos.index++; + this_track=&(env->tocent[env->pos.index]); skip_size = this_track->datastart + this_track->endsize; } } @@ -273,21 +233,17 @@ _cdio_read (void *env, void *data, size_t size) Return the size of the CD in logical block address (LBA) units. */ static uint32_t -_cdio_stat_size (void *env) +_stat_size_bincue (void *user_data) { - _img_private_t *_obj = env; + _img_private_t *env = user_data; long size; - int blocksize = _obj->sector_2336 - ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE_RAW; - _cdio_init (_obj); - - size = cdio_stream_stat (_obj->gen.data_source); + size = cdio_stream_stat (env->gen.data_source); - if (size % blocksize) + if (size % CDIO_CD_FRAMESIZE_RAW) { cdio_warn ("image %s size (%ld) not multiple of blocksize (%d)", - _obj->gen.source_name, size, blocksize); + env->gen.source_name, size, CDIO_CD_FRAMESIZE_RAW); if (size % M2RAW_SECTOR_SIZE == 0) cdio_warn ("this may be a 2336-type disc image"); else if (size % CDIO_CD_FRAMESIZE_RAW == 0) @@ -295,177 +251,539 @@ _cdio_stat_size (void *env) /* exit (EXIT_FAILURE); */ } - size /= blocksize; + size /= CDIO_CD_FRAMESIZE_RAW; return size; } -#define MAXLINE 512 +#define MAXLINE 4096 /* maximum line length + 1 */ static bool -_cdio_image_read_cue (_img_private_t *_obj) +parse_cuefile (_img_private_t *cd, const char *psz_cue_name) { + /* The below declarations may be common in other image-parse routines. */ FILE *fp; - char line[MAXLINE]; - - int track_num; - int min,sec,frame; - int blocksize; + char psz_line[MAXLINE]; /* text of current line read in file fp. */ + unsigned int i_line=0; /* line number in file of psz_line. */ + int i = -1; /* Position in tocent. Same as + cd->gen.i_tracks - 1 */ + char *psz_keyword, *psz_field; + cdio_log_level_t log_level = (NULL == cd) ? CDIO_LOG_INFO : CDIO_LOG_WARN; + cdtext_field_t cdtext_key; + + /* The below declarations may be unique to this image-parse routine. */ int start_index; - bool seen_first_index_for_track=false; - - if ( _obj == NULL || _obj->cue_name == NULL ) return false; + bool b_first_index_for_track=false; - fp = fopen (_obj->cue_name, "r"); - if (fp == NULL) return false; + if (NULL == psz_cue_name) + return false; + + fp = fopen (psz_cue_name, "r"); + if (fp == NULL) { + cdio_log(log_level, "error opening %s for reading: %s", + psz_cue_name, strerror(errno)); + return false; + } - _obj->total_tracks=0; - _obj->first_track_num=1; - _obj->mcn=NULL; + if (cd) { + cd->gen.i_tracks=0; + cd->gen.i_first_track=1; + cd->gen.b_cdtext_init = true; + cd->gen.b_cdtext_error = false; + cd->psz_mcn=NULL; + } - while ((fgets(line, MAXLINE, fp)) != NULL) { - char s[80]; - char *p; - /*printf("Retrieved line of length %zu :\n", read); - printf("%s", line); */ - for (p=line; isspace(*p); p++) ; - if (1==sscanf(p, "FILE \"%80s[^\"]", s)) { - /* Should expand file name based on cue file basename. - free(_obj->bin_file); - _obj->bin_file = strdup(s); - */ - /* printf("Found file name %s\n", s); */ - } else if (1==sscanf(p, "CATALOG %80s", s)) { - _obj->mcn = strdup(s); - } else if (2==sscanf(p, "TRACK %d MODE2/%d", &track_num, &blocksize)) { - track_info_t *this_track=&(_obj->tocent[_obj->total_tracks]); - this_track->track_num = track_num; - this_track->num_indices = 0; - this_track->track_format= TRACK_FORMAT_XA; - this_track->track_green = true; - _obj->total_tracks++; - seen_first_index_for_track=false; - /*printf("Added track %d with blocksize %d\n", track_num, blocksize);*/ - - this_track->blocksize = blocksize; - switch(blocksize) { - case 2336: - this_track->datastart = CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE; - this_track->datasize = M2RAW_SECTOR_SIZE; - this_track->endsize = 0; - break; - default: - cdio_warn ("Unknown MODE2 size %d. Assuming 2352", blocksize); - case 2352: - if (_obj->sector_2336) { - this_track->datastart = 0; - this_track->datasize = M2RAW_SECTOR_SIZE; - this_track->endsize = blocksize - 2336; + while ((fgets(psz_line, MAXLINE, fp)) != NULL) { + + i_line++; + + if (NULL != (psz_keyword = strtok (psz_line, " \t\n\r"))) { + /* REM remarks ... */ + if (0 == strcmp ("REM", psz_keyword)) { + ; + + /* global section */ + /* CATALOG ddddddddddddd */ + } else if (0 == strcmp ("CATALOG", psz_keyword)) { + if (-1 == i) { + if (NULL == (psz_field = strtok (NULL, " \t\n\r"))) { + cdio_log(log_level, + "%s line %d after word CATALOG: ", + psz_cue_name, i_line); + cdio_log(log_level, + "expecting 13-digit media catalog number, got nothing."); + goto err_exit; + } + if (strlen(psz_field) != 13) { + cdio_log(log_level, + "%s line %d after word CATALOG: ", + psz_cue_name, i_line); + cdio_log(log_level, + "Token %s has length %ld. Should be 13 digits.", + psz_field, (long int) strlen(psz_field)); + goto err_exit; + } else { + /* Check that we have all digits*/ + unsigned int i; + for (i=0; i<13; i++) { + if (!isdigit(psz_field[i])) { + cdio_log(log_level, + "%s line %d after word CATALOG:", + psz_cue_name, i_line); + cdio_log(log_level, + "Character \"%c\" at postition %i of token \"%s\" " + "is not all digits.", + psz_field[i], i+1, psz_field); + goto err_exit; + } + } + } + + if (cd) cd->psz_mcn = strdup (psz_field); + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + goto format_error; + } } else { - this_track->datastart = CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE + - CDIO_CD_SUBHEADER_SIZE; - this_track->datasize = CDIO_CD_FRAMESIZE; - this_track->endsize = CDIO_CD_SYNC_SIZE + CDIO_CD_ECC_SIZE; + goto not_in_global_section; } - break; - } - - } else if (2==sscanf(p, "TRACK %d MODE1/%d", &track_num, &blocksize)) { - track_info_t *this_track=&(_obj->tocent[_obj->total_tracks]); - this_track->blocksize = blocksize; - switch(blocksize) { - case 2048: - /* Is the below correct? */ - this_track->datastart = 0; - this_track->datasize = CDIO_CD_FRAMESIZE; - this_track->endsize = 0; - break; - default: - cdio_warn ("Unknown MODE1 size %d. Assuming 2352", blocksize); - case 2352: - this_track->datastart = CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE; - this_track->datasize = CDIO_CD_FRAMESIZE; - this_track->endsize = CDIO_CD_EDC_SIZE + CDIO_CD_M1F1_ZERO_SIZE - + CDIO_CD_ECC_SIZE; - } - - this_track->track_num = track_num; - this_track->num_indices = 0; - this_track->track_format = TRACK_FORMAT_DATA; - this_track->track_green = false; - _obj->total_tracks++; - seen_first_index_for_track=false; - /*printf("Added track %d with blocksize %d\n", track_num, blocksize);*/ - - } else if (1==sscanf(p, "TRACK %d AUDIO", &track_num)) { - track_info_t *this_track=&(_obj->tocent[_obj->total_tracks]); - this_track->blocksize = CDIO_CD_FRAMESIZE_RAW; - this_track->datasize = CDIO_CD_FRAMESIZE_RAW; - this_track->datastart = 0; - this_track->endsize = 0; - this_track->track_num = track_num; - this_track->num_indices = 0; - this_track->track_format = TRACK_FORMAT_AUDIO; - this_track->track_green = false; - _obj->total_tracks++; - seen_first_index_for_track=false; - - } else if (4==sscanf(p, "INDEX %d %d:%d:%d", - &start_index, &min, &sec, &frame)) { - track_info_t *this_track=&(_obj->tocent[_obj->total_tracks-1]); - /* FIXME! all of this is a big hack. - If start_index == 0, then this is the "last_cue" information. - The +2 below seconds is to adjust for the 150 pregap. - */ - if (start_index != 0) { - if (!seen_first_index_for_track) { - this_track->start_index = start_index; - sec += 2; - if (sec >= 60) { - min++; - sec -= 60; + + /* FILE "<filename>" <BINARY|WAVE|other?> */ + } else if (0 == strcmp ("FILE", psz_keyword)) { + if (NULL != (psz_field = strtok (NULL, "\"\t\n\r"))) { + if (cd) cd->tocent[i + 1].filename = strdup (psz_field); + } else { + goto format_error; + } + + /* TRACK N <mode> */ + } else if (0 == strcmp ("TRACK", psz_keyword)) { + int i_track; + + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + if (1!=sscanf(psz_field, "%d", &i_track)) { + cdio_log(log_level, + "%s line %d after word TRACK:", + psz_cue_name, i_line); + cdio_log(log_level, + "Expecting a track number, got %s", psz_field); + goto err_exit; } - this_track->start_msf.m = to_bcd8 (min); - this_track->start_msf.s = to_bcd8 (sec); - this_track->start_msf.f = to_bcd8 (frame); - this_track->start_lba = cdio_msf_to_lba(&this_track->start_msf); - seen_first_index_for_track=true; } - - if (_obj->total_tracks > 1) { - /* Figure out number of sectors for previous track */ - track_info_t *prev_track=&(_obj->tocent[_obj->total_tracks-2]); - if ( this_track->start_lba < prev_track->start_lba ) { - cdio_warn("track %d at LBA %lu starts before track %d at LBA %lu", - _obj->total_tracks, - (unsigned long int) this_track->start_lba, - _obj->total_tracks-1, - (unsigned long int) prev_track->start_lba); - prev_track->sec_count = 0; - } else if ( this_track->start_lba >= prev_track->start_lba - + CDIO_PREGAP_SECTORS ) { - prev_track->sec_count = this_track->start_lba - - prev_track->start_lba - CDIO_PREGAP_SECTORS ; + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + track_info_t *this_track=NULL; + + if (cd) { + this_track = &(cd->tocent[cd->gen.i_tracks]); + this_track->track_num = cd->gen.i_tracks; + this_track->num_indices = 0; + b_first_index_for_track = false; + cdtext_init (&(cd->gen.cdtext_track[cd->gen.i_tracks])); + cd->gen.i_tracks++; + } + i++; + + if (0 == strcmp ("AUDIO", psz_field)) { + if (cd) { + this_track->mode = AUDIO; + this_track->blocksize = CDIO_CD_FRAMESIZE_RAW; + this_track->datasize = CDIO_CD_FRAMESIZE_RAW; + this_track->datastart = 0; + this_track->endsize = 0; + this_track->track_format = TRACK_FORMAT_AUDIO; + this_track->track_green = false; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_DA; + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DATA: + case CDIO_DISC_MODE_CD_XA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else if (0 == strcmp ("MODE1/2048", psz_field)) { + if (cd) { + this_track->mode = MODE1; + this_track->blocksize = 2048; + this_track->track_format= TRACK_FORMAT_DATA; + this_track->track_green = false; + /* Is the below correct? */ + this_track->datastart = 0; + this_track->datasize = CDIO_CD_FRAMESIZE; + this_track->endsize = 0; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_DATA; + break; + case CDIO_DISC_MODE_CD_DATA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_XA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else if (0 == strcmp ("MODE1/2352", psz_field)) { + if (cd) { + this_track->blocksize = 2352; + this_track->track_format= TRACK_FORMAT_DATA; + this_track->track_green = false; + this_track->datastart = CDIO_CD_SYNC_SIZE + + CDIO_CD_HEADER_SIZE; + this_track->datasize = CDIO_CD_FRAMESIZE; + this_track->endsize = CDIO_CD_EDC_SIZE + + CDIO_CD_M1F1_ZERO_SIZE + CDIO_CD_ECC_SIZE; + this_track->mode = MODE1_RAW; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_DATA; + break; + case CDIO_DISC_MODE_CD_DATA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_XA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else if (0 == strcmp ("MODE2/2336", psz_field)) { + if (cd) { + this_track->blocksize = 2336; + this_track->track_format= TRACK_FORMAT_XA; + this_track->track_green = true; + this_track->mode = MODE2; + this_track->datastart = CDIO_CD_SYNC_SIZE + + CDIO_CD_HEADER_SIZE; + this_track->datasize = M2RAW_SECTOR_SIZE; + this_track->endsize = 0; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_DATA; + break; + case CDIO_DISC_MODE_CD_DATA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_XA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else if (0 == strcmp ("MODE2/2048", psz_field)) { + if (cd) { + this_track->blocksize = 2048; + this_track->track_format= TRACK_FORMAT_XA; + this_track->track_green = true; + this_track->mode = MODE2_FORM1; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_XA; + break; + case CDIO_DISC_MODE_CD_XA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_DATA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else if (0 == strcmp ("MODE2/2324", psz_field)) { + if (cd) { + this_track->blocksize = 2324; + this_track->track_format= TRACK_FORMAT_XA; + this_track->track_green = true; + this_track->mode = MODE2_FORM2; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_XA; + break; + case CDIO_DISC_MODE_CD_XA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_DATA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else if (0 == strcmp ("MODE2/2336", psz_field)) { + if (cd) { + this_track->blocksize = 2336; + this_track->track_format= TRACK_FORMAT_XA; + this_track->track_green = true; + this_track->mode = MODE2_FORM_MIX; + this_track->datastart = CDIO_CD_SYNC_SIZE + + CDIO_CD_HEADER_SIZE; + this_track->datasize = M2RAW_SECTOR_SIZE; + this_track->endsize = 0; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_XA; + break; + case CDIO_DISC_MODE_CD_XA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_DATA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else if (0 == strcmp ("MODE2/2352", psz_field)) { + if (cd) { + this_track->blocksize = 2352; + this_track->track_format= TRACK_FORMAT_XA; + this_track->track_green = true; + this_track->mode = MODE2_RAW; + this_track->datastart = CDIO_CD_SYNC_SIZE + + CDIO_CD_HEADER_SIZE + CDIO_CD_SUBHEADER_SIZE; + this_track->datasize = CDIO_CD_FRAMESIZE; + this_track->endsize = CDIO_CD_SYNC_SIZE + CDIO_CD_ECC_SIZE; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_XA; + break; + case CDIO_DISC_MODE_CD_XA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_DATA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else { + cdio_log(log_level, + "%s line %d after word TRACK:", + psz_cue_name, i_line); + cdio_log(log_level, + "Unknown track mode %s", psz_field); + goto err_exit; + } + } else { + goto format_error; + } + + /* FLAGS flag1 flag2 ... */ + } else if (0 == strcmp ("FLAGS", psz_keyword)) { + if (0 <= i) { + while (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + if (0 == strcmp ("PRE", psz_field)) { + if (cd) cd->tocent[i].flags |= PRE_EMPHASIS; + } else if (0 == strcmp ("DCP", psz_field)) { + if (cd) cd->tocent[i].flags |= COPY_PERMITTED; + } else if (0 == strcmp ("4CH", psz_field)) { + if (cd) cd->tocent[i].flags |= FOUR_CHANNEL_AUDIO; + } else if (0 == strcmp ("SCMS", psz_field)) { + if (cd) cd->tocent[i].flags |= SCMS; + } else { + goto format_error; + } + } + } else { + goto format_error; + } + + /* ISRC CCOOOYYSSSSS */ + } else if (0 == strcmp ("ISRC", psz_keyword)) { + if (0 <= i) { + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + if (cd) cd->tocent[i].isrc = strdup (psz_field); + } else { + goto format_error; + } + } else { + goto in_global_section; + } + + /* PREGAP MM:SS:FF */ + } else if (0 == strcmp ("PREGAP", psz_keyword)) { + if (0 <= i) { + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + lba_t lba = cdio_lsn_to_lba(cdio_mmssff_to_lba (psz_field)); + if (CDIO_INVALID_LBA == lba) { + cdio_log(log_level, "%s line %d: after word PREGAP:", + psz_cue_name, i_line); + cdio_log(log_level, "Invalid MSF string %s", + psz_field); + goto err_exit; + } + if (cd) { + cd->tocent[i].pregap = lba; + } } else { - cdio_warn ("%lu fewer than pregap (%d) sectors in track %d", - (long unsigned int) - this_track->start_lba - prev_track->start_lba, - CDIO_PREGAP_SECTORS, - _obj->total_tracks-1); - /* Include pregap portion in sec_count. Maybe the pregap - was omitted. */ - prev_track->sec_count = this_track->start_lba - - prev_track->start_lba; + goto format_error; + } if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + goto format_error; + } + } else { + goto in_global_section; + } + + /* INDEX [##] MM:SS:FF */ + } else if (0 == strcmp ("INDEX", psz_keyword)) { + if (0 <= i) { + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) + if (1!=sscanf(psz_field, "%d", &start_index)) { + cdio_log(log_level, + "%s line %d after word INDEX:", + psz_cue_name, i_line); + cdio_log(log_level, + "expecting an index number, got %s", + psz_field); + goto err_exit; + } + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + lba_t lba = cdio_mmssff_to_lba (psz_field); + if (CDIO_INVALID_LBA == lba) { + cdio_log(log_level, "%s line %d: after word INDEX:", + psz_cue_name, i_line); + cdio_log(log_level, "Invalid MSF string %s", + psz_field); + goto err_exit; + } + if (cd) { +#if FIXED_ME + cd->tocent[i].indexes[cd->tocent[i].nindex++] = lba; +#else + track_info_t *this_track= + &(cd->tocent[cd->gen.i_tracks - cd->gen.i_first_track]); + + if (start_index != 0) { + if (!b_first_index_for_track) { + lba += CDIO_PREGAP_SECTORS; + cdio_lba_to_msf(lba, &(this_track->start_msf)); + b_first_index_for_track = true; + this_track->start_lba = lba; + } + + if (cd->gen.i_tracks > 1) { + /* Figure out number of sectors for previous track */ + track_info_t *prev_track=&(cd->tocent[cd->gen.i_tracks-2]); + if ( this_track->start_lba < prev_track->start_lba ) { + cdio_log (log_level, + "track %d at LBA %lu starts before track %d at LBA %lu", + cd->gen.i_tracks, + (unsigned long int) this_track->start_lba, + cd->gen.i_tracks, + (unsigned long int) prev_track->start_lba); + prev_track->sec_count = 0; + } else if ( this_track->start_lba >= prev_track->start_lba + + CDIO_PREGAP_SECTORS ) { + prev_track->sec_count = this_track->start_lba - + prev_track->start_lba - CDIO_PREGAP_SECTORS ; + } else { + cdio_log (log_level, + "%lu fewer than pregap (%d) sectors in track %d", + (long unsigned int) + this_track->start_lba - prev_track->start_lba, + CDIO_PREGAP_SECTORS, + cd->gen.i_tracks); + /* Include pregap portion in sec_count. Maybe the pregap + was omitted. */ + prev_track->sec_count = this_track->start_lba - + prev_track->start_lba; + } + } + this_track->num_indices++; + } + } +#endif + } else { + goto format_error; + } + } else { + goto in_global_section; + } + + /* CD-TEXT */ + } else if ( CDTEXT_INVALID != + (cdtext_key = cdtext_is_keyword (psz_keyword)) ) { + if (-1 == i) { + if (cd) { + cdtext_set (cdtext_key, + strtok (NULL, "\"\t\n\r"), + &(cd->gen.cdtext)); + } + } else { + if (cd) { + cdtext_set (cdtext_key, strtok (NULL, "\"\t\n\r"), + &(cd->gen.cdtext_track[i])); } } - this_track->num_indices++; + + /* unrecognized line */ + } else { + cdio_log(log_level, "%s line %d: warning: unrecognized keyword: %s", + psz_cue_name, i_line, psz_keyword); + goto err_exit; } } } - _obj->have_cue = _obj->total_tracks != 0; + + if (NULL != cd) { + cd->gen.toc_init = true; + } fclose (fp); return true; + + format_error: + cdio_log(log_level, "%s line %d after word %s", + psz_cue_name, i_line, psz_keyword); + goto err_exit; + + in_global_section: + cdio_log(log_level, "%s line %d: word %s not allowed in global section", + psz_cue_name, i_line, psz_keyword); + goto err_exit; + + not_in_global_section: + cdio_log(log_level, "%s line %d: word %s only allowed in global section", + psz_cue_name, i_line, psz_keyword); + + err_exit: + fclose (fp); + return false; + } /*! @@ -473,31 +791,29 @@ _cdio_image_read_cue (_img_private_t *_obj) from lsn. Returns 0 if no error. */ static int -_cdio_read_audio_sectors (void *env, void *data, lsn_t lsn, +_read_audio_sectors_bincue (void *user_data, void *data, lsn_t lsn, unsigned int nblocks) { - _img_private_t *_obj = env; + _img_private_t *env = user_data; int ret; - _cdio_init (_obj); - /* Why the adjustment of 272, I don't know. It seems to work though */ if (lsn != 0) { - ret = cdio_stream_seek (_obj->gen.data_source, + ret = cdio_stream_seek (env->gen.data_source, (lsn * CDIO_CD_FRAMESIZE_RAW) - 272, SEEK_SET); if (ret!=0) return ret; - ret = cdio_stream_read (_obj->gen.data_source, data, + ret = cdio_stream_read (env->gen.data_source, data, CDIO_CD_FRAMESIZE_RAW, nblocks); } else { /* We need to pad out the first 272 bytes with 0's */ BZERO(data, 272); - ret = cdio_stream_seek (_obj->gen.data_source, 0, SEEK_SET); + ret = cdio_stream_seek (env->gen.data_source, 0, SEEK_SET); if (ret!=0) return ret; - ret = cdio_stream_read (_obj->gen.data_source, (uint8_t *) data+272, + ret = cdio_stream_read (env->gen.data_source, (uint8_t *) data+272, CDIO_CD_FRAMESIZE_RAW - 272, nblocks); } @@ -510,26 +826,19 @@ _cdio_read_audio_sectors (void *env, void *data, lsn_t lsn, from lsn. Returns 0 if no error. */ static int -_cdio_read_mode1_sector (void *env, void *data, lsn_t lsn, - bool b_form2) +_read_mode1_sector_bincue (void *user_data, void *data, lsn_t lsn, + bool b_form2) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; int ret; char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; - int blocksize = _obj->sector_2336 - ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE_RAW; - - _cdio_init (_obj); + int blocksize = CDIO_CD_FRAMESIZE_RAW; - ret = cdio_stream_seek (_obj->gen.data_source, lsn * blocksize, SEEK_SET); + ret = cdio_stream_seek (p_env->gen.data_source, lsn * blocksize, SEEK_SET); if (ret!=0) return ret; /* FIXME: Not completely sure the below is correct. */ - ret = cdio_stream_read (_obj->gen.data_source, - _obj->sector_2336 - ? (buf + CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE) - : buf, - blocksize, 1); + ret = cdio_stream_read (p_env->gen.data_source, buf, CDIO_CD_FRAMESIZE_RAW, 1); if (ret==0) return ret; memcpy (data, buf + CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE, @@ -544,16 +853,16 @@ _cdio_read_mode1_sector (void *env, void *data, lsn_t lsn, Returns 0 if no error. */ static int -_cdio_read_mode1_sectors (void *env, void *data, uint32_t lsn, - bool b_form2, unsigned int nblocks) +_read_mode1_sectors_bincue (void *user_data, void *data, lsn_t lsn, + bool b_form2, unsigned int nblocks) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; int i; int retval; unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE; for (i = 0; i < nblocks; i++) { - if ( (retval = _cdio_read_mode1_sector (_obj, + if ( (retval = _read_mode1_sector_bincue (p_env, ((char *)data) + (blocksize * i), lsn + i, b_form2)) ) return retval; @@ -566,10 +875,10 @@ _cdio_read_mode1_sectors (void *env, void *data, uint32_t lsn, from lsn. Returns 0 if no error. */ static int -_cdio_read_mode2_sector (void *env, void *data, lsn_t lsn, +_read_mode2_sector_bincue (void *user_data, void *data, lsn_t lsn, bool b_form2) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; int ret; char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; @@ -579,19 +888,12 @@ _cdio_read_mode2_sector (void *env, void *data, lsn_t lsn, Review this sector 2336 stuff later. */ - int blocksize = _obj->sector_2336 - ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE_RAW; + int blocksize = CDIO_CD_FRAMESIZE_RAW; - _cdio_init (_obj); - - ret = cdio_stream_seek (_obj->gen.data_source, lsn * blocksize, SEEK_SET); + ret = cdio_stream_seek (p_env->gen.data_source, lsn * blocksize, SEEK_SET); if (ret!=0) return ret; - ret = cdio_stream_read (_obj->gen.data_source, - _obj->sector_2336 - ? (buf + CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE) - : buf, - blocksize, 1); + ret = cdio_stream_read (p_env->gen.data_source, buf, CDIO_CD_FRAMESIZE_RAW, 1); if (ret==0) return ret; @@ -611,16 +913,16 @@ _cdio_read_mode2_sector (void *env, void *data, lsn_t lsn, Returns 0 if no error. */ static int -_cdio_read_mode2_sectors (void *env, void *data, uint32_t lsn, - bool b_form2, unsigned int nblocks) +_read_mode2_sectors_bincue (void *user_data, void *data, lsn_t lsn, + bool b_form2, unsigned int nblocks) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; int i; int retval; unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE; for (i = 0; i < nblocks; i++) { - if ( (retval = _cdio_read_mode2_sector (_obj, + if ( (retval = _read_mode2_sector_bincue (p_env, ((char *)data) + (blocksize * i), lsn + i, b_form2)) ) return retval; @@ -628,84 +930,8 @@ _cdio_read_mode2_sectors (void *env, void *data, uint32_t lsn, return 0; } -#define free_if_notnull(obj) \ - if (NULL != obj) { free(obj); obj=NULL; }; - -static void -_cdio_bincue_destroy (void *obj) -{ - _img_private_t *env = obj; - - if (NULL == env) return; - free_if_notnull(env->mcn); - free_if_notnull(env->cue_name); - cdio_generic_stdio_free(env); - free(env); -} - -/*! - Set the arg "key" with "value" in the source device. - Currently "source" to set the source device in I/O operations - is the only valid key. - - 0 is returned if no error was found, and nonzero if there as an error. -*/ -static int -_cdio_set_arg (void *env, const char key[], const char value[]) -{ - _img_private_t *_obj = env; - - if (!strcmp (key, "source")) - { - free_if_notnull (_obj->gen.source_name); - - if (!value) - return -2; - - _obj->gen.source_name = strdup (value); - } - else if (!strcmp (key, "sector")) - { - if (!strcmp (value, "2336")) - _obj->sector_2336 = true; - else if (!strcmp (value, "2352")) - _obj->sector_2336 = false; - else - return -2; - } - else if (!strcmp (key, "cue")) - { - free_if_notnull (_obj->cue_name); - - if (!value) - return -2; - - _obj->cue_name = strdup (value); - } - else - return -1; - - return 0; -} - -/*! - Return the value associated with the key "arg". -*/ -static const char * -_cdio_get_arg (void *env, const char key[]) -{ - _img_private_t *_obj = env; - - if (!strcmp (key, "source")) { - return _obj->gen.source_name; - } else if (!strcmp (key, "cue")) { - return _obj->cue_name; - } - return NULL; -} - /*! - Return an array of strings giving possible NRG disk images. + Return an array of strings giving possible BIN/CUE disk images. */ char ** cdio_get_devices_bincue (void) @@ -740,51 +966,14 @@ cdio_get_default_device_bincue(void) return drive; } -/*! - Return the number of of the first track. - CDIO_INVALID_TRACK is returned on error. -*/ -static track_t -_cdio_get_first_track_num(void *env) -{ - _img_private_t *_obj = env; - - _cdio_init (_obj); - - return _obj->first_track_num; -} - -/*! - Return the media catalog number (MCN) from the CD or NULL if there - is none or we don't have the ability to get it. - - Note: string is malloc'd so caller has to free() the returned - string when done with it. - */ -static char * -_cdio_get_mcn(void *env) +static bool +get_hwinfo_bincue ( const CdIo *p_cdio, /*out*/ cdio_hwinfo_t *hw_info) { - _img_private_t *_obj = env; + strcpy(hw_info->psz_vendor, "libcdio"); + strcpy(hw_info->psz_model, "CDRWIN"); + strcpy(hw_info->psz_revision, CDIO_VERSION); + return true; - _cdio_init (_obj); - - if (NULL == _obj->mcn) return NULL; - return strdup(_obj->mcn); -} - -/*! - Return the number of tracks in the current medium. - If no cuesheet is available, We fake it an just say there's - one big track. - CDIO_INVALID_TRACK is returned on error. -*/ -static track_t -_cdio_get_num_tracks(void *env) -{ - _img_private_t *_obj = env; - _cdio_init (_obj); - - return _obj->have_cue && _obj->total_tracks > 0 ? _obj->total_tracks : 1; } /*! @@ -792,16 +981,14 @@ _cdio_get_num_tracks(void *env) CDIO_INVALID_TRACK is returned on error. */ static track_format_t -_cdio_get_track_format(void *env, track_t track_num) +_get_track_format_bincue(void *user_data, track_t i_track) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; - if (!_obj->gen.init) _cdio_init(_obj); - - if (track_num > _obj->total_tracks || track_num == 0) + if (i_track > p_env->gen.i_tracks || i_track == 0) return TRACK_FORMAT_ERROR; - return _obj->tocent[track_num-1].track_format; + return p_env->tocent[i_track-p_env->gen.i_first_track].track_format; } /*! @@ -813,200 +1000,208 @@ _cdio_get_track_format(void *env, track_t track_num) FIXME: there's gotta be a better design for this and get_track_format? */ static bool -_cdio_get_track_green(void *env, track_t track_num) +_get_track_green_bincue(void *user_data, track_t i_track) { - _img_private_t *_obj = env; + _img_private_t *p_env = user_data; - if (!_obj->gen.init) _cdio_init(_obj); - - if (track_num > _obj->total_tracks || track_num == 0) + if ( NULL == p_env || + ( i_track < p_env->gen.i_first_track + || i_track >= p_env->gen.i_tracks + p_env->gen.i_first_track ) ) return false; - return _obj->tocent[track_num-1].track_green; + return p_env->tocent[i_track-p_env->gen.i_first_track].track_green; } /*! Return the starting LSN track number - track_num in obj. Track numbers start at 1. + i_track in obj. Track numbers start at 1. The "leadout" track is specified either by - using track_num LEADOUT_TRACK or the total tracks+1. + using i_track LEADOUT_TRACK or the total tracks+1. False is returned if there is no track entry. */ static lba_t -_cdio_get_track_lba(void *env, track_t track_num) +_get_lba_track_bincue(void *user_data, track_t i_track) { - _img_private_t *_obj = env; - _cdio_init (_obj); + _img_private_t *p_env = user_data; - if (track_num == CDIO_CDROM_LEADOUT_TRACK) track_num = _obj->total_tracks+1; + if (i_track == CDIO_CDROM_LEADOUT_TRACK) i_track = p_env->gen.i_tracks+1; - if (track_num <= _obj->total_tracks+1 && track_num != 0) { - return _obj->tocent[track_num-1].start_lba; + if (i_track <= p_env->gen.i_tracks + p_env->gen.i_first_track && i_track != 0) { + return p_env->tocent[i_track-p_env->gen.i_first_track].start_lba; } else return CDIO_INVALID_LBA; } -/*! - Return the starting MSF (minutes/secs/frames) for the track number - track_num in obj. Tracks numbers start at 1. - The "leadout" track is specified either by - using track_num LEADOUT_TRACK or the total tracks+1. - -*/ -static bool -_cdio_get_track_msf(void *env, track_t track_num, msf_t *msf) -{ - _img_private_t *_obj = env; - _cdio_init (_obj); - - if (NULL == msf) return false; - - if (track_num == CDIO_CDROM_LEADOUT_TRACK) track_num = _obj->total_tracks+1; - - if (track_num <= _obj->total_tracks+1 && track_num != 0) { - *msf = _obj->tocent[track_num-1].start_msf; - return true; - } else - return false; -} - /*! - Return corresponding BIN file if cue_name is a cue file or NULL + Return corresponding BIN file if psz_cue_name is a cue file or NULL if not a CUE file. - -*/ -/* Later we'll probably parse the entire file. For now though, this gets us - started for now. */ char * -cdio_is_cuefile(const char *cue_name) +cdio_is_cuefile(const char *psz_cue_name) { int i; - char *bin_name; + char *psz_bin_name; - if (cue_name == NULL) return false; + if (psz_cue_name == NULL) return NULL; + + /* FIXME? Now that we have cue parsing, should we really force + the filename extension requirement or is it enough just to + parse the cuefile? + */ - bin_name=strdup(cue_name); - i=strlen(bin_name)-strlen("cue"); + psz_bin_name=strdup(psz_cue_name); + i=strlen(psz_bin_name)-strlen("cue"); if (i>0) { - if (cue_name[i]=='c' && cue_name[i+1]=='u' && cue_name[i+2]=='e') { - bin_name[i++]='b'; bin_name[i++]='i'; bin_name[i++]='n'; - return bin_name; + if (psz_cue_name[i]=='c' && psz_cue_name[i+1]=='u' && psz_cue_name[i+2]=='e') { + psz_bin_name[i++]='b'; psz_bin_name[i++]='i'; psz_bin_name[i++]='n'; + if (parse_cuefile(NULL, psz_cue_name)) + return psz_bin_name; + else + goto error; } - else if (cue_name[i]=='C' && cue_name[i+1]=='U' && cue_name[i+2]=='E') { - bin_name[i++]='B'; bin_name[i++]='I'; bin_name[i++]='N'; - return bin_name; + else if (psz_cue_name[i]=='C' && psz_cue_name[i+1]=='U' && psz_cue_name[i+2]=='E') { + psz_bin_name[i++]='B'; psz_bin_name[i++]='I'; psz_bin_name[i++]='N'; + if (parse_cuefile(NULL, psz_cue_name)) + return psz_bin_name; + else + goto error; } } - free(bin_name); + error: + free(psz_bin_name); return NULL; } /*! - Return corresponding CUE file if bin_name is a bin file or NULL + Return corresponding CUE file if psz_bin_name is a bin file or NULL if not a BIN file. - -*/ -/* Later we'll probably do better. For now though, this gets us - started for now. */ char * -cdio_is_binfile(const char *bin_name) +cdio_is_binfile(const char *psz_bin_name) { int i; - char *cue_name; + char *psz_cue_name; - if (bin_name == NULL) return false; + if (psz_bin_name == NULL) return NULL; - cue_name=strdup(bin_name); - i=strlen(bin_name)-strlen("bin"); + psz_cue_name=strdup(psz_bin_name); + i=strlen(psz_bin_name)-strlen("bin"); if (i>0) { - if (bin_name[i]=='b' && bin_name[i+1]=='i' && bin_name[i+2]=='n') { - cue_name[i++]='c'; cue_name[i++]='u'; cue_name[i++]='e'; - return cue_name; + if (psz_bin_name[i]=='b' && psz_bin_name[i+1]=='i' && psz_bin_name[i+2]=='n') { + psz_cue_name[i++]='c'; psz_cue_name[i++]='u'; psz_cue_name[i++]='e'; + return psz_cue_name; } - else if (bin_name[i]=='B' && bin_name[i+1]=='I' && bin_name[i+2]=='N') { - cue_name[i++]='C'; cue_name[i++]='U'; cue_name[i++]='E'; - return cue_name; + else if (psz_bin_name[i]=='B' && psz_bin_name[i+1]=='I' && psz_bin_name[i+2]=='N') { + psz_cue_name[i++]='C'; psz_cue_name[i++]='U'; psz_cue_name[i++]='E'; + return psz_cue_name; } } - free(cue_name); + free(psz_cue_name); return NULL; } +/*! + Initialization routine. This is the only thing that doesn't + get called via a function pointer. In fact *we* are the + ones to set that up. + */ +CdIo * +cdio_open_am_bincue (const char *psz_source_name, const char *psz_access_mode) +{ + if (psz_access_mode != NULL) + cdio_warn ("there is only one access mode for bincue. Arg %s ignored", + psz_access_mode); + return cdio_open_bincue(psz_source_name); +} + +/*! + Initialization routine. This is the only thing that doesn't + get called via a function pointer. In fact *we* are the + ones to set that up. + */ CdIo * cdio_open_bincue (const char *source_name) { - char *bin_name = cdio_is_cuefile(source_name); + char *psz_bin_name = cdio_is_cuefile(source_name); - if (NULL != bin_name) { - free(bin_name); + if (NULL != psz_bin_name) { + free(psz_bin_name); return cdio_open_cue(source_name); } else { - char *cue_name = cdio_is_binfile(source_name); - CdIo *cdio = cdio_open_cue(cue_name); - free(cue_name); + char *psz_cue_name = cdio_is_binfile(source_name); + CdIo *cdio = cdio_open_cue(psz_cue_name); + free(psz_cue_name); return cdio; } } CdIo * -cdio_open_cue (const char *cue_name) +cdio_open_cue (const char *psz_cue_name) { CdIo *ret; _img_private_t *_data; - char *bin_name; - - cdio_funcs _funcs = { - .eject_media = cdio_generic_bogus_eject_media, - .free = _cdio_bincue_destroy, - .get_arg = _cdio_get_arg, - .get_default_device = cdio_get_default_device_bincue, - .get_first_track_num= _cdio_get_first_track_num, - .get_mcn = _cdio_get_mcn, - .get_num_tracks = _cdio_get_num_tracks, - .get_track_format = _cdio_get_track_format, - .get_track_green = _cdio_get_track_green, - .get_track_lba = _cdio_get_track_lba, - .get_track_msf = _cdio_get_track_msf, - .lseek = _cdio_lseek, - .read = _cdio_read, - .read_audio_sectors = _cdio_read_audio_sectors, - .read_mode1_sector = _cdio_read_mode1_sector, - .read_mode1_sectors = _cdio_read_mode1_sectors, - .read_mode2_sector = _cdio_read_mode2_sector, - .read_mode2_sectors = _cdio_read_mode2_sectors, - .set_arg = _cdio_set_arg, - .stat_size = _cdio_stat_size - }; - - if (NULL == cue_name) return NULL; - + char *psz_bin_name; + + cdio_funcs _funcs; + + memset( &_funcs, 0, sizeof(_funcs) ); + + _funcs.eject_media = _eject_media_image; + _funcs.free = _free_image; + _funcs.get_arg = _get_arg_image; + _funcs.get_cdtext = get_cdtext_generic; + _funcs.get_devices = cdio_get_devices_bincue; + _funcs.get_default_device = cdio_get_default_device_bincue; + _funcs.get_discmode = _get_discmode_image; + _funcs.get_drive_cap = _get_drive_cap_image; + _funcs.get_first_track_num= _get_first_track_num_image; + _funcs.get_hwinfo = get_hwinfo_bincue; + _funcs.get_mcn = _get_mcn_image; + _funcs.get_num_tracks = _get_num_tracks_image; + _funcs.get_track_format = _get_track_format_bincue; + _funcs.get_track_green = _get_track_green_bincue; + _funcs.get_track_lba = _get_lba_track_bincue; + _funcs.get_track_msf = _get_track_msf_image; + _funcs.lseek = _lseek_bincue; + _funcs.read = _read_bincue; + _funcs.read_audio_sectors = _read_audio_sectors_bincue; + _funcs.read_mode1_sector = _read_mode1_sector_bincue; + _funcs.read_mode1_sectors = _read_mode1_sectors_bincue; + _funcs.read_mode2_sector = _read_mode2_sector_bincue; + _funcs.read_mode2_sectors = _read_mode2_sectors_bincue; + _funcs.set_arg = _set_arg_image; + _funcs.stat_size = _stat_size_bincue; + + if (NULL == psz_cue_name) return NULL; + _data = _cdio_malloc (sizeof (_img_private_t)); - (_data)->gen.init = false; - (_data)->sector_2336 = false; - (_data)->cue_name = NULL; - - ret = cdio_new (_data, &_funcs); - - if (ret == NULL) return NULL; - - bin_name = cdio_is_cuefile(cue_name); - - if (NULL == bin_name) { - cdio_error ("source name %s is not recognized as a CUE file", cue_name); + _data->gen.init = false; + _data->psz_cue_name = NULL; + + ret = cdio_new ((void *)_data, &_funcs); + + if (ret == NULL) { + free(_data); + return NULL; } - _cdio_set_arg (_data, "cue", cue_name); - _cdio_set_arg (_data, "source", bin_name); - free(bin_name); - - if (_cdio_init(_data)) { + psz_bin_name = cdio_is_cuefile(psz_cue_name); + + if (NULL == psz_bin_name) { + cdio_error ("source name %s is not recognized as a CUE file", + psz_cue_name); + } + + _set_arg_image (_data, "cue", psz_cue_name); + _set_arg_image (_data, "source", psz_bin_name); + free(psz_bin_name); + + if (_init_bincue(_data)) { return ret; } else { - _cdio_bincue_destroy(_data); + _free_image(_data); free(ret); return NULL; } diff --git a/src/input/vcd/libcdio/image/cdrdao.c b/src/input/vcd/libcdio/image/cdrdao.c new file mode 100644 index 000000000..828172721 --- /dev/null +++ b/src/input/vcd/libcdio/image/cdrdao.c @@ -0,0 +1,1198 @@ +/* + $Id: cdrdao.c,v 1.1 2005/01/01 02:43:58 rockyb Exp $ + + Copyright (C) 2004 Rocky Bernstein <rocky@panix.com> + toc reading routine adapted from cuetools + Copyright (C) 2003 Svend Sanjay Sorensen <ssorensen@fastmail.fm> + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* This code implements low-level access functions for a CD images + residing inside a disk file (*.bin) and its associated cue sheet. + (*.cue). +*/ + +static const char _rcsid[] = "$Id: cdrdao.c,v 1.1 2005/01/01 02:43:58 rockyb Exp $"; + +#include "image.h" +#include "cdio_assert.h" +#include "_cdio_stdio.h" + +#include <cdio/logging.h> +#include <cdio/sector.h> +#include <cdio/util.h> +#include <cdio/version.h> + +#ifdef HAVE_STDIO_H +#include <stdio.h> +#endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#ifdef HAVE_STRING_H +#include <string.h> +#endif +#ifdef HAVE_STRINGS_H +#include <strings.h> +#endif +#ifdef HAVE_GLOB_H +#include <glob.h> +#endif +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif + +#include <ctype.h> + +#include "portable.h" + +/* reader */ + +#define DEFAULT_CDIO_DEVICE "videocd.bin" +#define DEFAULT_CDIO_CDRDAO "videocd.toc" + +typedef struct { + /* Things common to all drivers like this. + This must be first. */ + generic_img_private_t gen; + internal_position_t pos; + + char *psz_cue_name; + char *psz_mcn; /* Media Catalog Number (5.22.3) + exactly 13 bytes */ + track_info_t tocent[CDIO_CD_MAX_TRACKS+1]; /* entry info for each track + add 1 for leadout. */ + discmode_t disc_mode; +} _img_private_t; + +static uint32_t _stat_size_cdrdao (void *user_data); +static bool parse_tocfile (_img_private_t *cd, const char *toc_name); + +#define NEED_MEDIA_EJECT_IMAGE +#include "image_common.h" + +/*! + Initialize image structures. + */ +static bool +_init_cdrdao (_img_private_t *env) +{ + lsn_t lead_lsn; + + if (env->gen.init) + return false; + + /* Have to set init before calling _stat_size_cdrdao() or we will + get into infinite recursion calling passing right here. + */ + env->gen.init = true; + env->gen.i_first_track = 1; + env->psz_mcn = NULL; + env->disc_mode = CDIO_DISC_MODE_NO_INFO; + + cdtext_init (&(env->gen.cdtext)); + + /* Read in TOC sheet. */ + if ( !parse_tocfile(env, env->psz_cue_name) ) return false; + + lead_lsn = _stat_size_cdrdao( (_img_private_t *) env); + + if (-1 == lead_lsn) + return false; + + /* Fake out leadout track and sector count for last track*/ + cdio_lsn_to_msf (lead_lsn, &env->tocent[env->gen.i_tracks].start_msf); + env->tocent[env->gen.i_tracks].start_lba = cdio_lsn_to_lba(lead_lsn); + env->tocent[env->gen.i_tracks-env->gen.i_first_track].sec_count = + cdio_lsn_to_lba(lead_lsn - env->tocent[env->gen.i_tracks-1].start_lba); + + return true; +} + +/*! + Reads into buf the next size bytes. + Returns -1 on error. + Would be libc's seek() but we have to adjust for the extra track header + information in each sector. +*/ +static off_t +_lseek_cdrdao (void *user_data, off_t offset, int whence) +{ + _img_private_t *env = user_data; + + /* real_offset is the real byte offset inside the disk image + The number below was determined empirically. I'm guessing + the 1st 24 bytes of a bin file are used for something. + */ + off_t real_offset=0; + + unsigned int i; + + env->pos.lba = 0; + for (i=0; i<env->gen.i_tracks; i++) { + track_info_t *this_track=&(env->tocent[i]); + env->pos.index = i; + if ( (this_track->sec_count*this_track->datasize) >= offset) { + int blocks = offset / this_track->datasize; + int rem = offset % this_track->datasize; + int block_offset = blocks * this_track->blocksize; + real_offset += block_offset + rem; + env->pos.buff_offset = rem; + env->pos.lba += blocks; + break; + } + real_offset += this_track->sec_count*this_track->blocksize; + offset -= this_track->sec_count*this_track->datasize; + env->pos.lba += this_track->sec_count; + } + + if (i==env->gen.i_tracks) { + cdio_warn ("seeking outside range of disk image"); + return -1; + } else { + real_offset += env->tocent[i].datastart; + return cdio_stream_seek(env->tocent[i].data_source, real_offset, whence); + } +} + +/*! + Reads into buf the next size bytes. + Returns -1 on error. + FIXME: + At present we assume a read doesn't cross sector or track + boundaries. +*/ +static ssize_t +_read_cdrdao (void *user_data, void *data, size_t size) +{ + _img_private_t *env = user_data; + char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; + char *p = data; + ssize_t final_size=0; + ssize_t this_size; + track_info_t *this_track=&(env->tocent[env->pos.index]); + ssize_t skip_size = this_track->datastart + this_track->endsize; + + while (size > 0) { + int rem = this_track->datasize - env->pos.buff_offset; + if (size <= rem) { + this_size = cdio_stream_read(this_track->data_source, buf, size, 1); + final_size += this_size; + memcpy (p, buf, this_size); + break; + } + + /* Finish off reading this sector. */ + cdio_warn ("Reading across block boundaries not finished"); + + size -= rem; + this_size = cdio_stream_read(this_track->data_source, buf, rem, 1); + final_size += this_size; + memcpy (p, buf, this_size); + p += this_size; + this_size = cdio_stream_read(this_track->data_source, buf, rem, 1); + + /* Skip over stuff at end of this sector and the beginning of the next. + */ + cdio_stream_read(this_track->data_source, buf, skip_size, 1); + + /* Get ready to read another sector. */ + env->pos.buff_offset=0; + env->pos.lba++; + + /* Have gone into next track. */ + if (env->pos.lba >= env->tocent[env->pos.index+1].start_lba) { + env->pos.index++; + this_track=&(env->tocent[env->pos.index]); + skip_size = this_track->datastart + this_track->endsize; + } + } + return final_size; +} + +/*! + Return the size of the CD in logical block address (LBA) units. + */ +static uint32_t +_stat_size_cdrdao (void *user_data) +{ + _img_private_t *env = user_data; + long size; + + size = cdio_stream_stat (env->tocent[0].data_source); + + if (size % CDIO_CD_FRAMESIZE_RAW) + { + cdio_warn ("image %s size (%ld) not multiple of blocksize (%d)", + env->tocent[0].filename, size, CDIO_CD_FRAMESIZE_RAW); + if (size % M2RAW_SECTOR_SIZE == 0) + cdio_warn ("this may be a 2336-type disc image"); + else if (size % CDIO_CD_FRAMESIZE_RAW == 0) + cdio_warn ("this may be a 2352-type disc image"); + /* exit (EXIT_FAILURE); */ + } + + size /= CDIO_CD_FRAMESIZE_RAW; + + return size; +} + +#define MAXLINE 512 +#define UNIMPLIMENTED_MSG \ + cdio_log(log_level, "%s line %d: unimplimented keyword: %s", \ + psz_cue_name, i_line, psz_keyword) + + +static bool +parse_tocfile (_img_private_t *cd, const char *psz_cue_name) +{ + /* The below declarations may be common in other image-parse routines. */ + FILE *fp; + char psz_line[MAXLINE]; /* text of current line read in file fp. */ + unsigned int i_line=0; /* line number in file of psz_line. */ + int i = -1; /* Position in tocent. Same as + cd->gen.i_tracks - 1 */ + char *psz_keyword, *psz_field; + cdio_log_level_t log_level = (NULL == cd) ? CDIO_LOG_INFO : CDIO_LOG_WARN; + cdtext_field_t cdtext_key; + + /* The below declaration(s) may be unique to this image-parse routine. */ + unsigned int i_cdtext_nest = 0; + + if (NULL == psz_cue_name) + return false; + + fp = fopen (psz_cue_name, "r"); + if (fp == NULL) { + cdio_log(log_level, "error opening %s for reading: %s", + psz_cue_name, strerror(errno)); + return false; + } + + if (cd) { + cd->gen.b_cdtext_init = true; + cd->gen.b_cdtext_error = false; + } + + while ((fgets(psz_line, MAXLINE, fp)) != NULL) { + + i_line++; + + /* strip comment from line */ + /* todo: // in quoted strings? */ + /* //comment */ + if (NULL != (psz_field = strstr (psz_line, "//"))) + *psz_field = '\0'; + + if (NULL != (psz_keyword = strtok (psz_line, " \t\n\r"))) { + /* CATALOG "ddddddddddddd" */ + if (0 == strcmp ("CATALOG", psz_keyword)) { + if (-1 == i) { + if (NULL != (psz_field = strtok (NULL, "\"\t\n\r"))) { + if (13 != strlen(psz_field)) { + cdio_log(log_level, + "%s line %d after word CATALOG:", + psz_cue_name, i_line); + cdio_log(log_level, + "Token %s has length %ld. Should be 13 digits.", + psz_field, (long int) strlen(psz_field)); + + goto err_exit; + } else { + /* Check that we have all digits*/ + unsigned int i; + for (i=0; i<13; i++) { + if (!isdigit(psz_field[i])) { + cdio_log(log_level, + "%s line %d after word CATALOG:", + psz_cue_name, i_line); + cdio_log(log_level, + "Character \"%c\" at postition %i of token \"%s\"" + " is not all digits.", + psz_field[i], i+1, psz_field); + goto err_exit; + } + } + if (NULL != cd) cd->psz_mcn = strdup (psz_field); + } + } else { + cdio_log(log_level, + "%s line %d after word CATALOG:", + psz_cue_name, i_line); + cdio_log(log_level, "Expecting 13 digits; nothing seen."); + goto err_exit; + } + } else { + goto err_exit; + } + + /* CD_DA | CD_ROM | CD_ROM_XA */ + } else if (0 == strcmp ("CD_DA", psz_keyword)) { + if (-1 == i) { + if (NULL != cd) + cd->disc_mode = CDIO_DISC_MODE_CD_DA; + } else { + goto not_in_global_section; + } + } else if (0 == strcmp ("CD_ROM", psz_keyword)) { + if (-1 == i) { + if (NULL != cd) + cd->disc_mode = CDIO_DISC_MODE_CD_DATA; + } else { + goto not_in_global_section; + } + + } else if (0 == strcmp ("CD_ROM_XA", psz_keyword)) { + if (-1 == i) { + if (NULL != cd) + cd->disc_mode = CDIO_DISC_MODE_CD_XA; + } else { + goto not_in_global_section; + } + + /* TRACK <track-mode> [<sub-channel-mode>] */ + } else if (0 == strcmp ("TRACK", psz_keyword)) { + i++; + if (NULL != cd) cdtext_init (&(cd->gen.cdtext_track[i])); + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + if (0 == strcmp ("AUDIO", psz_field)) { + if (NULL != cd) { + cd->tocent[i].track_format = TRACK_FORMAT_AUDIO; + cd->tocent[i].blocksize = CDIO_CD_FRAMESIZE_RAW; + cd->tocent[i].datasize = CDIO_CD_FRAMESIZE_RAW; + cd->tocent[i].datastart = 0; + cd->tocent[i].endsize = 0; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_DA; + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DATA: + case CDIO_DISC_MODE_CD_XA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + + } + } else if (0 == strcmp ("MODE1", psz_field)) { + if (NULL != cd) { + cd->tocent[i].track_format = TRACK_FORMAT_DATA; + cd->tocent[i].blocksize = CDIO_CD_FRAMESIZE_RAW; + cd->tocent[i].datastart = CDIO_CD_SYNC_SIZE + + CDIO_CD_HEADER_SIZE; + cd->tocent[i].datasize = CDIO_CD_FRAMESIZE; + cd->tocent[i].endsize = CDIO_CD_EDC_SIZE + + CDIO_CD_M1F1_ZERO_SIZE + CDIO_CD_ECC_SIZE; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_DATA; + break; + case CDIO_DISC_MODE_CD_DATA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_XA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else if (0 == strcmp ("MODE1_RAW", psz_field)) { + if (NULL != cd) { + cd->tocent[i].track_format = TRACK_FORMAT_DATA; + cd->tocent[i].blocksize = CDIO_CD_FRAMESIZE_RAW; + cd->tocent[i].datastart = CDIO_CD_SYNC_SIZE + + CDIO_CD_HEADER_SIZE; + cd->tocent[i].datasize = CDIO_CD_FRAMESIZE; + cd->tocent[i].endsize = CDIO_CD_EDC_SIZE + + CDIO_CD_M1F1_ZERO_SIZE + CDIO_CD_ECC_SIZE; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_DATA; + break; + case CDIO_DISC_MODE_CD_DATA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_XA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else if (0 == strcmp ("MODE2", psz_field)) { + if (NULL != cd) { + cd->tocent[i].track_format = TRACK_FORMAT_XA; + cd->tocent[i].datastart = CDIO_CD_SYNC_SIZE + + CDIO_CD_HEADER_SIZE; + cd->tocent[i].datasize = M2RAW_SECTOR_SIZE; + cd->tocent[i].endsize = 0; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_XA; + break; + case CDIO_DISC_MODE_CD_XA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_DATA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else if (0 == strcmp ("MODE2_FORM1", psz_field)) { + if (NULL != cd) { + cd->tocent[i].track_format = TRACK_FORMAT_XA; + cd->tocent[i].datastart = CDIO_CD_SYNC_SIZE + + CDIO_CD_HEADER_SIZE; + cd->tocent[i].datasize = CDIO_CD_FRAMESIZE_RAW; + cd->tocent[i].endsize = 0; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_XA; + break; + case CDIO_DISC_MODE_CD_XA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_DATA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else if (0 == strcmp ("MODE2_FORM2", psz_field)) { + if (NULL != cd) { + cd->tocent[i].track_format = TRACK_FORMAT_XA; + cd->tocent[i].datastart = CDIO_CD_SYNC_SIZE + + CDIO_CD_HEADER_SIZE + CDIO_CD_SUBHEADER_SIZE; + cd->tocent[i].datasize = CDIO_CD_FRAMESIZE; + cd->tocent[i].endsize = CDIO_CD_SYNC_SIZE + + CDIO_CD_ECC_SIZE; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_XA; + break; + case CDIO_DISC_MODE_CD_XA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_DATA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else if (0 == strcmp ("MODE2_FORM_MIX", psz_field)) { + if (NULL != cd) { + cd->tocent[i].track_format = TRACK_FORMAT_XA; + cd->tocent[i].datasize = M2RAW_SECTOR_SIZE; + cd->tocent[i].blocksize = CDIO_CD_FRAMESIZE_RAW; + cd->tocent[i].datastart = CDIO_CD_SYNC_SIZE + + CDIO_CD_HEADER_SIZE + CDIO_CD_SUBHEADER_SIZE; + cd->tocent[i].track_green = true; + cd->tocent[i].endsize = 0; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_XA; + break; + case CDIO_DISC_MODE_CD_XA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_DATA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else if (0 == strcmp ("MODE2_RAW", psz_field)) { + if (NULL != cd) { + cd->tocent[i].track_format = TRACK_FORMAT_XA; + cd->tocent[i].blocksize = CDIO_CD_FRAMESIZE_RAW; + cd->tocent[i].datastart = CDIO_CD_SYNC_SIZE + + CDIO_CD_HEADER_SIZE + CDIO_CD_SUBHEADER_SIZE; + cd->tocent[i].datasize = CDIO_CD_FRAMESIZE; + cd->tocent[i].track_green = true; + cd->tocent[i].endsize = 0; + switch(cd->disc_mode) { + case CDIO_DISC_MODE_NO_INFO: + cd->disc_mode = CDIO_DISC_MODE_CD_XA; + break; + case CDIO_DISC_MODE_CD_XA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_ERROR: + /* Disc type stays the same. */ + break; + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_DATA: + cd->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + default: + cd->disc_mode = CDIO_DISC_MODE_ERROR; + } + } + } else { + cdio_log(log_level, "%s line %d after TRACK:", + psz_cue_name, i_line); + cdio_log(log_level, "'%s' not a valid mode.", psz_field); + goto err_exit; + } + } + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + /* todo: set sub-channel-mode */ + if (0 == strcmp ("RW", psz_field)) + ; + else if (0 == strcmp ("RW_RAW", psz_field)) + ; + } + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + goto format_error; + } + + /* track flags */ + /* [NO] COPY | [NO] PRE_EMPHASIS */ + } else if (0 == strcmp ("NO", psz_keyword)) { + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + if (0 == strcmp ("COPY", psz_field)) { + if (NULL != cd) + cd->tocent[i].flags &= ~CDIO_TRACK_FLAG_COPY_PERMITTED; + + } else if (0 == strcmp ("PRE_EMPHASIS", psz_field)) + if (NULL != cd) { + cd->tocent[i].flags &= ~CDIO_TRACK_FLAG_PRE_EMPHASIS; + goto err_exit; + } + } else { + goto format_error; + } + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + goto format_error; + } + } else if (0 == strcmp ("COPY", psz_keyword)) { + if (NULL != cd) + cd->tocent[i].flags |= CDIO_TRACK_FLAG_COPY_PERMITTED; + } else if (0 == strcmp ("PRE_EMPHASIS", psz_keyword)) { + if (NULL != cd) + cd->tocent[i].flags |= CDIO_TRACK_FLAG_PRE_EMPHASIS; + /* TWO_CHANNEL_AUDIO */ + } else if (0 == strcmp ("TWO_CHANNEL_AUDIO", psz_keyword)) { + if (NULL != cd) + cd->tocent[i].flags &= ~CDIO_TRACK_FLAG_FOUR_CHANNEL_AUDIO; + /* FOUR_CHANNEL_AUDIO */ + } else if (0 == strcmp ("FOUR_CHANNEL_AUDIO", psz_keyword)) { + if (NULL != cd) + cd->tocent[i].flags |= CDIO_TRACK_FLAG_FOUR_CHANNEL_AUDIO; + + /* ISRC "CCOOOYYSSSSS" */ + } else if (0 == strcmp ("ISRC", psz_keyword)) { + if (NULL != (psz_field = strtok (NULL, "\"\t\n\r"))) { + if (NULL != cd) + cd->tocent[i].isrc = strdup(psz_field); + } else { + goto format_error; + } + + /* SILENCE <length> */ + } else if (0 == strcmp ("SILENCE", psz_keyword)) { + UNIMPLIMENTED_MSG; + + /* ZERO <length> */ + } else if (0 == strcmp ("ZERO", psz_keyword)) { + UNIMPLIMENTED_MSG; + + /* [FILE|AUDIOFILE] "<filename>" <start> [<length>] */ + } else if (0 == strcmp ("FILE", psz_keyword) + || 0 == strcmp ("AUDIOFILE", psz_keyword)) { + if (0 <= i) { + if (NULL != (psz_field = strtok (NULL, "\"\t\n\r"))) { + if (NULL != cd) { + cd->tocent[i].filename = strdup (psz_field); + /* Todo: do something about reusing existing files. */ + if (!(cd->tocent[i].data_source = cdio_stdio_new (psz_field))) { + cdio_log (log_level, + "%s line %d: can't open file `%s' for reading", + psz_cue_name, i_line, psz_field); + goto err_exit; + } + } + } + + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + lba_t lba = cdio_lsn_to_lba(cdio_mmssff_to_lba (psz_field)); + if (CDIO_INVALID_LBA == lba) { + cdio_log(log_level, "%s line %d: invalid MSF string %s", + psz_cue_name, i_line, psz_field); + goto err_exit; + } + + if (NULL != cd) { + cd->tocent[i].start_lba = lba; + cdio_lba_to_msf(lba, &(cd->tocent[i].start_msf)); + } + } + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) + if (NULL != cd) + cd->tocent[i].length = cdio_mmssff_to_lba (psz_field); + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + goto format_error; + } + } else { + goto not_in_global_section; + } + + /* DATAFILE "<filename>" <start> [<length>] */ + } else if (0 == strcmp ("DATAFILE", psz_keyword)) { + goto unimplimented_error; + + /* FIFO "<fifo path>" [<length>] */ + } else if (0 == strcmp ("FIFO", psz_keyword)) { + goto unimplimented_error; + + /* START MM:SS:FF */ + } else if (0 == strcmp ("START", psz_keyword)) { + if (0 <= i) { + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + /* todo: line is too long! */ + if (NULL != cd) { + cd->tocent[i].start_lba += cdio_mmssff_to_lba (psz_field); + cdio_lba_to_msf(cd->tocent[i].start_lba, + &(cd->tocent[i].start_msf)); + } + } + + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + goto format_error; + } + } else { + goto not_in_global_section; + } + + /* PREGAP MM:SS:FF */ + } else if (0 == strcmp ("PREGAP", psz_keyword)) { + if (0 <= i) { + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + if (NULL != cd) + cd->tocent[i].pregap = cdio_mmssff_to_lba (psz_field); + } else { + goto format_error; + } + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + goto format_error; + } + } else { + goto not_in_global_section; + } + + /* INDEX MM:SS:FF */ + } else if (0 == strcmp ("INDEX", psz_keyword)) { + if (0 <= i) { + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + if (NULL != cd) { +#if 0 + if (1 == cd->tocent[i].nindex) { + cd->tocent[i].indexes[1] = cd->tocent[i].indexes[0]; + cd->tocent[i].nindex++; + } + cd->tocent[i].indexes[cd->tocent[i].nindex++] = + cdio_mmssff_to_lba (psz_field) + cd->tocent[i].indexes[0]; +#else + ; + +#endif + } + } else { + goto format_error; + } + if (NULL != (psz_field = strtok (NULL, " \t\n\r"))) { + goto format_error; + } + } else { + goto not_in_global_section; + } + + /* CD_TEXT { ... } */ + /* todo: opening { must be on same line as CD_TEXT */ + } else if (0 == strcmp ("CD_TEXT", psz_keyword)) { + if (NULL == (psz_field = strtok (NULL, " \t\n\r"))) { + goto format_error; + } + if ( 0 == strcmp( "{", psz_field ) ) { + i_cdtext_nest++; + } else { + cdio_log (log_level, + "%s line %d: expecting '{'", psz_cue_name, i_line); + goto err_exit; + } + + } else if (0 == strcmp ("LANGUAGE_MAP", psz_keyword)) { + /* LANGUAGE d { ... } */ + } else if (0 == strcmp ("LANGUAGE", psz_keyword)) { + if (NULL == (psz_field = strtok (NULL, " \t\n\r"))) { + goto format_error; + } + /* Language number */ + if (NULL == (psz_field = strtok (NULL, " \t\n\r"))) { + goto format_error; + } + if ( 0 == strcmp( "{", psz_field ) ) { + i_cdtext_nest++; + } + } else if (0 == strcmp ("{", psz_keyword)) { + i_cdtext_nest++; + } else if (0 == strcmp ("}", psz_keyword)) { + if (i_cdtext_nest > 0) i_cdtext_nest--; + } else if ( CDTEXT_INVALID != + (cdtext_key = cdtext_is_keyword (psz_keyword)) ) { + if (-1 == i) { + if (NULL != cd) { + cdtext_set (cdtext_key, + strtok (NULL, "\"\t\n\r"), + &(cd->gen.cdtext)); + } + } else { + if (NULL != cd) { + cdtext_set (cdtext_key, + strtok (NULL, "\"\t\n\r"), + &(cd->gen.cdtext_track[i])); + } + } + + /* unrecognized line */ + } else { + cdio_log(log_level, "%s line %d: warning: unrecognized word: %s", + psz_cue_name, i_line, psz_keyword); + goto err_exit; + } + } + } + + if (NULL != cd) { + cd->gen.i_tracks = i+1; + cd->gen.toc_init = true; + } + + fclose (fp); + return true; + + unimplimented_error: + UNIMPLIMENTED_MSG; + goto err_exit; + + format_error: + cdio_log(log_level, "%s line %d after word %s", + psz_cue_name, i_line, psz_keyword); + goto err_exit; + + not_in_global_section: + cdio_log(log_level, "%s line %d: word %s only allowed in global section", + psz_cue_name, i_line, psz_keyword); + + err_exit: + fclose (fp); + return false; +} + +/*! + Reads a single audio sector from CD device into data starting + from lsn. Returns 0 if no error. + */ +static int +_read_audio_sectors_cdrdao (void *user_data, void *data, lsn_t lsn, + unsigned int nblocks) +{ + _img_private_t *env = user_data; + int ret; + + /* Why the adjustment of 272, I don't know. It seems to work though */ + if (lsn != 0) { + ret = cdio_stream_seek (env->tocent[0].data_source, + (lsn * CDIO_CD_FRAMESIZE_RAW) - 272, SEEK_SET); + if (ret!=0) return ret; + + ret = cdio_stream_read (env->tocent[0].data_source, data, + CDIO_CD_FRAMESIZE_RAW, nblocks); + } else { + /* We need to pad out the first 272 bytes with 0's */ + BZERO(data, 272); + + ret = cdio_stream_seek (env->tocent[0].data_source, 0, SEEK_SET); + + if (ret!=0) return ret; + + ret = cdio_stream_read (env->tocent[0].data_source, (uint8_t *) data+272, + CDIO_CD_FRAMESIZE_RAW - 272, nblocks); + } + + /* ret is number of bytes if okay, but we need to return 0 okay. */ + return ret == 0; +} + +/*! + Reads a single mode2 sector from cd device into data starting + from lsn. Returns 0 if no error. + */ +static int +_read_mode1_sector_cdrdao (void *user_data, void *data, lsn_t lsn, + bool b_form2) +{ + _img_private_t *env = user_data; + int ret; + char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; + + ret = cdio_stream_seek (env->tocent[0].data_source, + lsn * CDIO_CD_FRAMESIZE_RAW, SEEK_SET); + if (ret!=0) return ret; + + /* FIXME: Not completely sure the below is correct. */ + ret = cdio_stream_read (env->tocent[0].data_source, buf, + CDIO_CD_FRAMESIZE_RAW, 1); + if (ret==0) return ret; + + memcpy (data, buf + CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE, + b_form2 ? M2RAW_SECTOR_SIZE: CDIO_CD_FRAMESIZE); + + return 0; +} + +/*! + Reads nblocks of mode1 sectors from cd device into data starting + from lsn. + Returns 0 if no error. + */ +static int +_read_mode1_sectors_cdrdao (void *user_data, void *data, lsn_t lsn, + bool b_form2, unsigned int nblocks) +{ + _img_private_t *env = user_data; + int i; + int retval; + unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE; + + for (i = 0; i < nblocks; i++) { + if ( (retval = _read_mode1_sector_cdrdao (env, + ((char *)data) + (blocksize * i), + lsn + i, b_form2)) ) + return retval; + } + return 0; +} + +/*! + Reads a single mode1 sector from cd device into data starting + from lsn. Returns 0 if no error. + */ +static int +_read_mode2_sector_cdrdao (void *user_data, void *data, lsn_t lsn, + bool b_form2) +{ + _img_private_t *env = user_data; + int ret; + char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; + + /* NOTE: The logic below seems a bit wrong and convoluted + to me, but passes the regression tests. (Perhaps it is why we get + valgrind errors in vcdxrip). Leave it the way it was for now. + Review this sector 2336 stuff later. + */ + + ret = cdio_stream_seek (env->tocent[0].data_source, + lsn * CDIO_CD_FRAMESIZE_RAW, SEEK_SET); + if (ret!=0) return ret; + + ret = cdio_stream_read (env->tocent[0].data_source, buf, + CDIO_CD_FRAMESIZE_RAW, 1); + if (ret==0) return ret; + + + /* See NOTE above. */ + if (b_form2) + memcpy (data, buf + CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE, + M2RAW_SECTOR_SIZE); + else + memcpy (data, buf + CDIO_CD_XA_SYNC_HEADER, CDIO_CD_FRAMESIZE); + + return 0; +} + +/*! + Reads nblocks of mode2 sectors from cd device into data starting + from lsn. + Returns 0 if no error. + */ +static int +_read_mode2_sectors_cdrdao (void *user_data, void *data, lsn_t lsn, + bool b_form2, unsigned int nblocks) +{ + _img_private_t *env = user_data; + int i; + int retval; + + for (i = 0; i < nblocks; i++) { + if ( (retval = _read_mode2_sector_cdrdao (env, + ((char *)data) + (CDIO_CD_FRAMESIZE * i), + lsn + i, b_form2)) ) + return retval; + } + return 0; +} + +/*! + Return an array of strings giving possible TOC disk images. + */ +char ** +cdio_get_devices_cdrdao (void) +{ + char **drives = NULL; + unsigned int num_files=0; +#ifdef HAVE_GLOB_H + unsigned int i; + glob_t globbuf; + globbuf.gl_offs = 0; + glob("*.toc", GLOB_DOOFFS, NULL, &globbuf); + for (i=0; i<globbuf.gl_pathc; i++) { + cdio_add_device_list(&drives, globbuf.gl_pathv[i], &num_files); + } + globfree(&globbuf); +#else + cdio_add_device_list(&drives, DEFAULT_CDIO_DEVICE, &num_files); +#endif /*HAVE_GLOB_H*/ + cdio_add_device_list(&drives, NULL, &num_files); + return drives; +} + +/*! + Return a string containing the default CD device. + */ +char * +cdio_get_default_device_cdrdao(void) +{ + char **drives = cdio_get_devices_nrg(); + char *drive = (drives[0] == NULL) ? NULL : strdup(drives[0]); + cdio_free_device_list(drives); + return drive; +} + +static bool +get_hwinfo_cdrdao ( const CdIo *p_cdio, /*out*/ cdio_hwinfo_t *hw_info) +{ + strcpy(hw_info->psz_vendor, "libcdio"); + strcpy(hw_info->psz_model, "cdrdao"); + strcpy(hw_info->psz_revision, CDIO_VERSION); + return true; + +} + +/*! + Return the number of tracks in the current medium. + CDIO_INVALID_TRACK is returned on error. +*/ +static track_format_t +_get_track_format_cdrdao(void *user_data, track_t i_track) +{ + _img_private_t *env = user_data; + + if (!env->gen.init) _init_cdrdao(env); + + if (i_track > env->gen.i_tracks || i_track == 0) + return TRACK_FORMAT_ERROR; + + return env->tocent[i_track-env->gen.i_first_track].track_format; +} + +/*! + Return true if we have XA data (green, mode2 form1) or + XA data (green, mode2 form2). That is track begins: + sync - header - subheader + 12 4 - 8 + + FIXME: there's gotta be a better design for this and get_track_format? +*/ +static bool +_get_track_green_cdrdao(void *user_data, track_t i_track) +{ + _img_private_t *env = user_data; + + if (!env->gen.init) _init_cdrdao(env); + + if (i_track > env->gen.i_tracks || i_track == 0) + return false; + + return env->tocent[i_track-env->gen.i_first_track].track_green; +} + +/*! + Return the starting LSN track number + i_track in obj. Track numbers start at 1. + The "leadout" track is specified either by + using i_track LEADOUT_TRACK or the total tracks+1. + False is returned if there is no track entry. +*/ +static lba_t +_get_lba_track_cdrdao(void *user_data, track_t i_track) +{ + _img_private_t *env = user_data; + _init_cdrdao (env); + + if (i_track == CDIO_CDROM_LEADOUT_TRACK) + i_track = env->gen.i_tracks+1; + + if (i_track <= env->gen.i_tracks+1 && i_track != 0) { + return env->tocent[i_track-1].start_lba; + } else + return CDIO_INVALID_LBA; +} + +/*! + Check that a TOC file is valid. We parse the entire file. + +*/ +bool +cdio_is_tocfile(const char *psz_cue_name) +{ + int i; + + if (psz_cue_name == NULL) return false; + + i=strlen(psz_cue_name)-strlen("toc"); + + if (i>0) { + if ( (psz_cue_name[i]=='t' && psz_cue_name[i+1]=='o' && psz_cue_name[i+2]=='c') + || (psz_cue_name[i]=='T' && psz_cue_name[i+1]=='O' && psz_cue_name[i+2]=='C') ) { + return parse_tocfile(NULL, psz_cue_name); + } + } + return false; +} + +/*! + Initialization routine. This is the only thing that doesn't + get called via a function pointer. In fact *we* are the + ones to set that up. + */ +CdIo * +cdio_open_am_cdrdao (const char *psz_source_name, const char *psz_access_mode) +{ + if (psz_access_mode != NULL && strcmp(psz_access_mode, "image")) + cdio_warn ("there is only one access mode, 'image' for cdrdao. Arg %s ignored", + psz_access_mode); + return cdio_open_cdrdao(psz_source_name); +} + +/*! + Initialization routine. This is the only thing that doesn't + get called via a function pointer. In fact *we* are the + ones to set that up. + */ +CdIo * +cdio_open_cdrdao (const char *psz_cue_name) +{ + CdIo *ret; + _img_private_t *_data; + + cdio_funcs _funcs; + + memset( &_funcs, 0, sizeof(_funcs) ); + + _funcs.eject_media = _eject_media_image; + _funcs.free = _free_image; + _funcs.get_arg = _get_arg_image; + _funcs.get_cdtext = get_cdtext_generic; + _funcs.get_devices = cdio_get_devices_cdrdao; + _funcs.get_default_device = cdio_get_default_device_cdrdao; + _funcs.get_discmode = _get_discmode_image; + _funcs.get_drive_cap = _get_drive_cap_image; + _funcs.get_first_track_num= _get_first_track_num_image; + _funcs.get_hwinfo = get_hwinfo_cdrdao; + _funcs.get_mcn = _get_mcn_image; + _funcs.get_num_tracks = _get_num_tracks_image; + _funcs.get_track_format = _get_track_format_cdrdao; + _funcs.get_track_green = _get_track_green_cdrdao; + _funcs.get_track_lba = _get_lba_track_cdrdao; + _funcs.get_track_msf = _get_track_msf_image; + _funcs.lseek = _lseek_cdrdao; + _funcs.read = _read_cdrdao; + _funcs.read_audio_sectors = _read_audio_sectors_cdrdao; + _funcs.read_mode1_sector = _read_mode1_sector_cdrdao; + _funcs.read_mode1_sectors = _read_mode1_sectors_cdrdao; + _funcs.read_mode2_sector = _read_mode2_sector_cdrdao; + _funcs.read_mode2_sectors = _read_mode2_sectors_cdrdao; + _funcs.set_arg = _set_arg_image; + _funcs.stat_size = _stat_size_cdrdao; + + if (NULL == psz_cue_name) return NULL; + + _data = _cdio_malloc (sizeof (_img_private_t)); + _data->gen.init = false; + _data->psz_cue_name = NULL; + _data->gen.data_source = NULL; + _data->gen.source_name = NULL; + + ret = cdio_new ((void *)_data, &_funcs); + + if (ret == NULL) { + free(_data); + return NULL; + } + + if (!cdio_is_tocfile(psz_cue_name)) { + cdio_debug ("source name %s is not recognized as a TOC file", + psz_cue_name); + return NULL; + } + + _set_arg_image (_data, "cue", psz_cue_name); + _set_arg_image (_data, "source", psz_cue_name); + + if (_init_cdrdao(_data)) { + return ret; + } else { + _free_image(_data); + free(ret); + return NULL; + } +} + +bool +cdio_have_cdrdao (void) +{ + return true; +} diff --git a/src/input/vcd/libcdio/image/nrg.c b/src/input/vcd/libcdio/image/nrg.c index c4aa5e403..0610eee1a 100644 --- a/src/input/vcd/libcdio/image/nrg.c +++ b/src/input/vcd/libcdio/image/nrg.c @@ -1,8 +1,8 @@ /* - $Id: nrg.c,v 1.1 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: nrg.c,v 1.2 2005/01/01 02:43:59 rockyb Exp $ - Copyright (C) 2001, 2003 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> + Copyright (C) 2001, 2003 Herbert Valerio Riedel <hvr@gnu.org> 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 @@ -22,9 +22,7 @@ CD-image format residing inside a disk file (*.nrg). */ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif +#include "image.h" #ifdef HAVE_STDIO_H #include <stdio.h> @@ -39,108 +37,22 @@ #include <glob.h> #endif +#include <cdio/bytesex.h> +#include <cdio/ds.h> #include <cdio/logging.h> -#include <cdio/sector.h> #include <cdio/util.h> +#include <cdio/version.h> #include "cdio_assert.h" -#include "bytesex.h" -#include "ds.h" -#include "cdio_private.h" #include "_cdio_stdio.h" +#include "nrg.h" -static const char _rcsid[] = "$Id: nrg.c,v 1.1 2004/04/11 12:20:32 miguelfreitas Exp $"; - -/* structures used */ - -/* this ugly image format is typical for lazy win32 programmers... at - least structure were set big endian, so at reverse - engineering wasn't such a big headache... */ +static const char _rcsid[] = "$Id: nrg.c,v 1.2 2005/01/01 02:43:59 rockyb Exp $"; -PRAGMA_BEGIN_PACKED -typedef struct { - uint32_t start GNUC_PACKED; - uint32_t length GNUC_PACKED; - uint32_t type GNUC_PACKED; /* 0x0 -> MODE1, 0x2 -> MODE2 form1, - 0x3 -> MIXED_MODE2 2336 blocksize - */ - uint32_t start_lsn GNUC_PACKED; /* does not include any pre-gaps! */ - uint32_t _unknown GNUC_PACKED; /* wtf is this for? -- always zero... */ -} _etnf_array_t; - -/* finally they realized that 32bit offsets are a bit outdated for IA64 *eg* */ -typedef struct { - uint64_t start GNUC_PACKED; - uint64_t length GNUC_PACKED; - uint32_t type GNUC_PACKED; /* 0x0 -> MODE1, 0x2 -> MODE2 form1, - 0x3 -> MIXED_MODE2 2336 blocksize - */ - uint32_t start_lsn GNUC_PACKED; - uint64_t _unknown GNUC_PACKED; /* wtf is this for? -- always zero... */ -} _etn2_array_t; - -typedef struct { - uint8_t _unknown1 GNUC_PACKED; /* 0x41 == 'A' */ - uint8_t track GNUC_PACKED; /* binary or BCD?? */ - uint8_t index GNUC_PACKED; /* makes 0->1 transitions */ - uint8_t _unknown2 GNUC_PACKED; /* ?? */ - uint32_t lsn GNUC_PACKED; -} _cuex_array_t; - -typedef struct { - uint8_t _unknown[64] GNUC_PACKED; -} _daox_array_t; - -typedef struct { - uint32_t id GNUC_PACKED; - uint32_t len GNUC_PACKED; - char data[EMPTY_ARRAY_SIZE] GNUC_PACKED; -} _chunk_t; - -PRAGMA_END_PACKED - -/* to be converted into BE */ -#define CUEX_ID 0x43554558 -#define CUES_ID 0x43554553 -#define DAOX_ID 0x44414f58 -#define DAOI_ID 0x44414f49 -#define END1_ID 0x454e4421 -#define ETN2_ID 0x45544e32 -#define ETNF_ID 0x45544e46 -#define NER5_ID 0x4e455235 -#define NERO_ID 0x4e45524f -#define SINF_ID 0x53494e46 /* Session information */ -#define MTYP_ID 0x4d545950 /* Disc Media type? */ - -#define MTYP_AUDIO_CD 1 /* This isn't correct. But I don't know the - the right thing is and it sometimes works (and - sometimes is wrong). */ - -/* Disk track type Values gleaned from DAOX */ -#define DTYP_MODE1 0 -#define DTYP_MODE2_XA 2 -#define DTYP_INVALID 255 /* reader */ #define DEFAULT_CDIO_DEVICE "image.nrg" -typedef struct { - int track_num; /* Probably is index+1 */ - msf_t start_msf; - lba_t start_lba; - int start_index; - int sec_count; /* Number of sectors in track. Does not - include pregap before next entry. */ - int flags; /* "DCP", "4CH", "PRE" */ - track_format_t track_format; - bool track_green; - uint16_t datasize; /* How much is in the portion we return back? */ - long int datastart; /* Offset from begining that data starts */ - uint16_t endsize; /* How much stuff at the end to skip over. This - stuff may have error correction (EDC, or ECC).*/ - uint16_t blocksize; /* total block size = start + size + end */ -} track_info_t; - /* Link element of track structure as a linked list. Possibly redundant with above track_info_t */ @@ -150,6 +62,7 @@ typedef struct { include pregap before next entry. */ uint64_t img_offset; /* Bytes offset from beginning of disk image file.*/ uint32_t blocksize; /* Number of bytes in a block */ + int flags; /* don't copy, 4 channel, pre-emphasis */ } _mapping_t; @@ -158,6 +71,17 @@ typedef struct { This must be first. */ generic_img_private_t gen; internal_position_t pos; + + /* This is common to all image drivers... */ + char *psz_cue_name; + char *psz_mcn; /* Media Catalog Number (5.22.3) */ + + track_info_t tocent[CDIO_CD_MAX_TRACKS+1]; /* entry info for each track + add 1 for leadout. */ + discmode_t disc_mode; + + /* Nero Specific stuff. Note: for the image_free to work, this *must* + be last. */ bool is_dao; /* True if some of disk at once. False if some sort of track at once. */ uint32_t mtyp; /* Value of MTYP (media type?) tag */ @@ -166,38 +90,38 @@ typedef struct { /* This is a hack because I don't really understnad NERO better. */ bool is_cues; - char *mcn; /* Media catalog number. */ - track_info_t tocent[100]; /* entry info for each track */ - track_t total_tracks; /* number of tracks in image */ - track_t first_track_num; /* track number of first track */ CdioList *mapping; /* List of track information */ uint32_t size; } _img_private_t; -static bool _cdio_parse_nero_footer (_img_private_t *_obj); -static uint32_t _cdio_stat_size (void *env); +static bool parse_nrg (_img_private_t *env, const char *psz_cue_name); +static uint32_t _stat_size_nrg (void *user_data); + +#include "image_common.h" /* Updates internal track TOC, so we can later simulate ioctl(CDROMREADTOCENTRY). */ static void -_register_mapping (_img_private_t *_obj, lsn_t start_lsn, uint32_t sec_count, +_register_mapping (_img_private_t *env, lsn_t start_lsn, uint32_t sec_count, uint64_t img_offset, uint32_t blocksize, - track_format_t track_format, bool track_green) + track_format_t track_format, bool track_green, + int flags) { - const int track_num=_obj->total_tracks; - track_info_t *this_track=&(_obj->tocent[_obj->total_tracks]); + const int track_num=env->gen.i_tracks; + track_info_t *this_track=&(env->tocent[env->gen.i_tracks]); _mapping_t *_map = _cdio_malloc (sizeof (_mapping_t)); _map->start_lsn = start_lsn; _map->sec_count = sec_count; _map->img_offset = img_offset; _map->blocksize = blocksize; + _map->flags = flags; - if (!_obj->mapping) _obj->mapping = _cdio_list_new (); - _cdio_list_append (_obj->mapping, _map); + if (!env->mapping) env->mapping = _cdio_list_new (); + _cdio_list_append (env->mapping, _map); - _obj->size = MAX (_obj->size, (start_lsn + sec_count)); + env->size = MAX (env->size, (start_lsn + sec_count)); /* Update *this_track and track_num. These structures are in a sense redundant witht the obj->mapping list. Perhaps one @@ -208,7 +132,7 @@ _register_mapping (_img_private_t *_obj, lsn_t start_lsn, uint32_t sec_count, this_track->start_lba = cdio_msf_to_lba(&this_track->start_msf); this_track->track_num = track_num+1; this_track->blocksize = blocksize; - if (_obj->is_cues) + if (env->is_cues) this_track->datastart = img_offset; else this_track->datastart = 0; @@ -260,10 +184,10 @@ _register_mapping (_img_private_t *_obj, lsn_t start_lsn, uint32_t sec_count, default: /*this_track->datasize=CDIO_CD_FRAMESIZE_RAW;*/ cdio_warn ("track %d has unknown format %d", - _obj->total_tracks, this_track->track_format); + env->gen.i_tracks, this_track->track_format); } - _obj->total_tracks++; + env->gen.i_tracks++; cdio_debug ("start lsn: %lu sector count: %0lu -> %8ld (%08lx)", (long unsigned int) start_lsn, @@ -276,66 +200,50 @@ _register_mapping (_img_private_t *_obj, lsn_t start_lsn, uint32_t sec_count, /* Disk and track information for a Nero file are located at the end of the file. This routine extracts that information. + + FIXME: right now psz_nrg_name is not used. It will be in the future. */ static bool -_cdio_parse_nero_footer (_img_private_t *_obj) +parse_nrg (_img_private_t *env, const char *psz_nrg_name) { long unsigned int footer_start; long unsigned int size; char *footer_buf = NULL; + cdio_log_level_t log_level = (NULL == env) ? CDIO_LOG_INFO : CDIO_LOG_WARN; - if (_obj->size) return true; - - size = cdio_stream_stat (_obj->gen.data_source); + size = cdio_stream_stat (env->gen.data_source); if (-1 == size) return false; { -PRAGMA_BEGIN_PACKED - union { - struct { - uint32_t __x GNUC_PACKED; - uint32_t ID GNUC_PACKED; - uint32_t footer_ofs GNUC_PACKED; - } v50; - struct { - uint32_t ID GNUC_PACKED; - uint64_t footer_ofs GNUC_PACKED; - } v55; - } buf; -PRAGMA_END_PACKED - + _footer_t buf; cdio_assert (sizeof (buf) == 12); - cdio_stream_seek (_obj->gen.data_source, size - sizeof (buf), SEEK_SET); - cdio_stream_read (_obj->gen.data_source, (void *) &buf, sizeof (buf), 1); + cdio_stream_seek (env->gen.data_source, size - sizeof (buf), SEEK_SET); + cdio_stream_read (env->gen.data_source, (void *) &buf, sizeof (buf), 1); - if (buf.v50.ID == UINT32_TO_BE (0x4e45524f)) /* "NERO" */ - { - cdio_info ("detected v50 (32bit offsets) NRG magic"); - footer_start = uint32_to_be (buf.v50.footer_ofs); - } - else if (buf.v55.ID == UINT32_TO_BE (0x4e455235)) /* "NER5" */ - { - cdio_info ("detected v55 (64bit offsets) NRG magic"); - footer_start = uint64_from_be (buf.v55.footer_ofs); - } - else - { - cdio_warn ("Image not recognized as either v50 or v55 type NRG"); - return false; - } + if (buf.v50.ID == UINT32_TO_BE (NERO_ID)) { + cdio_info ("detected Nero version 5.0 (32-bit offsets) NRG magic"); + footer_start = uint32_to_be (buf.v50.footer_ofs); + } else if (buf.v55.ID == UINT32_TO_BE (NER5_ID)) { + cdio_info ("detected Nero version 5.5.x (64-bit offsets) NRG magic"); + footer_start = uint64_from_be (buf.v55.footer_ofs); + } else { + cdio_log (log_level, "Image not recognized as either version 5.0 or " + "version 5.5.x-6.x type NRG"); + return false; + } - cdio_debug ("nrg footer start = %ld, length = %ld", + cdio_debug (".NRG footer start = %ld, length = %ld", (long) footer_start, (long) (size - footer_start)); cdio_assert (IN ((size - footer_start), 0, 4096)); footer_buf = _cdio_malloc (size - footer_start); - cdio_stream_seek (_obj->gen.data_source, footer_start, SEEK_SET); - cdio_stream_read (_obj->gen.data_source, footer_buf, size - footer_start, 1); + cdio_stream_seek (env->gen.data_source, footer_start, SEEK_SET); + cdio_stream_read (env->gen.data_source, footer_buf, + size - footer_start, 1); } - { int pos = 0; @@ -355,7 +263,7 @@ PRAGMA_END_PACKED unsigned entries = UINT32_FROM_BE (chunk->len); _cuex_array_t *_entries = (void *) chunk->data; - cdio_assert (_obj->mapping == NULL); + cdio_assert (env->mapping == NULL); cdio_assert ( sizeof (_cuex_array_t) == 8 ); cdio_assert ( UINT32_FROM_BE (chunk->len) % sizeof(_cuex_array_t) @@ -368,15 +276,22 @@ PRAGMA_END_PACKED int idx; cdio_info ("CUES type image detected" ); - /*cdio_assert (lsn == 0?);*/ + + /* CUES LSN has 150 pregap include at beginning? -/ + cdio_assert (lsn == 0?); + */ - _obj->is_cues = true; /* HACK alert. */ - _obj->total_tracks = 0; - _obj->first_track_num = 1; + env->is_cues = true; /* HACK alert. */ + env->gen.i_tracks = 0; + env->gen.i_first_track = 1; for (idx = 1; idx < entries-1; idx += 2) { lsn_t sec_count; - - cdio_assert (_entries[idx].index == 0); + int addrtype = _entries[idx].addr_ctrl / 16; + int control = _entries[idx].addr_ctrl % 16; + int flags = 0; + if ( 1 == control ) + flags &= ~CDIO_TRACK_FLAG_COPY_PERMITTED; + cdio_assert (_entries[idx].track == _entries[idx + 1].track); /* lsn and sec_count*2 aren't correct, but it comes closer on the @@ -384,103 +299,177 @@ PRAGMA_END_PACKED We are picking up the wrong fields and/or not interpreting them correctly. */ + + switch (addrtype) { + case 0: + lsn = UINT32_FROM_BE (_entries[idx].lsn); + break; + case 1: + { +#if 0 + msf_t msf = (msf_t) _entries[idx].lsn; + lsn = cdio_msf_to_lsn(&msf); +#else + lsn = CDIO_INVALID_LSN; +#endif + cdio_warn ("untested (i.e. probably wrong) CUE MSF code"); + break; + } + default: + lsn = CDIO_INVALID_LSN; + cdio_warn("unknown addrtype %d", addrtype); + } - lsn = UINT32_FROM_BE (_entries[idx].lsn); sec_count = UINT32_FROM_BE (_entries[idx + 1].lsn); - _register_mapping (_obj, lsn, sec_count*2, + _register_mapping (env, lsn, sec_count*2, (lsn+CDIO_PREGAP_SECTORS) * M2RAW_SECTOR_SIZE, - M2RAW_SECTOR_SIZE, TRACK_FORMAT_XA, true); + M2RAW_SECTOR_SIZE, TRACK_FORMAT_XA, true, + flags); } } else { lsn_t lsn = UINT32_FROM_BE (_entries[0].lsn); int idx; cdio_info ("CUEX type image detected"); - cdio_assert (lsn == 0xffffff6a); + + /* LSN must start at -150 (LBA 0)? */ + cdio_assert (lsn == -150); for (idx = 2; idx < entries; idx += 2) { lsn_t sec_count; - - cdio_assert (_entries[idx].index == 1); + int addrtype = _entries[idx].addr_ctrl >> 4; + int control = _entries[idx].addr_ctrl & 0xf; + int flags = 0; + if ( 1 == control ) + flags &= ~CDIO_TRACK_FLAG_COPY_PERMITTED; + + /* extractnrg.pl has addrtype for LBA's 0, and + for MSF 1. ??? + + FIXME: Should decode as appropriate for addrtype. + */ + cdio_assert ( addrtype == 0 || addrtype == 1 ); + cdio_assert (_entries[idx].track != _entries[idx + 1].track); lsn = UINT32_FROM_BE (_entries[idx].lsn); sec_count = UINT32_FROM_BE (_entries[idx + 1].lsn); - _register_mapping (_obj, lsn, sec_count - lsn, + _register_mapping (env, lsn, sec_count - lsn, (lsn + CDIO_PREGAP_SECTORS)*M2RAW_SECTOR_SIZE, - M2RAW_SECTOR_SIZE, TRACK_FORMAT_XA, true); + M2RAW_SECTOR_SIZE, TRACK_FORMAT_XA, true, + flags); } } break; } - case DAOI_ID: /* "DAOI" */ case DAOX_ID: /* "DAOX" */ + case DAOI_ID: /* "DAOI" */ { - _daox_array_t *_entries = (void *) chunk->data; track_format_t track_format; - int form = _entries->_unknown[18]; - _obj->dtyp = _entries->_unknown[36]; - _obj->is_dao = true; + int form2; + + /* We include an extra 0 byte so these can be used as C strings.*/ + env->psz_mcn = _cdio_malloc (CDIO_MCN_SIZE+1); + + if (DAOX_ID == opcode) { + _daox_array_t *_entries = (void *) chunk->data; + form2 = _entries->_unknown[1]; + env->dtyp = _entries->_unknown[19]; + memcpy(env->psz_mcn, &(_entries->psz_mcn), CDIO_MCN_SIZE); + env->psz_mcn[CDIO_MCN_SIZE] = '\0'; + } else { + _daoi_array_t *_entries = (void *) chunk->data; + form2 = _entries->_unknown[1]; + env->dtyp = _entries->_unknown[19]; + memcpy(env->psz_mcn, &(_entries->psz_mcn), CDIO_MCN_SIZE); + env->psz_mcn[CDIO_MCN_SIZE] = '\0'; + } + + env->is_dao = true; cdio_debug ("DAO%c tag detected, track format %d, form %x\n", - opcode==DAOX_ID ? 'X': 'I', _obj->dtyp, form); - switch (_obj->dtyp) { + opcode==DAOX_ID ? 'X': 'I', env->dtyp, form2); + switch (env->dtyp) { case 0: - track_format = TRACK_FORMAT_DATA; + /* Mode 1 */ + track_format = TRACK_FORMAT_DATA; + env->disc_mode = CDIO_DISC_MODE_CD_DATA; + break; + case 2: + /* Mode 2 form 1 */ + form2 = 0; + track_format = TRACK_FORMAT_XA; + env->disc_mode = CDIO_DISC_MODE_CD_XA; + break; + case 3: + /* Mode 2 */ + track_format = TRACK_FORMAT_XA; + env->disc_mode = CDIO_DISC_MODE_CD_XA; /* ?? */ break; case 0x6: - case 0x20: - track_format = TRACK_FORMAT_XA; + /* Mode2 form mix */ + track_format = TRACK_FORMAT_XA; + env->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + case 0x20: /* ??? Mode2 form 2, Mode2 raw?? */ + track_format = TRACK_FORMAT_XA; + env->disc_mode = CDIO_DISC_MODE_CD_XA; /* ??. */ break; case 0x7: - track_format = TRACK_FORMAT_AUDIO; + track_format = TRACK_FORMAT_AUDIO; + env->disc_mode = CDIO_DISC_MODE_CD_DA; break; default: - cdio_warn ("Unknown track format %x\n", - _obj->dtyp); + cdio_log (log_level, "Unknown track format %x\n", + env->dtyp); track_format = TRACK_FORMAT_AUDIO; } - if (0 == form) { + if (0 == form2) { int i; - for (i=0; i<_obj->total_tracks; i++) { - _obj->tocent[i].track_format= track_format; - _obj->tocent[i].datastart = 0; - _obj->tocent[i].track_green = false; + for (i=0; i<env->gen.i_tracks; i++) { + cdtext_init (&(env->gen.cdtext_track[i])); + env->tocent[i].track_format= track_format; + env->tocent[i].datastart = 0; + env->tocent[i].track_green = false; if (TRACK_FORMAT_AUDIO == track_format) { - _obj->tocent[i].blocksize = CDIO_CD_FRAMESIZE_RAW; - _obj->tocent[i].datasize = CDIO_CD_FRAMESIZE_RAW; - _obj->tocent[i].endsize = 0; + env->tocent[i].blocksize = CDIO_CD_FRAMESIZE_RAW; + env->tocent[i].datasize = CDIO_CD_FRAMESIZE_RAW; + env->tocent[i].endsize = 0; } else { - _obj->tocent[i].datasize = CDIO_CD_FRAMESIZE; - _obj->tocent[i].datastart = 0; + env->tocent[i].datasize = CDIO_CD_FRAMESIZE; + env->tocent[i].datastart = 0; } } - } else if (2 == form) { + } else if (2 == form2) { int i; - for (i=0; i<_obj->total_tracks; i++) { - _obj->tocent[i].track_green = true; - _obj->tocent[i].track_format= track_format; - _obj->tocent[i].datasize = CDIO_CD_FRAMESIZE; + for (i=0; i<env->gen.i_tracks; i++) { + cdtext_init (&(env->gen.cdtext_track[i])); + env->tocent[i].track_green = true; + env->tocent[i].track_format= track_format; + env->tocent[i].datasize = CDIO_CD_FRAMESIZE; if (TRACK_FORMAT_XA == track_format) { - _obj->tocent[i].datastart = CDIO_CD_SYNC_SIZE + env->tocent[i].datastart = CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE + CDIO_CD_SUBHEADER_SIZE; - _obj->tocent[i].endsize = CDIO_CD_SYNC_SIZE + env->tocent[i].endsize = CDIO_CD_SYNC_SIZE + CDIO_CD_ECC_SIZE; } else { - _obj->tocent[i].datastart = CDIO_CD_SYNC_SIZE + env->tocent[i].datastart = CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE; - _obj->tocent[i].endsize = CDIO_CD_EDC_SIZE + env->tocent[i].endsize = CDIO_CD_EDC_SIZE + CDIO_CD_M1F1_ZERO_SIZE + CDIO_CD_ECC_SIZE; } } + } else { + cdio_log (log_level, "Don't know if form1 or form2 form2: %x\n", + form2); } break; } - case NERO_ID: /* "NER0" */ - case NER5_ID: /* "NER5" */ + case NERO_ID: + case NER5_ID: cdio_error ("unexpected nrg magic ID NER%c detected", opcode==NERO_ID ? 'O': '5'); free(footer_buf); @@ -496,7 +485,7 @@ PRAGMA_END_PACKED unsigned entries = UINT32_FROM_BE (chunk->len); _etnf_array_t *_entries = (void *) chunk->data; - cdio_assert (_obj->mapping == NULL); + cdio_assert (env->mapping == NULL); cdio_assert ( sizeof (_etnf_array_t) == 20 ); cdio_assert ( UINT32_FROM_BE(chunk->len) % sizeof(_etnf_array_t) @@ -519,28 +508,49 @@ PRAGMA_END_PACKED switch (track_mode) { case 0: - track_format = TRACK_FORMAT_DATA; - track_green = false; /* ?? */ - blocksize = CDIO_CD_FRAMESIZE; + /* Mode 1 */ + track_format = TRACK_FORMAT_DATA; + track_green = false; /* ?? */ + blocksize = CDIO_CD_FRAMESIZE; + env->disc_mode = CDIO_DISC_MODE_CD_DATA; break; case 2: - track_format = TRACK_FORMAT_XA; - track_green = false; /* ?? */ - blocksize = CDIO_CD_FRAMESIZE; + /* Mode 2 form 1 */ + track_format = TRACK_FORMAT_XA; + track_green = false; /* ?? */ + blocksize = CDIO_CD_FRAMESIZE; + env->disc_mode = CDIO_DISC_MODE_CD_XA; break; case 3: - track_format = TRACK_FORMAT_XA; - track_green = true; - blocksize = M2RAW_SECTOR_SIZE; + /* Mode 2 */ + track_format = TRACK_FORMAT_XA; + track_green = true; + blocksize = M2RAW_SECTOR_SIZE; + env->disc_mode = CDIO_DISC_MODE_CD_XA; /* ?? */ + break; + case 06: + /* Mode2 form mix */ + track_format = TRACK_FORMAT_XA; + track_green = true; + blocksize = M2RAW_SECTOR_SIZE; + env->disc_mode = CDIO_DISC_MODE_CD_MIXED; + break; + case 0x20: /* ??? Mode2 form 2, Mode2 raw?? */ + track_format = TRACK_FORMAT_XA; + track_green = true; + blocksize = M2RAW_SECTOR_SIZE; + env->disc_mode = CDIO_DISC_MODE_CD_XA; /* ??. */ break; case 7: - track_format = TRACK_FORMAT_AUDIO; - track_green = false; - blocksize = CDIO_CD_FRAMESIZE_RAW; + track_format = TRACK_FORMAT_AUDIO; + track_green = false; + blocksize = CDIO_CD_FRAMESIZE_RAW; + env->disc_mode = CDIO_DISC_MODE_CD_DA; break; default: - cdio_warn ("Don't know how to handle track mode (%lu)?", - (long unsigned int) track_mode); + cdio_log (log_level, + "Don't know how to handle track mode (%lu)?", + (long unsigned int) track_mode); free(footer_buf); return false; } @@ -552,8 +562,8 @@ PRAGMA_END_PACKED cdio_assert (_start * blocksize == _start2); _start += idx * CDIO_PREGAP_SECTORS; - _register_mapping (_obj, _start, _len, _start2, blocksize, - track_format, track_green); + _register_mapping (env, _start, _len, _start2, blocksize, + track_format, track_green, 0); } } @@ -564,7 +574,7 @@ PRAGMA_END_PACKED unsigned entries = uint32_from_be (chunk->len); _etn2_array_t *_entries = (void *) chunk->data; - cdio_assert (_obj->mapping == NULL); + cdio_assert (env->mapping == NULL); cdio_assert (sizeof (_etn2_array_t) == 32); cdio_assert (uint32_from_be (chunk->len) % sizeof (_etn2_array_t) == 0); @@ -607,25 +617,30 @@ PRAGMA_END_PACKED blocksize = CDIO_CD_FRAMESIZE_RAW; break; default: - cdio_warn ("Don't know how to handle track mode (%lu)?", - (long unsigned int) track_mode); + cdio_log (log_level, + "Don't know how to handle track mode (%lu)?", + (long unsigned int) track_mode); free(footer_buf); return false; } if (_len % blocksize != 0) { - cdio_warn ("length is not a multiple of blocksize " + cdio_log (log_level, + "length is not a multiple of blocksize " "len %lu, size %d, rem %lu", (long unsigned int) _len, blocksize, (long unsigned int) _len % blocksize); if (0 == _len % CDIO_CD_FRAMESIZE) { - cdio_warn("Adjusting blocksize to %d", CDIO_CD_FRAMESIZE); + cdio_log(log_level, "Adjusting blocksize to %d", + CDIO_CD_FRAMESIZE); blocksize = CDIO_CD_FRAMESIZE; } else if (0 == _len % M2RAW_SECTOR_SIZE) { - cdio_warn("Adjusting blocksize to %d", M2RAW_SECTOR_SIZE); + cdio_log(log_level, + "Adjusting blocksize to %d", M2RAW_SECTOR_SIZE); blocksize = M2RAW_SECTOR_SIZE; } else if (0 == _len % CDIO_CD_FRAMESIZE_RAW) { - cdio_warn("Adjusting blocksize to %d", CDIO_CD_FRAMESIZE_RAW); + cdio_log(log_level, + "Adjusting blocksize to %d", CDIO_CD_FRAMESIZE_RAW); blocksize = CDIO_CD_FRAMESIZE_RAW; } } @@ -633,24 +648,28 @@ PRAGMA_END_PACKED _len /= blocksize; if (_start * blocksize != _start2) { - cdio_warn ("%lu * %d != %lu", + cdio_log (log_level, + "%lu * %d != %lu", (long unsigned int) _start, blocksize, (long unsigned int) _start2); if (_start * CDIO_CD_FRAMESIZE == _start2) { - cdio_warn("Adjusting blocksize to %d", CDIO_CD_FRAMESIZE); + cdio_log(log_level, + "Adjusting blocksize to %d", CDIO_CD_FRAMESIZE); blocksize = CDIO_CD_FRAMESIZE; } else if (_start * M2RAW_SECTOR_SIZE == _start2) { - cdio_warn("Adjusting blocksize to %d", M2RAW_SECTOR_SIZE); + cdio_log(log_level, + "Adjusting blocksize to %d", M2RAW_SECTOR_SIZE); blocksize = M2RAW_SECTOR_SIZE; } else if (0 == _start * CDIO_CD_FRAMESIZE_RAW == _start2) { - cdio_warn("Adjusting blocksize to %d", CDIO_CD_FRAMESIZE_RAW); + cdio_log(log_level, + "Adjusting blocksize to %d", CDIO_CD_FRAMESIZE_RAW); blocksize = CDIO_CD_FRAMESIZE_RAW; } } _start += idx * CDIO_PREGAP_SECTORS; - _register_mapping (_obj, _start, _len, _start2, blocksize, - track_format, track_green); + _register_mapping (env, _start, _len, _start2, blocksize, + track_format, track_green, 0); } } break; @@ -677,15 +696,24 @@ PRAGMA_END_PACKED (long unsigned int) UINT32_FROM_BE (*mtyp_p)); if (mtyp != MTYP_AUDIO_CD) { - cdio_warn ("Unknown MTYP value: %u", (unsigned int) mtyp); + cdio_log (log_level, + "Unknown MTYP value: %u", (unsigned int) mtyp); } - _obj->mtyp = mtyp; + env->mtyp = mtyp; } break; + case CDTX_ID: { /* "CD TEXT" */ + + cdio_log (log_level, + "Don't know how to handle CD TEXT yet" ); + break; + } + default: - cdio_warn ("unknown tag %8.8x seen", - (unsigned int) UINT32_FROM_BE (chunk->id)); + cdio_log (log_level, + "unknown tag %8.8x seen", + (unsigned int) UINT32_FROM_BE (chunk->id)); break; } @@ -698,14 +726,17 @@ PRAGMA_END_PACKED } /* Fake out leadout track. */ - /* Don't use _cdio_stat_size since that will lead to recursion since + /* Don't use _stat_size_nrg since that will lead to recursion since we haven't fully initialized things yet. */ - cdio_lsn_to_msf (_obj->size, &_obj->tocent[_obj->total_tracks].start_msf); - _obj->tocent[_obj->total_tracks].start_lba = cdio_lsn_to_lba(_obj->size); - _obj->tocent[_obj->total_tracks-1].sec_count = - cdio_lsn_to_lba(_obj->size - _obj->tocent[_obj->total_tracks-1].start_lba); - + cdio_lsn_to_msf (env->size, &env->tocent[env->gen.i_tracks].start_msf); + env->tocent[env->gen.i_tracks].start_lba = cdio_lsn_to_lba(env->size); + env->tocent[env->gen.i_tracks-1].sec_count = + cdio_lsn_to_lba(env->size - env->tocent[env->gen.i_tracks-1].start_lba); + + env->gen.b_cdtext_init = true; + env->gen.b_cdtext_error = false; + env->gen.toc_init = true; free(footer_buf); return true; } @@ -714,20 +745,31 @@ PRAGMA_END_PACKED Initialize image structures. */ static bool -_cdio_init (_img_private_t *_obj) +_init_nrg (_img_private_t *env) { - if (_obj->gen.init) { + if (env->gen.init) { cdio_error ("init called more than once"); return false; } - if (!(_obj->gen.data_source = cdio_stdio_new (_obj->gen.source_name))) { - cdio_warn ("init failed"); + if (!(env->gen.data_source = cdio_stdio_new (env->gen.source_name))) { + cdio_warn ("can't open nrg image file %s for reading", + env->gen.source_name); return false; } - _cdio_parse_nero_footer (_obj); - _obj->gen.init = true; + env->psz_mcn = NULL; + env->disc_mode = CDIO_DISC_MODE_NO_INFO; + + cdtext_init (&(env->gen.cdtext)); + + if ( !parse_nrg (env, env->gen.source_name) ) { + cdio_warn ("image file %s is not a Nero image", + env->gen.source_name); + return false; + } + + env->gen.init = true; return true; } @@ -739,40 +781,40 @@ _cdio_init (_img_private_t *_obj) information in each sector. */ static off_t -_cdio_lseek (void *env, off_t offset, int whence) +_lseek_nrg (void *user_data, off_t offset, int whence) { - _img_private_t *_obj = env; + _img_private_t *env = user_data; /* real_offset is the real byte offset inside the disk image The number below was determined empirically. */ - off_t real_offset= _obj->is_dao ? 0x4b000 : 0; + off_t real_offset= env->is_dao ? 0x4b000 : 0; unsigned int i; - for (i=0; i<_obj->total_tracks; i++) { - track_info_t *this_track=&(_obj->tocent[i]); - _obj->pos.index = i; + for (i=0; i<env->gen.i_tracks; i++) { + track_info_t *this_track=&(env->tocent[i]); + env->pos.index = i; if ( (this_track->sec_count*this_track->datasize) >= offset) { int blocks = offset / this_track->datasize; int rem = offset % this_track->datasize; int block_offset = blocks * this_track->blocksize; real_offset += block_offset + rem; - _obj->pos.buff_offset = rem; - _obj->pos.lba += blocks; + env->pos.buff_offset = rem; + env->pos.lba += blocks; break; } real_offset += this_track->sec_count*this_track->blocksize; offset -= this_track->sec_count*this_track->datasize; - _obj->pos.lba += this_track->sec_count; + env->pos.lba += this_track->sec_count; } - if (i==_obj->total_tracks) { + if (i==env->gen.i_tracks) { cdio_warn ("seeking outside range of disk image"); return -1; } else - real_offset += _obj->tocent[i].datastart; - return cdio_stream_seek(_obj->gen.data_source, real_offset, whence); + real_offset += env->tocent[i].datastart; + return cdio_stream_seek(env->gen.data_source, real_offset, whence); } /*! @@ -783,18 +825,18 @@ _cdio_lseek (void *env, off_t offset, int whence) boundaries. */ static ssize_t -_cdio_read (void *env, void *buf, size_t size) +_read_nrg (void *user_data, void *buf, size_t size) { - _img_private_t *_obj = env; - return cdio_stream_read(_obj->gen.data_source, buf, size, 1); + _img_private_t *env = user_data; + return cdio_stream_read(env->gen.data_source, buf, size, 1); } static uint32_t -_cdio_stat_size (void *env) +_stat_size_nrg (void *user_data) { - _img_private_t *_obj = env; + _img_private_t *env = user_data; - return _obj->size; + return env->size; } /*! @@ -802,21 +844,21 @@ _cdio_stat_size (void *env) from LSN. Returns 0 if no error. */ static int -_cdio_read_audio_sectors (void *env, void *data, lsn_t lsn, +_read_audio_sectors_nrg (void *user_data, void *data, lsn_t lsn, unsigned int nblocks) { - _img_private_t *_obj = env; + _img_private_t *env = user_data; CdioListNode *node; - if (lsn >= _obj->size) + if (lsn >= env->size) { cdio_warn ("trying to read beyond image size (%lu >= %lu)", - (long unsigned int) lsn, (long unsigned int) _obj->size); + (long unsigned int) lsn, (long unsigned int) env->size); return -1; } - _CDIO_LIST_FOREACH (node, _obj->mapping) { + _CDIO_LIST_FOREACH (node, env->mapping) { _mapping_t *_map = _cdio_list_node_data (node); if (IN (lsn, _map->start_lsn, (_map->start_lsn + _map->sec_count - 1))) { @@ -825,10 +867,10 @@ _cdio_read_audio_sectors (void *env, void *data, lsn_t lsn, img_offset += (lsn - _map->start_lsn) * CDIO_CD_FRAMESIZE_RAW; - ret = cdio_stream_seek (_obj->gen.data_source, img_offset, + ret = cdio_stream_seek (env->gen.data_source, img_offset, SEEK_SET); if (ret!=0) return ret; - ret = cdio_stream_read (_obj->gen.data_source, data, + ret = cdio_stream_read (env->gen.data_source, data, CDIO_CD_FRAMESIZE_RAW, nblocks); if (ret==0) return ret; break; @@ -842,22 +884,22 @@ _cdio_read_audio_sectors (void *env, void *data, lsn_t lsn, } static int -_cdio_read_mode1_sector (void *env, void *data, lsn_t lsn, +_read_mode1_sector_nrg (void *user_data, void *data, lsn_t lsn, bool b_form2) { - _img_private_t *_obj = env; + _img_private_t *env = user_data; char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; CdioListNode *node; - if (lsn >= _obj->size) + if (lsn >= env->size) { cdio_warn ("trying to read beyond image size (%lu >= %lu)", - (long unsigned int) lsn, (long unsigned int) _obj->size); + (long unsigned int) lsn, (long unsigned int) env->size); return -1; } - _CDIO_LIST_FOREACH (node, _obj->mapping) { + _CDIO_LIST_FOREACH (node, env->mapping) { _mapping_t *_map = _cdio_list_node_data (node); if (IN (lsn, _map->start_lsn, (_map->start_lsn + _map->sec_count - 1))) { @@ -866,12 +908,12 @@ _cdio_read_mode1_sector (void *env, void *data, lsn_t lsn, img_offset += (lsn - _map->start_lsn) * _map->blocksize; - ret = cdio_stream_seek (_obj->gen.data_source, img_offset, + ret = cdio_stream_seek (env->gen.data_source, img_offset, SEEK_SET); if (ret!=0) return ret; /* FIXME: Not completely sure the below is correct. */ - ret = cdio_stream_read (_obj->gen.data_source, + ret = cdio_stream_read (env->gen.data_source, (M2RAW_SECTOR_SIZE == _map->blocksize) ? (buf + CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE) : buf, @@ -896,16 +938,16 @@ _cdio_read_mode1_sector (void *env, void *data, lsn_t lsn, Returns 0 if no error. */ static int -_cdio_read_mode1_sectors (void *env, void *data, uint32_t lsn, - bool b_form2, unsigned nblocks) +_read_mode1_sectors_nrg (void *user_data, void *data, lsn_t lsn, + bool b_form2, unsigned nblocks) { - _img_private_t *_obj = env; + _img_private_t *env = user_data; int i; int retval; unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE; for (i = 0; i < nblocks; i++) { - if ( (retval = _cdio_read_mode1_sector (_obj, + if ( (retval = _read_mode1_sector_nrg (env, ((char *)data) + (blocksize * i), lsn + i, b_form2)) ) return retval; @@ -914,22 +956,22 @@ _cdio_read_mode1_sectors (void *env, void *data, uint32_t lsn, } static int -_cdio_read_mode2_sector (void *env, void *data, lsn_t lsn, +_read_mode2_sector_nrg (void *user_data, void *data, lsn_t lsn, bool b_form2) { - _img_private_t *_obj = env; + _img_private_t *env = user_data; char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; CdioListNode *node; - if (lsn >= _obj->size) + if (lsn >= env->size) { cdio_warn ("trying to read beyond image size (%lu >= %lu)", - (long unsigned int) lsn, (long unsigned int) _obj->size); + (long unsigned int) lsn, (long unsigned int) env->size); return -1; } - _CDIO_LIST_FOREACH (node, _obj->mapping) { + _CDIO_LIST_FOREACH (node, env->mapping) { _mapping_t *_map = _cdio_list_node_data (node); if (IN (lsn, _map->start_lsn, (_map->start_lsn + _map->sec_count - 1))) { @@ -938,10 +980,10 @@ _cdio_read_mode2_sector (void *env, void *data, lsn_t lsn, img_offset += (lsn - _map->start_lsn) * _map->blocksize; - ret = cdio_stream_seek (_obj->gen.data_source, img_offset, + ret = cdio_stream_seek (env->gen.data_source, img_offset, SEEK_SET); if (ret!=0) return ret; - ret = cdio_stream_read (_obj->gen.data_source, + ret = cdio_stream_read (env->gen.data_source, (M2RAW_SECTOR_SIZE == _map->blocksize) ? (buf + CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE) : buf, @@ -969,16 +1011,16 @@ _cdio_read_mode2_sector (void *env, void *data, lsn_t lsn, Returns 0 if no error. */ static int -_cdio_read_mode2_sectors (void *env, void *data, uint32_t lsn, - bool b_form2, unsigned nblocks) +_read_mode2_sectors_nrg (void *user_data, void *data, lsn_t lsn, + bool b_form2, unsigned nblocks) { - _img_private_t *_obj = env; + _img_private_t *env = user_data; int i; int retval; unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE; for (i = 0; i < nblocks; i++) { - if ( (retval = _cdio_read_mode2_sector (_obj, + if ( (retval = _read_mode2_sector_nrg (env, ((char *)data) + (blocksize * i), lsn + i, b_form2)) ) return retval; @@ -990,52 +1032,28 @@ _cdio_read_mode2_sectors (void *env, void *data, uint32_t lsn, Free memory resources associated with NRG object. */ static void -_cdio_nrg_destroy (void *obj) +_free_nrg (void *user_data) { - _img_private_t *env = obj; + _img_private_t *env = user_data; if (NULL == env) return; if (NULL != env->mapping) _cdio_list_free (env->mapping, true); - cdio_generic_stdio_free(env); - free(env); -} - -/* - Set the device to use in I/O operations. -*/ -static int -_cdio_set_arg (void *env, const char key[], const char value[]) -{ - _img_private_t *_obj = env; - - if (!strcmp (key, "source")) - { - free (_obj->gen.source_name); - - if (!value) - return -2; - _obj->gen.source_name = strdup (value); - } - else - return -1; - - return 0; + /* The remaining part of the image is like the other image drivers, + so free that in the same way. */ + _free_image(user_data); } /*! - Return the value associated with the key "arg". -*/ -static const char * -_cdio_get_arg (void *env, const char key[]) + Eject media -- there's nothing to do here except free resources. + We always return 2. + */ +static int +_eject_media_nrg(void *obj) { - _img_private_t *_obj = env; - - if (!strcmp (key, "source")) { - return _obj->gen.source_name; - } - return NULL; + _free_nrg (obj); + return 2; } /*! @@ -1074,28 +1092,14 @@ cdio_get_default_device_nrg(void) return drive; } -/*! - Return the number of of the first track. - CDIO_INVALID_TRACK is returned on error. -*/ -static track_t -_cdio_get_first_track_num(void *env) +static bool +get_hwinfo_nrg ( const CdIo *p_cdio, /*out*/ cdio_hwinfo_t *hw_info) { - _img_private_t *_obj = env; + strcpy(hw_info->psz_vendor, "libcdio"); + strcpy(hw_info->psz_model, "Nero"); + strcpy(hw_info->psz_revision, CDIO_VERSION); + return true; - return _obj->first_track_num; -} - -/*! - Return the number of tracks. We fake it an just say there's - one big track. -*/ -static track_t -_cdio_get_num_tracks(void *env) -{ - _img_private_t *_obj = env; - - return _obj->total_tracks; } /*! @@ -1103,15 +1107,15 @@ _cdio_get_num_tracks(void *env) CDIO_INVALID_TRACK is returned on error. */ static track_format_t -_cdio_get_track_format(void *env, track_t track_num) +get_track_format_nrg(void *user_data, track_t track_num) { - _img_private_t *_obj = env; + _img_private_t *env = user_data; - if (track_num > _obj->total_tracks || track_num == 0) + if (track_num > env->gen.i_tracks || track_num == 0) return TRACK_FORMAT_ERROR; - if ( _obj->dtyp != DTYP_INVALID) { - switch (_obj->dtyp) { + if ( env->dtyp != DTYP_INVALID) { + switch (env->dtyp) { case DTYP_MODE2_XA: return TRACK_FORMAT_XA; case DTYP_MODE1: @@ -1120,8 +1124,8 @@ _cdio_get_track_format(void *env, track_t track_num) } } - /*if ( MTYP_AUDIO_CD == _obj->mtyp) return TRACK_FORMAT_AUDIO; */ - return _obj->tocent[track_num-1].track_format; + /*if ( MTYP_AUDIO_CD == env->mtyp) return TRACK_FORMAT_AUDIO; */ + return env->tocent[track_num-1].track_format; } /*! @@ -1133,90 +1137,131 @@ _cdio_get_track_format(void *env, track_t track_num) FIXME: there's gotta be a better design for this and get_track_format? */ static bool -_cdio_get_track_green(void *env, track_t track_num) +_get_track_green_nrg(void *user_data, track_t track_num) { - _img_private_t *_obj = env; + _img_private_t *env = user_data; - if (track_num > _obj->total_tracks || track_num == 0) + if (track_num > env->gen.i_tracks || track_num == 0) return false; - if ( MTYP_AUDIO_CD == _obj->mtyp) return false; - return _obj->tocent[track_num-1].track_green; + if ( MTYP_AUDIO_CD == env->mtyp) return false; + return env->tocent[track_num-1].track_green; } -/*! - Return the starting MSF (minutes/secs/frames) for the track number - track_num in obj. Tracks numbers start at 1. - The "leadout" track is specified either by - using track_num LEADOUT_TRACK or the total tracks+1. +/*! + Check that a NRG file is valid. + */ -static bool -_cdio_get_track_msf(void *env, track_t track_num, msf_t *msf) +/* Later we'll probably do better. For now though, this gets us + started for now. +*/ +bool +cdio_is_nrg(const char *psz_nrg) { - _img_private_t *_obj = env; - - if (NULL == msf) return 1; + unsigned int i; + + if (psz_nrg == NULL) return false; - if (track_num == CDIO_CDROM_LEADOUT_TRACK) track_num = _obj->total_tracks+1; + i=strlen(psz_nrg)-strlen("nrg"); + + if (i>0) { + if (psz_nrg[i]=='n' && psz_nrg[i+1]=='r' && psz_nrg[i+2]=='g') { + return true; + } + else if (psz_nrg[i]=='N' && psz_nrg[i+1]=='R' && psz_nrg[i+2]=='G') { + return true; + } + } + return false; +} - if (track_num <= _obj->total_tracks+1 && track_num != 0) { - *msf = _obj->tocent[track_num-1].start_msf; - return true; - } else - return false; +/*! + Initialization routine. This is the only thing that doesn't + get called via a function pointer. In fact *we* are the + ones to set that up. + */ +CdIo * +cdio_open_am_nrg (const char *psz_source_name, const char *psz_access_mode) +{ + if (psz_access_mode != NULL && strcmp(psz_access_mode, "image")) + cdio_warn ("there is only one access mode for nrg. Arg %s ignored", + psz_access_mode); + return cdio_open_nrg(psz_source_name); } + CdIo * -cdio_open_nrg (const char *source_name) +cdio_open_nrg (const char *psz_source) { CdIo *ret; _img_private_t *_data; - cdio_funcs _funcs = { - .eject_media = cdio_generic_bogus_eject_media, - .free = _cdio_nrg_destroy, - .get_arg = _cdio_get_arg, - .get_devices = cdio_get_devices_nrg, - .get_default_device = cdio_get_default_device_nrg, - .get_first_track_num= _cdio_get_first_track_num, - .get_num_tracks = _cdio_get_num_tracks, - .get_track_format = _cdio_get_track_format, - .get_track_green = _cdio_get_track_green, - .get_track_lba = NULL, /* Will use generic routine via msf */ - .get_track_msf = _cdio_get_track_msf, - .lseek = _cdio_lseek, - .read = _cdio_read, - .read_audio_sectors = _cdio_read_audio_sectors, - .read_mode1_sector = _cdio_read_mode1_sector, - .read_mode1_sectors = _cdio_read_mode1_sectors, - .read_mode2_sector = _cdio_read_mode2_sector, - .read_mode2_sectors = _cdio_read_mode2_sectors, - .set_arg = _cdio_set_arg, - .stat_size = _cdio_stat_size, - }; - - _data = _cdio_malloc (sizeof (_img_private_t)); - _data->gen.init = false; - - _data->total_tracks = 0; - _data->mtyp = 0; - _data->dtyp = DTYP_INVALID; - _data->first_track_num= 1; - _data->is_dao = false; - _data->is_cues = false; /* FIXME: remove is_cues. */ - - - _cdio_set_arg(_data, "source", (NULL == source_name) - ? DEFAULT_CDIO_DEVICE: source_name); - - ret = cdio_new (_data, &_funcs); - if (ret == NULL) return NULL; - - if (_cdio_init(_data)) + cdio_funcs _funcs; + + memset( &_funcs, 0, sizeof(_funcs) ); + + _funcs.eject_media = _eject_media_nrg; + _funcs.free = _free_nrg; + _funcs.get_arg = _get_arg_image; + _funcs.get_cdtext = get_cdtext_generic; + _funcs.get_devices = cdio_get_devices_nrg; + _funcs.get_default_device = cdio_get_default_device_nrg; + _funcs.get_discmode = _get_discmode_image; + _funcs.get_drive_cap = _get_drive_cap_image; + _funcs.get_first_track_num= _get_first_track_num_image; + _funcs.get_hwinfo = get_hwinfo_nrg; + _funcs.get_mcn = _get_mcn_image; + _funcs.get_num_tracks = _get_num_tracks_image; + _funcs.get_track_format = get_track_format_nrg; + _funcs.get_track_green = _get_track_green_nrg; + _funcs.get_track_lba = NULL; /* Will use generic routine via msf */ + _funcs.get_track_msf = _get_track_msf_image; + _funcs.lseek = _lseek_nrg; + _funcs.read = _read_nrg; + _funcs.read_audio_sectors = _read_audio_sectors_nrg; + _funcs.read_mode1_sector = _read_mode1_sector_nrg; + _funcs.read_mode1_sectors = _read_mode1_sectors_nrg; + _funcs.read_mode2_sector = _read_mode2_sector_nrg; + _funcs.read_mode2_sectors = _read_mode2_sectors_nrg; + _funcs.set_arg = _set_arg_image; + _funcs.stat_size = _stat_size_nrg; + + _data = _cdio_malloc (sizeof (_img_private_t)); + _data->gen.init = false; + + _data->gen.i_tracks = 0; + _data->mtyp = 0; + _data->dtyp = DTYP_INVALID; + _data->gen.i_first_track= 1; + _data->is_dao = false; + _data->is_cues = false; /* FIXME: remove is_cues. */ + + ret = cdio_new ((void *)_data, &_funcs); + + if (ret == NULL) { + free(_data); + return NULL; + } + + _set_arg_image(_data, "source", (NULL == psz_source) + ? DEFAULT_CDIO_DEVICE: psz_source); + + _data->psz_cue_name = strdup(_get_arg_image(_data, "source")); + + if (!cdio_is_nrg(_data->psz_cue_name)) { + cdio_debug ("source name %s is not recognized as a NRG image", + _data->psz_cue_name); + _free_nrg(_data); + return NULL; + } + + _set_arg_image (_data, "cue", _data->psz_cue_name); + + if (_init_nrg(_data)) return ret; else { - cdio_generic_stdio_free (_data); - free(_data); + _free_nrg(_data); + free(ret); return NULL; } diff --git a/src/input/vcd/libcdio/image/nrg.h b/src/input/vcd/libcdio/image/nrg.h new file mode 100644 index 000000000..2923c78f1 --- /dev/null +++ b/src/input/vcd/libcdio/image/nrg.h @@ -0,0 +1,115 @@ +/* + $Id: nrg.h,v 1.1 2005/01/01 02:43:59 rockyb Exp $ + + Copyright (C) 2004 Rocky Bernstein <rocky@panix.com> + Copyright (C) 2001, 2003 Herbert Valerio Riedel <hvr@gnu.org> + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* NERO (NRG) file format structures. */ + +/* this ugly image format is typical for lazy win32 programmers... at + least structure were set big endian, so at reverse + engineering wasn't such a big headache... */ + +PRAGMA_BEGIN_PACKED +typedef union { + struct { + uint32_t __x GNUC_PACKED; + uint32_t ID GNUC_PACKED; + uint32_t footer_ofs GNUC_PACKED; + } v50; + struct { + uint32_t ID GNUC_PACKED; + uint64_t footer_ofs GNUC_PACKED; + } v55; +} _footer_t; + +typedef struct { + uint32_t start GNUC_PACKED; + uint32_t length GNUC_PACKED; + uint32_t type GNUC_PACKED; /* 0x0 -> MODE1, 0x2 -> MODE2 form1, + 0x3 -> MIXED_MODE2 2336 blocksize + */ + uint32_t start_lsn GNUC_PACKED; /* does not include any pre-gaps! */ + uint32_t _unknown GNUC_PACKED; /* wtf is this for? -- always zero... */ +} _etnf_array_t; + +/* Finally they realized that 32-bit offsets are a bit outdated for + IA64 *eg* */ +typedef struct { + uint64_t start GNUC_PACKED; + uint64_t length GNUC_PACKED; + uint32_t type GNUC_PACKED; /* 0x0 -> MODE1, 0x2 -> MODE2 form1, + 0x3 -> MIXED_MODE2 2336 blocksize + */ + uint32_t start_lsn GNUC_PACKED; + uint64_t _unknown GNUC_PACKED; /* wtf is this for? -- always zero... */ +} _etn2_array_t; + +typedef struct { + uint8_t type GNUC_PACKED; /* has track copy bit and whether audiofile + or datafile. Is often 0x41 == 'A' */ + uint8_t track GNUC_PACKED; /* binary or BCD?? */ + uint8_t addr_ctrl GNUC_PACKED; /* addresstype: MSF or LBA in lower 4 bits + control in upper 4 bits. + makes 0->1 transitions */ + uint8_t res GNUC_PACKED; /* ?? */ + uint32_t lsn GNUC_PACKED; +} _cuex_array_t; + +typedef struct { + uint32_t _unknown1 GNUC_PACKED; + char psz_mcn[CDIO_MCN_SIZE] GNUC_PACKED; + uint8_t _unknown[64-CDIO_MCN_SIZE-sizeof(uint32_t)] GNUC_PACKED; +} _daox_array_t; + +typedef struct { + uint32_t _unknown1 GNUC_PACKED; + char psz_mcn[CDIO_MCN_SIZE] GNUC_PACKED; + uint8_t _unknown[64-CDIO_MCN_SIZE-sizeof(uint32_t)] GNUC_PACKED; +} _daoi_array_t; + +typedef struct { + uint32_t id GNUC_PACKED; + uint32_t len GNUC_PACKED; + char data[EMPTY_ARRAY_SIZE] GNUC_PACKED; +} _chunk_t; + +PRAGMA_END_PACKED + +/* Nero images are Big Endian. */ +#define CDTX_ID 0x43445458 /* CD TEXT */ +#define CUEX_ID 0x43554558 /* Nero version 5.5.x-6.x */ +#define CUES_ID 0x43554553 /* Nero pre version 5.5.x-6.x */ +#define DAOX_ID 0x44414f58 /* Nero version 5.5.x-6.x */ +#define DAOI_ID 0x44414f49 +#define END1_ID 0x454e4421 +#define ETN2_ID 0x45544e32 +#define ETNF_ID 0x45544e46 +#define NER5_ID 0x4e455235 /* Nero version 5.5.x */ +#define NERO_ID 0x4e45524f /* Nero pre 5.5.x */ +#define SINF_ID 0x53494e46 /* Session information */ +#define MTYP_ID 0x4d545950 /* Disc Media type? */ + +#define MTYP_AUDIO_CD 1 /* This isn't correct. But I don't know the + the right thing is and it sometimes works (and + sometimes is wrong). */ + +/* Disk track type Values gleaned from DAOX */ +#define DTYP_MODE1 0 +#define DTYP_MODE2_XA 2 +#define DTYP_INVALID 255 diff --git a/src/input/vcd/libcdio/image_common.h b/src/input/vcd/libcdio/image_common.h new file mode 100644 index 000000000..30699c15c --- /dev/null +++ b/src/input/vcd/libcdio/image_common.h @@ -0,0 +1,225 @@ +/* + $Id: image_common.h,v 1.1 2005/01/01 02:43:57 rockyb Exp $ + + Copyright (C) 2004 Rocky Bernstein <rocky@panix.com> + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/*! Common image routines. + + Because _img_private_t may vary over image formats, the routines are + included into the image drivers after _img_private_t is defined. In + order for the below routines to work, there is a large part of + _img_private_t that is common among image drivers. For example, see + image.h +*/ + +#ifndef __CDIO_IMAGE_COMMON_H__ +#define __CDIO_IMAGE_COMMON_H__ + +#define free_if_notnull(obj) \ + if (NULL != obj) { free(obj); obj=NULL; }; + +/*! + We don't need the image any more. Free all memory associated with + it. + */ +static void +_free_image (void *user_data) +{ + _img_private_t *p_env = user_data; + track_t i_track; + + if (NULL == p_env) return; + + for (i_track=0; i_track < p_env->gen.i_tracks; i_track++) { + free_if_notnull(p_env->tocent[i_track].filename); + free_if_notnull(p_env->tocent[i_track].isrc); + cdtext_destroy(&(p_env->tocent[i_track].cdtext)); + } + + free_if_notnull(p_env->psz_mcn); + free_if_notnull(p_env->psz_cue_name); + cdtext_destroy(&(p_env->gen.cdtext)); + cdio_generic_stdio_free(p_env); + free(p_env); +} + +#ifdef NEED_MEDIA_EJECT_IMAGE +/*! + Eject media -- there's nothing to do here except free resources. + We always return 2. + */ +static int +_eject_media_image(void *user_data) +{ + _free_image (user_data); + return 2; +} +#endif + +/*! + Return the value associated with the key "arg". +*/ +static const char * +_get_arg_image (void *user_data, const char key[]) +{ + _img_private_t *p_env = user_data; + + if (!strcmp (key, "source")) { + return p_env->gen.source_name; + } else if (!strcmp (key, "cue")) { + return p_env->psz_cue_name; + } else if (!strcmp(key, "access-mode")) { + return "image"; + } + return NULL; +} + +/*! + Get disc type associated with cd_obj. +*/ +static discmode_t +_get_discmode_image (void *p_user_data) +{ + _img_private_t *p_env = p_user_data; + return p_env->disc_mode; +} + +/*! + Return the media catalog number (MCN) from the CD or NULL if there + is none or we don't have the ability to get it. + + Note: string is malloc'd so caller has to free() the returned + string when done with it. + */ +static char * +_get_mcn_image(const void *user_data) +{ + const _img_private_t *env = user_data; + + if (NULL == env || NULL == env->psz_mcn) return NULL; + return strdup(env->psz_mcn); +} + +/*! + Return the starting MSF (minutes/secs/frames) for the track number + track_num in obj. Tracks numbers start at 1. + The "leadout" track is specified either by + using track_num LEADOUT_TRACK or the total tracks+1. + +*/ +static bool +_get_track_msf_image(void *user_data, track_t track_num, msf_t *msf) +{ + _img_private_t *env = user_data; + + if (NULL == msf) return false; + + if (track_num == CDIO_CDROM_LEADOUT_TRACK) track_num = env->gen.i_tracks+1; + + if (track_num <= env->gen.i_tracks+1 && track_num != 0) { + *msf = env->tocent[track_num-env->gen.i_first_track].start_msf; + return true; + } else + return false; +} + +/*! + Return the number of of the first track. + CDIO_INVALID_TRACK is returned on error. +*/ +static track_t +_get_first_track_num_image(void *user_data) +{ + _img_private_t *env = user_data; + + return env->gen.i_first_track; +} + +/*! + Return the number of tracks. +*/ +static track_t +_get_num_tracks_image(void *user_data) +{ + _img_private_t *env = user_data; + + return env->gen.i_tracks; +} + +/*! + Set the arg "key" with "value" in the source device. + Currently "source" to set the source device in I/O operations + is the only valid key. + + 0 is returned if no error was found, and nonzero if there as an error. +*/ +static int +_set_arg_image (void *user_data, const char key[], const char value[]) +{ + _img_private_t *env = user_data; + + if (!strcmp (key, "source")) + { + free_if_notnull (env->gen.source_name); + + if (!value) + return -2; + + env->gen.source_name = strdup (value); + } + else if (!strcmp (key, "cue")) + { + free_if_notnull (env->psz_cue_name); + + if (!value) + return -2; + + env->psz_cue_name = strdup (value); + } + else + return -1; + + return 0; +} + +/*! + Return the the kind of drive capabilities of device. + + */ +static void +_get_drive_cap_image (const void *user_data, + cdio_drive_read_cap_t *p_read_cap, + cdio_drive_write_cap_t *p_write_cap, + cdio_drive_misc_cap_t *p_misc_cap) +{ + + *p_read_cap = CDIO_DRIVE_CAP_READ_AUDIO + | CDIO_DRIVE_CAP_READ_CD_G + | CDIO_DRIVE_CAP_READ_CD_R + | CDIO_DRIVE_CAP_READ_CD_RW + ; + + *p_write_cap = 0; + + /* In the future we may want to simulate + LOCK, OPEN_TRAY, CLOSE_TRAY, SELECT_SPEED, etc. + */ + *p_misc_cap = CDIO_DRIVE_CAP_MISC_FILE; +} + +#endif /* __CDIO_IMAGE_COMMON_H__ */ diff --git a/src/input/vcd/libcdio/iso9660.c b/src/input/vcd/libcdio/iso9660.c index c9c9ccb5e..4cb0bd062 100644 --- a/src/input/vcd/libcdio/iso9660.c +++ b/src/input/vcd/libcdio/iso9660.c @@ -1,8 +1,8 @@ /* - $Id: iso9660.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: iso9660.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> - Copyright (C) 2003 Rocky Bernstein <rocky@panix.com> + Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> 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 @@ -22,9 +22,9 @@ /* Private headers */ #include "iso9660_private.h" #include "cdio_assert.h" -#include "bytesex.h" /* Public headers */ +#include <cdio/bytesex.h> #include <cdio/iso9660.h> #include <cdio/util.h> @@ -37,12 +37,38 @@ #include <stdio.h> #endif -static const char _rcsid[] = "$Id: iso9660.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: iso9660.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $"; /* some parameters... */ #define SYSTEM_ID "CD-RTOS CD-BRIDGE" #define VOLUME_SET_ID "" +/*! + Change trailing blanks in str to nulls. Str has a maximum size of + n characters. +*/ +static char * +strip_trail (const char str[], size_t n) +{ + static char buf[1024]; + int j; + + cdio_assert (n < 1024); + + strncpy (buf, str, n); + buf[n] = '\0'; + + for (j = strlen (buf) - 1; j >= 0; j--) + { + if (buf[j] != ' ') + break; + + buf[j] = '\0'; + } + + return buf; +} + static void pathtable_get_size_and_entries(const void *pt, unsigned int *size, unsigned int *entries); @@ -52,72 +78,86 @@ pathtable_get_size_and_entries(const void *pt, unsigned int *size, record. Even though tm_wday and tm_yday fields are not explicitly in idr_date, the are calculated from the other fields. - If tm is to reflect the localtime set use_localtime true, otherwise + If tm is to reflect the localtime set b_localtime true, otherwise tm will reported in GMT. */ void -iso9660_get_dtime (const iso9660_dtime_t *idr_date, bool use_localtime, - /*out*/ struct tm *tm) +iso9660_get_dtime (const iso9660_dtime_t *idr_date, bool b_localtime, + /*out*/ struct tm *p_tm) { time_t t; - struct tm *temp_tm; + struct tm *p_temp_tm; if (!idr_date) return; - tm->tm_year = idr_date->dt_year; - tm->tm_mon = idr_date->dt_month - 1; - tm->tm_mday = idr_date->dt_day; - tm->tm_hour = idr_date->dt_hour; - tm->tm_min = idr_date->dt_minute; - tm->tm_sec = idr_date->dt_second; + memset(p_tm, 0, sizeof(struct tm)); + p_tm->tm_year = idr_date->dt_year; + p_tm->tm_mon = idr_date->dt_month - 1; + p_tm->tm_mday = idr_date->dt_day; + p_tm->tm_hour = idr_date->dt_hour; + p_tm->tm_min = idr_date->dt_minute; + p_tm->tm_sec = idr_date->dt_second; + +#if defined(HAVE_TM_GMTOFF) && defined(HAVE_TZSET) + if (b_localtime) { + tzset(); +#if defined(HAVE_TZNAME) + p_tm->tm_zone = (char *) tzname; +#endif +#if defined(HAVE_DAYLIGHT) + p_tm->tm_isdst = daylight; + p_tm->tm_gmtoff = timezone; +#endif + } +#endif /* Recompute tm_wday and tm_yday via mktime. */ - t = mktime(tm); + t = mktime(p_tm); - if (use_localtime) - temp_tm = localtime(&t); + if (b_localtime) + p_temp_tm = localtime(&t); else - temp_tm = gmtime(&t); + p_temp_tm = gmtime(&t); - memcpy(tm, temp_tm, sizeof(struct tm)); + memcpy(p_tm, p_temp_tm, sizeof(struct tm)); } /*! Set time in format used in ISO 9660 directory index record from a Unix time structure. */ void -iso9660_set_dtime (const struct tm *tm, /*out*/ iso9660_dtime_t *idr_date) +iso9660_set_dtime (const struct tm *p_tm, /*out*/ iso9660_dtime_t *p_idr_date) { - memset (idr_date, 0, 7); + memset (p_idr_date, 0, 7); - if (!tm) return; + if (!p_tm) return; - idr_date->dt_year = tm->tm_year; - idr_date->dt_month = tm->tm_mon + 1; - idr_date->dt_day = tm->tm_mday; - idr_date->dt_hour = tm->tm_hour; - idr_date->dt_minute = tm->tm_min; - idr_date->dt_second = tm->tm_sec; + p_idr_date->dt_year = p_tm->tm_year; + p_idr_date->dt_month = p_tm->tm_mon + 1; + p_idr_date->dt_day = p_tm->tm_mday; + p_idr_date->dt_hour = p_tm->tm_hour; + p_idr_date->dt_minute = p_tm->tm_min; + p_idr_date->dt_second = p_tm->tm_sec; #ifdef HAVE_TM_GMTOFF /* The ISO 9660 timezone is in the range -48..+52 and each unit represents a 15-minute interval. */ - idr_date->dt_gmtoff = tm->tm_gmtoff / (15 * 60); + p_idr_date->dt_gmtoff = p_tm->tm_gmtoff / (15 * 60); - if (tm->tm_isdst) idr_date->dt_gmtoff -= 4; + if (p_tm->tm_isdst) p_idr_date->dt_gmtoff -= 4; - if (idr_date->dt_gmtoff < -48 ) { + if (p_idr_date->dt_gmtoff < -48 ) { cdio_warn ("Converted ISO 9660 timezone %d is less than -48. Adjusted", - idr_date->dt_gmtoff); - idr_date->dt_gmtoff = -48; - } else if (idr_date->dt_gmtoff > 52) { + p_idr_date->dt_gmtoff); + p_idr_date->dt_gmtoff = -48; + } else if (p_idr_date->dt_gmtoff > 52) { cdio_warn ("Converted ISO 9660 timezone %d is over 52. Adjusted", - idr_date->dt_gmtoff); - idr_date->dt_gmtoff = 52; + p_idr_date->dt_gmtoff); + p_idr_date->dt_gmtoff = 52; } #else - idr_date->dt_gmtoff = 0; + p_idr_date->dt_gmtoff = 0; #endif } @@ -146,14 +186,28 @@ iso9660_set_ltime (const struct tm *_tm, /*out*/ iso9660_ltime_t *pvd_date) /*! Convert ISO-9660 file name that stored in a directory entry into what's usually listed as the file name in a listing. - Lowercase name, and trailing ;1's or .;1's and turn the - other ;'s into version numbers. + Lowercase name, and remove trailing ;1's or .;1's and + turn the other ;'s into version numbers. The length of the translated string is returned. */ int iso9660_name_translate(const char *old, char *new) { + return iso9660_name_translate_ext(old, new, 0); +} + +/*! + Convert ISO-9660 file name that stored in a directory entry into + what's usually listed as the file name in a listing. Lowercase + name if not using Joliet extension. Remove trailing ;1's or .;1's and + turn the other ;'s into version numbers. + + The length of the translated string is returned. +*/ +int +iso9660_name_translate_ext(const char *old, char *new, uint8_t i_joliet_level) +{ int len = strlen(old); int i; @@ -162,8 +216,8 @@ iso9660_name_translate(const char *old, char *new) if (!c) break; - /* lower case */ - if (isupper(c)) c = tolower(c); + /* Lower case, unless we have Joliet extensions. */ + if (!i_joliet_level && isupper(c)) c = tolower(c); /* Drop trailing '.;1' (ISO 9660:1988 7.5.1 requires period) */ if (c == '.' && i == len - 3 && old[i + 1] == ';' && old[i + 2] == '1') @@ -353,10 +407,13 @@ iso9660_set_pvd(void *pd, ipd.type_l_path_table = to_731(path_table_l_extent); ipd.type_m_path_table = to_732(path_table_m_extent); - cdio_assert (sizeof(ipd.root_directory_record) == 34); - memcpy(ipd.root_directory_record, root_dir, sizeof(ipd.root_directory_record)); - ipd.root_directory_record[0] = 34; - + /* root_directory_record doesn't contain the 1-byte filename, + so we add one for that. */ + cdio_assert (sizeof(ipd.root_directory_record) == 33); + memcpy(&(ipd.root_directory_record), root_dir, + sizeof(ipd.root_directory_record)); + ipd.root_directory_filename='\0'; + ipd.root_directory_record.length = 33+1; iso9660_strncpy_pad (ipd.volume_set_id, VOLUME_SET_ID, 128, ISO9660_DCHARS); iso9660_strncpy_pad (ipd.publisher_id, publisher_id, 128, ISO9660_ACHARS); @@ -797,6 +854,17 @@ iso9660_pathname_isofy (const char pathname[], uint16_t version) return strdup (tmpbuf); } +/*! + Return the PVD's application ID. + NULL is returned if there is some problem in getting this. +*/ +char * +iso9660_get_application_id(iso9660_pvd_t *p_pvd) +{ + if (NULL==p_pvd) return NULL; + return strdup(strip_trail(p_pvd->application_id, ISO_MAX_APPLICATION_ID)); +} + #if FIXME lsn_t iso9660_get_dir_extent(const iso9660_dir_t *idr) @@ -869,12 +937,66 @@ iso9660_get_root_lsn(const iso9660_pvd_t *pvd) if (NULL == pvd) return CDIO_INVALID_LSN; else { - iso9660_dir_t *idr = (void *) pvd->root_directory_record; + const iso9660_dir_t *idr = &(pvd->root_directory_record); if (NULL == idr) return CDIO_INVALID_LSN; return(from_733 (idr->extent)); } } +/*! + Return a string containing the preparer id with trailing + blanks removed. +*/ +char * +iso9660_get_preparer_id(const iso9660_pvd_t *pvd) +{ + if (NULL==pvd) return NULL; + return strdup(strip_trail(pvd->preparer_id, ISO_MAX_PREPARER_ID)); +} + +/*! + Return a string containing the publisher id with trailing + blanks removed. +*/ +char * +iso9660_get_publisher_id(const iso9660_pvd_t *pvd) +{ + if (NULL==pvd) return NULL; + return strdup(strip_trail(pvd->publisher_id, ISO_MAX_PUBLISHER_ID)); +} + +/*! + Return a string containing the PVD's system id with trailing + blanks removed. +*/ +char * +iso9660_get_system_id(const iso9660_pvd_t *pvd) +{ + if (NULL==pvd) return NULL; + return strdup(strip_trail(pvd->system_id, ISO_MAX_SYSTEM_ID)); +} + +/*! + Return the PVD's volume ID. +*/ +char * +iso9660_get_volume_id(const iso9660_pvd_t *pvd) +{ + if (NULL == pvd) return NULL; + return strdup(strip_trail(pvd->volume_id, ISO_MAX_VOLUME_ID)); +} + +/*! + Return the PVD's volumeset ID. + NULL is returned if there is some problem in getting this. +*/ +char * +iso9660_get_volumeset_id(const iso9660_pvd_t *pvd) +{ + if ( NULL == pvd ) return NULL; + return strdup(strip_trail(pvd->volume_set_id, ISO_MAX_VOLUMESET_ID)); +} + /* * Local variables: diff --git a/src/input/vcd/libcdio/iso9660_fs.c b/src/input/vcd/libcdio/iso9660_fs.c index 5841b7d87..0f49dfe5e 100644 --- a/src/input/vcd/libcdio/iso9660_fs.c +++ b/src/input/vcd/libcdio/iso9660_fs.c @@ -1,5 +1,5 @@ /* - $Id: iso9660_fs.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: iso9660_fs.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $ Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> @@ -24,48 +24,87 @@ #endif #ifdef HAVE_STRING_H -#include <string.h> +# include <string.h> +#endif + +#ifdef HAVE_ERRNO_H +# include <errno.h> +#endif + +#ifdef HAVE_ICONV +# include <iconv.h> +#endif + +#ifdef HAVE_LANGINFO_CODESET +#include <langinfo.h> #endif #include <cdio/cdio.h> +#include <cdio/bytesex.h> #include <cdio/iso9660.h> #include <cdio/util.h> /* Private headers */ #include "cdio_assert.h" -#include "bytesex.h" -#include "ds.h" #include "_cdio_stdio.h" #include "cdio_private.h" #include <stdio.h> -static const char _rcsid[] = "$Id: iso9660_fs.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: iso9660_fs.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $"; /* Implementation of iso9660_t type */ struct _iso9660 { CdioDataSource *stream; /* Stream pointer */ - void *env; /* environment. */ + bool b_xa; /* true if has XA attributes. */ + uint8_t i_joliet_level;/* 0 = no Joliet extensions. + 1-3: Joliet level. */ + iso9660_pvd_t pvd; + iso9660_svd_t svd; + iso_extension_mask_t iso_extension_mask; /* What extensions we + tolerate. */ }; /*! Open an ISO 9660 image for reading. Maybe in the future we will have - flags and mode. NULL is returned on error. + a mode. NULL is returned on error. +*/ +iso9660_t * +iso9660_open (const char *pathname /*, mode*/) +{ + return iso9660_open_ext(pathname, ISO_EXTENSION_NONE); +} + +/*! + Open an ISO 9660 image for reading. Maybe in the future we will have + a mode. NULL is returned on error. */ iso9660_t * -iso9660_open (const char *pathname /*flags, mode */) +iso9660_open_ext (const char *pathname, + iso_extension_mask_t iso_extension_mask) { - iso9660_t *iso = (iso9660_t *) _cdio_malloc(sizeof(struct _iso9660)) ; + iso9660_t *p_iso = (iso9660_t *) _cdio_malloc(sizeof(struct _iso9660)) ; - if (NULL == iso) return NULL; + if (NULL == p_iso) return NULL; - iso->stream = cdio_stdio_new( pathname ); - if (NULL == iso->stream) { - free(iso); - return NULL; - } + p_iso->stream = cdio_stdio_new( pathname ); + if (NULL == p_iso->stream) + goto error; + + if ( !iso9660_ifs_read_superblock(p_iso, iso_extension_mask) ) + goto error; + + /* Determine if image has XA attributes. */ - return iso; + p_iso->b_xa = !strncmp ((char *) &(p_iso->pvd) + ISO_XA_MARKER_OFFSET, + ISO_XA_MARKER_STRING, + strlen (ISO_XA_MARKER_STRING)); + p_iso->iso_extension_mask = iso_extension_mask; + return p_iso; + + error: + free(p_iso); + return NULL; } @@ -76,67 +115,535 @@ iso9660_open (const char *pathname /*flags, mode */) be returned. */ bool -iso9660_close (iso9660_t *iso) +iso9660_close (iso9660_t *p_iso) +{ + if (NULL != p_iso) { + cdio_stdio_destroy(p_iso->stream); + free(p_iso); + } + return true; +} + +static bool +check_pvd (const iso9660_pvd_t *p_pvd) +{ + if ( ISO_VD_PRIMARY != from_711(p_pvd->type) ) { + cdio_warn ("unexpected PVD type %d", p_pvd->type); + return false; + } + + if (strncmp (p_pvd->id, ISO_STANDARD_ID, strlen (ISO_STANDARD_ID))) + { + cdio_warn ("unexpected ID encountered (expected `" + ISO_STANDARD_ID "', got `%.5s'", p_pvd->id); + return false; + } + return true; +} + +#ifdef HAVE_JOLIET +static bool +ucs2be_to_locale(ICONV_CONST char *psz_ucs2be, size_t i_inlen, + char **p_psz_out, size_t i_outlen) +{ + + iconv_t ic = +#if defined(HAVE_LANGINFO_CODESET) + iconv_open(nl_langinfo(CODESET), "UCS-2BE"); +#else + iconv_open("ASCII", "UCS-2BE"); +#endif + + int rc; + char *psz_buf = NULL; + char *psz_buf2; + int i_outlen_max = i_outlen; + int i_outlen_actual; + + if (-1 == (size_t) ic) { +#if defined(HAVE_LANGINFO_CODESET) + cdio_info("Failed to get conversion table for locale, trying ASCII"); + ic = iconv_open("ASCII", "UCS-2BE"); + if (-1 == (size_t) ic) { + cdio_info("Failed to get conversion table for ASCII too"); + return false; + } +#else + cdio_info("Failed to get conversion table for locale"); + return false; +#endif + } + + psz_buf = (char *) realloc(psz_buf, i_outlen); + psz_buf2 = psz_buf; + if (!psz_buf) { + /* XXX: report out of memory error */ + goto error; + } + rc = iconv(ic, &psz_ucs2be, &i_inlen, &psz_buf2, &i_outlen); + iconv_close(ic); + if ((rc == -1) && (errno != E2BIG)) { + /* conversion failed */ + goto error; + } + i_outlen_actual = i_outlen_max - i_outlen; + *p_psz_out = malloc(i_outlen_actual + 1); + memcpy(*p_psz_out, psz_buf, i_outlen_actual); + *(*p_psz_out + i_outlen_actual) = '\0'; + free(psz_buf); + return true; + error: + free(psz_buf); + *p_psz_out = NULL; + return false; +} +#endif /*HAVE_JOLIET*/ + +/*! + Return the application ID. NULL is returned in psz_app_id if there + is some problem in getting this. +*/ +bool +iso9660_ifs_get_application_id(iso9660_t *p_iso, + /*out*/ char **p_psz_app_id) +{ + if (!p_iso) { + *p_psz_app_id = NULL; + return false; + } + +#ifdef HAVE_JOLIET + if (p_iso->i_joliet_level) { + /* TODO: check that we haven't reached the maximum size. + If we have, perhaps we've truncated and if we can get + longer results *and* have the same character using + the PVD, do that. + */ + if ( ucs2be_to_locale(p_iso->svd.application_id, + ISO_MAX_APPLICATION_ID, + p_psz_app_id, + ISO_MAX_APPLICATION_ID)) + return true; + } +#endif /*HAVE_JOLIET*/ + *p_psz_app_id = iso9660_get_application_id( &(p_iso->pvd) ); + return *p_psz_app_id != NULL && strlen(*p_psz_app_id); +} + +/*! + Return the Joliet level recognaized for p_iso. +*/ +uint8_t iso9660_ifs_get_joliet_level(iso9660_t *p_iso) +{ + if (!p_iso) return 0; + return p_iso->i_joliet_level; +} + +/*! + Return a string containing the preparer id with trailing + blanks removed. +*/ +bool +iso9660_ifs_get_preparer_id(iso9660_t *p_iso, + /*out*/ char **p_psz_preparer_id) +{ + if (!p_iso) { + *p_psz_preparer_id = NULL; + return false; + } + +#ifdef HAVE_JOLIET + if (p_iso->i_joliet_level) { + /* TODO: check that we haven't reached the maximum size. + If we have, perhaps we've truncated and if we can get + longer results *and* have the same character using + the PVD, do that. + */ + if ( ucs2be_to_locale(p_iso->svd.preparer_id, ISO_MAX_PREPARER_ID, + p_psz_preparer_id, ISO_MAX_PREPARER_ID) ) + return true; + } +#endif /*HAVE_JOLIET*/ + *p_psz_preparer_id = iso9660_get_preparer_id( &(p_iso->pvd) ); + return *p_psz_preparer_id != NULL && strlen(*p_psz_preparer_id); +} + +/*! + Return a string containing the PVD's publisher id with trailing + blanks removed. +*/ +bool iso9660_ifs_get_publisher_id(iso9660_t *p_iso, + /*out*/ char **p_psz_publisher_id) +{ + if (!p_iso) { + *p_psz_publisher_id = NULL; + return false; + } + +#ifdef HAVE_JOLIET + if (p_iso->i_joliet_level) { + /* TODO: check that we haven't reached the maximum size. + If we have, perhaps we've truncated and if we can get + longer results *and* have the same character using + the PVD, do that. + */ + if( ucs2be_to_locale(p_iso->svd.publisher_id, ISO_MAX_PUBLISHER_ID, + p_psz_publisher_id, ISO_MAX_PUBLISHER_ID) ) + return true; + } +#endif /*HAVE_JOLIET*/ + *p_psz_publisher_id = iso9660_get_publisher_id( &(p_iso->pvd) ); + return *p_psz_publisher_id != NULL && strlen(*p_psz_publisher_id); +} + + +/*! + Return a string containing the PVD's publisher id with trailing + blanks removed. +*/ +bool iso9660_ifs_get_system_id(iso9660_t *p_iso, + /*out*/ char **p_psz_system_id) +{ + if (!p_iso) { + *p_psz_system_id = NULL; + return false; + } + +#ifdef HAVE_JOLIET + if (p_iso->i_joliet_level) { + /* TODO: check that we haven't reached the maximum size. + If we have, perhaps we've truncated and if we can get + longer results *and* have the same character using + the PVD, do that. + */ + if ( ucs2be_to_locale(p_iso->svd.system_id, ISO_MAX_SYSTEM_ID, + p_psz_system_id, ISO_MAX_SYSTEM_ID) ) + return true; + } +#endif /*HAVE_JOLIET*/ + *p_psz_system_id = iso9660_get_system_id( &(p_iso->pvd) ); + return *p_psz_system_id != NULL && strlen(*p_psz_system_id); +} + + +/*! + Return a string containing the PVD's publisher id with trailing + blanks removed. +*/ +bool iso9660_ifs_get_volume_id(iso9660_t *p_iso, + /*out*/ char **p_psz_volume_id) +{ + if (!p_iso) { + *p_psz_volume_id = NULL; + return false; + } + +#ifdef HAVE_JOLIET + if (p_iso->i_joliet_level) { + /* TODO: check that we haven't reached the maximum size. + If we have, perhaps we've truncated and if we can get + longer results *and* have the same character using + the PVD, do that. + */ + if ( ucs2be_to_locale(p_iso->svd.volume_id, ISO_MAX_VOLUME_ID, + p_psz_volume_id, ISO_MAX_VOLUME_ID) ) + return true; + } +#endif /* HAVE_JOLIET */ + *p_psz_volume_id = iso9660_get_volume_id( &(p_iso->pvd) ); + return *p_psz_volume_id != NULL && strlen(*p_psz_volume_id); +} + + +/*! + Return a string containing the PVD's publisher id with trailing + blanks removed. +*/ +bool iso9660_ifs_get_volumeset_id(iso9660_t *p_iso, + /*out*/ char **p_psz_volumeset_id) +{ + if (!p_iso) { + *p_psz_volumeset_id = NULL; + return false; + } + +#ifdef HAVE_JOLIET + if (p_iso->i_joliet_level) { + /* TODO: check that we haven't reached the maximum size. + If we have, perhaps we've truncated and if we can get + longer results *and* have the same character using + the PVD, do that. + */ + if ( ucs2be_to_locale(p_iso->svd.volume_set_id, + ISO_MAX_VOLUMESET_ID, + p_psz_volumeset_id, + ISO_MAX_VOLUMESET_ID) ) + return true; + } +#endif /*HAVE_JOLIET*/ + *p_psz_volumeset_id = iso9660_get_volume_id( &(p_iso->pvd) ); + return *p_psz_volumeset_id != NULL && strlen(*p_psz_volumeset_id); +} + + +/*! + Read the Primary Volume Descriptor for an ISO 9660 image. + True is returned if read, and false if there was an error. +*/ +bool +iso9660_ifs_read_pvd (const iso9660_t *p_iso, /*out*/ iso9660_pvd_t *p_pvd) { - if (NULL != iso) { - cdio_stdio_destroy(iso->stream); - free(iso); + if (0 == iso9660_iso_seek_read (p_iso, p_pvd, ISO_PVD_SECTOR, 1)) { + cdio_warn ("error reading PVD sector (%d)", ISO_PVD_SECTOR); + return false; + } + return check_pvd(p_pvd); +} + + +/*! + Read the Super block of an ISO 9660 image. This is the + Primary Volume Descriptor (PVD) and perhaps a Supplemental Volume + Descriptor if (Joliet) extensions are acceptable. +*/ +bool +iso9660_ifs_read_superblock (iso9660_t *p_iso, + iso_extension_mask_t iso_extension_mask) +{ + iso9660_svd_t *p_svd; /* Secondary volume descriptor. */ + + if (!p_iso || !iso9660_ifs_read_pvd(p_iso, &(p_iso->pvd))) + return false; + + p_svd = &(p_iso->svd); + p_iso->i_joliet_level = 0; + + if (0 != iso9660_iso_seek_read (p_iso, p_svd, ISO_PVD_SECTOR+1, 1)) { + if ( ISO_VD_SUPPLEMENTARY == from_711(p_svd->type) ) { + if (p_svd->escape_sequences[0] == 0x25 + && p_svd->escape_sequences[1] == 0x2f) { + switch (p_svd->escape_sequences[2]) { + case 0x40: + if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL1) + p_iso->i_joliet_level = 1; + break; + case 0x43: + if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL2) + p_iso->i_joliet_level = 2; + break; + case 0x45: + if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL3) + p_iso->i_joliet_level = 3; + break; + default: + cdio_info("Supplementary Volume Descriptor found, but not Joliet"); + } + if (p_iso->i_joliet_level > 0) { + cdio_info("Found Extension: Joliet Level %d", p_iso->i_joliet_level); + } + } + } } + return true; } +/*! + Read the Primary Volume Descriptor for of CD. +*/ +bool +iso9660_fs_read_pvd(const CdIo *p_cdio, /*out*/ iso9660_pvd_t *p_pvd) +{ + /* A bit of a hack, we'll assume track 1 contains ISO_PVD_SECTOR.*/ + bool b_mode2; + char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; + int i_rc; + + switch(cdio_get_track_format(p_cdio, 1)) { + case TRACK_FORMAT_CDI: + case TRACK_FORMAT_XA: + b_mode2 = true; + break; + case TRACK_FORMAT_DATA: + b_mode2 = false; + break; + case TRACK_FORMAT_AUDIO: + case TRACK_FORMAT_PSX: + case TRACK_FORMAT_ERROR: + default: + return false; + } + + i_rc = b_mode2 + ? cdio_read_mode2_sector (p_cdio, buf, ISO_PVD_SECTOR, false) + : cdio_read_mode1_sector (p_cdio, buf, ISO_PVD_SECTOR, false); + + if (i_rc) { + cdio_warn ("error reading PVD sector (%d)", ISO_PVD_SECTOR); + return false; + } + + /* The size of a PVD or SVD is smaller than a sector. So we + allocated a bigger block above (buf) and now we'll copy just + the part we need to save. + */ + cdio_assert (sizeof(buf) >= sizeof (iso9660_pvd_t)); + memcpy(p_pvd, buf, sizeof(iso9660_pvd_t)); + + return check_pvd(p_pvd); +} + + +/*! + Read the Super block of an ISO 9660 image. This is the + Primary Volume Descriptor (PVD) and perhaps a Supplemental Volume + Descriptor if (Joliet) extensions are acceptable. +*/ +bool +iso9660_fs_read_superblock (CdIo *p_cdio, + iso_extension_mask_t iso_extension_mask) +{ + if (!p_cdio) return false; + + { + generic_img_private_t *p_env = (generic_img_private_t *) p_cdio->env; + iso9660_pvd_t *p_pvd = &(p_env->pvd); + iso9660_svd_t *p_svd = &(p_env->svd); + char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; + bool b_mode2; + int i_rc; + + /* A bit of a hack, we'll assume track 1 contains ISO_PVD_SECTOR.*/ + switch(cdio_get_track_format(p_cdio, 1)) { + case TRACK_FORMAT_CDI: + case TRACK_FORMAT_XA: + b_mode2 = true; + break; + case TRACK_FORMAT_DATA: + b_mode2 = false; + break; + case TRACK_FORMAT_AUDIO: + case TRACK_FORMAT_PSX: + case TRACK_FORMAT_ERROR: + default: + return false; + } + + if ( !iso9660_fs_read_pvd(p_cdio, p_pvd) ) + return false; + + p_env->i_joliet_level = 0; + + i_rc = (b_mode2) + ? cdio_read_mode2_sector (p_cdio, buf, ISO_PVD_SECTOR+1, false) + : cdio_read_mode1_sector (p_cdio, buf, ISO_PVD_SECTOR+1, false); + + if (0 == i_rc) { + /* The size of a PVD or SVD is smaller than a sector. So we + allocated a bigger block above (buf) and now we'll copy just + the part we need to save. + */ + cdio_assert (sizeof(buf) >= sizeof (iso9660_svd_t)); + memcpy(p_svd, buf, sizeof(iso9660_svd_t)); + + if ( ISO_VD_SUPPLEMENTARY == from_711(p_svd->type) ) { + if (p_svd->escape_sequences[0] == 0x25 + && p_svd->escape_sequences[1] == 0x2f) { + switch (p_svd->escape_sequences[2]) { + case 0x40: + if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL1) + p_env->i_joliet_level = 1; + break; + case 0x43: + if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL2) + p_env->i_joliet_level = 2; + break; + case 0x45: + if (iso_extension_mask & ISO_EXTENSION_JOLIET_LEVEL3) + p_env->i_joliet_level = 3; + break; + default: + cdio_info("Supplementary Volume Descriptor found, but not Joliet"); + } + if (p_env->i_joliet_level > 0) { + cdio_info("Found Extension: Joliet Level %d", + p_env->i_joliet_level); + } + } + } + } + } + + return true; +} /*! Seek to a position and then read n blocks. Size read is returned. */ long int -iso9660_iso_seek_read (iso9660_t *iso, void *ptr, lsn_t start, long int size) +iso9660_iso_seek_read (const iso9660_t *p_iso, void *ptr, lsn_t start, + long int size) { long int ret; - if (NULL == iso) return 0; - ret = cdio_stream_seek (iso->stream, start * ISO_BLOCKSIZE, SEEK_SET); + if (NULL == p_iso) return 0; + ret = cdio_stream_seek (p_iso->stream, start * ISO_BLOCKSIZE, SEEK_SET); if (ret!=0) return 0; - return cdio_stream_read (iso->stream, ptr, ISO_BLOCKSIZE, size); + return cdio_stream_read (p_iso->stream, ptr, ISO_BLOCKSIZE, size); } static iso9660_stat_t * -_iso9660_dir_to_statbuf (const iso9660_dir_t *iso9660_dir, bool is_mode2) +_iso9660_dir_to_statbuf (iso9660_dir_t *p_iso9660_dir, + bool b_mode2, uint8_t i_joliet_level) { iso9660_xa_t *xa_data = NULL; - uint8_t dir_len= iso9660_get_dir_len(iso9660_dir); + uint8_t dir_len= iso9660_get_dir_len(p_iso9660_dir); unsigned int filename_len; unsigned int stat_len; iso9660_stat_t *stat; if (!dir_len) return NULL; - filename_len = from_711(iso9660_dir->filename_len); + filename_len = from_711(p_iso9660_dir->filename_len); - /* .. string in statbuf is one longer than in iso9660_dir's listing '\1' */ + /* .. string in statbuf is one longer than in p_iso9660_dir's listing '\1' */ stat_len = sizeof(iso9660_stat_t)+filename_len+2; stat = _cdio_malloc(stat_len); - stat->type = (iso9660_dir->file_flags & ISO_DIRECTORY) + stat->type = (p_iso9660_dir->file_flags & ISO_DIRECTORY) ? _STAT_DIR : _STAT_FILE; - stat->lsn = from_733 (iso9660_dir->extent); - stat->size = from_733 (iso9660_dir->size); + stat->lsn = from_733 (p_iso9660_dir->extent); + stat->size = from_733 (p_iso9660_dir->size); stat->secsize = _cdio_len2blocks (stat->size, ISO_BLOCKSIZE); - if (iso9660_dir->filename[0] == '\0') + if ('\0' == p_iso9660_dir->filename[0] && 1 == filename_len) strcpy (stat->filename, "."); - else if (iso9660_dir->filename[0] == '\1') + else if ('\1' == p_iso9660_dir->filename[0] && 1 == filename_len) strcpy (stat->filename, ".."); - else - strncpy (stat->filename, iso9660_dir->filename, filename_len); + else { +#ifdef HAVE_JOLIET + if (i_joliet_level) { + int i_inlen = filename_len; + int i_outlen = (i_inlen / 2); + char *p_psz_out = NULL; + ucs2be_to_locale(p_iso9660_dir->filename, i_inlen, + &p_psz_out, i_outlen); + strncpy(stat->filename, p_psz_out, filename_len); + free(p_psz_out); + } else +#endif /*HAVE_JOLIET*/ + strncpy (stat->filename, p_iso9660_dir->filename, filename_len); + } + - iso9660_get_dtime(&(iso9660_dir->recording_time), true, &(stat->tm)); + iso9660_get_dtime(&(p_iso9660_dir->recording_time), true, &(stat->tm)); cdio_assert (dir_len >= sizeof (iso9660_dir_t)); - if (is_mode2) { - int su_length = iso9660_get_dir_len(iso9660_dir) - sizeof (iso9660_dir_t); + if (b_mode2) { + int su_length = iso9660_get_dir_len(p_iso9660_dir) + - sizeof (iso9660_dir_t); su_length -= filename_len; if (su_length % 2) @@ -145,8 +652,8 @@ _iso9660_dir_to_statbuf (const iso9660_dir_t *iso9660_dir, bool is_mode2) if (su_length < 0 || su_length < sizeof (iso9660_xa_t)) return stat; - xa_data = (void *) (((char *) iso9660_dir) - + (iso9660_get_dir_len(iso9660_dir) - su_length)); + xa_data = (void *) (((char *) p_iso9660_dir) + + (iso9660_get_dir_len(p_iso9660_dir) - su_length)); if (xa_data->signature[0] != 'X' || xa_data->signature[1] != 'A') @@ -154,7 +661,7 @@ _iso9660_dir_to_statbuf (const iso9660_dir_t *iso9660_dir, bool is_mode2) cdio_warn ("XA signature not found in ISO9660's system use area;" " ignoring XA attributes for this file entry."); cdio_debug ("%d %d %d, '%c%c' (%d, %d)", - iso9660_get_dir_len(iso9660_dir), + iso9660_get_dir_len(p_iso9660_dir), filename_len, su_length, xa_data->signature[0], xa_data->signature[1], @@ -194,57 +701,80 @@ iso9660_dir_to_name (const iso9660_dir_t *iso9660_dir) return strdup (namebuf); } - +/* + Return a pointer to a ISO 9660 stat buffer or NULL if there's an error +*/ static iso9660_stat_t * -_fs_stat_root (const CdIo *cdio, bool is_mode2) +_fs_stat_root (CdIo *p_cdio) { - char block[ISO_BLOCKSIZE] = { 0, }; - const iso9660_pvd_t *pvd = (void *) █ - const iso9660_dir_t *iso9660_dir = (void *) pvd->root_directory_record; - iso9660_stat_t *stat; - if (is_mode2) { - if (cdio_read_mode2_sector (cdio, &block, ISO_PVD_SECTOR, false)) - cdio_assert_not_reached (); - } else { - if (cdio_read_mode1_sector (cdio, &block, ISO_PVD_SECTOR, false)) - cdio_assert_not_reached (); - } + if (!p_cdio) return NULL; + + { + iso_extension_mask_t iso_extension_mask = ISO_EXTENSION_ALL; + generic_img_private_t *p_env = (generic_img_private_t *) p_cdio->env; + bool b_mode2 = cdio_get_track_green(p_cdio, 1); + iso9660_dir_t *p_iso9660_dir; + iso9660_stat_t *p_stat; + + if (!p_env->i_joliet_level) + iso_extension_mask &= ~ISO_EXTENSION_JOLIET; + + /* FIXME try also with Joliet.*/ + if ( !iso9660_fs_read_superblock (p_cdio, iso_extension_mask) ) { + cdio_warn("Could not read ISO-9660 Superblock."); + return NULL; + } - stat = _iso9660_dir_to_statbuf (iso9660_dir, is_mode2); - return stat; +#ifdef HAVE_JOLIET + p_iso9660_dir = p_env->i_joliet_level + ? &(p_env->svd.root_directory_record) + : &(p_env->pvd.root_directory_record) ; +#else + p_iso9660_dir = &(p_env->pvd.root_directory_record) ; +#endif + + p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, b_mode2, + p_env->i_joliet_level); + return p_stat; + } + } static iso9660_stat_t * -_fs_stat_iso_root (iso9660_t *iso) +_fs_stat_iso_root (iso9660_t *p_iso) { - char block[ISO_BLOCKSIZE] = { 0, }; - const iso9660_pvd_t *pvd = (void *) █ - const iso9660_dir_t *iso9660_dir = (void *) pvd->root_directory_record; - iso9660_stat_t *stat; - int ret; - - ret = iso9660_iso_seek_read (iso, block, ISO_PVD_SECTOR, 1); - if (ret!=ISO_BLOCKSIZE) return NULL; - - stat = _iso9660_dir_to_statbuf (iso9660_dir, true); - return stat; + iso9660_stat_t *p_stat; + iso9660_dir_t *p_iso9660_dir; + +#ifdef HAVE_JOLIET + p_iso9660_dir = p_iso->i_joliet_level + ? &(p_iso->svd.root_directory_record) + : &(p_iso->pvd.root_directory_record) ; +#else + p_iso9660_dir = &(p_iso->pvd.root_directory_record) ; +#endif + + p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, true, + p_iso->i_joliet_level); + return p_stat; } static iso9660_stat_t * -_fs_stat_traverse (const CdIo *cdio, const iso9660_stat_t *_root, - char **splitpath, bool is_mode2, bool translate) +_fs_stat_traverse (const CdIo *p_cdio, const iso9660_stat_t *_root, + char **splitpath, bool b_mode2, bool translate) { unsigned offset = 0; uint8_t *_dirbuf = NULL; - iso9660_stat_t *stat; + iso9660_stat_t *p_stat; + generic_img_private_t *p_env = (generic_img_private_t *) p_cdio->env; if (!splitpath[0]) { unsigned int len=sizeof(iso9660_stat_t) + strlen(_root->filename)+1; - stat = _cdio_malloc(len); - memcpy(stat, _root, len); - return stat; + p_stat = _cdio_malloc(len); + memcpy(p_stat, _root, len); + return p_stat; } if (_root->type == _STAT_FILE) @@ -261,58 +791,60 @@ _fs_stat_traverse (const CdIo *cdio, const iso9660_stat_t *_root, _dirbuf = _cdio_malloc (_root->secsize * ISO_BLOCKSIZE); - if (is_mode2) { - if (cdio_read_mode2_sectors (cdio, _dirbuf, _root->lsn, false, + if (b_mode2) { + if (cdio_read_mode2_sectors (p_cdio, _dirbuf, _root->lsn, false, _root->secsize)) return NULL; } else { - if (cdio_read_mode1_sectors (cdio, _dirbuf, _root->lsn, false, + if (cdio_read_mode1_sectors (p_cdio, _dirbuf, _root->lsn, false, _root->secsize)) return NULL; } while (offset < (_root->secsize * ISO_BLOCKSIZE)) { - const iso9660_dir_t *iso9660_dir = (void *) &_dirbuf[offset]; - iso9660_stat_t *stat; + iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset]; + iso9660_stat_t *p_stat; int cmp; - if (!iso9660_get_dir_len(iso9660_dir)) + if (!iso9660_get_dir_len(p_iso9660_dir)) { offset++; continue; } - stat = _iso9660_dir_to_statbuf (iso9660_dir, is_mode2); + p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, b_mode2, + p_env->i_joliet_level); if (translate) { - char *trans_fname = malloc(strlen(stat->filename)); + char *trans_fname = malloc(strlen(p_stat->filename)); int trans_len; if (trans_fname == NULL) { cdio_warn("can't allocate %lu bytes", - (long unsigned int) strlen(stat->filename)); + (long unsigned int) strlen(p_stat->filename)); return NULL; } - trans_len = iso9660_name_translate(stat->filename, trans_fname); + trans_len = iso9660_name_translate_ext(p_stat->filename, trans_fname, + p_env->i_joliet_level); cmp = strcmp(splitpath[0], trans_fname); free(trans_fname); } else { - cmp = strcmp(splitpath[0], stat->filename); + cmp = strcmp(splitpath[0], p_stat->filename); } if (!cmp) { iso9660_stat_t *ret_stat - = _fs_stat_traverse (cdio, stat, &splitpath[1], is_mode2, + = _fs_stat_traverse (p_cdio, p_stat, &splitpath[1], b_mode2, translate); - free(stat); + free(p_stat); free (_dirbuf); return ret_stat; } - free(stat); + free(p_stat); - offset += iso9660_get_dir_len(iso9660_dir); + offset += iso9660_get_dir_len(p_iso9660_dir); } cdio_assert (offset == (_root->secsize * ISO_BLOCKSIZE)); @@ -323,20 +855,20 @@ _fs_stat_traverse (const CdIo *cdio, const iso9660_stat_t *_root, } static iso9660_stat_t * -_fs_iso_stat_traverse (iso9660_t *iso, const iso9660_stat_t *_root, +_fs_iso_stat_traverse (iso9660_t *p_iso, const iso9660_stat_t *_root, char **splitpath, bool translate) { unsigned offset = 0; uint8_t *_dirbuf = NULL; - iso9660_stat_t *stat; int ret; if (!splitpath[0]) { + iso9660_stat_t *p_stat; unsigned int len=sizeof(iso9660_stat_t) + strlen(_root->filename)+1; - stat = _cdio_malloc(len); - memcpy(stat, _root, len); - return stat; + p_stat = _cdio_malloc(len); + memcpy(p_stat, _root, len); + return p_stat; } if (_root->type == _STAT_FILE) @@ -353,50 +885,52 @@ _fs_iso_stat_traverse (iso9660_t *iso, const iso9660_stat_t *_root, _dirbuf = _cdio_malloc (_root->secsize * ISO_BLOCKSIZE); - ret = iso9660_iso_seek_read (iso, _dirbuf, _root->lsn, _root->secsize); + ret = iso9660_iso_seek_read (p_iso, _dirbuf, _root->lsn, _root->secsize); if (ret!=ISO_BLOCKSIZE*_root->secsize) return NULL; while (offset < (_root->secsize * ISO_BLOCKSIZE)) { - const iso9660_dir_t *iso9660_dir = (void *) &_dirbuf[offset]; - iso9660_stat_t *stat; + iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset]; + iso9660_stat_t *p_stat; int cmp; - if (!iso9660_get_dir_len(iso9660_dir)) + if (!iso9660_get_dir_len(p_iso9660_dir)) { offset++; continue; } - stat = _iso9660_dir_to_statbuf (iso9660_dir, true); + p_stat = _iso9660_dir_to_statbuf (p_iso9660_dir, true, + p_iso->i_joliet_level); if (translate) { - char *trans_fname = malloc(strlen(stat->filename)+1); + char *trans_fname = malloc(strlen(p_stat->filename)+1); int trans_len; if (trans_fname == NULL) { cdio_warn("can't allocate %lu bytes", - (long unsigned int) strlen(stat->filename)); + (long unsigned int) strlen(p_stat->filename)); return NULL; } - trans_len = iso9660_name_translate(stat->filename, trans_fname); + trans_len = iso9660_name_translate_ext(p_stat->filename, trans_fname, + p_iso->i_joliet_level); cmp = strcmp(splitpath[0], trans_fname); free(trans_fname); } else { - cmp = strcmp(splitpath[0], stat->filename); + cmp = strcmp(splitpath[0], p_stat->filename); } if (!cmp) { iso9660_stat_t *ret_stat - = _fs_iso_stat_traverse (iso, stat, &splitpath[1], translate); - free(stat); + = _fs_iso_stat_traverse (p_iso, p_stat, &splitpath[1], translate); + free(p_stat); free (_dirbuf); return ret_stat; } - free(stat); + free(p_stat); - offset += iso9660_get_dir_len(iso9660_dir); + offset += iso9660_get_dir_len(p_iso9660_dir); } cdio_assert (offset == (_root->secsize * ISO_BLOCKSIZE)); @@ -410,24 +944,27 @@ _fs_iso_stat_traverse (iso9660_t *iso, const iso9660_stat_t *_root, Get file status for pathname into stat. NULL is returned on error. */ iso9660_stat_t * -iso9660_fs_stat (const CdIo *cdio, const char pathname[], bool is_mode2) +iso9660_fs_stat (CdIo *p_cdio, const char pathname[]) { - iso9660_stat_t *root; - char **splitpath; - iso9660_stat_t *stat; + iso9660_stat_t *p_root; + char **p_psz_splitpath; + iso9660_stat_t *p_stat; + /* A bit of a hack, we'll assume track 1 contains ISO_PVD_SECTOR.*/ + bool b_mode2; - if (cdio == NULL) return NULL; - if (pathname == NULL) return NULL; + if (!p_cdio) return NULL; + if (!pathname) return NULL; - root = _fs_stat_root (cdio, is_mode2); - if (NULL == root) return NULL; + p_root = _fs_stat_root (p_cdio); + if (!p_root) return NULL; - splitpath = _cdio_strsplit (pathname, '/'); - stat = _fs_stat_traverse (cdio, root, splitpath, is_mode2, false); - free(root); - _cdio_strfreev (splitpath); + b_mode2 = cdio_get_track_green(p_cdio, 1); + p_psz_splitpath = _cdio_strsplit (pathname, '/'); + p_stat = _fs_stat_traverse (p_cdio, p_root, p_psz_splitpath, b_mode2, false); + free(p_root); + _cdio_strfreev (p_psz_splitpath); - return stat; + return p_stat; } /*! @@ -437,47 +974,47 @@ iso9660_fs_stat (const CdIo *cdio, const char pathname[], bool is_mode2) are lowercased. */ iso9660_stat_t * -iso9660_fs_stat_translate (const CdIo *cdio, const char pathname[], - bool is_mode2) +iso9660_fs_stat_translate (CdIo *p_cdio, const char pathname[], + bool b_mode2) { - iso9660_stat_t *root; - char **splitpath; - iso9660_stat_t *stat; + iso9660_stat_t *p_root; + char **p_psz_splitpath; + iso9660_stat_t *p_stat; - if (cdio == NULL) return NULL; - if (pathname == NULL) return NULL; + if (!p_cdio) return NULL; + if (pathname) return NULL; - root = _fs_stat_root (cdio, is_mode2); - if (NULL == root) return NULL; + p_root = _fs_stat_root (p_cdio); + if (!p_root) return NULL; - splitpath = _cdio_strsplit (pathname, '/'); - stat = _fs_stat_traverse (cdio, root, splitpath, is_mode2, true); - free(root); - _cdio_strfreev (splitpath); + p_psz_splitpath = _cdio_strsplit (pathname, '/'); + p_stat = _fs_stat_traverse (p_cdio, p_root, p_psz_splitpath, b_mode2, true); + free(p_root); + _cdio_strfreev (p_psz_splitpath); - return stat; + return p_stat; } /*! Get file status for pathname into stat. NULL is returned on error. */ -void * -iso9660_ifs_stat (iso9660_t *iso, const char pathname[]) +iso9660_stat_t * +iso9660_ifs_stat (iso9660_t *p_iso, const char pathname[]) { - iso9660_stat_t *root; + iso9660_stat_t *p_root; char **splitpath; iso9660_stat_t *stat; - if (iso == NULL) return NULL; - if (pathname == NULL) return NULL; + if (!p_iso) return NULL; + if (!pathname) return NULL; - root = _fs_stat_iso_root (iso); - if (NULL == root) return NULL; + p_root = _fs_stat_iso_root (p_iso); + if (!p_root) return NULL; splitpath = _cdio_strsplit (pathname, '/'); - stat = _fs_iso_stat_traverse (iso, root, splitpath, false); - free(root); - _cdio_strfreev (splitpath); + stat = _fs_iso_stat_traverse (p_iso, p_root, splitpath, false); + free(p_root); + /*** FIXME _cdio_strfreev (splitpath); ***/ return stat; } @@ -488,45 +1025,45 @@ iso9660_ifs_stat (iso9660_t *iso, const char pathname[]) name are dropped, i.e. ;1 is removed and if level 1 ISO-9660 names are lowercased. */ -void * -iso9660_ifs_stat_translate (iso9660_t *iso, const char pathname[]) +iso9660_stat_t * +iso9660_ifs_stat_translate (iso9660_t *p_iso, const char pathname[]) { - iso9660_stat_t *root; - char **splitpath; - iso9660_stat_t *stat; + iso9660_stat_t *p_root; + char **p_psz_splitpath; + iso9660_stat_t *p_stat; - if (iso == NULL) return NULL; - if (pathname == NULL) return NULL; + if (!p_iso) return NULL; + if (!pathname) return NULL; - root = _fs_stat_iso_root (iso); - if (NULL == root) return NULL; + p_root = _fs_stat_iso_root (p_iso); + if (NULL == p_root) return NULL; - splitpath = _cdio_strsplit (pathname, '/'); - stat = _fs_iso_stat_traverse (iso, root, splitpath, true); - free(root); - _cdio_strfreev (splitpath); + p_psz_splitpath = _cdio_strsplit (pathname, '/'); + p_stat = _fs_iso_stat_traverse (p_iso, p_root, p_psz_splitpath, true); + free(p_root); + _cdio_strfreev (p_psz_splitpath); - return stat; + return p_stat; } /*! Read pathname (a directory) and return a list of iso9660_stat_t of the files inside that. The caller must free the returned result. */ -void * -iso9660_fs_readdir (const CdIo *cdio, const char pathname[], bool is_mode2) +CdioList * +iso9660_fs_readdir (CdIo *p_cdio, const char pathname[], bool b_mode2) { - iso9660_stat_t *stat; + iso9660_stat_t *p_stat; + generic_img_private_t *p_env = (generic_img_private_t *) p_cdio->env; - if (NULL == cdio) return NULL; - if (NULL == pathname) return NULL; + if (!p_cdio) return NULL; + if (!pathname) return NULL; - stat = iso9660_fs_stat (cdio, pathname, is_mode2); - if (NULL == stat) - return NULL; + p_stat = iso9660_fs_stat (p_cdio, pathname); + if (!p_stat) return NULL; - if (stat->type != _STAT_DIR) { - free(stat); + if (p_stat->type != _STAT_DIR) { + free(p_stat); return NULL; } @@ -535,46 +1072,47 @@ iso9660_fs_readdir (const CdIo *cdio, const char pathname[], bool is_mode2) uint8_t *_dirbuf = NULL; CdioList *retval = _cdio_list_new (); - if (stat->size != ISO_BLOCKSIZE * stat->secsize) + if (p_stat->size != ISO_BLOCKSIZE * p_stat->secsize) { cdio_warn ("bad size for ISO9660 directory (%ud) should be (%lu)!", - (unsigned) stat->size, - (unsigned long int) ISO_BLOCKSIZE * stat->secsize); + (unsigned) p_stat->size, + (unsigned long int) ISO_BLOCKSIZE * p_stat->secsize); } - _dirbuf = _cdio_malloc (stat->secsize * ISO_BLOCKSIZE); + _dirbuf = _cdio_malloc (p_stat->secsize * ISO_BLOCKSIZE); - if (is_mode2) { - if (cdio_read_mode2_sectors (cdio, _dirbuf, stat->lsn, false, - stat->secsize)) + if (b_mode2) { + if (cdio_read_mode2_sectors (p_cdio, _dirbuf, p_stat->lsn, false, + p_stat->secsize)) cdio_assert_not_reached (); } else { - if (cdio_read_mode1_sectors (cdio, _dirbuf, stat->lsn, false, - stat->secsize)) + if (cdio_read_mode1_sectors (p_cdio, _dirbuf, p_stat->lsn, false, + p_stat->secsize)) cdio_assert_not_reached (); } - while (offset < (stat->secsize * ISO_BLOCKSIZE)) + while (offset < (p_stat->secsize * ISO_BLOCKSIZE)) { - const iso9660_dir_t *iso9660_dir = (void *) &_dirbuf[offset]; - iso9660_stat_t *iso9660_stat; + iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset]; + iso9660_stat_t *p_iso9660_stat; - if (!iso9660_get_dir_len(iso9660_dir)) + if (!iso9660_get_dir_len(p_iso9660_dir)) { offset++; continue; } - iso9660_stat = _iso9660_dir_to_statbuf(iso9660_dir, is_mode2); - _cdio_list_append (retval, iso9660_stat); + p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir, b_mode2, + p_env->i_joliet_level); + _cdio_list_append (retval, p_iso9660_stat); - offset += iso9660_get_dir_len(iso9660_dir); + offset += iso9660_get_dir_len(p_iso9660_dir); } - cdio_assert (offset == (stat->secsize * ISO_BLOCKSIZE)); + cdio_assert (offset == (p_stat->secsize * ISO_BLOCKSIZE)); free (_dirbuf); - free (stat); + free (p_stat); return retval; } } @@ -583,19 +1121,19 @@ iso9660_fs_readdir (const CdIo *cdio, const char pathname[], bool is_mode2) Read pathname (a directory) and return a list of iso9660_stat_t of the files inside that. The caller must free the returned result. */ -void * -iso9660_ifs_readdir (iso9660_t *iso, const char pathname[]) +CdioList * +iso9660_ifs_readdir (iso9660_t *p_iso, const char pathname[]) { - iso9660_stat_t *stat; + iso9660_stat_t *p_stat; - if (NULL == iso) return NULL; - if (NULL == pathname) return NULL; + if (!p_iso) return NULL; + if (!pathname) return NULL; - stat = iso9660_ifs_stat (iso, pathname); - if (NULL == stat) return NULL; + p_stat = iso9660_ifs_stat (p_iso, pathname); + if (!p_stat) return NULL; - if (stat->type != _STAT_DIR) { - free(stat); + if (p_stat->type != _STAT_DIR) { + free(p_stat); return NULL; } @@ -605,47 +1143,48 @@ iso9660_ifs_readdir (iso9660_t *iso, const char pathname[]) uint8_t *_dirbuf = NULL; CdioList *retval = _cdio_list_new (); - if (stat->size != ISO_BLOCKSIZE * stat->secsize) + if (p_stat->size != ISO_BLOCKSIZE * p_stat->secsize) { cdio_warn ("bad size for ISO9660 directory (%ud) should be (%lu)!", - (unsigned) stat->size, - (unsigned long int) ISO_BLOCKSIZE * stat->secsize); + (unsigned int) p_stat->size, + (unsigned long int) ISO_BLOCKSIZE * p_stat->secsize); } - _dirbuf = _cdio_malloc (stat->secsize * ISO_BLOCKSIZE); + _dirbuf = _cdio_malloc (p_stat->secsize * ISO_BLOCKSIZE); - ret = iso9660_iso_seek_read (iso, _dirbuf, stat->lsn, stat->secsize); - if (ret != ISO_BLOCKSIZE*stat->secsize) return NULL; + ret = iso9660_iso_seek_read (p_iso, _dirbuf, p_stat->lsn, p_stat->secsize); + if (ret != ISO_BLOCKSIZE*p_stat->secsize) return NULL; - while (offset < (stat->secsize * ISO_BLOCKSIZE)) + while (offset < (p_stat->secsize * ISO_BLOCKSIZE)) { - const iso9660_dir_t *iso9660_dir = (void *) &_dirbuf[offset]; - iso9660_stat_t *iso9660_stat; + iso9660_dir_t *p_iso9660_dir = (void *) &_dirbuf[offset]; + iso9660_stat_t *p_iso9660_stat; - if (!iso9660_get_dir_len(iso9660_dir)) + if (!iso9660_get_dir_len(p_iso9660_dir)) { offset++; continue; } - iso9660_stat = _iso9660_dir_to_statbuf(iso9660_dir, true); - _cdio_list_append (retval, iso9660_stat); + p_iso9660_stat = _iso9660_dir_to_statbuf(p_iso9660_dir, true, + p_iso->i_joliet_level); + _cdio_list_append (retval, p_iso9660_stat); - offset += iso9660_get_dir_len(iso9660_dir); + offset += iso9660_get_dir_len(p_iso9660_dir); } - cdio_assert (offset == (stat->secsize * ISO_BLOCKSIZE)); + cdio_assert (offset == (p_stat->secsize * ISO_BLOCKSIZE)); free (_dirbuf); - free (stat); + free (p_stat); return retval; } } static iso9660_stat_t * -find_fs_lsn_recurse (const CdIo *cdio, const char pathname[], lsn_t lsn) +find_fs_lsn_recurse (CdIo *p_cdio, const char pathname[], lsn_t lsn) { - CdioList *entlist = iso9660_fs_readdir (cdio, pathname, true); + CdioList *entlist = iso9660_fs_readdir (p_cdio, pathname, true); CdioList *dirlist = _cdio_list_new (); CdioListNode *entnode; @@ -686,7 +1225,7 @@ find_fs_lsn_recurse (const CdIo *cdio, const char pathname[], lsn_t lsn) _CDIO_LIST_FOREACH (entnode, dirlist) { char *_fullname = _cdio_list_node_data (entnode); - iso9660_stat_t *ret_stat = find_fs_lsn_recurse (cdio, _fullname, lsn); + iso9660_stat_t *ret_stat = find_fs_lsn_recurse (p_cdio, _fullname, lsn); if (NULL != ret_stat) { _cdio_list_free (dirlist, true); @@ -705,8 +1244,17 @@ find_fs_lsn_recurse (const CdIo *cdio, const char pathname[], lsn_t lsn) Returns stat_t of entry if we found lsn, or NULL otherwise. */ iso9660_stat_t * -iso9660_find_fs_lsn(const CdIo *cdio, lsn_t lsn) +iso9660_find_fs_lsn(CdIo *p_cdio, lsn_t i_lsn) { - return find_fs_lsn_recurse (cdio, "/", lsn); + return find_fs_lsn_recurse (p_cdio, "/", i_lsn); } +/*! + Return true if ISO 9660 image has extended attrributes (XA). +*/ +bool +iso9660_ifs_is_xa (const iso9660_t * p_iso) +{ + if (!p_iso) return false; + return p_iso->b_xa; +} diff --git a/src/input/vcd/libcdio/portable.h b/src/input/vcd/libcdio/portable.h new file mode 100644 index 000000000..3da436245 --- /dev/null +++ b/src/input/vcd/libcdio/portable.h @@ -0,0 +1,74 @@ +/* + $Id: portable.h,v 1.1 2005/01/01 02:43:57 rockyb Exp $ + + Copyright (C) Rocky Bernstein <rocky@panix.com> + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + This file contains definitions to fill in for differences or + deficiencies to OS or compiler irregularities. If this file is + included other routines can be more portable. +*/ + +#ifndef __CDIO_PORTABLE_H__ +#define __CDIO_PORTABLE_H__ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#if !defined(HAVE_FTRUNCATE) +# if defined ( WIN32 ) +# define ftruncate chsize +# endif +#endif /*HAVE_FTRUNCATE*/ + +#if !defined(HAVE_SNPRINTF) +# if defined ( MSVC ) +# define snprintf _snprintf +# endif +#endif /*HAVE_SNPRINTF*/ + +#if !defined(HAVE_VSNPRINTF) +# if defined ( MSVC ) +# define snprintf _vsnprintf +# endif +#endif /*HAVE_SNPRINTF*/ + +#ifdef MSVC +# include <io.h> + +# ifndef S_ISBLK +# define _S_IFBLK 0060000 /* Block Special */ +# define S_ISBLK(x) (x & _S_IFBLK) +# endif + +# ifndef S_ISCHR +# define _S_IFCHR 0020000 /* character special */ +# define S_ISCHR(x) (x & _S_IFCHR) +# endif +#endif /*MSVC*/ + +#ifdef HAVE_MEMSET +# define BZERO(ptr, size) memset(ptr, 0, size) +#elif HAVE_BZERO +# define BZERO(ptr, size) bzero(ptr, size) +#else + Error -- you need either memset or bzero +#endif + +#endif /* __CDIO_PORTABLE_H__ */ diff --git a/src/input/vcd/libcdio/scsi_mmc.c b/src/input/vcd/libcdio/scsi_mmc.c new file mode 100644 index 000000000..9b4a456a5 --- /dev/null +++ b/src/input/vcd/libcdio/scsi_mmc.c @@ -0,0 +1,589 @@ +/* Common SCSI Multimedia Command (MMC) routines. + + $Id: scsi_mmc.c,v 1.1 2005/01/01 02:43:57 rockyb Exp $ + + Copyright (C) 2004 Rocky Bernstein <rocky@panix.com> + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <cdio/cdio.h> +#include <cdio/logging.h> +#include <cdio/scsi_mmc.h> +#include "cdio_private.h" + +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif + +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif + +/*! + On input a MODE_SENSE command was issued and we have the results + in p. We interpret this and return a bit mask set according to the + capabilities. + */ +void +scsi_mmc_get_drive_cap_buf(const uint8_t *p, + /*out*/ cdio_drive_read_cap_t *p_read_cap, + /*out*/ cdio_drive_write_cap_t *p_write_cap, + /*out*/ cdio_drive_misc_cap_t *p_misc_cap) +{ + /* Reader */ + if (p[2] & 0x01) *p_read_cap |= CDIO_DRIVE_CAP_READ_CD_R; + if (p[2] & 0x02) *p_read_cap |= CDIO_DRIVE_CAP_READ_CD_RW; + if (p[2] & 0x08) *p_read_cap |= CDIO_DRIVE_CAP_READ_DVD_ROM; + if (p[4] & 0x01) *p_read_cap |= CDIO_DRIVE_CAP_READ_AUDIO; + if (p[5] & 0x01) *p_read_cap |= CDIO_DRIVE_CAP_READ_CD_DA; + if (p[5] & 0x10) *p_read_cap |= CDIO_DRIVE_CAP_READ_C2_ERRS; + + /* Writer */ + if (p[3] & 0x01) *p_write_cap |= CDIO_DRIVE_CAP_WRITE_CD_R; + if (p[3] & 0x02) *p_write_cap |= CDIO_DRIVE_CAP_WRITE_CD_RW; + if (p[3] & 0x10) *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_R; + if (p[3] & 0x20) *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_RAM; + if (p[4] & 0x80) *p_misc_cap |= CDIO_DRIVE_CAP_WRITE_BURN_PROOF; + + /* Misc */ + if (p[4] & 0x40) *p_misc_cap |= CDIO_DRIVE_CAP_MISC_MULTI_SESSION; + if (p[6] & 0x01) *p_misc_cap |= CDIO_DRIVE_CAP_MISC_LOCK; + if (p[6] & 0x08) *p_misc_cap |= CDIO_DRIVE_CAP_MISC_EJECT; + if (p[6] >> 5 != 0) + *p_misc_cap |= CDIO_DRIVE_CAP_MISC_CLOSE_TRAY; +} + +/*! + Return the number of length in bytes of the Command Descriptor + buffer (CDB) for a given SCSI MMC command. The length will be + either 6, 10, or 12. +*/ +uint8_t +scsi_mmc_get_cmd_len(uint8_t scsi_cmd) +{ + static const uint8_t scsi_cdblen[8] = {6, 10, 10, 12, 12, 12, 10, 10}; + return scsi_cdblen[((scsi_cmd >> 5) & 7)]; +} + +/*! + Run a SCSI MMC command. + + cdio CD structure set by cdio_open(). + i_timeout time in milliseconds we will wait for the command + to complete. If this value is -1, use the default + time-out value. + buf Buffer for data, both sending and receiving + len Size of buffer + e_direction direction the transfer is to go + cdb CDB bytes. All values that are needed should be set on + input. We'll figure out what the right CDB length should be. + + We return 0 if command completed successfully and 1 if not. + */ +int +scsi_mmc_run_cmd( const CdIo *p_cdio, unsigned int i_timeout_ms, + const scsi_mmc_cdb_t *p_cdb, + scsi_mmc_direction_t e_direction, unsigned int i_buf, + /*in/out*/ void *p_buf ) +{ + if (p_cdio && p_cdio->op.run_scsi_mmc_cmd) { + return p_cdio->op.run_scsi_mmc_cmd(p_cdio->env, i_timeout_ms, + scsi_mmc_get_cmd_len(p_cdb->field[0]), + p_cdb, e_direction, i_buf, p_buf); + } else + return 1; +} + +#define DEFAULT_TIMEOUT_MS 6000 + +/*! + * Eject using SCSI MMC commands. Return 0 if successful. + */ +int +scsi_mmc_eject_media( const CdIo *cdio ) +{ + int i_status; + scsi_mmc_cdb_t cdb = {{0, }}; + uint8_t buf[1]; + scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd; + + if ( ! cdio || ! cdio->op.run_scsi_mmc_cmd ) + return -2; + + run_scsi_mmc_cmd = cdio->op.run_scsi_mmc_cmd; + + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_ALLOW_MEDIUM_REMOVAL); + + i_status = run_scsi_mmc_cmd (cdio->env, DEFAULT_TIMEOUT_MS, + scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, + SCSI_MMC_DATA_WRITE, 0, &buf); + if (0 != i_status) + return i_status; + + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_START_STOP); + cdb.field[4] = 1; + i_status = run_scsi_mmc_cmd (cdio->env, DEFAULT_TIMEOUT_MS, + scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, + SCSI_MMC_DATA_WRITE, 0, &buf); + if (0 != i_status) + return i_status; + + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_START_STOP); + cdb.field[4] = 2; /* eject */ + + return run_scsi_mmc_cmd (cdio->env, DEFAULT_TIMEOUT_MS, + scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, + SCSI_MMC_DATA_WRITE, 0, &buf); + +} + +/*! Packet driver to read mode2 sectors. + Can read only up to 25 blocks. +*/ +int +scsi_mmc_read_sectors ( const CdIo *cdio, void *p_buf, lba_t lba, + int sector_type, unsigned int nblocks ) +{ + scsi_mmc_cdb_t cdb = {{0, }}; + + scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd; + + if ( ! cdio || ! cdio->op.run_scsi_mmc_cmd ) + return -2; + + run_scsi_mmc_cmd = cdio->op.run_scsi_mmc_cmd; + + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_CD); + CDIO_MMC_SET_READ_TYPE (cdb.field, sector_type); + CDIO_MMC_SET_READ_LBA (cdb.field, lba); + CDIO_MMC_SET_READ_LENGTH24(cdb.field, nblocks); + CDIO_MMC_SET_MAIN_CHANNEL_SELECTION_BITS(cdb.field, + CDIO_MMC_MCSB_ALL_HEADERS); + + return run_scsi_mmc_cmd (cdio->env, DEFAULT_TIMEOUT_MS, + scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, + SCSI_MMC_DATA_READ, + CDIO_CD_FRAMESIZE_RAW * nblocks, + p_buf); +} + +int +scsi_mmc_set_blocksize_private ( const void *p_env, + const scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd, + unsigned int bsize) +{ + scsi_mmc_cdb_t cdb = {{0, }}; + + struct + { + uint8_t reserved1; + uint8_t medium; + uint8_t reserved2; + uint8_t block_desc_length; + uint8_t density; + uint8_t number_of_blocks_hi; + uint8_t number_of_blocks_med; + uint8_t number_of_blocks_lo; + uint8_t reserved3; + uint8_t block_length_hi; + uint8_t block_length_med; + uint8_t block_length_lo; + } mh; + + if ( ! p_env || ! run_scsi_mmc_cmd ) + return -2; + + memset (&mh, 0, sizeof (mh)); + mh.block_desc_length = 0x08; + mh.block_length_hi = (bsize >> 16) & 0xff; + mh.block_length_med = (bsize >> 8) & 0xff; + mh.block_length_lo = (bsize >> 0) & 0xff; + + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_MODE_SELECT_6); + + cdb.field[1] = 1 << 4; + cdb.field[4] = 12; + + return run_scsi_mmc_cmd (p_env, DEFAULT_TIMEOUT_MS, + scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, + SCSI_MMC_DATA_WRITE, sizeof(mh), &mh); +} + +int +scsi_mmc_set_blocksize ( const CdIo *cdio, unsigned int bsize) +{ + if ( ! cdio ) return -2; + return + scsi_mmc_set_blocksize_private (cdio->env, cdio->op.run_scsi_mmc_cmd, + bsize); +} + + +/*! + Return the the kind of drive capabilities of device. + */ +void +scsi_mmc_get_drive_cap_private (const void *p_env, + const scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd, + /*out*/ cdio_drive_read_cap_t *p_read_cap, + /*out*/ cdio_drive_write_cap_t *p_write_cap, + /*out*/ cdio_drive_misc_cap_t *p_misc_cap) +{ + /* Largest buffer size we use. */ +#define BUF_MAX 2048 + uint8_t buf[BUF_MAX] = { 0, }; + + scsi_mmc_cdb_t cdb = {{0, }}; + int i_status; + uint16_t i_data = BUF_MAX; + + if ( ! p_env || ! run_scsi_mmc_cmd ) + return; + + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_MODE_SENSE_10); + cdb.field[1] = 0x0; + cdb.field[2] = CDIO_MMC_ALL_PAGES; + + retry: + CDIO_MMC_SET_READ_LENGTH16(cdb.field, 8); + + /* In the first run we run MODE SENSE 10 we are trying to get the + length of the data features. */ + i_status = run_scsi_mmc_cmd (p_env, DEFAULT_TIMEOUT_MS, + scsi_mmc_get_cmd_len(cdb.field[0]), + &cdb, SCSI_MMC_DATA_READ, + sizeof(buf), &buf); + if (0 == i_status) { + uint16_t i_data_try = (uint16_t) CDIO_MMC_GET_LEN16(buf); + if (i_data_try < BUF_MAX) i_data = i_data_try; + } + + /* Now try getting all features with length set above, possibly + truncated or the default length if we couldn't get the proper + length. */ + CDIO_MMC_SET_READ_LENGTH16(cdb.field, i_data); + + i_status = run_scsi_mmc_cmd (p_env, DEFAULT_TIMEOUT_MS, + scsi_mmc_get_cmd_len(cdb.field[0]), + &cdb, SCSI_MMC_DATA_READ, + sizeof(buf), &buf); + + if (0 != i_status && CDIO_MMC_CAPABILITIES_PAGE != cdb.field[2]) { + cdb.field[2] = CDIO_MMC_CAPABILITIES_PAGE; + goto retry; + } + + if (0 == i_status) { + uint8_t *p; + uint8_t *p_max = buf + 256; + + *p_read_cap = 0; + *p_write_cap = 0; + *p_misc_cap = 0; + + /* set to first sense mask, and then walk through the masks */ + p = buf + 8; + while( (p < &(buf[2+i_data])) && (p < p_max) ) { + uint8_t which_page; + + which_page = p[0] & 0x3F; + switch( which_page ) + { + case CDIO_MMC_AUDIO_CTL_PAGE: + case CDIO_MMC_R_W_ERROR_PAGE: + case CDIO_MMC_CDR_PARMS_PAGE: + /* Don't handle these yet. */ + break; + case CDIO_MMC_CAPABILITIES_PAGE: + scsi_mmc_get_drive_cap_buf(p, p_read_cap, p_write_cap, p_misc_cap); + break; + default: ; + } + p += (p[1] + 2); + } + } else { + cdio_info("%s: %s\n", "error in MODE_SELECT", strerror(errno)); + *p_read_cap = CDIO_DRIVE_CAP_ERROR; + *p_write_cap = CDIO_DRIVE_CAP_ERROR; + *p_misc_cap = CDIO_DRIVE_CAP_ERROR; + } + return; +} + +void +scsi_mmc_get_drive_cap (const CdIo *p_cdio, + /*out*/ cdio_drive_read_cap_t *p_read_cap, + /*out*/ cdio_drive_write_cap_t *p_write_cap, + /*out*/ cdio_drive_misc_cap_t *p_misc_cap) +{ + if ( ! p_cdio ) return; + scsi_mmc_get_drive_cap_private (p_cdio->env, + p_cdio->op.run_scsi_mmc_cmd, + p_read_cap, p_write_cap, p_misc_cap); +} + +void +scsi_mmc_get_drive_cap_generic (const void *p_user_data, + /*out*/ cdio_drive_read_cap_t *p_read_cap, + /*out*/ cdio_drive_write_cap_t *p_write_cap, + /*out*/ cdio_drive_misc_cap_t *p_misc_cap) +{ + const generic_img_private_t *p_env = p_user_data; + scsi_mmc_get_drive_cap( p_env->cdio, + p_read_cap, p_write_cap, p_misc_cap ); +} + + +/*! + Get the DVD type associated with cd object. +*/ +discmode_t +scsi_mmc_get_dvd_struct_physical_private ( void *p_env, const + scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd, + cdio_dvd_struct_t *s) +{ + scsi_mmc_cdb_t cdb = {{0, }}; + unsigned char buf[4 + 4 * 20], *base; + int i_status; + uint8_t layer_num = s->physical.layer_num; + + cdio_dvd_layer_t *layer; + + if ( ! p_env || ! run_scsi_mmc_cmd ) + return -2; + + if (layer_num >= CDIO_DVD_MAX_LAYERS) + return -EINVAL; + + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_DVD_STRUCTURE); + cdb.field[6] = layer_num; + cdb.field[7] = CDIO_DVD_STRUCT_PHYSICAL; + cdb.field[9] = sizeof(buf) & 0xff; + + i_status = run_scsi_mmc_cmd(p_env, DEFAULT_TIMEOUT_MS, + scsi_mmc_get_cmd_len(cdb.field[0]), + &cdb, SCSI_MMC_DATA_READ, + sizeof(buf), &buf); + if (0 != i_status) + return CDIO_DISC_MODE_ERROR; + + base = &buf[4]; + layer = &s->physical.layer[layer_num]; + + /* + * place the data... really ugly, but at least we won't have to + * worry about endianess in userspace. + */ + memset(layer, 0, sizeof(*layer)); + layer->book_version = base[0] & 0xf; + layer->book_type = base[0] >> 4; + layer->min_rate = base[1] & 0xf; + layer->disc_size = base[1] >> 4; + layer->layer_type = base[2] & 0xf; + layer->track_path = (base[2] >> 4) & 1; + layer->nlayers = (base[2] >> 5) & 3; + layer->track_density = base[3] & 0xf; + layer->linear_density = base[3] >> 4; + layer->start_sector = base[5] << 16 | base[6] << 8 | base[7]; + layer->end_sector = base[9] << 16 | base[10] << 8 | base[11]; + layer->end_sector_l0 = base[13] << 16 | base[14] << 8 | base[15]; + layer->bca = base[16] >> 7; + + return 0; +} + + +/*! + Get the DVD type associated with cd object. +*/ +discmode_t +scsi_mmc_get_dvd_struct_physical ( const CdIo *p_cdio, cdio_dvd_struct_t *s) +{ + if ( ! p_cdio ) return -2; + return + scsi_mmc_get_dvd_struct_physical_private (p_cdio->env, + p_cdio->op.run_scsi_mmc_cmd, + s); +} + +/*! + Get the CD-ROM hardware info via a SCSI MMC INQUIRY command. + False is returned if we had an error getting the information. +*/ +bool +scsi_mmc_get_hwinfo ( const CdIo *p_cdio, + /*out*/ cdio_hwinfo_t *hw_info ) +{ + int i_status; /* Result of SCSI MMC command */ + char buf[36] = { 0, }; /* Place to hold returned data */ + scsi_mmc_cdb_t cdb = {{0, }}; /* Command Descriptor Block */ + + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_INQUIRY); + cdb.field[4] = sizeof(buf); + + if (! p_cdio || ! hw_info ) return false; + + i_status = scsi_mmc_run_cmd(p_cdio, DEFAULT_TIMEOUT_MS, + &cdb, SCSI_MMC_DATA_READ, + sizeof(buf), &buf); + if (i_status == 0) { + + memcpy(hw_info->psz_vendor, + buf + 8, + sizeof(hw_info->psz_vendor)-1); + hw_info->psz_vendor[sizeof(hw_info->psz_vendor)-1] = '\0'; + memcpy(hw_info->psz_model, + buf + 8 + CDIO_MMC_HW_VENDOR_LEN, + sizeof(hw_info->psz_model)-1); + hw_info->psz_model[sizeof(hw_info->psz_model)-1] = '\0'; + memcpy(hw_info->psz_revision, + buf + 8 + CDIO_MMC_HW_VENDOR_LEN + CDIO_MMC_HW_MODEL_LEN, + sizeof(hw_info->psz_revision)-1); + hw_info->psz_revision[sizeof(hw_info->psz_revision)-1] = '\0'; + return true; + } + return false; +} + +/*! + Return the media catalog number MCN. + + Note: string is malloc'd so caller should free() then returned + string when done with it. + + */ +char * +scsi_mmc_get_mcn_private ( void *p_env, + const scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd + ) +{ + scsi_mmc_cdb_t cdb = {{0, }}; + char buf[28] = { 0, }; + int i_status; + + if ( ! p_env || ! run_scsi_mmc_cmd ) + return NULL; + + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_SUBCHANNEL); + cdb.field[1] = 0x0; + cdb.field[2] = 0x40; + cdb.field[3] = CDIO_SUBCHANNEL_MEDIA_CATALOG; + CDIO_MMC_SET_READ_LENGTH16(cdb.field, sizeof(buf)); + + i_status = run_scsi_mmc_cmd(p_env, DEFAULT_TIMEOUT_MS, + scsi_mmc_get_cmd_len(cdb.field[0]), + &cdb, SCSI_MMC_DATA_READ, + sizeof(buf), buf); + if(i_status == 0) { + return strdup(&buf[9]); + } + return NULL; +} + +char * +scsi_mmc_get_mcn ( const CdIo *p_cdio ) +{ + if ( ! p_cdio ) return NULL; + return scsi_mmc_get_mcn_private (p_cdio->env, + p_cdio->op.run_scsi_mmc_cmd ); +} + +char * +scsi_mmc_get_mcn_generic (const void *p_user_data) +{ + const generic_img_private_t *p_env = p_user_data; + return scsi_mmc_get_mcn( p_env->cdio ); +} + +/* + Read cdtext information for a CdIo object . + + return true on success, false on error or CD-Text information does + not exist. +*/ +bool +scsi_mmc_init_cdtext_private ( void *p_user_data, + const scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd, + set_cdtext_field_fn_t set_cdtext_field_fn + ) +{ + + generic_img_private_t *p_env = p_user_data; + scsi_mmc_cdb_t cdb = {{0, }}; + unsigned char wdata[5000] = { 0, }; + int i_status, i_errno; + + if ( ! p_env || ! run_scsi_mmc_cmd || p_env->b_cdtext_error ) + return false; + + /* Operation code */ + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_TOC); + + cdb.field[1] = CDIO_CDROM_MSF; + /* Format */ + cdb.field[2] = CDIO_MMC_READTOC_FMT_CDTEXT; + + /* Setup to read header, to get length of data */ + CDIO_MMC_SET_READ_LENGTH16(cdb.field, 4); + + errno = 0; + +/* Set read timeout 3 minues. */ +#define READ_TIMEOUT 3*60*1000 + + /* We may need to give CD-Text a little more time to complete. */ + /* First off, just try and read the size */ + i_status = run_scsi_mmc_cmd (p_env, READ_TIMEOUT, + scsi_mmc_get_cmd_len(cdb.field[0]), + &cdb, SCSI_MMC_DATA_READ, + 4, &wdata); + + if (i_status != 0) { + cdio_info ("CD-Text read failed for header: %s\n", strerror(errno)); + i_errno = errno; + p_env->b_cdtext_error = true; + return false; + } else { + /* Now read the CD-Text data */ + int i_cdtext = CDIO_MMC_GET_LEN16(wdata); + + if (i_cdtext > sizeof(wdata)) i_cdtext = sizeof(wdata); + + CDIO_MMC_SET_READ_LENGTH16(cdb.field, i_cdtext); + i_status = run_scsi_mmc_cmd (p_env, READ_TIMEOUT, + scsi_mmc_get_cmd_len(cdb.field[0]), + &cdb, SCSI_MMC_DATA_READ, + i_cdtext, &wdata); + if (i_status != 0) { + cdio_info ("CD-Text read for text failed: %s\n", strerror(errno)); + i_errno = errno; + p_env->b_cdtext_error = true; + return false; + } + p_env->b_cdtext_init = true; + return cdtext_data_init(p_env, p_env->i_first_track, wdata, + set_cdtext_field_fn); + } +} + diff --git a/src/input/vcd/libcdio/scsi_mmc_private.h b/src/input/vcd/libcdio/scsi_mmc_private.h new file mode 100644 index 000000000..b3f1e7061 --- /dev/null +++ b/src/input/vcd/libcdio/scsi_mmc_private.h @@ -0,0 +1,105 @@ +/* private MMC helper routines. + + $Id: scsi_mmc_private.h,v 1.1 2005/01/01 02:43:57 rockyb Exp $ + + Copyright (C) 2004 Rocky Bernstein <rocky@panix.com> + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <cdio/scsi_mmc.h> +#include "cdtext_private.h" + +/*! Convert milliseconds to seconds taking the ceiling value, i.e. + 1002 milliseconds gets rounded to 2 seconds. +*/ +#define SECS2MSECS 1000 +static inline unsigned int +msecs2secs(unsigned int msecs) +{ + return (msecs+(SECS2MSECS-1)) / SECS2MSECS; +} +#undef SECS2MSECS + +typedef +int (*scsi_mmc_run_cmd_fn_t) ( const void *p_user_data, + unsigned int i_timeout_ms, + unsigned int i_cdb, + const scsi_mmc_cdb_t *p_cdb, + scsi_mmc_direction_t e_direction, + unsigned int i_buf, /*in/out*/ void *p_buf ); + +int scsi_mmc_set_blocksize_mmc_private ( const void *p_env, const + scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd, + unsigned int bsize ); + +/*! + Get the DVD type associated with cd object. +*/ +discmode_t +scsi_mmc_get_dvd_struct_physical_private ( void *p_env, const + scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd, + cdio_dvd_struct_t *s ); + + +int +scsi_mmc_set_blocksize_private ( const void *p_env, + const scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd, + unsigned int bsize); + +char *scsi_mmc_get_mcn_private ( void *p_env, + const scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd + ); + +char *scsi_mmc_get_mcn_generic (const void *p_user_data); + +bool scsi_mmc_init_cdtext_private ( void *user_data, const + scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd, + set_cdtext_field_fn_t set_cdtext_field_fn + ); + +/*! + On input a MODE_SENSE command was issued and we have the results + in p. We interpret this and return a bit mask set according to the + capabilities. + */ +void scsi_mmc_get_drive_cap_buf(const uint8_t *p, + /*out*/ cdio_drive_read_cap_t *p_read_cap, + /*out*/ cdio_drive_write_cap_t *p_write_cap, + /*out*/ cdio_drive_misc_cap_t *p_misc_cap); + +/*! + Return the the kind of drive capabilities of device. + + Note: string is malloc'd so caller should free() then returned + string when done with it. + + */ +void +scsi_mmc_get_drive_cap_private (const void *p_env, + const scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd, + /*out*/ cdio_drive_read_cap_t *p_read_cap, + /*out*/ cdio_drive_write_cap_t *p_write_cap, + /*out*/ cdio_drive_misc_cap_t *p_misc_cap); +void +scsi_mmc_get_drive_cap_generic (const void *p_user_data, + /*out*/ cdio_drive_read_cap_t *p_read_cap, + /*out*/ cdio_drive_write_cap_t *p_write_cap, + /*out*/ cdio_drive_misc_cap_t *p_misc_cap); + + + + + diff --git a/src/input/vcd/libcdio/sector.c b/src/input/vcd/libcdio/sector.c index 8ae28fc03..da49e9908 100644 --- a/src/input/vcd/libcdio/sector.c +++ b/src/input/vcd/libcdio/sector.c @@ -1,5 +1,5 @@ /* - $Id: sector.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: sector.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> @@ -24,6 +24,7 @@ #include <cdio/sector.h> #include <cdio/util.h> +#include <cdio/logging.h> #include "cdio_assert.h" #include <stdio.h> @@ -31,76 +32,253 @@ #include <string.h> #endif +#include <ctype.h> -static const char _rcsid[] = "$Id: sector.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: sector.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $"; lba_t cdio_lba_to_lsn (lba_t lba) { + if (CDIO_INVALID_LBA == lba) return CDIO_INVALID_LSN; return lba - CDIO_PREGAP_SECTORS; } +/* + The below is adapted from cdparanoia code which claims it is + straight from the MMC3 spec. +*/ + void -cdio_lba_to_msf (lba_t lba, msf_t *msf) +cdio_lsn_to_msf (lsn_t lsn, msf_t *msf) { + int m, s, f; + cdio_assert (msf != 0); - msf->m = to_bcd8 (lba / (60 * 75)); - msf->s = to_bcd8 ((lba / 75) % 60); - msf->f = to_bcd8 (lba % 75); + if ( lsn >= -CDIO_PREGAP_SECTORS ){ + m = (lsn + CDIO_PREGAP_SECTORS) / CDIO_CD_FRAMES_PER_MIN; + lsn -= m * CDIO_CD_FRAMES_PER_MIN; + s = (lsn + CDIO_PREGAP_SECTORS) / CDIO_CD_FRAMES_PER_SEC; + lsn -= s * CDIO_CD_FRAMES_PER_SEC; + f = lsn + CDIO_PREGAP_SECTORS; + } else { + m = (lsn + CDIO_CD_MAX_LSN) / CDIO_CD_FRAMES_PER_MIN; + lsn -= m * (CDIO_CD_FRAMES_PER_MIN); + s = (lsn+CDIO_CD_MAX_LSN) / CDIO_CD_FRAMES_PER_SEC; + lsn -= s * CDIO_CD_FRAMES_PER_SEC; + f = lsn + CDIO_CD_MAX_LSN; + } + + if (m > 99) { + cdio_warn ("number of minutes (%d) truncated to 99.", m); + m = 99; + } + + msf->m = cdio_to_bcd8 (m); + msf->s = cdio_to_bcd8 (s); + msf->f = cdio_to_bcd8 (f); } -/* warning, returns new allocated string */ +/*! + Convert an LBA into a string representation of the MSF. + \warning cdio_lba_to_msf_str returns new allocated string */ char * cdio_lba_to_msf_str (lba_t lba) { - char buf[16]; - msf_t _msf = { .m = 0, .s = 0, .f = 0 }; - - cdio_lba_to_msf (lba, &_msf); - - snprintf (buf, sizeof (buf), "%.2x:%.2x.%.2x", _msf.m, _msf.s, _msf.f); - return strdup (buf); + if (CDIO_INVALID_LBA == lba) { + return strdup("*INVALID"); + } else { + msf_t msf; + msf.m = msf.s = msf.f = 0; + cdio_lba_to_msf (lba, &msf); + return cdio_msf_to_str(&msf); + } } +/*! + Convert an LSN into the corresponding LBA. + CDIO_INVALID_LBA is returned if there is an error. +*/ lba_t cdio_lsn_to_lba (lsn_t lsn) { + if (CDIO_INVALID_LSN == lsn) return CDIO_INVALID_LBA; return lsn + CDIO_PREGAP_SECTORS; } +/*! + Convert an LBA into the corresponding MSF. +*/ void -cdio_lsn_to_msf (lsn_t lsn, msf_t *msf) +cdio_lba_to_msf (lba_t lba, msf_t *msf) { cdio_assert (msf != 0); - cdio_lba_to_msf(cdio_lsn_to_lba(lsn), msf); + cdio_lsn_to_msf(cdio_lba_to_lsn(lba), msf); } -uint32_t +/*! + Convert a MSF into the corresponding LBA. + CDIO_INVALID_LBA is returned if there is an error. +*/ +lba_t cdio_msf_to_lba (const msf_t *msf) { uint32_t lba = 0; cdio_assert (msf != 0); - lba = from_bcd8 (msf->m); - lba *= 60; + lba = cdio_from_bcd8 (msf->m); + lba *= CDIO_CD_SECS_PER_MIN; - lba += from_bcd8 (msf->s); - lba *= 75; + lba += cdio_from_bcd8 (msf->s); + lba *= CDIO_CD_FRAMES_PER_SEC; - lba += from_bcd8 (msf->f); + lba += cdio_from_bcd8 (msf->f); return lba; } -uint32_t +/*! + Convert a MSF into the corresponding LSN. + CDIO_INVALID_LSN is returned if there is an error. +*/ +lba_t cdio_msf_to_lsn (const msf_t *msf) { return cdio_lba_to_lsn(cdio_msf_to_lba (msf)); } +/*! + Convert an LBA into a string representation of the MSF. + \warning cdio_lba_to_msf_str returns new allocated string */ +char * +cdio_msf_to_str (const msf_t *msf) +{ + char buf[16]; + + snprintf (buf, sizeof (buf), "%2.2x:%2.2x:%2.2x", msf->m, msf->s, msf->f); + return strdup (buf); +} + +/*! + Convert a MSF - broken out as 3 integer components into the + corresponding LBA. + CDIO_INVALID_LBA is returned if there is an error. +*/ +lba_t +cdio_msf3_to_lba (unsigned int minutes, unsigned int seconds, + unsigned int frames) +{ + return ((minutes * CDIO_CD_SECS_PER_MIN + seconds) * CDIO_CD_FRAMES_PER_SEC + + frames); +} + +/*! + Convert a string of the form MM:SS:FF into the corresponding LBA. + CDIO_INVALID_LBA is returned if there is an error. +*/ +lba_t +cdio_mmssff_to_lba (const char *psz_mmssff) +{ + int psz_field; + lba_t ret; + char c; + + if (0 == strcmp (psz_mmssff, "0")) + return 0; + + c = *psz_mmssff++; + if(c >= '0' && c <= '9') + psz_field = (c - '0'); + else + return CDIO_INVALID_LBA; + while(':' != (c = *psz_mmssff++)) { + if(c >= '0' && c <= '9') + psz_field = psz_field * 10 + (c - '0'); + else + return CDIO_INVALID_LBA; + } + + ret = cdio_msf3_to_lba (psz_field, 0, 0); + + c = *psz_mmssff++; + if(c >= '0' && c <= '9') + psz_field = (c - '0'); + else + return CDIO_INVALID_LBA; + if(':' != (c = *psz_mmssff++)) { + if(c >= '0' && c <= '9') { + psz_field = psz_field * 10 + (c - '0'); + c = *psz_mmssff++; + if(c != ':') + return CDIO_INVALID_LBA; + } + else + return CDIO_INVALID_LBA; + } + + if(psz_field >= CDIO_CD_SECS_PER_MIN) + return CDIO_INVALID_LBA; + + ret += cdio_msf3_to_lba (0, psz_field, 0); + + c = *psz_mmssff++; + if (isdigit(c)) + psz_field = (c - '0'); + else + return -1; + if('\0' != (c = *psz_mmssff++)) { + if (isdigit(c)) { + psz_field = psz_field * 10 + (c - '0'); + c = *psz_mmssff++; + } + else + return CDIO_INVALID_LBA; + } + + if('\0' != c) + return CDIO_INVALID_LBA; + + if(psz_field >= CDIO_CD_FRAMES_PER_SEC) + return CDIO_INVALID_LBA; + + ret += psz_field; + + return ret; +} + +bool +cdio_is_discmode_cdrom(discmode_t discmode) +{ + switch (discmode) { + case CDIO_DISC_MODE_CD_DA: + case CDIO_DISC_MODE_CD_DATA: + case CDIO_DISC_MODE_CD_XA: + case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_NO_INFO: + return true; + default: + return false; + } +} + +bool +cdio_is_discmode_dvd(discmode_t discmode) +{ + switch (discmode) { + case CDIO_DISC_MODE_DVD_ROM: + case CDIO_DISC_MODE_DVD_RAM: + case CDIO_DISC_MODE_DVD_R: + case CDIO_DISC_MODE_DVD_RW: + case CDIO_DISC_MODE_DVD_PR: + case CDIO_DISC_MODE_DVD_PRW: + return true; + default: + return false; + } +} + /* * Local variables: diff --git a/src/input/vcd/libcdio/util.c b/src/input/vcd/libcdio/util.c index 55717a15f..9c646daf6 100644 --- a/src/input/vcd/libcdio/util.c +++ b/src/input/vcd/libcdio/util.c @@ -1,5 +1,5 @@ /* - $Id: util.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: util.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2003 Rocky Bernstein <rocky@panix.com> @@ -28,10 +28,15 @@ #include <stdio.h> #include <string.h> +#ifdef HAVE_INTTYPES_H +#include "inttypes.h" +#endif + #include "cdio_assert.h" +#include <cdio/types.h> #include <cdio/util.h> -static const char _rcsid[] = "$Id: util.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: util.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $"; size_t _cdio_strlenv(char **str_array) @@ -169,15 +174,15 @@ _cdio_strdup_upper (const char str[]) } uint8_t -to_bcd8 (uint8_t n) +cdio_to_bcd8 (uint8_t n) { - cdio_assert (n < 100); + /*cdio_assert (n < 100);*/ return ((n/10)<<4) | (n%10); } uint8_t -from_bcd8(uint8_t p) +cdio_from_bcd8(uint8_t p) { return (0xf & p)+(10*(p >> 4)); } diff --git a/src/input/vcd/libcdio/xa.c b/src/input/vcd/libcdio/xa.c index dbf8abd3c..f811f7ebd 100644 --- a/src/input/vcd/libcdio/xa.c +++ b/src/input/vcd/libcdio/xa.c @@ -1,5 +1,5 @@ /* - $Id: xa.c,v 1.2 2004/04/11 12:20:31 miguelfreitas Exp $ + $Id: xa.c,v 1.3 2005/01/01 02:43:57 rockyb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2003 Rocky Bernstein <rocky@panix.com> @@ -31,10 +31,10 @@ /* Public headers */ #include <cdio/iso9660.h> #include <cdio/util.h> +#include <cdio/bytesex.h> /* Private headers */ #include "cdio_assert.h" -#include "bytesex.h" #define BUF_COUNT 16 #define BUF_SIZE 80 diff --git a/src/input/vcd/libvcd/data_structures.c b/src/input/vcd/libvcd/data_structures.c index a269cc8f8..1fdca95c9 100644 --- a/src/input/vcd/libvcd/data_structures.c +++ b/src/input/vcd/libvcd/data_structures.c @@ -1,7 +1,8 @@ /* - $Id: data_structures.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: data_structures.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> + Copyright (C) 2004 Rocky Bernstein <rocky@panix.com> 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 @@ -35,63 +36,38 @@ #include "data_structures.h" #include "util.h" -static const char _rcsid[] = "$Id: data_structures.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: data_structures.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $"; -struct _VcdList +struct _CdioList { unsigned length; - VcdListNode *begin; - VcdListNode *end; + CdioListNode *begin; + CdioListNode *end; }; -struct _VcdListNode +struct _CdioListNode { - VcdList *list; + CdioList *list; - VcdListNode *next; + CdioListNode *next; void *data; }; /* impl */ -VcdList * -_vcd_list_new (void) -{ - VcdList *new_obj = _vcd_malloc (sizeof (VcdList)); - - return new_obj; -} - -void -_vcd_list_free (VcdList *list, int free_data) -{ - while (_vcd_list_length (list)) - _vcd_list_node_free (_vcd_list_begin (list), free_data); - - free (list); -} - -unsigned -_vcd_list_length (const VcdList *list) -{ - vcd_assert (list != NULL); - - return list->length; -} - static bool -_bubble_sort_iteration (VcdList *list, _vcd_list_cmp_func cmp_func) +_bubble_sort_iteration (CdioList *list, _cdio_list_cmp_func cmp_func) { - VcdListNode **pnode; + CdioListNode **pnode; bool changed = false; for (pnode = &(list->begin); (*pnode) != NULL && (*pnode)->next != NULL; pnode = &((*pnode)->next)) { - VcdListNode *node = *pnode; + CdioListNode *node = *pnode; if (cmp_func (node->data, node->next->data) <= 0) continue; /* n <= n->next */ @@ -110,7 +86,7 @@ _bubble_sort_iteration (VcdList *list, _vcd_list_cmp_func cmp_func) return changed; } -void _vcd_list_sort (VcdList *list, _vcd_list_cmp_func cmp_func) +void _vcd_list_sort (CdioList *list, _cdio_list_cmp_func cmp_func) { /* fixme -- this is bubble sort -- worst sorting algo... */ @@ -120,187 +96,27 @@ void _vcd_list_sort (VcdList *list, _vcd_list_cmp_func cmp_func) while (_bubble_sort_iteration (list, cmp_func)); } -void -_vcd_list_prepend (VcdList *list, void *data) -{ - VcdListNode *new_node; - - vcd_assert (list != NULL); - - new_node = _vcd_malloc (sizeof (VcdListNode)); - - new_node->list = list; - new_node->next = list->begin; - new_node->data = data; - - list->begin = new_node; - if (list->length == 0) - list->end = new_node; - - list->length++; -} - -void -_vcd_list_append (VcdList *list, void *data) -{ - vcd_assert (list != NULL); - - if (list->length == 0) - { - _vcd_list_prepend (list, data); - } - else - { - VcdListNode *new_node = _vcd_malloc (sizeof (VcdListNode)); - - new_node->list = list; - new_node->next = NULL; - new_node->data = data; - - list->end->next = new_node; - list->end = new_node; - - list->length++; - } -} - -void -_vcd_list_foreach (VcdList *list, _vcd_list_iterfunc func, void *user_data) -{ - VcdListNode *node; - - vcd_assert (list != NULL); - vcd_assert (func != 0); - - for (node = _vcd_list_begin (list); - node != NULL; - node = _vcd_list_node_next (node)) - func (_vcd_list_node_data (node), user_data); -} - -VcdListNode * -_vcd_list_find (VcdList *list, _vcd_list_iterfunc cmp_func, void *user_data) -{ - VcdListNode *node; - - vcd_assert (list != NULL); - vcd_assert (cmp_func != 0); - - for (node = _vcd_list_begin (list); - node != NULL; - node = _vcd_list_node_next (node)) - if (cmp_func (_vcd_list_node_data (node), user_data)) - break; - - return node; -} - /* node ops */ -VcdListNode * -_vcd_list_at (VcdList *list, int idx) +CdioListNode * +_vcd_list_at (CdioList *list, int idx) { - VcdListNode *node = _vcd_list_begin (list); + CdioListNode *node = _cdio_list_begin (list); if (idx < 0) - return _vcd_list_at (list, _vcd_list_length (list) + idx); + return _vcd_list_at (list, _cdio_list_length (list) + idx); vcd_assert (idx >= 0); while (node && idx) { - node = _vcd_list_node_next (node); + node = _cdio_list_node_next (node); idx--; } return node; } -VcdListNode * -_vcd_list_begin (const VcdList *list) -{ - vcd_assert (list != NULL); - - return list->begin; -} - -VcdListNode * -_vcd_list_end (VcdList *list) -{ - vcd_assert (list != NULL); - - return list->end; -} - -VcdListNode * -_vcd_list_node_next (VcdListNode *node) -{ - if (node) - return node->next; - - return NULL; -} - -void -_vcd_list_node_free (VcdListNode *node, int free_data) -{ - VcdList *list; - VcdListNode *prev_node; - - vcd_assert (node != NULL); - - list = node->list; - - vcd_assert (_vcd_list_length (list) > 0); - - if (free_data) - free (_vcd_list_node_data (node)); - - if (_vcd_list_length (list) == 1) - { - vcd_assert (list->begin == list->end); - - list->end = list->begin = NULL; - list->length = 0; - free (node); - return; - } - - vcd_assert (list->begin != list->end); - - if (list->begin == node) - { - list->begin = node->next; - free (node); - list->length--; - return; - } - - for (prev_node = list->begin; prev_node->next; prev_node = prev_node->next) - if (prev_node->next == node) - break; - - vcd_assert (prev_node->next != NULL); - - if (list->end == node) - list->end = prev_node; - - prev_node->next = node->next; - - list->length--; - - free (node); -} - -void * -_vcd_list_node_data (VcdListNode *node) -{ - if (node) - return node->data; - - return NULL; -} - /* * n-way tree based on list -- somewhat inefficent */ @@ -314,10 +130,10 @@ struct _VcdTreeNode { void *data; - VcdListNode *listnode; + CdioListNode *listnode; VcdTree *tree; VcdTreeNode *parent; - VcdList *children; + CdioList *children; }; VcdTree * @@ -363,8 +179,8 @@ _vcd_tree_node_destroy (VcdTreeNode *node, bool free_data) if (node->children) { - vcd_assert (_vcd_list_length (node->children) == 0); - _vcd_list_free (node->children, true); + vcd_assert (_cdio_list_length (node->children) == 0); + _cdio_list_free (node->children, true); node->children = NULL; } @@ -372,7 +188,7 @@ _vcd_tree_node_destroy (VcdTreeNode *node, bool free_data) free (_vcd_tree_node_set_data (node, NULL)); if (node->parent) - _vcd_list_node_free (node->listnode, true); + _cdio_list_node_free (node->listnode, true); else _vcd_tree_node_set_data (node, NULL); } @@ -407,16 +223,16 @@ _vcd_tree_node_append_child (VcdTreeNode *pnode, void *cdata) vcd_assert (pnode != NULL); if (!pnode->children) - pnode->children = _vcd_list_new (); + pnode->children = _cdio_list_new (); nnode = _vcd_malloc (sizeof (VcdTreeNode)); - _vcd_list_append (pnode->children, nnode); + _cdio_list_append (pnode->children, nnode); nnode->data = cdata; nnode->parent = pnode; nnode->tree = pnode->tree; - nnode->listnode = _vcd_list_end (pnode->children); + nnode->listnode = _cdio_list_end (pnode->children); return nnode; } @@ -429,7 +245,7 @@ _vcd_tree_node_first_child (VcdTreeNode *node) if (!node->children) return NULL; - return _vcd_list_node_data (_vcd_list_begin (node->children)); + return _cdio_list_node_data (_cdio_list_begin (node->children)); } VcdTreeNode * @@ -437,7 +253,7 @@ _vcd_tree_node_next_sibling (VcdTreeNode *node) { vcd_assert (node != NULL); - return _vcd_list_node_data (_vcd_list_node_next (node->listnode)); + return _cdio_list_node_data (_cdio_list_node_next (node->listnode)); } void @@ -446,7 +262,7 @@ _vcd_tree_node_sort_children (VcdTreeNode *node, _vcd_tree_node_cmp_func cmp_fun vcd_assert (node != NULL); if (node->children) - _vcd_list_sort (node->children, (_vcd_list_cmp_func) cmp_func); + _vcd_list_sort (node->children, (_cdio_list_cmp_func) cmp_func); } void @@ -471,31 +287,31 @@ _vcd_tree_node_traverse_bf (VcdTreeNode *node, _vcd_tree_node_traversal_func trav_func, void *user_data) /* breath-first */ { - VcdList *queue; + CdioList *queue; vcd_assert (node != NULL); - queue = _vcd_list_new (); + queue = _cdio_list_new (); - _vcd_list_prepend (queue, node); + _cdio_list_prepend (queue, node); - while (_vcd_list_length (queue)) + while (_cdio_list_length (queue)) { - VcdListNode *lastnode = _vcd_list_end (queue); - VcdTreeNode *treenode = _vcd_list_node_data (lastnode); - VcdTreeNode *childnode; + CdioListNode *lastnode = _cdio_list_end (queue); + VcdTreeNode *treenode = _cdio_list_node_data (lastnode); + VcdTreeNode *childnode; - _vcd_list_node_free (lastnode, false); + _cdio_list_node_free (lastnode, false); trav_func (treenode, user_data); _VCD_CHILD_FOREACH (childnode, treenode) { - _vcd_list_prepend (queue, childnode); + _cdio_list_prepend (queue, childnode); } } - _vcd_list_free (queue, false); + _cdio_list_free (queue, false); } VcdTreeNode *_vcd_tree_node_parent (VcdTreeNode *node) diff --git a/src/input/vcd/libvcd/data_structures.h b/src/input/vcd/libvcd/data_structures.h index 9ce996f01..70fe88045 100644 --- a/src/input/vcd/libvcd/data_structures.h +++ b/src/input/vcd/libvcd/data_structures.h @@ -1,5 +1,5 @@ /* - $Id: data_structures.h,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: data_structures.h,v 1.3 2005/01/01 02:43:59 rockyb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> @@ -21,48 +21,14 @@ #ifndef __VCD_DATA_STRUCTURES_H__ #define __VCD_DATA_STRUCTURES_H__ +#include <cdio/ds.h> #include <libvcd/types.h> -/* opaque... */ - -typedef int (*_vcd_list_cmp_func) (void *data1, void *data2); - -typedef int (*_vcd_list_iterfunc) (void *data, void *user_data); - -/* methods */ -VcdList *_vcd_list_new (void); - -void _vcd_list_free (VcdList *list, int free_data); - -unsigned _vcd_list_length (const VcdList *list); - -void _vcd_list_sort (VcdList *list, _vcd_list_cmp_func cmp_func); - -void _vcd_list_prepend (VcdList *list, void *data); - -void _vcd_list_append (VcdList *list, void *data); - -void _vcd_list_foreach (VcdList *list, _vcd_list_iterfunc func, void *user_data); - -VcdListNode *_vcd_list_find (VcdList *list, _vcd_list_iterfunc cmp_func, void *user_data); - -#define _VCD_LIST_FOREACH(node, list) \ - for (node = _vcd_list_begin (list); node; node = _vcd_list_node_next (node)) - /* node ops */ -VcdListNode *_vcd_list_at (VcdList *list, int idx); - -VcdListNode *_vcd_list_begin (const VcdList *list); - -VcdListNode *_vcd_list_end (VcdList *list); - -VcdListNode *_vcd_list_node_next (VcdListNode *node); - -void _vcd_list_node_free (VcdListNode *node, int free_data); - -void *_vcd_list_node_data (VcdListNode *node); +CdioListNode *_vcd_list_at (CdioList *list, int idx); +void _vcd_list_sort (CdioList *list, _cdio_list_cmp_func cmp_func); /* n-way tree */ diff --git a/src/input/vcd/libvcd/dict.h b/src/input/vcd/libvcd/dict.h index f7de3b1c9..229ad5706 100644 --- a/src/input/vcd/libvcd/dict.h +++ b/src/input/vcd/libvcd/dict.h @@ -1,7 +1,7 @@ /* - $Id: dict.h,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: dict.h,v 1.3 2005/01/01 02:43:59 rockyb Exp $ - Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> + Copyright (C) 2000, 2004 Herbert Valerio Riedel <hvr@gnu.org> 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 @@ -58,7 +58,7 @@ _dict_insert (VcdObj *obj, const char key[], uint32_t sector, uint32_t length, _new_node->buf = _vcd_malloc (length * ISO_BLOCKSIZE); _new_node->flags = end_flags; - _vcd_list_prepend (obj->buffer_dict_list, _new_node); + _cdio_list_prepend (obj->buffer_dict_list, _new_node); } static @@ -82,17 +82,17 @@ int _dict_sector_cmp (struct _dict_t *a, uint32_t *b) static const struct _dict_t * _dict_get_bykey (VcdObj *obj, const char key[]) { - VcdListNode *node; + CdioListNode *node; vcd_assert (obj != NULL); vcd_assert (key != NULL); - node = _vcd_list_find (obj->buffer_dict_list, - (_vcd_list_iterfunc) _dict_key_cmp, - (char *) key); + node = _cdio_list_find (obj->buffer_dict_list, + (_cdio_list_iterfunc) _dict_key_cmp, + (char *) key); if (node) - return _vcd_list_node_data (node); + return _cdio_list_node_data (node); return NULL; } @@ -100,17 +100,17 @@ _dict_get_bykey (VcdObj *obj, const char key[]) static const struct _dict_t * _dict_get_bysector (VcdObj *obj, uint32_t sector) { - VcdListNode *node; + CdioListNode *node; vcd_assert (obj != NULL); vcd_assert (sector != SECTOR_NIL); - node = _vcd_list_find (obj->buffer_dict_list, - (_vcd_list_iterfunc) _dict_sector_cmp, - §or); + node = _cdio_list_find (obj->buffer_dict_list, + (_cdio_list_iterfunc) _dict_sector_cmp, + §or); if (node) - return _vcd_list_node_data (node); + return _cdio_list_node_data (node); return NULL; } @@ -149,16 +149,16 @@ _dict_get_sector (VcdObj *obj, uint32_t sector) static void _dict_clean (VcdObj *obj) { - VcdListNode *node; + CdioListNode *node; - while ((node = _vcd_list_begin (obj->buffer_dict_list))) + while ((node = _cdio_list_begin (obj->buffer_dict_list))) { - struct _dict_t *p = _vcd_list_node_data (node); + struct _dict_t *p = _cdio_list_node_data (node); free (p->key); free (p->buf); - _vcd_list_node_free (node, true); + _cdio_list_node_free (node, true); } } diff --git a/src/input/vcd/libvcd/directory.c b/src/input/vcd/libvcd/directory.c index 49cc8fe8a..750bcd10c 100644 --- a/src/input/vcd/libvcd/directory.c +++ b/src/input/vcd/libvcd/directory.c @@ -1,5 +1,5 @@ /* - $Id: directory.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: directory.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> @@ -26,16 +26,16 @@ #include <string.h> /* Public headers */ +#include <cdio/bytesex.h> #include <cdio/iso9660.h> #include <libvcd/logging.h> /* Private headers */ #include "vcd_assert.h" -#include "bytesex.h" #include "directory.h" #include "util.h" -static const char _rcsid[] = "$Id: directory.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: directory.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $"; /* CD-ROM XA */ diff --git a/src/input/vcd/libvcd/files.c b/src/input/vcd/libvcd/files.c index 47210da7f..82d28eaf7 100644 --- a/src/input/vcd/libvcd/files.c +++ b/src/input/vcd/libvcd/files.c @@ -1,7 +1,7 @@ /* - $Id: files.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: files.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $ - Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> + Copyright (C) 2000, 2004 Herbert Valerio Riedel <hvr@gnu.org> 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 @@ -28,6 +28,7 @@ #include <math.h> #include <cdio/cdio.h> +#include <cdio/bytesex.h> #include <cdio/util.h> /* Public headers */ @@ -40,13 +41,12 @@ /* Private headers */ #include "vcd_assert.h" -#include "bytesex.h" #include "mpeg_stream.h" #include "obj.h" #include "pbc.h" #include "util.h" -static const char _rcsid[] = "$Id: files.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: files.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $"; inline static bool _pal_p (const struct vcd_mpeg_stream_vid_info *_info) @@ -136,15 +136,15 @@ _derive_aud_type (const struct vcd_mpeg_stream_info *_info, bool svcd) void set_entries_vcd (VcdObj *obj, void *buf) { - VcdListNode *node = NULL; + CdioListNode *node = NULL; int idx = 0; int track_idx = 0; - EntriesVcd entries_vcd; + EntriesVcd_t entries_vcd; - vcd_assert (sizeof(EntriesVcd) == 2048); + vcd_assert (sizeof(EntriesVcd_t) == 2048); - vcd_assert (_vcd_list_length (obj->mpeg_track_list) <= MAX_ENTRIES); - vcd_assert (_vcd_list_length (obj->mpeg_track_list) > 0); + vcd_assert (_cdio_list_length (obj->mpeg_track_list) <= MAX_ENTRIES); + vcd_assert (_cdio_list_length (obj->mpeg_track_list) > 0); memset(&entries_vcd, 0, sizeof(entries_vcd)); /* paranoia / fixme */ @@ -193,29 +193,29 @@ set_entries_vcd (VcdObj *obj, void *buf) idx = 0; track_idx = 2; - _VCD_LIST_FOREACH (node, obj->mpeg_sequence_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_sequence_list) { - mpeg_sequence_t *track = _vcd_list_node_data (node); + mpeg_sequence_t *track = _cdio_list_node_data (node); uint32_t lsect = track->relative_start_extent; - VcdListNode *node2; + CdioListNode *node2; lsect += obj->iso_size; - entries_vcd.entry[idx].n = to_bcd8(track_idx); + entries_vcd.entry[idx].n = cdio_to_bcd8(track_idx); cdio_lba_to_msf(cdio_lsn_to_lba(lsect), &(entries_vcd.entry[idx].msf)); idx++; lsect += obj->track_front_margin; - _VCD_LIST_FOREACH (node2, track->entry_list) + _CDIO_LIST_FOREACH (node2, track->entry_list) { - entry_t *_entry = _vcd_list_node_data (node2); + entry_t *_entry = _cdio_list_node_data (node2); /* additional entries */ vcd_assert (idx < MAX_ENTRIES); - entries_vcd.entry[idx].n = to_bcd8(track_idx); + entries_vcd.entry[idx].n = cdio_to_bcd8(track_idx); cdio_lba_to_msf(lsect + cdio_lsn_to_lba(_entry->aps.packet_no), &(entries_vcd.entry[idx].msf)); @@ -257,16 +257,16 @@ get_psd_size (VcdObj *obj, bool extended) void set_psd_vcd (VcdObj *obj, void *buf, bool extended) { - VcdListNode *node; + CdioListNode *node; if (extended) vcd_assert (_vcd_obj_has_cap_p (obj, _CAP_PBC_X)); vcd_assert (_vcd_pbc_available (obj)); - _VCD_LIST_FOREACH (node, obj->pbc_list) + _CDIO_LIST_FOREACH (node, obj->pbc_list) { - pbc_t *_pbc = _vcd_list_node_data (node); + pbc_t *_pbc = _cdio_list_node_data (node); char *_buf = buf; unsigned offset = (extended ? _pbc->offset_ext : _pbc->offset); @@ -279,23 +279,23 @@ set_psd_vcd (VcdObj *obj, void *buf, bool extended) void set_lot_vcd(VcdObj *obj, void *buf, bool extended) { - LotVcd *lot_vcd = NULL; - VcdListNode *node; + LotVcd_t *lot_vcd = NULL; + CdioListNode *node; if (extended) vcd_assert (_vcd_obj_has_cap_p (obj, _CAP_PBC_X)); vcd_assert (_vcd_pbc_available (obj)); - lot_vcd = _vcd_malloc (sizeof (LotVcd)); - memset(lot_vcd, 0xff, sizeof(LotVcd)); + lot_vcd = _vcd_malloc (sizeof (LotVcd_t)); + memset(lot_vcd, 0xff, sizeof(LotVcd_t)); lot_vcd->reserved = 0x0000; - _VCD_LIST_FOREACH (node, obj->pbc_list) + _CDIO_LIST_FOREACH (node, obj->pbc_list) { - pbc_t *_pbc = _vcd_list_node_data (node); - unsigned offset = extended ? _pbc->offset_ext : _pbc->offset; + pbc_t *_pbc = _cdio_list_node_data (node); + unsigned int offset = extended ? _pbc->offset_ext : _pbc->offset; vcd_assert (offset % INFO_OFFSET_MULT == 0); @@ -307,19 +307,19 @@ set_lot_vcd(VcdObj *obj, void *buf, bool extended) lot_vcd->offset[_pbc->lid - 1] = uint16_to_be (offset); } - memcpy(buf, lot_vcd, sizeof(LotVcd)); + memcpy(buf, lot_vcd, sizeof(LotVcd_t)); free(lot_vcd); } void set_info_vcd(VcdObj *obj, void *buf) { - InfoVcd info_vcd; - VcdListNode *node = NULL; + InfoVcd_t info_vcd; + CdioListNode *node = NULL; int n = 0; - vcd_assert (sizeof (InfoVcd) == 2048); - vcd_assert (_vcd_list_length (obj->mpeg_track_list) <= 98); + vcd_assert (sizeof (InfoVcd_t) == 2048); + vcd_assert (_cdio_list_length (obj->mpeg_track_list) <= 98); memset (&info_vcd, 0, sizeof (info_vcd)); @@ -373,9 +373,9 @@ set_info_vcd(VcdObj *obj, void *buf) /* NTSC/PAL bitset */ n = 0; - _VCD_LIST_FOREACH (node, obj->mpeg_track_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_track_list) { - mpeg_track_t *track = _vcd_list_node_data (node); + mpeg_track_t *track = _cdio_list_node_data (node); const struct vcd_mpeg_stream_vid_info *_info = &track->info->shdr[0]; @@ -407,7 +407,7 @@ set_info_vcd(VcdObj *obj, void *buf) info_vcd.offset_mult = _vcd_pbc_available (obj) ? INFO_OFFSET_MULT : 0; info_vcd.lot_entries = uint16_to_be (_vcd_pbc_max_lid (obj)); - if (_vcd_list_length (obj->mpeg_segment_list)) + if (_cdio_list_length (obj->mpeg_segment_list)) { unsigned segments = 0; @@ -415,9 +415,9 @@ set_info_vcd(VcdObj *obj, void *buf) vcd_warn ("segment items available, but no PBC items set!" " SPIs will be unreachable"); - _VCD_LIST_FOREACH (node, obj->mpeg_segment_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_segment_list) { - mpeg_segment_t *segment = _vcd_list_node_data (node); + mpeg_segment_t *segment = _cdio_list_node_data (node); unsigned idx; InfoSpiContents contents = { 0, }; @@ -465,20 +465,20 @@ set_tracks_svd_v30 (VcdObj *obj, void *buf) { char tracks_svd_buf[ISO_BLOCKSIZE] = { 0, }; TracksSVD_v30 *tracks_svd = (void *) tracks_svd_buf; - VcdListNode *node; + CdioListNode *node; double playtime; int n; strncpy (tracks_svd->file_id, TRACKS_SVD_FILE_ID, sizeof (TRACKS_SVD_FILE_ID)); tracks_svd->version = TRACKS_SVD_VERSION; - tracks_svd->tracks = _vcd_list_length (obj->mpeg_track_list); + tracks_svd->tracks = _cdio_list_length (obj->mpeg_track_list); n = 0; playtime = 0; - _VCD_LIST_FOREACH (node, obj->mpeg_track_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_track_list) { - mpeg_track_t *track = _vcd_list_node_data (node); + mpeg_track_t *track = _cdio_list_node_data (node); int i; playtime += track->info->playing_time; @@ -502,7 +502,8 @@ set_tracks_svd_v30 (VcdObj *obj, void *buf) f = modf(playtime, &i); cdio_lba_to_msf (i * 75, &tracks_svd->track[n].cum_playing_time); - tracks_svd->track[n].cum_playing_time.f = to_bcd8 (floor (f * 75.0)); + tracks_svd->track[n].cum_playing_time.f = + cdio_to_bcd8 (floor (f * 75.0)); } n++; @@ -517,7 +518,7 @@ set_tracks_svd (VcdObj *obj, void *buf) char tracks_svd[ISO_BLOCKSIZE] = { 0, }; TracksSVD *tracks_svd1 = (void *) tracks_svd; TracksSVD2 *tracks_svd2; - VcdListNode *node; + CdioListNode *node; int n; vcd_assert (_vcd_obj_has_cap_p (obj, _CAP_4C_SVCD)); @@ -533,15 +534,15 @@ set_tracks_svd (VcdObj *obj, void *buf) strncpy (tracks_svd1->file_id, TRACKS_SVD_FILE_ID, sizeof (TRACKS_SVD_FILE_ID)); tracks_svd1->version = TRACKS_SVD_VERSION; - tracks_svd1->tracks = _vcd_list_length (obj->mpeg_track_list); + tracks_svd1->tracks = _cdio_list_length (obj->mpeg_track_list); tracks_svd2 = (void *) &(tracks_svd1->playing_time[tracks_svd1->tracks]); n = 0; - _VCD_LIST_FOREACH (node, obj->mpeg_track_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_track_list) { - mpeg_track_t *track = _vcd_list_node_data (node); + mpeg_track_t *track = _cdio_list_node_data (node); const double playtime = track->info->playing_time; int _video; @@ -574,7 +575,7 @@ set_tracks_svd (VcdObj *obj, void *buf) } cdio_lba_to_msf (i * 75, &(tracks_svd1->playing_time[n])); - tracks_svd1->playing_time[n].f = to_bcd8 (floor (f * 75.0)); + tracks_svd1->playing_time[n].f = cdio_to_bcd8 (floor (f * 75.0)); } n++; @@ -587,11 +588,11 @@ static double _get_cumulative_playing_time (const VcdObj *obj, unsigned up_to_track_no) { double result = 0; - VcdListNode *node; + CdioListNode *node; - _VCD_LIST_FOREACH (node, obj->mpeg_track_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_track_list) { - mpeg_track_t *track = _vcd_list_node_data (node); + mpeg_track_t *track = _cdio_list_node_data (node); if (!up_to_track_no) break; @@ -611,7 +612,7 @@ _get_scanpoint_count (const VcdObj *obj) { double total_playing_time; - total_playing_time = _get_cumulative_playing_time (obj, _vcd_list_length (obj->mpeg_track_list)); + total_playing_time = _get_cumulative_playing_time (obj, _cdio_list_length (obj->mpeg_track_list)); return ceil (total_playing_time * 2.0); } @@ -623,39 +624,39 @@ get_search_dat_size (const VcdObj *obj) + (_get_scanpoint_count (obj) * sizeof (msf_t)); } -static VcdList * +static CdioList * _make_track_scantable (const VcdObj *obj) { - VcdList *all_aps = _vcd_list_new (); - VcdList *scantable = _vcd_list_new (); + CdioList *all_aps = _cdio_list_new (); + CdioList *scantable = _cdio_list_new (); unsigned scanpoints = _get_scanpoint_count (obj); unsigned track_no; - VcdListNode *node; + CdioListNode *node; track_no = 0; - _VCD_LIST_FOREACH (node, obj->mpeg_track_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_track_list) { - mpeg_track_t *track = _vcd_list_node_data (node); - VcdListNode *node2; + mpeg_track_t *track = _cdio_list_node_data (node); + CdioListNode *node2; - _VCD_LIST_FOREACH (node2, track->info->shdr[0].aps_list) + _CDIO_LIST_FOREACH (node2, track->info->shdr[0].aps_list) { struct aps_data *_data = _vcd_malloc (sizeof (struct aps_data)); - *_data = *(struct aps_data *)_vcd_list_node_data (node2); + *_data = *(struct aps_data *)_cdio_list_node_data (node2); _data->timestamp += _get_cumulative_playing_time (obj, track_no); _data->packet_no += obj->iso_size + track->relative_start_extent; _data->packet_no += obj->track_front_margin; - _vcd_list_append (all_aps, _data); + _cdio_list_append (all_aps, _data); } track_no++; } { - VcdListNode *aps_node = _vcd_list_begin (all_aps); - VcdListNode *n; + CdioListNode *aps_node = _cdio_list_begin (all_aps); + CdioListNode *n; struct aps_data *_data; double aps_time; double playing_time; @@ -667,15 +668,16 @@ _make_track_scantable (const VcdObj *obj) vcd_assert (aps_node != NULL); - _data = _vcd_list_node_data (aps_node); + _data = _cdio_list_node_data (aps_node); aps_time = _data->timestamp; aps_packet = _data->packet_no; for (t = 0; t < playing_time; t += 0.5) { - for(n = _vcd_list_node_next (aps_node); n; n = _vcd_list_node_next (n)) + for(n = _cdio_list_node_next (aps_node); n; + n = _cdio_list_node_next (n)) { - _data = _vcd_list_node_data (n); + _data = _cdio_list_node_data (n); if (fabs (_data->timestamp - t) < fabs (aps_time - t)) { @@ -691,16 +693,16 @@ _make_track_scantable (const VcdObj *obj) uint32_t *lsect = _vcd_malloc (sizeof (uint32_t)); *lsect = aps_packet; - _vcd_list_append (scantable, lsect); + _cdio_list_append (scantable, lsect); } } } - _vcd_list_free (all_aps, true); + _cdio_list_free (all_aps, true); - vcd_assert (scanpoints == _vcd_list_length (scantable)); + vcd_assert (scanpoints == _cdio_list_length (scantable)); return scantable; } @@ -708,8 +710,8 @@ _make_track_scantable (const VcdObj *obj) void set_search_dat (VcdObj *obj, void *buf) { - VcdList *scantable; - VcdListNode *node; + CdioList *scantable; + CdioListNode *node; SearchDat search_dat; unsigned n; @@ -729,10 +731,10 @@ set_search_dat (VcdObj *obj, void *buf) scantable = _make_track_scantable (obj); n = 0; - _VCD_LIST_FOREACH (node, scantable) + _CDIO_LIST_FOREACH (node, scantable) { SearchDat *search_dat2 = buf; - uint32_t sect = *(uint32_t *) _vcd_list_node_data (node); + uint32_t sect = *(uint32_t *) _cdio_list_node_data (node); cdio_lba_to_msf(cdio_lsn_to_lba(sect), &(search_dat2->points[n])); n++; @@ -740,7 +742,7 @@ set_search_dat (VcdObj *obj, void *buf) vcd_assert (n = _get_scanpoint_count (obj)); - _vcd_list_free (scantable, true); + _cdio_list_free (scantable, true); } static uint32_t @@ -752,7 +754,7 @@ _get_scandata_count (const struct vcd_mpeg_stream_info *info) static uint32_t * _get_scandata_table (const struct vcd_mpeg_stream_info *info) { - VcdListNode *n, *aps_node = _vcd_list_begin (info->shdr[0].aps_list); + CdioListNode *n, *aps_node = _cdio_list_begin (info->shdr[0].aps_list); struct aps_data *_data; double aps_time, t; int aps_packet; @@ -761,15 +763,15 @@ _get_scandata_table (const struct vcd_mpeg_stream_info *info) retval = _vcd_malloc (_get_scandata_count (info) * sizeof (uint32_t)); - _data = _vcd_list_node_data (aps_node); + _data = _cdio_list_node_data (aps_node); aps_time = _data->timestamp; aps_packet = _data->packet_no; for (t = 0, i = 0; t < info->playing_time; t += 0.5, i++) { - for(n = _vcd_list_node_next (aps_node); n; n = _vcd_list_node_next (n)) + for(n = _cdio_list_node_next (aps_node); n; n = _cdio_list_node_next (n)) { - _data = _vcd_list_node_data (n); + _data = _cdio_list_node_data (n); if (fabs (_data->timestamp - t) < fabs (aps_time - t)) { @@ -800,7 +802,7 @@ get_scandata_dat_size (const VcdObj *obj) /* struct 1 */ retval += sizeof (ScandataDat1); - retval += sizeof (msf_t) * _vcd_list_length (obj->mpeg_track_list); + retval += sizeof (msf_t) * _cdio_list_length (obj->mpeg_track_list); /* struct 2 */ /* vcd_assert (sizeof (ScandataDat2) == 0); @@ -809,16 +811,16 @@ get_scandata_dat_size (const VcdObj *obj) /* struct 3 */ retval += sizeof (ScandataDat3); - retval += (sizeof (uint8_t) + sizeof (uint16_t)) * _vcd_list_length (obj->mpeg_track_list); + retval += (sizeof (uint8_t) + sizeof (uint16_t)) * _cdio_list_length (obj->mpeg_track_list); /* struct 4 */ /* vcd_assert (sizeof (ScandataDat4) == 0); retval += sizeof (ScandataDat4); */ { - VcdListNode *node; - _VCD_LIST_FOREACH (node, obj->mpeg_track_list) + CdioListNode *node; + _CDIO_LIST_FOREACH (node, obj->mpeg_track_list) { - const mpeg_track_t *track = _vcd_list_node_data (node); + const mpeg_track_t *track = _cdio_list_node_data (node); retval += sizeof (msf_t) * _get_scandata_count (track->info); } @@ -830,7 +832,7 @@ get_scandata_dat_size (const VcdObj *obj) void set_scandata_dat (VcdObj *obj, void *buf) { - const unsigned tracks = _vcd_list_length (obj->mpeg_track_list); + const unsigned tracks = _cdio_list_length (obj->mpeg_track_list); ScandataDat1 *scandata_dat1 = (ScandataDat1 *) buf; ScandataDat2 *scandata_dat2 = @@ -844,7 +846,7 @@ set_scandata_dat (VcdObj *obj, void *buf) __cd_offsetof (ScandataDat3, mpeg_track_offsets[tracks]) - __cd_offsetof (ScandataDat3, mpeg_track_offsets); - VcdListNode *node; + CdioListNode *node; unsigned n; uint16_t _tmp_offset; @@ -875,7 +877,7 @@ set_scandata_dat (VcdObj *obj, void *buf) vcd_assert (i >= 0); cdio_lba_to_msf (i * 75, &(scandata_dat1->cum_playtimes[n])); - scandata_dat1->cum_playtimes[n].f = to_bcd8 (floor (f * 75.0)); + scandata_dat1->cum_playtimes[n].f = cdio_to_bcd8 (floor (f * 75.0)); } /* struct 2 -- nothing yet */ @@ -890,9 +892,9 @@ set_scandata_dat (VcdObj *obj, void *buf) scandata_dat3->mpegtrack_start_index = uint16_to_be (_begin_offset); n = 0; - _VCD_LIST_FOREACH (node, obj->mpeg_track_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_track_list) { - const mpeg_track_t *track = _vcd_list_node_data (node); + const mpeg_track_t *track = _cdio_list_node_data (node); uint32_t *_table; const unsigned scanpoints = _get_scandata_count (track->info); const unsigned _table_ofs = @@ -932,7 +934,7 @@ set_scandata_dat (VcdObj *obj, void *buf) vcd_type_t vcd_files_info_detect_type (const void *info_buf) { - const InfoVcd *_info = info_buf; + const InfoVcd_t *_info = info_buf; vcd_type_t _type = VCD_TYPE_INVALID; vcd_assert (info_buf != NULL); diff --git a/src/input/vcd/libvcd/image.c b/src/input/vcd/libvcd/image.c index 8824d3b79..d26bb0910 100644 --- a/src/input/vcd/libvcd/image.c +++ b/src/input/vcd/libvcd/image.c @@ -1,5 +1,5 @@ /* - $Id: image.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: image.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $ Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> 2002 Rocky Bernstein <rocky@panix.com> @@ -34,7 +34,7 @@ #include "image_sink.h" #include "util.h" -static const char _rcsid[] = "$Id: image.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: image.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $"; /* * VcdImageSink routines next. @@ -68,7 +68,7 @@ vcd_image_sink_destroy (VcdImageSink *obj) } int -vcd_image_sink_set_cuesheet (VcdImageSink *obj, const VcdList *vcd_cue_list) +vcd_image_sink_set_cuesheet (VcdImageSink *obj, const CdioList *vcd_cue_list) { vcd_assert (obj != NULL); @@ -76,7 +76,7 @@ vcd_image_sink_set_cuesheet (VcdImageSink *obj, const VcdList *vcd_cue_list) } int -vcd_image_sink_write (VcdImageSink *obj, void *buf, uint32_t lsn) +vcd_image_sink_write (VcdImageSink *obj, void *buf, lsn_t lsn) { vcd_assert (obj != NULL); diff --git a/src/input/vcd/libvcd/image_bincue.c b/src/input/vcd/libvcd/image_bincue.c index f8af4bbe0..9c447a42a 100644 --- a/src/input/vcd/libvcd/image_bincue.c +++ b/src/input/vcd/libvcd/image_bincue.c @@ -1,7 +1,7 @@ /* - $Id: image_bincue.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: image_bincue.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $ - Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> + Copyright (C) 2001, 2004 Herbert Valerio Riedel <hvr@gnu.org> 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 @@ -27,6 +27,7 @@ #include <string.h> #include <cdio/cdio.h> +#include <cdio/bytesex.h> #include <cdio/iso9660.h> /* Public headers */ @@ -35,12 +36,11 @@ /* Private headers */ #include "vcd_assert.h" -#include "bytesex.h" #include "image_sink.h" #include "stream_stdio.h" #include "util.h" -static const char _rcsid[] = "$Id: image_bincue.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: image_bincue.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $"; /* reader */ @@ -88,10 +88,10 @@ _sink_free (void *user_data) } static int -_set_cuesheet (void *user_data, const VcdList *vcd_cue_list) +_set_cuesheet (void *user_data, const CdioList *vcd_cue_list) { _img_bincue_snk_t *_obj = user_data; - VcdListNode *node; + CdioListNode *node; int track_no, index_no; const vcd_cue_t *_last_cue = 0; @@ -102,9 +102,10 @@ _set_cuesheet (void *user_data, const VcdList *vcd_cue_list) track_no = 0; index_no = 0; - _VCD_LIST_FOREACH (node, (VcdList *) vcd_cue_list) + _CDIO_LIST_FOREACH (node, (CdioList *) vcd_cue_list) { - const vcd_cue_t *_cue = _vcd_list_node_data (node); + const vcd_cue_t *_cue = _cdio_list_node_data (node); + char *psz_msf; msf_t _msf = { 0, 0, 0 }; @@ -122,19 +123,23 @@ _set_cuesheet (void *user_data, const VcdList *vcd_cue_list) if (_last_cue && _last_cue->type == VCD_CUE_PREGAP_START) { cdio_lba_to_msf (_last_cue->lsn, &_msf); + psz_msf = cdio_msf_to_str(&_msf); vcd_data_sink_printf (_obj->cue_snk, - " INDEX %2.2d %2.2x:%2.2x:%2.2x\r\n", - index_no, _msf.m, _msf.s, _msf.f); + " INDEX %2.2d %s\r\n", + index_no, psz_msf); + free(psz_msf); } index_no++; cdio_lba_to_msf (_cue->lsn, &_msf); + psz_msf = cdio_msf_to_str(&_msf); vcd_data_sink_printf (_obj->cue_snk, - " INDEX %2.2d %2.2x:%2.2x:%2.2x\r\n", - index_no, _msf.m, _msf.s, _msf.f); + " INDEX %2.2d %s\r\n", + index_no, psz_msf); + free(psz_msf); break; case VCD_CUE_PREGAP_START: @@ -145,13 +150,15 @@ _set_cuesheet (void *user_data, const VcdList *vcd_cue_list) vcd_assert (_last_cue != 0); index_no++; - vcd_assert (index_no < 100); + vcd_assert (index_no <= CDIO_CD_MAX_TRACKS); cdio_lba_to_msf (_cue->lsn, &_msf); + psz_msf = cdio_msf_to_str(&_msf); vcd_data_sink_printf (_obj->cue_snk, - " INDEX %2.2d %2.2x:%2.2x:%2.2x\r\n", - index_no, _msf.m, _msf.s, _msf.f); + " INDEX %2.2d %s\r\n", + index_no, psz_msf); + free(psz_msf); break; case VCD_CUE_END: @@ -172,7 +179,7 @@ _set_cuesheet (void *user_data, const VcdList *vcd_cue_list) } static int -_vcd_image_bincue_write (void *user_data, const void *data, uint32_t lsn) +_vcd_image_bincue_write (void *user_data, const void *data, lsn_t lsn) { const char *buf = data; _img_bincue_snk_t *_obj = user_data; diff --git a/src/input/vcd/libvcd/image_cdrdao.c b/src/input/vcd/libvcd/image_cdrdao.c index 58543ff8e..5e00c14ee 100644 --- a/src/input/vcd/libvcd/image_cdrdao.c +++ b/src/input/vcd/libvcd/image_cdrdao.c @@ -1,5 +1,5 @@ /* - $Id: image_cdrdao.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: image_cdrdao.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $ Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> @@ -28,18 +28,18 @@ /* Public headers */ #include <cdio/iso9660.h> +#include <cdio/bytesex.h> #include <libvcd/sector.h> #include <libvcd/logging.h> /* Private headers */ #include "vcd_assert.h" -#include "bytesex.h" #include "image_sink.h" #include "stream_stdio.h" #include "util.h" #include "vcd.h" -static const char _rcsid[] = "$Id: image_cdrdao.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: image_cdrdao.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $"; /* reader */ @@ -56,7 +56,7 @@ typedef struct { int last_snk_idx; bool last_pause; - VcdList *vcd_cue_list; + CdioList *vcd_cue_list; } _img_cdrdao_snk_t; static void @@ -73,12 +73,12 @@ _sink_free (void *user_data) } static int -_set_cuesheet (void *user_data, const VcdList *vcd_cue_list) +_set_cuesheet (void *user_data, const CdioList *vcd_cue_list) { _img_cdrdao_snk_t *_obj = user_data; VcdDataSink *toc_snk = vcd_data_sink_new_stdio (_obj->toc_fname); - VcdListNode *node; + CdioListNode *node; int track_no, index_no; const vcd_cue_t *_last_cue = 0; @@ -89,18 +89,18 @@ _set_cuesheet (void *user_data, const VcdList *vcd_cue_list) "// generated by %s\n\n" "CD_ROM_XA\n", vcd_version_string (false)); - _obj->vcd_cue_list = _vcd_list_new (); + _obj->vcd_cue_list = _cdio_list_new (); index_no = track_no = 0; - _VCD_LIST_FOREACH (node, (VcdList *) vcd_cue_list) + _CDIO_LIST_FOREACH (node, (CdioList *) vcd_cue_list) { - const vcd_cue_t *_cue = _vcd_list_node_data (node); + const vcd_cue_t *_cue = _cdio_list_node_data (node); /* copy cue list while traversing */ { vcd_cue_t *_cue2 = _vcd_malloc (sizeof (vcd_cue_t)); *_cue2 = *_cue; - _vcd_list_append (_obj->vcd_cue_list, _cue2); + _cdio_list_append (_obj->vcd_cue_list, _cue2); } switch (_cue->type) @@ -139,12 +139,13 @@ _set_cuesheet (void *user_data, const VcdList *vcd_cue_list) { msf_t _msf = { 0, 0, 0 }; + char *psz_msf; cdio_lba_to_msf (_cue->lsn - last_track_lsn, &_msf); + psz_msf = cdio_msf_to_str(&_msf); - vcd_data_sink_printf (toc_snk, - " INDEX %2.2x:%2.2x:%2.2x\n", - _msf.m, _msf.s, _msf.f); + vcd_data_sink_printf (toc_snk, " INDEX %s\n", psz_msf); + free(psz_msf); } break; @@ -170,23 +171,23 @@ _set_cuesheet (void *user_data, const VcdList *vcd_cue_list) } static int -_vcd_image_cdrdao_write (void *user_data, const void *data, uint32_t lsn) +_vcd_image_cdrdao_write (void *user_data, const void *data, lsn_t lsn) { const char *buf = data; _img_cdrdao_snk_t *_obj = user_data; long offset; { - VcdListNode *node; + CdioListNode *node; uint32_t _last = 0; uint32_t _ofs = 0; bool _lpregap = false; bool _pregap = false; int num = 0, in_track = 0; - _VCD_LIST_FOREACH (node, _obj->vcd_cue_list) + _CDIO_LIST_FOREACH (node, _obj->vcd_cue_list) { - const vcd_cue_t *_cue = _vcd_list_node_data (node); + const vcd_cue_t *_cue = _cdio_list_node_data (node); switch (_cue->type) { diff --git a/src/input/vcd/libvcd/image_nrg.c b/src/input/vcd/libvcd/image_nrg.c index 29798d724..c7912e26a 100644 --- a/src/input/vcd/libvcd/image_nrg.c +++ b/src/input/vcd/libvcd/image_nrg.c @@ -1,7 +1,7 @@ /* - $Id: image_nrg.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: image_nrg.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $ - Copyright (C) 2001,2003 Herbert Valerio Riedel <hvr@gnu.org> + Copyright (C) 2001, 2003, 2004 Herbert Valerio Riedel <hvr@gnu.org> 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 @@ -31,6 +31,7 @@ #include <string.h> #include <cdio/cdio.h> +#include <cdio/bytesex.h> #include <cdio/iso9660.h> /* Public headers */ @@ -39,12 +40,11 @@ /* Private headers */ #include "vcd_assert.h" -#include "bytesex.h" #include "image_sink.h" #include "stream_stdio.h" #include "util.h" -static const char _rcsid[] = "$Id: image_nrg.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: image_nrg.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $"; /* structures used */ @@ -107,7 +107,7 @@ typedef struct { VcdDataSink *nrg_snk; char *nrg_fname; - VcdList *vcd_cue_list; + CdioList *vcd_cue_list; int tracks; uint32_t cue_end_lsn; @@ -139,23 +139,23 @@ _sink_free (void *user_data) } static int -_set_cuesheet (void *user_data, const VcdList *vcd_cue_list) +_set_cuesheet (void *user_data, const CdioList *vcd_cue_list) { _img_nrg_snk_t *_obj = user_data; - VcdListNode *node; + CdioListNode *node; int num; _sink_init (_obj); - _obj->vcd_cue_list = _vcd_list_new (); + _obj->vcd_cue_list = _cdio_list_new (); num = 0; - _VCD_LIST_FOREACH (node, (VcdList *) vcd_cue_list) + _CDIO_LIST_FOREACH (node, (CdioList *) vcd_cue_list) { - const vcd_cue_t *_cue = _vcd_list_node_data (node); + const vcd_cue_t *_cue = _cdio_list_node_data (node); vcd_cue_t *_cue2 = _vcd_malloc (sizeof (vcd_cue_t)); *_cue2 = *_cue; - _vcd_list_append (_obj->vcd_cue_list, _cue2); + _cdio_list_append (_obj->vcd_cue_list, _cue2); if (_cue->type == VCD_CUE_TRACK_START) num++; @@ -166,7 +166,7 @@ _set_cuesheet (void *user_data, const VcdList *vcd_cue_list) _obj->tracks = num; - vcd_assert (num > 0 && num < 100); + vcd_assert (CDIO_CD_MIN_TRACK_NO >= 1 && num <= CDIO_CD_MAX_TRACKS); return 0; } @@ -174,15 +174,15 @@ _set_cuesheet (void *user_data, const VcdList *vcd_cue_list) static uint32_t _map (_img_nrg_snk_t *_obj, uint32_t lsn) { - VcdListNode *node; + CdioListNode *node; uint32_t result = lsn; vcd_cue_t *_cue = NULL, *_last = NULL; vcd_assert (_obj->cue_end_lsn > lsn); - _VCD_LIST_FOREACH (node, _obj->vcd_cue_list) + _CDIO_LIST_FOREACH (node, _obj->vcd_cue_list) { - _cue = _vcd_list_node_data (node); + _cue = _cdio_list_node_data (node); if (lsn < _cue->lsn) break; @@ -226,7 +226,7 @@ _map (_img_nrg_snk_t *_obj, uint32_t lsn) static int _write_tail (_img_nrg_snk_t *_obj, uint32_t offset) { - VcdListNode *node; + CdioListNode *node; int _size; _chunk_t _chunk; @@ -238,13 +238,14 @@ _write_tail (_img_nrg_snk_t *_obj, uint32_t offset) vcd_data_sink_write (_obj->nrg_snk, &_chunk, sizeof (_chunk_t), 1); - _VCD_LIST_FOREACH (node, _obj->vcd_cue_list) + _CDIO_LIST_FOREACH (node, _obj->vcd_cue_list) { - vcd_cue_t *_cue = _vcd_list_node_data (node); + vcd_cue_t *_cue = _cdio_list_node_data (node); if (_cue->type == VCD_CUE_TRACK_START) { - vcd_cue_t *_cue2 = _vcd_list_node_data (_vcd_list_node_next (node)); + vcd_cue_t *_cue2 = + _cdio_list_node_data (_cdio_list_node_next (node)); _etnf_array_t _etnf = { 0, }; @@ -281,7 +282,7 @@ _write_tail (_img_nrg_snk_t *_obj, uint32_t offset) } static int -_vcd_image_nrg_write (void *user_data, const void *data, uint32_t lsn) +_vcd_image_nrg_write (void *user_data, const void *data, lsn_t lsn) { const char *buf = data; _img_nrg_snk_t *_obj = user_data; diff --git a/src/input/vcd/libvcd/image_sink.h b/src/input/vcd/libvcd/image_sink.h index 98bbc0eb5..a71e30199 100644 --- a/src/input/vcd/libvcd/image_sink.h +++ b/src/input/vcd/libvcd/image_sink.h @@ -1,5 +1,5 @@ /* - $Id: image_sink.h,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: image_sink.h,v 1.3 2005/01/01 02:43:59 rockyb Exp $ Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> @@ -48,7 +48,7 @@ typedef struct { } vcd_cue_t; typedef struct { - int (*set_cuesheet) (void *user_data, const VcdList *vcd_cue_list); + int (*set_cuesheet) (void *user_data, const CdioList *vcd_cue_list); int (*write) (void *user_data, const void *buf, lsn_t lsn); void (*free) (void *user_data); int (*set_arg) (void *user_data, const char key[], const char value[]); @@ -61,7 +61,7 @@ void vcd_image_sink_destroy (VcdImageSink *obj); int -vcd_image_sink_set_cuesheet (VcdImageSink *obj, const VcdList *vcd_cue_list); +vcd_image_sink_set_cuesheet (VcdImageSink *obj, const CdioList *vcd_cue_list); int vcd_image_sink_write (VcdImageSink *obj, void *buf, lsn_t lsn); diff --git a/src/input/vcd/libvcd/inf.c b/src/input/vcd/libvcd/inf.c index c483f76af..588c8e5f7 100644 --- a/src/input/vcd/libvcd/inf.c +++ b/src/input/vcd/libvcd/inf.c @@ -1,5 +1,5 @@ /* - $Id: inf.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: inf.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $ Copyright (C) 2002,2003 Rocky Bernstein <rocky@panix.com> @@ -50,17 +50,17 @@ #endif #include <cdio/cdio.h> +#include <cdio/bytesex.h> #include <cdio/util.h> /* Eventually move above libvcd includes but having vcdinfo including. */ #include <libvcd/info.h> /* Private headers */ -#include "bytesex.h" #include "info_private.h" #include "pbc.h" -static const char _rcsid[] = "$Id: inf.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: inf.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $"; #define BUF_COUNT 16 #define BUF_SIZE 80 @@ -105,29 +105,18 @@ vcdinf_area_str (const struct psd_area_t *_area) some problem in getting this. */ const char * -vcdinf_get_album_id(const InfoVcd *info) +vcdinf_get_album_id(const InfoVcd_t *info) { if (NULL==info) return NULL; return vcdinfo_strip_trail (info->album_desc, MAX_ALBUM_LEN); } /*! - Return the VCD application ID. - NULL is returned if there is some problem in getting this. -*/ -const char * -vcdinf_get_application_id(const iso9660_pvd_t *pvd) -{ - if (NULL==pvd) return NULL; - return(vcdinfo_strip_trail(pvd->application_id, MAX_APPLICATION_ID)); -} - -/*! Get autowait time value for PsdPlayListDescriptor *d. Time is in seconds unless it is -1 (unlimited). */ int -vcdinf_get_autowait_time (const PsdPlayListDescriptor *d) +vcdinf_get_autowait_time (const PsdPlayListDescriptor_t *d) { return vcdinfo_get_wait_time (d->atime); } @@ -137,7 +126,7 @@ vcdinf_get_autowait_time (const PsdPlayListDescriptor *d) is an error. */ unsigned int -vcdinf_get_bsn(const PsdSelectionListDescriptor *psd) +vcdinf_get_bsn(const PsdSelectionListDescriptor_t *psd) { if (NULL==psd) return VCDINFO_INVALID_BSN; return(psd->bsn); @@ -179,7 +168,7 @@ vcdinf_get_format_version_str (vcd_type_t vcd_type) Return loop count. 0 is infinite loop. */ uint16_t -vcdinf_get_loop_count (const PsdSelectionListDescriptor *psd) +vcdinf_get_loop_count (const PsdSelectionListDescriptor_t *psd) { return 0x7f & psd->loop; } @@ -188,7 +177,7 @@ vcdinf_get_loop_count (const PsdSelectionListDescriptor *psd) Return LOT offset */ uint16_t -vcdinf_get_lot_offset (const LotVcd *lot, unsigned int n) +vcdinf_get_lot_offset (const LotVcd_t *lot, unsigned int n) { return uint16_from_be (lot->offset[n]); } @@ -197,7 +186,7 @@ vcdinf_get_lot_offset (const LotVcd *lot, unsigned int n) Return the number of entries in the VCD. */ unsigned int -vcdinf_get_num_entries(const EntriesVcd *entries) +vcdinf_get_num_entries(const EntriesVcd_t *entries) { if (NULL==entries) return 0; return (uint16_from_be (entries->entry_count)); @@ -207,7 +196,7 @@ vcdinf_get_num_entries(const EntriesVcd *entries) Return the number of segments in the VCD. */ segnum_t -vcdinf_get_num_segments(const InfoVcd *info) +vcdinf_get_num_segments(const InfoVcd_t *info) { if (NULL==info) return 0; return (uint16_from_be (info->item_count)); @@ -217,7 +206,7 @@ vcdinf_get_num_segments(const InfoVcd *info) Return number of LIDs. */ lid_t -vcdinf_get_num_LIDs (const InfoVcd *info) +vcdinf_get_num_LIDs (const InfoVcd_t *info) { if (NULL==info) return 0; /* Should probably use _vcd_pbc_max_lid instead? */ @@ -228,7 +217,7 @@ vcdinf_get_num_LIDs (const InfoVcd *info) Return the number of menu selections for selection list descriptor psd. */ unsigned int -vcdinf_get_num_selections(const PsdSelectionListDescriptor *psd) +vcdinf_get_num_selections(const PsdSelectionListDescriptor_t *psd) { return psd->nos; } @@ -238,62 +227,29 @@ vcdinf_get_num_selections(const PsdSelectionListDescriptor *psd) Time is in 1/15-second units. */ uint16_t -vcdinf_get_play_time (const PsdPlayListDescriptor *d) +vcdinf_get_play_time (const PsdPlayListDescriptor_t *d) { if (NULL==d) return 0; return uint16_from_be (d->ptime); } /*! - Return a string containing the VCD preparer id with trailing - blanks removed. -*/ -const char * -vcdinf_get_preparer_id(const iso9660_pvd_t *pvd) -{ - if (NULL==pvd) return NULL; - return(vcdinfo_strip_trail(pvd->preparer_id, MAX_PREPARER_ID)); -} - -/*! - Return a string containing the VCD publisher id with trailing - blanks removed. -*/ -const char * -vcdinf_get_publisher_id(const iso9660_pvd_t *pvd) -{ - if (NULL==pvd) return NULL; - return(vcdinfo_strip_trail(pvd->publisher_id, MAX_PUBLISHER_ID)); -} - -/*! Return number of bytes in PSD. */ uint32_t -vcdinf_get_psd_size (const InfoVcd *info) +vcdinf_get_psd_size (const InfoVcd_t *info) { if (NULL==info) return 0; return uint32_from_be (info->psd_size); } /*! - Return a string containing the VCD system id with trailing - blanks removed. -*/ -const char * -vcdinf_get_system_id(const iso9660_pvd_t *pvd) -{ - if (NULL==pvd) return NULL; - return(vcdinfo_strip_trail(pvd->system_id, MAX_SYSTEM_ID)); -} - -/*! Get timeout wait time value for PsdPlayListDescriptor *d. Return VCDINFO_INVALID_OFFSET if d is NULL; Time is in seconds unless it is -1 (unlimited). */ uint16_t -vcdinf_get_timeout_offset (const PsdSelectionListDescriptor *d) +vcdinf_get_timeout_offset (const PsdSelectionListDescriptor_t *d) { if (NULL == d) return VCDINFO_INVALID_OFFSET; return uint16_from_be (d->timeout_ofs); @@ -304,7 +260,7 @@ vcdinf_get_timeout_offset (const PsdSelectionListDescriptor *d) Time is in seconds unless it is -1 (unlimited). */ int -vcdinf_get_timeout_time (const PsdSelectionListDescriptor *d) +vcdinf_get_timeout_time (const PsdSelectionListDescriptor_t *d) { return vcdinfo_get_wait_time (d->totime); } @@ -315,12 +271,12 @@ vcdinf_get_timeout_time (const PsdSelectionListDescriptor *d) (We don't count the header track?) */ track_t -vcdinf_get_track(const EntriesVcd *entries, const unsigned int entry_num) +vcdinf_get_track(const EntriesVcd_t *entries, const unsigned int entry_num) { const unsigned int entry_count = uint16_from_be (entries->entry_count); /* Note entry_num is 0 origin. */ return entry_num < entry_count ? - from_bcd8 (entries->entry[entry_num].n): + cdio_from_bcd8 (entries->entry[entry_num].n): VCDINFO_INVALID_TRACK; } @@ -328,50 +284,29 @@ vcdinf_get_track(const EntriesVcd *entries, const unsigned int entry_num) Return the VCD volume count - the number of CD's in the collection. */ unsigned int -vcdinf_get_volume_count(const InfoVcd *info) +vcdinf_get_volume_count(const InfoVcd_t *info) { if (NULL==info) return 0; return(uint16_from_be( info->vol_count)); } /*! - Return the VCD ID. -*/ -const char * -vcdinf_get_volume_id(const iso9660_pvd_t *pvd) -{ - if (NULL == pvd) return NULL; - return(vcdinfo_strip_trail(pvd->volume_id, MAX_VOLUME_ID)); -} - -/*! Return the VCD volume num - the number of the CD in the collection. This is a number between 1 and the volume count. */ unsigned int -vcdinf_get_volume_num(const InfoVcd *info) +vcdinf_get_volume_num(const InfoVcd_t *info) { if (NULL == info) return 0; return uint16_from_be(info->vol_id); } /*! - Return the VCD volumeset ID. - NULL is returned if there is some problem in getting this. -*/ -const char * -vcdinf_get_volumeset_id(const iso9660_pvd_t *pvd) -{ - if ( NULL == pvd ) return NULL; - return vcdinfo_strip_trail(pvd->volume_set_id, MAX_VOLUMESET_ID); -} - -/*! Get wait time value for PsdPlayListDescriptor *d. Time is in seconds unless it is -1 (unlimited). */ int -vcdinf_get_wait_time (const PsdPlayListDescriptor *d) +vcdinf_get_wait_time (const PsdPlayListDescriptor_t *d) { return vcdinfo_get_wait_time (d->wtime); } @@ -380,7 +315,7 @@ vcdinf_get_wait_time (const PsdPlayListDescriptor *d) Return true if loop has a jump delay */ bool -vcdinf_has_jump_delay (const PsdSelectionListDescriptor *psd) +vcdinf_has_jump_delay (const PsdSelectionListDescriptor_t *psd) { if (NULL==psd) return false; return ((0x80 & psd->loop) != 0); @@ -419,7 +354,7 @@ vcdinf_lid_t_cmp (vcdinfo_offset_t *a, vcdinfo_offset_t *b) VCDINFO_REJECTED_MASK is returned d on error or pld is NULL. */ lid_t -vcdinf_pld_get_lid(const PsdPlayListDescriptor *pld) +vcdinf_pld_get_lid(const PsdPlayListDescriptor_t *pld) { return (pld != NULL) ? uint16_from_be (pld->lid) & VCDINFO_LID_MASK @@ -433,7 +368,7 @@ vcdinf_pld_get_lid(const PsdPlayListDescriptor *pld) entry or pld is NULL. Otherwise the LID offset is returned. */ uint16_t -vcdinf_pld_get_next_offset(const PsdPlayListDescriptor *pld) +vcdinf_pld_get_next_offset(const PsdPlayListDescriptor_t *pld) { if (NULL == pld) return VCDINFO_INVALID_OFFSET; return uint16_from_be (pld->next_ofs); @@ -443,7 +378,7 @@ vcdinf_pld_get_next_offset(const PsdPlayListDescriptor *pld) Return number of items in LIDs. Return 0 if error or not found. */ int -vcdinf_pld_get_noi (const PsdPlayListDescriptor *pld) +vcdinf_pld_get_noi (const PsdPlayListDescriptor_t *pld) { if ( NULL == pld ) return 0; return pld->noi; @@ -453,7 +388,7 @@ vcdinf_pld_get_noi (const PsdPlayListDescriptor *pld) Return the playlist item i in d. */ uint16_t -vcdinf_pld_get_play_item(const PsdPlayListDescriptor *pld, unsigned int i) +vcdinf_pld_get_play_item(const PsdPlayListDescriptor_t *pld, unsigned int i) { if (NULL==pld) return 0; return uint16_from_be(pld->itemid[i]); @@ -466,7 +401,7 @@ vcdinf_pld_get_play_item(const PsdPlayListDescriptor *pld, unsigned int i) entry or pld is NULL. Otherwise the LID offset is returned. */ uint16_t -vcdinf_pld_get_prev_offset(const PsdPlayListDescriptor *pld) +vcdinf_pld_get_prev_offset(const PsdPlayListDescriptor_t *pld) { return (pld != NULL) ? uint16_from_be (pld->prev_ofs) : VCDINFO_INVALID_OFFSET; @@ -479,7 +414,7 @@ vcdinf_pld_get_prev_offset(const PsdPlayListDescriptor *pld) "return" entry or pld is NULL. Otherwise the LID offset is returned. */ uint16_t -vcdinf_pld_get_return_offset(const PsdPlayListDescriptor *pld) +vcdinf_pld_get_return_offset(const PsdPlayListDescriptor_t *pld) { return (pld != NULL) ? uint16_from_be (pld->return_ofs) : VCDINFO_INVALID_OFFSET; @@ -492,7 +427,7 @@ vcdinf_pld_get_return_offset(const PsdPlayListDescriptor *pld) * NULL. Otherwise the LID offset is returned. */ uint16_t -vcdinf_psd_get_default_offset(const PsdSelectionListDescriptor *psd) +vcdinf_psd_get_default_offset(const PsdSelectionListDescriptor_t *psd) { if (NULL == psd) return VCDINFO_INVALID_OFFSET; return uint16_from_be (psd->default_ofs); @@ -503,7 +438,7 @@ vcdinf_psd_get_default_offset(const PsdSelectionListDescriptor *psd) VCDINFO_REJECTED_MASK is returned on error or if psd is NULL. */ uint16_t -vcdinf_psd_get_itemid(const PsdSelectionListDescriptor *psd) +vcdinf_psd_get_itemid(const PsdSelectionListDescriptor_t *psd) { return (psd != NULL) ? uint16_from_be(psd->itemid) : VCDINFO_REJECTED_MASK; } @@ -513,7 +448,7 @@ vcdinf_psd_get_itemid(const PsdSelectionListDescriptor *psd) VCDINFO_REJECTED_MASK is returned on error or psd is NULL. */ lid_t -vcdinf_psd_get_lid(const PsdSelectionListDescriptor *psd) +vcdinf_psd_get_lid(const PsdSelectionListDescriptor_t *psd) { return (psd != NULL) ? uint16_from_be (psd->lid) & VCDINFO_LID_MASK @@ -525,7 +460,7 @@ vcdinf_psd_get_lid(const PsdSelectionListDescriptor *psd) true is also returned d is NULL. */ bool -vcdinf_psd_get_lid_rejected(const PsdSelectionListDescriptor *psd) +vcdinf_psd_get_lid_rejected(const PsdSelectionListDescriptor_t *psd) { return (psd != NULL) ? vcdinfo_is_rejected(uint16_from_be(psd->lid)) @@ -539,7 +474,7 @@ vcdinf_psd_get_lid_rejected(const PsdSelectionListDescriptor *psd) * NULL. Otherwise the LID offset is returned. */ uint16_t -vcdinf_psd_get_next_offset(const PsdSelectionListDescriptor *psd) +vcdinf_psd_get_next_offset(const PsdSelectionListDescriptor_t *psd) { if (NULL == psd) return VCDINFO_INVALID_OFFSET; return uint16_from_be (psd->next_ofs); @@ -553,7 +488,7 @@ vcdinf_psd_get_next_offset(const PsdSelectionListDescriptor *psd) * NULL. Otherwise the LID offset is returned. */ uint16_t -vcdinf_psd_get_offset(const PsdSelectionListDescriptor *psd, +vcdinf_psd_get_offset(const PsdSelectionListDescriptor_t *psd, unsigned int entry_num) { return (psd != NULL && entry_num < vcdinf_get_num_selections(psd)) @@ -567,7 +502,7 @@ vcdinf_psd_get_offset(const PsdSelectionListDescriptor *psd, entry or psd is NULL. Otherwise the LID offset is returned. */ uint16_t -vcdinf_psd_get_prev_offset(const PsdSelectionListDescriptor *psd) +vcdinf_psd_get_prev_offset(const PsdSelectionListDescriptor_t *psd) { return (psd != NULL) ? uint16_from_be (psd->prev_ofs) : VCDINFO_INVALID_OFFSET; @@ -580,7 +515,7 @@ vcdinf_psd_get_prev_offset(const PsdSelectionListDescriptor *psd) "return" entry or psd is NULL. Otherwise the LID offset is returned. */ uint16_t -vcdinf_psd_get_return_offset(const PsdSelectionListDescriptor *psd) +vcdinf_psd_get_return_offset(const PsdSelectionListDescriptor_t *psd) { return (psd != NULL) ? uint16_from_be (psd->return_ofs) : VCDINFO_INVALID_OFFSET; diff --git a/src/input/vcd/libvcd/info.c b/src/input/vcd/libvcd/info.c index 096cb0b84..accd3e77f 100644 --- a/src/input/vcd/libvcd/info.c +++ b/src/input/vcd/libvcd/info.c @@ -1,7 +1,7 @@ /* - $Id: info.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: info.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $ - Copyright (C) 2002,2003 Rocky Bernstein <rocky@panix.com> + Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com> 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 @@ -27,7 +27,6 @@ /* Private headers */ #include "info_private.h" #include "vcd_assert.h" -#include "bytesex.h" #include "pbc.h" #include "util.h" #include "vcd_read.h" @@ -49,6 +48,7 @@ #endif #include <cdio/cdio.h> +#include <cdio/bytesex.h> #include <cdio/cd_types.h> #include <cdio/util.h> @@ -59,11 +59,7 @@ #include <stddef.h> #include <errno.h> -static const char _rcsid[] = "$Id: info.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $"; - -#define MIN_ENCODED_TRACK_NUM 100 -#define MIN_ENCODED_SEGMENT_NUM 1000 -#define MAX_ENCODED_SEGMENT_NUM 2979 +static const char _rcsid[] = "$Id: info.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $"; #define BUF_COUNT 16 #define BUF_SIZE 80 @@ -98,10 +94,10 @@ _getbuf (void) static void _init_segments (vcdinfo_obj_t *obj) { - InfoVcd *info = vcdinfo_get_infoVcd(obj); + InfoVcd_t *info = vcdinfo_get_infoVcd(obj); segnum_t num_segments = vcdinfo_get_num_segments(obj); - VcdListNode *entnode; - VcdList *entlist; + CdioListNode *entnode; + CdioList *entlist; int i; lsn_t last_lsn=0; @@ -113,8 +109,8 @@ _init_segments (vcdinfo_obj_t *obj) entlist = iso9660_fs_readdir(obj->img, "SEGMENT", true); i=0; - _VCD_LIST_FOREACH (entnode, entlist) { - iso9660_stat_t *statbuf = _vcd_list_node_data (entnode); + _CDIO_LIST_FOREACH (entnode, entlist) { + iso9660_stat_t *statbuf = _cdio_list_node_data (entnode); if (statbuf->type == _STAT_DIR) continue; @@ -145,7 +141,7 @@ _init_segments (vcdinfo_obj_t *obj) vcd_warn ("Number of segments found %d is not number of segments %d", i, num_segments); - _vcd_list_free (entlist, true); + _cdio_list_free (entlist, true); #if 0 @@ -281,7 +277,7 @@ vcdinfo_audio_type2str(const vcdinfo_obj_t *obj, unsigned int audio_type) const char * vcdinfo_ogt2str(const vcdinfo_obj_t *obj, segnum_t seg_num) { - const InfoVcd *info = &obj->info; + const InfoVcd_t *info = &obj->info; const char *ogt_str[] = { "None", @@ -356,7 +352,7 @@ vcdinfo_pin2str (uint16_t itemid_num) snprintf (buf, BUF_SIZE, "play nothing (0x%4.4x)", itemid.num); break; case VCDINFO_ITEM_TYPE_TRACK: - snprintf (buf, BUF_SIZE, "SEQUENCE[%d] (0x%4.4x)", itemid.num, + snprintf (buf, BUF_SIZE, "SEQUENCE[%d] (0x%4.4x)", itemid.num-1, itemid_num); break; case VCDINFO_ITEM_TYPE_ENTRY: @@ -391,11 +387,11 @@ vcdinfo_get_album_id(const vcdinfo_obj_t *obj) Return the VCD ID. NULL is returned if there is some problem in getting this. */ -const char * -vcdinfo_get_application_id(const vcdinfo_obj_t *obj) +char * +vcdinfo_get_application_id(vcdinfo_obj_t *p_obj) { - if ( NULL == obj ) return (NULL); - return(vcdinf_get_application_id(&obj->pvd)); + if ( NULL == p_obj ) return (NULL); + return iso9660_get_application_id(&p_obj->pvd); } /*! @@ -452,16 +448,25 @@ lid_t vcdinfo_selection_get_lid(const vcdinfo_obj_t *obj, lid_t lid, Return the LID offset associated with a the selection number of the passed-in LID parameter. - \return VCDINFO_INVALID_OFFSET is returned if obj on error or obj - is NULL. Otherwise the LID offset is returned. + \return VCDINFO_INVALID_OFFSET is returned if error, obj is NULL or + the lid is not some type of selection list. Otherwise the LID offset + is returned. */ uint16_t vcdinfo_selection_get_offset(const vcdinfo_obj_t *obj, lid_t lid, unsigned int selection) { unsigned int bsn; - PsdListDescriptor pxd; + PsdListDescriptor_t pxd; vcdinfo_lid_get_pxd(obj, &pxd, lid); + if (pxd.descriptor_type != PSD_TYPE_SELECTION_LIST && + pxd.descriptor_type != PSD_TYPE_EXT_SELECTION_LIST) { + vcd_warn( "Requesting selection of LID %i which not a selection list -" + " type is 0x%x", + lid, pxd.descriptor_type ); + return VCDINFO_INVALID_OFFSET; + } + bsn=vcdinf_get_bsn(pxd.psd); if ( (selection - bsn + 1) > 0) { @@ -483,7 +488,7 @@ vcdinfo_get_default_offset(const vcdinfo_obj_t *obj, lid_t lid) { if (NULL != obj) { - PsdListDescriptor pxd; + PsdListDescriptor_t pxd; vcdinfo_lid_get_pxd(obj, &pxd, lid); @@ -518,9 +523,14 @@ vcdinfo_get_default_offset(const vcdinfo_obj_t *obj, lid_t lid) */ lid_t vcdinfo_get_multi_default_lid(const vcdinfo_obj_t *obj, lid_t lid, - unsigned int entry_num) + lsn_t lsn) { - unsigned int offset = vcdinfo_get_multi_default_offset(obj, lid, entry_num); + unsigned int offset; + unsigned int entry_num; + + entry_num = vcdinfo_lsn_get_entry(obj, lsn); + offset = vcdinfo_get_multi_default_offset(obj, lid, entry_num); + switch (offset) { case VCDINFO_INVALID_OFFSET: case PSD_OFS_MULTI_DEF: @@ -560,21 +570,34 @@ vcdinfo_get_multi_default_offset(const vcdinfo_obj_t *obj, lid_t lid, case PSD_OFS_MULTI_DEF_NO_NUM: { /* Have some work todo... Figure the selection number. */ - unsigned int selection=0; - track_t track=vcdinfo_get_track(obj, entry_num); - track_t prev_track=VCDINFO_INVALID_TRACK; - for (selection=1; - track != VCDINFO_INVALID_TRACK - && track != prev_track - && entry_num > 0; - selection++) { - prev_track = track; - track=vcdinfo_get_track(obj, --entry_num); + PsdListDescriptor_t pxd; + + vcdinfo_lid_get_pxd(obj, &pxd, lid); + + switch (pxd.descriptor_type) { + + case PSD_TYPE_SELECTION_LIST: + case PSD_TYPE_EXT_SELECTION_LIST: { + vcdinfo_itemid_t selection_itemid; + uint16_t selection_itemid_num; + unsigned int start_entry_num; + + if (pxd.psd == NULL) return VCDINFO_INVALID_OFFSET; + selection_itemid_num = vcdinf_psd_get_itemid(pxd.psd); + vcdinfo_classify_itemid(selection_itemid_num, &selection_itemid); + if (selection_itemid.type != VCDINFO_ITEM_TYPE_TRACK) { + return VCDINFO_INVALID_OFFSET; + } + + start_entry_num = vcdinfo_track_get_entry(obj, selection_itemid.num); + return vcdinfo_selection_get_offset(obj, lid, + entry_num-start_entry_num); + } + default: ; } - return vcdinfo_selection_get_offset(obj, lid, selection); } - default: - return offset; + default: + return VCDINFO_INVALID_OFFSET; } } @@ -605,7 +628,7 @@ vcdinfo_get_default_device (const vcdinfo_obj_t *vcd_obj) uint32_t vcdinfo_get_entry_sect_count (const vcdinfo_obj_t *obj, unsigned int entry_num) { - const EntriesVcd *entries = &obj->entries; + const EntriesVcd_t *entries = &obj->entries; const unsigned int entry_count = vcdinf_get_num_entries(entries); if (entry_num > entry_count) return 0; @@ -665,7 +688,7 @@ vcdinfo_get_entry_sect_count (const vcdinfo_obj_t *obj, unsigned int entry_num) const msf_t * vcdinfo_get_entry_msf(const vcdinfo_obj_t *obj, unsigned int entry_num) { - const EntriesVcd *entries = &obj->entries; + const EntriesVcd_t *entries = &obj->entries; return vcdinf_get_entry_msf(entries, entry_num); } @@ -696,6 +719,13 @@ vcdinfo_get_entry_lsn(const vcdinfo_obj_t *obj, unsigned int entry_num) } } +EntriesVcd_t * +vcdinfo_get_entriesVcd (vcdinfo_obj_t *obj) +{ + if (NULL == obj) return NULL; + return &obj->entries; +} + /*! Get the VCD format (VCD 1.0 VCD 1.1, SVCD, ... for this object. The type is also set inside obj. @@ -717,25 +747,41 @@ vcdinfo_get_format_version_str (const vcdinfo_obj_t *obj) return vcdinf_get_format_version_str(obj->vcd_type); } -EntriesVcd * -vcdinfo_get_entriesVcd (vcdinfo_obj_t *obj) +InfoVcd_t * +vcdinfo_get_infoVcd (vcdinfo_obj_t *obj) { if (NULL == obj) return NULL; - return &obj->entries; + return &obj->info; } -InfoVcd * -vcdinfo_get_infoVcd (vcdinfo_obj_t *obj) +/*! Return the entry number closest and before the given LSN. + */ +unsigned int +vcdinfo_lsn_get_entry(const vcdinfo_obj_t *obj, lsn_t lsn) { - if (NULL == obj) return NULL; - return &obj->info; + + /* Do a binary search to find the entry. */ + unsigned int i = 0; + unsigned int j = vcdinfo_get_num_entries(obj); + unsigned int mid; + unsigned int mid_lsn; + do { + mid = (i+j)/2; + mid_lsn = vcdinfo_get_entry_lsn(obj, mid); + if ( lsn <= mid_lsn ) j = mid-1; + if ( lsn >= mid_lsn ) i = mid+1; + } while (i <= j); + + /* We want the entry closest but before. */ + return (lsn == mid_lsn) ? mid : mid-1; } + void * -vcdinfo_get_tracksSVD (vcdinfo_obj_t *obj) +vcdinfo_get_pvd (vcdinfo_obj_t *obj) { if (NULL == obj) return NULL; - return obj->tracks_buf; + return &obj->pvd; } void * @@ -753,10 +799,10 @@ vcdinfo_get_searchDat (vcdinfo_obj_t *obj) } void * -vcdinfo_get_pvd (vcdinfo_obj_t *obj) +vcdinfo_get_tracksSVD (vcdinfo_obj_t *obj) { if (NULL == obj) return NULL; - return &obj->pvd; + return obj->tracks_buf; } /*! @@ -766,7 +812,7 @@ vcdinfo_get_pvd (vcdinfo_obj_t *obj) uint16_t vcdinfo_lid_get_itemid(const vcdinfo_obj_t *obj, lid_t lid) { - PsdListDescriptor pxd; + PsdListDescriptor_t pxd; if (obj == NULL) return VCDINFO_REJECTED_MASK; vcdinfo_lid_get_pxd(obj, &pxd, lid); @@ -790,7 +836,7 @@ vcdinfo_lid_get_itemid(const vcdinfo_obj_t *obj, lid_t lid) /*! Get the LOT pointer. */ -LotVcd * +LotVcd_t * vcdinfo_get_lot(const vcdinfo_obj_t *obj) { if (NULL == obj) return NULL; @@ -800,7 +846,7 @@ vcdinfo_get_lot(const vcdinfo_obj_t *obj) /*! Get the extended LOT pointer. */ -LotVcd * +LotVcd_t * vcdinfo_get_lot_x(const vcdinfo_obj_t *obj) { if (NULL == obj) return NULL; @@ -824,7 +870,7 @@ vcdinfo_get_num_LIDs (const vcdinfo_obj_t *obj) unsigned int vcdinfo_get_num_entries(const vcdinfo_obj_t *obj) { - const EntriesVcd *entries = &obj->entries; + const EntriesVcd_t *entries = &obj->entries; return vcdinf_get_num_entries(entries); } @@ -849,7 +895,7 @@ uint16_t vcdinfo_lid_get_offset(const vcdinfo_obj_t *obj, lid_t lid, unsigned int entry_num) { - PsdListDescriptor pxd; + PsdListDescriptor_t pxd; if (obj == NULL) return VCDINFO_INVALID_OFFSET; vcdinfo_lid_get_pxd(obj, &pxd, lid); @@ -876,8 +922,8 @@ vcdinfo_lid_get_offset(const vcdinfo_obj_t *obj, lid_t lid, static vcdinfo_offset_t * _vcdinfo_get_offset_t (const vcdinfo_obj_t *obj, unsigned int offset, bool ext) { - VcdListNode *node; - VcdList *offset_list = ext ? obj->offset_x_list : obj->offset_list; + CdioListNode *node; + CdioList *offset_list = ext ? obj->offset_x_list : obj->offset_list; switch (offset) { case PSD_OFS_DISABLED: @@ -887,9 +933,9 @@ _vcdinfo_get_offset_t (const vcdinfo_obj_t *obj, unsigned int offset, bool ext) default: ; } - _VCD_LIST_FOREACH (node, offset_list) + _CDIO_LIST_FOREACH (node, offset_list) { - vcdinfo_offset_t *ofs = _vcd_list_node_data (node); + vcdinfo_offset_t *ofs = _cdio_list_node_data (node); if (offset == ofs->offset) return ofs; } @@ -899,7 +945,7 @@ _vcdinfo_get_offset_t (const vcdinfo_obj_t *obj, unsigned int offset, bool ext) /*! Get the VCD info list. */ -VcdList * +CdioList * vcdinfo_get_offset_list(const vcdinfo_obj_t *obj) { if (NULL == obj) return NULL; @@ -910,7 +956,7 @@ vcdinfo_get_offset_list(const vcdinfo_obj_t *obj) /*! Get the VCD info extended offset list. */ -VcdList * +CdioList * vcdinfo_get_offset_x_list(const vcdinfo_obj_t *obj) { if (NULL == obj) return NULL; @@ -947,7 +993,7 @@ const char * vcdinfo_get_preparer_id(const vcdinfo_obj_t *obj) { if ( NULL == obj ) return (NULL); - return vcdinf_get_preparer_id(&obj->pvd); + return iso9660_get_preparer_id(&obj->pvd); } /*! @@ -998,7 +1044,7 @@ const char * vcdinfo_get_publisher_id(const vcdinfo_obj_t *obj) { if ( NULL == obj ) return (NULL); - return vcdinf_get_publisher_id(&obj->pvd); + return iso9660_get_publisher_id(&obj->pvd); } /*! @@ -1006,19 +1052,19 @@ vcdinfo_get_publisher_id(const vcdinfo_obj_t *obj) NULL is returned if error or not found. */ static bool -_vcdinfo_lid_get_pxd(const vcdinfo_obj_t *obj, PsdListDescriptor *pxd, +_vcdinfo_lid_get_pxd(const vcdinfo_obj_t *obj, PsdListDescriptor_t *pxd, uint16_t lid, bool ext) { - VcdListNode *node; + CdioListNode *node; unsigned mult = obj->info.offset_mult; const uint8_t *psd = ext ? obj->psd_x : obj->psd; - VcdList *offset_list = ext ? obj->offset_x_list : obj->offset_list; + CdioList *offset_list = ext ? obj->offset_x_list : obj->offset_list; if (offset_list == NULL) return false; - _VCD_LIST_FOREACH (node, offset_list) + _CDIO_LIST_FOREACH (node, offset_list) { - vcdinfo_offset_t *ofs = _vcd_list_node_data (node); + vcdinfo_offset_t *ofs = _cdio_list_node_data (node); unsigned _rofs = ofs->offset * mult; pxd->descriptor_type = psd[_rofs]; @@ -1027,7 +1073,7 @@ _vcdinfo_lid_get_pxd(const vcdinfo_obj_t *obj, PsdListDescriptor *pxd, { case PSD_TYPE_PLAY_LIST: { - pxd->pld = (PsdPlayListDescriptor *) (psd + _rofs); + pxd->pld = (PsdPlayListDescriptor_t *) (psd + _rofs); if (vcdinf_pld_get_lid(pxd->pld) == lid) { return true; } @@ -1037,7 +1083,7 @@ _vcdinfo_lid_get_pxd(const vcdinfo_obj_t *obj, PsdListDescriptor *pxd, case PSD_TYPE_EXT_SELECTION_LIST: case PSD_TYPE_SELECTION_LIST: { - pxd->psd = (PsdSelectionListDescriptor *) (psd + _rofs); + pxd->psd = (PsdSelectionListDescriptor_t *) (psd + _rofs); if (vcdinf_psd_get_lid(pxd->psd) == lid) { return true; } @@ -1054,7 +1100,7 @@ _vcdinfo_lid_get_pxd(const vcdinfo_obj_t *obj, PsdListDescriptor *pxd, False is returned if not found. */ bool -vcdinfo_lid_get_pxd(const vcdinfo_obj_t *obj, PsdListDescriptor *pxd, +vcdinfo_lid_get_pxd(const vcdinfo_obj_t *obj, PsdListDescriptor_t *pxd, uint16_t lid) { if (_vcdinfo_lid_get_pxd(obj, pxd, lid, true)) @@ -1073,7 +1119,7 @@ vcdinfo_get_return_offset(const vcdinfo_obj_t *obj, lid_t lid) { if (NULL != obj) { - PsdListDescriptor pxd; + PsdListDescriptor_t pxd; vcdinfo_lid_get_pxd(obj, &pxd, lid); @@ -1189,7 +1235,7 @@ const char * vcdinfo_get_system_id(const vcdinfo_obj_t *obj) { if ( NULL == obj || NULL == &obj->pvd ) return (NULL); - return(vcdinf_get_system_id(&obj->pvd)); + return(iso9660_get_system_id(&obj->pvd)); } /*! @@ -1202,7 +1248,7 @@ vcdinfo_get_system_id(const vcdinfo_obj_t *obj) track_t vcdinfo_get_track(const vcdinfo_obj_t *obj, const unsigned int entry_num) { - const EntriesVcd *entries = &obj->entries; + const EntriesVcd_t *entries = &obj->entries; const unsigned int entry_count = vcdinf_get_num_entries(entries); /* Note entry_num is 0 origin. */ return entry_num < entry_count ? @@ -1311,9 +1357,9 @@ vcdinfo_get_track_msf(const vcdinfo_obj_t *obj, track_t track_num, /* CdIo tracks start at 1 rather than 0. */ if (cdio_get_track_msf(obj->img, track_num+1, &msf)) { - *min = from_bcd8(msf.m); - *sec = from_bcd8(msf.s); - *frame = from_bcd8(msf.f); + *min = cdio_from_bcd8(msf.m); + *sec = cdio_from_bcd8(msf.s); + *frame = cdio_from_bcd8(msf.f); return 0; } @@ -1398,7 +1444,7 @@ vcdinfo_get_track_size(const vcdinfo_obj_t *obj, track_t track_num) vcdinfo_video_segment_type_t vcdinfo_get_video_type(const vcdinfo_obj_t *obj, segnum_t seg_num) { - const InfoVcd *info; + const InfoVcd_t *info; if (obj == NULL) return VCDINFO_FILES_VIDEO_INVALID; info = &obj->info; if (info == NULL) return VCDINFO_FILES_VIDEO_INVALID; @@ -1435,7 +1481,7 @@ const char * vcdinfo_get_volume_id(const vcdinfo_obj_t *obj) { if ( NULL == obj || NULL == &obj->pvd ) return (NULL); - return(vcdinf_get_volume_id(&obj->pvd)); + return(iso9660_get_volume_id(&obj->pvd)); } /*! @@ -1446,7 +1492,7 @@ const char * vcdinfo_get_volumeset_id(const vcdinfo_obj_t *obj) { if ( NULL == obj || NULL == &obj->pvd ) return (NULL); - return(vcdinfo_strip_trail(obj->pvd.volume_set_id, MAX_VOLUMESET_ID)); + return(vcdinfo_strip_trail(obj->pvd.volume_set_id, ISO_MAX_VOLUMESET_ID)); } /*! @@ -1615,6 +1661,17 @@ vcdinfo_read_psd (vcdinfo_obj_t *obj) return true; } +/*! Return the entry number for the given track. */ +unsigned int +vcdinfo_track_get_entry(const vcdinfo_obj_t *obj, track_t i_track) +{ + /* FIXME: Add structure to directly map track to first entry number. + Until then... + */ + lsn_t lsn= vcdinfo_get_track_lsn(obj, i_track); + return vcdinfo_lsn_get_entry(obj, lsn); +} + /*! Calls recursive routine to populate obj->offset_list or obj->offset_x_list by going through LOT. @@ -1641,10 +1698,10 @@ vcdinfo_visit_lot (vcdinfo_obj_t *obj, bool extended) ret = vcdinf_visit_lot(&pbc_ctx); if (NULL != obj->offset_x_list) - _vcd_list_free(obj->offset_x_list, true); + _cdio_list_free(obj->offset_x_list, true); obj->offset_x_list = pbc_ctx.offset_x_list; if (NULL != obj->offset_list) - _vcd_list_free(obj->offset_list, true); + _cdio_list_free(obj->offset_list, true); obj->offset_list = pbc_ctx.offset_list; return ret; } @@ -1747,10 +1804,10 @@ vcdinfo_open(vcdinfo_obj_t **obj_p, char *source_name[], */ if (NULL == *source_name && source_type == DRIVER_UNKNOWN) { char **cd_drives=NULL; - cd_drives = cdio_get_devices_with_cap(NULL, + cd_drives = cdio_get_devices_with_cap_ret(NULL, (CDIO_FS_ANAL_SVCD|CDIO_FS_ANAL_CVD|CDIO_FS_ANAL_VIDEOCD |CDIO_FS_UNKNOWN), - true); + true, &source_type); if ( NULL == cd_drives || NULL == cd_drives[0] ) { return VCDINFO_OPEN_ERROR; } @@ -1776,7 +1833,7 @@ vcdinfo_open(vcdinfo_obj_t **obj_p, char *source_name[], memset (obj, 0, sizeof (vcdinfo_obj_t)); obj->img = img; /* Note we do this after the above wipeout! */ - if (!read_pvd(obj->img, &(obj->pvd))) { + if (!iso9660_fs_read_pvd(obj->img, &(obj->pvd))) { return VCDINFO_OPEN_ERROR; } @@ -1806,7 +1863,7 @@ vcdinfo_open(vcdinfo_obj_t **obj_p, char *source_name[], } if (obj->vcd_type == VCD_TYPE_SVCD || obj->vcd_type == VCD_TYPE_HQVCD) { - statbuf = iso9660_fs_stat (obj->img, "MPEGAV", true); + statbuf = iso9660_fs_stat (obj->img, "MPEGAV"); if (NULL != statbuf) { vcd_warn ("non compliant /MPEGAV folder detected!"); @@ -1814,7 +1871,7 @@ vcdinfo_open(vcdinfo_obj_t **obj_p, char *source_name[], } - statbuf = iso9660_fs_stat (obj->img, "SVCD/TRACKS.SVD;1", true); + statbuf = iso9660_fs_stat (obj->img, "SVCD/TRACKS.SVD;1"); if (NULL != statbuf) { lsn_t lsn = statbuf->lsn; if (statbuf->size != ISO_BLOCKSIZE) @@ -1836,7 +1893,7 @@ vcdinfo_open(vcdinfo_obj_t **obj_p, char *source_name[], iso9660_fs_readdir(img, "EXT", true) and then scanning for the files listed below. */ - statbuf = iso9660_fs_stat (img, "EXT/PSD_X.VCD;1", true); + statbuf = iso9660_fs_stat (img, "EXT/PSD_X.VCD;1"); if (NULL != statbuf) { lsn_t lsn = statbuf->lsn; uint32_t secsize = statbuf->secsize; @@ -1852,7 +1909,7 @@ vcdinfo_open(vcdinfo_obj_t **obj_p, char *source_name[], return VCDINFO_OPEN_ERROR; } - statbuf = iso9660_fs_stat (img, "EXT/LOT_X.VCD;1", true); + statbuf = iso9660_fs_stat (img, "EXT/LOT_X.VCD;1"); if (NULL != statbuf) { lsn_t lsn = statbuf->lsn; uint32_t secsize = statbuf->secsize; @@ -1877,13 +1934,13 @@ vcdinfo_open(vcdinfo_obj_t **obj_p, char *source_name[], iso9660_fs_readdir(img, "SVCD", true) and then scanning for the files listed below. */ - statbuf = iso9660_fs_stat (img, "MPEGAV", true); + statbuf = iso9660_fs_stat (img, "MPEGAV"); if (NULL != statbuf) { vcd_warn ("non compliant /MPEGAV folder detected!"); free(statbuf); } - statbuf = iso9660_fs_stat (img, "SVCD/TRACKS.SVD;1", true); + statbuf = iso9660_fs_stat (img, "SVCD/TRACKS.SVD;1"); if (NULL == statbuf) vcd_warn ("mandatory /SVCD/TRACKS.SVD not found!"); else { @@ -1892,7 +1949,7 @@ vcdinfo_open(vcdinfo_obj_t **obj_p, char *source_name[], free(statbuf); } - statbuf = iso9660_fs_stat (img, "SVCD/SEARCH.DAT;1", true); + statbuf = iso9660_fs_stat (img, "SVCD/SEARCH.DAT;1"); if (NULL == statbuf) vcd_warn ("mandatory /SVCD/SEARCH.DAT not found!"); else { @@ -1931,7 +1988,7 @@ vcdinfo_open(vcdinfo_obj_t **obj_p, char *source_name[], ; } - statbuf = iso9660_fs_stat (img, "EXT/SCANDATA.DAT;1", true); + statbuf = iso9660_fs_stat (img, "EXT/SCANDATA.DAT;1"); if (statbuf != NULL) { lsn_t lsn = statbuf->lsn; uint32_t secsize = statbuf->secsize; @@ -1960,13 +2017,14 @@ vcdinfo_close(vcdinfo_obj_t *obj) { if (obj != NULL) { if (obj->offset_list != NULL) - _vcd_list_free(obj->offset_list, true); + _cdio_list_free(obj->offset_list, true); if (obj->offset_x_list != NULL) - _vcd_list_free(obj->offset_x_list, true); + _cdio_list_free(obj->offset_x_list, true); free(obj->seg_sizes); free(obj->lot); free(obj->lot_x); if (obj->psd_x) free(obj->psd_x); + if (obj->psd) free(obj->psd); if (obj->scandata_buf) free(obj->scandata_buf); free(obj->tracks_buf); free(obj->search_buf); diff --git a/src/input/vcd/libvcd/info_private.c b/src/input/vcd/libvcd/info_private.c index bf86d9b89..9f89a3dcb 100644 --- a/src/input/vcd/libvcd/info_private.c +++ b/src/input/vcd/libvcd/info_private.c @@ -1,5 +1,5 @@ /* - $Id: info_private.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: info_private.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $ Copyright (C) 2003 Rocky Bernstein <rocky@panix.com> @@ -47,6 +47,7 @@ #endif #include <cdio/cdio.h> +#include <cdio/bytesex.h> #include <cdio/util.h> #include <libvcd/types.h> @@ -56,12 +57,11 @@ /* Private headers */ #include "vcd_assert.h" -#include "bytesex.h" #include "data_structures.h" #include "info_private.h" #include "pbc.h" -static const char _rcsid[] = "$Id: info_private.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: info_private.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $"; /* This fills in unassigned LIDs in the offset table. Due to @@ -75,25 +75,25 @@ vcdinf_update_offset_list(struct _vcdinf_pbc_ctx *obj, bool extended) { if (NULL==obj) return; { - VcdListNode *node; - VcdList *unused_lids = _vcd_list_new(); - VcdListNode *next_unused_node = _vcd_list_begin(unused_lids); + CdioListNode *node; + CdioList *unused_lids = _cdio_list_new(); + CdioListNode *next_unused_node = _cdio_list_begin(unused_lids); unsigned int last_lid=0; - VcdList *offset_list = extended ? obj->offset_x_list : obj->offset_list; + CdioList *offset_list = extended ? obj->offset_x_list : obj->offset_list; lid_t max_seen_lid=0; - _VCD_LIST_FOREACH (node, offset_list) + _CDIO_LIST_FOREACH (node, offset_list) { - vcdinfo_offset_t *ofs = _vcd_list_node_data (node); + vcdinfo_offset_t *ofs = _cdio_list_node_data (node); if (!ofs->lid) { /* We have a customer! Assign a LID from the free pool or take one from the end if no skipped LIDs. */ - VcdListNode *node=_vcd_list_node_next(next_unused_node); + CdioListNode *node=_cdio_list_node_next(next_unused_node); if (node != NULL) { - lid_t *next_unused_lid=_vcd_list_node_data(node); + lid_t *next_unused_lid=_cdio_list_node_data(node); ofs->lid = *next_unused_lid; next_unused_node=node; } else { @@ -106,12 +106,12 @@ vcdinf_update_offset_list(struct _vcdinf_pbc_ctx *obj, bool extended) while (last_lid != ofs->lid ) { lid_t * lid=_vcd_malloc (sizeof(lid_t)); *lid = last_lid; - _vcd_list_append(unused_lids, lid); + _cdio_list_append(unused_lids, lid); } if (last_lid > max_seen_lid) max_seen_lid=last_lid; } } - _vcd_list_free(unused_lids, true); + _cdio_list_free(unused_lids, true); } } @@ -124,7 +124,7 @@ vcdinf_update_offset_list(struct _vcdinf_pbc_ctx *obj, bool extended) bool vcdinf_visit_lot (struct _vcdinf_pbc_ctx *obj) { - const LotVcd *lot = obj->extended ? obj->lot_x : obj->lot; + const LotVcd_t *lot = obj->extended ? obj->lot_x : obj->lot; unsigned int n, tmp; bool ret=true; @@ -137,7 +137,7 @@ vcdinf_visit_lot (struct _vcdinf_pbc_ctx *obj) ret &= vcdinf_visit_pbc (obj, n + 1, tmp, true); _vcd_list_sort (obj->extended ? obj->offset_x_list : obj->offset_list, - (_vcd_list_cmp_func) vcdinf_lid_t_cmp); + (_cdio_list_cmp_func) vcdinf_lid_t_cmp); /* Now really complete the offset table with LIDs. This routine might obviate the need for vcdinf_visit_pbc() or some of it which is @@ -156,12 +156,12 @@ bool vcdinf_visit_pbc (struct _vcdinf_pbc_ctx *obj, lid_t lid, unsigned int offset, bool in_lot) { - VcdListNode *node; + CdioListNode *node; vcdinfo_offset_t *ofs; unsigned int psd_size = obj->extended ? obj->psd_x_size : obj->psd_size; const uint8_t *psd = obj->extended ? obj->psd_x : obj->psd; unsigned int _rofs = offset * obj->offset_mult; - VcdList *offset_list; + CdioList *offset_list; bool ret=true; vcd_assert (psd_size % 8 == 0); @@ -188,19 +188,19 @@ vcdinf_visit_pbc (struct _vcdinf_pbc_ctx *obj, lid_t lid, unsigned int offset, } if (!obj->offset_list) - obj->offset_list = _vcd_list_new (); + obj->offset_list = _cdio_list_new (); if (!obj->offset_x_list) - obj->offset_x_list = _vcd_list_new (); + obj->offset_x_list = _cdio_list_new (); if (obj->extended) { offset_list = obj->offset_x_list; } else offset_list = obj->offset_list; - _VCD_LIST_FOREACH (node, offset_list) + _CDIO_LIST_FOREACH (node, offset_list) { - ofs = _vcd_list_node_data (node); + ofs = _cdio_list_node_data (node); if (offset == ofs->offset) { @@ -232,9 +232,9 @@ vcdinf_visit_pbc (struct _vcdinf_pbc_ctx *obj, lid_t lid, unsigned int offset, switch (ofs->type) { case PSD_TYPE_PLAY_LIST: - _vcd_list_append (offset_list, ofs); + _cdio_list_append (offset_list, ofs); { - const PsdPlayListDescriptor *d = (const void *) (psd + _rofs); + const PsdPlayListDescriptor_t *d = (const void *) (psd + _rofs); const lid_t lid = vcdinf_pld_get_lid(d); if (!ofs->lid) @@ -253,9 +253,9 @@ vcdinf_visit_pbc (struct _vcdinf_pbc_ctx *obj, lid_t lid, unsigned int offset, case PSD_TYPE_EXT_SELECTION_LIST: case PSD_TYPE_SELECTION_LIST: - _vcd_list_append (offset_list, ofs); + _cdio_list_append (offset_list, ofs); { - const PsdSelectionListDescriptor *d = + const PsdSelectionListDescriptor_t *d = (const void *) (psd + _rofs); int idx; @@ -283,7 +283,7 @@ vcdinf_visit_pbc (struct _vcdinf_pbc_ctx *obj, lid_t lid, unsigned int offset, break; case PSD_TYPE_END_LIST: - _vcd_list_append (offset_list, ofs); + _cdio_list_append (offset_list, ofs); break; default: @@ -299,7 +299,7 @@ vcdinf_visit_pbc (struct _vcdinf_pbc_ctx *obj, lid_t lid, unsigned int offset, entry_num in obj. VCDINFO_NULL_LBA is returned if there is no entry. */ lba_t -vcdinf_get_entry_lba(const EntriesVcd *entries, unsigned int entry_num) +vcdinf_get_entry_lba(const EntriesVcd_t *entries, unsigned int entry_num) { const msf_t *msf = vcdinf_get_entry_msf(entries, entry_num); return (msf != NULL) ? cdio_msf_to_lba(msf) : VCDINFO_NULL_LBA; @@ -310,7 +310,7 @@ vcdinf_get_entry_lba(const EntriesVcd *entries, unsigned int entry_num) The first entry number is 0. */ const msf_t * -vcdinf_get_entry_msf(const EntriesVcd *entries, unsigned int entry_num) +vcdinf_get_entry_msf(const EntriesVcd_t *entries, unsigned int entry_num) { const unsigned int entry_count = uint16_from_be (entries->entry_count); return entry_num < entry_count ? diff --git a/src/input/vcd/libvcd/info_private.h b/src/input/vcd/libvcd/info_private.h index a0152abae..d17b6680b 100644 --- a/src/input/vcd/libvcd/info_private.h +++ b/src/input/vcd/libvcd/info_private.h @@ -31,6 +31,7 @@ #endif #include <cdio/cdio.h> +#include <cdio/ds.h> #include <cdio/iso9660.h> #include <libvcd/types.h> #include <libvcd/files_private.h> @@ -46,16 +47,16 @@ extern "C" { iso9660_pvd_t pvd; - InfoVcd info; - EntriesVcd entries; + InfoVcd_t info; + EntriesVcd_t entries; - VcdList *offset_list; - VcdList *offset_x_list; + CdioList *offset_list; + CdioList *offset_x_list; uint32_t *seg_sizes; lsn_t first_segment_lsn; - LotVcd *lot; - LotVcd *lot_x; + LotVcd_t *lot; + LotVcd_t *lot_x; uint8_t *psd; uint8_t *psd_x; unsigned int psd_x_size; @@ -75,18 +76,18 @@ extern "C" { entry_num in obj. NULL is returned if there is no entry. The first entry number is 0. */ - const msf_t * vcdinf_get_entry_msf(const EntriesVcd *entries, + const msf_t * vcdinf_get_entry_msf(const EntriesVcd_t *entries, unsigned int entry_num); struct _vcdinf_pbc_ctx { unsigned int psd_size; lid_t maximum_lid; unsigned offset_mult; - VcdList *offset_x_list; - VcdList *offset_list; + CdioList *offset_x_list; + CdioList *offset_list; - LotVcd *lot; - LotVcd *lot_x; + LotVcd_t *lot; + LotVcd_t *lot_x; uint8_t *psd; uint8_t *psd_x; unsigned int psd_x_size; diff --git a/src/input/vcd/libvcd/libvcd/inf.h b/src/input/vcd/libvcd/libvcd/inf.h index 8da69264a..fcd9098e2 100644 --- a/src/input/vcd/libvcd/libvcd/inf.h +++ b/src/input/vcd/libvcd/libvcd/inf.h @@ -1,7 +1,7 @@ /*! \file inf.h - Copyright (C) 2002,2003 Rocky Bernstein <rocky@panix.com> + Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com> \verbatim This program is free software; you can redistribute it and/or modify @@ -29,7 +29,6 @@ #ifndef _VCD_INF_H #define _VCD_INF_H -#include <cdio/iso9660.h> #include <libvcd/info.h> const char * vcdinf_area_str (const struct psd_area_t *_area); @@ -37,31 +36,25 @@ /*! Return a string containing the VCD album id. */ - const char * vcdinf_get_album_id(const InfoVcd *info); - - /*! - Return the VCD application ID. - NULL is returned if there is some problem in getting this. - */ - const char * vcdinf_get_application_id(const iso9660_pvd_t *pvd); + const char * vcdinf_get_album_id(const InfoVcd_t *info); /*! Get autowait time value for PsdPlayListDescriptor *d. Time is in seconds unless it is -1 (unlimited). */ - int vcdinf_get_autowait_time (const PsdPlayListDescriptor *d); + int vcdinf_get_autowait_time (const PsdPlayListDescriptor_t *d); /*! Return the base selection number. VCD_INVALID_BSN is returned if there is an error. */ - unsigned int vcdinf_get_bsn(const PsdSelectionListDescriptor *psd); + unsigned int vcdinf_get_bsn(const PsdSelectionListDescriptor_t *psd); /*! Return the starting LBA (logical block address) for sequence entry_num in obj. VCDINFO_NULL_LBA is returned if there is no entry. The first entry number is 0. */ - lba_t vcdinf_get_entry_lba(const EntriesVcd *entries, + lba_t vcdinf_get_entry_lba(const EntriesVcd_t *entries, unsigned int entry_num); const char * vcdinf_get_format_version_str (vcd_type_t vcd_type); @@ -69,118 +62,85 @@ /*! Return loop count. 0 is infinite loop. */ - uint16_t vcdinf_get_loop_count (const PsdSelectionListDescriptor *psd); + uint16_t vcdinf_get_loop_count (const PsdSelectionListDescriptor_t *psd); /*! Return LOT offset */ - uint16_t vcdinf_get_lot_offset (const LotVcd *lot, unsigned int n); - - /*! - Return a string containing the VCD preparer id with trailing - blanks removed. - NULL is returned if there is some problem in getting this. - */ - const char * vcdinf_get_preparer_id(const iso9660_pvd_t *pvd); + uint16_t vcdinf_get_lot_offset (const LotVcd_t *lot, unsigned int n); /*! Return number of bytes in PSD. */ - uint32_t vcdinf_get_psd_size (const InfoVcd *info); + uint32_t vcdinf_get_psd_size (const InfoVcd_t *info); /*! - Return a string containing the VCD publisher id with trailing - blanks removed. - NULL is returned if there is some problem in getting this. - */ - const char * vcdinf_get_publisher_id(const iso9660_pvd_t *pvd); - - /*! Return the number of segments in the VCD. */ - unsigned int vcdinf_get_num_entries(const EntriesVcd *entries); + unsigned int vcdinf_get_num_entries(const EntriesVcd_t *entries); /*! Return number of LIDs. */ - lid_t vcdinf_get_num_LIDs (const InfoVcd *info); + lid_t vcdinf_get_num_LIDs (const InfoVcd_t *info); /*! Return the number of segments in the VCD. */ - segnum_t vcdinf_get_num_segments(const InfoVcd *info); + segnum_t vcdinf_get_num_segments(const InfoVcd_t *info); /*! Return the number of menu selections for selection-list descriptor d. */ - unsigned int vcdinf_get_num_selections(const PsdSelectionListDescriptor *d); + unsigned int vcdinf_get_num_selections(const PsdSelectionListDescriptor_t *d); /*! Get play-time value for PsdPlayListDescriptor *d. Time is in 1/15-second units. */ - uint16_t vcdinf_get_play_time (const PsdPlayListDescriptor *d); - - /*! - Return a string containing the VCD system id with trailing - blanks removed. - NULL is returned if there is some problem in getting this. - */ - const char * vcdinf_get_system_id(const iso9660_pvd_t *pvd); + uint16_t vcdinf_get_play_time (const PsdPlayListDescriptor_t *d); /*! Get timeout offset for PsdPlayListDescriptor *d. Return VCDINFO_INVALID_OFFSET if d is NULL; Time is in seconds unless it is -1 (unlimited). */ - uint16_t vcdinf_get_timeout_offset (const PsdSelectionListDescriptor *d); + uint16_t vcdinf_get_timeout_offset (const PsdSelectionListDescriptor_t *d); /*! Get timeout wait value for PsdPlayListDescriptor *d. Time is in seconds unless it is -1 (unlimited). */ - int vcdinf_get_timeout_time (const PsdSelectionListDescriptor *d); + int vcdinf_get_timeout_time (const PsdSelectionListDescriptor_t *d); /*! Return the track number for entry n in obj. The first track starts at 1. */ - track_t vcdinf_get_track(const EntriesVcd *entries, + track_t vcdinf_get_track(const EntriesVcd_t *entries, const unsigned int entry_num); /*! Return the VCD volume num - the number of the CD in the collection. This is a number between 1 and the volume count. */ - unsigned int vcdinf_get_volume_num(const InfoVcd *info); + unsigned int vcdinf_get_volume_num(const InfoVcd_t *info); /*! Return the VCD volume count - the number of CD's in the collection. */ - unsigned int vcdinf_get_volume_count(const InfoVcd *info); - - /*! - Return the VCD ID. - NULL is returned if there is some problem in getting this. - */ - const char * vcdinf_get_volume_id(const iso9660_pvd_t *pvd); - - /*! - Return the VCD volumeset ID. - NULL is returned if there is some problem in getting this. - */ - const char * vcdinf_get_volumeset_id(const iso9660_pvd_t *pvd); + unsigned int vcdinf_get_volume_count(const InfoVcd_t *info); /*! Get wait time value for PsdPlayListDescriptor *d. Time is in seconds unless it is -1 (unlimited). */ - int vcdinf_get_wait_time (const PsdPlayListDescriptor *d); + int vcdinf_get_wait_time (const PsdPlayListDescriptor_t *d); /*! Return true if loop has a jump delay */ - bool vcdinf_has_jump_delay (const PsdSelectionListDescriptor *psd); + bool vcdinf_has_jump_delay (const PsdSelectionListDescriptor_t *psd); /*! Comparison routine used in sorting. We compare LIDs and if those are @@ -197,18 +157,18 @@ \return VCDINFO_INVALID_OFFSET is returned on error or if pld has no "next" entry or pld is NULL. Otherwise the LID offset is returned. */ - uint16_t vcdinf_pld_get_next_offset(const PsdPlayListDescriptor *pld); + uint16_t vcdinf_pld_get_next_offset(const PsdPlayListDescriptor_t *pld); /*! Get the LID from a given play-list descriptor. VCDINFO_REJECTED_MASK is returned on error or pld is NULL. */ - uint16_t vcdinf_pld_get_lid(const PsdPlayListDescriptor *pld); + uint16_t vcdinf_pld_get_lid(const PsdPlayListDescriptor_t *pld); /*! Return the playlist item i in d. */ - uint16_t vcdinf_pld_get_play_item(const PsdPlayListDescriptor *pld, + uint16_t vcdinf_pld_get_play_item(const PsdPlayListDescriptor_t *pld, unsigned int i); /** @@ -217,7 +177,7 @@ \return VCDINFO_INVALID_OFFSET is returned on error or if pld has no "prev" entry or pld is NULL. Otherwise the LID offset is returned. */ - uint16_t vcdinf_pld_get_prev_offset(const PsdPlayListDescriptor *pld); + uint16_t vcdinf_pld_get_prev_offset(const PsdPlayListDescriptor_t *pld); /** \fn vcdinf_pld_get_return_offset(const PsdPlayListDescriptor *pld); @@ -225,12 +185,12 @@ \return VCDINFO_INVALID_OFFSET is returned on error or if pld has no "return" entry or pld is NULL. Otherwise the LID offset is returned. */ - uint16_t vcdinf_pld_get_return_offset(const PsdPlayListDescriptor *pld); + uint16_t vcdinf_pld_get_return_offset(const PsdPlayListDescriptor_t *pld); /*! Return number of items in LIDs. Return 0 if error or not found. */ - int vcdinf_pld_get_noi (const PsdPlayListDescriptor *pld); + int vcdinf_pld_get_noi (const PsdPlayListDescriptor_t *pld); /** * \fn vcdinfo_psd_get_default_offset(const PsdSelectionListDescriptor *psd); @@ -238,26 +198,26 @@ * \return VCDINFO_INVALID_OFFSET is returned on error or if psd is * NULL. Otherwise the LID offset is returned. */ - uint16_t vcdinf_psd_get_default_offset(const PsdSelectionListDescriptor *psd); + uint16_t vcdinf_psd_get_default_offset(const PsdSelectionListDescriptor_t *psd); /*! Get the item id for a given selection-list descriptor. VCDINFO_REJECTED_MASK is returned on error or if psd is NULL. */ - uint16_t vcdinf_psd_get_itemid(const PsdSelectionListDescriptor *psd); + uint16_t vcdinf_psd_get_itemid(const PsdSelectionListDescriptor_t *psd); /*! Get the LID from a given selection-list descriptor. VCDINFO_REJECTED_MASK is returned on error or psd is NULL. */ - uint16_t vcdinf_psd_get_lid(const PsdSelectionListDescriptor *psd); + uint16_t vcdinf_psd_get_lid(const PsdSelectionListDescriptor_t *psd); /*! Get the LID rejected status for a given selection-list descriptor. true is also returned d is NULL. */ bool - vcdinf_psd_get_lid_rejected(const PsdSelectionListDescriptor *psd); + vcdinf_psd_get_lid_rejected(const PsdSelectionListDescriptor_t *psd); /** \fn vcdinf_psd_get_next_offset(const PsdSelectionListDescriptor *psd); @@ -265,7 +225,7 @@ \return VCDINFO_INVALID_OFFSET is returned on error or if psd has no "next" entry or psd is NULL. Otherwise the LID offset is returned. */ - lid_t vcdinf_psd_get_next_offset(const PsdSelectionListDescriptor *psd); + lid_t vcdinf_psd_get_next_offset(const PsdSelectionListDescriptor_t *psd); /*! \brief Get offset entry_num for a given PSD selector descriptor. @@ -274,7 +234,7 @@ \return VCDINFO_INVALID_OFFSET is returned if d on error or d is NULL. Otherwise the LID offset is returned. */ - uint16_t vcdinf_psd_get_offset(const PsdSelectionListDescriptor *d, + uint16_t vcdinf_psd_get_offset(const PsdSelectionListDescriptor_t *d, unsigned int entry_num); /** \fn vcdinf_psd_get_prev_offset(const PsdPlayListDescriptor *psd); @@ -283,7 +243,7 @@ "prev" entry or psd is NULL. Otherwise the LID offset is returned. */ - uint16_t vcdinf_psd_get_prev_offset(const PsdSelectionListDescriptor *psd); + uint16_t vcdinf_psd_get_prev_offset(const PsdSelectionListDescriptor_t *psd); /** * \fn vcdinf_psd_get_return_offset(const PsdSelectionListDescriptor *psd); @@ -291,7 +251,7 @@ \return VCDINFO_INVALID_OFFSET is returned on error or if psd has no "return" entry or psd is NULL. Otherwise the LID offset is returned. */ - uint16_t vcdinf_psd_get_return_offset(const PsdSelectionListDescriptor *psd); + uint16_t vcdinf_psd_get_return_offset(const PsdSelectionListDescriptor_t *psd); #ifdef __cplusplus } diff --git a/src/input/vcd/libvcd/libvcd/info.h b/src/input/vcd/libvcd/libvcd/info.h index e90253bc7..82aa78272 100644 --- a/src/input/vcd/libvcd/libvcd/info.h +++ b/src/input/vcd/libvcd/libvcd/info.h @@ -1,7 +1,7 @@ /*! \file info.h - Copyright (C) 2002,2003 Rocky Bernstein <rocky@panix.com> + Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com> \verbatim This program is free software; you can redistribute it and/or modify @@ -29,9 +29,11 @@ #ifndef _VCD_INFO_H #define _VCD_INFO_H +#include <libvcd/version.h> #include <libvcd/types.h> #include <libvcd/files.h> #include <cdio/cdio.h> +#include <cdio/ds.h> #ifdef __cplusplus extern "C" { @@ -41,12 +43,13 @@ extern "C" { /*! \def Max # characters in an album id. */ #define MAX_ALBUM_LEN 16 -#define MAX_APPLICATION_ID 128 -#define MAX_PREPARER_ID 128 -#define MAX_PUBLISHER_ID 128 -#define MAX_SYSTEM_ID 32 -#define MAX_VOLUME_ID 32 -#define MAX_VOLUMESET_ID 128 + +/*! \def Max # of selections allowed in a PBC selection list. */ +#define MAX_PBC_SELECTIONS 99 + +#define MIN_ENCODED_TRACK_NUM 100 +#define MIN_ENCODED_SEGMENT_NUM 1000 +#define MAX_ENCODED_SEGMENT_NUM 2979 /*! Invalid LBA, Note: VCD player uses the fact that this is a very high @@ -189,11 +192,14 @@ extern "C" { /* Only one of pld or psd is used below. Not all C compiler accept the anonymous unions commented out below. */ /* union { */ - PsdPlayListDescriptor *pld; - PsdSelectionListDescriptor *psd; + PsdPlayListDescriptor_t *pld; + PsdSelectionListDescriptor_t *psd; /* }; */ - } PsdListDescriptor; + } PsdListDescriptor_t; + + /* For backwards compatibility. Don't use PsdListDescriptor. */ +#define PsdListDescriptor PsdListDescriptor_t /*! Return the number of audio channels implied by "audio_type". @@ -245,8 +251,8 @@ extern "C" { Return the VCD application ID. NULL is returned if there is some problem in getting this. */ - const char * - vcdinfo_get_application_id(const vcdinfo_obj_t *obj); + char * + vcdinfo_get_application_id(vcdinfo_obj_t *obj); /*! Return a pointer to the cdio structure for the CD image opened or @@ -324,9 +330,9 @@ extern "C" { const char * vcdinfo_get_format_version_str (const vcdinfo_obj_t *obj); - EntriesVcd * vcdinfo_get_entriesVcd (vcdinfo_obj_t *obj); + EntriesVcd_t * vcdinfo_get_entriesVcd (vcdinfo_obj_t *obj); - InfoVcd * vcdinfo_get_infoVcd (vcdinfo_obj_t *obj); + InfoVcd_t * vcdinfo_get_infoVcd (vcdinfo_obj_t *obj); /*! \brief Get default or multi-default LID. @@ -345,7 +351,7 @@ extern "C" { */ lid_t vcdinfo_get_multi_default_lid(const vcdinfo_obj_t *obj, lid_t lid, - unsigned int selection); + lsn_t lsn); /*! \brief Get default or multi-default LID offset. @@ -377,13 +383,13 @@ extern "C" { /*! Get the LOT pointer. */ - LotVcd * + LotVcd_t * vcdinfo_get_lot(const vcdinfo_obj_t *obj); /*! Get the extended LOT pointer. */ - LotVcd * + LotVcd_t * vcdinfo_get_lot_x(const vcdinfo_obj_t *obj); /*! @@ -426,12 +432,12 @@ extern "C" { /*! Get the VCD info list. */ - VcdList *vcdinfo_get_offset_list(const vcdinfo_obj_t *obj); + CdioList *vcdinfo_get_offset_list(const vcdinfo_obj_t *obj); /*! Get the VCD info extended offset list. */ - VcdList *vcdinfo_get_offset_x_list(const vcdinfo_obj_t *obj); + CdioList *vcdinfo_get_offset_x_list(const vcdinfo_obj_t *obj); /*! Get the VCD info offset multiplier. @@ -726,9 +732,14 @@ extern "C" { Get the PSD Selection List Descriptor for a given lid. False is returned if not found. */ - bool vcdinfo_lid_get_pxd(const vcdinfo_obj_t *obj, PsdListDescriptor *pxd, + bool vcdinfo_lid_get_pxd(const vcdinfo_obj_t *obj, PsdListDescriptor_t *pxd, uint16_t lid); + /*! Return the entry number closest and before the given LSN. + */ + unsigned int + vcdinfo_lsn_get_entry(const vcdinfo_obj_t *obj, lsn_t lsn); + /*! Convert minutes, seconds and frame (MSF components) into a logical block address (or LBA). @@ -789,6 +800,11 @@ extern "C" { */ const char * vcdinfo_strip_trail (const char str[], size_t n); + /*! Return the entry number for the given track. + */ + unsigned int + vcdinfo_track_get_entry(const vcdinfo_obj_t *obj, track_t track); + /*! Initialize the vcdinfo structure "obj". Should be done before other routines using obj are called. diff --git a/src/input/vcd/libvcd/libvcd/types.h b/src/input/vcd/libvcd/libvcd/types.h index bde56e3c7..56a07d447 100644 --- a/src/input/vcd/libvcd/libvcd/types.h +++ b/src/input/vcd/libvcd/libvcd/types.h @@ -1,7 +1,7 @@ /* - $Id: types.h,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: types.h,v 1.3 2005/01/01 02:43:59 rockyb Exp $ - Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> + Copyright (C) 2000, 2004 Herbert Valerio Riedel <hvr@gnu.org> 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 @@ -34,13 +34,13 @@ extern "C" { typedef struct _VcdListNode VcdListNode; /* Defined fully in files_private.h */ - typedef struct _InfoVcd_tag InfoVcd; - typedef struct _EntriesVcd_tag EntriesVcd; - typedef struct _LotVcd_tag LotVcd; - - typedef struct _PsdPlayListDescriptor_tag PsdPlayListDescriptor; - typedef struct _PsdSelectionListDescriptor_tag PsdSelectionListDescriptor; + typedef struct _InfoVcd_tag InfoVcd_t; + typedef struct _EntriesVcd_tag EntriesVcd_t; + typedef struct _LotVcd_tag LotVcd_t; + typedef struct _PsdPlayListDescriptor_tag PsdPlayListDescriptor_t; + typedef struct _PsdSelectionListDescriptor_tag PsdSelectionListDescriptor_t; + /* Overall data structure representing a VideoCD object. Defined fully in info_private.h. */ diff --git a/src/input/vcd/libvcd/libvcd/version.h b/src/input/vcd/libvcd/libvcd/version.h index 054519ece..d71374724 100644 --- a/src/input/vcd/libvcd/libvcd/version.h +++ b/src/input/vcd/libvcd/libvcd/version.h @@ -1 +1 @@ -#define LIBVCD_VERSION "0.7.20" +#define LIBVCD_VERSION "0.7.20a" diff --git a/src/input/vcd/libvcd/mpeg.h b/src/input/vcd/libvcd/mpeg.h index d57c1a36e..2d28d2aef 100644 --- a/src/input/vcd/libvcd/mpeg.h +++ b/src/input/vcd/libvcd/mpeg.h @@ -1,5 +1,5 @@ /* - $Id: mpeg.h,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: mpeg.h,v 1.3 2005/01/01 02:43:59 rockyb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> @@ -103,7 +103,7 @@ typedef struct { unsigned vbvsize; bool constrained_flag; - VcdList *aps_list; /* filled up by vcd_mpeg_source */ + CdioList *aps_list; /* filled up by vcd_mpeg_source */ double last_aps_pts; /* temp, see ->packet */ } shdr[3]; diff --git a/src/input/vcd/libvcd/mpeg_stream.c b/src/input/vcd/libvcd/mpeg_stream.c index 4fcc1fa8b..e5466766a 100644 --- a/src/input/vcd/libvcd/mpeg_stream.c +++ b/src/input/vcd/libvcd/mpeg_stream.c @@ -1,7 +1,7 @@ /* - $Id: mpeg_stream.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: mpeg_stream.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $ - Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> + Copyright (C) 2000, 2004 Herbert Valerio Riedel <hvr@gnu.org> 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 @@ -27,18 +27,18 @@ #include <stdlib.h> #include <cdio/cdio.h> +#include <cdio/bytesex.h> #include <libvcd/logging.h> /* Private headers */ #include "vcd_assert.h" #include "mpeg_stream.h" -#include "bytesex.h" #include "data_structures.h" #include "mpeg.h" #include "util.h" -static const char _rcsid[] = "$Id: mpeg_stream.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: mpeg_stream.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $"; struct _VcdMpegSource { @@ -83,7 +83,7 @@ vcd_mpeg_source_destroy (VcdMpegSource *obj, bool destroy_file_obj) for (i = 0; i < 3; i++) if (obj->info.shdr[i].aps_list) - _vcd_list_free (obj->info.shdr[i].aps_list, true); + _cdio_list_free (obj->info.shdr[i].aps_list, true); free (obj); } @@ -117,7 +117,7 @@ vcd_mpeg_source_scan (VcdMpegSource *obj, bool strict_aps, bool fix_scan_info, unsigned padbytes = 0; unsigned padpackets = 0; VcdMpegStreamCtx state; - VcdListNode *n; + CdioListNode *n; vcd_mpeg_prog_info_t _progress = { 0, }; vcd_assert (obj != NULL); @@ -194,9 +194,9 @@ vcd_mpeg_source_scan (VcdMpegSource *obj, bool strict_aps, bool fix_scan_info, _data->timestamp = state.packet.aps_pts; if (!state.stream.shdr[state.packet.aps_idx].aps_list) - state.stream.shdr[state.packet.aps_idx].aps_list = _vcd_list_new (); + state.stream.shdr[state.packet.aps_idx].aps_list = _cdio_list_new (); - _vcd_list_append (state.stream.shdr[state.packet.aps_idx].aps_list, _data); + _cdio_list_append (state.stream.shdr[state.packet.aps_idx].aps_list, _data); } break; @@ -251,9 +251,9 @@ vcd_mpeg_source_scan (VcdMpegSource *obj, bool strict_aps, bool fix_scan_info, for (i = 0; i < 3; i++) if (obj->info.shdr[i].aps_list) - _VCD_LIST_FOREACH (n, obj->info.shdr[i].aps_list) + _CDIO_LIST_FOREACH (n, obj->info.shdr[i].aps_list) { - struct aps_data *_data = _vcd_list_node_data (n); + struct aps_data *_data = _cdio_list_node_data (n); _data->timestamp -= obj->info.min_pts; } @@ -268,18 +268,18 @@ vcd_mpeg_source_scan (VcdMpegSource *obj, bool strict_aps, bool fix_scan_info, } static double -_approx_pts (VcdList *aps_list, uint32_t packet_no) +_approx_pts (CdioList *aps_list, uint32_t packet_no) { double retval = 0; - VcdListNode *node; + CdioListNode *node; struct aps_data *_laps = NULL; double last_pts_ratio = 0; - _VCD_LIST_FOREACH (node, aps_list) + _CDIO_LIST_FOREACH (node, aps_list) { - struct aps_data *_aps = _vcd_list_node_data (node); + struct aps_data *_aps = _cdio_list_node_data (node); if (_laps) { @@ -322,14 +322,14 @@ _set_scan_msf (msf_t *_msf, long lsn) static void _fix_scan_info (struct vcd_mpeg_scan_data_t *scan_data_ptr, - unsigned packet_no, double pts, VcdList *aps_list) + unsigned packet_no, double pts, CdioList *aps_list) { - VcdListNode *node; + CdioListNode *node; long _next = -1, _prev = -1, _forw = -1, _back = -1; - _VCD_LIST_FOREACH (node, aps_list) + _CDIO_LIST_FOREACH (node, aps_list) { - struct aps_data *_aps = _vcd_list_node_data (node); + struct aps_data *_aps = _cdio_list_node_data (node); if (_aps->packet_no == packet_no) continue; diff --git a/src/input/vcd/libvcd/obj.h b/src/input/vcd/libvcd/obj.h index 55ed51462..d6849a3ab 100644 --- a/src/input/vcd/libvcd/obj.h +++ b/src/input/vcd/libvcd/obj.h @@ -1,5 +1,5 @@ /* - $Id: obj.h,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: obj.h,v 1.3 2005/01/01 02:43:59 rockyb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> @@ -48,10 +48,10 @@ typedef struct { char *id; const struct vcd_mpeg_stream_info *info; - VcdList *pause_list; /* pause_t */ + CdioList *pause_list; /* pause_t */ char *default_entry_id; - VcdList *entry_list; /* entry_t */ + CdioList *entry_list; /* entry_t */ /* pbc ref check */ bool referenced; @@ -69,7 +69,7 @@ typedef struct { char *id; const struct vcd_mpeg_stream_info *info; - VcdList *pause_list; /* pause_t */ + CdioList *pause_list; /* pause_t */ /* pbc ref check */ bool referenced; @@ -128,25 +128,25 @@ struct _VcdObj { /* input */ unsigned mpeg_segment_start_extent; - VcdList *mpeg_segment_list; /* mpeg_segment_t */ + CdioList *mpeg_segment_list; /* mpeg_segment_t */ - VcdList *mpeg_sequence_list; /* mpeg_sequence_t */ + CdioList *mpeg_sequence_list; /* mpeg_sequence_t */ unsigned relative_end_extent; /* last mpeg sequence track end extent */ /* PBC */ - VcdList *pbc_list; /* pbc_t */ + CdioList *pbc_list; /* pbc_t */ unsigned psd_size; unsigned psdx_size; /* custom files */ unsigned ext_file_start_extent; unsigned custom_file_start_extent; - VcdList *custom_file_list; /* custom_file_t */ - VcdList *custom_dir_list; /* char */ + CdioList *custom_file_list; /* custom_file_t */ + CdioList *custom_dir_list; /* char */ /* dictionary */ - VcdList *buffer_dict_list; + CdioList *buffer_dict_list; /* aggregates */ VcdSalloc *iso_bitmap; diff --git a/src/input/vcd/libvcd/pbc.c b/src/input/vcd/libvcd/pbc.c index b9172b41b..1b4f1a6c1 100644 --- a/src/input/vcd/libvcd/pbc.c +++ b/src/input/vcd/libvcd/pbc.c @@ -1,7 +1,7 @@ /* - $Id: pbc.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: pbc.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $ - Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> + Copyright (C) 2000, 2004 Herbert Valerio Riedel <hvr@gnu.org> 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 @@ -27,23 +27,24 @@ #include <math.h> #include <cdio/cdio.h> +#include <cdio/bytesex.h> /* Public headers */ #include <libvcd/logging.h> #include <libvcd/files.h> #include <libvcd/types.h> +#include <libvcd/info.h> /* FIXME! Make this really private. */ #include <libvcd/files_private.h> /* Private headers */ #include "vcd_assert.h" -#include "bytesex.h" #include "obj.h" #include "pbc.h" #include "util.h" -static const char _rcsid[] = "$Id: pbc.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: pbc.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $"; static uint8_t _wtime (int seconds) @@ -74,11 +75,11 @@ _wtime (int seconds) static pbc_t * _vcd_pbc_byid(const VcdObj *obj, const char item_id[]) { - VcdListNode *node; + CdioListNode *node; - _VCD_LIST_FOREACH (node, obj->pbc_list) + _CDIO_LIST_FOREACH (node, obj->pbc_list) { - pbc_t *_pbc = _vcd_list_node_data (node); + pbc_t *_pbc = _cdio_list_node_data (node); if (_pbc->id && !strcmp (item_id, _pbc->id)) return _pbc; @@ -91,12 +92,12 @@ _vcd_pbc_byid(const VcdObj *obj, const char item_id[]) unsigned _vcd_pbc_lid_lookup (const VcdObj *obj, const char item_id[]) { - VcdListNode *node; + CdioListNode *node; unsigned n = 1; - _VCD_LIST_FOREACH (node, obj->pbc_list) + _CDIO_LIST_FOREACH (node, obj->pbc_list) { - pbc_t *_pbc = _vcd_list_node_data (node); + pbc_t *_pbc = _cdio_list_node_data (node); vcd_assert (n < 0x8000); @@ -143,11 +144,11 @@ _vcd_pbc_lookup (const VcdObj *obj, const char item_id[]) { if (id < 2) return ITEM_TYPE_NOTFOUND; - else if (id < 100) + else if (id < MIN_ENCODED_TRACK_NUM) return ITEM_TYPE_TRACK; else if (id < 600) return ITEM_TYPE_ENTRY; - else if (id < 2980) + else if (id <= MAX_ENCODED_SEGMENT_NUM) return ITEM_TYPE_SEGMENT; else vcd_assert_not_reached (); @@ -162,7 +163,7 @@ uint16_t _vcd_pbc_pin_lookup (const VcdObj *obj, const char item_id[]) { int n; - VcdListNode *node; + CdioListNode *node; if (!item_id) return 0; @@ -170,9 +171,9 @@ _vcd_pbc_pin_lookup (const VcdObj *obj, const char item_id[]) /* check sequence items */ n = 0; - _VCD_LIST_FOREACH (node, obj->mpeg_sequence_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_sequence_list) { - mpeg_sequence_t *_sequence = _vcd_list_node_data (node); + mpeg_sequence_t *_sequence = _cdio_list_node_data (node); vcd_assert (n < 98); @@ -185,10 +186,10 @@ _vcd_pbc_pin_lookup (const VcdObj *obj, const char item_id[]) /* check entry points */ n = 0; - _VCD_LIST_FOREACH (node, obj->mpeg_sequence_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_sequence_list) { - mpeg_sequence_t *_sequence = _vcd_list_node_data (node); - VcdListNode *node2; + mpeg_sequence_t *_sequence = _cdio_list_node_data (node); + CdioListNode *node2; /* default entry point */ @@ -199,9 +200,9 @@ _vcd_pbc_pin_lookup (const VcdObj *obj, const char item_id[]) /* additional entry points */ - _VCD_LIST_FOREACH (node2, _sequence->entry_list) + _CDIO_LIST_FOREACH (node2, _sequence->entry_list) { - entry_t *_entry = _vcd_list_node_data (node2); + entry_t *_entry = _cdio_list_node_data (node2); vcd_assert (n < 500); @@ -215,14 +216,14 @@ _vcd_pbc_pin_lookup (const VcdObj *obj, const char item_id[]) /* check sequence items */ n = 0; - _VCD_LIST_FOREACH (node, obj->mpeg_segment_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_segment_list) { - mpeg_segment_t *_segment = _vcd_list_node_data (node); + mpeg_segment_t *_segment = _cdio_list_node_data (node); vcd_assert (n < 1980); if (_segment->id && !strcmp (item_id, _segment->id)) - return n + 1000; + return n + MIN_ENCODED_SEGMENT_NUM; n += _segment->segment_count; } @@ -236,7 +237,7 @@ _vcd_pbc_available (const VcdObj *obj) vcd_assert (obj != NULL); vcd_assert (obj->pbc_list != NULL); - if (!_vcd_list_length (obj->pbc_list)) + if (!_cdio_list_length (obj->pbc_list)) return false; if (!_vcd_obj_has_cap_p (obj, _CAP_PBC)) @@ -254,7 +255,7 @@ _vcd_pbc_max_lid (const VcdObj *obj) uint16_t retval = 0; if (_vcd_pbc_available (obj)) - retval = _vcd_list_length (obj->pbc_list); + retval = _cdio_list_length (obj->pbc_list); return retval; } @@ -272,14 +273,14 @@ _vcd_pbc_node_length (const VcdObj *obj, const pbc_t *_pbc, bool extended) int n; case PBC_PLAYLIST: - n = _vcd_list_length (_pbc->item_id_list); + n = _cdio_list_length (_pbc->item_id_list); retval = __cd_offsetof (_PsdPlayListDescriptor, itemid[n]); break; case PBC_SELECTION: - n = _vcd_list_length (_pbc->select_id_list); + n = _cdio_list_length (_pbc->select_id_list); - retval = __cd_offsetof (PsdSelectionListDescriptor, ofs[n]); + retval = __cd_offsetof (PsdSelectionListDescriptor_t, ofs[n]); if (extended || _vcd_obj_has_cap_p (obj, _CAP_4C_SVCD)) retval += __cd_offsetof (PsdSelectionListDescriptorExtended, area[n]); @@ -300,7 +301,7 @@ _vcd_pbc_node_length (const VcdObj *obj, const pbc_t *_pbc, bool extended) static uint16_t _lookup_psd_offset (const VcdObj *obj, const char item_id[], bool extended) { - VcdListNode *node; + CdioListNode *node; if (extended) vcd_assert (_vcd_obj_has_cap_p (obj, _CAP_PBC_X)); @@ -309,9 +310,9 @@ _lookup_psd_offset (const VcdObj *obj, const char item_id[], bool extended) if (!item_id) return PSD_OFS_DISABLED; - _VCD_LIST_FOREACH (node, obj->pbc_list) + _CDIO_LIST_FOREACH (node, obj->pbc_list) { - pbc_t *_pbc = _vcd_list_node_data (node); + pbc_t *_pbc = _cdio_list_node_data (node); if (!_pbc->id || strcmp (item_id, _pbc->id)) continue; @@ -367,15 +368,15 @@ _vcd_pbc_mark_id (const VcdObj *obj, const char _id[]) { case PBC_PLAYLIST: { - VcdListNode *node; + CdioListNode *node; _vcd_pbc_mark_id (obj, _pbc->prev_id); _vcd_pbc_mark_id (obj, _pbc->next_id); _vcd_pbc_mark_id (obj, _pbc->retn_id); - _VCD_LIST_FOREACH (node, _pbc->item_id_list) + _CDIO_LIST_FOREACH (node, _pbc->item_id_list) { - const char *_id = _vcd_list_node_data (node); + const char *_id = _cdio_list_node_data (node); _vcd_pin_mark_id (obj, _id); } @@ -384,7 +385,7 @@ _vcd_pbc_mark_id (const VcdObj *obj, const char _id[]) case PBC_SELECTION: { - VcdListNode *node; + CdioListNode *node; _vcd_pbc_mark_id (obj, _pbc->prev_id); _vcd_pbc_mark_id (obj, _pbc->next_id); @@ -397,9 +398,9 @@ _vcd_pbc_mark_id (const VcdObj *obj, const char _id[]) _vcd_pin_mark_id (obj, _pbc->item_id); - _VCD_LIST_FOREACH (node, _pbc->select_id_list) + _CDIO_LIST_FOREACH (node, _pbc->select_id_list) { - const char *_id = _vcd_list_node_data (node); + const char *_id = _cdio_list_node_data (node); _vcd_pbc_mark_id (obj, _id); } @@ -419,36 +420,36 @@ _vcd_pbc_mark_id (const VcdObj *obj, const char _id[]) void _vcd_pbc_check_unreferenced (const VcdObj *obj) { - VcdListNode *node; + CdioListNode *node; /* clear all flags */ - _VCD_LIST_FOREACH (node, obj->pbc_list) + _CDIO_LIST_FOREACH (node, obj->pbc_list) { - pbc_t *_pbc = _vcd_list_node_data (node); + pbc_t *_pbc = _cdio_list_node_data (node); _pbc->referenced = false; } - _VCD_LIST_FOREACH (node, obj->mpeg_sequence_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_sequence_list) { - mpeg_sequence_t *_sequence = _vcd_list_node_data (node); + mpeg_sequence_t *_sequence = _cdio_list_node_data (node); _sequence->referenced = false; } - _VCD_LIST_FOREACH (node, obj->mpeg_segment_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_segment_list) { - mpeg_segment_t *_segment = _vcd_list_node_data (node); + mpeg_segment_t *_segment = _cdio_list_node_data (node); _segment->referenced = false; } /* start from non-rejected lists */ - _VCD_LIST_FOREACH (node, obj->pbc_list) + _CDIO_LIST_FOREACH (node, obj->pbc_list) { - pbc_t *_pbc = _vcd_list_node_data (node); + pbc_t *_pbc = _cdio_list_node_data (node); vcd_assert (_pbc->id != NULL); @@ -460,25 +461,25 @@ _vcd_pbc_check_unreferenced (const VcdObj *obj) /* collect flags */ - _VCD_LIST_FOREACH (node, obj->pbc_list) + _CDIO_LIST_FOREACH (node, obj->pbc_list) { - pbc_t *_pbc = _vcd_list_node_data (node); + pbc_t *_pbc = _cdio_list_node_data (node); if (!_pbc->referenced) vcd_warn ("PSD item '%s' is unreachable", _pbc->id); } - _VCD_LIST_FOREACH (node, obj->mpeg_sequence_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_sequence_list) { - mpeg_sequence_t *_sequence = _vcd_list_node_data (node); + mpeg_sequence_t *_sequence = _cdio_list_node_data (node); if (!_sequence->referenced) vcd_warn ("sequence '%s' is not reachable by PBC", _sequence->id); } - _VCD_LIST_FOREACH (node, obj->mpeg_segment_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_segment_list) { - mpeg_segment_t *_segment = _vcd_list_node_data (node); + mpeg_segment_t *_segment = _cdio_list_node_data (node); if (!_segment->referenced) vcd_warn ("segment item '%s' is unreachable", _segment->id); @@ -502,11 +503,11 @@ _vcd_pbc_node_write (const VcdObj *obj, const pbc_t *_pbc, void *buf, case PBC_PLAYLIST: { _PsdPlayListDescriptor *_md = buf; - VcdListNode *node; + CdioListNode *node; int n; _md->type = PSD_TYPE_PLAY_LIST; - _md->noi = _vcd_list_length (_pbc->item_id_list); + _md->noi = _cdio_list_length (_pbc->item_id_list); vcd_assert (_pbc->lid < 0x8000); _md->lid = uint16_to_be (_pbc->lid | (_pbc->rejected ? 0x8000 : 0)); @@ -522,9 +523,9 @@ _vcd_pbc_node_write (const VcdObj *obj, const pbc_t *_pbc, void *buf, _md->atime = _wtime (_pbc->auto_pause_time); n = 0; - _VCD_LIST_FOREACH (node, _pbc->item_id_list) + _CDIO_LIST_FOREACH (node, _pbc->item_id_list) { - const char *_id = _vcd_list_node_data (node); + const char *_id = _cdio_list_node_data (node); uint16_t _pin; if (_id) @@ -546,22 +547,22 @@ _vcd_pbc_node_write (const VcdObj *obj, const pbc_t *_pbc, void *buf, case PBC_SELECTION: { - PsdSelectionListDescriptor *_md = buf; + PsdSelectionListDescriptor_t *_md = buf; - const unsigned _nos = _vcd_list_length (_pbc->select_id_list); + const unsigned int _nos = _cdio_list_length (_pbc->select_id_list); if (extended) _md->type = PSD_TYPE_EXT_SELECTION_LIST; else _md->type = PSD_TYPE_SELECTION_LIST; - if (!IN (_pbc->bsn, 1, 99)) - vcd_error ("selection '%s': BSN (%d) not in range [1..99]", - _pbc->id, _pbc->bsn); + if (!IN (_pbc->bsn, 1, MAX_PBC_SELECTIONS)) + vcd_error ("selection '%s': BSN (%d) not in range [1..%d]", + _pbc->id, _pbc->bsn, MAX_PBC_SELECTIONS); - if (!IN (_nos, 0, 99)) - vcd_error ("selection '%s': too many selections (%d > 99)", - _pbc->id, _nos); + if (!IN (_nos, 0, MAX_PBC_SELECTIONS)) + vcd_error ("selection '%s': too many selections (%d > %d)", + _pbc->id, _nos, MAX_PBC_SELECTIONS); if (_nos + _pbc->bsn > 100) vcd_error ("selection '%s': BSN + NOS (%d + %d) > 100", @@ -676,7 +677,8 @@ _vcd_pbc_node_write (const VcdObj *obj, const pbc_t *_pbc, void *buf, if ((_seq = _vcd_obj_get_sequence_by_id ((VcdObj *) obj, _pbc->item_id)) || (_seq = _vcd_obj_get_sequence_by_entry_id ((VcdObj *) obj, _pbc->item_id))) { - const unsigned _entries = _vcd_list_length (_seq->entry_list) + 1; + const unsigned _entries = + _cdio_list_length (_seq->entry_list) + 1; if (_nos != _entries) vcd_error ("selection '%s': number of entrypoints" @@ -699,13 +701,13 @@ _vcd_pbc_node_write (const VcdObj *obj, const pbc_t *_pbc, void *buf, /* fill selection array */ { - VcdListNode *node = NULL; + CdioListNode *node = NULL; int idx = 0; idx = 0; - _VCD_LIST_FOREACH (node, _pbc->select_id_list) + _CDIO_LIST_FOREACH (node, _pbc->select_id_list) { - const char *_id = _vcd_list_node_data (node); + const char *_id = _cdio_list_node_data (node); _md->ofs[idx] = uint16_to_be (_lookup_psd_offset (obj, _id, extended)); @@ -717,7 +719,7 @@ _vcd_pbc_node_write (const VcdObj *obj, const pbc_t *_pbc, void *buf, if (extended || _vcd_obj_has_cap_p (obj, _CAP_4C_SVCD)) { PsdSelectionListDescriptorExtended *_md2; - VcdListNode *node; + CdioListNode *node; int n; /* append extended selection areas */ @@ -732,9 +734,9 @@ _vcd_pbc_node_write (const VcdObj *obj, const pbc_t *_pbc, void *buf, n = 0; if (_pbc->select_area_list) - _VCD_LIST_FOREACH (node, _pbc->select_area_list) + _CDIO_LIST_FOREACH (node, _pbc->select_area_list) { - const pbc_area_t *_area = _vcd_list_node_data (node); + const pbc_area_t *_area = _cdio_list_node_data (node); _set_area_helper (&_md2->area[n], _area, _pbc->id); @@ -809,12 +811,12 @@ vcd_pbc_new (enum pbc_type_t type) switch (type) { case PBC_PLAYLIST: - _pbc->item_id_list = _vcd_list_new (); + _pbc->item_id_list = _cdio_list_new (); break; case PBC_SELECTION: - _pbc->select_id_list = _vcd_list_new (); - _pbc->select_area_list = _vcd_list_new (); + _pbc->select_id_list = _cdio_list_new (); + _pbc->select_area_list = _cdio_list_new (); break; case PBC_END: @@ -834,14 +836,14 @@ vcd_pbc_new (enum pbc_type_t type) bool _vcd_pbc_finalize (VcdObj *obj) { - VcdListNode *node; + CdioListNode *node; unsigned offset = 0, offset_ext = 0; unsigned lid; lid = 1; - _VCD_LIST_FOREACH (node, obj->pbc_list) + _CDIO_LIST_FOREACH (node, obj->pbc_list) { - pbc_t *_pbc = _vcd_list_node_data (node); + pbc_t *_pbc = _cdio_list_node_data (node); unsigned length, length_ext = 0; length = _vcd_pbc_node_length (obj, _pbc, false); diff --git a/src/input/vcd/libvcd/pbc.h b/src/input/vcd/libvcd/pbc.h index c58ea2091..9972c3143 100644 --- a/src/input/vcd/libvcd/pbc.h +++ b/src/input/vcd/libvcd/pbc.h @@ -1,5 +1,5 @@ /* - $Id: pbc.h,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: pbc.h,v 1.3 2005/01/01 02:43:59 rockyb Exp $ Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> @@ -72,7 +72,7 @@ struct _pbc_t { double playing_time; int wait_time; int auto_pause_time; - VcdList *item_id_list; /* char */ + CdioList *item_id_list; /* char */ /* used for selection lists */ enum selection_type_t { @@ -85,7 +85,7 @@ struct _pbc_t { pbc_area_t *next_area; pbc_area_t *return_area; pbc_area_t *default_area; /* depends on selection_type */ - VcdList *select_area_list; /* pbc_area_t */ + CdioList *select_area_list; /* pbc_area_t */ unsigned bsn; char *default_id; @@ -94,7 +94,7 @@ struct _pbc_t { unsigned loop_count; bool jump_delayed; char *item_id; - VcdList *select_id_list; /* char */ + CdioList *select_id_list; /* char */ /* used for end lists */ char *image_id; diff --git a/src/input/vcd/libvcd/vcd.c b/src/input/vcd/libvcd/vcd.c index baca9da91..e9618a7d7 100644 --- a/src/input/vcd/libvcd/vcd.c +++ b/src/input/vcd/libvcd/vcd.c @@ -1,7 +1,7 @@ /* - $Id: vcd.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: vcd.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $ - Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org> + Copyright (C) 2000, 2004 Herbert Valerio Riedel <hvr@gnu.org> 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 @@ -49,7 +49,7 @@ #include "util.h" #include "vcd.h" -static const char _rcsid[] = "$Id: vcd.c,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $"; +static const char _rcsid[] = "$Id: vcd.c,v 1.3 2005/01/01 02:43:59 rockyb Exp $"; static const char zero[CDIO_CD_FRAMESIZE_RAW] = { 0, }; @@ -61,14 +61,14 @@ static const char zero[CDIO_CD_FRAMESIZE_RAW] = { 0, }; mpeg_sequence_t * _vcd_obj_get_sequence_by_id (VcdObj *obj, const char sequence_id[]) { - VcdListNode *node; + CdioListNode *node; vcd_assert (sequence_id != NULL); vcd_assert (obj != NULL); - _VCD_LIST_FOREACH (node, obj->mpeg_sequence_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_sequence_list) { - mpeg_sequence_t *_sequence = _vcd_list_node_data (node); + mpeg_sequence_t *_sequence = _cdio_list_node_data (node); if (_sequence->id && !strcmp (sequence_id, _sequence->id)) return _sequence; @@ -80,15 +80,15 @@ _vcd_obj_get_sequence_by_id (VcdObj *obj, const char sequence_id[]) mpeg_sequence_t * _vcd_obj_get_sequence_by_entry_id (VcdObj *obj, const char entry_id[]) { - VcdListNode *node; + CdioListNode *node; vcd_assert (entry_id != NULL); vcd_assert (obj != NULL); - _VCD_LIST_FOREACH (node, obj->mpeg_sequence_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_sequence_list) { - mpeg_sequence_t *_sequence = _vcd_list_node_data (node); - VcdListNode *node2; + mpeg_sequence_t *_sequence = _cdio_list_node_data (node); + CdioListNode *node2; /* default entry point */ if (_sequence->default_entry_id @@ -96,9 +96,9 @@ _vcd_obj_get_sequence_by_entry_id (VcdObj *obj, const char entry_id[]) return _sequence; /* additional entry points */ - _VCD_LIST_FOREACH (node2, _sequence->entry_list) + _CDIO_LIST_FOREACH (node2, _sequence->entry_list) { - entry_t *_entry = _vcd_list_node_data (node2); + entry_t *_entry = _cdio_list_node_data (node2); if (_entry->id && !strcmp (entry_id, _entry->id)) @@ -114,14 +114,14 @@ _vcd_obj_get_sequence_by_entry_id (VcdObj *obj, const char entry_id[]) mpeg_segment_t * _vcd_obj_get_segment_by_id (VcdObj *obj, const char segment_id[]) { - VcdListNode *node; + CdioListNode *node; vcd_assert (segment_id != NULL); vcd_assert (obj != NULL); - _VCD_LIST_FOREACH (node, obj->mpeg_segment_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_segment_list) { - mpeg_segment_t *_segment = _vcd_list_node_data (node); + mpeg_segment_t *_segment = _cdio_list_node_data (node); if (_segment->id && !strcmp (segment_id, _segment->id)) return _segment; @@ -283,15 +283,15 @@ vcd_obj_new (vcd_type_t vcd_type) new_obj->info_volume_count = 1; new_obj->info_volume_number = 1; - new_obj->custom_file_list = _vcd_list_new (); - new_obj->custom_dir_list = _vcd_list_new (); + new_obj->custom_file_list = _cdio_list_new (); + new_obj->custom_dir_list = _cdio_list_new (); - new_obj->mpeg_sequence_list = _vcd_list_new (); + new_obj->mpeg_sequence_list = _cdio_list_new (); - new_obj->mpeg_segment_list = _vcd_list_new (); + new_obj->mpeg_segment_list = _cdio_list_new (); - new_obj->pbc_list = _vcd_list_new (); + new_obj->pbc_list = _cdio_list_new (); /* gap's defined by IEC-10149 / ECMA-130 */ @@ -327,7 +327,7 @@ _vcd_obj_remove_mpeg_track (VcdObj *obj, int track_id) { int length; mpeg_sequence_t *track = NULL; - VcdListNode *node = NULL; + CdioListNode *node = NULL; vcd_assert (track_id >= 0); @@ -335,7 +335,7 @@ _vcd_obj_remove_mpeg_track (VcdObj *obj, int track_id) vcd_assert (node != NULL); - track = (mpeg_sequence_t *) _vcd_list_node_data (node); + track = (mpeg_sequence_t *) _cdio_list_node_data (node); vcd_mpeg_source_destroy (track->source, true); @@ -344,15 +344,15 @@ _vcd_obj_remove_mpeg_track (VcdObj *obj, int track_id) /* fixup offsets */ { - VcdListNode *node2 = node; - while ((node2 = _vcd_list_node_next (node2)) != NULL) - ((mpeg_sequence_t *) _vcd_list_node_data (node))->relative_start_extent -= length; + CdioListNode *node2 = node; + while ((node2 = _cdio_list_node_next (node2)) != NULL) + ((mpeg_sequence_t *) _cdio_list_node_data (node))->relative_start_extent -= length; } obj->relative_end_extent -= length; /* shift up */ - _vcd_list_node_free (node, true); + _cdio_list_node_free (node, true); } int @@ -383,7 +383,7 @@ vcd_obj_append_segment_play_item (VcdObj *obj, VcdMpegSource *mpeg_source, } vcd_info ("scanning mpeg segment item #%d for scanpoints...", - _vcd_list_length (obj->mpeg_segment_list)); + _cdio_list_length (obj->mpeg_segment_list)); vcd_mpeg_source_scan (mpeg_source, !obj->relaxed_aps, obj->update_scan_offsets, NULL, NULL); @@ -405,13 +405,13 @@ vcd_obj_append_segment_play_item (VcdObj *obj, VcdMpegSource *mpeg_source, segment->info = vcd_mpeg_source_get_info (mpeg_source); segment->segment_count = _vcd_len2blocks (segment->info->packets, 150); - segment->pause_list = _vcd_list_new (); + segment->pause_list = _cdio_list_new (); vcd_debug ("SPI length is %d sector(s), allocated %d segment(s)", segment->info->packets, segment->segment_count); - _vcd_list_append (obj->mpeg_segment_list, segment); + _cdio_list_append (obj->mpeg_segment_list, segment); return 0; } @@ -423,7 +423,7 @@ vcd_obj_append_sequence_play_item (VcdObj *obj, VcdMpegSource *mpeg_source, { unsigned length; mpeg_sequence_t *sequence = NULL; - int track_no = _vcd_list_length (obj->mpeg_sequence_list); + int track_no = _cdio_list_length (obj->mpeg_sequence_list); vcd_assert (obj != NULL); vcd_assert (mpeg_source != NULL); @@ -463,8 +463,8 @@ vcd_obj_append_sequence_play_item (VcdObj *obj, VcdMpegSource *mpeg_source, sequence->info = vcd_mpeg_source_get_info (mpeg_source); length = sequence->info->packets; - sequence->entry_list = _vcd_list_new (); - sequence->pause_list = _vcd_list_new (); + sequence->entry_list = _cdio_list_new (); + sequence->pause_list = _cdio_list_new (); obj->relative_end_extent += obj->track_pregap; sequence->relative_start_extent = obj->relative_end_extent; @@ -526,7 +526,7 @@ vcd_obj_append_sequence_play_item (VcdObj *obj, VcdMpegSource *mpeg_source, /* vcd_debug ("track# %d's detected playing time: %.2f seconds", */ /* track_no, sequence->info->playing_time); */ - _vcd_list_append (obj->mpeg_sequence_list, sequence); + _cdio_list_append (obj->mpeg_sequence_list, sequence); return track_no; } @@ -554,7 +554,8 @@ vcd_obj_add_sequence_pause (VcdObj *obj, const char sequence_id[], if (sequence_id) _sequence = _vcd_obj_get_sequence_by_id (obj, sequence_id); else - _sequence = _vcd_list_node_data (_vcd_list_end (obj->mpeg_sequence_list)); + _sequence = + _cdio_list_node_data (_cdio_list_end (obj->mpeg_sequence_list)); if (!_sequence) { @@ -572,11 +573,11 @@ vcd_obj_add_sequence_pause (VcdObj *obj, const char sequence_id[], _pause->id = strdup (pause_id); _pause->time = pause_time; - _vcd_list_append (_sequence->pause_list, _pause); + _cdio_list_append (_sequence->pause_list, _pause); } _vcd_list_sort (_sequence->pause_list, - (_vcd_list_cmp_func) _pause_cmp); + (_cdio_list_cmp_func) _pause_cmp); vcd_debug ("added autopause point at %f", pause_time); @@ -594,7 +595,7 @@ vcd_obj_add_segment_pause (VcdObj *obj, const char segment_id[], if (segment_id) _segment = _vcd_obj_get_segment_by_id (obj, segment_id); else - _segment = _vcd_list_node_data (_vcd_list_end (obj->mpeg_segment_list)); + _segment = _cdio_list_node_data (_cdio_list_end (obj->mpeg_segment_list)); if (!_segment) { @@ -612,11 +613,11 @@ vcd_obj_add_segment_pause (VcdObj *obj, const char segment_id[], _pause->id = strdup (pause_id); _pause->time = pause_time; - _vcd_list_append (_segment->pause_list, _pause); + _cdio_list_append (_segment->pause_list, _pause); } _vcd_list_sort (_segment->pause_list, - (_vcd_list_cmp_func) _pause_cmp); + (_cdio_list_cmp_func) _pause_cmp); vcd_debug ("added autopause point at %f", pause_time); @@ -646,7 +647,8 @@ vcd_obj_add_sequence_entry (VcdObj *obj, const char sequence_id[], if (sequence_id) _sequence = _vcd_obj_get_sequence_by_id (obj, sequence_id); else - _sequence = _vcd_list_node_data (_vcd_list_end (obj->mpeg_sequence_list)); + _sequence = + _cdio_list_node_data (_cdio_list_end (obj->mpeg_sequence_list)); if (!_sequence) { @@ -654,7 +656,7 @@ vcd_obj_add_sequence_entry (VcdObj *obj, const char sequence_id[], return -1; } - if (_vcd_list_length (_sequence->entry_list) >= MAX_SEQ_ENTRIES) + if (_cdio_list_length (_sequence->entry_list) >= MAX_SEQ_ENTRIES) { vcd_error ("only %d entries per sequence allowed!", MAX_SEQ_ENTRIES); return -1; @@ -673,11 +675,11 @@ vcd_obj_add_sequence_entry (VcdObj *obj, const char sequence_id[], _entry->id = strdup (entry_id); _entry->time = entry_time; - _vcd_list_append (_sequence->entry_list, _entry); + _cdio_list_append (_sequence->entry_list, _entry); } _vcd_list_sort (_sequence->entry_list, - (_vcd_list_cmp_func) _entry_cmp); + (_cdio_list_cmp_func) _entry_cmp); return 0; } @@ -685,7 +687,7 @@ vcd_obj_add_sequence_entry (VcdObj *obj, const char sequence_id[], void vcd_obj_destroy (VcdObj *obj) { - VcdListNode *node; + CdioListNode *node; vcd_assert (obj != NULL); vcd_assert (!obj->in_output); @@ -693,20 +695,20 @@ vcd_obj_destroy (VcdObj *obj) free (obj->iso_volume_label); free (obj->iso_application_id); - _VCD_LIST_FOREACH (node, obj->custom_file_list) + _CDIO_LIST_FOREACH (node, obj->custom_file_list) { - custom_file_t *p = _vcd_list_node_data (node); + custom_file_t *p = _cdio_list_node_data (node); free (p->iso_pathname); } - _vcd_list_free (obj->custom_file_list, true); + _cdio_list_free (obj->custom_file_list, true); - _vcd_list_free (obj->custom_dir_list, true); + _cdio_list_free (obj->custom_dir_list, true); - while (_vcd_list_length (obj->mpeg_sequence_list)) + while (_cdio_list_length (obj->mpeg_sequence_list)) _vcd_obj_remove_mpeg_track (obj, 0); - _vcd_list_free (obj->mpeg_sequence_list, true); + _cdio_list_free (obj->mpeg_sequence_list, true); free (obj); } @@ -983,10 +985,10 @@ vcd_obj_add_dir (VcdObj *obj, const char iso_pathname[]) return 1; } - _vcd_list_append (obj->custom_dir_list, _iso_pathname); + _cdio_list_append (obj->custom_dir_list, _iso_pathname); _vcd_list_sort (obj->custom_dir_list, - (_vcd_list_cmp_func) strcmp); + (_cdio_list_cmp_func) strcmp); return 0; } @@ -1050,7 +1052,7 @@ vcd_obj_add_file (VcdObj *obj, const char iso_pathname[], p->start_extent = 0; p->sectors = sectors; - _vcd_list_append (obj->custom_file_list, p); + _cdio_list_append (obj->custom_file_list, p); } return 0; @@ -1060,7 +1062,7 @@ static void _finalize_vcd_iso_track_allocation (VcdObj *obj) { int n; - VcdListNode *node; + CdioListNode *node; uint32_t dir_secs = SECTOR_NIL; @@ -1119,9 +1121,9 @@ _finalize_vcd_iso_track_allocation (VcdObj *obj) /* insert segments */ - _VCD_LIST_FOREACH (node, obj->mpeg_segment_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_segment_list) { - mpeg_segment_t *_segment = _vcd_list_node_data (node); + mpeg_segment_t *_segment = _cdio_list_node_data (node); _segment->start_extent = _vcd_salloc (obj->iso_bitmap, SECTOR_NIL, @@ -1163,9 +1165,9 @@ _finalize_vcd_iso_track_allocation (VcdObj *obj) /* now for the custom files */ - _VCD_LIST_FOREACH (node, obj->custom_file_list) + _CDIO_LIST_FOREACH (node, obj->custom_file_list) { - custom_file_t *p = _vcd_list_node_data (node); + custom_file_t *p = _cdio_list_node_data (node); if (p->sectors) { @@ -1194,7 +1196,7 @@ static void _finalize_vcd_iso_track_filesystem (VcdObj *obj) { int n; - VcdListNode *node; + CdioListNode *node; /* create filesystem entries */ @@ -1211,7 +1213,7 @@ _finalize_vcd_iso_track_filesystem (VcdObj *obj) _vcd_directory_mkdir (obj->dir, "VCD"); /* add segment dir only when there are actually segment play items */ - if (_vcd_list_length (obj->mpeg_segment_list)) + if (_cdio_list_length (obj->mpeg_segment_list)) _vcd_directory_mkdir (obj->dir, "SEGMENT"); _vcd_directory_mkfile (obj->dir, "VCD/ENTRIES.VCD", @@ -1246,7 +1248,7 @@ _finalize_vcd_iso_track_filesystem (VcdObj *obj) } /* add segment dir only when there are actually segment play items */ - if (_vcd_list_length (obj->mpeg_segment_list)) + if (_cdio_list_length (obj->mpeg_segment_list)) _vcd_directory_mkdir (obj->dir, "SEGMENT"); _vcd_directory_mkdir (obj->dir, "SVCD"); @@ -1284,9 +1286,9 @@ _finalize_vcd_iso_track_filesystem (VcdObj *obj) /* SEGMENTS */ n = 1; - _VCD_LIST_FOREACH (node, obj->mpeg_segment_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_segment_list) { - mpeg_segment_t *segment = _vcd_list_node_data (node); + mpeg_segment_t *segment = _cdio_list_node_data (node); char segment_pathname[128] = { 0, }; const char *fmt = NULL; uint8_t fnum = 0; @@ -1344,15 +1346,15 @@ _finalize_vcd_iso_track_filesystem (VcdObj *obj) } /* custom files/dirs */ - _VCD_LIST_FOREACH (node, obj->custom_dir_list) + _CDIO_LIST_FOREACH (node, obj->custom_dir_list) { - char *p = _vcd_list_node_data (node); + char *p = _cdio_list_node_data (node); _vcd_directory_mkdir (obj->dir, p); } - _VCD_LIST_FOREACH (node, obj->custom_file_list) + _CDIO_LIST_FOREACH (node, obj->custom_file_list) { - custom_file_t *p = _vcd_list_node_data (node); + custom_file_t *p = _cdio_list_node_data (node); _vcd_directory_mkfile (obj->dir, p->iso_pathname, p->start_extent, (p->raw_flag @@ -1363,11 +1365,11 @@ _finalize_vcd_iso_track_filesystem (VcdObj *obj) n = 0; - _VCD_LIST_FOREACH (node, obj->mpeg_sequence_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_sequence_list) { char avseq_pathname[128] = { 0, }; const char *fmt = NULL; - mpeg_sequence_t *_sequence = _vcd_list_node_data (node); + mpeg_sequence_t *_sequence = _cdio_list_node_data (node); uint32_t extent = _sequence->relative_start_extent; uint8_t file_num = 0; @@ -1478,7 +1480,7 @@ _callback_wrapper (VcdObj *obj, int force) _pi.sectors_written = obj->sectors_written; _pi.total_sectors = obj->relative_end_extent + obj->iso_size; _pi.in_track = obj->in_track; - _pi.total_tracks = _vcd_list_length (obj->mpeg_sequence_list) + 1; + _pi.total_tracks = _cdio_list_length (obj->mpeg_sequence_list) + 1; return obj->progress_callback (&_pi, obj->callback_user_data); } @@ -1580,8 +1582,8 @@ static int _write_sequence (VcdObj *obj, int track_idx) { mpeg_sequence_t *track = - _vcd_list_node_data (_vcd_list_at (obj->mpeg_sequence_list, track_idx)); - VcdListNode *pause_node; + _cdio_list_node_data (_vcd_list_at (obj->mpeg_sequence_list, track_idx)); + CdioListNode *pause_node; int n, lastsect = obj->sectors_written; char buf[2324]; struct { @@ -1680,7 +1682,7 @@ _write_sequence (VcdObj *obj, int track_idx) _write_m2_image_sector (obj, zero, lastsect++, track_idx + 1, 0, SM_FORM2|SM_REALT, 0); - pause_node = _vcd_list_begin (track->pause_list); + pause_node = _cdio_list_begin (track->pause_list); for (n = 0; n < track->info->packets; n++) { int ci = 0, sm = 0, cnum = 0, fnum = 0; @@ -1692,7 +1694,7 @@ _write_sequence (VcdObj *obj, int track_idx) while (pause_node) { - pause_t *_pause = _vcd_list_node_data (pause_node); + pause_t *_pause = _cdio_list_node_data (pause_node); if (!pkt_flags.has_pts) break; /* no pts */ @@ -1706,7 +1708,7 @@ _write_sequence (VcdObj *obj, int track_idx) vcd_debug ("setting auto pause trigger for time %f (pts %f) @%d", _pause->time, pkt_flags.pts, n); - pause_node = _vcd_list_node_next (pause_node); + pause_node = _cdio_list_node_next (pause_node); } switch (vcd_mpeg_packet_get_type (&pkt_flags)) @@ -1807,13 +1809,13 @@ _write_sequence (VcdObj *obj, int track_idx) static int _write_segment (VcdObj *obj, mpeg_segment_t *_segment) { - VcdListNode *pause_node; + CdioListNode *pause_node; unsigned packet_no; int n = obj->sectors_written; vcd_assert (_segment->start_extent == n); - pause_node = _vcd_list_begin (_segment->pause_list); + pause_node = _cdio_list_begin (_segment->pause_list); for (packet_no = 0; packet_no < (_segment->segment_count * VCDINFO_SEGMENT_SECTOR_SIZE); @@ -1838,7 +1840,7 @@ _write_segment (VcdObj *obj, mpeg_segment_t *_segment) while (pause_node) { - pause_t *_pause = _vcd_list_node_data (pause_node); + pause_t *_pause = _cdio_list_node_data (pause_node); if (!pkt_flags.has_pts) break; /* no pts */ @@ -1852,7 +1854,7 @@ _write_segment (VcdObj *obj, mpeg_segment_t *_segment) vcd_debug ("setting auto pause trigger for time %f (pts %f) @%d", _pause->time, pkt_flags.pts, n); - pause_node = _vcd_list_node_next (pause_node); + pause_node = _cdio_list_node_next (pause_node); } switch (vcd_mpeg_packet_get_type (&pkt_flags)) @@ -1950,16 +1952,16 @@ static uint32_t _get_closest_aps (const struct vcd_mpeg_stream_info *_mpeg_info, double t, struct aps_data *_best_aps) { - VcdListNode *node; + CdioListNode *node; struct aps_data best_aps; bool first = true; vcd_assert (_mpeg_info != NULL); vcd_assert (_mpeg_info->shdr[0].aps_list != NULL); - _VCD_LIST_FOREACH (node, _mpeg_info->shdr[0].aps_list) + _CDIO_LIST_FOREACH (node, _mpeg_info->shdr[0].aps_list) { - struct aps_data *_aps = _vcd_list_node_data (node); + struct aps_data *_aps = _cdio_list_node_data (node); if (first) { @@ -1981,17 +1983,17 @@ _get_closest_aps (const struct vcd_mpeg_stream_info *_mpeg_info, double t, static void _update_entry_points (VcdObj *obj) { - VcdListNode *sequence_node; + CdioListNode *sequence_node; - _VCD_LIST_FOREACH (sequence_node, obj->mpeg_sequence_list) + _CDIO_LIST_FOREACH (sequence_node, obj->mpeg_sequence_list) { - mpeg_sequence_t *_sequence = _vcd_list_node_data (sequence_node); - VcdListNode *entry_node; + mpeg_sequence_t *_sequence = _cdio_list_node_data (sequence_node); + CdioListNode *entry_node; unsigned last_packet_no = 0; - _VCD_LIST_FOREACH (entry_node, _sequence->entry_list) + _CDIO_LIST_FOREACH (entry_node, _sequence->entry_list) { - entry_t *_entry = _vcd_list_node_data (entry_node); + entry_t *_entry = _cdio_list_node_data (entry_node); _get_closest_aps (_sequence->info, _entry->time, &_entry->aps); @@ -2014,7 +2016,7 @@ _update_entry_points (VcdObj *obj) static int _write_vcd_iso_track (VcdObj *obj, const time_t *create_time) { - VcdListNode *node; + CdioListNode *node; int n; /* generate dir sectors */ @@ -2092,9 +2094,9 @@ _write_vcd_iso_track (VcdObj *obj, const time_t *create_time) vcd_assert (n == obj->mpeg_segment_start_extent); - _VCD_LIST_FOREACH (node, obj->mpeg_segment_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_segment_list) { - mpeg_segment_t *_segment = _vcd_list_node_data (node); + mpeg_segment_t *_segment = _cdio_list_node_data (node); _write_segment (obj, _segment); } @@ -2127,12 +2129,12 @@ _write_vcd_iso_track (VcdObj *obj, const time_t *create_time) vcd_assert (n == obj->custom_file_start_extent); - _VCD_LIST_FOREACH (node, obj->custom_file_list) + _CDIO_LIST_FOREACH (node, obj->custom_file_list) { - custom_file_t *p = _vcd_list_node_data (node); + custom_file_t *p = _cdio_list_node_data (node); - vcd_info ("writing file `%s' (%d bytes%s)", - p->iso_pathname, p->size, + vcd_info ("writing file `%s' (%lu bytes%s)", + p->iso_pathname, (unsigned long) p->size, p->raw_flag ? ", raw sectors file": ""); if (p->raw_flag) _write_source_mode2_raw (obj, p->file, p->start_extent); @@ -2155,7 +2157,7 @@ vcd_obj_get_image_size (VcdObj *obj) vcd_assert (!obj->in_output); - if (_vcd_list_length (obj->mpeg_sequence_list) > 0) + if (_cdio_list_length (obj->mpeg_sequence_list) > 0) { /* fixme -- make this efficient */ size_sectors = vcd_obj_begin_output (obj); @@ -2171,7 +2173,7 @@ vcd_obj_begin_output (VcdObj *obj) uint32_t image_size; vcd_assert (obj != NULL); - vcd_assert (_vcd_list_length (obj->mpeg_sequence_list) > 0); + vcd_assert (_cdio_list_length (obj->mpeg_sequence_list) > 0); vcd_assert (!obj->in_output); obj->in_output = true; @@ -2183,7 +2185,7 @@ vcd_obj_begin_output (VcdObj *obj) obj->dir = _vcd_directory_new (); - obj->buffer_dict_list = _vcd_list_new (); + obj->buffer_dict_list = _cdio_list_new (); _finalize_vcd_iso_track (obj); @@ -2224,7 +2226,7 @@ vcd_obj_end_output (VcdObj *obj) _vcd_salloc_destroy (obj->iso_bitmap); _dict_clean (obj); - _vcd_list_free (obj->buffer_dict_list, true); + _cdio_list_free (obj->buffer_dict_list, true); } int @@ -2245,7 +2247,7 @@ vcd_obj_append_pbc_node (VcdObj *obj, struct _pbc_t *_pbc) return -1; } - _vcd_list_append (obj->pbc_list, _pbc); + _cdio_list_append (obj->pbc_list, _pbc); return 0; } @@ -2255,7 +2257,7 @@ vcd_obj_write_image (VcdObj *obj, VcdImageSink *image_sink, progress_callback_t callback, void *user_data, const time_t *create_time) { - VcdListNode *node; + CdioListNode *node; vcd_assert (obj != NULL); vcd_assert (obj->in_output); @@ -2266,37 +2268,40 @@ vcd_obj_write_image (VcdObj *obj, VcdImageSink *image_sink, /* start with meta info */ { - VcdList *cue_list; + CdioList *cue_list; vcd_cue_t *_cue; - cue_list = _vcd_list_new (); + cue_list = _cdio_list_new (); - _vcd_list_append (cue_list, (_cue = _vcd_malloc (sizeof (vcd_cue_t)))); + _cdio_list_append (cue_list, (_cue = _vcd_malloc (sizeof (vcd_cue_t)))); _cue->lsn = 0; _cue->type = VCD_CUE_TRACK_START; - _VCD_LIST_FOREACH (node, obj->mpeg_sequence_list) + _CDIO_LIST_FOREACH (node, obj->mpeg_sequence_list) { - mpeg_sequence_t *track = _vcd_list_node_data (node); - VcdListNode *entry_node; + mpeg_sequence_t *track = _cdio_list_node_data (node); + CdioListNode *entry_node; - _vcd_list_append (cue_list, (_cue = _vcd_malloc (sizeof (vcd_cue_t)))); + _cdio_list_append (cue_list, + (_cue = _vcd_malloc (sizeof (vcd_cue_t)))); _cue->lsn = track->relative_start_extent + obj->iso_size; _cue->lsn -= obj->track_pregap; _cue->type = VCD_CUE_PREGAP_START; - _vcd_list_append (cue_list, (_cue = _vcd_malloc (sizeof (vcd_cue_t)))); + _cdio_list_append (cue_list, + (_cue = _vcd_malloc (sizeof (vcd_cue_t)))); _cue->lsn = track->relative_start_extent + obj->iso_size; _cue->type = VCD_CUE_TRACK_START; - _VCD_LIST_FOREACH (entry_node, track->entry_list) + _CDIO_LIST_FOREACH (entry_node, track->entry_list) { - entry_t *_entry = _vcd_list_node_data (entry_node); + entry_t *_entry = _cdio_list_node_data (entry_node); - _vcd_list_append (cue_list, (_cue = _vcd_malloc (sizeof (vcd_cue_t)))); + _cdio_list_append (cue_list, + (_cue = _vcd_malloc (sizeof (vcd_cue_t)))); _cue->lsn = obj->iso_size; _cue->lsn += track->relative_start_extent; @@ -2309,7 +2314,7 @@ vcd_obj_write_image (VcdObj *obj, VcdImageSink *image_sink, /* add last one... */ - _vcd_list_append (cue_list, (_cue = _vcd_malloc (sizeof (vcd_cue_t)))); + _cdio_list_append (cue_list, (_cue = _vcd_malloc (sizeof (vcd_cue_t)))); _cue->lsn = obj->relative_end_extent + obj->iso_size; @@ -2321,7 +2326,7 @@ vcd_obj_write_image (VcdObj *obj, VcdImageSink *image_sink, vcd_image_sink_set_cuesheet (image_sink, cue_list); - _vcd_list_free (cue_list, true); + _cdio_list_free (cue_list, true); } /* and now for the pay load */ @@ -2347,7 +2352,7 @@ vcd_obj_write_image (VcdObj *obj, VcdImageSink *image_sink, if (obj->update_scan_offsets) vcd_info ("'update scan offsets' option enabled for the following tracks!"); - for (track = 0;track < _vcd_list_length (obj->mpeg_sequence_list);track++) + for (track = 0;track < _cdio_list_length (obj->mpeg_sequence_list);track++) { obj->in_track++; diff --git a/src/input/vcd/libvcd/vcd_read.c b/src/input/vcd/libvcd/vcd_read.c index b598ffe31..dd9d30cfa 100644 --- a/src/input/vcd/libvcd/vcd_read.c +++ b/src/input/vcd/libvcd/vcd_read.c @@ -1,5 +1,5 @@ /* - $Id: vcd_read.c,v 1.3 2004/04/11 14:59:23 mroi Exp $ + $Id: vcd_read.c,v 1.4 2005/01/01 02:43:59 rockyb Exp $ Copyright (C) 2001,2003 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2003 Rocky Bernstein <rocky@gnu.org> @@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - + #include "vcd_read.h" #include "vcd_assert.h" #include <libvcd/inf.h> @@ -53,7 +53,7 @@ read_pvd(CdIo *cdio, iso9660_pvd_t *pvd) } bool -read_entries(CdIo *cdio, EntriesVcd *entries) +read_entries(CdIo *cdio, EntriesVcd_t *entries) { if (cdio_read_mode2_sector (cdio, entries, ENTRIES_VCD_SECTOR, false)) { vcd_error ("error reading Entries sector (%d)", ENTRIES_VCD_SECTOR); @@ -74,7 +74,7 @@ read_entries(CdIo *cdio, EntriesVcd *entries) } bool -read_info(CdIo *cdio, InfoVcd *info, vcd_type_t *vcd_type) +read_info(CdIo *cdio, InfoVcd_t *info, vcd_type_t *vcd_type) { if (cdio_read_mode2_sector (cdio, info, INFO_VCD_SECTOR, false)) { vcd_error ("error reading Info sector (%d)", INFO_VCD_SECTOR); diff --git a/src/input/vcd/libvcd/vcd_read.h b/src/input/vcd/libvcd/vcd_read.h index 9dde195f4..fb9e1509b 100644 --- a/src/input/vcd/libvcd/vcd_read.h +++ b/src/input/vcd/libvcd/vcd_read.h @@ -1,5 +1,5 @@ /* - $Id: vcd_read.h,v 1.2 2004/04/11 12:20:32 miguelfreitas Exp $ + $Id: vcd_read.h,v 1.3 2005/01/01 02:43:59 rockyb Exp $ Copyright (C) 2003 Rocky Bernstein <rocky@gnu.org> @@ -29,8 +29,8 @@ #include <libvcd/files_private.h> bool read_pvd(CdIo *cdio, iso9660_pvd_t *pvd); -bool read_entries(CdIo *cdio, EntriesVcd *entries); -bool read_info(CdIo *cdio, InfoVcd *info, vcd_type_t *vcd_type); +bool read_entries(CdIo *cdio, EntriesVcd_t *entries); +bool read_info(CdIo *cdio, InfoVcd_t *info, vcd_type_t *vcd_type); diff --git a/src/input/vcd/libvcd/version.h b/src/input/vcd/libvcd/version.h new file mode 100644 index 000000000..d1f658c23 --- /dev/null +++ b/src/input/vcd/libvcd/version.h @@ -0,0 +1,11 @@ +/* $Id: version.h,v 1.1 2005/01/01 02:43:59 rockyb Exp $ */ +/** \file version.h + * \brief A file simply containing the library version number. + */ + +/*! LIBVCD_VERSION can as a string in programs to show what version is used. */ +#define LIBVCD_VERSION "0.7.21-" + +/*! LIBCDIO_VERSION_NUM can be used for testing in the C preprocessor */ +#define LIBVCD_VERSION_NUM 21 + diff --git a/src/input/vcd/vcdplayer.c b/src/input/vcd/vcdplayer.c index d82a24021..7a6009acd 100644 --- a/src/input/vcd/vcdplayer.c +++ b/src/input/vcd/vcdplayer.c @@ -1,5 +1,5 @@ /* - $Id: vcdplayer.c,v 1.10 2004/12/30 09:05:57 rockyb Exp $ + $Id: vcdplayer.c,v 1.11 2005/01/01 02:43:57 rockyb Exp $ Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com> @@ -810,15 +810,10 @@ vcdplayer_pbc_nav (vcdplayer_t *p_vcdplayer, uint8_t *buf) int rand_selection=bsn + (int) ((i_selections+0.0)*rand()/(RAND_MAX+1.0)); -#if defined(LIBVCD_VERSION) /* version 0.7.21 or greater */ lid_t rand_lid=vcdinfo_selection_get_lid(p_vcdplayer->vcd, p_vcdplayer->i_lid, rand_selection); -#else - lid_t rand_lid=vcdplayer_selection2lid (p_vcdplayer, rand_selection); -#endif /* LIBVCD_VERSION */ - itemid.num = rand_lid; itemid.type = VCDINFO_ITEM_TYPE_LID; dbg_print(INPUT_DBG_PBC, "random selection %d, lid: %d\n", diff --git a/src/input/vcd/vcdplayer.h b/src/input/vcd/vcdplayer.h index b4fe25b3c..d2f40a3ea 100644 --- a/src/input/vcd/vcdplayer.h +++ b/src/input/vcd/vcdplayer.h @@ -1,5 +1,5 @@ /* - $Id: vcdplayer.h,v 1.5 2004/12/30 09:05:57 rockyb Exp $ + $Id: vcdplayer.h,v 1.6 2005/01/01 02:43:57 rockyb Exp $ Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com> @@ -301,13 +301,6 @@ vcdplayer_seek (vcdplayer_t *p_vcdplayer, off_t offset, int origin); void vcdplayer_send_button_update(vcdplayer_t *p_vcdplayer, int mode); -#ifndef LIBVCD_VERSION -/* Older version of vcdimager. You really should consider using 0.7.21 - or later as that has bug and memory leak fixes. */ -lid_t -vcdplayer_selection2lid (vcdplayer_t *p_vcdplayer, int entry_num); -#endif - #endif /* _VCDPLAYER_H_ */ /* * Local variables: diff --git a/src/input/vcd/xineplug_inp_vcd.c b/src/input/vcd/xineplug_inp_vcd.c index 0fcc312f8..df749c7e8 100644 --- a/src/input/vcd/xineplug_inp_vcd.c +++ b/src/input/vcd/xineplug_inp_vcd.c @@ -1,5 +1,5 @@ /* - $Id: xineplug_inp_vcd.c,v 1.28 2004/12/30 09:05:57 rockyb Exp $ + $Id: xineplug_inp_vcd.c,v 1.29 2005/01/01 02:43:57 rockyb Exp $ Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com> @@ -1024,7 +1024,6 @@ vcd_handle_events (void) num = 0; break; case XINE_EVENT_INPUT_MENU2: -#if defined(LIBVCD_VERSION) if (vcdplayer_pbc_is_on(this)) { lid_t lid=vcdinfo_get_multi_default_lid(this->vcd, this->i_lid, this->i_lsn); @@ -1046,17 +1045,6 @@ vcd_handle_events (void) LOG_MSG("%s\n", _("DEFAULT selected but PBC is not on.")); ; } -#else - if (this->default_entry == VCDINFO_INVALID_ENTRY) { - LOG_MSG("%s\n", _("selection has no DEFAULT entry")); - return false; - } - itemid.num = this->default_entry; - dbg_print((INPUT_DBG_PBC|INPUT_DBG_EVENT), - "DEFAULT to %d\n", itemid.num); - /* Don't loop around -- doesn't make sense to loop a return*/ - num = 0; -#endif /* LIBVCD_VERSION */ break; case XINE_EVENT_INPUT_NEXT: if (this->next_entry == VCDINFO_INVALID_ENTRY) { @@ -1093,13 +1081,9 @@ vcd_handle_events (void) number_addend = 0; if (vcdplayer_pbc_is_on(this)) { -#if defined(LIBVCD_VERSION) /* version 0.7.21 or greater */ lid_t next_num=vcdinfo_selection_get_lid(this->vcd, this->i_lid, itemid.num); -#else - lid_t next_num=vcdplayer_selection2lid(this, itemid.num); -#endif /* LIBVCD_VERSION */ if (VCDINFO_INVALID_LID != next_num) { itemid.num = next_num; _x_demux_flush_engine(my_vcd.stream); |