diff options
Diffstat (limited to 'apps/tree.c')
-rw-r--r-- | apps/tree.c | 942 |
1 files changed, 322 insertions, 620 deletions
diff --git a/apps/tree.c b/apps/tree.c index 8d68814315..7d4ee7f703 100644 --- a/apps/tree.c +++ b/apps/tree.c | |||
@@ -63,6 +63,12 @@ | |||
63 | #include "rtc.h" | 63 | #include "rtc.h" |
64 | #include "dircache.h" | 64 | #include "dircache.h" |
65 | 65 | ||
66 | /* gui api */ | ||
67 | #include "list.h" | ||
68 | #include "statusbar.h" | ||
69 | #include "splash.h" | ||
70 | #include "buttonbar.h" | ||
71 | |||
66 | #ifdef HAVE_LCD_BITMAP | 72 | #ifdef HAVE_LCD_BITMAP |
67 | #include "widgets.h" | 73 | #include "widgets.h" |
68 | #endif | 74 | #endif |
@@ -99,6 +105,14 @@ const struct filetype filetypes[] = { | |||
99 | #endif /* #ifndef SIMULATOR */ | 105 | #endif /* #ifndef SIMULATOR */ |
100 | }; | 106 | }; |
101 | 107 | ||
108 | struct gui_synclist tree_lists; | ||
109 | |||
110 | /* I put it here because other files doesn't use it yet, | ||
111 | * but should be elsewhere since it will be used mostly everywhere */ | ||
112 | struct gui_syncstatusbar statusbars; | ||
113 | #ifdef HAS_BUTTONBAR | ||
114 | struct gui_buttonbar tree_buttonbar; | ||
115 | #endif | ||
102 | static struct tree_context tc; | 116 | static struct tree_context tc; |
103 | 117 | ||
104 | bool boot_changed = false; | 118 | bool boot_changed = false; |
@@ -112,17 +126,77 @@ static bool reload_dir = false; | |||
112 | 126 | ||
113 | static bool start_wps = false; | 127 | static bool start_wps = false; |
114 | static bool dirbrowse(void); | 128 | static bool dirbrowse(void); |
115 | static int curr_context = false; | 129 | static int curr_context = false;/* id3db or tree*/ |
130 | |||
131 | /* | ||
132 | * removes the extension of filename (if it doesn't start with a .) | ||
133 | * puts the result in buffer | ||
134 | */ | ||
135 | char * strip_extension(char * filename, char * buffer) | ||
136 | { | ||
137 | int dotpos; | ||
138 | char * dot=strrchr(filename, '.'); | ||
139 | if(dot!=0 && filename[0]!='.') | ||
140 | { | ||
141 | dotpos = dot-filename; | ||
142 | strncpy(buffer, filename, dotpos); | ||
143 | buffer[dotpos]='\0'; | ||
144 | return(buffer); | ||
145 | } | ||
146 | else | ||
147 | return(filename); | ||
148 | } | ||
149 | char * tree_get_filename(int selected_item, char *buffer) | ||
150 | { | ||
151 | char *name; | ||
152 | int attr=0; | ||
153 | bool id3db = *tc.dirfilter == SHOW_ID3DB; | ||
154 | if (id3db) { | ||
155 | name = ((char**)tc.dircache)[selected_item * tc.dentry_size]; | ||
156 | } | ||
157 | else { | ||
158 | struct entry* dc = tc.dircache; | ||
159 | struct entry* e = &dc[selected_item]; | ||
160 | name = e->name; | ||
161 | attr = e->attr; | ||
162 | } | ||
163 | /* if any file filter is on, and if it's not a directory, | ||
164 | * strip the extension */ | ||
165 | |||
166 | if ( (*tc.dirfilter != SHOW_ID3DB) && !(attr & ATTR_DIRECTORY) | ||
167 | && (*tc.dirfilter != SHOW_ALL) ) | ||
168 | { | ||
169 | return(strip_extension(name, buffer)); | ||
170 | } | ||
171 | return(name); | ||
172 | } | ||
173 | |||
174 | |||
175 | void tree_get_fileicon(int selected_item, ICON * icon) | ||
176 | { | ||
177 | bool id3db = *tc.dirfilter == SHOW_ID3DB; | ||
178 | if (id3db) { | ||
179 | *icon = db_get_icon(&tc); | ||
180 | } | ||
181 | else { | ||
182 | struct entry* dc = tc.dircache; | ||
183 | struct entry* e = &dc[selected_item]; | ||
184 | *icon = filetype_get_icon(e->attr); | ||
185 | } | ||
186 | } | ||
116 | 187 | ||
117 | bool check_rockboxdir(void) | 188 | bool check_rockboxdir(void) |
118 | { | 189 | { |
119 | DIR *dir = opendir(ROCKBOX_DIR); | 190 | DIR *dir = opendir(ROCKBOX_DIR); |
120 | if(!dir) | 191 | if(!dir) |
121 | { | 192 | { |
122 | lcd_clear_display(); | 193 | int i; |
123 | splash(HZ*2, true, str(LANG_NO_ROCKBOX_DIR)); | 194 | for(i = 0;i < NB_SCREENS;++i) |
124 | lcd_clear_display(); | 195 | screens[i].clear_display(); |
125 | splash(HZ*2, true, str(LANG_INSTALLATION_INCOMPLETE)); | 196 | gui_syncsplash(HZ*2, true, str(LANG_NO_ROCKBOX_DIR)); |
197 | for(i = 0;i < NB_SCREENS;++i) | ||
198 | screens[i].clear_display(); | ||
199 | gui_syncsplash(HZ*2, true, str(LANG_INSTALLATION_INCOMPLETE)); | ||
126 | return false; | 200 | return false; |
127 | } | 201 | } |
128 | closedir(dir); | 202 | closedir(dir); |
@@ -131,16 +205,28 @@ bool check_rockboxdir(void) | |||
131 | 205 | ||
132 | void browse_root(void) | 206 | void browse_root(void) |
133 | { | 207 | { |
208 | /* essential to all programs that wants to display things */ | ||
209 | screen_access_init(); | ||
210 | |||
134 | filetype_init(); | 211 | filetype_init(); |
135 | check_rockboxdir(); | 212 | check_rockboxdir(); |
136 | 213 | ||
137 | strcpy(tc.currdir, "/"); | 214 | strcpy(tc.currdir, "/"); |
215 | |||
138 | #ifdef HAVE_LCD_CHARCELLS | 216 | #ifdef HAVE_LCD_CHARCELLS |
139 | lcd_double_height(false); | 217 | int i; |
218 | for(i = 0;i < NB_SCREENS;++i) | ||
219 | screens[i].double_height(false); | ||
140 | #endif | 220 | #endif |
221 | #ifdef HAS_BUTTONBAR | ||
222 | gui_buttonbar_init(&tree_buttonbar); | ||
223 | /* since archos only have one screen, no need to create more than that */ | ||
224 | gui_buttonbar_set_display(&tree_buttonbar, &(screens[SCREEN_MAIN]) ); | ||
225 | #endif | ||
226 | gui_syncstatusbar_init(&statusbars); | ||
227 | gui_synclist_init(&tree_lists, &tree_get_fileicon, &tree_get_filename); | ||
141 | #ifndef SIMULATOR | 228 | #ifndef SIMULATOR |
142 | dirbrowse(); | 229 | dirbrowse(); |
143 | |||
144 | #else | 230 | #else |
145 | if (!dirbrowse()) { | 231 | if (!dirbrowse()) { |
146 | DEBUGF("No filesystem found. Have you forgotten to create it?\n"); | 232 | DEBUGF("No filesystem found. Have you forgotten to create it?\n"); |
@@ -159,126 +245,35 @@ struct tree_context* tree_get_context(void) | |||
159 | return &tc; | 245 | return &tc; |
160 | } | 246 | } |
161 | 247 | ||
162 | #ifdef HAVE_LCD_BITMAP | ||
163 | |||
164 | /* pixel margins */ | ||
165 | #define MARGIN_X (global_settings.scrollbar && \ | ||
166 | tc.filesindir > tree_max_on_screen ? SCROLLBAR_WIDTH : 0) + \ | ||
167 | CURSOR_WIDTH + (global_settings.show_icons && ICON_WIDTH > 0 ? ICON_WIDTH :0) | ||
168 | #define MARGIN_Y (global_settings.statusbar ? STATUSBAR_HEIGHT : 0) | ||
169 | |||
170 | /* position the entry-list starts at */ | ||
171 | #define LINE_X 0 | ||
172 | #define LINE_Y (global_settings.statusbar ? 1 : 0) | ||
173 | |||
174 | #define CURSOR_X (global_settings.scrollbar && \ | ||
175 | tc.filesindir > tree_max_on_screen ? 1 : 0) | ||
176 | #define CURSOR_Y 0 /* the cursor is not positioned in regard to | ||
177 | the margins, so this is the amount of lines | ||
178 | we add to the cursor Y position to position | ||
179 | it on a line */ | ||
180 | #define CURSOR_WIDTH (global_settings.invert_cursor ? 0 : 4) | ||
181 | |||
182 | #define ICON_WIDTH 6 | ||
183 | |||
184 | #define SCROLLBAR_X 0 | ||
185 | #define SCROLLBAR_Y lcd_getymargin() | ||
186 | #define SCROLLBAR_WIDTH 6 | ||
187 | |||
188 | #else /* HAVE_LCD_BITMAP */ | ||
189 | |||
190 | #define TREE_MAX_ON_SCREEN 2 | ||
191 | #define TREE_MAX_LEN_DISPLAY 11 /* max length that fits on screen */ | ||
192 | #define LINE_X 2 /* X position the entry-list starts at */ | ||
193 | #define LINE_Y 0 /* Y position the entry-list starts at */ | ||
194 | |||
195 | #define CURSOR_X 0 | ||
196 | #define CURSOR_Y 0 /* not really used for players */ | ||
197 | |||
198 | #endif /* HAVE_LCD_BITMAP */ | ||
199 | |||
200 | /* talkbox hovering delay, to avoid immediate disk activity */ | 248 | /* talkbox hovering delay, to avoid immediate disk activity */ |
201 | #define HOVER_DELAY (HZ/2) | 249 | #define HOVER_DELAY (HZ/2) |
202 | 250 | /* | |
203 | static void showfileline(int line, char* name, int attr, bool scroll) | 251 | * Returns the position of a given file in the current directory |
252 | * returns -1 if not found | ||
253 | */ | ||
254 | int tree_get_file_position(char * filename) | ||
204 | { | 255 | { |
205 | int xpos = LINE_X; | 256 | int i; |
206 | char* dotpos = NULL; | 257 | /* use lastfile to determine the selected item (default=0) */ |
207 | 258 | for (i=0; i < tc.filesindir; i++) | |
208 | #ifdef HAVE_LCD_CHARCELLS | ||
209 | if (!global_settings.show_icons) | ||
210 | xpos--; | ||
211 | #endif | ||
212 | |||
213 | /* if any file filter is on, strip the extension */ | ||
214 | if (*tc.dirfilter != SHOW_ID3DB && | ||
215 | *tc.dirfilter != SHOW_ALL && | ||
216 | !(attr & ATTR_DIRECTORY)) | ||
217 | { | 259 | { |
218 | dotpos = strrchr(name, '.'); | 260 | struct entry* dc = tc.dircache; |
219 | if (dotpos) { | 261 | struct entry* e = &dc[i]; |
220 | *dotpos = 0; | 262 | if (!strcasecmp(e->name, filename)) |
221 | } | 263 | return(i); |
222 | } | 264 | } |
223 | 265 | return(-1);/* no file can match, returns undefined */ | |
224 | if(scroll) { | ||
225 | #ifdef HAVE_LCD_BITMAP | ||
226 | lcd_setfont(FONT_UI); | ||
227 | if (global_settings.invert_cursor) | ||
228 | lcd_puts_scroll_style(xpos, line, name, STYLE_INVERT); | ||
229 | else | ||
230 | #endif | ||
231 | lcd_puts_scroll(xpos, line, name); | ||
232 | } else | ||
233 | lcd_puts(xpos, line, name); | ||
234 | |||
235 | /* Restore the dot before the extension if it was removed */ | ||
236 | if (dotpos) | ||
237 | *dotpos = '.'; | ||
238 | } | ||
239 | |||
240 | #ifdef HAVE_LCD_BITMAP | ||
241 | static int recalc_screen_height(void) | ||
242 | { | ||
243 | int fw, fh; | ||
244 | int height = LCD_HEIGHT; | ||
245 | |||
246 | lcd_setfont(FONT_UI); | ||
247 | lcd_getstringsize("A", &fw, &fh); | ||
248 | if(global_settings.statusbar) | ||
249 | height -= STATUSBAR_HEIGHT; | ||
250 | |||
251 | #if CONFIG_KEYPAD == RECORDER_PAD | ||
252 | if(global_settings.buttonbar) | ||
253 | height -= BUTTONBAR_HEIGHT; | ||
254 | #endif | ||
255 | |||
256 | return height / fh; | ||
257 | } | 266 | } |
258 | #endif | ||
259 | 267 | ||
260 | static int showdir(void) | 268 | /* |
269 | * Called when a new dir is loaded (for example when returning from other apps ...) | ||
270 | * also completely redraws the tree | ||
271 | */ | ||
272 | static int update_dir(void) | ||
261 | { | 273 | { |
262 | struct entry *dircache = tc.dircache; | ||
263 | int i; | ||
264 | int tree_max_on_screen; | ||
265 | int start = tc.dirstart; | ||
266 | bool id3db = *tc.dirfilter == SHOW_ID3DB; | 274 | bool id3db = *tc.dirfilter == SHOW_ID3DB; |
267 | bool newdir = false; | 275 | bool changed = false; |
268 | #ifdef HAVE_LCD_BITMAP | 276 | /* Checks for changes */ |
269 | const char* icon; | ||
270 | int line_height; | ||
271 | int fw, fh; | ||
272 | lcd_setfont(FONT_UI); | ||
273 | lcd_getstringsize("A", &fw, &fh); | ||
274 | tree_max_on_screen = recalc_screen_height(); | ||
275 | line_height = fh; | ||
276 | #else | ||
277 | int icon; | ||
278 | tree_max_on_screen = TREE_MAX_ON_SCREEN; | ||
279 | #endif | ||
280 | |||
281 | /* new file dir? load it */ | ||
282 | if (id3db) { | 277 | if (id3db) { |
283 | if (tc.currtable != lasttable || | 278 | if (tc.currtable != lasttable || |
284 | tc.currextra != lastextra || | 279 | tc.currextra != lastextra || |
@@ -286,151 +281,73 @@ static int showdir(void) | |||
286 | { | 281 | { |
287 | if (db_load(&tc) < 0) | 282 | if (db_load(&tc) < 0) |
288 | return -1; | 283 | return -1; |
284 | |||
289 | lasttable = tc.currtable; | 285 | lasttable = tc.currtable; |
290 | lastextra = tc.currextra; | 286 | lastextra = tc.currextra; |
291 | lastfirstpos = tc.firstpos; | 287 | lastfirstpos = tc.firstpos; |
292 | newdir = true; | 288 | changed = true; |
293 | } | 289 | } |
294 | } | 290 | } |
295 | else { | 291 | else { |
292 | /* if the tc.currdir has been changed, reload it ...*/ | ||
296 | if (strncmp(tc.currdir, lastdir, sizeof(lastdir)) || reload_dir) { | 293 | if (strncmp(tc.currdir, lastdir, sizeof(lastdir)) || reload_dir) { |
297 | if (ft_load(&tc, NULL) < 0) | 294 | |
295 | if (ft_load(&tc, NULL) < 0) | ||
298 | return -1; | 296 | return -1; |
299 | strcpy(lastdir, tc.currdir); | 297 | strcpy(lastdir, tc.currdir); |
300 | newdir = true; | 298 | changed = true; |
301 | } | 299 | } |
302 | } | 300 | } |
303 | 301 | /* if selected item is undefined */ | |
304 | if (newdir && !id3db && | 302 | if (tc.selected_item == -1) |
305 | (tc.dirfull || tc.filesindir == global_settings.max_files_in_dir) ) | ||
306 | { | 303 | { |
307 | #ifdef HAVE_LCD_CHARCELLS | 304 | /* use lastfile to determine the selected item */ |
308 | lcd_double_height(false); | 305 | tc.selected_item = tree_get_file_position(lastfile); |
309 | #endif | ||
310 | lcd_clear_display(); | ||
311 | lcd_puts(0,0,str(LANG_SHOWDIR_ERROR_BUFFER)); | ||
312 | lcd_puts(0,1,str(LANG_SHOWDIR_ERROR_FULL)); | ||
313 | lcd_update(); | ||
314 | sleep(HZ*2); | ||
315 | lcd_clear_display(); | ||
316 | } | ||
317 | |||
318 | if (start == -1) | ||
319 | { | ||
320 | int diff_files; | ||
321 | |||
322 | /* use lastfile to determine start (default=0) */ | ||
323 | start = 0; | ||
324 | |||
325 | for (i=0; i < tc.filesindir; i++) | ||
326 | { | ||
327 | struct entry *dircache = tc.dircache; | ||
328 | |||
329 | if (!strcasecmp(dircache[i].name, lastfile)) | ||
330 | { | ||
331 | start = i; | ||
332 | break; | ||
333 | } | ||
334 | } | ||
335 | |||
336 | diff_files = tc.filesindir - start; | ||
337 | if (diff_files < tree_max_on_screen) | ||
338 | { | ||
339 | int oldstart = start; | ||
340 | |||
341 | start -= (tree_max_on_screen - diff_files); | ||
342 | if (start < 0) | ||
343 | start = 0; | ||
344 | 306 | ||
345 | tc.dircursor = oldstart - start; | 307 | /* If the file doesn't exists, select the first one (default) */ |
346 | } | 308 | if(tc.selected_item < 0) |
347 | 309 | tc.selected_item = 0; | |
348 | tc.dirstart = start; | 310 | changed = true; |
349 | } | 311 | } |
350 | 312 | if (changed) | |
351 | /* The cursor might point to an invalid line, for example if someone | ||
352 | deleted the last file in the dir */ | ||
353 | if (tc.filesindir) | ||
354 | { | 313 | { |
355 | while (start + tc.dircursor >= tc.filesindir) | 314 | if(!id3db && (tc.dirfull || |
315 | tc.filesindir == global_settings.max_files_in_dir) ) | ||
356 | { | 316 | { |
357 | if (start) | 317 | /* dir full */ |
358 | start--; | 318 | int i; |
359 | else | 319 | for(i = 0;i < NB_SCREENS;++i) |
360 | if (tc.dircursor) | 320 | { |
361 | tc.dircursor--; | ||
362 | } | ||
363 | tc.dirstart = start; | ||
364 | } | ||
365 | |||
366 | #ifdef HAVE_LCD_CHARCELLS | 321 | #ifdef HAVE_LCD_CHARCELLS |
367 | lcd_stop_scroll(); | 322 | screens[i].double_height(false); |
368 | lcd_double_height(false); | ||
369 | #endif | ||
370 | lcd_clear_display(); | ||
371 | #ifdef HAVE_LCD_BITMAP | ||
372 | lcd_setmargins(MARGIN_X,MARGIN_Y); /* leave room for cursor and icon */ | ||
373 | lcd_setfont(FONT_UI); | ||
374 | #endif | 323 | #endif |
375 | 324 | screens[i].clear_display(); | |
376 | 325 | screens[i].puts(0,0,str(LANG_SHOWDIR_ERROR_BUFFER)); | |
377 | for ( i=start; i < start+tree_max_on_screen && i < tc.filesindir; i++ ) { | 326 | screens[i].puts(0,1,str(LANG_SHOWDIR_ERROR_FULL)); |
378 | int line = i - start; | 327 | #if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR) |
379 | char* name; | 328 | screens[i].update(); |
380 | int attr = 0; | ||
381 | |||
382 | if (id3db) { | ||
383 | name = ((char**)tc.dircache)[i * tc.dentry_size]; | ||
384 | icon = db_get_icon(&tc); | ||
385 | } | ||
386 | else { | ||
387 | struct entry* dc = tc.dircache; | ||
388 | struct entry* e = &dc[i]; | ||
389 | name = e->name; | ||
390 | attr = e->attr; | ||
391 | icon = filetype_get_icon(dircache[i].attr); | ||
392 | } | ||
393 | |||
394 | |||
395 | if (icon && global_settings.show_icons) { | ||
396 | #ifdef HAVE_LCD_BITMAP | ||
397 | int offset=0; | ||
398 | if ( line_height > 8 ) | ||
399 | offset = (line_height - 8) / 2; | ||
400 | lcd_mono_bitmap(icon, | ||
401 | CURSOR_X * 6 + CURSOR_WIDTH, | ||
402 | MARGIN_Y+(i-start)*line_height + offset, 6, 8); | ||
403 | #else | ||
404 | if (icon < 0 ) | ||
405 | icon = Icon_Unknown; | ||
406 | lcd_putc(LINE_X-1, i-start, icon); | ||
407 | #endif | 329 | #endif |
330 | } | ||
331 | sleep(HZ*2); | ||
332 | for(i = 0;i < NB_SCREENS;++i) | ||
333 | screens[i].clear_display(); | ||
408 | } | 334 | } |
409 | |||
410 | showfileline(line, name, attr, false); /* no scroll */ | ||
411 | } | 335 | } |
412 | 336 | gui_synclist_set_nb_items(&tree_lists, tc.filesindir); | |
413 | #ifdef HAVE_LCD_BITMAP | 337 | gui_synclist_select_item(&tree_lists, tc.selected_item); |
414 | if (global_settings.scrollbar && (tc.dirlength > tree_max_on_screen)) | 338 | gui_synclist_draw(&tree_lists); |
415 | scrollbar(SCROLLBAR_X, SCROLLBAR_Y, SCROLLBAR_WIDTH - 1, | 339 | gui_syncstatusbar_draw(&statusbars, true); |
416 | tree_max_on_screen * line_height, tc.dirlength, | 340 | #ifdef HAS_BUTTONBAR |
417 | start + tc.firstpos, | ||
418 | start + tc.firstpos + tree_max_on_screen, VERTICAL); | ||
419 | |||
420 | #if CONFIG_KEYPAD == RECORDER_PAD | ||
421 | if (global_settings.buttonbar) { | 341 | if (global_settings.buttonbar) { |
422 | if (*tc.dirfilter < NUM_FILTER_MODES) | 342 | if (*tc.dirfilter < NUM_FILTER_MODES) |
423 | buttonbar_set(str(LANG_DIRBROWSE_F1), | 343 | gui_buttonbar_set(&tree_buttonbar, str(LANG_DIRBROWSE_F1), |
424 | str(LANG_DIRBROWSE_F2), | 344 | str(LANG_DIRBROWSE_F2), |
425 | str(LANG_DIRBROWSE_F3)); | 345 | str(LANG_DIRBROWSE_F3)); |
426 | else | 346 | else |
427 | buttonbar_set("<<<", "", ""); | 347 | gui_buttonbar_set(&tree_buttonbar, "<<<", "", ""); |
428 | buttonbar_draw(); | 348 | gui_buttonbar_draw(&tree_buttonbar); |
429 | } | 349 | } |
430 | #endif | 350 | #endif |
431 | #endif | ||
432 | status_draw(true); | ||
433 | |||
434 | return tc.filesindir; | 351 | return tc.filesindir; |
435 | } | 352 | } |
436 | 353 | ||
@@ -468,7 +385,6 @@ void reload_directory(void) | |||
468 | static void start_resume(bool just_powered_on) | 385 | static void start_resume(bool just_powered_on) |
469 | { | 386 | { |
470 | bool do_resume = false; | 387 | bool do_resume = false; |
471 | |||
472 | if ( global_settings.resume_index != -1 ) { | 388 | if ( global_settings.resume_index != -1 ) { |
473 | DEBUGF("Resume index %X offset %X\n", | 389 | DEBUGF("Resume index %X offset %X\n", |
474 | global_settings.resume_index, | 390 | global_settings.resume_index, |
@@ -486,7 +402,7 @@ static void start_resume(bool just_powered_on) | |||
486 | do_resume = true; | 402 | do_resume = true; |
487 | 403 | ||
488 | if (! do_resume) return; | 404 | if (! do_resume) return; |
489 | 405 | ||
490 | if (playlist_resume() != -1) | 406 | if (playlist_resume() != -1) |
491 | { | 407 | { |
492 | playlist_start(global_settings.resume_index, | 408 | playlist_start(global_settings.resume_index, |
@@ -496,23 +412,23 @@ static void start_resume(bool just_powered_on) | |||
496 | } | 412 | } |
497 | else return; | 413 | else return; |
498 | } else if (! just_powered_on) { | 414 | } else if (! just_powered_on) { |
499 | splash(HZ*2, true, str(LANG_NOTHING_TO_RESUME)); | 415 | gui_syncsplash(HZ*2, true, str(LANG_NOTHING_TO_RESUME)); |
500 | } | 416 | } |
501 | } | 417 | } |
502 | 418 | ||
419 | /* Selects a file and update tree context properly */ | ||
503 | void set_current_file(char *path) | 420 | void set_current_file(char *path) |
504 | { | 421 | { |
505 | char *name; | 422 | char *name; |
506 | unsigned int i; | 423 | int i; |
507 | 424 | ||
508 | /* in ID3DB mode it is a bad idea to call this function */ | 425 | /* in ID3DB mode it is a bad idea to call this function */ |
509 | /* (only happens with `follow playlist') */ | 426 | /* (only happens with `follow playlist') */ |
510 | if( *tc.dirfilter == SHOW_ID3DB ) | 427 | if( *tc.dirfilter == SHOW_ID3DB ) |
511 | { | ||
512 | return; | 428 | return; |
513 | } | ||
514 | 429 | ||
515 | /* separate directory from filename */ | 430 | /* separate directory from filename */ |
431 | /* gets the directory's name and put it into tc.currdir */ | ||
516 | name = strrchr(path+1,'/'); | 432 | name = strrchr(path+1,'/'); |
517 | if (name) | 433 | if (name) |
518 | { | 434 | { |
@@ -528,24 +444,27 @@ void set_current_file(char *path) | |||
528 | } | 444 | } |
529 | 445 | ||
530 | strcpy(lastfile, name); | 446 | strcpy(lastfile, name); |
447 | |||
448 | /* undefined item selected */ | ||
449 | tc.selected_item = -1; | ||
531 | 450 | ||
532 | tc.dircursor = 0; | 451 | /* If we changed dir we must recalculate the dirlevel |
533 | tc.dirstart = -1; | 452 | and adjust the selected history properly */ |
534 | |||
535 | if (strncmp(tc.currdir,lastdir,sizeof(lastdir))) | 453 | if (strncmp(tc.currdir,lastdir,sizeof(lastdir))) |
536 | { | 454 | { |
537 | tc.dirlevel = 0; | 455 | tc.dirlevel = 0; |
538 | tc.dirpos[tc.dirlevel] = -1; | 456 | tc.selected_item_history[tc.dirlevel] = -1; |
539 | tc.cursorpos[tc.dirlevel] = 0; | ||
540 | 457 | ||
541 | /* use '/' to calculate dirlevel */ | 458 | /* use '/' to calculate dirlevel */ |
542 | for (i=1; i<strlen(path)+1; i++) | 459 | /* FIXME : strlen(path) : crazy oO better to store it at |
460 | the beginning */ | ||
461 | int path_len = strlen(path) + 1; | ||
462 | for (i = 1; i < path_len; i++) | ||
543 | { | 463 | { |
544 | if (path[i] == '/') | 464 | if (path[i] == '/') |
545 | { | 465 | { |
546 | tc.dirlevel++; | 466 | tc.dirlevel++; |
547 | tc.dirpos[tc.dirlevel] = -1; | 467 | tc.selected_item_history[tc.dirlevel] = -1; |
548 | tc.cursorpos[tc.dirlevel] = 0; | ||
549 | } | 468 | } |
550 | } | 469 | } |
551 | } | 470 | } |
@@ -567,24 +486,20 @@ static bool check_changed_id3mode(bool currmode) | |||
567 | } | 486 | } |
568 | return currmode; | 487 | return currmode; |
569 | } | 488 | } |
570 | 489 | /* main loop, handles key events */ | |
571 | static bool dirbrowse(void) | 490 | static bool dirbrowse(void) |
572 | { | 491 | { |
573 | int numentries=0; | 492 | int numentries=0; |
574 | char buf[MAX_PATH]; | 493 | char buf[MAX_PATH]; |
575 | int i; | 494 | int lasti = -1; |
576 | int lasti=-1; | ||
577 | unsigned button; | 495 | unsigned button; |
578 | int tree_max_on_screen; | ||
579 | bool reload_root = false; | 496 | bool reload_root = false; |
580 | int lastfilter = *tc.dirfilter; | 497 | int lastfilter = *tc.dirfilter; |
581 | bool lastsortcase = global_settings.sort_case; | 498 | bool lastsortcase = global_settings.sort_case; |
582 | int lastdircursor=-1; | ||
583 | bool need_update = true; | 499 | bool need_update = true; |
584 | bool exit_func = false; | 500 | bool exit_func = false; |
585 | long thumbnail_time = -1; /* for delaying a thumbnail */ | 501 | long thumbnail_time = -1; /* for delaying a thumbnail */ |
586 | bool update_all = false; /* set this to true when the whole file list | 502 | |
587 | has been refreshed on screen */ | ||
588 | unsigned lastbutton = 0; | 503 | unsigned lastbutton = 0; |
589 | char* currdir = tc.currdir; /* just a shortcut */ | 504 | char* currdir = tc.currdir; /* just a shortcut */ |
590 | bool id3db = *tc.dirfilter == SHOW_ID3DB; | 505 | bool id3db = *tc.dirfilter == SHOW_ID3DB; |
@@ -593,15 +508,10 @@ static bool dirbrowse(void) | |||
593 | curr_context=CONTEXT_ID3DB; | 508 | curr_context=CONTEXT_ID3DB; |
594 | else | 509 | else |
595 | curr_context=CONTEXT_TREE; | 510 | curr_context=CONTEXT_TREE; |
596 | |||
597 | #ifdef HAVE_LCD_BITMAP | 511 | #ifdef HAVE_LCD_BITMAP |
598 | tree_max_on_screen = recalc_screen_height(); | 512 | screen_access_update_nb_lines(); |
599 | #else | ||
600 | tree_max_on_screen = TREE_MAX_ON_SCREEN; | ||
601 | #endif | 513 | #endif |
602 | 514 | tc.selected_item = 0; | |
603 | tc.dircursor=0; | ||
604 | tc.dirstart=0; | ||
605 | tc.dirlevel=0; | 515 | tc.dirlevel=0; |
606 | tc.firstpos=0; | 516 | tc.firstpos=0; |
607 | lasttable = -1; | 517 | lasttable = -1; |
@@ -624,25 +534,21 @@ static bool dirbrowse(void) | |||
624 | start_resume(true); | 534 | start_resume(true); |
625 | 535 | ||
626 | } | 536 | } |
627 | 537 | /* If we don't need to show the wps, draw the dir */ | |
628 | if (!start_wps) { | 538 | if (!start_wps) { |
629 | numentries = showdir(); | 539 | numentries = update_dir(); |
630 | if (numentries == -1) | 540 | if (numentries == -1) |
631 | return false; /* currdir is not a directory */ | 541 | return false; /* currdir is not a directory */ |
632 | 542 | ||
633 | if (*tc.dirfilter > NUM_FILTER_MODES && numentries==0) | 543 | if (*tc.dirfilter > NUM_FILTER_MODES && numentries==0) |
634 | { | 544 | { |
635 | splash(HZ*2, true, str(LANG_NO_FILES)); | 545 | gui_syncsplash(HZ*2, true, str(LANG_NO_FILES)); |
636 | return false; /* No files found for rockbox_browser() */ | 546 | return false; /* No files found for rockbox_browser() */ |
637 | } | 547 | } |
638 | update_all = true; | ||
639 | |||
640 | put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor, true); | ||
641 | } | 548 | } |
642 | 549 | ||
643 | while(1) { | 550 | while(1) { |
644 | struct entry *dircache = tc.dircache; | 551 | struct entry *dircache = tc.dircache; |
645 | |||
646 | bool restore = false; | 552 | bool restore = false; |
647 | 553 | ||
648 | button = button_get_w_tmo(HZ/5); | 554 | button = button_get_w_tmo(HZ/5); |
@@ -651,15 +557,18 @@ static bool dirbrowse(void) | |||
651 | if (boot_changed) { | 557 | if (boot_changed) { |
652 | bool stop = false; | 558 | bool stop = false; |
653 | unsigned int button; | 559 | unsigned int button; |
654 | 560 | int i; | |
655 | lcd_clear_display(); | 561 | for(i = 0;i < NB_SCREENS;++i) |
656 | lcd_puts(0,0,str(LANG_BOOT_CHANGED)); | 562 | { |
657 | lcd_puts(0,1,str(LANG_REBOOT_NOW)); | 563 | screens[i].clear_display(); |
564 | screens[i].puts(0,0,str(LANG_BOOT_CHANGED)); | ||
565 | screens[i].puts(0,1,str(LANG_REBOOT_NOW)); | ||
658 | #ifdef HAVE_LCD_BITMAP | 566 | #ifdef HAVE_LCD_BITMAP |
659 | lcd_puts(0,3,str(LANG_CONFIRM_WITH_PLAY_RECORDER)); | 567 | screens[i].puts(0,3,str(LANG_CONFIRM_WITH_PLAY_RECORDER)); |
660 | lcd_puts(0,4,str(LANG_CANCEL_WITH_ANY_RECORDER)); | 568 | screens[i].puts(0,4,str(LANG_CANCEL_WITH_ANY_RECORDER)); |
661 | lcd_update(); | 569 | screens[i].update(); |
662 | #endif | 570 | #endif |
571 | } | ||
663 | while (!stop) { | 572 | while (!stop) { |
664 | button = button_get(true); | 573 | button = button_get(true); |
665 | switch (button) { | 574 | switch (button) { |
@@ -683,6 +592,7 @@ static bool dirbrowse(void) | |||
683 | boot_changed = false; | 592 | boot_changed = false; |
684 | } | 593 | } |
685 | #endif | 594 | #endif |
595 | need_update = gui_synclist_do_button(&tree_lists, button); | ||
686 | 596 | ||
687 | switch ( button ) { | 597 | switch ( button ) { |
688 | #ifdef TREE_ENTER | 598 | #ifdef TREE_ENTER |
@@ -702,33 +612,17 @@ static bool dirbrowse(void) | |||
702 | && (lastbutton != TREE_RUN_PRE))) | 612 | && (lastbutton != TREE_RUN_PRE))) |
703 | break; | 613 | break; |
704 | #endif | 614 | #endif |
705 | if ( !numentries ) | 615 | /* nothing to do if no files to display */ |
616 | if ( numentries == 0 ) | ||
706 | break; | 617 | break; |
707 | 618 | ||
708 | if (id3db) | 619 | switch (id3db?db_enter(&tc):ft_enter(&tc)) |
709 | i = db_enter(&tc); | ||
710 | else | ||
711 | i = ft_enter(&tc); | ||
712 | |||
713 | switch (i) | ||
714 | { | 620 | { |
715 | case 1: reload_dir = true; break; | 621 | case 1: reload_dir = true; break; |
716 | case 2: start_wps = true; break; | 622 | case 2: start_wps = true; break; |
717 | case 3: exit_func = true; break; | 623 | case 3: exit_func = true; break; |
718 | default: break; | 624 | default: break; |
719 | } | 625 | } |
720 | |||
721 | #ifdef HAVE_LCD_BITMAP | ||
722 | /* maybe we have a new font */ | ||
723 | tree_max_on_screen = recalc_screen_height(); | ||
724 | #endif | ||
725 | /* make sure cursor is on screen */ | ||
726 | while ( tc.dircursor > tree_max_on_screen ) | ||
727 | { | ||
728 | tc.dircursor--; | ||
729 | tc.dirstart++; | ||
730 | } | ||
731 | |||
732 | restore = true; | 626 | restore = true; |
733 | break; | 627 | break; |
734 | 628 | ||
@@ -741,8 +635,8 @@ static bool dirbrowse(void) | |||
741 | exit_func = true; | 635 | exit_func = true; |
742 | break; | 636 | break; |
743 | } | 637 | } |
744 | 638 | /* if we are in /, nothing to do */ | |
745 | if (!tc.dirlevel) | 639 | if (tc.dirlevel == 0) |
746 | break; | 640 | break; |
747 | 641 | ||
748 | if (id3db) | 642 | if (id3db) |
@@ -783,169 +677,6 @@ static bool dirbrowse(void) | |||
783 | break; | 677 | break; |
784 | #endif | 678 | #endif |
785 | #endif | 679 | #endif |
786 | |||
787 | case TREE_PREV: | ||
788 | case TREE_PREV | BUTTON_REPEAT: | ||
789 | #ifdef TREE_RC_PREV | ||
790 | case TREE_RC_PREV: | ||
791 | case TREE_RC_PREV | BUTTON_REPEAT: | ||
792 | #endif | ||
793 | if (!tc.filesindir) | ||
794 | break; | ||
795 | |||
796 | /* start scrolling when at 1/3 of the screen */ | ||
797 | if (tc.dircursor >= | ||
798 | tree_max_on_screen - (2 * tree_max_on_screen) / 3 | ||
799 | || (tc.dirstart == 0 && tc.dircursor > 0)) { | ||
800 | put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor, false); | ||
801 | tc.dircursor--; | ||
802 | put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor, true); | ||
803 | } | ||
804 | else { | ||
805 | if (tc.dirstart || tc.firstpos) { | ||
806 | if (tc.dirstart) | ||
807 | tc.dirstart--; | ||
808 | else { | ||
809 | if (tc.firstpos > max_files/2) { | ||
810 | tc.firstpos -= max_files/2; | ||
811 | tc.dirstart += max_files/2; | ||
812 | tc.dirstart--; | ||
813 | } | ||
814 | else { | ||
815 | tc.dirstart = tc.firstpos - 1; | ||
816 | tc.firstpos = 0; | ||
817 | } | ||
818 | } | ||
819 | restore = true; | ||
820 | } | ||
821 | else { | ||
822 | if (button & BUTTON_REPEAT) | ||
823 | break; | ||
824 | if (numentries < tree_max_on_screen) { | ||
825 | put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor, | ||
826 | false); | ||
827 | tc.dircursor = numentries - 1; | ||
828 | put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor, | ||
829 | true); | ||
830 | } | ||
831 | else if (id3db && tc.dirfull) { | ||
832 | /* load last dir segment */ | ||
833 | /* use max_files/2 in case names are longer than | ||
834 | AVERAGE_FILE_LENGTH */ | ||
835 | tc.firstpos = tc.dirlength - max_files/2; | ||
836 | tc.dirstart = tc.firstpos; | ||
837 | tc.dircursor = tree_max_on_screen - 1; | ||
838 | numentries = showdir(); | ||
839 | update_all = true; | ||
840 | put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor, | ||
841 | true); | ||
842 | } | ||
843 | else { | ||
844 | tc.dirstart = numentries - tree_max_on_screen; | ||
845 | tc.dircursor = tree_max_on_screen - 1; | ||
846 | restore = true; | ||
847 | } | ||
848 | } | ||
849 | } | ||
850 | need_update = true; | ||
851 | break; | ||
852 | |||
853 | case TREE_NEXT: | ||
854 | case TREE_NEXT | BUTTON_REPEAT: | ||
855 | #ifdef TREE_RC_NEXT | ||
856 | case TREE_RC_NEXT: | ||
857 | case TREE_RC_NEXT | BUTTON_REPEAT: | ||
858 | #endif | ||
859 | if (!tc.filesindir) | ||
860 | break; | ||
861 | |||
862 | if (tc.dircursor + tc.dirstart + 1 < numentries ) { | ||
863 | /* start scrolling when at 2/3 of the screen */ | ||
864 | if(tc.dircursor < (2 * tree_max_on_screen) / 3 || | ||
865 | numentries - tc.dirstart <= tree_max_on_screen) { | ||
866 | put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor, false); | ||
867 | tc.dircursor++; | ||
868 | put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor, true); | ||
869 | } | ||
870 | else { | ||
871 | tc.dirstart++; | ||
872 | restore = true; | ||
873 | } | ||
874 | } | ||
875 | else if (id3db && (tc.firstpos || tc.dirfull)) { | ||
876 | if (tc.dircursor + tc.dirstart + tc.firstpos + 1 >= tc.dirlength) { | ||
877 | /* wrap and load first dir segment */ | ||
878 | if (button & BUTTON_REPEAT) | ||
879 | break; | ||
880 | tc.firstpos = tc.dirstart = tc.dircursor = 0; | ||
881 | } | ||
882 | else { | ||
883 | /* load next dir segment */ | ||
884 | tc.firstpos += tc.dirstart; | ||
885 | tc.dirstart = 0; | ||
886 | } | ||
887 | restore = true; | ||
888 | } | ||
889 | else { | ||
890 | if (button & BUTTON_REPEAT) | ||
891 | break; | ||
892 | if(numentries < tree_max_on_screen) { | ||
893 | put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor, false); | ||
894 | tc.dirstart = tc.dircursor = 0; | ||
895 | put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor, true); | ||
896 | } | ||
897 | else { | ||
898 | tc.dirstart = tc.dircursor = 0; | ||
899 | numentries = showdir(); | ||
900 | update_all=true; | ||
901 | put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor, true); | ||
902 | } | ||
903 | } | ||
904 | need_update = true; | ||
905 | break; | ||
906 | |||
907 | #ifdef TREE_PGUP | ||
908 | case TREE_PGUP: | ||
909 | case TREE_PGUP | BUTTON_REPEAT: | ||
910 | if (tc.dirstart) { | ||
911 | tc.dirstart -= tree_max_on_screen; | ||
912 | if ( tc.dirstart < 0 ) | ||
913 | tc.dirstart = 0; | ||
914 | } | ||
915 | else if (tc.firstpos) { | ||
916 | if (tc.firstpos > max_files/2) { | ||
917 | tc.firstpos -= max_files/2; | ||
918 | tc.dirstart += max_files/2; | ||
919 | tc.dirstart -= tree_max_on_screen; | ||
920 | } | ||
921 | else { | ||
922 | tc.dirstart = tc.firstpos - tree_max_on_screen; | ||
923 | tc.firstpos = 0; | ||
924 | } | ||
925 | } | ||
926 | else | ||
927 | tc.dircursor = 0; | ||
928 | restore = true; | ||
929 | break; | ||
930 | |||
931 | case TREE_PGDN: | ||
932 | case TREE_PGDN | BUTTON_REPEAT: | ||
933 | if ( tc.dirstart < numentries - tree_max_on_screen ) { | ||
934 | tc.dirstart += tree_max_on_screen; | ||
935 | if ( tc.dirstart > numentries - tree_max_on_screen ) | ||
936 | tc.dirstart = numentries - tree_max_on_screen; | ||
937 | } | ||
938 | else if (id3db && tc.dirfull) { | ||
939 | /* load next dir segment */ | ||
940 | tc.firstpos += tc.dirstart; | ||
941 | tc.dirstart = 0; | ||
942 | } | ||
943 | else | ||
944 | tc.dircursor = numentries - tc.dirstart - 1; | ||
945 | restore = true; | ||
946 | break; | ||
947 | #endif | ||
948 | |||
949 | case TREE_MENU: | 680 | case TREE_MENU: |
950 | #ifdef TREE_RC_MENU | 681 | #ifdef TREE_RC_MENU |
951 | case TREE_RC_MENU: | 682 | case TREE_RC_MENU: |
@@ -957,7 +688,9 @@ static bool dirbrowse(void) | |||
957 | /* don't enter menu from plugin browser */ | 688 | /* don't enter menu from plugin browser */ |
958 | if (*tc.dirfilter < NUM_FILTER_MODES) | 689 | if (*tc.dirfilter < NUM_FILTER_MODES) |
959 | { | 690 | { |
960 | lcd_stop_scroll(); | 691 | int i; |
692 | for(i = 0;i < NB_SCREENS;++i) | ||
693 | screens[i].stop_scroll(); | ||
961 | if (main_menu()) | 694 | if (main_menu()) |
962 | reload_dir = true; | 695 | reload_dir = true; |
963 | restore = true; | 696 | restore = true; |
@@ -1017,7 +750,7 @@ static bool dirbrowse(void) | |||
1017 | { | 750 | { |
1018 | if (quick_screen(curr_context, BUTTON_F3)) | 751 | if (quick_screen(curr_context, BUTTON_F3)) |
1019 | reload_dir = true; | 752 | reload_dir = true; |
1020 | tree_max_on_screen = recalc_screen_height(); | 753 | screen_access_update_nb_lines(); |
1021 | restore = true; | 754 | restore = true; |
1022 | } | 755 | } |
1023 | break; | 756 | break; |
@@ -1052,20 +785,19 @@ static bool dirbrowse(void) | |||
1052 | } | 785 | } |
1053 | else | 786 | else |
1054 | { | 787 | { |
1055 | attr = dircache[tc.dircursor+tc.dirstart].attr; | 788 | attr = dircache[tc.selected_item].attr; |
1056 | 789 | ||
1057 | if (currdir[1]) | 790 | if (currdir[1]) /* Not in / */ |
1058 | snprintf(buf, sizeof buf, "%s/%s", | 791 | snprintf(buf, sizeof buf, "%s/%s", |
1059 | currdir, | 792 | currdir, |
1060 | dircache[tc.dircursor+tc.dirstart].name); | 793 | dircache[tc.selected_item].name); |
1061 | else | 794 | else /* In / */ |
1062 | snprintf(buf, sizeof buf, "/%s", | 795 | snprintf(buf, sizeof buf, "/%s", |
1063 | dircache[tc.dircursor+tc.dirstart].name); | 796 | dircache[tc.selected_item].name); |
1064 | } | 797 | } |
1065 | |||
1066 | onplay_result = onplay(buf, attr, curr_context); | 798 | onplay_result = onplay(buf, attr, curr_context); |
1067 | } | 799 | } |
1068 | 800 | ||
1069 | switch (onplay_result) | 801 | switch (onplay_result) |
1070 | { | 802 | { |
1071 | case ONPLAY_OK: | 803 | case ONPLAY_OK: |
@@ -1099,22 +831,22 @@ static bool dirbrowse(void) | |||
1099 | } | 831 | } |
1100 | } | 832 | } |
1101 | else | 833 | else |
1102 | { | 834 | { |
1103 | DEBUGF("Playing file thumbnail: %s/%s%s\n", | 835 | DEBUGF("Playing file thumbnail: %s/%s%s\n", |
1104 | currdir, dircache[lasti].name, file_thumbnail_ext); | 836 | currdir, dircache[lasti].name, file_thumbnail_ext); |
1105 | /* no fallback necessary, we knew in advance | 837 | /* no fallback necessary, we knew in advance |
1106 | that the file exists */ | 838 | that the file exists */ |
1107 | ft_play_filename(currdir, dircache[lasti].name); | 839 | ft_play_filename(currdir, dircache[lasti].name); |
1108 | } | 840 | } |
1109 | thumbnail_time = -1; /* job done */ | 841 | thumbnail_time = -1; /* job done */ |
1110 | } | 842 | } |
1111 | status_draw(false); | 843 | gui_syncstatusbar_draw(&statusbars, false); |
1112 | break; | 844 | break; |
1113 | 845 | ||
1114 | #ifdef HAVE_HOTSWAP | 846 | #ifdef HAVE_HOTSWAP |
1115 | case SYS_FS_CHANGED: | 847 | case SYS_FS_CHANGED: |
1116 | if (!id3db) | 848 | if (!id3db) |
1117 | reload_dir = true; | 849 | reload_dir = true; |
1118 | /* The 'dir no longer valid' situation will be caught later | 850 | /* The 'dir no longer valid' situation will be caught later |
1119 | * by checking the showdir() result. */ | 851 | * by checking the showdir() result. */ |
1120 | break; | 852 | break; |
@@ -1139,18 +871,20 @@ static bool dirbrowse(void) | |||
1139 | lastbutton = button; | 871 | lastbutton = button; |
1140 | } | 872 | } |
1141 | 873 | ||
1142 | if (start_wps) | 874 | if (start_wps && audio_status() ) |
1143 | { | 875 | { |
1144 | lcd_stop_scroll(); | 876 | int i; |
877 | for(i = 0;i < NB_SCREENS;++i) | ||
878 | screens[i].stop_scroll(); | ||
1145 | if (wps_show() == SYS_USB_CONNECTED) | 879 | if (wps_show() == SYS_USB_CONNECTED) |
1146 | reload_dir = true; | 880 | reload_dir = true; |
1147 | #ifdef HAVE_HOTSWAP | 881 | #ifdef HAVE_HOTSWAP |
1148 | else | 882 | else |
1149 | if (!id3db) /* Try reload to catch 'no longer valid' case. */ | 883 | if (!id3db) /* Try reload to catch 'no longer valid' case. */ |
1150 | reload_dir = true; | 884 | reload_dir = true; |
1151 | #endif | 885 | #endif |
1152 | #ifdef HAVE_LCD_BITMAP | 886 | #ifdef HAVE_LCD_BITMAP |
1153 | tree_max_on_screen = recalc_screen_height(); | 887 | screen_access_update_nb_lines(); |
1154 | #endif | 888 | #endif |
1155 | id3db = check_changed_id3mode(id3db); | 889 | id3db = check_changed_id3mode(id3db); |
1156 | restore = true; | 890 | restore = true; |
@@ -1174,8 +908,9 @@ static bool dirbrowse(void) | |||
1174 | } | 908 | } |
1175 | if (! reload_dir ) | 909 | if (! reload_dir ) |
1176 | { | 910 | { |
1177 | tc.dircursor = 0; | 911 | gui_synclist_select_item(&tree_lists, 0); |
1178 | tc.dirstart = 0; | 912 | gui_synclist_draw(&tree_lists); |
913 | tc.selected_item = 0; | ||
1179 | lastdir[0] = 0; | 914 | lastdir[0] = 0; |
1180 | } | 915 | } |
1181 | 916 | ||
@@ -1190,132 +925,88 @@ static bool dirbrowse(void) | |||
1190 | 925 | ||
1191 | if (restore || reload_dir) { | 926 | if (restore || reload_dir) { |
1192 | /* restore display */ | 927 | /* restore display */ |
1193 | |||
1194 | #ifdef HAVE_LCD_BITMAP | 928 | #ifdef HAVE_LCD_BITMAP |
1195 | tree_max_on_screen = recalc_screen_height(); | 929 | screen_access_update_nb_lines(); |
1196 | #endif | 930 | #endif |
1197 | 931 | numentries = update_dir(); | |
1198 | /* We need to adjust if the number of lines on screen have | ||
1199 | changed because of a status bar change */ | ||
1200 | if(CURSOR_Y+LINE_Y+tc.dircursor>tree_max_on_screen) { | ||
1201 | tc.dirstart++; | ||
1202 | tc.dircursor--; | ||
1203 | } | ||
1204 | #ifdef HAVE_LCD_BITMAP | ||
1205 | /* the sub-screen might've ruined the margins */ | ||
1206 | lcd_setmargins(MARGIN_X,MARGIN_Y); /* leave room for cursor and | ||
1207 | icon */ | ||
1208 | lcd_setfont(FONT_UI); | ||
1209 | #endif | ||
1210 | numentries = showdir(); | ||
1211 | if (currdir[1] && (numentries < 0)) | 932 | if (currdir[1] && (numentries < 0)) |
1212 | { /* not in root and reload failed */ | 933 | { /* not in root and reload failed */ |
1213 | reload_root = true; /* try root */ | 934 | reload_root = true; /* try root */ |
1214 | reload_dir = false; | 935 | reload_dir = false; |
1215 | goto check_rescan; | 936 | goto check_rescan; |
1216 | } | 937 | } |
1217 | update_all = true; | ||
1218 | put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor, true); | ||
1219 | |||
1220 | need_update = true; | 938 | need_update = true; |
1221 | reload_dir = false; | 939 | reload_dir = false; |
1222 | } | 940 | } |
941 | if(need_update) { | ||
942 | tc.selected_item = gui_synclist_get_selected_item_position(&tree_lists); | ||
943 | need_update=false; | ||
944 | if ( numentries > 0 ) { | ||
945 | /* Voice the file if changed */ | ||
946 | if(lasti != tc.selected_item || restore) { | ||
947 | lasti = tc.selected_item; | ||
948 | thumbnail_time = -1; /* Cancel whatever we were | ||
949 | about to say */ | ||
950 | |||
951 | /* Directory? */ | ||
952 | if (dircache[tc.selected_item].attr & ATTR_DIRECTORY) | ||
953 | { | ||
954 | /* play directory thumbnail */ | ||
955 | switch (global_settings.talk_dir) { | ||
956 | case 1: /* dirs as numbers */ | ||
957 | talk_id(VOICE_DIR, false); | ||
958 | talk_number(tc.selected_item+1, true); | ||
959 | break; | ||
1223 | 960 | ||
1224 | if ( (numentries > 0) && need_update) { | 961 | case 2: /* dirs spelled */ |
1225 | i = tc.dirstart+tc.dircursor; | 962 | talk_spell(dircache[tc.selected_item].name, |
1226 | 963 | false); | |
1227 | /* if MP3 filter is on, cut off the extension */ | 964 | break; |
1228 | if(lasti!=i || restore) { | ||
1229 | char* name; | ||
1230 | int attr = 0; | ||
1231 | |||
1232 | if (id3db) | ||
1233 | name = ((char**)tc.dircache)[lasti * tc.dentry_size]; | ||
1234 | else { | ||
1235 | struct entry* dc = tc.dircache; | ||
1236 | struct entry* e = &dc[lasti]; | ||
1237 | name = e->name; | ||
1238 | attr = e->attr; | ||
1239 | } | ||
1240 | |||
1241 | lcd_stop_scroll(); | ||
1242 | |||
1243 | /* So if lastdircursor and dircursor differ, and then full | ||
1244 | screen was not refreshed, restore the previous line */ | ||
1245 | if ((lastdircursor != tc.dircursor) && !update_all ) { | ||
1246 | showfileline(lastdircursor, name, attr, false); /* no scroll */ | ||
1247 | } | ||
1248 | lasti=i; | ||
1249 | lastdircursor=tc.dircursor; | ||
1250 | thumbnail_time = -1; /* cancel whatever we were about to say */ | ||
1251 | |||
1252 | if (id3db) | ||
1253 | name = ((char**)tc.dircache)[lasti * tc.dentry_size]; | ||
1254 | else { | ||
1255 | struct entry* dc = tc.dircache; | ||
1256 | struct entry* e = &dc[lasti]; | ||
1257 | name = e->name; | ||
1258 | attr = e->attr; | ||
1259 | } | ||
1260 | showfileline(tc.dircursor, name, attr, true); /* scroll please */ | ||
1261 | need_update = true; | ||
1262 | |||
1263 | if (dircache[i].attr & ATTR_DIRECTORY) /* directory? */ | ||
1264 | { | ||
1265 | /* play directory thumbnail */ | ||
1266 | switch (global_settings.talk_dir) { | ||
1267 | case 1: /* dirs as numbers */ | ||
1268 | talk_id(VOICE_DIR, false); | ||
1269 | talk_number(i+1, true); | ||
1270 | break; | ||
1271 | |||
1272 | case 2: /* dirs spelled */ | ||
1273 | talk_spell(dircache[i].name, false); | ||
1274 | break; | ||
1275 | 965 | ||
1276 | case 3: /* thumbnail clip */ | 966 | case 3: /* thumbnail clip */ |
1277 | /* "schedule" a thumbnail, to have a little dalay */ | 967 | /* "schedule" a thumbnail, to have a little |
1278 | thumbnail_time = current_tick + HOVER_DELAY; | 968 | delay */ |
1279 | break; | 969 | thumbnail_time = current_tick + HOVER_DELAY; |
970 | break; | ||
1280 | 971 | ||
1281 | default: | 972 | default: |
1282 | break; | 973 | break; |
974 | } | ||
1283 | } | 975 | } |
1284 | } | 976 | else /* file */ |
1285 | else /* file */ | 977 | { |
1286 | { | 978 | switch (global_settings.talk_file) { |
1287 | switch (global_settings.talk_file) { | 979 | case 1: /* files as numbers */ |
1288 | case 1: /* files as numbers */ | 980 | ft_play_filenumber( |
1289 | ft_play_filenumber(i-tc.dirsindir+1, | 981 | tc.selected_item-tc.dirsindir+1, |
1290 | dircache[i].attr & TREE_ATTR_MASK); | 982 | dircache[tc.selected_item].attr & |
1291 | break; | 983 | TREE_ATTR_MASK); |
984 | break; | ||
1292 | 985 | ||
1293 | case 2: /* files spelled */ | 986 | case 2: /* files spelled */ |
1294 | talk_spell(dircache[i].name, false); | 987 | talk_spell(dircache[tc.selected_item].name, |
1295 | break; | 988 | false); |
989 | break; | ||
1296 | 990 | ||
1297 | case 3: /* thumbnail clip */ | 991 | case 3: /* thumbnail clip */ |
1298 | /* "schedule" a thumbnail, to have a little delay */ | 992 | /* "schedule" a thumbnail, to have a little |
1299 | if (dircache[i].attr & TREE_ATTR_THUMBNAIL) | 993 | delay */ |
1300 | thumbnail_time = current_tick + HOVER_DELAY; | 994 | if (dircache[tc.selected_item].attr & |
1301 | else | 995 | TREE_ATTR_THUMBNAIL) |
1302 | /* spell the number as fallback */ | 996 | thumbnail_time = current_tick + HOVER_DELAY; |
1303 | talk_spell(dircache[i].name, false); | 997 | else |
1304 | break; | 998 | /* spell the number as fallback */ |
999 | talk_spell(dircache[tc.selected_item].name, | ||
1000 | false); | ||
1001 | break; | ||
1305 | 1002 | ||
1306 | default: | 1003 | default: |
1307 | break; | 1004 | break; |
1005 | } | ||
1308 | } | 1006 | } |
1309 | } | 1007 | } |
1310 | } | 1008 | } |
1311 | } | 1009 | } |
1312 | |||
1313 | if(need_update) { | ||
1314 | lcd_update(); | ||
1315 | |||
1316 | need_update = false; | ||
1317 | update_all = false; | ||
1318 | } | ||
1319 | } | 1010 | } |
1320 | 1011 | ||
1321 | return true; | 1012 | return true; |
@@ -1369,7 +1060,7 @@ static bool add_dir(char* dirname, int len, int fd) | |||
1369 | int x = strlen(entry->d_name); | 1060 | int x = strlen(entry->d_name); |
1370 | unsigned int i; | 1061 | unsigned int i; |
1371 | char *cp = strrchr(entry->d_name,'.'); | 1062 | char *cp = strrchr(entry->d_name,'.'); |
1372 | 1063 | ||
1373 | if (cp) { | 1064 | if (cp) { |
1374 | cp++; | 1065 | cp++; |
1375 | 1066 | ||
@@ -1379,6 +1070,7 @@ static bool add_dir(char* dirname, int len, int fd) | |||
1379 | if (!strcasecmp(cp, filetypes[i].extension)) | 1070 | if (!strcasecmp(cp, filetypes[i].extension)) |
1380 | { | 1071 | { |
1381 | char buf[8]; | 1072 | char buf[8]; |
1073 | int i; | ||
1382 | write(fd, dirname, strlen(dirname)); | 1074 | write(fd, dirname, strlen(dirname)); |
1383 | write(fd, "/", 1); | 1075 | write(fd, "/", 1); |
1384 | write(fd, entry->d_name, x); | 1076 | write(fd, entry->d_name, x); |
@@ -1387,8 +1079,11 @@ static bool add_dir(char* dirname, int len, int fd) | |||
1387 | plsize++; | 1079 | plsize++; |
1388 | snprintf(buf, sizeof buf, "%d", plsize); | 1080 | snprintf(buf, sizeof buf, "%d", plsize); |
1389 | #ifdef HAVE_LCD_BITMAP | 1081 | #ifdef HAVE_LCD_BITMAP |
1390 | lcd_puts(0,4,buf); | 1082 | for(i = 0;i < NB_SCREENS;++i) |
1391 | lcd_update(); | 1083 | { |
1084 | screens[i].puts(0,4,buf); | ||
1085 | screens[i].update(); | ||
1086 | } | ||
1392 | #else | 1087 | #else |
1393 | x = 10; | 1088 | x = 10; |
1394 | if (plsize > 999) | 1089 | if (plsize > 999) |
@@ -1401,7 +1096,8 @@ static bool add_dir(char* dirname, int len, int fd) | |||
1401 | x=9; | 1096 | x=9; |
1402 | } | 1097 | } |
1403 | } | 1098 | } |
1404 | lcd_puts(x,0,buf); | 1099 | for(i = 0;i < NB_SCREENS;++i) |
1100 | screens[i].puts(x,0,buf); | ||
1405 | #endif | 1101 | #endif |
1406 | break; | 1102 | break; |
1407 | } | 1103 | } |
@@ -1418,16 +1114,20 @@ static bool add_dir(char* dirname, int len, int fd) | |||
1418 | bool create_playlist(void) | 1114 | bool create_playlist(void) |
1419 | { | 1115 | { |
1420 | int fd; | 1116 | int fd; |
1117 | int i; | ||
1421 | char filename[MAX_PATH]; | 1118 | char filename[MAX_PATH]; |
1422 | 1119 | ||
1423 | snprintf(filename, sizeof filename, "%s.m3u", | 1120 | snprintf(filename, sizeof filename, "%s.m3u", |
1424 | tc.currdir[1] ? tc.currdir : "/root"); | 1121 | tc.currdir[1] ? tc.currdir : "/root"); |
1425 | 1122 | for(i = 0;i < NB_SCREENS;++i) | |
1426 | lcd_clear_display(); | 1123 | { |
1427 | lcd_puts(0,0,str(LANG_CREATING)); | 1124 | screens[i].clear_display(); |
1428 | lcd_puts_scroll(0,1,filename); | 1125 | screens[i].puts(0,0,str(LANG_CREATING)); |
1429 | lcd_update(); | 1126 | screens[i].puts_scroll(0,1,filename); |
1430 | 1127 | #if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR) | |
1128 | screens[i].update(); | ||
1129 | #endif | ||
1130 | } | ||
1431 | fd = creat(filename,0); | 1131 | fd = creat(filename,0); |
1432 | if (fd < 0) | 1132 | if (fd < 0) |
1433 | return false; | 1133 | return false; |
@@ -1435,7 +1135,7 @@ bool create_playlist(void) | |||
1435 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | 1135 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
1436 | cpu_boost(true); | 1136 | cpu_boost(true); |
1437 | #endif | 1137 | #endif |
1438 | 1138 | ||
1439 | snprintf(filename, sizeof(filename), "%s", | 1139 | snprintf(filename, sizeof(filename), "%s", |
1440 | tc.currdir[1] ? tc.currdir : "/"); | 1140 | tc.currdir[1] ? tc.currdir : "/"); |
1441 | plsize = 0; | 1141 | plsize = 0; |
@@ -1445,7 +1145,7 @@ bool create_playlist(void) | |||
1445 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | 1145 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
1446 | cpu_boost(false); | 1146 | cpu_boost(false); |
1447 | #endif | 1147 | #endif |
1448 | 1148 | ||
1449 | sleep(HZ); | 1149 | sleep(HZ); |
1450 | 1150 | ||
1451 | return true; | 1151 | return true; |
@@ -1460,12 +1160,10 @@ bool rockbox_browse(const char *root, int dirfilter) | |||
1460 | memcpy(tc.currdir, root, sizeof(tc.currdir)); | 1160 | memcpy(tc.currdir, root, sizeof(tc.currdir)); |
1461 | start_wps = false; | 1161 | start_wps = false; |
1462 | tc.dirfilter = &dirfilter; | 1162 | tc.dirfilter = &dirfilter; |
1463 | 1163 | ||
1464 | dirbrowse(); | 1164 | dirbrowse(); |
1465 | 1165 | ||
1466 | tc = backup; | 1166 | tc = backup; |
1467 | reload_dir = true; | ||
1468 | |||
1469 | return false; | 1167 | return false; |
1470 | } | 1168 | } |
1471 | 1169 | ||
@@ -1474,7 +1172,7 @@ void tree_init(void) | |||
1474 | /* We copy the settings value in case it is changed by the user. We can't | 1172 | /* We copy the settings value in case it is changed by the user. We can't |
1475 | use it until the next reboot. */ | 1173 | use it until the next reboot. */ |
1476 | max_files = global_settings.max_files_in_dir; | 1174 | max_files = global_settings.max_files_in_dir; |
1477 | 1175 | ||
1478 | /* initialize tree context struct */ | 1176 | /* initialize tree context struct */ |
1479 | memset(&tc, 0, sizeof(tc)); | 1177 | memset(&tc, 0, sizeof(tc)); |
1480 | tc.dirfilter = &global_settings.dirfilter; | 1178 | tc.dirfilter = &global_settings.dirfilter; |
@@ -1498,7 +1196,7 @@ void bookmark_play(char *resume_file, int index, int offset, int seed, | |||
1498 | { | 1196 | { |
1499 | /* Playlist playback */ | 1197 | /* Playlist playback */ |
1500 | char* slash; | 1198 | char* slash; |
1501 | // check that the file exists | 1199 | /* check that the file exists */ |
1502 | int fd = open(resume_file, O_RDONLY); | 1200 | int fd = open(resume_file, O_RDONLY); |
1503 | if(fd<0) | 1201 | if(fd<0) |
1504 | return; | 1202 | return; |
@@ -1538,7 +1236,7 @@ void bookmark_play(char *resume_file, int index, int offset, int seed, | |||
1538 | if ((strcmp(strrchr(playlist_peek(index) + 1,'/') + 1, | 1236 | if ((strcmp(strrchr(playlist_peek(index) + 1,'/') + 1, |
1539 | filename))) | 1237 | filename))) |
1540 | { | 1238 | { |
1541 | for ( i=0; i < playlist_amount(); i++ ) | 1239 | for ( i=0; i < playlist_amount(); i++ ) |
1542 | { | 1240 | { |
1543 | if ((strcmp(strrchr(playlist_peek(i) + 1,'/') + 1, | 1241 | if ((strcmp(strrchr(playlist_peek(i) + 1,'/') + 1, |
1544 | filename)) == 0) | 1242 | filename)) == 0) |
@@ -1599,7 +1297,7 @@ int ft_play_dirname(int start_index) | |||
1599 | } | 1297 | } |
1600 | 1298 | ||
1601 | close(fd); | 1299 | close(fd); |
1602 | 1300 | ||
1603 | DEBUGF("Found: %s\n", dirname_mp3_filename); | 1301 | DEBUGF("Found: %s\n", dirname_mp3_filename); |
1604 | 1302 | ||
1605 | talk_file(dirname_mp3_filename, false); | 1303 | talk_file(dirname_mp3_filename, false); |
@@ -1639,9 +1337,7 @@ void tree_flush(void) | |||
1639 | if (global_settings.dircache) | 1337 | if (global_settings.dircache) |
1640 | { | 1338 | { |
1641 | if (dircache_is_enabled()) | 1339 | if (dircache_is_enabled()) |
1642 | { | ||
1643 | global_settings.dircache_size = dircache_get_cache_size(); | 1340 | global_settings.dircache_size = dircache_get_cache_size(); |
1644 | } | ||
1645 | dircache_disable(); | 1341 | dircache_disable(); |
1646 | } | 1342 | } |
1647 | else | 1343 | else |
@@ -1659,21 +1355,27 @@ void tree_restore(void) | |||
1659 | #ifdef HAVE_DIRCACHE | 1355 | #ifdef HAVE_DIRCACHE |
1660 | if (global_settings.dircache) | 1356 | if (global_settings.dircache) |
1661 | { | 1357 | { |
1662 | int font_w, font_h; | ||
1663 | |||
1664 | /* Print "Scanning disk..." to the display. */ | 1358 | /* Print "Scanning disk..." to the display. */ |
1665 | lcd_getstringsize("A", &font_w, &font_h); | 1359 | int i; |
1666 | lcd_putsxy((LCD_WIDTH/2) - ((strlen(str(LANG_DIRCACHE_BUILDING))*font_w)/2), | 1360 | for(i = 0;i < NB_SCREENS;++i) |
1667 | LCD_HEIGHT-font_h*3, str(LANG_DIRCACHE_BUILDING)); | 1361 | { |
1668 | lcd_update(); | 1362 | screens[i].putsxy((LCD_WIDTH/2) - |
1669 | 1363 | ((strlen(str(LANG_DIRCACHE_BUILDING)) * | |
1364 | screens[i].char_width)/2), | ||
1365 | LCD_HEIGHT-screens[i].char_height*3, | ||
1366 | str(LANG_DIRCACHE_BUILDING)); | ||
1367 | screens[i].update(); | ||
1368 | } | ||
1670 | dircache_build(global_settings.dircache_size); | 1369 | dircache_build(global_settings.dircache_size); |
1671 | |||
1672 | /* Clean the text when we are done. */ | 1370 | /* Clean the text when we are done. */ |
1673 | lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); | 1371 | for(i=0;i<NB_SCREENS;++i) |
1674 | lcd_fillrect(0, LCD_HEIGHT-font_h*3, LCD_WIDTH, font_h); | 1372 | { |
1675 | lcd_set_drawmode(DRMODE_SOLID); | 1373 | screens[i].set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); |
1676 | lcd_update(); | 1374 | screens[i].fillrect(0, LCD_HEIGHT-screens[i].char_height*3, |
1375 | LCD_WIDTH, screens[i].char_height); | ||
1376 | screens[i].set_drawmode(DRMODE_SOLID); | ||
1377 | screens[i].update(); | ||
1378 | } | ||
1677 | } | 1379 | } |
1678 | #endif | 1380 | #endif |
1679 | } | 1381 | } |