Assorted spelling fixes.
[wine] / dlls / winmm / tests / wave.c
1 /*
2  * Unit tests for winmm functions
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 #include "mmddk.h"
32
33 /*
34  * Note that in most of this test we may get MMSYSERR_BADDEVICEID errors
35  * at about any time if the user starts another application that uses the
36  * sound device. So we should not report these as test failures.
37  *
38  * This test can play a test tone. But this only makes sense if someone
39  * is going to carefully listen to it, and would only bother everyone else.
40  * So this is only done if the test is being run in interactive mode.
41  */
42
43 #ifndef WAVE_FORMAT_48M08
44 #define WAVE_FORMAT_48M08      0x00001000    /* 48     kHz, Mono,   8-bit  */
45 #define WAVE_FORMAT_48S08      0x00002000    /* 48     kHz, Stereo, 8-bit  */
46 #define WAVE_FORMAT_48M16      0x00004000    /* 48     kHz, Mono,   16-bit */
47 #define WAVE_FORMAT_48S16      0x00008000    /* 48     kHz, Stereo, 16-bit */
48 #define WAVE_FORMAT_96M08      0x00010000    /* 96     kHz, Mono,   8-bit  */
49 #define WAVE_FORMAT_96S08      0x00020000    /* 96     kHz, Stereo, 8-bit  */
50 #define WAVE_FORMAT_96M16      0x00040000    /* 96     kHz, Mono,   16-bit */
51 #define WAVE_FORMAT_96S16      0x00080000    /* 96     kHz, Stereo, 16-bit */
52 #endif
53
54 static const unsigned int win_formats[][4]={
55     {WAVE_FORMAT_1M08,  11025,  8, 1},
56     {WAVE_FORMAT_1S08,  11025,  8, 2},
57     {WAVE_FORMAT_1M16,  11025, 16, 1},
58     {WAVE_FORMAT_1S16,  11025, 16, 2},
59     {WAVE_FORMAT_2M08,  22050,  8, 1},
60     {WAVE_FORMAT_2S08,  22050,  8, 2},
61     {WAVE_FORMAT_2M16,  22050, 16, 1},
62     {WAVE_FORMAT_2S16,  22050, 16, 2},
63     {WAVE_FORMAT_4M08,  44100,  8, 1},
64     {WAVE_FORMAT_4S08,  44100,  8, 2},
65     {WAVE_FORMAT_4M16,  44100, 16, 1},
66     {WAVE_FORMAT_4S16,  44100, 16, 2},
67     {WAVE_FORMAT_48M08, 48000,  8, 1},
68     {WAVE_FORMAT_48S08, 48000,  8, 2},
69     {WAVE_FORMAT_48M16, 48000, 16, 1},
70     {WAVE_FORMAT_48S16, 48000, 16, 2},
71     {WAVE_FORMAT_96M08, 96000,  8, 1},
72     {WAVE_FORMAT_96S08, 96000,  8, 2},
73     {WAVE_FORMAT_96M16, 96000, 16, 1},
74     {WAVE_FORMAT_96S16, 96000, 16, 2}
75 };
76 #define NB_WIN_FORMATS (sizeof(win_formats)/sizeof(*win_formats))
77
78 #define PI 3.14159265358979323846
79 static char* wave_generate_la(WAVEFORMATEX* wfx, double duration, DWORD* size)
80 {
81     int i;
82     int nb_samples;
83     char* buf;
84     char* b;
85
86     nb_samples=(int)(duration*wfx->nSamplesPerSec);
87     *size=nb_samples*wfx->nBlockAlign;
88     b=buf=malloc(*size);
89     for (i=0;i<nb_samples;i++) {
90         double y=sin(440.0*2*PI*i/wfx->nSamplesPerSec);
91         if (wfx->wBitsPerSample==8) {
92             unsigned char sample=(unsigned char)((double)127.5*(y+1.0));
93             *b++=sample;
94             if (wfx->nChannels==2)
95                *b++=sample;
96         } else {
97             signed short sample=(signed short)((double)32767.5*y-0.5);
98             b[0]=sample & 0xff;
99             b[1]=sample >> 8;
100             b+=2;
101             if (wfx->nChannels==2) {
102                 b[0]=sample & 0xff;
103                 b[1]=sample >> 8;
104                 b+=2;
105             }
106         }
107     }
108     return buf;
109 }
110
111 static const char * wave_out_error(MMRESULT error)
112 {
113     static char msg[1024];
114     MMRESULT rc;
115
116     rc = waveOutGetErrorText(error, msg, sizeof(msg));
117     if (rc != MMSYSERR_NOERROR)
118         sprintf(msg, "waveOutGetErrorText(%x) failed with error %x", error, rc);
119     return msg;
120 }
121
122 static const char * wave_open_flags(DWORD flags)
123 {
124     static char msg[1024];
125     int first = TRUE;
126     msg[0] = 0;
127     if ((flags & CALLBACK_TYPEMASK) == CALLBACK_EVENT) {
128         strcat(msg, "CALLBACK_EVENT");
129         first = FALSE;
130     }
131     if ((flags & CALLBACK_TYPEMASK) == CALLBACK_FUNCTION) {
132         if (!first) strcat(msg, "|");
133         strcat(msg, "CALLBACK_FUNCTION");
134         first = FALSE;
135     }
136     if ((flags & CALLBACK_TYPEMASK) == CALLBACK_NULL) {
137         if (!first) strcat(msg, "|");
138         strcat(msg, "CALLBACK_NULL");
139         first = FALSE;
140     }
141     if ((flags & CALLBACK_TYPEMASK) == CALLBACK_THREAD) {
142         if (!first) strcat(msg, "|");
143         strcat(msg, "CALLBACK_THREAD");
144         first = FALSE;
145     }
146     if ((flags & CALLBACK_TYPEMASK) == CALLBACK_WINDOW) {
147         if (!first) strcat(msg, "|");
148         strcat(msg, "CALLBACK_WINDOW");
149         first = FALSE;
150     }
151     if ((flags & WAVE_ALLOWSYNC) == WAVE_ALLOWSYNC) {
152         if (!first) strcat(msg, "|");
153         strcat(msg, "WAVE_ALLOWSYNC");
154         first = FALSE;
155     }
156     if ((flags & WAVE_FORMAT_DIRECT) == WAVE_FORMAT_DIRECT) {
157         if (!first) strcat(msg, "|");
158         strcat(msg, "WAVE_FORMAT_DIRECT");
159         first = FALSE;
160     }
161     if ((flags & WAVE_FORMAT_QUERY) == WAVE_FORMAT_QUERY) {
162         if (!first) strcat(msg, "|");
163         strcat(msg, "WAVE_FORMAT_QUERY");
164         first = FALSE;
165     }
166     if ((flags & WAVE_MAPPED) == WAVE_MAPPED) {
167         if (!first) strcat(msg, "|");
168         strcat(msg, "WAVE_MAPPED");
169         first = FALSE;
170     }
171     return msg;
172 }
173
174 static void wave_out_test_deviceOut(int device, int format, DWORD flags, LPWAVEOUTCAPS pcaps)
175 {
176     WAVEFORMATEX wfx;
177     HWAVEOUT wout;
178     HANDLE hevent;
179     WAVEHDR frag;
180     MMRESULT rc;
181     DWORD volume;
182
183     hevent=CreateEvent(NULL,FALSE,FALSE,NULL);
184     ok(hevent!=NULL,"CreateEvent: error=%ld\n",GetLastError());
185     if (hevent==NULL)
186         return;
187
188     wfx.wFormatTag=WAVE_FORMAT_PCM;
189     wfx.nChannels=win_formats[format][3];
190     wfx.wBitsPerSample=win_formats[format][2];
191     wfx.nSamplesPerSec=win_formats[format][1];
192     wfx.nBlockAlign=wfx.nChannels*wfx.wBitsPerSample/8;
193     wfx.nAvgBytesPerSec=wfx.nSamplesPerSec*wfx.nBlockAlign;
194     wfx.cbSize=0;
195
196     wout=NULL;
197     rc=waveOutOpen(&wout,device,&wfx,(DWORD)hevent,0,CALLBACK_EVENT|flags);
198     /* Note: Win9x doesn't know WAVE_FORMAT_DIRECT */
199     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID ||
200        (rc==WAVERR_BADFORMAT && (flags & WAVE_FORMAT_DIRECT) && (pcaps->dwFormats & win_formats[format][0])) ||
201        (rc==MMSYSERR_INVALFLAG && (flags & WAVE_FORMAT_DIRECT)),
202        "waveOutOpen: device=%d format=%ldx%2dx%d flags=%lx(%s) rc=%d(%s)\n",device,
203        wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,CALLBACK_EVENT|flags,
204        wave_open_flags(CALLBACK_EVENT|flags),rc,wave_out_error(rc));
205     if (rc!=MMSYSERR_NOERROR) {
206         CloseHandle(hevent);
207         return;
208     }
209
210     ok(wfx.nChannels==win_formats[format][3] &&
211        wfx.wBitsPerSample==win_formats[format][2] &&
212        wfx.nSamplesPerSec==win_formats[format][1],
213        "got the wrong format: %ldx%2dx%d instead of %dx%2dx%d\n",
214        wfx.nSamplesPerSec, wfx.wBitsPerSample,
215        wfx.nChannels, win_formats[format][1], win_formats[format][2],
216        win_formats[format][3]);
217
218     frag.lpData=wave_generate_la(&wfx,1.0,&frag.dwBufferLength);
219     frag.dwFlags=0;
220     frag.dwLoops=0;
221
222     rc=waveOutGetVolume(wout,&volume);
223     ok(rc==MMSYSERR_NOERROR,"waveOutGetVolume: device=%d rc=%d\n",device,rc);
224
225     rc=waveOutPrepareHeader(wout, &frag, sizeof(frag));
226     ok(rc==MMSYSERR_NOERROR,
227        "waveOutPrepareHeader: device=%d rc=%d\n",device,rc);
228
229     if (winetest_interactive && rc==MMSYSERR_NOERROR) {
230         trace("Playing 440Hz LA at %ldx%2dx%d %04lx\n",
231               wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels,flags);
232         rc=waveOutSetVolume(wout,0x20002000);
233         ok(rc==MMSYSERR_NOERROR,"waveOutSetVolume: device=%d rc=%d\n",device,rc);
234         WaitForSingleObject(hevent,INFINITE);
235
236         rc=waveOutWrite(wout, &frag, sizeof(frag));
237         ok(rc==MMSYSERR_NOERROR,"waveOutWrite: device=%d rc=%d\n",device,rc);
238         WaitForSingleObject(hevent,INFINITE);
239
240         rc=waveOutSetVolume(wout,volume);
241         ok(rc==MMSYSERR_NOERROR,"waveOutSetVolume: device=%d rc=%d\n",device,rc);
242     }
243
244     rc=waveOutUnprepareHeader(wout, &frag, sizeof(frag));
245     ok(rc==MMSYSERR_NOERROR,
246        "waveOutUnprepareHeader: device=%d rc=%d\n",device,rc);
247     free(frag.lpData);
248
249     CloseHandle(hevent);
250     waveOutClose(wout);
251 }
252
253 static void wave_out_tests()
254 {
255     WAVEOUTCAPS caps;
256     WAVEFORMATEX format, oformat;
257     HWAVEOUT wout;
258     MMRESULT rc;
259     UINT ndev,d,f;
260     WCHAR * wname;
261     CHAR * name;
262     DWORD size;
263
264     ndev=waveOutGetNumDevs();
265     trace("found %d WaveOut devices\n",ndev);
266
267     rc=waveOutGetDevCapsA(ndev+1,&caps,sizeof(caps));
268     ok(rc==MMSYSERR_BADDEVICEID,
269        "waveOutGetDevCapsA: MMSYSERR_BADDEVICEID expected, got %d\n",rc);
270
271     rc=waveOutGetDevCapsA(-1,&caps,sizeof(caps));
272     ok(rc==MMSYSERR_NOERROR,
273        "waveOutGetDevCapsA: MMSYSERR_NOERROR expected, got %d\n",rc);
274
275     format.wFormatTag=WAVE_FORMAT_PCM;
276     format.nChannels=2;
277     format.wBitsPerSample=16;
278     format.nSamplesPerSec=44100;
279     format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
280     format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
281     format.cbSize=0;
282     rc=waveOutOpen(&wout,ndev+1,&format,0,0,CALLBACK_NULL);
283     ok(rc==MMSYSERR_BADDEVICEID,
284        "waveOutOpen: MMSYSERR_BADDEVICEID expected, got %d\n",rc);
285
286     for (d=0;d<ndev;d++) {
287         rc=waveOutGetDevCapsA(d,&caps,sizeof(caps));
288         ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID,
289            "waveOutGetDevCapsA: failed to get capabilities of device %d: rc=%d\n",d,rc);
290         if (rc==MMSYSERR_BADDEVICEID)
291             continue;
292
293         name=NULL;
294         rc=waveOutMessage((HWAVEOUT)d, DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&size, 0);
295         ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_NOTSUPPORTED,
296            "waveOutMessage: failed to get interface size for device: %d rc=%d\n",d,rc);
297         if (rc==MMSYSERR_NOERROR) {
298             wname = (WCHAR *)malloc(size);
299             rc=waveOutMessage((HWAVEOUT)d, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)wname, size);
300             ok(rc==MMSYSERR_NOERROR,"waveOutMessage: failed to get interface name for device: %d rc=%d\n",d,rc);
301             ok(lstrlenW(wname)+1==size/sizeof(WCHAR),"got an incorrect size: %ld instead of %d\n",size,(lstrlenW(wname)+1)*sizeof(WCHAR));
302             if (rc==MMSYSERR_NOERROR) {
303                 name = malloc(size/sizeof(WCHAR));
304                 WideCharToMultiByte(CP_ACP, 0, wname, size/sizeof(WCHAR), name, size/sizeof(WCHAR), NULL, NULL);
305             }
306             free(wname);
307         }
308         else if (rc==MMSYSERR_NOTSUPPORTED)
309         {
310             name=strdup("not supported");
311         }
312
313         trace("  %d: \"%s\" (%s) %d.%d (%d:%d): channels=%d formats=%05lx support=%04lx\n",
314               d,caps.szPname,(name?name:"failed"),caps.vDriverVersion >> 8,
315               caps.vDriverVersion & 0xff,
316               caps.wMid,caps.wPid,
317               caps.wChannels,caps.dwFormats,caps.dwSupport);
318         free(name);
319
320         for (f=0;f<NB_WIN_FORMATS;f++) {
321             if (caps.dwFormats & win_formats[f][0]) {
322                 wave_out_test_deviceOut(d,f,0,&caps);
323                 wave_out_test_deviceOut(d,f,WAVE_FORMAT_DIRECT,&caps);
324             }
325         }
326
327         /* Try invalid formats to test error handling */
328         trace("Testing invalid format: 11 bits per sample\n");
329         format.wFormatTag=WAVE_FORMAT_PCM;
330         format.nChannels=2;
331         format.wBitsPerSample=11;
332         format.nSamplesPerSec=22050;
333         format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
334         format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
335         format.cbSize=0;
336         oformat=format;
337         rc=waveOutOpen(&wout,d,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
338         ok(rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG,
339            "waveOutOpen: opening the device in 11 bits mode should fail %d: rc=%d\n",d,rc);
340         if (rc==MMSYSERR_NOERROR) {
341             trace("     got %ldx%2dx%d for %ldx%2dx%d\n",
342                   format.nSamplesPerSec, format.wBitsPerSample,
343                   format.nChannels,
344                   oformat.nSamplesPerSec, oformat.wBitsPerSample,
345                   oformat.nChannels);
346             waveOutClose(wout);
347         }
348
349         trace("Testing invalid format: 2 MHz sample rate\n");
350         format.wFormatTag=WAVE_FORMAT_PCM;
351         format.nChannels=2;
352         format.wBitsPerSample=16;
353         format.nSamplesPerSec=2000000;
354         format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
355         format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
356         format.cbSize=0;
357         oformat=format;
358         rc=waveOutOpen(&wout,d,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
359         ok(rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG,
360            "waveOutOpen: opening the device at 2 MHz sample rate should fail %d: rc=%d\n",d,rc);
361         if (rc==MMSYSERR_NOERROR) {
362             trace("     got %ldx%2dx%d for %ldx%2dx%d\n",
363                   format.nSamplesPerSec, format.wBitsPerSample,
364                   format.nChannels,
365                   oformat.nSamplesPerSec, oformat.wBitsPerSample,
366                   oformat.nChannels);
367             waveOutClose(wout);
368         }
369     }
370 }
371
372 static const char * wave_in_error(MMRESULT error)
373 {
374     static char msg[1024];
375     MMRESULT rc;
376
377     rc = waveInGetErrorText(error, msg, sizeof(msg));
378     if (rc != MMSYSERR_NOERROR)
379         sprintf(msg, "waveInGetErrorText(%x) failed with error %x", error, rc);
380     return msg;
381 }
382
383 static void wave_in_test_deviceIn(int device, int format, DWORD flags, LPWAVEINCAPS pcaps)
384 {
385     WAVEFORMATEX wfx;
386     HWAVEIN win;
387     HANDLE hevent;
388     WAVEHDR frag;
389     MMRESULT rc;
390     DWORD res;
391
392     hevent=CreateEvent(NULL,FALSE,FALSE,NULL);
393     ok(hevent!=NULL,"CreateEvent: error=%ld\n",GetLastError());
394     if (hevent==NULL)
395         return;
396
397     wfx.wFormatTag=WAVE_FORMAT_PCM;
398     wfx.nChannels=win_formats[format][3];
399     wfx.wBitsPerSample=win_formats[format][2];
400     wfx.nSamplesPerSec=win_formats[format][1];
401     wfx.nBlockAlign=wfx.nChannels*wfx.wBitsPerSample/8;
402     wfx.nAvgBytesPerSec=wfx.nSamplesPerSec*wfx.nBlockAlign;
403     wfx.cbSize=0;
404
405     win=NULL;
406     rc=waveInOpen(&win,device,&wfx,(DWORD)hevent,0,CALLBACK_EVENT|flags);
407     /* Note: Win9x doesn't know WAVE_FORMAT_DIRECT */
408     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID ||
409        (rc==WAVERR_BADFORMAT && (flags & WAVE_FORMAT_DIRECT) && (pcaps->dwFormats & win_formats[format][0])) ||
410        (rc==MMSYSERR_INVALFLAG && (flags & WAVE_FORMAT_DIRECT)),
411        "waveInOpen: device=%d format=%ldx%2dx%d flags=%lx(%s) rc=%d(%s)\n",device,
412        wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,CALLBACK_EVENT|flags,
413        wave_open_flags(CALLBACK_EVENT|flags),rc,wave_in_error(rc));
414     if (rc!=MMSYSERR_NOERROR) {
415         CloseHandle(hevent);
416         return;
417     }
418     res=WaitForSingleObject(hevent,1000);
419     ok(res==WAIT_OBJECT_0,"WaitForSingleObject failed for open\n");
420
421     ok(wfx.nChannels==win_formats[format][3] &&
422        wfx.wBitsPerSample==win_formats[format][2] &&
423        wfx.nSamplesPerSec==win_formats[format][1],
424        "got the wrong format: %ldx%2dx%d instead of %dx%2dx%d\n",
425        wfx.nSamplesPerSec, wfx.wBitsPerSample,
426        wfx.nChannels, win_formats[format][1], win_formats[format][2],
427        win_formats[format][3]);
428
429     frag.lpData=malloc(wfx.nAvgBytesPerSec);
430     frag.dwBufferLength=wfx.nAvgBytesPerSec;
431     frag.dwBytesRecorded=0;
432     frag.dwUser=0;
433     frag.dwFlags=0;
434     frag.dwLoops=0;
435     frag.lpNext=0;
436
437     rc=waveInPrepareHeader(win, &frag, sizeof(frag));
438     ok(rc==MMSYSERR_NOERROR, "waveInPrepareHeader: device=%d rc=%d(%s)\n",device,rc,wave_in_error(rc));
439     ok(frag.dwFlags&WHDR_PREPARED,"waveInPrepareHeader: prepared flag not set\n");
440
441     if (winetest_interactive && rc==MMSYSERR_NOERROR) {
442         trace("Recording at %ldx%2dx%d %04lx\n",
443               wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels,flags);
444
445         rc=waveInAddBuffer(win, &frag, sizeof(frag));
446         ok(rc==MMSYSERR_NOERROR,"waveInAddBuffer: device=%d rc=%d(%s)\n",device,rc,wave_in_error(rc));
447
448         rc=waveInStart(win);
449         ok(rc==MMSYSERR_NOERROR,"waveInStart: device=%d rc=%d(%s)\n",device,rc,wave_in_error(rc));
450
451         res = WaitForSingleObject(hevent,1200);
452         ok(res==WAIT_OBJECT_0,"WaitForSingleObject failed for header\n");
453         ok(frag.dwFlags&WHDR_DONE,"WHDR_DONE not set in frag.dwFlags\n");
454         ok(frag.dwBytesRecorded==wfx.nAvgBytesPerSec,"frag.dwBytesRecorded=%ld, should=%ld\n",
455            frag.dwBytesRecorded,wfx.nAvgBytesPerSec);
456         /* stop playing on error */
457         if (res!=WAIT_OBJECT_0) {
458             rc=waveInStop(win);
459             ok(rc==MMSYSERR_NOERROR,
460                "waveInStop: device=%d rc=%d(%s)\n",device,rc,wave_in_error(rc));
461         }
462     }
463
464     rc=waveInUnprepareHeader(win, &frag, sizeof(frag));
465     ok(rc==MMSYSERR_NOERROR,
466        "waveInUnprepareHeader: device=%d rc=%d(%s)\n",device,rc,wave_in_error(rc));
467
468     waveInClose(win);
469     res=WaitForSingleObject(hevent,1000);
470     ok(res==WAIT_OBJECT_0,"WaitForSingleObject failed for close\n");
471     free(frag.lpData);
472     CloseHandle(hevent);
473 }
474
475 static void wave_in_tests()
476 {
477     WAVEINCAPS caps;
478     WAVEFORMATEX format,oformat;
479     HWAVEIN win;
480     MMRESULT rc;
481     UINT ndev,d,f;
482     WCHAR * wname;
483     CHAR * name;
484     DWORD size;
485
486     ndev=waveInGetNumDevs();
487     trace("found %d WaveIn devices\n",ndev);
488
489     rc=waveInGetDevCapsA(ndev+1,&caps,sizeof(caps));
490     ok(rc==MMSYSERR_BADDEVICEID,
491        "waveInGetDevCapsA: MMSYSERR_BADDEVICEID expected, got %d(%s)\n",rc,wave_in_error(rc));
492
493     rc=waveInGetDevCapsA(-1,&caps,sizeof(caps));
494     ok(rc==MMSYSERR_NOERROR,
495        "waveInGetDevCapsA: MMSYSERR_NOERROR expected, got %d\n",rc);
496
497     format.wFormatTag=WAVE_FORMAT_PCM;
498     format.nChannels=2;
499     format.wBitsPerSample=16;
500     format.nSamplesPerSec=44100;
501     format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
502     format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
503     format.cbSize=0;
504     rc=waveInOpen(&win,ndev+1,&format,0,0,CALLBACK_NULL);
505     ok(rc==MMSYSERR_BADDEVICEID,
506        "waveInOpen: MMSYSERR_BADDEVICEID expected, got %d(%s)\n",rc,wave_in_error(rc));
507
508     for (d=0;d<ndev;d++) {
509         rc=waveInGetDevCapsA(d,&caps,sizeof(caps));
510         ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID,
511            "waveInGetDevCapsA: failed to get capabilities of device %d: rc=%d(%s)\n",d,rc,wave_in_error(rc));
512         if (rc==MMSYSERR_BADDEVICEID)
513             continue;
514
515         name=NULL;
516         rc=waveInMessage((HWAVEIN)d, DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&size, 0);
517         ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_NOTSUPPORTED,
518            "waveInMessage: failed to get interface size for device: %d rc=%d(%s)\n",d,rc,wave_in_error(rc));
519         if (rc==MMSYSERR_NOERROR) {
520             wname = (WCHAR *)malloc(size);
521             rc=waveInMessage((HWAVEIN)d, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)wname, size);
522             ok(rc==MMSYSERR_NOERROR,"waveInMessage: failed to get interface name for device: %d rc=%d(%s)\n",d,rc,wave_in_error(rc));
523             ok(lstrlenW(wname)+1==size/sizeof(WCHAR),"got an incorrect size: %ld instead of %d\n",size,(lstrlenW(wname)+1)*sizeof(WCHAR));
524             if (rc==MMSYSERR_NOERROR) {
525                 name = malloc(size/sizeof(WCHAR));
526                 WideCharToMultiByte(CP_ACP, 0, wname, size/sizeof(WCHAR), name, size/sizeof(WCHAR), NULL, NULL);
527             }
528             free(wname);
529         }
530         else if (rc==MMSYSERR_NOTSUPPORTED)
531         {
532             name=strdup("not supported");
533         }
534
535         trace("  %d: \"%s\" (%s) %d.%d (%d:%d): channels=%d formats=%05lx\n",
536               d,caps.szPname,(name?name:"failed"),caps.vDriverVersion >> 8,
537               caps.vDriverVersion & 0xff,
538               caps.wMid,caps.wPid,
539               caps.wChannels,caps.dwFormats);
540         free(name);
541
542         for (f=0;f<NB_WIN_FORMATS;f++) {
543             if (caps.dwFormats & win_formats[f][0]) {
544                 wave_in_test_deviceIn(d,f,0, &caps);
545                 wave_in_test_deviceIn(d,f,WAVE_FORMAT_DIRECT, &caps);
546             }
547         }
548
549         /* Try invalid formats to test error handling */
550         trace("Testing invalid format: 11 bits per sample\n");
551         format.wFormatTag=WAVE_FORMAT_PCM;
552         format.nChannels=2;
553         format.wBitsPerSample=11;
554         format.nSamplesPerSec=22050;
555         format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
556         format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
557         format.cbSize=0;
558         oformat=format;
559         rc=waveInOpen(&win,d,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
560         ok(rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG,
561            "waveInOpen: opening the device in 11 bit mode should fail %d: rc=%d\n",d,rc);
562         if (rc==MMSYSERR_NOERROR) {
563             trace("     got %ldx%2dx%d for %ldx%2dx%d\n",
564                   format.nSamplesPerSec, format.wBitsPerSample,
565                   format.nChannels,
566                   oformat.nSamplesPerSec, oformat.wBitsPerSample,
567                   oformat.nChannels);
568             waveInClose(win);
569         }
570
571         trace("Testing invalid format: 2 MHz sample rate\n");
572         format.wFormatTag=WAVE_FORMAT_PCM;
573         format.nChannels=2;
574         format.wBitsPerSample=16;
575         format.nSamplesPerSec=2000000;
576         format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
577         format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
578         format.cbSize=0;
579         oformat=format;
580         rc=waveInOpen(&win,d,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
581         ok(rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG,
582            "waveInOpen: opening the device with 2 MHz sample rate should fail %d: rc=%d\n",d,rc);
583         if (rc==MMSYSERR_NOERROR) {
584             trace("     got %ldx%2dx%d for %ldx%2dx%d\n",
585                   format.nSamplesPerSec, format.wBitsPerSample,
586                   format.nChannels,
587                   oformat.nSamplesPerSec, oformat.wBitsPerSample,
588                   oformat.nChannels);
589             waveInClose(win);
590         }
591     }
592 }
593
594 START_TEST(wave)
595 {
596     wave_out_tests();
597     wave_in_tests();
598 }