summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Gordon <rockbox@jdgordon.info>2006-10-09 10:54:17 +0000
committerJonathan Gordon <rockbox@jdgordon.info>2006-10-09 10:54:17 +0000
commit27ad51fb15d6ba753ee8f7d7d9dafd43d20e6551 (patch)
tree56ece79078add1c5ac8a282b3878f4a710897fd1
parentbe2eb02d7a9bba97aeb022174e4abe2cc132d6a3 (diff)
downloadrockbox-27ad51fb15d6ba753ee8f7d7d9dafd43d20e6551.tar.gz
rockbox-27ad51fb15d6ba753ee8f7d7d9dafd43d20e6551.zip
Adds random folder advance option. RESETS SETTINGS. Refer to random_folder_advance_config wiki page for more info
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11158 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/lang/english.lang13
-rw-r--r--apps/playlist.c23
-rw-r--r--apps/plugins/SOURCES1
-rw-r--r--apps/plugins/random_folder_advance_config.c319
-rw-r--r--apps/settings.c4
-rw-r--r--apps/settings.h6
-rw-r--r--apps/settings_menu.c9
7 files changed, 371 insertions, 4 deletions
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 @@
9927 *: "Korea" 9927 *: "Korea"
9928 </voice> 9928 </voice>
9929</phrase> 9929</phrase>
9930<phrase>
9931 id: LANG_RANOOM
9932 desc: random folder
9933 <source>
9934 *: "Random"
9935 </source>
9936 <dest>
9937 *: "Random"
9938 </dest>
9939 <voice>
9940 *: "Random"
9941 </voice>
9942</phrase>
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)
1313 struct tree_context* tc = tree_get_context(); 1313 struct tree_context* tc = tree_get_context();
1314 int dirfilter = *(tc->dirfilter); 1314 int dirfilter = *(tc->dirfilter);
1315 1315
1316 if (global_settings.next_folder == FOLDER_ADVANCE_RANDOM)
1317 {
1318 int fd = open(ROCKBOX_DIR "/folder_advance_list.dat",O_RDONLY);
1319 char buffer[MAX_PATH];
1320 int folder_count = 0,i;
1321 srand(current_tick);
1322 if (fd >= 0)
1323 {
1324 read(fd,&folder_count,sizeof(int));
1325 while (!exit)
1326 {
1327 i = rand()%folder_count;
1328 lseek(fd,sizeof(int) + (MAX_PATH*i),SEEK_SET);
1329 read(fd,buffer,MAX_PATH);
1330 if (check_subdir_for_music(buffer,"") ==0)
1331 exit = true;
1332 }
1333 strcpy(dir,buffer);
1334 close(fd);
1335 return 0;
1336 }
1337 }
1338 /* not random folder advance */
1316 if (recursion){ 1339 if (recursion){
1317 /* start with root */ 1340 /* start with root */
1318 dir[0] = '\0'; 1341 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
9logo.c 9logo.c
10metronome.c 10metronome.c
11mosaique.c 11mosaique.c
12random_folder_advance_config.c
12#if (LCD_WIDTH != 240) && ((LCD_WIDTH != 128) || (LCD_HEIGHT != 64)) 13#if (LCD_WIDTH != 240) && ((LCD_WIDTH != 128) || (LCD_HEIGHT != 64))
13rockblox.c 14rockblox.c
14#endif 15#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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2006 Jonathan Gordon
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "plugin.h"
20
21PLUGIN_HEADER
22
23static struct plugin_api* rb;
24static bool abort;
25static int fd;
26static int dirs_count;
27static int lasttick;
28#define RFA_FILE ROCKBOX_DIR "/folder_advance_list.dat"
29char *buffer = NULL;
30int buffer_size;
31struct file_format {
32 int count;
33 char folder[][MAX_PATH];
34};
35struct file_format *list = NULL;
36#if CONFIG_KEYPAD == PLAYER_PAD
37
38#elif (CONFIG_KEYPAD == RECORDER_PAD) \
39 || (CONFIG_KEYPAD == ONDIO_PAD)
40
41#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) \
42 || (CONFIG_KEYPAD == IRIVER_H300_PAD)
43
44#elif (CONFIG_KEYPAD == IPOD_4G_PAD) \
45 || (CONFIG_KEYPAD == IPOD_3G_PAD)
46
47#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
48
49#elif CONFIG_KEYPAD == IAUDIO_X5_PAD
50
51#elif CONFIG_KEYPAD == GIGABEAT_PAD
52
53#elif CONFIG_KEYPAD == IRIVER_H10_PAD
54
55#endif
56
57void update_screen(void)
58{
59 char buf[15];
60 int i;
61 FOR_NB_SCREENS(i)
62 {
63 rb->snprintf(buf,15,"Folders: %d",dirs_count);
64 rb->screens[i]->clear_display();
65 rb->screens[i]->putsxy(0,0,buf);
66 rb->screens[i]->update();
67 }
68}
69
70void traversedir(char* location, char* name)
71{
72 struct dirent *entry;
73 DIR* dir;
74 char fullpath[MAX_PATH];
75 bool check = false;
76
77 rb->snprintf(fullpath, sizeof(fullpath), "%s/%s", location, name);
78 dir = rb->opendir(fullpath);
79 if (dir) {
80 entry = rb->readdir(dir);
81 while (entry) {
82 if (abort == true)
83 break;
84 /* Skip .. and . */
85 if (entry->d_name[0] == '.')
86 {
87 if ( !rb->strcmp(entry->d_name,".")
88 || !rb->strcmp(entry->d_name,"..")
89 || !rb->strcmp(entry->d_name,".rockbox"))
90 check = false;
91 else check = true;
92 }
93 else check = true;
94
95 if (check)
96 {
97 if (entry->attribute & ATTR_DIRECTORY) {
98 char *start, path[MAX_PATH];
99 dirs_count++;
100 rb->snprintf(path,MAX_PATH,"%s/%s",fullpath,entry->d_name);
101 start = &path[rb->strlen(path)];
102 rb->memset(start,0,&path[MAX_PATH-1]-start);
103 rb->write(fd,path,MAX_PATH);
104 traversedir(fullpath, entry->d_name);
105 }
106 }
107 if (*rb->current_tick - lasttick > (HZ/2)) {
108 update_screen();
109 lasttick = *rb->current_tick;
110 if (rb->action_userabort(TIMEOUT_NOBLOCK))
111 {
112 abort = true;
113 break;
114 }
115 }
116
117 entry = rb->readdir(dir);
118 }
119 rb->closedir(dir);
120 }
121}
122void generate(void)
123{
124 dirs_count = 0;
125 abort = false;
126 fd = rb->open(RFA_FILE,O_CREAT|O_WRONLY);
127 rb->write(fd,&dirs_count,sizeof(int));
128 if (fd < 0)
129 {
130 rb->splash(HZ, true, "Couldnt open %s", RFA_FILE);
131 return;
132 }
133 update_screen();
134 lasttick = *rb->current_tick;
135
136 traversedir("", "");
137 rb->lseek(fd,0,SEEK_SET);
138 rb->write(fd,&dirs_count,sizeof(int));
139 rb->close(fd);
140}
141char *list_get_name_cb(int selected_item,void* data,char* buf)
142{
143 (void)data;
144 rb->strcpy(buf,list->folder[selected_item]);
145 return buf;
146}
147
148void edit_list(void)
149{
150 struct gui_synclist lists;
151 bool exit = false;
152 int button,i;
153 int selection;
154 fd = rb->open(RFA_FILE,O_RDONLY);
155 if (fd < 0)
156 return;
157 buffer = rb->plugin_get_audio_buffer(&buffer_size);
158 if (!buffer)
159 return;
160 rb->read(fd,buffer,buffer_size);
161 rb->close(fd);
162 list = (struct file_format *)buffer;
163
164 rb->gui_synclist_init(&lists,list_get_name_cb,0, false, 1);
165 rb->gui_synclist_set_icon_callback(&lists,NULL);
166 rb->gui_synclist_set_nb_items(&lists,list->count);
167 rb->gui_synclist_limit_scroll(&lists,true);
168 rb->gui_synclist_select_item(&lists, 0);
169
170 while (!exit)
171 {
172 rb->gui_synclist_draw(&lists);
173 rb->lcd_update();
174 button = rb->get_action(CONTEXT_LIST,TIMEOUT_BLOCK);
175 if (rb->gui_synclist_do_button(&lists,button))
176 continue;
177 selection = rb->gui_synclist_get_sel_pos(&lists);
178 switch (button)
179 {
180 case ACTION_STD_OK:
181 list->folder[selection][0] = ' ';
182 list->folder[selection][1] = '\0';
183 break;
184 case ACTION_STD_CONTEXT:
185 {
186 int m, len;
187 static const struct menu_item items[] = {
188 { "Remove Folder", NULL },
189 { "Remove Folder Tree", NULL },
190 };
191 m = rb->menu_init(items, sizeof(items) / sizeof(*items),
192 NULL, NULL, NULL, NULL);
193
194 switch (rb->menu_show(m))
195 {
196 case 0:
197 list->folder[selection][0] = ' ';
198 list->folder[selection][1] = '\0';
199 break;
200 case 1:
201 {
202 char temp[MAX_PATH];
203 rb->strcpy(temp,list->folder[selection]);
204 len = rb->strlen(temp);
205 for (i=0;i<list->count;i++)
206 {
207 if (!rb->strncmp(list->folder[i],temp,len))
208 {
209 list->folder[i][0] = ' ';
210 list->folder[i][1] = '\0';
211 }
212 }
213 }
214 break;
215 }
216 rb->menu_exit(m);
217 }
218 break;
219 case ACTION_STD_CANCEL:
220 {
221 int m;
222 static const struct menu_item items[] = {
223 { "Save and Exit", NULL },
224 { "Ignore Changes and Exit", NULL },
225 };
226 m = rb->menu_init(items, sizeof(items) / sizeof(*items),
227 NULL, NULL, NULL, NULL);
228
229 switch (rb->menu_show(m))
230 {
231 case 0:
232 exit = true;
233 rb->splash(HZ*2, true, "Saving " RFA_FILE);
234 fd = rb->open(RFA_FILE, O_CREAT|O_WRONLY);
235 if (fd < 0)
236 {
237 rb->splash(HZ, true, "Could Not Open " RFA_FILE);
238 break;
239 }
240 dirs_count = 0;
241 rb->write(fd,&dirs_count,sizeof(int));
242 for (i=0;i<list->count;i++)
243 {
244 if (list->folder[i][0] != ' ')
245 {
246 dirs_count++;
247 rb->write(fd,list->folder[i],MAX_PATH);
248 }
249 }
250 rb->lseek(fd,0,SEEK_SET);
251 rb->write(fd,&dirs_count,sizeof(int));
252 rb->close(fd);
253 case 1:
254 exit = true;
255 }
256 rb->menu_exit(m);
257 }
258 break;
259 }
260 }
261}
262int main_menu(void)
263{
264 int m;
265 static const struct menu_item items[] = {
266 { "Generate Folder List", NULL },
267 { "Edit Folder List", NULL },
268 { "Quit", NULL },
269 };
270 m = rb->menu_init(items, sizeof(items) / sizeof(*items),
271 NULL, NULL, NULL, NULL);
272
273 switch (rb->menu_show(m))
274 {
275 case 0: /* generate */
276#ifdef HAVE_ADJUSTABLE_CPU_FREQ
277 rb->cpu_boost(true);
278#endif
279 generate();
280#ifdef HAVE_ADJUSTABLE_CPU_FREQ
281 rb->cpu_boost(false);
282#endif
283#ifdef HAVE_REMOTE_LCD
284 rb->remote_backlight_on();
285#endif
286 rb->backlight_on();
287 break;
288 case 1:
289#ifdef HAVE_ADJUSTABLE_CPU_FREQ
290 rb->cpu_boost(true);
291#endif
292 edit_list();
293#ifdef HAVE_ADJUSTABLE_CPU_FREQ
294 rb->cpu_boost(false);
295#endif
296#ifdef HAVE_REMOTE_LCD
297 rb->remote_backlight_on();
298#endif
299 rb->backlight_on();
300 break;
301 case 2:
302 rb->menu_exit(m);
303 return 1;
304 }
305 rb->menu_exit(m);
306 return 0;
307}
308
309enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
310{
311 (void)parameter;
312
313 rb = api;
314 abort = false;
315
316 while (!main_menu())
317 ;
318 return PLUGIN_OK;
319}
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;
96#include "eq_menu.h" 96#include "eq_menu.h"
97#endif 97#endif
98 98
99#define CONFIG_BLOCK_VERSION 52 99#define CONFIG_BLOCK_VERSION 53
100#define CONFIG_BLOCK_SIZE 512 100#define CONFIG_BLOCK_SIZE 512
101#define RTC_BLOCK_SIZE 44 101#define RTC_BLOCK_SIZE 44
102 102
@@ -544,7 +544,7 @@ static const struct bit_entry hd_bits[] =
544 {1, S_O(spdif_enable), false, "spdif enable", off_on}, 544 {1, S_O(spdif_enable), false, "spdif enable", off_on},
545#endif 545#endif
546 546
547 {1, S_O(next_folder), false, "folder navigation", off_on }, 547 {2, S_O(next_folder), false, "folder navigation", "off,on,random" },
548 {1, S_O(runtimedb), false, "gather runtime data", off_on }, 548 {1, S_O(runtimedb), false, "gather runtime data", off_on },
549 549
550#if CONFIG_CODEC == SWCODEC 550#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];
80#define CROSSFADE_ENABLE_SHUFFLE 1 80#define CROSSFADE_ENABLE_SHUFFLE 1
81#define CROSSFADE_ENABLE_ALWAYS 2 81#define CROSSFADE_ENABLE_ALWAYS 2
82 82
83#define FOLDER_ADVANCE_OFF 0
84#define FOLDER_ADVANCE_NEXT 1
85#define FOLDER_ADVANCE_RANDOM 2
86
83/* These define "virtual pointers", which could either be a literal string, 87/* These define "virtual pointers", which could either be a literal string,
84 or a mean a string ID if the pointer is in a certain range. 88 or a mean a string ID if the pointer is in a certain range.
85 This helps to save space for menus and options. */ 89 This helps to save space for menus and options. */
@@ -363,7 +367,7 @@ struct user_settings
363#endif 367#endif
364#endif /* HAVE_REMOTE_LCD */ 368#endif /* HAVE_REMOTE_LCD */
365 369
366 bool next_folder; /* move to next folder */ 370 int next_folder; /* move to next folder */
367 bool runtimedb; /* runtime database active? */ 371 bool runtimedb; /* runtime database active? */
368 372
369#if CONFIG_CODEC == SWCODEC 373#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)
1377 1377
1378static bool next_folder(void) 1378static bool next_folder(void)
1379{ 1379{
1380 return set_bool( str(LANG_NEXT_FOLDER), &global_settings.next_folder ); 1380 static const struct opt_items names[] = {
1381 { STR(LANG_SET_BOOL_NO) },
1382 { STR(LANG_SET_BOOL_YES) },
1383 { STR(LANG_RANOOM) },
1384 };
1385 return set_option(str(LANG_NEXT_FOLDER),
1386 &global_settings.next_folder,
1387 INT, names, 3, NULL );
1381} 1388}
1382 1389
1383static bool codepage_setting(void) 1390static bool codepage_setting(void)