summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/lang/english.lang28
-rw-r--r--apps/menus/settings_menu.c10
-rw-r--r--apps/playback.c40
-rw-r--r--apps/settings.h1
-rw-r--r--apps/settings_list.c3
-rw-r--r--apps/tagcache.c10
-rw-r--r--apps/tagcache.h5
-rw-r--r--apps/tagtree.c84
8 files changed, 150 insertions, 31 deletions
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index b2e54da8e9..0fad5bf5b0 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -12685,3 +12685,31 @@
*: "Filesize"
</voice>
</phrase>
+<phrase>
+ id: LANG_AUTORESUME_ENABLE
+ desc: resume settings menu
+ user: core
+ <source>
+ *: "Enable automatic resume"
+ </source>
+ <dest>
+ *: "Enable automatic resume"
+ </dest>
+ <voice>
+ *: "Enable automatic resume"
+ </voice>
+</phrase>
+<phrase>
+ id: LANG_AUTORESUME_ENABLE_YES
+ desc: resume settings menu
+ user: core
+ <source>
+ *: "Yes (requires initialized database)"
+ </source>
+ <dest>
+ *: "Yes (requires initialized database)"
+ </dest>
+ <voice>
+ *: "Yes (requires initialized database)"
+ </voice>
+</phrase>
diff --git a/apps/menus/settings_menu.c b/apps/menus/settings_menu.c
index 5de3a305f9..e609a4032e 100644
--- a/apps/menus/settings_menu.c
+++ b/apps/menus/settings_menu.c
@@ -424,6 +424,10 @@ MAKE_MENU(hotkey_menu, ID2P(LANG_HOTKEY), 0, Icon_NOICON,
/***********************************/
/* SETTINGS MENU */
+#ifdef HAVE_TAGCACHE
+MENUITEM_SETTING(autoresume_enable, &global_settings.autoresume_enable, NULL);
+#endif
+
static struct browse_folder_info langs = { LANG_DIR, SHOW_LNG };
MENUITEM_FUNCTION(browse_langs, MENU_FUNC_USEPARAM, ID2P(LANG_LANGUAGE),
@@ -436,7 +440,11 @@ MAKE_MENU(settings_menu_item, ID2P(LANG_GENERAL_SETTINGS), 0,
&tagcache_menu,
#endif
&display_menu, &system_menu,
- &bookmark_settings_menu, &browse_langs, &voice_settings_menu,
+ &bookmark_settings_menu,
+#ifdef HAVE_TAGCACHE
+ &autoresume_enable,
+#endif
+ &browse_langs, &voice_settings_menu,
#ifdef HAVE_HOTKEY
&hotkey_menu,
#endif
diff --git a/apps/playback.c b/apps/playback.c
index b18ba14e9f..e71e06b92c 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -992,13 +992,27 @@ long audio_filebufused(void)
/* Update track info after successful a codec track change */
static void audio_update_trackinfo(void)
{
+ bool resume = false;
+
/* Load the curent track's metadata into curtrack_id3 */
if (CUR_TI->id3_hid >= 0)
copy_mp3entry(thistrack_id3, bufgetid3(CUR_TI->id3_hid));
/* Reset current position */
thistrack_id3->elapsed = 0;
- thistrack_id3->offset = 0;
+
+#ifdef HAVE_TAGCACHE
+ /* Resume all manually selected tracks if so configured */
+ resume = global_settings.autoresume_enable && !automatic_skip;
+#endif
+
+ if (!resume)
+ {
+ thistrack_id3->offset = 0;
+ }
+
+ logf("audio_update_trackinfo: Set offset for %s to %lX\n",
+ thistrack_id3->title, thistrack_id3->offset);
/* Update the codec API */
ci.filesize = CUR_TI->filesize;
@@ -1210,6 +1224,9 @@ static bool audio_load_track(size_t offset, bool start_play)
{
copy_mp3entry(thistrack_id3, id3);
thistrack_id3->offset = offset;
+ logf("audio_load_track: set offset for %s to %lX\n",
+ thistrack_id3->title,
+ offset);
}
else
memset(thistrack_id3, 0, sizeof(struct mp3entry));
@@ -1415,8 +1432,14 @@ static void audio_finish_load_track(void)
return;
}
- /* All required data is now available for the codec. */
- tracks[track_widx].taginfo_ready = true;
+ /* All required data is now available for the codec -- unless the
+ autoresume feature is in effect. In the latter case, the codec
+ must wait until after PLAYBACK_EVENT_TRACK_BUFFER, which may
+ generate a resume position. */
+#ifdef HAVE_TAGCACHE
+ if (! global_settings.autoresume_enable)
+#endif
+ tracks[track_widx].taginfo_ready = true;
if (start_play)
{
@@ -1424,10 +1447,17 @@ static void audio_finish_load_track(void)
buf_request_buffer_handle(tracks[track_widx].audio_hid);
}
- track_widx = (track_widx + 1) & MAX_TRACK_MASK;
-
send_event(PLAYBACK_EVENT_TRACK_BUFFER, track_id3);
+#ifdef HAVE_TAGCACHE
+ /* In case the autoresume feature has been enabled, finally all
+ required data is available for the codec. */
+ if (global_settings.autoresume_enable)
+ tracks[track_widx].taginfo_ready = true;
+#endif
+
+ track_widx = (track_widx + 1) & MAX_TRACK_MASK;
+
/* load next track */
LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER");
queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
diff --git a/apps/settings.h b/apps/settings.h
index fac2c9634f..4c2875392b 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -576,6 +576,7 @@ struct user_settings
bool tagcache_ram; /* load tagcache to ram? */
#endif
bool tagcache_autoupdate; /* automatically keep tagcache in sync? */
+ bool autoresume_enable; /* enable autoupdate feature? */
bool runtimedb; /* runtime database active? */
#endif /* HAVE_TAGCACHE */
diff --git a/apps/settings_list.c b/apps/settings_list.c
index 80000ab23f..3da5f1db62 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -1257,6 +1257,9 @@ const struct settings_list settings[] = {
ID2P(LANG_RANDOM)),
#ifdef HAVE_TAGCACHE
+ BOOL_SETTING(0, autoresume_enable, LANG_AUTORESUME_ENABLE, false,
+ "autoresume enable", off_on,
+ LANG_AUTORESUME_ENABLE_YES, LANG_SET_BOOL_NO, NULL),
OFFON_SETTING(0, runtimedb, LANG_RUNTIMEDB_ACTIVE, false,
"gather runtime data", NULL),
#endif
diff --git a/apps/tagcache.c b/apps/tagcache.c
index 0831bab32d..1d90eee24b 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -195,7 +195,7 @@ static const char *tagfile_entry_ec = "ll";
/**
Note: This should be (1 + TAG_COUNT) amount of l's.
*/
-static const char *index_entry_ec = "lllllllllllllllllllll";
+static const char *index_entry_ec = "llllllllllllllllllllll";
static const char *tagcache_header_ec = "lll";
static const char *master_header_ec = "llllll";
@@ -1695,6 +1695,13 @@ bool tagcache_fill_tags(struct mp3entry *id3, const char *filename)
if (id3->bitrate == 0)
id3->bitrate = 1;
+ if (global_settings.autoresume_enable)
+ {
+ 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);
+ }
+
return true;
}
#endif
@@ -2315,6 +2322,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_lastoffset);
/* Avoid processing this entry again. */
idx.flag |= FLAG_RESURRECTED;
diff --git a/apps/tagcache.h b/apps/tagcache.h
index b52da76a0f..4fffccae2f 100644
--- a/apps/tagcache.h
+++ b/apps/tagcache.h
@@ -32,7 +32,7 @@
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_playtime, tag_lastplayed, tag_commitid, tag_mtime, tag_lastoffset,
/* Real tags end here, count them. */
TAG_COUNT,
/* Virtual tags */
@@ -50,7 +50,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 0x5443480d
+#define TAGCACHE_MAGIC 0x5443480e
/* How much to allocate extra space for ramcache. */
#define TAGCACHE_RESERVE 32768
@@ -103,6 +103,7 @@ 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_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))
diff --git a/apps/tagtree.c b/apps/tagtree.c
index 75caab01d4..8ebac0b3a5 100644
--- a/apps/tagtree.c
+++ b/apps/tagtree.c
@@ -53,6 +53,8 @@
#include "storage.h"
#include "dir.h"
+#define str_or_empty(x) (x ? x : "(NULL)")
+
#define FILE_SEARCH_INSTRUCTIONS ROCKBOX_DIR "/tagnavi.config"
static int tagtree_play_folder(struct tree_context* c);
@@ -168,6 +170,8 @@ static int current_entry_count;
static struct tree_context *tc;
+extern bool automatic_skip; /* Who initiated in-progress skip? (C/A-) */
+
static int get_token_str(char *buf, int size)
{
/* Find the start. */
@@ -239,6 +243,7 @@ static int get_tag(int *tag)
MATCH(tag, buf, "playcount", tag_playcount);
MATCH(tag, buf, "rating", tag_rating);
MATCH(tag, buf, "lastplayed", tag_lastplayed);
+ MATCH(tag, buf, "lastoffset", tag_lastoffset);
MATCH(tag, buf, "commitid", tag_commitid);
MATCH(tag, buf, "entryage", tag_virt_entryage);
MATCH(tag, buf, "autoscore", tag_virt_autoscore);
@@ -647,7 +652,7 @@ static void tagtree_buffer_event(void *data)
struct mp3entry *id3 = (struct mp3entry*)data;
/* Do not gather data unless proper setting has been enabled. */
- if (!global_settings.runtimedb)
+ if (!global_settings.runtimedb && !global_settings.autoresume_enable)
return;
logf("be:%s", id3->path);
@@ -661,12 +666,30 @@ static void tagtree_buffer_event(void *data)
return;
}
- id3->playcount = tagcache_get_numeric(&tcs, tag_playcount);
- if (!id3->rating)
- id3->rating = tagcache_get_numeric(&tcs, tag_rating);
- id3->lastplayed = tagcache_get_numeric(&tcs, tag_lastplayed);
- id3->score = tagcache_get_numeric(&tcs, tag_virt_autoscore) / 10;
- id3->playtime = tagcache_get_numeric(&tcs, tag_playtime);
+ if (global_settings.runtimedb)
+ {
+ id3->playcount = tagcache_get_numeric(&tcs, tag_playcount);
+ if (!id3->rating)
+ id3->rating = tagcache_get_numeric(&tcs, tag_rating);
+ id3->lastplayed = tagcache_get_numeric(&tcs, tag_lastplayed);
+ id3->score = tagcache_get_numeric(&tcs, tag_virt_autoscore) / 10;
+ id3->playtime = tagcache_get_numeric(&tcs, tag_playtime);
+
+ logf("-> %ld/%ld", id3->playcount, id3->playtime);
+ }
+
+ if (global_settings.autoresume_enable)
+ {
+ /* Load current file resume offset if not already defined (by
+ another resume mechanism) */
+ if (id3->offset == 0)
+ {
+ id3->offset = tagcache_get_numeric(&tcs, tag_lastoffset);
+
+ logf("tagtree_buffer_event: Set offset for %s to %lX\n",
+ str_or_empty(id3->title), id3->offset);
+ }
+ }
/* Store our tagcache index pointer. */
id3->tagcache_idx = tcs.idx_id+1;
@@ -676,16 +699,14 @@ static void tagtree_buffer_event(void *data)
static void tagtree_track_finish_event(void *data)
{
- long playcount;
- long playtime;
long lastplayed;
long tagcache_idx;
struct mp3entry *id3 = (struct mp3entry*)data;
/* Do not gather data unless proper setting has been enabled. */
- if (!global_settings.runtimedb)
+ if (!global_settings.runtimedb && !global_settings.autoresume_enable)
{
- logf("runtimedb gathering not enabled");
+ logf("runtimedb gathering and autoresume not enabled");
return;
}
@@ -704,7 +725,6 @@ static void tagtree_track_finish_event(void *data)
return;
}
- playcount = id3->playcount + 1;
lastplayed = tagcache_increase_serial();
if (lastplayed < 0)
{
@@ -712,17 +732,37 @@ static void tagtree_track_finish_event(void *data)
return;
}
- /* Ignore the last 15s (crossfade etc.) */
- playtime = id3->playtime + MIN(id3->length, id3->elapsed + 15 * 1000);
-
- logf("ube:%s", id3->path);
- logf("-> %ld/%ld", playcount, playtime);
- logf("-> %ld/%ld/%ld", id3->elapsed, id3->length, MIN(id3->length, id3->elapsed + 15 * 1000));
+ if (global_settings.runtimedb)
+ {
+ long playcount;
+ long playtime;
+
+ playcount = id3->playcount + 1;
+
+ /* Ignore the last 15s (crossfade etc.) */
+ playtime = id3->playtime + MIN(id3->length, id3->elapsed + 15 * 1000);
+
+ logf("ube:%s", id3->path);
+ logf("-> %ld/%ld", playcount, playtime);
+ logf("-> %ld/%ld/%ld", id3->elapsed, id3->length,
+ MIN(id3->length, id3->elapsed + 15 * 1000));
- /* Queue the updates to the tagcache system. */
- tagcache_update_numeric(tagcache_idx, tag_playcount, playcount);
- tagcache_update_numeric(tagcache_idx, tag_playtime, playtime);
- tagcache_update_numeric(tagcache_idx, tag_lastplayed, lastplayed);
+ /* Queue the updates to the tagcache system. */
+ tagcache_update_numeric(tagcache_idx, tag_playcount, playcount);
+ tagcache_update_numeric(tagcache_idx, tag_playtime, playtime);
+ tagcache_update_numeric(tagcache_idx, tag_lastplayed, lastplayed);
+ }
+
+ if (global_settings.autoresume_enable)
+ {
+ unsigned long offset
+ = automatic_skip ? 0 : id3->offset;
+
+ tagcache_update_numeric(tagcache_idx, tag_lastoffset, offset);
+
+ logf("tagtree_track_finish_event: Save offset for %s: %lX",
+ str_or_empty(id3->title), offset);
+ }
}
bool tagtree_export(void)