diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..7533d123 --- /dev/null +++ b/.clang-format @@ -0,0 +1,19 @@ +--- +UseTab: Never +--- +Language: Cpp +IndentWidth: 2 +AlignAfterOpenBracket: Align +BreakBeforeBraces: Allman +ColumnLimit: 120 +SortIncludes: false +NamespaceIndentation: All +--- +Language: ObjC +IndentWidth: 2 +AlignAfterOpenBracket: Align +BreakBeforeBraces: Allman +ColumnLimit: 120 +SortIncludes: false +NamespaceIndentation: All +... diff --git a/.github/workflows/code-checks.yml b/.github/workflows/code-checks.yml new file mode 100644 index 00000000..e16f9897 --- /dev/null +++ b/.github/workflows/code-checks.yml @@ -0,0 +1,21 @@ +name: Clap Wrapper Format and Code Checks +on: [pull_request] + +defaults: + run: + shell: bash + +jobs: + build-code-checks: + name: code-checks + runs-on: ubuntu-latest + strategy: + fail-fast: true + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + - name: Run Code Checks + run: | + cmake -Bbuild -DCLAP_WRAPPER_CODE_CHECKS_ONLY=TRUE + cmake --build build --target clap-wrapper-code-checks diff --git a/CMakeLists.txt b/CMakeLists.txt index bff1b282..332c3046 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,7 +55,11 @@ set(CMAKE_VISIBILITY_INLINES_HIDDEN ON) # defines functions relative to this, so needs a cache # variable with the source dir set(CLAP_WRAPPER_CMAKE_CURRENT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE STRING "Clap Wrapper Source Location") -include(cmake/enable_sdks.cmake) +if (DEFINED CLAP_WRAPPER_CODE_CHECKS_ONLY) + message(STATUS "clap-wrapper: code checks only; skipping enable sdks") +else() + include(cmake/enable_sdks.cmake) +endif() # automatically build the wrapper only if this is the top level project set(skipbuild FALSE) @@ -64,6 +68,9 @@ if (NOT PROJECT_IS_TOP_LEVEL) set(skipbuild TRUE) endif() endif() +if (DEFINED CLAP_WRAPPER_CODE_CHECKS_ONLY) + set(skipbuild ${CLAP_WRAPPER_CODE_CHECKS_ONLY}) +endif() if (${skipbuild}) message(STATUS "clap-wrapper: Skipping clap wrapper target ejection") @@ -106,3 +113,23 @@ else() endif() endif() endif() + + +add_custom_target(clap-wrapper-code-checks) + +# Clang Format checks +find_program(CLANG_FORMAT_EXE NAMES clang-format-12 clang-format) +set(CLANG_FORMAT_DIRS src) +set(CLANG_FORMAT_EXTS cpp h) +foreach(dir ${CLANG_FORMAT_DIRS}) + foreach(ext ${CLANG_FORMAT_EXTS}) + list(APPEND CLANG_FORMAT_GLOBS "':(glob)${dir}/**/*.${ext}'") + endforeach() +endforeach() +add_custom_command(TARGET clap-wrapper-code-checks + POST_BUILD + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMAND ${CMAKE_COMMAND} -E echo About to check clang-format using ${CLANG_FORMAT_EXE} + COMMAND git ls-files -- ${CLANG_FORMAT_GLOBS} | xargs ${CLANG_FORMAT_EXE} --dry-run --Werror + ) +# }}} \ No newline at end of file diff --git a/src/clap_proxy.cpp b/src/clap_proxy.cpp index 79f8bf47..fe1b1f6a 100644 --- a/src/clap_proxy.cpp +++ b/src/clap_proxy.cpp @@ -12,32 +12,20 @@ namespace Clap { namespace HostExt { - static Plugin* self(const clap_host_t* host) - { - return static_cast(host->host_data); - } + static Plugin *self(const clap_host_t *host) { return static_cast(host->host_data); } - void host_log(const clap_host_t* host, clap_log_severity severity, const char* msg) + void host_log(const clap_host_t *host, clap_log_severity severity, const char *msg) { self(host)->log(severity, msg); } - clap_host_log_t log = - { - host_log - }; + clap_host_log_t log = {host_log}; - void rescan(const clap_host_t* host, clap_param_rescan_flags flags) - { - self(host)->param_rescan(flags); - } + void rescan(const clap_host_t *host, clap_param_rescan_flags flags) { self(host)->param_rescan(flags); } // Clears references to a parameter. // [main-thread] - void clear(const clap_host_t* host, clap_id param_id, clap_param_clear_flags flags) - { - - } + void clear(const clap_host_t *host, clap_id param_id, clap_param_clear_flags flags) {} // Request a parameter flush. // @@ -49,86 +37,58 @@ namespace Clap // // This must not be called on the [audio-thread]. // [thread-safe,!audio-thread] - void request_flush(const clap_host_t* host) - { - self(host)->param_request_flush(); - } - clap_host_params_t params = - { - rescan, clear, request_flush - }; + void request_flush(const clap_host_t *host) { self(host)->param_request_flush(); } + clap_host_params_t params = {rescan, clear, request_flush}; - bool is_main_thread(const clap_host_t* host) - { - return self(host)->is_main_thread(); - } + bool is_main_thread(const clap_host_t *host) { return self(host)->is_main_thread(); } // Returns true if "this" thread is one of the audio threads. // [thread-safe] - bool is_audio_thread(const clap_host_t* host) - { - return self(host)->is_audio_thread(); - } + bool is_audio_thread(const clap_host_t *host) { return self(host)->is_audio_thread(); } - clap_host_thread_check_t threadcheck = - { - is_main_thread, is_audio_thread - }; + clap_host_thread_check_t threadcheck = {is_main_thread, is_audio_thread}; - static void resize_hints_changed(const clap_host_t* host) + static void resize_hints_changed(const clap_host_t *host) { self(host)->resize_hints_changed(); } + static bool request_resize(const clap_host_t *host, uint32_t width, uint32_t height) { - self(host)->resize_hints_changed(); - } - static bool request_resize(const clap_host_t* host, uint32_t width, uint32_t height) - { return self(host)->request_resize(width, height); } - static bool request_show(const clap_host_t* host) - { - return self(host)->request_show(); - } - static bool request_hide(const clap_host_t* host) - { - return self(host)->request_hide(); - } - static void closed(const clap_host_t* host, bool was_destroyed) - { - self(host)->closed(was_destroyed); - } + static bool request_show(const clap_host_t *host) { return self(host)->request_show(); } + static bool request_hide(const clap_host_t *host) { return self(host)->request_hide(); } + static void closed(const clap_host_t *host, bool was_destroyed) { self(host)->closed(was_destroyed); } - const clap_host_gui hostgui = { - resize_hints_changed,request_resize,request_show,request_hide,closed }; + const clap_host_gui hostgui = {resize_hints_changed, request_resize, request_show, request_hide, closed}; - const clap_host_timer_support hosttimer = { - /* register_timer */ [](const clap_host_t* host, uint32_t period_ms, clap_id* timer_id) -> bool { return self(host)->register_timer(period_ms, timer_id); }, - /* unregister_timer */ [](const clap_host_t* host, clap_id timer_id) -> bool { return self(host)->unregister_timer(timer_id); } - }; + const clap_host_timer_support hosttimer = { + /* register_timer */ [](const clap_host_t *host, uint32_t period_ms, clap_id *timer_id) -> bool + { return self(host)->register_timer(period_ms, timer_id); }, + /* unregister_timer */ + [](const clap_host_t *host, clap_id timer_id) -> bool { return self(host)->unregister_timer(timer_id); }}; #if LIN const clap_host_posix_fd_support hostposixfd = { - [](const clap_host_t *host, int fd, clap_posix_fd_flags_t flags) -> bool { return self(host)->register_fd(fd, flags);}, - [](const clap_host_t *host, int fd, clap_posix_fd_flags_t flags) -> bool { return self(host)->modify_fd(fd, flags);}, - [](const clap_host_t *host, int fd) -> bool { return self(host)->unregister_fd(fd);} - }; + [](const clap_host_t *host, int fd, clap_posix_fd_flags_t flags) -> bool + { return self(host)->register_fd(fd, flags); }, + [](const clap_host_t *host, int fd, clap_posix_fd_flags_t flags) -> bool + { return self(host)->modify_fd(fd, flags); }, + [](const clap_host_t *host, int fd) -> bool { return self(host)->unregister_fd(fd); }}; #endif - const clap_host_latency latency = { [](const clap_host_t* host) -> void { self(host)->latency_changed(); } }; + const clap_host_latency latency = {[](const clap_host_t *host) -> void { self(host)->latency_changed(); }}; - static void tail_changed(const clap_host_t* host) - { - self(host)->tail_changed(); - } + static void tail_changed(const clap_host_t *host) { self(host)->tail_changed(); } - const clap_host_tail tail = { tail_changed }; + const clap_host_tail tail = {tail_changed}; - } + } // namespace HostExt - std::shared_ptr Plugin::createInstance(Clap::Library& library, size_t index, IHost* host) + std::shared_ptr Plugin::createInstance(Clap::Library &library, size_t index, IHost *host) { if (library.plugins.size() > index) { auto plug = std::shared_ptr(new Plugin(host)); - auto instance = library._pluginFactory->create_plugin(library._pluginFactory, plug->getClapHostInterface(), library.plugins[index]->id); + auto instance = library._pluginFactory->create_plugin(library._pluginFactory, plug->getClapHostInterface(), + library.plugins[index]->id); plug->connectClap(instance); return plug; @@ -136,31 +96,27 @@ namespace Clap return nullptr; } - Plugin::Plugin(IHost* host) - : _host{ - CLAP_VERSION, - this, - "Clap-As-VST3-Wrapper", - "defiant nerd", - "https://www.defiantnerd.com", - "0.0.1", - Plugin::clapExtension, - Plugin::clapRequestRestart, - Plugin::clapRequestProcess, - Plugin::clapRequestCallback - } - , _parentHost(host) + Plugin::Plugin(IHost *host) + : _host{CLAP_VERSION, + this, + "Clap-As-VST3-Wrapper", + "defiant nerd", + "https://www.defiantnerd.com", + "0.0.1", + Plugin::clapExtension, + Plugin::clapRequestRestart, + Plugin::clapRequestProcess, + Plugin::clapRequestCallback}, + _parentHost(host) { - } - template - void getExtension(const clap_plugin_t* plugin, T& ref, const char* name) + template void getExtension(const clap_plugin_t *plugin, T &ref, const char *name) { ref = static_cast(plugin->get_extension(plugin, name)); } - void Plugin::connectClap(const clap_plugin_t* clap) + void Plugin::connectClap(const clap_plugin_t *clap) { _plugin = clap; @@ -189,15 +145,15 @@ namespace Clap if (_ext._gui) { - const char* api; + const char *api; #if WIN - api = CLAP_WINDOW_API_WIN32; + api = CLAP_WINDOW_API_WIN32; #endif #if MAC - api = CLAP_WINDOW_API_COCOA; + api = CLAP_WINDOW_API_COCOA; #endif #if LIN - api = CLAP_WINDOW_API_X11; + api = CLAP_WINDOW_API_X11; #endif if (!_ext._gui->is_api_supported(_plugin, api, false)) @@ -215,14 +171,9 @@ namespace Clap _plugin->destroy(_plugin); _plugin = nullptr; } - - } - - void Plugin::schnick() - { - } + void Plugin::schnick() {} bool Plugin::initialize() { @@ -250,10 +201,7 @@ namespace Clap _plugin = nullptr; } - void Plugin::setSampleRate(double sampleRate) - { - _audioSetup.sampleRate = sampleRate; - } + void Plugin::setSampleRate(double sampleRate) { _audioSetup.sampleRate = sampleRate; } void Plugin::setBlockSizes(uint32_t minFrames, uint32_t maxFrames) { @@ -261,7 +209,7 @@ namespace Clap _audioSetup.maxFrames = maxFrames; } - bool Plugin::load(const clap_istream_t* stream) + bool Plugin::load(const clap_istream_t *stream) { if (_ext._state) { @@ -270,7 +218,7 @@ namespace Clap return false; } - bool Plugin::save(const clap_ostream_t* stream) + bool Plugin::save(const clap_ostream_t *stream) { if (_ext._state) { @@ -284,10 +232,7 @@ namespace Clap return _plugin->activate(_plugin, _audioSetup.sampleRate, _audioSetup.minFrames, _audioSetup.maxFrames); } - void Plugin::deactivate() - { - _plugin->deactivate(_plugin); - } + void Plugin::deactivate() { _plugin->deactivate(_plugin); } bool Plugin::start_processing() { @@ -301,13 +246,13 @@ namespace Clap _plugin->stop_processing(_plugin); } - //void Plugin::process(const clap_process_t* data) + // void Plugin::process(const clap_process_t* data) //{ - // auto thisFn = AlwaysAudioThread(); - // _plugin->process(_plugin, data); - //} + // auto thisFn = AlwaysAudioThread(); + // _plugin->process(_plugin, data); + // } - const clap_plugin_gui_t* Plugin::getUI() + const clap_plugin_gui_t *Plugin::getUI() { if (_ext._gui) { @@ -319,17 +264,11 @@ namespace Clap return nullptr; } - void Plugin::latency_changed() - { - _parentHost->latency_changed(); - } + void Plugin::latency_changed() { _parentHost->latency_changed(); } - void Plugin::tail_changed() - { - _parentHost->tail_changed(); - } + void Plugin::tail_changed() { _parentHost->tail_changed(); } - void Plugin::log(clap_log_severity severity, const char* msg) + void Plugin::log(clap_log_severity severity, const char *msg) { std::string n; switch (severity) @@ -359,7 +298,7 @@ namespace Clap _CrtDbgBreak(); #endif #if MAC - fprintf(stderr,"%s\n",msg); + fprintf(stderr, "%s\n", msg); #endif break; } @@ -369,14 +308,11 @@ namespace Clap OutputDebugStringA("\n"); #endif #if MAC - fprintf(stderr,"%s\n",n.c_str()); + fprintf(stderr, "%s\n", n.c_str()); #endif } - bool Plugin::is_main_thread() const - { - return _main_thread_id == std::this_thread::get_id(); - } + bool Plugin::is_main_thread() const { return _main_thread_id == std::this_thread::get_id(); } bool Plugin::is_audio_thread() const { @@ -387,33 +323,20 @@ namespace Clap return !is_main_thread(); } - CLAP_NODISCARD Raise Plugin::AlwaysAudioThread() - { - return Raise(this->_audio_thread_override); - } + CLAP_NODISCARD Raise Plugin::AlwaysAudioThread() { return Raise(this->_audio_thread_override); } + void Plugin::param_rescan(clap_param_rescan_flags flags) { _parentHost->param_rescan(flags); } - void Plugin::param_rescan(clap_param_rescan_flags flags) - { - _parentHost->param_rescan(flags); - } - - void Plugin::param_clear(clap_id param, clap_param_clear_flags flags) - { - _parentHost->param_clear(param, flags); - } - void Plugin::param_request_flush() - { - _parentHost->param_request_flush(); - } + void Plugin::param_clear(clap_id param, clap_param_clear_flags flags) { _parentHost->param_clear(param, flags); } + void Plugin::param_request_flush() { _parentHost->param_request_flush(); } // Query an extension. // [thread-safe] - const void* Plugin::clapExtension(const clap_host* host, const char* extension) + const void *Plugin::clapExtension(const clap_host *host, const char *extension) { if (!strcmp(extension, CLAP_EXT_LOG)) return &HostExt::log; - if (!strcmp(extension, CLAP_EXT_PARAMS)) + if (!strcmp(extension, CLAP_EXT_PARAMS)) return &HostExt::params; if (!strcmp(extension, CLAP_EXT_THREAD_CHECK)) return &HostExt::threadcheck; @@ -441,52 +364,43 @@ namespace Clap // Request the host to schedule a call to plugin->on_main_thread(plugin) on the main thread. // [thread-safe] - void Plugin::clapRequestCallback(const clap_host* host) + void Plugin::clapRequestCallback(const clap_host *host) { - auto self = static_cast(host->host_data); + auto self = static_cast(host->host_data); self->_parentHost->request_callback(); } // Request the host to deactivate and then reactivate the plugin. // The operation may be delayed by the host. // [thread-safe] - void Plugin::clapRequestRestart(const clap_host* host) + void Plugin::clapRequestRestart(const clap_host *host) { - auto self = static_cast(host->host_data); + auto self = static_cast(host->host_data); self->_parentHost->restartPlugin(); } // Request the host to activate and start processing the plugin. // This is useful if you have external IO and need to wake up the plugin from "sleep". // [thread-safe] - void Plugin::clapRequestProcess(const clap_host* host) + void Plugin::clapRequestProcess(const clap_host *host) { // right now, I don't know how to communicate this to the host // in VST3 you can't force processing... } // Registers a periodic timer. -// The host may adjust the period if it is under a certain threshold. -// 30 Hz should be allowed. -// [main-thread] - bool Plugin::register_timer(uint32_t period_ms, clap_id* timer_id) + // The host may adjust the period if it is under a certain threshold. + // 30 Hz should be allowed. + // [main-thread] + bool Plugin::register_timer(uint32_t period_ms, clap_id *timer_id) { return _parentHost->register_timer(period_ms, timer_id); } - bool Plugin::unregister_timer(clap_id timer_id) - { - return _parentHost->unregister_timer(timer_id); - } + bool Plugin::unregister_timer(clap_id timer_id) { return _parentHost->unregister_timer(timer_id); } #if LIN - bool Plugin::register_fd(int fd, clap_posix_fd_flags_t flags) - { - return _parentHost->register_fd(fd, flags); - } - bool Plugin::modify_fd(int fd, clap_posix_fd_flags_t flags) - { - return _parentHost->modify_fd(fd, flags); - } + bool Plugin::register_fd(int fd, clap_posix_fd_flags_t flags) { return _parentHost->register_fd(fd, flags); } + bool Plugin::modify_fd(int fd, clap_posix_fd_flags_t flags) { return _parentHost->modify_fd(fd, flags); } bool Plugin::unregister_fd(int fd) { return _parentHost->unregister_fd(fd); } #endif - } +} // namespace Clap diff --git a/src/clap_proxy.h b/src/clap_proxy.h index b9773ea8..d7a3c3ca 100644 --- a/src/clap_proxy.h +++ b/src/clap_proxy.h @@ -39,13 +39,18 @@ namespace Clap virtual void restartPlugin() = 0; virtual void request_callback() = 0; - virtual void setupWrapperSpecifics(const clap_plugin_t* plugin) = 0; // called when a wrapper could scan for wrapper specific plugins - - virtual void setupAudioBusses(const clap_plugin_t* plugin, const clap_plugin_audio_ports_t* audioports) = 0; // called from initialize() to allow the setup of audio ports - virtual void setupMIDIBusses(const clap_plugin_t* plugin, const clap_plugin_note_ports_t* noteports) = 0; // called from initialize() to allow the setup of MIDI ports - virtual void setupParameters(const clap_plugin_t* plugin, const clap_plugin_params_t* params) = 0; - - virtual void param_rescan(clap_param_rescan_flags flags) = 0; // ext_host_params + virtual void setupWrapperSpecifics( + const clap_plugin_t *plugin) = 0; // called when a wrapper could scan for wrapper specific plugins + + virtual void setupAudioBusses( + const clap_plugin_t *plugin, + const clap_plugin_audio_ports_t *audioports) = 0; // called from initialize() to allow the setup of audio ports + virtual void setupMIDIBusses( + const clap_plugin_t *plugin, + const clap_plugin_note_ports_t *noteports) = 0; // called from initialize() to allow the setup of MIDI ports + virtual void setupParameters(const clap_plugin_t *plugin, const clap_plugin_params_t *params) = 0; + + virtual void param_rescan(clap_param_rescan_flags flags) = 0; // ext_host_params virtual void param_clear(clap_id param, clap_param_clear_flags flags) = 0; virtual void param_request_flush() = 0; @@ -54,7 +59,7 @@ namespace Clap virtual bool gui_request_show() = 0; virtual bool gui_request_hide() = 0; - virtual bool register_timer(uint32_t period_ms, clap_id* timer_id) = 0; + virtual bool register_timer(uint32_t period_ms, clap_id *timer_id) = 0; virtual bool unregister_timer(clap_id timer_id) = 0; #if LIN @@ -66,11 +71,10 @@ namespace Clap virtual void latency_changed() = 0; virtual void tail_changed() = 0; - }; struct ClapPluginExtensions; - + struct AudioSetup { double sampleRate = 44100.; @@ -80,36 +84,29 @@ namespace Clap struct ClapPluginExtensions { - const clap_plugin_state_t* _state = nullptr; - const clap_plugin_params_t* _params = nullptr; - const clap_plugin_audio_ports_t* _audioports = nullptr; - const clap_plugin_gui_t* _gui = nullptr; - const clap_plugin_note_ports_t* _noteports = nullptr; - const clap_plugin_midi_mappings_t* _midimap = nullptr; - const clap_plugin_latency_t* _latency = nullptr; - const clap_plugin_render_t* _render = nullptr; - const clap_plugin_tail_t* _tail = nullptr; - const clap_plugin_timer_support_t* _timer = nullptr; + const clap_plugin_state_t *_state = nullptr; + const clap_plugin_params_t *_params = nullptr; + const clap_plugin_audio_ports_t *_audioports = nullptr; + const clap_plugin_gui_t *_gui = nullptr; + const clap_plugin_note_ports_t *_noteports = nullptr; + const clap_plugin_midi_mappings_t *_midimap = nullptr; + const clap_plugin_latency_t *_latency = nullptr; + const clap_plugin_render_t *_render = nullptr; + const clap_plugin_tail_t *_tail = nullptr; + const clap_plugin_timer_support_t *_timer = nullptr; #if LIN - const clap_plugin_posix_fd_support* _posixfd = nullptr; + const clap_plugin_posix_fd_support *_posixfd = nullptr; #endif - }; class Raise { public: - Raise(std::atomic& counter) - : ctx(counter) - { - ++ctx; - } - ~Raise() - { - ctx--; - } + Raise(std::atomic &counter) : ctx(counter) { ++ctx; } + ~Raise() { ctx--; } + private: - std::atomic& ctx; + std::atomic &ctx; }; /// @@ -119,17 +116,19 @@ namespace Clap class Plugin { public: - static std::shared_ptr createInstance(Clap::Library& library, size_t index, IHost* host); + static std::shared_ptr createInstance(Clap::Library &library, size_t index, IHost *host); + protected: // only the Clap::Library is allowed to create instances - Plugin(IHost* host); - const clap_host_t* getClapHostInterface() { return &_host; } - void connectClap(const clap_plugin_t* clap); + Plugin(IHost *host); + const clap_host_t *getClapHostInterface() { return &_host; } + void connectClap(const clap_plugin_t *clap); + public: - Plugin(const Plugin&) = delete; - Plugin(Plugin&&) = delete; - Plugin& operator=(const Plugin&) = delete; - Plugin& operator=(Plugin&&) = delete; + Plugin(const Plugin &) = delete; + Plugin(Plugin &&) = delete; + Plugin &operator=(const Plugin &) = delete; + Plugin &operator=(Plugin &&) = delete; ~Plugin(); void schnick(); @@ -138,18 +137,18 @@ namespace Clap void setSampleRate(double sampleRate); void setBlockSizes(uint32_t minFrames, uint32_t maxFrames); - bool load(const clap_istream_t* stream); - bool save(const clap_ostream_t* stream); + bool load(const clap_istream_t *stream); + bool save(const clap_ostream_t *stream); bool activate(); void deactivate(); bool start_processing(); void stop_processing(); // void process(const clap_process_t* data); - const clap_plugin_gui_t* getUI(); + const clap_plugin_gui_t *getUI(); ClapPluginExtensions _ext; - const clap_plugin_t* _plugin = nullptr; - void log(clap_log_severity severity, const char* msg); + const clap_plugin_t *_plugin = nullptr; + void log(clap_log_severity severity, const char *msg); // threadcheck bool is_main_thread() const; @@ -167,9 +166,7 @@ namespace Clap void tail_changed(); // hostgui - void resize_hints_changed() - { - } + void resize_hints_changed() {} bool request_resize(uint32_t width, uint32_t height) { if (_parentHost->gui_can_resize()) @@ -179,20 +176,12 @@ namespace Clap } return false; } - bool request_show() - { - return _parentHost->gui_request_show(); - } - bool request_hide() - { - return false; - } - void closed(bool was_destroyed) - { - } + bool request_show() { return _parentHost->gui_request_show(); } + bool request_hide() { return false; } + void closed(bool was_destroyed) {} // clap_timer support - bool register_timer(uint32_t period_ms, clap_id* timer_id); + bool register_timer(uint32_t period_ms, clap_id *timer_id); bool unregister_timer(clap_id timer_id); #if LIN @@ -202,21 +191,20 @@ namespace Clap #endif CLAP_NODISCARD Raise AlwaysAudioThread(); - private: - - static const void* clapExtension(const clap_host* host, const char* extension); - static void clapRequestCallback(const clap_host* host); - static void clapRequestRestart(const clap_host* host); - static void clapRequestProcess(const clap_host* host); - //static bool clapIsMainThread(const clap_host* host); - //static bool clapIsAudioThread(const clap_host* host); + private: + static const void *clapExtension(const clap_host *host, const char *extension); + static void clapRequestCallback(const clap_host *host); + static void clapRequestRestart(const clap_host *host); + static void clapRequestProcess(const clap_host *host); + // static bool clapIsMainThread(const clap_host* host); + // static bool clapIsAudioThread(const clap_host* host); - clap_host_t _host; // the host_t structure for the proxy - IHost* _parentHost = nullptr; + clap_host_t _host; // the host_t structure for the proxy + IHost *_parentHost = nullptr; const std::thread::id _main_thread_id = std::this_thread::get_id(); std::atomic _audio_thread_override = 0; AudioSetup _audioSetup; }; -} \ No newline at end of file +} // namespace Clap \ No newline at end of file diff --git a/src/detail/auv2/auv2_base_classes.h b/src/detail/auv2/auv2_base_classes.h index 1f56fcc5..2dc42ba3 100644 --- a/src/detail/auv2/auv2_base_classes.h +++ b/src/detail/auv2/auv2_base_classes.h @@ -15,65 +15,62 @@ namespace free_audio::auv2_wrapper { - // ------------------------------------------------------------------------------------------------- + // ------------------------------------------------------------------------------------------------- - class ClapWrapper_AUV2_Effect : public ausdk::AUEffectBase + 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) { - 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 + 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) { - 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; + std::cout << "[clap-wrapper] auv2: creating note effect" << std::endl; + std::cout << "[clap-wrapper] auv2: id='" << clapid << "' index=" << clapidx << std::endl; + bridge.initialize(); + } + }; - bridge.initialize(); - } - }; + // ------------------------------------------------------------------------------------------------- - // ------------------------------------------------------------------------------------------------- + class ClapWrapper_AUV2_Instrument : public ausdk::MusicDeviceBase + { + using Base = ausdk::MusicDeviceBase; + ClapBridge bridge; - class ClapWrapper_AUV2_Instrument : public ausdk::MusicDeviceBase + 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) { - 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 + 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 index 7b52652b..4a9167d3 100644 --- a/src/detail/auv2/auv2_shared.h +++ b/src/detail/auv2/auv2_shared.h @@ -4,66 +4,79 @@ #include "detail/clap/fsutil.h" #include -namespace free_audio::auv2_wrapper { -struct ClapBridge { - std::string _clapname; - std::string _clapid; - int _idx; +namespace free_audio::auv2_wrapper +{ + struct ClapBridge + { + std::string _clapname; + std::string _clapid; + int _idx; - Clap::Library _library; + Clap::Library _library; - const clap_plugin_descriptor_t *_desc{nullptr}; + const clap_plugin_descriptor_t *_desc{nullptr}; - ClapBridge(const std::string &clapname, const std::string &clapid, int idx) - : _clapname(clapname), _clapid(clapid), _idx(idx) { - std::cout << "[clap-wraper] auv2: creating clap bridge nm=" << clapname - << " id=" << clapid << " idx=" << idx << std::endl; - } + ClapBridge(const std::string &clapname, const std::string &clapid, int idx) + : _clapname(clapname), _clapid(clapid), _idx(idx) + { + std::cout << "[clap-wraper] auv2: creating clap bridge nm=" << clapname << " id=" << clapid << " idx=" << idx + << std::endl; + } - void initialize() { - if (!_library.hasEntryPoint()) { - if (_clapname.empty()) { - std::cout << "[ERROR] _clapname (" << _clapname - << ") empty and no internal entry point" << std::endl; + void initialize() + { + if (!_library.hasEntryPoint()) + { + if (_clapname.empty()) + { + std::cout << "[ERROR] _clapname (" << _clapname << ") empty and no internal entry point" << std::endl; + } + bool loaded{false}; + auto csp = Clap::getValidCLAPSearchPaths(); + for (auto &cs : csp) + { + if (fs::is_directory(cs / (_clapname + ".clap"))) + if (cp ~_library.load(_clapname.c_str())) + { + std::cout << "[clap-wrapper] auv2 loaded clap from " << cs.u8string() << std::endl; + loaded = true; + break; + } + } + if (!loaded) + { + std::cout << "[ERROR] cannot load clap" << std::endl; + return; + } } - bool loaded{false}; - auto csp = Clap::getValidCLAPSearchPaths(); - for (auto &cs : csp) { - if (fs::is_directory(cs / (_clapname + ".clap"))) - if (_library.load(_clapname.c_str())) { - std::cout << "[clap-wrapper] auv2 loaded clap from " - << cs.u8string() << std::endl; - loaded = true; - break; - } + + if (_clapid.empty()) + { + if (_idx < 0 || _idx >= _library.plugins.size()) + { + std::cout << "[ERROR] cannot load by index" << std::endl; + return; + } + _desc = _library.plugins[_idx]; } - if (!loaded) { - std::cout << "[ERROR] cannot load clap" << std::endl; - return; + else + { + for (auto *d : _library.plugins) + { + if (strcmp(d->id, _clapid.c_str()) == 0) + { + _desc = d; + } + } } - } - if (_clapid.empty()) { - if (_idx < 0 || _idx >= _library.plugins.size()) { - std::cout << "[ERROR] cannot load by index" << std::endl; + if (!_desc) + { + std::cout << "[ERROR] cannot determine plugin description" << 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; } - - std::cout << "[clap-wrapper] auv2: Initialized '" << _desc->id << "' / '" - << _desc->name << "'" << std::endl; - } -}; + }; } // namespace free_audio::auv2_wrapper \ No newline at end of file diff --git a/src/detail/auv2/build-helper/build-helper.cpp b/src/detail/auv2/build-helper/build-helper.cpp index ce149ebd..6d0896a3 100644 --- a/src/detail/auv2/build-helper/build-helper.cpp +++ b/src/detail/auv2/build-helper/build-helper.cpp @@ -15,296 +15,294 @@ namespace fs = ghc::filesystem; struct auInfo { - std::string name, vers, type, subt, manu, manunm, clapid, desc, clapname; + std::string name, vers, type, subt, manu, manunm, clapid, desc, clapname; - const std::string factoryBase{"wrapAsAUV2_inst"}; + const std::string factoryBase{"wrapAsAUV2_inst"}; - void writePListFragment(std::ostream &of, int idx) const + void writePListFragment(std::ostream &of, int idx) const + { + if (!clapid.empty()) { - if (!clapid.empty()) - { - of << " \n"; - } - else - { - of << " \n"; - } - of << " \n" - << " name\n" - << " " << manunm << ": " << name << "\n" - << " description\n" - << " " << desc << "\n" - << " factoryFunction\n" - << " " << factoryBase << idx << "Factory" - << "\n" - << " manufacturer\n" - << " " << manu << "\n" - << " subtype\n" - << " " << subt << "\n" - << " type\n" - << " " << type << "\n" - << " version\n" - << " 1\n" - << " sandboxSafe\n" - << " \n" - << " resourceUsage\n" - << " \n" - << " network.client\n" - << " \n" - << " temporary-exception.files.all.read-write\n" - << " \n" - << " \n" - << " \n"; + of << " \n"; } + else + { + of << " \n"; + } + of << " \n" + << " name\n" + << " " << manunm << ": " << name << "\n" + << " description\n" + << " " << desc << "\n" + << " factoryFunction\n" + << " " << factoryBase << idx << "Factory" + << "\n" + << " manufacturer\n" + << " " << manu << "\n" + << " subtype\n" + << " " << subt << "\n" + << " type\n" + << " " << type << "\n" + << " version\n" + << " 1\n" + << " sandboxSafe\n" + << " \n" + << " resourceUsage\n" + << " \n" + << " network.client\n" + << " \n" + << " temporary-exception.files.all.read-write\n" + << " \n" + << " \n" + << " \n"; + } }; -bool buildUnitsFromClap(const std::string &clapfile, const std::string &clapname, 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())) + Clap::Library loader; + if (!loader.load(clapfile.c_str())) + { + std::cout << "[ERROR] library.load of clapfile failed" << std::endl; + return false; + } + + int idx{0}; + + if (manu.empty() && loader._pluginFactoryAUv2Info == nullptr) + { + std::cout << "[ERROR] No manufacturer provider and no auv2 info available" << std::endl; + return false; + } + + if (manu.empty()) + { + manu = loader._pluginFactoryAUv2Info->manufacturer_code; + manuName = loader._pluginFactoryAUv2Info->manufacturer_name; + std::cout << " - using factor manufacturer '" << manuName << "' (" << manu << ")" << std::endl; + } + + 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; + + 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) { - std::cout << "[ERROR] library.load of clapfile failed" << std::endl; - return false; + auto q = idHash & ((1 << 6) - 1); + stH += encoder[q]; + idHash = idHash >> 9; // mix it up a bit } - int idx{0}; + u.subt = stH; + u.manu = manu; + u.manunm = manuName; - if (manu.empty() && loader._pluginFactoryAUv2Info == nullptr) + auto f = clapPlug->features[0]; + if (f == nullptr || strcmp(f, CLAP_PLUGIN_FEATURE_INSTRUMENT) == 0) { - std::cout << "[ERROR] No manufacturer provider and no auv2 info available" << std::endl; - return false; + u.type = "aumu"; } - - if (manu.empty()) + else if (strcmp(f, CLAP_PLUGIN_FEATURE_AUDIO_EFFECT) == 0) + { + u.type = "aufx"; + } + else if (strcmp(f, CLAP_PLUGIN_FEATURE_NOTE_EFFECT) == 0) + { + u.type = "aumi"; + } + else { - manu = loader._pluginFactoryAUv2Info->manufacturer_code; - manuName = loader._pluginFactoryAUv2Info->manufacturer_name; - std::cout << " - using factor manufacturer '" << manuName << "' (" << manu << ")" << std::endl; + std::cout << "[WARNING] can't determine instrument type. Using aumu" << std::endl; + u.type = "aumu"; } - static const char *encoder = - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"; - for (const auto *clapPlug : loader.plugins) + if (loader._pluginFactoryAUv2Info) { - auto u = auInfo(); - u.name = clapPlug->name; - u.clapname = clapname; - u.clapid = clapPlug->id; - u.vers = clapPlug->version; - u.desc = clapPlug->description; - - 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; - - auto f = clapPlug->features[0]; - if (f == nullptr || strcmp(f, CLAP_PLUGIN_FEATURE_INSTRUMENT) == 0) - { - u.type = "aumu"; - } - else if (strcmp(f, CLAP_PLUGIN_FEATURE_AUDIO_EFFECT) == 0) - { - u.type = "aufx"; - } - else if (strcmp(f, CLAP_PLUGIN_FEATURE_NOTE_EFFECT) == 0) - { - u.type = "aumi"; - } - else - { - std::cout << "[WARNING] can't determine instrument type. Using aumu" << std::endl; - u.type = "aumu"; - } - - if (loader._pluginFactoryAUv2Info) - { - clap_plugin_info_as_auv2_t v2inf; - auto res = loader._pluginFactoryAUv2Info->get_auv2_info(loader._pluginFactoryAUv2Info, - idx, - &v2inf); - if (v2inf.au_type[0] != 0) - { - u.type = v2inf.au_type; - } - if (v2inf.au_subt[0] != 0) - { - u.subt = v2inf.au_subt; - } - } - - units.push_back(u); - idx++; + clap_plugin_info_as_auv2_t v2inf; + auto res = loader._pluginFactoryAUv2Info->get_auv2_info(loader._pluginFactoryAUv2Info, idx, &v2inf); + if (v2inf.au_type[0] != 0) + { + u.type = v2inf.au_type; + } + if (v2inf.au_subt[0] != 0) + { + u.subt = v2inf.au_subt; + } } - return true; + + units.push_back(u); + idx++; + } + return true; } int main(int argc, char **argv) { - if (argc < 2) - return 1; + if (argc < 2) + return 1; - std::cout << "clap-wrapper: auv2 configuration tool starting\n"; + std::cout << "clap-wrapper: auv2 configuration tool starting\n"; - std::vector units; - if (std::string(argv[1]) == "--explicit") + std::vector units; + if (std::string(argv[1]) == "--explicit") + { + if (argc != 8) { - if (argc != 8) - { - std::cout << "[ERROR] Configuration incorrect. Got " << argc << " arguments in explicit" << std::endl; - return 5; - } - 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++]); - u.manu = std::string(argv[idx++]); - u.manunm = std::string(argv[idx++]); - u.desc = u.name + " CLAP to AU Wrapper"; - - std::cout << " - single plugin explicit mode: " << u.name << " (" << u.type << "/" << u.subt << ")" << std::endl; - units.push_back(u); + std::cout << "[ERROR] Configuration incorrect. Got " << argc << " arguments in explicit" << std::endl; + return 5; } - else if (std::string(argv[1]) == "--fromclap") + 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++]); + u.manu = std::string(argv[idx++]); + u.manunm = std::string(argv[idx++]); + u.desc = u.name + " CLAP to AU Wrapper"; + + std::cout << " - single plugin explicit mode: " << u.name << " (" << u.type << "/" << u.subt << ")" << std::endl; + units.push_back(u); + } + else if (std::string(argv[1]) == "--fromclap") + { + if (argc < 4) { - if (argc < 4) - { - std::cout << "[ERROR] Configuration incorrect. Got " << argc << " arguments in fromclap" << std::endl; - return 6; - } - int idx = 2; - auto clapname = std::string(argv[idx++]); - auto clapfile = std::string(argv[idx++]); - auto mcode = (idx < argc) ? std::string(argv[idx++]) : std::string(); - auto mname = (idx < argc) ? std::string(argv[idx++]) : std::string(); - - try { - auto p = fs::path{clapfile}; - // This is a hack for now - we get to the dll - p = p.parent_path().parent_path().parent_path(); - clapfile = p.u8string(); - } - catch (const fs::filesystem_error &e) - { - std::cout << "[ERROR] cant get path " << e.what() << std::endl; - return 3; - } - - std::cout << " - building information from CLAP directly\n" - << " - source clap: '" << clapfile << "'" << std::endl; - - if (!buildUnitsFromClap(clapfile, clapname, mcode, mname, units)) - { - std::cout << "[ERROR] Can't build units from CLAP" << std::endl; - return 4; - } - - if (units.empty()) - { - std::cout << "[ERROR] No units from clap file\n"; - return 5; - } - - std::cout << " - clap file produced " << units.size() << " units" << std::endl; + std::cout << "[ERROR] Configuration incorrect. Got " << argc << " arguments in fromclap" << std::endl; + return 6; + } + int idx = 2; + auto clapname = std::string(argv[idx++]); + auto clapfile = std::string(argv[idx++]); + auto mcode = (idx < argc) ? std::string(argv[idx++]) : std::string(); + auto mname = (idx < argc) ? std::string(argv[idx++]) : std::string(); + try + { + auto p = fs::path{clapfile}; + // This is a hack for now - we get to the dll + p = p.parent_path().parent_path().parent_path(); + clapfile = p.u8string(); } - else + catch (const fs::filesystem_error &e) { - std::cout << "[ERROR] Unknown Mode : " << argv[1] << std::endl; - return 2; + std::cout << "[ERROR] cant get path " << e.what() << std::endl; + return 3; } - std::cout << " - generating auv2_Info.plist from auv2_infoplist_top" << std::endl; - std::ifstream intop("auv2_infoplist_top"); - if (!intop.is_open()) + std::cout << " - building information from CLAP directly\n" + << " - source clap: '" << clapfile << "'" << std::endl; + + if (!buildUnitsFromClap(clapfile, clapname, mcode, mname, units)) { - std::cerr << "[ERROR] Unable to open pre-generated file auv2_infoplist_top" << std::endl; - return 1; + std::cout << "[ERROR] Can't build units from CLAP" << std::endl; + return 4; } - std::ofstream of("auv2_Info.plist"); - if (!of.is_open()) + if (units.empty()) { - std::cerr << "[ERROR] Unable to open output file auv2_Info.plist" << std::endl; + std::cout << "[ERROR] No units from clap file\n"; + return 5; } - of << intop.rdbuf(); - of << " AudioComponents\n \n"; - int idx{0}; - for (const auto &u : units) + std::cout << " - clap file produced " << units.size() << " units" << std::endl; + } + else + { + std::cout << "[ERROR] Unknown Mode : " << argv[1] << std::endl; + return 2; + } + + std::cout << " - generating auv2_Info.plist from auv2_infoplist_top" << std::endl; + std::ifstream intop("auv2_infoplist_top"); + if (!intop.is_open()) + { + std::cerr << "[ERROR] Unable to open pre-generated file auv2_infoplist_top" << std::endl; + return 1; + } + + std::ofstream of("auv2_Info.plist"); + if (!of.is_open()) + { + std::cerr << "[ERROR] Unable to open output file auv2_Info.plist" << std::endl; + } + of << intop.rdbuf(); + + of << " AudioComponents\n \n"; + int idx{0}; + for (const auto &u : units) + { + std::cout << " + " << u.name << " (" << u.type << "/" << u.subt << ") by " << u.manunm << " (" << u.manu << ")" + << std::endl; + u.writePListFragment(of, idx++); + } + of << " \n"; + of << " \n\n"; + of.close(); + std::cout << " - auv2_Info.plist generated" << std::endl; + + std::cout << " - generating generated_entrypoints.hxx" << std::endl; + std::ofstream cppf("generated_entrypoints.hxx"); + if (!cppf.is_open()) + { + std::cout << "[ERROR] Unable to open generated_endpoints.hxx" << std::endl; + return 1; + } + + cppf << "#pragma once\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 << " (" << u.type << "/" << u.subt << ") by " << u.manunm - << " (" << u.manu << ")" << std::endl; - u.writePListFragment(of, idx++); + std::cout << " + " << u.name << " entry " << on << " from ClapWrapper_AUV2_Instrument" << std::endl; + cppf << "struct " << on << " : free_audio::auv2_wrapper::ClapWrapper_AUV2_Instrument {\n" + << " " << on << "(AudioComponentInstance ci) :\n" + << " free_audio::auv2_wrapper::ClapWrapper_AUV2_Instrument(" << args << ", ci) {}" + << "};\n" + << "AUSDK_COMPONENT_ENTRY(ausdk::AUMusicDeviceFactory, " << on << ");\n"; } - of << " \n"; - of << " \n\n"; - of.close(); - std::cout << " - auv2_Info.plist generated" << std::endl; - - std::cout << " - generating generated_entrypoints.hxx" << std::endl; - std::ofstream cppf("generated_entrypoints.hxx"); - if (!cppf.is_open()) + else if (u.type == "aumi") { - std::cout << "[ERROR] Unable to open generated_endpoints.hxx" << std::endl; - return 1; + std::cout << " + " << u.name << " entry " << on << " from ClapWrapper_AUV2_NoteEffect" << std::endl; + cppf << "struct " << on << " : free_audio::auv2_wrapper::ClapWrapper_AUV2_NoteEffect {\n" + << " " << on << "(AudioComponentInstance ci) :\n" + << " free_audio::auv2_wrapper::ClapWrapper_AUV2_NoteEffect(" << args << ", ci) {}" + << "};\n" + << "AUSDK_COMPONENT_ENTRY(ausdk::AUBaseFactory , " << on << ");\n"; } - - cppf << "#pragma once\n"; - cppf << "#include \"detail/auv2/auv2_base_classes.h\"\n\n"; - - idx = 0; - for (const auto &u : units) + else if (u.type == "aufx") { - 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 << " : free_audio::auv2_wrapper::ClapWrapper_AUV2_Instrument {\n" - << " " << on << "(AudioComponentInstance ci) :\n" - << " 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 << " : free_audio::auv2_wrapper::ClapWrapper_AUV2_NoteEffect {\n" - << " " << on << "(AudioComponentInstance ci) :\n" - << " 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 << " : free_audio::auv2_wrapper::ClapWrapper_AUV2_Effect {\n" - << " " << on << "(AudioComponentInstance ci) :\n" - << " free_audio::auv2_wrapper::ClapWrapper_AUV2_Effect(" << args << ", ci) {}" - << "};\n" - << "AUSDK_COMPONENT_ENTRY(ausdk::AUBaseFactory, " << on << ");\n"; - } - - idx++; + std::cout << " + " << u.name << " entry " << on << " from ClapWrapper_AUV2_Effect" << std::endl; + cppf << "struct " << on << " : free_audio::auv2_wrapper::ClapWrapper_AUV2_Effect {\n" + << " " << on << "(AudioComponentInstance ci) :\n" + << " free_audio::auv2_wrapper::ClapWrapper_AUV2_Effect(" << args << ", ci) {}" + << "};\n" + << "AUSDK_COMPONENT_ENTRY(ausdk::AUBaseFactory, " << on << ");\n"; } - cppf.close(); - std::cout << " - generated_entrypoints.hxx generated" << std::endl; - return 0; + idx++; + } + cppf.close(); + std::cout << " - generated_entrypoints.hxx generated" << std::endl; + + return 0; } diff --git a/src/detail/clap/automation.h b/src/detail/clap/automation.h index 1d5c8d81..45d54deb 100644 --- a/src/detail/clap/automation.h +++ b/src/detail/clap/automation.h @@ -4,12 +4,12 @@ namespace Clap { - class IAutomation - { - public: - virtual void onBeginEdit(clap_id id) = 0; - virtual void onPerformEdit(const clap_event_param_value_t* value) = 0; - virtual void onEndEdit(clap_id id) = 0; - virtual ~IAutomation() {} - }; -} \ No newline at end of file + class IAutomation + { + public: + virtual void onBeginEdit(clap_id id) = 0; + virtual void onPerformEdit(const clap_event_param_value_t *value) = 0; + virtual void onEndEdit(clap_id id) = 0; + virtual ~IAutomation() {} + }; +} // namespace Clap \ No newline at end of file diff --git a/src/detail/clap/fsutil.cpp b/src/detail/clap/fsutil.cpp index 8d34b391..b508f7bf 100644 --- a/src/detail/clap/fsutil.cpp +++ b/src/detail/clap/fsutil.cpp @@ -24,20 +24,21 @@ #include #endif - namespace Clap { #if WIN - std::string getEnvVariable(const char* varname) + std::string getEnvVariable(const char *varname) { - char* val; + char *val; size_t len; auto err = _dupenv_s(&val, &len, varname); - if (err) return std::string(); - if (val == nullptr) return std::string(); + if (err) + return std::string(); + if (val == nullptr) + return std::string(); std::string result(val); free(val); - return result; + return result; } #endif @@ -62,12 +63,12 @@ namespace Clap auto p = getEnvVariable("COMMONPROGRAMFILES"); if (!p.empty()) { - res.emplace_back(fs::path{ p } / "CLAP"); + res.emplace_back(fs::path{p} / "CLAP"); } auto q = getEnvVariable("LOCALAPPDATA"); if (!q.empty()) { - res.emplace_back(fs::path{ q } / "Programs" / "Common" / "CLAP"); + res.emplace_back(fs::path{q} / "Programs" / "Common" / "CLAP"); } } auto cp = getEnvVariable("CLAP_PATH"); @@ -89,39 +90,38 @@ namespace Clap { auto item = cp.substr(0, pos); cp = cp.substr(pos + 1); - res.emplace_back(fs::path{ item }); + res.emplace_back(fs::path{item}); } if (cp.size()) - res.emplace_back(fs::path{ cp }); + res.emplace_back(fs::path{cp}); } return res; } - bool Library::load(const char* name) + bool Library::load(const char *name) { #if MAC - _pluginEntry = nullptr; + _pluginEntry = nullptr; - auto cs = CFStringCreateWithBytes(kCFAllocatorDefault, (uint8_t *)name, strlen(name), - kCFStringEncodingUTF8, false); - auto bundleURL = - CFURLCreateWithFileSystemPath(kCFAllocatorDefault, cs, kCFURLPOSIXPathStyle, true); + auto cs = CFStringCreateWithBytes(kCFAllocatorDefault, (uint8_t *)name, strlen(name), kCFStringEncodingUTF8, false); + auto bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, cs, kCFURLPOSIXPathStyle, true); - _bundle = CFBundleCreate(kCFAllocatorDefault, bundleURL); - CFRelease(bundleURL); - CFRelease(cs); + _bundle = CFBundleCreate(kCFAllocatorDefault, bundleURL); + CFRelease(bundleURL); + CFRelease(cs); - if (!_bundle) { - return false; - } + if (!_bundle) + { + return false; + } - auto db = CFBundleGetDataPointerForName(_bundle, CFSTR("clap_entry")); + auto db = CFBundleGetDataPointerForName(_bundle, CFSTR("clap_entry")); - _pluginEntry = (const clap_plugin_entry *)db; + _pluginEntry = (const clap_plugin_entry *)db; - setupPluginsFromPluginEntry(name); - return _pluginEntry != nullptr; + setupPluginsFromPluginEntry(name); + return _pluginEntry != nullptr; #endif #if WIN @@ -149,23 +149,23 @@ namespace Clap #endif #if LIN - int *iptr; + int *iptr; - _handle = dlopen(name, RTLD_LOCAL | RTLD_LAZY); - if (!_handle) - return false; + _handle = dlopen(name, RTLD_LOCAL | RTLD_LAZY); + if (!_handle) + return false; - iptr = (int *)dlsym(_handle, "clap_entry"); - if (!iptr) - return false; + iptr = (int *)dlsym(_handle, "clap_entry"); + if (!iptr) + return false; - _pluginEntry = (const clap_plugin_entry_t *)iptr; - setupPluginsFromPluginEntry(name); - return true; + _pluginEntry = (const clap_plugin_entry_t *)iptr; + setupPluginsFromPluginEntry(name); + return true; #endif } - const clap_plugin_info_as_vst3_t* Library::get_vst3_info(uint32_t index) + const clap_plugin_info_as_vst3_t *Library::get_vst3_info(uint32_t index) { if (_pluginFactoryVst3Info && _pluginFactoryVst3Info->get_vst3_info) { @@ -175,49 +175,55 @@ namespace Clap } #if WIN - bool Library::getEntryFunction(HMODULE handle, const char* path) + bool Library::getEntryFunction(HMODULE handle, const char *path) { if (handle) { - _pluginEntry = reinterpret_cast(GetProcAddress(handle, "clap_entry")); + _pluginEntry = reinterpret_cast(GetProcAddress(handle, "clap_entry")); if (_pluginEntry) { - setupPluginsFromPluginEntry(path); + setupPluginsFromPluginEntry(path); } } return (_pluginEntry && !plugins.empty()); } #endif - void Library::setupPluginsFromPluginEntry(const char* path) { - if (clap_version_is_compatible(_pluginEntry->clap_version)) { - if (_pluginEntry->init(path)) { - _pluginFactory = - static_cast(_pluginEntry->get_factory(CLAP_PLUGIN_FACTORY_ID)); - _pluginFactoryVst3Info = - static_cast(_pluginEntry->get_factory(CLAP_PLUGIN_FACTORY_INFO_VST3)); - _pluginFactoryAUv2Info = - static_cast(_pluginEntry->get_factory(CLAP_PLUGIN_FACTORY_INFO_AUV2)); - - // detect plugins that do not check the CLAP_PLUGIN_FACTORY_ID - if ((void*)_pluginFactory == (void*)_pluginFactoryVst3Info) - { - _pluginFactoryVst3Info = nullptr; - _pluginFactoryAUv2Info = nullptr; - } - - auto count = _pluginFactory->get_plugin_count(_pluginFactory); - - for (decltype(count) i = 0; i < count; ++i) { - auto desc = _pluginFactory->get_plugin_descriptor(_pluginFactory, i); - if (clap_version_is_compatible(desc->clap_version)) { - plugins.push_back(desc); - } else { - // incompatible - } - } + void Library::setupPluginsFromPluginEntry(const char *path) + { + if (clap_version_is_compatible(_pluginEntry->clap_version)) + { + if (_pluginEntry->init(path)) + { + _pluginFactory = static_cast(_pluginEntry->get_factory(CLAP_PLUGIN_FACTORY_ID)); + _pluginFactoryVst3Info = + static_cast(_pluginEntry->get_factory(CLAP_PLUGIN_FACTORY_INFO_VST3)); + _pluginFactoryAUv2Info = + static_cast(_pluginEntry->get_factory(CLAP_PLUGIN_FACTORY_INFO_AUV2)); + + // detect plugins that do not check the CLAP_PLUGIN_FACTORY_ID + if ((void *)_pluginFactory == (void *)_pluginFactoryVst3Info) + { + _pluginFactoryVst3Info = nullptr; + _pluginFactoryAUv2Info = nullptr; } - } + + auto count = _pluginFactory->get_plugin_count(_pluginFactory); + + for (decltype(count) i = 0; i < count; ++i) + { + auto desc = _pluginFactory->get_plugin_descriptor(_pluginFactory, i); + if (clap_version_is_compatible(desc->clap_version)) + { + plugins.push_back(desc); + } + else + { + // incompatible + } + } + } + } } #if WIN || LIN @@ -238,7 +244,7 @@ namespace Clap } if (selfmodule) { - if (this->getEntryFunction(selfmodule, (const char*)modulename)) + if (this->getEntryFunction(selfmodule, (const char *)modulename)) { _selfcontained = true; } @@ -247,8 +253,7 @@ namespace Clap #if LIN Dl_info info; - if (dladdr(reinterpret_cast(&ffeomwe), &info) && - info.dli_fname[0]) + if (dladdr(reinterpret_cast(&ffeomwe), &info) && info.dli_fname[0]) { auto lhandle = dlopen(info.dli_fname, RTLD_LOCAL | RTLD_LAZY); if (lhandle) @@ -256,11 +261,11 @@ namespace Clap auto liptr = (int *)dlsym(_handle, "clap_entry"); if (liptr) { - _handle = lhandle; // as a result the Library dtor will dlclose me - _pluginEntry = (const clap_plugin_entry_t *)liptr; - _selfcontained = true; + _handle = lhandle; // as a result the Library dtor will dlclose me + _pluginEntry = (const clap_plugin_entry_t *)liptr; + _selfcontained = true; - setupPluginsFromPluginEntry(info.dli_fname); + setupPluginsFromPluginEntry(info.dli_fname); } } } @@ -272,9 +277,8 @@ namespace Clap if (!selfp.empty()) { std::string name = selfp.u8string(); - CFURLRef bundleUrl = CFURLCreateFromFileSystemRepresentation (0, - (const unsigned char*)name.c_str (), - name.size(), true); + CFURLRef bundleUrl = + CFURLCreateFromFileSystemRepresentation(0, (const unsigned char *)name.c_str(), name.size(), true); if (bundleUrl) { auto pluginBundle = CFBundleCreate(0, bundleUrl); @@ -285,22 +289,20 @@ namespace Clap auto db = CFBundleGetDataPointerForName(pluginBundle, CFSTR("clap_entry")); if (db) { - _bundle = pluginBundle; - _pluginEntry = (const clap_plugin_entry_t *)db; - _selfcontained = true; + _bundle = pluginBundle; + _pluginEntry = (const clap_plugin_entry_t *)db; + _selfcontained = true; - setupPluginsFromPluginEntry(selfp.u8string().c_str()); + setupPluginsFromPluginEntry(selfp.u8string().c_str()); } else { - CFRelease(pluginBundle); + CFRelease(pluginBundle); } } } } #endif - - } Library::~Library() @@ -321,8 +323,8 @@ namespace Clap #if LIN if (_handle) { - dlclose(_handle); - _handle = nullptr; + dlclose(_handle); + _handle = nullptr; } #endif @@ -334,4 +336,4 @@ namespace Clap #endif } -} +} // namespace Clap diff --git a/src/detail/clap/fsutil.h b/src/detail/clap/fsutil.h index a825fa94..321d771f 100644 --- a/src/detail/clap/fsutil.h +++ b/src/detail/clap/fsutil.h @@ -1,4 +1,4 @@ -/* +/* Copyright (c) 2022 Timo Kaluza (defiantnerd) Paul Walker @@ -49,48 +49,46 @@ namespace Clap public: Library(); ~Library(); - bool load(const char* name); - - const clap_plugin_entry_t* _pluginEntry = nullptr; - const clap_plugin_factory_t* _pluginFactory = nullptr; - const clap_plugin_factory_as_vst3* _pluginFactoryVst3Info = nullptr; - const clap_plugin_factory_as_auv2* _pluginFactoryAUv2Info = nullptr; - std::vector plugins; - const clap_plugin_info_as_vst3_t* get_vst3_info(uint32_t index); - - bool hasEntryPoint() const { + bool load(const char *name); + + const clap_plugin_entry_t *_pluginEntry = nullptr; + const clap_plugin_factory_t *_pluginFactory = nullptr; + const clap_plugin_factory_as_vst3 *_pluginFactoryVst3Info = nullptr; + const clap_plugin_factory_as_auv2 *_pluginFactoryAUv2Info = nullptr; + std::vector plugins; + const clap_plugin_info_as_vst3_t *get_vst3_info(uint32_t index); + + bool hasEntryPoint() const + { #if WIN - return _handle != 0 || _selfcontained; + return _handle != 0 || _selfcontained; #endif #if MAC - return _bundle != nullptr || _selfcontained; + return _bundle != nullptr || _selfcontained; #endif #if LIN - return _handle != nullptr || _selfcontained; + return _handle != nullptr || _selfcontained; #endif } private: #if MAC - CFBundleRef _bundle{nullptr}; + CFBundleRef _bundle{nullptr}; #endif #if LIN void *_handle{nullptr}; #endif - #if WIN HMODULE _handle = 0; - bool getEntryFunction(HMODULE handle, const char* path); + bool getEntryFunction(HMODULE handle, const char *path); #endif - void setupPluginsFromPluginEntry(const char* p); + void setupPluginsFromPluginEntry(const char *p); bool _selfcontained = false; }; -} - - +} // namespace Clap diff --git a/src/detail/clap/mac_helpers.mm b/src/detail/clap/mac_helpers.mm index e547d772..fd206c24 100644 --- a/src/detail/clap/mac_helpers.mm +++ b/src/detail/clap/mac_helpers.mm @@ -1,8 +1,8 @@ -/* +/* Copyright (c) 2022 Paul Walker Timo Kaluza (defiantnerd) - + This file is part of the clap-wrappers project which is released under MIT License. See file LICENSE or go to https://github.com/defiantnerd/clap-wrapper for full license details. @@ -23,14 +23,12 @@ Timo Kaluza (defiantnerd) #include - namespace Clap { fs::path sharedLibraryBundlePath() { Dl_info info; - if (!dladdr(reinterpret_cast(&sharedLibraryBundlePath), &info) || - !info.dli_fname[0]) + if (!dladdr(reinterpret_cast(&sharedLibraryBundlePath), &info) || !info.dli_fname[0]) { // If dladdr(3) returns zero, dlerror(3) won't know why either return {}; @@ -45,64 +43,62 @@ Timo Kaluza (defiantnerd) return res.parent_path(); } } - catch(const fs::filesystem_error &) + catch (const fs::filesystem_error &) { // oh well } return {}; } - std::vector getMacCLAPSearchPaths() { - auto res = std::vector(); + std::vector getMacCLAPSearchPaths() + { + auto res = std::vector(); - auto bundlePath = sharedLibraryBundlePath(); - if (!bundlePath.empty()) + auto bundlePath = sharedLibraryBundlePath(); + if (!bundlePath.empty()) + { + std::string name = bundlePath.u8string(); + CFURLRef bundleUrl = + CFURLCreateFromFileSystemRepresentation(0, (const unsigned char *)name.c_str(), name.size(), true); + if (bundleUrl) { - std::string name = bundlePath.u8string(); - CFURLRef bundleUrl = CFURLCreateFromFileSystemRepresentation (0, - (const unsigned char*)name.c_str (), - name.size(), true); - if (bundleUrl) - { - auto pluginBundle = CFBundleCreate (0, bundleUrl); - CFRelease (bundleUrl); + auto pluginBundle = CFBundleCreate(0, bundleUrl); + CFRelease(bundleUrl); - if (pluginBundle) - { - auto pluginFoldersUrl = CFBundleCopyBuiltInPlugInsURL(pluginBundle); + if (pluginBundle) + { + auto pluginFoldersUrl = CFBundleCopyBuiltInPlugInsURL(pluginBundle); - if (pluginFoldersUrl) - { - // Remember CFURL and NSURL are toll free bridged - auto *ns = (NSURL *)pluginFoldersUrl; - auto pp = fs::path{[ns fileSystemRepresentation]}; - res.push_back(pp); - CFRelease(pluginFoldersUrl); - } - CFRelease(pluginBundle); - } - } + if (pluginFoldersUrl) + { + // Remember CFURL and NSURL are toll free bridged + auto *ns = (NSURL *)pluginFoldersUrl; + auto pp = fs::path{[ns fileSystemRepresentation]}; + res.push_back(pp); + CFRelease(pluginFoldersUrl); + } + CFRelease(pluginBundle); + } } + } - auto *fileManager = [NSFileManager defaultManager]; - auto *userLibURLs = [fileManager URLsForDirectory:NSLibraryDirectory - inDomains:NSUserDomainMask]; - auto *sysLibURLs = [fileManager URLsForDirectory:NSLibraryDirectory - inDomains:NSLocalDomainMask]; + auto *fileManager = [NSFileManager defaultManager]; + auto *userLibURLs = [fileManager URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask]; + auto *sysLibURLs = [fileManager URLsForDirectory:NSLibraryDirectory inDomains:NSLocalDomainMask]; - if (userLibURLs) { - auto *u = [userLibURLs objectAtIndex:0]; - auto p = - fs::path{[u fileSystemRepresentation]} / "Audio" / "Plug-Ins" / "CLAP"; - res.push_back(p); - } + if (userLibURLs) + { + auto *u = [userLibURLs objectAtIndex:0]; + auto p = fs::path{[u fileSystemRepresentation]} / "Audio" / "Plug-Ins" / "CLAP"; + res.push_back(p); + } - if (sysLibURLs) { - auto *u = [sysLibURLs objectAtIndex:0]; - auto p = - fs::path{[u fileSystemRepresentation]} / "Audio" / "Plug-Ins" / "CLAP"; - res.push_back(p); - } - return res; + if (sysLibURLs) + { + auto *u = [sysLibURLs objectAtIndex:0]; + auto p = fs::path{[u fileSystemRepresentation]} / "Audio" / "Plug-Ins" / "CLAP"; + res.push_back(p); } + return res; + } } \ No newline at end of file diff --git a/src/detail/sha1.cpp b/src/detail/sha1.cpp index 59511dc7..44f66221 100644 --- a/src/detail/sha1.cpp +++ b/src/detail/sha1.cpp @@ -4,7 +4,6 @@ #include #include - static constexpr bool isBigEndian = false; namespace Crypto @@ -13,13 +12,14 @@ namespace Crypto { public: Sha1() { reset(); } - Sha1(const unsigned char* message_array, size_t length) + Sha1(const unsigned char *message_array, size_t length) { reset(); input(message_array, length); } - void input(const unsigned char* message_array, size_t length); + void input(const unsigned char *message_array, size_t length); struct sha1hash hash(); + private: void reset(); void processMessageBlock(); @@ -29,24 +29,17 @@ namespace Crypto return ((word << bits) & 0xFFFFFFFF) | ((word & 0xFFFFFFFF) >> (32 - bits)); } - unsigned H[5] = // Message digest buffers - { - 0x67452301, - 0xEFCDAB89, - 0x98BADCFE, - 0x10325476, - 0xC3D2E1F0 - }; - - uint32_t _lengthLow = 0; // Message length in bits - uint32_t _length_high = 0; // Message length in bits + unsigned H[5] = // Message digest buffers + {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0}; - unsigned char _messageBlock[64] = { 0 }; // 512-bit message blocks - int _messageBlockIndex = 0; // Index into message block array + uint32_t _lengthLow = 0; // Message length in bits + uint32_t _length_high = 0; // Message length in bits - bool _computed = false; // Is the digest computed? - bool _corrupted = false; // Is the message digest corruped? + unsigned char _messageBlock[64] = {0}; // 512-bit message blocks + int _messageBlockIndex = 0; // Index into message block array + bool _computed = false; // Is the digest computed? + bool _corrupted = false; // Is the message digest corruped? }; void Sha1::reset() @@ -65,7 +58,7 @@ namespace Crypto _corrupted = false; } - void Sha1::input(const unsigned char* message_array, size_t length) + void Sha1::input(const unsigned char *message_array, size_t length) { if (length == 0) { @@ -88,14 +81,14 @@ namespace Crypto _messageBlock[_messageBlockIndex++] = (*message_array & 0xFF); _lengthLow += 8; - _lengthLow &= 0xFFFFFFFF; // Force it to 32 bits + _lengthLow &= 0xFFFFFFFF; // Force it to 32 bits if (_lengthLow == 0) { _length_high++; - _length_high &= 0xFFFFFFFF; // Force it to 32 bits + _length_high &= 0xFFFFFFFF; // Force it to 32 bits if (_length_high == 0) { - _corrupted = true; // Message is too long + _corrupted = true; // Message is too long } } @@ -110,16 +103,12 @@ namespace Crypto void Sha1::processMessageBlock() { - const unsigned K[] = { // Constants defined for SHA-1 - 0x5A827999, - 0x6ED9EBA1, - 0x8F1BBCDC, - 0xCA62C1D6 - }; - int t; // Loop counter - unsigned temp; // Temporary word value - unsigned W[80]; // Word sequence - unsigned A, B, C, D, E; // Word buffers + const unsigned K[] = {// Constants defined for SHA-1 + 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6}; + int t; // Loop counter + unsigned temp; // Temporary word value + unsigned W[80]; // Word sequence + unsigned A, B, C, D, E; // Word buffers /* * Initialize the first 16 words in the array W @@ -167,8 +156,7 @@ namespace Crypto for (t = 40; t < 60; t++) { - temp = circularShift(5, A) + - ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; + temp = circularShift(5, A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; temp &= 0xFFFFFFFF; E = D; D = C; @@ -200,10 +188,10 @@ namespace Crypto void Sha1::padmessage() { /* - * Check to see if the current message block is too small to hold - * the initial padding bits and length. If so, we will pad the - * block, process it, and then continue padding into a second block. - */ + * Check to see if the current message block is too small to hold + * the initial padding bits and length. If so, we will pad the + * block, process it, and then continue padding into a second block. + */ if (_messageBlockIndex > 55) { _messageBlock[_messageBlockIndex++] = 0x80; @@ -226,7 +214,6 @@ namespace Crypto { _messageBlock[_messageBlockIndex++] = 0; } - } /* @@ -235,11 +222,11 @@ namespace Crypto _messageBlock[56] = (_length_high >> 24) & 0xFF; _messageBlock[57] = (_length_high >> 16) & 0xFF; _messageBlock[58] = (_length_high >> 8) & 0xFF; - _messageBlock[59] = (_length_high) & 0xFF; + _messageBlock[59] = (_length_high)&0xFF; _messageBlock[60] = (_lengthLow >> 24) & 0xFF; _messageBlock[61] = (_lengthLow >> 16) & 0xFF; _messageBlock[62] = (_lengthLow >> 8) & 0xFF; - _messageBlock[63] = (_lengthLow) & 0xFF; + _messageBlock[63] = (_lengthLow)&0xFF; processMessageBlock(); } @@ -281,10 +268,9 @@ namespace Crypto return r; } - - struct sha1hash sha1(const char* text, size_t len) + struct sha1hash sha1(const char *text, size_t len) { - Sha1 x((const unsigned char*)(text), len); + Sha1 x((const unsigned char *)(text), len); return x.hash(); } @@ -292,11 +278,7 @@ namespace Crypto { if (!isBigEndian) { - return - ((n >> 24) & 0x000000FF) | - ((n >> 8) & 0x0000FF00) | - ((n << 8) & 0x00FF0000) | - ((n << 24) & 0xFF000000); + return ((n >> 24) & 0x000000FF) | ((n >> 8) & 0x0000FF00) | ((n << 8) & 0x00FF0000) | ((n << 24) & 0xFF000000); } else { @@ -308,43 +290,33 @@ namespace Crypto { if (!isBigEndian) { - return - ((n >> 8) & 0x00FF) | - ((n << 8) & 0xFF00); + return ((n >> 8) & 0x00FF) | ((n << 8) & 0xFF00); } return n; } /* Name string is a fully-qualified domain name */ - uuid_object NameSpace_DNS = { /* 6ba7b810-9dad-11d1-80b4-00c04fd430c8 */ - 0x6ba7b810, - 0x9dad, - 0x11d1, - 0x80, 0xb4, { 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 } - }; + uuid_object NameSpace_DNS = {/* 6ba7b810-9dad-11d1-80b4-00c04fd430c8 */ + 0x6ba7b810, 0x9dad, 0x11d1, 0x80, 0xb4, {0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}}; - uuid_object create_sha1_guid_from_name(const char* name, size_t namelen) + uuid_object create_sha1_guid_from_name(const char *name, size_t namelen) { uuid_object uuid; /*put name space ID in network byte order so it hashes the same no matter what endian machine we're on */ - // namespace DNS - uuid_object net_nsid = { /* 6ba7b810-9dad-11d1-80b4-00c04fd430c8 */ - 0x6ba7b810, - 0x9dad, - 0x11d1, - 0x80, 0xb4, { 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8 } - }; + // namespace DNS + uuid_object net_nsid = {/* 6ba7b810-9dad-11d1-80b4-00c04fd430c8 */ + 0x6ba7b810, 0x9dad, 0x11d1, 0x80, 0xb4, {0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}}; net_nsid.time_low = swapOrder32(net_nsid.time_low); net_nsid.time_mid = swapOrder16(net_nsid.time_mid); net_nsid.time_hi_and_version = swapOrder16(net_nsid.time_hi_and_version); Sha1 c; - c.input((const uint8_t*)&net_nsid, sizeof(net_nsid)); - c.input((const uint8_t*)name, namelen); + c.input((const uint8_t *)&net_nsid, sizeof(net_nsid)); + c.input((const uint8_t *)name, namelen); auto hash = c.hash(); /* convert UUID to local byte order */ @@ -362,4 +334,4 @@ namespace Crypto return uuid; } -} +} // namespace Crypto diff --git a/src/detail/sha1.h b/src/detail/sha1.h index e1914bfc..08650dc4 100644 --- a/src/detail/sha1.h +++ b/src/detail/sha1.h @@ -11,20 +11,18 @@ namespace Crypto uint8_t bytes[20]; }; - struct sha1hash sha1(const char* text, size_t len); - - typedef struct uuid_object_ { - uint32_t time_low; - uint16_t time_mid; - uint16_t time_hi_and_version; - uint8_t clock_seq_hi_and_reserved; - uint8_t clock_seq_low; - uint8_t node[6]; - } uuid_object; - - uuid_object create_sha1_guid_from_name(const char* name, size_t namelen); - -} + struct sha1hash sha1(const char *text, size_t len); + typedef struct uuid_object_ + { + uint32_t time_low; + uint16_t time_mid; + uint16_t time_hi_and_version; + uint8_t clock_seq_hi_and_reserved; + uint8_t clock_seq_low; + uint8_t node[6]; + } uuid_object; + uuid_object create_sha1_guid_from_name(const char *name, size_t namelen); +} // namespace Crypto diff --git a/src/detail/vst3/categories.cpp b/src/detail/vst3/categories.cpp index 4d0d6291..fa960275 100644 --- a/src/detail/vst3/categories.cpp +++ b/src/detail/vst3/categories.cpp @@ -1,6 +1,6 @@ /* converting CLAP categories to VST3 categories - + Copyright (c) 2022 Timo Kaluza (defiantnerd) This file is part of the clap-wrappers project which is released under MIT License. @@ -50,62 +50,60 @@ using namespace Steinberg::Vst; static const struct _translate { - const char* clapattribute; - const char* vst3attribute; -} translationTable[] = -{ - // CLAP main categories - { CLAP_PLUGIN_FEATURE_INSTRUMENT , PlugType::kInstrument }, - { CLAP_PLUGIN_FEATURE_AUDIO_EFFECT , PlugType::kFx}, - { CLAP_PLUGIN_FEATURE_NOTE_EFFECT , PlugType::kInstrumentSynth}, // it seems there is no type for a sequencer etc - { CLAP_PLUGIN_FEATURE_DRUM , PlugType::kInstrumentDrum}, - { CLAP_PLUGIN_FEATURE_ANALYZER , PlugType::kAnalyzer}, - - // CLAP sub categories - { CLAP_PLUGIN_FEATURE_SYNTHESIZER , "Synth"}, - { CLAP_PLUGIN_FEATURE_SAMPLER , "Sampler"}, - { CLAP_PLUGIN_FEATURE_DRUM , "Drum"}, - { CLAP_PLUGIN_FEATURE_DRUM_MACHINE , "Drum"}, - - { CLAP_PLUGIN_FEATURE_FILTER , "Filter"}, - { CLAP_PLUGIN_FEATURE_PHASER , "Modulation" }, - { CLAP_PLUGIN_FEATURE_EQUALIZER , "EQ"}, - { CLAP_PLUGIN_FEATURE_DEESSER , "Restoration"}, - { CLAP_PLUGIN_FEATURE_PHASE_VOCODER , "Modulation"}, - { CLAP_PLUGIN_FEATURE_GRANULAR , "Synth"}, - { CLAP_PLUGIN_FEATURE_FREQUENCY_SHIFTER , "Modulator"}, - { CLAP_PLUGIN_FEATURE_PITCH_SHIFTER , "Pitch Shifter"}, - - { CLAP_PLUGIN_FEATURE_DISTORTION , "Distortion"}, - { CLAP_PLUGIN_FEATURE_TRANSIENT_SHAPER , "Distortion"}, - { CLAP_PLUGIN_FEATURE_COMPRESSOR , "Dynamics"}, - { CLAP_PLUGIN_FEATURE_LIMITER , "Dynamics"}, - - { CLAP_PLUGIN_FEATURE_FLANGER , "Modulation"}, - // { CLAP_PLUGIN_FEATURE_FLANGER , "Flanger"}, - { CLAP_PLUGIN_FEATURE_CHORUS , "Modulation"}, - // { CLAP_PLUGIN_FEATURE_CHORUS , "Chorus"}, - { CLAP_PLUGIN_FEATURE_DELAY , "Delay"}, - { CLAP_PLUGIN_FEATURE_REVERB , "Reverb"}, - - { CLAP_PLUGIN_FEATURE_TREMOLO , "Modulation"}, - { CLAP_PLUGIN_FEATURE_GLITCH , "Modulation"}, - - { CLAP_PLUGIN_FEATURE_UTILITY , "Tools"}, - { CLAP_PLUGIN_FEATURE_PITCH_CORRECTION , "Pitch Shift"}, - { CLAP_PLUGIN_FEATURE_RESTORATION , "Restoration"}, - - { CLAP_PLUGIN_FEATURE_MULTI_EFFECTS , "Tools"}, - - { CLAP_PLUGIN_FEATURE_MIXING , "Mixing"}, - { CLAP_PLUGIN_FEATURE_MASTERING , "Mastering"}, - - { "external" , "External"}, - - {nullptr, nullptr} -}; - -std::string clapCategoriesToVST3(const char* const* clap_categories) + const char *clapattribute; + const char *vst3attribute; +} translationTable[] = { + // CLAP main categories + {CLAP_PLUGIN_FEATURE_INSTRUMENT, PlugType::kInstrument}, + {CLAP_PLUGIN_FEATURE_AUDIO_EFFECT, PlugType::kFx}, + {CLAP_PLUGIN_FEATURE_NOTE_EFFECT, PlugType::kInstrumentSynth}, // it seems there is no type for a sequencer etc + {CLAP_PLUGIN_FEATURE_DRUM, PlugType::kInstrumentDrum}, + {CLAP_PLUGIN_FEATURE_ANALYZER, PlugType::kAnalyzer}, + + // CLAP sub categories + {CLAP_PLUGIN_FEATURE_SYNTHESIZER, "Synth"}, + {CLAP_PLUGIN_FEATURE_SAMPLER, "Sampler"}, + {CLAP_PLUGIN_FEATURE_DRUM, "Drum"}, + {CLAP_PLUGIN_FEATURE_DRUM_MACHINE, "Drum"}, + + {CLAP_PLUGIN_FEATURE_FILTER, "Filter"}, + {CLAP_PLUGIN_FEATURE_PHASER, "Modulation"}, + {CLAP_PLUGIN_FEATURE_EQUALIZER, "EQ"}, + {CLAP_PLUGIN_FEATURE_DEESSER, "Restoration"}, + {CLAP_PLUGIN_FEATURE_PHASE_VOCODER, "Modulation"}, + {CLAP_PLUGIN_FEATURE_GRANULAR, "Synth"}, + {CLAP_PLUGIN_FEATURE_FREQUENCY_SHIFTER, "Modulator"}, + {CLAP_PLUGIN_FEATURE_PITCH_SHIFTER, "Pitch Shifter"}, + + {CLAP_PLUGIN_FEATURE_DISTORTION, "Distortion"}, + {CLAP_PLUGIN_FEATURE_TRANSIENT_SHAPER, "Distortion"}, + {CLAP_PLUGIN_FEATURE_COMPRESSOR, "Dynamics"}, + {CLAP_PLUGIN_FEATURE_LIMITER, "Dynamics"}, + + {CLAP_PLUGIN_FEATURE_FLANGER, "Modulation"}, + // { CLAP_PLUGIN_FEATURE_FLANGER , "Flanger"}, + {CLAP_PLUGIN_FEATURE_CHORUS, "Modulation"}, + // { CLAP_PLUGIN_FEATURE_CHORUS , "Chorus"}, + {CLAP_PLUGIN_FEATURE_DELAY, "Delay"}, + {CLAP_PLUGIN_FEATURE_REVERB, "Reverb"}, + + {CLAP_PLUGIN_FEATURE_TREMOLO, "Modulation"}, + {CLAP_PLUGIN_FEATURE_GLITCH, "Modulation"}, + + {CLAP_PLUGIN_FEATURE_UTILITY, "Tools"}, + {CLAP_PLUGIN_FEATURE_PITCH_CORRECTION, "Pitch Shift"}, + {CLAP_PLUGIN_FEATURE_RESTORATION, "Restoration"}, + + {CLAP_PLUGIN_FEATURE_MULTI_EFFECTS, "Tools"}, + + {CLAP_PLUGIN_FEATURE_MIXING, "Mixing"}, + {CLAP_PLUGIN_FEATURE_MASTERING, "Mastering"}, + + {"external", "External"}, + + {nullptr, nullptr}}; + +std::string clapCategoriesToVST3(const char *const *clap_categories) { std::vector r; auto f = clap_categories; @@ -123,16 +121,16 @@ std::string clapCategoriesToVST3(const char* const* clap_categories) ++f; } std::vector r2; - for (auto& i : r) + for (auto &i : r) { if (std::find(r2.begin(), r2.end(), i) == r2.end()) { r2.push_back(i); } - } - + } + std::string result; - for (auto& i : r2) + for (auto &i : r2) { if (result.size() + i.size() <= Steinberg::PClassInfo2::kSubCategoriesSize) { @@ -147,5 +145,4 @@ std::string clapCategoriesToVST3(const char* const* clap_categories) } result.pop_back(); return result; - } \ No newline at end of file diff --git a/src/detail/vst3/categories.h b/src/detail/vst3/categories.h index 5db448a3..86d3b38f 100644 --- a/src/detail/vst3/categories.h +++ b/src/detail/vst3/categories.h @@ -3,4 +3,4 @@ // see categories.cpp for details #include -std::string clapCategoriesToVST3(const char* const* clap_categories); +std::string clapCategoriesToVST3(const char *const *clap_categories); diff --git a/src/detail/vst3/os/linux.cpp b/src/detail/vst3/os/linux.cpp index 6e7c269a..a8f07498 100644 --- a/src/detail/vst3/os/linux.cpp +++ b/src/detail/vst3/os/linux.cpp @@ -1,12 +1,12 @@ /** -* the Linux helper -* -* provides services for all plugin instances regarding Linux -* - global timer object -* - dispatch to UI thread -* - get binary name -* -*/ + * the Linux helper + * + * provides services for all plugin instances regarding Linux + * - global timer object + * - dispatch to UI thread + * - get binary name + * + */ #include "public.sdk/source/main/moduleinit.h" #include "osutil.h" @@ -17,25 +17,22 @@ namespace os { - void log(const char* text) - { - fprintf(stderr, "%s\n", text); - } + void log(const char *text) { fprintf(stderr, "%s\n", text); } - class LinuxHelper - { - public: - void init(); - void terminate(); - void attach(IPlugObject* plugobject); - void detach(IPlugObject* plugobject); + class LinuxHelper + { + public: + void init(); + void terminate(); + void attach(IPlugObject *plugobject); + void detach(IPlugObject *plugobject); - private: - void executeDefered(); - std::vector _plugs; - } gLinuxHelper; + private: + void executeDefered(); + std::vector _plugs; + } gLinuxHelper; - #if 0 +#if 0 class WindowsHelper { public: @@ -52,8 +49,8 @@ namespace os } gWindowsHelper; #endif - static Steinberg::ModuleInitializer createMessageWindow([] { gLinuxHelper.init(); }); - static Steinberg::ModuleTerminator dropMessageWindow([] { gLinuxHelper.terminate(); }); + static Steinberg::ModuleInitializer createMessageWindow([] { gLinuxHelper.init(); }); + static Steinberg::ModuleTerminator dropMessageWindow([] { gLinuxHelper.terminate(); }); #if 0 static char* getModuleNameA() @@ -79,40 +76,40 @@ namespace os } #endif - static std::string getModuleName() - { - Dl_info info; - if ( dladdr((void*)getModuleName,&info) ) - { - return info.dli_fname; - } - return nullptr; - } - - std::string getParentFolderName() - { - std::filesystem::path n = getModuleName(); - if (n.has_parent_path()) - { - auto p = n.parent_path(); - if (p.has_filename()) - { - return p.filename().u8string(); - } - } - - return std::string(); - } - - std::string getBinaryName() - { - std::filesystem::path n = getModuleName(); - if (n.has_filename()) - { - return n.stem().u8string(); - } - return std::string(); - } + static std::string getModuleName() + { + Dl_info info; + if (dladdr((void *)getModuleName, &info)) + { + return info.dli_fname; + } + return nullptr; + } + + std::string getParentFolderName() + { + std::filesystem::path n = getModuleName(); + if (n.has_parent_path()) + { + auto p = n.parent_path(); + if (p.has_filename()) + { + return p.filename().u8string(); + } + } + + return std::string(); + } + + std::string getBinaryName() + { + std::filesystem::path n = getModuleName(); + if (n.has_filename()) + { + return n.stem().u8string(); + } + return std::string(); + } #if 0 LRESULT WindowsHelper::Wndproc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) @@ -155,52 +152,33 @@ namespace os } #endif - void LinuxHelper::init() - { - - } + void LinuxHelper::init() {} - void LinuxHelper::terminate() - { - - } + void LinuxHelper::terminate() {} - void LinuxHelper::executeDefered() - { - for (auto p : _plugs) - { - p->onIdle(); - } - } - void LinuxHelper::attach(IPlugObject* plugobject) - { - _plugs.push_back(plugobject); - } + void LinuxHelper::executeDefered() + { + for (auto p : _plugs) + { + p->onIdle(); + } + } + void LinuxHelper::attach(IPlugObject *plugobject) { _plugs.push_back(plugobject); } - void LinuxHelper::detach(IPlugObject * plugobject) - { - _plugs.erase(std::remove(_plugs.begin(), _plugs.end(), plugobject), _plugs.end()); - } + void LinuxHelper::detach(IPlugObject *plugobject) + { + _plugs.erase(std::remove(_plugs.begin(), _plugs.end(), plugobject), _plugs.end()); + } -} +} // namespace os namespace os { - // [UI Thread] - void attach(IPlugObject* plugobject) - { - gLinuxHelper.attach(plugobject); - } - - // [UI Thread] - void detach(IPlugObject* plugobject) - { - gLinuxHelper.detach(plugobject); - } + // [UI Thread] + void attach(IPlugObject *plugobject) { gLinuxHelper.attach(plugobject); } - uint64_t getTickInMS() - { - return clock(); - } -} + // [UI Thread] + void detach(IPlugObject *plugobject) { gLinuxHelper.detach(plugobject); } + uint64_t getTickInMS() { return clock(); } +} // namespace os diff --git a/src/detail/vst3/os/macos.mm b/src/detail/vst3/os/macos.mm index baaed75c..569cfdf3 100644 --- a/src/detail/vst3/os/macos.mm +++ b/src/detail/vst3/os/macos.mm @@ -1,15 +1,14 @@ #define NOMINMAX 1 - /** -* the macos helper -* -* provides services for all plugin instances regarding macos -* - global timer object -* - dispatch to UI thread -* - get the bundle name -* -*/ + * the macos helper + * + * provides services for all plugin instances regarding macos + * - global timer object + * - dispatch to UI thread + * - get the bundle name + * + */ #include #include "public.sdk/source/main/moduleinit.h" @@ -26,114 +25,100 @@ namespace os { - void log(const char* text) - { - NSLog(@"%s", text); - } - - class MacOSHelper - { - public: - void init(); - void terminate(); - void attach(IPlugObject* plugobject); - void detach(IPlugObject* plugobject); - private: - static void timerCallback(CFRunLoopTimerRef t, void* info); - void executeDefered(); - CFRunLoopTimerRef _timer = nullptr; - std::vector _plugs; - } gMacOSHelper; - - static Steinberg::ModuleInitializer createMessageWindow([] { gMacOSHelper.init(); }); - static Steinberg::ModuleTerminator dropMessageWindow([] { gMacOSHelper.terminate(); }); - - void MacOSHelper::init() - { - - } - - void MacOSHelper::terminate() - { - - } - - void MacOSHelper::executeDefered() - { - for (auto p : _plugs) - { - p->onIdle(); - } - } - - void MacOSHelper::timerCallback(CFRunLoopTimerRef t, void* info) + void log(const char *text) { NSLog(@"%s", text); } + + class MacOSHelper + { + public: + void init(); + void terminate(); + void attach(IPlugObject *plugobject); + void detach(IPlugObject *plugobject); + + private: + static void timerCallback(CFRunLoopTimerRef t, void *info); + void executeDefered(); + CFRunLoopTimerRef _timer = nullptr; + std::vector _plugs; + } gMacOSHelper; + + static Steinberg::ModuleInitializer createMessageWindow([] { gMacOSHelper.init(); }); + static Steinberg::ModuleTerminator dropMessageWindow([] { gMacOSHelper.terminate(); }); + + void MacOSHelper::init() {} + + void MacOSHelper::terminate() {} + + void MacOSHelper::executeDefered() { - auto self = static_cast(info); + for (auto p : _plugs) + { + p->onIdle(); + } + } + + void MacOSHelper::timerCallback(CFRunLoopTimerRef t, void *info) + { + auto self = static_cast(info); self->executeDefered(); } static float kIntervall = 10.f; - void MacOSHelper::attach(IPlugObject* plugobject) - { - if ( _plugs.empty() ) - { - CFRunLoopTimerContext context = {}; - context.info = this; - _timer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + (kIntervall * 0.001f), kIntervall * 0.001f, 0, 0, timerCallback, &context); - if (_timer) - CFRunLoopAddTimer(CFRunLoopGetCurrent(), _timer, kCFRunLoopCommonModes); - } - _plugs.push_back(plugobject); - } - - void MacOSHelper::detach(IPlugObject * plugobject) - { - _plugs.erase(std::remove(_plugs.begin(), _plugs.end(), plugobject), _plugs.end()); - if ( _plugs.empty() ) - { - if (_timer) - { - CFRunLoopTimerInvalidate(_timer); - CFRelease(_timer); - } - _timer = nullptr; - } - } + void MacOSHelper::attach(IPlugObject *plugobject) + { + if (_plugs.empty()) + { + CFRunLoopTimerContext context = {}; + context.info = this; + _timer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + (kIntervall * 0.001f), + kIntervall * 0.001f, 0, 0, timerCallback, &context); + if (_timer) + CFRunLoopAddTimer(CFRunLoopGetCurrent(), _timer, kCFRunLoopCommonModes); + } + _plugs.push_back(plugobject); + } + + void MacOSHelper::detach(IPlugObject *plugobject) + { + _plugs.erase(std::remove(_plugs.begin(), _plugs.end(), plugobject), _plugs.end()); + if (_plugs.empty()) + { + if (_timer) + { + CFRunLoopTimerInvalidate(_timer); + CFRelease(_timer); + } + _timer = nullptr; + } + } } // the dummy class so we can use NSBundle bundleForClass @interface clapwrapper_dummy_object_to_trick_the_os : NSObject -- (void) fun; +- (void)fun; @end @implementation clapwrapper_dummy_object_to_trick_the_os -- (void) fun{} +- (void)fun +{ +} @end namespace os { - // [UI Thread] - void attach(IPlugObject* plugobject) - { - gMacOSHelper.attach(plugobject); - } - - // [UI Thread] - void detach(IPlugObject* plugobject) - { - gMacOSHelper.detach(plugobject); - } - - uint64_t getTickInMS() - { - return (::clock() * 1000) / CLOCKS_PER_SEC; - } + // [UI Thread] + void attach(IPlugObject *plugobject) { gMacOSHelper.attach(plugobject); } + + // [UI Thread] + void detach(IPlugObject *plugobject) { gMacOSHelper.detach(plugobject); } + + uint64_t getTickInMS() { return (::clock() * 1000) / CLOCKS_PER_SEC; } std::string getParentFolderName() { - NSString* identifier = [[NSBundle bundleForClass:[clapwrapper_dummy_object_to_trick_the_os class]] bundlePath]; + NSString *identifier = [[NSBundle bundleForClass:[clapwrapper_dummy_object_to_trick_the_os class]] bundlePath]; fs::path n = [identifier UTF8String]; if (n.has_parent_path()) { @@ -143,7 +128,7 @@ uint64_t getTickInMS() return p.filename().u8string(); } } - + return std::string(); } @@ -151,9 +136,9 @@ uint64_t getTickInMS() { // this is useless // NSString* identifier = [[NSBundle mainBundle] bundleIdentifier]; - + // this is needed: - NSString* identifier = [[NSBundle bundleForClass:[clapwrapper_dummy_object_to_trick_the_os class]] bundlePath]; + NSString *identifier = [[NSBundle bundleForClass:[clapwrapper_dummy_object_to_trick_the_os class]] bundlePath]; fs::path k = [identifier UTF8String]; return k.stem(); } diff --git a/src/detail/vst3/os/osutil.h b/src/detail/vst3/os/osutil.h index 6c30b94e..e3f60845 100644 --- a/src/detail/vst3/os/osutil.h +++ b/src/detail/vst3/os/osutil.h @@ -1,7 +1,7 @@ #pragma once /* - a minimalistic OS layer + a minimalistic OS layer */ @@ -11,31 +11,30 @@ #include "fmt/format.h" #include "fmt/ranges.h" - namespace os { - class IPlugObject - { - public: - virtual void onIdle() = 0; - virtual ~IPlugObject() {} - }; - void attach(IPlugObject* plugobject); - void detach(IPlugObject* plugobject); - uint64_t getTickInMS(); - std::string getParentFolderName(); - std::string getBinaryName(); + class IPlugObject + { + public: + virtual void onIdle() = 0; + virtual ~IPlugObject() {} + }; + void attach(IPlugObject *plugobject); + void detach(IPlugObject *plugobject); + uint64_t getTickInMS(); + std::string getParentFolderName(); + std::string getBinaryName(); - void log(const char* text); + void log(const char *text); - template - void log(const char* format_str, Args&&... args) { - fmt::memory_buffer buf; - fmt::format_to(std::back_inserter(buf), format_str, args...); - buf.push_back(0); - log((const char*)buf.data()); - }; -} + template void log(const char *format_str, Args &&...args) + { + fmt::memory_buffer buf; + fmt::format_to(std::back_inserter(buf), format_str, args...); + buf.push_back(0); + log((const char *)buf.data()); + }; +} // namespace os #ifndef CLAP_WRAPPER_LOGLEVEL #define CLAP_WRAPPER_LOGLEVEL 2 @@ -59,32 +58,29 @@ namespace os namespace util { - template - class fixedqueue - { - public: - inline void push(const T& val) - { - push(&val); - } - inline void push(const T* val) - { - _elements[_head] = *val; - _head = (_head + 1) % Q; - } - inline bool pop(T& out) - { - if (_head == _tail) - { - return false; - } - out = _elements[_tail]; - _tail = (_tail + 1) % Q; - return true; - } - private: - T _elements[Q] = { }; - std::atomic_uint32_t _head = 0u; - std::atomic_uint32_t _tail = 0u; - }; -}; \ No newline at end of file + template class fixedqueue + { + public: + inline void push(const T &val) { push(&val); } + inline void push(const T *val) + { + _elements[_head] = *val; + _head = (_head + 1) % Q; + } + inline bool pop(T &out) + { + if (_head == _tail) + { + return false; + } + out = _elements[_tail]; + _tail = (_tail + 1) % Q; + return true; + } + + private: + T _elements[Q] = {}; + std::atomic_uint32_t _head = 0u; + std::atomic_uint32_t _tail = 0u; + }; +}; // namespace util \ No newline at end of file diff --git a/src/detail/vst3/os/windows.cpp b/src/detail/vst3/os/windows.cpp index 7d8975fa..5c3ebe4f 100644 --- a/src/detail/vst3/os/windows.cpp +++ b/src/detail/vst3/os/windows.cpp @@ -1,13 +1,13 @@ #define NOMINMAX 1 /** -* the windows helper -* -* provides services for all plugin instances regarding Windows -* - global timer object -* - dispatch to UI thread -* -*/ + * the windows helper + * + * provides services for all plugin instances regarding Windows + * - global timer object + * - dispatch to UI thread + * + */ #include #include @@ -21,147 +21,135 @@ extern HINSTANCE ghInst; namespace os { - void log(const char* text) - { - OutputDebugStringA(text); - OutputDebugStringA("\n"); - - } - - class WindowsHelper - { - public: - void init(); - void terminate(); - void attach(IPlugObject* plugobject); - void detach(IPlugObject* plugobject); - private: - void executeDefered(); - static LRESULT Wndproc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); - HWND _msgWin = 0; - UINT_PTR _timer = 0; - std::vector _plugs; - } gWindowsHelper; - - static Steinberg::ModuleInitializer createMessageWindow([] { gWindowsHelper.init(); }); - static Steinberg::ModuleTerminator dropMessageWindow([] { gWindowsHelper.terminate(); }); - - static char* getModuleNameA() - { - static char modulename[2048]; - HMODULE selfmodule; - if (GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCSTR)getModuleNameA, &selfmodule)) - { - auto size = GetModuleFileNameA(selfmodule, modulename, 2048); - } - return modulename; - } - - static TCHAR* getModuleName() - { - static TCHAR modulename[2048]; - HMODULE selfmodule; - if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)getModuleName, &selfmodule)) - { - auto size = GetModuleFileName(selfmodule, modulename, 2048); - } - return modulename; - } - - std::string getParentFolderName() - { - std::filesystem::path n = getModuleNameA(); - if (n.has_parent_path()) - { - auto p = n.parent_path(); - if (p.has_filename()) - { - return p.filename().u8string(); - } - } - - return std::string(); - } - - std::string getBinaryName() - { - std::filesystem::path n = getModuleNameA(); - if (n.has_filename()) - { - return n.stem().u8string(); - } - return std::string(); - } - - - LRESULT WindowsHelper::Wndproc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) - { - switch (msg) - { - case WM_USER + 1: - return 1; - break; - case WM_TIMER: - gWindowsHelper.executeDefered(); - return 1; - break; - default: - return ::DefWindowProc(hwnd, msg, wParam, lParam); - } - } - - void WindowsHelper::init() - { - auto modulename = getModuleName(); - WNDCLASSEX wc; - memset(&wc, 0, sizeof(wc)); - wc.cbSize = sizeof(wc); - wc.hInstance = ghInst; - wc.lpfnWndProc = (WNDPROC)&Wndproc; - wc.lpszClassName = modulename; - auto a = RegisterClassEx(&wc); - - _msgWin = ::CreateWindowEx(0, modulename, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 0); - ::SetWindowLongW(_msgWin, GWLP_WNDPROC, (LONG_PTR)&Wndproc); - _timer = ::SetTimer(_msgWin, 0, 20, NULL); - } - - void WindowsHelper::terminate() - { - ::KillTimer(_msgWin, _timer); - ::DestroyWindow(_msgWin); - ::UnregisterClass(getModuleName(), ghInst); - } - - void WindowsHelper::executeDefered() - { - for (auto&& p : _plugs) p->onIdle(); - } - - void WindowsHelper::attach(IPlugObject* plugobject) - { - _plugs.push_back(plugobject); - } - - void WindowsHelper::detach(IPlugObject * plugobject) - { - _plugs.erase(std::remove(_plugs.begin(), _plugs.end(), plugobject), _plugs.end()); - } - - // [UI Thread] - void attach(IPlugObject* plugobject) - { - gWindowsHelper.attach(plugobject); - } - - // [UI Thread] - void detach(IPlugObject* plugobject) - { - gWindowsHelper.detach(plugobject); - } - - uint64_t getTickInMS() - { - return GetTickCount64(); - } -} + void log(const char *text) + { + OutputDebugStringA(text); + OutputDebugStringA("\n"); + } + + class WindowsHelper + { + public: + void init(); + void terminate(); + void attach(IPlugObject *plugobject); + void detach(IPlugObject *plugobject); + + private: + void executeDefered(); + static LRESULT Wndproc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + HWND _msgWin = 0; + UINT_PTR _timer = 0; + std::vector _plugs; + } gWindowsHelper; + + static Steinberg::ModuleInitializer createMessageWindow([] { gWindowsHelper.init(); }); + static Steinberg::ModuleTerminator dropMessageWindow([] { gWindowsHelper.terminate(); }); + + static char *getModuleNameA() + { + static char modulename[2048]; + HMODULE selfmodule; + if (GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCSTR)getModuleNameA, &selfmodule)) + { + auto size = GetModuleFileNameA(selfmodule, modulename, 2048); + } + return modulename; + } + + static TCHAR *getModuleName() + { + static TCHAR modulename[2048]; + HMODULE selfmodule; + if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)getModuleName, &selfmodule)) + { + auto size = GetModuleFileName(selfmodule, modulename, 2048); + } + return modulename; + } + + std::string getParentFolderName() + { + std::filesystem::path n = getModuleNameA(); + if (n.has_parent_path()) + { + auto p = n.parent_path(); + if (p.has_filename()) + { + return p.filename().u8string(); + } + } + + return std::string(); + } + + std::string getBinaryName() + { + std::filesystem::path n = getModuleNameA(); + if (n.has_filename()) + { + return n.stem().u8string(); + } + return std::string(); + } + + LRESULT WindowsHelper::Wndproc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + switch (msg) + { + case WM_USER + 1: + return 1; + break; + case WM_TIMER: + gWindowsHelper.executeDefered(); + return 1; + break; + default: + return ::DefWindowProc(hwnd, msg, wParam, lParam); + } + } + + void WindowsHelper::init() + { + auto modulename = getModuleName(); + WNDCLASSEX wc; + memset(&wc, 0, sizeof(wc)); + wc.cbSize = sizeof(wc); + wc.hInstance = ghInst; + wc.lpfnWndProc = (WNDPROC)&Wndproc; + wc.lpszClassName = modulename; + auto a = RegisterClassEx(&wc); + + _msgWin = ::CreateWindowEx(0, modulename, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 0); + ::SetWindowLongW(_msgWin, GWLP_WNDPROC, (LONG_PTR)&Wndproc); + _timer = ::SetTimer(_msgWin, 0, 20, NULL); + } + + void WindowsHelper::terminate() + { + ::KillTimer(_msgWin, _timer); + ::DestroyWindow(_msgWin); + ::UnregisterClass(getModuleName(), ghInst); + } + + void WindowsHelper::executeDefered() + { + for (auto &&p : _plugs) + p->onIdle(); + } + + void WindowsHelper::attach(IPlugObject *plugobject) { _plugs.push_back(plugobject); } + + void WindowsHelper::detach(IPlugObject *plugobject) + { + _plugs.erase(std::remove(_plugs.begin(), _plugs.end(), plugobject), _plugs.end()); + } + + // [UI Thread] + void attach(IPlugObject *plugobject) { gWindowsHelper.attach(plugobject); } + + // [UI Thread] + void detach(IPlugObject *plugobject) { gWindowsHelper.detach(plugobject); } + + uint64_t getTickInMS() { return GetTickCount64(); } +} // namespace os diff --git a/src/detail/vst3/parameter.cpp b/src/detail/vst3/parameter.cpp index 28395932..20663ef8 100644 --- a/src/detail/vst3/parameter.cpp +++ b/src/detail/vst3/parameter.cpp @@ -5,42 +5,31 @@ using namespace Steinberg; -Vst3Parameter::Vst3Parameter(const Steinberg::Vst::ParameterInfo& vst3info, const clap_param_info_t* clapinfo) -: Steinberg::Vst::Parameter(vst3info) -, id(clapinfo->id) -, cookie(clapinfo->cookie) -, min_value(clapinfo->min_value) -, max_value(clapinfo->max_value) +Vst3Parameter::Vst3Parameter(const Steinberg::Vst::ParameterInfo &vst3info, const clap_param_info_t *clapinfo) + : Steinberg::Vst::Parameter(vst3info), id(clapinfo->id), cookie(clapinfo->cookie), min_value(clapinfo->min_value), + max_value(clapinfo->max_value) { - // + // } -Vst3Parameter::Vst3Parameter(const Steinberg::Vst::ParameterInfo& vst3info, uint8_t bus, uint8_t channel, uint8_t cc) - : Steinberg::Vst::Parameter(vst3info) - , id(vst3info.id) - , cookie(nullptr) - , min_value(0) - , max_value(127) - , isMidi(true) - , channel(channel) - , controller(cc) -{ - if (cc == Vst::ControllerNumbers::kPitchBend) - { - max_value = 16383; - } -} -Vst3Parameter::~Vst3Parameter() +Vst3Parameter::Vst3Parameter(const Steinberg::Vst::ParameterInfo &vst3info, uint8_t bus, uint8_t channel, uint8_t cc) + : Steinberg::Vst::Parameter(vst3info), id(vst3info.id), cookie(nullptr), min_value(0), max_value(127), isMidi(true), + channel(channel), controller(cc) { + if (cc == Vst::ControllerNumbers::kPitchBend) + { + max_value = 16383; + } } +Vst3Parameter::~Vst3Parameter() {} bool Vst3Parameter::setNormalized(Steinberg::Vst::ParamValue v) { - if (isMidi && info.flags & Steinberg::Vst::ParameterInfo::kIsProgramChange) - { - return true; - } - return super::setNormalized(v); + if (isMidi && info.flags & Steinberg::Vst::ParameterInfo::kIsProgramChange) + { + return true; + } + return super::setNormalized(v); } #if 0 @@ -55,118 +44,119 @@ bool Vst3Parameter::fromString(const Steinberg::Vst::TChar* string, Steinberg::V } #endif -Vst3Parameter* Vst3Parameter::create(const clap_param_info_t* info, std::function getUnitId) +Vst3Parameter *Vst3Parameter::create(const clap_param_info_t *info, + std::function getUnitId) { - Vst::ParameterInfo v; - - v.id = info->id & 0x7FFFFFFF; // why ever SMTG does not want the highest bit to be set - - // the long name might contain the module name - // this will change when we split the module to units - std::string fullname; - Vst::UnitID unit = 0; - - // if there is a module name and a lambda - if (info->module[0] != 0 && getUnitId) - { - unit = getUnitId(info->module); - fullname = info->name; - } - else - { - if (!fullname.empty()) - { - fullname.append("/"); - } - fullname.append(info->name); - if (fullname.size() >= str16BufferSize(v.title)) - { - fullname = info->name; - } - } - - str8ToStr16(v.title, fullname.c_str(), str16BufferSize(v.title)); - // TODO: string shrink algorithm shortening the string a bit - str8ToStr16(v.shortTitle, info->name, str16BufferSize(v.shortTitle)); - v.units[0] = 0; // unfortunately, CLAP has no unit for parameter values - v.unitId = unit; - - /* - In the VST3 SDK the normalized value [0, 1] to discrete value and its inverse function discrete value to normalized value is defined like this: - - Normalize: - double normalized = discreteValue / (double) stepCount; - - Denormalize : - int discreteValue = min (stepCount, normalized * (stepCount + 1)); - */ - - v.flags = Vst::ParameterInfo::kNoFlags - | ((info->flags & CLAP_PARAM_IS_HIDDEN) ? Vst::ParameterInfo::kIsHidden : 0) - | ((info->flags & CLAP_PARAM_IS_BYPASS) ? Vst::ParameterInfo::kIsBypass : 0) - | ((info->flags & CLAP_PARAM_IS_AUTOMATABLE) ? Vst::ParameterInfo::kCanAutomate : 0) - | ((info->flags & CLAP_PARAM_IS_READONLY) ? Vst::ParameterInfo::kIsReadOnly : 0) - // | ((info->flags & CLAP_PARAM_IS_READONLY) ? Vst::ParameterInfo::kIsReadOnly : 0) - ; - - auto param_range = (info->max_value - info->min_value); - - v.defaultNormalizedValue = (info->default_value-info->min_value) / param_range; - if (info->flags & CLAP_PARAM_IS_STEPPED) - { - auto steps = param_range + 1; - v.stepCount = steps; - } - else - v.stepCount = 0; - - auto result = new Vst3Parameter(v, info); - result->addRef(); // ParameterContainer doesn't add the ref -> but we don't have copies - return result; + Vst::ParameterInfo v; + + v.id = info->id & 0x7FFFFFFF; // why ever SMTG does not want the highest bit to be set + + // the long name might contain the module name + // this will change when we split the module to units + std::string fullname; + Vst::UnitID unit = 0; + + // if there is a module name and a lambda + if (info->module[0] != 0 && getUnitId) + { + unit = getUnitId(info->module); + fullname = info->name; + } + else + { + if (!fullname.empty()) + { + fullname.append("/"); + } + fullname.append(info->name); + if (fullname.size() >= str16BufferSize(v.title)) + { + fullname = info->name; + } + } + + str8ToStr16(v.title, fullname.c_str(), str16BufferSize(v.title)); + // TODO: string shrink algorithm shortening the string a bit + str8ToStr16(v.shortTitle, info->name, str16BufferSize(v.shortTitle)); + v.units[0] = 0; // unfortunately, CLAP has no unit for parameter values + v.unitId = unit; + + /* + In the VST3 SDK the normalized value [0, 1] to discrete value and its inverse function discrete value + to normalized value is defined like this: + + Normalize: + double normalized = discreteValue / (double) stepCount; + + Denormalize : + int discreteValue = min (stepCount, normalized * (stepCount + 1)); + */ + + v.flags = Vst::ParameterInfo::kNoFlags | ((info->flags & CLAP_PARAM_IS_HIDDEN) ? Vst::ParameterInfo::kIsHidden : 0) | + ((info->flags & CLAP_PARAM_IS_BYPASS) ? Vst::ParameterInfo::kIsBypass : 0) | + ((info->flags & CLAP_PARAM_IS_AUTOMATABLE) ? Vst::ParameterInfo::kCanAutomate : 0) | + ((info->flags & CLAP_PARAM_IS_READONLY) ? Vst::ParameterInfo::kIsReadOnly : 0) + // | ((info->flags & CLAP_PARAM_IS_READONLY) ? Vst::ParameterInfo::kIsReadOnly : 0) + ; + + auto param_range = (info->max_value - info->min_value); + + v.defaultNormalizedValue = (info->default_value - info->min_value) / param_range; + if (info->flags & CLAP_PARAM_IS_STEPPED) + { + auto steps = param_range + 1; + v.stepCount = steps; + } + else + v.stepCount = 0; + + auto result = new Vst3Parameter(v, info); + result->addRef(); // ParameterContainer doesn't add the ref -> but we don't have copies + return result; } -Vst3Parameter* Vst3Parameter::create(uint8_t bus, uint8_t channel, uint8_t cc, Vst::ParamID id) +Vst3Parameter *Vst3Parameter::create(uint8_t bus, uint8_t channel, uint8_t cc, Vst::ParamID id) { - Vst::ParameterInfo v; - - v.id = id; - - auto name = "controller"; - // the long name might contain the module name - // this will change when we split the module to units - std::string fullname("MIDI"); - if (!fullname.empty()) - { - fullname.append("/"); - } - fullname.append("controller"); - if (fullname.size() >= str16BufferSize(v.title)) - { - fullname = "controller"; - } - str8ToStr16(v.title, fullname.c_str(), str16BufferSize(v.title)); - // TODO: string shrink algorithm shortening the string a bit - str8ToStr16(v.shortTitle, name, str16BufferSize(v.shortTitle)); - v.units[0] = 0; // unfortunately, CLAP has no unit for parameter values - v.unitId = channel+1; - - v.defaultNormalizedValue = 0; - v.flags = Vst::ParameterInfo::kNoFlags; - if (cc == Vst::ControllerNumbers::kCtrlProgramChange) - { - v.flags |= Vst::ParameterInfo::kIsProgramChange; - v.stepCount = 128; - } - - v.defaultNormalizedValue = 0; - v.stepCount = 128; - - if (cc == Vst::ControllerNumbers::kPitchBend) - { - v.stepCount = 16384; - } - - auto result = new Vst3Parameter(v,bus, channel, cc); - result->addRef(); // ParameterContainer doesn't add the ref -> but we don't have copies - return result; + Vst::ParameterInfo v; + + v.id = id; + + auto name = "controller"; + // the long name might contain the module name + // this will change when we split the module to units + std::string fullname("MIDI"); + if (!fullname.empty()) + { + fullname.append("/"); + } + fullname.append("controller"); + if (fullname.size() >= str16BufferSize(v.title)) + { + fullname = "controller"; + } + str8ToStr16(v.title, fullname.c_str(), str16BufferSize(v.title)); + // TODO: string shrink algorithm shortening the string a bit + str8ToStr16(v.shortTitle, name, str16BufferSize(v.shortTitle)); + v.units[0] = 0; // unfortunately, CLAP has no unit for parameter values + v.unitId = channel + 1; + + v.defaultNormalizedValue = 0; + v.flags = Vst::ParameterInfo::kNoFlags; + if (cc == Vst::ControllerNumbers::kCtrlProgramChange) + { + v.flags |= Vst::ParameterInfo::kIsProgramChange; + v.stepCount = 128; + } + + v.defaultNormalizedValue = 0; + v.stepCount = 128; + + if (cc == Vst::ControllerNumbers::kPitchBend) + { + v.stepCount = 16384; + } + + auto result = new Vst3Parameter(v, bus, channel, cc); + result->addRef(); // ParameterContainer doesn't add the ref -> but we don't have copies + return result; } diff --git a/src/detail/vst3/parameter.h b/src/detail/vst3/parameter.h index 96246fd0..4943090f 100644 --- a/src/detail/vst3/parameter.h +++ b/src/detail/vst3/parameter.h @@ -29,9 +29,11 @@ class Vst3Parameter : public Steinberg::Vst::Parameter { using super = Steinberg::Vst::Parameter; + protected: - Vst3Parameter(const Steinberg::Vst::ParameterInfo& vst3info, const clap_param_info_t* clapinfo); - Vst3Parameter(const Steinberg::Vst::ParameterInfo& vst3info, uint8_t bus, uint8_t channel, uint8_t cc); + Vst3Parameter(const Steinberg::Vst::ParameterInfo &vst3info, const clap_param_info_t *clapinfo); + Vst3Parameter(const Steinberg::Vst::ParameterInfo &vst3info, uint8_t bus, uint8_t channel, uint8_t cc); + public: virtual ~Vst3Parameter(); bool setNormalized(Steinberg::Vst::ParamValue v) override; @@ -47,24 +49,18 @@ class Vst3Parameter : public Steinberg::Vst::Parameter bool fromString(const Steinberg::Vst::TChar* string, Steinberg::Vst::ParamValue& valueNormalized) const override; #endif - inline double asClapValue(double vst3value) const - { - return vst3value * (max_value - min_value) + min_value; - } - inline double asVst3Value(double clapvalue) const - { - return (clapvalue - min_value) / (max_value - min_value); - } - static Vst3Parameter* create(const clap_param_info_t* info, std::function getUnitId); - static Vst3Parameter* create(uint8_t bus, uint8_t channel, uint8_t cc, Steinberg::Vst::ParamID id); + inline double asClapValue(double vst3value) const { return vst3value * (max_value - min_value) + min_value; } + inline double asVst3Value(double clapvalue) const { return (clapvalue - min_value) / (max_value - min_value); } + static Vst3Parameter *create(const clap_param_info_t *info, + std::function getUnitId); + static Vst3Parameter *create(uint8_t bus, uint8_t channel, uint8_t cc, Steinberg::Vst::ParamID id); // copies from the clap_param_info_t clap_id id = 0; - void* cookie = nullptr; - double min_value; // minimum plain value - double max_value; // maximum plain value + void *cookie = nullptr; + double min_value; // minimum plain value + double max_value; // maximum plain value // or it was MIDI bool isMidi = false; uint8_t channel = 0; uint8_t controller = 0; - }; diff --git a/src/detail/vst3/plugview.cpp b/src/detail/vst3/plugview.cpp index 8f3e73bf..8c60a59d 100644 --- a/src/detail/vst3/plugview.cpp +++ b/src/detail/vst3/plugview.cpp @@ -3,16 +3,11 @@ // #include #include -WrappedView::WrappedView(const clap_plugin_t* plugin, const clap_plugin_gui_t* gui, std::function onDestroy, +WrappedView::WrappedView(const clap_plugin_t *plugin, const clap_plugin_gui_t *gui, std::function onDestroy, std::function onRunLoopAvailable) - : IPlugView() - , FObject() - , _plugin(plugin) - , _extgui(gui) - , _onDestroy(onDestroy) - , _onRunLoopAvailable(onRunLoopAvailable) + : IPlugView(), FObject(), _plugin(plugin), _extgui(gui), _onDestroy(onDestroy), + _onRunLoopAvailable(onRunLoopAvailable) { - } WrappedView::~WrappedView() @@ -28,18 +23,18 @@ void WrappedView::ensure_ui() { if (!_created) { - const char* api{nullptr}; + const char *api{nullptr}; #if MAC - api = CLAP_WINDOW_API_COCOA; + api = CLAP_WINDOW_API_COCOA; #endif #if WIN - api = CLAP_WINDOW_API_WIN32; + api = CLAP_WINDOW_API_WIN32; #endif #if LIN - api = CLAP_WINDOW_API_X11; + api = CLAP_WINDOW_API_X11; #endif - if (_extgui->is_api_supported(_plugin, api, false)) + if (_extgui->is_api_supported(_plugin, api, false)) _extgui->create(_plugin, api, false); _created = true; @@ -58,17 +53,15 @@ void WrappedView::drop_ui() tresult PLUGIN_API WrappedView::isPlatformTypeSupported(FIDString type) { - static struct vst3_and_clap_match_types_t{ - const char* VST3; - const char* CLAP; - } platformTypeMatches[] = - { - { kPlatformTypeHWND, CLAP_WINDOW_API_WIN32}, - { kPlatformTypeNSView, CLAP_WINDOW_API_COCOA }, - { kPlatformTypeX11EmbedWindowID, CLAP_WINDOW_API_X11}, - { nullptr, nullptr } - }; - auto* n = platformTypeMatches; + static struct vst3_and_clap_match_types_t + { + const char *VST3; + const char *CLAP; + } platformTypeMatches[] = {{kPlatformTypeHWND, CLAP_WINDOW_API_WIN32}, + {kPlatformTypeNSView, CLAP_WINDOW_API_COCOA}, + {kPlatformTypeX11EmbedWindowID, CLAP_WINDOW_API_X11}, + {nullptr, nullptr}}; + auto *n = platformTypeMatches; while (n->VST3 && n->CLAP) { if (!strcmp(type, n->VST3)) @@ -84,19 +77,18 @@ tresult PLUGIN_API WrappedView::isPlatformTypeSupported(FIDString type) return kResultFalse; } -tresult PLUGIN_API WrappedView::attached(void* parent, FIDString type) +tresult PLUGIN_API WrappedView::attached(void *parent, FIDString type) { #if WIN - _window = { CLAP_WINDOW_API_WIN32, { parent } }; + _window = {CLAP_WINDOW_API_WIN32, {parent}}; #endif #if MAC - _window = { CLAP_WINDOW_API_COCOA, { parent } }; + _window = {CLAP_WINDOW_API_COCOA, {parent}}; #endif - #if LIN - _window = { CLAP_WINDOW_API_X11, { parent } }; + _window = {CLAP_WINDOW_API_X11, {parent}}; #endif ensure_ui(); @@ -108,10 +100,10 @@ tresult PLUGIN_API WrappedView::attached(void* parent, FIDString type) uint32_t h = _rect.getHeight(); if (_extgui->adjust_size(_plugin, &w, &h)) { - _rect.right = _rect.left + w +1; - _rect.bottom = _rect.top + h +1; + _rect.right = _rect.left + w + 1; + _rect.bottom = _rect.top + h + 1; } - _extgui->set_size(_plugin, w , h); + _extgui->set_size(_plugin, w, h); } _extgui->show(_plugin); return kResultOk; @@ -124,22 +116,13 @@ tresult PLUGIN_API WrappedView::removed() return kResultOk; } -tresult PLUGIN_API WrappedView::onWheel(float distance) -{ - return kResultOk; -} +tresult PLUGIN_API WrappedView::onWheel(float distance) { return kResultOk; } -tresult PLUGIN_API WrappedView::onKeyDown(char16 key, int16 keyCode, int16 modifiers) -{ - return kResultOk; -} +tresult PLUGIN_API WrappedView::onKeyDown(char16 key, int16 keyCode, int16 modifiers) { return kResultOk; } -tresult PLUGIN_API WrappedView::onKeyUp(char16 key, int16 keyCode, int16 modifiers) -{ - return kResultOk; -} +tresult PLUGIN_API WrappedView::onKeyUp(char16 key, int16 keyCode, int16 modifiers) { return kResultOk; } -tresult PLUGIN_API WrappedView::getSize(ViewRect* size) +tresult PLUGIN_API WrappedView::getSize(ViewRect *size) { ensure_ui(); if (size) @@ -157,7 +140,7 @@ tresult PLUGIN_API WrappedView::getSize(ViewRect* size) return kInvalidArgument; } -tresult PLUGIN_API WrappedView::onSize(ViewRect* newSize) +tresult PLUGIN_API WrappedView::onSize(ViewRect *newSize) { // TODO: discussion took place if this call should be ignored completely // since it seems not to match the CLAP UI scheme. @@ -185,11 +168,10 @@ tresult PLUGIN_API WrappedView::onSize(ViewRect* newSize) { return kResultFalse; } - } return kResultOk; } - + return kResultFalse; } @@ -200,13 +182,12 @@ tresult PLUGIN_API WrappedView::onFocus(TBool state) return kResultOk; } -tresult PLUGIN_API WrappedView::setFrame(IPlugFrame* frame) +tresult PLUGIN_API WrappedView::setFrame(IPlugFrame *frame) { _plugFrame = frame; #if LIN - if (_plugFrame->queryInterface(Steinberg::Linux::IRunLoop::iid, - (void **)&_runLoop) == Steinberg::kResultOk && + if (_plugFrame->queryInterface(Steinberg::Linux::IRunLoop::iid, (void **)&_runLoop) == Steinberg::kResultOk && _onRunLoopAvailable) { _onRunLoopAvailable(); @@ -222,7 +203,7 @@ tresult PLUGIN_API WrappedView::canResize() return _extgui->can_resize(_plugin) ? kResultOk : kResultFalse; } -tresult PLUGIN_API WrappedView::checkSizeConstraint(ViewRect* rect) +tresult PLUGIN_API WrappedView::checkSizeConstraint(ViewRect *rect) { ensure_ui(); uint32_t w = rect->getWidth(); diff --git a/src/detail/vst3/plugview.h b/src/detail/vst3/plugview.h index 03e16758..3768eeef 100644 --- a/src/detail/vst3/plugview.h +++ b/src/detail/vst3/plugview.h @@ -1,9 +1,9 @@ /* - Copyright (c) 2022 Timo Kaluza (defiantnerd) + Copyright (c) 2022 Timo Kaluza (defiantnerd) - This file is part of the clap-wrappers project which is released under MIT License. - See file LICENSE or go to https://github.com/free-audio/clap-wrapper for full license details. + This file is part of the clap-wrappers project which is released under MIT License. + See file LICENSE or go to https://github.com/free-audio/clap-wrapper for full license details. */ @@ -18,93 +18,92 @@ class WrappedView : public Steinberg::IPlugView, public Steinberg::FObject { public: - - WrappedView(const clap_plugin_t* plugin, const clap_plugin_gui_t* gui, std::function onDestroy, std::function onRunLoopAvailable); - ~WrappedView(); - - - // IPlugView interface - tresult PLUGIN_API isPlatformTypeSupported(FIDString type) override; - - /** The parent window of the view has been created, the (platform) representation of the view - should now be created as well. - Note that the parent is owned by the caller and you are not allowed to alter it in any way - other than adding your own views. - Note that in this call the plug-in could call a IPlugFrame::resizeView ()! - \param parent : platform handle of the parent window or view - \param type : \ref platformUIType which should be created */ - tresult PLUGIN_API attached(void* parent, FIDString type) override; - - /** The parent window of the view is about to be destroyed. - You have to remove all your own views from the parent window or view. */ - tresult PLUGIN_API removed() override; - - /** Handling of mouse wheel. */ - tresult PLUGIN_API onWheel(float distance) override; - - /** Handling of keyboard events : Key Down. - \param key : unicode code of key - \param keyCode : virtual keycode for non ascii keys - see \ref VirtualKeyCodes in keycodes.h - \param modifiers : any combination of modifiers - see \ref KeyModifier in keycodes.h - \return kResultTrue if the key is handled, otherwise kResultFalse. \n - Please note that kResultTrue must only be returned if the key has really been - handled. Otherwise key command handling of the host might be blocked! */ - tresult PLUGIN_API onKeyDown(char16 key, int16 keyCode, int16 modifiers) override; - - /** Handling of keyboard events : Key Up. - \param key : unicode code of key - \param keyCode : virtual keycode for non ascii keys - see \ref VirtualKeyCodes in keycodes.h - \param modifiers : any combination of KeyModifier - see \ref KeyModifier in keycodes.h - \return kResultTrue if the key is handled, otherwise return kResultFalse. */ - tresult PLUGIN_API onKeyUp(char16 key, int16 keyCode, int16 modifiers) override; - - /** Returns the size of the platform representation of the view. */ - tresult PLUGIN_API getSize(ViewRect* size) override; - - /** Resizes the platform representation of the view to the given rect. Note that if the plug-in - * requests a resize (IPlugFrame::resizeView ()) onSize has to be called afterward. */ - tresult PLUGIN_API onSize(ViewRect* newSize) override; - - /** Focus changed message. */ - tresult PLUGIN_API onFocus(TBool state) override; - - /** Sets IPlugFrame object to allow the plug-in to inform the host about resizing. */ - tresult PLUGIN_API setFrame(IPlugFrame* frame) override; - - /** Is view sizable by user. */ - tresult PLUGIN_API canResize() override; - - /** On live resize this is called to check if the view can be resized to the given rect, if not - * adjust the rect to the allowed size. */ - tresult PLUGIN_API checkSizeConstraint(ViewRect* rect) override; - - //---Interface------ - OBJ_METHODS(WrappedView, FObject) - DEFINE_INTERFACES - DEF_INTERFACE(IPlugView) - END_DEFINE_INTERFACES(FObject) - REFCOUNT_METHODS(FObject) + WrappedView(const clap_plugin_t *plugin, const clap_plugin_gui_t *gui, std::function onDestroy, + std::function onRunLoopAvailable); + ~WrappedView(); + + // IPlugView interface + tresult PLUGIN_API isPlatformTypeSupported(FIDString type) override; + + /** The parent window of the view has been created, the (platform) representation of the view + should now be created as well. + Note that the parent is owned by the caller and you are not allowed to alter it in any way + other than adding your own views. + Note that in this call the plug-in could call a IPlugFrame::resizeView ()! + \param parent : platform handle of the parent window or view + \param type : \ref platformUIType which should be created */ + tresult PLUGIN_API attached(void *parent, FIDString type) override; + + /** The parent window of the view is about to be destroyed. + You have to remove all your own views from the parent window or view. */ + tresult PLUGIN_API removed() override; + + /** Handling of mouse wheel. */ + tresult PLUGIN_API onWheel(float distance) override; + + /** Handling of keyboard events : Key Down. + \param key : unicode code of key + \param keyCode : virtual keycode for non ascii keys - see \ref VirtualKeyCodes in keycodes.h + \param modifiers : any combination of modifiers - see \ref KeyModifier in keycodes.h + \return kResultTrue if the key is handled, otherwise kResultFalse. \n + Please note that kResultTrue must only be returned if the key has + really been handled. Otherwise key command handling of the host might be blocked! */ + tresult PLUGIN_API onKeyDown(char16 key, int16 keyCode, int16 modifiers) override; + + /** Handling of keyboard events : Key Up. + \param key : unicode code of key + \param keyCode : virtual keycode for non ascii keys - see \ref VirtualKeyCodes in keycodes.h + \param modifiers : any combination of KeyModifier - see \ref KeyModifier in keycodes.h + \return kResultTrue if the key is handled, otherwise return kResultFalse. */ + tresult PLUGIN_API onKeyUp(char16 key, int16 keyCode, int16 modifiers) override; + + /** Returns the size of the platform representation of the view. */ + tresult PLUGIN_API getSize(ViewRect *size) override; + + /** Resizes the platform representation of the view to the given rect. Note that if the plug-in + * requests a resize (IPlugFrame::resizeView ()) onSize has to be called afterward. */ + tresult PLUGIN_API onSize(ViewRect *newSize) override; + + /** Focus changed message. */ + tresult PLUGIN_API onFocus(TBool state) override; + + /** Sets IPlugFrame object to allow the plug-in to inform the host about resizing. */ + tresult PLUGIN_API setFrame(IPlugFrame *frame) override; + + /** Is view sizable by user. */ + tresult PLUGIN_API canResize() override; + + /** On live resize this is called to check if the view can be resized to the given rect, if not + * adjust the rect to the allowed size. */ + tresult PLUGIN_API checkSizeConstraint(ViewRect *rect) override; + + //---Interface------ + OBJ_METHODS(WrappedView, FObject) + DEFINE_INTERFACES + DEF_INTERFACE(IPlugView) + END_DEFINE_INTERFACES(FObject) + REFCOUNT_METHODS(FObject) // wrapper needed interfaces - bool request_resize(uint32_t width, uint32_t height); + bool request_resize(uint32_t width, uint32_t height); private: - void ensure_ui(); - void drop_ui(); - const clap_plugin_t* _plugin = nullptr; - const clap_plugin_gui_t* _extgui = nullptr; - std::function _onDestroy = nullptr, _onRunLoopAvailable = nullptr; - clap_window_t _window = { nullptr, { nullptr } }; - IPlugFrame* _plugFrame = nullptr; - ViewRect _rect = {0,0,0,0}; - bool _created = false; - bool _attached = false; + void ensure_ui(); + void drop_ui(); + const clap_plugin_t *_plugin = nullptr; + const clap_plugin_gui_t *_extgui = nullptr; + std::function _onDestroy = nullptr, _onRunLoopAvailable = nullptr; + clap_window_t _window = {nullptr, {nullptr}}; + IPlugFrame *_plugFrame = nullptr; + ViewRect _rect = {0, 0, 0, 0}; + bool _created = false; + bool _attached = false; #if LIN public: - Steinberg::Linux::IRunLoop *getRunLoop() { return _runLoop; } + Steinberg::Linux::IRunLoop *getRunLoop() { return _runLoop; } + private: - Steinberg::Linux::IRunLoop *_runLoop = nullptr; + Steinberg::Linux::IRunLoop *_runLoop = nullptr; #endif - }; \ No newline at end of file diff --git a/src/detail/vst3/process.cpp b/src/detail/vst3/process.cpp index e401d9b1..018edad0 100644 --- a/src/detail/vst3/process.cpp +++ b/src/detail/vst3/process.cpp @@ -10,16 +10,16 @@ #include #include "../clap/automation.h" - namespace Clap { using namespace Steinberg; - void ProcessAdapter::setupProcessing(const clap_plugin_t* plugin, const clap_plugin_params_t* ext_params, - Vst::BusList& audioinputs, Vst::BusList& audiooutputs, - uint32_t numSamples, size_t numEventInputs, size_t numEventOutputs, - Steinberg::Vst::ParameterContainer& params, Steinberg::Vst::IComponentHandler* componenthandler, - IAutomation* automation, bool enablePolyPressure, bool supportsTuningNoteExpression) + void ProcessAdapter::setupProcessing(const clap_plugin_t *plugin, const clap_plugin_params_t *ext_params, + Vst::BusList &audioinputs, Vst::BusList &audiooutputs, uint32_t numSamples, + size_t numEventInputs, size_t numEventOutputs, + Steinberg::Vst::ParameterContainer ¶ms, + Steinberg::Vst::IComponentHandler *componenthandler, IAutomation *automation, + bool enablePolyPressure, bool supportsTuningNoteExpression) { _plugin = plugin; _ext_params = ext_params; @@ -46,12 +46,12 @@ namespace Clap delete[] _input_ports; _input_ports = nullptr; - if ( numInputs > 0) + if (numInputs > 0) { _input_ports = new clap_audio_buffer_t[numInputs]; for (auto i = 0U; i < numInputs; ++i) { - clap_audio_buffer_t& bus = _input_ports[i]; + clap_audio_buffer_t &bus = _input_ports[i]; Vst::BusInfo info; if (_audioinputs->at(i)->getInfo(info)) { @@ -73,13 +73,12 @@ namespace Clap delete[] _output_ports; _output_ports = nullptr; - if (numOutputs > 0) { _output_ports = new clap_audio_buffer_t[numOutputs]; for (auto i = 0U; i < numOutputs; ++i) { - clap_audio_buffer_t& bus = _output_ports[i]; + clap_audio_buffer_t &bus = _output_ports[i]; Vst::BusInfo info; if (_audiooutputs->at(i)->getInfo(info)) { @@ -122,7 +121,6 @@ namespace Clap _supportsPolyPressure = enablePolyPressure; _supportsTuningNoteExpression = supportsTuningNoteExpression; - } void ProcessAdapter::activateAudioBus(Steinberg::Vst::BusDirection dir, int32 index, TBool state) @@ -147,16 +145,9 @@ namespace Clap */ } - inline clap_beattime doubleToBeatTime(double t) - { - return std::round(t * CLAP_BEATTIME_FACTOR); - } - - inline clap_sectime doubleToSecTime(double t) - { - return round(t * CLAP_SECTIME_FACTOR); - } + inline clap_beattime doubleToBeatTime(double t) { return std::round(t * CLAP_BEATTIME_FACTOR); } + inline clap_sectime doubleToSecTime(double t) { return round(t * CLAP_SECTIME_FACTOR); } void ProcessAdapter::flush() { @@ -172,51 +163,49 @@ namespace Clap } // this converts the ProcessContext data from VST to CLAP - void ProcessAdapter::process(Steinberg::Vst::ProcessData& data) + void ProcessAdapter::process(Steinberg::Vst::ProcessData &data) { // remember the ProcessData pointer during process _vstdata = &data; /// convert timing - _transport.header = { - sizeof(_transport), - 0, - CLAP_CORE_EVENT_SPACE_ID, - CLAP_EVENT_TRANSPORT, - 0 - }; + _transport.header = {sizeof(_transport), 0, CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_TRANSPORT, 0}; _transport.flags = 0; if (_vstdata->processContext) { // converting the flags - _transport.flags |= 0 - // kPlaying = 1 << 1, ///< currently playing - | ((_vstdata->processContext->state & Vst::ProcessContext::kPlaying) ? CLAP_TRANSPORT_IS_PLAYING : 0) - // kRecording = 1 << 3, ///< currently recording - | ((_vstdata->processContext->state & Vst::ProcessContext::kRecording) ? CLAP_TRANSPORT_IS_RECORDING : 0) - // kCycleActive = 1 << 2, ///< cycle is active - | ((_vstdata->processContext->state & Vst::ProcessContext::kCycleActive) ? CLAP_TRANSPORT_IS_LOOP_ACTIVE : 0) - // kTempoValid = 1 << 10, ///< tempo contains valid information - | ((_vstdata->processContext->state & Vst::ProcessContext::kTempoValid) ? CLAP_TRANSPORT_HAS_TEMPO : 0) - | ((_vstdata->processContext->state & Vst::ProcessContext::kBarPositionValid) ? CLAP_TRANSPORT_HAS_BEATS_TIMELINE : 0) - | ((_vstdata->processContext->state & Vst::ProcessContext::kTimeSigValid) ? CLAP_TRANSPORT_HAS_TIME_SIGNATURE : 0) - - // the rest of the flags has no meaning to CLAP - // kSystemTimeValid = 1 << 8, ///< systemTime contains valid information - // kContTimeValid = 1 << 17, ///< continousTimeSamples contains valid information - // - // kProjectTimeMusicValid = 1 << 9,///< projectTimeMusic contains valid information - // kBarPositionValid = 1 << 11, ///< barPositionMusic contains valid information - // kCycleValid = 1 << 12, ///< cycleStartMusic and barPositionMusic contain valid information - // - // kClockValid = 1 << 15 ///< samplesToNextClock valid - // kTimeSigValid = 1 << 13, ///< timeSigNumerator and timeSigDenominator contain valid information - // kChordValid = 1 << 18, ///< chord contains valid information - // - // kSmpteValid = 1 << 14, ///< smpteOffset and frameRate contain valid information - - ; + _transport.flags |= + 0 + // kPlaying = 1 << 1, ///< currently playing + | ((_vstdata->processContext->state & Vst::ProcessContext::kPlaying) ? CLAP_TRANSPORT_IS_PLAYING : 0) + // kRecording = 1 << 3, ///< currently recording + | ((_vstdata->processContext->state & Vst::ProcessContext::kRecording) ? CLAP_TRANSPORT_IS_RECORDING : 0) + // kCycleActive = 1 << 2, ///< cycle is active + | ((_vstdata->processContext->state & Vst::ProcessContext::kCycleActive) ? CLAP_TRANSPORT_IS_LOOP_ACTIVE : 0) + // kTempoValid = 1 << 10, ///< tempo contains valid information + | ((_vstdata->processContext->state & Vst::ProcessContext::kTempoValid) ? CLAP_TRANSPORT_HAS_TEMPO : 0) | + ((_vstdata->processContext->state & Vst::ProcessContext::kBarPositionValid) + ? CLAP_TRANSPORT_HAS_BEATS_TIMELINE + : 0) | + ((_vstdata->processContext->state & Vst::ProcessContext::kTimeSigValid) ? CLAP_TRANSPORT_HAS_TIME_SIGNATURE + : 0) + + // the rest of the flags has no meaning to CLAP + // kSystemTimeValid = 1 << 8, ///< systemTime contains valid information + // kContTimeValid = 1 << 17, ///< continousTimeSamples contains valid information + // + // kProjectTimeMusicValid = 1 << 9,///< projectTimeMusic contains valid information + // kBarPositionValid = 1 << 11, ///< barPositionMusic contains valid information + // kCycleValid = 1 << 12, ///< cycleStartMusic and barPositionMusic contain valid information + // + // kClockValid = 1 << 15 ///< samplesToNextClock valid + // kTimeSigValid = 1 << 13, ///< timeSigNumerator and timeSigDenominator contain valid information + // kChordValid = 1 << 18, ///< chord contains valid information + // + // kSmpteValid = 1 << 14, ///< smpteOffset and frameRate contain valid information + + ; _transport.song_pos_beats = doubleToBeatTime(_vstdata->processContext->projectTimeMusic); _transport.song_pos_seconds = 0; @@ -273,7 +262,7 @@ namespace Clap continue; } - auto param = (Vst3Parameter*)parameters->getParameter(paramid); + auto param = (Vst3Parameter *)parameters->getParameter(paramid); if (param) { if (param->isMidi) @@ -338,7 +327,7 @@ namespace Clap n.param.cookie = param->cookie; // nothing note specific - n.param.note_id = -1; // always global + n.param.note_id = -1; // always global n.param.port_index = -1; n.param.channel = -1; n.param.key = -1; @@ -349,7 +338,6 @@ namespace Clap } } } - } } @@ -357,7 +345,7 @@ namespace Clap bool doProcess = true; - if (_vstdata->numSamples > 0 ) + if (_vstdata->numSamples > 0) { // setting the buffers auto inbusses = _audioinputs->size(); @@ -404,23 +392,20 @@ namespace Clap _vstdata = nullptr; } - void ProcessAdapter::processOutputParams(Steinberg::Vst::ProcessData& data) - { - - } + void ProcessAdapter::processOutputParams(Steinberg::Vst::ProcessData &data) {} - uint32_t ProcessAdapter::input_events_size(const struct clap_input_events* list) + uint32_t ProcessAdapter::input_events_size(const struct clap_input_events *list) { - auto self = static_cast(list->ctx); + auto self = static_cast(list->ctx); return (uint32_t)self->_events.size(); // return self->_vstdata->inputEvents->getEventCount(); } // returns the pointer to an event in the list. The index accessed is not the position in the event list itself // since all events indices were sorted by timestamp - const clap_event_header_t* ProcessAdapter::input_events_get(const struct clap_input_events* list, uint32_t index) + const clap_event_header_t *ProcessAdapter::input_events_get(const struct clap_input_events *list, uint32_t index) { - auto self = static_cast(list->ctx); + auto self = static_cast(list->ctx); if (self->_events.size() > index) { // we can safely return the note.header also for other event types @@ -431,9 +416,9 @@ namespace Clap return nullptr; } - bool ProcessAdapter::output_events_try_push(const struct clap_output_events* list, const clap_event_header_t* event) + bool ProcessAdapter::output_events_try_push(const struct clap_output_events *list, const clap_event_header_t *event) { - auto self = static_cast(list->ctx); + auto self = static_cast(list->ctx); // mainly used for CLAP_EVENT_NOTE_CHOKE and CLAP_EVENT_NOTE_END // but also for parameter changes return self->enqueueOutputEvent(event); @@ -442,14 +427,11 @@ namespace Clap void ProcessAdapter::sortEventIndices() { // just sorting the index - std::sort(_eventindices.begin(), _eventindices.end(), [&](size_t const& a, size_t const& b) - { - return _events[a].header.time < _events[b].header.time; - } - ); + std::sort(_eventindices.begin(), _eventindices.end(), + [&](size_t const &a, size_t const &b) { return _events[a].header.time < _events[b].header.time; }); } - void ProcessAdapter::processInputEvents(Steinberg::Vst::IEventList* eventlist) + void ProcessAdapter::processInputEvents(Steinberg::Vst::IEventList *eventlist) { if (eventlist) { @@ -480,24 +462,24 @@ namespace Clap // convert but only if your target clap supports note expressions if (_supportsTuningNoteExpression && vstevent.noteOn.tuning != 0) { - clap_multi_event_t n; - n.noteexpression.header.type = CLAP_EVENT_NOTE_EXPRESSION; - n.noteexpression.header.flags = (vstevent.flags & Vst::Event::kIsLive) ? CLAP_EVENT_IS_LIVE : 0; - n.noteexpression.header.space_id = CLAP_CORE_EVENT_SPACE_ID; - n.noteexpression.header.time = vstevent.sampleOffset; - n.noteexpression.header.size = sizeof(clap_event_note_expression); - n.noteexpression.note_id = vstevent.noteExpressionValue.noteId; - n.noteexpression.port_index = 0; - n.noteexpression.key = vstevent.noteOn.pitch; - n.noteexpression.channel = vstevent.noteOn.channel; - n.noteexpression.note_id = vstevent.noteOn.noteId; - n.noteexpression.value = vstevent.noteExpressionValue.value; - - // VST3 Tuning is float in cents. We are in semitones. So - n.noteexpression.value = vstevent.noteOn.tuning * 0.01; - n.noteexpression.expression_id = CLAP_NOTE_EXPRESSION_TUNING; - _eventindices.push_back(_events.size()); - _events.push_back(n); + clap_multi_event_t n; + n.noteexpression.header.type = CLAP_EVENT_NOTE_EXPRESSION; + n.noteexpression.header.flags = (vstevent.flags & Vst::Event::kIsLive) ? CLAP_EVENT_IS_LIVE : 0; + n.noteexpression.header.space_id = CLAP_CORE_EVENT_SPACE_ID; + n.noteexpression.header.time = vstevent.sampleOffset; + n.noteexpression.header.size = sizeof(clap_event_note_expression); + n.noteexpression.note_id = vstevent.noteExpressionValue.noteId; + n.noteexpression.port_index = 0; + n.noteexpression.key = vstevent.noteOn.pitch; + n.noteexpression.channel = vstevent.noteOn.channel; + n.noteexpression.note_id = vstevent.noteOn.noteId; + n.noteexpression.value = vstevent.noteExpressionValue.value; + + // VST3 Tuning is float in cents. We are in semitones. So + n.noteexpression.value = vstevent.noteOn.tuning * 0.01; + n.noteexpression.expression_id = CLAP_NOTE_EXPRESSION_TUNING; + _eventindices.push_back(_events.size()); + _events.push_back(n); } } if (vstevent.type == Vst::Event::kNoteOffEvent) @@ -546,13 +528,13 @@ namespace Clap n.noteexpression.header.time = vstevent.sampleOffset; n.noteexpression.header.size = sizeof(clap_event_note_expression); n.noteexpression.note_id = vstevent.polyPressure.noteId; - for (auto& i : _activeNotes) + for (auto &i : _activeNotes) { if (i.used && i.note_id == vstevent.polyPressure.noteId) { n.noteexpression.expression_id = CLAP_NOTE_EXPRESSION_PRESSURE; n.noteexpression.port_index = i.port_index; - n.noteexpression.key = i.key; // should be the same as vstevent.polyPressure.pitch + n.noteexpression.key = i.key; // should be the same as vstevent.polyPressure.pitch n.noteexpression.channel = i.channel; n.noteexpression.value = vstevent.polyPressure.pressure; } @@ -569,7 +551,7 @@ namespace Clap n.noteexpression.header.time = vstevent.sampleOffset; n.noteexpression.header.size = sizeof(clap_event_note_expression); n.noteexpression.note_id = vstevent.noteExpressionValue.noteId; - for (auto& i : _activeNotes) + for (auto &i : _activeNotes) { if (i.used && i.note_id == vstevent.noteExpressionValue.noteId) { @@ -612,7 +594,7 @@ namespace Clap } } - bool ProcessAdapter::enqueueOutputEvent(const clap_event_header_t* event) + bool ProcessAdapter::enqueueOutputEvent(const clap_event_header_t *event) { switch (event->type) { @@ -650,14 +632,13 @@ namespace Clap oe.busIndex = 0; // FIXME - multi-out midi still needs work oe.sampleOffset = nevt->header.time; - if (_vstdata && _vstdata->outputEvents) _vstdata->outputEvents->addEvent(oe); } return true; case CLAP_EVENT_NOTE_END: case CLAP_EVENT_NOTE_CHOKE: - removeFromActiveNotes((const clap_event_note*)(event)); + removeFromActiveNotes((const clap_event_note *)(event)); return true; break; case CLAP_EVENT_NOTE_EXPRESSION: @@ -665,8 +646,8 @@ namespace Clap break; case CLAP_EVENT_PARAM_VALUE: { - auto ev = (clap_event_param_value*)event; - auto param = (Vst3Parameter*)this->parameters->getParameter(ev->param_id & 0x7FFFFFFF); + auto ev = (clap_event_param_value *)event; + auto param = (Vst3Parameter *)this->parameters->getParameter(ev->param_id & 0x7FFFFFFF); if (param) { auto param_id = param->getInfo().id; @@ -684,45 +665,44 @@ namespace Clap // actually, it should be called getParameterQueue() auto list = _vstdata->outputParameterChanges->addParameterData(param_id, index); - // the implementation of addParameterData() in the SDK always returns a queue, but Cubase 12 (perhaps others, too) - // sometimes don't return a queue object during the first bunch of process calls. I (df) haven't figured out, why. - // therefore we have to check if there is an output queue at all + // the implementation of addParameterData() in the SDK always returns a queue, but Cubase 12 (perhaps others, + // too) sometimes don't return a queue object during the first bunch of process calls. I (df) haven't figured + // out, why. therefore we have to check if there is an output queue at all if (list) { Steinberg::int32 index2 = 0; list->addPoint(ev->header.time, param->asVst3Value(ev->value), index2); } - } } - return true; - break; + return true; + break; case CLAP_EVENT_PARAM_MOD: return true; break; case CLAP_EVENT_PARAM_GESTURE_BEGIN: - { - auto ev = (clap_event_param_gesture*)event; - auto param = (Vst3Parameter*)this->parameters->getParameter(ev->param_id & 0x7FFFFFFF); - _gesturedParameters.push_back(param->getInfo().id); - _automation->onBeginEdit(param->getInfo().id); - } + { + auto ev = (clap_event_param_gesture *)event; + auto param = (Vst3Parameter *)this->parameters->getParameter(ev->param_id & 0x7FFFFFFF); + _gesturedParameters.push_back(param->getInfo().id); + _automation->onBeginEdit(param->getInfo().id); + } return true; break; case CLAP_EVENT_PARAM_GESTURE_END: - { - auto ev = (clap_event_param_gesture*)event; - auto param = (Vst3Parameter*)this->parameters->getParameter(ev->param_id & 0x7FFFFFFF); + { + auto ev = (clap_event_param_gesture *)event; + auto param = (Vst3Parameter *)this->parameters->getParameter(ev->param_id & 0x7FFFFFFF); - auto n = std::remove(_gesturedParameters.begin(), _gesturedParameters.end(), param->getInfo().id); - if (n != _gesturedParameters.end()) - { - _gesturedParameters.erase(n, _gesturedParameters.end()); - _automation->onEndEdit(param->getInfo().id); - } + auto n = std::remove(_gesturedParameters.begin(), _gesturedParameters.end(), param->getInfo().id); + if (n != _gesturedParameters.end()) + { + _gesturedParameters.erase(n, _gesturedParameters.end()); + _automation->onEndEdit(param->getInfo().id); } + } return true; break; @@ -737,9 +717,9 @@ namespace Clap return false; } - void ProcessAdapter::addToActiveNotes(const clap_event_note* note) + void ProcessAdapter::addToActiveNotes(const clap_event_note *note) { - for (auto& i : _activeNotes) + for (auto &i : _activeNotes) { if (!i.used) { @@ -751,22 +731,18 @@ namespace Clap return; } } - _activeNotes.push_back({true,note->note_id, note->port_index, note->channel, note->key}); + _activeNotes.push_back({true, note->note_id, note->port_index, note->channel, note->key}); } - void ProcessAdapter::removeFromActiveNotes(const clap_event_note * note) + void ProcessAdapter::removeFromActiveNotes(const clap_event_note *note) { - for (auto& i : _activeNotes) + for (auto &i : _activeNotes) { - if (i.used - && i.port_index == note->port_index - && i.channel == note->channel - && i.note_id == note->note_id) + if (i.used && i.port_index == note->port_index && i.channel == note->channel && i.note_id == note->note_id) { i.used = false; } } } - -} +} // namespace Clap diff --git a/src/detail/vst3/process.h b/src/detail/vst3/process.h index 41d4bd83..b0262a51 100644 --- a/src/detail/vst3/process.h +++ b/src/detail/vst3/process.h @@ -1,15 +1,15 @@ #pragma once /* - VST3 process adapter + VST3 process adapter - Copyright (c) 2022 Timo Kaluza (defiantnerd) + Copyright (c) 2022 Timo Kaluza (defiantnerd) - This file is part of the clap-wrappers project which is released under MIT License. - See file LICENSE or go to https://github.com/free-audio/clap-wrapper for full license details. + This file is part of the clap-wrappers project which is released under MIT License. + See file LICENSE or go to https://github.com/free-audio/clap-wrapper for full license details. - The process adapter is responible to translate events, timing information + The process adapter is responible to translate events, timing information */ #include @@ -35,18 +35,18 @@ namespace Clap { - class ProcessAdapter - { - public: - typedef union clap_multi_event - { - clap_event_header_t header; - clap_event_note_t note; - clap_event_midi_t midi; - clap_event_midi_sysex_t sysex; - clap_event_param_value_t param; - clap_event_note_expression_t noteexpression; - } clap_multi_event_t; + class ProcessAdapter + { + public: + typedef union clap_multi_event + { + clap_event_header_t header; + clap_event_note_t note; + clap_event_midi_t midi; + clap_event_midi_sysex_t sysex; + clap_event_param_value_t param; + clap_event_note_expression_t noteexpression; + } clap_multi_event_t; #if 0 // the bitly helpers. These names conflict with macOS params.h but are @@ -63,73 +63,72 @@ namespace Clap } #endif - void setupProcessing(const clap_plugin_t* plugin, const clap_plugin_params_t* ext_params, - Steinberg::Vst::BusList& numInputs, Steinberg::Vst::BusList& numOutputs, - uint32_t numSamples, size_t numEventInputs, size_t numEventOutputs, - Steinberg::Vst::ParameterContainer& params, Steinberg::Vst::IComponentHandler* componenthandler, - IAutomation* automation, bool enablePolyPressure, bool supportsTuningNoteExpression); - void process(Steinberg::Vst::ProcessData& data); - void flush(); - void processOutputParams(Steinberg::Vst::ProcessData& data); - void activateAudioBus(Steinberg::Vst::BusDirection dir, Steinberg::int32 index, Steinberg::TBool state); - - // C callbacks - static uint32_t input_events_size(const struct clap_input_events* list); - static const clap_event_header_t* input_events_get(const struct clap_input_events* list, uint32_t index); - - static bool output_events_try_push(const struct clap_output_events* list, const clap_event_header_t* event); - private: - void sortEventIndices(); - void processInputEvents(Steinberg::Vst::IEventList* eventlist); - - bool enqueueOutputEvent(const clap_event_header_t* event); - void addToActiveNotes(const clap_event_note* note); - void removeFromActiveNotes(const clap_event_note* note); - - // the plugin - const clap_plugin_t* _plugin = nullptr; - const clap_plugin_params_t* _ext_params = nullptr; - - Steinberg::Vst::ParameterContainer* parameters = nullptr; - Steinberg::Vst::IComponentHandler* _componentHandler = nullptr; - IAutomation* _automation = nullptr; - Steinberg::Vst::BusList* _audioinputs = nullptr; - Steinberg::Vst::BusList* _audiooutputs = nullptr; - - // for automation gestures - std::vector _gesturedParameters; - - // for INoteExpression - struct ActiveNote - { - bool used = false; - int32_t note_id; // -1 if unspecified, otherwise >=0 - int16_t port_index; - int16_t channel; // 0..15 - int16_t key; // 0..127 - }; - std::vector _activeNotes; - - clap_audio_buffer_t* _input_ports = nullptr; - clap_audio_buffer_t* _output_ports = nullptr; - clap_event_transport_t _transport = {}; - clap_input_events_t _in_events = {}; - clap_output_events_t _out_events = {}; - - float* _silent_input = nullptr; - float* _silent_output = nullptr; - - clap_process_t _processData = { -1, 0, &_transport, nullptr, nullptr, 0, 0, &_in_events, &_out_events }; - - - Steinberg::Vst::ProcessData* _vstdata = nullptr; - - std::vector _events; - std::vector _eventindices; - - bool _supportsPolyPressure = false; - bool _supportsTuningNoteExpression = false; - - }; - -} \ No newline at end of file + void setupProcessing(const clap_plugin_t *plugin, const clap_plugin_params_t *ext_params, + Steinberg::Vst::BusList &numInputs, Steinberg::Vst::BusList &numOutputs, uint32_t numSamples, + size_t numEventInputs, size_t numEventOutputs, Steinberg::Vst::ParameterContainer ¶ms, + Steinberg::Vst::IComponentHandler *componenthandler, IAutomation *automation, + bool enablePolyPressure, bool supportsTuningNoteExpression); + void process(Steinberg::Vst::ProcessData &data); + void flush(); + void processOutputParams(Steinberg::Vst::ProcessData &data); + void activateAudioBus(Steinberg::Vst::BusDirection dir, Steinberg::int32 index, Steinberg::TBool state); + + // C callbacks + static uint32_t input_events_size(const struct clap_input_events *list); + static const clap_event_header_t *input_events_get(const struct clap_input_events *list, uint32_t index); + + static bool output_events_try_push(const struct clap_output_events *list, const clap_event_header_t *event); + + private: + void sortEventIndices(); + void processInputEvents(Steinberg::Vst::IEventList *eventlist); + + bool enqueueOutputEvent(const clap_event_header_t *event); + void addToActiveNotes(const clap_event_note *note); + void removeFromActiveNotes(const clap_event_note *note); + + // the plugin + const clap_plugin_t *_plugin = nullptr; + const clap_plugin_params_t *_ext_params = nullptr; + + Steinberg::Vst::ParameterContainer *parameters = nullptr; + Steinberg::Vst::IComponentHandler *_componentHandler = nullptr; + IAutomation *_automation = nullptr; + Steinberg::Vst::BusList *_audioinputs = nullptr; + Steinberg::Vst::BusList *_audiooutputs = nullptr; + + // for automation gestures + std::vector _gesturedParameters; + + // for INoteExpression + struct ActiveNote + { + bool used = false; + int32_t note_id; // -1 if unspecified, otherwise >=0 + int16_t port_index; + int16_t channel; // 0..15 + int16_t key; // 0..127 + }; + std::vector _activeNotes; + + clap_audio_buffer_t *_input_ports = nullptr; + clap_audio_buffer_t *_output_ports = nullptr; + clap_event_transport_t _transport = {}; + clap_input_events_t _in_events = {}; + clap_output_events_t _out_events = {}; + + float *_silent_input = nullptr; + float *_silent_output = nullptr; + + clap_process_t _processData = {-1, 0, &_transport, nullptr, nullptr, 0, 0, &_in_events, &_out_events}; + + Steinberg::Vst::ProcessData *_vstdata = nullptr; + + std::vector _events; + std::vector _eventindices; + + bool _supportsPolyPressure = false; + bool _supportsTuningNoteExpression = false; + }; + +} // namespace Clap \ No newline at end of file diff --git a/src/detail/vst3/state.h b/src/detail/vst3/state.h index 4bb18f3c..161d4651 100644 --- a/src/detail/vst3/state.h +++ b/src/detail/vst3/state.h @@ -12,31 +12,29 @@ class CLAPVST3StreamAdapter { public: - CLAPVST3StreamAdapter(Steinberg::IBStream* stream) - : vst_stream(stream) - { - } - operator const clap_istream_t* () const { return ∈ } - operator const clap_ostream_t* () const { return &out; } + CLAPVST3StreamAdapter(Steinberg::IBStream *stream) : vst_stream(stream) {} + operator const clap_istream_t *() const { return ∈ } + operator const clap_ostream_t *() const { return &out; } - static int64_t read(const struct clap_istream* stream, void* buffer, uint64_t size) + static int64_t read(const struct clap_istream *stream, void *buffer, uint64_t size) { - auto self = static_cast(stream->ctx); + auto self = static_cast(stream->ctx); Steinberg::int32 bytesRead = 0; if (kResultOk == self->vst_stream->read(buffer, (int32)size, &bytesRead)) return bytesRead; return -1; } - static int64_t write(const struct clap_ostream* stream, const void* buffer, uint64_t size) + static int64_t write(const struct clap_ostream *stream, const void *buffer, uint64_t size) { - auto self = static_cast(stream->ctx); + auto self = static_cast(stream->ctx); Steinberg::int32 bytesWritten = 0; - if (kResultOk == self->vst_stream->write(const_cast(buffer), (int32)size, &bytesWritten)) + if (kResultOk == self->vst_stream->write(const_cast(buffer), (int32)size, &bytesWritten)) return bytesWritten; return -1; } + private: - Steinberg::IBStream* vst_stream = nullptr; - clap_istream_t in = { this, read }; - clap_ostream_t out = { this, write }; + Steinberg::IBStream *vst_stream = nullptr; + clap_istream_t in = {this, read}; + clap_ostream_t out = {this, write}; }; diff --git a/src/wrapasvst3.cpp b/src/wrapasvst3.cpp index 8c9b0ed3..64e8fb65 100644 --- a/src/wrapasvst3.cpp +++ b/src/wrapasvst3.cpp @@ -13,27 +13,23 @@ #if WIN #include -#define S16(x) reinterpret_cast(_T(x)) +#define S16(x) reinterpret_cast(_T(x)) #endif #if MAC -#define S16(x) u ## x +#define S16(x) u##x #endif #if LIN -#define S16(x) u ## x +#define S16(x) u##x #endif struct ClapHostExtensions { - static inline ClapAsVst3* self(const clap_host_t* host) - { - return static_cast(host->host_data); - } - static void mark_dirty(const clap_host_t* host) { self(host)->mark_dirty(); } - const clap_host_state_t _state = { mark_dirty }; + static inline ClapAsVst3 *self(const clap_host_t *host) { return static_cast(host->host_data); } + static void mark_dirty(const clap_host_t *host) { self(host)->mark_dirty(); } + const clap_host_state_t _state = {mark_dirty}; }; - -tresult PLUGIN_API ClapAsVst3::initialize(FUnknown* context) +tresult PLUGIN_API ClapAsVst3::initialize(FUnknown *context) { auto result = super::initialize(context); if (result == kResultOk) @@ -43,14 +39,13 @@ tresult PLUGIN_API ClapAsVst3::initialize(FUnknown* context) _plugin = Clap::Plugin::createInstance(*_library, _libraryIndex, this); } result = (_plugin->initialize()) ? kResultOk : kResultFalse; - if ( result ) + if (result) { _useIMidiMapping = checkMIDIDialectSupport(); } } if (_plugin) { - } return result; } @@ -75,19 +70,17 @@ tresult PLUGIN_API ClapAsVst3::setActive(TBool state) return kResultFalse; _active = true; _processAdapter = new Clap::ProcessAdapter(); - + auto supportsnoteexpression = (_expressionmap & clap_supported_note_expressions::AS_VST3_NOTE_EXPRESSION_PRESSURE); // the processAdapter needs to know a few things to intercommunicate between VST3 host and CLAP plugin. - _processAdapter->setupProcessing(_plugin->_plugin, _plugin->_ext._params, - this->audioInputs, this->audioOutputs, - this->_largestBlocksize, - this->eventInputs.size(), this->eventOutputs.size(), - parameters, componentHandler, this, - supportsnoteexpression, _expressionmap & clap_supported_note_expressions::AS_VST3_NOTE_EXPRESSION_TUNING); + _processAdapter->setupProcessing(_plugin->_plugin, _plugin->_ext._params, this->audioInputs, this->audioOutputs, + this->_largestBlocksize, this->eventInputs.size(), this->eventOutputs.size(), + parameters, componentHandler, this, supportsnoteexpression, + _expressionmap & clap_supported_note_expressions::AS_VST3_NOTE_EXPRESSION_TUNING); updateAudioBusses(); - + os::attach(this); } if (!state) @@ -104,7 +97,7 @@ tresult PLUGIN_API ClapAsVst3::setActive(TBool state) return super::setActive(state); } -tresult PLUGIN_API ClapAsVst3::process(Vst::ProcessData& data) +tresult PLUGIN_API ClapAsVst3::process(Vst::ProcessData &data) { auto thisFn = _plugin->AlwaysAudioThread(); this->_processAdapter->process(data); @@ -120,12 +113,12 @@ tresult PLUGIN_API ClapAsVst3::canProcessSampleSize(int32 symbolicSampleSize) return kResultOk; } -tresult PLUGIN_API ClapAsVst3::setState(IBStream* state) +tresult PLUGIN_API ClapAsVst3::setState(IBStream *state) { return (_plugin->load(CLAPVST3StreamAdapter(state)) ? Steinberg::kResultOk : Steinberg::kResultFalse); } -tresult PLUGIN_API ClapAsVst3::getState(IBStream* state) +tresult PLUGIN_API ClapAsVst3::getState(IBStream *state) { return (_plugin->save(CLAPVST3StreamAdapter(state)) ? Steinberg::kResultOk : Steinberg::kResultFalse); } @@ -141,7 +134,7 @@ uint32 PLUGIN_API ClapAsVst3::getLatencySamples() uint32 PLUGIN_API ClapAsVst3::getTailSamples() { - // options would be kNoTail, number of samples or kInfiniteTail + // options would be kNoTail, number of samples or kInfiniteTail if (this->_plugin->_ext._tail) { auto tailsize = this->_plugin->_ext._tail->get(_plugin->_plugin); @@ -154,7 +147,7 @@ uint32 PLUGIN_API ClapAsVst3::getTailSamples() return super::getTailSamples(); } -tresult PLUGIN_API ClapAsVst3::setupProcessing(Vst::ProcessSetup& newSetup) +tresult PLUGIN_API ClapAsVst3::setupProcessing(Vst::ProcessSetup &newSetup) { if (newSetup.symbolicSampleSize != Vst::kSample32) { @@ -192,19 +185,18 @@ tresult PLUGIN_API ClapAsVst3::setProcessing(TBool state) return result; } -tresult PLUGIN_API ClapAsVst3::setBusArrangements(Vst::SpeakerArrangement* inputs, int32 numIns, - Vst::SpeakerArrangement* outputs, - int32 numOuts) +tresult PLUGIN_API ClapAsVst3::setBusArrangements(Vst::SpeakerArrangement *inputs, int32 numIns, + Vst::SpeakerArrangement *outputs, int32 numOuts) { return super::setBusArrangements(inputs, numIns, outputs, numOuts); }; -tresult PLUGIN_API ClapAsVst3::getBusArrangement(Vst::BusDirection dir, int32 index, Vst::SpeakerArrangement& arr) +tresult PLUGIN_API ClapAsVst3::getBusArrangement(Vst::BusDirection dir, int32 index, Vst::SpeakerArrangement &arr) { return super::getBusArrangement(dir, index, arr); } -IPlugView* PLUGIN_API ClapAsVst3::createView(FIDString name) +IPlugView *PLUGIN_API ClapAsVst3::createView(FIDString name) { if (_plugin->_ext._gui) { @@ -234,9 +226,10 @@ IPlugView* PLUGIN_API ClapAsVst3::createView(FIDString name) return nullptr; } -tresult PLUGIN_API ClapAsVst3::getParamStringByValue(Vst::ParamID id, Vst::ParamValue valueNormalized, Vst::String128 string) +tresult PLUGIN_API ClapAsVst3::getParamStringByValue(Vst::ParamID id, Vst::ParamValue valueNormalized, + Vst::String128 string) { - auto param = (Vst3Parameter*)this->getParameterObject(id); + auto param = (Vst3Parameter *)this->getParameterObject(id); auto val = param->asClapValue(valueNormalized); char outbuf[128]; @@ -244,16 +237,17 @@ tresult PLUGIN_API ClapAsVst3::getParamStringByValue(Vst::ParamID id, Vst::Param if (this->_plugin->_ext._params->value_to_text(_plugin->_plugin, param->id, val, outbuf, 127)) { UString wrapper(&string[0], str16BufferSize(Steinberg::Vst::String128)); - - wrapper.assign(outbuf,sizeof(outbuf)); + + wrapper.assign(outbuf, sizeof(outbuf)); return kResultOk; } return super::getParamStringByValue(id, valueNormalized, string); } -tresult PLUGIN_API ClapAsVst3::getParamValueByString(Vst::ParamID id, Vst::TChar* string, Vst::ParamValue& valueNormalized) +tresult PLUGIN_API ClapAsVst3::getParamValueByString(Vst::ParamID id, Vst::TChar *string, + Vst::ParamValue &valueNormalized) { - auto param = (Vst3Parameter*)this->getParameterObject(id); + auto param = (Vst3Parameter *)this->getParameterObject(id); Steinberg::String m(string); char inbuf[128]; m.copyTo8(inbuf, 0, 128); @@ -264,7 +258,6 @@ tresult PLUGIN_API ClapAsVst3::getParamValueByString(Vst::ParamID id, Vst::TChar return kResultOk; } return Steinberg::kResultFalse; - } tresult PLUGIN_API ClapAsVst3::activateBus(Vst::MediaType type, Vst::BusDirection dir, int32 index, TBool state) @@ -275,10 +268,11 @@ tresult PLUGIN_API ClapAsVst3::activateBus(Vst::MediaType type, Vst::BusDirectio //----------------------------------------------------------------------------- tresult PLUGIN_API ClapAsVst3::getMidiControllerAssignment(int32 busIndex, int16 channel, - Vst::CtrlNumber midiControllerNumber, Vst::ParamID& id/*out*/) + Vst::CtrlNumber midiControllerNumber, + Vst::ParamID &id /*out*/) { // for my first Event bus and for MIDI channel 0 and for MIDI CC Volume only - if (busIndex == 0 ) // && channel == 0) // && midiControllerNumber == Vst::kCtrlVolume) + if (busIndex == 0) // && channel == 0) // && midiControllerNumber == Vst::kCtrlVolume) { id = _IMidiMappingIDs[channel][midiControllerNumber]; return kResultTrue; @@ -288,7 +282,7 @@ tresult PLUGIN_API ClapAsVst3::getMidiControllerAssignment(int32 busIndex, int16 #if 1 //----from INoteExpressionController------------------------- - /** Returns number of supported note change types for event bus index and channel. */ +/** Returns number of supported note change types for event bus index and channel. */ int32 ClapAsVst3::getNoteExpressionCount(int32 busIndex, int16 channel) { if (busIndex == 0 && channel == 0) @@ -296,11 +290,11 @@ int32 ClapAsVst3::getNoteExpressionCount(int32 busIndex, int16 channel) return _noteExpressions.getNoteExpressionCount(); } return 0; - } /** Returns note change type info. */ -tresult ClapAsVst3::getNoteExpressionInfo(int32 busIndex, int16 channel, int32 noteExpressionIndex, Vst::NoteExpressionTypeInfo& info /*out*/) +tresult ClapAsVst3::getNoteExpressionInfo(int32 busIndex, int16 channel, int32 noteExpressionIndex, + Vst::NoteExpressionTypeInfo &info /*out*/) { if (busIndex == 0 && channel == 0) { @@ -310,37 +304,39 @@ tresult ClapAsVst3::getNoteExpressionInfo(int32 busIndex, int16 channel, int32 n } /** Gets a user readable representation of the normalized note change value. */ -tresult ClapAsVst3::getNoteExpressionStringByValue(int32 busIndex, int16 channel, Vst::NoteExpressionTypeID id, Vst::NoteExpressionValue valueNormalized /*in*/, Vst::String128 string /*out*/) +tresult ClapAsVst3::getNoteExpressionStringByValue(int32 busIndex, int16 channel, Vst::NoteExpressionTypeID id, + Vst::NoteExpressionValue valueNormalized /*in*/, + Vst::String128 string /*out*/) { return _noteExpressions.getNoteExpressionStringByValue(id, valueNormalized, string); } /** Converts the user readable representation to the normalized note change value. */ -tresult ClapAsVst3::getNoteExpressionValueByString(int32 busIndex, int16 channel, Vst::NoteExpressionTypeID id, const Vst::TChar* string /*in*/, Vst::NoteExpressionValue& valueNormalized /*out*/) +tresult ClapAsVst3::getNoteExpressionValueByString(int32 busIndex, int16 channel, Vst::NoteExpressionTypeID id, + const Vst::TChar *string /*in*/, + Vst::NoteExpressionValue &valueNormalized /*out*/) { - return _noteExpressions.getNoteExpressionValueByString(id, string, valueNormalized); + return _noteExpressions.getNoteExpressionValueByString(id, string, valueNormalized); } #endif ////----------------------------------------------------------------------------- -//tresult PLUGIN_API ClapAsVst3::queryInterface(const TUID iid, void** obj) +// tresult PLUGIN_API ClapAsVst3::queryInterface(const TUID iid, void** obj) //{ // DEF_INTERFACE(IMidiMapping) // return SingleComponentEffect::queryInterface(iid, obj); -//} +// } -static Vst::SpeakerArrangement speakerArrFromPortType(const char* port_type) +static Vst::SpeakerArrangement speakerArrFromPortType(const char *port_type) { - static const std::pair arrangementmap[] = - { - {CLAP_PORT_MONO, Vst::SpeakerArr::kMono}, - {CLAP_PORT_STEREO, Vst::SpeakerArr::kStereo}, - // {CLAP_PORT_AMBISONIC, Vst::SpeakerArr::kAmbi1stOrderACN} <- we need also CLAP_EXT_AMBISONIC - // {CLAP_PORT_SURROUND, Vst::SpeakerArr::kStereoSurround}, // add when CLAP_EXT_SURROUND is not draft anymore - // TODO: add more PortTypes to Speaker Arrangement - {nullptr,Vst::SpeakerArr::kEmpty} - }; + static const std::pair arrangementmap[] = { + {CLAP_PORT_MONO, Vst::SpeakerArr::kMono}, + {CLAP_PORT_STEREO, Vst::SpeakerArr::kStereo}, + // {CLAP_PORT_AMBISONIC, Vst::SpeakerArr::kAmbi1stOrderACN} <- we need also CLAP_EXT_AMBISONIC + // {CLAP_PORT_SURROUND, Vst::SpeakerArr::kStereoSurround}, // add when CLAP_EXT_SURROUND is not draft anymore + // TODO: add more PortTypes to Speaker Arrangement + {nullptr, Vst::SpeakerArr::kEmpty}}; auto p = &arrangementmap[0]; while (p->first) @@ -355,7 +351,7 @@ static Vst::SpeakerArrangement speakerArrFromPortType(const char* port_type) return Vst::SpeakerArr::kEmpty; } -void ClapAsVst3::addAudioBusFrom(const clap_audio_port_info_t* info, bool is_input) +void ClapAsVst3::addAudioBusFrom(const clap_audio_port_info_t *info, bool is_input) { auto spk = speakerArrFromPortType(info->port_type); auto bustype = (info->flags & CLAP_AUDIO_PORT_IS_MAIN) ? Vst::BusTypes::kMain : Vst::BusTypes::kAux; @@ -370,11 +366,9 @@ void ClapAsVst3::addAudioBusFrom(const clap_audio_port_info_t* info, bool is_inp { addAudioOutput(name16, spk, bustype, Vst::BusInfo::kDefaultActive); } - - } -void ClapAsVst3::addMIDIBusFrom(const clap_note_port_info_t* info, uint32_t index, bool is_input) +void ClapAsVst3::addMIDIBusFrom(const clap_note_port_info_t *info, uint32_t index, bool is_input) { if ((info->supported_dialects & CLAP_NOTE_DIALECT_MIDI) || (info->supported_dialects & CLAP_NOTE_DIALECT_CLAP)) { @@ -399,18 +393,17 @@ void ClapAsVst3::addMIDIBusFrom(const clap_note_port_info_t* info, uint32_t inde void ClapAsVst3::updateAudioBusses() { - for ( auto i = 0U; i < audioInputs.size() ; ++i) + for (auto i = 0U; i < audioInputs.size(); ++i) { - _processAdapter->activateAudioBus(Vst::kInput, i,audioInputs[i]->isActive()); + _processAdapter->activateAudioBus(Vst::kInput, i, audioInputs[i]->isActive()); } for (auto i = 0U; i < audioOutputs.size(); ++i) { _processAdapter->activateAudioBus(Vst::kOutput, i, audioOutputs[i]->isActive()); } - } -static std::vector split(const std::string& s, char delimiter) +static std::vector split(const std::string &s, char delimiter) { std::vector tokens; std::string token; @@ -422,7 +415,7 @@ static std::vector split(const std::string& s, char delimiter) return tokens; } -Vst::UnitID ClapAsVst3::getOrCreateUnitInfo(const char* modulename) +Vst::UnitID ClapAsVst3::getOrCreateUnitInfo(const char *modulename) { // lookup the modulename fast and return the unitID auto loc = _moduleToUnit.find(modulename); @@ -439,9 +432,9 @@ Vst::UnitID ClapAsVst3::getOrCreateUnitInfo(const char* modulename) // the module name is not yet present as unit, so // we will ensure that it is being created one by one - auto path = split(modulename,'/'); + auto path = split(modulename, '/'); std::string curpath; - Vst::UnitID id = Vst::kRootUnitId; // there is already a root element + Vst::UnitID id = Vst::kRootUnitId; // there is already a root element size_t i = 0; while (path.size() > i) { @@ -464,7 +457,7 @@ Vst::UnitID ClapAsVst3::getOrCreateUnitInfo(const char* modulename) if (VST3::StringConvert::convert(u8name, name)) { Vst::UnitID newid = static_cast(units.size()); - Vst::Unit* newunit = new Vst::Unit(name, newid, id); // a new unit without a program list + Vst::Unit *newunit = new Vst::Unit(name, newid, id); // a new unit without a program list addUnit(newunit); _moduleToUnit[u8name] = newid; id = newid; @@ -477,9 +470,9 @@ Vst::UnitID ClapAsVst3::getOrCreateUnitInfo(const char* modulename) // Clap::IHost -void ClapAsVst3::setupWrapperSpecifics(const clap_plugin_t* plugin) +void ClapAsVst3::setupWrapperSpecifics(const clap_plugin_t *plugin) { - _vst3specifics = (clap_plugin_as_vst3_t*) plugin->get_extension(plugin, CLAP_PLUGIN_AS_VST3); + _vst3specifics = (clap_plugin_as_vst3_t *)plugin->get_extension(plugin, CLAP_PLUGIN_AS_VST3); if (_vst3specifics) { _numMidiChannels = _vst3specifics->getNumMIDIChannels(_plugin->_plugin, 0); @@ -491,28 +484,29 @@ bool ClapAsVst3::checkMIDIDialectSupport() { // check if the plugin supports noteports and if one of the note ports supports MIDI dialect auto noteports = _plugin->_ext._noteports; - if (noteports ) + if (noteports) { auto numMIDIInputs = noteports->count(_plugin->_plugin, true); - for (uint32_t i = 0 ; i < numMIDIInputs ; ++i ) + for (uint32_t i = 0; i < numMIDIInputs; ++i) { clap_note_port_info_t info; - if ( noteports->get(_plugin->_plugin,i,true,&info) ) + if (noteports->get(_plugin->_plugin, i, true, &info)) { - if ( info.supported_dialects & CLAP_NOTE_DIALECT_MIDI ) + if (info.supported_dialects & CLAP_NOTE_DIALECT_MIDI) { return true; } } } } - + return false; } -void ClapAsVst3::setupAudioBusses(const clap_plugin_t* plugin, const clap_plugin_audio_ports_t* audioports) +void ClapAsVst3::setupAudioBusses(const clap_plugin_t *plugin, const clap_plugin_audio_ports_t *audioports) { - if (!audioports) return; + if (!audioports) + return; auto numAudioInputs = audioports->count(plugin, true); auto numAudioOutputs = audioports->count(plugin, false); @@ -536,9 +530,10 @@ void ClapAsVst3::setupAudioBusses(const clap_plugin_t* plugin, const clap_plugin } } -void ClapAsVst3::setupMIDIBusses(const clap_plugin_t* plugin, const clap_plugin_note_ports_t* noteports) +void ClapAsVst3::setupMIDIBusses(const clap_plugin_t *plugin, const clap_plugin_note_ports_t *noteports) { - if (!noteports) return; + if (!noteports) + return; auto numMIDIInPorts = noteports->count(plugin, true); auto numMIDIOutPorts = noteports->count(plugin, false); @@ -568,9 +563,10 @@ void ClapAsVst3::setupMIDIBusses(const clap_plugin_t* plugin, const clap_plugin_ } } -void ClapAsVst3::setupParameters(const clap_plugin_t* plugin, const clap_plugin_params_t* params) +void ClapAsVst3::setupParameters(const clap_plugin_t *plugin, const clap_plugin_params_t *params) { - if (!params) return; + if (!params) + return; // clear the units, they will be rebuild during the parameter conversion _moduleToUnit.clear(); @@ -578,7 +574,8 @@ void ClapAsVst3::setupParameters(const clap_plugin_t* plugin, const clap_plugin_ { Vst::String128 rootname(STR16("root")); - Vst::Unit* newunit = new Vst::Unit(rootname, Vst::kNoParentUnitId, Vst::kRootUnitId); // a new unit without a program list + Vst::Unit *newunit = + new Vst::Unit(rootname, Vst::kNoParentUnitId, Vst::kRootUnitId); // a new unit without a program list addUnit(newunit); } @@ -590,21 +587,19 @@ void ClapAsVst3::setupParameters(const clap_plugin_t* plugin, const clap_plugin_ clap_param_info info; if (params->get_info(plugin, i, &info)) { - auto p = Vst3Parameter::create(&info, [&](const char* modstring) - { - return this->getOrCreateUnitInfo(modstring); - }); + auto p = + Vst3Parameter::create(&info, [&](const char *modstring) { return this->getOrCreateUnitInfo(modstring); }); // auto p = Vst3Parameter::create(&info,nullptr); parameters.addParameter(p); } } - if ( _useIMidiMapping ) + if (_useIMidiMapping) { // find free tags for IMidiMapping Vst::ParamID x = 0xb00000; _IMidiMappingEasy = true; - + for (uint8_t channel = 0; channel < _numMidiChannels; channel++) { for (int i = 0; i < Vst::ControllerNumbers::kCountCtrlNumber; ++i) @@ -624,41 +619,34 @@ void ClapAsVst3::setupParameters(const clap_plugin_t* plugin, const clap_plugin_ } // setting up noteexpression - + if (_expressionmap & clap_supported_note_expressions::AS_VST3_NOTE_EXPRESSION_VOLUME) - _noteExpressions.addNoteExpressionType( - new Vst::NoteExpressionType(Vst::NoteExpressionTypeIDs::kVolumeTypeID, S16("Volume"), S16("Vol"), S16(""), 0, nullptr, 0) - ); + _noteExpressions.addNoteExpressionType(new Vst::NoteExpressionType( + Vst::NoteExpressionTypeIDs::kVolumeTypeID, S16("Volume"), S16("Vol"), S16(""), 0, nullptr, 0)); if (_expressionmap & clap_supported_note_expressions::AS_VST3_NOTE_EXPRESSION_PAN) - _noteExpressions.addNoteExpressionType( - new Vst::NoteExpressionType(Vst::NoteExpressionTypeIDs::kPanTypeID, S16("Panorama"), S16("Pan"), S16(""), 0, nullptr, 0) - ); + _noteExpressions.addNoteExpressionType(new Vst::NoteExpressionType( + Vst::NoteExpressionTypeIDs::kPanTypeID, S16("Panorama"), S16("Pan"), S16(""), 0, nullptr, 0)); if (_expressionmap & clap_supported_note_expressions::AS_VST3_NOTE_EXPRESSION_TUNING) - _noteExpressions.addNoteExpressionType( - new Vst::NoteExpressionType(Vst::NoteExpressionTypeIDs::kTuningTypeID, S16("Tuning"), S16("Tun"), S16(""), 0, nullptr, 0) - ); + _noteExpressions.addNoteExpressionType(new Vst::NoteExpressionType( + Vst::NoteExpressionTypeIDs::kTuningTypeID, S16("Tuning"), S16("Tun"), S16(""), 0, nullptr, 0)); if (_expressionmap & clap_supported_note_expressions::AS_VST3_NOTE_EXPRESSION_VIBRATO) - _noteExpressions.addNoteExpressionType( - new Vst::NoteExpressionType(Vst::NoteExpressionTypeIDs::kVibratoTypeID, S16("Vibrato"), S16("Vibr"), S16(""), 0, nullptr, 0) - ); + _noteExpressions.addNoteExpressionType(new Vst::NoteExpressionType( + Vst::NoteExpressionTypeIDs::kVibratoTypeID, S16("Vibrato"), S16("Vibr"), S16(""), 0, nullptr, 0)); if (_expressionmap & clap_supported_note_expressions::AS_VST3_NOTE_EXPRESSION_EXPRESSION) - _noteExpressions.addNoteExpressionType( - new Vst::NoteExpressionType(Vst::NoteExpressionTypeIDs::kExpressionTypeID, S16("Expression"), S16("Expr"), S16(""), 0, nullptr, 0) - ); + _noteExpressions.addNoteExpressionType(new Vst::NoteExpressionType( + Vst::NoteExpressionTypeIDs::kExpressionTypeID, S16("Expression"), S16("Expr"), S16(""), 0, nullptr, 0)); if (_expressionmap & clap_supported_note_expressions::AS_VST3_NOTE_EXPRESSION_BRIGHTNESS) - _noteExpressions.addNoteExpressionType( - new Vst::NoteExpressionType(Vst::NoteExpressionTypeIDs::kBrightnessTypeID, S16("Brightness"), S16("Brit"), S16(""), 0, nullptr, 0) - ); + _noteExpressions.addNoteExpressionType(new Vst::NoteExpressionType( + Vst::NoteExpressionTypeIDs::kBrightnessTypeID, S16("Brightness"), S16("Brit"), S16(""), 0, nullptr, 0)); // PRESSURE is handled by IMidiMapping (-> Polypressure) } - void ClapAsVst3::param_rescan(clap_param_rescan_flags flags) { auto vstflags = 0u; @@ -669,7 +657,9 @@ void ClapAsVst3::param_rescan(clap_param_rescan_flags flags) } vstflags |= ((flags & CLAP_PARAM_RESCAN_VALUES) ? (uint32_t)Vst::RestartFlags::kParamValuesChanged : 0u); - vstflags |= ((flags & CLAP_PARAM_RESCAN_INFO) ? Vst::RestartFlags::kParamValuesChanged | Vst::RestartFlags::kParamTitlesChanged : 0u); + vstflags |= ((flags & CLAP_PARAM_RESCAN_INFO) + ? Vst::RestartFlags::kParamValuesChanged | Vst::RestartFlags::kParamTitlesChanged + : 0u); if (vstflags != 0) { // update parameter values in our own tree @@ -677,7 +667,7 @@ void ClapAsVst3::param_rescan(clap_param_rescan_flags flags) for (decltype(len) i = 0; i < len; ++i) { auto p = parameters.getParameterByIndex(i); - auto p1 = static_cast(p); + auto p1 = static_cast(p); if (!p1->isMidi) { double val; @@ -693,18 +683,12 @@ void ClapAsVst3::param_rescan(clap_param_rescan_flags flags) } this->componentHandler->restartComponent(vstflags); } - } -void ClapAsVst3::param_clear(clap_id param, clap_param_clear_flags flags) -{ -} +void ClapAsVst3::param_clear(clap_id param, clap_param_clear_flags flags) {} // request_flush requests a defered call to flush if there is no processing -void ClapAsVst3::param_request_flush() -{ - _requestedFlush = true; -} +void ClapAsVst3::param_request_flush() { _requestedFlush = true; } bool ClapAsVst3::gui_can_resize() { @@ -724,10 +708,7 @@ bool ClapAsVst3::gui_request_show() return false; } -bool ClapAsVst3::gui_request_hide() -{ - return false; -} +bool ClapAsVst3::gui_request_hide() { return false; } void ClapAsVst3::latency_changed() { @@ -747,35 +728,28 @@ void ClapAsVst3::mark_dirty() componentHandler2->setDirty(true); } -void ClapAsVst3::request_callback() -{ - _requestUICallback = true; -} +void ClapAsVst3::request_callback() { _requestUICallback = true; } void ClapAsVst3::restartPlugin() -{ - if (componentHandler) componentHandler->restartComponent(Vst::RestartFlags::kReloadComponent); +{ + if (componentHandler) + componentHandler->restartComponent(Vst::RestartFlags::kReloadComponent); } void ClapAsVst3::onBeginEdit(clap_id id) { // receive beginEdit and pass it to the internal queue _queueToUI.push(beginEvent(id)); - } -void ClapAsVst3::onPerformEdit(const clap_event_param_value_t* value) +void ClapAsVst3::onPerformEdit(const clap_event_param_value_t *value) { // receive a value change and pass it to the internal queue _queueToUI.push(valueEvent(value)); } -void ClapAsVst3::onEndEdit(clap_id id) -{ - _queueToUI.push(endEvent(id)); - -} +void ClapAsVst3::onEndEdit(clap_id id) { _queueToUI.push(endEvent(id)); } // ext-timer -bool ClapAsVst3::register_timer(uint32_t period_ms, clap_id* timer_id) +bool ClapAsVst3::register_timer(uint32_t period_ms, clap_id *timer_id) { // restrict the timer to 30ms if (period_ms < 30) @@ -786,7 +760,7 @@ bool ClapAsVst3::register_timer(uint32_t period_ms, clap_id* timer_id) auto l = _timersObjects.size(); for (decltype(l) i = 0; i < l; ++i) { - auto& to = _timersObjects[i]; + auto &to = _timersObjects[i]; if (to.period == 0) { // reuse timer object. Lets choose not to use 0 as a timer id, just @@ -804,8 +778,8 @@ bool ClapAsVst3::register_timer(uint32_t period_ms, clap_id* timer_id) } } // create a new timer object - auto newid = (clap_id)(l+1000); - TimerObject f{ period_ms, os::getTickInMS() + period_ms, newid }; + auto newid = (clap_id)(l + 1000); + TimerObject f{period_ms, os::getTickInMS() + period_ms, newid}; *timer_id = newid; _timersObjects.push_back(f); #if LIN @@ -816,7 +790,7 @@ bool ClapAsVst3::register_timer(uint32_t period_ms, clap_id* timer_id) } bool ClapAsVst3::unregister_timer(clap_id timer_id) { - for (auto& to : _timersObjects) + for (auto &to : _timersObjects) { if (to.timer_id == timer_id) { @@ -825,7 +799,7 @@ bool ClapAsVst3::unregister_timer(clap_id timer_id) #if LIN if (to.handler && _iRunLoop) { - _iRunLoop->unregisterTimer(to.handler.get()); + _iRunLoop->unregisterTimer(to.handler.get()); } to.handler.reset(); #endif @@ -847,12 +821,12 @@ void ClapAsVst3::onIdle() beginEdit(n._data._id); break; case queueEvent::type_t::editvalue: - { - auto param = (Vst3Parameter*)(parameters.getParameter(n._data._value.param_id & 0x7FFFFFFF)); - auto v = n._data._value.value; - performEdit(param->getInfo().id, param->asVst3Value(v)); - } - break; + { + auto param = (Vst3Parameter *)(parameters.getParameter(n._data._value.param_id & 0x7FFFFFFF)); + auto v = n._data._value.value; + performEdit(param->getInfo().id, param->asVst3Value(v)); + } + break; case queueEvent::type_t::editend: endEdit(n._data._id); break; @@ -868,7 +842,8 @@ void ClapAsVst3::onIdle() { // setup a ProcessAdapter just for flush with no audio Clap::ProcessAdapter pa; - pa.setupProcessing(_plugin->_plugin, _plugin->_ext._params, audioInputs, audioOutputs, 0, 0, 0, this->parameters, componentHandler, nullptr, false, false); + pa.setupProcessing(_plugin->_plugin, _plugin->_ext._params, audioInputs, audioOutputs, 0, 0, 0, this->parameters, + componentHandler, nullptr, false, false); pa.flush(); } } @@ -880,10 +855,10 @@ void ClapAsVst3::onIdle() } #if LIN - if (!_iRunLoop) // don't process timers if we have a runloop. - // (but if we don't have a runloop on linux onIdle isn't called - // anyway so consider just not having this at all once we decide - // to do with the no UI case) + if (!_iRunLoop) // don't process timers if we have a runloop. + // (but if we don't have a runloop on linux onIdle isn't called + // anyway so consider just not having this at all once we decide + // to do with the no UI case) #endif { // handling timerobjects @@ -892,11 +867,11 @@ void ClapAsVst3::onIdle() { if (to.period > 0) { - if (to.nexttick < now) - { + if (to.nexttick < now) + { to.nexttick = now + to.period; this->_plugin->_ext._timer->on_timer(_plugin->_plugin, to.timer_id); - } + } } } } @@ -907,10 +882,7 @@ struct TimerHandler : Steinberg::Linux::ITimerHandler, public Steinberg::FObject { ClapAsVst3 *_parent{nullptr}; clap_id _timerId{0}; - TimerHandler(ClapAsVst3 *parent, clap_id timerId) - : _parent(parent), _timerId(timerId) - { - } + TimerHandler(ClapAsVst3 *parent, clap_id timerId) : _parent(parent), _timerId(timerId) {} void PLUGIN_API onTimer() final { _parent->fireTimer(_timerId); } DELEGATE_REFCOUNT(Steinberg::FObject) DEFINE_INTERFACES @@ -976,10 +948,7 @@ void ClapAsVst3::detachTimers(Steinberg::Linux::IRunLoop *r) } } -void ClapAsVst3::fireTimer(clap_id timer_id) -{ - _plugin->_ext._timer->on_timer(_plugin->_plugin, timer_id); -} +void ClapAsVst3::fireTimer(clap_id timer_id) { _plugin->_ext._timer->on_timer(_plugin->_plugin, timer_id); } bool ClapAsVst3::register_fd(int fd, clap_posix_fd_flags_t flags) { @@ -1030,14 +999,8 @@ struct FDHandler : Steinberg::Linux::IEventHandler, public Steinberg::FObject ClapAsVst3 *_parent{nullptr}; int _fd{0}; clap_posix_fd_flags_t _flags{}; - FDHandler(ClapAsVst3 *parent, int fd, clap_posix_fd_flags_t flags) - : _parent(parent), _fd(fd), _flags(flags) - { - } - void PLUGIN_API onFDIsSet(Steinberg::Linux::FileDescriptor) override - { - _parent->firePosixFDIsSet(_fd, _flags); - } + FDHandler(ClapAsVst3 *parent, int fd, clap_posix_fd_flags_t flags) : _parent(parent), _fd(fd), _flags(flags) {} + void PLUGIN_API onFDIsSet(Steinberg::Linux::FileDescriptor) override { _parent->firePosixFDIsSet(_fd, _flags); } DELEGATE_REFCOUNT(Steinberg::FObject) DEFINE_INTERFACES DEF_INTERFACE(Steinberg::Linux::IEventHandler) diff --git a/src/wrapasvst3.h b/src/wrapasvst3.h index c36b539b..fc012597 100644 --- a/src/wrapasvst3.h +++ b/src/wrapasvst3.h @@ -1,15 +1,15 @@ #pragma once /* - CLAP as VST3 + CLAP as VST3 Copyright (c) 2022 Timo Kaluza (defiantnerd) - This file is part of the clap-wrappers project which is released under MIT License. - See file LICENSE or go to https://github.com/free-audio/clap-wrapper for full license details. + This file is part of the clap-wrappers project which is released under MIT License. + See file LICENSE or go to https://github.com/free-audio/clap-wrapper for full license details. - This VST3 opens a CLAP plugin and matches all corresponding VST3 calls to it. - For the VST3 Host it is a VST3 plugin, for the CLAP plugin it is a CLAP host. + This VST3 opens a CLAP plugin and matches all corresponding VST3 calls to it. + For the VST3 Host it is a VST3 plugin, for the CLAP plugin it is a CLAP host. */ @@ -39,279 +39,275 @@ using namespace Steinberg; struct ClapHostExtensions; namespace Clap { - class ProcessAdapter; + class ProcessAdapter; } class queueEvent { public: - typedef enum class type - { - editstart, - editvalue, - editend, - } type_t; - type_t _type; - union - { - clap_id _id; - clap_event_param_value_t _value; - } _data; + typedef enum class type + { + editstart, + editvalue, + editend, + } type_t; + type_t _type; + union + { + clap_id _id; + clap_event_param_value_t _value; + } _data; }; class beginEvent : public queueEvent { public: - beginEvent(clap_id id) - : queueEvent() - { - this->_type = type::editstart; - _data._id = id; - } + beginEvent(clap_id id) : queueEvent() + { + this->_type = type::editstart; + _data._id = id; + } }; class endEvent : public queueEvent { public: - endEvent(clap_id id) - : queueEvent() - { - this->_type = type::editend; - _data._id = id; - } + endEvent(clap_id id) : queueEvent() + { + this->_type = type::editend; + _data._id = id; + } }; class valueEvent : public queueEvent { public: - valueEvent(const clap_event_param_value_t* value) - : queueEvent() - { - _type = type::editvalue; - _data._value = *value; - } + valueEvent(const clap_event_param_value_t *value) : queueEvent() + { + _type = type::editvalue; + _data._value = *value; + } }; -class ClapAsVst3 : public Steinberg::Vst::SingleComponentEffect - , public Steinberg::Vst::IMidiMapping - , public Steinberg::Vst::INoteExpressionController - , public Clap::IHost - , public Clap::IAutomation - , public os::IPlugObject +class ClapAsVst3 : public Steinberg::Vst::SingleComponentEffect, + public Steinberg::Vst::IMidiMapping, + public Steinberg::Vst::INoteExpressionController, + public Clap::IHost, + public Clap::IAutomation, + public os::IPlugObject { public: + using super = Steinberg::Vst::SingleComponentEffect; - using super = Steinberg::Vst::SingleComponentEffect; - - static FUnknown* createInstance(void* context); - - ClapAsVst3(Clap::Library* lib, int number, void* context) - : super() - , Steinberg::Vst::IMidiMapping() - , Steinberg::Vst::INoteExpressionController() - , _library(lib) - , _libraryIndex(number) - , _creationcontext(context) {} - - //---from IComponent----------------------- - tresult PLUGIN_API initialize(FUnknown* context) override; - tresult PLUGIN_API terminate() override; - tresult PLUGIN_API setActive(TBool state) override; - tresult PLUGIN_API process(Vst::ProcessData& data) override; - tresult PLUGIN_API canProcessSampleSize(int32 symbolicSampleSize) override; - tresult PLUGIN_API setState(IBStream* state) override; - tresult PLUGIN_API getState(IBStream* state) override; - uint32 PLUGIN_API getLatencySamples() override; - uint32 PLUGIN_API getTailSamples() override; - tresult PLUGIN_API setupProcessing(Vst::ProcessSetup& newSetup) override; - tresult PLUGIN_API setProcessing(TBool state) override; - tresult PLUGIN_API setBusArrangements(Vst::SpeakerArrangement* inputs, int32 numIns, - Vst::SpeakerArrangement* outputs, - int32 numOuts) override; - tresult PLUGIN_API getBusArrangement(Vst::BusDirection dir, int32 index, Vst::SpeakerArrangement& arr) override; - tresult PLUGIN_API activateBus(Vst::MediaType type, Vst::BusDirection dir, int32 index, - TBool state) override; - - //----from IEditControllerEx1-------------------------------- - IPlugView* PLUGIN_API createView(FIDString name) override; - /** Gets for a given paramID and normalized value its associated string representation. */ - tresult PLUGIN_API getParamStringByValue(Vst::ParamID id, Vst::ParamValue valueNormalized /*in*/, Vst::String128 string /*out*/) override; - /** Gets for a given paramID and string its normalized value. */ - tresult PLUGIN_API getParamValueByString(Vst::ParamID id, Vst::TChar* string /*in*/, Vst::ParamValue& valueNormalized /*out*/) override; - - //----from IMidiMapping-------------------------------------- - tresult PLUGIN_API getMidiControllerAssignment(int32 busIndex, int16 channel, - Vst::CtrlNumber midiControllerNumber, Vst::ParamID& id/*out*/) override; - -#if 1 - //----from INoteExpressionController------------------------- - /** Returns number of supported note change types for event bus index and channel. */ - int32 PLUGIN_API getNoteExpressionCount(int32 busIndex, int16 channel) override; + static FUnknown *createInstance(void *context); - /** Returns note change type info. */ - tresult PLUGIN_API getNoteExpressionInfo(int32 busIndex, int16 channel, int32 noteExpressionIndex, Vst::NoteExpressionTypeInfo& info /*out*/) override; + ClapAsVst3(Clap::Library *lib, int number, void *context) + : super(), Steinberg::Vst::IMidiMapping(), Steinberg::Vst::INoteExpressionController(), _library(lib), + _libraryIndex(number), _creationcontext(context) + { + } - /** Gets a user readable representation of the normalized note change value. */ - tresult PLUGIN_API getNoteExpressionStringByValue(int32 busIndex, int16 channel, Vst::NoteExpressionTypeID id, Vst::NoteExpressionValue valueNormalized /*in*/, Vst::String128 string /*out*/) override; + //---from IComponent----------------------- + tresult PLUGIN_API initialize(FUnknown *context) override; + tresult PLUGIN_API terminate() override; + tresult PLUGIN_API setActive(TBool state) override; + tresult PLUGIN_API process(Vst::ProcessData &data) override; + tresult PLUGIN_API canProcessSampleSize(int32 symbolicSampleSize) override; + tresult PLUGIN_API setState(IBStream *state) override; + tresult PLUGIN_API getState(IBStream *state) override; + uint32 PLUGIN_API getLatencySamples() override; + uint32 PLUGIN_API getTailSamples() override; + tresult PLUGIN_API setupProcessing(Vst::ProcessSetup &newSetup) override; + tresult PLUGIN_API setProcessing(TBool state) override; + tresult PLUGIN_API setBusArrangements(Vst::SpeakerArrangement *inputs, int32 numIns, Vst::SpeakerArrangement *outputs, + int32 numOuts) override; + tresult PLUGIN_API getBusArrangement(Vst::BusDirection dir, int32 index, Vst::SpeakerArrangement &arr) override; + tresult PLUGIN_API activateBus(Vst::MediaType type, Vst::BusDirection dir, int32 index, TBool state) override; + + //----from IEditControllerEx1-------------------------------- + IPlugView *PLUGIN_API createView(FIDString name) override; + /** Gets for a given paramID and normalized value its associated string representation. */ + tresult PLUGIN_API getParamStringByValue(Vst::ParamID id, Vst::ParamValue valueNormalized /*in*/, + Vst::String128 string /*out*/) override; + /** Gets for a given paramID and string its normalized value. */ + tresult PLUGIN_API getParamValueByString(Vst::ParamID id, Vst::TChar *string /*in*/, + Vst::ParamValue &valueNormalized /*out*/) override; + + //----from IMidiMapping-------------------------------------- + tresult PLUGIN_API getMidiControllerAssignment(int32 busIndex, int16 channel, Vst::CtrlNumber midiControllerNumber, + Vst::ParamID &id /*out*/) override; - /** Converts the user readable representation to the normalized note change value. */ - tresult PLUGIN_API getNoteExpressionValueByString(int32 busIndex, int16 channel, Vst::NoteExpressionTypeID id, const Vst::TChar* string /*in*/, Vst::NoteExpressionValue& valueNormalized /*out*/ ) override; +#if 1 + //----from INoteExpressionController------------------------- + /** Returns number of supported note change types for event bus index and channel. */ + int32 PLUGIN_API getNoteExpressionCount(int32 busIndex, int16 channel) override; + + /** Returns note change type info. */ + tresult PLUGIN_API getNoteExpressionInfo(int32 busIndex, int16 channel, int32 noteExpressionIndex, + Vst::NoteExpressionTypeInfo &info /*out*/) override; + + /** Gets a user readable representation of the normalized note change value. */ + tresult PLUGIN_API getNoteExpressionStringByValue(int32 busIndex, int16 channel, Vst::NoteExpressionTypeID id, + Vst::NoteExpressionValue valueNormalized /*in*/, + Vst::String128 string /*out*/) override; + + /** Converts the user readable representation to the normalized note change value. */ + tresult PLUGIN_API getNoteExpressionValueByString(int32 busIndex, int16 channel, Vst::NoteExpressionTypeID id, + const Vst::TChar *string /*in*/, + Vst::NoteExpressionValue &valueNormalized /*out*/) override; #endif - //---Interface-------------------------------------------------------------------------- - OBJ_METHODS(ClapAsVst3, SingleComponentEffect) - DEFINE_INTERFACES + //---Interface-------------------------------------------------------------------------- + OBJ_METHODS(ClapAsVst3, SingleComponentEffect) + DEFINE_INTERFACES // since the macro above opens a local function, this code is being executed during QueryInterface() :) - if (::Steinberg::FUnknownPrivate::iidEqual (iid, IMidiMapping::iid)) + if (::Steinberg::FUnknownPrivate::iidEqual(iid, IMidiMapping::iid)) { - // when queried for the IMididMapping interface, check if the CLAP supports MIDI dialect on the MIDI Input busses and only return IMidiMapping then - if ( _useIMidiMapping ) { + // when queried for the IMididMapping interface, check if the CLAP supports MIDI dialect on the MIDI Input busses + // and only return IMidiMapping then + if (_useIMidiMapping) + { DEF_INTERFACE(IMidiMapping) } } - DEF_INTERFACE(INoteExpressionController) - // tresult PLUGIN_API queryInterface(const TUID iid, void** obj) override; - END_DEFINE_INTERFACES(SingleComponentEffect) - REFCOUNT_METHODS(SingleComponentEffect); - + DEF_INTERFACE(INoteExpressionController) + // tresult PLUGIN_API queryInterface(const TUID iid, void** obj) override; + END_DEFINE_INTERFACES(SingleComponentEffect) + REFCOUNT_METHODS(SingleComponentEffect); + //---Clap::IHost------------------------------------------------------------------------ - //---Clap::IHost------------------------------------------------------------------------ + void setupWrapperSpecifics(const clap_plugin_t *plugin) override; - void setupWrapperSpecifics(const clap_plugin_t* plugin) override; + void setupAudioBusses(const clap_plugin_t *plugin, const clap_plugin_audio_ports_t *audioports) override; + void setupMIDIBusses(const clap_plugin_t *plugin, const clap_plugin_note_ports_t *noteports) override; + void setupParameters(const clap_plugin_t *plugin, const clap_plugin_params_t *params) override; - void setupAudioBusses(const clap_plugin_t* plugin, const clap_plugin_audio_ports_t* audioports) override; - void setupMIDIBusses(const clap_plugin_t* plugin, const clap_plugin_note_ports_t* noteports) override; - void setupParameters(const clap_plugin_t* plugin, const clap_plugin_params_t* params) override; + void param_rescan(clap_param_rescan_flags flags) override; + void param_clear(clap_id param, clap_param_clear_flags flags) override; + void param_request_flush() override; - void param_rescan(clap_param_rescan_flags flags) override; - void param_clear(clap_id param, clap_param_clear_flags flags) override; - void param_request_flush() override; + bool gui_can_resize() override; + bool gui_request_resize(uint32_t width, uint32_t height) override; + bool gui_request_show() override; + bool gui_request_hide() override; - bool gui_can_resize() override; - bool gui_request_resize(uint32_t width, uint32_t height) override; - bool gui_request_show() override; - bool gui_request_hide() override; + void latency_changed() override; - void latency_changed() override; + void tail_changed() override; - void tail_changed() override; + void mark_dirty() override; - void mark_dirty() override; + void restartPlugin() override; - void restartPlugin() override; - - void request_callback() override; - - // clap_timer support - bool register_timer(uint32_t period_ms, clap_id* timer_id) override; - bool unregister_timer(clap_id timer_id) override; + void request_callback() override; + // clap_timer support + bool register_timer(uint32_t period_ms, clap_id *timer_id) override; + bool unregister_timer(clap_id timer_id) override; #if LIN - bool register_fd(int fd, clap_posix_fd_flags_t flags) override; - bool modify_fd(int fd, clap_posix_fd_flags_t flags) override; - bool unregister_fd(int fd) override; + bool register_fd(int fd, clap_posix_fd_flags_t flags) override; + bool modify_fd(int fd, clap_posix_fd_flags_t flags) override; + bool unregister_fd(int fd) override; #endif - public: - //----from IPlugObject - void onIdle() override; -private: + //----from IPlugObject + void onIdle() override; - // from Clap::IAutomation - void onBeginEdit(clap_id id) override; - void onPerformEdit(const clap_event_param_value_t* value) override; - void onEndEdit(clap_id id) override; +private: + // from Clap::IAutomation + void onBeginEdit(clap_id id) override; + void onPerformEdit(const clap_event_param_value_t *value) override; + void onEndEdit(clap_id id) override; // information function to enable/disable the IMIDIMapping interface bool checkMIDIDialectSupport(); + private: - // helper functions - void addAudioBusFrom(const clap_audio_port_info_t* info, bool is_input); - void addMIDIBusFrom(const clap_note_port_info_t* info, uint32_t index, bool is_input); - void updateAudioBusses(); - - Vst::UnitID getOrCreateUnitInfo(const char* modulename); - std::map _moduleToUnit; - - Clap::Library* _library = nullptr; - int _libraryIndex = 0; - std::shared_ptr _plugin; - ClapHostExtensions* _hostextensions = nullptr; - clap_plugin_as_vst3_t* _vst3specifics = nullptr; - Clap::ProcessAdapter* _processAdapter = nullptr; - WrappedView* _wrappedview = nullptr; - - void* _creationcontext; // context from the CLAP library - - // plugin state - bool _active = false; - bool _processing = false; - std::mutex _processingLock; - std::atomic_bool _requestedFlush = false; - std::atomic_bool _requestUICallback = false; - - // the queue from audiothread to UI thread - util::fixedqueue _queueToUI; - - // for IMidiMapping + // helper functions + void addAudioBusFrom(const clap_audio_port_info_t *info, bool is_input); + void addMIDIBusFrom(const clap_note_port_info_t *info, uint32_t index, bool is_input); + void updateAudioBusses(); + + Vst::UnitID getOrCreateUnitInfo(const char *modulename); + std::map _moduleToUnit; + + Clap::Library *_library = nullptr; + int _libraryIndex = 0; + std::shared_ptr _plugin; + ClapHostExtensions *_hostextensions = nullptr; + clap_plugin_as_vst3_t *_vst3specifics = nullptr; + Clap::ProcessAdapter *_processAdapter = nullptr; + WrappedView *_wrappedview = nullptr; + + void *_creationcontext; // context from the CLAP library + + // plugin state + bool _active = false; + bool _processing = false; + std::mutex _processingLock; + std::atomic_bool _requestedFlush = false; + std::atomic_bool _requestUICallback = false; + + // the queue from audiothread to UI thread + util::fixedqueue _queueToUI; + + // for IMidiMapping bool _useIMidiMapping = false; - Vst::ParamID _IMidiMappingIDs[16][Vst::ControllerNumbers::kCountCtrlNumber] = {}; // 16 MappingIDs for 16 Channels - bool _IMidiMappingEasy = true; - uint8_t _numMidiChannels = 16; - uint32_t _largestBlocksize = 0; - - // for timer - struct TimerObject - { - uint32_t period = 0; // if period is 0 the entry is unused (and can be reused) - uint64_t nexttick = 0; - clap_id timer_id = 0; + Vst::ParamID _IMidiMappingIDs[16][Vst::ControllerNumbers::kCountCtrlNumber] = {}; // 16 MappingIDs for 16 Channels + bool _IMidiMappingEasy = true; + uint8_t _numMidiChannels = 16; + uint32_t _largestBlocksize = 0; + + // for timer + struct TimerObject + { + uint32_t period = 0; // if period is 0 the entry is unused (and can be reused) + uint64_t nexttick = 0; + clap_id timer_id = 0; #if LIN - Steinberg::IPtr handler = nullptr; + Steinberg::IPtr handler = nullptr; #endif - }; - std::vector _timersObjects; + }; + std::vector _timersObjects; #if LIN - Steinberg::IPtr _idleHandler; + Steinberg::IPtr _idleHandler; - void attachTimers(Steinberg::Linux::IRunLoop *); - void detachTimers(Steinberg::Linux::IRunLoop *); - Steinberg::Linux::IRunLoop *_iRunLoop{nullptr}; + void attachTimers(Steinberg::Linux::IRunLoop *); + void detachTimers(Steinberg::Linux::IRunLoop *); + Steinberg::Linux::IRunLoop *_iRunLoop{nullptr}; #endif - #if LIN - // for timer - struct PosixFDObject - { - PosixFDObject(int f, clap_posix_fd_flags_t fl) : fd(f), flags(fl) {} - int fd = 0; - clap_posix_fd_flags_t flags = 0; - Steinberg::IPtr handler = nullptr; - }; - std::vector _posixFDObjects; - - void attachPosixFD(Steinberg::Linux::IRunLoop *); - void detachPosixFD(Steinberg::Linux::IRunLoop *); + // for timer + struct PosixFDObject + { + PosixFDObject(int f, clap_posix_fd_flags_t fl) : fd(f), flags(fl) {} + int fd = 0; + clap_posix_fd_flags_t flags = 0; + Steinberg::IPtr handler = nullptr; + }; + std::vector _posixFDObjects; + + void attachPosixFD(Steinberg::Linux::IRunLoop *); + void detachPosixFD(Steinberg::Linux::IRunLoop *); #endif public: - void fireTimer(clap_id timer_id); - void firePosixFDIsSet(int fd, clap_posix_fd_flags_t flags); -private: + void fireTimer(clap_id timer_id); + void firePosixFDIsSet(int fd, clap_posix_fd_flags_t flags); - // INoteExpression - Vst::NoteExpressionTypeContainer _noteExpressions; +private: + // INoteExpression + Vst::NoteExpressionTypeContainer _noteExpressions; - // add a copiler options for which NE to support - uint32_t _expressionmap = + // add a copiler options for which NE to support + uint32_t _expressionmap = #if CLAP_SUPPORTS_ALL_NOTE_EXPRESSIONS - clap_supported_note_expressions::AS_VST3_NOTE_EXPRESSION_ALL; + clap_supported_note_expressions::AS_VST3_NOTE_EXPRESSION_ALL; #else - clap_supported_note_expressions::AS_VST3_NOTE_EXPRESSION_PRESSURE; + clap_supported_note_expressions::AS_VST3_NOTE_EXPRESSION_PRESSURE; #endif - }; diff --git a/src/wrapasvst3_entry.cpp b/src/wrapasvst3_entry.cpp index 764399bd..5bb40138 100644 --- a/src/wrapasvst3_entry.cpp +++ b/src/wrapasvst3_entry.cpp @@ -1,45 +1,44 @@ /* - CLAP AS VST3 - Entrypoint + CLAP AS VST3 - Entrypoint - Copyright (c) 2022 Timo Kaluza (defiantnerd) + Copyright (c) 2022 Timo Kaluza (defiantnerd) - This file is part of the clap-wrappers project which is released under MIT License. - See file LICENSE or go to https://github.com/free-audio/clap-wrapper for full license details. + This file is part of the clap-wrappers project which is released under MIT License. + See file LICENSE or go to https://github.com/free-audio/clap-wrapper for full license details. - Provides the entry function for the VST3 flavor of the wrapped plugin. + Provides the entry function for the VST3 flavor of the wrapped plugin. - When the VST3 factory is being scanned, this tries to locate a clap_entry function - in the following order and stops if a .clap binary has been found: + When the VST3 factory is being scanned, this tries to locate a clap_entry function + in the following order and stops if a .clap binary has been found: - 1) checks for exported `clap_enty` in this binary itself (statically linked wrapper) - 2) determines it's own filename without the .vst3 ending and determines a list of all valid CLAP search paths (see below) and - a) checks each CLAP search path for a matching .clap - b) checks it's own parent folder name and tries to add it to the .clap path. This allows a vst3 wrapper placed in - {any VST3 Folder}/mevendor/myplugin.vst3 to match {any CLAP folder}/mevendor/myplugin.clap - c) checks all subfolders in the CLAP folders for a matching .clap. - - Valid CLAP search paths are also documented in clap/include/clap/entry.h: + 1) checks for exported `clap_enty` in this binary itself (statically linked wrapper) + 2) determines it's own filename without the .vst3 ending and determines a list of all valid CLAP search + paths (see below) and a) checks each CLAP search path for a matching .clap b) checks it's own parent folder name and + tries to add it to the .clap path. This allows a vst3 wrapper placed in {any VST3 Folder}/mevendor/myplugin.vst3 to + match {any CLAP folder}/mevendor/myplugin.clap c) checks all subfolders in the CLAP folders for a matching .clap. - // CLAP plugins standard search path: + Valid CLAP search paths are also documented in clap/include/clap/entry.h: + + // CLAP plugins standard search path: Linux - ~/.clap - /usr/lib/clap - + Windows - %CommonFilesFolder%/CLAP/ - %LOCALAPPDATA%/Programs/Common/CLAP/ - + MacOS - /Library/Audio/Plug-Ins/CLAP - ~/Library/Audio/Plug-Ins/CLAP - + In addition to the OS-specific default locations above, a CLAP host must query the environment for a CLAP_PATH variable, which is a list of directories formatted in the same manner as the host OS binary search path (PATH on Unix, separated by `:` and Path on Windows, separated by ';', as of this writing). - + Each directory should be recursively searched for files and/or bundles as appropriate in your OS ending with the extension `.clap`. @@ -65,256 +64,254 @@ using namespace Steinberg::Vst; struct CreationContext { - Clap::Library* lib = nullptr; - int index = 0; - PClassInfo2 classinfo; + Clap::Library *lib = nullptr; + int index = 0; + PClassInfo2 classinfo; }; -bool findPlugin(Clap::Library& lib, const std::string& pluginfilename) +bool findPlugin(Clap::Library &lib, const std::string &pluginfilename) { - auto parentfolder = os::getParentFolderName(); - auto paths = Clap::getValidCLAPSearchPaths(); - - // Strategy 1: look for a clap with the same name as this binary - for (auto& i : paths) - { - if ( !fs::exists(i) ) - continue; - // try to find it the CLAP folder immediately - auto k1 = i / pluginfilename; - LOGDETAIL("scanning for binary: {}", k1.u8string().c_str()); - - if (fs::exists(k1)) - { - if (lib.load(k1.u8string().c_str())) - { - return true; - } - } - - // Strategy 2: try to locate "CLAP/vendorX/plugY.clap" - derived from "VST3/vendorX/plugY.vst3" - auto k2 = i / parentfolder / pluginfilename; - LOGDETAIL("scanning for binary: {}", k2.u8string().c_str()); - if (fs::exists(k2)) - { - if (lib.load(k2.u8string().c_str())) - { - return true; - } - } - - // Strategy 3: enumerate folders in CLAP folder and try to locate the plugin in any sub folder (only one level) - for (const auto& subdir : fs::directory_iterator(i)) - { - auto k3 = i / subdir / pluginfilename; - LOGDETAIL("scanning for binary: {}", k3.u8string().c_str()); - if (fs::exists(k3)) - { - if (lib.load(k3.u8string().c_str())) - { - return true; - } - } - } - } - - return false; + auto parentfolder = os::getParentFolderName(); + auto paths = Clap::getValidCLAPSearchPaths(); + + // Strategy 1: look for a clap with the same name as this binary + for (auto &i : paths) + { + if (!fs::exists(i)) + continue; + // try to find it the CLAP folder immediately + auto k1 = i / pluginfilename; + LOGDETAIL("scanning for binary: {}", k1.u8string().c_str()); + + if (fs::exists(k1)) + { + if (lib.load(k1.u8string().c_str())) + { + return true; + } + } + + // Strategy 2: try to locate "CLAP/vendorX/plugY.clap" - derived from "VST3/vendorX/plugY.vst3" + auto k2 = i / parentfolder / pluginfilename; + LOGDETAIL("scanning for binary: {}", k2.u8string().c_str()); + if (fs::exists(k2)) + { + if (lib.load(k2.u8string().c_str())) + { + return true; + } + } + + // Strategy 3: enumerate folders in CLAP folder and try to locate the plugin in any sub folder (only one level) + for (const auto &subdir : fs::directory_iterator(i)) + { + auto k3 = i / subdir / pluginfilename; + LOGDETAIL("scanning for binary: {}", k3.u8string().c_str()); + if (fs::exists(k3)) + { + if (lib.load(k3.u8string().c_str())) + { + return true; + } + } + } + } + + return false; } -IPluginFactory* GetPluginFactoryEntryPoint() { +IPluginFactory *GetPluginFactoryEntryPoint() +{ #if _DEBUG - // MessageBoxA(NULL,"halt","me",MB_OK); // <- enable this on Windows to get a debug attachment to vstscanner.exe (subprocess of cbse) + // MessageBoxA(NULL,"halt","me",MB_OK); // <- enable this on Windows to get a debug attachment to vstscanner.exe + // (subprocess of cbse) #endif #if SMTG_OS_WINDOWS // #pragma comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__) #endif - // static IPtr gPluginFactory = nullptr; - static Clap::Library gClapLibrary; - - static std::vector gCreationContexts; - - // if there is no ClapLibrary yet - if (!gClapLibrary._pluginFactory) - { - // if this binary does not already contain a CLAP entrypoint - if (!gClapLibrary.hasEntryPoint()) - { - // try to find a clap which filename stem matches our own - auto kx = os::getParentFolderName(); - auto plugname = os::getBinaryName(); - plugname.append(".clap"); - - if (!findPlugin(gClapLibrary, plugname)) - { - return nullptr; - } - } - else - { - LOGDETAIL("detected entrypoint in this binary"); - } - } - if (gClapLibrary.plugins.empty()) - { - // with no plugins there is nothing to do.. - LOGINFO("no plugin has been found"); - return nullptr; - } - - if (!clap_version_is_compatible(gClapLibrary.plugins[0]->clap_version)) - { - // CLAP version is not compatible -> eject - LOGINFO("CLAP version is not compatible"); - return nullptr; - } - - if (!gPluginFactory) - { - // we need at least one plugin to obtain vendor/name etc. - auto* factoryvendor = gClapLibrary.plugins[0]->vendor; - auto* vendor_url = gClapLibrary.plugins[0]->url; - // TODO: extract the domain and prefix with info@ - auto* contact = "info@"; - - // override for VST3 specifics - if (gClapLibrary._pluginFactoryVst3Info) - { - - LOGDETAIL("detected extension `{}`", CLAP_PLUGIN_FACTORY_INFO_VST3); - auto& v3 = gClapLibrary._pluginFactoryVst3Info; - if (v3->vendor) factoryvendor = v3->vendor; - if (v3->vendor_url) vendor_url = v3->vendor_url; - if (v3->email_contact) contact = v3->email_contact; - } - - static PFactoryInfo factoryInfo( - factoryvendor, - vendor_url, - contact, - Vst::kDefaultFactoryFlags); - - LOGDETAIL("created factory for vendor '{}'", factoryvendor); - - gPluginFactory = new Steinberg::CPluginFactory(factoryInfo); - // resize the classInfo vector - gCreationContexts.clear(); - gCreationContexts.reserve(gClapLibrary.plugins.size()); - int numPlugins = static_cast(gClapLibrary.plugins.size()); - LOGDETAIL("number of plugins in factory: {}", numPlugins); - for (int ctr = 0; ctr < numPlugins; ++ctr) - { - auto& clapdescr = gClapLibrary.plugins[ctr]; - auto vst3info = gClapLibrary.get_vst3_info(ctr); - - LOGDETAIL(" plugin #{}: '{}'", ctr, clapdescr->name); - - std::string n(clapdescr->name); + // static IPtr gPluginFactory = nullptr; + static Clap::Library gClapLibrary; + + static std::vector gCreationContexts; + + // if there is no ClapLibrary yet + if (!gClapLibrary._pluginFactory) + { + // if this binary does not already contain a CLAP entrypoint + if (!gClapLibrary.hasEntryPoint()) + { + // try to find a clap which filename stem matches our own + auto kx = os::getParentFolderName(); + auto plugname = os::getBinaryName(); + plugname.append(".clap"); + + if (!findPlugin(gClapLibrary, plugname)) + { + return nullptr; + } + } + else + { + LOGDETAIL("detected entrypoint in this binary"); + } + } + if (gClapLibrary.plugins.empty()) + { + // with no plugins there is nothing to do.. + LOGINFO("no plugin has been found"); + return nullptr; + } + + if (!clap_version_is_compatible(gClapLibrary.plugins[0]->clap_version)) + { + // CLAP version is not compatible -> eject + LOGINFO("CLAP version is not compatible"); + return nullptr; + } + + if (!gPluginFactory) + { + // we need at least one plugin to obtain vendor/name etc. + auto *factoryvendor = gClapLibrary.plugins[0]->vendor; + auto *vendor_url = gClapLibrary.plugins[0]->url; + // TODO: extract the domain and prefix with info@ + auto *contact = "info@"; + + // override for VST3 specifics + if (gClapLibrary._pluginFactoryVst3Info) + { + + LOGDETAIL("detected extension `{}`", CLAP_PLUGIN_FACTORY_INFO_VST3); + auto &v3 = gClapLibrary._pluginFactoryVst3Info; + if (v3->vendor) + factoryvendor = v3->vendor; + if (v3->vendor_url) + vendor_url = v3->vendor_url; + if (v3->email_contact) + contact = v3->email_contact; + } + + static PFactoryInfo factoryInfo(factoryvendor, vendor_url, contact, Vst::kDefaultFactoryFlags); + + LOGDETAIL("created factory for vendor '{}'", factoryvendor); + + gPluginFactory = new Steinberg::CPluginFactory(factoryInfo); + // resize the classInfo vector + gCreationContexts.clear(); + gCreationContexts.reserve(gClapLibrary.plugins.size()); + int numPlugins = static_cast(gClapLibrary.plugins.size()); + LOGDETAIL("number of plugins in factory: {}", numPlugins); + for (int ctr = 0; ctr < numPlugins; ++ctr) + { + auto &clapdescr = gClapLibrary.plugins[ctr]; + auto vst3info = gClapLibrary.get_vst3_info(ctr); + + LOGDETAIL(" plugin #{}: '{}'", ctr, clapdescr->name); + + std::string n(clapdescr->name); #ifdef _DEBUG - n.append(" (CLAP->VST3)"); + n.append(" (CLAP->VST3)"); #endif - auto plugname = n.c_str(); // clapdescr->name; + auto plugname = n.c_str(); // clapdescr->name; - // get vendor ------------------------------------- - auto pluginvendor = clapdescr->vendor; - if (pluginvendor == nullptr || *pluginvendor == 0) pluginvendor = "Unspecified Vendor"; - if (vst3info && vst3info->vendor) - { - LOGDETAIL(" plugin supports extension '{}'", CLAP_PLUGIN_AS_VST3); - pluginvendor = vst3info->vendor; - } + // get vendor ------------------------------------- + auto pluginvendor = clapdescr->vendor; + if (pluginvendor == nullptr || *pluginvendor == 0) + pluginvendor = "Unspecified Vendor"; + if (vst3info && vst3info->vendor) + { + LOGDETAIL(" plugin supports extension '{}'", CLAP_PLUGIN_AS_VST3); + pluginvendor = vst3info->vendor; + } - TUID lcid; - Crypto::uuid_object g; + TUID lcid; + Crypto::uuid_object g; #ifdef CLAP_VST3_TUID_STRING - Steinberg::FUID f; - if (f.fromString(CLAP_VST3_TUID_STRING)) - { - memcpy(&g, f.toTUID(), sizeof(TUID)); - memcpy(&lcid, &g, sizeof(TUID)); - } - else + Steinberg::FUID f; + if (f.fromString(CLAP_VST3_TUID_STRING)) + { + memcpy(&g, f.toTUID(), sizeof(TUID)); + memcpy(&lcid, &g, sizeof(TUID)); + } + else #endif - { - // make id or take it from vst3 info -------------- - std::string id(clapdescr->id); - if (vst3info && vst3info->componentId) { - memcpy(&g, vst3info->componentId, sizeof(g)); - } else { - g = Crypto::create_sha1_guid_from_name(id.c_str(), id.size()); - } - - memcpy(&lcid, &g, sizeof(TUID)); - } - - // features ---------------------------------------- - std::string features; - if (vst3info && vst3info->features) - { - features = vst3info->features; - } - else - { - features = clapCategoriesToVST3(clapdescr->features); - } - - -#if CLAP_WRAPPER_LOGLEVEL> 1 - { - const uint8_t * v = reinterpret_cast(&g); - char x[sizeof(g)*2+8]; - char* o = x; - constexpr char hexchar[] = "0123456789ABCDEF"; - for (auto i = 0U ; i < sizeof(g) ; i++) - { - auto n = v[i]; - *o++ = hexchar[(n >> 4) & 0xF]; - *o++ = hexchar[n & 0xF]; - if (!(i % 4)) *o++ = 32; - } - *o++ = 0; - LOGDETAIL("plugin id: {} -> {}", clapdescr->id,x); - } + { + // make id or take it from vst3 info -------------- + std::string id(clapdescr->id); + if (vst3info && vst3info->componentId) + { + memcpy(&g, vst3info->componentId, sizeof(g)); + } + else + { + g = Crypto::create_sha1_guid_from_name(id.c_str(), id.size()); + } + + memcpy(&lcid, &g, sizeof(TUID)); + } + + // features ---------------------------------------- + std::string features; + if (vst3info && vst3info->features) + { + features = vst3info->features; + } + else + { + features = clapCategoriesToVST3(clapdescr->features); + } + +#if CLAP_WRAPPER_LOGLEVEL > 1 + { + const uint8_t *v = reinterpret_cast(&g); + char x[sizeof(g) * 2 + 8]; + char *o = x; + constexpr char hexchar[] = "0123456789ABCDEF"; + for (auto i = 0U; i < sizeof(g); i++) + { + auto n = v[i]; + *o++ = hexchar[(n >> 4) & 0xF]; + *o++ = hexchar[n & 0xF]; + if (!(i % 4)) + *o++ = 32; + } + *o++ = 0; + LOGDETAIL("plugin id: {} -> {}", clapdescr->id, x); + } #endif - gCreationContexts.push_back({ &gClapLibrary, ctr, PClassInfo2( - lcid, - PClassInfo::kManyInstances, - kVstAudioEffectClass, - plugname, - 0 /* the only flag is usually Vst:kDistributable, but CLAPs aren't distributable */, - features.c_str(), - pluginvendor, - clapdescr->version, - kVstVersionString) - }); - gPluginFactory->registerClass(&gCreationContexts.back().classinfo, ClapAsVst3::createInstance, &gCreationContexts.back()); - } - - } - else - gPluginFactory->addRef(); - - return gPluginFactory; + gCreationContexts.push_back( + {&gClapLibrary, ctr, + PClassInfo2(lcid, PClassInfo::kManyInstances, kVstAudioEffectClass, plugname, + 0 /* the only flag is usually Vst:kDistributable, but CLAPs aren't distributable */, + features.c_str(), pluginvendor, clapdescr->version, kVstVersionString)}); + gPluginFactory->registerClass(&gCreationContexts.back().classinfo, ClapAsVst3::createInstance, + &gCreationContexts.back()); + } + } + else + gPluginFactory->addRef(); + + return gPluginFactory; } /* -* creates an Instance from the creationContext. -* actually, there is always a valid entrypoint, otherwise no factory would have been provided. -*/ -FUnknown* ClapAsVst3::createInstance(void* context) -{ - auto ctx = static_cast(context); - - LOGINFO("creating plugin {} (#{})", ctx->classinfo.name, ctx->index); - if (ctx->lib->hasEntryPoint()) - { - // MessageBoxA(NULL, "halt", "create", MB_OK); - return (IAudioProcessor*)new ClapAsVst3(ctx->lib, ctx->index, context); - } - return nullptr; // this should never happen. - + * creates an Instance from the creationContext. + * actually, there is always a valid entrypoint, otherwise no factory would have been provided. + */ +FUnknown *ClapAsVst3::createInstance(void *context) +{ + auto ctx = static_cast(context); + + LOGINFO("creating plugin {} (#{})", ctx->classinfo.name, ctx->index); + if (ctx->lib->hasEntryPoint()) + { + // MessageBoxA(NULL, "halt", "create", MB_OK); + return (IAudioProcessor *)new ClapAsVst3(ctx->lib, ctx->index, context); + } + return nullptr; // this should never happen. } diff --git a/src/wrapasvst3_export_entry.cpp b/src/wrapasvst3_export_entry.cpp index 4583331f..cafe9080 100644 --- a/src/wrapasvst3_export_entry.cpp +++ b/src/wrapasvst3_export_entry.cpp @@ -1,7 +1,8 @@ #include "public.sdk/source/main/pluginfactory.h" -SMTG_EXPORT_SYMBOL Steinberg::IPluginFactory* PLUGIN_API GetPluginFactory() { - extern Steinberg::IPluginFactory *GetPluginFactoryEntryPoint(); - return GetPluginFactoryEntryPoint(); +SMTG_EXPORT_SYMBOL Steinberg::IPluginFactory *PLUGIN_API GetPluginFactory() +{ + extern Steinberg::IPluginFactory *GetPluginFactoryEntryPoint(); + return GetPluginFactoryEntryPoint(); }