diff --git a/src/gui/gui.h b/src/gui/gui.h index 15ef19f2..0c5eb3a8 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -10,7 +10,7 @@ extern void runOnUiThread(std::function callback); extern void runOnWorkerThread(std::function callback); template -static inline R runOnUiThread(std::function& callback) +static inline R runOnUiThread(std::function callback) { R retvar; runOnUiThread( diff --git a/src/gui/layout.cpp b/src/gui/layout.cpp index 0b188c29..e299af31 100644 --- a/src/gui/layout.cpp +++ b/src/gui/layout.cpp @@ -135,7 +135,7 @@ MainWindowGen::MainWindowGen( wxWindow* parent, wxWindowID id, const wxString& t m_panel3->SetSizer( fgSizer9 ); m_panel3->Layout(); fgSizer9->Fit( m_panel3 ); - notebook->AddPage( m_panel3, wxT("Proto config"), false ); + notebook->AddPage( m_panel3, wxT("Debug info"), false ); fgSizer2->Add( notebook, 1, wxEXPAND | wxALL, 5 ); diff --git a/src/gui/layout.fbp b/src/gui/layout.fbp index 04326130..db4a3b5b 100644 --- a/src/gui/layout.fbp +++ b/src/gui/layout.fbp @@ -1034,7 +1034,7 @@ - Proto config + Debug info 0 1 diff --git a/src/gui/mainwindow.cc b/src/gui/mainwindow.cc index 5fc17f31..111e48fe 100644 --- a/src/gui/mainwindow.cc +++ b/src/gui/mainwindow.cc @@ -5,6 +5,7 @@ #include "reader.h" #include "fluxsource/fluxsource.h" #include "imagereader/imagereader.h" +#include "imagewriter/imagewriter.h" #include "decoders/decoders.h" #include "lib/usb/usbfinder.h" #include "fmt/format.h" @@ -16,39 +17,40 @@ extern const std::map formats; MainWindow::MainWindow(): MainWindowGen(nullptr) { - Logger::setLogger( - [&](std::shared_ptr message) { - runOnUiThread( - [message, this]() { - OnLogMessage(message); - } - ); - } - ); + Logger::setLogger( + [&](std::shared_ptr message) + { + runOnUiThread( + [message, this]() + { + OnLogMessage(message); + }); + }); - for (const auto& it : formats) - { - auto config = std::make_unique(); - if (!config->ParseFromString(it.second)) - continue; - if (config->is_extension()) - continue; + for (const auto& it : formats) + { + auto config = std::make_unique(); + if (!config->ParseFromString(it.second)) + continue; + if (config->is_extension()) + continue; - formatChoice->Append(it.first); - _formats.push_back(std::move(config)); - } + formatChoice->Append(it.first); + _formats.push_back(std::move(config)); + } - UpdateDevices(); - if (deviceCombo->GetCount() > 0) - deviceCombo->SetValue(deviceCombo->GetString(0)); + UpdateDevices(); + if (deviceCombo->GetCount() > 0) + deviceCombo->SetValue(deviceCombo->GetString(0)); - fluxSourceSinkCombo->SetValue(fluxSourceSinkCombo->GetString(0)); + fluxSourceSinkCombo->SetValue(fluxSourceSinkCombo->GetString(0)); - readFluxButton->Bind(wxEVT_BUTTON, &MainWindow::OnReadFluxButton, this); - readImageButton->Bind(wxEVT_BUTTON, &MainWindow::OnReadImageButton, this); - stopButton->Bind(wxEVT_BUTTON, &MainWindow::OnStopButton, this); + readFluxButton->Bind(wxEVT_BUTTON, &MainWindow::OnReadFluxButton, this); + readImageButton->Bind(wxEVT_BUTTON, &MainWindow::OnReadImageButton, this); + writeImageButton->Bind(wxEVT_BUTTON, &MainWindow::OnWriteImageButton, this); + stopButton->Bind(wxEVT_BUTTON, &MainWindow::OnStopButton, this); - UpdateState(); + UpdateState(); } void MainWindow::OnExit(wxCommandEvent& event) @@ -58,131 +60,175 @@ void MainWindow::OnExit(wxCommandEvent& event) void MainWindow::OnStopButton(wxCommandEvent&) { - emergencyStop = true; + emergencyStop = true; } void MainWindow::OnReadFluxButton(wxCommandEvent&) { - try - { - ConfigProto config = PrepareConfig(); + try + { + ConfigProto config = PrepareConfig(); - FluxSource::updateConfigForFilename(config.mutable_flux_source(), - fluxSourceSinkCombo->GetValue().ToStdString()); + FluxSource::updateConfigForFilename(config.mutable_flux_source(), + fluxSourceSinkCombo->GetValue().ToStdString()); + visualiser->Clear(); + _currentDisk = nullptr; - runOnWorkerThread( - [config, this]() { - ::config = config; - auto fluxSource = FluxSource::create(config.flux_source()); - auto decoder = AbstractDecoder::create(config.decoder()); - auto diskflux = readDiskCommand(*fluxSource, *decoder); - runOnUiThread( - [&]() { - visualiser->SetDiskData(diskflux); - } - ); - } - ); - } - catch (const ErrorException& e) - { - wxMessageBox(e.message, "Error", wxOK | wxICON_ERROR); - } + runOnWorkerThread( + [config, this]() + { + ::config = config; + auto fluxSource = FluxSource::create(config.flux_source()); + auto decoder = AbstractDecoder::create(config.decoder()); + auto diskflux = readDiskCommand(*fluxSource, *decoder); + runOnUiThread( + [&]() + { + visualiser->SetDiskData(diskflux); + }); + }); + } + catch (const ErrorException& e) + { + wxMessageBox(e.message, "Error", wxOK | wxICON_ERROR); + } } void MainWindow::OnReadImageButton(wxCommandEvent&) { - auto filename = wxFileSelector("Choose a file to open"); - if (filename.empty()) - return; + try + { + ConfigProto config = PrepareConfig(); + if (!config.has_image_reader()) + Error() << "This format is read-only."; - try - { - ConfigProto config = PrepareConfig(); - if (!config.has_image_reader()) - Error() << "This format is read-only."; + auto filename = wxFileSelector( + "Choose a image file to read", + /* default_path= */ wxEmptyString, + /* default_filename= */ config.image_reader().filename(), + /* default_extension= */ wxEmptyString, + /* wildcard= */ wxEmptyString, + /* flags= */ wxFD_OPEN | wxFD_FILE_MUST_EXIST); + if (filename.empty()) + return; - ImageReader::updateConfigForFilename( - config.mutable_image_reader(), filename.ToStdString()); + ImageReader::updateConfigForFilename( + config.mutable_image_reader(), filename.ToStdString()); + visualiser->Clear(); + _currentDisk = nullptr; - runOnWorkerThread( - [config, this]() { - ::config = config; - auto imageReader = ImageReader::create(config.image_reader()); - std::unique_ptr image = imageReader->readImage(); - runOnUiThread( - [&]() { - auto disk = std::make_shared(); - disk = std::make_shared(); - disk->image = std::move(image); - _currentDisk = disk; - visualiser->SetDiskData(_currentDisk); - } - ); - } - ); - } - catch (const ErrorException& e) - { - wxMessageBox(e.message, "Error", wxOK | wxICON_ERROR); - } + runOnWorkerThread( + [config, this]() + { + ::config = config; + auto imageReader = ImageReader::create(config.image_reader()); + std::unique_ptr image = imageReader->readImage(); + runOnUiThread( + [&]() + { + auto disk = std::make_shared(); + disk = std::make_shared(); + disk->image = std::move(image); + _currentDisk = disk; + visualiser->SetDiskData(_currentDisk); + }); + }); + } + catch (const ErrorException& e) + { + wxMessageBox(e.message, "Error", wxOK | wxICON_ERROR); + } +} + +void MainWindow::OnWriteImageButton(wxCommandEvent&) +{ + try + { + ConfigProto config = PrepareConfig(); + if (!config.has_image_writer()) + Error() << "This format is write-only."; + + auto filename = wxFileSelector( + "Choose a image file to write", + /* default_path= */ wxEmptyString, + /* default_filename= */ config.image_writer().filename(), + /* default_extension= */ wxEmptyString, + /* wildcard= */ wxEmptyString, + /* flags= */ wxFD_SAVE | wxFD_OVERWRITE_PROMPT); + if (filename.empty()) + return; + + ImageWriter::updateConfigForFilename( + config.mutable_image_writer(), filename.ToStdString()); + + auto image = _currentDisk->image; + runOnWorkerThread( + [config, image, this]() + { + ::config = config; + auto imageWriter = ImageWriter::create(config.image_writer()); + imageWriter->writeImage(*image); + }); + } + catch (const ErrorException& e) + { + wxMessageBox(e.message, "Error", wxOK | wxICON_ERROR); + } } ConfigProto MainWindow::PrepareConfig() { - auto formatSelection = formatChoice->GetSelection(); - if (formatSelection == wxNOT_FOUND) - Error() << "no format selected"; + auto formatSelection = formatChoice->GetSelection(); + if (formatSelection == wxNOT_FOUND) + Error() << "no format selected"; - ConfigProto config = *_formats[formatChoice->GetSelection()]; + ConfigProto config = *_formats[formatChoice->GetSelection()]; - auto serial = deviceCombo->GetValue().ToStdString(); - if (!serial.empty() && (serial[0] == '/')) - setProtoByString(&config, "usb.greaseweazle.port", serial); - else - setProtoByString(&config, "usb.serial", serial); + auto serial = deviceCombo->GetValue().ToStdString(); + if (!serial.empty() && (serial[0] == '/')) + setProtoByString(&config, "usb.greaseweazle.port", serial); + else + setProtoByString(&config, "usb.serial", serial); - ApplyCustomSettings(config); + ApplyCustomSettings(config); - { - std::string s; - google::protobuf::TextFormat::PrintToString(config, &s); - protoConfigEntry->Clear(); - protoConfigEntry->AppendText(s); - } + { + std::string s; + google::protobuf::TextFormat::PrintToString(config, &s); + protoConfigEntry->Clear(); + protoConfigEntry->AppendText(s); + } - visualiser->Clear(); - logEntry->Clear(); - _currentDisk = nullptr; + logEntry->Clear(); - return config; + return config; } void MainWindow::ApplyCustomSettings(ConfigProto& config) { - for (int i=0; i < additionalSettingsEntry->GetNumberOfLines(); i++) - { - auto setting = additionalSettingsEntry->GetLineText(i).ToStdString(); - trimWhitespace(setting); - if (setting.size() == 0) - continue; + for (int i = 0; i < additionalSettingsEntry->GetNumberOfLines(); i++) + { + auto setting = additionalSettingsEntry->GetLineText(i).ToStdString(); + trimWhitespace(setting); + if (setting.size() == 0) + continue; - auto equals = setting.find('='); - if (equals != std::string::npos) - { - auto key = setting.substr(0, equals); - auto value = setting.substr(equals+1); - setProtoByString(&config, key, value); - } - else - FlagGroup::parseConfigFile(setting, formats); - } + auto equals = setting.find('='); + if (equals != std::string::npos) + { + auto key = setting.substr(0, equals); + auto value = setting.substr(equals + 1); + setProtoByString(&config, key, value); + } + else + FlagGroup::parseConfigFile(setting, formats); + } } void MainWindow::OnLogMessage(std::shared_ptr message) { - logEntry->AppendText(Logger::toString(*message)); - notebook->SetSelection(1); + logEntry->AppendText(Logger::toString(*message)); + notebook->SetSelection(1); std::visit( overloaded{ @@ -191,42 +237,42 @@ void MainWindow::OnLogMessage(std::shared_ptr message) { }, - /* A fatal error. */ - [&](const ErrorLogMessage& m) - { - wxMessageBox(m.message, "Error", wxOK | wxICON_ERROR); - }, + /* A fatal error. */ + [&](const ErrorLogMessage& m) + { + wxMessageBox(m.message, "Error", wxOK | wxICON_ERROR); + }, /* Indicates that we're starting a write operation. */ [&](const BeginWriteOperationLogMessage& m) { - visualiser->SetMode(m.cylinder, m.head, VISMODE_WRITING); + visualiser->SetMode(m.cylinder, m.head, VISMODE_WRITING); }, [&](const EndWriteOperationLogMessage& m) { - visualiser->SetMode(0, 0, VISMODE_NOTHING); + visualiser->SetMode(0, 0, VISMODE_NOTHING); }, /* Indicates that we're starting a read operation. */ [&](const BeginReadOperationLogMessage& m) { - visualiser->SetMode(m.cylinder, m.head, VISMODE_READING); + visualiser->SetMode(m.cylinder, m.head, VISMODE_READING); }, [&](const EndReadOperationLogMessage& m) { - visualiser->SetMode(0, 0, VISMODE_NOTHING); + visualiser->SetMode(0, 0, VISMODE_NOTHING); }, [&](const TrackReadLogMessage& m) { - visualiser->SetTrackData(m.track); + visualiser->SetTrackData(m.track); }, [&](const DiskReadLogMessage& m) { - _currentDisk = m.disk; + _currentDisk = m.disk; }, }, *message); @@ -234,23 +280,22 @@ void MainWindow::OnLogMessage(std::shared_ptr message) void MainWindow::UpdateState() { - writeImageButton->Enable(!!_currentDisk); - writeFluxButton->Enable(!!_currentDisk); - stopButton->Enable(wxGetApp().IsWorkerThreadRunning()); - readFluxButton->Enable(!wxGetApp().IsWorkerThreadRunning()); - readImageButton->Enable(!wxGetApp().IsWorkerThreadRunning()); + writeImageButton->Enable(!!_currentDisk); + writeFluxButton->Enable(!!_currentDisk); + stopButton->Enable(wxGetApp().IsWorkerThreadRunning()); + readFluxButton->Enable(!wxGetApp().IsWorkerThreadRunning()); + readImageButton->Enable(!wxGetApp().IsWorkerThreadRunning()); } void MainWindow::UpdateDevices() { - auto candidates = findUsbDevices(); + auto candidates = findUsbDevices(); - deviceCombo->Clear(); - _devices.clear(); - for (auto& candidate : candidates) - { - deviceCombo->Append(candidate->serial); - _devices.push_back(std::move(candidate)); - } + deviceCombo->Clear(); + _devices.clear(); + for (auto& candidate : candidates) + { + deviceCombo->Append(candidate->serial); + _devices.push_back(std::move(candidate)); + } } - diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h index efb16174..332a5d48 100644 --- a/src/gui/mainwindow.h +++ b/src/gui/mainwindow.h @@ -18,6 +18,7 @@ private: void OnStopButton(wxCommandEvent&); void OnReadFluxButton(wxCommandEvent&); void OnReadImageButton(wxCommandEvent&); + void OnWriteImageButton(wxCommandEvent&); void OnLogMessage(std::shared_ptr message); public: