Fix build errors, added COPYING
[maelyrica:maelyrica.git] / lyricsDownloader.cpp
1 /* File: lyricsDownloader.cpp
2  *
3  * This file is part of MaeLyrica.
4  *
5  * Copyright (C) 2012 Marcin Mielniczuk.
6  *
7  * MaeLyrica is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation, version 3 of the License.
10  *
11  * MaeLyrica is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  *  along with MaeLyrica.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "lyricsDownloader.h"
21 #include <curl/curl.h>
22 #include <QDebug>
23 #include <iostream>
24 #include <QFile>
25 #include <QSettings>
26
27 using namespace std;
28
29 #define DEBUG 1
30
31 /////////////////////////////////////////////////////////////////////////////
32
33 const QString lyricsDownloader::OMPLyricsRoot("/home/user/.lyrics/");
34
35 Settings lyricsDownloader::progSettings;
36
37 inline void lyricsDownloader::setData(const string &a, const string &t)
38 {
39     artist = a;
40     track = t;
41 }
42
43 size_t lyricsDownloader::write_data_to_var(char *ptr, size_t size, size_t nmemb, void *userdata)
44 {
45     ostringstream * stream = (ostringstream*) userdata;
46     size_t count = size * nmemb;
47     stream->write(ptr, count);
48     return count;
49 }
50
51 QString lyricsDownloader::cleanQString(const QString qstr)
52 {
53     return qstr.toLower().replace("&", "and").remove(QRegExp("\\([^)]*\\)")).remove(QRegExp("[\\W_]"));
54 }
55
56 void lyricsDownloader::cleanTitle()
57 {
58     cleanedTitle = cleanQString( QString::fromStdString(artist));
59     cleanedTitle += "-";
60     cleanedTitle += cleanQString(QString::fromStdString(track));
61 }
62
63
64 bool lyricsDownloader::lyricsExistOMP()
65 {
66     lyricsUrlOMP = OMPLyricsRoot + cleanedTitle + ".txt";
67     return QFile(lyricsUrlOMP).exists();
68 }
69
70 void lyricsDownloader::saveLyricsMaeLyrica()
71 {
72     QSettings("Marcin Mielniczuk", "MaeLyrica").setValue("lyrics/" + cleanedTitle, lyrics);
73 }
74
75 void lyricsDownloader::saveLyricsOMP()
76 {
77     QFile lyricsFile(lyricsUrlOMP);
78     QTextStream lyricsFileStream(&lyricsFile);
79     lyricsFileStream << lyrics;
80 }
81
82 ///////////////////////////////////////////////////////////////////////////////
83
84 const string AZLyricsDownloader::rooturl("http://azlyrics.com/lyrics");
85 const QRegExp AZLyricsDownloader::endcomment("<!-- end of lyrics -->");
86 const QRegExp AZLyricsDownloader::startcomment("<!-- start of lyrics -->");
87
88
89
90 short AZLyricsDownloader::perform()
91 {
92     CURLcode dlret; // return value from curl
93     dlret = download(); // it doesn't fail yet to recognize
94
95     if ( parse() != 0)
96     {
97         if ( dlret != 0 ) // Error while downloading and parsing means that the lyrics are just not there
98         {
99             qDebug() << "The lyrics are not present in AZLyrics.com database\n";
100             return 3;
101         }
102         qDebug() << "Error while parsing lyrics\n";
103         return 2;
104     }
105     if (dlret != 0) // just error while downloading
106     {
107         qDebug() << "Error while downloading lyrics\n";
108         return 1;
109     }
110
111     //qDebug() << lyrics();
112     emit lyricsChanged(lyrics);
113     return 0;
114 }
115
116 string AZLyricsDownloader::toProviderCode() const
117 {
118     QString artist_www, track_www;
119     artist_www = QString::fromStdString(artist).toLower().remove(QRegExp("^the")).remove(QRegExp("\\W"));
120     track_www = QString::fromStdString(track).toLower().remove(QRegExp("\\W"));
121
122     return (rooturl + "/" + artist_www.toStdString() + "/" + track_www.toStdString() + ".html");
123
124 }
125
126 CURLcode AZLyricsDownloader::download()
127 {
128     CURL * handle;
129     CURLcode err;
130     ostringstream buff;
131     lyrics_str = new string;
132     handle = curl_easy_init();
133     if (! handle) return static_cast<CURLcode>(-1);
134     // set verbose if debug on
135     curl_easy_setopt( handle, CURLOPT_VERBOSE, DEBUG );
136     curl_easy_setopt( handle, CURLOPT_URL, toProviderCode().c_str() ); // set the download url to the generated one
137     curl_easy_setopt(handle, CURLOPT_WRITEDATA, &buff);
138     curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, &AZLyricsDownloader::write_data_to_var); // set the function writing to ostringstream
139     curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1); // curl needs to follow redirects with this provider
140     curl_easy_setopt(handle, CURLOPT_FAILONERROR, 1);
141     err = curl_easy_perform(handle);
142     curl_easy_cleanup(handle);
143
144     // copy the contents to text variable
145     *lyrics_str = buff.str();
146     return err;
147
148
149 }
150
151 bool AZLyricsDownloader::parse()
152 {
153     istringstream temp(*lyrics_str);
154     delete lyrics_str;
155     lyrics_str = 0;
156     string line;
157     QString lyrics_QStr, line_QStr;
158     while ( temp.good() ) // looking for comment about starting lyrics
159     {
160         getline(temp, line);
161         if (QString::fromStdString(line).contains(startcomment)) break;
162     }
163     if ( !temp.good() ) return 1; // something went wrong, returning blank string
164     // get every line until endcomment
165     while ( temp.good() )
166     {
167         getline(temp, line);
168         if (( line_QStr = QString::fromStdString(line) ).contains(endcomment)) break;
169         lyrics_QStr += line_QStr.remove(QRegExp("<br[ ]{0,1}[/]{0,1}>"));
170         lyrics_QStr += "\n";
171     }
172     if ( !temp.good() ) return 1; // something went wrong, returning blank string
173
174     lyrics = lyrics_QStr; // after parsing all the work will be done using QStrings
175     return 0;
176 }