src/audio/directsound/SDL_directsound.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 14 Jul 2013 18:17:28 -0700
changeset 7523 9e9ab1dc3811
parent 7461 489d2bbcf4aa
child 7663 53fe1b64eb2d
permissions -rw-r--r--
Fixed bug 1919 - Window icon disappears as soon as a renderer is created

Sebastian

Setting a window icon works just fine until a renderer is added to the window.
After adding the renderer the icon disappears.

Reproduce by:
- Take the example code from the wiki: http://wiki.libsdl.org/moin.fcg/SDL_SetWindowIcon

- Add the following two lines after SDL_FreeSurface(surface);
SDL_Delay(1000);
SDL_Renderer* ren = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

-compile and run

You will see the window icon correctly at first. After the Delay the Icon will disappear.
slouken@0
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@6885
     3
  Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
slouken@0
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@0
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@0
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@0
    20
*/
slouken@1402
    21
#include "SDL_config.h"
slouken@0
    22
slouken@6044
    23
#if SDL_AUDIO_DRIVER_DSOUND
slouken@6044
    24
slouken@0
    25
/* Allow access to a raw mixing buffer */
slouken@0
    26
slouken@0
    27
#include "SDL_timer.h"
slouken@5090
    28
#include "SDL_loadso.h"
slouken@0
    29
#include "SDL_audio.h"
slouken@1361
    30
#include "../SDL_audio_c.h"
icculus@5587
    31
#include "SDL_directsound.h"
slouken@0
    32
icculus@7449
    33
#ifndef WAVE_FORMAT_IEEE_FLOAT
icculus@7449
    34
#define WAVE_FORMAT_IEEE_FLOAT 0x0003
icculus@7449
    35
#endif
icculus@7449
    36
slouken@0
    37
/* DirectX function pointers for audio */
slouken@5090
    38
static void* DSoundDLL = NULL;
icculus@5587
    39
typedef HRESULT(WINAPI*fnDirectSoundCreate8)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN);
icculus@5587
    40
typedef HRESULT(WINAPI*fnDirectSoundEnumerateW)(LPDSENUMCALLBACKW, LPVOID);
icculus@5587
    41
typedef HRESULT(WINAPI*fnDirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW,LPVOID);
icculus@5587
    42
static fnDirectSoundCreate8 pDirectSoundCreate8 = NULL;
icculus@5587
    43
static fnDirectSoundEnumerateW pDirectSoundEnumerateW = NULL;
icculus@5587
    44
static fnDirectSoundCaptureEnumerateW pDirectSoundCaptureEnumerateW = NULL;
slouken@0
    45
slouken@1895
    46
static void
icculus@2049
    47
DSOUND_Unload(void)
slouken@0
    48
{
icculus@5587
    49
    pDirectSoundCreate8 = NULL;
icculus@5587
    50
    pDirectSoundEnumerateW = NULL;
icculus@5587
    51
    pDirectSoundCaptureEnumerateW = NULL;
slouken@5090
    52
slouken@1895
    53
    if (DSoundDLL != NULL) {
slouken@5090
    54
        SDL_UnloadObject(DSoundDLL);
slouken@5090
    55
        DSoundDLL = NULL;
slouken@1895
    56
    }
slouken@0
    57
}
slouken@0
    58
icculus@2049
    59
icculus@2049
    60
static int
icculus@2049
    61
