LightSong: add attribute "real_uri"
The UPnP database plugin can now show relative song URIs for remote songs.
This commit is contained in:
parent
5d4b450c52
commit
7471f65d95
|
@ -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) {}
|
||||||
|
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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()));
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue