src/audio/winmm/SDL_winmm.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 24 Sep 2018 11:49:25 -0700
changeset 12201 8bdc4d340419
parent 11811 5d94cb6b24d3
child 12503 806492103856
permissions -rw-r--r--
Fixed whitespace
icculus@5588
     1
/*
icculus@5588
     2
  Simple DirectMedia Layer
slouken@11811
     3
  Copyright (C) 1997-2018 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@8093
    21
#include "../../SDL_internal.h"
icculus@5588
    22
slouken@6044
    23
#if SDL_AUDIO_DRIVER_WINMM
slouken@6044
    24
icculus@5588
    25
/* Allow access to a raw mixing buffer */
icculus@5588
    26
icculus@5588
    27
#include "../../core/windows/SDL_windows.h"
icculus@5588
    28
#include <mmsystem.h>
icculus@5588
    29
icculus@10266
    30
#include "SDL_assert.h"
icculus@5588
    31
#include "SDL_timer.h"
icculus@5588
    32
#include "SDL_audio.h"
icculus@5588
    33
#include "../SDL_audio_c.h"
icculus@5588
    34
#include "SDL_winmm.h"
icculus@5588
    35
slouken@10822
    36
/* MinGW32 mmsystem.h doesn't include these structures */
slouken@10822
    37
#if defined(__MINGW32__) && defined(_MMSYSTEM_H)
slouken@10818
    38
slouken@10818
    39
typedef struct tagWAVEINCAPS2W 
slouken@10818
    40
{
slouken@10818
    41
    WORD wMid;
slouken@10818
    42
    WORD wPid;
slouken@10818
    43
    MMVERSION vDriverVersion;
slouken@10818
    44
    WCHAR szPname[MAXPNAMELEN];
slouken@10818
    45
    DWORD dwFormats;
slouken@10818
    46
    WORD wChannels;
slouken@10818
    47
    WORD wReserved1;
slouken@10818
    48
    GUID ManufacturerGuid;
slouken@10818
    49
    GUID ProductGuid;
slouken@10818
    50
    GUID NameGuid;
slouken@10818
    51
} WAVEINCAPS2W,*PWAVEINCAPS2W,*NPWAVEINCAPS2W,*LPWAVEINCAPS2W;
slouken@10818
    52
slouken@10818
    53
typedef struct tagWAVEOUTCAPS2W
slouken@10818
    54
{
slouken@10818
    55
    WORD wMid;
slouken@10818
    56
    WORD wPid;
slouken@10818
    57
    MMVERSION vDriverVersion;
slouken@10818
    58
    WCHAR szPname[MAXPNAMELEN];
slouken@10818
    59
    DWORD dwFormats;
slouken@10818
    60
    WORD wChannels;
slouken@10818
    61
    WORD wReserved1;
slouken@10818
    62
    DWORD dwSupport;
slouken@10818
    63
    GUID ManufacturerGuid;
slouken@10818
    64
    GUID ProductGuid;
slouken@10818
    65
    GUID NameGuid;
slouken@10818
    66
} WAVEOUTCAPS2W,*PWAVEOUTCAPS2W,*NPWAVEOUTCAPS2W,*LPWAVEOUTCAPS2W;
slouken@10818
    67
slouken@10822
    68
#endif /* defined(__MINGW32__) && defined(_MMSYSTEM_H) */
slouken@10818
    69
icculus@7449
    70
#ifndef WAVE_FORMAT_IEEE_FLOAT
icculus@7449
    71
#define WAVE_FORMAT_IEEE_FLOAT 0x0003
icculus@7449
    72
#endif
icculus@7449
    73
icculus@9394
    74
#define DETECT_DEV_IMPL(iscap, typ, capstyp) \
icculus@9394
    75
static void DetectWave##typ##Devs(void) { \
icculus@9394
    76
    const UINT iscapture = iscap ? 1 : 0; \
icculus@5593
    77
    const UINT devcount = wave##typ##GetNumDevs(); \
icculus@10268
    78
    capstyp##2W caps; \
icculus@5593
    79
    UINT i; \
