improve log message
[scrobby.git] / src / song.cpp
blobe3352ef0451b92a7b2af24d0f79a3668843ede2c
1 /***************************************************************************
2 * Copyright (C) 2008 by Andrzej Rybczak *
3 * electricityispower@gmail.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
21 #include <curl/curl.h>
22 #include <cstring>
23 #include <fstream>
24 #include <string>
25 #include <vector>
27 #include "callback.h"
28 #include "misc.h"
29 #include "scrobby.h"
30 #include "song.h"
32 using std::string;
34 extern Handshake myHandshake;
36 std::deque<std::string> MPD::Song::Queue;
38 MPD::Song::Song() : Data(0),
39 StartTime(0),
40 Playback(0),
41 itsIsStream(0)
45 MPD::Song::~Song()
47 if (Data)
48 mpd_freeSong(Data);
51 void MPD::Song::Clear()
53 if (Data)
54 mpd_freeSong(Data);
55 Data = 0;
56 StartTime = 0;
57 Playback = 0;
58 itsIsStream = 0;
61 void MPD::Song::SetData(mpd_Song *song)
63 if (!song)
64 return;
65 if (Data)
66 mpd_freeSong(Data);
67 Data = song;
68 itsIsStream = strncmp("http://", Data->file, 7) == 0;
71 void MPD::Song::Submit()
73 if (!Data)
74 return;
76 if (itsIsStream)
77 Data->time = Playback;
79 if (canBeSubmitted())
81 if (!Queue.empty())
83 Cache();
84 Clear();
85 SendQueue();
86 return;
89 if (myHandshake.Status != "OK" || myHandshake.SubmissionURL.empty())
91 Log(llInfo, "Problem with handshake, queue song at position %d...", Song::Queue.size());
92 Cache();
93 Clear();
94 return;
97 Log(llInfo, "Submitting song...");
99 std::ostringstream postdata;
100 string result, postdata_str;
101 CURLcode code;
103 char *c_artist = curl_easy_escape(0, Data->artist, 0);
104 char *c_title = curl_easy_escape(0, Data->title, 0);
105 char *c_album = Data->album ? curl_easy_escape(0, Data->album, 0) : NULL;
106 char *c_track = Data->track ? curl_easy_escape(0, Data->track, 0) : NULL;
108 postdata
109 << "s=" << myHandshake.SessionID
110 << "&a[0]=" << c_artist
111 << "&t[0]=" << c_title
112 << "&i[0]=" << StartTime
113 << "&o[0]=P"
114 << "&r[0]="
115 << "&l[0]=" << Data->time
116 << "&b[0]=";
117 if (c_album)
118 postdata << c_album;
119 postdata << "&n[0]=";
120 if (c_track)
121 postdata << c_track;
122 postdata << "&m[0]=";
124 curl_free(c_artist);
125 curl_free(c_title);
126 curl_free(c_album);
127 curl_free(c_track);
129 postdata_str = postdata.str();
131 Log(llVerbose, "URL: %s", myHandshake.SubmissionURL.c_str());
132 Log(llVerbose, "Post data: %s", postdata_str.c_str());
134 CURL *submission = curl_easy_init();
135 curl_easy_setopt(submission, CURLOPT_URL, myHandshake.SubmissionURL.c_str());
136 curl_easy_setopt(submission, CURLOPT_POST, 1);
137 curl_easy_setopt(submission, CURLOPT_POSTFIELDS, postdata_str.c_str());
138 curl_easy_setopt(submission, CURLOPT_WRITEFUNCTION, write_data);
139 curl_easy_setopt(submission, CURLOPT_WRITEDATA, &result);
140 curl_easy_setopt(submission, CURLOPT_CONNECTTIMEOUT, curl_timeout);
141 code = curl_easy_perform(submission);
142 curl_easy_cleanup(submission);
144 IgnoreNewlines(result);
146 if (result == "OK")
148 Log(llInfo, "Song submitted.");
150 else
152 if (result.empty())
154 Log(llInfo, "Error while submitting song: %s", curl_easy_strerror(code));
156 else
158 Log(llInfo, "Audioscrobbler returned status %s", result.c_str());
159 myHandshake.Clear(); // handshake probably failed if we are here, so reset it
160 Log(llVerbose, "Handshake reset");
162 Cache();
165 Clear();
168 void MPD::Song::Cache()
170 std::ostringstream cache;
171 string cache_str;
173 char *c_artist = curl_easy_escape(0, Data->artist, 0);
174 char *c_title = curl_easy_escape(0, Data->title, 0);
175 char *c_album = Data->album ? curl_easy_escape(0, Data->album, 0) : NULL;
176 char *c_track = Data->track ? curl_easy_escape(0, Data->track, 0) : NULL;
178 cache
179 << "&a[" << Song::Queue.size() << "]=" << c_artist
180 << "&t[" << Song::Queue.size() << "]=" << c_title
181 << "&i[" << Song::Queue.size() << "]=" << StartTime
182 << "&o[" << Song::Queue.size() << "]=P"
183 << "&r[" << Song::Queue.size() << "]="
184 << "&l[" << Song::Queue.size() << "]=" << Data->time
185 << "&b[" << Song::Queue.size() << "]=";
186 if (c_album)
187 cache << c_album;
188 cache << "&n[" << Song::Queue.size() << "]=";
189 if (c_track)
190 cache << c_track;
191 cache << "&m[" << Song::Queue.size() << "]=";
193 cache_str = cache.str();
195 Log(llVerbose, "Metadata: %s", cache_str.c_str());
197 curl_free(c_artist);
198 curl_free(c_title);
199 curl_free(c_album);
200 curl_free(c_track);
202 WriteCache(cache_str);
203 Song::Queue.push_back(cache_str);
204 Log(llInfo, "Song cached.");
207 bool MPD::Song::isStream() const
209 return itsIsStream;
212 bool MPD::Song::canBeSubmitted()
214 if (!StartTime || Data->time < 30 || !Data->artist || !Data->title)
216 if (!StartTime)
218 Log(llInfo, "Song's start time wasn't known, not submitting.");
220 else if (Data->time < 30)
222 Log(llInfo, "Song's length is too short, not submitting.");
224 else if (!Data->artist || !Data->title)
226 Log(llInfo, "Song has missing tags, not submitting.");
228 return false;
230 else if (Playback < 4*60 && Playback < Data->time/2)
232 Log(llInfo, "Noticed playback was too short, not submitting.");
233 return false;
235 return true;
238 void MPD::Song::GetCached()
240 std::ifstream f(Config.file_cache.c_str());
241 if (f.is_open())
243 std::string line;
244 while (!f.eof())
246 getline(f, line);
247 if (!line.empty())
248 Queue.push_back(line);
253 void MPD::Song::SendQueue()
255 if (Song::Queue.empty())
256 return;
258 Log(llInfo, "Queue is not empty, submitting songs...");
260 string result, postdata;
261 CURLcode code;
263 postdata = "s=";
264 postdata += myHandshake.SessionID;
266 for (std::deque<string>::const_iterator it = Song::Queue.begin(); it != Song::Queue.end(); it++)
267 postdata += *it;
269 Log(llVerbose, "URL: %s", myHandshake.SubmissionURL.c_str());
270 Log(llVerbose, "Post data: %s", postdata.c_str());
272 CURL *submission = curl_easy_init();
273 curl_easy_setopt(submission, CURLOPT_URL, myHandshake.SubmissionURL.c_str());
274 curl_easy_setopt(submission, CURLOPT_POST, 1);
275 curl_easy_setopt(submission, CURLOPT_POSTFIELDS, postdata.c_str());
276 curl_easy_setopt(submission, CURLOPT_WRITEFUNCTION, write_data);
277 curl_easy_setopt(submission, CURLOPT_WRITEDATA, &result);
278 curl_easy_setopt(submission, CURLOPT_CONNECTTIMEOUT, curl_timeout);
279 code = curl_easy_perform(submission);
280 curl_easy_cleanup(submission);
282 IgnoreNewlines(result);
284 if (result == "OK")
286 Log(llInfo, "Number of submitted songs: %d", Song::Queue.size());
287 Song::Queue.clear();
288 ClearCache();
290 else
292 if (result.empty())
294 Log(llInfo, "Error while submitting songs: %s", curl_easy_strerror(code));
296 else
298 Log(llInfo, "Audioscrobbler returned status %s", result.c_str());