1
0
Fork 0
forked from len0rd/rockbox

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>
This commit is contained in:
Nick Peskett 2012-03-19 09:56:38 +00:00
parent 69978d7046
commit be10817e1c
10 changed files with 159 additions and 71 deletions

View file

@ -12993,3 +12993,17 @@
*: "Restart Sleep Timer On Keypress" *: "Restart Sleep Timer On Keypress"
</voice> </voice>
</phrase> </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>

View file

@ -135,6 +135,8 @@ MENUITEM_SETTING(beep, &global_settings.beep ,NULL);
MENUITEM_SETTING(spdif_enable, &global_settings.spdif_enable, NULL); MENUITEM_SETTING(spdif_enable, &global_settings.spdif_enable, NULL);
#endif #endif
MENUITEM_SETTING(next_folder, &global_settings.next_folder, NULL); 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) static int audioscrobbler_callback(int action,const struct menu_item_ex *this_item)
{ {
(void)this_item; (void)this_item;
@ -205,7 +207,7 @@ MAKE_MENU(playback_settings,ID2P(LANG_PLAYBACK),0,
#ifdef HAVE_SPDIF_POWER #ifdef HAVE_SPDIF_POWER
&spdif_enable, &spdif_enable,
#endif #endif
&next_folder, &audioscrobbler, &cuesheet &next_folder, &constrain_next_folder, &audioscrobbler, &cuesheet
#ifdef HAVE_HEADPHONE_DETECTION #ifdef HAVE_HEADPHONE_DETECTION
,&unplug_menu ,&unplug_menu
#endif #endif

View file

@ -2644,8 +2644,17 @@ static void audio_on_skip(void)
skip_pending = TRACK_SKIP_NONE; skip_pending = TRACK_SKIP_NONE;
/* Update the playlist current track now */ /* 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 /* Manual skip out of range (because the playlist wasn't updated
yet by us and so the check in audio_skip returned 'ok') - bring yet by us and so the check in audio_skip returned 'ok') - bring
back into range */ back into range */

View file

@ -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, static int get_filename(struct playlist_info* playlist, int index, int seek,
bool control_file, char *buf, int buf_length); bool control_file, char *buf, int buf_length);
static int get_next_directory(char *dir); 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 get_previous_directory(char *dir);
static int check_subdir_for_music(char *dir, const char *subdir, bool recurse); 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, 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 else
res = get_previous_directory(dir); 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) if (global_settings.playlist_shuffle)
playlist_shuffle(current_tick, -1); playlist_shuffle(current_tick, -1);
if (play_last && direction <= 0) if (play_last && direction <= 0)
index = current_playlist.amount - 1; index = current_playlist.amount - 1;
else else
index = 0; index = 0;
#if (CONFIG_CODEC == SWCODEC) #if (CONFIG_CODEC == SWCODEC)
current_playlist.started = true; current_playlist.started = true;
#else #else
playlist_start(index, 0); playlist_start(index, 0);
#endif #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; 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){ 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){ 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 * search through all the directories (starting with the current) to find
* one that has tracks to play * 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; struct playlist_info* playlist = &current_playlist;
int result = -1; int result = -1;
@ -1454,6 +1455,27 @@ static int get_next_dir(char *dir, bool is_forward, bool recursion)
bool exit = false; bool exit = false;
struct tree_context* tc = tree_get_context(); struct tree_context* tc = tree_get_context();
int saved_dirfilter = *(tc->dirfilter); 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 */ /* process random folder advance */
if (global_settings.next_folder == FOLDER_ADVANCE_RANDOM) 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); int fd = open(ROCKBOX_DIR "/folder_advance_list.dat", O_RDONLY);
if (fd >= 0) if (fd >= 0)
{ {
char buffer[MAX_PATH];
int folder_count = 0; int folder_count = 0;
srand(current_tick);
*(tc->dirfilter) = SHOW_MUSIC;
tc->sort_dir = global_settings.sort_dir;
read(fd,&folder_count,sizeof(int)); read(fd,&folder_count,sizeof(int));
if (!folder_count)
exit = true;
while (!exit)
{
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;
}
if (folder_count) if (folder_count)
strcpy(dir,buffer); {
close(fd); char buffer[MAX_PATH];
*(tc->dirfilter) = saved_dirfilter; /* give up looking for a directory after we've had four
tc->sort_dir = global_settings.sort_dir; times as many tries as there are directories. */
reload_directory(); unsigned long allowed_tries = folder_count * 4;
return 0; 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;
}
}
else
close(fd);
} }
} }
/* not random folder advance (or random folder advance unavailable) */ /* if the current file is within our base dir, use its dir instead */
if (recursion) if (base_len == 0 || !strncmp(playlist->filename, dir, base_len))
{
/* start with root */
dir[0] = '\0';
}
else
{
/* start with current directory */
strlcpy(dir, playlist->filename, playlist->dirlen); strlcpy(dir, playlist->filename, playlist->dirlen);
}
/* use the tree browser dircache to load files */ /* use the tree browser dircache to load files */
*(tc->dirfilter) = SHOW_ALL; *(tc->dirfilter) = SHOW_ALL;
@ -1546,7 +1571,7 @@ static int get_next_dir(char *dir, bool is_forward, bool recursion)
exit = true; exit = true;
break; break;
} }
if (files[i].attr & ATTR_DIRECTORY) if (files[i].attr & ATTR_DIRECTORY)
{ {
if (!start_dir) if (!start_dir)
@ -1566,16 +1591,30 @@ static int get_next_dir(char *dir, bool is_forward, bool recursion)
if (!exit) if (!exit)
{ {
/* move down to parent directory. current directory name is /* we've already descended to the base dir with nothing found,
stored as the starting point for the search in parent */ check whether that contains music */
start_dir = strrchr(dir, '/'); if (strlen(dir) <= base_len)
if (start_dir)
{ {
*start_dir = '\0'; result = check_subdir_for_music(dir, "", true);
start_dir++; if (result == -1)
/* there's no music files in the base directory,
treat as a fatal error */
result = -2;
break;
} }
else 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->dirfilter) = saved_dirfilter;
tc->sort_dir = global_settings.sort_dir; 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; return result;
} }
@ -1606,7 +1640,12 @@ static int check_subdir_for_music(char *dir, const char *subdir, bool recurse)
bool has_subdir = false; bool has_subdir = false;
struct tree_context* tc = tree_get_context(); 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) if (ft_load(tc, dir) < 0)
{ {

View file

@ -65,8 +65,15 @@ static void traversedir(char* location, char* name)
bool check = false; bool check = false;
int i; int i;
rb->snprintf(fullpath, sizeof(fullpath), "%s/%s", location, name); /* behave differently if we're at root to avoid
dir = rb->opendir(fullpath); 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) { if (dir) {
entry = rb->readdir(dir); entry = rb->readdir(dir);
while (entry) { while (entry) {

View file

@ -590,6 +590,8 @@ struct user_settings
/* playlist/playback settings */ /* playlist/playback settings */
int repeat_mode; /* 0=off 1=repeat all 2=repeat one 3=shuffle 4=ab */ int repeat_mode; /* 0=off 1=repeat all 2=repeat one 3=shuffle 4=ab */
int next_folder; /* move to next folder */ 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 */ int recursive_dir_insert; /* should directories be inserted recursively */
bool fade_on_stop; /* fade on pause/unpause/stop */ bool fade_on_stop; /* fade on pause/unpause/stop */
bool playlist_shuffle; bool playlist_shuffle;

View file

@ -1328,6 +1328,9 @@ const struct settings_list settings[] = {
"folder navigation", "off,on,random",NULL ,3, "folder navigation", "off,on,random",NULL ,3,
ID2P(LANG_SET_BOOL_NO), ID2P(LANG_SET_BOOL_YES), ID2P(LANG_SET_BOOL_NO), ID2P(LANG_SET_BOOL_YES),
ID2P(LANG_RANDOM)), 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 #ifdef HAVE_TAGCACHE
#if CONFIG_CODEC == SWCODEC #if CONFIG_CODEC == SWCODEC

View file

@ -145,6 +145,7 @@
cuesheet support cuesheet support
& on, off & N/A\\ & on, off & N/A\\
folder navigation & off, on, random & N/A\\ folder navigation & off, on, random & N/A\\
constrain next folder & off, on & N/A\\
gather runtime data & off, on & N/A\\ gather runtime data & off, on & N/A\\
\opt{usb_charging_enable}{ \opt{usb_charging_enable}{
usb charging & on, off, force & N/A\\ usb charging & on, off, force & N/A\\

View file

@ -221,8 +221,15 @@ you to configure settings related to audio playback.
\note{This feature only works when songs have been played from the file \note{This feature only works when songs have been played from the file
browser. Using it with the database may cause unexpected behaviour.} browser. Using it with the database may cause unexpected behaviour.}
% %
\section{\label{ref:ConstrainAutoChange}Constrain Auto-Change}
If enabled and you have set \setting{Start File Browser Here} to a directory
other than root, \setting{Auto-Change Directory} will be constrained to the
directory you have chosen and those below it.
See \reference{ref:StartFileBrowserHere}.
%
\opt{headphone_detection}{ \opt{headphone_detection}{
\section{Pause on Headphone Unplug} \section{Pause on Headphone Unplug}
Enables and disables automatic pausing of Enables and disables automatic pausing of

View file

@ -188,9 +188,13 @@ each option pertains both to files and directories):
\item [Set As Recording Directory.] \item [Set As Recording Directory.]
Save recordings in the selected directory. Save recordings in the selected directory.
} }
\item [Start File Browser Here.] \item [\label{ref:StartFileBrowserHere}Start File Browser Here.]
This option allows users to set the currently selected directory as the default This option allows users to set the currently selected directory as the default
start directory for the file browser. This option is not available for files. start directory for the file browser. This option is not available for files.
\note{If you have \setting{Auto-Change Directory} and
\setting{Constrain Auto-Change} enabled, the directories returned will
be constrained to the directory you have chosen here and those below it.
See \reference{ref:ConstrainAutoChange}}
\item [Add to Shortcuts.] \item [Add to Shortcuts.]
Adds a link to the selected item in the \fname{shortcuts.link} file. Adds a link to the selected item in the \fname{shortcuts.link} file.
If the file does not already exist it will be created in the root directory. If the file does not already exist it will be created in the root directory.