Firmware updater GUI
This commit is contained in:
parent
3d09f2a980
commit
af360d7097
@ -352,8 +352,8 @@ sub _init_menubar {
|
||||
$menubar->Append($self->{object_menu}, L("&Object")) if $self->{object_menu};
|
||||
$menubar->Append($windowMenu, L("&Window"));
|
||||
$menubar->Append($self->{viewMenu}, L("&View")) if $self->{viewMenu};
|
||||
# Add a configuration menu.
|
||||
Slic3r::GUI::add_config_menu($menubar, $self->{preferences_event}, $self->{lang_ch_event});
|
||||
# Add additional menus from C++
|
||||
Slic3r::GUI::add_menus($menubar, $self->{preferences_event}, $self->{lang_ch_event});
|
||||
$menubar->Append($helpMenu, L("&Help"));
|
||||
$self->SetMenuBar($menubar);
|
||||
}
|
||||
|
@ -226,6 +226,8 @@ add_library(libslic3r_gui STATIC
|
||||
${LIBDIR}/slic3r/GUI/MsgDialog.hpp
|
||||
${LIBDIR}/slic3r/GUI/UpdateDialogs.cpp
|
||||
${LIBDIR}/slic3r/GUI/UpdateDialogs.hpp
|
||||
${LIBDIR}/slic3r/GUI/FirmwareDialog.cpp
|
||||
${LIBDIR}/slic3r/GUI/FirmwareDialog.hpp
|
||||
${LIBDIR}/slic3r/Utils/Http.cpp
|
||||
${LIBDIR}/slic3r/Utils/Http.hpp
|
||||
${LIBDIR}/slic3r/Utils/OctoPrint.cpp
|
||||
|
@ -5,30 +5,39 @@ extern "C" {
|
||||
#include "avrdude.h"
|
||||
}
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace AvrDude {
|
||||
|
||||
static void avrdude_message_handler_ostream(const char *msg, unsigned size, void *user_p)
|
||||
|
||||
// Used by our custom code in avrdude to receive messages that avrdude normally outputs on stdout (see avrdude_message())
|
||||
static void avrdude_message_handler_closure(const char *msg, unsigned size, void *user_p)
|
||||
{
|
||||
(void)size;
|
||||
std::ostream &os = *reinterpret_cast<std::ostream*>(user_p);
|
||||
os << msg;
|
||||
auto *message_fn = reinterpret_cast<MessageFn*>(user_p);
|
||||
(*message_fn)(msg, size);
|
||||
}
|
||||
|
||||
int main(std::vector<std::string> args, std::string sys_config, std::ostream &os)
|
||||
int main(std::vector<std::string> args, std::string sys_config, MessageFn message_fn)
|
||||
{
|
||||
std::vector<char *> c_args {{ const_cast<char*>(PACKAGE_NAME) }};
|
||||
for (const auto &arg : args) {
|
||||
c_args.push_back(const_cast<char*>(arg.data()));
|
||||
}
|
||||
|
||||
::avrdude_message_handler_set(avrdude_message_handler_ostream, reinterpret_cast<void*>(&os));
|
||||
::avrdude_message_handler_set(avrdude_message_handler_closure, reinterpret_cast<void*>(&message_fn));
|
||||
const auto res = ::avrdude_main(static_cast<int>(c_args.size()), c_args.data(), sys_config.c_str());
|
||||
::avrdude_message_handler_set(nullptr, nullptr);
|
||||
return res;
|
||||
}
|
||||
|
||||
int main(std::vector<std::string> args, std::string sys_config, std::ostream &os)
|
||||
{
|
||||
return main(std::move(args), std::move(sys_config), std::move([&os](const char *msg, unsigned /* size */) {
|
||||
os << msg;
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -4,10 +4,14 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
#include <functional>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace AvrDude {
|
||||
typedef std::function<void(const char * /* msg */, unsigned /* size */)> MessageFn;
|
||||
|
||||
int main(std::vector<std::string> args, std::string sys_config, MessageFn message_fn);
|
||||
int main(std::vector<std::string> args, std::string sys_config, std::ostream &os);
|
||||
}
|
||||
|
||||
|
197
xs/src/slic3r/GUI/FirmwareDialog.cpp
Normal file
197
xs/src/slic3r/GUI/FirmwareDialog.cpp
Normal file
@ -0,0 +1,197 @@
|
||||
#include "FirmwareDialog.hpp"
|
||||
|
||||
#include <ostream>
|
||||
#include <numeric>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
|
||||
#include <wx/app.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/filepicker.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/combobox.h>
|
||||
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "avrdude/avrdude-slic3r.hpp"
|
||||
#include "GUI.hpp"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
||||
// Private
|
||||
|
||||
struct FirmwareDialog::priv
|
||||
{
|
||||
std::string avrdude_config;
|
||||
|
||||
wxComboBox *port_picker;
|
||||
wxFilePickerCtrl *hex_picker;
|
||||
wxStaticText *status;
|
||||
wxTextCtrl *txt_stdout;
|
||||
wxButton *btn_flash;
|
||||
|
||||
priv() : avrdude_config((fs::path(::Slic3r::resources_dir()) / "avrdude" / "avrdude.conf").string()) {}
|
||||
|
||||
void find_serial_ports();
|
||||
void perform_upload();
|
||||
};
|
||||
|
||||
void FirmwareDialog::priv::find_serial_ports()
|
||||
{
|
||||
auto ports = GUI::scan_serial_ports();
|
||||
|
||||
port_picker->Clear();
|
||||
for (const auto &port : ports) { port_picker->Append(port); }
|
||||
|
||||
if (ports.size() > 0 && port_picker->GetValue().IsEmpty()) {
|
||||
port_picker->SetSelection(0);
|
||||
}
|
||||
}
|
||||
|
||||
void FirmwareDialog::priv::perform_upload()
|
||||
{
|
||||
auto filename = hex_picker->GetPath();
|
||||
auto port = port_picker->GetValue();
|
||||
if (filename.IsEmpty() || port.IsEmpty()) { return; }
|
||||
|
||||
// Note: we're not using wxTextCtrl's ability to act as a std::ostream
|
||||
// because its imeplementation doesn't handle conversion from local charset
|
||||
// which mangles error messages from perror().
|
||||
|
||||
auto message_fn = [this](const char *msg, unsigned /* size */) {
|
||||
// TODO: also log into boost? (Problematic with progress bars.)
|
||||
this->txt_stdout->AppendText(wxString(msg));
|
||||
wxTheApp->Yield();
|
||||
};
|
||||
|
||||
txt_stdout->SetValue(wxEmptyString);
|
||||
status->SetLabel(_(L("Flashing in progress. Please do not disconnect the printer!")));
|
||||
auto status_color_orig = status->GetForegroundColour();
|
||||
status->SetForegroundColour(GUI::get_label_clr_modified());
|
||||
btn_flash->Disable();
|
||||
|
||||
std::vector<std::string> args {{
|
||||
"-v",
|
||||
"-p", "atmega2560",
|
||||
"-c", "wiring",
|
||||
"-P", port.ToStdString(),
|
||||
"-b", "115200", // XXX: is this ok to hardcode?
|
||||
"-D",
|
||||
"-U", (boost::format("flash:w:%1%:i") % filename.ToStdString()).str()
|
||||
}};
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "Invoking avrdude, arguments: "
|
||||
<< std::accumulate(std::next(args.begin()), args.end(), args[0], [](std::string a, const std::string &b) {
|
||||
return a + ' ' + b;
|
||||
});
|
||||
|
||||
auto res = AvrDude::main(std::move(args), avrdude_config, std::move(message_fn));
|
||||
|
||||
BOOST_LOG_TRIVIAL(info) << "avrdude exit code: " << res;
|
||||
|
||||
btn_flash->Enable();
|
||||
|
||||
status->SetForegroundColour(status_color_orig);
|
||||
status->SetLabel(
|
||||
res == 0 ? _(L("Flashing succeeded!")) : _(L("Flashing failed. Please see the avrdude log below."))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Public
|
||||
|
||||
FirmwareDialog::FirmwareDialog(wxWindow *parent) :
|
||||
wxDialog(parent, wxID_ANY, _(L("Firmware flasher"))),
|
||||
// p(new priv(this))
|
||||
p(new priv())
|
||||
{
|
||||
enum {
|
||||
DIALOG_MARGIN = 15,
|
||||
SPACING = 10,
|
||||
};
|
||||
|
||||
wxFont bold_font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
|
||||
bold_font.MakeBold();
|
||||
wxFont mono_font(wxFontInfo().Family(wxFONTFAMILY_TELETYPE));
|
||||
mono_font.MakeSmaller();
|
||||
|
||||
auto *panel = new wxPanel(this);
|
||||
wxBoxSizer *vsizer = new wxBoxSizer(wxVERTICAL);
|
||||
panel->SetSizer(vsizer);
|
||||
|
||||
auto *txt_port_picker = new wxStaticText(panel, wxID_ANY, _(L("Serial port:")));
|
||||
p->port_picker = new wxComboBox(panel, wxID_ANY);
|
||||
auto *btn_rescan = new wxButton(panel, wxID_ANY, _(L("Rescan")));
|
||||
auto *port_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
port_sizer->Add(p->port_picker, 1, wxEXPAND | wxRIGHT, SPACING);
|
||||
port_sizer->Add(btn_rescan, 0);
|
||||
|
||||
auto *txt_hex_picker = new wxStaticText(panel, wxID_ANY, _(L("Firmware image:")));
|
||||
p->hex_picker = new wxFilePickerCtrl(panel, wxID_ANY);
|
||||
|
||||
auto *txt_status = new wxStaticText(panel, wxID_ANY, _(L("Status:")));
|
||||
p->status = new wxStaticText(panel, wxID_ANY, _(L("Ready")));
|
||||
p->status->SetFont(bold_font);
|
||||
|
||||
auto *sizer_pickers = new wxFlexGridSizer(2, SPACING, SPACING);
|
||||
sizer_pickers->AddGrowableCol(1);
|
||||
sizer_pickers->Add(txt_port_picker, 0, wxALIGN_CENTER_VERTICAL);
|
||||
sizer_pickers->Add(port_sizer, 0, wxEXPAND);
|
||||
sizer_pickers->Add(txt_hex_picker, 0, wxALIGN_CENTER_VERTICAL);
|
||||
sizer_pickers->Add(p->hex_picker, 0, wxEXPAND);
|
||||
sizer_pickers->Add(txt_status, 0, wxALIGN_CENTER_VERTICAL);
|
||||
sizer_pickers->Add(p->status, 0, wxEXPAND);
|
||||
vsizer->Add(sizer_pickers, 0, wxEXPAND | wxBOTTOM, SPACING);
|
||||
|
||||
p->txt_stdout = new wxTextCtrl(panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY);
|
||||
p->txt_stdout->SetFont(mono_font);
|
||||
vsizer->Add(p->txt_stdout, 1, wxEXPAND | wxBOTTOM, SPACING);
|
||||
|
||||
p->btn_flash = new wxButton(panel, wxID_ANY, _(L("Flash!")));
|
||||
auto *bsizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
bsizer->AddStretchSpacer();
|
||||
bsizer->Add(p->btn_flash);
|
||||
vsizer->Add(bsizer, 0, wxEXPAND);
|
||||
|
||||
auto *topsizer = new wxBoxSizer(wxVERTICAL);
|
||||
topsizer->Add(panel, 1, wxEXPAND | wxALL, DIALOG_MARGIN);
|
||||
SetSizerAndFit(topsizer);
|
||||
SetMinSize(wxSize(400, 400));
|
||||
SetSize(wxSize(800, 800));
|
||||
|
||||
p->find_serial_ports();
|
||||
|
||||
p->btn_flash->Bind(wxEVT_BUTTON, [this](wxCommandEvent &) { this->p->perform_upload(); });
|
||||
btn_rescan->Bind(wxEVT_BUTTON, [this](wxCommandEvent &) { this->p->find_serial_ports(); });
|
||||
|
||||
// Bind(EVT_BONJOUR_REPLY, &FirmwareDialog::on_reply, this);
|
||||
|
||||
// Bind(EVT_BONJOUR_COMPLETE, [this](wxCommandEvent &) {
|
||||
// this->timer_state = 0;
|
||||
// });
|
||||
|
||||
// Bind(wxEVT_TIMER, &FirmwareDialog::on_timer, this);
|
||||
}
|
||||
|
||||
FirmwareDialog::~FirmwareDialog()
|
||||
{
|
||||
// Needed bacuse of forward defs
|
||||
}
|
||||
|
||||
void FirmwareDialog::run(wxWindow *parent)
|
||||
{
|
||||
FirmwareDialog dialog(parent);
|
||||
dialog.ShowModal();
|
||||
}
|
||||
|
||||
|
||||
}
|
31
xs/src/slic3r/GUI/FirmwareDialog.hpp
Normal file
31
xs/src/slic3r/GUI/FirmwareDialog.hpp
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef slic3r_FirmwareDialog_hpp_
|
||||
#define slic3r_FirmwareDialog_hpp_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <wx/dialog.h>
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
||||
class FirmwareDialog: public wxDialog
|
||||
{
|
||||
public:
|
||||
FirmwareDialog(wxWindow *parent);
|
||||
FirmwareDialog(FirmwareDialog &&) = delete;
|
||||
FirmwareDialog(const FirmwareDialog &) = delete;
|
||||
FirmwareDialog &operator=(FirmwareDialog &&) = delete;
|
||||
FirmwareDialog &operator=(const FirmwareDialog &) = delete;
|
||||
~FirmwareDialog();
|
||||
|
||||
static void run(wxWindow *parent);
|
||||
private:
|
||||
struct priv;
|
||||
std::unique_ptr<priv> p;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,7 +1,6 @@
|
||||
#include "GUI.hpp"
|
||||
#include "WipeTowerDialog.hpp"
|
||||
|
||||
#include <iostream> // XXX
|
||||
#include <assert.h>
|
||||
#include <cmath>
|
||||
|
||||
@ -56,11 +55,11 @@
|
||||
#include "Preferences.hpp"
|
||||
#include "PresetBundle.hpp"
|
||||
#include "UpdateDialogs.hpp"
|
||||
#include "FirmwareDialog.hpp"
|
||||
|
||||
#include "../Utils/PresetUpdater.hpp"
|
||||
#include "../Config/Snapshot.hpp"
|
||||
|
||||
#include "avrdude/avrdude-slic3r.hpp" // XXX: TMP!
|
||||
|
||||
namespace Slic3r { namespace GUI {
|
||||
|
||||
@ -254,27 +253,6 @@ void set_app_config(AppConfig *app_config)
|
||||
void set_preset_bundle(PresetBundle *preset_bundle)
|
||||
{
|
||||
g_PresetBundle = preset_bundle;
|
||||
|
||||
auto res = AvrDude::main({{
|
||||
// "-h",
|
||||
"-v",
|
||||
"-p",
|
||||
"atmega2560",
|
||||
"-c",
|
||||
"wiring",
|
||||
"-P",
|
||||
"COM1",
|
||||
"-b115200",
|
||||
"-D",
|
||||
"-U",
|
||||
"flash:w:c:\\local\\prusa3d_fw-3.2.0-RC2.534-1_75mm_MK3-EINSy10a-E3Dv6full.hex:i",
|
||||
}},
|
||||
"c:\\local\\Slic3r\\resources\\avrdude\\avrdude.conf", std::cerr
|
||||
); // XXX: tmp
|
||||
|
||||
std::cerr << "AvrDude::main: " << res << std::endl;
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void set_preset_updater(PresetUpdater *updater)
|
||||
@ -485,6 +463,42 @@ void add_config_menu(wxMenuBar *menu, int event_preferences_changed, int event_l
|
||||
menu->Append(local_menu, _(L("&Configuration")));
|
||||
}
|
||||
|
||||
enum FirmwareMenuIDs {
|
||||
FirmwareMenuFlash,
|
||||
FirmwareMenuDict,
|
||||
FirmwareMenuCnt,
|
||||
};
|
||||
|
||||
void add_firmware_menu(wxMenuBar *top_menu)
|
||||
{
|
||||
auto *menu = new wxMenu();
|
||||
wxWindowID id_base = wxWindow::NewControlId(FirmwareMenuCnt);
|
||||
|
||||
menu->Append(id_base + FirmwareMenuFlash, _(L("Flash printer firmware")), _(L("Upload a firmware image into a Prusa printer")));
|
||||
menu->Append(id_base + FirmwareMenuDict, _(L("Flash language file")), _(L("Upload a language dictionary file into a Prusa printer")));
|
||||
|
||||
menu->Bind(wxEVT_MENU, [id_base](wxEvent &event) {
|
||||
switch (event.GetId() - id_base) {
|
||||
case FirmwareMenuFlash:
|
||||
FirmwareDialog::run(g_wxMainFrame);
|
||||
break;
|
||||
case FirmwareMenuDict:
|
||||
// TODO
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
top_menu->Append(menu, _(L("Fir&mware")));
|
||||
}
|
||||
|
||||
void add_menus(wxMenuBar *menu, int event_preferences_changed, int event_language_change)
|
||||
{
|
||||
add_config_menu(menu, event_language_change, event_language_change);
|
||||
add_firmware_menu(menu);
|
||||
}
|
||||
|
||||
// This is called when closing the application, when loading a config file or when starting the config wizard
|
||||
// to notify the user whether he is aware that some preset changes will be lost.
|
||||
bool check_unsaved_changes()
|
||||
|
@ -91,7 +91,7 @@ unsigned get_colour_approx_luma(const wxColour &colour);
|
||||
void set_label_clr_modified(const wxColour& clr);
|
||||
void set_label_clr_sys(const wxColour& clr);
|
||||
|
||||
extern void add_config_menu(wxMenuBar *menu, int event_preferences_changed, int event_language_change);
|
||||
extern void add_menus(wxMenuBar *menu, int event_preferences_changed, int event_language_change);
|
||||
|
||||
// This is called when closing the application, when loading a config file or when starting the config wizard
|
||||
// to notify the user whether he is aware that some preset changes will be lost.
|
||||
|
@ -36,8 +36,8 @@ void set_main_frame(SV *ui)
|
||||
void set_tab_panel(SV *ui)
|
||||
%code%{ Slic3r::GUI::set_tab_panel((wxNotebook*)wxPli_sv_2_object(aTHX_ ui, "Wx::Notebook")); %};
|
||||
|
||||
void add_config_menu(SV *ui, int event_preferences_changed, int event_language_change)
|
||||
%code%{ Slic3r::GUI::add_config_menu((wxMenuBar*)wxPli_sv_2_object(aTHX_ ui, "Wx::MenuBar"), event_preferences_changed, event_language_change); %};
|
||||
void add_menus(SV *ui, int event_preferences_changed, int event_language_change)
|
||||
%code%{ Slic3r::GUI::add_menus((wxMenuBar*)wxPli_sv_2_object(aTHX_ ui, "Wx::MenuBar"), event_preferences_changed, event_language_change); %};
|
||||
|
||||
void create_preset_tabs(bool no_controller, int event_value_change, int event_presets_changed)
|
||||
%code%{ Slic3r::GUI::create_preset_tabs(no_controller, event_value_change, event_presets_changed); %};
|
||||
|
Loading…
Reference in New Issue
Block a user