"Fossies" - the Fresh Open Source Software Archive

Member "wine-6.0.1/dlls/winmm/tests/wave.c" (7 Jun 2021, 71837 Bytes) of package /linux/misc/wine-6.0.1.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "wave.c": 6.0_vs_6.0.1.

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