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