Prevent crash when no URL is specified.
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 "mmsystem.h"
31 #define NOBITMAP
32 #include "mmreg.h"
33
34 extern GUID KSDATAFORMAT_SUBTYPE_PCM;
35 extern GUID KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
36
37 #include "winmm_test.h"
38
39 static const char * wave_in_error(MMRESULT error)
40 {
41     static char msg[1024];
42     static char long_msg[1100];
43     MMRESULT rc;
44
45     rc = waveInGetErrorText(error, msg, sizeof(msg));
46     if (rc != MMSYSERR_NOERROR)
47         sprintf(long_msg, "waveInGetErrorText(%x) failed with error %x", error, rc);
48     else
49         sprintf(long_msg, "%s(%s)", mmsys_error(error), msg);
50     return long_msg;
51 }
52
53 static void wave_in_test_deviceIn(int device, LPWAVEFORMATEX pwfx, DWORD format, DWORD flags, LPWAVEINCAPS pcaps)
54 {
55     HWAVEIN win;
56     HANDLE hevent;
57     WAVEHDR frag;
58     MMRESULT rc;
59     DWORD res;
60     WORD nChannels = pwfx->nChannels;
61     WORD wBitsPerSample = pwfx->wBitsPerSample;
62     DWORD nSamplesPerSec = pwfx->nSamplesPerSec;
63
64     hevent=CreateEvent(NULL,FALSE,FALSE,NULL);
65     ok(hevent!=NULL,"CreateEvent(): error=%ld\n",GetLastError());
66     if (hevent==NULL)
67         return;
68
69     win=NULL;
70     rc=waveInOpen(&win,device,pwfx,(DWORD)hevent,0,CALLBACK_EVENT|flags);
71     /* Note: Win9x doesn't know WAVE_FORMAT_DIRECT */
72     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID ||
73        rc==MMSYSERR_NOTENABLED || rc==MMSYSERR_NODRIVER ||
74        rc==MMSYSERR_ALLOCATED ||
75        ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
76        (flags & WAVE_FORMAT_DIRECT) && !(pcaps->dwFormats & format)) ||
77        ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
78        (!(flags & WAVE_FORMAT_DIRECT) || (flags & WAVE_MAPPED)) &&
79        !(pcaps->dwFormats & format)) ||
80        (rc==MMSYSERR_INVALFLAG && (flags & WAVE_FORMAT_DIRECT)),
81        "waveInOpen(%s): format=%ldx%2dx%d flags=%lx(%s) rc=%s\n",
82        dev_name(device),pwfx->nSamplesPerSec,pwfx->wBitsPerSample,
83        pwfx->nChannels,CALLBACK_EVENT|flags,
84        wave_open_flags(CALLBACK_EVENT|flags),wave_in_error(rc));
85     if ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
86        (flags & WAVE_FORMAT_DIRECT) && (pcaps->dwFormats & format))
87         trace(" Reason: The device lists this format as supported in it's "
88               "capabilities but opening it failed.\n");
89     if ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
90        !(pcaps->dwFormats & format))
91         trace("waveInOpen(%s): format=%ldx%2dx%d %s rc=%s failed but format "
92               "not supported so OK.\n",dev_name(device),pwfx->nSamplesPerSec,
93               pwfx->wBitsPerSample,pwfx->nChannels,
94               flags & WAVE_FORMAT_DIRECT ? "flags=WAVE_FORMAT_DIRECT" :
95               flags & WAVE_MAPPED ? "flags=WAVE_MAPPED" : "", mmsys_error(rc));
96     if (rc!=MMSYSERR_NOERROR) {
97         CloseHandle(hevent);
98         return;
99     }
100     res=WaitForSingleObject(hevent,1000);
101     ok(res==WAIT_OBJECT_0,"WaitForSingleObject failed for open\n");
102
103     ok(pwfx->nChannels==nChannels &&
104        pwfx->wBitsPerSample==wBitsPerSample &&
105        pwfx->nSamplesPerSec==nSamplesPerSec,
106        "got the wrong format: %ldx%2dx%d instead of %ldx%2dx%d\n",
107        pwfx->nSamplesPerSec, pwfx->wBitsPerSample,
108        pwfx->nChannels, nSamplesPerSec, wBitsPerSample, nChannels);
109
110     frag.lpData=malloc(pwfx->nAvgBytesPerSec);
111     frag.dwBufferLength=pwfx->nAvgBytesPerSec;
112     frag.dwBytesRecorded=0;
113     frag.dwUser=0;
114     frag.dwFlags=0;
115     frag.dwLoops=0;
116     frag.lpNext=0;
117
118     rc=waveInPrepareHeader(win, &frag, sizeof(frag));
119     ok(rc==MMSYSERR_NOERROR, "waveInPrepareHeader(%s): rc=%s\n",
120        dev_name(device),wave_in_error(rc));
121     ok(frag.dwFlags&WHDR_PREPARED,"waveInPrepareHeader(%s): prepared flag "
122        "not set\n",dev_name(device));
123
124     if (winetest_interactive && rc==MMSYSERR_NOERROR) {
125         trace("Recording for 1 second at %5ldx%2dx%d %s %s\n",
126               pwfx->nSamplesPerSec, pwfx->wBitsPerSample,pwfx->nChannels,
127               get_format_str(pwfx->wFormatTag),
128               flags & WAVE_FORMAT_DIRECT ? "WAVE_FORMAT_DIRECT" :
129               flags & WAVE_MAPPED ? "WAVE_MAPPED" : "");
130         rc=waveInAddBuffer(win, &frag, sizeof(frag));
131         ok(rc==MMSYSERR_NOERROR,"waveInAddBuffer(%s): rc=%s\n",
132            dev_name(device),wave_in_error(rc));
133
134         rc=waveInStart(win);
135         ok(rc==MMSYSERR_NOERROR,"waveInStart(%s): rc=%s\n",
136            dev_name(device),wave_in_error(rc));
137
138         res = WaitForSingleObject(hevent,1200);
139         ok(res==WAIT_OBJECT_0,"WaitForSingleObject failed for header\n");
140         ok(frag.dwFlags&WHDR_DONE,"WHDR_DONE not set in frag.dwFlags\n");
141         ok(frag.dwBytesRecorded==pwfx->nAvgBytesPerSec,
142            "frag.dwBytesRecorded=%ld, should=%ld\n",
143            frag.dwBytesRecorded,pwfx->nAvgBytesPerSec);
144         /* stop playing on error */
145         if (res!=WAIT_OBJECT_0) {
146             rc=waveInStop(win);
147             ok(rc==MMSYSERR_NOERROR,
148                "waveInStop(%s): rc=%s\n",dev_name(device),wave_in_error(rc));
149         }
150     }
151
152     rc=waveInUnprepareHeader(win, &frag, sizeof(frag));
153     ok(rc==MMSYSERR_NOERROR,"waveInUnprepareHeader(%s): rc=%s\n",
154        dev_name(device),wave_in_error(rc));
155
156     rc=waveInClose(win);
157     ok(rc==MMSYSERR_NOERROR,
158        "waveInClose(%s): rc=%s\n",dev_name(device),wave_in_error(rc));
159     res=WaitForSingleObject(hevent,1000);
160     ok(res==WAIT_OBJECT_0,"WaitForSingleObject failed for close\n");
161
162     if (winetest_interactive)
163     {
164         /*
165          * Now play back what we recorded
166          */
167         HWAVEOUT wout;
168
169         trace("Playing back recorded sound\n");
170         rc=waveOutOpen(&wout,WAVE_MAPPER,pwfx,(DWORD)hevent,0,CALLBACK_EVENT);
171         ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID ||
172            rc==MMSYSERR_NOTENABLED || rc==MMSYSERR_NODRIVER ||
173            rc==MMSYSERR_ALLOCATED ||
174            ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
175             !(pcaps->dwFormats & format)),
176            "waveOutOpen(%s) format=%ldx%2dx%d flags=%lx(%s) rc=%s\n",
177            dev_name(device),pwfx->nSamplesPerSec,pwfx->wBitsPerSample,
178            pwfx->nChannels,CALLBACK_EVENT|flags,
179            wave_open_flags(CALLBACK_EVENT),wave_out_error(rc));
180         if (rc==MMSYSERR_NOERROR)
181         {
182             rc=waveOutPrepareHeader(wout, &frag, sizeof(frag));
183             ok(rc==MMSYSERR_NOERROR,"waveOutPrepareHeader(%s): rc=%s\n",
184                dev_name(device),wave_out_error(rc));
185
186             if (rc==MMSYSERR_NOERROR)
187             {
188                 WaitForSingleObject(hevent,INFINITE);
189                 rc=waveOutWrite(wout, &frag, sizeof(frag));
190                 ok(rc==MMSYSERR_NOERROR,"waveOutWrite(%s): rc=%s\n",
191                    dev_name(device),wave_out_error(rc));
192                 WaitForSingleObject(hevent,INFINITE);
193
194                 rc=waveOutUnprepareHeader(wout, &frag, sizeof(frag));
195                 ok(rc==MMSYSERR_NOERROR,"waveOutUnprepareHeader(%s): rc=%s\n",
196                    dev_name(device),wave_out_error(rc));
197             }
198             rc=waveOutClose(wout);
199             ok(rc==MMSYSERR_NOERROR,"waveOutClose(%s): rc=%s\n",
200                dev_name(device),wave_out_error(rc));
201         }
202         else
203             trace("Unable to play back the recorded sound\n");
204     }
205
206     free(frag.lpData);
207     CloseHandle(hevent);
208 }
209
210 static void wave_in_test_device(int device)
211 {
212     WAVEINCAPSA capsA;
213     WAVEINCAPSW capsW;
214     WAVEFORMATEX format,oformat;
215     WAVEFORMATEXTENSIBLE wfex;
216     HWAVEIN win;
217     MMRESULT rc;
218     UINT f;
219     WCHAR * nameW;
220     CHAR * nameA;
221     DWORD size;
222     DWORD dwPageSize;
223     BYTE * twoPages;
224     SYSTEM_INFO sSysInfo;
225     DWORD flOldProtect;
226     BOOL res;
227
228     GetSystemInfo(&sSysInfo);
229     dwPageSize = sSysInfo.dwPageSize;
230
231     rc=waveInGetDevCapsA(device,&capsA,sizeof(capsA));
232     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID ||
233        rc==MMSYSERR_NODRIVER,
234        "waveInGetDevCapsA(%s): failed to get capabilities: rc=%s\n",
235        dev_name(device),wave_in_error(rc));
236     if (rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NODRIVER)
237         return;
238
239     rc=waveInGetDevCapsW(device,&capsW,sizeof(capsW));
240     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NOTSUPPORTED,
241        "waveInGetDevCapsW(%s): MMSYSERR_NOERROR or MMSYSERR_NOTSUPPORTED "
242        "expected, got %s\n",dev_name(device),wave_in_error(rc));
243
244     rc=waveInGetDevCapsA(device,0,sizeof(capsA));
245     ok(rc==MMSYSERR_INVALPARAM,
246        "waveInGetDevCapsA(%s): MMSYSERR_INVALPARAM expected, got %s\n",
247        dev_name(device),wave_in_error(rc));
248
249     rc=waveInGetDevCapsW(device,0,sizeof(capsW));
250     ok(rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_NOTSUPPORTED,
251        "waveInGetDevCapsW(%s): MMSYSERR_INVALPARAM or MMSYSERR_NOTSUPPORTED "
252        "expected, got %s\n",dev_name(device),wave_in_error(rc));
253
254 #if 0 /* FIXME: this works on windows but crashes wine */
255     rc=waveInGetDevCapsA(device,1,sizeof(capsA));
256     ok(rc==MMSYSERR_INVALPARAM,
257        "waveInGetDevCapsA(%s): MMSYSERR_INVALPARAM expected, got %s\n",
258        dev_name(device),wave_in_error(rc));
259
260     rc=waveInGetDevCapsW(device,1,sizeof(capsW));
261     ok(rc==MMSYSERR_INVALPARAM ||  rc==MMSYSERR_NOTSUPPORTED,
262        "waveInGetDevCapsW(%s): MMSYSERR_INVALPARAM or MMSYSERR_NOTSUPPORTED "
263        "expected, got %s\n",dev_name(device),wave_in_error(rc));
264 #endif
265
266     rc=waveInGetDevCapsA(device,&capsA,4);
267     ok(rc==MMSYSERR_NOERROR,
268        "waveInGetDevCapsA(%s): MMSYSERR_NOERROR expected, got %s\n",
269        dev_name(device),wave_in_error(rc));
270
271     rc=waveInGetDevCapsW(device,&capsW,4);
272     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NOTSUPPORTED,
273        "waveInGetDevCapsW(%s): MMSYSERR_NOERROR or MMSYSERR_NOTSUPPORTED "
274        "expected, got %s\n",dev_name(device),wave_in_error(rc));
275
276     nameA=NULL;
277     rc=waveInMessage((HWAVEIN)device, DRV_QUERYDEVICEINTERFACESIZE,
278                      (DWORD_PTR)&size, 0);
279     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_INVALPARAM ||
280        rc==MMSYSERR_NOTSUPPORTED,
281        "waveInMessage(%s): failed to get interface size: rc=%s\n",
282        dev_name(device),wave_in_error(rc));
283     if (rc==MMSYSERR_NOERROR) {
284         nameW = (WCHAR *)malloc(size);
285         rc=waveInMessage((HWAVEIN)device, DRV_QUERYDEVICEINTERFACE,
286                          (DWORD_PTR)nameW, size);
287         ok(rc==MMSYSERR_NOERROR,"waveInMessage(%s): failed to get interface "
288            "name: rc=%s\n",dev_name(device),wave_in_error(rc));
289         ok(lstrlenW(nameW)+1==size/sizeof(WCHAR),
290            "got an incorrect size: %ld instead of %d\n",
291            size,(lstrlenW(nameW)+1)*sizeof(WCHAR));
292         if (rc==MMSYSERR_NOERROR) {
293             nameA = malloc(size/sizeof(WCHAR));
294             WideCharToMultiByte(CP_ACP, 0, nameW, size/sizeof(WCHAR),
295                                 nameA, size/sizeof(WCHAR), NULL, NULL);
296         }
297         free(nameW);
298     } else if (rc==MMSYSERR_NOTSUPPORTED) {
299         nameA=strdup("not supported");
300     }
301
302     trace("  %s: \"%s\" (%s) %d.%d (%d:%d)\n",dev_name(device),capsA.szPname,
303           (nameA?nameA:"failed"),capsA.vDriverVersion >> 8,
304           capsA.vDriverVersion & 0xff,capsA.wMid,capsA.wPid);
305     trace("     channels=%d formats=%05lx\n",
306           capsA.wChannels,capsA.dwFormats);
307
308     free(nameA);
309
310     for (f=0;f<NB_WIN_FORMATS;f++) {
311         format.wFormatTag=WAVE_FORMAT_PCM;
312         format.nChannels=win_formats[f][3];
313         format.wBitsPerSample=win_formats[f][2];
314         format.nSamplesPerSec=win_formats[f][1];
315         format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
316         format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
317         format.cbSize=0;
318         wave_in_test_deviceIn(device,&format,win_formats[f][0],0, &capsA);
319         wave_in_test_deviceIn(device,&format,win_formats[f][0],
320                               WAVE_FORMAT_DIRECT, &capsA);
321         if (device != WAVE_MAPPER)
322             wave_in_test_deviceIn(device,&format,win_formats[f][0],
323                                   WAVE_MAPPED, &capsA);
324     }
325
326     /* Try a PCMWAVEFORMAT aligned next to an unaccessible page for bounds
327      * checking */
328     twoPages = VirtualAlloc(NULL, 2 * dwPageSize, MEM_RESERVE | MEM_COMMIT,
329                             PAGE_READWRITE);
330     ok(twoPages!=NULL,"Failed to allocate 2 pages of memory\n");
331     if (twoPages) {
332         res = VirtualProtect(twoPages + dwPageSize, dwPageSize, PAGE_NOACCESS,
333                              &flOldProtect);
334         ok(res, "Failed to set memory access on second page\n");
335         if (res) {
336             LPWAVEFORMATEX pwfx = (LPWAVEFORMATEX)(twoPages + dwPageSize -
337                 sizeof(PCMWAVEFORMAT));
338             pwfx->wFormatTag=WAVE_FORMAT_PCM;
339             pwfx->nChannels=1;
340             pwfx->wBitsPerSample=8;
341             pwfx->nSamplesPerSec=22050;
342             pwfx->nBlockAlign=pwfx->nChannels*pwfx->wBitsPerSample/8;
343             pwfx->nAvgBytesPerSec=pwfx->nSamplesPerSec*pwfx->nBlockAlign;
344             wave_in_test_deviceIn(device,pwfx,WAVE_FORMAT_2M08,0, &capsA);
345             wave_in_test_deviceIn(device,pwfx,WAVE_FORMAT_2M08,
346                 WAVE_FORMAT_DIRECT, &capsA);
347             if (device != WAVE_MAPPER)
348                 wave_in_test_deviceIn(device,pwfx,WAVE_FORMAT_2M08,
349                                       WAVE_MAPPED, &capsA);
350         }
351         VirtualFree(twoPages, 2 * dwPageSize, MEM_RELEASE);
352     }
353
354     /* Testing invalid format: 2 MHz sample rate */
355     format.wFormatTag=WAVE_FORMAT_PCM;
356     format.nChannels=2;
357     format.wBitsPerSample=16;
358     format.nSamplesPerSec=2000000;
359     format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
360     format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
361     format.cbSize=0;
362     oformat=format;
363     rc=waveInOpen(&win,device,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
364     ok(rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG ||
365        rc==MMSYSERR_INVALPARAM,
366        "waveInOpen(%s): opening the device with 2 MHz sample rate should fail: "
367        " rc=%s\n",dev_name(device),wave_in_error(rc));
368     if (rc==MMSYSERR_NOERROR) {
369         trace("     got %ldx%2dx%d for %ldx%2dx%d\n",
370               format.nSamplesPerSec, format.wBitsPerSample,
371               format.nChannels,
372               oformat.nSamplesPerSec, oformat.wBitsPerSample,
373               oformat.nChannels);
374         waveInClose(win);
375     }
376
377     /* test non PCM formats */
378     format.wFormatTag=WAVE_FORMAT_MULAW;
379     format.nChannels=1;
380     format.wBitsPerSample=8;
381     format.nSamplesPerSec=8000;
382     format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
383     format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
384     format.cbSize=0;
385     rc=waveInOpen(&win,device,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
386     ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
387        rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
388        "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc));
389     if (rc==MMSYSERR_NOERROR) {
390         waveInClose(win);
391         wave_in_test_deviceIn(device,&format,0,0,&capsA);
392     } else
393         trace("waveInOpen(%s): WAVE_FORMAT_MULAW not supported\n",
394               dev_name(device));
395
396     format.wFormatTag=WAVE_FORMAT_ADPCM;
397     format.nChannels=2;
398     format.wBitsPerSample=4;
399     format.nSamplesPerSec=22050;
400     format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
401     format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
402     format.cbSize=0;
403     rc=waveInOpen(&win,device,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
404     ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
405        rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
406        "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc));
407     if (rc==MMSYSERR_NOERROR) {
408         waveInClose(win);
409         wave_in_test_deviceIn(device,&format,0,0,&capsA);
410     } else
411         trace("waveInOpen(%s): WAVE_FORMAT_ADPCM not supported\n",
412               dev_name(device));
413
414     /* test if WAVEFORMATEXTENSIBLE supported */
415     wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
416     wfex.Format.nChannels=2;
417     wfex.Format.wBitsPerSample=16;
418     wfex.Format.nSamplesPerSec=22050;
419     wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
420     wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*
421         wfex.Format.nBlockAlign;
422     wfex.Format.cbSize=22;
423     wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
424     wfex.dwChannelMask=SPEAKER_ALL;
425     wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM;
426     rc=waveInOpen(&win,device,&wfex.Format,0,0,
427                   CALLBACK_NULL|WAVE_FORMAT_DIRECT);
428     ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
429        rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
430        "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc));
431     if (rc==MMSYSERR_NOERROR) {
432         waveInClose(win);
433         wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA);
434     } else
435         trace("waveInOpen(%s): WAVE_FORMAT_EXTENSIBLE not supported\n",
436               dev_name(device));
437
438     /* test if 4 channels supported */
439     wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
440     wfex.Format.nChannels=4;
441     wfex.Format.wBitsPerSample=16;
442     wfex.Format.nSamplesPerSec=22050;
443     wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
444     wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*
445         wfex.Format.nBlockAlign;
446     wfex.Format.cbSize=22;
447     wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
448     wfex.dwChannelMask=SPEAKER_ALL;
449     wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM;
450     rc=waveInOpen(&win,device,&wfex.Format,0,0,
451                   CALLBACK_NULL|WAVE_FORMAT_DIRECT);
452     ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
453        rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
454        "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc));
455     if (rc==MMSYSERR_NOERROR) {
456         waveInClose(win);
457         wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA);
458     } else
459         trace("waveInOpen(%s): 4 channels not supported\n",
460               dev_name(device));
461
462     /* test if 6 channels supported */
463     wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
464     wfex.Format.nChannels=6;
465     wfex.Format.wBitsPerSample=16;
466     wfex.Format.nSamplesPerSec=22050;
467     wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
468     wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*
469         wfex.Format.nBlockAlign;
470     wfex.Format.cbSize=22;
471     wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
472     wfex.dwChannelMask=SPEAKER_ALL;
473     wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM;
474     rc=waveInOpen(&win,device,&wfex.Format,0,0,
475                   CALLBACK_NULL|WAVE_FORMAT_DIRECT);
476     ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
477        rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
478        "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc));
479     if (rc==MMSYSERR_NOERROR) {
480         waveInClose(win);
481         wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA);
482     } else
483         trace("waveInOpen(%s): 6 channels not supported\n",
484               dev_name(device));
485
486 #if 0   /* ALSA doesn't like this */
487     /* test if 24 bit samples supported */
488     wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
489     wfex.Format.nChannels=2;
490     wfex.Format.wBitsPerSample=24;
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): 24 bit samples not supported\n",
509               dev_name(device));
510 #endif
511
512     /* test if 32 bit samples supported */
513     wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
514     wfex.Format.nChannels=2;
515     wfex.Format.wBitsPerSample=32;
516     wfex.Format.nSamplesPerSec=22050;
517     wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
518     wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*
519         wfex.Format.nBlockAlign;
520     wfex.Format.cbSize=22;
521     wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
522     wfex.dwChannelMask=SPEAKER_ALL;
523     wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM;
524     rc=waveInOpen(&win,device,&wfex.Format,0,0,
525                   CALLBACK_NULL|WAVE_FORMAT_DIRECT);
526     ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
527        rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
528        "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc));
529     if (rc==MMSYSERR_NOERROR) {
530         waveInClose(win);
531         wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA);
532     } else
533         trace("waveInOpen(%s): 32 bit samples not supported\n",
534               dev_name(device));
535
536     /* test if 32 bit float samples supported */
537     wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE;
538     wfex.Format.nChannels=2;
539     wfex.Format.wBitsPerSample=32;
540     wfex.Format.nSamplesPerSec=22050;
541     wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8;
542     wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec*
543         wfex.Format.nBlockAlign;
544     wfex.Format.cbSize=22;
545     wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample;
546     wfex.dwChannelMask=SPEAKER_ALL;
547     wfex.SubFormat=KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
548     rc=waveInOpen(&win,device,&wfex.Format,0,0,
549                   CALLBACK_NULL|WAVE_FORMAT_DIRECT);
550     ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT ||
551        rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
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): 32 bit float samples not supported\n",
558               dev_name(device));
559 }
560
561 static void wave_in_tests()
562 {
563     WAVEINCAPSA capsA;
564     WAVEINCAPSW capsW;
565     WAVEFORMATEX format;
566     HWAVEIN win;
567     MMRESULT rc;
568     UINT ndev,d;
569
570     ndev=waveInGetNumDevs();
571     trace("found %d WaveIn devices\n",ndev);
572
573     rc=waveInGetDevCapsA(ndev+1,&capsA,sizeof(capsA));
574     ok(rc==MMSYSERR_BADDEVICEID,
575        "waveInGetDevCapsA(%s): MMSYSERR_BADDEVICEID expected, got %s\n",
576        dev_name(ndev+1),wave_in_error(rc));
577
578     rc=waveInGetDevCapsA(WAVE_MAPPER,&capsA,sizeof(capsA));
579     if (ndev>0)
580         ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NODRIVER,
581            "waveInGetDevCapsA(%s): MMSYSERR_NOERROR or MMSYSERR_NODRIVER "
582            "expected, got %s\n",dev_name(WAVE_MAPPER),wave_in_error(rc));
583     else
584         ok(rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NODRIVER,
585            "waveInGetDevCapsA(%s): MMSYSERR_BADDEVICEID or MMSYSERR_NODRIVER "
586            "expected, got %s\n",dev_name(WAVE_MAPPER),wave_in_error(rc));
587
588     rc=waveInGetDevCapsW(ndev+1,&capsW,sizeof(capsW));
589     ok(rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NOTSUPPORTED,
590        "waveInGetDevCapsW(%s): MMSYSERR_BADDEVICEID or MMSYSERR_NOTSUPPORTED "
591        "expected, got %s\n",dev_name(ndev+1),wave_in_error(rc));
592
593     rc=waveInGetDevCapsW(WAVE_MAPPER,&capsW,sizeof(capsW));
594     if (ndev>0)
595         ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NODRIVER ||
596            rc==MMSYSERR_NOTSUPPORTED,
597            "waveInGetDevCapsW(%s): MMSYSERR_NOERROR or MMSYSERR_NODRIVER or "
598            "MMSYSERR_NOTSUPPORTED expected, got %s\n",
599            dev_name(ndev+1),wave_in_error(rc));
600     else
601         ok(rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NODRIVER ||
602           rc==MMSYSERR_NOTSUPPORTED,
603            "waveInGetDevCapsW(%s): MMSYSERR_BADDEVICEID or MMSYSERR_NODRIVER or"
604            "MMSYSERR_NOTSUPPORTED expected, got %s\n",
605            dev_name(ndev+1),wave_in_error(rc));
606
607     format.wFormatTag=WAVE_FORMAT_PCM;
608     format.nChannels=2;
609     format.wBitsPerSample=16;
610     format.nSamplesPerSec=44100;
611     format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
612     format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
613     format.cbSize=0;
614     rc=waveInOpen(&win,ndev+1,&format,0,0,CALLBACK_NULL);
615     ok(rc==MMSYSERR_BADDEVICEID,
616        "waveInOpen(%s): MMSYSERR_BADDEVICEID expected, got %s\n",
617        dev_name(ndev+1),wave_in_error(rc));
618
619     for (d=0;d<ndev;d++)
620         wave_in_test_device(d);
621
622     if (ndev>0)
623         wave_in_test_device(WAVE_MAPPER);
624 }
625
626 START_TEST(capture)
627 {
628     wave_in_tests();
629 }