Make the list of lyrics fetchers customizable

This commit is contained in:
Andrzej Rybczak
2016-11-16 09:12:06 +01:00
parent b833818023
commit a2862b9fdf
9 changed files with 120 additions and 49 deletions

View File

@@ -43,7 +43,7 @@ using Global::MainHeight;
using Global::MainStartY;
#ifdef HAVE_CURL_CURL_H
LyricsFetcher **Lyrics::itsFetcher = 0;
LyricsFetcher *Lyrics::itsFetcher = nullptr;
std::queue<MPD::Song *> Lyrics::itsToDownload;
pthread_mutex_t Lyrics::itsDIBLock = PTHREAD_MUTEX_INITIALIZER;
size_t Lyrics::itsWorkersNumber = 0;
@@ -207,16 +207,20 @@ void Lyrics::DownloadInBackgroundImplHelper(const MPD::Song &s)
std::string title = Curl::escape(s.getTitle());
LyricsFetcher::Result result;
bool fetcher_defined = itsFetcher && *itsFetcher;
for (LyricsFetcher **plugin = fetcher_defined ? itsFetcher : lyricsPlugins; *plugin != 0; ++plugin)
if (itsFetcher == nullptr)
{
result = (*plugin)->fetch(artist, title);
if (result.first)
break;
if (fetcher_defined)
break;
for (auto &fetcher : Config.lyrics_fetchers)
{
result = fetcher->fetch(artist, title);
if (result.first)
break;
}
}
if (result.first == true)
else
itsFetcher->fetch(artist, title);
if (result.first)
Save(GenerateFilename(s), result.second);
}
@@ -224,25 +228,38 @@ void *Lyrics::Download()
{
std::string artist = Curl::escape(itsSong.getArtist());
std::string title_ = Curl::escape(itsSong.getTitle());
LyricsFetcher::Result result;
// if one of plugins is selected, try only this one,
// otherwise try all of them until one of them succeeds
bool fetcher_defined = itsFetcher && *itsFetcher;
for (LyricsFetcher **plugin = fetcher_defined ? itsFetcher : lyricsPlugins; *plugin != 0; ++plugin)
{
w << "Fetching lyrics from " << NC::Format::Bold << (*plugin)->name() << NC::Format::NoBold << "... ";
result = (*plugin)->fetch(artist, title_);
auto fetch_lyrics = [&](auto &fetcher) {
w << "Fetching lyrics from "
<< NC::Format::Bold
<< fetcher->name()
<< NC::Format::NoBold << "... ";
auto result = fetcher->fetch(artist, title_);
if (result.first == false)
w << NC::Color::Red << result.second << NC::Color::End << '\n';
else
break;
if (fetcher_defined)
break;
{
w << NC::Color::Red
<< result.second
<< NC::Color::End
<< '\n';
}
return result;
};
LyricsFetcher::Result result;
if (itsFetcher == nullptr)
{
for (auto &fetcher : Config.lyrics_fetchers)
{
result = fetch_lyrics(fetcher);
if (result.first)
break;
}
}
if (result.first == true)
else
result = fetch_lyrics(itsFetcher);
if (result.first)
{
Save(itsFilename, result.second);
w.clear();
@@ -401,14 +418,28 @@ void Lyrics::Refetch()
void Lyrics::ToggleFetcher()
{
if (itsFetcher && *itsFetcher)
++itsFetcher;
if (itsFetcher != nullptr)
{
auto fetcher = std::find_if(Config.lyrics_fetchers.begin(),
Config.lyrics_fetchers.end(),
[](auto &f) { return f.get() == itsFetcher; });
assert(fetcher != Config.lyrics_fetchers.end());
++fetcher;
if (fetcher != Config.lyrics_fetchers.end())
itsFetcher = fetcher->get();
else
itsFetcher = nullptr;
}
else
itsFetcher = &lyricsPlugins[0];
if (*itsFetcher)
Statusbar::printf("Using lyrics database: %s", (*itsFetcher)->name());
{
assert(!Config.lyrics_fetchers.empty());
itsFetcher = Config.lyrics_fetchers[0].get();
}
if (itsFetcher != nullptr)
Statusbar::printf("Using lyrics fetcher: %s", itsFetcher->name());
else
Statusbar::print("Using all lyrics databases");
Statusbar::print("Using all lyrics fetchers");
}
void Lyrics::Take()

View File

@@ -83,7 +83,7 @@ private:
bool isDownloadInProgress;
pthread_t itsDownloader;
static LyricsFetcher **itsFetcher;
static LyricsFetcher *itsFetcher;
# endif // HAVE_CURL_CURL_H
size_t itsScrollBegin;

View File

@@ -36,19 +36,28 @@
#include "utility/html.h"
#include "utility/string.h"
LyricsFetcher *lyricsPlugins[] =
std::unique_ptr<LyricsFetcher> toLyricsFetcher(const std::string &s)
{
new LyricwikiFetcher(),
new GeniusLyricsFetcher(),
new AzLyricsFetcher(),
new Sing365Fetcher(),
new LyricsmaniaFetcher(),
new MetrolyricsFetcher(),
new JustSomeLyricsFetcher(),
new TekstowoLyricsFetcher(),
new InternetLyricsFetcher(),
0
};
if (s == "lyricwiki")
return std::make_unique<LyricwikiFetcher>();
else if (s == "azlyrics")
return std::make_unique<AzLyricsFetcher>();
else if (s == "genius")
return std::make_unique<GeniusFetcher>();
else if (s == "sing365")
return std::make_unique<Sing365Fetcher>();
else if (s == "lyricsmania")
return std::make_unique<LyricsmaniaFetcher>();
else if (s == "metrolyrics")
return std::make_unique<MetrolyricsFetcher>();
else if (s == "justsomelyrics")
return std::make_unique<JustSomeLyricsFetcher>();
else if (s == "tekstowo")
return std::make_unique<TekstowoFetcher>();
else if (s == "internet")
return std::make_unique<InternetLyricsFetcher>();
throw std::runtime_error("no lyrics fetcher named '" + s + "'");
}
const char LyricsFetcher::msgNotFound[] = "Not found";

View File

@@ -25,6 +25,7 @@
#ifdef HAVE_CURL_CURL_H
#include <memory>
#include <string>
struct LyricsFetcher
@@ -46,6 +47,12 @@ protected:
static const char msgNotFound[];
};
typedef std::vector<std::unique_ptr<LyricsFetcher>> LyricsFetchers;
std::unique_ptr<LyricsFetcher> toLyricsFetcher(const std::string &s);
/**********************************************************************/
struct LyricwikiFetcher : public LyricsFetcher
{
virtual const char *name() const override { return "lyricwiki.com"; }
@@ -116,7 +123,7 @@ protected:
virtual const char *regex() const override { return "<div class=\"lyricsh\">.*?</h2>.*<div>(.*?)</div>"; }
};
struct GeniusLyricsFetcher : public GoogleLyricsFetcher
struct GeniusFetcher : public GoogleLyricsFetcher
{
virtual const char *name() const override { return "genius.com"; }
@@ -124,7 +131,7 @@ protected:
virtual const char *regex() const override { return "<lyrics.*?>(.*?)</lyrics>"; }
};
struct TekstowoLyricsFetcher : public GoogleLyricsFetcher
struct TekstowoFetcher : public GoogleLyricsFetcher
{
virtual const char *name() const override { return "tekstowo.pl"; }
@@ -147,8 +154,6 @@ private:
std::string URL;
};
extern LyricsFetcher *lyricsPlugins[];
#endif // HAVE_CURL_CURL_H
#endif // NCMPCPP_LYRICS_FETCHER_H

View File

@@ -503,6 +503,23 @@ bool Configuration::read(const std::vector<std::string> &config_paths, bool igno
p.add("lines_scrolled", assign_default(
lines_scrolled, 2
));
p.add("lyrics_fetchers", option_parser::worker([this](std::string v) {
boost::sregex_token_iterator fetcher(v.begin(), v.end(), boost::regex("\\w+")), end;
for (; fetcher != end; ++fetcher)
lyrics_fetchers.push_back(toLyricsFetcher(*fetcher));
if (lyrics_fetchers.empty())
throw std::runtime_error("empty list");
}, [this] {
lyrics_fetchers.push_back(std::make_unique<LyricwikiFetcher>());
lyrics_fetchers.push_back(std::make_unique<AzLyricsFetcher>());
lyrics_fetchers.push_back(std::make_unique<GeniusFetcher>());
lyrics_fetchers.push_back(std::make_unique<Sing365Fetcher>());
lyrics_fetchers.push_back(std::make_unique<LyricsmaniaFetcher>());
lyrics_fetchers.push_back(std::make_unique<MetrolyricsFetcher>());
lyrics_fetchers.push_back(std::make_unique<JustSomeLyricsFetcher>());
lyrics_fetchers.push_back(std::make_unique<TekstowoFetcher>());
lyrics_fetchers.push_back(std::make_unique<InternetLyricsFetcher>());
}));
p.add("follow_now_playing_lyrics", yes_no(
now_playing_lyrics, false
));

View File

@@ -30,6 +30,7 @@
#include "enums.h"
#include "format.h"
#include "lyrics_fetcher.h"
#include "screen_type.h"
#include "strbuffer.h"
@@ -195,6 +196,8 @@ struct Configuration
std::list<ScreenType> screen_sequence;
SortMode browser_sort_mode;
LyricsFetchers lyrics_fetchers;
};
extern Configuration Config;