diff options
Diffstat (limited to 'Src/external_dependencies/openmpt-trunk/include/asiomodern')
12 files changed, 4185 insertions, 0 deletions
diff --git a/Src/external_dependencies/openmpt-trunk/include/asiomodern/OpenMPT.txt b/Src/external_dependencies/openmpt-trunk/include/asiomodern/OpenMPT.txt new file mode 100644 index 00000000..3879702b --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/asiomodern/OpenMPT.txt @@ -0,0 +1 @@ +ASIO::Modern v0.12.5
diff --git a/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/.clang-format b/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/.clang-format new file mode 100644 index 00000000..db82ab66 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/.clang-format @@ -0,0 +1,153 @@ +# clang-format 13 + +Language: Cpp +Standard: c++20 + +AccessModifierOffset: -4 #? +AlignAfterOpenBracket: AlwaysBreak +AlignArrayOfStructures: Left +AlignConsecutiveAssignments: true +AlignConsecutiveBitFields: true +AlignConsecutiveDeclarations: true +AlignConsecutiveMacros: true +AlignEscapedNewlines: DontAlign +AlignOperands: AlignAfterOperator +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortEnumsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: false +AllowShortLambdasOnASingleLine: Inline +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: [] +BinPackArguments: true +BinPackParameters: false +BitFieldColonSpacing: Both +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: MultiLine + AfterEnum: false + AfterFunction: false + AfterNamespace: false + #AfterObjCDeclaration + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: false + SplitEmptyNamespace: true +#BreakAfterJavaFieldAnnotations +BreakBeforeBinaryOperators: NonAssignment +BreakBeforeBraces: Custom +BreakBeforeConceptDeclarations: true +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeComma +BreakInheritanceList: BeforeComma +BreakStringLiterals: false +ColumnLimit: 0 +CommentPragmas: '' #? +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 #? +ContinuationIndentWidth: 4 #? +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +EmptyLineAfterAccessModifier: Leave +EmptyLineBeforeAccessModifier: Leave +FixNamespaceComments: true +ForEachMacros: [] +IfMacros: [''] +IncludeBlocks: Preserve +IncludeCategories: [] #? +IncludeIsMainRegex: '' #? +IncludeIsMainSourceRegex: '' #? +IndentAccessModifiers: false +IndentCaseLabels: true +IndentCaseBlocks: true +IndentExternBlock: NoIndent +IndentGotoLabels: false +IndentPPDirectives: None +#IndentRequiresClause: true +InsertTrailingCommas: None +#BeforeHash +IndentWidth: 4 +IndentWrappedFunctionNames: true +#JavaImportGroups +#JavaScriptQuotes +#JavaScriptWrapImports +KeepEmptyLinesAtTheStartOfBlocks: true +LambdaBodyIndentation: OuterScope +MacroBlockBegin: '' #? +MacroBlockEnd: '' #? +MaxEmptyLinesToKeep: 5 +NamespaceIndentation: None +NamespaceMacros: [] #? +#ObjCBinPackProtocolList +#ObjCBlockIndentWidth +#ObjCBreakBeforeNestedBlockParam +#ObjCSpaceAfterProperty +#ObjCSpaceBeforeProtocolList +#PenaltyBreakAssignment +#PenaltyBreakBeforeFirstCallParameter +#PenaltyBreakComment +#PenaltyBreakFirstLessLess +#PenaltyBreakString +#PenaltyBreakTemplateDeclaration +#PenaltyExcessCharacter +#PenaltyIndentedWhitespace +#PenaltyReturnTypeOnItsOwnLine +PointerAlignment: Middle +PPIndentWidth: -1 +#RawStringFormats +ReferenceAlignment: Pointer +ReflowComments: false +ShortNamespaceLines: 1 +SortIncludes: false +#SortJavaStaticImport +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceAroundPointerQualifiers: Default +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyBlock: true +SpaceInEmptyParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInParentheses: false +SpacesInSquareBrackets: false +StatementAttributeLikeMacros: [] +StatementMacros: [ '_Pragma', '__pragma' ] #? +TabWidth: 4 +TypenameMacros: [] #? +UseCRLF: false +UseTab: ForContinuationAndIndentation +WhitespaceSensitiveMacros: + - ASIO_PP_STRINGIFY diff --git a/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIO.hpp b/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIO.hpp new file mode 100644 index 00000000..891f2e12 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIO.hpp @@ -0,0 +1,16 @@ + +#ifndef ASIO_ASIO_HPP +#define ASIO_ASIO_HPP + + + +#include "ASIOVersion.hpp" +#include "ASIOConfig.hpp" +#include "ASIOCore.hpp" +#include "ASIOModern.hpp" +//#include "ASIOSystemWindows.hpp" +//#include "ASIOSampleConvert.hpp" + + + +#endif // ASIO_ASIO_HPP diff --git a/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOConfig.hpp b/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOConfig.hpp new file mode 100644 index 00000000..7ae4e493 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOConfig.hpp @@ -0,0 +1,385 @@ + +#ifndef ASIO_ASIOCONFIG_HPP +#define ASIO_ASIOCONFIG_HPP + + + +#include "ASIOVersion.hpp" + + + +#include <algorithm> +#include <string> +#include <string_view> + +#include <cstddef> +#include <cstdint> +#include <cstring> + + + +#if defined(_WIN32) +#define ASIO_SYSTEM_WINDOWS 1 +#endif + +#ifndef ASIO_SYSTEM_WINDOWS +#define ASIO_SYSTEM_WINDOWS 0 +#endif + + +#if defined(__clang__) +#define ASIO_COMPILER_CLANG 1 +#elif defined(_MSC_VER) +#define ASIO_COMPILER_MSVC 1 +#elif defined(__GNUC__) +#define ASIO_COMPILER_GCC 1 +#endif + +#ifndef ASIO_COMPILER_CLANG +#define ASIO_COMPILER_CLANG 0 +#endif +#ifndef ASIO_COMPILER_MSVC +#define ASIO_COMPILER_MSVC 0 +#endif +#ifndef ASIO_COMPILER_GCC +#define ASIO_COMPILER_GCC 0 +#endif + + +#if ASIO_COMPILER_MSVC || ASIO_COMPILER_CLANG || ASIO_COMPILER_GCC || ASIO_SYSTEM_WINDOWS +// assume #pragma pack support on Windows +#define ASIO_HAVE_PRAGMA_PACK 1 +#else +#define ASIO_HAVE_PRAGMA_PACK 0 +#endif + + +#if ASIO_COMPILER_MSVC || ASIO_COMPILER_CLANG || ASIO_SYSTEM_WINDOWS +// assume #pragma comment lib support on Windows +#define ASIO_HAVE_PRAGMA_COMMENT_LIB 1 +#else +#define ASIO_HAVE_PRAGMA_COMMENT_LIB 0 +#endif + + + +#if ASIO_SYSTEM_WINDOWS +#include <objbase.h> +#endif // ASIO_SYSTEM_WINDOWS + + + +namespace ASIO { + + + +#define ASIO_PP_DEFER(m, ...) m(__VA_ARGS__) + +#define ASIO_PP_STRINGIFY(x) #x + +#define ASIO_PP_JOIN_HELPER(a, b) a##b +#define ASIO_PP_JOIN(a, b) ASIO_PP_JOIN_HELPER(a, b) + +#define ASIO_PP_UNIQUE_IDENTIFIER(prefix) ASIO_PP_JOIN(prefix, __LINE__) + + + +#if ASIO_COMPILER_MSVC +#define ASIO_WARNING(text) __pragma(message(__FILE__ "(" ASIO_PP_DEFER(ASIO_PP_STRINGIFY, __LINE__) "): Warning: " text)) +#elif ASIO_COMPILER_GCC || ASIO_COMPILER_CLANG +#define ASIO_WARNING(text) _Pragma(MPT_PP_STRINGIFY(GCC warning text)) +#else +#define ASIO_WARNING(text) \ + static inline int ASIO_PP_UNIQUE_IDENTIFIER(ASIO_WARNING_NAME)() noexcept { \ + int warning [[deprecated("Warning: " text)]] = 0; \ + return warning; \ + } \ +/**/ +#endif + + + +#if ASIO_SYSTEM_WINDOWS + + +#if !ASIO_HAVE_PRAGMA_PACK +#error "ASIO on Windows requires #pragma pack support" +#endif // !ASIO_HAVE_PRAGMA_PACK + +#define ASIO_INTERFACE interface + +#if ASIO_COMPILER_MSVC +#define ASIO_ATTR_DRIVERCALL +#define ASIO_DRIVERCALL __thiscall +#elif ASIO_COMPILER_CLANG +#define ASIO_ATTR_DRIVERCALL +#define ASIO_DRIVERCALL __thiscall +#elif ASIO_COMPILER_GCC +#pragma push_macro("thiscall") +#ifdef thiscall +#undef thiscall +#endif +#define ASIO_ATTR_DRIVERCALL [[gnu::thiscall]] +#define ASIO_DRIVERCALL +#pragma pop_macro("thiscall") +#else +#define ASIO_ATTR_DRIVERCALL +#define ASIO_DRIVERCALL __thiscall +#endif + +#if ASIO_COMPILER_MSVC +#define ASIO_ATTR_CALL +#define ASIO_CALL __cdecl +#elif ASIO_COMPILER_CLANG +#define ASIO_ATTR_CALL +#define ASIO_CALL __cdecl +#elif ASIO_COMPILER_GCC +#pragma push_macro("cdecl") +#ifdef cdecl +#undef cdecl +#endif +#define ASIO_ATTR_CALL [[gnu::cdecl]] +#define ASIO_CALL +#pragma pop_macro("cdecl") +#else +#define ASIO_ATTR_CALL +#define ASIO_CALL __cdecl +#endif + + +#else // !ASIO_SYSTEM_WINDOWS + + +#error "Only Windows is supported by this ASIO header" + + +#define ASIO_INTERFACE struct + +#define ASIO_ATTR_DRIVERCALL +#define ASIO_DRIVERCALL + +#define ASIO_ATTR_CALL +#define ASIO_CALL + + +#endif // ASIO_SYSTEM_WINDOWS + + + +inline namespace Core { + + + +inline namespace ASIO_VERSION_NAMESPACE { + + + +#if ASIO_SYSTEM_WINDOWS + + +using SysHandle = void *; + +using Byte = std::uint8_t; + +using Long = std::int32_t; + +using ULong = std::uint32_t; + +using LongLong = std::int64_t; + +using ULongLong = std::uint64_t; + +using Double = double; + +using Char = char; + +using Padding1 = std::uint8_t; + +using PaddingLong = ULong; + + +#else // !ASIO_SYSTEM_WINDOWS + + +#error "Only Windows is supported by this ASIO header" + + +#define ASIO_INTERFACE struct + +#define ASIO_ATTR_DRIVERCALL +#define ASIO_DRIVERCALL + +#define ASIO_ATTR_CALL +#define ASIO_CALL + +using SysHandle = void *; + +using Byte = unsigned char; + +using Long = signed long; + +using ULong = unsigned long; + +using LongLong = signed long long; + +using ULongLong = unsigned long long; + +using Double = double; + +using Char = char; + +using Padding1 = std::uint8_t; + +using PaddingLong = ULong; + + +#endif // ASIO_SYSTEM_WINDOWS + + + +struct Bool { +private: + ULong m_val; + +public: + constexpr Bool() noexcept + : m_val(0) { } + constexpr Bool(bool val) noexcept + : m_val(val ? 1 : 0) { } + constexpr explicit Bool(ULong val) noexcept + : m_val(val ? 1 : 0) { } + constexpr bool operator!() const noexcept { + return m_val ? false : true; + } + constexpr operator bool() const noexcept { + return m_val ? true : false; + } +}; + +struct HiLoLongLong { +private: + ULong m_hi; + ULong m_lo; + +public: + constexpr HiLoLongLong() noexcept + : m_hi(0) + , m_lo(0) { + } + constexpr HiLoLongLong(LongLong val) noexcept + : m_hi(static_cast<ULong>((static_cast<ULongLong>(val) & 0xffffffff00000000ull) >> 32)) + , m_lo(static_cast<ULong>((static_cast<ULongLong>(val) & 0x00000000ffffffffull) >> 0)) { + } + constexpr operator LongLong() const noexcept { + return static_cast<LongLong>((static_cast<ULongLong>(m_hi) << 32) | (static_cast<ULongLong>(m_lo) << 0)); + } +}; + +using ResultBool = ULong; + +template <std::size_t size> +struct CharBuf { +private: + Char buf[size] = ""; + +public: + CharBuf() = default; + CharBuf(const CharBuf &) = default; + CharBuf(CharBuf &&) = default; + CharBuf & operator=(const CharBuf &) = default; + CharBuf & operator=(CharBuf &&) = default; + +public: + constexpr CharBuf(std::nullptr_t) noexcept + : CharBuf() { + } + inline CharBuf(const char * str) noexcept + : CharBuf() { + if (str) { + std::copy(str, str + std::min(std::strlen(str), size - 1), buf); + std::fill(buf + std::min(std::strlen(str), size - 1), buf + size, Char('\0')); + } + } + inline CharBuf(const std::string_view & str) noexcept + : CharBuf() { + std::copy(str.data(), str.data() + std::min(str.length(), size - 1), buf); + std::fill(buf + std::min(str.length(), size - 1), buf + size, Char('\0')); + } + inline CharBuf(const std::string & str) noexcept + : CharBuf() { + std::copy(str.data(), str.data() + std::min(str.length(), size - 1), buf); + std::fill(buf + std::min(str.length(), size - 1), buf + size, Char('\0')); + } + inline CharBuf & operator=(std::nullptr_t) noexcept { + std::fill(buf, buf + size, Char('\0')); + return *this; + } + inline CharBuf & operator=(const char * str) noexcept { + if (str) { + std::copy(str, str + std::min(std::strlen(str), size - 1), buf); + std::fill(buf + std::min(std::strlen(str), size - 1), buf + size, Char('\0')); + } else { + std::fill(buf, buf + size, Char('\0')); + } + return *this; + } + inline CharBuf & operator=(const std::string & str) noexcept { + std::fill(buf, buf + size, Char('\0')); + std::copy(str.data(), str.data() + std::min(str.length(), size - 1), buf); + std::fill(buf + std::min(str.length(), size - 1), buf + size, Char('\0')); + return *this; + } + inline CharBuf & operator=(const std::string_view & str) noexcept { + std::fill(buf, buf + size, Char('\0')); + std::copy(str.data(), str.data() + std::min(str.length(), size - 1), buf); + std::fill(buf + std::min(str.length(), size - 1), buf + size, Char('\0')); + return *this; + } + inline explicit operator std::string_view() const noexcept { + std::size_t len = std::find(buf, buf + size - 1, Char('\0')) - buf; + return std::string_view(buf, buf + len); + } + inline operator std::string() const { + std::size_t len = std::find(buf, buf + size - 1, Char('\0')) - buf; + return std::string(buf, buf + len); + } +}; + +inline constexpr std::size_t SizeOfChar = sizeof(Char); +inline constexpr std::size_t SizeOfByte = sizeof(Byte); +inline constexpr std::size_t SizeOfBool = sizeof(Bool); +inline constexpr std::size_t SizeOfLong = sizeof(Long); +inline constexpr std::size_t SizeOfLongLong = sizeof(LongLong); +inline constexpr std::size_t SizeOfDouble = sizeof(Double); +inline constexpr std::size_t SizeOfHiLoLongLong = sizeof(HiLoLongLong); + +static_assert(SizeOfChar == 1); +static_assert(SizeOfByte == 1); + +static_assert(SizeOfBool == SizeOfLong); + +static_assert(SizeOfHiLoLongLong == SizeOfLongLong); + +static_assert(SizeOfLongLong == 8); + +static_assert(sizeof(Padding1) == 1); + +static_assert(sizeof(PaddingLong) == SizeOfLong); + +static_assert(sizeof(CharBuf<1>) == 1); + + + +} // namespace ASIO_VERSION_NAMESPACE + + + +} // namespace Core + + + +} // namespace ASIO + + + +#endif // ASIO_ASIOCONFIG_HPP diff --git a/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOCore.hpp b/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOCore.hpp new file mode 100644 index 00000000..97b6206a --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOCore.hpp @@ -0,0 +1,469 @@ + +#ifndef ASIO_ASIOCORE_HPP +#define ASIO_ASIOCORE_HPP + + + +#include "ASIOVersion.hpp" +#include "ASIOConfig.hpp" + +#include <algorithm> +#include <string> +#include <type_traits> + +#include <cstddef> +#include <cstdint> + + + +namespace ASIO { + + + +inline namespace Core { + + + +inline namespace ASIO_VERSION_NAMESPACE { + + + +using Samples = HiLoLongLong; + +using TimeStamp = HiLoLongLong; + +using SampleRate = Double; + +enum class SampleType : Long { + Int16MSB = 0, + Int24MSB = 1, + Int32MSB = 2, + Float32MSB = 3, + Float64MSB = 4, + Int32MSB16 = 8, + Int32MSB18 = 9, + Int32MSB20 = 10, + Int32MSB24 = 11, + Int16LSB = 16, + Int24LSB = 17, + Int32LSB = 18, + Float32LSB = 19, + Float64LSB = 20, + Int32LSB16 = 24, + Int32LSB18 = 25, + Int32LSB20 = 26, + Int32LSB24 = 27, + DSDInt8LSB1 = 32, + DSDInt8MSB1 = 33, + DSDInt8NER8 = 40, +}; +static_assert(sizeof(SampleType) == SizeOfLong); + +enum class ErrorCode : Long { + OK = 0, + SUCCESS = 0x3f4847a0, + NotPresent = -1000, + HWMalfunction = -999, + InvalidParameter = -998, + InvalidMode = -997, + SPNotAdvancing = -996, + NoClock = -995, + NoMemory = -994, +}; +static_assert(sizeof(ErrorCode) == SizeOfLong); + +enum TimeCodeFlags : ULong { + TimeCodeFlagValid = 1 << 0, + TimeCodeFlagRunning = 1 << 1, + TimeCodeFlagReverse = 1 << 2, + TimeCodeFlagOnspeed = 1 << 3, + TimeCodeFlagStill = 1 << 4, + TimeCodeFlagSpeedValid = 1 << 8, +}; +constexpr inline TimeCodeFlags operator|(TimeCodeFlags a, TimeCodeFlags b) noexcept { + return static_cast<TimeCodeFlags>(static_cast<std::underlying_type<TimeCodeFlags>::type>(a) | static_cast<std::underlying_type<TimeCodeFlags>::type>(b)); +} +constexpr inline TimeCodeFlags operator&(TimeCodeFlags a, TimeCodeFlags b) noexcept { + return static_cast<TimeCodeFlags>(static_cast<std::underlying_type<TimeCodeFlags>::type>(a) & static_cast<std::underlying_type<TimeCodeFlags>::type>(b)); +} +constexpr inline TimeCodeFlags operator^(TimeCodeFlags a, TimeCodeFlags b) noexcept { + return static_cast<TimeCodeFlags>(static_cast<std::underlying_type<TimeCodeFlags>::type>(a) ^ static_cast<std::underlying_type<TimeCodeFlags>::type>(b)); +} +constexpr inline TimeCodeFlags operator~(TimeCodeFlags a) noexcept { + return static_cast<TimeCodeFlags>(~static_cast<std::underlying_type<TimeCodeFlags>::type>(a)); +} +constexpr inline TimeCodeFlags & operator|=(TimeCodeFlags & a, TimeCodeFlags b) noexcept { + return a = a | b; +} +constexpr inline TimeCodeFlags & operator&=(TimeCodeFlags & a, TimeCodeFlags b) noexcept { + return a = a & b; +} +constexpr inline TimeCodeFlags & operator^=(TimeCodeFlags & a, TimeCodeFlags b) noexcept { + return a = a ^ b; +} +static_assert(sizeof(TimeCodeFlags) == SizeOfLong); + +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(push, 4) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +struct TimeCode { + Double speed = 0.0; + HiLoLongLong timeCodeSamples = 0; + TimeCodeFlags flags = static_cast<TimeCodeFlags>(0); + Padding1 future[64] = {0}; +}; +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(pop) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +static_assert(sizeof(TimeCode) == (SizeOfDouble + SizeOfLongLong + SizeOfLong + 64)); + +enum TimeInfoFlags : ULong { + TimeInfoFlagSystemTimeValid = 1 << 0, + TimeInfoFlagSamplePositionValid = 1 << 1, + TimeInfoFlagSampleRateValid = 1 << 2, + TimeInfoFlagSpeedValid = 1 << 3, + TimeInfoFlagSampleRateChanged = 1 << 4, + TimeInfoFlagClockSourceChanged = 1 << 5, +}; +constexpr inline TimeInfoFlags operator|(TimeInfoFlags a, TimeInfoFlags b) noexcept { + return static_cast<TimeInfoFlags>(static_cast<std::underlying_type<TimeInfoFlags>::type>(a) | static_cast<std::underlying_type<TimeInfoFlags>::type>(b)); +} +constexpr inline TimeInfoFlags operator&(TimeInfoFlags a, TimeInfoFlags b) noexcept { + return static_cast<TimeInfoFlags>(static_cast<std::underlying_type<TimeInfoFlags>::type>(a) & static_cast<std::underlying_type<TimeInfoFlags>::type>(b)); +} +constexpr inline TimeInfoFlags operator^(TimeInfoFlags a, TimeInfoFlags b) noexcept { + return static_cast<TimeInfoFlags>(static_cast<std::underlying_type<TimeInfoFlags>::type>(a) ^ static_cast<std::underlying_type<TimeInfoFlags>::type>(b)); +} +constexpr inline TimeInfoFlags operator~(TimeInfoFlags a) noexcept { + return static_cast<TimeInfoFlags>(~static_cast<std::underlying_type<TimeInfoFlags>::type>(a)); +} +constexpr inline TimeInfoFlags & operator|=(TimeInfoFlags & a, TimeInfoFlags b) noexcept { + return a = a | b; +} +constexpr inline TimeInfoFlags & operator&=(TimeInfoFlags & a, TimeInfoFlags b) noexcept { + return a = a & b; +} +constexpr inline TimeInfoFlags & operator^=(TimeInfoFlags & a, TimeInfoFlags b) noexcept { + return a = a ^ b; +} +static_assert(sizeof(TimeInfoFlags) == SizeOfLong); + +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(push, 4) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +struct TimeInfo { + Double speed = 0.0; + HiLoLongLong systemTime = 0; + HiLoLongLong samplePosition = 0; + SampleRate sampleRate = 0.0; + TimeInfoFlags flags = static_cast<TimeInfoFlags>(0); + Padding1 reserved[12] = {0}; +}; +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(pop) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +static_assert(sizeof(TimeInfo) == (SizeOfDouble + SizeOfLongLong + SizeOfLongLong + SizeOfDouble + SizeOfLong + 12)); + +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(push, 4) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +struct Time { + PaddingLong reserved[4] = {0}; + TimeInfo timeInfo; + TimeCode timeCode; +}; +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(pop) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +static_assert(sizeof(Time) == (4 * SizeOfLong + sizeof(TimeInfo) + sizeof(TimeCode))); + +enum class MessageSelector : Long { + SelectorSupported = 1, + EngineVersion = 2, + ResetRequest = 3, + BufferSizeChange = 4, + ResyncRequest = 5, + LatenciesChanged = 6, + SupportsTimeInfo = 7, + SupportsTimeCode = 8, + MMCCommand = 9, + SupportsInputMonitor = 10, + SupportsInputGain = 11, + SupportsInputMeter = 12, + SupportsOutputGain = 13, + SupportsOutputMeter = 14, + Overload = 15, +}; +static_assert(sizeof(MessageSelector) == SizeOfLong); + +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(push, 4) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#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) +struct Callbacks { + void(ASIO_CALL * bufferSwitch ASIO_ATTR_CALL)(Long doubleBufferIndex, Bool directProcess) noexcept = nullptr; + void(ASIO_CALL * sampleRateDidChange ASIO_ATTR_CALL)(SampleRate sRate) noexcept = nullptr; + Long(ASIO_CALL * asioMessage ASIO_ATTR_CALL)(MessageSelector selector, Long value, void const * message, Double const * opt) noexcept = nullptr; + Time const *(ASIO_CALL * bufferSwitchTimeInfo ASIO_ATTR_CALL)(Time const * params, Long doubleBufferIndex, Bool directProcess) noexcept = nullptr; +}; +#if ASIO_SYSTEM_WINDOWS && (ASIO_COMPILER_GCC || ASIO_COMPILER_CLANG) +#pragma pop_macro("cdecl") +#endif // ASIO_SYSTEM_WINDOWS && (ASIO_COMPILER_GCC || ASIO_COMPILER_CLANG) +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(pop) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +static_assert(sizeof(Callbacks) == (4 * sizeof(void (*)(void)))); + +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(push, 4) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +struct ClockSource { + Long index = 0; + Long associatedChannel = 0; + Long associatedGroup = 0; + Bool isCurrentSource = false; + CharBuf<32> name = nullptr; +}; +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(pop) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +static_assert(sizeof(ClockSource) == (SizeOfLong + SizeOfLong + SizeOfLong + SizeOfBool + 32)); + +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(push, 4) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +struct ChannelInfo { + Long channel = 0; + Bool isInput = false; + Bool isActive = false; + Long channelGroup = 0; + SampleType type = static_cast<SampleType>(0); + CharBuf<32> name = nullptr; +}; +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(pop) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +static_assert(sizeof(ChannelInfo) == (SizeOfLong + SizeOfBool + SizeOfBool + SizeOfLong + sizeof(SampleType) + 32)); + +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(push, 4) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +struct BufferInfo { + Bool isInput = false; + Long channelNum = 0; + void * buffers[2] = {nullptr, nullptr}; +}; +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(pop) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +static_assert(sizeof(BufferInfo) == (SizeOfBool + SizeOfLong + 2 * sizeof(void *))); + +enum class FutureSelector : Long { + EnableTimeCodeRead = 1, + DisableTimeCodeRead = 2, + SetInputMonitor = 3, + Transport = 4, + SetInputGain = 5, + GetInputMeter = 6, + SetOutputGain = 7, + GetOutputMeter = 8, + CanInputMonitor = 9, + CanTimeInfo = 10, + CanTimeCode = 11, + CanTransport = 12, + CanInputGain = 13, + CanInputMeter = 14, + CanOutputGain = 15, + CanOutputMeter = 16, + OptionalOne = 17, + SetIoFormat = 0x23111961, + GetIoFormat = 0x23111983, + CanDoIoFormat = 0x23112004, + CanReportOverload = 0x24042012, + GetInternalBufferSamples = 0x25042012, +}; +static_assert(sizeof(FutureSelector) == SizeOfLong); + +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(push, 4) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +struct InputMonitor { + Long input = 0; + Long output = 0; + Long gain = 0; + Bool state = false; + Long pan = 0; +}; +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(pop) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +static_assert(sizeof(InputMonitor) == (SizeOfLong + SizeOfLong + SizeOfLong + SizeOfBool + SizeOfLong)); + +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(push, 4) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +struct ChannelControls { + Long channel = 0; + Bool isInput = false; + Long gain = 0; + Long meter = 0; + Padding1 future[32] = {0}; +}; +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(pop) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +static_assert(sizeof(ChannelControls) == (SizeOfLong + SizeOfBool + SizeOfLong + SizeOfLong + 32)); + +enum class TransportCommand : Long { + Start = 1, + Stop = 2, + Locate = 3, + PunchIn = 4, + PunchOut = 5, + ArmOn = 6, + ArmOff = 7, + MonitorOn = 8, + MonitorOff = 9, + Arm = 10, + Monitor = 11, +}; +static_assert(sizeof(TransportCommand) == SizeOfLong); + +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(push, 4) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +struct TransportParameters { + TransportCommand command = static_cast<TransportCommand>(0); + HiLoLongLong samplePosition = 0; + Long track = 0; + Byte trackSwitches[64] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + Padding1 future[64] = {0}; +}; +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(pop) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +static_assert(sizeof(TransportParameters) == (sizeof(TransportCommand) + SizeOfLongLong + SizeOfLong + 64 + 64)); + +enum class IoFormatType : Long { + Invalid = -1, + PCM = 0, + DSD = 1, +}; +static_assert(sizeof(IoFormatType) == SizeOfLong); + +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(push, 4) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +struct IoFormat { + IoFormatType FormatType = static_cast<IoFormatType>(0); + Padding1 future[512 - sizeof(IoFormatType)] = {0}; +}; +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(pop) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +static_assert(sizeof(IoFormat) == 512); + +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(push, 4) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +struct InternalBufferInfo { + Long inputSamples = 0; + Long outputSamples = 0; +}; +#if ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +#pragma pack(pop) +#endif // ASIO_SYSTEM_WINDOWS && ASIO_HAVE_PRAGMA_PACK +static_assert(sizeof(InternalBufferInfo) == (SizeOfLong + SizeOfLong)); + + + +typedef ASIO_INTERFACE ISystemDriver ISystemDriver; + +using DriverName = CharBuf<32>; +using ErrorMessage = CharBuf<124>; + +#if ASIO_SYSTEM_WINDOWS && (ASIO_COMPILER_GCC || ASIO_COMPILER_CLANG) +#pragma push_macro("thiscall") +#ifdef thiscall +#undef thiscall +#endif +#endif // ASIO_SYSTEM_WINDOWS && (ASIO_COMPILER_GCC || ASIO_COMPILER_CLANG) +ASIO_INTERFACE ISystemDriver : public IUnknown { + [[nodiscard]] virtual ResultBool ASIO_DRIVERCALL init ASIO_ATTR_DRIVERCALL(SysHandle sysHandle) = 0; + virtual void ASIO_DRIVERCALL getDriverName ASIO_ATTR_DRIVERCALL(DriverName * name) = 0; + [[nodiscard]] virtual Long ASIO_DRIVERCALL getDriverVersion ASIO_ATTR_DRIVERCALL() = 0; + virtual void ASIO_DRIVERCALL getErrorMessage ASIO_ATTR_DRIVERCALL(ErrorMessage * string) = 0; + [[nodiscard]] virtual ErrorCode ASIO_DRIVERCALL start ASIO_ATTR_DRIVERCALL() = 0; + [[nodiscard]] virtual ErrorCode ASIO_DRIVERCALL stop ASIO_ATTR_DRIVERCALL() = 0; + [[nodiscard]] virtual ErrorCode ASIO_DRIVERCALL getChannels ASIO_ATTR_DRIVERCALL(Long * numInputChannels, Long * numOutputChannels) = 0; + [[nodiscard]] virtual ErrorCode ASIO_DRIVERCALL getLatencies ASIO_ATTR_DRIVERCALL(Long * inputLatency, Long * outputLatency) = 0; + [[nodiscard]] virtual ErrorCode ASIO_DRIVERCALL getBufferSize ASIO_ATTR_DRIVERCALL(Long * minSize, Long * maxSize, Long * preferredSize, Long * granularity) = 0; + [[nodiscard]] virtual ErrorCode ASIO_DRIVERCALL canSampleRate ASIO_ATTR_DRIVERCALL(SampleRate sampleRate) = 0; + [[nodiscard]] virtual ErrorCode ASIO_DRIVERCALL getSampleRate ASIO_ATTR_DRIVERCALL(SampleRate * sampleRate) = 0; + [[nodiscard]] virtual ErrorCode ASIO_DRIVERCALL setSampleRate ASIO_ATTR_DRIVERCALL(SampleRate sampleRate) = 0; + [[nodiscard]] virtual ErrorCode ASIO_DRIVERCALL getClockSources ASIO_ATTR_DRIVERCALL(ClockSource * clocks, Long * numSources) = 0; + [[nodiscard]] virtual ErrorCode ASIO_DRIVERCALL setClockSource ASIO_ATTR_DRIVERCALL(Long reference) = 0; + [[nodiscard]] virtual ErrorCode ASIO_DRIVERCALL getSamplePosition ASIO_ATTR_DRIVERCALL(HiLoLongLong * samplePosition, HiLoLongLong * timeStamp) = 0; + [[nodiscard]] virtual ErrorCode ASIO_DRIVERCALL getChannelInfo ASIO_ATTR_DRIVERCALL(ChannelInfo * info) = 0; + [[nodiscard]] virtual ErrorCode ASIO_DRIVERCALL createBuffers ASIO_ATTR_DRIVERCALL(BufferInfo * bufferInfos, Long numChannels, Long bufferSize, Callbacks const * callbacks) = 0; + [[nodiscard]] virtual ErrorCode ASIO_DRIVERCALL disposeBuffers ASIO_ATTR_DRIVERCALL() = 0; + [[nodiscard]] virtual ErrorCode ASIO_DRIVERCALL controlPanel ASIO_ATTR_DRIVERCALL() = 0; + [[nodiscard]] virtual ErrorCode ASIO_DRIVERCALL future ASIO_ATTR_DRIVERCALL(FutureSelector selector, void * opt) = 0; + [[nodiscard]] virtual ErrorCode ASIO_DRIVERCALL outputReady ASIO_ATTR_DRIVERCALL() = 0; +}; +#if ASIO_SYSTEM_WINDOWS && (ASIO_COMPILER_GCC || ASIO_COMPILER_CLANG) +#pragma pop_macro("thiscall") +#endif // ASIO_SYSTEM_WINDOWS && (ASIO_COMPILER_GCC || ASIO_COMPILER_CLANG) + + + +class IDriver { +protected: + IDriver() = default; + +public: + virtual ~IDriver() noexcept(false) { } + +public: + virtual void getDriverName(DriverName * name) = 0; + [[nodiscard]] virtual Long getDriverVersion() = 0; + virtual void getErrorMessage(ErrorMessage * string) = 0; + [[nodiscard]] virtual ErrorCode start() = 0; + [[nodiscard]] virtual ErrorCode stop() = 0; + [[nodiscard]] virtual ErrorCode getChannels(Long * numInputChannels, Long * numOutputChannels) = 0; + [[nodiscard]] virtual ErrorCode getLatencies(Long * inputLatency, Long * outputLatency) = 0; + [[nodiscard]] virtual ErrorCode getBufferSize(Long * minSize, Long * maxSize, Long * preferredSize, Long * granularity) = 0; + [[nodiscard]] virtual ErrorCode canSampleRate(SampleRate sampleRate) = 0; + [[nodiscard]] virtual ErrorCode getSampleRate(SampleRate * sampleRate) = 0; + [[nodiscard]] virtual ErrorCode setSampleRate(SampleRate sampleRate) = 0; + [[nodiscard]] virtual ErrorCode getClockSources(ClockSource * clocks, Long * numSources) = 0; + [[nodiscard]] virtual ErrorCode setClockSource(Long reference) = 0; + [[nodiscard]] virtual ErrorCode getSamplePosition(HiLoLongLong * samplePosition, HiLoLongLong * timeStamp) = 0; + [[nodiscard]] virtual ErrorCode getChannelInfo(ChannelInfo * info) = 0; + [[nodiscard]] virtual ErrorCode createBuffers(BufferInfo * bufferInfos, Long numChannels, Long bufferSize, Callbacks const * callbacks) = 0; + [[nodiscard]] virtual ErrorCode disposeBuffers() = 0; + [[nodiscard]] virtual ErrorCode controlPanel() = 0; + [[nodiscard]] virtual ErrorCode future(FutureSelector selector, void * opt) = 0; + [[nodiscard]] virtual ErrorCode outputReady() = 0; +}; + + + +} // namespace ASIO_VERSION_NAMESPACE + + + +} // namespace Core + + + +} // namespace ASIO + + + +#endif // ASIO_ASIOCORE_HPP diff --git a/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOModern.hpp b/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOModern.hpp new file mode 100644 index 00000000..0413bed2 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOModern.hpp @@ -0,0 +1,960 @@ + +#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 diff --git a/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOSampleConvert.hpp b/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOSampleConvert.hpp new file mode 100644 index 00000000..106a6a20 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOSampleConvert.hpp @@ -0,0 +1,1100 @@ + +#ifndef ASIO_ASIOSAMPLECONVERT_HPP +#define ASIO_ASIOSAMPLECONVERT_HPP + + + +#include "ASIOVersion.hpp" +#include "ASIOConfig.hpp" +#include "ASIOCore.hpp" + +#include <algorithm> +#include <array> +#include <limits> +#include <type_traits> + +#include "ASIOstdcxx20bit.hpp" + +#include <cassert> +#include <cmath> +#include <cstddef> +#include <cstdint> + + + +namespace ASIO { + + + +namespace Sample { + + + +inline namespace ASIO_VERSION_NAMESPACE { + + + +namespace detail { + + + +template <typename Type> +struct TraitsExternal { }; + +template <> +struct TraitsExternal<std::int8_t> { + using type = std::int8_t; + using internal_type = std::int64_t; + static constexpr internal_type scale = static_cast<internal_type>(1) << 24; +}; +template <> +struct TraitsExternal<std::int16_t> { + using type = std::int16_t; + using internal_type = std::int64_t; + static constexpr internal_type scale = static_cast<internal_type>(1) << 16; +}; +template <> +struct TraitsExternal<std::int32_t> { + using type = std::int32_t; + using internal_type = std::int64_t; + static constexpr internal_type scale = static_cast<internal_type>(1) << 0; +}; +template <> +struct TraitsExternal<float> { + using type = float; + using internal_type = float; +}; +template <> +struct TraitsExternal<double> { + using type = double; + using internal_type = double; +}; +template <> +struct TraitsExternal<long double> { + using type = long double; + using internal_type = double; +}; + + + +struct Int16MSB { + std::array<std::byte, 2> data; +}; +struct Int24MSB { + std::array<std::byte, 3> data; +}; +struct Int32MSB { + std::array<std::byte, 4> data; +}; +struct Int32MSB16 { + std::array<std::byte, 4> data; +}; +struct Int32MSB18 { + std::array<std::byte, 4> data; +}; +struct Int32MSB20 { + std::array<std::byte, 4> data; +}; +struct Int32MSB24 { + std::array<std::byte, 4> data; +}; +struct Float32MSB { + std::array<std::byte, 4> data; +}; +struct Float64MSB { + std::array<std::byte, 8> data; +}; + +struct Int16LSB { + std::array<std::byte, 2> data; +}; +struct Int24LSB { + std::array<std::byte, 3> data; +}; +struct Int32LSB { + std::array<std::byte, 4> data; +}; +struct Int32LSB16 { + std::array<std::byte, 4> data; +}; +struct Int32LSB18 { + std::array<std::byte, 4> data; +}; +struct Int32LSB20 { + std::array<std::byte, 4> data; +}; +struct Int32LSB24 { + std::array<std::byte, 4> data; +}; +struct Float32LSB { + std::array<std::byte, 4> data; +}; +struct Float64LSB { + std::array<std::byte, 8> data; +}; + + + +template <typename Type> +struct Types { }; + +template <> +struct Types<detail::Int16MSB> { + using type = detail::Int16MSB; + static constexpr SampleType sample_type = SampleType::Int16MSB; + using internal_type = std::int64_t; + using value_type = std::int16_t; + using unsigned_type = std::make_unsigned<value_type>::type; + static constexpr std::size_t valid_bits = 16; + static constexpr bool is_float = std::is_floating_point<value_type>::value; + static constexpr bool is_be = true; +}; +template <> +struct Types<detail::Int24MSB> { + using type = detail::Int24MSB; + static constexpr SampleType sample_type = SampleType::Int24MSB; + using internal_type = std::int64_t; + using value_type = std::int32_t; + using unsigned_type = std::make_unsigned<value_type>::type; + static constexpr std::size_t valid_bits = 24; + static constexpr bool is_float = std::is_floating_point<value_type>::value; + static constexpr bool is_be = true; +}; +template <> +struct Types<detail::Int32MSB> { + using type = detail::Int32MSB; + static constexpr SampleType sample_type = SampleType::Int32MSB; + using internal_type = std::int64_t; + using value_type = std::int32_t; + using unsigned_type = std::make_unsigned<value_type>::type; + static constexpr std::size_t valid_bits = 32; + static constexpr bool is_float = std::is_floating_point<value_type>::value; + static constexpr bool is_be = true; +}; +template <> +struct Types<detail::Int32MSB16> { + using type = detail::Int32MSB16; + static constexpr SampleType sample_type = SampleType::Int32MSB16; + using internal_type = std::int64_t; + using value_type = std::int32_t; + using unsigned_type = std::make_unsigned<value_type>::type; + static constexpr std::size_t valid_bits = 16; + static constexpr bool is_float = std::is_floating_point<value_type>::value; + static constexpr bool is_be = true; +}; +template <> +struct Types<detail::Int32MSB18> { + using type = detail::Int32MSB18; + static constexpr SampleType sample_type = SampleType::Int32MSB18; + using internal_type = std::int64_t; + using value_type = std::int32_t; + using unsigned_type = std::make_unsigned<value_type>::type; + static constexpr std::size_t valid_bits = 18; + static constexpr bool is_float = std::is_floating_point<value_type>::value; + static constexpr bool is_be = true; +}; +template <> +struct Types<detail::Int32MSB20> { + using type = detail::Int32MSB20; + static constexpr SampleType sample_type = SampleType::Int32MSB20; + using internal_type = std::int64_t; + using value_type = std::int32_t; + using unsigned_type = std::make_unsigned<value_type>::type; + static constexpr std::size_t valid_bits = 20; + static constexpr bool is_float = std::is_floating_point<value_type>::value; + static constexpr bool is_be = true; +}; +template <> +struct Types<detail::Int32MSB24> { + using type = detail::Int32MSB24; + static constexpr SampleType sample_type = SampleType::Int32MSB24; + using internal_type = std::int64_t; + using value_type = std::int32_t; + using unsigned_type = std::make_unsigned<value_type>::type; + static constexpr std::size_t valid_bits = 24; + static constexpr bool is_float = std::is_floating_point<value_type>::value; + static constexpr bool is_be = true; +}; +template <> +struct Types<detail::Float32MSB> { + using type = detail::Float32MSB; + static constexpr SampleType sample_type = SampleType::Float32MSB; + using internal_type = float; + using value_type = float; + using unsigned_type = float; + static constexpr std::size_t valid_bits = 32; + static constexpr bool is_float = std::is_floating_point<value_type>::value; + static constexpr bool is_be = true; +}; +template <> +struct Types<detail::Float64MSB> { + using type = detail::Float64MSB; + static constexpr SampleType sample_type = SampleType::Float64MSB; + using internal_type = double; + using value_type = double; + using unsigned_type = double; + static constexpr std::size_t valid_bits = 64; + static constexpr bool is_float = std::is_floating_point<value_type>::value; + static constexpr bool is_be = true; +}; + +template <> +struct Types<detail::Int16LSB> { + using type = detail::Int16LSB; + static constexpr SampleType sample_type = SampleType::Int16MSB; + using internal_type = std::int64_t; + using value_type = std::int16_t; + using unsigned_type = std::make_unsigned<value_type>::type; + static constexpr std::size_t valid_bits = 16; + static constexpr bool is_float = std::is_floating_point<value_type>::value; + static constexpr bool is_be = false; +}; +template <> +struct Types<detail::Int24LSB> { + using type = detail::Int24LSB; + static constexpr SampleType sample_type = SampleType::Int24LSB; + using internal_type = std::int64_t; + using value_type = std::int32_t; + using unsigned_type = std::make_unsigned<value_type>::type; + static constexpr std::size_t valid_bits = 24; + static constexpr bool is_float = std::is_floating_point<value_type>::value; + static constexpr bool is_be = false; +}; +template <> +struct Types<detail::Int32LSB> { + using type = detail::Int32LSB; + static constexpr SampleType sample_type = SampleType::Int32LSB; + using internal_type = std::int64_t; + using value_type = std::int32_t; + using unsigned_type = std::make_unsigned<value_type>::type; + static constexpr std::size_t valid_bits = 32; + static constexpr bool is_float = std::is_floating_point<value_type>::value; + static constexpr bool is_be = false; +}; +template <> +struct Types<detail::Int32LSB16> { + using type = detail::Int32LSB16; + static constexpr SampleType sample_type = SampleType::Int32LSB16; + using internal_type = std::int64_t; + using value_type = std::int32_t; + using unsigned_type = std::make_unsigned<value_type>::type; + static constexpr std::size_t valid_bits = 16; + static constexpr bool is_float = std::is_floating_point<value_type>::value; + static constexpr bool is_be = false; +}; +template <> +struct Types<detail::Int32LSB18> { + using type = detail::Int32LSB18; + static constexpr SampleType sample_type = SampleType::Int32LSB18; + using internal_type = std::int64_t; + using value_type = std::int32_t; + using unsigned_type = std::make_unsigned<value_type>::type; + static constexpr std::size_t valid_bits = 18; + static constexpr bool is_float = std::is_floating_point<value_type>::value; + static constexpr bool is_be = false; +}; +template <> +struct Types<detail::Int32LSB20> { + using type = detail::Int32LSB20; + static constexpr SampleType sample_type = SampleType::Int32LSB20; + using internal_type = std::int64_t; + using value_type = std::int32_t; + using unsigned_type = std::make_unsigned<value_type>::type; + static constexpr std::size_t valid_bits = 20; + static constexpr bool is_float = std::is_floating_point<value_type>::value; + static constexpr bool is_be = false; +}; +template <> +struct Types<detail::Int32LSB24> { + using type = detail::Int32LSB24; + static constexpr SampleType sample_type = SampleType::Int32LSB24; + using internal_type = std::int64_t; + using value_type = std::int32_t; + using unsigned_type = std::make_unsigned<value_type>::type; + static constexpr std::size_t valid_bits = 24; + static constexpr bool is_float = std::is_floating_point<value_type>::value; + static constexpr bool is_be = false; +}; +template <> +struct Types<detail::Float32LSB> { + using type = detail::Float32LSB; + static constexpr SampleType sample_type = SampleType::Float32LSB; + using internal_type = float; + using value_type = float; + using unsigned_type = float; + static constexpr std::size_t valid_bits = 32; + static constexpr bool is_float = std::is_floating_point<value_type>::value; + static constexpr bool is_be = false; +}; +template <> +struct Types<detail::Float64LSB> { + using type = detail::Float64LSB; + static constexpr SampleType sample_type = SampleType::Float64LSB; + using internal_type = double; + using value_type = double; + using unsigned_type = double; + static constexpr std::size_t valid_bits = 64; + static constexpr bool is_float = std::is_floating_point<value_type>::value; + static constexpr bool is_be = false; +}; + + + +template <typename T> +constexpr T clip(T x) noexcept = delete; +template <> +constexpr std::int64_t clip<std::int64_t>(std::int64_t q32) noexcept { + return std::clamp(q32, static_cast<std::int64_t>(std::numeric_limits<std::int32_t>::min()), static_cast<std::int64_t>(std::numeric_limits<std::int32_t>::max())); +} +template <> +constexpr double clip<double>(double dbl) noexcept { + return std::clamp(dbl, -1.0, 1.0); +} +template <> +constexpr float clip<float>(float flt) noexcept { + return std::clamp(flt, -1.0f, 1.0f); +} + + + +template <typename Tdst, typename Tsrc> +inline Tdst convert_internal(Tsrc x) noexcept = delete; +template <> +inline std::int64_t convert_internal<std::int64_t, std::int64_t>(std::int64_t q32) noexcept { + return q32; +} +template <> +inline std::int64_t convert_internal<std::int64_t, double>(double dbl) noexcept { + return std::llround(dbl * static_cast<double>(1ll << 32)); +} +template <> +inline std::int64_t convert_internal<std::int64_t, float>(float flt) noexcept { + return std::llround(flt * static_cast<float>(1ll << 32)); +} +template <> +inline double convert_internal<double, std::int64_t>(std::int64_t q32) noexcept { + return static_cast<double>(q32) * (1.0 / static_cast<double>(1ll << 32)); +} +template <> +inline double convert_internal<double, double>(double dbl) noexcept { + return dbl; +} +template <> +inline double convert_internal<double, float>(float flt) noexcept { + return static_cast<double>(flt); +} +template <> +inline float convert_internal<float, std::int64_t>(std::int64_t q32) noexcept { + return static_cast<float>(q32) * (1.0f / static_cast<float>(1ll << 32)); +} +template <> +inline float convert_internal<float, double>(double dbl) noexcept { + return static_cast<float>(dbl); +} +template <> +inline float convert_internal<float, float>(float flt) noexcept { + return flt; +} + + + +template <typename SampleType> +inline SampleType sample_from_value(typename Types<SampleType>::value_type val) noexcept { + if constexpr (Types<SampleType>::is_float) { + static_assert(sizeof(SampleType) == sizeof(typename Types<SampleType>::value_type)); + static_assert((stdcxx20::endian::native == stdcxx20::endian::little) || (stdcxx20::endian::native == stdcxx20::endian::big)); + SampleType result = stdcxx20::bit_cast<SampleType>(val); + if constexpr (Types<SampleType>::is_be) { + if constexpr (stdcxx20::endian::native == stdcxx20::endian::little) { + std::reverse(std::begin(result.data), std::end(result.data)); + } + } else { + if constexpr (stdcxx20::endian::native == stdcxx20::endian::big) { + std::reverse(std::begin(result.data), std::end(result.data)); + } + } + return result; + } else { + SampleType result{}; + typename Types<SampleType>::unsigned_type uval = static_cast<typename Types<SampleType>::unsigned_type>(val); + for (std::size_t byte = 0; byte < sizeof(SampleType); ++byte) { + if constexpr (Types<SampleType>::is_be) { + result.data[sizeof(SampleType) - 1 - byte] = std::byte{static_cast<std::uint8_t>(uval)}; + } else { + result.data[byte] = std::byte{static_cast<std::uint8_t>(uval)}; + } + uval /= (1u << 8); + } + return result; + } +} + +template <typename SampleType> +inline typename Types<SampleType>::value_type value_from_sample(SampleType smp) noexcept { + if constexpr (Types<SampleType>::is_float) { + static_assert(sizeof(SampleType) == sizeof(typename Types<SampleType>::value_type)); + static_assert((stdcxx20::endian::native == stdcxx20::endian::little) || (stdcxx20::endian::native == stdcxx20::endian::big)); + if constexpr (Types<SampleType>::is_be) { + if constexpr (stdcxx20::endian::native == stdcxx20::endian::little) { + std::reverse(std::begin(smp.data), std::end(smp.data)); + } + } else { + if constexpr (stdcxx20::endian::native == stdcxx20::endian::big) { + std::reverse(std::begin(smp.data), std::end(smp.data)); + } + } + return stdcxx20::bit_cast<typename Types<SampleType>::value_type>(smp.data); + } else { + typename Types<SampleType>::unsigned_type uval = 0; + for (std::size_t byte = 0; byte < sizeof(SampleType); ++byte) { + uval *= (1u << 8); + if constexpr (Types<SampleType>::is_be) { + uval |= std::to_integer<std::uint8_t>(smp.data[byte]); + } else { + uval |= std::to_integer<std::uint8_t>(smp.data[sizeof(SampleType) - 1 - byte]); + } + } + return static_cast<typename Types<SampleType>::value_type>(uval); + } +} + + + +template <typename SampleType> +inline typename Types<SampleType>::value_type value_from_internal(typename Types<SampleType>::internal_type smp_int) noexcept { + if constexpr (Types<SampleType>::is_float) { + return static_cast<typename Types<SampleType>::value_type>(smp_int); + } else { + return static_cast<typename Types<SampleType>::value_type>(clip(smp_int) / (static_cast<typename Types<SampleType>::internal_type>(1) << (32 - Types<SampleType>::valid_bits))); + } +} + +template <typename SampleType> +inline typename Types<SampleType>::internal_type internal_from_value(typename Types<SampleType>::value_type val) noexcept { + if constexpr (Types<SampleType>::is_float) { + return static_cast<typename Types<SampleType>::internal_type>(val); + } else { + return clip(static_cast<typename Types<SampleType>::internal_type>(val) * (static_cast<typename Types<SampleType>::internal_type>(1) << (32 - Types<SampleType>::valid_bits))); + } +} + + + +template <typename ExternalType> +inline typename TraitsExternal<ExternalType>::internal_type internal_from_external(ExternalType x) noexcept { + static_assert(std::is_floating_point<typename TraitsExternal<ExternalType>::internal_type>::value == std::is_floating_point<ExternalType>::value); + if constexpr (std::is_floating_point<ExternalType>::value) { + return static_cast<typename TraitsExternal<ExternalType>::internal_type>(x); + } else { + return static_cast<typename TraitsExternal<ExternalType>::internal_type>(x) * TraitsExternal<ExternalType>::scale; + } +} + +template <typename ExternalType> +inline ExternalType external_from_internal(typename TraitsExternal<ExternalType>::internal_type x) noexcept { + static_assert(std::is_floating_point<typename TraitsExternal<ExternalType>::internal_type>::value == std::is_floating_point<ExternalType>::value); + if constexpr (std::is_floating_point<ExternalType>::value) { + return static_cast<ExternalType>(x); + } else { + return static_cast<ExternalType>(clip(x) / TraitsExternal<ExternalType>::scale); + } +} + + + +template <typename SampleType, typename ExternalType> +inline SampleType sample_from_external(ExternalType x) noexcept { + return sample_from_value<SampleType>(value_from_internal<SampleType>(convert_internal<typename Types<SampleType>::internal_type, typename TraitsExternal<ExternalType>::internal_type>(internal_from_external<ExternalType>(x)))); +} + +template <typename ExternalType, typename SampleType> +inline ExternalType external_from_sample(SampleType x) noexcept { + return external_from_internal<ExternalType>(convert_internal<typename TraitsExternal<ExternalType>::internal_type, typename Types<SampleType>::internal_type>(internal_from_value<SampleType>(value_from_sample<SampleType>(x)))); +} + + + +template <typename Tdst> +inline void ClearBuffer(Tdst * dst, std::size_t dst_stride, std::size_t count) noexcept { + for (std::size_t i = 0; i < count; ++i) + { + Tdst val{}; + std::fill(val.data.begin(), val.data.end(), std::byte{0}); + *dst = val; + dst += dst_stride; + } +} + + + +template <typename Tdst, typename Tsrc, typename Tfunc> +inline void ConvertBuffer(Tdst * dst, std::size_t dst_stride, const Tsrc * src, std::size_t src_stride, std::size_t count, Tfunc func) noexcept(noexcept(func(Tsrc()))) { + for (std::size_t i = 0; i < count; ++i) + { + *dst = func(*src); + src += src_stride; + dst += dst_stride; + } +} + + + +} // namespace detail + + + +inline void ClearBufferASIO(void * dst, SampleType type, std::size_t count) noexcept { + switch (type) { + case SampleType::Int16MSB: + { + using SampleType = detail::Int16MSB; + detail::ClearBuffer(static_cast<SampleType *>(dst), 1, count); + } + break; + case SampleType::Int16LSB: + { + using SampleType = detail::Int16LSB; + detail::ClearBuffer(static_cast<SampleType *>(dst), 1, count); + } + break; + case SampleType::Int24MSB: + { + using SampleType = detail::Int24MSB; + detail::ClearBuffer(static_cast<SampleType *>(dst), 1, count); + } + break; + case SampleType::Int24LSB: + { + using SampleType = detail::Int24LSB; + detail::ClearBuffer(static_cast<SampleType *>(dst), 1, count); + } + break; + case SampleType::Int32MSB: + { + using SampleType = detail::Int32MSB; + detail::ClearBuffer(static_cast<SampleType *>(dst), 1, count); + } + break; + case SampleType::Int32LSB: + { + using SampleType = detail::Int32LSB; + detail::ClearBuffer(static_cast<SampleType *>(dst), 1, count); + } + break; + case SampleType::Float32MSB: + { + using SampleType = detail::Float32MSB; + detail::ClearBuffer(static_cast<SampleType *>(dst), 1, count); + } + break; + case SampleType::Float32LSB: + { + using SampleType = detail::Float32LSB; + detail::ClearBuffer(static_cast<SampleType *>(dst), 1, count); + } + break; + case SampleType::Float64MSB: + { + using SampleType = detail::Float64MSB; + detail::ClearBuffer(static_cast<SampleType *>(dst), 1, count); + } + break; + case SampleType::Float64LSB: + { + using SampleType = detail::Float64LSB; + detail::ClearBuffer(static_cast<SampleType *>(dst), 1, count); + } + break; + case SampleType::Int32MSB16: + { + using SampleType = detail::Int32MSB16; + detail::ClearBuffer(static_cast<SampleType *>(dst), 1, count); + } + break; + case SampleType::Int32LSB16: + { + using SampleType = detail::Int32LSB16; + detail::ClearBuffer(static_cast<SampleType *>(dst), 1, count); + } + break; + case SampleType::Int32MSB18: + { + using SampleType = detail::Int32MSB18; + detail::ClearBuffer(static_cast<SampleType *>(dst), 1, count); + } + break; + case SampleType::Int32LSB18: + { + using SampleType = detail::Int32LSB18; + detail::ClearBuffer(static_cast<SampleType *>(dst), 1, count); + } + break; + case SampleType::Int32MSB20: + { + using SampleType = detail::Int32MSB20; + detail::ClearBuffer(static_cast<SampleType *>(dst), 1, count); + } + break; + case SampleType::Int32LSB20: + { + using SampleType = detail::Int32LSB20; + detail::ClearBuffer(static_cast<SampleType *>(dst), 1, count); + } + break; + case SampleType::Int32MSB24: + { + using SampleType = detail::Int32MSB24; + detail::ClearBuffer(static_cast<SampleType *>(dst), 1, count); + } + break; + case SampleType::Int32LSB24: + { + using SampleType = detail::Int32LSB24; + detail::ClearBuffer(static_cast<SampleType *>(dst), 1, count); + } + break; + default: + assert(false); + break; + } +} + + +template <typename Tdst> +inline void CopyRawFromASIO(Tdst * dst, std::size_t dst_stride, const void * src, std::size_t count) noexcept { + detail::ConvertBuffer(dst, dst_stride, static_cast<const Tdst *>(src), 1, count, [](Tdst smp) { return smp; }); +} + +template <typename Tsrc> +inline void CopyRawToASIO(void * dst, const Tsrc * src, std::size_t src_stride, std::size_t count) noexcept { + detail::ConvertBuffer(static_cast<Tsrc *>(dst), 1, src, src_stride, count, [](Tsrc smp) { return smp; }); +} + + + +template <typename Tdst> +inline void ConvertFromASIO(Tdst * dst, std::size_t dst_stride, SampleType type, const void * src, std::size_t count) noexcept { + switch (type) { + case SampleType::Int16MSB: + { + using SampleType = detail::Int16MSB; + detail::ConvertBuffer(dst, dst_stride, static_cast<const SampleType *>(src), 1, count, [](SampleType smp) { return detail::external_from_sample<Tdst, SampleType>(smp); }); + } + break; + case SampleType::Int16LSB: + { + using SampleType = detail::Int16LSB; + detail::ConvertBuffer(dst, dst_stride, static_cast<const SampleType *>(src), 1, count, [](SampleType smp) { return detail::external_from_sample<Tdst, SampleType>(smp); }); + } + break; + case SampleType::Int24MSB: + { + using SampleType = detail::Int24MSB; + detail::ConvertBuffer(dst, dst_stride, static_cast<const SampleType *>(src), 1, count, [](SampleType smp) { return detail::external_from_sample<Tdst, SampleType>(smp); }); + } + break; + case SampleType::Int24LSB: + { + using SampleType = detail::Int24LSB; + detail::ConvertBuffer(dst, dst_stride, static_cast<const SampleType *>(src), 1, count, [](SampleType smp) { return detail::external_from_sample<Tdst, SampleType>(smp); }); + } + break; + case SampleType::Int32MSB: + { + using SampleType = detail::Int32MSB; + detail::ConvertBuffer(dst, dst_stride, static_cast<const SampleType *>(src), 1, count, [](SampleType smp) { return detail::external_from_sample<Tdst, SampleType>(smp); }); + } + break; + case SampleType::Int32LSB: + { + using SampleType = detail::Int32LSB; + detail::ConvertBuffer(dst, dst_stride, static_cast<const SampleType *>(src), 1, count, [](SampleType smp) { return detail::external_from_sample<Tdst, SampleType>(smp); }); + } + break; + case SampleType::Float32MSB: + { + using SampleType = detail::Float32MSB; + detail::ConvertBuffer(dst, dst_stride, static_cast<const SampleType *>(src), 1, count, [](SampleType smp) { return detail::external_from_sample<Tdst, SampleType>(smp); }); + } + break; + case SampleType::Float32LSB: + { + using SampleType = detail::Float32LSB; + detail::ConvertBuffer(dst, dst_stride, static_cast<const SampleType *>(src), 1, count, [](SampleType smp) { return detail::external_from_sample<Tdst, SampleType>(smp); }); + } + break; + case SampleType::Float64MSB: + { + using SampleType = detail::Float64MSB; + detail::ConvertBuffer(dst, dst_stride, static_cast<const SampleType *>(src), 1, count, [](SampleType smp) { return detail::external_from_sample<Tdst, SampleType>(smp); }); + } + break; + case SampleType::Float64LSB: + { + using SampleType = detail::Float64LSB; + detail::ConvertBuffer(dst, dst_stride, static_cast<const SampleType *>(src), 1, count, [](SampleType smp) { return detail::external_from_sample<Tdst, SampleType>(smp); }); + } + break; + case SampleType::Int32MSB16: + { + using SampleType = detail::Int32MSB16; + detail::ConvertBuffer(dst, dst_stride, static_cast<const SampleType *>(src), 1, count, [](SampleType smp) { return detail::external_from_sample<Tdst, SampleType>(smp); }); + } + break; + case SampleType::Int32LSB16: + { + using SampleType = detail::Int32LSB16; + detail::ConvertBuffer(dst, dst_stride, static_cast<const SampleType *>(src), 1, count, [](SampleType smp) { return detail::external_from_sample<Tdst, SampleType>(smp); }); + } + break; + case SampleType::Int32MSB18: + { + using SampleType = detail::Int32MSB18; + detail::ConvertBuffer(dst, dst_stride, static_cast<const SampleType *>(src), 1, count, [](SampleType smp) { return detail::external_from_sample<Tdst, SampleType>(smp); }); + } + break; + case SampleType::Int32LSB18: + { + using SampleType = detail::Int32LSB18; + detail::ConvertBuffer(dst, dst_stride, static_cast<const SampleType *>(src), 1, count, [](SampleType smp) { return detail::external_from_sample<Tdst, SampleType>(smp); }); + } + break; + case SampleType::Int32MSB20: + { + using SampleType = detail::Int32MSB20; + detail::ConvertBuffer(dst, dst_stride, static_cast<const SampleType *>(src), 1, count, [](SampleType smp) { return detail::external_from_sample<Tdst, SampleType>(smp); }); + } + break; + case SampleType::Int32LSB20: + { + using SampleType = detail::Int32LSB20; + detail::ConvertBuffer(dst, dst_stride, static_cast<const SampleType *>(src), 1, count, [](SampleType smp) { return detail::external_from_sample<Tdst, SampleType>(smp); }); + } + break; + case SampleType::Int32MSB24: + { + using SampleType = detail::Int32MSB24; + detail::ConvertBuffer(dst, dst_stride, static_cast<const SampleType *>(src), 1, count, [](SampleType smp) { return detail::external_from_sample<Tdst, SampleType>(smp); }); + } + break; + case SampleType::Int32LSB24: + { + using SampleType = detail::Int32LSB24; + detail::ConvertBuffer(dst, dst_stride, static_cast<const SampleType *>(src), 1, count, [](SampleType smp) { return detail::external_from_sample<Tdst, SampleType>(smp); }); + } + break; + default: + assert(false); + break; + } +} + +template <typename Tsrc> +inline void ConvertToASIO(void * dst, SampleType type, const Tsrc * src, std::size_t src_stride, std::size_t count) noexcept { + switch (type) { + case SampleType::Int16MSB: + { + using SampleType = detail::Int16MSB; + detail::ConvertBuffer(static_cast<SampleType *>(dst), 1, src, src_stride, count, [](Tsrc smp) { return detail::sample_from_external<SampleType, Tsrc>(smp); }); + } + break; + case SampleType::Int16LSB: + { + using SampleType = detail::Int16LSB; + detail::ConvertBuffer(static_cast<SampleType *>(dst), 1, src, src_stride, count, [](Tsrc smp) { return detail::sample_from_external<SampleType, Tsrc>(smp); }); + } + break; + case SampleType::Int24MSB: + { + using SampleType = detail::Int24MSB; + detail::ConvertBuffer(static_cast<SampleType *>(dst), 1, src, src_stride, count, [](Tsrc smp) { return detail::sample_from_external<SampleType, Tsrc>(smp); }); + } + break; + case SampleType::Int24LSB: + { + using SampleType = detail::Int24LSB; + detail::ConvertBuffer(static_cast<SampleType *>(dst), 1, src, src_stride, count, [](Tsrc smp) { return detail::sample_from_external<SampleType, Tsrc>(smp); }); + } + break; + case SampleType::Int32MSB: + { + using SampleType = detail::Int32MSB; + detail::ConvertBuffer(static_cast<SampleType *>(dst), 1, src, src_stride, count, [](Tsrc smp) { return detail::sample_from_external<SampleType, Tsrc>(smp); }); + } + break; + case SampleType::Int32LSB: + { + using SampleType = detail::Int32LSB; + detail::ConvertBuffer(static_cast<SampleType *>(dst), 1, src, src_stride, count, [](Tsrc smp) { return detail::sample_from_external<SampleType, Tsrc>(smp); }); + } + break; + case SampleType::Float32MSB: + { + using SampleType = detail::Float32MSB; + detail::ConvertBuffer(static_cast<SampleType *>(dst), 1, src, src_stride, count, [](Tsrc smp) { return detail::sample_from_external<SampleType, Tsrc>(smp); }); + } + break; + case SampleType::Float32LSB: + { + using SampleType = detail::Float32LSB; + detail::ConvertBuffer(static_cast<SampleType *>(dst), 1, src, src_stride, count, [](Tsrc smp) { return detail::sample_from_external<SampleType, Tsrc>(smp); }); + } + break; + case SampleType::Float64MSB: + { + using SampleType = detail::Float64MSB; + detail::ConvertBuffer(static_cast<SampleType *>(dst), 1, src, src_stride, count, [](Tsrc smp) { return detail::sample_from_external<SampleType, Tsrc>(smp); }); + } + break; + case SampleType::Float64LSB: + { + using SampleType = detail::Float64LSB; + detail::ConvertBuffer(static_cast<SampleType *>(dst), 1, src, src_stride, count, [](Tsrc smp) { return detail::sample_from_external<SampleType, Tsrc>(smp); }); + } + break; + case SampleType::Int32MSB16: + { + using SampleType = detail::Int32MSB16; + detail::ConvertBuffer(static_cast<SampleType *>(dst), 1, src, src_stride, count, [](Tsrc smp) { return detail::sample_from_external<SampleType, Tsrc>(smp); }); + } + break; + case SampleType::Int32LSB16: + { + using SampleType = detail::Int32LSB16; + detail::ConvertBuffer(static_cast<SampleType *>(dst), 1, src, src_stride, count, [](Tsrc smp) { return detail::sample_from_external<SampleType, Tsrc>(smp); }); + } + break; + case SampleType::Int32MSB18: + { + using SampleType = detail::Int32MSB18; + detail::ConvertBuffer(static_cast<SampleType *>(dst), 1, src, src_stride, count, [](Tsrc smp) { return detail::sample_from_external<SampleType, Tsrc>(smp); }); + } + break; + case SampleType::Int32LSB18: + { + using SampleType = detail::Int32LSB18; + detail::ConvertBuffer(static_cast<SampleType *>(dst), 1, src, src_stride, count, [](Tsrc smp) { return detail::sample_from_external<SampleType, Tsrc>(smp); }); + } + break; + case SampleType::Int32MSB20: + { + using SampleType = detail::Int32MSB20; + detail::ConvertBuffer(static_cast<SampleType *>(dst), 1, src, src_stride, count, [](Tsrc smp) { return detail::sample_from_external<SampleType, Tsrc>(smp); }); + } + break; + case SampleType::Int32LSB20: + { + using SampleType = detail::Int32LSB20; + detail::ConvertBuffer(static_cast<SampleType *>(dst), 1, src, src_stride, count, [](Tsrc smp) { return detail::sample_from_external<SampleType, Tsrc>(smp); }); + } + break; + case SampleType::Int32MSB24: + { + using SampleType = detail::Int32MSB24; + detail::ConvertBuffer(static_cast<SampleType *>(dst), 1, src, src_stride, count, [](Tsrc smp) { return detail::sample_from_external<SampleType, Tsrc>(smp); }); + } + break; + case SampleType::Int32LSB24: + { + using SampleType = detail::Int32LSB24; + detail::ConvertBuffer(static_cast<SampleType *>(dst), 1, src, src_stride, count, [](Tsrc smp) { return detail::sample_from_external<SampleType, Tsrc>(smp); }); + } + break; + default: + assert(false); + break; + } +} + + + +struct Traits { + std::size_t size_bytes = 0; + std::size_t valid_bits = 0; + bool is_float = false; + bool is_be = false; + constexpr explicit Traits(SampleType type) noexcept { + switch (type) { + case SampleType::Int16MSB: + { + using Type = detail::Types<detail::Int16MSB>; + size_bytes = sizeof(Type::type); + valid_bits = Type::valid_bits; + is_float = Type::is_float; + is_be = Type::is_be; + } + break; + case SampleType::Int24MSB: + { + using Type = detail::Types<detail::Int24MSB>; + size_bytes = sizeof(Type::type); + valid_bits = Type::valid_bits; + is_float = Type::is_float; + is_be = Type::is_be; + } + break; + case SampleType::Int32MSB: + { + using Type = detail::Types<detail::Int32MSB>; + size_bytes = sizeof(Type::type); + valid_bits = Type::valid_bits; + is_float = Type::is_float; + is_be = Type::is_be; + } + break; + case SampleType::Float32MSB: + { + using Type = detail::Types<detail::Float32MSB>; + size_bytes = sizeof(Type::type); + valid_bits = Type::valid_bits; + is_float = Type::is_float; + is_be = Type::is_be; + } + break; + case SampleType::Float64MSB: + { + using Type = detail::Types<detail::Float64MSB>; + size_bytes = sizeof(Type::type); + valid_bits = Type::valid_bits; + is_float = Type::is_float; + is_be = Type::is_be; + } + break; + case SampleType::Int32MSB16: + { + using Type = detail::Types<detail::Int32MSB16>; + size_bytes = sizeof(Type::type); + valid_bits = Type::valid_bits; + is_float = Type::is_float; + is_be = Type::is_be; + } + break; + case SampleType::Int32MSB18: + { + using Type = detail::Types<detail::Int32MSB18>; + size_bytes = sizeof(Type::type); + valid_bits = Type::valid_bits; + is_float = Type::is_float; + is_be = Type::is_be; + } + break; + case SampleType::Int32MSB20: + { + using Type = detail::Types<detail::Int32MSB20>; + size_bytes = sizeof(Type::type); + valid_bits = Type::valid_bits; + is_float = Type::is_float; + is_be = Type::is_be; + } + break; + case SampleType::Int32MSB24: + { + using Type = detail::Types<detail::Int32MSB24>; + size_bytes = sizeof(Type::type); + valid_bits = Type::valid_bits; + is_float = Type::is_float; + is_be = Type::is_be; + } + break; + case SampleType::Int16LSB: + { + using Type = detail::Types<detail::Int16LSB>; + size_bytes = sizeof(Type::type); + valid_bits = Type::valid_bits; + is_float = Type::is_float; + is_be = Type::is_be; + } + break; + case SampleType::Int24LSB: + { + using Type = detail::Types<detail::Int24LSB>; + size_bytes = sizeof(Type::type); + valid_bits = Type::valid_bits; + is_float = Type::is_float; + is_be = Type::is_be; + } + break; + case SampleType::Int32LSB: + { + using Type = detail::Types<detail::Int32LSB>; + size_bytes = sizeof(Type::type); + valid_bits = Type::valid_bits; + is_float = Type::is_float; + is_be = Type::is_be; + } + break; + case SampleType::Float32LSB: + { + using Type = detail::Types<detail::Float32LSB>; + size_bytes = sizeof(Type::type); + valid_bits = Type::valid_bits; + is_float = Type::is_float; + is_be = Type::is_be; + } + break; + case SampleType::Float64LSB: + { + using Type = detail::Types<detail::Float64LSB>; + size_bytes = sizeof(Type::type); + valid_bits = Type::valid_bits; + is_float = Type::is_float; + is_be = Type::is_be; + } + break; + case SampleType::Int32LSB16: + { + using Type = detail::Types<detail::Int32LSB16>; + size_bytes = sizeof(Type::type); + valid_bits = Type::valid_bits; + is_float = Type::is_float; + is_be = Type::is_be; + } + break; + case SampleType::Int32LSB18: + { + using Type = detail::Types<detail::Int32LSB18>; + size_bytes = sizeof(Type::type); + valid_bits = Type::valid_bits; + is_float = Type::is_float; + is_be = Type::is_be; + } + break; + case SampleType::Int32LSB20: + { + using Type = detail::Types<detail::Int32LSB20>; + size_bytes = sizeof(Type::type); + valid_bits = Type::valid_bits; + is_float = Type::is_float; + is_be = Type::is_be; + } + break; + case SampleType::Int32LSB24: + { + using Type = detail::Types<detail::Int32LSB24>; + size_bytes = sizeof(Type::type); + valid_bits = Type::valid_bits; + is_float = Type::is_float; + is_be = Type::is_be; + } + break; + default: + break; + } + } +}; + + + +} // namespace ASIO_VERSION_NAMESPACE + + + +} // namespace Sample + + + +} // namespace ASIO + + + +#endif // ASIO_ASIOSAMPLECONVERT_HPP
\ No newline at end of file diff --git a/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOSystemWindows.hpp b/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOSystemWindows.hpp new file mode 100644 index 00000000..2473dd70 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOSystemWindows.hpp @@ -0,0 +1,511 @@ + +#ifndef ASIO_ASIOSYSTEMWINDOWS_HPP +#define ASIO_ASIOSYSTEMWINDOWS_HPP + + + +#include "ASIOVersion.hpp" +#include "ASIOConfig.hpp" +#include "ASIOCore.hpp" + +#include <exception> +#include <memory> +#include <stdexcept> +#include <string> +#include <string_view> +#include <vector> + +#include <cassert> + +#if ASIO_SYSTEM_WINDOWS +#include <windows.h> +#if !defined(NTDDI_VERSION) +#error "NTDDI_VERSION undefined" +#endif +#if !defined(_WIN32_WINNT) +#error "_WIN32_WINNT undefined" +#endif +#include <avrt.h> +#endif // ASIO_SYSTEM_WINDOWS + + + +#if ASIO_SYSTEM_WINDOWS +#if ASIO_HAVE_PRAGMA_COMMENT_LIB +#pragma comment(lib, "kernel32.lib") +#pragma comment(lib, "advapi32.lib") +#pragma comment(lib, "avrt.lib") +#endif // ASIO_HAVE_PRAGMA_COMMENT_LIB +#endif // ASIO_SYSTEM_WINDOWS + + + +namespace ASIO { + + + +#if ASIO_SYSTEM_WINDOWS + + + +namespace Windows { + + + +inline namespace ASIO_VERSION_NAMESPACE { + + + +static_assert(NTDDI_VERSION >= NTDDI_WIN7); +static_assert(_WIN32_WINNT >= _WIN32_WINNT_WIN7); + + + +#if defined(UNICODE) +inline namespace Unicode { +#else +inline namespace Ansi { +#endif + + + +struct DriverInfo { + std::basic_string<TCHAR> Key; + std::basic_string<TCHAR> Id; + CLSID Clsid{}; + std::basic_string<TCHAR> Name; + std::basic_string<TCHAR> Description; + std::basic_string<TCHAR> DisplayName() const { + if (Description.empty()) { + return Key; + } + return Description; + } +}; + + +class HKey { +private: + HKEY m_Key = NULL; + +public: + HKey() = default; + HKey(const HKey &) = delete; + HKey & operator=(const HKey &) = delete; + ~HKey() { + if (m_Key) { + RegCloseKey(m_Key); + } + } + operator HKEY &() { + return m_Key; + } + operator HKEY *() { + return &m_Key; + } +}; + + +inline LRESULT CheckLRESULTOutOfMemory(LRESULT lr) { + if ((lr == ERROR_NOT_ENOUGH_MEMORY) || (lr == ERROR_OUTOFMEMORY)) { + throw std::bad_alloc(); + } + return lr; +} + +inline HRESULT CheckHRESULTOutOfMemory(HRESULT hr) { + if (hr == E_OUTOFMEMORY) { + throw std::bad_alloc(); + } + return hr; +} + + +inline std::vector<DriverInfo> EnumerateDrivers() { + std::vector<DriverInfo> drivers; + HKey hkAsioEnum; + if (CheckLRESULTOutOfMemory(RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\ASIO"), 0, KEY_READ, hkAsioEnum)) != ERROR_SUCCESS) { + return drivers; + } + DWORD numSubKeys = 0; + DWORD maxSubKeyLen = 0; + if (CheckLRESULTOutOfMemory(RegQueryInfoKey(hkAsioEnum, NULL, NULL, NULL, &numSubKeys, &maxSubKeyLen, NULL, NULL, NULL, NULL, NULL, NULL)) != ERROR_SUCCESS) { + return drivers; + } + for (DWORD i = 0; i < numSubKeys; ++i) { + std::vector<TCHAR> bufKey(static_cast<std::size_t>(maxSubKeyLen) + 1); + DWORD lenKey = static_cast<DWORD>(bufKey.size()); + if (CheckLRESULTOutOfMemory(RegEnumKeyEx(hkAsioEnum, i, bufKey.data(), &lenKey, NULL, NULL, NULL, NULL)) != ERROR_SUCCESS) { + continue; + } + std::basic_string<TCHAR> key(bufKey.data(), bufKey.data() + lenKey); + HKey hkDriver; + if (CheckLRESULTOutOfMemory(RegOpenKeyEx(hkAsioEnum, key.c_str(), 0, KEY_READ, hkDriver)) != ERROR_SUCCESS) { + continue; + } + DWORD maxValueLen = 0; + if (CheckLRESULTOutOfMemory(RegQueryInfoKey(hkDriver, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &maxValueLen, NULL, NULL)) != ERROR_SUCCESS) { + continue; + } + std::vector<TCHAR> bufClsid(static_cast<std::size_t>(maxValueLen) + 1); + DWORD lenClsid = static_cast<DWORD>(bufClsid.size()) * sizeof(TCHAR); + DWORD typeClsid = REG_SZ; + if (CheckLRESULTOutOfMemory(RegQueryValueEx(hkDriver, TEXT("CLSID"), NULL, &typeClsid, reinterpret_cast<LPBYTE>(bufClsid.data()), &lenClsid)) != ERROR_SUCCESS) { + continue; + } + std::basic_string<TCHAR> strClsid = std::basic_string<TCHAR>(bufClsid.data(), bufClsid.data() + (lenClsid / sizeof(TCHAR))).c_str(); + std::vector<OLECHAR> oleClsid(strClsid.c_str(), strClsid.c_str() + strClsid.length() + 1); + CLSID clsid = CLSID(); + if (CheckHRESULTOutOfMemory(CLSIDFromString(oleClsid.data(), &clsid)) != NOERROR) { + continue; + } + std::vector<TCHAR> bufName(static_cast<std::size_t>(maxValueLen) + 1); + DWORD lenName = static_cast<DWORD>(bufName.size()) * sizeof(TCHAR); + DWORD typeName = REG_SZ; + std::basic_string<TCHAR> name; + if (CheckLRESULTOutOfMemory(RegQueryValueEx(hkDriver, TEXT(""), NULL, &typeName, reinterpret_cast<LPBYTE>(bufName.data()), &lenName)) == ERROR_SUCCESS) { + name = std::basic_string<TCHAR>(bufName.data(), bufName.data() + (lenName / sizeof(TCHAR))).c_str(); + } + std::vector<TCHAR> bufDesc(static_cast<std::size_t>(maxValueLen) + 1); + DWORD lenDesc = static_cast<DWORD>(bufDesc.size()) * sizeof(TCHAR); + DWORD typeDesc = REG_SZ; + std::basic_string<TCHAR> desc; + if (CheckLRESULTOutOfMemory(RegQueryValueEx(hkDriver, TEXT("Description"), NULL, &typeDesc, reinterpret_cast<LPBYTE>(bufDesc.data()), &lenDesc)) == ERROR_SUCCESS) { + desc = std::basic_string<TCHAR>(bufDesc.data(), bufDesc.data() + (lenDesc / sizeof(TCHAR))).c_str(); + } + DriverInfo info; + info.Key = key; + info.Id = strClsid; + info.Clsid = clsid; + info.Name = name; + info.Description = desc; + drivers.push_back(std::move(info)); + } + return drivers; +} + + +[[nodiscard]] inline ISystemDriver * OpenDriver(CLSID clsid) { + ISystemDriver * driver = nullptr; + if (CheckHRESULTOutOfMemory(CoCreateInstance(clsid, 0, CLSCTX_INPROC_SERVER, clsid, reinterpret_cast<void **>(&driver))) != S_OK) { + return nullptr; + } + return driver; +} + +inline ULONG CloseDriver(ISystemDriver * driver) { + return driver->Release(); +} + + +struct DriverLoadFailed + : public std::runtime_error { + DriverLoadFailed() + : std::runtime_error("ASIO Driver load failed.") { + return; + } +}; + + +struct DriverInitFailed + : public std::runtime_error { + DriverInitFailed() + : std::runtime_error("ASIO Driver init failed.") { + return; + } +}; + + +class Driver + : public IDriver { + +private: + ISystemDriver * m_Driver = nullptr; + +public: + explicit Driver(CLSID clsid, HWND wnd) { + m_Driver = openDriver(clsid); + if (!m_Driver) { + throw DriverLoadFailed(); + } + if (!initDriver(wnd)) { + closeDriver(m_Driver); + throw DriverInitFailed(); + } + } + + Driver(const Driver &) = delete; + + Driver & operator=(const Driver &) = delete; + + ~Driver() override { + closeDriver(m_Driver); + } + +private: + ISystemDriver * openDriver(CLSID clsid) { + return OpenDriver(clsid); + } + + ULONG closeDriver(ISystemDriver * driver) { + return driver->Release(); + } + +private: + Bool initDriver(HWND sysHandle) { + return static_cast<Bool>(m_Driver->init(reinterpret_cast<SysHandle>(sysHandle))); + } + +public: + void getDriverName(DriverName * name) final { + return m_Driver->getDriverName(name); + } + [[nodiscard]] Long getDriverVersion() final { + return m_Driver->getDriverVersion(); + } + void getErrorMessage(ErrorMessage * string) final { + return m_Driver->getErrorMessage(string); + } + [[nodiscard]] ErrorCode start() final { + return m_Driver->start(); + } + [[nodiscard]] ErrorCode stop() final { + return m_Driver->stop(); + } + [[nodiscard]] ErrorCode getChannels(Long * numInputChannels, Long * numOutputChannels) final { + return m_Driver->getChannels(numInputChannels, numOutputChannels); + } + [[nodiscard]] ErrorCode getLatencies(Long * inputLatency, Long * outputLatency) final { + return m_Driver->getLatencies(inputLatency, outputLatency); + } + [[nodiscard]] ErrorCode getBufferSize(Long * minSize, Long * maxSize, Long * preferredSize, Long * granularity) final { + return m_Driver->getBufferSize(minSize, maxSize, preferredSize, granularity); + } + [[nodiscard]] ErrorCode canSampleRate(SampleRate sampleRate) final { + return m_Driver->canSampleRate(sampleRate); + } + [[nodiscard]] ErrorCode getSampleRate(SampleRate * sampleRate) final { + return m_Driver->getSampleRate(sampleRate); + } + [[nodiscard]] ErrorCode setSampleRate(SampleRate sampleRate) final { + return m_Driver->setSampleRate(sampleRate); + } + [[nodiscard]] ErrorCode getClockSources(ClockSource * clocks, Long * numSources) final { + return m_Driver->getClockSources(clocks, numSources); + } + [[nodiscard]] ErrorCode setClockSource(Long reference) final { + return m_Driver->setClockSource(reference); + } + [[nodiscard]] ErrorCode getSamplePosition(HiLoLongLong * samplePosition, HiLoLongLong * timeStamp) final { + return m_Driver->getSamplePosition(samplePosition, timeStamp); + } + [[nodiscard]] ErrorCode getChannelInfo(ChannelInfo * info) final { + return m_Driver->getChannelInfo(info); + } + [[nodiscard]] ErrorCode createBuffers(BufferInfo * bufferInfos, Long numChannels, Long bufferSize, Callbacks const * callbacks) final { + return m_Driver->createBuffers(bufferInfos, numChannels, bufferSize, callbacks); + } + [[nodiscard]] ErrorCode disposeBuffers() final { + return m_Driver->disposeBuffers(); + } + [[nodiscard]] ErrorCode controlPanel() final { + return m_Driver->controlPanel(); + } + [[nodiscard]] ErrorCode future(FutureSelector selector, void * opt) final { + return m_Driver->future(selector, opt); + } + [[nodiscard]] ErrorCode outputReady() final { + return m_Driver->outputReady(); + } +}; + + + +class IBufferSwitchDispatcher { +public: + virtual ~IBufferSwitchDispatcher() = default; + +public: + virtual void Dispatch(std::size_t bufferIndex) = 0; +}; + +class BufferSwitchDispatcherBase + : public IBufferSwitchDispatcher { + +private: + HANDLE m_hBufferSwitch[2] = {NULL, NULL}; + + HANDLE m_hStarted = NULL; + HANDLE m_hStopRequest = NULL; + + HANDLE m_hThread = NULL; + +public: + BufferSwitchDispatcherBase() { + m_hBufferSwitch[0] = CreateEvent(NULL, FALSE, FALSE, NULL); + if (m_hBufferSwitch[0] == NULL) { + goto error; + } + m_hBufferSwitch[1] = CreateEvent(NULL, FALSE, FALSE, NULL); + if (m_hBufferSwitch[1] == NULL) { + goto error; + } + m_hStarted = CreateEvent(NULL, TRUE, FALSE, NULL); + if (m_hStarted == NULL) { + goto error; + } + m_hStopRequest = CreateEvent(NULL, TRUE, FALSE, NULL); + if (m_hStopRequest == NULL) { + goto error; + } + m_hThread = CreateThread(NULL, 0, &ThreadProc, this, 0, NULL); + if (m_hThread == NULL) { + goto error; + } + if (WaitForSingleObject(m_hStarted, INFINITE) != WAIT_OBJECT_0) { + if (SetEvent(m_hStopRequest) != TRUE) { + goto error; + } + if (WaitForSingleObject(m_hThread, INFINITE) != WAIT_OBJECT_0) { + goto error; + } + goto error; + } + return; +error: + if (m_hThread != NULL) { + CloseHandle(m_hThread); + } + if (m_hStopRequest != NULL) { + CloseHandle(m_hStopRequest); + } + if (m_hStarted != NULL) { + CloseHandle(m_hStarted); + } + if (m_hBufferSwitch[1] != NULL) { + CloseHandle(m_hBufferSwitch[1]); + } + if (m_hBufferSwitch[0] != NULL) { + CloseHandle(m_hBufferSwitch[0]); + } + throw std::bad_alloc(); + } + + ~BufferSwitchDispatcherBase() override { + SetEvent(m_hStopRequest); + WaitForSingleObject(m_hThread, INFINITE); + CloseHandle(m_hThread); + CloseHandle(m_hStopRequest); + CloseHandle(m_hStarted); + CloseHandle(m_hBufferSwitch[1]); + CloseHandle(m_hBufferSwitch[0]); + } + + BufferSwitchDispatcherBase(const BufferSwitchDispatcherBase &) noexcept = delete; + BufferSwitchDispatcherBase & operator=(const BufferSwitchDispatcherBase &) noexcept = delete; + +private: + static DWORD WINAPI ThreadProc(LPVOID lpParameter) noexcept { + if (!lpParameter) { + return 1; + } + return static_cast<BufferSwitchDispatcherBase *>(lpParameter)->ThreadMain() ? 0 : 1; + } + + [[nodiscard]] bool ThreadMain() noexcept { + DWORD task_idx = 0; + HANDLE hTask = AvSetMmThreadCharacteristics(TEXT("Pro Audio"), &task_idx); + SetEvent(m_hStarted); + bool result = ThreadLoop(); + if (hTask) { + AvRevertMmThreadCharacteristics(hTask); + } + hTask = NULL; + task_idx = 0; + return result; + } + + [[nodiscard]] bool ThreadLoop() noexcept { + bool stop = false; + while (!stop) { + HANDLE events[3] = {m_hBufferSwitch[0], m_hBufferSwitch[1], m_hStopRequest}; + switch (WaitForMultipleObjects(3, events, FALSE, INFINITE)) { + case WAIT_OBJECT_0 + 0: + CallFunc(0); + break; + case WAIT_OBJECT_0 + 1: + CallFunc(1); + break; + case WAIT_OBJECT_0 + 2: + stop = true; + break; + default: + return false; + break; + } + } + return true; + } + +protected: + virtual void CallFunc(std::size_t bufferIndex) = 0; + +public: + void Dispatch(std::size_t bufferIndex) final { + if (SetEvent(m_hBufferSwitch[bufferIndex & 1u]) != TRUE) { + throw std::bad_alloc(); + } + } +}; + +template <typename Tfunc> +class BufferSwitchDispatcher + : public BufferSwitchDispatcherBase { + +private: + Tfunc m_func; + +public: + BufferSwitchDispatcher(Tfunc func) + : m_func(func) { + return; + } + +protected: + void CallFunc(std::size_t bufferIndex) final { + m_func(bufferIndex); + } +}; + +template <typename Tfunc> +inline std::unique_ptr<IBufferSwitchDispatcher> CreateBufferSwitchDispatcher(Tfunc func) { + return std::make_unique<BufferSwitchDispatcher<Tfunc>>(func); +} + + + +#if defined(UNICODE) +} // namespace Unicode +#else +} // namespace Ansi +#endif + + + +} // namespace ASIO_VERSION_NAMESPACE + + + +} // namespace Windows + + + +#endif // ASIO_SYSTEM_WINDOWS + + + +} // namespace ASIO + + + +#endif // ASIO_ASIOSYSTEMWINDOWS_HPP diff --git a/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOSystemWindowsSEH.hpp b/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOSystemWindowsSEH.hpp new file mode 100644 index 00000000..e36e61bc --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOSystemWindowsSEH.hpp @@ -0,0 +1,283 @@ + +#ifndef ASIO_ASIOSYSTEMWINDOWSSEH_HPP +#define ASIO_ASIOSYSTEMWINDOWSSEH_HPP + + + +#include "ASIOVersion.hpp" +#include "ASIOConfig.hpp" +#include "ASIOCore.hpp" +#include "ASIOSystemWindows.hpp" + +#include <memory> +#include <string_view> + +#include <cassert> + +#if ASIO_SYSTEM_WINDOWS +#include <windows.h> +#if !defined(NTDDI_VERSION) +#error "NTDDI_VERSION undefined" +#endif +#if !defined(_WIN32_WINNT) +#error "_WIN32_WINNT undefined" +#endif +#endif // ASIO_SYSTEM_WINDOWS + + + +namespace ASIO { + + + +#if ASIO_SYSTEM_WINDOWS + + + +namespace Windows { + + + +inline namespace ASIO_VERSION_NAMESPACE { + + + +static_assert(NTDDI_VERSION >= NTDDI_WIN7); +static_assert(_WIN32_WINNT >= _WIN32_WINNT_WIN7); + + + +#if defined(UNICODE) +inline namespace Unicode { +#else +inline namespace Ansi { +#endif + + + +namespace SEH { + +struct DriverCrash { +private: + DWORD m_Code; + std::string_view m_Func; + +public: + explicit constexpr DriverCrash(DWORD code, std::string_view func) noexcept + : m_Code(code) + , m_Func(func) { + return; + } + +public: + constexpr DWORD code() const noexcept { + return m_Code; + } + constexpr std::string_view func() const noexcept { + return m_Func; + } +}; + +class IState { +protected: + IState() noexcept = default; + +public: + IState(const IState &) = delete; + IState & operator=(const IState &) = delete; + +public: + virtual ~IState() = default; +}; + +class ITranslator { +protected: + ITranslator() noexcept = default; + +public: + ITranslator(const ITranslator &) = delete; + ITranslator & operator=(const ITranslator &) = delete; + +public: + virtual ~ITranslator() = default; + +public: + [[nodiscard]] virtual LONG TranslatorFilter(std::unique_ptr<IState> & state, DWORD code, LPEXCEPTION_POINTERS records, std::string_view func) const noexcept = 0; + [[noreturn]] virtual void TranslatorHandler(std::unique_ptr<IState> & state, DWORD code, std::string_view func) const = 0; +}; + +class DefaultTranslator + : public ITranslator { +public: + virtual ~DefaultTranslator() = default; + +public: + [[nodiscard]] LONG TranslatorFilter(std::unique_ptr<IState> & /* state */, DWORD /* code */, LPEXCEPTION_POINTERS /* records */, std::string_view /* func */) const noexcept final { + return EXCEPTION_EXECUTE_HANDLER; + } + [[noreturn]] void TranslatorHandler(std::unique_ptr<IState> & /* state */, DWORD code, std::string_view func) const final { + throw DriverCrash(code, func); + } +}; + +class Driver + : public IDriver { + +private: + ISystemDriver * m_Driver = nullptr; + std::unique_ptr<ITranslator> m_Translator = nullptr; + +private: + template <typename Tfn> + static auto TranslateSEtry(std::unique_ptr<ITranslator> & translator, std::unique_ptr<IState> & state, Tfn fn, std::string_view func) -> decltype(fn()) { + __try + { + return fn(); + } __except (translator->TranslatorFilter(state, GetExceptionCode(), GetExceptionInformation(), func)) + { + translator->TranslatorHandler(state, GetExceptionCode(), func); + } + throw DriverCrash(0, func); + } + + template <typename Tfn> + auto TranslateSE(Tfn fn, std::string_view func) -> decltype(fn()) { + assert(m_Translator); + std::unique_ptr<IState> state; + return TranslateSEtry(m_Translator, state, fn, func); + } + + template <typename Tfn> + auto CallDriver(Tfn fn, std::string_view func) -> decltype(fn()) { + return TranslateSE(fn, func); + } + +public: + explicit Driver(CLSID clsid, HWND wnd, std::unique_ptr<ITranslator> translator = std::make_unique<DefaultTranslator>()) + : m_Translator(std::move(translator)) { + m_Driver = openDriver(clsid); + if (!m_Driver) { + throw DriverLoadFailed(); + } + if (!initDriver(wnd)) { + closeDriver(m_Driver); + throw DriverInitFailed(); + } + } + + Driver(const Driver &) = delete; + + Driver & operator=(const Driver &) = delete; + + ~Driver() noexcept(false) override { + closeDriver(m_Driver); + } + +private: + ISystemDriver * openDriver(CLSID clsid) { + return CallDriver([&]() { return OpenDriver(clsid); }, __func__); + } + + ULONG closeDriver(ISystemDriver * driver) { + return CallDriver([&]() { return CloseDriver(driver); }, __func__); + } + +private: + Bool initDriver(HWND sysHandle) { + return static_cast<Bool>(CallDriver([&]() { return m_Driver->init(reinterpret_cast<SysHandle>(sysHandle)); }, __func__)); + } + +public: + void getDriverName(DriverName * name) final { + return CallDriver([&]() { return m_Driver->getDriverName(name); }, __func__); + } + [[nodiscard]] Long getDriverVersion() final { + return CallDriver([&]() { return m_Driver->getDriverVersion(); }, __func__); + } + void getErrorMessage(ErrorMessage * string) final { + return CallDriver([&]() { return m_Driver->getErrorMessage(string); }, __func__); + } + [[nodiscard]] ErrorCode start() final { + return CallDriver([&]() { return m_Driver->start(); }, __func__); + } + [[nodiscard]] ErrorCode stop() final { + return CallDriver([&]() { return m_Driver->stop(); }, __func__); + } + [[nodiscard]] ErrorCode getChannels(Long * numInputChannels, Long * numOutputChannels) final { + return CallDriver([&]() { return m_Driver->getChannels(numInputChannels, numOutputChannels); }, __func__); + } + [[nodiscard]] ErrorCode getLatencies(Long * inputLatency, Long * outputLatency) final { + return CallDriver([&]() { return m_Driver->getLatencies(inputLatency, outputLatency); }, __func__); + } + [[nodiscard]] ErrorCode getBufferSize(Long * minSize, Long * maxSize, Long * preferredSize, Long * granularity) final { + return CallDriver([&]() { return m_Driver->getBufferSize(minSize, maxSize, preferredSize, granularity); }, __func__); + } + [[nodiscard]] ErrorCode canSampleRate(SampleRate sampleRate) final { + return CallDriver([&]() { return m_Driver->canSampleRate(sampleRate); }, __func__); + } + [[nodiscard]] ErrorCode getSampleRate(SampleRate * sampleRate) final { + return CallDriver([&]() { return m_Driver->getSampleRate(sampleRate); }, __func__); + } + [[nodiscard]] ErrorCode setSampleRate(SampleRate sampleRate) final { + return CallDriver([&]() { return m_Driver->setSampleRate(sampleRate); }, __func__); + } + [[nodiscard]] ErrorCode getClockSources(ClockSource * clocks, Long * numSources) final { + return CallDriver([&]() { return m_Driver->getClockSources(clocks, numSources); }, __func__); + } + [[nodiscard]] ErrorCode setClockSource(Long reference) final { + return CallDriver([&]() { return m_Driver->setClockSource(reference); }, __func__); + } + [[nodiscard]] ErrorCode getSamplePosition(HiLoLongLong * samplePosition, HiLoLongLong * timeStamp) final { + return CallDriver([&]() { return m_Driver->getSamplePosition(samplePosition, timeStamp); }, __func__); + } + [[nodiscard]] ErrorCode getChannelInfo(ChannelInfo * info) final { + return CallDriver([&]() { return m_Driver->getChannelInfo(info); }, __func__); + } + [[nodiscard]] ErrorCode createBuffers(BufferInfo * bufferInfos, Long numChannels, Long bufferSize, Callbacks const * callbacks) final { + return CallDriver([&]() { return m_Driver->createBuffers(bufferInfos, numChannels, bufferSize, callbacks); }, __func__); + } + [[nodiscard]] ErrorCode disposeBuffers() final { + return CallDriver([&]() { return m_Driver->disposeBuffers(); }, __func__); + } + [[nodiscard]] ErrorCode controlPanel() final { + return CallDriver([&]() { return m_Driver->controlPanel(); }, __func__); + } + [[nodiscard]] ErrorCode future(FutureSelector selector, void * opt) final { + return CallDriver([&]() { return m_Driver->future(selector, opt); }, __func__); + } + [[nodiscard]] ErrorCode outputReady() final { + return CallDriver([&]() { return m_Driver->outputReady(); }, __func__); + } +}; + + + +} // namespace SEH + + + +#if defined(UNICODE) +} // namespace Unicode +#else +} // namespace Ansi +#endif + + + +} // namespace ASIO_VERSION_NAMESPACE + + + +} // namespace Windows + + + +#endif // ASIO_SYSTEM_WINDOWS + + + +} // namespace ASIO + + + +#endif // ASIO_ASIOSYSTEMWINDOWS_HPP diff --git a/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOVerifyABI.hpp b/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOVerifyABI.hpp new file mode 100644 index 00000000..94df6e56 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOVerifyABI.hpp @@ -0,0 +1,127 @@ + +#ifndef ASIO_ASIOVERIFY_ABI_HPP +#define ASIO_ASIOVERIFY_ABI_HPP + + + +#include "ASIOVersion.hpp" +#include "ASIOConfig.hpp" +#include "ASIOCore.hpp" + +#if __has_include(<iasiodrv.h>) +#define ASIO_ABI_VERIFIED 1 +#include <iasiodrv.h> +#else +#define ASIO_ABI_VERIFIED 0 +ASIO_WARNING("Warning: iasiodrv.h not found. ASIO ABI is not verified.") +#endif + + + +namespace ASIO { + + + +#if ASIO_ABI_VERIFIED + +inline namespace VerifyABI { + + + +inline namespace ASIO_VERSION_NAMESPACE { + + + +static_assert(sizeof(ASIO::SysHandle) == sizeof(void *)); +static_assert(sizeof(ASIO::Byte) == sizeof(char)); +static_assert(sizeof(ASIO::Long) == sizeof(long)); +static_assert(sizeof(ASIO::ULong) == sizeof(unsigned long)); +static_assert(sizeof(ASIO::ULongLong) == sizeof(unsigned long long int)); +static_assert(sizeof(ASIO::Double) == sizeof(double)); +static_assert(sizeof(ASIO::Char) == sizeof(char)); +static_assert(sizeof(ASIO::Padding1) == sizeof(char)); +static_assert(sizeof(ASIO::PaddingLong) == sizeof(long)); +static_assert(sizeof(ASIO::Bool) == sizeof(long)); +static_assert(sizeof(ASIO::HiLoLongLong) == sizeof(long long int)); +static_assert(sizeof(ASIO::ResultBool) == sizeof(long)); +static_assert(sizeof(ASIO::CharBuf<1>) == sizeof(char[1])); +static_assert(sizeof(ASIO::Samples) == sizeof(::ASIOSamples)); +static_assert(sizeof(ASIO::TimeStamp) == sizeof(::ASIOTimeStamp)); +static_assert(sizeof(ASIO::SampleRate) == sizeof(::ASIOSampleRate)); +static_assert(sizeof(ASIO::SampleType) == sizeof(::ASIOSampleType)); +static_assert(sizeof(ASIO::ErrorCode) == sizeof(::ASIOError)); +static_assert(sizeof(ASIO::TimeCodeFlags) == sizeof(::ASIOTimeCodeFlags)); +static_assert(sizeof(ASIO::TimeCode) == sizeof(::ASIOTimeCode)); +static_assert(sizeof(ASIO::TimeInfoFlags) == sizeof(::AsioTimeInfoFlags)); +static_assert(sizeof(ASIO::TimeInfo) == sizeof(::AsioTimeInfo)); +static_assert(sizeof(ASIO::Time) == sizeof(::ASIOTime)); +static_assert(sizeof(ASIO::MessageSelector) == sizeof(long)); +static_assert(sizeof(ASIO::Callbacks) == sizeof(::ASIOCallbacks)); +static_assert(sizeof(ASIO::ClockSource) == sizeof(::ASIOClockSource)); +static_assert(sizeof(ASIO::ChannelInfo) == sizeof(::ASIOChannelInfo)); +static_assert(sizeof(ASIO::BufferInfo) == sizeof(::ASIOBufferInfo)); +static_assert(sizeof(ASIO::FutureSelector) == sizeof(long)); +static_assert(sizeof(ASIO::InputMonitor) == sizeof(::ASIOInputMonitor)); +static_assert(sizeof(ASIO::ChannelControls) == sizeof(::ASIOChannelControls)); +static_assert(sizeof(ASIO::TransportCommand) == sizeof(long)); +static_assert(sizeof(ASIO::TransportParameters) == sizeof(::ASIOTransportParameters)); +static_assert(sizeof(ASIO::IoFormatType) == sizeof(::ASIOIoFormatType)); +static_assert(sizeof(ASIO::IoFormat) == sizeof(::ASIOIoFormat)); +static_assert(sizeof(ASIO::InternalBufferInfo) == sizeof(::ASIOInternalBufferInfo)); +static_assert(sizeof(ASIO::ISystemDriver) == sizeof(::IASIO)); + +static_assert(alignof(ASIO::SysHandle) == alignof(void *)); +static_assert(alignof(ASIO::Byte) == alignof(char)); +static_assert(alignof(ASIO::Long) == alignof(long)); +static_assert(alignof(ASIO::ULong) == alignof(unsigned long)); +static_assert(alignof(ASIO::ULongLong) == alignof(unsigned long long int)); +static_assert(alignof(ASIO::Double) == alignof(double)); +static_assert(alignof(ASIO::Char) == alignof(char)); +static_assert(alignof(ASIO::Padding1) == alignof(char)); +static_assert(alignof(ASIO::PaddingLong) == alignof(long)); +static_assert(alignof(ASIO::Bool) == alignof(long)); +static_assert((NATIVE_INT64 && (alignof(ASIO::HiLoLongLong) == alignof(long long int))) || (!NATIVE_INT64 && (alignof(ASIO::HiLoLongLong) == alignof(unsigned long[2])))); +static_assert(alignof(ASIO::ResultBool) == alignof(long)); +static_assert(alignof(ASIO::CharBuf<1>) == alignof(char[1])); +static_assert(alignof(ASIO::Samples) == alignof(::ASIOSamples)); +static_assert(alignof(ASIO::TimeStamp) == alignof(::ASIOTimeStamp)); +static_assert(alignof(ASIO::SampleRate) == alignof(::ASIOSampleRate)); +static_assert(alignof(ASIO::SampleType) == alignof(::ASIOSampleType)); +static_assert(alignof(ASIO::ErrorCode) == alignof(::ASIOError)); +static_assert(alignof(ASIO::TimeCodeFlags) == alignof(::ASIOTimeCodeFlags)); +static_assert(alignof(ASIO::TimeCode) == alignof(::ASIOTimeCode)); +static_assert(alignof(ASIO::TimeInfoFlags) == alignof(::AsioTimeInfoFlags)); +static_assert(alignof(ASIO::TimeInfo) == alignof(::AsioTimeInfo)); +static_assert(alignof(ASIO::Time) == alignof(::ASIOTime)); +static_assert(alignof(ASIO::MessageSelector) == alignof(long)); +static_assert(alignof(ASIO::Callbacks) == alignof(::ASIOCallbacks)); +static_assert(alignof(ASIO::ClockSource) == alignof(::ASIOClockSource)); +static_assert(alignof(ASIO::ChannelInfo) == alignof(::ASIOChannelInfo)); +static_assert(alignof(ASIO::BufferInfo) == alignof(::ASIOBufferInfo)); +static_assert(alignof(ASIO::FutureSelector) == alignof(long)); +static_assert(alignof(ASIO::InputMonitor) == alignof(::ASIOInputMonitor)); +static_assert(alignof(ASIO::ChannelControls) == alignof(::ASIOChannelControls)); +static_assert(alignof(ASIO::TransportCommand) == alignof(long)); +static_assert(alignof(ASIO::TransportParameters) == alignof(::ASIOTransportParameters)); +static_assert(alignof(ASIO::IoFormatType) == alignof(::ASIOIoFormatType)); +static_assert(alignof(ASIO::IoFormat) == alignof(::ASIOIoFormat)); +static_assert(alignof(ASIO::InternalBufferInfo) == alignof(::ASIOInternalBufferInfo)); +static_assert(alignof(ASIO::ISystemDriver) == alignof(::IASIO)); + + + +} // namespace ASIO_VERSION_NAMESPACE + + + +} // namespace VerifyABI + +#endif // ASIO_ABI_VERIFIED + + + +} // namespace ASIO + + + +#endif // ASIO_ASIOVERIFY_ABI_HPP diff --git a/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOVersion.hpp b/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOVersion.hpp new file mode 100644 index 00000000..02fd4fe7 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOVersion.hpp @@ -0,0 +1,132 @@ + +#ifndef ASIO_ASIOVERSION_HPP +#define ASIO_ASIOVERSION_HPP + + + +namespace ASIO { + + + +#define ASIO_VERSION_MAJOR 2 +#define ASIO_VERSION_MINOR 3 +#define ASIO_VERSION_PATCH 3 +#define ASIO_VERSION_BUILD 20190614 + + + +#define ASIO_MODERNSDK_VERSION_MAJOR 0 +#define ASIO_MODERNSDK_VERSION_MINOR 12 +#define ASIO_MODERNSDK_VERSION_PATCH 5 +#define ASIO_MODERNSDK_VERSION_BUILD 0 + + + +#define ASIO_VERSION_BUILD_NAMESPACE_IMPL(a, b, c, d) v##a##_##b##_##c +#define ASIO_VERSION_BUILD_NAMESPACE(a, b, c, d) ASIO_VERSION_BUILD_NAMESPACE_IMPL(a, b, c, d) + + + +#define ASIO_VERSION_NAMESPACE ASIO_VERSION_BUILD_NAMESPACE(ASIO_MODERNSDK_VERSION_MAJOR, ASIO_MODERNSDK_VERSION_MINOR, ASIO_MODERNSDK_VERSION_PATCH, ASIO_MODERNSDK_VERSION_BUILD) + + + +inline namespace Version { + + + +inline namespace ASIO_VERSION_NAMESPACE { + + + +struct SemanticVersion { + unsigned long long Major = 0; + unsigned long long Minor = 0; + unsigned long long Patch = 0; + constexpr std::tuple<unsigned long long, unsigned long long, unsigned long long> as_tuple() const noexcept { + return std::make_tuple(Major, Minor, Patch); + } +}; + +constexpr bool operator==(SemanticVersion a, SemanticVersion b) noexcept { + return a.as_tuple() == b.as_tuple(); +} +constexpr bool operator!=(SemanticVersion a, SemanticVersion b) noexcept { + return a.as_tuple() != b.as_tuple(); +} +constexpr bool operator<(SemanticVersion a, SemanticVersion b) noexcept { + return a.as_tuple() < b.as_tuple(); +} +constexpr bool operator>(SemanticVersion a, SemanticVersion b) noexcept { + return a.as_tuple() > b.as_tuple(); +} +constexpr bool operator<=(SemanticVersion a, SemanticVersion b) noexcept { + return a.as_tuple() <= b.as_tuple(); +} +constexpr bool operator>=(SemanticVersion a, SemanticVersion b) noexcept { + return a.as_tuple() >= b.as_tuple(); +} + +struct VersionInfo { + SemanticVersion SemVer; + unsigned long long Build = 0; + constexpr std::tuple<std::tuple<unsigned long long, unsigned long long, unsigned long long>, unsigned long long> as_tuple() const noexcept { + return std::make_tuple(SemVer.as_tuple(), Build); + } + template <typename Tostream> + friend Tostream & operator<<(Tostream & os, VersionInfo vi) { + if (vi.Build > 0) { + os << vi.SemVer.Major << "." << vi.SemVer.Minor << "." << vi.SemVer.Patch << "+build." << vi.Build; + } else { + os << vi.SemVer.Major << "." << vi.SemVer.Minor << "." << vi.SemVer.Patch; + } + return os; + } +}; + +constexpr bool operator==(VersionInfo a, VersionInfo b) noexcept { + return a.as_tuple() == b.as_tuple(); +} +constexpr bool operator!=(VersionInfo a, VersionInfo b) noexcept { + return a.as_tuple() != b.as_tuple(); +} +constexpr bool operator<(VersionInfo a, VersionInfo b) noexcept { + return a.as_tuple() < b.as_tuple(); +} +constexpr bool operator>(VersionInfo a, VersionInfo b) noexcept { + return a.as_tuple() > b.as_tuple(); +} +constexpr bool operator<=(VersionInfo a, VersionInfo b) noexcept { + return a.as_tuple() <= b.as_tuple(); +} +constexpr bool operator>=(VersionInfo a, VersionInfo b) noexcept { + return a.as_tuple() >= b.as_tuple(); +} + + + +constexpr inline VersionInfo Version = { + {ASIO_VERSION_MAJOR, ASIO_VERSION_MINOR, ASIO_VERSION_PATCH}, + ASIO_VERSION_BUILD +}; + +constexpr inline VersionInfo ModernSDKVersion = { + {ASIO_MODERNSDK_VERSION_MAJOR, ASIO_MODERNSDK_VERSION_MINOR, ASIO_MODERNSDK_VERSION_PATCH}, + ASIO_MODERNSDK_VERSION_BUILD +}; + + + +} // namespace ASIO_VERSION_NAMESPACE + + + +} // namespace Version + + + +} // namespace ASIO + + + +#endif // ASIO_ASIOVERSION_HPP diff --git a/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOstdcxx20bit.hpp b/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOstdcxx20bit.hpp new file mode 100644 index 00000000..7b401ba9 --- /dev/null +++ b/Src/external_dependencies/openmpt-trunk/include/asiomodern/include/ASIOModern/ASIOstdcxx20bit.hpp @@ -0,0 +1,48 @@ + +#ifndef ASIO_ASIOSTDCXX20BIT_HPP +#define ASIO_ASIOSTDCXX20BIT_HPP + + + +#include "ASIOVersion.hpp" +#include "ASIOConfig.hpp" + + + +#if (__cplusplus > 202000L) +#include <bit> +namespace ASIO { +namespace stdcxx20 { +using std::bit_cast; +using std::endian; +} // namespace stdcxx20 +} // namespace ASIO +#else // !C++20 +#include <type_traits> +#include <cstring> +namespace ASIO { +namespace stdcxx20 { +template <class To, class From> +typename std::enable_if<(sizeof(To) == sizeof(From)) && std::is_trivially_copyable<From>::value && std::is_trivial<To>::value, To>::type inline bit_cast(const From & src) noexcept { + To dst; + std::memcpy(&dst, &src, sizeof(To)); + return dst; +} +enum class endian { +#if ASIO_SYSTEM_WINDOWS + little = 0, + big = 1, + native = little, +#elif ASIO_COMPILER_CLANG || ASIO_COMPILER_GCC + little = __ORDER_LITTLE_ENDIAN__, + big = __ORDER_BIG_ENDIAN__, + native = __BYTE_ORDER__, +#endif +}; +} // namespace stdcxx20 +} // namespace ASIO +#endif // C++20 + + + +#endif // ASIO_ASIOSTDCXX20BIT_HPP |