Make WiiMote consume less resources (do not run thread if not required)

This commit is contained in:
Flamefire committed 2014-03-11 21:55:26 +01:00
1 parent 44dceaed60
commit 668d72d3a7
3 files changed
+68 -124

No files matched your search

+6 -6
View File
@@ -161,25 +161,25 @@ namespace Vocaluxe.Lib.Input
public static int ReadTimeout(IntPtr device, ref byte[] data, int length, int milliseconds) public static int ReadTimeout(IntPtr device, ref byte[] data, int length, int milliseconds)
{ {
IntPtr dataPtr = Marshal.AllocHGlobal(length); IntPtr dataPtr = Marshal.AllocHGlobal(length);
int result; int bytesRead;
try try
{ {
result = hid_read_timeout(device, dataPtr, length, milliseconds); bytesRead = hid_read_timeout(device, dataPtr, length, milliseconds);
} }
catch (Exception e) catch (Exception e)
{ {
result = -1; bytesRead = -1;
CLog.LogError("Error CHIDAPI.ReadTimeout(): " + e); CLog.LogError("Error CHIDAPI.ReadTimeout(): " + e);
} }
if (result != -1) if (bytesRead != -1)
Marshal.Copy(dataPtr, data, 0, result); Marshal.Copy(dataPtr, data, 0, bytesRead);
else else
data = null; data = null;
Marshal.FreeHGlobal(dataPtr); Marshal.FreeHGlobal(dataPtr);
return result; return bytesRead;
} }
[DllImport(_HIDApiDll, ExactSpelling = false, CallingConvention = CallingConvention.Cdecl, EntryPoint = "hid_read", CharSet = CharSet.Unicode)] [DllImport(_HIDApiDll, ExactSpelling = false, CallingConvention = CallingConvention.Cdecl, EntryPoint = "hid_read", CharSet = CharSet.Unicode)]
+3 -14
View File
@@ -25,7 +25,7 @@ using VocaluxeLib;
namespace Vocaluxe.Lib.Input.WiiMote namespace Vocaluxe.Lib.Input.WiiMote
{ {
class CWiiMote : IController, IDisposable class CWiiMote : IController
{ {
private CWiiMoteLib _WiiMote; private CWiiMoteLib _WiiMote;
@@ -54,7 +54,7 @@ namespace Vocaluxe.Lib.Input.WiiMote
_RumbleTimer = new CRumbleTimer(); _RumbleTimer = new CRumbleTimer();
_Gesture = new CGesture(); _Gesture = new CGesture();
_HandlerThread = new Thread(_MainLoop) {Priority = ThreadPriority.BelowNormal}; _HandlerThread = new Thread(_MainLoop) {Name = "WiiMote", Priority = ThreadPriority.BelowNormal};
_KeysPool = new List<SKeyEvent>(); _KeysPool = new List<SKeyEvent>();
_CurrentKeysPool = new List<SKeyEvent>(); _CurrentKeysPool = new List<SKeyEvent>();
@@ -151,8 +151,7 @@ namespace Vocaluxe.Lib.Input.WiiMote
if (startRumble) if (startRumble)
_WiiMote.SetRumble(true); _WiiMote.SetRumble(true);
else if (stopRumble)
if (stopRumble)
_WiiMote.SetRumble(false); _WiiMote.SetRumble(false);
} }
} }
@@ -314,15 +313,5 @@ namespace Vocaluxe.Lib.Input.WiiMote
_MousePool.Clear(); _MousePool.Clear();
} }
} }
public void Dispose()
{
if (_WiiMote != null)
{
_WiiMote.Dispose();
_WiiMote = null;
}
GC.SuppressFinalize(this);
}
} }
} }
+59 -104
View File
@@ -137,7 +137,7 @@ namespace Vocaluxe.Lib.Input.WiiMote
} }
#endregion Events #endregion Events
public sealed class CWiiMoteLib : IDisposable public sealed class CWiiMoteLib
{ {
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
private const ushort _VID = 0x057e; private const ushort _VID = 0x057e;
@@ -178,8 +178,7 @@ namespace Vocaluxe.Lib.Input.WiiMote
private int _Address; private int _Address;
private short _Size; private short _Size;
private readonly Thread _Reader; private Thread _Reader;
private bool _Active;
private readonly bool _Error; private readonly bool _Error;
public bool Connected { get; private set; } public bool Connected { get; private set; }
@@ -191,72 +190,63 @@ namespace Vocaluxe.Lib.Input.WiiMote
#region Interface #region Interface
public CWiiMoteLib() public CWiiMoteLib()
{ {
Connected = false;
_Active = true;
_Error = false;
_Reader = new Thread(_ReaderLoop);
_Reader.Start();
if (!CHIDApi.Init()) if (!CHIDApi.Init())
{ {
CLog.LogError("WiiMoteLib: Can't initialize HID API"); CLog.LogError("WiiMoteLib: Can't initialize HID API");
const string msg = "Please install the Visual C++ Redistributable Packages 2008!"; CLog.LogError("Please install the Visual C++ Redistributable Packages 2008!");
CLog.LogError(msg);
_Active = false;
_Error = true; _Error = true;
} }
} }
~CWiiMoteLib() ~CWiiMoteLib()
{ {
Dispose(false); Disconnect();
//Wait for thread to finish (if any)
_WaitForReader();
CHIDApi.Exit();
_ReadDone.Dispose();
} }
private bool _TryConnect(ushort pid) private void _StartReader()
{ {
bool connected = CHIDApi.Open(_VID, pid, out _Handle); _Reader = new Thread(_ReaderLoop) {Name = "WiiMoteLib"};
if (connected) _Reader.Start();
}
private void _WaitForReader()
{
if (_Reader == null)
return;
_Reader.Join();
_Reader = null;
}
private void _TryConnect(ushort pid)
{
//We might have had a reader thread, that is not finished yet, so let it finish and close it's handle first or it will close the new one
_WaitForReader();
Connected = CHIDApi.Open(_VID, pid, out _Handle);
if (Connected)
{ {
connected = _ReadCalibration(); _StartReader();
if (!connected) if (!_ReadCalibration())
CHIDApi.Close(_Handle); Connected = false;
} }
return connected;
} }
public bool Connect() public bool Connect()
{ {
Connected = false; if (Connected)
return true;
if (_Error) if (_Error)
return false; return false;
//Try WiiMotion _TryConnect(_PID); //Try WiiMotion
Connected = CHIDApi.Open(_VID, _PID, out _Handle);
if (Connected)
{
Connected = _ReadCalibration();
if (!Connected)
CHIDApi.Close(_Handle);
}
else
CHIDApi.Close(_Handle);
if (Connected)
return true;
//Try WiiMotion Plus
Connected = CHIDApi.Open(_VID, _PIDPlus, out _Handle);
if (Connected)
{
Connected = _ReadCalibration();
if (!Connected)
CHIDApi.Close(_Handle);
}
else
CHIDApi.Close(_Handle);
if (!Connected)
_TryConnect(_PIDPlus); //Try WiiMotion Plus
return Connected; return Connected;
} }
@@ -264,8 +254,6 @@ namespace Vocaluxe.Lib.Input.WiiMote
public void Disconnect() public void Disconnect()
{ {
Connected = false; Connected = false;
_Active = false;
CHIDApi.Exit();
} }
public void SetReportType(EInputReport type, EIRSensitivity irSensitivity, bool continuous) public void SetReportType(EInputReport type, EIRSensitivity irSensitivity, bool continuous)
@@ -328,68 +316,54 @@ namespace Vocaluxe.Lib.Input.WiiMote
#region Private stuff #region Private stuff
private void _ReaderLoop() private void _ReaderLoop()
{ {
while (_Active) var buff = new byte[_ReportLength];
while (Connected)
{ {
Thread.Sleep(5); int bytesRead;
try
if (_Handle != IntPtr.Zero && Connected)
{ {
var buff = new byte[_ReportLength]; bytesRead = CHIDApi.ReadTimeout(_Handle, ref buff, _ReportLength, 400);
if (bytesRead == -1)
try
{ {
CHIDApi.ReadTimeout(_Handle, ref buff, _ReportLength, 200); Connected = false; //Disconnected
} break;
catch (Exception e)
{
CLog.LogError("(WiiMoteLib) Error reading from device: " + e);
}
if (_ParseInputReport(buff))
{
if (WiiMoteChanged != null)
WiiMoteChanged(this, new CWiiMoteChangedEventArgs(_WiiMoteState));
} }
} }
catch (Exception e)
{
CLog.LogError("(WiiMoteLib) Error reading from device: " + e);
Connected = false;
break;
}
if (bytesRead > 0 && _ParseInputReport(buff))
{
if (WiiMoteChanged != null)
WiiMoteChanged(this, new CWiiMoteChangedEventArgs(_WiiMoteState));
}
Thread.Sleep(5);
} }
CHIDApi.Close(_Handle);
} }
private bool _ParseInputReport(byte[] buff) private bool _ParseInputReport(byte[] buff)
{ {
if (buff == null)
{
Connected = false;
return false;
}
var type = (EInputReport)buff[0]; var type = (EInputReport)buff[0];
switch (type) switch (type)
{ {
case EInputReport.Buttons: case EInputReport.Buttons:
_ParseButtons(buff);
break;
case EInputReport.ButtonsAccel:
_ParseButtons(buff);
_ParseAccel(buff);
break;
case EInputReport.IRAccel:
_ParseButtons(buff);
_ParseAccel(buff);
_ParseIR(buff);
break;
case EInputReport.ButtonsExtension: case EInputReport.ButtonsExtension:
_ParseButtons(buff); _ParseButtons(buff);
break; break;
case EInputReport.ButtonsAccel:
case EInputReport.ExtensionAccel: case EInputReport.ExtensionAccel:
_ParseButtons(buff); _ParseButtons(buff);
_ParseAccel(buff); _ParseAccel(buff);
break; break;
case EInputReport.IRAccel:
case EInputReport.IRExtensionAccel: case EInputReport.IRExtensionAccel:
_ParseButtons(buff); _ParseButtons(buff);
_ParseAccel(buff); _ParseAccel(buff);
@@ -693,24 +667,5 @@ namespace Vocaluxe.Lib.Input.WiiMote
Thread.Sleep(100); Thread.Sleep(100);
} }
#endregion Private stuff #endregion Private stuff
#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// ReSharper disable InconsistentNaming
private void Dispose(bool disposing)
// ReSharper restore InconsistentNaming
{
if (disposing)
{
Disconnect();
_ReadDone.Close();
}
}
#endregion
} }
} }