mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-27 15:45:56 -05:00
[filescanner] Fix and refactor scanning of playlists
This commit is contained in:
parent
f5c65d1eef
commit
f4aade7f3a
@ -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;
|
||||
|
||||
|
@ -20,4 +20,7 @@ void
|
||||
scan_itunes_itml(char *file);
|
||||
#endif
|
||||
|
||||
const char *
|
||||
filename_from_path(const char *path);
|
||||
|
||||
#endif /* !__FILESCANNER_H__ */
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user