improve logging
[scrobby.git] / src / song.cpp
blobd513c4ebef5375f3b5a331ab6ed0c2dbbfa9f1bd
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 <string>
24 #include <vector>
26 #include "misc.h"
27 #include "scrobby.h"
28 #include "song.h"
30 using std::string;
32 extern Handshake handshake;
34 extern pthread_mutex_t curl_lock;
35 extern pthread_mutex_t handshake_lock;
37 extern std::vector<string> SongsQueue;
39 MPD::Song::Song() : itsSong(0),
40 itsStartTime(0),
41 itsNoticedPlayback(0),
42 itsIsStream(0)
46 MPD::Song::~Song()
48 if (itsSong)
49 mpd_freeSong(itsSong);
52 void MPD::Song::Clear()
54 if (itsSong)
55 mpd_freeSong(itsSong);
56 itsSong = 0;
57 itsStartTime = 0;
58 itsNoticedPlayback = 0;
59 itsIsStream = 0;
62 void MPD::Song::SetData(mpd_Song *song)
64 if (!song)
65 return;
66 if (itsSong)
67 mpd_freeSong(itsSong);
68 itsSong = song;
69 itsIsStream = strncmp("http://", itsSong->file, 7) == 0;
73 void MPD::Song::SetStartTime()
75 itsStartTime = time(NULL);
78 void MPD::Song::Submit()
80 if (!itsSong)
81 return;
83 if (itsIsStream)
85 itsSong->time = itsNoticedPlayback;
88 pthread_mutex_lock(&handshake_lock);
89 if (canBeSubmitted())
91 if (handshake.status != "OK" || handshake.submission_url.empty())
93 Log(llInfo, "Problems with handshake status, SongsQueue song at position %d...", SongsQueue.size());
94 goto SUBMISSION_FAILED;
97 Log(llInfo, "Submitting song...");
99 string result, postdata;
100 CURLcode code;
102 pthread_mutex_lock(&curl_lock);
103 CURL *submission = curl_easy_init();
105 char *c_artist = curl_easy_escape(submission, itsSong->artist, 0);
106 char *c_title = curl_easy_escape(submission, itsSong->title, 0);
107 char *c_album = itsSong->album ? curl_easy_escape(submission, itsSong->album, 0) : NULL;
108 char *c_track = itsSong->track ? curl_easy_escape(submission, itsSong->track, 0) : NULL;
110 postdata = "s=";
111 postdata += handshake.session_id;
112 postdata += "&a[0]=";
113 postdata += c_artist;
114 postdata += "&t[0]=";
115 postdata += c_title;
116 postdata += "&i[0]=";
117 postdata += IntoStr(itsStartTime);
118 postdata += "&o[0]=P";
119 postdata += "&r[0]=";
120 postdata += "&l[0]=";
121 postdata += IntoStr(itsSong->time);
122 postdata += "&b[0]=";
123 if (c_album)
124 postdata += c_album;
125 postdata += "&n[0]=";
126 if (c_track)
127 postdata += c_track;
128 postdata += "&m[0]=";
130 curl_free(c_artist);
131 curl_free(c_title);
132 curl_free(c_album);
133 curl_free(c_track);
135 Log(llVerbose, "URL: %s", handshake.submission_url.c_str());
136 Log(llVerbose, "Post data: %s", postdata.c_str());
138 curl_easy_setopt(submission, CURLOPT_URL, handshake.submission_url.c_str());
139 curl_easy_setopt(submission, CURLOPT_POST, 1);
140 curl_easy_setopt(submission, CURLOPT_POSTFIELDS, postdata.c_str());
141 curl_easy_setopt(submission, CURLOPT_WRITEFUNCTION, write_data);
142 curl_easy_setopt(submission, CURLOPT_WRITEDATA, &result);
143 curl_easy_setopt(submission, CURLOPT_CONNECTTIMEOUT, curl_timeout);
144 code = curl_easy_perform(submission);
145 curl_easy_cleanup(submission);
146 pthread_mutex_unlock(&curl_lock);
148 ignore_newlines(result);
150 if (result == "OK")
152 Log(llInfo, "Song submitted.");
154 else
156 if (result.empty())
158 Log(llInfo, "Error while submitting song: %s", curl_easy_strerror(code));
160 else
162 Log(llInfo, "Audioscrobbler returned status %s", result.c_str());
164 goto SUBMISSION_FAILED;
167 if (0)
169 SUBMISSION_FAILED: // so we cache not submitted song
171 handshake.Clear(); // handshake probably failed if we are here, so reset it
172 Log(llVerbose, "Handshake status reset");
174 string cache;
175 string offset = IntoStr(SongsQueue.size());
177 char *c_artist = curl_easy_escape(0, itsSong->artist, 0);
178 char *c_title = curl_easy_escape(0, itsSong->title, 0);
179 char *c_album = itsSong->album ? curl_easy_escape(0, itsSong->album, 0) : NULL;
180 char *c_track = itsSong->track ? curl_easy_escape(0, itsSong->track, 0) : NULL;
182 cache = "&a[";
183 cache += offset;
184 cache += "]=";
185 cache += c_artist;
186 cache += "&t[";
187 cache += offset;
188 cache += "]=";
189 cache += c_title;
190 cache += "&i[";
191 cache += offset;
192 cache += "]=";
193 cache += IntoStr(itsStartTime);
194 cache += "&o[";
195 cache += offset;
196 cache += "]=P";
197 cache += "&r[";
198 cache += offset;
199 cache += "]=";
200 cache += "&l[";
201 cache += offset;
202 cache += "]=";
203 cache += IntoStr(itsSong->time);
204 cache += "&b[";
205 cache += offset;
206 cache += "]=";
207 if (c_album)
208 cache += c_album;
209 cache += "&n[";
210 cache += offset;
211 cache += "]=";
212 if (c_track)
213 cache += c_track;
214 cache += "&m[";
215 cache += offset;
216 cache += "]=";
218 Log(llVerbose, "Metadata: %s", cache.c_str());
220 curl_free(c_artist);
221 curl_free(c_title);
222 curl_free(c_album);
223 curl_free(c_track);
225 Cache(cache);
226 SongsQueue.push_back(cache);
227 Log(llInfo, "Song cached.");
229 pthread_mutex_unlock(&handshake_lock);
230 Clear();
233 bool MPD::Song::isStream()
235 return itsIsStream;
238 int & MPD::Song::Playback()
240 return itsNoticedPlayback;
243 const mpd_Song *& MPD::Song::Data()
245 return (const mpd_Song *&)itsSong;
248 bool MPD::Song::canBeSubmitted()
250 if (!itsStartTime || itsSong->time < 30 || !itsSong->artist || !itsSong->title)
252 if (!itsStartTime)
254 Log(llInfo, "Song's start time isn't known, not submitting.");
256 else if (itsSong->time < 30)
258 Log(llInfo, "Song's length is too short, not submitting.");
260 else if (!itsSong->artist || !itsSong->title)
262 Log(llInfo, "Song has missing tags, not submitting.");
264 return false;
266 else if (itsNoticedPlayback < 4*60 && itsNoticedPlayback < itsSong->time/2)
268 Log(llInfo, "Noticed playback was too short, not submitting.");
269 return false;
271 return true;