From 60ebac076bd9d95840c177820f8c6985f436aece Mon Sep 17 00:00:00 2001 From: chme Date: Fri, 9 Mar 2018 19:03:43 +0100 Subject: [PATCH] Refactor adding non library items to the queue Instead of asking a client to first scan the path into a media_file_info object and afterwards add it to the queue, we now offer a library function to directly add a path. The library-source that can handle the given path translates the path into new queue item(s) and adds them to the queue. --- src/db.c | 450 +++++++++++++++++++++++++++++++++----- src/db.h | 17 +- src/library.c | 337 +--------------------------- src/library.h | 16 +- src/library/filescanner.c | 111 ++++++++-- src/mpd.c | 12 +- 6 files changed, 516 insertions(+), 427 deletions(-) diff --git a/src/db.c b/src/db.c index 275c8c5c..3365c6be 100644 --- a/src/db.c +++ b/src/db.c @@ -32,6 +32,9 @@ #include #include #include +#include +#include +#include #include #include @@ -641,6 +644,324 @@ unicode_fixup_mfi(struct media_file_info *mfi) } } +static void +sort_tag_create(char **sort_tag, char *src_tag) +{ + const uint8_t *i_ptr; + const uint8_t *n_ptr; + const uint8_t *number; + uint8_t out[1024]; + uint8_t *o_ptr; + int append_number; + ucs4_t puc; + int numlen; + size_t len; + int charlen; + + /* Note: include terminating NUL in string length for u8_normalize */ + + if (*sort_tag) + { + DPRINTF(E_DBG, L_LIB, "Existing sort tag will be normalized: %s\n", *sort_tag); + o_ptr = u8_normalize(UNINORM_NFD, (uint8_t *)*sort_tag, strlen(*sort_tag) + 1, NULL, &len); + free(*sort_tag); + *sort_tag = (char *)o_ptr; + return; + } + + if (!src_tag || ((len = strlen(src_tag)) == 0)) + { + *sort_tag = NULL; + return; + } + + // Set input pointer past article if present + if ((strncasecmp(src_tag, "a ", 2) == 0) && (len > 2)) + i_ptr = (uint8_t *)(src_tag + 2); + else if ((strncasecmp(src_tag, "an ", 3) == 0) && (len > 3)) + i_ptr = (uint8_t *)(src_tag + 3); + else if ((strncasecmp(src_tag, "the ", 4) == 0) && (len > 4)) + i_ptr = (uint8_t *)(src_tag + 4); + else + i_ptr = (uint8_t *)src_tag; + + // Poor man's natural sort. Makes sure we sort like this: a1, a2, a10, a11, a21, a111 + // We do this by padding zeroes to (short) numbers. As an alternative we could have + // made a proper natural sort algorithm in sqlext.c, but we don't, since we don't + // want any risk of hurting response times + memset(&out, 0, sizeof(out)); + o_ptr = (uint8_t *)&out; + number = NULL; + append_number = 0; + + do + { + n_ptr = u8_next(&puc, i_ptr); + + if (uc_is_digit(puc)) + { + if (!number) // We have encountered the beginning of a number + number = i_ptr; + append_number = (n_ptr == NULL); // If last char in string append number now + } + else + { + if (number) + append_number = 1; // A number has ended so time to append it + else + { + charlen = u8_strmblen(i_ptr); + if (charlen >= 0) + o_ptr = u8_stpncpy(o_ptr, i_ptr, charlen); // No numbers in sight, just append char + } + } + + // Break if less than 100 bytes remain (prevent buffer overflow) + if (sizeof(out) - u8_strlen(out) < 100) + break; + + // Break if number is very large (prevent buffer overflow) + if (number && (i_ptr - number > 50)) + break; + + if (append_number) + { + numlen = i_ptr - number; + if (numlen < 5) // Max pad width + { + u8_strcpy(o_ptr, (uint8_t *)"00000"); + o_ptr += (5 - numlen); + } + o_ptr = u8_stpncpy(o_ptr, number, numlen + u8_strmblen(i_ptr)); + + number = NULL; + append_number = 0; + } + + i_ptr = n_ptr; + } + while (n_ptr); + + *sort_tag = (char *)u8_normalize(UNINORM_NFD, (uint8_t *)&out, u8_strlen(out) + 1, NULL, &len); +} + +void +fixup_tags_mfi(struct media_file_info *mfi) +{ + cfg_t *lib; + size_t len; + char *tag; + char *sep = " - "; + char *ca; + + if (mfi->genre && (strlen(mfi->genre) == 0)) + { + free(mfi->genre); + mfi->genre = NULL; + } + + if (mfi->artist && (strlen(mfi->artist) == 0)) + { + free(mfi->artist); + mfi->artist = NULL; + } + + if (mfi->title && (strlen(mfi->title) == 0)) + { + free(mfi->title); + mfi->title = NULL; + } + + /* + * Default to mpeg4 video/audio for unknown file types + * in an attempt to allow streaming of DRM-afflicted files + */ + if (mfi->codectype && strcmp(mfi->codectype, "unkn") == 0) + { + if (mfi->has_video) + { + strcpy(mfi->codectype, "mp4v"); + strcpy(mfi->type, "m4v"); + } + else + { + strcpy(mfi->codectype, "mp4a"); + strcpy(mfi->type, "m4a"); + } + } + + if (!mfi->artist) + { + if (mfi->orchestra && mfi->conductor) + { + len = strlen(mfi->orchestra) + strlen(sep) + strlen(mfi->conductor); + tag = (char *)malloc(len + 1); + if (tag) + { + sprintf(tag,"%s%s%s", mfi->orchestra, sep, mfi->conductor); + mfi->artist = tag; + } + } + else if (mfi->orchestra) + { + mfi->artist = strdup(mfi->orchestra); + } + else if (mfi->conductor) + { + mfi->artist = strdup(mfi->conductor); + } + } + + /* Handle TV shows, try to present prettier metadata */ + if (mfi->tv_series_name && strlen(mfi->tv_series_name) != 0) + { + mfi->media_kind = MEDIA_KIND_TVSHOW; /* tv show */ + + /* Default to artist = series_name */ + if (mfi->artist && strlen(mfi->artist) == 0) + { + free(mfi->artist); + mfi->artist = NULL; + } + + if (!mfi->artist) + mfi->artist = strdup(mfi->tv_series_name); + + /* Default to album = ", Season " */ + if (mfi->album && strlen(mfi->album) == 0) + { + free(mfi->album); + mfi->album = NULL; + } + + if (!mfi->album) + { + len = snprintf(NULL, 0, "%s, Season %u", mfi->tv_series_name, mfi->tv_season_num); + + mfi->album = (char *)malloc(len + 1); + if (mfi->album) + sprintf(mfi->album, "%s, Season %u", mfi->tv_series_name, mfi->tv_season_num); + } + } + + /* Check the 4 top-tags are filled */ + if (!mfi->artist) + mfi->artist = strdup("Unknown artist"); + if (!mfi->album) + mfi->album = strdup("Unknown album"); + if (!mfi->genre) + mfi->genre = strdup("Unknown genre"); + if (!mfi->title) + { + /* fname is left untouched by unicode_fixup_mfi() for + * obvious reasons, so ensure it is proper UTF-8 + */ + mfi->title = unicode_fixup_string(mfi->fname, "ascii"); + if (mfi->title == mfi->fname) + mfi->title = strdup(mfi->fname); + } + + /* Ensure sort tags are filled, manipulated and normalized */ + sort_tag_create(&mfi->artist_sort, mfi->artist); + sort_tag_create(&mfi->album_sort, mfi->album); + sort_tag_create(&mfi->title_sort, mfi->title); + + /* We need to set album_artist according to media type and config */ + if (mfi->compilation) /* Compilation */ + { + lib = cfg_getsec(cfg, "library"); + ca = cfg_getstr(lib, "compilation_artist"); + if (ca && mfi->album_artist) + { + free(mfi->album_artist); + mfi->album_artist = strdup(ca); + } + else if (ca && !mfi->album_artist) + { + mfi->album_artist = strdup(ca); + } + else if (!ca && !mfi->album_artist) + { + mfi->album_artist = strdup(""); + mfi->album_artist_sort = strdup(""); + } + } + else if (mfi->media_kind == MEDIA_KIND_PODCAST) /* Podcast */ + { + if (mfi->album_artist) + free(mfi->album_artist); + mfi->album_artist = strdup(""); + mfi->album_artist_sort = strdup(""); + } + else if (!mfi->album_artist) /* Regular media without album_artist */ + { + mfi->album_artist = strdup(mfi->artist); + } + + if (!mfi->album_artist_sort && (strcmp(mfi->album_artist, mfi->artist) == 0)) + mfi->album_artist_sort = strdup(mfi->artist_sort); + else + sort_tag_create(&mfi->album_artist_sort, mfi->album_artist); + + /* Composer is not one of our mandatory tags, so take extra care */ + if (mfi->composer_sort || mfi->composer) + sort_tag_create(&mfi->composer_sort, mfi->composer); +} + +static void +fixup_tags_queue_item(struct db_queue_item *queue_item) +{ + if (queue_item->genre && (strlen(queue_item->genre) == 0)) + { + free(queue_item->genre); + queue_item->genre = NULL; + } + + if (queue_item->artist && (strlen(queue_item->artist) == 0)) + { + free(queue_item->artist); + queue_item->artist = NULL; + } + + if (queue_item->title && (strlen(queue_item->title) == 0)) + { + free(queue_item->title); + queue_item->title = NULL; + } + + /* Check the 4 top-tags are filled */ + if (!queue_item->artist) + queue_item->artist = strdup("Unknown artist"); + if (!queue_item->album) + queue_item->album = strdup("Unknown album"); + if (!queue_item->genre) + queue_item->genre = strdup("Unknown genre"); + if (!queue_item->title) + queue_item->title = strdup(queue_item->path); + + /* Ensure sort tags are filled, manipulated and normalized */ + sort_tag_create(&queue_item->artist_sort, queue_item->artist); + sort_tag_create(&queue_item->album_sort, queue_item->album); + + /* We need to set album_artist according to media type and config */ + if (queue_item->media_kind == MEDIA_KIND_PODCAST) /* Podcast */ + { + if (queue_item->album_artist) + free(queue_item->album_artist); + queue_item->album_artist = strdup(""); + queue_item->album_artist_sort = strdup(""); + } + else if (!queue_item->album_artist) /* Regular media without album_artist */ + { + queue_item->album_artist = strdup(queue_item->artist); + } + + if (!queue_item->album_artist_sort && (strcmp(queue_item->album_artist, queue_item->artist) == 0)) + queue_item->album_artist_sort = strdup(queue_item->artist_sort); + else + sort_tag_create(&queue_item->album_artist_sort, queue_item->album_artist); +} + /* Unlock notification support */ static void @@ -4219,6 +4540,38 @@ queue_add_file(struct db_media_file_info *dbmfi, int pos, int shuffle_pos, int q #undef Q_TMPL } +static int +queue_add_item(struct db_queue_item *item, int pos, int shuffle_pos, int queue_version) +{ +#define Q_TMPL "INSERT INTO queue " \ + "(id, file_id, song_length, data_kind, media_kind, " \ + "pos, shuffle_pos, path, virtual_path, title, " \ + "artist, album_artist, album, genre, songalbumid, " \ + "time_modified, artist_sort, album_sort, album_artist_sort, year, " \ + "track, disc, queue_version)" \ + "VALUES" \ + "(NULL, %d, %d, %d, %d, " \ + "%d, %d, %Q, %Q, %Q, " \ + "%Q, %Q, %Q, %Q, %" PRIi64 ", " \ + "%d, %Q, %Q, %Q, %d, " \ + "%d, %d, %d);" + + char *query; + int ret; + + query = sqlite3_mprintf(Q_TMPL, + item->file_id, item->song_length, item->data_kind, item->media_kind, + pos, pos, item->path, item->virtual_path, item->title, + item->artist, item->album_artist, item->album, item->genre, item->songalbumid, + item->time_modified, item->artist_sort, item->album_sort, item->album_artist_sort, item->year, + item->track, item->disc, queue_version); + ret = db_query_run(query, 1, 0); + + return ret; + +#undef Q_TMPL +} + int db_queue_update_item(struct db_queue_item *qi) { @@ -4337,6 +4690,46 @@ db_queue_add_by_queryafteritemid(struct query_params *qp, uint32_t item_id) return ret; } +int +db_queue_add_start(struct db_queue_add_info *queue_add_info) +{ + int ret = 0; + + memset(queue_add_info, 0, sizeof(struct db_queue_add_info)); + queue_add_info->queue_version = queue_transaction_begin(); + + queue_add_info->pos = db_queue_get_count(); + if (queue_add_info->pos < 0) + { + ret = -1; + queue_transaction_end(ret, queue_add_info->queue_version); + return ret; + } + + return 0; +} + +void +db_queue_add_end(struct db_queue_add_info *queue_add_info, int ret) +{ + queue_transaction_end(ret, queue_add_info->queue_version); +} + +int +db_queue_add_item(struct db_queue_add_info *queue_add_info, struct db_queue_item *item) +{ + int ret; + + fixup_tags_queue_item(item); + ret = queue_add_item(item, queue_add_info->pos, queue_add_info->pos, queue_add_info->queue_version); + if (ret == 0) + queue_add_info->pos++; + + return ret; + +#undef Q_TMPL +} + /* * Adds the files matching the given query to the queue * @@ -4465,63 +4858,6 @@ db_queue_add_by_fileid(int id, char reshuffle, uint32_t item_id) return ret; } -int -db_queue_add_item(struct db_queue_item *queue_item, char reshuffle, uint32_t item_id) -{ -#define Q_TMPL "INSERT INTO queue " \ - "(id, file_id, song_length, data_kind, media_kind, " \ - "pos, shuffle_pos, path, virtual_path, title, " \ - "artist, album_artist, album, genre, songalbumid, " \ - "time_modified, artist_sort, album_sort, album_artist_sort, year, " \ - "track, disc, queue_version)" \ - "VALUES" \ - "(NULL, %d, %d, %d, %d, " \ - "%d, %d, %Q, %Q, %Q, " \ - "%Q, %Q, %Q, %Q, %d, " \ - "%d, %Q, %Q, %Q, %d, " \ - "%d, %d, %d);" - - int queue_version; - char *query; - int pos; - int new_item_id = 0; // Quell compiler warning about uninitialized use of new_item_id - int ret; - - queue_version = queue_transaction_begin(); - - pos = db_queue_get_count(); - if (pos < 0) - { - ret = -1; - goto end_transaction; - } - - query = sqlite3_mprintf(Q_TMPL, - queue_item->file_id, queue_item->song_length, queue_item->data_kind, queue_item->media_kind, - pos, pos, queue_item->path, queue_item->virtual_path, queue_item->title, - queue_item->artist, queue_item->album_artist, queue_item->album, queue_item->genre, queue_item->songalbumid, - queue_item->time_modified, queue_item->artist_sort, queue_item->album_sort, queue_item->album_artist_sort, queue_item->year, - queue_item->track, queue_item->disc, queue_version); - ret = db_query_run(query, 1, 0); - if (ret < 0) - goto end_transaction; - - new_item_id = (int) sqlite3_last_insert_rowid(hdl); - - // Reshuffle after adding new items - if (reshuffle) - { - ret = queue_reshuffle(item_id, queue_version); - } - - end_transaction: - queue_transaction_end(ret, queue_version); - - return (ret == 0) ? new_item_id : ret; - -#undef Q_TMPL -} - static int queue_enum_start(struct query_params *qp) { diff --git a/src/db.h b/src/db.h index 149f1972..f7c244ec 100644 --- a/src/db.h +++ b/src/db.h @@ -454,6 +454,12 @@ struct db_queue_item uint32_t queue_version; }; +struct db_queue_add_info +{ + int queue_version; + int pos; +}; + char * db_escape_string(const char *str); // TODO Remove this, use db_mprintf instead @@ -484,6 +490,9 @@ free_queue_item(struct db_queue_item *queue_item, int content_only); void unicode_fixup_mfi(struct media_file_info *mfi); +void +fixup_tags_mfi(struct media_file_info *mfi); + /* Maintenance and DB hygiene */ void db_hook_post_scan(void); @@ -764,7 +773,13 @@ int db_queue_add_by_fileid(int id, char reshuffle, uint32_t item_id); int -db_queue_add_item(struct db_queue_item *queue_item, char reshuffle, uint32_t item_id); +db_queue_add_start(struct db_queue_add_info *queue_add_info); + +void +db_queue_add_end(struct db_queue_add_info *queue_add_info, int ret); + +int +db_queue_add_item(struct db_queue_add_info *queue_add_info, struct db_queue_item *item); int db_queue_enum_start(struct query_params *qp); diff --git a/src/library.c b/src/library.c index 9c101a01..90682297 100644 --- a/src/library.c +++ b/src/library.c @@ -111,270 +111,6 @@ handle_deferred_update_notifications(void) return ret; } -static void -sort_tag_create(char **sort_tag, char *src_tag) -{ - const uint8_t *i_ptr; - const uint8_t *n_ptr; - const uint8_t *number; - uint8_t out[1024]; - uint8_t *o_ptr; - int append_number; - ucs4_t puc; - int numlen; - size_t len; - int charlen; - - /* Note: include terminating NUL in string length for u8_normalize */ - - if (*sort_tag) - { - DPRINTF(E_DBG, L_LIB, "Existing sort tag will be normalized: %s\n", *sort_tag); - o_ptr = u8_normalize(UNINORM_NFD, (uint8_t *)*sort_tag, strlen(*sort_tag) + 1, NULL, &len); - free(*sort_tag); - *sort_tag = (char *)o_ptr; - return; - } - - if (!src_tag || ((len = strlen(src_tag)) == 0)) - { - *sort_tag = NULL; - return; - } - - // Set input pointer past article if present - if ((strncasecmp(src_tag, "a ", 2) == 0) && (len > 2)) - i_ptr = (uint8_t *)(src_tag + 2); - else if ((strncasecmp(src_tag, "an ", 3) == 0) && (len > 3)) - i_ptr = (uint8_t *)(src_tag + 3); - else if ((strncasecmp(src_tag, "the ", 4) == 0) && (len > 4)) - i_ptr = (uint8_t *)(src_tag + 4); - else - i_ptr = (uint8_t *)src_tag; - - // Poor man's natural sort. Makes sure we sort like this: a1, a2, a10, a11, a21, a111 - // We do this by padding zeroes to (short) numbers. As an alternative we could have - // made a proper natural sort algorithm in sqlext.c, but we don't, since we don't - // want any risk of hurting response times - memset(&out, 0, sizeof(out)); - o_ptr = (uint8_t *)&out; - number = NULL; - append_number = 0; - - do - { - n_ptr = u8_next(&puc, i_ptr); - - if (uc_is_digit(puc)) - { - if (!number) // We have encountered the beginning of a number - number = i_ptr; - append_number = (n_ptr == NULL); // If last char in string append number now - } - else - { - if (number) - append_number = 1; // A number has ended so time to append it - else - { - charlen = u8_strmblen(i_ptr); - if (charlen >= 0) - o_ptr = u8_stpncpy(o_ptr, i_ptr, charlen); // No numbers in sight, just append char - } - } - - // Break if less than 100 bytes remain (prevent buffer overflow) - if (sizeof(out) - u8_strlen(out) < 100) - break; - - // Break if number is very large (prevent buffer overflow) - if (number && (i_ptr - number > 50)) - break; - - if (append_number) - { - numlen = i_ptr - number; - if (numlen < 5) // Max pad width - { - u8_strcpy(o_ptr, (uint8_t *)"00000"); - o_ptr += (5 - numlen); - } - o_ptr = u8_stpncpy(o_ptr, number, numlen + u8_strmblen(i_ptr)); - - number = NULL; - append_number = 0; - } - - i_ptr = n_ptr; - } - while (n_ptr); - - *sort_tag = (char *)u8_normalize(UNINORM_NFD, (uint8_t *)&out, u8_strlen(out) + 1, NULL, &len); -} - -static void -fixup_tags(struct media_file_info *mfi) -{ - cfg_t *lib; - size_t len; - char *tag; - char *sep = " - "; - char *ca; - - if (mfi->genre && (strlen(mfi->genre) == 0)) - { - free(mfi->genre); - mfi->genre = NULL; - } - - if (mfi->artist && (strlen(mfi->artist) == 0)) - { - free(mfi->artist); - mfi->artist = NULL; - } - - if (mfi->title && (strlen(mfi->title) == 0)) - { - free(mfi->title); - mfi->title = NULL; - } - - /* - * Default to mpeg4 video/audio for unknown file types - * in an attempt to allow streaming of DRM-afflicted files - */ - if (mfi->codectype && strcmp(mfi->codectype, "unkn") == 0) - { - if (mfi->has_video) - { - strcpy(mfi->codectype, "mp4v"); - strcpy(mfi->type, "m4v"); - } - else - { - strcpy(mfi->codectype, "mp4a"); - strcpy(mfi->type, "m4a"); - } - } - - if (!mfi->artist) - { - if (mfi->orchestra && mfi->conductor) - { - len = strlen(mfi->orchestra) + strlen(sep) + strlen(mfi->conductor); - tag = (char *)malloc(len + 1); - if (tag) - { - sprintf(tag,"%s%s%s", mfi->orchestra, sep, mfi->conductor); - mfi->artist = tag; - } - } - else if (mfi->orchestra) - { - mfi->artist = strdup(mfi->orchestra); - } - else if (mfi->conductor) - { - mfi->artist = strdup(mfi->conductor); - } - } - - /* Handle TV shows, try to present prettier metadata */ - if (mfi->tv_series_name && strlen(mfi->tv_series_name) != 0) - { - mfi->media_kind = MEDIA_KIND_TVSHOW; /* tv show */ - - /* Default to artist = series_name */ - if (mfi->artist && strlen(mfi->artist) == 0) - { - free(mfi->artist); - mfi->artist = NULL; - } - - if (!mfi->artist) - mfi->artist = strdup(mfi->tv_series_name); - - /* Default to album = ", Season " */ - if (mfi->album && strlen(mfi->album) == 0) - { - free(mfi->album); - mfi->album = NULL; - } - - if (!mfi->album) - { - len = snprintf(NULL, 0, "%s, Season %u", mfi->tv_series_name, mfi->tv_season_num); - - mfi->album = (char *)malloc(len + 1); - if (mfi->album) - sprintf(mfi->album, "%s, Season %u", mfi->tv_series_name, mfi->tv_season_num); - } - } - - /* Check the 4 top-tags are filled */ - if (!mfi->artist) - mfi->artist = strdup("Unknown artist"); - if (!mfi->album) - mfi->album = strdup("Unknown album"); - if (!mfi->genre) - mfi->genre = strdup("Unknown genre"); - if (!mfi->title) - { - /* fname is left untouched by unicode_fixup_mfi() for - * obvious reasons, so ensure it is proper UTF-8 - */ - mfi->title = unicode_fixup_string(mfi->fname, "ascii"); - if (mfi->title == mfi->fname) - mfi->title = strdup(mfi->fname); - } - - /* Ensure sort tags are filled, manipulated and normalized */ - sort_tag_create(&mfi->artist_sort, mfi->artist); - sort_tag_create(&mfi->album_sort, mfi->album); - sort_tag_create(&mfi->title_sort, mfi->title); - - /* We need to set album_artist according to media type and config */ - if (mfi->compilation) /* Compilation */ - { - lib = cfg_getsec(cfg, "library"); - ca = cfg_getstr(lib, "compilation_artist"); - if (ca && mfi->album_artist) - { - free(mfi->album_artist); - mfi->album_artist = strdup(ca); - } - else if (ca && !mfi->album_artist) - { - mfi->album_artist = strdup(ca); - } - else if (!ca && !mfi->album_artist) - { - mfi->album_artist = strdup(""); - mfi->album_artist_sort = strdup(""); - } - } - else if (mfi->media_kind == MEDIA_KIND_PODCAST) /* Podcast */ - { - if (mfi->album_artist) - free(mfi->album_artist); - mfi->album_artist = strdup(""); - mfi->album_artist_sort = strdup(""); - } - else if (!mfi->album_artist) /* Regular media without album_artist */ - { - mfi->album_artist = strdup(mfi->artist); - } - - if (!mfi->album_artist_sort && (strcmp(mfi->album_artist, mfi->artist) == 0)) - mfi->album_artist_sort = strdup(mfi->artist_sort); - else - sort_tag_create(&mfi->album_artist_sort, mfi->album_artist); - - /* Composer is not one of our mandatory tags, so take extra care */ - if (mfi->composer_sort || mfi->composer) - sort_tag_create(&mfi->composer_sort, mfi->composer); -} - void library_add_media(struct media_file_info *mfi) { @@ -398,8 +134,7 @@ library_add_media(struct media_file_info *mfi) mfi->media_kind = MEDIA_KIND_MUSIC; /* music */ unicode_fixup_mfi(mfi); - - fixup_tags(mfi); + fixup_tags_mfi(mfi); if (mfi->id == 0) db_file_add(mfi); @@ -408,45 +143,33 @@ library_add_media(struct media_file_info *mfi) } int -library_scan_media(const char *path, struct media_file_info *mfi) +library_queue_add(const char *path) { int i; int ret; - DPRINTF(E_DBG, L_LIB, "Scan metadata for path '%s'\n", path); + DPRINTF(E_DBG, L_LIB, "Add items for path '%s' to the queue\n", path); ret = LIBRARY_PATH_INVALID; for (i = 0; sources[i] && ret == LIBRARY_PATH_INVALID; i++) { - if (sources[i]->disabled || !sources[i]->scan_metadata) + if (sources[i]->disabled || !sources[i]->queue_add) { - DPRINTF(E_DBG, L_LIB, "Library source '%s' is disabled or does not support scan_metadata\n", sources[i]->name); + DPRINTF(E_DBG, L_LIB, "Library source '%s' is disabled or does not support queue_add\n", sources[i]->name); continue; } - ret = sources[i]->scan_metadata(path, mfi); + ret = sources[i]->queue_add(path); if (ret == LIBRARY_OK) - DPRINTF(E_DBG, L_LIB, "Got metadata for path '%s' from library source '%s'\n", path, sources[i]->name); + { + DPRINTF(E_DBG, L_LIB, "Items for path '%s' from library source '%s' added to the queue\n", path, sources[i]->name); + break; + } } - if (ret == LIBRARY_OK) - { - 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 */ - - unicode_fixup_mfi(mfi); - - fixup_tags(mfi); - } - else - { - DPRINTF(E_LOG, L_LIB, "Failed to read metadata for path '%s' (ret=%d)\n", path, ret); - } + if (ret != LIBRARY_OK) + DPRINTF(E_LOG, L_LIB, "Failed to add items for path '%s' to the queue (%d)\n", path, ret); return ret; } @@ -519,42 +242,6 @@ library_add_playlist_info(const char *path, const char *title, const char *virtu return plid; } -int -library_add_queue_item(struct media_file_info *mfi) -{ - struct db_queue_item queue_item; - - memset(&queue_item, 0, sizeof(struct db_queue_item)); - - if (mfi->id) - queue_item.file_id = mfi->id; - else - queue_item.file_id = 9999999; - - queue_item.title = mfi->title; - queue_item.artist = mfi->artist; - queue_item.album_artist = mfi->album_artist; - queue_item.album = mfi->album; - queue_item.genre = mfi->genre; - queue_item.artist_sort = mfi->artist_sort; - queue_item.album_artist_sort = mfi->album_artist_sort; - queue_item.album_sort = mfi->album_sort; - queue_item.path = mfi->path; - queue_item.virtual_path = mfi->virtual_path; - queue_item.data_kind = mfi->data_kind; - queue_item.media_kind = mfi->media_kind; - queue_item.song_length = mfi->song_length; - queue_item.seek = mfi->seek; - queue_item.songalbumid = mfi->songalbumid; - queue_item.time_modified = mfi->time_modified; - queue_item.year = mfi->year; - queue_item.track = mfi->track; - queue_item.disc = mfi->disc; - //queue_item.artwork_url - - return db_queue_add_item(&queue_item, 0, 0); -} - static void purge_cruft(time_t start) { diff --git a/src/library.h b/src/library.h index 63f4d986..e02446ea 100644 --- a/src/library.h +++ b/src/library.h @@ -66,11 +66,6 @@ struct library_source */ int (*fullrescan)(void); - /* - * Scans metadata for the media file with the given path into the given mfi - */ - int (*scan_metadata)(const char *path, struct media_file_info *mfi); - /* * Save queue as a new playlist under the given virtual path */ @@ -85,8 +80,12 @@ struct library_source * Save queue as a new playlist under the given virtual path */ int (*queue_save)(const char *virtual_path); -}; + /* + * Add item for the given path to the current queue + */ + int (*queue_add)(const char *path); +}; void library_add_media(struct media_file_info *mfi); @@ -95,10 +94,7 @@ int library_add_playlist_info(const char *path, const char *title, const char *virtual_path, enum pl_type type, int parent_pl_id, int dir_id); int -library_scan_media(const char *path, struct media_file_info *mfi); - -int -library_add_queue_item(struct media_file_info *mfi); +library_queue_add(const char *path); void library_rescan(); diff --git a/src/library/filescanner.c b/src/library/filescanner.c index bafcf70d..7b6d787e 100644 --- a/src/library/filescanner.c +++ b/src/library/filescanner.c @@ -1643,39 +1643,102 @@ filescanner_fullrescan() return 0; } -static int -scan_metadata(const char *path, struct media_file_info *mfi) +static void +map_media_file_to_queue_item(struct db_queue_item *queue_item, struct media_file_info *mfi) { + memset(queue_item, 0, sizeof(struct db_queue_item)); + + if (mfi->id) + queue_item->file_id = mfi->id; + else + queue_item->file_id = 9999999; + + queue_item->title = safe_strdup(mfi->title); + queue_item->artist = safe_strdup(mfi->artist); + queue_item->album_artist = safe_strdup(mfi->album_artist); + queue_item->album = safe_strdup(mfi->album); + queue_item->genre = safe_strdup(mfi->genre); + queue_item->artist_sort = safe_strdup(mfi->artist_sort); + queue_item->album_artist_sort = safe_strdup(mfi->album_artist_sort); + queue_item->album_sort = safe_strdup(mfi->album_sort); + queue_item->path = safe_strdup(mfi->path); + queue_item->virtual_path = safe_strdup(mfi->virtual_path); + queue_item->data_kind = mfi->data_kind; + queue_item->media_kind = mfi->media_kind; + queue_item->song_length = mfi->song_length; + queue_item->seek = mfi->seek; + queue_item->songalbumid = mfi->songalbumid; + queue_item->time_modified = mfi->time_modified; + queue_item->year = mfi->year; + queue_item->track = mfi->track; + queue_item->disc = mfi->disc; + //queue_item->artwork_url +} + +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; - if (strncasecmp(path, "http://", strlen("http://")) == 0) + 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) { - memset(mfi, 0, sizeof(struct media_file_info)); - mfi->path = strdup(path); - mfi->virtual_path = safe_asprintf("/%s", mfi->path); + 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"); + } - pos = strchr(path, '#'); - if (pos) - mfi->fname = strdup(pos+1); - else - mfi->fname = strdup(filename_from_path(mfi->path)); + if (!mfi.title) + mfi.title = strdup(mfi.fname); - mfi->data_kind = DATA_KIND_HTTP; - mfi->directory_id = DIR_HTTP; + 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 */ - 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"); - } + unicode_fixup_mfi(&mfi); - if (!mfi->title) - mfi->title = strdup(mfi->fname); + map_media_file_to_queue_item(&item, &mfi); + ret = db_queue_add_start(&queue_add_info); + if (ret == 0) + { + ret = db_queue_add_item(&queue_add_info, &item); + db_queue_add_end(&queue_add_info, ret); + } + + free_queue_item(&item, 1); + free_mfi(&mfi, 1); + + return 0; +} + +static int +queue_add(const char *uri) +{ + if (strncasecmp(uri, "http://", strlen("http://")) == 0) + { + queue_add_stream(uri); return LIBRARY_OK; } @@ -2052,8 +2115,8 @@ struct library_source filescanner = .initscan = filescanner_initscan, .rescan = filescanner_rescan, .fullrescan = filescanner_fullrescan, - .scan_metadata = scan_metadata, .playlist_add = playlist_add, .playlist_remove = playlist_remove, .queue_save = queue_save, + .queue_add = queue_add, }; diff --git a/src/mpd.c b/src/mpd.c index 77e6384c..84d2adf5 100644 --- a/src/mpd.c +++ b/src/mpd.c @@ -1685,7 +1685,6 @@ mpd_queue_add(char *path, bool exact_match) static int mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx) { - struct media_file_info mfi; int ret; ret = mpd_queue_add(argv[1], false); @@ -1699,15 +1698,12 @@ mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, st if (ret == 0) { // Given path is not in the library, check if it is possible to add as a non-library queue item - ret = library_scan_media(argv[1], &mfi); + ret = library_queue_add(argv[1]); if (ret != LIBRARY_OK) { *errmsg = safe_asprintf("Failed to add song '%s' to playlist (unkown path)", argv[1]); return ACK_ERROR_UNKNOWN; } - - library_add_queue_item(&mfi); - free_mfi(&mfi, 1); } return 0; @@ -1722,7 +1718,6 @@ mpd_command_add(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, st static int mpd_command_addid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, struct mpd_client_ctx *ctx) { - struct media_file_info mfi; int to_pos = -1; int ret; @@ -1741,15 +1736,12 @@ mpd_command_addid(struct evbuffer *evbuf, int argc, char **argv, char **errmsg, if (ret == 0) { // Given path is not in the library, directly add it as a new queue item - ret = library_scan_media(argv[1], &mfi); + ret = library_queue_add(argv[1]); if (ret != LIBRARY_OK) { *errmsg = safe_asprintf("Failed to add song '%s' to playlist (unkown path)", argv[1]); return ACK_ERROR_UNKNOWN; } - - ret = library_add_queue_item(&mfi); - free_mfi(&mfi, 1); } if (ret < 0)