src/audio/winmm/SDL_winmm.c
author Sam Lantinga
Mon, 09 Jan 2017 11:58:01 -0800
changeset 10802 6afc9b833867
parent 10737 3406a0f8b041
child 10818 7e06b0e4dbe0
permissions -rw-r--r--
We only need the first few keymaps corresponding to the following constants:
K_NORMTAB, K_SHIFTTAB, K_ALTTAB, K_ALTSHIFTTAB

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