diff --git a/src/library/filescanner.c b/src/library/filescanner.c index 5ecdc61a..f12763e1 100644 --- a/src/library/filescanner.c +++ b/src/library/filescanner.c @@ -162,6 +162,20 @@ static int filescanner_fullrescan(); +const char * +filename_from_path(const char *path) +{ + const char *filename; + + filename = strrchr(path, '/'); + if ((!filename) || (strlen(filename) == 1)) + filename = path; + else + filename++; + + return filename; +} + static int push_dir(struct stacked_dir **s, char *path, int parent_id) { @@ -417,7 +431,7 @@ process_regular_file(char *file, struct stat *sb, int type, int flags, int dir_i memset(&mfi, 0, sizeof(struct media_file_info)); mfi.id = id; - mfi.fname = strdup(basename(file)); + mfi.fname = strdup(filename_from_path(file)); mfi.path = strdup(file); mfi.time_modified = sb->st_mtime; @@ -1538,7 +1552,7 @@ scan_metadata(const char *path, struct media_file_info *mfi) { memset(mfi, 0, sizeof(struct media_file_info)); mfi->path = strdup(path); - mfi->fname = strdup(basename(mfi->path)); + mfi->fname = strdup(filename_from_path(mfi->path)); mfi->data_kind = DATA_KIND_HTTP; mfi->directory_id = DIR_HTTP; diff --git a/src/library/filescanner.h b/src/library/filescanner.h index 9e9b89e8..8279f15d 100644 --- a/src/library/filescanner.h +++ b/src/library/filescanner.h @@ -20,4 +20,7 @@ void scan_itunes_itml(char *file); #endif +const char * +filename_from_path(const char *path); + #endif /* !__FILESCANNER_H__ */ diff --git a/src/library/filescanner_playlist.c b/src/library/filescanner_playlist.c index f44f95a3..a34ba465 100644 --- a/src/library/filescanner_playlist.c +++ b/src/library/filescanner_playlist.c @@ -75,6 +75,112 @@ extinf_get(char *string, struct media_file_info *mfi, int *extinf) return 1; } +static int +process_url(const char *path, time_t mtime, int extinf, struct media_file_info *mfi, char **filename) +{ + char virtual_path[PATH_MAX]; + time_t stamp; + int id; + int ret; + + *filename = strdup(path); + + db_file_stamp_bypath(path, &stamp, &id); + if (stamp && (stamp >= mtime)) + { + db_file_ping(id); + return 0; + } + + if (extinf) + DPRINTF(E_INFO, L_SCAN, "Playlist has EXTINF metadata, artist is '%s', title is '%s'\n", mfi->artist, mfi->title); + + mfi->id = id; + mfi->path = strdup(path); + mfi->fname = strdup(filename_from_path(path)); + mfi->data_kind = DATA_KIND_HTTP; + mfi->time_modified = mtime; + mfi->directory_id = DIR_HTTP; + + ret = scan_metadata_ffmpeg(path, mfi); + if (ret < 0) + { + DPRINTF(E_LOG, L_SCAN, "Playlist URL '%s' is unavailable for probe/metadata, assuming MP3 encoding\n", path); + mfi->type = strdup("mp3"); + mfi->codectype = strdup("mpeg"); + mfi->description = strdup("MPEG audio file"); + } + + if (!mfi->title) + mfi->title = strdup(mfi->fname); + + snprintf(virtual_path, PATH_MAX, "/http:/%s", mfi->title); + mfi->virtual_path = strdup(virtual_path); + + library_add_media(mfi); + + return 0; +} + +int +process_regular_file(char *path, char **filename) +{ + int i; + int mfi_id; + char *ptr; + char *entry; + int ret; + + /* Playlist might be from Windows so we change backslash to forward slash */ + for (i = 0; i < strlen(path); i++) + { + if (path[i] == '\\') + path[i] = '/'; + } + + /* Now search for the library item where the path has closest match to playlist item */ + /* Succes is when we find an unambiguous match, or when we no longer can expand the */ + /* the path to refine our search. */ + entry = NULL; + do + { + ptr = strrchr(path, '/'); + if (entry) + *(entry - 1) = '/'; + + if (ptr) + { + *ptr = '\0'; + entry = ptr + 1; + } + else + entry = path; + + DPRINTF(E_SPAM, L_SCAN, "Playlist entry is now %s\n", entry); + ret = db_files_get_count_bymatch(entry); + } + while (ptr && (ret > 1)); + + if (ret > 0) + { + mfi_id = db_file_id_bymatch(entry); + DPRINTF(E_DBG, L_SCAN, "Found playlist entry match, id is %d, entry is %s\n", mfi_id, entry); + *filename = db_file_path_byid(mfi_id); + if (!(*filename)) + { + DPRINTF(E_LOG, L_SCAN, "Playlist entry %s matches file id %d, but file path is missing.\n", entry, mfi_id); + return -1; + } + } + else + { + DPRINTF(E_DBG, L_SCAN, "No match for playlist entry %s\n", entry); + return -1; + } + + return 0; +} + void scan_playlist(char *file, time_t mtime, int dir_id) { @@ -84,19 +190,15 @@ scan_playlist(char *file, time_t mtime, int dir_id) struct stat sb; char buf[PATH_MAX]; char *path; - char *entry; - char *filename; + const char *filename; char *ptr; size_t len; int extinf; int pl_id; int pl_format; - int mfi_id; int ret; char virtual_path[PATH_MAX]; - int i; - time_t stamp; - int id; + char *plitem_path; DPRINTF(E_LOG, L_SCAN, "Processing static playlist: %s\n", file); @@ -111,11 +213,7 @@ scan_playlist(char *file, time_t mtime, int dir_id) else return; - filename = strrchr(file, '/'); - if (!filename) - filename = file; - else - filename++; + filename = filename_from_path(file); ret = stat(file, &sb); if (ret < 0) @@ -231,105 +329,25 @@ scan_playlist(char *file, time_t mtime, int dir_id) { DPRINTF(E_DBG, L_SCAN, "Playlist contains URL entry: '%s'\n", path); - db_file_stamp_bypath(path, &stamp, &id); - if (stamp && (stamp >= sb.st_mtime)) - { - db_file_ping(id); - continue; - } - - filename = strdup(path); - if (!filename) - { - DPRINTF(E_LOG, L_SCAN, "Out of memory for playlist filename\n"); - - continue; - } - - if (extinf) - DPRINTF(E_INFO, L_SCAN, "Playlist has EXTINF metadata, artist is '%s', title is '%s'\n", mfi.artist, mfi.title); - - mfi.id = id; - mfi.fname = strdup(basename(filename)); - mfi.path = strdup(filename); - mfi.data_kind = DATA_KIND_HTTP; - mfi.time_modified = mtime; - mfi.directory_id = DIR_HTTP; - - ret = scan_metadata_ffmpeg(path, &mfi); - if (ret < 0) - { - DPRINTF(E_LOG, L_SCAN, "Playlist URL '%s' is unavailable for probe/metadata, assuming MP3 encoding\n", path); - mfi.type = strdup("mp3"); - mfi.codectype = strdup("mpeg"); - mfi.description = strdup("MPEG audio file"); - } - - snprintf(virtual_path, PATH_MAX, "/http:/%s", mfi.title); //TODO can title be null at this point? - mfi.virtual_path = strdup(virtual_path); - library_add_media(&mfi); + ret = process_url(path, sb.st_mtime, extinf, &mfi, &plitem_path); } /* Regular file, should already be in library */ else { - /* Playlist might be from Windows so we change backslash to forward slash */ - for (i = 0; i < strlen(path); i++) - { - if (path[i] == '\\') - path[i] = '/'; - } - - /* Now search for the library item where the path has closest match to playlist item */ - /* Succes is when we find an unambiguous match, or when we no longer can expand the */ - /* the path to refine our search. */ - entry = NULL; - do - { - ptr = strrchr(path, '/'); - if (entry) - *(entry - 1) = '/'; - if (ptr) - { - *ptr = '\0'; - entry = ptr + 1; - } - else - entry = path; - - DPRINTF(E_SPAM, L_SCAN, "Playlist entry is now %s\n", entry); - ret = db_files_get_count_bymatch(entry); - - } while (ptr && (ret > 1)); - - if (ret > 0) - { - mfi_id = db_file_id_bymatch(entry); - DPRINTF(E_DBG, L_SCAN, "Found playlist entry match, id is %d, entry is %s\n", mfi_id, entry); - - filename = db_file_path_byid(mfi_id); - if (!filename) - { - DPRINTF(E_LOG, L_SCAN, "Playlist entry %s matches file id %d, but file path is missing.\n", entry, mfi_id); - - continue; - } - } - else - { - DPRINTF(E_DBG, L_SCAN, "No match for playlist entry %s\n", entry); - - continue; - } + ret = process_regular_file(path, &plitem_path); } - ret = db_pl_add_item_bypath(pl_id, filename); - if (ret < 0) - DPRINTF(E_WARN, L_SCAN, "Could not add %s to playlist\n", filename); + if (ret == 0) + { + ret = db_pl_add_item_bypath(pl_id, plitem_path); + if (ret < 0) + DPRINTF(E_WARN, L_SCAN, "Could not add %s to playlist\n", plitem_path); - /* Clean up in preparation for next item */ - extinf = 0; - free_mfi(&mfi, 1); - free(filename); + /* Clean up in preparation for next item */ + extinf = 0; + free_mfi(&mfi, 1); + free(plitem_path); + } } /* We had some extinf that we never got to use, free it now */