From 5972f886ab622e4cb8acb1d71f1be06882ab923d Mon Sep 17 00:00:00 2001 From: John Peterson Date: Tue, 3 Feb 2009 07:43:52 +0000 Subject: [PATCH] Wiimote: Fixed the hanging for real. Any call to a function in the wxDialog frame class while the main thread is in a WaitForSingleObject() loop or any other loop will hang the g_pReadThread execution until sometime after that loop has ended. So we must wait for pReadThread to stop from the wxDialog with a timer, we can not use any loop in the main thread to wait for it to stop. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2083 8ced0084-cf51-0410-be5f-012b33b47a6e --- .../Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp | 26 +++++++++++--- Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h | 5 +-- .../Plugin_Wiimote/Src/ReadWiimote.cpp | 34 ++++++++++++------- Source/Plugins/Plugin_Wiimote/Src/main.cpp | 14 ++++---- .../Plugin_Wiimote/Src/wiimote_real.cpp | 17 +++++----- .../Plugins/Plugin_Wiimote/Src/wiimote_real.h | 2 ++ 6 files changed, 63 insertions(+), 35 deletions(-) diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp index 1905c52b8d..a625170f73 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp @@ -90,7 +90,8 @@ BEGIN_EVENT_TABLE(ConfigDialog,wxDialog) EVT_BUTTON(IDB_RECORD + 14, ConfigDialog::RecordMovement) EVT_BUTTON(IDB_RECORD + 15, ConfigDialog::RecordMovement) - EVT_TIMER(IDTM_UPDATE, ConfigDialog::Update) + EVT_TIMER(IDTM_UPDATE, ConfigDialog::Update) + EVT_TIMER(IDTM_SHUTDOWN, ConfigDialog::ShutDown) END_EVENT_TABLE() ///////////////////////////// @@ -104,6 +105,7 @@ ConfigDialog::ConfigDialog(wxWindow *parent, wxWindowID id, const wxString &titl { #if wxUSE_TIMER m_TimeoutTimer = new wxTimer(this, IDTM_UPDATE); + m_ShutDownTimer = new wxTimer(this, IDTM_SHUTDOWN); m_TimeoutATimer = new wxTimer(this, IDTM_UPDATEA); // Reset values m_bWaitForRecording = false; @@ -139,23 +141,37 @@ void ConfigDialog::OnKeyDown(wxKeyEvent& event) UpdateGUI(); } } + void ConfigDialog::OnClose(wxCloseEvent& WXUNUSED (event)) { + g_FrameOpen = false; SaveFile(); - g_Config.Save(); - g_FrameOpen = false; + g_Config.Save(); //SuccessAlert("Saved\n"); if (!g_EmulatorRunning) Shutdown(); EndModal(0); } +/* Timeout the shutdown. In Windows at least the g_pReadThread execution will hang at any attempt to + call a frame function after the main thread has entered WaitForSingleObject() or any other loop. + We must therefore shut down the thread from here and wait for that before we can call ShutDown(). */ +void ConfigDialog::ShutDown(wxTimerEvent& WXUNUSED(event)) +{ + // Close() is a wxWidgets function that will trigger EVT_CLOSE() and then call this->Destroy(). + if(!WiiMoteReal::g_ThreadGoing) + { + m_ShutDownTimer->Stop(); + Close(); + } +} + void ConfigDialog::CloseClick(wxCommandEvent& event) { switch(event.GetId()) { case ID_CLOSE: - // wxWidgets function. This will also trigger EVT_CLOSE(). - Close(); + WiiMoteReal::g_Shutdown = true; + m_ShutDownTimer->Start(10); break; case ID_APPLY: SaveFile(); diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h index 23191b5680..10efec4efe 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h @@ -60,8 +60,9 @@ class ConfigDialog : public wxDialog void DoRecordMovement(u8 _x, u8 _y, u8 _z, const u8 *_IR, int IRBytes); void DoRecordA(bool Pressed); void ConvertToString(); - wxTimer *m_TimeoutTimer, *m_TimeoutATimer; + wxTimer *m_TimeoutTimer, *m_ShutDownTimer, *m_TimeoutATimer; void Update(wxTimerEvent& WXUNUSED(event)); + void ShutDown(wxTimerEvent& WXUNUSED(event)); void UpdateA(wxTimerEvent& WXUNUSED(event)); private: @@ -105,7 +106,7 @@ class ConfigDialog : public wxDialog ID_CLOSE = 1000, ID_APPLY, ID_ABOUTOGL, - IDTM_EXIT, IDTM_UPDATE, IDTM_UPDATEA, // Timer + IDTM_EXIT, IDTM_UPDATE, IDTM_SHUTDOWN, IDTM_UPDATEA, // Timer ID_NOTEBOOK, ID_PAGEEMU, diff --git a/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp b/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp index 28ec7d32ac..52805179fe 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp @@ -20,13 +20,13 @@ // Includes // ŻŻŻŻŻŻŻŻŻŻ #include // System -#include "pluginspecs_wiimote.h" #include "wiiuse.h" // Externals #include "ConsoleWindow.h" // Common #include "StringUtil.h" #include "Timer.h" +#include "pluginspecs_wiimote.h" #include "wiimote_real.h" // Local #include "wiimote_hid.h" @@ -44,13 +44,13 @@ namespace WiiMoteReal void handle_ctrl_status(struct wiimote_t* wm) { - printf("\n\n--- CONTROLLER STATUS [wiimote id %i] ---\n", wm->unid); + Console::Print("\n\n--- CONTROLLER STATUS [wiimote id %i] ---\n", wm->unid); - printf("attachment: %i\n", wm->exp.type); - printf("speaker: %i\n", WIIUSE_USING_SPEAKER(wm)); - printf("ir: %i\n", WIIUSE_USING_IR(wm)); - printf("leds: %i %i %i %i\n", WIIUSE_IS_LED_SET(wm, 1), WIIUSE_IS_LED_SET(wm, 2), WIIUSE_IS_LED_SET(wm, 3), WIIUSE_IS_LED_SET(wm, 4)); - printf("battery: %f %%\n", wm->battery_level); + Console::Print("attachment: %i\n", wm->exp.type); + Console::Print("speaker: %i\n", WIIUSE_USING_SPEAKER(wm)); + Console::Print("ir: %i\n", WIIUSE_USING_IR(wm)); + Console::Print("leds: %i %i %i %i\n", WIIUSE_IS_LED_SET(wm, 1), WIIUSE_IS_LED_SET(wm, 2), WIIUSE_IS_LED_SET(wm, 3), WIIUSE_IS_LED_SET(wm, 4)); + Console::Print("battery: %f %%\n", wm->battery_level); } @@ -73,7 +73,7 @@ bool IRDataOK(struct wiimote_t* wm) void handle_event(struct wiimote_t* wm) { - printf("\n\n--- EVENT [id %i] ---\n", wm->unid); + //Console::Print("\n\n--- EVENT [id %i] ---\n", wm->unid); /* if a button is pressed, report it */ if (IS_PRESSED(wm, WIIMOTE_BUTTON_A)) Console::Print("A pressed\n"); @@ -111,9 +111,8 @@ void handle_event(struct wiimote_t* wm) wiiuse_set_ir(wm, 1); /* Print battery status */ - if(frame) - if(g_Config.bUpdateRealWiimote) - frame->m_GaugeBattery->SetValue((int)floor((wm->battery_level * 100) + 0.5)); + if(frame && g_Config.bUpdateRealWiimote) + frame->m_GaugeBattery->SetValue((int)floor((wm->battery_level * 100) + 0.5)); /* If the accelerometer is turned on then print angles */ if (WIIUSE_USING_ACC(wm) && WIIUSE_USING_IR(wm)) @@ -211,9 +210,15 @@ void handle_event(struct wiimote_t* wm) void ReadWiimote() { + /* I place this outside wiiuse_poll() to produce a continous recording regardless of the status + change of the Wiimote, wiiuse_poll() is only true if the status has changed. However, this the + timing functions for recording playback that checks the time of the recording this should not + be needed. But I still use it becase it seemed like state_changed() or the threshold values or + something else might fail so that only huge status changed were reported. */ handle_event(g_WiiMotesFromWiiUse[0]); std::string Temp; - // Read formatted data + + // Read formatted Wiimote data if (wiiuse_poll(g_WiiMotesFromWiiUse, MAX_WIIMOTES)) { /* @@ -297,4 +302,7 @@ void ReadWiimote() } } -}; // end of namespace \ No newline at end of file + +}; // end of namespace + + diff --git a/Source/Plugins/Plugin_Wiimote/Src/main.cpp b/Source/Plugins/Plugin_Wiimote/Src/main.cpp index 6d1f639abf..9e0952e1cf 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/main.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/main.cpp @@ -76,7 +76,7 @@ HINSTANCE g_hInstance; #if defined(HAVE_WX) && HAVE_WX wxWindow win; - ConfigDialog *frame; + ConfigDialog *frame = NULL; class wxDLLApp : public wxApp { @@ -159,11 +159,12 @@ void DllConfig(HWND _hParent) //Console::Open(); DoInitialize(); - g_FrameOpen = true; frame = new ConfigDialog(&win); - - frame->ShowModal(); - //frame.Show(); + g_FrameOpen = true; + /* We don't need to use ShowModal() anymore becaue FreeLibrary() is not called after this function + anymore */ + //frame->ShowModal(); + frame->Show(); #ifdef _WIN32 win.SetHWND(0); @@ -200,7 +201,8 @@ extern "C" void Shutdown(void) if(frame) frame->UpdateGUI(); #endif - // Don't shut down the wiimote when we still have the window open + /* Don't shut down the wiimote when we still have the config window open, we may still want + want to use the Wiimote in the config window. */ return; } diff --git a/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp b/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp index c13062853a..0833279ee0 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.cpp @@ -69,6 +69,7 @@ Common::Thread* g_pReadThread = NULL; int g_NumberOfWiiMotes; CWiiMote* g_WiiMotes[MAX_WIIMOTES]; bool g_Shutdown = false; +bool g_ThreadGoing = false; bool g_LocalThread = true; bool g_IRSensing = false; bool g_MotionSensing = false; @@ -471,8 +472,8 @@ int Initialize() g_Config.bClassicControllerConnected = (g_WiiMotesFromWiiUse[0]->exp.type == EXP_CLASSIC); // Initialized - if (g_NumberOfWiiMotes > 0) { g_RealWiiMoteInitialized = true; g_Shutdown = false; } - + if (g_NumberOfWiiMotes > 0) { g_RealWiiMoteInitialized = true; g_Shutdown = false; } + return g_NumberOfWiiMotes; } @@ -483,16 +484,11 @@ void Shutdown(void) // Stop the loop in the thread g_Shutdown = true; - // Sleep this thread to wait for activity in g_pReadThread to stop entirely - Sleep(100); - // Stop the thread if (g_pReadThread != NULL) { - // This sometimes hangs for some reason so I'm trying to disable it - // It seemed to hang in WaitForSingleObject(), but I don't know why - //g_pReadThread->WaitForDeath(); - delete g_pReadThread; + g_pReadThread->WaitForDeath(); + delete g_pReadThread; g_pReadThread = NULL; } @@ -555,10 +551,13 @@ void Update() { while (!g_Shutdown) { + // We need g_ThreadGoing to do a manual WaitForSingleObject() from the configuration window + g_ThreadGoing = true; if(g_Config.bUseRealWiimote && !g_RunTemporary) for (int i = 0; i < g_NumberOfWiiMotes; i++) g_WiiMotes[i]->ReadData(); else ReadWiimote(); + g_ThreadGoing = false; } return 0; } diff --git a/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.h b/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.h index 8bd98df26e..1d4f5e21f3 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.h +++ b/Source/Plugins/Plugin_Wiimote/Src/wiimote_real.h @@ -46,6 +46,8 @@ void ReadWiimote(); #ifndef EXCLUDE_H extern wiimote_t** g_WiiMotesFromWiiUse; + extern bool g_Shutdown; + extern bool g_ThreadGoing; extern int g_NumberOfWiiMotes; extern bool g_MotionSensing; extern bool g_IRSensing;