// yabridge: a Wine VST bridge
// Copyright (C) 2020-2021 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 .
#include "boost-fix.h"
#include
// Generated inside of the build directory
#include
#include
#include "../common/utils.h"
#include "bridges/group.h"
#include "bridges/vst2.h"
/**
* This works very similar to the host application defined in
* `individual-host.cpp`, but instead of just loading a single plugin this will
* act as a daemon that can host multiple 'grouped' plugins. This works by
* allowing the `libyabridge-{vst2,vst3}.so` instance to connect this this
* process over a socket to ask this process to host a VST `.dll` file using a
* provided socket. After that initialization step both the regular individual
* plugin host and this group plugin host will function identically on both the
* plugin and the Wine VST host side.
*/
int __attribute__((visibility("default")))
#ifdef WINE_USE_CDECL
__cdecl
#endif
main(int argc, char* argv[]) {
// Instead of directly hosting a plugin, this process will receive a UNIX
// domain socket endpoint path that it should listen on to allow yabridge
// instances to spawn plugins in this process.
if (argc < 2) {
std::cerr << "Usage: "
#ifdef __i386__
<< yabridge_group_host_name_32bit
#else
<< yabridge_group_host_name
#endif
<< " " << std::endl;
return 1;
}
const std::string group_socket_endpoint_path(argv[1]);
std::cerr << "Initializing yabridge group host version "
<< yabridge_git_version
#ifdef __i386__
<< " (32-bit compatibility mode)"
#endif
<< std::endl;
// NOTE: Some plugins use Microsoft COM, but don't initialize it first and
// just pray the host does it for them. Examples of this are
// PSPaudioware's InfiniStrip and Shattered Glass Audio Code Red Free.
OleInitialize(nullptr);
try {
GroupBridge bridge(group_socket_endpoint_path);
// Blocks the main thread until all plugins have exited
bridge.handle_incoming_connections();
} catch (const boost::system::system_error& error) {
// If another process is already listening on the socket, we'll just
// print a message and exit quietly. This could happen if the host
// starts multiple yabridge instances that all use the same plugin group
// at the same time.
std::cerr << "Another process is already listening on this group's "
"socket, connecting to the existing process:"
<< std::endl;
std::cerr << error.what() << std::endl;
return 0;
} catch (const std::system_error& error) {
std::cerr << "Could not create pipe:" << std::endl;
std::cerr << error.what() << std::endl;
return 0;
}
// Like in `individual-host.cpp`, this shouldn't be needed, but sometimes
// with Wine background threads will be kept alive while this process exits
TerminateProcess(GetCurrentProcess(), 0);
}