DSOUND_Load(void)
slouken@0
    62
{
icculus@2049
    63
    int loaded = 0;
icculus@2049
    64
icculus@2049
    65
    DSOUND_Unload();
slouken@0
    66
slouken@5090
    67
    DSoundDLL = SDL_LoadObject("DSOUND.DLL");
icculus@2049
    68
    if (DSoundDLL == NULL) {
icculus@2049
    69
        SDL_SetError("DirectSound: failed to load DSOUND.DLL");
icculus@2049
    70
    } else {
icculus@5587
    71
        /* Now make sure we have DirectX 8 or better... */
icculus@5587
    72
        #define DSOUNDLOAD(f) { \
icculus@5587
    73
            p##f = (fn##f) SDL_LoadFunction(DSoundDLL, #f); \
icculus@5587
    74
            if (!p##f) loaded = 0; \
icculus@2049
    75
        }
icculus@5587
    76
        loaded = 1;  /* will reset if necessary. */
icculus@5587
    77
        DSOUNDLOAD(DirectSoundCreate8);
icculus@5587
    78
        DSOUNDLOAD(DirectSoundEnumerateW);
icculus@5587
    79
        DSOUNDLOAD(DirectSoundCaptureEnumerateW);
icculus@5587
    80
        #undef DSOUNDLOAD
icculus@2049
    81
icculus@5587
    82
        if (!loaded) {
icculus@5587
    83
            SDL_SetError("DirectSound: System doesn't appear to have DX8.");
icculus@2049
    84
        }
slouken@1895
    85
    }
slouken@0
    86
icculus@2049
    87
    if (!loaded) {
icculus@2049
    88
        DSOUND_Unload();
slouken@1895
    89
    }
slouken@0
    90
icculus@2049
    91
    return loaded;
slouken@0
    92
}
slouken@0
    93
icculus@5587
    94
static __inline__ char *
icculus@5587
    95
utf16_to_utf8(const WCHAR *S)
icculus@5587
    96
{
icculus@5587
    97
    /* !!! FIXME: this should be UTF-16, not UCS-2! */
icculus@5587
    98
    return SDL_iconv_string("UTF-8", "UCS-2", (char *)(S),
icculus@5587
    99
                            (SDL_wcslen(S)+1)*sizeof(WCHAR));
icculus@5587
   100
}
slouken@0
   101
icculus@7037
   102
static int
slouken@1895
   103
SetDSerror(const char *function, int code)
slouken@0
   104
{
slouken@1895
   105
    static const char *error;
slouken@1895
   106
    static char errbuf[1024];
slouken@0
   107
slouken@1895
   108
    errbuf[0] = 0;
slouken@1895
   109
    switch (code) {
slouken@1895
   110
    case E_NOINTERFACE:
icculus@5587
   111
        error = "Unsupported interface -- Is DirectX 8.0 or later installed?";
slouken@1895
   112
        break;
slouken@1895
   113
    case DSERR_ALLOCATED:
slouken@1895
   114
        error = "Audio device in use";
slouken@1895
   115
        break;
slouken@1895
   116
    case DSERR_BADFORMAT:
slouken@1895
   117
        error = "Unsupported audio format";
slouken@1895
   118
        break;
slouken@1895
   119
    case DSERR_BUFFERLOST:
slouken@1895
   120
        error = "Mixing buffer was lost";
slouken@1895
   121
        break;
slouken@1895
   122
    case DSERR_CONTROLUNAVAIL:
slouken@1895
   123
        error = "Control requested is not available";
slouken@1895
   124
        break;
slouken@1895
   125
    case DSERR_INVALIDCALL:
slouken@1895
   126
        error = "Invalid call for the current state";
slouken@1895
   127
        break;
slouken@1895
   128
    case DSERR_INVALIDPARAM:
slouken@1895
   129
        error = "Invalid parameter";
slouken@1895
   130
        break;
slouken@1895
   131
    case DSERR_NODRIVER:
slouken@1895
   132
        error = "No audio device found";
slouken@1895
   133
        break;
slouken@1895
   134
    case DSERR_OUTOFMEMORY:
slouken@1895
   135
        error = "Out of memory";
slouken@1895
   136
        break;
slouken@1895
   137
    case DSERR_PRIOLEVELNEEDED:
slouken@1895
   138
        error = "Caller doesn't have priority";
slouken@1895
   139
        break;
slouken@1895
   140
    case DSERR_UNSUPPORTED:
slouken@1895
   141
        error = "Function not supported";
slouken@1895
   142
        break;
slouken@1895
   143
    default:
slouken@1895
   144
        SDL_snprintf(errbuf, SDL_arraysize(errbuf),
slouken@1895
   145
                     "%s: Unknown DirectSound error: 0x%x", function, code);
slouken@1895
   146
        break;
slouken@1895
   147
    }
slouken@1895
   148
    if (!errbuf[0]) {
slouken@1895
   149
        SDL_snprintf(errbuf, SDL_arraysize(errbuf), "%s: %s", function,
slouken@1895
   150
                     error);
slouken@1895
   151
    }
icculus@7037
   152
    return SDL_SetError("%s", errbuf);
slouken@0
   153
}
slouken@0
   154
