new cmd line handling; try to fix event thread on mac
This commit is contained in:
parent
3301251d90
commit
e55e3f4c1d
|
@ -18,8 +18,12 @@
|
||||||
Created on December 3, 2022, 3:02 PM
|
Created on December 3, 2022, 3:02 PM
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
#include "E2wxApp.h"
|
#include "E2wxApp.h"
|
||||||
#include "E2wxFrame.h"
|
#include "E2wxFrame.h"
|
||||||
|
#include "emulator.h"
|
||||||
|
#include "gui.h"
|
||||||
|
#include "configep2.h"
|
||||||
#include <wx/app.h>
|
#include <wx/app.h>
|
||||||
#include <wx/xrc/xmlres.h>
|
#include <wx/xrc/xmlres.h>
|
||||||
#include <wx/fileconf.h>
|
#include <wx/fileconf.h>
|
||||||
|
@ -35,6 +39,9 @@
|
||||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||||
#include <wx/debugrpt.h>
|
#include <wx/debugrpt.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,7 +96,9 @@ bool E2wxApp::OnInit() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef wxUSE_ON_FATAL_EXCEPTION
|
||||||
wxHandleFatalExceptions();
|
wxHandleFatalExceptions();
|
||||||
|
#endif
|
||||||
|
|
||||||
wxStandardPaths& stdpaths = wxStandardPaths::Get();
|
wxStandardPaths& stdpaths = wxStandardPaths::Get();
|
||||||
//stdpaths.SetInstallPrefix(".");
|
//stdpaths.SetInstallPrefix(".");
|
||||||
|
@ -135,6 +144,10 @@ bool E2wxApp::OnInit() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
StartSdlEpple2();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
E2wxFrame *frame = new E2wxFrame();
|
E2wxFrame *frame = new E2wxFrame();
|
||||||
frame->DoInit();
|
frame->DoInit();
|
||||||
frame->Show();
|
frame->Show();
|
||||||
|
@ -144,6 +157,31 @@ bool E2wxApp::OnInit() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int run(const std::string config_file) {
|
||||||
|
std::unique_ptr<Emulator> emu(new Emulator());
|
||||||
|
|
||||||
|
Config cfg(config_file);
|
||||||
|
emu->config(cfg);
|
||||||
|
|
||||||
|
emu->init();
|
||||||
|
|
||||||
|
return emu->run();
|
||||||
|
}
|
||||||
|
|
||||||
|
void E2wxApp::StartSdlEpple2() {
|
||||||
|
std::cout << "starting sdl thread..." << std::endl;
|
||||||
|
this->thread_sdl = new std::thread(run, this->arg_configfile);
|
||||||
|
std::cout << "started sdl thread." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int E2wxApp::OnExit() {
|
||||||
|
std::cout << "stopping sdl thread..." << std::endl;
|
||||||
|
GUI::queueQuit();
|
||||||
|
this->thread_sdl->join();
|
||||||
|
std::cout << "exiting wx application..." << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void E2wxApp::OnFatalException() {
|
void E2wxApp::OnFatalException() {
|
||||||
wxDebugReport report;
|
wxDebugReport report;
|
||||||
report.AddAll();
|
report.AddAll();
|
||||||
|
@ -154,10 +192,33 @@ void E2wxApp::OnFatalException() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int E2wxApp::OnExit() {
|
static const wxCmdLineEntryDesc cmdLineDesc[] =
|
||||||
return 0;
|
{
|
||||||
|
{ wxCMD_LINE_PARAM, NULL, NULL, "config file", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
|
||||||
|
wxCMD_LINE_DESC_END
|
||||||
|
};
|
||||||
|
|
||||||
|
void E2wxApp::OnInitCmdLine(wxCmdLineParser& parser) {
|
||||||
|
wxApp::OnInitCmdLine(parser);
|
||||||
|
parser.SetDesc(cmdLineDesc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool E2wxApp::OnCmdLineParsed(wxCmdLineParser& parser) {
|
||||||
|
if (!wxApp::OnCmdLineParsed(parser)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int n = parser.GetParamCount();
|
||||||
|
|
||||||
|
if (n <= 0) {
|
||||||
|
std::cout << "no config file specified on the command line; will use config file specified in user-preferences" << std::endl;
|
||||||
|
} else {
|
||||||
|
this->arg_configfile = parser.GetParam(0);
|
||||||
|
std::cout << "using config file specified on the command line: " << this->arg_configfile << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const std::filesystem::path E2wxApp::GetLogFile() const {
|
const std::filesystem::path E2wxApp::GetLogFile() const {
|
||||||
|
|
|
@ -25,7 +25,10 @@
|
||||||
#ifndef WX_PRECOMP
|
#ifndef WX_PRECOMP
|
||||||
#include <wx/wx.h>
|
#include <wx/wx.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <wx/app.h>
|
||||||
|
#include <wx/cmdline.h>
|
||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
|
#include <thread>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -37,9 +40,12 @@ class E2wxApp : public wxApp {
|
||||||
std::filesystem::path conffile;
|
std::filesystem::path conffile;
|
||||||
std::filesystem::path confdir;
|
std::filesystem::path confdir;
|
||||||
std::filesystem::path docsdir;
|
std::filesystem::path docsdir;
|
||||||
|
std::string arg_configfile;
|
||||||
|
std::thread *thread_sdl;
|
||||||
|
|
||||||
const std::filesystem::path BuildLogFilePath() const;
|
const std::filesystem::path BuildLogFilePath() const;
|
||||||
void InitBoostLog();
|
void InitBoostLog();
|
||||||
|
void StartSdlEpple2();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
E2wxApp();
|
E2wxApp();
|
||||||
|
@ -56,6 +62,8 @@ public:
|
||||||
virtual bool OnInit() override;
|
virtual bool OnInit() override;
|
||||||
virtual int OnExit() override;
|
virtual int OnExit() override;
|
||||||
virtual void OnFatalException() override;
|
virtual void OnFatalException() override;
|
||||||
|
virtual void OnInitCmdLine(wxCmdLineParser& parser) override;
|
||||||
|
virtual bool OnCmdLineParsed(wxCmdLineParser& parser) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
wxDECLARE_APP(E2wxApp);
|
wxDECLARE_APP(E2wxApp);
|
||||||
|
|
|
@ -21,14 +21,18 @@
|
||||||
#include "E2wxFrame.h"
|
#include "E2wxFrame.h"
|
||||||
#include "E2wxApp.h"
|
#include "E2wxApp.h"
|
||||||
#include "PreferencesDialog.h"
|
#include "PreferencesDialog.h"
|
||||||
|
#include "gui.h"
|
||||||
#include <wx/persist/toplevel.h>
|
#include <wx/persist/toplevel.h>
|
||||||
|
|
||||||
|
enum E2MenuID {
|
||||||
|
ID_MENUITEM_POWER = wxID_HIGHEST+1
|
||||||
|
};
|
||||||
|
|
||||||
wxBEGIN_EVENT_TABLE(E2wxFrame, wxFrame)
|
wxBEGIN_EVENT_TABLE(E2wxFrame, wxFrame)
|
||||||
EVT_MENU(wxID_EXIT, E2wxFrame::OnExit)
|
EVT_MENU(wxID_EXIT, E2wxFrame::OnExit)
|
||||||
EVT_MENU(wxID_PREFERENCES, E2wxFrame::OnPreferences)
|
EVT_MENU(wxID_PREFERENCES, E2wxFrame::OnPreferences)
|
||||||
EVT_MENU(wxID_ABOUT, E2wxFrame::OnAbout)
|
EVT_MENU(wxID_ABOUT, E2wxFrame::OnAbout)
|
||||||
|
EVT_MENU(ID_MENUITEM_POWER, E2wxFrame::OnTogglePower)
|
||||||
wxEND_EVENT_TABLE()
|
wxEND_EVENT_TABLE()
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,6 +64,10 @@ void E2wxFrame::InitMenuBar() {
|
||||||
menuBar->Append(menuEdit, "&Edit");
|
menuBar->Append(menuEdit, "&Edit");
|
||||||
menuEdit->Append(wxID_PREFERENCES);
|
menuEdit->Append(wxID_PREFERENCES);
|
||||||
|
|
||||||
|
wxMenu *menuMachine = new wxMenu();
|
||||||
|
menuBar->Append(menuMachine, "&Machine");
|
||||||
|
menuMachine->Append(ID_MENUITEM_POWER, "Toggle Power");
|
||||||
|
|
||||||
wxMenu *menuHelp = new wxMenu();
|
wxMenu *menuHelp = new wxMenu();
|
||||||
menuBar->Append(menuHelp, "&Help");
|
menuBar->Append(menuHelp, "&Help");
|
||||||
menuHelp->Append(wxID_ABOUT);
|
menuHelp->Append(wxID_ABOUT);
|
||||||
|
@ -94,3 +102,7 @@ void E2wxFrame::OnPreferences(wxCommandEvent& event) {
|
||||||
dlg->OnInit();
|
dlg->OnInit();
|
||||||
dlg->ShowModal();
|
dlg->ShowModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void E2wxFrame::OnTogglePower(wxCommandEvent& event) {
|
||||||
|
GUI::queueTogglePower();
|
||||||
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ private:
|
||||||
void OnExit(wxCommandEvent& event);
|
void OnExit(wxCommandEvent& event);
|
||||||
void OnPreferences(wxCommandEvent& event);
|
void OnPreferences(wxCommandEvent& event);
|
||||||
void OnAbout(wxCommandEvent& event);
|
void OnAbout(wxCommandEvent& event);
|
||||||
|
void OnTogglePower(wxCommandEvent& event);
|
||||||
|
|
||||||
void InitMenuBar();
|
void InitMenuBar();
|
||||||
void InitStatusBar();
|
void InitStatusBar();
|
||||||
|
|
|
@ -204,21 +204,12 @@ void PreferencesDialog::OnTreeSelectionChanged(wxTreeEvent& evt) {
|
||||||
|
|
||||||
void PreferencesDialog::PreSelectUserConfigItemName(const std::filesystem::path& n) {
|
void PreferencesDialog::PreSelectUserConfigItemName(const std::filesystem::path& n) {
|
||||||
CTRL(wxTreeCtrl, treItems);
|
CTRL(wxTreeCtrl, treItems);
|
||||||
wxTreeItemId id = treItems->GetRootItem();
|
|
||||||
wxTreeItemIdValue ctx;
|
wxTreeItemId i = treItems->GetRootItem();
|
||||||
wxTreeItemId i = treItems->GetFirstChild(id, ctx);
|
while (i.IsOk() && treItems->GetItemText(i) != wxFileName::FileName(n.c_str()).GetName()) {
|
||||||
while (i.IsOk() && treItems->GetItemText(i) != wxT("user")) {
|
i = treItems->GetNextVisible(i);
|
||||||
i = treItems->GetNextChild(id, ctx);
|
|
||||||
}
|
|
||||||
if (!i.IsOk()) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
id = i;
|
|
||||||
i = treItems->GetFirstChild(id, ctx);
|
|
||||||
while (i.IsOk() && treItems->GetItemText(i) != wxFileName::FileName(n.c_str()).GetName()) {
|
|
||||||
i = treItems->GetNextChild(id, ctx);
|
|
||||||
}
|
|
||||||
if (!i.IsOk()) {
|
if (!i.IsOk()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -247,6 +238,7 @@ void PreferencesDialog::OnActive(wxCommandEvent& evt) {
|
||||||
const std::filesystem::path p = data->path();
|
const std::filesystem::path p = data->path();
|
||||||
wxString name = wxFileName::FileName(p.c_str()).GetName();
|
wxString name = wxFileName::FileName(p.c_str()).GetName();
|
||||||
this->active = name;
|
this->active = name;
|
||||||
|
std::cout << "setting current active config file to: " << this->active << std::endl;
|
||||||
wxConfigBase::Get()->Write(wxT("/ActivePreferences/name"), this->active);
|
wxConfigBase::Get()->Write(wxT("/ActivePreferences/name"), this->active);
|
||||||
BuildItemTree(); // invalidates "data" pointer variable
|
BuildItemTree(); // invalidates "data" pointer variable
|
||||||
PreSelectUserConfigItemName(p);
|
PreSelectUserConfigItemName(p);
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#ifndef CONFIG_H
|
#ifndef CONFIGEP2_H
|
||||||
#define CONFIG_H
|
#define CONFIGEP2_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
class Memory;
|
class Memory;
|
||||||
|
|
|
@ -25,9 +25,9 @@ help from John Morris, Tom Greene, Michael Guidero, and Lane Roathe.
|
||||||
|
|
||||||
Stepper motor has 2 cans each with a center-tapped coil, allowing
|
Stepper motor has 2 cans each with a center-tapped coil, allowing
|
||||||
for current flow in one of either direction, causing a N/S or S/N
|
for current flow in one of either direction, causing a N/S or S/N
|
||||||
polarity fo the top/bottom of the can. Each top/bottom has fingers
|
polarity of the top/bottom of the can. Each top/bottom has fingers
|
||||||
bending down/up towards the center, the fingers from alternate surfaces
|
bending down/up towards the center, the fingers from alternate surfaces
|
||||||
being interlased. These fingers transfer the polarity from the coil.
|
being interlaced. These fingers transfer the polarity from the coil.
|
||||||
|
|
||||||
Example of coil-0, controlled by phases 0 and 2,
|
Example of coil-0, controlled by phases 0 and 2,
|
||||||
the two possible energized states, N/S and S/N,
|
the two possible energized states, N/S and S/N,
|
||||||
|
@ -134,7 +134,7 @@ But 7&1 is a special case (calculation-wise): since it's a circle, they
|
||||||
Adjacent fingers within a can are of reverse polarity, and are 4 positions apart.
|
Adjacent fingers within a can are of reverse polarity, and are 4 positions apart.
|
||||||
Cans are offset from each other by 2 positions.
|
Cans are offset from each other by 2 positions.
|
||||||
|
|
||||||
PH = phase 0-4 (on or off)
|
PH = phase 0-3 (on or off)
|
||||||
CAN = can 0-1 (north, south, or off)
|
CAN = can 0-1 (north, south, or off)
|
||||||
|
|
||||||
CAN0 = PH0+PH2
|
CAN0 = PH0+PH2
|
||||||
|
@ -288,6 +288,7 @@ int Disk2StepperMotor::magnetic_position() const {
|
||||||
return this->can_1.magnetic_position();
|
return this->can_1.magnetic_position();
|
||||||
}
|
}
|
||||||
assert(false);
|
assert(false);
|
||||||
|
return 0; // quell compiler warning "control reaches end of non-void function"
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disk2StepperMotor::tick() {
|
void Disk2StepperMotor::tick() {
|
||||||
|
|
38
src/gui.cpp
38
src/gui.cpp
|
@ -35,7 +35,41 @@ GUI::~GUI() {
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
GUI::NotInitException::NotInitException() :
|
static void pushSdlEvent(SDL_Event *e) {
|
||||||
runtime_error("Unable to initialize SDL") {
|
const int r = SDL_PushEvent(e);
|
||||||
|
|
||||||
|
if (r < 0) {
|
||||||
|
std::cerr << "SDL reported error: " << SDL_GetError() << std::endl;
|
||||||
|
} else if (r == 0) {
|
||||||
|
std::cerr << "SDL filtered event, sorry" << std::endl;
|
||||||
|
} else if (r == 1) {
|
||||||
|
std::cerr << "Pushed event to SDL" << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cerr << "SDL reported unexpected error code: " << r << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GUI::queueTogglePower() {
|
||||||
|
SDL_Event *e = new SDL_Event(); // note: creating struct on the stack doesn't seem to work
|
||||||
|
e->type = SDL_KEYDOWN;
|
||||||
|
e->key.keysym.sym = SDLK_F1;
|
||||||
|
pushSdlEvent(e);
|
||||||
|
delete e;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GUI::queueQuit() {
|
||||||
|
SDL_Event *e = new SDL_Event();
|
||||||
|
e->type = SDL_KEYDOWN;
|
||||||
|
e->key.keysym.sym = SDLK_F9;
|
||||||
|
pushSdlEvent(e);
|
||||||
|
delete e;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
GUI::NotInitException::NotInitException() : runtime_error("Unable to initialize SDL") {
|
||||||
SDL_GetError();
|
SDL_GetError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GUI::NotInitException::~NotInitException() {
|
||||||
|
}
|
||||||
|
|
14
src/gui.h
14
src/gui.h
|
@ -20,19 +20,19 @@
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
class GUI
|
class GUI {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
GUI();
|
GUI();
|
||||||
~GUI();
|
virtual ~GUI();
|
||||||
|
|
||||||
class NotInitException : public std::runtime_error
|
static void queueQuit();
|
||||||
{
|
static void queueTogglePower();
|
||||||
|
|
||||||
|
class NotInitException : public std::runtime_error {
|
||||||
public:
|
public:
|
||||||
NotInitException();
|
NotInitException();
|
||||||
virtual ~NotInitException() throw () {}
|
virtual ~NotInitException();
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
69
src/main.cpp
69
src/main.cpp
|
@ -15,81 +15,36 @@
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include <SDL.h>
|
|
||||||
#include "emulator.h"
|
|
||||||
#include "configep2.h"
|
|
||||||
#include "gui.h"
|
|
||||||
#include "e2const.h"
|
#include "e2const.h"
|
||||||
|
#include "gui.h"
|
||||||
|
|
||||||
#include <wx/app.h>
|
#include <wx/app.h>
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iomanip>
|
#include <ostream>
|
||||||
#include <thread>
|
#include <stdexcept>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
|
||||||
static std::string parse_args(int argc, char* argv[]) {
|
|
||||||
if (argc > 2) {
|
|
||||||
throw std::runtime_error("usage: epple2 [config-file]" );
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argc <= 1) {
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::string(argv[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int run(const std::string config_file) {
|
|
||||||
GUI gui;
|
|
||||||
|
|
||||||
std::unique_ptr<Emulator> emu(new Emulator());
|
|
||||||
|
|
||||||
Config cfg(config_file);
|
|
||||||
emu->config(cfg);
|
|
||||||
|
|
||||||
emu->init();
|
|
||||||
|
|
||||||
return emu->run();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void queueEmuQuit() {
|
|
||||||
SDL_Event f9;
|
|
||||||
f9.type = SDL_KEYDOWN;
|
|
||||||
f9.key.keysym.sym = SDLK_F9;
|
|
||||||
SDL_PushEvent(&f9);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
#endif
|
#endif
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
setbuf(stdout, NULL);
|
::setbuf(::stdout, nullptr);
|
||||||
setbuf(stderr, NULL);
|
::setbuf(::stderr, nullptr);
|
||||||
|
|
||||||
int x = E2Const::test();
|
const int x = E2Const::test();
|
||||||
if (x != -1) {
|
if (x != -1) {
|
||||||
std::cerr << x << std::endl;
|
std::cerr << x << std::endl;
|
||||||
throw std::runtime_error("bad constant in e2const.h" );
|
throw std::runtime_error("bad constant in e2const.h" );
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string config_file = parse_args(argc, argv);
|
GUI gui;
|
||||||
|
|
||||||
|
wxEntry(argc, argv);
|
||||||
|
|
||||||
std::thread sdl_thread(run, config_file);
|
|
||||||
|
|
||||||
int none(0);
|
|
||||||
wxEntry(none, (char**)nullptr);
|
|
||||||
// Runs wxWidgets main event loop and waits for user to File/Exit.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
queueEmuQuit();
|
|
||||||
sdl_thread.join();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue