From daad444f3c183a7388d5285d5a7fa6cd5133d84e Mon Sep 17 00:00:00 2001 From: Andrzej Rybczak Date: Mon, 9 Aug 2010 11:39:41 +0200 Subject: [PATCH] lyrics: redesigned plugins system --- doc/config | 10 --- doc/ncmpcpp.1 | 4 -- src/Makefile.am | 16 ++--- src/curl_handle.cpp | 2 +- src/curl_handle.h | 2 +- src/lyrics.cpp | 160 +++++++++-------------------------------- src/lyrics.h | 22 ------ src/lyrics_fetcher.cpp | 93 ++++++++++++++++++++++++ src/lyrics_fetcher.h | 74 +++++++++++++++++++ src/ncmpcpp.cpp | 11 --- src/settings.cpp | 10 --- 11 files changed, 209 insertions(+), 195 deletions(-) create mode 100644 src/lyrics_fetcher.cpp create mode 100644 src/lyrics_fetcher.h diff --git a/doc/config b/doc/config index 6970df08..96643ca7 100644 --- a/doc/config +++ b/doc/config @@ -384,16 +384,6 @@ # #allow_physical_directories_deletion = "no" # -##### lyrics support ##### -## -## supported lyrics databases: -## -## - 1 - lyrc.com.ar -## - 2 - lyricsfly.com -## -# -#lyrics_database = "1" -# #external_editor = "" # #use_console_editor = "no" (set to yes, if your editor is console app) diff --git a/doc/ncmpcpp.1 b/doc/ncmpcpp.1 index 3becafca..5042b036 100644 --- a/doc/ncmpcpp.1 +++ b/doc/ncmpcpp.1 @@ -288,10 +288,6 @@ If enabled, ncmpcpp will override current window title with its own one. .B regular_expressions = basic/extended Type of currently used regular expressions. .TP -.B lyrics_database = NUMBER -Number of lyrics database in use. Currently supported DBs are: - 1 - lyricsplugin.com -.TP .B user_interface = classic/alternative Default user interface used by ncmpcpp at start. .TP diff --git a/src/Makefile.am b/src/Makefile.am index ad3bf3ad..5312d9b8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,9 +1,9 @@ bin_PROGRAMS = ncmpcpp ncmpcpp_SOURCES = browser.cpp charset.cpp clock.cpp conv.cpp curl_handle.cpp \ - display.cpp error.cpp help.cpp helpers.cpp info.cpp lyrics.cpp media_library.cpp \ - menu.cpp mpdpp.cpp ncmpcpp.cpp outputs.cpp playlist.cpp playlist_editor.cpp \ - scrollpad.cpp search_engine.cpp sel_items_adder.cpp server_info.cpp settings.cpp \ - song.cpp status.cpp tag_editor.cpp tiny_tag_editor.cpp tolower.cpp \ + display.cpp error.cpp help.cpp helpers.cpp info.cpp lyrics.cpp lyrics_fetcher.cpp \ + media_library.cpp menu.cpp mpdpp.cpp ncmpcpp.cpp outputs.cpp playlist.cpp \ + playlist_editor.cpp scrollpad.cpp search_engine.cpp sel_items_adder.cpp server_info.cpp \ + settings.cpp song.cpp status.cpp tag_editor.cpp tiny_tag_editor.cpp tolower.cpp \ visualizer.cpp window.cpp # set the include path found by configure @@ -12,7 +12,7 @@ INCLUDES= $(all_includes) # the library search path. ncmpcpp_LDFLAGS = $(all_libraries) noinst_HEADERS = browser.h charset.h clock.h conv.h curl_handle.h display.h \ - error.h global.h help.h helpers.h home.h info.h lyrics.h media_library.h menu.h \ - mpdpp.h outputs.h playlist_editor.h screen.h scrollpad.h search_engine.h \ - sel_items_adder.h server_info.h settings.h song.h tag_editor.h tiny_tag_editor.h \ - tolower.h visualizer.h window.h + error.h global.h help.h helpers.h home.h info.h lyrics.h lyrics_fetcher.h \ + media_library.h menu.h mpdpp.h outputs.h playlist_editor.h screen.h scrollpad.h \ + search_engine.h sel_items_adder.h server_info.h settings.h song.h tag_editor.h \ + tiny_tag_editor.h tolower.h visualizer.h window.h diff --git a/src/curl_handle.cpp b/src/curl_handle.cpp index 0b476645..2414fc1b 100644 --- a/src/curl_handle.cpp +++ b/src/curl_handle.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2008-2009 by Andrzej Rybczak * + * Copyright (C) 2008-2010 by Andrzej Rybczak * * electricityispower@gmail.com * * * * This program is free software; you can redistribute it and/or modify * diff --git a/src/curl_handle.h b/src/curl_handle.h index 96f938e4..9edee326 100644 --- a/src/curl_handle.h +++ b/src/curl_handle.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2008-2009 by Andrzej Rybczak * + * Copyright (C) 2008-2010 by Andrzej Rybczak * * electricityispower@gmail.com * * * * This program is free software; you can redistribute it and/or modify * diff --git a/src/lyrics.cpp b/src/lyrics.cpp index fd4c976c..72119b67 100644 --- a/src/lyrics.cpp +++ b/src/lyrics.cpp @@ -28,6 +28,7 @@ #include #include "lyrics.h" +#include "lyrics_fetcher.h" #include "browser.h" #include "charset.h" @@ -85,10 +86,18 @@ void Lyrics::Resize() void Lyrics::Update() { # if defined(HAVE_CURL_CURL_H) && defined(HAVE_PTHREAD_H) - if (myLyrics->Ready) - myLyrics->Take(); + if (Ready) + Take(); # endif // HAVE_CURL_CURL_H && HAVE_PTHREAD_H +# ifdef HAVE_PTHREAD_H + if (Downloader) + { + w->Flush(); + w->Refresh(); + } +# endif + if (Reload) SwitchTo(); } @@ -134,13 +143,9 @@ void Lyrics::SwitchTo() Global::RedrawHeader = 1; w->Clear(); w->Reset(); -# ifdef HAVE_CURL_CURL_H - static_cast(*w) << "Fetching lyrics..."; - w->Window::Refresh(); # ifdef HAVE_PTHREAD_H if (!Downloader) # endif // HAVE_PTHREAD_H -# endif // HAVE_CURL_CURL_H { std::string file = locale_to_utf_cpy(itsSong.GetArtist()) + " - " + locale_to_utf_cpy(itsSong.GetTitle()) + ".txt"; EscapeUnallowedChars(file); @@ -205,62 +210,35 @@ void Lyrics::SpacePressed() void *Lyrics::Get(void *screen_void_ptr) { Lyrics *screen = static_cast(screen_void_ptr); - const Plugin *my_lyrics = ChoosePlugin(Config.lyrics_db); - - std::string result; - std::string artist = locale_to_utf_cpy(screen->itsSong.GetArtist()); - std::string title = locale_to_utf_cpy(screen->itsSong.GetTitle()); - - std::string url = my_lyrics->url; - Replace(url, "%artist%", Curl::escape(artist).c_str()); - Replace(url, "%title%", Curl::escape(title).c_str()); - - CURLcode code = Curl::perform(url, result); - if (code != CURLE_OK) - { - *screen->w << "Error while fetching lyrics: " << curl_easy_strerror(code); - Ready = 1; - pthread_exit(0); - } + std::string artist = Curl::escape(locale_to_utf_cpy(screen->itsSong.GetArtist())); + std::string title = Curl::escape(locale_to_utf_cpy(screen->itsSong.GetTitle())); - size_t a, b; - bool parse_failed = 0; + LyricsFetcher::Result result; - if ((a = result.find(my_lyrics->tag_open)) != std::string::npos) + for (LyricsFetcher **plugin = lyricsPlugins; *plugin != 0; ++plugin) { - a += strlen(my_lyrics->tag_open); - if ((b = result.find(my_lyrics->tag_close, a)) != std::string::npos) - result = result.substr(a, b-a); + *screen->w << "Fetching lyrics from " << fmtBold << (*plugin)->name() << fmtBoldEnd << "... "; + result = (*plugin)->fetch(artist, title); + if (result.first == false) + *screen->w << clRed << result.second << clEnd << "\n"; else - parse_failed = 1; + break; } - else - parse_failed = 1; - if (parse_failed || my_lyrics->not_found(result)) + if (result.first == true) { - *screen->w << "Not found"; - Ready = 1; - pthread_exit(0); + screen->w->Clear(); + *screen->w << utf_to_locale_cpy(result.second); + + std::ofstream output(screen->itsFilenamePath.c_str()); + if (output.is_open()) + { + output << result.second; + output.close(); + } } - if (my_lyrics == &Lyricsfly) - Replace(result, "[br]", ""); - Replace(result, "<", "<"); - Replace(result, ">", ">"); - - EscapeHtml(result); - Trim(result); - - *screen->w << utf_to_locale_cpy(result); - - std::ofstream output(screen->itsFilenamePath.c_str()); - if (output.is_open()) - { - output << result; - output.close(); - } Ready = 1; pthread_exit(0); } @@ -307,9 +285,7 @@ void Lyrics::FetchAgain() } } -#ifdef HAVE_CURL_CURL_H - -#ifdef HAVE_PTHREAD_H +#if defined(HAVE_CURL_CURL_H) && defined(HAVE_PTHREAD_H) void Lyrics::Take() { if (!Ready) @@ -321,77 +297,5 @@ void Lyrics::Take() Downloader = 0; Ready = 0; } -#endif // HAVE_PTHREAD_H - -const unsigned Lyrics::DBs = 2; // number of currently supported lyrics databases - -const char *Lyrics::PluginsList[] = -{ - //"lyricsplugin.com", - "lyrc.com.ar", - "lyricsfly.com", - 0 -}; - -const char *Lyrics::GetPluginName(int offset) -{ - return PluginsList[offset]; -} - -/*bool Lyrics::LyricsPlugin_NotFound(const std::string &s) -{ - if (s.empty()) - return true; - for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) - if (isprint(*it)) - return false; - return true; -} - -const Lyrics::Plugin Lyrics::LyricsPlugin = -{ - "http://www.lyricsplugin.com/winamp03/plugin/?artist=%artist%&title=%title%", - "
", - "
", - LyricsPlugin_NotFound -};*/ - -bool Lyrics::Generic_NotFound(const std::string &) -{ - // it should never fail as open_tag and close_tag - // are not present if lyrics are not found - return false; -} - -const Lyrics::Plugin Lyrics::LyrcComAr = -{ - "http://lyrc.com.ar/tema1es.php?artist=%artist%&songname=%title%", - "", - "

