From 7dd8955a92b68d1347085828fa804a448da893bb Mon Sep 17 00:00:00 2001 From: chme Date: Thu, 12 Apr 2018 20:43:05 +0200 Subject: [PATCH] [filescanner] Add http stream to the library prior to adding to a persistent playlist --- src/db.h | 3 + src/httpd_dacp.c | 4 +- src/library/filescanner.c | 103 ++++++++++++++++------------- src/library/filescanner.h | 3 + src/library/filescanner_playlist.c | 24 +++---- src/mpd.c | 2 +- 6 files changed, 76 insertions(+), 63 deletions(-) diff --git a/src/db.h b/src/db.h index f7c244ec..7c74c748 100644 --- a/src/db.h +++ b/src/db.h @@ -78,6 +78,9 @@ enum query_type { /* Max value for media_file_info->rating (valid range is from 0 to 100) */ #define DB_FILES_RATING_MAX 100 +/* Magic id for media_file_info objects that are not stored in the files database table */ +#define DB_MEDIA_FILE_NON_PERSISTENT_ID 9999999 + struct query_params { /* Query parameters, filled in by caller */ enum query_type type; diff --git a/src/httpd_dacp.c b/src/httpd_dacp.c index ef2dbef9..a7362d39 100644 --- a/src/httpd_dacp.c +++ b/src/httpd_dacp.c @@ -143,7 +143,7 @@ static int seek_target; /* If an item is removed from the library while in the queue, we replace it with this */ static struct media_file_info dummy_mfi = { - .id = 9999999, + .id = DB_MEDIA_FILE_NON_PERSISTENT_ID, .title = "(unknown title)", .artist = "(unknown artist)", .album = "(unknown album)", @@ -151,7 +151,7 @@ static struct media_file_info dummy_mfi = }; static struct db_queue_item dummy_queue_item = { - .file_id = 9999999, + .file_id = DB_MEDIA_FILE_NON_PERSISTENT_ID, .title = "(unknown title)", .artist = "(unknown artist)", .album = "(unknown album)", diff --git a/src/library/filescanner.c b/src/library/filescanner.c index 7b6d787e..fd36704b 100644 --- a/src/library/filescanner.c +++ b/src/library/filescanner.c @@ -1651,7 +1651,7 @@ map_media_file_to_queue_item(struct db_queue_item *queue_item, struct media_file if (mfi->id) queue_item->file_id = mfi->id; else - queue_item->file_id = 9999999; + queue_item->file_id = DB_MEDIA_FILE_NON_PERSISTENT_ID; queue_item->title = safe_strdup(mfi->title); queue_item->artist = safe_strdup(mfi->artist); @@ -1679,43 +1679,13 @@ static int queue_add_stream(const char *path) { struct media_file_info mfi; - char *pos; struct db_queue_item item; struct db_queue_add_info queue_add_info; int ret; memset(&mfi, 0, sizeof(struct media_file_info)); - mfi.path = strdup(path); - mfi.virtual_path = safe_asprintf("/%s", mfi.path); - - pos = strchr(path, '#'); - if (pos) - mfi.fname = strdup(pos+1); - else - mfi.fname = strdup(filename_from_path(mfi.path)); - - mfi.data_kind = DATA_KIND_HTTP; - 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); - - if (!mfi.virtual_path) - mfi.virtual_path = strdup(mfi.path); - if (!mfi.item_kind) - mfi.item_kind = 2; /* music */ - if (!mfi.media_kind) - mfi.media_kind = MEDIA_KIND_MUSIC; /* music */ + scan_metadata_stream(path, &mfi); unicode_fixup_mfi(&mfi); map_media_file_to_queue_item(&item, &mfi); @@ -1891,6 +1861,8 @@ playlist_add_files(FILE *fp, int pl_id, const char *virtual_path) struct query_params qp; struct db_media_file_info dbmfi; uint32_t data_kind; + const char *path; + struct media_file_info mfi; int ret; memset(&qp, 0, sizeof(struct query_params)); @@ -1901,28 +1873,45 @@ playlist_add_files(FILE *fp, int pl_id, const char *virtual_path) ret = db_query_start(&qp); if (ret < 0) - { - db_query_end(&qp); - free(qp.filter); - return -1; - } + goto out; - while (((ret = db_query_fetch_file(&qp, &dbmfi)) == 0) && (dbmfi.id)) + if (qp.results > 0) { - if ((safe_atou32(dbmfi.data_kind, &data_kind) < 0) - || (data_kind == DATA_KIND_PIPE)) - { - DPRINTF(E_WARN, L_SCAN, "Item '%s' not added to playlist (id = %d), unsupported data kind\n", dbmfi.path, pl_id); - continue; + while (((ret = db_query_fetch_file(&qp, &dbmfi)) == 0) && (dbmfi.id)) + { + if ((safe_atou32(dbmfi.data_kind, &data_kind) < 0) + || (data_kind == DATA_KIND_PIPE)) + { + DPRINTF(E_WARN, L_SCAN, "Item '%s' not added to playlist (id = %d), unsupported data kind\n", dbmfi.path, pl_id); + continue; + } + + ret = playlist_add_path(fp, pl_id, dbmfi.path); + if (ret < 0) + break; + + DPRINTF(E_DBG, L_SCAN, "Item '%s' added to playlist (id = %d)\n", dbmfi.path, pl_id); } + } + else if (strncasecmp(virtual_path, "/http://", strlen("/http://")) == 0) + { + path = (virtual_path + 1); - ret = playlist_add_path(fp, pl_id, dbmfi.path); + DPRINTF(E_DBG, L_SCAN, "Scan stream '%s' and add to playlist (id = %d)\n", path, pl_id); + + memset(&mfi, 0, sizeof(struct media_file_info)); + scan_metadata_stream(path, &mfi); + library_add_media(&mfi); + free_mfi(&mfi, 1); + + ret = playlist_add_path(fp, pl_id, path); if (ret < 0) - break; - - DPRINTF(E_DBG, L_SCAN, "Item '%s' added to playlist (id = %d)\n", dbmfi.path, pl_id); + DPRINTF(E_LOG, L_SCAN, "Failed to add stream '%s' to playlist (id = %d)\n", path, pl_id); + else + DPRINTF(E_DBG, L_SCAN, "Item '%s' added to playlist (id = %d)\n", path, pl_id); } + out: db_query_end(&qp); free(qp.filter); @@ -2017,6 +2006,7 @@ queue_save(const char *virtual_path) FILE *fp; struct query_params query_params; struct db_queue_item queue_item; + struct media_file_info mfi; int pl_id; int ret; @@ -2058,6 +2048,25 @@ queue_save(const char *virtual_path) continue; } + if (queue_item.file_id == DB_MEDIA_FILE_NON_PERSISTENT_ID) + { + // If the queue item is not in the library and it is a http stream, scan and add to the library prior to saving to the playlist file. + if (queue_item.data_kind == DATA_KIND_HTTP) + { + DPRINTF(E_DBG, L_SCAN, "Scan stream '%s' and add to playlist (id = %d)\n", queue_item.path, pl_id); + + memset(&mfi, 0, sizeof(struct media_file_info)); + scan_metadata_stream(queue_item.path, &mfi); + library_add_media(&mfi); + free_mfi(&mfi, 1); + } + else + { + DPRINTF(E_LOG, L_SCAN, "Unsupported item for playlist file '%s' ignoring item '%s'\n", virtual_path, queue_item.path); + continue; + } + } + ret = fprintf(fp, "%s\n", queue_item.path); if (ret < 0) { diff --git a/src/library/filescanner.h b/src/library/filescanner.h index b65216a8..3f225e77 100644 --- a/src/library/filescanner.h +++ b/src/library/filescanner.h @@ -10,6 +10,9 @@ int scan_metadata_ffmpeg(const char *file, struct media_file_info *mfi); +void +scan_metadata_stream(const char *path, struct media_file_info *mfi); + void scan_playlist(const char *file, time_t mtime, int dir_id); diff --git a/src/library/filescanner_playlist.c b/src/library/filescanner_playlist.c index 08ef4962..e81a1fda 100644 --- a/src/library/filescanner_playlist.c +++ b/src/library/filescanner_playlist.c @@ -72,18 +72,14 @@ extinf_get(char *string, struct media_file_info *mfi, int *extinf) return 1; } -static int -process_url(int pl_id, const char *path, time_t mtime, int extinf, struct media_file_info *mfi) +void +scan_metadata_stream(const char *path, struct media_file_info *mfi) { - char virtual_path[PATH_MAX]; char *pos; int ret; - if (extinf) - DPRINTF(E_INFO, L_SCAN, "Playlist has EXTINF metadata, artist is '%s', title is '%s'\n", mfi->artist, mfi->title); - - mfi->id = db_file_id_bypath(path); mfi->path = strdup(path); + mfi->virtual_path = safe_asprintf("/%s", mfi->path); pos = strchr(path, '#'); if (pos) @@ -92,7 +88,7 @@ process_url(int pl_id, const char *path, time_t mtime, int extinf, struct media_ mfi->fname = strdup(filename_from_path(mfi->path)); mfi->data_kind = DATA_KIND_HTTP; - mfi->time_modified = mtime; + mfi->time_modified = time(NULL); mfi->directory_id = DIR_HTTP; ret = scan_metadata_ffmpeg(path, mfi); @@ -106,12 +102,14 @@ process_url(int pl_id, const char *path, time_t mtime, int extinf, struct media_ if (!mfi->title) mfi->title = strdup(mfi->fname); +} - snprintf(virtual_path, sizeof(virtual_path), "/%s", mfi->path); - mfi->virtual_path = strdup(virtual_path); - +static int +process_url(int pl_id, const char *path, struct media_file_info *mfi) +{ + mfi->id = db_file_id_bypath(path); + scan_metadata_stream(path, mfi); library_add_media(mfi); - return db_pl_add_item_bypath(pl_id, path); } @@ -341,7 +339,7 @@ scan_playlist(const char *file, time_t mtime, int dir_id) /* Check if line is an URL, will be added to library, otherwise it should already be there */ if (strncasecmp(path, "http://", 7) == 0) - ret = process_url(pl_id, path, sb.st_mtime, extinf, &mfi); + ret = process_url(pl_id, path, &mfi); else ret = process_regular_file(pl_id, path); diff --git a/src/mpd.c b/src/mpd.c index 84d2adf5..71165a26 100644 --- a/src/mpd.c +++ b/src/mpd.c @@ -2510,7 +2510,7 @@ mpd_command_playlistadd(struct evbuffer *evbuf, int argc, char **argv, char **er free(vp_item); if (ret < 0) { - *errmsg = safe_asprintf("Error saving queue to file '%s'", argv[1]); + *errmsg = safe_asprintf("Error adding item to file '%s'", argv[1]); return ACK_ERROR_ARG; }