icculus@5587
   155
icculus@5593
   156
static BOOL CALLBACK
icculus@5593
   157
FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID data)
slouken@0
   158
{
icculus@5593
   159
    SDL_AddAudioDevice addfn = (SDL_AddAudioDevice) data;
icculus@5593
   160
    if (guid != NULL) {  /* skip default device */
icculus@5593
   161
        char *str = utf16_to_utf8(desc);
icculus@5593
   162
        if (str != NULL) {
icculus@5593
   163
            addfn(str);
icculus@5593
   164
            SDL_free(str);  /* addfn() makes a copy of this string. */
icculus@5587
   165
        }
icculus@5587
   166
    }
icculus@5587
   167
    return TRUE;  /* keep enumerating. */
slouken@0
   168
}
slouken@0
   169
icculus@5593
   170
static void
icculus@5593
   171
DSOUND_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
icculus@5587
   172
{
icculus@5587
   173
    if (iscapture) {
icculus@5593
   174
        pDirectSoundCaptureEnumerateW(FindAllDevs, addfn);
icculus@5587
   175
    } else {
icculus@5593
   176
        pDirectSoundEnumerateW(FindAllDevs, addfn);
icculus@5587
   177
    }
icculus@5587
   178
}
icculus@5587
   179
icculus@5587
   180
slouken@1895
   181
static void
icculus@2049
   182
DSOUND_WaitDevice(_THIS)
slouken@0
   183
{
icculus@2049
   184
    DWORD status = 0;
icculus@2049
   185
    DWORD cursor = 0;
icculus@2049
   186
    DWORD junk = 0;
icculus@2049
   187
    HRESULT result = DS_OK;
slouken@0
   188
slouken@1895
   189
    /* Semi-busy wait, since we have no way of getting play notification
slouken@1895
   190
       on a primary mixing buffer located in hardware (DirectX 5.0)
slouken@1895
   191
     */
icculus@2049
   192
    result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
icculus@2049
   193
                                                   &junk, &cursor);
slouken@1895
   194
    if (result != DS_OK) {
slouken@1895
   195
        if (result == DSERR_BUFFERLOST) {
icculus@2049
   196
            IDirectSoundBuffer_Restore(this->hidden->mixbuf);
slouken@1895
   197
        }
slouken@0
   198
#ifdef DEBUG_SOUND
slouken@1895
   199
        SetDSerror("DirectSound GetCurrentPosition", result);
slouken@0
   200
#endif
slouken@1895
   201
        return;
slouken@1895
   202
    }
slouken@0
   203
icculus@2049
   204
    while ((cursor / this->hidden->mixlen) == this->hidden->lastchunk) {
slouken@1895
   205
        /* FIXME: find out how much time is left and sleep that long */
slouken@1895
   206
        SDL_Delay(1);
slouken@0
   207
slouken@1895
   208
        /* Try to restore a lost sound buffer */
icculus@2049
   209
        IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status);
slouken@1895
   210
        if ((status & DSBSTATUS_BUFFERLOST)) {
icculus@2049
   211
            IDirectSoundBuffer_Restore(this->hidden->mixbuf);
icculus@2049
   212
            IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status);
slouken@1895
   213
            if ((status & DSBSTATUS_BUFFERLOST)) {
slouken@1895
   214
                break;
slouken@1895
   215
            }
slouken@1895
   216
        }
