#include <wiimote.h>


Classes | |
| struct | hid |
| struct | recording |
Public Types | |
| enum | input_report { IN_BUTTONS = 0x30, IN_BUTTONS_ACCEL = 0x31, IN_BUTTONS_ACCEL_IR = 0x33, IN_BUTTONS_ACCEL_EXT = 0x35, IN_BUTTONS_ACCEL_IR_EXT = 0x37, IN_BUTTONS_BALANCE_BOARD = 0x32 } |
| typedef wiimote_state_event | state_event |
| typedef std::list< state_event > | state_history |
Public Member Functions | |
| wiimote () | |
| virtual | ~wiimote () |
| bool | operator== (const wiimote &remote) |
| bool | operator!= (const wiimote &remote) |
| bool | IsConnected () const |
| bool | ConnectionLost () const |
| bool | IsBalanceBoard () const |
| bool | NunchukConnected () const |
| bool | ClassicConnected () const |
| bool | MotionPlusConnected () const |
| bool | MotionPlusEnabled () const |
| bool | MotionPlusHasExtension () const |
| bool | IsPlayingAudio () const |
| bool | IsPlayingSample () const |
| bool | IsUsingHIDwrites () const |
| bool | IsRecordingState () const |
| virtual void | ChangedNotifier (state_change_flags changed, const wiimote_state &new_state) |
| bool | Connect (unsigned wiimote_index=FIRST_AVAILABLE, bool force_hidwrites=false) |
| void | Disconnect () |
| void | SetReportType (input_report type, bool continuous=false) |
| bool | EnableMotionPlus () |
| bool | DisableMotionPlus () |
| void | CalibrateAtRest () |
| state_change_flags | RefreshState () |
| void | Reset () |
| void | SetLEDs (BYTE led_bits) |
| void | SetRumble (bool on) |
| void | RumbleForAsync (unsigned milliseconds) |
| bool | MuteSpeaker (bool on) |
| bool | EnableSpeaker (bool on) |
| bool | PlaySquareWave (speaker_freq freq, BYTE volume=0x40) |
| bool | PlaySample (const wiimote_sample &sample, BYTE volume=0x40, speaker_freq freq_override=FREQ_NONE) |
| void | RecordState (state_history &events_out, unsigned max_time_ms=UNTIL_STOP, state_change_flags change_trigger=CHANGED_ALL) |
| void | StopRecording () |
Static Public Member Functions | |
| static unsigned | TotalConnected () |
| static const TCHAR * | GetButtonNameFromBit (unsigned index) |
| static const TCHAR * | GetClassicButtonNameFromBit (unsigned index) |
| static const unsigned | GetFreqLookup (unsigned index) |
| static bool | Load16bitMonoSampleWAV (const TCHAR *filepath, wiimote_sample &out) |
| static bool | Load16BitMonoSampleRAW (const TCHAR *filepath, bool _signed, speaker_freq freq, wiimote_sample &out) |
| static bool | Convert16bitMonoSamples (const short *samples, bool _signed, DWORD length, speaker_freq freq, wiimote_sample &out) |
Public Attributes | |
| QWORD | UniqueID |
| state_changed_callback | ChangedCallback |
| state_change_flags | CallbackTriggerFlags |
Static Public Attributes | |
| static const TCHAR * | ReportTypeName [] |
| static const TCHAR * | ButtonNameFromBit [16] |
| static const TCHAR * | ClassicButtonNameFromBit [16] |
| static const unsigned | FreqLookup [10] |
| static const unsigned | FIRST_AVAILABLE = 0xffffffff |
| static const unsigned | UNTIL_STOP = 0xffffffff |
Definition at line 92 of file wiimote.h.
| typedef std::list<state_event> wiimote::state_history |
| IN_BUTTONS | |
| IN_BUTTONS_ACCEL | |
| IN_BUTTONS_ACCEL_IR | |
| IN_BUTTONS_ACCEL_EXT | |
| IN_BUTTONS_ACCEL_IR_EXT | |
| IN_BUTTONS_BALANCE_BOARD |
Definition at line 108 of file wiimote.h.
{
// combinations if buttons/acceleration/IR/Extension data
IN_BUTTONS = 0x30,
IN_BUTTONS_ACCEL = 0x31,
IN_BUTTONS_ACCEL_IR = 0x33, // reports IR EXTENDED data (dot sizes)
IN_BUTTONS_ACCEL_EXT = 0x35,
IN_BUTTONS_ACCEL_IR_EXT = 0x37, // reports IR BASIC data (no dot sizes)
IN_BUTTONS_BALANCE_BOARD = 0x32, // must use this for the balance board
};
| wiimote::wiimote | ( | ) |
Definition at line 129 of file wiimote.cpp.
References _ASSERT, wiimote_state::Clear(), INVALID_HANDLE_VALUE, TRACE, and WARN.
:
DataRead (CreateEvent(NULL, FALSE, FALSE, NULL)),
Handle (INVALID_HANDLE_VALUE),
ReportType (IN_BUTTONS),
bStatusReceived (false), // for output method detection
bConnectInProgress (true ),
bInitInProgress (false),
bEnablingMotionPlus (false),
bConnectionLost (false), // set if write fails after connection
bMotionPlusDetected (false),
bMotionPlusEnabled (false),
bMotionPlusExtension (false),
bCalibrateAtRest (false),
bUseHIDwrite (false), // if OS supports it
ChangedCallback (NULL),
CallbackTriggerFlags (CHANGED_ALL),
InternalChanged (NO_CHANGE),
CurrentSample (NULL),
HIDwriteThread (NULL),
ReadParseThread (NULL),
SampleThread (NULL),
AsyncRumbleThread (NULL),
AsyncRumbleTimeout (0),
UniqueID (0) // not _guaranteed_ unique, see comments in header
#ifdef ID2_FROM_DEVICEPATH // (see comments in header)
// UniqueID2 (0)
#endif
{
_ASSERT(DataRead != INVALID_HANDLE_VALUE);
// if this is the first wiimote object, detect & enable HID write support
if(++_TotalCreated == 1)
{
HidDLL = LoadLibrary(_T("hid.dll"));
_ASSERT(HidDLL);
if(!HidDLL)
WARN(_T("Couldn't load hid.dll - shouldn't happen!"));
else{
_HidD_SetOutputReport = (hidwrite_ptr)
GetProcAddress(HidDLL, "HidD_SetOutputReport");
if(_HidD_SetOutputReport)
TRACE(_T("OS supports HID writes."));
else
TRACE(_T("OS doesn't support HID writes."));
}
}
// clear our public and private state data completely (including deadzones)
Clear (true);
Internal.Clear(true);
// and the state recording vars
memset(&Recording, 0, sizeof(Recording));
// for overlapped IO (Read/WriteFile)
memset(&Overlapped, 0, sizeof(Overlapped));
Overlapped.hEvent = DataRead;
Overlapped.Offset =
Overlapped.OffsetHigh = 0;
// for async HID output method
InitializeCriticalSection(&HIDwriteQueueLock);
// for polling
InitializeCriticalSection(&StateLock);
// request millisecond timer accuracy
timeBeginPeriod(1);
}
| wiimote::~wiimote | ( | ) | [virtual] |
Definition at line 199 of file wiimote.cpp.
References Disconnect(), and INVALID_HANDLE_VALUE.
{
Disconnect();
// events & critical sections are kept open for the lifetime of the object,
// so tidy them up here:
if(DataRead != INVALID_HANDLE_VALUE)
CloseHandle(DataRead);
DeleteCriticalSection(&HIDwriteQueueLock);
DeleteCriticalSection(&StateLock);
// tidy up timer accuracy request
timeEndPeriod(1);
// release HID DLL (for dynamic HID write method)
if((--_TotalCreated == 0) && HidDLL)
{
FreeLibrary(HidDLL);
HidDLL = NULL;
_HidD_SetOutputReport = NULL;
}
}
| void wiimote::CalibrateAtRest | ( | ) |
Definition at line 467 of file wiimote.cpp.
References _ASSERT, wiimote_state::balance_board::AtRestKg, wiimote_state::BalanceBoard, IsBalanceBoard(), IsConnected(), wiimote_state::balance_board::Kg, RefreshState(), and TRACE.
{
_ASSERT(IsConnected());
if(!IsConnected())
return;
// the app calls this to remove 'at rest' offsets from the analogue sensor
// values (currently only works for the Balance Board):
if(IsBalanceBoard()) {
TRACE(_T(".. removing 'at rest' BBoard offsets."));
Internal.BalanceBoard.AtRestKg = Internal.BalanceBoard.Kg;
RefreshState();
}
}
| virtual void wiimote::ChangedNotifier | ( | state_change_flags | changed, |
| const wiimote_state & | new_state | ||
| ) | [inline, virtual] |
| bool wiimote::ClassicConnected | ( | ) | const [inline] |
Definition at line 130 of file wiimote.h.
References wiimote_state::bExtension, wiimote_state::CLASSIC, and wiimote_state::ExtensionType.
{ return (Internal.bExtension &&
(Internal.ExtensionType==wiimote_state::CLASSIC)); }
| bool wiimote::Connect | ( | unsigned | wiimote_index = FIRST_AVAILABLE, |
| bool | force_hidwrites = false |
||
| ) |
Definition at line 224 of file wiimote.cpp.
References _ASSERT, wiimote_state::CalibrationInfo, CallbackTriggerFlags, ChangedCallback, ChangedNotifier(), wiimote_state::Clear(), CONNECTED, DEEP_TRACE, DETECT_MPLUS_COUNT, DETECT_MPLUS_EVERY_MS, Disconnect(), FIRST_AVAILABLE, INVALID_HANDLE_VALUE, IsConnected(), NO_CHANGE, RefreshState(), REQUEST_STATUS_EVERY_MS, Reset(), TRACE, UniqueID, and WARN.
{
if(wiimote_index == FIRST_AVAILABLE)
TRACE(_T("Connecting first available Wiimote:"));
else
TRACE(_T("Connecting Wiimote %u:"), wiimote_index);
// auto-disconnect if user is being naughty
if(IsConnected())
Disconnect();
// get the GUID of the HID class
GUID guid;
HidD_GetHidGuid(&guid);
// get a handle to all devices that are part of the HID class
// Brian: Fun fact: DIGCF_PRESENT worked on my machine just fine. I reinstalled
// Vista, and now it no longer finds the Wiimote with that parameter enabled...
HDEVINFO dev_info = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_DEVICEINTERFACE);// | DIGCF_PRESENT);
if(!dev_info) {
WARN(_T("couldn't get device info"));
return false;
}
// enumerate the devices
SP_DEVICE_INTERFACE_DATA didata;
didata.cbSize = sizeof(didata);
unsigned index = 0;
unsigned wiimotes_found = 0;
while(SetupDiEnumDeviceInterfaces(dev_info, NULL, &guid, index, &didata))
{
// get the buffer size for this device detail instance
DWORD req_size = 0;
SetupDiGetDeviceInterfaceDetail(dev_info, &didata, NULL, 0, &req_size, NULL);
// (bizarre way of doing it) create a buffer large enough to hold the
// fixed-size detail struct components, and the variable string size
SP_DEVICE_INTERFACE_DETAIL_DATA *didetail =
(SP_DEVICE_INTERFACE_DETAIL_DATA*) new BYTE[req_size];
_ASSERT(didetail);
didetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
// now actually get the detail struct
if(!SetupDiGetDeviceInterfaceDetail(dev_info, &didata, didetail,
req_size, &req_size, NULL)) {
WARN(_T("couldn't get devinterface info for %u"), index);
break;
}
// open a shared handle to the device to query it (this will succeed even
// if the wiimote is already Connect()'ed)
DEEP_TRACE(_T(".. querying device %s"), didetail->DevicePath);
Handle = CreateFile(didetail->DevicePath, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if(Handle == INVALID_HANDLE_VALUE) {
DEEP_TRACE(_T(".... failed with err %x (probably harmless)."),
GetLastError());
goto skip;
}
// get the device attributes
HIDD_ATTRIBUTES attrib;
attrib.Size = sizeof(attrib);
if(HidD_GetAttributes(Handle, &attrib))
{
// is this a wiimote?
if((attrib.VendorID != VID) || (attrib.ProductID != PID))
goto skip;
// yes, but is it the one we're interested in?
++wiimotes_found;
if((wiimote_index != FIRST_AVAILABLE) &&
(wiimote_index != wiimotes_found))
goto skip;
// the wiimote is installed, but it may not be currently paired:
if(wiimote_index == FIRST_AVAILABLE)
TRACE(_T(".. opening Wiimote %u:"), wiimotes_found);
else
TRACE(_T(".. opening:"));
// re-open the handle, but this time we don't allow write sharing
// (that way subsequent calls can still _discover_ wiimotes above, but
// will correctly fail here if they're already connected)
CloseHandle(Handle);
// note this also means that if another application has already opened
// the device, the library can no longer connect it (this may happen
// with software that enumerates all joysticks in the system, because
// even though the wiimote is not a standard joystick (and can't
// be read as such), it unfortunately announces itself to the OS
// as one. The SDL library was known to do grab wiimotes like this.
// If you cannot stop the application from doing it, you may change the
// call below to open the device in full shared mode - but then the
// library can no longer detect if you've already connected a device
// and will allow you to connect it twice! So be careful ...
Handle = CreateFile(didetail->DevicePath, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ,
NULL, OPEN_EXISTING,
FILE_FLAG_OVERLAPPED, NULL);
if(Handle == INVALID_HANDLE_VALUE) {
TRACE(_T(".... failed with err %x"), GetLastError());
goto skip;
}
// clear the wiimote state & buffers
Clear (false); // preserves existing deadzones
Internal.Clear(false); // "
InternalChanged = NO_CHANGE;
memset(ReadBuff , 0, sizeof(ReadBuff));
bConnectionLost = false;
bConnectInProgress = true; // don't parse extensions or request regular
// updates until complete
// enable async reading
BeginAsyncRead();
// autodetect which write method the Bluetooth stack supports,
// by requesting the wiimote status report:
if(force_hidwrites && !_HidD_SetOutputReport) {
TRACE(_T(".. can't force HID writes (not supported)"));
force_hidwrites = false;
}
if(force_hidwrites)
TRACE(_T(".. (HID writes forced)"));
else{
// - try WriteFile() first as it's the most efficient (it uses
// harware interrupts where possible and is async-capable):
bUseHIDwrite = false;
RequestStatusReport();
// and wait for the report to arrive:
DWORD last_time = timeGetTime();
while(!bStatusReceived && ((timeGetTime()-last_time) < 500))
Sleep(10);
TRACE(_T(".. WriteFile() %s."), bStatusReceived? _T("succeeded") :
_T("failed"));
}
// try HID write method (if supported)
if(!bStatusReceived && _HidD_SetOutputReport)
{
bUseHIDwrite = true;
RequestStatusReport();
// wait for the report to arrive:
DWORD last_time = timeGetTime();
while(!bStatusReceived && ((timeGetTime()-last_time) < 500))
Sleep(10);
// did we get it?
TRACE(_T(".. HID write %s."), bStatusReceived? _T("succeeded") :
_T("failed"));
}
// still failed?
if(!bStatusReceived) {
WARN(_T("output failed - wiimote is not connected (or confused)."));
Disconnect();
goto skip;
}
//Sleep(500);
// reset it
Reset();
// read the wiimote calibration info
ReadCalibration();
// allow the result(s) to come in (so that the caller can immediately test
// MotionPlusConnected()
Sleep(300); // note, don't need it on my system, better to be safe though
// connected succesfully:
_TotalConnected++;
// use the first incomding analogue sensor values as the 'at rest'
// offsets (only supports the Balance Board currently)
bCalibrateAtRest = true;
// refresh the public state from the internal one (so that everything
// is available straight away
RefreshState();
// attempt to construct a unique hardware ID from the calibration
// data bytes (this is obviously not guaranteed to be unique across
// all devices, but may work fairly well in practice... ?)
memcpy(&UniqueID, &CalibrationInfo, sizeof(CalibrationInfo));
_ASSERT(UniqueID != 0); // if this fires, the calibration data didn't
// arrive - this shouldn't happen
#ifdef ID2_FROM_DEVICEPATH // (see comments in header)
// create a 2nd alternative id by simply adding all the characters
// in the device path to create a single number
UniqueID2 = 0;
for(unsigned index=0; index<_tcslen(didetail->DevicePath); index++)
UniqueID2 += didetail->DevicePath[index];
#endif
// and show when we want to trigger the next periodic status request
// (for battery level and connection loss detection)
NextStatusTime = timeGetTime() + REQUEST_STATUS_EVERY_MS;
NextMPlusDetectTime = timeGetTime() + DETECT_MPLUS_EVERY_MS;
MPlusDetectCount = DETECT_MPLUS_COUNT;
// tidy up
delete[] (BYTE*)didetail;
break;
}
skip:
// tidy up
delete[] (BYTE*)didetail;
if(Handle != INVALID_HANDLE_VALUE) {
CloseHandle(Handle);
Handle = INVALID_HANDLE_VALUE;
}
// if this was the specified wiimote index, abort
if((wiimote_index != FIRST_AVAILABLE) &&
(wiimote_index == (wiimotes_found-1)))
break;
index++;
}
// clean up our list
SetupDiDestroyDeviceInfoList(dev_info);
bConnectInProgress = false;
if(IsConnected()) {
TRACE(_T(".. connected!"));
// notify the callbacks (if requested to do so)
if(CallbackTriggerFlags & CONNECTED)
{
ChangedNotifier(CONNECTED, Internal);
if(ChangedCallback)
ChangedCallback(*this, CONNECTED, Internal);
}
return true;
}
TRACE(_T(".. connection failed."));
return false;
}
| bool wiimote::ConnectionLost | ( | ) | const [inline] |
| bool wiimote::Convert16bitMonoSamples | ( | const short * | samples, |
| bool | _signed, | ||
| DWORD | length, | ||
| speaker_freq | freq, | ||
| wiimote_sample & | out | ||
| ) | [static] |
Definition at line 2594 of file wiimote.cpp.
References _ASSERT, wiimote_sample::freq, wiimote_sample::length, and wiimote_sample::samples.
Referenced by Load16BitMonoSampleRAW(), and Load16bitMonoSampleWAV().
{
// converts 16bit mono sample data to the native 4bit format used by the Wiimote,
// and returns the data in a BYTE array (caller must delete[] when no
// longer needed):
memset(&out, 0, sizeof(0));
_ASSERT(samples && length);
if(!samples || !length)
return false;
// allocate the output buffer
out.samples = new BYTE[length];
_ASSERT(out.samples);
if(!out.samples)
return false;
// clear it
memset(out.samples, 0, length);
out.length = length;
out.freq = freq;
// ADPCM code, adapted from
// http://www.wiindows.org/index.php/Talk:Wiimote#Input.2FOutput_Reports
static const int index_table[16] = { -1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8 };
static const int diff_table [16] = { 1, 3, 5, 7, 9, 11, 13, 15,
-1, -3, -5, -7, -9, -11, -13, 15 };
static const int step_scale [16] = { 230, 230, 230, 230, 307, 409, 512, 614,
230, 230, 230, 230, 307, 409, 512, 614 };
// Encode to ADPCM, on initialization set adpcm_prev_value to 0 and adpcm_step
// to 127 (these variables must be preserved across reports)
int adpcm_prev_value = 0;
int adpcm_step = 127;
for(size_t i=0; i<length; i++)
{
// convert to 16bit signed
int value = samples[i];// (8bit) << 8);// | samples[i]; // dither it?
if(!_signed)
value -= 32768;
// encode:
int diff = value - adpcm_prev_value;
BYTE encoded_val = 0;
if(diff < 0) {
encoded_val |= 8;
diff = -diff;
}
diff = (diff << 2) / adpcm_step;
if (diff > 7)
diff = 7;
encoded_val |= diff;
adpcm_prev_value += ((adpcm_step * diff_table[encoded_val]) / 8);
if(adpcm_prev_value > 0x7fff)
adpcm_prev_value = 0x7fff;
if(adpcm_prev_value < -0x8000)
adpcm_prev_value = -0x8000;
adpcm_step = (adpcm_step * step_scale[encoded_val]) >> 8;
if(adpcm_step < 127)
adpcm_step = 127;
if(adpcm_step > 24567)
adpcm_step = 24567;
if(i & 1)
out.samples[i>>1] |= encoded_val;
else
out.samples[i>>1] |= encoded_val << 4;
}
return true;
}
| bool wiimote::DisableMotionPlus | ( | ) |
Definition at line 1086 of file wiimote.cpp.
References TRACE.
Referenced by Reset().
{
if(!bMotionPlusDetected || !bMotionPlusEnabled)
return false;
TRACE(_T("Disabling Motion Plus:"));
// disable it (this makes standard extensions visible again)
WriteData(REGISTER_EXTENSION_INIT1, 0x55);
return true;
}
| void wiimote::Disconnect | ( | ) |
Definition at line 482 of file wiimote.cpp.
References _ASSERT, wiimote_state::Clear(), INVALID_HANDLE_VALUE, IsConnected(), NO_CHANGE, Reset(), TRACE, and UniqueID.
Referenced by Connect(), and ~wiimote().
{
if(Handle == INVALID_HANDLE_VALUE)
return;
TRACE(_T("Disconnect()."));
if(IsConnected())
{
_ASSERT(_TotalConnected > 0); // sanity
_TotalConnected--;
if(!bConnectionLost)
Reset();
}
CloseHandle(Handle);
Handle = INVALID_HANDLE_VALUE;
UniqueID = 0;
#ifdef ID2_FROM_DEVICEPATH // (see comments in header)
UniqueID2 = 0;
#endif
// close the read thread
if(ReadParseThread) {
// unblock it so it can realise we're closing and exit straight away
SetEvent(DataRead);
WaitForSingleObject(ReadParseThread, 3000);
CloseHandle(ReadParseThread);
ReadParseThread = NULL;
}
// close the rumble thread
if(AsyncRumbleThread) {
WaitForSingleObject(AsyncRumbleThread, 3000);
CloseHandle(AsyncRumbleThread);
AsyncRumbleThread = NULL;
AsyncRumbleTimeout = 0;
}
// and the sample streaming thread
if(SampleThread) {
WaitForSingleObject(SampleThread, 3000);
CloseHandle(SampleThread);
SampleThread = NULL;
}
#ifndef USE_DYNAMIC_HIDQUEUE
HID.Deallocate();
#endif
bStatusReceived = false;
// and clear the state
Clear (false); // (preserves deadzones)
Internal.Clear(false); // "
InternalChanged = NO_CHANGE;
}
| bool wiimote::EnableMotionPlus | ( | ) |
Definition at line 1062 of file wiimote.cpp.
References _ASSERT, and TRACE.
{
_ASSERT(bMotionPlusDetected);
if(!bMotionPlusDetected)
return false;
if(bMotionPlusEnabled)
return true;
TRACE(_T("Enabling Motion Plus:"));
bMotionPlusExtension = false;
bInitInProgress = true;
bEnablingMotionPlus = true;
// Initialize it:
WriteData(REGISTER_MOTIONPLUS_INIT , 0x55);
// Sleep(50);
// Enable it (this maps it to the standard extension port):
WriteData(REGISTER_MOTIONPLUS_ENABLE, 0x04);
// Sleep(50);
Sleep(500);
return true;
}
| bool wiimote::EnableSpeaker | ( | bool | on ) |
Definition at line 2208 of file wiimote.cpp.
References _ASSERT, wiimote_state::speaker::bEnabled, wiimote_state::speaker::Freq, FREQ_NONE, IsConnected(), MuteSpeaker(), wiimote_state::Speaker, TRACE, and wiimote_state::speaker::Volume.
Referenced by PlaySample(), PlaySquareWave(), and Reset().
{
_ASSERT(IsConnected());
if(!IsConnected())
return false;
if(Internal.Speaker.bEnabled == on)
return true;
if(on) TRACE(_T("enabling speaker.")); else TRACE(_T("disabling speaker."));
BYTE buff [REPORT_LENGTH] = {0};
buff[0] = OUT_SPEAKER_ENABLE;
buff[1] = (on? 0x04 : 0x00) | GetRumbleBit();
if(!WriteReport(buff))
return false;
if(!on) {
Internal.Speaker.Freq = FREQ_NONE;
Internal.Speaker.Volume = 0;
MuteSpeaker(true);
}
Internal.Speaker.bEnabled = on;
return true;
}
| static const TCHAR* wiimote::GetButtonNameFromBit | ( | unsigned | index ) | [inline, static] |
Definition at line 169 of file wiimote.h.
References _ASSERT, ButtonNameFromBit, and TOTAL_BUTTON_BITS.
{
_ASSERT(index < TOTAL_BUTTON_BITS);
if(index >= TOTAL_BUTTON_BITS)
return _T("[invalid index]");
return ButtonNameFromBit[index];
}
| static const TCHAR* wiimote::GetClassicButtonNameFromBit | ( | unsigned | index ) | [inline, static] |
Definition at line 179 of file wiimote.h.
References _ASSERT, ClassicButtonNameFromBit, and TOTAL_BUTTON_BITS.
{
_ASSERT(index < TOTAL_BUTTON_BITS);
if(index >= TOTAL_BUTTON_BITS)
return _T("[invalid index]");
return ClassicButtonNameFromBit[index];
}
| static const unsigned wiimote::GetFreqLookup | ( | unsigned | index ) | [inline, static] |
Definition at line 189 of file wiimote.h.
References _ASSERT, FreqLookup, and TOTAL_FREQUENCIES.
{
_ASSERT(index < TOTAL_FREQUENCIES);
if(index >= TOTAL_FREQUENCIES)
return 0;
return FreqLookup[index];
}
| bool wiimote::IsBalanceBoard | ( | ) | const [inline] |
Definition at line 126 of file wiimote.h.
References wiimote_state::BALANCE_BOARD, wiimote_state::bExtension, and wiimote_state::ExtensionType.
Referenced by CalibrateAtRest(), Reset(), and SetReportType().
{ return (Internal.bExtension &&
(Internal.ExtensionType==wiimote_state::BALANCE_BOARD)); }
| bool wiimote::IsConnected | ( | ) | const [inline] |
Definition at line 123 of file wiimote.h.
Referenced by CalibrateAtRest(), Connect(), Disconnect(), EnableSpeaker(), MuteSpeaker(), PlaySample(), PlaySquareWave(), RumbleForAsync(), SetLEDs(), SetReportType(), and SetRumble().
{ return bStatusReceived; }
| bool wiimote::IsPlayingAudio | ( | ) | const [inline] |
Definition at line 135 of file wiimote.h.
References wiimote_state::speaker::Freq, wiimote_state::Speaker, and wiimote_state::speaker::Volume.
Referenced by IsPlayingSample(), PlaySquareWave(), and SetRumble().
| bool wiimote::IsPlayingSample | ( | ) | const [inline] |
Definition at line 137 of file wiimote.h.
References IsPlayingAudio().
Referenced by PlaySquareWave().
{ return IsPlayingAudio() &&
(CurrentSample != NULL); }
| bool wiimote::IsRecordingState | ( | ) | const [inline] |
| bool wiimote::IsUsingHIDwrites | ( | ) | const [inline] |
| bool wiimote::Load16BitMonoSampleRAW | ( | const TCHAR * | filepath, |
| bool | _signed, | ||
| speaker_freq | freq, | ||
| wiimote_sample & | out | ||
| ) | [static] |
Definition at line 2530 of file wiimote.cpp.
References _ASSERT, Convert16bitMonoSamples(), TRACE, and WARN.
{
// converts (.wav style) unsigned 16bit mono raw data to the 4bit ADPCM variant
// used by the Wiimote, and returns the data in a BYTE array (caller must
// delete[] it when no longer needed):
memset(&out, 0, sizeof(out));
// get the length of the file
struct _stat file_info;
if(_tstat(filepath, &file_info)) {
WARN(_T("couldn't get filesize for '%s'"), filepath);
return false;
}
DWORD len = file_info.st_size;
_ASSERT(len);
if(!len) {
WARN(_T("zero-size sample file '%s'"), filepath);
return false;
}
unsigned total_samples = (len+1) / 2; // round up just in case file is corrupt
// allocate a buffer to hold the samples to convert
short *samples = new short[total_samples];
_ASSERT(samples);
if(!samples) {
TRACE(_T("Couldn't open '%s"), filepath);
return false;
}
// load them
FILE *file;
bool res;
#if (_MSC_VER >= 1400) // VC 2005+
_tfopen_s(&file, filepath, _T("rb"));
#else
file = _tfopen(filepath, _T("rb"));
#endif
_ASSERT(file);
if(!file) {
TRACE(_T("Couldn't open '%s"), filepath);
goto error;
}
res = (fread(samples, 1, len, file) == len);
fclose(file);
if(!res) {
WARN(_T("Couldn't load file '%s'"), filepath);
goto error;
}
// and convert them
res = Convert16bitMonoSamples(samples, _signed, total_samples, freq, out);
delete[] samples;
return res;
error:
delete[] samples;
return false;
}
| bool wiimote::Load16bitMonoSampleWAV | ( | const TCHAR * | filepath, |
| wiimote_sample & | out | ||
| ) | [static] |
Definition at line 2362 of file wiimote.cpp.
References _ASSERT, ARRAY_ENTRIES, Convert16bitMonoSamples(), FREQ_NONE, FreqLookup, READ, READ_SIZE, TRACE, and WARN.
{
// converts unsigned 16bit mono .wav audio data to the 4bit ADPCM variant
// used by the Wiimote (at least the closest match so far), and returns
// the data in a BYTE array (caller must delete[] it when no longer needed):
memset(&out, 0, sizeof(out));
TRACE(_T("Loading '%s'"), filepath);
FILE *file;
#if (_MSC_VER >= 1400) // VC 2005+
_tfopen_s(&file, filepath, _T("rb"));
#else
file = _tfopen(filepath, _T("rb"));
#endif
_ASSERT(file);
if(!file) {
WARN(_T("Couldn't open '%s"), filepath);
return false;
}
// parse the .wav file
struct riff_chunkheader {
char ckID [4];
DWORD ckSize;
char formType [4];
};
struct chunk_header {
char ckID [4];
DWORD ckSize;
};
union {
WAVEFORMATEX x;
WAVEFORMATEXTENSIBLE xe;
} wf = {0};
riff_chunkheader riff_chunkheader;
chunk_header chunk_header;
speaker_freq freq = FREQ_NONE;
#define READ(data) if(fread(&data, sizeof(data), 1, file) != 1) { \
TRACE(_T(".wav file corrupt")); \
fclose(file); \
return false; \
}
#define READ_SIZE(ptr,size) if(fread(ptr, size, 1, file) != 1) { \
TRACE(_T(".wav file corrupt")); \
fclose(file); \
return false; \
}
// read the riff chunk header
READ(riff_chunkheader);
// valid RIFF file?
_ASSERT(!strncmp(riff_chunkheader.ckID, "RIFF", 4));
if(strncmp(riff_chunkheader.ckID, "RIFF", 4))
goto unsupported; // nope
// valid WAV variant?
_ASSERT(!strncmp(riff_chunkheader.formType, "WAVE", 4));
if(strncmp(riff_chunkheader.formType, "WAVE", 4))
goto unsupported; // nope
// find the format & data chunks
while(1)
{
READ(chunk_header);
if(!strncmp(chunk_header.ckID, "fmt ", 4))
{
// not a valid .wav file?
if(chunk_header.ckSize < 16 ||
chunk_header.ckSize > sizeof(WAVEFORMATEXTENSIBLE))
goto unsupported;
READ_SIZE((BYTE*)&wf.x, chunk_header.ckSize);
// now we know it's true wav file
bool extensible = (wf.x.wFormatTag == WAVE_FORMAT_EXTENSIBLE);
int format = extensible? wf.xe.SubFormat.Data1 :
wf.x .wFormatTag;
// must be uncompressed PCM (the format comparisons also work on
// the 'extensible' header, even though they're named differently)
if(format != WAVE_FORMAT_PCM) {
TRACE(_T(".. not uncompressed PCM"));
goto unsupported;
}
// must be mono, 16bit
if((wf.x.nChannels != 1) || (wf.x.wBitsPerSample != 16)) {
TRACE(_T(".. %d bit, %d channel%s"), wf.x.wBitsPerSample,
wf.x.nChannels,
(wf.x.nChannels>1? _T("s"):_T("")));
goto unsupported;
}
// must be _near_ a supported speaker frequency range (but allow some
// tolerance, especially as the speaker freq values aren't final yet):
unsigned sample_freq = wf.x.nSamplesPerSec;
const unsigned epsilon = 100; // for now
for(unsigned index=1; index<ARRAY_ENTRIES(FreqLookup); index++)
{
if((sample_freq+epsilon) >= FreqLookup[index] &&
(sample_freq-epsilon) <= FreqLookup[index]) {
freq = (speaker_freq)index;
TRACE(_T(".. using speaker freq %u"), FreqLookup[index]);
break;
}
}
if(freq == FREQ_NONE) {
WARN(_T("Couldn't (loosely) match .wav samplerate %u Hz to speaker"),
sample_freq);
goto unsupported;
}
}
else if(!strncmp(chunk_header.ckID, "data", 4))
{
// make sure we got a valid fmt chunk first
if(!wf.x.nBlockAlign)
goto corrupt_file;
// grab the data
unsigned total_samples = chunk_header.ckSize / wf.x.nBlockAlign;
if(total_samples == 0)
goto corrupt_file;
short *samples = new short[total_samples];
size_t read = fread(samples, 2, total_samples, file);
fclose(file);
if(read != total_samples)
{
if(read == 0) {
delete[] samples;
goto corrupt_file;
}
// got a different number, but use them anyway
WARN(_T("found %s .wav audio data than expected (%u/%u samples)"),
((read < total_samples)? _T("less") : _T("more")),
read, total_samples);
total_samples = read;
}
// and convert them
bool res = Convert16bitMonoSamples(samples, true, total_samples, freq,
out);
delete[] samples;
return res;
}
else{
// unknown chunk, skip its data
DWORD chunk_bytes = (chunk_header.ckSize + 1) & ~1L;
if(fseek(file, chunk_bytes, SEEK_CUR))
goto corrupt_file;
}
}
corrupt_file:
WARN(_T(".wav file is corrupt"));
fclose(file);
return false;
unsupported:
WARN(_T(".wav file format not supported (must be mono 16bit PCM)"));
fclose(file);
return false;
}
| bool wiimote::MotionPlusConnected | ( | ) | const [inline] |
| bool wiimote::MotionPlusEnabled | ( | ) | const [inline] |
| bool wiimote::MotionPlusHasExtension | ( | ) | const [inline] |
| bool wiimote::MuteSpeaker | ( | bool | on ) |
Definition at line 2186 of file wiimote.cpp.
References _ASSERT, wiimote_state::speaker::bMuted, IsConnected(), wiimote_state::Speaker, and TRACE.
Referenced by EnableSpeaker(), PlaySample(), and PlaySquareWave().
{
_ASSERT(IsConnected());
if(!IsConnected())
return false;
if(Internal.Speaker.bMuted == on)
return true;
if(on) TRACE(_T("muting speaker." ));
else TRACE(_T("unmuting speaker."));
BYTE buff [REPORT_LENGTH] = {0};
buff[0] = OUT_SPEAKER_MUTE;
buff[1] = (on? 0x04 : 0x00) | GetRumbleBit();
if(!WriteReport(buff))
return false;
Sleep(1);
Internal.Speaker.bMuted = on;
return true;
}
| bool wiimote::NunchukConnected | ( | ) | const [inline] |
Definition at line 128 of file wiimote.h.
References wiimote_state::bExtension, wiimote_state::ExtensionType, and wiimote_state::NUNCHUK.
{ return (Internal.bExtension &&
(Internal.ExtensionType==wiimote_state::NUNCHUK)); }
| bool wiimote::operator!= | ( | const wiimote & | remote ) | [inline] |
| bool wiimote::operator== | ( | const wiimote & | remote ) | [inline] |
| bool wiimote::PlaySample | ( | const wiimote_sample & | sample, |
| BYTE | volume = 0x40, |
||
| speaker_freq | freq_override = FREQ_NONE |
||
| ) |
Definition at line 2669 of file wiimote.cpp.
References _ASSERT, EnableSpeaker(), wiimote_state::speaker::Freq, wiimote_sample::freq, HANDLE(), IsConnected(), MuteSpeaker(), wiimote_state::Speaker, TRACE, wiimote_state::speaker::Volume, WARN, and WORKER_THREAD_PRIORITY.
{
_ASSERT(IsConnected());
if(!IsConnected())
return false;
speaker_freq freq = freq_override? freq_override : sample.freq;
TRACE(_T("playing sample."));
EnableSpeaker(true);
MuteSpeaker (true);
#if 0
// combine everything into one write - faster, seems to work?
BYTE bytes[9] = { 0x00, 0x00, 0x00, 10+freq, vol, 0x00, 0x00, 0x01, 0x01 };
WriteData(0x04a20001, sizeof(bytes), bytes);
#else
// Write 0x01 to register 0x04a20009
WriteData(0x04a20009, 0x01);
// Write 0x08 to register 0x04a20001
WriteData(0x04a20001, 0x08);
// Write 7-byte configuration to registers 0x04a20001-0x04a20008
BYTE bytes[7] = { 0x00, 0x00, 0x00, 10+(BYTE)freq, volume, 0x00, 0x00 };
WriteData(0x04a20001, sizeof(bytes), bytes);
// + Write 0x01 to register 0x04a20008
WriteData(0x04a20008, 0x01);
#endif
Internal.Speaker.Freq = freq;
Internal.Speaker.Volume = volume;
CurrentSample = &sample;
MuteSpeaker(false);
return StartSampleThread();
}
| bool wiimote::PlaySquareWave | ( | speaker_freq | freq, |
| BYTE | volume = 0x40 |
||
| ) |
Definition at line 2725 of file wiimote.cpp.
References _ASSERT, EnableSpeaker(), wiimote_state::speaker::Freq, IsConnected(), IsPlayingAudio(), IsPlayingSample(), MuteSpeaker(), wiimote_state::Speaker, TRACE, and wiimote_state::speaker::Volume.
{
_ASSERT(IsConnected());
if(!IsConnected())
return false;
// if we're already playing a sample, stop it first
if(IsPlayingSample())
CurrentSample = NULL;
// if we're already playing a square wave at this freq and volume, return
else if(IsPlayingAudio() && (Internal.Speaker.Freq == freq) &&
(Internal.Speaker.Volume == volume))
return true;
TRACE(_T("playing square wave."));
// stop playing samples
CurrentSample = 0;
EnableSpeaker(true);
MuteSpeaker (true);
#if 0
// combined everything into one write - much faster, seems to work?
BYTE bytes[9] = { 0x00, 0x00, 0x00, freq, volume, 0x00, 0x00, 0x01, 0x1 };
WriteData(0x04a20001, sizeof(bytes), bytes);
#else
// write 0x01 to register 0xa20009
WriteData(0x04a20009, 0x01);
// write 0x08 to register 0xa20001
WriteData(0x04a20001, 0x08);
// write default sound mode (4bit ADPCM, we assume) 7-byte configuration
// to registers 0xa20001-0xa20008
BYTE bytes[7] = { 0x00, 0x00, 0x00, 10+(BYTE)freq, volume, 0x00, 0x00 };
WriteData(0x04a20001, sizeof(bytes), bytes);
// write 0x01 to register 0xa20008
WriteData(0x04a20008, 0x01);
#endif
Internal.Speaker.Freq = freq;
Internal.Speaker.Volume = volume;
MuteSpeaker(false);
return StartSampleThread();
}
| void wiimote::RecordState | ( | state_history & | events_out, |
| unsigned | max_time_ms = UNTIL_STOP, |
||
| state_change_flags | change_trigger = CHANGED_ALL |
||
| ) |
Definition at line 2770 of file wiimote.cpp.
References StopRecording().
{
// user being naughty?
if(Recording.bEnabled)
StopRecording();
// clear the list
if(!events_out.empty())
events_out.clear();
// start recording
Recording.StateHistory = &events_out;
Recording.StartTimeMS = timeGetTime();
Recording.EndTimeMS = Recording.StartTimeMS + max_time_ms;
Recording.TriggerFlags = change_trigger;
// as this call happens outside the read/parse thread, set the boolean
// which will enable reocrding last, so that all params are in place.
// TODO: * stricly speaking this only works on VC2005+ or better, as it
// automatically places a memory barrier on volatile variables - earlier/
// other compilers may reorder the assignments!). *
Recording.bEnabled = true;
}
| state_change_flags wiimote::RefreshState | ( | ) |
Definition at line 1016 of file wiimote.cpp.
References wiimote_state::ClassicController, wiimote_state::joystick::DeadZone, wiimote_state::nunchuk::Joystick, wiimote_state::classic_controller::JoystickL, wiimote_state::classic_controller::JoystickR, NO_CHANGE, and wiimote_state::Nunchuk.
Referenced by CalibrateAtRest(), and Connect().
{
// nothing changed since the last call?
if(InternalChanged == NO_CHANGE)
return NO_CHANGE;
// copy the internal state to our public data members:
// synchronise the interal state with the read/parse thread (we don't want
// values changing during the copy)
EnterCriticalSection(&StateLock);
// remember which state changed since the last call
state_change_flags changed = InternalChanged;
// preserve the application-set deadzones (if any)
joystick::deadzone nunchuk_deadzone = Nunchuk.Joystick.DeadZone;
joystick::deadzone classic_joyl_deadzone = ClassicController.JoystickL.DeadZone;
joystick::deadzone classic_joyr_deadzone = ClassicController.JoystickR.DeadZone;
// copy the internal state to the public one
*(wiimote_state*)this = Internal;
InternalChanged = NO_CHANGE;
// restore the application-set deadzones
Nunchuk.Joystick.DeadZone = nunchuk_deadzone;
ClassicController.JoystickL.DeadZone = classic_joyl_deadzone;
ClassicController.JoystickR.DeadZone = classic_joyr_deadzone;
LeaveCriticalSection(&StateLock);
return changed;
}
| void wiimote::Reset | ( | ) |
Definition at line 539 of file wiimote.cpp.
References DisableMotionPlus(), EnableSpeaker(), IN_BUTTONS, IN_BUTTONS_BALANCE_BOARD, IsBalanceBoard(), SetLEDs(), SetReportType(), SetRumble(), and TRACE.
Referenced by Connect(), and Disconnect().
{
TRACE(_T("Resetting wiimote."));
if(bMotionPlusEnabled)
DisableMotionPlus();
// stop updates (by setting report type to non-continuous, buttons-only)
if(IsBalanceBoard())
SetReportType(IN_BUTTONS_BALANCE_BOARD, false);
else
SetReportType(IN_BUTTONS, false);
SetRumble (false);
SetLEDs (0x00);
// MuteSpeaker (true);
EnableSpeaker(false);
Sleep(150); // avoids loosing the extension calibration data on Connect()
}
| void wiimote::RumbleForAsync | ( | unsigned | milliseconds ) |
Definition at line 843 of file wiimote.cpp.
References _ASSERT, HANDLE(), IsConnected(), SetRumble(), WARN, and WORKER_THREAD_PRIORITY.
{
// rumble for a fixed amount of time
_ASSERT(IsConnected());
if(!IsConnected())
return;
SetRumble(true);
// show how long thread should wait to disable rumble again
// (it it's currently rumbling it will just extend the time)
AsyncRumbleTimeout = timeGetTime() + milliseconds;
// create the thread?
if(AsyncRumbleThread)
return;
AsyncRumbleThread = (HANDLE)_beginthreadex(NULL, 0, AsyncRumbleThreadfunc, this,
0, NULL);
_ASSERT(AsyncRumbleThread);
if(!AsyncRumbleThread) {
WARN(_T("couldn't create rumble thread!"));
return;
}
SetThreadPriority(AsyncRumbleThread, WORKER_THREAD_PRIORITY);
}
| void wiimote::SetLEDs | ( | BYTE | led_bits ) |
Definition at line 779 of file wiimote.cpp.
References _ASSERT, wiimote_state::leds::Bits, IsConnected(), and wiimote_state::LED.
Referenced by Reset().
{
_ASSERT(IsConnected());
if(!IsConnected() || bInitInProgress)
return;
_ASSERT(led_bits <= 0x0f);
led_bits &= 0xf;
BYTE buff [REPORT_LENGTH] = {0};
buff[0] = OUT_LEDs;
buff[1] = (led_bits<<4) | GetRumbleBit();
WriteReport(buff);
Internal.LED.Bits = led_bits;
}
| void wiimote::SetReportType | ( | input_report | type, |
| bool | continuous = false |
||
| ) |
Definition at line 734 of file wiimote.cpp.
References _ASSERT, wiimote_state::ir::BASIC, wiimote_state::ir::EXTENDED, IN_BUTTONS, IN_BUTTONS_ACCEL_EXT, IN_BUTTONS_ACCEL_IR, IN_BUTTONS_ACCEL_IR_EXT, IN_BUTTONS_BALANCE_BOARD, IsBalanceBoard(), IsConnected(), TRACE, and TYPE2NAME.
Referenced by Reset().
{
_ASSERT(IsConnected());
if(!IsConnected())
return;
// the balance board only uses one type of report
_ASSERT(!IsBalanceBoard() || type == IN_BUTTONS_BALANCE_BOARD);
if(IsBalanceBoard() && (type != IN_BUTTONS_BALANCE_BOARD))
return;
#ifdef TRACE
#define TYPE2NAME(_type) (type==_type)? _T(#_type)
const TCHAR* name = TYPE2NAME(IN_BUTTONS) :
TYPE2NAME(IN_BUTTONS_ACCEL_IR) :
TYPE2NAME(IN_BUTTONS_ACCEL_EXT) :
TYPE2NAME(IN_BUTTONS_ACCEL_IR_EXT) :
TYPE2NAME(IN_BUTTONS_BALANCE_BOARD) :
_T("(unknown??)");
TRACE(_T("ReportType: %s (%s)"), name, (continuous? _T("continuous") :
_T("non-continuous")));
#endif
ReportType = type;
switch(type)
{
case IN_BUTTONS_ACCEL_IR:
EnableIR(wiimote_state::ir::EXTENDED);
break;
case IN_BUTTONS_ACCEL_IR_EXT:
EnableIR(wiimote_state::ir::BASIC);
break;
default:
DisableIR();
break;
}
BYTE buff [REPORT_LENGTH] = {0};
buff[0] = OUT_TYPE;
buff[1] = (continuous ? 0x04 : 0x00) | GetRumbleBit();
buff[2] = (BYTE)type;
WriteReport(buff);
// Sleep(15);
}
| void wiimote::SetRumble | ( | bool | on ) |
Definition at line 796 of file wiimote.cpp.
References _ASSERT, wiimote_state::bRumble, IsConnected(), and IsPlayingAudio().
Referenced by Reset(), and RumbleForAsync().
{
_ASSERT(IsConnected());
if(!IsConnected())
return;
if(Internal.bRumble == on)
return;
Internal.bRumble = on;
// if we're streaming audio, we don't need to send a report (sending it makes
// the audio glitch, and the rumble bit is sent with every report anyway)
if(IsPlayingAudio())
return;
BYTE buff [REPORT_LENGTH] = {0};
buff[0] = OUT_STATUS;
buff[1] = on? 0x01 : 0x00;
WriteReport(buff);
}
| void wiimote::StopRecording | ( | ) |
Definition at line 2795 of file wiimote.cpp.
Referenced by RecordState().
{
if(!Recording.bEnabled)
return;
Recording.bEnabled = false;
// make sure the read/parse thread has time to notice the change (else it might
// still write one more state to the list)
Sleep(10); // too much?
}
| static unsigned wiimote::TotalConnected | ( | ) | [inline, static] |
const TCHAR * wiimote::ButtonNameFromBit [static] |
{ _T("Left") , _T("Right"), _T("Down"), _T("Up"),
_T("Plus") , _T("??") , _T("??") , _T("??") ,
_T("Two") , _T("One") , _T("B") , _T("A") ,
_T("Minus"), _T("??") , _T("??") , _T("Home") }
Definition at line 165 of file wiimote.h.
Referenced by GetButtonNameFromBit().
Definition at line 162 of file wiimote.h.
Referenced by Connect(), and mitk::WiiMoteThread::WiiMoteThread().
Definition at line 159 of file wiimote.h.
Referenced by Connect(), and mitk::WiiMoteThread::WiiMoteThread().
const TCHAR * wiimote::ClassicButtonNameFromBit [static] |
{ _T("??") , _T("TrigR") , _T("Plus") , _T("Home"),
_T("Minus"), _T("TrigL") , _T("Down") , _T("Right") ,
_T("Up") , _T("Left") , _T("ZR") , _T("X") ,
_T("A") , _T("Y") , _T("B") , _T("ZL") }
Definition at line 178 of file wiimote.h.
Referenced by GetClassicButtonNameFromBit().
const unsigned wiimote::FIRST_AVAILABLE = 0xffffffff [static] |
Definition at line 205 of file wiimote.h.
Referenced by Connect(), mitk::WiiMoteThread::ReconnectWiiMote(), and mitk::WiiMoteThread::StartWiiMote().
const unsigned wiimote::FreqLookup [static] |
{ 0, 4200, 3920, 3640, 3360,
3130, 2940, 2760, 2610, 2470 }
Definition at line 188 of file wiimote.h.
Referenced by GetFreqLookup(), and Load16bitMonoSampleWAV().
const TCHAR* wiimote::ReportTypeName[] [static] |
Definition at line 146 of file wiimote.h.
Referenced by Connect(), and Disconnect().
const unsigned wiimote::UNTIL_STOP = 0xffffffff [static] |
1.7.2