diff --git a/src/common/communication/vst3.h b/src/common/communication/vst3.h
new file mode 100644
index 00000000..bab15217
--- /dev/null
+++ b/src/common/communication/vst3.h
@@ -0,0 +1,65 @@
+// yabridge: a Wine VST bridge
+// Copyright (C) 2020 Robbert van der Helm
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+#pragma once
+
+#include
+
+#include "common.h"
+
+/**
+ * Manages all the sockets used for communicating between the plugin and the
+ * Wine host when hosting a VST3 plugin.
+ *
+ * On the plugin side this class should be initialized with `listen` set to
+ * `true` before launching the Wine VST host. This will start listening on the
+ * sockets, and the call to `connect()` will then accept any incoming
+ * connections.
+ *
+ * @tparam Thread The thread implementation to use. On the Linux side this
+ * should be `std::jthread` and on the Wine side this should be `Win32Thread`.
+ */
+template
+class Vst3Sockets : public Sockets {
+ public:
+ /**
+ * Sets up the sockets using the specified base directory. The sockets won't
+ * be active until `connect()` gets called.
+ *
+ * @param io_context The IO context the sockets should be bound to. Relevant
+ * when doing asynchronous operations.
+ * @param endpoint_base_dir The base directory that will be used for the
+ * Unix domain sockets.
+ * @param listen If `true`, start listening on the sockets. Incoming
+ * connections will be accepted when `connect()` gets called. This should
+ * be set to `true` on the plugin side, and `false` on the Wine host side.
+ *
+ * @see Vst3Sockets::connect
+ */
+ Vst3Sockets(boost::asio::io_context& io_context,
+ const boost::filesystem::path& endpoint_base_dir,
+ bool listen)
+ : Sockets(endpoint_base_dir) {}
+
+ ~Vst3Sockets() { close(); }
+
+ void connect() override {}
+
+ void close() override {
+ // Manually close all sockets so we break out of any blocking operations
+ // that may still be active
+ }
+};
diff --git a/src/wine-host/bridges/group.cpp b/src/wine-host/bridges/group.cpp
index 350e400b..d38cbf49 100644
--- a/src/wine-host/bridges/group.cpp
+++ b/src/wine-host/bridges/group.cpp
@@ -208,7 +208,9 @@ void GroupBridge::accept_requests() {
break;
case PluginType::vst3:
#ifdef WITH_VST3
- throw std::runtime_error("TODO: Not yet implemented");
+ bridge = std::make_unique(
+ main_context, request.plugin_path,
+ request.endpoint_base_dir);
#else
throw std::runtime_error(
"This version of yabridge has not been compiled "
diff --git a/src/wine-host/bridges/vst2.h b/src/wine-host/bridges/vst2.h
index 403977b5..5f80c029 100644
--- a/src/wine-host/bridges/vst2.h
+++ b/src/wine-host/bridges/vst2.h
@@ -28,7 +28,6 @@
#include
#include
-#include
#include
#include "../../common/communication/vst2.h"
@@ -43,14 +42,14 @@
class Vst2Bridge : public HostBridge {
public:
/**
- * Initializes the Windows VST plugin and set up communication with the
- * native Linux VST plugin.
+ * Initializes the Windows VST2 plugin and set up communication with the
+ * native Linux VST2 plugin.
*
* @param main_context The main IO context for this application. Most events
* will be dispatched to this context, and the event handling loop should
* also be run from this context.
- * @param plugin_dll_path A (Unix style) path to the VST plugin .dll file to
- * load.
+ * @param plugin_dll_path A (Unix style) path to the VST2 plugin .dll file
+ * to load.
* @param endpoint_base_dir The base directory used for the socket
* endpoints. See `Sockets` for more information.
*
diff --git a/src/wine-host/bridges/vst3.cpp b/src/wine-host/bridges/vst3.cpp
index 11535ba9..700a46d0 100644
--- a/src/wine-host/bridges/vst3.cpp
+++ b/src/wine-host/bridges/vst3.cpp
@@ -18,24 +18,38 @@
#include "../boost-fix.h"
-// TODO: Do something with this, I just wanted to get the build working
#include
-void justdewit(const std::string& path) {
+Vst3Bridge::Vst3Bridge(MainContext& main_context,
+ std::string plugin_dll_path,
+ std::string endpoint_base_dir)
+ : HostBridge(plugin_dll_path),
+ main_context(main_context),
+ sockets(main_context.context, endpoint_base_dir, false) {
std::string error;
- std::shared_ptr plugin =
- VST3::Hosting::Win32Module::create(path, error);
+ module = VST3::Hosting::Win32Module::create(plugin_dll_path, error);
- if (plugin) {
+ // TODO: Do something more useful with this
+ if (module) {
// TODO: They use some thin wrappers around the interfaces, we can
// probably reuse these instead of having to make our own
- VST3::Hosting::FactoryInfo info = plugin->getFactory().info();
- std::cout << "Plugin name: " << plugin->getName() << std::endl;
+ VST3::Hosting::FactoryInfo info = module->getFactory().info();
+ std::cout << "Plugin name: " << module->getName() << std::endl;
std::cout << "Vendor: " << info.vendor() << std::endl;
std::cout << "URL: " << info.url() << std::endl;
std::cout << "Send spam to: " << info.email() << std::endl;
} else {
- std::cerr << "Ohnoes!" << std::endl;
- std::cerr << error << std::endl;
+ throw std::runtime_error("Could not load the VST3 module for '" +
+ plugin_dll_path + "': " + error);
}
+
+ sockets.connect();
+
+ // TODO: We should send a copy of the configuration from the plugin at this
+ // point config = sockets.host_vst_control.receive_single();
+}
+
+void Vst3Bridge::run() {
+ // TODO: Do something
+ std::cerr << "TODO: Not yet implemented" << std::endl;
}
diff --git a/src/wine-host/bridges/vst3.h b/src/wine-host/bridges/vst3.h
index e6206b82..45ca30a6 100644
--- a/src/wine-host/bridges/vst3.h
+++ b/src/wine-host/bridges/vst3.h
@@ -18,4 +18,65 @@
#include
-void justdewit(const std::string& path);
+#include
+
+#include "../../common/communication/vst3.h"
+#include "../../common/configuration.h"
+#include "common.h"
+
+/**
+ * This hosts a Windows VST3 plugin, forwards messages sent by the Linux VST
+ * plugin and provides host callback function for the plugin to talk back.
+ */
+class Vst3Bridge : public HostBridge {
+ public:
+ /**
+ * Initializes the Windows VST3 plugin and set up communication with the
+ * native Linux VST plugin.
+ *
+ * @param main_context The main IO context for this application. Most events
+ * will be dispatched to this context, and the event handling loop should
+ * also be run from this context.
+ * @param plugin_dll_path A (Unix style) path to the VST plugin .dll file to
+ * load.
+ * @param endpoint_base_dir The base directory used for the socket
+ * endpoints. See `Sockets` for more information.
+ *
+ * @note The object has to be constructed from the same thread that calls
+ * `main_context.run()`.
+ *
+ * @throw std::runtime_error Thrown when the VST plugin could not be loaded,
+ * or if communication could not be set up.
+ */
+ Vst3Bridge(MainContext& main_context,
+ std::string plugin_dll_path,
+ std::string endpoint_base_dir);
+
+ void run() override;
+
+ private:
+ /**
+ * The IO context used for event handling so that all events and window
+ * message handling can be performed from a single thread, even when hosting
+ * multiple plugins.
+ */
+ MainContext& main_context;
+
+ /**
+ * The configuration for this instance of yabridge based on the `.so` file
+ * that got loaded by the host. This configuration gets loaded on the plugin
+ * side, and then sent over to the Wine host as part of the startup process.
+ */
+ Configuration config;
+
+ std::shared_ptr module;
+
+ /**
+ * All sockets used for communicating with this specific plugin.
+ *
+ * NOTE: This is defined **after** the threads on purpose. This way the
+ * sockets will be closed first, and we can then safely wait for the
+ * threads to exit.
+ */
+ Vst3Sockets sockets;
+};
diff --git a/src/wine-host/individual-host.cpp b/src/wine-host/individual-host.cpp
index 1201ecf0..aeff5f5a 100644
--- a/src/wine-host/individual-host.cpp
+++ b/src/wine-host/individual-host.cpp
@@ -85,10 +85,8 @@ main(int argc, char* argv[]) {
break;
case PluginType::vst3:
#ifdef WITH_VST3
- justdewit(plugin_location);
-
- std::cerr << "TODO: Not yet implemented" << std::endl;
- return 1;
+ bridge = std::make_unique(
+ main_context, plugin_location, socket_endpoint_path);
#else
std::cerr << "This version of yabridge has not been compiled "
"with VST3 support"