diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..a7026a8 --- /dev/null +++ b/.clang-format @@ -0,0 +1,59 @@ +--- +BasedOnStyle: LLVM +IndentWidth: 4 +--- +Language: Cpp +BasedOnStyle: LLVM +IndentWidth: 4 +AlignAfterOpenBracket: Align +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: true + AfterClass: true + AfterControlStatement: Always + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: true + BeforeElse: true + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +ColumnLimit: 100 +SortIncludes: false +--- +Language: ObjC +BasedOnStyle: LLVM +IndentWidth: 4 +AlignAfterOpenBracket: Align +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: true + AfterClass: true + AfterControlStatement: Always + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: true + BeforeElse: true + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +ColumnLimit: 100 +SortIncludes: false +--- + diff --git a/CMakeLists.txt b/CMakeLists.txt index f2f3a1e..bfc1661 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,8 @@ set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD 17) +option(COPY_AFTER_BUILD "Copy the clap to ~/Library on MACOS, ~/.clap on linux" FALSE) + # use asan as an option (currently mac only) option(USE_SANITIZER "Build and link with ASAN" FALSE) @@ -32,7 +34,6 @@ endif() add_library(${PROJECT_NAME} MODULE src/claudio.cpp - src/claudio_configured.cpp ) target_include_directories(${PROJECT_NAME} PRIVATE include ${CMAKE_BINARY_DIR}/individuals) target_link_libraries(${PROJECT_NAME} clap-core clap-helpers) @@ -100,14 +101,13 @@ foreach(awt ${AW}) endforeach() file(APPEND ${sumfn} "} return nullptr; } \n") -file(APPEND ${sumfn} "AudioEffect *claudio_get_aeffInstance(audioMasterCallback c, const char* plugin_id)\n") +file(APPEND ${sumfn} "std::pair claudio_get_aeffInstance(audioMasterCallback c, const char* plugin_id)\n") file(APPEND ${sumfn} "{") set(CASEW 0) foreach(awt ${AW}) - - file(APPEND ${sumfn} "if (strcmp(plugin_id, \"unofficial.com.airwindows.${awt}\") == 0) return claudio_${awt}CreateEffectInstance(c);\n") + file(APPEND ${sumfn} "if (strcmp(plugin_id, \"unofficial.com.airwindows.${awt}\") == 0) return { claudio_${awt}CreateEffectInstance(c), &claudio_${awt}_desc};\n") endforeach() -file(APPEND ${sumfn} "return nullptr; } \n") +file(APPEND ${sumfn} "return {nullptr, nullptr}; } \n") if(APPLE) diff --git a/include/audioeffectx.h b/include/audioeffectx.h index e62a6bb..3f597c9 100644 --- a/include/audioeffectx.h +++ b/include/audioeffectx.h @@ -7,9 +7,10 @@ #include #include +#include struct clap_host; -typedef const clap_host * audioMasterCallback; +typedef const clap_host *audioMasterCallback; typedef int VstPlugCategory; typedef int32_t VstInt32; #define vst_strncpy strncpy @@ -21,33 +22,46 @@ static constexpr uint32_t kVstMaxVendorStrLen = 64; static constexpr uint32_t kPlugCategEffect = 1; -inline void float2string(float, const char*, uint32_t) {} +inline void float2string(float f, char *c, uint32_t n) { + strncpy(c, std::to_string(f).c_str(), n); +} + +struct AudioEffect { + uint32_t numParams{0}; + AudioEffect(audioMasterCallback audioMaster, uint32_t kNumPrograms, uint32_t kNumParameters) : numParams(kNumParameters){} -struct AudioEffect -{ virtual ~AudioEffect() = default; - double getSampleRate() { return 48000.0; } + double sr{1}; + + void setSampleRate(double d) { sr = d; } + double getSampleRate() { return sr; } - void setNumInputs(uint32_t kNumInputs) {} - void setNumOutputs(uint32_t kNumOutputs) {} - void setUniqueID(uint32_t kUniqueId) {} + int nin{0}, nout{0}; + void setNumInputs(uint32_t kNumInputs) { nin = kNumInputs; } + void setNumOutputs(uint32_t kNumOutputs) { nout = kNumOutputs; } + void setUniqueID(uint32_t kUniqueId) {} - bool canProcessReplacing() { return false; } - bool canDoubleReplacing() { return false; } + bool canProcessReplacing() { return false; } + bool canDoubleReplacing() { return false; } - void programsAreChunks(bool b) {} + void programsAreChunks(bool b) {} - virtual bool getEffectName(char* name) = 0; // The plug-in name + virtual bool getEffectName(char *name) = 0; // The plug-in name virtual VstPlugCategory getPlugCategory() = 0; // The general category for the plug-in - virtual bool getProductString(char* text) = 0; // This is a unique plug-in string provided by Steinberg - virtual bool getVendorString(char* text) = 0 ; // Vendor info + virtual bool + getProductString(char *text) = 0; // This is a unique plug-in string provided by Steinberg + virtual bool getVendorString(char *text) = 0; // Vendor info virtual VstInt32 getVendorVersion() = 0; // Version number - virtual void processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames) = 0; - virtual void processDoubleReplacing (double** inputs, double** outputs, VstInt32 sampleFrames) = 0; - virtual VstInt32 getChunk (void** data, bool isPreset) = 0; - virtual VstInt32 setChunk (void* data, VstInt32 byteSize, bool isPreset) = 0; + virtual void processReplacing(float **inputs, float **outputs, VstInt32 sampleFrames) = 0; + + virtual void processDoubleReplacing(double **inputs, double **outputs, VstInt32 sampleFrames) = 0; + + virtual VstInt32 getChunk(void **data, bool isPreset) = 0; + + virtual VstInt32 setChunk(void *data, VstInt32 byteSize, bool isPreset) = 0; + virtual float getParameter(VstInt32 index) = 0; // get the parameter value at the specified index virtual void setParameter(VstInt32 index, float value) = 0; // set the parameter at index to value virtual void getParameterLabel(VstInt32 index, char *text) = 0; // label for the parameter (eg dB) @@ -56,9 +70,7 @@ struct AudioEffect virtual VstInt32 canDo(char *text) = 0; }; -struct AudioEffectX : public AudioEffect -{ - AudioEffectX(audioMasterCallback audioMaster, uint32_t kNumPrograms, uint32_t kNumParameters) {} -}; +typedef AudioEffect AudioEffectX; + #endif //CLAUDIO_EFFECT_X_AUDIOEFFECTX_H diff --git a/src/claudio.cpp b/src/claudio.cpp index 731dcf4..27f2200 100644 --- a/src/claudio.cpp +++ b/src/claudio.cpp @@ -2,16 +2,129 @@ // Created by Paul Walker on 6/18/22. // -#include "audioeffectx.h" +#include "clap/clap.h" +#include "clap/helpers/plugin.hh" +#include "clap/helpers/plugin.hxx" -#include "claudio_Galactic.h" +#include "clap/helpers/host-proxy.hh" +#include "clap/helpers/host-proxy.hxx" -#include "clap/clap.h" +#include "claudio_configured.hxx" + +#include +#include + +struct ClaudioWrapper : public clap::helpers::Plugin +{ + AudioEffect *underlyer{nullptr}; + ClaudioWrapper(const clap_host *host, const clap_plugin_descriptor *desc, AudioEffect *effect) + : clap::helpers::Plugin(desc, host), + underlyer(effect) + { + assert(underlyer); + } + ~ClaudioWrapper() = default; + + bool activate(double sampleRate, uint32_t minFrameCount, + uint32_t maxFrameCount) noexcept override + { + underlyer->setSampleRate(sampleRate); + return true; + } + + protected: + static constexpr int paramOff = 10472; + bool implementsParams() const noexcept override { return true; } + bool isValidParamId(clap_id paramId) const noexcept override + { + return paramId >= paramOff && paramId < paramsCount() + paramOff; + } + uint32_t paramsCount() const noexcept override { return underlyer->numParams; } + bool paramsInfo(uint32_t paramIndex, clap_param_info *info) const noexcept override + { + if (paramIndex > paramsCount()) + return false; + + info->flags = CLAP_PARAM_IS_AUTOMATABLE; + info->id = paramIndex + paramOff; + char tmp[CLAP_NAME_SIZE]; + underlyer->getParameterName(paramIndex, tmp); + strncpy(info->name, tmp, CLAP_NAME_SIZE); + info->module[0] = 0; + info->min_value = 0; + info->max_value = 1; + info->default_value = underlyer->getParameter(paramIndex); + return true; + } + bool paramsValue(clap_id paramId, double *value) noexcept override + { + *value = underlyer->getParameter(paramId - paramOff); + return true; + } + bool paramsValueToText(clap_id paramId, double value, char *display, + uint32_t size) noexcept override + { + // I know this isn't right + underlyer->getParameterDisplay(paramId - paramOff, display); + return true; + } + + bool implementsAudioPorts() const noexcept override { return true; } + uint32_t audioPortsCount(bool isInput) const noexcept override + { + if (isInput) return underlyer->nin; + return underlyer->nout; + } + bool audioPortsInfo(uint32_t index, bool isInput, + clap_audio_port_info *info) const noexcept override + { + info->id = isInput ? 2112 : 90210; + strncpy(info->name, "main", sizeof(info->name)); + info->flags = CLAP_AUDIO_PORT_IS_MAIN; + info->channel_count = 2; + info->port_type = CLAP_PORT_STEREO; + return true; + } + + clap_process_status process(const clap_process *process) noexcept override + { + return Plugin::process(process); + } +}; + +static const clap_plugin *clap_create_plugin(const clap_plugin_factory *f, const clap_host *host, + const char *plugin_id) +{ + auto [fx, desc] = claudio_get_aeffInstance(host, plugin_id); + std::cout << "FX = " << fx << " plugin_id = " << plugin_id << std::endl; + + auto wr = new ClaudioWrapper(host, desc, fx); + return wr->clapPlugin(); +} + +const CLAP_EXPORT struct clap_plugin_factory claudio_factory = { + claudio_get_plugin_count, + claudio_get_plugin_descriptor, + clap_create_plugin, +}; + +static const void *get_factory(const char *factory_id) { return &claudio_factory; } +// clap_init and clap_deinit are required to be fast, but we have nothing we need to do here +bool clap_init(const char *p) { return true; } +void clap_deinit() {} -int foo() +extern "C" { - claudio_GalacticCreateEffectInstance(nullptr); - return 0; -} \ No newline at end of file + // clang-format off +const CLAP_EXPORT struct clap_plugin_entry clap_entry = { + CLAP_VERSION, + clap_init, + clap_deinit, + get_factory +}; + // clang-format on +} diff --git a/src/claudio_configured.cpp b/src/claudio_configured.cpp deleted file mode 100644 index e7b56e6..0000000 --- a/src/claudio_configured.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// -// Created by Paul Walker on 6/19/22. -// - -#include "claudio_configured.hxx" - -#include -#include -#include - - -static const clap_plugin *clap_create_plugin(const clap_plugin_factory *f, const clap_host *host, - const char *plugin_id) -{ - auto fx = claudio_get_aeffInstance(host, plugin_id); - std::cout << "FX = " << fx << " plugin_id = " << plugin_id << std::endl; - - return nullptr; -} - -const CLAP_EXPORT struct clap_plugin_factory claudio_factory = { - claudio_get_plugin_count, - claudio_get_plugin_descriptor, - clap_create_plugin, -}; - -static const void *get_factory(const char *factory_id) { return &claudio_factory; } - -// clap_init and clap_deinit are required to be fast, but we have nothing we need to do here -bool clap_init(const char *p) { return true; } - -void clap_deinit() {} - -extern "C" -{ -// clang-format off -const CLAP_EXPORT struct clap_plugin_entry clap_entry = { - CLAP_VERSION, - clap_init, - clap_deinit, - get_factory -}; -// clang-format on -} \ No newline at end of file diff --git a/src/individual_claudio.in.cpp b/src/individual_claudio.in.cpp index 9557b50..6d00adf 100644 --- a/src/individual_claudio.in.cpp +++ b/src/individual_claudio.in.cpp @@ -2,17 +2,19 @@ // Created by Paul Walker on 6/19/22. // +// clang-format off #include "audioeffectx.h" #include "claudio_@AIRWIN_NAME@.h" const char *@AIRWIN_NAME@_features[] = {CLAP_PLUGIN_FEATURE_AUDIO_EFFECT, nullptr}; -clap_plugin_descriptor claudio_@AIRWIN_NAME@_desc = {CLAP_VERSION, - "unofficial.com.airwindows.@AIRWIN_NAME@", // change this change the cmake generatortoo - "Airwindows @AIRWIN_NAME@ (Unofficial)", - "Unsupported", - "https://airwindows.com", - "", - "", - "1.0.0", - "The airwindows effect @AIRWIN_NAME@.", - @AIRWIN_NAME@_features}; \ No newline at end of file +clap_plugin_descriptor claudio_@AIRWIN_NAME@_desc = { + CLAP_VERSION, + "unofficial.com.airwindows.@AIRWIN_NAME@", // change this change the cmake generatortoo + "Airwindows @AIRWIN_NAME@ (Unofficial)", + "Unsupported", + "https://airwindows.com", + "", + "", + "1.0.0", + "The airwindows effect @AIRWIN_NAME@.", + @AIRWIN_NAME@_features}; \ No newline at end of file diff --git a/src/individual_claudio.in.h b/src/individual_claudio.in.h index 0afec62..3f7248f 100644 --- a/src/individual_claudio.in.h +++ b/src/individual_claudio.in.h @@ -2,13 +2,14 @@ // Created by Paul Walker on 6/19/22. // +// clang-format off #ifndef CLAUDIO_EFFECT_@AIRWIN_NAME@_X_INDIVIDUAL_CLAUDIO_IN_H #define CLAUDIO_EFFECT_@AIRWIN_NAME@_X_INDIVIDUAL_CLAUDIO_IN_H #include "audioeffectx.h" #include -extern AudioEffect * @CREATE_FN@ (audioMasterCallback audioMaster); +extern AudioEffect *@CREATE_FN@ (audioMasterCallback audioMaster); extern clap_plugin_descriptor claudio_@AIRWIN_NAME@_desc; -#endif //CLAUDIO_EFFECT_X_INDIVIDUAL_CLAUDIO_IN_H +#endif // CLAUDIO_EFFECT_X_INDIVIDUAL_CLAUDIO_IN_H