DetachedSong: add method Update()

Don't create an intermediate Song instance when all we want is a
DetachedSong.
This commit is contained in:
Max Kellermann 2014-01-15 12:05:44 +01:00
parent df80deb070
commit 9fb82f9687
5 changed files with 55 additions and 15 deletions

View File

@ -179,6 +179,13 @@ public:
gcc_pure
double GetDuration() const;
/**
* Update the #tag and #mtime.
*
* @return true on success
*/
bool Update();
};
#endif

View File

@ -61,13 +61,11 @@ PlaylistResult
playlist::AppendFile(PlayerControl &pc,
const char *path_utf8, unsigned *added_id)
{
Song *song = Song::LoadFile(path_utf8, nullptr);
if (song == nullptr)
DetachedSong song(path_utf8);
if (!song.Update())
return PlaylistResult::NO_SUCH_SONG;
const auto result = AppendSong(pc, DetachedSong(*song), added_id);
song->Free();
return result;
return AppendSong(pc, std::move(song), added_id);
}
PlaylistResult

View File

@ -100,12 +100,11 @@ playlist_check_load_song(const DetachedSong *song, const char *uri, bool secure)
if (uri_has_scheme(uri)) {
dest = new DetachedSong(uri);
} else if (PathTraitsUTF8::IsAbsolute(uri) && secure) {
Song *tmp = Song::LoadFile(uri, nullptr);
if (tmp == nullptr)
dest = new DetachedSong(uri);
if (!dest->Update()) {
delete dest;
return nullptr;
dest = new DetachedSong(*tmp);
delete tmp;
}
} else {
const Database *db = GetDatabase();
if (db == nullptr)

View File

@ -19,6 +19,7 @@
#include "config.h" /* must be first for large file support */
#include "Song.hxx"
#include "DetachedSong.hxx"
#include "util/UriUtil.hxx"
#include "Directory.hxx"
#include "Mapper.hxx"
@ -126,3 +127,39 @@ Song::UpdateFileInArchive()
tag = tag_builder.CommitNew();
return true;
}
bool
DetachedSong::Update()
{
if (IsAbsoluteFile()) {
const AllocatedPath path_fs =
AllocatedPath::FromUTF8(uri.c_str());
struct stat st;
if (!StatFile(path_fs, st) || !S_ISREG(st.st_mode))
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);
mtime = st.st_mtime;
tag_builder.Commit(tag);
return true;
} else if (IsRemote()) {
TagBuilder tag_builder;
if (!tag_stream_scan(uri.c_str(), full_tag_handler,
&tag_builder))
return false;
mtime = 0;
tag_builder.Commit(tag);
return true;
} else
// TODO: implement
return false;
}

View File

@ -23,7 +23,7 @@
#include "CommandError.hxx"
#include "UpdateGlue.hxx"
#include "Directory.hxx"
#include "Song.hxx"
#include "DetachedSong.hxx"
#include "SongPrint.hxx"
#include "TagPrint.hxx"
#include "TagStream.hxx"
@ -140,15 +140,14 @@ handle_lsinfo(Client &client, int argc, char *argv[])
if (!client_allow_file(client, path_fs, error))
return print_error(client, error);
Song *song = Song::LoadFile(path_utf8, nullptr);
if (song == nullptr) {
DetachedSong song(path_utf8);
if (!song.Update()) {
command_error(client, ACK_ERROR_NO_EXIST,
"No such file");
return CommandResult::ERROR;
}
song_print_info(client, *song);
song->Free();
song_print_info(client, song);
return CommandResult::OK;
}