[PATCH v2 4/8] windows.gaming.input: Implement IConstantForceEffect_SetParameters(WithEnvelope).
Rémi Bernon
wine at gitlab.winehq.org
Wed May 18 03:20:48 CDT 2022
From: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
dlls/dinput/tests/force_feedback.c | 6 +-
dlls/windows.gaming.input/constant_effect.c | 45 +++++++++++++--
dlls/windows.gaming.input/force_feedback.c | 62 +++++++++++++++++++++
dlls/windows.gaming.input/provider.idl | 29 ++++++++++
4 files changed, 132 insertions(+), 10 deletions(-)
diff --git a/dlls/dinput/tests/force_feedback.c b/dlls/dinput/tests/force_feedback.c
index 7755cca1927..8d06cdda3d8 100644
--- a/dlls/dinput/tests/force_feedback.c
+++ b/dlls/dinput/tests/force_feedback.c
@@ -5557,7 +5557,6 @@ static void test_windows_gaming_input(void)
.report_id = 9,
.report_len = 4,
.report_buf = {9,0x01,0xc8,0x00},
- .todo = TRUE,
},
/* set envelope */
{
@@ -5565,14 +5564,13 @@ static void test_windows_gaming_input(void)
.report_id = 8,
.report_len = 8,
.report_buf = {8,0x01,0x19,0x4c,0x14,0x00,0x3c,0x00},
- .todo = TRUE,
},
/* update effect */
{
.code = IOCTL_HID_WRITE_REPORT,
.report_id = 3,
.report_len = 18,
- .report_buf = {3,0x01,0x04,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x7f,0x5a,0x00,0x00,0x00},
+ .report_buf = {3,0x01,0x04,0x08,0x5a,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0xff,0x7f,0xce,0x00,0x00,0x00},
.wine_only = TRUE,
.todo = TRUE,
},
@@ -6304,11 +6302,9 @@ static void test_windows_gaming_input(void)
ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
hr = IConstantForceEffect_SetParameters( constant_effect, direction, duration );
- todo_wine
ok( hr == S_OK, "SetParameters returned %#lx\n", hr );
hr = IConstantForceEffect_SetParametersWithEnvelope( constant_effect, direction, 0.1, 0.2, 0.3,
delay, attack_duration, duration, release_duration, 1 );
- todo_wine
ok( hr == S_OK, "SetParametersWithEnvelope returned %#lx\n", hr );
IConstantForceEffect_Release( constant_effect );
diff --git a/dlls/windows.gaming.input/constant_effect.c b/dlls/windows.gaming.input/constant_effect.c
index 928927144b9..0af5d736f48 100644
--- a/dlls/windows.gaming.input/constant_effect.c
+++ b/dlls/windows.gaming.input/constant_effect.c
@@ -99,8 +99,21 @@ static HRESULT WINAPI effect_GetTrustLevel( IConstantForceEffect *iface, TrustLe
static HRESULT WINAPI effect_SetParameters( IConstantForceEffect *iface, Vector3 direction, TimeSpan duration )
{
- FIXME( "iface %p, direction %s, duration %I64u stub!\n", iface, debugstr_vector3( &direction ), duration.Duration );
- return E_NOTIMPL;
+ WineForceFeedbackEffectParameters params =
+ {
+ .constant =
+ {
+ .type = WineForceFeedbackEffectType_Constant,
+ .direction = direction,
+ .duration = duration,
+ .repeat_count = 1,
+ },
+ };
+ struct constant_effect *impl = impl_from_IConstantForceEffect( iface );
+
+ TRACE( "iface %p, direction %s, duration %I64u.\n", iface, debugstr_vector3( &direction ), duration.Duration );
+
+ return IWineForceFeedbackEffectImpl_put_Parameters( impl->IWineForceFeedbackEffectImpl_inner, params, NULL );
}
static HRESULT WINAPI effect_SetParametersWithEnvelope( IConstantForceEffect *iface, Vector3 direction, FLOAT attack_gain,
@@ -108,11 +121,33 @@ static HRESULT WINAPI effect_SetParametersWithEnvelope( IConstantForceEffect *if
TimeSpan attack_duration, TimeSpan sustain_duration,
TimeSpan release_duration, UINT32 repeat_count )
{
- FIXME( "iface %p, direction %s, attack_gain %f, sustain_gain %f, release_gain %f, start_delay %I64u, attack_duration %I64u, "
- "sustain_duration %I64u, release_duration %I64u, repeat_count %u stub!\n", iface, debugstr_vector3( &direction ),
+ WineForceFeedbackEffectParameters params =
+ {
+ .constant =
+ {
+ .type = WineForceFeedbackEffectType_Constant,
+ .direction = direction,
+ .duration = {attack_duration.Duration + sustain_duration.Duration + release_duration.Duration},
+ .start_delay = start_delay,
+ .repeat_count = repeat_count,
+ .gain = sustain_gain,
+ },
+ };
+ WineForceFeedbackEffectEnvelope envelope =
+ {
+ .attack_gain = attack_gain,
+ .release_gain = release_gain,
+ .attack_duration = attack_duration,
+ .release_duration = release_duration,
+ };
+ struct constant_effect *impl = impl_from_IConstantForceEffect( iface );
+
+ TRACE( "iface %p, direction %s, attack_gain %f, sustain_gain %f, release_gain %f, start_delay %I64u, attack_duration %I64u, "
+ "sustain_duration %I64u, release_duration %I64u, repeat_count %u.\n", iface, debugstr_vector3( &direction ),
attack_gain, sustain_gain, release_gain, start_delay.Duration, attack_duration.Duration, sustain_duration.Duration,
release_duration.Duration, repeat_count );
- return E_NOTIMPL;
+
+ return IWineForceFeedbackEffectImpl_put_Parameters( impl->IWineForceFeedbackEffectImpl_inner, params, &envelope );
}
static const struct IConstantForceEffectVtbl effect_vtbl =
diff --git a/dlls/windows.gaming.input/force_feedback.c b/dlls/windows.gaming.input/force_feedback.c
index 667174829f5..ce30db14cd9 100644
--- a/dlls/windows.gaming.input/force_feedback.c
+++ b/dlls/windows.gaming.input/force_feedback.c
@@ -43,10 +43,12 @@ struct effect
GUID type;
DWORD axes[3];
LONG directions[3];
+ ULONG repeat_count;
DICONSTANTFORCE constant_force;
DIRAMPFORCE ramp_force;
DICONDITION condition;
DIPERIODIC periodic;
+ DIENVELOPE envelope;
DIEFFECT params;
};
@@ -107,12 +109,71 @@ static ULONG WINAPI effect_impl_Release( IWineForceFeedbackEffectImpl *iface )
return ref;
}
+static HRESULT WINAPI effect_impl_put_Parameters( IWineForceFeedbackEffectImpl *iface, WineForceFeedbackEffectParameters params,
+ WineForceFeedbackEffectEnvelope *envelope )
+{
+ struct effect *impl = impl_from_IWineForceFeedbackEffectImpl( iface );
+ HRESULT hr;
+
+ TRACE( "iface %p, params %p, envelope %p.\n", iface, ¶ms, envelope );
+
+ EnterCriticalSection( &impl->cs );
+ switch (params.type)
+ {
+ case WineForceFeedbackEffectType_Constant:
+ impl->repeat_count = params.constant.repeat_count;
+ impl->constant_force.lMagnitude = round( params.constant.gain * params.constant.direction.X * 10000 );
+ impl->params.dwDuration = params.constant.duration.Duration / 10;
+ impl->params.dwStartDelay = params.constant.start_delay.Duration / 10;
+ impl->directions[0] = round( -params.constant.direction.X * 10000 );
+ impl->directions[1] = round( -params.constant.direction.Y * 10000 );
+ impl->directions[2] = round( -params.constant.direction.Z * 10000 );
+ break;
+
+ case WineForceFeedbackEffectType_Ramp:
+ FIXME("stub!\n");
+ break;
+
+ case WineForceFeedbackEffectType_Periodic_SineWave:
+ case WineForceFeedbackEffectType_Periodic_TriangleWave:
+ case WineForceFeedbackEffectType_Periodic_SquareWave:
+ case WineForceFeedbackEffectType_Periodic_SawtoothWaveDown:
+ case WineForceFeedbackEffectType_Periodic_SawtoothWaveUp:
+ FIXME("stub!\n");
+ break;
+
+ case WineForceFeedbackEffectType_Condition_Spring:
+ case WineForceFeedbackEffectType_Condition_Damper:
+ case WineForceFeedbackEffectType_Condition_Inertia:
+ case WineForceFeedbackEffectType_Condition_Friction:
+ FIXME("stub!\n");
+ break;
+ }
+
+ if (!envelope) impl->params.lpEnvelope = NULL;
+ else
+ {
+ impl->envelope.dwAttackTime = envelope->attack_duration.Duration / 10;
+ impl->envelope.dwAttackLevel = round( envelope->attack_gain * 10000 );
+ impl->envelope.dwFadeTime = impl->params.dwDuration - envelope->release_duration.Duration / 10;
+ impl->envelope.dwFadeLevel = round( envelope->release_gain * 10000 );
+ impl->params.lpEnvelope = &impl->envelope;
+ }
+
+ if (!impl->effect) hr = S_OK;
+ else hr = IDirectInputEffect_SetParameters( impl->effect, &impl->params, DIEP_ALLPARAMS & ~DIEP_AXES );
+ LeaveCriticalSection( &impl->cs );
+
+ return hr;
+}
+
static const struct IWineForceFeedbackEffectImplVtbl effect_impl_vtbl =
{
effect_impl_QueryInterface,
effect_impl_AddRef,
effect_impl_Release,
/* IWineForceFeedbackEffectImpl methods */
+ effect_impl_put_Parameters,
};
DEFINE_IINSPECTABLE_OUTER( effect, IForceFeedbackEffect, struct effect, IInspectable_outer )
@@ -245,6 +306,7 @@ HRESULT force_feedback_effect_create( enum WineForceFeedbackEffectType type, IIn
break;
}
+ impl->envelope.dwSize = sizeof(DIENVELOPE);
impl->params.dwSize = sizeof(DIEFFECT);
impl->params.rgdwAxes = impl->axes;
impl->params.rglDirection = impl->directions;
diff --git a/dlls/windows.gaming.input/provider.idl b/dlls/windows.gaming.input/provider.idl
index 128e68893a9..16d394e7afa 100644
--- a/dlls/windows.gaming.input/provider.idl
+++ b/dlls/windows.gaming.input/provider.idl
@@ -37,6 +37,9 @@ namespace Windows.Gaming.Input.Custom {
typedef enum WineForceFeedbackEffectType WineForceFeedbackEffectType;
typedef struct WineGameControllerState WineGameControllerState;
typedef struct WineGameControllerVibration WineGameControllerVibration;
+ typedef struct WineConstantEffectParameters WineConstantEffectParameters;
+ typedef struct WineForceFeedbackEffectEnvelope WineForceFeedbackEffectEnvelope;
+ typedef union WineForceFeedbackEffectParameters WineForceFeedbackEffectParameters;
interface IWineGameControllerProvider;
runtimeclass WineGameControllerProvider;
@@ -87,6 +90,30 @@ namespace Windows.Gaming.Input.Custom {
UINT16 right;
};
+ struct WineConstantEffectParameters
+ {
+ WineForceFeedbackEffectType type;
+ Windows.Foundation.Numerics.Vector3 direction;
+ Windows.Foundation.TimeSpan duration;
+ Windows.Foundation.TimeSpan start_delay;
+ UINT32 repeat_count;
+ FLOAT gain;
+ };
+
+ struct WineForceFeedbackEffectEnvelope
+ {
+ FLOAT attack_gain;
+ FLOAT release_gain;
+ Windows.Foundation.TimeSpan attack_duration;
+ Windows.Foundation.TimeSpan release_duration;
+ };
+
+ union WineForceFeedbackEffectParameters
+ {
+ WineForceFeedbackEffectType type;
+ WineConstantEffectParameters constant;
+ };
+
[
uuid(06e58977-7684-4dc5-bad1-cda52a4aa06d)
]
@@ -122,6 +149,8 @@ namespace Windows.Gaming.Input.Custom {
interface IWineForceFeedbackEffectImpl : IUnknown
requires Windows.Gaming.Input.ForceFeedback.IForceFeedbackEffect
{
+ [propput] HRESULT Parameters([in] WineForceFeedbackEffectParameters parameters,
+ [in, optional] WineForceFeedbackEffectEnvelope *envelope);
}
[
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/87
More information about the wine-devel
mailing list