Andrew Eikum : dinput: Implement force feedback functions for OSX joysticks .

Alexandre Julliard julliard at winehq.org
Tue May 21 13:56:27 CDT 2013


Module: wine
Branch: master
Commit: 3de75b1e95187c6d1d68fe35f064cbea7edef3c3
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=3de75b1e95187c6d1d68fe35f064cbea7edef3c3

Author: Andrew Eikum <aeikum at codeweavers.com>
Date:   Mon May 20 14:10:33 2013 -0500

dinput: Implement force feedback functions for OSX joysticks.

---

 dlls/dinput/joystick_osx.c |  230 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 228 insertions(+), 2 deletions(-)

diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index 66a4acb..0d3927a 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -111,6 +111,7 @@ struct JoystickImpl
     CFMutableArrayRef      elementCFArrayRef;
     ObjProps               **propmap;
     FFDeviceObjectReference ff;
+    struct list effects;
 };
 
 static inline JoystickImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface)
@@ -124,6 +125,24 @@ static inline JoystickImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W
            JoystickGenericImpl, base), JoystickImpl, generic);
 }
 
+typedef struct _EffectImpl {
+    IDirectInputEffect IDirectInputEffect_iface;
+    LONG ref;
+
+    JoystickImpl *device;
+    FFEffectObjectReference effect;
+    GUID guid;
+
+    struct list entry;
+} EffectImpl;
+
+static EffectImpl *impl_from_IDirectInputEffect(IDirectInputEffect *iface)
+{
+    return CONTAINING_RECORD(iface, EffectImpl, IDirectInputEffect_iface);
+}
+
+static const IDirectInputEffectVtbl EffectVtbl;
+
 static const GUID DInput_Wine_OsX_Joystick_GUID = { /* 59CAD8F6-E617-41E2-8EB7-47B23EEEDC5A */
   0x59CAD8F6, 0xE617, 0x41E2, {0x8E, 0xB7, 0x47, 0xB2, 0x3E, 0xEE, 0xDC, 0x5A}
 };
@@ -831,6 +850,7 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
     newDevice->generic.name = HeapAlloc(GetProcessHeap(),0,strlen(name) + 1);
     strcpy(newDevice->generic.name, name);
 
+    list_init(&newDevice->effects);
     device = get_device_ref(index);
     if(get_ff(device, &newDevice->ff) == S_OK){
         newDevice->generic.devcaps.dwFlags |= DIDC_FORCEFEEDBACK;
@@ -1038,6 +1058,82 @@ static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REF
     return DIERR_DEVICENOTREG;
 }
 
