mpd: replace all consumers with iterators

This commit is contained in:
Andrzej Rybczak
2014-11-03 00:43:47 +01:00
parent e5b0c7a357
commit 202a21c4b3
7 changed files with 141 additions and 172 deletions

View File

@@ -558,9 +558,9 @@ void Browser::remove(const MPD::Item &item)
void Browser::fetchSupportedExtensions() void Browser::fetchSupportedExtensions()
{ {
lm_supported_extensions.clear(); lm_supported_extensions.clear();
Mpd.GetSupportedExtensions([&](std::string extension) { MPD::StringIterator extension = Mpd.GetSupportedExtensions(), end;
lm_supported_extensions.insert("." + std::move(extension)); for (; extension != end; ++extension)
}); lm_supported_extensions.insert("." + std::move(*extension));
} }
/***********************************************************************/ /***********************************************************************/

View File

@@ -321,9 +321,9 @@ void MediaLibrary::update()
} }
else else
{ {
Mpd.GetList(Config.media_lib_primary_tag, [&tags](std::string tag) { MPD::StringIterator tag = Mpd.GetList(Config.media_lib_primary_tag), end;
tags[tag] = 0; for (; tag != end; ++tag)
}); tags[std::move(*tag)] = 0;
} }
withUnfilteredMenuReapplyFilter(Tags, [this, &tags]() { withUnfilteredMenuReapplyFilter(Tags, [this, &tags]() {
size_t idx = 0; size_t idx = 0;

View File

@@ -31,16 +31,20 @@ MPD::Connection Mpd;
namespace { namespace {
bool fetchItem(MPD::ItemIterator::State &state) template <typename ObjectT, typename SourceT>
std::function<bool(typename MPD::Iterator<ObjectT>::State &)>
defaultFetcher(SourceT *(fetcher)(mpd_connection *))
{ {
auto src = mpd_recv_entity(state.connection()); return [fetcher](typename MPD::Iterator<ObjectT>::State &state) {
if (src != nullptr) auto src = fetcher(state.connection());
{ if (src != nullptr)
state.setObject(src); {
return true; state.setObject(src);
} return true;
else }
return false; else
return false;
};
} }
bool fetchItemSong(MPD::SongIterator::State &state) bool fetchItemSong(MPD::SongIterator::State &state)
@@ -61,42 +65,6 @@ bool fetchItemSong(MPD::SongIterator::State &state)
return false; return false;
} }
bool fetchPlaylist(MPD::PlaylistIterator::State &state)
{
auto src = mpd_recv_playlist(state.connection());
if (src != nullptr)
{
state.setObject(src);
return true;
}
else
return false;
}
bool fetchSong(MPD::SongIterator::State &state)
{
auto src = mpd_recv_song(state.connection());
if (src != nullptr)
{
state.setObject(src);
return true;
}
else
return false;
}
bool fetchOutput(MPD::OutputIterator::State &state)
{
auto src = mpd_recv_output(state.connection());
if (src != nullptr)
{
state.setObject(src);
return true;
}
else
return false;
}
} }
namespace MPD { namespace MPD {
@@ -365,7 +333,7 @@ SongIterator Connection::GetPlaylistChanges(unsigned version)
prechecksNoCommandsList(); prechecksNoCommandsList();
mpd_send_queue_changes_meta(m_connection.get(), version); mpd_send_queue_changes_meta(m_connection.get(), version);
checkErrors(); checkErrors();
return SongIterator(m_connection.get(), fetchSong); return SongIterator(m_connection.get(), defaultFetcher<Song>(mpd_recv_song));
} }
Song Connection::GetCurrentSong() Song Connection::GetCurrentSong()
@@ -392,7 +360,7 @@ SongIterator Connection::GetPlaylistContent(const std::string &path)
{ {
prechecksNoCommandsList(); prechecksNoCommandsList();
mpd_send_list_playlist_meta(m_connection.get(), path.c_str()); mpd_send_list_playlist_meta(m_connection.get(), path.c_str());
SongIterator result(m_connection.get(), fetchSong); SongIterator result(m_connection.get(), defaultFetcher<Song>(mpd_recv_song));
checkErrors(); checkErrors();
return result; return result;
} }
@@ -401,22 +369,27 @@ SongIterator Connection::GetPlaylistContentNoInfo(const std::string &path)
{ {
prechecksNoCommandsList(); prechecksNoCommandsList();
mpd_send_list_playlist(m_connection.get(), path.c_str()); mpd_send_list_playlist(m_connection.get(), path.c_str());
SongIterator result(m_connection.get(), fetchSong); SongIterator result(m_connection.get(), defaultFetcher<Song>(mpd_recv_song));
checkErrors(); checkErrors();
return result; return result;
} }
void Connection::GetSupportedExtensions(StringConsumer f) StringIterator Connection::GetSupportedExtensions()
{ {
prechecksNoCommandsList(); prechecksNoCommandsList();
mpd_send_command(m_connection.get(), "decoders", NULL); mpd_send_command(m_connection.get(), "decoders", NULL);
while (mpd_pair *pair = mpd_recv_pair_named(m_connection.get(), "suffix"))
{
f(pair->value);
mpd_return_pair(m_connection.get(), pair);
}
mpd_response_finish(m_connection.get());
checkErrors(); checkErrors();
return StringIterator(m_connection.get(), [](StringIterator::State &state) {
auto src = mpd_recv_pair_named(state.connection(), "suffix");
if (src != nullptr)
{
state.setObject(src->value);
mpd_return_pair(state.connection(), src);
return true;
}
else
return false;
});
} }
void Connection::SetRepeat(bool mode) void Connection::SetRepeat(bool mode)
@@ -550,33 +523,27 @@ void Connection::Add(const std::string &path)
bool Connection::AddRandomTag(mpd_tag_type tag, size_t number) bool Connection::AddRandomTag(mpd_tag_type tag, size_t number)
{ {
StringList tags; std::vector<std::string> tags(
GetList(tag, [&tags](std::string tag_name) { std::make_move_iterator(GetList(tag)),
tags.push_back(tag_name); std::make_move_iterator(StringIterator())
}); );
if (number > tags.size()) if (number > tags.size())
{
//if (itsErrorHandler)
// itsErrorHandler(this, 0, "Requested number is out of range", itsErrorHandlerUserdata);
return false; return false;
}
else std::random_shuffle(tags.begin(), tags.end());
auto it = tags.begin()+rand()%(tags.size()-number);
for (size_t i = 0; i < number && it != tags.end(); ++i)
{ {
std::random_shuffle(tags.begin(), tags.end()); StartSearch(true);
auto it = tags.begin()+rand()%(tags.size()-number); AddSearch(tag, *it++);
for (size_t i = 0; i < number && it != tags.end(); ++i) std::vector<std::string> paths;
{ MPD::SongIterator s = CommitSearchSongs(), end;
StartSearch(true); for (; s != end; ++s)
AddSearch(tag, *it++); paths.push_back(s->getURI());
std::vector<std::string> paths; StartCommandsList();
MPD::SongIterator s = CommitSearchSongs(), end; for (const auto &path : paths)
for (; s != end; ++s) AddSong(path);
paths.push_back(s->getURI()); CommitCommandsList();
StartCommandsList();
for (const auto &path : paths)
AddSong(path);
CommitCommandsList();
}
} }
return true; return true;
} }
@@ -679,21 +646,26 @@ PlaylistIterator Connection::GetPlaylists()
prechecksNoCommandsList(); prechecksNoCommandsList();
mpd_send_list_playlists(m_connection.get()); mpd_send_list_playlists(m_connection.get());
checkErrors(); checkErrors();
return PlaylistIterator(m_connection.get(), fetchPlaylist); return PlaylistIterator(m_connection.get(), defaultFetcher<Playlist>(mpd_recv_playlist));
} }
void Connection::GetList(mpd_tag_type type, StringConsumer f) StringIterator Connection::GetList(mpd_tag_type type)
{ {
prechecksNoCommandsList(); prechecksNoCommandsList();
mpd_search_db_tags(m_connection.get(), type); mpd_search_db_tags(m_connection.get(), type);
mpd_search_commit(m_connection.get()); mpd_search_commit(m_connection.get());
while (mpd_pair *item = mpd_recv_pair_tag(m_connection.get(), type))
{
f(std::string(item->value));
mpd_return_pair(m_connection.get(), item);
}
mpd_response_finish(m_connection.get());
checkErrors(); checkErrors();
return StringIterator(m_connection.get(), [type](StringIterator::State &state) {
auto src = mpd_recv_pair_tag(state.connection(), type);
if (src != nullptr)
{
state.setObject(src->value);
mpd_return_pair(state.connection(), src);
return true;
}
else
return false;
});
} }
void Connection::StartSearch(bool exact_match) void Connection::StartSearch(bool exact_match)
@@ -731,20 +703,7 @@ SongIterator Connection::CommitSearchSongs()
prechecksNoCommandsList(); prechecksNoCommandsList();
mpd_search_commit(m_connection.get()); mpd_search_commit(m_connection.get());
checkErrors(); checkErrors();
return SongIterator(m_connection.get(), fetchSong); return SongIterator(m_connection.get(), defaultFetcher<Song>(mpd_recv_song));
}
void Connection::CommitSearchTags(StringConsumer f)
{
prechecksNoCommandsList();
mpd_search_commit(m_connection.get());
while (mpd_pair *tag = mpd_recv_pair_tag(m_connection.get(), m_searched_field))
{
f(std::string(tag->value));
mpd_return_pair(m_connection.get(), tag);
}
mpd_response_finish(m_connection.get());
checkErrors();
} }
ItemIterator Connection::GetDirectory(const std::string &directory) ItemIterator Connection::GetDirectory(const std::string &directory)
@@ -752,7 +711,7 @@ ItemIterator Connection::GetDirectory(const std::string &directory)
prechecksNoCommandsList(); prechecksNoCommandsList();
mpd_send_list_meta(m_connection.get(), directory.c_str()); mpd_send_list_meta(m_connection.get(), directory.c_str());
checkErrors(); checkErrors();
return ItemIterator(m_connection.get(), fetchItem); return ItemIterator(m_connection.get(), defaultFetcher<Item>(mpd_recv_entity));
} }
SongIterator Connection::GetDirectoryRecursive(const std::string &directory) SongIterator Connection::GetDirectoryRecursive(const std::string &directory)
@@ -763,17 +722,12 @@ SongIterator Connection::GetDirectoryRecursive(const std::string &directory)
return SongIterator(m_connection.get(), fetchItemSong); return SongIterator(m_connection.get(), fetchItemSong);
} }
void Connection::GetDirectories(const std::string &directory, StringConsumer f) DirectoryIterator Connection::GetDirectories(const std::string &directory)
{ {
prechecksNoCommandsList(); prechecksNoCommandsList();
mpd_send_list_meta(m_connection.get(), directory.c_str()); mpd_send_list_meta(m_connection.get(), directory.c_str());
while (mpd_directory *dir = mpd_recv_directory(m_connection.get()))
{
f(std::string(mpd_directory_get_path(dir)));
mpd_directory_free(dir);
}
mpd_response_finish(m_connection.get());
checkErrors(); checkErrors();
return DirectoryIterator(m_connection.get(), defaultFetcher<Directory>(mpd_recv_directory));
} }
SongIterator Connection::GetSongs(const std::string &directory) SongIterator Connection::GetSongs(const std::string &directory)
@@ -781,7 +735,7 @@ SongIterator Connection::GetSongs(const std::string &directory)
prechecksNoCommandsList(); prechecksNoCommandsList();
mpd_send_list_meta(m_connection.get(), directory.c_str()); mpd_send_list_meta(m_connection.get(), directory.c_str());
checkErrors(); checkErrors();
return SongIterator(m_connection.get(), fetchSong); return SongIterator(m_connection.get(), defaultFetcher<Song>(mpd_recv_song));
} }
OutputIterator Connection::GetOutputs() OutputIterator Connection::GetOutputs()
@@ -789,7 +743,7 @@ OutputIterator Connection::GetOutputs()
prechecksNoCommandsList(); prechecksNoCommandsList();
mpd_send_outputs(m_connection.get()); mpd_send_outputs(m_connection.get());
checkErrors(); checkErrors();
return OutputIterator(m_connection.get(), fetchOutput); return OutputIterator(m_connection.get(), defaultFetcher<Output>(mpd_recv_output));
} }
void Connection::EnableOutput(int id) void Connection::EnableOutput(int id)
@@ -806,31 +760,41 @@ void Connection::DisableOutput(int id)
checkErrors(); checkErrors();
} }
void Connection::GetURLHandlers(StringConsumer f) StringIterator Connection::GetURLHandlers()
{ {
prechecksNoCommandsList(); prechecksNoCommandsList();
mpd_send_list_url_schemes(m_connection.get()); mpd_send_list_url_schemes(m_connection.get());
while (mpd_pair *handler = mpd_recv_pair_named(m_connection.get(), "handler"))
{
f(std::string(handler->value));
mpd_return_pair(m_connection.get(), handler);
}
mpd_response_finish(m_connection.get());
checkErrors(); checkErrors();
return StringIterator(m_connection.get(), [](StringIterator::State &state) {
auto src = mpd_recv_pair_named(state.connection(), "handler");
if (src != nullptr)
{
state.setObject(src->value);
mpd_return_pair(state.connection(), src);
return true;
}
else
return false;
});
} }
void Connection::GetTagTypes(StringConsumer f) StringIterator Connection::GetTagTypes()
{ {
prechecksNoCommandsList(); prechecksNoCommandsList();
mpd_send_list_tag_types(m_connection.get()); mpd_send_list_tag_types(m_connection.get());
while (mpd_pair *tag_type = mpd_recv_pair_named(m_connection.get(), "tagtype"))
{
f(std::string(tag_type->value));
mpd_return_pair(m_connection.get(), tag_type);
}
mpd_response_finish(m_connection.get());
checkErrors(); checkErrors();
return StringIterator(m_connection.get(), [](StringIterator::State &state) {
auto src = mpd_recv_pair_named(state.connection(), "tagtype");
if (src != nullptr)
{
state.setObject(src->value);
mpd_return_pair(state.connection(), src);
return true;
}
else
return false;
});
} }
void Connection::checkConnection() const void Connection::checkConnection() const

