X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Faccess%2Fvcdx%2Faccess.c;h=c8cb59126ff23cece632e2d2d8b5119ae6af0628;hb=a29a4e2e57c454027d791cdd8c69948ed03643e0;hp=9e03318955461d31b55c63b7e93cf28162b3109f;hpb=27fdfcfd6872d4868a8bef6f01ef4341fe033096;p=vlc diff --git a/modules/access/vcdx/access.c b/modules/access/vcdx/access.c index 9e03318955..c8cb59126f 100644 --- a/modules/access/vcdx/access.c +++ b/modules/access/vcdx/access.c @@ -1,14 +1,14 @@ /***************************************************************************** - * vcd.c : VCD input module for vlc - * using libcdio, libvcd and libvcdinfo. vlc-specific things tend - * to go here. + * vcd.c : VCD input module for vlc using libcdio, libvcd and libvcdinfo. + * vlc-specific things tend to go here. ***************************************************************************** - * Copyright (C) 2000, 2003, 2004 VideoLAN + * Copyright (C) 2000, 2003, 2004, 2005 the VideoLAN team * $Id$ * * Authors: Rocky Bernstein * Some code is based on the non-libcdio VCD plugin (as there really - * isn't real documentation yet.) + * isn't real developer documentation yet on how to write a + * navigable plugin.) * * 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,7 +22,7 @@ * * 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. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** @@ -30,13 +30,9 @@ *****************************************************************************/ #include -#include -#include - -#include "vcd.h" -#include "vcdplayer.h" -#include "intf.h" -#include "info.h" +#include +#include +#include #include "vlc_keys.h" #include @@ -45,11 +41,12 @@ #include #include #include +#include "vcd.h" +#include "info.h" +#include "intf.h" -#include "cdrom.h" - -/* how many blocks VCDRead will read in each loop */ -#define VCD_BLOCKS_ONCE 20 +extern void VCDSetOrigin( access_t *p_access, lsn_t i_lsn, track_t i_track, + const vcdinfo_itemid_t *p_itemid ); /***************************************************************************** * Local prototypes @@ -58,31 +55,21 @@ /* First those which are accessed from outside (via pointers). */ static block_t *VCDReadBlock ( access_t * ); -static int VCDControl ( access_t *p_access, int i_query, - va_list args ); +static int VCDControl ( access_t *p_access, int i_query, + va_list args ); /* Now those which are strictly internal */ -static void VCDSetOrigin ( access_t *p_access, - lsn_t origin_lsn, - lsn_t i_lsn, lsn_t end_lsn, - track_t track, - const vcdinfo_itemid_t * p_itemid ); -static int VCDEntryPoints ( access_t * ); -static int VCDLIDs ( access_t * ); -#ifdef FIXED -static int VCDSegments ( access_t * ); -#endif +static vlc_bool_t VCDEntryPoints ( access_t * ); +static vlc_bool_t VCDLIDs ( access_t * ); +static vlc_bool_t VCDSegments ( access_t * ); static int VCDTitles ( access_t * ); -static int VCDReadSector ( vlc_object_t *p_this, - const vcdinfo_obj_t *p_vcd, lsn_t i_lsn, - byte_t * p_buffer ); static char *VCDParse ( access_t *, /*out*/ vcdinfo_itemid_t * p_itemid , /*out*/ vlc_bool_t *play_single_item ); static void VCDUpdateVar( access_t *p_access, int i_entry, int i_action, const char *p_varname, char *p_label, - const char *p_debug_label ); + const char *p_debug_label ); static vcdinfo_obj_t *vcd_Open ( vlc_object_t *p_this, const char *psz_dev ); @@ -99,11 +86,11 @@ static access_t *p_vcd_access = NULL; static void cdio_log_handler (cdio_log_level_t level, const char message[]) { - const access_vcd_data_t *p_vcd = (access_vcd_data_t *)p_vcd_access->p_sys; + const vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_vcd_access->p_sys; switch (level) { case CDIO_LOG_DEBUG: case CDIO_LOG_INFO: - if (p_vcd->i_debug & INPUT_DBG_CDIO) + if (p_vcdplayer->i_debug & INPUT_DBG_CDIO) msg_Dbg( p_vcd_access, message); break; case CDIO_LOG_WARN: @@ -125,11 +112,11 @@ cdio_log_handler (cdio_log_level_t level, const char message[]) static void vcd_log_handler (vcd_log_level_t level, const char message[]) { - access_vcd_data_t *p_vcd = (access_vcd_data_t *)p_vcd_access->p_sys; + vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_vcd_access->p_sys; switch (level) { case VCD_LOG_DEBUG: case VCD_LOG_INFO: - if (p_vcd->i_debug & INPUT_DBG_VCDINFO) + if (p_vcdplayer->i_debug & INPUT_DBG_VCDINFO) msg_Dbg( p_vcd_access, message); break; case VCD_LOG_WARN: @@ -154,120 +141,104 @@ vcd_log_handler (vcd_log_level_t level, const char message[]) static block_t * VCDReadBlock( access_t * p_access ) { - access_vcd_data_t * p_vcd= (access_vcd_data_t *)p_access->p_sys; - block_t *p_block; - int i_blocks = VCD_BLOCKS_ONCE; - int i_index; - int i_read; - byte_t p_last_sector[ M2F2_SECTOR_SIZE ]; + vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys; + const int i_blocks = p_vcdplayer->i_blocks_per_read; + block_t *p_block; + int i_read; + uint8_t *p_buf; i_read = 0; - dbg_print( (INPUT_DBG_CALL), "lsn: %lu", - (long unsigned int) p_vcd->i_lsn ); - - /* Compute the number of blocks we have to read */ - - i_blocks = VCD_BLOCKS_ONCE ; + dbg_print( (INPUT_DBG_LSN), "lsn: %lu", + (long unsigned int) p_vcdplayer->i_lsn ); /* Allocate a block for the reading */ if( !( p_block = block_New( p_access, i_blocks * M2F2_SECTOR_SIZE ) ) ) { msg_Err( p_access, "cannot get a new block of size: %i", i_blocks * M2F2_SECTOR_SIZE ); - block_Release( p_block ); + block_Release( p_block ); return NULL; } - for ( i_index = 0 ; i_index < i_blocks ; i_index++ ) + p_buf = (uint8_t *) p_block->p_buffer; + for ( i_read = 0 ; i_read < i_blocks ; i_read++ ) { + vcdplayer_read_status_t read_status = vcdplayer_read(p_access, p_buf); - if ( p_vcd->i_lsn == p_vcd->end_lsn ) { - vcdplayer_read_status_t read_status; - - /* We've run off of the end of this entry. Do we continue or stop? */ - dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC), - "end reached, cur: %lu", - (long unsigned int) p_vcd->i_lsn ); - - read_status = vcdplayer_pbc_is_on( p_vcd ) - ? vcdplayer_pbc_nav( p_access ) - : vcdplayer_non_pbc_nav( p_access ); - - switch (read_status) { - case READ_END: - /* End reached. Return NULL to indicated this. */ - case READ_ERROR: - /* Some sort of error. */ - return NULL; - - case READ_STILL_FRAME: - { - /* Reached the end of a still frame. */ - byte_t * p_buf = (byte_t *) p_block->p_buffer; - - p_buf += (i_index*M2F2_SECTOR_SIZE); - memset(p_buf, 0, M2F2_SECTOR_SIZE); - p_buf += 2; - *p_buf = 0x01; - dbg_print(INPUT_DBG_STILL, "Handled still event"); + p_access->info.i_pos += M2F2_SECTOR_SIZE; - p_vcd->p_intf->p_sys->b_still = VLC_TRUE; - var_SetInteger( p_access, "state", PAUSE_S ); - - return p_block; - } - default: - case READ_BLOCK: - break; + switch ( read_status ) { + case READ_END: + /* End reached. Return NULL to indicated this. */ + /* We also set the postion to the end so the higher level + (demux?) doesn't try to keep reading. If everything works out + right this shouldn't have to happen. + */ +#if 0 + if ( p_access->info.i_pos != p_access->info.i_size ) { + msg_Warn( p_access, + "At end but pos (%llu) is not size (%llu). Adjusting.", + p_access->info.i_pos, p_access->info.i_size ); + p_access->info.i_pos = p_access->info.i_size; } - } +#endif - if ( VCDReadSector( VLC_OBJECT(p_access), p_vcd->vcd, - p_vcd->i_lsn, - (byte_t *) p_block->p_buffer + (i_index*M2F2_SECTOR_SIZE) ) < 0 ) + block_Release( p_block ); + return NULL; + + case READ_ERROR: + /* Some sort of error. Should we increment lsn? to skip block? + */ + block_Release( p_block ); + return NULL; + case READ_STILL_FRAME: { - LOG_ERR ("could not read sector %lu", - (long unsigned int) p_vcd->i_lsn ); + /* FIXME The below should be done in an event thread. + Until then... + */ +#if 1 + msleep( MILLISECONDS_PER_SEC * *p_buf ); + VCDSetOrigin(p_access, p_vcdplayer->origin_lsn, p_vcdplayer->i_track, + &(p_vcdplayer->play_item)); + // p_vcd->in_still = VLC_FALSE; + dbg_print(INPUT_DBG_STILL, "still wait time done"); +#else + vcdIntfStillTime(p_vcdplayer->p_intf, *p_buf); +#endif + + block_Release( p_block ); return NULL; } - p_vcd->i_lsn ++; - - } + default: + case READ_BLOCK: + /* Read buffer */ + ; + } - if ( i_index != i_blocks ) /* this should not happen */ - { - if ( VCDReadSector( VLC_OBJECT(p_access), p_vcd->vcd, - p_vcd->i_lsn, p_last_sector ) < 0 ) + p_buf += M2F2_SECTOR_SIZE; + /* Update seekpoint */ + if ( VCDINFO_ITEM_TYPE_ENTRY == p_vcdplayer->play_item.type ) + { + unsigned int i_entry = p_vcdplayer->play_item.num+1; + lsn_t i_lsn = vcdinfo_get_entry_lsn(p_vcdplayer->vcd, i_entry); + if ( p_vcdplayer->i_lsn >= i_lsn && i_lsn != VCDINFO_NULL_LSN ) { - LOG_ERR ("could not read sector %lu", - (long unsigned int) p_vcd->i_lsn ); - } - - return NULL; - } + const track_t i_track = p_vcdplayer->i_track; - /* Update seekpoints */ - for( i_read = 0; i_read < i_blocks; i_read++ ) - { - input_title_t *t = p_vcd->p_title[p_access->info.i_title]; + dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC), + "entry change to %d, current LSN %u >= end %u", + i_entry, p_vcdplayer->i_lsn, i_lsn); - if( t->i_seekpoint > 0 && - p_access->info.i_seekpoint + 1 < t->i_seekpoint && - p_access->info.i_pos + i_read * M2F2_SECTOR_SIZE >= - t->seekpoint[p_access->info.i_seekpoint+1]->i_byte_offset ) - { - msg_Dbg( p_access, "seekpoint change" ); - p_access->info.i_update |= INPUT_UPDATE_SEEKPOINT; - p_access->info.i_seekpoint++; + p_vcdplayer->play_item.num = i_entry; + + VCDSetOrigin( p_access, i_lsn, i_track, + &(p_vcdplayer->play_item) ); } + } } - /* Update a few values */ - p_vcd->i_lsn += i_blocks; - p_access->info.i_pos += p_block->i_buffer; - return p_block; } @@ -279,35 +250,54 @@ int VCDSeek( access_t * p_access, int64_t i_pos ) { if (!p_access || !p_access->p_sys) return VLC_EGENERIC; - + { - access_vcd_data_t *p_vcd = - (access_vcd_data_t *)p_vcd_access->p_sys; - const input_title_t *t = p_vcd->p_title[p_access->info.i_title]; + vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_vcd_access->p_sys; + const input_title_t *t = p_vcdplayer->p_title[p_access->info.i_title]; + unsigned int i_entry = VCDINFO_INVALID_ENTRY; int i_seekpoint; - unsigned int i_entry=VCDINFO_INVALID_ENTRY; - + /* Next sector to read */ p_access->info.i_pos = i_pos; - p_vcd->i_lsn = (i_pos / (int64_t)M2F2_SECTOR_SIZE) + - p_vcd->origin_lsn; - + p_vcdplayer->i_lsn = (i_pos / (int64_t) M2F2_SECTOR_SIZE) + + p_vcdplayer->origin_lsn; + + switch (p_vcdplayer->play_item.type) { + case VCDINFO_ITEM_TYPE_TRACK: + case VCDINFO_ITEM_TYPE_ENTRY: + break ; + default: + p_vcdplayer->b_valid_ep = VLC_FALSE; + } + /* Find entry */ - if( p_vcd->b_valid_ep ) - { - for( i_entry = 0 ; i_entry < p_vcd->i_entries ; i_entry ++ ) - { - if( p_vcd->i_lsn < p_vcd->p_entries[i_entry] ) - { - VCDUpdateVar( p_access, i_entry, VLC_VAR_SETVALUE, - "chapter", _("Entry"), "Setting entry" ); - break; - } - } - p_vcd->play_item.num = i_entry; - p_vcd->play_item.type = VCDINFO_ITEM_TYPE_ENTRY; - } - + if( p_vcdplayer->b_valid_ep ) + { + for( i_entry = 0 ; i_entry < p_vcdplayer->i_entries ; i_entry ++ ) + { + if( p_vcdplayer->i_lsn < p_vcdplayer->p_entries[i_entry] ) + { + VCDUpdateVar( p_access, i_entry, VLC_VAR_SETVALUE, + "chapter", _("Entry"), "Setting entry" ); + break; + } + } + + { + vcdinfo_itemid_t itemid; + itemid.num = i_entry; + itemid.type = VCDINFO_ITEM_TYPE_ENTRY; + VCDSetOrigin(p_access, p_vcdplayer->i_lsn, p_vcdplayer->i_track, + &itemid); + } + } + + dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK), + "orig %lu, cur: %lu, offset: %lld, entry %d", + (long unsigned int) p_vcdplayer->origin_lsn, + (long unsigned int) p_vcdplayer->i_lsn, i_pos, + i_entry ); + /* Find seekpoint */ for( i_seekpoint = 0; i_seekpoint < t->i_seekpoint; i_seekpoint++ ) { @@ -318,310 +308,138 @@ VCDSeek( access_t * p_access, int64_t i_pos ) /* Update current seekpoint */ if( i_seekpoint != p_access->info.i_seekpoint ) { - msg_Dbg( p_access, "seekpoint change" ); + dbg_print( (INPUT_DBG_SEEK), "seekpoint change %lu", + (long unsigned int) i_seekpoint ); p_access->info.i_update |= INPUT_UPDATE_SEEKPOINT; p_access->info.i_seekpoint = i_seekpoint; } - dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK), - "orig %lu, cur: %lu, offset: %lld, entry %d", - (long unsigned int) p_vcd->origin_lsn, - (long unsigned int) p_vcd->i_lsn, i_pos, - i_entry ); - } + p_access->info.b_eof = VLC_FALSE; return VLC_SUCCESS; } -/***************************************************************************** - VCDPlay: set up internal structures so seeking/reading places an item. - itemid: the thing to play. - user_entry: true if itemid is a user selection (rather than internally- - generated selection such as via PBC) in which case we may have to adjust - for differences in numbering. - *****************************************************************************/ -int -VCDPlay( access_t *p_access, vcdinfo_itemid_t itemid ) -{ - if (!p_access || !p_access->p_sys) return VLC_EGENERIC; - - { - - access_vcd_data_t *p_vcd= (access_vcd_data_t *)p_access->p_sys; -#if 0 - const vlc_bool_t b_was_still = p_vcd->in_still; -#endif - - dbg_print(INPUT_DBG_CALL, "itemid.num: %d, itemid.type: %d\n", - itemid.num, itemid.type); - - switch (itemid.type) { - case VCDINFO_ITEM_TYPE_TRACK: - - { - track_t i_track = itemid.num; - unsigned int i_entry = - vcdinfo_track_get_entry( p_vcd->vcd, i_track); - - /* Valid tracks go from 1...i_tracks-1, because track 0 is - unplayable. */ - - if (i_track == 0 || i_track >= p_vcd->i_tracks) { - LOG_ERR ("Invalid track number %d", i_track ); - return VLC_EGENERIC; - } - p_vcd->in_still = VLC_FALSE; - VCDSetOrigin( p_access, p_vcd->p_sectors[i_track], - vcdinfo_get_entry_lsn(p_vcd->vcd, i_entry), - p_vcd->p_sectors[i_track+1], - i_track, &itemid ); - break; - } - - case VCDINFO_ITEM_TYPE_SEGMENT: - { - int i_seg = itemid.num; - - /* Valid segments go from 0...i_segments-1. */ - if (itemid.num >= p_vcd->i_segments) { - LOG_ERR ( "Invalid segment number: %d", i_seg ); - return VLC_EGENERIC; - } else { - vcdinfo_video_segment_type_t segtype = - vcdinfo_get_video_type(p_vcd->vcd, i_seg); - - dbg_print(INPUT_DBG_PBC, "%s (%d), seg_num: %d", - vcdinfo_video_type2str(p_vcd->vcd, i_seg), - (int) segtype, itemid.num); - - switch (segtype) - { - case VCDINFO_FILES_VIDEO_NTSC_STILL: - case VCDINFO_FILES_VIDEO_NTSC_STILL2: - case VCDINFO_FILES_VIDEO_PAL_STILL: - case VCDINFO_FILES_VIDEO_PAL_STILL2: - p_vcd->in_still = VLC_TRUE; - break; - default: - p_vcd->in_still = VLC_FALSE; - } - VCDSetOrigin( p_access, p_vcd->p_segments[i_seg], - p_vcd->p_segments[i_seg], - p_vcd->p_segments[i_seg+1], - 0, &itemid ); - } - - } - break; - - case VCDINFO_ITEM_TYPE_LID: - /* LIDs go from 1..i_lids. */ - if (itemid.num == 0 || itemid.num > p_vcd->i_lids) { - LOG_ERR ( "Invalid LID number: %d", itemid.num ); - return VLC_EGENERIC; - } else { - p_vcd->i_lid = itemid.num; - vcdinfo_lid_get_pxd(p_vcd->vcd, &(p_vcd->pxd), itemid.num); - - switch (p_vcd->pxd.descriptor_type) { - - case PSD_TYPE_SELECTION_LIST: - case PSD_TYPE_EXT_SELECTION_LIST: { - vcdinfo_itemid_t trans_itemid; - uint16_t trans_itemid_num; - - if (p_vcd->pxd.psd == NULL) return VLC_EGENERIC; - trans_itemid_num = vcdinf_psd_get_itemid(p_vcd->pxd.psd); - vcdinfo_classify_itemid(trans_itemid_num, &trans_itemid); - p_vcd->loop_count = 1; - p_vcd->loop_item = trans_itemid; - return VCDPlay( p_access, trans_itemid ); - break; - } - - case PSD_TYPE_PLAY_LIST: { - if (p_vcd->pxd.pld == NULL) return VLC_EGENERIC; - p_vcd->pdi = -1; - return vcdplayer_inc_play_item(p_access) - ? VLC_SUCCESS : VLC_EGENERIC; - break; - } - - case PSD_TYPE_END_LIST: - case PSD_TYPE_COMMAND_LIST: - - default: - ; - } - } - return VLC_EGENERIC; - case VCDINFO_ITEM_TYPE_ENTRY: - { - int i_entry = itemid.num; - - /* Entries go from 0..i_entries-1. */ - if (itemid.num >= p_vcd->i_entries) { - LOG_ERR ("Invalid entry number: %d", i_entry ); - return VLC_EGENERIC; - } 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], - vcdinfo_get_entry_lsn(p_vcd->vcd, i_entry), - p_vcd->p_sectors[i_track+1], - i_track, &itemid ); - } - break; - } - - default: - LOG_ERR ("unknown entry type" ); - return VLC_EGENERIC; - } - - p_vcd->play_item = itemid; - - } - - - return VLC_SUCCESS; -} - /***************************************************************************** VCDEntryPoints: Reads the information about the entry points on the disc and initializes area information with that. Before calling this track information should have been read in. *****************************************************************************/ -static int +static vlc_bool_t VCDEntryPoints( access_t * p_access ) { - if (!p_access || !p_access->p_sys) return VLC_EGENERIC; + if (!p_access || !p_access->p_sys) return VLC_FALSE; { - access_vcd_data_t *p_vcd = (access_vcd_data_t *) p_access->p_sys; - const unsigned int i_entries = vcdinfo_get_num_entries(p_vcd->vcd); + vcdplayer_t *p_vcdplayer = (vcdplayer_t *) p_access->p_sys; + const unsigned int i_entries = + vcdinfo_get_num_entries(p_vcdplayer->vcd); const track_t i_last_track - = cdio_get_num_tracks(vcdinfo_get_cd_image(p_vcd->vcd)) - + cdio_get_first_track_num(vcdinfo_get_cd_image(p_vcd->vcd)); + = cdio_get_num_tracks(vcdinfo_get_cd_image(p_vcdplayer->vcd)) + + cdio_get_first_track_num(vcdinfo_get_cd_image(p_vcdplayer->vcd)); unsigned int i; if (0 == i_entries) { LOG_ERR ("no entires found -- something is wrong" ); - return VLC_EGENERIC; + return VLC_FALSE; } - p_vcd->p_entries = malloc( sizeof( lsn_t ) * i_entries ); + p_vcdplayer->p_entries = malloc( sizeof( lsn_t ) * i_entries ); - if( p_vcd->p_entries == NULL ) + if( p_vcdplayer->p_entries == NULL ) { LOG_ERR ("not enough memory for entry points treatment" ); - return VLC_EGENERIC; + return VLC_FALSE; } - p_vcd->i_entries = i_entries; + p_vcdplayer->i_entries = i_entries; for( i = 0 ; i < i_entries ; i++ ) { - const track_t i_track = vcdinfo_get_track(p_vcd->vcd, i); + const track_t i_track = vcdinfo_get_track(p_vcdplayer->vcd, i); if( i_track <= i_last_track ) { seekpoint_t *s = vlc_seekpoint_New(); char psz_entry[100]; - snprintf(psz_entry, sizeof(psz_entry), "%s%02d", _("Entry "), i ); + snprintf(psz_entry, sizeof(psz_entry), "%s %02d", _("Entry"), i ); - p_vcd->p_entries[i] = vcdinfo_get_entry_lsn(p_vcd->vcd, i); + p_vcdplayer->p_entries[i] = vcdinfo_get_entry_lsn(p_vcdplayer->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_vcdplayer->p_entries[i] - vcdinfo_get_track_lsn(p_vcdplayer->vcd, i_track)) * M2F2_SECTOR_SIZE; - TAB_APPEND( p_vcd->p_title[i_track-1]->i_seekpoint, - p_vcd->p_title[i_track-1]->seekpoint, s ); - } else - msg_Warn( p_access, "wrong track number found in entry points" ); + dbg_print( INPUT_DBG_MRL, + "%s, lsn %d, byte_offset %ld", + s->psz_name, p_vcdplayer->p_entries[i], + (unsigned long int) s->i_byte_offset); + TAB_APPEND( p_vcdplayer->p_title[i_track-1]->i_seekpoint, + p_vcdplayer->p_title[i_track-1]->seekpoint, s ); + + } else + msg_Warn( p_access, "wrong track number found in entry points" ); } - p_vcd->b_valid_ep = VLC_TRUE; - return 0; + p_vcdplayer->b_valid_ep = VLC_TRUE; + return VLC_TRUE; } } -/*????? FIXME!!! */ -#ifdef FIXED /***************************************************************************** * VCDSegments: Reads the information about the segments the disc. *****************************************************************************/ -static int +static vlc_bool_t VCDSegments( access_t * p_access ) { - access_vcd_data_t * p_vcd; - unsigned int i; - unsigned int i_segments; - + vcdplayer_t *p_vcdplayer = (vcdplayer_t *) p_access->p_sys; + unsigned int i; + input_title_t *t; - p_vcd = (access_vcd_data_t *) p_access->p_sys; - i_segments = p_vcd->num_segments = vcdinfo_get_num_segments(p_vcd->vcd); + p_vcdplayer->i_segments = vcdinfo_get_num_segments(p_vcdplayer->vcd); -#define area p_access->stream.pp_areas - - /* area 0 is reserved for segments. Set Absolute start offset - and size */ - area[0]->i_plugin_data = 0; - input_DelArea( p_access, area[0] ); - input_AddArea( p_access, 0, 0 ); - - area[0]->i_start = (off_t)p_vcd->p_sectors[0] - * (off_t)M2F2_SECTOR_SIZE; - area[0]->i_size = (off_t)(p_vcd->p_sectors[1] - p_vcd->p_sectors[0]) - * (off_t)M2F2_SECTOR_SIZE; - - /* Default Segment */ - area[0]->i_part = 0; - - /* i_plugin_data is used to store which entry point is the first - of the track (area) */ - area[0]->i_plugin_data = 0; + dbg_print( (INPUT_DBG_CALL|INPUT_DBG_MRL), + "Segments: %d", p_vcdplayer->i_segments); - area[0]->i_part_nb = 0; + if ( 0 == p_vcdplayer->i_segments ) return VLC_FALSE; - dbg_print( INPUT_DBG_MRL, - "area[0] id: %d, i_start: %lld, i_size: %lld", - area[0]->i_id, area[0]->i_start, area[0]->i_size ); + t = p_vcdplayer->p_title[p_vcdplayer->i_titles] = vlc_input_title_New(); + p_vcdplayer->i_titles++; - if (i_segments == 0) return 0; + t->i_size = 0; /* Not sure Segments have a size associated */ + t->psz_name = strdup(_("Segments")); /* We have one additional segment allocated so we can get the size by subtracting seg[i+1] - seg[i]. */ - p_vcd->p_segments = malloc( sizeof( lsn_t ) * (i_segments+1) ); - if( p_vcd->p_segments == NULL ) + p_vcdplayer->p_segments = + malloc( sizeof( lsn_t ) * (p_vcdplayer->i_segments+1) ); + if( p_vcdplayer->p_segments == NULL ) { LOG_ERR ("not enough memory for segment treatment" ); - return -1; + return VLC_FALSE; } - /* Update the navigation variables without triggering a callback */ - VCDUpdateVar( p_access, 0, VLC_VAR_SETVALUE, "title", _("Track"), - "Setting track" ); + for( i = 0 ; i < p_vcdplayer->i_segments ; i++ ) + { + char psz_segment[100]; + seekpoint_t *s = vlc_seekpoint_New(); + p_vcdplayer->p_segments[i] = vcdinfo_get_seg_lsn(p_vcdplayer->vcd, i); - var_Change( p_access, "chapter", VLC_VAR_CLEARCHOICES, NULL, NULL ); + snprintf( psz_segment, sizeof(psz_segment), "%s %02d", _("Segment"), + i ); - for( i = 0 ; i < i_segments ; i++ ) - { - p_vcd->p_segments[i] = vcdinfo_get_seg_lsn(p_vcd->vcd, i); - area[0]->i_part_nb ++; - VCDUpdateVar( p_access, i , VLC_VAR_ADDCHOICE, - "chapter", _("Segment"), "Adding segment choice"); + s->i_byte_offset = 0; /* Not sure what this would mean here */ + s->psz_name = strdup(psz_segment); + TAB_APPEND( t->i_seekpoint, t->seekpoint, s ); } -#undef area + p_vcdplayer->p_segments[p_vcdplayer->i_segments] = + p_vcdplayer->p_segments[p_vcdplayer->i_segments-1]+ + vcdinfo_get_seg_sector_count(p_vcdplayer->vcd, + p_vcdplayer->i_segments-1); - p_vcd->p_segments[i_segments] = p_vcd->p_segments[i_segments-1]+ - vcdinfo_get_seg_sector_count(p_vcd->vcd, i_segments-1); - - return 0; + return VLC_TRUE; } -#endif /***************************************************************************** Build title table which will be returned via ACCESS_GET_TITLE_INFO. @@ -637,35 +455,32 @@ 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; { - access_vcd_data_t *p_vcd = (access_vcd_data_t *) p_access->p_sys; - track_t i; + vcdplayer_t *p_vcdplayer = (vcdplayer_t *) p_access->p_sys; + track_t i; - p_vcd->i_titles = 0; - for( i = 2 ; i <= p_vcd->i_tracks ; i++ ) + p_vcdplayer->i_titles = 0; + for( i = 1 ; i <= p_vcdplayer->i_tracks ; i++ ) { - input_title_t *t = p_vcd->p_title[i - i_first_mpeg_track] - = 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 ); - - snprintf(psz_track, sizeof(psz_track), "%s%02d", _("Track "), - i-1 ); - - t->i_size = (i_secsize) * (int64_t) M2F2_SECTOR_SIZE; - t->psz_name = strdup(psz_track); - - dbg_print( INPUT_DBG_MRL, "track[%d] i_size: %lld", - i, t->i_size ); - - p_vcd->i_titles++; - } - + input_title_t *t = p_vcdplayer->p_title[i-1] = + vlc_input_title_New(); + char psz_track[80]; + + snprintf( psz_track, sizeof(psz_track), "%s %02d", _("Track"), + i ); + t->i_size = (int64_t) vcdinfo_get_track_size( p_vcdplayer->vcd, + i ) + * M2F2_SECTOR_SIZE / CDIO_CD_FRAMESIZE ; + t->psz_name = strdup(psz_track); + + dbg_print( INPUT_DBG_MRL, "track[%d] i_size: %lld", i, t->i_size ); + + p_vcdplayer->i_titles++; + } + return VLC_SUCCESS; } } @@ -673,17 +488,24 @@ VCDTitles( access_t * p_access ) /***************************************************************************** VCDLIDs: Reads the LIST IDs from the LOT. *****************************************************************************/ -static int +static vlc_bool_t VCDLIDs( access_t * p_access ) { - access_vcd_data_t *p_vcd = (access_vcd_data_t *) p_access->p_sys; + vcdplayer_t *p_vcdplayer = (vcdplayer_t *) p_access->p_sys; + input_title_t *t; + unsigned int i_lid, i_title; - p_vcd->i_lids = vcdinfo_get_num_LIDs(p_vcd->vcd); - p_vcd->i_lid = VCDINFO_INVALID_ENTRY; + p_vcdplayer->i_lids = vcdinfo_get_num_LIDs(p_vcdplayer->vcd); + p_vcdplayer->i_lid = VCDINFO_INVALID_ENTRY; + + dbg_print( (INPUT_DBG_CALL|INPUT_DBG_MRL), + "LIDs: %d", p_vcdplayer->i_lids); - if (vcdinfo_read_psd (p_vcd->vcd)) { + if ( 0 == p_vcdplayer->i_lids ) return VLC_FALSE; - vcdinfo_visit_lot (p_vcd->vcd, VLC_FALSE); + if (vcdinfo_read_psd (p_vcdplayer->vcd)) { + + vcdinfo_visit_lot (p_vcdplayer->vcd, false); #if FIXED /* @@ -692,15 +514,39 @@ VCDLIDs( access_t * p_access ) selection features in the extended PSD haven't been implemented, it's best then to not try to read this at all. */ - if (vcdinfo_get_psd_x_size(p_vcd->vcd)) - vcdinfo_visit_lot (p_vcd->vcd, VLC_TRUE); + if (vcdinfo_get_psd_x_size(p_vcdplayer->vcd)) + vcdinfo_visit_lot (p_vcdplayer->vcd, VLC_TRUE); #endif } - dbg_print( (INPUT_DBG_CALL|INPUT_DBG_MRL), - "num LIDs=%d", p_vcd->i_lids); + /* Set up LIDs Navigation Menu */ + t = vlc_input_title_New(); + t->b_menu = VLC_TRUE; + t->psz_name = strdup( "LIDs" ); + + i_title = p_vcdplayer->i_tracks; + for( i_lid = 1 ; i_lid <= p_vcdplayer->i_lids ; i_lid++ ) + { + char psz_lid[100]; + seekpoint_t *s = vlc_seekpoint_New(); + + snprintf( psz_lid, sizeof(psz_lid), "%s %02d", _("LID"), + i_lid ); + + s->i_byte_offset = 0; /* A lid doesn't have an offset + size associated with it */ + s->psz_name = strdup(psz_lid); + TAB_APPEND( t->i_seekpoint, t->seekpoint, s ); + } - return 0; +#if DYNAMICALLY_ALLOCATED + TAB_APPEND( p_vcdplayer->i_titles, p_vcdplayer->p_title, t ); +#else + p_vcdplayer->p_title[p_vcdplayer->i_titles] = t; + p_vcdplayer->i_titles++; +#endif + + return VLC_TRUE; } /***************************************************************************** @@ -710,17 +556,17 @@ static char * VCDParse( access_t * p_access, /*out*/ vcdinfo_itemid_t * p_itemid, /*out*/ vlc_bool_t *play_single_item ) { - access_vcd_data_t *p_vcd = (access_vcd_data_t *)p_access->p_sys; - char * psz_parser; - char * psz_source; - char * psz_next; + vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys; + char *psz_parser; + char *psz_source; + char *psz_next; if( config_GetInt( p_access, MODULE_STRING "-PBC" ) ) { p_itemid->type = VCDINFO_ITEM_TYPE_LID; p_itemid->num = 1; *play_single_item = VLC_FALSE; } - else + else { p_itemid->type = VCDINFO_ITEM_TYPE_ENTRY; p_itemid->num = 0; @@ -807,8 +653,8 @@ VCDParse( access_t * p_access, /*out*/ vcdinfo_itemid_t * p_itemid, VLC_TRUE ); if( NULL == cd_drives ) return NULL; if( cd_drives[0] == NULL ) - { - cdio_free_device_list( cd_drives ); + { + cdio_free_device_list( cd_drives ); return NULL; } psz_source = strdup( cd_drives[0] ); @@ -824,48 +670,88 @@ VCDParse( access_t * p_access, /*out*/ vcdinfo_itemid_t * p_itemid, } /* - Set's start origin subsequent seeks/reads + Sets start origin for subsequent seeks/reads */ -static void -VCDSetOrigin( access_t *p_access, lsn_t origin_lsn, - lsn_t i_lsn, lsn_t end_lsn, track_t i_track, - const vcdinfo_itemid_t *p_itemid ) +void +VCDSetOrigin( access_t *p_access, lsn_t i_lsn, track_t i_track, + const vcdinfo_itemid_t *p_itemid ) { - access_vcd_data_t *p_vcd= (access_vcd_data_t *)p_access->p_sys; + vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys; - p_vcd->origin_lsn = origin_lsn; - p_vcd->i_lsn = i_lsn; - p_vcd->end_lsn = end_lsn; - p_vcd->i_track = i_track; - p_vcd->play_item.num = p_itemid->num; - p_vcd->play_item.type = p_itemid->type; + dbg_print( (INPUT_DBG_CALL|INPUT_DBG_LSN), + "i_lsn: %lu, track: %d", (long unsigned int) i_lsn, + i_track ); - 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_pos = ( i_lsn - origin_lsn ) * M2F2_SECTOR_SIZE; + vcdplayer_set_origin(p_access, i_lsn, i_track, p_itemid); + + switch (p_vcdplayer->play_item.type) { + case VCDINFO_ITEM_TYPE_ENTRY: + VCDUpdateVar( p_access, p_itemid->num, VLC_VAR_SETVALUE, + "chapter", _("Entry"), "Setting entry/segment"); + p_access->info.i_title = i_track-1; + if (p_vcdplayer->b_track_length) + { + p_access->info.i_size = p_vcdplayer->p_title[i_track-1]->i_size; + p_access->info.i_pos = (int64_t) M2F2_SECTOR_SIZE * + (vcdinfo_get_track_lsn(p_vcdplayer->vcd, i_track) - i_lsn) ; + } else { + p_access->info.i_size = M2F2_SECTOR_SIZE * (int64_t) + vcdinfo_get_entry_sect_count(p_vcdplayer->vcd, p_itemid->num); + p_access->info.i_pos = 0; + } + dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC), "size: %llu, pos: %llu", + p_access->info.i_size, p_access->info.i_pos ); + p_access->info.i_seekpoint = p_itemid->num; + break; + + case VCDINFO_ITEM_TYPE_SEGMENT: + VCDUpdateVar( p_access, p_itemid->num, VLC_VAR_SETVALUE, + "chapter", _("Segment"), "Setting entry/segment"); + /* The last title entry is the for segments (when segments exist + and they must here. The segment seekpoints are stored after + the entry seekpoints and (zeroed) lid seekpoints. + */ + p_access->info.i_title = p_vcdplayer->i_titles - 1; + p_access->info.i_size = 0; /* No seeking on stills, please. */ + p_access->info.i_pos = 0; + p_access->info.i_seekpoint = p_vcdplayer->i_entries + + p_vcdplayer->i_lids + p_itemid->num; + break; + + case VCDINFO_ITEM_TYPE_TRACK: + p_access->info.i_title = i_track-1; + p_access->info.i_size = p_vcdplayer->p_title[i_track-1]->i_size; + p_access->info.i_pos = 0; + p_access->info.i_seekpoint = vcdinfo_track_get_entry(p_vcdplayer->vcd, + i_track); + break; + + default: + msg_Warn( p_access, "can't set origin for play type %d", + p_vcdplayer->play_item.type ); + } + + p_access->info.i_update = INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE + | INPUT_UPDATE_SEEKPOINT; + + VCDUpdateTitle( p_access ); - dbg_print( (INPUT_DBG_CALL|INPUT_DBG_LSN), - "origin: %lu, cur_lsn: %lu, end_lsn: %lu, track: %d", - (long unsigned int) origin_lsn, - (long unsigned int) i_lsn, - (long unsigned int) end_lsn, i_track ); - - VCDUpdateVar( p_access, p_itemid->num, VLC_VAR_SETVALUE, - "chapter", - p_itemid->type == VCDINFO_ITEM_TYPE_ENTRY ? - _("Entry") : _("Segment"), - "Setting entry/segment"); } /***************************************************************************** - * vcd_Open: Opens a VCD device or file and returns an opaque handle + * vcd_Open: Opens a VCD device or file initializes, a list of + tracks, segements and entry lsns and sizes and returns an opaque handle. *****************************************************************************/ static vcdinfo_obj_t * vcd_Open( vlc_object_t *p_this, const char *psz_dev ) { + access_t *p_access = (access_t *)p_this; + vcdplayer_t *p_vcdplayer = (vcdplayer_t *) p_access->p_sys; vcdinfo_obj_t *p_vcdobj; char *actual_dev; + unsigned int i; + + dbg_print(INPUT_DBG_CALL, "called with %s", psz_dev); if( !psz_dev ) return NULL; @@ -877,35 +763,49 @@ vcd_Open( vlc_object_t *p_this, const char *psz_dev ) } free(actual_dev); - return p_vcdobj; -} + /* + Save summary info on tracks, segments and entries... + */ + + if ( 0 < (p_vcdplayer->i_tracks = vcdinfo_get_num_tracks(p_vcdobj)) ) { + p_vcdplayer->track = (vcdplayer_play_item_info_t *) + calloc(p_vcdplayer->i_tracks, sizeof(vcdplayer_play_item_info_t)); + + for (i=0; ii_tracks; i++) { + unsigned int track_num=i+1; + p_vcdplayer->track[i].size = + vcdinfo_get_track_sect_count(p_vcdobj, track_num); + p_vcdplayer->track[i].start_LSN = + vcdinfo_get_track_lsn(p_vcdobj, track_num); + } + } else + p_vcdplayer->track = NULL; -/**************************************************************************** - * VCDReadSector: Read a sector (2324 bytes) - ****************************************************************************/ -static int -VCDReadSector( vlc_object_t *p_this, const vcdinfo_obj_t *p_vcd, - lsn_t i_lsn, byte_t * p_buffer ) -{ - typedef struct { - uint8_t subheader [CDIO_CD_SUBHEADER_SIZE]; - uint8_t data [M2F2_SECTOR_SIZE]; - uint8_t spare [4]; - } vcdsector_t; - vcdsector_t vcd_sector; - - if( cdio_read_mode2_sector( vcdinfo_get_cd_image( p_vcd ), - &vcd_sector, i_lsn, VLC_TRUE ) - != 0) - { - msg_Warn( p_this, "Could not read LSN %lu", - (long unsigned int) i_lsn ); - return -1; - } + if ( 0 < (p_vcdplayer->i_entries = vcdinfo_get_num_entries(p_vcdobj)) ) { + p_vcdplayer->entry = (vcdplayer_play_item_info_t *) + calloc(p_vcdplayer->i_entries, sizeof(vcdplayer_play_item_info_t)); + + for (i=0; ii_entries; i++) { + p_vcdplayer->entry[i].size = + vcdinfo_get_entry_sect_count(p_vcdobj, i); + p_vcdplayer->entry[i].start_LSN = vcdinfo_get_entry_lsn(p_vcdobj, i); + } + } else + p_vcdplayer->entry = NULL; - memcpy (p_buffer, vcd_sector.data, M2F2_SECTOR_SIZE); + if ( 0 < (p_vcdplayer->i_segments = vcdinfo_get_num_segments(p_vcdobj)) ) { + p_vcdplayer->segment = (vcdplayer_play_item_info_t *) + calloc(p_vcdplayer->i_segments, sizeof(vcdplayer_play_item_info_t)); - return( 0 ); + for (i=0; ii_segments; i++) { + p_vcdplayer->segment[i].size = + vcdinfo_get_seg_sector_count(p_vcdobj, i); + p_vcdplayer->segment[i].start_LSN = vcdinfo_get_seg_lsn(p_vcdobj, i); + } + } else + p_vcdplayer->segment = NULL; + + return p_vcdobj; } /**************************************************************************** @@ -913,13 +813,13 @@ VCDReadSector( vlc_object_t *p_this, const vcdinfo_obj_t *p_vcd, ****************************************************************************/ static void VCDUpdateVar( access_t *p_access, int i_num, int i_action, - const char *p_varname, char *p_label, - const char *p_debug_label) + const char *p_varname, char *p_label, + const char *p_debug_label) { vlc_value_t val; val.i_int = i_num; if (p_access) { - const access_vcd_data_t *p_vcd = (access_vcd_data_t *)p_vcd_access->p_sys; + const vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_vcd_access->p_sys; dbg_print( INPUT_DBG_PBC, "%s %d", p_debug_label, i_num ); } if (p_label) { @@ -934,24 +834,6 @@ VCDUpdateVar( access_t *p_access, int i_num, int i_action, /***************************************************************************** * Public routines. *****************************************************************************/ -int -E_(DebugCallback) ( vlc_object_t *p_this, const char *psz_name, - vlc_value_t oldval, vlc_value_t val, void *p_data ) -{ - access_vcd_data_t *p_vcd; - - if (NULL == p_vcd_access) return VLC_EGENERIC; - - p_vcd = (access_vcd_data_t *)p_vcd_access->p_sys; - - if (p_vcd->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) { - msg_Dbg( p_vcd_access, "Old debug (x%0x) %d, new debug (x%0x) %d", - p_vcd->i_debug, p_vcd->i_debug, val.i_int, val.i_int); - } - p_vcd->i_debug = val.i_int; - return VLC_SUCCESS; -} - /***************************************************************************** VCDOpen: open VCD. @@ -963,14 +845,13 @@ E_(DebugCallback) ( vlc_object_t *p_this, const char *psz_name, and VLC_EGENERIC for some other error. *****************************************************************************/ int -E_(VCDOpen) ( vlc_object_t *p_this ) +VCDOpen ( vlc_object_t *p_this ) { - access_t * p_access = (access_t *)p_this; - access_vcd_data_t * p_vcd; - char * psz_source; - vcdinfo_itemid_t itemid; - vlc_bool_t b_play_ok; - vlc_bool_t play_single_item = VLC_FALSE; + access_t *p_access = (access_t *)p_this; + vcdplayer_t *p_vcdplayer; + char *psz_source; + vcdinfo_itemid_t itemid; + vlc_bool_t play_single_item = VLC_FALSE; p_access->pf_read = NULL; p_access->pf_block = VCDReadBlock; @@ -984,22 +865,16 @@ E_(VCDOpen) ( vlc_object_t *p_this ) p_access->info.i_title = 0; p_access->info.i_seekpoint = 0; - p_vcd = malloc( sizeof(access_vcd_data_t) ); + p_vcdplayer = malloc( sizeof(vcdplayer_t) ); - if( p_vcd == NULL ) + if( p_vcdplayer == NULL ) { LOG_ERR ("out of memory" ); return VLC_ENOMEM; } - 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(); + p_vcdplayer->i_debug = config_GetInt( p_this, MODULE_STRING "-debug" ); + p_access->p_sys = (access_sys_t *) p_vcdplayer; /* Set where to log errors messages from libcdio. */ p_vcd_access = p_access; @@ -1010,95 +885,98 @@ E_(VCDOpen) ( vlc_object_t *p_this ) if ( NULL == psz_source ) { - free( p_vcd ); + free( p_vcdplayer ); return( VLC_EGENERIC ); } dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "source: %s: mrl: %s", psz_source, p_access->psz_path ); - p_vcd->p_segments = NULL; - p_vcd->p_entries = NULL; + p_vcdplayer->psz_source = strdup(psz_source); + p_vcdplayer->i_blocks_per_read = config_GetInt( p_this, MODULE_STRING + "-blocks-per-read" ); + p_vcdplayer->b_track_length = config_GetInt( p_this, MODULE_STRING + "-track-length" ); + p_vcdplayer->in_still = VLC_FALSE; + p_vcdplayer->play_item.type = VCDINFO_ITEM_TYPE_NOTFOUND; + p_vcdplayer->p_input = vlc_object_find( p_access, + VLC_OBJECT_INPUT, + FIND_PARENT ); +// p_vcdplayer->p_meta = vlc_meta_New(); + p_vcdplayer->p_segments = NULL; + p_vcdplayer->p_entries = NULL; /* set up input */ - if( !(p_vcd->vcd = vcd_Open( p_this, psz_source )) ) + if( !(p_vcdplayer->vcd = vcd_Open( p_this, psz_source )) ) { - msg_Warn( p_access, "could not open %s", psz_source ); goto err_exit; } - p_vcd->b_svd= (vlc_bool_t) vcdinfo_get_tracksSVD(p_vcd->vcd);; - + p_vcdplayer->b_svd= (vlc_bool_t) vcdinfo_get_tracksSVD(p_vcdplayer->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 ) { - vcdinfo_close( p_vcd->vcd ); + p_vcdplayer->i_tracks = vcdinfo_get_num_tracks(p_vcdplayer->vcd); + + if( p_vcdplayer->i_tracks < 1 || CDIO_INVALID_TRACK == p_vcdplayer->i_tracks ) { + vcdinfo_close( p_vcdplayer->vcd ); LOG_ERR ("no movie tracks found" ); goto err_exit; } - -#ifdef FIXED - /* Initialize segment information. */ - VCDSegments( p_access ); -#endif - /* Build Navigation Title table. */ + /* Build Navigation Title table for the tracks. */ VCDTitles( p_access ); - /* Map entry points into Chapters */ - if( VCDEntryPoints( p_access ) < 0 ) + /* Add into the above entry points as "Chapters". */ + if( ! VCDEntryPoints( p_access ) ) { msg_Warn( p_access, "could not read entry points, will not use them" ); - p_vcd->b_valid_ep = VLC_FALSE; + p_vcdplayer->b_valid_ep = VLC_FALSE; } - if( VCDLIDs( p_access ) < 0 ) + /* Initialize LID info and add that as a menu item */ + if( ! VCDLIDs( p_access ) ) { msg_Warn( p_access, "could not read entry LIDs" ); } -#if FIXED - b_play_ok = (VLC_SUCCESS == VCDPlay( p_access, itemid )); + /* Do we set PBC (via LID) on? */ + p_vcdplayer->i_lid = + ( VCDINFO_ITEM_TYPE_LID == itemid.type + && p_vcdplayer->i_lids > itemid.num ) + ? itemid.num + : VCDINFO_INVALID_ENTRY; - if ( ! b_play_ok ) { - vcdinfo_close( p_vcd->vcd ); - goto err_exit; - } -#else - /* We assume playing CD track 2 (1st MPEG data) for now */ - - p_vcd->origin_lsn = p_vcd->i_lsn = p_vcd->p_sectors[1]; - p_access->info.i_title = 0; - p_access->info.i_seekpoint = 0; - p_access->info.i_size = p_vcd->p_title[0]->i_size; - p_access->info.i_pos = 0; - -#endif + /* Initialize segment information and add that a "Track". */ + VCDSegments( p_access ); + + vcdplayer_play( p_access, itemid ); p_access->psz_demux = strdup( "ps" ); #if FIXED - p_vcd->p_intf = intf_Create( p_access, "vcdx" ); - p_vcd->p_intf->b_block = VLC_FALSE; - intf_RunThread( p_vcd->p_intf ); + if (play_single_item) + VCDFixupPlayList( p_access, p_vcd, psz_source, &itemid, + play_single_item ); #endif #if FIXED - if (play_single_item) - VCDFixupPlayList( p_access, p_vcd, psz_source, &itemid, - play_single_item ); + p_vcdplayer->p_intf = intf_Create( p_access, "vcdx" ); + p_vcdplayer->p_intf->b_block = VLC_FALSE; +#endif + p_vcdplayer->p_access = p_access; + +#ifdef FIXED + intf_RunThread( p_vcdplayer->p_intf ); #endif - free( psz_source ); return VLC_SUCCESS; err_exit: + if( p_vcdplayer->p_input ) vlc_object_release( p_vcdplayer->p_input ); free( psz_source ); - free( p_vcd ); + free( p_vcdplayer ); return VLC_EGENERIC; } @@ -1106,30 +984,32 @@ E_(VCDOpen) ( vlc_object_t *p_this ) * VCDClose: closes VCD releasing allocated memory. *****************************************************************************/ void -E_(VCDClose) ( vlc_object_t *p_this ) +VCDClose ( vlc_object_t *p_this ) { - access_t *p_access = (access_t *)p_this; - access_vcd_data_t *p_vcd = (access_vcd_data_t *)p_access->p_sys; + access_t *p_access = (access_t *)p_this; + vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys; dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "VCDClose" ); - vcdinfo_close( p_vcd->vcd ); - - free( p_vcd->p_entries ); - free( p_vcd->p_segments ); - free( p_vcd->p_sectors ); - - /* 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 - it causes problems upstream. - */ - if( p_vcd->p_intf != NULL ) { - p_vcd->p_intf = NULL; + unsigned int i; + for (i=0 ; ii_titles; i++) + if (p_vcdplayer->p_title[i]) + free(p_vcdplayer->p_title[i]->psz_name); } - - free( p_vcd ); - p_access->p_sys = NULL; + + vcdinfo_close( p_vcdplayer->vcd ); + + if( p_vcdplayer->p_input ) vlc_object_release( p_vcdplayer->p_input ); + + FREENULL( p_vcdplayer->p_entries ); + FREENULL( p_vcdplayer->p_segments ); + FREENULL( p_vcdplayer->psz_source ); + FREENULL( p_vcdplayer->track ); + FREENULL( p_vcdplayer->segment ); + FREENULL( p_vcdplayer->entry ); + FREENULL( p_access->psz_demux ); + FREENULL( p_vcdplayer ); p_vcd_access = NULL; } @@ -1140,8 +1020,8 @@ E_(VCDClose) ( vlc_object_t *p_this ) *****************************************************************************/ static int VCDControl( access_t *p_access, int i_query, va_list args ) { - access_vcd_data_t * p_vcd= (access_vcd_data_t *)p_access->p_sys; - int *pi_int; + vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys; + int *pi_int; int i; dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_EVENT), @@ -1150,141 +1030,194 @@ static int VCDControl( access_t *p_access, int i_query, va_list args ) switch( i_query ) { /* Pass back a copy of meta information that was gathered when we - during the Open/Initialize call. - */ + during the Open/Initialize call. + */ case ACCESS_GET_META: - { - vlc_meta_t **pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** ); + { + vlc_meta_t **pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** ); - dbg_print( INPUT_DBG_EVENT, "get meta info" ); + dbg_print( INPUT_DBG_EVENT, "get meta info" ); +#if 0 + if( p_vcdplayer->p_meta ) + { + *pp_meta = vlc_meta_Duplicate( p_vcdplayer->p_meta ); + dbg_print( INPUT_DBG_META, "%s", "Meta copied" ); + } + else +#endif + msg_Warn( p_access, "tried to copy NULL meta info" ); - if ( p_vcd->p_meta ) { - *pp_meta = vlc_meta_Duplicate( p_vcd->p_meta ); - dbg_print( INPUT_DBG_META, "%s", "Meta copied" ); - } else - msg_Warn( p_access, "tried to copy NULL meta info" ); - - return VLC_SUCCESS; - } - return VLC_EGENERIC; + return VLC_SUCCESS; + } + return VLC_EGENERIC; case ACCESS_CAN_SEEK: case ACCESS_CAN_FASTSEEK: case ACCESS_CAN_PAUSE: - case ACCESS_CAN_CONTROL_PACE: - { + case ACCESS_CAN_CONTROL_PACE: + { vlc_bool_t *pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* ); - dbg_print( INPUT_DBG_EVENT, - "seek/fastseek/pause/can_control_pace" ); + dbg_print( INPUT_DBG_EVENT, + "seek/fastseek/pause/can_control_pace" ); *pb_bool = VLC_TRUE; - return VLC_SUCCESS; + return VLC_SUCCESS; break; - } + } /* */ case ACCESS_GET_MTU: pi_int = (int*)va_arg( args, int * ); - *pi_int = (VCD_BLOCKS_ONCE * M2F2_SECTOR_SIZE); - dbg_print( INPUT_DBG_EVENT, "GET MTU: %d", *pi_int ); + *pi_int = (p_vcdplayer->i_blocks_per_read * M2F2_SECTOR_SIZE); + dbg_print( INPUT_DBG_EVENT, "GET MTU: %d", *pi_int ); break; case ACCESS_GET_PTS_DELAY: - { - int64_t *pi_64 = (int64_t*)va_arg( args, int64_t * ); + { + int64_t *pi_64 = (int64_t*)va_arg( args, int64_t * ); *pi_64 = var_GetInteger( p_access, MODULE_STRING "-caching" ) - * MILLISECONDS_PER_SEC; - dbg_print( INPUT_DBG_EVENT, "GET PTS DELAY" ); - return VLC_SUCCESS; + * MILLISECONDS_PER_SEC; + dbg_print( INPUT_DBG_EVENT, "GET PTS DELAY" ); + return VLC_SUCCESS; break; - } + } /* */ case ACCESS_SET_PAUSE_STATE: - dbg_print( INPUT_DBG_EVENT, "SET PAUSE STATE" ); - return VLC_SUCCESS; + dbg_print( INPUT_DBG_EVENT, "SET PAUSE STATE" ); + return VLC_SUCCESS; break; case ACCESS_GET_TITLE_INFO: - { - input_title_t ***ppp_title; - unsigned int i; + { + unsigned int psz_mrl_max = strlen(VCD_MRL_PREFIX) + + strlen(p_vcdplayer->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 ); + dbg_print( INPUT_DBG_EVENT, "GET TITLE: i_titles %d", + p_vcdplayer->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_vcdplayer->psz_source); + VCDMetaInfo( p_access, psz_mrl ); + free(psz_mrl); + } /* Duplicate title info */ - if( p_vcd->i_titles == 0 ) + if( p_vcdplayer->i_titles == 0 ) { *pi_int = 0; ppp_title = NULL; return VLC_SUCCESS; } - *pi_int = p_vcd->i_titles; - *ppp_title = malloc(sizeof( input_title_t **) * p_vcd->i_titles ); + *pi_int = p_vcdplayer->i_titles; + *ppp_title = malloc( sizeof( input_title_t **) + * p_vcdplayer->i_titles ); - if (!*ppp_title) return VLC_ENOMEM; + if (!*ppp_title) return VLC_ENOMEM; - for( i = 0; i < p_vcd->i_titles; i++ ) - { - if ( p_vcd->p_title[i] ) - (*ppp_title)[i] = - vlc_input_title_Duplicate( p_vcd->p_title[i] ); - } - - - return VLC_SUCCESS; - } - break; + for( i = 0; i < p_vcdplayer->i_titles; i++ ) + { + if ( p_vcdplayer->p_title[i] ) + (*ppp_title)[i] = + vlc_input_title_Duplicate( p_vcdplayer->p_title[i] ); + } + } + break; case ACCESS_SET_TITLE: i = (int)va_arg( args, int ); - dbg_print( INPUT_DBG_EVENT, "set title %d" , i); + 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; - - /* Next sector to read */ - p_vcd->i_lsn = p_vcd->p_sectors[i]; + vcdinfo_itemid_t itemid; + track_t i_track = i+1; + unsigned int i_entry = + vcdinfo_track_get_entry( p_vcdplayer->vcd, i_track); + + if( i < p_vcdplayer->i_tracks ) + { + /* 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; + } + else + { + /* FIXME! i_tracks+2 are Segments, but we need to + be able to figure out which segment of that. + i_tracks+1 is either Segments (if no LIDs) or + LIDs otherwise. Again need a way to get the LID + number. */ + msg_Warn( p_access, + "Trying to set track (%u) beyond end of last track (%u).", + i+1, p_vcdplayer->i_tracks ); + return VLC_EGENERIC; + } + + VCDSetOrigin(p_access, + vcdinfo_get_entry_lsn(p_vcdplayer->vcd, i_entry), + i_track, &itemid ); } break; case ACCESS_SET_SEEKPOINT: { - input_title_t *t = p_vcd->p_title[p_access->info.i_title]; - i = (int)va_arg( args, int ); + input_title_t *t = p_vcdplayer->p_title[p_access->info.i_title]; + unsigned int i = (unsigned int)va_arg( args, unsigned int ); + + dbg_print( INPUT_DBG_EVENT, "set seekpoint %d", i ); if( t->i_seekpoint > 0 ) { - 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; - - p_access->info.i_pos = - (int64_t)(p_vcd->i_lsn - - p_vcd->p_sectors[1+p_access->info.i_title]) - * M2F2_SECTOR_SIZE; + track_t i_track = p_access->info.i_title+1; + lsn_t lsn; + + /* FIXME! For now we are assuming titles are only + tracks and that track == title+1 and we the play + item is entries (not tracks or lids). + We need to generalize all of this. + */ + + if (i < p_vcdplayer->i_entries) + { + p_vcdplayer->play_item.num = i; + p_vcdplayer->play_item.type = VCDINFO_ITEM_TYPE_ENTRY; + lsn = vcdinfo_get_entry_lsn(p_vcdplayer->vcd, i); + } else if ( i < p_vcdplayer->i_entries + p_vcdplayer->i_lids ) + { + p_vcdplayer->play_item.num = i + = i - p_vcdplayer->i_entries; + p_vcdplayer->play_item.type = VCDINFO_ITEM_TYPE_LID; + lsn = 0; + } else + { + p_vcdplayer->play_item.num = i + = i - p_vcdplayer->i_entries - p_vcdplayer->i_lids; + p_vcdplayer->play_item.type = VCDINFO_ITEM_TYPE_SEGMENT; + lsn = vcdinfo_get_seg_lsn(p_vcdplayer->vcd, i); + } + + VCDSetOrigin( p_access, + vcdinfo_get_entry_lsn(p_vcdplayer->vcd, i), + i_track, &(p_vcdplayer->play_item) ); } return VLC_SUCCESS; } case ACCESS_SET_PRIVATE_ID_STATE: - dbg_print( INPUT_DBG_EVENT, "set seekpoint/set private id" ); + dbg_print( INPUT_DBG_EVENT, "set private id" ); return VLC_EGENERIC; default: - msg_Warn( p_access, "unimplemented query in control" ); + msg_Warn( p_access, "unimplemented query in control" ); return VLC_EGENERIC; }