aboutsummaryrefslogtreecommitdiffstats
path: root/alc/backends/dsound.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'alc/backends/dsound.cpp')
-rw-r--r--alc/backends/dsound.cpp486
1 files changed, 210 insertions, 276 deletions
diff --git a/alc/backends/dsound.cpp b/alc/backends/dsound.cpp
index c04ba9e4..f549c0fe 100644
--- a/alc/backends/dsound.cpp
+++ b/alc/backends/dsound.cpp
@@ -20,7 +20,7 @@
#include "config.h"
-#include "backends/dsound.h"
+#include "dsound.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
@@ -44,12 +44,13 @@
#include <algorithm>
#include <functional>
-#include "alcmain.h"
-#include "alexcpt.h"
-#include "alu.h"
-#include "ringbuffer.h"
-#include "compat.h"
+#include "alnumeric.h"
+#include "comptr.h"
+#include "core/device.h"
+#include "core/helpers.h"
+#include "core/logging.h"
#include "dynload.h"
+#include "ringbuffer.h"
#include "strutils.h"
#include "threads.h"
@@ -107,6 +108,15 @@ HRESULT (WINAPI *pDirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW pDSEnumCallbac
#endif
+#define MONO SPEAKER_FRONT_CENTER
+#define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT)
+#define QUAD (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
+#define X5DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
+#define X5DOT1REAR (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
+#define X6DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_CENTER|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
+#define X7DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
+#define X7DOT1DOT4 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT|SPEAKER_TOP_FRONT_LEFT|SPEAKER_TOP_FRONT_RIGHT|SPEAKER_TOP_BACK_LEFT|SPEAKER_TOP_BACK_RIGHT)
+
#define MAX_UPDATES 128
struct DevMap {
@@ -161,21 +171,21 @@ BOOL CALLBACK DSoundEnumDevices(GUID *guid, const WCHAR *desc, const WCHAR*, voi
struct DSoundPlayback final : public BackendBase {
- DSoundPlayback(ALCdevice *device) noexcept : BackendBase{device} { }
+ DSoundPlayback(DeviceBase *device) noexcept : BackendBase{device} { }
~DSoundPlayback() override;
int mixerProc();
- void open(const ALCchar *name) override;
+ void open(const char *name) override;
bool reset() override;
- bool start() override;
+ void start() override;
void stop() override;
- IDirectSound *mDS{nullptr};
- IDirectSoundBuffer *mPrimaryBuffer{nullptr};
- IDirectSoundBuffer *mBuffer{nullptr};
- IDirectSoundNotify *mNotifies{nullptr};
- HANDLE mNotifyEvent{nullptr};
+ ComPtr<IDirectSound> mDS;
+ ComPtr<IDirectSoundBuffer> mPrimaryBuffer;
+ ComPtr<IDirectSoundBuffer> mBuffer;
+ ComPtr<IDirectSoundNotify> mNotifies;
+ HANDLE mNotifyEvent{nullptr};
std::atomic<bool> mKillNow{true};
std::thread mThread;
@@ -185,19 +195,11 @@ struct DSoundPlayback final : public BackendBase {
DSoundPlayback::~DSoundPlayback()
{
- if(mNotifies)
- mNotifies->Release();
mNotifies = nullptr;
- if(mBuffer)
- mBuffer->Release();
mBuffer = nullptr;
- if(mPrimaryBuffer)
- mPrimaryBuffer->Release();
mPrimaryBuffer = nullptr;
-
- if(mDS)
- mDS->Release();
mDS = nullptr;
+
if(mNotifyEvent)
CloseHandle(mNotifyEvent);
mNotifyEvent = nullptr;
@@ -215,18 +217,19 @@ FORCE_ALIGN int DSoundPlayback::mixerProc()
if(FAILED(err))
{
ERR("Failed to get buffer caps: 0x%lx\n", err);
- aluHandleDisconnect(mDevice, "Failure retrieving playback buffer info: 0x%lx", err);
+ mDevice->handleDisconnect("Failure retrieving playback buffer info: 0x%lx", err);
return 1;
}
- ALuint FrameSize{mDevice->frameSizeFromFmt()};
+ const size_t FrameStep{mDevice->channelsFromFmt()};
+ uint FrameSize{mDevice->frameSizeFromFmt()};
DWORD FragSize{mDevice->UpdateSize * FrameSize};
bool Playing{false};
DWORD LastCursor{0u};
mBuffer->GetCurrentPosition(&LastCursor, nullptr);
- while(!mKillNow.load(std::memory_order_acquire) &&
- mDevice->Connected.load(std::memory_order_acquire))
+ while(!mKillNow.load(std::memory_order_acquire)
+ && mDevice->Connected.load(std::memory_order_acquire))
{
// Get current play cursor
DWORD PlayCursor;
@@ -241,7 +244,7 @@ FORCE_ALIGN int DSoundPlayback::mixerProc()
if(FAILED(err))
{
ERR("Failed to play buffer: 0x%lx\n", err);
- aluHandleDisconnect(mDevice, "Failure starting playback: 0x%lx", err);
+ mDevice->handleDisconnect("Failure starting playback: 0x%lx", err);
return 1;
}
Playing = true;
@@ -275,19 +278,16 @@ FORCE_ALIGN int DSoundPlayback::mixerProc()
if(SUCCEEDED(err))
{
- std::unique_lock<DSoundPlayback> dlock{*this};
- aluMixData(mDevice, WritePtr1, WriteCnt1/FrameSize);
+ mDevice->renderSamples(WritePtr1, WriteCnt1/FrameSize, FrameStep);
if(WriteCnt2 > 0)
- aluMixData(mDevice, WritePtr2, WriteCnt2/FrameSize);
- dlock.unlock();
+ mDevice->renderSamples(WritePtr2, WriteCnt2/FrameSize, FrameStep);
mBuffer->Unlock(WritePtr1, WriteCnt1, WritePtr2, WriteCnt2);
}
else
{
ERR("Buffer lock error: %#lx\n", err);
- std::lock_guard<DSoundPlayback> _{*this};
- aluHandleDisconnect(mDevice, "Failed to lock output buffer: 0x%lx", err);
+ mDevice->handleDisconnect("Failed to lock output buffer: 0x%lx", err);
return 1;
}
@@ -299,7 +299,7 @@ FORCE_ALIGN int DSoundPlayback::mixerProc()
return 0;
}
-void DSoundPlayback::open(const ALCchar *name)
+void DSoundPlayback::open(const char *name)
{
HRESULT hr;
if(PlaybackDevices.empty())
@@ -322,155 +322,124 @@ void DSoundPlayback::open(const ALCchar *name)
else
{
auto iter = std::find_if(PlaybackDevices.cbegin(), PlaybackDevices.cend(),
- [name](const DevMap &entry) -> bool
- { return entry.name == name; }
- );
+ [name](const DevMap &entry) -> bool { return entry.name == name; });
if(iter == PlaybackDevices.cend())
- throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name};
+ {
+ GUID id{};
+ hr = CLSIDFromString(utf8_to_wstr(name).c_str(), &id);
+ if(SUCCEEDED(hr))
+ iter = std::find_if(PlaybackDevices.cbegin(), PlaybackDevices.cend(),
+ [&id](const DevMap &entry) -> bool { return entry.guid == id; });
+ if(iter == PlaybackDevices.cend())
+ throw al::backend_exception{al::backend_error::NoDevice,
+ "Device name \"%s\" not found", name};
+ }
guid = &iter->guid;
}
hr = DS_OK;
- mNotifyEvent = CreateEventW(nullptr, FALSE, FALSE, nullptr);
- if(!mNotifyEvent) hr = E_FAIL;
+ if(!mNotifyEvent)
+ {
+ mNotifyEvent = CreateEventW(nullptr, FALSE, FALSE, nullptr);
+ if(!mNotifyEvent) hr = E_FAIL;
+ }
//DirectSound Init code
+ ComPtr<IDirectSound> ds;
if(SUCCEEDED(hr))
- hr = DirectSoundCreate(guid, &mDS, nullptr);
+ hr = DirectSoundCreate(guid, ds.getPtr(), nullptr);
if(SUCCEEDED(hr))
- hr = mDS->SetCooperativeLevel(GetForegroundWindow(), DSSCL_PRIORITY);
+ hr = ds->SetCooperativeLevel(GetForegroundWindow(), DSSCL_PRIORITY);
if(FAILED(hr))
- throw al::backend_exception{ALC_INVALID_VALUE, "Device init failed: 0x%08lx", hr};
+ throw al::backend_exception{al::backend_error::DeviceError, "Device init failed: 0x%08lx",
+ hr};
+
+ mNotifies = nullptr;
+ mBuffer = nullptr;
+ mPrimaryBuffer = nullptr;
+ mDS = std::move(ds);
mDevice->DeviceName = name;
}
bool DSoundPlayback::reset()
{
- if(mNotifies)
- mNotifies->Release();
mNotifies = nullptr;
- if(mBuffer)
- mBuffer->Release();
mBuffer = nullptr;
- if(mPrimaryBuffer)
- mPrimaryBuffer->Release();
mPrimaryBuffer = nullptr;
switch(mDevice->FmtType)
{
- case DevFmtByte:
- mDevice->FmtType = DevFmtUByte;
- break;
- case DevFmtFloat:
- if(mDevice->Flags.get<SampleTypeRequest>())
- break;
- /* fall-through */
- case DevFmtUShort:
- mDevice->FmtType = DevFmtShort;
- break;
- case DevFmtUInt:
- mDevice->FmtType = DevFmtInt;
- break;
- case DevFmtUByte:
- case DevFmtShort:
- case DevFmtInt:
+ case DevFmtByte:
+ mDevice->FmtType = DevFmtUByte;
+ break;
+ case DevFmtFloat:
+ if(mDevice->Flags.test(SampleTypeRequest))
break;
+ /* fall-through */
+ case DevFmtUShort:
+ mDevice->FmtType = DevFmtShort;
+ break;
+ case DevFmtUInt:
+ mDevice->FmtType = DevFmtInt;
+ break;
+ case DevFmtUByte:
+ case DevFmtShort:
+ case DevFmtInt:
+ break;
}
WAVEFORMATEXTENSIBLE OutputType{};
- DWORD speakers;
+ DWORD speakers{};
HRESULT hr{mDS->GetSpeakerConfig(&speakers)};
- if(SUCCEEDED(hr))
+ if(FAILED(hr))
+ throw al::backend_exception{al::backend_error::DeviceError,
+ "Failed to get speaker config: 0x%08lx", hr};
+
+ speakers = DSSPEAKER_CONFIG(speakers);
+ if(!mDevice->Flags.test(ChannelsRequest))
{
- speakers = DSSPEAKER_CONFIG(speakers);
- if(!mDevice->Flags.get<ChannelsRequest>())
- {
- if(speakers == DSSPEAKER_MONO)
- mDevice->FmtChans = DevFmtMono;
- else if(speakers == DSSPEAKER_STEREO || speakers == DSSPEAKER_HEADPHONE)
- mDevice->FmtChans = DevFmtStereo;
- else if(speakers == DSSPEAKER_QUAD)
- mDevice->FmtChans = DevFmtQuad;
- else if(speakers == DSSPEAKER_5POINT1_SURROUND)
- mDevice->FmtChans = DevFmtX51;
- else if(speakers == DSSPEAKER_5POINT1_BACK)
- mDevice->FmtChans = DevFmtX51Rear;
- else if(speakers == DSSPEAKER_7POINT1 || speakers == DSSPEAKER_7POINT1_SURROUND)
- mDevice->FmtChans = DevFmtX71;
- else
- ERR("Unknown system speaker config: 0x%lx\n", speakers);
- }
- mDevice->IsHeadphones = (mDevice->FmtChans == DevFmtStereo &&
- speakers == DSSPEAKER_HEADPHONE);
+ if(speakers == DSSPEAKER_MONO)
+ mDevice->FmtChans = DevFmtMono;
+ else if(speakers == DSSPEAKER_STEREO || speakers == DSSPEAKER_HEADPHONE)
+ mDevice->FmtChans = DevFmtStereo;
+ else if(speakers == DSSPEAKER_QUAD)
+ mDevice->FmtChans = DevFmtQuad;
+ else if(speakers == DSSPEAKER_5POINT1_SURROUND || speakers == DSSPEAKER_5POINT1_BACK)
+ mDevice->FmtChans = DevFmtX51;
+ else if(speakers == DSSPEAKER_7POINT1 || speakers == DSSPEAKER_7POINT1_SURROUND)
+ mDevice->FmtChans = DevFmtX71;
+ else
+ ERR("Unknown system speaker config: 0x%lx\n", speakers);
+ }
+ mDevice->Flags.set(DirectEar, (speakers == DSSPEAKER_HEADPHONE));
+ const bool isRear51{speakers == DSSPEAKER_5POINT1_BACK};
- switch(mDevice->FmtChans)
- {
- case DevFmtMono:
- OutputType.dwChannelMask = SPEAKER_FRONT_CENTER;
- break;
- case DevFmtAmbi3D:
- mDevice->FmtChans = DevFmtStereo;
- /*fall-through*/
- case DevFmtStereo:
- OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
- SPEAKER_FRONT_RIGHT;
- break;
- case DevFmtQuad:
- OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
- SPEAKER_FRONT_RIGHT |
- SPEAKER_BACK_LEFT |
- SPEAKER_BACK_RIGHT;
- break;
- case DevFmtX51:
- OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
- SPEAKER_FRONT_RIGHT |
- SPEAKER_FRONT_CENTER |
- SPEAKER_LOW_FREQUENCY |
- SPEAKER_SIDE_LEFT |
- SPEAKER_SIDE_RIGHT;
- break;
- case DevFmtX51Rear:
- OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
- SPEAKER_FRONT_RIGHT |
- SPEAKER_FRONT_CENTER |
- SPEAKER_LOW_FREQUENCY |
- SPEAKER_BACK_LEFT |
- SPEAKER_BACK_RIGHT;
- break;
- case DevFmtX61:
- OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
- SPEAKER_FRONT_RIGHT |
- SPEAKER_FRONT_CENTER |
- SPEAKER_LOW_FREQUENCY |
- SPEAKER_BACK_CENTER |
- SPEAKER_SIDE_LEFT |
- SPEAKER_SIDE_RIGHT;
- break;
- case DevFmtX71:
- OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
- SPEAKER_FRONT_RIGHT |
- SPEAKER_FRONT_CENTER |
- SPEAKER_LOW_FREQUENCY |
- SPEAKER_BACK_LEFT |
- SPEAKER_BACK_RIGHT |
- SPEAKER_SIDE_LEFT |
- SPEAKER_SIDE_RIGHT;
- break;
- }
+ switch(mDevice->FmtChans)
+ {
+ case DevFmtMono: OutputType.dwChannelMask = MONO; break;
+ case DevFmtAmbi3D: mDevice->FmtChans = DevFmtStereo;
+ /* fall-through */
+ case DevFmtStereo: OutputType.dwChannelMask = STEREO; break;
+ case DevFmtQuad: OutputType.dwChannelMask = QUAD; break;
+ case DevFmtX51: OutputType.dwChannelMask = isRear51 ? X5DOT1REAR : X5DOT1; break;
+ case DevFmtX61: OutputType.dwChannelMask = X6DOT1; break;
+ case DevFmtX71: OutputType.dwChannelMask = X7DOT1; break;
+ case DevFmtX714: OutputType.dwChannelMask = X7DOT1DOT4; break;
+ case DevFmtX3D71: OutputType.dwChannelMask = X7DOT1; break;
+ }
retry_open:
- hr = S_OK;
- OutputType.Format.wFormatTag = WAVE_FORMAT_PCM;
- OutputType.Format.nChannels = static_cast<WORD>(mDevice->channelsFromFmt());
- OutputType.Format.wBitsPerSample = static_cast<WORD>(mDevice->bytesFromFmt() * 8);
- OutputType.Format.nBlockAlign = static_cast<WORD>(OutputType.Format.nChannels *
- OutputType.Format.wBitsPerSample / 8);
- OutputType.Format.nSamplesPerSec = mDevice->Frequency;
- OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec *
- OutputType.Format.nBlockAlign;
- OutputType.Format.cbSize = 0;
- }
+ hr = S_OK;
+ OutputType.Format.wFormatTag = WAVE_FORMAT_PCM;
+ OutputType.Format.nChannels = static_cast<WORD>(mDevice->channelsFromFmt());
+ OutputType.Format.wBitsPerSample = static_cast<WORD>(mDevice->bytesFromFmt() * 8);
+ OutputType.Format.nBlockAlign = static_cast<WORD>(OutputType.Format.nChannels *
+ OutputType.Format.wBitsPerSample / 8);
+ OutputType.Format.nSamplesPerSec = mDevice->Frequency;
+ OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec *
+ OutputType.Format.nBlockAlign;
+ OutputType.Format.cbSize = 0;
if(OutputType.Format.nChannels > 2 || mDevice->FmtType == DevFmtFloat)
{
@@ -482,8 +451,6 @@ retry_open:
else
OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
- if(mPrimaryBuffer)
- mPrimaryBuffer->Release();
mPrimaryBuffer = nullptr;
}
else
@@ -493,7 +460,7 @@ retry_open:
DSBUFFERDESC DSBDescription{};
DSBDescription.dwSize = sizeof(DSBDescription);
DSBDescription.dwFlags = DSBCAPS_PRIMARYBUFFER;
- hr = mDS->CreateSoundBuffer(&DSBDescription, &mPrimaryBuffer, nullptr);
+ hr = mDS->CreateSoundBuffer(&DSBDescription, mPrimaryBuffer.getPtr(), nullptr);
}
if(SUCCEEDED(hr))
hr = mPrimaryBuffer->SetFormat(&OutputType.Format);
@@ -501,19 +468,19 @@ retry_open:
if(SUCCEEDED(hr))
{
- ALuint num_updates{mDevice->BufferSize / mDevice->UpdateSize};
+ uint num_updates{mDevice->BufferSize / mDevice->UpdateSize};
if(num_updates > MAX_UPDATES)
num_updates = MAX_UPDATES;
mDevice->BufferSize = mDevice->UpdateSize * num_updates;
DSBUFFERDESC DSBDescription{};
DSBDescription.dwSize = sizeof(DSBDescription);
- DSBDescription.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2 |
- DSBCAPS_GLOBALFOCUS;
+ DSBDescription.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2
+ | DSBCAPS_GLOBALFOCUS;
DSBDescription.dwBufferBytes = mDevice->BufferSize * OutputType.Format.nBlockAlign;
DSBDescription.lpwfxFormat = &OutputType.Format;
- hr = mDS->CreateSoundBuffer(&DSBDescription, &mBuffer, nullptr);
+ hr = mDS->CreateSoundBuffer(&DSBDescription, mBuffer.getPtr(), nullptr);
if(FAILED(hr) && mDevice->FmtType == DevFmtFloat)
{
mDevice->FmtType = DevFmtShort;
@@ -527,56 +494,46 @@ retry_open:
hr = mBuffer->QueryInterface(IID_IDirectSoundNotify, &ptr);
if(SUCCEEDED(hr))
{
- auto Notifies = static_cast<IDirectSoundNotify*>(ptr);
- mNotifies = Notifies;
+ mNotifies = ComPtr<IDirectSoundNotify>{static_cast<IDirectSoundNotify*>(ptr)};
- ALuint num_updates{mDevice->BufferSize / mDevice->UpdateSize};
+ uint num_updates{mDevice->BufferSize / mDevice->UpdateSize};
assert(num_updates <= MAX_UPDATES);
std::array<DSBPOSITIONNOTIFY,MAX_UPDATES> nots;
- for(ALuint i{0};i < num_updates;++i)
+ for(uint i{0};i < num_updates;++i)
{
nots[i].dwOffset = i * mDevice->UpdateSize * OutputType.Format.nBlockAlign;
nots[i].hEventNotify = mNotifyEvent;
}
- if(Notifies->SetNotificationPositions(num_updates, nots.data()) != DS_OK)
+ if(mNotifies->SetNotificationPositions(num_updates, nots.data()) != DS_OK)
hr = E_FAIL;
}
}
if(FAILED(hr))
{
- if(mNotifies)
- mNotifies->Release();
mNotifies = nullptr;
- if(mBuffer)
- mBuffer->Release();
mBuffer = nullptr;
- if(mPrimaryBuffer)
- mPrimaryBuffer->Release();
mPrimaryBuffer = nullptr;
return false;
}
ResetEvent(mNotifyEvent);
- SetDefaultWFXChannelOrder(mDevice);
+ setDefaultWFXChannelOrder();
return true;
}
-bool DSoundPlayback::start()
+void DSoundPlayback::start()
{
try {
mKillNow.store(false, std::memory_order_release);
mThread = std::thread{std::mem_fn(&DSoundPlayback::mixerProc), this};
- return true;
}
catch(std::exception& e) {
- ERR("Failed to start mixing thread: %s\n", e.what());
+ throw al::backend_exception{al::backend_error::DeviceError,
+ "Failed to start mixing thread: %s", e.what()};
}
- catch(...) {
- }
- return false;
}
void DSoundPlayback::stop()
@@ -590,17 +547,17 @@ void DSoundPlayback::stop()
struct DSoundCapture final : public BackendBase {
- DSoundCapture(ALCdevice *device) noexcept : BackendBase{device} { }
+ DSoundCapture(DeviceBase *device) noexcept : BackendBase{device} { }
~DSoundCapture() override;
- void open(const ALCchar *name) override;
- bool start() override;
+ void open(const char *name) override;
+ void start() override;
void stop() override;
- ALCenum captureSamples(al::byte *buffer, ALCuint samples) override;
- ALCuint availableSamples() override;
+ void captureSamples(al::byte *buffer, uint samples) override;
+ uint availableSamples() override;
- IDirectSoundCapture *mDSC{nullptr};
- IDirectSoundCaptureBuffer *mDSCbuffer{nullptr};
+ ComPtr<IDirectSoundCapture> mDSC;
+ ComPtr<IDirectSoundCaptureBuffer> mDSCbuffer;
DWORD mBufferBytes{0u};
DWORD mCursor{0u};
@@ -614,17 +571,13 @@ DSoundCapture::~DSoundCapture()
if(mDSCbuffer)
{
mDSCbuffer->Stop();
- mDSCbuffer->Release();
mDSCbuffer = nullptr;
}
-
- if(mDSC)
- mDSC->Release();
mDSC = nullptr;
}
-void DSoundCapture::open(const ALCchar *name)
+void DSoundCapture::open(const char *name)
{
HRESULT hr;
if(CaptureDevices.empty())
@@ -647,11 +600,18 @@ void DSoundCapture::open(const ALCchar *name)
else
{
auto iter = std::find_if(CaptureDevices.cbegin(), CaptureDevices.cend(),
- [name](const DevMap &entry) -> bool
- { return entry.name == name; }
- );
+ [name](const DevMap &entry) -> bool { return entry.name == name; });
if(iter == CaptureDevices.cend())
- throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name};
+ {
+ GUID id{};
+ hr = CLSIDFromString(utf8_to_wstr(name).c_str(), &id);
+ if(SUCCEEDED(hr))
+ iter = std::find_if(CaptureDevices.cbegin(), CaptureDevices.cend(),
+ [&id](const DevMap &entry) -> bool { return entry.guid == id; });
+ if(iter == CaptureDevices.cend())
+ throw al::backend_exception{al::backend_error::NoDevice,
+ "Device name \"%s\" not found", name};
+ }
guid = &iter->guid;
}
@@ -661,8 +621,8 @@ void DSoundCapture::open(const ALCchar *name)
case DevFmtUShort:
case DevFmtUInt:
WARN("%s capture samples not supported\n", DevFmtTypeString(mDevice->FmtType));
- throw al::backend_exception{ALC_INVALID_VALUE, "%s capture samples not supported",
- DevFmtTypeString(mDevice->FmtType)};
+ throw al::backend_exception{al::backend_error::DeviceError,
+ "%s capture samples not supported", DevFmtTypeString(mDevice->FmtType)};
case DevFmtUByte:
case DevFmtShort:
@@ -674,36 +634,17 @@ void DSoundCapture::open(const ALCchar *name)
WAVEFORMATEXTENSIBLE InputType{};
switch(mDevice->FmtChans)
{
- case DevFmtMono:
- InputType.dwChannelMask = SPEAKER_FRONT_CENTER;
- break;
- case DevFmtStereo:
- InputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT;
- break;
- case DevFmtQuad:
- InputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT |
- SPEAKER_BACK_RIGHT;
- break;
- case DevFmtX51:
- InputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER |
- SPEAKER_LOW_FREQUENCY | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT;
- break;
- case DevFmtX51Rear:
- InputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER |
- SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
- break;
- case DevFmtX61:
- InputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER |
- SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_CENTER | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT;
- break;
- case DevFmtX71:
- InputType.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER |
- SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT |
- SPEAKER_SIDE_RIGHT;
- break;
+ case DevFmtMono: InputType.dwChannelMask = MONO; break;
+ case DevFmtStereo: InputType.dwChannelMask = STEREO; break;
+ case DevFmtQuad: InputType.dwChannelMask = QUAD; break;
+ case DevFmtX51: InputType.dwChannelMask = X5DOT1; break;
+ case DevFmtX61: InputType.dwChannelMask = X6DOT1; break;
+ case DevFmtX71: InputType.dwChannelMask = X7DOT1; break;
+ case DevFmtX714: InputType.dwChannelMask = X7DOT1DOT4; break;
+ case DevFmtX3D71:
case DevFmtAmbi3D:
WARN("%s capture not supported\n", DevFmtChannelsString(mDevice->FmtChans));
- throw al::backend_exception{ALC_INVALID_VALUE, "%s capture not supported",
+ throw al::backend_exception{al::backend_error::DeviceError, "%s capture not supported",
DevFmtChannelsString(mDevice->FmtChans)};
}
@@ -728,7 +669,7 @@ void DSoundCapture::open(const ALCchar *name)
InputType.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
}
- ALuint samples{mDevice->BufferSize};
+ uint samples{mDevice->BufferSize};
samples = maxu(samples, 100 * mDevice->Frequency / 1000);
DSCBUFFERDESC DSCBDescription{};
@@ -738,41 +679,34 @@ void DSoundCapture::open(const ALCchar *name)
DSCBDescription.lpwfxFormat = &InputType.Format;
//DirectSoundCapture Init code
- hr = DirectSoundCaptureCreate(guid, &mDSC, nullptr);
+ hr = DirectSoundCaptureCreate(guid, mDSC.getPtr(), nullptr);
if(SUCCEEDED(hr))
- mDSC->CreateCaptureBuffer(&DSCBDescription, &mDSCbuffer, nullptr);
+ mDSC->CreateCaptureBuffer(&DSCBDescription, mDSCbuffer.getPtr(), nullptr);
if(SUCCEEDED(hr))
- mRing = CreateRingBuffer(mDevice->BufferSize, InputType.Format.nBlockAlign, false);
+ mRing = RingBuffer::Create(mDevice->BufferSize, InputType.Format.nBlockAlign, false);
if(FAILED(hr))
{
mRing = nullptr;
- if(mDSCbuffer)
- mDSCbuffer->Release();
mDSCbuffer = nullptr;
- if(mDSC)
- mDSC->Release();
mDSC = nullptr;
- throw al::backend_exception{ALC_INVALID_VALUE, "Device init failed: 0x%08lx", hr};
+ throw al::backend_exception{al::backend_error::DeviceError, "Device init failed: 0x%08lx",
+ hr};
}
mBufferBytes = DSCBDescription.dwBufferBytes;
- SetDefaultWFXChannelOrder(mDevice);
+ setDefaultWFXChannelOrder();
mDevice->DeviceName = name;
}
-bool DSoundCapture::start()
+void DSoundCapture::start()
{
- HRESULT hr{mDSCbuffer->Start(DSCBSTART_LOOPING)};
+ const HRESULT hr{mDSCbuffer->Start(DSCBSTART_LOOPING)};
if(FAILED(hr))
- {
- ERR("start failed: 0x%08lx\n", hr);
- aluHandleDisconnect(mDevice, "Failure starting capture: 0x%lx", hr);
- return false;
- }
- return true;
+ throw al::backend_exception{al::backend_error::DeviceError,
+ "Failure starting capture: 0x%lx", hr};
}
void DSoundCapture::stop()
@@ -781,24 +715,21 @@ void DSoundCapture::stop()
if(FAILED(hr))
{
ERR("stop failed: 0x%08lx\n", hr);
- aluHandleDisconnect(mDevice, "Failure stopping capture: 0x%lx", hr);
+ mDevice->handleDisconnect("Failure stopping capture: 0x%lx", hr);
}
}
-ALCenum DSoundCapture::captureSamples(al::byte *buffer, ALCuint samples)
-{
- mRing->read(buffer, samples);
- return ALC_NO_ERROR;
-}
+void DSoundCapture::captureSamples(al::byte *buffer, uint samples)
+{ mRing->read(buffer, samples); }
-ALCuint DSoundCapture::availableSamples()
+uint DSoundCapture::availableSamples()
{
if(!mDevice->Connected.load(std::memory_order_acquire))
- return static_cast<ALCuint>(mRing->readSpace());
+ return static_cast<uint>(mRing->readSpace());
- ALuint FrameSize{mDevice->frameSizeFromFmt()};
- DWORD BufferBytes{mBufferBytes};
- DWORD LastCursor{mCursor};
+ const uint FrameSize{mDevice->frameSizeFromFmt()};
+ const DWORD BufferBytes{mBufferBytes};
+ const DWORD LastCursor{mCursor};
DWORD ReadCursor{};
void *ReadPtr1{}, *ReadPtr2{};
@@ -806,8 +737,8 @@ ALCuint DSoundCapture::availableSamples()
HRESULT hr{mDSCbuffer->GetCurrentPosition(nullptr, &ReadCursor)};
if(SUCCEEDED(hr))
{
- DWORD NumBytes{(ReadCursor-LastCursor + BufferBytes) % BufferBytes};
- if(!NumBytes) return static_cast<ALCubyte>(mRing->readSpace());
+ const DWORD NumBytes{(BufferBytes+ReadCursor-LastCursor) % BufferBytes};
+ if(!NumBytes) return static_cast<uint>(mRing->readSpace());
hr = mDSCbuffer->Lock(LastCursor, NumBytes, &ReadPtr1, &ReadCnt1, &ReadPtr2, &ReadCnt2, 0);
}
if(SUCCEEDED(hr))
@@ -816,16 +747,16 @@ ALCuint DSoundCapture::availableSamples()
if(ReadPtr2 != nullptr && ReadCnt2 > 0)
mRing->write(ReadPtr2, ReadCnt2/FrameSize);
hr = mDSCbuffer->Unlock(ReadPtr1, ReadCnt1, ReadPtr2, ReadCnt2);
- mCursor = (LastCursor+ReadCnt1+ReadCnt2) % BufferBytes;
+ mCursor = ReadCursor;
}
if(FAILED(hr))
{
ERR("update failed: 0x%08lx\n", hr);
- aluHandleDisconnect(mDevice, "Failure retrieving capture data: 0x%lx", hr);
+ mDevice->handleDisconnect("Failure retrieving capture data: 0x%lx", hr);
}
- return static_cast<ALCuint>(mRing->readSpace());
+ return static_cast<uint>(mRing->readSpace());
}
} // namespace
@@ -871,14 +802,15 @@ bool DSoundBackendFactory::init()
bool DSoundBackendFactory::querySupport(BackendType type)
{ return (type == BackendType::Playback || type == BackendType::Capture); }
-void DSoundBackendFactory::probe(DevProbe type, std::string *outnames)
+std::string DSoundBackendFactory::probe(BackendType type)
{
- auto add_device = [outnames](const DevMap &entry) -> void
+ std::string outnames;
+ auto add_device = [&outnames](const DevMap &entry) -> void
{
/* +1 to also append the null char (to ensure a null-separated list and
* double-null terminated list).
*/
- outnames->append(entry.name.c_str(), entry.name.length()+1);
+ outnames.append(entry.name.c_str(), entry.name.length()+1);
};
/* Initialize COM to prevent name truncation */
@@ -886,27 +818,29 @@ void DSoundBackendFactory::probe(DevProbe type, std::string *outnames)
HRESULT hrcom{CoInitialize(nullptr)};
switch(type)
{
- case DevProbe::Playback:
- PlaybackDevices.clear();
- hr = DirectSoundEnumerateW(DSoundEnumDevices, &PlaybackDevices);
- if(FAILED(hr))
- ERR("Error enumerating DirectSound playback devices (0x%lx)!\n", hr);
- std::for_each(PlaybackDevices.cbegin(), PlaybackDevices.cend(), add_device);
- break;
+ case BackendType::Playback:
+ PlaybackDevices.clear();
+ hr = DirectSoundEnumerateW(DSoundEnumDevices, &PlaybackDevices);
+ if(FAILED(hr))
+ ERR("Error enumerating DirectSound playback devices (0x%lx)!\n", hr);
+ std::for_each(PlaybackDevices.cbegin(), PlaybackDevices.cend(), add_device);
+ break;
- case DevProbe::Capture:
- CaptureDevices.clear();
- hr = DirectSoundCaptureEnumerateW(DSoundEnumDevices, &CaptureDevices);
- if(FAILED(hr))
- ERR("Error enumerating DirectSound capture devices (0x%lx)!\n", hr);
- std::for_each(CaptureDevices.cbegin(), CaptureDevices.cend(), add_device);
- break;
+ case BackendType::Capture:
+ CaptureDevices.clear();
+ hr = DirectSoundCaptureEnumerateW(DSoundEnumDevices, &CaptureDevices);
+ if(FAILED(hr))
+ ERR("Error enumerating DirectSound capture devices (0x%lx)!\n", hr);
+ std::for_each(CaptureDevices.cbegin(), CaptureDevices.cend(), add_device);
+ break;
}
if(SUCCEEDED(hrcom))
CoUninitialize();
+
+ return outnames;
}
-BackendPtr DSoundBackendFactory::createBackend(ALCdevice *device, BackendType type)
+BackendPtr DSoundBackendFactory::createBackend(DeviceBase *device, BackendType type)
{
if(type == BackendType::Playback)
return BackendPtr{new DSoundPlayback{device}};