diff options
author | Chris Robinson <[email protected]> | 2019-10-07 21:37:56 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2019-10-07 21:37:56 -0700 |
commit | 02d80cd74dd7b4517550af2f4ea22c409323a1d9 (patch) | |
tree | f72a927a6565d76dc7087f1a15f82733d92b4155 /alc | |
parent | f8ff4e269bf04aae1c430dbb218b4f4f6605df45 (diff) |
Use exceptions for backend open failures
Diffstat (limited to 'alc')
-rw-r--r-- | alc/alc.cpp | 32 | ||||
-rw-r--r-- | alc/backends/alsa.cpp | 35 | ||||
-rw-r--r-- | alc/backends/base.cpp | 3 | ||||
-rw-r--r-- | alc/backends/base.h | 2 | ||||
-rw-r--r-- | alc/backends/coreaudio.cpp | 165 | ||||
-rw-r--r-- | alc/backends/dsound.cpp | 122 | ||||
-rw-r--r-- | alc/backends/jack.cpp | 23 | ||||
-rw-r--r-- | alc/backends/loopback.cpp | 5 | ||||
-rw-r--r-- | alc/backends/null.cpp | 9 | ||||
-rw-r--r-- | alc/backends/opensl.cpp | 120 | ||||
-rw-r--r-- | alc/backends/oss.cpp | 70 | ||||
-rw-r--r-- | alc/backends/portaudio.cpp | 129 | ||||
-rw-r--r-- | alc/backends/pulseaudio.cpp | 96 | ||||
-rw-r--r-- | alc/backends/qsa.cpp | 25 | ||||
-rw-r--r-- | alc/backends/sdl2.cpp | 50 | ||||
-rw-r--r-- | alc/backends/sndio.cpp | 85 | ||||
-rw-r--r-- | alc/backends/solaris.cpp | 11 | ||||
-rw-r--r-- | alc/backends/wasapi.cpp | 25 | ||||
-rw-r--r-- | alc/backends/wave.cpp | 14 | ||||
-rw-r--r-- | alc/backends/winmm.cpp | 67 |
20 files changed, 524 insertions, 564 deletions
diff --git a/alc/alc.cpp b/alc/alc.cpp index 119067fd..025395fe 100644 --- a/alc/alc.cpp +++ b/alc/alc.cpp @@ -3548,16 +3548,9 @@ START_API_FUNC device->NumAuxSends = DEFAULT_SENDS; try { - /* Create the device backend. */ - device->Backend = PlaybackFactory->createBackend(device.get(), BackendType::Playback); - - /* Find a playback device to open */ - ALCenum err{device->Backend->open(deviceName)}; - if(err != ALC_NO_ERROR) - { - alcSetError(nullptr, err); - return nullptr; - } + auto backend = PlaybackFactory->createBackend(device.get(), BackendType::Playback); + backend->open(deviceName); + device->Backend = std::move(backend); } catch(al::backend_exception &e) { WARN("Failed to open playback device: %s\n", e.what()); @@ -3811,17 +3804,13 @@ START_API_FUNC device->BufferSize = static_cast<ALuint>(samples); try { - device->Backend = CaptureFactory->createBackend(device.get(), BackendType::Capture); - TRACE("Capture format: %s, %s, %uhz, %u / %u buffer\n", DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), device->Frequency, device->UpdateSize, device->BufferSize); - ALCenum err{device->Backend->open(deviceName)}; - if(err != ALC_NO_ERROR) - { - alcSetError(nullptr, err); - return nullptr; - } + + auto backend = CaptureFactory->createBackend(device.get(), BackendType::Capture); + backend->open(deviceName); + device->Backend = std::move(backend); } catch(al::backend_exception &e) { WARN("Failed to open capture device: %s\n", e.what()); @@ -4000,11 +3989,10 @@ START_API_FUNC device->NumMonoSources = device->SourcesMax - device->NumStereoSources; try { - device->Backend = LoopbackBackendFactory::getFactory().createBackend(device.get(), + auto backend = LoopbackBackendFactory::getFactory().createBackend(device.get(), BackendType::Playback); - - // Open the "backend" - device->Backend->open("Loopback"); + backend->open("Loopback"); + device->Backend = std::move(backend); } catch(al::backend_exception &e) { WARN("Failed to open loopback device: %s\n", e.what()); diff --git a/alc/backends/alsa.cpp b/alc/backends/alsa.cpp index da928171..2e157602 100644 --- a/alc/backends/alsa.cpp +++ b/alc/backends/alsa.cpp @@ -40,6 +40,7 @@ #include "albyte.h" #include "alcmain.h" #include "alconfig.h" +#include "alexcpt.h" #include "almalloc.h" #include "alnumeric.h" #include "aloptional.h" @@ -394,7 +395,7 @@ struct AlsaPlayback final : public BackendBase { int mixerProc(); int mixerNoMMapProc(); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool reset() override; bool start() override; void stop() override; @@ -592,7 +593,7 @@ int AlsaPlayback::mixerNoMMapProc() } -ALCenum AlsaPlayback::open(const ALCchar *name) +void AlsaPlayback::open(const ALCchar *name) { const char *driver{}; if(name) @@ -605,7 +606,7 @@ ALCenum AlsaPlayback::open(const ALCchar *name) { return entry.name == name; } ); if(iter == PlaybackDevices.cend()) - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name}; driver = iter->device_name.c_str(); } else @@ -619,15 +620,14 @@ ALCenum AlsaPlayback::open(const ALCchar *name) if(err < 0) { ERR("Could not open playback device '%s': %s\n", driver, snd_strerror(err)); - return ALC_OUT_OF_MEMORY; + throw al::backend_exception{ALC_OUT_OF_MEMORY, "Could not open ALSA playback \"%s\"", + driver}; } /* Free alsa's global config tree. Otherwise valgrind reports a ton of leaks. */ snd_config_update_free_global(); mDevice->DeviceName = name; - - return ALC_NO_ERROR; } bool AlsaPlayback::reset() @@ -868,7 +868,7 @@ struct AlsaCapture final : public BackendBase { AlsaCapture(ALCdevice *device) noexcept : BackendBase{device} { } ~AlsaCapture() override; - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool start() override; void stop() override; ALCenum captureSamples(al::byte *buffer, ALCuint samples) override; @@ -895,7 +895,7 @@ AlsaCapture::~AlsaCapture() } -ALCenum AlsaCapture::open(const ALCchar *name) +void AlsaCapture::open(const ALCchar *name) { const char *driver{}; if(name) @@ -908,7 +908,7 @@ ALCenum AlsaCapture::open(const ALCchar *name) { return entry.name == name; } ); if(iter == CaptureDevices.cend()) - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name}; driver = iter->device_name.c_str(); } else @@ -922,7 +922,8 @@ ALCenum AlsaCapture::open(const ALCchar *name) if(err < 0) { ERR("Could not open capture device '%s': %s\n", driver, snd_strerror(err)); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_OUT_OF_MEMORY, "Could not open ALSA capture \"%s\"", + driver}; } /* Free alsa's global config tree. Otherwise valgrind reports a ton of leaks. */ @@ -994,24 +995,16 @@ ALCenum AlsaCapture::open(const ALCchar *name) if(!mRing) { ERR("ring buffer create failed\n"); - goto error2; + throw al::backend_exception{ALC_INVALID_VALUE, "Failed to create ring buffer"}; } } mDevice->DeviceName = name; - - return ALC_NO_ERROR; + return; error: - ERR("%s failed: %s\n", funcerr, snd_strerror(err)); if(hp) snd_pcm_hw_params_free(hp); - -error2: - mRing = nullptr; - snd_pcm_close(mPcmHandle); - mPcmHandle = nullptr; - - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "%s failed: %s", funcerr, snd_strerror(err)}; } diff --git a/alc/backends/base.cpp b/alc/backends/base.cpp index a5f66606..4fce0a67 100644 --- a/alc/backends/base.cpp +++ b/alc/backends/base.cpp @@ -9,6 +9,7 @@ #include "AL/al.h" #include "alcmain.h" +#include "alexcpt.h" #include "alnumeric.h" #include "atomic.h" @@ -29,7 +30,7 @@ BackendBase::BackendBase(ALCdevice *device) noexcept : mDevice{device} BackendBase::~BackendBase() = default; bool BackendBase::reset() -{ return false; } +{ throw al::backend_exception{ALC_INVALID_VALUE, "Invalid BackendVase call"}; } ALCenum BackendBase::captureSamples(al::byte*, ALCuint) { return ALC_INVALID_DEVICE; } diff --git a/alc/backends/base.h b/alc/backends/base.h index 55240fd2..d4856818 100644 --- a/alc/backends/base.h +++ b/alc/backends/base.h @@ -32,7 +32,7 @@ inline std::chrono::nanoseconds GetDeviceClockTime(ALCdevice *device) ClockLatency GetClockLatency(ALCdevice *device); struct BackendBase { - virtual ALCenum open(const ALCchar *name) = 0; + virtual void open(const ALCchar *name) = 0; virtual bool reset(); virtual bool start() = 0; diff --git a/alc/backends/coreaudio.cpp b/alc/backends/coreaudio.cpp index 5d004efc..9254dbe0 100644 --- a/alc/backends/coreaudio.cpp +++ b/alc/backends/coreaudio.cpp @@ -27,6 +27,7 @@ #include <string.h> #include "alcmain.h" +#include "alexcpt.h" #include "alu.h" #include "ringbuffer.h" #include "converter.h" @@ -48,17 +49,21 @@ struct CoreAudioPlayback final : public BackendBase { static OSStatus MixerProcC(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, - AudioBufferList *ioData); + AudioBufferList *ioData) + { + return static_cast<CoreAudioPlayback*>(inRefCon)->MixerProc(ioActionFlags, inTimeStamp, + inBusNumber, inNumberFrames, ioData); + } OSStatus MixerProc(AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool reset() override; bool start() override; void stop() override; - AudioUnit mAudioUnit; + AudioUnit mAudioUnit{}; ALuint mFrameSize{0u}; AudioStreamBasicDescription mFormat{}; // This is the OpenAL format as a CoreAudio ASBD @@ -73,14 +78,6 @@ CoreAudioPlayback::~CoreAudioPlayback() } -OSStatus CoreAudioPlayback::MixerProcC(void *inRefCon, - AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, - UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) -{ - return static_cast<CoreAudioPlayback*>(inRefCon)->MixerProc(ioActionFlags, inTimeStamp, - inBusNumber, inNumberFrames, ioData); -} - OSStatus CoreAudioPlayback::MixerProc(AudioUnitRenderActionFlags*, const AudioTimeStamp*, UInt32, UInt32, AudioBufferList *ioData) { @@ -91,12 +88,12 @@ OSStatus CoreAudioPlayback::MixerProc(AudioUnitRenderActionFlags*, } -ALCenum CoreAudioPlayback::open(const ALCchar *name) +void CoreAudioPlayback::open(const ALCchar *name) { if(!name) name = ca_device; else if(strcmp(name, ca_device) != 0) - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name}; /* open the default output unit */ AudioComponentDescription desc{}; @@ -114,14 +111,15 @@ ALCenum CoreAudioPlayback::open(const ALCchar *name) if(comp == nullptr) { ERR("AudioComponentFindNext failed\n"); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Could not find audio component"}; } OSStatus err{AudioComponentInstanceNew(comp, &mAudioUnit)}; if(err != noErr) { ERR("AudioComponentInstanceNew failed\n"); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Could not create component instance: %u", + err}; } /* init and start the default audio unit... */ @@ -129,12 +127,10 @@ ALCenum CoreAudioPlayback::open(const ALCchar *name) if(err != noErr) { ERR("AudioUnitInitialize failed\n"); - AudioComponentInstanceDispose(mAudioUnit); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Could not initialize audio unit: %u", err}; } mDevice->DeviceName = name; - return ALC_NO_ERROR; } bool CoreAudioPlayback::reset() @@ -307,12 +303,16 @@ struct CoreAudioCapture final : public BackendBase { static OSStatus RecordProcC(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, - AudioBufferList *ioData); + AudioBufferList *ioData) + { + return static_cast<CoreAudioCapture*>(inRefCon)->RecordProc(ioActionFlags, inTimeStamp, + inBusNumber, inNumberFrames, ioData); + } OSStatus RecordProc(AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool start() override; void stop() override; ALCenum captureSamples(al::byte *buffer, ALCuint samples) override; @@ -338,23 +338,15 @@ CoreAudioCapture::~CoreAudioCapture() } -OSStatus CoreAudioCapture::RecordProcC(void *inRefCon, - AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, - UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) -{ - return static_cast<CoreAudioCapture*>(inRefCon)->RecordProc(ioActionFlags, inTimeStamp, - inBusNumber, inNumberFrames, ioData); -} - OSStatus CoreAudioCapture::RecordProc(AudioUnitRenderActionFlags*, const AudioTimeStamp *inTimeStamp, UInt32, UInt32 inNumberFrames, AudioBufferList*) { AudioUnitRenderActionFlags flags = 0; union { - ALbyte _[sizeof(AudioBufferList) + sizeof(AudioBuffer)*2]; + al::byte _[sizeof(AudioBufferList) + sizeof(AudioBuffer)*2]; AudioBufferList list; - } audiobuf = { { 0 } }; + } audiobuf{}; auto rec_vec = mRing->getWriteVector(); inNumberFrames = static_cast<UInt32>(minz(inNumberFrames, @@ -393,7 +385,7 @@ OSStatus CoreAudioCapture::RecordProc(AudioUnitRenderActionFlags*, } -ALCenum CoreAudioCapture::open(const ALCchar *name) +void CoreAudioCapture::open(const ALCchar *name) { AudioStreamBasicDescription requestedFormat; // The application requested format AudioStreamBasicDescription hardwareFormat; // The hardware format @@ -412,7 +404,7 @@ ALCenum CoreAudioCapture::open(const ALCchar *name) if(!name) name = ca_device; else if(strcmp(name, ca_device) != 0) - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name}; desc.componentType = kAudioUnitType_Output; #if TARGET_OS_IOS @@ -429,7 +421,7 @@ ALCenum CoreAudioCapture::open(const ALCchar *name) if(comp == NULL) { ERR("AudioComponentFindNext failed\n"); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Could not finda udio component"}; } // Open the component @@ -437,7 +429,8 @@ ALCenum CoreAudioCapture::open(const ALCchar *name) if(err != noErr) { ERR("AudioComponentInstanceNew failed\n"); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Could not create component instance: %u", + err}; } // Turn off AudioUnit output @@ -447,7 +440,8 @@ ALCenum CoreAudioCapture::open(const ALCchar *name) if(err != noErr) { ERR("AudioUnitSetProperty failed\n"); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, + "Could not disable audio unit output property: %u", err}; } // Turn on AudioUnit input @@ -457,7 +451,8 @@ ALCenum CoreAudioCapture::open(const ALCchar *name) if(err != noErr) { ERR("AudioUnitSetProperty failed\n"); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, + "Could not enable audio unit input property: %u", err}; } #if !TARGET_OS_IOS @@ -470,16 +465,17 @@ ALCenum CoreAudioCapture::open(const ALCchar *name) propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; propertyAddress.mElement = kAudioObjectPropertyElementMaster; - err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &propertySize, &inputDevice); + err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, nullptr, + &propertySize, &inputDevice); if(err != noErr) { ERR("AudioObjectGetPropertyData failed\n"); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Could not get input device: %u", err}; } if(inputDevice == kAudioDeviceUnknown) { ERR("No input device found\n"); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Unknown input device"}; } // Track the input device @@ -488,7 +484,7 @@ ALCenum CoreAudioCapture::open(const ALCchar *name) if(err != noErr) { ERR("AudioUnitSetProperty failed\n"); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Could not set input device: %u", err}; } } #endif @@ -502,7 +498,7 @@ ALCenum CoreAudioCapture::open(const ALCchar *name) if(err != noErr) { ERR("AudioUnitSetProperty failed\n"); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Could not set capture callback: %u", err}; } // Initialize the device @@ -510,7 +506,7 @@ ALCenum CoreAudioCapture::open(const ALCchar *name) if(err != noErr) { ERR("AudioUnitInitialize failed\n"); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Could not initialize audio unit: %u", err}; } // Get the hardware format @@ -520,52 +516,54 @@ ALCenum CoreAudioCapture::open(const ALCchar *name) if(err != noErr || propertySize != sizeof(AudioStreamBasicDescription)) { ERR("AudioUnitGetProperty failed\n"); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Could not get input format: %u", err}; } // Set up the requested format description switch(mDevice->FmtType) { - case DevFmtUByte: - requestedFormat.mBitsPerChannel = 8; - requestedFormat.mFormatFlags = kAudioFormatFlagIsPacked; - break; - case DevFmtShort: - requestedFormat.mBitsPerChannel = 16; - requestedFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked; - break; - case DevFmtInt: - requestedFormat.mBitsPerChannel = 32; - requestedFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked; - break; - case DevFmtFloat: - requestedFormat.mBitsPerChannel = 32; - requestedFormat.mFormatFlags = kAudioFormatFlagIsPacked; - break; - case DevFmtByte: - case DevFmtUShort: - case DevFmtUInt: - ERR("%s samples not supported\n", DevFmtTypeString(mDevice->FmtType)); - return ALC_INVALID_VALUE; + case DevFmtUByte: + requestedFormat.mBitsPerChannel = 8; + requestedFormat.mFormatFlags = kAudioFormatFlagIsPacked; + break; + case DevFmtShort: + requestedFormat.mBitsPerChannel = 16; + requestedFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked; + break; + case DevFmtInt: + requestedFormat.mBitsPerChannel = 32; + requestedFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked; + break; + case DevFmtFloat: + requestedFormat.mBitsPerChannel = 32; + requestedFormat.mFormatFlags = kAudioFormatFlagIsPacked; + break; + case DevFmtByte: + case DevFmtUShort: + case DevFmtUInt: + ERR("%s samples not supported\n", DevFmtTypeString(mDevice->FmtType)); + throw al::backend_exception{ALC_INVALID_VALUE, "%s samples not suppoted", + DevFmtTypeString(mDevice->FmtType)}; } switch(mDevice->FmtChans) { - case DevFmtMono: - requestedFormat.mChannelsPerFrame = 1; - break; - case DevFmtStereo: - requestedFormat.mChannelsPerFrame = 2; - break; + case DevFmtMono: + requestedFormat.mChannelsPerFrame = 1; + break; + case DevFmtStereo: + requestedFormat.mChannelsPerFrame = 2; + break; - case DevFmtQuad: - case DevFmtX51: - case DevFmtX51Rear: - case DevFmtX61: - case DevFmtX71: - case DevFmtAmbi3D: - ERR("%s not supported\n", DevFmtChannelsString(mDevice->FmtChans)); - return ALC_INVALID_VALUE; + case DevFmtQuad: + case DevFmtX51: + case DevFmtX51Rear: + case DevFmtX61: + case DevFmtX71: + case DevFmtAmbi3D: + ERR("%s not supported\n", DevFmtChannelsString(mDevice->FmtChans)); + throw al::backend_exception{ALC_INVALID_VALUE, "%s not supported", + DevFmtChannelsString(mDevice->FmtChans)}; } requestedFormat.mBytesPerFrame = requestedFormat.mChannelsPerFrame * requestedFormat.mBitsPerChannel / 8; @@ -591,7 +589,7 @@ ALCenum CoreAudioCapture::open(const ALCchar *name) if(err != noErr) { ERR("AudioUnitSetProperty failed\n"); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Could not set input format: %u", err}; } // Set the AudioUnit output format frame count @@ -602,7 +600,8 @@ ALCenum CoreAudioCapture::open(const ALCchar *name) if(FrameCount64 > std::numeric_limits<uint32_t>::max()/2) { ERR("FrameCount too large\n"); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, + "Calculated frame count is too lareg: %" PRIu64, FrameCount64}; } outputFrameCount = static_cast<uint32_t>(FrameCount64); @@ -611,7 +610,8 @@ ALCenum CoreAudioCapture::open(const ALCchar *name) if(err != noErr) { ERR("AudioUnitSetProperty failed: %d\n", err); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Failed to set capture frame count: %u", + err}; } // Set up sample converter if needed @@ -621,10 +621,9 @@ ALCenum CoreAudioCapture::open(const ALCchar *name) mDevice->Frequency, Resampler::FastBSinc24); mRing = CreateRingBuffer(outputFrameCount, mFrameSize, false); - if(!mRing) return ALC_INVALID_VALUE; + if(!mRing) throw al::backend_exception{ALC_INVALID_VALUE, "Failed to allocate ring buffer"}; mDevice->DeviceName = name; - return ALC_NO_ERROR; } diff --git a/alc/backends/dsound.cpp b/alc/backends/dsound.cpp index c7014e33..19a3c604 100644 --- a/alc/backends/dsound.cpp +++ b/alc/backends/dsound.cpp @@ -45,6 +45,7 @@ #include <functional> #include "alcmain.h" +#include "alexcpt.h" #include "alu.h" #include "ringbuffer.h" #include "compat.h" @@ -166,7 +167,7 @@ struct DSoundPlayback final : public BackendBase { int mixerProc(); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool reset() override; bool start() override; void stop() override; @@ -298,7 +299,7 @@ FORCE_ALIGN int DSoundPlayback::mixerProc() return 0; } -ALCenum DSoundPlayback::open(const ALCchar *name) +void DSoundPlayback::open(const ALCchar *name) { HRESULT hr; if(PlaybackDevices.empty()) @@ -325,7 +326,7 @@ ALCenum DSoundPlayback::open(const ALCchar *name) { return entry.name == name; } ); if(iter == PlaybackDevices.cend()) - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name}; guid = &iter->guid; } @@ -341,11 +342,10 @@ ALCenum DSoundPlayback::open(const ALCchar *name) if(FAILED(hr)) { ERR("Device init failed: 0x%08lx\n", hr); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Device init failed: 0x%08lx", hr}; } mDevice->DeviceName = name; - return ALC_NO_ERROR; } bool DSoundPlayback::reset() @@ -596,7 +596,7 @@ struct DSoundCapture final : public BackendBase { DSoundCapture(ALCdevice *device) noexcept : BackendBase{device} { } ~DSoundCapture() override; - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool start() override; void stop() override; ALCenum captureSamples(al::byte *buffer, ALCuint samples) override; @@ -627,7 +627,7 @@ DSoundCapture::~DSoundCapture() } -ALCenum DSoundCapture::open(const ALCchar *name) +void DSoundCapture::open(const ALCchar *name) { HRESULT hr; if(CaptureDevices.empty()) @@ -654,79 +654,60 @@ ALCenum DSoundCapture::open(const ALCchar *name) { return entry.name == name; } ); if(iter == CaptureDevices.cend()) - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name}; guid = &iter->guid; } switch(mDevice->FmtType) { - case DevFmtByte: - case DevFmtUShort: - case DevFmtUInt: - WARN("%s capture samples not supported\n", DevFmtTypeString(mDevice->FmtType)); - return ALC_INVALID_ENUM; + case DevFmtByte: + 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)}; - case DevFmtUByte: - case DevFmtShort: - case DevFmtInt: - case DevFmtFloat: - break; + case DevFmtUByte: + case DevFmtShort: + case DevFmtInt: + case DevFmtFloat: + break; } 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 DevFmtAmbi3D: - WARN("%s capture not supported\n", DevFmtChannelsString(mDevice->FmtChans)); - return ALC_INVALID_ENUM; + 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 DevFmtAmbi3D: + WARN("%s capture not supported\n", DevFmtChannelsString(mDevice->FmtChans)); + throw al::backend_exception{ALC_INVALID_VALUE, "%s capture not supported", + DevFmtChannelsString(mDevice->FmtChans)}; } InputType.Format.wFormatTag = WAVE_FORMAT_PCM; @@ -781,14 +762,13 @@ ALCenum DSoundCapture::open(const ALCchar *name) mDSC->Release(); mDSC = nullptr; - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Device init failed: 0x%08lx", hr}; } mBufferBytes = DSCBDescription.dwBufferBytes; SetDefaultWFXChannelOrder(mDevice); mDevice->DeviceName = name; - return ALC_NO_ERROR; } bool DSoundCapture::start() diff --git a/alc/backends/jack.cpp b/alc/backends/jack.cpp index 660ea933..c7e2839c 100644 --- a/alc/backends/jack.cpp +++ b/alc/backends/jack.cpp @@ -32,6 +32,7 @@ #include "alcmain.h" #include "alu.h" #include "alconfig.h" +#include "alexcpt.h" #include "dynload.h" #include "ringbuffer.h" #include "threads.h" @@ -153,15 +154,17 @@ struct JackPlayback final : public BackendBase { JackPlayback(ALCdevice *device) noexcept : BackendBase{device} { } ~JackPlayback() override; - static int bufferSizeNotifyC(jack_nframes_t numframes, void *arg); + static int bufferSizeNotifyC(jack_nframes_t numframes, void *arg) + { return static_cast<JackPlayback*>(arg)->bufferSizeNotify(numframes); } int bufferSizeNotify(jack_nframes_t numframes); - static int processC(jack_nframes_t numframes, void *arg); + static int processC(jack_nframes_t numframes, void *arg) + { return static_cast<JackPlayback*>(arg)->process(numframes); } int process(jack_nframes_t numframes); int mixerProc(); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool reset() override; bool start() override; void stop() override; @@ -194,9 +197,6 @@ JackPlayback::~JackPlayback() } -int JackPlayback::bufferSizeNotifyC(jack_nframes_t numframes, void *arg) -{ return static_cast<JackPlayback*>(arg)->bufferSizeNotify(numframes); } - int JackPlayback::bufferSizeNotify(jack_nframes_t numframes) { std::lock_guard<std::mutex> _{mDevice->StateLock}; @@ -221,9 +221,6 @@ int JackPlayback::bufferSizeNotify(jack_nframes_t numframes) } -int JackPlayback::processC(jack_nframes_t numframes, void *arg) -{ return static_cast<JackPlayback*>(arg)->process(numframes); } - int JackPlayback::process(jack_nframes_t numframes) { jack_default_audio_sample_t *out[MAX_OUTPUT_CHANNELS]; @@ -329,12 +326,12 @@ int JackPlayback::mixerProc() } -ALCenum JackPlayback::open(const ALCchar *name) +void JackPlayback::open(const ALCchar *name) { if(!name) name = jackDevice; else if(strcmp(name, jackDevice) != 0) - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name}; const char *client_name{"alsoft"}; jack_status_t status; @@ -342,7 +339,8 @@ ALCenum JackPlayback::open(const ALCchar *name) if(mClient == nullptr) { ERR("jack_client_open() failed, status = 0x%02x\n", status); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Failed to connect to JACK server: 0x%02x", + status}; } if((status&JackServerStarted)) TRACE("JACK server started\n"); @@ -356,7 +354,6 @@ ALCenum JackPlayback::open(const ALCchar *name) jack_set_buffer_size_callback(mClient, &JackPlayback::bufferSizeNotifyC, this); mDevice->DeviceName = name; - return ALC_NO_ERROR; } bool JackPlayback::reset() diff --git a/alc/backends/loopback.cpp b/alc/backends/loopback.cpp index 7edc2d40..511061f3 100644 --- a/alc/backends/loopback.cpp +++ b/alc/backends/loopback.cpp @@ -31,7 +31,7 @@ namespace { struct LoopbackBackend final : public BackendBase { LoopbackBackend(ALCdevice *device) noexcept : BackendBase{device} { } - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool reset() override; bool start() override; void stop() override; @@ -40,10 +40,9 @@ struct LoopbackBackend final : public BackendBase { }; -ALCenum LoopbackBackend::open(const ALCchar *name) +void LoopbackBackend::open(const ALCchar *name) { mDevice->DeviceName = name; - return ALC_NO_ERROR; } bool LoopbackBackend::reset() diff --git a/alc/backends/null.cpp b/alc/backends/null.cpp index b6b115f1..aca59605 100644 --- a/alc/backends/null.cpp +++ b/alc/backends/null.cpp @@ -31,6 +31,7 @@ #include <thread> #include "alcmain.h" +#include "alexcpt.h" #include "almalloc.h" #include "alu.h" #include "logging.h" @@ -51,7 +52,7 @@ struct NullBackend final : public BackendBase { int mixerProc(); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool reset() override; bool start() override; void stop() override; @@ -108,16 +109,14 @@ int NullBackend::mixerProc() } -ALCenum NullBackend::open(const ALCchar *name) +void NullBackend::open(const ALCchar *name) { if(!name) name = nullDevice; else if(strcmp(name, nullDevice) != 0) - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name}; mDevice->DeviceName = name; - - return ALC_NO_ERROR; } bool NullBackend::reset() diff --git a/alc/backends/opensl.cpp b/alc/backends/opensl.cpp index 50ea884d..4e4ceb5b 100644 --- a/alc/backends/opensl.cpp +++ b/alc/backends/opensl.cpp @@ -28,10 +28,12 @@ #include <new> #include <array> +#include <cstring> #include <thread> #include <functional> #include "alcmain.h" +#include "alexcpt.h" #include "alu.h" #include "compat.h" #include "endiantest.h" @@ -58,26 +60,24 @@ SLuint32 GetChannelMask(DevFmtChannels chans) { switch(chans) { - case DevFmtMono: return SL_SPEAKER_FRONT_CENTER; - case DevFmtStereo: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT; - case DevFmtQuad: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT| - SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT; - case DevFmtX51: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT| - SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY| - SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT; - case DevFmtX51Rear: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT| - SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY| - SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT; - case DevFmtX61: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT| - SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY| - SL_SPEAKER_BACK_CENTER| - SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT; - case DevFmtX71: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT| - SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY| - SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT| - SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT; - case DevFmtAmbi3D: - break; + case DevFmtMono: return SL_SPEAKER_FRONT_CENTER; + case DevFmtStereo: return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; + case DevFmtQuad: return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT | + SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT; + case DevFmtX51: return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT | + SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY | SL_SPEAKER_SIDE_LEFT | + SL_SPEAKER_SIDE_RIGHT; + case DevFmtX51Rear: return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT | + SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY | SL_SPEAKER_BACK_LEFT | + SL_SPEAKER_BACK_RIGHT; + case DevFmtX61: return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT | + SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY | SL_SPEAKER_BACK_CENTER | + SL_SPEAKER_SIDE_LEFT | SL_SPEAKER_SIDE_RIGHT; + case DevFmtX71: return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT | + SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY | SL_SPEAKER_BACK_LEFT | + SL_SPEAKER_BACK_RIGHT | SL_SPEAKER_SIDE_LEFT | SL_SPEAKER_SIDE_RIGHT; + case DevFmtAmbi3D: + break; } return 0; } @@ -87,16 +87,16 @@ SLuint32 GetTypeRepresentation(DevFmtType type) { switch(type) { - case DevFmtUByte: - case DevFmtUShort: - case DevFmtUInt: - return SL_ANDROID_PCM_REPRESENTATION_UNSIGNED_INT; - case DevFmtByte: - case DevFmtShort: - case DevFmtInt: - return SL_ANDROID_PCM_REPRESENTATION_SIGNED_INT; - case DevFmtFloat: - return SL_ANDROID_PCM_REPRESENTATION_FLOAT; + case DevFmtUByte: + case DevFmtUShort: + case DevFmtUInt: + return SL_ANDROID_PCM_REPRESENTATION_UNSIGNED_INT; + case DevFmtByte: + case DevFmtShort: + case DevFmtInt: + return SL_ANDROID_PCM_REPRESENTATION_SIGNED_INT; + case DevFmtFloat: + return SL_ANDROID_PCM_REPRESENTATION_FLOAT; } return 0; } @@ -106,31 +106,31 @@ const char *res_str(SLresult result) { switch(result) { - case SL_RESULT_SUCCESS: return "Success"; - case SL_RESULT_PRECONDITIONS_VIOLATED: return "Preconditions violated"; - case SL_RESULT_PARAMETER_INVALID: return "Parameter invalid"; - case SL_RESULT_MEMORY_FAILURE: return "Memory failure"; - case SL_RESULT_RESOURCE_ERROR: return "Resource error"; - case SL_RESULT_RESOURCE_LOST: return "Resource lost"; - case SL_RESULT_IO_ERROR: return "I/O error"; - case SL_RESULT_BUFFER_INSUFFICIENT: return "Buffer insufficient"; - case SL_RESULT_CONTENT_CORRUPTED: return "Content corrupted"; - case SL_RESULT_CONTENT_UNSUPPORTED: return "Content unsupported"; - case SL_RESULT_CONTENT_NOT_FOUND: return "Content not found"; - case SL_RESULT_PERMISSION_DENIED: return "Permission denied"; - case SL_RESULT_FEATURE_UNSUPPORTED: return "Feature unsupported"; - case SL_RESULT_INTERNAL_ERROR: return "Internal error"; - case SL_RESULT_UNKNOWN_ERROR: return "Unknown error"; - case SL_RESULT_OPERATION_ABORTED: return "Operation aborted"; - case SL_RESULT_CONTROL_LOST: return "Control lost"; + case SL_RESULT_SUCCESS: return "Success"; + case SL_RESULT_PRECONDITIONS_VIOLATED: return "Preconditions violated"; + case SL_RESULT_PARAMETER_INVALID: return "Parameter invalid"; + case SL_RESULT_MEMORY_FAILURE: return "Memory failure"; + case SL_RESULT_RESOURCE_ERROR: return "Resource error"; + case SL_RESULT_RESOURCE_LOST: return "Resource lost"; + case SL_RESULT_IO_ERROR: return "I/O error"; + case SL_RESULT_BUFFER_INSUFFICIENT: return "Buffer insufficient"; + case SL_RESULT_CONTENT_CORRUPTED: return "Content corrupted"; + case SL_RESULT_CONTENT_UNSUPPORTED: return "Content unsupported"; + case SL_RESULT_CONTENT_NOT_FOUND: return "Content not found"; + case SL_RESULT_PERMISSION_DENIED: return "Permission denied"; + case SL_RESULT_FEATURE_UNSUPPORTED: return "Feature unsupported"; + case SL_RESULT_INTERNAL_ERROR: return "Internal error"; + case SL_RESULT_UNKNOWN_ERROR: return "Unknown error"; + case SL_RESULT_OPERATION_ABORTED: return "Operation aborted"; + case SL_RESULT_CONTROL_LOST: return "Control lost"; #ifdef SL_RESULT_READONLY - case SL_RESULT_READONLY: return "ReadOnly"; + case SL_RESULT_READONLY: return "ReadOnly"; #endif #ifdef SL_RESULT_ENGINEOPTION_UNSUPPORTED - case SL_RESULT_ENGINEOPTION_UNSUPPORTED: return "Engine option unsupported"; + case SL_RESULT_ENGINEOPTION_UNSUPPORTED: return "Engine option unsupported"; #endif #ifdef SL_RESULT_SOURCE_SINK_INCOMPATIBLE - case SL_RESULT_SOURCE_SINK_INCOMPATIBLE: return "Source/Sink incompatible"; + case SL_RESULT_SOURCE_SINK_INCOMPATIBLE: return "Source/Sink incompatible"; #endif } return "Unknown error code"; @@ -152,7 +152,7 @@ struct OpenSLPlayback final : public BackendBase { int mixerProc(); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool reset() override; bool start() override; void stop() override; @@ -298,12 +298,12 @@ int OpenSLPlayback::mixerProc() } -ALCenum OpenSLPlayback::open(const ALCchar *name) +void OpenSLPlayback::open(const ALCchar *name) { if(!name) name = opensl_device; else if(strcmp(name, opensl_device) != 0) - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name}; // create engine SLresult result{slCreateEngine(&mEngineObj, 0, nullptr, 0, nullptr, nullptr)}; @@ -340,11 +340,11 @@ ALCenum OpenSLPlayback::open(const ALCchar *name) mEngineObj = nullptr; mEngine = nullptr; - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Failed to initialize OpenSL: 0x%08x", + result}; } mDevice->DeviceName = name; - return ALC_NO_ERROR; } bool OpenSLPlayback::reset() @@ -635,7 +635,7 @@ struct OpenSLCapture final : public BackendBase { { static_cast<OpenSLCapture*>(context)->process(bq); } void process(SLAndroidSimpleBufferQueueItf bq); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool start() override; void stop() override; ALCenum captureSamples(al::byte *buffer, ALCuint samples) override; @@ -676,12 +676,12 @@ void OpenSLCapture::process(SLAndroidSimpleBufferQueueItf) } -ALCenum OpenSLCapture::open(const ALCchar* name) +void OpenSLCapture::open(const ALCchar* name) { if(!name) name = opensl_device; else if(strcmp(name, opensl_device) != 0) - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name}; SLresult result{slCreateEngine(&mEngineObj, 0, nullptr, 0, nullptr, nullptr)}; PRINTERR(result, "slCreateEngine"); @@ -841,11 +841,11 @@ ALCenum OpenSLCapture::open(const ALCchar* name) mEngineObj = nullptr; mEngine = nullptr; - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Failed to initialize OpenSL: 0x%08x", + result}; } mDevice->DeviceName = name; - return ALC_NO_ERROR; } bool OpenSLCapture::start() diff --git a/alc/backends/oss.cpp b/alc/backends/oss.cpp index c825ce3e..1e3ad28b 100644 --- a/alc/backends/oss.cpp +++ b/alc/backends/oss.cpp @@ -45,6 +45,7 @@ #include "alcmain.h" #include "alconfig.h" +#include "alexcpt.h" #include "almalloc.h" #include "alnumeric.h" #include "aloptional.h" @@ -248,7 +249,7 @@ struct OSSPlayback final : public BackendBase { int mixerProc(); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool reset() override; bool start() override; void stop() override; @@ -329,7 +330,7 @@ int OSSPlayback::mixerProc() } -ALCenum OSSPlayback::open(const ALCchar *name) +void OSSPlayback::open(const ALCchar *name) { const char *devname{DefaultPlayback.c_str()}; if(!name) @@ -344,7 +345,7 @@ ALCenum OSSPlayback::open(const ALCchar *name) { return entry.name == name; } ); if(iter == PlaybackDevices.cend()) - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name}; devname = iter->device_name.c_str(); } @@ -352,11 +353,11 @@ ALCenum OSSPlayback::open(const ALCchar *name) if(mFd == -1) { ERR("Could not open %s: %s\n", devname, strerror(errno)); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Could not open %s: %s", devname, + strerror(errno)}; } mDevice->DeviceName = name; - return ALC_NO_ERROR; } bool OSSPlayback::reset() @@ -469,7 +470,7 @@ struct OSScapture final : public BackendBase { int recordProc(); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool start() override; void stop() override; ALCenum captureSamples(al::byte *buffer, ALCuint samples) override; @@ -539,7 +540,7 @@ int OSScapture::recordProc() } -ALCenum OSScapture::open(const ALCchar *name) +void OSScapture::open(const ALCchar *name) { const char *devname{DefaultCapture.c_str()}; if(!name) @@ -554,7 +555,7 @@ ALCenum OSScapture::open(const ALCchar *name) { return entry.name == name; } ); if(iter == CaptureDevices.cend()) - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name}; devname = iter->device_name.c_str(); } @@ -562,27 +563,29 @@ ALCenum OSScapture::open(const ALCchar *name) if(mFd == -1) { ERR("Could not open %s: %s\n", devname, strerror(errno)); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Could not open %s: %s", devname, + strerror(errno)}; } int ossFormat{}; switch(mDevice->FmtType) { - case DevFmtByte: - ossFormat = AFMT_S8; - break; - case DevFmtUByte: - ossFormat = AFMT_U8; - break; - case DevFmtShort: - ossFormat = AFMT_S16_NE; - break; - case DevFmtUShort: - case DevFmtInt: - case DevFmtUInt: - case DevFmtFloat: - ERR("%s capture samples not supported\n", DevFmtTypeString(mDevice->FmtType)); - return ALC_INVALID_VALUE; + case DevFmtByte: + ossFormat = AFMT_S8; + break; + case DevFmtUByte: + ossFormat = AFMT_U8; + break; + case DevFmtShort: + ossFormat = AFMT_S16_NE; + break; + case DevFmtUShort: + case DevFmtInt: + case DevFmtUInt: + case DevFmtFloat: + ERR("%s capture samples not supported\n", DevFmtTypeString(mDevice->FmtType)); + throw al::backend_exception{ALC_INVALID_VALUE, "%s capture samples not supported", + DevFmtTypeString(mDevice->FmtType)}; } ALuint periods{4}; @@ -608,9 +611,7 @@ ALCenum OSScapture::open(const ALCchar *name) { err: ERR("%s failed: %s\n", err, strerror(errno)); - close(mFd); - mFd = -1; - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "%s failed: %s", err, strerror(errno)}; } #undef CHECKERR @@ -618,9 +619,8 @@ ALCenum OSScapture::open(const ALCchar *name) { ERR("Failed to set %s, got %d channels instead\n", DevFmtChannelsString(mDevice->FmtChans), numChannels); - close(mFd); - mFd = -1; - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Failed to set %s capture", + DevFmtChannelsString(mDevice->FmtChans)}; } if(!((ossFormat == AFMT_S8 && mDevice->FmtType == DevFmtByte) || @@ -628,22 +628,18 @@ ALCenum OSScapture::open(const ALCchar *name) (ossFormat == AFMT_S16_NE && mDevice->FmtType == DevFmtShort))) { ERR("Failed to set %s samples, got OSS format %#x\n", DevFmtTypeString(mDevice->FmtType), ossFormat); - close(mFd); - mFd = -1; - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Failed to set %s samples", + DevFmtTypeString(mDevice->FmtType)}; } mRing = CreateRingBuffer(mDevice->BufferSize, frameSize, false); if(!mRing) { ERR("Ring buffer create failed\n"); - close(mFd); - mFd = -1; - return ALC_OUT_OF_MEMORY; + throw al::backend_exception{ALC_INVALID_VALUE, "Failed to create ring buffer"}; } mDevice->DeviceName = name; - return ALC_NO_ERROR; } bool OSScapture::start() diff --git a/alc/backends/portaudio.cpp b/alc/backends/portaudio.cpp index 0b77f622..7847f41d 100644 --- a/alc/backends/portaudio.cpp +++ b/alc/backends/portaudio.cpp @@ -27,6 +27,7 @@ #include <cstring> #include "alcmain.h" +#include "alexcpt.h" #include "alu.h" #include "alconfig.h" #include "dynload.h" @@ -76,11 +77,15 @@ struct PortPlayback final : public BackendBase { static int writeCallbackC(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, - const PaStreamCallbackFlags statusFlags, void *userData); + const PaStreamCallbackFlags statusFlags, void *userData) + { + return static_cast<PortPlayback*>(userData)->writeCallback(inputBuffer, outputBuffer, + framesPerBuffer, timeInfo, statusFlags); + } int writeCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, const PaStreamCallbackFlags statusFlags); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool reset() override; bool start() override; void stop() override; @@ -101,14 +106,6 @@ PortPlayback::~PortPlayback() } -int PortPlayback::writeCallbackC(const void *inputBuffer, void *outputBuffer, - unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, - const PaStreamCallbackFlags statusFlags, void *userData) -{ - return static_cast<PortPlayback*>(userData)->writeCallback(inputBuffer, outputBuffer, - framesPerBuffer, timeInfo, statusFlags); -} - int PortPlayback::writeCallback(const void*, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo*, const PaStreamCallbackFlags) @@ -120,12 +117,12 @@ int PortPlayback::writeCallback(const void*, void *outputBuffer, } -ALCenum PortPlayback::open(const ALCchar *name) +void PortPlayback::open(const ALCchar *name) { if(!name) name = pa_device; else if(strcmp(name, pa_device) != 0) - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name}; mUpdateSize = mDevice->UpdateSize; @@ -139,25 +136,25 @@ ALCenum PortPlayback::open(const ALCchar *name) switch(mDevice->FmtType) { - case DevFmtByte: - mParams.sampleFormat = paInt8; - break; - case DevFmtUByte: - mParams.sampleFormat = paUInt8; - break; - case DevFmtUShort: - /* fall-through */ - case DevFmtShort: - mParams.sampleFormat = paInt16; - break; - case DevFmtUInt: - /* fall-through */ - case DevFmtInt: - mParams.sampleFormat = paInt32; - break; - case DevFmtFloat: - mParams.sampleFormat = paFloat32; - break; + case DevFmtByte: + mParams.sampleFormat = paInt8; + break; + case DevFmtUByte: + mParams.sampleFormat = paUInt8; + break; + case DevFmtUShort: + /* fall-through */ + case DevFmtShort: + mParams.sampleFormat = paInt16; + break; + case DevFmtUInt: + /* fall-through */ + case DevFmtInt: + mParams.sampleFormat = paInt32; + break; + case DevFmtFloat: + mParams.sampleFormat = paFloat32; + break; } retry_open: @@ -171,12 +168,11 @@ retry_open: goto retry_open; } ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err)); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Failed to open stream: %s", + Pa_GetErrorText(err)}; } mDevice->DeviceName = name; - return ALC_NO_ERROR; - } bool PortPlayback::reset() @@ -240,11 +236,15 @@ struct PortCapture final : public BackendBase { static int readCallbackC(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, - const PaStreamCallbackFlags statusFlags, void *userData); + const PaStreamCallbackFlags statusFlags, void *userData) + { + return static_cast<PortCapture*>(userData)->readCallback(inputBuffer, outputBuffer, + framesPerBuffer, timeInfo, statusFlags); + } int readCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, const PaStreamCallbackFlags statusFlags); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool start() override; void stop() override; ALCenum captureSamples(al::byte *buffer, ALCuint samples) override; @@ -267,14 +267,6 @@ PortCapture::~PortCapture() } -int PortCapture::readCallbackC(const void *inputBuffer, void *outputBuffer, - unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, - const PaStreamCallbackFlags statusFlags, void* userData) -{ - return static_cast<PortCapture*>(userData)->readCallback(inputBuffer, outputBuffer, - framesPerBuffer, timeInfo, statusFlags); -} - int PortCapture::readCallback(const void *inputBuffer, void*, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo*, const PaStreamCallbackFlags) @@ -284,19 +276,19 @@ int PortCapture::readCallback(const void *inputBuffer, void*, } -ALCenum PortCapture::open(const ALCchar *name) +void PortCapture::open(const ALCchar *name) { if(!name) name = pa_device; else if(strcmp(name, pa_device) != 0) - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name}; ALuint samples{mDevice->BufferSize}; samples = maxu(samples, 100 * mDevice->Frequency / 1000); ALuint frame_size{mDevice->frameSizeFromFmt()}; mRing = CreateRingBuffer(samples, frame_size, false); - if(!mRing) return ALC_INVALID_VALUE; + if(!mRing) throw al::backend_exception{ALC_INVALID_VALUE, "Failed to create ring buffer"}; auto devidopt = ConfigValueInt(nullptr, "port", "capture"); if(devidopt && *devidopt >= 0) mParams.device = *devidopt; @@ -306,25 +298,26 @@ ALCenum PortCapture::open(const ALCchar *name) switch(mDevice->FmtType) { - case DevFmtByte: - mParams.sampleFormat = paInt8; - break; - case DevFmtUByte: - mParams.sampleFormat = paUInt8; - break; - case DevFmtShort: - mParams.sampleFormat = paInt16; - break; - case DevFmtInt: - mParams.sampleFormat = paInt32; - break; - case DevFmtFloat: - mParams.sampleFormat = paFloat32; - break; - case DevFmtUInt: - case DevFmtUShort: - ERR("%s samples not supported\n", DevFmtTypeString(mDevice->FmtType)); - return ALC_INVALID_VALUE; + case DevFmtByte: + mParams.sampleFormat = paInt8; + break; + case DevFmtUByte: + mParams.sampleFormat = paUInt8; + break; + case DevFmtShort: + mParams.sampleFormat = paInt16; + break; + case DevFmtInt: + mParams.sampleFormat = paInt32; + break; + case DevFmtFloat: + mParams.sampleFormat = paFloat32; + break; + case DevFmtUInt: + case DevFmtUShort: + ERR("%s samples not supported\n", DevFmtTypeString(mDevice->FmtType)); + throw al::backend_exception{ALC_INVALID_VALUE, "%s samples not supported", + DevFmtTypeString(mDevice->FmtType)}; } mParams.channelCount = static_cast<int>(mDevice->channelsFromFmt()); @@ -333,11 +326,11 @@ ALCenum PortCapture::open(const ALCchar *name) if(err != paNoError) { ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err)); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Failed to open stream: %s", + Pa_GetErrorText(err)}; } mDevice->DeviceName = name; - return ALC_NO_ERROR; } diff --git a/alc/backends/pulseaudio.cpp b/alc/backends/pulseaudio.cpp index 4d3b34d9..be78ee17 100644 --- a/alc/backends/pulseaudio.cpp +++ b/alc/backends/pulseaudio.cpp @@ -663,7 +663,7 @@ struct PulsePlayback final : public BackendBase { static void streamMovedCallbackC(pa_stream *stream, void *pdata); void streamMovedCallback(pa_stream *stream); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool reset() override; bool start() override; void stop() override; @@ -818,7 +818,7 @@ void PulsePlayback::streamMovedCallback(pa_stream *stream) } -ALCenum PulsePlayback::open(const ALCchar *name) +void PulsePlayback::open(const ALCchar *name) { const char *pulse_name{nullptr}; const char *dev_name{nullptr}; @@ -873,8 +873,6 @@ ALCenum PulsePlayback::open(const ALCchar *name) } else mDevice->DeviceName = dev_name; - - return ALC_NO_ERROR; } bool PulsePlayback::reset() @@ -1107,7 +1105,7 @@ struct PulseCapture final : public BackendBase { static void streamMovedCallbackC(pa_stream *stream, void *pdata); void streamMovedCallback(pa_stream *stream); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool start() override; void stop() override; ALCenum captureSamples(al::byte *buffer, ALCuint samples) override; @@ -1192,7 +1190,7 @@ void PulseCapture::streamMovedCallback(pa_stream *stream) } -ALCenum PulseCapture::open(const ALCchar *name) +void PulseCapture::open(const ALCchar *name) { const char *pulse_name{nullptr}; if(name) @@ -1218,53 +1216,53 @@ ALCenum PulseCapture::open(const ALCchar *name) pa_channel_map chanmap{}; switch(mDevice->FmtChans) { - case DevFmtMono: - chanmap = MonoChanMap; - break; - case DevFmtStereo: - chanmap = StereoChanMap; - break; - case DevFmtQuad: - chanmap = QuadChanMap; - break; - case DevFmtX51: - chanmap = X51ChanMap; - break; - case DevFmtX51Rear: - chanmap = X51RearChanMap; - break; - case DevFmtX61: - chanmap = X61ChanMap; - break; - case DevFmtX71: - chanmap = X71ChanMap; - break; - case DevFmtAmbi3D: - throw al::backend_exception{ALC_INVALID_VALUE, "%s capture samples not supported", - DevFmtChannelsString(mDevice->FmtChans)}; + case DevFmtMono: + chanmap = MonoChanMap; + break; + case DevFmtStereo: + chanmap = StereoChanMap; + break; + case DevFmtQuad: + chanmap = QuadChanMap; + break; + case DevFmtX51: + chanmap = X51ChanMap; + break; + case DevFmtX51Rear: + chanmap = X51RearChanMap; + break; + case DevFmtX61: + chanmap = X61ChanMap; + break; + case DevFmtX71: + chanmap = X71ChanMap; + break; + case DevFmtAmbi3D: + throw al::backend_exception{ALC_INVALID_VALUE, "%s capture samples not supported", + DevFmtChannelsString(mDevice->FmtChans)}; } SetChannelOrderFromMap(mDevice, chanmap); switch(mDevice->FmtType) { - case DevFmtUByte: - mSilentVal = al::byte(0x80); - mSpec.format = PA_SAMPLE_U8; - break; - case DevFmtShort: - mSpec.format = PA_SAMPLE_S16NE; - break; - case DevFmtInt: - mSpec.format = PA_SAMPLE_S32NE; - break; - case DevFmtFloat: - mSpec.format = PA_SAMPLE_FLOAT32NE; - break; - case DevFmtByte: - case DevFmtUShort: - case DevFmtUInt: - throw al::backend_exception{ALC_INVALID_VALUE, "%s capture samples not supported", - DevFmtTypeString(mDevice->FmtType)}; + case DevFmtUByte: + mSilentVal = al::byte(0x80); + mSpec.format = PA_SAMPLE_U8; + break; + case DevFmtShort: + mSpec.format = PA_SAMPLE_S16NE; + break; + case DevFmtInt: + mSpec.format = PA_SAMPLE_S32NE; + break; + case DevFmtFloat: + mSpec.format = PA_SAMPLE_FLOAT32NE; + break; + case DevFmtByte: + case DevFmtUShort: + case DevFmtUInt: + throw al::backend_exception{ALC_INVALID_VALUE, "%s capture samples not supported", + DevFmtTypeString(mDevice->FmtType)}; } mSpec.rate = mDevice->Frequency; mSpec.channels = static_cast<uint8_t>(mDevice->channelsFromFmt()); @@ -1297,8 +1295,6 @@ ALCenum PulseCapture::open(const ALCchar *name) &PulseCapture::sourceNameCallbackC, this)}; wait_for_operation(op, plock); } - - return ALC_NO_ERROR; } bool PulseCapture::start() diff --git a/alc/backends/qsa.cpp b/alc/backends/qsa.cpp index 5fee2989..872a8541 100644 --- a/alc/backends/qsa.cpp +++ b/alc/backends/qsa.cpp @@ -34,6 +34,7 @@ #include <algorithm> #include "alcmain.h" +#include "alexcpt.h" #include "alu.h" #include "threads.h" @@ -174,7 +175,7 @@ struct PlaybackWrapper final : public BackendBase { PlaybackWrapper(ALCdevice *device) noexcept : BackendBase{device} { } ~PlaybackWrapper() override; - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool reset() override; bool start() override; void stop() override; @@ -613,11 +614,18 @@ PlaybackWrapper::~PlaybackWrapper() qsa_close_playback(this); } -ALCenum PlaybackWrapper::open(const ALCchar *name) -{ return qsa_open_playback(this, name); } +void PlaybackWrapper::open(const ALCchar *name) +{ + if(auto err = qsa_open_playback(this, name)) + throw al::backend_exception{ALC_INVALID_VALUE, "%d", err}; +} bool PlaybackWrapper::reset() -{ return qsa_reset_playback(this); } +{ + if(!qsa_reset_playback(this)) + throw al::backend_exception{ALC_INVALID_VALUE, ""}; + return true; +} bool PlaybackWrapper::start() { return qsa_start_playback(this); } @@ -634,7 +642,7 @@ struct CaptureWrapper final : public BackendBase { CaptureWrapper(ALCdevice *device) noexcept : BackendBase{device} { } ~CaptureWrapper() override; - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool start() override; void stop() override; ALCenum captureSamples(al::byte *buffer, ALCuint samples) override; @@ -891,8 +899,11 @@ CaptureWrapper::~CaptureWrapper() qsa_close_capture(this); } -ALCenum CaptureWrapper::open(const ALCchar *name) -{ return qsa_open_capture(this, name); } +void CaptureWrapper::open(const ALCchar *name) +{ + if(auto err = qsa_open_capture(this, name)) + throw al::backend_exception{ALC_INVALID_VALUE, "%d", err}; +} bool CaptureWrapper::start() { qsa_start_capture(this); return true; } diff --git a/alc/backends/sdl2.cpp b/alc/backends/sdl2.cpp index 71616906..1063ca7a 100644 --- a/alc/backends/sdl2.cpp +++ b/alc/backends/sdl2.cpp @@ -30,6 +30,7 @@ #include "AL/al.h" #include "alcmain.h" +#include "alexcpt.h" #include "almalloc.h" #include "alu.h" #include "logging.h" @@ -54,7 +55,7 @@ struct Sdl2Backend final : public BackendBase { static void audioCallbackC(void *ptr, Uint8 *stream, int len); void audioCallback(Uint8 *stream, int len); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool reset() override; bool start() override; void stop() override; @@ -89,20 +90,20 @@ void Sdl2Backend::audioCallback(Uint8 *stream, int len) aluMixData(mDevice, stream, ulen / mFrameSize); } -ALCenum Sdl2Backend::open(const ALCchar *name) +void Sdl2Backend::open(const ALCchar *name) { SDL_AudioSpec want{}, have{}; want.freq = static_cast<int>(mDevice->Frequency); switch(mDevice->FmtType) { - case DevFmtUByte: want.format = AUDIO_U8; break; - case DevFmtByte: want.format = AUDIO_S8; break; - case DevFmtUShort: want.format = AUDIO_U16SYS; break; - case DevFmtShort: want.format = AUDIO_S16SYS; break; - case DevFmtUInt: /* fall-through */ - case DevFmtInt: want.format = AUDIO_S32SYS; break; - case DevFmtFloat: want.format = AUDIO_F32; break; + case DevFmtUByte: want.format = AUDIO_U8; break; + case DevFmtByte: want.format = AUDIO_S8; break; + case DevFmtUShort: want.format = AUDIO_U16SYS; break; + case DevFmtShort: want.format = AUDIO_S16SYS; break; + case DevFmtUInt: /* fall-through */ + case DevFmtInt: want.format = AUDIO_S32SYS; break; + case DevFmtFloat: want.format = AUDIO_F32; break; } want.channels = (mDevice->FmtChans == DevFmtMono) ? 1 : 2; want.samples = static_cast<Uint16>(mDevice->UpdateSize); @@ -114,19 +115,19 @@ ALCenum Sdl2Backend::open(const ALCchar *name) */ if(!name || strcmp(name, defaultDeviceName) == 0) mDeviceID = SDL_OpenAudioDevice(nullptr, SDL_FALSE, &want, &have, - SDL_AUDIO_ALLOW_ANY_CHANGE); + SDL_AUDIO_ALLOW_ANY_CHANGE); else { const size_t prefix_len = strlen(DEVNAME_PREFIX); if(strncmp(name, DEVNAME_PREFIX, prefix_len) == 0) mDeviceID = SDL_OpenAudioDevice(name+prefix_len, SDL_FALSE, &want, &have, - SDL_AUDIO_ALLOW_ANY_CHANGE); + SDL_AUDIO_ALLOW_ANY_CHANGE); else mDeviceID = SDL_OpenAudioDevice(name, SDL_FALSE, &want, &have, - SDL_AUDIO_ALLOW_ANY_CHANGE); + SDL_AUDIO_ALLOW_ANY_CHANGE); } if(mDeviceID == 0) - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "%s", SDL_GetError()}; mDevice->Frequency = static_cast<ALuint>(have.freq); if(have.channels == 1) @@ -136,19 +137,21 @@ ALCenum Sdl2Backend::open(const ALCchar *name) else { ERR("Got unhandled SDL channel count: %d\n", int{have.channels}); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Unhandled SDL channel count: %d", + int{have.channels}}; } switch(have.format) { - case AUDIO_U8: mDevice->FmtType = DevFmtUByte; break; - case AUDIO_S8: mDevice->FmtType = DevFmtByte; break; - case AUDIO_U16SYS: mDevice->FmtType = DevFmtUShort; break; - case AUDIO_S16SYS: mDevice->FmtType = DevFmtShort; break; - case AUDIO_S32SYS: mDevice->FmtType = DevFmtInt; break; - case AUDIO_F32SYS: mDevice->FmtType = DevFmtFloat; break; - default: - ERR("Got unsupported SDL format: 0x%04x\n", have.format); - return ALC_INVALID_VALUE; + case AUDIO_U8: mDevice->FmtType = DevFmtUByte; break; + case AUDIO_S8: mDevice->FmtType = DevFmtByte; break; + case AUDIO_U16SYS: mDevice->FmtType = DevFmtUShort; break; + case AUDIO_S16SYS: mDevice->FmtType = DevFmtShort; break; + case AUDIO_S32SYS: mDevice->FmtType = DevFmtInt; break; + case AUDIO_F32SYS: mDevice->FmtType = DevFmtFloat; break; + default: + ERR("Got unsupported SDL format: 0x%04x\n", have.format); + throw al::backend_exception{ALC_INVALID_VALUE, "Unhandled SDL format: 0x%04x", + have.format}; } mDevice->UpdateSize = have.samples; mDevice->BufferSize = have.samples * 2; /* SDL always (tries to) use two periods. */ @@ -160,7 +163,6 @@ ALCenum Sdl2Backend::open(const ALCchar *name) mUpdateSize = mDevice->UpdateSize; mDevice->DeviceName = name ? name : defaultDeviceName; - return ALC_NO_ERROR; } bool Sdl2Backend::reset() diff --git a/alc/backends/sndio.cpp b/alc/backends/sndio.cpp index d2654853..e0c70762 100644 --- a/alc/backends/sndio.cpp +++ b/alc/backends/sndio.cpp @@ -30,6 +30,7 @@ #include <functional> #include "alcmain.h" +#include "alexcpt.h" #include "alu.h" #include "threads.h" #include "vector.h" @@ -49,7 +50,7 @@ struct SndioPlayback final : public BackendBase { int mixerProc(); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool reset() override; bool start() override; void stop() override; @@ -106,22 +107,21 @@ int SndioPlayback::mixerProc() } -ALCenum SndioPlayback::open(const ALCchar *name) +void SndioPlayback::open(const ALCchar *name) { if(!name) name = sndio_device; else if(strcmp(name, sndio_device) != 0) - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name}; mSndHandle = sio_open(nullptr, SIO_PLAY, 0); if(mSndHandle == nullptr) { ERR("Could not open device\n"); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Could not open sound device"}; } mDevice->DeviceName = name; - return ALC_NO_ERROR; } bool SndioPlayback::reset() @@ -249,7 +249,7 @@ struct SndioCapture final : public BackendBase { int recordProc(); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool start() override; void stop() override; ALCenum captureSamples(al::byte *buffer, ALCuint samples) override; @@ -319,18 +319,18 @@ int SndioCapture::recordProc() } -ALCenum SndioCapture::open(const ALCchar *name) +void SndioCapture::open(const ALCchar *name) { if(!name) name = sndio_device; else if(strcmp(name, sndio_device) != 0) - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name}; mSndHandle = sio_open(nullptr, SIO_REC, 0); if(mSndHandle == nullptr) { ERR("Could not open device\n"); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Could not open sound device"}; } sio_par par; @@ -338,33 +338,34 @@ ALCenum SndioCapture::open(const ALCchar *name) switch(mDevice->FmtType) { - case DevFmtByte: - par.bps = 1; - par.sig = 1; - break; - case DevFmtUByte: - par.bps = 1; - par.sig = 0; - break; - case DevFmtShort: - par.bps = 2; - par.sig = 1; - break; - case DevFmtUShort: - par.bps = 2; - par.sig = 0; - break; - case DevFmtInt: - par.bps = 4; - par.sig = 1; - break; - case DevFmtUInt: - par.bps = 4; - par.sig = 0; - break; - case DevFmtFloat: - ERR("%s capture samples not supported\n", DevFmtTypeString(mDevice->FmtType)); - return ALC_INVALID_VALUE; + case DevFmtByte: + par.bps = 1; + par.sig = 1; + break; + case DevFmtUByte: + par.bps = 1; + par.sig = 0; + break; + case DevFmtShort: + par.bps = 2; + par.sig = 1; + break; + case DevFmtUShort: + par.bps = 2; + par.sig = 0; + break; + case DevFmtInt: + par.bps = 4; + par.sig = 1; + break; + case DevFmtUInt: + par.bps = 4; + par.sig = 0; + break; + case DevFmtFloat: + ERR("%s capture samples not supported\n", DevFmtTypeString(mDevice->FmtType)); + throw al::backend_exception{ALC_INVALID_VALUE, "%s capture samples not supported", + DevFmtTypeString(mDevice->FmtType)}; } par.bits = par.bps * 8; par.le = SIO_LE_NATIVE; @@ -381,13 +382,14 @@ ALCenum SndioCapture::open(const ALCchar *name) if(!sio_setpar(mSndHandle, &par) || !sio_getpar(mSndHandle, &par)) { ERR("Failed to set device parameters\n"); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Failed to set device praameters"}; } if(par.bits != par.bps*8) { ERR("Padded samples not supported (%u of %u bits)\n", par.bits, par.bps*8); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, + "Padded samples not supported (got %u of %u bits)", par.bits, par.bps*8}; } if(!((mDevice->FmtType == DevFmtByte && par.bits == 8 && par.sig != 0) || @@ -401,20 +403,21 @@ ALCenum SndioCapture::open(const ALCchar *name) ERR("Failed to set format %s %s %uhz, got %c%u %u-channel %uhz instead\n", DevFmtTypeString(mDevice->FmtType), DevFmtChannelsString(mDevice->FmtChans), mDevice->Frequency, par.sig?'s':'u', par.bits, par.rchan, par.rate); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Could not set format %s %s %uhz", + DevFmtTypeString(mDevice->FmtType), DevFmtChannelsString(mDevice->FmtChans), + mDevice->Frequency}; } mRing = CreateRingBuffer(mDevice->BufferSize, par.bps*par.rchan, false); if(!mRing) { ERR("Failed to allocate %u-byte ringbuffer\n", mDevice->BufferSize*par.bps*par.rchan); - return ALC_OUT_OF_MEMORY; + throw al::backend_exception{ALC_OUT_OF_MEMORY, "Failed to allocate ring buffer"}; } SetDefaultChannelOrder(mDevice); mDevice->DeviceName = name; - return ALC_NO_ERROR; } bool SndioCapture::start() diff --git a/alc/backends/solaris.cpp b/alc/backends/solaris.cpp index 128924bb..5963a4b2 100644 --- a/alc/backends/solaris.cpp +++ b/alc/backends/solaris.cpp @@ -39,6 +39,7 @@ #include <functional> #include "alcmain.h" +#include "alexcpt.h" #include "alu.h" #include "alconfig.h" #include "threads.h" @@ -61,7 +62,7 @@ struct SolarisBackend final : public BackendBase { int mixerProc(); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool reset() override; bool start() override; void stop() override; @@ -142,22 +143,22 @@ int SolarisBackend::mixerProc() } -ALCenum SolarisBackend::open(const ALCchar *name) +void SolarisBackend::open(const ALCchar *name) { if(!name) name = solaris_device; else if(strcmp(name, solaris_device) != 0) - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name}; mFd = ::open(solaris_driver.c_str(), O_WRONLY); if(mFd == -1) { ERR("Could not open %s: %s\n", solaris_driver.c_str(), strerror(errno)); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Could not open %s: %s", + solaris_driver.c_str(), strerror(errno)}; } mDevice->DeviceName = name; - return ALC_NO_ERROR; } bool SolarisBackend::reset() diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index 2a610c8d..b6f5b5fb 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -55,6 +55,7 @@ #include <condition_variable> #include "alcmain.h" +#include "alexcpt.h" #include "alu.h" #include "ringbuffer.h" #include "compat.h" @@ -610,7 +611,7 @@ struct WasapiPlayback final : public BackendBase, WasapiProxy { int mixerProc(); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; HRESULT openProxy() override; void closeProxy() override; @@ -708,7 +709,7 @@ FORCE_ALIGN int WasapiPlayback::mixerProc() } -ALCenum WasapiPlayback::open(const ALCchar *name) +void WasapiPlayback::open(const ALCchar *name) { HRESULT hr{S_OK}; @@ -762,10 +763,8 @@ ALCenum WasapiPlayback::open(const ALCchar *name) mDevId.clear(); ERR("Device init failed: 0x%08lx\n", hr); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Device init failed: 0x%08lx", hr}; } - - return ALC_NO_ERROR; } HRESULT WasapiPlayback::openProxy() @@ -815,7 +814,9 @@ void WasapiPlayback::closeProxy() bool WasapiPlayback::reset() { HRESULT hr{pushMessage(MsgType::ResetDevice).get()}; - return SUCCEEDED(hr) ? true : false; + if(FAILED(hr)) + throw al::backend_exception{ALC_INVALID_VALUE, "0x%08lx", hr}; + return true; } HRESULT WasapiPlayback::resetProxy() @@ -1151,7 +1152,7 @@ struct WasapiCapture final : public BackendBase, WasapiProxy { int recordProc(); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; HRESULT openProxy() override; void closeProxy() override; @@ -1283,7 +1284,7 @@ FORCE_ALIGN int WasapiCapture::recordProc() } -ALCenum WasapiCapture::open(const ALCchar *name) +void WasapiCapture::open(const ALCchar *name) { HRESULT hr{S_OK}; @@ -1337,18 +1338,16 @@ ALCenum WasapiCapture::open(const ALCchar *name) mDevId.clear(); ERR("Device init failed: 0x%08lx\n", hr); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Device init failed: 0x%08lx", hr}; } hr = pushMessage(MsgType::ResetDevice).get(); if(FAILED(hr)) { if(hr == E_OUTOFMEMORY) - return ALC_OUT_OF_MEMORY; - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_OUT_OF_MEMORY, "Out of memory"}; + throw al::backend_exception{ALC_INVALID_VALUE, "Device reset failed"}; } - - return ALC_NO_ERROR; } HRESULT WasapiCapture::openProxy() diff --git a/alc/backends/wave.cpp b/alc/backends/wave.cpp index 797a9fa5..927cb276 100644 --- a/alc/backends/wave.cpp +++ b/alc/backends/wave.cpp @@ -38,6 +38,7 @@ #include "albyte.h" #include "alcmain.h" #include "alconfig.h" +#include "alexcpt.h" #include "almalloc.h" #include "alnumeric.h" #include "alu.h" @@ -96,7 +97,7 @@ struct WaveBackend final : public BackendBase { int mixerProc(); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool reset() override; bool start() override; void stop() override; @@ -202,15 +203,15 @@ int WaveBackend::mixerProc() return 0; } -ALCenum WaveBackend::open(const ALCchar *name) +void WaveBackend::open(const ALCchar *name) { const char *fname{GetConfigValue(nullptr, "wave", "file", "")}; - if(!fname[0]) return ALC_INVALID_VALUE; + if(!fname[0]) throw al::backend_exception{ALC_INVALID_VALUE, "No wave output filename"}; if(!name) name = waveDevice; else if(strcmp(name, waveDevice) != 0) - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name}; #ifdef _WIN32 { @@ -223,12 +224,11 @@ ALCenum WaveBackend::open(const ALCchar *name) if(!mFile) { ERR("Could not open file '%s': %s\n", fname, strerror(errno)); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "Could not open file '%s': %s", fname, + strerror(errno)}; } mDevice->DeviceName = name; - - return ALC_NO_ERROR; } bool WaveBackend::reset() diff --git a/alc/backends/winmm.cpp b/alc/backends/winmm.cpp index d58fa959..c287e136 100644 --- a/alc/backends/winmm.cpp +++ b/alc/backends/winmm.cpp @@ -38,6 +38,7 @@ #include <functional> #include "alcmain.h" +#include "alexcpt.h" #include "alu.h" #include "ringbuffer.h" #include "strutils.h" @@ -131,7 +132,7 @@ struct WinMMPlayback final : public BackendBase { int mixerProc(); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool reset() override; bool start() override; void stop() override; @@ -212,7 +213,7 @@ FORCE_ALIGN int WinMMPlayback::mixerProc() } -ALCenum WinMMPlayback::open(const ALCchar *name) +void WinMMPlayback::open(const ALCchar *name) { if(PlaybackDevices.empty()) ProbePlaybackDevices(); @@ -221,7 +222,8 @@ ALCenum WinMMPlayback::open(const ALCchar *name) auto iter = name ? std::find(PlaybackDevices.cbegin(), PlaybackDevices.cend(), name) : PlaybackDevices.cbegin(); - if(iter == PlaybackDevices.cend()) return ALC_INVALID_VALUE; + if(iter == PlaybackDevices.cend()) + throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name}; auto DeviceID = static_cast<UINT>(std::distance(PlaybackDevices.cbegin(), iter)); retry_open: @@ -256,11 +258,10 @@ retry_open: goto retry_open; } ERR("waveOutOpen failed: %u\n", res); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "waveOutOpen failed: %u", res}; } mDevice->DeviceName = PlaybackDevices[DeviceID]; - return ALC_NO_ERROR; } bool WinMMPlayback::reset() @@ -373,7 +374,7 @@ struct WinMMCapture final : public BackendBase { int captureProc(); - ALCenum open(const ALCchar *name) override; + void open(const ALCchar *name) override; bool start() override; void stop() override; ALCenum captureSamples(al::byte *buffer, ALCuint samples) override; @@ -456,7 +457,7 @@ int WinMMCapture::captureProc() } -ALCenum WinMMCapture::open(const ALCchar *name) +void WinMMCapture::open(const ALCchar *name) { if(CaptureDevices.empty()) ProbeCaptureDevices(); @@ -465,36 +466,39 @@ ALCenum WinMMCapture::open(const ALCchar *name) auto iter = name ? std::find(CaptureDevices.cbegin(), CaptureDevices.cend(), name) : CaptureDevices.cbegin(); - if(iter == CaptureDevices.cend()) return ALC_INVALID_VALUE; + if(iter == CaptureDevices.cend()) + throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name}; auto DeviceID = static_cast<UINT>(std::distance(CaptureDevices.cbegin(), iter)); switch(mDevice->FmtChans) { - case DevFmtMono: - case DevFmtStereo: - break; - - case DevFmtQuad: - case DevFmtX51: - case DevFmtX51Rear: - case DevFmtX61: - case DevFmtX71: - case DevFmtAmbi3D: - return ALC_INVALID_ENUM; + case DevFmtMono: + case DevFmtStereo: + break; + + case DevFmtQuad: + case DevFmtX51: + case DevFmtX51Rear: + case DevFmtX61: + case DevFmtX71: + case DevFmtAmbi3D: + throw al::backend_exception{ALC_INVALID_VALUE, "%s capture not supported", + DevFmtChannelsString(mDevice->FmtChans)}; } switch(mDevice->FmtType) { - case DevFmtUByte: - case DevFmtShort: - case DevFmtInt: - case DevFmtFloat: - break; - - case DevFmtByte: - case DevFmtUShort: - case DevFmtUInt: - return ALC_INVALID_ENUM; + case DevFmtUByte: + case DevFmtShort: + case DevFmtInt: + case DevFmtFloat: + break; + + case DevFmtByte: + case DevFmtUShort: + case DevFmtUInt: + throw al::backend_exception{ALC_INVALID_VALUE, "%s samples not supported", + DevFmtTypeString(mDevice->FmtType)}; } mFormat = WAVEFORMATEX{}; @@ -513,7 +517,7 @@ ALCenum WinMMCapture::open(const ALCchar *name) if(res != MMSYSERR_NOERROR) { ERR("waveInOpen failed: %u\n", res); - return ALC_INVALID_VALUE; + throw al::backend_exception{ALC_INVALID_VALUE, "waveInOpen failed: %u", res}; } // Ensure each buffer is 50ms each @@ -526,7 +530,7 @@ ALCenum WinMMCapture::open(const ALCchar *name) CapturedDataSize = static_cast<ALuint>(maxz(CapturedDataSize, BufferSize*mWaveBuffer.size())); mRing = CreateRingBuffer(CapturedDataSize, mFormat.nBlockAlign, false); - if(!mRing) return ALC_INVALID_VALUE; + if(!mRing) throw al::backend_exception{ALC_INVALID_VALUE, "Could not create ring buffer"}; al_free(mWaveBuffer[0].lpData); mWaveBuffer[0] = WAVEHDR{}; @@ -540,7 +544,6 @@ ALCenum WinMMCapture::open(const ALCchar *name) } mDevice->DeviceName = CaptureDevices[DeviceID]; - return ALC_NO_ERROR; } bool WinMMCapture::start() |