- /* we can't use the interface slider until initilization is complete */
- p_input->stream.b_seekable = 0;
-
- if( p_area != p_input->stream.p_selected_area )
- {
- unsigned int i;
-
- /* If is the result of a track change, make the entry valid. */
- if (i_entry < p_area->i_plugin_data || i_entry >= i_nb)
- i_entry = p_area->i_plugin_data;
-
- /* Change the default area */
- p_input->stream.p_selected_area = p_area;
-
- /* Update the navigation variables without triggering a callback */
- VCDUpdateVar( p_input, i_track, VLC_VAR_SETVALUE, "title",
- "Setting track");
-
- var_Change( p_input, "chapter", VLC_VAR_CLEARCHOICES, NULL, NULL );
- for( i = p_area->i_plugin_data; i < i_nb; i++ )
- {
- VCDUpdateVar( p_input, i , VLC_VAR_ADDCHOICE,
- "chapter", "Adding entry choice");
- }
- }
-
- if (i_track == 0)
- VCDSetOrigin( p_input, p_vcd->p_segments[i_entry],
- p_vcd->p_segments[i_entry], p_vcd->p_segments[i_entry+1],
- i_entry, 0 );
- else
- VCDSetOrigin( p_input, p_vcd->p_sectors[i_track],
- vcdinfo_get_entry_lsn(p_vcd->vcd, i_entry),
- p_vcd->p_sectors[i_track+1],
- i_entry, i_track );
-
- p_input->stream.b_seekable = old_seekable;
- /* warn interface that something has changed */
- p_input->stream.b_changed = 1;
-
- return VLC_SUCCESS;
-}
-
-
-/****************************************************************************
- * VCDSeek
- ****************************************************************************/
-void
-VCDSeek( input_thread_t * p_input, off_t i_off )
-{
- thread_vcd_data_t * p_vcd;
- unsigned int i_entry=0; /* invalid entry */
-
- p_vcd = (thread_vcd_data_t *) p_input->p_access_data;
-
- p_vcd->cur_lsn = p_vcd->origin_lsn + (i_off / (off_t)M2F2_SECTOR_SIZE);
-
- vlc_mutex_lock( &p_input->stream.stream_lock );
-#define p_area p_input->stream.p_selected_area
- /* Find entry */
- if( p_vcd->b_valid_ep )
- {
- for( i_entry = 1 ; i_entry < p_vcd->num_entries ; i_entry ++ )
- {
- if( p_vcd->cur_lsn < p_vcd->p_entries[i_entry] )
- {
- VCDUpdateVar( p_input, i_entry, VLC_VAR_SETVALUE,
- "chapter", "Setting entry" );
- break;
- }
- }
- p_vcd->play_item.num = p_area->i_part = i_entry;
- p_vcd->play_item.type = VCDINFO_ITEM_TYPE_ENTRY;
- }
-#undef p_area
-
- p_input->stream.p_selected_area->i_tell = i_off;
-
- dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
- "orig %d, cur: %d, offset: %lld, start: %lld, entry %d",
- p_vcd->origin_lsn, p_vcd->cur_lsn, i_off,
- p_input->stream.p_selected_area->i_start, i_entry );
-
- vlc_mutex_unlock( &p_input->stream.stream_lock );
-}
-
-/*****************************************************************************
- 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( input_thread_t *p_input, vcdinfo_itemid_t itemid )
-{
- thread_vcd_data_t * p_vcd= (thread_vcd_data_t *)p_input->p_access_data;
- input_area_t * p_area;
-
- p_vcd->in_still = 0;
-
-#define area p_input->stream.pp_areas
-
- switch (itemid.type) {
- case VCDINFO_ITEM_TYPE_TRACK:
-
- /* Valid tracks go from 1...num_tracks-1, because track 0 is unplayable.
- */
-
- if (itemid.num == 0 || itemid.num >= p_vcd->num_tracks) {
- LOG_ERR ("Invalid track number %d", itemid.num );
- return VLC_EGENERIC;
- }
- p_area = area[itemid.num];
- p_area->i_part = p_area->i_plugin_data;
- p_input->stream.b_seekable = 1;
- break;
- case VCDINFO_ITEM_TYPE_SEGMENT:
- /* Valid segments go from 0...num_segments-1. */
- if (itemid.num >= p_vcd->num_segments) {
- LOG_ERR ( "Invalid segment number: %d", itemid.num );
- return VLC_EGENERIC;
- } else {
- vcdinfo_video_segment_type_t segtype =
- vcdinfo_get_video_type(p_vcd->vcd, itemid.num);
-
- dbg_print(INPUT_DBG_PBC, "%s (%d), seg_num: %d",
- vcdinfo_video_type2str(p_vcd->vcd, itemid.num),
- (int) segtype, itemid.num);
-
- p_area = area[0];
- p_area->i_part = 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_input->stream.b_seekable = 0;
- p_vcd->in_still = -5;
- break;
- default:
- p_input->stream.b_seekable = 1;
- p_vcd->in_still = 0;
- }
- }
- break;
-
- case VCDINFO_ITEM_TYPE_LID:
- /* LIDs go from 1..num_lids. */
- if (itemid.num == 0 || itemid.num > p_vcd->num_lids) {
- LOG_ERR ( "Invalid LID number: %d", itemid.num );
- return VLC_EGENERIC;
- } else {
- p_vcd->cur_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_input, 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_input)
- ? VLC_SUCCESS : VLC_EGENERIC;
- break;
- }
-
- case PSD_TYPE_END_LIST:
- case PSD_TYPE_COMMAND_LIST:
-
- default:
- ;
- }
- }
- return VLC_EGENERIC;
- case VCDINFO_ITEM_TYPE_ENTRY:
- /* Entries go from 0..num_entries-1. */
- if (itemid.num >= p_vcd->num_entries) {
- LOG_ERR ("Invalid entry number: %d", itemid.num );
- return VLC_EGENERIC;
- } else {
- track_t cur_track = vcdinfo_get_track(p_vcd->vcd, itemid.num);
- p_area = area[cur_track];
- p_area->i_part = itemid.num;
- p_input->stream.b_seekable = 1;
- }
- break;
- default:
- LOG_ERR ("unknown entry type" );
- return VLC_EGENERIC;
- }
-
- VCDSetArea( p_input, p_area );
-
-#undef area
-
- p_vcd->play_item = itemid;
-
- dbg_print( (INPUT_DBG_CALL),
- "i_start %lld, i_size: %lld, i_tell: %lld, lsn %d",
- p_area->i_start, p_area->i_size,
- p_area->i_tell, p_vcd->cur_lsn );
-
- 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
-VCDEntryPoints( input_thread_t * p_input )
-{
- thread_vcd_data_t * p_vcd;
- unsigned int i_nb;
- unsigned int i, i_entry_index = 0;
- unsigned int i_previous_track = CDIO_INVALID_TRACK;
-
- p_vcd = (thread_vcd_data_t *) p_input->p_access_data;
-
- i_nb = vcdinfo_get_num_entries(p_vcd->vcd);
- if (0 == i_nb)
- return -1;
-
- p_vcd->p_entries = malloc( sizeof( lba_t ) * i_nb );
-
- if( p_vcd->p_entries == NULL )
- {
- LOG_ERR ("not enough memory for entry points treatment" );
- return -1;
- }
-
- p_vcd->num_entries = 0;
-
- for( i = 0 ; i < i_nb ; i++ )
- {
- track_t i_track = vcdinfo_get_track(p_vcd->vcd, i);
- if( i_track <= p_input->stream.i_area_nb )
- {
- p_vcd->p_entries[i] =
- vcdinfo_get_entry_lsn(p_vcd->vcd, i);
- p_input->stream.pp_areas[i_track]->i_part_nb ++;
-
- /* if this entry belongs to a new track */
- if( i_track != i_previous_track )
- {
- /* i_plugin_data is used to store the first entry of the area*/
- p_input->stream.pp_areas[i_track]->i_plugin_data =
- i_entry_index;
- i_previous_track = i_track;
- p_input->stream.pp_areas[i_track]->i_part_nb = 1;
- }
- i_entry_index ++;
- p_vcd->num_entries ++;
- }
- else
- msg_Warn( p_input, "wrong track number found in entry points" );
- }
- p_vcd->b_valid_ep = true;
- return 0;
-}
-
-/*****************************************************************************
- * VCDSegments: Reads the information about the segments the disc.
- *****************************************************************************/
-static int
-VCDSegments( input_thread_t * p_input )
-{
- thread_vcd_data_t * p_vcd;
- unsigned int i;
- unsigned int num_segments;
-
-
- p_vcd = (thread_vcd_data_t *) p_input->p_access_data;
- num_segments = p_vcd->num_segments = vcdinfo_get_num_segments(p_vcd->vcd);
-
-#define area p_input->stream.pp_areas
-
- /* area 0 is reserved for segments. Set Absolute start offset
- and size */
- area[0]->i_plugin_data = 0;
- input_DelArea( p_input, area[0] );
- input_AddArea( p_input, 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;
-
- area[0]->i_part_nb = 0;
-
- dbg_print( INPUT_DBG_MRL, "area id %d, for segment track %d",
- area[0]->i_id, 0 );
-
- if (num_segments == 0) return 0;
-
- /* 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( lba_t ) * (num_segments+1) );
- if( p_vcd->p_segments == NULL )
- {
- LOG_ERR ("not enough memory for segment treatment" );
- return -1;
- }
-
- /* Update the navigation variables without triggering a callback */
- VCDUpdateVar( p_input, 0, VLC_VAR_SETVALUE, "title", "Setting track" );
- var_Change( p_input, "chapter", VLC_VAR_CLEARCHOICES, NULL, NULL );
-
- for( i = 0 ; i < num_segments ; i++ )
- {
- p_vcd->p_segments[i] = vcdinfo_get_seg_lsn(p_vcd->vcd, i);
- area[0]->i_part_nb ++;
- VCDUpdateVar( p_input, i , VLC_VAR_ADDCHOICE,
- "chapter", "Adding segment choice");
- }
-
-#undef area
-
- p_vcd->p_segments[num_segments] = p_vcd->p_segments[num_segments-1]+
- vcdinfo_get_seg_sector_count(p_vcd->vcd, num_segments-1);
-
- return 0;
-}
-
-/*****************************************************************************
- VCDTracks: initializes area information.
- Before calling this track information should have been read in.
- *****************************************************************************/
-static void
-VCDTracks( input_thread_t * p_input )
-{
- thread_vcd_data_t * p_vcd;
- unsigned int i;
-
- p_vcd = (thread_vcd_data_t *) p_input->p_access_data;
-
-#define area p_input->stream.pp_areas
-
- /* We start area addressing for tracks at 1 since the default area 0
- is reserved for segments */
-
- for( i = 1 ; i < p_vcd->num_tracks ; i++ )
- {
- /* Tracks are Program Chains */
- input_AddArea( p_input, i, i );
-
- /* Absolute start byte offset and byte size */
- area[i]->i_start = (off_t) p_vcd->p_sectors[i]
- * (off_t)M2F2_SECTOR_SIZE;
- area[i]->i_size = (off_t)(p_vcd->p_sectors[i+1] - p_vcd->p_sectors[i])
- * (off_t)M2F2_SECTOR_SIZE;
-
- /* Current entry being played in track */
- area[i]->i_part = 0;
-
- /* i_plugin_data is used to store which entry point is the first
- * of the track (area) */
- area[i]->i_plugin_data = 0;
-
- dbg_print( INPUT_DBG_MRL,
- "area[%d] id: %d, i_start: %lld, i_size: %lld",
- i, area[i]->i_id, area[i]->i_start, area[i]->i_size );
- }
-
-#undef area
-
- return ;
-}
-
-/*****************************************************************************
- VCDLIDs: Reads the LIST IDs from the LOT.
- *****************************************************************************/
-static int
-VCDLIDs( input_thread_t * p_input )
-{
- thread_vcd_data_t *p_vcd = (thread_vcd_data_t *) p_input->p_access_data;
-
- p_vcd->num_lids = vcdinfo_get_num_LIDs(p_vcd->vcd);
- p_vcd->cur_lid = VCDINFO_INVALID_ENTRY;
-
- if (vcdinfo_read_psd (p_vcd->vcd)) {
-
- vcdinfo_visit_lot (p_vcd->vcd, false);
-
- if (vcdinfo_get_psd_x_size(p_vcd->vcd))
- vcdinfo_visit_lot (p_vcd->vcd, true);
- }
-
- dbg_print( (INPUT_DBG_CALL|INPUT_DBG_MRL),
- "num LIDs=%d", p_vcd->num_lids);
-
- return 0;
-}