/*! Take a format string and expand escape sequences, that is sequences that begin with %, with information from the current VCD. The expanded string is returned. Here is a list of escape sequences: %A : The album information %C : The VCD volume count - the number of CD's in the collection. %c : The VCD volume num - the number of the CD in the collection. %F : The VCD Format, e.g. VCD 1.0, VCD 1.1, VCD 2.0, or SVCD %I : The current entry/segment/playback type, e.g. ENTRY, TRACK, SEGMENT... %L : The playlist ID prefixed with " LID" if it exists %M : MRL %N : The current number of the %I - a decimal number %P : The publisher ID %p : The preparer ID %S : If we are in a segment (menu), the kind of segment %T : The track number %V : The volume set ID %v : The volume ID A number between 1 and the volume count. %% : a % */ static char * VCDFormatStr(vcdplayer_t *p_vcdplayer, const char *format_str, const char *mrl, const vcdinfo_itemid_t *itemid) { #define TEMP_STR_SIZE 256 char temp_str[TEMP_STR_SIZE]; char *tp = temp_str; const char *te = tp+TEMP_STR_SIZE-1; bool saw_control_prefix = false; memset(temp_str, 0, TEMP_STR_SIZE); for (; *format_str && tp<te; ++format_str) { if (!saw_control_prefix && *format_str != '%') { *tp++ = *format_str; saw_control_prefix = false; continue; } switch(*format_str) { case '%': if (saw_control_prefix) { *tp++ = '%'; } saw_control_prefix = !saw_control_prefix; break; case 'A': tp += snprintf(tp,te-tp,"%s", vcdinfo_strip_trail(vcdinfo_get_album_id(p_vcdplayer->vcd), MAX_ALBUM_LEN)); break; case 'c': tp += snprintf(tp,te-tp,"%d",vcdinfo_get_volume_num(p_vcdplayer->vcd)); break; case 'C': tp += snprintf(tp,te-tp,"%d",vcdinfo_get_volume_count(p_vcdplayer->vcd)); break; case 'F': tp += snprintf(tp,te-tp,"%s", vcdinfo_get_format_version_str(p_vcdplayer->vcd)); break; case 'I': { switch (itemid->type) { case VCDINFO_ITEM_TYPE_TRACK: tp += snprintf(tp,te-tp,"%s",_("Track")); break; case VCDINFO_ITEM_TYPE_ENTRY: tp += snprintf(tp,te-tp,"%s",_("Entry")); break; case VCDINFO_ITEM_TYPE_SEGMENT: tp += snprintf(tp,te-tp,"%s",_("Segment")); break; case VCDINFO_ITEM_TYPE_LID: tp += snprintf(tp,te-tp,"%s",_("List ID")); break; case VCDINFO_ITEM_TYPE_SPAREID2: tp += snprintf(tp,te-tp,"%s",_("Navigation")); break; default: /* What to do? */ ; } saw_control_prefix = false; } break; case 'L': if (vcdplayer_pbc_is_on(p_vcdplayer)) tp += snprintf(tp,te-tp,"%s %d",_("List ID"),p_vcdplayer->i_lid); saw_control_prefix = false; break; case 'M': tp += snprintf(tp,te-tp,"%s",mrl); break; case 'N': tp += snprintf(tp,te-tp,"%d",itemid->num); break; case 'p': tp += snprintf(tp,te-tp,"%s",vcdinfo_get_preparer_id(p_vcdplayer->vcd)); break; case 'P': tp += snprintf(tp,te-tp,"%s",vcdinfo_get_publisher_id(p_vcdplayer->vcd)); break; case 'S': if ( VCDINFO_ITEM_TYPE_SEGMENT==itemid->type ) { tp += snprintf(tp,te-tp," %s", vcdinfo_video_type2str(p_vcdplayer->vcd, itemid->num)); } saw_control_prefix = false; break; case 'T': tp += snprintf(tp,te-tp,"%d",p_vcdplayer->i_track); break; case 'V': tp += snprintf(tp,te-tp,"%s",vcdinfo_get_volumeset_id(p_vcdplayer->vcd)); break; case 'v': tp += snprintf(tp,te-tp,"%s",vcdinfo_get_volume_id(p_vcdplayer->vcd)); break; default: *tp++ = '%'; if(tp<te) *tp++ = *format_str; saw_control_prefix = false; } } return strdup(temp_str); }
/* Play a single item. */ static bool vcdplayer_play_single_item( access_t * p_access, vcdinfo_itemid_t itemid) { vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys; vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd; dbg_print(INPUT_DBG_CALL, "called itemid.num: %d, itemid.type: %d", itemid.num, itemid.type); p_vcdplayer->i_still = 0; switch (itemid.type) { case VCDINFO_ITEM_TYPE_SEGMENT: { vcdinfo_video_segment_type_t segtype = vcdinfo_get_video_type(p_vcdinfo, itemid.num); segnum_t i_segs = vcdinfo_get_num_segments(p_vcdinfo); dbg_print(INPUT_DBG_PBC, "%s (%d), itemid.num: %d", vcdinfo_video_type2str(p_vcdinfo, itemid.num), (int) segtype, itemid.num); if (itemid.num >= i_segs) return false; _vcdplayer_set_segment(p_access, 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_vcdplayer->i_still = STILL_READING; break; default: p_vcdplayer->i_still = 0; } break; } case VCDINFO_ITEM_TYPE_TRACK: dbg_print(INPUT_DBG_PBC, "track %d", itemid.num); if (itemid.num < 1 || itemid.num > p_vcdplayer->i_tracks) return false; _vcdplayer_set_track(p_access, itemid.num); break; case VCDINFO_ITEM_TYPE_ENTRY: { unsigned int i_entries = vcdinfo_get_num_entries(p_vcdinfo); dbg_print(INPUT_DBG_PBC, "entry %d", itemid.num); if (itemid.num >= i_entries) return false; _vcdplayer_set_entry(p_access, itemid.num); break; } case VCDINFO_ITEM_TYPE_LID: LOG_ERR("%s", "Should have converted p_vcdplayer above"); return false; break; case VCDINFO_ITEM_TYPE_NOTFOUND: dbg_print(INPUT_DBG_PBC, "play nothing"); p_vcdplayer->i_lsn = p_vcdplayer->end_lsn; return false; default: LOG_ERR("item type %d not implemented.", itemid.type); return false; } p_vcdplayer->play_item = itemid; /* Some players like xine, have a fifo queue of audio and video buffers that need to be flushed when playing a new selection. */ /* if (p_vcdplayer->flush_buffers) p_vcdplayer->flush_buffers(); */ return true; }