diff --git a/apps/menus/playlist_menu.c b/apps/menus/playlist_menu.c index be3ad307c4..f4fa6bc653 100644 --- a/apps/menus/playlist_menu.c +++ b/apps/menus/playlist_menu.c @@ -61,7 +61,7 @@ int save_playlist_screen(struct playlist_info* playlist) if (!kbd_input(temp, sizeof(temp))) { - playlist_save(playlist, temp); + playlist_save(playlist, temp, NULL, 0); /* reload in case playlist was saved to cwd */ reload_directory(); @@ -113,4 +113,3 @@ MAKE_MENU(playlist_options, ID2P(LANG_PLAYLISTS), NULL, Icon_Playlist, &create_playlist_item, &view_cur_playlist, &save_playlist, &clear_catalog_directory_item); - diff --git a/apps/playlist.c b/apps/playlist.c index a066dd2ea0..b0f7964178 100755 --- a/apps/playlist.c +++ b/apps/playlist.c @@ -105,6 +105,7 @@ #include "root_menu.h" #include "plugin.h" /* To borrow a temp buffer to rewrite a .m3u8 file */ #include "panic.h" +#include "logdiskf.h" #define PLAYLIST_CONTROL_FILE_VERSION 2 @@ -523,6 +524,9 @@ static int add_indices_to_playlist(struct playlist_info* playlist, bool store_index; unsigned char *p; int result = 0; + /* get emergency buffer so we don't fail horribly */ + if (!buflen) + buffer = __builtin_alloca((buflen = 64)); if(-1 == playlist->fd) playlist->fd = open_utf8(playlist->filename, O_RDONLY); @@ -1983,8 +1987,6 @@ static int move_callback(int handle, void* current, void* new) playlist->indices = new; else if (current == playlist->filenames) playlist->filenames = new; - /* buffer can possibly point to a new buffer temporarily (playlist_save()). - * just don't overwrite the pointer to that temp buffer */ else if (current == playlist->buffer) playlist->buffer = new; @@ -3528,8 +3530,11 @@ int playlist_get_track_info(struct playlist_info* playlist, int index, return 0; } -/* save the current dynamic playlist to specified file */ -int playlist_save(struct playlist_info* playlist, char *filename) +/* save the current dynamic playlist to specified file. The + * temp_buffer (if not NULL) is used as a scratchpad when loading indices + * (slow if not used). */ +int playlist_save(struct playlist_info* playlist, char *filename, + void* temp_buffer, size_t temp_buffer_size) { int fd; int i, index; @@ -3538,6 +3543,17 @@ int playlist_save(struct playlist_info* playlist, char *filename) char tmp_buf[MAX_PATH+1]; int result = 0; bool overwrite_current = false; + int *seek_buf; + bool reparse; + + ALIGN_BUFFER(temp_buffer, temp_buffer_size, sizeof(int)); + seek_buf = temp_buffer; + + /* without temp_buffer, or when it's depleted, and we overwrite the current + * playlist then the newly saved playlist has to be reparsed. With + * sufficient temp_buffer the indicies be remembered and added without + * reparsing */ + reparse = temp_buffer_size == 0; if (!playlist) playlist = ¤t_playlist; @@ -3556,23 +3572,9 @@ int playlist_save(struct playlist_info* playlist, char *filename) if (!strncmp(playlist->filename, path, strlen(path))) { - /* Attempting to overwrite current playlist file.*/ - - if (playlist->buffer_size < (int)(playlist->amount * sizeof(int))) - { - /* not enough buffer space to store updated indices */ - /* Try to get a buffer */ - playlist->buffer = plugin_get_buffer((size_t*)&playlist->buffer_size); - if (playlist->buffer_size < (int)(playlist->amount * sizeof(int))) - { - splash(HZ*2, ID2P(LANG_PLAYLIST_ACCESS_ERROR)); - result = -1; - goto reset_old_buffer; - } - } - - /* use temporary pathname */ - snprintf(path, sizeof(path), "%s_temp", playlist->filename); + /* Attempting to overwrite current playlist file. + * use temporary pathname and overwrite later */ + strlcat(path, "_temp", sizeof(path)); overwrite_current = true; } @@ -3624,8 +3626,8 @@ int playlist_save(struct playlist_info* playlist, char *filename) break; } - if (overwrite_current) - playlist->seek_buf[count] = lseek(fd, 0, SEEK_CUR); + if (overwrite_current && !reparse) + seek_buf[count] = lseek(fd, 0, SEEK_CUR); if (fdprintf(fd, "%s\n", tmp_buf) < 0) { @@ -3635,6 +3637,10 @@ int playlist_save(struct playlist_info* playlist, char *filename) } count++; + /* when our temp buffer is depleted we have to fall + * back to reparsing the playlist (slow) */ + if (count*sizeof(int) >= temp_buffer_size) + reparse = true; if ((count % PLAYLIST_DISPLAY_COUNT) == 0) display_playlist_count(count, ID2P(LANG_PLAYLIST_SAVE_COUNT), @@ -3666,17 +3672,25 @@ int playlist_save(struct playlist_info* playlist, char *filename) playlist->fd = open_utf8(playlist->filename, O_RDONLY); if (playlist->fd >= 0) { - index = playlist->first_index; - for (i=0, count=0; iamount; i++) + if (!reparse) { - if (!(playlist->indices[index] & PLAYLIST_QUEUE_MASK)) + index = playlist->first_index; + for (i=0, count=0; iamount; i++) { - playlist->indices[index] = playlist->seek_buf[count]; - count++; + if (!(playlist->indices[index] & PLAYLIST_QUEUE_MASK)) + { + playlist->indices[index] = seek_buf[count]; + count++; + } + index = (index+1)%playlist->amount; } - index = (index+1)%playlist->amount; } - + else + { + NOTEF("reparsing current playlist (slow)"); + playlist->amount = 0; + add_indices_to_playlist(playlist, temp_buffer, temp_buffer_size); + } /* we need to recreate control because inserted tracks are now part of the playlist and shuffle has been invalidated */ diff --git a/apps/playlist.h b/apps/playlist.h index 6314e9a6ee..a331838fde 100644 --- a/apps/playlist.h +++ b/apps/playlist.h @@ -88,10 +88,7 @@ struct playlist_info bool in_ram; /* playlist stored in ram (dirplay) */ int buffer_handle; /* handle to the below buffer (-1 if non-buflib) */ - union { - volatile char *buffer;/* buffer for in-ram playlists */ - int *seek_buf; /* buffer for seeks in real playlists */ - }; + volatile char *buffer;/* buffer for in-ram playlists */ int buffer_size; /* size of buffer */ int buffer_end_pos; /* last position where buffer was written */ int index; /* index of current playing track */ @@ -184,7 +181,8 @@ char *playlist_get_name(const struct playlist_info* playlist, char *buf, int buf_size); int playlist_get_track_info(struct playlist_info* playlist, int index, struct playlist_track_info* info); -int playlist_save(struct playlist_info* playlist, char *filename); +int playlist_save(struct playlist_info* playlist, char *filename, + void* temp_buffer, size_t temp_buffer_size); int playlist_directory_tracksearch(const char* dirname, bool recurse, int (*callback)(char*, void*), void* context);