diff --git a/cmake/enable_sdks.cmake b/cmake/enable_sdks.cmake index cbf83f5d..2640b771 100644 --- a/cmake/enable_sdks.cmake +++ b/cmake/enable_sdks.cmake @@ -9,6 +9,7 @@ # make CPM available include(cmake/CPM.cmake) + if (${CLAP_WRAPPER_DOWNLOAD_DEPENDENCIES}) message(STATUS "clap-wrapper: Downloading dependencies using CPM") @@ -247,6 +248,34 @@ if (APPLE) endif() endif() + +add_library(clap-wrapper-compile-options INTERFACE) +add_library(clap-wrapper-sanitizer-options INTERFACE) + +target_compile_options(clap-wrapper-compile-options INTERFACE -D${CLAP_WRAPPER_PLATFORM}=1) +if (APPLE) + target_link_libraries(clap-wrapper-compile-options INTERFACE macos_filesystem_support) +endif() +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") + target_compile_options(clap-wrapper-compile-options INTERFACE -Wall -Wextra -Wno-unused-parameter -Wpedantic -Werror) + if (${CLAP_WRAPPER_ENABLE_SANITIZER}) + message(STATUS "clap-wrapper: enabling sanitizer build") + + target_compile_options(clap-wrapper-sanitizer-options INTERFACE + -fsanitize=address,undefined,float-divide-by-zero + -fsanitize-address-use-after-return=always + -fsanitize-address-use-after-scope + ) + target_link_options(clap-wrapper-sanitizer-options INTERFACE + -fsanitize=address,undefined,float-divide-by-zero + -fsanitize-address-use-after-return=always + -fsanitize-address-use-after-scope + ) + target_link_libraries(clap-wrapper-compile-options INTERFACE clap-wrapper-sanitizer-options) + endif() +endif() + + # define libraries function(target_add_vst3_wrapper) set(oneValueArgs @@ -291,6 +320,7 @@ function(target_add_vst3_wrapper) add_library(base-sdk-vst3 STATIC ${vst3sources}) target_include_directories(base-sdk-vst3 PUBLIC ${VST3_SDK_ROOT} ${VST3_SDK_ROOT}/public.sdk ${VST3_SDK_ROOT}/pluginterfaces) target_compile_options(base-sdk-vst3 PUBLIC $,-DDEVELOPMENT=1,-DRELEASE=1>) # work through steinbergs alternate choices for these + target_link_libraries(base-sdk-vst3 PUBLIC clap-wrapper-sanitizer-options) # The VST3SDK uses sprintf, not snprintf, which macOS flags as deprecated # to move people to snprintf. Silence that warning on the VST3 build if (APPLE) @@ -322,19 +352,11 @@ function(target_add_vst3_wrapper) target_link_libraries(${V3_TARGET}-clap-wrapper-vst3-lib PUBLIC clap base-sdk-vst3) # clap-wrapper-extensions are PUBLIC, so a clap linking the library can access the clap-wrapper-extensions - target_compile_definitions(${V3_TARGET}-clap-wrapper-vst3-lib PUBLIC -D${CLAP_WRAPPER_PLATFORM}=1) - target_link_libraries(${V3_TARGET}-clap-wrapper-vst3-lib PUBLIC clap-wrapper-extensions clap-wrapper-shared-detail) + target_link_libraries(${V3_TARGET}-clap-wrapper-vst3-lib PUBLIC clap-wrapper-extensions clap-wrapper-compile-options clap-wrapper-shared-detail) target_compile_options(${V3_TARGET}-clap-wrapper-vst3-lib PRIVATE -DCLAP_SUPPORTS_ALL_NOTE_EXPRESSIONS=$,1,0> ) - - if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU") - target_compile_options(${V3_TARGET}-clap-wrapper-vst3-lib PRIVATE -Wall -Wextra -Wno-unused-parameter -Wpedantic -Werror) - endif() - if (APPLE) - target_link_libraries(${V3_TARGET}-clap-wrapper-vst3-lib PUBLIC macos_filesystem_support) - endif() endif() @@ -588,8 +610,7 @@ if (APPLE) target_link_libraries(${AUV2_TARGET}-clap-wrapper-auv2-lib INTERFACE clap base-sdk-auv2) # 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 clap-wrapper-shared-detail macos_filesystem_support) + target_link_libraries(${AUV2_TARGET}-clap-wrapper-auv2-lib INTERFACE clap-wrapper-extensions clap-wrapper-shared-detail clap-wrapper-compile-options) endif() @@ -653,15 +674,10 @@ add_library(clap-wrapper-shared-detail STATIC src/detail/clap/fsutil.cpp src/detail/clap/automation.h ) -target_compile_options(clap-wrapper-shared-detail PUBLIC -D${CLAP_WRAPPER_PLATFORM}=1) -target_link_libraries(clap-wrapper-shared-detail PUBLIC clap clap-wrapper-extensions) +target_link_libraries(clap-wrapper-shared-detail PUBLIC clap clap-wrapper-extensions clap-wrapper-compile-options) 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 diff --git a/src/detail/auv2/auv2_shared.h b/src/detail/auv2/auv2_shared.h index 99ce22df..b3f445c9 100644 --- a/src/detail/auv2/auv2_shared.h +++ b/src/detail/auv2/auv2_shared.h @@ -53,7 +53,7 @@ struct ClapBridge if (_clapid.empty()) { - if (_idx < 0 || _idx >= _library.plugins.size()) + if (_idx < 0 || _idx >= (int)_library.plugins.size()) { std::cout << "[ERROR] cannot load by index" << std::endl; return; diff --git a/src/detail/auv2/build-helper/build-helper.cpp b/src/detail/auv2/build-helper/build-helper.cpp index 06b59521..97594ded 100644 --- a/src/detail/auv2/build-helper/build-helper.cpp +++ b/src/detail/auv2/build-helper/build-helper.cpp @@ -132,13 +132,16 @@ bool buildUnitsFromClap(const std::string &clapfile, const std::string &clapname clap_plugin_info_as_auv2_t v2inf; auto res = loader._pluginFactoryAUv2Info->get_auv2_info(loader._pluginFactoryAUv2Info, idx, &v2inf); - if (v2inf.au_type[0] != 0) + if (res) { - u.type = v2inf.au_type; - } - if (v2inf.au_subt[0] != 0) - { - u.subt = v2inf.au_subt; + if (v2inf.au_type[0] != 0) + { + u.type = v2inf.au_type; + } + if (v2inf.au_subt[0] != 0) + { + u.subt = v2inf.au_subt; + } } } diff --git a/src/detail/vst3/os/osutil.h b/src/detail/vst3/os/osutil.h index c1d2572b..30d9dea0 100644 --- a/src/detail/vst3/os/osutil.h +++ b/src/detail/vst3/os/osutil.h @@ -7,12 +7,54 @@ #include #include +#include #define FMT_HEADER_ONLY 1 #include "fmt/format.h" #include "fmt/ranges.h" namespace os { + +class State +{ + // the State class ensures that a specific function pair (like init/terminate) is only called in pairs. + // the bool _state reflects if the _on lambda has already been called + // on destruction, it makes sure that the _off lambda is definitely called. + // + // the construct should only be applied to when no state machine can cover this properly + // or your own code depends on correct calling sequences of an external code base and should + // help to implement defensive programming. + + public: + State(std::function on, std::function off) : _on(on), _off(off) + { + } + ~State() + { + off(); + } + void on() + { + if (!_state) + { + _on(); + } + _state = true; + } + void off() + { + if (_state) + { + _off(); + } + _state = false; + } + + private: + bool _state = false; + std::function _on, _off; +}; + class IPlugObject { public: @@ -90,4 +132,4 @@ class fixedqueue std::atomic_uint32_t _head = 0u; std::atomic_uint32_t _tail = 0u; }; -}; // namespace util \ No newline at end of file +}; // namespace util diff --git a/src/wrapasvst3.cpp b/src/wrapasvst3.cpp index 2e081662..97a8204e 100644 --- a/src/wrapasvst3.cpp +++ b/src/wrapasvst3.cpp @@ -60,6 +60,7 @@ tresult PLUGIN_API ClapAsVst3::terminate() { if (_plugin) { + _os_attached.off(); // ensure we are detached _plugin->terminate(); _plugin.reset(); } @@ -87,11 +88,12 @@ tresult PLUGIN_API ClapAsVst3::setActive(TBool state) _expressionmap & clap_supported_note_expressions::AS_VST3_NOTE_EXPRESSION_TUNING); updateAudioBusses(); - os::attach(this); + _os_attached.on(); } if (!state) { - os::detach(this); + _os_attached.off(); + if (_active) { _plugin->deactivate(); @@ -461,7 +463,6 @@ Vst::UnitID ClapAsVst3::getOrCreateUnitInfo(const char* modulename) } else { - // the unit needs to be created Steinberg::Vst::String128 name; std::string u8name(path[i]); if (VST3::StringConvert::convert(u8name, name)) @@ -581,10 +582,14 @@ void ClapAsVst3::setupParameters(const clap_plugin_t* plugin, const clap_plugin_ units.clear(); { - Vst::String128 rootname(STR16("root")); - Vst::Unit* newunit = new Vst::Unit(rootname, Vst::kNoParentUnitId, - Vst::kRootUnitId); // a new unit without a program list - addUnit(newunit); + Vst::UnitInfo rootInfo; + rootInfo.id = Vst::kRootUnitId; + rootInfo.parentUnitId = Vst::kNoParentUnitId; + rootInfo.programListId = Vst::kNoProgramListId; + VST3::StringConvert::convert(std::string("Root"), rootInfo.name); + + auto rootUnit = new Vst::Unit(rootInfo); + addUnit(rootUnit); } auto numparams = params->count(plugin); diff --git a/src/wrapasvst3.h b/src/wrapasvst3.h index 579bbf33..eca10d7d 100644 --- a/src/wrapasvst3.h +++ b/src/wrapasvst3.h @@ -108,6 +108,7 @@ class ClapAsVst3 : public Steinberg::Vst::SingleComponentEffect, , _library(lib) , _libraryIndex(number) , _creationcontext(context) + , _os_attached([this] { os::attach(this); }, [this] { os::detach(this); }) { } @@ -253,6 +254,7 @@ class ClapAsVst3 : public Steinberg::Vst::SingleComponentEffect, // plugin state bool _active = false; + os::State _os_attached; bool _processing = false; std::mutex _processingLock; std::atomic_bool _requestedFlush = false;