// 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 << ""; }); }