slouken@1895
   217
        if (!(status & DSBSTATUS_PLAYING)) {
icculus@2049
   218
            result = IDirectSoundBuffer_Play(this->hidden->mixbuf, 0, 0,
icculus@2049
   219
                                             DSBPLAY_LOOPING);
slouken@1895
   220
            if (result == DS_OK) {
slouken@1895
   221
                continue;
slouken@1895
   222
            }
slouken@0
   223
#ifdef DEBUG_SOUND
slouken@1895
   224
            SetDSerror("DirectSound Play", result);
slouken@0
   225
#endif
slouken@1895
   226
            return;
slouken@1895
   227
        }
slouken@0
   228
slouken@1895
   229
        /* Find out where we are playing */
icculus@2049
   230
        result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
slouken@1895
   231
                                                       &junk, &cursor);
slouken@1895
   232
        if (result != DS_OK) {
slouken@1895
   233
            SetDSerror("DirectSound GetCurrentPosition", result);
slouken@1895
   234
            return;
slouken@1895
   235
        }
slouken@1895
   236
    }
slouken@0
   237
}
slouken@0
   238
slouken@1895
   239
static void
icculus@2049
   240
DSOUND_PlayDevice(_THIS)
slouken@0
   241
{
slouken@1895
   242
    /* Unlock the buffer, allowing it to play */
icculus@2049
   243
    if (this->hidden->locked_buf) {
icculus@2049
   244
        IDirectSoundBuffer_Unlock(this->hidden->mixbuf,
icculus@2049
   245
                                  this->hidden->locked_buf,
icculus@2049
   246
                                  this->hidden->mixlen, NULL, 0);
slouken@1895
   247
    }
slouken@0
   248
slouken@0
   249
}
slouken@0
   250
slouken@1895
   251
static Uint8 *
icculus@2049
   252
DSOUND_GetDeviceBuf(_THIS)
slouken@0
   253
{
icculus@2049
   254
    DWORD cursor = 0;
icculus@2049
   255
    DWORD junk = 0;
icculus@2049
   256
    HRESULT result = DS_OK;
icculus@2049
   257
    DWORD rawlen = 0;
slouken@0
   258
slouken@1895
   259
    /* Figure out which blocks to fill next */
icculus@2049
   260
    this->hidden->locked_buf = NULL;
icculus@2049
   261
    result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
icculus@2049
   262
                                                   &junk, &cursor);
slouken@1895
   263
    if (result == DSERR_BUFFERLOST) {
icculus@2049
   264
        IDirectSoundBuffer_Restore(this->hidden->mixbuf);
icculus@2049
   265
        result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
slouken@1895
   266
                                                       &junk, &cursor);
slouken@1895
   267
    }
slouken@1895
   268
    if (result != DS_OK) {
slouken@1895
   269
        SetDSerror("DirectSound GetCurrentPosition", result);
slouken@1895
   270
        return (NULL);
slouken@1895
   271
    }
icculus@2049
   272
    cursor /= this->hidden->mixlen;
slouken@1877
   273
#ifdef DEBUG_SOUND
slouken@1895
   274
    /* Detect audio dropouts */
slouken@1895
   275
    {
slouken@1895
   276
        DWORD spot = cursor;
icculus@2049
   277
        if (spot < this->hidden->lastchunk) {
icculus@2049
   278
            spot += this->hidden->num_buffers;
slouken@1895
   279
        }
icculus@2049
   280
        if (spot > this->hidden->lastchunk + 1) {
slouken@1895
   281
            fprintf(stderr, "Audio dropout, missed %d fragments\n",
icculus@2049
   282
                    (spot - (this->hidden->lastchunk + 1)));
slouken@1895
   283
        }
slouken@1895
   284
    }
slouken@1877
   285
#endif
icculus@2049
   286
    this->hidden->lastchunk = cursor;
icculus@2049
   287
    cursor = (cursor + 1) % this->hidden->num_buffers;
icculus@2049
   288
    cursor *= this->hidden->mixlen;
