From e55e3f4c1d3b0762c83a838163085160d8add55a Mon Sep 17 00:00:00 2001 From: "Christopher A. Mosher" Date: Sun, 4 Dec 2022 22:45:35 -0500 Subject: [PATCH] new cmd line handling; try to fix event thread on mac --- src/E2wxApp.cpp | 65 ++++++++++++++++++++++++++++++++++-- src/E2wxApp.h | 8 +++++ src/E2wxFrame.cpp | 14 +++++++- src/E2wxFrame.h | 1 + src/PreferencesDialog.cpp | 18 +++------- src/configep2.h | 4 +-- src/disk2steppermotor.cpp | 7 ++-- src/gui.cpp | 38 +++++++++++++++++++-- src/gui.h | 14 ++++---- src/main.cpp | 69 +++++++-------------------------------- 10 files changed, 151 insertions(+), 87 deletions(-) diff --git a/src/E2wxApp.cpp b/src/E2wxApp.cpp index cdac5c1..cb87b7e 100644 --- a/src/E2wxApp.cpp +++ b/src/E2wxApp.cpp @@ -18,8 +18,12 @@ Created on December 3, 2022, 3:02 PM */ +#include "config.h" #include "E2wxApp.h" #include "E2wxFrame.h" +#include "emulator.h" +#include "gui.h" +#include "configep2.h" #include #include #include @@ -35,6 +39,9 @@ #include #include #include +#include +#include +#include #include @@ -89,7 +96,9 @@ bool E2wxApp::OnInit() { return false; } +#ifdef wxUSE_ON_FATAL_EXCEPTION wxHandleFatalExceptions(); +#endif wxStandardPaths& stdpaths = wxStandardPaths::Get(); //stdpaths.SetInstallPrefix("."); @@ -135,6 +144,10 @@ bool E2wxApp::OnInit() { + StartSdlEpple2(); + + + E2wxFrame *frame = new E2wxFrame(); frame->DoInit(); frame->Show(); @@ -144,6 +157,31 @@ bool E2wxApp::OnInit() { return true; } +static int run(const std::string config_file) { + std::unique_ptr 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() { wxDebugReport report; report.AddAll(); @@ -154,10 +192,33 @@ void E2wxApp::OnFatalException() { } } -int E2wxApp::OnExit() { - return 0; +static const wxCmdLineEntryDesc cmdLineDesc[] = +{ + { 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 { diff --git a/src/E2wxApp.h b/src/E2wxApp.h index a37edba..b8eaa18 100644 --- a/src/E2wxApp.h +++ b/src/E2wxApp.h @@ -25,7 +25,10 @@ #ifndef WX_PRECOMP #include #endif +#include +#include #include +#include #include #include @@ -37,9 +40,12 @@ class E2wxApp : public wxApp { std::filesystem::path conffile; std::filesystem::path confdir; std::filesystem::path docsdir; + std::string arg_configfile; + std::thread *thread_sdl; const std::filesystem::path BuildLogFilePath() const; void InitBoostLog(); + void StartSdlEpple2(); public: E2wxApp(); @@ -56,6 +62,8 @@ public: virtual bool OnInit() override; virtual int OnExit() override; virtual void OnFatalException() override; + virtual void OnInitCmdLine(wxCmdLineParser& parser) override; + virtual bool OnCmdLineParsed(wxCmdLineParser& parser) override; }; wxDECLARE_APP(E2wxApp); diff --git a/src/E2wxFrame.cpp b/src/E2wxFrame.cpp index bb755ca..f30e9ca 100644 --- a/src/E2wxFrame.cpp +++ b/src/E2wxFrame.cpp @@ -21,14 +21,18 @@ #include "E2wxFrame.h" #include "E2wxApp.h" #include "PreferencesDialog.h" +#include "gui.h" #include - +enum E2MenuID { + ID_MENUITEM_POWER = wxID_HIGHEST+1 +}; wxBEGIN_EVENT_TABLE(E2wxFrame, wxFrame) EVT_MENU(wxID_EXIT, E2wxFrame::OnExit) EVT_MENU(wxID_PREFERENCES, E2wxFrame::OnPreferences) EVT_MENU(wxID_ABOUT, E2wxFrame::OnAbout) + EVT_MENU(ID_MENUITEM_POWER, E2wxFrame::OnTogglePower) wxEND_EVENT_TABLE() @@ -60,6 +64,10 @@ void E2wxFrame::InitMenuBar() { menuBar->Append(menuEdit, "&Edit"); menuEdit->Append(wxID_PREFERENCES); + wxMenu *menuMachine = new wxMenu(); + menuBar->Append(menuMachine, "&Machine"); + menuMachine->Append(ID_MENUITEM_POWER, "Toggle Power"); + wxMenu *menuHelp = new wxMenu(); menuBar->Append(menuHelp, "&Help"); menuHelp->Append(wxID_ABOUT); @@ -94,3 +102,7 @@ void E2wxFrame::OnPreferences(wxCommandEvent& event) { dlg->OnInit(); dlg->ShowModal(); } + +void E2wxFrame::OnTogglePower(wxCommandEvent& event) { + GUI::queueTogglePower(); +} diff --git a/src/E2wxFrame.h b/src/E2wxFrame.h index 094499c..4ec8508 100644 --- a/src/E2wxFrame.h +++ b/src/E2wxFrame.h @@ -39,6 +39,7 @@ private: void OnExit(wxCommandEvent& event); void OnPreferences(wxCommandEvent& event); void OnAbout(wxCommandEvent& event); + void OnTogglePower(wxCommandEvent& event); void InitMenuBar(); void InitStatusBar(); diff --git a/src/PreferencesDialog.cpp b/src/PreferencesDialog.cpp index c2b9e2e..91c5e97 100644 --- a/src/PreferencesDialog.cpp +++ b/src/PreferencesDialog.cpp @@ -204,21 +204,12 @@ void PreferencesDialog::OnTreeSelectionChanged(wxTreeEvent& evt) { void PreferencesDialog::PreSelectUserConfigItemName(const std::filesystem::path& n) { CTRL(wxTreeCtrl, treItems); - wxTreeItemId id = treItems->GetRootItem(); - wxTreeItemIdValue ctx; - wxTreeItemId i = treItems->GetFirstChild(id, ctx); - while (i.IsOk() && treItems->GetItemText(i) != wxT("user")) { - i = treItems->GetNextChild(id, ctx); - } - if (!i.IsOk()) { - return; + + wxTreeItemId i = treItems->GetRootItem(); + while (i.IsOk() && treItems->GetItemText(i) != wxFileName::FileName(n.c_str()).GetName()) { + i = treItems->GetNextVisible(i); } - 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()) { return; } @@ -247,6 +238,7 @@ void PreferencesDialog::OnActive(wxCommandEvent& evt) { const std::filesystem::path p = data->path(); wxString name = wxFileName::FileName(p.c_str()).GetName(); this->active = name; + std::cout << "setting current active config file to: " << this->active << std::endl; wxConfigBase::Get()->Write(wxT("/ActivePreferences/name"), this->active); BuildItemTree(); // invalidates "data" pointer variable PreSelectUserConfigItemName(p); diff --git a/src/configep2.h b/src/configep2.h index 3d6e3d2..2e745e1 100644 --- a/src/configep2.h +++ b/src/configep2.h @@ -15,8 +15,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef CONFIG_H -#define CONFIG_H +#ifndef CONFIGEP2_H +#define CONFIGEP2_H #include class Memory; diff --git a/src/disk2steppermotor.cpp b/src/disk2steppermotor.cpp index a783077..e069c94 100644 --- a/src/disk2steppermotor.cpp +++ b/src/disk2steppermotor.cpp @@ -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 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 -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, 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. 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) CAN0 = PH0+PH2 @@ -288,6 +288,7 @@ int Disk2StepperMotor::magnetic_position() const { return this->can_1.magnetic_position(); } assert(false); + return 0; // quell compiler warning "control reaches end of non-void function" } void Disk2StepperMotor::tick() { diff --git a/src/gui.cpp b/src/gui.cpp index f3a4f13..d3c4590 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -35,7 +35,41 @@ GUI::~GUI() { SDL_Quit(); } -GUI::NotInitException::NotInitException() : - runtime_error("Unable to initialize SDL") { +static void pushSdlEvent(SDL_Event *e) { + 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(); } + +GUI::NotInitException::~NotInitException() { +} diff --git a/src/gui.h b/src/gui.h index 3e556cc..30e0c1c 100644 --- a/src/gui.h +++ b/src/gui.h @@ -20,19 +20,19 @@ #include -class GUI -{ +class GUI { public: GUI(); - ~GUI(); + virtual ~GUI(); - class NotInitException : public std::runtime_error - { + static void queueQuit(); + static void queueTogglePower(); + + class NotInitException : public std::runtime_error { public: NotInitException(); - virtual ~NotInitException() throw () {} + virtual ~NotInitException(); }; - }; #endif diff --git a/src/main.cpp b/src/main.cpp index 05caf50..476f3d9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,81 +15,36 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include -#include "emulator.h" -#include "configep2.h" -#include "gui.h" + #include "e2const.h" +#include "gui.h" #include -#include -#include -#include #include -#include -#include +#include +#include +#include +#include -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 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 extern "C" #endif -int main(int argc, char* argv[]) { - setbuf(stdout, NULL); - setbuf(stderr, NULL); +int main(int argc, char *argv[]) { + ::setbuf(::stdout, nullptr); + ::setbuf(::stderr, nullptr); - int x = E2Const::test(); + const int x = E2Const::test(); if (x != -1) { std::cerr << x << std::endl; throw std::runtime_error("bad constant in e2const.h" ); } - const std::string config_file = parse_args(argc, argv); + GUI gui; - - - 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(); + wxEntry(argc, argv); return 0; }