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 = waveInGetErrorTextA(error, msg, sizeof(msg));
47     if (rc != MMSYSERR_NOERROR)
48         sprintf(long_msg, "waveInGetErrorTextA(%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, WAVEFORMATEX *pwfx, DWORD format, DWORD flags,
131         WAVEINCAPSA *pcaps)
132 {
133     HWAVEIN win;
134     HANDLE hevent = CreateEventW(NULL, FALSE, FALSE, NULL);
135     WAVEHDR frag;
136     MMRESULT rc;
137     DWORD res;
138     MMTIME mmt;
139     WORD nChannels = pwfx->nChannels;
140     WORD wBitsPerSample = pwfx->wBitsPerSample;
141     DWORD nSamplesPerSec = pwfx->nSamplesPerSec;
142 
143     win=NULL;
144     flags |= CALLBACK_EVENT;
145     rc=waveInOpen(&win,device,pwfx,(DWORD_PTR)hevent,0,flags);
146     /* Note: Win9x doesn't know WAVE_FORMAT_DIRECT */
147     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID ||
148        rc==MMSYSERR_NOTENABLED || rc==MMSYSERR_NODRIVER ||
149        rc==MMSYSERR_ALLOCATED ||
150        ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
151        (flags & WAVE_FORMAT_DIRECT) && !(pcaps->dwFormats & format)) ||
152        ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
153        (!(flags & WAVE_FORMAT_DIRECT) || (flags & WAVE_MAPPED)) &&
154        !(pcaps->dwFormats & format)) ||
155        (rc==MMSYSERR_INVALFLAG && (flags & WAVE_FORMAT_DIRECT)),
156        "waveInOpen(%s): format=%dx%2dx%d flags=%x(%s) rc=%s\n",
157        dev_name(device),pwfx->nSamplesPerSec,pwfx->wBitsPerSample,
158        pwfx->nChannels,flags,wave_open_flags(flags),wave_in_error(rc));
159     if ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
160        (flags & WAVE_FORMAT_DIRECT) && (pcaps->dwFormats & format))
161         trace(" Reason: The device lists this format as supported in its "
162               "capabilities but opening it failed.\n");
163     if ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
164        !(pcaps->dwFormats & format))
165         trace("waveInOpen(%s): format=%dx%2dx%d %s rc=%s failed but format "
166               "not supported so OK.\n",dev_name(device),pwfx->nSamplesPerSec,
167               pwfx->wBitsPerSample,pwfx->nChannels,
168               flags & WAVE_FORMAT_DIRECT ? "flags=WAVE_FORMAT_DIRECT" :
169               flags & WAVE_MAPPED ? "flags=WAVE_MAPPED" : "", mmsys_error(rc));
170     if (rc!=MMSYSERR_NOERROR) {
171         CloseHandle(hevent);
172         return;
173     }
174     res=WaitForSingleObject(hevent,1000);
175     ok(res==WAIT_OBJECT_0,"WaitForSingleObject failed for open\n");
176 
177     ok(pwfx->nChannels==nChannels &&
178        pwfx->wBitsPerSample==wBitsPerSample &&
179        pwfx->nSamplesPerSec==nSamplesPerSec,
180        "got the wrong format: %dx%2dx%d instead of %dx%2dx%d\n",
181        pwfx->nSamplesPerSec, pwfx->wBitsPerSample,
182        pwfx->nChannels, nSamplesPerSec, wBitsPerSample, nChannels);
183 
184     /* Check that the position is 0 at start */
185     check_position(device, win, 0, pwfx);
186 
187     frag.lpData=HeapAlloc(GetProcessHeap(), 0, pwfx->nAvgBytesPerSec);
188     frag.dwBufferLength=pwfx->nAvgBytesPerSec;
189     frag.dwBytesRecorded=0;
190     frag.dwUser=0;
191     frag.dwFlags=0;
192     frag.dwLoops=0;
193     frag.lpNext=0;
194 
195     rc=waveInPrepareHeader(win, &frag, sizeof(frag));
196     ok(rc==MMSYSERR_NOERROR, "waveInPrepareHeader(%s): rc=%s\n",
197        dev_name(device),wave_in_error(rc));
198     ok(frag.dwFlags&WHDR_PREPARED,"waveInPrepareHeader(%s): prepared flag "
199        "not set\n",dev_name(device));
200 
201     if (winetest_interactive && rc==MMSYSERR_NOERROR) {
202         trace("Recording for 1 second at %5dx%2dx%d %s %s\n",
203               pwfx->nSamplesPerSec, pwfx->wBitsPerSample,pwfx->nChannels,
204               get_format_str(pwfx->wFormatTag),
205               flags & WAVE_FORMAT_DIRECT ? "WAVE_FORMAT_DIRECT" :
206               flags & WAVE_MAPPED ? "WAVE_MAPPED" : "");
207         rc=waveInAddBuffer(win, &frag, sizeof(frag));
208         ok(rc==MMSYSERR_NOERROR,"waveInAddBuffer(%s): rc=%s\n",
209            dev_name(device),wave_in_error(rc));
210 
211         /* Check that the position is 0 at start */
212         check_position(device, win, 0, pwfx);
213 
214         rc=waveInStart(win);
215         ok(rc==MMSYSERR_NOERROR,"waveInStart(%s): rc=%s\n",
216            dev_name(device),wave_in_error(rc));
217 
218         res = WaitForSingleObject(hevent,1200);
219         ok(res==WAIT_OBJECT_0,"WaitForSingleObject failed for header\n");
220         ok(frag.dwFlags&WHDR_DONE,"WHDR_DONE not set in frag.dwFlags\n");
221         ok(frag.dwBytesRecorded==pwfx->nAvgBytesPerSec,
222            "frag.dwBytesRecorded=%d, should=%d\n",
223            frag.dwBytesRecorded,pwfx->nAvgBytesPerSec);
224 
225         mmt.wType = TIME_BYTES;
226         rc=waveInGetPosition(win, &mmt, sizeof(mmt));
227         ok(rc==MMSYSERR_NOERROR,"waveInGetPosition(%s): rc=%s\n",
228            dev_name(device),wave_in_error(rc));
229         ok(mmt.wType == TIME_BYTES, "doesn't support TIME_BYTES: %u\n", mmt.wType);
230         ok(mmt.u.cb == frag.dwBytesRecorded, "Got wrong position: %u\n", mmt.u.cb);
231 
232         /* stop playing on error */
233         if (res!=WAIT_OBJECT_0) {
234             rc=waveInStop(win);
235             ok(rc==MMSYSERR_NOERROR,
236                "waveInStop(%s): rc=%s\n",dev_name(device),wave_in_error(rc));
237         }
238     }
239 
240     rc=waveInUnprepareHeader(win, &frag, sizeof(frag));
241     ok(rc==MMSYSERR_NOERROR,"waveInUnprepareHeader(%s): rc=%s\n",
242        dev_name(device),wave_in_error(rc));
243 
244     rc=waveInClose(win);
245     ok(rc==MMSYSERR_NOERROR,
246        "waveInClose(%s): rc=%s\n",dev_name(device),wave_in_error(rc));
247     res=WaitForSingleObject(hevent,1000);
248     ok(res==WAIT_OBJECT_0,"WaitForSingleObject failed for close\n");
249 
250     if (winetest_interactive)
251     {
252         /*
253          * Now play back what we recorded
254          */
255         HWAVEOUT wout;
256 
257         trace("Playing back recorded sound\n");
258         rc=waveOutOpen(&wout,WAVE_MAPPER,pwfx,(DWORD_PTR)hevent,0,CALLBACK_EVENT);
259         ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID ||
260            rc==MMSYSERR_NOTENABLED || rc==MMSYSERR_NODRIVER ||
261            rc==MMSYSERR_ALLOCATED ||
262            ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
263             !(pcaps->dwFormats & format)),
264            "waveOutOpen(%s) format=%dx%2dx%d flags=CALLBACK_EVENT rc=%s\n",
265            dev_name(device),pwfx->nSamplesPerSec,pwfx->wBitsPerSample,
266            pwfx->nChannels,wave_out_error(rc));
267         if (rc==MMSYSERR_NOERROR)
268         {
269             rc=waveOutPrepareHeader(wout, &frag, sizeof(frag));
270             ok(rc==MMSYSERR_NOERROR,"waveOutPrepareHeader(%s): rc=%s\n",
271                dev_name(device),wave_out_error(rc));
272 
273             if (rc==MMSYSERR_NOERROR)
274             {
275                 WaitForSingleObject(hevent,INFINITE);
276                 rc=waveOutWrite(wout, &frag, sizeof(frag));
277                 ok(rc==MMSYSERR_NOERROR,"waveOutWrite(%s): rc=%s\n",
278                    dev_name(device),wave_out_error(rc));
279                 WaitForSingleObject(hevent,INFINITE);
280 
281                 rc=waveOutUnprepareHeader(wout, &frag, sizeof(frag));
282                 ok(rc==MMSYSERR_NOERROR,"waveOutUnprepareHeader(%s): rc=%s\n",
283                    dev_name(device),wave_out_error(rc));
284             }
285             rc=waveOutClose(wout);
286             ok(rc==MMSYSERR_NOERROR,"waveOutClose(%s): rc=%s\n",
287                dev_name(device),wave_out_error(rc));
288         }
289         else
290             trace("Unable to play back the recorded sound\n");
291     }
292 
293     HeapFree(GetProcessHeap(), 0, frag.lpData);
294     CloseHandle(hevent);
295 }
296 
297 static void wave_in_test_device(UINT_PTR device)
298 {
299     WAVEINCAPSA capsA;
300     WAVEINCAPSW capsW;
301     WAVEFORMATEX format;
302     WAVEFORMATEXTENSIBLE wfex;
303     HWAVEIN win;
304     MMRESULT rc;
305     UINT f;
306     WCHAR * nameW;
307     CHAR * nameA;
308     DWORD size;
309     DWORD dwPageSize;
310     BYTE * twoPages;
311     SYSTEM_INFO sSysInfo;
312     DWORD flOldProtect;
313     BOOL res;
314 
315     GetSystemInfo(&sSysInfo);
316     dwPageSize = sSysInfo.dwPageSize;
317 
318     rc=waveInGetDevCapsA(device,&capsA,sizeof(capsA));
319     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID ||
320        rc==MMSYSERR_NODRIVER,
321        "waveInGetDevCapsA(%s): failed to get capabilities: rc=%s\n",
322        dev_name(device),wave_in_error(rc));
323     if (rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NODRIVER)
324         return;
325 
326     rc=waveInGetDevCapsW(device,&capsW,sizeof(capsW));
327     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NOTSUPPORTED,
328        "waveInGetDevCapsW(%s): MMSYSERR_NOERROR or MMSYSERR_NOTSUPPORTED "
329        "expected, got %s\n",dev_name(device),wave_in_error(rc));
330 
331     rc=waveInGetDevCapsA(device,NULL,sizeof(capsA));
332     ok(rc==MMSYSERR_INVALPARAM,
333        "waveInGetDevCapsA(%s): MMSYSERR_INVALPARAM expected, got %s\n",
334        dev_name(device),wave_in_error(rc));
335 
336     rc=waveInGetDevCapsW(device,NULL,sizeof(capsW));
337     ok(rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_NOTSUPPORTED,
338        "waveInGetDevCapsW(%s): MMSYSERR_INVALPARAM or MMSYSERR_NOTSUPPORTED "
339        "expected, got %s\n",dev_name(device),wave_in_error(rc));
340 
341     if (0)
342     {
343     /* FIXME: this works on windows but crashes wine */
344     rc=waveInGetDevCapsA(device,(LPWAVEINCAPSA)1,sizeof(capsA));
345     ok(rc==MMSYSERR_INVALPARAM,
346        "waveInGetDevCapsA(%s): MMSYSERR_INVALPARAM expected, got %s\n",
347        dev_name(device),wave_in_error(rc));
348 
349     rc=waveInGetDevCapsW(device,(LPWAVEINCAPSW)1,sizeof(capsW));
350     ok(rc==MMSYSERR_INVALPARAM ||  rc==MMSYSERR_NOTSUPPORTED,
351        "waveInGetDevCapsW(%s): MMSYSERR_INVALPARAM or MMSYSERR_NOTSUPPORTED "
352        "expected, got %s\n",dev_name(device),wave_in_error(rc));
353     }
354 
355     rc=waveInGetDevCapsA(device,&capsA,4);
356     ok(rc==MMSYSERR_NOERROR,
357        "waveInGetDevCapsA(%s): MMSYSERR_NOERROR expected, got %s\n",
358        dev_name(device),wave_in_error(rc));
359 
360     rc=waveInGetDevCapsW(device,&capsW,4);
361     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NOTSUPPORTED ||
362        rc==MMSYSERR_INVALPARAM, /* Vista, W2K8 */
363        "waveInGetDevCapsW(%s): unexpected return value %s\n",
364        dev_name(device),wave_in_error(rc));
365 
366     nameA=NULL;
367     rc=waveInMessage((HWAVEIN)device, DRV_QUERYDEVICEINTERFACESIZE,
368                      (DWORD_PTR)&size, 0);
369     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_INVALPARAM ||
370        rc==MMSYSERR_NOTSUPPORTED,
371        "waveInMessage(%s): failed to get interface size: rc=%s\n",
372        dev_name(device),wave_in_error(rc));
373     if (rc==MMSYSERR_NOERROR) {
374         nameW = HeapAlloc(GetProcessHeap(), 0, size);
375         rc=waveInMessage((HWAVEIN)device, DRV_QUERYDEVICEINTERFACE,
376                          (DWORD_PTR)nameW, size);
377         ok(rc==MMSYSERR_NOERROR,"waveInMessage(%s): failed to get interface "
378            "name: rc=%s\n",dev_name(device),wave_in_error(rc));
379         ok(lstrlenW(nameW)+1==size/sizeof(WCHAR),
380            "got an incorrect size %d\n", size);
381         if (rc==MMSYSERR_NOERROR) {
382             nameA = HeapAlloc(GetProcessHeap(), 0, size/sizeof(WCHAR));
383             WideCharToMultiByte(CP_ACP, 0, nameW, size/sizeof(WCHAR),
384                                 nameA, size/sizeof(WCHAR), NULL, NULL);
385         }
386         HeapFree(GetProcessHeap(), 0, nameW);
387     } else if (rc==MMSYSERR_NOTSUPPORTED) {
388         nameA=HeapAlloc(GetProcessHeap(), 0, sizeof("not supported"));
389         strcpy(nameA, "not supported");
390     }
391 
392     trace("  %s: \"%s\" (%s) %d.%d (%d:%d)\n",dev_name(device),capsA.szPname,
393           (nameA?nameA:"failed"),capsA.vDriverVersion >> 8,
394           capsA.vDriverVersion & 0xff,capsA.wMid,capsA.wPid);
395     trace("     channels=%d formats=%05x\n",
396           capsA.wChannels,capsA.dwFormats);
397 
398     HeapFree(GetProcessHeap(), 0, nameA);
399 
400     for (f = 0; f < ARRAY_SIZE(win_formats); f++) {
401         format.wFormatTag=WAVE_FORMAT_PCM;
402         format.nChannels=win_formats[f][3];
403         format.wBitsPerSample=win_formats[f][2];
404         format.nSamplesPerSec=win_formats[f][1];
405         format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
406         format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
407         format.cbSize=0;
408         wave_in_test_deviceIn(device,&format,win_formats[f][0],0, &capsA);
409         if (device != WAVE_MAPPER) {
410             wave_in_test_deviceIn(device,&format,win_formats[f][0],
411                                   WAVE_FORMAT_DIRECT, &capsA);
412             wave_in_test_deviceIn(device,&format,win_formats[f][0],
413                                   WAVE_MAPPED, &capsA);
414         }
415     }
416 
417     /* Try a PCMWAVEFORMAT aligned next to an unaccessible page for bounds
418      * checking */
419     twoPages = VirtualAlloc(NULL, 2 * dwPageSize, MEM_RESERVE | MEM_COMMIT,
420                             PAGE_READWRITE);
421     ok(twoPages!=NULL,"Failed to allocate 2 pages of memory\n");
422     if (twoPages) {
423         res = VirtualProtect(twoPages + dwPageSize, dwPageSize, PAGE_NOACCESS,
424                              &flOldProtect);
425         ok(res, "Failed to set memory access on second page\n");
426         if (res) {
427             LPWAVEFORMATEX pwfx = (LPWAVEFORMATEX)(twoPages + dwPageSize -
428                 sizeof(PCMWAVEFORMAT));
429             pwfx->wFormatTag=WAVE_FORMAT_PCM;
430             pwfx->nChannels=1;
431             pwfx->wBitsPerSample=8;
432             pwfx->nSamplesPerSec=22050;
433             pwfx->nBlockAlign=pwfx->nChannels*pwfx->wBitsPerSample/8;
434             pwfx->nAvgBytesPerSec=pwfx->nSamplesPerSec*pwfx->nBlockAlign;
435             wave_in_test_deviceIn(device,pwfx,WAVE_FORMAT_2M08,0, &capsA);
436             if (device != WAVE_MAPPER) {
437                 wave_in_test_deviceIn(device,pwfx,WAVE_FORMAT_2M08,
438                     WAVE_FORMAT_DIRECT, &capsA);
439                 wave_in_test_deviceIn(device,pwfx,WAVE_FORMAT_2M08,
440                                       WAVE_MAPPED, &capsA);
441             }
442         }
443         VirtualFree(twoPages, 2 * dwPageSize, MEM_RELEASE);
444     }
445 
446     /* test non PCM formats */
447     format.wFormatTag=WAVE_FORMAT_MULAW;
448     format.nChannels=1;
449     format.wBitsPerSample=8;
450     format.nSamplesPerSec=8000;
451     format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
452     format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
453     format.cbSize=0;
454     rc=waveInOpen(&win,device,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
455     ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
456        rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM ||
457        rc==MMSYSERR_ALLOCATED,
458        "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc));
459     if (rc==MMSYSERR_NOERROR) {
460         waveInClose(win);
461         wave_in_test_deviceIn(device,&format,0,0,&capsA);
462     } else
463         trace("waveInOpen(%s): WAVE_FORMAT_MULAW not supported\n",
464               dev_name(device));
465 
466     format.wFormatTag=WAVE_FORMAT_ADPCM;
467     format.nChannels=2;
468     format.wBitsPerSample=4;
469     format.nSamplesPerSec=22050;
470     format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
471     format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
472     format.cbSize=0;
473     rc=waveInOpen(&win,device,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
474     ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
475        rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM ||
476        rc==MMSYSERR_ALLOCATED,
477        "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc));
478     if (rc==MMSYSERR_NOERROR) {
479         waveInClose(win);
480         wave_in_test_deviceIn(device,&format,0,0,&capsA);
481     } else
482         trace("waveInOpen(%s): WAVE_FORMAT_ADPCM not supported\n",
483               dev_name(device));
484 
485     /* test if WAVEFORMATEXTENSIBLE supported */
486     wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
487     wfex.Format.nChannels=2;
488     wfex.Format.wBitsPerSample=16;
489     wfex.Format.nSamplesPerSec=22050;
490     wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
491     wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*
492         wfex.Format.nBlockAlign;
493     wfex.Format.cbSize=22;
494     wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
495     wfex.dwChannelMask=SPEAKER_ALL;
496     wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM;
497     rc=waveInOpen(&win,device,&wfex.Format,0,0,
498                   CALLBACK_NULL|WAVE_FORMAT_DIRECT);
499     ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
500        rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM ||
501        rc==MMSYSERR_ALLOCATED,
502        "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc));
503     if (rc==MMSYSERR_NOERROR) {
504         waveInClose(win);
505         wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA);
506     } else
507         trace("waveInOpen(%s): WAVE_FORMAT_EXTENSIBLE not supported\n",
508               dev_name(device));
509 
510     /* test if 4 channels supported */
511     wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
512     wfex.Format.nChannels=4;
513     wfex.Format.wBitsPerSample=16;
514     wfex.Format.nSamplesPerSec=22050;
515     wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
516     wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*
517         wfex.Format.nBlockAlign;
518     wfex.Format.cbSize=22;
519     wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
520     wfex.dwChannelMask=SPEAKER_ALL;
521     wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM;
522     rc=waveInOpen(&win,device,&wfex.Format,0,0,
523                   CALLBACK_NULL|WAVE_FORMAT_DIRECT);
524     ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
525        rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM ||
526        rc==MMSYSERR_ALLOCATED,
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        rc==MMSYSERR_ALLOCATED,
552        "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc));
553     if (rc==MMSYSERR_NOERROR) {
554         waveInClose(win);
555         wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA);
556     } else
557         trace("waveInOpen(%s): 6 channels not supported\n",
558               dev_name(device));
559 
560     if (0)
561     {
562     /* FIXME: ALSA doesn't like this */
563     /* test if 24 bit samples supported */
564     wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
565     wfex.Format.nChannels=2;
566     wfex.Format.wBitsPerSample=24;
567     wfex.Format.nSamplesPerSec=22050;
568     wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
569     wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*
570         wfex.Format.nBlockAlign;
571     wfex.Format.cbSize=22;
572     wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
573     wfex.dwChannelMask=SPEAKER_ALL;
574     wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM;
575     rc=waveInOpen(&win,device,&wfex.Format,0,0,
576                   CALLBACK_NULL|WAVE_FORMAT_DIRECT);
577     ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
578        rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM ||
579        rc==MMSYSERR_ALLOCATED,
580        "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc));
581     if (rc==MMSYSERR_NOERROR) {
582         waveInClose(win);
583         wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA);
584     } else
585         trace("waveInOpen(%s): 24 bit samples not supported\n",
586               dev_name(device));
587     }
588 
589     /* test if 32 bit samples supported */
590     wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
591     wfex.Format.nChannels=2;
592     wfex.Format.wBitsPerSample=32;
593     wfex.Format.nSamplesPerSec=22050;
594     wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
595     wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*
596         wfex.Format.nBlockAlign;
597     wfex.Format.cbSize=22;
598     wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
599     wfex.dwChannelMask=SPEAKER_ALL;
600     wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM;
601     rc=waveInOpen(&win,device,&wfex.Format,0,0,
602                   CALLBACK_NULL|WAVE_FORMAT_DIRECT);
603     ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
604        rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM ||
605        rc==MMSYSERR_ALLOCATED,
606        "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc));
607     if (rc==MMSYSERR_NOERROR) {
608         waveInClose(win);
609         wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA);
610     } else
611         trace("waveInOpen(%s): 32 bit samples not supported\n",
612               dev_name(device));
613 
614     /* test if 32 bit float samples supported */
615     wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
616     wfex.Format.nChannels=2;
617     wfex.Format.wBitsPerSample=32;
618     wfex.Format.nSamplesPerSec=22050;
619     wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
620     wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*
621         wfex.Format.nBlockAlign;
622     wfex.Format.cbSize=22;
623     wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
624     wfex.dwChannelMask=SPEAKER_ALL;
625     wfex.SubFormat=KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
626     rc=waveInOpen(&win,device,&wfex.Format,0,0,
627                   CALLBACK_NULL|WAVE_FORMAT_DIRECT);
628     ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
629        rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM ||
630        rc==MMSYSERR_ALLOCATED,
631        "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc));
632     if (rc==MMSYSERR_NOERROR) {
633         waveInClose(win);
634         wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA);
635     } else
636         trace("waveInOpen(%s): 32 bit float samples not supported\n",
637               dev_name(device));
638 }
639 
640 static void wave_in_tests(void)
641 {
642     WAVEINCAPSA capsA;
643     WAVEINCAPSW capsW;
644     WAVEFORMATEX format;
645     HWAVEIN win;
646     MMRESULT rc;
647     DWORD preferred, status;
648     UINT ndev,d;
649 
650     ndev=waveInGetNumDevs();
651     trace("found %d WaveIn devices\n",ndev);
652 
653     rc = waveInMessage((HWAVEIN)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET,
654             (DWORD_PTR)&preferred, (DWORD_PTR)&status);
655     ok((ndev == 0 && (rc == MMSYSERR_NODRIVER || rc == MMSYSERR_BADDEVICEID)) ||
656             rc == MMSYSERR_NOTSUPPORTED ||
657             rc == MMSYSERR_NOERROR, "waveInMessage(DRVM_MAPPER_PREFERRED_GET) failed: %u\n", rc);
658 
659     if(rc != MMSYSERR_NOTSUPPORTED)
660         ok((ndev == 0 && (preferred == -1 || broken(preferred != -1))) ||
661                 preferred < ndev, "Got invalid preferred device: 0x%x\n", preferred);
662 
663     rc = waveInMessage((HWAVEIN)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET,
664          (DWORD_PTR)-1  , 0);
665     ok(rc == MMSYSERR_INVALPARAM || rc == MMSYSERR_BADDEVICEID, /* w2008+wvista */
666        "waveInMessage(DRVM_MAPPER_PREFERRED_GET) failed: %u\n", rc);
667 
668     rc = waveInMessage((HWAVEIN)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET,
669          0, (DWORD_PTR)&status);
670     ok(rc == MMSYSERR_INVALPARAM || rc == MMSYSERR_BADDEVICEID, /* w2008+wvista */
671        "waveInMessage(DRVM_MAPPER_PREFERRED_GET) failed: %u\n", rc);
672 
673     rc=waveInGetDevCapsA(ndev+1,&capsA,sizeof(capsA));
674     ok(rc==MMSYSERR_BADDEVICEID,
675        "waveInGetDevCapsA(%s): MMSYSERR_BADDEVICEID expected, got %s\n",
676        dev_name(ndev+1),wave_in_error(rc));
677 
678     rc=waveInGetDevCapsA(WAVE_MAPPER,&capsA,sizeof(capsA));
679     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NODRIVER || (!ndev && (rc==MMSYSERR_BADDEVICEID)),
680        "waveInGetDevCapsA(%s): got %s\n",dev_name(WAVE_MAPPER),wave_in_error(rc));
681 
682     rc=waveInGetDevCapsW(ndev+1,&capsW,sizeof(capsW));
683     ok(rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NOTSUPPORTED,
684        "waveInGetDevCapsW(%s): MMSYSERR_BADDEVICEID or MMSYSERR_NOTSUPPORTED "
685        "expected, got %s\n",dev_name(ndev+1),wave_in_error(rc));
686 
687     rc=waveInGetDevCapsW(WAVE_MAPPER,&capsW,sizeof(capsW));
688     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NODRIVER ||
689        rc==MMSYSERR_NOTSUPPORTED || (!ndev && (rc==MMSYSERR_BADDEVICEID)),
690        "waveInGetDevCapsW(%s): got %s\n", dev_name(ndev+1),wave_in_error(rc));
691 
692     format.wFormatTag=WAVE_FORMAT_PCM;
693     format.nChannels=2;
694     format.wBitsPerSample=16;
695     format.nSamplesPerSec=44100;
696     format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
697     format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
698     format.cbSize=0;
699     rc=waveInOpen(&win,ndev+1,&format,0,0,CALLBACK_NULL);
700     ok(rc==MMSYSERR_BADDEVICEID,
701        "waveInOpen(%s): MMSYSERR_BADDEVICEID expected, got %s\n",
702        dev_name(ndev+1),wave_in_error(rc));
703 
704     for (d=0;d<ndev;d++)
705         wave_in_test_device(d);
706 
707     if (ndev>0)
708         wave_in_test_device(WAVE_MAPPER);
709 }
710 
711 START_TEST(capture)
712 {
713     wave_in_tests();
714 }
715