diff --git a/dlls/dinput/tests/force_feedback.c b/dlls/dinput/tests/force_feedback.c index acd12f22401..6903e490193 100644 --- a/dlls/dinput/tests/force_feedback.c +++ b/dlls/dinput/tests/force_feedback.c @@ -5467,7 +5467,6 @@ static void test_windows_gaming_input(void) .report_id = 7, .report_len = 10, .report_buf = {7,0x01,0xa0,0x0f,0xd0,0x07,0x70,0xff,0x0a,0x00}, - .todo = TRUE, }, /* set envelope */ { @@ -5475,14 +5474,13 @@ static void test_windows_gaming_input(void) .report_id = 8, .report_len = 8, .report_buf = {8,0x01,0x4c,0x7f,0x28,0x00,0x50,0x00}, - .todo = TRUE, }, /* update effect */ { .code = IOCTL_HID_WRITE_REPORT, .report_id = 3, .report_len = 18, - .report_buf = {3,0x01,0x02,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x5a,0x00,0x00,0x00}, + .report_buf = {3,0x01,0x02,0x08,0x78,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0xff,0xff,0xce,0x00,0x00,0x00}, .wine_only = TRUE, .todo = TRUE, }, @@ -6047,11 +6045,9 @@ static void test_windows_gaming_input(void) ok( hr == S_OK, "get_Kind returned %#lx\n", hr ); ok( periodic_kind == PeriodicForceEffectKind_SawtoothWaveUp, "got kind %u\n", periodic_kind ); hr = IPeriodicForceEffect_SetParameters( periodic_effect, direction, 1.0, 0.1, 0.0, duration ); - todo_wine ok( hr == S_OK, "SetParameters returned %#lx\n", hr ); hr = IPeriodicForceEffect_SetParametersWithEnvelope( periodic_effect, direction, 100.0, 0.1, 0.2, 0.3, 0.4, 0.5, delay, attack_duration, duration, release_duration, 1 ); - todo_wine ok( hr == S_OK, "SetParametersWithEnvelope returned %#lx\n", hr ); IPeriodicForceEffect_Release( periodic_effect ); @@ -6120,11 +6116,9 @@ static void test_windows_gaming_input(void) ok( hr == S_OK, "get_Kind returned %#lx\n", hr ); ok( periodic_kind == PeriodicForceEffectKind_SineWave, "got kind %u\n", periodic_kind ); hr = IPeriodicForceEffect_SetParameters( periodic_effect, direction, 1.0, 0.1, 0.0, duration ); - todo_wine ok( hr == S_OK, "SetParameters returned %#lx\n", hr ); hr = IPeriodicForceEffect_SetParametersWithEnvelope( periodic_effect, direction, 100.0, 0.1, 0.2, 0.3, 0.4, 0.5, delay, duration, duration, duration, 1 ); - todo_wine ok( hr == S_OK, "SetParametersWithEnvelope returned %#lx\n", hr ); IPeriodicForceEffect_Release( periodic_effect ); diff --git a/dlls/windows.gaming.input/force_feedback.c b/dlls/windows.gaming.input/force_feedback.c index 2ed272916c9..3e6b49ee1aa 100644 --- a/dlls/windows.gaming.input/force_feedback.c +++ b/dlls/windows.gaming.input/force_feedback.c @@ -146,7 +146,16 @@ static HRESULT WINAPI effect_impl_put_Parameters( IWineForceFeedbackEffectImpl * case WineForceFeedbackEffectType_Periodic_SquareWave: case WineForceFeedbackEffectType_Periodic_SawtoothWaveDown: case WineForceFeedbackEffectType_Periodic_SawtoothWaveUp: - FIXME("stub!\n"); + impl->repeat_count = params.periodic.repeat_count; + impl->periodic.dwMagnitude = round( params.periodic.gain * 10000 ); + impl->periodic.dwPeriod = 1000000 / params.periodic.frequency; + impl->periodic.dwPhase = round( params.periodic.phase * 36000 ); + impl->periodic.lOffset = round( params.periodic.bias * 10000 ); + impl->params.dwDuration = params.periodic.duration.Duration / 10; + impl->params.dwStartDelay = params.periodic.start_delay.Duration / 10; + impl->directions[0] = round( -params.periodic.direction.X * 10000 ); + impl->directions[1] = round( -params.periodic.direction.Y * 10000 ); + impl->directions[2] = round( -params.periodic.direction.Z * 10000 ); break; case WineForceFeedbackEffectType_Condition_Spring: diff --git a/dlls/windows.gaming.input/periodic_effect.c b/dlls/windows.gaming.input/periodic_effect.c index 81ca60f28ef..8633a8fb9b9 100644 --- a/dlls/windows.gaming.input/periodic_effect.c +++ b/dlls/windows.gaming.input/periodic_effect.c @@ -110,9 +110,26 @@ static HRESULT WINAPI effect_get_Kind( IPeriodicForceEffect *iface, PeriodicForc static HRESULT WINAPI effect_SetParameters( IPeriodicForceEffect *iface, Vector3 direction, FLOAT frequency, FLOAT phase, FLOAT bias, TimeSpan duration ) { - FIXME( "iface %p, direction %s, frequency %f, phase %f, bias %f, duration %I64u stub!\n", iface, + struct periodic_effect *impl = impl_from_IPeriodicForceEffect( iface ); + WineForceFeedbackEffectParameters params = + { + .periodic = + { + .type = WineForceFeedbackEffectType_Periodic_SquareWave + impl->kind, + .direction = direction, + .frequency = frequency, + .phase = phase, + .bias = bias, + .duration = duration, + .repeat_count = 1, + .gain = 1., + }, + }; + + TRACE( "iface %p, direction %s, frequency %f, phase %f, bias %f, duration %I64u.\n", iface, debugstr_vector3( &direction ), frequency, phase, bias, duration.Duration ); - return E_NOTIMPL; + + return IWineForceFeedbackEffectImpl_put_Parameters( impl->IWineForceFeedbackEffectImpl_inner, params, NULL ); } static HRESULT WINAPI effect_SetParametersWithEnvelope( IPeriodicForceEffect *iface, Vector3 direction, FLOAT frequency, FLOAT phase, FLOAT bias, @@ -120,11 +137,36 @@ static HRESULT WINAPI effect_SetParametersWithEnvelope( IPeriodicForceEffect *if TimeSpan attack_duration, TimeSpan sustain_duration, TimeSpan release_duration, UINT32 repeat_count ) { - FIXME( "iface %p, direction %s, frequency %f, phase %f, bias %f, 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 ), + struct periodic_effect *impl = impl_from_IPeriodicForceEffect( iface ); + WineForceFeedbackEffectParameters params = + { + .periodic = + { + .type = WineForceFeedbackEffectType_Periodic_SquareWave + impl->kind, + .direction = direction, + .frequency = frequency, + .phase = phase, + .bias = bias, + .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, + }; + + TRACE( "iface %p, direction %s, frequency %f, phase %f, bias %f, 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 ), frequency, phase, bias, 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 IPeriodicForceEffectVtbl effect_vtbl = diff --git a/dlls/windows.gaming.input/provider.idl b/dlls/windows.gaming.input/provider.idl index 3baac4fe77d..4aacc43d80e 100644 --- a/dlls/windows.gaming.input/provider.idl +++ b/dlls/windows.gaming.input/provider.idl @@ -39,6 +39,7 @@ namespace Windows.Gaming.Input.Custom { typedef struct WineGameControllerVibration WineGameControllerVibration; typedef struct WineConstantEffectParameters WineConstantEffectParameters; typedef struct WineRampEffectParameters WineRampEffectParameters; + typedef struct WinePeriodicEffectParameters WinePeriodicEffectParameters; typedef struct WineForceFeedbackEffectEnvelope WineForceFeedbackEffectEnvelope; typedef union WineForceFeedbackEffectParameters WineForceFeedbackEffectParameters; interface IWineGameControllerProvider; @@ -112,6 +113,19 @@ namespace Windows.Gaming.Input.Custom { FLOAT gain; }; + struct WinePeriodicEffectParameters + { + WineForceFeedbackEffectType type; + Windows.Foundation.Numerics.Vector3 direction; + Windows.Foundation.TimeSpan duration; + Windows.Foundation.TimeSpan start_delay; + UINT32 repeat_count; + FLOAT frequency; + FLOAT phase; + FLOAT bias; + FLOAT gain; + }; + struct WineForceFeedbackEffectEnvelope { FLOAT attack_gain; @@ -125,6 +139,7 @@ namespace Windows.Gaming.Input.Custom { WineForceFeedbackEffectType type; WineConstantEffectParameters constant; WineRampEffectParameters ramp; + WinePeriodicEffectParameters periodic; }; [