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>
31 MPD::State old_state
= MPD::psUnknown
;
32 MPD::State current_state
= MPD::psUnknown
;
34 extern Handshake handshake
;
37 extern pthread_mutex_t curl_lock
;
38 extern pthread_mutex_t handshake_lock
;
40 extern bool notify_about_now_playing
;
42 void ScrobbyErrorCallback(MPD::Connection
*, int, string errormessage
, void *)
44 ignore_newlines(errormessage
);
45 Log("MPD: " + errormessage
, llVerbose
);
48 void ScrobbyStatusChanged(MPD::Connection
*Mpd
, MPD::StatusChanges changed
, void *)
52 old_state
= current_state
;
53 current_state
= Mpd
->GetState();
54 if (old_state
== MPD::psStop
&& current_state
== MPD::psPlay
)
57 if (changed
.ElapsedTime
)
59 if (!Mpd
->GetElapsedTime())
63 if (changed
.SongID
|| (old_state
== MPD::psPlay
&& current_state
== MPD::psStop
))
67 // in this case allow entering only once
68 if (old_state
== MPD::psPlay
&& current_state
== MPD::psStop
)
69 old_state
= MPD::psUnknown
;
71 if (Mpd
->GetElapsedTime() < 5)
74 if (current_state
== MPD::psPlay
|| current_state
== MPD::psPause
)
77 s
.SetData(Mpd
->CurrentSong());
79 notify_about_now_playing
= !s
.isStream();
82 if (notify_about_now_playing
)
84 pthread_mutex_lock(&handshake_lock
);
85 if (s
.Data() && (!s
.Data()->artist
|| !s
.Data()->title
))
87 Log("Playing song with missing tags detected.", llInfo
);
89 else if (s
.Data() && s
.Data()->time
<= 0)
91 Log("Playing song with unknown length detected.", llInfo
);
93 else if (s
.Data() && s
.Data()->artist
&& s
.Data()->title
)
95 Log("Playing song detected: " + string(s
.Data()->artist
) + " - " + string(s
.Data()->title
), llVerbose
);
97 if (handshake
.status
== "OK" && !handshake
.nowplaying_url
.empty())
99 Log("Sending now playing notification...", llInfo
);
103 Log("Notification not sent due to problem with connection.", llInfo
);
104 goto NOTIFICATION_FAILED
;
107 string result
, postdata
;
110 pthread_mutex_lock(&curl_lock
);
111 CURL
*np_notification
= curl_easy_init();
113 char *c_artist
= curl_easy_escape(np_notification
, s
.Data()->artist
, 0);
114 char *c_title
= curl_easy_escape(np_notification
, s
.Data()->title
, 0);
115 char *c_album
= s
.Data()->album
? curl_easy_escape(np_notification
, s
.Data()->album
, 0) : NULL
;
116 char *c_track
= s
.Data()->track
? curl_easy_escape(np_notification
, s
.Data()->track
, 0) : NULL
;
119 postdata
+= handshake
.session_id
;
121 postdata
+= c_artist
;
128 postdata
+= IntoStr(s
.Data()->time
);
139 Log("URL: " + handshake
.nowplaying_url
, llVerbose
);
140 Log("Post data: " + postdata
, llVerbose
);
142 curl_easy_setopt(np_notification
, CURLOPT_URL
, handshake
.nowplaying_url
.c_str());
143 curl_easy_setopt(np_notification
, CURLOPT_POST
, 1);
144 curl_easy_setopt(np_notification
, CURLOPT_POSTFIELDS
, postdata
.c_str());
145 curl_easy_setopt(np_notification
, CURLOPT_WRITEFUNCTION
, write_data
);
146 curl_easy_setopt(np_notification
, CURLOPT_WRITEDATA
, &result
);
147 curl_easy_setopt(np_notification
, CURLOPT_CONNECTTIMEOUT
, curl_timeout
);
148 code
= curl_easy_perform(np_notification
);
149 curl_easy_cleanup(np_notification
);
150 pthread_mutex_unlock(&curl_lock
);
152 ignore_newlines(result
);
156 Log("Notification about currently playing song sent.", llInfo
);
162 Log("Error while sending notification: " + string(curl_easy_strerror(code
)), llInfo
);
166 Log("Audioscrobbler returned status " + result
, llInfo
);
168 goto NOTIFICATION_FAILED
;
175 handshake
.Clear(); // handshake probably failed if we are here, so reset it
176 Log("Handshake status reset", llVerbose
);
178 pthread_mutex_unlock(&handshake_lock
);
179 notify_about_now_playing
= 0;