DXInput::~DXInput() { traceIn(DXInput::~DXInput); bInputExiting = 1; SetEvent(InputEvents[0]); SetEvent(InputEvents[1]); //WaitForSingleObject(hInputThread, 5000); //CloseHandle(hInputThread); diKeyboard->SetEventNotification(NULL); diMouse->SetEventNotification(NULL); CloseHandle(InputEvents[0]); CloseHandle(InputEvents[1]); DIDestroyKeyboardDevice(); DIDestroyMouseDevice(); diDevice->Release(); bDInputActive = 0; Log(TEXT("DirectInput Freed")); traceOut; }
//----------------------------------------------------------------------------- // Name: InitDirectInput() // Desc: Initialize the DirectInput variables. //----------------------------------------------------------------------------- HRESULT InitDirectInput( HWND hWnd ) { HRESULT hr; // Register with the DirectInput subsystem and get a pointer // to a IDirectInput interface we can use. // Create a DInput object if( FAILED( hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&g_pDI, NULL ) ) ) return hr; // Obtain an interface to the system mouse device. if( FAILED( hr = g_pDI->CreateDevice( GUID_SysMouse, &g_pMouse, NULL ) ) ) return hr; // Set the data format to "mouse format" - a predefined data format // // A data format specifies which controls on a device we // are interested in, and how they should be reported. // // This tells DirectInput that we will be passing a // DIMOUSESTATE structure to IDirectInputDevice::GetDeviceState. if( FAILED( hr = g_pMouse->SetDataFormat( &c_dfDIMouse ) ) ) return hr; // Set the cooperativity level to let DirectInput know how // this device should interact with the system and with other // DirectInput applications. if( FAILED( hr = g_pMouse->SetCooperativeLevel( hWnd, DISCL_EXCLUSIVE|DISCL_FOREGROUND ) ) ) return hr; // Create a win32 event which is signaled when mouse data is availible g_hMouseEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); if( NULL == g_hMouseEvent ) return E_FAIL; // Give the event to the mouse device if( FAILED( hr = g_pMouse->SetEventNotification( g_hMouseEvent ) ) ) return hr; // Setup the buffer size for the mouse data DIPROPDWORD dipdw; dipdw.diph.dwSize = sizeof(DIPROPDWORD); dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); dipdw.diph.dwObj = 0; dipdw.diph.dwHow = DIPH_DEVICE; dipdw.dwData = SAMPLE_BUFFER_SIZE; // Arbitary buffer size if( FAILED( hr = g_pMouse->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph ) ) ) return hr; // Not necessary, but nice for left handed users that have // their swapped mouse buttons g_bSwapMouseButtons = GetSystemMetrics( SM_SWAPBUTTON ); return S_OK; }
void WINAPI DICreateKeyboardDevice(HANDLE window) { traceIn(DICreateKeyboardDevice); if(bDInputActive) { HRESULT result; if(diDevice->CreateDevice(GUID_SysKeyboard, &diKeyboard, NULL) != DI_OK) CrashError(TEXT("DInput: Could not Create Keyboard device")); if(diKeyboard->SetDataFormat(&c_dfDIKeyboard) != DI_OK) CrashError(TEXT("DInput: Could not set keyboard data format")); if(diKeyboard->SetCooperativeLevel((HWND)window, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE) != DI_OK) CrashError(TEXT("DInput: Could not set keyboard cooperation level")); if((result = diKeyboard->SetEventNotification(InputEvents[0])) != DI_OK) CrashError(TEXT("DInput: couldn't set a keyboard notification. that sucks.")); if((result = diKeyboard->Acquire()) != DI_OK) { if(result != DIERR_OTHERAPPHASPRIO) CrashError(TEXT("DInput: Could not aquire keyboard device")); } if((result = diKeyboard->GetDeviceState(256, keys)) != DI_OK) { if((result != DIERR_OTHERAPPHASPRIO) && (result != DIERR_NOTACQUIRED)) CrashError(TEXT("DInput: Could not get keyboard device state")); } /*else { keys[DIK_LSHIFT] |= keys[DIK_RSHIFT]; keys[DIK_RSHIFT] = 0; keys[DIK_LCONTROL] |= keys[DIK_RCONTROL]; keys[DIK_RCONTROL] = 0; }*/ } traceOut; }
void WINAPI DICreateMouseDevice(HANDLE window) { traceIn(DICreateMouseDevice); if(bDInputActive) { HRESULT result; if(diDevice->CreateDevice(GUID_SysMouse, &diMouse, NULL) != DI_OK) CrashError(TEXT("DInput: Could not Create Mouse device")); if(diMouse->SetDataFormat(&c_dfDIMouse) != DI_OK) CrashError(TEXT("DInput: Could not set mouse data format")); if(diMouse->SetCooperativeLevel((HWND)window, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE) != DI_OK) CrashError(TEXT("DInput: Could not set mouse cooperation level")); if((result = diMouse->SetEventNotification(InputEvents[1])) != DI_OK) CrashError(TEXT("DInput: couldn't set a mouse notification. that sucks.")); if((result = diMouse->Acquire()) != DI_OK) { if(result != DIERR_OTHERAPPHASPRIO) CrashError(TEXT("DInput: Could not aquire mouse device")); } if((result = diMouse->GetDeviceState(sizeof(DIMOUSESTATE), &mousestate)) != DI_OK) { if((result != DIERR_OTHERAPPHASPRIO) && (result != DIERR_NOTACQUIRED)) CrashError(TEXT("DInput: Could not get mouse state")); curMouseButtonStates = 0; } else { if(mousestate.rgbButtons[0]) curMouseButtonStates |= STATE_LBUTTONDOWN; if(mousestate.rgbButtons[1]) curMouseButtonStates |= STATE_MBUTTONDOWN; if(mousestate.rgbButtons[2]) curMouseButtonStates |= STATE_RBUTTONDOWN; } } traceOut; }
void PsychHIDOSKbQueueStart(int deviceIndex) { LPDIRECTINPUTDEVICE8 kb; DIPROPDWORD dipdw; psych_bool queueActive; int i; if (deviceIndex < 0) { deviceIndex = PsychHIDGetDefaultKbQueueDevice(); // Ok, deviceIndex now contains our default keyboard to use - The first suitable keyboard. } if ((deviceIndex < 0) || (deviceIndex >= ndevices)) { // Out of range index: PsychErrorExitMsg(PsychError_user, "Invalid 'deviceIndex' specified. No such device!"); } // Does Keyboard queue for this deviceIndex already exist? if (NULL == psychHIDKbQueueFirstPress[deviceIndex]) { // No. Bad bad... printf("PsychHID-ERROR: Tried to start processing on non-existent keyboard queue for deviceIndex %i! Call KbQueueCreate first!\n", deviceIndex); PsychErrorExitMsg(PsychError_user, "Invalid keyboard 'deviceIndex' specified. No queue for that device yet!"); } // Keyboard queue already stopped? Then we ain't nothing to do: if (psychHIDKbQueueActive[deviceIndex]) return; // Queue is inactive. Start it: // Will this be the first active queue, ie., aren't there any queues running so far? queueActive = FALSE; for (i = 0; i < PSYCH_HID_MAX_DEVICES; i++) { queueActive |= psychHIDKbQueueActive[i]; } PsychLockMutex(&KbQueueMutex); // Clear out current state for this queue: memset(psychHIDKbQueueFirstPress[deviceIndex] , 0, (256 * sizeof(double))); memset(psychHIDKbQueueFirstRelease[deviceIndex] , 0, (256 * sizeof(double))); memset(psychHIDKbQueueLastPress[deviceIndex] , 0, (256 * sizeof(double))); memset(psychHIDKbQueueLastRelease[deviceIndex] , 0, (256 * sizeof(double))); // Setup event mask, so events from our associated xinput device // get enqueued in our event queue: kb = GetXDevice(deviceIndex); // Device specific data format setup: switch (info[deviceIndex].dwDevType & 0xff) { case DI8DEVTYPE_KEYBOARD: if (DI_OK != kb->SetDataFormat(&c_dfDIKeyboard)) { PsychUnlockMutex(&KbQueueMutex); printf("PsychHID-ERROR: Tried to start processing on keyboard queue for deviceIndex %i, but setting dataformat failed!\n", deviceIndex); PsychErrorExitMsg(PsychError_user, "Starting keyboard queue failed!"); } break; case DI8DEVTYPE_MOUSE: case DI8DEVTYPE_SCREENPOINTER: if (DI_OK != kb->SetDataFormat(&c_dfDIMouse2)) { PsychUnlockMutex(&KbQueueMutex); printf("PsychHID-ERROR: Tried to start processing on keyboard queue for deviceIndex %i, but setting dataformat failed!\n", deviceIndex); PsychErrorExitMsg(PsychError_user, "Starting keyboard queue failed!"); } break; case DI8DEVTYPE_JOYSTICK: if (DI_OK != kb->SetDataFormat(&c_dfDIJoystick2)) { PsychUnlockMutex(&KbQueueMutex); printf("PsychHID-ERROR: Tried to start processing on keyboard queue for deviceIndex %i, but setting dataformat failed!\n", deviceIndex); PsychErrorExitMsg(PsychError_user, "Starting keyboard queue failed!"); } break; } // Set device event buffer size to 256 elements: dipdw.diph.dwSize = sizeof(DIPROPDWORD); dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); dipdw.diph.dwObj = 0; dipdw.diph.dwHow = DIPH_DEVICE; dipdw.dwData = 256; if (DI_OK != kb->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph)) { PsychUnlockMutex(&KbQueueMutex); printf("PsychHID-ERROR: Tried to start processing on keyboard queue for deviceIndex %i, but setting buffersize on device failed!\n", deviceIndex); PsychErrorExitMsg(PsychError_user, "Starting keyboard queue failed!"); } // Enable state-change event notifications: if (DI_OK != kb->SetEventNotification(hEvent)) { PsychUnlockMutex(&KbQueueMutex); printf("PsychHID-ERROR: Tried to start processing on keyboard queue for deviceIndex %i, but setting device state notifications failed!\n", deviceIndex); PsychErrorExitMsg(PsychError_user, "Starting keyboard queue failed!"); } if (DI_OK != kb->Acquire()) { PsychUnlockMutex(&KbQueueMutex); printf("PsychHID-ERROR: Tried to start processing on keyboard queue for deviceIndex %i, but acquiring device failed!\n", deviceIndex); PsychErrorExitMsg(PsychError_user, "Starting keyboard queue failed!"); } // Mark this queue as logically started: psychHIDKbQueueActive[deviceIndex] = TRUE; // Queue started. PsychUnlockMutex(&KbQueueMutex); // If other queues are already active then we're done: if (queueActive) return; // No other active queues. We are the first one. // Start the common processing thread for all queues: PsychLockMutex(&KbQueueMutex); KbQueueThreadTerminate = FALSE; if (PsychCreateThread(&KbQueueThread, NULL, KbQueueWorkerThreadMain, NULL)) { // We are soo screwed: // Cleanup the mess: psychHIDKbQueueActive[deviceIndex] = FALSE; PsychUnlockMutex(&KbQueueMutex); // Whine a little bit: printf("PsychHID-ERROR: Start of keyboard queue processing failed!\n"); PsychErrorExitMsg(PsychError_system, "Creation of keyboard queue background processing thread failed!"); } // Up and running, we're done! PsychUnlockMutex(&KbQueueMutex); return; }
void PsychHIDOSKbQueueStop(int deviceIndex) { LPDIRECTINPUTDEVICE8 kb; psych_bool queueActive; int i; if (deviceIndex < 0) { deviceIndex = PsychHIDGetDefaultKbQueueDevice(); // Ok, deviceIndex now contains our default keyboard to use - The first suitable keyboard. } if ((deviceIndex < 0) || (deviceIndex >= ndevices)) { // Out of range index: PsychErrorExitMsg(PsychError_user, "Invalid 'deviceIndex' specified. No such device!"); } // Keyboard queue for this deviceIndex already exists? if (NULL == psychHIDKbQueueFirstPress[deviceIndex]) { // No. Nothing to do then. return; } // Keyboard queue already stopped? if (!psychHIDKbQueueActive[deviceIndex]) return; // Get device: kb = GetXDevice(deviceIndex); // Queue is active. Stop it: PsychLockMutex(&KbQueueMutex); // Release the device: if (DI_OK != kb->Unacquire()) { PsychUnlockMutex(&KbQueueMutex); printf("PsychHID-ERROR: Tried to stop processing on keyboard queue for deviceIndex %i, but releasing device failed!\n", deviceIndex); PsychErrorExitMsg(PsychError_user, "Stopping keyboard queue failed!"); } // Disable state-change event notifications: if (DI_OK != kb->SetEventNotification(NULL)) { PsychUnlockMutex(&KbQueueMutex); printf("PsychHID-ERROR: Tried to stop processing on keyboard queue for deviceIndex %i, but disabling device state notifications failed!\n", deviceIndex); PsychErrorExitMsg(PsychError_user, "Stopping keyboard queue failed!"); } // Mark queue logically stopped: psychHIDKbQueueActive[deviceIndex] = FALSE; PsychUnlockMutex(&KbQueueMutex); // Was this the last active queue? queueActive = FALSE; for (i = 0; i < PSYCH_HID_MAX_DEVICES; i++) { queueActive |= psychHIDKbQueueActive[i]; } // If more queues are active then we're done: if (queueActive) return; // No more active queues. Shutdown the common processing thread: PsychLockMutex(&KbQueueMutex); KbQueueThreadTerminate = TRUE; // Done. PsychUnlockMutex(&KbQueueMutex); // Shutdown the thread, wait for its termination: PsychDeleteThread(&KbQueueThread); KbQueueThreadTerminate = FALSE; // printf("DEBUG: THREAD JOINED.\n"); fflush(NULL); return; }
HRESULT _stdcall SetEventNotification(HANDLE a) { return RealDevice->SetEventNotification(a); }
int main(int argc, wchar_t* argv[]) { try { HWND wnd; if (FAILED(wnd = CreateWindow(NULL, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL))) throw "Can't create message window"; LPDIRECTINPUT8 di; if (FAILED(DirectInput8Create(GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&di, NULL))) throw "Can't create directinput"; LPDIRECTINPUTDEVICE8 dev; if (FAILED(di->CreateDevice(GUID_SysKeyboard, &dev, NULL))) throw "Can't create device"; if (FAILED(dev->SetDataFormat(&c_dfDIKeyboard))) throw "Can't set keyboard format"; if (FAILED(dev->SetCooperativeLevel(wnd, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE))) throw "Can't set cooperative level."; HANDLE ev = CreateEvent(NULL, FALSE, FALSE, NULL); const size_t buffer_size = 50; { DIPROPDWORD dipdw; dipdw.diph.dwSize = sizeof(DIPROPDWORD); dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); dipdw.diph.dwObj = 0; dipdw.diph.dwHow = DIPH_DEVICE; dipdw.dwData = buffer_size; if (FAILED(dev->SetProperty(DIPROP_BUFFERSIZE, &dipdw.diph))) throw "Couldn't set buffer size"; } if (FAILED(dev->SetEventNotification(ev))) throw "Couldn't set event"; if (FAILED(dev->Acquire())) throw "Failed to acquire"; DIDEVICEOBJECTDATA buffer[buffer_size]; while (WaitForSingleObject(ev, INFINITE) != WAIT_FAILED) { DWORD items = buffer_size; HRESULT hr; if (FAILED(hr = dev->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), buffer, &items, 0))) throw "Couldn't get data"; for (size_t i = 0; i < items; ++i) if (buffer[i].dwData) std::cout << buffer[i].dwData << ", " << buffer[i].dwOfs << std::endl; } return 0; } catch (const char * c) { std::cout << "failure: " << c << std::endl; } catch (HRESULT hr) { std::cout << "failureno: " << hr << std::endl; } catch (...) { std::cout << "general failure" << std::endl; } return 7; }