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;
73 void MPD::Song::SetStartTime()
75 itsStartTime
= time(NULL
);
78 void MPD::Song::Submit()
85 itsSong
->time
= itsNoticedPlayback
;
88 pthread_mutex_lock(&handshake_lock
);
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
;
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
;
111 postdata
+= handshake
.session_id
;
112 postdata
+= "&a[0]=";
113 postdata
+= c_artist
;
114 postdata
+= "&t[0]=";
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]=";
125 postdata
+= "&n[0]=";
128 postdata
+= "&m[0]=";
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
);
152 Log(llInfo
, "Song submitted.");
158 Log(llInfo
, "Error while submitting song: %s", curl_easy_strerror(code
));
162 Log(llInfo
, "Audioscrobbler returned status %s", result
.c_str());
164 goto SUBMISSION_FAILED
;
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");
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
;
193 cache
+= IntoStr(itsStartTime
);
203 cache
+= IntoStr(itsSong
->time
);
218 Log(llVerbose
, "Metadata: %s", cache
.c_str());
226 SongsQueue
.push_back(cache
);
227 Log(llInfo
, "Song cached.");
229 pthread_mutex_unlock(&handshake_lock
);
233 bool MPD::Song::isStream()
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
)
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.");
266 else if (itsNoticedPlayback
< 4*60 && itsNoticedPlayback
< itsSong
->time
/2)
268 Log(llInfo
, "Noticed playback was too short, not submitting.");