Removed 11 bit sample size capture test because at least 2
[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 #include "mmddk.h"
32
33 #include "winmm_test.h"
34
35 static const char * wave_in_error(MMRESULT error)
36 {
37     static char msg[1024];
38     static char long_msg[1100];
39     MMRESULT rc;
40
41     rc = waveInGetErrorText(error, msg, sizeof(msg));
42     if (rc != MMSYSERR_NOERROR)
43         sprintf(long_msg, "waveInGetErrorText(%x) failed with error %x", error, rc);
44     else
45         sprintf(long_msg, "%s(%s)", mmsys_error(error), msg);
46     return long_msg;
47 }
48
49 static void wave_in_test_deviceIn(int device, LPWAVEFORMATEX pwfx, DWORD format, DWORD flags, LPWAVEINCAPS pcaps)
50 {
51     HWAVEIN win;
52     HANDLE hevent;
53     WAVEHDR frag;
54     MMRESULT rc;
55     DWORD res;
56     WORD nChannels = pwfx->nChannels;
57     WORD wBitsPerSample = pwfx->wBitsPerSample;
58     DWORD nSamplesPerSec = pwfx->nSamplesPerSec;
59
60     hevent=CreateEvent(NULL,FALSE,FALSE,NULL);
61     ok(hevent!=NULL,"CreateEvent: error=%ld\n",GetLastError());
62     if (hevent==NULL)
63         return;
64
65     win=NULL;
66     rc=waveInOpen(&win,device,pwfx,(DWORD)hevent,0,CALLBACK_EVENT|flags);
67     /* Note: Win9x doesn't know WAVE_FORMAT_DIRECT */
68     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID ||
69        rc==MMSYSERR_NOTENABLED || rc==MMSYSERR_NODRIVER || rc==MMSYSERR_ALLOCATED ||
70        ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
71        (flags & WAVE_FORMAT_DIRECT) && !(pcaps->dwFormats & format)) ||
72        ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
73        (!(flags & WAVE_FORMAT_DIRECT) || (flags & WAVE_MAPPED)) && !(pcaps->dwFormats & format)) ||
74        (rc==MMSYSERR_INVALFLAG && (flags & WAVE_FORMAT_DIRECT)),
75        "waveInOpen: device=%s format=%ldx%2dx%d flags=%lx(%s) rc=%s\n",dev_name(device),
76        pwfx->nSamplesPerSec,pwfx->wBitsPerSample,pwfx->nChannels,CALLBACK_EVENT|flags,
77        wave_open_flags(CALLBACK_EVENT|flags),wave_in_error(rc));
78     if ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
79        (flags & WAVE_FORMAT_DIRECT) && (pcaps->dwFormats & format))
80         trace(" Reason: The device lists this format as supported in it's capabilities but opening it failed.\n");
81     if ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) &&
82        !(pcaps->dwFormats & format))
83         trace("waveInOpen: device=%s format=%ldx%2dx%d %s rc=%s failed but format not supported so OK.\n",
84               dev_name(device), pwfx->nSamplesPerSec,pwfx->wBitsPerSample,pwfx->nChannels,
85               flags & WAVE_FORMAT_DIRECT ? "flags=WAVE_FORMAT_DIRECT" :
86               flags & WAVE_MAPPED ? "flags=WAVE_MAPPED" : "", mmsys_error(rc));
87     if (rc!=MMSYSERR_NOERROR) {
88         CloseHandle(hevent);
89         return;
90     }
91     res=WaitForSingleObject(hevent,1000);
92     ok(res==WAIT_OBJECT_0,"WaitForSingleObject failed for open\n");
93
94     ok(pwfx->nChannels==nChannels &&
95        pwfx->wBitsPerSample==wBitsPerSample &&
96        pwfx->nSamplesPerSec==nSamplesPerSec,
97        "got the wrong format: %ldx%2dx%d instead of %ldx%2dx%d\n",
98        pwfx->nSamplesPerSec, pwfx->wBitsPerSample,
99        pwfx->nChannels, nSamplesPerSec, wBitsPerSample, nChannels);
100
101     frag.lpData=malloc(pwfx->nAvgBytesPerSec);
102     frag.dwBufferLength=pwfx->nAvgBytesPerSec;
103     frag.dwBytesRecorded=0;
104     frag.dwUser=0;
105     frag.dwFlags=0;
106     frag.dwLoops=0;
107     frag.lpNext=0;
108
109     rc=waveInPrepareHeader(win, &frag, sizeof(frag));
110     ok(rc==MMSYSERR_NOERROR, "waveInPrepareHeader: device=%s rc=%s\n",dev_name(device),wave_in_error(rc));
111     ok(frag.dwFlags&WHDR_PREPARED,"waveInPrepareHeader: prepared flag not set\n");
112
113     if (winetest_interactive && rc==MMSYSERR_NOERROR) {
114         trace("Recording for 1 second at %5ldx%2dx%d %s\n",
115               pwfx->nSamplesPerSec, pwfx->wBitsPerSample,pwfx->nChannels,
116               flags & WAVE_FORMAT_DIRECT ? "WAVE_FORMAT_DIRECT" :
117               flags & WAVE_MAPPED ? "WAVE_MAPPED" : "");
118         rc=waveInAddBuffer(win, &frag, sizeof(frag));
119         ok(rc==MMSYSERR_NOERROR,"waveInAddBuffer: device=%s rc=%s\n",dev_name(device),wave_in_error(rc));
120
121         rc=waveInStart(win);
122         ok(rc==MMSYSERR_NOERROR,"waveInStart: device=%s rc=%s\n",dev_name(device),wave_in_error(rc));
123
124         res = WaitForSingleObject(hevent,1200);
125         ok(res==WAIT_OBJECT_0,"WaitForSingleObject failed for header\n");
126         ok(frag.dwFlags&WHDR_DONE,"WHDR_DONE not set in frag.dwFlags\n");
127         ok(frag.dwBytesRecorded==pwfx->nAvgBytesPerSec,"frag.dwBytesRecorded=%ld, should=%ld\n",
128            frag.dwBytesRecorded,pwfx->nAvgBytesPerSec);
129         /* stop playing on error */
130         if (res!=WAIT_OBJECT_0) {
131             rc=waveInStop(win);
132             ok(rc==MMSYSERR_NOERROR,
133                "waveInStop: device=%s rc=%s\n",dev_name(device),wave_in_error(rc));
134         }
135     }
136
137     rc=waveInUnprepareHeader(win, &frag, sizeof(frag));
138     ok(rc==MMSYSERR_NOERROR,
139        "waveInUnprepareHeader: device=%s rc=%s\n",dev_name(device),wave_in_error(rc));
140
141     rc=waveInClose(win);
142     ok(rc==MMSYSERR_NOERROR,
143        "waveInClose: device=%s rc=%s\n",dev_name(device),wave_in_error(rc));
144     res=WaitForSingleObject(hevent,1000);
145     ok(res==WAIT_OBJECT_0,"WaitForSingleObject failed for close\n");
146     free(frag.lpData);
147     CloseHandle(hevent);
148 }
149
150 static void wave_in_test_device(int device)
151 {
152     WAVEINCAPS caps;
153     WAVEFORMATEX format,oformat;
154     HWAVEIN win;
155     MMRESULT rc;
156     UINT f;
157     WCHAR * wname;
158     CHAR * name;
159     DWORD size;
160     DWORD dwPageSize;
161     BYTE * twoPages;
162     SYSTEM_INFO sSysInfo;
163     DWORD flOldProtect;
164     BOOL res;
165
166     GetSystemInfo(&sSysInfo);
167     dwPageSize = sSysInfo.dwPageSize;
168
169     rc=waveInGetDevCapsA(device,&caps,sizeof(caps));
170     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NODRIVER,
171        "waveInGetDevCapsA: failed to get capabilities of device %s: rc=%s\n",dev_name(device),wave_in_error(rc));
172     if (rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NODRIVER)
173         return;
174
175     rc=waveInGetDevCapsA(device,0,sizeof(caps));
176     ok(rc==MMSYSERR_INVALPARAM,
177        "waveInGetDevCapsA: MMSYSERR_INVALPARAM expected, got %s\n",wave_in_error(rc));
178
179 #if 0 /* FIXME: this works on windows but crashes wine */
180     rc=waveInGetDevCapsA(device,1,sizeof(caps));
181     ok(rc==MMSYSERR_INVALPARAM,
182        "waveInGetDevCapsA: MMSYSERR_INVALPARAM expected, got %s\n",wave_in_error(rc));
183 #endif
184
185     rc=waveInGetDevCapsA(device,&caps,4);
186     ok(rc==MMSYSERR_NOERROR,
187        "waveInGetDevCapsA: MMSYSERR_NOERROR expected, got %s\n",wave_in_error(rc));
188
189     name=NULL;
190     rc=waveInMessage((HWAVEIN)device, DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&size, 0);
191     ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_NOTSUPPORTED,
192        "waveInMessage: failed to get interface size for device: %s rc=%s\n",dev_name(device),wave_in_error(rc));
193     if (rc==MMSYSERR_NOERROR) {
194         wname = (WCHAR *)malloc(size);
195         rc=waveInMessage((HWAVEIN)device, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)wname, size);
196         ok(rc==MMSYSERR_NOERROR,"waveInMessage: failed to get interface name for device: %s rc=%s\n",dev_name(device),wave_in_error(rc));
197         ok(lstrlenW(wname)+1==size/sizeof(WCHAR),"got an incorrect size: %ld instead of %d\n",size,(lstrlenW(wname)+1)*sizeof(WCHAR));
198         if (rc==MMSYSERR_NOERROR) {
199             name = malloc(size/sizeof(WCHAR));
200             WideCharToMultiByte(CP_ACP, 0, wname, size/sizeof(WCHAR), name, size/sizeof(WCHAR), NULL, NULL);
201         }
202         free(wname);
203     } else if (rc==MMSYSERR_NOTSUPPORTED) {
204         name=strdup("not supported");
205     }
206
207     trace("  %s: \"%s\" (%s) %d.%d (%d:%d): channels=%d formats=%05lx\n",
208           dev_name(device),caps.szPname,(name?name:"failed"),caps.vDriverVersion >> 8,
209           caps.vDriverVersion & 0xff,
210           caps.wMid,caps.wPid,
211           caps.wChannels,caps.dwFormats);
212
213     free(name);
214
215     for (f=0;f<NB_WIN_FORMATS;f++) {
216         format.wFormatTag=WAVE_FORMAT_PCM;
217         format.nChannels=win_formats[f][3];
218         format.wBitsPerSample=win_formats[f][2];
219         format.nSamplesPerSec=win_formats[f][1];
220         format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
221         format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
222         format.cbSize=0;
223         wave_in_test_deviceIn(device,&format,win_formats[f][0],0, &caps);
224         wave_in_test_deviceIn(device,&format,win_formats[f][0],WAVE_FORMAT_DIRECT, &caps);
225         if (device != WAVE_MAPPER)
226             wave_in_test_deviceIn(device,&format,win_formats[f][0],WAVE_MAPPED, &caps);
227     }
228
229     /* Try a PCMWAVEFORMAT aligned next to an unaccessable page for bounds checking */
230     twoPages = VirtualAlloc(NULL, 2 * dwPageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
231     ok(twoPages!=NULL,"Failed to allocate 2 pages of memory\n");
232     if (twoPages) {
233         res = VirtualProtect(twoPages + dwPageSize, dwPageSize, PAGE_NOACCESS, &flOldProtect);
234         ok(res, "Failed to set memory access on second page\n");
235         if (res) {
236             LPWAVEFORMATEX pwfx = (LPWAVEFORMATEX)(twoPages + dwPageSize - sizeof(PCMWAVEFORMAT));
237             pwfx->wFormatTag=WAVE_FORMAT_PCM;
238             pwfx->nChannels=1;
239             pwfx->wBitsPerSample=8;
240             pwfx->nSamplesPerSec=22050;
241             pwfx->nBlockAlign=pwfx->nChannels*pwfx->wBitsPerSample/8;
242             pwfx->nAvgBytesPerSec=pwfx->nSamplesPerSec*pwfx->nBlockAlign;
243             wave_in_test_deviceIn(device,pwfx,WAVE_FORMAT_2M08,0, &caps);
244             wave_in_test_deviceIn(device,pwfx,WAVE_FORMAT_2M08,WAVE_FORMAT_DIRECT, &caps);
245             if (device != WAVE_MAPPER)
246                 wave_in_test_deviceIn(device,pwfx,WAVE_FORMAT_2M08,WAVE_MAPPED, &caps);
247         }
248         VirtualFree(twoPages, 2 * dwPageSize, MEM_RELEASE);
249     }
250
251     /* Try invalid formats to test error handling */
252     trace("Testing invalid format: 2 MHz sample rate\n");
253     format.wFormatTag=WAVE_FORMAT_PCM;
254     format.nChannels=2;
255     format.wBitsPerSample=16;
256     format.nSamplesPerSec=2000000;
257     format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
258     format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
259     format.cbSize=0;
260     oformat=format;
261     rc=waveInOpen(&win,device,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT);
262     ok(rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM,
263        "waveInOpen: opening the device with 2 MHz sample rate should fail %s: rc=%s\n",dev_name(device),wave_in_error(rc));
264     if (rc==MMSYSERR_NOERROR) {
265         trace("     got %ldx%2dx%d for %ldx%2dx%d\n",
266               format.nSamplesPerSec, format.wBitsPerSample,
267               format.nChannels,
268               oformat.nSamplesPerSec, oformat.wBitsPerSample,
269               oformat.nChannels);
270         waveInClose(win);
271     }
272 }
273
274 static void wave_in_tests()
275 {
276     WAVEINCAPS caps;
277     WAVEFORMATEX format;
278     HWAVEIN win;
279     MMRESULT rc;
280     UINT ndev,d;
281
282     ndev=waveInGetNumDevs();
283     trace("found %d WaveIn devices\n",ndev);
284
285     rc=waveInGetDevCapsA(ndev+1,&caps,sizeof(caps));
286     ok(rc==MMSYSERR_BADDEVICEID,
287        "waveInGetDevCapsA: MMSYSERR_BADDEVICEID expected, got %s\n",wave_in_error(rc));
288
289     rc=waveInGetDevCapsA(WAVE_MAPPER,&caps,sizeof(caps));
290     if (ndev>0)
291         ok(rc==MMSYSERR_NOERROR,
292            "waveInGetDevCapsA: MMSYSERR_NOERROR expected, got %s\n",wave_in_error(rc));
293     else
294         ok(rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NODRIVER,
295            "waveInGetDevCapsA: MMSYSERR_BADDEVICEID or MMSYSERR_NODRIVER expected, got %s\n",wave_in_error(rc));
296
297     format.wFormatTag=WAVE_FORMAT_PCM;
298     format.nChannels=2;
299     format.wBitsPerSample=16;
300     format.nSamplesPerSec=44100;
301     format.nBlockAlign=format.nChannels*format.wBitsPerSample/8;
302     format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign;
303     format.cbSize=0;
304     rc=waveInOpen(&win,ndev+1,&format,0,0,CALLBACK_NULL);
305     ok(rc==MMSYSERR_BADDEVICEID,
306        "waveInOpen: MMSYSERR_BADDEVICEID expected, got %s\n",wave_in_error(rc));
307
308     for (d=0;d<ndev;d++)
309         wave_in_test_device(d);
310
311     if (ndev>0)
312         wave_in_test_device(WAVE_MAPPER);
313 }
314
315 START_TEST(capture)
316 {
317     wave_in_tests();
318 }