icculus@5593
    80
    for (i = 0; i < devcount; i++) { \
slouken@12201
    81
        if (wave##typ##GetDevCaps(i,(LP##capstyp##W)&caps,sizeof(caps))==MMSYSERR_NOERROR) { \
icculus@10278
    82
            char *name = WIN_LookupAudioDeviceName(caps.szPname,&caps.NameGuid); \
icculus@5593
    83
            if (name != NULL) { \
icculus@9410
    84
                SDL_AddAudioDevice((int) iscapture, name, (void *) ((size_t) i+1)); \
icculus@5593
    85
                SDL_free(name); \
icculus@5593
    86
            } \
icculus@5593
    87
        } \
icculus@5593
    88
    } \
icculus@5588
    89
}
icculus@5588
    90
icculus@9394
    91
DETECT_DEV_IMPL(SDL_FALSE, Out, WAVEOUTCAPS)
icculus@9394
    92
DETECT_DEV_IMPL(SDL_TRUE, In, WAVEINCAPS)
icculus@5588
    93
icculus@5593
    94
static void
icculus@9404
    95
WINMM_DetectDevices(void)
icculus@5588
    96
{
icculus@9394
    97
    DetectWaveInDevs();
icculus@9394
    98
    DetectWaveOutDevs();
icculus@5588
    99
}
icculus@5588
   100
icculus@5588
   101
static void CALLBACK
icculus@5588
   102
CaptureSound(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance,
icculus@5588
   103
          DWORD_PTR dwParam1, DWORD_PTR dwParam2)
icculus@5588
   104
{
icculus@5588
   105
    SDL_AudioDevice *this = (SDL_AudioDevice *) dwInstance;
icculus@5588
   106
icculus@5588
   107
    /* Only service "buffer is filled" messages */
icculus@5588
   108
    if (uMsg != WIM_DATA)
icculus@5588
   109
        return;
icculus@5588
   110
icculus@5588
   111
    /* Signal that we have a new buffer of data */
icculus@5588
   112
    ReleaseSemaphore(this->hidden->audio_sem, 1, NULL);
icculus@5588
   113
}
icculus@5588
   114
icculus@5588
   115
icculus@5588
   116
/* The Win32 callback for filling the WAVE device */
icculus@5588
   117
static void CALLBACK
icculus@5588
   118
FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
icculus@5588
   119
          DWORD_PTR dwParam1, DWORD_PTR dwParam2)
icculus@5588
   120
{
icculus@5588
   121
    SDL_AudioDevice *this = (SDL_AudioDevice *) dwInstance;
icculus@5588
   122
icculus@5588
   123
    /* Only service "buffer done playing" messages */
icculus@5588
   124
    if (uMsg != WOM_DONE)
icculus@5588
   125
        return;
icculus@5588
   126
icculus@5588
   127
    /* Signal that we are done playing a buffer */
icculus@5588
   128
    ReleaseSemaphore(this->hidden->audio_sem, 1, NULL);
icculus@5588
   129
}
icculus@5588
   130
icculus@7038
   131
static int
icculus@5588
   132
SetMMerror(char *function, MMRESULT code)
icculus@5588
   133
{
slouken@8585
   134
    int len;
icculus@5588
   135
    char errbuf[MAXERRORLENGTH];
icculus@5588
   136
    wchar_t werrbuf[MAXERRORLENGTH];
icculus@5588
   137
icculus@5588
   138
    SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: ", function);
slouken@8585
   139
    len = SDL_static_cast(int, SDL_strlen(errbuf));
icculus@5588
   140
icculus@5588
   141
    waveOutGetErrorText(code, werrbuf, MAXERRORLENGTH - len);
icculus@5588
   142
    WideCharToMultiByte(CP_ACP, 0, werrbuf, -1, errbuf + len,
icculus@5588
   143
                        MAXERRORLENGTH - len, NULL, NULL);
icculus@5588
   144
icculus@7038
   145
    return SDL_SetError("%s", errbuf);
icculus@5588
   146
}
icculus@5588
   147
icculus@5588
   148
static void
icculus@5588
   149
WINMM_WaitDevice(_THIS)
icculus@5588
   150
{
icculus@5588
   151
    /* Wait for an audio chunk to finish */
icculus@5588
   152
    WaitForSingleObject(this->hidden->audio_sem, INFINITE);
icculus@5588
   153
}
icculus@5588
   154
icculus@5588
   155
static Uint8 *
icculus@5588
   156
WINMM_GetDeviceBuf(_THIS)
icculus@5588
   157
{
icculus@5588
   158
    return (Uint8 *) (this->hidden->
icculus@5588
   159
                      wavebuf[this->hidden->next_buffer].lpData);
icculus@5588
   160
}
icculus@5588
   161
