Commit 5d4b450c authored by Max Kellermann's avatar Max Kellermann

DetachedSong: add attribute "real_uri"

Prepare for UPnP songs that retain there database identity.
parent 483b1f51
......@@ -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;
......
......@@ -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
......
......@@ -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;
......@@ -98,6 +108,29 @@ public:
}
/**
* 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;
......
......@@ -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());
}
......
......@@ -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());
......
......@@ -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;
......
......@@ -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))
......
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