", - Generic_NotFound -}; - -const Lyrics::Plugin Lyrics::Lyricsfly = -{ - "http://api.lyricsfly.com/api/api.php?i=30002e18b71fbe4f0-temporary.API.access&a=%artist%&t=%title%", - "", - "", - Generic_NotFound -}; - -const Lyrics::Plugin *Lyrics::ChoosePlugin(int i) -{ - switch (i) - { - case 0: - //return &LyricsPlugin; - return &LyrcComAr; - case 1: - return &Lyricsfly; - default: - return &LyrcComAr; - } -} - -#endif // HAVE_CURL_CURL_H +#endif // HAVE_CURL_CURL_H && HAVE_PTHREAD_H diff --git a/src/lyrics.h b/src/lyrics.h index 30bf837f..9b591fb9 100644 --- a/src/lyrics.h +++ b/src/lyrics.h @@ -27,14 +27,6 @@ class Lyrics : public Screen { - struct Plugin - { - const char *url; - const char *tag_open; - const char *tag_close; - bool (*not_found)(const std::string &); - }; - public: Lyrics() : itsScrollBegin(0) { } ~Lyrics() { } @@ -58,12 +50,6 @@ class Lyrics : public Screen static bool Reload; -# ifdef HAVE_CURL_CURL_H - static const char *GetPluginName(int offset); - - static const unsigned DBs; -# endif // HAVE_CURL_CURL_H - protected: virtual void Init(); @@ -79,20 +65,12 @@ class Lyrics : public Screen void Take(); # endif // HAVE_PTHREAD_H - static const Plugin *ChoosePlugin(int); - //static bool LyricsPlugin_NotFound(const std::string &); - static bool Generic_NotFound(const std::string &); - static bool Ready; # ifdef HAVE_PTHREAD_H static pthread_t *Downloader; # endif // HAVE_PTHREAD_H - static const char *PluginsList[]; - //static const Plugin LyricsPlugin; - static const Plugin LyrcComAr; - static const Plugin Lyricsfly; # endif // HAVE_CURL_CURL_H size_t itsScrollBegin; diff --git a/src/lyrics_fetcher.cpp b/src/lyrics_fetcher.cpp new file mode 100644 index 00000000..d5561be6 --- /dev/null +++ b/src/lyrics_fetcher.cpp @@ -0,0 +1,93 @@ +/*************************************************************************** + * Copyright (C) 2008-2010 by Andrzej Rybczak * + * electricityispower@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "curl_handle.h" + +#ifdef HAVE_CURL_CURL_H + +#include "conv.h" +#include "lyrics_fetcher.h" + +LyricsFetcher *lyricsPlugins[] = +{ + new LyrcComArFetcher(), + new LyricsflyFetcher(), + 0 +}; + +LyricsFetcher::Result LyricsFetcher::fetch(const std::string &artist, const std::string &title) +{ + Result result; + result.first = false; + + std::string url = getURL(); + Replace(url, "%artist%", artist.c_str()); + Replace(url, "%title%", title.c_str()); + + std::string data; + CURLcode code = Curl::perform(url, data); + + if (code != CURLE_OK) + { + result.second = "Error while fetching lyrics: "; + result.second += curl_easy_strerror(code); + return result; + } + + size_t a, b; + bool parse_failed = false; + if ((a = data.find(getOpenTag())) != std::string::npos) + { + a += strlen(getCloseTag())-1; + if ((b = data.find(getCloseTag(), a)) != std::string::npos) + data = data.substr(a, b-a); + else + parse_failed = true; + } + else + parse_failed = true; + + if (parse_failed || notLyrics(data)) + { + result.second = "Not found"; + return result; + } + + postProcess(data); + + result.second = data; + result.first = true; + return result; +} + +void LyricsFetcher::postProcess(std::string &data) +{ + EscapeHtml(data); + Trim(data); +} + +void LyricsflyFetcher::postProcess(std::string &data) +{ + Replace(data, "[br]", ""); + Trim(data); +} + +#endif // HAVE_CURL_CURL_H + diff --git a/src/lyrics_fetcher.h b/src/lyrics_fetcher.h new file mode 100644 index 00000000..5aa2cfd7 --- /dev/null +++ b/src/lyrics_fetcher.h @@ -0,0 +1,74 @@ +/*************************************************************************** + * Copyright (C) 2008-2010 by Andrzej Rybczak * + * electricityispower@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#ifndef _LYRICS_FETCHER_H +#define _LYRICS_FETCHER_H + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_CURL_CURL_H + +#include + +struct LyricsFetcher +{ + typedef std::pair Result; + + virtual const char *name() = 0; + virtual Result fetch(const std::string &artist, const std::string &title); + + protected: + virtual const char *getURL() = 0; + virtual const char *getOpenTag() = 0; + virtual const char *getCloseTag() = 0; + + virtual bool notLyrics(GNUC_UNUSED const std::string &data) { return false; } + virtual void postProcess(std::string &data); +}; + +struct LyrcComArFetcher : public LyricsFetcher +{ + virtual const char *name() { return "lyrc.com.ar"; } + + protected: + virtual const char *getURL() { return "http://lyrc.com.ar/tema1es.php?artist=%artist%&songname=%title%"; } + virtual const char *getOpenTag() { return ""; } + virtual const char *getCloseTag() { return "

