diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/onplay.c | 14 | ||||
-rw-r--r-- | apps/playlist.c | 184 | ||||
-rw-r--r-- | apps/playlist_menu.c | 38 | ||||
-rw-r--r-- | apps/playlist_menu.h | 3 | ||||
-rw-r--r-- | apps/playlist_viewer.c | 13 |
5 files changed, 208 insertions, 44 deletions
diff --git a/apps/onplay.c b/apps/onplay.c index 9b94be0959..88607f7754 100644 --- a/apps/onplay.c +++ b/apps/onplay.c | |||
@@ -61,6 +61,7 @@ | |||
61 | #if CONFIG_CODEC == SWCODEC | 61 | #if CONFIG_CODEC == SWCODEC |
62 | #include "eq_menu.h" | 62 | #include "eq_menu.h" |
63 | #endif | 63 | #endif |
64 | #include "playlist_menu.h" | ||
64 | 65 | ||
65 | static int context; | 66 | static int context; |
66 | static char* selected_file = NULL; | 67 | static char* selected_file = NULL; |
@@ -152,18 +153,7 @@ static bool shuffle_playlist(void) | |||
152 | 153 | ||
153 | static bool save_playlist(void) | 154 | static bool save_playlist(void) |
154 | { | 155 | { |
155 | char filename[MAX_PATH+1]; | 156 | save_playlist_screen(NULL); |
156 | |||
157 | strncpy(filename, DEFAULT_DYNAMIC_PLAYLIST_NAME, sizeof(filename)); | ||
158 | |||
159 | if (!kbd_input(filename, sizeof(filename))) | ||
160 | { | ||
161 | playlist_save(NULL, filename); | ||
162 | |||
163 | /* reload in case playlist was saved to cwd */ | ||
164 | onplay_result = ONPLAY_RELOAD_DIR; | ||
165 | } | ||
166 | |||
167 | return false; | 157 | return false; |
168 | } | 158 | } |
169 | 159 | ||
diff --git a/apps/playlist.c b/apps/playlist.c index 25939bb3ee..84160195b7 100644 --- a/apps/playlist.c +++ b/apps/playlist.c | |||
@@ -143,6 +143,7 @@ static void new_playlist(struct playlist_info* playlist, const char *dir, | |||
143 | const char *file); | 143 | const char *file); |
144 | static void create_control(struct playlist_info* playlist); | 144 | static void create_control(struct playlist_info* playlist); |
145 | static int check_control(struct playlist_info* playlist); | 145 | static int check_control(struct playlist_info* playlist); |
146 | static int recreate_control(struct playlist_info* playlist); | ||
146 | static void update_playlist_filename(struct playlist_info* playlist, | 147 | static void update_playlist_filename(struct playlist_info* playlist, |
147 | const char *dir, const char *file); | 148 | const char *dir, const char *file); |
148 | static int add_indices_to_playlist(struct playlist_info* playlist, | 149 | static int add_indices_to_playlist(struct playlist_info* playlist, |
@@ -322,6 +323,107 @@ static int check_control(struct playlist_info* playlist) | |||
322 | } | 323 | } |
323 | 324 | ||
324 | /* | 325 | /* |
326 | * recreate the control file based on current playlist entries | ||
327 | */ | ||
328 | static int recreate_control(struct playlist_info* playlist) | ||
329 | { | ||
330 | char temp_file[MAX_PATH+1]; | ||
331 | int temp_fd = -1; | ||
332 | int i; | ||
333 | int result = 0; | ||
334 | |||
335 | if(playlist->control_fd >= 0) | ||
336 | { | ||
337 | char* dir = playlist->filename; | ||
338 | char* file = playlist->filename+playlist->dirlen; | ||
339 | char c = playlist->filename[playlist->dirlen-1]; | ||
340 | |||
341 | close(playlist->control_fd); | ||
342 | |||
343 | snprintf(temp_file, sizeof(temp_file), "%s_temp", | ||
344 | playlist->control_filename); | ||
345 | |||
346 | if (rename(playlist->control_filename, temp_file) < 0) | ||
347 | return -1; | ||
348 | |||
349 | temp_fd = open(temp_file, O_RDONLY); | ||
350 | if (temp_fd < 0) | ||
351 | return -1; | ||
352 | |||
353 | playlist->control_fd = open(playlist->control_filename, | ||
354 | O_CREAT|O_RDWR|O_TRUNC); | ||
355 | if (playlist->control_fd < 0) | ||
356 | return -1; | ||
357 | |||
358 | playlist->filename[playlist->dirlen-1] = '\0'; | ||
359 | |||
360 | /* cannot call update_control() because of mutex */ | ||
361 | result = fdprintf(playlist->control_fd, "P:%d:%s:%s\n", | ||
362 | PLAYLIST_CONTROL_FILE_VERSION, dir, file); | ||
363 | |||
364 | playlist->filename[playlist->dirlen-1] = c; | ||
365 | |||
366 | if (result < 0) | ||
367 | { | ||
368 | close(temp_fd); | ||
369 | return result; | ||
370 | } | ||
371 | } | ||
372 | |||
373 | playlist->seed = 0; | ||
374 | playlist->shuffle_modified = false; | ||
375 | playlist->deleted = false; | ||
376 | playlist->num_inserted_tracks = 0; | ||
377 | |||
378 | if (playlist->current) | ||
379 | { | ||
380 | global_settings.resume_seed = -1; | ||
381 | settings_save(); | ||
382 | } | ||
383 | |||
384 | for (i=0; i<playlist->amount; i++) | ||
385 | { | ||
386 | if (playlist->indices[i] & PLAYLIST_INSERT_TYPE_MASK) | ||
387 | { | ||
388 | bool queue = playlist->indices[i] & PLAYLIST_QUEUE_MASK; | ||
389 | char inserted_file[MAX_PATH+1]; | ||
390 | |||
391 | lseek(temp_fd, playlist->indices[i] & PLAYLIST_SEEK_MASK, | ||
392 | SEEK_SET); | ||
393 | read_line(temp_fd, inserted_file, sizeof(inserted_file)); | ||
394 | |||
395 | result = fdprintf(playlist->control_fd, "%c:%d:%d:", | ||
396 | queue?'Q':'A', i, playlist->last_insert_pos); | ||
397 | if (result > 0) | ||
398 | { | ||
399 | /* save the position in file where name is written */ | ||
400 | int seek_pos = lseek(playlist->control_fd, 0, SEEK_CUR); | ||
401 | |||
402 | result = fdprintf(playlist->control_fd, "%s\n", | ||
403 | inserted_file); | ||
404 | |||
405 | playlist->indices[i] = | ||
406 | (playlist->indices[i] & ~PLAYLIST_SEEK_MASK) | seek_pos; | ||
407 | } | ||
408 | |||
409 | if (result < 0) | ||
410 | break; | ||
411 | |||
412 | playlist->num_inserted_tracks++; | ||
413 | } | ||
414 | } | ||
415 | |||
416 | close(temp_fd); | ||
417 | remove(temp_file); | ||
418 | fsync(playlist->control_fd); | ||
419 | |||
420 | if (result < 0) | ||
421 | return result; | ||
422 | |||
423 | return 0; | ||
424 | } | ||
425 | |||
426 | /* | ||
325 | * store directory and name of playlist file | 427 | * store directory and name of playlist file |
326 | */ | 428 | */ |
327 | static void update_playlist_filename(struct playlist_info* playlist, | 429 | static void update_playlist_filename(struct playlist_info* playlist, |
@@ -1183,6 +1285,8 @@ static int get_filename(struct playlist_info* playlist, int index, int seek, | |||
1183 | } | 1285 | } |
1184 | else if (max < 0) | 1286 | else if (max < 0) |
1185 | { | 1287 | { |
1288 | mutex_lock(&playlist->control_mutex); | ||
1289 | |||
1186 | if (control_file) | 1290 | if (control_file) |
1187 | fd = playlist->control_fd; | 1291 | fd = playlist->control_fd; |
1188 | else | 1292 | else |
@@ -1195,18 +1299,15 @@ static int get_filename(struct playlist_info* playlist, int index, int seek, | |||
1195 | 1299 | ||
1196 | if(-1 != fd) | 1300 | if(-1 != fd) |
1197 | { | 1301 | { |
1198 | if (control_file) | ||
1199 | mutex_lock(&playlist->control_mutex); | ||
1200 | 1302 | ||
1201 | if (lseek(fd, seek, SEEK_SET) != seek) | 1303 | if (lseek(fd, seek, SEEK_SET) != seek) |
1202 | max = -1; | 1304 | max = -1; |
1203 | else | 1305 | else |
1204 | max = read(fd, tmp_buf, buf_length); | 1306 | max = read(fd, tmp_buf, buf_length); |
1205 | |||
1206 | if (control_file) | ||
1207 | mutex_unlock(&playlist->control_mutex); | ||
1208 | } | 1307 | } |
1209 | 1308 | ||
1309 | mutex_unlock(&playlist->control_mutex); | ||
1310 | |||
1210 | if (max < 0) | 1311 | if (max < 0) |
1211 | { | 1312 | { |
1212 | if (control_file) | 1313 | if (control_file) |
@@ -3114,8 +3215,11 @@ int playlist_save(struct playlist_info* playlist, char *filename) | |||
3114 | int fd; | 3215 | int fd; |
3115 | int i, index; | 3216 | int i, index; |
3116 | int count = 0; | 3217 | int count = 0; |
3218 | char path[MAX_PATH+1]; | ||
3117 | char tmp_buf[MAX_PATH+1]; | 3219 | char tmp_buf[MAX_PATH+1]; |
3118 | int result = 0; | 3220 | int result = 0; |
3221 | bool overwrite_current = false; | ||
3222 | int* index_buf = NULL; | ||
3119 | 3223 | ||
3120 | if (!playlist) | 3224 | if (!playlist) |
3121 | playlist = ¤t_playlist; | 3225 | playlist = ¤t_playlist; |
@@ -3124,11 +3228,31 @@ int playlist_save(struct playlist_info* playlist, char *filename) | |||
3124 | return -1; | 3228 | return -1; |
3125 | 3229 | ||
3126 | /* use current working directory as base for pathname */ | 3230 | /* use current working directory as base for pathname */ |
3127 | if (format_track_path(tmp_buf, filename, sizeof(tmp_buf), | 3231 | if (format_track_path(path, filename, sizeof(tmp_buf), |
3128 | strlen(filename)+1, getcwd(NULL, -1)) < 0) | 3232 | strlen(filename)+1, getcwd(NULL, -1)) < 0) |
3129 | return -1; | 3233 | return -1; |
3130 | 3234 | ||
3131 | fd = open(tmp_buf, O_CREAT|O_WRONLY|O_TRUNC); | 3235 | if (!strncmp(playlist->filename, path, strlen(path))) |
3236 | { | ||
3237 | /* Attempting to overwrite current playlist file.*/ | ||
3238 | |||
3239 | if (playlist->buffer_size < (int)(playlist->amount * sizeof(int))) | ||
3240 | { | ||
3241 | /* not enough buffer space to store updated indices */ | ||
3242 | gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_ACCESS_ERROR)); | ||
3243 | return -1; | ||
3244 | } | ||
3245 | |||
3246 | /* in_ram buffer is unused for m3u files so we'll use for storing | ||
3247 | updated indices */ | ||
3248 | index_buf = (int*)playlist->buffer; | ||
3249 | |||
3250 | /* use temporary pathname */ | ||
3251 | snprintf(path, sizeof(path), "%s_temp", playlist->filename); | ||
3252 | overwrite_current = true; | ||
3253 | } | ||
3254 | |||
3255 | fd = open(path, O_CREAT|O_WRONLY|O_TRUNC); | ||
3132 | if (fd < 0) | 3256 | if (fd < 0) |
3133 | { | 3257 | { |
3134 | gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_ACCESS_ERROR)); | 3258 | gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_ACCESS_ERROR)); |
@@ -3146,7 +3270,10 @@ int playlist_save(struct playlist_info* playlist, char *filename) | |||
3146 | 3270 | ||
3147 | /* user abort */ | 3271 | /* user abort */ |
3148 | if (button_get(false) == SETTINGS_CANCEL) | 3272 | if (button_get(false) == SETTINGS_CANCEL) |
3273 | { | ||
3274 | result = -1; | ||
3149 | break; | 3275 | break; |
3276 | } | ||
3150 | 3277 | ||
3151 | control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK; | 3278 | control_file = playlist->indices[index] & PLAYLIST_INSERT_TYPE_MASK; |
3152 | queue = playlist->indices[index] & PLAYLIST_QUEUE_MASK; | 3279 | queue = playlist->indices[index] & PLAYLIST_QUEUE_MASK; |
@@ -3162,9 +3289,12 @@ int playlist_save(struct playlist_info* playlist, char *filename) | |||
3162 | break; | 3289 | break; |
3163 | } | 3290 | } |
3164 | 3291 | ||
3292 | if (overwrite_current) | ||
3293 | index_buf[count] = lseek(fd, 0, SEEK_CUR); | ||
3294 | |||
3165 | if (fdprintf(fd, "%s\n", tmp_buf) < 0) | 3295 | if (fdprintf(fd, "%s\n", tmp_buf) < 0) |
3166 | { | 3296 | { |
3167 | gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_UPDATE_ERROR)); | 3297 | gui_syncsplash(HZ*2, true, str(LANG_PLAYLIST_ACCESS_ERROR)); |
3168 | result = -1; | 3298 | result = -1; |
3169 | break; | 3299 | break; |
3170 | } | 3300 | } |
@@ -3184,5 +3314,43 @@ int playlist_save(struct playlist_info* playlist, char *filename) | |||
3184 | 3314 | ||
3185 | close(fd); | 3315 | close(fd); |
3186 | 3316 | ||
3317 | if (overwrite_current && result >= 0) | ||
3318 | { | ||
3319 | result = -1; | ||
3320 | |||
3321 | mutex_lock(&playlist->control_mutex); | ||
3322 | |||
3323 | /* Replace the current playlist with the new one and update indices */ | ||
3324 | close(playlist->fd); | ||
3325 | if (remove(playlist->filename) >= 0) | ||
3326 | { | ||
3327 | if (rename(path, playlist->filename) >= 0) | ||
3328 | { | ||
3329 | playlist->fd = open(playlist->filename, O_RDONLY); | ||
3330 | if (playlist->fd >= 0) | ||
3331 | { | ||
3332 | index = playlist->first_index; | ||
3333 | for (i=0, count=0; i<playlist->amount; i++) | ||
3334 | { | ||
3335 | if (!(playlist->indices[index] & PLAYLIST_QUEUE_MASK)) | ||
3336 | { | ||
3337 | playlist->indices[index] = index_buf[count]; | ||
3338 | count++; | ||
3339 | } | ||
3340 | index = (index+1)%playlist->amount; | ||
3341 | } | ||
3342 | |||
3343 | /* we need to recreate control because inserted tracks are | ||
3344 | now part of the playlist and shuffle has been | ||
3345 | invalidated */ | ||
3346 | result = recreate_control(playlist); | ||
3347 | } | ||
3348 | } | ||
3349 | } | ||
3350 | |||
3351 | mutex_unlock(&playlist->control_mutex); | ||
3352 | |||
3353 | } | ||
3354 | |||
3187 | return result; | 3355 | return result; |
3188 | } | 3356 | } |
diff --git a/apps/playlist_menu.c b/apps/playlist_menu.c index c70a510a6e..c390e8077d 100644 --- a/apps/playlist_menu.c +++ b/apps/playlist_menu.c | |||
@@ -28,22 +28,11 @@ | |||
28 | #include "playlist_viewer.h" | 28 | #include "playlist_viewer.h" |
29 | #include "talk.h" | 29 | #include "talk.h" |
30 | #include "lang.h" | 30 | #include "lang.h" |
31 | #include "playlist_menu.h" | ||
31 | 32 | ||
32 | /* FIXME: there is a very similar function in onplay.c */ | ||
33 | static bool save_playlist(void) | 33 | static bool save_playlist(void) |
34 | { | 34 | { |
35 | char filename[MAX_PATH+1]; | 35 | save_playlist_screen(NULL); |
36 | |||
37 | strncpy(filename, DEFAULT_DYNAMIC_PLAYLIST_NAME, sizeof(filename)); | ||
38 | |||
39 | if (!kbd_input(filename, sizeof(filename))) | ||
40 | { | ||
41 | playlist_save(NULL, filename); | ||
42 | |||
43 | /* reload in case playlist was saved to cwd */ | ||
44 | reload_directory(); | ||
45 | } | ||
46 | |||
47 | return false; | 36 | return false; |
48 | } | 37 | } |
49 | 38 | ||
@@ -85,3 +74,26 @@ bool playlist_menu(void) | |||
85 | menu_exit(m); | 74 | menu_exit(m); |
86 | return result; | 75 | return result; |
87 | } | 76 | } |
77 | |||
78 | int save_playlist_screen(struct playlist_info* playlist) | ||
79 | { | ||
80 | char* filename; | ||
81 | char temp[MAX_PATH+1]; | ||
82 | int len; | ||
83 | |||
84 | filename = playlist_get_name(playlist, temp, sizeof(temp)); | ||
85 | |||
86 | if (!filename || (len=strlen(filename)) <= 4 || | ||
87 | strcasecmp(&filename[len-4], ".m3u")) | ||
88 | filename = DEFAULT_DYNAMIC_PLAYLIST_NAME; | ||
89 | |||
90 | if (!kbd_input(filename, sizeof(filename))) | ||
91 | { | ||
92 | playlist_save(playlist, filename); | ||
93 | |||
94 | /* reload in case playlist was saved to cwd */ | ||
95 | reload_directory(); | ||
96 | } | ||
97 | |||
98 | return 0; | ||
99 | } | ||
diff --git a/apps/playlist_menu.h b/apps/playlist_menu.h index e10fc81299..db841c371d 100644 --- a/apps/playlist_menu.h +++ b/apps/playlist_menu.h | |||
@@ -19,6 +19,9 @@ | |||
19 | #ifndef _PLAYLIST_MENU_H | 19 | #ifndef _PLAYLIST_MENU_H |
20 | #define _PLAYLIST_MENU_H | 20 | #define _PLAYLIST_MENU_H |
21 | 21 | ||
22 | #include "playlist.h" | ||
23 | |||
22 | bool playlist_menu(void); | 24 | bool playlist_menu(void); |
25 | int save_playlist_screen(struct playlist_info* playlist); | ||
23 | 26 | ||
24 | #endif | 27 | #endif |
diff --git a/apps/playlist_viewer.c b/apps/playlist_viewer.c index 6dc168d49a..ddc238cb27 100644 --- a/apps/playlist_viewer.c +++ b/apps/playlist_viewer.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include "list.h" | 46 | #include "list.h" |
47 | #include "statusbar.h" | 47 | #include "statusbar.h" |
48 | #include "splash.h" | 48 | #include "splash.h" |
49 | #include "playlist_menu.h" | ||
49 | 50 | ||
50 | /* Maximum number of tracks we can have loaded at one time */ | 51 | /* Maximum number of tracks we can have loaded at one time */ |
51 | #define MAX_PLAYLIST_ENTRIES 200 | 52 | #define MAX_PLAYLIST_ENTRIES 200 |
@@ -543,17 +544,7 @@ static bool track_display(void) | |||
543 | /* Save playlist to disk */ | 544 | /* Save playlist to disk */ |
544 | static bool save_playlist(void) | 545 | static bool save_playlist(void) |
545 | { | 546 | { |
546 | char filename[MAX_PATH+1]; | 547 | save_playlist_screen(viewer.playlist); |
547 | |||
548 | strncpy(filename, DEFAULT_VIEWER_PLAYLIST_NAME, sizeof(filename)); | ||
549 | |||
550 | if (!kbd_input(filename, sizeof(filename))) | ||
551 | { | ||
552 | playlist_save(viewer.playlist, filename); | ||
553 | /* reload in case playlist was saved to cwd */ | ||
554 | reload_directory(); | ||
555 | } | ||
556 | |||
557 | return false; | 548 | return false; |
558 | } | 549 | } |
559 | 550 | ||