Commit 29b18d9a authored by Max Kellermann's avatar Max Kellermann

SongUpdate: use the Storage interface, support remote files

This commit finally allows the database update to scan remote files, e.g. using the smbclient storage plugin. However, it is not yet possible to configure that, therefore the feature is not accessible yet.
parent ad309cde
......@@ -21,7 +21,10 @@
#include "DetachedSong.hxx"
#include "db/Song.hxx"
#include "db/Directory.hxx"
#include "storage/StorageInterface.hxx"
#include "storage/FileInfo.hxx"
#include "util/UriUtil.hxx"
#include "util/Error.hxx"
#include "Mapper.hxx"
#include "fs/AllocatedPath.hxx"
#include "fs/Traits.hxx"
......@@ -42,7 +45,7 @@
#ifdef ENABLE_DATABASE
Song *
Song::LoadFile(const char *path_utf8, Directory &parent)
Song::LoadFile(Storage &storage, const char *path_utf8, Directory &parent)
{
assert(!uri_has_scheme(path_utf8));
assert(strchr(path_utf8, '\n') == nullptr);
......@@ -52,7 +55,7 @@ Song::LoadFile(const char *path_utf8, Directory &parent)
//in archive ?
bool success = parent.device == DEVICE_INARCHIVE
? song->UpdateFileInArchive()
: song->UpdateFile();
: song->UpdateFile(storage);
if (!success) {
song->Free();
return nullptr;
......@@ -77,27 +80,36 @@ tag_scan_fallback(Path path,
#ifdef ENABLE_DATABASE
bool
Song::UpdateFile()
Song::UpdateFile(Storage &storage)
{
const auto path_fs = map_song_fs(*this);
if (path_fs.IsNull())
const auto &relative_uri = GetURI();
FileInfo info;
if (!storage.GetInfo(relative_uri.c_str(), true, info, IgnoreError()))
return false;
struct stat st;
if (!StatFile(path_fs, st) || !S_ISREG(st.st_mode))
if (!info.IsRegular())
return false;
TagBuilder tag_builder;
if (!tag_file_scan(path_fs,
full_tag_handler, &tag_builder))
return false;
if (tag_builder.IsEmpty())
tag_scan_fallback(path_fs, &full_tag_handler,
&tag_builder);
const auto path_fs = storage.MapFS(relative_uri.c_str());
if (path_fs.IsNull()) {
const auto absolute_uri =
storage.MapUTF8(relative_uri.c_str());
if (!tag_stream_scan(absolute_uri.c_str(),
full_tag_handler, &tag_builder))
return false;
} else {
if (!tag_file_scan(path_fs, full_tag_handler, &tag_builder))
return false;
mtime = st.st_mtime;
if (tag_builder.IsEmpty())
tag_scan_fallback(path_fs, &full_tag_handler,
&tag_builder);
}
mtime = info.mtime;
tag_builder.Commit(tag);
return true;
}
......
......@@ -32,6 +32,7 @@
struct LightSong;
struct Directory;
class DetachedSong;
class Storage;
/**
* A song file inside the configured music directory.
......@@ -91,11 +92,12 @@ struct Song {
* data, nullptr is returned.
*/
gcc_malloc
static Song *LoadFile(const char *path_utf8, Directory &parent);
static Song *LoadFile(Storage &storage, const char *name_utf8,
Directory &parent);
void Free();
bool UpdateFile();
bool UpdateFile(Storage &storage);
bool UpdateFileInArchive();
/**
......
......@@ -65,7 +65,7 @@ UpdateWalk::UpdateArchiveTree(Directory &directory, const char *name)
Song *song = directory.FindSong(name);
db_unlock();
if (song == nullptr) {
song = Song::LoadFile(name, directory);
song = Song::LoadFile(storage, name, directory);
if (song != nullptr) {
db_lock();
directory.AddSong(song);
......
......@@ -61,7 +61,7 @@ UpdateWalk::UpdateSongFile2(Directory &directory,
if (song == nullptr) {
FormatDebug(update_domain, "reading %s/%s",
directory.GetPath(), name);
song = Song::LoadFile(name, directory);
song = Song::LoadFile(storage, name, directory);
if (song == nullptr) {
FormatDebug(update_domain,
"ignoring unrecognized file %s/%s",
......@@ -79,7 +79,7 @@ UpdateWalk::UpdateSongFile2(Directory &directory,
} else if (info.mtime != song->mtime || walk_discard) {
FormatDefault(update_domain, "updating %s/%s",
directory.GetPath(), name);
if (!song->UpdateFile()) {
if (!song->UpdateFile(storage)) {
FormatDebug(update_domain,
"deleting unrecognized file %s/%s",
directory.GetPath(), name);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment