src/audio/winmm/SDL_winmm.c
author Ryan C. Gordon
Thu, 04 Aug 2011 01:24:22 -0400
changeset 5588 57bfc2a2a452
child 5593 ab22ca13c47f
permissions -rw-r--r--
Reworked Windows waveOut code.

Implemented multi-device support, changed name to "winmm".
icculus@5588
     1
/*
icculus@5588
     2
  Simple DirectMedia Layer
icculus@5588
     3
  Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
icculus@5588
     4
icculus@5588
     5
  This software is provided 'as-is', without any express or implied
icculus@5588
     6
  warranty.  In no event will the authors be held liable for any damages
icculus@5588
     7
  arising from the use of this software.
icculus@5588
     8
icculus@5588
     9
  Permission is granted to anyone to use this software for any purpose,
icculus@5588
    10
  including commercial applications, and to alter it and redistribute it
icculus@5588
    11
  freely, subject to the following restrictions:
icculus@5588
    12
icculus@5588
    13
  1. The origin of this software must not be misrepresented; you must not
icculus@5588
    14
     claim that you wrote the original software. If you use this software
icculus@5588
    15
     in a product, an acknowledgment in the product documentation would be
icculus@5588
    16
     appreciated but is not required.
icculus@5588
    17
  2. Altered source versions must be plainly marked as such, and must not be
icculus@5588
    18
     misrepresented as being the original software.
icculus@5588
    19
  3. This notice may not be removed or altered from any source distribution.
icculus@5588
    20
*/
icculus@5588
    21
#include "SDL_config.h"
icculus@5588
    22
icculus@5588
    23
/* Allow access to a raw mixing buffer */
icculus@5588
    24
icculus@5588
    25
#include "../../core/windows/SDL_windows.h"
icculus@5588
    26
#include <mmsystem.h>
icculus@5588
    27
icculus@5588
    28
#include "SDL_timer.h"
icculus@5588
    29
#include "SDL_audio.h"
icculus@5588
    30
#include "../SDL_audio_c.h"
icculus@5588
    31
#include "SDL_winmm.h"
icculus@5588
    32
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
icculus@5588
    33
#include "win_ce_semaphore.h"
icculus@5588
    34
#endif
icculus@5588
    35
icculus@5588
    36
icculus@5588
    37
/* !!! FIXME: this is a cut and paste of SDL_FreeUnixAudioDevices(),
icculus@5588
    38
 * !!! FIXME:  which is more proof this needs to be managed in SDL_audio.c
icculus@5588
    39
 * !!! FIXME:  and not in drivers.
icculus@5588
    40
 */
icculus@5588
    41
static void
icculus@5588
    42
FreeWaveOutAudioDevices(char ***devices, int *devCount)
icculus@5588
    43
{
icculus@5588
    44
    int i = *devCount;
icculus@5588
    45
    if ((i > 0) && (*devices != NULL)) {
icculus@5588
    46
        while (i--) {
icculus@5588
    47
            SDL_free((*devices)[i]);
icculus@5588
    48
        }
icculus@5588
    49
    }
icculus@5588
    50
icculus@5588
    51
    if (*devices != NULL) {
icculus@5588
    52
        SDL_free(*devices);
icculus@5588
    53
    }
icculus@5588
    54
icculus@5588
    55
    *devices = NULL;
icculus@5588
    56
    *devCount = 0;
icculus@5588
    57
}
icculus@5588
    58
icculus@5588
    59
static char **outputDevices = NULL;
icculus@5588
    60
static int outputDeviceCount = 0;
icculus@5588
    61
static char **inputDevices = NULL;
icculus@5588
    62
static int inputDeviceCount = 0;
icculus@5588
    63
icculus@5588
    64
static int
icculus@5588
    65
DetectWaveOutDevices(void)
icculus@5588
    66
{
icculus@5588
    67
    UINT i;
icculus@5588
    68
    const UINT devcount = waveOutGetNumDevs();
icculus@5588
    69
    WAVEOUTCAPS caps;
icculus@5588
    70
    FreeWaveOutAudioDevices(&outputDevices, &outputDeviceCount);
icculus@5588
    71
    outputDevices = (const char **) SDL_malloc(sizeof (char *) * devcount);
icculus@5588
    72
    for (i = 0; i < devcount; i++) {
icculus@5588
    73
        if (waveOutGetDevCaps(i, &caps, sizeof (caps)) == MMSYSERR_NOERROR) {
icculus@5588
    74
            outputDevices[outputDeviceCount] = WIN_StringToUTF8(caps.szPname);
icculus@5588
    75
            if (outputDevices[outputDeviceCount] != NULL) {
icculus@5588
    76
                outputDeviceCount++;
icculus@5588
    77
            }
icculus@5588
    78
        }
icculus@5588
    79
    }
icculus@5588
    80
    return outputDeviceCount;
icculus@5588
    81
}
icculus@5588
    82
icculus@5588
    83
static int
icculus@5588
    84
DetectWaveInDevices(void)
icculus@5588
    85
{
icculus@5588
    86
    UINT i;
icculus@5588
    87
    const UINT devcount = waveInGetNumDevs();
icculus@5588
    88
    WAVEINCAPS caps;
icculus@5588
    89
    FreeWaveInAudioDevices(&inputDevices, &inputDeviceCount);
icculus@5588
    90
    inputDevices = (const char **) SDL_malloc(sizeof (char *) * devcount);
icculus@5588
    91
    for (i = 0; i < devcount; i++) {
icculus@5588
    92
        if (waveInGetDevCaps(i, &caps, sizeof (caps)) == MMSYSERR_NOERROR) {
icculus@5588
    93
            inputDevices[inputDeviceCount] = WIN_StringToUTF8(caps.szPname);
icculus@5588
    94
            if (inputDevices[inputDeviceCount] != NULL) {
icculus@5588
    95
                inputDeviceCount++;
icculus@5588
    96
            }
icculus@5588
    97
        }
icculus@5588
    98
    }
icculus@5588
    99
    return inputDeviceCount;
icculus@5588
   100
}
icculus@5588
   101
icculus@5588
   102
static int
icculus@5588
   103
WINMM_DetectDevices(int iscapture)
icculus@5588
   104
{
icculus@5588
   105
    return (iscapture) ? DetectWaveInDevices() : DetectWaveOutDevices();
icculus@5588
   106
}
icculus@5588
   107
icculus@5588
   108
static const char *
icculus@5588
   109
WINMM_GetDeviceName(int index, int iscapture)
icculus@5588
   110
{
icculus@5588
   111
    if ((iscapture) && (index < inputDeviceCount)) {
icculus@5588
   112
        return inputDevices[index];
icculus@5588
   113
    } else if ((!iscapture) && (index < outputDeviceCount)) {
icculus@5588
   114
        return outputDevices[index];
icculus@5588
   115
    }
icculus@5588
   116
icculus@5588
   117
    SDL_SetError("No such device");
icculus@5588
   118
    return NULL;
icculus@5588
   119
}
icculus@5588
   120
icculus@5588
   121
static void CALLBACK
icculus@5588
   122
CaptureSound(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance,
icculus@5588
   123
          DWORD_PTR dwParam1, DWORD_PTR dwParam2)
icculus@5588
   124
{
icculus@5588
   125
    SDL_AudioDevice *this = (SDL_AudioDevice *) dwInstance;
icculus@5588
   126
icculus@5588
   127
    /* Only service "buffer is filled" messages */
icculus@5588
   128
    if (uMsg != WIM_DATA)
icculus@5588
   129
        return;
icculus@5588
   130
icculus@5588
   131
    /* Signal that we have a new buffer of data */
icculus@5588
   132
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
icculus@5588
   133
    ReleaseSemaphoreCE(this->hidden->audio_sem, 1, NULL);
icculus@5588
   134
#else
icculus@5588
   135
    ReleaseSemaphore(this->hidden->audio_sem, 1, NULL);
icculus@5588
   136
#endif
icculus@5588
   137
}
icculus@5588
   138
icculus@5588
   139
icculus@5588
   140
/* The Win32 callback for filling the WAVE device */
icculus@5588
   141
static void CALLBACK
icculus@5588
   142
FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
icculus@5588
   143
          DWORD_PTR dwParam1, DWORD_PTR dwParam2)
icculus@5588
   144
{
icculus@5588
   145
    SDL_AudioDevice *this = (SDL_AudioDevice *) dwInstance;
icculus@5588
   146
icculus@5588
   147
    /* Only service "buffer done playing" messages */
icculus@5588
   148
    if (uMsg != WOM_DONE)
icculus@5588
   149
        return;
icculus@5588
   150
icculus@5588
   151
    /* Signal that we are done playing a buffer */
icculus@5588
   152
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
icculus@5588
   153
    ReleaseSemaphoreCE(this->hidden->audio_sem, 1, NULL);
icculus@5588
   154
#else
icculus@5588
   155
    ReleaseSemaphore(this->hidden->audio_sem, 1, NULL);
icculus@5588
   156
#endif
icculus@5588
   157
}
icculus@5588
   158
