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 a8c32bb..0000000 Binary files a/templates/lv2/src/.lv2.c.swp and /dev/null differ diff --git a/templates/lv2/src/lv2.c b/templates/lv2/src/lv2.c index 2cd2390..a46f40c 100644 --- a/templates/lv2/src/lv2.c +++ b/templates/lv2/src/lv2.c @@ -199,7 +199,9 @@ static void run(LV2_Handle instance, uint32_t sample_count) { // from https://lv2plug.in/book #if DATA_PRODUCT_MIDI_INPUTS_N > 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": [