mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-10 04:30:12 +02:00
Add a dynamic wrapper for VstSpeakerArrangement
Similar to `DynamicVstEvents`, so we can serialize the object to binary data transfer it over our sockets.
This commit is contained in:
@@ -32,9 +32,9 @@ VstEvents& DynamicVstEvents::as_c_events() {
|
|||||||
// First we need to allocate enough memory for the entire object. The events
|
// First we need to allocate enough memory for the entire object. The events
|
||||||
// are stored as pointers to objects in the `events` vector that we sent
|
// are stored as pointers to objects in the `events` vector that we sent
|
||||||
// over the socket.
|
// over the socket.
|
||||||
static_assert(std::extent<decltype(VstEvents::events)>::value == 1);
|
static_assert(std::extent_v<decltype(VstEvents::events)> == 1);
|
||||||
const size_t buffer_size =
|
const size_t buffer_size =
|
||||||
sizeof(VstEvents) + (events.size() - 1) * sizeof(VstEvent*);
|
sizeof(VstEvents) + ((events.size() - 1) * sizeof(VstEvent*));
|
||||||
vst_events_buffer.resize(buffer_size);
|
vst_events_buffer.resize(buffer_size);
|
||||||
|
|
||||||
// Now we can populate the VLA with pointers to the objects in the `events`
|
// Now we can populate the VLA with pointers to the objects in the `events`
|
||||||
@@ -47,3 +47,40 @@ VstEvents& DynamicVstEvents::as_c_events() {
|
|||||||
|
|
||||||
return *vst_events;
|
return *vst_events;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DynamicSpeakerArrangement::DynamicSpeakerArrangement(
|
||||||
|
const VstSpeakerArrangement& speaker_arrangement)
|
||||||
|
: flags(speaker_arrangement.flags),
|
||||||
|
speakers(speaker_arrangement.num_speakers) {
|
||||||
|
using speaker_type =
|
||||||
|
std::remove_extent_t<decltype(speaker_arrangement.speakers)>;
|
||||||
|
static_assert(std::is_same_v<speaker_type, VstSpeaker>);
|
||||||
|
|
||||||
|
// Copy from the C-style array into a vector for serialization
|
||||||
|
speakers.assign(
|
||||||
|
speaker_arrangement.speakers,
|
||||||
|
speaker_arrangement.speakers +
|
||||||
|
(speaker_arrangement.num_speakers * sizeof(speaker_type)));
|
||||||
|
}
|
||||||
|
|
||||||
|
VstSpeakerArrangement& DynamicSpeakerArrangement::as_c_speaker_arrangement() {
|
||||||
|
// Just like in `DynamicVstEvents::as_c_events()`, we will use our buffer
|
||||||
|
// vector to allocate enough heap space and then reconstruct the original
|
||||||
|
// `VstSpeakerArrangement` object passed to the constructor.
|
||||||
|
static_assert(std::extent_v<decltype(VstSpeakerArrangement::speakers)> ==
|
||||||
|
2);
|
||||||
|
const size_t buffer_size = sizeof(VstSpeakerArrangement) +
|
||||||
|
((speakers.size() - 2) * sizeof(VstSpeaker));
|
||||||
|
speaker_arrangement_buffer.resize(buffer_size);
|
||||||
|
|
||||||
|
// Now we'll just copy over the elements from our vector to the VLA in this
|
||||||
|
// struct
|
||||||
|
VstSpeakerArrangement* speaker_arrangement =
|
||||||
|
reinterpret_cast<VstSpeakerArrangement*>(
|
||||||
|
speaker_arrangement_buffer.data());
|
||||||
|
speaker_arrangement->flags = flags;
|
||||||
|
speaker_arrangement->num_speakers = speakers.size();
|
||||||
|
std::copy(speakers.begin(), speakers.end(), speaker_arrangement->speakers);
|
||||||
|
|
||||||
|
return *speaker_arrangement;
|
||||||
|
}
|
||||||
|
|||||||
@@ -190,8 +190,9 @@ class alignas(16) DynamicVstEvents {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Some buffer we can build a `VstEvents`. This object can be populated with
|
* Some buffer we can build a `VstEvents` object in. This object can be
|
||||||
* contents of the `VstEvents` vector using the `as_c_events()` method.
|
* populated with contents of the `VstEvents` vector using the
|
||||||
|
* `as_c_events()` method.
|
||||||
*
|
*
|
||||||
* The reason why this is necessary is because the `VstEvents` struct is
|
* The reason why this is necessary is because the `VstEvents` struct is
|
||||||
* actually a variable size object. In the definition in
|
* actually a variable size object. In the definition in
|
||||||
@@ -204,6 +205,54 @@ class alignas(16) DynamicVstEvents {
|
|||||||
std::vector<uint8_t> vst_events_buffer;
|
std::vector<uint8_t> vst_events_buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A wrapper around `VstSpeakerArrangement` that works the same way as the above
|
||||||
|
* wrapper for `VstEvents`. This is needed because the `VstSpeakerArrangement`
|
||||||
|
* struct is actually a variable sized array. Even though it will be very
|
||||||
|
* unlikely that we'll encounter systems with more than 8 speakers, it is
|
||||||
|
* something we should be able to support.
|
||||||
|
*
|
||||||
|
* Before serialization the events are read from a C-style array into a vector
|
||||||
|
* using this class's constructor, and after deserializing the original struct
|
||||||
|
* can be reconstructed using the `as_c_speaker_arrangement()` method.
|
||||||
|
*/
|
||||||
|
class alignas(16) DynamicSpeakerArrangement {
|
||||||
|
public:
|
||||||
|
DynamicSpeakerArrangement(){};
|
||||||
|
|
||||||
|
explicit DynamicSpeakerArrangement(
|
||||||
|
const VstSpeakerArrangement& speaker_arrangement);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a dynamically sized `VstSpeakerArrangement` struct based on
|
||||||
|
* this object.
|
||||||
|
*/
|
||||||
|
VstSpeakerArrangement& as_c_speaker_arrangement();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The flags field from `VstSpeakerArrangement`
|
||||||
|
*/
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information about the speakers in a particular input or output
|
||||||
|
* configuration.
|
||||||
|
*/
|
||||||
|
std::vector<VstSpeaker> speakers;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Some buffer we can build a `VstSpeakerArrangement` object in. This object
|
||||||
|
* can be populated using the `as_c_speaker_arrangement()` method.
|
||||||
|
*
|
||||||
|
* This is necessary because the `VstSpeakerArrangement` struct contains a
|
||||||
|
* dynamically sized array of length `VstSpeakerArrangement::num_speakers`.
|
||||||
|
* We build this object in a byte sized vector to make allocating enough
|
||||||
|
* heap space easy and safe.
|
||||||
|
*/
|
||||||
|
std::vector<uint8_t> speaker_arrangement_buffer;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marker struct to indicate that that the event writes arbitrary data into one
|
* Marker struct to indicate that that the event writes arbitrary data into one
|
||||||
* of its own buffers and uses the void pointer to store start of that data,
|
* of its own buffers and uses the void pointer to store start of that data,
|
||||||
@@ -348,8 +397,8 @@ struct Event {
|
|||||||
* gets passed along.
|
* gets passed along.
|
||||||
* - A (short) string.
|
* - A (short) string.
|
||||||
* - Some binary blob stored as a byte vector. During `effGetChunk` this will
|
* - Some binary blob stored as a byte vector. During `effGetChunk` this will
|
||||||
contain some chunk data that should be written to
|
* contain some chunk data that should be written to
|
||||||
`PluginBridge::chunk_data`.
|
* `PluginBridge::chunk_data`.
|
||||||
* - A specific struct in response to an event such as `audioMasterGetTime` or
|
* - A specific struct in response to an event such as `audioMasterGetTime` or
|
||||||
* `audioMasterIOChanged`.
|
* `audioMasterIOChanged`.
|
||||||
* - An X11 window pointer for the editor window.
|
* - An X11 window pointer for the editor window.
|
||||||
|
|||||||
+4
-1
@@ -80,6 +80,9 @@ struct VstSpeaker {
|
|||||||
* during `eff{Get,Set}SpeakerArrangement`. Reverse engineered from Renoise by
|
* during `eff{Get,Set}SpeakerArrangement`. Reverse engineered from Renoise by
|
||||||
* attaching gdb and dumping both the `value` and `data` pointers when the host
|
* attaching gdb and dumping both the `value` and `data` pointers when the host
|
||||||
* calls opcode 42.
|
* calls opcode 42.
|
||||||
|
*
|
||||||
|
* Use the `DynamicSpeakerArrangement` class to serialize and construct these
|
||||||
|
* objects.
|
||||||
*/
|
*/
|
||||||
struct VstSpeakerArrangement {
|
struct VstSpeakerArrangement {
|
||||||
int flags;
|
int flags;
|
||||||
@@ -88,5 +91,5 @@ struct VstSpeakerArrangement {
|
|||||||
* Variable length array of speakers. Similar to how `VstEvents` works, but
|
* Variable length array of speakers. Similar to how `VstEvents` works, but
|
||||||
* with an array of objects instead of an array of pointers to objects.
|
* with an array of objects instead of an array of pointers to objects.
|
||||||
*/
|
*/
|
||||||
VstSpeaker speakers[8];
|
VstSpeaker speakers[2];
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user