diff --git a/Makefile.plugins.mk b/Makefile.plugins.mk index b2106ce7..48a8d50c 100644 --- a/Makefile.plugins.mk +++ b/Makefile.plugins.mk @@ -375,19 +375,19 @@ else jack = $(TARGET_DIR)/$(NAME)$(APP_EXT) endif -ladspa_dsp = $(TARGET_DIR)/$(NAME)-ladspa$(LIB_EXT) +clap = $(TARGET_DIR)/$(CLAP_FILENAME) dssi_dsp = $(TARGET_DIR)/$(NAME)-dssi$(LIB_EXT) dssi_ui = $(TARGET_DIR)/$(NAME)-dssi/$(NAME)_ui$(APP_EXT) +ladspa_dsp = $(TARGET_DIR)/$(NAME)-ladspa$(LIB_EXT) lv2 = $(TARGET_DIR)/$(NAME).lv2/$(NAME)$(LIB_EXT) lv2_dsp = $(TARGET_DIR)/$(NAME).lv2/$(NAME)_dsp$(LIB_EXT) lv2_ui = $(TARGET_DIR)/$(NAME).lv2/$(NAME)_ui$(LIB_EXT) +mapi = $(TARGET_DIR)/$(NAME)$(LIB_EXT) +static = $(TARGET_DIR)/$(NAME).a vst2 = $(TARGET_DIR)/$(VST2_FILENAME) ifneq ($(VST3_FILENAME),) vst3 = $(TARGET_DIR)/$(VST3_FILENAME) endif -clap = $(TARGET_DIR)/$(CLAP_FILENAME) -shared = $(TARGET_DIR)/$(NAME)$(LIB_EXT) -static = $(TARGET_DIR)/$(NAME).a ifeq ($(MACOS),true) BUNDLE_RESOURCES = Info.plist PkgInfo Resources/empty.lproj @@ -414,45 +414,45 @@ endif ifeq ($(MACOS),true) SYMBOLS_AU = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/au.exp -SYMBOLS_LADSPA = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/ladspa.exp +SYMBOLS_CLAP = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/clap.exp SYMBOLS_DSSI = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/dssi.exp +SYMBOLS_LADSPA = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/ladspa.exp +SYMBOLS_LV2 = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/lv2.exp SYMBOLS_LV2DSP = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/lv2-dsp.exp SYMBOLS_LV2UI = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/lv2-ui.exp -SYMBOLS_LV2 = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/lv2.exp +SYMBOLS_MAPI = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/mapi.exp SYMBOLS_VST2 = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/vst2.exp SYMBOLS_VST3 = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/vst3.exp -SYMBOLS_CLAP = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/clap.exp -SYMBOLS_SHARED = -Wl,-exported_symbols_list,$(DPF_PATH)/utils/symbols/shared.exp else ifeq ($(WASM),true) -SYMBOLS_LADSPA = -sEXPORTED_FUNCTIONS="['ladspa_descriptor']" +SYMBOLS_CLAP = -sEXPORTED_FUNCTIONS="['clap_entry']" SYMBOLS_DSSI = -sEXPORTED_FUNCTIONS="['ladspa_descriptor','dssi_descriptor']" +SYMBOLS_LADSPA = -sEXPORTED_FUNCTIONS="['ladspa_descriptor']" +SYMBOLS_LV2 = -sEXPORTED_FUNCTIONS="['lv2_descriptor','lv2_generate_ttl','lv2ui_descriptor']" SYMBOLS_LV2DSP = -sEXPORTED_FUNCTIONS="['lv2_descriptor','lv2_generate_ttl']" SYMBOLS_LV2UI = -sEXPORTED_FUNCTIONS="['lv2ui_descriptor']" -SYMBOLS_LV2 = -sEXPORTED_FUNCTIONS="['lv2_descriptor','lv2_generate_ttl','lv2ui_descriptor']" +SYMBOLS_MAPI = -sEXPORTED_FUNCTIONS="['mapi_create','mapi_process','mapi_set_parameter','mapi_set_state','mapi_destroy']" SYMBOLS_VST2 = -sEXPORTED_FUNCTIONS="['VSTPluginMain']" SYMBOLS_VST3 = -sEXPORTED_FUNCTIONS="['GetPluginFactory','ModuleEntry','ModuleExit']" -SYMBOLS_CLAP = -sEXPORTED_FUNCTIONS="['clap_entry']" -SYMBOLS_SHARED = -sEXPORTED_FUNCTIONS="['createSharedPlugin']" else ifeq ($(WINDOWS),true) -SYMBOLS_LADSPA = $(DPF_PATH)/utils/symbols/ladspa.def +SYMBOLS_CLAP = $(DPF_PATH)/utils/symbols/clap.def SYMBOLS_DSSI = $(DPF_PATH)/utils/symbols/dssi.def +SYMBOLS_LADSPA = $(DPF_PATH)/utils/symbols/ladspa.def +SYMBOLS_LV2 = $(DPF_PATH)/utils/symbols/lv2.def SYMBOLS_LV2DSP = $(DPF_PATH)/utils/symbols/lv2-dsp.def SYMBOLS_LV2UI = $(DPF_PATH)/utils/symbols/lv2-ui.def -SYMBOLS_LV2 = $(DPF_PATH)/utils/symbols/lv2.def +SYMBOLS_MAPI = $(DPF_PATH)/utils/symbols/mapi.def SYMBOLS_VST2 = $(DPF_PATH)/utils/symbols/vst2.def SYMBOLS_VST3 = $(DPF_PATH)/utils/symbols/vst3.def -SYMBOLS_CLAP = $(DPF_PATH)/utils/symbols/clap.def -SYMBOLS_SHARED = $(DPF_PATH)/utils/symbols/shared.def else ifneq ($(DEBUG),true) -SYMBOLS_LADSPA = -Wl,--version-script=$(DPF_PATH)/utils/symbols/ladspa.version +SYMBOLS_CLAP = -Wl,--version-script=$(DPF_PATH)/utils/symbols/clap.version SYMBOLS_DSSI = -Wl,--version-script=$(DPF_PATH)/utils/symbols/dssi.version +SYMBOLS_LADSPA = -Wl,--version-script=$(DPF_PATH)/utils/symbols/ladspa.version +SYMBOLS_LV2 = -Wl,--version-script=$(DPF_PATH)/utils/symbols/lv2.version SYMBOLS_LV2DSP = -Wl,--version-script=$(DPF_PATH)/utils/symbols/lv2-dsp.version SYMBOLS_LV2UI = -Wl,--version-script=$(DPF_PATH)/utils/symbols/lv2-ui.version -SYMBOLS_LV2 = -Wl,--version-script=$(DPF_PATH)/utils/symbols/lv2.version +SYMBOLS_MAPI = -Wl,--version-script=$(DPF_PATH)/utils/symbols/mapi.version SYMBOLS_VST2 = -Wl,--version-script=$(DPF_PATH)/utils/symbols/vst2.version SYMBOLS_VST3 = -Wl,--version-script=$(DPF_PATH)/utils/symbols/vst3.version -SYMBOLS_CLAP = -Wl,--version-script=$(DPF_PATH)/utils/symbols/clap.version -SYMBOLS_SHARED = -Wl,--version-script=$(DPF_PATH)/utils/symbols/shared.version endif # --------------------------------------------------------------------------------------------------------------------- @@ -811,6 +811,16 @@ endif @echo "Creating AU component for $(NAME)" $(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(EXTRA_LIBS) $(EXTRA_DSP_LIBS) $(EXTRA_UI_LIBS) $(DGL_LIBS) -framework AudioToolbox -framework AudioUnit -framework CoreFoundation $(SHARED) $(SYMBOLS_AU) -o $@ +# --------------------------------------------------------------------------------------------------------------------- +# MAPI + +mapi: $(mapi) + +$(mapi): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_MAPI.cpp.o + -@mkdir -p $(shell dirname $@) + @echo "Creating MAPI for $(NAME)" + $(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(EXTRA_LIBS) $(EXTRA_DSP_LIBS) $(EXTRA_UI_LIBS) $(DGL_LIBS) $(SHARED) $(SYMBOLS_MAPI) -o $@ + # --------------------------------------------------------------------------------------------------------------------- # Export @@ -823,20 +833,6 @@ endif @echo "Creating export tool for $(NAME)" $(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(EXTRA_LIBS) $(EXTRA_DSP_LIBS) $(EXTRA_UI_LIBS) $(DGL_LIBS) -o $@ -# --------------------------------------------------------------------------------------------------------------------- -# Shared - -shared: $(shared) - -ifeq ($(HAVE_DGL),true) -$(shared): $(OBJS_DSP) $(OBJS_UI) $(BUILD_DIR)/DistrhoPluginMain_SHARED.cpp.o $(BUILD_DIR)/DistrhoUIMain_SHARED.cpp.o $(DGL_LIB) $(DGL_LIB_SHARED) -else -$(shared): $(OBJS_DSP) $(BUILD_DIR)/DistrhoPluginMain_SHARED.cpp.o -endif - -@mkdir -p $(shell dirname $@) - @echo "Creating shared library for $(NAME)" - $(SILENT)$(CXX) $^ $(BUILD_CXX_FLAGS) $(LINK_FLAGS) $(EXTRA_LIBS) $(EXTRA_DSP_LIBS) $(EXTRA_UI_LIBS) $(DGL_LIBS) $(SHARED) $(SYMBOLS_SHARED) -o $@ - # --------------------------------------------------------------------------------------------------------------------- # Static @@ -885,28 +881,27 @@ ifneq ($(UI_TYPE),) -include $(OBJS_UI:%.o=%.d) endif +-include $(BUILD_DIR)/DistrhoPluginMain_AU.cpp.d +-include $(BUILD_DIR)/DistrhoPluginMain_CLAP.cpp.d +-include $(BUILD_DIR)/DistrhoPluginMain_DSSI.cpp.d +-include $(BUILD_DIR)/DistrhoPluginMain_Export.cpp.d -include $(BUILD_DIR)/DistrhoPluginMain_JACK.cpp.d -include $(BUILD_DIR)/DistrhoPluginMain_LADSPA.cpp.d --include $(BUILD_DIR)/DistrhoPluginMain_DSSI.cpp.d -include $(BUILD_DIR)/DistrhoPluginMain_LV2.cpp.d -include $(BUILD_DIR)/DistrhoPluginMain_LV2_single_obj.cpp.d +-include $(BUILD_DIR)/DistrhoPluginMain_MAPI.cpp.d +-include $(BUILD_DIR)/DistrhoPluginMain_STATIC.cpp.d -include $(BUILD_DIR)/DistrhoPluginMain_VST2.cpp.d -include $(BUILD_DIR)/DistrhoPluginMain_VST3.cpp.d --include $(BUILD_DIR)/DistrhoPluginMain_CLAP.cpp.d --include $(BUILD_DIR)/DistrhoPluginMain_AU.cpp.d --include $(BUILD_DIR)/DistrhoPluginMain_Export.cpp.d --include $(BUILD_DIR)/DistrhoPluginMain_SHARED.cpp.d --include $(BUILD_DIR)/DistrhoPluginMain_STATIC.cpp.d --include $(BUILD_DIR)/DistrhoUIMain_JACK.cpp.d +-include $(BUILD_DIR)/DistrhoUIMain_AU.cpp.d +-include $(BUILD_DIR)/DistrhoUIMain_CLAP.cpp.d -include $(BUILD_DIR)/DistrhoUIMain_DSSI.cpp.d +-include $(BUILD_DIR)/DistrhoUIMain_JACK.cpp.d -include $(BUILD_DIR)/DistrhoUIMain_LV2.cpp.d -include $(BUILD_DIR)/DistrhoUIMain_LV2_single_obj.cpp.d +-include $(BUILD_DIR)/DistrhoUIMain_STATIC.cpp.d -include $(BUILD_DIR)/DistrhoUIMain_VST2.cpp.d -include $(BUILD_DIR)/DistrhoUIMain_VST3.cpp.d --include $(BUILD_DIR)/DistrhoUIMain_CLAP.cpp.d --include $(BUILD_DIR)/DistrhoUIMain_AU.cpp.d --include $(BUILD_DIR)/DistrhoUIMain_SHARED.cpp.d --include $(BUILD_DIR)/DistrhoUIMain_STATIC.cpp.d # --------------------------------------------------------------------------------------------------------------------- diff --git a/distrho/DistrhoPluginMain.cpp b/distrho/DistrhoPluginMain.cpp index 254da24e..d5650b08 100644 --- a/distrho/DistrhoPluginMain.cpp +++ b/distrho/DistrhoPluginMain.cpp @@ -1,6 +1,6 @@ /* * DISTRHO Plugin Framework (DPF) - * Copyright (C) 2012-2024 Filipe Coelho + * Copyright (C) 2012-2025 Filipe Coelho * * Permission to use, copy, modify, and/or distribute this software for any purpose with * or without fee is hereby granted, provided that the above copyright notice and this @@ -29,15 +29,14 @@ #elif defined(DISTRHO_PLUGIN_TARGET_LV2) # include "src/DistrhoPluginLV2.cpp" # include "src/DistrhoPluginLV2export.cpp" +#elif defined(DISTRHO_PLUGIN_TARGET_MAPI) +# include "src/DistrhoPluginMAPI.cpp" #elif defined(DISTRHO_PLUGIN_TARGET_VST2) # include "src/DistrhoPluginVST2.cpp" #elif defined(DISTRHO_PLUGIN_TARGET_VST3) # include "src/DistrhoPluginVST3.cpp" #elif defined(DISTRHO_PLUGIN_TARGET_EXPORT) # include "src/DistrhoPluginExport.cpp" -#elif defined(DISTRHO_PLUGIN_TARGET_SHARED) -DISTRHO_PLUGIN_EXPORT DISTRHO_NAMESPACE::Plugin* createSharedPlugin(); -DISTRHO_PLUGIN_EXPORT DISTRHO_NAMESPACE::Plugin* createSharedPlugin() { return DISTRHO_NAMESPACE::createPlugin(); } #elif defined(DISTRHO_PLUGIN_TARGET_STATIC) START_NAMESPACE_DISTRHO Plugin* createStaticPlugin() { return createPlugin(); } diff --git a/distrho/src/DistrhoPluginMAPI.cpp b/distrho/src/DistrhoPluginMAPI.cpp new file mode 100644 index 00000000..ef85ef1d --- /dev/null +++ b/distrho/src/DistrhoPluginMAPI.cpp @@ -0,0 +1,156 @@ +/* + * DISTRHO Plugin Framework (DPF) + * Copyright (C) 2012-2025 Filipe Coelho + * + * Permission to use, copy, modify, and/or distribute this software for any purpose with + * or without fee is hereby granted, provided that the above copyright notice and this + * permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "DistrhoPluginInternal.hpp" + +#ifndef DISTRHO_NO_WARNINGS +# if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST +# error Cannot use parameter value change request with MAPI +# endif +# if DISTRHO_PLUGIN_WANT_MIDI_INPUT || DISTRHO_PLUGIN_WANT_MIDI_OUTPUT +# error Cannot use MIDI with MAPI +# endif +# if DISTRHO_PLUGIN_WANT_FULL_STATE +# error Cannot use full state with MAPI +# endif +# if DISTRHO_PLUGIN_WANT_TIMEPOS +# error Cannot use time position with MAPI +# endif +#endif + +#include "mapi/mapi.h" + +START_NAMESPACE_DISTRHO + +// -------------------------------------------------------------------------------------------------------------------- + +class PluginMAPI +{ +public: + PluginMAPI() + : fPlugin(nullptr, nullptr, nullptr, nullptr) + { + fPlugin.activate(); + } + + ~PluginMAPI() noexcept + { + fPlugin.deactivate(); + } + + // ---------------------------------------------------------------------------------------------------------------- + + void process(const float* const* ins, float** outs, unsigned int frames) + { + #if DISTRHO_PLUGIN_WANT_MIDI_INPUT + fPlugin.run(ins, outs, frames, nullptr, 0); + #else + fPlugin.run(const_cast(ins), outs, frames); + #endif + + updateParameterOutputsAndTriggers(); + } + + void setParameter(unsigned int index, float value) + { + fPlugin.setParameterValue(index, fPlugin.getParameterRanges(index).getUnnormalizedValue(value)); + } + + #if DISTRHO_PLUGIN_WANT_STATE + void setState(const char* key, const char* value) + { + fPlugin.setState(key, value); + } + #endif + + // ---------------------------------------------------------------------------------------------------------------- + +private: + PluginExporter fPlugin; + + void updateParameterOutputsAndTriggers() + { + float value; + + for (uint32_t i = 0, count = fPlugin.getParameterCount(); i < count; ++i) + { + if ((fPlugin.getParameterHints(i) & kParameterIsTrigger) == kParameterIsTrigger) + { + // NOTE: no trigger support in MAPI, simulate it here + value = fPlugin.getParameterRanges(i).def; + + if (d_isEqual(value, fPlugin.getParameterValue(i))) + continue; + + fPlugin.setParameterValue(i, value); + } + } + } +}; + +// -------------------------------------------------------------------------------------------------------------------- + +MAPI_EXPORT +mapi_handle_t mapi_create(unsigned int sample_rate) +{ + if (d_nextBufferSize == 0) + { + #if defined(_DARKGLASS_DEVICE_PABLITO) + d_nextBufferSize = 16; + #elif defined(__MOD_DEVICES__) + d_nextBufferSize = 128; + #else + d_nextBufferSize = 2048; + #endif + } + + d_nextSampleRate = sample_rate; + + return new PluginMAPI(); +} + +MAPI_EXPORT +void mapi_process(mapi_handle_t handle, + const float* const* ins, + float** outs, + unsigned int frames) +{ + static_cast(handle)->process(ins, outs, frames); +} + +MAPI_EXPORT +void mapi_set_parameter(mapi_handle_t handle, unsigned int index, float value) +{ + static_cast(handle)->setParameter(index, value); +} + +#if DISTRHO_PLUGIN_WANT_STATE +MAPI_EXPORT +void mapi_set_state(mapi_handle_t handle, const char* key, const char* value) +{ + static_cast(handle)->setState(key, value); +} +#endif + +MAPI_EXPORT +void mapi_destroy(mapi_handle_t handle) +{ + delete static_cast(handle); +} + +// -------------------------------------------------------------------------------------------------------------------- + +END_NAMESPACE_DISTRHO diff --git a/distrho/src/mapi/mapi.h b/distrho/src/mapi/mapi.h new file mode 100644 index 00000000..d1175c0b --- /dev/null +++ b/distrho/src/mapi/mapi.h @@ -0,0 +1,73 @@ +// Copyright 2025 Filipe Coelho +// SPDX-License-Identifier: ISC + +#pragma once + +#ifdef __cplusplus +extern "C" { +# define MAPI_API extern "C" +#else +# define MAPI_API +#endif + +/* Define MAPI_EXPORT for exporting function symbols */ +#ifdef _WIN32 +# define MAPI_EXPORT MAPI_API __declspec (dllexport) +#else +# define MAPI_EXPORT MAPI_API __attribute__ ((visibility("default"))) +#endif + +/** Handle used through-out this API. */ +typedef void* mapi_handle_t; + +/** + Create an effect. + @param sample_rate Sample rate in Hz to use for the effect. + @return A handle for the new effect, or NULL if creation failed. +*/ +MAPI_EXPORT +mapi_handle_t mapi_create(unsigned int sample_rate); + +/** + Process an effect. + @param handle A previously created effect. + @param ins An array of audio buffers used for audio input. + @param outs An array of audio buffers used for audio output. + @param frames How many frames to process. + @note Input and output buffers might share the same location in memory, + typically referred to as "in-place processing". +*/ +MAPI_EXPORT +void mapi_process(mapi_handle_t filter, + const float* const* ins, + float** outs, + unsigned int frames); + +/** + Set an effect parameter. + @param handle A previously created effect. + @param index A known index for this effect. + @param value A normalized value between 0 and 1, scaled internally by the effect as necessary. +*/ +MAPI_EXPORT +void mapi_set_parameter(mapi_handle_t filter, unsigned int index, float value); + +/** + Set an effect state, using strings for both key and value. + @param handle A previously created effect. + @param key A known key for this effect, must not be NULL or empty. + @param value A non-NULL value, allowed to be empty. +*/ +MAPI_EXPORT +void mapi_set_state(mapi_handle_t filter, const char* key, const char* value); + +/** + Destroy a previously created effect. + @param handle A previously created effect. +*/ +MAPI_EXPORT +void mapi_destroy(mapi_handle_t filter); + +#ifdef __cplusplus +} +#endif diff --git a/utils/symbols/mapi.def b/utils/symbols/mapi.def new file mode 100644 index 00000000..d7640674 --- /dev/null +++ b/utils/symbols/mapi.def @@ -0,0 +1,6 @@ +EXPORTS +mapi_create +mapi_process +mapi_set_parameter +mapi_set_state +mapi_destroy diff --git a/utils/symbols/mapi.exp b/utils/symbols/mapi.exp new file mode 100644 index 00000000..32983990 --- /dev/null +++ b/utils/symbols/mapi.exp @@ -0,0 +1,5 @@ +_mapi_create +_mapi_process +_mapi_set_parameter +_mapi_set_state +_mapi_destroy diff --git a/utils/symbols/mapi.version b/utils/symbols/mapi.version new file mode 100644 index 00000000..740aa0c9 --- /dev/null +++ b/utils/symbols/mapi.version @@ -0,0 +1,4 @@ +{ + global: mapi_create; mapi_process; mapi_set_parameter; mapi_set_state; mapi_destroy; + local: *; +}; diff --git a/utils/symbols/shared.def b/utils/symbols/shared.def deleted file mode 100644 index 1413caea..00000000 --- a/utils/symbols/shared.def +++ /dev/null @@ -1,2 +0,0 @@ -EXPORTS -createSharedPlugin diff --git a/utils/symbols/shared.exp b/utils/symbols/shared.exp deleted file mode 100644 index 80f62510..00000000 --- a/utils/symbols/shared.exp +++ /dev/null @@ -1 +0,0 @@ -_createSharedPlugin diff --git a/utils/symbols/shared.version b/utils/symbols/shared.version deleted file mode 100644 index e60a663a..00000000 --- a/utils/symbols/shared.version +++ /dev/null @@ -1,4 +0,0 @@ -{ - global: createSharedPlugin; - local: *; -};