From 31d7aec996e33a41a7101c981c5040fce479d205 Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Sat, 9 Sep 2023 13:51:19 -0400 Subject: [PATCH] AUv2 Feature Set continues 1. An attempt at a moderately reasonable hash for the subt in multi-mode. 2. Actually load the description --- cmake/enable_sdks.cmake | 8 +- src/detail/auv2/auv2_base_classes.h | 79 +++++++++++++++++++ src/detail/auv2/auv2_shared.h | 64 +++++++++++++++ src/detail/auv2/base_classes.h | 61 -------------- src/detail/auv2/build-helper/build-helper.cpp | 46 ++++++++--- 5 files changed, 183 insertions(+), 75 deletions(-) create mode 100644 src/detail/auv2/auv2_base_classes.h create mode 100644 src/detail/auv2/auv2_shared.h delete mode 100644 src/detail/auv2/base_classes.h diff --git a/cmake/enable_sdks.cmake b/cmake/enable_sdks.cmake index 3f587327..16178b8b 100644 --- a/cmake/enable_sdks.cmake +++ b/cmake/enable_sdks.cmake @@ -521,6 +521,7 @@ if (APPLE) WORKING_DIRECTORY ${bhtgoutdir} BYPRODUCTS ${bhtgoutdir}/auv2_Info.plist ${bhtgoutdir}/generated_entrypoints.hxx COMMAND $ --fromclap + "${AUV2_OUTPUT_NAME}" "$" "${AUV2_MANUFACTURER_CODE}" "${AUV2_MANUFACTURER_NAME}" ) @@ -580,7 +581,7 @@ if (APPLE) # clap-wrapper-extensions are PUBLIC, so a clap linking the library can access the clap-wrapper-extensions target_compile_definitions(${AUV2_TARGET}-clap-wrapper-auv2-lib INTERFACE -D${CLAP_WRAPPER_PLATFORM}=1) - target_link_libraries(${AUV2_TARGET}-clap-wrapper-auv2-lib INTERFACE clap-wrapper-extensions macos_filesystem_support) + target_link_libraries(${AUV2_TARGET}-clap-wrapper-auv2-lib INTERFACE clap-wrapper-extensions clap-wrapper-shared-detail macos_filesystem_support) endif() @@ -653,6 +654,11 @@ target_link_libraries(clap-wrapper-shared-detail PUBLIC clap clap-wrapper-extens target_include_directories(clap-wrapper-shared-detail PUBLIC libs/fmt) target_include_directories(clap-wrapper-shared-detail PUBLIC src) +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") + target_compile_options(clap-wrapper-shared-detail PRIVATE -Wall -Wextra -Wno-unused-parameter -Wpedantic -Werror) +endif() + + if (APPLE) target_sources(clap-wrapper-shared-detail PRIVATE src/detail/clap/mac_helpers.mm diff --git a/src/detail/auv2/auv2_base_classes.h b/src/detail/auv2/auv2_base_classes.h new file mode 100644 index 00000000..1f56fcc5 --- /dev/null +++ b/src/detail/auv2/auv2_base_classes.h @@ -0,0 +1,79 @@ +/* + * document + */ + +#pragma once + +#include +#include +#include + +#include +#include "auv2_shared.h" +#include + +namespace free_audio::auv2_wrapper +{ + + // ------------------------------------------------------------------------------------------------- + + class ClapWrapper_AUV2_Effect : public ausdk::AUEffectBase + { + using Base = ausdk::AUEffectBase; + ClapBridge bridge; + public: + explicit ClapWrapper_AUV2_Effect(const std::string &clapname, const std::string &clapid, + int clapidx, AudioComponentInstance ci) + : Base{ci, true}, bridge(clapname, clapid, clapidx) + { + std::cout << "[clap-wrapper] auv2: creating effect" << std::endl; + std::cout << "[clap-wrapper] auv2: id='" << clapid << "' index=" << clapidx + << std::endl; + + bridge.initialize(); + } + }; + + class ClapWrapper_AUV2_NoteEffect : public ausdk::AUMIDIEffectBase + { + using Base = ausdk::AUMIDIEffectBase; + ClapBridge bridge; + + public: + explicit ClapWrapper_AUV2_NoteEffect(const std::string &clapname, const std::string &clapid, + int clapidx, AudioComponentInstance ci) + : Base{ci, true}, bridge(clapname, clapid, clapidx) + { + std::cout << "[clap-wrapper] auv2: creating note effect" << std::endl; + std::cout << "[clap-wrapper] auv2: id='" << clapid << "' index=" << clapidx + << std::endl; + + + bridge.initialize(); + } + }; + + // ------------------------------------------------------------------------------------------------- + + class ClapWrapper_AUV2_Instrument : public ausdk::MusicDeviceBase + { + using Base = ausdk::MusicDeviceBase; + ClapBridge bridge; + + public: + explicit ClapWrapper_AUV2_Instrument(const std::string &clapname, const std::string &clapid, + int clapidx, AudioComponentInstance ci) + : Base{ci, 0, 1}, bridge(clapname, clapid, clapidx) + { + std::cout << "[clap-wrapper] auv2: creating instrument" << std::endl; + std::cout << "[clap-wrapper] auv2: id='" << clapid << "' index=" << clapidx + << std::endl; + + bridge.initialize(); + } + + bool StreamFormatWritable(AudioUnitScope, AudioUnitElement) override { return true; } + + bool CanScheduleParameters() const override { return false; } + }; +} // namespace free_audio: auv2_wrapper \ No newline at end of file diff --git a/src/detail/auv2/auv2_shared.h b/src/detail/auv2/auv2_shared.h new file mode 100644 index 00000000..7e1660fd --- /dev/null +++ b/src/detail/auv2/auv2_shared.h @@ -0,0 +1,64 @@ + +#pragma once + +#include "detail/clap/fsutil.h" + +namespace free_audio::auv2_wrapper +{ +struct ClapBridge +{ + std::string _clapname; + std::string _clapid; + int _idx; + + Clap::Library _library; + + const clap_plugin_descriptor_t *_desc{nullptr}; + + ClapBridge(const std::string &clapname, + const std::string &clapid, + int idx) : _clapname(clapname), _clapid(clapid), _idx(idx) + { + } + + void initialize() + { + if (!_library.hasEntryPoint()) + { + if (!_library.load(_clapname.c_str())) + { + std::cout << "[ERROR] cannot load either by internal entry nor _clapname" << std::endl; + return; + } + } + + if (_clapid.empty()) + { + if (_idx < 0 || _idx >= _library.plugins.size()) + { + std::cout << "[ERROR] cannot load by index" << std::endl; + return; + } + _desc = _library.plugins[_idx]; + } + else + { + for (auto *d : _library.plugins) + { + if (strcmp(d->id, _clapid.c_str()) == 0) + { + _desc = d; + } + } + } + + if (!_desc) + { + std::cout << "[ERROR] cannot determine plugin description" << std::endl; + return; + } + + std::cout << "[clap-wrapper] auv2: Initialized '" << _desc->id << "' / '" << _desc->name << "'" << std::endl; + } +}; +} \ No newline at end of file diff --git a/src/detail/auv2/base_classes.h b/src/detail/auv2/base_classes.h deleted file mode 100644 index 9e86f0a9..00000000 --- a/src/detail/auv2/base_classes.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * document - */ - -#pragma once - -#include -#include -#include - -#include - -// ------------------------------------------------------------------------------------------------- - -class ClapWrapper_AUV2_Effect : public ausdk::AUEffectBase -{ - using Base = ausdk::AUEffectBase; - - public: - explicit ClapWrapper_AUV2_Effect(const std::string &clapid, int clapidx, - AudioComponentInstance ci) - : Base{ci, true} - { - std::cout << "[clap-wrapper] auv2: creating effect" << std::endl; - std::cout << "[clap-wrapper] auv2: id='" << clapid << "' index=" << clapidx << std::endl; - } -}; - -class ClapWrapper_AUV2_NoteEffect : public ausdk::AUMIDIEffectBase -{ - using Base = ausdk::AUMIDIEffectBase; - - public: - explicit ClapWrapper_AUV2_NoteEffect(const std::string &clapid, int clapidx, - AudioComponentInstance ci) - : Base{ci, true} - { - std::cout << "[clap-wrapper] auv2: creating note effect" << std::endl; - std::cout << "[clap-wrapper] auv2: id='" << clapid << "' index=" << clapidx << std::endl; - } -}; - -// ------------------------------------------------------------------------------------------------- - -class ClapWrapper_AUV2_Instrument : public ausdk::MusicDeviceBase -{ - using Base = ausdk::MusicDeviceBase; - - public: - explicit ClapWrapper_AUV2_Instrument(const std::string &clapid, int clapidx, - AudioComponentInstance ci) - : Base{ci, 0, 1} - { - std::cout << "[clap-wrapper] auv2: creating instrument" << std::endl; - std::cout << "[clap-wrapper] auv2: id='" << clapid << "' index=" << clapidx << std::endl; - } - - bool StreamFormatWritable(AudioUnitScope, AudioUnitElement) override { return true; } - - bool CanScheduleParameters() const override { return false; } -}; diff --git a/src/detail/auv2/build-helper/build-helper.cpp b/src/detail/auv2/build-helper/build-helper.cpp index 988abb9e..67979773 100644 --- a/src/detail/auv2/build-helper/build-helper.cpp +++ b/src/detail/auv2/build-helper/build-helper.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "detail/clap/fsutil.h" @@ -14,7 +15,7 @@ namespace fs = ghc::filesystem; struct auInfo { - std::string name, vers, type, subt, manu, manunm, clapid, desc; + std::string name, vers, type, subt, manu, manunm, clapid, desc, clapname; const std::string factoryBase{"wrapAsAUV2_inst"}; @@ -57,7 +58,7 @@ struct auInfo } }; -bool buildUnitsFromClap(const std::string &clapfile, std::string &manu, std::string &manuName, std::vector &units) +bool buildUnitsFromClap(const std::string &clapfile, const std::string &clapname, std::string &manu, std::string &manuName, std::vector &units) { Clap::Library loader; if (!loader.load(clapfile.c_str())) @@ -67,15 +68,30 @@ bool buildUnitsFromClap(const std::string &clapfile, std::string &manu, std::str } int idx{0}; + + static const char *encoder = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"; for (const auto *clapPlug : loader.plugins) { auto u = auInfo(); u.name = clapPlug->name; + u.clapname = clapname; u.clapid = clapPlug->id; u.vers = clapPlug->version; u.desc = clapPlug->description; - u.subt = "FIX" + std::to_string(idx++); + static_assert(sizeof(size_t) == 8); + size_t idHash = std::hash{}(clapPlug->id); + std::string stH; + // We have to make an ascii-representable 4 char string. Here's a way I guess. + for (int i=0; i<4; ++i) + { + auto q = idHash & ((1 << 6) - 1); + stH += encoder[q]; + idHash = idHash >> 9; // mix it up a bit + } + + u.subt = stH; u.manu = manu; u.manunm = manuName; @@ -123,6 +139,7 @@ int main(int argc, char **argv) int idx = 2; auInfo u; u.name = std::string(argv[idx++]); + u.clapname = u.name; u.vers = std::string(argv[idx++]); u.type = std::string(argv[idx++]); u.subt = std::string(argv[idx++]); @@ -135,12 +152,13 @@ int main(int argc, char **argv) } else if (std::string(argv[1]) == "--fromclap") { - if (argc != 5) + if (argc != 6) { std::cout << "[ERROR] Configuration incorrect. Got " << argc << " arguments in fromclap" << std::endl; - return 5; + return 6; } int idx = 2; + auto clapname = std::string(argv[idx++]); auto clapfile = std::string(argv[idx++]); auto mcode = std::string(argv[idx++]); auto mname = std::string(argv[idx++]); @@ -160,7 +178,7 @@ int main(int argc, char **argv) std::cout << " - building information from CLAP directly\n" << " - source clap: '" << clapfile << "'" << std::endl; - if (!buildUnitsFromClap(clapfile, mcode, mname, units)) + if (!buildUnitsFromClap(clapfile, clapname, mcode, mname, units)) { std::cout << "[ERROR] Can't build units from CLAP" << std::endl; return 4; @@ -218,37 +236,39 @@ int main(int argc, char **argv) } cppf << "#pragma once\n"; - cppf << "#include \"detail/auv2/base_classes.h\"\n\n"; + cppf << "#include \"detail/auv2/auv2_base_classes.h\"\n\n"; idx = 0; for (const auto &u : units) { auto on = u.factoryBase + std::to_string(idx); + auto args = std::string("\"") + u.clapname + "\", \"" + u.clapid + "\", " + std::to_string(idx); + if (u.type == "aumu") { std::cout << " + " << u.name << " entry " << on << " from ClapWrapper_AUV2_Instrument" << std::endl; - cppf << "struct " << on << " : ClapWrapper_AUV2_Instrument {\n" + cppf << "struct " << on << " : free_audio::auv2_wrapper::ClapWrapper_AUV2_Instrument {\n" << " " << on << "(AudioComponentInstance ci) :\n" - << " ClapWrapper_AUV2_Instrument(\"" << u.clapid << "\", " << idx << ", ci) {}" + << " free_audio::auv2_wrapper::ClapWrapper_AUV2_Instrument(" << args << ", ci) {}" << "};\n" << "AUSDK_COMPONENT_ENTRY(ausdk::AUMusicDeviceFactory, " << on << ");\n"; } else if (u.type == "aumi") { std::cout << " + " << u.name << " entry " << on << " from ClapWrapper_AUV2_NoteEffect" << std::endl; - cppf << "struct " << on << " : ClapWrapper_AUV2_NoteEffect {\n" + cppf << "struct " << on << " : free_audio::auv2_wrapper::ClapWrapper_AUV2_NoteEffect {\n" << " " << on << "(AudioComponentInstance ci) :\n" - << " ClapWrapper_AUV2_NoteEffect(\"" << u.clapid << "\", " << idx << ", ci) {}" + << " free_audio::auv2_wrapper::ClapWrapper_AUV2_NoteEffect(" << args << ", ci) {}" << "};\n" << "AUSDK_COMPONENT_ENTRY(ausdk::AUBaseFactory , " << on << ");\n"; } else if (u.type == "aufx") { std::cout << " + " << u.name << " entry " << on << " from ClapWrapper_AUV2_Effect" << std::endl; - cppf << "struct " << on << " : ClapWrapper_AUV2_Effect {\n" + cppf << "struct " << on << " : free_audio::auv2_wrapper::ClapWrapper_AUV2_Effect {\n" << " " << on << "(AudioComponentInstance ci) :\n" - << " ClapWrapper_AUV2_Effect(\"" << u.clapid << "\", " << idx << ", ci) {}" + << " free_audio::auv2_wrapper::ClapWrapper_AUV2_Effect(" << args << ", ci) {}" << "};\n" << "AUSDK_COMPONENT_ENTRY(ausdk::AUBaseFactory, " << on << ");\n"; }