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