db/Interface: migrate visitor methods from class Error to C++ exceptions
This commit is contained in:
parent
9a9da7b077
commit
fac8edd47a
@ -26,7 +26,6 @@
|
|||||||
#include "db/Selection.hxx"
|
#include "db/Selection.hxx"
|
||||||
#include "db/Interface.hxx"
|
#include "db/Interface.hxx"
|
||||||
#include "db/Stats.hxx"
|
#include "db/Stats.hxx"
|
||||||
#include "util/Error.hxx"
|
|
||||||
#include "system/Clock.hxx"
|
#include "system/Clock.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
|
|
||||||
@ -79,20 +78,12 @@ stats_update(const Database &db)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error error;
|
|
||||||
|
|
||||||
const DatabaseSelection selection("", true);
|
const DatabaseSelection selection("", true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (db.GetStats(selection, stats, error)) {
|
stats = db.GetStats(selection);
|
||||||
stats_validity = StatsValidity::VALID;
|
stats_validity = StatsValidity::VALID;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
|
||||||
LogError(error);
|
|
||||||
|
|
||||||
stats_validity = StatsValidity::FAILED;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} catch (const std::runtime_error &e) {
|
} catch (const std::runtime_error &e) {
|
||||||
LogError(e);
|
LogError(e);
|
||||||
stats_validity = StatsValidity::FAILED;
|
stats_validity = StatsValidity::FAILED;
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
#include "client/Response.hxx"
|
#include "client/Response.hxx"
|
||||||
#include "tag/Tag.hxx"
|
#include "tag/Tag.hxx"
|
||||||
#include "util/ConstBuffer.hxx"
|
#include "util/ConstBuffer.hxx"
|
||||||
#include "util/Error.hxx"
|
|
||||||
#include "util/StringAPI.hxx"
|
#include "util/StringAPI.hxx"
|
||||||
#include "SongFilter.hxx"
|
#include "SongFilter.hxx"
|
||||||
#include "BulkEdit.hxx"
|
#include "BulkEdit.hxx"
|
||||||
@ -41,12 +40,8 @@ CommandResult
|
|||||||
handle_listfiles_db(Client &client, Response &r, const char *uri)
|
handle_listfiles_db(Client &client, Response &r, const char *uri)
|
||||||
{
|
{
|
||||||
const DatabaseSelection selection(uri, false);
|
const DatabaseSelection selection(uri, false);
|
||||||
|
db_selection_print(r, client.partition,
|
||||||
Error error;
|
selection, false, true);
|
||||||
if (!db_selection_print(r, client.partition,
|
|
||||||
selection, false, true, error))
|
|
||||||
return print_error(r, error);
|
|
||||||
|
|
||||||
return CommandResult::OK;
|
return CommandResult::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,12 +49,8 @@ CommandResult
|
|||||||
handle_lsinfo2(Client &client, const char *uri, Response &r)
|
handle_lsinfo2(Client &client, const char *uri, Response &r)
|
||||||
{
|
{
|
||||||
const DatabaseSelection selection(uri, false);
|
const DatabaseSelection selection(uri, false);
|
||||||
|
db_selection_print(r, client.partition,
|
||||||
Error error;
|
selection, true, false);
|
||||||
if (!db_selection_print(r, client.partition,
|
|
||||||
selection, true, false, error))
|
|
||||||
return print_error(r, error);
|
|
||||||
|
|
||||||
return CommandResult::OK;
|
return CommandResult::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,12 +74,10 @@ handle_match(Client &client, Request args, Response &r, bool fold_case)
|
|||||||
|
|
||||||
const DatabaseSelection selection("", true, &filter);
|
const DatabaseSelection selection("", true, &filter);
|
||||||
|
|
||||||
Error error;
|
db_selection_print(r, client.partition,
|
||||||
return db_selection_print(r, client.partition,
|
|
||||||
selection, true, false,
|
selection, true, false,
|
||||||
window.start, window.end, error)
|
window.start, window.end);
|
||||||
? CommandResult::OK
|
return CommandResult::OK;
|
||||||
: print_error(r, error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandResult
|
CommandResult
|
||||||
@ -115,10 +104,8 @@ handle_match_add(Client &client, Request args, Response &r, bool fold_case)
|
|||||||
const ScopeBulkEdit bulk_edit(client.partition);
|
const ScopeBulkEdit bulk_edit(client.partition);
|
||||||
|
|
||||||
const DatabaseSelection selection("", true, &filter);
|
const DatabaseSelection selection("", true, &filter);
|
||||||
Error error;
|
AddFromDatabase(client.partition, selection);
|
||||||
return AddFromDatabase(client.partition, selection, error)
|
return CommandResult::OK;
|
||||||
? CommandResult::OK
|
|
||||||
: print_error(r, error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandResult
|
CommandResult
|
||||||
@ -144,13 +131,11 @@ handle_searchaddpl(Client &client, Request args, Response &r)
|
|||||||
return CommandResult::ERROR;
|
return CommandResult::ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error error;
|
|
||||||
const Database &db = client.GetDatabaseOrThrow();
|
const Database &db = client.GetDatabaseOrThrow();
|
||||||
|
|
||||||
return search_add_to_playlist(db, *client.GetStorage(),
|
search_add_to_playlist(db, *client.GetStorage(),
|
||||||
"", playlist, &filter, error)
|
"", playlist, &filter);
|
||||||
? CommandResult::OK
|
return CommandResult::OK;
|
||||||
: print_error(r, error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandResult
|
CommandResult
|
||||||
@ -176,10 +161,8 @@ handle_count(Client &client, Request args, Response &r)
|
|||||||
return CommandResult::ERROR;
|
return CommandResult::ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error error;
|
PrintSongCount(r, client.partition, "", &filter, group);
|
||||||
return PrintSongCount(r, client.partition, "", &filter, group, error)
|
return CommandResult::OK;
|
||||||
? CommandResult::OK
|
|
||||||
: print_error(r, error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandResult
|
CommandResult
|
||||||
@ -188,12 +171,10 @@ handle_listall(Client &client, Request args, Response &r)
|
|||||||
/* default is root directory */
|
/* default is root directory */
|
||||||
const auto uri = args.GetOptional(0, "");
|
const auto uri = args.GetOptional(0, "");
|
||||||
|
|
||||||
Error error;
|
db_selection_print(r, client.partition,
|
||||||
return db_selection_print(r, client.partition,
|
|
||||||
DatabaseSelection(uri, true),
|
DatabaseSelection(uri, true),
|
||||||
false, false, error)
|
false, false);
|
||||||
? CommandResult::OK
|
return CommandResult::OK;
|
||||||
: print_error(r, error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandResult
|
CommandResult
|
||||||
@ -255,14 +236,9 @@ handle_list(Client &client, Request args, Response &r)
|
|||||||
return CommandResult::ERROR;
|
return CommandResult::ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error error;
|
|
||||||
CommandResult ret =
|
|
||||||
PrintUniqueTags(r, client.partition,
|
PrintUniqueTags(r, client.partition,
|
||||||
tagType, group_mask, filter.get(), error)
|
tagType, group_mask, filter.get());
|
||||||
? CommandResult::OK
|
return CommandResult::OK;
|
||||||
: print_error(r, error);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandResult
|
CommandResult
|
||||||
@ -271,10 +247,8 @@ handle_listallinfo(Client &client, Request args, Response &r)
|
|||||||
/* default is root directory */
|
/* default is root directory */
|
||||||
const auto uri = args.GetOptional(0, "");
|
const auto uri = args.GetOptional(0, "");
|
||||||
|
|
||||||
Error error;
|
db_selection_print(r, client.partition,
|
||||||
return db_selection_print(r, client.partition,
|
|
||||||
DatabaseSelection(uri, true),
|
DatabaseSelection(uri, true),
|
||||||
true, false, error)
|
true, false);
|
||||||
? CommandResult::OK
|
return CommandResult::OK;
|
||||||
: print_error(r, error);
|
|
||||||
}
|
}
|
||||||
|
@ -156,35 +156,27 @@ handle_playlistclear(gcc_unused Client &client,
|
|||||||
}
|
}
|
||||||
|
|
||||||
CommandResult
|
CommandResult
|
||||||
handle_playlistadd(Client &client, Request args, Response &r)
|
handle_playlistadd(Client &client, Request args, gcc_unused Response &r)
|
||||||
{
|
{
|
||||||
const char *const playlist = args[0];
|
const char *const playlist = args[0];
|
||||||
const char *const uri = args[1];
|
const char *const uri = args[1];
|
||||||
|
|
||||||
bool success;
|
|
||||||
Error error;
|
|
||||||
if (uri_has_scheme(uri)) {
|
if (uri_has_scheme(uri)) {
|
||||||
const SongLoader loader(client);
|
const SongLoader loader(client);
|
||||||
spl_append_uri(playlist, loader, uri);
|
spl_append_uri(playlist, loader, uri);
|
||||||
success = true;
|
|
||||||
} else {
|
} else {
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
const Database &db = client.GetDatabaseOrThrow();
|
const Database &db = client.GetDatabaseOrThrow();
|
||||||
|
|
||||||
success = search_add_to_playlist(db, *client.GetStorage(),
|
search_add_to_playlist(db, *client.GetStorage(),
|
||||||
uri, playlist, nullptr,
|
uri, playlist, nullptr);
|
||||||
error);
|
|
||||||
#else
|
#else
|
||||||
success = false;
|
r.Error(ACK_ERROR_NO_EXIST, "directory or file not found");
|
||||||
|
return CommandResult::ERROR;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success && !error.IsDefined()) {
|
return CommandResult::OK;
|
||||||
r.Error(ACK_ERROR_NO_EXIST, "directory or file not found");
|
|
||||||
return CommandResult::ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
return success ? CommandResult::OK : print_error(r, error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandResult
|
CommandResult
|
||||||
|
@ -52,16 +52,15 @@ AddUri(Client &client, const LocatedUri &uri)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static CommandResult
|
static CommandResult
|
||||||
AddDatabaseSelection(Client &client, const char *uri, Response &r)
|
AddDatabaseSelection(Client &client, const char *uri,
|
||||||
|
gcc_unused Response &r)
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
const ScopeBulkEdit bulk_edit(client.partition);
|
const ScopeBulkEdit bulk_edit(client.partition);
|
||||||
|
|
||||||
const DatabaseSelection selection(uri, true);
|
const DatabaseSelection selection(uri, true);
|
||||||
Error error;
|
AddFromDatabase(client.partition, selection);
|
||||||
return AddFromDatabase(client.partition, selection, error)
|
return CommandResult::OK;
|
||||||
? CommandResult::OK
|
|
||||||
: print_error(r, error);
|
|
||||||
#else
|
#else
|
||||||
(void)client;
|
(void)client;
|
||||||
(void)uri;
|
(void)uri;
|
||||||
|
@ -107,11 +107,10 @@ GroupCountVisitor(TagCountMap &map, TagType group, const LightSong &song)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
PrintSongCount(Response &r, const Partition &partition, const char *name,
|
PrintSongCount(Response &r, const Partition &partition, const char *name,
|
||||||
const SongFilter *filter,
|
const SongFilter *filter,
|
||||||
TagType group,
|
TagType group)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
const Database &db = partition.GetDatabaseOrThrow();
|
const Database &db = partition.GetDatabaseOrThrow();
|
||||||
|
|
||||||
@ -125,8 +124,7 @@ PrintSongCount(Response &r, const Partition &partition, const char *name,
|
|||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
const auto f = std::bind(stats_visitor_song, std::ref(stats),
|
const auto f = std::bind(stats_visitor_song, std::ref(stats),
|
||||||
_1);
|
_1);
|
||||||
if (!db.Visit(selection, f, error))
|
db.Visit(selection, f);
|
||||||
return false;
|
|
||||||
|
|
||||||
PrintSearchStats(r, stats);
|
PrintSearchStats(r, stats);
|
||||||
} else {
|
} else {
|
||||||
@ -138,11 +136,8 @@ PrintSongCount(Response &r, const Partition &partition, const char *name,
|
|||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
const auto f = std::bind(GroupCountVisitor, std::ref(map),
|
const auto f = std::bind(GroupCountVisitor, std::ref(map),
|
||||||
group, _1);
|
group, _1);
|
||||||
if (!db.Visit(selection, f, error))
|
db.Visit(selection, f);
|
||||||
return false;
|
|
||||||
|
|
||||||
Print(r, group, map);
|
Print(r, group, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
@ -28,13 +28,11 @@ enum TagType : uint8_t;
|
|||||||
struct Partition;
|
struct Partition;
|
||||||
class Response;
|
class Response;
|
||||||
class SongFilter;
|
class SongFilter;
|
||||||
class Error;
|
|
||||||
|
|
||||||
gcc_nonnull(3)
|
gcc_nonnull(3)
|
||||||
bool
|
void
|
||||||
PrintSongCount(Response &r, const Partition &partition, const char *name,
|
PrintSongCount(Response &r, const Partition &partition, const char *name,
|
||||||
const SongFilter *filter,
|
const SongFilter *filter,
|
||||||
TagType group,
|
TagType group);
|
||||||
Error &error);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -36,16 +36,15 @@ AddSong(const Storage &storage, const char *playlist_path_utf8,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
search_add_to_playlist(const Database &db, const Storage &storage,
|
search_add_to_playlist(const Database &db, const Storage &storage,
|
||||||
const char *uri, const char *playlist_path_utf8,
|
const char *uri, const char *playlist_path_utf8,
|
||||||
const SongFilter *filter,
|
const SongFilter *filter)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
const DatabaseSelection selection(uri, true, filter);
|
const DatabaseSelection selection(uri, true, filter);
|
||||||
|
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
const auto f = std::bind(AddSong, std::ref(storage),
|
const auto f = std::bind(AddSong, std::ref(storage),
|
||||||
playlist_path_utf8, _1);
|
playlist_path_utf8, _1);
|
||||||
return db.Visit(selection, f, error);
|
db.Visit(selection, f);
|
||||||
}
|
}
|
||||||
|
@ -25,13 +25,11 @@
|
|||||||
class Database;
|
class Database;
|
||||||
class Storage;
|
class Storage;
|
||||||
class SongFilter;
|
class SongFilter;
|
||||||
class Error;
|
|
||||||
|
|
||||||
gcc_nonnull(3,4)
|
gcc_nonnull(3,4)
|
||||||
bool
|
void
|
||||||
search_add_to_playlist(const Database &db, const Storage &storage,
|
search_add_to_playlist(const Database &db, const Storage &storage,
|
||||||
const char *uri, const char *path_utf8,
|
const char *uri, const char *path_utf8,
|
||||||
const SongFilter *filter,
|
const SongFilter *filter);
|
||||||
Error &error);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -148,12 +148,11 @@ PrintPlaylistFull(Response &r, bool base,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
db_selection_print(Response &r, Partition &partition,
|
db_selection_print(Response &r, Partition &partition,
|
||||||
const DatabaseSelection &selection,
|
const DatabaseSelection &selection,
|
||||||
bool full, bool base,
|
bool full, bool base,
|
||||||
unsigned window_start, unsigned window_end,
|
unsigned window_start, unsigned window_end)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
const Database &db = partition.GetDatabaseOrThrow();
|
const Database &db = partition.GetDatabaseOrThrow();
|
||||||
|
|
||||||
@ -180,18 +179,16 @@ db_selection_print(Response &r, Partition &partition,
|
|||||||
s(song);
|
s(song);
|
||||||
};
|
};
|
||||||
|
|
||||||
return db.Visit(selection, d, s, p, error);
|
db.Visit(selection, d, s, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
db_selection_print(Response &r, Partition &partition,
|
db_selection_print(Response &r, Partition &partition,
|
||||||
const DatabaseSelection &selection,
|
const DatabaseSelection &selection,
|
||||||
bool full, bool base,
|
bool full, bool base)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
return db_selection_print(r, partition, selection, full, base,
|
db_selection_print(r, partition, selection, full, base,
|
||||||
0, std::numeric_limits<int>::max(),
|
0, std::numeric_limits<int>::max());
|
||||||
error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@ -218,11 +215,10 @@ PrintUniqueTag(Response &r, TagType tag_type,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
PrintUniqueTags(Response &r, Partition &partition,
|
PrintUniqueTags(Response &r, Partition &partition,
|
||||||
unsigned type, tag_mask_t group_mask,
|
unsigned type, tag_mask_t group_mask,
|
||||||
const SongFilter *filter,
|
const SongFilter *filter)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
const Database &db = partition.GetDatabaseOrThrow();
|
const Database &db = partition.GetDatabaseOrThrow();
|
||||||
|
|
||||||
@ -232,15 +228,14 @@ PrintUniqueTags(Response &r, Partition &partition,
|
|||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
const auto f = std::bind(PrintSongURIVisitor,
|
const auto f = std::bind(PrintSongURIVisitor,
|
||||||
std::ref(r), std::ref(partition), _1);
|
std::ref(r), std::ref(partition), _1);
|
||||||
return db.Visit(selection, f, error);
|
db.Visit(selection, f);
|
||||||
} else {
|
} else {
|
||||||
assert(type < TAG_NUM_OF_ITEM_TYPES);
|
assert(type < TAG_NUM_OF_ITEM_TYPES);
|
||||||
|
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
const auto f = std::bind(PrintUniqueTag, std::ref(r),
|
const auto f = std::bind(PrintUniqueTag, std::ref(r),
|
||||||
(TagType)type, _1);
|
(TagType)type, _1);
|
||||||
return db.VisitUniqueTags(selection, (TagType)type,
|
db.VisitUniqueTags(selection, (TagType)type,
|
||||||
group_mask,
|
group_mask, f);
|
||||||
f, error);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,28 +26,25 @@ class SongFilter;
|
|||||||
struct DatabaseSelection;
|
struct DatabaseSelection;
|
||||||
struct Partition;
|
struct Partition;
|
||||||
class Response;
|
class Response;
|
||||||
class Error;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param full print attributes/tags
|
* @param full print attributes/tags
|
||||||
* @param base print only base name of songs/directories?
|
* @param base print only base name of songs/directories?
|
||||||
*/
|
*/
|
||||||
bool
|
void
|
||||||
db_selection_print(Response &r, Partition &partition,
|
db_selection_print(Response &r, Partition &partition,
|
||||||
const DatabaseSelection &selection,
|
const DatabaseSelection &selection,
|
||||||
bool full, bool base, Error &error);
|
bool full, bool base);
|
||||||
|
|
||||||
bool
|
void
|
||||||
db_selection_print(Response &r, Partition &partition,
|
db_selection_print(Response &r, Partition &partition,
|
||||||
const DatabaseSelection &selection,
|
const DatabaseSelection &selection,
|
||||||
bool full, bool base,
|
bool full, bool base,
|
||||||
unsigned window_start, unsigned window_end,
|
unsigned window_start, unsigned window_end);
|
||||||
Error &error);
|
|
||||||
|
|
||||||
bool
|
void
|
||||||
PrintUniqueTags(Response &r, Partition &partition,
|
PrintUniqueTags(Response &r, Partition &partition,
|
||||||
unsigned type, tag_mask_t group_mask,
|
unsigned type, tag_mask_t group_mask,
|
||||||
const SongFilter *filter,
|
const SongFilter *filter);
|
||||||
Error &error);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -37,13 +37,12 @@ AddToQueue(Partition &partition, const LightSong &song)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
AddFromDatabase(Partition &partition, const DatabaseSelection &selection,
|
AddFromDatabase(Partition &partition, const DatabaseSelection &selection)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
const Database &db = partition.instance.GetDatabaseOrThrow();
|
const Database &db = partition.instance.GetDatabaseOrThrow();
|
||||||
|
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
const auto f = std::bind(AddToQueue, std::ref(partition), _1);
|
const auto f = std::bind(AddToQueue, std::ref(partition), _1);
|
||||||
return db.Visit(selection, f, error);
|
db.Visit(selection, f);
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,8 @@
|
|||||||
|
|
||||||
struct Partition;
|
struct Partition;
|
||||||
struct DatabaseSelection;
|
struct DatabaseSelection;
|
||||||
class Error;
|
|
||||||
|
|
||||||
bool
|
void
|
||||||
AddFromDatabase(Partition &partition, const DatabaseSelection &selection,
|
AddFromDatabase(Partition &partition, const DatabaseSelection &selection);
|
||||||
Error &error);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -78,10 +78,10 @@ StatsVisitSong(DatabaseStats &stats, StringSet &artists, StringSet &albums,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
DatabaseStats
|
||||||
GetStats(const Database &db, const DatabaseSelection &selection,
|
GetStats(const Database &db, const DatabaseSelection &selection)
|
||||||
DatabaseStats &stats, Error &error)
|
|
||||||
{
|
{
|
||||||
|
DatabaseStats stats;
|
||||||
stats.Clear();
|
stats.Clear();
|
||||||
|
|
||||||
StringSet artists, albums;
|
StringSet artists, albums;
|
||||||
@ -89,10 +89,9 @@ GetStats(const Database &db, const DatabaseSelection &selection,
|
|||||||
const auto f = std::bind(StatsVisitSong,
|
const auto f = std::bind(StatsVisitSong,
|
||||||
std::ref(stats), std::ref(artists),
|
std::ref(stats), std::ref(artists),
|
||||||
std::ref(albums), _1);
|
std::ref(albums), _1);
|
||||||
if (!db.Visit(selection, f, error))
|
db.Visit(selection, f);
|
||||||
return false;
|
|
||||||
|
|
||||||
stats.artist_count = artists.size();
|
stats.artist_count = artists.size();
|
||||||
stats.album_count = albums.size();
|
stats.album_count = albums.size();
|
||||||
return true;
|
return stats;
|
||||||
}
|
}
|
||||||
|
@ -20,13 +20,11 @@
|
|||||||
#ifndef MPD_MEMORY_DATABASE_PLUGIN_HXX
|
#ifndef MPD_MEMORY_DATABASE_PLUGIN_HXX
|
||||||
#define MPD_MEMORY_DATABASE_PLUGIN_HXX
|
#define MPD_MEMORY_DATABASE_PLUGIN_HXX
|
||||||
|
|
||||||
class Error;
|
|
||||||
class Database;
|
class Database;
|
||||||
struct DatabaseSelection;
|
struct DatabaseSelection;
|
||||||
struct DatabaseStats;
|
struct DatabaseStats;
|
||||||
|
|
||||||
bool
|
DatabaseStats
|
||||||
GetStats(const Database &db, const DatabaseSelection &selection,
|
GetStats(const Database &db, const DatabaseSelection &selection);
|
||||||
DatabaseStats &stats, Error &error);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -84,36 +84,31 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Visit the selected entities.
|
* Visit the selected entities.
|
||||||
*/
|
*/
|
||||||
virtual bool Visit(const DatabaseSelection &selection,
|
virtual void Visit(const DatabaseSelection &selection,
|
||||||
VisitDirectory visit_directory,
|
VisitDirectory visit_directory,
|
||||||
VisitSong visit_song,
|
VisitSong visit_song,
|
||||||
VisitPlaylist visit_playlist,
|
VisitPlaylist visit_playlist) const = 0;
|
||||||
Error &error) const = 0;
|
|
||||||
|
|
||||||
bool Visit(const DatabaseSelection &selection,
|
void Visit(const DatabaseSelection &selection,
|
||||||
VisitDirectory visit_directory,
|
VisitDirectory visit_directory,
|
||||||
VisitSong visit_song,
|
VisitSong visit_song) const {
|
||||||
Error &error) const {
|
Visit(selection, visit_directory, visit_song, VisitPlaylist());
|
||||||
return Visit(selection, visit_directory, visit_song,
|
|
||||||
VisitPlaylist(), error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Visit(const DatabaseSelection &selection, VisitSong visit_song,
|
void Visit(const DatabaseSelection &selection,
|
||||||
Error &error) const {
|
VisitSong visit_song) const {
|
||||||
return Visit(selection, VisitDirectory(), visit_song, error);
|
return Visit(selection, VisitDirectory(), visit_song);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visit all unique tag values.
|
* Visit all unique tag values.
|
||||||
*/
|
*/
|
||||||
virtual bool VisitUniqueTags(const DatabaseSelection &selection,
|
virtual void VisitUniqueTags(const DatabaseSelection &selection,
|
||||||
TagType tag_type, tag_mask_t group_mask,
|
TagType tag_type, tag_mask_t group_mask,
|
||||||
VisitTag visit_tag,
|
VisitTag visit_tag) const = 0;
|
||||||
Error &error) const = 0;
|
|
||||||
|
|
||||||
virtual bool GetStats(const DatabaseSelection &selection,
|
gcc_pure
|
||||||
DatabaseStats &stats,
|
virtual DatabaseStats GetStats(const DatabaseSelection &selection) const = 0;
|
||||||
Error &error) const = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the database. Returns the job id on success, 0 on
|
* Update the database. Returns the job id on success, 0 on
|
||||||
|
@ -36,22 +36,18 @@ CollectTags(TagSet &set, TagType tag_type, tag_mask_t group_mask,
|
|||||||
set.InsertUnique(tag, tag_type, group_mask);
|
set.InsertUnique(tag, tag_type, group_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
VisitUniqueTags(const Database &db, const DatabaseSelection &selection,
|
VisitUniqueTags(const Database &db, const DatabaseSelection &selection,
|
||||||
TagType tag_type, tag_mask_t group_mask,
|
TagType tag_type, tag_mask_t group_mask,
|
||||||
VisitTag visit_tag,
|
VisitTag visit_tag)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
TagSet set;
|
TagSet set;
|
||||||
|
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
const auto f = std::bind(CollectTags, std::ref(set),
|
const auto f = std::bind(CollectTags, std::ref(set),
|
||||||
tag_type, group_mask, _1);
|
tag_type, group_mask, _1);
|
||||||
if (!db.Visit(selection, f, error))
|
db.Visit(selection, f);
|
||||||
return false;
|
|
||||||
|
|
||||||
for (const auto &value : set)
|
for (const auto &value : set)
|
||||||
visit_tag(value);
|
visit_tag(value);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
@ -24,14 +24,12 @@
|
|||||||
#include "tag/TagType.h"
|
#include "tag/TagType.h"
|
||||||
#include "tag/Mask.hxx"
|
#include "tag/Mask.hxx"
|
||||||
|
|
||||||
class Error;
|
|
||||||
class Database;
|
class Database;
|
||||||
struct DatabaseSelection;
|
struct DatabaseSelection;
|
||||||
|
|
||||||
bool
|
void
|
||||||
VisitUniqueTags(const Database &db, const DatabaseSelection &selection,
|
VisitUniqueTags(const Database &db, const DatabaseSelection &selection,
|
||||||
TagType tag_type, tag_mask_t group_mask,
|
TagType tag_type, tag_mask_t group_mask,
|
||||||
VisitTag visit_tag,
|
VisitTag visit_tag);
|
||||||
Error &error);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,8 +33,6 @@
|
|||||||
#include "config/Block.hxx"
|
#include "config/Block.hxx"
|
||||||
#include "tag/TagBuilder.hxx"
|
#include "tag/TagBuilder.hxx"
|
||||||
#include "tag/Tag.hxx"
|
#include "tag/Tag.hxx"
|
||||||
#include "util/Error.hxx"
|
|
||||||
#include "util/Domain.hxx"
|
|
||||||
#include "util/ScopeExit.hxx"
|
#include "util/ScopeExit.hxx"
|
||||||
#include "protocol/Ack.hxx"
|
#include "protocol/Ack.hxx"
|
||||||
#include "event/SocketMonitor.hxx"
|
#include "event/SocketMonitor.hxx"
|
||||||
@ -115,20 +113,16 @@ public:
|
|||||||
const LightSong *GetSong(const char *uri_utf8) const override;
|
const LightSong *GetSong(const char *uri_utf8) const override;
|
||||||
void ReturnSong(const LightSong *song) const override;
|
void ReturnSong(const LightSong *song) const override;
|
||||||
|
|
||||||
virtual bool Visit(const DatabaseSelection &selection,
|
void Visit(const DatabaseSelection &selection,
|
||||||
VisitDirectory visit_directory,
|
VisitDirectory visit_directory,
|
||||||
VisitSong visit_song,
|
VisitSong visit_song,
|
||||||
VisitPlaylist visit_playlist,
|
VisitPlaylist visit_playlist) const override;
|
||||||
Error &error) const override;
|
|
||||||
|
|
||||||
virtual bool VisitUniqueTags(const DatabaseSelection &selection,
|
void VisitUniqueTags(const DatabaseSelection &selection,
|
||||||
TagType tag_type, tag_mask_t group_mask,
|
TagType tag_type, tag_mask_t group_mask,
|
||||||
VisitTag visit_tag,
|
VisitTag visit_tag) const override;
|
||||||
Error &error) const override;
|
|
||||||
|
|
||||||
virtual bool GetStats(const DatabaseSelection &selection,
|
DatabaseStats GetStats(const DatabaseSelection &selection) const override;
|
||||||
DatabaseStats &stats,
|
|
||||||
Error &error) const override;
|
|
||||||
|
|
||||||
virtual unsigned Update(const char *uri_utf8, bool discard,
|
virtual unsigned Update(const char *uri_utf8, bool discard,
|
||||||
Error &error) override;
|
Error &error) override;
|
||||||
@ -151,8 +145,6 @@ private:
|
|||||||
virtual void OnIdle() override;
|
virtual void OnIdle() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr Domain libmpdclient_domain("libmpdclient");
|
|
||||||
|
|
||||||
static constexpr struct {
|
static constexpr struct {
|
||||||
TagType d;
|
TagType d;
|
||||||
enum mpd_tag_type s;
|
enum mpd_tag_type s;
|
||||||
@ -543,18 +535,18 @@ ProxyDatabase::ReturnSong(const LightSong *_song) const
|
|||||||
delete song;
|
delete song;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
Visit(struct mpd_connection *connection, const char *uri,
|
Visit(struct mpd_connection *connection, const char *uri,
|
||||||
bool recursive, const SongFilter *filter,
|
bool recursive, const SongFilter *filter,
|
||||||
VisitDirectory visit_directory, VisitSong visit_song,
|
VisitDirectory visit_directory, VisitSong visit_song,
|
||||||
VisitPlaylist visit_playlist, Error &error);
|
VisitPlaylist visit_playlist);
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
Visit(struct mpd_connection *connection,
|
Visit(struct mpd_connection *connection,
|
||||||
bool recursive, const SongFilter *filter,
|
bool recursive, const SongFilter *filter,
|
||||||
const struct mpd_directory *directory,
|
const struct mpd_directory *directory,
|
||||||
VisitDirectory visit_directory, VisitSong visit_song,
|
VisitDirectory visit_directory, VisitSong visit_song,
|
||||||
VisitPlaylist visit_playlist, Error &error)
|
VisitPlaylist visit_playlist)
|
||||||
{
|
{
|
||||||
const char *path = mpd_directory_get_path(directory);
|
const char *path = mpd_directory_get_path(directory);
|
||||||
#if LIBMPDCLIENT_CHECK_VERSION(2,9,0)
|
#if LIBMPDCLIENT_CHECK_VERSION(2,9,0)
|
||||||
@ -566,12 +558,9 @@ Visit(struct mpd_connection *connection,
|
|||||||
if (visit_directory)
|
if (visit_directory)
|
||||||
visit_directory(LightDirectory(path, mtime));
|
visit_directory(LightDirectory(path, mtime));
|
||||||
|
|
||||||
if (recursive &&
|
if (recursive)
|
||||||
!Visit(connection, path, recursive, filter,
|
Visit(connection, path, recursive, filter,
|
||||||
visit_directory, visit_song, visit_playlist, error))
|
visit_directory, visit_song, visit_playlist);
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
@ -645,11 +634,11 @@ ReceiveEntities(struct mpd_connection *connection)
|
|||||||
return entities;
|
return entities;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
Visit(struct mpd_connection *connection, const char *uri,
|
Visit(struct mpd_connection *connection, const char *uri,
|
||||||
bool recursive, const SongFilter *filter,
|
bool recursive, const SongFilter *filter,
|
||||||
VisitDirectory visit_directory, VisitSong visit_song,
|
VisitDirectory visit_directory, VisitSong visit_song,
|
||||||
VisitPlaylist visit_playlist, Error &error)
|
VisitPlaylist visit_playlist)
|
||||||
{
|
{
|
||||||
if (!mpd_send_list_meta(connection, uri))
|
if (!mpd_send_list_meta(connection, uri))
|
||||||
ThrowError(connection);
|
ThrowError(connection);
|
||||||
@ -663,11 +652,9 @@ Visit(struct mpd_connection *connection, const char *uri,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MPD_ENTITY_TYPE_DIRECTORY:
|
case MPD_ENTITY_TYPE_DIRECTORY:
|
||||||
if (!Visit(connection, recursive, filter,
|
Visit(connection, recursive, filter,
|
||||||
mpd_entity_get_directory(entity),
|
mpd_entity_get_directory(entity),
|
||||||
visit_directory, visit_song, visit_playlist,
|
visit_directory, visit_song, visit_playlist);
|
||||||
error))
|
|
||||||
return false;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MPD_ENTITY_TYPE_SONG:
|
case MPD_ENTITY_TYPE_SONG:
|
||||||
@ -680,8 +667,6 @@ Visit(struct mpd_connection *connection, const char *uri,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -734,12 +719,11 @@ ServerSupportsSearchBase(const struct mpd_connection *connection)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
ProxyDatabase::Visit(const DatabaseSelection &selection,
|
ProxyDatabase::Visit(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
|
|
||||||
{
|
{
|
||||||
// TODO: eliminate the const_cast
|
// TODO: eliminate the const_cast
|
||||||
const_cast<ProxyDatabase *>(this)->EnsureConnected();
|
const_cast<ProxyDatabase *>(this)->EnsureConnected();
|
||||||
@ -751,31 +735,27 @@ ProxyDatabase::Visit(const DatabaseSelection &selection,
|
|||||||
/* this optimized code path can only be used under
|
/* this optimized code path can only be used under
|
||||||
certain conditions */
|
certain conditions */
|
||||||
::SearchSongs(connection, selection, visit_song);
|
::SearchSongs(connection, selection, visit_song);
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fall back to recursive walk (slow!) */
|
/* fall back to recursive walk (slow!) */
|
||||||
return ::Visit(connection, selection.uri.c_str(),
|
::Visit(connection, selection.uri.c_str(),
|
||||||
selection.recursive, selection.filter,
|
selection.recursive, selection.filter,
|
||||||
visit_directory, visit_song, visit_playlist,
|
visit_directory, visit_song, visit_playlist);
|
||||||
error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
ProxyDatabase::VisitUniqueTags(const DatabaseSelection &selection,
|
ProxyDatabase::VisitUniqueTags(const DatabaseSelection &selection,
|
||||||
TagType tag_type,
|
TagType tag_type,
|
||||||
gcc_unused tag_mask_t group_mask,
|
gcc_unused tag_mask_t group_mask,
|
||||||
VisitTag visit_tag,
|
VisitTag visit_tag) const
|
||||||
Error &error) const
|
|
||||||
{
|
{
|
||||||
// TODO: eliminate the const_cast
|
// TODO: eliminate the const_cast
|
||||||
const_cast<ProxyDatabase *>(this)->EnsureConnected();
|
const_cast<ProxyDatabase *>(this)->EnsureConnected();
|
||||||
|
|
||||||
enum mpd_tag_type tag_type2 = Convert(tag_type);
|
enum mpd_tag_type tag_type2 = Convert(tag_type);
|
||||||
if (tag_type2 == MPD_TAG_COUNT) {
|
if (tag_type2 == MPD_TAG_COUNT)
|
||||||
error.Set(libmpdclient_domain, "Unsupported tag");
|
throw std::runtime_error("Unsupported tag");
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mpd_search_db_tags(connection, tag_type2) ||
|
if (!mpd_search_db_tags(connection, tag_type2) ||
|
||||||
!SendConstraints(connection, selection))
|
!SendConstraints(connection, selection))
|
||||||
@ -812,13 +792,10 @@ ProxyDatabase::VisitUniqueTags(const DatabaseSelection &selection,
|
|||||||
|
|
||||||
if (!mpd_response_finish(connection))
|
if (!mpd_response_finish(connection))
|
||||||
ThrowError(connection);
|
ThrowError(connection);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
DatabaseStats
|
||||||
ProxyDatabase::GetStats(const DatabaseSelection &selection,
|
ProxyDatabase::GetStats(const DatabaseSelection &selection) const
|
||||||
DatabaseStats &stats, gcc_unused Error &error) const
|
|
||||||
{
|
{
|
||||||
// TODO: match
|
// TODO: match
|
||||||
(void)selection;
|
(void)selection;
|
||||||
@ -833,13 +810,13 @@ ProxyDatabase::GetStats(const DatabaseSelection &selection,
|
|||||||
|
|
||||||
update_stamp = (time_t)mpd_stats_get_db_update_time(stats2);
|
update_stamp = (time_t)mpd_stats_get_db_update_time(stats2);
|
||||||
|
|
||||||
|
DatabaseStats stats;
|
||||||
stats.song_count = mpd_stats_get_number_of_songs(stats2);
|
stats.song_count = mpd_stats_get_number_of_songs(stats2);
|
||||||
stats.total_duration = std::chrono::seconds(mpd_stats_get_db_play_time(stats2));
|
stats.total_duration = std::chrono::seconds(mpd_stats_get_db_play_time(stats2));
|
||||||
stats.artist_count = mpd_stats_get_number_of_artists(stats2);
|
stats.artist_count = mpd_stats_get_number_of_artists(stats2);
|
||||||
stats.album_count = mpd_stats_get_number_of_albums(stats2);
|
stats.album_count = mpd_stats_get_number_of_albums(stats2);
|
||||||
mpd_stats_free(stats2);
|
mpd_stats_free(stats2);
|
||||||
|
return stats;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
|
@ -32,7 +32,6 @@
|
|||||||
#include "fs/Traits.hxx"
|
#include "fs/Traits.hxx"
|
||||||
#include "util/Alloc.hxx"
|
#include "util/Alloc.hxx"
|
||||||
#include "util/DeleteDisposer.hxx"
|
#include "util/DeleteDisposer.hxx"
|
||||||
#include "util/Error.hxx"
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -218,14 +217,11 @@ Directory::Sort()
|
|||||||
child.Sort();
|
child.Sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
Directory::Walk(bool recursive, const SongFilter *filter,
|
Directory::Walk(bool recursive, const SongFilter *filter,
|
||||||
VisitDirectory visit_directory, VisitSong visit_song,
|
VisitDirectory visit_directory, VisitSong visit_song,
|
||||||
VisitPlaylist visit_playlist,
|
VisitPlaylist visit_playlist) const
|
||||||
Error &error) const
|
|
||||||
{
|
{
|
||||||
assert(!error.IsDefined());
|
|
||||||
|
|
||||||
if (IsMount()) {
|
if (IsMount()) {
|
||||||
assert(IsEmpty());
|
assert(IsEmpty());
|
||||||
|
|
||||||
@ -233,11 +229,11 @@ Directory::Walk(bool recursive, const SongFilter *filter,
|
|||||||
because the child's SimpleDatabasePlugin::Visit()
|
because the child's SimpleDatabasePlugin::Visit()
|
||||||
call will lock it again */
|
call will lock it again */
|
||||||
const ScopeDatabaseUnlock unlock;
|
const ScopeDatabaseUnlock unlock;
|
||||||
return WalkMount(GetPath(), *mounted_database,
|
WalkMount(GetPath(), *mounted_database,
|
||||||
recursive, filter,
|
recursive, filter,
|
||||||
visit_directory, visit_song,
|
visit_directory, visit_song,
|
||||||
visit_playlist,
|
visit_playlist);
|
||||||
error);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (visit_song) {
|
if (visit_song) {
|
||||||
@ -257,14 +253,11 @@ Directory::Walk(bool recursive, const SongFilter *filter,
|
|||||||
if (visit_directory)
|
if (visit_directory)
|
||||||
visit_directory(child.Export());
|
visit_directory(child.Export());
|
||||||
|
|
||||||
if (recursive &&
|
if (recursive)
|
||||||
!child.Walk(recursive, filter,
|
child.Walk(recursive, filter,
|
||||||
visit_directory, visit_song, visit_playlist,
|
visit_directory, visit_song,
|
||||||
error))
|
visit_playlist);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LightDirectory
|
LightDirectory
|
||||||
|
@ -44,7 +44,6 @@ static constexpr unsigned DEVICE_INARCHIVE = -1;
|
|||||||
static constexpr unsigned DEVICE_CONTAINER = -2;
|
static constexpr unsigned DEVICE_CONTAINER = -2;
|
||||||
|
|
||||||
class SongFilter;
|
class SongFilter;
|
||||||
class Error;
|
|
||||||
class Database;
|
class Database;
|
||||||
|
|
||||||
struct Directory {
|
struct Directory {
|
||||||
@ -266,10 +265,9 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Caller must lock #db_mutex.
|
* Caller must lock #db_mutex.
|
||||||
*/
|
*/
|
||||||
bool Walk(bool recursive, const SongFilter *match,
|
void Walk(bool recursive, const SongFilter *match,
|
||||||
VisitDirectory visit_directory, VisitSong visit_song,
|
VisitDirectory visit_directory, VisitSong visit_song,
|
||||||
VisitPlaylist visit_playlist,
|
VisitPlaylist visit_playlist) const;
|
||||||
Error &error) const;
|
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
LightDirectory Export() const;
|
LightDirectory Export() const;
|
||||||
|
@ -63,12 +63,11 @@ PrefixVisitPlaylist(const char *base, const VisitPlaylist &visit_playlist,
|
|||||||
PrefixedLightDirectory(directory, base));
|
PrefixedLightDirectory(directory, base));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
WalkMount(const char *base, const Database &db,
|
WalkMount(const char *base, const Database &db,
|
||||||
bool recursive, const SongFilter *filter,
|
bool recursive, const SongFilter *filter,
|
||||||
const VisitDirectory &visit_directory, const VisitSong &visit_song,
|
const VisitDirectory &visit_directory, const VisitSong &visit_song,
|
||||||
const VisitPlaylist &visit_playlist,
|
const VisitPlaylist &visit_playlist)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
|
|
||||||
@ -87,6 +86,5 @@ WalkMount(const char *base, const Database &db,
|
|||||||
vp = std::bind(PrefixVisitPlaylist,
|
vp = std::bind(PrefixVisitPlaylist,
|
||||||
base, std::ref(visit_playlist), _1, _2);
|
base, std::ref(visit_playlist), _1, _2);
|
||||||
|
|
||||||
return db.Visit(DatabaseSelection("", recursive, filter),
|
db.Visit(DatabaseSelection("", recursive, filter), vd, vs, vp);
|
||||||
vd, vs, vp, error);
|
|
||||||
}
|
}
|
||||||
|
@ -24,13 +24,11 @@
|
|||||||
|
|
||||||
class Database;
|
class Database;
|
||||||
class SongFilter;
|
class SongFilter;
|
||||||
class Error;
|
|
||||||
|
|
||||||
bool
|
void
|
||||||
WalkMount(const char *base, const Database &db,
|
WalkMount(const char *base, const Database &db,
|
||||||
bool recursive, const SongFilter *filter,
|
bool recursive, const SongFilter *filter,
|
||||||
const VisitDirectory &visit_directory, const VisitSong &visit_song,
|
const VisitDirectory &visit_directory, const VisitSong &visit_song,
|
||||||
const VisitPlaylist &visit_playlist,
|
const VisitPlaylist &visit_playlist);
|
||||||
Error &error);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "db/DatabasePlugin.hxx"
|
#include "db/DatabasePlugin.hxx"
|
||||||
#include "db/Selection.hxx"
|
#include "db/Selection.hxx"
|
||||||
#include "db/Helpers.hxx"
|
#include "db/Helpers.hxx"
|
||||||
|
#include "db/Stats.hxx"
|
||||||
#include "db/UniqueTags.hxx"
|
#include "db/UniqueTags.hxx"
|
||||||
#include "db/LightDirectory.hxx"
|
#include "db/LightDirectory.hxx"
|
||||||
#include "Directory.hxx"
|
#include "Directory.hxx"
|
||||||
@ -37,7 +38,6 @@
|
|||||||
#include "config/Block.hxx"
|
#include "config/Block.hxx"
|
||||||
#include "fs/FileSystem.hxx"
|
#include "fs/FileSystem.hxx"
|
||||||
#include "util/CharUtil.hxx"
|
#include "util/CharUtil.hxx"
|
||||||
#include "util/Error.hxx"
|
|
||||||
#include "util/Domain.hxx"
|
#include "util/Domain.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
|
|
||||||
@ -261,12 +261,11 @@ SimpleDatabase::ReturnSong(gcc_unused const LightSong *song) const
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
SimpleDatabase::Visit(const DatabaseSelection &selection,
|
SimpleDatabase::Visit(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
|
|
||||||
{
|
{
|
||||||
ScopeDatabaseLock protect;
|
ScopeDatabaseLock protect;
|
||||||
|
|
||||||
@ -277,10 +276,10 @@ SimpleDatabase::Visit(const DatabaseSelection &selection,
|
|||||||
if (selection.recursive && visit_directory)
|
if (selection.recursive && visit_directory)
|
||||||
visit_directory(r.directory->Export());
|
visit_directory(r.directory->Export());
|
||||||
|
|
||||||
return r.directory->Walk(selection.recursive, selection.filter,
|
r.directory->Walk(selection.recursive, selection.filter,
|
||||||
visit_directory, visit_song,
|
visit_directory, visit_song,
|
||||||
visit_playlist,
|
visit_playlist);
|
||||||
error);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strchr(r.uri, '/') == nullptr) {
|
if (strchr(r.uri, '/') == nullptr) {
|
||||||
@ -298,22 +297,18 @@ SimpleDatabase::Visit(const DatabaseSelection &selection,
|
|||||||
"No such directory");
|
"No such directory");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
SimpleDatabase::VisitUniqueTags(const DatabaseSelection &selection,
|
SimpleDatabase::VisitUniqueTags(const DatabaseSelection &selection,
|
||||||
TagType tag_type, tag_mask_t group_mask,
|
TagType tag_type, tag_mask_t group_mask,
|
||||||
VisitTag visit_tag,
|
VisitTag visit_tag) const
|
||||||
Error &error) const
|
|
||||||
{
|
{
|
||||||
return ::VisitUniqueTags(*this, selection, tag_type, group_mask,
|
::VisitUniqueTags(*this, selection, tag_type, group_mask, visit_tag);
|
||||||
visit_tag,
|
|
||||||
error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
DatabaseStats
|
||||||
SimpleDatabase::GetStats(const DatabaseSelection &selection,
|
SimpleDatabase::GetStats(const DatabaseSelection &selection) const
|
||||||
DatabaseStats &stats, Error &error) const
|
|
||||||
{
|
{
|
||||||
return ::GetStats(*this, selection, stats, error);
|
return ::GetStats(*this, selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -112,20 +112,16 @@ public:
|
|||||||
const LightSong *GetSong(const char *uri_utf8) const override;
|
const LightSong *GetSong(const char *uri_utf8) const override;
|
||||||
void ReturnSong(const LightSong *song) const override;
|
void ReturnSong(const LightSong *song) const override;
|
||||||
|
|
||||||
virtual bool Visit(const DatabaseSelection &selection,
|
void Visit(const DatabaseSelection &selection,
|
||||||
VisitDirectory visit_directory,
|
VisitDirectory visit_directory,
|
||||||
VisitSong visit_song,
|
VisitSong visit_song,
|
||||||
VisitPlaylist visit_playlist,
|
VisitPlaylist visit_playlist) const override;
|
||||||
Error &error) const override;
|
|
||||||
|
|
||||||
virtual bool VisitUniqueTags(const DatabaseSelection &selection,
|
void VisitUniqueTags(const DatabaseSelection &selection,
|
||||||
TagType tag_type, tag_mask_t group_mask,
|
TagType tag_type, tag_mask_t group_mask,
|
||||||
VisitTag visit_tag,
|
VisitTag visit_tag) const override;
|
||||||
Error &error) const override;
|
|
||||||
|
|
||||||
virtual bool GetStats(const DatabaseSelection &selection,
|
DatabaseStats GetStats(const DatabaseSelection &selection) const override;
|
||||||
DatabaseStats &stats,
|
|
||||||
Error &error) const override;
|
|
||||||
|
|
||||||
virtual time_t GetUpdateStamp() const override {
|
virtual time_t GetUpdateStamp() const override {
|
||||||
return mtime;
|
return mtime;
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
#include "util/NumberParser.hxx"
|
#include "util/NumberParser.hxx"
|
||||||
#include "util/UriUtil.hxx"
|
#include "util/UriUtil.hxx"
|
||||||
#include "util/RuntimeError.hxx"
|
#include "util/RuntimeError.hxx"
|
||||||
#include "util/Error.hxx"
|
|
||||||
#include "util/ScopeExit.hxx"
|
#include "util/ScopeExit.hxx"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -35,8 +35,6 @@
|
|||||||
#include "config/Block.hxx"
|
#include "config/Block.hxx"
|
||||||
#include "tag/TagBuilder.hxx"
|
#include "tag/TagBuilder.hxx"
|
||||||
#include "tag/TagTable.hxx"
|
#include "tag/TagTable.hxx"
|
||||||
#include "util/Error.hxx"
|
|
||||||
#include "util/Domain.hxx"
|
|
||||||
#include "fs/Traits.hxx"
|
#include "fs/Traits.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
#include "SongFilter.hxx"
|
#include "SongFilter.hxx"
|
||||||
@ -84,20 +82,17 @@ public:
|
|||||||
virtual const LightSong *GetSong(const char *uri_utf8) const override;
|
virtual const LightSong *GetSong(const char *uri_utf8) const override;
|
||||||
void ReturnSong(const LightSong *song) const override;
|
void ReturnSong(const LightSong *song) const override;
|
||||||
|
|
||||||
virtual bool Visit(const DatabaseSelection &selection,
|
void Visit(const DatabaseSelection &selection,
|
||||||
VisitDirectory visit_directory,
|
VisitDirectory visit_directory,
|
||||||
VisitSong visit_song,
|
VisitSong visit_song,
|
||||||
VisitPlaylist visit_playlist,
|
VisitPlaylist visit_playlist) const override;
|
||||||
Error &error) const override;
|
|
||||||
|
|
||||||
virtual bool VisitUniqueTags(const DatabaseSelection &selection,
|
void VisitUniqueTags(const DatabaseSelection &selection,
|
||||||
TagType tag_type, tag_mask_t group_mask,
|
TagType tag_type, tag_mask_t group_mask,
|
||||||
VisitTag visit_tag,
|
VisitTag visit_tag) const override;
|
||||||
Error &error) const override;
|
|
||||||
|
DatabaseStats GetStats(const DatabaseSelection &selection) const override;
|
||||||
|
|
||||||
virtual bool GetStats(const DatabaseSelection &selection,
|
|
||||||
DatabaseStats &stats,
|
|
||||||
Error &error) const override;
|
|
||||||
time_t GetUpdateStamp() const override {
|
time_t GetUpdateStamp() const override {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -576,12 +571,11 @@ UpnpDatabase::VisitServer(const ContentDirectoryService &server,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Deal with the possibly multiple servers, call VisitServer if needed.
|
// Deal with the possibly multiple servers, call VisitServer if needed.
|
||||||
bool
|
void
|
||||||
UpnpDatabase::Visit(const DatabaseSelection &selection,
|
UpnpDatabase::Visit(const DatabaseSelection &selection,
|
||||||
VisitDirectory visit_directory,
|
VisitDirectory visit_directory,
|
||||||
VisitSong visit_song,
|
VisitSong visit_song,
|
||||||
VisitPlaylist visit_playlist,
|
VisitPlaylist visit_playlist) const
|
||||||
Error &) const
|
|
||||||
{
|
{
|
||||||
auto vpath = stringToTokens(selection.uri, "/", true);
|
auto vpath = stringToTokens(selection.uri, "/", true);
|
||||||
if (vpath.empty()) {
|
if (vpath.empty()) {
|
||||||
@ -597,7 +591,7 @@ UpnpDatabase::Visit(const DatabaseSelection &selection,
|
|||||||
visit_playlist);
|
visit_playlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We do have a path: the first element selects the server
|
// We do have a path: the first element selects the server
|
||||||
@ -607,19 +601,17 @@ UpnpDatabase::Visit(const DatabaseSelection &selection,
|
|||||||
auto server = discovery->GetServer(servername.c_str());
|
auto server = discovery->GetServer(servername.c_str());
|
||||||
VisitServer(server, vpath, selection,
|
VisitServer(server, vpath, selection,
|
||||||
visit_directory, visit_song, visit_playlist);
|
visit_directory, visit_song, visit_playlist);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
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) const
|
||||||
Error &) const
|
|
||||||
{
|
{
|
||||||
// TODO: use group_mask
|
// TODO: use group_mask
|
||||||
|
|
||||||
if (!visit_tag)
|
if (!visit_tag)
|
||||||
return true;
|
return;
|
||||||
|
|
||||||
std::set<std::string> values;
|
std::set<std::string> values;
|
||||||
for (auto& server : discovery->GetDirectories()) {
|
for (auto& server : discovery->GetDirectories()) {
|
||||||
@ -646,18 +638,16 @@ UpnpDatabase::VisitUniqueTags(const DatabaseSelection &selection,
|
|||||||
builder.AddItem(tag, value.c_str());
|
builder.AddItem(tag, value.c_str());
|
||||||
visit_tag(builder.Commit());
|
visit_tag(builder.Commit());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
DatabaseStats
|
||||||
UpnpDatabase::GetStats(const DatabaseSelection &,
|
UpnpDatabase::GetStats(const DatabaseSelection &) const
|
||||||
DatabaseStats &stats, Error &) const
|
|
||||||
{
|
{
|
||||||
/* Note: this gets called before the daemonizing so we can't
|
/* Note: this gets called before the daemonizing so we can't
|
||||||
reallyopen this would be a problem if we had real stats */
|
reallyopen this would be a problem if we had real stats */
|
||||||
|
DatabaseStats stats;
|
||||||
stats.Clear();
|
stats.Clear();
|
||||||
return true;
|
return stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DatabasePlugin upnp_db_plugin = {
|
const DatabasePlugin upnp_db_plugin = {
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
#include "fs/Path.hxx"
|
#include "fs/Path.hxx"
|
||||||
#include "event/Loop.hxx"
|
#include "event/Loop.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
#include "util/Error.hxx"
|
|
||||||
#include "util/ScopeExit.hxx"
|
#include "util/ScopeExit.hxx"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@ -108,7 +107,6 @@ try {
|
|||||||
config_global_init();
|
config_global_init();
|
||||||
AtScopeExit() { config_global_finish(); };
|
AtScopeExit() { config_global_finish(); };
|
||||||
|
|
||||||
Error error;
|
|
||||||
ReadConfigFile(config_path);
|
ReadConfigFile(config_path);
|
||||||
|
|
||||||
TagLoadConfig();
|
TagLoadConfig();
|
||||||
@ -133,11 +131,7 @@ try {
|
|||||||
|
|
||||||
const DatabaseSelection selection("", true);
|
const DatabaseSelection selection("", true);
|
||||||
|
|
||||||
if (!db->Visit(selection, DumpDirectory, DumpSong, DumpPlaylist,
|
db->Visit(selection, DumpDirectory, DumpSong, DumpPlaylist);
|
||||||
error)) {
|
|
||||||
cerr << error.GetMessage() << endl;
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
|
Loading…
Reference in New Issue
Block a user