summaryrefslogtreecommitdiff
path: root/apps/playlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/playlist.c')
-rw-r--r--apps/playlist.c184
1 files changed, 176 insertions, 8 deletions
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);
144static void create_control(struct playlist_info* playlist); 144static void create_control(struct playlist_info* playlist);
145static int check_control(struct playlist_info* playlist); 145static int check_control(struct playlist_info* playlist);
146static int recreate_control(struct playlist_info* playlist);
146static void update_playlist_filename(struct playlist_info* playlist, 147static void update_playlist_filename(struct playlist_info* playlist,
147 const char *dir, const char *file); 148 const char *dir, const char *file);
148static int add_indices_to_playlist(struct playlist_info* playlist, 149static 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 */
328static 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 */
327static void update_playlist_filename(struct playlist_info* playlist, 429static 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 = &current_playlist; 3225 playlist = &current_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}