summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjörn Stenberg <bjorn@haxx.se>2003-01-09 00:55:00 +0000
committerBjörn Stenberg <bjorn@haxx.se>2003-01-09 00:55:00 +0000
commitc78e1b07fead2b5861fb6fc4c9ba130660fb323f (patch)
tree267406ed9e1e3c68238f688934d2088a1fa7c8e3
parent0e342181c3f96890506aa8720ac2d680b97c12e4 (diff)
downloadrockbox-c78e1b07fead2b5861fb6fc4c9ba130660fb323f.tar.gz
rockbox-c78e1b07fead2b5861fb6fc4c9ba130660fb323f.zip
The much-anticipated queue patch by Hardeep Sidhu. Queue a file by holding down PLAY on it while playing other music.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3040 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/applimits.h1
-rw-r--r--apps/lang/english.lang15
-rw-r--r--apps/playlist.c340
-rw-r--r--apps/playlist.h16
-rw-r--r--apps/settings.c65
-rw-r--r--apps/settings.h7
-rw-r--r--apps/tree.c88
-rw-r--r--apps/wps.c12
-rw-r--r--uisimulator/x11/file.h5
-rw-r--r--uisimulator/x11/io.c26
10 files changed, 469 insertions, 106 deletions
diff --git a/apps/applimits.h b/apps/applimits.h
index a18544e87d..6372dac924 100644
--- a/apps/applimits.h
+++ b/apps/applimits.h
@@ -23,5 +23,6 @@
23#define AVERAGE_FILENAME_LENGTH 40 23#define AVERAGE_FILENAME_LENGTH 40
24#define MAX_DIR_LEVELS 10 24#define MAX_DIR_LEVELS 10
25#define MAX_PLAYLIST_SIZE 10000 25#define MAX_PLAYLIST_SIZE 10000
26#define MAX_QUEUED_FILES 100
26 27
27#endif 28#endif
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index e358474477..97435bb36c 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -1221,3 +1221,18 @@ id: LANG_BATTERY_CAPACITY
1221desc: in settings_menu 1221desc: in settings_menu
1222eng: "Battery Capacity" 1222eng: "Battery Capacity"
1223new: 1223new:
1224
1225id: LANG_QUEUE_QUEUED
1226desc: queued track name %s
1227eng: "Queued: %s"
1228new:
1229
1230id: LANG_QUEUE_TOTAL
1231desc: number of queued tracks %d
1232eng: "Total queued: %d"
1233new:
1234
1235id: LANG_QUEUE_FULL
1236desc: queue buffer full
1237eng: "Queue buffer full"
1238new:
diff --git a/apps/playlist.c b/apps/playlist.c
index 38eca09fc9..0a99cb91f4 100644
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -21,7 +21,7 @@
21#include <stdlib.h> 21#include <stdlib.h>
22#include <string.h> 22#include <string.h>
23#include "playlist.h" 23#include "playlist.h"
24#include <file.h> 24#include "file.h"
25#include "sprintf.h" 25#include "sprintf.h"
26#include "debug.h" 26#include "debug.h"
27#include "mpeg.h" 27#include "mpeg.h"
@@ -39,6 +39,7 @@
39 39
40static struct playlist_info playlist; 40static struct playlist_info playlist;
41 41
42#define QUEUE_FILE ROCKBOX_DIR "/.queue_file"
42#define PLAYLIST_BUFFER_SIZE (AVERAGE_FILENAME_LENGTH*MAX_FILES_IN_DIR) 43#define PLAYLIST_BUFFER_SIZE (AVERAGE_FILENAME_LENGTH*MAX_FILES_IN_DIR)
43 44
44static unsigned char playlist_buffer[PLAYLIST_BUFFER_SIZE]; 45static unsigned char playlist_buffer[PLAYLIST_BUFFER_SIZE];
@@ -46,64 +47,153 @@ static int playlist_end_pos = 0;
46 47
47static char now_playing[MAX_PATH+1]; 48static char now_playing[MAX_PATH+1];
48 49
49void playlist_clear(void) 50/*
51 * remove any files and indices associated with the playlist
52 */
53static void empty_playlist(bool queue_resume)
50{ 54{
51 playlist_end_pos = 0; 55 int fd;
52 playlist_buffer[0] = 0; 56
57 playlist.filename[0] = '\0';
58 playlist.index = 0;
59 playlist.queue_index = 0;
60 playlist.last_queue_index = 0;
61 playlist.amount = 0;
62 playlist.num_queued = 0;
63 playlist.start_queue = 0;
64
65 if (!queue_resume)
66 {
67 /* start with fresh queue file when starting new playlist */
68 remove(QUEUE_FILE);
69 fd = creat(QUEUE_FILE, 0);
70 if (fd > 0)
71 close(fd);
72 }
53} 73}
54 74
55int playlist_add(char *filename) 75/* update queue list after resume */
76static void add_indices_to_queuelist(int seek)
56{ 77{
57 int len = strlen(filename); 78 int nread;
79 int fd = -1;
80 int i = seek;
81 int count = 0;
82 bool store_index;
83 char buf[MAX_PATH];
58 84
59 if(len+2 > PLAYLIST_BUFFER_SIZE - playlist_end_pos) 85 unsigned char *p = buf;
60 return -1;
61 86
62 strcpy(&playlist_buffer[playlist_end_pos], filename); 87 fd = open(QUEUE_FILE, O_RDONLY);
63 playlist_end_pos += len; 88 if(fd < 0)
64 playlist_buffer[playlist_end_pos++] = '\n'; 89 return;
65 playlist_buffer[playlist_end_pos] = '\0'; 90
66 return 0; 91 nread = lseek(fd, seek, SEEK_SET);
92 if (nread < 0)
93 return;
94
95 store_index = true;
96
97 while(1)
98 {
99 nread = read(fd, buf, MAX_PATH);
100 if(nread <= 0)
101 break;
102
103 p = buf;
104
105 for(count=0; count < nread; count++,p++) {
106 if(*p == '\n')
107 store_index = true;
108 else if(store_index)
109 {
110 store_index = false;
111
112 playlist.queue_indices[playlist.last_queue_index] = i+count;
113 playlist.last_queue_index =
114 (playlist.last_queue_index + 1) % MAX_QUEUED_FILES;
115 playlist.num_queued++;
116 }
117 }
118
119 i += count;
120 }
67} 121}
68 122
69static int get_next_index(int steps) 123static int get_next_index(int steps, bool *queue)
70{ 124{
71 int current_index = playlist.index; 125 int current_index = playlist.index;
72 int next_index = -1; 126 int next_index = -1;
73 127
128 if (global_settings.repeat_mode == REPEAT_ONE)
129 steps = 0;
130 else if (steps >= 0)
131 steps -= playlist.start_queue;
132
133 if (steps >= 0 && playlist.num_queued > 0 &&
134 playlist.num_queued - steps > 0)
135 *queue = true;
136 else
137 {
138 *queue = false;
139 if (playlist.num_queued)
140 {
141 if (steps >= 0)
142 steps -= (playlist.num_queued - 1);
143 else if (!playlist.start_queue)
144 steps += 1;
145 }
146 }
147
74 switch (global_settings.repeat_mode) 148 switch (global_settings.repeat_mode)
75 { 149 {
76 case REPEAT_OFF: 150 case REPEAT_OFF:
77 if (current_index < playlist.first_index) 151 if (*queue)
78 current_index += playlist.amount; 152 next_index = (playlist.queue_index+steps) % MAX_QUEUED_FILES;
79 current_index -= playlist.first_index;
80
81 next_index = current_index+steps;
82 if ((next_index < 0) || (next_index >= playlist.amount))
83 next_index = -1;
84 else 153 else
85 next_index = (next_index+playlist.first_index)%playlist.amount; 154 {
155 if (current_index < playlist.first_index)
156 current_index += playlist.amount;
157 current_index -= playlist.first_index;
158
159 next_index = current_index+steps;
160 if ((next_index < 0) || (next_index >= playlist.amount))
161 next_index = -1;
162 else
163 next_index = (next_index+playlist.first_index) %
164 playlist.amount;
165 }
86 break; 166 break;
87 167
88 case REPEAT_ONE: 168 case REPEAT_ONE:
89 next_index = current_index; 169 if (*queue && !playlist.start_queue)
170 next_index = playlist.queue_index;
171 else
172 {
173 next_index = current_index;
174 *queue = false;
175 }
90 break; 176 break;
91 177
92 case REPEAT_ALL: 178 case REPEAT_ALL:
93 default: 179 default:
94 next_index = (current_index+steps) % playlist.amount; 180 if (*queue)
95 while (next_index < 0) 181 next_index = (playlist.queue_index+steps) % MAX_QUEUED_FILES;
96 next_index += playlist.amount; 182 else
183 {
184 next_index = (current_index+steps) % playlist.amount;
185 while (next_index < 0)
186 next_index += playlist.amount;
187 }
97 break; 188 break;
98 } 189 }
99 190
100 return next_index; 191 return next_index;
101} 192}
102 193
103/* the mpeg thread might ask us */
104int playlist_amount(void) 194int playlist_amount(void)
105{ 195{
106 return playlist.amount; 196 return playlist.amount + playlist.num_queued;
107} 197}
108 198
109int playlist_first_index(void) 199int playlist_first_index(void)
@@ -111,6 +201,36 @@ int playlist_first_index(void)
111 return playlist.first_index; 201 return playlist.first_index;
112} 202}
113 203
204int playlist_get_resume_info(int *resume_index, int *queue_resume,
205 int *queue_resume_index)
206{
207 int result = 0;
208
209 *resume_index = playlist.index;
210
211 if (playlist.num_queued > 0)
212 {
213 if (global_settings.save_queue_resume)
214 {
215 *queue_resume_index =
216 playlist.queue_indices[playlist.queue_index];
217 if (playlist.start_queue)
218 *queue_resume = QUEUE_BEGIN_PLAYLIST;
219 else
220 *queue_resume = QUEUE_BEGIN_QUEUE;
221 }
222 else if (!playlist.start_queue)
223 {
224 *queue_resume = QUEUE_OFF;
225 result = -1;
226 }
227 }
228 else
229 *queue_resume = QUEUE_OFF;
230
231 return result;
232}
233
114char *playlist_name(char *buf, int buf_size) 234char *playlist_name(char *buf, int buf_size)
115{ 235{
116 char *sep; 236 char *sep;
@@ -128,11 +248,101 @@ char *playlist_name(char *buf, int buf_size)
128 return buf; 248 return buf;
129} 249}
130 250
251void playlist_clear(void)
252{
253 playlist_end_pos = 0;
254 playlist_buffer[0] = 0;
255}
256
257int playlist_add(char *filename)
258{
259 int len = strlen(filename);
260
261 if(len+2 > PLAYLIST_BUFFER_SIZE - playlist_end_pos)
262 return -1;
263
264 strcpy(&playlist_buffer[playlist_end_pos], filename);
265 playlist_end_pos += len;
266 playlist_buffer[playlist_end_pos++] = '\n';
267 playlist_buffer[playlist_end_pos] = '\0';
268 return 0;
269}
270
271/* Add track to queue file */
272int queue_add(char *filename)
273{
274 int fd, seek, result;
275 int len = strlen(filename);
276
277 if(playlist.num_queued >= MAX_QUEUED_FILES)
278 return -1;
279
280 fd = open(QUEUE_FILE, O_WRONLY);
281 if (fd < 0)
282 return -1;
283
284 seek = lseek(fd, 0, SEEK_END);
285 if (seek < 0)
286 {
287 close(fd);
288 return -1;
289 }
290
291 filename[len] = '\n';
292 result = write(fd, filename, len+1);
293 if (result < 0)
294 {
295 close(fd);
296 return -1;
297 }
298 filename[len] = '\0';
299
300 close(fd);
301
302 if (playlist.num_queued <= 0)
303 playlist.start_queue = 1;
304
305 playlist.queue_indices[playlist.last_queue_index] = seek;
306 playlist.last_queue_index =
307 (playlist.last_queue_index + 1) % MAX_QUEUED_FILES;
308 playlist.num_queued++;
309
310 mpeg_flush_and_reload_tracks();
311
312 return playlist.num_queued;
313}
314
131int playlist_next(int steps) 315int playlist_next(int steps)
132{ 316{
133 playlist.index = get_next_index(steps); 317 bool queue;
318 int index = get_next_index(steps, &queue);
134 319
135 return playlist.index; 320 if (queue)
321 {
322 int queue_diff = index - playlist.queue_index;
323 if (queue_diff < 0)
324 queue_diff += MAX_QUEUED_FILES;
325
326 playlist.num_queued -= queue_diff;
327 playlist.queue_index = index;
328 playlist.start_queue = 0;
329 }
330 else
331 {
332 playlist.index = index;
333 if (playlist.num_queued > 0 && !playlist.start_queue)
334 {
335 if (steps >= 0)
336 {
337 playlist.queue_index = playlist.last_queue_index;
338 playlist.num_queued = 0;
339 }
340 else
341 playlist.start_queue = true;
342 }
343 }
344
345 return index;
136} 346}
137 347
138char* playlist_peek(int steps) 348char* playlist_peek(int steps)
@@ -145,24 +355,19 @@ char* playlist_peek(int steps)
145 char dir_buf[MAX_PATH+1]; 355 char dir_buf[MAX_PATH+1];
146 char *dir_end; 356 char *dir_end;
147 int index; 357 int index;
358 bool queue;
148 359
149 index = get_next_index(steps); 360 index = get_next_index(steps, &queue);
150 if (index >= 0) 361 if (index < 0)
151 seek = playlist.indices[index];
152 else
153 return NULL; 362 return NULL;
154 363
155 if(playlist.in_ram) 364 if (queue)
156 { 365 {
157 buf = playlist_buffer + seek; 366 seek = playlist.queue_indices[index];
158 max = playlist_end_pos - seek; 367 fd = open(QUEUE_FILE, O_RDONLY);
159 }
160 else
161 {
162 fd = open(playlist.filename, O_RDONLY);
163 if(-1 != fd) 368 if(-1 != fd)
164 { 369 {
165 buf = playlist_buffer; 370 buf = dir_buf;
166 lseek(fd, seek, SEEK_SET); 371 lseek(fd, seek, SEEK_SET);
167 max = read(fd, buf, MAX_PATH); 372 max = read(fd, buf, MAX_PATH);
168 close(fd); 373 close(fd);
@@ -170,6 +375,29 @@ char* playlist_peek(int steps)
170 else 375 else
171 return NULL; 376 return NULL;
172 } 377 }
378 else
379 {
380 seek = playlist.indices[index];
381
382 if(playlist.in_ram)
383 {
384 buf = playlist_buffer + seek;
385 max = playlist_end_pos - seek;
386 }
387 else
388 {
389 fd = open(playlist.filename, O_RDONLY);
390 if(-1 != fd)
391 {
392 buf = playlist_buffer;
393 lseek(fd, seek, SEEK_SET);
394 max = read(fd, buf, MAX_PATH);
395 close(fd);
396 }
397 else
398 return NULL;
399 }
400 }
173 401
174 /* Zero-terminate the file name */ 402 /* Zero-terminate the file name */
175 seek=0; 403 seek=0;
@@ -260,11 +488,13 @@ int play_list(char *dir, /* "current directory" */
260 playlist AFTER the shuffle */ 488 playlist AFTER the shuffle */
261 int start_offset, /* offset in the file */ 489 int start_offset, /* offset in the file */
262 int random_seed, /* used for shuffling */ 490 int random_seed, /* used for shuffling */
263 int first_index ) /* first index of playlist */ 491 int first_index, /* first index of playlist */
492 int queue_resume, /* resume queue list? */
493 int queue_resume_index ) /* queue list seek pos */
264{ 494{
265 char *sep=""; 495 char *sep="";
266 int dirlen; 496 int dirlen;
267 empty_playlist(); 497 empty_playlist(queue_resume);
268 498
269 playlist.index = start_index; 499 playlist.index = start_index;
270 playlist.first_index = first_index; 500 playlist.first_index = first_index;
@@ -343,6 +573,18 @@ int play_list(char *dir, /* "current directory" */
343 } 573 }
344 } 574 }
345 575
576 /* update the queue indices */
577 if (queue_resume)
578 {
579 add_indices_to_queuelist(queue_resume_index);
580
581 if (queue_resume == QUEUE_BEGIN_PLAYLIST)
582 {
583 playlist.start_queue = 1;
584 playlist.index++; /* so we begin at the correct track */
585 }
586 }
587
346 if(!playlist.in_ram) { 588 if(!playlist.in_ram) {
347 lcd_puts(0,0,str(LANG_PLAYLIST_PLAY)); 589 lcd_puts(0,0,str(LANG_PLAYLIST_PLAY));
348 status_draw(); 590 status_draw();
@@ -355,16 +597,6 @@ int play_list(char *dir, /* "current directory" */
355} 597}
356 598
357/* 599/*
358 * remove any filename and indices associated with the playlist
359 */
360void empty_playlist(void)
361{
362 playlist.filename[0] = '\0';
363 playlist.index = 0;
364 playlist.amount = 0;
365}
366
367/*
368 * calculate track offsets within a playlist file 600 * calculate track offsets within a playlist file
369 */ 601 */
370void add_indices_to_playlist(void) 602void add_indices_to_playlist(void)
diff --git a/apps/playlist.h b/apps/playlist.h
index 47422a40a5..57a23f2a8f 100644
--- a/apps/playlist.h
+++ b/apps/playlist.h
@@ -36,6 +36,13 @@ struct playlist_info
36 int seed; /* random seed */ 36 int seed; /* random seed */
37 int amount; /* number of tracks in the index */ 37 int amount; /* number of tracks in the index */
38 bool in_ram; /* True if the playlist is RAM-based */ 38 bool in_ram; /* True if the playlist is RAM-based */
39
40 /* Queue function */
41 int queue_indices[MAX_QUEUED_FILES]; /* array of queue indices */
42 int last_queue_index; /* index of last queued track */
43 int queue_index; /* index of current playing queued track */
44 int num_queued; /* number of songs queued */
45 int start_queue; /* the first song was queued */
39}; 46};
40 47
41extern struct playlist_info playlist; 48extern struct playlist_info playlist;
@@ -43,18 +50,23 @@ extern bool playlist_shuffle;
43 50
44int play_list(char *dir, char *file, int start_index, 51int play_list(char *dir, char *file, int start_index,
45 bool shuffled_index, int start_offset, 52 bool shuffled_index, int start_offset,
46 int random_seed, int first_index); 53 int random_seed, int first_index, int queue_resume,
54 int queue_resume_index);
47char* playlist_peek(int steps); 55char* playlist_peek(int steps);
48char* playlist_name(char *name, int name_size); 56char* playlist_name(char *name, int name_size);
49int playlist_next(int steps); 57int playlist_next(int steps);
50void randomise_playlist( unsigned int seed ); 58void randomise_playlist( unsigned int seed );
51void sort_playlist(bool start_current); 59void sort_playlist(bool start_current);
52void empty_playlist(void);
53void add_indices_to_playlist(void); 60void add_indices_to_playlist(void);
54void playlist_clear(void); 61void playlist_clear(void);
55int playlist_add(char *filename); 62int playlist_add(char *filename);
63int queue_add(char *filename);
56int playlist_amount(void); 64int playlist_amount(void);
57int playlist_first_index(void); 65int playlist_first_index(void);
66int playlist_get_resume_info(int *resume_index, int *queue_resume,
67 int *queue_resume_index);
68
69enum { QUEUE_OFF, QUEUE_BEGIN_QUEUE, QUEUE_BEGIN_PLAYLIST, NUM_QUEUE_MODES };
58 70
59#endif /* __PLAYLIST_H__ */ 71#endif /* __PLAYLIST_H__ */
60 72
diff --git a/apps/settings.c b/apps/settings.c
index 5a532bf95e..717443f6cd 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -92,14 +92,10 @@ offset abs
920x12 0x26 <(int) Resume playlist index, or -1 if no playlist resume> 920x12 0x26 <(int) Resume playlist index, or -1 if no playlist resume>
930x16 0x2a <(int) Byte offset into resume file> 930x16 0x2a <(int) Byte offset into resume file>
940x1a 0x2e <time until disk spindown> 940x1a 0x2e <time until disk spindown>
950x1b 0x2f <browse current, play selected> 950x1b 0x2f <browse current, play selected, queue_resume>
960x1c 0x30 <peak meter hold timeout (bit 0-4)>, 960x1c 0x30 <peak meter hold timeout (bit 0-4)>,
97 peak_meter_performance (bit 7) 97 peak_meter_performance (bit 7)
980x1d 0x31 <peak meter clip hold timeout (bit 0-4) 980x1d 0x31 <(int) queue resume index>
990x1e 0x32 <peak meter release step size,
100 peak_meter_dbfs (bit 7)
1010x1f 0x33 <peak meter min either in -db or in percent>
1020x20 0x34 <peak meter max either in -db or in percent>
1030x21 0x35 <repeat mode (bit 0-1), rec. channels (bit 2), 990x21 0x35 <repeat mode (bit 0-1), rec. channels (bit 2),
104 mic gain (bit 4-7)> 100 mic gain (bit 4-7)>
1050x22 0x36 <rec. quality (bit 0-2), source (bit 3-4), frequency (bit 5-7)> 1010x22 0x36 <rec. quality (bit 0-2), source (bit 3-4), frequency (bit 5-7)>
@@ -125,7 +121,10 @@ modified unless the header & checksum test fails.
125 121
126 122
127Rest of config block, only saved to disk: 123Rest of config block, only saved to disk:
128 1240xB0 peak meter clip hold timeout (bit 0-4)
1250xB1 peak meter release step size, peak_meter_dbfs (bit 7)
1260xB2 peak meter min either in -db or in percent
1270xB3 peak meter max either in -db or in percent
1290xB4 battery capacity 1280xB4 battery capacity
1300xB5 scroll step in pixels 1290xB5 scroll step in pixels
1310xB6 scroll start and endpoint delay 1300xB6 scroll start and endpoint delay
@@ -330,15 +329,13 @@ int settings_save( void )
330 config_block[0x1a] = (unsigned char)global_settings.disk_spindown; 329 config_block[0x1a] = (unsigned char)global_settings.disk_spindown;
331 config_block[0x1b] = (unsigned char) 330 config_block[0x1b] = (unsigned char)
332 (((global_settings.browse_current & 1)) | 331 (((global_settings.browse_current & 1)) |
333 ((global_settings.play_selected & 1) << 1)); 332 ((global_settings.play_selected & 1) << 1) |
333 ((global_settings.queue_resume & 3) << 2));
334 334
335 config_block[0x1c] = (unsigned char)global_settings.peak_meter_hold; 335 config_block[0x1c] = (unsigned char)global_settings.peak_meter_hold;
336 config_block[0x1d] = (unsigned char)global_settings.peak_meter_clip_hold | 336
337 (global_settings.peak_meter_performance ? 0x80 : 0); 337 memcpy(&config_block[0x1d], &global_settings.queue_resume_index, 4);
338 config_block[0x1e] = global_settings.peak_meter_release | 338
339 (global_settings.peak_meter_dbfs ? 0x80 : 0);
340 config_block[0x1f] = (unsigned char)global_settings.peak_meter_min;
341 config_block[0x20] = (unsigned char)global_settings.peak_meter_max;
342 config_block[0x21] = (unsigned char) 339 config_block[0x21] = (unsigned char)
343 ((global_settings.repeat_mode & 3) | 340 ((global_settings.repeat_mode & 3) |
344 ((global_settings.rec_channels & 1) << 2) | 341 ((global_settings.rec_channels & 1) << 2) |
@@ -369,6 +366,13 @@ int settings_save( void )
369 config_block[0x29]=(unsigned char)(global_settings.topruntime >> 8); 366 config_block[0x29]=(unsigned char)(global_settings.topruntime >> 8);
370 } 367 }
371 368
369 config_block[0xb0] = (unsigned char)global_settings.peak_meter_clip_hold |
370 (global_settings.peak_meter_performance ? 0x80 : 0);
371 config_block[0xb1] = global_settings.peak_meter_release |
372 (global_settings.peak_meter_dbfs ? 0x80 : 0);
373 config_block[0xb2] = (unsigned char)global_settings.peak_meter_min;
374 config_block[0xb3] = (unsigned char)global_settings.peak_meter_max;
375
372 config_block[0xb4]=(global_settings.battery_capacity - 1000) / 50; 376 config_block[0xb4]=(global_settings.battery_capacity - 1000) / 50;
373 config_block[0xb5]=(unsigned char)global_settings.scroll_step; 377 config_block[0xb5]=(unsigned char)global_settings.scroll_step;
374 config_block[0xb6]=(unsigned char)global_settings.scroll_delay; 378 config_block[0xb6]=(unsigned char)global_settings.scroll_delay;
@@ -595,27 +599,15 @@ void settings_load(void)
595 if (config_block[0x1b] != 0xFF) { 599 if (config_block[0x1b] != 0xFF) {
596 global_settings.browse_current = (config_block[0x1b]) & 1; 600 global_settings.browse_current = (config_block[0x1b]) & 1;
597 global_settings.play_selected = (config_block[0x1b] >> 1) & 1; 601 global_settings.play_selected = (config_block[0x1b] >> 1) & 1;
602 global_settings.queue_resume = (config_block[0x1b] >> 2) & 3;
598 } 603 }
599 604
600 if (config_block[0x1c] != 0xFF) 605 if (config_block[0x1c] != 0xFF)
601 global_settings.peak_meter_hold = (config_block[0x1c]) & 0x1f; 606 global_settings.peak_meter_hold = (config_block[0x1c]) & 0x1f;
602 607
603 if (config_block[0x1d] != 0xFF) { 608 if (config_block[0x1d] != 0xFF)
604 global_settings.peak_meter_clip_hold = (config_block[0x1d]) & 0x1f; 609 memcpy(&global_settings.queue_resume_index, &config_block[0x1d],
605 global_settings.peak_meter_performance = 610 4);
606 (config_block[0x1d] & 0x80) != 0;
607 }
608
609 if (config_block[0x1e] != 0xFF) {
610 global_settings.peak_meter_release = config_block[0x1e] & 0x7f;
611 global_settings.peak_meter_dbfs = (config_block[0x1e] & 0x80) != 0;
612 }
613
614 if (config_block[0x1f] != 0xFF)
615 global_settings.peak_meter_min = config_block[0x1f];
616
617 if (config_block[0x20] != 0xFF)
618 global_settings.peak_meter_max = config_block[0x20];
619 611
620 if (config_block[0x21] != 0xFF) 612 if (config_block[0x21] != 0xFF)
621 { 613 {
@@ -652,6 +644,16 @@ void settings_load(void)
652 global_settings.topruntime = 644 global_settings.topruntime =
653 config_block[0x28] | (config_block[0x29] << 8); 645 config_block[0x28] | (config_block[0x29] << 8);
654 646
647 global_settings.peak_meter_clip_hold = (config_block[0xb0]) & 0x1f;
648 global_settings.peak_meter_performance =
649 (config_block[0xb0] & 0x80) != 0;
650
651 global_settings.peak_meter_release = config_block[0xb1] & 0x7f;
652 global_settings.peak_meter_dbfs = (config_block[0xb1] & 0x80) != 0;
653
654 global_settings.peak_meter_min = config_block[0xb2];
655 global_settings.peak_meter_max = config_block[0xb3];
656
655 global_settings.battery_capacity = config_block[0xb4]*50 + 1000; 657 global_settings.battery_capacity = config_block[0xb4]*50 + 1000;
656 658
657 if (config_block[0xb5] != 0xff) 659 if (config_block[0xb5] != 0xff)
@@ -857,6 +859,9 @@ void settings_reset(void) {
857 global_settings.ff_rewind_accel = DEFAULT_FF_REWIND_ACCEL_SETTING; 859 global_settings.ff_rewind_accel = DEFAULT_FF_REWIND_ACCEL_SETTING;
858 global_settings.resume_index = -1; 860 global_settings.resume_index = -1;
859 global_settings.resume_offset = -1; 861 global_settings.resume_offset = -1;
862 global_settings.save_queue_resume = true;
863 global_settings.queue_resume = 0;
864 global_settings.queue_resume_index = -1;
860 global_settings.disk_spindown = 5; 865 global_settings.disk_spindown = 5;
861 global_settings.disk_poweroff = false; 866 global_settings.disk_poweroff = false;
862 global_settings.buffer_margin = 0; 867 global_settings.buffer_margin = 0;
diff --git a/apps/settings.h b/apps/settings.h
index 41f9b803c1..be41ef8ec9 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -94,6 +94,13 @@ struct user_settings
94 int resume_offset; /* byte offset in mp3 file */ 94 int resume_offset; /* byte offset in mp3 file */
95 int resume_seed; /* random seed for playlist shuffle */ 95 int resume_seed; /* random seed for playlist shuffle */
96 int resume_first_index; /* first index of playlist */ 96 int resume_first_index; /* first index of playlist */
97
98 bool save_queue_resume; /* save queued songs for resume */
99 int queue_resume; /* resume queue file?: 0 = no
100 1 = resume at queue index
101 2 = resume at playlist index */
102 int queue_resume_index; /* queue index (seek point in queue file) */
103
97 unsigned char resume_file[MAX_PATH+1]; /* playlist name (or dir) */ 104 unsigned char resume_file[MAX_PATH+1]; /* playlist name (or dir) */
98 unsigned char font_file[MAX_FILENAME+1]; /* last font */ 105 unsigned char font_file[MAX_FILENAME+1]; /* last font */
99 unsigned char wps_file[MAX_FILENAME+1]; /* last wps */ 106 unsigned char wps_file[MAX_FILENAME+1]; /* last wps */
diff --git a/apps/tree.c b/apps/tree.c
index 03de011255..37a791c13c 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -452,6 +452,36 @@ static int showdir(char *path, int start)
452 return filesindir; 452 return filesindir;
453} 453}
454 454
455static void show_queue_display(int queue_count, char *filename)
456{
457#ifdef HAVE_LCD_CHARCELLS
458 lcd_double_height(false);
459#endif
460
461#ifdef HAVE_LCD_BITMAP
462 lcd_setmargins(0,0);
463#endif
464
465 lcd_clear_display();
466 if (queue_count > 0)
467 {
468 char s[32];
469
470 snprintf(s, sizeof(s), str(LANG_QUEUE_QUEUED), filename);
471 lcd_puts(0,0,s);
472
473 snprintf(s, sizeof(s), str(LANG_QUEUE_TOTAL), queue_count);
474 lcd_puts(0,1,s);
475 }
476 else
477 {
478 lcd_puts(0,0,str(LANG_QUEUE_FULL));
479 }
480 lcd_update();
481 sleep(HZ);
482 lcd_clear_display();
483}
484
455bool ask_resume(void) 485bool ask_resume(void)
456{ 486{
457#ifdef HAVE_LCD_CHARCELLS 487#ifdef HAVE_LCD_CHARCELLS
@@ -518,7 +548,9 @@ void start_resume(void)
518 true, /* the index is AFTER shuffle */ 548 true, /* the index is AFTER shuffle */
519 global_settings.resume_offset, 549 global_settings.resume_offset,
520 global_settings.resume_seed, 550 global_settings.resume_seed,
521 global_settings.resume_first_index); 551 global_settings.resume_first_index,
552 global_settings.queue_resume,
553 global_settings.queue_resume_index);
522 *slash='/'; 554 *slash='/';
523 } 555 }
524 else { 556 else {
@@ -537,7 +569,9 @@ void start_resume(void)
537 true, 569 true,
538 global_settings.resume_offset, 570 global_settings.resume_offset,
539 global_settings.resume_seed, 571 global_settings.resume_seed,
540 global_settings.resume_first_index); 572 global_settings.resume_first_index,
573 global_settings.queue_resume,
574 global_settings.queue_resume_index);
541 } 575 }
542 } 576 }
543 else { 577 else {
@@ -556,7 +590,9 @@ void start_resume(void)
556 true, 590 true,
557 global_settings.resume_offset, 591 global_settings.resume_offset,
558 global_settings.resume_seed, 592 global_settings.resume_seed,
559 global_settings.resume_first_index); 593 global_settings.resume_first_index,
594 global_settings.queue_resume,
595 global_settings.queue_resume_index);
560 } 596 }
561 597
562 status_set_playmode(STATUS_PLAY); 598 status_set_playmode(STATUS_PLAY);
@@ -774,10 +810,10 @@ bool dirbrowse(char *root)
774 break; 810 break;
775 811
776 812
777 case TREE_ENTER: 813 case TREE_ENTER | BUTTON_REL:
778 case TREE_ENTER | BUTTON_REPEAT: 814 case TREE_ENTER | BUTTON_REPEAT:
779#ifdef HAVE_RECORDER_KEYPAD 815#ifdef HAVE_RECORDER_KEYPAD
780 case BUTTON_PLAY: 816 case BUTTON_PLAY | BUTTON_REL:
781 case BUTTON_PLAY | BUTTON_REPEAT: 817 case BUTTON_PLAY | BUTTON_REPEAT:
782#endif 818#endif
783 if ( !numentries ) 819 if ( !numentries )
@@ -798,6 +834,7 @@ bool dirbrowse(char *root)
798 dircursor=0; 834 dircursor=0;
799 dirstart=0; 835 dirstart=0;
800 } else { 836 } else {
837 static int repeat_count = 0;
801 int seed = current_tick; 838 int seed = current_tick;
802 bool play = false; 839 bool play = false;
803 int start_index=0; 840 int start_index=0;
@@ -810,23 +847,40 @@ bool dirbrowse(char *root)
810 MAX_PATH, "%s/%s", 847 MAX_PATH, "%s/%s",
811 currdir, file->name); 848 currdir, file->name);
812 play_list(currdir, file->name, 0, false, 0, 849 play_list(currdir, file->name, 0, false, 0,
813 seed, 0); 850 seed, 0, 0, -1);
814 start_index = 0; 851 start_index = 0;
815 play = true; 852 play = true;
816 break; 853 break;
817 854
818 case TREE_ATTR_MPA: 855 case TREE_ATTR_MPA:
819 if ( global_settings.resume ) 856 if (button & BUTTON_REPEAT &&
820 strncpy(global_settings.resume_file, 857 mpeg_status() & MPEG_STATUS_PLAY)
821 currdir, MAX_PATH); 858 {
822 start_index = build_playlist(dircursor+dirstart); 859 int queue_count = queue_add(buf);
823 860 show_queue_display(queue_count,
824 /* it is important that we get back the index in 861 file->name);
825 the (shuffled) list and stor that */ 862
826 start_index = play_list(currdir, NULL, 863 while( !(button_get(true) & BUTTON_REL) ) ;
827 start_index, false, 864
828 0, seed, 0); 865 repeat_count = 0;
829 play = true; 866 restore = true;
867 }
868 else
869 {
870 repeat_count = 0;
871 if ( global_settings.resume )
872 strncpy(global_settings.resume_file,
873 currdir, MAX_PATH);
874 start_index =
875 build_playlist(dircursor+dirstart);
876
877 /* it is important that we get back the index
878 in the (shuffled) list and store that */
879 start_index = play_list(currdir, NULL,
880 start_index, false,
881 0, seed, 0, 0, -1);
882 play = true;
883 }
830 break; 884 break;
831 885
832 /* wps config file */ 886 /* wps config file */
diff --git a/apps/wps.c b/apps/wps.c
index 73c68d0d4d..bfbaf7cd56 100644
--- a/apps/wps.c
+++ b/apps/wps.c
@@ -38,6 +38,7 @@
38#include "main_menu.h" 38#include "main_menu.h"
39#include "ata.h" 39#include "ata.h"
40#include "screens.h" 40#include "screens.h"
41#include "playlist.h"
41#ifdef HAVE_LCD_BITMAP 42#ifdef HAVE_LCD_BITMAP
42#include "icons.h" 43#include "icons.h"
43#include "peakmeter.h" 44#include "peakmeter.h"
@@ -437,9 +438,14 @@ static bool update(void)
437 global_settings.resume_offset != id3->offset ) { 438 global_settings.resume_offset != id3->offset ) {
438 DEBUGF("R%X,%X (%X)\n", global_settings.resume_offset, 439 DEBUGF("R%X,%X (%X)\n", global_settings.resume_offset,
439 id3->offset,id3); 440 id3->offset,id3);
440 global_settings.resume_index = id3->index; 441
441 global_settings.resume_offset = id3->offset; 442 if (!playlist_get_resume_info(&global_settings.resume_index,
442 settings_save(); 443 &global_settings.queue_resume,
444 &global_settings.queue_resume_index))
445 {
446 global_settings.resume_offset = id3->offset;
447 settings_save();
448 }
443 } 449 }
444 else if ( !id3 && track_changed ) { 450 else if ( !id3 && track_changed ) {
445 global_settings.resume_index = -1; 451 global_settings.resume_index = -1;
diff --git a/uisimulator/x11/file.h b/uisimulator/x11/file.h
index 28c2f2c17a..134019148c 100644
--- a/uisimulator/x11/file.h
+++ b/uisimulator/x11/file.h
@@ -21,13 +21,18 @@
21#include <sys/types.h> 21#include <sys/types.h>
22 22
23int x11_open(char *name, int opts); 23int x11_open(char *name, int opts);
24int x11_creat(char *name, int mode);
25int x11_remove(char *name);
24 26
25#define open(x,y) x11_open(x,y) 27#define open(x,y) x11_open(x,y)
28#define creat(x,y) x11_open(x,y)
29#define remove(x) x11_remove(x)
26 30
27#include "../../firmware/common/file.h" 31#include "../../firmware/common/file.h"
28 32
29extern int open(char* pathname, int flags); 33extern int open(char* pathname, int flags);
30extern int close(int fd); 34extern int close(int fd);
31extern int read(int fd, void* buf, int count); 35extern int read(int fd, void* buf, int count);
36extern int write(int fd, void* buf, int count);
32extern int lseek(int fd, int offset, int whence); 37extern int lseek(int fd, int offset, int whence);
33extern int printf(const char *format, ...); 38extern int printf(const char *format, ...);
diff --git a/uisimulator/x11/io.c b/uisimulator/x11/io.c
index 2951b1f4a0..5890254b79 100644
--- a/uisimulator/x11/io.c
+++ b/uisimulator/x11/io.c
@@ -109,6 +109,32 @@ int x11_open(char *name, int opts)
109 return open(name, opts); 109 return open(name, opts);
110} 110}
111 111
112int x11_creat(char *name, int mode)
113{
114 char buffer[256]; /* sufficiently big */
115
116 if(name[0] == '/') {
117 sprintf(buffer, "%s%s", SIMULATOR_ARCHOS_ROOT, name);
118
119 debugf("We open the real file '%s'\n", buffer);
120 return creat(buffer, mode);
121 }
122 return creat(name, mode);
123}
124
125int x11_remove(char *name)
126{
127 char buffer[256]; /* sufficiently big */
128
129 if(name[0] == '/') {
130 sprintf(buffer, "%s%s", SIMULATOR_ARCHOS_ROOT, name);
131
132 debugf("We open the real file '%s'\n", buffer);
133 return remove(buffer);
134 }
135 return remove(name);
136}
137
112void fat_size(unsigned int* size, unsigned int* free) 138void fat_size(unsigned int* size, unsigned int* free)
113{ 139{
114 struct statfs fs; 140 struct statfs fs;