mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-06 19:40:10 +02:00
Allow for an arbitrary number of midi events
By building the object on the heap in a buffer. I preferred the old solution but this is more flexible.
This commit is contained in:
@@ -14,9 +14,6 @@ There are a few things that should be done before releasing this, including:
|
||||
- Fix implementation bugs:
|
||||
- KiloHearts plugins fail during initialization.
|
||||
- Serum crashes when closing bitwig (but otherwise exits just fine).
|
||||
- Serum crashes if you keep playing midi notes while the GUI is blocked.
|
||||
Related to the above, and probably because of the current limit of 512 midi
|
||||
events.
|
||||
- Melda plugins crash when opening their GUI.
|
||||
- Add missing details if any to the architecture section.
|
||||
- Document what this has been tested on and what does or does not work.
|
||||
|
||||
@@ -25,13 +25,25 @@ DynamicVstEvents::DynamicVstEvents(const VstEvents& c_events)
|
||||
}
|
||||
|
||||
VstEvents& DynamicVstEvents::as_c_events() {
|
||||
vst_events.numEvents = events.size();
|
||||
// As explained in `vst_events_buffer`'s docstring we have to build the
|
||||
// `VstEvents` struct by hand on the heap since it's actually a dynamically
|
||||
// sized object
|
||||
|
||||
// Populate the vst_events struct with data from the vector. This will
|
||||
// overflow past the defined length of `vst_events.events` because it's
|
||||
// actually a VLA. This is why I put some padding at the end of this struct.
|
||||
std::transform(events.begin(), events.end(), &vst_events.events[0],
|
||||
// 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
|
||||
// over the socket.
|
||||
static_assert(std::extent<decltype(VstEvents::events)>::value == 1);
|
||||
const size_t buffer_size =
|
||||
sizeof(VstEvents) + (events.size() - 1) * sizeof(VstEvent*);
|
||||
vst_events_buffer.resize(buffer_size);
|
||||
|
||||
// Now we can populate the VLA with pointers to the objects in the `events`
|
||||
// vector
|
||||
VstEvents* vst_events =
|
||||
reinterpret_cast<VstEvents*>(vst_events_buffer.data());
|
||||
vst_events->numEvents = events.size();
|
||||
std::transform(events.begin(), events.end(), vst_events->events,
|
||||
[](VstEvent& event) -> VstEvent* { return &event; });
|
||||
|
||||
return vst_events;
|
||||
return *vst_events;
|
||||
}
|
||||
|
||||
+13
-15
@@ -42,7 +42,7 @@ constexpr size_t max_buffer_size = 16384;
|
||||
/**
|
||||
* The maximum number of midi events in a single `VstEvents` struct.
|
||||
*/
|
||||
constexpr size_t max_midi_events = 256;
|
||||
constexpr size_t max_midi_events = max_buffer_size / sizeof(size_t);
|
||||
/**
|
||||
* The maximum size in bytes of a string or buffer passed through a void pointer
|
||||
* in one of the dispatch functions. This is used to create buffers for plugins
|
||||
@@ -122,7 +122,7 @@ void serialize(S& s, VstTimeInfo& time_info) {
|
||||
*
|
||||
* 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 usign the `as_c_events()` method.
|
||||
* can be reconstructed using the `as_c_events()` method.
|
||||
*/
|
||||
class alignas(16) DynamicVstEvents {
|
||||
public:
|
||||
@@ -144,20 +144,18 @@ class alignas(16) DynamicVstEvents {
|
||||
|
||||
private:
|
||||
/**
|
||||
* A `VstEvents` struct based on the `events` vector. Use the
|
||||
* `as_c_events()` method to populate and return this after the `events`
|
||||
* vector has been filled.
|
||||
* Some buffer we can build a `VstEvents`. This object can be 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
|
||||
* actually a variable size object. In the definition in
|
||||
* `vestige/aeffectx.h` the struct contains a single element `VstEvent`
|
||||
* pointer array, but the actual length of this array is
|
||||
* `VstEvents::numEvents`. Because there is no real limit on the number of
|
||||
* midi events the host can send at once we have to build this object on the
|
||||
* heap by hand.
|
||||
*/
|
||||
VstEvents vst_events;
|
||||
/**
|
||||
* The `VstEvents` struct is defined to look like it contains a one or two
|
||||
* element array of `VstEvent` pointers. The actual truth is that the
|
||||
* `VstEvents::event` array is actually a variable length array with length
|
||||
* `VstEvents::numEvents`. This is probably not part of any header files
|
||||
* because VLAs are not part of any C++ standard. This struct is here to
|
||||
* make sure there is enough room to copy the elements into.
|
||||
*/
|
||||
size_t dummy[max_midi_events];
|
||||
std::vector<uint8_t> vst_events_buffer;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user