+static CFUUIDRef effect_win_to_mac(const GUID *effect)
+{
+#define DO_MAP(X) \
+    if(IsEqualGUID(&GUID_##X, effect)) \
+        return kFFEffectType_##X##_ID;
+    DO_MAP(ConstantForce)
+    DO_MAP(RampForce)
+    DO_MAP(Square)
+    DO_MAP(Sine)
+    DO_MAP(Triangle)
+    DO_MAP(SawtoothUp)
+    DO_MAP(SawtoothDown)
+    DO_MAP(Spring)
+    DO_MAP(Damper)
+    DO_MAP(Inertia)
+    DO_MAP(Friction)
+    DO_MAP(CustomForce)
+#undef DO_MAP
+    WARN("Unknown effect GUID! %s\n", debugstr_guid(effect));
+    return 0;
+}
+
+static HRESULT WINAPI JoystickWImpl_CreateEffect(IDirectInputDevice8W *iface,
+        const GUID *type, const DIEFFECT *params, IDirectInputEffect **out,
+        IUnknown *outer)
+{
+    JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
+    EffectImpl *effect;
+    HRESULT hr;
+
+    TRACE("%p %s %p %p %p\n", iface, debugstr_guid(type), params, out, outer);
+
+    if(!This->ff){
+        TRACE("No force feedback support\n");
+        *out = NULL;
+        return S_OK;
+    }
+
+    if(outer)
+        WARN("aggregation not implemented\n");
+
+    effect = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This));
+    effect->IDirectInputEffect_iface.lpVtbl = &EffectVtbl;
+    effect->ref = 1;
+    effect->guid = *type;
+    effect->device = This;
+
+    /* Mac's FFEFFECT and Win's DIEFFECT are binary identical. */
+    hr = FFDeviceCreateEffect(This->ff, effect_win_to_mac(type),
+            (FFEFFECT*)params, &effect->effect);
+    if(FAILED(hr)){
+        WARN("FFDeviceCreateEffect failed: %08x\n", hr);
+        HeapFree(GetProcessHeap(), 0, effect);
+        return hr;
+    }
+
+    list_add_tail(&This->effects, &effect->entry);
+    *out = &effect->IDirectInputEffect_iface;
+
+    TRACE("allocated effect: %p\n", effect);
+
+    return S_OK;
+}
+
+static HRESULT WINAPI JoystickAImpl_CreateEffect(IDirectInputDevice8A *iface,
+        const GUID *type, const DIEFFECT *params, IDirectInputEffect **out,
+        IUnknown *outer)
+{
+    JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
+
+    TRACE("%p %s %p %p %p\n", iface, debugstr_guid(type), params, out, outer);
+
+    return JoystickWImpl_CreateEffect(&This->generic.base.IDirectInputDevice8W_iface,
+            type, params, out, outer);
+}
+
 const struct dinput_device joystick_osx_device = {
   "Wine OS X joystick driver",
   joydev_enum_deviceA,
@@ -1065,7 +1161,7 @@ static const IDirectInputDevice8AVtbl JoystickAvt =
     JoystickAGenericImpl_GetDeviceInfo,
     IDirectInputDevice2AImpl_RunControlPanel,
     IDirectInputDevice2AImpl_Initialize,
-    IDirectInputDevice2AImpl_CreateEffect,
+    JoystickAImpl_CreateEffect,
     IDirectInputDevice2AImpl_EnumEffects,
     IDirectInputDevice2AImpl_GetEffectInfo,
     IDirectInputDevice2AImpl_GetForceFeedbackState,
@@ -1101,7 +1197,7 @@ static const IDirectInputDevice8WVtbl JoystickWvt =
     JoystickWGenericImpl_GetDeviceInfo,
     IDirectInputDevice2WImpl_RunControlPanel,
     IDirectInputDevice2WImpl_Initialize,
-    IDirectInputDevice2WImpl_CreateEffect,
+    JoystickWImpl_CreateEffect,
     IDirectInputDevice2WImpl_EnumEffects,
     IDirectInputDevice2WImpl_GetEffectInfo,
     IDirectInputDevice2WImpl_GetForceFeedbackState,
@@ -1117,6 +1213,136 @@ static const IDirectInputDevice8WVtbl JoystickWvt =
     IDirectInputDevice8WImpl_GetImageInfo
 };
 
