static void joydx_inactivate_joy(ALLEGRO_JOYSTICK_DIRECTX *joy) { if (joy->config_state == STATE_UNUSED) return; joy->config_state = STATE_UNUSED; joy->marked = false; if (joy->device) { IDirectInputDevice8_SetEventNotification(joy->device, NULL); IDirectInputDevice8_Release(joy->device); joy->device = NULL; } memset(&joy->guid, 0, sizeof(GUID)); if (joy->waker_event) { CloseHandle(joy->waker_event); joy->waker_event = NULL; } memset(&joy->parent.info, 0, sizeof(joy->parent.info)); /* XXX the joystick name really belongs in joy->parent.info too */ joy->name[0] = '\0'; memset(&joy->joystate, 0, sizeof(joy->joystate)); }
static void dx_dinput_finalize (GObject *object) { ControllerDXDInput *controller = CONTROLLER_DX_DINPUT (object); if (controller->source != NULL) { g_source_remove_poll (controller->source, controller->pollfd); g_source_remove (g_source_get_id (controller->source)); g_source_unref (controller->source); } if (controller->didevice8) IDirectInputDevice8_SetEventNotification (controller->didevice8, NULL); if (controller->format != NULL) { g_free (controller->format->rgodf); g_free (controller->format); controller->format = NULL; } g_free (controller->prevdata); controller->prevdata = NULL; if (controller->event != NULL) { CloseHandle (controller->event); controller->event = 0; } if (controller->store) { g_object_unref (controller->store); controller->store = NULL; } G_OBJECT_CLASS (controller_dx_dinput_parent_class)->finalize (object); }
/* joystick_enum_callback: [primary thread] * Helper function to find out how many joysticks we have and set them up. * At the end joydx_num_joysticks and joydx_joystick[] will be initialised. */ static BOOL CALLBACK joystick_enum_callback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) { DIPROPRANGE property_range = { /* the header */ { sizeof(DIPROPRANGE), // diph.dwSize sizeof(DIPROPHEADER), // diph.dwHeaderSize 0, // diph.dwObj DIPH_DEVICE, // diph.dwHow }, /* the data */ -32767, // lMin +32767 // lMax }; DIPROPDWORD property_deadzone = { /* the header */ { sizeof(DIPROPDWORD), // diph.dwSize sizeof(DIPROPHEADER), // diph.dwHeaderSize 0, // diph.dwObj DIPH_DEVICE, // diph.dwHow }, /* the data */ 2000, // dwData }; DIPROPDWORD property_buffersize = { /* the header */ { sizeof(DIPROPDWORD), // diph.dwSize sizeof(DIPROPHEADER), // diph.dwHeaderSize 0, // diph.dwObj DIPH_DEVICE, // diph.dwHow }, /* the data */ DEVICE_BUFFER_SIZE // number of data items }; LPDIRECTINPUTDEVICE _dinput_device1; LPDIRECTINPUTDEVICE2 dinput_device = NULL; HRESULT hr; LPVOID temp; CAPS_AND_NAMES caps_and_names; ALLEGRO_JOYSTICK_DIRECTX *joy; int num; (void)pvRef; /* check if the joystick already existed before */ joy = joydx_by_guid(lpddi->guidInstance); if (joy) { ALLEGRO_DEBUG("Device %s still exists\n", joydx_guid_string(joy)); joy->marked = true; return DIENUM_CONTINUE; } /* create the DirectInput joystick device */ hr = IDirectInput8_CreateDevice(joystick_dinput, &lpddi->guidInstance, &_dinput_device1, NULL); if (FAILED(hr)) goto Error; /* query the DirectInputDevice2 interface needed for the poll() method */ hr = IDirectInputDevice8_QueryInterface(_dinput_device1, &__al_IID_IDirectInputDevice8A, &temp); IDirectInputDevice8_Release(_dinput_device1); if (FAILED(hr)) goto Error; dinput_device = temp; /* enumerate objects available on the device */ memset(&caps_and_names, 0, sizeof(caps_and_names)); hr = IDirectInputDevice8_EnumObjects(dinput_device, object_enum_callback, &caps_and_names, DIDFT_PSHBUTTON | DIDFT_AXIS | DIDFT_POV); if (FAILED(hr)) goto Error; /* set data format */ hr = IDirectInputDevice8_SetDataFormat(dinput_device, &__al_c_dfDIJoystick); if (FAILED(hr)) goto Error; /* set the range of axes */ hr = IDirectInputDevice8_SetProperty(dinput_device, DIPROP_RANGE, &property_range.diph); if (FAILED(hr)) goto Error; /* set the dead zone of axes */ hr = IDirectInputDevice8_SetProperty(dinput_device, DIPROP_DEADZONE, &property_deadzone.diph); if (FAILED(hr)) goto Error; /* set the buffer size */ hr = IDirectInputDevice8_SetProperty(dinput_device, DIPROP_BUFFERSIZE, &property_buffersize.diph); if (FAILED(hr)) goto Error; /* set up the joystick structure */ joy = joydx_allocate_structure(&num); if (!joy) { ALLEGRO_ERROR("Joystick array full\n"); goto Error; } joy->config_state = STATE_BORN; joy->marked = true; joy->device = dinput_device; memcpy(&joy->guid, &lpddi->guidInstance, sizeof(GUID)); _al_sane_strncpy(joy->name, lpddi->tszInstanceName, sizeof(joy->name)); /* fill in the joystick structure */ fill_joystick_info_using_caps_and_names(joy, &caps_and_names); /* create a thread event for this joystick, unless it was already created */ joy->waker_event = CreateEvent(NULL, false, false, NULL); /* tell the joystick background thread to wake up when this joystick * device's state changes */ hr = IDirectInputDevice8_SetEventNotification(joy->device, joy->waker_event); if (FAILED(hr)) { ALLEGRO_ERROR("SetEventNotification failed for joystick %d: %s\n", num, dinput_err_str(hr)); goto Error; } if (hr == DI_POLLEDDEVICE) { /* This joystick device must be polled -- replace the Event with * a Waitable Timer object. * * Theoretically all polled devices could share a single * waitable timer object. But, really, how many such devices * are there going to be on a system? */ CloseHandle(joy->waker_event); joy->waker_event = CreateWaitableTimer(NULL, false, NULL); if (joy->waker_event == NULL) { ALLEGRO_ERROR("CreateWaitableTimer failed for polled device.\n"); goto Error; } { LARGE_INTEGER due_time; due_time.HighPart = 0; due_time.LowPart = 150; /* 15 ms (arbitrary) */ SetWaitableTimer(joy->waker_event, &due_time, true, /* periodic */ NULL, NULL, false); } } ALLEGRO_INFO("Joystick %d initialized, GUID: %s\n", num, joydx_guid_string(joy)); config_needs_merging = true; return DIENUM_CONTINUE; Error: if (dinput_device) IDirectInputDevice8_Release(dinput_device); if (joy) { joy->device = NULL; joydx_inactivate_joy(joy); } return DIENUM_CONTINUE; }
static gboolean dx_dinput_setup_events (ControllerDXDInput *controller, GError **error) { HRESULT hresult; DIPROPDWORD dword; gint i, k; DXDInputSource *source; if ((controller->event = CreateEvent (NULL, TRUE, FALSE, NULL)) == NULL) { g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED, "CreateEvent failed: %s", g_win32_error_message (GetLastError ())); return FALSE; } controller->format = g_new (DIDATAFORMAT, 1); controller->format->dwSize = sizeof (DIDATAFORMAT); controller->format->dwObjSize = sizeof (DIOBJECTDATAFORMAT); dword.diph.dwSize = sizeof (DIPROPDWORD); dword.diph.dwHeaderSize = sizeof (DIPROPHEADER); dword.diph.dwObj = 0; dword.diph.dwHow = DIPH_DEVICE; /* Get the axis mode so we can use the same in the format */ if (FAILED ((hresult = IDirectInputDevice8_GetProperty (controller->didevice8, DIPROP_AXISMODE, &dword.diph)))) { g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED, "IDirectInputDevice8::GetParameters failed: %s", g_win32_error_message (hresult)); goto fail0; } controller->format->dwFlags = dword.dwData + 1; controller->format->dwNumObjs = controller->num_buttons + controller->num_axes + controller->num_sliders + controller->num_povs; controller->format->rgodf = g_new (DIOBJECTDATAFORMAT, controller->format->dwNumObjs); k = 0; controller->format->dwDataSize = 0; for (i = 0; i < controller->num_buttons; i++) { controller->format->rgodf[k].pguid = NULL; controller->format->rgodf[k].dwOfs = controller->format->dwDataSize; controller->format->rgodf[k].dwType = DIDFT_BUTTON | DIDFT_MAKEINSTANCE (i); controller->format->rgodf[k].dwFlags = 0; controller->format->dwDataSize += 1; k++; } controller->format->dwDataSize = 4*((controller->format->dwDataSize + 3)/4); for (i = 0; i < controller->num_axes; i++) { controller->format->rgodf[k].pguid = NULL; controller->format->rgodf[k].dwOfs = controller->format->dwDataSize; controller->format->rgodf[k].dwType = DIDFT_AXIS | DIDFT_MAKEINSTANCE (i); controller->format->rgodf[k].dwFlags = DIDOI_ASPECTPOSITION; controller->format->dwDataSize += 4; k++; } for (i = 0; i < controller->num_sliders; i++) { controller->format->rgodf[k].pguid = NULL; controller->format->rgodf[k].dwOfs = controller->format->dwDataSize; controller->format->rgodf[k].dwType = DIDFT_AXIS | DIDFT_MAKEINSTANCE (i); controller->format->rgodf[k].dwFlags = DIDOI_ASPECTPOSITION; controller->format->dwDataSize += 4; k++; } for (i = 0; i < controller->num_povs; i++) { controller->format->rgodf[k].pguid = NULL; controller->format->rgodf[k].dwOfs = controller->format->dwDataSize; controller->format->rgodf[k].dwType = DIDFT_POV | DIDFT_MAKEINSTANCE (i); controller->format->rgodf[k].dwFlags = 0; controller->format->dwDataSize += 4; k++; } g_assert (k == controller->format->dwNumObjs); controller->format->dwDataSize = 4*((controller->format->dwDataSize + 3)/4); controller->prevdata = g_malloc (controller->format->dwDataSize); dump_data_format (controller->format); if (FAILED ((hresult = IDirectInputDevice8_SetDataFormat (controller->didevice8, controller->format)))) { g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED, "IDirectInputDevice8::SetDataFormat failed: %s", g_win32_error_message (hresult)); goto fail1; } if (FAILED ((hresult = IDirectInputDevice8_SetEventNotification (controller->didevice8, controller->event)))) { g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED, "IDirectInputDevice8::SetEventNotification failed: %s", g_win32_error_message (hresult)); goto fail2; } if (FAILED ((hresult = IDirectInputDevice8_Acquire (controller->didevice8)))) { g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED, "IDirectInputDevice8::Acquire failed: %s", g_win32_error_message (hresult)); goto fail2; } if (FAILED ((hresult = IDirectInputDevice8_GetDeviceState (controller->didevice8, controller->format->dwDataSize, controller->prevdata)))) { g_set_error (error, GIMP_MODULE_ERROR, GIMP_MODULE_FAILED, "IDirectInputDevice8::GetDeviceState failed: %s", g_win32_error_message (hresult)); goto fail2; } source = (DXDInputSource *) g_source_new (&dx_dinput_event_funcs, sizeof (DXDInputSource)); source->controller = controller; controller->source = (GSource *) source; controller->pollfd = g_new (GPollFD, 1); controller->pollfd->fd = (int) controller->event; controller->pollfd->events = G_IO_IN; g_source_add_poll (&source->source, controller->pollfd); g_source_attach (&source->source, NULL); return TRUE; fail2: IDirectInputDevice8_SetEventNotification (controller->didevice8, NULL); fail1: g_free (controller->format->rgodf); g_free (controller->format); controller->format = NULL; g_free (controller->prevdata); controller->prevdata = NULL; fail0: CloseHandle (controller->event); controller->event = 0; return FALSE; }