Add option to customize which tracks should be considered as
autoresumable.
Tracks can be selected for autoresume based on their file location
(comma-separated list of filename substrings) or their genre tag
(comma-separated list of genre substrings).
---
apps/lang/english.lang | 84 ++++++++++++++++++++++++++++++++++++++++++++
apps/menus/settings_menu.c | 22 +++++++++++-
apps/metadata.c | 56 +++++++++++++++++++++++++++++
apps/metadata.h | 7 ++++
apps/playback.c | 1 +
apps/settings.h | 3 ++
apps/settings_list.c | 11 +++++-
apps/tagtree.c | 2 +-
8 files changed, 182 insertions(+), 4 deletions(-)
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 1a13000..e932a54 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -12737,3 +12737,87 @@
*: "Resume on automatic track change"
+
+ id: LANG_AUTORESUME_ALL_RESUMABLE
+ desc: autoresume: all resumable tracks
+ user: core
+
+ *: "All resumable tracks"
+
+
+ *: "All resumable tracks"
+
+
+ *: "All resumable tracks"
+
+
+
+ id: LANG_AUTORESUME_CUSTOM_MENU
+ desc: custom resume filter menu
+ user: core
+
+ *: "Resumable tracks"
+
+
+ *: "Resumable tracks"
+
+
+ *: "Resumable tracks"
+
+
+
+ id: LANG_AUTORESUME_CUSTOM
+ desc: enable custom resume filter (based on filename/genre tag)?
+ user: core
+
+ *: "Enable customization"
+
+
+ *: "Enable customization"
+
+
+ *: "Enable customization"
+
+
+
+ id: LANG_AUTORESUME_CUSTOM_NO
+ desc: enable custom resume filter (based on filename/genre tag)?
+ user: core
+
+ *: "No (resume all tracks)"
+
+
+ *: "No (resume all tracks)"
+
+
+ *: "No (resume all tracks)"
+
+
+
+ id: LANG_AUTORESUME_PATHSUB
+ desc: custom resume filter: filename
+ user: core
+
+ *: "Path substrings (comma-separated)"
+
+
+ *: "Path substrings (comma-separated)"
+
+
+ *: "Path substrings (comma-separated)"
+
+
+
+ id: LANG_AUTORESUME_TAGSUB
+ desc: custom resume filter: genre tag
+ user: core
+
+ *: "Genre tag substrings (comma-separated)"
+
+
+ *: "Genre tag substrings (comma-separated)"
+
+
+ *: "Genre tag substrings (comma-separated)"
+
+
diff --git a/apps/menus/settings_menu.c b/apps/menus/settings_menu.c
index 2ceeb28..b783155 100644
--- a/apps/menus/settings_menu.c
+++ b/apps/menus/settings_menu.c
@@ -28,6 +28,7 @@
#include "action.h"
#include "settings.h"
#include "menu.h"
+#include "keyboard.h"
#include "sound_menu.h"
#include "exported_menus.h"
#include "tree.h"
@@ -370,13 +371,32 @@ MAKE_MENU(bookmark_settings_menu, ID2P(LANG_BOOKMARK_SETTINGS), 0,
/* AUTORESUME MENU */
#ifdef HAVE_TAGCACHE
+static void edit_name_buf(char *textbuf)
+{
+ kbd_input (textbuf, MAX_PATHNAME+1);
+}
+
MENUITEM_SETTING(autoresume_enable, &global_settings.autoresume_enable, NULL);
MENUITEM_SETTING(autoresume_automatic, &global_settings.autoresume_automatic,
NULL);
+MENUITEM_SETTING(autoresume_custom, &global_settings.autoresume_custom, NULL);
+MENUITEM_FUNCTION(autoresume_pathsub, MENU_FUNC_USEPARAM,
+ ID2P(LANG_AUTORESUME_PATHSUB),
+ edit_name_buf, &global_settings.autoresume_pathsub, NULL,
+ Icon_NOICON);
+MENUITEM_FUNCTION(autoresume_tagsub, MENU_FUNC_USEPARAM,
+ ID2P(LANG_AUTORESUME_TAGSUB),
+ edit_name_buf, &global_settings.autoresume_tagsub, NULL,
+ Icon_NOICON);
+
+MAKE_MENU(autoresume_custom_menu, ID2P(LANG_AUTORESUME_CUSTOM_MENU),
+ 0, Icon_NOICON,
+ &autoresume_custom, &autoresume_pathsub, &autoresume_tagsub);
+
MAKE_MENU(autoresume_menu, ID2P(LANG_AUTORESUME),
0, Icon_NOICON,
- &autoresume_enable, &autoresume_automatic);
+ &autoresume_enable, &autoresume_custom_menu, &autoresume_automatic);
#endif /* HAVE_TAGCACHE */
/* AUTORESUME MENU */
diff --git a/apps/metadata.c b/apps/metadata.c
index 79ef7eb..9f61783 100644
--- a/apps/metadata.c
+++ b/apps/metadata.c
@@ -25,6 +25,7 @@
#include "debug.h"
#include "logf.h"
+#include "settings.h"
#include "cuesheet.h"
#include "metadata.h"
@@ -419,3 +420,58 @@ void copy_mp3entry(struct mp3entry *dest, const struct mp3entry *orig)
memcpy(dest, orig, sizeof(struct mp3entry));
adjust_mp3entry(dest, dest, orig);
}
+
+#ifdef HAVE_TAGCACHE
+
+enum { AUTORESUMABLE_UNKNOWN = 0, AUTORESUMABLE_TRUE, AUTORESUMABLE_FALSE };
+
+bool autoresumable(struct mp3entry *id3)
+{
+ unsigned char search[MAX_PATHNAME+1];
+ char *saveptr, *substr;
+ bool is_resumable;
+
+ if (id3->autoresumable) /* result cached? */
+ return id3->autoresumable == AUTORESUMABLE_TRUE;
+
+ is_resumable = true;
+
+ if (! global_settings.autoresume_custom)
+ goto out;
+
+ strcpy(search, global_settings.autoresume_pathsub);
+
+ for (substr = strtok_r(search, ",", &saveptr);
+ substr;
+ substr = strtok_r(NULL, ",", &saveptr))
+ {
+ if (id3->path && strcasestr(id3->path, substr))
+ goto out;
+ }
+
+ strcpy(search, global_settings.autoresume_tagsub);
+
+ for (substr = strtok_r(search, ",", &saveptr);
+ substr;
+ substr = strtok_r(NULL, ",", &saveptr))
+ {
+ if (id3->genre_string && strcasestr(id3->genre_string, substr))
+ goto out;
+ }
+
+ is_resumable = false;
+
+ out:
+ /* cache result */
+ id3->autoresumable =
+ is_resumable ? AUTORESUMABLE_TRUE : AUTORESUMABLE_FALSE;
+
+ logf("autoresumable: %s with genre %s is%s resumable",
+ id3->path,
+ id3->genre_string ? id3->genre_string : "(NULL)",
+ is_resumable ? "" : " not");
+
+ return is_resumable;
+}
+
+#endif /* HAVE_TAGCACHE */
diff --git a/apps/metadata.h b/apps/metadata.h
index 8c7188d..13310fc 100644
--- a/apps/metadata.h
+++ b/apps/metadata.h
@@ -247,6 +247,8 @@ struct mp3entry {
int index; /* playlist index */
#ifdef HAVE_TAGCACHE
+ unsigned char autoresumable; /* caches result of autoresumable() */
+
/* runtime database fields */
long tagcache_idx; /* 0=invalid, otherwise idx+1 */
int rating;
@@ -279,10 +281,15 @@ bool get_metadata(struct mp3entry* id3, int fd, const char* trackname);
bool mp3info(struct mp3entry *entry, const char *filename);
void adjust_mp3entry(struct mp3entry *entry, void *dest, const void *orig);
void copy_mp3entry(struct mp3entry *dest, const struct mp3entry *orig);
+
#if CONFIG_CODEC == SWCODEC
void strip_tags(int handle_id);
#endif
+#ifdef HAVE_TAGCACHE
+bool autoresumable(struct mp3entry *id3);
+#endif
+
#endif
diff --git a/apps/playback.c b/apps/playback.c
index 1e515d5..12c6abe 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -1006,6 +1006,7 @@ static void audio_update_trackinfo(void)
resume = global_settings.autoresume_enable &&
(!automatic_skip /* Resume all manually selected tracks */
|| (global_settings.autoresume_automatic >= 0 /* Not never resume? */
+ && autoresumable(thistrack_id3) /* Pass Resume filter? */
&& (global_settings.autoresume_automatic == 0 /* Always resume? */
|| thistrack_id3->length /* Long track? */
>= global_settings.autoresume_automatic * 60UL * 1000UL)));
diff --git a/apps/settings.h b/apps/settings.h
index 591a2c9..af6398f 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -579,6 +579,9 @@ struct user_settings
bool autoresume_enable; /* enable autoupdate feature? */
int autoresume_automatic; /* resume next track? -1=never,
0=always, other = if longer than .. min */
+ bool autoresume_custom; /* resume only for files matching file/tag below? */
+ unsigned char autoresume_pathsub[MAX_PATHNAME+1]; /* comma-separated list */
+ unsigned char autoresume_tagsub[MAX_PATHNAME+1]; /* dito */
bool runtimedb; /* runtime database active? */
#endif /* HAVE_TAGCACHE */
diff --git a/apps/settings_list.c b/apps/settings_list.c
index 34ca31e..01d1cde 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -341,7 +341,7 @@ static const char* formatter_autoresume_automatic(char *buffer,
if (val == -1)
return str(LANG_NEVER);
else if (val == 0)
- return str(LANG_ALWAYS);
+ return str(LANG_AUTORESUME_ALL_RESUMABLE);
else
snprintf(buffer, buffer_size, "%d min", val);
return buffer;
@@ -353,7 +353,7 @@ static int32_t getlang_autoresume_automatic(int value, int unit)
if (value == -1)
return LANG_NEVER;
else if (value == 0)
- return LANG_ALWAYS;
+ return LANG_AUTORESUME_ALL_RESUMABLE;
else
return TALK_ID(value, UNIT_MIN);
}
@@ -1293,6 +1293,13 @@ const struct settings_list settings[] = {
UNIT_MIN, formatter_autoresume_automatic,
getlang_autoresume_automatic, NULL,
8, -1,0,5,10,15,20,25,30),
+ BOOL_SETTING(0, autoresume_custom, LANG_AUTORESUME_CUSTOM, false,
+ "autoresume custom filter", off_on,
+ LANG_SET_BOOL_YES, LANG_AUTORESUME_CUSTOM_NO, NULL),
+ TEXT_SETTING(0, autoresume_pathsub, "autoresume path substring",
+ "podcast,audiobook", NULL, NULL),
+ TEXT_SETTING(0, autoresume_tagsub, "autoresume tag substring",
+ "podcast,audiobook", NULL, NULL),
OFFON_SETTING(0, runtimedb, LANG_RUNTIMEDB_ACTIVE, false,
"gather runtime data", NULL),
diff --git a/apps/tagtree.c b/apps/tagtree.c
index 53f12fa..50dcbce 100644
--- a/apps/tagtree.c
+++ b/apps/tagtree.c
@@ -758,7 +758,7 @@ static void tagtree_track_finish_event(void *data)
&& (automatic_skip || (id3->elapsed >= 15UL * 1000UL)))
{
unsigned long offset
- = automatic_skip ? 0 : id3->offset;
+ = automatic_skip || !autoresumable(id3) ? 0 : id3->offset;
tagcache_update_numeric(tagcache_idx, tag_lastoffset, offset);
--
1.7.1