dinput: Move gain support from effect to device
Vincent Pelletier
plr.vincent at gmail.com
Sun Feb 1 07:02:31 CST 2009
Le Friday 30 January 2009 02:58:34 Vitaliy Margolen, vous avez écrit :
> First why do you typecase DWORD to (int) to assign to DWORD? Second DWORD
> will always be > 0. If you want to check it against limit then just check
> it being <= 10000 otherwise return error.
[...]
> You should use MulDiv instead because this can be optimized out by compiler
> into something that won't be as accurate.
I store internaly as a DWORD because of those accuracy problems.
Thanks for pointing out this function, attached patch is now more homogeneous
with existing code, and does not do any casting magic.
> You should be checking This->base.acquired instead of fd.
Right, fixed.
Also fixed in test:
- test vs. message incoherent
- typo in test message
--
Vincent Pelletier
-------------- next part --------------
From f7be6c024d7e888e5abc4a52100abd15ff16ff3e Mon Sep 17 00:00:00 2001
From: Vincent Pelletier <plr.vincent at gmail.com>
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
More information about the wine-patches
mailing list