1 /* 2 * Test winmm sound playback in each sound format 3 * 4 * Copyright (c) 2002 Francois Gouget 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include <stdarg.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <math.h> 25 26 #include "wine/test.h" 27 #include "windef.h" 28 #include "winbase.h" 29 #include "winuser.h" 30 #include "winnls.h" 31 #include "mmsystem.h" 32 #define NOBITMAP 33 #include "mmddk.h" 34 #include "mmreg.h" 35 #include "ks.h" 36 #include "ksguid.h" 37 #ifndef __REACTOS__ 38 #include "ksmedia.h" 39 #endif 40 41 #include "winmm_test.h" 42 43 #ifdef __REACTOS__ /* FIXME */ 44 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); 45 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); 46 #endif 47 48 static DWORD g_tid; 49 50 static void test_multiple_waveopens(void) 51 { 52 HWAVEOUT handle1, handle2; 53 MMRESULT ret; 54 WAVEFORMATEX wfx; 55 56 wfx.wFormatTag = WAVE_FORMAT_PCM; 57 wfx.nChannels = 1; 58 wfx.nSamplesPerSec = 11025; 59 wfx.nBlockAlign = 1; 60 wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign; 61 wfx.wBitsPerSample = 8; 62 wfx.cbSize = 0; 63 64 ret = waveOutOpen(&handle1, 0, &wfx, 0, 0, 0); 65 if (ret != MMSYSERR_NOERROR) 66 { 67 skip("Could not do the duplicate waveopen test\n"); 68 return; 69 } 70 71 ret = waveOutOpen(&handle2, 0, &wfx, 0, 0, 0); 72 /* Modern Windows allows for wave-out devices to be opened multiple times. 73 * Some Wine audio drivers allow that and some don't. To avoid false alarms 74 * for those that do, don't "todo_wine ok(...)" on success. 75 */ 76 if (ret != MMSYSERR_NOERROR) 77 { 78 todo_wine ok(ret == MMSYSERR_NOERROR || broken(ret == MMSYSERR_ALLOCATED), /* winME */ 79 "second waveOutOpen returns: %x\n", ret); 80 } 81 else 82 waveOutClose(handle2); 83 84 waveOutClose(handle1); 85 } 86 87 /* 88 * Note that in most of this test we may get MMSYSERR_BADDEVICEID errors 89 * at about any time if the user starts another application that uses the 90 * sound device. So we should not report these as test failures. 91 * 92 * This test can play a test tone. But this only makes sense if someone 93 * is going to carefully listen to it, and would only bother everyone else. 94 * So this is only done if the test is being run in interactive mode. 95 */ 96 97 #define PI 3.14159265358979323846 98 static char* wave_generate_la(WAVEFORMATEX* wfx, double duration, DWORD* size) 99 { 100 int i,j; 101 int nb_samples; 102 char* buf; 103 char* b; 104 WAVEFORMATEXTENSIBLE *wfex = (WAVEFORMATEXTENSIBLE*)wfx; 105 106 nb_samples=(int)(duration*wfx->nSamplesPerSec); 107 *size=nb_samples*wfx->nBlockAlign; 108 b=buf=HeapAlloc(GetProcessHeap(), 0, *size); 109 for (i=0;i<nb_samples;i++) { 110 double y=sin(440.0*2*PI*i/wfx->nSamplesPerSec); 111 if (wfx->wBitsPerSample==8) { 112 unsigned char sample=(unsigned char)((double)127.5*(y+1.0)); 113 for (j = 0; j < wfx->nChannels; j++) 114 *b++=sample; 115 } else if (wfx->wBitsPerSample==16) { 116 signed short sample=(signed short)((double)32767.5*y-0.5); 117 for (j = 0; j < wfx->nChannels; j++) { 118 b[0]=sample & 0xff; 119 b[1]=sample >> 8; 120 b+=2; 121 } 122 } else if (wfx->wBitsPerSample==24) { 123 signed int sample=(signed int)(((double)0x7fffff+0.5)*y-0.5); 124 for (j = 0; j < wfx->nChannels; j++) { 125 b[0]=sample & 0xff; 126 b[1]=(sample >> 8) & 0xff; 127 b[2]=(sample >> 16) & 0xff; 128 b+=3; 129 } 130 } else if ((wfx->wBitsPerSample==32) && ((wfx->wFormatTag == WAVE_FORMAT_PCM) || 131 ((wfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) && 132 IsEqualGUID(&wfex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)))) { 133 signed int sample=(signed int)(((double)0x7fffffff+0.5)*y-0.5); 134 for (j = 0; j < wfx->nChannels; j++) { 135 b[0]=sample & 0xff; 136 b[1]=(sample >> 8) & 0xff; 137 b[2]=(sample >> 16) & 0xff; 138 b[3]=(sample >> 24) & 0xff; 139 b+=4; 140 } 141 } else if ((wfx->wBitsPerSample==32) && (wfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) && 142 IsEqualGUID(&wfex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) { 143 union { float f; char c[4]; } sample; 144 sample.f=(float)y; 145 for (j = 0; j < wfx->nChannels; j++) { 146 b[0]=sample.c[0]; 147 b[1]=sample.c[1]; 148 b[2]=sample.c[2]; 149 b[3]=sample.c[3]; 150 b+=4; 151 } 152 } 153 } 154 return buf; 155 } 156 157 static char* wave_generate_silence(WAVEFORMATEX* wfx, double duration, DWORD* size) 158 { 159 int i,j; 160 int nb_samples; 161 char* buf; 162 char* b; 163 WAVEFORMATEXTENSIBLE *wfex = (WAVEFORMATEXTENSIBLE*)wfx; 164 165 nb_samples=(int)(duration*wfx->nSamplesPerSec); 166 *size=nb_samples*wfx->nBlockAlign; 167 b=buf=HeapAlloc(GetProcessHeap(), 0, *size); 168 for (i=0;i<nb_samples;i++) { 169 if (wfx->wBitsPerSample==8) { 170 for (j = 0; j < wfx->nChannels; j++) 171 *b++=128; 172 } else if (wfx->wBitsPerSample==16) { 173 for (j = 0; j < wfx->nChannels; j++) { 174 b[0]=0; 175 b[1]=0; 176 b+=2; 177 } 178 } else if (wfx->wBitsPerSample==24) { 179 for (j = 0; j < wfx->nChannels; j++) { 180 b[0]=0; 181 b[1]=0; 182 b[2]=0; 183 b+=3; 184 } 185 } else if ((wfx->wBitsPerSample==32) && ((wfx->wFormatTag == WAVE_FORMAT_PCM) || 186 ((wfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) && 187 IsEqualGUID(&wfex->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)))) { 188 for (j = 0; j < wfx->nChannels; j++) { 189 b[0]=0; 190 b[1]=0; 191 b[2]=0; 192 b[3]=0; 193 b+=4; 194 } 195 } else if ((wfx->wBitsPerSample==32) && (wfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) && 196 IsEqualGUID(&wfex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) { 197 union { float f; char c[4]; } sample; 198 sample.f=0; 199 for (j = 0; j < wfx->nChannels; j++) { 200 b[0]=sample.c[0]; 201 b[1]=sample.c[1]; 202 b[2]=sample.c[2]; 203 b[3]=sample.c[3]; 204 b+=4; 205 } 206 } 207 } 208 return buf; 209 } 210 211 const char * dev_name(int device) 212 { 213 static char name[16]; 214 if (device == WAVE_MAPPER) 215 return "WAVE_MAPPER"; 216 sprintf(name, "%d", device); 217 return name; 218 } 219 220 const char* mmsys_error(MMRESULT error) 221 { 222 #define ERR_TO_STR(dev) case dev: return #dev 223 static char unknown[32]; 224 switch (error) { 225 ERR_TO_STR(MMSYSERR_NOERROR); 226 ERR_TO_STR(MMSYSERR_ERROR); 227 ERR_TO_STR(MMSYSERR_BADDEVICEID); 228 ERR_TO_STR(MMSYSERR_NOTENABLED); 229 ERR_TO_STR(MMSYSERR_ALLOCATED); 230 ERR_TO_STR(MMSYSERR_INVALHANDLE); 231 ERR_TO_STR(MMSYSERR_NODRIVER); 232 ERR_TO_STR(MMSYSERR_NOMEM); 233 ERR_TO_STR(MMSYSERR_NOTSUPPORTED); 234 ERR_TO_STR(MMSYSERR_BADERRNUM); 235 ERR_TO_STR(MMSYSERR_INVALFLAG); 236 ERR_TO_STR(MMSYSERR_INVALPARAM); 237 ERR_TO_STR(WAVERR_BADFORMAT); 238 ERR_TO_STR(WAVERR_STILLPLAYING); 239 ERR_TO_STR(WAVERR_UNPREPARED); 240 ERR_TO_STR(WAVERR_SYNC); 241 ERR_TO_STR(MIDIERR_UNPREPARED); 242 ERR_TO_STR(MIDIERR_STILLPLAYING); 243 ERR_TO_STR(MIDIERR_NOTREADY); 244 ERR_TO_STR(MIDIERR_NODEVICE); 245 ERR_TO_STR(MIDIERR_INVALIDSETUP); 246 ERR_TO_STR(TIMERR_NOCANDO); 247 ERR_TO_STR(TIMERR_STRUCT); 248 ERR_TO_STR(JOYERR_PARMS); 249 ERR_TO_STR(JOYERR_NOCANDO); 250 ERR_TO_STR(JOYERR_UNPLUGGED); 251 ERR_TO_STR(MIXERR_INVALLINE); 252 ERR_TO_STR(MIXERR_INVALCONTROL); 253 ERR_TO_STR(MIXERR_INVALVALUE); 254 ERR_TO_STR(MMIOERR_FILENOTFOUND); 255 ERR_TO_STR(MMIOERR_OUTOFMEMORY); 256 ERR_TO_STR(MMIOERR_CANNOTOPEN); 257 ERR_TO_STR(MMIOERR_CANNOTCLOSE); 258 ERR_TO_STR(MMIOERR_CANNOTREAD); 259 ERR_TO_STR(MMIOERR_CANNOTWRITE); 260 ERR_TO_STR(MMIOERR_CANNOTSEEK); 261 ERR_TO_STR(MMIOERR_CANNOTEXPAND); 262 ERR_TO_STR(MMIOERR_CHUNKNOTFOUND); 263 ERR_TO_STR(MMIOERR_UNBUFFERED); 264 } 265 sprintf(unknown, "Unknown(0x%08x)", error); 266 return unknown; 267 #undef ERR_TO_STR 268 } 269 270 const char* wave_out_error(MMRESULT error) 271 { 272 static char msg[1024]; 273 static char long_msg[1100]; 274 MMRESULT rc; 275 276 rc = waveOutGetErrorTextA(error, msg, sizeof(msg)); 277 if (rc != MMSYSERR_NOERROR) 278 sprintf(long_msg, "waveOutGetErrorTextA(%x) failed with error %x", error, rc); 279 else 280 sprintf(long_msg, "%s(%s)", mmsys_error(error), msg); 281 return long_msg; 282 } 283 284 const char * wave_open_flags(DWORD flags) 285 { 286 static char msg[1024]; 287 BOOL first = TRUE; 288 msg[0] = 0; 289 if ((flags & CALLBACK_TYPEMASK) == CALLBACK_EVENT) { 290 strcat(msg, "CALLBACK_EVENT"); 291 first = FALSE; 292 } 293 if ((flags & CALLBACK_TYPEMASK) == CALLBACK_FUNCTION) { 294 if (!first) strcat(msg, "|"); 295 strcat(msg, "CALLBACK_FUNCTION"); 296 first = FALSE; 297 } 298 if ((flags & CALLBACK_TYPEMASK) == CALLBACK_NULL) { 299 if (!first) strcat(msg, "|"); 300 strcat(msg, "CALLBACK_NULL"); 301 first = FALSE; 302 } 303 if ((flags & CALLBACK_TYPEMASK) == CALLBACK_THREAD) { 304 if (!first) strcat(msg, "|"); 305 strcat(msg, "CALLBACK_THREAD"); 306 first = FALSE; 307 } 308 if ((flags & CALLBACK_TYPEMASK) == CALLBACK_WINDOW) { 309 if (!first) strcat(msg, "|"); 310 strcat(msg, "CALLBACK_WINDOW"); 311 first = FALSE; 312 } 313 if ((flags & WAVE_ALLOWSYNC) == WAVE_ALLOWSYNC) { 314 if (!first) strcat(msg, "|"); 315 strcat(msg, "WAVE_ALLOWSYNC"); 316 first = FALSE; 317 } 318 if ((flags & WAVE_FORMAT_DIRECT) == WAVE_FORMAT_DIRECT) { 319 if (!first) strcat(msg, "|"); 320 strcat(msg, "WAVE_FORMAT_DIRECT"); 321 first = FALSE; 322 } 323 if ((flags & WAVE_FORMAT_QUERY) == WAVE_FORMAT_QUERY) { 324 if (!first) strcat(msg, "|"); 325 strcat(msg, "WAVE_FORMAT_QUERY"); 326 first = FALSE; 327 } 328 if ((flags & WAVE_MAPPED) == WAVE_MAPPED) { 329 if (!first) strcat(msg, "|"); 330 strcat(msg, "WAVE_MAPPED"); 331 } 332 return msg; 333 } 334 335 static const char * wave_header_flags(DWORD flags) 336 { 337 #define WHDR_MASK (WHDR_BEGINLOOP|WHDR_DONE|WHDR_ENDLOOP|WHDR_INQUEUE|WHDR_PREPARED) 338 static char msg[1024]; 339 BOOL first = TRUE; 340 msg[0] = 0; 341 if (flags & WHDR_BEGINLOOP) { 342 strcat(msg, "WHDR_BEGINLOOP"); 343 first = FALSE; 344 } 345 if (flags & WHDR_DONE) { 346 if (!first) strcat(msg, " "); 347 strcat(msg, "WHDR_DONE"); 348 first = FALSE; 349 } 350 if (flags & WHDR_ENDLOOP) { 351 if (!first) strcat(msg, " "); 352 strcat(msg, "WHDR_ENDLOOP"); 353 first = FALSE; 354 } 355 if (flags & WHDR_INQUEUE) { 356 if (!first) strcat(msg, " "); 357 strcat(msg, "WHDR_INQUEUE"); 358 first = FALSE; 359 } 360 if (flags & WHDR_PREPARED) { 361 if (!first) strcat(msg, " "); 362 strcat(msg, "WHDR_PREPARED"); 363 first = FALSE; 364 } 365 if (flags & ~WHDR_MASK) { 366 char temp[32]; 367 sprintf(temp, "UNKNOWN(0x%08x)", flags & ~WHDR_MASK); 368 if (!first) strcat(msg, " "); 369 strcat(msg, temp); 370 } 371 return msg; 372 } 373 374 static const char * wave_out_caps(DWORD dwSupport) 375 { 376 #define ADD_FLAG(f) if (dwSupport & f) strcat(msg, " " #f) 377 static char msg[256]; 378 msg[0] = 0; 379 380 ADD_FLAG(WAVECAPS_PITCH); 381 ADD_FLAG(WAVECAPS_PLAYBACKRATE); 382 ADD_FLAG(WAVECAPS_VOLUME); 383 ADD_FLAG(WAVECAPS_LRVOLUME); 384 ADD_FLAG(WAVECAPS_SYNC); 385 ADD_FLAG(WAVECAPS_SAMPLEACCURATE); 386 387 return msg[0] ? msg + 1 : ""; 388 #undef ADD_FLAG 389 } 390 391 const char * wave_time_format(UINT type) 392 { 393 static char msg[32]; 394 #define TIME_FORMAT(f) case f: return #f 395 switch (type) { 396 TIME_FORMAT(TIME_MS); 397 TIME_FORMAT(TIME_SAMPLES); 398 TIME_FORMAT(TIME_BYTES); 399 TIME_FORMAT(TIME_SMPTE); 400 TIME_FORMAT(TIME_MIDI); 401 TIME_FORMAT(TIME_TICKS); 402 } 403 #undef TIME_FORMAT 404 sprintf(msg, "Unknown(0x%04x)", type); 405 return msg; 406 } 407 408 const char * get_format_str(WORD format) 409 { 410 static char msg[32]; 411 #define WAVE_FORMAT(f) case f: return #f 412 switch (format) { 413 WAVE_FORMAT(WAVE_FORMAT_PCM); 414 WAVE_FORMAT(WAVE_FORMAT_ADPCM); 415 WAVE_FORMAT(WAVE_FORMAT_IBM_CVSD); 416 WAVE_FORMAT(WAVE_FORMAT_ALAW); 417 WAVE_FORMAT(WAVE_FORMAT_MULAW); 418 WAVE_FORMAT(WAVE_FORMAT_OKI_ADPCM); 419 WAVE_FORMAT(WAVE_FORMAT_IMA_ADPCM); 420 WAVE_FORMAT(WAVE_FORMAT_MEDIASPACE_ADPCM); 421 WAVE_FORMAT(WAVE_FORMAT_SIERRA_ADPCM); 422 WAVE_FORMAT(WAVE_FORMAT_G723_ADPCM); 423 WAVE_FORMAT(WAVE_FORMAT_DIGISTD); 424 WAVE_FORMAT(WAVE_FORMAT_DIGIFIX); 425 WAVE_FORMAT(WAVE_FORMAT_DIALOGIC_OKI_ADPCM); 426 WAVE_FORMAT(WAVE_FORMAT_YAMAHA_ADPCM); 427 WAVE_FORMAT(WAVE_FORMAT_SONARC); 428 WAVE_FORMAT(WAVE_FORMAT_DSPGROUP_TRUESPEECH); 429 WAVE_FORMAT(WAVE_FORMAT_ECHOSC1); 430 WAVE_FORMAT(WAVE_FORMAT_AUDIOFILE_AF36); 431 WAVE_FORMAT(WAVE_FORMAT_APTX); 432 WAVE_FORMAT(WAVE_FORMAT_AUDIOFILE_AF10); 433 WAVE_FORMAT(WAVE_FORMAT_DOLBY_AC2); 434 WAVE_FORMAT(WAVE_FORMAT_GSM610); 435 WAVE_FORMAT(WAVE_FORMAT_ANTEX_ADPCME); 436 WAVE_FORMAT(WAVE_FORMAT_CONTROL_RES_VQLPC); 437 WAVE_FORMAT(WAVE_FORMAT_DIGIREAL); 438 WAVE_FORMAT(WAVE_FORMAT_DIGIADPCM); 439 WAVE_FORMAT(WAVE_FORMAT_CONTROL_RES_CR10); 440 WAVE_FORMAT(WAVE_FORMAT_NMS_VBXADPCM); 441 WAVE_FORMAT(WAVE_FORMAT_G721_ADPCM); 442 WAVE_FORMAT(WAVE_FORMAT_MPEG); 443 WAVE_FORMAT(WAVE_FORMAT_MPEGLAYER3); 444 WAVE_FORMAT(WAVE_FORMAT_CREATIVE_ADPCM); 445 WAVE_FORMAT(WAVE_FORMAT_CREATIVE_FASTSPEECH8); 446 WAVE_FORMAT(WAVE_FORMAT_CREATIVE_FASTSPEECH10); 447 WAVE_FORMAT(WAVE_FORMAT_FM_TOWNS_SND); 448 WAVE_FORMAT(WAVE_FORMAT_OLIGSM); 449 WAVE_FORMAT(WAVE_FORMAT_OLIADPCM); 450 WAVE_FORMAT(WAVE_FORMAT_OLICELP); 451 WAVE_FORMAT(WAVE_FORMAT_OLISBC); 452 WAVE_FORMAT(WAVE_FORMAT_OLIOPR); 453 WAVE_FORMAT(WAVE_FORMAT_DEVELOPMENT); 454 WAVE_FORMAT(WAVE_FORMAT_EXTENSIBLE); 455 } 456 #undef WAVE_FORMAT 457 sprintf(msg, "Unknown(0x%04x)", format); 458 return msg; 459 } 460 461 DWORD bytes_to_samples(DWORD bytes, LPWAVEFORMATEX pwfx) 462 { 463 return bytes / pwfx->nBlockAlign; 464 } 465 466 DWORD bytes_to_ms(DWORD bytes, LPWAVEFORMATEX pwfx) 467 { 468 return bytes_to_samples(bytes, pwfx) * 1000 / pwfx->nSamplesPerSec; 469 } 470 471 DWORD time_to_bytes(LPMMTIME mmtime, LPWAVEFORMATEX pwfx) 472 { 473 if (mmtime->wType == TIME_BYTES) 474 return mmtime->u.cb; 475 else if (mmtime->wType == TIME_SAMPLES) 476 return mmtime->u.sample * pwfx->nBlockAlign; 477 else if (mmtime->wType == TIME_MS) 478 return mmtime->u.ms * pwfx->nAvgBytesPerSec / 1000; 479 else if (mmtime->wType == TIME_SMPTE) 480 return ((mmtime->u.smpte.hour * 60 * 60) + 481 (mmtime->u.smpte.min * 60) + 482 (mmtime->u.smpte.sec)) * pwfx->nAvgBytesPerSec + 483 mmtime->u.smpte.frame * pwfx->nAvgBytesPerSec / 30; 484 485 trace("FIXME: time_to_bytes() type not supported\n"); 486 return -1; 487 } 488 489 static void check_position(int device, HWAVEOUT wout, DWORD bytes, 490 LPWAVEFORMATEX pwfx ) 491 { 492 MMTIME mmtime; 493 MMRESULT rc; 494 DWORD returned; 495 496 mmtime.wType = TIME_BYTES; 497 rc=waveOutGetPosition(wout, &mmtime, sizeof(mmtime) - 1); 498 ok(rc==MMSYSERR_ERROR, 499 "waveOutGetPosition(%s): rc=%s\n",dev_name(device),wave_out_error(rc)); 500 501 mmtime.wType = TIME_BYTES; 502 rc=waveOutGetPosition(wout, &mmtime, sizeof(mmtime) + 1); 503 ok(rc==MMSYSERR_NOERROR, 504 "waveOutGetPosition(%s): rc=%s\n",dev_name(device),wave_out_error(rc)); 505 if (mmtime.wType != TIME_BYTES && winetest_debug > 1) 506 trace("waveOutGetPosition(%s): TIME_BYTES not supported, returned %s\n", 507 dev_name(device),wave_time_format(mmtime.wType)); 508 returned = time_to_bytes(&mmtime, pwfx); 509 ok(returned == bytes, "waveOutGetPosition(%s): returned %d bytes, " 510 "should be %d\n", dev_name(device), returned, bytes); 511 512 mmtime.wType = TIME_SAMPLES; 513 rc=waveOutGetPosition(wout, &mmtime, sizeof(mmtime)); 514 ok(rc==MMSYSERR_NOERROR, 515 "waveOutGetPosition(%s): rc=%s\n",dev_name(device),wave_out_error(rc)); 516 if (mmtime.wType != TIME_SAMPLES && winetest_debug > 1) 517 trace("waveOutGetPosition(%s): TIME_SAMPLES not supported, " 518 "returned %s\n",dev_name(device),wave_time_format(mmtime.wType)); 519 returned = time_to_bytes(&mmtime, pwfx); 520 ok(returned == bytes, "waveOutGetPosition(%s): returned %d samples " 521 "(%d bytes), should be %d (%d bytes)\n", dev_name(device), 522 bytes_to_samples(returned, pwfx), returned, 523 bytes_to_samples(bytes, pwfx), bytes); 524 525 mmtime.wType = TIME_MS; 526 rc=waveOutGetPosition(wout, &mmtime, sizeof(mmtime)); 527 ok(rc==MMSYSERR_NOERROR, 528 "waveOutGetPosition(%s): rc=%s\n",dev_name(device),wave_out_error(rc)); 529 if (mmtime.wType != TIME_MS && winetest_debug > 1) 530 trace("waveOutGetPosition(%s): TIME_MS not supported, returned %s\n", 531 dev_name(device), wave_time_format(mmtime.wType)); 532 returned = time_to_bytes(&mmtime, pwfx); 533 ok(returned == bytes, "waveOutGetPosition(%s): returned %d ms, " 534 "(%d bytes), should be %d (%d bytes)\n", dev_name(device), 535 bytes_to_ms(returned, pwfx), returned, 536 bytes_to_ms(bytes, pwfx), bytes); 537 538 mmtime.wType = TIME_SMPTE; 539 rc=waveOutGetPosition(wout, &mmtime, sizeof(mmtime)); 540 ok(rc==MMSYSERR_NOERROR, 541 "waveOutGetPosition(%s): rc=%s\n",dev_name(device),wave_out_error(rc)); 542 if (mmtime.wType != TIME_SMPTE && winetest_debug > 1) 543 trace("waveOutGetPosition(%s): TIME_SMPTE not supported, returned %s\n", 544 dev_name(device),wave_time_format(mmtime.wType)); 545 returned = time_to_bytes(&mmtime, pwfx); 546 ok(returned == bytes, "waveOutGetPosition(%s): SMPTE test failed\n", 547 dev_name(device)); 548 549 mmtime.wType = TIME_MIDI; 550 rc=waveOutGetPosition(wout, &mmtime, sizeof(mmtime)); 551 ok(rc==MMSYSERR_NOERROR, 552 "waveOutGetPosition(%s): rc=%s\n",dev_name(device),wave_out_error(rc)); 553 if (mmtime.wType != TIME_MIDI && winetest_debug > 1) 554 trace("waveOutGetPosition(%s): TIME_MIDI not supported, returned %s\n", 555 dev_name(device),wave_time_format(mmtime.wType)); 556 returned = time_to_bytes(&mmtime, pwfx); 557 ok(returned == bytes, "waveOutGetPosition(%s): MIDI test failed\n", 558 dev_name(device)); 559 560 mmtime.wType = TIME_TICKS; 561 rc=waveOutGetPosition(wout, &mmtime, sizeof(mmtime)); 562 ok(rc==MMSYSERR_NOERROR, 563 "waveOutGetPosition(%s): rc=%s\n",dev_name(device),wave_out_error(rc)); 564 if (mmtime.wType != TIME_TICKS && winetest_debug > 1) 565 trace("waveOutGetPosition(%s): TIME_TICKS not supported, returned %s\n", 566 dev_name(device),wave_time_format(mmtime.wType)); 567 returned = time_to_bytes(&mmtime, pwfx); 568 ok(returned == bytes, "waveOutGetPosition(%s): TICKS test failed\n", 569 dev_name(device)); 570 } 571 572 static void CALLBACK callback_func(HWAVEOUT hwo, UINT uMsg, 573 DWORD_PTR dwInstance, 574 DWORD dwParam1, DWORD dwParam2) 575 { 576 if(uMsg == WOM_OPEN || uMsg == WOM_CLOSE) 577 ok(GetCurrentThreadId() == g_tid, "Got different thread ID\n"); 578 SetEvent((HANDLE)dwInstance); 579 } 580 581 static DWORD WINAPI callback_thread(LPVOID lpParameter) 582 { 583 MSG msg; 584 585 PeekMessageW( &msg, 0, 0, 0, PM_NOREMOVE ); /* make sure the thread has a message queue */ 586 SetEvent(lpParameter); 587 588 while (GetMessageA(&msg, 0, 0, 0)) { 589 UINT message = msg.message; 590 /* for some reason XP sends a WM_USER message before WOM_OPEN */ 591 ok (message == WOM_OPEN || message == WOM_DONE || 592 message == WOM_CLOSE || message == WM_USER || message == WM_APP, 593 "GetMessageA returned unexpected message: %u\n", message); 594 if (message == WOM_OPEN || message == WOM_DONE || message == WOM_CLOSE) 595 SetEvent(lpParameter); 596 else if (message == WM_APP) { 597 SetEvent(lpParameter); 598 return 0; 599 } 600 } 601 602 return 0; 603 } 604 605 static void wave_out_test_deviceOut(int device, double duration, int headers, int loops, 606 WAVEFORMATEX *pwfx, DWORD format, DWORD flags, WAVEOUTCAPSA *pcaps, BOOL interactive, 607 BOOL sine, BOOL pause) 608 { 609 HWAVEOUT wout; 610 HANDLE hevent = CreateEventW(NULL, FALSE, FALSE, NULL); 611 WAVEHDR *frags = 0; 612 MMRESULT rc; 613 DWORD volume; 614 WORD nChannels = pwfx->nChannels; 615 WORD wBitsPerSample = pwfx->wBitsPerSample; 616 DWORD nSamplesPerSec = pwfx->nSamplesPerSec; 617 BOOL has_volume = (pcaps->dwSupport & WAVECAPS_VOLUME) != 0; 618 double paused = 0.0; 619 DWORD_PTR callback = 0; 620 DWORD_PTR callback_instance = 0; 621 HANDLE thread = 0; 622 DWORD thread_id; 623 char * buffer; 624 DWORD length; 625 DWORD frag_length; 626 int i, j; 627 628 if ((flags & CALLBACK_TYPEMASK) == CALLBACK_EVENT) { 629 callback = (DWORD_PTR)hevent; 630 callback_instance = 0; 631 } else if ((flags & CALLBACK_TYPEMASK) == CALLBACK_FUNCTION) { 632 callback = (DWORD_PTR)callback_func; 633 callback_instance = (DWORD_PTR)hevent; 634 } else if ((flags & CALLBACK_TYPEMASK) == CALLBACK_THREAD) { 635 thread = CreateThread(NULL, 0, callback_thread, hevent, 0, &thread_id); 636 if (thread) { 637 /* make sure thread is running */ 638 WaitForSingleObject(hevent,10000); 639 callback = thread_id; 640 callback_instance = 0; 641 } else { 642 trace("CreateThread() failed\n"); 643 CloseHandle(hevent); 644 return; 645 } 646 } else if ((flags & CALLBACK_TYPEMASK) == CALLBACK_WINDOW) { 647 trace("CALLBACK_THREAD not implemented\n"); 648 CloseHandle(hevent); 649 return; 650 } else if (flags & CALLBACK_TYPEMASK) { 651 trace("Undefined callback type!\n"); 652 CloseHandle(hevent); 653 return; 654 } else { 655 trace("CALLBACK_NULL not implemented\n"); 656 CloseHandle(hevent); 657 return; 658 } 659 wout=NULL; 660 g_tid = GetCurrentThreadId(); 661 rc=waveOutOpen(&wout,device,pwfx,callback,callback_instance,flags); 662 /* Note: Win9x doesn't know WAVE_FORMAT_DIRECT */ 663 /* It is acceptable to fail on formats that are not specified to work */ 664 ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID || 665 rc==MMSYSERR_NOTENABLED || rc==MMSYSERR_NODRIVER || 666 rc==MMSYSERR_ALLOCATED || 667 ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) && 668 (flags & WAVE_FORMAT_DIRECT) && !(pcaps->dwFormats & format)) || 669 ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) && 670 (!(flags & WAVE_FORMAT_DIRECT) || (flags & WAVE_MAPPED)) && 671 !(pcaps->dwFormats & format)) || 672 (rc==MMSYSERR_INVALFLAG && (flags & WAVE_FORMAT_DIRECT)), 673 "waveOutOpen(%s): format=%dx%2dx%d flags=%x(%s) rc=%s\n", 674 dev_name(device),pwfx->nSamplesPerSec,pwfx->wBitsPerSample, 675 pwfx->nChannels,CALLBACK_EVENT|flags, 676 wave_open_flags(CALLBACK_EVENT|flags),wave_out_error(rc)); 677 if ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) && 678 (flags & WAVE_FORMAT_DIRECT) && (pcaps->dwFormats & format)) 679 trace(" Reason: The device lists this format as supported in its " 680 "capabilities but opening it failed.\n"); 681 if ((rc==WAVERR_BADFORMAT || rc==MMSYSERR_NOTSUPPORTED) && 682 !(pcaps->dwFormats & format)) 683 trace("waveOutOpen(%s): format=%dx%2dx%d %s rc=%s failed but format " 684 "not supported so OK.\n", dev_name(device), pwfx->nSamplesPerSec, 685 pwfx->wBitsPerSample,pwfx->nChannels, 686 flags & WAVE_FORMAT_DIRECT ? "flags=WAVE_FORMAT_DIRECT" : 687 flags & WAVE_MAPPED ? "flags=WAVE_MAPPED" : "", mmsys_error(rc)); 688 if (rc!=MMSYSERR_NOERROR) 689 goto EXIT; 690 691 rc=WaitForSingleObject(hevent,9000); 692 ok(rc==WAIT_OBJECT_0, "missing WOM_OPEN notification\n"); 693 694 ok(pwfx->nChannels==nChannels && 695 pwfx->wBitsPerSample==wBitsPerSample && 696 pwfx->nSamplesPerSec==nSamplesPerSec, 697 "got the wrong format: %dx%2dx%d instead of %dx%2dx%d\n", 698 pwfx->nSamplesPerSec, pwfx->wBitsPerSample, 699 pwfx->nChannels, nSamplesPerSec, wBitsPerSample, nChannels); 700 701 frags = HeapAlloc(GetProcessHeap(), 0, headers * sizeof(WAVEHDR)); 702 703 if (sine) 704 buffer=wave_generate_la(pwfx,duration / (loops + 1),&length); 705 else 706 buffer=wave_generate_silence(pwfx,duration / (loops + 1),&length); 707 708 rc=waveOutGetVolume(wout,0); 709 ok(rc==MMSYSERR_INVALPARAM,"waveOutGetVolume(%s,0) expected " 710 "MMSYSERR_INVALPARAM, got %s\n", dev_name(device),wave_out_error(rc)); 711 rc=waveOutGetVolume(wout,&volume); 712 if (rc == MMSYSERR_NOTSUPPORTED) has_volume = FALSE; 713 ok(has_volume ? rc==MMSYSERR_NOERROR : rc==MMSYSERR_NOTSUPPORTED, 714 "waveOutGetVolume(%s): rc=%s\n",dev_name(device),wave_out_error(rc)); 715 716 /* make sure fragment length is a multiple of block size */ 717 frag_length = ((length / headers) / pwfx->nBlockAlign) * pwfx->nBlockAlign; 718 719 for (i = 0; i < headers; i++) { 720 frags[i].lpData=buffer + (i * frag_length); 721 if (i != (headers-1)) 722 frags[i].dwBufferLength=frag_length; 723 else { 724 /* use remainder of buffer for last fragment */ 725 frags[i].dwBufferLength=length - (i * frag_length); 726 } 727 frags[i].dwFlags=0; 728 frags[i].dwLoops=0; 729 rc=waveOutPrepareHeader(wout, &frags[i], sizeof(frags[0])); 730 ok(rc==MMSYSERR_NOERROR, 731 "waveOutPrepareHeader(%s): rc=%s\n",dev_name(device),wave_out_error(rc)); 732 } 733 734 if (interactive && rc==MMSYSERR_NOERROR) { 735 trace("Playing %g second %s at %5dx%2dx%d %2d header%s %d loop%s %d bytes %s %s\n",duration, 736 sine ? "440 Hz tone" : "silence", pwfx->nSamplesPerSec, 737 pwfx->wBitsPerSample,pwfx->nChannels, headers, headers > 1 ? "s": " ", 738 loops, loops == 1 ? " " : "s", length * (loops + 1), 739 get_format_str(pwfx->wFormatTag), 740 wave_open_flags(flags)); 741 if (sine && has_volume && volume == 0) 742 trace("*** Warning the sound is muted, you will not hear the test\n"); 743 744 /* Check that the position is 0 at start */ 745 check_position(device, wout, 0, pwfx); 746 747 rc=waveOutSetVolume(wout,0x20002000); 748 ok(has_volume ? rc==MMSYSERR_NOERROR : rc==MMSYSERR_NOTSUPPORTED, 749 "waveOutSetVolume(%s): rc=%s\n",dev_name(device),wave_out_error(rc)); 750 751 rc=waveOutSetVolume(wout,volume); 752 ok(has_volume ? rc==MMSYSERR_NOERROR : rc==MMSYSERR_NOTSUPPORTED, 753 "waveOutSetVolume(%s): rc=%s\n",dev_name(device),wave_out_error(rc)); 754 755 rc=waveOutWrite(wout, &frags[0], sizeof(frags[0])); 756 ok(rc==MMSYSERR_NOERROR,"waveOutWrite(%s): rc=%s\n", 757 dev_name(device),wave_out_error(rc)); 758 759 ok(frags[0].dwFlags==(WHDR_PREPARED|WHDR_INQUEUE), 760 "WHDR_INQUEUE WHDR_PREPARED expected, got= %s\n", 761 wave_header_flags(frags[0].dwFlags)); 762 763 rc=waveOutWrite(wout, &frags[0], sizeof(frags[0])); 764 ok(rc==WAVERR_STILLPLAYING, 765 "waveOutWrite(%s): WAVE_STILLPLAYING expected, got %s\n", 766 dev_name(device),wave_out_error(rc)); 767 768 ok(frags[0].dwFlags==(WHDR_PREPARED|WHDR_INQUEUE), 769 "WHDR_INQUEUE WHDR_PREPARED expected, got %s\n", 770 wave_header_flags(frags[0].dwFlags)); 771 772 if (headers == 1 && loops == 0 && pause) { 773 paused = duration / 2; 774 Sleep(paused * 1000); 775 rc=waveOutPause(wout); 776 ok(rc==MMSYSERR_NOERROR,"waveOutPause(%s): rc=%s\n", 777 dev_name(device),wave_out_error(rc)); 778 trace("pausing for %g seconds\n", paused); 779 Sleep(paused * 1000); 780 rc=waveOutRestart(wout); 781 ok(rc==MMSYSERR_NOERROR,"waveOutRestart(%s): rc=%s\n", 782 dev_name(device),wave_out_error(rc)); 783 } 784 785 for (j = 0; j <= loops; j++) { 786 for (i = 0; i < headers; i++) { 787 /* don't do last one */ 788 if (!((j == loops) && (i == (headers - 1)))) { 789 if (j > 0) 790 frags[(i+1) % headers].dwFlags = WHDR_PREPARED; 791 rc=waveOutWrite(wout, &frags[(i+1) % headers], sizeof(frags[0])); 792 ok(rc==MMSYSERR_NOERROR,"waveOutWrite(%s, header[%d]): rc=%s\n", 793 dev_name(device),(i+1)%headers,wave_out_error(rc)); 794 } 795 rc=WaitForSingleObject(hevent,8000); 796 ok(rc==WAIT_OBJECT_0, "missing WOM_DONE notification\n"); 797 } 798 } 799 800 for (i = 0; i < headers; i++) { 801 ok(frags[i].dwFlags==(WHDR_DONE|WHDR_PREPARED) || 802 broken((flags & CALLBACK_TYPEMASK)==CALLBACK_EVENT && 803 frags[i].dwFlags==(WHDR_DONE|WHDR_PREPARED|0x1000)), /* < NT4 */ 804 "(%02d) WHDR_DONE WHDR_PREPARED expected, got %s\n", 805 i, wave_header_flags(frags[i].dwFlags)); 806 } 807 check_position(device, wout, length * (loops + 1), pwfx); 808 } 809 810 for (i = 0; i < headers; i++) { 811 rc=waveOutUnprepareHeader(wout, &frags[i], sizeof(frags[0])); 812 ok(rc==MMSYSERR_NOERROR, 813 "waveOutUnprepareHeader(%s): rc=%s\n",dev_name(device), 814 wave_out_error(rc)); 815 } 816 817 ok(frags[0].dwFlags==(interactive ? WHDR_DONE : 0), "dwFlags(%d)=%x\n",device,frags[0].dwFlags); 818 819 frags[0].dwFlags |= WHDR_DONE; 820 rc=waveOutUnprepareHeader(wout, &frags[0], sizeof(frags[0])); 821 ok(rc==MMSYSERR_NOERROR, "waveOutUnprepareHeader(%d): rc=%s\n",device,wave_out_error(rc)); 822 ok(frags[0].dwFlags==WHDR_DONE, "dwFlags(%d)=%x\n",device,frags[0].dwFlags); 823 824 frags[0].dwFlags |= WHDR_INQUEUE; 825 rc=waveOutPrepareHeader(wout, &frags[0], sizeof(frags[0])); 826 ok(rc==MMSYSERR_NOERROR, "waveOutPrepareHeader(%d): rc=%s\n",device,wave_out_error(rc)); 827 ok(frags[0].dwFlags==WHDR_PREPARED, "dwFlags(%d)=%x\n",device,frags[0].dwFlags); 828 829 frags[0].dwFlags |= WHDR_INQUEUE; 830 rc=waveOutPrepareHeader(wout, &frags[0], sizeof(frags[0])); 831 ok(rc==MMSYSERR_NOERROR, "waveOutPrepareHeader(%d): rc=%s\n",device,wave_out_error(rc)); 832 ok(frags[0].dwFlags==(WHDR_PREPARED|WHDR_INQUEUE), "dwFlags(%d)=%x\n",device,frags[0].dwFlags); 833 834 frags[0].dwFlags &= ~(WHDR_INQUEUE|WHDR_DONE); 835 rc=waveOutUnprepareHeader(wout, &frags[0], sizeof(frags[0])); 836 ok(rc==MMSYSERR_NOERROR, "waveOutUnprepareHeader(%d): rc=%s\n",device,wave_out_error(rc)); 837 ok(frags[0].dwFlags==0, "dwFlags(%d)=%x\n",device,frags[0].dwFlags); 838 839 rc=waveOutClose(wout); 840 ok(rc==MMSYSERR_NOERROR,"waveOutClose(%s): rc=%s\n",dev_name(device), 841 wave_out_error(rc)); 842 if (rc==WAVERR_STILLPLAYING) { 843 /* waveOutReset ought to return all buffers s.t. waveOutClose succeeds */ 844 rc=waveOutReset(wout); 845 ok(rc==MMSYSERR_NOERROR,"waveOutReset(%s): rc=%s\n",dev_name(device), 846 wave_out_error(rc)); 847 848 for (i = 0; i < headers; i++) { 849 rc=waveOutUnprepareHeader(wout, &frags[i], sizeof(frags[0])); 850 ok(rc==MMSYSERR_NOERROR, 851 "waveOutUnprepareHeader(%s): rc=%s\n",dev_name(device), 852 wave_out_error(rc)); 853 } 854 rc=waveOutClose(wout); 855 ok(rc==MMSYSERR_NOERROR,"waveOutClose(%s): rc=%s\n",dev_name(device), 856 wave_out_error(rc)); 857 } 858 rc=WaitForSingleObject(hevent,1500); 859 ok(rc==WAIT_OBJECT_0, "missing WOM_CLOSE notification\n"); 860 861 wout = (HWAVEOUT)0xdeadf00d; 862 rc=waveOutOpen(&wout,device,pwfx,callback,callback_instance,flags|WAVE_FORMAT_QUERY); 863 ok(rc==MMSYSERR_NOERROR, "WAVE_FORMAT_QUERY(%s): rc=%s\n",dev_name(device), 864 wave_out_error(rc)); 865 ok(wout==(HWAVEOUT)0xdeadf00d, "WAVE_FORMAT_QUERY handle %p\n", wout); 866 867 rc=WaitForSingleObject(hevent,20); 868 ok(rc==WAIT_TIMEOUT, "Notification from %s rc=%x\n", 869 wave_open_flags(flags|WAVE_FORMAT_QUERY),rc); 870 871 HeapFree(GetProcessHeap(), 0, buffer); 872 EXIT: 873 if ((flags & CALLBACK_TYPEMASK) == CALLBACK_THREAD) { 874 PostThreadMessageW(thread_id, WM_APP, 0, 0); 875 WaitForSingleObject(hevent,10000); 876 } 877 CloseHandle(hevent); 878 HeapFree(GetProcessHeap(), 0, frags); 879 } 880 881 static void wave_out_test_device(UINT_PTR device) 882 { 883 WAVEOUTCAPSA capsA; 884 WAVEOUTCAPSW capsW; 885 WAVEFORMATEX format; 886 WAVEFORMATEXTENSIBLE wfex; 887 IMAADPCMWAVEFORMAT wfa; 888 HWAVEOUT wout; 889 MMRESULT rc; 890 UINT f; 891 WCHAR * nameW; 892 CHAR * nameA; 893 DWORD size; 894 DWORD dwPageSize; 895 BYTE * twoPages; 896 SYSTEM_INFO sSysInfo; 897 DWORD flOldProtect; 898 BOOL res; 899 900 GetSystemInfo(&sSysInfo); 901 dwPageSize = sSysInfo.dwPageSize; 902 903 rc=waveOutGetDevCapsA(device,&capsA,sizeof(capsA)); 904 ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID || 905 rc==MMSYSERR_NODRIVER, 906 "waveOutGetDevCapsA(%s): failed to get capabilities: rc=%s\n", 907 dev_name(device),wave_out_error(rc)); 908 if (rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NODRIVER) 909 return; 910 911 rc=waveOutGetDevCapsW(device,&capsW,sizeof(capsW)); 912 ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NOTSUPPORTED, 913 "waveOutGetDevCapsW(%s): MMSYSERR_NOERROR or MMSYSERR_NOTSUPPORTED " 914 "expected, got %s\n",dev_name(device),wave_out_error(rc)); 915 916 rc=waveOutGetDevCapsA(device,0,sizeof(capsA)); 917 ok(rc==MMSYSERR_INVALPARAM, 918 "waveOutGetDevCapsA(%s): MMSYSERR_INVALPARAM expected, " 919 "got %s\n",dev_name(device),wave_out_error(rc)); 920 921 rc=waveOutGetDevCapsW(device,0,sizeof(capsW)); 922 ok(rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_NOTSUPPORTED, 923 "waveOutGetDevCapsW(%s): MMSYSERR_INVALPARAM or MMSYSERR_NOTSUPPORTED " 924 "expected, got %s\n",dev_name(device),wave_out_error(rc)); 925 926 if (0) 927 { 928 /* FIXME: this works on windows but crashes wine */ 929 rc=waveOutGetDevCapsA(device,(LPWAVEOUTCAPSA)1,sizeof(capsA)); 930 ok(rc==MMSYSERR_INVALPARAM, 931 "waveOutGetDevCapsA(%s): MMSYSERR_INVALPARAM expected, got %s\n", 932 dev_name(device),wave_out_error(rc)); 933 934 rc=waveOutGetDevCapsW(device,(LPWAVEOUTCAPSW)1,sizeof(capsW)); 935 ok(rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_NOTSUPPORTED, 936 "waveOutGetDevCapsW(%s): MMSYSERR_INVALPARAM or MMSYSERR_NOTSUPPORTED " 937 "expected, got %s\n",dev_name(device),wave_out_error(rc)); 938 } 939 940 rc=waveOutGetDevCapsA(device,&capsA,4); 941 ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_INVALPARAM, 942 "waveOutGetDevCapsA(%s): MMSYSERR_NOERROR or MMSYSERR_INVALPARAM " 943 "expected, got %s\n", dev_name(device),wave_out_error(rc)); 944 945 rc=waveOutGetDevCapsW(device,&capsW,4); 946 ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NOTSUPPORTED || 947 rc==MMSYSERR_INVALPARAM, /* Vista, W2K8 */ 948 "waveOutGetDevCapsW(%s): unexpected return value %s\n", 949 dev_name(device),wave_out_error(rc)); 950 951 rc=waveOutMessage((HWAVEOUT)device, DRV_QUERYMAPPABLE, 0, 0); 952 ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NOTSUPPORTED, 953 "DRV_QUERYMAPPABLE(%s): unexpected return value %s\n", 954 dev_name(device),wave_out_error(rc)); 955 956 nameA=NULL; 957 rc=waveOutMessage((HWAVEOUT)device, DRV_QUERYDEVICEINTERFACESIZE, 958 (DWORD_PTR)&size, 0); 959 ok(rc==MMSYSERR_NOERROR || broken(rc==MMSYSERR_INVALPARAM || 960 rc==MMSYSERR_NOTSUPPORTED), 961 "waveOutMessage(%s): failed to get interface size, rc=%s\n", 962 dev_name(device),wave_out_error(rc)); 963 if (rc==MMSYSERR_NOERROR) { 964 nameW = HeapAlloc(GetProcessHeap(), 0, size); 965 rc=waveOutMessage((HWAVEOUT)device, DRV_QUERYDEVICEINTERFACE, 966 (DWORD_PTR)nameW, size); 967 ok(rc==MMSYSERR_NOERROR,"waveOutMessage(%s): failed to get interface " 968 "name, rc=%s\n",dev_name(device),wave_out_error(rc)); 969 ok(lstrlenW(nameW)+1==size/sizeof(WCHAR),"got an incorrect size %d\n",size); 970 if (rc==MMSYSERR_NOERROR) { 971 nameA = HeapAlloc(GetProcessHeap(), 0, size/sizeof(WCHAR)); 972 WideCharToMultiByte(CP_ACP, 0, nameW, size/sizeof(WCHAR), nameA, 973 size/sizeof(WCHAR), NULL, NULL); 974 } 975 HeapFree(GetProcessHeap(), 0, nameW); 976 } 977 else if (rc==MMSYSERR_NOTSUPPORTED) { 978 nameA=HeapAlloc(GetProcessHeap(), 0, sizeof("not supported")); 979 strcpy(nameA, "not supported"); 980 } 981 982 rc=waveOutGetDevCapsA(device,&capsA,sizeof(capsA)); 983 ok(rc==MMSYSERR_NOERROR, 984 "waveOutGetDevCapsA(%s): MMSYSERR_NOERROR expected, got %s\n", 985 dev_name(device),wave_out_error(rc)); 986 if (rc!=MMSYSERR_NOERROR) 987 { 988 HeapFree(GetProcessHeap(), 0, nameA); 989 return; 990 } 991 992 trace(" %s: \"%s\" (%s) %d.%d (%d:%d)\n",dev_name(device),capsA.szPname, 993 (nameA?nameA:"failed"),capsA.vDriverVersion >> 8, 994 capsA.vDriverVersion & 0xff, capsA.wMid,capsA.wPid); 995 trace(" channels=%d formats=%05x support=%04x\n", 996 capsA.wChannels,capsA.dwFormats,capsA.dwSupport); 997 trace(" %s\n",wave_out_caps(capsA.dwSupport)); 998 HeapFree(GetProcessHeap(), 0, nameA); 999 1000 if (winetest_interactive && (device != WAVE_MAPPER)) 1001 { 1002 trace("Playing a 5 seconds reference tone.\n"); 1003 trace("All subsequent tones should be identical to this one.\n"); 1004 trace("Listen for stutter, changes in pitch, volume, etc.\n"); 1005 format.wFormatTag=WAVE_FORMAT_PCM; 1006 format.nChannels=1; 1007 format.wBitsPerSample=8; 1008 format.nSamplesPerSec=22050; 1009 format.nBlockAlign=format.nChannels*format.wBitsPerSample/8; 1010 format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign; 1011 format.cbSize=0; 1012 1013 wave_out_test_deviceOut(device,5.0,1,0,&format,WAVE_FORMAT_2M08, 1014 CALLBACK_EVENT,&capsA,TRUE,TRUE,FALSE); 1015 wave_out_test_deviceOut(device,5.0,1,0,&format,WAVE_FORMAT_2M08, 1016 CALLBACK_FUNCTION,&capsA,TRUE,TRUE,FALSE); 1017 wave_out_test_deviceOut(device,5.0,1,0,&format,WAVE_FORMAT_2M08, 1018 CALLBACK_THREAD,&capsA,TRUE,TRUE,FALSE); 1019 1020 wave_out_test_deviceOut(device,5.0,10,0,&format,WAVE_FORMAT_2M08, 1021 CALLBACK_EVENT,&capsA,TRUE,TRUE,FALSE); 1022 wave_out_test_deviceOut(device,5.0,5,1,&format,WAVE_FORMAT_2M08, 1023 CALLBACK_EVENT,&capsA,TRUE,TRUE,FALSE); 1024 } else { 1025 format.wFormatTag=WAVE_FORMAT_PCM; 1026 format.nChannels=1; 1027 format.wBitsPerSample=8; 1028 format.nSamplesPerSec=22050; 1029 format.nBlockAlign=format.nChannels*format.wBitsPerSample/8; 1030 format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign; 1031 format.cbSize=0; 1032 wave_out_test_deviceOut(device,0.6,1,0,&format,WAVE_FORMAT_2M08, 1033 CALLBACK_EVENT,&capsA,TRUE,FALSE,FALSE); 1034 wave_out_test_deviceOut(device,0.6,1,0,&format,WAVE_FORMAT_2M08, 1035 CALLBACK_EVENT,&capsA,TRUE,FALSE,TRUE); 1036 wave_out_test_deviceOut(device,0.6,1,0,&format,WAVE_FORMAT_2M08, 1037 CALLBACK_FUNCTION,&capsA,TRUE,FALSE,FALSE); 1038 wave_out_test_deviceOut(device,0.6,1,0,&format,WAVE_FORMAT_2M08, 1039 CALLBACK_FUNCTION,&capsA,TRUE,FALSE,TRUE); 1040 wave_out_test_deviceOut(device,0.6,1,0,&format,WAVE_FORMAT_2M08, 1041 CALLBACK_THREAD,&capsA,TRUE,FALSE,FALSE); 1042 wave_out_test_deviceOut(device,0.6,1,0,&format,WAVE_FORMAT_2M08, 1043 CALLBACK_THREAD,&capsA,TRUE,FALSE,TRUE); 1044 1045 wave_out_test_deviceOut(device,0.8,10,0,&format,WAVE_FORMAT_2M08, 1046 CALLBACK_EVENT,&capsA,TRUE,FALSE,FALSE); 1047 wave_out_test_deviceOut(device,1.0,5,1,&format,WAVE_FORMAT_2M08, 1048 CALLBACK_EVENT,&capsA,TRUE,FALSE,FALSE); 1049 } 1050 1051 for (f=0;f<NB_WIN_FORMATS;f++) { 1052 format.wFormatTag=WAVE_FORMAT_PCM; 1053 format.nChannels=win_formats[f][3]; 1054 format.wBitsPerSample=win_formats[f][2]; 1055 format.nSamplesPerSec=win_formats[f][1]; 1056 format.nBlockAlign=format.nChannels*format.wBitsPerSample/8; 1057 format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign; 1058 format.cbSize=0; 1059 wave_out_test_deviceOut(device,1.0,1,0,&format,win_formats[f][0], 1060 CALLBACK_EVENT,&capsA,winetest_interactive, 1061 TRUE,FALSE); 1062 wave_out_test_deviceOut(device,1.0,1,0,&format,win_formats[f][0], 1063 CALLBACK_FUNCTION,&capsA,winetest_interactive, 1064 TRUE,FALSE); 1065 wave_out_test_deviceOut(device,1.0,1,0,&format,win_formats[f][0], 1066 CALLBACK_THREAD,&capsA,winetest_interactive, 1067 TRUE,FALSE); 1068 1069 wave_out_test_deviceOut(device,1.0,10,0,&format,win_formats[f][0], 1070 CALLBACK_EVENT,&capsA,winetest_interactive, 1071 TRUE,FALSE); 1072 wave_out_test_deviceOut(device,1.0,5,1,&format,win_formats[f][0], 1073 CALLBACK_EVENT,&capsA,winetest_interactive, 1074 TRUE,FALSE); 1075 1076 if (winetest_interactive) { 1077 wave_out_test_deviceOut(device,1.0,1,0,&format,win_formats[f][0], 1078 CALLBACK_EVENT,&capsA,winetest_interactive, 1079 TRUE,TRUE); 1080 wave_out_test_deviceOut(device,1.0,1,0,&format,win_formats[f][0], 1081 CALLBACK_FUNCTION,&capsA,winetest_interactive, 1082 TRUE,TRUE); 1083 wave_out_test_deviceOut(device,1.0,1,0,&format,win_formats[f][0], 1084 CALLBACK_THREAD,&capsA,winetest_interactive, 1085 TRUE,TRUE); 1086 1087 wave_out_test_deviceOut(device,1.0,10,0,&format,win_formats[f][0], 1088 CALLBACK_EVENT,&capsA,winetest_interactive, 1089 TRUE,TRUE); 1090 wave_out_test_deviceOut(device,1.0,5,1,&format,win_formats[f][0], 1091 CALLBACK_EVENT,&capsA,winetest_interactive, 1092 TRUE,TRUE); 1093 } 1094 if (device != WAVE_MAPPER) 1095 { 1096 wave_out_test_deviceOut(device,1.0,1,0,&format,win_formats[f][0], 1097 CALLBACK_EVENT|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_EVENT|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_FUNCTION|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_FUNCTION|WAVE_MAPPED,&capsA, 1107 winetest_interactive,TRUE,FALSE); 1108 wave_out_test_deviceOut(device,1.0,1,0,&format,win_formats[f][0], 1109 CALLBACK_THREAD|WAVE_FORMAT_DIRECT,&capsA, 1110 winetest_interactive,TRUE,FALSE); 1111 wave_out_test_deviceOut(device,1.0,1,0,&format,win_formats[f][0], 1112 CALLBACK_THREAD|WAVE_MAPPED,&capsA, 1113 winetest_interactive,TRUE,FALSE); 1114 1115 wave_out_test_deviceOut(device,1.0,10,0,&format,win_formats[f][0], 1116 CALLBACK_EVENT|WAVE_FORMAT_DIRECT,&capsA, 1117 winetest_interactive,TRUE,FALSE); 1118 wave_out_test_deviceOut(device,1.0,5,1,&format,win_formats[f][0], 1119 CALLBACK_EVENT|WAVE_FORMAT_DIRECT,&capsA, 1120 winetest_interactive,TRUE,FALSE); 1121 } 1122 } 1123 1124 /* Try a PCMWAVEFORMAT aligned next to an unaccessible page for bounds 1125 * checking */ 1126 twoPages = VirtualAlloc(NULL, 2 * dwPageSize, MEM_RESERVE | MEM_COMMIT, 1127 PAGE_READWRITE); 1128 ok(twoPages!=NULL,"Failed to allocate 2 pages of memory\n"); 1129 if (twoPages) { 1130 res = VirtualProtect(twoPages + dwPageSize, dwPageSize, PAGE_NOACCESS, 1131 &flOldProtect); 1132 ok(res, "Failed to set memory access on second page\n"); 1133 if (res) { 1134 LPWAVEFORMATEX pwfx = (LPWAVEFORMATEX)(twoPages + dwPageSize - 1135 sizeof(PCMWAVEFORMAT)); 1136 pwfx->wFormatTag=WAVE_FORMAT_PCM; 1137 pwfx->nChannels=1; 1138 pwfx->wBitsPerSample=8; 1139 pwfx->nSamplesPerSec=22050; 1140 pwfx->nBlockAlign=pwfx->nChannels*pwfx->wBitsPerSample/8; 1141 pwfx->nAvgBytesPerSec=pwfx->nSamplesPerSec*pwfx->nBlockAlign; 1142 wave_out_test_deviceOut(device,1.0,1,0,pwfx,WAVE_FORMAT_2M08, 1143 CALLBACK_EVENT,&capsA,winetest_interactive, 1144 TRUE,FALSE); 1145 wave_out_test_deviceOut(device,1.0,10,0,pwfx,WAVE_FORMAT_2M08, 1146 CALLBACK_EVENT,&capsA,winetest_interactive, 1147 TRUE,FALSE); 1148 wave_out_test_deviceOut(device,1.0,5,1,pwfx,WAVE_FORMAT_2M08, 1149 CALLBACK_EVENT,&capsA,winetest_interactive, 1150 TRUE,FALSE); 1151 if (device != WAVE_MAPPER) 1152 { 1153 wave_out_test_deviceOut(device,1.0,1,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,1,0,pwfx,WAVE_FORMAT_2M08, 1157 CALLBACK_EVENT|WAVE_MAPPED,&capsA, 1158 winetest_interactive,TRUE,FALSE); 1159 wave_out_test_deviceOut(device,1.0,10,0,pwfx,WAVE_FORMAT_2M08, 1160 CALLBACK_EVENT|WAVE_FORMAT_DIRECT, 1161 &capsA,winetest_interactive,TRUE,FALSE); 1162 wave_out_test_deviceOut(device,1.0,10,0,pwfx,WAVE_FORMAT_2M08, 1163 CALLBACK_EVENT|WAVE_MAPPED,&capsA, 1164 winetest_interactive,TRUE,FALSE); 1165 wave_out_test_deviceOut(device,1.0,5,1,pwfx,WAVE_FORMAT_2M08, 1166 CALLBACK_EVENT|WAVE_FORMAT_DIRECT, 1167 &capsA,winetest_interactive,TRUE,FALSE); 1168 wave_out_test_deviceOut(device,1.0,5,1,pwfx,WAVE_FORMAT_2M08, 1169 CALLBACK_EVENT|WAVE_MAPPED,&capsA, 1170 winetest_interactive,TRUE,FALSE); 1171 } 1172 } 1173 VirtualFree(twoPages, 0, MEM_RELEASE); 1174 } 1175 1176 /* try some non PCM formats */ 1177 format.wFormatTag=WAVE_FORMAT_MULAW; 1178 format.nChannels=1; 1179 format.wBitsPerSample=8; 1180 format.nSamplesPerSec=8000; 1181 format.nBlockAlign=format.nChannels*format.wBitsPerSample/8; 1182 format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign; 1183 format.cbSize=0; 1184 rc=waveOutOpen(&wout,device,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT); 1185 ok(rc==MMSYSERR_NOERROR ||rc==WAVERR_BADFORMAT || 1186 rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM, 1187 "waveOutOpen(%s): returned %s\n",dev_name(device),wave_out_error(rc)); 1188 if (rc==MMSYSERR_NOERROR) { 1189 waveOutClose(wout); 1190 wave_out_test_deviceOut(device,1.0,1,0,&format,0,CALLBACK_EVENT, 1191 &capsA,winetest_interactive,TRUE,FALSE); 1192 wave_out_test_deviceOut(device,1.0,10,0,&format,0,CALLBACK_EVENT, 1193 &capsA,winetest_interactive,TRUE,FALSE); 1194 wave_out_test_deviceOut(device,1.0,5,1,&format,0,CALLBACK_EVENT, 1195 &capsA,winetest_interactive,TRUE,FALSE); 1196 } else { 1197 MMRESULT query_rc; 1198 1199 trace("waveOutOpen(%s): WAVE_FORMAT_MULAW not supported\n", 1200 dev_name(device)); 1201 1202 query_rc = waveOutOpen(NULL, device, &format, 0, 0, CALLBACK_NULL | WAVE_FORMAT_QUERY); 1203 ok(query_rc==MMSYSERR_NOERROR || query_rc==WAVERR_BADFORMAT || query_rc==MMSYSERR_INVALPARAM, 1204 "waveOutOpen(%s): returned %s\n",dev_name(device),wave_out_error(rc)); 1205 1206 rc = waveOutOpen(&wout, device, &format, 0, 0, CALLBACK_NULL); 1207 ok(rc == query_rc, 1208 "waveOutOpen(%s): returned different from query: %s\n",dev_name(device),wave_out_error(rc)); 1209 if(rc == MMSYSERR_NOERROR) 1210 waveOutClose(wout); 1211 } 1212 1213 wfa.wfx.wFormatTag=WAVE_FORMAT_IMA_ADPCM; 1214 wfa.wfx.nChannels=1; 1215 wfa.wfx.nSamplesPerSec=11025; 1216 wfa.wfx.nAvgBytesPerSec=5588; 1217 wfa.wfx.nBlockAlign=256; 1218 wfa.wfx.wBitsPerSample=4; /* see imaadp32.c */ 1219 wfa.wfx.cbSize=2; 1220 wfa.wSamplesPerBlock=505; 1221 rc=waveOutOpen(&wout,device,&wfa.wfx,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT); 1222 ok(rc==MMSYSERR_NOERROR ||rc==WAVERR_BADFORMAT || 1223 rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM, 1224 "waveOutOpen(%s): returned %s\n",dev_name(device),wave_out_error(rc)); 1225 if (rc==MMSYSERR_NOERROR) { 1226 waveOutClose(wout); 1227 /* TODO: teach wave_generate_* ADPCM 1228 wave_out_test_deviceOut(device,1.0,1,0,&wfa.wfx,0,CALLBACK_EVENT, 1229 &capsA,winetest_interactive,TRUE,FALSE); 1230 wave_out_test_deviceOut(device,1.0,10,0,&wfa.wfx,0,CALLBACK_EVENT, 1231 &capsA,winetest_interactive,TRUE,FALSE); 1232 wave_out_test_deviceOut(device,1.0,5,1,&wfa.wfx,0,CALLBACK_EVENT, 1233 &capsA,winetest_interactive,TRUE,FALSE); 1234 */ 1235 } else 1236 trace("waveOutOpen(%s): WAVE_FORMAT_IMA_ADPCM not supported\n", 1237 dev_name(device)); 1238 1239 /* test if WAVEFORMATEXTENSIBLE supported */ 1240 wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE; 1241 wfex.Format.nChannels=2; 1242 wfex.Format.wBitsPerSample=16; 1243 wfex.Format.nSamplesPerSec=22050; 1244 wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8; 1245 wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec* 1246 wfex.Format.nBlockAlign; 1247 wfex.Format.cbSize=22; 1248 wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample; 1249 wfex.dwChannelMask=SPEAKER_ALL; 1250 wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM; 1251 rc=waveOutOpen(&wout,device,&wfex.Format,0,0, 1252 CALLBACK_NULL|WAVE_FORMAT_DIRECT); 1253 ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT || 1254 rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM, 1255 "waveOutOpen(%s): returned %s\n",dev_name(device),wave_out_error(rc)); 1256 if (rc==MMSYSERR_NOERROR) { 1257 waveOutClose(wout); 1258 wave_out_test_deviceOut(device,1.0,1,0,&wfex.Format,WAVE_FORMAT_2M16, 1259 CALLBACK_EVENT,&capsA,winetest_interactive, 1260 TRUE,FALSE); 1261 wave_out_test_deviceOut(device,1.0,10,0,&wfex.Format,WAVE_FORMAT_2M16, 1262 CALLBACK_EVENT,&capsA,winetest_interactive, 1263 TRUE,FALSE); 1264 wave_out_test_deviceOut(device,1.0,5,1,&wfex.Format,WAVE_FORMAT_2M16, 1265 CALLBACK_EVENT,&capsA,winetest_interactive, 1266 TRUE,FALSE); 1267 } else 1268 trace("waveOutOpen(%s): WAVE_FORMAT_EXTENSIBLE not supported\n", 1269 dev_name(device)); 1270 1271 /* test if 4 channels supported */ 1272 wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE; 1273 wfex.Format.nChannels=4; 1274 wfex.Format.wBitsPerSample=16; 1275 wfex.Format.nSamplesPerSec=22050; 1276 wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8; 1277 wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec* 1278 wfex.Format.nBlockAlign; 1279 wfex.Format.cbSize=22; 1280 wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample; 1281 wfex.dwChannelMask=SPEAKER_ALL; 1282 wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM; 1283 rc=waveOutOpen(&wout,device,&wfex.Format,0,0, 1284 CALLBACK_NULL|WAVE_FORMAT_DIRECT); 1285 ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT || 1286 rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM, 1287 "waveOutOpen(%s): returned %s\n",dev_name(device),wave_out_error(rc)); 1288 if (rc==MMSYSERR_NOERROR) { 1289 waveOutClose(wout); 1290 wave_out_test_deviceOut(device,1.0,1,0,&wfex.Format,0,CALLBACK_EVENT, 1291 &capsA,winetest_interactive,TRUE,FALSE); 1292 wave_out_test_deviceOut(device,1.0,10,0,&wfex.Format,0,CALLBACK_EVENT, 1293 &capsA,winetest_interactive,TRUE,FALSE); 1294 wave_out_test_deviceOut(device,1.0,5,1,&wfex.Format,0,CALLBACK_EVENT, 1295 &capsA,winetest_interactive,TRUE,FALSE); 1296 } else 1297 trace("waveOutOpen(%s): 4 channels not supported\n", 1298 dev_name(device)); 1299 1300 /* test if 6 channels supported */ 1301 wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE; 1302 wfex.Format.nChannels=6; 1303 wfex.Format.wBitsPerSample=16; 1304 wfex.Format.nSamplesPerSec=22050; 1305 wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8; 1306 wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec* 1307 wfex.Format.nBlockAlign; 1308 wfex.Format.cbSize=22; 1309 wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample; 1310 wfex.dwChannelMask=SPEAKER_ALL; 1311 wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM; 1312 rc=waveOutOpen(&wout,device,&wfex.Format,0,0, 1313 CALLBACK_NULL|WAVE_FORMAT_DIRECT); 1314 ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT || 1315 rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM, 1316 "waveOutOpen(%s): returned %s\n",dev_name(device),wave_out_error(rc)); 1317 if (rc==MMSYSERR_NOERROR) { 1318 waveOutClose(wout); 1319 wave_out_test_deviceOut(device,1.0,1,0,&wfex.Format,WAVE_FORMAT_2M16, 1320 CALLBACK_EVENT,&capsA,winetest_interactive, 1321 TRUE,FALSE); 1322 wave_out_test_deviceOut(device,1.0,10,0,&wfex.Format,WAVE_FORMAT_2M16, 1323 CALLBACK_EVENT,&capsA,winetest_interactive, 1324 TRUE,FALSE); 1325 wave_out_test_deviceOut(device,1.0,5,1,&wfex.Format,WAVE_FORMAT_2M16, 1326 CALLBACK_EVENT,&capsA,winetest_interactive, 1327 TRUE,FALSE); 1328 } else 1329 trace("waveOutOpen(%s): 6 channels not supported\n", 1330 dev_name(device)); 1331 1332 if (0) 1333 { 1334 /* FIXME: ALSA doesn't like this format */ 1335 /* test if 24 bit samples supported */ 1336 wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE; 1337 wfex.Format.nChannels=2; 1338 wfex.Format.wBitsPerSample=24; 1339 wfex.Format.nSamplesPerSec=22050; 1340 wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8; 1341 wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec* 1342 wfex.Format.nBlockAlign; 1343 wfex.Format.cbSize=22; 1344 wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample; 1345 wfex.dwChannelMask=SPEAKER_ALL; 1346 wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM; 1347 rc=waveOutOpen(&wout,device,&wfex.Format,0,0, 1348 CALLBACK_NULL|WAVE_FORMAT_DIRECT); 1349 ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT || 1350 rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM, 1351 "waveOutOpen(%s): returned %s\n",dev_name(device),wave_out_error(rc)); 1352 if (rc==MMSYSERR_NOERROR) { 1353 waveOutClose(wout); 1354 wave_out_test_deviceOut(device,1.0,1,0,&wfex.Format,WAVE_FORMAT_2M16, 1355 CALLBACK_EVENT,&capsA,winetest_interactive, 1356 TRUE,FALSE); 1357 } else 1358 trace("waveOutOpen(%s): 24 bit samples not supported\n", 1359 dev_name(device)); 1360 } 1361 1362 /* test if 32 bit samples supported */ 1363 wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE; 1364 wfex.Format.nChannels=2; 1365 wfex.Format.wBitsPerSample=32; 1366 wfex.Format.nSamplesPerSec=22050; 1367 wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8; 1368 wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec* 1369 wfex.Format.nBlockAlign; 1370 wfex.Format.cbSize=22; 1371 wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample; 1372 wfex.dwChannelMask=SPEAKER_ALL; 1373 wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM; 1374 rc=waveOutOpen(&wout,device,&wfex.Format,0,0, 1375 CALLBACK_NULL|WAVE_FORMAT_DIRECT); 1376 ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT || 1377 rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM, 1378 "waveOutOpen(%s): returned %s\n",dev_name(device),wave_out_error(rc)); 1379 if (rc==MMSYSERR_NOERROR) { 1380 waveOutClose(wout); 1381 wave_out_test_deviceOut(device,1.0,1,0,&wfex.Format,WAVE_FORMAT_2M16, 1382 CALLBACK_EVENT,&capsA,winetest_interactive, 1383 TRUE,FALSE); 1384 wave_out_test_deviceOut(device,1.0,10,0,&wfex.Format,WAVE_FORMAT_2M16, 1385 CALLBACK_EVENT,&capsA,winetest_interactive, 1386 TRUE,FALSE); 1387 wave_out_test_deviceOut(device,1.0,5,1,&wfex.Format,WAVE_FORMAT_2M16, 1388 CALLBACK_EVENT,&capsA,winetest_interactive, 1389 TRUE,FALSE); 1390 } else 1391 trace("waveOutOpen(%s): 32 bit samples not supported\n", 1392 dev_name(device)); 1393 1394 /* test if 32 bit float samples supported */ 1395 wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE; 1396 wfex.Format.nChannels=2; 1397 wfex.Format.wBitsPerSample=32; 1398 wfex.Format.nSamplesPerSec=22050; 1399 wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8; 1400 wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec* 1401 wfex.Format.nBlockAlign; 1402 wfex.Format.cbSize=22; 1403 wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample; 1404 wfex.dwChannelMask=SPEAKER_ALL; 1405 wfex.SubFormat=KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; 1406 rc=waveOutOpen(&wout,device,&wfex.Format,0,0, 1407 CALLBACK_NULL|WAVE_FORMAT_DIRECT); 1408 ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT || 1409 rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM, 1410 "waveOutOpen(%s): returned %s\n",dev_name(device),wave_out_error(rc)); 1411 if (rc==MMSYSERR_NOERROR) { 1412 waveOutClose(wout); 1413 wave_out_test_deviceOut(device,1.0,1,0,&wfex.Format,WAVE_FORMAT_2M16, 1414 CALLBACK_EVENT,&capsA,winetest_interactive, 1415 TRUE,FALSE); 1416 wave_out_test_deviceOut(device,1.0,10,0,&wfex.Format,WAVE_FORMAT_2M16, 1417 CALLBACK_EVENT,&capsA,winetest_interactive, 1418 TRUE,FALSE); 1419 wave_out_test_deviceOut(device,1.0,5,1,&wfex.Format,WAVE_FORMAT_2M16, 1420 CALLBACK_EVENT,&capsA,winetest_interactive, 1421 TRUE,FALSE); 1422 } else 1423 trace("waveOutOpen(%s): 32 bit float samples not supported\n", 1424 dev_name(device)); 1425 } 1426 1427 static void wave_out_tests(void) 1428 { 1429 WAVEOUTCAPSA capsA; 1430 WAVEOUTCAPSW capsW; 1431 WAVEFORMATEX format; 1432 HWAVEOUT wout; 1433 MMRESULT rc; 1434 DWORD preferred, status; 1435 UINT ndev,d; 1436 1437 ndev=waveOutGetNumDevs(); 1438 trace("found %d WaveOut devices\n",ndev); 1439 1440 rc = waveOutMessage((HWAVEOUT)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, 1441 (DWORD_PTR)&preferred, (DWORD_PTR)&status); 1442 ok((ndev == 0 && (rc == MMSYSERR_NODRIVER || rc == MMSYSERR_BADDEVICEID)) || 1443 rc == MMSYSERR_NOTSUPPORTED || 1444 rc == MMSYSERR_NOERROR, "waveOutMessage(DRVM_MAPPER_PREFERRED_GET) failed: %u\n", rc); 1445 1446 if(rc != MMSYSERR_NOTSUPPORTED) 1447 ok((ndev == 0 && (preferred == -1 || broken(preferred != -1))) || 1448 preferred < ndev, "Got invalid preferred device: 0x%x\n", preferred); 1449 1450 rc=waveOutGetDevCapsA(ndev+1,&capsA,sizeof(capsA)); 1451 ok(rc==MMSYSERR_BADDEVICEID, 1452 "waveOutGetDevCapsA(%s): MMSYSERR_BADDEVICEID expected, got %s\n", 1453 dev_name(ndev+1),mmsys_error(rc)); 1454 1455 rc=waveOutGetDevCapsW(ndev+1,&capsW,sizeof(capsW)); 1456 ok(rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NOTSUPPORTED, 1457 "waveOutGetDevCapsW(%s): MMSYSERR_BADDEVICEID or MMSYSERR_NOTSUPPORTED " 1458 "expected, got %s\n",dev_name(ndev+1),mmsys_error(rc)); 1459 1460 rc=waveOutGetDevCapsA(WAVE_MAPPER,&capsA,sizeof(capsA)); 1461 if (ndev>0) 1462 ok(rc==MMSYSERR_NOERROR, 1463 "waveOutGetDevCapsA(%s): MMSYSERR_NOERROR expected, got %s\n", 1464 dev_name(WAVE_MAPPER),mmsys_error(rc)); 1465 else 1466 ok(rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NODRIVER, 1467 "waveOutGetDevCapsA(%s): MMSYSERR_BADDEVICEID or MMSYSERR_NODRIVER " 1468 "expected, got %s\n",dev_name(WAVE_MAPPER),mmsys_error(rc)); 1469 1470 rc=waveOutGetDevCapsW(WAVE_MAPPER,&capsW,sizeof(capsW)); 1471 if (ndev>0) 1472 ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NOTSUPPORTED, 1473 "waveOutGetDevCapsW(%s): MMSYSERR_NOERROR or MMSYSERR_NOTSUPPORTED " 1474 "expected, got %s\n",dev_name(WAVE_MAPPER),mmsys_error(rc)); 1475 else 1476 ok(rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NODRIVER || 1477 rc==MMSYSERR_NOTSUPPORTED, 1478 "waveOutGetDevCapsW(%s): MMSYSERR_BADDEVICEID or MMSYSERR_NODRIVER " 1479 " or MMSYSERR_NOTSUPPORTED expected, got %s\n", 1480 dev_name(WAVE_MAPPER),mmsys_error(rc)); 1481 1482 format.wFormatTag=WAVE_FORMAT_PCM; 1483 format.nChannels=2; 1484 format.wBitsPerSample=16; 1485 format.nSamplesPerSec=44100; 1486 format.nBlockAlign=format.nChannels*format.wBitsPerSample/8; 1487 format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign; 1488 format.cbSize=0; 1489 rc=waveOutOpen(&wout,ndev+1,&format,0,0,CALLBACK_NULL); 1490 ok(rc==MMSYSERR_BADDEVICEID, 1491 "waveOutOpen(%s): MMSYSERR_BADDEVICEID expected, got %s\n", 1492 dev_name(ndev+1),mmsys_error(rc)); 1493 1494 if(winetest_interactive) 1495 for (d=0;d<ndev;d++) 1496 wave_out_test_device(d); 1497 1498 if (ndev>0) 1499 wave_out_test_device(WAVE_MAPPER); 1500 } 1501 1502 static void test_sndPlaySound(void) 1503 { 1504 BOOL br; 1505 1506 static const WCHAR not_existW[] = {'C',':','\\','n','o','t','_','e','x','i','s','t','.','w','a','v',0}; 1507 static const WCHAR SystemAsteriskW[] = {'S','y','s','t','e','m','A','s','t','e','r','i','s','k',0}; 1508 1509 br = sndPlaySoundA((LPCSTR)SND_ALIAS_SYSTEMASTERISK, SND_ALIAS_ID|SND_SYNC); 1510 ok(br == TRUE || br == FALSE, "sndPlaySound gave strange return: %u\n", br); 1511 1512 br = sndPlaySoundW((LPCWSTR)SND_ALIAS_SYSTEMASTERISK, SND_ALIAS_ID|SND_SYNC); 1513 ok(br == TRUE || br == FALSE, "sndPlaySound gave strange return: %u\n", br); 1514 1515 br = sndPlaySoundA((LPCSTR)sndAlias('X','Y'), SND_ALIAS_ID|SND_SYNC); 1516 ok(br == TRUE || br == FALSE, "sndPlaySound gave strange return: %u\n", br); 1517 1518 br = sndPlaySoundW((LPCWSTR)sndAlias('X','Y'), SND_ALIAS_ID|SND_SYNC); 1519 ok(br == TRUE || br == FALSE, "sndPlaySound gave strange return: %u\n", br); 1520 1521 br = sndPlaySoundA("SystemAsterisk", SND_ALIAS|SND_SYNC); 1522 ok(br == TRUE || br == FALSE, "sndPlaySound gave strange return: %u\n", br); 1523 1524 br = sndPlaySoundW(SystemAsteriskW, SND_ALIAS|SND_SYNC); 1525 ok(br == TRUE || br == FALSE, "sndPlaySound gave strange return: %u\n", br); 1526 1527 br = sndPlaySoundA("C:\not_exist.wav", SND_FILENAME|SND_SYNC); 1528 ok(br == TRUE || br == FALSE, "sndPlaySound gave strange return: %u\n", br); 1529 1530 br = sndPlaySoundW(not_existW, SND_FILENAME|SND_SYNC); 1531 ok(br == TRUE || br == FALSE, "sndPlaySound gave strange return: %u\n", br); 1532 } 1533 1534 static void test_fragmentsize(void) 1535 { 1536 MMRESULT rc; 1537 WAVEHDR hdr[2]; 1538 HWAVEOUT wout; 1539 WAVEFORMATEX fmt; 1540 MMTIME mmtime; 1541 DWORD wait; 1542 HANDLE hevent; 1543 1544 if(waveOutGetNumDevs() == 0) 1545 return; 1546 1547 fmt.wFormatTag = WAVE_FORMAT_PCM; 1548 fmt.nChannels = 2; 1549 fmt.nSamplesPerSec = 44100; 1550 fmt.wBitsPerSample = 16; 1551 fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8; 1552 fmt.nAvgBytesPerSec = fmt.nBlockAlign * fmt.nSamplesPerSec; 1553 fmt.cbSize = sizeof(WAVEFORMATEX); 1554 1555 hevent = CreateEventW(NULL, FALSE, FALSE, NULL); 1556 g_tid = GetCurrentThreadId(); 1557 1558 rc = waveOutOpen(&wout, WAVE_MAPPER, &fmt, (DWORD_PTR)callback_func, 1559 (DWORD_PTR)hevent, CALLBACK_FUNCTION); 1560 ok(rc == MMSYSERR_NOERROR || rc == WAVERR_BADFORMAT || 1561 rc == MMSYSERR_INVALFLAG || rc == MMSYSERR_INVALPARAM, 1562 "waveOutOpen(%s) failed: %s\n", dev_name(WAVE_MAPPER), wave_out_error(rc)); 1563 if(rc != MMSYSERR_NOERROR){ 1564 CloseHandle(hevent); 1565 return; 1566 } 1567 1568 wait = WaitForSingleObject(hevent, 1000); 1569 ok(wait == WAIT_OBJECT_0, "wave open callback missed\n"); 1570 1571 memset(hdr, 0, sizeof(hdr)); 1572 hdr[0].dwBufferLength = (fmt.nSamplesPerSec * fmt.nBlockAlign / 4) + 1; 1573 hdr[1].dwBufferLength = hdr[0].dwBufferLength - 2; 1574 hdr[1].lpData = hdr[0].lpData = 1575 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, hdr[0].dwBufferLength); 1576 1577 rc = waveOutPrepareHeader(wout, &hdr[0], sizeof(hdr[0])); 1578 ok(rc == MMSYSERR_NOERROR, "waveOutPrepareHeader failed: %s\n", wave_out_error(rc)); 1579 1580 rc = waveOutPrepareHeader(wout, &hdr[1], sizeof(hdr[1])); 1581 ok(rc == MMSYSERR_NOERROR, "waveOutPrepareHeader failed: %s\n", wave_out_error(rc)); 1582 1583 trace("writing %u bytes then %u bytes\n", hdr[0].dwBufferLength, hdr[1].dwBufferLength); 1584 rc = waveOutWrite(wout, &hdr[0], sizeof(hdr[0])); 1585 ok(rc == MMSYSERR_NOERROR, "waveOutWrite failed: %s\n", wave_out_error(rc)); 1586 1587 rc = waveOutWrite(wout, &hdr[1], sizeof(hdr[1])); 1588 ok(rc == MMSYSERR_NOERROR, "waveOutWrite failed: %s\n", wave_out_error(rc)); 1589 1590 wait = WaitForSingleObject(hevent, 1000); 1591 ok(wait == WAIT_OBJECT_0, "header 1 callback missed\n"); 1592 1593 wait = WaitForSingleObject(hevent, 1000); 1594 ok(wait == WAIT_OBJECT_0, "header 2 callback missed\n"); 1595 1596 memset(&mmtime, 0, sizeof(mmtime)); 1597 mmtime.wType = TIME_BYTES; 1598 1599 rc = waveOutGetPosition(wout, &mmtime, sizeof(mmtime)); 1600 ok(rc == MMSYSERR_NOERROR, "waveOutGetPosition failed: %s\n", wave_out_error(rc)); 1601 1602 /* windows behavior is inconsistent */ 1603 ok(mmtime.u.cb == 88200 || 1604 mmtime.u.cb == 88196, "after position: %u\n", mmtime.u.cb); 1605 1606 rc = waveOutClose(wout); 1607 ok(rc == MMSYSERR_NOERROR, "waveOutClose failed: %s\n", wave_out_error(rc)); 1608 1609 HeapFree(GetProcessHeap(), 0, hdr[0].lpData); 1610 CloseHandle(hevent); 1611 } 1612 1613 static void create_wav_file(char *temp_file) 1614 { 1615 WAVEFORMATEX format; 1616 HMMIO h; 1617 MMCKINFO riff_chunk, chunk; 1618 MMRESULT rc; 1619 LONG written; 1620 DWORD length; 1621 char *buffer; 1622 1623 format.wFormatTag=WAVE_FORMAT_PCM; 1624 format.cbSize = 0; 1625 format.nChannels=1; 1626 format.wBitsPerSample=8; 1627 format.nSamplesPerSec=8000; 1628 format.nBlockAlign=format.nChannels*format.wBitsPerSample/8; 1629 format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign; 1630 1631 h = mmioOpenA(temp_file, NULL, MMIO_ALLOCBUF | MMIO_WRITE | MMIO_CREATE); 1632 ok(h != NULL, "Can't open temp_file\n"); 1633 1634 riff_chunk.fccType = mmioFOURCC('W','A','V','E'); 1635 riff_chunk.cksize = 0; 1636 rc = mmioCreateChunk(h, &riff_chunk, MMIO_CREATERIFF); 1637 ok(rc == MMSYSERR_NOERROR, "mmioCreateChunk failed, got %u\n", rc); 1638 1639 chunk.ckid = mmioFOURCC('f','m','t',' '); 1640 chunk.cksize = 0; 1641 rc = mmioCreateChunk(h, &chunk, 0); 1642 ok(rc == MMSYSERR_NOERROR, "mmioCreateChunk failed, got %u\n", rc); 1643 written = mmioWrite(h, (char*)&format, sizeof(format)); 1644 ok(written == sizeof(format), "mmioWrite failed, got %d\n", written); 1645 rc = mmioAscend(h, &chunk, 0); 1646 ok(rc == MMSYSERR_NOERROR, "mmioAscend failed, got %d\n", rc); 1647 1648 chunk.ckid = mmioFOURCC('d','a','t','a'); 1649 rc = mmioCreateChunk(h, &chunk, 0); 1650 ok(rc == MMSYSERR_NOERROR, "mmioCreateChunk failed, got %u\n", rc); 1651 buffer = wave_generate_silence(&format, .1, &length); 1652 written = mmioWrite(h, buffer, length); 1653 ok(written == length, "mmioWrite failed, got %d\n", written); 1654 rc = mmioAscend(h, &chunk, 0); 1655 ok(rc == MMSYSERR_NOERROR, "mmioAscend failed, got %d\n", rc); 1656 HeapFree(GetProcessHeap(), 0, buffer); 1657 1658 rc = mmioAscend(h, &riff_chunk, 0); 1659 ok(rc == MMSYSERR_NOERROR, "mmioAscend failed, got %d\n", rc); 1660 1661 rc = mmioClose(h, 0); 1662 ok(rc == MMSYSERR_NOERROR, "mmioClose failed, got %u\n", rc); 1663 } 1664 1665 static void test_PlaySound(void) 1666 { 1667 BOOL br; 1668 char test_file[MAX_PATH], temp[MAX_PATH], *exts; 1669 void *psound_ordinal, *psound_name; 1670 HMODULE dll = GetModuleHandleA("winmm.dll"); 1671 1672 psound_name = GetProcAddress(dll, "PlaySound"); 1673 psound_ordinal = GetProcAddress(dll, (LPCSTR) 2); 1674 ok(psound_name == psound_ordinal, "Expected ordinal 2 to be PlaySound function\n"); 1675 1676 if(waveOutGetNumDevs() == 0) { 1677 skip("No output devices available\n"); 1678 return; 1679 } 1680 1681 GetTempPathA(sizeof(test_file), test_file); 1682 strcat(test_file, "mysound.wav"); 1683 create_wav_file(test_file); 1684 1685 br = PlaySoundA(test_file, NULL, SND_FILENAME | SND_NODEFAULT); 1686 ok(br, "PlaySound failed, got %d\n", br); 1687 1688 /* SND_ALIAS fallbacks to SND_FILENAME */ 1689 br = PlaySoundA(test_file, NULL, SND_ALIAS | SND_NODEFAULT); 1690 ok(br, "PlaySound failed, got %d\n", br); 1691 1692 strcpy(temp, test_file); 1693 exts = strrchr(temp, '.'); 1694 1695 /* no extensions */ 1696 *exts = '\0'; 1697 br = PlaySoundA(temp, NULL, SND_FILENAME | SND_NODEFAULT); 1698 ok(br, "PlaySound failed, got %d\n", br); 1699 1700 /* ends with a dot */ 1701 strcpy(exts, "."); 1702 br = PlaySoundA(temp, NULL, SND_FILENAME | SND_NODEFAULT); 1703 ok(!br || broken(br), "PlaySound succeeded, got %d\n", br); 1704 1705 DeleteFileA(test_file); 1706 } 1707 1708 START_TEST(wave) 1709 { 1710 test_multiple_waveopens(); 1711 wave_out_tests(); 1712 test_sndPlaySound(); 1713 test_fragmentsize(); 1714 test_PlaySound(); 1715 } 1716