// 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 .
#include "vst3.h"
#include "src/common/serialization/vst3.h"
Vst3Logger::Vst3Logger(Logger& generic_logger) : logger(generic_logger) {}
void Vst3Logger::log_unknown_interface(
const std::string& where,
const std::optional& uid) {
if (BOOST_UNLIKELY(logger.verbosity >= Logger::Verbosity::most_events)) {
std::string uid_string = uid ? format_uid(*uid) : "";
std::ostringstream message;
message << "[unknown interface] " << where << ": " << uid_string;
log(message.str());
}
}
void Vst3Logger::log_request(bool is_host_vst,
const Vst3PluginProxy::Construct& request) {
log_request_base(is_host_vst, [&](auto& message) {
message << "IPluginFactory::createComponent(cid = "
<< format_uid(Steinberg::FUID::fromTUID(request.cid.data()))
<< ", _iid = ";
switch (request.requested_interface) {
case Vst3PluginProxy::Construct::Interface::IComponent:
message << "IComponent::iid";
break;
case Vst3PluginProxy::Construct::Interface::IEditController:
message << "IEditController::iid";
break;
}
message << ", &obj)";
});
}
void Vst3Logger::log_request(bool is_host_vst,
const Vst3PluginProxy::Destruct& request) {
log_request_base(is_host_vst, [&](auto& message) {
// We don't know what class this instance was originally instantiated
// as, but it also doesn't really matter
message << "::~FUnknown()";
});
}
void Vst3Logger::log_request(bool is_host_vst,
const Vst3PluginProxy::SetState& request) {
log_request_base(is_host_vst, [&](auto& message) {
message << "<{IComponent,IEditController}* #" << request.instance_id
<< ">::setState(state = )";
});
}
void Vst3Logger::log_request(bool is_host_vst,
const Vst3PluginProxy::GetState& request) {
log_request_base(is_host_vst, [&](auto& message) {
message << "<{IComponent,IEditController}* #" << request.instance_id
<< ">::getState(state = )";
});
}
void Vst3Logger::log_request(
bool is_host_vst,
const YaAudioProcessor::SetBusArrangements& request) {
log_request_base(is_host_vst, [&](auto& message) {
message << "::setBusArrangements(inputs = [SpeakerArrangement; "
<< request.inputs.size() << "], numIns = " << request.num_ins
<< ", outputs = [SpeakerArrangement; " << request.outputs.size()
<< "], numOuts = " << request.num_outs << ")";
});
}
void Vst3Logger::log_request(
bool is_host_vst,
const YaAudioProcessor::GetBusArrangement& request) {
log_request_base(is_host_vst, [&](auto& message) {
message << "::getBusArrangement(dir = " << request.dir
<< ", index = " << request.index << ", &arr)";
});
}
void Vst3Logger::log_request(
bool is_host_vst,
const YaAudioProcessor::CanProcessSampleSize& request) {
log_request_base(is_host_vst, [&](auto& message) {
message << "::canProcessSampleSize(symbolicSampleSize = "
<< request.symbolic_sample_size << ")";
});
}
void Vst3Logger::log_request(
bool is_host_vst,
const YaAudioProcessor::GetLatencySamples& request) {
log_request_base(is_host_vst, [&](auto& message) {
message << "::getLatencySamples()";
});
}
void Vst3Logger::log_request(bool is_host_vst,
const YaAudioProcessor::SetupProcessing& request) {
log_request_base(is_host_vst, [&](auto& message) {
message << "::setupProcessing(setup = )";
});
}
void Vst3Logger::log_request(bool is_host_vst,
const YaAudioProcessor::SetProcessing& request) {
log_request_base(is_host_vst, [&](auto& message) {
message << "::setProcessing(state = "
<< (request.state ? "true" : "false") << ")";
});
}
void Vst3Logger::log_request(bool is_host_vst,
const YaAudioProcessor::Process& request) {
log_request_base(
is_host_vst, Logger::Verbosity::all_events, [&](auto& message) {
// This is incredibly verbose, but if you're really a plugin that
// handles processing in a weird way you're going to need all of
// this
std::ostringstream num_input_channels;
num_input_channels << "[";
for (bool is_first = true;
const auto& buffers : request.data.inputs) {
num_input_channels << (is_first ? "" : ", ")
<< buffers.num_channels();
is_first = false;
}
num_input_channels << "]";
std::ostringstream num_output_channels;
num_output_channels << "[";
for (bool is_first = true;
const auto& num_channels : request.data.outputs_num_channels) {
num_output_channels << (is_first ? "" : ", ") << num_channels;
is_first = false;
}
num_output_channels << "]";
message << "::process(data = , output_parameter_changes = "
<< (request.data.output_parameter_changes_supported
? ""
: "nullptr")
<< ", input_events = ";
if (request.data.input_events) {
message << "num_events()
<< " events>";
} else {
message << "nullptr";
}
message << ", output_events = "
<< (request.data.output_events_supported ? ""
: "nullptr")
<< ", process_context = "
<< (request.data.process_context ? ""
: "nullptr")
<< ", process_mode = " << request.data.process_mode
<< ", symbolic_sample_size = "
<< request.data.symbolic_sample_size << ">)";
});
}
void Vst3Logger::log_request(bool is_host_vst,
const YaAudioProcessor::GetTailSamples& request) {
log_request_base(is_host_vst, [&](auto& message) {
message << "::getTailSamples()";
});
}
void Vst3Logger::log_request(bool is_host_vst,
const YaComponent::SetIoMode& request) {
log_request_base(is_host_vst, [&](auto& message) {
message << "::setIoMode(mode = " << request.mode << ")";
});
}
void Vst3Logger::log_request(bool is_host_vst,
const YaComponent::GetBusCount& request) {
log_request_base(is_host_vst, [&](auto& message) {
message << "::getBusCount(type = " << request.type
<< ", dir = " << request.dir << ")";
});
}
void Vst3Logger::log_request(bool is_host_vst,
const YaComponent::GetBusInfo& request) {
log_request_base(is_host_vst, [&](auto& message) {
message << "::getBusInfo(type = " << request.type
<< ", dir = " << request.dir << ", index = " << request.index
<< ", &bus)";
});
}
void Vst3Logger::log_request(bool is_host_vst,
const YaComponent::GetRoutingInfo& request) {
log_request_base(is_host_vst, [&](auto& message) {
message << "::getRoutingInfo(inInfo = , outInfo = )";
});
}
void Vst3Logger::log_request(bool is_host_vst,
const YaComponent::ActivateBus& request) {
log_request_base(is_host_vst, [&](auto& message) {
message << "::activateBus(type = " << request.type
<< ", dir = " << request.dir << ", index = " << request.index
<< ", state = " << (request.state ? "true" : "false") << ")";
});
}
void Vst3Logger::log_request(bool is_host_vst,
const YaComponent::SetActive& request) {
log_request_base(is_host_vst, [&](auto& message) {
message << "::setActive(state = " << (request.state ? "true" : "false")
<< ")";
});
}
void Vst3Logger::log_request(bool is_host_vst,
const YaPluginBase::Initialize& request) {
log_request_base(is_host_vst, [&](auto& message) {
message << "::initialize(context = ";
if (request.host_application_context_args) {
message << "";
} else {
message << "";
}
message << ")";
});
}
void Vst3Logger::log_request(bool is_host_vst,
const YaPluginBase::Terminate& request) {
log_request_base(is_host_vst, [&](auto& message) {
message << "::terminate()";
});
}
void Vst3Logger::log_request(bool is_host_vst,
const YaPluginFactory::Construct&) {
log_request_base(is_host_vst,
[&](auto& message) { message << "GetPluginFactory()"; });
}
void Vst3Logger::log_request(bool is_host_vst,
const YaPluginFactory::SetHostContext&) {
log_request_base(is_host_vst, [&](auto& message) {
message << "IPluginFactory3::setHostContext(IHostApplication*)";
});
}
void Vst3Logger::log_request(bool is_host_vst, const WantsConfiguration&) {
log_request_base(is_host_vst, [&](auto& message) {
message << "Requesting ";
});
}
void Vst3Logger::log_response(bool is_host_vst, const Ack&) {
log_response_base(is_host_vst, [&](auto& message) { message << "ACK"; });
}
void Vst3Logger::log_response(bool is_host_vst,
const std::variant& result) {
log_response_base(is_host_vst, [&](auto& message) {
std::visit(overload{[&](const Vst3PluginProxy::ConstructArgs& args) {
message << "";
},
[&](const UniversalTResult& code) {
message << code.string();
}},
result);
});
}
void Vst3Logger::log_response(
bool is_host_vst,
const Vst3PluginProxy::GetStateResponse& response) {
log_response_base(is_host_vst, [&](auto& message) {
message << response.result.string();
if (response.result == Steinberg::kResultOk) {
message << ", ";
}
});
}
void Vst3Logger::log_response(
bool is_host_vst,
const YaAudioProcessor::GetBusArrangementResponse& response) {
log_response_base(is_host_vst, [&](auto& message) {
message << response.result.string();
if (response.result == Steinberg::kResultOk) {
message << ", ";
}
});
}
void Vst3Logger::log_response(
bool is_host_vst,
const YaAudioProcessor::ProcessResponse& response) {
log_response_base(
is_host_vst, Logger::Verbosity::all_events, [&](auto& message) {
message << response.result.string();
// This is incredibly verbose, but if you're really a plugin that
// handles processing in a weird way you're going to need all of
// this
std::ostringstream num_output_channels;
num_output_channels << "[";
for (bool is_first = true;
const auto& buffers : response.output_data.outputs) {
num_output_channels << (is_first ? "" : ", ")
<< buffers.num_channels();
is_first = false;
}
num_output_channels << "]";
message << ", ";
if (response.output_data.output_parameter_changes) {
message << ", num_parameters()
<< " parameters>";
} else {
message << ", host does not support parameter outputs";
}
if (response.output_data.output_events) {
message << ", num_events()
<< " events>";
} else {
message << ", host does not support event outputs";
}
});
}
void Vst3Logger::log_response(bool is_host_vst,
const YaComponent::GetBusInfoResponse& response) {
log_response_base(is_host_vst, [&](auto& message) {
message << response.result.string();
if (response.result == Steinberg::kResultOk) {
message << ", ";
}
});
}
void Vst3Logger::log_response(
bool is_host_vst,
const YaComponent::GetRoutingInfoResponse& response) {
log_response_base(is_host_vst, [&](auto& message) {
message << response.result.string();
if (response.result == Steinberg::kResultOk) {
message << ", ";
}
});
}
void Vst3Logger::log_response(bool is_host_vst,
const YaPluginFactory::ConstructArgs& args) {
log_response_base(is_host_vst, [&](auto& message) {
message << " with " << args.num_classes
<< " registered classes";
});
}
void Vst3Logger::log_response(bool is_host_vst, const Configuration&) {
log_response_base(is_host_vst,
[&](auto& message) { message << ""; });
}