Fix problem with multiple timespan export. Most probably originated in r13305.
[ardour.git] / libs / ardour / callback.cc
1 /*
2     Copyright (C) 2012 Paul Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <iostream>
21 #include <string>
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <cstdlib>
28 #include <sys/utsname.h>
29 #include <curl/curl.h>
30
31 #include <glibmm/fileutils.h>
32 #include <glibmm/miscutils.h>
33
34 #include "pbd/compose.h"
35 #include "pbd/strsplit.h"
36 #include "pbd/convert.h"
37
38 #include "ardour/filesystem_paths.h"
39
40 using namespace std;
41
42 #define PING_URL "http://ardour.org/pingback/versioncheck"
43 #define OFF_THE_HOOK ".offthehook"
44
45 static size_t
46 curl_write_data (char *bufptr, size_t size, size_t nitems, void *ptr)
47 {
48         /* we know its a string */
49
50         string* sptr = (string*) ptr;
51
52         for (size_t i = 0; i < nitems; ++i) {
53                 for (size_t n = 0; n < size; ++n) {
54                         if (*bufptr == '\n') {
55                                 break;
56                         }
57
58                         (*sptr) += *bufptr++;
59                 }
60         }
61
62         return size * nitems;
63 }
64
65 static string
66 watermark ()
67 {
68         return string();
69 }
70
71 void
72 block_mothership ()
73 {
74         string hangup = Glib::build_filename (ARDOUR::user_config_directory(), OFF_THE_HOOK);
75         int fd;
76         if ((fd = ::open (hangup.c_str(), O_RDWR|O_CREAT, 0600)) >= 0) {
77                 close (fd);
78         }
79 }
80
81 void
82 unblock_mothership ()
83 {
84         string hangup = Glib::build_filename (ARDOUR::user_config_directory(), OFF_THE_HOOK);
85         ::unlink (hangup.c_str());
86 }
87
88 bool
89 mothership_blocked ()
90 {
91         string hangup = Glib::build_filename (ARDOUR::user_config_directory(), OFF_THE_HOOK);
92         return Glib::file_test (hangup, Glib::FILE_TEST_EXISTS);
93 }
94
95 void
96 call_the_mothership (const string& version)
97 {
98         /* check if the user says never to do this
99          */
100
101         if (mothership_blocked()) {
102                 return;
103         }
104
105         CURL* c;
106         struct utsname utb;
107         std::string versionstr;
108
109         if (uname (&utb)) {
110                 return;
111         }
112
113         curl_global_init (CURL_GLOBAL_NOTHING);
114
115         c = curl_easy_init ();
116
117         string data;
118         string wm;
119
120         data = string_compose ("version=%1&platform=%2 %3 %4", version, utb.sysname, utb.release, utb.machine);
121
122         wm = watermark();
123         if (!wm.empty()) {
124                 data += string_compose ("&watermark=%1", wm);
125         }
126
127         curl_easy_setopt(c, CURLOPT_POSTFIELDS, data.c_str());
128         curl_easy_setopt(c, CURLOPT_URL, PING_URL);
129         curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, curl_write_data);
130         curl_easy_setopt(c, CURLOPT_WRITEDATA, &versionstr);
131
132         std::cerr << "Callback to ardour.org ...\n";
133
134         char errbuf[CURL_ERROR_SIZE];
135         curl_easy_setopt(c, CURLOPT_ERRORBUFFER, errbuf);
136
137         if (curl_easy_perform (c) == 0) {
138                 cerr << "Current release is " << versionstr << endl;
139
140                 vector<string> ours;
141                 vector<string> current;
142
143                 split (version, ours, '.');
144                 split (versionstr, current, '.');
145
146                 if (ours.size() == 3 && current.size() == 3) {
147
148                         int ours_n[3];
149                         int current_n[3];
150
151                         using namespace PBD;
152
153                         ours_n[0] = atoi (ours[0]);
154                         ours_n[1] = atoi (ours[1]);
155                         ours_n[2] = atoi (ours[2]);
156
157                         current_n[0] = atoi (current[0]);
158                         current_n[1] = atoi (current[1]);
159                         current_n[2] = atoi (current[2]);
160
161                         if (ours_n[0] < current_n[0] ||
162                             ((ours_n[0] == current_n[0]) && (ours_n[1] < current_n[1])) ||
163                             ((ours_n[0] == current_n[0]) && (ours_n[1] == current_n[1]) && (ours_n[2] < current_n[2]))) {
164                                 cerr << "TOO OLD\n";
165                         } else {
166                                 cerr << "CURRENT\n";
167                         }
168                 } else {
169                         cerr << "Unusual local version: " << version << endl;
170                 }
171         }
172
173         curl_easy_cleanup (c);
174 }