[db,library] Add "scan_kind" field to playlists, directories and files

(db upgrade to v22.00)

`scan_kind` identifies the library "scanner" component that created the
item and is responsible to keep it up to date (rescan).

The library update now supports passing a `scan_kind` to update only the
items of one particular "scanner". This allows e. g. to only update the
item from the Spotify library or only update the RSS feeds.

The OwnTone database is upgraded to v22.00 and the `scan_kind` columns
in `files`, `playlists`, `directories` are identified by:

 1. Check if item is part of a RSS playlist (podcast RSS feed), they
belong to the "rssscanner"
 2. Check if item has a Spotify `virtual_path`, they belong to the
"spotifyscanner"
 3. Remaining items belong to the "filescanner"
This commit is contained in:
chme
2021-12-28 09:19:44 +01:00
parent 31e90070ff
commit 1d2e4dc7a8
13 changed files with 390 additions and 106 deletions

View File

@@ -438,6 +438,7 @@ playlist_fill(struct playlist_info *pli, const char *path)
pli->path = strdup(path);
pli->title = strip_extension(filename); // Will alloc
pli->virtual_path = strip_extension(virtual_path); // Will alloc
pli->scan_kind = SCAN_KIND_FILES;
pli->directory_id = get_parent_dir_id(path);
@@ -586,6 +587,7 @@ process_regular_file(const char *file, struct stat *sb, int type, int flags, int
mfi.virtual_path = strdup(virtual_path);
mfi.directory_id = dir_id;
mfi.scan_kind = SCAN_KIND_FILES;
if (S_ISFIFO(sb->st_mode))
{
@@ -699,7 +701,7 @@ process_file(char *file, struct stat *sb, enum file_type file_type, int scan_typ
DPRINTF(E_LOG, L_SCAN, "Startup rescan triggered, found init-rescan file: %s\n", file);
library_rescan();
library_rescan(0);
break;
case FILE_CTRL_METASCAN:
@@ -708,7 +710,7 @@ process_file(char *file, struct stat *sb, enum file_type file_type, int scan_typ
DPRINTF(E_LOG, L_SCAN, "Meta rescan triggered, found meta-rescan file: %s\n", file);
library_metarescan();
library_metarescan(0);
break;
case FILE_CTRL_FULLSCAN:
@@ -828,7 +830,7 @@ process_directory(char *path, int parent_id, int flags)
return;
}
dir_id = db_directory_addorupdate(virtual_path, path, 0, parent_id);
dir_id = library_directory_save(virtual_path, path, 0, parent_id, SCAN_KIND_FILES);
if (dir_id <= 0)
{
DPRINTF(E_LOG, L_SCAN, "Insert or update of directory failed '%s'\n", virtual_path);
@@ -956,7 +958,7 @@ process_parent_directories(char *path)
if (ret < 0)
return 0;
dir_id = db_directory_addorupdate(virtual_path, buf, 0, dir_id);
dir_id = library_directory_save(virtual_path, buf, 0, dir_id, SCAN_KIND_FILES);
if (dir_id <= 0)
{
DPRINTF(E_LOG, L_SCAN, "Insert or update of directory failed '%s'\n", virtual_path);
@@ -2154,7 +2156,7 @@ filescanner_deinit(void)
struct library_source filescanner =
{
.name = "filescanner",
.scan_kind = SCAN_KIND_FILES,
.disabled = 0,
.init = filescanner_init,
.deinit = filescanner_deinit,

View File

@@ -159,6 +159,7 @@ scan_metadata_stream(struct media_file_info *mfi, const char *path)
mfi->data_kind = DATA_KIND_HTTP;
mfi->time_modified = time(NULL);
mfi->directory_id = DIR_HTTP;
mfi->scan_kind = SCAN_KIND_FILES;
ret = scan_metadata_ffmpeg(mfi, path);
if (ret < 0)
@@ -186,6 +187,7 @@ process_nested_playlist(int parent_id, const char *path)
goto error;
pli->type = PL_FOLDER;
pli->scan_kind = SCAN_KIND_FILES;
ret = library_playlist_save(pli);
if (ret < 0)
goto error;

View File

@@ -217,6 +217,7 @@ playlist_fetch(bool *is_new, const char *path)
pli->directory_id = DIR_HTTP;
pli->type = PL_RSS;
pli->query_limit = RSS_LIMIT_DEFAULT;
pli->scan_kind = SCAN_KIND_RSS;
ret = library_playlist_save(pli);
if (ret < 0)
@@ -487,6 +488,7 @@ rss_save(struct playlist_info *pli, int *count, enum rss_scan_type scan_type)
}
scan_metadata_stream(&mfi, ri.url);
mfi.scan_kind = SCAN_KIND_RSS;
mfi_metadata_fixup(&mfi, &ri, feed_title, feed_author, time_added);
@@ -641,7 +643,7 @@ rss_add(const char *path)
struct library_source rssscanner =
{
.name = "RSS feeds",
.scan_kind = SCAN_KIND_RSS,
.disabled = 0,
.initscan = rss_rescan,
.rescan = rss_rescan,

View File

@@ -1465,7 +1465,7 @@ prepare_directories(const char *artist, const char *album)
DPRINTF(E_LOG, L_SPOTIFY, "Virtual path exceeds PATH_MAX (/spotify:/%s)\n", artist);
return -1;
}
dir_id = db_directory_addorupdate(virtual_path, NULL, 0, DIR_SPOTIFY);
dir_id = library_directory_save(virtual_path, NULL, 0, DIR_SPOTIFY, SCAN_KIND_SPOTIFY);
if (dir_id <= 0)
{
DPRINTF(E_LOG, L_SPOTIFY, "Could not add or update directory '%s'\n", virtual_path);
@@ -1477,7 +1477,7 @@ prepare_directories(const char *artist, const char *album)
DPRINTF(E_LOG, L_SPOTIFY, "Virtual path exceeds PATH_MAX (/spotify:/%s/%s)\n", artist, album);
return -1;
}
dir_id = db_directory_addorupdate(virtual_path, NULL, 0, dir_id);
dir_id = library_directory_save(virtual_path, NULL, 0, dir_id, SCAN_KIND_SPOTIFY);
if (dir_id <= 0)
{
DPRINTF(E_LOG, L_SPOTIFY, "Could not add or update directory '%s'\n", virtual_path);
@@ -1580,6 +1580,7 @@ map_track_to_mfi(struct media_file_info *mfi, const struct spotify_track *track,
}
snprintf(virtual_path, PATH_MAX, "/spotify:/%s/%s/%s", mfi->album_artist, mfi->album, mfi->title);
mfi->virtual_path = strdup(virtual_path);
mfi->scan_kind = SCAN_KIND_SPOTIFY;
}
static int
@@ -1873,8 +1874,9 @@ map_playlist_to_pli(struct playlist_info *pli, struct spotify_playlist *playlist
pli->path = strdup(playlist->uri);
pli->title = safe_strdup(playlist->name);
pli->parent_id = spotify_base_plid;
pli->directory_id = DIR_SPOTIFY;
pli->parent_id = spotify_base_plid;
pli->directory_id = DIR_SPOTIFY;
pli->scan_kind = SCAN_KIND_SPOTIFY;
if (playlist->owner)
pli->virtual_path = safe_asprintf("/spotify:/%s (%s)", playlist->name, playlist->owner);
@@ -1945,6 +1947,7 @@ create_saved_tracks_playlist(void)
.type = PL_PLAIN,
.parent_id = spotify_base_plid,
.directory_id = DIR_SPOTIFY,
.scan_kind = SCAN_KIND_SPOTIFY,
};
spotify_saved_plid = playlist_add_or_update(&pli);
@@ -1969,6 +1972,7 @@ create_base_playlist(void)
.path = strdup("spotify:playlistfolder"),
.title = strdup("Spotify"),
.type = PL_FOLDER,
.scan_kind = SCAN_KIND_SPOTIFY,
};
spotify_base_plid = 0;
@@ -2330,7 +2334,7 @@ spotifywebapi_deinit()
struct library_source spotifyscanner =
{
.name = "spotifyscanner",
.scan_kind = SCAN_KIND_SPOTIFY,
.disabled = 0,
.init = spotifywebapi_init,
.deinit = spotifywebapi_deinit,