18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * QEMU DirectSound audio driver
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 2005 Vassili Karpov (malc)
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of this software and associated documentation files (the "Software"), to deal
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in the Software without restriction, including without limitation the rights
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * copies of the Software, and to permit persons to whom the Software is
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * furnished to do so, subject to the following conditions:
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The above copyright notice and this permission notice shall be included in
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * all copies or substantial portions of the Software.
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE.
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * SEAL 1.07 by Carlos 'pel' Hasan was used as documentation
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
295d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner#include "qemu-common.h"
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "audio.h"
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define AUDIO_CAP "dsound"
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "audio_int.h"
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <windows.h>
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <mmsystem.h>
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <objbase.h>
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <dsound.h>
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
405d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner#include "audio_win_int.h"
415d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* #define DEBUG_DSOUND */
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic struct {
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int lock_retries;
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int restore_retries;
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int getstatus_retries;
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int set_primary;
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int bufsize_in;
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int bufsize_out;
515d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    struct audsettings settings;
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int latency_millis;
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} conf = {
545d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .lock_retries       = 1,
555d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .restore_retries    = 1,
565d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .getstatus_retries  = 1,
575d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .set_primary        = 0,
585d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .bufsize_in         = 16384,
595d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .bufsize_out        = 16384,
605d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .settings.freq      = 44100,
615d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .settings.nchannels = 2,
625d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .settings.fmt       = AUD_FMT_S16,
635d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .latency_millis     = 10
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct {
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    LPDIRECTSOUND dsound;
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    LPDIRECTSOUNDCAPTURE dsound_capture;
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    LPDIRECTSOUNDBUFFER dsound_primary_buffer;
705d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    struct audsettings settings;
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} dsound;
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic dsound glob_dsound;
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct {
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HWVoiceOut hw;
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    LPDIRECTSOUNDBUFFER dsound_buffer;
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD old_pos;
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int first_time;
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_DSOUND
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD old_ppos;
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD played;
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD mixed;
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} DSoundVoiceOut;
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct {
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HWVoiceIn hw;
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int first_time;
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    LPDIRECTSOUNDCAPTUREBUFFER dsound_capture_buffer;
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} DSoundVoiceIn;
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void dsound_log_hresult (HRESULT hr)
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *str = "BUG";
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (hr) {
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DS_OK:
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "The method succeeded";
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DS_NO_VIRTUALIZATION
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DS_NO_VIRTUALIZATION:
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "The buffer was created, but another 3D algorithm was substituted";
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DS_INCOMPLETE
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DS_INCOMPLETE:
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "The method succeeded, but not all the optional effects were obtained";
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_ACCESSDENIED
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_ACCESSDENIED:
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "The request failed because access was denied";
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_ALLOCATED
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_ALLOCATED:
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "The request failed because resources, such as a priority level, were already in use by another caller";
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_ALREADYINITIALIZED
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_ALREADYINITIALIZED:
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "The object is already initialized";
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_BADFORMAT
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_BADFORMAT:
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "The specified wave format is not supported";
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_BADSENDBUFFERGUID
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_BADSENDBUFFERGUID:
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "The GUID specified in an audiopath file does not match a valid mix-in buffer";
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_BUFFERLOST
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_BUFFERLOST:
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "The buffer memory has been lost and must be restored";
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_BUFFERTOOSMALL
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_BUFFERTOOSMALL:
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "The buffer size is not great enough to enable effects processing";
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_CONTROLUNAVAIL
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_CONTROLUNAVAIL:
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "The buffer control (volume, pan, and so on) requested by the caller is not available. Controls must be specified when the buffer is created, using the dwFlags member of DSBUFFERDESC";
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_DS8_REQUIRED
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_DS8_REQUIRED:
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "A DirectSound object of class CLSID_DirectSound8 or later is required for the requested functionality. For more information, see IDirectSound8 Interface";
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_FXUNAVAILABLE
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_FXUNAVAILABLE:
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "The effects requested could not be found on the system, or they are in the wrong order or in the wrong location; for example, an effect expected in hardware was found in software";
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_GENERIC
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_GENERIC :
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "An undetermined error occurred inside the DirectSound subsystem";
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_INVALIDCALL
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_INVALIDCALL:
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "This function is not valid for the current state of this object";
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_INVALIDPARAM
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_INVALIDPARAM:
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "An invalid parameter was passed to the returning function";
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_NOAGGREGATION
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_NOAGGREGATION:
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "The object does not support aggregation";
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_NODRIVER
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_NODRIVER:
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "No sound driver is available for use, or the given GUID is not a valid DirectSound device ID";
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_NOINTERFACE
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_NOINTERFACE:
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "The requested COM interface is not available";
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_OBJECTNOTFOUND
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_OBJECTNOTFOUND:
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "The requested object was not found";
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_OTHERAPPHASPRIO
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_OTHERAPPHASPRIO:
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "Another application has a higher priority level, preventing this call from succeeding";
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_OUTOFMEMORY
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_OUTOFMEMORY:
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "The DirectSound subsystem could not allocate sufficient memory to complete the caller's request";
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_PRIOLEVELNEEDED
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_PRIOLEVELNEEDED:
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "A cooperative level of DSSCL_PRIORITY or higher is required";
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_SENDLOOP
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_SENDLOOP:
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "A circular loop of send effects was detected";
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_UNINITIALIZED
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_UNINITIALIZED:
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "The Initialize method has not been called or has not been called successfully before other methods were called";
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DSERR_UNSUPPORTED
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case DSERR_UNSUPPORTED:
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str = "The function called is not supported at this time";
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    default:
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        AUD_log (AUDIO_CAP, "Reason: Unknown (HRESULT %#lx)\n", hr);
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    AUD_log (AUDIO_CAP, "Reason: %s\n", str);
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void GCC_FMT_ATTR (2, 3) dsound_logerr (
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HRESULT hr,
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *fmt,
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ...
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    )
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_list ap;
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_start (ap, fmt);
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    AUD_vlog (AUDIO_CAP, fmt, ap);
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_end (ap);
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dsound_log_hresult (hr);
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void GCC_FMT_ATTR (3, 4) dsound_logerr2 (
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HRESULT hr,
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *typ,
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char *fmt,
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ...
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    )
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_list ap;
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    AUD_log (AUDIO_CAP, "Could not initialize %s\n", typ);
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_start (ap, fmt);
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    AUD_vlog (AUDIO_CAP, fmt, ap);
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_end (ap);
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dsound_log_hresult (hr);
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic DWORD millis_to_bytes (struct audio_pcm_info *info, DWORD millis)
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return (millis * info->bytes_per_second) / 1000;
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_DSOUND
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void print_wave_format (WAVEFORMATEX *wfx)
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dolog ("tag             = %d\n", wfx->wFormatTag);
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dolog ("nChannels       = %d\n", wfx->nChannels);
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dolog ("nSamplesPerSec  = %ld\n", wfx->nSamplesPerSec);
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dolog ("nAvgBytesPerSec = %ld\n", wfx->nAvgBytesPerSec);
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dolog ("nBlockAlign     = %d\n", wfx->nBlockAlign);
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dolog ("wBitsPerSample  = %d\n", wfx->wBitsPerSample);
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dolog ("cbSize          = %d\n", wfx->cbSize);
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int dsound_restore_out (LPDIRECTSOUNDBUFFER dsb)
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HRESULT hr;
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (i = 0; i < conf.restore_retries; ++i) {
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hr = IDirectSoundBuffer_Restore (dsb);
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        switch (hr) {
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case DS_OK:
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case DSERR_BUFFERLOST:
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            continue;
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default:
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dsound_logerr (hr, "Could not restore playback buffer\n");
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dolog ("%d attempts to restore playback buffer failed\n", i);
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "dsound_template.h"
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define DSBTYPE_IN
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "dsound_template.h"
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef DSBTYPE_IN
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int dsound_get_status_out (LPDIRECTSOUNDBUFFER dsb, DWORD *statusp)
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HRESULT hr;
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int i;
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (i = 0; i < conf.getstatus_retries; ++i) {
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hr = IDirectSoundBuffer_GetStatus (dsb, statusp);
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (FAILED (hr)) {
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dsound_logerr (hr, "Could not get playback buffer status\n");
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (*statusp & DSERR_BUFFERLOST) {
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (dsound_restore_out (dsb)) {
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return -1;
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            continue;
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int dsound_get_status_in (LPDIRECTSOUNDCAPTUREBUFFER dscb,
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                 DWORD *statusp)
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HRESULT hr;
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hr = IDirectSoundCaptureBuffer_GetStatus (dscb, statusp);
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (FAILED (hr)) {
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dsound_logerr (hr, "Could not get capture buffer status\n");
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void dsound_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len)
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int src_len1 = dst_len;
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int src_len2 = 0;
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int pos = hw->rpos + dst_len;
3575d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    struct st_sample *src1 = hw->mix_buf + hw->rpos;
3585d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    struct st_sample *src2 = NULL;
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (pos > hw->samples) {
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        src_len1 = hw->samples - hw->rpos;
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        src2 = hw->mix_buf;
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        src_len2 = dst_len - src_len1;
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pos = src_len2;
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (src_len1) {
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hw->clip (dst, src1, src_len1);
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (src_len2) {
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dst = advance (dst, src_len1 << hw->info.shift);
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hw->clip (dst, src2, src_len2);
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hw->rpos = pos % hw->samples;
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void dsound_clear_sample (HWVoiceOut *hw, LPDIRECTSOUNDBUFFER dsb)
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int err;
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    LPVOID p1, p2;
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD blen1, blen2, len1, len2;
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    err = dsound_lock_out (
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dsb,
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &hw->info,
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        0,
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hw->samples << hw->info.shift,
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &p1, &p2,
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &blen1, &blen2,
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        1
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        );
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (err) {
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len1 = blen1 >> hw->info.shift;
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len2 = blen2 >> hw->info.shift;
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_DSOUND
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dolog ("clear %p,%ld,%ld %p,%ld,%ld\n",
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           p1, blen1, len1,
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           p2, blen2, len2);
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p1 && len1) {
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        audio_pcm_info_clear_buf (&hw->info, p1, len1);
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p2 && len2) {
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        audio_pcm_info_clear_buf (&hw->info, p2, len2);
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dsound_unlock_out (dsb, p1, p2, blen1, blen2);
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void dsound_close (dsound *s)
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HRESULT hr;
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (s->dsound_primary_buffer) {
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hr = IDirectSoundBuffer_Release (s->dsound_primary_buffer);
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (FAILED (hr)) {
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dsound_logerr (hr, "Could not release primary buffer\n");
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->dsound_primary_buffer = NULL;
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int dsound_open (dsound *s)
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int err;
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HRESULT hr;
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    WAVEFORMATEX wfx;
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DSBUFFERDESC dsbd;
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HWND hwnd;
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hwnd = GetForegroundWindow ();
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hr = IDirectSound_SetCooperativeLevel (
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->dsound,
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hwnd,
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        DSSCL_PRIORITY
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        );
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (FAILED (hr)) {
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dsound_logerr (hr, "Could not set cooperative level for window %p\n",
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       hwnd);
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!conf.set_primary) {
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    err = waveformat_from_audio_settings (&wfx, &conf.settings);
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (err) {
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memset (&dsbd, 0, sizeof (dsbd));
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dsbd.dwSize = sizeof (dsbd);
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dsbd.dwBufferBytes = 0;
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dsbd.lpwfxFormat = NULL;
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hr = IDirectSound_CreateSoundBuffer (
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->dsound,
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &dsbd,
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &s->dsound_primary_buffer,
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        NULL
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        );
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (FAILED (hr)) {
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dsound_logerr (hr, "Could not create primary playback buffer\n");
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hr = IDirectSoundBuffer_SetFormat (s->dsound_primary_buffer, &wfx);
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (FAILED (hr)) {
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dsound_logerr (hr, "Could not set primary playback buffer format\n");
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hr = IDirectSoundBuffer_GetFormat (
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->dsound_primary_buffer,
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &wfx,
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sizeof (wfx),
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        NULL
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        );
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (FAILED (hr)) {
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dsound_logerr (hr, "Could not get primary playback buffer format\n");
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto fail0;
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_DSOUND
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dolog ("Primary\n");
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    print_wave_format (&wfx);
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    err = waveformat_to_audio_settings (&wfx, &s->settings);
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (err) {
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto fail0;
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project fail0:
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dsound_close (s);
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int dsound_ctl_out (HWVoiceOut *hw, int cmd, ...)
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HRESULT hr;
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD status;
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!dsb) {
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Attempt to control voice without a buffer\n");
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (cmd) {
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case VOICE_ENABLE:
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dsound_get_status_out (dsb, &status)) {
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (status & DSBSTATUS_PLAYING) {
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dolog ("warning: Voice is already playing\n");
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dsound_clear_sample (hw, dsb);
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hr = IDirectSoundBuffer_Play (dsb, 0, 0, DSBPLAY_LOOPING);
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (FAILED (hr)) {
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dsound_logerr (hr, "Could not start playing buffer\n");
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case VOICE_DISABLE:
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dsound_get_status_out (dsb, &status)) {
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (status & DSBSTATUS_PLAYING) {
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            hr = IDirectSoundBuffer_Stop (dsb);
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (FAILED (hr)) {
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                dsound_logerr (hr, "Could not stop playing buffer\n");
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return -1;
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else {
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dolog ("warning: Voice is not playing\n");
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int dsound_write (SWVoiceOut *sw, void *buf, int len)
5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return audio_pcm_sw_write (sw, buf, len);
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5685d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turnerstatic int dsound_run_out (HWVoiceOut *hw, int live)
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int err;
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HRESULT hr;
5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer;
5745d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    int len, hwshift;
5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD blen1, blen2;
5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD len1, len2;
5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD decr;
5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD wpos, ppos, old_pos;
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    LPVOID p1, p2;
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int bufsize;
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!dsb) {
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Attempt to run empty with playback buffer\n");
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hwshift = hw->info.shift;
5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    bufsize = hw->samples << hwshift;
5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hr = IDirectSoundBuffer_GetCurrentPosition (
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dsb,
5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &ppos,
5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ds->first_time ? &wpos : NULL
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        );
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (FAILED (hr)) {
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dsound_logerr (hr, "Could not get playback buffer position\n");
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = live << hwshift;
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ds->first_time) {
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (conf.latency_millis) {
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            DWORD cur_blat;
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            cur_blat = audio_ring_dist (wpos, ppos, bufsize);
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ds->first_time = 0;
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            old_pos = wpos;
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            old_pos +=
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                millis_to_bytes (&hw->info, conf.latency_millis) - cur_blat;
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            old_pos %= bufsize;
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            old_pos &= ~hw->info.align;
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else {
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            old_pos = wpos;
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_DSOUND
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ds->played = 0;
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ds->mixed = 0;
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ds->old_pos == ppos) {
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_DSOUND
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dolog ("old_pos == ppos\n");
6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_DSOUND
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ds->played += audio_ring_dist (ds->old_pos, ppos, hw->bufsize);
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        old_pos = ds->old_pos;
6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ((old_pos < ppos) && ((old_pos + len) > ppos)) {
6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = ppos - old_pos;
6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
6408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ((old_pos > ppos) && ((old_pos + len) > (ppos + bufsize))) {
6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len = bufsize - old_pos + ppos;
6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
6438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (audio_bug (AUDIO_FUNC, len < 0 || len > bufsize)) {
6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("len=%d bufsize=%d old_pos=%ld ppos=%ld\n",
6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               len, bufsize, old_pos, ppos);
6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len &= ~hw->info.align;
6528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!len) {
6538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
6548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_DSOUND
6578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ds->old_ppos = ppos;
6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    err = dsound_lock_out (
6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dsb,
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &hw->info,
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        old_pos,
6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len,
6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &p1, &p2,
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &blen1, &blen2,
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        0
6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        );
6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (err) {
6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len1 = blen1 >> hwshift;
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len2 = blen2 >> hwshift;
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    decr = len1 + len2;
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p1 && len1) {
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dsound_write_sample (hw, p1, len1);
6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p2 && len2) {
6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dsound_write_sample (hw, p2, len2);
6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dsound_unlock_out (dsb, p1, p2, blen1, blen2);
6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ds->old_pos = (old_pos + (decr << hwshift)) % bufsize;
6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG_DSOUND
6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ds->mixed += decr << hwshift;
6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dolog ("played %lu mixed %lu diff %ld sec %f\n",
6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           ds->played,
6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           ds->mixed,
6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           ds->mixed - ds->played,
6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           abs (ds->mixed - ds->played) / (double) hw->info.bytes_per_second);
6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return decr;
6978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int dsound_ctl_in (HWVoiceIn *hw, int cmd, ...)
7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HRESULT hr;
7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD status;
7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer;
7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!dscb) {
7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Attempt to control capture voice without a buffer\n");
7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (cmd) {
7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case VOICE_ENABLE:
7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dsound_get_status_in (dscb, &status)) {
7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (status & DSCBSTATUS_CAPTURING) {
7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dolog ("warning: Voice is already capturing\n");
7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* clear ?? */
7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hr = IDirectSoundCaptureBuffer_Start (dscb, DSCBSTART_LOOPING);
7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (FAILED (hr)) {
7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dsound_logerr (hr, "Could not start capturing\n");
7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
7288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    case VOICE_DISABLE:
7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (dsound_get_status_in (dscb, &status)) {
7338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (status & DSCBSTATUS_CAPTURING) {
7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            hr = IDirectSoundCaptureBuffer_Stop (dscb);
7388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (FAILED (hr)) {
7398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                dsound_logerr (hr, "Could not stop capturing\n");
7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return -1;
7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        else {
7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dolog ("warning: Voice is not capturing\n");
7458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        break;
7478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int dsound_read (SWVoiceIn *sw, void *buf, int len)
7528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return audio_pcm_sw_read (sw, buf, len);
7548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int dsound_run_in (HWVoiceIn *hw)
7578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int err;
7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HRESULT hr;
7608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
7618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    LPDIRECTSOUNDCAPTUREBUFFER dscb = ds->dsound_capture_buffer;
7628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int live, len, dead;
7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD blen1, blen2;
7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD len1, len2;
7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD decr;
7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    DWORD cpos, rpos;
7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    LPVOID p1, p2;
7688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int hwshift;
7698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!dscb) {
7718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dolog ("Attempt to run without capture buffer\n");
7728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
7738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hwshift = hw->info.shift;
7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    live = audio_pcm_hw_get_live_in (hw);
7788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dead = hw->samples - live;
7798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!dead) {
7808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
7818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hr = IDirectSoundCaptureBuffer_GetCurrentPosition (
7848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dscb,
7858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &cpos,
7868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ds->first_time ? &rpos : NULL
7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        );
7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (FAILED (hr)) {
7898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dsound_logerr (hr, "Could not get capture buffer position\n");
7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
7918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ds->first_time) {
7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ds->first_time = 0;
7958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (rpos & hw->info.align) {
7968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ldebug ("warning: Misaligned capture read position %ld(%d)\n",
7978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    rpos, hw->info.align);
7988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
7998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hw->wpos = rpos >> hwshift;
8008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cpos & hw->info.align) {
8038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ldebug ("warning: Misaligned capture position %ld(%d)\n",
8048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                cpos, hw->info.align);
8058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    cpos >>= hwshift;
8078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = audio_ring_dist (cpos, hw->wpos, hw->samples);
8098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!len) {
8108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
8118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = audio_MIN (len, dead);
8138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    err = dsound_lock_in (
8158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dscb,
8168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &hw->info,
8178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hw->wpos << hwshift,
8188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len << hwshift,
8198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &p1,
8208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &p2,
8218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &blen1,
8228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &blen2,
8238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        0
8248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        );
8258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (err) {
8268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
8278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len1 = blen1 >> hwshift;
8308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len2 = blen2 >> hwshift;
8318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    decr = len1 + len2;
8328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p1 && len1) {
8348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hw->conv (hw->conv_buf + hw->wpos, p1, len1, &nominal_volume);
8358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p2 && len2) {
8388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hw->conv (hw->conv_buf, p2, len2, &nominal_volume);
8398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dsound_unlock_in (dscb, p1, p2, blen1, blen2);
8428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hw->wpos = (hw->wpos + decr) % hw->samples;
8438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return decr;
8448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void dsound_audio_fini (void *opaque)
8478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HRESULT hr;
8498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dsound *s = opaque;
8508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!s->dsound) {
8528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
8538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hr = IDirectSound_Release (s->dsound);
8568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (FAILED (hr)) {
8578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dsound_logerr (hr, "Could not release DirectSound\n");
8588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->dsound = NULL;
8608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!s->dsound_capture) {
8628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
8638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hr = IDirectSoundCapture_Release (s->dsound_capture);
8668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (FAILED (hr)) {
8678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dsound_logerr (hr, "Could not release DirectSoundCapture\n");
8688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s->dsound_capture = NULL;
8708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void *dsound_audio_init (void)
8738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int err;
8758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    HRESULT hr;
8768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dsound *s = &glob_dsound;
8778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hr = CoInitialize (NULL);
8798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (FAILED (hr)) {
8808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dsound_logerr (hr, "Could not initialize COM\n");
8818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
8828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hr = CoCreateInstance (
8858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &CLSID_DirectSound,
8868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        NULL,
8878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        CLSCTX_ALL,
8888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &IID_IDirectSound,
8898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        (void **) &s->dsound
8908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        );
8918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (FAILED (hr)) {
8928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dsound_logerr (hr, "Could not create DirectSound instance\n");
8938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
8948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hr = IDirectSound_Initialize (s->dsound, NULL);
8978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (FAILED (hr)) {
8988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dsound_logerr (hr, "Could not initialize DirectSound\n");
8998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hr = IDirectSound_Release (s->dsound);
9018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (FAILED (hr)) {
9028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dsound_logerr (hr, "Could not release DirectSound\n");
9038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
9048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        s->dsound = NULL;
9058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
9068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    hr = CoCreateInstance (
9098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &CLSID_DirectSoundCapture,
9108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        NULL,
9118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        CLSCTX_ALL,
9128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        &IID_IDirectSoundCapture,
9138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        (void **) &s->dsound_capture
9148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        );
9158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (FAILED (hr)) {
9168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dsound_logerr (hr, "Could not create DirectSoundCapture instance\n");
9178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
9198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hr = IDirectSoundCapture_Initialize (s->dsound_capture, NULL);
9208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (FAILED (hr)) {
9218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dsound_logerr (hr, "Could not initialize DirectSoundCapture\n");
9228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            hr = IDirectSoundCapture_Release (s->dsound_capture);
9248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (FAILED (hr)) {
9258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                dsound_logerr (hr, "Could not release DirectSoundCapture\n");
9268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
9278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            s->dsound_capture = NULL;
9288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
9298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    err = dsound_open (s);
9328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (err) {
9338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dsound_audio_fini (s);
9348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return NULL;
9358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return s;
9388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic struct audio_option dsound_options[] = {
9415d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
9425d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "LOCK_RETRIES",
9435d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_INT,
9445d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.lock_retries,
9455d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "Number of times to attempt locking the buffer"
9465d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
9475d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
9485d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "RESTOURE_RETRIES",
9495d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_INT,
9505d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.restore_retries,
9515d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "Number of times to attempt restoring the buffer"
9525d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
9535d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
9545d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "GETSTATUS_RETRIES",
9555d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_INT,
9565d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.getstatus_retries,
9575d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "Number of times to attempt getting status of the buffer"
9585d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
9595d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
9605d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "SET_PRIMARY",
9615d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_BOOL,
9625d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.set_primary,
9635d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "Set the parameters of primary buffer"
9645d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
9655d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
9665d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "LATENCY_MILLIS",
9675d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_INT,
9685d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.latency_millis,
9695d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "(undocumented)"
9705d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
9715d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
9725d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "PRIMARY_FREQ",
9735d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_INT,
9745d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.settings.freq,
9755d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "Primary buffer frequency"
9765d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
9775d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
9785d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "PRIMARY_CHANNELS",
9795d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_INT,
9805d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.settings.nchannels,
9815d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "Primary buffer number of channels (1 - mono, 2 - stereo)"
9825d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
9835d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
9845d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "PRIMARY_FMT",
9855d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_FMT,
9865d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.settings.fmt,
9875d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "Primary buffer format"
9885d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
9895d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
9905d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "BUFSIZE_OUT",
9915d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_INT,
9925d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.bufsize_out,
9935d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "(undocumented)"
9945d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
9955d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    {
9965d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .name  = "BUFSIZE_IN",
9975d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .tag   = AUD_OPT_INT,
9985d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .valp  = &conf.bufsize_in,
9995d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner        .descr = "(undocumented)"
10005d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    },
10015d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    { /* End of list */ }
10028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
10038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic struct audio_pcm_ops dsound_pcm_ops = {
10055d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .init_out = dsound_init_out,
10065d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .fini_out = dsound_fini_out,
10075d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .run_out  = dsound_run_out,
10085d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .write    = dsound_write,
10095d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .ctl_out  = dsound_ctl_out,
10105d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner
10115d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .init_in  = dsound_init_in,
10125d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .fini_in  = dsound_fini_in,
10135d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .run_in   = dsound_run_in,
10145d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .read     = dsound_read,
10155d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .ctl_in   = dsound_ctl_in
10168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
10178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct audio_driver dsound_audio_driver = {
10195d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .name           = "dsound",
10205d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .descr          = "DirectSound http://wikipedia.org/wiki/DirectSound",
10215d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .options        = dsound_options,
10225d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .init           = dsound_audio_init,
10235d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .fini           = dsound_audio_fini,
10245d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .pcm_ops        = &dsound_pcm_ops,
10255d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .can_be_default = 1,
10265d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .max_voices_out = INT_MAX,
10275d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .max_voices_in  = 1,
10285d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .voice_size_out = sizeof (DSoundVoiceOut),
10295d0e37bc290d1743cb5acf76eb6608f1303f27ddDavid 'Digit' Turner    .voice_size_in  = sizeof (DSoundVoiceIn)
10308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
1031