FS6338: Playlist playing time
Originally by Stephane Doyon. Updated by Alex Wallis, Igor Poretsky, and myself. Change-Id: I15a06f7774c886cefd9c2cb93230d67de3e5f9a9
This commit is contained in:
parent
39b64f7d4d
commit
fe95127c45
|
@ -237,7 +237,7 @@
|
||||||
*: "Loading... %d%% done (%s)"
|
*: "Loading... %d%% done (%s)"
|
||||||
</dest>
|
</dest>
|
||||||
<voice>
|
<voice>
|
||||||
*: ""
|
*: "Loading"
|
||||||
</voice>
|
</voice>
|
||||||
</phrase>
|
</phrase>
|
||||||
<phrase>
|
<phrase>
|
||||||
|
@ -13829,3 +13829,157 @@
|
||||||
*: "Never"
|
*: "Never"
|
||||||
</voice>
|
</voice>
|
||||||
</phrase>
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_PLAYTIME_ELAPSED
|
||||||
|
desc: playing time screen
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "Playlist elapsed: %s / %s %ld%%"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "Playlist elapsed: %s / %s %ld%%"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Playlist elapsed"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_PLAYTIME_TRK_ELAPSED
|
||||||
|
desc: playing time screen
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "Track elapsed: %s / %s %ld%%"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "Track elapsed: %s / %s %ld%%"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Track elapsed"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_PLAYTIME_REMAINING
|
||||||
|
desc: playing time screen
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "Playlist remaining: %s"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "Playlist remaining: %s"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Playlist remaining"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_PLAYTIME_TRK_REMAINING
|
||||||
|
desc: playing time screen
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "Track remaining: %s"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "Track remaining: %s"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Track remaining"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_PLAYTIME_TRACK
|
||||||
|
desc: playing time screen
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "Track %d / %d %d%%"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "Track %d / %d %d%%"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Track"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_PLAYTIME_STORAGE
|
||||||
|
desc: playing time screen
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "Storage: %s (done %s, remaining %s)"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "Storage: %s (done %s, remaining %s)"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Storage"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: VOICE_PLAYTIME_DONE
|
||||||
|
desc: playing time screen
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: ""
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: ""
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Done"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_PLAYTIME_AVG_TRACK_SIZE
|
||||||
|
desc: playing time screen
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "Average track size: %s"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "Average track size: %s"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Average track size"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_PLAYTIME_AVG_BITRATE
|
||||||
|
desc: playing time screen
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "Average bitrate: %ld kbps"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "Average bitrate: %ld kbps"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Average bit rate"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_PLAYTIME_ERROR
|
||||||
|
desc: playing time screen
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "Error while gathering info"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "Error while gathering info"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Error while gathering info"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
<phrase>
|
||||||
|
id: LANG_PLAYING_TIME
|
||||||
|
desc: onplay menu
|
||||||
|
user: core
|
||||||
|
<source>
|
||||||
|
*: "Playing time"
|
||||||
|
</source>
|
||||||
|
<dest>
|
||||||
|
*: "Playing time"
|
||||||
|
</dest>
|
||||||
|
<voice>
|
||||||
|
*: "Playing time"
|
||||||
|
</voice>
|
||||||
|
</phrase>
|
||||||
|
|
263
apps/onplay.c
263
apps/onplay.c
|
@ -192,6 +192,263 @@ static int bookmark_menu_callback(int action,
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* playing_time screen context */
|
||||||
|
struct playing_time_info {
|
||||||
|
int curr_playing; /* index of currently playing track in playlist */
|
||||||
|
int nb_tracks; /* how many tracks in playlist */
|
||||||
|
/* seconds before and after current position, and total. Datatype
|
||||||
|
allows for values up to 68years. If I had kept it in ms
|
||||||
|
though, it would have overflowed at 24days, which takes
|
||||||
|
something like 8.5GB at 32kbps, and so we could conceivably
|
||||||
|
have playlists lasting longer than that. */
|
||||||
|
long secs_bef, secs_aft, secs_ttl;
|
||||||
|
long trk_secs_bef, trk_secs_aft, trk_secs_ttl;
|
||||||
|
/* kilobytes played before and after current pos, and total.
|
||||||
|
Kilobytes because bytes would overflow. Data type range is up
|
||||||
|
to 2TB. */
|
||||||
|
long kbs_bef, kbs_aft, kbs_ttl;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* list callback for playing_time screen */
|
||||||
|
static const char * playing_time_get_or_speak_info(int selected_item, void * data,
|
||||||
|
char *buf, size_t buffer_len,
|
||||||
|
bool say_it)
|
||||||
|
{
|
||||||
|
struct playing_time_info *pti = (struct playing_time_info *)data;
|
||||||
|
switch(selected_item) {
|
||||||
|
case 0: { /* elapsed and total time */
|
||||||
|
char timestr1[25], timestr2[25];
|
||||||
|
format_time_auto(timestr1, sizeof(timestr1), pti->secs_bef,
|
||||||
|
UNIT_SEC, false);
|
||||||
|
format_time_auto(timestr2, sizeof(timestr2), pti->secs_ttl,
|
||||||
|
UNIT_SEC, false);
|
||||||
|
long elapsed_perc; /* percentage of duration elapsed */
|
||||||
|
if (pti->secs_ttl == 0)
|
||||||
|
elapsed_perc = 0;
|
||||||
|
else if (pti->secs_ttl <= 0xFFFFFF)
|
||||||
|
elapsed_perc = pti->secs_bef *100 / pti->secs_ttl;
|
||||||
|
else /* sacrifice some precision to avoid overflow */
|
||||||
|
elapsed_perc = (pti->secs_bef>>7) *100 /(pti->secs_ttl>>7);
|
||||||
|
snprintf(buf, buffer_len, str(LANG_PLAYTIME_ELAPSED),
|
||||||
|
timestr1, timestr2, elapsed_perc);
|
||||||
|
if (say_it)
|
||||||
|
talk_ids(false, LANG_PLAYTIME_ELAPSED,
|
||||||
|
TALK_ID(pti->secs_bef, UNIT_TIME),
|
||||||
|
VOICE_OF,
|
||||||
|
TALK_ID(pti->secs_ttl, UNIT_TIME),
|
||||||
|
VOICE_PAUSE,
|
||||||
|
TALK_ID(elapsed_perc, UNIT_PERCENT));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: { /* playlist remaining time */
|
||||||
|
char timestr[25];
|
||||||
|
format_time_auto(timestr, sizeof(timestr), pti->secs_aft,
|
||||||
|
UNIT_SEC, false);
|
||||||
|
snprintf(buf, buffer_len, str(LANG_PLAYTIME_REMAINING),
|
||||||
|
timestr);
|
||||||
|
if (say_it)
|
||||||
|
talk_ids(false, LANG_PLAYTIME_REMAINING,
|
||||||
|
TALK_ID(pti->secs_aft, UNIT_TIME));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: { /* track elapsed and duration */
|
||||||
|
char timestr1[25], timestr2[25];
|
||||||
|
format_time_auto(timestr1, sizeof(timestr1), pti->trk_secs_bef,
|
||||||
|
UNIT_SEC, false);
|
||||||
|
format_time_auto(timestr2, sizeof(timestr2), pti->trk_secs_ttl,
|
||||||
|
UNIT_SEC, false);
|
||||||
|
long elapsed_perc; /* percentage of duration elapsed */
|
||||||
|
if (pti->trk_secs_ttl == 0)
|
||||||
|
elapsed_perc = 0;
|
||||||
|
else if (pti->trk_secs_ttl <= 0xFFFFFF)
|
||||||
|
elapsed_perc = pti->trk_secs_bef *100 / pti->trk_secs_ttl;
|
||||||
|
else /* sacrifice some precision to avoid overflow */
|
||||||
|
elapsed_perc = (pti->trk_secs_bef>>7) *100 /(pti->trk_secs_ttl>>7);
|
||||||
|
snprintf(buf, buffer_len, str(LANG_PLAYTIME_TRK_ELAPSED),
|
||||||
|
timestr1, timestr2, elapsed_perc);
|
||||||
|
if (say_it)
|
||||||
|
talk_ids(false, LANG_PLAYTIME_TRK_ELAPSED,
|
||||||
|
TALK_ID(pti->trk_secs_bef, UNIT_TIME),
|
||||||
|
VOICE_OF,
|
||||||
|
TALK_ID(pti->trk_secs_ttl, UNIT_TIME),
|
||||||
|
VOICE_PAUSE,
|
||||||
|
TALK_ID(elapsed_perc, UNIT_PERCENT));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: { /* track remaining time */
|
||||||
|
char timestr[25];
|
||||||
|
format_time_auto(timestr, sizeof(timestr), pti->trk_secs_aft,
|
||||||
|
UNIT_SEC, false);
|
||||||
|
snprintf(buf, buffer_len, str(LANG_PLAYTIME_TRK_REMAINING),
|
||||||
|
timestr);
|
||||||
|
if (say_it)
|
||||||
|
talk_ids(false, LANG_PLAYTIME_TRK_REMAINING,
|
||||||
|
TALK_ID(pti->trk_secs_aft, UNIT_TIME));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4: { /* track index */
|
||||||
|
int track_perc = (pti->curr_playing+1) *100 / pti->nb_tracks;
|
||||||
|
snprintf(buf, buffer_len, str(LANG_PLAYTIME_TRACK),
|
||||||
|
pti->curr_playing, pti->nb_tracks, track_perc);
|
||||||
|
if (say_it)
|
||||||
|
talk_ids(false, LANG_PLAYTIME_TRACK,
|
||||||
|
TALK_ID(pti->curr_playing+1, UNIT_INT),
|
||||||
|
VOICE_OF,
|
||||||
|
TALK_ID(pti->nb_tracks, UNIT_INT),
|
||||||
|
VOICE_PAUSE,
|
||||||
|
TALK_ID(track_perc, UNIT_PERCENT));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5: { /* storage size */
|
||||||
|
char str1[10], str2[10], str3[10];
|
||||||
|
output_dyn_value(str1, sizeof(str1), pti->kbs_ttl, kibyte_units, 3, true);
|
||||||
|
output_dyn_value(str2, sizeof(str2), pti->kbs_bef, kibyte_units, 3, true);
|
||||||
|
output_dyn_value(str3, sizeof(str3), pti->kbs_aft, kibyte_units, 3, true);
|
||||||
|
snprintf(buf, buffer_len, str(LANG_PLAYTIME_STORAGE),
|
||||||
|
str1,str2,str3);
|
||||||
|
if (say_it) {
|
||||||
|
talk_id(LANG_PLAYTIME_STORAGE, false);
|
||||||
|
output_dyn_value(NULL, 0, pti->kbs_ttl, kibyte_units, 3, true);
|
||||||
|
talk_ids(true, VOICE_PAUSE, VOICE_PLAYTIME_DONE);
|
||||||
|
output_dyn_value(NULL, 0, pti->kbs_bef, kibyte_units, 3, true);
|
||||||
|
talk_id(LANG_PLAYTIME_REMAINING, true);
|
||||||
|
output_dyn_value(NULL, 0, pti->kbs_aft, kibyte_units, 3, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 6: { /* Average track file size */
|
||||||
|
char str[10];
|
||||||
|
long avg_track_size = pti->kbs_ttl /pti->nb_tracks;
|
||||||
|
output_dyn_value(str, sizeof(str), avg_track_size, kibyte_units, 3, true);
|
||||||
|
snprintf(buf, buffer_len, str(LANG_PLAYTIME_AVG_TRACK_SIZE),
|
||||||
|
str);
|
||||||
|
if (say_it) {
|
||||||
|
talk_id(LANG_PLAYTIME_AVG_TRACK_SIZE, false);
|
||||||
|
output_dyn_value(NULL, 0, avg_track_size, kibyte_units, 3, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 7: { /* Average bitrate */
|
||||||
|
/* Convert power of 2 kilobytes to power of 10 kilobits */
|
||||||
|
long avg_bitrate = pti->kbs_ttl / pti->secs_ttl *1024 *8 /1000;
|
||||||
|
snprintf(buf, buffer_len, str(LANG_PLAYTIME_AVG_BITRATE),
|
||||||
|
avg_bitrate);
|
||||||
|
if (say_it)
|
||||||
|
talk_ids(false, LANG_PLAYTIME_AVG_BITRATE,
|
||||||
|
TALK_ID(avg_bitrate, UNIT_KBIT));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char * playing_time_get_info(int selected_item, void * data,
|
||||||
|
char *buffer, size_t buffer_len)
|
||||||
|
{
|
||||||
|
return playing_time_get_or_speak_info(selected_item, data,
|
||||||
|
buffer, buffer_len, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int playing_time_speak_info(int selected_item, void * data)
|
||||||
|
{
|
||||||
|
static char buffer[MAX_PATH];
|
||||||
|
playing_time_get_or_speak_info(selected_item, data,
|
||||||
|
buffer, MAX_PATH, true);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* playing time screen: shows total and elapsed playlist duration and
|
||||||
|
other stats */
|
||||||
|
static bool playing_time(void)
|
||||||
|
{
|
||||||
|
unsigned long talked_tick = current_tick;
|
||||||
|
struct playing_time_info pti;
|
||||||
|
struct playlist_track_info pltrack;
|
||||||
|
struct mp3entry id3;
|
||||||
|
int i, fd, ret;
|
||||||
|
|
||||||
|
pti.nb_tracks = playlist_amount();
|
||||||
|
playlist_get_resume_info(&pti.curr_playing);
|
||||||
|
struct mp3entry *curr_id3 = audio_current_track();
|
||||||
|
if (pti.curr_playing == -1 || !curr_id3)
|
||||||
|
return false;
|
||||||
|
pti.secs_bef = pti.trk_secs_bef = curr_id3->elapsed/1000;
|
||||||
|
pti.secs_aft = pti.trk_secs_aft
|
||||||
|
= (curr_id3->length -curr_id3->elapsed)/1000;
|
||||||
|
pti.kbs_bef = curr_id3->offset/1024;
|
||||||
|
pti.kbs_aft = (curr_id3->filesize -curr_id3->offset)/1024;
|
||||||
|
|
||||||
|
splash(0, ID2P(LANG_WAIT));
|
||||||
|
|
||||||
|
/* Go through each file in the playlist and get its stats. For
|
||||||
|
huge playlists this can take a while... The reference position
|
||||||
|
is the position at the moment this function was invoked,
|
||||||
|
although playback continues forward. */
|
||||||
|
for (i = 0; i < pti.nb_tracks; i++) {
|
||||||
|
/* Show a splash while we are loading. */
|
||||||
|
splashf(0, str(LANG_LOADING_PERCENT),
|
||||||
|
i*100/pti.nb_tracks, str(LANG_OFF_ABORT));
|
||||||
|
/* Voice equivalent */
|
||||||
|
if (TIME_AFTER(current_tick, talked_tick+5*HZ)) {
|
||||||
|
talked_tick = current_tick;
|
||||||
|
talk_ids(false, LANG_LOADING_PERCENT,
|
||||||
|
TALK_ID(i*100/pti.nb_tracks, UNIT_PERCENT));
|
||||||
|
}
|
||||||
|
if (action_userabort(TIMEOUT_NOBLOCK))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
if (i == pti.curr_playing)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (playlist_get_track_info(NULL, i, &pltrack) < 0)
|
||||||
|
goto error;
|
||||||
|
if ((fd = open(pltrack.filename, O_RDONLY)) < 0)
|
||||||
|
goto error;
|
||||||
|
ret = get_metadata(&id3, fd, pltrack.filename);
|
||||||
|
close(fd);
|
||||||
|
if (!ret)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if (i < pti.curr_playing) {
|
||||||
|
pti.secs_bef += id3.length/1000;
|
||||||
|
pti.kbs_bef += id3.filesize/1024;
|
||||||
|
} else {
|
||||||
|
pti.secs_aft += id3.length/1000;
|
||||||
|
pti.kbs_aft += id3.filesize/1024;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pti.secs_ttl = pti.secs_bef +pti.secs_aft;
|
||||||
|
pti.trk_secs_ttl = pti.trk_secs_bef +pti.trk_secs_aft;
|
||||||
|
pti.kbs_ttl = pti.kbs_bef +pti.kbs_aft;
|
||||||
|
|
||||||
|
struct gui_synclist pt_lists;
|
||||||
|
int key;
|
||||||
|
|
||||||
|
gui_synclist_init(&pt_lists, &playing_time_get_info, &pti, true, 1, NULL);
|
||||||
|
if (global_settings.talk_menu)
|
||||||
|
gui_synclist_set_voice_callback(&pt_lists, playing_time_speak_info);
|
||||||
|
gui_synclist_set_nb_items(&pt_lists, 8);
|
||||||
|
gui_synclist_draw(&pt_lists);
|
||||||
|
gui_syncstatusbar_draw(&statusbars, true);
|
||||||
|
gui_synclist_speak_item(&pt_lists);
|
||||||
|
while (true) {
|
||||||
|
gui_syncstatusbar_draw(&statusbars, false);
|
||||||
|
if (list_do_action(CONTEXT_LIST, HZ/2,
|
||||||
|
&pt_lists, &key, LIST_WRAP_UNLESS_HELD) == 0
|
||||||
|
&& key!=ACTION_NONE && key!=ACTION_UNKNOWN)
|
||||||
|
{
|
||||||
|
talk_force_shutup();
|
||||||
|
return(default_event_handler(key) == SYS_USB_CONNECTED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error:
|
||||||
|
splash(HZ, ID2P(LANG_PLAYTIME_ERROR));
|
||||||
|
exit:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* CONTEXT_WPS playlist options */
|
/* CONTEXT_WPS playlist options */
|
||||||
static bool shuffle_playlist(void)
|
static bool shuffle_playlist(void)
|
||||||
{
|
{
|
||||||
|
@ -213,10 +470,12 @@ MENUITEM_FUNCTION(playlist_save_item, 0, ID2P(LANG_SAVE_DYNAMIC_PLAYLIST),
|
||||||
save_playlist, NULL, NULL, Icon_Playlist);
|
save_playlist, NULL, NULL, Icon_Playlist);
|
||||||
MENUITEM_FUNCTION(reshuffle_item, 0, ID2P(LANG_SHUFFLE_PLAYLIST),
|
MENUITEM_FUNCTION(reshuffle_item, 0, ID2P(LANG_SHUFFLE_PLAYLIST),
|
||||||
shuffle_playlist, NULL, NULL, Icon_Playlist);
|
shuffle_playlist, NULL, NULL, Icon_Playlist);
|
||||||
|
MENUITEM_FUNCTION(playing_time_item, 0, ID2P(LANG_PLAYING_TIME),
|
||||||
|
playing_time, NULL, NULL, Icon_Playlist);
|
||||||
MAKE_ONPLAYMENU( wps_playlist_menu, ID2P(LANG_PLAYLIST),
|
MAKE_ONPLAYMENU( wps_playlist_menu, ID2P(LANG_PLAYLIST),
|
||||||
NULL, Icon_Playlist,
|
NULL, Icon_Playlist,
|
||||||
&view_cur_playlist, &search_playlist_item,
|
&view_cur_playlist, &search_playlist_item,
|
||||||
&playlist_save_item, &reshuffle_item
|
&playlist_save_item, &reshuffle_item, &playing_time_item
|
||||||
);
|
);
|
||||||
|
|
||||||
/* CONTEXT_[TREE|ID3DB] playlist options */
|
/* CONTEXT_[TREE|ID3DB] playlist options */
|
||||||
|
@ -1160,7 +1419,7 @@ MENUITEM_RETURNVALUE(pictureflow_item, ID2P(LANG_ONPLAY_PICTUREFLOW),
|
||||||
static bool view_cue(void)
|
static bool view_cue(void)
|
||||||
{
|
{
|
||||||
struct mp3entry* id3 = audio_current_track();
|
struct mp3entry* id3 = audio_current_track();
|
||||||
if(id3 && id3->cuesheet)
|
if (id3 && id3->cuesheet)
|
||||||
{
|
{
|
||||||
browse_cuesheet(id3->cuesheet);
|
browse_cuesheet(id3->cuesheet);
|
||||||
}
|
}
|
||||||
|
|
|
@ -673,6 +673,8 @@ Malik Enes Şafak
|
||||||
Roman Levkin-Taymenev
|
Roman Levkin-Taymenev
|
||||||
Nathan Follens
|
Nathan Follens
|
||||||
Gergely Békési
|
Gergely Békési
|
||||||
|
Stephane Doyon
|
||||||
|
Alex Wallis
|
||||||
|
|
||||||
The libmad team
|
The libmad team
|
||||||
The wavpack team
|
The wavpack team
|
||||||
|
|
|
@ -217,12 +217,12 @@ Like the context menu for the \setting{File Browser}, the \setting{WPS Context M
|
||||||
allows you quick access to some often used functions.
|
allows you quick access to some often used functions.
|
||||||
|
|
||||||
\subsubsection{Playlist}
|
\subsubsection{Playlist}
|
||||||
The \setting{Playlist} submenu allows you to view, save, search and
|
The \setting{Playlist} submenu allows you to view, save, search, reshuffle,
|
||||||
reshuffle the current playlist. These and other operations are detailed in
|
and display the play time of the current playlist. These and other operations
|
||||||
\reference{ref:working_with_playlists}. To change settings for the
|
are detailed in \reference{ref:working_with_playlists}. To change settings for
|
||||||
\setting{Playlist Viewer} press \ActionStdContext{} while viewing the current
|
the \setting{Playlist Viewer} press \ActionStdContext{} while viewing the
|
||||||
playlist to bring up the \setting{Playlist Viewer Menu}. In this menu, you
|
current playlist to bring up the \setting{Playlist Viewer Menu}. In this
|
||||||
can find the \setting{Playlist Viewer Settings}.
|
menu, you can find the \setting{Playlist Viewer Settings}.
|
||||||
|
|
||||||
\paragraph{Playlist Viewer Settings}
|
\paragraph{Playlist Viewer Settings}
|
||||||
\begin{description}
|
\begin{description}
|
||||||
|
|
|
@ -137,7 +137,8 @@ playlist.
|
||||||
Dynamic playlists are saved so resume will restore them exactly as they
|
Dynamic playlists are saved so resume will restore them exactly as they
|
||||||
were before shutdown.
|
were before shutdown.
|
||||||
|
|
||||||
\note{To view, save or reshuffle the current dynamic playlist use the
|
\note{To view, save, reshuffle, or display the play time of the current
|
||||||
|
dynamic playlist use the
|
||||||
\setting{Playlist} sub menu in the WPS context menu or in the
|
\setting{Playlist} sub menu in the WPS context menu or in the
|
||||||
\setting{Main Menu}.}
|
\setting{Main Menu}.}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user