LightSong: add attribute "real_uri"

The UPnP database plugin can now show relative song URIs for remote
songs.
This commit is contained in:
Max Kellermann 2014-01-20 09:18:33 +01:00
parent 5d4b450c52
commit 7471f65d95
4 changed files with 30 additions and 25 deletions

View File

@ -25,6 +25,7 @@
DetachedSong::DetachedSong(const LightSong &other) DetachedSong::DetachedSong(const LightSong &other)
:uri(other.GetURI().c_str()), :uri(other.GetURI().c_str()),
real_uri(other.real_uri),
tag(*other.tag), tag(*other.tag),
mtime(other.mtime), mtime(other.mtime),
start_ms(other.start_ms), end_ms(other.end_ms) {} start_ms(other.start_ms), end_ms(other.end_ms) {}

View File

@ -46,6 +46,16 @@ struct LightSong {
const char *uri; const char *uri;
/**
* The "real" URI, the one to be used for opening the
* resource. If this attribute is empty, then #uri (and
* #directory) shall be used.
*
* This attribute is used for songs from the database which
* have a relative URI.
*/
std::string real_uri;
/** /**
* Must not be nullptr. * Must not be nullptr.
*/ */

View File

@ -223,7 +223,7 @@ map_song_detach(const LightSong &song)
{ {
DetachedSong detached(song); DetachedSong detached(song);
if (detached.IsInDatabase()) { if (detached.IsInDatabase() && !detached.HasRealURI()) {
const auto uri = song.GetURI(); const auto uri = song.GetURI();
detached.SetRealURI(PathTraitsUTF8::Build(music_dir_utf8.c_str(), detached.SetRealURI(PathTraitsUTF8::Build(music_dir_utf8.c_str(),
uri.c_str())); uri.c_str()));

View File

@ -50,27 +50,18 @@
static const char *const rootid = "0"; static const char *const rootid = "0";
class UpnpSong : public LightSong { class UpnpSong : public LightSong {
std::string uri2; std::string uri2, real_uri2;
Tag tag2; Tag tag2;
public: public:
explicit UpnpSong(UPnPDirObject &&object) UpnpSong(UPnPDirObject &&object, std::string &&_uri)
:uri2(std::move(object.url)), tag2(std::move(object.tag)) { :uri2(std::move(_uri)),
directory = nullptr; real_uri2(std::move(object.url)),
uri = uri2.c_str();
tag = &tag2;
mtime = 0;
start_ms = end_ms = 0;
}
UpnpSong(UPnPDirObject &&object, const char *_uri)
:uri2(_uri == nullptr
? std::move(object.url)
: std::string(_uri)),
tag2(std::move(object.tag)) { tag2(std::move(object.tag)) {
directory = nullptr; directory = nullptr;
uri = uri2.c_str(); uri = uri2.c_str();
real_uri = real_uri2.c_str();
tag = &tag2; tag = &tag2;
mtime = 0; mtime = 0;
start_ms = end_ms = 0; start_ms = end_ms = 0;
@ -247,7 +238,7 @@ UpnpDatabase::GetSong(const char *uri, Error &error) const
return nullptr; return nullptr;
} }
song = new UpnpSong(std::move(dirent)); song = new UpnpSong(std::move(dirent), uri);
} }
if (song == nullptr) if (song == nullptr)
error.Format(db_domain, DB_NOT_FOUND, "No such song: %s", uri); error.Format(db_domain, DB_NOT_FOUND, "No such song: %s", uri);
@ -366,14 +357,14 @@ UpnpDatabase::SearchSongs(ContentDirectoryService &server,
} }
static bool static bool
visitSong(UPnPDirObject &&meta, const char *path, visitSong(UPnPDirObject &&meta, std::string &&path,
const DatabaseSelection &selection, const DatabaseSelection &selection,
VisitSong visit_song, Error& error) VisitSong visit_song, Error& error)
{ {
if (!visit_song) if (!visit_song)
return true; return true;
const UpnpSong song(std::move(meta), path); const UpnpSong song(std::move(meta), std::move(path));
return !selection.Match(song) || visit_song(song, error); return !selection.Match(song) || visit_song(song, error);
} }
@ -382,7 +373,7 @@ visitSong(UPnPDirObject &&meta, const char *path,
* of "rootid" is arbitrary, any name that is not likely to be a top * of "rootid" is arbitrary, any name that is not likely to be a top
* directory name would fit. * directory name would fit.
*/ */
static const std::string static std::string
songPath(const std::string &servername, songPath(const std::string &servername,
const std::string &objid) const std::string &objid)
{ {
@ -423,10 +414,9 @@ UpnpDatabase::SearchSongs(ContentDirectoryService &server,
// course, 'All Music' is very big. // course, 'All Music' is very big.
// So we return synthetic and ugly paths based on the object id, // So we return synthetic and ugly paths based on the object id,
// which we later have to detect. // which we later have to detect.
std::string path = songPath(server.getFriendlyName(), if (!visitSong(std::move(dirent),
dirent.m_id); songPath(server.getFriendlyName(),
//BuildPath(server, dirent, path); dirent.m_id),
if (!visitSong(std::move(dirent), path.c_str(),
selection, visit_song, selection, visit_song,
error)) error))
return false; return false;
@ -566,7 +556,10 @@ UpnpDatabase::VisitServer(ContentDirectoryService &server,
error)) error))
return false; return false;
if (!visitSong(std::move(dirent), nullptr, selection, std::string path = songPath(server.getFriendlyName(),
dirent.m_id);
if (!visitSong(std::move(dirent), path.c_str(),
selection,
visit_song, error)) visit_song, error))
return false; return false;
} }
@ -597,7 +590,8 @@ UpnpDatabase::VisitServer(ContentDirectoryService &server,
switch (tdirent.item_class) { switch (tdirent.item_class) {
case UPnPDirObject::ItemClass::MUSIC: case UPnPDirObject::ItemClass::MUSIC:
if (visit_song) if (visit_song)
return visitSong(std::move(tdirent), nullptr, return visitSong(std::move(tdirent),
std::string(selection.uri),
selection, visit_song, selection, visit_song,
error); error);
break; break;