#include <boost/algorithm/string.hpp>
#include <curl/curl.h>
#include <libcxml/cxml.h>
+#include <dcp/raw_convert.h>
#include "update.h"
#include "version.h"
#include "ui_signaller.h"
using std::min;
using std::string;
using std::stringstream;
-using boost::lexical_cast;
+using dcp::raw_convert;
+/** Singleton instance */
UpdateChecker* UpdateChecker::_instance = 0;
static size_t
return reinterpret_cast<UpdateChecker*>(user)->write_callback (data, size, nmemb);
}
+/** Construct an UpdateChecker. This sets things up and starts a thread to
+ * do the work.
+ */
UpdateChecker::UpdateChecker ()
: _buffer (new char[BUFFER_SIZE])
, _offset (0)
, _curl (0)
, _state (NOT_RUN)
- , _startup (true)
+ , _emits (0)
+ , _to_do (0)
{
curl_global_init (CURL_GLOBAL_ALL);
_curl = curl_easy_init ();
string const agent = "dcpomatic/" + string (dcpomatic_version);
curl_easy_setopt (_curl, CURLOPT_USERAGENT, agent.c_str ());
+
+ _thread = new boost::thread (boost::bind (&UpdateChecker::thread, this));
}
UpdateChecker::~UpdateChecker ()
{
+ /* We are not cleaning up our thread, but hey well */
+
curl_easy_cleanup (_curl);
curl_global_cleanup ();
delete[] _buffer;
}
+/** Start running the update check */
void
-UpdateChecker::run (bool startup)
-try
+UpdateChecker::run ()
{
- boost::mutex::scoped_lock lm (_single_thread_mutex);
-
- {
- boost::mutex::scoped_lock lm (_data_mutex);
- _startup = startup;
- }
-
- _offset = 0;
-
- int r = curl_easy_perform (_curl);
- if (r != CURLE_OK) {
- set_state (FAILED);
- return;
- }
-
- _buffer[_offset] = '\0';
- stringstream s;
- s << _buffer;
- cxml::Document doc ("Update");
- doc.read_stream (s);
-
- {
- boost::mutex::scoped_lock lm (_data_mutex);
- _stable = doc.string_child ("Stable");
- }
-
- string current = string (dcpomatic_version);
- bool current_pre = false;
- if (boost::algorithm::ends_with (current, "pre")) {
- current = current.substr (0, current.length() - 3);
- current_pre = true;
- }
-
- float current_float = lexical_cast<float> (current);
- if (current_pre) {
- current_float -= 0.005;
- }
+ boost::mutex::scoped_lock lm (_process_mutex);
+ _to_do++;
+ _condition.notify_one ();
+}
- if (current_float < lexical_cast<float> (_stable)) {
- set_state (YES);
- } else {
- set_state (NO);
+void
+UpdateChecker::thread ()
+{
+ while (true) {
+ /* Block until there is something to do */
+ boost::mutex::scoped_lock lock (_process_mutex);
+ while (_to_do == 0) {
+ _condition.wait (lock);
+ }
+ --_to_do;
+ lock.unlock ();
+
+ try {
+ _offset = 0;
+
+ /* Perform the request */
+
+ int r = curl_easy_perform (_curl);
+ if (r != CURLE_OK) {
+ set_state (FAILED);
+ return;
+ }
+
+ /* Parse the reply */
+
+ _buffer[_offset] = '\0';
+ stringstream s;
+ s << _buffer;
+ cxml::Document doc ("Update");
+ doc.read_stream (s);
+
+ {
+ boost::mutex::scoped_lock lm (_data_mutex);
+ _stable = doc.string_child ("Stable");
+ _test = doc.string_child ("Test");
+ }
+
+ string current = string (dcpomatic_version);
+ bool current_pre = false;
+ if (boost::algorithm::ends_with (current, "pre")) {
+ current = current.substr (0, current.length() - 3);
+ current_pre = true;
+ }
+
+ float current_float = raw_convert<float> (current);
+ if (current_pre) {
+ current_float -= 0.005;
+ }
+
+ if (current_float < raw_convert<float> (_stable)) {
+ set_state (YES);
+ } else {
+ set_state (NO);
+ }
+ } catch (...) {
+ set_state (FAILED);
+ }
}
-} catch (...) {
- set_state (FAILED);
}
-
+
size_t
UpdateChecker::write_callback (void* data, size_t size, size_t nmemb)
{
{
boost::mutex::scoped_lock lm (_data_mutex);
_state = s;
+ _emits++;
}
-
+
ui_signaller->emit (boost::bind (boost::ref (StateChanged)));
}