From 7141ff45133c9c669e9a0769a6c13e05cbe0595c Mon Sep 17 00:00:00 2001 From: Michael Hohmuth Date: Tue, 8 Feb 2011 20:31:35 +0000 Subject: [PATCH] Add option to resume next track on automatic track change Move autoresume setting into its own menu. Add option to customize which tracks should be resumed on automatic track change. Tracks can be selected based on their their file location or genre tag (comma-separated list of filename / genre substrings). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29251 a1c6a512-1295-4272-9138-f99709370657 --- apps/lang/english.lang | 28 +++++++++++++ apps/menus/settings_menu.c | 86 ++++++++++++++++++++++++++------------ apps/metadata.c | 47 +++++++++++++++++++++ apps/metadata.h | 7 ++++ apps/playback.c | 9 +++- apps/settings.h | 7 ++++ apps/settings_list.c | 9 ++++ 7 files changed, 165 insertions(+), 28 deletions(-) diff --git a/apps/lang/english.lang b/apps/lang/english.lang index dd8ed84caf..7da2cc2959 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -12716,3 +12716,31 @@ *: "Automatic resume" + + id: LANG_AUTORESUME_AUTOMATIC + desc: resume on automatic track change + user: core + + *: "Resume on automatic track change" + + + *: "Resume on automatic track change" + + + *: "Resume on automatic track change" + + + + id: LANG_AUTORESUME_CUSTOM + desc: enable customization of resume on automatic track change + user: core + + *: "Custom path/genre substrings (comma-separated)" + + + *: "Custom path/genre substrings (comma-separated)" + + + *: "Custom path/genre substrings (comma-separated)" + + diff --git a/apps/menus/settings_menu.c b/apps/menus/settings_menu.c index ce03e1a646..363792870d 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" @@ -367,6 +368,64 @@ MAKE_MENU(bookmark_settings_menu, ID2P(LANG_BOOKMARK_SETTINGS), 0, /* BOOKMARK MENU */ /***********************************/ +/***********************************/ +/* AUTORESUME MENU */ +#ifdef HAVE_TAGCACHE +#if CONFIG_CODEC == SWCODEC + +static int autoresume_callback(int action, const struct menu_item_ex *this_item) +{ + (void)this_item; + + if (action == ACTION_EXIT_MENUITEM /* on exit */ + && global_settings.autoresume_enable + && !tagcache_is_usable()) + { + static const char *lines[] = {ID2P(LANG_TAGCACHE_BUSY), + ID2P(LANG_TAGCACHE_FORCE_UPDATE)}; + static const struct text_message message = {lines, 2}; + + if (gui_syncyesno_run(&message, NULL, NULL) == YESNO_YES) + tagcache_rebuild_with_splash(); + } + return action; +} + +static int autoresume_nexttrack_callback(int action, + const struct menu_item_ex *this_item) +{ + (void)this_item; + static int oldval = 0; + switch (action) + { + case ACTION_ENTER_MENUITEM: + oldval = global_settings.autoresume_automatic; + break; + case ACTION_EXIT_MENUITEM: + if (global_settings.autoresume_automatic == AUTORESUME_NEXTTRACK_CUSTOM + && kbd_input ((char*) &global_settings.autoresume_strpat, + MAX_PATHNAME+1) < 0) + { + global_settings.autoresume_automatic = oldval; + } + } + return action; +} + +MENUITEM_SETTING(autoresume_enable, &global_settings.autoresume_enable, + autoresume_callback); +MENUITEM_SETTING(autoresume_automatic, &global_settings.autoresume_automatic, + autoresume_nexttrack_callback); + +MAKE_MENU(autoresume_menu, ID2P(LANG_AUTORESUME), + 0, Icon_NOICON, + &autoresume_enable, &autoresume_automatic); + +#endif /* CONFIG_CODEC == SWCODEC */ +#endif /* HAVE_TAGCACHE */ +/* AUTORESUME MENU */ +/***********************************/ + /***********************************/ /* VOICE MENU */ static int talk_callback(int action,const struct menu_item_ex *this_item); @@ -425,31 +484,6 @@ MAKE_MENU(hotkey_menu, ID2P(LANG_HOTKEY), 0, Icon_NOICON, /***********************************/ /* SETTINGS MENU */ -#ifdef HAVE_TAGCACHE -#if CONFIG_CODEC == SWCODEC -static int autoresume_callback(int action, const struct menu_item_ex *this_item) -{ - (void)this_item; - - if (action == ACTION_EXIT_MENUITEM /* on exit */ - && global_settings.autoresume_enable - && !tagcache_is_usable()) - { - static const char *lines[] = {ID2P(LANG_TAGCACHE_BUSY), - ID2P(LANG_TAGCACHE_FORCE_UPDATE)}; - static const struct text_message message = {lines, 2}; - - if (gui_syncyesno_run(&message, NULL, NULL) == YESNO_YES) - tagcache_rebuild_with_splash(); - } - return action; -} - -MENUITEM_SETTING(autoresume_enable, &global_settings.autoresume_enable, - autoresume_callback); -#endif -#endif - static struct browse_folder_info langs = { LANG_DIR, SHOW_LNG }; MENUITEM_FUNCTION(browse_langs, MENU_FUNC_USEPARAM, ID2P(LANG_LANGUAGE), @@ -465,7 +499,7 @@ MAKE_MENU(settings_menu_item, ID2P(LANG_GENERAL_SETTINGS), 0, &bookmark_settings_menu, #ifdef HAVE_TAGCACHE #if CONFIG_CODEC == SWCODEC - &autoresume_enable, + &autoresume_menu, #endif #endif &browse_langs, &voice_settings_menu, diff --git a/apps/metadata.c b/apps/metadata.c index 47c0e7449b..da20a0df2b 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" @@ -425,3 +426,49 @@ void copy_mp3entry(struct mp3entry *dest, const struct mp3entry *orig) memcpy(dest, orig, sizeof(struct mp3entry)); adjust_mp3entry(dest, dest, orig); } + +#ifdef HAVE_TAGCACHE +#if CONFIG_CODEC == SWCODEC + +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; + + strcpy(search, global_settings.autoresume_strpat); + + for (substr = strtok_r(search, ",", &saveptr); + substr; + substr = strtok_r(NULL, ",", &saveptr)) + { + if (id3->path && strcasestr(id3->path, substr)) + goto out; + 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 /* SWCODEC */ +#endif /* HAVE_TAGCACHE */ diff --git a/apps/metadata.h b/apps/metadata.h index 3831062418..b99d4d09d6 100644 --- a/apps/metadata.h +++ b/apps/metadata.h @@ -255,6 +255,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; @@ -287,10 +289,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 e33a4ac507..fe7b74893a 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -1002,8 +1002,13 @@ static void audio_update_trackinfo(void) thistrack_id3->elapsed = 0; #ifdef HAVE_TAGCACHE - /* Resume all manually selected tracks if so configured */ - resume = global_settings.autoresume_enable && !automatic_skip; + /* Ignoring resume position for automatic track change if so configured */ + resume = global_settings.autoresume_enable && + (!automatic_skip /* Resume all manually selected tracks */ + || global_settings.autoresume_automatic == AUTORESUME_NEXTTRACK_ALWAYS + || (global_settings.autoresume_automatic != AUTORESUME_NEXTTRACK_NEVER + /* Not never resume? */ + && autoresumable(thistrack_id3))); /* Pass Resume filter? */ #endif if (!resume) diff --git a/apps/settings.h b/apps/settings.h index 131ff181dd..ae32a65bc6 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -125,6 +125,10 @@ enum { SHOW_PATH_OFF = 0, SHOW_PATH_CURRENT, SHOW_PATH_FULL }; /* scrollbar visibility/position */ enum { SCROLLBAR_OFF = 0, SCROLLBAR_LEFT, SCROLLBAR_RIGHT }; +/* autoresume settings */ +enum { AUTORESUME_NEXTTRACK_NEVER = 0, AUTORESUME_NEXTTRACK_ALWAYS, + AUTORESUME_NEXTTRACK_CUSTOM}; + /* Alarm settings */ #ifdef HAVE_RTC_ALARM enum { ALARM_START_WPS = 0, @@ -577,6 +581,9 @@ struct user_settings #endif bool tagcache_autoupdate; /* automatically keep tagcache in sync? */ bool autoresume_enable; /* enable auto-resume feature? */ + int autoresume_automatic; /* resume next track? 0=never, 1=always, + 2=custom */ + unsigned char autoresume_strpat[MAX_PATHNAME+1]; /* comma-separated list */ bool runtimedb; /* runtime database active? */ #endif /* HAVE_TAGCACHE */ diff --git a/apps/settings_list.c b/apps/settings_list.c index 0521d4fb90..75e989eb10 100644 --- a/apps/settings_list.c +++ b/apps/settings_list.c @@ -1261,6 +1261,15 @@ const struct settings_list settings[] = { BOOL_SETTING(0, autoresume_enable, LANG_AUTORESUME, false, "autoresume enable", off_on, LANG_SET_BOOL_YES, LANG_SET_BOOL_NO, NULL), + CHOICE_SETTING(0, autoresume_automatic, LANG_AUTORESUME_AUTOMATIC, + AUTORESUME_NEXTTRACK_NEVER, + "autoresume next track", "never,all,custom", + NULL, 3, + ID2P(LANG_SET_BOOL_NO), + ID2P(LANG_ALWAYS), + ID2P(LANG_AUTORESUME_CUSTOM)), + TEXT_SETTING(0, autoresume_strpat, "autoresume next track patterns", + "podcast", NULL, NULL), #endif OFFON_SETTING(0, runtimedb, LANG_RUNTIMEDB_ACTIVE, false,