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
;
36 bool MPD::Song::NowPlayingNotify
= 0;
38 std::deque
<std::string
> MPD::Song::SubmitQueue
;
39 std::queue
<MPD::Song
> MPD::Song::Queue
;
41 MPD::Song::Song() : Data(0),
54 void MPD::Song::Clear()
64 void MPD::Song::SetData(mpd_Song
*song
)
71 itsIsStream
= strncmp("http://", Data
->file
, 7) == 0;
74 void MPD::Song::Submit()
80 Data
->time
= Playback
;
86 Log(llInfo
, "Song queued for submission.");
91 bool MPD::Song::isStream() const
96 bool MPD::Song::canBeSubmitted()
98 if (!StartTime
|| Data
->time
< 30 || !Data
->artist
|| !Data
->title
)
102 Log(llInfo
, "Song's start time wasn't known, not submitting.");
104 else if (Data
->time
< 30)
106 Log(llInfo
, "Song's length is too short, not submitting.");
108 else if (!Data
->artist
|| !Data
->title
)
110 Log(llInfo
, "Song has missing tags, not submitting.");
114 else if (Playback
< 4*60 && Playback
< Data
->time
/2)
116 Log(llInfo
, "Noticed playback was too short, not submitting.");
122 void MPD::Song::GetCached()
124 std::ifstream
f(Config
.file_cache
.c_str());
132 SubmitQueue
.push_back(line
);
137 void MPD::Song::ExtractQueue()
139 for (; !Queue
.empty(); Queue
.pop())
141 const MPD::Song
&s
= Queue
.front();
144 std::ostringstream cache
;
146 char *c_artist
= curl_easy_escape(0, s
.Data
->artist
, 0);
147 char *c_title
= curl_easy_escape(0, s
.Data
->title
, 0);
148 char *c_album
= s
.Data
->album
? curl_easy_escape(0, s
.Data
->album
, 0) : 0;
149 char *c_track
= s
.Data
->track
? curl_easy_escape(0, s
.Data
->track
, 0) : 0;
150 char *c_mb_trackid
= s
.Data
->musicbrainz_trackid
? curl_easy_escape(0, s
.Data
->musicbrainz_trackid
, 0) : 0;
153 << "&a[" << Song::SubmitQueue
.size() << "]=" << c_artist
154 << "&t[" << Song::SubmitQueue
.size() << "]=" << c_title
155 << "&i[" << Song::SubmitQueue
.size() << "]=" << s
.StartTime
156 << "&o[" << Song::SubmitQueue
.size() << "]=P"
157 << "&r[" << Song::SubmitQueue
.size() << "]="
158 << "&l[" << Song::SubmitQueue
.size() << "]=" << s
.Data
->time
159 << "&b[" << Song::SubmitQueue
.size() << "]=";
162 cache
<< "&n[" << Song::SubmitQueue
.size() << "]=";
165 cache
<< "&m[" << Song::SubmitQueue
.size() << "]=";
167 cache
<< c_mb_trackid
;
169 cache_str
= cache
.str();
171 SubmitQueue
.push_back(cache_str
);
172 WriteCache(cache_str
);
178 curl_free(c_mb_trackid
);
182 bool MPD::Song::SendQueue()
186 if (!myHandshake
.OK())
189 Log(llInfo
, "Submitting songs...");
191 string result
, postdata
;
195 postdata
+= myHandshake
.SessionID
;
197 for (std::deque
<string
>::const_iterator it
= Song::SubmitQueue
.begin(); it
!= Song::SubmitQueue
.end(); it
++)
200 Log(llVerbose
, "URL: %s", myHandshake
.SubmissionURL
.c_str());
201 Log(llVerbose
, "Post data: %s", postdata
.c_str());
203 CURL
*submission
= curl_easy_init();
204 curl_easy_setopt(submission
, CURLOPT_URL
, myHandshake
.SubmissionURL
.c_str());
205 curl_easy_setopt(submission
, CURLOPT_POST
, 1);
206 curl_easy_setopt(submission
, CURLOPT_POSTFIELDS
, postdata
.c_str());
207 curl_easy_setopt(submission
, CURLOPT_WRITEFUNCTION
, write_data
);
208 curl_easy_setopt(submission
, CURLOPT_WRITEDATA
, &result
);
209 curl_easy_setopt(submission
, CURLOPT_CONNECTTIMEOUT
, curl_queue_connecttimeout
);
210 curl_easy_setopt(submission
, CURLOPT_TIMEOUT
, curl_queue_timeout
);
211 curl_easy_setopt(submission
, CURLOPT_DNS_CACHE_TIMEOUT
, 0);
212 curl_easy_setopt(submission
, CURLOPT_NOPROGRESS
, 1);
213 curl_easy_setopt(submission
, CURLOPT_NOSIGNAL
, 1);
214 code
= curl_easy_perform(submission
);
215 curl_easy_cleanup(submission
);
217 IgnoreNewlines(result
);
221 Log(llInfo
, "Number of submitted songs: %d", Song::SubmitQueue
.size());
223 std::ofstream
f(Config
.file_cache
.c_str(), std::ios::trunc
);
225 NowPlayingNotify
= s
.Data
&& !s
.isStream();
232 Log(llInfo
, "Error while submitting songs: %s", curl_easy_strerror(code
));
236 Log(llInfo
, "Audioscrobbler returned status %s", result
.c_str());
237 // BADSESSION or FAILED was returned, handshake needs resetting.
239 Log(llVerbose
, "Handshake reset");