slouken@0
   289
slouken@1895
   290
    /* Lock the audio buffer */
icculus@2049
   291
    result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
icculus@2049
   292
                                     this->hidden->mixlen,
slouken@2060
   293
                                     (LPVOID *) & this->hidden->locked_buf,
icculus@2049
   294
                                     &rawlen, NULL, &junk, 0);
slouken@1895
   295
    if (result == DSERR_BUFFERLOST) {
icculus@2049
   296
        IDirectSoundBuffer_Restore(this->hidden->mixbuf);
icculus@2049
   297
        result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
icculus@2049
   298
                                         this->hidden->mixlen,
slouken@3013
   299
                                         (LPVOID *) & this->
slouken@3013
   300
                                         hidden->locked_buf, &rawlen, NULL,
slouken@3013
   301
                                         &junk, 0);
slouken@1895
   302
    }
slouken@1895
   303
    if (result != DS_OK) {
slouken@1895
   304
        SetDSerror("DirectSound Lock", result);
slouken@1895
   305
        return (NULL);
slouken@1895
   306
    }
icculus@2049
   307
    return (this->hidden->locked_buf);
slouken@0
   308
}
slouken@0
   309
slouken@1895
   310
static void
icculus@2049
   311
DSOUND_WaitDone(_THIS)
slouken@0
   312
{
icculus@2049
   313
    Uint8 *stream = DSOUND_GetDeviceBuf(this);
icculus@2049
   314
icculus@2049
   315
    /* Wait for the playing chunk to finish */
icculus@2049
   316
    if (stream != NULL) {
icculus@2049
   317
        SDL_memset(stream, this->spec.silence, this->hidden->mixlen);
icculus@2049
   318
        DSOUND_PlayDevice(this);
slouken@1895
   319
    }
icculus@2049
   320
    DSOUND_WaitDevice(this);
icculus@2049
   321
icculus@2049
   322
    /* Stop the looping sound buffer */
icculus@2049
   323
    IDirectSoundBuffer_Stop(this->hidden->mixbuf);
slouken@0
   324
}
slouken@0
   325
icculus@2049
   326
static void
icculus@2049
   327
DSOUND_CloseDevice(_THIS)
slouken@0
   328
{
icculus@2049
   329
    if (this->hidden != NULL) {
icculus@2049
   330
        if (this->hidden->sound != NULL) {
icculus@2049
   331
            if (this->hidden->mixbuf != NULL) {
icculus@2049
   332
                /* Clean up the audio buffer */
icculus@2049
   333
                IDirectSoundBuffer_Release(this->hidden->mixbuf);
icculus@2049
   334
                this->hidden->mixbuf = NULL;
icculus@2049
   335
            }
icculus@2049
   336
            IDirectSound_Release(this->hidden->sound);
icculus@2049
   337
            this->hidden->sound = NULL;
icculus@2049
   338
        }
slouken@0
   339
icculus@2049
   340
        SDL_free(this->hidden);
icculus@2049
   341
        this->hidden = NULL;
slouken@1895
   342
    }
slouken@0
   343
}
slouken@0
   344
slouken@0
   345
/* This function tries to create a secondary audio buffer, and returns the
slouken@0
   346
   number of audio chunks available in the created buffer.
slouken@0
   347
*/
slouken@1895
   348
static int
icculus@7461
   349
