Make the list of lyrics fetchers customizable
This commit is contained in:
1
NEWS
1
NEWS
@@ -6,6 +6,7 @@ ncmpcpp-0.8 (????-??-??)
|
||||
* Lyrics from files containing DOS line endings now load properly on Linux.
|
||||
* Added support for fetching lyrics from genius.com.
|
||||
* Added support for fetching lyrics from tekstowo.pl.
|
||||
* The list of lyrics fetchers can now be set via configuration file.
|
||||
|
||||
ncmpcpp-0.7.7 (2016-10-31)
|
||||
* Fixed compilation on 32bit platforms.
|
||||
|
||||
@@ -368,6 +368,8 @@
|
||||
#
|
||||
#lines_scrolled = 2
|
||||
#
|
||||
#lyrics_fetchers = lyricwiki, azlyrics, genius, sing365, lyricsmania, metrolyrics, justsomelyrics, tekstowo, internet
|
||||
#
|
||||
#follow_now_playing_lyrics = no
|
||||
#
|
||||
#fetch_lyrics_for_current_song_in_background = no
|
||||
|
||||
@@ -244,6 +244,9 @@ If enabled, cyclic scrolling is used (e.g. if you press down arrow being at the
|
||||
.B lines_scrolled = NUMBER
|
||||
Number of lines that are scrolled with mouse wheel.
|
||||
.TP
|
||||
.B lyrics_fetchers = FETCHERS
|
||||
Comma separated list of lyrics fetchers.
|
||||
.TP
|
||||
.B follow_now_playing_lyrics = yes/no
|
||||
If enabled, lyrics will be switched at song's change to currently playing one's (Note: this works only if you are viewing lyrics of item from Playlist).
|
||||
.TP
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -83,7 +83,7 @@ private:
|
||||
bool isDownloadInProgress;
|
||||
pthread_t itsDownloader;
|
||||
|
||||
static LyricsFetcher **itsFetcher;
|
||||
static LyricsFetcher *itsFetcher;
|
||||
# endif // HAVE_CURL_CURL_H
|
||||
|
||||
size_t itsScrollBegin;
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
));
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user