diff options
Diffstat (limited to 'alc/backends/dsound.cpp')
-rw-r--r-- | alc/backends/dsound.cpp | 486 |
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}}; |