summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorNick Peskett <rockbox@peskett.co.uk>2012-03-19 09:56:38 +0000
committerNick Peskett <rockbox@peskett.co.uk>2012-03-19 11:49:55 +0100
commitbe10817e1c09d5a41710435cf6d58deb6dde9301 (patch)
tree4635fcb1ab51d2ef6dc1db28db045c369cf1abaf /apps
parent69978d7046cd7e537c5079a5e306d22621a1767a (diff)
downloadrockbox-be10817e1c09d5a41710435cf6d58deb6dde9301.tar.gz
rockbox-be10817e1c09d5a41710435cf6d58deb6dde9301.zip
Option to constrain get_next_dir() to directories below global_settings.start_directory.
When enabled, if the user has set "Start File Browser Here" (config.cfg: start directory) to anything other than root and "Auto-Change Directory" is set to "Yes" or "Random", the directory returned when an auto change is required will be constrained to the value of "start directory" or below. Change-Id: Iaab773868c4cab5a54f6ae67bdb22e84642a9e4b Reviewed-on: http://gerrit.rockbox.org/182 Reviewed-by: Nick Peskett <rockbox@peskett.co.uk> Tested-by: Nick Peskett <rockbox@peskett.co.uk>
Diffstat (limited to 'apps')
-rw-r--r--apps/lang/english.lang14
-rw-r--r--apps/menus/playback_menu.c4
-rw-r--r--apps/playback.c11
-rw-r--r--apps/playlist.c167
-rw-r--r--apps/plugins/random_folder_advance_config.c11
-rw-r--r--apps/settings.h2
-rw-r--r--apps/settings_list.c3
7 files changed, 144 insertions, 68 deletions
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 627fda8b12..d428bee232 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -12993,3 +12993,17 @@
*: "Restart Sleep Timer On Keypress"
</voice>
</phrase>
+<phrase>
+ id: LANG_CONSTRAIN_NEXT_FOLDER
+ desc: in settings_menu. Whether LANG_NEXT_FOLDER should be constrained to directories within LANG_SET_AS_START_DIR
+ user: core
+ <source>
+ *: "Constrain Auto-Change"
+ </source>
+ <dest>
+ *: "Constrain Auto-Change"
+ </dest>
+ <voice>
+ *: "Constrain Auto-Change"
+ </voice>
+</phrase>
diff --git a/apps/menus/playback_menu.c b/apps/menus/playback_menu.c
index d5b20d09f5..17b7e57d32 100644
--- a/apps/menus/playback_menu.c
+++ b/apps/menus/playback_menu.c
@@ -135,6 +135,8 @@ MENUITEM_SETTING(beep, &global_settings.beep ,NULL);
MENUITEM_SETTING(spdif_enable, &global_settings.spdif_enable, NULL);
#endif
MENUITEM_SETTING(next_folder, &global_settings.next_folder, NULL);
+MENUITEM_SETTING(constrain_next_folder,
+ &global_settings.constrain_next_folder, NULL);
static int audioscrobbler_callback(int action,const struct menu_item_ex *this_item)
{
(void)this_item;
@@ -205,7 +207,7 @@ MAKE_MENU(playback_settings,ID2P(LANG_PLAYBACK),0,
#ifdef HAVE_SPDIF_POWER
&spdif_enable,
#endif
- &next_folder, &audioscrobbler, &cuesheet
+ &next_folder, &constrain_next_folder, &audioscrobbler, &cuesheet
#ifdef HAVE_HEADPHONE_DETECTION
,&unplug_menu
#endif
diff --git a/apps/playback.c b/apps/playback.c
index 8fe43eb884..28f664357c 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -2644,8 +2644,17 @@ static void audio_on_skip(void)
skip_pending = TRACK_SKIP_NONE;
/* Update the playlist current track now */
- while (playlist_next(playlist_delta) < 0)
+ int pl_retval;
+ while ((pl_retval = playlist_next(playlist_delta)) < 0)
{
+ if (pl_retval < -1)
+ {
+ /* Some variety of fatal error while updating playlist */
+ filling = STATE_ENDED;
+ audio_stop_playback();
+ return;
+ }
+
/* Manual skip out of range (because the playlist wasn't updated
yet by us and so the check in audio_skip returned 'ok') - bring
back into range */
diff --git a/apps/playlist.c b/apps/playlist.c
index bf55671bf1..5b5f489cde 100644
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -175,7 +175,7 @@ static int compare(const void* p1, const void* p2);
static int get_filename(struct playlist_info* playlist, int index, int seek,
bool control_file, char *buf, int buf_length);
static int get_next_directory(char *dir);
-static int get_next_dir(char *dir, bool is_forward, bool recursion);
+static int get_next_dir(char *dir, bool is_forward);
static int get_previous_directory(char *dir);
static int check_subdir_for_music(char *dir, const char *subdir, bool recurse);
static int format_track_path(char *dest, char *src, int buf_length, int max,
@@ -608,32 +608,33 @@ static int create_and_play_dir(int direction, bool play_last)
else
res = get_previous_directory(dir);
- if (!res)
+ if (res < 0)
+ /* return the error encountered */
+ return res;
+
+ if (playlist_create(dir, NULL) != -1)
{
- if (playlist_create(dir, NULL) != -1)
- {
- ft_build_playlist(tree_get_context(), 0);
+ ft_build_playlist(tree_get_context(), 0);
- if (global_settings.playlist_shuffle)
- playlist_shuffle(current_tick, -1);
+ if (global_settings.playlist_shuffle)
+ playlist_shuffle(current_tick, -1);
- if (play_last && direction <= 0)
- index = current_playlist.amount - 1;
- else
- index = 0;
+ if (play_last && direction <= 0)
+ index = current_playlist.amount - 1;
+ else
+ index = 0;
#if (CONFIG_CODEC == SWCODEC)
- current_playlist.started = true;
+ current_playlist.started = true;
#else
- playlist_start(index, 0);
+ playlist_start(index, 0);
#endif
- }
-
- /* we've overwritten the dircache when getting the next/previous dir,
- so the tree browser context will need to be reloaded */
- reload_directory();
}
+ /* we've overwritten the dircache when getting the next/previous dir,
+ so the tree browser context will need to be reloaded */
+ reload_directory();
+
return index;
}
@@ -1435,18 +1436,18 @@ static int get_filename(struct playlist_info* playlist, int index, int seek,
}
static int get_next_directory(char *dir){
- return get_next_dir(dir,true,false);
+ return get_next_dir(dir, true);
}
static int get_previous_directory(char *dir){
- return get_next_dir(dir,false,false);
+ return get_next_dir(dir, false);
}
/*
* search through all the directories (starting with the current) to find
* one that has tracks to play
*/
-static int get_next_dir(char *dir, bool is_forward, bool recursion)
+static int get_next_dir(char *dir, bool is_forward)
{
struct playlist_info* playlist = &current_playlist;
int result = -1;
@@ -1454,6 +1455,27 @@ static int get_next_dir(char *dir, bool is_forward, bool recursion)
bool exit = false;
struct tree_context* tc = tree_get_context();
int saved_dirfilter = *(tc->dirfilter);
+ unsigned int base_len;
+
+ if (global_settings.constrain_next_folder)
+ {
+ /* constrain results to directories below user's start directory */
+ strcpy(dir, global_settings.start_directory);
+ base_len = strlen(dir);
+
+ /* strip any trailing slash from base directory */
+ if (base_len > 0 && dir[base_len - 1] == '/')
+ {
+ base_len--;
+ dir[base_len] = '\0';
+ }
+ }
+ else
+ {
+ /* start from root directory */
+ dir[0] = '\0';
+ base_len = 0;
+ }
/* process random folder advance */
if (global_settings.next_folder == FOLDER_ADVANCE_RANDOM)
@@ -1461,43 +1483,46 @@ static int get_next_dir(char *dir, bool is_forward, bool recursion)
int fd = open(ROCKBOX_DIR "/folder_advance_list.dat", O_RDONLY);
if (fd >= 0)
{
- char buffer[MAX_PATH];
int folder_count = 0;
- srand(current_tick);
- *(tc->dirfilter) = SHOW_MUSIC;
- tc->sort_dir = global_settings.sort_dir;
read(fd,&folder_count,sizeof(int));
- if (!folder_count)
- exit = true;
- while (!exit)
+ if (folder_count)
{
- int i = rand()%folder_count;
- lseek(fd,sizeof(int) + (MAX_PATH*i),SEEK_SET);
- read(fd,buffer,MAX_PATH);
- if (check_subdir_for_music(buffer, "", false) ==0)
- exit = true;
+ char buffer[MAX_PATH];
+ /* give up looking for a directory after we've had four
+ times as many tries as there are directories. */
+ unsigned long allowed_tries = folder_count * 4;
+ int i;
+ srand(current_tick);
+ *(tc->dirfilter) = SHOW_MUSIC;
+ tc->sort_dir = global_settings.sort_dir;
+ while (!exit && allowed_tries--)
+ {
+ i = rand() % folder_count;
+ lseek(fd, sizeof(int) + (MAX_PATH * i), SEEK_SET);
+ read(fd, buffer, MAX_PATH);
+ /* is the current dir within our base dir and has music? */
+ if ((base_len == 0 || !strncmp(buffer, dir, base_len))
+ && check_subdir_for_music(buffer, "", false) == 0)
+ exit = true;
+ }
+ close(fd);
+ *(tc->dirfilter) = saved_dirfilter;
+ tc->sort_dir = global_settings.sort_dir;
+ reload_directory();
+ if (exit)
+ {
+ strcpy(dir,buffer);
+ return 0;
+ }
}
- if (folder_count)
- strcpy(dir,buffer);
- close(fd);
- *(tc->dirfilter) = saved_dirfilter;
- tc->sort_dir = global_settings.sort_dir;
- reload_directory();
- return 0;
+ else
+ close(fd);
}
}
- /* not random folder advance (or random folder advance unavailable) */
- if (recursion)
- {
- /* start with root */
- dir[0] = '\0';
- }
- else
- {
- /* start with current directory */
+ /* if the current file is within our base dir, use its dir instead */
+ if (base_len == 0 || !strncmp(playlist->filename, dir, base_len))
strlcpy(dir, playlist->filename, playlist->dirlen);
- }
/* use the tree browser dircache to load files */
*(tc->dirfilter) = SHOW_ALL;
@@ -1546,7 +1571,7 @@ static int get_next_dir(char *dir, bool is_forward, bool recursion)
exit = true;
break;
}
-
+
if (files[i].attr & ATTR_DIRECTORY)
{
if (!start_dir)
@@ -1566,16 +1591,30 @@ static int get_next_dir(char *dir, bool is_forward, bool recursion)
if (!exit)
{
- /* move down to parent directory. current directory name is
- stored as the starting point for the search in parent */
- start_dir = strrchr(dir, '/');
- if (start_dir)
+ /* we've already descended to the base dir with nothing found,
+ check whether that contains music */
+ if (strlen(dir) <= base_len)
{
- *start_dir = '\0';
- start_dir++;
+ result = check_subdir_for_music(dir, "", true);
+ if (result == -1)
+ /* there's no music files in the base directory,
+ treat as a fatal error */
+ result = -2;
+ break;
}
else
- break;
+ {
+ /* move down to parent directory. current directory name is
+ stored as the starting point for the search in parent */
+ start_dir = strrchr(dir, '/');
+ if (start_dir)
+ {
+ *start_dir = '\0';
+ start_dir++;
+ }
+ else
+ break;
+ }
}
}
@@ -1583,11 +1622,6 @@ static int get_next_dir(char *dir, bool is_forward, bool recursion)
*(tc->dirfilter) = saved_dirfilter;
tc->sort_dir = global_settings.sort_dir;
- /* special case if nothing found: try start searching again from root */
- if (result == -1 && !recursion){
- result = get_next_dir(dir, is_forward, true);
- }
-
return result;
}
@@ -1606,7 +1640,12 @@ static int check_subdir_for_music(char *dir, const char *subdir, bool recurse)
bool has_subdir = false;
struct tree_context* tc = tree_get_context();
- snprintf(dir+dirlen, MAX_PATH-dirlen, "/%s", subdir);
+ snprintf(
+ dir + dirlen, MAX_PATH - dirlen,
+ /* only add a trailing slash if we need one */
+ dirlen && dir[dirlen - 1] == '/' ? "%s" : "/%s",
+ subdir
+ );
if (ft_load(tc, dir) < 0)
{
diff --git a/apps/plugins/random_folder_advance_config.c b/apps/plugins/random_folder_advance_config.c
index f459aa0776..7f6018df4e 100644
--- a/apps/plugins/random_folder_advance_config.c
+++ b/apps/plugins/random_folder_advance_config.c
@@ -65,8 +65,15 @@ static void traversedir(char* location, char* name)
bool check = false;
int i;
- rb->snprintf(fullpath, sizeof(fullpath), "%s/%s", location, name);
- dir = rb->opendir(fullpath);
+ /* behave differently if we're at root to avoid
+ duplication of the initial slash later on */
+ if (location[0] == '\0' && name[0] == '\0') {
+ rb->strcpy(fullpath, "");
+ dir = rb->opendir("/");
+ } else {
+ rb->snprintf(fullpath, sizeof(fullpath), "%s/%s", location, name);
+ dir = rb->opendir(fullpath);
+ }
if (dir) {
entry = rb->readdir(dir);
while (entry) {
diff --git a/apps/settings.h b/apps/settings.h
index 012e289d0c..777c7dbefe 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -590,6 +590,8 @@ struct user_settings
/* playlist/playback settings */
int repeat_mode; /* 0=off 1=repeat all 2=repeat one 3=shuffle 4=ab */
int next_folder; /* move to next folder */
+ bool constrain_next_folder; /* whether next_folder is constrained to
+ directories within start_directory */
int recursive_dir_insert; /* should directories be inserted recursively */
bool fade_on_stop; /* fade on pause/unpause/stop */
bool playlist_shuffle;
diff --git a/apps/settings_list.c b/apps/settings_list.c
index 2258582a78..5acebef2a5 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -1328,6 +1328,9 @@ const struct settings_list settings[] = {
"folder navigation", "off,on,random",NULL ,3,
ID2P(LANG_SET_BOOL_NO), ID2P(LANG_SET_BOOL_YES),
ID2P(LANG_RANDOM)),
+ BOOL_SETTING(0, constrain_next_folder, LANG_CONSTRAIN_NEXT_FOLDER, false,
+ "constrain next folder", off_on,
+ LANG_SET_BOOL_YES, LANG_SET_BOOL_NO, NULL),
#ifdef HAVE_TAGCACHE
#if CONFIG_CODEC == SWCODEC