icculus@5588
   159
static void
icculus@5588
   160
SetMMerror(char *function, MMRESULT code)
icculus@5588
   161
{
icculus@5588
   162
    size_t len;
icculus@5588
   163
    char errbuf[MAXERRORLENGTH];
icculus@5588
   164
    wchar_t werrbuf[MAXERRORLENGTH];
icculus@5588
   165
icculus@5588
   166
    SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: ", function);
icculus@5588
   167
    len = SDL_strlen(errbuf);
icculus@5588
   168
icculus@5588
   169
    waveOutGetErrorText(code, werrbuf, MAXERRORLENGTH - len);
icculus@5588
   170
    WideCharToMultiByte(CP_ACP, 0, werrbuf, -1, errbuf + len,
icculus@5588
   171
                        MAXERRORLENGTH - len, NULL, NULL);
icculus@5588
   172
icculus@5588
   173
    SDL_SetError("%s", errbuf);
icculus@5588
   174
}
icculus@5588
   175
icculus@5588
   176
static void
icculus@5588
   177
WINMM_WaitDevice(_THIS)
icculus@5588
   178
{
icculus@5588
   179
    /* Wait for an audio chunk to finish */
icculus@5588
   180
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
icculus@5588
   181
    WaitForSemaphoreCE(this->hidden->audio_sem, INFINITE);
icculus@5588
   182
#else
icculus@5588
   183
    WaitForSingleObject(this->hidden->audio_sem, INFINITE);
icculus@5588
   184
#endif
icculus@5588
   185
}
icculus@5588
   186
icculus@5588
   187
static Uint8 *
icculus@5588
   188
WINMM_GetDeviceBuf(_THIS)
icculus@5588
   189
{
icculus@5588
   190
    return (Uint8 *) (this->hidden->
icculus@5588
   191
                      wavebuf[this->hidden->next_buffer].lpData);
icculus@5588
   192
}
icculus@5588
   193
icculus@5588
   194
static void
icculus@5588
   195
WINMM_PlayDevice(_THIS)
icculus@5588
   196
{
icculus@5588
   197
    /* Queue it up */
icculus@5588
   198
    waveOutWrite(this->hidden->hout,
icculus@5588
   199
                 &this->hidden->wavebuf[this->hidden->next_buffer],
icculus@5588
   200
                 sizeof(this->hidden->wavebuf[0]));
icculus@5588
   201
    this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
icculus@5588
   202
}
icculus@5588
   203
icculus@5588
   204
static void
icculus@5588
   205
WINMM_WaitDone(_THIS)
icculus@5588
   206
{
icculus@5588
   207
    int i, left;
icculus@5588
   208
icculus@5588
   209
    do {
icculus@5588
   210
        left = NUM_BUFFERS;
icculus@5588
   211
        for (i = 0; i < NUM_BUFFERS; ++i) {
icculus@5588
   212
            if (this->hidden->wavebuf[i].dwFlags & WHDR_DONE) {
icculus@5588
   213
                --left;
icculus@5588
   214
            }
icculus@5588
   215
        }
icculus@5588
   216
        if (left > 0) {
icculus@5588
   217
            SDL_Delay(100);
icculus@5588
   218
        }
icculus@5588
   219
    } while (left > 0);
icculus@5588
   220
}
icculus@5588
   221
icculus@5588
   222
static void
icculus@5588
   223
