Change the naming scheme for class field members

I'm not a fan of Hungarian notation, but C++ kind of needs it with its
implicit `this`. And of all the common options for this, I find
suffixing members with an underscore the least offensive one.
This commit is contained in:
Robbert van der Helm
2022-01-01 21:07:17 +01:00
parent e0ab24e645
commit 0b9a16cf40
169 changed files with 2448 additions and 2405 deletions
+81 -80
View File
@@ -79,50 +79,50 @@ class PluginBridge {
PluginBridge(PluginType plugin_type, F&& create_socket_instance)
// This is still correct for VST3 plugins because we can configure an
// entire directory (the module's bundle) at once
: config(load_config_for(get_this_file_location())),
info(plugin_type, config.vst3_prefer_32bit),
io_context(),
sockets(create_socket_instance(io_context, info)),
generic_logger(Logger::create_from_environment(
create_logger_prefix(sockets.base_dir))),
plugin_host(
config.group
: config_(load_config_for(get_this_file_location())),
info_(plugin_type, config_.vst3_prefer_32bit),
io_context_(),
sockets_(create_socket_instance(io_context_, info_)),
generic_logger_(Logger::create_from_environment(
create_logger_prefix(sockets_.base_dir_))),
plugin_host_(
config_.group
? std::unique_ptr<HostProcess>(std::make_unique<GroupHost>(
io_context,
generic_logger,
config,
sockets,
info,
io_context_,
generic_logger_,
config_,
sockets_,
info_,
HostRequest{
.plugin_type = plugin_type,
.plugin_path = info.windows_plugin_path.string(),
.endpoint_base_dir = sockets.base_dir.string(),
.plugin_path = info_.windows_plugin_path_.string(),
.endpoint_base_dir = sockets_.base_dir_.string(),
.parent_pid = getpid()}))
: std::unique_ptr<HostProcess>(
std::make_unique<IndividualHost>(
io_context,
generic_logger,
config,
sockets,
info,
HostRequest{
.plugin_type = plugin_type,
.plugin_path =
info.windows_plugin_path.string(),
.endpoint_base_dir = sockets.base_dir.string(),
.parent_pid = getpid()}))),
has_realtime_priority(has_realtime_priority_promise.get_future()),
wine_io_handler([&]() {
io_context_,
generic_logger_,
config_,
sockets_,
info_,
HostRequest{.plugin_type = plugin_type,
.plugin_path =
info_.windows_plugin_path_.string(),
.endpoint_base_dir =
sockets_.base_dir_.string(),
.parent_pid = getpid()}))),
has_realtime_priority_(has_realtime_priority_promise_.get_future()),
wine_io_handler_([&]() {
// We no longer run this thread with realtime scheduling because
// plugins that produce a lot of FIXMEs could in theory cause
// dropouts that way, but we still need to run this from a thread
// to check whether we support it
has_realtime_priority_promise.set_value(
has_realtime_priority_promise_.set_value(
set_realtime_priority(true));
set_realtime_priority(false);
pthread_setname_np(pthread_self(), "wine-stdio");
io_context.run();
io_context_.run();
}) {}
virtual ~PluginBridge() noexcept {};
@@ -139,14 +139,15 @@ class PluginBridge {
<< " (32-bit build)"
#endif
<< std::endl;
init_msg << "host: '" << plugin_host->path().string() << "'"
init_msg << "host: '" << plugin_host_->path().string() << "'"
<< std::endl;
init_msg << "plugin: '" << info.windows_plugin_path.string()
init_msg << "plugin: '" << info_.windows_plugin_path_.string()
<< "'" << std::endl;
init_msg << "plugin type: '"
<< plugin_type_to_string(info.plugin_type) << "'" << std::endl;
<< plugin_type_to_string(info_.plugin_type_) << "'"
<< std::endl;
init_msg << "realtime: ";
if (has_realtime_priority.get()) {
if (has_realtime_priority_.get()) {
// Warn if `RLIMIT_RTTIME` is set to some low value. This can happen
// when using PipeWire.
if (auto rttime_limit = get_rttime_limit()) {
@@ -225,7 +226,7 @@ class PluginBridge {
<< "memlock limit: 'WARNING: Could not fetch RLIMIT_MEMLOCK'"
<< std::endl;
}
init_msg << "sockets: '" << sockets.base_dir.string() << "'"
init_msg << "sockets: '" << sockets_.base_dir_.string() << "'"
<< std::endl;
init_msg << "wine prefix: '";
@@ -239,10 +240,10 @@ class PluginBridge {
},
[&](const DefaultWinePrefix&) { init_msg << "<default>"; },
},
info.wine_prefix);
info_.wine_prefix_);
init_msg << "'" << std::endl;
init_msg << "wine version: '" << info.wine_version() << "'"
init_msg << "wine version: '" << info_.wine_version() << "'"
<< std::endl;
init_msg << std::endl;
@@ -251,21 +252,21 @@ class PluginBridge {
// useful but it'll be very noisy and it's likely going to be clear from
// the shown values anyways.
init_msg << "config from: '";
if (config.matched_file && config.matched_pattern) {
init_msg << config.matched_file->string() << ", section \""
<< *config.matched_pattern << "\"";
if (config_.matched_file && config_.matched_pattern) {
init_msg << config_.matched_file->string() << ", section \""
<< *config_.matched_pattern << "\"";
} else {
init_msg << "<defaults>";
}
init_msg << "'" << std::endl;
init_msg << "hosting mode: '";
if (config.group) {
init_msg << "plugin group \"" << *config.group << "\"";
if (config_.group) {
init_msg << "plugin group \"" << *config_.group << "\"";
} else {
init_msg << "individually";
}
switch (info.plugin_arch) {
switch (info_.plugin_arch_) {
case LibArchitecture::dll_32:
init_msg << ", 32-bit";
break;
@@ -277,33 +278,33 @@ class PluginBridge {
init_msg << "other options: ";
std::vector<std::string> other_options;
if (config.disable_pipes) {
if (config_.disable_pipes) {
other_options.push_back(
"hack: pipes disabled, plugin output will go to \"" +
config.disable_pipes->string() + "\"");
config_.disable_pipes->string() + "\"");
}
if (config.editor_coordinate_hack) {
if (config_.editor_coordinate_hack) {
other_options.push_back("editor: coordinate hack");
}
if (config.editor_force_dnd) {
if (config_.editor_force_dnd) {
other_options.push_back("editor: force drag-and-drop");
}
if (config.editor_xembed) {
if (config_.editor_xembed) {
other_options.push_back("editor: XEmbed");
}
if (config.frame_rate) {
if (config_.frame_rate) {
std::ostringstream option;
option << "frame rate: " << std::setprecision(2)
<< *config.frame_rate << " fps";
<< *config_.frame_rate << " fps";
other_options.push_back(option.str());
}
if (config.hide_daw) {
if (config_.hide_daw) {
other_options.push_back("hack: hide DAW name");
}
if (config.vst3_no_scaling) {
if (config_.vst3_no_scaling) {
other_options.push_back("vst3: no GUI scaling");
}
if (config.vst3_prefer_32bit) {
if (config_.vst3_prefer_32bit) {
other_options.push_back("vst3: prefer 32-bit");
}
if (!other_options.empty()) {
@@ -315,14 +316,14 @@ class PluginBridge {
// To make debugging easier, we'll print both unrecognized options (that
// might be left over when an option gets removed) as well as options
// have the wrong argument types
if (!config.invalid_options.empty()) {
if (!config_.invalid_options.empty()) {
init_msg << "invalid arguments: "
<< join_quoted_strings(config.invalid_options)
<< join_quoted_strings(config_.invalid_options)
<< " (check the readme for more information)" << std::endl;
}
if (!config.unknown_options.empty()) {
if (!config_.unknown_options.empty()) {
init_msg << "unrecognized options: "
<< join_quoted_strings(config.unknown_options)
<< join_quoted_strings(config_.unknown_options)
<< std::endl;
}
init_msg << std::endl;
@@ -345,7 +346,7 @@ class PluginBridge {
init_msg << std::endl;
for (std::string line = ""; std::getline(init_msg, line);) {
generic_logger.log(line);
generic_logger_.log(line);
}
}
@@ -367,14 +368,14 @@ class PluginBridge {
// and throw when it is not. The alternative would be to rewrite this to
// using `async_accept`, Boost.Asio timers, and another IO context, but
// I feel like this a much simpler solution.
host_watchdog_handler = std::jthread([&](std::stop_token st) {
host_watchdog_handler_ = std::jthread([&](std::stop_token st) {
using namespace std::literals::chrono_literals;
pthread_setname_np(pthread_self(), "watchdog");
while (!st.stop_requested()) {
if (!plugin_host->running()) {
generic_logger.log(
if (!plugin_host_->running()) {
generic_logger_.log(
"The Wine host process has exited unexpectedly. Check "
"the output above for more information.");
@@ -396,9 +397,9 @@ class PluginBridge {
});
#endif
sockets.connect();
sockets_.connect();
#ifndef WITH_WINEDBG
host_watchdog_handler.request_stop();
host_watchdog_handler_.request_stop();
#endif
}
@@ -410,13 +411,13 @@ class PluginBridge {
*/
void warn_on_version_mismatch(const std::string& host_version) {
if (host_version != yabridge_git_version) {
generic_logger.log(
generic_logger_.log(
"WARNING: The host application's version does not match");
generic_logger.log(
generic_logger_.log(
" this plugin's. If you just updated yabridge, then");
generic_logger.log(
generic_logger_.log(
" you may need rerun 'yabridgectl sync' first to");
generic_logger.log(" update your plugins.");
generic_logger_.log(" update your plugins.");
send_notification(
"Version mismatch",
@@ -432,24 +433,24 @@ class PluginBridge {
*
* @see ../utils.h:load_config_for
*/
Configuration config;
Configuration config_;
/**
* Information about the plugin we're bridging.
*/
const PluginInfo info;
const PluginInfo info_;
boost::asio::io_context io_context;
boost::asio::io_context io_context_;
/**
* The sockets used for communication with the Wine process.
*
* @remark `sockets.connect()` should not be called directly.
* @remark `sockets_.connect()` should not be called directly.
* `connect_sockets_guarded()` should be used instead.
*
* @see PluginBridge::connect_sockets_guarded
*/
TSockets sockets;
TSockets sockets_;
/**
* The logging facility used for this instance of yabridge. See
@@ -457,20 +458,20 @@ class PluginBridge {
*
* @see Logger::create_from_env
*/
Logger generic_logger;
Logger generic_logger_;
/**
* The Wine process hosting our plugins. In the case of group hosts a
* `PluginBridge` instance doesn't actually own a process, but rather either
* spawns a new detached process or it connects to an existing one.
*/
std::unique_ptr<HostProcess> plugin_host;
std::unique_ptr<HostProcess> plugin_host_;
private:
/**
* The promise belonging to `has_realtime_priority` below.
* The promise belonging to `has_realtime_priority_` below.
*/
std::promise<bool> has_realtime_priority_promise;
std::promise<bool> has_realtime_priority_promise_;
public:
/**
@@ -480,13 +481,13 @@ class PluginBridge {
* that's initializing the plugin because some DAWs may do that from the UI
* thread.
*/
std::future<bool> has_realtime_priority;
std::future<bool> has_realtime_priority_;
/**
* Runs the Boost.Asio `io_context` thread for logging the Wine process
* Runs the Boost.Asio `io_context_` thread for logging the Wine process
* STDOUT and STDERR messages.
*/
std::jthread wine_io_handler;
std::jthread wine_io_handler_;
private:
/**
@@ -496,5 +497,5 @@ class PluginBridge {
* detach the thread as it has to check whether the VST host is still
* running.
*/
std::jthread host_watchdog_handler;
std::jthread host_watchdog_handler_;
};
+120 -118
View File
@@ -41,7 +41,7 @@ Vst2PluginBridge::Vst2PluginBridge(audioMasterCallback host_callback)
[](boost::asio::io_context& io_context, const PluginInfo& info) {
return Vst2Sockets<std::jthread>(
io_context,
generate_endpoint_base(info.native_library_path.filename()
generate_endpoint_base(info.native_library_path_.filename()
.replace_extension("")
.string()),
true);
@@ -49,9 +49,9 @@ Vst2PluginBridge::Vst2PluginBridge(audioMasterCallback host_callback)
// All the fields should be zero initialized because
// `Vst2PluginInstance::vstAudioMasterCallback` from Bitwig's plugin
// bridge will crash otherwise
plugin(),
host_callback_function(host_callback),
logger(generic_logger) {
plugin_(),
host_callback_function_(host_callback),
logger_(generic_logger_) {
log_init_message();
// This will block until all sockets have been connected to by the Wine VST
@@ -60,23 +60,23 @@ Vst2PluginBridge::Vst2PluginBridge(audioMasterCallback host_callback)
// Set up all pointers for our `AEffect` struct. We will fill this with data
// from the VST plugin loaded in Wine at the end of this constructor.
plugin.ptr3 = this;
plugin.dispatcher = dispatch_proxy;
plugin.process = process_proxy;
plugin.setParameter = set_parameter_proxy;
plugin.getParameter = get_parameter_proxy;
plugin.processReplacing = process_replacing_proxy;
plugin.processDoubleReplacing = process_double_replacing_proxy;
plugin_.ptr3 = this;
plugin_.dispatcher = dispatch_proxy;
plugin_.process = process_proxy;
plugin_.setParameter = set_parameter_proxy;
plugin_.getParameter = get_parameter_proxy;
plugin_.processReplacing = process_replacing_proxy;
plugin_.processDoubleReplacing = process_double_replacing_proxy;
// For our communication we use simple threads and blocking operations
// instead of asynchronous IO since communication has to be handled in
// lockstep anyway
host_callback_handler = std::jthread([&]() {
host_callback_handler_ = std::jthread([&]() {
set_realtime_priority(true);
pthread_setname_np(pthread_self(), "host-callbacks");
sockets.vst_host_callback.receive_events(
std::pair<Vst2Logger&, bool>(logger, false),
sockets_.vst_host_callback_.receive_events(
std::pair<Vst2Logger&, bool>(logger_, false),
[&](Vst2Event& event, bool /*on_main_thread*/) {
switch (event.opcode) {
// MIDI events sent from the plugin back to the host are
@@ -87,9 +87,9 @@ Vst2PluginBridge::Vst2PluginBridge(audioMasterCallback host_callback)
// actually send them to the host at the end of the
// `process_replacing()` function.
case audioMasterProcessEvents: {
std::lock_guard lock(incoming_midi_events_mutex);
std::lock_guard lock(incoming_midi_events_mutex_);
incoming_midi_events.push_back(
incoming_midi_events_.push_back(
std::get<DynamicVstEvents>(event.payload));
return Vst2EventResult{.return_value = 1,
@@ -102,9 +102,9 @@ Vst2PluginBridge::Vst2PluginBridge(audioMasterCallback host_callback)
// store the last resize request and then only pass it to
// the host when it calls `effEditIdle()`.
case audioMasterSizeWindow: {
std::lock_guard lock(incoming_resize_mutex);
std::lock_guard lock(incoming_resize_mutex_);
incoming_resize = std::pair(event.index, event.value);
incoming_resize_ = std::pair(event.index, event.value);
return Vst2EventResult{.return_value = 1,
.payload = nullptr,
@@ -120,11 +120,13 @@ Vst2PluginBridge::Vst2PluginBridge(audioMasterCallback host_callback)
// initialization, and at that point we will not yet
// have sent the configuration to the plugin.
case audioMasterGetProductString: {
if (config.hide_daw) {
logger.log("The plugin asked for the host's name.");
logger.log("Reporting \"" +
std::string(product_name_override) +
"\" instead of the actual host's name.");
if (config_.hide_daw) {
logger_.log(
"The plugin asked for the host's name.");
logger_.log(
"Reporting \"" +
std::string(product_name_override) +
"\" instead of the actual host's name.");
return Vst2EventResult{
.return_value = 1,
@@ -133,10 +135,10 @@ Vst2PluginBridge::Vst2PluginBridge(audioMasterCallback host_callback)
}
} break;
case audioMasterGetVendorString: {
if (config.hide_daw) {
logger.log(
if (config_.hide_daw) {
logger_.log(
"The plugin asked for the host's vendor.");
logger.log(
logger_.log(
"Reporting \"" +
std::string(vendor_name_override) +
"\" instead of the actual host's vendor.");
@@ -148,14 +150,14 @@ Vst2PluginBridge::Vst2PluginBridge(audioMasterCallback host_callback)
}
} break;
case audioMasterDeadBeef:
logger.log("");
logger.log(
logger_.log("");
logger_.log(
" The plugin wants to use REAPER's host vendor");
logger.log(
logger_.log(
" extensions which currently aren't supported "
"by");
logger.log(" yabridge. Ignoring the request.");
logger.log("");
logger_.log(" yabridge. Ignoring the request.");
logger_.log("");
return Vst2EventResult{.return_value = 0,
.payload = nullptr,
@@ -163,7 +165,7 @@ Vst2PluginBridge::Vst2PluginBridge(audioMasterCallback host_callback)
break;
}
return passthrough_event(&plugin, host_callback_function,
return passthrough_event(&plugin_, host_callback_function_,
event);
});
});
@@ -174,7 +176,7 @@ Vst2PluginBridge::Vst2PluginBridge(audioMasterCallback host_callback)
// over the `dispatcher()` socket. This would happen whenever the plugin
// calls `audioMasterIOChanged()` and after the host calls `effOpen()`.
const auto initialization_data =
sockets.host_vst_control.receive_single<Vst2EventResult>();
sockets_.host_vst_control_.receive_single<Vst2EventResult>();
const auto initialized_plugin =
std::get<AEffect>(initialization_data.payload);
@@ -184,19 +186,19 @@ Vst2PluginBridge::Vst2PluginBridge(audioMasterCallback host_callback)
// After receiving the `AEffect` values we'll want to send the configuration
// back to complete the startup process
sockets.host_vst_control.send(config);
sockets_.host_vst_control_.send(config_);
update_aeffect(plugin, initialized_plugin);
update_aeffect(plugin_, initialized_plugin);
}
Vst2PluginBridge::~Vst2PluginBridge() noexcept {
try {
// Drop all work make sure all sockets are closed
plugin_host->terminate();
plugin_host_->terminate();
// The `stop()` method will cause the IO context to just drop all of its
// outstanding work immediately
io_context.stop();
io_context_.stop();
} catch (const boost::system::system_error&) {
// It could be that the sockets have already been closed or that the
// process has already exited (at which point we probably won't be
@@ -210,10 +212,10 @@ class DispatchDataConverter : public DefaultDataConverter {
std::vector<uint8_t>& chunk_data,
AEffect& plugin,
VstRect& editor_rectangle) noexcept
: process_buffers(process_buffers),
chunk(chunk_data),
plugin(plugin),
rect(editor_rectangle) {}
: process_buffers_(process_buffers),
chunk_(chunk_data),
plugin_(plugin),
rect_(editor_rectangle) {}
Vst2Event::Payload read_data(const int opcode,
const int index,
@@ -376,16 +378,16 @@ class DispatchDataConverter : public DefaultDataConverter {
// any notification about this.
const auto& updated_plugin =
std::get<AEffect>(response.payload);
update_aeffect(plugin, updated_plugin);
update_aeffect(plugin_, updated_plugin);
} break;
case effMainsChanged: {
if (const auto* audio_buffer_config =
std::get_if<AudioShmBuffer::Config>(
&response.payload)) {
if (!process_buffers) {
process_buffers.emplace(*audio_buffer_config);
if (!process_buffers_) {
process_buffers_.emplace(*audio_buffer_config);
} else {
process_buffers->resize(*audio_buffer_config);
process_buffers_->resize(*audio_buffer_config);
}
}
} break;
@@ -397,9 +399,9 @@ class DispatchDataConverter : public DefaultDataConverter {
}
const auto& new_rect = std::get<VstRect>(response.payload);
rect = new_rect;
rect_ = new_rect;
*static_cast<VstRect**>(data) = &rect;
*static_cast<VstRect**>(data) = &rect_;
} break;
case effGetChunk: {
// Write the chunk data to some publically accessible place in
@@ -407,9 +409,9 @@ class DispatchDataConverter : public DefaultDataConverter {
// data pointer
const auto& buffer =
std::get<ChunkData>(response.payload).buffer;
chunk.assign(buffer.begin(), buffer.end());
chunk_.assign(buffer.begin(), buffer.end());
*static_cast<uint8_t**>(data) = chunk.data();
*static_cast<uint8_t**>(data) = chunk_.data();
} break;
case effGetInputProperties:
case effGetOutputProperties: {
@@ -492,10 +494,10 @@ class DispatchDataConverter : public DefaultDataConverter {
}
private:
std::optional<AudioShmBuffer>& process_buffers;
std::vector<uint8_t>& chunk;
AEffect& plugin;
VstRect& rect;
std::optional<AudioShmBuffer>& process_buffers_;
std::vector<uint8_t>& chunk_;
AEffect& plugin_;
VstRect& rect_;
};
intptr_t Vst2PluginBridge::dispatch(AEffect* /*plugin*/,
@@ -510,19 +512,19 @@ intptr_t Vst2PluginBridge::dispatch(AEffect* /*plugin*/,
// been a release that contains the fix yet. This should be removed
// once Ardour 6.0 gets released.
// https://tracker.ardour.org/view.php?id=7668
if (plugin.magic == 0) [[unlikely]] {
logger.log_event(true, opcode, index, value, nullptr, option,
std::nullopt);
logger.log(
if (plugin_.magic == 0) [[unlikely]] {
logger_.log_event(true, opcode, index, value, nullptr, option,
std::nullopt);
logger_.log(
" Warning: The host has dispatched an event before the plugin "
"has finished initializing, ignoring the event. (are we running "
"Ardour 5.X?)");
logger.log_event_response(true, opcode, 0, nullptr, std::nullopt);
logger_.log_event_response(true, opcode, 0, nullptr, std::nullopt);
return 0;
}
DispatchDataConverter converter(process_buffers, chunk_data, plugin,
editor_rectangle);
DispatchDataConverter converter(process_buffers_, chunk_data_, plugin_,
editor_rectangle_);
switch (opcode) {
case effClose: {
@@ -533,13 +535,13 @@ intptr_t Vst2PluginBridge::dispatch(AEffect* /*plugin*/,
intptr_t return_value = 0;
try {
// TODO: Add some kind of timeout?
return_value = sockets.host_vst_dispatch.send_event(
converter, std::pair<Vst2Logger&, bool>(logger, true),
return_value = sockets_.host_vst_dispatch_.send_event(
converter, std::pair<Vst2Logger&, bool>(logger_, true),
opcode, index, value, data, option);
} catch (const boost::system::system_error&) {
// Thrown when the socket gets closed because the VST plugin
// loaded into the Wine process crashed during shutdown
logger.log("The plugin crashed during shutdown, ignoring");
logger_.log("The plugin crashed during shutdown, ignoring");
}
delete this;
@@ -555,26 +557,26 @@ intptr_t Vst2PluginBridge::dispatch(AEffect* /*plugin*/,
// from a non-GUI thread (which could cause issues), or we would
// need a timer anyways to proc the function when the GUI is being
// blocked by for instance an open dropdown.
logger.log_event(true, opcode, index, value, nullptr, option,
std::nullopt);
logger_.log_event(true, opcode, index, value, nullptr, option,
std::nullopt);
// REAPER requires `audioMasterSizeWindow()` calls to be done from
// the GUI thread. In every other host this doesn't make a
// difference, but in REAPER the FX window only resizes when this is
// called from here.
{
std::unique_lock lock(incoming_resize_mutex);
if (incoming_resize) {
const auto& [width, height] = *incoming_resize;
incoming_resize.reset();
std::unique_lock lock(incoming_resize_mutex_);
if (incoming_resize_) {
const auto& [width, height] = *incoming_resize_;
incoming_resize_.reset();
lock.unlock();
host_callback_function(&plugin, audioMasterSizeWindow,
width, height, nullptr, 0.0);
host_callback_function_(&plugin_, audioMasterSizeWindow,
width, height, nullptr, 0.0);
}
}
logger.log_event_response(true, opcode, 0, nullptr, std::nullopt);
logger_.log_event_response(true, opcode, 0, nullptr, std::nullopt);
return 0;
}; break;
case effCanDo: {
@@ -585,20 +587,20 @@ intptr_t Vst2PluginBridge::dispatch(AEffect* /*plugin*/,
// window ID to `effEditOpen`. This is of course not going to
// work when the GUI is handled using Wine so we'll ignore it.
if (query == "hasCockosViewAsConfig") {
logger.log_event(true, opcode, index, value, query, option,
std::nullopt);
logger_.log_event(true, opcode, index, value, query, option,
std::nullopt);
logger.log("");
logger.log(
logger_.log("");
logger_.log(
" The host has requested libSwell GUI support, which is");
logger.log(" not supported when using Wine.");
logger.log(
logger_.log(" not supported when using Wine.");
logger_.log(
" You can safely ignore this message; this is normal");
logger.log(" when using REAPER.");
logger.log("");
logger_.log(" when using REAPER.");
logger_.log("");
logger.log_event_response(true, opcode, -1, nullptr,
std::nullopt);
logger_.log_event_response(true, opcode, -1, nullptr,
std::nullopt);
return -1;
}
} break;
@@ -609,8 +611,8 @@ intptr_t Vst2PluginBridge::dispatch(AEffect* /*plugin*/,
// and loading plugin state it's much better to have bitsery or our
// receiving function temporarily allocate a large enough buffer rather than
// to have a bunch of allocated memory sitting around doing nothing.
return sockets.host_vst_dispatch.send_event(
converter, std::pair<Vst2Logger&, bool>(logger, true), opcode, index,
return sockets_.host_vst_dispatch_.send_event(
converter, std::pair<Vst2Logger&, bool>(logger_, true), opcode, index,
value, data, option);
}
@@ -630,8 +632,8 @@ void Vst2PluginBridge::do_process(T** inputs, T** outputs, int sample_frames) {
// VeSTige headers, let's just set all of them!
const VstTimeInfo* returned_time_info =
reinterpret_cast<const VstTimeInfo*>(
host_callback_function(&plugin, audioMasterGetTime, 0,
~static_cast<intptr_t>(0), nullptr, 0.0));
host_callback_function_(&plugin_, audioMasterGetTime, 0,
~static_cast<intptr_t>(0), nullptr, 0.0));
if (returned_time_info) {
request.current_time_info = *returned_time_info;
} else {
@@ -640,16 +642,16 @@ void Vst2PluginBridge::do_process(T** inputs, T** outputs, int sample_frames) {
// Some plugisn also ask for the current process level, so we'll prefetch
// that information as well
request.current_process_level = static_cast<int>(host_callback_function(
&plugin, audioMasterGetCurrentProcessLevel, 0, 0, nullptr, 0.0));
request.current_process_level = static_cast<int>(host_callback_function_(
&plugin_, audioMasterGetCurrentProcessLevel, 0, 0, nullptr, 0.0));
// We'll synchronize the scheduling priority of the audio thread on the Wine
// plugin host with that of the host's audio thread every once in a while
const time_t now = time(nullptr);
if (now > last_audio_thread_priority_synchronization +
if (now > last_audio_thread_priority_synchronization_ +
audio_thread_priority_synchronization_interval) {
request.new_realtime_priority = get_realtime_priority();
last_audio_thread_priority_synchronization = now;
last_audio_thread_priority_synchronization_ = now;
} else {
request.new_realtime_priority.reset();
}
@@ -675,25 +677,25 @@ void Vst2PluginBridge::do_process(T** inputs, T** outputs, int sample_frames) {
// The host should have called `effMainsChanged()` before sending audio to
// process
assert(process_buffers);
for (int channel = 0; channel < plugin.numInputs; channel++) {
T* input_channel = process_buffers->input_channel_ptr<T>(0, channel);
assert(process_buffers_);
for (int channel = 0; channel < plugin_.numInputs; channel++) {
T* input_channel = process_buffers_->input_channel_ptr<T>(0, channel);
std::copy_n(inputs[channel], sample_frames, input_channel);
}
// After writing audio to the shared memory buffers, we'll send the
// processing request parameters to the Wine plugin host so it can start
// processing audio. This is why we don't need any explicit synchronisation.
sockets.host_vst_process_replacing.send(request);
sockets_.host_vst_process_replacing_.send(request);
// From the Wine side we'll send a zero byte struct back as an
// acknowledgement that audio processing has finished. At this point the
// audio will have been written to our buffers.
sockets.host_vst_process_replacing.receive_single<Ack>();
sockets_.host_vst_process_replacing_.receive_single<Ack>();
for (int channel = 0; channel < plugin.numOutputs; channel++) {
for (int channel = 0; channel < plugin_.numOutputs; channel++) {
const T* output_channel =
process_buffers->output_channel_ptr<T>(0, channel);
process_buffers_->output_channel_ptr<T>(0, channel);
if constexpr (replacing) {
std::copy_n(output_channel, sample_frames, outputs[channel]);
@@ -720,13 +722,13 @@ void Vst2PluginBridge::do_process(T** inputs, T** outputs, int sample_frames) {
// prevent these events from getting delayed by a sample we'll process them
// after the plugin is done processing audio rather than during the time
// we're still waiting on the plugin.
std::lock_guard lock(incoming_midi_events_mutex);
for (DynamicVstEvents& events : incoming_midi_events) {
host_callback_function(&plugin, audioMasterProcessEvents, 0, 0,
&events.as_c_events(), 0.0);
std::lock_guard lock(incoming_midi_events_mutex_);
for (DynamicVstEvents& events : incoming_midi_events_) {
host_callback_function_(&plugin_, audioMasterProcessEvents, 0, 0,
&events.as_c_events(), 0.0);
}
incoming_midi_events.clear();
incoming_midi_events_.clear();
}
void Vst2PluginBridge::process(AEffect* /*plugin*/,
@@ -736,31 +738,31 @@ void Vst2PluginBridge::process(AEffect* /*plugin*/,
// Technically either `Vst2PluginBridge::process()` or
// `Vst2PluginBridge::process_replacing()` could actually call the other
// function on the plugin depending on what the plugin supports.
logger.log_trace([]() { return ">> process() :: start"; });
logger_.log_trace([]() { return ">> process() :: start"; });
do_process<float, false>(inputs, outputs, sample_frames);
logger.log_trace([]() { return " process() :: end"; });
logger_.log_trace([]() { return " process() :: end"; });
}
void Vst2PluginBridge::process_replacing(AEffect* /*plugin*/,
float** inputs,
float** outputs,
int sample_frames) {
logger.log_trace([]() { return ">> processReplacing() :: start"; });
logger_.log_trace([]() { return ">> processReplacing() :: start"; });
do_process<float, true>(inputs, outputs, sample_frames);
logger.log_trace([]() { return " processReplacing() :: end"; });
logger_.log_trace([]() { return " processReplacing() :: end"; });
}
void Vst2PluginBridge::process_double_replacing(AEffect* /*plugin*/,
double** inputs,
double** outputs,
int sample_frames) {
logger.log_trace([]() { return ">> processDoubleReplacing() :: start"; });
logger_.log_trace([]() { return ">> processDoubleReplacing() :: start"; });
do_process<double, true>(inputs, outputs, sample_frames);
logger.log_trace([]() { return " processDoubleReplacing() :: end"; });
logger_.log_trace([]() { return " processDoubleReplacing() :: end"; });
}
float Vst2PluginBridge::get_parameter(AEffect* /*plugin*/, int index) {
logger.log_get_parameter(index);
logger_.log_get_parameter(index);
const Parameter request{index, std::nullopt};
ParameterResult response;
@@ -768,14 +770,14 @@ float Vst2PluginBridge::get_parameter(AEffect* /*plugin*/, int index) {
// Prevent race conditions from `getParameter()` and `setParameter()` being
// called at the same time since they share the same socket
{
std::lock_guard lock(parameters_mutex);
sockets.host_vst_parameters.send(request);
std::lock_guard lock(parameters_mutex_);
sockets_.host_vst_parameters_.send(request);
response =
sockets.host_vst_parameters.receive_single<ParameterResult>();
sockets_.host_vst_parameters_.receive_single<ParameterResult>();
}
logger.log_get_parameter_response(*response.value);
logger_.log_get_parameter_response(*response.value);
return *response.value;
}
@@ -783,20 +785,20 @@ float Vst2PluginBridge::get_parameter(AEffect* /*plugin*/, int index) {
void Vst2PluginBridge::set_parameter(AEffect* /*plugin*/,
int index,
float value) {
logger.log_set_parameter(index, value);
logger_.log_set_parameter(index, value);
const Parameter request{index, value};
ParameterResult response;
{
std::lock_guard lock(parameters_mutex);
sockets.host_vst_parameters.send(request);
std::lock_guard lock(parameters_mutex_);
sockets_.host_vst_parameters_.send(request);
response =
sockets.host_vst_parameters.receive_single<ParameterResult>();
sockets_.host_vst_parameters_.receive_single<ParameterResult>();
}
logger.log_set_parameter_response();
logger_.log_set_parameter_response();
// This should not contain any values and just serve as an acknowledgement
assert(!response.value);
+13 -13
View File
@@ -126,13 +126,13 @@ class Vst2PluginBridge : PluginBridge<Vst2Sockets<std::jthread>> {
* VST host during initialization and then passed as a pointer to the Linux
* native VST host from the Linux VST plugin's entry point.
*/
AEffect plugin;
AEffect plugin_;
private:
/**
* The thread that handles host callbacks.
*/
std::jthread host_callback_handler;
std::jthread host_callback_handler_;
/**
* A mutex to prevent multiple simultaneous calls to `getParameter()` and
@@ -140,18 +140,18 @@ class Vst2PluginBridge : PluginBridge<Vst2Sockets<std::jthread>> {
* For `dispatch()` and `audioMaster()` there's some more complex logic for
* this in `Vst2EventHandler`.
*/
std::mutex parameters_mutex;
std::mutex parameters_mutex_;
/**
* The callback function passed by the host to the VST plugin instance.
*/
audioMasterCallback host_callback_function;
audioMasterCallback host_callback_function_;
/**
* The logging facility used for this instance of yabridge. Wraps around
* `PluginBridge::generic_logger`.
*/
Vst2Logger logger;
Vst2Logger logger_;
/**
* A shared memory object that contains both the input and output audio
@@ -165,14 +165,14 @@ class Vst2PluginBridge : PluginBridge<Vst2Sockets<std::jthread>> {
*
* This will be a nullopt until `effMainsChanged` has been called.
*/
std::optional<AudioShmBuffer> process_buffers;
std::optional<AudioShmBuffer> process_buffers_;
/**
* We'll periodically synchronize the Wine host's audio thread priority with
* that of the host. Since the overhead from doing so does add up, we'll
* only do this every once in a while.
*/
time_t last_audio_thread_priority_synchronization = 0;
time_t last_audio_thread_priority_synchronization_ = 0;
/**
* The VST host can query a plugin for arbitrary binary data such as
@@ -180,12 +180,12 @@ class Vst2PluginBridge : PluginBridge<Vst2Sockets<std::jthread>> {
* that data. This vector is where we store the chunk data for the last
* `effGetChunk` event.
*/
std::vector<uint8_t> chunk_data;
std::vector<uint8_t> chunk_data_;
/**
* The VST host will expect to be returned a pointer to a struct that stores
* the dimensions of the editor window.
*/
VstRect editor_rectangle;
VstRect editor_rectangle_;
/**
* Sending MIDI events sent to the host by the plugin using
@@ -196,12 +196,12 @@ class Vst2PluginBridge : PluginBridge<Vst2Sockets<std::jthread>> {
* we receive so we can send them to host on the audio thread at the end of
* `process_replacing()`.
*/
boost::container::small_vector<DynamicVstEvents, 1> incoming_midi_events;
boost::container::small_vector<DynamicVstEvents, 1> incoming_midi_events_;
/**
* Mutex for locking the above event queue, since recieving and processing
* now happens in two different threads.
*/
std::mutex incoming_midi_events_mutex;
std::mutex incoming_midi_events_mutex_;
/**
* REAPER requires us to call `audioMasterSizeWidnow()` from the same thread
@@ -211,6 +211,6 @@ class Vst2PluginBridge : PluginBridge<Vst2Sockets<std::jthread>> {
* `audioMasterSizeWindow`. If this contains a value, we'll then call
* `audioMasterSizeWindow()` with the new size during `effEditIdle()`.
*/
std::optional<std::pair<int, int>> incoming_resize;
std::mutex incoming_resize_mutex;
std::optional<std::pair<int, int>> incoming_resize_;
std::mutex incoming_resize_mutex_;
};
@@ -18,20 +18,21 @@
YaContextMenuTargetImpl::YaContextMenuTargetImpl(Vst3PluginBridge& bridge,
ConstructArgs&& args) noexcept
: YaContextMenuTarget(std::move(args)), bridge(bridge) {}
: YaContextMenuTarget(std::move(args)), bridge_(bridge) {}
tresult PLUGIN_API
YaContextMenuTargetImpl::queryInterface(const Steinberg::TUID _iid,
void** obj) {
const tresult result = YaContextMenuTarget::queryInterface(_iid, obj);
bridge.logger.log_query_interface("In IContextMenuTarget::queryInterface()",
result, Steinberg::FUID::fromTUID(_iid));
bridge_.logger_.log_query_interface(
"In IContextMenuTarget::queryInterface()", result,
Steinberg::FUID::fromTUID(_iid));
return result;
}
tresult PLUGIN_API YaContextMenuTargetImpl::executeMenuItem(int32 tag) {
return bridge.send_message(YaContextMenuTarget::ExecuteMenuItem{
return bridge_.send_message(YaContextMenuTarget::ExecuteMenuItem{
.owner_instance_id = owner_instance_id(),
.context_menu_id = context_menu_id(),
.target_tag = target_tag(),
@@ -34,5 +34,5 @@ class YaContextMenuTargetImpl : public YaContextMenuTarget {
tresult PLUGIN_API executeMenuItem(int32 tag) override;
private:
Vst3PluginBridge& bridge;
Vst3PluginBridge& bridge_;
};
@@ -17,10 +17,10 @@
#include "plug-view-proxy.h"
RunLoopTasks::RunLoopTasks(Steinberg::IPtr<Steinberg::IPlugFrame> plug_frame)
: run_loop(plug_frame) {
: run_loop_(plug_frame) {
FUNKNOWN_CTOR
if (!run_loop) {
if (!run_loop_) {
throw std::runtime_error(
"The host's 'IPlugFrame' object does not support 'IRunLoop'");
}
@@ -32,9 +32,9 @@ RunLoopTasks::RunLoopTasks(Steinberg::IPtr<Steinberg::IPlugFrame> plug_frame)
throw std::runtime_error("Failed to create a Unix domain socket");
}
socket_read_fd = sockets[0];
socket_write_fd = sockets[1];
if (run_loop->registerEventHandler(this, socket_read_fd) !=
socket_read_fd_ = sockets[0];
socket_write_fd_ = sockets[1];
if (run_loop_->registerEventHandler(this, socket_read_fd_) !=
Steinberg::kResultOk) {
throw std::runtime_error(
"Failed to register an event handler with the host's run loop");
@@ -44,9 +44,9 @@ RunLoopTasks::RunLoopTasks(Steinberg::IPtr<Steinberg::IPlugFrame> plug_frame)
RunLoopTasks::~RunLoopTasks() {
FUNKNOWN_DTOR
run_loop->unregisterEventHandler(this);
close(socket_read_fd);
close(socket_write_fd);
run_loop_->unregisterEventHandler(this);
close(socket_read_fd_);
close(socket_write_fd_);
}
#pragma GCC diagnostic push
@@ -57,38 +57,38 @@ IMPLEMENT_FUNKNOWN_METHODS(RunLoopTasks,
#pragma GCC diagnostic pop
void RunLoopTasks::schedule(fu2::unique_function<void()> task) {
std::lock_guard eventfd_lock(tasks_mutex);
tasks.push_back(std::move(task));
std::lock_guard eventfd_lock(tasks_mutex_);
tasks_.push_back(std::move(task));
uint8_t notify_value = 1;
assert(write(socket_write_fd, &notify_value, sizeof(notify_value)) ==
assert(write(socket_write_fd_, &notify_value, sizeof(notify_value)) ==
sizeof(notify_value));
}
void PLUGIN_API
RunLoopTasks::onFDIsSet(Steinberg::Linux::FileDescriptor /*fd*/) {
std::lock_guard lock(tasks_mutex);
std::lock_guard lock(tasks_mutex_);
// Run all tasks that have been submitted to our queue from the host's
// calling thread (which will be the GUI thread)
for (auto& task : tasks) {
for (auto& task : tasks_) {
task();
// This should in theory stop the host from calling this function, but
// REAPER doesn't care. And funnily enough we only have to do all of
// this because of REAPER.
uint8_t notify_value;
assert(read(socket_read_fd, &notify_value, sizeof(notify_value)) ==
assert(read(socket_read_fd_, &notify_value, sizeof(notify_value)) ==
sizeof(notify_value));
}
tasks.clear();
tasks_.clear();
}
Vst3PlugViewProxyImpl::Vst3PlugViewProxyImpl(
Vst3PluginBridge& bridge,
Vst3PlugViewProxy::ConstructArgs&& args) noexcept
: Vst3PlugViewProxy(std::move(args)), bridge(bridge) {}
: Vst3PlugViewProxy(std::move(args)), bridge_(bridge) {}
Vst3PlugViewProxyImpl::~Vst3PlugViewProxyImpl() noexcept {
// Also drop the plug view smart pointer on the Wine side when this gets
@@ -96,15 +96,16 @@ Vst3PlugViewProxyImpl::~Vst3PlugViewProxyImpl() noexcept {
// NOTE: This can actually throw (e.g. out of memory or the socket got
// closed). But if that were to happen, then we wouldn't be able to
// recover from it anyways.
bridge.send_mutually_recursive_message(
bridge_.send_mutually_recursive_message(
Vst3PlugViewProxy::Destruct{.owner_instance_id = owner_instance_id()});
}
tresult PLUGIN_API
Vst3PlugViewProxyImpl::queryInterface(const Steinberg::TUID _iid, void** obj) {
const tresult result = Vst3PlugViewProxy::queryInterface(_iid, obj);
bridge.logger.log_query_interface("In IPlugView::queryInterface()", result,
Steinberg::FUID::fromTUID(_iid));
bridge_.logger_.log_query_interface("In IPlugView::queryInterface()",
result,
Steinberg::FUID::fromTUID(_iid));
return result;
}
@@ -114,11 +115,11 @@ Vst3PlugViewProxyImpl::isPlatformTypeSupported(Steinberg::FIDString type) {
if (type) {
// We'll swap the X11 window ID platform type string for the Win32 HWND
// equivalent on the Wine side
return bridge.send_mutually_recursive_message(
return bridge_.send_mutually_recursive_message(
YaPlugView::IsPlatformTypeSupported{
.owner_instance_id = owner_instance_id(), .type = type});
} else {
bridge.logger.log(
bridge_.logger_.log(
"WARNING: Null pointer passed to "
"'IPlugView::isPlatformTypeSupported()'");
return Steinberg::kInvalidArgument;
@@ -130,31 +131,31 @@ tresult PLUGIN_API Vst3PlugViewProxyImpl::attached(void* parent,
if (parent && type) {
// We will embed the Wine Win32 window into the X11 window provided by
// the host
return bridge.send_mutually_recursive_message(YaPlugView::Attached{
return bridge_.send_mutually_recursive_message(YaPlugView::Attached{
.owner_instance_id = owner_instance_id(),
.parent = reinterpret_cast<native_size_t>(parent),
.type = type});
} else {
bridge.logger.log(
bridge_.logger_.log(
"WARNING: Null pointer passed to 'IPlugView::attached()'");
return Steinberg::kInvalidArgument;
}
}
tresult PLUGIN_API Vst3PlugViewProxyImpl::removed() {
return bridge.send_mutually_recursive_message(
return bridge_.send_mutually_recursive_message(
YaPlugView::Removed{.owner_instance_id = owner_instance_id()});
}
tresult PLUGIN_API Vst3PlugViewProxyImpl::onWheel(float distance) {
return bridge.send_mutually_recursive_message(YaPlugView::OnWheel{
return bridge_.send_mutually_recursive_message(YaPlugView::OnWheel{
.owner_instance_id = owner_instance_id(), .distance = distance});
}
tresult PLUGIN_API Vst3PlugViewProxyImpl::onKeyDown(char16 key,
int16 keyCode,
int16 modifiers) {
return bridge.send_mutually_recursive_message(
return bridge_.send_mutually_recursive_message(
YaPlugView::OnKeyDown{.owner_instance_id = owner_instance_id(),
.key = key,
.key_code = keyCode,
@@ -164,7 +165,7 @@ tresult PLUGIN_API Vst3PlugViewProxyImpl::onKeyDown(char16 key,
tresult PLUGIN_API Vst3PlugViewProxyImpl::onKeyUp(char16 key,
int16 keyCode,
int16 modifiers) {
return bridge.send_mutually_recursive_message(
return bridge_.send_mutually_recursive_message(
YaPlugView::OnKeyUp{.owner_instance_id = owner_instance_id(),
.key = key,
.key_code = keyCode,
@@ -173,14 +174,15 @@ tresult PLUGIN_API Vst3PlugViewProxyImpl::onKeyUp(char16 key,
tresult PLUGIN_API Vst3PlugViewProxyImpl::getSize(Steinberg::ViewRect* size) {
if (size) {
const GetSizeResponse response = bridge.send_mutually_recursive_message(
YaPlugView::GetSize{.owner_instance_id = owner_instance_id()});
const GetSizeResponse response =
bridge_.send_mutually_recursive_message(
YaPlugView::GetSize{.owner_instance_id = owner_instance_id()});
*size = response.size;
return response.result;
} else {
bridge.logger.log(
bridge_.logger_.log(
"WARNING: Null pointer passed to 'IPlugView::getSize()'");
return Steinberg::kInvalidArgument;
}
@@ -188,17 +190,17 @@ tresult PLUGIN_API Vst3PlugViewProxyImpl::getSize(Steinberg::ViewRect* size) {
tresult PLUGIN_API Vst3PlugViewProxyImpl::onSize(Steinberg::ViewRect* newSize) {
if (newSize) {
return bridge.send_mutually_recursive_message(YaPlugView::OnSize{
return bridge_.send_mutually_recursive_message(YaPlugView::OnSize{
.owner_instance_id = owner_instance_id(), .new_size = *newSize});
} else {
bridge.logger.log(
bridge_.logger_.log(
"WARNING: Null pointer passed to 'IPlugView::onSize()'");
return Steinberg::kInvalidArgument;
}
}
tresult PLUGIN_API Vst3PlugViewProxyImpl::onFocus(TBool state) {
return bridge.send_mutually_recursive_message(YaPlugView::OnFocus{
return bridge_.send_mutually_recursive_message(YaPlugView::OnFocus{
.owner_instance_id = owner_instance_id(), .state = state});
}
@@ -209,35 +211,35 @@ Vst3PlugViewProxyImpl::setFrame(Steinberg::IPlugFrame* frame) {
if (frame) {
// We'll store the pointer for when the plugin later makes a callback to
// this component handler
plug_frame = frame;
plug_frame_ = frame;
// REAPER's GUI is not thread safe, and if we don't call
// `IPlugFrame::resizeView()` or `IContextMenu::popup()` from a thread
// owned by REAPER then REAPER will eventually segfault We should thus
// try to call those functions from an `IRunLoop` event handler.
try {
run_loop_tasks.emplace(plug_frame);
run_loop_tasks_.emplace(plug_frame_);
} catch (const std::runtime_error& error) {
// In case the host does not support `IRunLoop` or if we can't
// register an event handler, we'll throw during `RunLoopTasks`'
// constructor
run_loop_tasks.reset();
run_loop_tasks_.reset();
bridge.logger.log(
bridge_.logger_.log(
"The host does not support IRunLoop, falling back to naive GUI "
"function execution: " +
std::string(error.what()));
}
return bridge.send_mutually_recursive_message(YaPlugView::SetFrame{
return bridge_.send_mutually_recursive_message(YaPlugView::SetFrame{
.owner_instance_id = owner_instance_id(),
.plug_frame_args = Vst3PlugFrameProxy::ConstructArgs(
plug_frame, owner_instance_id())});
plug_frame_, owner_instance_id())});
} else {
plug_frame.reset();
run_loop_tasks.reset();
plug_frame_.reset();
run_loop_tasks_.reset();
return bridge.send_mutually_recursive_message(
return bridge_.send_mutually_recursive_message(
YaPlugView::SetFrame{.owner_instance_id = owner_instance_id(),
.plug_frame_args = std::nullopt});
}
@@ -248,11 +250,12 @@ tresult PLUGIN_API Vst3PlugViewProxyImpl::canResize() {
YaPlugView::CanResize{.owner_instance_id = owner_instance_id()};
{
std::lock_guard lock(can_resize_cache_mutex);
if (const tresult* result = can_resize_cache.get_and_keep_alive(5)) {
const bool log_response = bridge.logger.log_request(true, request);
std::lock_guard lock(can_resize_cache_mutex_);
if (const tresult* result = can_resize_cache_.get_and_keep_alive(5)) {
const bool log_response =
bridge_.logger_.log_request(true, request);
if (log_response) {
bridge.logger.log_response(
bridge_.logger_.log_response(
true, YaPlugView::CanResize::Response(*result), true);
}
@@ -261,11 +264,11 @@ tresult PLUGIN_API Vst3PlugViewProxyImpl::canResize() {
}
const UniversalTResult result =
bridge.send_mutually_recursive_message(request);
bridge_.send_mutually_recursive_message(request);
{
std::lock_guard lock(can_resize_cache_mutex);
can_resize_cache.set(result, 5);
std::lock_guard lock(can_resize_cache_mutex_);
can_resize_cache_.set(result, 5);
}
return result;
@@ -275,7 +278,7 @@ tresult PLUGIN_API
Vst3PlugViewProxyImpl::checkSizeConstraint(Steinberg::ViewRect* rect) {
if (rect) {
const CheckSizeConstraintResponse response =
bridge.send_mutually_recursive_message(
bridge_.send_mutually_recursive_message(
YaPlugView::CheckSizeConstraint{
.owner_instance_id = owner_instance_id(), .rect = *rect});
@@ -283,7 +286,7 @@ Vst3PlugViewProxyImpl::checkSizeConstraint(Steinberg::ViewRect* rect) {
return response.result;
} else {
bridge.logger.log(
bridge_.logger_.log(
"WARNING: Null pointer passed to "
"'IPlugView::checkSizeConstraint()'");
return Steinberg::kInvalidArgument;
@@ -295,10 +298,11 @@ tresult PLUGIN_API Vst3PlugViewProxyImpl::findParameter(
int32 yPos,
Steinberg::Vst::ParamID& resultTag /*out*/) {
const FindParameterResponse response =
bridge.send_mutually_recursive_message(YaParameterFinder::FindParameter{
.owner_instance_id = owner_instance_id(),
.x_pos = xPos,
.y_pos = yPos});
bridge_.send_mutually_recursive_message(
YaParameterFinder::FindParameter{
.owner_instance_id = owner_instance_id(),
.x_pos = xPos,
.y_pos = yPos});
resultTag = response.result_tag;
@@ -307,7 +311,7 @@ tresult PLUGIN_API Vst3PlugViewProxyImpl::findParameter(
tresult PLUGIN_API
Vst3PlugViewProxyImpl::setContentScaleFactor(ScaleFactor factor) {
return bridge.send_mutually_recursive_message(
return bridge_.send_mutually_recursive_message(
YaPlugViewContentScaleSupport::SetContentScaleFactor{
.owner_instance_id = owner_instance_id(), .factor = factor});
}
+16 -16
View File
@@ -73,7 +73,7 @@ class RunLoopTasks : public Steinberg::Linux::IEventHandler {
* This pointer is cast from `plug_frame` once `IPlugView::setFrame()` has
* been called.
*/
Steinberg::FUnknownPtr<Steinberg::Linux::IRunLoop> run_loop;
Steinberg::FUnknownPtr<Steinberg::Linux::IRunLoop> run_loop_;
/**
* Tasks that should be executed in the next `IRunLoop` event handler call.
@@ -82,8 +82,8 @@ class RunLoopTasks : public Steinberg::Linux::IEventHandler {
*
* @see RunLoopTasks::schedule
*/
std::vector<fu2::unique_function<void()>> tasks;
std::mutex tasks_mutex;
std::vector<fu2::unique_function<void()>> tasks_;
std::mutex tasks_mutex_;
/**
* A dumy Unix domain socket file descriptor used to signal that there is a
@@ -93,12 +93,12 @@ class RunLoopTasks : public Steinberg::Linux::IEventHandler {
* XXX: This should be backed by eventfd instead, but Ardour doesn't support
* that
*/
int socket_read_fd = -1;
int socket_read_fd_ = -1;
/**
* The other side of `socket_read_fd`. We'll write to this when we want the
* hsot to call our event handler.
*/
int socket_write_fd = -1;
int socket_write_fd_ = -1;
};
class Vst3PlugViewProxyImpl : public Vst3PlugViewProxy {
@@ -131,9 +131,9 @@ class Vst3PlugViewProxyImpl : public Vst3PlugViewProxy {
*
* This works similarly to
* `Vst3Bridge::do_mutual_recursion_or_handle_in_main_context`, except that
* we can post tasks to `run_loop_tasks` instead of executing them directly
* in `main_context` when no mutually recursive function calls are happening
* right now.
* we can post tasks to `run_loop_tasks_` instead of executing them directly
* in `main_context_` when no mutually recursive function calls are
* happening right now.
*
* @see Vst3HostBridge::send_mutually_recursive_message
*/
@@ -148,15 +148,15 @@ class Vst3PlugViewProxyImpl : public Vst3PlugViewProxy {
// registered to the host's run loop, if that exists. Finally if the
// host does not support `IRunLoop`, then we'll just run `fn` directly.
if (const auto result =
bridge.maybe_run_on_mutual_recursion_thread(fn)) {
bridge_.maybe_run_on_mutual_recursion_thread(fn)) {
return *result;
}
if (run_loop_tasks) {
if (run_loop_tasks_) {
std::packaged_task<Result()> do_call(std::forward<F>(fn));
std::future<Result> do_call_response = do_call.get_future();
run_loop_tasks->schedule(std::move(do_call));
run_loop_tasks_->schedule(std::move(do_call));
return do_call_response.get();
} else {
@@ -198,10 +198,10 @@ class Vst3PlugViewProxyImpl : public Vst3PlugViewProxy {
* `IPlugView::setFrame()`. When the plugin makes a callback on the
* `IPlugFrame` proxy object, we'll pass the call through to this object.
*/
Steinberg::IPtr<Steinberg::IPlugFrame> plug_frame;
Steinberg::IPtr<Steinberg::IPlugFrame> plug_frame_;
private:
Vst3PluginBridge& bridge;
Vst3PluginBridge& bridge_;
/**
* If the host supports `IRunLoop`, we'll use this to run certain tasks from
@@ -210,7 +210,7 @@ class Vst3PlugViewProxyImpl : public Vst3PlugViewProxy {
*
* This will be an `std::nullopt` if the hostdoes not support `IRunLoop`.
*/
std::optional<RunLoopTasks> run_loop_tasks;
std::optional<RunLoopTasks> run_loop_tasks_;
// Caches
@@ -225,6 +225,6 @@ class Vst3PlugViewProxyImpl : public Vst3PlugViewProxy {
* resizing a lot laggier than they would have to be, so as a compromise
* we'll remember this value for the duration of the resize.
*/
TimedValueCache<tresult> can_resize_cache;
std::mutex can_resize_cache_mutex;
TimedValueCache<tresult> can_resize_cache_;
std::mutex can_resize_cache_mutex_;
};
@@ -24,14 +24,15 @@
Vst3PluginFactoryProxyImpl::Vst3PluginFactoryProxyImpl(
Vst3PluginBridge& bridge,
Vst3PluginFactoryProxy::ConstructArgs&& args) noexcept
: Vst3PluginFactoryProxy(std::move(args)), bridge(bridge) {}
: Vst3PluginFactoryProxy(std::move(args)), bridge_(bridge) {}
tresult PLUGIN_API
Vst3PluginFactoryProxyImpl::queryInterface(const Steinberg::TUID _iid,
void** obj) {
const tresult result = Vst3PluginFactoryProxy::queryInterface(_iid, obj);
bridge.logger.log_query_interface("In IPluginFactory::queryInterface()",
result, Steinberg::FUID::fromTUID(_iid));
bridge_.logger_.log_query_interface("In IPluginFactory::queryInterface()",
result,
Steinberg::FUID::fromTUID(_iid));
return result;
}
@@ -63,16 +64,16 @@ Vst3PluginFactoryProxyImpl::createInstance(Steinberg::FIDString cid,
} else {
// When the host requests an interface we do not (yet) implement, we'll
// print a recognizable log message
bridge.logger.log_query_interface("In IPluginFactory::createInstance()",
Steinberg::kNotImplemented,
requested_iid);
bridge_.logger_.log_query_interface(
"In IPluginFactory::createInstance()", Steinberg::kNotImplemented,
requested_iid);
*obj = nullptr;
return Steinberg::kNotImplemented;
}
std::variant<Vst3PluginProxy::ConstructArgs, UniversalTResult> result =
bridge.send_mutually_recursive_message(Vst3PluginProxy::Construct{
bridge_.send_mutually_recursive_message(Vst3PluginProxy::Construct{
.cid = cid_array, .requested_interface = requested_interface});
return std::visit(
@@ -83,7 +84,7 @@ Vst3PluginFactoryProxyImpl::createInstance(Steinberg::FIDString cid,
// reference count of 1), and then the receiving side will use
// `Steinberg::owned()` to adopt it to an `IPtr<T>`.
Vst3PluginProxyImpl* proxy_object =
new Vst3PluginProxyImpl(bridge, std::move(args));
new Vst3PluginProxyImpl(bridge_, std::move(args));
// We return a properly downcasted version of the proxy object
// we just created
@@ -111,18 +112,18 @@ Vst3PluginFactoryProxyImpl::setHostContext(Steinberg::FUnknown* context) {
// interfaces as `context`, and then we'll store `context` in this
// object. We can then use it to handle callbacks made by the Windows
// VST3 plugin to this context.
host_context = context;
host_context_ = context;
// Automatically converted smart pointers for when the plugin performs a
// callback later
host_application = host_context;
plug_interface_support = host_context;
host_application_ = host_context_;
plug_interface_support_ = host_context_;
return bridge.send_message(YaPluginFactory3::SetHostContext{
return bridge_.send_message(YaPluginFactory3::SetHostContext{
.host_context_args = Vst3HostContextProxy::ConstructArgs(
host_context, std::nullopt)});
host_context_, std::nullopt)});
} else {
bridge.logger.log(
bridge_.logger_.log(
"WARNING: Null pointer passed to "
"'IPluginFactory3::setHostContext()'");
return Steinberg::kInvalidArgument;
@@ -43,16 +43,16 @@ class Vst3PluginFactoryProxyImpl : public Vst3PluginFactoryProxy {
// The following pointers are cast from `host_context` if
// `IPluginFactory3::setHostContext()` has been called
Steinberg::FUnknownPtr<Steinberg::Vst::IHostApplication> host_application;
Steinberg::FUnknownPtr<Steinberg::Vst::IHostApplication> host_application_;
Steinberg::FUnknownPtr<Steinberg::Vst::IPlugInterfaceSupport>
plug_interface_support;
plug_interface_support_;
private:
Vst3PluginBridge& bridge;
Vst3PluginBridge& bridge_;
/**
* An host context if we get passed one through
* `IPluginFactory3::setHostContext()`.
*/
Steinberg::IPtr<Steinberg::FUnknown> host_context;
Steinberg::IPtr<Steinberg::FUnknown> host_context_;
};
File diff suppressed because it is too large Load Diff
+34 -34
View File
@@ -71,8 +71,8 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy {
*
* See the bottom of this class for more information on what we're caching.
*
* @see clear_bus_cache
* @see function_result_cache
* @see clear_bus_cache_
* @see function_result_cache_
*/
void clear_caches() noexcept;
@@ -309,7 +309,7 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy {
* callback on a component handler proxy object, we'll pass the call through
* to this object.
*/
Steinberg::IPtr<Steinberg::Vst::IComponentHandler> component_handler;
Steinberg::IPtr<Steinberg::Vst::IComponentHandler> component_handler_;
/**
* If the host places a proxy between two objects in
@@ -320,15 +320,15 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy {
* IDs this way, we'll still connect the objects directly on the Wine plugin
* host side. So far this is only needed for Ardour.
*/
std::optional<size_t> connected_instance_id;
std::optional<size_t> connected_instance_id_;
/**
* If we cannot manage to bypass the connection proxy as mentioned in the
* docstring of `connected_instance_id`, then we'll store the host's
* docstring of `connected_instance_id_`, then we'll store the host's
* connection point proxy here and we'll proxy that proxy, if that makes any
* sense.
*/
Steinberg::IPtr<Steinberg::Vst::IConnectionPoint> connection_point_proxy;
Steinberg::IPtr<Steinberg::Vst::IConnectionPoint> connection_point_proxy_;
/**
* An unmanaged, raw pointer to the `IPlugView` instance returned in our
@@ -340,7 +340,7 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy {
* currently only defines a single type of view so that shouldn't be an
* issue
*/
Vst3PlugViewProxyImpl* last_created_plug_view = nullptr;
Vst3PlugViewProxyImpl* last_created_plug_view_ = nullptr;
/**
* A pointer to a context menu returned by the host as a response to a call
@@ -373,28 +373,28 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy {
* @see Vst3PluginProxyImpl::register_context_menu
* @see Vst3PluginProxyImpl::unregister_context_menu
*/
std::map<size_t, ContextMenu> context_menus;
std::mutex context_menus_mutex;
std::map<size_t, ContextMenu> context_menus_;
std::mutex context_menus_mutex_;
// The following pointers are cast from `host_context` if
// `IPluginBase::initialize()` has been called
Steinberg::FUnknownPtr<Steinberg::Vst::IHostApplication> host_application;
Steinberg::FUnknownPtr<Steinberg::Vst::IHostApplication> host_application_;
Steinberg::FUnknownPtr<Steinberg::Vst::IPlugInterfaceSupport>
plug_interface_support;
plug_interface_support_;
// The following pointers are cast from `component_handler` if
// `IEditController::setComponentHandler()` has been called
Steinberg::FUnknownPtr<Steinberg::Vst::IComponentHandler2>
component_handler_2;
component_handler_2_;
Steinberg::FUnknownPtr<Steinberg::Vst::IComponentHandler3>
component_handler_3;
component_handler_3_;
Steinberg::FUnknownPtr<Steinberg::Vst::IComponentHandlerBusActivation>
component_handler_bus_activation;
Steinberg::FUnknownPtr<Steinberg::Vst::IProgress> progress;
Steinberg::FUnknownPtr<Steinberg::Vst::IUnitHandler> unit_handler;
Steinberg::FUnknownPtr<Steinberg::Vst::IUnitHandler2> unit_handler_2;
component_handler_bus_activation_;
Steinberg::FUnknownPtr<Steinberg::Vst::IProgress> progress_;
Steinberg::FUnknownPtr<Steinberg::Vst::IUnitHandler> unit_handler_;
Steinberg::FUnknownPtr<Steinberg::Vst::IUnitHandler2> unit_handler_2_;
private:
/**
@@ -409,11 +409,11 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy {
* manually flush this cache when the stores information potentially becomes
* invalid.
*
* @see processing_bus_cache
* @see processing_bus_cache_
*/
void clear_bus_cache() noexcept;
Vst3PluginBridge& bridge;
Vst3PluginBridge& bridge_;
/**
* An host context if we get passed one through `IPluginBase::initialize()`.
@@ -422,14 +422,14 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy {
* all plugin instances so we should not have to store it here separately,
* but for the sake of correctness we will.
*/
Steinberg::IPtr<Steinberg::FUnknown> host_context;
Steinberg::IPtr<Steinberg::FUnknown> host_context_;
/**
* We'll periodically synchronize the Wine host's audio thread priority with
* that of the host. Since the overhead from doing so does add up, we'll
* only do this every once in a while.
*/
time_t last_audio_thread_priority_synchronization = 0;
time_t last_audio_thread_priority_synchronization_ = 0;
/**
* Used to assign unique identifiers to context menus created by
@@ -437,7 +437,7 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy {
*
* @related Vst3PluginProxyImpl::register_context_menu
*/
std::atomic_size_t current_context_menu_id;
std::atomic_size_t current_context_menu_id_;
/**
* We'll reuse the request objects for the audio processor so we can keep
@@ -449,16 +449,16 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy {
* from and to existing objects without having to copy or reallocate them.
*
* To reduce the amount of copying during audio processing we'll write the
* audio data to a shared memory object stored in `process_buffers` first.
* audio data to a shared memory object stored in `process_buffers_` first.
*/
YaAudioProcessor::Process process_request;
YaAudioProcessor::Process process_request_;
/**
* The response object we'll get in return when we send the
* `process_request` object above to the Wine plugin host. This object also
* `process_request_` object above to the Wine plugin host. This object also
* contains heap data, so we also want to reuse this.
*/
YaAudioProcessor::ProcessResponse process_response;
YaAudioProcessor::ProcessResponse process_response_;
/**
* A shared memory object to share audio buffers between the native plugin
@@ -469,7 +469,7 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy {
*
* This will be set up during `IAudioProcessor::setupProcessing()`.
*/
std::optional<AudioShmBuffer> process_buffers;
std::optional<AudioShmBuffer> process_buffers_;
// Caches
@@ -480,7 +480,7 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy {
* values should be immutable until the plugin tells the host that this
* information has changed).
*
* @see processing_bus_cache
* @see processing_bus_cache_
*/
struct BusInfoCache {
// `std::unordered_map` would be better here, but tuples aren't hashable
@@ -508,10 +508,10 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy {
* Since this information is immutable during audio processing, this cache
* will only be available at those times.
*
* @see clear_bus_cache
* @see clear_bus_cache_
*/
std::optional<BusInfoCache> processing_bus_cache;
std::mutex processing_bus_cache_mutex;
std::optional<BusInfoCache> processing_bus_cache_;
std::mutex processing_bus_cache_mutex_;
/**
* A cache for several function calls that should be safe to cache since
@@ -519,7 +519,7 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy {
* calls until the plugin tells the host that parameter information has
* changed.
*
* @see function_result_cache
* @see function_result_cache_
*/
struct FunctionResultCache {
/**
@@ -551,6 +551,6 @@ class Vst3PluginProxyImpl : public Vst3PluginProxy {
*
* @see clear_caches
*/
FunctionResultCache function_result_cache;
std::mutex function_result_cache_mutex;
FunctionResultCache function_result_cache_;
std::mutex function_result_cache_mutex_;
};
+60 -56
View File
@@ -30,12 +30,12 @@ Vst3PluginBridge::Vst3PluginBridge()
[](boost::asio::io_context& io_context, const PluginInfo& info) {
return Vst3Sockets<std::jthread>(
io_context,
generate_endpoint_base(info.native_library_path.filename()
generate_endpoint_base(info.native_library_path_.filename()
.replace_extension("")
.string()),
true);
}),
logger(generic_logger) {
logger_(generic_logger_) {
log_init_message();
// This will block until all sockets have been connected to by the Wine VST
@@ -47,12 +47,12 @@ Vst3PluginBridge::Vst3PluginBridge()
// messaging mechanism is how we relay the VST3 communication protocol. As a
// first thing, the Wine VST host will ask us for a copy of the
// configuration.
host_callback_handler = std::jthread([&]() {
host_callback_handler_ = std::jthread([&]() {
set_realtime_priority(true);
pthread_setname_np(pthread_self(), "host-callbacks");
sockets.vst_host_callback.receive_messages(
std::pair<Vst3Logger&, bool>(logger, false),
sockets_.vst_host_callback_.receive_messages(
std::pair<Vst3Logger&, bool>(logger_, false),
overload{
[&](const Vst3ContextMenuProxy::Destruct& request)
-> Vst3ContextMenuProxy::Destruct::Response {
@@ -68,14 +68,14 @@ Vst3PluginBridge::Vst3PluginBridge()
-> WantsConfiguration::Response {
warn_on_version_mismatch(request.host_version);
return config;
return config_;
},
[&](const YaComponentHandler::BeginEdit& request)
-> YaComponentHandler::BeginEdit::Response {
const auto& [proxy_object, _] =
get_proxy(request.owner_instance_id);
return proxy_object.component_handler->beginEdit(
return proxy_object.component_handler_->beginEdit(
request.id);
},
[&](const YaComponentHandler::PerformEdit& request)
@@ -83,7 +83,7 @@ Vst3PluginBridge::Vst3PluginBridge()
const auto& [proxy_object, _] =
get_proxy(request.owner_instance_id);
return proxy_object.component_handler->performEdit(
return proxy_object.component_handler_->performEdit(
request.id, request.value_normalized);
},
[&](const YaComponentHandler::EndEdit& request)
@@ -91,7 +91,7 @@ Vst3PluginBridge::Vst3PluginBridge()
const auto& [proxy_object, _] =
get_proxy(request.owner_instance_id);
return proxy_object.component_handler->endEdit(request.id);
return proxy_object.component_handler_->endEdit(request.id);
},
[&](const YaComponentHandler::RestartComponent& request)
-> YaComponentHandler::RestartComponent::Response {
@@ -102,7 +102,7 @@ Vst3PluginBridge::Vst3PluginBridge()
// of our caches whenever a plugin requests a restart
proxy_object.clear_caches();
return proxy_object.component_handler->restartComponent(
return proxy_object.component_handler_->restartComponent(
request.flags);
},
[&](const YaComponentHandler2::SetDirty& request)
@@ -110,7 +110,7 @@ Vst3PluginBridge::Vst3PluginBridge()
const auto& [proxy_object, _] =
get_proxy(request.owner_instance_id);
return proxy_object.component_handler_2->setDirty(
return proxy_object.component_handler_2_->setDirty(
request.state);
},
[&](const YaComponentHandler2::RequestOpenEditor& request)
@@ -118,7 +118,7 @@ Vst3PluginBridge::Vst3PluginBridge()
const auto& [proxy_object, _] =
get_proxy(request.owner_instance_id);
return proxy_object.component_handler_2->requestOpenEditor(
return proxy_object.component_handler_2_->requestOpenEditor(
request.name.c_str());
},
[&](const YaComponentHandler2::StartGroupEdit& request)
@@ -126,14 +126,14 @@ Vst3PluginBridge::Vst3PluginBridge()
const auto& [proxy_object, _] =
get_proxy(request.owner_instance_id);
return proxy_object.component_handler_2->startGroupEdit();
return proxy_object.component_handler_2_->startGroupEdit();
},
[&](const YaComponentHandler2::FinishGroupEdit& request)
-> YaComponentHandler2::FinishGroupEdit::Response {
const auto& [proxy_object, _] =
get_proxy(request.owner_instance_id);
return proxy_object.component_handler_2->finishGroupEdit();
return proxy_object.component_handler_2_->finishGroupEdit();
},
[&](const YaComponentHandler3::CreateContextMenu& request)
-> YaComponentHandler3::CreateContextMenu::Response {
@@ -146,13 +146,15 @@ Vst3PluginBridge::Vst3PluginBridge()
// (and only) `IPlugView*` instance returned by the
// plugin.
Vst3PlugViewProxyImpl* plug_view =
proxy_object.last_created_plug_view;
proxy_object.last_created_plug_view_;
Steinberg::IPtr<Steinberg::Vst::IContextMenu> context_menu =
Steinberg::owned(
proxy_object.component_handler_3->createContextMenu(
plug_view, request.param_id ? &*request.param_id
: nullptr));
proxy_object.component_handler_3_
->createContextMenu(plug_view,
request.param_id
? &*request.param_id
: nullptr));
if (context_menu) {
const size_t context_menu_id =
@@ -176,7 +178,7 @@ Vst3PluginBridge::Vst3PluginBridge()
request.owner_instance_id);
return proxy_object
.component_handler_bus_activation
.component_handler_bus_activation_
->requestBusActivation(
request.type, request.dir,
request.index, request.state);
@@ -186,7 +188,7 @@ Vst3PluginBridge::Vst3PluginBridge()
const auto& [proxy_object, _] =
get_proxy(request.owner_instance_id);
return proxy_object.context_menus
return proxy_object.context_menus_
.at(request.context_menu_id)
.menu->getItemCount();
},
@@ -196,7 +198,7 @@ Vst3PluginBridge::Vst3PluginBridge()
get_proxy(request.owner_instance_id);
Vst3PluginProxyImpl::ContextMenu& context_menu =
proxy_object.context_menus.at(request.context_menu_id);
proxy_object.context_menus_.at(request.context_menu_id);
if (request.target) {
context_menu.targets[request.item.tag] =
@@ -217,7 +219,7 @@ Vst3PluginBridge::Vst3PluginBridge()
get_proxy(request.owner_instance_id);
Vst3PluginProxyImpl::ContextMenu& context_menu =
proxy_object.context_menus.at(request.context_menu_id);
proxy_object.context_menus_.at(request.context_menu_id);
if (const auto it =
context_menu.targets.find(request.item.tag);
@@ -236,9 +238,9 @@ Vst3PluginBridge::Vst3PluginBridge()
// REAPER requires this to be run from its provided event
// loop or else it will likely segfault at some point
return proxy_object.last_created_plug_view->run_gui_task(
return proxy_object.last_created_plug_view_->run_gui_task(
[&, &proxy_object = proxy_object]() -> tresult {
return proxy_object.context_menus
return proxy_object.context_menus_
.at(request.context_menu_id)
.menu->popup(request.x, request.y);
});
@@ -248,7 +250,7 @@ Vst3PluginBridge::Vst3PluginBridge()
const auto& [proxy_object, _] =
get_proxy(request.instance_id);
return proxy_object.connection_point_proxy->notify(
return proxy_object.connection_point_proxy_->notify(
&request.message_ptr);
},
[&](const YaHostApplication::GetName& request)
@@ -263,7 +265,7 @@ Vst3PluginBridge::Vst3PluginBridge()
// under some other host. We do this here to stay
// consistent with the VST2 version, where it has to
// be done on the plugin's side.
if (config.hide_daw) {
if (config_.hide_daw) {
// This is the only sane-ish way to copy a c-style
// string to an UTF-16 string buffer
Steinberg::UString128(product_name_override)
@@ -279,10 +281,11 @@ Vst3PluginBridge::Vst3PluginBridge()
get_proxy(*request.owner_instance_id);
result =
proxy_object.host_application->getName(name);
proxy_object.host_application_->getName(name);
} else {
result =
plugin_factory->host_application->getName(name);
plugin_factory_->host_application_->getName(
name);
}
}
@@ -302,12 +305,12 @@ Vst3PluginBridge::Vst3PluginBridge()
// (and only) `IPlugView*` instance returned by the
// plugin.
Vst3PlugViewProxyImpl* plug_view =
proxy_object.last_created_plug_view;
proxy_object.last_created_plug_view_;
// REAPER requires this to be run from its provided event
// loop or else it will likely segfault at some point
return plug_view->run_gui_task([&]() -> tresult {
return plug_view->plug_frame->resizeView(
return plug_view->plug_frame_->resizeView(
plug_view, &request.new_size);
});
},
@@ -323,11 +326,11 @@ Vst3PluginBridge::Vst3PluginBridge()
const auto& [proxy_object, _] =
get_proxy(*request.owner_instance_id);
return proxy_object.plug_interface_support
return proxy_object.plug_interface_support_
->isPlugInterfaceSupported(
request.iid.get_native_uid().data());
} else {
return plugin_factory->plug_interface_support
return plugin_factory_->plug_interface_support_
->isPlugInterfaceSupported(
request.iid.get_native_uid().data());
}
@@ -338,7 +341,7 @@ Vst3PluginBridge::Vst3PluginBridge()
get_proxy(request.owner_instance_id);
Steinberg::Vst::IProgress::ID out_id;
const tresult result = proxy_object.progress->start(
const tresult result = proxy_object.progress_->start(
request.type,
request.optional_description
? u16string_to_tchar_pointer(
@@ -354,22 +357,22 @@ Vst3PluginBridge::Vst3PluginBridge()
const auto& [proxy_object, _] =
get_proxy(request.owner_instance_id);
return proxy_object.progress->update(request.id,
request.norm_value);
return proxy_object.progress_->update(request.id,
request.norm_value);
},
[&](const YaProgress::Finish& request)
-> YaProgress::Finish::Response {
const auto& [proxy_object, _] =
get_proxy(request.owner_instance_id);
return proxy_object.progress->finish(request.id);
return proxy_object.progress_->finish(request.id);
},
[&](const YaUnitHandler::NotifyUnitSelection& request)
-> YaUnitHandler::NotifyUnitSelection::Response {
const auto& [proxy_object, _] =
get_proxy(request.owner_instance_id);
return proxy_object.unit_handler->notifyUnitSelection(
return proxy_object.unit_handler_->notifyUnitSelection(
request.unit_id);
},
[&](const YaUnitHandler::NotifyProgramListChange& request)
@@ -377,7 +380,7 @@ Vst3PluginBridge::Vst3PluginBridge()
const auto& [proxy_object, _] =
get_proxy(request.owner_instance_id);
return proxy_object.unit_handler->notifyProgramListChange(
return proxy_object.unit_handler_->notifyProgramListChange(
request.list_id, request.program_index);
},
[&](const YaUnitHandler2::NotifyUnitByBusChange& request)
@@ -385,7 +388,8 @@ Vst3PluginBridge::Vst3PluginBridge()
const auto& [proxy_object, _] =
get_proxy(request.owner_instance_id);
return proxy_object.unit_handler_2->notifyUnitByBusChange();
return proxy_object.unit_handler_2_
->notifyUnitByBusChange();
},
});
});
@@ -394,8 +398,8 @@ Vst3PluginBridge::Vst3PluginBridge()
Vst3PluginBridge::~Vst3PluginBridge() noexcept {
try {
// Drop all work make sure all sockets are closed
plugin_host->terminate();
io_context.stop();
plugin_host_->terminate();
io_context_.stop();
} catch (const boost::system::system_error&) {
// It could be that the sockets have already been closed or that the
// process has already exited (at which point we probably won't be
@@ -409,56 +413,56 @@ Steinberg::IPluginFactory* Vst3PluginBridge::get_plugin_factory() {
// the plugin factory with an `IPtr` ourselves so it cannot be freed before
// `Vst3PluginBridge` gets freed. This is needed for REAPER as REAPER does
// not call `ModuleExit()`.
if (!plugin_factory) {
if (!plugin_factory_) {
// Set up the plugin factory, since this is the first thing the host
// will request after loading the module. Host callback handlers should
// have started before this since the Wine plugin host will request a
// copy of the configuration during its initialization.
Vst3PluginFactoryProxy::ConstructArgs factory_args =
sockets.host_vst_control.send_message(
sockets_.host_vst_control_.send_message(
Vst3PluginFactoryProxy::Construct{},
std::pair<Vst3Logger&, bool>(logger, true));
plugin_factory = Steinberg::owned(
std::pair<Vst3Logger&, bool>(logger_, true));
plugin_factory_ = Steinberg::owned(
new Vst3PluginFactoryProxyImpl(*this, std::move(factory_args)));
}
// Because we're returning a raw pointer, we have to increase the reference
// count ourselves
plugin_factory->addRef();
plugin_factory_->addRef();
return plugin_factory;
return plugin_factory_;
}
std::pair<Vst3PluginProxyImpl&, std::shared_lock<std::shared_mutex>>
Vst3PluginBridge::get_proxy(size_t instance_id) noexcept {
std::shared_lock lock(plugin_proxies_mutex);
std::shared_lock lock(plugin_proxies_mutex_);
return std::pair<Vst3PluginProxyImpl&, std::shared_lock<std::shared_mutex>>(
plugin_proxies.at(instance_id).get(), std::move(lock));
plugin_proxies_.at(instance_id).get(), std::move(lock));
}
void Vst3PluginBridge::register_plugin_proxy(
Vst3PluginProxyImpl& proxy_object) {
std::unique_lock lock(plugin_proxies_mutex);
std::unique_lock lock(plugin_proxies_mutex_);
plugin_proxies.emplace(proxy_object.instance_id(),
std::ref<Vst3PluginProxyImpl>(proxy_object));
plugin_proxies_.emplace(proxy_object.instance_id(),
std::ref<Vst3PluginProxyImpl>(proxy_object));
// For optimization reaons we use dedicated sockets for functions that will
// be run in the audio processing loop
if (proxy_object.YaAudioProcessor::supported() ||
proxy_object.YaComponent::supported()) {
sockets.add_audio_processor_and_connect(proxy_object.instance_id());
sockets_.add_audio_processor_and_connect(proxy_object.instance_id());
}
}
void Vst3PluginBridge::unregister_plugin_proxy(
Vst3PluginProxyImpl& proxy_object) {
std::lock_guard lock(plugin_proxies_mutex);
std::lock_guard lock(plugin_proxies_mutex_);
plugin_proxies.erase(proxy_object.instance_id());
plugin_proxies_.erase(proxy_object.instance_id());
if (proxy_object.YaAudioProcessor::supported() ||
proxy_object.YaComponent::supported()) {
sockets.remove_audio_processor(proxy_object.instance_id());
sockets_.remove_audio_processor(proxy_object.instance_id());
}
}
+19 -19
View File
@@ -70,7 +70,7 @@ class Vst3PluginBridge : PluginBridge<Vst3Sockets<std::jthread>> {
* have to manually increase the reference count here for every plugin
* factory instance we return.
*
* @see plugin_factory
* @see plugin_factory_
*/
Steinberg::IPluginFactory* get_plugin_factory();
@@ -93,7 +93,7 @@ class Vst3PluginBridge : PluginBridge<Vst3Sockets<std::jthread>> {
* @param proxy_object The proxy object so we can access its host context
* and unique instance identifier.
*
* @see plugin_proxies
* @see plugin_proxies_
*/
void register_plugin_proxy(Vst3PluginProxyImpl& proxy_object);
@@ -105,19 +105,19 @@ class Vst3PluginBridge : PluginBridge<Vst3Sockets<std::jthread>> {
* @param proxy_object The proxy object so we can access its unique instance
* identifier.
*
* @see plugin_proxies
* @see plugin_proxies_
*/
void unregister_plugin_proxy(Vst3PluginProxyImpl& proxy_object);
/**
* Send a control message to the Wine plugin host return the response. This
* is a shorthand for `sockets.host_vst_control.send_message` for use in
* is a shorthand for `sockets_.host_vst_control_.send_message()` for use in
* VST3 interface implementations.
*/
template <typename T>
typename T::Response send_message(const T& object) {
return sockets.host_vst_control.send_message(
object, std::pair<Vst3Logger&, bool>(logger, true));
return sockets_.host_vst_control_.send_message(
object, std::pair<Vst3Logger&, bool>(logger_, true));
}
/**
@@ -128,8 +128,8 @@ class Vst3PluginBridge : PluginBridge<Vst3Sockets<std::jthread>> {
*/
template <typename T>
typename T::Response send_audio_processor_message(const T& object) {
return sockets.send_audio_processor_message(
object, std::pair<Vst3Logger&, bool>(logger, true));
return sockets_.send_audio_processor_message(
object, std::pair<Vst3Logger&, bool>(logger_, true));
}
/**
@@ -142,9 +142,9 @@ class Vst3PluginBridge : PluginBridge<Vst3Sockets<std::jthread>> {
typename T::Response& receive_audio_processor_message_into(
const T& object,
typename T::Response& response_object) {
return sockets.receive_audio_processor_message_into(
return sockets_.receive_audio_processor_message_into(
object, response_object,
std::pair<Vst3Logger&, bool>(logger, true));
std::pair<Vst3Logger&, bool>(logger_, true));
}
/**
@@ -161,7 +161,7 @@ class Vst3PluginBridge : PluginBridge<Vst3Sockets<std::jthread>> {
*/
template <typename T>
typename T::Response send_mutually_recursive_message(const T& object) {
return mutual_recursion.fork([&]() { return send_message(object); });
return mutual_recursion_.fork([&]() { return send_message(object); });
}
/**
@@ -178,21 +178,21 @@ class Vst3PluginBridge : PluginBridge<Vst3Sockets<std::jthread>> {
template <std::invocable F>
std::optional<std::invoke_result_t<F>> maybe_run_on_mutual_recursion_thread(
F&& fn) {
return mutual_recursion.maybe_handle(std::forward<F>(fn));
return mutual_recursion_.maybe_handle(std::forward<F>(fn));
}
/**
* The logging facility used for this instance of yabridge. Wraps around
* `PluginBridge::generic_logger`.
*/
Vst3Logger logger;
Vst3Logger logger_;
private:
/**
* Handles callbacks from the plugin to the host over the
* `vst_host_callback` sockets.
* `vst_host_callback_` sockets.
*/
std::jthread host_callback_handler;
std::jthread host_callback_handler_;
/**
* Our plugin factory. All information about the plugin and its supported
@@ -202,7 +202,7 @@ class Vst3PluginBridge : PluginBridge<Vst3Sockets<std::jthread>> {
*
* @related get_plugin_factory
*/
Steinberg::IPtr<Vst3PluginFactoryProxyImpl> plugin_factory = nullptr;
Steinberg::IPtr<Vst3PluginFactoryProxyImpl> plugin_factory_ = nullptr;
/**
* All VST3 plugin objects we created from this plugin. We keep track of
@@ -215,7 +215,7 @@ class Vst3PluginBridge : PluginBridge<Vst3Sockets<std::jthread>> {
* the destructor.
*/
std::unordered_map<size_t, std::reference_wrapper<Vst3PluginProxyImpl>>
plugin_proxies;
plugin_proxies_;
/**
* In theory all object handling is safe iff the host also doesn't do
@@ -228,12 +228,12 @@ class Vst3PluginBridge : PluginBridge<Vst3Sockets<std::jthread>> {
* `get_proxy()` never yields to the scheduler during audio
* processing, but it's still something we should avoid at all costs.
*/
std::shared_mutex plugin_proxies_mutex;
std::shared_mutex plugin_proxies_mutex_;
/**
* Used in `Vst3Bridge::send_mutually_recursive_message()` to be able to
* execute functions from that same calling thread while we're waiting for a
* response. This is used in `Vst3PlugViewProxyImpl::run_loop_tasks()`.
*/
MutualRecursionHelper<std::jthread> mutual_recursion;
MutualRecursionHelper<std::jthread> mutual_recursion_;
};