diff options
author | Nick Peskett <rockbox@peskett.co.uk> | 2012-03-19 09:56:38 +0000 |
---|---|---|
committer | Nick Peskett <rockbox@peskett.co.uk> | 2012-03-19 11:49:55 +0100 |
commit | be10817e1c09d5a41710435cf6d58deb6dde9301 (patch) | |
tree | 4635fcb1ab51d2ef6dc1db28db045c369cf1abaf | |
parent | 69978d7046cd7e537c5079a5e306d22621a1767a (diff) | |
download | rockbox-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>
-rw-r--r-- | apps/lang/english.lang | 14 | ||||
-rw-r--r-- | apps/menus/playback_menu.c | 4 | ||||
-rw-r--r-- | apps/playback.c | 11 | ||||
-rw-r--r-- | apps/playlist.c | 167 | ||||
-rw-r--r-- | apps/plugins/random_folder_advance_config.c | 11 | ||||
-rw-r--r-- | apps/settings.h | 2 | ||||
-rw-r--r-- | apps/settings_list.c | 3 | ||||
-rw-r--r-- | manual/appendix/config_file_options.tex | 1 | ||||
-rw-r--r-- | manual/configure_rockbox/playback_options.tex | 7 | ||||
-rw-r--r-- | manual/rockbox_interface/browsing_and_playing.tex | 6 |
10 files changed, 157 insertions, 69 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 = ¤t_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 diff --git a/manual/appendix/config_file_options.tex b/manual/appendix/config_file_options.tex index 3db416ecfa..59148e15cc 100644 --- a/manual/appendix/config_file_options.tex +++ b/manual/appendix/config_file_options.tex @@ -145,6 +145,7 @@ cuesheet support & on, off & N/A\\ folder navigation & off, on, random & N/A\\ + constrain next folder & off, on & N/A\\ gather runtime data & off, on & N/A\\ \opt{usb_charging_enable}{ usb charging & on, off, force & N/A\\ diff --git a/manual/configure_rockbox/playback_options.tex b/manual/configure_rockbox/playback_options.tex index b3a5c82ee6..bfc2f5c87a 100644 --- a/manual/configure_rockbox/playback_options.tex +++ b/manual/configure_rockbox/playback_options.tex @@ -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 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}{ \section{Pause on Headphone Unplug} Enables and disables automatic pausing of diff --git a/manual/rockbox_interface/browsing_and_playing.tex b/manual/rockbox_interface/browsing_and_playing.tex index d0144c261d..37d8cb01ca 100644 --- a/manual/rockbox_interface/browsing_and_playing.tex +++ b/manual/rockbox_interface/browsing_and_playing.tex @@ -188,9 +188,13 @@ each option pertains both to files and directories): \item [Set As Recording 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 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.] 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. |