WINMM_CloseDevice(_THIS)
icculus@5588
   224
{
icculus@5588
   225
    /* Close up audio */
icculus@5588
   226
    if (this->hidden != NULL) {
icculus@5588
   227
        int i;
icculus@5588
   228
icculus@5588
   229
        if (this->hidden->audio_sem) {
icculus@5588
   230
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
icculus@5588
   231
            CloseSynchHandle(this->hidden->audio_sem);
icculus@5588
   232
#else
icculus@5588
   233
            CloseHandle(this->hidden->audio_sem);
icculus@5588
   234
#endif
icculus@5588
   235
            this->hidden->audio_sem = 0;
icculus@5588
   236
        }
icculus@5588
   237
icculus@5588
   238
        if (this->hidden->hin) {
icculus@5588
   239
            waveInClose(this->hidden->hin);
icculus@5588
   240
            this->hidden->hin = 0;
icculus@5588
   241
        }
icculus@5588
   242
icculus@5588
   243
        if (this->hidden->hout) {
icculus@5588
   244
            waveOutClose(this->hidden->hout);
icculus@5588
   245
            this->hidden->hout = 0;
icculus@5588
   246
        }
icculus@5588
   247
icculus@5588
   248
        /* Clean up mixing buffers */
icculus@5588
   249
        for (i = 0; i < NUM_BUFFERS; ++i) {
icculus@5588
   250
            if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
icculus@5588
   251
                waveOutUnprepareHeader(this->hidden->hout,
icculus@5588
   252
                                       &this->hidden->wavebuf[i],
icculus@5588
   253
                                       sizeof(this->hidden->wavebuf[i]));
icculus@5588
   254
                this->hidden->wavebuf[i].dwUser = 0xFFFF;
icculus@5588
   255
            }
icculus@5588
   256
        }
icculus@5588
   257
icculus@5588
   258
        if (this->hidden->mixbuf != NULL) {
icculus@5588
   259
            /* Free raw mixing buffer */
icculus@5588
   260
            SDL_free(this->hidden->mixbuf);
icculus@5588
   261
            this->hidden->mixbuf = NULL;
icculus@5588
   262
        }
icculus@5588
   263
icculus@5588
   264
        SDL_free(this->hidden);
icculus@5588
   265
        this->hidden = NULL;
icculus@5588
   266
    }
icculus@5588
   267
}
icculus@5588
   268
icculus@5588
   269
static int
icculus@5588
   270
