winamp/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOModern.hpp

961 lines
28 KiB
C++

#ifndef ASIO_ASIOMODERN_HPP
#define ASIO_ASIOMODERN_HPP
#include "ASIOVersion.hpp"
#include "ASIOConfig.hpp"
#include "ASIOCore.hpp"
#include <array>
#include <exception>
#include <mutex>
#include <stdexcept>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include <cassert>
#include <cstddef>
#include <cstdint>
namespace ASIO {
inline namespace Modern {
inline namespace ASIO_VERSION_NAMESPACE {
class Error
: public std::runtime_error {
private:
ErrorCode m_Code;
private:
static constexpr std::string_view Message(ErrorCode ec) noexcept {
std::string_view message = "";
switch (ec) {
case ErrorCode::OK:
message = "OK";
break;
case ErrorCode::SUCCESS:
message = "SUCCESS";
break;
case ErrorCode::NotPresent:
message = "NotPresent";
break;
case ErrorCode::HWMalfunction:
message = "HWMalfunction";
break;
case ErrorCode::InvalidParameter:
message = "InvalidParameter";
break;
case ErrorCode::InvalidMode:
message = "InvalidMode";
break;
case ErrorCode::SPNotAdvancing:
message = "SPNotAdvancing";
break;
case ErrorCode::NoClock:
message = "NoClock";
break;
case ErrorCode::NoMemory:
message = "NoMemory";
break;
default:
message = "";
break;
}
return message;
}
public:
Error(ErrorCode ec)
: std::runtime_error(std::string("ASIO Error ") + std::string(Message(ec)))
, m_Code(ec) {
return;
}
ErrorCode Code() const noexcept {
return m_Code;
}
};
struct CallbacksWithContext {
void (*bufferSwitch)(void * context, Long doubleBufferIndex, Bool directProcess) noexcept = nullptr;
void (*sampleRateDidChange)(void * context, SampleRate sRate) noexcept = nullptr;
Long (*asioMessage)(void * context, MessageSelector selector, const Long value, const void * message, const Double * opt) noexcept = nullptr;
const Time * (*bufferSwitchTimeInfo)(void * context, const Time * params, Long doubleBufferIndex, Bool directProcess) noexcept = nullptr;
};
struct CallbacksWrapperState {
CallbacksWithContext callbacks;
void * context = nullptr;
};
#if ASIO_SYSTEM_WINDOWS && (ASIO_COMPILER_GCC || ASIO_COMPILER_CLANG)
#pragma push_macro("cdecl")
#ifdef cdecl
#undef cdecl
#endif
#endif // ASIO_SYSTEM_WINDOWS && (ASIO_COMPILER_GCC || ASIO_COMPILER_CLANG)
template <typename Tarray, Tarray * A, std::size_t I>
class CallbacksWrapper {
public:
static constexpr Callbacks init() noexcept {
Callbacks result = {&CallbackBufferSwitch, &CallbackSampleRateDidChange, &CallbackAsioMessage, &CallbackBufferSwitchTimeInfo};
return result;
}
public:
static void ASIO_CALL CallbackBufferSwitch ASIO_ATTR_CALL(Long doubleBufferIndex, Bool directProcess) noexcept {
return (*A)[I].callbacks.bufferSwitch((*A)[I].context, doubleBufferIndex, directProcess);
}
static void ASIO_CALL CallbackSampleRateDidChange ASIO_ATTR_CALL(SampleRate sRate) noexcept {
return (*A)[I].callbacks.sampleRateDidChange((*A)[I].context, sRate);
}
static Long ASIO_CALL CallbackAsioMessage ASIO_ATTR_CALL(MessageSelector selector, Long value, const void * message, const Double * opt) noexcept {
return (*A)[I].callbacks.asioMessage((*A)[I].context, selector, value, message, opt);
}
static const Time * ASIO_CALL CallbackBufferSwitchTimeInfo ASIO_ATTR_CALL(const Time * params, Long doubleBufferIndex, Bool directProcess) noexcept {
return (*A)[I].callbacks.bufferSwitchTimeInfo((*A)[I].context, params, doubleBufferIndex, directProcess);
}
};
#if ASIO_SYSTEM_WINDOWS && (ASIO_COMPILER_GCC || ASIO_COMPILER_CLANG)
#pragma pop_macro("cdecl")
#endif // ASIO_SYSTEM_WINDOWS && (ASIO_COMPILER_GCC || ASIO_COMPILER_CLANG)
namespace detail {
template <typename T, std::size_t N, typename Tx>
constexpr std::array<T, N> init_array(const Tx & x) {
std::array<T, N> result{};
for (std::size_t i = 0; i < N; ++i) {
result[i] = x;
}
return result;
}
} // namespace detail
template <std::uint64_t AppID1, std::uint64_t AppID2, std::size_t MaxInstances>
class AsioCallbacksMultiplexerGlobalState {
private:
template <typename Tarray, Tarray * a, std::size_t... Is>
static constexpr auto construct_callbacks_array(std::index_sequence<Is...>) noexcept -> std::array<Callbacks, sizeof...(Is)> {
return {CallbacksWrapper<Tarray, a, Is>::init()...};
}
private:
static inline std::mutex s_AllocationMutex;
static inline std::array<bool, MaxInstances> s_Allocation = detail::init_array<bool, MaxInstances>(false);
static inline std::array<CallbacksWrapperState, MaxInstances> s_AsioCallbackWrapperStates = detail::init_array<CallbacksWrapperState, MaxInstances>(CallbacksWrapperState{
{nullptr, nullptr, nullptr, nullptr},
nullptr
});
static constexpr inline std::array<Callbacks, MaxInstances> s_AsioCallbacks = construct_callbacks_array<std::array<CallbacksWrapperState, MaxInstances>, &s_AsioCallbackWrapperStates>(std::make_index_sequence<MaxInstances>());
private:
static std::size_t Alloc() {
std::lock_guard<std::mutex> guard(s_AllocationMutex);
for (std::size_t i = 0; i < MaxInstances; ++i) {
if (!s_Allocation[i]) {
s_Allocation[i] = true;
return i;
}
}
throw Error(ErrorCode::NoMemory);
}
static void Free(std::size_t index) noexcept {
std::lock_guard<std::mutex> guard(s_AllocationMutex);
assert(s_Allocation[index]);
s_Allocation[index] = false;
}
public:
static std::pair<std::size_t, Callbacks> Multiplex(void * context, CallbacksWithContext callbacks) {
std::size_t cookie = Alloc();
s_AsioCallbackWrapperStates[cookie] = {callbacks, context};
return std::make_pair(cookie, s_AsioCallbacks[cookie]);
}
static void Unmultiplex(std::pair<std::size_t, Callbacks> state) noexcept {
Free(state.first);
}
};
class IMultiplexedCallbacks {
protected:
IMultiplexedCallbacks() = default;
public:
IMultiplexedCallbacks(const IMultiplexedCallbacks &) = delete;
IMultiplexedCallbacks & operator=(const IMultiplexedCallbacks &) = delete;
public:
virtual ~IMultiplexedCallbacks() = default;
public:
virtual operator const Callbacks *() const noexcept = 0;
virtual operator const Callbacks &() const noexcept = 0;
virtual operator Callbacks *() noexcept = 0;
virtual operator Callbacks &() noexcept = 0;
};
template <std::uint64_t AppID1, std::uint64_t AppID2, std::size_t MaxInstances>
class MultiplexedCallbacks
: public IMultiplexedCallbacks {
public:
using GlobalState = AsioCallbacksMultiplexerGlobalState<AppID1, AppID2, MaxInstances>;
using State = std::unique_ptr<IMultiplexedCallbacks>;
private:
std::pair<std::size_t, Callbacks> m_State;
public:
MultiplexedCallbacks(void * context, CallbacksWithContext callbacks)
: m_State(GlobalState::Multiplex(context, callbacks)) {
if (!callbacks.bufferSwitch) {
m_State.second.bufferSwitch = nullptr;
}
if (!callbacks.sampleRateDidChange) {
m_State.second.sampleRateDidChange = nullptr;
}
if (!callbacks.asioMessage) {
m_State.second.asioMessage = nullptr;
}
if (!callbacks.bufferSwitchTimeInfo) {
m_State.second.bufferSwitchTimeInfo = nullptr;
}
}
MultiplexedCallbacks(const MultiplexedCallbacks &) = delete;
MultiplexedCallbacks & operator=(const MultiplexedCallbacks &) = delete;
~MultiplexedCallbacks() final {
GlobalState::Unmultiplex(m_State);
}
public:
operator const Callbacks *() const noexcept final {
return &m_State.second;
}
operator const Callbacks &() const noexcept final {
return m_State.second;
}
operator Callbacks *() noexcept final {
return &m_State.second;
}
operator Callbacks &() noexcept final {
return m_State.second;
}
public:
static std::unique_ptr<MultiplexedCallbacks> make(void * context, CallbacksWithContext callbacks) {
return std::make_unique<MultiplexedCallbacks>(context, callbacks);
}
static std::unique_ptr<MultiplexedCallbacks> null() {
return std::unique_ptr<MultiplexedCallbacks>();
}
};
struct Channels {
Long Input = 0;
Long Output = 0;
};
struct Latencies {
Long Input = 0;
Long Output = 0;
};
struct BufferSizes {
Long Min = 0;
Long Max = 0;
Long Preferred = 0;
Long Granularity = 0;
};
struct SamplePosition {
Samples samplePosition = 0;
TimeStamp systemTime = 0;
};
struct BufferIndex {
std::uint8_t Index : 1;
constexpr BufferIndex() noexcept
: Index(0) {
}
constexpr BufferIndex(Long doubleBufferIndex) noexcept
: Index(static_cast<std::uint8_t>(static_cast<ULong>(doubleBufferIndex) & 1u)) {
}
constexpr BufferIndex(std::size_t bufferIndex) noexcept
: Index(static_cast<std::uint8_t>(bufferIndex & 1u)) {
}
constexpr operator std::size_t() const noexcept {
return Index;
}
};
class Driver {
public:
class ICallbackHandler {
protected:
ICallbackHandler() = default;
public:
ICallbackHandler(const ICallbackHandler &) = delete;
ICallbackHandler & operator=(const ICallbackHandler &) = delete;
virtual ~ICallbackHandler() = default;
public:
virtual Long CallbackMessage(Driver & driver, MessageSelector selector, Long value, const void * message, const Double * opt) noexcept = 0;
virtual void CallbackSampleRateDidChange(Driver & driver, SampleRate sRate) noexcept = 0;
virtual void CallbackBufferSwitch(Driver & driver, Long doubleBufferIndex, Bool directProcess) noexcept = 0;
virtual const Time * CallbackBufferSwitchTimeInfo(Driver & driver, const Time * params, Long doubleBufferIndex, Bool directProcess) noexcept = 0;
};
class CallbackHandler
: public ICallbackHandler {
/*
void MessageResetRequest() noexcept override;
bool MessageBufferSizeChange(ASIO::Long newSize) noexcept override;
bool MessageResyncRequest() noexcept override;
void MessageLatenciesChanged() noexcept override;
ASIO::Long MessageMMCCommand(ASIO::Long value, const void * message, const ASIO::Double * opt) noexcept override;
void MessageOverload() noexcept override;
ASIO::Long MessageUnknown(ASIO::MessageSelector selector, ASIO::Long value, const void * message, const ASIO::Double * opt) noexcept override;
void RealtimeSampleRateDidChange(ASIO::SampleRate sRate) noexcept override;
void RealtimeRequestDeferredProcessing(bool value) noexcept override;
void RealtimeTimeInfo(ASIO::Time time) noexcept override;
void RealtimeBufferSwitch(ASIO::BufferIndex bufferIndex) noexcept override;
*/
public:
CallbackHandler() = default;
CallbackHandler(const CallbackHandler &) = delete;
CallbackHandler & operator=(const CallbackHandler &) = delete;
virtual ~CallbackHandler() = default;
public:
bool MessageSelectorSupported(MessageSelector selector) const noexcept {
bool result = false;
switch (selector) {
case MessageSelector::SelectorSupported:
result = true;
break;
case MessageSelector::EngineVersion:
result = true;
break;
case MessageSelector::ResetRequest:
result = true;
break;
case MessageSelector::BufferSizeChange:
result = true;
break;
case MessageSelector::ResyncRequest:
result = true;
break;
case MessageSelector::LatenciesChanged:
result = true;
break;
case MessageSelector::SupportsTimeInfo:
result = true;
break;
case MessageSelector::SupportsTimeCode:
result = true;
break;
case MessageSelector::MMCCommand:
result = true;
break;
case MessageSelector::SupportsInputMonitor:
result = true;
break;
case MessageSelector::SupportsInputGain:
result = true;
break;
case MessageSelector::SupportsInputMeter:
result = true;
break;
case MessageSelector::SupportsOutputGain:
result = true;
break;
case MessageSelector::SupportsOutputMeter:
result = true;
break;
case MessageSelector::Overload:
result = true;
break;
}
return result;
}
Long MessageEngineVersion() const noexcept {
return 2;
}
virtual void MessageResetRequest() noexcept = 0;
virtual bool MessageBufferSizeChange(Long newSize) noexcept {
static_cast<void>(newSize);
return false;
}
virtual bool MessageResyncRequest() noexcept {
return false;
}
virtual void MessageLatenciesChanged() noexcept {
return;
}
bool MessageSupportsTimeInfo() const noexcept {
return true;
}
bool MessageSupportsTimeCode() const noexcept {
return true;
}
virtual Long MessageMMCCommand(Long value, const void * message, const Double * opt) noexcept {
static_cast<void>(value);
static_cast<void>(message);
static_cast<void>(opt);
return 0;
}
bool MessageSupportsInputMonitor() const noexcept {
return true;
}
bool MessageSupportsInputGain() const noexcept {
return true;
}
bool MessageSupportsInputMeter() const noexcept {
return true;
}
bool MessageSupportsOutputGain() const noexcept {
return true;
}
bool MessageSupportsOutputMeter() const noexcept {
return true;
}
virtual void MessageOverload() noexcept {
return;
}
virtual Long MessageUnknown(MessageSelector selector, Long value, const void * message, const Double * opt) noexcept {
static_cast<void>(selector);
static_cast<void>(value);
static_cast<void>(message);
static_cast<void>(opt);
return 0;
}
virtual void RealtimeSampleRateDidChange(SampleRate sRate) noexcept {
static_cast<void>(sRate);
}
virtual void RealtimeRequestDeferredProcessing(bool deferred) noexcept {
static_cast<void>(deferred);
}
virtual void RealtimeTimeInfo(Time time) noexcept {
static_cast<void>(time);
}
virtual void RealtimeBufferSwitch(ASIO::BufferIndex bufferIndex) noexcept = 0;
public:
Long CallbackMessage(Driver & driver, MessageSelector selector, Long value, const void * message, const Double * opt) noexcept final {
static_cast<void>(driver);
Long result = 0;
switch (selector) {
case MessageSelector::SelectorSupported:
result = MessageSelectorSupported(static_cast<MessageSelector>(value)) ? 1 : 0;
break;
case MessageSelector::EngineVersion:
result = MessageEngineVersion();
break;
case MessageSelector::ResetRequest:
MessageResetRequest();
result = 1;
break;
case MessageSelector::BufferSizeChange:
result = MessageBufferSizeChange(value) ? 1 : 0;
break;
case MessageSelector::ResyncRequest:
result = MessageResyncRequest() ? 1 : 0;
break;
case MessageSelector::LatenciesChanged:
MessageLatenciesChanged();
result = 1;
break;
case MessageSelector::SupportsTimeInfo:
result = MessageSupportsTimeInfo() ? 1 : 0;
break;
case MessageSelector::SupportsTimeCode:
result = MessageSupportsTimeCode() ? 1 : 0;
break;
case MessageSelector::MMCCommand:
result = MessageMMCCommand(value, message, opt);
break;
case MessageSelector::SupportsInputMonitor:
result = MessageSupportsInputMonitor() ? 1 : 0;
break;
case MessageSelector::SupportsInputGain:
result = MessageSupportsInputGain() ? 1 : 0;
break;
case MessageSelector::SupportsInputMeter:
result = MessageSupportsInputMeter() ? 1 : 0;
break;
case MessageSelector::SupportsOutputGain:
result = MessageSupportsOutputGain() ? 1 : 0;
break;
case MessageSelector::SupportsOutputMeter:
result = MessageSupportsOutputMeter() ? 1 : 0;
break;
case MessageSelector::Overload:
MessageOverload();
result = 1;
break;
default:
result = MessageUnknown(selector, value, message, opt);
break;
}
return result;
}
void CallbackSampleRateDidChange(Driver & driver, SampleRate sRate) noexcept final {
static_cast<void>(driver);
RealtimeSampleRateDidChange(sRate);
}
void CallbackBufferSwitch(Driver & driver, Long doubleBufferIndex, Bool directProcess) noexcept final {
CallbackBufferSwitchTimeInfo(driver, nullptr, doubleBufferIndex, directProcess);
}
const Time * CallbackBufferSwitchTimeInfo(Driver & driver, const Time * params, Long doubleBufferIndex, Bool directProcess) noexcept final {
Time time;
if (params) {
time = *params;
} else {
try {
HiLoLongLong samplePosition = 0;
HiLoLongLong systemTime = 0;
if (driver.realDriver().getSamplePosition(&samplePosition, &systemTime) == ErrorCode::OK) {
time.timeInfo.flags |= TimeInfoFlagSamplePositionValid | TimeInfoFlagSystemTimeValid;
time.timeInfo.samplePosition = samplePosition;
time.timeInfo.systemTime = systemTime;
time.timeInfo.speed = 1.0;
SampleRate sampleRate = 0.0;
if (driver.realDriver().getSampleRate(&sampleRate) == ErrorCode::OK) {
if (sampleRate >= 0.0) {
time.timeInfo.flags |= TimeInfoFlagSampleRateValid;
time.timeInfo.sampleRate = sampleRate;
}
}
}
} catch (...) {
// nothing
}
}
RealtimeRequestDeferredProcessing(!directProcess);
RealtimeTimeInfo(time);
RealtimeBufferSwitch(doubleBufferIndex);
return params;
}
};
private:
std::unique_ptr<IDriver> m_Driver;
ICallbackHandler * m_CallbackHandler = nullptr;
std::unique_ptr<IMultiplexedCallbacks> m_Callbacks;
private:
const IDriver & realDriver() const noexcept {
return *m_Driver;
}
IDriver & realDriver() noexcept {
return *m_Driver;
}
public:
explicit Driver(std::unique_ptr<IDriver> driver)
: m_Driver(std::move(driver)) {
return;
}
Driver(const Driver &) = delete;
Driver & operator=(const Driver &) = delete;
~Driver() {
return;
}
private:
[[nodiscard]] static ErrorCode CheckResultOutOfMemory(ErrorCode ec) {
if (ec == ErrorCode::NoMemory) {
throw std::bad_alloc();
}
return ec;
}
static void CheckResult(ErrorCode expected, ErrorCode ec) {
ec = CheckResultOutOfMemory(ec);
if (ec != expected) {
throw Error(ec);
}
}
static void CheckResultNoOutOfMemory(ErrorCode expected, ErrorCode ec) {
if (ec != expected) {
throw Error(ec);
}
}
static void CheckOK(ErrorCode ec) {
CheckResult(ErrorCode::OK, ec);
}
static void CheckSUCCESS(ErrorCode ec) {
CheckResult(ErrorCode::SUCCESS, ec);
}
static void CheckOKNoOutOfMemory(ErrorCode ec) {
CheckResultNoOutOfMemory(ErrorCode::OK, ec);
}
static void CheckSUCCESSNoOutOfMemory(ErrorCode ec) {
CheckResultNoOutOfMemory(ErrorCode::SUCCESS, ec);
}
private:
static Driver * ThisFromVoid(void * context) noexcept {
return reinterpret_cast<Driver *>(context);
}
void * MyContext() noexcept {
return this;
}
static constexpr CallbacksWithContext MyCallbacks() noexcept {
CallbacksWithContext result = {&CallbackBufferSwitch, &CallbackSampleRateDidChange, &CallbackAsioMessage, &CallbackBufferSwitchTimeInfo};
return result;
}
private:
static void CallbackBufferSwitch(void * context, Long doubleBufferIndex, Bool directProcess) noexcept {
assert(context);
assert(ThisFromVoid(context)->m_CallbackHandler);
return ThisFromVoid(context)->m_CallbackHandler->CallbackBufferSwitch(*ThisFromVoid(context), doubleBufferIndex, directProcess);
}
static void CallbackSampleRateDidChange(void * context, SampleRate sRate) noexcept {
assert(context);
assert(ThisFromVoid(context)->m_CallbackHandler);
return ThisFromVoid(context)->m_CallbackHandler->CallbackSampleRateDidChange(*ThisFromVoid(context), sRate);
}
static Long CallbackAsioMessage(void * context, MessageSelector selector, Long value, const void * message, const Double * opt) noexcept {
assert(context);
assert(ThisFromVoid(context)->m_CallbackHandler);
return ThisFromVoid(context)->m_CallbackHandler->CallbackMessage(*ThisFromVoid(context), selector, value, message, opt);
}
static const Time * CallbackBufferSwitchTimeInfo(void * context, const Time * params, Long doubleBufferIndex, Bool directProcess) noexcept {
assert(context);
assert(ThisFromVoid(context)->m_CallbackHandler);
return ThisFromVoid(context)->m_CallbackHandler->CallbackBufferSwitchTimeInfo(*ThisFromVoid(context), params, doubleBufferIndex, directProcess);
}
public:
std::string getDriverName() const {
DriverName name = "";
m_Driver->getDriverName(&name);
return name;
}
[[nodiscard]] Long getDriverVersion() const {
return m_Driver->getDriverVersion();
}
std::string getErrorMessage() const {
ErrorMessage string = "";
m_Driver->getErrorMessage(&string);
return string;
}
void start() {
CheckOK(m_Driver->start());
}
void stop() {
CheckOK(m_Driver->stop());
}
Channels getChannels() const {
Channels result;
CheckOK(m_Driver->getChannels(&result.Input, &result.Output));
return result;
}
Latencies getLatencies() const {
Latencies result;
CheckOK(m_Driver->getLatencies(&result.Input, &result.Output));
return result;
}
BufferSizes getBufferSizes() const {
BufferSizes result;
CheckOK(m_Driver->getBufferSize(&result.Min, &result.Max, &result.Preferred, &result.Granularity));
return result;
}
bool canSampleRate(SampleRate sampleRate) const {
ErrorCode ec = m_Driver->canSampleRate(sampleRate);
if ((ec != ErrorCode::OK) && (ec != ErrorCode::NoClock)) {
CheckOK(ec);
}
return (ec == ErrorCode::OK);
}
SampleRate getSampleRate() const {
SampleRate sampleRate = 0.0;
ErrorCode ec = m_Driver->getSampleRate(&sampleRate);
if ((ec != ErrorCode::OK) && (ec != ErrorCode::NoClock)) {
CheckOK(ec);
}
return sampleRate;
}
void setSampleRate(SampleRate sampleRate) {
CheckOK(m_Driver->setSampleRate(sampleRate));
}
std::vector<ClockSource> getClockSources() const {
std::vector<ClockSource> clocks(1);
Long numSources = 1;
CheckOK(m_Driver->getClockSources(clocks.data(), &numSources));
if (numSources > 1) {
clocks.resize(numSources);
CheckOK(m_Driver->getClockSources(clocks.data(), &numSources));
}
return clocks;
}
void setClockSource(Long reference) {
CheckOK(m_Driver->setClockSource(reference));
}
SamplePosition getSamplePosition() const {
HiLoLongLong samplePosition = 0;
HiLoLongLong systemTime = 0;
CheckOK(m_Driver->getSamplePosition(&samplePosition, &systemTime));
SamplePosition result;
result.samplePosition = samplePosition;
result.systemTime = systemTime;
return result;
}
ChannelInfo getChannelInfo(Long channel, Bool input) const {
ChannelInfo info;
info.channel = channel;
info.isInput = input;
CheckOK(m_Driver->getChannelInfo(&info));
return info;
}
template <std::uint64_t AppID1, std::uint64_t AppID2, std::size_t MaxInstances = 256>
void createBuffers(std::vector<BufferInfo> & bufferInfos, Long bufferSize, ICallbackHandler & handler) {
assert(!m_CallbackHandler);
assert(!m_Callbacks);
m_CallbackHandler = &handler;
m_Callbacks = MultiplexedCallbacks<AppID1, AppID2, MaxInstances>::make(MyContext(), MyCallbacks());
try {
CheckOKNoOutOfMemory(m_Driver->createBuffers(bufferInfos.data(), static_cast<Long>(bufferInfos.size()), bufferSize, *m_Callbacks));
} catch (...) {
m_Callbacks = nullptr;
m_CallbackHandler = nullptr;
throw;
}
}
void disposeBuffers() {
assert(m_CallbackHandler);
assert(m_Callbacks);
try {
CheckOK(m_Driver->disposeBuffers());
} catch (...) {
m_Callbacks = nullptr;
m_CallbackHandler = nullptr;
throw;
}
m_Callbacks = nullptr;
m_CallbackHandler = nullptr;
}
bool controlPanel() {
ErrorCode ec = m_Driver->controlPanel();
if ((ec != ErrorCode::OK) && (ec != ErrorCode::NotPresent)) {
CheckOK(ec);
}
return (ec == ErrorCode::OK);
}
[[deprecated]] [[nodiscard]] ErrorCode future(FutureSelector selector, void * opt) {
return CheckResultOutOfMemory(m_Driver->future(selector, opt));
}
void enableTimeCodeRead() {
CheckSUCCESS(m_Driver->future(FutureSelector::EnableTimeCodeRead, nullptr));
}
void disableTimeCodeRead() {
CheckSUCCESS(m_Driver->future(FutureSelector::DisableTimeCodeRead, nullptr));
}
void setInputMonitor(InputMonitor & inputMonitor) {
CheckSUCCESS(m_Driver->future(FutureSelector::SetInputMonitor, &inputMonitor));
}
void transport(TransportParameters & transportParameters) {
CheckSUCCESS(m_Driver->future(FutureSelector::Transport, &transportParameters));
}
void setInputGain(Long channel, Bool input, Long gain) {
ChannelControls channelControls;
channelControls.channel = channel;
channelControls.isInput = input;
channelControls.gain = gain;
CheckSUCCESS(m_Driver->future(FutureSelector::SetInputGain, &channelControls));
}
Long getInputMeter(Long channel, Bool input) const {
ChannelControls channelControls;
channelControls.channel = channel;
channelControls.isInput = input;
CheckSUCCESS(m_Driver->future(FutureSelector::GetInputMeter, &channelControls));
return channelControls.meter;
}
void setOutputGain(Long channel, Bool input, Long gain) {
ChannelControls channelControls;
channelControls.channel = channel;
channelControls.isInput = input;
channelControls.gain = gain;
CheckSUCCESS(m_Driver->future(FutureSelector::SetOutputGain, &channelControls));
}
Long getOutputMeter(Long channel, Bool input) const {
ChannelControls channelControls;
channelControls.channel = channel;
channelControls.isInput = input;
CheckSUCCESS(m_Driver->future(FutureSelector::GetOutputMeter, &channelControls));
return channelControls.meter;
}
bool canInputMonitor() const {
ErrorCode ec = CheckResultOutOfMemory(m_Driver->future(FutureSelector::CanInputMonitor, nullptr));
return (ec == ErrorCode::SUCCESS);
}
bool canTimeInfo() const {
ErrorCode ec = CheckResultOutOfMemory(m_Driver->future(FutureSelector::CanTimeInfo, nullptr));
return (ec == ErrorCode::SUCCESS);
}
bool canTimeCode() const {
ErrorCode ec = CheckResultOutOfMemory(m_Driver->future(FutureSelector::CanTimeCode, nullptr));
return (ec == ErrorCode::SUCCESS);
}
bool canTransport() const {
ErrorCode ec = CheckResultOutOfMemory(m_Driver->future(FutureSelector::CanTransport, nullptr));
return (ec == ErrorCode::SUCCESS);
}
bool canInputGain() const {
ErrorCode ec = CheckResultOutOfMemory(m_Driver->future(FutureSelector::CanInputGain, nullptr));
return (ec == ErrorCode::SUCCESS);
}
bool canInputMeter() const {
ErrorCode ec = CheckResultOutOfMemory(m_Driver->future(FutureSelector::CanInputMeter, nullptr));
return (ec == ErrorCode::SUCCESS);
}
bool canOutputGain() const {
ErrorCode ec = CheckResultOutOfMemory(m_Driver->future(FutureSelector::CanOutputGain, nullptr));
return (ec == ErrorCode::SUCCESS);
}
bool canOutputMeter() const {
ErrorCode ec = CheckResultOutOfMemory(m_Driver->future(FutureSelector::CanOutputMeter, nullptr));
return (ec == ErrorCode::SUCCESS);
}
[[nodiscard]] ErrorCode optionalOne(void * param) {
return CheckResultOutOfMemory(m_Driver->future(FutureSelector::OptionalOne, param));
}
void setIoFormat(IoFormatType type) {
IoFormat ioFormat;
ioFormat.FormatType = type;
CheckSUCCESS(m_Driver->future(FutureSelector::SetIoFormat, &ioFormat));
}
IoFormatType getIoFormat() const {
IoFormat ioFormat;
CheckSUCCESS(m_Driver->future(FutureSelector::GetIoFormat, &ioFormat));
return ioFormat.FormatType;
}
bool canDoIoFormat(IoFormatType type) {
IoFormat ioFormat;
ioFormat.FormatType = type;
ErrorCode ec = CheckResultOutOfMemory(m_Driver->future(FutureSelector::CanDoIoFormat, &ioFormat));
return (ec == ErrorCode::SUCCESS);
}
bool canReportOverload() const {
ErrorCode ec = CheckResultOutOfMemory(m_Driver->future(FutureSelector::CanReportOverload, nullptr));
return (ec == ErrorCode::SUCCESS);
}
InternalBufferInfo getInternalBufferSamples() const {
InternalBufferInfo internalBufferInfo;
ErrorCode ec = CheckResultOutOfMemory(m_Driver->future(FutureSelector::CanReportOverload, &internalBufferInfo));
if (ec != ErrorCode::SUCCESS) {
return InternalBufferInfo();
}
return internalBufferInfo;
}
bool canOutputReady() const {
ErrorCode ec = m_Driver->outputReady();
if ((ec != ErrorCode::OK) && (ec != ErrorCode::NotPresent)) {
CheckOK(ec);
}
return (ec == ErrorCode::OK);
}
void outputReady() {
CheckOK(m_Driver->outputReady());
}
};
} // namespace ASIO_VERSION_NAMESPACE
} // namespace Modern
} // namespace ASIO
#endif // ASIO_ASIOMODERN_HPP