lyrics: add support for showing notifications about fetching lyrics in background
This commit is contained in:
@@ -317,6 +317,10 @@ void UpdateEnvironment::run(bool update_timer, bool refresh_window)
|
||||
// update timer, status if necessary etc.
|
||||
Status::trace(update_timer, true);
|
||||
|
||||
// show lyrics consumer notification if appropriate
|
||||
if (auto message = myLyrics->tryTakeConsumerMessage())
|
||||
Statusbar::print(*message);
|
||||
|
||||
// header stuff
|
||||
if ((myScreen == myPlaylist || myScreen == myBrowser || myScreen == myLyrics)
|
||||
&& (Timer - m_past > boost::posix_time::milliseconds(500))
|
||||
|
||||
@@ -190,7 +190,6 @@ Lyrics::Lyrics()
|
||||
, m_refresh_window(false)
|
||||
, m_scroll_begin(0)
|
||||
, m_fetcher(nullptr)
|
||||
, m_shared_queue(std::make_pair(false, std::queue<MPD::Song>{}))
|
||||
{ }
|
||||
|
||||
void Lyrics::resize()
|
||||
@@ -359,42 +358,62 @@ void Lyrics::toggleFetcher()
|
||||
Statusbar::print("Using all lyrics fetchers");
|
||||
}
|
||||
|
||||
void Lyrics::fetchInBackground(const MPD::Song &s)
|
||||
void Lyrics::fetchInBackground(const MPD::Song &s, bool notify_)
|
||||
{
|
||||
auto consumer = [this] {
|
||||
auto consumer_impl = [this] {
|
||||
std::string lyrics_file;
|
||||
while (true)
|
||||
{
|
||||
MPD::Song qs;
|
||||
ConsumerState::Song cs;
|
||||
{
|
||||
auto queue = m_shared_queue.acquire();
|
||||
assert(queue->first);
|
||||
if (queue->second.empty())
|
||||
auto consumer = m_consumer_state.acquire();
|
||||
assert(consumer->running);
|
||||
if (consumer->songs.empty())
|
||||
{
|
||||
queue->first = false;
|
||||
consumer->running = false;
|
||||
break;
|
||||
}
|
||||
lyrics_file = lyricsFilename(queue->second.front());
|
||||
lyrics_file = lyricsFilename(consumer->songs.front().song());
|
||||
if (!boost::filesystem::exists(lyrics_file))
|
||||
qs = queue->second.front();
|
||||
queue->second.pop();
|
||||
{
|
||||
cs = consumer->songs.front();
|
||||
if (cs.notify())
|
||||
{
|
||||
consumer->message = "Fetching lyrics for \""
|
||||
+ Format::stringify<char>(Config.song_status_format, &cs.song())
|
||||
+ "\"...";
|
||||
}
|
||||
}
|
||||
consumer->songs.pop();
|
||||
}
|
||||
if (!qs.empty())
|
||||
if (!cs.song().empty())
|
||||
{
|
||||
auto lyrics = downloadLyrics(qs, nullptr, m_fetcher);
|
||||
auto lyrics = downloadLyrics(cs.song(), nullptr, m_fetcher);
|
||||
if (lyrics)
|
||||
saveLyrics(lyrics_file, *lyrics);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto queue = m_shared_queue.acquire();
|
||||
queue->second.push(s);
|
||||
auto consumer = m_consumer_state.acquire();
|
||||
consumer->songs.emplace(s, notify_);
|
||||
// Start the consumer if it's not running.
|
||||
if (!queue->first)
|
||||
if (!consumer->running)
|
||||
{
|
||||
std::thread t(consumer);
|
||||
std::thread t(consumer_impl);
|
||||
t.detach();
|
||||
queue->first = true;
|
||||
consumer->running = true;
|
||||
}
|
||||
}
|
||||
|
||||
boost::optional<std::string> Lyrics::tryTakeConsumerMessage()
|
||||
{
|
||||
boost::optional<std::string> result;
|
||||
auto consumer = m_consumer_state.acquire();
|
||||
if (consumer->message)
|
||||
{
|
||||
result = std::move(consumer->message);
|
||||
consumer->message = boost::none;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
34
src/lyrics.h
34
src/lyrics.h
@@ -55,9 +55,39 @@ struct Lyrics: Screen<NC::Scrollpad>, Tabbable
|
||||
void edit();
|
||||
void toggleFetcher();
|
||||
|
||||
void fetchInBackground(const MPD::Song &s);
|
||||
void fetchInBackground(const MPD::Song &s, bool notify_);
|
||||
boost::optional<std::string> tryTakeConsumerMessage();
|
||||
|
||||
private:
|
||||
struct ConsumerState
|
||||
{
|
||||
struct Song
|
||||
{
|
||||
Song()
|
||||
: m_notify(false)
|
||||
{ }
|
||||
|
||||
Song(const MPD::Song &s, bool notify_)
|
||||
: m_song(s), m_notify(notify_)
|
||||
{ }
|
||||
|
||||
const MPD::Song &song() const { return m_song; }
|
||||
bool notify() const { return m_notify; }
|
||||
|
||||
private:
|
||||
MPD::Song m_song;
|
||||
bool m_notify;
|
||||
};
|
||||
|
||||
ConsumerState()
|
||||
: running(false)
|
||||
{ }
|
||||
|
||||
bool running;
|
||||
std::queue<Song> songs;
|
||||
boost::optional<std::string> message;
|
||||
};
|
||||
|
||||
bool m_refresh_window;
|
||||
size_t m_scroll_begin;
|
||||
|
||||
@@ -67,7 +97,7 @@ private:
|
||||
LyricsFetcher *m_fetcher;
|
||||
std::future<boost::optional<std::string>> m_worker;
|
||||
|
||||
Shared<std::pair<bool, std::queue<MPD::Song>>> m_shared_queue;
|
||||
Shared<ConsumerState> m_consumer_state;
|
||||
};
|
||||
|
||||
extern Lyrics *myLyrics;
|
||||
|
||||
@@ -573,7 +573,7 @@ void Status::Changes::songID(int song_id)
|
||||
res = system(Config.execute_on_song_change.c_str());
|
||||
|
||||
if (Config.fetch_lyrics_in_background)
|
||||
myLyrics->fetchInBackground(s);
|
||||
myLyrics->fetchInBackground(s, false);
|
||||
|
||||
drawTitle(s);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user