new cmd line handling; try to fix event thread on mac

This commit is contained in:
Christopher A. Mosher 2022-12-04 22:45:35 -05:00
parent 3301251d90
commit e55e3f4c1d
10 changed files with 151 additions and 87 deletions

View File

@ -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 <wx/app.h>
#include <wx/xrc/xmlres.h>
#include <wx/fileconf.h>
@ -35,6 +39,9 @@
#include <boost/date_time/posix_time/posix_time.hpp>
#include <wx/debugrpt.h>
#include <iostream>
#include <thread>
#include <string>
#include <memory>
#include <algorithm>
@ -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<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() {
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 {

View File

@ -25,7 +25,10 @@
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/app.h>
#include <wx/cmdline.h>
#include <wx/string.h>
#include <thread>
#include <filesystem>
#include <string>
@ -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);

View File

@ -21,14 +21,18 @@
#include "E2wxFrame.h"
#include "E2wxApp.h"
#include "PreferencesDialog.h"
#include "gui.h"
#include <wx/persist/toplevel.h>
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();
}

View File

@ -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();

View File

@ -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);

View File

@ -15,8 +15,8 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CONFIG_H
#define CONFIG_H
#ifndef CONFIGEP2_H
#define CONFIGEP2_H
#include <string>
class Memory;

View File

@ -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() {

View File

@ -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() {
}

View File

@ -20,19 +20,19 @@
#include <stdexcept>
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

View File

@ -15,81 +15,36 @@
You should have received a copy of the GNU General Public License
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 "gui.h"
#include <wx/app.h>
#include <string>
#include <memory>
#include <stdexcept>
#include <iostream>
#include <iomanip>
#include <thread>
#include <ostream>
#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
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;
}