db/Visitor: remove the Error parameter
Implementations shall use exceptions instead.
This commit is contained in:
parent
78bf4ef5fa
commit
3ff728ab02
|
@ -173,11 +173,11 @@ db_selection_print(Response &r, Partition &partition,
|
||||||
|
|
||||||
if (window_start > 0 ||
|
if (window_start > 0 ||
|
||||||
window_end < (unsigned)std::numeric_limits<int>::max())
|
window_end < (unsigned)std::numeric_limits<int>::max())
|
||||||
s = [s, window_start, window_end, &i](const LightSong &song,
|
s = [s, window_start, window_end, &i](const LightSong &song){
|
||||||
Error &error2){
|
|
||||||
const bool in_window = i >= window_start && i < window_end;
|
const bool in_window = i >= window_start && i < window_end;
|
||||||
++i;
|
++i;
|
||||||
return !in_window || s(song, error2);
|
if (in_window)
|
||||||
|
s(song);
|
||||||
};
|
};
|
||||||
|
|
||||||
return db.Visit(selection, d, s, p, error);
|
return db.Visit(selection, d, s, p, error);
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
CollectTags(TagSet &set, TagType tag_type, tag_mask_t group_mask,
|
CollectTags(TagSet &set, TagType tag_type, tag_mask_t group_mask,
|
||||||
const LightSong &song)
|
const LightSong &song)
|
||||||
{
|
{
|
||||||
|
@ -34,7 +34,6 @@ CollectTags(TagSet &set, TagType tag_type, tag_mask_t group_mask,
|
||||||
const Tag &tag = *song.tag;
|
const Tag &tag = *song.tag;
|
||||||
|
|
||||||
set.InsertUnique(tag, tag_type, group_mask);
|
set.InsertUnique(tag, tag_type, group_mask);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -52,8 +51,7 @@ VisitUniqueTags(const Database &db, const DatabaseSelection &selection,
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (const auto &value : set)
|
for (const auto &value : set)
|
||||||
if (!visit_tag(value, error))
|
visit_tag(value);
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,13 +26,12 @@ struct LightDirectory;
|
||||||
struct LightSong;
|
struct LightSong;
|
||||||
struct PlaylistInfo;
|
struct PlaylistInfo;
|
||||||
struct Tag;
|
struct Tag;
|
||||||
class Error;
|
|
||||||
|
|
||||||
typedef std::function<bool(const LightDirectory &, Error &)> VisitDirectory;
|
typedef std::function<void(const LightDirectory &)> VisitDirectory;
|
||||||
typedef std::function<bool(const LightSong &, Error &)> VisitSong;
|
typedef std::function<void(const LightSong &)> VisitSong;
|
||||||
typedef std::function<bool(const PlaylistInfo &, const LightDirectory &,
|
typedef std::function<void(const PlaylistInfo &,
|
||||||
Error &)> VisitPlaylist;
|
const LightDirectory &)> VisitPlaylist;
|
||||||
|
|
||||||
typedef std::function<bool(const Tag &, Error &)> VisitTag;
|
typedef std::function<void(const Tag &)> VisitTag;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -563,9 +563,8 @@ Visit(struct mpd_connection *connection,
|
||||||
time_t mtime = 0;
|
time_t mtime = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (visit_directory &&
|
if (visit_directory)
|
||||||
!visit_directory(LightDirectory(path, mtime), error))
|
visit_directory(LightDirectory(path, mtime));
|
||||||
return false;
|
|
||||||
|
|
||||||
if (recursive &&
|
if (recursive &&
|
||||||
!Visit(connection, path, recursive, filter,
|
!Visit(connection, path, recursive, filter,
|
||||||
|
@ -582,29 +581,30 @@ Match(const SongFilter *filter, const LightSong &song)
|
||||||
return filter == nullptr || filter->Match(song);
|
return filter == nullptr || filter->Match(song);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
Visit(const SongFilter *filter,
|
Visit(const SongFilter *filter,
|
||||||
const mpd_song *_song,
|
const mpd_song *_song,
|
||||||
VisitSong visit_song, Error &error)
|
VisitSong visit_song)
|
||||||
{
|
{
|
||||||
if (!visit_song)
|
if (!visit_song)
|
||||||
return true;
|
return;
|
||||||
|
|
||||||
const ProxySong song(_song);
|
const ProxySong song(_song);
|
||||||
return !Match(filter, song) || visit_song(song, error);
|
if (Match(filter, song))
|
||||||
|
visit_song(song);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
Visit(const struct mpd_playlist *playlist,
|
Visit(const struct mpd_playlist *playlist,
|
||||||
VisitPlaylist visit_playlist, Error &error)
|
VisitPlaylist visit_playlist)
|
||||||
{
|
{
|
||||||
if (!visit_playlist)
|
if (!visit_playlist)
|
||||||
return true;
|
return;
|
||||||
|
|
||||||
PlaylistInfo p(mpd_playlist_get_path(playlist),
|
PlaylistInfo p(mpd_playlist_get_path(playlist),
|
||||||
mpd_playlist_get_last_modified(playlist));
|
mpd_playlist_get_last_modified(playlist));
|
||||||
|
|
||||||
return visit_playlist(p, LightDirectory::Root(), error);
|
visit_playlist(p, LightDirectory::Root());
|
||||||
}
|
}
|
||||||
|
|
||||||
class ProxyEntity {
|
class ProxyEntity {
|
||||||
|
@ -671,16 +671,12 @@ Visit(struct mpd_connection *connection, const char *uri,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MPD_ENTITY_TYPE_SONG:
|
case MPD_ENTITY_TYPE_SONG:
|
||||||
if (!Visit(filter,
|
Visit(filter, mpd_entity_get_song(entity), visit_song);
|
||||||
mpd_entity_get_song(entity), visit_song,
|
|
||||||
error))
|
|
||||||
return false;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MPD_ENTITY_TYPE_PLAYLIST:
|
case MPD_ENTITY_TYPE_PLAYLIST:
|
||||||
if (!Visit(mpd_entity_get_playlist(entity),
|
Visit(mpd_entity_get_playlist(entity),
|
||||||
visit_playlist, error))
|
visit_playlist);
|
||||||
return false;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -688,11 +684,10 @@ Visit(struct mpd_connection *connection, const char *uri,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
SearchSongs(struct mpd_connection *connection,
|
SearchSongs(struct mpd_connection *connection,
|
||||||
const DatabaseSelection &selection,
|
const DatabaseSelection &selection,
|
||||||
VisitSong visit_song,
|
VisitSong visit_song)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
assert(selection.recursive);
|
assert(selection.recursive);
|
||||||
assert(visit_song);
|
assert(visit_song);
|
||||||
|
@ -705,19 +700,21 @@ SearchSongs(struct mpd_connection *connection,
|
||||||
!mpd_search_commit(connection))
|
!mpd_search_commit(connection))
|
||||||
ThrowError(connection);
|
ThrowError(connection);
|
||||||
|
|
||||||
bool result = true;
|
while (auto *song = mpd_recv_song(connection)) {
|
||||||
struct mpd_song *song;
|
|
||||||
while (result && (song = mpd_recv_song(connection)) != nullptr) {
|
|
||||||
AllocatedProxySong song2(song);
|
AllocatedProxySong song2(song);
|
||||||
|
|
||||||
result = !Match(selection.filter, song2) ||
|
if (Match(selection.filter, song2)) {
|
||||||
visit_song(song2, error);
|
try {
|
||||||
|
visit_song(song2);
|
||||||
|
} catch (...) {
|
||||||
|
mpd_response_finish(connection);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mpd_response_finish(connection) && result)
|
if (!mpd_response_finish(connection))
|
||||||
ThrowError(connection);
|
ThrowError(connection);
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -750,10 +747,12 @@ ProxyDatabase::Visit(const DatabaseSelection &selection,
|
||||||
if (!visit_directory && !visit_playlist && selection.recursive &&
|
if (!visit_directory && !visit_playlist && selection.recursive &&
|
||||||
(ServerSupportsSearchBase(connection)
|
(ServerSupportsSearchBase(connection)
|
||||||
? !selection.IsEmpty()
|
? !selection.IsEmpty()
|
||||||
: selection.HasOtherThanBase()))
|
: selection.HasOtherThanBase())) {
|
||||||
/* this optimized code path can only be used under
|
/* this optimized code path can only be used under
|
||||||
certain conditions */
|
certain conditions */
|
||||||
return ::SearchSongs(connection, selection, visit_song, error);
|
::SearchSongs(connection, selection, visit_song);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* fall back to recursive walk (slow!) */
|
/* fall back to recursive walk (slow!) */
|
||||||
return ::Visit(connection, selection.uri.c_str(),
|
return ::Visit(connection, selection.uri.c_str(),
|
||||||
|
@ -787,11 +786,7 @@ ProxyDatabase::VisitUniqueTags(const DatabaseSelection &selection,
|
||||||
if (!mpd_search_commit(connection))
|
if (!mpd_search_commit(connection))
|
||||||
ThrowError(connection);
|
ThrowError(connection);
|
||||||
|
|
||||||
bool result = true;
|
while (auto *pair = mpd_recv_pair_tag(connection, tag_type2)) {
|
||||||
|
|
||||||
struct mpd_pair *pair;
|
|
||||||
while (result &&
|
|
||||||
(pair = mpd_recv_pair_tag(connection, tag_type2)) != nullptr) {
|
|
||||||
AtScopeExit(this, pair) {
|
AtScopeExit(this, pair) {
|
||||||
mpd_return_pair(connection, pair);
|
mpd_return_pair(connection, pair);
|
||||||
};
|
};
|
||||||
|
@ -807,13 +802,18 @@ ProxyDatabase::VisitUniqueTags(const DatabaseSelection &selection,
|
||||||
given tag type to be present */
|
given tag type to be present */
|
||||||
tag.AddEmptyItem(tag_type);
|
tag.AddEmptyItem(tag_type);
|
||||||
|
|
||||||
result = visit_tag(tag.Commit(), error);
|
try {
|
||||||
|
visit_tag(tag.Commit());
|
||||||
|
} catch (...) {
|
||||||
|
mpd_response_finish(connection);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mpd_response_finish(connection) && result)
|
if (!mpd_response_finish(connection))
|
||||||
ThrowError(connection);
|
ThrowError(connection);
|
||||||
|
|
||||||
return result;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -243,22 +243,19 @@ Directory::Walk(bool recursive, const SongFilter *filter,
|
||||||
if (visit_song) {
|
if (visit_song) {
|
||||||
for (auto &song : songs){
|
for (auto &song : songs){
|
||||||
const LightSong song2 = song.Export();
|
const LightSong song2 = song.Export();
|
||||||
if ((filter == nullptr || filter->Match(song2)) &&
|
if (filter == nullptr || filter->Match(song2))
|
||||||
!visit_song(song2, error))
|
visit_song(song2);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (visit_playlist) {
|
if (visit_playlist) {
|
||||||
for (const PlaylistInfo &p : playlists)
|
for (const PlaylistInfo &p : playlists)
|
||||||
if (!visit_playlist(p, Export(), error))
|
visit_playlist(p, Export());
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &child : children) {
|
for (auto &child : children) {
|
||||||
if (visit_directory &&
|
if (visit_directory)
|
||||||
!visit_directory(child.Export(), error))
|
visit_directory(child.Export());
|
||||||
return false;
|
|
||||||
|
|
||||||
if (recursive &&
|
if (recursive &&
|
||||||
!child.Walk(recursive, filter,
|
!child.Walk(recursive, filter,
|
||||||
|
|
|
@ -40,29 +40,27 @@ struct PrefixedLightDirectory : LightDirectory {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
PrefixVisitDirectory(const char *base, const VisitDirectory &visit_directory,
|
PrefixVisitDirectory(const char *base, const VisitDirectory &visit_directory,
|
||||||
const LightDirectory &directory, Error &error)
|
const LightDirectory &directory)
|
||||||
{
|
{
|
||||||
return visit_directory(PrefixedLightDirectory(directory, base), error);
|
visit_directory(PrefixedLightDirectory(directory, base));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
PrefixVisitSong(const char *base, const VisitSong &visit_song,
|
PrefixVisitSong(const char *base, const VisitSong &visit_song,
|
||||||
const LightSong &song, Error &error)
|
const LightSong &song)
|
||||||
{
|
{
|
||||||
return visit_song(PrefixedLightSong(song, base), error);
|
visit_song(PrefixedLightSong(song, base));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
PrefixVisitPlaylist(const char *base, const VisitPlaylist &visit_playlist,
|
PrefixVisitPlaylist(const char *base, const VisitPlaylist &visit_playlist,
|
||||||
const PlaylistInfo &playlist,
|
const PlaylistInfo &playlist,
|
||||||
const LightDirectory &directory,
|
const LightDirectory &directory)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
return visit_playlist(playlist,
|
visit_playlist(playlist,
|
||||||
PrefixedLightDirectory(directory, base),
|
PrefixedLightDirectory(directory, base));
|
||||||
error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -77,17 +75,17 @@ WalkMount(const char *base, const Database &db,
|
||||||
VisitDirectory vd;
|
VisitDirectory vd;
|
||||||
if (visit_directory)
|
if (visit_directory)
|
||||||
vd = std::bind(PrefixVisitDirectory,
|
vd = std::bind(PrefixVisitDirectory,
|
||||||
base, std::ref(visit_directory), _1, _2);
|
base, std::ref(visit_directory), _1);
|
||||||
|
|
||||||
VisitSong vs;
|
VisitSong vs;
|
||||||
if (visit_song)
|
if (visit_song)
|
||||||
vs = std::bind(PrefixVisitSong,
|
vs = std::bind(PrefixVisitSong,
|
||||||
base, std::ref(visit_song), _1, _2);
|
base, std::ref(visit_song), _1);
|
||||||
|
|
||||||
VisitPlaylist vp;
|
VisitPlaylist vp;
|
||||||
if (visit_playlist)
|
if (visit_playlist)
|
||||||
vp = std::bind(PrefixVisitPlaylist,
|
vp = std::bind(PrefixVisitPlaylist,
|
||||||
base, std::ref(visit_playlist), _1, _2, _3);
|
base, std::ref(visit_playlist), _1, _2);
|
||||||
|
|
||||||
return db.Visit(DatabaseSelection("", recursive, filter),
|
return db.Visit(DatabaseSelection("", recursive, filter),
|
||||||
vd, vs, vp, error);
|
vd, vs, vp, error);
|
||||||
|
|
|
@ -274,9 +274,8 @@ SimpleDatabase::Visit(const DatabaseSelection &selection,
|
||||||
if (r.uri == nullptr) {
|
if (r.uri == nullptr) {
|
||||||
/* it's a directory */
|
/* it's a directory */
|
||||||
|
|
||||||
if (selection.recursive && visit_directory &&
|
if (selection.recursive && visit_directory)
|
||||||
!visit_directory(r.directory->Export(), error))
|
visit_directory(r.directory->Export());
|
||||||
return false;
|
|
||||||
|
|
||||||
return r.directory->Walk(selection.recursive, selection.filter,
|
return r.directory->Walk(selection.recursive, selection.filter,
|
||||||
visit_directory, visit_song,
|
visit_directory, visit_song,
|
||||||
|
@ -289,8 +288,8 @@ SimpleDatabase::Visit(const DatabaseSelection &selection,
|
||||||
Song *song = r.directory->FindSong(r.uri);
|
Song *song = r.directory->FindSong(r.uri);
|
||||||
if (song != nullptr) {
|
if (song != nullptr) {
|
||||||
const LightSong song2 = song->Export();
|
const LightSong song2 = song->Export();
|
||||||
return !selection.Match(song2) ||
|
if (selection.Match(song2))
|
||||||
visit_song(song2, error);
|
visit_song(song2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,23 +103,21 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool VisitServer(const ContentDirectoryService &server,
|
void VisitServer(const ContentDirectoryService &server,
|
||||||
const std::list<std::string> &vpath,
|
const std::list<std::string> &vpath,
|
||||||
const DatabaseSelection &selection,
|
const DatabaseSelection &selection,
|
||||||
VisitDirectory visit_directory,
|
VisitDirectory visit_directory,
|
||||||
VisitSong visit_song,
|
VisitSong visit_song,
|
||||||
VisitPlaylist visit_playlist,
|
VisitPlaylist visit_playlist) const;
|
||||||
Error &error) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run an UPnP search according to MPD parameters, and
|
* Run an UPnP search according to MPD parameters, and
|
||||||
* visit_song the results.
|
* visit_song the results.
|
||||||
*/
|
*/
|
||||||
bool SearchSongs(const ContentDirectoryService &server,
|
void SearchSongs(const ContentDirectoryService &server,
|
||||||
const char *objid,
|
const char *objid,
|
||||||
const DatabaseSelection &selection,
|
const DatabaseSelection &selection,
|
||||||
VisitSong visit_song,
|
VisitSong visit_song) const;
|
||||||
Error &error) const;
|
|
||||||
|
|
||||||
UPnPDirContent SearchSongs(const ContentDirectoryService &server,
|
UPnPDirContent SearchSongs(const ContentDirectoryService &server,
|
||||||
const char *objid,
|
const char *objid,
|
||||||
|
@ -307,13 +305,13 @@ UpnpDatabase::SearchSongs(const ContentDirectoryService &server,
|
||||||
return server.search(handle, objid, cond.c_str());
|
return server.search(handle, objid, cond.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
visitSong(const UPnPDirObject &meta, const char *path,
|
visitSong(const UPnPDirObject &meta, const char *path,
|
||||||
const DatabaseSelection &selection,
|
const DatabaseSelection &selection,
|
||||||
VisitSong visit_song, Error& error)
|
VisitSong visit_song)
|
||||||
{
|
{
|
||||||
if (!visit_song)
|
if (!visit_song)
|
||||||
return true;
|
return;
|
||||||
|
|
||||||
LightSong song;
|
LightSong song;
|
||||||
song.directory = nullptr;
|
song.directory = nullptr;
|
||||||
|
@ -323,7 +321,8 @@ visitSong(const UPnPDirObject &meta, const char *path,
|
||||||
song.mtime = 0;
|
song.mtime = 0;
|
||||||
song.start_time = song.end_time = SongTime::zero();
|
song.start_time = song.end_time = SongTime::zero();
|
||||||
|
|
||||||
return !selection.Match(song) || visit_song(song, error);
|
if (selection.Match(song))
|
||||||
|
visit_song(song);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -338,15 +337,14 @@ songPath(const std::string &servername,
|
||||||
return servername + "/" + rootid + "/" + objid;
|
return servername + "/" + rootid + "/" + objid;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
UpnpDatabase::SearchSongs(const ContentDirectoryService &server,
|
UpnpDatabase::SearchSongs(const ContentDirectoryService &server,
|
||||||
const char *objid,
|
const char *objid,
|
||||||
const DatabaseSelection &selection,
|
const DatabaseSelection &selection,
|
||||||
VisitSong visit_song,
|
VisitSong visit_song) const
|
||||||
Error &error) const
|
|
||||||
{
|
{
|
||||||
if (!visit_song)
|
if (!visit_song)
|
||||||
return true;
|
return;
|
||||||
|
|
||||||
for (auto &dirent : SearchSongs(server, objid, selection).objects) {
|
for (auto &dirent : SearchSongs(server, objid, selection).objects) {
|
||||||
if (dirent.type != UPnPDirObject::Type::ITEM ||
|
if (dirent.type != UPnPDirObject::Type::ITEM ||
|
||||||
|
@ -371,13 +369,9 @@ UpnpDatabase::SearchSongs(const ContentDirectoryService &server,
|
||||||
// which we later have to detect.
|
// which we later have to detect.
|
||||||
const std::string path = songPath(server.getFriendlyName(),
|
const std::string path = songPath(server.getFriendlyName(),
|
||||||
dirent.id);
|
dirent.id);
|
||||||
if (!visitSong(std::move(dirent), path.c_str(),
|
visitSong(std::move(dirent), path.c_str(),
|
||||||
selection, visit_song,
|
selection, visit_song);
|
||||||
error))
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UPnPDirObject
|
UPnPDirObject
|
||||||
|
@ -444,19 +438,17 @@ UpnpDatabase::Namei(const ContentDirectoryService &server,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
VisitItem(const UPnPDirObject &object, const char *uri,
|
VisitItem(const UPnPDirObject &object, const char *uri,
|
||||||
const DatabaseSelection &selection,
|
const DatabaseSelection &selection,
|
||||||
VisitSong visit_song, VisitPlaylist visit_playlist,
|
VisitSong visit_song, VisitPlaylist visit_playlist)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
assert(object.type == UPnPDirObject::Type::ITEM);
|
assert(object.type == UPnPDirObject::Type::ITEM);
|
||||||
|
|
||||||
switch (object.item_class) {
|
switch (object.item_class) {
|
||||||
case UPnPDirObject::ItemClass::MUSIC:
|
case UPnPDirObject::ItemClass::MUSIC:
|
||||||
return !visit_song ||
|
visitSong(object, uri, selection, visit_song);
|
||||||
visitSong(object, uri,
|
break;
|
||||||
selection, visit_song, error);
|
|
||||||
|
|
||||||
case UPnPDirObject::ItemClass::PLAYLIST:
|
case UPnPDirObject::ItemClass::PLAYLIST:
|
||||||
if (visit_playlist) {
|
if (visit_playlist) {
|
||||||
|
@ -468,23 +460,19 @@ VisitItem(const UPnPDirObject &object, const char *uri,
|
||||||
see one... */
|
see one... */
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
break;
|
||||||
|
|
||||||
case UPnPDirObject::ItemClass::UNKNOWN:
|
case UPnPDirObject::ItemClass::UNKNOWN:
|
||||||
return true;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(false);
|
static void
|
||||||
gcc_unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
VisitObject(const UPnPDirObject &object, const char *uri,
|
VisitObject(const UPnPDirObject &object, const char *uri,
|
||||||
const DatabaseSelection &selection,
|
const DatabaseSelection &selection,
|
||||||
VisitDirectory visit_directory,
|
VisitDirectory visit_directory,
|
||||||
VisitSong visit_song,
|
VisitSong visit_song,
|
||||||
VisitPlaylist visit_playlist,
|
VisitPlaylist visit_playlist)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
switch (object.type) {
|
switch (object.type) {
|
||||||
case UPnPDirObject::Type::UNKNOWN:
|
case UPnPDirObject::Type::UNKNOWN:
|
||||||
|
@ -492,29 +480,26 @@ VisitObject(const UPnPDirObject &object, const char *uri,
|
||||||
gcc_unreachable();
|
gcc_unreachable();
|
||||||
|
|
||||||
case UPnPDirObject::Type::CONTAINER:
|
case UPnPDirObject::Type::CONTAINER:
|
||||||
return !visit_directory ||
|
if (visit_directory)
|
||||||
visit_directory(LightDirectory(uri, 0), error);
|
visit_directory(LightDirectory(uri, 0));
|
||||||
|
break;
|
||||||
|
|
||||||
case UPnPDirObject::Type::ITEM:
|
case UPnPDirObject::Type::ITEM:
|
||||||
return VisitItem(object, uri, selection,
|
VisitItem(object, uri, selection,
|
||||||
visit_song, visit_playlist,
|
visit_song, visit_playlist);
|
||||||
error);
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(false);
|
|
||||||
gcc_unreachable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// vpath is a parsed and writeable version of selection.uri. There is
|
// vpath is a parsed and writeable version of selection.uri. There is
|
||||||
// really just one path parameter.
|
// really just one path parameter.
|
||||||
bool
|
void
|
||||||
UpnpDatabase::VisitServer(const ContentDirectoryService &server,
|
UpnpDatabase::VisitServer(const ContentDirectoryService &server,
|
||||||
const std::list<std::string> &vpath,
|
const std::list<std::string> &vpath,
|
||||||
const DatabaseSelection &selection,
|
const DatabaseSelection &selection,
|
||||||
VisitDirectory visit_directory,
|
VisitDirectory visit_directory,
|
||||||
VisitSong visit_song,
|
VisitSong visit_song,
|
||||||
VisitPlaylist visit_playlist,
|
VisitPlaylist visit_playlist) const
|
||||||
Error &error) const
|
|
||||||
{
|
{
|
||||||
/* If the path begins with rootid, we know that this is a
|
/* If the path begins with rootid, we know that this is a
|
||||||
song, not a directory (because that's how we set things
|
song, not a directory (because that's how we set things
|
||||||
|
@ -527,7 +512,7 @@ UpnpDatabase::VisitServer(const ContentDirectoryService &server,
|
||||||
if (!vpath.empty() && vpath.front() == rootid) {
|
if (!vpath.empty() && vpath.front() == rootid) {
|
||||||
switch (vpath.size()) {
|
switch (vpath.size()) {
|
||||||
case 1:
|
case 1:
|
||||||
return true;
|
return;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
break;
|
break;
|
||||||
|
@ -547,12 +532,11 @@ UpnpDatabase::VisitServer(const ContentDirectoryService &server,
|
||||||
|
|
||||||
std::string path = songPath(server.getFriendlyName(),
|
std::string path = songPath(server.getFriendlyName(),
|
||||||
dirent.id);
|
dirent.id);
|
||||||
if (!visitSong(std::move(dirent), path.c_str(),
|
visitSong(std::move(dirent), path.c_str(),
|
||||||
selection,
|
selection, visit_song);
|
||||||
visit_song, error))
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translate the target path into an object id and the associated metadata.
|
// Translate the target path into an object id and the associated metadata.
|
||||||
|
@ -562,19 +546,20 @@ UpnpDatabase::VisitServer(const ContentDirectoryService &server,
|
||||||
if the filter is empty. In this case, we implement limited
|
if the filter is empty. In this case, we implement limited
|
||||||
recursion (1-deep) here, which will handle the "add dir"
|
recursion (1-deep) here, which will handle the "add dir"
|
||||||
case. */
|
case. */
|
||||||
if (selection.recursive && selection.filter)
|
if (selection.recursive && selection.filter) {
|
||||||
return SearchSongs(server, tdirent.id.c_str(), selection,
|
SearchSongs(server, tdirent.id.c_str(), selection, visit_song);
|
||||||
visit_song, error);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const char *const base_uri = selection.uri.empty()
|
const char *const base_uri = selection.uri.empty()
|
||||||
? server.getFriendlyName()
|
? server.getFriendlyName()
|
||||||
: selection.uri.c_str();
|
: selection.uri.c_str();
|
||||||
|
|
||||||
if (tdirent.type == UPnPDirObject::Type::ITEM) {
|
if (tdirent.type == UPnPDirObject::Type::ITEM) {
|
||||||
return VisitItem(tdirent, base_uri,
|
VisitItem(tdirent, base_uri,
|
||||||
selection,
|
selection,
|
||||||
visit_song, visit_playlist,
|
visit_song, visit_playlist);
|
||||||
error);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Target was a a container. Visit it. We could read slices
|
/* Target was a a container. Visit it. We could read slices
|
||||||
|
@ -583,15 +568,11 @@ UpnpDatabase::VisitServer(const ContentDirectoryService &server,
|
||||||
for (const auto &dirent : server.readDir(handle, tdirent.id.c_str()).objects) {
|
for (const auto &dirent : server.readDir(handle, tdirent.id.c_str()).objects) {
|
||||||
const std::string uri = PathTraitsUTF8::Build(base_uri,
|
const std::string uri = PathTraitsUTF8::Build(base_uri,
|
||||||
dirent.name.c_str());
|
dirent.name.c_str());
|
||||||
if (!VisitObject(dirent, uri.c_str(),
|
VisitObject(dirent, uri.c_str(),
|
||||||
selection,
|
selection,
|
||||||
visit_directory,
|
visit_directory,
|
||||||
visit_song, visit_playlist,
|
visit_song, visit_playlist);
|
||||||
error))
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deal with the possibly multiple servers, call VisitServer if needed.
|
// Deal with the possibly multiple servers, call VisitServer if needed.
|
||||||
|
@ -600,22 +581,20 @@ UpnpDatabase::Visit(const DatabaseSelection &selection,
|
||||||
VisitDirectory visit_directory,
|
VisitDirectory visit_directory,
|
||||||
VisitSong visit_song,
|
VisitSong visit_song,
|
||||||
VisitPlaylist visit_playlist,
|
VisitPlaylist visit_playlist,
|
||||||
Error &error) const
|
Error &) const
|
||||||
{
|
{
|
||||||
auto vpath = stringToTokens(selection.uri, "/", true);
|
auto vpath = stringToTokens(selection.uri, "/", true);
|
||||||
if (vpath.empty()) {
|
if (vpath.empty()) {
|
||||||
for (const auto &server : discovery->GetDirectories()) {
|
for (const auto &server : discovery->GetDirectories()) {
|
||||||
if (visit_directory) {
|
if (visit_directory) {
|
||||||
const LightDirectory d(server.getFriendlyName(), 0);
|
const LightDirectory d(server.getFriendlyName(), 0);
|
||||||
if (!visit_directory(d, error))
|
visit_directory(d);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selection.recursive &&
|
if (selection.recursive)
|
||||||
!VisitServer(server, vpath, selection,
|
VisitServer(server, vpath, selection,
|
||||||
visit_directory, visit_song, visit_playlist,
|
visit_directory, visit_song,
|
||||||
error))
|
visit_playlist);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -626,15 +605,16 @@ UpnpDatabase::Visit(const DatabaseSelection &selection,
|
||||||
vpath.pop_front();
|
vpath.pop_front();
|
||||||
|
|
||||||
auto server = discovery->GetServer(servername.c_str());
|
auto server = discovery->GetServer(servername.c_str());
|
||||||
return VisitServer(server, vpath, selection,
|
VisitServer(server, vpath, selection,
|
||||||
visit_directory, visit_song, visit_playlist, error);
|
visit_directory, visit_song, visit_playlist);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
UpnpDatabase::VisitUniqueTags(const DatabaseSelection &selection,
|
UpnpDatabase::VisitUniqueTags(const DatabaseSelection &selection,
|
||||||
TagType tag, gcc_unused tag_mask_t group_mask,
|
TagType tag, gcc_unused tag_mask_t group_mask,
|
||||||
VisitTag visit_tag,
|
VisitTag visit_tag,
|
||||||
Error &error) const
|
Error &) const
|
||||||
{
|
{
|
||||||
// TODO: use group_mask
|
// TODO: use group_mask
|
||||||
|
|
||||||
|
@ -664,8 +644,7 @@ UpnpDatabase::VisitUniqueTags(const DatabaseSelection &selection,
|
||||||
for (const auto& value : values) {
|
for (const auto& value : values) {
|
||||||
TagBuilder builder;
|
TagBuilder builder;
|
||||||
builder.AddItem(tag, value.c_str());
|
builder.AddItem(tag, value.c_str());
|
||||||
if (!visit_tag(builder.Commit(), error))
|
visit_tag(builder.Commit());
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -64,30 +64,26 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
DumpDirectory(const LightDirectory &directory, Error &)
|
DumpDirectory(const LightDirectory &directory)
|
||||||
{
|
{
|
||||||
cout << "D " << directory.GetPath() << endl;
|
cout << "D " << directory.GetPath() << endl;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
DumpSong(const LightSong &song, Error &)
|
DumpSong(const LightSong &song)
|
||||||
{
|
{
|
||||||
cout << "S ";
|
cout << "S ";
|
||||||
if (song.directory != nullptr)
|
if (song.directory != nullptr)
|
||||||
cout << song.directory << "/";
|
cout << song.directory << "/";
|
||||||
cout << song.uri << endl;
|
cout << song.uri << endl;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
DumpPlaylist(const PlaylistInfo &playlist,
|
DumpPlaylist(const PlaylistInfo &playlist, const LightDirectory &directory)
|
||||||
const LightDirectory &directory, Error &)
|
|
||||||
{
|
{
|
||||||
cout << "P " << directory.GetPath()
|
cout << "P " << directory.GetPath()
|
||||||
<< "/" << playlist.name.c_str() << endl;
|
<< "/" << playlist.name.c_str() << endl;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
Loading…
Reference in New Issue