summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/bookmark.c2
-rw-r--r--apps/filetree.c5
-rw-r--r--apps/gui/skin_engine/skin_parser.c6
-rw-r--r--apps/gui/skin_engine/skin_touchsupport.c1
-rw-r--r--apps/misc.c2
-rw-r--r--apps/mpeg.c60
-rw-r--r--apps/onplay.c2
-rw-r--r--apps/playback.c137
-rwxr-xr-xapps/playlist.c21
-rw-r--r--apps/playlist.h6
-rw-r--r--apps/playlist_viewer.c10
-rw-r--r--apps/plugin.h12
-rw-r--r--apps/plugins/alarmclock.c1
-rw-r--r--apps/plugins/alpine_cdc.c4
-rw-r--r--apps/plugins/lib/playback_control.c1
-rw-r--r--apps/plugins/lrcplayer.c1
-rw-r--r--apps/plugins/pictureflow/pictureflow.c2
-rw-r--r--apps/plugins/random_folder_advance_config.c2
-rw-r--r--apps/root_menu.c1
-rw-r--r--apps/settings.c11
-rw-r--r--apps/settings.h2
-rw-r--r--apps/settings_list.c1
-rw-r--r--apps/settings_list.h2
-rw-r--r--apps/tagcache.c12
-rw-r--r--apps/tagcache.h14
-rw-r--r--apps/tagtree.c20
-rw-r--r--apps/tree.c8
-rw-r--r--apps/tree.h4
28 files changed, 241 insertions, 109 deletions
diff --git a/apps/bookmark.c b/apps/bookmark.c
index 543e89331a..3234e77d9b 100644
--- a/apps/bookmark.c
+++ b/apps/bookmark.c
@@ -972,7 +972,7 @@ static bool play_bookmark(const char* bookmark)
if (!warn_on_pl_erase())
return false;
return bookmark_play(global_temp_buffer, bm.resume_index,
- bm.resume_offset, bm.resume_seed, global_filename);
+ bm.resume_time, bm.resume_offset, bm.resume_seed, global_filename);
}
return false;
diff --git a/apps/filetree.c b/apps/filetree.c
index 2edcaf3a03..319b5f4a77 100644
--- a/apps/filetree.c
+++ b/apps/filetree.c
@@ -118,7 +118,7 @@ bool ft_play_playlist(char* pathname, char* dirname, char* filename)
playlist_shuffle(current_tick, -1);
}
- playlist_start(0, 0);
+ playlist_start(0, 0, 0);
return true;
}
@@ -498,7 +498,7 @@ int ft_enter(struct tree_context* c)
start_index = 0;
}
- playlist_start(start_index, 0);
+ playlist_start(start_index, 0, 0);
play = true;
}
break;
@@ -705,6 +705,7 @@ int ft_enter(struct tree_context* c)
global_status.resume_index = start_index;
global_status.resume_crc32 =
playlist_get_filename_crc32(NULL, start_index);
+ global_status.resume_elapsed = 0;
global_status.resume_offset = 0;
status_save();
rc = GO_TO_WPS;
diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c
index a76a06ac61..57153ed602 100644
--- a/apps/gui/skin_engine/skin_parser.c
+++ b/apps/gui/skin_engine/skin_parser.c
@@ -2414,10 +2414,12 @@ bool skin_data_load(enum screen_type screen, struct wps_data *wps_data,
(((wps_data->last_albumart_height != aa->height) ||
(wps_data->last_albumart_width != aa->width)))))
{
- long offset = audio_current_track()->offset;
+ struct mp3entry *id3 = audio_current_track();
+ unsigned long elapsed = id3->elapsed;
+ unsigned long offset = id3->offset;
audio_stop();
if (!(status & AUDIO_STATUS_PAUSE))
- audio_play(offset);
+ audio_play(elapsed, offset);
}
}
#endif
diff --git a/apps/gui/skin_engine/skin_touchsupport.c b/apps/gui/skin_engine/skin_touchsupport.c
index dbc561500a..7a03e83c36 100644
--- a/apps/gui/skin_engine/skin_touchsupport.c
+++ b/apps/gui/skin_engine/skin_touchsupport.c
@@ -177,6 +177,7 @@ int skin_get_touchaction(struct wps_data *data, int* edge_offset,
if (playlist_resume() != -1)
{
playlist_start(global_status.resume_index,
+ global_status.resume_elapsed,
global_status.resume_offset);
}
}
diff --git a/apps/misc.c b/apps/misc.c
index fdbc1fb831..6c589b99e4 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -618,6 +618,7 @@ long default_event_handler_ex(long event, void (*callback)(void *), void *parame
if (resume && playlist_resume() != -1)
{
playlist_start(global_status.resume_index,
+ global_status.resume_elapsed,
global_status.resume_offset);
}
resume = false;
@@ -657,6 +658,7 @@ long default_event_handler_ex(long event, void (*callback)(void *), void *parame
if (playlist_resume() != -1)
{
playlist_start(global_status.resume_index,
+ global_status.resume_elapsed,
global_status.resume_offset);
}
return event;
diff --git a/apps/mpeg.c b/apps/mpeg.c
index c0b2ae0c0e..d3e0e5c137 100644
--- a/apps/mpeg.c
+++ b/apps/mpeg.c
@@ -177,6 +177,13 @@ static long low_watermark; /* Dynamic low watermark level */
static long low_watermark_margin = 0; /* Extra time in seconds for watermark */
static long lowest_watermark_level; /* Debug value to observe the buffer
usage */
+
+struct audio_resume_info
+{
+ unsigned long elapsed;
+ unsigned long offset;
+};
+
#if CONFIG_CODEC == MAS3587F
static char recording_filename[MAX_PATH]; /* argument to thread */
static char delayed_filename[MAX_PATH]; /* internal copy of above */
@@ -430,10 +437,9 @@ static void set_elapsed(struct mp3entry* id3)
id3->elapsed = id3->offset / (id3->bitrate / 8);
}
-int audio_get_file_pos(void)
+static int audio_get_file_pos_int(struct mp3entry *id3)
{
int pos = -1;
- struct mp3entry *id3 = audio_current_track();
if (id3->vbr)
{
@@ -490,6 +496,12 @@ int audio_get_file_pos(void)
return pos;
}
+int audio_get_file_pos(void)
+{
+ struct mp3entry *id3 = audio_current_track();
+ return id3 ? audio_get_file_pos_int(id3) : 0;
+}
+
unsigned long mpeg_get_last_header(void)
{
#ifdef SIMULATOR
@@ -545,7 +557,13 @@ static int shrink_callback(int handle, unsigned hints, void* start, size_t old_s
}
/* TODO: Do it without stopping playback, if possible */
bool playing = (audio_status() & AUDIO_STATUS_PLAY) == AUDIO_STATUS_PLAY;
- long offset = audio_current_track()->offset;
+ struct mp3entry *id3 = audio_current_track();
+ unsigned long elapsed = 0, offset = 0;
+ if (id3)
+ {
+ elapsed = id3->elapsed;
+ offset = id3->offset;
+ }
/* don't call audio_hard_stop() as it frees this handle */
if (thread_self() == audio_thread_id)
{ /* inline case MPEG_STOP (audio_stop()) response
@@ -574,7 +592,7 @@ static int shrink_callback(int handle, unsigned hints, void* start, size_t old_s
}
if (playing)
{ /* safe to call even from the audio thread (due to queue_post()) */
- audio_play(offset);
+ audio_play(elapsed, offset);
}
return BUFLIB_CB_OK;
@@ -1274,7 +1292,7 @@ static void mpeg_thread(void)
int unplayed_space_left;
int amount_to_read;
int t1, t2;
- int start_offset;
+ unsigned long start_elapsed, start_offset;
#if CONFIG_CODEC == MAS3587F
int amount_to_save;
int save_endpos = 0;
@@ -1337,9 +1355,16 @@ static void mpeg_thread(void)
break;
}
- start_offset = (int)ev.data;
+ start_elapsed = ((struct audio_resume_info *)ev.data)->elapsed;
+ start_offset = ((struct audio_resume_info *)ev.data)->offset;
/* mid-song resume? */
+ if (!start_offset && start_elapsed) {
+ struct mp3entry *id3 = &get_trackdata(0)->id3;
+ id3->elapsed = start_elapsed;
+ start_offset = audio_get_file_pos_int(id3);
+ }
+
if (start_offset) {
struct mp3entry* id3 = &get_trackdata(0)->id3;
lseek(mpeg_file, start_offset, SEEK_SET);
@@ -1506,7 +1531,7 @@ static void mpeg_thread(void)
id3->elapsed = newtime;
- newpos = audio_get_file_pos();
+ newpos = audio_get_file_pos_int(id3);
if(newpos < 0)
{
id3->elapsed = oldtime;
@@ -2765,7 +2790,7 @@ static void audio_reset_buffer(void)
audio_reset_buffer_noalloc(core_get_data(audiobuf_handle), bufsize);
}
-void audio_play(long offset)
+void audio_play(unsigned long elapsed, unsigned long offset)
{
audio_reset_buffer();
#ifdef SIMULATOR
@@ -2789,15 +2814,28 @@ void audio_play(long offset)
real_mpeg_play(trackname);
#endif
playlist_next(steps);
- taginfo.offset = offset;
- set_elapsed(&taginfo);
+ if (!offset && elapsed)
+ {
+ /* has an elapsed time but no offset; elapsed may take
+ precedence in this case */
+ taginfo.elapsed = elapsed;
+ taginfo.offset = audio_get_file_pos_int(&taginfo);
+ }
+ else
+ {
+ taginfo.offset = offset;
+ set_elapsed(&taginfo);
+ }
is_playing = true;
playing = true;
break;
} while(1);
#else /* !SIMULATOR */
+ static struct audio_resume_info resume;
is_playing = true;
- queue_post(&mpeg_queue, MPEG_PLAY, offset);
+ resume.elapsed = elapsed;
+ resume.offset = offset;
+ queue_post(&mpeg_queue, MPEG_PLAY, (intptr_t)&resume);
#endif /* !SIMULATOR */
mpeg_errno = 0;
diff --git a/apps/onplay.c b/apps/onplay.c
index 9152d87bf5..7c5f517090 100644
--- a/apps/onplay.c
+++ b/apps/onplay.c
@@ -223,7 +223,7 @@ static bool add_to_playlist(int position, bool queue)
inserted */
if (global_settings.playlist_shuffle)
playlist_shuffle(current_tick, -1);
- playlist_start(0,0);
+ playlist_start(0, 0, 0);
onplay_result = ONPLAY_START_PLAY;
}
diff --git a/apps/playback.c b/apps/playback.c
index 5e234beb36..80a0585b17 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -151,6 +151,12 @@ enum audio_id3_types
};
static struct mp3entry static_id3_entries[ID3_TYPE_NUM_STATIC]; /* (A,O) */
+struct audio_resume_info
+{
+ unsigned long elapsed;
+ unsigned long offset;
+};
+
/* Peeking functions can yield and mess us up */
static struct mutex id3_mutex SHAREDBSS_ATTR; /* (A,O)*/
@@ -325,7 +331,8 @@ enum audio_start_playback_flags
AUDIO_START_NEWBUF = 0x2, /* Mark the audiobuffer as invalid */
};
-static void audio_start_playback(size_t offset, unsigned int flags);
+static void audio_start_playback(const struct audio_resume_info *resume_info,
+ unsigned int flags);
static void audio_stop_playback(void);
static void buffer_event_buffer_low_callback(void *data);
static void buffer_event_rebuffer_callback(void *data);
@@ -792,7 +799,11 @@ static int shrink_callback(int handle, unsigned hints, void* start, size_t old_s
/* codec messages */
{ Q_AUDIO_PLAY, Q_AUDIO_PLAY },
};
+
+ static struct audio_resume_info resume;
+
bool give_up = false;
+
/* filebuflen is, at this point, the buffering.c buffer size,
* i.e. the audiobuf except voice, scratch mem, pcm, ... */
ssize_t extradata_size = old_size - filebuflen;
@@ -813,7 +824,9 @@ static int shrink_callback(int handle, unsigned hints, void* start, size_t old_s
/* TODO: Do it without stopping playback, if possible */
- long offset = audio_current_track()->offset;
+ struct mp3entry *id3 = audio_current_track();
+ unsigned long elapsed = id3->elapsed;
+ unsigned long offset = id3->offset;
/* resume if playing */
bool playing = (audio_status() == AUDIO_STATUS_PLAY);
/* There's one problem with stoping and resuming: If it happens in a too
@@ -825,10 +838,20 @@ static int shrink_callback(int handle, unsigned hints, void* start, size_t old_s
* queue_post from the last call to get the correct offset. This also
* lets us conviniently remove the queue event so Q_AUDIO_PLAY is only
* processed once. */
- bool play_queued = queue_peek_ex(&audio_queue, &ev, QPEEK_REMOVE_EVENTS, filter_list);
+ bool play_queued = queue_peek_ex(&audio_queue, &ev, QPEEK_REMOVE_EVENTS,
+ filter_list);
- if (playing && offset > 0) /* current id3->offset is king */
- ev.data = offset;
+ if (playing && ev.data != (intptr_t)&resume)
+ {
+ resume = *(struct audio_resume_info *)ev.data;
+
+ /* current id3->elapsed/offset are king */
+ if (elapsed > 0)
+ resume.elapsed = elapsed;
+
+ if (offset > 0)
+ resume.offset = offset;
+ }
/* don't call audio_hard_stop() as it frees this handle */
if (thread_self() == audio_thread_id)
@@ -867,7 +890,7 @@ static int shrink_callback(int handle, unsigned hints, void* start, size_t old_s
if (playing || play_queued)
{
/* post, to make subsequent calls not break the resume position */
- audio_queue_post(Q_AUDIO_PLAY, ev.data);
+ audio_queue_post(Q_AUDIO_PLAY, (intptr_t)&resume);
}
return BUFLIB_CB_OK;
@@ -1099,7 +1122,8 @@ static void audio_update_and_announce_next_track(const struct mp3entry *id3_next
/* Bring the user current mp3entry up to date and set a new offset for the
buffered metadata */
-static void playing_id3_sync(struct track_info *user_info, off_t offset)
+static void playing_id3_sync(struct track_info *user_info,
+ unsigned long elapsed, unsigned long offset)
{
id3_mutex_lock();
@@ -1113,9 +1137,14 @@ static void playing_id3_sync(struct track_info *user_info, off_t offset)
id3_write(PLAYING_ID3, id3);
- if (offset < 0)
+ if (elapsed == (unsigned long)-1)
{
playing_id3->elapsed = e;
+ elapsed = 0;
+ }
+
+ if (offset == (unsigned long)-1)
+ {
playing_id3->offset = o;
offset = 0;
}
@@ -1123,7 +1152,10 @@ static void playing_id3_sync(struct track_info *user_info, off_t offset)
pcm_play_unlock();
if (id3)
+ {
+ id3->elapsed = elapsed;
id3->offset = offset;
+ }
id3_mutex_unlock();
}
@@ -1299,19 +1331,16 @@ static bool audio_get_track_metadata(int offset, struct mp3entry *id3)
return false;
}
-/* Get a resume rewind adjusted offset from the ID3 */
-static unsigned long resume_rewind_adjusted_offset(const struct mp3entry *id3)
+/* Get resume rewind adjusted progress from the ID3 */
+static void resume_rewind_adjust_progress(const struct mp3entry *id3,
+ unsigned long *elapsed,
+ unsigned long *offset)
{
- unsigned long offset = id3->offset;
- size_t resume_rewind = global_settings.resume_rewind *
- id3->bitrate * (1000/8);
-
- if (offset < resume_rewind)
- offset = 0;
- else
- offset -= resume_rewind;
-
- return offset;
+ unsigned int rewind = MAX(global_settings.resume_rewind, 0);
+ unsigned long d_e = rewind*1000;
+ *elapsed = id3->elapsed - MIN(id3->elapsed, d_e);
+ unsigned long d_o = rewind * id3->bitrate * (1000/8);
+ *offset = id3->offset - MIN(id3->offset, d_o);
}
/* Get the codec into ram and initialize it - keep it if it's ready */
@@ -1436,7 +1465,7 @@ static bool audio_start_codec(bool auto_skip)
#ifdef HAVE_TAGCACHE
bool autoresume_enable = global_settings.autoresume_enable;
- if (autoresume_enable && !cur_id3->offset)
+ if (autoresume_enable && !(cur_id3->elapsed || cur_id3->offset))
{
/* Resume all manually selected tracks */
bool resume = !auto_skip;
@@ -1466,10 +1495,13 @@ static bool audio_start_codec(bool auto_skip)
}
if (!resume)
+ {
+ cur_id3->elapsed = 0;
cur_id3->offset = 0;
+ }
- logf("%s: Set offset for %s to %lX\n", __func__,
- cur_id3->title, cur_id3->offset);
+ logf("%s: Set resume for %s to %lu %lX", __func__,
+ cur_id3->title, cur_id3->elapsed, cur_id3->offset);
}
#endif /* HAVE_TAGCACHE */
@@ -1481,7 +1513,8 @@ static bool audio_start_codec(bool auto_skip)
and back again will cause accumulation of silent rewinds - that's not
our job to track directly nor could it be in any reasonable way
*/
- cur_id3->offset = resume_rewind_adjusted_offset(cur_id3);
+ resume_rewind_adjust_progress(cur_id3, &cur_id3->elapsed,
+ &cur_id3->offset);
/* Update the codec API with the metadata and track info */
id3_write(CODEC_ID3, cur_id3);
@@ -1494,7 +1527,7 @@ static bool audio_start_codec(bool auto_skip)
codec_go();
#ifdef HAVE_TAGCACHE
- if (!autoresume_enable || cur_id3->offset)
+ if (!autoresume_enable || cur_id3->elapsed || cur_id3->offset)
#endif
{
/* Send the "buffer" event now */
@@ -1923,7 +1956,9 @@ static int audio_finish_load_track(struct track_info *info)
/** Finally, load the audio **/
size_t file_offset = 0;
- track_id3->elapsed = 0;
+
+ if (track_id3->elapsed > track_id3->length)
+ track_id3->elapsed = 0;
if (track_id3->offset >= info->filesize)
track_id3->offset = 0;
@@ -1933,7 +1968,11 @@ static int audio_finish_load_track(struct track_info *info)
/* Adjust for resume rewind so we know what to buffer - starting the codec
calls it again, so we don't save it (and they shouldn't accumulate) */
- size_t offset = resume_rewind_adjusted_offset(track_id3);
+ unsigned long elapsed, offset;
+ resume_rewind_adjust_progress(track_id3, &elapsed, &offset);
+
+ logf("%s: Set resume for %s to %lu %lX", __func__,
+ id3->title, elapsed, offset);
enum data_type audiotype = rbcodec_format_is_atomic(track_id3->codectype) ?
TYPE_ATOMIC_AUDIO : TYPE_PACKET_AUDIO;
@@ -2168,7 +2207,7 @@ static void audio_on_finish_load_track(int id3_hid)
change otherwise */
bool was_valid = valid_mp3entry(id3_get(PLAYING_ID3));
- playing_id3_sync(info, -1);
+ playing_id3_sync(info, -1, -1);
if (!was_valid)
{
@@ -2306,7 +2345,7 @@ static void audio_begin_track_change(enum pcm_track_change_type type,
if (audio_start_codec(auto_skip))
{
if (!auto_skip)
- playing_id3_sync(info, -1);
+ playing_id3_sync(info, -1, -1);
return;
}
@@ -2455,8 +2494,11 @@ static void audio_on_track_changed(void)
/* Begin playback from an idle state, transition to a new playlist or
invalidate the buffer and resume (if playing).
(usually Q_AUDIO_PLAY, Q_AUDIO_REMAKE_AUDIO_BUFFER) */
-static void audio_start_playback(size_t offset, unsigned int flags)
+static void audio_start_playback(const struct audio_resume_info *resume_info,
+ unsigned int flags)
{
+ struct audio_resume_info resume =
+ *(resume_info ?: &(struct audio_resume_info){ 0, 0 } );
enum play_status old_status = play_status;
if (flags & AUDIO_START_NEWBUF)
@@ -2469,7 +2511,8 @@ static void audio_start_playback(size_t offset, unsigned int flags)
if (old_status != PLAY_STOPPED)
{
- logf("%s(%lu): skipping", __func__, (unsigned long)offset);
+ logf("%s(%lu, %lu): skipping", __func__, resume.elapsed,
+ resume.offset);
halt_decoding_track(true);
@@ -2481,7 +2524,8 @@ static void audio_start_playback(size_t offset, unsigned int flags)
/* Clear out some stuff to resume the current track where it
left off */
pcmbuf_play_stop();
- offset = id3_get(PLAYING_ID3)->offset;
+ resume.elapsed = id3_get(PLAYING_ID3)->elapsed;
+ resume.offset = id3_get(PLAYING_ID3)->offset;
track_list_clear(TRACK_LIST_CLEAR_ALL);
}
else
@@ -2505,7 +2549,8 @@ static void audio_start_playback(size_t offset, unsigned int flags)
return; /* Must already be playing */
/* Cold playback start from a stopped state */
- logf("%s(%lu): starting", __func__, offset);
+ logf("%s(%lu, %lu): starting", __func__, resume.elapsed,
+ resume.offset);
/* Set audio parameters */
#if INPUT_SRC_CAPS != 0
@@ -2555,7 +2600,7 @@ static void audio_start_playback(size_t offset, unsigned int flags)
if (trackstat >= LOAD_TRACK_OK)
{
/* This is the currently playing track - get metadata, stat */
- playing_id3_sync(track_list_current(0), offset);
+ playing_id3_sync(track_list_current(0), resume.elapsed, resume.offset);
if (valid_mp3entry(id3_get(PLAYING_ID3)))
{
@@ -2892,7 +2937,9 @@ static void audio_on_ff_rewind(long time)
if (!haltres)
{
- /* If codec must be (re)started, reset the offset */
+ /* If codec must be (re)started, reset the resume info so that
+ it doesn't execute resume procedures */
+ ci_id3->elapsed = 0;
ci_id3->offset = 0;
}
@@ -2970,7 +3017,7 @@ static void audio_on_audio_flush(void)
not possible so a restart is required in order to continue the
currently playing track without the now invalid future track
playing */
- audio_start_playback(0, AUDIO_START_RESTART);
+ audio_start_playback(NULL, AUDIO_START_RESTART);
break;
default: /* Nothing else is a state */
@@ -3008,7 +3055,7 @@ void audio_playback_handler(struct queue_event *ev)
/** Control messages **/
case Q_AUDIO_PLAY:
LOGFQUEUE("playback < Q_AUDIO_PLAY");
- audio_start_playback(ev->data, 0);
+ audio_start_playback((struct audio_resume_info *)ev->data, 0);
break;
#ifdef HAVE_RECORDING
@@ -3082,7 +3129,7 @@ void audio_playback_handler(struct queue_event *ev)
case Q_AUDIO_REMAKE_AUDIO_BUFFER:
/* buffer needs to be reinitialized */
LOGFQUEUE("playback < Q_AUDIO_REMAKE_AUDIO_BUFFER");
- audio_start_playback(0, AUDIO_START_RESTART | AUDIO_START_NEWBUF);
+ audio_start_playback(NULL, AUDIO_START_RESTART | AUDIO_START_NEWBUF);
if (play_status == PLAY_STOPPED)
return; /* just need to change buffer state */
break;
@@ -3368,8 +3415,8 @@ struct mp3entry * audio_next_track(void)
return id3;
}
-/* Start playback at the specified offset */
-void audio_play(long offset)
+/* Start playback at the specified elapsed time or offset */
+void audio_play(unsigned long elapsed, unsigned long offset)
{
logf("audio_play");
@@ -3379,8 +3426,9 @@ void audio_play(long offset)
talk_force_shutup();
#endif
- LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
- audio_queue_send(Q_AUDIO_PLAY, offset);
+ LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %lu %lX", elapsed, offset);
+ audio_queue_send(Q_AUDIO_PLAY,
+ (intptr_t)&(struct audio_resume_info){ elapsed, offset });
}
/* Stop playback if playing */
@@ -3582,11 +3630,10 @@ void playback_release_aa_slot(int slot)
}
#endif /* HAVE_ALBUMART */
-/* Would normally calculate byte offset from an elapsed time but is not
- used on SWCODEC */
+/* Return file byte offset */
int audio_get_file_pos(void)
{
- return 0;
+ return id3_get(PLAYING_ID3)->offset;
}
/* Return total file buffer length after accounting for the talk buf */
diff --git a/apps/playlist.c b/apps/playlist.c
index 9c895bfd67..0e73781238 100755
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -621,7 +621,7 @@ static int create_and_play_dir(int direction, bool play_last)
#if (CONFIG_CODEC == SWCODEC)
current_playlist.started = true;
#else
- playlist_start(index, 0);
+ playlist_start(index, 0, 0);
#endif
}
@@ -2565,7 +2565,8 @@ unsigned int playlist_get_filename_crc32(struct playlist_info *playlist,
}
/* resume a playlist track with the given crc_32 of the track name. */
-void playlist_resume_track(int start_index, unsigned int crc, int offset)
+void playlist_resume_track(int start_index, unsigned int crc,
+ unsigned long elapsed, unsigned long offset)
{
int i;
unsigned int tmp_crc;
@@ -2573,7 +2574,7 @@ void playlist_resume_track(int start_index, unsigned int crc, int offset)
tmp_crc = playlist_get_filename_crc32(playlist, start_index);
if (tmp_crc == crc)
{
- playlist_start(start_index, offset);
+ playlist_start(start_index, elapsed, offset);
return;
}
@@ -2582,17 +2583,18 @@ void playlist_resume_track(int start_index, unsigned int crc, int offset)
tmp_crc = playlist_get_filename_crc32(playlist, i);
if (tmp_crc == crc)
{
- playlist_start(i, offset);
+ playlist_start(i, elapsed, offset);
return;
}
}
/* If we got here the file wasnt found, so start from the beginning */
- playlist_start(0,0);
+ playlist_start(0, 0, 0);
}
/* start playing current playlist at specified index/offset */
-void playlist_start(int start_index, int offset)
+void playlist_start(int start_index, unsigned long elapsed,
+ unsigned long offset)
{
struct playlist_info* playlist = &current_playlist;
@@ -2605,7 +2607,7 @@ void playlist_start(int start_index, int offset)
playlist->started = true;
sync_control(playlist, false);
- audio_play(offset);
+ audio_play(elapsed, offset);
}
/* Returns false if 'steps' is out of bounds, else true */
@@ -2723,7 +2725,7 @@ int playlist_next(int steps)
#if CONFIG_CODEC == SWCODEC
playlist->started = true;
#else
- playlist_start(0, 0);
+ playlist_start(0, 0, 0);
#endif
playlist->index = 0;
index = 0;
@@ -2801,11 +2803,13 @@ int playlist_update_resume_info(const struct mp3entry* id3)
if (id3)
{
if (global_status.resume_index != playlist->index ||
+ global_status.resume_elapsed != id3->elapsed ||
global_status.resume_offset != id3->offset)
{
unsigned int crc = crc_32(id3->path, strlen(id3->path), -1);
global_status.resume_index = playlist->index;
global_status.resume_crc32 = crc;
+ global_status.resume_elapsed = id3->elapsed;
global_status.resume_offset = id3->offset;
status_save();
}
@@ -2814,6 +2818,7 @@ int playlist_update_resume_info(const struct mp3entry* id3)
{
global_status.resume_index = -1;
global_status.resume_crc32 = -1;
+ global_status.resume_elapsed = -1;
global_status.resume_offset = -1;
status_save();
}
diff --git a/apps/playlist.h b/apps/playlist.h
index d80d8aa2ee..6314e9a6ee 100644
--- a/apps/playlist.h
+++ b/apps/playlist.h
@@ -133,8 +133,10 @@ int playlist_add(const char *filename);
int playlist_shuffle(int random_seed, int start_index);
unsigned int playlist_get_filename_crc32(struct playlist_info *playlist,
int index);
-void playlist_resume_track(int start_index, unsigned int crc, int offset);
-void playlist_start(int start_index, int offset);
+void playlist_resume_track(int start_index, unsigned int crc,
+ unsigned long elapsed, unsigned long offset);
+void playlist_start(int start_index, unsigned long elapsed,
+ unsigned long offset);
bool playlist_check(int steps);
const char *playlist_peek(int steps, char* buf, size_t buf_size);
int playlist_next(int steps);
diff --git a/apps/playlist_viewer.c b/apps/playlist_viewer.c
index 6a20bf1aac..d28643ab20 100644
--- a/apps/playlist_viewer.c
+++ b/apps/playlist_viewer.c
@@ -458,6 +458,7 @@ static bool update_playlist(bool force)
{
global_status.resume_index = -1;
global_status.resume_offset = -1;
+ global_status.resume_elapsed = -1;
return false;
}
playlist_buffer_load_entries_screen(&viewer.buffer, FORWARD,
@@ -466,6 +467,7 @@ static bool update_playlist(bool force)
{
global_status.resume_index = -1;
global_status.resume_offset = -1;
+ global_status.resume_elapsed = -1;
return false;
}
}
@@ -526,7 +528,7 @@ static int onplay_menu(int index)
if (current_track->display_index!=viewer.num_tracks ||
global_settings.repeat_mode == REPEAT_ALL)
{
- audio_play(0);
+ audio_play(0, 0);
viewer.current_playing_track = -1;
}
}
@@ -773,7 +775,7 @@ enum playlist_viewer_result playlist_viewer_ex(const char* filename)
/* play new track */
if (!global_settings.party_mode)
{
- playlist_start(current_track->index, 0);
+ playlist_start(current_track->index, 0, 0);
update_playlist(false);
}
}
@@ -790,7 +792,7 @@ enum playlist_viewer_result playlist_viewer_ex(const char* filename)
goto exit;
if (global_settings.playlist_shuffle)
start_index = playlist_shuffle(current_tick, start_index);
- playlist_start(start_index, 0);
+ playlist_start(start_index, 0, 0);
/* Our playlist is now the current list */
if (!playlist_viewer_init(&viewer, NULL, true))
@@ -937,7 +939,7 @@ bool search_playlist(void)
case ACTION_STD_OK:
{
int sel = gui_synclist_get_sel_pos(&playlist_lists);
- playlist_start(found_indicies[sel], 0);
+ playlist_start(found_indicies[sel], 0, 0);
exit = 1;
}
break;
diff --git a/apps/plugin.h b/apps/plugin.h
index 764af4a6b7..ffdfa8fb77 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -160,12 +160,12 @@ void* plugin_get_buffer(size_t *buffer_size);
#define PLUGIN_MAGIC 0x526F634B /* RocK */
/* increase this every time the api struct changes */
-#define PLUGIN_API_VERSION 226
+#define PLUGIN_API_VERSION 227
/* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any
new function which are "waiting" at the end of the function table) */
-#define PLUGIN_MIN_API_VERSION 226
+#define PLUGIN_MIN_API_VERSION 227
/* plugin return codes */
/* internal returns start at 0x100 to make exit(1..255) work */
@@ -723,8 +723,10 @@ struct plugin_api {
/* playback control */
int (*playlist_amount)(void);
int (*playlist_resume)(void);
- void (*playlist_resume_track)(int start_index, unsigned int crc, int offset);
- void (*playlist_start)(int start_index, int offset);
+ void (*playlist_resume_track)(int start_index, unsigned int crc,
+ unsigned long elapsed, unsigned long offset);
+ void (*playlist_start)(int start_index, unsigned long elapsed,
+ unsigned long offset);
int (*playlist_add)(const char *filename);
void (*playlist_sync)(struct playlist_info* playlist);
int (*playlist_remove_all_tracks)(struct playlist_info *playlist);
@@ -735,7 +737,7 @@ struct plugin_api {
const char *dirname, int position, bool queue,
bool recurse);
int (*playlist_shuffle)(int random_seed, int start_index);
- void (*audio_play)(long offset);
+ void (*audio_play)(unsigned long elapsed, unsigned long offset);
void (*audio_stop)(void);
void (*audio_pause)(void);
void (*audio_resume)(void);
diff --git a/apps/plugins/alarmclock.c b/apps/plugins/alarmclock.c
index 79a676003a..ecafceddc7 100644
--- a/apps/plugins/alarmclock.c
+++ b/apps/plugins/alarmclock.c
@@ -109,6 +109,7 @@ static void resume_audio(void)
if (rb->playlist_resume() != -1) {
rb->playlist_resume_track(rb->global_status->resume_index,
rb->global_status->resume_crc32,
+ rb->global_status->resume_elapsed,
rb->global_status->resume_offset);
}
}
diff --git a/apps/plugins/alpine_cdc.c b/apps/plugins/alpine_cdc.c
index 653c968ffa..28bb8d8b7f 100644
--- a/apps/plugins/alpine_cdc.c
+++ b/apps/plugins/alpine_cdc.c
@@ -997,8 +997,8 @@ void set_play(void)
}
else
{
- print_scroll("audio_play(0)");
- rb->audio_play(0);
+ print_scroll("audio_play(0, 0)");
+ rb->audio_play(0, 0);
}
}
diff --git a/apps/plugins/lib/playback_control.c b/apps/plugins/lib/playback_control.c
index 47921e52f2..1be234f70f 100644
--- a/apps/plugins/lib/playback_control.c
+++ b/apps/plugins/lib/playback_control.c
@@ -39,6 +39,7 @@ static bool play(void)
{
rb->playlist_resume_track(rb->global_status->resume_index,
rb->global_status->resume_crc32,
+ rb->global_status->resume_elapsed,
rb->global_status->resume_offset);
}
}
diff --git a/apps/plugins/lrcplayer.c b/apps/plugins/lrcplayer.c
index 6e0394fa51..392e78e77f 100644
--- a/apps/plugins/lrcplayer.c
+++ b/apps/plugins/lrcplayer.c
@@ -2684,6 +2684,7 @@ static int handle_button(void)
{
rb->playlist_resume_track(rb->global_status->resume_index,
rb->global_status->resume_crc32,
+ rb->global_status->resume_elapsed,
rb->global_status->resume_offset);
}
}
diff --git a/apps/plugins/pictureflow/pictureflow.c b/apps/plugins/pictureflow/pictureflow.c
index 51fe5ebfc5..bb7cec888f 100644
--- a/apps/plugins/pictureflow/pictureflow.c
+++ b/apps/plugins/pictureflow/pictureflow.c
@@ -2580,7 +2580,7 @@ play:
* if shuffle, we can't predict the playing track easily, and for either
* case the track list doesn't get auto scrolled*/
if(!append)
- rb->playlist_start(position, 0);
+ rb->playlist_start(position, 0, 0);
old_playlist = center_slide.slide_index;
old_shuffle = shuffle;
}
diff --git a/apps/plugins/random_folder_advance_config.c b/apps/plugins/random_folder_advance_config.c
index 7f6018df4e..0b3532dde0 100644
--- a/apps/plugins/random_folder_advance_config.c
+++ b/apps/plugins/random_folder_advance_config.c
@@ -541,7 +541,7 @@ static int start_shuffled_play(void)
}
}
rb->splash(HZ, "Done");
- rb->playlist_start(0,0);
+ rb->playlist_start(0, 0, 0);
return 1;
}
diff --git a/apps/root_menu.c b/apps/root_menu.c
index 259d9bf69c..09c7efad9d 100644
--- a/apps/root_menu.c
+++ b/apps/root_menu.c
@@ -306,6 +306,7 @@ static int wpsscrn(void* param)
{
playlist_resume_track(global_status.resume_index,
global_status.resume_crc32,
+ global_status.resume_elapsed,
global_status.resume_offset);
ret_val = gui_wps_show();
}
diff --git a/apps/settings.c b/apps/settings.c
index 13dcb5cca9..58d58788be 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -738,12 +738,17 @@ void settings_apply_play_freq(int value, bool playback)
bool changed = value != prev_setting;
prev_setting = value;
- long offset = 0;
+ unsigned long elapsed = 0;
+ unsigned long offset = 0;
bool playing = changed && !playback &&
audio_status() == AUDIO_STATUS_PLAY;
if (playing)
- offset = audio_current_track()->offset;
+ {
+ struct mp3entry *id3 = audio_current_track();
+ elapsed = id3->elapsed;
+ offset = id3->offset;
+ }
if (changed && !playback)
audio_hard_stop();
@@ -752,7 +757,7 @@ void settings_apply_play_freq(int value, bool playback)
mixer_set_frequency(play_sampr[value]);
if (playing)
- audio_play(offset);
+ audio_play(elapsed, offset);
}
#endif /* HAVE_PLAY_FREQ */
diff --git a/apps/settings.h b/apps/settings.h
index 5b876d3e67..60658f6857 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -266,6 +266,7 @@ struct system_status
{
int resume_index; /* index in playlist (-1 for no active resume) */
uint32_t resume_crc32; /* crc32 of the name of the file */
+ uint32_t resume_elapsed; /* elapsed time in last file */
uint32_t resume_offset; /* byte offset in mp3 file */
int runtime; /* current runtime since last charge */
int topruntime; /* top known runtime */
@@ -282,6 +283,7 @@ struct system_status
#ifdef HAVE_LCD_BITMAP
int font_id[NB_SCREENS]; /* font id of the settings font for each screen */
#endif
+
};
struct user_settings
diff --git a/apps/settings_list.c b/apps/settings_list.c
index 39258dff8f..1ef9c62bf0 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -818,6 +818,7 @@ const struct settings_list settings[] = {
OFFON_SETTING(0, playlist_shuffle, LANG_SHUFFLE, false, "shuffle", NULL),
SYSTEM_SETTING(NVRAM(4), resume_index, -1),
SYSTEM_SETTING(NVRAM(4), resume_crc32, -1),
+ SYSTEM_SETTING(NVRAM(4), resume_elapsed, -1),
SYSTEM_SETTING(NVRAM(4), resume_offset, -1),
CHOICE_SETTING(0, repeat_mode, LANG_REPEAT, REPEAT_OFF, "repeat",
"off,all,one,shuffle"
diff --git a/apps/settings_list.h b/apps/settings_list.h
index 66b20ca6ca..2e63220da1 100644
--- a/apps/settings_list.h
+++ b/apps/settings_list.h
@@ -142,7 +142,7 @@ struct custom_setting {
#define F_NVRAM_BYTES_MASK 0xE0000 /*0-4 bytes can be stored */
#define F_NVRAM_MASK_SHIFT 17
-#define NVRAM_CONFIG_VERSION 7
+#define NVRAM_CONFIG_VERSION 8
/* Above define should be bumped if
- a new NVRAM setting is added between 2 other NVRAM settings
- number of bytes for a NVRAM setting is changed
diff --git a/apps/tagcache.c b/apps/tagcache.c
index 07d8d1d7a2..3ce0247188 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -130,7 +130,7 @@ static long tempbuf_pos;
static const char *tags_str[] = { "artist", "album", "genre", "title",
"filename", "composer", "comment", "albumartist", "grouping", "year",
"discnumber", "tracknumber", "bitrate", "length", "playcount", "rating",
- "playtime", "lastplayed", "commitid", "mtime", "lastoffset" };
+ "playtime", "lastplayed", "commitid", "mtime", "lastelapsed", "lastoffset" };
/* Status information of the tagcache. */
static struct tagcache_stat tc_stat;
@@ -196,7 +196,7 @@ static const char * const tagfile_entry_ec = "ll";
/**
Note: This should be (1 + TAG_COUNT) amount of l's.
*/
-static const char * const index_entry_ec = "llllllllllllllllllllll";
+static const char * const index_entry_ec = "lllllllllllllllllllllll";
static const char * const tagcache_header_ec = "lll";
static const char * const master_header_ec = "llllll";
@@ -1752,6 +1752,10 @@ bool tagcache_fill_tags(struct mp3entry *id3, const char *filename)
#if CONFIG_CODEC == SWCODEC
if (global_settings.autoresume_enable)
{
+ id3->elapsed = get_tag_numeric(entry, tag_lastelapsed, idx_id);
+ logf("tagcache_fill_tags: Set elapsed for %s to %lX\n",
+ id3->title, id3->elapsed);
+
id3->offset = get_tag_numeric(entry, tag_lastoffset, idx_id);
logf("tagcache_fill_tags: Set offset for %s to %lX\n",
id3->title, id3->offset);
@@ -2348,6 +2352,7 @@ static bool build_numeric_indices(struct tagcache_header *h, int tmpfd)
tmpdb_copy_tag(tag_playtime);
tmpdb_copy_tag(tag_lastplayed);
tmpdb_copy_tag(tag_commitid);
+ tmpdb_copy_tag(tag_lastelapsed);
tmpdb_copy_tag(tag_lastoffset);
/* Avoid processing this entry again. */
@@ -3419,7 +3424,8 @@ static int parse_changelog_line(int line_n, char *buf, void *parameters)
int idx_id;
long masterfd = (long)parameters;
const int import_tags[] = { tag_playcount, tag_rating, tag_playtime,
- tag_lastplayed, tag_commitid, tag_lastoffset };
+ tag_lastplayed, tag_commitid, tag_lastelapsed,
+ tag_lastoffset };
int i;
(void)line_n;
diff --git a/apps/tagcache.h b/apps/tagcache.h
index dbe1c92d39..e358cc26e0 100644
--- a/apps/tagcache.h
+++ b/apps/tagcache.h
@@ -33,7 +33,8 @@
enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title,
tag_filename, tag_composer, tag_comment, tag_albumartist, tag_grouping, tag_year,
tag_discnumber, tag_tracknumber, tag_bitrate, tag_length, tag_playcount, tag_rating,
- tag_playtime, tag_lastplayed, tag_commitid, tag_mtime, tag_lastoffset,
+ tag_playtime, tag_lastplayed, tag_commitid, tag_mtime, tag_lastelapsed,
+ tag_lastoffset,
/* Real tags end here, count them. */
TAG_COUNT,
/* Virtual tags */
@@ -51,7 +52,7 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title,
#define IDX_BUF_DEPTH 64
/* Tag Cache Header version 'TCHxx'. Increment when changing internal structures. */
-#define TAGCACHE_MAGIC 0x5443480e
+#define TAGCACHE_MAGIC 0x5443480f
/* Dump store/restore header version 'TCSxx'. */
#define TAGCACHE_STATEFILE_MAGIC 0x54435301
@@ -107,10 +108,11 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title,
(1LU << tag_tracknumber) | (1LU << tag_length) | (1LU << tag_bitrate) | \
(1LU << tag_playcount) | (1LU << tag_rating) | (1LU << tag_playtime) | \
(1LU << tag_lastplayed) | (1LU << tag_commitid) | (1LU << tag_mtime) | \
- (1LU << tag_lastoffset) | (1LU << tag_virt_basename) | \
- (1LU << tag_virt_length_min) | (1LU << tag_virt_length_sec) | \
- (1LU << tag_virt_playtime_min) | (1LU << tag_virt_playtime_sec) | \
- (1LU << tag_virt_entryage) | (1LU << tag_virt_autoscore))
+ (1LU << tag_lastelapsed) | (1LU << tag_lastoffset) | \
+ (1LU << tag_virt_basename) | (1LU << tag_virt_length_min) | \
+ (1LU << tag_virt_length_sec) | (1LU << tag_virt_playtime_min) | \
+ (1LU << tag_virt_playtime_sec) | (1LU << tag_virt_entryage) | \
+ (1LU << tag_virt_autoscore))
#define TAGCACHE_IS_NUMERIC(tag) (BIT_N(tag) & TAGCACHE_NUMERIC_TAGS)
diff --git a/apps/tagtree.c b/apps/tagtree.c
index 9eef38b5e6..ff364ec5e4 100644
--- a/apps/tagtree.c
+++ b/apps/tagtree.c
@@ -330,6 +330,7 @@ static int get_tag(int *tag)
{"playcount", tag_playcount},
{"rating", tag_rating},
{"lastplayed", tag_lastplayed},
+ {"lastelapsed", tag_lastelapsed},
{"lastoffset", tag_lastoffset},
{"commitid", tag_commitid},
{"entryage", tag_virt_entryage},
@@ -841,8 +842,16 @@ static void tagtree_buffer_event(void *data)
#if CONFIG_CODEC == SWCODEC
if (autoresume)
{
- /* Load current file resume offset if not already defined (by
+ /* Load current file resume info if not already defined (by
another resume mechanism) */
+ if (id3->elapsed == 0)
+ {
+ id3->elapsed = tagcache_get_numeric(&tcs, tag_lastelapsed);
+
+ logf("tagtree_buffer_event: Set elapsed for %s to %lX\n",
+ str_or_empty(id3->title), id3->elapsed);
+ }
+
if (id3->offset == 0)
{
id3->offset = tagcache_get_numeric(&tcs, tag_lastoffset);
@@ -940,12 +949,13 @@ static void tagtree_track_finish_event(void *data)
#if CONFIG_CODEC == SWCODEC
if (autoresume)
{
+ unsigned long elapsed = auto_skip ? 0 : id3->elapsed;
unsigned long offset = auto_skip ? 0 : id3->offset;
-
+ tagcache_update_numeric(tagcache_idx, tag_lastelapsed, elapsed);
tagcache_update_numeric(tagcache_idx, tag_lastoffset, offset);
- logf("tagtree_track_finish_event: Save offset for %s: %lX",
- str_or_empty(id3->title), offset);
+ logf("tagtree_track_finish_event: Save resume for %s: %lX %lX",
+ str_or_empty(id3->title), elapsed, offset);
}
#endif
}
@@ -2034,7 +2044,7 @@ static int tagtree_play_folder(struct tree_context* c)
c->selected_item = 0;
gui_synclist_select_item(&tree_lists, c->selected_item);
- playlist_start(c->selected_item,0);
+ playlist_start(c->selected_item, 0, 0);
playlist_get_current()->num_inserted_tracks = 0; /* make warn on playlist erase work */
return 0;
}
diff --git a/apps/tree.c b/apps/tree.c
index cc080ac7fa..f72774fe1e 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -1052,8 +1052,8 @@ void tree_mem_init(void)
tree_get_filetypes(&filetypes, &filetypes_count);
}
-bool bookmark_play(char *resume_file, int index, int offset, int seed,
- char *filename)
+bool bookmark_play(char *resume_file, int index, unsigned long elapsed,
+ unsigned long offset, int seed, char *filename)
{
int i;
char* suffix = strrchr(resume_file, '.');
@@ -1082,7 +1082,7 @@ bool bookmark_play(char *resume_file, int index, int offset, int seed,
{
if (global_settings.playlist_shuffle)
playlist_shuffle(seed, -1);
- playlist_start(index,offset);
+ playlist_start(index, elapsed, offset);
started = true;
}
*slash='/';
@@ -1133,7 +1133,7 @@ bool bookmark_play(char *resume_file, int index, int offset, int seed,
else
return false;
}
- playlist_start(index,offset);
+ playlist_start(index, elapsed, offset);
started = true;
}
}
diff --git a/apps/tree.h b/apps/tree.h
index 70494f8a88..1601447b58 100644
--- a/apps/tree.h
+++ b/apps/tree.h
@@ -139,8 +139,8 @@ struct tree_context* tree_get_context(void);
void tree_flush(void);
void tree_restore(void);
-bool bookmark_play(char* resume_file, int index, int offset, int seed,
- char *filename);
+bool bookmark_play(char* resume_file, int index, unsigned long elapsed,
+ unsigned long offset, int seed, char *filename);
extern struct gui_synclist tree_lists;
#endif