remove CURLOPT_NOSIGNAL
[scrobby.git] / src / callback.cpp
blobb43eab70545672e5e35d97608e5a4c0760235ffd
1 /***************************************************************************
2 * Copyright (C) 2008 by Andrzej Rybczak *
3 * electricityispower@gmail.com *
4 * *
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. *
9 * *
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. *
14 * *
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>
22 #include <cstring>
24 #include "callback.h"
25 #include "misc.h"
26 #include "scrobby.h"
27 #include "song.h"
29 using std::string;
31 MPD::State old_state = MPD::psUnknown;
32 MPD::State current_state = MPD::psUnknown;
34 extern Handshake handshake;
35 extern MPD::Song s;
37 extern bool notify_about_now_playing;
39 void ScrobbyErrorCallback(MPD::Connection *, int, string errormessage, void *)
41 ignore_newlines(errormessage);
42 Log(llVerbose, "MPD: %s", errormessage.c_str());
45 void ScrobbyStatusChanged(MPD::Connection *Mpd, MPD::StatusChanges changed, void *)
47 if (changed.State)
49 old_state = current_state;
50 current_state = Mpd->GetState();
51 if (old_state == MPD::psStop && current_state == MPD::psPlay)
52 changed.SongID = 1;
54 if (changed.ElapsedTime)
56 static int crossfade;
57 if (Mpd->GetElapsedTime() == ((crossfade = Mpd->GetCrossfade()) ? crossfade : 0 ))
58 changed.SongID = 1;
59 s.Playback++;
61 if (changed.SongID || (old_state == MPD::psPlay && current_state == MPD::psStop))
63 s.Submit();
65 // in this case allow entering only once
66 if (old_state == MPD::psPlay && current_state == MPD::psStop)
67 old_state = MPD::psUnknown;
69 if (Mpd->GetElapsedTime() < Mpd->GetCrossfade()+10)
70 time(&s.StartTime);
72 if (current_state == MPD::psPlay || current_state == MPD::psPause)
74 s.SetData(Mpd->CurrentSong());
75 notify_about_now_playing = s.Data && !s.isStream();
78 if (notify_about_now_playing)
80 if (s.Data && (!s.Data->artist || !s.Data->title))
82 Log(llInfo, "Playing song with missing tags detected.");
84 else if (s.Data && s.Data->time <= 0)
86 Log(llInfo, "Playing song with unknown length detected.");
88 else if (s.Data && s.Data->artist && s.Data->title)
90 Log(llVerbose, "Playing song detected: %s - %s", s.Data->artist, s.Data->title);
92 if (handshake.status == "OK" && !handshake.nowplaying_url.empty())
94 Log(llInfo, "Sending now playing notification...");
96 else
98 Log(llInfo, "Notification not sent due to problem with connection.");
99 goto NOTIFICATION_FAILED;
102 std::ostringstream postdata;
103 string result, postdata_str;
104 CURLcode code;
106 char *c_artist = curl_easy_escape(0, s.Data->artist, 0);
107 char *c_title = curl_easy_escape(0, s.Data->title, 0);
108 char *c_album = s.Data->album ? curl_easy_escape(0, s.Data->album, 0) : NULL;
109 char *c_track = s.Data->track ? curl_easy_escape(0, s.Data->track, 0) : NULL;
111 postdata
112 << "s=" << handshake.session_id
113 << "&a=" << c_artist
114 << "&t=" << c_title
115 << "&b=";
116 if (c_album)
117 postdata << c_album;
118 postdata << "&l=" << s.Data->time
119 << "&n=";
120 if (c_track)
121 postdata << c_track;
122 postdata << "&m=";
124 curl_free(c_artist);
125 curl_free(c_title);
126 curl_free(c_album);
127 curl_free(c_track);
129 postdata_str = postdata.str();
131 Log(llVerbose, "URL: %s", handshake.nowplaying_url.c_str());
132 Log(llVerbose, "Post data: %s", postdata_str.c_str());
134 CURL *np_notification = curl_easy_init();
135 curl_easy_setopt(np_notification, CURLOPT_URL, handshake.nowplaying_url.c_str());
136 curl_easy_setopt(np_notification, CURLOPT_POST, 1);
137 curl_easy_setopt(np_notification, CURLOPT_POSTFIELDS, postdata_str.c_str());
138 curl_easy_setopt(np_notification, CURLOPT_WRITEFUNCTION, write_data);
139 curl_easy_setopt(np_notification, CURLOPT_WRITEDATA, &result);
140 curl_easy_setopt(np_notification, CURLOPT_CONNECTTIMEOUT, curl_timeout);
141 code = curl_easy_perform(np_notification);
142 curl_easy_cleanup(np_notification);
144 ignore_newlines(result);
146 if (result == "OK")
148 Log(llInfo, "Notification about currently playing song sent.");
150 else
152 if (result.empty())
154 Log(llInfo, "Error while sending notification: %s", curl_easy_strerror(code));
156 else
158 Log(llInfo, "Audioscrobbler returned status %s", result.c_str());
160 goto NOTIFICATION_FAILED;
163 if (0)
165 NOTIFICATION_FAILED:
167 handshake.Clear(); // handshake probably failed if we are here, so reset it
168 Log(llVerbose, "Handshake status reset");
170 notify_about_now_playing = 0;