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_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()
|
END_EVENT_TABLE()
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
|
|
||||||
|
@ -104,6 +105,7 @@ ConfigDialog::ConfigDialog(wxWindow *parent, wxWindowID id, const wxString &titl
|
||||||
{
|
{
|
||||||
#if wxUSE_TIMER
|
#if wxUSE_TIMER
|
||||||
m_TimeoutTimer = new wxTimer(this, IDTM_UPDATE);
|
m_TimeoutTimer = new wxTimer(this, IDTM_UPDATE);
|
||||||
|
m_ShutDownTimer = new wxTimer(this, IDTM_SHUTDOWN);
|
||||||
m_TimeoutATimer = new wxTimer(this, IDTM_UPDATEA);
|
m_TimeoutATimer = new wxTimer(this, IDTM_UPDATEA);
|
||||||
// Reset values
|
// Reset values
|
||||||
m_bWaitForRecording = false;
|
m_bWaitForRecording = false;
|
||||||
|
@ -139,23 +141,37 @@ void ConfigDialog::OnKeyDown(wxKeyEvent& event)
|
||||||
UpdateGUI();
|
UpdateGUI();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigDialog::OnClose(wxCloseEvent& WXUNUSED (event))
|
void ConfigDialog::OnClose(wxCloseEvent& WXUNUSED (event))
|
||||||
{
|
{
|
||||||
|
g_FrameOpen = false;
|
||||||
SaveFile();
|
SaveFile();
|
||||||
g_Config.Save();
|
g_Config.Save();
|
||||||
g_FrameOpen = false;
|
|
||||||
//SuccessAlert("Saved\n");
|
//SuccessAlert("Saved\n");
|
||||||
if (!g_EmulatorRunning) Shutdown();
|
if (!g_EmulatorRunning) Shutdown();
|
||||||
EndModal(0);
|
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)
|
void ConfigDialog::CloseClick(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
switch(event.GetId())
|
switch(event.GetId())
|
||||||
{
|
{
|
||||||
case ID_CLOSE:
|
case ID_CLOSE:
|
||||||
// wxWidgets function. This will also trigger EVT_CLOSE().
|
WiiMoteReal::g_Shutdown = true;
|
||||||
Close();
|
m_ShutDownTimer->Start(10);
|
||||||
break;
|
break;
|
||||||
case ID_APPLY:
|
case ID_APPLY:
|
||||||
SaveFile();
|
SaveFile();
|
||||||
|
|
|
@ -60,8 +60,9 @@ class ConfigDialog : public wxDialog
|
||||||
void DoRecordMovement(u8 _x, u8 _y, u8 _z, const u8 *_IR, int IRBytes);
|
void DoRecordMovement(u8 _x, u8 _y, u8 _z, const u8 *_IR, int IRBytes);
|
||||||
void DoRecordA(bool Pressed);
|
void DoRecordA(bool Pressed);
|
||||||
void ConvertToString();
|
void ConvertToString();
|
||||||
wxTimer *m_TimeoutTimer, *m_TimeoutATimer;
|
wxTimer *m_TimeoutTimer, *m_ShutDownTimer, *m_TimeoutATimer;
|
||||||
void Update(wxTimerEvent& WXUNUSED(event));
|
void Update(wxTimerEvent& WXUNUSED(event));
|
||||||
|
void ShutDown(wxTimerEvent& WXUNUSED(event));
|
||||||
void UpdateA(wxTimerEvent& WXUNUSED(event));
|
void UpdateA(wxTimerEvent& WXUNUSED(event));
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -105,7 +106,7 @@ class ConfigDialog : public wxDialog
|
||||||
ID_CLOSE = 1000,
|
ID_CLOSE = 1000,
|
||||||
ID_APPLY,
|
ID_APPLY,
|
||||||
ID_ABOUTOGL,
|
ID_ABOUTOGL,
|
||||||
IDTM_EXIT, IDTM_UPDATE, IDTM_UPDATEA, // Timer
|
IDTM_EXIT, IDTM_UPDATE, IDTM_SHUTDOWN, IDTM_UPDATEA, // Timer
|
||||||
|
|
||||||
ID_NOTEBOOK,
|
ID_NOTEBOOK,
|
||||||
ID_PAGEEMU,
|
ID_PAGEEMU,
|
||||||
|
|
|
@ -20,13 +20,13 @@
|
||||||
// Includes
|
// Includes
|
||||||
// ¯¯¯¯¯¯¯¯¯¯
|
// ¯¯¯¯¯¯¯¯¯¯
|
||||||
#include <iostream> // System
|
#include <iostream> // System
|
||||||
#include "pluginspecs_wiimote.h"
|
|
||||||
|
|
||||||
#include "wiiuse.h" // Externals
|
#include "wiiuse.h" // Externals
|
||||||
|
|
||||||
#include "ConsoleWindow.h" // Common
|
#include "ConsoleWindow.h" // Common
|
||||||
#include "StringUtil.h"
|
#include "StringUtil.h"
|
||||||
#include "Timer.h"
|
#include "Timer.h"
|
||||||
|
#include "pluginspecs_wiimote.h"
|
||||||
|
|
||||||
#include "wiimote_real.h" // Local
|
#include "wiimote_real.h" // Local
|
||||||
#include "wiimote_hid.h"
|
#include "wiimote_hid.h"
|
||||||
|
@ -44,13 +44,13 @@ namespace WiiMoteReal
|
||||||
|
|
||||||
void handle_ctrl_status(struct wiimote_t* wm)
|
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);
|
Console::Print("attachment: %i\n", wm->exp.type);
|
||||||
printf("speaker: %i\n", WIIUSE_USING_SPEAKER(wm));
|
Console::Print("speaker: %i\n", WIIUSE_USING_SPEAKER(wm));
|
||||||
printf("ir: %i\n", WIIUSE_USING_IR(wm));
|
Console::Print("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));
|
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));
|
||||||
printf("battery: %f %%\n", wm->battery_level);
|
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)
|
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 a button is pressed, report it */
|
||||||
if (IS_PRESSED(wm, WIIMOTE_BUTTON_A)) Console::Print("A pressed\n");
|
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);
|
wiiuse_set_ir(wm, 1);
|
||||||
|
|
||||||
/* Print battery status */
|
/* Print battery status */
|
||||||
if(frame)
|
if(frame && g_Config.bUpdateRealWiimote)
|
||||||
if(g_Config.bUpdateRealWiimote)
|
|
||||||
frame->m_GaugeBattery->SetValue((int)floor((wm->battery_level * 100) + 0.5));
|
frame->m_GaugeBattery->SetValue((int)floor((wm->battery_level * 100) + 0.5));
|
||||||
|
|
||||||
/* If the accelerometer is turned on then print angles */
|
/* If the accelerometer is turned on then print angles */
|
||||||
|
@ -211,9 +210,15 @@ void handle_event(struct wiimote_t* wm)
|
||||||
|
|
||||||
void ReadWiimote()
|
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]);
|
handle_event(g_WiiMotesFromWiiUse[0]);
|
||||||
std::string Temp;
|
std::string Temp;
|
||||||
// Read formatted data
|
|
||||||
|
// Read formatted Wiimote data
|
||||||
if (wiiuse_poll(g_WiiMotesFromWiiUse, MAX_WIIMOTES))
|
if (wiiuse_poll(g_WiiMotesFromWiiUse, MAX_WIIMOTES))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -297,4 +302,7 @@ void ReadWiimote()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}; // end of namespace
|
}; // end of namespace
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ HINSTANCE g_hInstance;
|
||||||
|
|
||||||
#if defined(HAVE_WX) && HAVE_WX
|
#if defined(HAVE_WX) && HAVE_WX
|
||||||
wxWindow win;
|
wxWindow win;
|
||||||
ConfigDialog *frame;
|
ConfigDialog *frame = NULL;
|
||||||
|
|
||||||
class wxDLLApp : public wxApp
|
class wxDLLApp : public wxApp
|
||||||
{
|
{
|
||||||
|
@ -159,11 +159,12 @@ void DllConfig(HWND _hParent)
|
||||||
//Console::Open();
|
//Console::Open();
|
||||||
DoInitialize();
|
DoInitialize();
|
||||||
|
|
||||||
g_FrameOpen = true;
|
|
||||||
frame = new ConfigDialog(&win);
|
frame = new ConfigDialog(&win);
|
||||||
|
g_FrameOpen = true;
|
||||||
frame->ShowModal();
|
/* We don't need to use ShowModal() anymore becaue FreeLibrary() is not called after this function
|
||||||
//frame.Show();
|
anymore */
|
||||||
|
//frame->ShowModal();
|
||||||
|
frame->Show();
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
win.SetHWND(0);
|
win.SetHWND(0);
|
||||||
|
@ -200,7 +201,8 @@ extern "C" void Shutdown(void)
|
||||||
if(frame) frame->UpdateGUI();
|
if(frame) frame->UpdateGUI();
|
||||||
#endif
|
#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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,7 @@ Common::Thread* g_pReadThread = NULL;
|
||||||
int g_NumberOfWiiMotes;
|
int g_NumberOfWiiMotes;
|
||||||
CWiiMote* g_WiiMotes[MAX_WIIMOTES];
|
CWiiMote* g_WiiMotes[MAX_WIIMOTES];
|
||||||
bool g_Shutdown = false;
|
bool g_Shutdown = false;
|
||||||
|
bool g_ThreadGoing = false;
|
||||||
bool g_LocalThread = true;
|
bool g_LocalThread = true;
|
||||||
bool g_IRSensing = false;
|
bool g_IRSensing = false;
|
||||||
bool g_MotionSensing = false;
|
bool g_MotionSensing = false;
|
||||||
|
@ -483,15 +484,10 @@ void Shutdown(void)
|
||||||
// Stop the loop in the thread
|
// Stop the loop in the thread
|
||||||
g_Shutdown = true;
|
g_Shutdown = true;
|
||||||
|
|
||||||
// Sleep this thread to wait for activity in g_pReadThread to stop entirely
|
|
||||||
Sleep(100);
|
|
||||||
|
|
||||||
// Stop the thread
|
// Stop the thread
|
||||||
if (g_pReadThread != NULL)
|
if (g_pReadThread != NULL)
|
||||||
{
|
{
|
||||||
// This sometimes hangs for some reason so I'm trying to disable it
|
g_pReadThread->WaitForDeath();
|
||||||
// It seemed to hang in WaitForSingleObject(), but I don't know why
|
|
||||||
//g_pReadThread->WaitForDeath();
|
|
||||||
delete g_pReadThread;
|
delete g_pReadThread;
|
||||||
g_pReadThread = NULL;
|
g_pReadThread = NULL;
|
||||||
}
|
}
|
||||||
|
@ -555,10 +551,13 @@ void Update()
|
||||||
{
|
{
|
||||||
while (!g_Shutdown)
|
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)
|
if(g_Config.bUseRealWiimote && !g_RunTemporary)
|
||||||
for (int i = 0; i < g_NumberOfWiiMotes; i++) g_WiiMotes[i]->ReadData();
|
for (int i = 0; i < g_NumberOfWiiMotes; i++) g_WiiMotes[i]->ReadData();
|
||||||
else
|
else
|
||||||
ReadWiimote();
|
ReadWiimote();
|
||||||
|
g_ThreadGoing = false;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,8 @@ void ReadWiimote();
|
||||||
|
|
||||||
#ifndef EXCLUDE_H
|
#ifndef EXCLUDE_H
|
||||||
extern wiimote_t** g_WiiMotesFromWiiUse;
|
extern wiimote_t** g_WiiMotesFromWiiUse;
|
||||||
|
extern bool g_Shutdown;
|
||||||
|
extern bool g_ThreadGoing;
|
||||||
extern int g_NumberOfWiiMotes;
|
extern int g_NumberOfWiiMotes;
|
||||||
extern bool g_MotionSensing;
|
extern bool g_MotionSensing;
|
||||||
extern bool g_IRSensing;
|
extern bool g_IRSensing;
|
||||||
|
|
Loading…
Reference in New Issue