[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, &params, 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