View File

@@ -68,7 +68,7 @@ private:
struct Statistics struct Statistics
{ {
friend class Connection; friend struct Connection;
bool empty() const { return m_stats.get() == nullptr; } bool empty() const { return m_stats.get() == nullptr; }
@@ -88,7 +88,7 @@ private:
struct Status struct Status
{ {
friend class Connection; friend struct Connection;
Status() { } Status() { }
@@ -337,7 +337,7 @@ struct Iterator: std::iterator<std::input_iterator_tag, ObjectT>
{ {
friend Iterator; friend Iterator;
typedef bool (*Fetcher)(State &); typedef std::function<bool(State &)> Fetcher;
State(mpd_connection *connection, Fetcher fetcher) State(mpd_connection *connection, Fetcher fetcher)
: m_connection(connection) : m_connection(connection)
@@ -448,16 +448,15 @@ private:
std::shared_ptr<State> m_state; std::shared_ptr<State> m_state;
}; };
typedef Iterator<Directory> DirectoryIterator;
typedef Iterator<Item> ItemIterator; typedef Iterator<Item> ItemIterator;
typedef Iterator<Output> OutputIterator; typedef Iterator<Output> OutputIterator;
typedef Iterator<Playlist> PlaylistIterator; typedef Iterator<Playlist> PlaylistIterator;
typedef Iterator<Song> SongIterator; typedef Iterator<Song> SongIterator;
typedef Iterator<std::string> StringIterator;
class Connection struct Connection
{ {
typedef std::function<void(std::string)> StringConsumer;
public:
Connection(); Connection();
void Connect(); void Connect();
@@ -503,7 +502,7 @@ public:
SongIterator GetPlaylistContent(const std::string &name); SongIterator GetPlaylistContent(const std::string &name);
SongIterator GetPlaylistContentNoInfo(const std::string &name); SongIterator GetPlaylistContentNoInfo(const std::string &name);
void GetSupportedExtensions(StringConsumer f); StringIterator GetSupportedExtensions();
void SetRepeat(bool); void SetRepeat(bool);
void SetRandom(bool); void SetRandom(bool);
@@ -542,21 +541,20 @@ public:
void AddSearchAny(const std::string &str) const; void AddSearchAny(const std::string &str) const;
void AddSearchURI(const std::string &str) const; void AddSearchURI(const std::string &str) const;
SongIterator CommitSearchSongs(); SongIterator CommitSearchSongs();
void CommitSearchTags(StringConsumer f);
PlaylistIterator GetPlaylists(); PlaylistIterator GetPlaylists();
void GetList(mpd_tag_type type, StringConsumer f); StringIterator GetList(mpd_tag_type type);
ItemIterator GetDirectory(const std::string &directory); ItemIterator GetDirectory(const std::string &directory);
SongIterator GetDirectoryRecursive(const std::string &directory); SongIterator GetDirectoryRecursive(const std::string &directory);
SongIterator GetSongs(const std::string &directory); SongIterator GetSongs(const std::string &directory);
void GetDirectories(const std::string &directory, StringConsumer f); DirectoryIterator GetDirectories(const std::string &directory);
OutputIterator GetOutputs(); OutputIterator GetOutputs();
void EnableOutput(int id); void EnableOutput(int id);
void DisableOutput(int id); void DisableOutput(int id);
void GetURLHandlers(StringConsumer f); StringIterator GetURLHandlers();
void GetTagTypes(StringConsumer f); StringIterator GetTagTypes();
void idle(); void idle();
int noidle(); int noidle();
@@ -583,8 +581,6 @@ private:
int m_port; int m_port;
int m_timeout; int m_timeout;
std::string m_password; std::string m_password;
mpd_tag_type m_searched_field;
}; };
} }

View File

@@ -36,7 +36,7 @@ ServerInfo::ServerInfo()
: m_timer(boost::posix_time::from_time_t(0)) : m_timer(boost::posix_time::from_time_t(0))
{ {
SetDimensions(); SetDimensions();
w = NC::Scrollpad((COLS-itsWidth)/2, (MainHeight-itsHeight)/2+MainStartY, itsWidth, itsHeight, "MPD server info", Config.main_color, Config.window_border); w = NC::Scrollpad((COLS-m_width)/2, (MainHeight-m_height)/2+MainStartY, m_width, m_height, "MPD server info", Config.main_color, Config.window_border);
} }
void ServerInfo::switchTo() void ServerInfo::switchTo()
@@ -46,11 +46,19 @@ void ServerInfo::switchTo()
{ {
SwitchTo::execute(this); SwitchTo::execute(this);
itsURLHandlers.clear(); m_url_handlers.clear();
itsTagTypes.clear(); std::copy(
std::make_move_iterator(Mpd.GetURLHandlers()),
std::make_move_iterator(MPD::StringIterator()),
std::back_inserter(m_url_handlers)
);
Mpd.GetURLHandlers(vectorMoveInserter(itsURLHandlers)); m_tag_types.clear();
Mpd.GetTagTypes(vectorMoveInserter(itsTagTypes)); std::copy(
std::make_move_iterator(Mpd.GetTagTypes()),
std::make_move_iterator(MPD::StringIterator()),
std::back_inserter(m_tag_types)
);
} }
else else
switchToPreviousScreen(); switchToPreviousScreen();
@@ -59,8 +67,8 @@ void ServerInfo::switchTo()
void ServerInfo::resize() void ServerInfo::resize()
{ {
SetDimensions(); SetDimensions();
w.resize(itsWidth, itsHeight); w.resize(m_width, m_height);
w.moveTo((COLS-itsWidth)/2, (MainHeight-itsHeight)/2+MainStartY); w.moveTo((COLS-m_width)/2, (MainHeight-m_height)/2+MainStartY);
if (previousScreen() && previousScreen()->hasToBeResized) // resize background window if (previousScreen() && previousScreen()->hasToBeResized) // resize background window
{ {
previousScreen()->resize(); previousScreen()->resize();
@@ -102,12 +110,12 @@ void ServerInfo::update()
w << NC::Format::Bold << "Last DB update: " << NC::Format::NoBold << Timestamp(stats.dbUpdateTime()) << '\n'; w << NC::Format::Bold << "Last DB update: " << NC::Format::NoBold << Timestamp(stats.dbUpdateTime()) << '\n';
w << '\n'; w << '\n';
w << NC::Format::Bold << "URL Handlers:" << NC::Format::NoBold; w << NC::Format::Bold << "URL Handlers:" << NC::Format::NoBold;
for (auto it = itsURLHandlers.begin(); it != itsURLHandlers.end(); ++it) for (auto it = m_url_handlers.begin(); it != m_url_handlers.end(); ++it)
w << (it != itsURLHandlers.begin() ? ", " : " ") << *it; w << (it != m_url_handlers.begin() ? ", " : " ") << *it;
w << "\n\n"; w << "\n\n";
w << NC::Format::Bold << "Tag Types:" << NC::Format::NoBold; w << NC::Format::Bold << "Tag Types:" << NC::Format::NoBold;
for (auto it = itsTagTypes.begin(); it != itsTagTypes.end(); ++it) for (auto it = m_tag_types.begin(); it != m_tag_types.end(); ++it)
w << (it != itsTagTypes.begin() ? ", " : " ") << *it; w << (it != m_tag_types.begin() ? ", " : " ") << *it;
w.flush(); w.flush();
w.refresh(); w.refresh();
@@ -115,7 +123,7 @@ void ServerInfo::update()
void ServerInfo::SetDimensions() void ServerInfo::SetDimensions()
{ {
itsWidth = COLS*0.6; m_width = COLS*0.6;
itsHeight = std::min(size_t(LINES*0.7), MainHeight); m_height = std::min(size_t(LINES*0.7), MainHeight);
} }

View File

@@ -52,11 +52,11 @@ private:
boost::posix_time::ptime m_timer; boost::posix_time::ptime m_timer;
MPD::StringList itsURLHandlers; std::vector<std::string> m_url_handlers;
MPD::StringList itsTagTypes; std::vector<std::string> m_tag_types;
size_t itsWidth; size_t m_width;
size_t itsHeight; size_t m_height;
}; };
extern ServerInfo *myServerInfo; extern ServerInfo *myServerInfo;

View File

@@ -239,11 +239,13 @@ void TagEditor::update()
Dirs->addItem(std::make_pair("..", getParentDirectory(itsBrowsedDir))); Dirs->addItem(std::make_pair("..", getParentDirectory(itsBrowsedDir)));
else else
Dirs->addItem(std::make_pair(".", "/")); Dirs->addItem(std::make_pair(".", "/"));
Mpd.GetDirectories(itsBrowsedDir, [this](std::string directory) { MPD::DirectoryIterator directory = Mpd.GetDirectories(itsBrowsedDir), end;
Dirs->addItem(std::make_pair(getBasename(directory), directory)); for (; directory != end; ++directory)
if (directory == itsHighlightedDir) {
Dirs->addItem(std::make_pair(getBasename(directory->path()), directory->path()));
if (directory->path() == itsHighlightedDir)
Dirs->highlight(Dirs->size()-1); Dirs->highlight(Dirs->size()-1);
}); };
std::sort(Dirs->beginV()+1, Dirs->endV(), std::sort(Dirs->beginV()+1, Dirs->endV(),
LocaleBasedSorting(std::locale(), Config.ignore_leading_the)); LocaleBasedSorting(std::locale(), Config.ignore_leading_the));
Dirs->display(); Dirs->display();
@@ -277,10 +279,9 @@ void TagEditor::enterPressed()
if (w == Dirs) if (w == Dirs)
{ {
bool has_subdirs = false; MPD::DirectoryIterator directory = Mpd.GetDirectories(Dirs->current().value().second), end;
Mpd.GetDirectories(Dirs->current().value().second, [&has_subdirs](std::string) { bool has_subdirs = directory != end;
has_subdirs = true; directory.finish();
});
if (has_subdirs) if (has_subdirs)
{ {
itsHighlightedDir = itsBrowsedDir; itsHighlightedDir = itsBrowsedDir;