Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/xs/src
diff options
context:
space:
mode:
authorVojtech Kral <vojtech@kral.hk>2018-04-04 12:18:22 +0300
committerbubnikv <bubnikv@gmail.com>2018-04-04 12:18:22 +0300
commitb0840065ed84f4006207b38de3c9c6a5e15a7071 (patch)
tree3da655b0f6ca247d0f567831a978a73c68246978 /xs/src
parent00324a14b84f47cc6ae1dc92e6582ee6b6171e03 (diff)
Octoprint (#804)
* Octoprint progress dialog * Fix curl version on Windows
Diffstat (limited to 'xs/src')
-rw-r--r--xs/src/slic3r/Utils/Http.cpp73
-rw-r--r--xs/src/slic3r/Utils/Http.hpp17
-rw-r--r--xs/src/slic3r/Utils/OctoPrint.cpp66
-rw-r--r--xs/src/slic3r/Utils/OctoPrint.hpp2
4 files changed, 124 insertions, 34 deletions
diff --git a/xs/src/slic3r/Utils/Http.cpp b/xs/src/slic3r/Utils/Http.cpp
index de28904e2..0826284d8 100644
--- a/xs/src/slic3r/Utils/Http.cpp
+++ b/xs/src/slic3r/Utils/Http.cpp
@@ -36,16 +36,20 @@ struct Http::priv
::curl_slist *headerlist;
std::string buffer;
size_t limit;
+ bool cancel;
std::thread io_thread;
Http::CompleteFn completefn;
Http::ErrorFn errorfn;
+ Http::ProgressFn progressfn;
priv(const std::string &url);
~priv();
static bool ca_file_supported(::CURL *curl);
static size_t writecb(void *data, size_t size, size_t nmemb, void *userp);
+ static int xfercb(void *userp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow);
+ static int xfercb_legacy(void *userp, double dltotal, double dlnow, double ultotal, double ulnow);
std::string curl_error(CURLcode curlcode);
std::string body_size_error();
void http_perform();
@@ -55,7 +59,8 @@ Http::priv::priv(const std::string &url) :
curl(::curl_easy_init()),
form(nullptr),
form_end(nullptr),
- headerlist(nullptr)
+ headerlist(nullptr),
+ cancel(false)
{
if (curl == nullptr) {
throw std::runtime_error(std::string("Could not construct Curl object"));
@@ -112,6 +117,24 @@ size_t Http::priv::writecb(void *data, size_t size, size_t nmemb, void *userp)
return realsize;
}
+int Http::priv::xfercb(void *userp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
+{
+ auto self = static_cast<priv*>(userp);
+ bool cb_cancel = false;
+
+ if (self->progressfn) {
+ Progress progress(dltotal, dlnow, ultotal, ulnow);
+ self->progressfn(progress, cb_cancel);
+ }
+
+ return self->cancel || cb_cancel;
+}
+
+int Http::priv::xfercb_legacy(void *userp, double dltotal, double dlnow, double ultotal, double ulnow)
+{
+ return xfercb(userp, dltotal, dlnow, ultotal, ulnow);
+}
+
std::string Http::priv::curl_error(CURLcode curlcode)
{
return (boost::format("%1% (%2%)")
@@ -132,6 +155,16 @@ void Http::priv::http_perform()
::curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writecb);
::curl_easy_setopt(curl, CURLOPT_WRITEDATA, static_cast<void*>(this));
+ ::curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
+#if LIBCURL_VERSION_MAJOR >= 7 && LIBCURL_VERSION_MINOR >= 32
+ ::curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xfercb);
+ ::curl_easy_setopt(curl, CURLOPT_XFERINFODATA, static_cast<void*>(this));
+ (void)xfercb_legacy; // prevent unused function warning
+#else
+ ::curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, xfercb);
+ ::curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, static_cast<void*>(this));
+#endif
+
#ifndef NDEBUG
::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
#endif
@@ -149,16 +182,16 @@ void Http::priv::http_perform()
::curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_status);
if (res != CURLE_OK) {
- std::string error;
- if (res == CURLE_WRITE_ERROR) {
- error = std::move(body_size_error());
+ if (res == CURLE_ABORTED_BY_CALLBACK) {
+ Progress dummyprogress(0, 0, 0, 0);
+ bool cancel = true;
+ if (progressfn) { progressfn(dummyprogress, cancel); }
+ }
+ else if (res == CURLE_WRITE_ERROR) {
+ if (errorfn) { errorfn(std::move(buffer), std::move(body_size_error()), http_status); }
} else {
- error = std::move(curl_error(res));
+ if (errorfn) { errorfn(std::move(buffer), std::move(curl_error(res)), http_status); }
};
-
- if (errorfn) {
- errorfn(std::move(buffer), std::move(error), http_status);
- }
} else {
if (completefn) {
completefn(std::move(buffer), http_status);
@@ -258,6 +291,12 @@ Http& Http::on_error(ErrorFn fn)
return *this;
}
+Http& Http::on_progress(ProgressFn fn)
+{
+ if (p) { p->progressfn = std::move(fn); }
+ return *this;
+}
+
Http::Ptr Http::perform()
{
auto self = std::make_shared<Http>(std::move(*this));
@@ -277,6 +316,11 @@ void Http::perform_sync()
if (p) { p->http_perform(); }
}
+void Http::cancel()
+{
+ if (p) { p->cancel = true; }
+}
+
Http Http::get(std::string url)
{
return std::move(Http{std::move(url)});
@@ -297,5 +341,16 @@ bool Http::ca_file_supported()
return res;
}
+std::ostream& operator<<(std::ostream &os, const Http::Progress &progress)
+{
+ os << "Http::Progress("
+ << "dltotal = " << progress.dltotal
+ << ", dlnow = " << progress.dlnow
+ << ", ultotal = " << progress.ultotal
+ << ", ulnow = " << progress.ulnow
+ << ")";
+ return os;
+}
+
}
diff --git a/xs/src/slic3r/Utils/Http.hpp b/xs/src/slic3r/Utils/Http.hpp
index 6ac5fcce1..7ed8196e6 100644
--- a/xs/src/slic3r/Utils/Http.hpp
+++ b/xs/src/slic3r/Utils/Http.hpp
@@ -14,9 +14,22 @@ class Http : public std::enable_shared_from_this<Http> {
private:
struct priv;
public:
+ struct Progress
+ {
+ size_t dltotal;
+ size_t dlnow;
+ size_t ultotal;
+ size_t ulnow;
+
+ Progress(size_t dltotal, size_t dlnow, size_t ultotal, size_t ulnow) :
+ dltotal(dltotal), dlnow(dlnow), ultotal(ultotal), ulnow(ulnow)
+ {}
+ };
+
typedef std::shared_ptr<Http> Ptr;
typedef std::function<void(std::string /* body */, unsigned /* http_status */)> CompleteFn;
typedef std::function<void(std::string /* body */, std::string /* error */, unsigned /* http_status */)> ErrorFn;
+ typedef std::function<void(Progress, bool& /* cancel */)> ProgressFn;
Http(Http &&other);
@@ -37,9 +50,11 @@ public:
Http& on_complete(CompleteFn fn);
Http& on_error(ErrorFn fn);
+ Http& on_progress(ProgressFn fn);
Ptr perform();
void perform_sync();
+ void cancel();
static bool ca_file_supported();
private:
@@ -48,6 +63,8 @@ private:
std::unique_ptr<priv> p;
};
+std::ostream& operator<<(std::ostream &, const Http::Progress &);
+
}
diff --git a/xs/src/slic3r/Utils/OctoPrint.cpp b/xs/src/slic3r/Utils/OctoPrint.cpp
index 5bf51f470..e63a16c38 100644
--- a/xs/src/slic3r/Utils/OctoPrint.cpp
+++ b/xs/src/slic3r/Utils/OctoPrint.cpp
@@ -1,10 +1,11 @@
#include "OctoPrint.hpp"
-#include <iostream>
+#include <algorithm>
#include <boost/format.hpp>
#include <wx/frame.h>
#include <wx/event.h>
+#include <wx/progdlg.h>
#include "libslic3r/PrintConfig.hpp"
#include "slic3r/GUI/GUI.hpp"
@@ -39,36 +40,53 @@ bool OctoPrint::test(wxString &msg) const
return res;
}
-void OctoPrint::send_gcode(int windowId, int completeEvt, int errorEvt, const std::string &filename, bool print) const
+bool OctoPrint::send_gcode(const std::string &filename, bool print) const
{
+ enum { PROGRESS_RANGE = 1000 };
+
+ const auto errortitle = _(L("Error while uploading to the OctoPrint server"));
+
+ wxProgressDialog progress_dialog(
+ _(L("OctoPrint upload")),
+ _(L("Sending G-code file to the OctoPrint server...")),
+ PROGRESS_RANGE, nullptr, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);
+ progress_dialog.Pulse();
+
+ wxString test_msg;
+ if (!test(test_msg)) {
+ auto errormsg = wxString::Format("%s: %s", errortitle, test_msg);
+ GUI::show_error(&progress_dialog, std::move(errormsg));
+ return false;
+ }
+
+ bool res = true;
+
auto http = Http::post(std::move(make_url("api/files/local")));
set_auth(http);
http.form_add("print", print ? "true" : "false")
.form_add_file("file", filename)
- .on_complete([=](std::string body, unsigned status) {
- wxWindow *window = wxWindow::FindWindowById(windowId);
- if (window == nullptr) { return; }
-
- wxCommandEvent* evt = new wxCommandEvent(completeEvt);
- evt->SetString(_(L("G-code file successfully uploaded to the OctoPrint server")));
- evt->SetInt(100);
- wxQueueEvent(window, evt);
+ .on_complete([&](std::string body, unsigned status) {
+ progress_dialog.Update(PROGRESS_RANGE);
+ })
+ .on_error([&](std::string body, std::string error, unsigned status) {
+ auto errormsg = wxString::Format("%s: %s", errortitle, format_error(error, status));
+ GUI::show_error(&progress_dialog, std::move(errormsg));
+ res = false;
})
- .on_error([=](std::string body, std::string error, unsigned status) {
- wxWindow *window = wxWindow::FindWindowById(windowId);
- if (window == nullptr) { return; }
-
- wxCommandEvent* evt_complete = new wxCommandEvent(completeEvt);
- evt_complete->SetInt(100);
- wxQueueEvent(window, evt_complete);
-
- wxCommandEvent* evt_error = new wxCommandEvent(errorEvt);
- evt_error->SetString(wxString::Format("%s: %s",
- _(L("Error while uploading to the OctoPrint server")),
- format_error(error, status)));
- wxQueueEvent(window, evt_error);
+ .on_progress([&](Http::Progress progress, bool &cancel) {
+ if (cancel) {
+ // Upload was canceled
+ res = false;
+ } else if (progress.ultotal > 0) {
+ int value = PROGRESS_RANGE * progress.ulnow / progress.ultotal;
+ cancel = !progress_dialog.Update(std::min(value, PROGRESS_RANGE - 1)); // Cap the value to prevent premature dialog closing
+ } else {
+ cancel = !progress_dialog.Pulse();
+ }
})
- .perform();
+ .perform_sync();
+
+ return res;
}
void OctoPrint::set_auth(Http &http) const
diff --git a/xs/src/slic3r/Utils/OctoPrint.hpp b/xs/src/slic3r/Utils/OctoPrint.hpp
index 1f544295c..744b4fcc1 100644
--- a/xs/src/slic3r/Utils/OctoPrint.hpp
+++ b/xs/src/slic3r/Utils/OctoPrint.hpp
@@ -17,7 +17,7 @@ public:
OctoPrint(DynamicPrintConfig *config);
bool test(wxString &curl_msg) const;
- void send_gcode(int windowId, int completeEvt, int errorEvt, const std::string &filename, bool print = false) const;
+ bool send_gcode(const std::string &filename, bool print = false) const;
private:
std::string host;
std::string apikey;