From 95faa6568854b5f861db07e9b8697169aaceec3c Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 7 Jan 2014 13:53:28 +0000 Subject: Add unfinished check-for-updates. Bump ffmpeg to get windows build fix. --- cscript | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'cscript') diff --git a/cscript b/cscript index 36cddc79e..b164bc422 100644 --- a/cscript +++ b/cscript @@ -114,8 +114,8 @@ def make_control(version, bits, filename): print >>f,' digital projectors.' def dependencies(target): - return (('ffmpeg-cdist', 'a629ea68a20d990b4e61c16067e91563d8d08f50'), - ('libdcp', 'v0.92')) + return (('ffmpeg-cdist', '5ac3a6af077c10f07c31954c372a8f29e4e18e2a'), + ('libdcp', 'cc8c14b765038405e75d7436cf0da3d56b61063b')) def build(target): cmd = './waf configure --prefix=%s' % target.work_dir_cscript() -- cgit v1.2.3 From 4983b57d7ccba4ea0b393cf3a40043c1ed5c6b77 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 7 Jan 2014 15:06:15 +0000 Subject: Basic dialog reporting of manual update checks. --- cscript | 2 +- src/lib/update.cc | 112 +++++++++++++++++++++++++++++++++++---------- src/lib/update.h | 48 +++++++++++++++++-- src/tools/dcpomatic.cc | 40 +++++++++++++--- src/tools/update_dialog.cc | 0 src/tools/update_dialog.h | 31 +++++++++++++ 6 files changed, 198 insertions(+), 35 deletions(-) create mode 100644 src/tools/update_dialog.cc create mode 100644 src/tools/update_dialog.h (limited to 'cscript') diff --git a/cscript b/cscript index b164bc422..0d6336b22 100644 --- a/cscript +++ b/cscript @@ -115,7 +115,7 @@ def make_control(version, bits, filename): def dependencies(target): return (('ffmpeg-cdist', '5ac3a6af077c10f07c31954c372a8f29e4e18e2a'), - ('libdcp', 'cc8c14b765038405e75d7436cf0da3d56b61063b')) + ('libdcp', '3a148fab61d2b23379589a4f0f256c21950742b8')) def build(target): cmd = './waf configure --prefix=%s' % target.work_dir_cscript() diff --git a/src/lib/update.cc b/src/lib/update.cc index 6e9d1169a..d68979e60 100644 --- a/src/lib/update.cc +++ b/src/lib/update.cc @@ -19,10 +19,12 @@ #include #include +#include #include #include #include "update.h" #include "version.h" +#include "ui_signaller.h" #define BUFFER_SIZE 1024 @@ -30,59 +32,121 @@ using std::cout; using std::min; using std::string; using std::stringstream; +using boost::lexical_cast; + +UpdateChecker* UpdateChecker::_instance = 0; + +static size_t +write_callback_wrapper (void* data, size_t size, size_t nmemb, void* user) +{ + return reinterpret_cast(user)->write_callback (data, size, nmemb); +} UpdateChecker::UpdateChecker () : _buffer (new char[BUFFER_SIZE]) , _offset (0) + , _curl (0) + , _state (NOT_RUN) + , _startup (true) { + curl_global_init (CURL_GLOBAL_ALL); + _curl = curl_easy_init (); + + curl_easy_setopt (_curl, CURLOPT_URL, "http://dcpomatic.com/update"); + curl_easy_setopt (_curl, CURLOPT_WRITEFUNCTION, write_callback_wrapper); + curl_easy_setopt (_curl, CURLOPT_WRITEDATA, this); + curl_easy_setopt (_curl, CURLOPT_TIMEOUT, 20); + string const agent = "dcpomatic/" + string (dcpomatic_version); + curl_easy_setopt (_curl, CURLOPT_USERAGENT, agent.c_str ()); } UpdateChecker::~UpdateChecker () { + curl_easy_cleanup (_curl); + curl_global_cleanup (); delete[] _buffer; } -static size_t -write_callback_wrapper (void* data, size_t size, size_t nmemb, void* user) +void +UpdateChecker::run (bool startup) +try { - return reinterpret_cast(user)->write_callback (data, size, nmemb); -} + boost::mutex::scoped_lock lm (_single_thread_mutex); -UpdateChecker::Result -UpdateChecker::run () -{ - curl_global_init (CURL_GLOBAL_ALL); - CURL* curl = curl_easy_init (); - if (!curl) { - return MAYBE; + { + boost::mutex::scoped_lock lm (_data_mutex); + _startup = startup; } - - curl_easy_setopt (curl, CURLOPT_URL, "http://dcpomatic.com/update.php"); - curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, write_callback_wrapper); - curl_easy_setopt (curl, CURLOPT_WRITEDATA, this); - string const agent = "dcpomatic/" + string (dcpomatic_version); - curl_easy_setopt (curl, CURLOPT_USERAGENT, agent.c_str ()); - int r = curl_easy_perform (curl); + + _offset = 0; + + int r = curl_easy_perform (_curl); if (r != CURLE_OK) { - return MAYBE; + set_state (FAILED); + return; } - - _buffer[BUFFER_SIZE-1] = '\0'; + + _buffer[_offset] = '\0'; stringstream s; s << _buffer; cxml::Document doc ("Update"); doc.read_stream (s); - cout << doc.string_child ("Stable") << "\n"; - return YES; + { + 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 (current); + if (current_pre) { + current_float -= 0.005; + } + + if (current_float < lexical_cast (_stable)) { + set_state (YES); + } else { + set_state (NO); + } +} catch (...) { + set_state (FAILED); } size_t UpdateChecker::write_callback (void* data, size_t size, size_t nmemb) { - size_t const t = min (size * nmemb, size_t (BUFFER_SIZE - _offset)); + size_t const t = min (size * nmemb, size_t (BUFFER_SIZE - _offset - 1)); memcpy (_buffer + _offset, data, t); _offset += t; return t; } + +void +UpdateChecker::set_state (State s) +{ + { + boost::mutex::scoped_lock lm (_data_mutex); + _state = s; + } + + ui_signaller->emit (boost::bind (boost::ref (StateChanged))); +} + +UpdateChecker * +UpdateChecker::instance () +{ + if (!_instance) { + _instance = new UpdateChecker (); + } + + return _instance; +} + + diff --git a/src/lib/update.h b/src/lib/update.h index 2063dd484..b879e9026 100644 --- a/src/lib/update.h +++ b/src/lib/update.h @@ -17,23 +17,63 @@ */ +#include +#include +#include + class UpdateChecker { public: UpdateChecker (); ~UpdateChecker (); - enum Result { + void run (bool); + + enum State { YES, - MAYBE, - NO + FAILED, + NO, + NOT_RUN }; - Result run (); + State state () { + boost::mutex::scoped_lock lm (_data_mutex); + return _state; + } + + std::string stable () { + boost::mutex::scoped_lock lm (_data_mutex); + return _stable; + } + + /** @return true if this check was run at startup, otherwise false */ + bool startup () const { + boost::mutex::scoped_lock lm (_data_mutex); + return _startup; + } size_t write_callback (void *, size_t, size_t); + boost::signals2::signal StateChanged; + + static UpdateChecker* instance (); + private: + static UpdateChecker* _instance; + + void set_state (State); + char* _buffer; int _offset; + CURL* _curl; + + /** mutex to protect _state, _stable and _startup */ + mutable boost::mutex _data_mutex; + State _state; + std::string _stable; + /** true if this check was run at startup, otherwise false */ + bool _startup; + + /** mutex to ensure that only one query runs at once */ + boost::mutex _single_thread_mutex; }; diff --git a/src/tools/dcpomatic.cc b/src/tools/dcpomatic.cc index b69385e24..fcb47f2d1 100644 --- a/src/tools/dcpomatic.cc +++ b/src/tools/dcpomatic.cc @@ -536,8 +536,7 @@ private: void tools_check_for_updates () { - UpdateChecker c; - c.run (); + UpdateChecker::instance()->run (false); } void help_about () @@ -646,10 +645,12 @@ class App : public wxApp film->set_name (boost::filesystem::path (film_to_create).filename().generic_string ()); } - Frame* f = new Frame (_("DCP-o-matic")); - SetTopWindow (f); - f->Maximize (); - f->Show (); + _frame = new Frame (_("DCP-o-matic")); + SetTopWindow (_frame); + _frame->Maximize (); + _frame->Show (); + + UpdateChecker::instance()->StateChanged.connect (boost::bind (&App::update_checker_state_changed, this)); ui_signaller = new wxUISignaller (this); Bind (wxEVT_IDLE, boost::bind (&App::idle, this)); @@ -704,6 +705,33 @@ class App : public wxApp } } + void update_checker_state_changed () + { + switch (UpdateChecker::instance()->state ()) { + case UpdateChecker::YES: + error_dialog ( + _frame, + wxString::Format ( + _("A new version %s of DCP-o-matic is available from http://dcpomatic.com/download"), + std_to_wx (UpdateChecker::instance()->stable()).wx_str () + ) + ); + break; + case UpdateChecker::NO: + if (!UpdateChecker::instance()->startup ()) { + error_dialog (_frame, _("There are no new versions of DCP-o-matic available.")); + } + break; + case UpdateChecker::FAILED: + if (!UpdateChecker::instance()->startup ()) { + error_dialog (_frame, _("The DCP-o-matic download server could not be contacted.")); + } + default: + break; + } + } + + wxFrame* _frame; shared_ptr _timer; }; diff --git a/src/tools/update_dialog.cc b/src/tools/update_dialog.cc new file mode 100644 index 000000000..e69de29bb diff --git a/src/tools/update_dialog.h b/src/tools/update_dialog.h new file mode 100644 index 000000000..8b499ebcc --- /dev/null +++ b/src/tools/update_dialog.h @@ -0,0 +1,31 @@ +/* + Copyright (C) 2014 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +class UpdateDialog +{ +public: + UpdateDialog (wxWindow *); + +private: + wxGauge* _gauge; + wxStaticText* _message; + boost::thread* _thread; + boost::optional _result; + std::string _stable; +}; -- cgit v1.2.3 From 9e9a394e4ddb953eada9b8228c1e53be22c09c49 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 7 Jan 2014 22:32:31 +0000 Subject: Fix cscript. --- cscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cscript') diff --git a/cscript b/cscript index 0d6336b22..5182500b1 100644 --- a/cscript +++ b/cscript @@ -117,7 +117,7 @@ def dependencies(target): return (('ffmpeg-cdist', '5ac3a6af077c10f07c31954c372a8f29e4e18e2a'), ('libdcp', '3a148fab61d2b23379589a4f0f256c21950742b8')) -def build(target): +def build(target, options): cmd = './waf configure --prefix=%s' % target.work_dir_cscript() if target.platform == 'windows': cmd += ' --target-windows' -- cgit v1.2.3 From 458f875d657e380c27347acf79d207f7c2df98ca Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 8 Jan 2014 10:06:49 +0000 Subject: Bump libdcp for better FileError error numbers. --- cscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cscript') diff --git a/cscript b/cscript index 5182500b1..91939f1a0 100644 --- a/cscript +++ b/cscript @@ -115,7 +115,7 @@ def make_control(version, bits, filename): def dependencies(target): return (('ffmpeg-cdist', '5ac3a6af077c10f07c31954c372a8f29e4e18e2a'), - ('libdcp', '3a148fab61d2b23379589a4f0f256c21950742b8')) + ('libdcp', '83591a4390db550a7d1495b9699c62315e2d7710')) def build(target, options): cmd = './waf configure --prefix=%s' % target.work_dir_cscript() -- cgit v1.2.3 From 0581cdaad9ca5ceeb67afdd6db8bc72661214b96 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 8 Jan 2014 11:27:16 +0000 Subject: Bump libdcp version to fix build. --- cscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cscript') diff --git a/cscript b/cscript index 91939f1a0..5f36d9622 100644 --- a/cscript +++ b/cscript @@ -115,7 +115,7 @@ def make_control(version, bits, filename): def dependencies(target): return (('ffmpeg-cdist', '5ac3a6af077c10f07c31954c372a8f29e4e18e2a'), - ('libdcp', '83591a4390db550a7d1495b9699c62315e2d7710')) + ('libdcp', '8803a19c6901ab3c3ff85c964343f08458e0824e')) def build(target, options): cmd = './waf configure --prefix=%s' % target.work_dir_cscript() -- cgit v1.2.3