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 *****************************************************************************/
33 #include <vlc_input.h>
34 #include <vlc_interface.h>
37 #include "vcdplayer.h"
41 #include <cdio/cdio.h>
42 #include <cdio/util.h>
43 #include <libvcd/info.h>
45 extern void VCDSetOrigin ( access_t *p_access, lsn_t i_lsn, track_t i_track,
46 const vcdinfo_itemid_t * p_itemid );
49 Return true if playback control (PBC) is on
52 vcdplayer_pbc_is_on( const vcdplayer_t *p_vcdplayer )
54 return VCDINFO_INVALID_ENTRY != p_vcdplayer->i_lid;
57 /* Given an itemid, return the size for the object (via information
58 previously stored when opening the vcd). */
60 vcdplayer_get_item_size(access_t * p_access, vcdinfo_itemid_t itemid)
62 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
64 switch (itemid.type) {
65 case VCDINFO_ITEM_TYPE_ENTRY:
66 return p_vcdplayer->entry[itemid.num].size;
68 case VCDINFO_ITEM_TYPE_SEGMENT:
69 return p_vcdplayer->segment[itemid.num].size;
71 case VCDINFO_ITEM_TYPE_TRACK:
72 return p_vcdplayer->track[itemid.num-1].size;
74 case VCDINFO_ITEM_TYPE_LID:
75 /* Play list number (LID) */
78 case VCDINFO_ITEM_TYPE_NOTFOUND:
79 case VCDINFO_ITEM_TYPE_SPAREID2:
81 LOG_ERR("%s %d", "bad item type", itemid.type);
87 vcdplayer_update_entry( access_t * p_access, uint16_t ofs,
88 uint16_t *entry, const char *label)
90 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
92 if ( ofs == VCDINFO_INVALID_OFFSET ) {
93 *entry = VCDINFO_INVALID_ENTRY;
95 vcdinfo_offset_t *off = vcdinfo_get_offset_t(p_vcdplayer->vcd, ofs);
98 dbg_print(INPUT_DBG_PBC, "%s: LID %d", label, off->lid);
100 *entry = VCDINFO_INVALID_ENTRY;
104 /* Handles navigation when NOT in PBC reaching the end of a play item.
106 The navigations rules here may be sort of made up, but the intent
107 is to do something that's probably right or helpful.
109 return true if the caller should return.
111 vcdplayer_read_status_t
112 vcdplayer_non_pbc_nav ( access_t *p_access, uint8_t *wait_time )
114 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
116 /* Not in playback control. Do we advance automatically or stop? */
117 switch (p_vcdplayer->play_item.type) {
118 case VCDINFO_ITEM_TYPE_TRACK:
119 case VCDINFO_ITEM_TYPE_ENTRY: {
120 if ( ! vcdplayer_play_next( p_access ) )
126 case VCDINFO_ITEM_TYPE_SPAREID2:
127 dbg_print( (INPUT_DBG_STILL|INPUT_DBG_LSN),
129 if (p_vcdplayer->in_still)
131 dbg_print( (INPUT_DBG_STILL|INPUT_DBG_LSN),
132 "End of still spareid2" );
134 return READ_STILL_FRAME ;
137 case VCDINFO_ITEM_TYPE_NOTFOUND:
138 LOG_ERR ("NOTFOUND outside PBC -- not supposed to happen");
140 case VCDINFO_ITEM_TYPE_LID:
141 LOG_ERR ("LID outside PBC -- not supposed to happen");
143 case VCDINFO_ITEM_TYPE_SEGMENT:
144 /* Hack: Just go back and do still again */
146 if (p_vcdplayer->in_still)
148 dbg_print( (INPUT_DBG_STILL|INPUT_DBG_LSN),
149 "End of still Segment" );
151 return READ_STILL_FRAME;
159 Set reading to play an entire track.
162 _vcdplayer_set_track(access_t * p_access, track_t i_track)
164 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
165 if (i_track < 1 || i_track > p_vcdplayer->i_tracks)
168 const vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;
169 vcdinfo_itemid_t itemid;
171 itemid.num = i_track;
172 itemid.type = VCDINFO_ITEM_TYPE_TRACK;
173 p_vcdplayer->in_still = 0;
175 VCDSetOrigin(p_access, vcdinfo_get_track_lsn(p_vcdinfo, i_track),
178 dbg_print(INPUT_DBG_LSN, "LSN: %u", p_vcdplayer->i_lsn);
183 Set reading to play an entry
186 _vcdplayer_set_entry(access_t * p_access, unsigned int num)
188 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
189 vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;
190 const unsigned int i_entries = vcdinfo_get_num_entries(p_vcdinfo);
192 if (num >= i_entries) {
193 LOG_ERR("%s %d", "bad entry number", num);
196 vcdinfo_itemid_t itemid;
199 itemid.type = VCDINFO_ITEM_TYPE_ENTRY;
200 p_vcdplayer->i_still = 0;
202 VCDSetOrigin(p_access, vcdinfo_get_entry_lsn(p_vcdinfo, num),
203 vcdinfo_get_track(p_vcdinfo, num), &itemid);
205 dbg_print(INPUT_DBG_LSN, "LSN: %u, track_end LSN: %u",
206 p_vcdplayer->i_lsn, p_vcdplayer->track_end_lsn);
211 Set reading to play an segment (e.g. still frame)
214 _vcdplayer_set_segment(access_t * p_access, unsigned int num)
216 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
217 vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;
218 segnum_t i_segs = vcdinfo_get_num_segments(p_vcdinfo);
221 LOG_ERR("%s %d", "bad segment number", num);
224 vcdinfo_itemid_t itemid;
226 if (VCDINFO_NULL_LSN==p_vcdplayer->i_lsn) {
228 "Error in getting current segment number", num);
233 itemid.type = VCDINFO_ITEM_TYPE_SEGMENT;
235 VCDSetOrigin(p_access, vcdinfo_get_seg_lsn(p_vcdinfo, num), 0, &itemid);
237 dbg_print(INPUT_DBG_LSN, "LSN: %u", p_vcdplayer->i_lsn);
242 /* Play a single item. */
244 vcdplayer_play_single_item( access_t * p_access, vcdinfo_itemid_t itemid)
246 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
247 vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;
249 dbg_print(INPUT_DBG_CALL, "called itemid.num: %d, itemid.type: %d",
250 itemid.num, itemid.type);
252 p_vcdplayer->i_still = 0;
254 switch (itemid.type) {
255 case VCDINFO_ITEM_TYPE_SEGMENT:
257 vcdinfo_video_segment_type_t segtype
258 = vcdinfo_get_video_type(p_vcdinfo, itemid.num);
259 segnum_t i_segs = vcdinfo_get_num_segments(p_vcdinfo);
261 dbg_print(INPUT_DBG_PBC, "%s (%d), itemid.num: %d",
262 vcdinfo_video_type2str(p_vcdinfo, itemid.num),
263 (int) segtype, itemid.num);
265 if (itemid.num >= i_segs) return false;
266 _vcdplayer_set_segment(p_access, itemid.num);
270 case VCDINFO_FILES_VIDEO_NTSC_STILL:
271 case VCDINFO_FILES_VIDEO_NTSC_STILL2:
272 case VCDINFO_FILES_VIDEO_PAL_STILL:
273 case VCDINFO_FILES_VIDEO_PAL_STILL2:
274 p_vcdplayer->i_still = STILL_READING;
277 p_vcdplayer->i_still = 0;
283 case VCDINFO_ITEM_TYPE_TRACK:
284 dbg_print(INPUT_DBG_PBC, "track %d", itemid.num);
285 if (itemid.num < 1 || itemid.num > p_vcdplayer->i_tracks) return false;
286 _vcdplayer_set_track(p_access, itemid.num);
289 case VCDINFO_ITEM_TYPE_ENTRY:
291 unsigned int i_entries = vcdinfo_get_num_entries(p_vcdinfo);
292 dbg_print(INPUT_DBG_PBC, "entry %d", itemid.num);
293 if (itemid.num >= i_entries) return false;
294 _vcdplayer_set_entry(p_access, itemid.num);
298 case VCDINFO_ITEM_TYPE_LID:
299 LOG_ERR("%s", "Should have converted p_vcdplayer above");
303 case VCDINFO_ITEM_TYPE_NOTFOUND:
304 dbg_print(INPUT_DBG_PBC, "play nothing");
305 p_vcdplayer->i_lsn = p_vcdplayer->end_lsn;
309 LOG_ERR("item type %d not implemented.", itemid.type);
313 p_vcdplayer->play_item = itemid;
315 /* Some players like xine, have a fifo queue of audio and video buffers
316 that need to be flushed when playing a new selection. */
317 /* if (p_vcdplayer->flush_buffers)
318 p_vcdplayer->flush_buffers(); */
323 Set's start origin and size for subsequent seeks.
324 input: p_vcdplayer->i_lsn, p_vcdplayer->play_item
325 changed: p_vcdplayer->origin_lsn, p_vcdplayer->end_lsn
329 vcdplayer_set_origin(access_t *p_access, lsn_t i_lsn, track_t i_track,
330 const vcdinfo_itemid_t *p_itemid)
332 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
333 const size_t i_size= vcdplayer_get_item_size(p_access, *p_itemid);
335 if( VCDINFO_NULL_LSN == i_lsn )
337 LOG_ERR("%s %d", "Invalid LSN for track", i_track);
341 p_vcdplayer->play_item.num = p_itemid->num;
342 p_vcdplayer->play_item.type = p_itemid->type;
343 p_vcdplayer->i_lsn = i_lsn;
344 p_vcdplayer->end_lsn = p_vcdplayer->i_lsn + i_size;
345 p_vcdplayer->origin_lsn = p_vcdplayer->i_lsn;
346 p_vcdplayer->i_track = i_track;
347 p_vcdplayer->track_lsn = vcdinfo_get_track_lsn(p_vcdplayer->vcd,
349 p_vcdplayer->track_end_lsn = p_vcdplayer->track_lsn +
350 vcdinfo_get_track_sect_count(p_vcdplayer->vcd, i_track);
352 dbg_print((INPUT_DBG_CALL|INPUT_DBG_LSN),
353 "lsn %u, end LSN: %u item.num %d, item.type %d",
354 p_vcdplayer->i_lsn, p_vcdplayer->end_lsn,
355 p_vcdplayer->play_item.num, p_vcdplayer->play_item.type);
359 Get the next play-item in the list given in the LIDs. Note play-item
360 here refers to list of play-items for a single LID It shouldn't be
361 confused with a user's list of favorite things to play or the
362 "next" field of a LID which moves us to a different LID.
365 vcdplayer_inc_play_item(access_t *p_access)
368 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
371 dbg_print(INPUT_DBG_CALL, "called pli: %d", p_vcdplayer->pdi);
373 if ( NULL == p_vcdplayer || NULL == p_vcdplayer->pxd.pld ) return false;
375 noi = vcdinf_pld_get_noi(p_vcdplayer->pxd.pld);
377 if ( noi <= 0 ) return false;
379 /* Handle delays like autowait or wait here? */
383 if ( p_vcdplayer->pdi < 0 || p_vcdplayer->pdi >= noi ) return false;
386 uint16_t trans_itemid_num=vcdinf_pld_get_play_item(p_vcdplayer->pxd.pld,
388 vcdinfo_itemid_t trans_itemid;
390 if (VCDINFO_INVALID_ITEMID == trans_itemid_num) return false;
392 vcdinfo_classify_itemid(trans_itemid_num, &trans_itemid);
393 dbg_print(INPUT_DBG_PBC, " play-item[%d]: %s",
394 p_vcdplayer->pdi, vcdinfo_pin2str (trans_itemid_num));
395 return vcdplayer_play_single_item(p_access, trans_itemid);
400 vcdplayer_play(access_t *p_access, vcdinfo_itemid_t itemid)
402 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
404 dbg_print(INPUT_DBG_CALL, "called itemid.num: %d itemid.type: %d",
405 itemid.num, itemid.type);
407 if (!vcdplayer_pbc_is_on(p_vcdplayer)) {
408 vcdplayer_play_single_item(p_access, itemid);
410 /* PBC on - Itemid.num is LID. */
412 vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;
414 if (p_vcdinfo == NULL) return;
416 p_vcdplayer->i_lid = itemid.num;
417 vcdinfo_lid_get_pxd(p_vcdinfo, &(p_vcdplayer->pxd), itemid.num);
419 switch (p_vcdplayer->pxd.descriptor_type) {
421 case PSD_TYPE_SELECTION_LIST:
422 case PSD_TYPE_EXT_SELECTION_LIST: {
423 vcdinfo_itemid_t trans_itemid;
424 uint16_t trans_itemid_num;
426 if (p_vcdplayer->pxd.psd == NULL) return;
427 trans_itemid_num = vcdinf_psd_get_itemid(p_vcdplayer->pxd.psd);
428 vcdinfo_classify_itemid(trans_itemid_num, &trans_itemid);
429 p_vcdplayer->i_loop = 1;
430 p_vcdplayer->loop_item = trans_itemid;
431 vcdplayer_play_single_item(p_access, trans_itemid);
435 case PSD_TYPE_PLAY_LIST: {
436 if (p_vcdplayer->pxd.pld == NULL) return;
437 p_vcdplayer->pdi = -1;
438 vcdplayer_inc_play_item(p_access);
442 case PSD_TYPE_END_LIST:
443 case PSD_TYPE_COMMAND_LIST:
451 /* Handles PBC navigation when reaching the end of a play item. */
452 vcdplayer_read_status_t
453 vcdplayer_pbc_nav ( access_t * p_access, uint8_t *wait_time )
455 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
457 /* We are in playback control. */
458 vcdinfo_itemid_t itemid;
460 /* The end of an entry is really the end of the associated
461 sequence (or track). */
463 if ( (VCDINFO_ITEM_TYPE_ENTRY == p_vcdplayer->play_item.type) &&
464 (p_vcdplayer->i_lsn < p_vcdplayer->end_lsn) ) {
465 /* Set up to just continue to the next entry */
466 p_vcdplayer->play_item.num++;
467 dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC),
468 "continuing into next entry: %u", p_vcdplayer->play_item.num);
469 vcdplayer_play_single_item( p_access, p_vcdplayer->play_item );
470 /* p_vcdplayer->update_title(); */
474 switch (p_vcdplayer->pxd.descriptor_type) {
475 case PSD_TYPE_END_LIST:
478 case PSD_TYPE_PLAY_LIST: {
479 if (vcdplayer_inc_play_item(p_access))
482 /* Set up for caller process wait time given. */
483 if (p_vcdplayer->i_still) {
484 *wait_time = vcdinf_get_wait_time(p_vcdplayer->pxd.pld);
485 dbg_print((INPUT_DBG_PBC|INPUT_DBG_STILL),
486 "playlist wait time: %d", *wait_time);
487 return READ_STILL_FRAME;
490 /* Wait time has been processed; continue with next entry. */
491 vcdplayer_update_entry( p_access,
492 vcdinf_pld_get_next_offset(p_vcdplayer->pxd.pld),
493 &itemid.num, "next" );
494 itemid.type = VCDINFO_ITEM_TYPE_LID;
495 vcdplayer_play( p_access, itemid );
498 case PSD_TYPE_SELECTION_LIST: /* Selection List (+Ext. for SVCD) */
499 case PSD_TYPE_EXT_SELECTION_LIST: /* Extended Selection List (VCD2.0) */
501 uint16_t timeout_offs = vcdinf_get_timeout_offset(p_vcdplayer->pxd.psd);
502 uint16_t max_loop = vcdinf_get_loop_count(p_vcdplayer->pxd.psd);
503 vcdinfo_offset_t *offset_timeout_LID =
504 vcdinfo_get_offset_t(p_vcdplayer->vcd, timeout_offs);
506 dbg_print(INPUT_DBG_PBC, "looped: %d, max_loop %d",
507 p_vcdplayer->i_loop, max_loop);
509 /* Set up for caller process wait time given. */
510 if (p_vcdplayer->i_still) {
511 *wait_time = vcdinf_get_timeout_time(p_vcdplayer->pxd.psd);
512 dbg_print((INPUT_DBG_PBC|INPUT_DBG_STILL),
513 "playlist wait_time: %d", *wait_time);
514 return READ_STILL_FRAME;
517 /* Wait time has been processed; continue with next entry. */
518 /* Handle any looping given. */
519 if ( max_loop == 0 || p_vcdplayer->i_loop < max_loop ) {
520 p_vcdplayer->i_loop++;
521 if (p_vcdplayer->i_loop == 0x7f) p_vcdplayer->i_loop = 0;
522 vcdplayer_play_single_item(p_access, p_vcdplayer->loop_item);
523 /* if (p_vcdplayer->i_still) p_vcdplayer->force_redisplay();*/
527 /* Looping finished and wait finished. Move to timeout
528 entry or next entry, or handle still. */
530 if (NULL != offset_timeout_LID) {
531 /* Handle timeout_LID */
532 itemid.num = offset_timeout_LID->lid;
533 itemid.type = VCDINFO_ITEM_TYPE_LID;
534 dbg_print(INPUT_DBG_PBC, "timeout to: %d", itemid.num);
535 vcdplayer_play( p_access, itemid );
538 int i_selections = vcdinf_get_num_selections(p_vcdplayer->pxd.psd);
539 if (i_selections > 0) {
540 /* Pick a random selection. */
541 unsigned int bsn=vcdinf_get_bsn(p_vcdplayer->pxd.psd);
542 int rand_selection=bsn +
543 (int) ((i_selections+0.0)*rand()/(RAND_MAX+1.0));
544 lid_t rand_lid=vcdinfo_selection_get_lid (p_vcdplayer->vcd,
547 itemid.num = rand_lid;
548 itemid.type = VCDINFO_ITEM_TYPE_LID;
549 dbg_print(INPUT_DBG_PBC, "random selection %d, lid: %d",
550 rand_selection - bsn, rand_lid);
551 vcdplayer_play( p_access, itemid );
553 } else if (p_vcdplayer->i_still) {
554 /* Hack: Just go back and do still again */
556 return READ_STILL_FRAME;
561 case VCDINFO_ITEM_TYPE_NOTFOUND:
562 LOG_ERR( "NOTFOUND in PBC -- not supposed to happen" );
564 case VCDINFO_ITEM_TYPE_SPAREID2:
565 LOG_ERR( "SPAREID2 in PBC -- not supposed to happen" );
567 case VCDINFO_ITEM_TYPE_LID:
568 LOG_ERR( "LID in PBC -- not supposed to happen" );
574 /* FIXME: Should handle autowait ... */
580 Read block into p_buf and return the status back.
582 This routine is a bit complicated because on reaching the end of
583 a track or entry we may automatically advance to the item, or
584 interpret the next item in the playback-control list.
586 vcdplayer_read_status_t
587 vcdplayer_read (access_t * p_access, uint8_t *p_buf)
590 /* p_access->handle_events (); */
593 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
594 if ( p_vcdplayer->i_lsn > p_vcdplayer->end_lsn ) {
595 vcdplayer_read_status_t read_status;
597 /* We've run off of the end of this entry. Do we continue or stop? */
598 dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC),
599 "end reached, cur: %u, end: %u\n", p_vcdplayer->i_lsn, p_vcdplayer->end_lsn);
601 handle_item_continuation:
602 read_status = vcdplayer_pbc_is_on( p_vcdplayer )
603 ? vcdplayer_pbc_nav( p_access, &wait_time )
604 : vcdplayer_non_pbc_nav( p_access, &wait_time );
606 if (READ_STILL_FRAME == read_status) {
608 return READ_STILL_FRAME;
611 if (READ_BLOCK != read_status) return read_status;
614 /* Read the next block.
616 Important note: we probably speed things up by removing "data"
617 and the memcpy to it by extending vcd_image_source_read_mode2
618 to allow a mode to do what's below in addition to its
619 "raw" and "block" mode. It also would probably improve the modularity
620 a little bit as well.
624 CdIo *p_img = vcdinfo_get_cd_image(p_vcdplayer->vcd);
626 uint8_t subheader [CDIO_CD_SUBHEADER_SIZE];
627 uint8_t data [M2F2_SECTOR_SIZE];
630 vcdsector_t vcd_sector;
633 if (cdio_read_mode2_sector(p_img, &vcd_sector,
634 p_vcdplayer->i_lsn, true)!=0) {
635 dbg_print(INPUT_DBG_LSN, "read error\n");
636 p_vcdplayer->i_lsn++;
639 p_vcdplayer->i_lsn++;
641 if ( p_vcdplayer->i_lsn >= p_vcdplayer->end_lsn ) {
642 /* We've run off of the end of this entry. Do we continue or stop? */
643 dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC),
644 "end reached in reading, cur: %u, end: %u\n",
645 p_vcdplayer->i_lsn, p_vcdplayer->end_lsn);
649 /* Check header ID for a padding sector and simply discard
650 these. It is alleged that VCD's put these in to keep the
653 } while((vcd_sector.subheader[2]&~0x01)==0x60);
655 if ( p_vcdplayer->i_lsn >= p_vcdplayer->end_lsn )
656 /* We've run off of the end of this entry. Do we continue or stop? */
657 goto handle_item_continuation;
659 memcpy (p_buf, vcd_sector.data, M2F2_SECTOR_SIZE);
665 Play item assocated with the "default" selection.
667 Return false if there was some problem.
670 vcdplayer_play_default( access_t * p_access )
672 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
674 vcdinfo_itemid_t itemid;
677 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_PBC),
678 "null p_vcdplayer" );
683 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_PBC),
684 "current: %d" , p_vcdplayer->play_item.num);
686 itemid.type = p_vcdplayer->play_item.type;
688 if (vcdplayer_pbc_is_on(p_vcdplayer)) {
690 #if defined(LIBVCD_VERSION)
691 lid_t lid=vcdinfo_get_multi_default_lid(p_vcdplayer->vcd, p_vcdplayer->i_lid,
694 if (VCDINFO_INVALID_LID != lid) {
696 itemid.type = VCDINFO_ITEM_TYPE_LID;
697 dbg_print(INPUT_DBG_PBC, "DEFAULT to %d", itemid.num);
699 dbg_print(INPUT_DBG_PBC, "no DEFAULT for LID %d", p_vcdplayer->i_lid);
704 vcdinfo_lid_get_pxd(p_vcdplayer->vcd, &(p_vcdplayer->pxd), p_vcdplayer->i_lid);
706 switch (p_vcdplayer->pxd.descriptor_type) {
707 case PSD_TYPE_SELECTION_LIST:
708 case PSD_TYPE_EXT_SELECTION_LIST:
709 if (p_vcdplayer->pxd.psd == NULL) return false;
710 vcdplayer_update_entry( p_access,
711 vcdinfo_get_default_offset(p_vcdplayer->vcd,
713 &itemid.num, "default");
716 case PSD_TYPE_PLAY_LIST:
717 case PSD_TYPE_END_LIST:
718 case PSD_TYPE_COMMAND_LIST:
719 LOG_WARN( "There is no PBC 'default' selection here" );
722 #endif /* LIBVCD_VERSION (< 0.7.21) */
727 /* PBC is not on. "default" selection beginning of current
730 itemid.num = p_vcdplayer->play_item.num;
734 /** ??? p_vcdplayer->update_title(); ***/
735 vcdplayer_play( p_access, itemid );
741 Play item assocated with the "next" selection.
743 Return false if there was some problem.
746 vcdplayer_play_next( access_t * p_access )
748 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
750 vcdinfo_obj_t *p_vcdinfo;
751 vcdinfo_itemid_t itemid;
753 if (!p_vcdplayer) return false;
755 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_PBC),
756 "current: %d" , p_vcdplayer->play_item.num);
758 p_vcdinfo = p_vcdplayer->vcd;
760 itemid = p_vcdplayer->play_item;
762 if (vcdplayer_pbc_is_on(p_vcdplayer)) {
764 vcdinfo_lid_get_pxd(p_vcdinfo, &(p_vcdplayer->pxd), p_vcdplayer->i_lid);
766 switch (p_vcdplayer->pxd.descriptor_type) {
767 case PSD_TYPE_SELECTION_LIST:
768 case PSD_TYPE_EXT_SELECTION_LIST:
769 if (p_vcdplayer->pxd.psd == NULL) return false;
770 vcdplayer_update_entry( p_access,
771 vcdinf_psd_get_next_offset(p_vcdplayer->pxd.psd),
772 &itemid.num, "next");
773 itemid.type = VCDINFO_ITEM_TYPE_LID;
776 case PSD_TYPE_PLAY_LIST:
777 if (p_vcdplayer->pxd.pld == NULL) return false;
778 vcdplayer_update_entry( p_access,
779 vcdinf_pld_get_next_offset(p_vcdplayer->pxd.pld),
780 &itemid.num, "next");
781 itemid.type = VCDINFO_ITEM_TYPE_LID;
784 case PSD_TYPE_END_LIST:
785 case PSD_TYPE_COMMAND_LIST:
786 LOG_WARN( "There is no PBC 'next' selection here" );
791 /* PBC is not on. "Next" selection is play_item.num+1 if possible. */
795 switch (p_vcdplayer->play_item.type) {
796 case VCDINFO_ITEM_TYPE_ENTRY:
797 case VCDINFO_ITEM_TYPE_SEGMENT:
798 case VCDINFO_ITEM_TYPE_TRACK:
800 switch (p_vcdplayer->play_item.type) {
801 case VCDINFO_ITEM_TYPE_ENTRY:
802 max_entry = p_vcdplayer->i_entries;
804 case VCDINFO_ITEM_TYPE_SEGMENT:
805 max_entry = p_vcdplayer->i_segments;
807 case VCDINFO_ITEM_TYPE_TRACK:
808 max_entry = p_vcdplayer->i_tracks;
810 default: ; /* Handle exceptional cases below */
813 if (p_vcdplayer->play_item.num+1 < max_entry) {
814 itemid.num = p_vcdplayer->play_item.num+1;
816 LOG_WARN( "At the end - non-PBC 'next' not possible here" );
822 case VCDINFO_ITEM_TYPE_LID:
824 /* Should have handled above. */
825 LOG_WARN( "Internal inconsistency - should not have gotten here." );
833 /** ??? p_vcdplayer->update_title(); ***/
834 vcdplayer_play( p_access, itemid );
840 Play item assocated with the "prev" selection.
842 Return false if there was some problem.
845 vcdplayer_play_prev( access_t * p_access )
847 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
848 vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;
849 vcdinfo_itemid_t itemid;
851 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_PBC),
852 "current: %d" , p_vcdplayer->play_item.num);
854 itemid = p_vcdplayer->play_item;
856 if (vcdplayer_pbc_is_on(p_vcdplayer)) {
858 vcdinfo_lid_get_pxd(p_vcdinfo, &(p_vcdplayer->pxd), p_vcdplayer->i_lid);
860 switch (p_vcdplayer->pxd.descriptor_type) {
861 case PSD_TYPE_SELECTION_LIST:
862 case PSD_TYPE_EXT_SELECTION_LIST:
863 if (p_vcdplayer->pxd.psd == NULL) return false;
864 vcdplayer_update_entry( p_access,
865 vcdinf_psd_get_prev_offset(p_vcdplayer->pxd.psd),
866 &itemid.num, "prev");
867 itemid.type = VCDINFO_ITEM_TYPE_LID;
870 case PSD_TYPE_PLAY_LIST:
871 if (p_vcdplayer->pxd.pld == NULL) return false;
872 vcdplayer_update_entry( p_access,
873 vcdinf_pld_get_prev_offset(p_vcdplayer->pxd.pld),
874 &itemid.num, "prev");
875 itemid.type = VCDINFO_ITEM_TYPE_LID;
878 case PSD_TYPE_END_LIST:
879 case PSD_TYPE_COMMAND_LIST:
880 LOG_WARN( "There is no PBC 'prev' selection here" );
885 /* PBC is not on. "Prev" selection is play_item.num-1 if possible. */
887 int min_entry = (VCDINFO_ITEM_TYPE_ENTRY == p_vcdplayer->play_item.type)
890 if (p_vcdplayer->play_item.num > min_entry) {
891 itemid.num = p_vcdplayer->play_item.num-1;
893 LOG_WARN( "At the beginning - non-PBC 'prev' not possible here" );
899 /** ??? p_vcdplayer->update_title(); ***/
900 vcdplayer_play( p_access, itemid );
906 Play item assocated with the "return" selection.
908 Return false if there was some problem.
911 vcdplayer_play_return( access_t * p_access )
913 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
914 vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;
915 vcdinfo_itemid_t itemid;
917 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_PBC),
918 "current: %d" , p_vcdplayer->play_item.num);
920 itemid = p_vcdplayer->play_item;
922 if (vcdplayer_pbc_is_on(p_vcdplayer)) {
924 vcdinfo_lid_get_pxd(p_vcdinfo, &(p_vcdplayer->pxd), p_vcdplayer->i_lid);
926 switch (p_vcdplayer->pxd.descriptor_type) {
927 case PSD_TYPE_SELECTION_LIST:
928 case PSD_TYPE_EXT_SELECTION_LIST:
929 if (p_vcdplayer->pxd.psd == NULL) return false;
930 vcdplayer_update_entry( p_access,
931 vcdinf_psd_get_return_offset(p_vcdplayer->pxd.psd),
932 &itemid.num, "return");
933 itemid.type = VCDINFO_ITEM_TYPE_LID;
936 case PSD_TYPE_PLAY_LIST:
937 if (p_vcdplayer->pxd.pld == NULL) return false;
938 vcdplayer_update_entry( p_access,
939 vcdinf_pld_get_return_offset(p_vcdplayer->pxd.pld),
940 &itemid.num, "return");
941 itemid.type = VCDINFO_ITEM_TYPE_LID;
944 case PSD_TYPE_END_LIST:
945 case PSD_TYPE_COMMAND_LIST:
946 LOG_WARN( "There is no PBC 'return' selection here" );
951 /* PBC is not on. "Return" selection is min_entry if possible. */
953 p_vcdplayer->play_item.num =
954 (VCDINFO_ITEM_TYPE_ENTRY == p_vcdplayer->play_item.type)
959 /** ??? p_vcdplayer->update_title(); ***/
960 vcdplayer_play( p_access, itemid );
967 * c-file-style: "gnu"
969 * indent-tabs-mode: nil