WINMM_OpenDevice(_THIS, const char *devname, int iscapture)
icculus@5588
   271
{
icculus@5588
   272
    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
icculus@5588
   273
    int valid_datatype = 0;
icculus@5588
   274
    MMRESULT result;
icculus@5588
   275
    WAVEFORMATEX waveformat;
icculus@5588
   276
    UINT_PTR devId = WAVE_MAPPER;  /* WAVE_MAPPER == choose system's default */
icculus@5588
   277
    char *utf8 = NULL;
icculus@5588
   278
    int i;
icculus@5588
   279
icculus@5588
   280
    if (devname != NULL) {  /* specific device requested? */
icculus@5588
   281
        if (iscapture) {
icculus@5588
   282
            const int devcount = (int) waveInGetNumDevs();
icculus@5588
   283
            WAVEINCAPS caps;
icculus@5588
   284
            for (i = 0; (i < devcount) && (devId == WAVE_MAPPER); i++) {
icculus@5588
   285
                result = waveInGetDevCaps(i, &caps, sizeof (caps));
icculus@5588
   286
                if (result != MMSYSERR_NOERROR)
icculus@5588
   287
                    continue;
icculus@5588
   288
                else if ((utf8 = WIN_StringToUTF8(caps.szPname)) == NULL)
icculus@5588
   289
                    continue;
icculus@5588
   290
                else if (SDL_strcmp(devname, utf8) == 0)
icculus@5588
   291
                    devId = (UINT_PTR) i;
icculus@5588
   292
                SDL_free(utf8);
icculus@5588
   293
            }
icculus@5588
   294
        } else {
icculus@5588
   295
            const int devcount = (int) waveOutGetNumDevs();
icculus@5588
   296
            WAVEOUTCAPS caps;
icculus@5588
   297
            for (i = 0; (i < devcount) && (devId == WAVE_MAPPER); i++) {
icculus@5588
   298
                result = waveOutGetDevCaps(i, &caps, sizeof (caps));
icculus@5588
   299
                if (result != MMSYSERR_NOERROR)
icculus@5588
   300
                    continue;
icculus@5588
   301
                else if ((utf8 = WIN_StringToUTF8(caps.szPname)) == NULL)
icculus@5588
   302
                    continue;
icculus@5588
   303
                else if (SDL_strcmp(devname, utf8) == 0)
icculus@5588
   304
                    devId = (UINT_PTR) i;
icculus@5588
   305
                SDL_free(utf8);
icculus@5588
   306
            }
icculus@5588
   307
        }
icculus@5588
   308
icculus@5588
   309
        if (devId == WAVE_MAPPER) {
icculus@5588
   310
            SDL_SetError("Requested device not found");
icculus@5588
   311
            return 0;
icculus@5588
   312
        }
icculus@5588
   313
    }
icculus@5588
   314
icculus@5588
   315
    /* Initialize all variables that we clean on shutdown */
icculus@5588
   316
    this->hidden = (struct SDL_PrivateAudioData *)
icculus@5588
   317
        SDL_malloc((sizeof *this->hidden));
icculus@5588
   318
    if (this->hidden == NULL) {
icculus@5588
   319
        SDL_OutOfMemory();
icculus@5588
   320
        return 0;
icculus@5588
   321
    }
icculus@5588
   322
    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
icculus@5588
   323
icculus@5588
   324
    /* Initialize the wavebuf structures for closing */
icculus@5588
   325
    for (i = 0; i < NUM_BUFFERS; ++i)
icculus@5588
   326
        this->hidden->wavebuf[i].dwUser = 0xFFFF;
icculus@5588
   327
icculus@5588
   328
    while ((!valid_datatype) && (test_format)) {
icculus@5588
   329
        valid_datatype = 1;
icculus@5588
   330
        this->spec.format = test_format;
icculus@5588
   331
        switch (test_format) {
icculus@5588
   332
        case AUDIO_U8:
icculus@5588
   333
        case AUDIO_S16:
icculus@5588
   334
        case AUDIO_S32:
icculus@5588
   335
            break;              /* valid. */
icculus@5588
   336
icculus@5588
   337
        default:
icculus@5588
   338
            valid_datatype = 0;
icculus@5588
   339
            test_format = SDL_NextAudioFormat();
icculus@5588
   340
            break;
icculus@5588
   341
        }
icculus@5588
   342
    }
icculus@5588
   343
icculus@5588
   344
    if (!valid_datatype) {
icculus@5588
   345
        WINMM_CloseDevice(this);
icculus@5588
   346
        SDL_SetError("Unsupported audio format");
icculus@5588
   347
        return 0;
icculus@5588
   348
    }
icculus@5588
   349
icculus@5588
   350
    /* Set basic WAVE format parameters */
icculus@5588
   351
    SDL_memset(&waveformat, '\0', sizeof(waveformat));
icculus@5588
   352
    waveformat.wFormatTag = WAVE_FORMAT_PCM;
icculus@5588
   353
    waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
icculus@5588
   354
icculus@5588
   355
    if (this->spec.channels > 2)
icculus@5588
   356
        this->spec.channels = 2;        /* !!! FIXME: is this right? */
icculus@5588
   357
icculus@5588
   358
    waveformat.nChannels = this->spec.channels;
icculus@5588
   359
    waveformat.nSamplesPerSec = this->spec.freq;
icculus@5588
   360
    waveformat.nBlockAlign =
icculus@5588
   361
        waveformat.nChannels * (waveformat.wBitsPerSample / 8);
icculus@5588
   362
    waveformat.nAvgBytesPerSec =
icculus@5588
   363
        waveformat.nSamplesPerSec * waveformat.nBlockAlign;
icculus@5588
   364
icculus@5588
   365
    /* Check the buffer size -- minimum of 1/4 second (word aligned) */
icculus@5588
   366
    if (this->spec.samples < (this->spec.freq / 4))
icculus@5588
   367
        this->spec.samples = ((this->spec.freq / 4) + 3) & ~3;
icculus@5588
   368
icculus@5588
   369
    /* Update the fragment size as size in bytes */
icculus@5588
   370
    SDL_CalculateAudioSpec(&this->spec);
icculus@5588
   371
icculus@5588
   372
    /* Open the audio device */
icculus@5588
   373
    if (iscapture) {
icculus@5588
   374
        result = waveInOpen(&this->hidden->hin, devId, &waveformat,
icculus@5588
   375
                             (DWORD_PTR) CaptureSound, (DWORD_PTR) this,
icculus@5588
   376
                             CALLBACK_FUNCTION);
icculus@5588
   377
    } else {
icculus@5588
   378
        result = waveOutOpen(&this->hidden->hout, devId, &waveformat,
icculus@5588
   379
                             (DWORD_PTR) FillSound, (DWORD_PTR) this,
icculus@5588
   380
                             CALLBACK_FUNCTION);
icculus@5588
   381
    }
icculus@5588
   382
icculus@5588
   383
    if (result != MMSYSERR_NOERROR) {
icculus@5588
   384
        WINMM_CloseDevice(this);
icculus@5588
   385
        SetMMerror("waveOutOpen()", result);
icculus@5588
   386
        return 0;
icculus@5588
   387
    }
icculus@5588
   388
#ifdef SOUND_DEBUG
icculus@5588
   389
    /* Check the sound device we retrieved */
icculus@5588
   390
    {
icculus@5588
   391
        WAVEOUTCAPS caps;
icculus@5588
   392
icculus@5588
   393
        result = waveOutGetDevCaps((UINT) this->hidden->hout,
icculus@5588
   394
                                   &caps, sizeof(caps));
icculus@5588
   395
        if (result != MMSYSERR_NOERROR) {
icculus@5588
   396
            WINMM_CloseDevice(this);
icculus@5588
   397
            SetMMerror("waveOutGetDevCaps()", result);
icculus@5588
   398
            return 0;
icculus@5588
   399
        }
icculus@5588
   400
        printf("Audio device: %s\n", caps.szPname);
icculus@5588
   401
    }
icculus@5588
   402
#endif
icculus@5588
   403
icculus@5588
   404
    /* Create the audio buffer semaphore */
icculus@5588
   405
    this->hidden->audio_sem =
icculus@5588
   406
#if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
icculus@5588
   407
        CreateSemaphoreCE(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
icculus@5588
   408
#else
icculus@5588
   409
        CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
icculus@5588
   410
#endif
icculus@5588
   411
    if (this->hidden->audio_sem == NULL) {
icculus@5588
   412
        WINMM_CloseDevice(this);
icculus@5588
   413
        SDL_SetError("Couldn't create semaphore");
icculus@5588
   414
        return 0;
icculus@5588
   415
    }
icculus@5588
   416
icculus@5588
   417
    /* Create the sound buffers */
icculus@5588
   418
    this->hidden->mixbuf =
icculus@5588
   419
        (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
icculus@5588
   420
    if (this->hidden->mixbuf == NULL) {
icculus@5588
   421
        WINMM_CloseDevice(this);
icculus@5588
   422
        SDL_OutOfMemory();
icculus@5588
   423
        return 0;
icculus@5588
   424
    }
icculus@5588
   425
    for (i = 0; i < NUM_BUFFERS; ++i) {
icculus@5588
   426
        SDL_memset(&this->hidden->wavebuf[i], '\0',
icculus@5588
   427
                   sizeof(this->hidden->wavebuf[i]));
icculus@5588
   428
        this->hidden->wavebuf[i].dwBufferLength = this->spec.size;
icculus@5588
   429
        this->hidden->wavebuf[i].dwFlags = WHDR_DONE;
icculus@5588
   430
        this->hidden->wavebuf[i].lpData =
icculus@5588
   431
            (LPSTR) & this->hidden->mixbuf[i * this->spec.size];
icculus@5588
   432
        result = waveOutPrepareHeader(this->hidden->hout,
icculus@5588
   433
                                      &this->hidden->wavebuf[i],
icculus@5588
   434
                                      sizeof(this->hidden->wavebuf[i]));
icculus@5588
   435
        if (result != MMSYSERR_NOERROR) {
icculus@5588
   436
            WINMM_CloseDevice(this);
icculus@5588
   437
            SetMMerror("waveOutPrepareHeader()", result);
icculus@5588
   438
            return 0;
icculus@5588
   439
        }
icculus@5588
   440
    }
icculus@5588
   441
icculus@5588
   442
    return 1;                   /* Ready to go! */
icculus@5588
   443
}
icculus@5588
   444
icculus@5588
   445
icculus@5588
   446
static int
icculus@5588
   447
WINMM_Init(SDL_AudioDriverImpl * impl)
icculus@5588
   448
{
icculus@5588
   449
    /* Set the function pointers */
icculus@5588
   450
    impl->DetectDevices = WINMM_DetectDevices;
icculus@5588
   451
    impl->GetDeviceName = WINMM_GetDeviceName;
icculus@5588
   452
    impl->OpenDevice = WINMM_OpenDevice;
icculus@5588
   453
    impl->PlayDevice = WINMM_PlayDevice;
icculus@5588
   454
    impl->WaitDevice = WINMM_WaitDevice;
icculus@5588
   455
    impl->WaitDone = WINMM_WaitDone;
icculus@5588
   456
    impl->GetDeviceBuf = WINMM_GetDeviceBuf;
icculus@5588
   457
    impl->CloseDevice = WINMM_CloseDevice;
icculus@5588
   458
icculus@5588
   459
    return 1;   /* this audio target is available. */
icculus@5588
   460
}
icculus@5588
   461
icculus@5588
   462
AudioBootStrap WINMM_bootstrap = {
icculus@5588
   463
    "winmm", "Windows Waveform Audio", WINMM_Init, 0
icculus@5588
   464
};
icculus@5588
   465
icculus@5588
   466
/* vi: set ts=4 sw=4 expandtab: */