diff --git a/doc/ncmpcpp_keys b/doc/ncmpcpp_keys index 942718ba..71fbd079 100644 --- a/doc/ncmpcpp_keys +++ b/doc/ncmpcpp_keys @@ -95,6 +95,8 @@ # #key_song_info = 'i' # +#key_artist_info = 'I' +# #key_lyrics = 'l' # #key_reverse_selection = 'v' diff --git a/src/help.cpp b/src/help.cpp index 4221bad0..dd298872 100644 --- a/src/help.cpp +++ b/src/help.cpp @@ -136,7 +136,10 @@ string GetKeybindings() result += DisplayKeys(Key.EditTags) + "Edit song's tags/playlist's name\n"; # endif // HAVE_TAGLIB_H result += DisplayKeys(Key.GoToPosition) + "Go to chosen position in current song\n"; - result += DisplayKeys(Key.ShowInfo) + "Show song's info\n"; + result += DisplayKeys(Key.SongInfo) + "Show song's info\n"; +# ifdef HAVE_CURL_CURL_H + result += DisplayKeys(Key.ArtistInfo) + "Show artist's info\n"; +# endif // HAVE_CURL_CURL_H result += DisplayKeys(Key.Lyrics) + "Show/hide song's lyrics\n\n"; result += DisplayKeys(Key.Quit) + "Quit\n\n\n"; diff --git a/src/lyrics.cpp b/src/lyrics.cpp index bdb9c722..c030286b 100644 --- a/src/lyrics.cpp +++ b/src/lyrics.cpp @@ -20,6 +20,9 @@ #include #include "lyrics.h" +#include "settings.h" + +extern ncmpcpp_config Config; const string lyrics_folder = home_folder + "/" + ".lyrics"; @@ -49,6 +52,136 @@ void EscapeHtml(string &str) str.replace(i, 6, "&"); } +#ifdef HAVE_CURL_CURL_H +string GetArtistInfo(string artist) +{ + const string filename = artist + ".txt"; + const string fullpath = lyrics_folder + "/" + filename; + mkdir(lyrics_folder.c_str(), 0755); + + string result; + std::ifstream input(fullpath.c_str()); + + if (input.is_open()) + { + string line; + while (getline(input, line)) + result += line + "\n"; + return result.substr(0, result.length()-1); + } + + for (string::iterator it = artist.begin(); it != artist.end(); it++) + if (*it == ' ') + *it = '+'; + + CURLcode code; + + string url = "http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&artist=" + artist + "&api_key=d94e5b6e26469a2d1ffae8ef20131b79"; + + CURL *info = curl_easy_init(); + curl_easy_setopt(info, CURLOPT_URL, url.c_str()); + curl_easy_setopt(info, CURLOPT_WRITEFUNCTION, write_data); + curl_easy_setopt(info, CURLOPT_WRITEDATA, &result); + curl_easy_setopt(info, CURLOPT_CONNECTTIMEOUT, 10); + code = curl_easy_perform(info); + curl_easy_cleanup(info); + + if (code != CURLE_OK) + { + result = "Error while fetching artist's info: " + string(curl_easy_strerror(code)); + return result; + } + + int a, b; + bool erase = 0; + bool save = 1; + + a = result.find("status=\"failed\""); + + if (a != string::npos) + { + EscapeHtml(result); + return "Last.fm returned an error message: " + result; + } + + vector similar; + for (int i = result.find(""); i != string::npos; i = result.find("")) + { + result[i] = '.'; + int j = result.find(""); + result[j] = '.'; + i += 6; + similar.push_back(result.substr(i, j-i)); + } + vector urls; + for (int i = result.find(""); i != string::npos; i = result.find("")) + { + result[i] = '.'; + int j = result.find(""); + result[j] = '.'; + i += 5; + urls.push_back(result.substr(i, j-i)); + } + + a = result.find("")+9; + b = result.find(""); + + if (a == b) + { + result = "No description available for this artist."; + save = 0; + } + else + { + a += 9; // for + result = result.substr(a, b-a); + } + + EscapeHtml(result); + for (int i = 0; i < result.length(); i++) + { + if (erase) + { + result.erase(result.begin()+i); + erase = 0; + } + if (result[i] == 13) + { + result[i] = '\n'; + erase = 1; + } + else if (result[i] == '\t') + result[i] = ' '; + } + + int i = result.length(); + if (result[i-1] == '\n') + { + while (result[--i] == '\n'); + result = result.substr(0, i+1); + } + + result += "\n\n[.b]Similar artists:[/b]\n"; + for (int i = 1; i < similar.size(); i++) + result += "\n [." + Config.color2 + "]*[/" + Config.color2 + "] " + similar[i] + " (" + urls[i] + ")"; + + result += "\n\n" + urls.front(); + + if (save) + { + std::ofstream output(fullpath.c_str()); + if (output.is_open()) + { + output << result; + output.close(); + } + } + + return result; +} +#endif // HAVE_CURL_CURL_H + string GetLyrics(string artist, string song) { const string filename = artist + " - " + song + ".txt"; @@ -63,7 +196,7 @@ string GetLyrics(string artist, string song) string line; while (getline(input, line)) result += line + "\n"; - return result; + return result.substr(0, result.length()-1); } # ifdef HAVE_CURL_CURL_H @@ -110,7 +243,6 @@ string GetLyrics(string artist, string song) EscapeHtml(result); std::ofstream output(fullpath.c_str()); - if (output.is_open()) { output << result; @@ -119,6 +251,6 @@ string GetLyrics(string artist, string song) # else result = "Local lyrics not found. As ncmpcpp has been compiled without curl support, you can put appropriate lyrics into ~/.lyrics directory (file syntax is \"ARTIST - TITLE.txt\") or recompile ncmpcpp with curl support."; # endif - return result + '\n'; + return result; } diff --git a/src/lyrics.h b/src/lyrics.h index 5ae8ce9d..9e1dbbfd 100644 --- a/src/lyrics.h +++ b/src/lyrics.h @@ -26,6 +26,7 @@ #include #ifdef HAVE_CURL_CURL_H # include "curl/curl.h" +string GetArtistInfo(string); #endif void EscapeHtml(string &); diff --git a/src/ncmpcpp.cpp b/src/ncmpcpp.cpp index 618d9586..10a352a9 100644 --- a/src/ncmpcpp.cpp +++ b/src/ncmpcpp.cpp @@ -304,6 +304,7 @@ int main(int argc, char *argv[]) bool title_allowed = 0; string lyrics_title; + string info_title; // local variables end while (!main_exit) @@ -348,7 +349,7 @@ int main(int argc, char *argv[]) title = "Tag editor"; break; case csInfo: - title = "Song info"; + title = info_title; break; case csSearcher: title = "Search engine"; @@ -2717,7 +2718,7 @@ int main(int argc, char *argv[]) Config.space_selects = !Config.space_selects; ShowMessage("Space mode: " + string(Config.space_selects ? "Select/deselect" : "Add") + " item"); } - else if (Keypressed(input, Key.ShowInfo)) + else if (Keypressed(input, Key.SongInfo)) { if (wCurrent == sInfo) { @@ -2779,11 +2780,88 @@ int main(int argc, char *argv[]) prev_screen = current_screen; current_screen = csInfo; redraw_header = 1; + info_title = "Song info"; sInfo->Clear(); sInfo->Add(GetInfo(*s)); sInfo->Hide(); } } +# ifdef HAVE_CURL_CURL_H + else if (Keypressed(input, Key.ArtistInfo)) + { + if (wCurrent == sInfo) + { + wCurrent->Hide(); + current_screen = prev_screen; + wCurrent = wPrev; + redraw_screen = 1; + redraw_header = 1; + if (current_screen == csLibrary) + { + REFRESH_MEDIA_LIBRARY_SCREEN; + } + else if (current_screen == csPlaylistEditor) + { + REFRESH_PLAYLIST_EDITOR_SCREEN; + } +# ifdef HAVE_TAGLIB_H + else if (current_screen == csTagEditor) + { + REFRESH_TAG_EDITOR_SCREEN; + } +# endif // HAVE_TAGLIB_H + } + else if ( + (wCurrent == mPlaylist && !mPlaylist->Empty()) + || (wCurrent == mBrowser && mBrowser->Current().type == itSong) + || (wCurrent == mSearcher && mSearcher->Current().first == ".") + || (wCurrent == mLibArtists && !mLibArtists->Empty()) + || (wCurrent == mLibSongs && !mLibSongs->Empty()) + || (wCurrent == mPlaylistEditor && !mPlaylistEditor->Empty()) + || (wCurrent == mEditorTags && !mEditorTags->Empty())) + { + string artist; + int id = wCurrent->GetChoice(); + switch (current_screen) + { + case csPlaylist: + artist = mPlaylist->at(id).GetArtist(); + break; + case csBrowser: + artist = mBrowser->at(id).song->GetArtist(); + break; + case csSearcher: + artist = mSearcher->at(id).second.GetArtist(); + break; + case csLibrary: + artist = mLibArtists->at(id); + break; + case csPlaylistEditor: + artist = mPlaylistEditor->at(id).GetArtist(); + break; + case csTagEditor: + artist = mEditorTags->at(id).GetArtist(); + break; + default: + break; + } + if (artist != UNKNOWN_ARTIST) + { + wPrev = wCurrent; + wCurrent = sInfo; + prev_screen = current_screen; + current_screen = csInfo; + redraw_header = 1; + info_title = "Artist's info - " + artist; + sInfo->Clear(); + sInfo->WriteXY(0, 0, "Fetching artist's info..."); + sInfo->Refresh(); + sInfo->Add(GetArtistInfo(artist)); + sInfo->Hide(); + } + } + } +# endif // HAVE_CURL_CURL_H else if (Keypressed(input, Key.Lyrics)) { if (wCurrent == sLyrics) diff --git a/src/settings.cpp b/src/settings.cpp index 4a3c6a41..7021f0ed 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -66,7 +66,8 @@ void DefaultKeys(ncmpcpp_keys &keys) keys.PrevFoundPosition[0] = ','; keys.ToggleFindMode[0] = 'w'; keys.EditTags[0] = 'e'; - keys.ShowInfo[0] = 'i'; + keys.SongInfo[0] = 'i'; + keys.ArtistInfo[0] = 'I'; keys.GoToPosition[0] = 'g'; keys.Lyrics[0] = 'l'; keys.ReverseSelection[0] = 'v'; @@ -125,7 +126,8 @@ void DefaultKeys(ncmpcpp_keys &keys) keys.PrevFoundPosition[1] = null_key; keys.ToggleFindMode[1] = null_key; keys.EditTags[1] = null_key; - keys.ShowInfo[1] = null_key; + keys.SongInfo[1] = null_key; + keys.ArtistInfo[1] = null_key; keys.GoToPosition[1] = null_key; keys.Lyrics[1] = null_key; keys.ReverseSelection[1] = null_key; @@ -381,7 +383,9 @@ void ReadKeys(ncmpcpp_keys &keys) else if (it->find("key_go_to_position ") != string::npos) GetKeys(*it, keys.GoToPosition); else if (it->find("key_song_info ") != string::npos) - GetKeys(*it, keys.ShowInfo); + GetKeys(*it, keys.SongInfo); + else if (it->find("key_artist_info ") != string::npos) + GetKeys(*it, keys.ArtistInfo); else if (it->find("key_lyrics ") != string::npos) GetKeys(*it, keys.Lyrics); else if (it->find("key_reverse_selection ") != string::npos) diff --git a/src/settings.h b/src/settings.h index 5add4798..a6eec8b2 100644 --- a/src/settings.h +++ b/src/settings.h @@ -68,7 +68,8 @@ struct ncmpcpp_keys int PrevFoundPosition[2]; int ToggleFindMode[2]; int EditTags[2]; - int ShowInfo[2]; + int SongInfo[2]; + int ArtistInfo[2]; int GoToPosition[2]; int Lyrics[2]; int ReverseSelection[2];