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
This commit is contained in:
parent
f999ae94df
commit
5972f886ab
|
@ -91,6 +91,7 @@ BEGIN_EVENT_TABLE(ConfigDialog,wxDialog)
|
|||
EVT_BUTTON(IDB_RECORD + 15, ConfigDialog::RecordMovement)
|
||||
|
||||
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;
|
||||
//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();
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -20,13 +20,13 @@
|
|||
// Includes
|
||||
// ¯¯¯¯¯¯¯¯¯¯
|
||||
#include <iostream> // 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,8 +111,7 @@ void handle_event(struct wiimote_t* wm)
|
|||
wiiuse_set_ir(wm, 1);
|
||||
|
||||
/* Print battery status */
|
||||
if(frame)
|
||||
if(g_Config.bUpdateRealWiimote)
|
||||
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 */
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -483,15 +484,10 @@ 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();
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue