From f7be6c024d7e888e5abc4a52100abd15ff16ff3e Mon Sep 17 00:00:00 2001 From: Vincent Pelletier Date: Thu, 29 Jan 2009 21:26:30 +0100 Subject: Add support for device gain. Remove support for effect gain, since it incorrectly used device gain, and there is no effect gain available on Linux. Add test for device gain. --- dlls/dinput/effect_linuxinput.c | 10 ++---- dlls/dinput/joystick_linuxinput.c | 37 +++++++++++++++++++++-- dlls/dinput/tests/joystick.c | 60 +++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 10 deletions(-) diff --git a/dlls/dinput/effect_linuxinput.c b/dlls/dinput/effect_linuxinput.c index 155d800..b309af9 100644 --- a/dlls/dinput/effect_linuxinput.c +++ b/dlls/dinput/effect_linuxinput.c @@ -512,12 +512,6 @@ static HRESULT WINAPI LinuxInputEffectImpl_Start( } event.type = EV_FF; - - event.code = FF_GAIN; - event.value = This->gain; - if (write(*(This->fd), &event, sizeof(event)) == -1) - FIXME("Failed setting gain. Error: %d \"%s\".\n", errno, strerror(errno)); - event.code = This->effect.id; event.value = dwIterations; if (write(*(This->fd), &event, sizeof(event)) == -1) { @@ -627,8 +621,10 @@ static HRESULT WINAPI LinuxInputEffectImpl_SetParameters( /* Gain and Sample Period settings are not supported by the linux * event system */ - if (dwFlags & DIEP_GAIN) + if (dwFlags & DIEP_GAIN) { This->gain = 0xFFFF * peff->dwGain / 10000; + TRACE("Effect gain requested but no effect gain functionality present.\n"); + } if (dwFlags & DIEP_SAMPLEPERIOD) TRACE("Sample period requested but no sample period functionality present.\n"); diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c index e1b92f7..c24ade9 100644 --- a/dlls/dinput/joystick_linuxinput.c +++ b/dlls/dinput/joystick_linuxinput.c @@ -194,6 +194,7 @@ struct JoystickImpl struct list ff_effects; int ff_state; int ff_autocenter; + int ff_gain; }; static void fake_current_js_state(JoystickImpl *ji); @@ -461,6 +462,7 @@ static JoystickImpl *alloc_device(REFGUID rguid, const void *jvt, IDirectInputIm Instead, track it with ff_autocenter, and assume it's initialy enabled. */ newDevice->ff_autocenter = 1; + newDevice->ff_gain = 0xFFFF; InitializeCriticalSection(&newDevice->base.crit); newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->base.crit"); @@ -670,12 +672,16 @@ static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface) } else { + struct input_event event; + + event.type = EV_FF; + event.code = FF_GAIN; + event.value = This->ff_gain; + if (write(This->joyfd, &event, sizeof(event)) == -1) + ERR("Failed to set gain (%i): %d %s\n", This->ff_gain, errno, strerror(errno)); if (!This->ff_autocenter) { - struct input_event event; - /* Disable autocenter. */ - event.type = EV_FF; event.code = FF_AUTOCENTER; event.value = 0; if (write(This->joyfd, &event, sizeof(event)) == -1) @@ -974,6 +980,23 @@ static HRESULT WINAPI JoystickAImpl_SetProperty(LPDIRECTINPUTDEVICE8A iface, fake_current_js_state(This); break; } + case (DWORD_PTR)DIPROP_FFGAIN: { + LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph; + + TRACE("DIPROP_FFGAIN(%d)\n", pd->dwData); + This->ff_gain = MulDiv(pd->dwData, 0xFFFF, 10000); + if (This->base.acquired) { + /* Update immediately. */ + struct input_event event; + + event.type = EV_FF; + event.code = FF_GAIN; + event.value = This->ff_gain; + if (write(This->joyfd, &event, sizeof(event)) == -1) + ERR("Failed to set gain (%i): %d %s\n", This->ff_gain, errno, strerror(errno)); + } + break; + } default: return IDirectInputDevice2AImpl_SetProperty(iface, rguid, ph); } @@ -1085,6 +1108,14 @@ static HRESULT WINAPI JoystickAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, TRACE("autocenter(%d)\n", pd->dwData); break; } + case (DWORD_PTR) DIPROP_FFGAIN: + { + LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph; + + pd->dwData = MulDiv(This->ff_gain, 10000, 0xFFFF); + TRACE("DIPROP_FFGAIN(%d)\n", pd->dwData); + break; + } default: return IDirectInputDevice2AImpl_GetProperty(iface, rguid, pdiph); diff --git a/dlls/dinput/tests/joystick.c b/dlls/dinput/tests/joystick.c index 371f7ee..944dbb1 100644 --- a/dlls/dinput/tests/joystick.c +++ b/dlls/dinput/tests/joystick.c @@ -330,6 +330,7 @@ static BOOL CALLBACK EnumJoysticks( LONG cnt1, cnt2; HWND real_hWnd; HINSTANCE hInstance = GetModuleHandle(NULL); + DIPROPDWORD dip_gain_set, dip_gain_get; trace("Testing force-feedback\n"); memset(&eff, 0, sizeof(eff)); @@ -486,6 +487,65 @@ static BOOL CALLBACK EnumJoysticks( ok(hr==DI_OK,"IDirectInputDevice_Acquire() failed: %08x\n", hr); hr = IDirectInputDevice2_GetProperty(pJoystick, DIPROP_AUTOCENTER, &diprop_word.diph); + /* Device gain (DIPROP_FFGAIN). + * From MSDN: + * 0..10000 range, otherwise DIERR_INVALIDPARAM. + * Can be changed even if device is acquired. + * Difference found by tests: + * <0 is refused, >10000 is accepted + */ + dip_gain_set.diph.dwSize = sizeof(DIPROPDWORD); + dip_gain_set.diph.dwHeaderSize = sizeof(DIPROPHEADER); + dip_gain_set.diph.dwObj = 0; + dip_gain_set.diph.dwHow = DIPH_DEVICE; + dip_gain_set.dwData = 10000; + dip_gain_get.diph.dwSize = sizeof(DIPROPDWORD); + dip_gain_get.diph.dwHeaderSize = sizeof(DIPROPHEADER); + dip_gain_get.diph.dwObj = 0; + dip_gain_get.diph.dwHow = DIPH_DEVICE; + dip_gain_get.dwData = 0; + + /* Test device is acquisition (non)impact. */ + hr = IDirectInputDevice_Unacquire(pJoystick); + ok(hr == DI_OK, "IDirectInputDevice_Unacquire() should have returned S_FALSE, got: %08x\n", hr); + dip_gain_set.dwData = 1; + hr = IDirectInputDevice_SetProperty(pJoystick, DIPROP_FFGAIN, &dip_gain_set.diph); + ok(hr==DI_OK, "IDirectInputDevice_SetProperty() failed: %08x\n", hr); + hr = IDirectInputDevice_GetProperty(pJoystick, DIPROP_FFGAIN, &dip_gain_get.diph); + ok(hr==DI_OK, "IDirectInputDevice_GetProperty() failed: %08x\n", hr); + ok(dip_gain_get.dwData==dip_gain_set.dwData, "Gain not udated: %i\n", dip_gain_get.dwData); + hr = IDirectInputDevice_Acquire(pJoystick); + ok(hr==DI_OK,"IDirectInputDevice_Acquire() failed: %08x\n", hr); + dip_gain_set.dwData = 2; + hr = IDirectInputDevice_SetProperty(pJoystick, DIPROP_FFGAIN, &dip_gain_set.diph); + ok(hr==DI_OK, "IDirectInputDevice_SetProperty() failed: %08x\n", hr); + hr = IDirectInputDevice_GetProperty(pJoystick, DIPROP_FFGAIN, &dip_gain_get.diph); + ok(hr==DI_OK, "IDirectInputDevice_GetProperty() failed: %08x\n", hr); + ok(dip_gain_get.dwData==dip_gain_set.dwData, "Gain not udated: %i\n", dip_gain_get.dwData); + /* Test range and internal clamping. */ + dip_gain_set.dwData = -1; + hr = IDirectInputDevice_SetProperty(pJoystick, DIPROP_FFGAIN, &dip_gain_set.diph); + todo_wine ok(hr==DIERR_INVALIDPARAM, "IDirectInputDevice_SetProperty() should have returned %08x: %08x\n", DIERR_INVALIDPARAM, hr); + dip_gain_set.dwData = 0; + hr = IDirectInputDevice_SetProperty(pJoystick, DIPROP_FFGAIN, &dip_gain_set.diph); + ok(hr==DI_OK, "IDirectInputDevice_SetProperty() failed: %08x\n", hr); + hr = IDirectInputDevice_GetProperty(pJoystick, DIPROP_FFGAIN, &dip_gain_get.diph); + ok(hr==DI_OK, "IDirectInputDevice_GetProperty() failed: %08x\n", hr); + ok(dip_gain_get.dwData==dip_gain_set.dwData, "Gain not updated: %i\n", dip_gain_get.dwData); + dip_gain_set.dwData = 10000; + hr = IDirectInputDevice_SetProperty(pJoystick, DIPROP_FFGAIN, &dip_gain_set.diph); + ok(hr==DI_OK, "IDirectInputDevice_SetProperty() failed: %08x\n", hr); + hr = IDirectInputDevice_GetProperty(pJoystick, DIPROP_FFGAIN, &dip_gain_get.diph); + ok(hr==DI_OK, "IDirectInputDevice_GetProperty() failed: %08x\n", hr); + ok(dip_gain_get.dwData==dip_gain_set.dwData, "Gain not updated: %i\n", dip_gain_get.dwData); + /* WARNING: This call succeeds, on the contrary of what is stated on MSDN. */ + dip_gain_set.dwData = 10001; + hr = IDirectInputDevice_SetProperty(pJoystick, DIPROP_FFGAIN, &dip_gain_set.diph); + ok(hr==DI_OK, "IDirectInputDevice_SetProperty() failed: %08x\n", hr); + hr = IDirectInputDevice_GetProperty(pJoystick, DIPROP_FFGAIN, &dip_gain_get.diph); + ok(hr==DI_OK, "IDirectInputDevice_GetProperty() failed: %08x\n", hr); + ok(dip_gain_get.dwData==dip_gain_set.dwData, "Gain not updated: %i\n", dip_gain_get.dwData); + ref = IUnknown_Release(effect); ok(ref == 0, "IDirectInputDevice_Release() reference count = %d\n", ref); } -- 1.5.6.5