1 /***************************************************************************
2 * Copyright (C) 2008-2009 by Andrzej Rybczak *
3 * electricityispower@gmail.com *
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. *
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. *
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 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
21 #include <curl/curl.h>
33 extern Handshake myHandshake
;
35 std::deque
<std::string
> MPD::Song::Queue
;
37 MPD::Song::Song() : Data(0),
50 void MPD::Song::Clear()
60 void MPD::Song::SetData(mpd_Song
*song
)
67 itsIsStream
= strncmp("http://", Data
->file
, 7) == 0;
70 void MPD::Song::Submit()
76 Data
->time
= Playback
;
82 Log(llInfo
, "Adding song to queue...");
89 if (myHandshake
.Status
!= "OK" || myHandshake
.SubmissionURL
.empty())
91 Log(llInfo
, "Problem with handshake, queue song at position %d...", Song::Queue
.size());
97 Log(llInfo
, "Submitting song...");
99 std::ostringstream postdata
;
100 string result
, postdata_str
;
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
;
107 char *c_mb_trackid
= Data
->musicbrainz_trackid
? curl_easy_escape(0, Data
->musicbrainz_trackid
, 0) : NULL
;
110 << "s=" << myHandshake
.SessionID
111 << "&a[0]=" << c_artist
112 << "&t[0]=" << c_title
113 << "&i[0]=" << StartTime
116 << "&l[0]=" << Data
->time
120 postdata
<< "&n[0]=";
123 postdata
<< "&m[0]=";
125 postdata
<< c_mb_trackid
;
131 curl_free(c_mb_trackid
);
133 postdata_str
= postdata
.str();
135 Log(llVerbose
, "URL: %s", myHandshake
.SubmissionURL
.c_str());
136 Log(llVerbose
, "Post data: %s", postdata_str
.c_str());
138 CURL
*submission
= curl_easy_init();
139 curl_easy_setopt(submission
, CURLOPT_URL
, myHandshake
.SubmissionURL
.c_str());
140 curl_easy_setopt(submission
, CURLOPT_POST
, 1);
141 curl_easy_setopt(submission
, CURLOPT_POSTFIELDS
, postdata_str
.c_str());
142 curl_easy_setopt(submission
, CURLOPT_WRITEFUNCTION
, write_data
);
143 curl_easy_setopt(submission
, CURLOPT_WRITEDATA
, &result
);
144 curl_easy_setopt(submission
, CURLOPT_CONNECTTIMEOUT
, curl_connecttimeout
);
145 curl_easy_setopt(submission
, CURLOPT_TIMEOUT
, curl_timeout
);
146 curl_easy_setopt(submission
, CURLOPT_DNS_CACHE_TIMEOUT
, 0);
147 curl_easy_setopt(submission
, CURLOPT_NOPROGRESS
, 1);
148 curl_easy_setopt(submission
, CURLOPT_NOSIGNAL
, 1);
149 code
= curl_easy_perform(submission
);
150 curl_easy_cleanup(submission
);
152 IgnoreNewlines(result
);
156 Log(llInfo
, "Song submitted.");
162 Log(llInfo
, "Error while submitting song: %s", curl_easy_strerror(code
));
166 Log(llInfo
, "Audioscrobbler returned status %s", result
.c_str());
167 myHandshake
.Clear(); // handshake probably failed if we are here, so reset it
168 Log(llVerbose
, "Handshake reset");
176 void MPD::Song::Cache()
178 std::ostringstream cache
;
181 char *c_artist
= curl_easy_escape(0, Data
->artist
, 0);
182 char *c_title
= curl_easy_escape(0, Data
->title
, 0);
183 char *c_album
= Data
->album
? curl_easy_escape(0, Data
->album
, 0) : NULL
;
184 char *c_track
= Data
->track
? curl_easy_escape(0, Data
->track
, 0) : NULL
;
185 char *c_mb_trackid
= Data
->musicbrainz_trackid
? curl_easy_escape(0, Data
->musicbrainz_trackid
, 0) : NULL
;
188 << "&a[" << Song::Queue
.size() << "]=" << c_artist
189 << "&t[" << Song::Queue
.size() << "]=" << c_title
190 << "&i[" << Song::Queue
.size() << "]=" << StartTime
191 << "&o[" << Song::Queue
.size() << "]=P"
192 << "&r[" << Song::Queue
.size() << "]="
193 << "&l[" << Song::Queue
.size() << "]=" << Data
->time
194 << "&b[" << Song::Queue
.size() << "]=";
197 cache
<< "&n[" << Song::Queue
.size() << "]=";
200 cache
<< "&m[" << Song::Queue
.size() << "]=";
202 cache
<< c_mb_trackid
;
204 cache_str
= cache
.str();
206 Log(llVerbose
, "Metadata: %s", cache_str
.c_str());
212 curl_free(c_mb_trackid
);
214 WriteCache(cache_str
);
215 Song::Queue
.push_back(cache_str
);
216 Log(llInfo
, "Song cached.");
219 bool MPD::Song::isStream() const
224 bool MPD::Song::canBeSubmitted()
226 if (!StartTime
|| Data
->time
< 30 || !Data
->artist
|| !Data
->title
)
230 Log(llInfo
, "Song's start time wasn't known, not submitting.");
232 else if (Data
->time
< 30)
234 Log(llInfo
, "Song's length is too short, not submitting.");
236 else if (!Data
->artist
|| !Data
->title
)
238 Log(llInfo
, "Song has missing tags, not submitting.");
242 else if (Playback
< 4*60 && Playback
< Data
->time
/2)
244 Log(llInfo
, "Noticed playback was too short, not submitting.");
250 void MPD::Song::GetCached()
252 std::ifstream
f(Config
.file_cache
.c_str());
260 Queue
.push_back(line
);
265 void MPD::Song::SendQueue()
267 if (Song::Queue
.empty())
270 Log(llInfo
, "Submitting songs from queue...");
272 string result
, postdata
;
276 postdata
+= myHandshake
.SessionID
;
278 for (std::deque
<string
>::const_iterator it
= Song::Queue
.begin(); it
!= Song::Queue
.end(); it
++)
281 Log(llVerbose
, "URL: %s", myHandshake
.SubmissionURL
.c_str());
282 Log(llVerbose
, "Post data: %s", postdata
.c_str());
284 CURL
*submission
= curl_easy_init();
285 curl_easy_setopt(submission
, CURLOPT_URL
, myHandshake
.SubmissionURL
.c_str());
286 curl_easy_setopt(submission
, CURLOPT_POST
, 1);
287 curl_easy_setopt(submission
, CURLOPT_POSTFIELDS
, postdata
.c_str());
288 curl_easy_setopt(submission
, CURLOPT_WRITEFUNCTION
, write_data
);
289 curl_easy_setopt(submission
, CURLOPT_WRITEDATA
, &result
);
290 curl_easy_setopt(submission
, CURLOPT_CONNECTTIMEOUT
, curl_connecttimeout
);
291 curl_easy_setopt(submission
, CURLOPT_TIMEOUT
, curl_timeout
);
292 curl_easy_setopt(submission
, CURLOPT_DNS_CACHE_TIMEOUT
, 0);
293 curl_easy_setopt(submission
, CURLOPT_NOPROGRESS
, 1);
294 curl_easy_setopt(submission
, CURLOPT_NOSIGNAL
, 1);
295 code
= curl_easy_perform(submission
);
296 curl_easy_cleanup(submission
);
298 IgnoreNewlines(result
);
302 Log(llInfo
, "Number of submitted songs: %d", Song::Queue
.size());
310 Log(llInfo
, "Error while submitting songs: %s", curl_easy_strerror(code
));
314 Log(llInfo
, "Audioscrobbler returned status %s", result
.c_str());