src/java.desktop/windows/native/libjsound/PLATFORM_API_WinOS_DirectSound.cpp
author aivanov
Wed, 30 Oct 2019 14:08:07 +0000
changeset 58859 3fc5905f2bec
parent 55191 feb860d41612
permissions -rw-r--r--
8232724: Remove indirection with calling JNU_NewStringPlatform Reviewed-by: dholmes, clanger
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
7668
d4a77089c587 6962318: Update copyright year
ohair
parents: 7015
diff changeset
     2
 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4384
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4384
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4384
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4384
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4384
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
#define USE_ERROR
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
#define USE_TRACE
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
/* define this for the silencing/servicing code. Requires USE_TRACE */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
//#define USE_DEBUG_SILENCING
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
#ifndef WIN32_EXTRA_LEAN
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
#define WIN32_EXTRA_LEAN
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
#endif
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
#ifndef WIN32_LEAN_AND_MEAN
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
#define WIN32_LEAN_AND_MEAN
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
#endif
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
#include <windows.h>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
#include <mmsystem.h>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
#include <string.h>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
/* include DirectSound headers */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
#include <dsound.h>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
/* include Java Sound specific headers as C code */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
#ifdef __cplusplus
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
extern "C" {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
#endif
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 #include "DirectAudio.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
#ifdef __cplusplus
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
#endif
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
47191
8c95ea7056b7 8177951: Charset problem when the name of the sound device contains Chinese character
serb
parents: 41566
diff changeset
    55
/* include to prevent charset problem */
8c95ea7056b7 8177951: Charset problem when the name of the sound device contains Chinese character
serb
parents: 41566
diff changeset
    56
#include "PLATFORM_API_WinOS_Charset_Util.h"
8c95ea7056b7 8177951: Charset problem when the name of the sound device contains Chinese character
serb
parents: 41566
diff changeset
    57
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
#ifdef USE_DEBUG_SILENCING
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
#define DEBUG_SILENCING0(p) TRACE0(p)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
#define DEBUG_SILENCING1(p1,p2) TRACE1(p1,p2)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
#define DEBUG_SILENCING2(p1,p2,p3) TRACE2(p1,p2,p3)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
#else
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
#define DEBUG_SILENCING0(p)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
#define DEBUG_SILENCING1(p1,p2)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
#define DEBUG_SILENCING2(p1,p2,p3)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
#endif
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
#if USE_DAUDIO == TRUE
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
/* half a minute to wait before device list is re-read */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
#define WAIT_BETWEEN_CACHE_REFRESH_MILLIS 30000
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
/* maximum number of supported devices, playback+capture */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
#define MAX_DS_DEVICES 60
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
typedef struct {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
    INT32 mixerIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
    BOOL isSource;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
    /* either LPDIRECTSOUND or LPDIRECTSOUNDCAPTURE */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
    void* dev;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
    /* how many instances use the dev */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
    INT32 refCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
    GUID guid;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
} DS_AudioDeviceCache;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
static DS_AudioDeviceCache g_audioDeviceCache[MAX_DS_DEVICES];
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
static INT32 g_cacheCount = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
static UINT64 g_lastCacheRefreshTime = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
static INT32 g_mixerCount = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
BOOL DS_lockCache() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
    /* dummy implementation for now, Java does locking */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
    return TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
void DS_unlockCache() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
    /* dummy implementation for now */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
static GUID CLSID_DAUDIO_Zero = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
BOOL isEqualGUID(LPGUID lpGuid1, LPGUID lpGuid2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
    if (lpGuid1 == NULL || lpGuid2 == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
        if (lpGuid1 == lpGuid2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
            return TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
        if (lpGuid1 == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
            lpGuid1 = (LPGUID) (&CLSID_DAUDIO_Zero);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
            lpGuid2 = (LPGUID) (&CLSID_DAUDIO_Zero);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
    return memcmp(lpGuid1, lpGuid2, sizeof(GUID)) == 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
INT32 findCacheItemByGUID(LPGUID lpGuid, BOOL isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
    int i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
    for (i = 0; i < g_cacheCount; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
        if (isSource == g_audioDeviceCache[i].isSource
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
            && isEqualGUID(lpGuid, &(g_audioDeviceCache[i].guid))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
            return i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
    return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
INT32 findCacheItemByMixerIndex(INT32 mixerIndex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
    int i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
    for (i = 0; i < g_cacheCount; i++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
        if (g_audioDeviceCache[i].mixerIndex == mixerIndex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
            return i;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
    return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
typedef struct {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
    INT32 currMixerIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
    BOOL isSource;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
} DS_RefreshCacheStruct;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
BOOL CALLBACK DS_RefreshCacheEnum(LPGUID lpGuid,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
                                  LPCSTR lpstrDescription,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
                                  LPCSTR lpstrModule,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
                                  DS_RefreshCacheStruct* rs) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
    INT32 cacheIndex = findCacheItemByGUID(lpGuid, rs->isSource);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
    /*TRACE3("Enumerating %d: %s (%s)\n", cacheIndex, lpstrDescription, lpstrModule);*/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
    if (cacheIndex == -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
        /* add this device */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
        if (g_cacheCount < MAX_DS_DEVICES-1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
            g_audioDeviceCache[g_cacheCount].mixerIndex = rs->currMixerIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
            g_audioDeviceCache[g_cacheCount].isSource = rs->isSource;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
            g_audioDeviceCache[g_cacheCount].dev = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
            g_audioDeviceCache[g_cacheCount].refCount = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
            if (lpGuid == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
                memset(&(g_audioDeviceCache[g_cacheCount].guid), 0, sizeof(GUID));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
                memcpy(&(g_audioDeviceCache[g_cacheCount].guid), lpGuid, sizeof(GUID));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
            g_cacheCount++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
            rs->currMixerIndex++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
            /* failure case: more than MAX_DS_DEVICES available... */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
        /* device already exists in cache... update mixer number */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
        g_audioDeviceCache[cacheIndex].mixerIndex = rs->currMixerIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
        rs->currMixerIndex++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
    /* continue enumeration */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
    return TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
///// implemented functions of DirectAudio.h
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
INT32 DAUDIO_GetDirectAudioDeviceCount() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
    DS_RefreshCacheStruct rs;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
    INT32 oldCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
    INT32 cacheIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
    if (!DS_lockCache()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
        return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
    if (g_lastCacheRefreshTime == 0
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
        || (UINT64) timeGetTime() > (UINT64) (g_lastCacheRefreshTime + WAIT_BETWEEN_CACHE_REFRESH_MILLIS)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
        /* first, initialize any old cache items */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
        for (cacheIndex = 0; cacheIndex < g_cacheCount; cacheIndex++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
            g_audioDeviceCache[cacheIndex].mixerIndex = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
        /* enumerate all devices and either add them to the device cache,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
         * or refresh the mixer number
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
        rs.currMixerIndex = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
        rs.isSource = TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
        DirectSoundEnumerate((LPDSENUMCALLBACK) DS_RefreshCacheEnum, &rs);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
        /* if we only got the Primary Sound Driver (GUID=NULL),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
         * then there aren't any playback devices installed */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
        if (rs.currMixerIndex == 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
            cacheIndex = findCacheItemByGUID(NULL, TRUE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
            if (cacheIndex == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
                rs.currMixerIndex = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
                g_audioDeviceCache[0].mixerIndex = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
                TRACE0("Removing stale Primary Sound Driver from list.\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
        oldCount = rs.currMixerIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
        rs.isSource = FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
        DirectSoundCaptureEnumerate((LPDSENUMCALLBACK) DS_RefreshCacheEnum, &rs);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
        /* if we only got the Primary Sound Capture Driver (GUID=NULL),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
         * then there aren't any capture devices installed */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
        if ((rs.currMixerIndex - oldCount) == 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
            cacheIndex = findCacheItemByGUID(NULL, FALSE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
            if (cacheIndex != -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
                rs.currMixerIndex = oldCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
                g_audioDeviceCache[cacheIndex].mixerIndex = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
                TRACE0("Removing stale Primary Sound Capture Driver from list.\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
        g_mixerCount = rs.currMixerIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
        g_lastCacheRefreshTime = (UINT64) timeGetTime();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
    DS_unlockCache();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
    /*TRACE1("DirectSound: %d installed devices\n", g_mixerCount);*/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
    return g_mixerCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
BOOL CALLBACK DS_GetDescEnum(LPGUID lpGuid,
47191
8c95ea7056b7 8177951: Charset problem when the name of the sound device contains Chinese character
serb
parents: 41566
diff changeset
   233
                             LPCWSTR lpstrDescription,
8c95ea7056b7 8177951: Charset problem when the name of the sound device contains Chinese character
serb
parents: 41566
diff changeset
   234
                             LPCWSTR lpstrModule,
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
                             DirectAudioDeviceDescription* desc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
    INT32 cacheIndex = findCacheItemByGUID(lpGuid, g_audioDeviceCache[desc->deviceID].isSource);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
    if (cacheIndex == desc->deviceID) {
47191
8c95ea7056b7 8177951: Charset problem when the name of the sound device contains Chinese character
serb
parents: 41566
diff changeset
   239
        UnicodeToUTF8AndCopy(desc->name, lpstrDescription, DAUDIO_STRING_LENGTH);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
        //strncpy(desc->description, lpstrModule, DAUDIO_STRING_LENGTH);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
        desc->maxSimulLines = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
        /* do not continue enumeration */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
        return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
    return TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
INT32 DAUDIO_GetDirectAudioDeviceDescription(INT32 mixerIndex, DirectAudioDeviceDescription* desc) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
    if (!DS_lockCache()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
        return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
    /* set the deviceID field to the cache index */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
    desc->deviceID = findCacheItemByMixerIndex(mixerIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
    if (desc->deviceID < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
        DS_unlockCache();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
        return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
    desc->maxSimulLines = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
    if (g_audioDeviceCache[desc->deviceID].isSource) {
47191
8c95ea7056b7 8177951: Charset problem when the name of the sound device contains Chinese character
serb
parents: 41566
diff changeset
   263
        DirectSoundEnumerateW((LPDSENUMCALLBACKW) DS_GetDescEnum, desc);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
        strncpy(desc->description, "DirectSound Playback", DAUDIO_STRING_LENGTH);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
    } else {
47191
8c95ea7056b7 8177951: Charset problem when the name of the sound device contains Chinese character
serb
parents: 41566
diff changeset
   266
        DirectSoundCaptureEnumerateW((LPDSENUMCALLBACKW) DS_GetDescEnum, desc);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
        strncpy(desc->description, "DirectSound Capture", DAUDIO_STRING_LENGTH);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
    /*desc->vendor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
    desc->version;*/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
    DS_unlockCache();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
    return (desc->maxSimulLines == -1)?TRUE:FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
/* multi-channel info: http://www.microsoft.com/whdc/hwdev/tech/audio/multichaud.mspx */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
//static UINT32 sampleRateArray[] = { 8000, 11025, 16000, 22050, 32000, 44100, 48000, 56000, 88000, 96000, 172000, 192000 };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
static INT32 sampleRateArray[] = { -1 };
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
static INT32 channelsArray[] = { 1, 2};
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
static INT32 bitsArray[] = { 8, 16};
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
#define SAMPLERATE_COUNT sizeof(sampleRateArray)/sizeof(INT32)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
#define CHANNELS_COUNT sizeof(channelsArray)/sizeof(INT32)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
#define BITS_COUNT sizeof(bitsArray)/sizeof(INT32)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* creator) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
    int rateIndex, channelIndex, bitIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
    /* no need to lock, since deviceID identifies the device sufficiently */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
    /* sanity */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
    if (deviceID >= g_cacheCount) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
        return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
    if ((g_audioDeviceCache[deviceID].isSource && !isSource)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
        || (!g_audioDeviceCache[deviceID].isSource && isSource)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
        /* only support Playback or Capture */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
        return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
    for (rateIndex = 0; rateIndex < SAMPLERATE_COUNT; rateIndex++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
        for (channelIndex = 0; channelIndex < CHANNELS_COUNT; channelIndex++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
            for (bitIndex = 0; bitIndex < BITS_COUNT; bitIndex++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
                DAUDIO_AddAudioFormat(creator, bitsArray[bitIndex],
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
                                      ((bitsArray[bitIndex] + 7) / 8) * channelsArray[channelIndex],
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
                                      channelsArray[channelIndex],
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
                                      (float) sampleRateArray[rateIndex],
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
                                      DAUDIO_PCM,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
                                      (bitsArray[bitIndex]==8)?FALSE:TRUE,  /* signed */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
                                      (bitsArray[bitIndex]==8)?FALSE:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
#ifndef _LITTLE_ENDIAN
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
                                      TRUE /* big endian */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
#else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
                                      FALSE /* little endian */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
#endif
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
                                      );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
typedef struct {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
    int deviceID;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
    /* for convenience */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
    BOOL isSource;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
    /* the secondary buffer (Playback) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
    LPDIRECTSOUNDBUFFER playBuffer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
    /* the secondary buffer (Capture) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
    LPDIRECTSOUNDCAPTUREBUFFER captureBuffer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
    /* size of the directsound buffer, usually 2 seconds */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
    int dsBufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
    /* size of the read/write-ahead, as specified by Java */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
    int bufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
    int bitsPerSample;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
    int frameSize; // storage size in Bytes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
    UINT64 framePos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
    /* where to write into the buffer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
     * -1 if at current position (Playback)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
     * For Capture, this is the read position
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
    int writePos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
    /* if start() had been called */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
    BOOL started;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
    /* how many bytes there is silence from current write position */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
    int silencedBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
    BOOL underrun;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
} DS_Info;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
55191
feb860d41612 8224056: Fix some assignments of string literals to LPSTR (instead of LPCSTR)
prr
parents: 47216
diff changeset
   360
LPCSTR TranslateDSError(HRESULT hr) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
    switch(hr) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
        case DSERR_ALLOCATED:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
            return "DSERR_ALLOCATED";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
        case DSERR_CONTROLUNAVAIL:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
            return "DSERR_CONTROLUNAVAIL";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
        case DSERR_INVALIDPARAM:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
            return "DSERR_INVALIDPARAM";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
        case DSERR_INVALIDCALL:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
            return "DSERR_INVALIDCALL";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
        case DSERR_GENERIC:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
            return "DSERR_GENERIC";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
        case DSERR_PRIOLEVELNEEDED:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
            return "DSERR_PRIOLEVELNEEDED";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
        case DSERR_OUTOFMEMORY:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
            return "DSERR_OUTOFMEMORY";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
        case DSERR_BADFORMAT:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
            return "DSERR_BADFORMAT";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
        case DSERR_UNSUPPORTED:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
            return "DSERR_UNSUPPORTED";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
        case DSERR_NODRIVER:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
            return "DSERR_NODRIVER";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
        case DSERR_ALREADYINITIALIZED:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
            return "DSERR_ALREADYINITIALIZED";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
        case DSERR_NOAGGREGATION:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
            return "DSERR_NOAGGREGATION";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
        case DSERR_BUFFERLOST:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
            return "DSERR_BUFFERLOST";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
        case DSERR_OTHERAPPHASPRIO:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
            return "DSERR_OTHERAPPHASPRIO";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
        case DSERR_UNINITIALIZED:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
            return "DSERR_UNINITIALIZED";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
        default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
            return "Unknown HRESULT";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
** data/routines for starting DS buffers by separate thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
** (joint into DS_StartBufferHelper class)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
** see cr6372428: playback fails after exiting from thread that has started it
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
** due IDirectSoundBuffer8::Play() description:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
** http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
**       /directx/htm/idirectsoundbuffer8play.asp
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
** (remark section): If the application is multithreaded, the thread that plays
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
** the buffer must continue to exist as long as the buffer is playing.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
** Buffers created on WDM drivers stop playing when the thread is terminated.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
** IDirectSoundCaptureBuffer8::Start() has the same remark:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
** http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
**       /directx/htm/idirectsoundcapturebuffer8start.asp
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
*/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
class DS_StartBufferHelper {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
public:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
    /* starts DirectSound buffer (playback or capture) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
    static HRESULT StartBuffer(DS_Info* info);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
    /* checks for initialization success */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
    static inline BOOL isInitialized() { return data.threadHandle != NULL; }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
protected:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
    DS_StartBufferHelper() {}  // no need to create an instance
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
    /* data class */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
    class Data {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
    public:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
        Data();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
        ~Data();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
        // public data to access from parent class
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
        CRITICAL_SECTION crit_sect;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
        volatile HANDLE threadHandle;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
        volatile HANDLE startEvent;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
        volatile HANDLE startedEvent;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
        volatile DS_Info* line2Start;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
        volatile HRESULT startResult;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
    } static data;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
    /* StartThread function */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
    static DWORD WINAPI __stdcall ThreadProc(void *param);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
};
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
/* StartBufferHelper class implementation
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
*/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
DS_StartBufferHelper::Data DS_StartBufferHelper::data;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
DS_StartBufferHelper::Data::Data() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
    threadHandle = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
    ::InitializeCriticalSection(&crit_sect);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
    startEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
    startedEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
    if (startEvent != NULL && startedEvent != NULL)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
        threadHandle = ::CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
DS_StartBufferHelper::Data::~Data() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
    ::EnterCriticalSection(&crit_sect);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
    if (threadHandle != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
        // terminate thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
        line2Start = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
        ::SetEvent(startEvent);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
        ::CloseHandle(threadHandle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
        threadHandle = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
    ::LeaveCriticalSection(&crit_sect);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
    // won't delete startEvent/startedEvent/crit_sect
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
    // - Windows will do during process shutdown
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
DWORD WINAPI __stdcall DS_StartBufferHelper::ThreadProc(void *param)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
{
7015
7fe7dbe02025 6950553: Applet: IE process crash in OLE32.DLL when playing a sound
amenkov
parents: 5506
diff changeset
   482
    ::CoInitialize(NULL);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
    while (1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
        // wait for something to do
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
        ::WaitForSingleObject(data.startEvent, INFINITE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
        if (data.line2Start == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
            // (data.line2Start == NULL) is a signal to terminate thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
        if (data.line2Start->isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
            data.startResult =
4384
4f4dae717b45 6887318: Incorrect constant used in DirectSound Mixer implementation
amenkov
parents: 2
diff changeset
   492
                data.line2Start->playBuffer->Play(0, 0, DSBPLAY_LOOPING);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
            data.startResult =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
                data.line2Start->captureBuffer->Start(DSCBSTART_LOOPING);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
        ::SetEvent(data.startedEvent);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
    }
7015
7fe7dbe02025 6950553: Applet: IE process crash in OLE32.DLL when playing a sound
amenkov
parents: 5506
diff changeset
   499
    ::CoUninitialize();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
    return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
HRESULT DS_StartBufferHelper::StartBuffer(DS_Info* info) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
    HRESULT hr;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
    ::EnterCriticalSection(&data.crit_sect);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
    if (!isInitialized()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
        ::LeaveCriticalSection(&data.crit_sect);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
        return E_FAIL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
    data.line2Start = info;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
    ::SetEvent(data.startEvent);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
    ::WaitForSingleObject(data.startedEvent, INFINITE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
    hr = data.startResult;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
    ::LeaveCriticalSection(&data.crit_sect);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
    return hr;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
/* helper routines for DS buffer positions */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
/* returns distance from pos1 to pos2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
inline int DS_getDistance(DS_Info* info, int pos1, int pos2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
    int distance = pos2 - pos1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
    while (distance < 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
        distance += info->dsBufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
    return distance;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
/* adds 2 positions
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
inline int DS_addPos(DS_Info* info, int pos1, int pos2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
    int result = pos1 + pos2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
    while (result >= info->dsBufferSizeInBytes)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
        result -= info->dsBufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
    return result;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
BOOL DS_addDeviceRef(INT32 deviceID) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
    HWND ownerWindow;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
    HRESULT res = DS_OK;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
    LPDIRECTSOUND devPlay;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
    LPDIRECTSOUNDCAPTURE devCapture;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
    LPGUID lpGuid = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
    if (g_audioDeviceCache[deviceID].dev == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
        /* Create DirectSound */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
        TRACE1("Creating DirectSound object for device %d\n", deviceID);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
        lpGuid = &(g_audioDeviceCache[deviceID].guid);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
        if (isEqualGUID(lpGuid, NULL)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
            lpGuid = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
        if (g_audioDeviceCache[deviceID].isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
            res = DirectSoundCreate(lpGuid, &devPlay, NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
            g_audioDeviceCache[deviceID].dev = (void*) devPlay;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
            res = DirectSoundCaptureCreate(lpGuid, &devCapture, NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
            g_audioDeviceCache[deviceID].dev = (void*) devCapture;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
        g_audioDeviceCache[deviceID].refCount = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
        if (FAILED(res)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
            ERROR1("DAUDIO_Open: ERROR: Failed to create DirectSound: %s", TranslateDSError(res));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
            g_audioDeviceCache[deviceID].dev = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
            return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
        if (g_audioDeviceCache[deviceID].isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
            ownerWindow = GetForegroundWindow();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
            if (ownerWindow == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
                ownerWindow = GetDesktopWindow();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
            TRACE0("DAUDIO_Open: Setting cooperative level\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
            res = devPlay->SetCooperativeLevel(ownerWindow, DSSCL_NORMAL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
            if (FAILED(res)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
                ERROR1("DAUDIO_Open: ERROR: Failed to set cooperative level: %s", TranslateDSError(res));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
                return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
    g_audioDeviceCache[deviceID].refCount++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
    return TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
#define DEV_PLAY(devID)    ((LPDIRECTSOUND) g_audioDeviceCache[devID].dev)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
#define DEV_CAPTURE(devID) ((LPDIRECTSOUNDCAPTURE) g_audioDeviceCache[devID].dev)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
void DS_removeDeviceRef(INT32 deviceID) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
    if (g_audioDeviceCache[deviceID].refCount) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
        g_audioDeviceCache[deviceID].refCount--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
    if (g_audioDeviceCache[deviceID].refCount == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
        if (g_audioDeviceCache[deviceID].dev != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
            if (g_audioDeviceCache[deviceID].isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
                DEV_PLAY(deviceID)->Release();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
                DEV_CAPTURE(deviceID)->Release();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
            g_audioDeviceCache[deviceID].dev = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
#ifndef _WAVEFORMATEXTENSIBLE_
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
#define _WAVEFORMATEXTENSIBLE_
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
typedef struct {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
    WAVEFORMATEX    Format;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
    union {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
        WORD wValidBitsPerSample;       /* bits of precision  */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
        WORD wSamplesPerBlock;          /* valid if wBitsPerSample==0 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
        WORD wReserved;                 /* If neither applies, set to zero. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
    } Samples;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
    DWORD           dwChannelMask;      /* which channels are */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
                                        /* present in stream  */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
    GUID            SubFormat;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
} WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
#endif // !_WAVEFORMATEXTENSIBLE_
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
#if !defined(WAVE_FORMAT_EXTENSIBLE)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
#define  WAVE_FORMAT_EXTENSIBLE                 0xFFFE
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
#endif // !defined(WAVE_FORMAT_EXTENSIBLE)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
#if !defined(DEFINE_WAVEFORMATEX_GUID)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
#define DEFINE_WAVEFORMATEX_GUID(x) (USHORT)(x), 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
#endif
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
#ifndef STATIC_KSDATAFORMAT_SUBTYPE_PCM
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
#define STATIC_KSDATAFORMAT_SUBTYPE_PCM\
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
    DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_PCM)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
#endif
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
void createWaveFormat(WAVEFORMATEXTENSIBLE* format,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
                      int sampleRate,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
                      int channels,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
                      int bits,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
                      int significantBits) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
    GUID subtypePCM = {STATIC_KSDATAFORMAT_SUBTYPE_PCM};
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
    format->Format.nSamplesPerSec = (DWORD)sampleRate;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
    format->Format.nChannels = (WORD) channels;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
    /* do not support useless padding, like 24-bit samples stored in 32-bit containers */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
    format->Format.wBitsPerSample = (WORD) ((bits + 7) & 0xFFF8);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
    if (channels <= 2 && bits <= 16) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
        format->Format.wFormatTag = WAVE_FORMAT_PCM;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
        format->Format.cbSize = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
        format->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
        format->Format.cbSize = 22;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
        format->Samples.wValidBitsPerSample = bits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
        /* no way to specify speaker locations */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
        format->dwChannelMask = 0xFFFFFFFF;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
        format->SubFormat = subtypePCM;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
    format->Format.nBlockAlign = (WORD)((format->Format.wBitsPerSample * format->Format.nChannels) / 8);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
    format->Format.nAvgBytesPerSec = format->Format.nSamplesPerSec * format->Format.nBlockAlign;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
/* fill buffer with silence
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
void DS_clearBuffer(DS_Info* info, BOOL fromWritePos) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
    UBYTE* pb1=NULL, *pb2=NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
    DWORD  cb1=0, cb2=0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
    DWORD flags = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
    int start, count;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
    TRACE1("> DS_clearBuffer for device %d\n", info->deviceID);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
    if (info->isSource)  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
        if (fromWritePos) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
                DWORD playCursor, writeCursor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
                int end;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
                if (FAILED(info->playBuffer->GetCurrentPosition(&playCursor, &writeCursor))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
                    ERROR0("  DS_clearBuffer: ERROR: Failed to get current position.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
                    TRACE0("< DS_clearbuffer\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
                DEBUG_SILENCING2("  DS_clearBuffer: DS playPos=%d  myWritePos=%d", (int) playCursor, (int) info->writePos);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
                if (info->writePos >= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
                    start = info->writePos + info->silencedBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
                    start = writeCursor + info->silencedBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
                    //flags |= DSBLOCK_FROMWRITECURSOR;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
                while (start >= info->dsBufferSizeInBytes) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
                    start -= info->dsBufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
                // fix for bug 6251460 (REGRESSION: short sounds do not play)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
                // for unknown reason with hardware DS buffer playCursor sometimes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
                // jumps back for little interval (mostly 2-8 bytes) (writeCursor moves forward as usual)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
                // The issue happens right after start playing and for short sounds only (less then DS buffer,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
                // when whole sound written into the buffer and remaining space filled by silence)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
                // the case doesn't produce any audible aftifacts so just catch it to prevent filling
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
                // whole buffer by silence.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
                if (((int)playCursor <= start && start < (int)writeCursor)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
                    || (writeCursor < playCursor    // buffer bound is between playCursor & writeCursor
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
                        && (start < (int)writeCursor || (int)playCursor <= start))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
                count = info->dsBufferSizeInBytes - info->silencedBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
                // why / 4?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
                //if (count > info->dsBufferSizeInBytes / 4) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
                //    count = info->dsBufferSizeInBytes / 4;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
                //}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
                end = start + count;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
                if ((int) playCursor < start) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
                    playCursor += (DWORD) info->dsBufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
                if (start <= (int) playCursor && end > (int) playCursor) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
                    /* at maximum, silence until play cursor */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
                    count = (int) playCursor - start;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
#ifdef USE_TRACE
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
                    if ((int) playCursor >= info->dsBufferSizeInBytes) playCursor -= (DWORD) info->dsBufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
                    TRACE3("\n  DS_clearBuffer: Start Writing from %d, "
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
                           "would overwrite playCursor=%d, so reduce count to %d\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
                           start, playCursor, count);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
#endif
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
                DEBUG_SILENCING2("  clearing buffer from %d, count=%d. ", (int)start, (int) count);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
                if (count <= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
                    DEBUG_SILENCING0("\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
                    TRACE1("< DS_clearBuffer: no need to clear, silencedBytes=%d\n", info->silencedBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
                    return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
                start = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
                count = info->dsBufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
                flags |= DSBLOCK_ENTIREBUFFER;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
        if (FAILED(info->playBuffer->Lock(start,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
                                          count,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
                                          (LPVOID*) &pb1, &cb1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
                                          (LPVOID*) &pb2, &cb2, flags))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
            ERROR0("\n  DS_clearBuffer: ERROR: Failed to lock sound buffer.\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
            TRACE0("< DS_clearbuffer\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
        if (FAILED(info->captureBuffer->Lock(0,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
                                             info->dsBufferSizeInBytes,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   740
                                             (LPVOID*) &pb1, &cb1,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
                                             (LPVOID*) &pb2, &cb2, DSCBLOCK_ENTIREBUFFER))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   742
            ERROR0("  DS_clearBuffer: ERROR: Failed to lock sound buffer.\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   743
            TRACE0("< DS_clearbuffer\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   744
            return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
    if (pb1!=NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
        memset(pb1, (info->bitsPerSample == 8)?128:0, cb1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
    if (pb2!=NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
        memset(pb2, (info->bitsPerSample == 8)?128:0, cb2);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
    if (info->isSource)  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
        info->playBuffer->Unlock( pb1, cb1, pb2, cb2 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
        if (!fromWritePos) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   756
            /* doesn't matter where to start writing next time */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
            info->writePos = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
            info->silencedBytes = info->dsBufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
            info->silencedBytes += (cb1+cb2);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
            if (info->silencedBytes > info->dsBufferSizeInBytes) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
                ERROR1("  DS_clearbuffer: ERROR: silencedBytes=%d exceeds buffer size!\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
                       info->silencedBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
                info->silencedBytes = info->dsBufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
        DEBUG_SILENCING2("  silencedBytes=%d, my writePos=%d\n", (int)info->silencedBytes, (int)info->writePos);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
        info->captureBuffer->Unlock( pb1, cb1, pb2, cb2 );
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   771
    TRACE0("< DS_clearbuffer\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   772
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
/* returns pointer to buffer */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
void* DS_createSoundBuffer(DS_Info* info,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
                          float sampleRate,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
                          int sampleSizeInBits,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
                          int channels,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
                          int bufferSizeInBytes) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
    DSBUFFERDESC dsbdesc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
    DSCBUFFERDESC dscbdesc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
    HRESULT res;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
    WAVEFORMATEXTENSIBLE format;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
    void* buffer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
    TRACE1("Creating secondary buffer for device %d\n", info->deviceID);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
    createWaveFormat(&format,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
                     (int) sampleRate,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
                     channels,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
                     info->frameSize / channels * 8,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
                     sampleSizeInBits);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
    /* 2 second secondary buffer */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
    info->dsBufferSizeInBytes = 2 * ((int) sampleRate) * info->frameSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
    if (bufferSizeInBytes > info->dsBufferSizeInBytes / 2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
        bufferSizeInBytes = info->dsBufferSizeInBytes / 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
    bufferSizeInBytes = (bufferSizeInBytes / info->frameSize) * info->frameSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
    info->bufferSizeInBytes = bufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
    if (info->isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
        memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
        dsbdesc.dwSize = sizeof(DSBUFFERDESC);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
        dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
                    | DSBCAPS_GLOBALFOCUS;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
        dsbdesc.dwBufferBytes = info->dsBufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
        dsbdesc.lpwfxFormat = (WAVEFORMATEX*) &format;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
        res = DEV_PLAY(info->deviceID)->CreateSoundBuffer
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
            (&dsbdesc, (LPDIRECTSOUNDBUFFER*) &buffer, NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
        memset(&dscbdesc, 0, sizeof(DSCBUFFERDESC));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
        dscbdesc.dwSize = sizeof(DSCBUFFERDESC);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
        dscbdesc.dwFlags = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
        dscbdesc.dwBufferBytes = info->dsBufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
        dscbdesc.lpwfxFormat = (WAVEFORMATEX*) &format;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   818
        res = DEV_CAPTURE(info->deviceID)->CreateCaptureBuffer
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
            (&dscbdesc, (LPDIRECTSOUNDCAPTUREBUFFER*) &buffer, NULL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
    if (FAILED(res)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   822
        ERROR1("DS_createSoundBuffer: ERROR: Failed to create sound buffer: %s", TranslateDSError(res));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   823
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   824
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   825
    return buffer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   826
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   827
90ce3da70b43 Initial load
duke
parents:
diff changeset
   828
void DS_destroySoundBuffer(DS_Info* info) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   829
    if (info->playBuffer != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   830
        info->playBuffer->Release();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   831
        info->playBuffer = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   832
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   833
    if (info->captureBuffer != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   834
        info->captureBuffer->Release();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   835
        info->captureBuffer = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   836
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   837
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
                  int encoding, float sampleRate, int sampleSizeInBits,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   842
                  int frameSize, int channels,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
                  int isSigned, int isBigEndian, int bufferSizeInBytes) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   844
90ce3da70b43 Initial load
duke
parents:
diff changeset
   845
    DS_Info* info;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   846
    void* buffer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   847
90ce3da70b43 Initial load
duke
parents:
diff changeset
   848
    TRACE0("> DAUDIO_Open\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   849
90ce3da70b43 Initial load
duke
parents:
diff changeset
   850
    /* some sanity checks */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   851
    if (deviceID >= g_cacheCount) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   852
        ERROR1("DAUDIO_Open: ERROR: cannot open the device with deviceID=%d!\n", deviceID);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   853
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   854
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   855
    if ((g_audioDeviceCache[deviceID].isSource && !isSource)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   856
        || (!g_audioDeviceCache[deviceID].isSource && isSource)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   857
        /* only support Playback or Capture */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   858
        ERROR0("DAUDIO_Open: ERROR: Cache is corrupt: cannot open the device in specified isSource mode!\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   859
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   860
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   861
    if (encoding != DAUDIO_PCM) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   862
        ERROR1("DAUDIO_Open: ERROR: cannot open the device with encoding=%d!\n", encoding);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   863
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   864
    }
41566
f52207d194bf 8157753: Audio replay enhancement
serb
parents: 25859
diff changeset
   865
    if (channels <= 0) {
f52207d194bf 8157753: Audio replay enhancement
serb
parents: 25859
diff changeset
   866
        ERROR1("DAUDIO_Open: ERROR: Invalid number of channels=%d!\n", channels);
f52207d194bf 8157753: Audio replay enhancement
serb
parents: 25859
diff changeset
   867
        return NULL;
f52207d194bf 8157753: Audio replay enhancement
serb
parents: 25859
diff changeset
   868
    }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   869
    if (sampleSizeInBits > 8 &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   870
#ifdef _LITTLE_ENDIAN
90ce3da70b43 Initial load
duke
parents:
diff changeset
   871
        isBigEndian
90ce3da70b43 Initial load
duke
parents:
diff changeset
   872
#else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   873
        !isBigEndian
90ce3da70b43 Initial load
duke
parents:
diff changeset
   874
#endif
90ce3da70b43 Initial load
duke
parents:
diff changeset
   875
        ) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   876
        ERROR1("DAUDIO_Open: ERROR: wrong endianness: isBigEndian==%d!\n", isBigEndian);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   877
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   878
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   879
    if (sampleSizeInBits == 8 && isSigned) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   880
        ERROR0("DAUDIO_Open: ERROR: wrong signed'ness: with 8 bits, data must be unsigned!\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   881
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   882
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   883
    if (!DS_StartBufferHelper::isInitialized()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   884
        ERROR0("DAUDIO_Open: ERROR: StartBufferHelper initialization was failed!\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   885
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   886
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   887
90ce3da70b43 Initial load
duke
parents:
diff changeset
   888
    info = (DS_Info*) malloc(sizeof(DS_Info));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   889
    if (!info) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   890
        ERROR0("DAUDIO_Open: ERROR: Out of memory\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   891
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   892
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   893
    memset(info, 0, sizeof(DS_Info));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   894
90ce3da70b43 Initial load
duke
parents:
diff changeset
   895
    info->deviceID = deviceID;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   896
    info->isSource = isSource;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   897
    info->bitsPerSample = sampleSizeInBits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   898
    info->frameSize = frameSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   899
    info->framePos = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   900
    info->started = FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   901
    info->underrun = FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   902
90ce3da70b43 Initial load
duke
parents:
diff changeset
   903
    if (!DS_addDeviceRef(deviceID)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   904
        DS_removeDeviceRef(deviceID);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   905
        free(info);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   906
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   907
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   908
90ce3da70b43 Initial load
duke
parents:
diff changeset
   909
    buffer = DS_createSoundBuffer(info,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   910
                                  sampleRate,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   911
                                  sampleSizeInBits,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   912
                                  channels,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   913
                                  bufferSizeInBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   914
    if (!buffer) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   915
        DS_removeDeviceRef(deviceID);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   916
        free(info);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   917
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   918
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   919
90ce3da70b43 Initial load
duke
parents:
diff changeset
   920
    if (info->isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   921
        info->playBuffer = (LPDIRECTSOUNDBUFFER) buffer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   922
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   923
        info->captureBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) buffer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   924
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   925
    DS_clearBuffer(info, FALSE /* entire buffer */);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   926
90ce3da70b43 Initial load
duke
parents:
diff changeset
   927
    /* use writepos of device */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   928
    if (info->isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   929
        info->writePos = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   930
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   931
        info->writePos = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   932
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   933
90ce3da70b43 Initial load
duke
parents:
diff changeset
   934
    TRACE0("< DAUDIO_Open: Opened device successfully.\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   935
    return (void*) info;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   936
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   937
90ce3da70b43 Initial load
duke
parents:
diff changeset
   938
int DAUDIO_Start(void* id, int isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   939
    DS_Info* info = (DS_Info*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   940
    HRESULT res = DS_OK;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   941
    DWORD status;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   942
90ce3da70b43 Initial load
duke
parents:
diff changeset
   943
    TRACE0("> DAUDIO_Start\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   944
90ce3da70b43 Initial load
duke
parents:
diff changeset
   945
    if (info->isSource)  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   946
        res = info->playBuffer->GetStatus(&status);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   947
        if (res == DS_OK) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   948
            if (status & DSBSTATUS_LOOPING) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   949
                ERROR0("DAUDIO_Start: ERROR: Already started!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   950
                return TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   951
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   952
90ce3da70b43 Initial load
duke
parents:
diff changeset
   953
            /* only start buffer if already something written to it */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   954
            if (info->writePos >= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   955
                res = DS_StartBufferHelper::StartBuffer(info);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   956
                if (res == DSERR_BUFFERLOST) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   957
                    res = info->playBuffer->Restore();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   958
                    if (res == DS_OK) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   959
                        DS_clearBuffer(info, FALSE /* entire buffer */);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   960
                        /* write() will trigger actual device start */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   961
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   962
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   963
                    /* make sure that we will have silence after
90ce3da70b43 Initial load
duke
parents:
diff changeset
   964
                       the currently valid audio data */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   965
                    DS_clearBuffer(info, TRUE /* from write position */);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   966
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   967
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   968
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   969
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   970
        if (info->captureBuffer->GetStatus(&status) == DS_OK) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   971
            if (status & DSCBSTATUS_LOOPING) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   972
                ERROR0("DAUDIO_Start: ERROR: Already started!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   973
                return TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   974
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   975
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   976
        res = DS_StartBufferHelper::StartBuffer(info);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   977
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   978
    if (FAILED(res)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   979
        ERROR1("DAUDIO_Start: ERROR: Failed to start: %s", TranslateDSError(res));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   980
        return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   981
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   982
    info->started = TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   983
    return TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   984
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   985
90ce3da70b43 Initial load
duke
parents:
diff changeset
   986
int DAUDIO_Stop(void* id, int isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   987
    DS_Info* info = (DS_Info*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   988
90ce3da70b43 Initial load
duke
parents:
diff changeset
   989
    TRACE0("> DAUDIO_Stop\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   990
90ce3da70b43 Initial load
duke
parents:
diff changeset
   991
    info->started = FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   992
    if (info->isSource)  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   993
        info->playBuffer->Stop();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   994
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   995
        info->captureBuffer->Stop();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   996
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   997
90ce3da70b43 Initial load
duke
parents:
diff changeset
   998
    TRACE0("< DAUDIO_Stop\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   999
    return TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1000
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1001
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1002
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1003
void DAUDIO_Close(void* id, int isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1004
    DS_Info* info = (DS_Info*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1005
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1006
    TRACE0("DAUDIO_Close\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1007
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1008
    if (info != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1009
        DS_destroySoundBuffer(info);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1010
        DS_removeDeviceRef(info->deviceID);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1011
        free(info);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1012
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1013
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1014
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1015
/* Check buffer for underrun
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1016
 * This method is only meaningful for Output devices (write devices).
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1017
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1018
void DS_CheckUnderrun(DS_Info* info, DWORD playCursor, DWORD writeCursor) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1019
    TRACE5("DS_CheckUnderrun: playCursor=%d, writeCursor=%d, "
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1020
           "info->writePos=%d  silencedBytes=%d  dsBufferSizeInBytes=%d\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1021
           (int) playCursor, (int) writeCursor, (int) info->writePos,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1022
           (int) info->silencedBytes, (int) info->dsBufferSizeInBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1023
    if (info->underrun || info->writePos < 0) return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1024
    int writeAhead = DS_getDistance(info, writeCursor, info->writePos);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1025
    if (writeAhead > info->bufferSizeInBytes) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1026
        // this may occur after Stop(), when writeCursor decreases (real valid data size > bufferSizeInBytes)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1027
        // But the case can occur only when we have more then info->bufferSizeInBytes valid bytes
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1028
        // (and less then (info->dsBufferSizeInBytes - info->bufferSizeInBytes) silenced bytes)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1029
        // If we already have a lot of silencedBytes after valid data (written by
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1030
        // DAUDIO_StillDraining() or DAUDIO_Service()) then it's underrun
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1031
        if (info->silencedBytes >= info->dsBufferSizeInBytes - info->bufferSizeInBytes) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1032
            // underrun!
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1033
            ERROR0("DS_CheckUnderrun: ERROR: underrun detected!\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1034
            info->underrun = TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1035
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1036
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1037
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1038
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1039
/* For source (playback) line:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1040
 *   (a) if (fromPlayCursor == FALSE), returns number of bytes available
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1041
 *     for writing: bufferSize - (info->writePos - writeCursor);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1042
 *   (b) if (fromPlayCursor == TRUE), playCursor is used instead writeCursor
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1043
 *     and returned value can be used for play position calculation (see also
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1044
 *     note about bufferSize)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1045
 * For destination (capture) line:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1046
 *   (c) if (fromPlayCursor == FALSE), returns number of bytes available
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1047
 *     for reading from the buffer: readCursor - info->writePos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1048
 *   (d) if (fromPlayCursor == TRUE), captureCursor is used instead readCursor
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1049
 *     and returned value can be used for capture position calculation (see
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1050
 *     note about bufferSize)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1051
 * bufferSize parameter are filled by "actual" buffer size:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1052
 *   if (fromPlayCursor == FALSE), bufferSize = info->bufferSizeInBytes
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1053
 *   otherwise it increase by number of bytes currently processed by DirectSound
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1054
 *     (writeCursor - playCursor) or (captureCursor - readCursor)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1055
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1056
int DS_GetAvailable(DS_Info* info,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1057
                    DWORD* playCursor, DWORD* writeCursor,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1058
                    int* bufferSize, BOOL fromPlayCursor) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1059
    int available;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1060
    int newReadPos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1061
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1062
    TRACE2("DS_GetAvailable: fromPlayCursor=%d,  deviceID=%d\n", fromPlayCursor, info->deviceID);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1063
    if (!info->playBuffer && !info->captureBuffer) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1064
        ERROR0("DS_GetAvailable: ERROR: buffer not yet created");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1065
        return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1066
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1067
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1068
    if (info->isSource)  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1069
        if (FAILED(info->playBuffer->GetCurrentPosition(playCursor, writeCursor))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1070
            ERROR0("DS_GetAvailable: ERROR: Failed to get current position.\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1071
            return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1072
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1073
        int processing = DS_getDistance(info, (int)*playCursor, (int)*writeCursor);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1074
        // workaround: sometimes DirectSound report writeCursor is less (for several bytes) then playCursor
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1075
        if (processing > info->dsBufferSizeInBytes / 2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1076
            *writeCursor = *playCursor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1077
            processing = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1078
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1079
        TRACE3("   playCursor=%d, writeCursor=%d, info->writePos=%d\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1080
               *playCursor, *writeCursor, info->writePos);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1081
        *bufferSize = info->bufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1082
        if (fromPlayCursor) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1083
            *bufferSize += processing;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1084
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1085
        DS_CheckUnderrun(info, *playCursor, *writeCursor);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1086
        if (info->writePos == -1 || (info->underrun && !fromPlayCursor)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1087
                /* always full buffer if at beginning */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1088
                available = *bufferSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1089
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1090
            int currWriteAhead = DS_getDistance(info, fromPlayCursor ? (int)*playCursor : (int)*writeCursor, info->writePos);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1091
            if (currWriteAhead > *bufferSize) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1092
                if (info->underrun) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1093
                    // playCursor surpassed writePos - no valid data, whole buffer available
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1094
                    available = *bufferSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1095
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1096
                    // the case may occur after stop(), when writeCursor jumps back to playCursor
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1097
                    // so "actual" buffer size has grown
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1098
                    *bufferSize = currWriteAhead;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1099
                    available = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1100
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1101
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1102
                available = *bufferSize - currWriteAhead;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1103
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1104
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1105
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1106
        if (FAILED(info->captureBuffer->GetCurrentPosition(playCursor, writeCursor))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1107
            ERROR0("DS_GetAvailable: ERROR: Failed to get current position.\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1108
            return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1109
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1110
        *bufferSize = info->bufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1111
        if (fromPlayCursor) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1112
            *bufferSize += DS_getDistance(info, (int)*playCursor, (int)*writeCursor);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1113
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1114
        TRACE4("   captureCursor=%d, readCursor=%d, info->readPos=%d  refBufferSize=%d\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1115
               *playCursor, *writeCursor, info->writePos, *bufferSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1116
        if (info->writePos == -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1117
            /* always empty buffer if at beginning */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1118
            info->writePos = (int) (*writeCursor);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1119
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1120
        if (fromPlayCursor) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1121
            available = ((int) (*playCursor) - info->writePos);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1122
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1123
            available = ((int) (*writeCursor) - info->writePos);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1124
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1125
        if (available < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1126
            available += info->dsBufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1127
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1128
        if (!fromPlayCursor && available > info->bufferSizeInBytes) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1129
            /* overflow */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1130
            ERROR2("DS_GetAvailable: ERROR: overflow detected: "
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1131
                   "DirectSoundBufferSize=%d, bufferSize=%d, ",
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1132
                   info->dsBufferSizeInBytes, info->bufferSizeInBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1133
            ERROR3("captureCursor=%d, readCursor=%d, info->readPos=%d\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1134
                   *playCursor, *writeCursor, info->writePos);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1135
            /* advance read position, to allow exactly one buffer worth of data */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1136
            newReadPos = (int) (*writeCursor) - info->bufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1137
            if (newReadPos < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1138
                newReadPos += info->dsBufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1139
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1140
            info->writePos = newReadPos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1141
            available = info->bufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1142
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1143
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1144
    available = (available / info->frameSize) * info->frameSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1145
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1146
    TRACE1("DS_available: Returning %d available bytes\n", (int) available);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1147
    return available;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1148
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1149
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1150
// returns -1 on error, otherwise bytes written
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1151
int DAUDIO_Write(void* id, char* data, int byteSize) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1152
    DS_Info* info = (DS_Info*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1153
    int available;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1154
    int thisWritePos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1155
    DWORD playCursor, writeCursor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1156
    HRESULT res;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1157
    void* buffer1, *buffer2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1158
    DWORD buffer1len, buffer2len;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1159
    BOOL needRestart = FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1160
    int bufferLostTrials = 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1161
    int bufferSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1162
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1163
    TRACE1("> DAUDIO_Write %d bytes\n", byteSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1164
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1165
    while (--bufferLostTrials > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1166
        available = DS_GetAvailable(info, &playCursor, &writeCursor, &bufferSize, FALSE /* fromPlayCursor */);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1167
        if (byteSize > available) byteSize = available;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1168
        if (byteSize == 0) break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1169
        thisWritePos = info->writePos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1170
        if (thisWritePos == -1 || info->underrun) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1171
            // play from current write cursor after flush, etc.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1172
            needRestart = TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1173
            thisWritePos = writeCursor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1174
            info->underrun = FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1175
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1176
        DEBUG_SILENCING2("DAUDIO_Write: writing from %d, count=%d\n", (int) thisWritePos, (int) byteSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1177
        res = info->playBuffer->Lock(thisWritePos, byteSize,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1178
                                     (LPVOID *) &buffer1, &buffer1len,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1179
                                     (LPVOID *) &buffer2, &buffer2len,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1180
                                     0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1181
        if (res != DS_OK) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1182
            /* some DS failure */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1183
            if (res == DSERR_BUFFERLOST) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1184
                ERROR0("DAUDIO_write: ERROR: Restoring lost Buffer.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1185
                if (info->playBuffer->Restore() == DS_OK) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1186
                    DS_clearBuffer(info, FALSE /* entire buffer */);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1187
                    info->writePos = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1188
                    /* try again */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1189
                    continue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1190
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1191
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1192
            /* can't recover from error */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1193
            byteSize = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1194
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1195
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1196
        /* buffer could be locked successfully */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1197
        /* first fill first buffer */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1198
        if (buffer1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1199
            memcpy(buffer1, data, buffer1len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1200
            data = (char*) (((UINT_PTR) data) + buffer1len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1201
        } else buffer1len = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1202
        if (buffer2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1203
            memcpy(buffer2, data, buffer2len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1204
        } else buffer2len = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1205
        byteSize = buffer1len + buffer2len;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1206
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1207
        /* update next write pos */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1208
        thisWritePos += byteSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1209
        while (thisWritePos >= info->dsBufferSizeInBytes) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1210
            thisWritePos -= info->dsBufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1211
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1212
        /* commit data to directsound */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1213
        info->playBuffer->Unlock(buffer1, buffer1len, buffer2, buffer2len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1214
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1215
        info->writePos = thisWritePos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1216
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1217
        /* update position
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1218
         * must be AFTER updating writePos,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1219
         * so that getSvailable doesn't return too little,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1220
         * so that getFramePos doesn't jump
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1221
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1222
        info->framePos += (byteSize / info->frameSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1223
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1224
        /* decrease silenced bytes */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1225
        if (info->silencedBytes > byteSize) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1226
            info->silencedBytes -= byteSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1227
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1228
            info->silencedBytes = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1229
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1230
        break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1231
    } /* while */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1232
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1233
    /* start the device, if necessary */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1234
    if (info->started && needRestart && (info->writePos >= 0)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1235
        DS_StartBufferHelper::StartBuffer(info);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1236
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1237
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1238
    TRACE1("< DAUDIO_Write: returning %d bytes.\n", byteSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1239
    return byteSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1240
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1241
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1242
// returns -1 on error
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1243
int DAUDIO_Read(void* id, char* data, int byteSize) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1244
    DS_Info* info = (DS_Info*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1245
    int available;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1246
    int thisReadPos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1247
    DWORD captureCursor, readCursor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1248
    HRESULT res;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1249
    void* buffer1, *buffer2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1250
    DWORD buffer1len, buffer2len;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1251
    int bufferSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1252
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1253
    TRACE1("> DAUDIO_Read %d bytes\n", byteSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1254
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1255
    available = DS_GetAvailable(info, &captureCursor, &readCursor, &bufferSize, FALSE /* fromCaptureCursor? */);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1256
    if (byteSize > available) byteSize = available;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1257
    if (byteSize > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1258
        thisReadPos = info->writePos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1259
        if (thisReadPos == -1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1260
            /* from beginning */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1261
            thisReadPos = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1262
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1263
        res = info->captureBuffer->Lock(thisReadPos, byteSize,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1264
                                        (LPVOID *) &buffer1, &buffer1len,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1265
                                        (LPVOID *) &buffer2, &buffer2len,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1266
                                        0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1267
        if (res != DS_OK) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1268
            /* can't recover from error */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1269
            byteSize = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1270
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1271
            /* buffer could be locked successfully */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1272
            /* first fill first buffer */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1273
            if (buffer1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1274
                memcpy(data, buffer1, buffer1len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1275
                data = (char*) (((UINT_PTR) data) + buffer1len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1276
            } else buffer1len = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1277
            if (buffer2) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1278
                memcpy(data, buffer2, buffer2len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1279
            } else buffer2len = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1280
            byteSize = buffer1len + buffer2len;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1281
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1282
            /* update next read pos */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1283
            thisReadPos = DS_addPos(info, thisReadPos, byteSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1284
            /* commit data to directsound */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1285
            info->captureBuffer->Unlock(buffer1, buffer1len, buffer2, buffer2len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1286
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1287
            /* update position
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1288
             * must be BEFORE updating readPos,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1289
             * so that getAvailable doesn't return too much,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1290
             * so that getFramePos doesn't jump
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1291
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1292
            info->framePos += (byteSize / info->frameSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1293
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1294
            info->writePos = thisReadPos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1295
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1296
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1297
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1298
    TRACE1("< DAUDIO_Read: returning %d bytes.\n", byteSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1299
    return byteSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1300
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1301
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1302
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1303
int DAUDIO_GetBufferSize(void* id, int isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1304
    DS_Info* info = (DS_Info*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1305
    return info->bufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1306
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1307
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1308
int DAUDIO_StillDraining(void* id, int isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1309
    DS_Info* info = (DS_Info*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1310
    BOOL draining = FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1311
    int available, bufferSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1312
    DWORD playCursor, writeCursor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1313
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1314
    DS_clearBuffer(info, TRUE /* from write position */);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1315
    available = DS_GetAvailable(info, &playCursor, &writeCursor, &bufferSize, TRUE /* fromPlayCursor */);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1316
    draining = (available < bufferSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1317
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1318
    TRACE3("DAUDIO_StillDraining: available=%d  silencedBytes=%d  Still draining: %s\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1319
           available, info->silencedBytes, draining?"TRUE":"FALSE");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1320
    return draining;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1321
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1322
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1323
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1324
int DAUDIO_Flush(void* id, int isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1325
    DS_Info* info = (DS_Info*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1326
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1327
    TRACE0("DAUDIO_Flush\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1328
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1329
    if (info->isSource)  {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1330
        info->playBuffer->Stop();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1331
        DS_clearBuffer(info, FALSE /* entire buffer */);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1332
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1333
        DWORD captureCursor, readCursor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1334
        /* set the read pointer to the current read position */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1335
        if (FAILED(info->captureBuffer->GetCurrentPosition(&captureCursor, &readCursor))) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1336
            ERROR0("DAUDIO_Flush: ERROR: Failed to get current position.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1337
            return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1338
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1339
        DS_clearBuffer(info, FALSE /* entire buffer */);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1340
        /* SHOULD set to *captureCursor*,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1341
         * but that would be detected as overflow
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1342
         * in a subsequent GetAvailable() call.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1343
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1344
        info->writePos = (int) readCursor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1345
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1346
    return TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1347
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1348
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1349
int DAUDIO_GetAvailable(void* id, int isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1350
    DS_Info* info = (DS_Info*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1351
    DWORD playCursor, writeCursor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1352
    int ret, bufferSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1353
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1354
    ret = DS_GetAvailable(info, &playCursor, &writeCursor, &bufferSize, /*fromPlayCursor?*/ FALSE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1355
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1356
    TRACE1("DAUDIO_GetAvailable returns %d bytes\n", ret);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1357
    return ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1358
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1359
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1360
INT64 estimatePositionFromAvail(DS_Info* info, INT64 javaBytePos, int bufferSize, int availInBytes) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1361
    // estimate the current position with the buffer size and
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1362
    // the available bytes to read or write in the buffer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1363
    // not an elegant solution - bytePos will stop on xruns,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1364
    // and in race conditions it may jump backwards
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1365
    // Advantage is that it is indeed based on the samples that go through
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1366
    // the system (rather than time-based methods)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1367
    if (info->isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1368
        // javaBytePos is the position that is reached when the current
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1369
        // buffer is played completely
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1370
        return (INT64) (javaBytePos - bufferSize + availInBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1371
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1372
        // javaBytePos is the position that was when the current buffer was empty
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1373
        return (INT64) (javaBytePos + availInBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1374
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1375
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1376
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1377
INT64 DAUDIO_GetBytePosition(void* id, int isSource, INT64 javaBytePos) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1378
    DS_Info* info = (DS_Info*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1379
    int available, bufferSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1380
    DWORD playCursor, writeCursor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1381
    INT64 result = javaBytePos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1382
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1383
    available = DS_GetAvailable(info, &playCursor, &writeCursor, &bufferSize, /*fromPlayCursor?*/ TRUE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1384
    result = estimatePositionFromAvail(info, javaBytePos, bufferSize, available);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1385
    return result;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1386
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1387
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1388
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1389
void DAUDIO_SetBytePosition(void* id, int isSource, INT64 javaBytePos) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1390
    /* save to ignore, since GetBytePosition
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1391
     * takes the javaBytePos param into account
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1392
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1393
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1394
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1395
int DAUDIO_RequiresServicing(void* id, int isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1396
    // need servicing on for SourceDataLines
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1397
    return isSource?TRUE:FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1398
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1399
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1400
void DAUDIO_Service(void* id, int isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1401
    DS_Info* info = (DS_Info*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1402
    if (isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1403
        if (info->silencedBytes < info->dsBufferSizeInBytes) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1404
            // clear buffer
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1405
            TRACE0("DAUDIO_Service\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1406
            DS_clearBuffer(info, TRUE /* from write position */);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1407
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1408
        if (info->writePos >= 0
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1409
            && info->started
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1410
            && !info->underrun
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1411
            && info->silencedBytes >= info->dsBufferSizeInBytes) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1412
            // if we're currently playing, and the entire buffer is silenced...
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1413
            // then we are underrunning!
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1414
            info->underrun = TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1415
            ERROR0("DAUDIO_Service: ERROR: DirectSound: underrun detected!\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1416
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1417
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1418
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1419
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1420
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1421
#endif // USE_DAUDIO