Commit cf38ae46 authored by Rocky Bernstein's avatar Rocky Bernstein

Cleanups towards getting this to a usable state.

Much still remains to be done. 
parent febb3324
SOURCES_vcdx = \
access.c \
cdrom.c \
cdrom.h \
intf.h \
vcd.c \
vcd.h \
vcdplayer.h \
......
......@@ -46,8 +46,6 @@
#include <libvcd/info.h>
#include <libvcd/logging.h>
#include "cdrom.h"
/* how many blocks VCDRead will read in each loop */
#define VCD_BLOCKS_ONCE 20
......@@ -372,9 +370,10 @@ VCDPlay( access_t *p_access, vcdinfo_itemid_t itemid )
return VLC_EGENERIC;
}
p_vcd->in_still = VLC_FALSE;
VCDSetOrigin( p_access, p_vcd->p_sectors[i_track],
VCDSetOrigin( p_access,
vcdinfo_get_track_lsn(p_vcd->vcd, i_track),
vcdinfo_get_entry_lsn(p_vcd->vcd, i_entry),
p_vcd->p_sectors[i_track+1],
vcdinfo_get_track_lsn(p_vcd->vcd, i_track+1),
i_track, &itemid );
break;
}
......@@ -467,9 +466,10 @@ VCDPlay( access_t *p_access, vcdinfo_itemid_t itemid )
} else {
track_t i_track = vcdinfo_get_track(p_vcd->vcd, i_entry);
p_vcd->in_still = VLC_FALSE;
VCDSetOrigin( p_access, p_vcd->p_sectors[i_track],
VCDSetOrigin( p_access,
vcdinfo_get_entry_lsn(p_vcd->vcd, i_track),
vcdinfo_get_entry_lsn(p_vcd->vcd, i_entry),
p_vcd->p_sectors[i_track+1],
vcdinfo_get_entry_lsn(p_vcd->vcd, i_track+1),
i_track, &itemid );
}
break;
......@@ -533,7 +533,8 @@ VCDEntryPoints( access_t * p_access )
p_vcd->p_entries[i] = vcdinfo_get_entry_lsn(p_vcd->vcd, i);
s->psz_name = strdup(psz_entry);
s->i_byte_offset = (p_vcd->p_entries[i] - p_vcd->p_sectors[i_track])
s->i_byte_offset =
(p_vcd->p_entries[i] - vcdinfo_get_track_lsn(p_vcd->vcd, i_track))
* M2F2_SECTOR_SIZE;
TAB_APPEND( p_vcd->p_title[i_track-1]->i_seekpoint,
......@@ -637,7 +638,6 @@ VCDTitles( access_t * p_access )
very careful about this. Note: cdio_get_first_track() will give the
ISO-9660 track before the MPEG tracks.
*/
const unsigned int i_first_mpeg_track=2;
if (!p_access || !p_access->p_sys) return VLC_EGENERIC;
......@@ -646,16 +646,14 @@ VCDTitles( access_t * p_access )
track_t i;
p_vcd->i_titles = 0;
for( i = 2 ; i <= p_vcd->i_tracks ; i++ )
for( i = 1 ; i <= p_vcd->i_tracks ; i++ )
{
input_title_t *t = p_vcd->p_title[i - i_first_mpeg_track]
= vlc_input_title_New();
input_title_t *t = p_vcd->p_title[i-1] = vlc_input_title_New();
char psz_track[100];
uint32_t i_secsize =
cdio_get_track_sec_count( vcdinfo_get_cd_image(p_vcd->vcd), i );
uint32_t i_secsize = vcdinfo_get_track_sect_count( p_vcd->vcd, i );
snprintf(psz_track, sizeof(psz_track), "%s%02d", _("Track "),
i-1 );
snprintf( psz_track, sizeof(psz_track), "%s%02d", _("Track "),
i );
t->i_size = (i_secsize) * (int64_t) M2F2_SECTOR_SIZE;
t->psz_name = strdup(psz_track);
......@@ -833,6 +831,8 @@ VCDSetOrigin( access_t *p_access, lsn_t origin_lsn,
{
access_vcd_data_t *p_vcd= (access_vcd_data_t *)p_access->p_sys;
unsigned int i_title = i_track - 1; /* For now */
p_vcd->origin_lsn = origin_lsn;
p_vcd->i_lsn = i_lsn;
p_vcd->end_lsn = end_lsn;
......@@ -842,8 +842,9 @@ VCDSetOrigin( access_t *p_access, lsn_t origin_lsn,
p_access->info.i_title = i_track-1;
p_access->info.i_seekpoint = p_itemid->num;
p_access->info.i_size = p_vcd->p_title[i_track]->i_size;
p_access->info.i_size = p_vcd->p_title[i_title]->i_size;
p_access->info.i_pos = ( i_lsn - origin_lsn ) * M2F2_SECTOR_SIZE;
p_access->info.i_update |= INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
dbg_print( (INPUT_DBG_CALL|INPUT_DBG_LSN),
"origin: %lu, cur_lsn: %lu, end_lsn: %lu, track: %d",
......@@ -994,13 +995,6 @@ E_(VCDOpen) ( vlc_object_t *p_this )
p_access->p_sys = (access_sys_t *) p_vcd;
p_vcd->i_debug = config_GetInt( p_this, MODULE_STRING "-debug" );
p_vcd->in_still = VLC_FALSE;
p_vcd->play_item.type = VCDINFO_ITEM_TYPE_NOTFOUND;
p_vcd->p_input = vlc_object_find( p_access, VLC_OBJECT_INPUT,
FIND_PARENT );
p_vcd->p_meta = vlc_meta_New();
/* Set where to log errors messages from libcdio. */
p_vcd_access = p_access;
cdio_log_set_handler ( cdio_log_handler );
......@@ -1017,6 +1011,13 @@ E_(VCDOpen) ( vlc_object_t *p_this )
dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "source: %s: mrl: %s",
psz_source, p_access->psz_path );
p_vcd->psz_source = strdup(psz_source);
p_vcd->i_debug = config_GetInt( p_this, MODULE_STRING "-debug" );
p_vcd->in_still = VLC_FALSE;
p_vcd->play_item.type = VCDINFO_ITEM_TYPE_NOTFOUND;
p_vcd->p_input = vlc_object_find( p_access, VLC_OBJECT_INPUT,
FIND_PARENT );
p_vcd->p_meta = vlc_meta_New();
p_vcd->p_segments = NULL;
p_vcd->p_entries = NULL;
......@@ -1031,10 +1032,9 @@ E_(VCDOpen) ( vlc_object_t *p_this )
p_vcd->b_svd= (vlc_bool_t) vcdinfo_get_tracksSVD(p_vcd->vcd);;
/* Get track information. */
p_vcd->i_tracks = ioctl_GetTracksMap( VLC_OBJECT(p_access),
vcdinfo_get_cd_image(p_vcd->vcd),
&p_vcd->p_sectors );
if( p_vcd->i_tracks <= 1 ) {
p_vcd->i_tracks = vcdinfo_get_num_tracks(p_vcd->vcd);
if( p_vcd->i_tracks < 1 || CDIO_INVALID_TRACK == p_vcd->i_tracks ) {
vcdinfo_close( p_vcd->vcd );
LOG_ERR ("no movie tracks found" );
goto err_exit;
......@@ -1060,7 +1060,7 @@ E_(VCDOpen) ( vlc_object_t *p_this )
msg_Warn( p_access, "could not read entry LIDs" );
}
#if FIXED
#if 1
b_play_ok = (VLC_SUCCESS == VCDPlay( p_access, itemid ));
if ( ! b_play_ok ) {
......@@ -1117,7 +1117,7 @@ E_(VCDClose) ( vlc_object_t *p_this )
free( p_vcd->p_entries );
free( p_vcd->p_segments );
free( p_vcd->p_sectors );
free( p_vcd->psz_source );
/* For reasons that are a mystery to me we don't have to deal with
stopping, and destroying the p_vcd->p_intf thread. And if we do
......@@ -1207,16 +1207,26 @@ static int VCDControl( access_t *p_access, int i_query, va_list args )
case ACCESS_GET_TITLE_INFO:
{
input_title_t ***ppp_title;
unsigned int psz_mrl_max = strlen(VCD_MRL_PREFIX)
+ strlen(p_vcd->psz_source) + sizeof("@E999")+3;
input_title_t ***ppp_title
= (input_title_t***)va_arg( args, input_title_t*** );
char *psz_mrl = malloc( psz_mrl_max );
unsigned int i;
ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
pi_int = (int*)va_arg( args, int* );
dbg_print( INPUT_DBG_EVENT, "GET TITLE: i_titles %d",
p_vcd->i_titles );
VCDMetaInfo( p_access );
if( psz_mrl == NULL ) {
msg_Warn( p_access, "out of memory" );
} else {
snprintf(psz_mrl, psz_mrl_max, "%s%s",
VCD_MRL_PREFIX, p_vcd->psz_source);
VCDMetaInfo( p_access, psz_mrl );
free(psz_mrl);
}
/* Duplicate title info */
if( p_vcd->i_titles == 0 )
......@@ -1247,15 +1257,21 @@ static int VCDControl( access_t *p_access, int i_query, va_list args )
dbg_print( INPUT_DBG_EVENT, "set title %d" , i);
if( i != p_access->info.i_title )
{
/* Update info */
p_access->info.i_update |=
INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
p_access->info.i_title = i;
p_access->info.i_size = p_vcd->p_title[i]->i_size;
p_access->info.i_pos = 0;
vcdinfo_itemid_t itemid;
track_t i_track = i+1;
unsigned int i_entry =
vcdinfo_track_get_entry( p_vcd->vcd, i_track);
/* Next sector to read */
p_vcd->i_lsn = p_vcd->p_sectors[i];
/* FIXME! For now we are assuming titles are only
tracks and that track == title+1 */
itemid.num = i_track;
itemid.type = VCDINFO_ITEM_TYPE_TRACK;
VCDSetOrigin(p_access,
vcdinfo_get_track_lsn(p_vcd->vcd, i_track),
vcdinfo_get_entry_lsn(p_vcd->vcd, i_entry),
vcdinfo_get_track_lsn(p_vcd->vcd, i_track+1),
i_track, &itemid );
}
break;
......@@ -1265,15 +1281,19 @@ static int VCDControl( access_t *p_access, int i_query, va_list args )
i = (int)va_arg( args, int );
if( t->i_seekpoint > 0 )
{
track_t i_track = p_access->info.i_title+1;
lsn_t track_lsn = vcdinfo_get_track_lsn(p_vcd->vcd, i_track);
p_access->info.i_update |= INPUT_UPDATE_SEEKPOINT;
p_access->info.i_seekpoint = i;
p_vcd->i_lsn = p_vcd->p_sectors[1+p_access->info.i_title] +
t->seekpoint[i]->i_byte_offset / M2F2_SECTOR_SIZE;
/* FIXME! For now we are assuming titles are only
tracks and that track == title+1 */
p_vcd->i_lsn = track_lsn
+ (t->seekpoint[i]->i_byte_offset / M2F2_SECTOR_SIZE);
p_access->info.i_pos =
(int64_t)(p_vcd->i_lsn -
p_vcd->p_sectors[1+p_access->info.i_title])
p_access->info.i_pos = (int64_t)(p_vcd->i_lsn - track_lsn)
* M2F2_SECTOR_SIZE;
}
return VLC_SUCCESS;
......
/****************************************************************************
* cdrom.c: cdrom tools
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id$
*
* Authors: Johan Bilien <jobi@via.ecp.fr>
* Gildas Bazin <gbazin@netcourrier.com>
* Jon Lech Johansen <jon-vl@nanocrew.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <vlc/vlc.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <string.h>
#include <errno.h>
#include "cdrom.h"
/*****************************************************************************
* Local Prototypes
*****************************************************************************/
static void cd_log_handler (cdio_log_level_t level, const char message[]);
/*****************************************************************************
* ioctl_Open: Opens a VCD device or file and returns an opaque handle
*****************************************************************************/
cddev_t *ioctl_Open( vlc_object_t *p_this, const char *psz_dev )
{
cddev_t *p_cddev;
if( !psz_dev ) return NULL;
/*
* Initialize structure with default values
*/
p_cddev = (cddev_t *)malloc( sizeof(cddev_t) );
if( p_cddev == NULL )
{
msg_Err( p_this, "out of memory" );
return NULL;
}
/* Set where to log errors messages from libcdio. */
cdio_log_set_handler ( cd_log_handler );
p_cddev->cdio = cdio_open(psz_dev, DRIVER_UNKNOWN);
if( p_cddev->cdio == NULL )
{
free( p_cddev );
p_cddev = NULL;
}
return p_cddev;
}
/*****************************************************************************
* ioctl_Close: Closes an already opened VCD device or file.
*****************************************************************************/
void ioctl_Close( cddev_t *p_cddev )
{
cdio_destroy(p_cddev->cdio);
}
/*****************************************************************************
* ioctl_GetTracksMap: Read the Table of Contents, fill in the pp_sectors map
* if pp_sectors is not null and return the number of
* tracks available.
* We allocate and fill one more track than are on
* the CD. The last "track" is leadout track information.
* This makes finding the end of the last track uniform
* how it is done for other tracks.
*****************************************************************************/
track_t ioctl_GetTracksMap( vlc_object_t *p_this, const CdIo *p_cdio,
lsn_t **pp_sectors )
{
track_t i_tracks = cdio_get_num_tracks(p_cdio);
track_t first_track = cdio_get_first_track_num(p_cdio);
track_t i;
if (CDIO_INVALID_TRACK == i_tracks)
return 0;
*pp_sectors = malloc( (i_tracks + 1) * sizeof(lsn_t) );
if( *pp_sectors == NULL )
{
msg_Err( p_this, "out of memory" );
return 0;
}
/* Fill the p_sectors structure with the track/sector matches.
Note cdio_get_track_lsn when given num_tracks + 1 will return
the leadout LSN.
*/
for( i = 0 ; i <= i_tracks ; i++ )
{
(*pp_sectors)[ i ] = cdio_get_track_lsn(p_cdio, first_track+i);
}
return i_tracks;
}
/****************************************************************************
* ioctl_ReadSector: Read a sector (2324 bytes)
****************************************************************************/
int ioctl_ReadSector( vlc_object_t *p_this, const cddev_t *p_cddev,
int i_sector, byte_t * p_buffer )
{
typedef struct {
uint8_t subheader [8];
uint8_t data [M2F2_SECTOR_SIZE];
} vcdsector_t;
vcdsector_t vcd_sector;
if( cdio_read_mode2_sector(p_cddev->cdio, &vcd_sector, i_sector, VLC_TRUE)
!= 0)
{
// msg_Err( p_this, "Could not read sector %d", i_sector );
return -1;
}
memcpy (p_buffer, vcd_sector.data, M2F2_SECTOR_SIZE);
return( 0 );
}
/****************************************************************************
* Private functions
****************************************************************************/
/* For now we're going to just discard error messages from libcdio... */
static void
cd_log_handler (cdio_log_level_t level, const char message[])
{
return;
}
/****************************************************************************
* cdrom.h: cdrom tools header
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id$
*
* Authors: Johan Bilien <jobi@via.ecp.fr>
* Gildas Bazin <gbazin@netcourrier.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, USA.
*****************************************************************************/
#ifndef VCDX_CDROM_H
#define VCDX_CDROM_H
#include <cdio/cdio.h>
#include <cdio/logging.h>
/*****************************************************************************
* The cddev structure
*****************************************************************************/
typedef struct cddev_s
{
int *p_sectors; /* tracks layout on the vcd */
CdIo *cdio; /* libcdio uses this to read */
} cddev_t;
/*****************************************************************************
* Prototypes
*****************************************************************************/
cddev_t *ioctl_Open ( vlc_object_t *, const char * );
void ioctl_Close ( cddev_t * );
track_t ioctl_GetTracksMap ( vlc_object_t *, const CdIo *, lsn_t ** );
int ioctl_ReadSector ( vlc_object_t *, const cddev_t *,
int, byte_t * );
#endif /*VCDX_CDROM_H*/
......@@ -36,6 +36,10 @@
#include <libvcd/info.h>
#include <libvcd/logging.h>
static char *VCDFormatStr(const access_t *p_access, access_vcd_data_t *p_vcd,
const char format_str[], const char *mrl,
const vcdinfo_itemid_t *itemid);
static inline void
MetaInfoAddStr(access_t *p_access, char *p_cat,
char *title, const char *str)
......@@ -63,7 +67,7 @@ MetaInfoAddNum(access_t *p_access, char *psz_cat, char *title, int num)
MetaInfoAddNum( p_access, psz_cat, title, num );
void
VCDMetaInfo( access_t *p_access )
VCDMetaInfo( access_t *p_access, /*const*/ char *psz_mrl )
{
access_vcd_data_t *p_vcd = (access_vcd_data_t *) p_access->p_sys;
unsigned int i_entries = vcdinfo_get_num_entries(p_vcd->vcd);
......@@ -96,8 +100,8 @@ VCDMetaInfo( access_t *p_access )
for( i_track = 1 ; i_track < p_vcd->i_tracks ; i_track++ ) {
unsigned int audio_type = vcdinfo_get_track_audio_type(p_vcd->vcd,
i_track);
uint32_t i_secsize =
p_vcd->p_sectors[i_track+1] - p_vcd->p_sectors[i_track];
uint32_t i_secsize = vcdinfo_get_track_sect_count(p_vcd->vcd, i_track);
if (p_vcd->b_svd) {
addnum(_("Audio Channels"),
vcdinfo_audio_type_num_channels(p_vcd->vcd, audio_type) );
......@@ -110,6 +114,17 @@ VCDMetaInfo( access_t *p_access )
addnum(_("Last Entry Point"), last_entry-1 );
addnum(_("Track size (in sectors)"), i_secsize );
}
if ( CDIO_INVALID_TRACK != i_track )
{
char *psz_name =
VCDFormatStr( p_access, p_vcd,
config_GetPsz( p_access, MODULE_STRING "-title-format" ),
psz_mrl, &(p_vcd->play_item) );
input_Control( p_vcd->p_input, INPUT_SET_NAME, psz_name );
}
}
#define add_format_str_info(val) \
......
......@@ -31,9 +31,9 @@ int VCDFixupPlayList( access_t *p_access, access_vcd_data_t *p_vcd,
/*
Sets VCD meta information and navigation/playlist entries.
*/
void VCDMetaInfo( access_t *p_access );
void VCDMetaInfo( access_t *p_access, /*const*/ char *psz_mrl );
char *
VCDFormatStr(const access_t *p_access, access_vcd_data_t *p_vcd,
char * VCDFormatStr(const access_t *p_access, access_vcd_data_t *p_vcd,
const char format_str[], const char *mrl,
const vcdinfo_itemid_t *itemid);
......@@ -75,11 +75,11 @@ int E_(DebugCallback) ( vlc_object_t *p_this, const char *psz_name,
" %L : The playlist ID prefixed with \" LID\" if it exists\n" \
" %N : The current number of the %I - a decimal number\n" \
" %P : The publisher ID\n" \
" %p : The preparer I\n" \
" %p : The preparer ID\n" \
" %S : If we are in a segment (menu), the kind of segment\n" \
" %T : The track number\n" \
" %V : The volume set I\n" \
" %v : The volume I\n" \
" %T : The MPEG track number (starts at 1)\n" \
" %V : The volume set ID\n" \
" %v : The volume ID\n" \
" A number between 1 and the volume count.\n" \
" %% : a % \n")
......@@ -91,8 +91,11 @@ vlc_module_begin();
add_usage_hint( N_("vcdx://[device-or-file][@{P,S,T}num]") );
set_description( _("Video CD (VCD 1.0, 1.1, 2.0, SVCD, HQVCD) input") );
set_capability( "access2", 55 /* slightly lower than vcd */ );
set_shortname( N_("(Super) Video CD"));
set_callbacks( E_(VCDOpen), E_(VCDClose) );
add_shortcut( "vcdx" );
set_category( CAT_INPUT );
set_subcategory( SUBCAT_INPUT_ACCESS );
/* Configuration options */
add_integer ( MODULE_STRING "-debug", 0, E_(DebugCallback),
......@@ -112,7 +115,7 @@ vlc_module_begin();
VCD_TITLE_FMT_LONGTEXT, VLC_TRUE );
add_string( MODULE_STRING "-title-format",
"%I %N%L%S - %M",
"%I %N%L%S - %M %A %v - disc %c of %C %F",
NULL,
N_("Format to use in playlist \"title\" field"),
VCD_TITLE_FMT_LONGTEXT, VLC_TRUE );
......
......@@ -91,8 +91,8 @@ vcdplayer_non_pbc_nav ( access_t * p_access )
case VCDINFO_ITEM_TYPE_TRACK:
case VCDINFO_ITEM_TYPE_ENTRY: {
dbg_print( INPUT_DBG_LSN, "new track %d, lsn %d", p_vcd->i_track,
p_vcd->p_sectors[p_vcd->i_track+1] );
dbg_print( INPUT_DBG_LSN, "new track %d, lsn %d", p_vcd->i_track+1,
vcdinfo_get_track_lsn(p_vcd->vcd, p_vcd->i_track+1) );
return READ_END;
break;
}
......
......@@ -66,13 +66,10 @@ typedef enum {
typedef struct thread_vcd_data_s
{
vcdinfo_obj_t *vcd; /* CD device descriptor */
/* Current State: position */
int i_debug; /* Debugging mask */
vlc_bool_t in_still; /* true if in still */
vlc_bool_t b_svd; /* true if we have SVD info */
track_t i_tracks; /* # of tracks */
unsigned int i_segments; /* # of segments */
unsigned int i_entries; /* # of entries */
unsigned int i_lids; /* # of List IDs */
unsigned int i_titles; /* # of navigatable titles. */
vcdinfo_itemid_t play_item; /* play-item, VCDPLAYER_BAD_ENTRY
if none */
int i_lid; /* LID that play item is in. Implies
......@@ -93,21 +90,26 @@ typedef struct thread_vcd_data_s
lsn_t end_lsn; /* LSN of end of current
entry/segment/track. */
lsn_t origin_lsn; /* LSN of start of seek/slider */
lsn_t * p_sectors; /* Track sectors. This is 0 origin
so the first VCD track will be
at 0 and this is the ISO9660
filesystem. The first Mode2 form2
MPEG track is probably track 2 or
p_sectors[1].
*/
lsn_t * p_entries; /* Entry points */
lsn_t * p_segments; /* Segments */
vlc_bool_t b_valid_ep; /* Valid entry points flag */
vlc_bool_t b_end_of_track; /* If the end of track was reached */
int i_debug; /* Debugging mask */
/* Information about CD */
/* Information about (S)VCD */
char * psz_source; /* (S)VCD drive or image filename */
vlc_bool_t b_svd; /* true if we have SVD info */
vlc_meta_t *p_meta;
track_t i_tracks; /* # of playable MPEG tracks. This is
generally one less than the number
of CD tracks as the first CD track
is an ISO-9660 track and is not
playable.
*/
unsigned int i_segments; /* # of segments */
unsigned int i_entries; /* # of entries */
unsigned int i_lids; /* # of List IDs */
unsigned int i_titles; /* # of navigatable titles. */
input_title_t *p_title[CDIO_CD_MAX_TRACKS];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment