// 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 #include "../../common.h" #include "../base.h" #include "../process-data.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wnon-virtual-dtor" /** * Wraps around `IAudioProcessor` for serialization purposes. This is * instantiated as part of `Vst3PluginProxy`. */ class YaAudioProcessor : public Steinberg::Vst::IAudioProcessor { public: /** * These are the arguments for creating a `YaAudioProcessor`. */ struct ConstructArgs { ConstructArgs(); /** * Check whether an existing implementation implements `IAudioProcessor` * and read arguments from it. */ ConstructArgs(Steinberg::IPtr object); /** * Whether the object supported this interface. */ bool supported; template void serialize(S& s) { s.value1b(supported); } }; /** * Instantiate this instance with arguments read from another interface * implementation. */ YaAudioProcessor(const ConstructArgs&& args); inline bool supported() const { return arguments.supported; } /** * Message to pass through a call to * `IAudioProcessor::setBusArrangements(inputs, num_ins, outputs, num_outs)` * to the Wine plugin host. */ struct SetBusArrangements { using Response = UniversalTResult; native_size_t instance_id; // These are orginally C-style heap arrays, not normal pointers std::vector inputs; int32 num_ins; std::vector outputs; int32 num_outs; template void serialize(S& s) { s.value8b(instance_id); s.container8b(inputs, max_num_speakers); s.value4b(num_ins); s.container8b(outputs, max_num_speakers); s.value4b(num_outs); } }; virtual tresult PLUGIN_API setBusArrangements(Steinberg::Vst::SpeakerArrangement* inputs, int32 numIns, Steinberg::Vst::SpeakerArrangement* outputs, int32 numOuts) override = 0; /** * The response code and written state for a call to * `IAudioProcessor::getBusArrangement(dir, index, arr)`. */ struct GetBusArrangementResponse { UniversalTResult result; Steinberg::Vst::SpeakerArrangement updated_arr; template void serialize(S& s) { s.object(result); s.value8b(updated_arr); } }; /** * Message to pass through a call to * `IAudioProcessor::getBusArrangement(dir, index, arr)` to the Wine * plugin host. */ struct GetBusArrangement { using Response = GetBusArrangementResponse; native_size_t instance_id; Steinberg::Vst::BusDirection dir; int32 index; Steinberg::Vst::SpeakerArrangement arr; template void serialize(S& s) { s.value8b(instance_id); s.value4b(dir); s.value4b(index); s.value8b(arr); } }; virtual tresult PLUGIN_API getBusArrangement(Steinberg::Vst::BusDirection dir, int32 index, Steinberg::Vst::SpeakerArrangement& arr) override = 0; /** * Message to pass through a call to * `IAudioProcessor::canProcessSampleSize(symbolic_sample_size)` to the Wine * plugin host. */ struct CanProcessSampleSize { using Response = UniversalTResult; native_size_t instance_id; int32 symbolic_sample_size; template void serialize(S& s) { s.value8b(instance_id); s.value4b(symbolic_sample_size); } }; virtual tresult PLUGIN_API canProcessSampleSize(int32 symbolicSampleSize) override = 0; /** * Message to pass through a call to `IAudioProcessor::getLatencySamples()` * to the Wine plugin host. */ struct GetLatencySamples { using Response = PrimitiveWrapper; native_size_t instance_id; template void serialize(S& s) { s.value8b(instance_id); } }; virtual uint32 PLUGIN_API getLatencySamples() override = 0; /** * Message to pass through a call to * `IAudioProcessor::setupProcessing(setup)` to the Wine plugin host. */ struct SetupProcessing { using Response = UniversalTResult; native_size_t instance_id; Steinberg::Vst::ProcessSetup setup; template void serialize(S& s) { s.value8b(instance_id); s.object(setup); } }; virtual tresult PLUGIN_API setupProcessing(Steinberg::Vst::ProcessSetup& setup) override = 0; /** * Message to pass through a call to `IAudioProcessor::setProcessing(state)` * to the Wine plugin host. */ struct SetProcessing { using Response = UniversalTResult; native_size_t instance_id; TBool state; template void serialize(S& s) { s.value8b(instance_id); s.value1b(state); } }; virtual tresult PLUGIN_API setProcessing(TBool state) override = 0; /** * The response code and all the output data resulting from a call to * `IAudioProcessor::process(data)`. */ struct ProcessResponse { UniversalTResult result; YaProcessDataResponse output_data; template void serialize(S& s) { s.object(result); s.object(output_data); } }; /** * Message to pass through a call to `IAudioProcessor::process(data)` to the * Wine plugin host. This `YaProcessData` object wraps around all input * audio buffers, parameter changes and events along with all context data * provided by the host so we can send it to the Wine plugin host. We can * then use `YaProcessData::get()` on the Wine plugin host side to * reconstruct the original `ProcessData` object, and we then finally use * `YaProcessData::move_outputs_to_response()` to create a response object * that we can write back to the `ProcessData` object provided by the host. */ struct Process { using Response = ProcessResponse; native_size_t instance_id; YaProcessData data; template void serialize(S& s) { s.value8b(instance_id); s.object(data); } }; virtual tresult PLUGIN_API process(Steinberg::Vst::ProcessData& data) override = 0; /** * Message to pass through a call to `IAudioProcessor::getTailSamples()` * to the Wine plugin host. */ struct GetTailSamples { using Response = PrimitiveWrapper; native_size_t instance_id; template void serialize(S& s) { s.value8b(instance_id); } }; virtual uint32 PLUGIN_API getTailSamples() override = 0; protected: ConstructArgs arguments; }; #pragma GCC diagnostic pop namespace Steinberg { namespace Vst { template void serialize(S& s, Steinberg::Vst::BusInfo& info) { s.value4b(info.mediaType); s.value4b(info.direction); s.value4b(info.channelCount); s.container2b(info.name); s.value4b(info.busType); s.value4b(info.flags); } template void serialize(S& s, Steinberg::Vst::RoutingInfo& info) { s.value4b(info.mediaType); s.value4b(info.busIndex); s.value4b(info.channel); } template void serialize(S& s, Steinberg::Vst::ProcessSetup& setup) { s.value4b(setup.processMode); s.value4b(setup.symbolicSampleSize); s.value4b(setup.maxSamplesPerBlock); s.value8b(setup.sampleRate); } } // namespace Vst } // namespace Steinberg