+static HRESULT WINAPI effect_QueryInterface(IDirectInputEffect *iface,
+        const GUID *guid, void **out)
+{
+    EffectImpl *This = impl_from_IDirectInputEffect(iface);
+
+    TRACE("%p %s %p\n", This, debugstr_guid(guid), out);
+
+    if(IsEqualIID(guid, &IID_IDirectInputEffect)){
+        *out = iface;
+        IDirectInputEffect_AddRef(iface);
+        return S_OK;
+    }
+
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI effect_AddRef(IDirectInputEffect *iface)
+{
+    EffectImpl *This = impl_from_IDirectInputEffect(iface);
+    ULONG ref = InterlockedIncrement(&This->ref);
+    TRACE("%p, ref is now: %u\n", This, ref);
+    return ref;
+}
+
+static ULONG WINAPI effect_Release(IDirectInputEffect *iface)
+{
+    EffectImpl *This = impl_from_IDirectInputEffect(iface);
+    ULONG ref = InterlockedDecrement(&This->ref);
+    TRACE("%p, ref is now: %u\n", This, ref);
+
+    if(!ref){
+        list_remove(&This->entry);
+        FFDeviceReleaseEffect(This->device->ff, This->effect);
+        HeapFree(GetProcessHeap(), 0, This);
+    }
+
+    return ref;
+}
+
+static HRESULT WINAPI effect_Initialize(IDirectInputEffect *iface, HINSTANCE hinst,
+        DWORD version, const GUID *guid)
+{
+    EffectImpl *This = impl_from_IDirectInputEffect(iface);
+    TRACE("%p %p 0x%x, %s\n", This, hinst, version, debugstr_guid(guid));
+    return S_OK;
+}
+
+static HRESULT WINAPI effect_GetEffectGuid(IDirectInputEffect *iface, GUID *out)
+{
+    EffectImpl *This = impl_from_IDirectInputEffect(iface);
+    TRACE("%p %p\n", This, out);
+    *out = This->guid;
+    return S_OK;
+}
+
+static HRESULT WINAPI effect_GetParameters(IDirectInputEffect *iface,
+        DIEFFECT *effect, DWORD flags)
+{
+    EffectImpl *This = impl_from_IDirectInputEffect(iface);
+    TRACE("%p %p 0x%x\n", This, effect, flags);
+    return FFEffectGetParameters(This->effect, (FFEFFECT*)effect, flags);
+}
+
+static HRESULT WINAPI effect_SetParameters(IDirectInputEffect *iface,
+        const DIEFFECT *effect, DWORD flags)
+{
+    EffectImpl *This = impl_from_IDirectInputEffect(iface);
+    TRACE("%p %p 0x%x\n", This, effect, flags);
+    return FFEffectSetParameters(This->effect, (FFEFFECT*)effect, flags);
+}
+
+static HRESULT WINAPI effect_Start(IDirectInputEffect *iface, DWORD iterations,
+        DWORD flags)
+{
+    EffectImpl *This = impl_from_IDirectInputEffect(iface);
+    TRACE("%p 0x%x 0x%x\n", This, iterations, flags);
+    return FFEffectStart(This->effect, iterations, flags);
+}
+
+static HRESULT WINAPI effect_Stop(IDirectInputEffect *iface)
+{
+    EffectImpl *This = impl_from_IDirectInputEffect(iface);
+    TRACE("%p\n", This);
+    return FFEffectStop(This->effect);
+}
+
+static HRESULT WINAPI effect_GetEffectStatus(IDirectInputEffect *iface, DWORD *flags)
+{
+    EffectImpl *This = impl_from_IDirectInputEffect(iface);
+    TRACE("%p %p\n", This, flags);
+    return FFEffectGetEffectStatus(This->effect, (UInt32*)flags);
+}
+
+static HRESULT WINAPI effect_Download(IDirectInputEffect *iface)
+{
+    EffectImpl *This = impl_from_IDirectInputEffect(iface);
+    TRACE("%p\n", This);
+    return FFEffectDownload(This->effect);
+}
+
+static HRESULT WINAPI effect_Unload(IDirectInputEffect *iface)
+{
+    EffectImpl *This = impl_from_IDirectInputEffect(iface);
+    TRACE("%p\n", This);
+    return FFEffectUnload(This->effect);
+}
+
+static HRESULT WINAPI effect_Escape(IDirectInputEffect *iface, DIEFFESCAPE *escape)
+{
+    EffectImpl *This = impl_from_IDirectInputEffect(iface);
+    TRACE("%p %p\n", This, escape);
+    return FFEffectEscape(This->effect, (FFEFFESCAPE*)escape);
+}
+
+static const IDirectInputEffectVtbl EffectVtbl = {
+    effect_QueryInterface,
+    effect_AddRef,
+    effect_Release,
+    effect_Initialize,
+    effect_GetEffectGuid,
+    effect_GetParameters,
+    effect_SetParameters,
+    effect_Start,
+    effect_Stop,
+    effect_GetEffectStatus,
+    effect_Download,
+    effect_Unload,
+    effect_Escape
+};
+
 #else /* HAVE_IOHIDMANAGERCREATE */
 
 const struct dinput_device joystick_osx_device = {




More information about the wine-cvs mailing list