Use exceptions for backend open failures
This commit is contained in:
+10
-22
@@ -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());
|
||||
|
||||
+14
-21
@@ -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)};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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; }
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
+82
-83
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+51
-71
@@ -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()
|
||||
|
||||
+10
-13
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
+60
-60
@@ -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()
|
||||
|
||||
+33
-37
@@ -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()
|
||||
|
||||
+61
-68
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+46
-50
@@ -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()
|
||||
|
||||
+18
-7
@@ -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; }
|
||||
|
||||
+26
-24
@@ -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()
|
||||
|
||||
+44
-41
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
+12
-13
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
+33
-30
@@ -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 DevFmtMono:
|
||||
case DevFmtStereo:
|
||||
break;
|
||||
|
||||
case DevFmtQuad:
|
||||
case DevFmtX51:
|
||||
case DevFmtX51Rear:
|
||||
case DevFmtX61:
|
||||
case DevFmtX71:
|
||||
case DevFmtAmbi3D:
|
||||
return ALC_INVALID_ENUM;
|
||||
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 DevFmtUByte:
|
||||
case DevFmtShort:
|
||||
case DevFmtInt:
|
||||
case DevFmtFloat:
|
||||
break;
|
||||
|
||||
case DevFmtByte:
|
||||
case DevFmtUShort:
|
||||
case DevFmtUInt:
|
||||
return ALC_INVALID_ENUM;
|
||||
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()
|
||||
|
||||
Reference in New Issue
Block a user