mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-10 04:30:12 +02:00
Pass through getParameter and setParameter
This commit is contained in:
@@ -104,8 +104,6 @@ struct EventResult {
|
|||||||
*/
|
*/
|
||||||
std::optional<std::string> data;
|
std::optional<std::string> data;
|
||||||
|
|
||||||
// TODO: Add missing return value fields;
|
|
||||||
|
|
||||||
template <typename S>
|
template <typename S>
|
||||||
void serialize(S& s) {
|
void serialize(S& s) {
|
||||||
s.value8b(return_value);
|
s.value8b(return_value);
|
||||||
@@ -114,6 +112,37 @@ struct EventResult {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a call to either `getParameter` or `setParameter`, depending on
|
||||||
|
* whether `value` contains a value or not.
|
||||||
|
*/
|
||||||
|
struct Parameter {
|
||||||
|
int32_t index;
|
||||||
|
std::optional<float> value;
|
||||||
|
|
||||||
|
template <typename S>
|
||||||
|
void serialize(S& s) {
|
||||||
|
s.value4b(index);
|
||||||
|
s.ext(value, bitsery::ext::StdOptional(),
|
||||||
|
[](S& s, auto& v) { s.value4b(v); });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The result of a `getParameter` or a `setParameter` call. For `setParameter`
|
||||||
|
* this struct won't contain any values and mostly acts as an acknowledgement
|
||||||
|
* from the Wine VST host.
|
||||||
|
*/
|
||||||
|
struct ParameterResult {
|
||||||
|
std::optional<float> value;
|
||||||
|
|
||||||
|
template <typename S>
|
||||||
|
void serialize(S& s) {
|
||||||
|
s.ext(value, bitsery::ext::StdOptional(),
|
||||||
|
[](S& s, auto& v) { s.value4b(v); });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The serialization function for `AEffect` structs. This will s serialize all
|
* The serialization function for `AEffect` structs. This will s serialize all
|
||||||
* of the values but it will not touch any of the pointer fields. That way you
|
* of the values but it will not touch any of the pointer fields. That way you
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ HostBridge::HostBridge(audioMasterCallback host_callback)
|
|||||||
socket_acceptor(io_context, socket_endpoint),
|
socket_acceptor(io_context, socket_endpoint),
|
||||||
host_vst_dispatch(io_context),
|
host_vst_dispatch(io_context),
|
||||||
vst_host_callback(io_context),
|
vst_host_callback(io_context),
|
||||||
|
host_vst_parameters(io_context),
|
||||||
vst_host_aeffect(io_context),
|
vst_host_aeffect(io_context),
|
||||||
host_callback_function(host_callback),
|
host_callback_function(host_callback),
|
||||||
vst_host(find_wine_vst_host(),
|
vst_host(find_wine_vst_host(),
|
||||||
@@ -84,6 +85,7 @@ HostBridge::HostBridge(audioMasterCallback host_callback)
|
|||||||
// in the Wine VST host
|
// in the Wine VST host
|
||||||
socket_acceptor.accept(host_vst_dispatch);
|
socket_acceptor.accept(host_vst_dispatch);
|
||||||
socket_acceptor.accept(vst_host_callback);
|
socket_acceptor.accept(vst_host_callback);
|
||||||
|
socket_acceptor.accept(host_vst_parameters);
|
||||||
socket_acceptor.accept(vst_host_aeffect);
|
socket_acceptor.accept(vst_host_aeffect);
|
||||||
|
|
||||||
// Set up all pointers for our `AEffect` struct. We will fill this with data
|
// Set up all pointers for our `AEffect` struct. We will fill this with data
|
||||||
@@ -160,15 +162,22 @@ void HostBridge::process_replacing(AEffect* /*plugin*/,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HostBridge::set_parameter(AEffect* /*plugin*/,
|
void HostBridge::set_parameter(AEffect* /*plugin*/,
|
||||||
int32_t /*index*/,
|
int32_t index,
|
||||||
float /*value*/) {
|
float value) {
|
||||||
// TODO: Unimplmemented
|
Parameter request{index, value};
|
||||||
|
write_object(host_vst_parameters, request);
|
||||||
|
|
||||||
|
// This should not contain any values and just serve as an acknowledgement
|
||||||
|
const auto response = read_object<ParameterResult>(host_vst_parameters);
|
||||||
|
assert(!response.value.has_value());
|
||||||
}
|
}
|
||||||
|
|
||||||
float HostBridge::get_parameter(AEffect* /*plugin*/, int32_t /*index*/
|
float HostBridge::get_parameter(AEffect* /*plugin*/, int32_t index) {
|
||||||
) {
|
Parameter request{index, std::nullopt};
|
||||||
// TODO: Unimplmemented
|
write_object(host_vst_parameters, request);
|
||||||
return 0.0f;
|
|
||||||
|
const auto response = read_object<ParameterResult>(host_vst_parameters);
|
||||||
|
return response.value.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -84,6 +84,14 @@ class HostBridge {
|
|||||||
// plugin (through the Wine VST host).
|
// plugin (through the Wine VST host).
|
||||||
boost::asio::local::stream_protocol::socket host_vst_dispatch;
|
boost::asio::local::stream_protocol::socket host_vst_dispatch;
|
||||||
boost::asio::local::stream_protocol::socket vst_host_callback;
|
boost::asio::local::stream_protocol::socket vst_host_callback;
|
||||||
|
/**
|
||||||
|
* Used for both `getParameter` and `setParameter` since they mostly
|
||||||
|
* overlap.
|
||||||
|
*
|
||||||
|
* TODO: Verify that these 100% won't be called simultanously since that
|
||||||
|
* would cause a race condition.
|
||||||
|
*/
|
||||||
|
boost::asio::local::stream_protocol::socket host_vst_parameters;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This socket only handles updates of the `AEffect` struct instead of
|
* This socket only handles updates of the `AEffect` struct instead of
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ PluginBridge::PluginBridge(std::string plugin_dll_path,
|
|||||||
socket_endpoint(socket_endpoint_path),
|
socket_endpoint(socket_endpoint_path),
|
||||||
host_vst_dispatch(io_context),
|
host_vst_dispatch(io_context),
|
||||||
vst_host_callback(io_context),
|
vst_host_callback(io_context),
|
||||||
|
host_vst_parameters(io_context),
|
||||||
vst_host_aeffect(io_context) {
|
vst_host_aeffect(io_context) {
|
||||||
// Got to love these C APIs
|
// Got to love these C APIs
|
||||||
if (plugin_handle == nullptr) {
|
if (plugin_handle == nullptr) {
|
||||||
@@ -86,6 +87,7 @@ PluginBridge::PluginBridge(std::string plugin_dll_path,
|
|||||||
// in the Linus plugin
|
// in the Linus plugin
|
||||||
host_vst_dispatch.connect(socket_endpoint);
|
host_vst_dispatch.connect(socket_endpoint);
|
||||||
vst_host_callback.connect(socket_endpoint);
|
vst_host_callback.connect(socket_endpoint);
|
||||||
|
host_vst_parameters.connect(socket_endpoint);
|
||||||
vst_host_aeffect.connect(socket_endpoint);
|
vst_host_aeffect.connect(socket_endpoint);
|
||||||
|
|
||||||
// Initialize after communication has been set up We'll try to do the same
|
// Initialize after communication has been set up We'll try to do the same
|
||||||
@@ -117,6 +119,30 @@ PluginBridge::PluginBridge(std::string plugin_dll_path,
|
|||||||
passthrough_event(host_vst_dispatch, plugin, plugin->dispatcher);
|
passthrough_event(host_vst_dispatch, plugin, plugin->dispatcher);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
parameters_handler = std::thread([&]() {
|
||||||
|
while (true) {
|
||||||
|
// Both `getParameter` and `setParameter` functions are passed
|
||||||
|
// through on this socket since they have a lot of overlap. The
|
||||||
|
// presence of the `value` field tells us which one we're dealing
|
||||||
|
// with.
|
||||||
|
auto request = read_object<Parameter>(host_vst_parameters);
|
||||||
|
if (request.value.has_value()) {
|
||||||
|
// `setParameter`
|
||||||
|
plugin->setParameter(plugin, request.index,
|
||||||
|
request.value.value());
|
||||||
|
|
||||||
|
ParameterResult response{std::nullopt};
|
||||||
|
write_object(host_vst_parameters, response);
|
||||||
|
} else {
|
||||||
|
// `getParameter`
|
||||||
|
float value = plugin->getParameter(plugin, request.index);
|
||||||
|
|
||||||
|
ParameterResult response{value};
|
||||||
|
write_object(host_vst_parameters, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void PluginBridge::wait() {
|
void PluginBridge::wait() {
|
||||||
|
|||||||
@@ -77,6 +77,11 @@ class PluginBridge {
|
|||||||
// plugin (through the Wine VST host).
|
// plugin (through the Wine VST host).
|
||||||
boost::asio::local::stream_protocol::socket host_vst_dispatch;
|
boost::asio::local::stream_protocol::socket host_vst_dispatch;
|
||||||
boost::asio::local::stream_protocol::socket vst_host_callback;
|
boost::asio::local::stream_protocol::socket vst_host_callback;
|
||||||
|
/**
|
||||||
|
* Used for both `getParameter` and `setParameter` since they mostly
|
||||||
|
* overlap.
|
||||||
|
*/
|
||||||
|
boost::asio::local::stream_protocol::socket host_vst_parameters;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This socket only handles updates of the `AEffect` struct instead of
|
* This socket only handles updates of the `AEffect` struct instead of
|
||||||
@@ -89,6 +94,10 @@ class PluginBridge {
|
|||||||
* The thread that handles dispatch events from the host.
|
* The thread that handles dispatch events from the host.
|
||||||
*/
|
*/
|
||||||
std::thread dispatch_handler;
|
std::thread dispatch_handler;
|
||||||
|
/**
|
||||||
|
* The thread that responds to `getParameter` and `setParameter` requests.
|
||||||
|
*/
|
||||||
|
std::thread parameters_handler;
|
||||||
|
|
||||||
// TODO: Set up all other callback handlers
|
// TODO: Set up process and processReplacing callback handlers
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user