diff options
Diffstat (limited to 'src/input/vcd/libvcd/info.c')
-rw-r--r-- | src/input/vcd/libvcd/info.c | 2103 |
1 files changed, 0 insertions, 2103 deletions
diff --git a/src/input/vcd/libvcd/info.c b/src/input/vcd/libvcd/info.c deleted file mode 100644 index b01bd6eee..000000000 --- a/src/input/vcd/libvcd/info.c +++ /dev/null @@ -1,2103 +0,0 @@ -/* - $Id: info.c,v 1.8 2007/03/23 21:47:31 dsalt Exp $ - - 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 - 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 Foundation - Software, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ -/* - Things here refer to higher-level structures usually accessed via - vcdinfo_t. For lower-level access which generally use - structures other than vcdinfo_t, see inf.c -*/ - - -/* Private headers */ -#include "info_private.h" -#include "vcd_assert.h" -#include "pbc.h" -#include "util.h" -#include "vcd_read.h" - -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif -#ifdef HAVE_STRING_H -#include <string.h> -#endif -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#include <cdio/cdio.h> -#include <cdio/bytesex.h> -#include <cdio/cd_types.h> -#include <cdio/util.h> - -/* Eventually move above libvcd includes but having vcdinfo including. */ -#include <libvcd/info.h> - -#include <stdio.h> -#include <stddef.h> -#include <errno.h> - -static const char _rcsid[] = "$Id: info.c,v 1.8 2007/03/23 21:47:31 dsalt Exp $"; - -#define BUF_COUNT 16 -#define BUF_SIZE 80 - -/* Return a pointer to a internal free buffer */ -static char * -_getbuf (void) -{ - static char _buf[BUF_COUNT][BUF_SIZE]; - static int _num = -1; - - _num++; - _num %= BUF_COUNT; - - memset (_buf[_num], 0, BUF_SIZE); - - return _buf[_num]; -} - -/* - Initialize/allocate segment portion of vcdinfo_obj_t. - - Getting exact segments sizes is done in a rather complicated way. - A simple approach would be to use the fixed size allocated on disk, - but players have trouble with the internal fragmentation padding. - More accurate results are obtained by consulting with ISO 9660 - information for the corresponding file entry. - - Another approach to get segment sizes is to read/scan the - MPEGs. That would be rather slow. -*/ -static void -_init_segments (vcdinfo_obj_t *obj) -{ - InfoVcd_t *info = vcdinfo_get_infoVcd(obj); - segnum_t num_segments = vcdinfo_get_num_segments(obj); - CdioListNode *entnode; - CdioList *entlist; - int i; - lsn_t last_lsn=0; - - obj->first_segment_lsn = cdio_msf_to_lsn(&info->first_seg_addr); - obj->seg_sizes = _vcd_malloc( num_segments * sizeof(uint32_t *)); - - if (NULL == obj->seg_sizes || 0 == num_segments) return; - - entlist = iso9660_fs_readdir(obj->img, "SEGMENT", true); - - i=0; - _CDIO_LIST_FOREACH (entnode, entlist) { - iso9660_stat_t *statbuf = _cdio_list_node_data (entnode); - - if (statbuf->type == _STAT_DIR) continue; - - while(info->spi_contents[i].item_cont) { - obj->seg_sizes[i] = VCDINFO_SEGMENT_SECTOR_SIZE; - i++; - } - - /* Should have an entry in the ISO 9660 filesystem. Get and save - in statbuf.secsize this size. - */ - obj->seg_sizes[i] = statbuf->secsize; - - if (last_lsn >= statbuf->lsn) - vcd_warn ("Segments if ISO 9660 directory out of order lsn %ul >= %ul", - (unsigned int) last_lsn, (unsigned int) statbuf->lsn); - last_lsn = statbuf->lsn; - - i++; - } - - while(i < num_segments && info->spi_contents[i].item_cont) { - obj->seg_sizes[i] = VCDINFO_SEGMENT_SECTOR_SIZE; - i++; - } - - if (i != num_segments) - vcd_warn ("Number of segments found %d is not number of segments %d", - i, num_segments); - - _cdio_list_free (entlist, true); - - -#if 0 - /* Figure all of the segment sector sizes */ - for (i=0; i < num_segments; i++) { - - obj->seg_sizes[i] = VCDINFO_SEGMENT_SECTOR_SIZE; - - if ( !info->spi_contents[i].item_cont ) { - /* Should have an entry in the ISO 9660 filesystem. Get and save - in statbuf.secsize this size. - */ - lsn_t lsn = vcdinfo_get_seg_lsn(obj, i); - iso9660_stat_t *statbuf =iso9660_find_fs_lsn(obj->img, lsn); - if (NULL != statbuf) { - obj->seg_sizes[i] = statbuf->secsize; - free(statbuf); - } else { - vcd_warn ("Trouble finding ISO 9660 size for segment %d.", i); - } - } - } -#endif - -} - -/*! - Return the number of audio channels implied by "audio_type". - 0 is returned on error. -*/ -unsigned int -vcdinfo_audio_type_num_channels(const vcdinfo_obj_t *obj, - unsigned int audio_type) -{ - const int audio_types[2][5] = - { - { /* VCD 2.0 */ - 0, /* no audio*/ - 1, /* single channel */ - 1, /* stereo */ - 2, /* dual channel */ - 0}, /* error */ - - { /* SVCD, HQVCD */ - 0, /* no stream */ - 1, /* 1 stream */ - 2, /* 2 streams */ - 1, /* 1 multi-channel stream (surround sound) */ - 0} /* error */ - }; - - /* We should also check that the second index is in range too. */ - if (audio_type > 4) { - return 0; - } - - /* Get first index entry into above audio_type array from vcd_type */ - switch (obj->vcd_type) { - - case VCD_TYPE_VCD: - case VCD_TYPE_VCD11: - return 1; - - case VCD_TYPE_VCD2: - return 3; - break; - - case VCD_TYPE_HQVCD: - case VCD_TYPE_SVCD: - return audio_types[1][audio_type]; - break; - - case VCD_TYPE_INVALID: - default: - /* We have an invalid entry. Set to handle below. */ - return 0; - } -} - -/*! - Return a string describing an audio type. -*/ -const char * -vcdinfo_audio_type2str(const vcdinfo_obj_t *obj, unsigned int audio_type) -{ - const char *audio_types[3][5] = - { - /* INVALID, VCD 1.0, or VCD 1.1 */ - { "unknown", "invalid", "", "", "" }, - - /*VCD 2.0 */ - { "no audio", "single channel", "stereo", "dual channel", "error" }, - - /* SVCD, HQVCD */ - { "no stream", "1 stream", "2 streams", - "1 multi-channel stream (surround sound)", "error"}, - }; - - unsigned int first_index = 0; - - /* Get first index entry into above audio_type array from vcd_type */ - switch (obj->vcd_type) { - - case VCD_TYPE_VCD: - case VCD_TYPE_VCD11: - case VCD_TYPE_VCD2: - first_index=1; - break; - - case VCD_TYPE_HQVCD: - case VCD_TYPE_SVCD: - first_index=2; - break; - - case VCD_TYPE_INVALID: - default: - /* We have an invalid entry. Set to handle below. */ - audio_type=4; - } - - /* We should also check that the second index is in range too. */ - if (audio_type > 3) { - first_index=0; - audio_type=1; - } - - return audio_types[first_index][audio_type]; -} - -/*! - Note first seg_num is 0! -*/ -const char * -vcdinfo_ogt2str(const vcdinfo_obj_t *obj, segnum_t seg_num) -{ - const InfoVcd_t *info = &obj->info; - const char *ogt_str[] = - { - "None", - "1 available", - "0 & 1 available", - "all 4 available" - }; - - return ogt_str[info->spi_contents[seg_num].ogt]; -} - - -const char * -vcdinfo_video_type2str(const vcdinfo_obj_t *obj, segnum_t seg_num) -{ - const char *video_types[] = - { - "no stream", - "NTSC still", - "NTSC still (lo+hires)", - "NTSC motion", - "reserved (0x4)", - "PAL still", - "PAL still (lo+hires)", - "PAL motion", - "INVALID ENTRY" - }; - - return video_types[vcdinfo_get_video_type(obj, seg_num)]; -} - -/*! - \brief Classify itemid_num into the kind of item it is: track #, entry #, - segment #. - \param itemid is set to contain this classification an the converted - entry number. -*/ -void -vcdinfo_classify_itemid (uint16_t itemid_num, - /*out*/ vcdinfo_itemid_t *itemid) -{ - - itemid->num = itemid_num; - if (itemid_num < 2) - itemid->type = VCDINFO_ITEM_TYPE_NOTFOUND; - else if (itemid_num < MIN_ENCODED_TRACK_NUM) { - itemid->type = VCDINFO_ITEM_TYPE_TRACK; - itemid->num--; - } else if (itemid_num < 600) { - itemid->type = VCDINFO_ITEM_TYPE_ENTRY; - itemid->num -= MIN_ENCODED_TRACK_NUM; - } else if (itemid_num < MIN_ENCODED_SEGMENT_NUM) - itemid->type = VCDINFO_ITEM_TYPE_LID; - else if (itemid_num <= MAX_ENCODED_SEGMENT_NUM) { - itemid->type = VCDINFO_ITEM_TYPE_SEGMENT; - itemid->num -= (MIN_ENCODED_SEGMENT_NUM); - } else - itemid->type = VCDINFO_ITEM_TYPE_SPAREID2; -} - -const char * -vcdinfo_pin2str (uint16_t itemid_num) -{ - char *buf = _getbuf (); - vcdinfo_itemid_t itemid; - - vcdinfo_classify_itemid(itemid_num, &itemid); - strcpy (buf, "??"); - - switch(itemid.type) { - case VCDINFO_ITEM_TYPE_NOTFOUND: - 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-1, - itemid_num); - break; - case VCDINFO_ITEM_TYPE_ENTRY: - snprintf (buf, BUF_SIZE, "ENTRY[%d] (0x%4.4x)", itemid.num, itemid_num); - break; - case VCDINFO_ITEM_TYPE_SEGMENT: - snprintf (buf, BUF_SIZE, "SEGMENT[%d] (0x%4.4x)", itemid.num, itemid_num); - break; - case VCDINFO_ITEM_TYPE_LID: - snprintf (buf, BUF_SIZE, "spare id (0x%4.4x)", itemid.num); - break; - case VCDINFO_ITEM_TYPE_SPAREID2: - snprintf (buf, BUF_SIZE, "spare id2 (0x%4.4x)", itemid.num); - break; - } - - return buf; -} - -/*! - Return a string containing the VCD album id, or NULL if there is - some problem in getting this. -*/ -const char * -vcdinfo_get_album_id(const vcdinfo_obj_t *obj) -{ - if ( NULL == obj ) return (NULL); - return vcdinf_get_album_id(&obj->info); -} - -/*! - Return the VCD ID. - NULL is returned if there is some problem in getting this. -*/ -char * -vcdinfo_get_application_id(vcdinfo_obj_t *p_obj) -{ - if ( NULL == p_obj ) return (NULL); - return iso9660_get_application_id(&p_obj->pvd); -} - -/*! - Return a pointer to the cdio structure for the CD image opened or - NULL if error. -*/ -CdIo * -vcdinfo_get_cd_image (const vcdinfo_obj_t *vcd_obj) -{ - if (NULL == vcd_obj) return NULL; - return vcd_obj->img; -} - - -/*! - \fn vcdinfo_selection_get_lid(const vcdinfo_obj_t *obj, lid_t lid, - unsigned int selection); - - \brief Get offset of a selection for a given lid. - - Return the LID offset associated with a the selection number of the - passed-in LID parameter. - - \return VCDINFO_INVALID_LID is returned if obj on error or obj - is NULL. Otherwise the LID offset is returned. -*/ -lid_t vcdinfo_selection_get_lid(const vcdinfo_obj_t *obj, lid_t lid, - unsigned int selection) -{ - unsigned int offset; - - if (NULL == obj) return VCDINFO_INVALID_LID; - - offset = vcdinfo_selection_get_offset(obj, lid, selection); - switch (offset) { - case VCDINFO_INVALID_OFFSET: - case PSD_OFS_MULTI_DEF: - case PSD_OFS_MULTI_DEF_NO_NUM: - return VCDINFO_INVALID_LID; - default: - { - vcdinfo_offset_t *ofs = vcdinfo_get_offset_t(obj, offset); - return ofs->lid; - } - } -} - -/*! - \fn vcdinfo_selection_get_offset(const vcdinfo_obj_t *obj, lid_t lid, - unsigned int selection); - - \brief Get offset of a selection for a given lid. - - Return the LID offset associated with a the selection number of the - passed-in LID parameter. - - \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_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) { - return vcdinfo_lid_get_offset(obj, lid, selection-bsn+1); - } else { - vcd_warn( "Selection number %u too small. bsn %u", selection, bsn ); - return VCDINFO_INVALID_OFFSET; - } -} - -/** - \fn vcdinfo_get_default_offset(const vcdinfo_obj_t *obj, unsinged int lid); - \brief Get return offset for a given PLD selector descriptor. - \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 -vcdinfo_get_default_offset(const vcdinfo_obj_t *obj, lid_t lid) -{ - if (NULL != obj) { - - PsdListDescriptor_t pxd; - - vcdinfo_lid_get_pxd(obj, &pxd, lid); - - switch (pxd.descriptor_type) { - case PSD_TYPE_EXT_SELECTION_LIST: - case PSD_TYPE_SELECTION_LIST: - return vcdinf_psd_get_default_offset(pxd.psd); - break; - case PSD_TYPE_PLAY_LIST: - case PSD_TYPE_END_LIST: - case PSD_TYPE_COMMAND_LIST: - break; - } - } - return VCDINFO_INVALID_OFFSET; -} - -/*! - \brief Get default or multi-default LID. - - Return the LID offset associated with a the "default" entry of the - passed-in LID parameter. Note "default" entries are associated - with PSDs that are (extended) selection lists. If the "default" - offset is a multi-default, we use entry_num to find the proper - "default" LID. Otherwise this routine is exactly like - vcdinfo_get_default_lid with the exception of requiring an - additional "entry_num" parameter. - - \return VCDINFO_INVALID_LID is returned on error, or if the LID - is not a selection list or no "default" entry. Otherwise the LID - offset is returned. -*/ -lid_t -vcdinfo_get_multi_default_lid(const vcdinfo_obj_t *obj, lid_t lid, - lsn_t lsn) -{ - 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: - case PSD_OFS_MULTI_DEF_NO_NUM: - return VCDINFO_INVALID_LID; - default: - { - vcdinfo_offset_t *ofs = vcdinfo_get_offset_t(obj, offset); - return ofs->lid; - } - } -} - -/*! - \brief Get default or multi-default LID offset. - - Return the LID offset associated with a the "default" entry of the - passed-in LID parameter. Note "default" entries are associated - with PSDs that are (extended) selection lists. If the "default" - offset is a multi-default, we use entry_num to find the proper - "default" offset. Otherwise this routine is exactly like - vcdinfo_get_default_offset with the exception of requiring an - additional "entry_num" parameter. - - \return VCDINFO_INVALID_OFFSET is returned on error, or if the LID - is not a selection list or no "default" entry. Otherwise the LID - offset is returned. -*/ -uint16_t -vcdinfo_get_multi_default_offset(const vcdinfo_obj_t *obj, lid_t lid, - unsigned int entry_num) -{ - uint16_t offset=vcdinfo_get_default_offset(obj, lid); - - switch (offset) { - case PSD_OFS_MULTI_DEF: - case PSD_OFS_MULTI_DEF_NO_NUM: - { - /* Have some work todo... Figure the selection number. */ - 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: ; - } - } - default: - return VCDINFO_INVALID_OFFSET; - } -} - -/*! - Return a string containing the default VCD device if none is specified. - Return NULL we can't get this information. -*/ -char * -vcdinfo_get_default_device (const vcdinfo_obj_t *vcd_obj) -{ - - /* If device not already open, then we'll open it temporarily and - let CdIo select a driver, get the default for that and then - close/destroy the temporary we created. - */ - CdIo *cdio=NULL; - if (vcd_obj != NULL && vcd_obj->img != NULL) - cdio = vcd_obj->img; - - return cdio_get_default_device(cdio); -} - -/*! - Return number of sector units in of an entry. 0 is returned if entry_num - is out of range. - The first entry number is 0. -*/ -uint32_t -vcdinfo_get_entry_sect_count (const vcdinfo_obj_t *obj, unsigned int entry_num) -{ - const EntriesVcd_t *entries = &obj->entries; - const unsigned int entry_count = vcdinf_get_num_entries(entries); - if (entry_num > entry_count) - return 0; - else { - const lsn_t this_lsn = vcdinfo_get_entry_lsn(obj, entry_num); - lsn_t next_lsn; - if (entry_num < entry_count-1) { - track_t track=vcdinfo_get_track(obj, entry_num); - track_t next_track=vcdinfo_get_track(obj, entry_num+1); - next_lsn = vcdinfo_get_entry_lsn(obj, entry_num+1); - /* If we've changed tracks, don't include pregap sector between - tracks. - */ - if (track != next_track) next_lsn -= CDIO_PREGAP_SECTORS; - } else { - /* entry_num == entry_count -1. Or the last entry. - This is really really ugly. There's probably a better - way to do it. - Below we get the track of the current entry and then the LBA of the - beginning of the following (leadout?) track. - - Wait! It's uglier than that! Since VCD's can be created - *without* a pregap to the leadout track, we try not to use - that if we can get the entry from the ISO 9660 filesystem. - */ - track_t track = vcdinfo_get_track(obj, entry_num); - if (track != VCDINFO_INVALID_TRACK) { - iso9660_stat_t *statbuf; - const lsn_t lsn = vcdinfo_get_track_lsn(obj, track); - - /* Try to get the sector count from the ISO 9660 filesystem */ - statbuf = iso9660_find_fs_lsn(obj->img, lsn); - - if (NULL != statbuf) { - next_lsn = lsn + statbuf->secsize; - free(statbuf); - } else { - /* Failed on ISO 9660 filesystem. Use next track or - LEADOUT track. */ - next_lsn = vcdinfo_get_track_lsn(obj, track+1); - } - if (next_lsn == VCDINFO_NULL_LSN) - return 0; - } else { - /* Something went wrong. Set up size to zero. */ - return 0; - } - } - return (next_lsn - this_lsn); - } -} - -/*! Return the starting MSF (minutes/secs/frames) for sequence - entry_num in obj. NULL is returned if there is no entry. - The first entry number is 0. -*/ -const msf_t * -vcdinfo_get_entry_msf(const vcdinfo_obj_t *obj, unsigned int entry_num) -{ - const EntriesVcd_t *entries = &obj->entries; - return vcdinf_get_entry_msf(entries, entry_num); -} - -/*! Return the starting LBA (logical block address) for sequence - entry_num in obj. VCDINFO_NULL_LBA is returned if there is no entry. -*/ -lba_t -vcdinfo_get_entry_lba(const vcdinfo_obj_t *obj, unsigned int entry_num) -{ - if ( NULL == obj ) return VCDINFO_NULL_LBA; - else { - const msf_t *msf = vcdinfo_get_entry_msf(obj, entry_num); - msf = vcdinfo_get_entry_msf(obj, entry_num); - return (msf != NULL) ? cdio_msf_to_lba(msf) : VCDINFO_NULL_LBA; - } -} - -/*! Return the starting LBA (logical block address) for sequence - entry_num in obj. VCDINFO_NULL_LBA is returned if there is no entry. -*/ -lsn_t -vcdinfo_get_entry_lsn(const vcdinfo_obj_t *obj, unsigned int entry_num) -{ - if ( NULL == obj ) return VCDINFO_NULL_LBA; - else { - const msf_t *msf = vcdinfo_get_entry_msf(obj, entry_num); - return (msf != NULL) ? cdio_msf_to_lsn(msf) : VCDINFO_NULL_LSN; - } -} - -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. -*/ -vcd_type_t -vcdinfo_get_format_version (vcdinfo_obj_t *obj) -{ - return obj->vcd_type; -} - -/*! - Return a string giving VCD format (VCD 1.0 VCD 1.1, SVCD, ... - for this object. -*/ -const char * -vcdinfo_get_format_version_str (const vcdinfo_obj_t *obj) -{ - if (NULL == obj) return "*Uninitialized*"; - return vcdinf_get_format_version_str(obj->vcd_type); -} - -InfoVcd_t * -vcdinfo_get_infoVcd (vcdinfo_obj_t *obj) -{ - if (NULL == obj) return NULL; - return &obj->info; -} - -/*! Return the entry number closest and before the given LSN. - */ -unsigned int -vcdinfo_lsn_get_entry(const vcdinfo_obj_t *obj, lsn_t lsn) -{ - - /* 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_pvd (vcdinfo_obj_t *obj) -{ - if (NULL == obj) return NULL; - return &obj->pvd; -} - -void * -vcdinfo_get_scandata (vcdinfo_obj_t *obj) -{ - if (NULL == obj) return NULL; - return obj->scandata_buf; -} - -void * -vcdinfo_get_searchDat (vcdinfo_obj_t *obj) -{ - if (NULL == obj) return NULL; - return obj->search_buf; -} - -void * -vcdinfo_get_tracksSVD (vcdinfo_obj_t *obj) -{ - if (NULL == obj) return NULL; - return obj->tracks_buf; -} - -/*! - Get the itemid for a given list ID. - VCDINFO_REJECTED_MASK is returned on error or if obj is NULL. -*/ -uint16_t -vcdinfo_lid_get_itemid(const vcdinfo_obj_t *obj, lid_t lid) -{ - PsdListDescriptor_t pxd; - - if (obj == NULL) return VCDINFO_REJECTED_MASK; - vcdinfo_lid_get_pxd(obj, &pxd, lid); - switch (pxd.descriptor_type) { - case PSD_TYPE_SELECTION_LIST: - case PSD_TYPE_EXT_SELECTION_LIST: - if (pxd.psd == NULL) return VCDINFO_REJECTED_MASK; - return vcdinf_psd_get_itemid(pxd.psd); - break; - case PSD_TYPE_PLAY_LIST: - /* FIXME: There is an array of items */ - case PSD_TYPE_END_LIST: - case PSD_TYPE_COMMAND_LIST: - return VCDINFO_REJECTED_MASK; - } - - return VCDINFO_REJECTED_MASK; - -} - -/*! - Get the LOT pointer. -*/ -LotVcd_t * -vcdinfo_get_lot(const vcdinfo_obj_t *obj) -{ - if (NULL == obj) return NULL; - return obj->lot; -} - -/*! - Get the extended LOT pointer. -*/ -LotVcd_t * -vcdinfo_get_lot_x(const vcdinfo_obj_t *obj) -{ - if (NULL == obj) return NULL; - return obj->lot_x; -} - -/*! - Return number of LIDs. -*/ -lid_t -vcdinfo_get_num_LIDs (const vcdinfo_obj_t *obj) -{ - /* Should probably use _vcd_pbc_max_lid instead? */ - if (NULL==obj) return 0; - return vcdinf_get_num_LIDs(&obj->info); -} - -/*! - Return the number of entries in the VCD. -*/ -unsigned int -vcdinfo_get_num_entries(const vcdinfo_obj_t *obj) -{ - const EntriesVcd_t *entries = &obj->entries; - return vcdinf_get_num_entries(entries); -} - -/*! - Return the number of segments in the VCD. Return 0 if there is some - problem. -*/ -segnum_t -vcdinfo_get_num_segments(const vcdinfo_obj_t *obj) -{ - if (NULL==obj) return 0; - return vcdinf_get_num_segments(&obj->info); -} - -/*! - \fn vcdinfo_get_offset_lid(const vcdinfo_obj_t *obj, unsigned int entry_num); - \brief Get offset entry_num for a given LID. - \return VCDINFO_INVALID_OFFSET is returned if obj on error or obj - is NULL. Otherwise the LID offset is returned. -*/ -uint16_t -vcdinfo_lid_get_offset(const vcdinfo_obj_t *obj, lid_t lid, - unsigned int entry_num) -{ - PsdListDescriptor_t pxd; - - if (obj == NULL) return VCDINFO_INVALID_OFFSET; - vcdinfo_lid_get_pxd(obj, &pxd, lid); - - switch (pxd.descriptor_type) { - case PSD_TYPE_SELECTION_LIST: - case PSD_TYPE_EXT_SELECTION_LIST: - if (pxd.psd == NULL) return VCDINFO_INVALID_OFFSET; - return vcdinf_psd_get_offset(pxd.psd, entry_num-1); - break; - case PSD_TYPE_PLAY_LIST: - /* FIXME: There is an array of items */ - case PSD_TYPE_END_LIST: - case PSD_TYPE_COMMAND_LIST: - return VCDINFO_INVALID_OFFSET; - } - return VCDINFO_INVALID_OFFSET; - -} - -/*! - NULL is returned on error. -*/ -static vcdinfo_offset_t * -_vcdinfo_get_offset_t (const vcdinfo_obj_t *obj, unsigned int offset, bool ext) -{ - CdioListNode *node; - CdioList *offset_list = ext ? obj->offset_x_list : obj->offset_list; - - switch (offset) { - case PSD_OFS_DISABLED: - case PSD_OFS_MULTI_DEF: - case PSD_OFS_MULTI_DEF_NO_NUM: - return NULL; - default: ; - } - - _CDIO_LIST_FOREACH (node, offset_list) - { - vcdinfo_offset_t *ofs = _cdio_list_node_data (node); - if (offset == ofs->offset) - return ofs; - } - return NULL; -} - -/*! - Get the VCD info list. -*/ -CdioList * -vcdinfo_get_offset_list(const vcdinfo_obj_t *obj) -{ - if (NULL == obj) return NULL; - return obj->offset_list; -} - - -/*! - Get the VCD info extended offset list. -*/ -CdioList * -vcdinfo_get_offset_x_list(const vcdinfo_obj_t *obj) -{ - if (NULL == obj) return NULL; - return obj->offset_x_list; -} - -/*! - Get the VCD info offset multiplier. -*/ -unsigned int vcdinfo_get_offset_mult(const vcdinfo_obj_t *obj) -{ - if (NULL == obj) return 0xFFFF; - return obj->info.offset_mult; -} - -/*! - Get entry in offset list for the item that has offset. This entry - has for example the LID. NULL is returned on error. -*/ -vcdinfo_offset_t * -vcdinfo_get_offset_t (const vcdinfo_obj_t *obj, unsigned int offset) -{ - vcdinfo_offset_t *off_p= _vcdinfo_get_offset_t (obj, offset, true); - if (NULL != off_p) - return off_p; - return _vcdinfo_get_offset_t (obj, offset, false); -} - -/*! - Return a string containing the VCD publisher id with trailing - blanks removed, or NULL if there is some problem in getting this. -*/ -const char * -vcdinfo_get_preparer_id(const vcdinfo_obj_t *obj) -{ - if ( NULL == obj ) return (NULL); - return iso9660_get_preparer_id(&obj->pvd); -} - -/*! - Get the PSD. -*/ -uint8_t * -vcdinfo_get_psd(const vcdinfo_obj_t *obj) -{ - if ( NULL == obj ) return (NULL); - return obj->psd; -} - -/*! - Get the extended PSD. -*/ -uint8_t * -vcdinfo_get_psd_x(const vcdinfo_obj_t *obj) -{ - if ( NULL == obj ) return (NULL); - return obj->psd_x; -} - -/*! - Return number of bytes in PSD. Return 0 if there's an error. -*/ -uint32_t -vcdinfo_get_psd_size (const vcdinfo_obj_t *obj) -{ - if ( NULL == obj ) return 0; - return vcdinf_get_psd_size(&obj->info); -} - -/*! - Return number of bytes in the extended PSD. Return 0 if there's an error. -*/ -uint32_t -vcdinfo_get_psd_x_size (const vcdinfo_obj_t *obj) -{ - if ( NULL == obj ) return 0; - return obj->psd_x_size; -} - -/*! - Return a string containing the VCD publisher id with trailing - blanks removed, or NULL if there is some problem in getting this. -*/ -char * -vcdinfo_get_publisher_id(const vcdinfo_obj_t *obj) -{ - if ( NULL == obj ) return (NULL); - return iso9660_get_publisher_id(&obj->pvd); -} - -/*! - Get the PSD Selection List Descriptor for a given lid. - NULL is returned if error or not found. -*/ -static bool -_vcdinfo_lid_get_pxd(const vcdinfo_obj_t *obj, PsdListDescriptor_t *pxd, - uint16_t lid, bool ext) -{ - CdioListNode *node; - unsigned mult = obj->info.offset_mult; - const uint8_t *psd = ext ? obj->psd_x : obj->psd; - CdioList *offset_list = ext ? obj->offset_x_list : obj->offset_list; - - if (offset_list == NULL) return false; - - _CDIO_LIST_FOREACH (node, offset_list) - { - vcdinfo_offset_t *ofs = _cdio_list_node_data (node); - unsigned _rofs = ofs->offset * mult; - - pxd->descriptor_type = psd[_rofs]; - - switch (pxd->descriptor_type) - { - case PSD_TYPE_PLAY_LIST: - { - pxd->pld = (PsdPlayListDescriptor_t *) (psd + _rofs); - if (vcdinf_pld_get_lid(pxd->pld) == lid) { - return true; - } - break; - } - - case PSD_TYPE_EXT_SELECTION_LIST: - case PSD_TYPE_SELECTION_LIST: - { - pxd->psd = (PsdSelectionListDescriptor_t *) (psd + _rofs); - if (vcdinf_psd_get_lid(pxd->psd) == lid) { - return true; - } - break; - } - default: ; - } - } - return false; -} - -/*! - 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_t *pxd, - uint16_t lid) -{ - if (_vcdinfo_lid_get_pxd(obj, pxd, lid, true)) - return true; - return _vcdinfo_lid_get_pxd(obj, pxd, lid, false); -} - -/** - \fn vcdinfo_get_return_offset(const vcdinfo_obj_t *obj); - \brief Get return offset for a given LID. - \return VCDINFO_INVALID_OFFSET is returned on error or if LID has no - "return" entry. Otherwise the LID offset is returned. - */ -uint16_t -vcdinfo_get_return_offset(const vcdinfo_obj_t *obj, lid_t lid) -{ - if (NULL != obj) { - - PsdListDescriptor_t pxd; - - vcdinfo_lid_get_pxd(obj, &pxd, lid); - - switch (pxd.descriptor_type) { - case PSD_TYPE_PLAY_LIST: - return vcdinf_pld_get_return_offset(pxd.pld); - case PSD_TYPE_SELECTION_LIST: - case PSD_TYPE_EXT_SELECTION_LIST: - return vcdinf_psd_get_return_offset(pxd.psd); - break; - case PSD_TYPE_END_LIST: - case PSD_TYPE_COMMAND_LIST: - break; - } - } - - return VCDINFO_INVALID_OFFSET; -} - -/*! - Return the audio type for a given segment. - VCDINFO_INVALID_AUDIO_TYPE is returned on error. -*/ -unsigned int -vcdinfo_get_seg_audio_type(const vcdinfo_obj_t *obj, segnum_t seg_num) -{ - if ( NULL == obj || NULL == &obj->info - || seg_num >= vcdinfo_get_num_segments(obj) ) - return VCDINFO_INVALID_AUDIO_TYPE; - return(obj->info.spi_contents[seg_num].audio_type); -} - -/*! - Return true if this segment is supposed to continue to the next one, - (is part of an "item" or listing in the ISO 9660 filesystem). -*/ -bool -vcdinfo_get_seg_continue(const vcdinfo_obj_t *obj, segnum_t seg_num) -{ - if ( NULL == obj || NULL == &obj->info - || seg_num >= vcdinfo_get_num_segments(obj) ) - return false; - return(obj->info.spi_contents[seg_num].item_cont); -} - -/*! Return the starting LBA (logical block address) for segment - entry_num in obj. VCDINFO_LBA_NULL is returned if there is no entry. - - Note first seg_num is 0. -*/ -lba_t -vcdinfo_get_seg_lba(const vcdinfo_obj_t *obj, segnum_t seg_num) -{ - if (obj == NULL) return VCDINFO_NULL_LBA; - return cdio_lsn_to_lba(vcdinfo_get_seg_lba(obj, seg_num)); -} - -/*! Return the starting LBA (logical block address) for segment - entry_num in obj. VCDINFO_LSN_NULL is returned if there is no entry. - - Note first seg_num is 0. -*/ -lsn_t -vcdinfo_get_seg_lsn(const vcdinfo_obj_t *obj, segnum_t seg_num) -{ - if (obj == NULL || seg_num >= vcdinfo_get_num_segments(obj)) - return VCDINFO_NULL_LSN; - return obj->first_segment_lsn + (VCDINFO_SEGMENT_SECTOR_SIZE * seg_num); -} - -/*! Return the starting MSF (minutes/secs/frames) for segment - entry_num in obj. NULL is returned if there is no entry. - - Note first seg_num is 0! -*/ -const msf_t * -vcdinfo_get_seg_msf(const vcdinfo_obj_t *obj, segnum_t seg_num) -{ - if (obj == NULL || seg_num >= vcdinfo_get_num_segments(obj)) - return NULL; - else { - lsn_t lsn = vcdinfo_get_seg_lsn(obj, seg_num); - static msf_t msf; - cdio_lsn_to_msf(lsn, &msf); - return &msf; - } -} - -/*! Return the x-y resolution for a given segment. - Note first i_seg is 0. -*/ -void -vcdinfo_get_seg_resolution(const vcdinfo_obj_t *p_vcdinfo, segnum_t i_seg, - /*out*/ uint16_t *max_x, /*out*/ uint16_t *max_y) -{ - vcdinfo_video_segment_type_t segtype - = vcdinfo_get_video_type(p_vcdinfo, i_seg); - segnum_t i_segs = vcdinfo_get_num_segments(p_vcdinfo); - - if (i_seg >= i_segs) return; - - switch (segtype) { - case VCDINFO_FILES_VIDEO_NTSC_STILL: - *max_x = 704; - *max_y = 480; - break; - case VCDINFO_FILES_VIDEO_NTSC_STILL2: - *max_x = 352; - *max_y = 240; - break; - case VCDINFO_FILES_VIDEO_PAL_STILL: - *max_x = 704; - *max_y = 576; - break; - case VCDINFO_FILES_VIDEO_PAL_STILL2: - *max_x = 352; - *max_y = 288; - break; - default: - /* */ - switch (vcdinfo_get_format_version(p_vcdinfo)) { - case VCD_TYPE_VCD: - *max_x = 352; - *max_y = 240; - break; - case VCD_TYPE_VCD11: - case VCD_TYPE_VCD2: - *max_x = 352; - switch(segtype) { - case VCDINFO_FILES_VIDEO_NTSC_MOTION: - *max_y = 240; - break; - case VCDINFO_FILES_VIDEO_PAL_MOTION: - *max_y = 288; - default: - *max_y = 289; - } - break; - default: ; - } - } -} - - - -/*! - Return the number of sectors for segment - entry_num in obj. 0 is returned if there is no entry. - - Use this routine to figure out the actual number of bytes a physical - region of a disk or CD takes up for a segment. - - If an item has been broken up into a number of "continued" segments, - we will report the item size for the first segment and 0 for the - remaining ones. We may revisit this decision later. -*/ -uint32_t -vcdinfo_get_seg_sector_count(const vcdinfo_obj_t *obj, segnum_t seg_num) -{ - if (obj == NULL || seg_num >= vcdinfo_get_num_segments(obj)) - return 0; - return obj->seg_sizes[seg_num]; -} - -/*! - Return a string containing the VCD system id with trailing - blanks removed, or NULL if there is some problem in getting this. -*/ -const char * -vcdinfo_get_system_id(const vcdinfo_obj_t *obj) -{ - if ( NULL == obj || NULL == &obj->pvd ) return (NULL); - return(iso9660_get_system_id(&obj->pvd)); -} - -/*! - Return the track number for entry n in obj. - - In contrast to libcdio we start numbering at 0 which is the - ISO9660 and metadata information for the Video CD. Thus track - 1 is the first track the first complete MPEG track generally. -*/ -track_t -vcdinfo_get_track(const vcdinfo_obj_t *obj, const unsigned int entry_num) -{ - 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 ? - vcdinf_get_track(entries, entry_num)-1: VCDINFO_INVALID_TRACK; -} - -/*! - Return the audio type for a given track. - VCDINFO_INVALID_AUDIO_TYPE is returned on error. - - Note: track 1 is usually the first track. -*/ -unsigned int -vcdinfo_get_track_audio_type(const vcdinfo_obj_t *obj, track_t track_num) -{ - TracksSVD *tracks; - TracksSVD2 *tracks2; - if ( NULL == obj || NULL == &obj->info ) return VCDINFO_INVALID_AUDIO_TYPE; - tracks = obj->tracks_buf; - - if ( NULL == tracks ) return 0; - tracks2 = (TracksSVD2 *) &(tracks->playing_time[tracks->tracks]); - return(tracks2->contents[track_num-1].audio); -} - -/*! - Return the highest track number in the current medium. - - Because we track start numbering at 0 (which is the ISO 9660 track - containing Video CD naviagion and disk information), this is one - less than the number of tracks. - - If there are no tracks, we return -1. -*/ -unsigned int -vcdinfo_get_num_tracks(const vcdinfo_obj_t *obj) -{ - if (obj == NULL || obj->img == NULL) return 0; - - return cdio_get_num_tracks(obj->img)-1; -} - - -/*! - Return the starting LBA (logical block address) for track number - track_num in obj. - - The IS0-9660 filesystem track has number 0. Tracks associated - with playable entries numbers start at 1. - - The "leadout" track is specified either by - using track_num LEADOUT_TRACK or the total tracks+1. - VCDINFO_NULL_LBA is returned on failure. -*/ -lba_t -vcdinfo_get_track_lba(const vcdinfo_obj_t *obj, track_t track_num) -{ - if (NULL == obj || NULL == obj->img) - return VCDINFO_NULL_LBA; - - - /* CdIo tracks start at 1 rather than 0. */ - return cdio_get_track_lba(obj->img, track_num+1); -} - -/*! - Return the starting LSN (logical sector number) for track number - track_num in obj. - - The IS0-9660 filesystem track has number 0. Tracks associated - with playable entries numbers start at 1. - - The "leadout" track is specified either by - using track_num LEADOUT_TRACK or the total tracks+1. - VCDINFO_NULL_LBA is returned on failure. -*/ -lsn_t -vcdinfo_get_track_lsn(const vcdinfo_obj_t *obj, track_t track_num) -{ - if (NULL == obj || NULL == obj->img) - return VCDINFO_NULL_LSN; - - /* CdIo tracks start at 1 rather than 0. */ - return cdio_get_track_lsn(obj->img, track_num+1); -} - -/*! - Return the starting MSF (minutes/secs/frames) for track number - track_num in obj. - - The IS0-9660 filesystem track has number 0. Tracks associated - with playable entries numbers start at 1. - - The "leadout" track is specified either by - using track_num LEADOUT_TRACK or the total tracks+1. - VCDINFO_NULL_LBA is returned on failure. -*/ -int -vcdinfo_get_track_msf(const vcdinfo_obj_t *obj, track_t track_num, - uint8_t *min, uint8_t *sec, uint8_t *frame) -{ - msf_t msf; - - if (NULL == obj || NULL == obj->img) - return 1; - - /* CdIo tracks start at 1 rather than 0. */ - if (cdio_get_track_msf(obj->img, track_num+1, &msf)) { - *min = cdio_from_bcd8(msf.m); - *sec = cdio_from_bcd8(msf.s); - *frame = cdio_from_bcd8(msf.f); - return 0; - } - - return 1; -} - -/*! - Return the size in sectors for track n. - - The IS0-9660 filesystem track has number 0. Tracks associated - with playable entries numbers start at 1. - - FIXME: Whether we count the track pregap sectors is a bit haphazard. - We should add a parameter to indicate whether this is wanted or not. - -*/ -unsigned int -vcdinfo_get_track_sect_count(const vcdinfo_obj_t *obj, const track_t track_num) -{ - if (NULL == obj || VCDINFO_INVALID_TRACK == track_num) - return 0; - - { - iso9660_stat_t *statbuf; - const lsn_t lsn = vcdinfo_get_track_lsn(obj, track_num); - - /* Try to get the sector count from the ISO 9660 filesystem */ - if (obj->has_xa && (statbuf = iso9660_find_fs_lsn(obj->img, lsn))) { - unsigned int secsize = statbuf->secsize; - free(statbuf); - return secsize; - } else { - const lsn_t next_lsn=vcdinfo_get_track_lsn(obj, track_num+1); - /* Failed on ISO 9660 filesystem. Use track information. */ - return next_lsn > lsn ? next_lsn - lsn : 0; - } - } - return 0; -} - -/*! - Return size in bytes for track number for entry n in obj. - - The IS0-9660 filesystem track has number 1. Tracks associated - with playable entries numbers start at 2. - - FIXME: Whether we count the track pregap sectors is a bit haphazard. - We should add a parameter to indicate whether this is wanted or not. -*/ -unsigned int -vcdinfo_get_track_size(const vcdinfo_obj_t *obj, track_t track_num) -{ - if (NULL == obj || VCDINFO_INVALID_TRACK == track_num) - return 0; - - { - iso9660_stat_t statbuf; - const lsn_t lsn = cdio_lba_to_lsn(vcdinfo_get_track_lba(obj, track_num)); - - /* Try to get the sector count from the ISO 9660 filesystem */ - if (obj->has_xa && iso9660_find_fs_lsn(obj->img, lsn)) { - return statbuf.size; - } -#if 0 - else { - /* Failed on ISO 9660 filesystem. Use track information. */ - if (obj->img != NULL) - return cdio_get_track_size(obj->img); - } -#endif - } - return 0; -} - -/*! - \brief Get the kind of video stream segment of segment seg_num in obj. - \return VCDINFO_FILES_VIDEO_INVALID is returned if on error or obj is - null. Otherwise the enumeration type. - - Note first seg_num is 0! -*/ -vcdinfo_video_segment_type_t -vcdinfo_get_video_type(const vcdinfo_obj_t *obj, segnum_t seg_num) -{ - const InfoVcd_t *info; - if (obj == NULL) return VCDINFO_FILES_VIDEO_INVALID; - info = &obj->info; - if (info == NULL) return VCDINFO_FILES_VIDEO_INVALID; - return info->spi_contents[seg_num].video_type; -} - -/*! - \brief Get the kind of VCD that obj refers to. -*/ -vcd_type_t -vcdinfo_get_VCD_type(const vcdinfo_obj_t *obj) -{ - if (NULL == obj) return VCD_TYPE_INVALID; - return obj->vcd_type; -} - - -/*! - Return the VCD volume count - the number of CD's in the collection. - O is returned if there is some problem in getting this. -*/ -unsigned int -vcdinfo_get_volume_count(const vcdinfo_obj_t *obj) -{ - if ( NULL == obj ) return 0; - return vcdinf_get_volume_count(&obj->info); -} - -/*! - Return the VCD ID. - NULL is returned if there is some problem in getting this. -*/ -const char * -vcdinfo_get_volume_id(const vcdinfo_obj_t *obj) -{ - if ( NULL == obj || NULL == &obj->pvd ) return (NULL); - return(iso9660_get_volume_id(&obj->pvd)); -} - -/*! - Return the VCD volumeset ID. - NULL is returned if there is some problem in getting this. -*/ -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, ISO_MAX_VOLUMESET_ID)); -} - -/*! - Return the VCD volume num - the number of the CD in the collection. - This is a number between 1 and the volume count. - O is returned if there is some problem in getting this. -*/ -unsigned int -vcdinfo_get_volume_num(const vcdinfo_obj_t *obj) -{ - if ( NULL == obj ) return 0; - return(uint16_from_be( obj->info.vol_id)); -} - -int -vcdinfo_get_wait_time (uint16_t wtime) -{ - /* Note: this doesn't agree exactly with _wtime */ - if (wtime < 61) - return wtime; - else if (wtime < 255) - return (wtime - 60) * 10 + 60; - else - return -1; -} - -/*! - Return true is there is playback control. -*/ -bool -vcdinfo_has_pbc (const vcdinfo_obj_t *obj) -{ - return (obj && obj->info.psd_size!=0); -} - -/*! - Return true if VCD has "extended attributes" (XA). Extended attributes - add meta-data attributes to a entries of file describing the file. - See also cdio_get_xa_attr_str() which returns a string similar to - a string you might get on a Unix filesystem listing ("ls"). -*/ -bool -vcdinfo_has_xa(const vcdinfo_obj_t *obj) -{ - return obj->has_xa; -} - -/*! - Add one to the MSF. -*/ -void -vcdinfo_inc_msf (uint8_t *min, uint8_t *sec, int8_t *frame) -{ - (*frame)++; - if (*frame>=CDIO_CD_FRAMES_PER_SEC) { - *frame = 0; - (*sec)++; - if (*sec>=CDIO_CD_SECS_PER_MIN) { - *sec = 0; - (*min)++; - } - } -} - -/*! - Convert minutes, seconds and frame (MSF components) into a - logical block address (or LBA). - See also cdio_msf_to_lba which uses msf_t as its single parameter. -*/ -lba_t -vcdinfo_msf2lba (uint8_t min, uint8_t sec, int8_t frame) -{ - return CDIO_CD_FRAMES_PER_SEC*(CDIO_CD_SECS_PER_MIN*min + sec) + frame; -} - -/*! - Convert minutes, seconds and frame (MSF components) into a - logical block address (or LBA). - See also cdio_msf_to_lba which uses msf_t as its single parameter. -*/ -void -vcdinfo_lba2msf (lba_t lba, uint8_t *min, uint8_t *sec, uint8_t *frame) -{ - *min = lba / (60*75); - lba %= (60*75); - *sec = lba / 75; - *frame = lba % 75; -} - -/*! - Convert minutes, seconds and frame (MSF components) into a - logical sector number (or LSN). -*/ -lsn_t -vcdinfo_msf2lsn (uint8_t min, uint8_t sec, int8_t frame) -{ - lba_t lba=75*(60*min + sec) + frame; - if (lba < CDIO_PREGAP_SECTORS) { - vcd_error ("lba (%u) less than pregap sector (%u)", - (unsigned int) lba, CDIO_PREGAP_SECTORS); - return lba; - } - return lba - CDIO_PREGAP_SECTORS; -} - -const char * -vcdinfo_ofs2str (const vcdinfo_obj_t *obj, unsigned int offset, bool ext) -{ - vcdinfo_offset_t *ofs; - char *buf; - - switch (offset) { - case PSD_OFS_DISABLED: - return "disabled"; - case PSD_OFS_MULTI_DEF: - return "multi-default"; - case PSD_OFS_MULTI_DEF_NO_NUM: - return "multi_def_no_num"; - default: ; - } - - buf = _getbuf (); - ofs = _vcdinfo_get_offset_t(obj, offset, ext); - if (ofs != NULL) { - if (ofs->lid) - snprintf (buf, BUF_SIZE, "LID[%d] @0x%4.4x", - ofs->lid, ofs->offset); - else - snprintf (buf, BUF_SIZE, "PSD[?] @0x%4.4x", - ofs->offset); - } else { - snprintf (buf, BUF_SIZE, "? @0x%4.4x", offset); - } - return buf; -} - -bool -vcdinfo_read_psd (vcdinfo_obj_t *obj) -{ - unsigned psd_size = vcdinfo_get_psd_size (obj); - - if (psd_size) - { - if (psd_size > 256*1024) - { - vcd_error ("weird psd size (%u) -- aborting", psd_size); - return false; - } - - obj->lot = _vcd_malloc (ISO_BLOCKSIZE * LOT_VCD_SIZE); - obj->psd = _vcd_malloc (ISO_BLOCKSIZE * _vcd_len2blocks (psd_size, - ISO_BLOCKSIZE)); - - if (cdio_read_mode2_sectors (obj->img, (void *) obj->lot, LOT_VCD_SECTOR, - false, LOT_VCD_SIZE)) - return false; - - if (cdio_read_mode2_sectors (obj->img, (void *) obj->psd, PSD_VCD_SECTOR, - false, _vcd_len2blocks (psd_size, - ISO_BLOCKSIZE))) - return false; - - } else { - return false; - } - 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. - - Returns false if there was some error. -*/ -bool -vcdinfo_visit_lot (vcdinfo_obj_t *obj, bool extended) -{ - struct _vcdinf_pbc_ctx pbc_ctx; - bool ret; - - pbc_ctx.psd_size = vcdinfo_get_psd_size (obj); - pbc_ctx.psd_x_size = obj->psd_x_size; - pbc_ctx.offset_mult = 8; - pbc_ctx.maximum_lid = vcdinfo_get_num_LIDs(obj); - pbc_ctx.offset_x_list = NULL; - pbc_ctx.offset_list = NULL; - pbc_ctx.psd = obj->psd; - pbc_ctx.psd_x = obj->psd_x; - pbc_ctx.lot = obj->lot; - pbc_ctx.lot_x = obj->lot_x; - pbc_ctx.extended = extended; - - ret = vcdinf_visit_lot(&pbc_ctx); - if (NULL != obj->offset_x_list) - _cdio_list_free(obj->offset_x_list, true); - obj->offset_x_list = pbc_ctx.offset_x_list; - if (NULL != obj->offset_list) - _cdio_list_free(obj->offset_list, true); - obj->offset_list = pbc_ctx.offset_list; - return ret; -} - -/*! - Change trailing blanks in str to nulls. Str has a maximum size of - n characters. -*/ -const char * -vcdinfo_strip_trail (const char str[], size_t n) -{ - static char buf[1025]; - int j; - - vcd_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; -} - -/*! - Return true if offset is "rejected". That is shouldn't be displayed - in a list of entries. -*/ -bool -vcdinfo_is_rejected(uint16_t offset) -{ - return (offset & VCDINFO_REJECTED_MASK) != 0; -} - -/*! - Nulls/zeros vcdinfo_obj_t structures; The caller should have - ensured that obj != NULL. - routines using obj are called. -*/ -static void -_vcdinfo_zero(vcdinfo_obj_t *obj) -{ - memset(obj, 0, sizeof(vcdinfo_obj_t)); - obj->vcd_type = VCD_TYPE_INVALID; - obj->img = NULL; - obj->lot = NULL; - obj->source_name = NULL; - obj->seg_sizes = NULL; -} - -/*! - Initialize the vcdinfo structure "obj". Should be done before other - routines using obj are called. -*/ -bool -vcdinfo_init(vcdinfo_obj_t *obj) -{ - if (NULL == obj) return false; - _vcdinfo_zero(obj); - return cdio_init(); -} - -/*! - Set up vcdinfo structure "obj" for reading from a particular - medium. This should be done before after initialization but before - any routines that need to retrieve data. - - source_name is the device or file to use for inspection, and - source_type indicates what driver to use or class of drivers in the - case of DRIVER_DEVICE. - access_mode gives the CD access method for reading should the driver - allow for more than one kind of access method (e.g. MMC versus ioctl - on GNU/Linux) - - If source_name is NULL we'll fill in the appropriate default device - name for the given source_type. However if in addtion source_type is - DRIVER_UNKNOWN, then we'll scan for a drive containing a VCD. - - VCDINFO_OPEN_VCD is returned if everything went okay; - VCDINFO_OPEN_ERROR if there was an error and VCDINFO_OPEN_OTHER if the - medium is something other than a VCD. - */ -vcdinfo_open_return_t -vcdinfo_open(vcdinfo_obj_t **obj_p, char *source_name[], - driver_id_t source_type, const char access_mode[]) -{ - CdIo *img; - vcdinfo_obj_t *obj = _vcd_malloc(sizeof(vcdinfo_obj_t)); - iso9660_stat_t *statbuf; - - - /* If we don't specify a driver_id or a source_name, scan the - system for a CD that contains a VCD. - */ - if (NULL == *source_name && source_type == DRIVER_UNKNOWN) { - char **cd_drives=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, &source_type); - if ( NULL == cd_drives || NULL == cd_drives[0] ) { - return VCDINFO_OPEN_ERROR; - } - *source_name = strdup(cd_drives[0]); - cdio_free_device_list(cd_drives); - } - - img = cdio_open(*source_name, source_type); - if (NULL == img) { - return VCDINFO_OPEN_ERROR; - } - - *obj_p = obj; - - if (access_mode != NULL) - cdio_set_arg (img, "access-mode", access_mode); - - if (NULL == *source_name) { - *source_name = cdio_get_default_device(img); - if (NULL == *source_name) return VCDINFO_OPEN_ERROR; - } - - memset (obj, 0, sizeof (vcdinfo_obj_t)); - obj->img = img; /* Note we do this after the above wipeout! */ - - if (!iso9660_fs_read_pvd(obj->img, &(obj->pvd))) { - return VCDINFO_OPEN_ERROR; - } - - /* Determine if VCD has XA attributes. */ - { - - iso9660_pvd_t const *pvd = &obj->pvd; - - obj->has_xa = !strncmp ((char *) pvd + ISO_XA_MARKER_OFFSET, - ISO_XA_MARKER_STRING, - strlen (ISO_XA_MARKER_STRING)); - } - - if (!read_info(obj->img, &(obj->info), &(obj->vcd_type)) || - vcdinfo_get_format_version (obj) == VCD_TYPE_INVALID || - !read_entries(obj->img, &(obj->entries))) { - free (obj); /* match 0.7.23's behaviour */ - return VCDINFO_OPEN_OTHER; - } - - { - size_t len = strlen(*source_name)+1; - obj->source_name = (char *) malloc(len * sizeof(char)); - strncpy(obj->source_name, *source_name, len); - } - - if (obj->vcd_type == VCD_TYPE_SVCD || obj->vcd_type == VCD_TYPE_HQVCD) { - statbuf = iso9660_fs_stat (obj->img, "MPEGAV"); - - if (NULL != statbuf) { - vcd_warn ("non compliant /MPEGAV folder detected!"); - free(statbuf); - } - - - statbuf = iso9660_fs_stat (obj->img, "SVCD/TRACKS.SVD;1"); - if (NULL != statbuf) { - lsn_t lsn = statbuf->lsn; - if (statbuf->size != ISO_BLOCKSIZE) - vcd_warn ("TRACKS.SVD filesize != %d!", ISO_BLOCKSIZE); - - obj->tracks_buf = _vcd_malloc (ISO_BLOCKSIZE); - - free(statbuf); - if (cdio_read_mode2_sector (obj->img, obj->tracks_buf, lsn, false)) - return VCDINFO_OPEN_ERROR; - } - } - - _init_segments (obj); - - switch (obj->vcd_type) { - case VCD_TYPE_VCD2: { - /* FIXME: Can reduce CD reads by using - iso9660_fs_readdir(img, "EXT", true) and then scanning for - the files listed below. - */ - statbuf = iso9660_fs_stat (img, "EXT/PSD_X.VCD;1"); - if (NULL != statbuf) { - lsn_t lsn = statbuf->lsn; - uint32_t secsize = statbuf->secsize; - - obj->psd_x = _vcd_malloc (ISO_BLOCKSIZE * secsize); - obj->psd_x_size = statbuf->size; - - vcd_debug ("found /EXT/PSD_X.VCD at sector %lu", - (long unsigned int) lsn); - - free(statbuf); - if (cdio_read_mode2_sectors (img, obj->psd_x, lsn, false, secsize)) - return VCDINFO_OPEN_ERROR; - } - - statbuf = iso9660_fs_stat (img, "EXT/LOT_X.VCD;1"); - if (NULL != statbuf) { - lsn_t lsn = statbuf->lsn; - uint32_t secsize = statbuf->secsize; - obj->lot_x = _vcd_malloc (ISO_BLOCKSIZE * secsize); - - vcd_debug ("found /EXT/LOT_X.VCD at sector %lu", - (unsigned long int) lsn); - - if (statbuf->size != LOT_VCD_SIZE * ISO_BLOCKSIZE) - vcd_warn ("LOT_X.VCD size != 65535"); - - free(statbuf); - if (cdio_read_mode2_sectors (img, obj->lot_x, lsn, false, secsize)) - return VCDINFO_OPEN_ERROR; - - } - break; - } - case VCD_TYPE_SVCD: - case VCD_TYPE_HQVCD: { - /* FIXME: Can reduce CD reads by using - iso9660_fs_readdir(img, "SVCD", true) and then scanning for - the files listed below. - */ - 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"); - if (NULL == statbuf) - vcd_warn ("mandatory /SVCD/TRACKS.SVD not found!"); - else { - vcd_debug ("found TRACKS.SVD signature at sector %lu", - (unsigned long int) statbuf->lsn); - free(statbuf); - } - - statbuf = iso9660_fs_stat (img, "SVCD/SEARCH.DAT;1"); - if (NULL == statbuf) - vcd_warn ("mandatory /SVCD/SEARCH.DAT not found!"); - else { - lsn_t lsn = statbuf->lsn; - uint32_t secsize = statbuf->secsize; - uint32_t stat_size = statbuf->size; - uint32_t size; - - vcd_debug ("found SEARCH.DAT at sector %lu", (unsigned long int) lsn); - - obj->search_buf = _vcd_malloc (ISO_BLOCKSIZE * secsize); - - if (cdio_read_mode2_sectors (img, obj->search_buf, lsn, false, secsize)) - return VCDINFO_OPEN_ERROR; - - size = (3 * uint16_from_be (((SearchDat *)obj->search_buf)->scan_points)) - + sizeof (SearchDat); - - free(statbuf); - if (size > stat_size) { - vcd_warn ("number of scanpoints leads to bigger size than " - "file size of SEARCH.DAT! -- rereading"); - - free (obj->search_buf); - obj->search_buf = _vcd_malloc (ISO_BLOCKSIZE - * _vcd_len2blocks(size, ISO_BLOCKSIZE)); - - if (cdio_read_mode2_sectors (img, obj->search_buf, lsn, false, - secsize)) - return VCDINFO_OPEN_ERROR; - } - } - break; - } - default: - ; - } - - statbuf = iso9660_fs_stat (img, "EXT/SCANDATA.DAT;1"); - if (statbuf != NULL) { - lsn_t lsn = statbuf->lsn; - uint32_t secsize = statbuf->secsize; - - vcd_debug ("found /EXT/SCANDATA.DAT at sector %u", (unsigned int) lsn); - - obj->scandata_buf = _vcd_malloc (ISO_BLOCKSIZE * secsize); - - free(statbuf); - if (cdio_read_mode2_sectors (img, obj->scandata_buf, lsn, false, secsize)) - return VCDINFO_OPEN_ERROR; - } - - return VCDINFO_OPEN_VCD; - -} - -/*! - Dispose of any resources associated with vcdinfo structure "obj". - Call this when "obj" it isn't needed anymore. - - True is returned is everything went okay, and false if not. -*/ -bool -vcdinfo_close(vcdinfo_obj_t *obj) -{ - if (obj != NULL) { - if (obj->offset_list != NULL) - _cdio_list_free(obj->offset_list, true); - if (obj->offset_x_list != NULL) - _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); - free(obj->source_name); - - if (obj->img != NULL) cdio_destroy (obj->img); - _vcdinfo_zero(obj); - } - - free(obj); - return(true); -} - - -/* - * Local variables: - * c-file-style: "gnu" - * tab-width: 8 - * indent-tabs-mode: nil - * End: - */ |