"; } +}; + +struct LyricsflyFetcher : public LyricsFetcher +{ + virtual const char *name() { return "lyricsfly.com"; } + + protected: + virtual const char *getURL() { return "http://api.lyricsfly.com/api/api.php?i=1b76e55254f5f22ae-temporary.API.access&a=%artist%&t=%title%"; } + virtual const char *getOpenTag() { return ""; } + virtual const char *getCloseTag() { return ""; } + + virtual void postProcess(std::string &data); +}; + +extern LyricsFetcher *lyricsPlugins[]; + +#endif // HAVE_CURL_CURL_H + +#endif diff --git a/src/ncmpcpp.cpp b/src/ncmpcpp.cpp index 61017490..8a6c7741 100644 --- a/src/ncmpcpp.cpp +++ b/src/ncmpcpp.cpp @@ -1334,17 +1334,6 @@ int main(int argc, char *argv[]) Config.playlist_separate_albums = !Config.playlist_separate_albums; ShowMessage("Separators between albums in playlist: %s", Config.playlist_separate_albums ? "On" : "Off"); } -# ifdef HAVE_CURL_CURL_H - else if (Keypressed(input, Key.ToggleLyricsDB)) - { - const char *current_lyrics_plugin = Lyrics::GetPluginName(++Config.lyrics_db); - if (!current_lyrics_plugin) - { - current_lyrics_plugin = Lyrics::GetPluginName(Config.lyrics_db = 0); - } - ShowMessage("Using lyrics database: %s", current_lyrics_plugin); - } -# endif // HAVE_CURL_CURL_H else if (Keypressed(input, Key.ToggleAutoCenter)) { Config.autocenter_mode = !Config.autocenter_mode; diff --git a/src/settings.cpp b/src/settings.cpp index 8d52d966..a415a2d0 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1037,16 +1037,6 @@ void NcmpcppConfig::Read() { regex_type = REG_EXTENDED * (v != "basic"); } -# ifdef HAVE_CURL_CURL_H - else if (cl.find("lyrics_database") != std::string::npos) - { - if (!v.empty()) - { - unsigned n = StrToInt(v)-1; - lyrics_db = n < Lyrics::DBs ? n : 0; - } - } -# endif // HAVE_CURL_CURL_H else if (cl.find("lines_scrolled") != std::string::npos) { if (!v.empty())