2 * Test winmm sound playback in each sound format
4 * Copyright (c) 2002 Francois Gouget
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.
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.
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
26 #include "wine/test.h"
37 //#include "ksmedia.h"
39 #include "winmm_test.h"
42 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM
, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
43 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
47 static void test_multiple_waveopens(void)
49 HWAVEOUT handle1
, handle2
;
53 wfx
.wFormatTag
= WAVE_FORMAT_PCM
;
55 wfx
.nSamplesPerSec
= 11025;
57 wfx
.nAvgBytesPerSec
= wfx
.nSamplesPerSec
* wfx
.nBlockAlign
;
58 wfx
.wBitsPerSample
= 8;
61 ret
= waveOutOpen(&handle1
, 0, &wfx
, 0, 0, 0);
62 if (ret
!= MMSYSERR_NOERROR
)
64 skip("Could not do the duplicate waveopen test\n");
68 ret
= waveOutOpen(&handle2
, 0, &wfx
, 0, 0, 0);
69 /* Modern Windows allows for wave-out devices to be opened multiple times.
70 * Some Wine audio drivers allow that and some don't. To avoid false alarms
71 * for those that do, don't "todo_wine ok(...)" on success.
73 if (ret
!= MMSYSERR_NOERROR
)
75 todo_wine
ok(ret
== MMSYSERR_NOERROR
|| broken(ret
== MMSYSERR_ALLOCATED
), /* winME */
76 "second waveOutOpen returns: %x\n", ret
);
79 waveOutClose(handle2
);
81 waveOutClose(handle1
);
85 * Note that in most of this test we may get MMSYSERR_BADDEVICEID errors
86 * at about any time if the user starts another application that uses the
87 * sound device. So we should not report these as test failures.
89 * This test can play a test tone. But this only makes sense if someone
90 * is going to carefully listen to it, and would only bother everyone else.
91 * So this is only done if the test is being run in interactive mode.
94 #define PI 3.14159265358979323846
95 static char* wave_generate_la(WAVEFORMATEX
* wfx
, double duration
, DWORD
* size
)
101 WAVEFORMATEXTENSIBLE
*wfex
= (WAVEFORMATEXTENSIBLE
*)wfx
;
103 nb_samples
=(int)(duration
*wfx
->nSamplesPerSec
);
104 *size
=nb_samples
*wfx
->nBlockAlign
;
105 b
=buf
=HeapAlloc(GetProcessHeap(), 0, *size
);
106 for (i
=0;i
<nb_samples
;i
++) {
107 double y
=sin(440.0*2*PI
*i
/wfx
->nSamplesPerSec
);
108 if (wfx
->wBitsPerSample
==8) {
109 unsigned char sample
=(unsigned char)((double)127.5*(y
+1.0));
110 for (j
= 0; j
< wfx
->nChannels
; j
++)
112 } else if (wfx
->wBitsPerSample
==16) {
113 signed short sample
=(signed short)((double)32767.5*y
-0.5);
114 for (j
= 0; j
< wfx
->nChannels
; j
++) {
119 } else if (wfx
->wBitsPerSample
==24) {
120 signed int sample
=(signed int)(((double)0x7fffff+0.5)*y
-0.5);
121 for (j
= 0; j
< wfx
->nChannels
; j
++) {
123 b
[1]=(sample
>> 8) & 0xff;
124 b
[2]=(sample
>> 16) & 0xff;
127 } else if ((wfx
->wBitsPerSample
==32) && ((wfx
->wFormatTag
== WAVE_FORMAT_PCM
) ||
128 ((wfx
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
) &&
129 IsEqualGUID(&wfex
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
)))) {
130 signed int sample
=(signed int)(((double)0x7fffffff+0.5)*y
-0.5);
131 for (j
= 0; j
< wfx
->nChannels
; j
++) {
133 b
[1]=(sample
>> 8) & 0xff;
134 b
[2]=(sample
>> 16) & 0xff;
135 b
[3]=(sample
>> 24) & 0xff;
138 } else if ((wfx
->wBitsPerSample
==32) && (wfx
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
) &&
139 IsEqualGUID(&wfex
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
)) {
140 union { float f
; char c
[4]; } sample
;
142 for (j
= 0; j
< wfx
->nChannels
; j
++) {
154 static char* wave_generate_silence(WAVEFORMATEX
* wfx
, double duration
, DWORD
* size
)
160 WAVEFORMATEXTENSIBLE
*wfex
= (WAVEFORMATEXTENSIBLE
*)wfx
;
162 nb_samples
=(int)(duration
*wfx
->nSamplesPerSec
);
163 *size
=nb_samples
*wfx
->nBlockAlign
;
164 b
=buf
=HeapAlloc(GetProcessHeap(), 0, *size
);
165 for (i
=0;i
<nb_samples
;i
++) {
166 if (wfx
->wBitsPerSample
==8) {
167 for (j
= 0; j
< wfx
->nChannels
; j
++)
169 } else if (wfx
->wBitsPerSample
==16) {
170 for (j
= 0; j
< wfx
->nChannels
; j
++) {
175 } else if (wfx
->wBitsPerSample
==24) {
176 for (j
= 0; j
< wfx
->nChannels
; j
++) {
182 } else if ((wfx
->wBitsPerSample
==32) && ((wfx
->wFormatTag
== WAVE_FORMAT_PCM
) ||
183 ((wfx
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
) &&
184 IsEqualGUID(&wfex
->SubFormat
, &KSDATAFORMAT_SUBTYPE_PCM
)))) {
185 for (j
= 0; j
< wfx
->nChannels
; j
++) {
192 } else if ((wfx
->wBitsPerSample
==32) && (wfx
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
) &&
193 IsEqualGUID(&wfex
->SubFormat
, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
)) {
194 union { float f
; char c
[4]; } sample
;
196 for (j
= 0; j
< wfx
->nChannels
; j
++) {
208 const char * dev_name(int device
)
210 static char name
[16];
211 if (device
== WAVE_MAPPER
)
212 return "WAVE_MAPPER";
213 sprintf(name
, "%d", device
);
217 const char* mmsys_error(MMRESULT error
)
219 #define ERR_TO_STR(dev) case dev: return #dev
220 static char unknown
[32];
222 ERR_TO_STR(MMSYSERR_NOERROR
);
223 ERR_TO_STR(MMSYSERR_ERROR
);
224 ERR_TO_STR(MMSYSERR_BADDEVICEID
);
225 ERR_TO_STR(MMSYSERR_NOTENABLED
);
226 ERR_TO_STR(MMSYSERR_ALLOCATED
);
227 ERR_TO_STR(MMSYSERR_INVALHANDLE
);
228 ERR_TO_STR(MMSYSERR_NODRIVER
);
229 ERR_TO_STR(MMSYSERR_NOMEM
);
230 ERR_TO_STR(MMSYSERR_NOTSUPPORTED
);
231 ERR_TO_STR(MMSYSERR_BADERRNUM
);
232 ERR_TO_STR(MMSYSERR_INVALFLAG
);
233 ERR_TO_STR(MMSYSERR_INVALPARAM
);
234 ERR_TO_STR(WAVERR_BADFORMAT
);
235 ERR_TO_STR(WAVERR_STILLPLAYING
);
236 ERR_TO_STR(WAVERR_UNPREPARED
);
237 ERR_TO_STR(WAVERR_SYNC
);
238 ERR_TO_STR(MIDIERR_UNPREPARED
);
239 ERR_TO_STR(MIDIERR_STILLPLAYING
);
240 ERR_TO_STR(MIDIERR_NOTREADY
);
241 ERR_TO_STR(MIDIERR_NODEVICE
);
242 ERR_TO_STR(MIDIERR_INVALIDSETUP
);
243 ERR_TO_STR(TIMERR_NOCANDO
);
244 ERR_TO_STR(TIMERR_STRUCT
);
245 ERR_TO_STR(JOYERR_PARMS
);
246 ERR_TO_STR(JOYERR_NOCANDO
);
247 ERR_TO_STR(JOYERR_UNPLUGGED
);
248 ERR_TO_STR(MIXERR_INVALLINE
);
249 ERR_TO_STR(MIXERR_INVALCONTROL
);
250 ERR_TO_STR(MIXERR_INVALVALUE
);
251 ERR_TO_STR(MMIOERR_FILENOTFOUND
);
252 ERR_TO_STR(MMIOERR_OUTOFMEMORY
);
253 ERR_TO_STR(MMIOERR_CANNOTOPEN
);
254 ERR_TO_STR(MMIOERR_CANNOTCLOSE
);
255 ERR_TO_STR(MMIOERR_CANNOTREAD
);
256 ERR_TO_STR(MMIOERR_CANNOTWRITE
);
257 ERR_TO_STR(MMIOERR_CANNOTSEEK
);
258 ERR_TO_STR(MMIOERR_CANNOTEXPAND
);
259 ERR_TO_STR(MMIOERR_CHUNKNOTFOUND
);
260 ERR_TO_STR(MMIOERR_UNBUFFERED
);
262 sprintf(unknown
, "Unknown(0x%08x)", error
);
267 const char* wave_out_error(MMRESULT error
)
269 static char msg
[1024];
270 static char long_msg
[1100];
273 rc
= waveOutGetErrorTextA(error
, msg
, sizeof(msg
));
274 if (rc
!= MMSYSERR_NOERROR
)
275 sprintf(long_msg
, "waveOutGetErrorTextA(%x) failed with error %x", error
, rc
);
277 sprintf(long_msg
, "%s(%s)", mmsys_error(error
), msg
);
281 const char * wave_open_flags(DWORD flags
)
283 static char msg
[1024];
286 if ((flags
& CALLBACK_TYPEMASK
) == CALLBACK_EVENT
) {
287 strcat(msg
, "CALLBACK_EVENT");
290 if ((flags
& CALLBACK_TYPEMASK
) == CALLBACK_FUNCTION
) {
291 if (!first
) strcat(msg
, "|");
292 strcat(msg
, "CALLBACK_FUNCTION");
295 if ((flags
& CALLBACK_TYPEMASK
) == CALLBACK_NULL
) {
296 if (!first
) strcat(msg
, "|");
297 strcat(msg
, "CALLBACK_NULL");
300 if ((flags
& CALLBACK_TYPEMASK
) == CALLBACK_THREAD
) {
301 if (!first
) strcat(msg
, "|");
302 strcat(msg
, "CALLBACK_THREAD");
305 if ((flags
& CALLBACK_TYPEMASK
) == CALLBACK_WINDOW
) {
306 if (!first
) strcat(msg
, "|");
307 strcat(msg
, "CALLBACK_WINDOW");
310 if ((flags
& WAVE_ALLOWSYNC
) == WAVE_ALLOWSYNC
) {
311 if (!first
) strcat(msg
, "|");
312 strcat(msg
, "WAVE_ALLOWSYNC");
315 if ((flags
& WAVE_FORMAT_DIRECT
) == WAVE_FORMAT_DIRECT
) {
316 if (!first
) strcat(msg
, "|");
317 strcat(msg
, "WAVE_FORMAT_DIRECT");
320 if ((flags
& WAVE_FORMAT_QUERY
) == WAVE_FORMAT_QUERY
) {
321 if (!first
) strcat(msg
, "|");
322 strcat(msg
, "WAVE_FORMAT_QUERY");
325 if ((flags
& WAVE_MAPPED
) == WAVE_MAPPED
) {
326 if (!first
) strcat(msg
, "|");
327 strcat(msg
, "WAVE_MAPPED");
332 static const char * wave_header_flags(DWORD flags
)
334 #define WHDR_MASK (WHDR_BEGINLOOP|WHDR_DONE|WHDR_ENDLOOP|WHDR_INQUEUE|WHDR_PREPARED)
335 static char msg
[1024];
338 if (flags
& WHDR_BEGINLOOP
) {
339 strcat(msg
, "WHDR_BEGINLOOP");
342 if (flags
& WHDR_DONE
) {
343 if (!first
) strcat(msg
, " ");
344 strcat(msg
, "WHDR_DONE");
347 if (flags
& WHDR_ENDLOOP
) {
348 if (!first
) strcat(msg
, " ");
349 strcat(msg
, "WHDR_ENDLOOP");
352 if (flags
& WHDR_INQUEUE
) {
353 if (!first
) strcat(msg
, " ");
354 strcat(msg
, "WHDR_INQUEUE");
357 if (flags
& WHDR_PREPARED
) {
358 if (!first
) strcat(msg
, " ");
359 strcat(msg
, "WHDR_PREPARED");
362 if (flags
& ~WHDR_MASK
) {
364 sprintf(temp
, "UNKNOWN(0x%08x)", flags
& ~WHDR_MASK
);
365 if (!first
) strcat(msg
, " ");
371 static const char * wave_out_caps(DWORD dwSupport
)
373 #define ADD_FLAG(f) if (dwSupport & f) strcat(msg, " " #f)
374 static char msg
[256];
377 ADD_FLAG(WAVECAPS_PITCH
);
378 ADD_FLAG(WAVECAPS_PLAYBACKRATE
);
379 ADD_FLAG(WAVECAPS_VOLUME
);
380 ADD_FLAG(WAVECAPS_LRVOLUME
);
381 ADD_FLAG(WAVECAPS_SYNC
);
382 ADD_FLAG(WAVECAPS_SAMPLEACCURATE
);
384 return msg
[0] ? msg
+ 1 : "";
388 const char * wave_time_format(UINT type
)
391 #define TIME_FORMAT(f) case f: return #f
393 TIME_FORMAT(TIME_MS
);
394 TIME_FORMAT(TIME_SAMPLES
);
395 TIME_FORMAT(TIME_BYTES
);
396 TIME_FORMAT(TIME_SMPTE
);
397 TIME_FORMAT(TIME_MIDI
);
398 TIME_FORMAT(TIME_TICKS
);
401 sprintf(msg
, "Unknown(0x%04x)", type
);
405 const char * get_format_str(WORD format
)
408 #define WAVE_FORMAT(f) case f: return #f
410 WAVE_FORMAT(WAVE_FORMAT_PCM
);
411 WAVE_FORMAT(WAVE_FORMAT_ADPCM
);
412 WAVE_FORMAT(WAVE_FORMAT_IBM_CVSD
);
413 WAVE_FORMAT(WAVE_FORMAT_ALAW
);
414 WAVE_FORMAT(WAVE_FORMAT_MULAW
);
415 WAVE_FORMAT(WAVE_FORMAT_OKI_ADPCM
);
416 WAVE_FORMAT(WAVE_FORMAT_IMA_ADPCM
);
417 WAVE_FORMAT(WAVE_FORMAT_MEDIASPACE_ADPCM
);
418 WAVE_FORMAT(WAVE_FORMAT_SIERRA_ADPCM
);
419 WAVE_FORMAT(WAVE_FORMAT_G723_ADPCM
);
420 WAVE_FORMAT(WAVE_FORMAT_DIGISTD
);
421 WAVE_FORMAT(WAVE_FORMAT_DIGIFIX
);
422 WAVE_FORMAT(WAVE_FORMAT_DIALOGIC_OKI_ADPCM
);
423 WAVE_FORMAT(WAVE_FORMAT_YAMAHA_ADPCM
);
424 WAVE_FORMAT(WAVE_FORMAT_SONARC
);
425 WAVE_FORMAT(WAVE_FORMAT_DSPGROUP_TRUESPEECH
);
426 WAVE_FORMAT(WAVE_FORMAT_ECHOSC1
);
427 WAVE_FORMAT(WAVE_FORMAT_AUDIOFILE_AF36
);
428 WAVE_FORMAT(WAVE_FORMAT_APTX
);
429 WAVE_FORMAT(WAVE_FORMAT_AUDIOFILE_AF10
);
430 WAVE_FORMAT(WAVE_FORMAT_DOLBY_AC2
);
431 WAVE_FORMAT(WAVE_FORMAT_GSM610
);
432 WAVE_FORMAT(WAVE_FORMAT_ANTEX_ADPCME
);
433 WAVE_FORMAT(WAVE_FORMAT_CONTROL_RES_VQLPC
);
434 WAVE_FORMAT(WAVE_FORMAT_DIGIREAL
);
435 WAVE_FORMAT(WAVE_FORMAT_DIGIADPCM
);
436 WAVE_FORMAT(WAVE_FORMAT_CONTROL_RES_CR10
);
437 WAVE_FORMAT(WAVE_FORMAT_NMS_VBXADPCM
);
438 WAVE_FORMAT(WAVE_FORMAT_G721_ADPCM
);
439 WAVE_FORMAT(WAVE_FORMAT_MPEG
);
440 WAVE_FORMAT(WAVE_FORMAT_MPEGLAYER3
);
441 WAVE_FORMAT(WAVE_FORMAT_CREATIVE_ADPCM
);
442 WAVE_FORMAT(WAVE_FORMAT_CREATIVE_FASTSPEECH8
);
443 WAVE_FORMAT(WAVE_FORMAT_CREATIVE_FASTSPEECH10
);
444 WAVE_FORMAT(WAVE_FORMAT_FM_TOWNS_SND
);
445 WAVE_FORMAT(WAVE_FORMAT_OLIGSM
);
446 WAVE_FORMAT(WAVE_FORMAT_OLIADPCM
);
447 WAVE_FORMAT(WAVE_FORMAT_OLICELP
);
448 WAVE_FORMAT(WAVE_FORMAT_OLISBC
);
449 WAVE_FORMAT(WAVE_FORMAT_OLIOPR
);
450 WAVE_FORMAT(WAVE_FORMAT_DEVELOPMENT
);
451 WAVE_FORMAT(WAVE_FORMAT_EXTENSIBLE
);
454 sprintf(msg
, "Unknown(0x%04x)", format
);
458 DWORD
bytes_to_samples(DWORD bytes
, LPWAVEFORMATEX pwfx
)
460 return bytes
/ pwfx
->nBlockAlign
;
463 DWORD
bytes_to_ms(DWORD bytes
, LPWAVEFORMATEX pwfx
)
465 return bytes_to_samples(bytes
, pwfx
) * 1000 / pwfx
->nSamplesPerSec
;
468 DWORD
time_to_bytes(LPMMTIME mmtime
, LPWAVEFORMATEX pwfx
)
470 if (mmtime
->wType
== TIME_BYTES
)
472 else if (mmtime
->wType
== TIME_SAMPLES
)
473 return mmtime
->u
.sample
* pwfx
->nBlockAlign
;
474 else if (mmtime
->wType
== TIME_MS
)
475 return mmtime
->u
.ms
* pwfx
->nAvgBytesPerSec
/ 1000;
476 else if (mmtime
->wType
== TIME_SMPTE
)
477 return ((mmtime
->u
.smpte
.hour
* 60 * 60) +
478 (mmtime
->u
.smpte
.min
* 60) +
479 (mmtime
->u
.smpte
.sec
)) * pwfx
->nAvgBytesPerSec
+
480 mmtime
->u
.smpte
.frame
* pwfx
->nAvgBytesPerSec
/ 30;
482 trace("FIXME: time_to_bytes() type not supported\n");
486 static void check_position(int device
, HWAVEOUT wout
, DWORD bytes
,
487 LPWAVEFORMATEX pwfx
)
493 mmtime
.wType
= TIME_BYTES
;
494 rc
=waveOutGetPosition(wout
, &mmtime
, sizeof(mmtime
) - 1);
495 ok(rc
==MMSYSERR_ERROR
,
496 "waveOutGetPosition(%s): rc=%s\n",dev_name(device
),wave_out_error(rc
));
498 mmtime
.wType
= TIME_BYTES
;
499 rc
=waveOutGetPosition(wout
, &mmtime
, sizeof(mmtime
) + 1);
500 ok(rc
==MMSYSERR_NOERROR
,
501 "waveOutGetPosition(%s): rc=%s\n",dev_name(device
),wave_out_error(rc
));
502 if (mmtime
.wType
!= TIME_BYTES
&& winetest_debug
> 1)
503 trace("waveOutGetPosition(%s): TIME_BYTES not supported, returned %s\n",
504 dev_name(device
),wave_time_format(mmtime
.wType
));
505 returned
= time_to_bytes(&mmtime
, pwfx
);
506 ok(returned
== bytes
, "waveOutGetPosition(%s): returned %d bytes, "
507 "should be %d\n", dev_name(device
), returned
, bytes
);
509 mmtime
.wType
= TIME_SAMPLES
;
510 rc
=waveOutGetPosition(wout
, &mmtime
, sizeof(mmtime
));
511 ok(rc
==MMSYSERR_NOERROR
,
512 "waveOutGetPosition(%s): rc=%s\n",dev_name(device
),wave_out_error(rc
));
513 if (mmtime
.wType
!= TIME_SAMPLES
&& winetest_debug
> 1)
514 trace("waveOutGetPosition(%s): TIME_SAMPLES not supported, "
515 "returned %s\n",dev_name(device
),wave_time_format(mmtime
.wType
));
516 returned
= time_to_bytes(&mmtime
, pwfx
);
517 ok(returned
== bytes
, "waveOutGetPosition(%s): returned %d samples "
518 "(%d bytes), should be %d (%d bytes)\n", dev_name(device
),
519 bytes_to_samples(returned
, pwfx
), returned
,
520 bytes_to_samples(bytes
, pwfx
), bytes
);
522 mmtime
.wType
= TIME_MS
;
523 rc
=waveOutGetPosition(wout
, &mmtime
, sizeof(mmtime
));
524 ok(rc
==MMSYSERR_NOERROR
,
525 "waveOutGetPosition(%s): rc=%s\n",dev_name(device
),wave_out_error(rc
));
526 if (mmtime
.wType
!= TIME_MS
&& winetest_debug
> 1)
527 trace("waveOutGetPosition(%s): TIME_MS not supported, returned %s\n",
528 dev_name(device
), wave_time_format(mmtime
.wType
));
529 returned
= time_to_bytes(&mmtime
, pwfx
);
530 ok(returned
== bytes
, "waveOutGetPosition(%s): returned %d ms, "
531 "(%d bytes), should be %d (%d bytes)\n", dev_name(device
),
532 bytes_to_ms(returned
, pwfx
), returned
,
533 bytes_to_ms(bytes
, pwfx
), bytes
);
535 mmtime
.wType
= TIME_SMPTE
;
536 rc
=waveOutGetPosition(wout
, &mmtime
, sizeof(mmtime
));
537 ok(rc
==MMSYSERR_NOERROR
,
538 "waveOutGetPosition(%s): rc=%s\n",dev_name(device
),wave_out_error(rc
));
539 if (mmtime
.wType
!= TIME_SMPTE
&& winetest_debug
> 1)
540 trace("waveOutGetPosition(%s): TIME_SMPTE not supported, returned %s\n",
541 dev_name(device
),wave_time_format(mmtime
.wType
));
542 returned
= time_to_bytes(&mmtime
, pwfx
);
543 ok(returned
== bytes
, "waveOutGetPosition(%s): SMPTE test failed\n",
546 mmtime
.wType
= TIME_MIDI
;
547 rc
=waveOutGetPosition(wout
, &mmtime
, sizeof(mmtime
));
548 ok(rc
==MMSYSERR_NOERROR
,
549 "waveOutGetPosition(%s): rc=%s\n",dev_name(device
),wave_out_error(rc
));
550 if (mmtime
.wType
!= TIME_MIDI
&& winetest_debug
> 1)
551 trace("waveOutGetPosition(%s): TIME_MIDI not supported, returned %s\n",
552 dev_name(device
),wave_time_format(mmtime
.wType
));
553 returned
= time_to_bytes(&mmtime
, pwfx
);
554 ok(returned
== bytes
, "waveOutGetPosition(%s): MIDI test failed\n",
557 mmtime
.wType
= TIME_TICKS
;
558 rc
=waveOutGetPosition(wout
, &mmtime
, sizeof(mmtime
));
559 ok(rc
==MMSYSERR_NOERROR
,
560 "waveOutGetPosition(%s): rc=%s\n",dev_name(device
),wave_out_error(rc
));
561 if (mmtime
.wType
!= TIME_TICKS
&& winetest_debug
> 1)
562 trace("waveOutGetPosition(%s): TIME_TICKS not supported, returned %s\n",
563 dev_name(device
),wave_time_format(mmtime
.wType
));
564 returned
= time_to_bytes(&mmtime
, pwfx
);
565 ok(returned
== bytes
, "waveOutGetPosition(%s): TICKS test failed\n",
569 static void CALLBACK
callback_func(HWAVEOUT hwo
, UINT uMsg
,
570 DWORD_PTR dwInstance
,
571 DWORD dwParam1
, DWORD dwParam2
)
573 if(uMsg
== WOM_OPEN
|| uMsg
== WOM_CLOSE
)
574 ok(GetCurrentThreadId() == g_tid
, "Got different thread ID\n");
575 SetEvent((HANDLE
)dwInstance
);
578 static DWORD WINAPI
callback_thread(LPVOID lpParameter
)
582 PeekMessageW( &msg
, 0, 0, 0, PM_NOREMOVE
); /* make sure the thread has a message queue */
583 SetEvent(lpParameter
);
585 while (GetMessageA(&msg
, 0, 0, 0)) {
586 UINT message
= msg
.message
;
587 /* for some reason XP sends a WM_USER message before WOM_OPEN */
588 ok (message
== WOM_OPEN
|| message
== WOM_DONE
||
589 message
== WOM_CLOSE
|| message
== WM_USER
|| message
== WM_APP
,
590 "GetMessageA returned unexpected message: %u\n", message
);
591 if (message
== WOM_OPEN
|| message
== WOM_DONE
|| message
== WOM_CLOSE
)
592 SetEvent(lpParameter
);
593 else if (message
== WM_APP
) {
594 SetEvent(lpParameter
);
602 static void wave_out_test_deviceOut(int device
, double duration
, int headers
, int loops
,
603 WAVEFORMATEX
*pwfx
, DWORD format
, DWORD flags
, WAVEOUTCAPSA
*pcaps
, BOOL interactive
,
604 BOOL sine
, BOOL pause
)
607 HANDLE hevent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
611 WORD nChannels
= pwfx
->nChannels
;
612 WORD wBitsPerSample
= pwfx
->wBitsPerSample
;
613 DWORD nSamplesPerSec
= pwfx
->nSamplesPerSec
;
614 BOOL has_volume
= (pcaps
->dwSupport
& WAVECAPS_VOLUME
) != 0;
616 DWORD_PTR callback
= 0;
617 DWORD_PTR callback_instance
= 0;
625 if ((flags
& CALLBACK_TYPEMASK
) == CALLBACK_EVENT
) {
626 callback
= (DWORD_PTR
)hevent
;
627 callback_instance
= 0;
628 } else if ((flags
& CALLBACK_TYPEMASK
) == CALLBACK_FUNCTION
) {
629 callback
= (DWORD_PTR
)callback_func
;
630 callback_instance
= (DWORD_PTR
)hevent
;
631 } else if ((flags
& CALLBACK_TYPEMASK
) == CALLBACK_THREAD
) {
632 thread
= CreateThread(NULL
, 0, callback_thread
, hevent
, 0, &thread_id
);
634 /* make sure thread is running */
635 WaitForSingleObject(hevent
,10000);
636 callback
= thread_id
;
637 callback_instance
= 0;
639 trace("CreateThread() failed\n");
643 } else if ((flags
& CALLBACK_TYPEMASK
) == CALLBACK_WINDOW
) {
644 trace("CALLBACK_THREAD not implemented\n");
647 } else if (flags
& CALLBACK_TYPEMASK
) {
648 trace("Undefined callback type!\n");
652 trace("CALLBACK_NULL not implemented\n");
657 g_tid
= GetCurrentThreadId();
658 rc
=waveOutOpen(&wout
,device
,pwfx
,callback
,callback_instance
,flags
);
659 /* Note: Win9x doesn't know WAVE_FORMAT_DIRECT */
660 /* It is acceptable to fail on formats that are not specified to work */
661 ok(rc
==MMSYSERR_NOERROR
|| rc
==MMSYSERR_BADDEVICEID
||
662 rc
==MMSYSERR_NOTENABLED
|| rc
==MMSYSERR_NODRIVER
||
663 rc
==MMSYSERR_ALLOCATED
||
664 ((rc
==WAVERR_BADFORMAT
|| rc
==MMSYSERR_NOTSUPPORTED
) &&
665 (flags
& WAVE_FORMAT_DIRECT
) && !(pcaps
->dwFormats
& format
)) ||
666 ((rc
==WAVERR_BADFORMAT
|| rc
==MMSYSERR_NOTSUPPORTED
) &&
667 (!(flags
& WAVE_FORMAT_DIRECT
) || (flags
& WAVE_MAPPED
)) &&
668 !(pcaps
->dwFormats
& format
)) ||
669 (rc
==MMSYSERR_INVALFLAG
&& (flags
& WAVE_FORMAT_DIRECT
)),
670 "waveOutOpen(%s): format=%dx%2dx%d flags=%x(%s) rc=%s\n",
671 dev_name(device
),pwfx
->nSamplesPerSec
,pwfx
->wBitsPerSample
,
672 pwfx
->nChannels
,CALLBACK_EVENT
|flags
,
673 wave_open_flags(CALLBACK_EVENT
|flags
),wave_out_error(rc
));
674 if ((rc
==WAVERR_BADFORMAT
|| rc
==MMSYSERR_NOTSUPPORTED
) &&
675 (flags
& WAVE_FORMAT_DIRECT
) && (pcaps
->dwFormats
& format
))
676 trace(" Reason: The device lists this format as supported in its "
677 "capabilities but opening it failed.\n");
678 if ((rc
==WAVERR_BADFORMAT
|| rc
==MMSYSERR_NOTSUPPORTED
) &&
679 !(pcaps
->dwFormats
& format
))
680 trace("waveOutOpen(%s): format=%dx%2dx%d %s rc=%s failed but format "
681 "not supported so OK.\n", dev_name(device
), pwfx
->nSamplesPerSec
,
682 pwfx
->wBitsPerSample
,pwfx
->nChannels
,
683 flags
& WAVE_FORMAT_DIRECT
? "flags=WAVE_FORMAT_DIRECT" :
684 flags
& WAVE_MAPPED
? "flags=WAVE_MAPPED" : "", mmsys_error(rc
));
685 if (rc
!=MMSYSERR_NOERROR
)
688 rc
=WaitForSingleObject(hevent
,9000);
689 ok(rc
==WAIT_OBJECT_0
, "missing WOM_OPEN notification\n");
691 ok(pwfx
->nChannels
==nChannels
&&
692 pwfx
->wBitsPerSample
==wBitsPerSample
&&
693 pwfx
->nSamplesPerSec
==nSamplesPerSec
,
694 "got the wrong format: %dx%2dx%d instead of %dx%2dx%d\n",
695 pwfx
->nSamplesPerSec
, pwfx
->wBitsPerSample
,
696 pwfx
->nChannels
, nSamplesPerSec
, wBitsPerSample
, nChannels
);
698 frags
= HeapAlloc(GetProcessHeap(), 0, headers
* sizeof(WAVEHDR
));
701 buffer
=wave_generate_la(pwfx
,duration
/ (loops
+ 1),&length
);
703 buffer
=wave_generate_silence(pwfx
,duration
/ (loops
+ 1),&length
);
705 rc
=waveOutGetVolume(wout
,0);
706 ok(rc
==MMSYSERR_INVALPARAM
,"waveOutGetVolume(%s,0) expected "
707 "MMSYSERR_INVALPARAM, got %s\n", dev_name(device
),wave_out_error(rc
));
708 rc
=waveOutGetVolume(wout
,&volume
);
709 if (rc
== MMSYSERR_NOTSUPPORTED
) has_volume
= FALSE
;
710 ok(has_volume
? rc
==MMSYSERR_NOERROR
: rc
==MMSYSERR_NOTSUPPORTED
,
711 "waveOutGetVolume(%s): rc=%s\n",dev_name(device
),wave_out_error(rc
));
713 /* make sure fragment length is a multiple of block size */
714 frag_length
= ((length
/ headers
) / pwfx
->nBlockAlign
) * pwfx
->nBlockAlign
;
716 for (i
= 0; i
< headers
; i
++) {
717 frags
[i
].lpData
=buffer
+ (i
* frag_length
);
718 if (i
!= (headers
-1))
719 frags
[i
].dwBufferLength
=frag_length
;
721 /* use remainder of buffer for last fragment */
722 frags
[i
].dwBufferLength
=length
- (i
* frag_length
);
726 rc
=waveOutPrepareHeader(wout
, &frags
[i
], sizeof(frags
[0]));
727 ok(rc
==MMSYSERR_NOERROR
,
728 "waveOutPrepareHeader(%s): rc=%s\n",dev_name(device
),wave_out_error(rc
));
731 if (interactive
&& rc
==MMSYSERR_NOERROR
) {
732 trace("Playing %g second %s at %5dx%2dx%d %2d header%s %d loop%s %d bytes %s %s\n",duration
,
733 sine
? "440 Hz tone" : "silence", pwfx
->nSamplesPerSec
,
734 pwfx
->wBitsPerSample
,pwfx
->nChannels
, headers
, headers
> 1 ? "s": " ",
735 loops
, loops
== 1 ? " " : "s", length
* (loops
+ 1),
736 get_format_str(pwfx
->wFormatTag
),
737 wave_open_flags(flags
));
738 if (sine
&& has_volume
&& volume
== 0)
739 trace("*** Warning the sound is muted, you will not hear the test\n");
741 /* Check that the position is 0 at start */
742 check_position(device
, wout
, 0, pwfx
);
744 rc
=waveOutSetVolume(wout
,0x20002000);
745 ok(has_volume
? rc
==MMSYSERR_NOERROR
: rc
==MMSYSERR_NOTSUPPORTED
,
746 "waveOutSetVolume(%s): rc=%s\n",dev_name(device
),wave_out_error(rc
));
748 rc
=waveOutSetVolume(wout
,volume
);
749 ok(has_volume
? rc
==MMSYSERR_NOERROR
: rc
==MMSYSERR_NOTSUPPORTED
,
750 "waveOutSetVolume(%s): rc=%s\n",dev_name(device
),wave_out_error(rc
));
752 rc
=waveOutWrite(wout
, &frags
[0], sizeof(frags
[0]));
753 ok(rc
==MMSYSERR_NOERROR
,"waveOutWrite(%s): rc=%s\n",
754 dev_name(device
),wave_out_error(rc
));
756 ok(frags
[0].dwFlags
==(WHDR_PREPARED
|WHDR_INQUEUE
),
757 "WHDR_INQUEUE WHDR_PREPARED expected, got= %s\n",
758 wave_header_flags(frags
[0].dwFlags
));
760 rc
=waveOutWrite(wout
, &frags
[0], sizeof(frags
[0]));
761 ok(rc
==WAVERR_STILLPLAYING
,
762 "waveOutWrite(%s): WAVE_STILLPLAYING expected, got %s\n",
763 dev_name(device
),wave_out_error(rc
));
765 ok(frags
[0].dwFlags
==(WHDR_PREPARED
|WHDR_INQUEUE
),
766 "WHDR_INQUEUE WHDR_PREPARED expected, got %s\n",
767 wave_header_flags(frags
[0].dwFlags
));
769 if (headers
== 1 && loops
== 0 && pause
) {
770 paused
= duration
/ 2;
771 Sleep(paused
* 1000);
772 rc
=waveOutPause(wout
);
773 ok(rc
==MMSYSERR_NOERROR
,"waveOutPause(%s): rc=%s\n",
774 dev_name(device
),wave_out_error(rc
));
775 trace("pausing for %g seconds\n", paused
);
776 Sleep(paused
* 1000);
777 rc
=waveOutRestart(wout
);
778 ok(rc
==MMSYSERR_NOERROR
,"waveOutRestart(%s): rc=%s\n",
779 dev_name(device
),wave_out_error(rc
));
782 for (j
= 0; j
<= loops
; j
++) {
783 for (i
= 0; i
< headers
; i
++) {
784 /* don't do last one */
785 if (!((j
== loops
) && (i
== (headers
- 1)))) {
787 frags
[(i
+1) % headers
].dwFlags
= WHDR_PREPARED
;
788 rc
=waveOutWrite(wout
, &frags
[(i
+1) % headers
], sizeof(frags
[0]));
789 ok(rc
==MMSYSERR_NOERROR
,"waveOutWrite(%s, header[%d]): rc=%s\n",
790 dev_name(device
),(i
+1)%headers
,wave_out_error(rc
));
792 rc
=WaitForSingleObject(hevent
,8000);
793 ok(rc
==WAIT_OBJECT_0
, "missing WOM_DONE notification\n");
797 for (i
= 0; i
< headers
; i
++) {
798 ok(frags
[i
].dwFlags
==(WHDR_DONE
|WHDR_PREPARED
) ||
799 broken((flags
& CALLBACK_TYPEMASK
)==CALLBACK_EVENT
&&
800 frags
[i
].dwFlags
==(WHDR_DONE
|WHDR_PREPARED
|0x1000)), /* < NT4 */
801 "(%02d) WHDR_DONE WHDR_PREPARED expected, got %s\n",
802 i
, wave_header_flags(frags
[i
].dwFlags
));
804 check_position(device
, wout
, length
* (loops
+ 1), pwfx
);
807 for (i
= 0; i
< headers
; i
++) {
808 rc
=waveOutUnprepareHeader(wout
, &frags
[i
], sizeof(frags
[0]));
809 ok(rc
==MMSYSERR_NOERROR
,
810 "waveOutUnprepareHeader(%s): rc=%s\n",dev_name(device
),
814 ok(frags
[0].dwFlags
==(interactive
? WHDR_DONE
: 0), "dwFlags(%d)=%x\n",device
,frags
[0].dwFlags
);
816 frags
[0].dwFlags
|= WHDR_DONE
;
817 rc
=waveOutUnprepareHeader(wout
, &frags
[0], sizeof(frags
[0]));
818 ok(rc
==MMSYSERR_NOERROR
, "waveOutUnprepareHeader(%d): rc=%s\n",device
,wave_out_error(rc
));
819 ok(frags
[0].dwFlags
==WHDR_DONE
, "dwFlags(%d)=%x\n",device
,frags
[0].dwFlags
);
821 frags
[0].dwFlags
|= WHDR_INQUEUE
;
822 rc
=waveOutPrepareHeader(wout
, &frags
[0], sizeof(frags
[0]));
823 ok(rc
==MMSYSERR_NOERROR
, "waveOutPrepareHeader(%d): rc=%s\n",device
,wave_out_error(rc
));
824 ok(frags
[0].dwFlags
==WHDR_PREPARED
, "dwFlags(%d)=%x\n",device
,frags
[0].dwFlags
);
826 frags
[0].dwFlags
|= WHDR_INQUEUE
;
827 rc
=waveOutPrepareHeader(wout
, &frags
[0], sizeof(frags
[0]));
828 ok(rc
==MMSYSERR_NOERROR
, "waveOutPrepareHeader(%d): rc=%s\n",device
,wave_out_error(rc
));
829 ok(frags
[0].dwFlags
==(WHDR_PREPARED
|WHDR_INQUEUE
), "dwFlags(%d)=%x\n",device
,frags
[0].dwFlags
);
831 frags
[0].dwFlags
&= ~(WHDR_INQUEUE
|WHDR_DONE
);
832 rc
=waveOutUnprepareHeader(wout
, &frags
[0], sizeof(frags
[0]));
833 ok(rc
==MMSYSERR_NOERROR
, "waveOutUnprepareHeader(%d): rc=%s\n",device
,wave_out_error(rc
));
834 ok(frags
[0].dwFlags
==0, "dwFlags(%d)=%x\n",device
,frags
[0].dwFlags
);
836 rc
=waveOutClose(wout
);
837 ok(rc
==MMSYSERR_NOERROR
,"waveOutClose(%s): rc=%s\n",dev_name(device
),
839 if (rc
==WAVERR_STILLPLAYING
) {
840 /* waveOutReset ought to return all buffers s.t. waveOutClose succeeds */
841 rc
=waveOutReset(wout
);
842 ok(rc
==MMSYSERR_NOERROR
,"waveOutReset(%s): rc=%s\n",dev_name(device
),
845 for (i
= 0; i
< headers
; i
++) {
846 rc
=waveOutUnprepareHeader(wout
, &frags
[i
], sizeof(frags
[0]));
847 ok(rc
==MMSYSERR_NOERROR
,
848 "waveOutUnprepareHeader(%s): rc=%s\n",dev_name(device
),
851 rc
=waveOutClose(wout
);
852 ok(rc
==MMSYSERR_NOERROR
,"waveOutClose(%s): rc=%s\n",dev_name(device
),
855 rc
=WaitForSingleObject(hevent
,1500);
856 ok(rc
==WAIT_OBJECT_0
, "missing WOM_CLOSE notification\n");
858 wout
= (HWAVEOUT
)0xdeadf00d;
859 rc
=waveOutOpen(&wout
,device
,pwfx
,callback
,callback_instance
,flags
|WAVE_FORMAT_QUERY
);
860 ok(rc
==MMSYSERR_NOERROR
, "WAVE_FORMAT_QUERY(%s): rc=%s\n",dev_name(device
),
862 ok(wout
==(HWAVEOUT
)0xdeadf00d, "WAVE_FORMAT_QUERY handle %p\n", wout
);
864 rc
=WaitForSingleObject(hevent
,20);
865 ok(rc
==WAIT_TIMEOUT
, "Notification from %s rc=%x\n",
866 wave_open_flags(flags
|WAVE_FORMAT_QUERY
),rc
);
868 HeapFree(GetProcessHeap(), 0, buffer
);
870 if ((flags
& CALLBACK_TYPEMASK
) == CALLBACK_THREAD
) {
871 PostThreadMessageW(thread_id
, WM_APP
, 0, 0);
872 WaitForSingleObject(hevent
,10000);
875 HeapFree(GetProcessHeap(), 0, frags
);
878 static void wave_out_test_device(UINT_PTR device
)
883 WAVEFORMATEXTENSIBLE wfex
;
884 IMAADPCMWAVEFORMAT wfa
;
893 SYSTEM_INFO sSysInfo
;
897 GetSystemInfo(&sSysInfo
);
898 dwPageSize
= sSysInfo
.dwPageSize
;
900 rc
=waveOutGetDevCapsA(device
,&capsA
,sizeof(capsA
));
901 ok(rc
==MMSYSERR_NOERROR
|| rc
==MMSYSERR_BADDEVICEID
||
902 rc
==MMSYSERR_NODRIVER
,
903 "waveOutGetDevCapsA(%s): failed to get capabilities: rc=%s\n",
904 dev_name(device
),wave_out_error(rc
));
905 if (rc
==MMSYSERR_BADDEVICEID
|| rc
==MMSYSERR_NODRIVER
)
908 rc
=waveOutGetDevCapsW(device
,&capsW
,sizeof(capsW
));
909 ok(rc
==MMSYSERR_NOERROR
|| rc
==MMSYSERR_NOTSUPPORTED
,
910 "waveOutGetDevCapsW(%s): MMSYSERR_NOERROR or MMSYSERR_NOTSUPPORTED "
911 "expected, got %s\n",dev_name(device
),wave_out_error(rc
));
913 rc
=waveOutGetDevCapsA(device
,0,sizeof(capsA
));
914 ok(rc
==MMSYSERR_INVALPARAM
,
915 "waveOutGetDevCapsA(%s): MMSYSERR_INVALPARAM expected, "
916 "got %s\n",dev_name(device
),wave_out_error(rc
));
918 rc
=waveOutGetDevCapsW(device
,0,sizeof(capsW
));
919 ok(rc
==MMSYSERR_INVALPARAM
|| rc
==MMSYSERR_NOTSUPPORTED
,
920 "waveOutGetDevCapsW(%s): MMSYSERR_INVALPARAM or MMSYSERR_NOTSUPPORTED "
921 "expected, got %s\n",dev_name(device
),wave_out_error(rc
));
925 /* FIXME: this works on windows but crashes wine */
926 rc
=waveOutGetDevCapsA(device
,(LPWAVEOUTCAPSA
)1,sizeof(capsA
));
927 ok(rc
==MMSYSERR_INVALPARAM
,
928 "waveOutGetDevCapsA(%s): MMSYSERR_INVALPARAM expected, got %s\n",
929 dev_name(device
),wave_out_error(rc
));
931 rc
=waveOutGetDevCapsW(device
,(LPWAVEOUTCAPSW
)1,sizeof(capsW
));
932 ok(rc
==MMSYSERR_INVALPARAM
|| rc
==MMSYSERR_NOTSUPPORTED
,
933 "waveOutGetDevCapsW(%s): MMSYSERR_INVALPARAM or MMSYSERR_NOTSUPPORTED "
934 "expected, got %s\n",dev_name(device
),wave_out_error(rc
));
937 rc
=waveOutGetDevCapsA(device
,&capsA
,4);
938 ok(rc
==MMSYSERR_NOERROR
|| rc
==MMSYSERR_INVALPARAM
,
939 "waveOutGetDevCapsA(%s): MMSYSERR_NOERROR or MMSYSERR_INVALPARAM "
940 "expected, got %s\n", dev_name(device
),wave_out_error(rc
));
942 rc
=waveOutGetDevCapsW(device
,&capsW
,4);
943 ok(rc
==MMSYSERR_NOERROR
|| rc
==MMSYSERR_NOTSUPPORTED
||
944 rc
==MMSYSERR_INVALPARAM
, /* Vista, W2K8 */
945 "waveOutGetDevCapsW(%s): unexpected return value %s\n",
946 dev_name(device
),wave_out_error(rc
));
948 rc
=waveOutMessage((HWAVEOUT
)device
, DRV_QUERYMAPPABLE
, 0, 0);
949 ok(rc
==MMSYSERR_NOERROR
|| rc
==MMSYSERR_NOTSUPPORTED
,
950 "DRV_QUERYMAPPABLE(%s): unexpected return value %s\n",
951 dev_name(device
),wave_out_error(rc
));
954 rc
=waveOutMessage((HWAVEOUT
)device
, DRV_QUERYDEVICEINTERFACESIZE
,
955 (DWORD_PTR
)&size
, 0);
956 ok(rc
==MMSYSERR_NOERROR
|| broken(rc
==MMSYSERR_INVALPARAM
||
957 rc
==MMSYSERR_NOTSUPPORTED
),
958 "waveOutMessage(%s): failed to get interface size, rc=%s\n",
959 dev_name(device
),wave_out_error(rc
));
960 if (rc
==MMSYSERR_NOERROR
) {
961 nameW
= HeapAlloc(GetProcessHeap(), 0, size
);
962 rc
=waveOutMessage((HWAVEOUT
)device
, DRV_QUERYDEVICEINTERFACE
,
963 (DWORD_PTR
)nameW
, size
);
964 ok(rc
==MMSYSERR_NOERROR
,"waveOutMessage(%s): failed to get interface "
965 "name, rc=%s\n",dev_name(device
),wave_out_error(rc
));
966 ok(lstrlenW(nameW
)+1==size
/sizeof(WCHAR
),"got an incorrect size %d\n",size
);
967 if (rc
==MMSYSERR_NOERROR
) {
968 nameA
= HeapAlloc(GetProcessHeap(), 0, size
/sizeof(WCHAR
));
969 WideCharToMultiByte(CP_ACP
, 0, nameW
, size
/sizeof(WCHAR
), nameA
,
970 size
/sizeof(WCHAR
), NULL
, NULL
);
972 HeapFree(GetProcessHeap(), 0, nameW
);
974 else if (rc
==MMSYSERR_NOTSUPPORTED
) {
975 nameA
=HeapAlloc(GetProcessHeap(), 0, sizeof("not supported"));
976 strcpy(nameA
, "not supported");
979 rc
=waveOutGetDevCapsA(device
,&capsA
,sizeof(capsA
));
980 ok(rc
==MMSYSERR_NOERROR
,
981 "waveOutGetDevCapsA(%s): MMSYSERR_NOERROR expected, got %s\n",
982 dev_name(device
),wave_out_error(rc
));
983 if (rc
!=MMSYSERR_NOERROR
)
986 trace(" %s: \"%s\" (%s) %d.%d (%d:%d)\n",dev_name(device
),capsA
.szPname
,
987 (nameA
?nameA
:"failed"),capsA
.vDriverVersion
>> 8,
988 capsA
.vDriverVersion
& 0xff, capsA
.wMid
,capsA
.wPid
);
989 trace(" channels=%d formats=%05x support=%04x\n",
990 capsA
.wChannels
,capsA
.dwFormats
,capsA
.dwSupport
);
991 trace(" %s\n",wave_out_caps(capsA
.dwSupport
));
992 HeapFree(GetProcessHeap(), 0, nameA
);
994 if (winetest_interactive
&& (device
!= WAVE_MAPPER
))
996 trace("Playing a 5 seconds reference tone.\n");
997 trace("All subsequent tones should be identical to this one.\n");
998 trace("Listen for stutter, changes in pitch, volume, etc.\n");
999 format
.wFormatTag
=WAVE_FORMAT_PCM
;
1001 format
.wBitsPerSample
=8;
1002 format
.nSamplesPerSec
=22050;
1003 format
.nBlockAlign
=format
.nChannels
*format
.wBitsPerSample
/8;
1004 format
.nAvgBytesPerSec
=format
.nSamplesPerSec
*format
.nBlockAlign
;
1007 wave_out_test_deviceOut(device
,5.0,1,0,&format
,WAVE_FORMAT_2M08
,
1008 CALLBACK_EVENT
,&capsA
,TRUE
,TRUE
,FALSE
);
1009 wave_out_test_deviceOut(device
,5.0,1,0,&format
,WAVE_FORMAT_2M08
,
1010 CALLBACK_FUNCTION
,&capsA
,TRUE
,TRUE
,FALSE
);
1011 wave_out_test_deviceOut(device
,5.0,1,0,&format
,WAVE_FORMAT_2M08
,
1012 CALLBACK_THREAD
,&capsA
,TRUE
,TRUE
,FALSE
);
1014 wave_out_test_deviceOut(device
,5.0,10,0,&format
,WAVE_FORMAT_2M08
,
1015 CALLBACK_EVENT
,&capsA
,TRUE
,TRUE
,FALSE
);
1016 wave_out_test_deviceOut(device
,5.0,5,1,&format
,WAVE_FORMAT_2M08
,
1017 CALLBACK_EVENT
,&capsA
,TRUE
,TRUE
,FALSE
);
1019 format
.wFormatTag
=WAVE_FORMAT_PCM
;
1021 format
.wBitsPerSample
=8;
1022 format
.nSamplesPerSec
=22050;
1023 format
.nBlockAlign
=format
.nChannels
*format
.wBitsPerSample
/8;
1024 format
.nAvgBytesPerSec
=format
.nSamplesPerSec
*format
.nBlockAlign
;
1026 wave_out_test_deviceOut(device
,0.6,1,0,&format
,WAVE_FORMAT_2M08
,
1027 CALLBACK_EVENT
,&capsA
,TRUE
,FALSE
,FALSE
);
1028 wave_out_test_deviceOut(device
,0.6,1,0,&format
,WAVE_FORMAT_2M08
,
1029 CALLBACK_EVENT
,&capsA
,TRUE
,FALSE
,TRUE
);
1030 wave_out_test_deviceOut(device
,0.6,1,0,&format
,WAVE_FORMAT_2M08
,
1031 CALLBACK_FUNCTION
,&capsA
,TRUE
,FALSE
,FALSE
);
1032 wave_out_test_deviceOut(device
,0.6,1,0,&format
,WAVE_FORMAT_2M08
,
1033 CALLBACK_FUNCTION
,&capsA
,TRUE
,FALSE
,TRUE
);
1034 wave_out_test_deviceOut(device
,0.6,1,0,&format
,WAVE_FORMAT_2M08
,
1035 CALLBACK_THREAD
,&capsA
,TRUE
,FALSE
,FALSE
);
1036 wave_out_test_deviceOut(device
,0.6,1,0,&format
,WAVE_FORMAT_2M08
,
1037 CALLBACK_THREAD
,&capsA
,TRUE
,FALSE
,TRUE
);
1039 wave_out_test_deviceOut(device
,0.8,10,0,&format
,WAVE_FORMAT_2M08
,
1040 CALLBACK_EVENT
,&capsA
,TRUE
,FALSE
,FALSE
);
1041 wave_out_test_deviceOut(device
,1.0,5,1,&format
,WAVE_FORMAT_2M08
,
1042 CALLBACK_EVENT
,&capsA
,TRUE
,FALSE
,FALSE
);
1045 for (f
=0;f
<NB_WIN_FORMATS
;f
++) {
1046 format
.wFormatTag
=WAVE_FORMAT_PCM
;
1047 format
.nChannels
=win_formats
[f
][3];
1048 format
.wBitsPerSample
=win_formats
[f
][2];
1049 format
.nSamplesPerSec
=win_formats
[f
][1];
1050 format
.nBlockAlign
=format
.nChannels
*format
.wBitsPerSample
/8;
1051 format
.nAvgBytesPerSec
=format
.nSamplesPerSec
*format
.nBlockAlign
;
1053 wave_out_test_deviceOut(device
,1.0,1,0,&format
,win_formats
[f
][0],
1054 CALLBACK_EVENT
,&capsA
,winetest_interactive
,
1056 wave_out_test_deviceOut(device
,1.0,1,0,&format
,win_formats
[f
][0],
1057 CALLBACK_FUNCTION
,&capsA
,winetest_interactive
,
1059 wave_out_test_deviceOut(device
,1.0,1,0,&format
,win_formats
[f
][0],
1060 CALLBACK_THREAD
,&capsA
,winetest_interactive
,
1063 wave_out_test_deviceOut(device
,1.0,10,0,&format
,win_formats
[f
][0],
1064 CALLBACK_EVENT
,&capsA
,winetest_interactive
,
1066 wave_out_test_deviceOut(device
,1.0,5,1,&format
,win_formats
[f
][0],
1067 CALLBACK_EVENT
,&capsA
,winetest_interactive
,
1070 if (winetest_interactive
) {
1071 wave_out_test_deviceOut(device
,1.0,1,0,&format
,win_formats
[f
][0],
1072 CALLBACK_EVENT
,&capsA
,winetest_interactive
,
1074 wave_out_test_deviceOut(device
,1.0,1,0,&format
,win_formats
[f
][0],
1075 CALLBACK_FUNCTION
,&capsA
,winetest_interactive
,
1077 wave_out_test_deviceOut(device
,1.0,1,0,&format
,win_formats
[f
][0],
1078 CALLBACK_THREAD
,&capsA
,winetest_interactive
,
1081 wave_out_test_deviceOut(device
,1.0,10,0,&format
,win_formats
[f
][0],
1082 CALLBACK_EVENT
,&capsA
,winetest_interactive
,
1084 wave_out_test_deviceOut(device
,1.0,5,1,&format
,win_formats
[f
][0],
1085 CALLBACK_EVENT
,&capsA
,winetest_interactive
,
1088 if (device
!= WAVE_MAPPER
)
1090 wave_out_test_deviceOut(device
,1.0,1,0,&format
,win_formats
[f
][0],
1091 CALLBACK_EVENT
|WAVE_FORMAT_DIRECT
,&capsA
,
1092 winetest_interactive
,TRUE
,FALSE
);
1093 wave_out_test_deviceOut(device
,1.0,1,0,&format
,win_formats
[f
][0],
1094 CALLBACK_EVENT
|WAVE_MAPPED
,&capsA
,
1095 winetest_interactive
,TRUE
,FALSE
);
1096 wave_out_test_deviceOut(device
,1.0,1,0,&format
,win_formats
[f
][0],
1097 CALLBACK_FUNCTION
|WAVE_FORMAT_DIRECT
,&capsA
,
1098 winetest_interactive
,TRUE
,FALSE
);
1099 wave_out_test_deviceOut(device
,1.0,1,0,&format
,win_formats
[f
][0],
1100 CALLBACK_FUNCTION
|WAVE_MAPPED
,&capsA
,
1101 winetest_interactive
,TRUE
,FALSE
);
1102 wave_out_test_deviceOut(device
,1.0,1,0,&format
,win_formats
[f
][0],
1103 CALLBACK_THREAD
|WAVE_FORMAT_DIRECT
,&capsA
,
1104 winetest_interactive
,TRUE
,FALSE
);
1105 wave_out_test_deviceOut(device
,1.0,1,0,&format
,win_formats
[f
][0],
1106 CALLBACK_THREAD
|WAVE_MAPPED
,&capsA
,
1107 winetest_interactive
,TRUE
,FALSE
);
1109 wave_out_test_deviceOut(device
,1.0,10,0,&format
,win_formats
[f
][0],
1110 CALLBACK_EVENT
|WAVE_FORMAT_DIRECT
,&capsA
,
1111 winetest_interactive
,TRUE
,FALSE
);
1112 wave_out_test_deviceOut(device
,1.0,5,1,&format
,win_formats
[f
][0],
1113 CALLBACK_EVENT
|WAVE_FORMAT_DIRECT
,&capsA
,
1114 winetest_interactive
,TRUE
,FALSE
);
1118 /* Try a PCMWAVEFORMAT aligned next to an unaccessible page for bounds
1120 twoPages
= VirtualAlloc(NULL
, 2 * dwPageSize
, MEM_RESERVE
| MEM_COMMIT
,
1122 ok(twoPages
!=NULL
,"Failed to allocate 2 pages of memory\n");
1124 res
= VirtualProtect(twoPages
+ dwPageSize
, dwPageSize
, PAGE_NOACCESS
,
1126 ok(res
, "Failed to set memory access on second page\n");
1128 LPWAVEFORMATEX pwfx
= (LPWAVEFORMATEX
)(twoPages
+ dwPageSize
-
1129 sizeof(PCMWAVEFORMAT
));
1130 pwfx
->wFormatTag
=WAVE_FORMAT_PCM
;
1132 pwfx
->wBitsPerSample
=8;
1133 pwfx
->nSamplesPerSec
=22050;
1134 pwfx
->nBlockAlign
=pwfx
->nChannels
*pwfx
->wBitsPerSample
/8;
1135 pwfx
->nAvgBytesPerSec
=pwfx
->nSamplesPerSec
*pwfx
->nBlockAlign
;
1136 wave_out_test_deviceOut(device
,1.0,1,0,pwfx
,WAVE_FORMAT_2M08
,
1137 CALLBACK_EVENT
,&capsA
,winetest_interactive
,
1139 wave_out_test_deviceOut(device
,1.0,10,0,pwfx
,WAVE_FORMAT_2M08
,
1140 CALLBACK_EVENT
,&capsA
,winetest_interactive
,
1142 wave_out_test_deviceOut(device
,1.0,5,1,pwfx
,WAVE_FORMAT_2M08
,
1143 CALLBACK_EVENT
,&capsA
,winetest_interactive
,
1145 if (device
!= WAVE_MAPPER
)
1147 wave_out_test_deviceOut(device
,1.0,1,0,pwfx
,WAVE_FORMAT_2M08
,
1148 CALLBACK_EVENT
|WAVE_FORMAT_DIRECT
,
1149 &capsA
,winetest_interactive
,TRUE
,FALSE
);
1150 wave_out_test_deviceOut(device
,1.0,1,0,pwfx
,WAVE_FORMAT_2M08
,
1151 CALLBACK_EVENT
|WAVE_MAPPED
,&capsA
,
1152 winetest_interactive
,TRUE
,FALSE
);
1153 wave_out_test_deviceOut(device
,1.0,10,0,pwfx
,WAVE_FORMAT_2M08
,
1154 CALLBACK_EVENT
|WAVE_FORMAT_DIRECT
,
1155 &capsA
,winetest_interactive
,TRUE
,FALSE
);
1156 wave_out_test_deviceOut(device
,1.0,10,0,pwfx
,WAVE_FORMAT_2M08
,
1157 CALLBACK_EVENT
|WAVE_MAPPED
,&capsA
,
1158 winetest_interactive
,TRUE
,FALSE
);
1159 wave_out_test_deviceOut(device
,1.0,5,1,pwfx
,WAVE_FORMAT_2M08
,
1160 CALLBACK_EVENT
|WAVE_FORMAT_DIRECT
,
1161 &capsA
,winetest_interactive
,TRUE
,FALSE
);
1162 wave_out_test_deviceOut(device
,1.0,5,1,pwfx
,WAVE_FORMAT_2M08
,
1163 CALLBACK_EVENT
|WAVE_MAPPED
,&capsA
,
1164 winetest_interactive
,TRUE
,FALSE
);
1167 VirtualFree(twoPages
, 0, MEM_RELEASE
);
1170 /* try some non PCM formats */
1171 format
.wFormatTag
=WAVE_FORMAT_MULAW
;
1173 format
.wBitsPerSample
=8;
1174 format
.nSamplesPerSec
=8000;
1175 format
.nBlockAlign
=format
.nChannels
*format
.wBitsPerSample
/8;
1176 format
.nAvgBytesPerSec
=format
.nSamplesPerSec
*format
.nBlockAlign
;
1178 rc
=waveOutOpen(&wout
,device
,&format
,0,0,CALLBACK_NULL
|WAVE_FORMAT_DIRECT
);
1179 ok(rc
==MMSYSERR_NOERROR
||rc
==WAVERR_BADFORMAT
||
1180 rc
==MMSYSERR_INVALFLAG
|| rc
==MMSYSERR_INVALPARAM
,
1181 "waveOutOpen(%s): returned %s\n",dev_name(device
),wave_out_error(rc
));
1182 if (rc
==MMSYSERR_NOERROR
) {
1184 wave_out_test_deviceOut(device
,1.0,1,0,&format
,0,CALLBACK_EVENT
,
1185 &capsA
,winetest_interactive
,TRUE
,FALSE
);
1186 wave_out_test_deviceOut(device
,1.0,10,0,&format
,0,CALLBACK_EVENT
,
1187 &capsA
,winetest_interactive
,TRUE
,FALSE
);
1188 wave_out_test_deviceOut(device
,1.0,5,1,&format
,0,CALLBACK_EVENT
,
1189 &capsA
,winetest_interactive
,TRUE
,FALSE
);
1193 trace("waveOutOpen(%s): WAVE_FORMAT_MULAW not supported\n",
1196 query_rc
= waveOutOpen(NULL
, device
, &format
, 0, 0, CALLBACK_NULL
| WAVE_FORMAT_QUERY
);
1197 ok(query_rc
==MMSYSERR_NOERROR
|| query_rc
==WAVERR_BADFORMAT
|| query_rc
==MMSYSERR_INVALPARAM
,
1198 "waveOutOpen(%s): returned %s\n",dev_name(device
),wave_out_error(rc
));
1200 rc
= waveOutOpen(&wout
, device
, &format
, 0, 0, CALLBACK_NULL
);
1202 "waveOutOpen(%s): returned different from query: %s\n",dev_name(device
),wave_out_error(rc
));
1203 if(rc
== MMSYSERR_NOERROR
)
1207 wfa
.wfx
.wFormatTag
=WAVE_FORMAT_IMA_ADPCM
;
1208 wfa
.wfx
.nChannels
=1;
1209 wfa
.wfx
.nSamplesPerSec
=11025;
1210 wfa
.wfx
.nAvgBytesPerSec
=5588;
1211 wfa
.wfx
.nBlockAlign
=256;
1212 wfa
.wfx
.wBitsPerSample
=4; /* see imaadp32.c */
1214 wfa
.wSamplesPerBlock
=505;
1215 rc
=waveOutOpen(&wout
,device
,&wfa
.wfx
,0,0,CALLBACK_NULL
|WAVE_FORMAT_DIRECT
);
1216 ok(rc
==MMSYSERR_NOERROR
||rc
==WAVERR_BADFORMAT
||
1217 rc
==MMSYSERR_INVALFLAG
|| rc
==MMSYSERR_INVALPARAM
,
1218 "waveOutOpen(%s): returned %s\n",dev_name(device
),wave_out_error(rc
));
1219 if (rc
==MMSYSERR_NOERROR
) {
1221 /* TODO: teach wave_generate_* ADPCM
1222 wave_out_test_deviceOut(device,1.0,1,0,&wfa.wfx,0,CALLBACK_EVENT,
1223 &capsA,winetest_interactive,TRUE,FALSE);
1224 wave_out_test_deviceOut(device,1.0,10,0,&wfa.wfx,0,CALLBACK_EVENT,
1225 &capsA,winetest_interactive,TRUE,FALSE);
1226 wave_out_test_deviceOut(device,1.0,5,1,&wfa.wfx,0,CALLBACK_EVENT,
1227 &capsA,winetest_interactive,TRUE,FALSE);
1230 trace("waveOutOpen(%s): WAVE_FORMAT_IMA_ADPCM not supported\n",
1233 /* test if WAVEFORMATEXTENSIBLE supported */
1234 wfex
.Format
.wFormatTag
=WAVE_FORMAT_EXTENSIBLE
;
1235 wfex
.Format
.nChannels
=2;
1236 wfex
.Format
.wBitsPerSample
=16;
1237 wfex
.Format
.nSamplesPerSec
=22050;
1238 wfex
.Format
.nBlockAlign
=wfex
.Format
.nChannels
*wfex
.Format
.wBitsPerSample
/8;
1239 wfex
.Format
.nAvgBytesPerSec
=wfex
.Format
.nSamplesPerSec
*
1240 wfex
.Format
.nBlockAlign
;
1241 wfex
.Format
.cbSize
=22;
1242 wfex
.Samples
.wValidBitsPerSample
=wfex
.Format
.wBitsPerSample
;
1243 wfex
.dwChannelMask
=SPEAKER_ALL
;
1244 wfex
.SubFormat
=KSDATAFORMAT_SUBTYPE_PCM
;
1245 rc
=waveOutOpen(&wout
,device
,&wfex
.Format
,0,0,
1246 CALLBACK_NULL
|WAVE_FORMAT_DIRECT
);
1247 ok(rc
==MMSYSERR_NOERROR
|| rc
==WAVERR_BADFORMAT
||
1248 rc
==MMSYSERR_INVALFLAG
|| rc
==MMSYSERR_INVALPARAM
,
1249 "waveOutOpen(%s): returned %s\n",dev_name(device
),wave_out_error(rc
));
1250 if (rc
==MMSYSERR_NOERROR
) {
1252 wave_out_test_deviceOut(device
,1.0,1,0,&wfex
.Format
,WAVE_FORMAT_2M16
,
1253 CALLBACK_EVENT
,&capsA
,winetest_interactive
,
1255 wave_out_test_deviceOut(device
,1.0,10,0,&wfex
.Format
,WAVE_FORMAT_2M16
,
1256 CALLBACK_EVENT
,&capsA
,winetest_interactive
,
1258 wave_out_test_deviceOut(device
,1.0,5,1,&wfex
.Format
,WAVE_FORMAT_2M16
,
1259 CALLBACK_EVENT
,&capsA
,winetest_interactive
,
1262 trace("waveOutOpen(%s): WAVE_FORMAT_EXTENSIBLE not supported\n",
1265 /* test if 4 channels supported */
1266 wfex
.Format
.wFormatTag
=WAVE_FORMAT_EXTENSIBLE
;
1267 wfex
.Format
.nChannels
=4;
1268 wfex
.Format
.wBitsPerSample
=16;
1269 wfex
.Format
.nSamplesPerSec
=22050;
1270 wfex
.Format
.nBlockAlign
=wfex
.Format
.nChannels
*wfex
.Format
.wBitsPerSample
/8;
1271 wfex
.Format
.nAvgBytesPerSec
=wfex
.Format
.nSamplesPerSec
*
1272 wfex
.Format
.nBlockAlign
;
1273 wfex
.Format
.cbSize
=22;
1274 wfex
.Samples
.wValidBitsPerSample
=wfex
.Format
.wBitsPerSample
;
1275 wfex
.dwChannelMask
=SPEAKER_ALL
;
1276 wfex
.SubFormat
=KSDATAFORMAT_SUBTYPE_PCM
;
1277 rc
=waveOutOpen(&wout
,device
,&wfex
.Format
,0,0,
1278 CALLBACK_NULL
|WAVE_FORMAT_DIRECT
);
1279 ok(rc
==MMSYSERR_NOERROR
|| rc
==WAVERR_BADFORMAT
||
1280 rc
==MMSYSERR_INVALFLAG
|| rc
==MMSYSERR_INVALPARAM
,
1281 "waveOutOpen(%s): returned %s\n",dev_name(device
),wave_out_error(rc
));
1282 if (rc
==MMSYSERR_NOERROR
) {
1284 wave_out_test_deviceOut(device
,1.0,1,0,&wfex
.Format
,0,CALLBACK_EVENT
,
1285 &capsA
,winetest_interactive
,TRUE
,FALSE
);
1286 wave_out_test_deviceOut(device
,1.0,10,0,&wfex
.Format
,0,CALLBACK_EVENT
,
1287 &capsA
,winetest_interactive
,TRUE
,FALSE
);
1288 wave_out_test_deviceOut(device
,1.0,5,1,&wfex
.Format
,0,CALLBACK_EVENT
,
1289 &capsA
,winetest_interactive
,TRUE
,FALSE
);
1291 trace("waveOutOpen(%s): 4 channels not supported\n",
1294 /* test if 6 channels supported */
1295 wfex
.Format
.wFormatTag
=WAVE_FORMAT_EXTENSIBLE
;
1296 wfex
.Format
.nChannels
=6;
1297 wfex
.Format
.wBitsPerSample
=16;
1298 wfex
.Format
.nSamplesPerSec
=22050;
1299 wfex
.Format
.nBlockAlign
=wfex
.Format
.nChannels
*wfex
.Format
.wBitsPerSample
/8;
1300 wfex
.Format
.nAvgBytesPerSec
=wfex
.Format
.nSamplesPerSec
*
1301 wfex
.Format
.nBlockAlign
;
1302 wfex
.Format
.cbSize
=22;
1303 wfex
.Samples
.wValidBitsPerSample
=wfex
.Format
.wBitsPerSample
;
1304 wfex
.dwChannelMask
=SPEAKER_ALL
;
1305 wfex
.SubFormat
=KSDATAFORMAT_SUBTYPE_PCM
;
1306 rc
=waveOutOpen(&wout
,device
,&wfex
.Format
,0,0,
1307 CALLBACK_NULL
|WAVE_FORMAT_DIRECT
);
1308 ok(rc
==MMSYSERR_NOERROR
|| rc
==WAVERR_BADFORMAT
||
1309 rc
==MMSYSERR_INVALFLAG
|| rc
==MMSYSERR_INVALPARAM
,
1310 "waveOutOpen(%s): returned %s\n",dev_name(device
),wave_out_error(rc
));
1311 if (rc
==MMSYSERR_NOERROR
) {
1313 wave_out_test_deviceOut(device
,1.0,1,0,&wfex
.Format
,WAVE_FORMAT_2M16
,
1314 CALLBACK_EVENT
,&capsA
,winetest_interactive
,
1316 wave_out_test_deviceOut(device
,1.0,10,0,&wfex
.Format
,WAVE_FORMAT_2M16
,
1317 CALLBACK_EVENT
,&capsA
,winetest_interactive
,
1319 wave_out_test_deviceOut(device
,1.0,5,1,&wfex
.Format
,WAVE_FORMAT_2M16
,
1320 CALLBACK_EVENT
,&capsA
,winetest_interactive
,
1323 trace("waveOutOpen(%s): 6 channels not supported\n",
1328 /* FIXME: ALSA doesn't like this format */
1329 /* test if 24 bit samples supported */
1330 wfex
.Format
.wFormatTag
=WAVE_FORMAT_EXTENSIBLE
;
1331 wfex
.Format
.nChannels
=2;
1332 wfex
.Format
.wBitsPerSample
=24;
1333 wfex
.Format
.nSamplesPerSec
=22050;
1334 wfex
.Format
.nBlockAlign
=wfex
.Format
.nChannels
*wfex
.Format
.wBitsPerSample
/8;
1335 wfex
.Format
.nAvgBytesPerSec
=wfex
.Format
.nSamplesPerSec
*
1336 wfex
.Format
.nBlockAlign
;
1337 wfex
.Format
.cbSize
=22;
1338 wfex
.Samples
.wValidBitsPerSample
=wfex
.Format
.wBitsPerSample
;
1339 wfex
.dwChannelMask
=SPEAKER_ALL
;
1340 wfex
.SubFormat
=KSDATAFORMAT_SUBTYPE_PCM
;
1341 rc
=waveOutOpen(&wout
,device
,&wfex
.Format
,0,0,
1342 CALLBACK_NULL
|WAVE_FORMAT_DIRECT
);
1343 ok(rc
==MMSYSERR_NOERROR
|| rc
==WAVERR_BADFORMAT
||
1344 rc
==MMSYSERR_INVALFLAG
|| rc
==MMSYSERR_INVALPARAM
,
1345 "waveOutOpen(%s): returned %s\n",dev_name(device
),wave_out_error(rc
));
1346 if (rc
==MMSYSERR_NOERROR
) {
1348 wave_out_test_deviceOut(device
,1.0,1,0,&wfex
.Format
,WAVE_FORMAT_2M16
,
1349 CALLBACK_EVENT
,&capsA
,winetest_interactive
,
1352 trace("waveOutOpen(%s): 24 bit samples not supported\n",
1356 /* test if 32 bit samples supported */
1357 wfex
.Format
.wFormatTag
=WAVE_FORMAT_EXTENSIBLE
;
1358 wfex
.Format
.nChannels
=2;
1359 wfex
.Format
.wBitsPerSample
=32;
1360 wfex
.Format
.nSamplesPerSec
=22050;
1361 wfex
.Format
.nBlockAlign
=wfex
.Format
.nChannels
*wfex
.Format
.wBitsPerSample
/8;
1362 wfex
.Format
.nAvgBytesPerSec
=wfex
.Format
.nSamplesPerSec
*
1363 wfex
.Format
.nBlockAlign
;
1364 wfex
.Format
.cbSize
=22;
1365 wfex
.Samples
.wValidBitsPerSample
=wfex
.Format
.wBitsPerSample
;
1366 wfex
.dwChannelMask
=SPEAKER_ALL
;
1367 wfex
.SubFormat
=KSDATAFORMAT_SUBTYPE_PCM
;
1368 rc
=waveOutOpen(&wout
,device
,&wfex
.Format
,0,0,
1369 CALLBACK_NULL
|WAVE_FORMAT_DIRECT
);
1370 ok(rc
==MMSYSERR_NOERROR
|| rc
==WAVERR_BADFORMAT
||
1371 rc
==MMSYSERR_INVALFLAG
|| rc
==MMSYSERR_INVALPARAM
,
1372 "waveOutOpen(%s): returned %s\n",dev_name(device
),wave_out_error(rc
));
1373 if (rc
==MMSYSERR_NOERROR
) {
1375 wave_out_test_deviceOut(device
,1.0,1,0,&wfex
.Format
,WAVE_FORMAT_2M16
,
1376 CALLBACK_EVENT
,&capsA
,winetest_interactive
,
1378 wave_out_test_deviceOut(device
,1.0,10,0,&wfex
.Format
,WAVE_FORMAT_2M16
,
1379 CALLBACK_EVENT
,&capsA
,winetest_interactive
,
1381 wave_out_test_deviceOut(device
,1.0,5,1,&wfex
.Format
,WAVE_FORMAT_2M16
,
1382 CALLBACK_EVENT
,&capsA
,winetest_interactive
,
1385 trace("waveOutOpen(%s): 32 bit samples not supported\n",
1388 /* test if 32 bit float samples supported */
1389 wfex
.Format
.wFormatTag
=WAVE_FORMAT_EXTENSIBLE
;
1390 wfex
.Format
.nChannels
=2;
1391 wfex
.Format
.wBitsPerSample
=32;
1392 wfex
.Format
.nSamplesPerSec
=22050;
1393 wfex
.Format
.nBlockAlign
=wfex
.Format
.nChannels
*wfex
.Format
.wBitsPerSample
/8;
1394 wfex
.Format
.nAvgBytesPerSec
=wfex
.Format
.nSamplesPerSec
*
1395 wfex
.Format
.nBlockAlign
;
1396 wfex
.Format
.cbSize
=22;
1397 wfex
.Samples
.wValidBitsPerSample
=wfex
.Format
.wBitsPerSample
;
1398 wfex
.dwChannelMask
=SPEAKER_ALL
;
1399 wfex
.SubFormat
=KSDATAFORMAT_SUBTYPE_IEEE_FLOAT
;
1400 rc
=waveOutOpen(&wout
,device
,&wfex
.Format
,0,0,
1401 CALLBACK_NULL
|WAVE_FORMAT_DIRECT
);
1402 ok(rc
==MMSYSERR_NOERROR
|| rc
==WAVERR_BADFORMAT
||
1403 rc
==MMSYSERR_INVALFLAG
|| rc
==MMSYSERR_INVALPARAM
,
1404 "waveOutOpen(%s): returned %s\n",dev_name(device
),wave_out_error(rc
));
1405 if (rc
==MMSYSERR_NOERROR
) {
1407 wave_out_test_deviceOut(device
,1.0,1,0,&wfex
.Format
,WAVE_FORMAT_2M16
,
1408 CALLBACK_EVENT
,&capsA
,winetest_interactive
,
1410 wave_out_test_deviceOut(device
,1.0,10,0,&wfex
.Format
,WAVE_FORMAT_2M16
,
1411 CALLBACK_EVENT
,&capsA
,winetest_interactive
,
1413 wave_out_test_deviceOut(device
,1.0,5,1,&wfex
.Format
,WAVE_FORMAT_2M16
,
1414 CALLBACK_EVENT
,&capsA
,winetest_interactive
,
1417 trace("waveOutOpen(%s): 32 bit float samples not supported\n",
1421 static void wave_out_tests(void)
1425 WAVEFORMATEX format
;
1428 DWORD preferred
, status
;
1431 ndev
=waveOutGetNumDevs();
1432 trace("found %d WaveOut devices\n",ndev
);
1434 rc
= waveOutMessage((HWAVEOUT
)WAVE_MAPPER
, DRVM_MAPPER_PREFERRED_GET
,
1435 (DWORD_PTR
)&preferred
, (DWORD_PTR
)&status
);
1436 ok((ndev
== 0 && (rc
== MMSYSERR_NODRIVER
|| rc
== MMSYSERR_BADDEVICEID
)) ||
1437 rc
== MMSYSERR_NOTSUPPORTED
||
1438 rc
== MMSYSERR_NOERROR
, "waveOutMessage(DRVM_MAPPER_PREFERRED_GET) failed: %u\n", rc
);
1440 if(rc
!= MMSYSERR_NOTSUPPORTED
)
1441 ok((ndev
== 0 && (preferred
== -1 || broken(preferred
!= -1))) ||
1442 preferred
< ndev
, "Got invalid preferred device: 0x%x\n", preferred
);
1444 rc
=waveOutGetDevCapsA(ndev
+1,&capsA
,sizeof(capsA
));
1445 ok(rc
==MMSYSERR_BADDEVICEID
,
1446 "waveOutGetDevCapsA(%s): MMSYSERR_BADDEVICEID expected, got %s\n",
1447 dev_name(ndev
+1),mmsys_error(rc
));
1449 rc
=waveOutGetDevCapsW(ndev
+1,&capsW
,sizeof(capsW
));
1450 ok(rc
==MMSYSERR_BADDEVICEID
|| rc
==MMSYSERR_NOTSUPPORTED
,
1451 "waveOutGetDevCapsW(%s): MMSYSERR_BADDEVICEID or MMSYSERR_NOTSUPPORTED "
1452 "expected, got %s\n",dev_name(ndev
+1),mmsys_error(rc
));
1454 rc
=waveOutGetDevCapsA(WAVE_MAPPER
,&capsA
,sizeof(capsA
));
1456 ok(rc
==MMSYSERR_NOERROR
,
1457 "waveOutGetDevCapsA(%s): MMSYSERR_NOERROR expected, got %s\n",
1458 dev_name(WAVE_MAPPER
),mmsys_error(rc
));
1460 ok(rc
==MMSYSERR_BADDEVICEID
|| rc
==MMSYSERR_NODRIVER
,
1461 "waveOutGetDevCapsA(%s): MMSYSERR_BADDEVICEID or MMSYSERR_NODRIVER "
1462 "expected, got %s\n",dev_name(WAVE_MAPPER
),mmsys_error(rc
));
1464 rc
=waveOutGetDevCapsW(WAVE_MAPPER
,&capsW
,sizeof(capsW
));
1466 ok(rc
==MMSYSERR_NOERROR
|| rc
==MMSYSERR_NOTSUPPORTED
,
1467 "waveOutGetDevCapsW(%s): MMSYSERR_NOERROR or MMSYSERR_NOTSUPPORTED "
1468 "expected, got %s\n",dev_name(WAVE_MAPPER
),mmsys_error(rc
));
1470 ok(rc
==MMSYSERR_BADDEVICEID
|| rc
==MMSYSERR_NODRIVER
||
1471 rc
==MMSYSERR_NOTSUPPORTED
,
1472 "waveOutGetDevCapsW(%s): MMSYSERR_BADDEVICEID or MMSYSERR_NODRIVER "
1473 " or MMSYSERR_NOTSUPPORTED expected, got %s\n",
1474 dev_name(WAVE_MAPPER
),mmsys_error(rc
));
1476 format
.wFormatTag
=WAVE_FORMAT_PCM
;
1478 format
.wBitsPerSample
=16;
1479 format
.nSamplesPerSec
=44100;
1480 format
.nBlockAlign
=format
.nChannels
*format
.wBitsPerSample
/8;
1481 format
.nAvgBytesPerSec
=format
.nSamplesPerSec
*format
.nBlockAlign
;
1483 rc
=waveOutOpen(&wout
,ndev
+1,&format
,0,0,CALLBACK_NULL
);
1484 ok(rc
==MMSYSERR_BADDEVICEID
,
1485 "waveOutOpen(%s): MMSYSERR_BADDEVICEID expected, got %s\n",
1486 dev_name(ndev
+1),mmsys_error(rc
));
1488 if(winetest_interactive
)
1489 for (d
=0;d
<ndev
;d
++)
1490 wave_out_test_device(d
);
1493 wave_out_test_device(WAVE_MAPPER
);
1496 static void test_sndPlaySound(void)
1500 static const WCHAR not_existW
[] = {'C',':','\\','n','o','t','_','e','x','i','s','t','.','w','a','v',0};
1501 static const WCHAR SystemAsteriskW
[] = {'S','y','s','t','e','m','A','s','t','e','r','i','s','k',0};
1503 br
= sndPlaySoundA((LPCSTR
)SND_ALIAS_SYSTEMASTERISK
, SND_ALIAS_ID
|SND_SYNC
);
1504 ok(br
== TRUE
|| br
== FALSE
, "sndPlaySound gave strange return: %u\n", br
);
1506 br
= sndPlaySoundW((LPCWSTR
)SND_ALIAS_SYSTEMASTERISK
, SND_ALIAS_ID
|SND_SYNC
);
1507 ok(br
== TRUE
|| br
== FALSE
, "sndPlaySound gave strange return: %u\n", br
);
1509 br
= sndPlaySoundA((LPCSTR
)sndAlias('X','Y'), SND_ALIAS_ID
|SND_SYNC
);
1510 ok(br
== TRUE
|| br
== FALSE
, "sndPlaySound gave strange return: %u\n", br
);
1512 br
= sndPlaySoundW((LPCWSTR
)sndAlias('X','Y'), SND_ALIAS_ID
|SND_SYNC
);
1513 ok(br
== TRUE
|| br
== FALSE
, "sndPlaySound gave strange return: %u\n", br
);
1515 br
= sndPlaySoundA("SystemAsterisk", SND_ALIAS
|SND_SYNC
);
1516 ok(br
== TRUE
|| br
== FALSE
, "sndPlaySound gave strange return: %u\n", br
);
1518 br
= sndPlaySoundW(SystemAsteriskW
, SND_ALIAS
|SND_SYNC
);
1519 ok(br
== TRUE
|| br
== FALSE
, "sndPlaySound gave strange return: %u\n", br
);
1521 br
= sndPlaySoundA("C:\not_exist.wav", SND_FILENAME
|SND_SYNC
);
1522 ok(br
== TRUE
|| br
== FALSE
, "sndPlaySound gave strange return: %u\n", br
);
1524 br
= sndPlaySoundW(not_existW
, SND_FILENAME
|SND_SYNC
);
1525 ok(br
== TRUE
|| br
== FALSE
, "sndPlaySound gave strange return: %u\n", br
);
1528 static void test_fragmentsize(void)
1538 if(waveOutGetNumDevs() == 0)
1541 fmt
.wFormatTag
= WAVE_FORMAT_PCM
;
1543 fmt
.nSamplesPerSec
= 44100;
1544 fmt
.wBitsPerSample
= 16;
1545 fmt
.nBlockAlign
= fmt
.nChannels
* fmt
.wBitsPerSample
/ 8;
1546 fmt
.nAvgBytesPerSec
= fmt
.nBlockAlign
* fmt
.nSamplesPerSec
;
1547 fmt
.cbSize
= sizeof(WAVEFORMATEX
);
1549 hevent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1550 g_tid
= GetCurrentThreadId();
1552 rc
= waveOutOpen(&wout
, WAVE_MAPPER
, &fmt
, (DWORD_PTR
)callback_func
,
1553 (DWORD_PTR
)hevent
, CALLBACK_FUNCTION
);
1554 ok(rc
== MMSYSERR_NOERROR
|| rc
== WAVERR_BADFORMAT
||
1555 rc
== MMSYSERR_INVALFLAG
|| rc
== MMSYSERR_INVALPARAM
,
1556 "waveOutOpen(%s) failed: %s\n", dev_name(WAVE_MAPPER
), wave_out_error(rc
));
1557 if(rc
!= MMSYSERR_NOERROR
){
1558 CloseHandle(hevent
);
1562 wait
= WaitForSingleObject(hevent
, 1000);
1563 ok(wait
== WAIT_OBJECT_0
, "wave open callback missed\n");
1565 memset(hdr
, 0, sizeof(hdr
));
1566 hdr
[0].dwBufferLength
= (fmt
.nSamplesPerSec
* fmt
.nBlockAlign
/ 4) + 1;
1567 hdr
[1].dwBufferLength
= hdr
[0].dwBufferLength
- 2;
1568 hdr
[1].lpData
= hdr
[0].lpData
=
1569 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, hdr
[0].dwBufferLength
);
1571 rc
= waveOutPrepareHeader(wout
, &hdr
[0], sizeof(hdr
[0]));
1572 ok(rc
== MMSYSERR_NOERROR
, "waveOutPrepareHeader failed: %s\n", wave_out_error(rc
));
1574 rc
= waveOutPrepareHeader(wout
, &hdr
[1], sizeof(hdr
[1]));
1575 ok(rc
== MMSYSERR_NOERROR
, "waveOutPrepareHeader failed: %s\n", wave_out_error(rc
));
1577 trace("writing %u bytes then %u bytes\n", hdr
[0].dwBufferLength
, hdr
[1].dwBufferLength
);
1578 rc
= waveOutWrite(wout
, &hdr
[0], sizeof(hdr
[0]));
1579 ok(rc
== MMSYSERR_NOERROR
, "waveOutWrite failed: %s\n", wave_out_error(rc
));
1581 rc
= waveOutWrite(wout
, &hdr
[1], sizeof(hdr
[1]));
1582 ok(rc
== MMSYSERR_NOERROR
, "waveOutWrite failed: %s\n", wave_out_error(rc
));
1584 wait
= WaitForSingleObject(hevent
, 1000);
1585 ok(wait
== WAIT_OBJECT_0
, "header 1 callback missed\n");
1587 wait
= WaitForSingleObject(hevent
, 1000);
1588 ok(wait
== WAIT_OBJECT_0
, "header 2 callback missed\n");
1590 memset(&mmtime
, 0, sizeof(mmtime
));
1591 mmtime
.wType
= TIME_BYTES
;
1593 rc
= waveOutGetPosition(wout
, &mmtime
, sizeof(mmtime
));
1594 ok(rc
== MMSYSERR_NOERROR
, "waveOutGetPosition failed: %s\n", wave_out_error(rc
));
1596 /* windows behavior is inconsistent */
1597 ok(mmtime
.u
.cb
== 88200 ||
1598 mmtime
.u
.cb
== 88196, "after position: %u\n", mmtime
.u
.cb
);
1600 rc
= waveOutClose(wout
);
1601 ok(rc
== MMSYSERR_NOERROR
, "waveOutClose failed: %s\n", wave_out_error(rc
));
1603 HeapFree(GetProcessHeap(), 0, hdr
[0].lpData
);
1604 CloseHandle(hevent
);
1607 static void create_wav_file(char *temp_file
)
1609 WAVEFORMATEX format
;
1611 MMCKINFO riff_chunk
, chunk
;
1617 format
.wFormatTag
=WAVE_FORMAT_PCM
;
1620 format
.wBitsPerSample
=8;
1621 format
.nSamplesPerSec
=8000;
1622 format
.nBlockAlign
=format
.nChannels
*format
.wBitsPerSample
/8;
1623 format
.nAvgBytesPerSec
=format
.nSamplesPerSec
*format
.nBlockAlign
;
1625 h
= mmioOpenA(temp_file
, NULL
, MMIO_ALLOCBUF
| MMIO_WRITE
| MMIO_CREATE
);
1626 ok(h
!= NULL
, "Can't open temp_file\n");
1628 riff_chunk
.fccType
= mmioFOURCC('W','A','V','E');
1629 riff_chunk
.cksize
= 0;
1630 rc
= mmioCreateChunk(h
, &riff_chunk
, MMIO_CREATERIFF
);
1631 ok(rc
== MMSYSERR_NOERROR
, "mmioCreateChunk failed, got %u\n", rc
);
1633 chunk
.ckid
= mmioFOURCC('f','m','t',' ');
1635 rc
= mmioCreateChunk(h
, &chunk
, 0);
1636 ok(rc
== MMSYSERR_NOERROR
, "mmioCreateChunk failed, got %u\n", rc
);
1637 written
= mmioWrite(h
, (char*)&format
, sizeof(format
));
1638 ok(written
== sizeof(format
), "mmioWrite failed, got %d\n", written
);
1639 rc
= mmioAscend(h
, &chunk
, 0);
1640 ok(rc
== MMSYSERR_NOERROR
, "mmioAscend failed, got %d\n", rc
);
1642 chunk
.ckid
= mmioFOURCC('d','a','t','a');
1643 rc
= mmioCreateChunk(h
, &chunk
, 0);
1644 ok(rc
== MMSYSERR_NOERROR
, "mmioCreateChunk failed, got %u\n", rc
);
1645 buffer
= wave_generate_silence(&format
, .1, &length
);
1646 written
= mmioWrite(h
, buffer
, length
);
1647 ok(written
== length
, "mmioWrite failed, got %d\n", written
);
1648 rc
= mmioAscend(h
, &chunk
, 0);
1649 ok(rc
== MMSYSERR_NOERROR
, "mmioAscend failed, got %d\n", rc
);
1650 HeapFree(GetProcessHeap(), 0, buffer
);
1652 rc
= mmioAscend(h
, &riff_chunk
, 0);
1653 ok(rc
== MMSYSERR_NOERROR
, "mmioAscend failed, got %d\n", rc
);
1655 rc
= mmioClose(h
, 0);
1656 ok(rc
== MMSYSERR_NOERROR
, "mmioClose failed, got %u\n", rc
);
1659 static void test_PlaySound(void)
1662 char test_file
[MAX_PATH
], temp
[MAX_PATH
], *exts
;
1663 void *psound_ordinal
, *psound_name
;
1664 HMODULE dll
= GetModuleHandleA("winmm.dll");
1666 psound_name
= GetProcAddress(dll
, "PlaySound");
1667 psound_ordinal
= GetProcAddress(dll
, (LPCSTR
) 2);
1668 ok(psound_name
== psound_ordinal
, "Expected ordinal 2 to be PlaySound function\n");
1670 if(waveOutGetNumDevs() == 0) {
1671 skip("No output devices available\n");
1675 GetTempPathA(sizeof(test_file
), test_file
);
1676 strcat(test_file
, "mysound.wav");
1677 create_wav_file(test_file
);
1679 br
= PlaySoundA(test_file
, NULL
, SND_FILENAME
| SND_NODEFAULT
);
1680 ok(br
, "PlaySound failed, got %d\n", br
);
1682 /* SND_ALIAS fallbacks to SND_FILENAME */
1683 br
= PlaySoundA(test_file
, NULL
, SND_ALIAS
| SND_NODEFAULT
);
1684 ok(br
, "PlaySound failed, got %d\n", br
);
1686 strcpy(temp
, test_file
);
1687 exts
= strrchr(temp
, '.');
1691 br
= PlaySoundA(temp
, NULL
, SND_FILENAME
| SND_NODEFAULT
);
1692 ok(br
, "PlaySound failed, got %d\n", br
);
1694 /* ends with a dot */
1696 br
= PlaySoundA(temp
, NULL
, SND_FILENAME
| SND_NODEFAULT
);
1697 ok(!br
|| broken(br
), "PlaySound succeeded, got %d\n", br
);
1699 DeleteFileA(test_file
);
1704 test_multiple_waveopens();
1706 test_sndPlaySound();
1707 test_fragmentsize();