diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index f93ce0a0ac..eee33b7d08 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -9927,3 +9927,16 @@
*: "Korea"
+
+ id: LANG_RANOOM
+ desc: random folder
+
+
+ *: "Random"
+
+
+ *: "Random"
+
+
diff --git a/apps/playlist.c b/apps/playlist.c
index 9d844e3b84..5a5313b736 100644
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -1313,6 +1313,29 @@ static int get_next_dir(char *dir, bool is_forward, bool recursion)
struct tree_context* tc = tree_get_context();
int dirfilter = *(tc->dirfilter);
+ if (global_settings.next_folder == FOLDER_ADVANCE_RANDOM)
+ {
+ int fd = open(ROCKBOX_DIR "/folder_advance_list.dat",O_RDONLY);
+ char buffer[MAX_PATH];
+ int folder_count = 0,i;
+ srand(current_tick);
+ if (fd >= 0)
+ {
+ read(fd,&folder_count,sizeof(int));
+ while (!exit)
+ {
+ i = rand()%folder_count;
+ lseek(fd,sizeof(int) + (MAX_PATH*i),SEEK_SET);
+ read(fd,buffer,MAX_PATH);
+ if (check_subdir_for_music(buffer,"") ==0)
+ exit = true;
+ }
+ strcpy(dir,buffer);
+ close(fd);
+ return 0;
+ }
+ }
+ /* not random folder advance */
if (recursion){
/* start with root */
dir[0] = '\0';
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index d2ccf81f62..b0e5f70e0a 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -9,6 +9,7 @@ firmware_flash.c
logo.c
metronome.c
mosaique.c
+random_folder_advance_config.c
#if (LCD_WIDTH != 240) && ((LCD_WIDTH != 128) || (LCD_HEIGHT != 64))
rockblox.c
#endif
diff --git a/apps/plugins/random_folder_advance_config.c b/apps/plugins/random_folder_advance_config.c
new file mode 100644
index 0000000000..033232a29e
--- /dev/null
+++ b/apps/plugins/random_folder_advance_config.c
@@ -0,0 +1,319 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Jonathan Gordon
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "plugin.h"
+
+PLUGIN_HEADER
+
+static struct plugin_api* rb;
+static bool abort;
+static int fd;
+static int dirs_count;
+static int lasttick;
+#define RFA_FILE ROCKBOX_DIR "/folder_advance_list.dat"
+char *buffer = NULL;
+int buffer_size;
+struct file_format {
+ int count;
+ char folder[][MAX_PATH];
+};
+struct file_format *list = NULL;
+#if CONFIG_KEYPAD == PLAYER_PAD
+
+#elif (CONFIG_KEYPAD == RECORDER_PAD) \
+ || (CONFIG_KEYPAD == ONDIO_PAD)
+
+#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) \
+ || (CONFIG_KEYPAD == IRIVER_H300_PAD)
+
+#elif (CONFIG_KEYPAD == IPOD_4G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_3G_PAD)
+
+#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
+
+#elif CONFIG_KEYPAD == IAUDIO_X5_PAD
+
+#elif CONFIG_KEYPAD == GIGABEAT_PAD
+
+#elif CONFIG_KEYPAD == IRIVER_H10_PAD
+
+#endif
+
+void update_screen(void)
+{
+ char buf[15];
+ int i;
+ FOR_NB_SCREENS(i)
+ {
+ rb->snprintf(buf,15,"Folders: %d",dirs_count);
+ rb->screens[i]->clear_display();
+ rb->screens[i]->putsxy(0,0,buf);
+ rb->screens[i]->update();
+ }
+}
+
+void traversedir(char* location, char* name)
+{
+ struct dirent *entry;
+ DIR* dir;
+ char fullpath[MAX_PATH];
+ bool check = false;
+
+ rb->snprintf(fullpath, sizeof(fullpath), "%s/%s", location, name);
+ dir = rb->opendir(fullpath);
+ if (dir) {
+ entry = rb->readdir(dir);
+ while (entry) {
+ if (abort == true)
+ break;
+ /* Skip .. and . */
+ if (entry->d_name[0] == '.')
+ {
+ if ( !rb->strcmp(entry->d_name,".")
+ || !rb->strcmp(entry->d_name,"..")
+ || !rb->strcmp(entry->d_name,".rockbox"))
+ check = false;
+ else check = true;
+ }
+ else check = true;
+
+ if (check)
+ {
+ if (entry->attribute & ATTR_DIRECTORY) {
+ char *start, path[MAX_PATH];
+ dirs_count++;
+ rb->snprintf(path,MAX_PATH,"%s/%s",fullpath,entry->d_name);
+ start = &path[rb->strlen(path)];
+ rb->memset(start,0,&path[MAX_PATH-1]-start);
+ rb->write(fd,path,MAX_PATH);
+ traversedir(fullpath, entry->d_name);
+ }
+ }
+ if (*rb->current_tick - lasttick > (HZ/2)) {
+ update_screen();
+ lasttick = *rb->current_tick;
+ if (rb->action_userabort(TIMEOUT_NOBLOCK))
+ {
+ abort = true;
+ break;
+ }
+ }
+
+ entry = rb->readdir(dir);
+ }
+ rb->closedir(dir);
+ }
+}
+void generate(void)
+{
+ dirs_count = 0;
+ abort = false;
+ fd = rb->open(RFA_FILE,O_CREAT|O_WRONLY);
+ rb->write(fd,&dirs_count,sizeof(int));
+ if (fd < 0)
+ {
+ rb->splash(HZ, true, "Couldnt open %s", RFA_FILE);
+ return;
+ }
+ update_screen();
+ lasttick = *rb->current_tick;
+
+ traversedir("", "");
+ rb->lseek(fd,0,SEEK_SET);
+ rb->write(fd,&dirs_count,sizeof(int));
+ rb->close(fd);
+}
+char *list_get_name_cb(int selected_item,void* data,char* buf)
+{
+ (void)data;
+ rb->strcpy(buf,list->folder[selected_item]);
+ return buf;
+}
+
+void edit_list(void)
+{
+ struct gui_synclist lists;
+ bool exit = false;
+ int button,i;
+ int selection;
+ fd = rb->open(RFA_FILE,O_RDONLY);
+ if (fd < 0)
+ return;
+ buffer = rb->plugin_get_audio_buffer(&buffer_size);
+ if (!buffer)
+ return;
+ rb->read(fd,buffer,buffer_size);
+ rb->close(fd);
+ list = (struct file_format *)buffer;
+
+ rb->gui_synclist_init(&lists,list_get_name_cb,0, false, 1);
+ rb->gui_synclist_set_icon_callback(&lists,NULL);
+ rb->gui_synclist_set_nb_items(&lists,list->count);
+ rb->gui_synclist_limit_scroll(&lists,true);
+ rb->gui_synclist_select_item(&lists, 0);
+
+ while (!exit)
+ {
+ rb->gui_synclist_draw(&lists);
+ rb->lcd_update();
+ button = rb->get_action(CONTEXT_LIST,TIMEOUT_BLOCK);
+ if (rb->gui_synclist_do_button(&lists,button))
+ continue;
+ selection = rb->gui_synclist_get_sel_pos(&lists);
+ switch (button)
+ {
+ case ACTION_STD_OK:
+ list->folder[selection][0] = ' ';
+ list->folder[selection][1] = '\0';
+ break;
+ case ACTION_STD_CONTEXT:
+ {
+ int m, len;
+ static const struct menu_item items[] = {
+ { "Remove Folder", NULL },
+ { "Remove Folder Tree", NULL },
+ };
+ m = rb->menu_init(items, sizeof(items) / sizeof(*items),
+ NULL, NULL, NULL, NULL);
+
+ switch (rb->menu_show(m))
+ {
+ case 0:
+ list->folder[selection][0] = ' ';
+ list->folder[selection][1] = '\0';
+ break;
+ case 1:
+ {
+ char temp[MAX_PATH];
+ rb->strcpy(temp,list->folder[selection]);
+ len = rb->strlen(temp);
+ for (i=0;icount;i++)
+ {
+ if (!rb->strncmp(list->folder[i],temp,len))
+ {
+ list->folder[i][0] = ' ';
+ list->folder[i][1] = '\0';
+ }
+ }
+ }
+ break;
+ }
+ rb->menu_exit(m);
+ }
+ break;
+ case ACTION_STD_CANCEL:
+ {
+ int m;
+ static const struct menu_item items[] = {
+ { "Save and Exit", NULL },
+ { "Ignore Changes and Exit", NULL },
+ };
+ m = rb->menu_init(items, sizeof(items) / sizeof(*items),
+ NULL, NULL, NULL, NULL);
+
+ switch (rb->menu_show(m))
+ {
+ case 0:
+ exit = true;
+ rb->splash(HZ*2, true, "Saving " RFA_FILE);
+ fd = rb->open(RFA_FILE, O_CREAT|O_WRONLY);
+ if (fd < 0)
+ {
+ rb->splash(HZ, true, "Could Not Open " RFA_FILE);
+ break;
+ }
+ dirs_count = 0;
+ rb->write(fd,&dirs_count,sizeof(int));
+ for (i=0;icount;i++)
+ {
+ if (list->folder[i][0] != ' ')
+ {
+ dirs_count++;
+ rb->write(fd,list->folder[i],MAX_PATH);
+ }
+ }
+ rb->lseek(fd,0,SEEK_SET);
+ rb->write(fd,&dirs_count,sizeof(int));
+ rb->close(fd);
+ case 1:
+ exit = true;
+ }
+ rb->menu_exit(m);
+ }
+ break;
+ }
+ }
+}
+int main_menu(void)
+{
+ int m;
+ static const struct menu_item items[] = {
+ { "Generate Folder List", NULL },
+ { "Edit Folder List", NULL },
+ { "Quit", NULL },
+ };
+ m = rb->menu_init(items, sizeof(items) / sizeof(*items),
+ NULL, NULL, NULL, NULL);
+
+ switch (rb->menu_show(m))
+ {
+ case 0: /* generate */
+#ifdef HAVE_ADJUSTABLE_CPU_FREQ
+ rb->cpu_boost(true);
+#endif
+ generate();
+#ifdef HAVE_ADJUSTABLE_CPU_FREQ
+ rb->cpu_boost(false);
+#endif
+#ifdef HAVE_REMOTE_LCD
+ rb->remote_backlight_on();
+#endif
+ rb->backlight_on();
+ break;
+ case 1:
+#ifdef HAVE_ADJUSTABLE_CPU_FREQ
+ rb->cpu_boost(true);
+#endif
+ edit_list();
+#ifdef HAVE_ADJUSTABLE_CPU_FREQ
+ rb->cpu_boost(false);
+#endif
+#ifdef HAVE_REMOTE_LCD
+ rb->remote_backlight_on();
+#endif
+ rb->backlight_on();
+ break;
+ case 2:
+ rb->menu_exit(m);
+ return 1;
+ }
+ rb->menu_exit(m);
+ return 0;
+}
+
+enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
+{
+ (void)parameter;
+
+ rb = api;
+ abort = false;
+
+ while (!main_menu())
+ ;
+ return PLUGIN_OK;
+}
diff --git a/apps/settings.c b/apps/settings.c
index ebe0d1e4cd..63f85f0608 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -96,7 +96,7 @@ const char rec_base_directory[] = REC_BASE_DIR;
#include "eq_menu.h"
#endif
-#define CONFIG_BLOCK_VERSION 52
+#define CONFIG_BLOCK_VERSION 53
#define CONFIG_BLOCK_SIZE 512
#define RTC_BLOCK_SIZE 44
@@ -544,7 +544,7 @@ static const struct bit_entry hd_bits[] =
{1, S_O(spdif_enable), false, "spdif enable", off_on},
#endif
- {1, S_O(next_folder), false, "folder navigation", off_on },
+ {2, S_O(next_folder), false, "folder navigation", "off,on,random" },
{1, S_O(runtimedb), false, "gather runtime data", off_on },
#if CONFIG_CODEC == SWCODEC
diff --git a/apps/settings.h b/apps/settings.h
index b29a219733..5313fe37b1 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -80,6 +80,10 @@ extern const char * const trig_durations[TRIG_DURATION_COUNT];
#define CROSSFADE_ENABLE_SHUFFLE 1
#define CROSSFADE_ENABLE_ALWAYS 2
+#define FOLDER_ADVANCE_OFF 0
+#define FOLDER_ADVANCE_NEXT 1
+#define FOLDER_ADVANCE_RANDOM 2
+
/* These define "virtual pointers", which could either be a literal string,
or a mean a string ID if the pointer is in a certain range.
This helps to save space for menus and options. */
@@ -363,7 +367,7 @@ struct user_settings
#endif
#endif /* HAVE_REMOTE_LCD */
- bool next_folder; /* move to next folder */
+ int next_folder; /* move to next folder */
bool runtimedb; /* runtime database active? */
#if CONFIG_CODEC == SWCODEC
diff --git a/apps/settings_menu.c b/apps/settings_menu.c
index b2d261492e..9c19f19fb1 100644
--- a/apps/settings_menu.c
+++ b/apps/settings_menu.c
@@ -1377,7 +1377,14 @@ static bool id3_order(void)
static bool next_folder(void)
{
- return set_bool( str(LANG_NEXT_FOLDER), &global_settings.next_folder );
+ static const struct opt_items names[] = {
+ { STR(LANG_SET_BOOL_NO) },
+ { STR(LANG_SET_BOOL_YES) },
+ { STR(LANG_RANOOM) },
+ };
+ return set_option(str(LANG_NEXT_FOLDER),
+ &global_settings.next_folder,
+ INT, names, 3, NULL );
}
static bool codepage_setting(void)