CreateSecondary(_THIS, HWND focus)
slouken@0
   350
{
icculus@2049
   351
    LPDIRECTSOUND sndObj = this->hidden->sound;
icculus@2051
   352
    LPDIRECTSOUNDBUFFER *sndbuf = &this->hidden->mixbuf;
icculus@2049
   353
    Uint32 chunksize = this->spec.size;
slouken@1895
   354
    const int numchunks = 8;
icculus@2049
   355
    HRESULT result = DS_OK;
slouken@1895
   356
    DSBUFFERDESC format;
slouken@1895
   357
    LPVOID pvAudioPtr1, pvAudioPtr2;
slouken@1895
   358
    DWORD dwAudioBytes1, dwAudioBytes2;
icculus@7461
   359
    WAVEFORMATEX wfmt;
icculus@7461
   360
icculus@7461
   361
    SDL_zero(wfmt);
icculus@7461
   362
icculus@7461
   363
    if (SDL_AUDIO_ISFLOAT(this->spec.format)) {
icculus@7461
   364
        wfmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
icculus@7461
   365
    } else {
icculus@7461
   366
        wfmt.wFormatTag = WAVE_FORMAT_PCM;
icculus@7461
   367
    }
icculus@7461
   368
icculus@7461
   369
    wfmt.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
icculus@7461
   370
    wfmt.nChannels = this->spec.channels;
icculus@7461
   371
    wfmt.nSamplesPerSec = this->spec.freq;
icculus@7461
   372
    wfmt.nBlockAlign = wfmt.nChannels * (wfmt.wBitsPerSample / 8);
icculus@7461
   373
    wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign;
icculus@7461
   374
icculus@7461
   375
    /* Update the fragment size as size in bytes */
icculus@7461
   376
    SDL_CalculateAudioSpec(&this->spec);
slouken@0
   377
slouken@1895
   378
    /* Try to set primary mixing privileges */
slouken@1895
   379
    if (focus) {
slouken@1895
   380
        result = IDirectSound_SetCooperativeLevel(sndObj,
slouken@1895
   381
                                                  focus, DSSCL_PRIORITY);
slouken@1895
   382
    } else {
slouken@1895
   383
        result = IDirectSound_SetCooperativeLevel(sndObj,
slouken@1895
   384
                                                  GetDesktopWindow(),
slouken@1895
   385
                                                  DSSCL_NORMAL);
slouken@1895
   386
    }
slouken@1895
   387
    if (result != DS_OK) {
icculus@7038
   388
        return SetDSerror("DirectSound SetCooperativeLevel", result);
slouken@1895
   389
    }
slouken@0
   390
slouken@1895
   391
    /* Try to create the secondary buffer */
icculus@7461
   392
    SDL_zero(format);
slouken@1895
   393
    format.dwSize = sizeof(format);
slouken@1895
   394
    format.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
slouken@1895
   395
    if (!focus) {
slouken@1895
   396
        format.dwFlags |= DSBCAPS_GLOBALFOCUS;
slouken@1895
   397
    } else {
slouken@1895
   398
        format.dwFlags |= DSBCAPS_STICKYFOCUS;
slouken@1895
   399
    }
slouken@1895
   400
    format.dwBufferBytes = numchunks * chunksize;
slouken@1895
   401
    if ((format.dwBufferBytes < DSBSIZE_MIN) ||
slouken@1895
   402
        (format.dwBufferBytes > DSBSIZE_MAX)) {
icculus@7037
   403
        return SDL_SetError("Sound buffer size must be between %d and %d",
icculus@7037
   404
                            DSBSIZE_MIN / numchunks, DSBSIZE_MAX / numchunks);
slouken@1895
   405
    }
slouken@1895
   406
    format.dwReserved = 0;
icculus@7461
   407
    format.lpwfxFormat = &wfmt;
slouken@1895
   408
    result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL);
slouken@1895
   409
    if (result != DS_OK) {
icculus@7037
   410
        return SetDSerror("DirectSound CreateSoundBuffer", result);
slouken@1895
   411
    }
icculus@7461
   412
    IDirectSoundBuffer_SetFormat(*sndbuf, &wfmt);
slouken@0
   413
slouken@1895
   414
    /* Silence the initial audio buffer */
slouken@1895
   415
    result = IDirectSoundBuffer_Lock(*sndbuf, 0, format.dwBufferBytes,
slouken@1895
   416
                                     (LPVOID *) & pvAudioPtr1, &dwAudioBytes1,
slouken@1895
   417
                                     (LPVOID *) & pvAudioPtr2, &dwAudioBytes2,
slouken@1895
   418
                                     DSBLOCK_ENTIREBUFFER);
