Make SpaceNav disposable, remove lock

This commit is contained in:
Thibaud Gasser 2018-05-30 19:36:43 +02:00
parent 6e3b39a78f
commit 50402abe53

View File

@ -3,13 +3,12 @@ using System.Runtime.InteropServices;
namespace spnavwrapper namespace spnavwrapper
{ {
public sealed class SpaceNav public sealed class SpaceNav : IDisposable
{ {
double _sensitivity = 1.0; double _sensitivity = 1.0;
int _threshold = 5; int _threshold = 5;
static SpaceNav instance = null; static SpaceNav instance;
static readonly object padlock = new object();
const int SPNAV_EVENT_MOTION = 1; const int SPNAV_EVENT_MOTION = 1;
const int SPNAV_EVENT_BUTTON = 2; const int SPNAV_EVENT_BUTTON = 2;
@ -53,7 +52,7 @@ namespace spnavwrapper
[DllImport(DLL_NAME)] [DllImport(DLL_NAME)]
static extern int spnav_sensitivity(double sens); static extern int spnav_sensitivity(double sens);
[DllImport(DLL_NAME)] [DllImport(DLL_NAME)]
static extern int spnav_deadzone(int threshold); static extern int spnav_deadzone(int threshold);
SpaceNav() SpaceNav()
{ {
@ -61,107 +60,110 @@ namespace spnavwrapper
spnav_open(SPNAV_VENDOR_ID, SPNAV_PRODUCT_ID); spnav_open(SPNAV_VENDOR_ID, SPNAV_PRODUCT_ID);
} }
~SpaceNav()
{
// TODO : handle retcode
spnav_close();
}
public static SpaceNav Instance public static SpaceNav Instance
{ {
get get
{ {
lock (padlock) if (instance == null)
{ {
if (instance == null) instance = new SpaceNav();
{
instance = new SpaceNav();
}
return instance;
} }
return instance;
} }
} }
public void CloseDevice() public void CloseDevice()
{ {
lock (padlock) spnav_close();
{ instance = null;
spnav_close();
instance = null;
}
} }
public SpaceNavEvent WaitEvent() public SpaceNavEvent WaitEvent()
{ {
lock (padlock) SpNavEvent sev = new SpNavEvent();
spnav_wait_event(ref sev);
switch (sev.type)
{ {
SpNavEvent sev = new SpNavEvent(); case SPNAV_EVENT_BUTTON:
spnav_wait_event(ref sev); return new SpaceNavButtonEvent(Convert.ToBoolean(sev.button.press), sev.button.bnum);
switch (sev.type) case SPNAV_EVENT_MOTION:
{ var ev = sev.motion;
case SPNAV_EVENT_BUTTON: return new SpaceNavMotionEvent(ev.x, ev.y, ev.z, ev.rx, ev.ry, ev.rz);
return new SpaceNavButtonEvent(Convert.ToBoolean(sev.button.press), sev.button.bnum); default:
case SPNAV_EVENT_MOTION: return null;
var ev = sev.motion;
return new SpaceNavMotionEvent(ev.x, ev.y, ev.z, ev.rx, ev.ry, ev.rz);
default:
return null;
}
} }
} }
public SpaceNavEvent WaitEvent(int milliseconds) public SpaceNavEvent WaitEvent(int milliseconds)
{ {
lock (padlock) SpNavEvent sev = new SpNavEvent();
int ev_type = spnav_wait_event_timeout(ref sev, milliseconds);
switch (ev_type)
{ {
SpNavEvent sev = new SpNavEvent(); case SPNAV_EVENT_BUTTON:
int ev_type = spnav_wait_event_timeout(ref sev, milliseconds); return new SpaceNavButtonEvent(Convert.ToBoolean(sev.button.press), sev.button.bnum);
switch (ev_type) case SPNAV_EVENT_MOTION:
{ var ev = sev.motion;
case SPNAV_EVENT_BUTTON: return new SpaceNavMotionEvent(ev.x, ev.y, ev.z, ev.rx, ev.ry, ev.rz);
return new SpaceNavButtonEvent(Convert.ToBoolean(sev.button.press), sev.button.bnum); default:
case SPNAV_EVENT_MOTION: return null;
var ev = sev.motion;
return new SpaceNavMotionEvent(ev.x, ev.y, ev.z, ev.rx, ev.ry, ev.rz);
default:
return null;
}
} }
} }
public double Sensitivity public double Sensitivity
{ {
get get
{ {
return _sensitivity; return _sensitivity;
} }
set set
{ {
lock (padlock) // TODO : handle retcode
{ spnav_sensitivity(value);
// TODO : handle retcode _sensitivity = value;
spnav_sensitivity(value);
_sensitivity = value;
}
} }
} }
public int Threshold public int Threshold
{ {
get get
{ {
return _threshold; return _threshold;
} }
set set
{ {
lock (padlock) // TODO : handle retcode
{ spnav_deadzone(value);
// TODO : handle retcode _threshold = value;
spnav_deadzone(value);
_threshold = value;
}
} }
} }
#region IDisposable Support
private bool disposedValue = false; // To detect redundant calls
void Dispose(bool disposing)
{
if (!disposedValue)
{
// Free unmanaged resources
spnav_close();
disposedValue = true;
}
}
~SpaceNav()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(false);
}
// This code added to correctly implement the disposable pattern.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
} }
} }