msxml3: Implement comment node.
[wine] / dlls / dinput / tests / joystick.c
1 /*
2  * Copyright (c) 2004-2005 Robert Reif
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #define DIRECTINPUT_VERSION 0x0700
20
21 #define NONAMELESSSTRUCT
22 #define NONAMELESSUNION
23 #include <windows.h>
24
25 #include <math.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28
29 #include "wine/test.h"
30 #include "windef.h"
31 #include "wingdi.h"
32 #include "dinput.h"
33 #include "dxerr8.h"
34 #include "dinput_test.h"
35
36 #define numObjects(x) (sizeof(x) / sizeof(x[0]))
37
38 typedef struct tagUserData {
39     LPDIRECTINPUT pDI;
40     DWORD version;
41 } UserData;
42
43 static const DIOBJECTDATAFORMAT dfDIJoystickTest[] = {
44   { &GUID_XAxis,DIJOFS_X,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
45   { &GUID_YAxis,DIJOFS_Y,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
46   { &GUID_ZAxis,DIJOFS_Z,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
47   { &GUID_RxAxis,DIJOFS_RX,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
48   { &GUID_RyAxis,DIJOFS_RY,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
49   { &GUID_RzAxis,DIJOFS_RZ,DIDFT_OPTIONAL|DIDFT_AXIS|DIDFT_ANYINSTANCE,0},
50   { &GUID_Button,DIJOFS_BUTTON(0),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
51   { &GUID_Button,DIJOFS_BUTTON(1),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
52   { &GUID_Button,DIJOFS_BUTTON(2),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
53   { &GUID_Button,DIJOFS_BUTTON(3),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
54   { &GUID_Button,DIJOFS_BUTTON(4),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
55   { &GUID_Button,DIJOFS_BUTTON(5),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
56   { &GUID_Button,DIJOFS_BUTTON(6),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
57   { &GUID_Button,DIJOFS_BUTTON(7),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
58   { &GUID_Button,DIJOFS_BUTTON(8),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
59   { &GUID_Button,DIJOFS_BUTTON(9),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
60   { &GUID_Button,DIJOFS_BUTTON(10),DIDFT_OPTIONAL|DIDFT_BUTTON|DIDFT_ANYINSTANCE,0},
61 };
62
63 static const DIDATAFORMAT c_dfDIJoystickTest = {
64     sizeof(DIDATAFORMAT),
65     sizeof(DIOBJECTDATAFORMAT),
66     DIDF_ABSAXIS,
67     sizeof(DIJOYSTATE2),
68     numObjects(dfDIJoystickTest),
69     (LPDIOBJECTDATAFORMAT)dfDIJoystickTest
70 };
71
72 HWND get_hwnd(void)
73 {
74     HWND hwnd=GetForegroundWindow();
75     if (!hwnd)
76         hwnd=GetDesktopWindow();
77     return hwnd;
78 }
79
80 typedef struct tagJoystickInfo
81 {
82     LPDIRECTINPUTDEVICE pJoystick;
83     DWORD axis;
84     DWORD pov;
85     DWORD button;
86 } JoystickInfo;
87
88 static BOOL CALLBACK EnumAxes(
89     const DIDEVICEOBJECTINSTANCE* pdidoi,
90     VOID* pContext)
91 {
92     HRESULT hr;
93     JoystickInfo * info = (JoystickInfo *)pContext;
94
95     if (IsEqualIID(&pdidoi->guidType, &GUID_XAxis) ||
96         IsEqualIID(&pdidoi->guidType, &GUID_YAxis) ||
97         IsEqualIID(&pdidoi->guidType, &GUID_ZAxis) ||
98         IsEqualIID(&pdidoi->guidType, &GUID_RxAxis) ||
99         IsEqualIID(&pdidoi->guidType, &GUID_RyAxis) ||
100         IsEqualIID(&pdidoi->guidType, &GUID_RzAxis) ||
101         IsEqualIID(&pdidoi->guidType, &GUID_Slider)) {
102         DIPROPRANGE diprg;
103         diprg.diph.dwSize       = sizeof(DIPROPRANGE);
104         diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
105         diprg.diph.dwHow        = DIPH_BYID;
106         diprg.diph.dwObj        = pdidoi->dwType;
107         diprg.lMin              = -1000;
108         diprg.lMax              = +1000;
109
110         hr = IDirectInputDevice_SetProperty(info->pJoystick, DIPROP_RANGE, NULL);
111         ok(hr==E_INVALIDARG,"IDirectInputDevice_SetProperty() should have returned "
112            "E_INVALIDARG, returned: %s\n", DXGetErrorString8(hr));
113
114         hr = IDirectInputDevice_SetProperty(info->pJoystick, DIPROP_RANGE, &diprg.diph);
115         ok(hr==DI_OK,"IDirectInputDevice_SetProperty() failed: %s\n", DXGetErrorString8(hr));
116
117         info->axis++;
118     } else if (IsEqualIID(&pdidoi->guidType, &GUID_POV))
119         info->pov++;
120     else if (IsEqualIID(&pdidoi->guidType, &GUID_Button))
121         info->button++;
122
123     return DIENUM_CONTINUE;
124 }
125
126 static BOOL CALLBACK EnumJoysticks(
127     LPCDIDEVICEINSTANCE lpddi,
128     LPVOID pvRef)
129 {
130     HRESULT hr;
131     UserData * data = (UserData *)pvRef;
132     LPDIRECTINPUTDEVICE pJoystick;
133     DIDATAFORMAT format;
134     DIDEVCAPS caps;
135     DIJOYSTATE2 js;
136     JoystickInfo info;
137     int i, count;
138     ULONG ref;
139     DIDEVICEINSTANCE inst;
140     DIDEVICEINSTANCE_DX3 inst3;
141     HWND hWnd = get_hwnd();
142     char oldstate[248], curstate[248];
143
144     ok(data->version > 0x0300, "Joysticks not supported in version 0x%04lx\n", data->version);
145  
146     hr = IDirectInput_CreateDevice(data->pDI, &lpddi->guidInstance, NULL, NULL);
147     ok(hr==E_POINTER,"IDirectInput_CreateDevice() should have returned "
148        "E_POINTER, returned: %s\n", DXGetErrorString8(hr));
149
150     hr = IDirectInput_CreateDevice(data->pDI, NULL, &pJoystick, NULL);
151     ok(hr==E_POINTER,"IDirectInput_CreateDevice() should have returned "
152        "E_POINTER, returned: %s\n", DXGetErrorString8(hr));
153
154     hr = IDirectInput_CreateDevice(data->pDI, NULL, NULL, NULL);
155     ok(hr==E_POINTER,"IDirectInput_CreateDevice() should have returned "
156        "E_POINTER, returned: %s\n", DXGetErrorString8(hr));
157
158     hr = IDirectInput_CreateDevice(data->pDI, &lpddi->guidInstance,
159                                    &pJoystick, NULL);
160     ok(hr==DI_OK,"IDirectInput_CreateDevice() failed: %s\n",
161        DXGetErrorString8(hr));
162     if (hr!=DI_OK)
163         goto DONE;
164
165     trace("---- %s ----\n", lpddi->tszProductName);
166
167     hr = IDirectInputDevice_SetDataFormat(pJoystick, NULL);
168     ok(hr==E_POINTER,"IDirectInputDevice_SetDataFormat() should have returned "
169        "E_POINTER, returned: %s\n", DXGetErrorString8(hr));
170
171     ZeroMemory(&format, sizeof(format));
172     hr = IDirectInputDevice_SetDataFormat(pJoystick, &format);
173     ok(hr==DIERR_INVALIDPARAM,"IDirectInputDevice_SetDataFormat() should have "
174        "returned DIERR_INVALIDPARAM, returned: %s\n", DXGetErrorString8(hr));
175
176     /* try the default formats */
177     hr = IDirectInputDevice_SetDataFormat(pJoystick, &c_dfDIJoystick);
178     ok(hr==DI_OK,"IDirectInputDevice_SetDataFormat() failed: %s\n",
179        DXGetErrorString8(hr));
180
181     hr = IDirectInputDevice_SetDataFormat(pJoystick, &c_dfDIJoystick2);
182     ok(hr==DI_OK,"IDirectInputDevice_SetDataFormat() failed: %s\n",
183        DXGetErrorString8(hr));
184
185     /* try an alternate format */
186     hr = IDirectInputDevice_SetDataFormat(pJoystick, &c_dfDIJoystickTest);
187     ok(hr==DI_OK,"IDirectInputDevice_SetDataFormat() failed: %s\n",
188        DXGetErrorString8(hr));
189
190     hr = IDirectInputDevice_SetDataFormat(pJoystick, &c_dfDIJoystick2);
191     ok(hr==DI_OK,"IDirectInputDevice_SetDataFormat() failed: %s\n",
192        DXGetErrorString8(hr));
193     if (hr != DI_OK)
194         goto RELEASE;
195
196     hr = IDirectInputDevice_SetCooperativeLevel(pJoystick, hWnd,
197                                                 DISCL_NONEXCLUSIVE | DISCL_BACKGROUND);
198     ok(hr==DI_OK,"IDirectInputDevice_SetCooperativeLevel() failed: %s\n",
199        DXGetErrorString8(hr));
200
201     /* get capabilities */
202     hr = IDirectInputDevice_GetCapabilities(pJoystick, NULL);
203     ok(hr==E_POINTER,"IDirectInputDevice_GetCapabilities() "
204        "should have returned E_POINTER, returned: %s\n",
205        DXGetErrorString8(hr));
206
207     ZeroMemory(&caps, sizeof(caps));
208     hr = IDirectInputDevice_GetCapabilities(pJoystick, &caps);
209     ok(hr==DIERR_INVALIDPARAM,"IDirectInputDevice_GetCapabilities() "
210        "should have returned DIERR_INVALIDPARAM, returned: %s\n",
211        DXGetErrorString8(hr));
212
213     caps.dwSize = sizeof(caps);
214     hr = IDirectInputDevice_GetCapabilities(pJoystick, &caps);
215     ok(hr==DI_OK,"IDirectInputDevice_GetCapabilities() failed: %s\n",
216        DXGetErrorString8(hr));
217
218     ZeroMemory(&info, sizeof(info));
219     info.pJoystick = pJoystick;
220
221     /* enumerate objects */
222     hr = IDirectInputDevice_EnumObjects(pJoystick, EnumAxes, (VOID*)&info, DIDFT_ALL);
223     ok(hr==DI_OK,"IDirectInputDevice_EnumObjects() failed: %s\n",
224        DXGetErrorString8(hr));
225
226     ok(caps.dwAxes == info.axis, "Number of enumerated axes doesn't match capabilities\n");
227     ok(caps.dwButtons == info.button, "Number of enumerated buttons doesn't match capabilities\n");
228     ok(caps.dwPOVs == info.pov, "Number of enumerated POVs doesn't match capabilities\n");
229
230     hr = IDirectInputDevice_GetDeviceInfo(pJoystick, 0);
231     ok(hr==E_POINTER, "IDirectInputDevice_GetDeviceInfo() "
232        "should have returned E_POINTER, returned: %s\n",
233        DXGetErrorString8(hr));
234
235     ZeroMemory(&inst, sizeof(inst));
236     ZeroMemory(&inst3, sizeof(inst3));
237
238     hr = IDirectInputDevice_GetDeviceInfo(pJoystick, &inst);
239     ok(hr==DIERR_INVALIDPARAM, "IDirectInputDevice_GetDeviceInfo() "
240        "should have returned DIERR_INVALIDPARAM, returned: %s\n",
241        DXGetErrorString8(hr));
242
243     inst.dwSize = sizeof(inst);
244     hr = IDirectInputDevice_GetDeviceInfo(pJoystick, &inst);
245     ok(hr==DI_OK,"IDirectInputDevice_GetDeviceInfo() failed: %s\n",
246        DXGetErrorString8(hr));
247
248     inst3.dwSize = sizeof(inst3);
249     hr = IDirectInputDevice_GetDeviceInfo(pJoystick, (LPDIDEVICEINSTANCE)&inst3);
250     ok(hr==DI_OK,"IDirectInputDevice_GetDeviceInfo() failed: %s\n",
251        DXGetErrorString8(hr));
252
253     hr = IDirectInputDevice_Acquire(pJoystick);
254     ok(hr==DI_OK,"IDirectInputDevice_Acquire() failed: %s\n",
255        DXGetErrorString8(hr));
256     if (hr != DI_OK)
257         goto RELEASE;
258
259     if (winetest_interactive) {
260         trace("You have 30 seconds to test all axes, sliders, POVs and buttons\n");
261         count = 300;
262     } else
263         count = 1;
264
265     trace("\n");
266     oldstate[0]='\0';
267     for (i = 0; i < count; i++) {
268         hr = IDirectInputDevice_GetDeviceState(pJoystick, sizeof(DIJOYSTATE2), &js);
269         ok(hr==DI_OK,"IDirectInputDevice_GetDeviceState() failed: %s\n",
270            DXGetErrorString8(hr));
271         if (hr != DI_OK)
272             break;
273         sprintf(curstate, "X%5ld Y%5ld Z%5ld Rx%5ld Ry%5ld Rz%5ld "
274               "S0%5ld S1%5ld POV0%5ld POV1%5ld POV2%5ld POV3%5ld "
275               "B %d %d %d %d %d %d %d %d %d %d %d %d\n",
276               js.lX, js.lY, js.lZ, js.lRx, js.lRy, js.lRz,
277               js.rglSlider[0], js.rglSlider[1],
278               js.rgdwPOV[0], js.rgdwPOV[1], js.rgdwPOV[2], js.rgdwPOV[3],
279               js.rgbButtons[0]>>7, js.rgbButtons[1]>>7, js.rgbButtons[2]>>7,
280               js.rgbButtons[3]>>7, js.rgbButtons[4]>>7, js.rgbButtons[5]>>7,
281               js.rgbButtons[6]>>7, js.rgbButtons[7]>>7, js.rgbButtons[8]>>7,
282               js.rgbButtons[9]>>7, js.rgbButtons[10]>>7, js.rgbButtons[11]>>7);
283         if (strcmp(oldstate, curstate) != 0)
284         {
285             trace(curstate);
286             strcpy(oldstate, curstate);
287         }
288         Sleep(100);
289     }
290     trace("\n");
291
292     hr = IDirectInputDevice_Unacquire(pJoystick);
293     ok(hr==DI_OK,"IDirectInputDevice_Unacquire() failed: %s\n",
294        DXGetErrorString8(hr));
295
296 RELEASE:
297     ref = IDirectInputDevice_Release(pJoystick);
298     ok(ref==0,"IDirectInputDevice_Release() reference count = %ld\n", ref);
299
300 DONE:
301     return DIENUM_CONTINUE;
302 }
303
304 static void joystick_tests(DWORD version)
305 {
306     HRESULT hr;
307     LPDIRECTINPUT pDI;
308     ULONG ref;
309     HINSTANCE hInstance = GetModuleHandle(NULL);
310
311     trace("-- Testing Direct Input Version 0x%04lx --\n", version);
312     hr = DirectInputCreate(hInstance, version, &pDI, NULL);
313     ok(hr==DI_OK||hr==DIERR_OLDDIRECTINPUTVERSION,
314        "DirectInputCreate() failed: %s\n", DXGetErrorString8(hr));
315     if (hr==DI_OK && pDI!=0) {
316         UserData data;
317         data.pDI = pDI;
318         data.version = version;
319         hr = IDirectInput_EnumDevices(pDI, DIDEVTYPE_JOYSTICK, EnumJoysticks,
320                                       &data, DIEDFL_ALLDEVICES);
321         ok(hr==DI_OK,"IDirectInput_EnumDevices() failed: %s\n",
322            DXGetErrorString8(hr));
323         ref = IDirectInput_Release(pDI);
324         ok(ref==0,"IDirectInput_Release() reference count = %ld\n", ref);
325     } else if (hr==DIERR_OLDDIRECTINPUTVERSION)
326         trace("  Version Not Supported\n");
327 }
328
329 START_TEST(joystick)
330 {
331     CoInitialize(NULL);
332
333     trace("DLL Version: %s\n", get_file_version("dinput.dll"));
334
335     joystick_tests(0x0700);
336     joystick_tests(0x0500);
337     joystick_tests(0x0300);
338
339     CoUninitialize();
340 }