slouken@1895
   419
    if (result == DS_OK) {
icculus@2049
   420
        SDL_memset(pvAudioPtr1, this->spec.silence, dwAudioBytes1);
slouken@1895
   421
        IDirectSoundBuffer_Unlock(*sndbuf,
slouken@1895
   422
                                  (LPVOID) pvAudioPtr1, dwAudioBytes1,
slouken@1895
   423
                                  (LPVOID) pvAudioPtr2, dwAudioBytes2);
slouken@1895
   424
    }
slouken@118
   425
slouken@1895
   426
    /* We're ready to go */
slouken@1895
   427
    return (numchunks);
slouken@0
   428
}
slouken@0
   429
icculus@5587
   430
typedef struct FindDevGUIDData
icculus@5587
   431
{
icculus@5587
   432
    const char *devname;
icculus@5587
   433
    GUID guid;
icculus@5587
   434
    int found;
icculus@5587
   435
} FindDevGUIDData;
icculus@5587
   436
icculus@5587
   437
static BOOL CALLBACK
icculus@5587
   438
FindDevGUID(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID _data)
icculus@5587
   439
{
icculus@5587
   440
    if (guid != NULL) {  /* skip the default device. */
icculus@5587
   441
        FindDevGUIDData *data = (FindDevGUIDData *) _data;
icculus@5587
   442
        char *str = utf16_to_utf8(desc);
icculus@5587
   443
        const int match = (SDL_strcmp(str, data->devname) == 0);
icculus@5587
   444
        SDL_free(str);
icculus@5587
   445
        if (match) {
icculus@5587
   446
            data->found = 1;
icculus@5587
   447
            SDL_memcpy(&data->guid, guid, sizeof (data->guid));
icculus@5587
   448
            return FALSE;  /* found it! stop enumerating. */
icculus@5587
   449
        }
icculus@5587
   450
    }
icculus@5587
   451
    return TRUE;  /* keep enumerating. */
icculus@5587
   452
}
icculus@5587
   453
slouken@1895
   454
static int
icculus@2049
   455
