1 /*****************************************************************************
2 * vcdplayer.c : VCD input module for vlc
3 * using libcdio, libvcd and libvcdinfo
4 *****************************************************************************
5 * Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
24 This contains more of the vlc-independent parts that might be used
25 in any VCD input module for a media player. However at present there
26 are vlc-specific structures. See also vcdplayer.c of the xine plugin.
28 /*****************************************************************************
30 *****************************************************************************/
37 #include <vlc_input.h>
38 #include <vlc_interface.h>
41 #include "vcdplayer.h"
45 #include <cdio/cdio.h>
46 #include <cdio/util.h>
47 #include <libvcd/info.h>
49 extern void VCDSetOrigin ( access_t *p_access, lsn_t i_lsn, track_t i_track,
50 const vcdinfo_itemid_t * p_itemid );
53 Return true if playback control (PBC) is on
56 vcdplayer_pbc_is_on( const vcdplayer_t *p_vcdplayer )
58 return VCDINFO_INVALID_ENTRY != p_vcdplayer->i_lid;
61 /* Given an itemid, return the size for the object (via information
62 previously stored when opening the vcd). */
64 vcdplayer_get_item_size(access_t * p_access, vcdinfo_itemid_t itemid)
66 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
68 switch (itemid.type) {
69 case VCDINFO_ITEM_TYPE_ENTRY:
70 return p_vcdplayer->entry[itemid.num].size;
72 case VCDINFO_ITEM_TYPE_SEGMENT:
73 return p_vcdplayer->segment[itemid.num].size;
75 case VCDINFO_ITEM_TYPE_TRACK:
76 return p_vcdplayer->track[itemid.num-1].size;
78 case VCDINFO_ITEM_TYPE_LID:
79 /* Play list number (LID) */
82 case VCDINFO_ITEM_TYPE_NOTFOUND:
83 case VCDINFO_ITEM_TYPE_SPAREID2:
85 LOG_ERR("%s %d", "bad item type", itemid.type);
91 vcdplayer_update_entry( access_t * p_access, uint16_t ofs,
92 uint16_t *entry, const char *label)
94 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
96 if ( ofs == VCDINFO_INVALID_OFFSET ) {
97 *entry = VCDINFO_INVALID_ENTRY;
99 vcdinfo_offset_t *off = vcdinfo_get_offset_t(p_vcdplayer->vcd, ofs);
102 dbg_print(INPUT_DBG_PBC, "%s: LID %d", label, off->lid);
104 *entry = VCDINFO_INVALID_ENTRY;
108 /* Handles navigation when NOT in PBC reaching the end of a play item.
110 The navigations rules here may be sort of made up, but the intent
111 is to do something that's probably right or helpful.
113 return true if the caller should return.
115 vcdplayer_read_status_t
116 vcdplayer_non_pbc_nav ( access_t *p_access, uint8_t *wait_time )
118 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
120 /* Not in playback control. Do we advance automatically or stop? */
121 switch (p_vcdplayer->play_item.type) {
122 case VCDINFO_ITEM_TYPE_TRACK:
123 case VCDINFO_ITEM_TYPE_ENTRY: {
124 if ( ! vcdplayer_play_next( p_access ) )
130 case VCDINFO_ITEM_TYPE_SPAREID2:
131 dbg_print( (INPUT_DBG_STILL|INPUT_DBG_LSN),
133 if (p_vcdplayer->in_still)
135 dbg_print( (INPUT_DBG_STILL|INPUT_DBG_LSN),
136 "End of still spareid2" );
138 return READ_STILL_FRAME ;
141 case VCDINFO_ITEM_TYPE_NOTFOUND:
142 LOG_ERR ("NOTFOUND outside PBC -- not supposed to happen");
144 case VCDINFO_ITEM_TYPE_LID:
145 LOG_ERR ("LID outside PBC -- not supposed to happen");
147 case VCDINFO_ITEM_TYPE_SEGMENT:
148 /* Hack: Just go back and do still again */
150 if (p_vcdplayer->in_still)
152 dbg_print( (INPUT_DBG_STILL|INPUT_DBG_LSN),
153 "End of still Segment" );
155 return READ_STILL_FRAME;
163 Set reading to play an entire track.
166 _vcdplayer_set_track(access_t * p_access, track_t i_track)
168 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
169 if (i_track < 1 || i_track > p_vcdplayer->i_tracks)
172 const vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;
173 vcdinfo_itemid_t itemid;
175 itemid.num = i_track;
176 itemid.type = VCDINFO_ITEM_TYPE_TRACK;
177 p_vcdplayer->in_still = 0;
179 VCDSetOrigin(p_access, vcdinfo_get_track_lsn(p_vcdinfo, i_track),
182 dbg_print(INPUT_DBG_LSN, "LSN: %u", p_vcdplayer->i_lsn);
187 Set reading to play an entry
190 _vcdplayer_set_entry(access_t * p_access, unsigned int num)
192 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
193 vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;
194 const unsigned int i_entries = vcdinfo_get_num_entries(p_vcdinfo);
196 if (num >= i_entries) {
197 LOG_ERR("%s %d", "bad entry number", num);
200 vcdinfo_itemid_t itemid;
203 itemid.type = VCDINFO_ITEM_TYPE_ENTRY;
204 p_vcdplayer->i_still = 0;
206 VCDSetOrigin(p_access, vcdinfo_get_entry_lsn(p_vcdinfo, num),
207 vcdinfo_get_track(p_vcdinfo, num), &itemid);
209 dbg_print(INPUT_DBG_LSN, "LSN: %u, track_end LSN: %u",
210 p_vcdplayer->i_lsn, p_vcdplayer->track_end_lsn);
215 Set reading to play an segment (e.g. still frame)
218 _vcdplayer_set_segment(access_t * p_access, unsigned int num)
220 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
221 vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;
222 segnum_t i_segs = vcdinfo_get_num_segments(p_vcdinfo);
225 LOG_ERR("%s %d", "bad segment number", num);
228 vcdinfo_itemid_t itemid;
230 if (VCDINFO_NULL_LSN==p_vcdplayer->i_lsn) {
232 "Error in getting current segment number", num);
237 itemid.type = VCDINFO_ITEM_TYPE_SEGMENT;
239 VCDSetOrigin(p_access, vcdinfo_get_seg_lsn(p_vcdinfo, num), 0, &itemid);
241 dbg_print(INPUT_DBG_LSN, "LSN: %u", p_vcdplayer->i_lsn);
246 /* Play a single item. */
248 vcdplayer_play_single_item( access_t * p_access, vcdinfo_itemid_t itemid)
250 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
251 vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;
253 dbg_print(INPUT_DBG_CALL, "called itemid.num: %d, itemid.type: %d",
254 itemid.num, itemid.type);
256 p_vcdplayer->i_still = 0;
258 switch (itemid.type) {
259 case VCDINFO_ITEM_TYPE_SEGMENT:
261 vcdinfo_video_segment_type_t segtype
262 = vcdinfo_get_video_type(p_vcdinfo, itemid.num);
263 segnum_t i_segs = vcdinfo_get_num_segments(p_vcdinfo);
265 dbg_print(INPUT_DBG_PBC, "%s (%d), itemid.num: %d",
266 vcdinfo_video_type2str(p_vcdinfo, itemid.num),
267 (int) segtype, itemid.num);
269 if (itemid.num >= i_segs) return false;
270 _vcdplayer_set_segment(p_access, itemid.num);
274 case VCDINFO_FILES_VIDEO_NTSC_STILL:
275 case VCDINFO_FILES_VIDEO_NTSC_STILL2:
276 case VCDINFO_FILES_VIDEO_PAL_STILL:
277 case VCDINFO_FILES_VIDEO_PAL_STILL2:
278 p_vcdplayer->i_still = STILL_READING;
281 p_vcdplayer->i_still = 0;
287 case VCDINFO_ITEM_TYPE_TRACK:
288 dbg_print(INPUT_DBG_PBC, "track %d", itemid.num);
289 if (itemid.num < 1 || itemid.num > p_vcdplayer->i_tracks) return false;
290 _vcdplayer_set_track(p_access, itemid.num);
293 case VCDINFO_ITEM_TYPE_ENTRY:
295 unsigned int i_entries = vcdinfo_get_num_entries(p_vcdinfo);
296 dbg_print(INPUT_DBG_PBC, "entry %d", itemid.num);
297 if (itemid.num >= i_entries) return false;
298 _vcdplayer_set_entry(p_access, itemid.num);
302 case VCDINFO_ITEM_TYPE_LID:
303 LOG_ERR("%s", "Should have converted p_vcdplayer above");
307 case VCDINFO_ITEM_TYPE_NOTFOUND:
308 dbg_print(INPUT_DBG_PBC, "play nothing");
309 p_vcdplayer->i_lsn = p_vcdplayer->end_lsn;
313 LOG_ERR("item type %d not implemented.", itemid.type);
317 p_vcdplayer->play_item = itemid;
319 /* Some players like xine, have a fifo queue of audio and video buffers
320 that need to be flushed when playing a new selection. */
321 /* if (p_vcdplayer->flush_buffers)
322 p_vcdplayer->flush_buffers(); */
327 Set's start origin and size for subsequent seeks.
328 input: p_vcdplayer->i_lsn, p_vcdplayer->play_item
329 changed: p_vcdplayer->origin_lsn, p_vcdplayer->end_lsn
333 vcdplayer_set_origin(access_t *p_access, lsn_t i_lsn, track_t i_track,
334 const vcdinfo_itemid_t *p_itemid)
336 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
337 const size_t i_size= vcdplayer_get_item_size(p_access, *p_itemid);
339 if( VCDINFO_NULL_LSN == i_lsn )
341 LOG_ERR("%s %d", "Invalid LSN for track", i_track);
345 p_vcdplayer->play_item.num = p_itemid->num;
346 p_vcdplayer->play_item.type = p_itemid->type;
347 p_vcdplayer->i_lsn = i_lsn;
348 p_vcdplayer->end_lsn = p_vcdplayer->i_lsn + i_size;
349 p_vcdplayer->origin_lsn = p_vcdplayer->i_lsn;
350 p_vcdplayer->i_track = i_track;
351 p_vcdplayer->track_lsn = vcdinfo_get_track_lsn(p_vcdplayer->vcd,
353 p_vcdplayer->track_end_lsn = p_vcdplayer->track_lsn +
354 vcdinfo_get_track_sect_count(p_vcdplayer->vcd, i_track);
356 dbg_print((INPUT_DBG_CALL|INPUT_DBG_LSN),
357 "lsn %u, end LSN: %u item.num %d, item.type %d",
358 p_vcdplayer->i_lsn, p_vcdplayer->end_lsn,
359 p_vcdplayer->play_item.num, p_vcdplayer->play_item.type);
363 Get the next play-item in the list given in the LIDs. Note play-item
364 here refers to list of play-items for a single LID It shouldn't be
365 confused with a user's list of favorite things to play or the
366 "next" field of a LID which moves us to a different LID.
369 vcdplayer_inc_play_item(access_t *p_access)
372 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
375 dbg_print(INPUT_DBG_CALL, "called pli: %d", p_vcdplayer->pdi);
377 if ( NULL == p_vcdplayer || NULL == p_vcdplayer->pxd.pld ) return false;
379 noi = vcdinf_pld_get_noi(p_vcdplayer->pxd.pld);
381 if ( noi <= 0 ) return false;
383 /* Handle delays like autowait or wait here? */
387 if ( p_vcdplayer->pdi < 0 || p_vcdplayer->pdi >= noi ) return false;
390 uint16_t trans_itemid_num=vcdinf_pld_get_play_item(p_vcdplayer->pxd.pld,
392 vcdinfo_itemid_t trans_itemid;
394 if (VCDINFO_INVALID_ITEMID == trans_itemid_num) return false;
396 vcdinfo_classify_itemid(trans_itemid_num, &trans_itemid);
397 dbg_print(INPUT_DBG_PBC, " play-item[%d]: %s",
398 p_vcdplayer->pdi, vcdinfo_pin2str (trans_itemid_num));
399 return vcdplayer_play_single_item(p_access, trans_itemid);
404 vcdplayer_play(access_t *p_access, vcdinfo_itemid_t itemid)
406 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
408 dbg_print(INPUT_DBG_CALL, "called itemid.num: %d itemid.type: %d",
409 itemid.num, itemid.type);
411 if (!vcdplayer_pbc_is_on(p_vcdplayer)) {
412 vcdplayer_play_single_item(p_access, itemid);
414 /* PBC on - Itemid.num is LID. */
416 vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;
418 if (p_vcdinfo == NULL) return;
420 p_vcdplayer->i_lid = itemid.num;
421 vcdinfo_lid_get_pxd(p_vcdinfo, &(p_vcdplayer->pxd), itemid.num);
423 switch (p_vcdplayer->pxd.descriptor_type) {
425 case PSD_TYPE_SELECTION_LIST:
426 case PSD_TYPE_EXT_SELECTION_LIST: {
427 vcdinfo_itemid_t trans_itemid;
428 uint16_t trans_itemid_num;
430 if (p_vcdplayer->pxd.psd == NULL) return;
431 trans_itemid_num = vcdinf_psd_get_itemid(p_vcdplayer->pxd.psd);
432 vcdinfo_classify_itemid(trans_itemid_num, &trans_itemid);
433 p_vcdplayer->i_loop = 1;
434 p_vcdplayer->loop_item = trans_itemid;
435 vcdplayer_play_single_item(p_access, trans_itemid);
439 case PSD_TYPE_PLAY_LIST: {
440 if (p_vcdplayer->pxd.pld == NULL) return;
441 p_vcdplayer->pdi = -1;
442 vcdplayer_inc_play_item(p_access);
446 case PSD_TYPE_END_LIST:
447 case PSD_TYPE_COMMAND_LIST:
455 /* Handles PBC navigation when reaching the end of a play item. */
456 vcdplayer_read_status_t
457 vcdplayer_pbc_nav ( access_t * p_access, uint8_t *wait_time )
459 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
461 /* We are in playback control. */
462 vcdinfo_itemid_t itemid;
464 /* The end of an entry is really the end of the associated
465 sequence (or track). */
467 if ( (VCDINFO_ITEM_TYPE_ENTRY == p_vcdplayer->play_item.type) &&
468 (p_vcdplayer->i_lsn < p_vcdplayer->end_lsn) ) {
469 /* Set up to just continue to the next entry */
470 p_vcdplayer->play_item.num++;
471 dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC),
472 "continuing into next entry: %u", p_vcdplayer->play_item.num);
473 vcdplayer_play_single_item( p_access, p_vcdplayer->play_item );
474 /* p_vcdplayer->update_title(); */
478 switch (p_vcdplayer->pxd.descriptor_type) {
479 case PSD_TYPE_END_LIST:
482 case PSD_TYPE_PLAY_LIST: {
483 if (vcdplayer_inc_play_item(p_access))
486 /* Set up for caller process wait time given. */
487 if (p_vcdplayer->i_still) {
488 *wait_time = vcdinf_get_wait_time(p_vcdplayer->pxd.pld);
489 dbg_print((INPUT_DBG_PBC|INPUT_DBG_STILL),
490 "playlist wait time: %d", *wait_time);
491 return READ_STILL_FRAME;
494 /* Wait time has been processed; continue with next entry. */
495 vcdplayer_update_entry( p_access,
496 vcdinf_pld_get_next_offset(p_vcdplayer->pxd.pld),
497 &itemid.num, "next" );
498 itemid.type = VCDINFO_ITEM_TYPE_LID;
499 vcdplayer_play( p_access, itemid );
502 case PSD_TYPE_SELECTION_LIST: /* Selection List (+Ext. for SVCD) */
503 case PSD_TYPE_EXT_SELECTION_LIST: /* Extended Selection List (VCD2.0) */
505 uint16_t timeout_offs = vcdinf_get_timeout_offset(p_vcdplayer->pxd.psd);
506 uint16_t max_loop = vcdinf_get_loop_count(p_vcdplayer->pxd.psd);
507 vcdinfo_offset_t *offset_timeout_LID =
508 vcdinfo_get_offset_t(p_vcdplayer->vcd, timeout_offs);
510 dbg_print(INPUT_DBG_PBC, "looped: %d, max_loop %d",
511 p_vcdplayer->i_loop, max_loop);
513 /* Set up for caller process wait time given. */
514 if (p_vcdplayer->i_still) {
515 *wait_time = vcdinf_get_timeout_time(p_vcdplayer->pxd.psd);
516 dbg_print((INPUT_DBG_PBC|INPUT_DBG_STILL),
517 "playlist wait_time: %d", *wait_time);
518 return READ_STILL_FRAME;
521 /* Wait time has been processed; continue with next entry. */
522 /* Handle any looping given. */
523 if ( max_loop == 0 || p_vcdplayer->i_loop < max_loop ) {
524 p_vcdplayer->i_loop++;
525 if (p_vcdplayer->i_loop == 0x7f) p_vcdplayer->i_loop = 0;
526 vcdplayer_play_single_item(p_access, p_vcdplayer->loop_item);
527 /* if (p_vcdplayer->i_still) p_vcdplayer->force_redisplay();*/
531 /* Looping finished and wait finished. Move to timeout
532 entry or next entry, or handle still. */
534 if (NULL != offset_timeout_LID) {
535 /* Handle timeout_LID */
536 itemid.num = offset_timeout_LID->lid;
537 itemid.type = VCDINFO_ITEM_TYPE_LID;
538 dbg_print(INPUT_DBG_PBC, "timeout to: %d", itemid.num);
539 vcdplayer_play( p_access, itemid );
542 int i_selections = vcdinf_get_num_selections(p_vcdplayer->pxd.psd);
543 if (i_selections > 0) {
544 /* Pick a random selection. */
545 unsigned int bsn=vcdinf_get_bsn(p_vcdplayer->pxd.psd);
546 int rand_selection=bsn +
547 (int) ((i_selections+0.0)*rand()/(RAND_MAX+1.0));
548 lid_t rand_lid=vcdinfo_selection_get_lid (p_vcdplayer->vcd,
551 itemid.num = rand_lid;
552 itemid.type = VCDINFO_ITEM_TYPE_LID;
553 dbg_print(INPUT_DBG_PBC, "random selection %d, lid: %d",
554 rand_selection - bsn, rand_lid);
555 vcdplayer_play( p_access, itemid );
557 } else if (p_vcdplayer->i_still) {
558 /* Hack: Just go back and do still again */
560 return READ_STILL_FRAME;
565 case VCDINFO_ITEM_TYPE_NOTFOUND:
566 LOG_ERR( "NOTFOUND in PBC -- not supposed to happen" );
568 case VCDINFO_ITEM_TYPE_SPAREID2:
569 LOG_ERR( "SPAREID2 in PBC -- not supposed to happen" );
571 case VCDINFO_ITEM_TYPE_LID:
572 LOG_ERR( "LID in PBC -- not supposed to happen" );
578 /* FIXME: Should handle autowait ... */
584 Read block into p_buf and return the status back.
586 This routine is a bit complicated because on reaching the end of
587 a track or entry we may automatically advance to the item, or
588 interpret the next item in the playback-control list.
590 vcdplayer_read_status_t
591 vcdplayer_read (access_t * p_access, uint8_t *p_buf)
594 /* p_access->handle_events (); */
597 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
598 if ( p_vcdplayer->i_lsn > p_vcdplayer->end_lsn ) {
599 vcdplayer_read_status_t read_status;
601 /* We've run off of the end of this entry. Do we continue or stop? */
602 dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC),
603 "end reached, cur: %u, end: %u\n", p_vcdplayer->i_lsn, p_vcdplayer->end_lsn);
605 handle_item_continuation:
606 read_status = vcdplayer_pbc_is_on( p_vcdplayer )
607 ? vcdplayer_pbc_nav( p_access, &wait_time )
608 : vcdplayer_non_pbc_nav( p_access, &wait_time );
610 if (READ_STILL_FRAME == read_status) {
612 return READ_STILL_FRAME;
615 if (READ_BLOCK != read_status) return read_status;
618 /* Read the next block.
620 Important note: we probably speed things up by removing "data"
621 and the memcpy to it by extending vcd_image_source_read_mode2
622 to allow a mode to do what's below in addition to its
623 "raw" and "block" mode. It also would probably improve the modularity
624 a little bit as well.
628 CdIo *p_img = vcdinfo_get_cd_image(p_vcdplayer->vcd);
630 uint8_t subheader [CDIO_CD_SUBHEADER_SIZE];
631 uint8_t data [M2F2_SECTOR_SIZE];
634 vcdsector_t vcd_sector;
637 if (cdio_read_mode2_sector(p_img, &vcd_sector,
638 p_vcdplayer->i_lsn, true)!=0) {
639 dbg_print(INPUT_DBG_LSN, "read error\n");
640 p_vcdplayer->i_lsn++;
643 p_vcdplayer->i_lsn++;
645 if ( p_vcdplayer->i_lsn >= p_vcdplayer->end_lsn ) {
646 /* We've run off of the end of this entry. Do we continue or stop? */
647 dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC),
648 "end reached in reading, cur: %u, end: %u\n",
649 p_vcdplayer->i_lsn, p_vcdplayer->end_lsn);
653 /* Check header ID for a padding sector and simply discard
654 these. It is alleged that VCD's put these in to keep the
657 } while((vcd_sector.subheader[2]&~0x01)==0x60);
659 if ( p_vcdplayer->i_lsn >= p_vcdplayer->end_lsn )
660 /* We've run off of the end of this entry. Do we continue or stop? */
661 goto handle_item_continuation;
663 memcpy (p_buf, vcd_sector.data, M2F2_SECTOR_SIZE);
669 Play item assocated with the "default" selection.
671 Return false if there was some problem.
674 vcdplayer_play_default( access_t * p_access )
676 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
678 vcdinfo_itemid_t itemid;
681 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_PBC),
682 "null p_vcdplayer" );
687 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_PBC),
688 "current: %d" , p_vcdplayer->play_item.num);
690 itemid.type = p_vcdplayer->play_item.type;
692 if (vcdplayer_pbc_is_on(p_vcdplayer)) {
694 #if defined(LIBVCD_VERSION)
695 lid_t lid=vcdinfo_get_multi_default_lid(p_vcdplayer->vcd, p_vcdplayer->i_lid,
698 if (VCDINFO_INVALID_LID != lid) {
700 itemid.type = VCDINFO_ITEM_TYPE_LID;
701 dbg_print(INPUT_DBG_PBC, "DEFAULT to %d", itemid.num);
703 dbg_print(INPUT_DBG_PBC, "no DEFAULT for LID %d", p_vcdplayer->i_lid);
708 vcdinfo_lid_get_pxd(p_vcdplayer->vcd, &(p_vcdplayer->pxd), p_vcdplayer->i_lid);
710 switch (p_vcdplayer->pxd.descriptor_type) {
711 case PSD_TYPE_SELECTION_LIST:
712 case PSD_TYPE_EXT_SELECTION_LIST:
713 if (p_vcdplayer->pxd.psd == NULL) return false;
714 vcdplayer_update_entry( p_access,
715 vcdinfo_get_default_offset(p_vcdplayer->vcd,
717 &itemid.num, "default");
720 case PSD_TYPE_PLAY_LIST:
721 case PSD_TYPE_END_LIST:
722 case PSD_TYPE_COMMAND_LIST:
723 LOG_WARN( "There is no PBC 'default' selection here" );
726 #endif /* LIBVCD_VERSION (< 0.7.21) */
731 /* PBC is not on. "default" selection beginning of current
734 itemid.num = p_vcdplayer->play_item.num;
738 /** ??? p_vcdplayer->update_title(); ***/
739 vcdplayer_play( p_access, itemid );
745 Play item assocated with the "next" selection.
747 Return false if there was some problem.
750 vcdplayer_play_next( access_t * p_access )
752 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
754 vcdinfo_obj_t *p_vcdinfo;
755 vcdinfo_itemid_t itemid;
757 if (!p_vcdplayer) return false;
759 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_PBC),
760 "current: %d" , p_vcdplayer->play_item.num);
762 p_vcdinfo = p_vcdplayer->vcd;
764 itemid = p_vcdplayer->play_item;
766 if (vcdplayer_pbc_is_on(p_vcdplayer)) {
768 vcdinfo_lid_get_pxd(p_vcdinfo, &(p_vcdplayer->pxd), p_vcdplayer->i_lid);
770 switch (p_vcdplayer->pxd.descriptor_type) {
771 case PSD_TYPE_SELECTION_LIST:
772 case PSD_TYPE_EXT_SELECTION_LIST:
773 if (p_vcdplayer->pxd.psd == NULL) return false;
774 vcdplayer_update_entry( p_access,
775 vcdinf_psd_get_next_offset(p_vcdplayer->pxd.psd),
776 &itemid.num, "next");
777 itemid.type = VCDINFO_ITEM_TYPE_LID;
780 case PSD_TYPE_PLAY_LIST:
781 if (p_vcdplayer->pxd.pld == NULL) return false;
782 vcdplayer_update_entry( p_access,
783 vcdinf_pld_get_next_offset(p_vcdplayer->pxd.pld),
784 &itemid.num, "next");
785 itemid.type = VCDINFO_ITEM_TYPE_LID;
788 case PSD_TYPE_END_LIST:
789 case PSD_TYPE_COMMAND_LIST:
790 LOG_WARN( "There is no PBC 'next' selection here" );
795 /* PBC is not on. "Next" selection is play_item.num+1 if possible. */
799 switch (p_vcdplayer->play_item.type) {
800 case VCDINFO_ITEM_TYPE_ENTRY:
801 case VCDINFO_ITEM_TYPE_SEGMENT:
802 case VCDINFO_ITEM_TYPE_TRACK:
804 switch (p_vcdplayer->play_item.type) {
805 case VCDINFO_ITEM_TYPE_ENTRY:
806 max_entry = p_vcdplayer->i_entries;
808 case VCDINFO_ITEM_TYPE_SEGMENT:
809 max_entry = p_vcdplayer->i_segments;
811 case VCDINFO_ITEM_TYPE_TRACK:
812 max_entry = p_vcdplayer->i_tracks;
814 default: ; /* Handle exceptional cases below */
817 if (p_vcdplayer->play_item.num+1 < max_entry) {
818 itemid.num = p_vcdplayer->play_item.num+1;
820 LOG_WARN( "At the end - non-PBC 'next' not possible here" );
826 case VCDINFO_ITEM_TYPE_LID:
828 /* Should have handled above. */
829 LOG_WARN( "Internal inconsistency - should not have gotten here." );
837 /** ??? p_vcdplayer->update_title(); ***/
838 vcdplayer_play( p_access, itemid );
844 Play item assocated with the "prev" selection.
846 Return false if there was some problem.
849 vcdplayer_play_prev( access_t * p_access )
851 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
852 vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;
853 vcdinfo_itemid_t itemid;
855 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_PBC),
856 "current: %d" , p_vcdplayer->play_item.num);
858 itemid = p_vcdplayer->play_item;
860 if (vcdplayer_pbc_is_on(p_vcdplayer)) {
862 vcdinfo_lid_get_pxd(p_vcdinfo, &(p_vcdplayer->pxd), p_vcdplayer->i_lid);
864 switch (p_vcdplayer->pxd.descriptor_type) {
865 case PSD_TYPE_SELECTION_LIST:
866 case PSD_TYPE_EXT_SELECTION_LIST:
867 if (p_vcdplayer->pxd.psd == NULL) return false;
868 vcdplayer_update_entry( p_access,
869 vcdinf_psd_get_prev_offset(p_vcdplayer->pxd.psd),
870 &itemid.num, "prev");
871 itemid.type = VCDINFO_ITEM_TYPE_LID;
874 case PSD_TYPE_PLAY_LIST:
875 if (p_vcdplayer->pxd.pld == NULL) return false;
876 vcdplayer_update_entry( p_access,
877 vcdinf_pld_get_prev_offset(p_vcdplayer->pxd.pld),
878 &itemid.num, "prev");
879 itemid.type = VCDINFO_ITEM_TYPE_LID;
882 case PSD_TYPE_END_LIST:
883 case PSD_TYPE_COMMAND_LIST:
884 LOG_WARN( "There is no PBC 'prev' selection here" );
889 /* PBC is not on. "Prev" selection is play_item.num-1 if possible. */
891 int min_entry = (VCDINFO_ITEM_TYPE_ENTRY == p_vcdplayer->play_item.type)
894 if (p_vcdplayer->play_item.num > min_entry) {
895 itemid.num = p_vcdplayer->play_item.num-1;
897 LOG_WARN( "At the beginning - non-PBC 'prev' not possible here" );
903 /** ??? p_vcdplayer->update_title(); ***/
904 vcdplayer_play( p_access, itemid );
910 Play item assocated with the "return" selection.
912 Return false if there was some problem.
915 vcdplayer_play_return( access_t * p_access )
917 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
918 vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;
919 vcdinfo_itemid_t itemid;
921 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_PBC),
922 "current: %d" , p_vcdplayer->play_item.num);
924 itemid = p_vcdplayer->play_item;
926 if (vcdplayer_pbc_is_on(p_vcdplayer)) {
928 vcdinfo_lid_get_pxd(p_vcdinfo, &(p_vcdplayer->pxd), p_vcdplayer->i_lid);
930 switch (p_vcdplayer->pxd.descriptor_type) {
931 case PSD_TYPE_SELECTION_LIST:
932 case PSD_TYPE_EXT_SELECTION_LIST:
933 if (p_vcdplayer->pxd.psd == NULL) return false;
934 vcdplayer_update_entry( p_access,
935 vcdinf_psd_get_return_offset(p_vcdplayer->pxd.psd),
936 &itemid.num, "return");
937 itemid.type = VCDINFO_ITEM_TYPE_LID;
940 case PSD_TYPE_PLAY_LIST:
941 if (p_vcdplayer->pxd.pld == NULL) return false;
942 vcdplayer_update_entry( p_access,
943 vcdinf_pld_get_return_offset(p_vcdplayer->pxd.pld),
944 &itemid.num, "return");
945 itemid.type = VCDINFO_ITEM_TYPE_LID;
948 case PSD_TYPE_END_LIST:
949 case PSD_TYPE_COMMAND_LIST:
950 LOG_WARN( "There is no PBC 'return' selection here" );
955 /* PBC is not on. "Return" selection is min_entry if possible. */
957 p_vcdplayer->play_item.num =
958 (VCDINFO_ITEM_TYPE_ENTRY == p_vcdplayer->play_item.type)
963 /** ??? p_vcdplayer->update_title(); ***/
964 vcdplayer_play( p_access, itemid );
971 * c-file-style: "gnu"
973 * indent-tabs-mode: nil