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
This commit is contained in:
Michael Hohmuth 2011-02-08 20:31:35 +00:00
parent 4844142e16
commit 7141ff4513
7 changed files with 165 additions and 28 deletions

View file

@ -12716,3 +12716,31 @@
*: "Automatic resume"
</voice>
</phrase>
<phrase>
id: LANG_AUTORESUME_AUTOMATIC
desc: resume on automatic track change
user: core
<source>
*: "Resume on automatic track change"
</source>
<dest>
*: "Resume on automatic track change"
</dest>
<voice>
*: "Resume on automatic track change"
</voice>
</phrase>
<phrase>
id: LANG_AUTORESUME_CUSTOM
desc: enable customization of resume on automatic track change
user: core
<source>
*: "Custom path/genre substrings (comma-separated)"
</source>
<dest>
*: "Custom path/genre substrings (comma-separated)"
</dest>
<voice>
*: "Custom path/genre substrings (comma-separated)"
</voice>
</phrase>

View file

@ -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,

View file

@ -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 */

View file

@ -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

View file

@ -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)

View file

@ -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 */

View file

@ -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,