diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/playlist.c | 300 | ||||
-rw-r--r-- | apps/playlist.h | 16 |
2 files changed, 198 insertions, 118 deletions
diff --git a/apps/playlist.c b/apps/playlist.c index fdd88a17bc..465470c069 100644 --- a/apps/playlist.c +++ b/apps/playlist.c | |||
@@ -33,157 +33,224 @@ | |||
33 | 33 | ||
34 | playlist_info_t playlist; | 34 | playlist_info_t playlist; |
35 | 35 | ||
36 | #define PLAYLIST_BUFFER_SIZE (MAX_PATH*200) | ||
37 | |||
38 | unsigned char playlist_buffer[PLAYLIST_BUFFER_SIZE]; | ||
39 | static int playlist_end_pos = 0; | ||
40 | |||
36 | char now_playing[MAX_PATH+1]; | 41 | char now_playing[MAX_PATH+1]; |
37 | 42 | ||
38 | char* playlist_next(int steps, char *dirname) | 43 | void playlist_clear(void) |
44 | { | ||
45 | playlist_end_pos = 0; | ||
46 | playlist_buffer[0] = 0; | ||
47 | } | ||
48 | |||
49 | int playlist_add(char *filename) | ||
50 | { | ||
51 | int len = strlen(filename); | ||
52 | |||
53 | if(len+2 > PLAYLIST_BUFFER_SIZE - playlist_end_pos) | ||
54 | return -1; | ||
55 | |||
56 | strcpy(&playlist_buffer[playlist_end_pos], filename); | ||
57 | playlist_end_pos += len; | ||
58 | playlist_buffer[playlist_end_pos++] = '\n'; | ||
59 | playlist_buffer[playlist_end_pos] = '\0'; | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | char* playlist_next(int steps) | ||
39 | { | 64 | { |
40 | int seek; | 65 | int seek; |
41 | int max; | 66 | int max; |
42 | int fd; | 67 | int fd; |
43 | int i; | 68 | int i; |
44 | char buf[MAX_PATH+1]; | 69 | char *buf; |
45 | char dir_buf[MAX_PATH+1]; | 70 | char dir_buf[MAX_PATH+1]; |
46 | char *dir_end; | 71 | char *dir_end; |
47 | 72 | ||
48 | playlist.index = (playlist.index+steps) % playlist.amount; | 73 | playlist.index = (playlist.index+steps) % playlist.amount; |
49 | seek = playlist.indices[playlist.index]; | 74 | seek = playlist.indices[playlist.index]; |
50 | 75 | ||
51 | fd = open(playlist.filename, O_RDONLY); | 76 | if(playlist.in_ram) |
52 | if(-1 != fd) { | 77 | { |
53 | lseek(fd, seek, SEEK_SET); | 78 | buf = playlist_buffer + seek; |
54 | max = read(fd, buf, sizeof(buf)-1); | 79 | max = playlist_end_pos - seek; |
55 | close(fd); | 80 | } |
56 | 81 | else | |
57 | /* Zero-terminate the file name */ | 82 | { |
58 | seek=0; | 83 | fd = open(playlist.filename, O_RDONLY); |
59 | while((buf[seek] != '\n') && | 84 | if(-1 != fd) |
60 | (buf[seek] != '\r') && | 85 | { |
61 | (seek < max)) | 86 | buf = playlist_buffer; |
87 | lseek(fd, seek, SEEK_SET); | ||
88 | max = read(fd, buf, MAX_PATH); | ||
89 | close(fd); | ||
90 | } | ||
91 | else | ||
92 | return NULL; | ||
93 | } | ||
94 | |||
95 | |||
96 | /* Zero-terminate the file name */ | ||
97 | seek=0; | ||
98 | while((buf[seek] != '\n') && | ||
99 | (buf[seek] != '\r') && | ||
100 | (seek < max)) | ||
62 | seek++; | 101 | seek++; |
63 | 102 | ||
64 | /* Now work back killing white space */ | 103 | /* Now work back killing white space */ |
65 | while((buf[seek-1] == ' ') || | 104 | while((buf[seek-1] == ' ') || |
66 | (buf[seek-1] == '\t')) | 105 | (buf[seek-1] == '\t')) |
67 | seek--; | 106 | seek--; |
68 | 107 | ||
69 | buf[seek]=0; | 108 | buf[seek]=0; |
70 | 109 | ||
71 | /* replace backslashes with forward slashes */ | 110 | /* replace backslashes with forward slashes */ |
72 | for ( i=0; i<seek; i++ ) | 111 | for ( i=0; i<seek; i++ ) |
73 | if ( buf[i] == '\\' ) | 112 | if ( buf[i] == '\\' ) |
74 | buf[i] = '/'; | 113 | buf[i] = '/'; |
75 | 114 | ||
76 | if('/' == buf[0]) { | 115 | if('/' == buf[0]) { |
77 | strcpy(now_playing, &buf[0]); | 116 | strcpy(now_playing, &buf[0]); |
78 | return now_playing; | 117 | return now_playing; |
79 | } | 118 | } |
80 | else { | 119 | else { |
81 | /* handle dos style drive letter */ | 120 | strncpy(dir_buf, playlist.filename, playlist.dirlen); |
82 | if ( ':' == buf[1] ) { | 121 | dir_buf[playlist.dirlen] = 0; |
83 | strcpy(now_playing, &buf[2]); | 122 | |
84 | return now_playing; | 123 | /* handle dos style drive letter */ |
85 | } | 124 | if ( ':' == buf[1] ) { |
86 | else if ( '.' == buf[0] && '.' == buf[1] && '/' == buf[2] ) { | 125 | strcpy(now_playing, &buf[2]); |
87 | /* handle relative paths */ | 126 | return now_playing; |
88 | seek=3; | 127 | } |
89 | while(buf[seek] == '.' && | 128 | else if ( '.' == buf[0] && '.' == buf[1] && '/' == buf[2] ) { |
90 | buf[seek+1] == '.' && | 129 | /* handle relative paths */ |
91 | buf[seek+2] == '/') | 130 | seek=3; |
92 | seek += 3; | 131 | while(buf[seek] == '.' && |
93 | strcpy(dir_buf, dirname); | 132 | buf[seek+1] == '.' && |
94 | for (i=0; i<seek/3; i++) { | 133 | buf[seek+2] == '/') |
95 | dir_end = strrchr(dir_buf, '/'); | 134 | seek += 3; |
96 | if (dir_end) | 135 | for (i=0; i<seek/3; i++) { |
97 | *dir_end = '\0'; | 136 | dir_end = strrchr(dir_buf, '/'); |
98 | else | 137 | if (dir_end) |
99 | break; | 138 | *dir_end = '\0'; |
100 | } | 139 | else |
101 | snprintf(now_playing, MAX_PATH+1, "%s/%s", dir_buf, &buf[seek]); | 140 | break; |
102 | return now_playing; | 141 | } |
103 | } | 142 | snprintf(now_playing, MAX_PATH+1, "%s/%s", dir_buf, &buf[seek]); |
104 | else if ( '.' == buf[0] && '/' == buf[1] ) { | 143 | return now_playing; |
105 | snprintf(now_playing, MAX_PATH+1, "%s/%s", dirname, &buf[2]); | 144 | } |
106 | return now_playing; | 145 | else if ( '.' == buf[0] && '/' == buf[1] ) { |
107 | } | 146 | snprintf(now_playing, MAX_PATH+1, "%s/%s", dir_buf, &buf[2]); |
108 | else { | 147 | return now_playing; |
109 | snprintf(now_playing, MAX_PATH+1, "%s/%s", dirname, buf); | 148 | } |
110 | return now_playing; | 149 | else { |
111 | } | 150 | snprintf(now_playing, MAX_PATH+1, "%s/%s", dir_buf, buf); |
112 | } | 151 | return now_playing; |
152 | } | ||
113 | } | 153 | } |
114 | else | ||
115 | return NULL; | ||
116 | } | 154 | } |
117 | 155 | ||
118 | void play_list(char *dir, char *file) | 156 | void play_list(char *dir, char *file) |
119 | { | 157 | { |
120 | char *sep=""; | 158 | char *sep=""; |
159 | int dirlen; | ||
121 | 160 | ||
122 | lcd_clear_display(); | 161 | empty_playlist(); |
123 | lcd_puts(0,0,"Loading..."); | 162 | |
124 | lcd_update(); | 163 | /* If file is NULL, the list is in RAM */ |
125 | empty_playlist(&playlist); | 164 | if(file) { |
165 | lcd_clear_display(); | ||
166 | lcd_puts(0,0,"Loading..."); | ||
167 | lcd_update(); | ||
168 | playlist.in_ram = false; | ||
169 | } else { | ||
170 | /* Assign a dummy filename */ | ||
171 | file = ""; | ||
172 | playlist.in_ram = true; | ||
173 | } | ||
126 | 174 | ||
127 | /* If the dir does not end in trailing new line, we use a separator. | 175 | dirlen = strlen(dir); |
176 | |||
177 | /* If the dir does not end in trailing slash, we use a separator. | ||
128 | Otherwise we don't. */ | 178 | Otherwise we don't. */ |
129 | if('/' != dir[strlen(dir)-1]) | 179 | if('/' != dir[dirlen-1]) { |
130 | sep="/"; | 180 | sep="/"; |
181 | dirlen++; | ||
182 | } | ||
183 | |||
184 | playlist.dirlen = dirlen; | ||
131 | 185 | ||
132 | snprintf(playlist.filename, sizeof(playlist.filename), | 186 | snprintf(playlist.filename, sizeof(playlist.filename), |
133 | "%s%s%s", | 187 | "%s%s%s", |
134 | dir, sep, file); | 188 | dir, sep, file); |
135 | 189 | ||
136 | /* add track indices to playlist data structure */ | 190 | /* add track indices to playlist data structure */ |
137 | add_indices_to_playlist(&playlist); | 191 | add_indices_to_playlist(); |
138 | 192 | ||
139 | if(global_settings.playlist_shuffle) { | 193 | if(global_settings.playlist_shuffle) { |
140 | lcd_puts(0,0,"Shuffling..."); | 194 | if(!playlist.in_ram) { |
141 | lcd_update(); | 195 | lcd_puts(0,0,"Shuffling..."); |
142 | randomise_playlist( &playlist, current_tick ); | 196 | lcd_update(); |
197 | } | ||
198 | randomise_playlist( current_tick ); | ||
143 | } | 199 | } |
144 | 200 | ||
145 | lcd_puts(0,0,"Playing... "); | 201 | if(!playlist.in_ram) { |
146 | lcd_update(); | 202 | lcd_puts(0,0,"Playing... "); |
203 | lcd_update(); | ||
204 | } | ||
147 | /* also make the first song get playing */ | 205 | /* also make the first song get playing */ |
148 | mpeg_play(playlist_next(0, dir)); | 206 | mpeg_play(playlist_next(0)); |
149 | sleep(HZ); | ||
150 | } | 207 | } |
151 | 208 | ||
152 | /* | 209 | /* |
153 | * remove any filename and indices associated with the playlist | 210 | * remove any filename and indices associated with the playlist |
154 | */ | 211 | */ |
155 | void empty_playlist( playlist_info_t *playlist ) | 212 | void empty_playlist(void) |
156 | { | 213 | { |
157 | playlist->filename[0] = '\0'; | 214 | playlist.filename[0] = '\0'; |
158 | playlist->index = 0; | 215 | playlist.index = 0; |
159 | playlist->amount = 0; | 216 | playlist.amount = 0; |
160 | } | 217 | } |
161 | 218 | ||
162 | /* | 219 | /* |
163 | * calculate track offsets within a playlist file | 220 | * calculate track offsets within a playlist file |
164 | */ | 221 | */ |
165 | void add_indices_to_playlist( playlist_info_t *playlist ) | 222 | void add_indices_to_playlist(void) |
166 | { | 223 | { |
167 | int nread; | 224 | int nread; |
168 | int fd; | 225 | int fd = -1; |
169 | int i = 0; | 226 | int i = 0; |
170 | int store_index = 0; | 227 | int store_index = 0; |
171 | int count = 0; | 228 | int count = 0; |
172 | int next_tick = current_tick + HZ; | 229 | int next_tick = current_tick + HZ; |
173 | 230 | ||
174 | unsigned char *p; | 231 | unsigned char *p = playlist_buffer; |
175 | unsigned char buf[512]; | ||
176 | char line[16]; | 232 | char line[16]; |
177 | 233 | ||
178 | fd = open(playlist->filename, O_RDONLY); | 234 | if(!playlist.in_ram) { |
179 | if(-1 == fd) | 235 | fd = open(playlist.filename, O_RDONLY); |
180 | return; /* failure */ | 236 | if(-1 == fd) |
237 | return; /* failure */ | ||
238 | } | ||
181 | 239 | ||
182 | store_index = 1; | 240 | store_index = 1; |
183 | 241 | ||
184 | while((nread = read(fd, &buf, sizeof(buf))) != 0) | 242 | while(1) |
185 | { | 243 | { |
186 | p = buf; | 244 | if(playlist.in_ram) { |
245 | nread = playlist_end_pos; | ||
246 | } else { | ||
247 | nread = read(fd, playlist_buffer, PLAYLIST_BUFFER_SIZE); | ||
248 | /* Terminate on EOF */ | ||
249 | if(nread <= 0) | ||
250 | break; | ||
251 | } | ||
252 | |||
253 | p = playlist_buffer; | ||
187 | 254 | ||
188 | for(count=0; count < nread; count++,p++) { | 255 | for(count=0; count < nread; count++,p++) { |
189 | 256 | ||
@@ -203,36 +270,45 @@ void add_indices_to_playlist( playlist_info_t *playlist ) | |||
203 | { | 270 | { |
204 | 271 | ||
205 | /* Store a new entry */ | 272 | /* Store a new entry */ |
206 | playlist->indices[ playlist->amount ] = i+count; | 273 | playlist.indices[ playlist.amount ] = i+count; |
207 | playlist->amount++; | 274 | playlist.amount++; |
208 | if ( playlist->amount >= MAX_PLAYLIST_SIZE ) { | 275 | if ( playlist.amount >= MAX_PLAYLIST_SIZE ) { |
209 | close(fd); | 276 | if(!playlist.in_ram) |
277 | close(fd); | ||
210 | return; | 278 | return; |
211 | } | 279 | } |
212 | 280 | ||
213 | store_index = 0; | 281 | store_index = 0; |
214 | if ( current_tick >= next_tick ) { | 282 | /* Update the screen if it takes very long */ |
215 | next_tick = current_tick + HZ; | 283 | if(!playlist.in_ram) { |
216 | snprintf(line, sizeof line, "%d files", playlist->amount); | 284 | if ( current_tick >= next_tick ) { |
217 | lcd_puts(0,1,line); | 285 | next_tick = current_tick + HZ; |
218 | lcd_update(); | 286 | snprintf(line, sizeof line, "%d files", |
287 | playlist.amount); | ||
288 | lcd_puts(0,1,line); | ||
289 | lcd_update(); | ||
290 | } | ||
219 | } | 291 | } |
220 | } | 292 | } |
221 | } | 293 | } |
222 | 294 | ||
223 | i+= count; | 295 | i+= count; |
224 | } | ||
225 | snprintf(line, sizeof line, "%d files", playlist->amount); | ||
226 | lcd_puts(0,1,line); | ||
227 | lcd_update(); | ||
228 | 296 | ||
229 | close(fd); | 297 | if(playlist.in_ram) |
298 | break; | ||
299 | } | ||
300 | if(!playlist.in_ram) { | ||
301 | snprintf(line, sizeof line, "%d files", playlist.amount); | ||
302 | lcd_puts(0,1,line); | ||
303 | lcd_update(); | ||
304 | close(fd); | ||
305 | } | ||
230 | } | 306 | } |
231 | 307 | ||
232 | /* | 308 | /* |
233 | * randomly rearrange the array of indices for the playlist | 309 | * randomly rearrange the array of indices for the playlist |
234 | */ | 310 | */ |
235 | void randomise_playlist( playlist_info_t *playlist, unsigned int seed ) | 311 | void randomise_playlist( unsigned int seed ) |
236 | { | 312 | { |
237 | int count; | 313 | int count; |
238 | int candidate; | 314 | int candidate; |
@@ -242,15 +318,15 @@ void randomise_playlist( playlist_info_t *playlist, unsigned int seed ) | |||
242 | srand( seed ); | 318 | srand( seed ); |
243 | 319 | ||
244 | /* randomise entire indices list */ | 320 | /* randomise entire indices list */ |
245 | for(count = playlist->amount - 1; count >= 0; count--) | 321 | for(count = playlist.amount - 1; count >= 0; count--) |
246 | { | 322 | { |
247 | /* the rand is from 0 to RAND_MAX, so adjust to our value range */ | 323 | /* the rand is from 0 to RAND_MAX, so adjust to our value range */ |
248 | candidate = rand() % (count + 1); | 324 | candidate = rand() % (count + 1); |
249 | 325 | ||
250 | /* now swap the values at the 'count' and 'candidate' positions */ | 326 | /* now swap the values at the 'count' and 'candidate' positions */ |
251 | store = playlist->indices[candidate]; | 327 | store = playlist.indices[candidate]; |
252 | playlist->indices[candidate] = playlist->indices[count]; | 328 | playlist.indices[candidate] = playlist.indices[count]; |
253 | playlist->indices[count] = store; | 329 | playlist.indices[count] = store; |
254 | } | 330 | } |
255 | } | 331 | } |
256 | 332 | ||
@@ -265,11 +341,11 @@ static int compare(const void* p1, const void* p2) | |||
265 | /* | 341 | /* |
266 | * sort the array of indices for the playlist | 342 | * sort the array of indices for the playlist |
267 | */ | 343 | */ |
268 | void sort_playlist( playlist_info_t *playlist ) | 344 | void sort_playlist(void) |
269 | { | 345 | { |
270 | if (playlist->amount > 0) | 346 | if (playlist.amount > 0) |
271 | { | 347 | { |
272 | qsort(&playlist->indices, playlist->amount, sizeof(playlist->indices[0]), compare); | 348 | qsort(&playlist.indices, playlist.amount, sizeof(playlist.indices[0]), compare); |
273 | } | 349 | } |
274 | } | 350 | } |
275 | 351 | ||
diff --git a/apps/playlist.h b/apps/playlist.h index 3d37c5da5f..a218209857 100644 --- a/apps/playlist.h +++ b/apps/playlist.h | |||
@@ -29,20 +29,24 @@ | |||
29 | typedef struct | 29 | typedef struct |
30 | { | 30 | { |
31 | char filename[MAX_PATH]; /* path name of m3u playlist on disk */ | 31 | char filename[MAX_PATH]; /* path name of m3u playlist on disk */ |
32 | int dirlen; /* Length of the path to the playlist file */ | ||
32 | int indices[MAX_PLAYLIST_SIZE]; /* array of indices */ | 33 | int indices[MAX_PLAYLIST_SIZE]; /* array of indices */ |
33 | int index; /* index of *NEXT* track to play */ | 34 | int index; /* index of *NEXT* track to play */ |
34 | int seed; /* random seed */ | 35 | int seed; /* random seed */ |
35 | int amount; /* number of tracks in the index */ | 36 | int amount; /* number of tracks in the index */ |
37 | bool in_ram; /* True if the playlist is RAM-based */ | ||
36 | } playlist_info_t; | 38 | } playlist_info_t; |
37 | 39 | ||
38 | extern playlist_info_t playlist; | 40 | //extern playlist_info_t playlist; |
39 | extern bool playlist_shuffle; | 41 | extern bool playlist_shuffle; |
40 | 42 | ||
41 | void play_list(char *dir, char *file); | 43 | void play_list(char *dir, char *file); |
42 | char* playlist_next(int steps, char *dirname); | 44 | char* playlist_next(int steps); |
43 | void randomise_playlist( playlist_info_t *playlist, unsigned int seed ); | 45 | void randomise_playlist( unsigned int seed ); |
44 | void sort_playlist( playlist_info_t *playlist ); | 46 | void sort_playlist(void); |
45 | void empty_playlist( playlist_info_t *playlist ); | 47 | void empty_playlist(void); |
46 | void add_indices_to_playlist( playlist_info_t *playlist ); | 48 | void add_indices_to_playlist(void); |
49 | void playlist_clear(void); | ||
50 | int playlist_add(char *filename); | ||
47 | 51 | ||
48 | #endif /* __PLAYLIST_H__ */ | 52 | #endif /* __PLAYLIST_H__ */ |