mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-07 03:50:11 +02:00
0b9a16cf40
I'm not a fan of Hungarian notation, but C++ kind of needs it with its implicit `this`. And of all the common options for this, I find suffixing members with an underscore the least offensive one.
145 lines
5.5 KiB
C++
145 lines
5.5 KiB
C++
// yabridge: a Wine VST bridge
|
|
// Copyright (C) 2020-2022 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 <https://www.gnu.org/licenses/>.
|
|
|
|
#pragma once
|
|
|
|
#include <pluginterfaces/vst/ivstmessage.h>
|
|
|
|
#include "../../bitsery/ext/in-place-optional.h"
|
|
#include "../common.h"
|
|
#include "attribute-list.h"
|
|
#include "base.h"
|
|
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
|
|
|
/**
|
|
* A serialization wrapper around `IMessage`. As explained in `YaMessage`, we
|
|
* can't exchange the regular `YaMessage` object when dealing with
|
|
* `IConnectionPoint` connection proxies. Instead, we'll use this wrapper that
|
|
* only stores the ID (for logging purposes) and a pointer to the original
|
|
* object. That way we can pass the original message created by the plugin to
|
|
* the receiver without having to know what object the host's connection proxy
|
|
* is actually connecting us to.
|
|
*
|
|
* @note THis object should _not_ be passed to the plugin directly. The only
|
|
* purpose of this object is to be able to pass the original `IMessage*`
|
|
* object passed the connection proxy to the receiver, by wrapping a pointer
|
|
* to it in this object. `YaMessagePtr::get_original()` can be used to
|
|
* retrieve the original object.
|
|
*/
|
|
class YaMessagePtr : public Steinberg::Vst::IMessage {
|
|
public:
|
|
YaMessagePtr() noexcept;
|
|
|
|
/**
|
|
* Create a proxy for this message. We'll store the message's ID for logging
|
|
* purposes as well as a pointer to it so we can retrieve the object after a
|
|
* round trip from the Wine plugin host, to the native plugin, to the host,
|
|
* back to the native plugin, and then finally back to the Wine plugin host
|
|
* again.
|
|
*/
|
|
explicit YaMessagePtr(IMessage& message);
|
|
|
|
~YaMessagePtr() noexcept;
|
|
|
|
DECLARE_FUNKNOWN_METHODS
|
|
|
|
/**
|
|
* Get back a pointer to the original `IMessage` object passed to the
|
|
* constructor. This should be used on the Wine plugin host side when
|
|
* handling `IConnectionPoint::notify`.
|
|
*/
|
|
Steinberg::Vst::IMessage* get_original() const noexcept;
|
|
|
|
virtual Steinberg::FIDString PLUGIN_API getMessageID() override;
|
|
virtual void PLUGIN_API
|
|
setMessageID(Steinberg::FIDString id /*in*/) override;
|
|
virtual Steinberg::Vst::IAttributeList* PLUGIN_API getAttributes() override;
|
|
|
|
template <typename S>
|
|
void serialize(S& s) {
|
|
s.ext(message_id_, bitsery::ext::InPlaceOptional{},
|
|
[](S& s, std::string& id) { s.text1b(id, 1024); });
|
|
s.value8b(original_message_ptr_);
|
|
}
|
|
|
|
private:
|
|
/**
|
|
* The implementation that comes with the SDK returns a null pointer when
|
|
* the ID has not yet been set, so we'll do the same thing.
|
|
*/
|
|
std::optional<std::string> message_id_;
|
|
|
|
/**
|
|
* The pointer to the message passed during the constructor, as a 64-bit
|
|
* unsigned integer. This way we can retrieve the original object after a
|
|
* round trip.
|
|
*/
|
|
native_size_t original_message_ptr_ = 0;
|
|
|
|
/**
|
|
* An empty attribute list, in case the host checks this for some reason.
|
|
*/
|
|
YaAttributeList attribute_list_;
|
|
};
|
|
|
|
/**
|
|
* A `IMessage` implementation the plugin can use to exchange messages with. We
|
|
* create instances of these in `IHostApplication::createInstance()` so the
|
|
* Windows VST3 plugin can send messages between objects. A plugin's controller
|
|
* or processor will fill the message with data and then try to send it to the
|
|
* connected object using `IConnectionPoint::notify()`. For directly connected
|
|
* objects this works exactly like you'd expect. When the host places a proxy
|
|
* between the two, it becomes a bit more interesting, and we'll have to proxy
|
|
* that proxy. In that case we won't send the actual `YaMessage` object from the
|
|
* Wine plugin host to the native plugin, and then back to the Wine plugin host.
|
|
* Instead, we'll send a thin wrapper that only stores a name and a pointer to
|
|
* the actual object. This is needed in case the plugin tries to store the
|
|
* `IMessage` object, thinking it's backed by a smart pointer. This means that
|
|
* the message we pass while handling `IConnectionPoint::notify` should live as
|
|
* long as the original message object, thus we'll use a pointer to get back the
|
|
* original message object.
|
|
*
|
|
* @relates YaMessagePtr
|
|
*/
|
|
class YaMessage : public Steinberg::Vst::IMessage {
|
|
public:
|
|
/**
|
|
* Default constructor with an empty message. The plugin can use this to
|
|
* write a message.
|
|
*/
|
|
YaMessage() noexcept;
|
|
|
|
~YaMessage() noexcept;
|
|
|
|
DECLARE_FUNKNOWN_METHODS
|
|
|
|
virtual Steinberg::FIDString PLUGIN_API getMessageID() override;
|
|
virtual void PLUGIN_API
|
|
setMessageID(Steinberg::FIDString id /*in*/) override;
|
|
virtual Steinberg::Vst::IAttributeList* PLUGIN_API getAttributes() override;
|
|
|
|
private:
|
|
/**
|
|
* The implementation that comes with the SDK returns a null pointer when
|
|
* the ID has not yet been set, so we'll do the same thing.
|
|
*/
|
|
std::optional<std::string> message_id_;
|
|
|
|
YaAttributeList attribute_list_;
|
|
};
|