DetachedSong: add attribute "real_uri"

Prepare for UPnP songs that retain there database identity.
This commit is contained in:
Max Kellermann 2014-01-18 18:20:54 +01:00
parent 483b1f51c9
commit 5d4b450c52
7 changed files with 62 additions and 11 deletions

View File

@ -402,7 +402,7 @@ decoder_run(DecoderControl &dc)
const std::string uri = song.IsFile()
? map_song_fs(song).c_str()
: song.GetURI();
: song.GetRealURI();
if (uri.empty()) {
dc.state = DecoderState::ERROR;

View File

@ -32,13 +32,23 @@ DetachedSong::DetachedSong(const LightSong &other)
bool
DetachedSong::IsRemote() const
{
return uri_has_scheme(uri.c_str());
return uri_has_scheme(GetRealURI());
}
bool
DetachedSong::IsAbsoluteFile() const
{
return PathTraitsUTF8::IsAbsolute(uri.c_str());
return PathTraitsUTF8::IsAbsolute(GetRealURI());
}
bool
DetachedSong::IsInDatabase() const
{
/* here, we use GetURI() and not GetRealURI() because
GetRealURI() is never relative */
const char *_uri = GetURI();
return !uri_has_scheme(_uri) && !PathTraitsUTF8::IsAbsolute(_uri);
}
double

View File

@ -47,6 +47,16 @@ class DetachedSong {
*/
std::string uri;
/**
* The "real" URI, the one to be used for opening the
* resource. If this attribute is empty, then #uri shall be
* used.
*
* This attribute is used for songs from the database which
* have a relative URI.
*/
std::string real_uri;
Tag tag;
time_t mtime;
@ -97,6 +107,29 @@ public:
uri = std::forward<T>(_uri);
}
/**
* Does this object have a "real" URI different from the
* displayed URI?
*/
gcc_pure
bool HasRealURI() const {
return !real_uri.empty();
}
/**
* Returns "real" URI (#real_uri) and falls back to just
* GetURI().
*/
gcc_pure
const char *GetRealURI() const {
return (HasRealURI() ? real_uri : uri).c_str();
}
template<typename T>
void SetRealURI(T &&_uri) {
real_uri = std::forward<T>(_uri);
}
/**
* Returns true if both objects refer to the same physical
* song.
@ -123,9 +156,7 @@ public:
bool IsAbsoluteFile() const;
gcc_pure
bool IsInDatabase() const {
return IsFile() && !IsAbsoluteFile();
}
bool IsInDatabase() const;
const Tag &GetTag() const {
return tag;

View File

@ -26,6 +26,7 @@
#include "Directory.hxx"
#include "Song.hxx"
#include "DetachedSong.hxx"
#include "LightSong.hxx"
#include "fs/AllocatedPath.hxx"
#include "fs/Traits.hxx"
#include "fs/Charset.hxx"
@ -220,7 +221,15 @@ map_detached_song_fs(const char *uri_utf8)
DetachedSong
map_song_detach(const LightSong &song)
{
return DetachedSong(song);
DetachedSong detached(song);
if (detached.IsInDatabase()) {
const auto uri = song.GetURI();
detached.SetRealURI(PathTraitsUTF8::Build(music_dir_utf8.c_str(),
uri.c_str()));
}
return detached;
}
AllocatedPath
@ -235,7 +244,7 @@ AllocatedPath
map_song_fs(const DetachedSong &song)
{
if (song.IsAbsoluteFile())
return AllocatedPath::FromUTF8(song.GetURI());
return AllocatedPath::FromUTF8(song.GetRealURI());
else
return map_uri_fs(song.GetURI());
}

View File

@ -38,7 +38,8 @@
void
playlist_print_song(FILE *file, const DetachedSong &song)
{
if (playlist_saveAbsolutePaths && song.IsInDatabase()) {
if (playlist_saveAbsolutePaths &&
song.IsInDatabase() && song.IsFile()) {
const auto path = map_song_fs(song);
if (!path.IsNull())
fprintf(file, "%s\n", path.c_str());

View File

@ -30,7 +30,7 @@
static bool
UpdatePlaylistSong(const Database &db, DetachedSong &song)
{
if (!song.IsInDatabase())
if (!song.IsInDatabase() || !song.IsFile())
/* only update Songs instances that are "detached"
from the Database */
return false;

View File

@ -130,7 +130,7 @@ DetachedSong::Update()
{
if (IsAbsoluteFile()) {
const AllocatedPath path_fs =
AllocatedPath::FromUTF8(uri.c_str());
AllocatedPath::FromUTF8(GetRealURI());
struct stat st;
if (!StatFile(path_fs, st) || !S_ISREG(st.st_mode))