initial import
This commit is contained in:
commit
81cdabbfe2
5
LICENSE
Normal file
5
LICENSE
Normal file
@ -0,0 +1,5 @@
|
||||
Copyright 2023 Stefano D'Angelo
|
||||
|
||||
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.
|
8
TODO
Normal file
8
TODO
Normal file
@ -0,0 +1,8 @@
|
||||
* recursive object merge in tibia
|
||||
* copyrights
|
||||
* dotjs error on undefined or JSON schema
|
||||
* type audio + sidechain + cv... to think about
|
||||
* check all return codes and algos wrt official impl
|
||||
* escape string and max lengths
|
||||
* printf -> trace
|
||||
* EXPORT symbols, visibility hidden
|
12
templates/vst3/data/Info.plist
Normal file
12
templates/vst3/data/Info.plist
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleName</key>
|
||||
<string>{{=it.plugin.bundleName}}</string>
|
||||
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>{{=it.plugin.bundleName}}</string>
|
||||
|
||||
</dict>
|
||||
</plist>
|
1
templates/vst3/data/PkgInfo
Normal file
1
templates/vst3/data/PkgInfo
Normal file
@ -0,0 +1 @@
|
||||
BNDL????
|
2
templates/vst3/data/desktop.ini
Normal file
2
templates/vst3/data/desktop.ini
Normal file
@ -0,0 +1,2 @@
|
||||
[.ShellClassInfo]
|
||||
IconResource=Plugin.ico,0
|
25
templates/vst3/make/Makefile
Normal file
25
templates/vst3/make/Makefile
Normal file
@ -0,0 +1,25 @@
|
||||
include vars.mk
|
||||
|
||||
CC = gcc
|
||||
CFLAGS = -fPIC -Wall -Wpedantic -Wextra -Wno-unused-parameter
|
||||
|
||||
BUNDLE_DIR = ${BUNDLE_NAME}.vst3
|
||||
|
||||
SO_DIR := $(shell uname -m)-linux
|
||||
SO_FILE := ${SO_DIR}/${BUNDLE_NAME}.so
|
||||
|
||||
all: build/${BUNDLE_DIR}/Contents/Info.plist build/${BUNDLE_DIR}/Contents/${SO_FILE}
|
||||
|
||||
build/${BUNDLE_DIR}/Contents/Info.plist: data/Info.plist | build/${BUNDLE_DIR}/Contents
|
||||
cp $^ $@
|
||||
|
||||
build/${BUNDLE_DIR}/Contents/${SO_FILE}: src/vst3.c | build/${BUNDLE_DIR}/Contents/${SO_DIR}
|
||||
${CC} $^ -o $@ ${CFLAGS} -I${VST3_C_API_DIR} -shared
|
||||
|
||||
build/${BUNDLE_DIR}/Contents build/${BUNDLE_DIR}/Contents/${SO_DIR}:
|
||||
mkdir -p $@
|
||||
|
||||
clean:
|
||||
rm -fr build
|
||||
|
||||
.PHONY: clean
|
2
templates/vst3/make/vars.mk
Normal file
2
templates/vst3/make/vars.mk
Normal file
@ -0,0 +1,2 @@
|
||||
BUNDLE_NAME := {{=it.plugin.bundleName}}
|
||||
VST3_C_API_DIR := ../../vst3_c_api
|
102
templates/vst3/src/data.h
Normal file
102
templates/vst3/src/data.h
Normal file
@ -0,0 +1,102 @@
|
||||
#define DATA_COMPANY_NAME "{{=it.company.name}}"
|
||||
#define DATA_COMPANY_URL "{{=it.company.url}}"
|
||||
#define DATA_COMPANY_EMAIL "{{=it.company.email}}"
|
||||
|
||||
#define DATA_PLUGIN_NAME "{{=it.plugin.name}}"
|
||||
#define DATA_PLUGIN_VERSION "{{=it.plugin.version}}"
|
||||
|
||||
#define DATA_VST3_PLUGIN_CID_1 0x{{=it.vst3.plugin.cid.substring(0, 8)}}
|
||||
#define DATA_VST3_PLUGIN_CID_2 0x{{=it.vst3.plugin.cid.substring(8, 16)}}
|
||||
#define DATA_VST3_PLUGIN_CID_3 0x{{=it.vst3.plugin.cid.substring(16, 24)}}
|
||||
#define DATA_VST3_PLUGIN_CID_4 0x{{=it.vst3.plugin.cid.substring(24, 32)}}
|
||||
|
||||
#define DATA_VST3_CONTROLLER_CID_1 0x{{=it.vst3.controller.cid.substring(0, 8)}}
|
||||
#define DATA_VST3_CONTROLLER_CID_2 0x{{=it.vst3.controller.cid.substring(8, 16)}}
|
||||
#define DATA_VST3_CONTROLLER_CID_3 0x{{=it.vst3.controller.cid.substring(16, 24)}}
|
||||
#define DATA_VST3_CONTROLLER_CID_4 0x{{=it.vst3.controller.cid.substring(24, 32)}}
|
||||
|
||||
#define DATA_VST3_SUBCATEGORY "{{=it.vst3.subCategory}}"
|
||||
|
||||
#define DATA_PLUGIN_BUSES_AUDIO_INPUT_N {{=it.plugin.buses.filter(x => x.type == "audio" && x.direction == "input").length}}
|
||||
#define DATA_PLUGIN_BUSES_AUDIO_OUTPUT_N {{=it.plugin.buses.filter(x => x.type == "audio" && x.direction == "output").length}}
|
||||
#define DATA_PLUGIN_BUSES_EVENT_INPUT_N {{=it.plugin.buses.filter(x => x.type == "event" && x.direction == "input").length}}
|
||||
#define DATA_PLUGIN_BUSES_EVENT_OUTPUT_N {{=it.plugin.buses.filter(x => x.type == "event" && x.direction == "output").length}}
|
||||
|
||||
#if DATA_PLUGIN_BUSES_AUDIO_INPUT_N > 0
|
||||
static struct Steinberg_Vst_BusInfo busInfoAudioInput[DATA_PLUGIN_BUSES_AUDIO_INPUT_N] = {
|
||||
{{~it.plugin.buses.filter(x => x.type == "audio" && x.direction == "input") :b}}
|
||||
{
|
||||
/* .mediaType = */ Steinberg_Vst_MediaTypes_kAudio,
|
||||
/* .direction = */ Steinberg_Vst_BusDirections_kInput,
|
||||
/* .channelCount = */ {{=b.channels}},
|
||||
/* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .busType = */ {{?b.aux}}Steinberg_Vst_BusTypes_kAux{{??}}Steinberg_Vst_BusTypes_kMain{{?}},
|
||||
/* .flags = */ {{?b.cv}}Steinberg_Vst_BusInfo_BusFlags_kIsControlVoltage{{??}}Steinberg_Vst_BusInfo_BusFlags_kDefaultActive{{?}}
|
||||
},
|
||||
{{~}}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if DATA_PLUGIN_BUSES_AUDIO_OUTPUT_N > 0
|
||||
static struct Steinberg_Vst_BusInfo busInfoAudioOutput[DATA_PLUGIN_BUSES_AUDIO_OUTPUT_N] = {
|
||||
{{~it.plugin.buses.filter(x => x.type == "audio" && x.direction == "output") :b}}
|
||||
{
|
||||
/* .mediaType = */ Steinberg_Vst_MediaTypes_kAudio,
|
||||
/* .direction = */ Steinberg_Vst_BusDirections_kOutput,
|
||||
/* .channelCount = */ {{=b.channels}},
|
||||
/* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .busType = */ {{?b.aux}}Steinberg_Vst_BusTypes_kAux{{??}}Steinberg_Vst_BusTypes_kMain{{?}},
|
||||
/* .flags = */ {{?b.cv}}Steinberg_Vst_BusInfo_BusFlags_kIsControlVoltage{{??}}Steinberg_Vst_BusInfo_BusFlags_kDefaultActive{{?}}
|
||||
},
|
||||
{{~}}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if DATA_PLUGIN_BUSES_EVENT_INPUT_N > 0
|
||||
static struct Steinberg_Vst_BusInfo busInfoEventInput[DATA_PLUGIN_BUSES_EVENT_INPUT_N] = {
|
||||
{{~it.plugin.buses.filter(x => x.type == "event" && x.direction == "input") :b}}
|
||||
{
|
||||
/* .mediaType = */ Steinberg_Vst_MediaTypes_kEvent,
|
||||
/* .direction = */ Steinberg_Vst_BusDirections_kInput,
|
||||
/* .channelCount = */ {{=b.channels}},
|
||||
/* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .busType = */ Steinberg_Vst_BusTypes_kMain,
|
||||
/* .flags = */ Steinberg_Vst_BusInfo_BusFlags_kDefaultActive
|
||||
},
|
||||
{{~}}
|
||||
};
|
||||
#endif
|
||||
|
||||
#if DATA_PLUGIN_BUSES_EVENT_OUTPUT_N > 0
|
||||
static struct Steinberg_Vst_BusInfo busInfoAudioInput[DATA_PLUGIN_BUSES_EVENT_OUTPUT_N] = {
|
||||
{{~it.plugin.buses.filter(x => x.type == "event" && x.direction == "output") :b}}
|
||||
{
|
||||
/* .mediaType = */ Steinberg_Vst_MediaTypes_kEvent,
|
||||
/* .direction = */ Steinberg_Vst_BusDirections_kOutput,
|
||||
/* .channelCount = */ {{=b.channels}},
|
||||
/* .name = */ { {{~Array.from(b.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .busType = */ Steinberg_Vst_BusTypes_kMain,
|
||||
/* .flags = */ Steinberg_Vst_BusInfo_BusFlags_kDefaultActive
|
||||
},
|
||||
{{~}}
|
||||
};
|
||||
#endif
|
||||
|
||||
#define DATA_PLUGIN_PARAMETERS_N {{=it.plugin.parameters.length}}
|
||||
|
||||
#if DATA_PLUGIN_PARAMETERS_N > 0
|
||||
static struct Steinberg_Vst_ParameterInfo parameterInfo[DATA_PLUGIN_PARAMETERS_N] = {
|
||||
{{~it.plugin.parameters :p:i}}
|
||||
{
|
||||
/* .id = */ {{=i}},
|
||||
/* .title = */ { {{~Array.from(p.name) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .shortTitle = */ { {{~Array.from(p.shortName) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .units = */ { {{~Array.from(p.units) :c}}0x{{=c.charCodeAt(0).toString(16)}}, {{~}}0 },
|
||||
/* .stepCount = */ {{=p.steps}},
|
||||
/* .defaultNormalizedValue = */ {{=p.defaultValue}},
|
||||
/* .unitId = */ 0,
|
||||
/* .flags = */ {{?p.isBypass}}Steinberg_Vst_ParameterInfo_ParameterFlags_kIsBypass | {{?}}{{?p.direction == "input"}}Steinberg_Vst_ParameterInfo_ParameterFlags_kCanAutomate{{??}}Steinberg_Vst_ParameterInfo_ParameterFlags_kIsReadOnly{{?}}
|
||||
},
|
||||
{{~}}
|
||||
};
|
||||
#endif
|
3
templates/vst3/src/plugin.h
Normal file
3
templates/vst3/src/plugin.h
Normal file
@ -0,0 +1,3 @@
|
||||
typedef struct plugin {
|
||||
char abc;
|
||||
} plugin;
|
800
templates/vst3/src/vst3.c
Normal file
800
templates/vst3/src/vst3.c
Normal file
@ -0,0 +1,800 @@
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "vst3_c_api.h"
|
||||
#include "data.h"
|
||||
#include "plugin.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
// COM in C doc:
|
||||
// https://github.com/rubberduck-vba/Rubberduck/wiki/COM-in-plain-C
|
||||
// https://devblogs.microsoft.com/oldnewthing/20040205-00/?p=40733
|
||||
|
||||
#ifdef NDEBUG
|
||||
# define TRACE(...) /* do nothing */
|
||||
#else
|
||||
# define TRACE(...) printf(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
static const Steinberg_TUID pluginCID = SMTG_INLINE_UID(DATA_VST3_PLUGIN_CID_1, DATA_VST3_PLUGIN_CID_2, DATA_VST3_PLUGIN_CID_3, DATA_VST3_PLUGIN_CID_4);
|
||||
static const Steinberg_TUID controllerCID = SMTG_INLINE_UID(DATA_VST3_CONTROLLER_CID_1, DATA_VST3_CONTROLLER_CID_2, DATA_VST3_CONTROLLER_CID_3, DATA_VST3_CONTROLLER_CID_4);
|
||||
|
||||
typedef struct pluginInstance {
|
||||
Steinberg_Vst_IComponentVtbl * vtblIComponent;
|
||||
Steinberg_Vst_IAudioProcessorVtbl * vtblIAudioProcessor;
|
||||
Steinberg_Vst_IProcessContextRequirementsVtbl * vtblIProcessContextRequirements;
|
||||
Steinberg_uint32 refs;
|
||||
Steinberg_FUnknown * context;
|
||||
plugin p;
|
||||
} pluginInstance;
|
||||
|
||||
static Steinberg_Vst_IComponentVtbl pluginVtblIComponent;
|
||||
static Steinberg_Vst_IAudioProcessorVtbl pluginVtblIAudioProcessor;
|
||||
|
||||
static Steinberg_tresult pluginQueryInterface(pluginInstance *p, const Steinberg_TUID iid, void ** obj) {
|
||||
// This seems to violate the way multiple inheritance should work in COM, but hosts like it, so what do I know...
|
||||
size_t offset;
|
||||
if (memcmp(iid, Steinberg_FUnknown_iid, sizeof(Steinberg_TUID)) == 0
|
||||
|| memcmp(iid, Steinberg_IPluginBase_iid, sizeof(Steinberg_TUID)) == 0
|
||||
|| memcmp(iid, Steinberg_Vst_IComponent_iid, sizeof(Steinberg_TUID)) == 0)
|
||||
offset = offsetof(pluginInstance, vtblIComponent);
|
||||
else if (memcmp(iid, Steinberg_Vst_IAudioProcessor_iid, sizeof(Steinberg_TUID)) == 0)
|
||||
offset = offsetof(pluginInstance, vtblIAudioProcessor);
|
||||
else if (memcmp(iid, Steinberg_Vst_IProcessContextRequirements_iid, sizeof(Steinberg_TUID)) == 0)
|
||||
offset = offsetof(pluginInstance, vtblIProcessContextRequirements);
|
||||
else {
|
||||
TRACE(" not supported\n");
|
||||
*obj = NULL;
|
||||
return Steinberg_kNoInterface;
|
||||
}
|
||||
*obj = (void *)((char *)p + offset);
|
||||
p->refs++;
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_uint32 pluginAddRef(pluginInstance *p) {
|
||||
p->refs++;
|
||||
return p->refs;
|
||||
}
|
||||
|
||||
static Steinberg_uint32 pluginRelease(pluginInstance *p) {
|
||||
p->refs--;
|
||||
if (p->refs == 0) {
|
||||
TRACE(" free %p\n", (void *)p);
|
||||
free(p);
|
||||
return 0;
|
||||
}
|
||||
return p->refs;
|
||||
}
|
||||
|
||||
static Steinberg_tresult pluginIComponentQueryInterface(void *thisInterface, const Steinberg_TUID iid, void ** obj) {
|
||||
TRACE("plugin IComponent queryInterface %p\n", thisInterface);
|
||||
return pluginQueryInterface((pluginInstance *)((char *)thisInterface - offsetof(pluginInstance, vtblIComponent)), iid, obj);
|
||||
}
|
||||
|
||||
static Steinberg_uint32 pluginIComponentAddRef(void *thisInterface) {
|
||||
TRACE("plugin IComponent addRef %p\n", thisInterface);
|
||||
return pluginAddRef((pluginInstance *)((char *)thisInterface - offsetof(pluginInstance, vtblIComponent)));
|
||||
}
|
||||
|
||||
static Steinberg_uint32 pluginIComponentRelease(void *thisInterface) {
|
||||
TRACE("plugin IComponent release %p\n", thisInterface);
|
||||
return pluginRelease((pluginInstance *)((char *)thisInterface - offsetof(pluginInstance, vtblIComponent)));
|
||||
}
|
||||
|
||||
static Steinberg_tresult pluginInitialize(void *thisInterface, struct Steinberg_FUnknown *context) {
|
||||
TRACE("plugin initialize\n");
|
||||
pluginInstance *p = (pluginInstance *)thisInterface;
|
||||
if (p->context != NULL)
|
||||
return Steinberg_kResultFalse;
|
||||
p->context = context;
|
||||
//TBD
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_tresult pluginTerminate(void *thisInterface) {
|
||||
TRACE("plugin terminate\n");
|
||||
pluginInstance *p = (pluginInstance *)thisInterface;
|
||||
p->context = NULL;
|
||||
//TBD
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_tresult pluginGetControllerClassId(void *thisInterface, Steinberg_TUID classId) {
|
||||
TRACE("plugin get controller class id %p %p\n", thisInterface, classId);
|
||||
if (classId != NULL) {
|
||||
memcpy(classId, controllerCID, sizeof(Steinberg_TUID));
|
||||
return Steinberg_kResultTrue;
|
||||
}
|
||||
return Steinberg_kResultFalse;
|
||||
}
|
||||
|
||||
static Steinberg_tresult pluginSetIoMode(void *thisInterface, Steinberg_Vst_IoMode mode) {
|
||||
TRACE("plugin set io mode\n");
|
||||
return Steinberg_kNotImplemented;
|
||||
}
|
||||
|
||||
static Steinberg_int32 pluginGetBusCount(void *thisInterface, Steinberg_Vst_MediaType type, Steinberg_Vst_BusDirection dir) {
|
||||
TRACE("plugin get bus count\n");
|
||||
if (type == Steinberg_Vst_MediaTypes_kAudio) {
|
||||
if (dir == Steinberg_Vst_BusDirections_kInput)
|
||||
return DATA_PLUGIN_BUSES_AUDIO_INPUT_N;
|
||||
else if (dir == Steinberg_Vst_BusDirections_kOutput)
|
||||
return DATA_PLUGIN_BUSES_AUDIO_OUTPUT_N;
|
||||
} else if (type == Steinberg_Vst_MediaTypes_kEvent) {
|
||||
if (dir == Steinberg_Vst_BusDirections_kInput)
|
||||
return DATA_PLUGIN_BUSES_EVENT_INPUT_N;
|
||||
else if (dir == Steinberg_Vst_BusDirections_kOutput)
|
||||
return DATA_PLUGIN_BUSES_EVENT_OUTPUT_N;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Steinberg_tresult pluginGetBusInfo(void* thisInterface, Steinberg_Vst_MediaType type, Steinberg_Vst_BusDirection dir, Steinberg_int32 index, struct Steinberg_Vst_BusInfo* bus) {
|
||||
TRACE("plugin get bus info\n");
|
||||
if (index < 0)
|
||||
return Steinberg_kInvalidArgument;
|
||||
if (type == Steinberg_Vst_MediaTypes_kAudio) {
|
||||
if (dir == Steinberg_Vst_BusDirections_kInput) {
|
||||
#if DATA_PLUGIN_BUSES_AUDIO_INPUT_N > 0
|
||||
if (index >= DATA_PLUGIN_BUSES_AUDIO_INPUT_N)
|
||||
return Steinberg_kInvalidArgument;
|
||||
*bus = busInfoAudioInput[index];
|
||||
return Steinberg_kResultTrue;
|
||||
#endif
|
||||
} else if (dir == Steinberg_Vst_BusDirections_kOutput) {
|
||||
#if DATA_PLUGIN_BUSES_AUDIO_OUTPUT_N > 0
|
||||
if (index >= DATA_PLUGIN_BUSES_AUDIO_OUTPUT_N)
|
||||
return Steinberg_kInvalidArgument;
|
||||
*bus = busInfoAudioOutput[index];
|
||||
return Steinberg_kResultTrue;
|
||||
#endif
|
||||
}
|
||||
} else if (type == Steinberg_Vst_MediaTypes_kEvent) {
|
||||
if (dir == Steinberg_Vst_BusDirections_kInput) {
|
||||
#if DATA_PLUGIN_BUSES_EVENT_INPUT_N > 0
|
||||
if (index >= DATA_PLUGIN_BUSES_AUDIO_INPUT_N)
|
||||
return Steinberg_kInvalidArgument;
|
||||
*bus = busInfoEventInput[index];
|
||||
return Steinberg_kResultTrue;
|
||||
#endif
|
||||
} else if (dir == Steinberg_Vst_BusDirections_kOutput) {
|
||||
#if DATA_PLUGIN_BUSES_EVENT_OUTPUT_N > 0
|
||||
if (index >= DATA_PLUGIN_BUSES_AUDIO_OUTPUT_N)
|
||||
return Steinberg_kInvalidArgument;
|
||||
*bus = busInfoEventOutput[index];
|
||||
return Steinberg_kResultTrue;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return Steinberg_kInvalidArgument;
|
||||
}
|
||||
|
||||
static Steinberg_tresult pluginGetRoutingInfo(void* thisInterface, struct Steinberg_Vst_RoutingInfo* inInfo, struct Steinberg_Vst_RoutingInfo* outInfo) {
|
||||
TRACE("plugin get routing info\n");
|
||||
return Steinberg_kNotImplemented;
|
||||
}
|
||||
|
||||
static Steinberg_tresult pluginActivateBus(void* thisInterface, Steinberg_Vst_MediaType type, Steinberg_Vst_BusDirection dir, Steinberg_int32 index, Steinberg_TBool state) {
|
||||
TRACE("plugin activate bus\n");
|
||||
if (index < 0)
|
||||
return Steinberg_kInvalidArgument;
|
||||
if (type == Steinberg_Vst_MediaTypes_kAudio) {
|
||||
if (dir == Steinberg_Vst_BusDirections_kInput) {
|
||||
#if DATA_PLUGIN_BUSES_AUDIO_INPUT_N > 0
|
||||
if (index >= DATA_PLUGIN_BUSES_AUDIO_INPUT_N)
|
||||
return Steinberg_kInvalidArgument;
|
||||
// TBD
|
||||
return Steinberg_kResultTrue;
|
||||
#endif
|
||||
} else if (dir == Steinberg_Vst_BusDirections_kOutput) {
|
||||
#if DATA_PLUGIN_BUSES_AUDIO_OUTPUT_N > 0
|
||||
if (index >= DATA_PLUGIN_BUSES_AUDIO_OUTPUT_N)
|
||||
return Steinberg_kInvalidArgument;
|
||||
// TBD
|
||||
return Steinberg_kResultTrue;
|
||||
#endif
|
||||
}
|
||||
} else if (type == Steinberg_Vst_MediaTypes_kEvent) {
|
||||
if (dir == Steinberg_Vst_BusDirections_kInput) {
|
||||
#if DATA_PLUGIN_BUSES_EVENT_INPUT_N > 0
|
||||
if (index >= DATA_PLUGIN_BUSES_AUDIO_INPUT_N)
|
||||
return Steinberg_kInvalidArgument;
|
||||
// TBD
|
||||
return Steinberg_kResultTrue;
|
||||
#endif
|
||||
} else if (dir == Steinberg_Vst_BusDirections_kOutput) {
|
||||
#if DATA_PLUGIN_BUSES_EVENT_OUTPUT_N > 0
|
||||
if (index >= DATA_PLUGIN_BUSES_AUDIO_OUTPUT_N)
|
||||
return Steinberg_kInvalidArgument;
|
||||
// TBD
|
||||
return Steinberg_kResultTrue;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return Steinberg_kInvalidArgument;
|
||||
}
|
||||
|
||||
static Steinberg_tresult pluginSetActive(void* thisInterface, Steinberg_TBool state) {
|
||||
TRACE("plugin set active\n");
|
||||
//TBD
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_tresult pluginSetState(void* thisInterface, struct Steinberg_IBStream* state) {
|
||||
TRACE("plugin set state\n");
|
||||
//TBD
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_tresult pluginGetState(void* thisInterface, struct Steinberg_IBStream* state) {
|
||||
TRACE("plugin get state\n");
|
||||
//TBD
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_Vst_IComponentVtbl pluginVtblIComponent = {
|
||||
/* FUnknown */
|
||||
/* .queryInterface = */ pluginIComponentQueryInterface,
|
||||
/* .addRef = */ pluginIComponentAddRef,
|
||||
/* .release = */ pluginIComponentRelease,
|
||||
|
||||
/* IPluginBase */
|
||||
/* .initialize = */ pluginInitialize,
|
||||
/* .terminate = */ pluginTerminate,
|
||||
|
||||
/* IComponent */
|
||||
/* .getControllerClassId = */ pluginGetControllerClassId,
|
||||
/* .setIoMode = */ pluginSetIoMode,
|
||||
/* .getBusCount = */ pluginGetBusCount,
|
||||
/* .getBusInfo = */ pluginGetBusInfo,
|
||||
/* .getRoutingInfo = */ pluginGetRoutingInfo,
|
||||
/* .activateBus = */ pluginActivateBus,
|
||||
/* .setActive = */ pluginSetActive,
|
||||
/* .setState = */ pluginSetState,
|
||||
/* .getState = */ pluginGetState
|
||||
};
|
||||
|
||||
static Steinberg_tresult pluginIAudioProcessorQueryInterface(void *thisInterface, const Steinberg_TUID iid, void ** obj) {
|
||||
TRACE("plugin IAudioProcessor queryInterface %p\n", thisInterface);
|
||||
return pluginQueryInterface((pluginInstance *)((char *)thisInterface - offsetof(pluginInstance, vtblIAudioProcessor)), iid, obj);
|
||||
}
|
||||
|
||||
static Steinberg_uint32 pluginIAudioProcessorAddRef(void *thisInterface) {
|
||||
TRACE("plugin IAudioProcessor addRef %p\n", thisInterface);
|
||||
return pluginAddRef((pluginInstance *)((char *)thisInterface - offsetof(pluginInstance, vtblIAudioProcessor)));
|
||||
}
|
||||
|
||||
static Steinberg_uint32 pluginIAudioProcessorRelease(void *thisInterface) {
|
||||
TRACE("plugin IAudioProcessor release %p\n", thisInterface);
|
||||
return pluginRelease((pluginInstance *)((char *)thisInterface - offsetof(pluginInstance, vtblIAudioProcessor)));
|
||||
}
|
||||
|
||||
static Steinberg_tresult pluginSetBusArrangements(void* thisInterface, Steinberg_Vst_SpeakerArrangement* inputs, Steinberg_int32 numIns, Steinberg_Vst_SpeakerArrangement* outputs, Steinberg_int32 numOuts) {
|
||||
TRACE("plugin IAudioProcessor set bus arrangements\n");
|
||||
//TBD
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_tresult pluginGetBusArrangement(void* thisInterface, Steinberg_Vst_BusDirection dir, Steinberg_int32 index, Steinberg_Vst_SpeakerArrangement* arr) {
|
||||
TRACE("plugin IAudioProcessor get bus arrangement\n");
|
||||
//TBD
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_tresult pluginCanProcessSampleSize(void* thisInterface, Steinberg_int32 symbolicSampleSize) {
|
||||
TRACE("plugin IAudioProcessor can process sample size\n");
|
||||
//TBD
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_uint32 pluginGetLatencySamples(void* thisInterface) {
|
||||
TRACE("plugin IAudioProcessor get latency samples\n");
|
||||
//TBD
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Steinberg_tresult pluginSetupProcessing(void* thisInterface, struct Steinberg_Vst_ProcessSetup* setup) {
|
||||
TRACE("plugin IAudioProcessor setup processing\n");
|
||||
//TBD
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_tresult pluginSetProcessing(void* thisInterface, Steinberg_TBool state) {
|
||||
TRACE("plugin IAudioProcessor set processing\n");
|
||||
//TBD
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_tresult pluginProcess(void* thisInterface, struct Steinberg_Vst_ProcessData* data) {
|
||||
TRACE("plugin IAudioProcessor process\n");
|
||||
//TBD
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_uint32 pluginGetTailSamples(void* thisInterface) {
|
||||
TRACE("plugin IAudioProcessor get tail samples\n");
|
||||
//TBD
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Steinberg_Vst_IAudioProcessorVtbl pluginVtblIAudioProcessor = {
|
||||
/* FUnknown */
|
||||
/* .queryInterface = */ pluginIAudioProcessorQueryInterface,
|
||||
/* .addRef = */ pluginIAudioProcessorAddRef,
|
||||
/* .release = */ pluginIAudioProcessorRelease,
|
||||
|
||||
/* IAudioProcessor */
|
||||
/* .setBusArrangements = */ pluginSetBusArrangements,
|
||||
/*. getBusArrangement = */ pluginGetBusArrangement,
|
||||
/* .canProcessSampleSize = */ pluginCanProcessSampleSize,
|
||||
/* .getLatencySamples = */ pluginGetLatencySamples,
|
||||
/* .setupProcessing = */ pluginSetupProcessing,
|
||||
/* .setProcessing = */ pluginSetProcessing,
|
||||
/* .process = */ pluginProcess,
|
||||
/* .getTailSamples = */ pluginGetTailSamples
|
||||
};
|
||||
|
||||
static Steinberg_tresult pluginIProcessContextRequirementsQueryInterface(void *thisInterface, const Steinberg_TUID iid, void ** obj) {
|
||||
TRACE("plugin IProcessContextRequirements queryInterface %p\n", thisInterface);
|
||||
return pluginQueryInterface((pluginInstance *)((char *)thisInterface - offsetof(pluginInstance, vtblIProcessContextRequirements)), iid, obj);
|
||||
}
|
||||
|
||||
static Steinberg_uint32 pluginIProcessContextRequirementsAddRef(void *thisInterface) {
|
||||
TRACE("plugin IComponent addRef %p\n", thisInterface);
|
||||
return pluginAddRef((pluginInstance *)((char *)thisInterface - offsetof(pluginInstance, vtblIProcessContextRequirements)));
|
||||
}
|
||||
|
||||
static Steinberg_uint32 pluginIProcessContextRequirementsRelease(void *thisInterface) {
|
||||
TRACE("plugin IComponent release %p\n", thisInterface);
|
||||
return pluginRelease((pluginInstance *)((char *)thisInterface - offsetof(pluginInstance, vtblIProcessContextRequirements)));
|
||||
}
|
||||
static Steinberg_uint32 pluginGetProcessContextRequirements(void* thisInterface) {
|
||||
// TBD
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Steinberg_Vst_IProcessContextRequirementsVtbl pluginVtblIProcessContextRequirements = {
|
||||
/* FUnknown */
|
||||
/* .queryInterface = */ pluginIProcessContextRequirementsQueryInterface,
|
||||
/* .addRef = */ pluginIProcessContextRequirementsAddRef,
|
||||
/* .release = */ pluginIProcessContextRequirementsRelease,
|
||||
|
||||
/* IProcessContextRequirements */
|
||||
/* .getProcessContextRequirements = */ pluginGetProcessContextRequirements
|
||||
};
|
||||
|
||||
typedef struct controller {
|
||||
Steinberg_Vst_IEditControllerVtbl * vtblIEditController;
|
||||
Steinberg_uint32 refs;
|
||||
Steinberg_FUnknown * context;
|
||||
double parameters[DATA_PLUGIN_PARAMETERS_N];
|
||||
} controller;
|
||||
|
||||
static Steinberg_tresult controllerQueryInterface(void* thisInterface, const Steinberg_TUID iid, void** obj) {
|
||||
TRACE("controller queryInterface %p\n", thisInterface);
|
||||
if (memcmp(iid, Steinberg_FUnknown_iid, sizeof(Steinberg_TUID))
|
||||
&& memcmp(iid, Steinberg_IPluginBase_iid, sizeof(Steinberg_TUID))
|
||||
&& memcmp(iid, Steinberg_Vst_IEditController_iid, sizeof(Steinberg_TUID))) {
|
||||
TRACE(" oooo\n");
|
||||
*obj = NULL;
|
||||
return Steinberg_kNoInterface;
|
||||
}
|
||||
*obj = thisInterface;
|
||||
controller *c = (controller *)thisInterface;
|
||||
c->refs++;
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_uint32 controllerAddRef(void* thisInterface) {
|
||||
TRACE("controller addRef %p\n", thisInterface);
|
||||
controller *c = (controller *)thisInterface;
|
||||
c->refs++;
|
||||
return c->refs;
|
||||
}
|
||||
|
||||
static Steinberg_uint32 controllerRelease (void* thisInterface) {
|
||||
TRACE("controller release %p\n", thisInterface);
|
||||
controller *c = (controller *)thisInterface;
|
||||
c->refs--;
|
||||
if (c->refs == 0) {
|
||||
free(c);
|
||||
return 0;
|
||||
}
|
||||
return c->refs;
|
||||
}
|
||||
|
||||
static Steinberg_tresult controllerInitialize(void* thisInterface, struct Steinberg_FUnknown* context) {
|
||||
TRACE("controller initialize\n");
|
||||
controller *c = (controller *)thisInterface;
|
||||
if (c->context != NULL)
|
||||
return Steinberg_kResultFalse;
|
||||
c->context = context;
|
||||
//TBD
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_tresult controllerTerminate(void* thisInterface) {
|
||||
TRACE("controller terminate\n");
|
||||
controller *c = (controller *)thisInterface;
|
||||
c->context = NULL;
|
||||
//TBD
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_tresult controllerSetComponentState(void* thisInterface, struct Steinberg_IBStream* state) {
|
||||
TRACE("controller set component state\n");
|
||||
if (state == NULL)
|
||||
return Steinberg_kResultFalse;
|
||||
//TBD
|
||||
return Steinberg_kResultTrue;
|
||||
}
|
||||
|
||||
static Steinberg_tresult controllerSetState(void* thisInterface, struct Steinberg_IBStream* state) {
|
||||
TRACE("controller set state\n");
|
||||
return Steinberg_kNotImplemented;
|
||||
}
|
||||
|
||||
static Steinberg_tresult controllerGetState(void* thisInterface, struct Steinberg_IBStream* state) {
|
||||
TRACE("controller get state\n");
|
||||
return Steinberg_kNotImplemented;
|
||||
}
|
||||
|
||||
static Steinberg_int32 controllerGetParameterCount(void* thisInterface) {
|
||||
TRACE("controller get parameter count\n");
|
||||
return DATA_PLUGIN_PARAMETERS_N;
|
||||
}
|
||||
|
||||
static Steinberg_tresult controllerGetParameterInfo(void* thisInterface, Steinberg_int32 paramIndex, struct Steinberg_Vst_ParameterInfo* info) {
|
||||
TRACE("controller get parameter info\n");
|
||||
if (paramIndex < 0 || paramIndex >= DATA_PLUGIN_PARAMETERS_N)
|
||||
return Steinberg_kResultFalse;
|
||||
*info = parameterInfo[paramIndex];
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static void dToStr(double v, Steinberg_Vst_String128 s, int precision) {
|
||||
int i = 0;
|
||||
|
||||
if (v < 0.0) {
|
||||
s[0] = '-';
|
||||
v = -v;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (v < 1.0) {
|
||||
s[i] = '0';
|
||||
i++;
|
||||
} else {
|
||||
double x = 1.0;
|
||||
while (x <= v)
|
||||
x *= 10.0;
|
||||
x *= 0.1;
|
||||
while (x >= 1.0) {
|
||||
char c = v / x;
|
||||
s[i] = c + '0';
|
||||
i++;
|
||||
v -= c * x;
|
||||
x *= 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
s[i] = '.';
|
||||
i++;
|
||||
|
||||
double x = 0.1;
|
||||
while (precision != 0) {
|
||||
char c = v / x;
|
||||
s[i] = c + '0';
|
||||
i++;
|
||||
v -= c * x;
|
||||
x *= 0.1;
|
||||
precision--;
|
||||
}
|
||||
|
||||
s[i] = '\0';
|
||||
}
|
||||
|
||||
static Steinberg_tresult controllerGetParamStringByValue(void* thisInterface, Steinberg_Vst_ParamID id, Steinberg_Vst_ParamValue valueNormalized, Steinberg_Vst_String128 string) {
|
||||
TRACE("controller get param string by value\n");
|
||||
if (id >= DATA_PLUGIN_PARAMETERS_N)
|
||||
return Steinberg_kResultFalse;
|
||||
//mapping TBD
|
||||
dToStr(valueNormalized, string, 2);
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
void TCharToD(Steinberg_Vst_TChar* s, double *v) {
|
||||
int i = 0;
|
||||
*v = 0.0;
|
||||
|
||||
if (s[0] == '-') {
|
||||
*v = -0.0;
|
||||
i++;
|
||||
}
|
||||
|
||||
while (s[i] >= '0' && s[i] <= '9') {
|
||||
char d = s[i] - '0';
|
||||
i++;
|
||||
*v = 10.0 * *v + d;
|
||||
}
|
||||
|
||||
if (s[i] != '.')
|
||||
return;
|
||||
i++;
|
||||
|
||||
double x = 1.0;
|
||||
while (s[i] >= '0' && s[i] <= '9') {
|
||||
char d = s[i] - '0';
|
||||
i++;
|
||||
x *= 0.1;
|
||||
*v = *v + d * x;
|
||||
}
|
||||
}
|
||||
|
||||
static Steinberg_tresult controllerGetParamValueByString(void* thisInterface, Steinberg_Vst_ParamID id, Steinberg_Vst_TChar* string, Steinberg_Vst_ParamValue* valueNormalized) {
|
||||
TRACE("controller get param value by string\n");
|
||||
if (id >= DATA_PLUGIN_PARAMETERS_N)
|
||||
return Steinberg_kResultFalse;
|
||||
//mapping TBD
|
||||
TCharToD(string, valueNormalized);
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_Vst_ParamValue controllerNormalizedParamToPlain(void* thisInterface, Steinberg_Vst_ParamID id, Steinberg_Vst_ParamValue valueNormalized) {
|
||||
TRACE("controller normalized param to plain\n");
|
||||
//mapping TBD
|
||||
return valueNormalized;
|
||||
}
|
||||
|
||||
static Steinberg_Vst_ParamValue controllerPlainParamToNormalized(void* thisInterface, Steinberg_Vst_ParamID id, Steinberg_Vst_ParamValue plainValue) {
|
||||
TRACE("controller plain param to normalized\n");
|
||||
//mapping TBD
|
||||
return plainValue;
|
||||
}
|
||||
|
||||
static Steinberg_Vst_ParamValue controllerGetParamNormalized(void* thisInterface, Steinberg_Vst_ParamID id) {
|
||||
TRACE("controller get param normalized\n");
|
||||
controller *c = (controller *)thisInterface;
|
||||
return c->parameters[id];
|
||||
}
|
||||
|
||||
static Steinberg_tresult controllerSetParamNormalized(void* thisInterface, Steinberg_Vst_ParamID id, Steinberg_Vst_ParamValue value) {
|
||||
TRACE("controller set param normalized\n");
|
||||
if (id >= DATA_PLUGIN_PARAMETERS_N)
|
||||
return Steinberg_kResultFalse;
|
||||
controller *c = (controller *)thisInterface;
|
||||
c->parameters[id] = value;
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_tresult controllerSetComponentHandler(void* thisInterface, struct Steinberg_Vst_IComponentHandler* handler) {
|
||||
TRACE("controller set component handler\n");
|
||||
//TBD
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static struct Steinberg_IPlugView* controllerCreateView(void* thisInterface, Steinberg_FIDString name) {
|
||||
TRACE("controller create view\n");
|
||||
//TBD
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Steinberg_Vst_IEditControllerVtbl controllerVtbl = {
|
||||
/* FUnknown */
|
||||
/* .queryInterface = */ controllerQueryInterface,
|
||||
/* .addRef = */ controllerAddRef,
|
||||
/* .release = */ controllerRelease,
|
||||
|
||||
/* IPluginBase */
|
||||
/* .initialize = */ controllerInitialize,
|
||||
/* .terminate = */ controllerTerminate,
|
||||
|
||||
/* IEditController */
|
||||
/* .setComponentState = */ controllerSetComponentState,
|
||||
/* .setState = */ controllerSetState,
|
||||
/* .getState = */ controllerGetState,
|
||||
/* .getParameterCount = */ controllerGetParameterCount,
|
||||
/* .getParameterInfo = */ controllerGetParameterInfo,
|
||||
/* .getParamStringByValue = */ controllerGetParamStringByValue,
|
||||
/* .getParamValueByString = */ controllerGetParamValueByString,
|
||||
/* .normalizedParamToPlain = */ controllerNormalizedParamToPlain,
|
||||
/* .plainParamToNormalized = */ controllerPlainParamToNormalized,
|
||||
/* .getParamNormalized = */ controllerGetParamNormalized,
|
||||
/* .setParamNormalized = */ controllerSetParamNormalized,
|
||||
/* .setComponentHandler = */ controllerSetComponentHandler,
|
||||
/* .createView = */ controllerCreateView
|
||||
};
|
||||
|
||||
static Steinberg_tresult factoryQueryInterface(void *thisInterface, const Steinberg_TUID iid, void ** obj) {
|
||||
TRACE("factory queryInterface\n");
|
||||
if (memcmp(iid, Steinberg_FUnknown_iid, sizeof(Steinberg_TUID))
|
||||
&& memcmp(iid, Steinberg_IPluginFactory_iid, sizeof(Steinberg_TUID))
|
||||
&& memcmp(iid, Steinberg_IPluginFactory2_iid, sizeof(Steinberg_TUID))) {
|
||||
//&& memcmp(iid, Steinberg_IPluginFactory3_iid, sizeof(Steinberg_TUID))) {
|
||||
TRACE(" not supported\n");
|
||||
*obj = NULL;
|
||||
return Steinberg_kNoInterface;
|
||||
}
|
||||
*obj = thisInterface;
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_uint32 factoryAddRef(void *thisInterface) {
|
||||
TRACE("factory add ref\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static Steinberg_uint32 factoryRelease(void *thisInterface) {
|
||||
TRACE("factory release\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static Steinberg_tresult factoryGetFactoryInfo(void *thisInterface, struct Steinberg_PFactoryInfo * info) {
|
||||
TRACE("getFactoryInfo\n");
|
||||
strcpy(info->vendor, DATA_COMPANY_NAME);
|
||||
strcpy(info->url, DATA_COMPANY_URL);
|
||||
strcpy(info->email, DATA_COMPANY_EMAIL);
|
||||
info->flags = Steinberg_PFactoryInfo_FactoryFlags_kUnicode;
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_int32 factoryCountClasses(void *thisInterface) {
|
||||
TRACE("countClasses\n");
|
||||
return 2;
|
||||
}
|
||||
|
||||
static Steinberg_tresult factoryGetClassInfo(void *thisInterface, Steinberg_int32 index, struct Steinberg_PClassInfo * info) {
|
||||
TRACE("getClassInfo\n");
|
||||
switch (index) {
|
||||
case 0:
|
||||
TRACE(" class 0\n");
|
||||
memcpy(info->cid, pluginCID, sizeof(Steinberg_TUID));
|
||||
info->cardinality = Steinberg_PClassInfo_ClassCardinality_kManyInstances;
|
||||
strcpy(info->category, "Audio Module Class");
|
||||
strcpy(info->name, DATA_PLUGIN_NAME);
|
||||
break;
|
||||
case 1:
|
||||
TRACE(" class 1\n");
|
||||
memcpy(info->cid, controllerCID, sizeof(Steinberg_TUID));
|
||||
info->cardinality = Steinberg_PClassInfo_ClassCardinality_kManyInstances;
|
||||
strcpy(info->category, "Component Controller Class");
|
||||
strcpy(info->name, DATA_PLUGIN_NAME " Controller");
|
||||
break;
|
||||
default:
|
||||
return Steinberg_kInvalidArgument;
|
||||
break;
|
||||
}
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_tresult factoryCreateInstance(void *thisInterface, Steinberg_FIDString cid, Steinberg_FIDString iid, void ** obj) {
|
||||
TRACE("createInstance\n");
|
||||
if (memcmp(cid, pluginCID, sizeof(Steinberg_TUID)) == 0) {
|
||||
TRACE(" plugin\n");
|
||||
size_t offset; // FIXME: does it actually work like this? or is offset always 0?
|
||||
if ((memcmp(iid, Steinberg_FUnknown_iid, sizeof(Steinberg_TUID)) == 0)
|
||||
|| (memcmp(iid, Steinberg_IPluginBase_iid, sizeof(Steinberg_TUID)) != 0)
|
||||
|| (memcmp(iid, Steinberg_Vst_IComponent_iid, sizeof(Steinberg_TUID)) != 0)) {
|
||||
TRACE(" IComponent\n");
|
||||
offset = offsetof(pluginInstance, vtblIComponent);
|
||||
} else if (memcmp(iid, Steinberg_Vst_IAudioProcessor_iid, sizeof(Steinberg_TUID)) != 0) {
|
||||
TRACE(" IAudioProcessor\n");
|
||||
offset = offsetof(pluginInstance, vtblIAudioProcessor);
|
||||
} else if (memcmp(iid, Steinberg_Vst_IProcessContextRequirements_iid, sizeof(Steinberg_TUID)) != 0) {
|
||||
TRACE(" IAudioProcessor\n");
|
||||
offset = offsetof(pluginInstance, vtblIProcessContextRequirements);
|
||||
} else {
|
||||
TRACE(" INothing :(\n");
|
||||
return Steinberg_kNoInterface;
|
||||
}
|
||||
pluginInstance *p = malloc(sizeof(pluginInstance));
|
||||
if (p == NULL)
|
||||
return Steinberg_kOutOfMemory;
|
||||
p->vtblIComponent = &pluginVtblIComponent;
|
||||
p->vtblIAudioProcessor = &pluginVtblIAudioProcessor;
|
||||
p->vtblIProcessContextRequirements = &pluginVtblIProcessContextRequirements;
|
||||
p->refs = 1;
|
||||
p->context = NULL;
|
||||
*obj = (void *)((char *)p + offset);
|
||||
TRACE(" instance: %p\n", (void *)p);
|
||||
} else if (memcmp(cid, controllerCID, sizeof(Steinberg_TUID)) == 0) {
|
||||
TRACE(" controller\n");
|
||||
if (memcmp(iid, Steinberg_FUnknown_iid, sizeof(Steinberg_TUID))
|
||||
&& memcmp(iid, Steinberg_IPluginBase_iid, sizeof(Steinberg_TUID))
|
||||
&& memcmp(iid, Steinberg_Vst_IEditController_iid, sizeof(Steinberg_TUID)))
|
||||
return Steinberg_kNoInterface;
|
||||
controller *c = malloc(sizeof(controller));
|
||||
if (c == NULL)
|
||||
return Steinberg_kOutOfMemory;
|
||||
c->vtblIEditController = &controllerVtbl;
|
||||
c->refs = 1;
|
||||
c->context = NULL;
|
||||
for (int i = 0; i < DATA_PLUGIN_PARAMETERS_N; i++)
|
||||
c->parameters[i] = parameterInfo[i].defaultNormalizedValue;
|
||||
*obj = c;
|
||||
TRACE(" instance: %p\n", (void *)c);
|
||||
} else {
|
||||
*obj = NULL;
|
||||
return Steinberg_kNoInterface;
|
||||
}
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_tresult factoryGetClassInfo2(void* thisInterface, Steinberg_int32 index, struct Steinberg_PClassInfo2* info) {
|
||||
TRACE("getClassInfo2\n");
|
||||
switch (index) {
|
||||
case 0:
|
||||
TRACE(" class 0\n");
|
||||
memcpy(info->cid, pluginCID, sizeof(Steinberg_TUID));
|
||||
info->cardinality = Steinberg_PClassInfo_ClassCardinality_kManyInstances;
|
||||
strcpy(info->category, "Audio Module Class");
|
||||
strcpy(info->name, DATA_PLUGIN_NAME);
|
||||
info->classFlags = Steinberg_Vst_ComponentFlags_kDistributable;
|
||||
strcpy(info->subCategories, DATA_VST3_SUBCATEGORY);
|
||||
*info->vendor = '\0';
|
||||
strcpy(info->version, DATA_PLUGIN_VERSION);
|
||||
strcpy(info->sdkVersion, "VST 3.7.4 | Tibia");
|
||||
break;
|
||||
case 1:
|
||||
TRACE(" class 1\n");
|
||||
memcpy(info->cid, controllerCID, sizeof(Steinberg_TUID));
|
||||
info->cardinality = Steinberg_PClassInfo_ClassCardinality_kManyInstances;
|
||||
strcpy(info->category, "Component Controller Class");
|
||||
strcpy(info->name, DATA_PLUGIN_NAME " Controller");
|
||||
info->classFlags = 0;
|
||||
*info->subCategories = '\0';
|
||||
*info->vendor = '\0';
|
||||
strcpy(info->version, DATA_PLUGIN_VERSION);
|
||||
strcpy(info->sdkVersion, "VST 3.7.4 | Tibia");
|
||||
break;
|
||||
default:
|
||||
return Steinberg_kInvalidArgument;
|
||||
break;
|
||||
}
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_tresult factoryGetClassInfoUnicode(void* thisInterface, Steinberg_int32 index, struct Steinberg_PClassInfoW* info) {
|
||||
TRACE("getClassInfo unicode\n");
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_tresult factorySetHostContext(void* thisInterface, struct Steinberg_FUnknown* context) {
|
||||
TRACE("factory set host context\n");
|
||||
return Steinberg_kResultOk;
|
||||
}
|
||||
|
||||
static Steinberg_IPluginFactory2Vtbl factoryVtbl = {
|
||||
/* FUnknown */
|
||||
/* .queryInterface = */ factoryQueryInterface,
|
||||
/* .addRef = */ factoryAddRef,
|
||||
/* .release = */ factoryRelease,
|
||||
|
||||
/* IPluginFactory */
|
||||
/* .getFactoryInfo = */ factoryGetFactoryInfo,
|
||||
/* .countClasses = */ factoryCountClasses,
|
||||
/* .getClassInfo = */ factoryGetClassInfo,
|
||||
/* .createInstance = */ factoryCreateInstance,
|
||||
|
||||
/* IPluginFactory2 */
|
||||
/* .getClassInfo2 = */ factoryGetClassInfo2,
|
||||
|
||||
/* IPluginFactory3 */
|
||||
/* .getClassInfoUnicode = */ //factoryGetClassInfoUnicode,
|
||||
/* .setHostContext = */ //factorySetHostContext
|
||||
};
|
||||
static Steinberg_IPluginFactory2 factory = { &factoryVtbl };
|
||||
|
||||
Steinberg_IPluginFactory * GetPluginFactory() {
|
||||
return (Steinberg_IPluginFactory *)&factory;
|
||||
}
|
||||
|
||||
char ModuleEntry (void *handle) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
char ModuleExit () {
|
||||
return 1;
|
||||
}
|
11
templates/vst3/tibia-index.js
Normal file
11
templates/vst3/tibia-index.js
Normal file
@ -0,0 +1,11 @@
|
||||
var path = require("path");
|
||||
var sep = path.sep;
|
||||
|
||||
module.exports = function (data, api) {
|
||||
api.generateFileFromTemplateFile(`data${sep}Info.plist`, `data${sep}Info.plist`, data);
|
||||
api.copyFile(`src${sep}vst3.c`, `src${sep}vst3.c`);
|
||||
api.generateFileFromTemplateFile(`src${sep}data.h`, `src${sep}data.h`, data);
|
||||
api.copyFileIfNotExists(`src${sep}plugin.h`, `src${sep}plugin.h`);
|
||||
api.copyFile(`make${sep}Makefile`, `Makefile`);
|
||||
api.generateFileFromTemplateFile(`make${sep}vars.mk`, `vars.mk`, data);
|
||||
};
|
7
test/company.json
Normal file
7
test/company.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"company": {
|
||||
"name": "Orastron",
|
||||
"url": "https://www.orastron.com",
|
||||
"email": "info@orastron.com"
|
||||
}
|
||||
}
|
45
test/product.json
Normal file
45
test/product.json
Normal file
@ -0,0 +1,45 @@
|
||||
{
|
||||
"plugin": {
|
||||
"name": "Tibia test plugin",
|
||||
"version": "1.0.0.1",
|
||||
"bundleName": "tibia_test",
|
||||
"buses": [
|
||||
{
|
||||
"type": "audio",
|
||||
"direction": "input",
|
||||
"channels": 1,
|
||||
"name": "Input",
|
||||
"sidechain": false,
|
||||
"cv": false
|
||||
},
|
||||
{
|
||||
"type": "audio",
|
||||
"direction": "output",
|
||||
"channels": 1,
|
||||
"name": "Output",
|
||||
"sidechain": false,
|
||||
"cv": false
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"name": "Gain",
|
||||
"shortName": "Gain",
|
||||
"units": "dB",
|
||||
"steps": 0,
|
||||
"direction": "input",
|
||||
"isBypass": false,
|
||||
"defaultValue": 1.0
|
||||
},
|
||||
{
|
||||
"name": "Bypass",
|
||||
"shortName": "Bypass",
|
||||
"units": "",
|
||||
"steps": 1,
|
||||
"direction": "input",
|
||||
"isBypass": true,
|
||||
"defaultValue": 0.0
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
4
test/run.sh
Executable file
4
test/run.sh
Executable file
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
dir=`dirname $0`
|
||||
$dir/../tibia $dir/product.json,$dir/company.json,$dir/vst3.json $dir/../templates/vst3 $dir/../out
|
11
test/vst3.json
Normal file
11
test/vst3.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"vst3": {
|
||||
"plugin": {
|
||||
"cid": "66994c64bc3449f2b97fd96e36e18ba1"
|
||||
},
|
||||
"controller": {
|
||||
"cid": "ecf4f431312f44fbb37b88c545ae9993"
|
||||
},
|
||||
"subCategory": "FX"
|
||||
}
|
||||
}
|
66
tibia
Executable file
66
tibia
Executable file
@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
if (process.argv.length != 5) {
|
||||
console.log("Usage: tibia file1.json,file2.json,...filen.json template outDirectory");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
|
||||
var jsonFiles = process.argv[2].split(",");
|
||||
var template = process.argv[3];
|
||||
var outputDir = process.argv[4];
|
||||
|
||||
var data = {};
|
||||
for (var i = 0; i < jsonFiles.length; i++) {
|
||||
var d = JSON.parse(fs.readFileSync(jsonFiles[i], { encoding: "utf-8" }));
|
||||
for (var k in d)
|
||||
data[k] = d[k];
|
||||
}
|
||||
|
||||
var doT = require("dot");
|
||||
doT.templateSettings.strip = false;
|
||||
|
||||
var api = {
|
||||
// https://coderrocketfuel.com/article/recursively-list-all-the-files-in-a-directory-using-node-js
|
||||
getAllFiles: function (dirPath, arrayOfFiles, relDir) {
|
||||
var files = fs.readdirSync(dirPath);
|
||||
|
||||
var arrayOfFiles = arrayOfFiles || [];
|
||||
var relDir = relDir || "";
|
||||
|
||||
files.forEach(function(file) {
|
||||
if (fs.statSync(dirPath + path.sep + file).isDirectory())
|
||||
arrayOfFiles = api.getAllFiles(dirPath + path.sep + file, arrayOfFiles, relDir + file + path.sep);
|
||||
else
|
||||
arrayOfFiles.push(relDir + file);
|
||||
});
|
||||
|
||||
return arrayOfFiles
|
||||
},
|
||||
|
||||
generateFileFromTemplateFile: function (templateFile, outFile, data) {
|
||||
var dir = outputDir + path.sep + path.dirname(outFile);
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
var t = doT.template(fs.readFileSync(template + path.sep + templateFile, { encoding: "utf-8" }));
|
||||
fs.writeFileSync(outputDir + path.sep + outFile, t(data), { encoding: "utf-8" });
|
||||
},
|
||||
|
||||
copyFile: function (inFile, outFile) {
|
||||
var dir = outputDir + path.sep + path.dirname(outFile);
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
fs.copyFileSync(template + path.sep + inFile, outputDir + path.sep + outFile);
|
||||
},
|
||||
|
||||
copyFileIfNotExists: function (inFile, outFile) {
|
||||
var p = outputDir + path.sep + outFile;
|
||||
if (fs.existsSync(p))
|
||||
return;
|
||||
var dir = outputDir + path.sep + path.dirname(outFile);
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
fs.copyFileSync(template + path.sep + inFile, p);
|
||||
}
|
||||
};
|
||||
|
||||
require(path.resolve(template + path.sep + "tibia-index.js"))(data, api);
|
Loading…
Reference in New Issue
Block a user