icculus@5588
   162
static void
icculus@5588
   163
WINMM_PlayDevice(_THIS)
icculus@5588
   164
{
icculus@5588
   165
    /* Queue it up */
icculus@5588
   166
    waveOutWrite(this->hidden->hout,
icculus@5588
   167
                 &this->hidden->wavebuf[this->hidden->next_buffer],
icculus@5588
   168
                 sizeof(this->hidden->wavebuf[0]));
icculus@5588
   169
    this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
icculus@5588
   170
}
icculus@5588
   171
icculus@10266
   172
static int
icculus@10266
   173
WINMM_CaptureFromDevice(_THIS, void *buffer, int buflen)
icculus@10266
   174
{
icculus@10266
   175
    const int nextbuf = this->hidden->next_buffer;
icculus@10266
   176
    MMRESULT result;
icculus@10266
   177
icculus@10266
   178
    SDL_assert(buflen == this->spec.size);
icculus@10266
   179
icculus@10266
   180
    /* Wait for an audio chunk to finish */
icculus@10266
   181
    WaitForSingleObject(this->hidden->audio_sem, INFINITE);
icculus@10266
   182
icculus@10266
   183
    /* Copy it to caller's buffer... */
icculus@10266
   184
    SDL_memcpy(buffer, this->hidden->wavebuf[nextbuf].lpData, this->spec.size);
icculus@10266
   185
icculus@10266
   186
    /* requeue the buffer that just finished. */
icculus@10266
   187
    result = waveInAddBuffer(this->hidden->hin,
icculus@10266
   188
                             &this->hidden->wavebuf[nextbuf],
icculus@10266
   189
                             sizeof (this->hidden->wavebuf[nextbuf]));
icculus@10266
   190
    if (result != MMSYSERR_NOERROR) {
icculus@10266
   191
        return -1;  /* uhoh! Disable the device. */
icculus@10266
   192
    }
icculus@10266
   193
icculus@10266
   194
    /* queue the next buffer in sequence, next time. */
icculus@10266
   195
    this->hidden->next_buffer = (nextbuf + 1) % NUM_BUFFERS;
icculus@10266
   196
    return this->spec.size;
icculus@10266
   197
}
icculus@10266
   198
icculus@10266
   199
static void
icculus@10266
   200
WINMM_FlushCapture(_THIS)
icculus@10266
   201
{
icculus@10266
   202
    /* Wait for an audio chunk to finish */
icculus@10266
   203
    if (WaitForSingleObject(this->hidden->audio_sem, 0) == WAIT_OBJECT_0) {
icculus@10266
   204
        const int nextbuf = this->hidden->next_buffer;
icculus@10266
   205
        /* requeue the buffer that just finished without reading from it. */
icculus@10266
   206
        waveInAddBuffer(this->hidden->hin,
icculus@10266
   207
                        &this->hidden->wavebuf[nextbuf],
icculus@10266
   208
                        sizeof (this->hidden->wavebuf[nextbuf]));
icculus@10266
   209
        this->hidden->next_buffer = (nextbuf + 1) % NUM_BUFFERS;
icculus@10266
   210
    }
icculus@10266
   211
}
icculus@10266
   212
icculus@5588
   213
static void
icculus@5588
   214
WINMM_CloseDevice(_THIS)
icculus@5588
   215
{
icculus@10255
   216
    int i;
icculus@5588
   217
icculus@10266
   218
    if (this->hidden->hout) {
icculus@10266
   219
        waveOutReset(this->hidden->hout);
icculus@10255
   220
icculus@10266
   221
        /* Clean up mixing buffers */
icculus@10266
   222
        for (i = 0; i < NUM_BUFFERS; ++i) {
icculus@10266
   223
            if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
icculus@10266
   224
                waveOutUnprepareHeader(this->hidden->hout,
icculus@10266
   225
                                       &this->hidden->wavebuf[i],
icculus@10266
   226
                                       sizeof (this->hidden->wavebuf[i]));
icculus@10266
   227
            }
icculus@5588
   228
        }
icculus@10266
   229
icculus@10266
   230
        waveOutClose(this->hidden->hout);
icculus@10255
   231
    }
icculus@5588
   232
