diff options
Diffstat (limited to 'apps/playlist.c')
-rwxr-xr-x | apps/playlist.c | 237 |
1 files changed, 94 insertions, 143 deletions
diff --git a/apps/playlist.c b/apps/playlist.c index 43aa97790b..db93344ef1 100755 --- a/apps/playlist.c +++ b/apps/playlist.c @@ -86,7 +86,7 @@ #include "screens.h" #include "core_alloc.h" #include "misc.h" -#include "filefuncs.h" +#include "pathfuncs.h" #include "button.h" #include "filetree.h" #include "abrepeat.h" @@ -107,6 +107,8 @@ #include "panic.h" #include "logdiskf.h" +#undef HAVE_DIRCACHE + #define PLAYLIST_CONTROL_FILE_VERSION 2 /* @@ -180,8 +182,8 @@ static int get_next_directory(char *dir); static int get_next_dir(char *dir, bool is_forward); static int get_previous_directory(char *dir); static int check_subdir_for_music(char *dir, const char *subdir, bool recurse); -static int format_track_path(char *dest, char *src, int buf_length, int max, - const char *dir); +static ssize_t format_track_path(char *dest, char *src, int buf_length, + const char *dir); static void display_playlist_count(int count, const unsigned char *fmt, bool final); static void display_buffer_full(void); @@ -526,7 +528,7 @@ static int add_indices_to_playlist(struct playlist_info* playlist, int result = 0; /* get emergency buffer so we don't fail horribly */ if (!buflen) - buffer = __builtin_alloca((buflen = 64)); + buffer = alloca((buflen = 64)); if(-1 == playlist->fd) playlist->fd = open_utf8(playlist->filename, O_RDONLY); @@ -1429,7 +1431,7 @@ static int get_filename(struct playlist_info* playlist, int index, int seek, strlcpy(dir_buf, playlist->filename, playlist->dirlen); - return (format_track_path(buf, tmp_buf, buf_length, max, dir_buf)); + return format_track_path(buf, tmp_buf, buf_length, dir_buf); } static int get_next_directory(char *dir){ @@ -1629,7 +1631,7 @@ static int get_next_dir(char *dir, bool is_forward) static int check_subdir_for_music(char *dir, const char *subdir, bool recurse) { int result = -1; - int dirlen = strlen(dir); + size_t dirlen = strlen(dir); int num_files = 0; int i; struct entry *files; @@ -1637,12 +1639,11 @@ static int check_subdir_for_music(char *dir, const char *subdir, bool recurse) bool has_subdir = false; struct tree_context* tc = tree_get_context(); - snprintf( - dir + dirlen, MAX_PATH - dirlen, - /* only add a trailing slash if we need one */ - dirlen && dir[dirlen - 1] == '/' ? "%s" : "/%s", - subdir - ); + if (path_append(dir + dirlen, PA_SEP_HARD, subdir, MAX_PATH - dirlen) >= + MAX_PATH - dirlen) + { + return 0; + } if (ft_load(tc, dir) < 0) { @@ -1695,7 +1696,7 @@ static int check_subdir_for_music(char *dir, const char *subdir, bool recurse) } else { - strcpy(dir, "/"); + strcpy(dir, PATH_ROOTSTR); } /* we now need to reload our current directory */ @@ -1708,79 +1709,31 @@ static int check_subdir_for_music(char *dir, const char *subdir, bool recurse) /* * Returns absolute path of track */ -static int format_track_path(char *dest, char *src, int buf_length, int max, - const char *dir) +static ssize_t format_track_path(char *dest, char *src, int buf_length, + const char *dir) { - int i = 0; - int j; - char *temp_ptr; - - /* Look for the end of the string */ - while((i < max) && - (src[i] != '\n') && - (src[i] != '\r') && - (src[i] != '\0')) - i++; - - /* Now work back killing white space */ - while((i > 0) && - ((src[i-1] == ' ') || - (src[i-1] == '\t'))) - i--; + size_t len; - /* Zero-terminate the file name */ - src[i]=0; + /* strip whitespace at beginning and end */ + len = path_trim_whitespace(src, (const char **)&src); + src[len] = '\0'; /* replace backslashes with forward slashes */ - for ( j=0; j<i; j++ ) - if ( src[j] == '\\' ) - src[j] = '/'; + path_correct_separators(src, src); - if('/' == src[0]) - { - strlcpy(dest, src, buf_length); - } - else - { - /* handle dos style drive letter */ - if (':' == src[1]) - strlcpy(dest, &src[2], buf_length); - else if (!strncmp(src, "../", 3)) - { - /* handle relative paths */ - i=3; - while(!strncmp(&src[i], "../", 3)) - i += 3; - for (j=0; j<i/3; j++) { - temp_ptr = strrchr(dir, '/'); - if (temp_ptr) - *temp_ptr = '\0'; - else - break; - } - snprintf(dest, buf_length, "%s/%s", dir, &src[i]); - } - else if ( '.' == src[0] && '/' == src[1] ) { - snprintf(dest, buf_length, "%s/%s", dir, &src[2]); - } - else { - snprintf(dest, buf_length, "%s/%s", dir, src); - } - } -#ifdef HAVE_MULTIVOLUME + /* handle DOS style drive letter and parse non-greedily so that: + * 1) "c:/foo" becomes "/foo" and the result is absolute + * 2) "c:foo becomes "foo" and the result is relative + * This is how Windows seems to handle it except drive letters are of no + * meaning here. */ + path_strip_drive(src, (const char **)&src, false); - char vol_string[VOL_ENUM_POS + 8]; - snprintf(vol_string, sizeof(vol_string), "/"VOL_NAMES, 1); + /* prepends directory only if src is relative */ + len = path_append(dest, *dir ? dir : PATH_ROOTSTR, src, buf_length); + if (len >= (size_t)buf_length) + return -1; /* buffer too small */ - /*check if the playlist is on a external card, and correct path if needed */ - if(strstr(dir, vol_string) && (strstr(dest, vol_string) == NULL)){ - char temp[buf_length]; - strlcpy(temp, dest, buf_length); - snprintf(dest, buf_length, "%s%s", vol_string, temp); - } -#endif - - return 0; + return len; } /* @@ -3113,8 +3066,7 @@ int playlist_insert_playlist(struct playlist_info* playlist, const char *filenam { int fd; int max; - char *temp_ptr; - const char *dir; + char *dir; unsigned char *count_str; char temp_buf[MAX_PATH+1]; char trackname[MAX_PATH+1]; @@ -3139,13 +3091,8 @@ int playlist_insert_playlist(struct playlist_info* playlist, const char *filenam } /* we need the directory name for formatting purposes */ - dir = filename; - - temp_ptr = strrchr(filename+1,'/'); - if (temp_ptr) - *temp_ptr = 0; - else - dir = "/"; + size_t dirlen = path_dirname(filename, (const char **)&dir); + dir = strmemdupa(dir, dirlen); if (queue) count_str = ID2P(LANG_PLAYLIST_QUEUE_COUNT); @@ -3183,8 +3130,8 @@ int playlist_insert_playlist(struct playlist_info* playlist, const char *filenam /* we need to format so that relative paths are correctly handled */ - if (format_track_path(trackname, temp_buf, sizeof(trackname), max, - dir) < 0) + if (format_track_path(trackname, temp_buf, sizeof(trackname), + dir) < 0) { result = -1; break; @@ -3223,9 +3170,6 @@ int playlist_insert_playlist(struct playlist_info* playlist, const char *filenam close(fd); - if (temp_ptr) - *temp_ptr = '/'; - sync_control(playlist, false); cpu_boost(false); @@ -3537,9 +3481,9 @@ int playlist_save(struct playlist_info* playlist, char *filename, char path[MAX_PATH+1]; char tmp_buf[MAX_PATH+1]; int result = 0; - bool overwrite_current = false; int *seek_buf; bool reparse; + ssize_t pathlen; ALIGN_BUFFER(temp_buffer, temp_buffer_size, sizeof(int)); seek_buf = temp_buffer; @@ -3557,22 +3501,18 @@ int playlist_save(struct playlist_info* playlist, char *filename, return -1; /* use current working directory as base for pathname */ - if (format_track_path(path, filename, sizeof(tmp_buf), - strlen(filename)+1, "/") < 0) + pathlen = format_track_path(path, filename, sizeof(path), PATH_ROOTSTR); + if (pathlen < 0) + return -1; + + /* Use temporary pathname and overwrite/rename later */ + if (strlcat(path, "_temp", sizeof(path)) >= sizeof (path)) return -1; /* can ignore volatile here, because core_get_data() is called later */ char* old_buffer = (char*)playlist->buffer; size_t old_buffer_size = playlist->buffer_size; - if (!strncmp(playlist->filename, path, strlen(path))) - { - /* Attempting to overwrite current playlist file. - * use temporary pathname and overwrite later */ - strlcat(path, "_temp", sizeof(path)); - overwrite_current = true; - } - if (is_m3u8(path)) { fd = open_utf8(path, O_CREAT|O_WRONLY|O_TRUNC); @@ -3621,8 +3561,8 @@ int playlist_save(struct playlist_info* playlist, char *filename, break; } - if (overwrite_current && !reparse) - seek_buf[count] = lseek(fd, 0, SEEK_CUR); + if (!reparse) + seek_buf[count] = filesize(fd); if (fdprintf(fd, "%s\n", tmp_buf) < 0) { @@ -3647,57 +3587,61 @@ int playlist_save(struct playlist_info* playlist, char *filename, index = (index+1)%playlist->amount; } - display_playlist_count(count, ID2P(LANG_PLAYLIST_SAVE_COUNT), true); - close(fd); + fd = -1; - if (overwrite_current && result >= 0) + display_playlist_count(count, ID2P(LANG_PLAYLIST_SAVE_COUNT), true); + + if (result >= 0) { - result = -1; + strmemcpy(tmp_buf, path, pathlen); /* remove "_temp" */ mutex_lock(playlist->control_mutex); - /* Replace the current playlist with the new one and update indices */ - close(playlist->fd); - playlist->fd = -1; - if (remove(playlist->filename) >= 0) + if (!rename(path, tmp_buf)) { - if (rename(path, playlist->filename) >= 0) + fd = open_utf8(tmp_buf, O_RDONLY); + if (fsamefile(fd, playlist->fd) > 0) { - playlist->fd = open_utf8(playlist->filename, O_RDONLY); - if (playlist->fd >= 0) + /* Replace the current playlist with the new one and update + indices */ + close(playlist->fd); + playlist->fd = fd; + fd = -1; + + if (!reparse) { - if (!reparse) + index = playlist->first_index; + for (i=0, count=0; i<playlist->amount; i++) { - index = playlist->first_index; - for (i=0, count=0; i<playlist->amount; i++) + if (!(playlist->indices[index] & PLAYLIST_QUEUE_MASK)) { - if (!(playlist->indices[index] & PLAYLIST_QUEUE_MASK)) - { - playlist->indices[index] = seek_buf[count]; - count++; - } - index = (index+1)%playlist->amount; + playlist->indices[index] = seek_buf[count]; + count++; } + 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 */ - result = recreate_control(playlist); } - } - } + else + { + NOTEF("reparsing current playlist (slow)"); + playlist->amount = 0; + add_indices_to_playlist(playlist, temp_buffer, + temp_buffer_size); + } - mutex_unlock(playlist->control_mutex); + /* we need to recreate control because inserted tracks are + now part of the playlist and shuffle has been invalidated */ + result = recreate_control(playlist); + } + } + mutex_unlock(playlist->control_mutex); } + if (fd >= 0) + close(fd); + cpu_boost(false); reset_old_buffer: @@ -3759,8 +3703,12 @@ int playlist_directory_tracksearch(const char* dirname, bool recurse, if (recurse) { /* recursively add directories */ - snprintf(buf, sizeof(buf), "%s/%s", - dirname[1]? dirname: "", files[i].name); + if (path_append(buf, dirname, files[i].name, sizeof(buf)) + >= sizeof(buf)) + { + continue; + } + result = playlist_directory_tracksearch(buf, recurse, callback, context); if (result < 0) @@ -3785,8 +3733,11 @@ int playlist_directory_tracksearch(const char* dirname, bool recurse, } else if ((files[i].attr & FILE_ATTR_MASK) == FILE_ATTR_AUDIO) { - snprintf(buf, sizeof(buf), "%s/%s", - dirname[1]? dirname: "", files[i].name); + if (path_append(buf, dirname, files[i].name, sizeof(buf)) + >= sizeof(buf)) + { + continue; + } if (callback(buf, context) != 0) { |