Release 1.5.29.
[wine] / dlls / winmm / tests / capture.c
1 /*
2  * Test winmm sound capture in each sound format
3  *
4  * Copyright (c) 2002 Francois Gouget
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <math.h>
25
26 #include "wine/test.h"
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winnls.h"
30 #include "mmddk.h"
31 #include "mmsystem.h"
32 #define NOBITMAP
33 #include "mmreg.h"
34
35 extern GUID KSDATAFORMAT_SUBTYPE_PCM;
36 extern GUID KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
37
38 #include "winmm_test.h"
39
40 static const char * wave_in_error(MMRESULT error)
41 {
42     static char msg[1024];
43     static char long_msg[1100];
44     MMRESULT rc;
45
46     rc = waveInGetErrorText(error, msg, sizeof(msg));
47     if (rc != MMSYSERR_NOERROR)
48         sprintf(long_msg, "waveInGetErrorText(%x) failed with error %x", error, rc);
49     else
50         sprintf(long_msg, "%s(%s)", mmsys_error(error), msg);
51     return long_msg;
52 }
53
54 static void check_position(int device, HWAVEIN win, DWORD bytes,
55                            LPWAVEFORMATEX pwfx )
56 {
57     MMTIME mmtime;
58     MMRESULT rc;
59     DWORD returned;
60
61     mmtime.wType = TIME_BYTES;
62     rc=waveInGetPosition(win, &mmtime, sizeof(mmtime));
63     ok(rc==MMSYSERR_NOERROR,
64        "waveInGetPosition(%s): rc=%s\n",dev_name(device),wave_in_error(rc));
65     if (mmtime.wType != TIME_BYTES && winetest_debug > 1)
66         trace("waveInGetPosition(%s): TIME_BYTES not supported, returned %s\n",
67               dev_name(device),wave_time_format(mmtime.wType));
68     returned = time_to_bytes(&mmtime, pwfx);
69     ok(returned == bytes, "waveInGetPosition(%s): returned %d bytes, "
70        "should be %d\n", dev_name(device), returned, bytes);
71
72     mmtime.wType = TIME_SAMPLES;
73     rc=waveInGetPosition(win, &mmtime, sizeof(mmtime));
74     ok(rc==MMSYSERR_NOERROR,
75        "waveInGetPosition(%s): rc=%s\n",dev_name(device),wave_in_error(rc));
76     if (mmtime.wType != TIME_SAMPLES && winetest_debug > 1)
77         trace("waveInGetPosition(%s): TIME_SAMPLES not supported, "
78               "returned %s\n",dev_name(device),wave_time_format(mmtime.wType));
79     returned = time_to_bytes(&mmtime, pwfx);
80     ok(returned == bytes, "waveInGetPosition(%s): returned %d samples, "
81        "should be %d\n", dev_name(device), bytes_to_samples(returned, pwfx),
82        bytes_to_samples(bytes, pwfx));
83
84     mmtime.wType = TIME_MS;
85     rc=waveInGetPosition(win, &mmtime, sizeof(mmtime));
86     ok(rc==MMSYSERR_NOERROR,
87        "waveInGetPosition(%s): rc=%s\n",dev_name(device),wave_in_error(rc));
88     if (mmtime.wType != TIME_MS && winetest_debug > 1)
89         trace("waveInGetPosition(%s): TIME_MS not supported, returned %s\n",
90               dev_name(device), wave_time_format(mmtime.wType));
91     returned = time_to_bytes(&mmtime, pwfx);
92     ok(returned == bytes, "waveInGetPosition(%s): returned %d ms, "
93        "should be %d\n", dev_name(device), bytes_to_ms(returned, pwfx),
94        bytes_to_ms(bytes, pwfx));
95
96     mmtime.wType = TIME_SMPTE;
97     rc=waveInGetPosition(win, &mmtime, sizeof(mmtime));
98     ok(rc==MMSYSERR_NOERROR,
99        "waveInGetPosition(%s): rc=%s\n",dev_name(device),wave_in_error(rc));
100     if (mmtime.wType != TIME_SMPTE && winetest_debug > 1)
101         trace("waveInGetPosition(%s): TIME_SMPTE not supported, returned %s\n",
102               dev_name(device),wave_time_format(mmtime.wType));
103     returned = time_to_bytes(&mmtime, pwfx);
104     ok(returned == bytes, "waveInGetPosition(%s): SMPTE test failed\n",
105        dev_name(device));
106
107     mmtime.wType = TIME_MIDI;
108     rc=waveInGetPosition(win, &mmtime, sizeof(mmtime));
109     ok(rc==MMSYSERR_NOERROR,
110        "waveInGetPosition(%s): rc=%s\n",dev_name(device),wave_in_error(rc));
111     if (mmtime.wType != TIME_MIDI && winetest_debug > 1)
112         trace("waveInGetPosition(%s): TIME_MIDI not supported, returned %s\n",
113               dev_name(device),wave_time_format(mmtime.wType));
114     returned = time_to_bytes(&mmtime, pwfx);
115     ok(returned == bytes, "waveInGetPosition(%s): MIDI test failed\n",
116        dev_name(device));
117
118     mmtime.wType = TIME_TICKS;
119     rc=waveInGetPosition(win, &mmtime, sizeof(mmtime));
120     ok(rc==MMSYSERR_NOERROR,
121        "waveInGetPosition(%s): rc=%s\n",dev_name(device),wave_in_error(rc));
122     if (mmtime.wType != TIME_TICKS && winetest_debug > 1)
123         trace("waveInGetPosition(%s): TIME_TICKS not supported, returned %s\n",
124               dev_name(device),wave_time_format(mmtime.wType));
125     returned = time_to_bytes(&mmtime, pwfx);
126     ok(returned == bytes, "waveInGetPosition(%s): TICKS test failed\n",
127        dev_name(device));
128 }
129
130 static void wave_in_test_deviceIn(int device, LPWAVEFORMATEX pwfx, DWORD format, DWORD flags, LPWAVEINCAPS pcaps)
131 {
132     HWAVEIN win;
133     HANDLE hevent;
134     WAVEHDR frag;
135     MMRESULT rc;
136     DWORD res;
137     MMTIME mmt;
138     WORD nChannels = pwfx->nChannels;
139     WORD wBitsPerSample = pwfx->wBitsPerSample;
140     DWORD nSamplesPerSec = pwfx->nSamplesPerSec;
141
142     hevent=CreateEvent(NULL,FALSE,FALSE,NULL);
143     ok(hevent!=NULL,"CreateEvent(): error=%d\n",GetLastError());
144     if (hevent==NULL)
145         return;
146
147     win=NULL;
148     rc=waveInOpen(&win,device,pwfx,(DWORD_PTR)hevent,0,CALLBACK_EVENT|flags);
149     /* Note: Win9x doesn't know WAVE_FORMAT_DIRECT */
150     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID ||
151        rc==MMSYSERR_NOTENABLED || rc==MMSYSERR_NODRIVER ||
152        rc==MMSYSERR_ALLOCATED ||
153        ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
154        (flags & WAVE_FORMAT_DIRECT) && !(pcaps->dwFormats & format)) ||
155        ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
156        (!(flags & WAVE_FORMAT_DIRECT) || (flags & WAVE_MAPPED)) &&
157        !(pcaps->dwFormats & format)) ||
158        (rc==MMSYSERR_INVALFLAG && (flags & WAVE_FORMAT_DIRECT)),
159        "waveInOpen(%s): format=%dx%2dx%d flags=%x(%s) rc=%s\n",
160        dev_name(device),pwfx->nSamplesPerSec,pwfx->wBitsPerSample,
161        pwfx->nChannels,CALLBACK_EVENT|flags,
162        wave_open_flags(CALLBACK_EVENT|flags),wave_in_error(rc));
163     if ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
164        (flags & WAVE_FORMAT_DIRECT) && (pcaps->dwFormats & format))
165         trace(" Reason: The device lists this format as supported in it's "
166               "capabilities but opening it failed.\n");
167     if ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
168        !(pcaps->dwFormats & format))
169         trace("waveInOpen(%s): format=%dx%2dx%d %s rc=%s failed but format "
170               "not supported so OK.\n",dev_name(device),pwfx->nSamplesPerSec,
171               pwfx->wBitsPerSample,pwfx->nChannels,
172               flags & WAVE_FORMAT_DIRECT ? "flags=WAVE_FORMAT_DIRECT" :
173               flags & WAVE_MAPPED ? "flags=WAVE_MAPPED" : "", mmsys_error(rc));
174     if (rc!=MMSYSERR_NOERROR) {
175         CloseHandle(hevent);
176         return;
177     }
178     res=WaitForSingleObject(hevent,1000);
179     ok(res==WAIT_OBJECT_0,"WaitForSingleObject failed for open\n");
180
181     ok(pwfx->nChannels==nChannels &&
182        pwfx->wBitsPerSample==wBitsPerSample &&
183        pwfx->nSamplesPerSec==nSamplesPerSec,
184        "got the wrong format: %dx%2dx%d instead of %dx%2dx%d\n",
185        pwfx->nSamplesPerSec, pwfx->wBitsPerSample,
186        pwfx->nChannels, nSamplesPerSec, wBitsPerSample, nChannels);
187
188     /* Check that the position is 0 at start */
189     check_position(device, win, 0, pwfx);
190
191     frag.lpData=HeapAlloc(GetProcessHeap(), 0, pwfx->nAvgBytesPerSec);
192     frag.dwBufferLength=pwfx->nAvgBytesPerSec;
193     frag.dwBytesRecorded=0;
194     frag.dwUser=0;
195     frag.dwFlags=0;
196     frag.dwLoops=0;
197     frag.lpNext=0;
198
199     rc=waveInPrepareHeader(win, &frag, sizeof(frag));
200     ok(rc==MMSYSERR_NOERROR, "waveInPrepareHeader(%s): rc=%s\n",
201        dev_name(device),wave_in_error(rc));
202     ok(frag.dwFlags&WHDR_PREPARED,"waveInPrepareHeader(%s): prepared flag "
203        "not set\n",dev_name(device));
204
205     if (winetest_interactive && rc==MMSYSERR_NOERROR) {
206         trace("Recording for 1 second at %5dx%2dx%d %s %s\n",
207               pwfx->nSamplesPerSec, pwfx->wBitsPerSample,pwfx->nChannels,
208               get_format_str(pwfx->wFormatTag),
209               flags & WAVE_FORMAT_DIRECT ? "WAVE_FORMAT_DIRECT" :
210               flags & WAVE_MAPPED ? "WAVE_MAPPED" : "");
211         rc=waveInAddBuffer(win, &frag, sizeof(frag));
212         ok(rc==MMSYSERR_NOERROR,"waveInAddBuffer(%s): rc=%s\n",
213            dev_name(device),wave_in_error(rc));
214
215         /* Check that the position is 0 at start */
216         check_position(device, win, 0, pwfx);
217
218         rc=waveInStart(win);
219         ok(rc==MMSYSERR_NOERROR,"waveInStart(%s): rc=%s\n",
220            dev_name(device),wave_in_error(rc));
221
222         res = WaitForSingleObject(hevent,1200);
223         ok(res==WAIT_OBJECT_0,"WaitForSingleObject failed for header\n");
224         ok(frag.dwFlags&WHDR_DONE,"WHDR_DONE not set in frag.dwFlags\n");
225         ok(frag.dwBytesRecorded==pwfx->nAvgBytesPerSec,
226            "frag.dwBytesRecorded=%d, should=%d\n",
227            frag.dwBytesRecorded,pwfx->nAvgBytesPerSec);
228
229         mmt.wType = TIME_SAMPLES;
230         rc=waveInGetPosition(win, &mmt, sizeof(mmt));
231         ok(rc==MMSYSERR_NOERROR,"waveInGetPosition(%s): rc=%s\n",
232            dev_name(device),wave_in_error(rc));
233         ok(mmt.u.cb == frag.dwBytesRecorded, "Got wrong position: %u\n", mmt.u.cb);
234
235         /* stop playing on error */
236         if (res!=WAIT_OBJECT_0) {
237             rc=waveInStop(win);
238             ok(rc==MMSYSERR_NOERROR,
239                "waveInStop(%s): rc=%s\n",dev_name(device),wave_in_error(rc));
240         }
241     }
242
243     rc=waveInUnprepareHeader(win, &frag, sizeof(frag));
244     ok(rc==MMSYSERR_NOERROR,"waveInUnprepareHeader(%s): rc=%s\n",
245        dev_name(device),wave_in_error(rc));
246
247     rc=waveInClose(win);
248     ok(rc==MMSYSERR_NOERROR,
249        "waveInClose(%s): rc=%s\n",dev_name(device),wave_in_error(rc));
250     res=WaitForSingleObject(hevent,1000);
251     ok(res==WAIT_OBJECT_0,"WaitForSingleObject failed for close\n");
252
253     if (winetest_interactive)
254     {
255         /*
256          * Now play back what we recorded
257          */
258         HWAVEOUT wout;
259
260         trace("Playing back recorded sound\n");
261         rc=waveOutOpen(&wout,WAVE_MAPPER,pwfx,(DWORD_PTR)hevent,0,CALLBACK_EVENT);
262         ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID ||
263            rc==MMSYSERR_NOTENABLED || rc==MMSYSERR_NODRIVER ||
264            rc==MMSYSERR_ALLOCATED ||
265            ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
266             !(pcaps->dwFormats & format)),
267            "waveOutOpen(%s) format=%dx%2dx%d flags=%x(%s) rc=%s\n",
268            dev_name(device),pwfx->nSamplesPerSec,pwfx->wBitsPerSample,
269            pwfx->nChannels,CALLBACK_EVENT|flags,
270            wave_open_flags(CALLBACK_EVENT),wave_out_error(rc));
271         if (rc==MMSYSERR_NOERROR)
272         {
273             rc=waveOutPrepareHeader(wout, &frag, sizeof(frag));
274             ok(rc==MMSYSERR_NOERROR,"waveOutPrepareHeader(%s): rc=%s\n",
275                dev_name(device),wave_out_error(rc));
276
277             if (rc==MMSYSERR_NOERROR)
278             {
279                 WaitForSingleObject(hevent,INFINITE);
280                 rc=waveOutWrite(wout, &frag, sizeof(frag));
281                 ok(rc==MMSYSERR_NOERROR,"waveOutWrite(%s): rc=%s\n",
282                    dev_name(device),wave_out_error(rc));
283                 WaitForSingleObject(hevent,INFINITE);
284
285                 rc=waveOutUnprepareHeader(wout, &frag, sizeof(frag));
286                 ok(rc==MMSYSERR_NOERROR,"waveOutUnprepareHeader(%s): rc=%s\n",
287                    dev_name(device),wave_out_error(rc));
288             }
289             rc=waveOutClose(wout);
290             ok(rc==MMSYSERR_NOERROR,"waveOutClose(%s): rc=%s\n",
291                dev_name(device),wave_out_error(rc));
292         }
293         else
294             trace("Unable to play back the recorded sound\n");
295     }
296
297     HeapFree(GetProcessHeap(), 0, frag.lpData);
298     CloseHandle(hevent);
299 }
300
301 static void wave_in_test_device(UINT_PTR device)
302 {
303     WAVEINCAPSA capsA;
304     WAVEINCAPSW capsW;
305     WAVEFORMATEX format;
306     WAVEFORMATEXTENSIBLE wfex;
307     HWAVEIN win;
308     MMRESULT rc;
309     UINT f;
310     WCHAR * nameW;
311     CHAR * nameA;
312     DWORD size;
313     DWORD dwPageSize;
314     BYTE * twoPages;
315     SYSTEM_INFO sSysInfo;
316     DWORD flOldProtect;
317     BOOL res;
318
319     GetSystemInfo(&sSysInfo);
320     dwPageSize = sSysInfo.dwPageSize;
321
322     rc=waveInGetDevCapsA(device,&capsA,sizeof(capsA));
323     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID ||
324        rc==MMSYSERR_NODRIVER,
325        "waveInGetDevCapsA(%s): failed to get capabilities: rc=%s\n",
326        dev_name(device),wave_in_error(rc));
327     if (rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NODRIVER)
328         return;
329
330     rc=waveInGetDevCapsW(device,&capsW,sizeof(capsW));
331     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NOTSUPPORTED,
332        "waveInGetDevCapsW(%s): MMSYSERR_NOERROR or MMSYSERR_NOTSUPPORTED "
333        "expected, got %s\n",dev_name(device),wave_in_error(rc));
334
335     rc=waveInGetDevCapsA(device,NULL,sizeof(capsA));
336     ok(rc==MMSYSERR_INVALPARAM,
337        "waveInGetDevCapsA(%s): MMSYSERR_INVALPARAM expected, got %s\n",
338        dev_name(device),wave_in_error(rc));
339
340     rc=waveInGetDevCapsW(device,NULL,sizeof(capsW));
341     ok(rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_NOTSUPPORTED,
342        "waveInGetDevCapsW(%s): MMSYSERR_INVALPARAM or MMSYSERR_NOTSUPPORTED "
343        "expected, got %s\n",dev_name(device),wave_in_error(rc));
344
345     if (0)
346     {
347     /* FIXME: this works on windows but crashes wine */
348     rc=waveInGetDevCapsA(device,(LPWAVEINCAPSA)1,sizeof(capsA));
349     ok(rc==MMSYSERR_INVALPARAM,
350        "waveInGetDevCapsA(%s): MMSYSERR_INVALPARAM expected, got %s\n",
351        dev_name(device),wave_in_error(rc));
352
353     rc=waveInGetDevCapsW(device,(LPWAVEINCAPSW)1,sizeof(capsW));
354     ok(rc==MMSYSERR_INVALPARAM ||  rc==MMSYSERR_NOTSUPPORTED,
355        "waveInGetDevCapsW(%s): MMSYSERR_INVALPARAM or MMSYSERR_NOTSUPPORTED "
356        "expected, got %s\n",dev_name(device),wave_in_error(rc));
357     }
358
359     rc=waveInGetDevCapsA(device,&capsA,4);
360     ok(rc==MMSYSERR_NOERROR,
361        "waveInGetDevCapsA(%s): MMSYSERR_NOERROR expected, got %s\n",
362        dev_name(device),wave_in_error(rc));
363
364     rc=waveInGetDevCapsW(device,&capsW,4);
365     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NOTSUPPORTED ||
366        rc==MMSYSERR_INVALPARAM, /* Vista, W2K8 */
367        "waveInGetDevCapsW(%s): unexpected return value %s\n",
368        dev_name(device),wave_in_error(rc));
369
370     nameA=NULL;
371     rc=waveInMessage((HWAVEIN)device, DRV_QUERYDEVICEINTERFACESIZE,
372                      (DWORD_PTR)&size, 0);
373     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_INVALPARAM ||
374        rc==MMSYSERR_NOTSUPPORTED,
375        "waveInMessage(%s): failed to get interface size: rc=%s\n",
376        dev_name(device),wave_in_error(rc));
377     if (rc==MMSYSERR_NOERROR) {
378         nameW = HeapAlloc(GetProcessHeap(), 0, size);
379         rc=waveInMessage((HWAVEIN)device, DRV_QUERYDEVICEINTERFACE,
380                          (DWORD_PTR)nameW, size);
381         ok(rc==MMSYSERR_NOERROR,"waveInMessage(%s): failed to get interface "
382            "name: rc=%s\n",dev_name(device),wave_in_error(rc));
383         ok(lstrlenW(nameW)+1==size/sizeof(WCHAR),
384            "got an incorrect size %d\n", size);
385         if (rc==MMSYSERR_NOERROR) {
386             nameA = HeapAlloc(GetProcessHeap(), 0, size/sizeof(WCHAR));
387             WideCharToMultiByte(CP_ACP, 0, nameW, size/sizeof(WCHAR),
388                                 nameA, size/sizeof(WCHAR), NULL, NULL);
389         }
390         HeapFree(GetProcessHeap(), 0, nameW);
391     } else if (rc==MMSYSERR_NOTSUPPORTED) {
392         nameA=HeapAlloc(GetProcessHeap(), 0, sizeof("not supported"));
393         strcpy(nameA, "not supported");
394     }
395
396     trace("  %s: \"%s\" (%s) %d.%d (%d:%d)\n",dev_name(device),capsA.szPname,
397           (nameA?nameA:"failed"),capsA.vDriverVersion >> 8,
398           capsA.vDriverVersion & 0xff,capsA.wMid,capsA.wPid);
399     trace("     channels=%d formats=%05x\n",
400           capsA.wChannels,capsA.dwFormats);
401
402     HeapFree(GetProcessHeap(), 0, nameA);
403
404     for (f=0;f<NB_WIN_FORMATS;f++) {
405         format.wFormatTag=WAVE_FORMAT_PCM;
406         format.nChannels=win_formats[f][3];
407         format.wBitsPerSample=win_formats[f][2];
408         format.nSamplesPerSec=win_formats[f][1];
409         format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
410         format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
411         format.cbSize=0;
412         wave_in_test_deviceIn(device,&format,win_formats[f][0],0, &capsA);
413         if (device != WAVE_MAPPER) {
414             wave_in_test_deviceIn(device,&format,win_formats[f][0],
415                                   WAVE_FORMAT_DIRECT, &capsA);
416             wave_in_test_deviceIn(device,&format,win_formats[f][0],
417                                   WAVE_MAPPED, &capsA);
418         }
419     }
420
421     /* Try a PCMWAVEFORMAT aligned next to an unaccessible page for bounds
422      * checking */
423     twoPages = VirtualAlloc(NULL, 2 * dwPageSize, MEM_RESERVE | MEM_COMMIT,
424                             PAGE_READWRITE);
425     ok(twoPages!=NULL,"Failed to allocate 2 pages of memory\n");
426     if (twoPages) {
427         res = VirtualProtect(twoPages + dwPageSize, dwPageSize, PAGE_NOACCESS,
428                              &flOldProtect);
429         ok(res, "Failed to set memory access on second page\n");
430         if (res) {
431             LPWAVEFORMATEX pwfx = (LPWAVEFORMATEX)(twoPages + dwPageSize -
432                 sizeof(PCMWAVEFORMAT));
433             pwfx->wFormatTag=WAVE_FORMAT_PCM;
434             pwfx->nChannels=1;
435             pwfx->wBitsPerSample=8;
436             pwfx->nSamplesPerSec=22050;
437             pwfx->nBlockAlign=pwfx->nChannels*pwfx->wBitsPerSample/8;
438             pwfx->nAvgBytesPerSec=pwfx->nSamplesPerSec*pwfx->nBlockAlign;
439             wave_in_test_deviceIn(device,pwfx,WAVE_FORMAT_2M08,0, &capsA);
440             if (device != WAVE_MAPPER) {
441                 wave_in_test_deviceIn(device,pwfx,WAVE_FORMAT_2M08,
442                     WAVE_FORMAT_DIRECT, &capsA);
443                 wave_in_test_deviceIn(device,pwfx,WAVE_FORMAT_2M08,
444                                       WAVE_MAPPED, &capsA);
445             }
446         }
447         VirtualFree(twoPages, 2 * dwPageSize, MEM_RELEASE);
448     }
449
450     /* test non PCM formats */
451     format.wFormatTag=WAVE_FORMAT_MULAW;
452     format.nChannels=1;
453     format.wBitsPerSample=8;
454     format.nSamplesPerSec=8000;
455     format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
456     format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
457     format.cbSize=0;
458     rc=waveInOpen(&win,device,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
459     ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
460        rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
461        "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc));
462     if (rc==MMSYSERR_NOERROR) {
463         waveInClose(win);
464         wave_in_test_deviceIn(device,&format,0,0,&capsA);
465     } else
466         trace("waveInOpen(%s): WAVE_FORMAT_MULAW not supported\n",
467               dev_name(device));
468
469     format.wFormatTag=WAVE_FORMAT_ADPCM;
470     format.nChannels=2;
471     format.wBitsPerSample=4;
472     format.nSamplesPerSec=22050;
473     format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
474     format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
475     format.cbSize=0;
476     rc=waveInOpen(&win,device,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
477     ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
478        rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
479        "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc));
480     if (rc==MMSYSERR_NOERROR) {
481         waveInClose(win);
482         wave_in_test_deviceIn(device,&format,0,0,&capsA);
483     } else
484         trace("waveInOpen(%s): WAVE_FORMAT_ADPCM not supported\n",
485               dev_name(device));
486
487     /* test if WAVEFORMATEXTENSIBLE supported */
488     wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
489     wfex.Format.nChannels=2;
490     wfex.Format.wBitsPerSample=16;
491     wfex.Format.nSamplesPerSec=22050;
492     wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
493     wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*
494         wfex.Format.nBlockAlign;
495     wfex.Format.cbSize=22;
496     wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
497     wfex.dwChannelMask=SPEAKER_ALL;
498     wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM;
499     rc=waveInOpen(&win,device,&wfex.Format,0,0,
500                   CALLBACK_NULL|WAVE_FORMAT_DIRECT);
501     ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
502        rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
503        "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc));
504     if (rc==MMSYSERR_NOERROR) {
505         waveInClose(win);
506         wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA);
507     } else
508         trace("waveInOpen(%s): WAVE_FORMAT_EXTENSIBLE not supported\n",
509               dev_name(device));
510
511     /* test if 4 channels supported */
512     wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
513     wfex.Format.nChannels=4;
514     wfex.Format.wBitsPerSample=16;
515     wfex.Format.nSamplesPerSec=22050;
516     wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
517     wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*
518         wfex.Format.nBlockAlign;
519     wfex.Format.cbSize=22;
520     wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
521     wfex.dwChannelMask=SPEAKER_ALL;
522     wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM;
523     rc=waveInOpen(&win,device,&wfex.Format,0,0,
524                   CALLBACK_NULL|WAVE_FORMAT_DIRECT);
525     ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
526        rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
527        "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc));
528     if (rc==MMSYSERR_NOERROR) {
529         waveInClose(win);
530         wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA);
531     } else
532         trace("waveInOpen(%s): 4 channels not supported\n",
533               dev_name(device));
534
535     /* test if 6 channels supported */
536     wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
537     wfex.Format.nChannels=6;
538     wfex.Format.wBitsPerSample=16;
539     wfex.Format.nSamplesPerSec=22050;
540     wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
541     wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*
542         wfex.Format.nBlockAlign;
543     wfex.Format.cbSize=22;
544     wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
545     wfex.dwChannelMask=SPEAKER_ALL;
546     wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM;
547     rc=waveInOpen(&win,device,&wfex.Format,0,0,
548                   CALLBACK_NULL|WAVE_FORMAT_DIRECT);
549     ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
550        rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
551        "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc));
552     if (rc==MMSYSERR_NOERROR) {
553         waveInClose(win);
554         wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA);
555     } else
556         trace("waveInOpen(%s): 6 channels not supported\n",
557               dev_name(device));
558
559     if (0)
560     {
561     /* FIXME: ALSA doesn't like this */
562     /* test if 24 bit samples supported */
563     wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
564     wfex.Format.nChannels=2;
565     wfex.Format.wBitsPerSample=24;
566     wfex.Format.nSamplesPerSec=22050;
567     wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
568     wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*
569         wfex.Format.nBlockAlign;
570     wfex.Format.cbSize=22;
571     wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
572     wfex.dwChannelMask=SPEAKER_ALL;
573     wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM;
574     rc=waveInOpen(&win,device,&wfex.Format,0,0,
575                   CALLBACK_NULL|WAVE_FORMAT_DIRECT);
576     ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
577        rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
578        "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc));
579     if (rc==MMSYSERR_NOERROR) {
580         waveInClose(win);
581         wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA);
582     } else
583         trace("waveInOpen(%s): 24 bit samples not supported\n",
584               dev_name(device));
585     }
586
587     /* test if 32 bit samples supported */
588     wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
589     wfex.Format.nChannels=2;
590     wfex.Format.wBitsPerSample=32;
591     wfex.Format.nSamplesPerSec=22050;
592     wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
593     wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*
594         wfex.Format.nBlockAlign;
595     wfex.Format.cbSize=22;
596     wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
597     wfex.dwChannelMask=SPEAKER_ALL;
598     wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM;
599     rc=waveInOpen(&win,device,&wfex.Format,0,0,
600                   CALLBACK_NULL|WAVE_FORMAT_DIRECT);
601     ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
602        rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
603        "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc));
604     if (rc==MMSYSERR_NOERROR) {
605         waveInClose(win);
606         wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA);
607     } else
608         trace("waveInOpen(%s): 32 bit samples not supported\n",
609               dev_name(device));
610
611     /* test if 32 bit float samples supported */
612     wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
613     wfex.Format.nChannels=2;
614     wfex.Format.wBitsPerSample=32;
615     wfex.Format.nSamplesPerSec=22050;
616     wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
617     wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*
618         wfex.Format.nBlockAlign;
619     wfex.Format.cbSize=22;
620     wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
621     wfex.dwChannelMask=SPEAKER_ALL;
622     wfex.SubFormat=KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
623     rc=waveInOpen(&win,device,&wfex.Format,0,0,
624                   CALLBACK_NULL|WAVE_FORMAT_DIRECT);
625     ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
626        rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
627        "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc));
628     if (rc==MMSYSERR_NOERROR) {
629         waveInClose(win);
630         wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA);
631     } else
632         trace("waveInOpen(%s): 32 bit float samples not supported\n",
633               dev_name(device));
634 }
635
636 static void wave_in_tests(void)
637 {
638     WAVEINCAPSA capsA;
639     WAVEINCAPSW capsW;
640     WAVEFORMATEX format;
641     HWAVEIN win;
642     MMRESULT rc;
643     DWORD preferred, status;
644     UINT ndev,d;
645
646     ndev=waveInGetNumDevs();
647     trace("found %d WaveIn devices\n",ndev);
648
649     rc = waveInMessage((HWAVEIN)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET,
650             (DWORD_PTR)&preferred, (DWORD_PTR)&status);
651     ok((ndev == 0 && (rc == MMSYSERR_NODRIVER || rc == MMSYSERR_BADDEVICEID)) ||
652             rc == MMSYSERR_NOERROR, "waveInMessage(DRVM_MAPPER_PREFERRED_GET) failed: %u\n", rc);
653
654     ok((ndev == 0 && (preferred == -1 || broken(preferred != -1))) ||
655             preferred < ndev, "Got invalid preferred device: 0x%x\n", preferred);
656
657     rc=waveInGetDevCapsA(ndev+1,&capsA,sizeof(capsA));
658     ok(rc==MMSYSERR_BADDEVICEID,
659        "waveInGetDevCapsA(%s): MMSYSERR_BADDEVICEID expected, got %s\n",
660        dev_name(ndev+1),wave_in_error(rc));
661
662     rc=waveInGetDevCapsA(WAVE_MAPPER,&capsA,sizeof(capsA));
663     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NODRIVER || (!ndev && (rc==MMSYSERR_BADDEVICEID)),
664        "waveInGetDevCapsA(%s): got %s\n",dev_name(WAVE_MAPPER),wave_in_error(rc));
665
666     rc=waveInGetDevCapsW(ndev+1,&capsW,sizeof(capsW));
667     ok(rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NOTSUPPORTED,
668        "waveInGetDevCapsW(%s): MMSYSERR_BADDEVICEID or MMSYSERR_NOTSUPPORTED "
669        "expected, got %s\n",dev_name(ndev+1),wave_in_error(rc));
670
671     rc=waveInGetDevCapsW(WAVE_MAPPER,&capsW,sizeof(capsW));
672     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NODRIVER ||
673        rc==MMSYSERR_NOTSUPPORTED || (!ndev && (rc==MMSYSERR_BADDEVICEID)),
674        "waveInGetDevCapsW(%s): got %s\n", dev_name(ndev+1),wave_in_error(rc));
675
676     format.wFormatTag=WAVE_FORMAT_PCM;
677     format.nChannels=2;
678     format.wBitsPerSample=16;
679     format.nSamplesPerSec=44100;
680     format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
681     format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
682     format.cbSize=0;
683     rc=waveInOpen(&win,ndev+1,&format,0,0,CALLBACK_NULL);
684     ok(rc==MMSYSERR_BADDEVICEID,
685        "waveInOpen(%s): MMSYSERR_BADDEVICEID expected, got %s\n",
686        dev_name(ndev+1),wave_in_error(rc));
687
688     for (d=0;d<ndev;d++)
689         wave_in_test_device(d);
690
691     if (ndev>0)
692         wave_in_test_device(WAVE_MAPPER);
693 }
694
695 START_TEST(capture)
696 {
697     wave_in_tests();
698 }