@@ -0,0 +1,19 @@ | |||
.directory | |||
.fuse-* | |||
.*.kate-swp | |||
*~ | |||
*.o | |||
*.a | |||
*.exe | |||
*.so | |||
*.dll | |||
*.pyc | |||
ui_*.py | |||
icons_rc.py | |||
carla-discovery-* | |||
aeffect.h | |||
aeffectx.h |
@@ -0,0 +1,55 @@ | |||
#!/usr/bin/make -f | |||
# Makefile for Carla-Discovery # | |||
# ----------------------------------------- # | |||
# Created by falkTX | |||
# | |||
CXX ?= g++ | |||
BUILD_FLAGS = -ffast-math -fomit-frame-pointer -mtune=generic -msse -O2 -Wall -I../carla-includes $(CXXFLAGS) | |||
BUILD_FLAGS += -DVESTIGE_HEADER -I../carla-includes/vestige # Comment this line to not use vestige header | |||
LINK_FLAGS = $(LDFLAGS) | |||
32BIT_FLAGS = -m32 | |||
64BIT_FLAGS = -m64 #-fPIC | |||
UNIX_32BIT_FLAGS = -L/usr/lib32 -L/usr/lib/i386-linux-gnu $(32BIT_FLAGS) | |||
UNIX_64BIT_FLAGS = -L/usr/lib64 -L/usr/lib/x86_64-linux-gnu $(64BIT_FLAGS) | |||
UNIX_LINK_FLAGS = -ldl $(LINK_FLAGS) | |||
WIN32_FLAGS = $(32BIT_FLAGS) -static | |||
WIN64_FLAGS = $(64BIT_FLAGS) -static | |||
ifeq ($(FLUIDSYNTH),) | |||
else | |||
BUILD_FLAGS += `pkg-config --cflags fluidsynth` -DWANT_FLUIDSYNTH | |||
LINK_FLAGS += `pkg-config --libs fluidsynth` | |||
endif | |||
all: | |||
@echo "Build type must be unix32, unix64, win32 or win64" | |||
unix32: carla-discovery-unix32 | |||
unix64: carla-discovery-unix64 | |||
win32: carla-discovery-win32.exe | |||
win64: carla-discovery-win64.exe | |||
carla-discovery-unix32: carla-discovery.cpp | |||
$(CXX) carla-discovery.cpp $(BUILD_FLAGS) $(UNIX_32BIT_FLAGS) $(UNIX_LINK_FLAGS) -o $@ | |||
carla-discovery-unix64: carla-discovery.cpp | |||
$(CXX) carla-discovery.cpp $(BUILD_FLAGS) $(UNIX_64BIT_FLAGS) $(UNIX_LINK_FLAGS) -o $@ | |||
carla-discovery-win32.exe: carla-discovery.cpp | |||
$(CXX) carla-discovery.cpp $(BUILD_FLAGS) $(WIN32_FLAGS) $(LINK_FLAGS) -o $@ | |||
carla-discovery-win64.exe: carla-discovery.cpp | |||
$(CXX) carla-discovery.cpp $(BUILD_FLAGS) $(WIN64_FLAGS) $(LINK_FLAGS) -o $@ | |||
clean: | |||
rm -f carla-discovery-* |
@@ -0,0 +1,895 @@ | |||
/* Carla Plugin discovery code */ | |||
#ifndef nullptr | |||
const class { | |||
public: | |||
template<class T> operator T*() const | |||
{ | |||
return 0; | |||
} | |||
template<class C, class T> operator T C::*() const | |||
{ | |||
return 0; | |||
} | |||
private: | |||
void operator&() const; | |||
} nullptr_ = {}; | |||
#define nullptr nullptr_ | |||
#endif | |||
#if defined(__WIN32__) || defined(__WIN64__) | |||
#include <windows.h> | |||
#ifndef __WINDOWS__ | |||
#define __WINDOWS__ | |||
#endif | |||
#else | |||
#include <dlfcn.h> | |||
#ifndef __cdecl | |||
#define __cdecl | |||
#endif | |||
#endif | |||
#include <stdio.h> | |||
#include <stdint.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include <iostream> | |||
#include "ladspa/ladspa.h" | |||
#include "dssi/dssi.h" | |||
#define VST_FORCE_DEPRECATED 0 | |||
#include "aeffectx.h" | |||
#if VESTIGE_HEADER | |||
#warning Using vestige header | |||
#define kVstVersion 2400 | |||
#define effGetPlugCategory 35 | |||
#define effSetBlockSizeAndSampleRate 43 | |||
#define effShellGetNextPlugin 70 | |||
#define effStartProcess 71 | |||
#define effStopProcess 72 | |||
#define effSetProcessPrecision 77 | |||
#define kVstProcessPrecision32 0 | |||
#define kPlugCategUnknown 0 | |||
#define kPlugCategSynth 2 | |||
#define kPlugCategAnalysis 3 | |||
#define kPlugCategMastering 4 | |||
#define kPlugCategRoomFx 6 | |||
#define kPlugCategRestoration 8 | |||
#define kPlugCategShell 10 | |||
#define kPlugCategGenerator 11 | |||
#endif | |||
// we don't need to support SoundFonts in 32bit or Wine builds | |||
#ifdef WANT_FLUIDSYNTH | |||
#include <fluidsynth.h> | |||
#endif | |||
#define DISCOVERY_OUT(x, y) std::cout << "\ncarla-discovery::" << x << "::" << y << std::endl; | |||
// fake values to test plugins with | |||
const unsigned int bufferSize = 512; | |||
const unsigned int sampleRate = 44100; | |||
// ------------------------------ Carla main defs ------------------------------ | |||
// plugin hints | |||
const unsigned int PLUGIN_HAS_GUI = 0x01; | |||
const unsigned int PLUGIN_IS_BRIDGE = 0x02; | |||
const unsigned int PLUGIN_IS_SYNTH = 0x04; | |||
const unsigned int PLUGIN_USES_CHUNKS = 0x08; | |||
const unsigned int PLUGIN_CAN_DRYWET = 0x10; | |||
const unsigned int PLUGIN_CAN_VOL = 0x20; | |||
const unsigned int PLUGIN_CAN_BALANCE = 0x40; | |||
enum PluginType { | |||
PLUGIN_NONE = 0, | |||
PLUGIN_LADSPA = 1, | |||
PLUGIN_DSSI = 2, | |||
PLUGIN_LV2 = 3, | |||
PLUGIN_VST = 4, | |||
PLUGIN_SF2 = 5 | |||
}; | |||
enum PluginInfoCategory { | |||
PLUGIN_CATEGORY_NONE = 0, | |||
PLUGIN_CATEGORY_SYNTH = 1, | |||
PLUGIN_CATEGORY_DELAY = 2, // also Reverb | |||
PLUGIN_CATEGORY_EQ = 3, | |||
PLUGIN_CATEGORY_FILTER = 4, | |||
PLUGIN_CATEGORY_DYNAMICS = 5, // Amplifier, Compressor, Gate | |||
PLUGIN_CATEGORY_MODULATOR = 6, // Chorus, Flanger, Phaser | |||
PLUGIN_CATEGORY_UTILITY = 7, // Analyzer, Converter, Mixer | |||
PLUGIN_CATEGORY_OUTRO = 8 // used to check if a plugin has a category | |||
}; | |||
// ------------------------------ library functions ------------------------------ | |||
void* lib_open(const char* filename) | |||
{ | |||
#ifdef __WINDOWS__ | |||
return LoadLibraryA(filename); | |||
#else | |||
return dlopen(filename, RTLD_LAZY); | |||
#endif | |||
} | |||
int lib_close(void* lib) | |||
{ | |||
#ifdef __WINDOWS__ | |||
return FreeLibrary((HMODULE)lib); | |||
#else | |||
return dlclose(lib); | |||
#endif | |||
} | |||
void* lib_symbol(void* lib, const char* symbol) | |||
{ | |||
#ifdef __WINDOWS__ | |||
return (void*)GetProcAddress((HMODULE)lib, symbol); | |||
#else | |||
return dlsym(lib, symbol); | |||
#endif | |||
} | |||
const char* lib_error(const char* filename) | |||
{ | |||
#ifdef __WINDOWS__ | |||
static char libError[2048]; | |||
memset(libError, 0, sizeof(char)*2048); | |||
LPVOID winErrorString; | |||
DWORD winErrorCode = GetLastError(); | |||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, winErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&winErrorString, 0, nullptr); | |||
snprintf(libError, 2048, "%s: error code %li: %s", filename, winErrorCode, (const char*)winErrorString); | |||
LocalFree(winErrorString); | |||
return libError; | |||
#else | |||
(void)filename; | |||
return dlerror(); | |||
#endif | |||
} | |||
// ------------------------------ VST Stuff ------------------------------ | |||
typedef AEffect* (*VST_Function)(audioMasterCallback); | |||
intptr_t VstCurrentUniqueId = 0; | |||
bool VstPluginCanDo(AEffect* effect, const char* feature) | |||
{ | |||
return (effect->dispatcher(effect, effCanDo, 0, 0, (void*)feature, 0.0f) == 1); | |||
} | |||
intptr_t VstHostCallback(AEffect* effect, int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt) | |||
{ | |||
std::cout << "VstHostCallback(" << effect << ", " << opcode << ", " << index << ", " << value << ", " << ptr << ", " << opt << ")" << std::endl; | |||
switch (opcode) | |||
{ | |||
case audioMasterAutomate: | |||
if (effect) | |||
effect->setParameter(effect, index, opt); | |||
break; | |||
case audioMasterVersion: | |||
return kVstVersion; | |||
case audioMasterCurrentId: | |||
return VstCurrentUniqueId; | |||
case audioMasterGetTime: | |||
static VstTimeInfo timeInfo; | |||
memset(&timeInfo, 0, sizeof(VstTimeInfo)); | |||
timeInfo.sampleRate = sampleRate; | |||
return (intptr_t)&timeInfo; | |||
case audioMasterGetSampleRate: | |||
return sampleRate; | |||
case audioMasterGetBlockSize: | |||
return bufferSize; | |||
case audioMasterGetVendorString: | |||
if (ptr) | |||
strcpy((char*)ptr, "falkTX"); | |||
break; | |||
case audioMasterGetProductString: | |||
if (ptr) | |||
strcpy((char*)ptr, "Carla-Discovery"); | |||
break; | |||
case audioMasterGetVendorVersion: | |||
return 0x05; // 0.5 | |||
case audioMasterCanDo: | |||
std::cout << "VstHostCallback:audioMasterCanDo - " << (char*)ptr << std::endl; | |||
if (strcmp((char*)ptr, "sendVstEvents") == 0) | |||
return 1; | |||
else if (strcmp((char*)ptr, "sendVstMidiEvent") == 0) | |||
return 1; | |||
else if (strcmp((char*)ptr, "sendVstTimeInfo") == 0) | |||
return 1; | |||
else if (strcmp((char*)ptr, "receiveVstEvents") == 0) | |||
return 1; | |||
else if (strcmp((char*)ptr, "receiveVstMidiEvent") == 0) | |||
return 1; | |||
#if !VST_FORCE_DEPRECATED | |||
else if (strcmp((char*)ptr, "receiveVstTimeInfo") == 0) | |||
return -1; | |||
#endif | |||
else if (strcmp((char*)ptr, "reportConnectionChanges") == 0) | |||
return 1; | |||
else if (strcmp((char*)ptr, "acceptIOChanges") == 0) | |||
return 1; | |||
else if (strcmp((char*)ptr, "sizeWindow") == 0) | |||
return 1; | |||
else if (strcmp((char*)ptr, "offline") == 0) | |||
return 1; | |||
else if (strcmp((char*)ptr, "openFileSelector") == 0) | |||
return -1; | |||
else if (strcmp((char*)ptr, "closeFileSelector") == 0) | |||
return -1; | |||
else if (strcmp((char*)ptr, "startStopProcess") == 0) | |||
return 1; | |||
else if (strcmp((char*)ptr, "shellCategory") == 0) | |||
return 1; | |||
else if (strcmp((char*)ptr, "sendVstMidiEventFlagIsRealtime") == 0) | |||
return -1; | |||
else | |||
{ | |||
std::cerr << "VstHostCallback:audioMasterCanDo - Got uninplemented feature request '" << (char*)ptr << "'" << std::endl; | |||
return 0; | |||
} | |||
case audioMasterGetLanguage: | |||
return kVstLangEnglish; | |||
default: | |||
break; | |||
} | |||
return 0; | |||
} | |||
// ------------------------------ Plugin Check ------------------------------ | |||
void do_ladspa_check(void* lib_handle) | |||
{ | |||
LADSPA_Handle handle; | |||
const LADSPA_Descriptor* descriptor; | |||
LADSPA_Descriptor_Function descfn = (LADSPA_Descriptor_Function)lib_symbol(lib_handle, "ladspa_descriptor"); | |||
if (descfn == nullptr) | |||
{ | |||
DISCOVERY_OUT("error", "Not a LADSPA plugin"); | |||
return; | |||
} | |||
unsigned long i = 0; | |||
while ((descriptor = descfn(i++))) | |||
{ | |||
handle = descriptor->instantiate(descriptor, sampleRate); | |||
if (handle) | |||
{ | |||
DISCOVERY_OUT("init", "-----------"); | |||
DISCOVERY_OUT("name", descriptor->Name); | |||
DISCOVERY_OUT("label", descriptor->Label); | |||
DISCOVERY_OUT("maker", descriptor->Maker); | |||
DISCOVERY_OUT("copyright", descriptor->Copyright); | |||
DISCOVERY_OUT("id", descriptor->UniqueID); | |||
int hints = 0; | |||
PluginInfoCategory category = PLUGIN_CATEGORY_NONE; | |||
int audio_ins = 0; | |||
int audio_outs = 0; | |||
int audio_total = 0; | |||
int midi_ins = 0; | |||
int midi_outs = 0; | |||
int midi_total = 0; | |||
int parameters_ins = 0; | |||
int parameters_outs = 0; | |||
int parameters_total = 0; | |||
int programs_total = 0; | |||
for (unsigned long j=0; j < descriptor->PortCount; j++) | |||
{ | |||
const LADSPA_PortDescriptor PortDescriptor = descriptor->PortDescriptors[j]; | |||
if (PortDescriptor & LADSPA_PORT_AUDIO) | |||
{ | |||
if (PortDescriptor & LADSPA_PORT_INPUT) | |||
audio_ins += 1; | |||
else if (PortDescriptor & LADSPA_PORT_OUTPUT) | |||
audio_outs += 1; | |||
audio_total += 1; | |||
} | |||
else if (PortDescriptor & LADSPA_PORT_CONTROL) | |||
{ | |||
if (PortDescriptor & LADSPA_PORT_INPUT) | |||
parameters_ins += 1; | |||
else if (PortDescriptor & LADSPA_PORT_OUTPUT) | |||
{ | |||
if (strcmp(descriptor->PortNames[j], "latency") != 0 && strcmp(descriptor->PortNames[j], "_latency") != 0) | |||
parameters_outs += 1; | |||
} | |||
parameters_total += 1; | |||
} | |||
} | |||
// small crash-free plugin test | |||
float bufferAudio[bufferSize][audio_total]; | |||
memset(&bufferAudio, 0, sizeof(float)*bufferSize*audio_total); | |||
float bufferParams[parameters_total]; | |||
memset(&bufferParams, 0, sizeof(float)*parameters_total); | |||
for (unsigned long j=0, iA=0, iP=0; j < descriptor->PortCount; j++) | |||
{ | |||
const LADSPA_PortDescriptor PortDescriptor = descriptor->PortDescriptors[j]; | |||
if (PortDescriptor & LADSPA_PORT_AUDIO) | |||
descriptor->connect_port(handle, j, bufferAudio[iA++]); | |||
else if (PortDescriptor & LADSPA_PORT_CONTROL) | |||
descriptor->connect_port(handle, j, &bufferParams[iP++]); | |||
} | |||
if (descriptor->activate) | |||
descriptor->activate(handle); | |||
descriptor->run(handle, bufferSize); | |||
if (descriptor->deactivate) | |||
descriptor->deactivate(handle); | |||
DISCOVERY_OUT("hints", hints); | |||
DISCOVERY_OUT("category", category); | |||
DISCOVERY_OUT("audio.ins", audio_ins); | |||
DISCOVERY_OUT("audio.outs", audio_outs); | |||
DISCOVERY_OUT("audio.total", audio_total); | |||
DISCOVERY_OUT("midi.ins", midi_ins); | |||
DISCOVERY_OUT("midi.outs", midi_outs); | |||
DISCOVERY_OUT("midi.total", midi_total); | |||
DISCOVERY_OUT("parameters.ins", parameters_ins); | |||
DISCOVERY_OUT("parameters.outs", parameters_outs); | |||
DISCOVERY_OUT("parameters.total", parameters_total); | |||
DISCOVERY_OUT("programs.total", programs_total); | |||
DISCOVERY_OUT("end", "------------"); | |||
if (descriptor->cleanup) | |||
descriptor->cleanup(handle); | |||
} | |||
else | |||
DISCOVERY_OUT("error", "Failed to init LADSPA plugin"); | |||
} | |||
} | |||
void do_dssi_check(void* lib_handle) | |||
{ | |||
LADSPA_Handle handle; | |||
const LADSPA_Descriptor* ldescriptor; | |||
const DSSI_Descriptor* descriptor; | |||
DSSI_Descriptor_Function descfn = (DSSI_Descriptor_Function)lib_symbol(lib_handle, "dssi_descriptor"); | |||
if (descfn == nullptr) | |||
{ | |||
DISCOVERY_OUT("error", "Not a DSSI plugin"); | |||
return; | |||
} | |||
unsigned long i = 0; | |||
while ((descriptor = descfn(i++))) | |||
{ | |||
ldescriptor = descriptor->LADSPA_Plugin; | |||
handle = ldescriptor->instantiate(ldescriptor, sampleRate); | |||
if (handle) | |||
{ | |||
DISCOVERY_OUT("init", "-----------"); | |||
DISCOVERY_OUT("name", ldescriptor->Name); | |||
DISCOVERY_OUT("label", ldescriptor->Label); | |||
DISCOVERY_OUT("maker", ldescriptor->Maker); | |||
DISCOVERY_OUT("copyright", ldescriptor->Copyright); | |||
DISCOVERY_OUT("id", ldescriptor->UniqueID); | |||
int hints = 0; | |||
PluginInfoCategory category = PLUGIN_CATEGORY_NONE; | |||
int audio_ins = 0; | |||
int audio_outs = 0; | |||
int audio_total = 0; | |||
int midi_ins = 0; | |||
int midi_outs = 0; | |||
int midi_total = 0; | |||
int parameters_ins = 0; | |||
int parameters_outs = 0; | |||
int parameters_total = 0; | |||
int programs_total = 0; | |||
for (unsigned long j=0; j < ldescriptor->PortCount; j++) | |||
{ | |||
const LADSPA_PortDescriptor PortDescriptor = ldescriptor->PortDescriptors[j]; | |||
if (PortDescriptor & LADSPA_PORT_AUDIO) | |||
{ | |||
if (PortDescriptor & LADSPA_PORT_INPUT) | |||
audio_ins += 1; | |||
else if (PortDescriptor & LADSPA_PORT_OUTPUT) | |||
audio_outs += 1; | |||
audio_total += 1; | |||
} | |||
else if (PortDescriptor & LADSPA_PORT_CONTROL) | |||
{ | |||
if (PortDescriptor & LADSPA_PORT_INPUT) | |||
parameters_ins += 1; | |||
else if (PortDescriptor & LADSPA_PORT_OUTPUT) | |||
{ | |||
if (strcmp(ldescriptor->PortNames[j], "latency") != 0 && strcmp(ldescriptor->PortNames[j], "_latency") != 0) | |||
parameters_outs += 1; | |||
} | |||
parameters_total += 1; | |||
} | |||
} | |||
if (descriptor->run_synth || descriptor->run_multiple_synths) | |||
{ | |||
midi_ins = 1; | |||
midi_total = 1; | |||
} | |||
if (midi_ins > 0 && audio_outs > 0) | |||
hints |= PLUGIN_IS_SYNTH; | |||
if (descriptor->get_program) | |||
{ | |||
while ((descriptor->get_program(handle, programs_total))) | |||
programs_total += 1; | |||
} | |||
// small crash-free plugin test | |||
float bufferAudio[bufferSize][audio_total]; | |||
memset(&bufferAudio, 0, sizeof(float)*bufferSize*audio_total); | |||
float bufferParams[parameters_total]; | |||
memset(&bufferParams, 0, sizeof(float)*parameters_total); | |||
snd_seq_event_t midiEvents[2]; | |||
memset(&midiEvents, 0, sizeof(snd_seq_event_t)*2); | |||
unsigned long midiEventCount = 2; | |||
midiEvents[0].type = SND_SEQ_EVENT_NOTEON; | |||
midiEvents[0].data.note.note = 64; | |||
midiEvents[0].data.note.velocity = 100; | |||
midiEvents[1].type = SND_SEQ_EVENT_NOTEOFF; | |||
midiEvents[1].data.note.note = 64; | |||
midiEvents[1].data.note.velocity = 0; | |||
midiEvents[1].time.tick = bufferSize/2; | |||
for (unsigned long j=0, iA=0, iP=0; j < ldescriptor->PortCount; j++) | |||
{ | |||
const LADSPA_PortDescriptor PortDescriptor = ldescriptor->PortDescriptors[j]; | |||
if (PortDescriptor & LADSPA_PORT_AUDIO) | |||
ldescriptor->connect_port(handle, j, bufferAudio[iA++]); | |||
else if (PortDescriptor & LADSPA_PORT_CONTROL) | |||
ldescriptor->connect_port(handle, j, &bufferParams[iP++]); | |||
} | |||
if (ldescriptor->activate) | |||
ldescriptor->activate(handle); | |||
if (descriptor->run_synth) | |||
descriptor->run_synth(handle, bufferSize, midiEvents, midiEventCount); | |||
else if (descriptor->run_multiple_synths) | |||
{ | |||
snd_seq_event_t* midiEventsPtr[] = { midiEvents, nullptr }; | |||
descriptor->run_multiple_synths(1, &handle, bufferSize, midiEventsPtr, &midiEventCount); | |||
} | |||
else | |||
ldescriptor->run(handle, bufferSize); | |||
if (ldescriptor->deactivate) | |||
ldescriptor->deactivate(handle); | |||
DISCOVERY_OUT("hints", hints); | |||
DISCOVERY_OUT("category", category); | |||
DISCOVERY_OUT("audio.ins", audio_ins); | |||
DISCOVERY_OUT("audio.outs", audio_outs); | |||
DISCOVERY_OUT("audio.total", audio_total); | |||
DISCOVERY_OUT("midi.ins", midi_ins); | |||
DISCOVERY_OUT("midi.outs", midi_outs); | |||
DISCOVERY_OUT("midi.total", midi_total); | |||
DISCOVERY_OUT("parameters.ins", parameters_ins); | |||
DISCOVERY_OUT("parameters.outs", parameters_outs); | |||
DISCOVERY_OUT("parameters.total", parameters_total); | |||
DISCOVERY_OUT("programs.total", programs_total); | |||
DISCOVERY_OUT("end", "------------"); | |||
if (ldescriptor->cleanup) | |||
ldescriptor->cleanup(handle); | |||
} | |||
else | |||
DISCOVERY_OUT("error", "Failed to init DSSI plugin"); | |||
} | |||
} | |||
void do_lv2_check(const char* bundle) | |||
{ | |||
// TODO | |||
(void)bundle; | |||
} | |||
void do_vst_check(void* lib_handle) | |||
{ | |||
VST_Function vstfn = (VST_Function)lib_symbol(lib_handle, "VSTPluginMain"); | |||
if (vstfn == nullptr) | |||
{ | |||
if (vstfn == nullptr) | |||
{ | |||
#ifdef TARGET_API_MAC_CARBON | |||
vstfn = (VST_Function)lib_symbol(lib_handle, "main_macho"); | |||
if (vstfn == nullptr) | |||
#endif | |||
vstfn = (VST_Function)lib_symbol(lib_handle, "main"); | |||
} | |||
} | |||
if (vstfn == nullptr) | |||
{ | |||
DISCOVERY_OUT("error", "Not a VST plugin"); | |||
return; | |||
} | |||
AEffect* effect = vstfn(VstHostCallback); | |||
if (effect && effect->magic == kEffectMagic) | |||
{ | |||
const char* c_name; | |||
const char* c_product; | |||
const char* c_vendor; | |||
char buf_str[255] = { 0 }; | |||
effect->dispatcher(effect, effGetEffectName, 0, 0, buf_str, 0.0f); | |||
c_name = strdup((buf_str[0] != 0) ? buf_str : ""); | |||
buf_str[0] = 0; | |||
effect->dispatcher(effect, effGetProductString, 0, 0, buf_str, 0.0f); | |||
c_product = strdup((buf_str[0] != 0) ? buf_str : ""); | |||
buf_str[0] = 0; | |||
effect->dispatcher(effect, effGetVendorString, 0, 0, buf_str, 0.0f); | |||
c_vendor = strdup((buf_str[0] != 0) ? buf_str : ""); | |||
VstCurrentUniqueId = effect->uniqueID; | |||
intptr_t VstCategory = effect->dispatcher(effect, effGetPlugCategory, 0, 0, nullptr, 0.0f); | |||
while (true) | |||
{ | |||
DISCOVERY_OUT("init", "-----------"); | |||
effect->dispatcher(effect, effOpen, 0, 0, nullptr, 0.0f); | |||
DISCOVERY_OUT("name", c_name); | |||
DISCOVERY_OUT("label", c_product); | |||
DISCOVERY_OUT("maker", c_vendor); | |||
DISCOVERY_OUT("copyright", c_vendor); | |||
DISCOVERY_OUT("id", VstCurrentUniqueId); | |||
int hints = 0; | |||
PluginInfoCategory category = PLUGIN_CATEGORY_NONE; | |||
switch (VstCategory) | |||
{ | |||
case kPlugCategUnknown: | |||
category = PLUGIN_CATEGORY_NONE; | |||
break; | |||
case kPlugCategSynth: | |||
category = PLUGIN_CATEGORY_SYNTH; | |||
break; | |||
case kPlugCategAnalysis: | |||
category = PLUGIN_CATEGORY_UTILITY; | |||
break; | |||
case kPlugCategMastering: | |||
category = PLUGIN_CATEGORY_DYNAMICS; | |||
break; | |||
case kPlugCategRoomFx: | |||
category = PLUGIN_CATEGORY_DELAY; | |||
break; | |||
case kPlugCategRestoration: | |||
category = PLUGIN_CATEGORY_UTILITY; | |||
break; | |||
case kPlugCategGenerator: | |||
category = PLUGIN_CATEGORY_SYNTH; | |||
break; | |||
default: | |||
category = PLUGIN_CATEGORY_OUTRO; | |||
} | |||
if (effect->flags & effFlagsHasEditor) | |||
hints |= PLUGIN_HAS_GUI; | |||
if (effect->flags & effFlagsIsSynth) | |||
{ | |||
hints |= PLUGIN_IS_SYNTH; | |||
if (category == PLUGIN_CATEGORY_NONE) | |||
category = PLUGIN_CATEGORY_SYNTH; | |||
} | |||
int audio_ins = effect->numInputs; | |||
int audio_outs = effect->numOutputs; | |||
int audio_total = audio_ins + audio_outs; | |||
int midi_ins = 0; | |||
int midi_outs = 0; | |||
int midi_total = 0; | |||
int parameters_ins = effect->numParams; | |||
int parameters_outs = 0; | |||
int parameters_total = parameters_ins; | |||
int programs_total = effect->numPrograms; | |||
if (VstPluginCanDo(effect, "receiveVstEvents") || VstPluginCanDo(effect, "receiveVstMidiEvent") || effect->flags & effFlagsIsSynth) | |||
midi_ins = 1; | |||
if (VstPluginCanDo(effect, "sendVstEvents") || VstPluginCanDo(effect, "sendVstMidiEvent")) | |||
midi_outs = 1; | |||
midi_total = midi_ins + midi_outs; | |||
// small crash-free plugin test | |||
float** bufferAudioIn = new float* [audio_ins]; | |||
for (int j=0; j < audio_ins; j++) | |||
{ | |||
bufferAudioIn[j] = new float [bufferSize]; | |||
memset(bufferAudioIn[j], 0, sizeof(float)*bufferSize); | |||
} | |||
float** bufferAudioOut = new float* [audio_outs]; | |||
for (int j=0; j < audio_outs; j++) | |||
{ | |||
bufferAudioOut[j] = new float [bufferSize]; | |||
memset(bufferAudioOut[j], 0, sizeof(float)*bufferSize); | |||
} | |||
struct { | |||
int32_t numEvents; | |||
intptr_t reserved; | |||
VstEvent* data[2]; | |||
} events; | |||
VstMidiEvent midiEvents[2]; | |||
memset(&midiEvents, 0, sizeof(VstMidiEvent)*2); | |||
midiEvents[0].type = kVstMidiType; | |||
midiEvents[0].byteSize = sizeof(VstMidiEvent); | |||
midiEvents[0].midiData[0] = 0x90; | |||
midiEvents[0].midiData[1] = 64; | |||
midiEvents[0].midiData[2] = 100; | |||
midiEvents[1].type = kVstMidiType; | |||
midiEvents[1].byteSize = sizeof(VstMidiEvent); | |||
midiEvents[1].midiData[0] = 0x90; | |||
midiEvents[1].midiData[1] = 64; | |||
midiEvents[1].deltaFrames = bufferSize/2; | |||
events.numEvents = 2; | |||
events.reserved = 0; | |||
events.data[0] = (VstEvent*)&midiEvents[0]; | |||
events.data[1] = (VstEvent*)&midiEvents[1]; | |||
#if !VST_FORCE_DEPRECATED | |||
effect->dispatcher(effect, effSetBlockSizeAndSampleRate, 0, bufferSize, nullptr, sampleRate); | |||
#endif | |||
effect->dispatcher(effect, effSetSampleRate, 0, 0, nullptr, sampleRate); | |||
effect->dispatcher(effect, effSetBlockSize, 0, bufferSize, nullptr, 0.0f); | |||
effect->dispatcher(effect, effSetProcessPrecision, 0, kVstProcessPrecision32, nullptr, 0.0f); | |||
effect->dispatcher(effect, effMainsChanged, 0, 1, nullptr, 0.0f); | |||
effect->dispatcher(effect, effStartProcess, 0, 0, nullptr, 0.0f); | |||
if (midi_ins == 1) | |||
effect->dispatcher(effect, effProcessEvents, 0, 0, &events, 0.0f); | |||
if (effect->flags & effFlagsCanReplacing) | |||
effect->processReplacing(effect, bufferAudioIn, bufferAudioOut, bufferSize); | |||
#if !VST_FORCE_DEPRECATED | |||
else | |||
effect->process(effect, bufferAudioIn, bufferAudioOut, bufferSize); | |||
#endif | |||
effect->dispatcher(effect, effStopProcess, 0, 0, nullptr, 0.0f); | |||
effect->dispatcher(effect, effMainsChanged, 0, 0, nullptr, 0.0f); | |||
for (int j=0; j < audio_ins; j++) | |||
delete[] bufferAudioIn[j]; | |||
for (int j=0; j < audio_outs; j++) | |||
delete[] bufferAudioOut[j]; | |||
delete[] bufferAudioIn; | |||
delete[] bufferAudioOut; | |||
DISCOVERY_OUT("hints", hints); | |||
DISCOVERY_OUT("category", category); | |||
DISCOVERY_OUT("audio.ins", audio_ins); | |||
DISCOVERY_OUT("audio.outs", audio_outs); | |||
DISCOVERY_OUT("audio.total", audio_total); | |||
DISCOVERY_OUT("midi.ins", midi_ins); | |||
DISCOVERY_OUT("midi.outs", midi_outs); | |||
DISCOVERY_OUT("midi.total", midi_total); | |||
DISCOVERY_OUT("parameters.ins", parameters_ins); | |||
DISCOVERY_OUT("parameters.outs", parameters_outs); | |||
DISCOVERY_OUT("parameters.total", parameters_total); | |||
DISCOVERY_OUT("programs.total", programs_total); | |||
effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f); | |||
DISCOVERY_OUT("end", "------------"); | |||
if (VstCategory == kPlugCategShell) | |||
{ | |||
buf_str[0] = 0; | |||
VstCurrentUniqueId = effect->dispatcher(effect, effShellGetNextPlugin, 0, 0, buf_str, 0.0f); | |||
if (VstCurrentUniqueId != 0) | |||
{ | |||
free((void*)c_name); | |||
c_name = strdup((buf_str[0] != 0) ? buf_str : ""); | |||
} | |||
else | |||
break; | |||
} | |||
else | |||
break; | |||
} | |||
free((void*)c_name); | |||
free((void*)c_product); | |||
free((void*)c_vendor); | |||
} | |||
else | |||
DISCOVERY_OUT("error", "Failed to init VST plugin"); | |||
} | |||
void do_sf2_check(const char* filename) | |||
{ | |||
#ifdef WANT_FLUIDSYNTH | |||
if (fluid_is_soundfont(filename)) | |||
{ | |||
fluid_settings_t* f_settings = new_fluid_settings(); | |||
fluid_synth_t* f_synth = new_fluid_synth(f_settings); | |||
int f_id = fluid_synth_sfload(f_synth, filename, 0); | |||
if (f_id >= 0) | |||
{ | |||
int programs = 0; | |||
fluid_sfont_t* f_sfont; | |||
fluid_preset_t f_preset; | |||
f_sfont = fluid_synth_get_sfont_by_id(f_synth, f_id); | |||
// initial check to know how much midi-programs we get | |||
f_sfont->iteration_start(f_sfont); | |||
while (f_sfont->iteration_next(f_sfont, &f_preset)) | |||
programs += 1; | |||
DISCOVERY_OUT("init", "-----------"); | |||
DISCOVERY_OUT("name", ""); | |||
DISCOVERY_OUT("label", ""); | |||
DISCOVERY_OUT("maker", ""); | |||
DISCOVERY_OUT("copyright", ""); | |||
DISCOVERY_OUT("id", 0); | |||
DISCOVERY_OUT("hints", 0); | |||
DISCOVERY_OUT("category", PLUGIN_CATEGORY_SYNTH); | |||
DISCOVERY_OUT("audio.ins", 0); | |||
DISCOVERY_OUT("audio.outs", 2); | |||
DISCOVERY_OUT("audio.total", 2); | |||
DISCOVERY_OUT("midi.ins", 1); | |||
DISCOVERY_OUT("midi.outs", 0); | |||
DISCOVERY_OUT("midi.total", 1); | |||
DISCOVERY_OUT("programs.total", programs); | |||
// defined in Carla | |||
DISCOVERY_OUT("parameters.ins", 13); | |||
DISCOVERY_OUT("parameters.outs", 1); | |||
DISCOVERY_OUT("parameters.total", 14); | |||
DISCOVERY_OUT("end", "------------"); | |||
} | |||
else | |||
DISCOVERY_OUT("error", "Failed to load SF2 file"); | |||
delete_fluid_synth(f_synth); | |||
delete_fluid_settings(f_settings); | |||
} | |||
else | |||
DISCOVERY_OUT("error", "Not a SF2 file"); | |||
#else | |||
(void)filename; | |||
DISCOVERY_OUT("error", "SF2 support not available"); | |||
#endif | |||
} | |||
// ------------------------------ main entry point ------------------------------ | |||
int main(int argc, char* argv[]) | |||
{ | |||
if (argc != 3) | |||
return 1; | |||
const char* type_str = argv[1]; | |||
const char* filename = argv[2]; | |||
bool open_lib; | |||
PluginType type; | |||
void* handle = 0; | |||
if (strcmp(type_str, "LADSPA") == 0) | |||
{ | |||
open_lib = true; | |||
type = PLUGIN_LADSPA; | |||
} | |||
else if (strcmp(type_str, "DSSI") == 0) | |||
{ | |||
open_lib = true; | |||
type = PLUGIN_DSSI; | |||
} | |||
else if (strcmp(type_str, "LV2") == 0) | |||
{ | |||
open_lib = false; | |||
type = PLUGIN_LV2; | |||
} | |||
else if (strcmp(type_str, "VST") == 0) | |||
{ | |||
open_lib = true; | |||
type = PLUGIN_VST; | |||
} | |||
else if (strcmp(type_str, "SF2") == 0) | |||
{ | |||
open_lib = false; | |||
type = PLUGIN_SF2; | |||
} | |||
else | |||
{ | |||
open_lib = false; | |||
type = PLUGIN_NONE; | |||
} | |||
if (open_lib) | |||
{ | |||
handle = lib_open(filename); | |||
if (handle == nullptr) | |||
{ | |||
const char* error = lib_error(filename); | |||
// Since discovery can find multi-architecture binaries, don't print ELF related errors | |||
if (error && (strstr(error, "wrong ELF class") == nullptr || strstr(error, "Bad EXE format") == nullptr)) | |||
DISCOVERY_OUT("error", error); | |||
return 1; | |||
} | |||
} | |||
switch (type) | |||
{ | |||
case PLUGIN_LADSPA: | |||
do_ladspa_check(handle); | |||
break; | |||
case PLUGIN_DSSI: | |||
do_dssi_check(handle); | |||
break; | |||
case PLUGIN_LV2: | |||
do_lv2_check(filename); | |||
break; | |||
case PLUGIN_VST: | |||
do_vst_check(handle); | |||
break; | |||
case PLUGIN_SF2: | |||
do_sf2_check(filename); | |||
break; | |||
default: | |||
break; | |||
} | |||
if (open_lib) | |||
lib_close(handle); | |||
return 0; | |||
} |
@@ -0,0 +1,437 @@ | |||
/* -*- c-basic-offset: 4 -*- */ | |||
/* dssi.h | |||
DSSI version 1.0 | |||
Copyright (c) 2004, 2009 Chris Cannam, Steve Harris and Sean Bolton | |||
This library is free software; you can redistribute it and/or | |||
modify it under the terms of the GNU Lesser General Public License | |||
as published by the Free Software Foundation; either version 2.1 of | |||
the License, or (at your option) any later version. | |||
This library is distributed in the hope that it will be useful, but | |||
WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
Lesser General Public License for more details. | |||
You should have received a copy of the GNU Lesser General Public | |||
License along with this library; if not, write to the Free Software | |||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | |||
MA 02110-1301 USA | |||
*/ | |||
#ifndef DSSI_INCLUDED | |||
#define DSSI_INCLUDED | |||
#include "../ladspa/ladspa.h" | |||
#include "seq_event-compat.h" | |||
#define DSSI_VERSION "1.0" | |||
#define DSSI_VERSION_MAJOR 1 | |||
#define DSSI_VERSION_MINOR 0 | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/* | |||
There is a need for an API that supports hosted MIDI soft synths | |||
with GUIs in Linux audio applications. In time the GMPI initiative | |||
should comprehensively address this need, but the requirement for | |||
Linux applications to be able to support simple hosted synths is | |||
here now, and GMPI is not. This proposal (the "DSSI Soft Synth | |||
Interface" or DSSI, pronounced "dizzy") aims to provide a simple | |||
solution in a way that we hope will prove complete and compelling | |||
enough to support now, yet not so compelling as to supplant GMPI or | |||
any other comprehensive future proposal. | |||
For simplicity and familiarity, this API is based as far as | |||
possible on existing work -- the LADSPA plugin API for control | |||
values and audio processing, and the ALSA sequencer event types for | |||
MIDI event communication. The GUI part of the proposal is quite | |||
new, but may also be applicable retroactively to LADSPA plugins | |||
that do not otherwise support this synth interface. | |||
*/ | |||
typedef struct _DSSI_Program_Descriptor { | |||
/** Bank number for this program. Note that DSSI does not support | |||
MIDI-style separation of bank LSB and MSB values. There is no | |||
restriction on the set of available banks: the numbers do not | |||
need to be contiguous, there does not need to be a bank 0, etc. */ | |||
unsigned long Bank; | |||
/** Program number (unique within its bank) for this program. | |||
There is no restriction on the set of available programs: the | |||
numbers do not need to be contiguous, there does not need to | |||
be a program 0, etc. */ | |||
unsigned long Program; | |||
/** Name of the program. */ | |||
const char * Name; | |||
} DSSI_Program_Descriptor; | |||
typedef struct _DSSI_Descriptor { | |||
/** | |||
* DSSI_API_Version | |||
* | |||
* This member indicates the DSSI API level used by this plugin. | |||
* If we're lucky, this will never be needed. For now all plugins | |||
* must set it to 1. | |||
*/ | |||
int DSSI_API_Version; | |||
/** | |||
* LADSPA_Plugin | |||
* | |||
* A DSSI synth plugin consists of a LADSPA plugin plus an | |||
* additional framework for controlling program settings and | |||
* transmitting MIDI events. A plugin must fully implement the | |||
* LADSPA descriptor fields as well as the required LADSPA | |||
* functions including instantiate() and (de)activate(). It | |||
* should also implement run(), with the same behaviour as if | |||
* run_synth() (below) were called with no synth events. | |||
* | |||
* In order to instantiate a synth the host calls the LADSPA | |||
* instantiate function, passing in this LADSPA_Descriptor | |||
* pointer. The returned LADSPA_Handle is used as the argument | |||
* for the DSSI functions below as well as for the LADSPA ones. | |||
*/ | |||
const LADSPA_Descriptor *LADSPA_Plugin; | |||
/** | |||
* configure() | |||
* | |||
* This member is a function pointer that sends a piece of | |||
* configuration data to the plugin. The key argument specifies | |||
* some aspect of the synth's configuration that is to be changed, | |||
* and the value argument specifies a new value for it. A plugin | |||
* that does not require this facility at all may set this member | |||
* to NULL. | |||
* | |||
* This call is intended to set some session-scoped aspect of a | |||
* plugin's behaviour, for example to tell the plugin to load | |||
* sample data from a particular file. The plugin should act | |||
* immediately on the request. The call should return NULL on | |||
* success, or an error string that may be shown to the user. The | |||
* host will free the returned value after use if it is non-NULL. | |||
* | |||
* Calls to configure() are not automated as timed events. | |||
* Instead, a host should remember the last value associated with | |||
* each key passed to configure() during a given session for a | |||
* given plugin instance, and should call configure() with the | |||
* correct value for each key the next time it instantiates the | |||
* "same" plugin instance, for example on reloading a project in | |||
* which the plugin was used before. Plugins should note that a | |||
* host may typically instantiate a plugin multiple times with the | |||
* same configuration values, and should share data between | |||
* instances where practical. | |||
* | |||
* Calling configure() completely invalidates the program and bank | |||
* information last obtained from the plugin. | |||
* | |||
* Reserved and special key prefixes | |||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |||
* The DSSI: prefix | |||
* ---------------- | |||
* Configure keys starting with DSSI: are reserved for particular | |||
* purposes documented in the DSSI specification. At the moment, | |||
* there is one such key: DSSI:PROJECT_DIRECTORY. A host may call | |||
* configure() passing this key and a directory path value. This | |||
* indicates to the plugin and its UI that a directory at that | |||
* path exists and may be used for project-local data. Plugins | |||
* may wish to use the project directory as a fallback location | |||
* when looking for other file data, or as a base for relative | |||
* paths in other configuration values. | |||
* | |||
* The GLOBAL: prefix | |||
* ------------------ | |||
* Configure keys starting with GLOBAL: may be used by the plugin | |||
* and its UI for any purpose, but are treated specially by the | |||
* host. When one of these keys is used in a configure OSC call | |||
* from the plugin UI, the host makes the corresponding configure | |||
* call (preserving the GLOBAL: prefix) not only to the target | |||
* plugin but also to all other plugins in the same instance | |||
* group, as well as their UIs. Note that if any instance | |||
* returns non-NULL from configure to indicate error, the host | |||
* may stop there (and the set of plugins on which configure has | |||
* been called will thus depend on the host implementation). | |||
* See also the configure OSC call documentation in RFC.txt. | |||
*/ | |||
char *(*configure)(LADSPA_Handle Instance, | |||
const char *Key, | |||
const char *Value); | |||
#define DSSI_RESERVED_CONFIGURE_PREFIX "DSSI:" | |||
#define DSSI_GLOBAL_CONFIGURE_PREFIX "GLOBAL:" | |||
#define DSSI_PROJECT_DIRECTORY_KEY \ | |||
DSSI_RESERVED_CONFIGURE_PREFIX "PROJECT_DIRECTORY" | |||
/** | |||
* get_program() | |||
* | |||
* This member is a function pointer that provides a description | |||
* of a program (named preset sound) available on this synth. A | |||
* plugin that does not support programs at all should set this | |||
* member to NULL. | |||
* | |||
* The Index argument is an index into the plugin's list of | |||
* programs, not a program number as represented by the Program | |||
* field of the DSSI_Program_Descriptor. (This distinction is | |||
* needed to support synths that use non-contiguous program or | |||
* bank numbers.) | |||
* | |||
* This function returns a DSSI_Program_Descriptor pointer that is | |||
* guaranteed to be valid only until the next call to get_program, | |||
* deactivate, or configure, on the same plugin instance. This | |||
* function must return NULL if passed an Index argument out of | |||
* range, so that the host can use it to query the number of | |||
* programs as well as their properties. | |||
*/ | |||
const DSSI_Program_Descriptor *(*get_program)(LADSPA_Handle Instance, | |||
unsigned long Index); | |||
/** | |||
* select_program() | |||
* | |||
* This member is a function pointer that selects a new program | |||
* for this synth. The program change should take effect | |||
* immediately at the start of the next run_synth() call. (This | |||
* means that a host providing the capability of changing programs | |||
* between any two notes on a track must vary the block size so as | |||
* to place the program change at the right place. A host that | |||
* wanted to avoid this would probably just instantiate a plugin | |||
* for each program.) | |||
* | |||
* A plugin that does not support programs at all should set this | |||
* member NULL. Plugins should ignore a select_program() call | |||
* with an invalid bank or program. | |||
* | |||
* A plugin is not required to select any particular default | |||
* program on activate(): it's the host's duty to set a program | |||
* explicitly. The current program is invalidated by any call to | |||
* configure(). | |||
* | |||
* A plugin is permitted to re-write the values of its input | |||
* control ports when select_program is called. The host should | |||
* re-read the input control port values and update its own | |||
* records appropriately. (This is the only circumstance in | |||
* which a DSSI plugin is allowed to modify its own input ports.) | |||
*/ | |||
void (*select_program)(LADSPA_Handle Instance, | |||
unsigned long Bank, | |||
unsigned long Program); | |||
/** | |||
* get_midi_controller_for_port() | |||
* | |||
* This member is a function pointer that returns the MIDI | |||
* controller number or NRPN that should be mapped to the given | |||
* input control port. If the given port should not have any MIDI | |||
* controller mapped to it, the function should return DSSI_NONE. | |||
* The behaviour of this function is undefined if the given port | |||
* number does not correspond to an input control port. A plugin | |||
* that does not want MIDI controllers mapped to ports at all may | |||
* set this member NULL. | |||
* | |||
* Correct values can be got using the macros DSSI_CC(num) and | |||
* DSSI_NRPN(num) as appropriate, and values can be combined using | |||
* bitwise OR: e.g. DSSI_CC(23) | DSSI_NRPN(1069) means the port | |||
* should respond to CC #23 and NRPN #1069. | |||
* | |||
* The host is responsible for doing proper scaling from MIDI | |||
* controller and NRPN value ranges to port ranges according to | |||
* the plugin's LADSPA port hints. Hosts should not deliver | |||
* through run_synth any MIDI controller events that have already | |||
* been mapped to control port values. | |||
* | |||
* A plugin should not attempt to request mappings from | |||
* controllers 0 or 32 (MIDI Bank Select MSB and LSB). | |||
*/ | |||
int (*get_midi_controller_for_port)(LADSPA_Handle Instance, | |||
unsigned long Port); | |||
/** | |||
* run_synth() | |||
* | |||
* This member is a function pointer that runs a synth for a | |||
* block. This is identical in function to the LADSPA run() | |||
* function, except that it also supplies events to the synth. | |||
* | |||
* A plugin may provide this function, run_multiple_synths() (see | |||
* below), both, or neither (if it is not in fact a synth). A | |||
* plugin that does not provide this function must set this member | |||
* to NULL. Authors of synth plugins are encouraged to provide | |||
* this function if at all possible. | |||
* | |||
* The Events pointer points to a block of EventCount ALSA | |||
* sequencer events, which is used to communicate MIDI and related | |||
* events to the synth. Each event is timestamped relative to the | |||
* start of the block, (mis)using the ALSA "tick time" field as a | |||
* frame count. The host is responsible for ensuring that events | |||
* with differing timestamps are already ordered by time. | |||
* | |||
* See also the notes on activation, port connection etc in | |||
* ladpsa.h, in the context of the LADSPA run() function. | |||
* | |||
* Note Events | |||
* ~~~~~~~~~~~ | |||
* There are two minor requirements aimed at making the plugin | |||
* writer's life as simple as possible: | |||
* | |||
* 1. A host must never send events of type SND_SEQ_EVENT_NOTE. | |||
* Notes should always be sent as separate SND_SEQ_EVENT_NOTE_ON | |||
* and NOTE_OFF events. A plugin should discard any one-point | |||
* NOTE events it sees. | |||
* | |||
* 2. A host must not attempt to switch notes off by sending | |||
* zero-velocity NOTE_ON events. It should always send true | |||
* NOTE_OFFs. It is the host's responsibility to remap events in | |||
* cases where an external MIDI source has sent it zero-velocity | |||
* NOTE_ONs. | |||
* | |||
* Bank and Program Events | |||
* ~~~~~~~~~~~~~~~~~~~~~~~ | |||
* Hosts must map MIDI Bank Select MSB and LSB (0 and 32) | |||
* controllers and MIDI Program Change events onto the banks and | |||
* programs specified by the plugin, using the DSSI select_program | |||
* call. No host should ever deliver a program change or bank | |||
* select controller to a plugin via run_synth. | |||
*/ | |||
void (*run_synth)(LADSPA_Handle Instance, | |||
unsigned long SampleCount, | |||
snd_seq_event_t *Events, | |||
unsigned long EventCount); | |||
/** | |||
* run_synth_adding() | |||
* | |||
* This member is a function pointer that runs an instance of a | |||
* synth for a block, adding its outputs to the values already | |||
* present at the output ports. This is provided for symmetry | |||
* with LADSPA run_adding(), and is equally optional. A plugin | |||
* that does not provide it must set this member to NULL. | |||
*/ | |||
void (*run_synth_adding)(LADSPA_Handle Instance, | |||
unsigned long SampleCount, | |||
snd_seq_event_t *Events, | |||
unsigned long EventCount); | |||
/** | |||
* run_multiple_synths() | |||
* | |||
* This member is a function pointer that runs multiple synth | |||
* instances for a block. This is very similar to run_synth(), | |||
* except that Instances, Events, and EventCounts each point to | |||
* arrays that hold the LADSPA handles, event buffers, and | |||
* event counts for each of InstanceCount instances. That is, | |||
* Instances points to an array of InstanceCount pointers to | |||
* DSSI plugin instantiations, Events points to an array of | |||
* pointers to each instantiation's respective event list, and | |||
* EventCounts points to an array containing each instantiation's | |||
* respective event count. | |||
* | |||
* A host using this function must guarantee that ALL active | |||
* instances of the plugin are represented in each call to the | |||
* function -- that is, a host may not call run_multiple_synths() | |||
* for some instances of a given plugin and then call run_synth() | |||
* as well for others. 'All .. instances of the plugin' means | |||
* every instance sharing the same LADSPA label and shared object | |||
* (*.so) file (rather than every instance sharing the same *.so). | |||
* 'Active' means any instance for which activate() has been called | |||
* but deactivate() has not. | |||
* | |||
* A plugin may provide this function, run_synths() (see above), | |||
* both, or neither (if it not in fact a synth). A plugin that | |||
* does not provide this function must set this member to NULL. | |||
* Plugin authors implementing run_multiple_synths are strongly | |||
* encouraged to implement run_synth as well if at all possible, | |||
* to aid simplistic hosts, even where it would be less efficient | |||
* to use it. | |||
*/ | |||
void (*run_multiple_synths)(unsigned long InstanceCount, | |||
LADSPA_Handle *Instances, | |||
unsigned long SampleCount, | |||
snd_seq_event_t **Events, | |||
unsigned long *EventCounts); | |||
/** | |||
* run_multiple_synths_adding() | |||
* | |||
* This member is a function pointer that runs multiple synth | |||
* instances for a block, adding each synth's outputs to the | |||
* values already present at the output ports. This is provided | |||
* for symmetry with both the DSSI run_multiple_synths() and LADSPA | |||
* run_adding() functions, and is equally optional. A plugin | |||
* that does not provide it must set this member to NULL. | |||
*/ | |||
void (*run_multiple_synths_adding)(unsigned long InstanceCount, | |||
LADSPA_Handle *Instances, | |||
unsigned long SampleCount, | |||
snd_seq_event_t **Events, | |||
unsigned long *EventCounts); | |||
/** | |||
* set_custom_data() | |||
*/ | |||
int (*set_custom_data)(LADSPA_Handle Instance, void *Data, unsigned long DataLength); | |||
/** | |||
* get_custom_data() | |||
*/ | |||
int (*get_custom_data)(LADSPA_Handle Instance, void **Data, unsigned long *DataLength); | |||
} DSSI_Descriptor; | |||
/** | |||
* DSSI supports a plugin discovery method similar to that of LADSPA: | |||
* | |||
* - DSSI hosts may wish to locate DSSI plugin shared object files by | |||
* searching the paths contained in the DSSI_PATH and LADSPA_PATH | |||
* environment variables, if they are present. Both are expected | |||
* to be colon-separated lists of directories to be searched (in | |||
* order), and DSSI_PATH should be searched first if both variables | |||
* are set. | |||
* | |||
* - Each shared object file containing DSSI plugins must include a | |||
* function dssi_descriptor(), with the following function prototype | |||
* and C-style linkage. Hosts may enumerate the plugin types | |||
* available in the shared object file by repeatedly calling | |||
* this function with successive Index values (beginning from 0), | |||
* until a return value of NULL indicates no more plugin types are | |||
* available. Each non-NULL return is the DSSI_Descriptor | |||
* of a distinct plugin type. | |||
*/ | |||
const DSSI_Descriptor *dssi_descriptor(unsigned long Index); | |||
typedef const DSSI_Descriptor *(*DSSI_Descriptor_Function)(unsigned long Index); | |||
/* | |||
* Macros to specify particular MIDI controllers in return values from | |||
* get_midi_controller_for_port() | |||
*/ | |||
#define DSSI_CC_BITS 0x20000000 | |||
#define DSSI_NRPN_BITS 0x40000000 | |||
#define DSSI_NONE -1 | |||
#define DSSI_CONTROLLER_IS_SET(n) (DSSI_NONE != (n)) | |||
#define DSSI_CC(n) (DSSI_CC_BITS | (n)) | |||
#define DSSI_IS_CC(n) (DSSI_CC_BITS & (n)) | |||
#define DSSI_CC_NUMBER(n) ((n) & 0x7f) | |||
#define DSSI_NRPN(n) (DSSI_NRPN_BITS | ((n) << 7)) | |||
#define DSSI_IS_NRPN(n) (DSSI_NRPN_BITS & (n)) | |||
#define DSSI_NRPN_NUMBER(n) (((n) >> 7) & 0x3fff) | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* DSSI_INCLUDED */ |
@@ -0,0 +1,272 @@ | |||
/* | |||
* This library is free software; you can redistribute it and/or modify | |||
* it under the terms of the GNU Lesser General Public License as | |||
* published by the Free Software Foundation; either version 2.1 of | |||
* the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public | |||
* License along with this library; if not, write to the Free Software | |||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |||
* | |||
*/ | |||
#ifndef __ALSA_SEQ_EVENT_COMPAT_H | |||
#define __ALSA_SEQ_EVENT_COMPAT_H | |||
/** | |||
* Sequencer event data type | |||
*/ | |||
typedef unsigned char snd_seq_event_type_t; | |||
/** Sequencer event type */ | |||
enum snd_seq_event_type { | |||
/** system status; event data type = #snd_seq_result_t */ | |||
SND_SEQ_EVENT_SYSTEM = 0, | |||
/** returned result status; event data type = #snd_seq_result_t */ | |||
SND_SEQ_EVENT_RESULT, | |||
/** note on and off with duration; event data type = #snd_seq_ev_note_t */ | |||
SND_SEQ_EVENT_NOTE = 5, | |||
/** note on; event data type = #snd_seq_ev_note_t */ | |||
SND_SEQ_EVENT_NOTEON, | |||
/** note off; event data type = #snd_seq_ev_note_t */ | |||
SND_SEQ_EVENT_NOTEOFF, | |||
/** key pressure change (aftertouch); event data type = #snd_seq_ev_note_t */ | |||
SND_SEQ_EVENT_KEYPRESS, | |||
/** controller; event data type = #snd_seq_ev_ctrl_t */ | |||
SND_SEQ_EVENT_CONTROLLER = 10, | |||
/** program change; event data type = #snd_seq_ev_ctrl_t */ | |||
SND_SEQ_EVENT_PGMCHANGE, | |||
/** channel pressure; event data type = #snd_seq_ev_ctrl_t */ | |||
SND_SEQ_EVENT_CHANPRESS, | |||
/** pitchwheel; event data type = #snd_seq_ev_ctrl_t; data is from -8192 to 8191) */ | |||
SND_SEQ_EVENT_PITCHBEND, | |||
/** 14 bit controller value; event data type = #snd_seq_ev_ctrl_t */ | |||
SND_SEQ_EVENT_CONTROL14, | |||
/** 14 bit NRPN; event data type = #snd_seq_ev_ctrl_t */ | |||
SND_SEQ_EVENT_NONREGPARAM, | |||
/** 14 bit RPN; event data type = #snd_seq_ev_ctrl_t */ | |||
SND_SEQ_EVENT_REGPARAM, | |||
/** SPP with LSB and MSB values; event data type = #snd_seq_ev_ctrl_t */ | |||
SND_SEQ_EVENT_SONGPOS = 20, | |||
/** Song Select with song ID number; event data type = #snd_seq_ev_ctrl_t */ | |||
SND_SEQ_EVENT_SONGSEL, | |||
/** midi time code quarter frame; event data type = #snd_seq_ev_ctrl_t */ | |||
SND_SEQ_EVENT_QFRAME, | |||
/** SMF Time Signature event; event data type = #snd_seq_ev_ctrl_t */ | |||
SND_SEQ_EVENT_TIMESIGN, | |||
/** SMF Key Signature event; event data type = #snd_seq_ev_ctrl_t */ | |||
SND_SEQ_EVENT_KEYSIGN, | |||
/** MIDI Real Time Start message; event data type = #snd_seq_ev_queue_control_t */ | |||
SND_SEQ_EVENT_START = 30, | |||
/** MIDI Real Time Continue message; event data type = #snd_seq_ev_queue_control_t */ | |||
SND_SEQ_EVENT_CONTINUE, | |||
/** MIDI Real Time Stop message; event data type = #snd_seq_ev_queue_control_t */ | |||
SND_SEQ_EVENT_STOP, | |||
/** Set tick queue position; event data type = #snd_seq_ev_queue_control_t */ | |||
SND_SEQ_EVENT_SETPOS_TICK, | |||
/** Set real-time queue position; event data type = #snd_seq_ev_queue_control_t */ | |||
SND_SEQ_EVENT_SETPOS_TIME, | |||
/** (SMF) Tempo event; event data type = #snd_seq_ev_queue_control_t */ | |||
SND_SEQ_EVENT_TEMPO, | |||
/** MIDI Real Time Clock message; event data type = #snd_seq_ev_queue_control_t */ | |||
SND_SEQ_EVENT_CLOCK, | |||
/** MIDI Real Time Tick message; event data type = #snd_seq_ev_queue_control_t */ | |||
SND_SEQ_EVENT_TICK, | |||
/** Queue timer skew; event data type = #snd_seq_ev_queue_control_t */ | |||
SND_SEQ_EVENT_QUEUE_SKEW, | |||
/** Sync position changed; event data type = #snd_seq_ev_queue_control_t */ | |||
SND_SEQ_EVENT_SYNC_POS, | |||
/** Tune request; event data type = none */ | |||
SND_SEQ_EVENT_TUNE_REQUEST = 40, | |||
/** Reset to power-on state; event data type = none */ | |||
SND_SEQ_EVENT_RESET, | |||
/** Active sensing event; event data type = none */ | |||
SND_SEQ_EVENT_SENSING, | |||
/** Echo-back event; event data type = any type */ | |||
SND_SEQ_EVENT_ECHO = 50, | |||
/** OSS emulation raw event; event data type = any type */ | |||
SND_SEQ_EVENT_OSS, | |||
/** New client has connected; event data type = #snd_seq_addr_t */ | |||
SND_SEQ_EVENT_CLIENT_START = 60, | |||
/** Client has left the system; event data type = #snd_seq_addr_t */ | |||
SND_SEQ_EVENT_CLIENT_EXIT, | |||
/** Client status/info has changed; event data type = #snd_seq_addr_t */ | |||
SND_SEQ_EVENT_CLIENT_CHANGE, | |||
/** New port was created; event data type = #snd_seq_addr_t */ | |||
SND_SEQ_EVENT_PORT_START, | |||
/** Port was deleted from system; event data type = #snd_seq_addr_t */ | |||
SND_SEQ_EVENT_PORT_EXIT, | |||
/** Port status/info has changed; event data type = #snd_seq_addr_t */ | |||
SND_SEQ_EVENT_PORT_CHANGE, | |||
/** Ports connected; event data type = #snd_seq_connect_t */ | |||
SND_SEQ_EVENT_PORT_SUBSCRIBED, | |||
/** Ports disconnected; event data type = #snd_seq_connect_t */ | |||
SND_SEQ_EVENT_PORT_UNSUBSCRIBED, | |||
/** user-defined event; event data type = any (fixed size) */ | |||
SND_SEQ_EVENT_USR0 = 90, | |||
/** user-defined event; event data type = any (fixed size) */ | |||
SND_SEQ_EVENT_USR1, | |||
/** user-defined event; event data type = any (fixed size) */ | |||
SND_SEQ_EVENT_USR2, | |||
/** user-defined event; event data type = any (fixed size) */ | |||
SND_SEQ_EVENT_USR3, | |||
/** user-defined event; event data type = any (fixed size) */ | |||
SND_SEQ_EVENT_USR4, | |||
/** user-defined event; event data type = any (fixed size) */ | |||
SND_SEQ_EVENT_USR5, | |||
/** user-defined event; event data type = any (fixed size) */ | |||
SND_SEQ_EVENT_USR6, | |||
/** user-defined event; event data type = any (fixed size) */ | |||
SND_SEQ_EVENT_USR7, | |||
/** user-defined event; event data type = any (fixed size) */ | |||
SND_SEQ_EVENT_USR8, | |||
/** user-defined event; event data type = any (fixed size) */ | |||
SND_SEQ_EVENT_USR9, | |||
/** system exclusive data (variable length); event data type = #snd_seq_ev_ext_t */ | |||
SND_SEQ_EVENT_SYSEX = 130, | |||
/** error event; event data type = #snd_seq_ev_ext_t */ | |||
SND_SEQ_EVENT_BOUNCE, | |||
/** reserved for user apps; event data type = #snd_seq_ev_ext_t */ | |||
SND_SEQ_EVENT_USR_VAR0 = 135, | |||
/** reserved for user apps; event data type = #snd_seq_ev_ext_t */ | |||
SND_SEQ_EVENT_USR_VAR1, | |||
/** reserved for user apps; event data type = #snd_seq_ev_ext_t */ | |||
SND_SEQ_EVENT_USR_VAR2, | |||
/** reserved for user apps; event data type = #snd_seq_ev_ext_t */ | |||
SND_SEQ_EVENT_USR_VAR3, | |||
/** reserved for user apps; event data type = #snd_seq_ev_ext_t */ | |||
SND_SEQ_EVENT_USR_VAR4, | |||
/** NOP; ignored in any case */ | |||
SND_SEQ_EVENT_NONE = 255 | |||
}; | |||
/** Sequencer event address */ | |||
typedef struct snd_seq_addr { | |||
unsigned char client; /**< Client id */ | |||
unsigned char port; /**< Port id */ | |||
} snd_seq_addr_t; | |||
/** Connection (subscription) between ports */ | |||
typedef struct snd_seq_connect { | |||
snd_seq_addr_t sender; /**< sender address */ | |||
snd_seq_addr_t dest; /**< destination address */ | |||
} snd_seq_connect_t; | |||
/** Real-time data record */ | |||
typedef struct snd_seq_real_time { | |||
unsigned int tv_sec; /**< seconds */ | |||
unsigned int tv_nsec; /**< nanoseconds */ | |||
} snd_seq_real_time_t; | |||
/** (MIDI) Tick-time data record */ | |||
typedef unsigned int snd_seq_tick_time_t; | |||
/** unioned time stamp */ | |||
typedef union snd_seq_timestamp { | |||
snd_seq_tick_time_t tick; /**< tick-time */ | |||
struct snd_seq_real_time time; /**< real-time */ | |||
} snd_seq_timestamp_t; | |||
/** Note event */ | |||
typedef struct snd_seq_ev_note { | |||
unsigned char channel; /**< channel number */ | |||
unsigned char note; /**< note */ | |||
unsigned char velocity; /**< velocity */ | |||
unsigned char off_velocity; /**< note-off velocity; only for #SND_SEQ_EVENT_NOTE */ | |||
unsigned int duration; /**< duration until note-off; only for #SND_SEQ_EVENT_NOTE */ | |||
} snd_seq_ev_note_t; | |||
/** Controller event */ | |||
typedef struct snd_seq_ev_ctrl { | |||
unsigned char channel; /**< channel number */ | |||
unsigned char unused[3]; /**< reserved */ | |||
unsigned int param; /**< control parameter */ | |||
signed int value; /**< control value */ | |||
} snd_seq_ev_ctrl_t; | |||
/** generic set of bytes (12x8 bit) */ | |||
typedef struct snd_seq_ev_raw8 { | |||
unsigned char d[12]; /**< 8 bit value */ | |||
} snd_seq_ev_raw8_t; | |||
/** generic set of integers (3x32 bit) */ | |||
typedef struct snd_seq_ev_raw32 { | |||
unsigned int d[3]; /**< 32 bit value */ | |||
} snd_seq_ev_raw32_t; | |||
/** external stored data */ | |||
typedef struct snd_seq_ev_ext { | |||
unsigned int len; /**< length of data */ | |||
void *ptr; /**< pointer to data (note: can be 64-bit) */ | |||
} __attribute__((packed)) snd_seq_ev_ext_t; | |||
/** Result events */ | |||
typedef struct snd_seq_result { | |||
int event; /**< processed event type */ | |||
int result; /**< status */ | |||
} snd_seq_result_t; | |||
/** Queue skew values */ | |||
typedef struct snd_seq_queue_skew { | |||
unsigned int value; /**< skew value */ | |||
unsigned int base; /**< skew base */ | |||
} snd_seq_queue_skew_t; | |||
/** queue timer control */ | |||
typedef struct snd_seq_ev_queue_control { | |||
unsigned char queue; /**< affected queue */ | |||
unsigned char unused[3]; /**< reserved */ | |||
union { | |||
signed int value; /**< affected value (e.g. tempo) */ | |||
snd_seq_timestamp_t time; /**< time */ | |||
unsigned int position; /**< sync position */ | |||
snd_seq_queue_skew_t skew; /**< queue skew */ | |||
unsigned int d32[2]; /**< any data */ | |||
unsigned char d8[8]; /**< any data */ | |||
} param; /**< data value union */ | |||
} snd_seq_ev_queue_control_t; | |||
/** Sequencer event */ | |||
typedef struct snd_seq_event { | |||
snd_seq_event_type_t type; /**< event type */ | |||
unsigned char flags; /**< event flags */ | |||
unsigned char tag; /**< tag */ | |||
unsigned char queue; /**< schedule queue */ | |||
snd_seq_timestamp_t time; /**< schedule time */ | |||
snd_seq_addr_t source; /**< source address */ | |||
snd_seq_addr_t dest; /**< destination address */ | |||
union { | |||
snd_seq_ev_note_t note; /**< note information */ | |||
snd_seq_ev_ctrl_t control; /**< MIDI control information */ | |||
snd_seq_ev_raw8_t raw8; /**< raw8 data */ | |||
snd_seq_ev_raw32_t raw32; /**< raw32 data */ | |||
snd_seq_ev_ext_t ext; /**< external data */ | |||
snd_seq_ev_queue_control_t queue; /**< queue control */ | |||
snd_seq_timestamp_t time; /**< timestamp */ | |||
snd_seq_addr_t addr; /**< address */ | |||
snd_seq_connect_t connect; /**< connect information */ | |||
snd_seq_result_t result; /**< operation result code */ | |||
} data; /**< event data... */ | |||
} snd_seq_event_t; | |||
#endif /* __ALSA_SEQ_EVENT_COMPAT_H */ | |||
@@ -0,0 +1,603 @@ | |||
/* ladspa.h | |||
Linux Audio Developer's Simple Plugin API Version 1.1[LGPL]. | |||
Copyright (C) 2000-2002 Richard W.E. Furse, Paul Barton-Davis, | |||
Stefan Westerfeld. | |||
This library is free software; you can redistribute it and/or | |||
modify it under the terms of the GNU Lesser General Public License | |||
as published by the Free Software Foundation; either version 2.1 of | |||
the License, or (at your option) any later version. | |||
This library is distributed in the hope that it will be useful, but | |||
WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
Lesser General Public License for more details. | |||
You should have received a copy of the GNU Lesser General Public | |||
License along with this library; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | |||
USA. */ | |||
#ifndef LADSPA_INCLUDED | |||
#define LADSPA_INCLUDED | |||
#define LADSPA_VERSION "1.1" | |||
#define LADSPA_VERSION_MAJOR 1 | |||
#define LADSPA_VERSION_MINOR 1 | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/*****************************************************************************/ | |||
/* Overview: | |||
There is a large number of synthesis packages in use or development | |||
on the Linux platform at this time. This API (`The Linux Audio | |||
Developer's Simple Plugin API') attempts to give programmers the | |||
ability to write simple `plugin' audio processors in C/C++ and link | |||
them dynamically (`plug') into a range of these packages (`hosts'). | |||
It should be possible for any host and any plugin to communicate | |||
completely through this interface. | |||
This API is deliberately short and simple. To achieve compatibility | |||
with a range of promising Linux sound synthesis packages it | |||
attempts to find the `greatest common divisor' in their logical | |||
behaviour. Having said this, certain limiting decisions are | |||
implicit, notably the use of a fixed type (LADSPA_Data) for all | |||
data transfer and absence of a parameterised `initialisation' | |||
phase. See below for the LADSPA_Data typedef. | |||
Plugins are expected to distinguish between control and audio | |||
data. Plugins have `ports' that are inputs or outputs for audio or | |||
control data and each plugin is `run' for a `block' corresponding | |||
to a short time interval measured in samples. Audio data is | |||
communicated using arrays of LADSPA_Data, allowing a block of audio | |||
to be processed by the plugin in a single pass. Control data is | |||
communicated using single LADSPA_Data values. Control data has a | |||
single value at the start of a call to the `run()' or `run_adding()' | |||
function, and may be considered to remain this value for its | |||
duration. The plugin may assume that all its input and output ports | |||
have been connected to the relevant data location (see the | |||
`connect_port()' function below) before it is asked to run. | |||
Plugins will reside in shared object files suitable for dynamic | |||
linking by dlopen() and family. The file will provide a number of | |||
`plugin types' that can be used to instantiate actual plugins | |||
(sometimes known as `plugin instances') that can be connected | |||
together to perform tasks. | |||
This API contains very limited error-handling. */ | |||
/*****************************************************************************/ | |||
/* Fundamental data type passed in and out of plugin. This data type | |||
is used to communicate audio samples and control values. It is | |||
assumed that the plugin will work sensibly given any numeric input | |||
value although it may have a preferred range (see hints below). | |||
For audio it is generally assumed that 1.0f is the `0dB' reference | |||
amplitude and is a `normal' signal level. */ | |||
typedef float LADSPA_Data; | |||
/*****************************************************************************/ | |||
/* Special Plugin Properties: | |||
Optional features of the plugin type are encapsulated in the | |||
LADSPA_Properties type. This is assembled by ORing individual | |||
properties together. */ | |||
typedef int LADSPA_Properties; | |||
/* Property LADSPA_PROPERTY_REALTIME indicates that the plugin has a | |||
real-time dependency (e.g. listens to a MIDI device) and so its | |||
output must not be cached or subject to significant latency. */ | |||
#define LADSPA_PROPERTY_REALTIME 0x1 | |||
/* Property LADSPA_PROPERTY_INPLACE_BROKEN indicates that the plugin | |||
may cease to work correctly if the host elects to use the same data | |||
location for both input and output (see connect_port()). This | |||
should be avoided as enabling this flag makes it impossible for | |||
hosts to use the plugin to process audio `in-place.' */ | |||
#define LADSPA_PROPERTY_INPLACE_BROKEN 0x2 | |||
/* Property LADSPA_PROPERTY_HARD_RT_CAPABLE indicates that the plugin | |||
is capable of running not only in a conventional host but also in a | |||
`hard real-time' environment. To qualify for this the plugin must | |||
satisfy all of the following: | |||
(1) The plugin must not use malloc(), free() or other heap memory | |||
management within its run() or run_adding() functions. All new | |||
memory used in run() must be managed via the stack. These | |||
restrictions only apply to the run() function. | |||
(2) The plugin will not attempt to make use of any library | |||
functions with the exceptions of functions in the ANSI standard C | |||
and C maths libraries, which the host is expected to provide. | |||
(3) The plugin will not access files, devices, pipes, sockets, IPC | |||
or any other mechanism that might result in process or thread | |||
blocking. | |||
(4) The plugin will take an amount of time to execute a run() or | |||
run_adding() call approximately of form (A+B*SampleCount) where A | |||
and B depend on the machine and host in use. This amount of time | |||
may not depend on input signals or plugin state. The host is left | |||
the responsibility to perform timings to estimate upper bounds for | |||
A and B. */ | |||
#define LADSPA_PROPERTY_HARD_RT_CAPABLE 0x4 | |||
#define LADSPA_IS_REALTIME(x) ((x) & LADSPA_PROPERTY_REALTIME) | |||
#define LADSPA_IS_INPLACE_BROKEN(x) ((x) & LADSPA_PROPERTY_INPLACE_BROKEN) | |||
#define LADSPA_IS_HARD_RT_CAPABLE(x) ((x) & LADSPA_PROPERTY_HARD_RT_CAPABLE) | |||
/*****************************************************************************/ | |||
/* Plugin Ports: | |||
Plugins have `ports' that are inputs or outputs for audio or | |||
data. Ports can communicate arrays of LADSPA_Data (for audio | |||
inputs/outputs) or single LADSPA_Data values (for control | |||
input/outputs). This information is encapsulated in the | |||
LADSPA_PortDescriptor type which is assembled by ORing individual | |||
properties together. | |||
Note that a port must be an input or an output port but not both | |||
and that a port must be a control or audio port but not both. */ | |||
typedef int LADSPA_PortDescriptor; | |||
/* Property LADSPA_PORT_INPUT indicates that the port is an input. */ | |||
#define LADSPA_PORT_INPUT 0x1 | |||
/* Property LADSPA_PORT_OUTPUT indicates that the port is an output. */ | |||
#define LADSPA_PORT_OUTPUT 0x2 | |||
/* Property LADSPA_PORT_CONTROL indicates that the port is a control | |||
port. */ | |||
#define LADSPA_PORT_CONTROL 0x4 | |||
/* Property LADSPA_PORT_AUDIO indicates that the port is a audio | |||
port. */ | |||
#define LADSPA_PORT_AUDIO 0x8 | |||
#define LADSPA_IS_PORT_INPUT(x) ((x) & LADSPA_PORT_INPUT) | |||
#define LADSPA_IS_PORT_OUTPUT(x) ((x) & LADSPA_PORT_OUTPUT) | |||
#define LADSPA_IS_PORT_CONTROL(x) ((x) & LADSPA_PORT_CONTROL) | |||
#define LADSPA_IS_PORT_AUDIO(x) ((x) & LADSPA_PORT_AUDIO) | |||
/*****************************************************************************/ | |||
/* Plugin Port Range Hints: | |||
The host may wish to provide a representation of data entering or | |||
leaving a plugin (e.g. to generate a GUI automatically). To make | |||
this more meaningful, the plugin should provide `hints' to the host | |||
describing the usual values taken by the data. | |||
Note that these are only hints. The host may ignore them and the | |||
plugin must not assume that data supplied to it is meaningful. If | |||
the plugin receives invalid input data it is expected to continue | |||
to run without failure and, where possible, produce a sensible | |||
output (e.g. a high-pass filter given a negative cutoff frequency | |||
might switch to an all-pass mode). | |||
Hints are meaningful for all input and output ports but hints for | |||
input control ports are expected to be particularly useful. | |||
More hint information is encapsulated in the | |||
LADSPA_PortRangeHintDescriptor type which is assembled by ORing | |||
individual hint types together. Hints may require further | |||
LowerBound and UpperBound information. | |||
All the hint information for a particular port is aggregated in the | |||
LADSPA_PortRangeHint structure. */ | |||
typedef int LADSPA_PortRangeHintDescriptor; | |||
/* Hint LADSPA_HINT_BOUNDED_BELOW indicates that the LowerBound field | |||
of the LADSPA_PortRangeHint should be considered meaningful. The | |||
value in this field should be considered the (inclusive) lower | |||
bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also | |||
specified then the value of LowerBound should be multiplied by the | |||
sample rate. */ | |||
#define LADSPA_HINT_BOUNDED_BELOW 0x1 | |||
/* Hint LADSPA_HINT_BOUNDED_ABOVE indicates that the UpperBound field | |||
of the LADSPA_PortRangeHint should be considered meaningful. The | |||
value in this field should be considered the (inclusive) upper | |||
bound of the valid range. If LADSPA_HINT_SAMPLE_RATE is also | |||
specified then the value of UpperBound should be multiplied by the | |||
sample rate. */ | |||
#define LADSPA_HINT_BOUNDED_ABOVE 0x2 | |||
/* Hint LADSPA_HINT_TOGGLED indicates that the data item should be | |||
considered a Boolean toggle. Data less than or equal to zero should | |||
be considered `off' or `false,' and data above zero should be | |||
considered `on' or `true.' LADSPA_HINT_TOGGLED may not be used in | |||
conjunction with any other hint except LADSPA_HINT_DEFAULT_0 or | |||
LADSPA_HINT_DEFAULT_1. */ | |||
#define LADSPA_HINT_TOGGLED 0x4 | |||
/* Hint LADSPA_HINT_SAMPLE_RATE indicates that any bounds specified | |||
should be interpreted as multiples of the sample rate. For | |||
instance, a frequency range from 0Hz to the Nyquist frequency (half | |||
the sample rate) could be requested by this hint in conjunction | |||
with LowerBound = 0 and UpperBound = 0.5. Hosts that support bounds | |||
at all must support this hint to retain meaning. */ | |||
#define LADSPA_HINT_SAMPLE_RATE 0x8 | |||
/* Hint LADSPA_HINT_LOGARITHMIC indicates that it is likely that the | |||
user will find it more intuitive to view values using a logarithmic | |||
scale. This is particularly useful for frequencies and gains. */ | |||
#define LADSPA_HINT_LOGARITHMIC 0x10 | |||
/* Hint LADSPA_HINT_INTEGER indicates that a user interface would | |||
probably wish to provide a stepped control taking only integer | |||
values. Any bounds set should be slightly wider than the actual | |||
integer range required to avoid floating point rounding errors. For | |||
instance, the integer set {0,1,2,3} might be described as [-0.1, | |||
3.1]. */ | |||
#define LADSPA_HINT_INTEGER 0x20 | |||
/* The various LADSPA_HINT_HAS_DEFAULT_* hints indicate a `normal' | |||
value for the port that is sensible as a default. For instance, | |||
this value is suitable for use as an initial value in a user | |||
interface or as a value the host might assign to a control port | |||
when the user has not provided one. Defaults are encoded using a | |||
mask so only one default may be specified for a port. Some of the | |||
hints make use of lower and upper bounds, in which case the | |||
relevant bound or bounds must be available and | |||
LADSPA_HINT_SAMPLE_RATE must be applied as usual. The resulting | |||
default must be rounded if LADSPA_HINT_INTEGER is present. Default | |||
values were introduced in LADSPA v1.1. */ | |||
#define LADSPA_HINT_DEFAULT_MASK 0x3C0 | |||
/* This default values indicates that no default is provided. */ | |||
#define LADSPA_HINT_DEFAULT_NONE 0x0 | |||
/* This default hint indicates that the suggested lower bound for the | |||
port should be used. */ | |||
#define LADSPA_HINT_DEFAULT_MINIMUM 0x40 | |||
/* This default hint indicates that a low value between the suggested | |||
lower and upper bounds should be chosen. For ports with | |||
LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.75 + | |||
log(upper) * 0.25). Otherwise, this should be (lower * 0.75 + upper | |||
* 0.25). */ | |||
#define LADSPA_HINT_DEFAULT_LOW 0x80 | |||
/* This default hint indicates that a middle value between the | |||
suggested lower and upper bounds should be chosen. For ports with | |||
LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.5 + | |||
log(upper) * 0.5). Otherwise, this should be (lower * 0.5 + upper * | |||
0.5). */ | |||
#define LADSPA_HINT_DEFAULT_MIDDLE 0xC0 | |||
/* This default hint indicates that a high value between the suggested | |||
lower and upper bounds should be chosen. For ports with | |||
LADSPA_HINT_LOGARITHMIC, this should be exp(log(lower) * 0.25 + | |||
log(upper) * 0.75). Otherwise, this should be (lower * 0.25 + upper | |||
* 0.75). */ | |||
#define LADSPA_HINT_DEFAULT_HIGH 0x100 | |||
/* This default hint indicates that the suggested upper bound for the | |||
port should be used. */ | |||
#define LADSPA_HINT_DEFAULT_MAXIMUM 0x140 | |||
/* This default hint indicates that the number 0 should be used. Note | |||
that this default may be used in conjunction with | |||
LADSPA_HINT_TOGGLED. */ | |||
#define LADSPA_HINT_DEFAULT_0 0x200 | |||
/* This default hint indicates that the number 1 should be used. Note | |||
that this default may be used in conjunction with | |||
LADSPA_HINT_TOGGLED. */ | |||
#define LADSPA_HINT_DEFAULT_1 0x240 | |||
/* This default hint indicates that the number 100 should be used. */ | |||
#define LADSPA_HINT_DEFAULT_100 0x280 | |||
/* This default hint indicates that the Hz frequency of `concert A' | |||
should be used. This will be 440 unless the host uses an unusual | |||
tuning convention, in which case it may be within a few Hz. */ | |||
#define LADSPA_HINT_DEFAULT_440 0x2C0 | |||
#define LADSPA_IS_HINT_BOUNDED_BELOW(x) ((x) & LADSPA_HINT_BOUNDED_BELOW) | |||
#define LADSPA_IS_HINT_BOUNDED_ABOVE(x) ((x) & LADSPA_HINT_BOUNDED_ABOVE) | |||
#define LADSPA_IS_HINT_TOGGLED(x) ((x) & LADSPA_HINT_TOGGLED) | |||
#define LADSPA_IS_HINT_SAMPLE_RATE(x) ((x) & LADSPA_HINT_SAMPLE_RATE) | |||
#define LADSPA_IS_HINT_LOGARITHMIC(x) ((x) & LADSPA_HINT_LOGARITHMIC) | |||
#define LADSPA_IS_HINT_INTEGER(x) ((x) & LADSPA_HINT_INTEGER) | |||
#define LADSPA_IS_HINT_HAS_DEFAULT(x) ((x) & LADSPA_HINT_DEFAULT_MASK) | |||
#define LADSPA_IS_HINT_DEFAULT_MINIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ | |||
== LADSPA_HINT_DEFAULT_MINIMUM) | |||
#define LADSPA_IS_HINT_DEFAULT_LOW(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ | |||
== LADSPA_HINT_DEFAULT_LOW) | |||
#define LADSPA_IS_HINT_DEFAULT_MIDDLE(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ | |||
== LADSPA_HINT_DEFAULT_MIDDLE) | |||
#define LADSPA_IS_HINT_DEFAULT_HIGH(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ | |||
== LADSPA_HINT_DEFAULT_HIGH) | |||
#define LADSPA_IS_HINT_DEFAULT_MAXIMUM(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ | |||
== LADSPA_HINT_DEFAULT_MAXIMUM) | |||
#define LADSPA_IS_HINT_DEFAULT_0(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ | |||
== LADSPA_HINT_DEFAULT_0) | |||
#define LADSPA_IS_HINT_DEFAULT_1(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ | |||
== LADSPA_HINT_DEFAULT_1) | |||
#define LADSPA_IS_HINT_DEFAULT_100(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ | |||
== LADSPA_HINT_DEFAULT_100) | |||
#define LADSPA_IS_HINT_DEFAULT_440(x) (((x) & LADSPA_HINT_DEFAULT_MASK) \ | |||
== LADSPA_HINT_DEFAULT_440) | |||
typedef struct _LADSPA_PortRangeHint { | |||
/* Hints about the port. */ | |||
LADSPA_PortRangeHintDescriptor HintDescriptor; | |||
/* Meaningful when hint LADSPA_HINT_BOUNDED_BELOW is active. When | |||
LADSPA_HINT_SAMPLE_RATE is also active then this value should be | |||
multiplied by the relevant sample rate. */ | |||
LADSPA_Data LowerBound; | |||
/* Meaningful when hint LADSPA_HINT_BOUNDED_ABOVE is active. When | |||
LADSPA_HINT_SAMPLE_RATE is also active then this value should be | |||
multiplied by the relevant sample rate. */ | |||
LADSPA_Data UpperBound; | |||
} LADSPA_PortRangeHint; | |||
/*****************************************************************************/ | |||
/* Plugin Handles: | |||
This plugin handle indicates a particular instance of the plugin | |||
concerned. It is valid to compare this to NULL (0 for C++) but | |||
otherwise the host should not attempt to interpret it. The plugin | |||
may use it to reference internal instance data. */ | |||
typedef void * LADSPA_Handle; | |||
/*****************************************************************************/ | |||
/* Descriptor for a Type of Plugin: | |||
This structure is used to describe a plugin type. It provides a | |||
number of functions to examine the type, instantiate it, link it to | |||
buffers and workspaces and to run it. */ | |||
typedef struct _LADSPA_Descriptor { | |||
/* This numeric identifier indicates the plugin type | |||
uniquely. Plugin programmers may reserve ranges of IDs from a | |||
central body to avoid clashes. Hosts may assume that IDs are | |||
below 0x1000000. */ | |||
unsigned long UniqueID; | |||
/* This identifier can be used as a unique, case-sensitive | |||
identifier for the plugin type within the plugin file. Plugin | |||
types should be identified by file and label rather than by index | |||
or plugin name, which may be changed in new plugin | |||
versions. Labels must not contain white-space characters. */ | |||
const char * Label; | |||
/* This indicates a number of properties of the plugin. */ | |||
LADSPA_Properties Properties; | |||
/* This member points to the null-terminated name of the plugin | |||
(e.g. "Sine Oscillator"). */ | |||
const char * Name; | |||
/* This member points to the null-terminated string indicating the | |||
maker of the plugin. This can be an empty string but not NULL. */ | |||
const char * Maker; | |||
/* This member points to the null-terminated string indicating any | |||
copyright applying to the plugin. If no Copyright applies the | |||
string "None" should be used. */ | |||
const char * Copyright; | |||
/* This indicates the number of ports (input AND output) present on | |||
the plugin. */ | |||
unsigned long PortCount; | |||
/* This member indicates an array of port descriptors. Valid indices | |||
vary from 0 to PortCount-1. */ | |||
const LADSPA_PortDescriptor * PortDescriptors; | |||
/* This member indicates an array of null-terminated strings | |||
describing ports (e.g. "Frequency (Hz)"). Valid indices vary from | |||
0 to PortCount-1. */ | |||
const char * const * PortNames; | |||
/* This member indicates an array of range hints for each port (see | |||
above). Valid indices vary from 0 to PortCount-1. */ | |||
const LADSPA_PortRangeHint * PortRangeHints; | |||
/* This may be used by the plugin developer to pass any custom | |||
implementation data into an instantiate call. It must not be used | |||
or interpreted by the host. It is expected that most plugin | |||
writers will not use this facility as LADSPA_Handle should be | |||
used to hold instance data. */ | |||
void * ImplementationData; | |||
/* This member is a function pointer that instantiates a plugin. A | |||
handle is returned indicating the new plugin instance. The | |||
instantiation function accepts a sample rate as a parameter. The | |||
plugin descriptor from which this instantiate function was found | |||
must also be passed. This function must return NULL if | |||
instantiation fails. | |||
Note that instance initialisation should generally occur in | |||
activate() rather than here. */ | |||
LADSPA_Handle (*instantiate)(const struct _LADSPA_Descriptor * Descriptor, | |||
unsigned long SampleRate); | |||
/* This member is a function pointer that connects a port on an | |||
instantiated plugin to a memory location at which a block of data | |||
for the port will be read/written. The data location is expected | |||
to be an array of LADSPA_Data for audio ports or a single | |||
LADSPA_Data value for control ports. Memory issues will be | |||
managed by the host. The plugin must read/write the data at these | |||
locations every time run() or run_adding() is called and the data | |||
present at the time of this connection call should not be | |||
considered meaningful. | |||
connect_port() may be called more than once for a plugin instance | |||
to allow the host to change the buffers that the plugin is | |||
reading or writing. These calls may be made before or after | |||
activate() or deactivate() calls. | |||
connect_port() must be called at least once for each port before | |||
run() or run_adding() is called. When working with blocks of | |||
LADSPA_Data the plugin should pay careful attention to the block | |||
size passed to the run function as the block allocated may only | |||
just be large enough to contain the block of samples. | |||
Plugin writers should be aware that the host may elect to use the | |||
same buffer for more than one port and even use the same buffer | |||
for both input and output (see LADSPA_PROPERTY_INPLACE_BROKEN). | |||
However, overlapped buffers or use of a single buffer for both | |||
audio and control data may result in unexpected behaviour. */ | |||
void (*connect_port)(LADSPA_Handle Instance, | |||
unsigned long Port, | |||
LADSPA_Data * DataLocation); | |||
/* This member is a function pointer that initialises a plugin | |||
instance and activates it for use. This is separated from | |||
instantiate() to aid real-time support and so that hosts can | |||
reinitialise a plugin instance by calling deactivate() and then | |||
activate(). In this case the plugin instance must reset all state | |||
information dependent on the history of the plugin instance | |||
except for any data locations provided by connect_port() and any | |||
gain set by set_run_adding_gain(). If there is nothing for | |||
activate() to do then the plugin writer may provide a NULL rather | |||
than an empty function. | |||
When present, hosts must call this function once before run() (or | |||
run_adding()) is called for the first time. This call should be | |||
made as close to the run() call as possible and indicates to | |||
real-time plugins that they are now live. Plugins should not rely | |||
on a prompt call to run() after activate(). activate() may not be | |||
called again unless deactivate() is called first. Note that | |||
connect_port() may be called before or after a call to | |||
activate(). */ | |||
void (*activate)(LADSPA_Handle Instance); | |||
/* This method is a function pointer that runs an instance of a | |||
plugin for a block. Two parameters are required: the first is a | |||
handle to the particular instance to be run and the second | |||
indicates the block size (in samples) for which the plugin | |||
instance may run. | |||
Note that if an activate() function exists then it must be called | |||
before run() or run_adding(). If deactivate() is called for a | |||
plugin instance then the plugin instance may not be reused until | |||
activate() has been called again. | |||
If the plugin has the property LADSPA_PROPERTY_HARD_RT_CAPABLE | |||
then there are various things that the plugin should not do | |||
within the run() or run_adding() functions (see above). */ | |||
void (*run)(LADSPA_Handle Instance, | |||
unsigned long SampleCount); | |||
/* This method is a function pointer that runs an instance of a | |||
plugin for a block. This has identical behaviour to run() except | |||
in the way data is output from the plugin. When run() is used, | |||
values are written directly to the memory areas associated with | |||
the output ports. However when run_adding() is called, values | |||
must be added to the values already present in the memory | |||
areas. Furthermore, output values written must be scaled by the | |||
current gain set by set_run_adding_gain() (see below) before | |||
addition. | |||
run_adding() is optional. When it is not provided by a plugin, | |||
this function pointer must be set to NULL. When it is provided, | |||
the function set_run_adding_gain() must be provided also. */ | |||
void (*run_adding)(LADSPA_Handle Instance, | |||
unsigned long SampleCount); | |||
/* This method is a function pointer that sets the output gain for | |||
use when run_adding() is called (see above). If this function is | |||
never called the gain is assumed to default to 1. Gain | |||
information should be retained when activate() or deactivate() | |||
are called. | |||
This function should be provided by the plugin if and only if the | |||
run_adding() function is provided. When it is absent this | |||
function pointer must be set to NULL. */ | |||
void (*set_run_adding_gain)(LADSPA_Handle Instance, | |||
LADSPA_Data Gain); | |||
/* This is the counterpart to activate() (see above). If there is | |||
nothing for deactivate() to do then the plugin writer may provide | |||
a NULL rather than an empty function. | |||
Hosts must deactivate all activated units after they have been | |||
run() (or run_adding()) for the last time. This call should be | |||
made as close to the last run() call as possible and indicates to | |||
real-time plugins that they are no longer live. Plugins should | |||
not rely on prompt deactivation. Note that connect_port() may be | |||
called before or after a call to deactivate(). | |||
Deactivation is not similar to pausing as the plugin instance | |||
will be reinitialised when activate() is called to reuse it. */ | |||
void (*deactivate)(LADSPA_Handle Instance); | |||
/* Once an instance of a plugin has been finished with it can be | |||
deleted using the following function. The instance handle passed | |||
ceases to be valid after this call. | |||
If activate() was called for a plugin instance then a | |||
corresponding call to deactivate() must be made before cleanup() | |||
is called. */ | |||
void (*cleanup)(LADSPA_Handle Instance); | |||
} LADSPA_Descriptor; | |||
/**********************************************************************/ | |||
/* Accessing a Plugin: */ | |||
/* The exact mechanism by which plugins are loaded is host-dependent, | |||
however all most hosts will need to know is the name of shared | |||
object file containing the plugin types. To allow multiple hosts to | |||
share plugin types, hosts may wish to check for environment | |||
variable LADSPA_PATH. If present, this should contain a | |||
colon-separated path indicating directories that should be searched | |||
(in order) when loading plugin types. | |||
A plugin programmer must include a function called | |||
"ladspa_descriptor" with the following function prototype within | |||
the shared object file. This function will have C-style linkage (if | |||
you are using C++ this is taken care of by the `extern "C"' clause | |||
at the top of the file). | |||
A host will find the plugin shared object file by one means or | |||
another, find the ladspa_descriptor() function, call it, and | |||
proceed from there. | |||
Plugin types are accessed by index (not ID) using values from 0 | |||
upwards. Out of range indexes must result in this function | |||
returning NULL, so the plugin count can be determined by checking | |||
for the least index that results in NULL being returned. */ | |||
const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index); | |||
/* Datatype corresponding to the ladspa_descriptor() function. */ | |||
typedef const LADSPA_Descriptor * | |||
(*LADSPA_Descriptor_Function)(unsigned long Index); | |||
/**********************************************************************/ | |||
#ifdef __cplusplus | |||
} | |||
#endif | |||
#endif /* LADSPA_INCLUDED */ | |||
/* EOF */ |
@@ -0,0 +1,279 @@ | |||
/* | |||
* aeffectx.h - simple header to allow VeSTige compilation and eventually work | |||
* | |||
* Copyright (c) 2006 Javier Serrano Polo <jasp00/at/users.sourceforge.net> | |||
* | |||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 2 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public | |||
* License along with this program (see COPYING); if not, write to the | |||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |||
* Boston, MA 02110-1301 USA. | |||
* | |||
*/ | |||
#include <stdint.h> | |||
#ifndef _AEFFECTX_H | |||
#define _AEFFECTX_H | |||
#define CCONST(a, b, c, d)( ( ( (int) a ) << 24 ) | \ | |||
( ( (int) b ) << 16 ) | \ | |||
( ( (int) c ) << 8 ) | \ | |||
( ( (int) d ) << 0 ) ) | |||
#define audioMasterAutomate 0 | |||
#define audioMasterVersion 1 | |||
#define audioMasterCurrentId 2 | |||
#define audioMasterIdle 3 | |||
#define audioMasterPinConnected 4 | |||
// unsupported? 5 | |||
#define audioMasterWantMidi 6 | |||
#define audioMasterGetTime 7 | |||
#define audioMasterProcessEvents 8 | |||
#define audioMasterSetTime 9 | |||
#define audioMasterTempoAt 10 | |||
#define audioMasterGetNumAutomatableParameters 11 | |||
#define audioMasterGetParameterQuantization 12 | |||
#define audioMasterIOChanged 13 | |||
#define audioMasterNeedIdle 14 | |||
#define audioMasterSizeWindow 15 | |||
#define audioMasterGetSampleRate 16 | |||
#define audioMasterGetBlockSize 17 | |||
#define audioMasterGetInputLatency 18 | |||
#define audioMasterGetOutputLatency 19 | |||
#define audioMasterGetPreviousPlug 20 | |||
#define audioMasterGetNextPlug 21 | |||
#define audioMasterWillReplaceOrAccumulate 22 | |||
#define audioMasterGetCurrentProcessLevel 23 | |||
#define audioMasterGetAutomationState 24 | |||
#define audioMasterOfflineStart 25 | |||
#define audioMasterOfflineRead 26 | |||
#define audioMasterOfflineWrite 27 | |||
#define audioMasterOfflineGetCurrentPass 28 | |||
#define audioMasterOfflineGetCurrentMetaPass 29 | |||
#define audioMasterSetOutputSampleRate 30 | |||
// unsupported? 31 | |||
#define audioMasterGetSpeakerArrangement 31 // deprecated in 2.4? | |||
#define audioMasterGetVendorString 32 | |||
#define audioMasterGetProductString 33 | |||
#define audioMasterGetVendorVersion 34 | |||
#define audioMasterVendorSpecific 35 | |||
#define audioMasterSetIcon 36 | |||
#define audioMasterCanDo 37 | |||
#define audioMasterGetLanguage 38 | |||
#define audioMasterOpenWindow 39 | |||
#define audioMasterCloseWindow 40 | |||
#define audioMasterGetDirectory 41 | |||
#define audioMasterUpdateDisplay 42 | |||
#define audioMasterBeginEdit 43 | |||
#define audioMasterEndEdit 44 | |||
#define audioMasterOpenFileSelector 45 | |||
#define audioMasterCloseFileSelector 46 // currently unused | |||
#define audioMasterEditFile 47 // currently unused | |||
#define audioMasterGetChunkFile 48 // currently unused | |||
#define audioMasterGetInputSpeakerArrangement 49 // currently unused | |||
#define effFlagsHasEditor 1 | |||
#define effFlagsCanReplacing (1 << 4) // very likely | |||
#define effFlagsIsSynth (1 << 8) // currently unused | |||
#define effOpen 0 | |||
#define effClose 1 // currently unused | |||
#define effSetProgram 2 // currently unused | |||
#define effGetProgram 3 // currently unused | |||
#define effGetProgramName 5 // currently unused | |||
#define effGetParamName 8 // currently unused | |||
#define effSetSampleRate 10 | |||
#define effSetBlockSize 11 | |||
#define effMainsChanged 12 | |||
#define effEditGetRect 13 | |||
#define effEditOpen 14 | |||
#define effEditClose 15 | |||
#define effEditIdle 19 | |||
#define effEditTop 20 | |||
#define effProcessEvents 25 | |||
#define effGetEffectName 45 | |||
#define effGetVendorString 47 | |||
#define effGetProductString 48 | |||
#define effGetVendorVersion 49 | |||
#define effCanDo 51 // currently unused | |||
/* from http://asseca.com/vst-24-specs/efGetParameterProperties.html */ | |||
#define effGetParameterProperties 56 | |||
#define effGetVstVersion 58 // currently unused | |||
#define kEffectMagic (CCONST( 'V', 's', 't', 'P' )) | |||
#define kVstLangEnglish 1 | |||
#define kVstMidiType 1 | |||
#define kVstTempoValid (1 << 10) | |||
#define kVstTransportPlaying (1 << 1) | |||
struct RemoteVstPlugin; | |||
#define kVstNanosValid (1 << 8) | |||
#define kVstPpqPosValid (1 << 9) | |||
#define kVstTempoValid (1 << 10) | |||
#define kVstBarsValid (1 << 11) | |||
#define kVstCyclePosValid (1 << 12) | |||
#define kVstTimeSigValid (1 << 13) | |||
#define kVstSmpteValid (1 << 14) | |||
#define kVstClockValid (1 << 15) | |||
struct _VstMidiEvent | |||
{ | |||
// 00 | |||
int type; | |||
// 04 | |||
int byteSize; | |||
// 08 | |||
int deltaFrames; | |||
// 0c? | |||
int flags; | |||
// 10? | |||
int noteLength; | |||
// 14? | |||
int noteOffset; | |||
// 18 | |||
char midiData[4]; | |||
// 1c? | |||
char detune; | |||
// 1d? | |||
char noteOffVelocity; | |||
// 1e? | |||
char reserved1; | |||
// 1f? | |||
char reserved2; | |||
}; | |||
typedef struct _VstMidiEvent VstMidiEvent; | |||
struct _VstEvent | |||
{ | |||
char dump[sizeof (VstMidiEvent)]; | |||
}; | |||
typedef struct _VstEvent VstEvent; | |||
struct _VstEvents | |||
{ | |||
// 00 | |||
int numEvents; | |||
// 04 | |||
void *reserved; | |||
// 08 | |||
VstEvent * events[]; | |||
}; | |||
typedef struct _VstEvents VstEvents; | |||
/* this struct taken from http://asseca.com/vst-24-specs/efGetParameterProperties.html */ | |||
struct _VstParameterProperties | |||
{ | |||
float stepFloat; | |||
float smallStepFloat; | |||
float largeStepFloat; | |||
char label[64]; | |||
int32_t flags; | |||
int32_t minInteger; | |||
int32_t maxInteger; | |||
int32_t stepInteger; | |||
int32_t largeStepInteger; | |||
char shortLabel[8]; | |||
}; | |||
typedef struct _VstParameterProperties VstParameterProperties; | |||
/* this enum taken from http://asseca.com/vst-24-specs/efGetParameterProperties.html */ | |||
enum VstParameterFlags | |||
{ | |||
kVstParameterIsSwitch = 1 << 0, /* parameter is a switch (on/off) */ | |||
kVstParameterUsesIntegerMinMax = 1 << 1, /* minInteger, maxInteger valid */ | |||
kVstParameterUsesFloatStep = 1 << 2, /* stepFloat, smallStepFloat, largeStepFloat valid */ | |||
kVstParameterUsesIntStep = 1 << 3, /* stepInteger, largeStepInteger valid */ | |||
kVstParameterSupportsDisplayIndex = 1 << 4, /* displayIndex valid */ | |||
kVstParameterSupportsDisplayCategory = 1 << 5, /* category, etc. valid */ | |||
kVstParameterCanRamp = 1 << 6 /* set if parameter value can ramp up/down */ | |||
}; | |||
struct _AEffect | |||
{ | |||
// Never use virtual functions!!! | |||
// 00-03 | |||
int magic; | |||
// dispatcher 04-07 | |||
intptr_t (* dispatcher) (struct _AEffect *, int, int, intptr_t, void *, float); | |||
// process, quite sure 08-0b | |||
void (* process) (struct _AEffect *, float **, float **, int); | |||
// setParameter 0c-0f | |||
void (* setParameter) (struct _AEffect *, int, float); | |||
// getParameter 10-13 | |||
float (* getParameter) (struct _AEffect *, int); | |||
// programs 14-17 | |||
int numPrograms; | |||
// Params 18-1b | |||
int numParams; | |||
// Input 1c-1f | |||
int numInputs; | |||
// Output 20-23 | |||
int numOutputs; | |||
// flags 24-27 | |||
int flags; | |||
// Fill somewhere 28-2b | |||
void *ptr1; | |||
void *ptr2; | |||
// Zeroes 2c-2f 30-33 34-37 38-3b | |||
char empty3[4 + 4 + 4]; | |||
// 1.0f 3c-3f | |||
float unkown_float; | |||
// An object? pointer 40-43 | |||
void *ptr3; | |||
// Zeroes 44-47 | |||
void *user; | |||
// Id 48-4b | |||
int32_t uniqueID; | |||
// Don't know 4c-4f | |||
char unknown1[4]; | |||
// processReplacing 50-53 | |||
void (* processReplacing) (struct _AEffect *, float **, float **, int); | |||
}; | |||
typedef struct _AEffect AEffect; | |||
struct _VstTimeInfo | |||
{ | |||
// 00 | |||
double samplePos; | |||
// 08 | |||
double sampleRate; | |||
// unconfirmed 10 18 | |||
char empty1[8 + 8]; | |||
// 20? | |||
double tempo; | |||
// unconfirmed 28 30 38 | |||
char empty2[8 + 8 + 8]; | |||
// 40? | |||
int timeSigNumerator; | |||
// 44? | |||
int timeSigDenominator; | |||
// unconfirmed 48 4c 50 | |||
char empty3[4 + 4 + 4]; | |||
// 54 | |||
int flags; | |||
}; | |||
typedef struct _VstTimeInfo VstTimeInfo; | |||
typedef intptr_t (* audioMasterCallback) (AEffect *, int32_t, int32_t, intptr_t, void *, float); | |||
#endif |
@@ -695,7 +695,6 @@ def recheck_all_plugins(qobject=None): | |||
# Parse all RDF files | |||
for i in range(len(rdf_files)): | |||
rdf_file = rdf_files[i] | |||
print(rdf_file) | |||
# Tell GUI we're parsing this bundle | |||
if (qobject): | |||