Properly handle effGet{Input,Output}Properties

Apparently the plugin needs the actual contents of the struct for this
to work.
This commit is contained in:
Robbert van der Helm
2020-03-26 16:24:49 +01:00
parent 0d7a5f10cd
commit cc52c87f34
4 changed files with 62 additions and 21 deletions
+8 -1
View File
@@ -135,6 +135,7 @@ intptr_t send_event(boost::asio::local::stream_protocol::socket& socket,
const std::optional<EventPayload> payload = const std::optional<EventPayload> payload =
data_converter.read(opcode, index, value, data); data_converter.read(opcode, index, value, data);
if (!payload.has_value()) { if (!payload.has_value()) {
// A 1 usually means that the event was processed succesfully
return 1; return 1;
} }
@@ -217,7 +218,8 @@ void passthrough_event(boost::asio::local::stream_protocol::socket& socket,
return &events.as_c_events(); return &events.as_c_events();
}, },
[&](WantsChunkBuffer&) -> void* { return string_buffer.data(); }, [&](WantsChunkBuffer&) -> void* { return string_buffer.data(); },
[&](const WantsVstRect&) -> void* { return string_buffer.data(); }, [&](VstIOProperties& props) -> void* { return &props; },
[&](WantsVstRect&) -> void* { return string_buffer.data(); },
[&](const WantsVstTimeInfo&) -> void* { return nullptr; }, [&](const WantsVstTimeInfo&) -> void* { return nullptr; },
[&](WantsString&) -> void* { return string_buffer.data(); }}, [&](WantsString&) -> void* { return string_buffer.data(); }},
event.payload); event.payload);
@@ -265,6 +267,11 @@ void passthrough_event(boost::asio::local::stream_protocol::socket& socket,
return std::string(*static_cast<char**>(data), return std::string(*static_cast<char**>(data),
return_value); return_value);
}, },
[&](VstIOProperties& props) -> EventResposnePayload {
// The plugin has written a pointer to a VstRect struct
// into the data poitner
return props;
},
[&](WantsVstRect&) -> EventResposnePayload { [&](WantsVstRect&) -> EventResposnePayload {
// The plugin has written a pointer to a VstRect struct // The plugin has written a pointer to a VstRect struct
// into the data poitner // into the data poitner
+20 -17
View File
@@ -177,6 +177,7 @@ void Logger::log_event(bool is_dispatch,
[&](const WantsChunkBuffer&) { [&](const WantsChunkBuffer&) {
message << "<writable_buffer>"; message << "<writable_buffer>";
}, },
[&](const VstIOProperties&) { message << "<io_properties>"; },
[&](const WantsVstRect&) { message << "<writable_buffer>"; }, [&](const WantsVstRect&) { message << "<writable_buffer>"; },
[&](const WantsVstTimeInfo&) { message << "<nullptr>"; }, [&](const WantsVstTimeInfo&) { message << "<nullptr>"; },
[&](const WantsString&) { message << "<writable_string>"; }}, [&](const WantsString&) { message << "<writable_string>"; }},
@@ -202,23 +203,25 @@ void Logger::log_event_response(bool is_dispatch,
message << return_value; message << return_value;
std::visit( std::visit(
overload{[&](const std::monostate&) {}, overload{
[&](const std::string& s) { [&](const std::monostate&) {},
if (s.size() < 32) { [&](const std::string& s) {
message << ", \"" << s << "\""; if (s.size() < 32) {
} else { message << ", \"" << s << "\"";
// Long strings contain binary data that we } else {
// probably don't want to print // Long strings contain binary data that we probably
message << ", <" << s.size() << " bytes>"; // don't want to print
} message << ", <" << s.size() << " bytes>";
}, }
[&](const AEffect&) { message << ", <AEffect_object>"; }, },
[&](const VstRect& rect) { [&](const AEffect&) { message << ", <AEffect_object>"; },
message << ", {l: " << rect.left << ", t: " << rect.top [&](const VstIOProperties&) { message << ", <io_properties>"; },
<< ", r: " << rect.right [&](const VstRect& rect) {
<< ", b: " << rect.bottom << "}"; message << ", {l: " << rect.left << ", t: " << rect.top
}, << ", r: " << rect.right << ", b: " << rect.bottom
[&](const VstTimeInfo&) { message << ", <time_info>"; }}, << "}";
},
[&](const VstTimeInfo&) { message << ", <time_info>"; }},
payload); payload);
log(message.str()); log(message.str());
+16 -2
View File
@@ -27,6 +27,8 @@
#include <variant> #include <variant>
#include "vst24.h"
// These constants are limits used by bitsery // These constants are limits used by bitsery
/** /**
@@ -83,6 +85,11 @@ void serialize(S& s, AEffect& plugin) {
s.value4b(plugin.version); s.value4b(plugin.version);
} }
template <typename S>
void serialize(S& s, VstIOProperties& props) {
s.container1b(props.data);
}
template <typename S> template <typename S>
void serialize(S& s, VstRect& rect) { void serialize(S& s, VstRect& rect) {
s.value2b(rect.top); s.value2b(rect.top);
@@ -212,6 +219,7 @@ using EventPayload = std::variant<std::nullptr_t,
AEffect, AEffect,
DynamicVstEvents, DynamicVstEvents,
WantsChunkBuffer, WantsChunkBuffer,
VstIOProperties,
WantsVstRect, WantsVstRect,
WantsVstTimeInfo, WantsVstTimeInfo,
WantsString>; WantsString>;
@@ -233,6 +241,7 @@ void serialize(S& s, EventPayload& payload) {
events.events, max_midi_events, events.events, max_midi_events,
[](S& s, VstEvent& event) { s.container1b(event.dump); }); [](S& s, VstEvent& event) { s.container1b(event.dump); });
}, },
[](S& s, VstIOProperties& props) { s.object(props); },
[](S&, WantsChunkBuffer&) {}, [](S&, WantsVstRect&) {}, [](S&, WantsChunkBuffer&) {}, [](S&, WantsVstRect&) {},
[](S&, WantsVstTimeInfo&) {}, [](S&, WantsString&) {}}); [](S&, WantsVstTimeInfo&) {}, [](S&, WantsString&) {}});
} }
@@ -289,8 +298,12 @@ struct Event {
* `audioMasterIOChanged`. * `audioMasterIOChanged`.
* - An X11 window pointer for the editor window. * - An X11 window pointer for the editor window.
*/ */
using EventResposnePayload = using EventResposnePayload = std::variant<std::monostate,
std::variant<std::monostate, std::string, AEffect, VstRect, VstTimeInfo>; std::string,
AEffect,
VstIOProperties,
VstRect,
VstTimeInfo>;
template <typename S> template <typename S>
void serialize(S& s, EventResposnePayload& payload) { void serialize(S& s, EventResposnePayload& payload) {
@@ -304,6 +317,7 @@ void serialize(S& s, EventResposnePayload& payload) {
s.text1b(string, binary_buffer_size); s.text1b(string, binary_buffer_size);
}, },
[](S& s, AEffect& effect) { s.object(effect); }, [](S& s, AEffect& effect) { s.object(effect); },
[](S& s, VstIOProperties& props) { s.object(props); },
[](S& s, VstRect& rect) { s.object(rect); }, [](S& s, VstRect& rect) { s.object(rect); },
[](S& s, VstTimeInfo& time_info) { s.object(time_info); }}); [](S& s, VstTimeInfo& time_info) { s.object(time_info); }});
} }
+18 -1
View File
@@ -206,6 +206,13 @@ class DispatchDataConverter : DefaultDataConverter {
case effProcessEvents: case effProcessEvents:
return DynamicVstEvents(*static_cast<const VstEvents*>(data)); return DynamicVstEvents(*static_cast<const VstEvents*>(data));
break; break;
case effGetInputProperties:
case effGetOutputProperties:
// In this case we can't simply pass an empty marker struct
// because the host can have already populated this field with
// data (or at least Bitwig does this)
return *static_cast<const VstIOProperties*>(data);
break;
default: default:
return DefaultDataConverter::read(opcode, index, value, data); return DefaultDataConverter::read(opcode, index, value, data);
break; break;
@@ -232,11 +239,21 @@ class DispatchDataConverter : DefaultDataConverter {
// `HostBridge` and write a pointer to that struct to the data // `HostBridge` and write a pointer to that struct to the data
// pointer // pointer
std::string buffer = std::get<std::string>(response.payload); const auto buffer = std::get<std::string>(response.payload);
chunk.assign(buffer.begin(), buffer.end()); chunk.assign(buffer.begin(), buffer.end());
*static_cast<void**>(data) = chunk.data(); *static_cast<void**>(data) = chunk.data();
} break; } break;
case effGetInputProperties:
case effGetOutputProperties: {
// These opcodes pass the plugin some empty struct through the
// data parameter that the plugin then fills with flags and
// other data to describe an input or output channel.
const auto properties =
std::get<VstIOProperties>(response.payload);
*static_cast<VstIOProperties*>(data) = properties;
} break;
default: default:
DefaultDataConverter::write(opcode, data, response); DefaultDataConverter::write(opcode, data, response);
break; break;