Finally implement eff{Set,Get}SpeakerConfiguration

As mentioned in #1. This also indirectly allows yabridge to work under
Renoise.
This commit is contained in:
Robbert van der Helm
2020-05-07 18:05:15 +02:00
parent 92f0d95357
commit 868b0fd357
6 changed files with 130 additions and 5 deletions
+72
View File
@@ -359,6 +359,13 @@ class DispatchDataConverter : DefaultDataConverter {
case effGetMidiKeyName:
return *static_cast<const VstMidiKeyName*>(data);
break;
case effSetSpeakerArrangement:
case effGetSpeakerArrangement:
// This is the output speaker configuration, the `read_value()`
// method below reads the input speaker configuration
return DynamicSpeakerArrangement(
*static_cast<const VstSpeakerArrangement*>(data));
break;
// Any VST host I've encountered has properly zeroed out these their
// string buffers, but we'll add a list of opcodes that should
// return a string just in case `DefaultDataConverter::read()` can't
@@ -380,6 +387,26 @@ class DispatchDataConverter : DefaultDataConverter {
}
}
std::optional<EventPayload> read_value(const int opcode,
const intptr_t value) {
switch (opcode) {
case effSetSpeakerArrangement:
case effGetSpeakerArrangement:
// These two events are special in that they pass a pointer to
// the output speaker configuration through the `data`
// parameter, but then they also pass a pointer to the input
// speaker configuration through the `value` parameter. This is
// the only event that does this.
return DynamicSpeakerArrangement(
*static_cast<const VstSpeakerArrangement*>(
reinterpret_cast<void*>(value)));
break;
default:
return DefaultDataConverter::read_value(opcode, value);
break;
}
}
void write(const int opcode, void* data, const EventResult& response) {
switch (opcode) {
case effEditGetRect: {
@@ -423,6 +450,25 @@ class DispatchDataConverter : DefaultDataConverter {
*static_cast<VstMidiKeyName*>(data) = properties;
} break;
case effGetSpeakerArrangement: {
// The plugin will have updated the objects passed by the host
// with its preferred output speaker configuration if it
// supports this. The same thing happens for the input speaker
// configuration in `write_value()`.
auto speaker_arrangement =
std::get<DynamicSpeakerArrangement>(response.payload);
// Reconstruct a dynamically sized `VstSpeakerArrangement`
// object to a buffer, and write back the results to the data
// parameter.
VstSpeakerArrangement* output =
static_cast<VstSpeakerArrangement*>(data);
std::vector<uint8_t> reconstructed_object =
speaker_arrangement.as_raw_data();
std::copy(reconstructed_object.begin(),
reconstructed_object.end(),
reinterpret_cast<uint8_t*>(output));
} break;
default:
DefaultDataConverter::write(opcode, data, response);
break;
@@ -433,6 +479,32 @@ class DispatchDataConverter : DefaultDataConverter {
return DefaultDataConverter::return_value(opcode, original);
}
void write_value(const int opcode,
intptr_t value,
const EventResult& response) {
switch (opcode) {
case effGetSpeakerArrangement: {
// Same as the above, but now for the input speaker
// configuration object under the `value` pointer
auto speaker_arrangement =
std::get<DynamicSpeakerArrangement>(response.payload);
VstSpeakerArrangement* output =
static_cast<VstSpeakerArrangement*>(
reinterpret_cast<void*>(value));
std::vector<uint8_t> reconstructed_object =
speaker_arrangement.as_raw_data();
std::copy(reconstructed_object.begin(),
reconstructed_object.end(),
reinterpret_cast<uint8_t*>(output));
} break;
default:
return DefaultDataConverter::write_value(opcode, value,
response);
break;
}
}
private:
std::vector<uint8_t>& chunk;
VstRect& rect;