icculus@10255
   233
    if (this->hidden->hin) {
icculus@10266
   234
        waveInReset(this->hidden->hin);
icculus@10266
   235
icculus@10266
   236
        /* Clean up mixing buffers */
icculus@10266
   237
        for (i = 0; i < NUM_BUFFERS; ++i) {
icculus@10266
   238
            if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
icculus@10266
   239
                waveInUnprepareHeader(this->hidden->hin,
icculus@10266
   240
                                       &this->hidden->wavebuf[i],
icculus@10266
   241
                                       sizeof (this->hidden->wavebuf[i]));
icculus@10266
   242
            }
icculus@10266
   243
        }
icculus@10255
   244
        waveInClose(this->hidden->hin);
icculus@10255
   245
    }
icculus@5588
   246
icculus@10266
   247
    if (this->hidden->audio_sem) {
icculus@10266
   248
        CloseHandle(this->hidden->audio_sem);
icculus@10255
   249
    }
icculus@5588
   250
icculus@10255
   251
    SDL_free(this->hidden->mixbuf);
icculus@10255
   252
    SDL_free(this->hidden);
icculus@5588
   253
}
icculus@5588
   254
icculus@7461
   255
static SDL_bool
slouken@8585
   256
PrepWaveFormat(_THIS, UINT devId, WAVEFORMATEX *pfmt, const int iscapture)
icculus@7461
   257
{
icculus@7461
   258
    SDL_zerop(pfmt);
icculus@7461
   259
icculus@7461
   260
    if (SDL_AUDIO_ISFLOAT(this->spec.format)) {
icculus@7461
   261
        pfmt->wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
icculus@7461
   262
    } else {
icculus@7461
   263
        pfmt->wFormatTag = WAVE_FORMAT_PCM;
icculus@7461
   264
    }
icculus@7461
   265
    pfmt->wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
icculus@7461
   266
icculus@7461
   267
    pfmt->nChannels = this->spec.channels;
icculus@7461
   268
    pfmt->nSamplesPerSec = this->spec.freq;
icculus@7461
   269
    pfmt->nBlockAlign = pfmt->nChannels * (pfmt->wBitsPerSample / 8);
icculus@7461
   270
    pfmt->nAvgBytesPerSec = pfmt->nSamplesPerSec * pfmt->nBlockAlign;
icculus@7461
   271
icculus@7461
   272
    if (iscapture) {
icculus@7461
   273
        return (waveInOpen(0, devId, pfmt, 0, 0, WAVE_FORMAT_QUERY) == 0);
icculus@7461
   274
    } else {
icculus@7461
   275
        return (waveOutOpen(0, devId, pfmt, 0, 0, WAVE_FORMAT_QUERY) == 0);
icculus@7461
   276
    }
icculus@7461
   277
}
icculus@7461
   278
icculus@5588
   279
static int
icculus@9394
   280
WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
icculus@5588
   281
{
icculus@5588
   282
    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
icculus@5588
   283
    int valid_datatype = 0;
icculus@5588
   284
    MMRESULT result;
icculus@5588
   285
    WAVEFORMATEX waveformat;
slouken@8585
   286
    UINT devId = WAVE_MAPPER;  /* WAVE_MAPPER == choose system's default */
slouken@8585
   287
    UINT i;
icculus@5588
   288
icculus@9394
   289
    if (handle != NULL) {  /* specific device requested? */
icculus@9410
   290
        /* -1 because we increment the original value to avoid NULL. */
icculus@9410
   291
        const size_t val = ((size_t) handle) - 1;
icculus@9394
   292
        devId = (UINT) val;
icculus@5588
   293
    }
icculus@5588
   294
icculus@5588
   295
    /* Initialize all variables that we clean on shutdown */
icculus@5588
   296
    this->hidden = (struct SDL_PrivateAudioData *)
icculus@5588
   297
        SDL_malloc((sizeof *this->hidden));
icculus@5588
   298
    if (this->hidden == NULL) {
icculus@7038
   299
        return SDL_OutOfMemory();
icculus@5588
   300
    }
icculus@10257
   301
    SDL_zerop(this->hidden);
icculus@5588
   302
icculus@5588
   303
    /* Initialize the wavebuf structures for closing */
icculus@5588
   304
    for (i = 0; i < NUM_BUFFERS; ++i)
icculus@5588
   305
        this->hidden->wavebuf[i].dwUser = 0xFFFF;
icculus@5588
   306
icculus@7461
   307
    if (this->spec.channels > 2)
icculus@7461
   308
        this->spec.channels = 2;        /* !!! FIXME: is this right? */
icculus@7461
   309
icculus@5588
   310
    while ((!valid_datatype) && (test_format)) {
icculus@5588
   311
        switch (test_format) {
icculus@5588
   312
        case AUDIO_U8:
icculus@5588
   313
        case AUDIO_S16:
icculus@5588
   314
        case AUDIO_S32:
icculus@7449
   315
        case AUDIO_F32:
icculus@7461
   316
            this->spec.format = test_format;
icculus@7461
   317
            if (PrepWaveFormat(this, devId, &waveformat, iscapture)) {
icculus@7461
   318
                valid_datatype = 1;
icculus@7461
   319
            } else {
icculus@7461
   320
                test_format = SDL_NextAudioFormat();
icculus@7461
   321
            }
icculus@7461
   322
            break;
icculus@5588
   323
icculus@5588
   324
        default:
icculus@5588
   325
            test_format = SDL_NextAudioFormat();
icculus@5588
   326
            break;
icculus@5588
   327
        }
icculus@5588
   328
    }
icculus@5588
   329
icculus@5588
   330
    if (!valid_datatype) {
icculus@7038
   331
        return SDL_SetError("Unsupported audio format");
icculus@5588
   332
    }
icculus@5588
   333
icculus@5588
   334
    /* Update the fragment size as size in bytes */
icculus@5588
   335
    SDL_CalculateAudioSpec(&this->spec);
icculus@5588
   336
icculus@5588
   337
    /* Open the audio device */
icculus@5588
   338
    if (iscapture) {
icculus@5588
   339
        result = waveInOpen(&this->hidden->hin, devId, &waveformat,
icculus@5588
   340
                             (DWORD_PTR) CaptureSound, (DWORD_PTR) this,
icculus@5588
   341
                             CALLBACK_FUNCTION);
icculus@10266
   342
        if (result != MMSYSERR_NOERROR) {
icculus@10266
   343
            return SetMMerror("waveInOpen()", result);
icculus@10266
   344
        }
icculus@5588
   345
    } else {
icculus@5588
   346
        result = waveOutOpen(&this->hidden->hout, devId, &waveformat,
icculus@5588
   347
                             (DWORD_PTR) FillSound, (DWORD_PTR) this,
icculus@5588
   348
                             CALLBACK_FUNCTION);
icculus@10266
   349
        if (result != MMSYSERR_NOERROR) {
icculus@10266
   350
            return SetMMerror("waveOutOpen()", result);
icculus@10266
   351
        }
icculus@5588
   352
    }
icculus@5588
   353
icculus@5588
   354
#ifdef SOUND_DEBUG
icculus@5588
   355
    /* Check the sound device we retrieved */
icculus@5588
   356
    {
icculus@10266
   357
        if (iscapture) {
icculus@10266
   358
            WAVEINCAPS caps;
icculus@10266
   359
            result = waveInGetDevCaps((UINT) this->hidden->hout,
icculus@10266
   360
                                      &caps, sizeof (caps));
icculus@10266
   361
            if (result != MMSYSERR_NOERROR) {
icculus@10266
   362
                return SetMMerror("waveInGetDevCaps()", result);
icculus@10266
   363
            }
icculus@10266
   364
            printf("Audio device: %s\n", caps.szPname);
icculus@10266
   365
        } else {
icculus@10266
   366
            WAVEOUTCAPS caps;
icculus@10266
   367
            result = waveOutGetDevCaps((UINT) this->hidden->hout,
icculus@10266
   368
                                       &caps, sizeof(caps));
icculus@10266
   369
            if (result != MMSYSERR_NOERROR) {
icculus@10266
   370
                return SetMMerror("waveOutGetDevCaps()", result);
icculus@10266
   371
            }
icculus@10266
   372
            printf("Audio device: %s\n", caps.szPname);
icculus@5588
   373
        }
icculus@5588
   374
    }
icculus@5588
   375
#endif
icculus@5588
   376
icculus@5588
   377
    /* Create the audio buffer semaphore */
slouken@12201
   378
    this->hidden->audio_sem = CreateSemaphore(NULL, iscapture ? 0 : NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
icculus@5588
   379
    if (this->hidden->audio_sem == NULL) {
icculus@7038
   380
        return SDL_SetError("Couldn't create semaphore");
icculus@5588
   381
    }
icculus@5588
   382
icculus@5588
   383
    /* Create the sound buffers */
icculus@5588
   384
    this->hidden->mixbuf =
icculus@5588
   385
        (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
icculus@5588
   386
    if (this->hidden->mixbuf == NULL) {
icculus@7038
   387
        return SDL_OutOfMemory();
icculus@5588
   388
    }
icculus@10257
   389
icculus@10257
   390
    SDL_zero(this->hidden->wavebuf);
icculus@5588
   391
    for (i = 0; i < NUM_BUFFERS; ++i) {
icculus@5588
   392
        this->hidden->wavebuf[i].dwBufferLength = this->spec.size;
icculus@5588
   393
        this->hidden->wavebuf[i].dwFlags = WHDR_DONE;
icculus@5588
   394
        this->hidden->wavebuf[i].lpData =
icculus@5588
   395
            (LPSTR) & this->hidden->mixbuf[i * this->spec.size];
icculus@10266
   396
icculus@10266
   397
        if (iscapture) {
icculus@10266
   398
            result = waveInPrepareHeader(this->hidden->hin,
icculus@10266
   399
                                          &this->hidden->wavebuf[i],
icculus@10266
   400
                                          sizeof(this->hidden->wavebuf[i]));
icculus@10266
   401
            if (result != MMSYSERR_NOERROR) {
icculus@10266
   402
                return SetMMerror("waveInPrepareHeader()", result);
icculus@10266
   403
            }
icculus@10266
   404
icculus@10266
   405
            result = waveInAddBuffer(this->hidden->hin,
icculus@10266
   406
                                     &this->hidden->wavebuf[i],
icculus@10266
   407
                                     sizeof(this->hidden->wavebuf[i]));
icculus@10266
   408
            if (result != MMSYSERR_NOERROR) {
icculus@10266
   409
                return SetMMerror("waveInAddBuffer()", result);
icculus@10266
   410
            }
icculus@10266
   411
        } else {
icculus@10266
   412
            result = waveOutPrepareHeader(this->hidden->hout,
icculus@10266
   413
                                          &this->hidden->wavebuf[i],
icculus@10266
   414
                                          sizeof(this->hidden->wavebuf[i]));
icculus@10266
   415
            if (result != MMSYSERR_NOERROR) {
icculus@10266
   416
                return SetMMerror("waveOutPrepareHeader()", result);
icculus@10266
   417
            }
icculus@10266
   418
        }
icculus@10266
   419
    }
icculus@10266
   420
icculus@10266
   421
    if (iscapture) {
icculus@10266
   422
        result = waveInStart(this->hidden->hin);
icculus@5588
   423
        if (result != MMSYSERR_NOERROR) {
icculus@10266
   424
            return SetMMerror("waveInStart()", result);
icculus@5588
   425
        }
icculus@5588
   426
    }
icculus@5588
   427
icculus@7038
   428
    return 0;                   /* Ready to go! */
icculus@5588
   429
}
icculus@5588
   430
icculus@5588
   431
icculus@5588
   432
static int
icculus@5588
   433
WINMM_Init(SDL_AudioDriverImpl * impl)
icculus@5588
   434
{
icculus@5588
   435
    /* Set the function pointers */
icculus@5588
   436
    impl->DetectDevices = WINMM_DetectDevices;
icculus@5588
   437
    impl->OpenDevice = WINMM_OpenDevice;
icculus@5588
   438
    impl->PlayDevice = WINMM_PlayDevice;
icculus@5588
   439
    impl->WaitDevice = WINMM_WaitDevice;
icculus@5588
   440
    impl->GetDeviceBuf = WINMM_GetDeviceBuf;
icculus@10266
   441
    impl->CaptureFromDevice = WINMM_CaptureFromDevice;
icculus@10266
   442
    impl->FlushCapture = WINMM_FlushCapture;
icculus@5588
   443
    impl->CloseDevice = WINMM_CloseDevice;
icculus@5588
   444
icculus@10266
   445
    impl->HasCaptureSupport = SDL_TRUE;
icculus@10266
   446
icculus@5588
   447
    return 1;   /* this audio target is available. */
icculus@5588
   448
}
icculus@5588
   449
icculus@5588
   450
AudioBootStrap WINMM_bootstrap = {
icculus@5588
   451
    "winmm", "Windows Waveform Audio", WINMM_Init, 0
icculus@5588
   452
};
icculus@5588
   453
slouken@6044
   454
#endif /* SDL_AUDIO_DRIVER_WINMM */
slouken@6044
   455
icculus@5588
   456
/* vi: set ts=4 sw=4 expandtab: */