DSOUND_OpenDevice(_THIS, const char *devname, int iscapture)
slouken@0
   456
{
slouken@1895
   457
    HRESULT result;
icculus@7461
   458
    SDL_bool valid_format = SDL_FALSE;
icculus@7461
   459
    SDL_bool tried_format = SDL_FALSE;
icculus@2049
   460
    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
icculus@5587
   461
    FindDevGUIDData devguid;
icculus@5587
   462
    LPGUID guid = NULL;
slouken@0
   463
icculus@5587
   464
    if (devname != NULL) {
icculus@5587
   465
        devguid.found = 0;
icculus@5587
   466
        devguid.devname = devname;
icculus@5587
   467
        if (iscapture)
icculus@5587
   468
            pDirectSoundCaptureEnumerateW(FindDevGUID, &devguid);
icculus@5587
   469
        else
icculus@5587
   470
            pDirectSoundEnumerateW(FindDevGUID, &devguid);
icculus@5587
   471
icculus@5587
   472
        if (!devguid.found) {
icculus@7038
   473
            return SDL_SetError("DirectSound: Requested device not found");
icculus@5587
   474
        }
icculus@5587
   475
        guid = &devguid.guid;
icculus@5587
   476
    }
icculus@2049
   477
icculus@2049
   478
    /* Initialize all variables that we clean on shutdown */
icculus@2049
   479
    this->hidden = (struct SDL_PrivateAudioData *)
slouken@2060
   480
        SDL_malloc((sizeof *this->hidden));
icculus@2049
   481
    if (this->hidden == NULL) {
icculus@7038
   482
        return SDL_OutOfMemory();
icculus@2049
   483
    }
icculus@2049
   484
    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
icculus@2049
   485
icculus@7461
   486
    /* Open the audio device */
icculus@7461
   487
    result = pDirectSoundCreate8(guid, &this->hidden->sound, NULL);
icculus@7461
   488
    if (result != DS_OK) {
icculus@7461
   489
        DSOUND_CloseDevice(this);
icculus@7461
   490
        return SetDSerror("DirectSoundCreate", result);
icculus@7461
   491
    }
icculus@7461
   492
icculus@2049
   493
    while ((!valid_format) && (test_format)) {
icculus@2049
   494
        switch (test_format) {
slouken@2060
   495
        case AUDIO_U8:
slouken@2060
   496
        case AUDIO_S16:
slouken@2060
   497
        case AUDIO_S32:
icculus@7449
   498
        case AUDIO_F32:
icculus@7461
   499
            tried_format = SDL_TRUE;
slouken@2060
   500
            this->spec.format = test_format;
icculus@7461
   501
            this->hidden->num_buffers = CreateSecondary(this, NULL);
icculus@7461
   502
            if (this->hidden->num_buffers > 0) {
icculus@7461
   503
                valid_format = SDL_TRUE;
icculus@7461
   504
            }
slouken@2060
   505
            break;
icculus@2049
   506
        }
icculus@2049
   507
        test_format = SDL_NextAudioFormat();
icculus@2049
   508
    }
icculus@2049
   509
icculus@2049
   510
    if (!valid_format) {
icculus@2049
   511
        DSOUND_CloseDevice(this);
icculus@7461
   512
        if (tried_format) {
icculus@7461
   513
            return -1;  // CreateSecondary() should have called SDL_SetError().
icculus@7461
   514
        }
icculus@7038
   515
        return SDL_SetError("DirectSound: Unsupported audio format");
icculus@2049
   516
    }
icculus@2049
   517
icculus@2049
   518
    /* The buffer will auto-start playing in DSOUND_WaitDevice() */
icculus@2049
   519
    this->hidden->mixlen = this->spec.size;
slouken@0
   520
icculus@7038
   521
    return 0;                   /* good to go. */
icculus@2049
   522
}
icculus@2049
   523
icculus@2049
   524
icculus@2049
   525
static void
icculus@2049
   526
DSOUND_Deinitialize(void)
icculus@2049
   527
{
icculus@2049
   528
    DSOUND_Unload();
slouken@0
   529
}
slouken@0
   530
icculus@2049
   531
icculus@2049
   532
static int
slouken@2060
   533
DSOUND_Init(SDL_AudioDriverImpl * impl)
icculus@2049
   534
{
icculus@2049
   535
    if (!DSOUND_Load()) {
icculus@2049
   536
        return 0;
icculus@2049
   537
    }
icculus@2049
   538
icculus@2049
   539
    /* Set the function pointers */
icculus@5587
   540
    impl->DetectDevices = DSOUND_DetectDevices;
icculus@2049
   541
    impl->OpenDevice = DSOUND_OpenDevice;
icculus@2049
   542
    impl->PlayDevice = DSOUND_PlayDevice;
icculus@2049
   543
    impl->WaitDevice = DSOUND_WaitDevice;
icculus@2049
   544
    impl->WaitDone = DSOUND_WaitDone;
icculus@2049
   545
    impl->GetDeviceBuf = DSOUND_GetDeviceBuf;
icculus@2049
   546
    impl->CloseDevice = DSOUND_CloseDevice;
icculus@2049
   547
    impl->Deinitialize = DSOUND_Deinitialize;
icculus@2049
   548
icculus@3699
   549
    return 1;   /* this audio target is available. */
icculus@2049
   550
}
icculus@2049
   551
icculus@2049
   552
AudioBootStrap DSOUND_bootstrap = {
icculus@5587
   553
    "directsound", "DirectSound", DSOUND_Init, 0
icculus@2049
   554
};
icculus@2049
   555
slouken@6044
   556
#endif /* SDL_AUDIO_DRIVER_DSOUND */
slouken@6044
   557
slouken@1895
   558
/* vi: set ts=4 sw=4 expandtab: */