From 3b6a621d8e08b65487f82e39e2614112c203e565 Mon Sep 17 00:00:00 2001 From: Stefano D'Angelo Date: Wed, 17 Jan 2024 11:24:40 +0100 Subject: [PATCH] fixes + adjustments + doc --- notes | 45 +++++++++++++++++++++++++++-- templates/lv2/src/.lv2.c.swp | Bin 24576 -> 0 bytes templates/lv2/src/lv2.c | 5 +++- templates/vst3/src/data.h | 2 +- templates/vst3/src/vst3.c | 53 +++++++++++++++++++++++++++++++++++ test/product.json | 9 ------ 6 files changed, 100 insertions(+), 14 deletions(-) delete mode 100644 templates/lv2/src/.lv2.c.swp diff --git a/notes b/notes index fefd908..7f6d9d0 100644 --- a/notes +++ b/notes @@ -23,7 +23,46 @@ product { bundleName: VST3: plugin folder name, plugin .dll name, Info.plist LV2: plugin folder name, plugin .dll name, manifest.ttl plugin lv2:binary - buses: ... + buses: [ + { + name: + bus name string, required + VST3: BusInfo name + LV2: manifest.ttl lv2:port lv2:name + shortName: + bus short name string, required + VST3: not used + LV2: manifest.ttl lv2:port lv2:shortName + direction: + "input" or "output", required + VST3: BusInfo flags - lots of implications + LV2: manifest.ttl lv2:port a - lots of implications + type: + "audio" or "midi", required + VST3: BusInfo mediaType, ParameterInfo (channel pressure, pitch bend params) - lots of implications + LV2: lots of implications everywhere + channels: + "mono" or "stereo", audio type only, required + VST3: BusInfo channelCount, plugin get/set bus arrangements + LV2: manifest.ttl lv2:port - lots of implications + sidechain: + bus is not part of main audio path (sidechain)? boolean, default false + VST3: BusInfo busType + LV2: manifest.ttl lv2:port lv2:portProperty lv2:isSideChain + cv: + bus is control voltage audio-rate? boolean, audio type only, default false + VST3: BusInfo flags + LV2: manifest.ttl lv2:port a lv2:CVPort + control: + bus is the "primary control channel" (send cmds, receive responses)? boolean, midi type only, default false + VST3: not used + LV2: manifest.ttl lv2:port lv2:designation lv2:control + optional: + bus is optionally connected? boolean, default false + VST3: BusInfo flags, plugin initialize, activate bus, set active + LV2: manifest.ttl lv2:port lv2:portProperty lv2:connectionOptional + } + ] parameters: [ { name: @@ -36,8 +75,8 @@ product { LV2: manifest.ttl lv2:port lv2:shortName direction: "input" or "output", required - VST3: ParameterInfo flags - LV2: manifest.ttl lv2:port a + VST3: ParameterInfo flags - lots of implications + LV2: manifest.ttl lv2:port a - lots of implications isBypass: parameter is bypass/enabled? boolean - lots of implications, default false VST3: ParameterInfo, controller get/set parameter/state diff --git a/templates/lv2/src/.lv2.c.swp b/templates/lv2/src/.lv2.c.swp deleted file mode 100644 index a8c32bbc8fd8303c454794f8364ea75dd02da7bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24576 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 oi^rNomFWgcDr4|bVMRd$&ULgBd3lYesGClbwv; 0 - for (size_t j = 0; j < DATA_PRODUCT_MIDI_INPUTS_N; j++) + for (size_t j = 0; j < DATA_PRODUCT_MIDI_INPUTS_N; j++) { + if (i->x_midi[j] == NULL) + continue; LV2_ATOM_SEQUENCE_FOREACH(i->x_midi[j], ev) { if (ev->body.type == i->uri_midi_MidiEvent) { const uint8_t * const msg = (const uint8_t *)(ev + 1); @@ -236,6 +238,7 @@ static void run(LV2_Handle instance, uint32_t sample_count) { } } } + } #endif plugin_process(&i->p, i->x, i->y, sample_count); diff --git a/templates/vst3/src/data.h b/templates/vst3/src/data.h index f311260..1e9f1a0 100644 --- a/templates/vst3/src/data.h +++ b/templates/vst3/src/data.h @@ -174,5 +174,5 @@ static struct { #endif {{?it.product.parameters.find(x => x.isLatency)}} -# define DATA_PARAM_LATENCY_INDEX {{=it.product.parameters.find(x => x.isLatency).paramIndex}} +#define DATA_PARAM_LATENCY_INDEX {{=it.product.parameters.find(x => x.isLatency).paramIndex}} {{?}} diff --git a/templates/vst3/src/vst3.c b/templates/vst3/src/vst3.c index 6dd0f4e..cd342f5 100644 --- a/templates/vst3/src/vst3.c +++ b/templates/vst3/src/vst3.c @@ -56,6 +56,18 @@ typedef struct pluginInstance { #endif #if DATA_PRODUCT_CHANNELS_AUDIO_OUTPUT_N > 0 float * outputs[DATA_PRODUCT_CHANNELS_AUDIO_INPUT_N]; +#endif +#if DATA_PRODUCT_BUSES_AUDIO_INPUT_N > 0 + char inputsActive[DATA_PRODUCT_BUSES_AUDIO_INPUT_N]; +#endif +#if DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N > 0 + char outputsActive[DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N]; +#endif +#if DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0 + char midiInputsActive[DATA_PRODUCT_BUSES_MIDI_INPUT_N]; +#endif +#if DATA_PRODUCT_BUSES_MIDI_OUTPUT_N > 0 + char midiOutputsActive[DATA_PRODUCT_BUSES_MIDI_OUTPUT_N]; #endif void * mem; } pluginInstance; @@ -130,6 +142,22 @@ static Steinberg_tresult pluginInitialize(void *thisInterface, struct Steinberg_ if (!(parameterInfo[i].flags & Steinberg_Vst_ParameterInfo_ParameterFlags_kIsReadOnly)) plugin_set_parameter(&p->p, parameterData[i].index, parameterData[i].def); } +#endif +#if DATA_PRODUCT_BUSES_AUDIO_INPUT_N > 0 + for (size_t i = 0; i < DATA_PRODUCT_BUSES_AUDIO_INPUT_N; i++) + p->inputsActive[i] = 0; +#endif +#if DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N > 0 + for (size_t i = 0; i < DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N; i++) + p->outputsActive[i] = 0; +#endif +#if DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0 + for (size_t i = 0; i < DATA_PRODUCT_BUSES_MIDI_INPUT_N; i++) + p->midiInputsActive[i] = 0; +#endif +#if DATA_PRODUCT_BUSES_MIDI_OUTPUT_N > 0 + for (size_t i = 0; i < DATA_PRODUCT_BUSES_MIDI_OUTPUT_N; i++) + p->midiOutputsActive[i] = 0; #endif p->mem = NULL; return Steinberg_kResultOk; @@ -224,17 +252,20 @@ static Steinberg_tresult pluginActivateBus(void* thisInterface, Steinberg_Vst_Me TRACE("plugin activate bus\n"); if (index < 0) return Steinberg_kInvalidArgument; + pluginInstance *p = (pluginInstance *)((char *)thisInterface - offsetof(pluginInstance, vtblIComponent)); if (type == Steinberg_Vst_MediaTypes_kAudio) { if (dir == Steinberg_Vst_BusDirections_kInput) { #if DATA_PRODUCT_BUSES_AUDIO_INPUT_N > 0 if (index >= DATA_PRODUCT_BUSES_AUDIO_INPUT_N) return Steinberg_kInvalidArgument; + p->inputsActive[index] = state; return Steinberg_kResultTrue; #endif } else if (dir == Steinberg_Vst_BusDirections_kOutput) { #if DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N > 0 if (index >= DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N) return Steinberg_kInvalidArgument; + p->outputsActive[index] = state; return Steinberg_kResultTrue; #endif } @@ -243,12 +274,14 @@ static Steinberg_tresult pluginActivateBus(void* thisInterface, Steinberg_Vst_Me #if DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0 if (index >= DATA_PRODUCT_BUSES_MIDI_INPUT_N) return Steinberg_kInvalidArgument; + p->midiInputsActive[index] = state; return Steinberg_kResultTrue; #endif } else if (dir == Steinberg_Vst_BusDirections_kOutput) { #if DATA_PRODUCT_BUSES_MIDI_OUTPUT_N > 0 if (index >= DATA_PRODUCT_BUSES_MIDI_OUTPUT_N) return Steinberg_kInvalidArgument; + p->midiOutputsActive[index] = state; return Steinberg_kResultTrue; #endif } @@ -264,6 +297,26 @@ static Steinberg_tresult pluginSetActive(void* thisInterface, Steinberg_TBool st p->mem = NULL; } if (state) { +#if DATA_PRODUCT_BUSES_AUDIO_INPUT_N > 0 + for (size_t i = 0; i < DATA_PRODUCT_BUSES_AUDIO_INPUT_N; i++) + if (!p->inputsActive[i] && (busInfoAudioInput[i].flags & Steinberg_Vst_BusInfo_BusFlags_kDefaultActive)) + return Steinberg_kResultFalse; +#endif +#if DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N > 0 + for (size_t i = 0; i < DATA_PRODUCT_BUSES_AUDIO_OUTPUT_N; i++) + if (!p->outputsActive[i] && (busInfoAudioOutput[i].flags & Steinberg_Vst_BusInfo_BusFlags_kDefaultActive)) + return Steinberg_kResultFalse; +#endif +#if DATA_PRODUCT_BUSES_MIDI_INPUT_N > 0 + for (size_t i = 0; i < DATA_PRODUCT_BUSES_MIDI_INPUT_N; i++) + if (!p->midiInputsActive[i] && (busInfoMidiInput[i].flags & Steinberg_Vst_BusInfo_BusFlags_kDefaultActive)) + return Steinberg_kResultFalse; +#endif +#if DATA_PRODUCT_BUSES_MIDI_OUTPUT_N > 0 + for (size_t i = 0; i < DATA_PRODUCT_BUSES_MIDI_OUTPUT_N; i++) + if (!p->midiOutputsActive[i] && (busInfoMidiOutput[i].flags & Steinberg_Vst_BusInfo_BusFlags_kDefaultActive)) + return Steinberg_kResultFalse; +#endif plugin_set_sample_rate(&p->p, p->sampleRate); size_t req = plugin_mem_req(&p->p); if (req != 0) { diff --git a/test/product.json b/test/product.json index 2aea107..3bf1fd1 100644 --- a/test/product.json +++ b/test/product.json @@ -33,15 +33,6 @@ "sidechain": true, "control": true, "optional": true - }, - { - "type": "midi", - "direction": "output", - "name": "MIDI output", - "shortName": "MIDI output", - "sidechain": true, - "control": true, - "optional": true } ], "parameters": [