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., 59 Temple Place - Suite 330, Boston, MA 02111, 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>
37 #include "vcdplayer.h"
42 #include <cdio/cdio.h>
43 #include <cdio/util.h>
44 #include <libvcd/info.h>
47 #define sleep(A) Sleep((A)*1000)
50 extern void VCDSetOrigin ( access_t *p_access, lsn_t i_lsn, track_t i_track,
51 const vcdinfo_itemid_t * p_itemid );
54 Return true if playback control (PBC) is on
57 vcdplayer_pbc_is_on( const vcdplayer_t *p_vcdplayer )
59 return VCDINFO_INVALID_ENTRY != p_vcdplayer->i_lid;
62 /* Given an itemid, return the size for the object (via information
63 previously stored when opening the vcd). */
65 vcdplayer_get_item_size(access_t * p_access, vcdinfo_itemid_t itemid)
67 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
69 switch (itemid.type) {
70 case VCDINFO_ITEM_TYPE_ENTRY:
71 return p_vcdplayer->entry[itemid.num].size;
73 case VCDINFO_ITEM_TYPE_SEGMENT:
74 return p_vcdplayer->segment[itemid.num].size;
76 case VCDINFO_ITEM_TYPE_TRACK:
77 return p_vcdplayer->track[itemid.num-1].size;
79 case VCDINFO_ITEM_TYPE_LID:
80 /* Play list number (LID) */
83 case VCDINFO_ITEM_TYPE_NOTFOUND:
84 case VCDINFO_ITEM_TYPE_SPAREID2:
86 LOG_ERR("%s %d", "bad item type", itemid.type);
92 vcdplayer_update_entry( access_t * p_access, uint16_t ofs,
93 uint16_t *entry, const char *label)
95 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
97 if ( ofs == VCDINFO_INVALID_OFFSET ) {
98 *entry = VCDINFO_INVALID_ENTRY;
100 vcdinfo_offset_t *off = vcdinfo_get_offset_t(p_vcdplayer->vcd, ofs);
103 dbg_print(INPUT_DBG_PBC, "%s: LID %d", label, off->lid);
105 *entry = VCDINFO_INVALID_ENTRY;
109 /* Handles navigation when NOT in PBC reaching the end of a play item.
111 The navigations rules here may be sort of made up, but the intent
112 is to do something that's probably right or helpful.
114 return true if the caller should return.
116 vcdplayer_read_status_t
117 vcdplayer_non_pbc_nav ( access_t *p_access, uint8_t *wait_time )
119 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
121 /* Not in playback control. Do we advance automatically or stop? */
122 switch (p_vcdplayer->play_item.type) {
123 case VCDINFO_ITEM_TYPE_TRACK:
124 case VCDINFO_ITEM_TYPE_ENTRY: {
125 if ( ! vcdplayer_play_next( p_access ) )
131 case VCDINFO_ITEM_TYPE_SPAREID2:
132 dbg_print( (INPUT_DBG_STILL|INPUT_DBG_LSN),
134 if (p_vcdplayer->in_still)
136 dbg_print( (INPUT_DBG_STILL|INPUT_DBG_LSN),
137 "End of still spareid2" );
139 return READ_STILL_FRAME ;
142 case VCDINFO_ITEM_TYPE_NOTFOUND:
143 LOG_ERR ("NOTFOUND outside PBC -- not supposed to happen");
145 case VCDINFO_ITEM_TYPE_LID:
146 LOG_ERR ("LID outside PBC -- not supposed to happen");
148 case VCDINFO_ITEM_TYPE_SEGMENT:
149 /* Hack: Just go back and do still again */
151 if (p_vcdplayer->in_still)
153 dbg_print( (INPUT_DBG_STILL|INPUT_DBG_LSN),
154 "End of still Segment" );
156 return READ_STILL_FRAME;
164 Set reading to play an entire track.
167 _vcdplayer_set_track(access_t * p_access, track_t i_track)
169 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
170 if (i_track < 1 || i_track > p_vcdplayer->i_tracks)
173 const vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;
174 vcdinfo_itemid_t itemid;
176 itemid.num = i_track;
177 itemid.type = VCDINFO_ITEM_TYPE_TRACK;
178 p_vcdplayer->in_still = 0;
180 VCDSetOrigin(p_access, vcdinfo_get_track_lsn(p_vcdinfo, i_track),
183 dbg_print(INPUT_DBG_LSN, "LSN: %u", p_vcdplayer->i_lsn);
188 Set reading to play an entry
191 _vcdplayer_set_entry(access_t * p_access, unsigned int num)
193 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
194 vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;
195 const unsigned int i_entries = vcdinfo_get_num_entries(p_vcdinfo);
197 if (num >= i_entries) {
198 LOG_ERR("%s %d", "bad entry number", num);
201 vcdinfo_itemid_t itemid;
204 itemid.type = VCDINFO_ITEM_TYPE_ENTRY;
205 p_vcdplayer->i_still = 0;
207 VCDSetOrigin(p_access, vcdinfo_get_entry_lsn(p_vcdinfo, num),
208 vcdinfo_get_track(p_vcdinfo, num), &itemid);
210 dbg_print(INPUT_DBG_LSN, "LSN: %u, track_end LSN: %u",
211 p_vcdplayer->i_lsn, p_vcdplayer->track_end_lsn);
216 Set reading to play an segment (e.g. still frame)
219 _vcdplayer_set_segment(access_t * p_access, unsigned int num)
221 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
222 vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;
223 segnum_t i_segs = vcdinfo_get_num_segments(p_vcdinfo);
226 LOG_ERR("%s %d", "bad segment number", num);
229 vcdinfo_itemid_t itemid;
231 if (VCDINFO_NULL_LSN==p_vcdplayer->i_lsn) {
233 "Error in getting current segment number", num);
238 itemid.type = VCDINFO_ITEM_TYPE_SEGMENT;
240 VCDSetOrigin(p_access, vcdinfo_get_seg_lsn(p_vcdinfo, num), 0, &itemid);
242 dbg_print(INPUT_DBG_LSN, "LSN: %u", p_vcdplayer->i_lsn);
247 /* Play a single item. */
249 vcdplayer_play_single_item( access_t * p_access, vcdinfo_itemid_t itemid)
251 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
252 vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;
254 dbg_print(INPUT_DBG_CALL, "called itemid.num: %d, itemid.type: %d",
255 itemid.num, itemid.type);
257 p_vcdplayer->i_still = 0;
259 switch (itemid.type) {
260 case VCDINFO_ITEM_TYPE_SEGMENT:
262 vcdinfo_video_segment_type_t segtype
263 = vcdinfo_get_video_type(p_vcdinfo, itemid.num);
264 segnum_t i_segs = vcdinfo_get_num_segments(p_vcdinfo);
266 dbg_print(INPUT_DBG_PBC, "%s (%d), itemid.num: %d",
267 vcdinfo_video_type2str(p_vcdinfo, itemid.num),
268 (int) segtype, itemid.num);
270 if (itemid.num >= i_segs) return false;
271 _vcdplayer_set_segment(p_access, itemid.num);
275 case VCDINFO_FILES_VIDEO_NTSC_STILL:
276 case VCDINFO_FILES_VIDEO_NTSC_STILL2:
277 case VCDINFO_FILES_VIDEO_PAL_STILL:
278 case VCDINFO_FILES_VIDEO_PAL_STILL2:
279 p_vcdplayer->i_still = STILL_READING;
282 p_vcdplayer->i_still = 0;
288 case VCDINFO_ITEM_TYPE_TRACK:
289 dbg_print(INPUT_DBG_PBC, "track %d", itemid.num);
290 if (itemid.num < 1 || itemid.num > p_vcdplayer->i_tracks) return false;
291 _vcdplayer_set_track(p_access, itemid.num);
294 case VCDINFO_ITEM_TYPE_ENTRY:
296 unsigned int i_entries = vcdinfo_get_num_entries(p_vcdinfo);
297 dbg_print(INPUT_DBG_PBC, "entry %d", itemid.num);
298 if (itemid.num >= i_entries) return false;
299 _vcdplayer_set_entry(p_access, itemid.num);
303 case VCDINFO_ITEM_TYPE_LID:
304 LOG_ERR("%s", "Should have converted p_vcdplayer above");
308 case VCDINFO_ITEM_TYPE_NOTFOUND:
309 dbg_print(INPUT_DBG_PBC, "play nothing");
310 p_vcdplayer->i_lsn = p_vcdplayer->end_lsn;
314 LOG_ERR("item type %d not implemented.", itemid.type);
318 p_vcdplayer->play_item = itemid;
320 /* Some players like xine, have a fifo queue of audio and video buffers
321 that need to be flushed when playing a new selection. */
322 /* if (p_vcdplayer->flush_buffers)
323 p_vcdplayer->flush_buffers(); */
328 Set's start origin and size for subsequent seeks.
329 input: p_vcdplayer->i_lsn, p_vcdplayer->play_item
330 changed: p_vcdplayer->origin_lsn, p_vcdplayer->end_lsn
333 /* FIXME: add parameters lsn, i_track, p_itemid and set accordingly. */
335 vcdplayer_set_origin(access_t *p_access, lsn_t i_lsn, track_t i_track,
336 const vcdinfo_itemid_t *p_itemid)
338 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
339 const size_t i_size= vcdplayer_get_item_size(p_access, *p_itemid);
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,
350 dbg_print((INPUT_DBG_CALL|INPUT_DBG_LSN),
351 "lsn %u, end LSN: %u item.num %d, item.type %d",
352 p_vcdplayer->i_lsn, p_vcdplayer->end_lsn,
353 p_vcdplayer->play_item.num, p_vcdplayer->play_item.type);
357 Get the next play-item in the list given in the LIDs. Note play-item
358 here refers to list of play-items for a single LID It shouldn't be
359 confused with a user's list of favorite things to play or the
360 "next" field of a LID which moves us to a different LID.
363 vcdplayer_inc_play_item(access_t *p_access)
366 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
369 dbg_print(INPUT_DBG_CALL, "called pli: %d", p_vcdplayer->pdi);
371 if ( NULL == p_vcdplayer || NULL == p_vcdplayer->pxd.pld ) return false;
373 noi = vcdinf_pld_get_noi(p_vcdplayer->pxd.pld);
375 if ( noi <= 0 ) return false;
377 /* Handle delays like autowait or wait here? */
381 if ( p_vcdplayer->pdi < 0 || p_vcdplayer->pdi >= noi ) return false;
384 uint16_t trans_itemid_num=vcdinf_pld_get_play_item(p_vcdplayer->pxd.pld,
386 vcdinfo_itemid_t trans_itemid;
388 if (VCDINFO_INVALID_ITEMID == trans_itemid_num) return false;
390 vcdinfo_classify_itemid(trans_itemid_num, &trans_itemid);
391 dbg_print(INPUT_DBG_PBC, " play-item[%d]: %s",
392 p_vcdplayer->pdi, vcdinfo_pin2str (trans_itemid_num));
393 return vcdplayer_play_single_item(p_access, trans_itemid);
398 vcdplayer_play(access_t *p_access, vcdinfo_itemid_t itemid)
400 vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys;
402 dbg_print(INPUT_DBG_CALL, "called itemid.num: %d itemid.type: %d",
403 itemid.num, itemid.type);
405 if (!vcdplayer_pbc_is_on(p_vcdplayer)) {
406 vcdplayer_play_single_item(p_access, itemid);
408 /* PBC on - Itemid.num is LID. */
410 vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;
412 if (p_vcdinfo == NULL) return;
414 p_vcdplayer->i_lid = itemid.num;
415 vcdinfo_lid_get_pxd(p_vcdinfo, &(p_vcdplayer->pxd), itemid.num);
417 switch (p_vcdplayer->pxd.descriptor_type) {
419 case PSD_TYPE_SELECTION_LIST:
420 case PSD_TYPE_EXT_SELECTION_LIST: {
421 vcdinfo_itemid_t trans_itemid;
422 uint16_t trans_itemid_num;
424 if (p_vcdplayer->pxd.psd == NULL) return;
425 trans_itemid_num = vcdinf_psd_get_itemid(p_vcdplayer->pxd.psd);
426 vcdinfo_classify_itemid(trans_itemid_num, &trans_itemid);
427 p_vcdplayer->i_loop = 1;
428 p_vcdplayer->loop_item = trans_itemid;
429 vcdplayer_play_single_item(p_access, trans_itemid);
433 case PSD_TYPE_PLAY_LIST: {
434 if (p_vcdplayer->pxd.pld == NULL) return;
435 p_vcdplayer->pdi = -1;
436 vcdplayer_inc_play_item(p_access);
440 case PSD_TYPE_END_LIST:
441 case PSD_TYPE_COMMAND_LIST:
449 /* Handles PBC navigation when reaching the end of a play item. */
450 vcdplayer_read_status_t
451 vcdplayer_pbc_nav ( access_t * p_access, uint8_t *wait_time )
453 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
455 /* We are in playback control. */
456 vcdinfo_itemid_t itemid;
458 /* The end of an entry is really the end of the associated
459 sequence (or track). */
461 if ( (VCDINFO_ITEM_TYPE_ENTRY == p_vcdplayer->play_item.type) &&
462 (p_vcdplayer->i_lsn < p_vcdplayer->end_lsn) ) {
463 /* Set up to just continue to the next entry */
464 p_vcdplayer->play_item.num++;
465 dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC),
466 "continuing into next entry: %u", p_vcdplayer->play_item.num);
467 vcdplayer_play_single_item( p_access, p_vcdplayer->play_item );
468 /* p_vcdplayer->update_title(); */
472 switch (p_vcdplayer->pxd.descriptor_type) {
473 case PSD_TYPE_END_LIST:
476 case PSD_TYPE_PLAY_LIST: {
477 if (vcdplayer_inc_play_item(p_access))
480 /* Set up for caller process wait time given. */
481 if (p_vcdplayer->i_still) {
482 *wait_time = vcdinf_get_wait_time(p_vcdplayer->pxd.pld);
483 dbg_print((INPUT_DBG_PBC|INPUT_DBG_STILL),
484 "playlist wait time: %d", *wait_time);
485 return READ_STILL_FRAME;
488 /* Wait time has been processed; continue with next entry. */
489 vcdplayer_update_entry( p_access,
490 vcdinf_pld_get_next_offset(p_vcdplayer->pxd.pld),
491 &itemid.num, "next" );
492 itemid.type = VCDINFO_ITEM_TYPE_LID;
493 vcdplayer_play( p_access, itemid );
496 case PSD_TYPE_SELECTION_LIST: /* Selection List (+Ext. for SVCD) */
497 case PSD_TYPE_EXT_SELECTION_LIST: /* Extended Selection List (VCD2.0) */
499 uint16_t timeout_offs = vcdinf_get_timeout_offset(p_vcdplayer->pxd.psd);
500 uint16_t max_loop = vcdinf_get_loop_count(p_vcdplayer->pxd.psd);
501 vcdinfo_offset_t *offset_timeout_LID =
502 vcdinfo_get_offset_t(p_vcdplayer->vcd, timeout_offs);
504 dbg_print(INPUT_DBG_PBC, "looped: %d, max_loop %d",
505 p_vcdplayer->i_loop, max_loop);
507 /* Set up for caller process wait time given. */
508 if (p_vcdplayer->i_still) {
509 *wait_time = vcdinf_get_timeout_time(p_vcdplayer->pxd.psd);
510 dbg_print((INPUT_DBG_PBC|INPUT_DBG_STILL),
511 "playlist wait_time: %d", *wait_time);
512 return READ_STILL_FRAME;
515 /* Wait time has been processed; continue with next entry. */
516 /* Handle any looping given. */
517 if ( max_loop == 0 || p_vcdplayer->i_loop < max_loop ) {
518 p_vcdplayer->i_loop++;
519 if (p_vcdplayer->i_loop == 0x7f) p_vcdplayer->i_loop = 0;
520 vcdplayer_play_single_item(p_access, p_vcdplayer->loop_item);
521 /* if (p_vcdplayer->i_still) p_vcdplayer->force_redisplay();*/
525 /* Looping finished and wait finished. Move to timeout
526 entry or next entry, or handle still. */
528 if (NULL != offset_timeout_LID) {
529 /* Handle timeout_LID */
530 itemid.num = offset_timeout_LID->lid;
531 itemid.type = VCDINFO_ITEM_TYPE_LID;
532 dbg_print(INPUT_DBG_PBC, "timeout to: %d", itemid.num);
533 vcdplayer_play( p_access, itemid );
536 int i_selections = vcdinf_get_num_selections(p_vcdplayer->pxd.psd);
537 if (i_selections > 0) {
538 /* Pick a random selection. */
539 unsigned int bsn=vcdinf_get_bsn(p_vcdplayer->pxd.psd);
540 int rand_selection=bsn +
541 (int) ((i_selections+0.0)*rand()/(RAND_MAX+1.0));
542 lid_t rand_lid=vcdinfo_selection_get_lid (p_vcdplayer->vcd,
545 itemid.num = rand_lid;
546 itemid.type = VCDINFO_ITEM_TYPE_LID;
547 dbg_print(INPUT_DBG_PBC, "random selection %d, lid: %d",
548 rand_selection - bsn, rand_lid);
549 vcdplayer_play( p_access, itemid );
551 } else if (p_vcdplayer->i_still) {
552 /* Hack: Just go back and do still again */
554 return READ_STILL_FRAME;
559 case VCDINFO_ITEM_TYPE_NOTFOUND:
560 LOG_ERR( "NOTFOUND in PBC -- not supposed to happen" );
562 case VCDINFO_ITEM_TYPE_SPAREID2:
563 LOG_ERR( "SPAREID2 in PBC -- not supposed to happen" );
565 case VCDINFO_ITEM_TYPE_LID:
566 LOG_ERR( "LID in PBC -- not supposed to happen" );
572 /* FIXME: Should handle autowait ... */
578 Read block into p_buf and return the status back.
580 This routine is a bit complicated because on reaching the end of
581 a track or entry we may automatically advance to the item, or
582 interpret the next item in the playback-control list.
584 vcdplayer_read_status_t
585 vcdplayer_read (access_t * p_access, uint8_t *p_buf)
588 /* p_access->handle_events (); */
591 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
592 if ( p_vcdplayer->i_lsn > p_vcdplayer->end_lsn ) {
593 vcdplayer_read_status_t read_status;
595 /* We've run off of the end of this entry. Do we continue or stop? */
596 dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC),
597 "end reached, cur: %u, end: %u\n", p_vcdplayer->i_lsn, p_vcdplayer->end_lsn);
599 handle_item_continuation:
600 read_status = vcdplayer_pbc_is_on( p_vcdplayer )
601 ? vcdplayer_pbc_nav( p_access, &wait_time )
602 : vcdplayer_non_pbc_nav( p_access, &wait_time );
604 if (READ_STILL_FRAME == read_status) {
606 return READ_STILL_FRAME;
609 if (READ_BLOCK != read_status) return read_status;
612 /* Read the next block.
614 Important note: we probably speed things up by removing "data"
615 and the memcpy to it by extending vcd_image_source_read_mode2
616 to allow a mode to do what's below in addition to its
617 "raw" and "block" mode. It also would probably improve the modularity
618 a little bit as well.
622 CdIo *p_img = vcdinfo_get_cd_image(p_vcdplayer->vcd);
624 uint8_t subheader [CDIO_CD_SUBHEADER_SIZE];
625 uint8_t data [M2F2_SECTOR_SIZE];
628 vcdsector_t vcd_sector;
631 if (cdio_read_mode2_sector(p_img, &vcd_sector,
632 p_vcdplayer->i_lsn, true)!=0) {
633 dbg_print(INPUT_DBG_LSN, "read error\n");
634 p_vcdplayer->i_lsn++;
637 p_vcdplayer->i_lsn++;
639 if ( p_vcdplayer->i_lsn >= p_vcdplayer->end_lsn ) {
640 /* We've run off of the end of this entry. Do we continue or stop? */
641 dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC),
642 "end reached in reading, cur: %u, end: %u\n",
643 p_vcdplayer->i_lsn, p_vcdplayer->end_lsn);
647 /* Check header ID for a padding sector and simply discard
648 these. It is alleged that VCD's put these in to keep the
651 } while((vcd_sector.subheader[2]&~0x01)==0x60);
653 if ( p_vcdplayer->i_lsn >= p_vcdplayer->end_lsn )
654 /* We've run off of the end of this entry. Do we continue or stop? */
655 goto handle_item_continuation;
657 memcpy (p_buf, vcd_sector.data, M2F2_SECTOR_SIZE);
663 Play item assocated with the "default" selection.
665 Return false if there was some problem.
668 vcdplayer_play_default( access_t * p_access )
670 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
672 vcdinfo_itemid_t itemid;
675 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_PBC),
676 "null p_vcdplayer" );
681 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_PBC),
682 "current: %d" , p_vcdplayer->play_item.num);
684 itemid.type = p_vcdplayer->play_item.type;
686 if (vcdplayer_pbc_is_on(p_vcdplayer)) {
688 #if defined(LIBVCD_VERSION)
689 lid_t lid=vcdinfo_get_multi_default_lid(p_vcdplayer->vcd, p_vcdplayer->i_lid,
692 if (VCDINFO_INVALID_LID != lid) {
694 itemid.type = VCDINFO_ITEM_TYPE_LID;
695 dbg_print(INPUT_DBG_PBC, "DEFAULT to %d", itemid.num);
697 dbg_print(INPUT_DBG_PBC, "no DEFAULT for LID %d", p_vcdplayer->i_lid);
702 vcdinfo_lid_get_pxd(p_vcdplayer->vcd, &(p_vcdplayer->pxd), p_vcdplayer->i_lid);
704 switch (p_vcdplayer->pxd.descriptor_type) {
705 case PSD_TYPE_SELECTION_LIST:
706 case PSD_TYPE_EXT_SELECTION_LIST:
707 if (p_vcdplayer->pxd.psd == NULL) return false;
708 vcdplayer_update_entry( p_access,
709 vcdinfo_get_default_offset(p_vcdplayer->vcd,
711 &itemid.num, "default");
714 case PSD_TYPE_PLAY_LIST:
715 case PSD_TYPE_END_LIST:
716 case PSD_TYPE_COMMAND_LIST:
717 LOG_WARN( "There is no PBC 'default' selection here" );
720 #endif /* LIBVCD_VERSION (< 0.7.21) */
725 /* PBC is not on. "default" selection beginning of current
728 itemid.num = p_vcdplayer->play_item.num;
732 /** ??? p_vcdplayer->update_title(); ***/
733 vcdplayer_play( p_access, itemid );
739 Play item assocated with the "next" selection.
741 Return false if there was some problem.
744 vcdplayer_play_next( access_t * p_access )
746 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
748 vcdinfo_obj_t *p_vcdinfo;
749 vcdinfo_itemid_t itemid;
751 if (!p_vcdplayer) return false;
753 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_PBC),
754 "current: %d" , p_vcdplayer->play_item.num);
756 p_vcdinfo = p_vcdplayer->vcd;
758 itemid = p_vcdplayer->play_item;
760 if (vcdplayer_pbc_is_on(p_vcdplayer)) {
762 vcdinfo_lid_get_pxd(p_vcdinfo, &(p_vcdplayer->pxd), p_vcdplayer->i_lid);
764 switch (p_vcdplayer->pxd.descriptor_type) {
765 case PSD_TYPE_SELECTION_LIST:
766 case PSD_TYPE_EXT_SELECTION_LIST:
767 if (p_vcdplayer->pxd.psd == NULL) return false;
768 vcdplayer_update_entry( p_access,
769 vcdinf_psd_get_next_offset(p_vcdplayer->pxd.psd),
770 &itemid.num, "next");
771 itemid.type = VCDINFO_ITEM_TYPE_LID;
774 case PSD_TYPE_PLAY_LIST:
775 if (p_vcdplayer->pxd.pld == NULL) return false;
776 vcdplayer_update_entry( p_access,
777 vcdinf_pld_get_next_offset(p_vcdplayer->pxd.pld),
778 &itemid.num, "next");
779 itemid.type = VCDINFO_ITEM_TYPE_LID;
782 case PSD_TYPE_END_LIST:
783 case PSD_TYPE_COMMAND_LIST:
784 LOG_WARN( "There is no PBC 'next' selection here" );
789 /* PBC is not on. "Next" selection is play_item.num+1 if possible. */
793 switch (p_vcdplayer->play_item.type) {
794 case VCDINFO_ITEM_TYPE_ENTRY:
795 case VCDINFO_ITEM_TYPE_SEGMENT:
796 case VCDINFO_ITEM_TYPE_TRACK:
798 switch (p_vcdplayer->play_item.type) {
799 case VCDINFO_ITEM_TYPE_ENTRY:
800 max_entry = p_vcdplayer->i_entries;
802 case VCDINFO_ITEM_TYPE_SEGMENT:
803 max_entry = p_vcdplayer->i_segments;
805 case VCDINFO_ITEM_TYPE_TRACK:
806 max_entry = p_vcdplayer->i_tracks;
808 default: ; /* Handle exceptional cases below */
811 if (p_vcdplayer->play_item.num+1 < max_entry) {
812 itemid.num = p_vcdplayer->play_item.num+1;
814 LOG_WARN( "At the end - non-PBC 'next' not possible here" );
820 case VCDINFO_ITEM_TYPE_LID:
822 /* Should have handled above. */
823 LOG_WARN( "Internal inconsistency - should not have gotten here." );
831 /** ??? p_vcdplayer->update_title(); ***/
832 vcdplayer_play( p_access, itemid );
838 Play item assocated with the "prev" selection.
840 Return false if there was some problem.
843 vcdplayer_play_prev( access_t * p_access )
845 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
846 vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;
847 vcdinfo_itemid_t itemid;
849 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_PBC),
850 "current: %d" , p_vcdplayer->play_item.num);
852 itemid = p_vcdplayer->play_item;
854 if (vcdplayer_pbc_is_on(p_vcdplayer)) {
856 vcdinfo_lid_get_pxd(p_vcdinfo, &(p_vcdplayer->pxd), p_vcdplayer->i_lid);
858 switch (p_vcdplayer->pxd.descriptor_type) {
859 case PSD_TYPE_SELECTION_LIST:
860 case PSD_TYPE_EXT_SELECTION_LIST:
861 if (p_vcdplayer->pxd.psd == NULL) return false;
862 vcdplayer_update_entry( p_access,
863 vcdinf_psd_get_prev_offset(p_vcdplayer->pxd.psd),
864 &itemid.num, "prev");
865 itemid.type = VCDINFO_ITEM_TYPE_LID;
868 case PSD_TYPE_PLAY_LIST:
869 if (p_vcdplayer->pxd.pld == NULL) return false;
870 vcdplayer_update_entry( p_access,
871 vcdinf_pld_get_prev_offset(p_vcdplayer->pxd.pld),
872 &itemid.num, "prev");
873 itemid.type = VCDINFO_ITEM_TYPE_LID;
876 case PSD_TYPE_END_LIST:
877 case PSD_TYPE_COMMAND_LIST:
878 LOG_WARN( "There is no PBC 'prev' selection here" );
883 /* PBC is not on. "Prev" selection is play_item.num-1 if possible. */
885 int min_entry = (VCDINFO_ITEM_TYPE_ENTRY == p_vcdplayer->play_item.type)
888 if (p_vcdplayer->play_item.num > min_entry) {
889 itemid.num = p_vcdplayer->play_item.num-1;
891 LOG_WARN( "At the beginning - non-PBC 'prev' not possible here" );
897 /** ??? p_vcdplayer->update_title(); ***/
898 vcdplayer_play( p_access, itemid );
904 Play item assocated with the "return" selection.
906 Return false if there was some problem.
909 vcdplayer_play_return( access_t * p_access )
911 vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys;
912 vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;
913 vcdinfo_itemid_t itemid;
915 dbg_print( (INPUT_DBG_CALL|INPUT_DBG_PBC),
916 "current: %d" , p_vcdplayer->play_item.num);
918 itemid = p_vcdplayer->play_item;
920 if (vcdplayer_pbc_is_on(p_vcdplayer)) {
922 vcdinfo_lid_get_pxd(p_vcdinfo, &(p_vcdplayer->pxd), p_vcdplayer->i_lid);
924 switch (p_vcdplayer->pxd.descriptor_type) {
925 case PSD_TYPE_SELECTION_LIST:
926 case PSD_TYPE_EXT_SELECTION_LIST:
927 if (p_vcdplayer->pxd.psd == NULL) return false;
928 vcdplayer_update_entry( p_access,
929 vcdinf_psd_get_return_offset(p_vcdplayer->pxd.psd),
930 &itemid.num, "return");
931 itemid.type = VCDINFO_ITEM_TYPE_LID;
934 case PSD_TYPE_PLAY_LIST:
935 if (p_vcdplayer->pxd.pld == NULL) return false;
936 vcdplayer_update_entry( p_access,
937 vcdinf_pld_get_return_offset(p_vcdplayer->pxd.pld),
938 &itemid.num, "return");
939 itemid.type = VCDINFO_ITEM_TYPE_LID;
942 case PSD_TYPE_END_LIST:
943 case PSD_TYPE_COMMAND_LIST:
944 LOG_WARN( "There is no PBC 'return' selection here" );
949 /* PBC is not on. "Return" selection is min_entry if possible. */
951 p_vcdplayer->play_item.num =
952 (VCDINFO_ITEM_TYPE_ENTRY == p_vcdplayer->play_item.type)
957 /** ??? p_vcdplayer->update_title(); ***/
958 vcdplayer_play( p_access, itemid );
965 * c-file-style: "gnu"
967 * indent-tabs-mode: nil