mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-10 04:30:12 +02:00
Delegate the plugin functionality to a class
This way we can hopefully contain all the manual memory management and raw pointers somewhat.
This commit is contained in:
+2
-1
@@ -25,7 +25,8 @@ include_dir = include_directories('src/include')
|
|||||||
common_src = []
|
common_src = []
|
||||||
|
|
||||||
linux_plugin_src = [
|
linux_plugin_src = [
|
||||||
'src/plugin/yabridge.cpp',
|
'src/plugin/bridge.cpp',
|
||||||
|
'src/plugin/plugin.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
wine_host_src = [
|
wine_host_src = [
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
#include "bridge.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
// TODO: I should track down the VST2 SDK for clarification on some of the
|
||||||
|
// implementation details, such as the use of intptr_t isntead of void*
|
||||||
|
// here.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle an event sent by the VST host. Most of these opcodes will be passed
|
||||||
|
* through to the winelib VST host.
|
||||||
|
*/
|
||||||
|
intptr_t Bridge::dispatch(AEffect* /*plugin*/,
|
||||||
|
int32_t opcode,
|
||||||
|
int32_t /*parameter*/,
|
||||||
|
intptr_t /*value*/,
|
||||||
|
void* result,
|
||||||
|
float /*option*/) {
|
||||||
|
switch (opcode) {
|
||||||
|
case effGetEffectName:
|
||||||
|
const std::string plugin_name("Hello, world!");
|
||||||
|
std::copy(plugin_name.begin(), plugin_name.end(),
|
||||||
|
static_cast<char*>(result));
|
||||||
|
|
||||||
|
// return 1; // TODO: Why?
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Unimplmemented
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bridge::process(AEffect* /*plugin*/,
|
||||||
|
float** /*inputs*/,
|
||||||
|
float** /*outputs*/,
|
||||||
|
int32_t /*sample_frames*/) {
|
||||||
|
// TODO: Unimplmemented
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bridge::set_parameter(AEffect* /*plugin*/,
|
||||||
|
int32_t /*index*/,
|
||||||
|
float /*value*/) {
|
||||||
|
// TODO: Unimplmemented
|
||||||
|
}
|
||||||
|
|
||||||
|
float Bridge::get_parameter(AEffect* /*plugin*/, int32_t /*index*/
|
||||||
|
) {
|
||||||
|
// TODO: Unimplmemented
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vestige/aeffect.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This handles the communication between the Linux native VST plugin and the
|
||||||
|
* Wine VST host. The functions below should be used as callback functions in an
|
||||||
|
* `AEffect` object.
|
||||||
|
*/
|
||||||
|
class Bridge {
|
||||||
|
public:
|
||||||
|
// The below four functions are the handlers from the VST2 API. They are
|
||||||
|
// called through proxy functions in `plugin.cpp`.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle an event sent by the VST host. Most of these opcodes will be
|
||||||
|
* passed through to the winelib VST host through a Unix domain socket.
|
||||||
|
*/
|
||||||
|
intptr_t dispatch(AEffect* plugin,
|
||||||
|
int32_t opcode,
|
||||||
|
int32_t parameter,
|
||||||
|
intptr_t value,
|
||||||
|
void* result,
|
||||||
|
float option);
|
||||||
|
void process(AEffect* plugin,
|
||||||
|
float** inputs,
|
||||||
|
float** outputs,
|
||||||
|
int32_t sample_frames);
|
||||||
|
void set_parameter(AEffect* plugin, int32_t index, float value);
|
||||||
|
float get_parameter(AEffect* plugin, int32_t index);
|
||||||
|
};
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
#include <vestige/aeffect.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "bridge.h"
|
||||||
|
|
||||||
|
#define VST_EXPORT __attribute__((visibility("default")))
|
||||||
|
|
||||||
|
// The main entry point for VST plugins should be called `VSTPluginMain``. The
|
||||||
|
// other two exist for legacy reasons since some old hosts might still use
|
||||||
|
// them.`
|
||||||
|
extern "C" {
|
||||||
|
extern VST_EXPORT AEffect* VSTPluginMain(audioMasterCallback);
|
||||||
|
|
||||||
|
VST_EXPORT AEffect* MAIN(audioMasterCallback audioMaster) {
|
||||||
|
return VSTPluginMain(audioMaster);
|
||||||
|
}
|
||||||
|
|
||||||
|
VST_EXPORT AEffect* main_plugin(audioMasterCallback audioMaster) {
|
||||||
|
return VSTPluginMain(audioMaster);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
intptr_t dispatch(AEffect*, int32_t, int32_t, intptr_t, void*, float);
|
||||||
|
void process(AEffect*, float**, float**, int32_t);
|
||||||
|
void setParameter(AEffect*, int32_t, float);
|
||||||
|
float getParameter(AEffect*, int32_t);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the bridge instance stored in an unused pointer from a VST plugin.
|
||||||
|
* This is sadly needed as a workaround to avoid using globals since we need
|
||||||
|
* free function pointers to interface with the VST API.
|
||||||
|
*/
|
||||||
|
Bridge* get_bridge_instance(const AEffect& plugin) {
|
||||||
|
return static_cast<Bridge*>(plugin.ptr3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main VST plugin entry point. This finds the Windows VST plugin that
|
||||||
|
* should be run, executes it in our VST host inside Wine, and sets up
|
||||||
|
* communication between the two processes.
|
||||||
|
*
|
||||||
|
* This is a bit of a mess since we're interacting with an external C API. To
|
||||||
|
* keep this somewhat contained this is the only place where we're doing manual
|
||||||
|
* memory management.
|
||||||
|
*/
|
||||||
|
VST_EXPORT AEffect* VSTPluginMain(audioMasterCallback /*audioMaster*/) {
|
||||||
|
// TODO: Since we are returning raw pointers, how does cleanup work?
|
||||||
|
AEffect* plugin = new AEffect();
|
||||||
|
plugin->ptr3 = new Bridge();
|
||||||
|
|
||||||
|
plugin->dispatcher = dispatch;
|
||||||
|
plugin->process = process;
|
||||||
|
plugin->setParameter = setParameter;
|
||||||
|
plugin->getParameter = getParameter;
|
||||||
|
// // XXX: processReplacing?
|
||||||
|
|
||||||
|
// TODO: Add more and actual data
|
||||||
|
plugin->magic = kEffectMagic;
|
||||||
|
plugin->numParams = 69;
|
||||||
|
plugin->uniqueID = 69420;
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The below functions are proxy functions for the methods defined in
|
||||||
|
// `Bridge.cpp`
|
||||||
|
|
||||||
|
intptr_t dispatch(AEffect* plugin,
|
||||||
|
int32_t opcode,
|
||||||
|
int32_t parameter,
|
||||||
|
intptr_t value,
|
||||||
|
void* result,
|
||||||
|
float option) {
|
||||||
|
return get_bridge_instance(*plugin)->dispatch(plugin, opcode, parameter,
|
||||||
|
value, result, option);
|
||||||
|
}
|
||||||
|
|
||||||
|
void process(AEffect* plugin,
|
||||||
|
float** inputs,
|
||||||
|
float** outputs,
|
||||||
|
int32_t sample_frames) {
|
||||||
|
return get_bridge_instance(*plugin)->process(plugin, inputs, outputs,
|
||||||
|
sample_frames);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setParameter(AEffect* plugin, int32_t index, float value) {
|
||||||
|
return get_bridge_instance(*plugin)->set_parameter(plugin, index, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
float getParameter(AEffect* plugin, int32_t index) {
|
||||||
|
return get_bridge_instance(*plugin)->get_parameter(plugin, index);
|
||||||
|
}
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
#include <vestige/aeffect.h>
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#define VST_EXPORT __attribute__((visibility("default")))
|
|
||||||
|
|
||||||
// The main entry point for VST plugins should be called `VSTPluginMain``. The
|
|
||||||
// other two exist for legacy reasons since some old hosts might still use
|
|
||||||
// them.`
|
|
||||||
extern "C" {
|
|
||||||
extern VST_EXPORT AEffect* VSTPluginMain(audioMasterCallback);
|
|
||||||
|
|
||||||
VST_EXPORT AEffect* MAIN(audioMasterCallback audioMaster) {
|
|
||||||
return VSTPluginMain(audioMaster);
|
|
||||||
}
|
|
||||||
|
|
||||||
VST_EXPORT AEffect* main_plugin(audioMasterCallback audioMaster) {
|
|
||||||
return VSTPluginMain(audioMaster);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
intptr_t dispatch(AEffect*, int32_t, int32_t, intptr_t, void*, float);
|
|
||||||
void process(AEffect*, float**, float**, int32_t);
|
|
||||||
void setParameter(AEffect*, int32_t, float);
|
|
||||||
float getParameter(AEffect*, int32_t);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The main VST plugin entry point. This finds the Windows VST plugin that
|
|
||||||
* should be run, executes it in our VST host inside Wine, and sets up
|
|
||||||
* communication between the two processes.
|
|
||||||
*/
|
|
||||||
VST_EXPORT AEffect* VSTPluginMain(audioMasterCallback /*audioMaster*/) {
|
|
||||||
// TODO: Do something useful ehre
|
|
||||||
std::cout << "Hello, world!" << std::endl;
|
|
||||||
|
|
||||||
AEffect* effect = new AEffect();
|
|
||||||
effect->magic = kEffectMagic;
|
|
||||||
effect->dispatcher = dispatch;
|
|
||||||
effect->process = process;
|
|
||||||
// XXX: processReplacing?
|
|
||||||
effect->setParameter = setParameter;
|
|
||||||
effect->getParameter = getParameter;
|
|
||||||
effect->numParams = 69;
|
|
||||||
effect->uniqueID = 69420;
|
|
||||||
|
|
||||||
return effect;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: I should track down the VST2 SDK for clarification on some of the
|
|
||||||
// implementation details, such as the use of intptr_t isntead of void*
|
|
||||||
// here.
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle an event sent by the VST host.
|
|
||||||
*
|
|
||||||
* TODO: Look up what the return value here is actually doing.
|
|
||||||
*/
|
|
||||||
intptr_t dispatch(AEffect* /*effect*/,
|
|
||||||
int32_t opcode,
|
|
||||||
int32_t /*parameter*/,
|
|
||||||
intptr_t /*value*/,
|
|
||||||
void* result,
|
|
||||||
float /*option*/) {
|
|
||||||
switch (opcode) {
|
|
||||||
case effGetEffectName:
|
|
||||||
const std::string plugin_name("Hello, world!");
|
|
||||||
std::copy(plugin_name.begin(), plugin_name.end(),
|
|
||||||
static_cast<char*>(result));
|
|
||||||
|
|
||||||
return 1; // TODO: Why?
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Unimplmemented
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void process(AEffect*, float**, float**, int32_t) {
|
|
||||||
// TODO: Unimplmemented
|
|
||||||
}
|
|
||||||
|
|
||||||
void setParameter(AEffect*, int32_t, float) {
|
|
||||||
// TODO: Unimplmemented
|
|
||||||
}
|
|
||||||
|
|
||||||
float getParameter(AEffect*, int32_t) {
|
|
||||||
// TODO: Unimplmemented
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user