1 /***************************************************************************
2 * Copyright (C) 2008 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 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
21 #include <curl/curl.h>
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),
41 itsNoticedPlayback(0),
49 mpd_freeSong(itsSong
);
52 void MPD::Song::Clear()
55 mpd_freeSong(itsSong
);
58 itsNoticedPlayback
= 0;
62 void MPD::Song::SetData(mpd_Song
*song
)
67 mpd_freeSong(itsSong
);
69 itsIsStream
= strncmp("http://", itsSong
->file
, 7) == 0;
72 void MPD::Song::SetStartTime()
74 itsStartTime
= time(NULL
);
77 void MPD::Song::Submit()
84 itsSong
->time
= itsNoticedPlayback
;
87 pthread_mutex_lock(&handshake_lock
);
90 if (handshake
.status
!= "OK" || handshake
.submission_url
.empty())
92 Log(llInfo
, "Problems with handshake status, queue song at position %d...", SongsQueue
.size());
93 goto SUBMISSION_FAILED
;
96 Log(llInfo
, "Submitting song...");
98 string result
, postdata
;
101 pthread_mutex_lock(&curl_lock
);
102 CURL
*submission
= curl_easy_init();
104 char *c_artist
= curl_easy_escape(submission
, itsSong
->artist
, 0);
105 char *c_title
= curl_easy_escape(submission
, itsSong
->title
, 0);
106 char *c_album
= itsSong
->album
? curl_easy_escape(submission
, itsSong
->album
, 0) : NULL
;
107 char *c_track
= itsSong
->track
? curl_easy_escape(submission
, itsSong
->track
, 0) : NULL
;
110 postdata
+= handshake
.session_id
;
111 postdata
+= "&a[0]=";
112 postdata
+= c_artist
;
113 postdata
+= "&t[0]=";
115 postdata
+= "&i[0]=";
116 postdata
+= IntoStr(itsStartTime
);
117 postdata
+= "&o[0]=P";
118 postdata
+= "&r[0]=";
119 postdata
+= "&l[0]=";
120 postdata
+= IntoStr(itsSong
->time
);
121 postdata
+= "&b[0]=";
124 postdata
+= "&n[0]=";
127 postdata
+= "&m[0]=";
134 Log(llVerbose
, "URL: %s", handshake
.submission_url
.c_str());
135 Log(llVerbose
, "Post data: %s", postdata
.c_str());
137 curl_easy_setopt(submission
, CURLOPT_URL
, handshake
.submission_url
.c_str());
138 curl_easy_setopt(submission
, CURLOPT_POST
, 1);
139 curl_easy_setopt(submission
, CURLOPT_POSTFIELDS
, postdata
.c_str());
140 curl_easy_setopt(submission
, CURLOPT_WRITEFUNCTION
, write_data
);
141 curl_easy_setopt(submission
, CURLOPT_WRITEDATA
, &result
);
142 curl_easy_setopt(submission
, CURLOPT_CONNECTTIMEOUT
, curl_timeout
);
143 code
= curl_easy_perform(submission
);
144 curl_easy_cleanup(submission
);
145 pthread_mutex_unlock(&curl_lock
);
147 ignore_newlines(result
);
151 Log(llInfo
, "Song submitted.");
157 Log(llInfo
, "Error while submitting song: %s", curl_easy_strerror(code
));
161 Log(llInfo
, "Audioscrobbler returned status %s", result
.c_str());
163 goto SUBMISSION_FAILED
;
168 SUBMISSION_FAILED
: // so we cache not submitted song
170 handshake
.Clear(); // handshake probably failed if we are here, so reset it
171 Log(llVerbose
, "Handshake status reset");
174 string offset
= IntoStr(SongsQueue
.size());
176 char *c_artist
= curl_easy_escape(0, itsSong
->artist
, 0);
177 char *c_title
= curl_easy_escape(0, itsSong
->title
, 0);
178 char *c_album
= itsSong
->album
? curl_easy_escape(0, itsSong
->album
, 0) : NULL
;
179 char *c_track
= itsSong
->track
? curl_easy_escape(0, itsSong
->track
, 0) : NULL
;
192 cache
+= IntoStr(itsStartTime
);
202 cache
+= IntoStr(itsSong
->time
);
217 Log(llVerbose
, "Metadata: %s", cache
.c_str());
225 SongsQueue
.push_back(cache
);
226 Log(llInfo
, "Song cached.");
228 pthread_mutex_unlock(&handshake_lock
);
232 bool MPD::Song::isStream() const
237 int & MPD::Song::Playback()
239 return itsNoticedPlayback
;
242 const mpd_Song
*& MPD::Song::Data() const
244 return (const mpd_Song
*&)itsSong
;
247 bool MPD::Song::canBeSubmitted()
249 if (!itsStartTime
|| itsSong
->time
< 30 || !itsSong
->artist
|| !itsSong
->title
)
253 Log(llInfo
, "Song's start time isn't known, not submitting.");
255 else if (itsSong
->time
< 30)
257 Log(llInfo
, "Song's length is too short, not submitting.");
259 else if (!itsSong
->artist
|| !itsSong
->title
)
261 Log(llInfo
, "Song has missing tags, not submitting.");
265 else if (itsNoticedPlayback
< 4*60 && itsNoticedPlayback
< itsSong
->time
/2)
267 Log(llInfo
, "Noticed playback was too short, not submitting.");