Merge pull request #865 from jpcima/vst-defered
Make VST updates defered
This commit is contained in:
commit
eba974cfe1
6 changed files with 128 additions and 210 deletions
|
|
@ -21,8 +21,7 @@ tresult PLUGIN_API SfizzVstControllerNoUi::initialize(FUnknown* context)
|
||||||
Steinberg::UpdateHandler::instance();
|
Steinberg::UpdateHandler::instance();
|
||||||
|
|
||||||
// create update objects
|
// create update objects
|
||||||
oscUpdate_ = Steinberg::owned(new OSCUpdate);
|
queuedUpdates_ = Steinberg::owned(new QueuedUpdates);
|
||||||
noteUpdate_ = Steinberg::owned(new NoteUpdate);
|
|
||||||
sfzUpdate_ = Steinberg::owned(new SfzUpdate);
|
sfzUpdate_ = Steinberg::owned(new SfzUpdate);
|
||||||
sfzDescriptionUpdate_ = Steinberg::owned(new SfzDescriptionUpdate);
|
sfzDescriptionUpdate_ = Steinberg::owned(new SfzDescriptionUpdate);
|
||||||
scalaUpdate_ = Steinberg::owned(new ScalaUpdate);
|
scalaUpdate_ = Steinberg::owned(new ScalaUpdate);
|
||||||
|
|
@ -289,10 +288,10 @@ tresult SfizzVstControllerNoUi::notify(Vst::IMessage* message)
|
||||||
if (result != kResultTrue)
|
if (result != kResultTrue)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
// this is a synchronous send, because the update object gets reused
|
IPtr<OSCUpdate> update = Steinberg::owned(
|
||||||
oscUpdate_->setMessage(data, size, false);
|
new OSCUpdate(reinterpret_cast<const uint8*>(data), size));
|
||||||
oscUpdate_->changed();
|
queuedUpdates_->enqueue(update);
|
||||||
oscUpdate_->clear();
|
queuedUpdates_->deferUpdate();
|
||||||
}
|
}
|
||||||
else if (!strcmp(id, "NoteEvents")) {
|
else if (!strcmp(id, "NoteEvents")) {
|
||||||
const void* data = nullptr;
|
const void* data = nullptr;
|
||||||
|
|
@ -303,10 +302,10 @@ tresult SfizzVstControllerNoUi::notify(Vst::IMessage* message)
|
||||||
const std::pair<uint32_t, float>*>(data);
|
const std::pair<uint32_t, float>*>(data);
|
||||||
uint32 numEvents = size / sizeof(events[0]);
|
uint32 numEvents = size / sizeof(events[0]);
|
||||||
|
|
||||||
// this is a synchronous send, because the update object gets reused
|
IPtr<NoteUpdate> update = Steinberg::owned(
|
||||||
noteUpdate_->setEvents(events, numEvents, false);
|
new NoteUpdate(events, numEvents));
|
||||||
noteUpdate_->changed();
|
queuedUpdates_->enqueue(update);
|
||||||
noteUpdate_->clear();
|
queuedUpdates_->deferUpdate();
|
||||||
}
|
}
|
||||||
else if (!strcmp(id, "Automate")) {
|
else if (!strcmp(id, "Automate")) {
|
||||||
const void* data = nullptr;
|
const void* data = nullptr;
|
||||||
|
|
@ -343,20 +342,17 @@ IPlugView* PLUGIN_API SfizzVstController::createView(FIDString _name)
|
||||||
if (name != Vst::ViewType::kEditor)
|
if (name != Vst::ViewType::kEditor)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
std::vector<FObject*> continuousUpdates;
|
std::vector<FObject*> updates;
|
||||||
continuousUpdates.push_back(sfzUpdate_);
|
updates.push_back(queuedUpdates_);
|
||||||
continuousUpdates.push_back(sfzDescriptionUpdate_);
|
updates.push_back(sfzUpdate_);
|
||||||
continuousUpdates.push_back(scalaUpdate_);
|
updates.push_back(sfzDescriptionUpdate_);
|
||||||
continuousUpdates.push_back(playStateUpdate_);
|
updates.push_back(scalaUpdate_);
|
||||||
|
updates.push_back(playStateUpdate_);
|
||||||
for (uint32 i = 0, n = parameters.getParameterCount(); i < n; ++i)
|
for (uint32 i = 0, n = parameters.getParameterCount(); i < n; ++i)
|
||||||
continuousUpdates.push_back(parameters.getParameterByIndex(i));
|
updates.push_back(parameters.getParameterByIndex(i));
|
||||||
|
|
||||||
std::vector<FObject*> triggerUpdates;
|
|
||||||
triggerUpdates.push_back(oscUpdate_);
|
|
||||||
triggerUpdates.push_back(noteUpdate_);
|
|
||||||
|
|
||||||
IPtr<SfizzVstEditor> editor = Steinberg::owned(
|
IPtr<SfizzVstEditor> editor = Steinberg::owned(
|
||||||
new SfizzVstEditor(this, absl::MakeSpan(continuousUpdates), absl::MakeSpan(triggerUpdates)));
|
new SfizzVstEditor(this, absl::MakeSpan(updates)));
|
||||||
|
|
||||||
editor->remember();
|
editor->remember();
|
||||||
return editor;
|
return editor;
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,7 @@ public:
|
||||||
REFCOUNT_METHODS(Vst::EditController)
|
REFCOUNT_METHODS(Vst::EditController)
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Steinberg::IPtr<OSCUpdate> oscUpdate_;
|
Steinberg::IPtr<QueuedUpdates> queuedUpdates_;
|
||||||
Steinberg::IPtr<NoteUpdate> noteUpdate_;
|
|
||||||
Steinberg::IPtr<SfzUpdate> sfzUpdate_;
|
Steinberg::IPtr<SfzUpdate> sfzUpdate_;
|
||||||
Steinberg::IPtr<SfzDescriptionUpdate> sfzDescriptionUpdate_;
|
Steinberg::IPtr<SfzDescriptionUpdate> sfzDescriptionUpdate_;
|
||||||
Steinberg::IPtr<ScalaUpdate> scalaUpdate_;
|
Steinberg::IPtr<ScalaUpdate> scalaUpdate_;
|
||||||
|
|
|
||||||
|
|
@ -30,14 +30,10 @@ enum {
|
||||||
kNoteEventQueueSize = 8192,
|
kNoteEventQueueSize = 8192,
|
||||||
};
|
};
|
||||||
|
|
||||||
SfizzVstEditor::SfizzVstEditor(
|
SfizzVstEditor::SfizzVstEditor(SfizzVstController* controller, absl::Span<FObject*> updates)
|
||||||
SfizzVstController* controller,
|
|
||||||
absl::Span<FObject*> continuousUpdates,
|
|
||||||
absl::Span<FObject*> triggerUpdates)
|
|
||||||
: VSTGUIEditor(controller, &sfizzUiViewRect),
|
: VSTGUIEditor(controller, &sfizzUiViewRect),
|
||||||
oscTemp_(new uint8_t[kOscTempSize]),
|
oscTemp_(new uint8_t[kOscTempSize]),
|
||||||
continuousUpdates_(continuousUpdates.begin(), continuousUpdates.end()),
|
updates_(updates.begin(), updates.end())
|
||||||
triggerUpdates_(triggerUpdates.begin(), triggerUpdates.end())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -69,19 +65,6 @@ bool PLUGIN_API SfizzVstEditor::open(void* parent, const VSTGUI::PlatformType& p
|
||||||
editor_.reset(editor);
|
editor_.reset(editor);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(oscQueueMutex_);
|
|
||||||
OscByteVec* queue = new OscByteVec;
|
|
||||||
oscQueue_.reset(queue);
|
|
||||||
queue->reserve(kOscQueueSize);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(noteEventQueueMutex_);
|
|
||||||
NoteEventsVec* queue = new NoteEventsVec;
|
|
||||||
noteEventQueue_.reset(queue);
|
|
||||||
queue->reserve(kNoteEventQueueSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!frame->open(parent, platformType, config)) {
|
if (!frame->open(parent, platformType, config)) {
|
||||||
fprintf(stderr, "[sfizz] error opening frame\n");
|
fprintf(stderr, "[sfizz] error opening frame\n");
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -89,9 +72,7 @@ bool PLUGIN_API SfizzVstEditor::open(void* parent, const VSTGUI::PlatformType& p
|
||||||
|
|
||||||
editor->open(*frame);
|
editor->open(*frame);
|
||||||
|
|
||||||
for (FObject* update : continuousUpdates_)
|
for (FObject* update : updates_)
|
||||||
update->addDependent(this);
|
|
||||||
for (FObject* update : triggerUpdates_)
|
|
||||||
update->addDependent(this);
|
update->addDependent(this);
|
||||||
|
|
||||||
threadChecker_ = Vst::ThreadChecker::create();
|
threadChecker_ = Vst::ThreadChecker::create();
|
||||||
|
|
@ -100,7 +81,7 @@ bool PLUGIN_API SfizzVstEditor::open(void* parent, const VSTGUI::PlatformType& p
|
||||||
|
|
||||||
Steinberg::IdleUpdateHandler::start();
|
Steinberg::IdleUpdateHandler::start();
|
||||||
|
|
||||||
for (FObject* update : continuousUpdates_)
|
for (FObject* update : updates_)
|
||||||
update->deferUpdate();
|
update->deferUpdate();
|
||||||
|
|
||||||
// let the editor know about plugin format
|
// let the editor know about plugin format
|
||||||
|
|
@ -138,9 +119,7 @@ void PLUGIN_API SfizzVstEditor::close()
|
||||||
if (frame) {
|
if (frame) {
|
||||||
Steinberg::IdleUpdateHandler::stop();
|
Steinberg::IdleUpdateHandler::stop();
|
||||||
|
|
||||||
for (FObject* update : continuousUpdates_)
|
for (FObject* update : updates_)
|
||||||
update->removeDependent(this);
|
|
||||||
for (FObject* update : triggerUpdates_)
|
|
||||||
update->removeDependent(this);
|
update->removeDependent(this);
|
||||||
|
|
||||||
if (editor_)
|
if (editor_)
|
||||||
|
|
@ -152,15 +131,6 @@ void PLUGIN_API SfizzVstEditor::close()
|
||||||
this->frame = nullptr;
|
this->frame = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(oscQueueMutex_);
|
|
||||||
oscQueue_.reset();
|
|
||||||
}
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(noteEventQueueMutex_);
|
|
||||||
noteEventQueue_.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
updateEditorIsOpenParameter();
|
updateEditorIsOpenParameter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -195,8 +165,6 @@ CMessageResult SfizzVstEditor::notify(CBaseObject* sender, const char* message)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (message == CVSTGUITimer::kMsgTimer) {
|
if (message == CVSTGUITimer::kMsgTimer) {
|
||||||
processOscQueue();
|
|
||||||
processNoteEventQueue();
|
|
||||||
processParameterUpdates();
|
processParameterUpdates();
|
||||||
updateEditorIsOpenParameter(); // Note(jpc) for Reaper, it can fail at open time
|
updateEditorIsOpenParameter(); // Note(jpc) for Reaper, it can fail at open time
|
||||||
}
|
}
|
||||||
|
|
@ -206,34 +174,51 @@ CMessageResult SfizzVstEditor::notify(CBaseObject* sender, const char* message)
|
||||||
|
|
||||||
void PLUGIN_API SfizzVstEditor::update(FUnknown* changedUnknown, int32 message)
|
void PLUGIN_API SfizzVstEditor::update(FUnknown* changedUnknown, int32 message)
|
||||||
{
|
{
|
||||||
if (OSCUpdate* update = FCast<OSCUpdate>(changedUnknown)) {
|
if (processUpdate(changedUnknown, message))
|
||||||
// this update is synchronous: may happen from non-UI thread
|
|
||||||
uint32 size = update->size();
|
|
||||||
if (size > 0) {
|
|
||||||
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(update->data());
|
|
||||||
std::lock_guard<std::mutex> lock(oscQueueMutex_);
|
|
||||||
if (OscByteVec* queue = oscQueue_.get())
|
|
||||||
std::copy(bytes, bytes + size, std::back_inserter(*queue));
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Vst::VSTGUIEditor::update(changedUnknown, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SfizzVstEditor::processUpdate(FUnknown* changedUnknown, int32 message)
|
||||||
|
{
|
||||||
|
if (QueuedUpdates* update = FCast<QueuedUpdates>(changedUnknown)) {
|
||||||
|
for (FObject* queuedUpdate : update->getUpdates(this))
|
||||||
|
processUpdate(queuedUpdate, message);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OSCUpdate* update = FCast<OSCUpdate>(changedUnknown)) {
|
||||||
|
const uint8* oscData = update->data();
|
||||||
|
uint32 oscSize = update->size();
|
||||||
|
|
||||||
|
const char* path;
|
||||||
|
const char* sig;
|
||||||
|
const sfizz_arg_t* args;
|
||||||
|
uint8_t buffer[1024];
|
||||||
|
|
||||||
|
uint32_t msgSize;
|
||||||
|
while ((msgSize = sfizz_extract_message(oscData, oscSize, buffer, sizeof(buffer), &path, &sig, &args)) > 0) {
|
||||||
|
uiReceiveMessage(path, sig, args);
|
||||||
|
oscData += msgSize;
|
||||||
|
oscSize -= msgSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NoteUpdate* update = FCast<NoteUpdate>(changedUnknown)) {
|
if (NoteUpdate* update = FCast<NoteUpdate>(changedUnknown)) {
|
||||||
// this update is synchronous: may happen from non-UI thread
|
const NoteUpdate::Item* events = update->events();
|
||||||
uint32 count = update->count();
|
uint32 count = update->count();
|
||||||
if (count > 0) {
|
for (uint32 i = 0; i < count; ++i)
|
||||||
const auto* events = update->events();
|
uiReceiveValue(editIdForKey(events[i].first), events[i].second);
|
||||||
std::lock_guard<std::mutex> lock(noteEventQueueMutex_);
|
return true;
|
||||||
if (NoteEventsVec* queue = noteEventQueue_.get())
|
|
||||||
std::copy(events, events + count, std::back_inserter(*queue));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SfzUpdate* update = FCast<SfzUpdate>(changedUnknown)) {
|
if (SfzUpdate* update = FCast<SfzUpdate>(changedUnknown)) {
|
||||||
const std::string path = update->getPath();
|
const std::string path = update->getPath();
|
||||||
uiReceiveValue(EditId::SfzFile, path);
|
uiReceiveValue(EditId::SfzFile, path);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SfzDescriptionUpdate* update = FCast<SfzDescriptionUpdate>(changedUnknown)) {
|
if (SfzDescriptionUpdate* update = FCast<SfzDescriptionUpdate>(changedUnknown)) {
|
||||||
|
|
@ -268,19 +253,19 @@ void PLUGIN_API SfizzVstEditor::update(FUnknown* changedUnknown, int32 message)
|
||||||
uiReceiveValue(editIdForCCLabel(int(cc)), desc.ccLabel[cc]);
|
uiReceiveValue(editIdForCCLabel(int(cc)), desc.ccLabel[cc]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ScalaUpdate* update = FCast<ScalaUpdate>(changedUnknown)) {
|
if (ScalaUpdate* update = FCast<ScalaUpdate>(changedUnknown)) {
|
||||||
const std::string path = update->getPath();
|
const std::string path = update->getPath();
|
||||||
uiReceiveValue(EditId::ScalaFile, path);
|
uiReceiveValue(EditId::ScalaFile, path);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PlayStateUpdate* update = FCast<PlayStateUpdate>(changedUnknown)) {
|
if (PlayStateUpdate* update = FCast<PlayStateUpdate>(changedUnknown)) {
|
||||||
const SfizzPlayState playState = update->getState();
|
const SfizzPlayState playState = update->getState();
|
||||||
uiReceiveValue(EditId::UINumActiveVoices, playState.activeVoices);
|
uiReceiveValue(EditId::UINumActiveVoices, playState.activeVoices);
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Vst::RangeParameter* param = Steinberg::FCast<Vst::RangeParameter>(changedUnknown)) {
|
if (Vst::RangeParameter* param = Steinberg::FCast<Vst::RangeParameter>(changedUnknown)) {
|
||||||
|
|
@ -297,50 +282,10 @@ void PLUGIN_API SfizzVstEditor::update(FUnknown* changedUnknown, int32 message)
|
||||||
std::lock_guard<std::mutex> lock(parametersToUpdateMutex_);
|
std::lock_guard<std::mutex> lock(parametersToUpdateMutex_);
|
||||||
parametersToUpdate_.insert(id);
|
parametersToUpdate_.insert(id);
|
||||||
}
|
}
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vst::VSTGUIEditor::update(changedUnknown, message);
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
void SfizzVstEditor::processOscQueue()
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(oscQueueMutex_);
|
|
||||||
|
|
||||||
OscByteVec* queue = oscQueue_.get();
|
|
||||||
if (!queue)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const uint8_t* oscData = queue->data();
|
|
||||||
size_t oscSize = queue->size();
|
|
||||||
|
|
||||||
const char* path;
|
|
||||||
const char* sig;
|
|
||||||
const sfizz_arg_t* args;
|
|
||||||
uint8_t buffer[1024];
|
|
||||||
|
|
||||||
uint32_t msgSize;
|
|
||||||
while ((msgSize = sfizz_extract_message(oscData, oscSize, buffer, sizeof(buffer), &path, &sig, &args)) > 0) {
|
|
||||||
uiReceiveMessage(path, sig, args);
|
|
||||||
oscData += msgSize;
|
|
||||||
oscSize -= msgSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
queue->clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SfizzVstEditor::processNoteEventQueue()
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(noteEventQueueMutex_);
|
|
||||||
|
|
||||||
NoteEventsVec* queue = noteEventQueue_.get();
|
|
||||||
if (!queue)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (std::pair<uint32, float> event : *queue)
|
|
||||||
uiReceiveValue(editIdForKey(event.first), event.second);
|
|
||||||
|
|
||||||
queue->clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SfizzVstEditor::processParameterUpdates()
|
void SfizzVstEditor::processParameterUpdates()
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,7 @@ class SfizzVstEditor : public Vst::VSTGUIEditor,
|
||||||
public:
|
public:
|
||||||
using Self = SfizzVstEditor;
|
using Self = SfizzVstEditor;
|
||||||
|
|
||||||
SfizzVstEditor(
|
SfizzVstEditor(SfizzVstController* controller, absl::Span<FObject*> updates);
|
||||||
SfizzVstController* controller,
|
|
||||||
absl::Span<FObject*> continuousUpdates,
|
|
||||||
absl::Span<FObject*> triggerUpdates);
|
|
||||||
~SfizzVstEditor();
|
~SfizzVstEditor();
|
||||||
|
|
||||||
bool PLUGIN_API open(void* parent, const VSTGUI::PlatformType& platformType) override;
|
bool PLUGIN_API open(void* parent, const VSTGUI::PlatformType& platformType) override;
|
||||||
|
|
@ -48,8 +45,7 @@ public:
|
||||||
|
|
||||||
//
|
//
|
||||||
private:
|
private:
|
||||||
void processOscQueue();
|
bool processUpdate(FUnknown* changedUnknown, int32 message);
|
||||||
void processNoteEventQueue();
|
|
||||||
void processParameterUpdates();
|
void processParameterUpdates();
|
||||||
void updateParameter(Vst::Parameter* parameterToUpdate);
|
void updateParameter(Vst::Parameter* parameterToUpdate);
|
||||||
|
|
||||||
|
|
@ -76,18 +72,8 @@ private:
|
||||||
// messaging
|
// messaging
|
||||||
std::unique_ptr<uint8[]> oscTemp_;
|
std::unique_ptr<uint8[]> oscTemp_;
|
||||||
|
|
||||||
// editor state
|
|
||||||
// note: might be updated from a non-UI thread
|
|
||||||
typedef std::vector<uint8_t> OscByteVec;
|
|
||||||
std::unique_ptr<OscByteVec> oscQueue_;
|
|
||||||
std::mutex oscQueueMutex_;
|
|
||||||
typedef std::vector<std::pair<uint32, float>> NoteEventsVec;
|
|
||||||
std::unique_ptr<NoteEventsVec> noteEventQueue_;
|
|
||||||
std::mutex noteEventQueueMutex_;
|
|
||||||
|
|
||||||
// subscribed updates
|
// subscribed updates
|
||||||
std::vector<IPtr<FObject>> continuousUpdates_;
|
std::vector<IPtr<FObject>> updates_;
|
||||||
std::vector<IPtr<FObject>> triggerUpdates_;
|
|
||||||
|
|
||||||
// thread safety
|
// thread safety
|
||||||
std::unique_ptr<Vst::ThreadChecker> threadChecker_;
|
std::unique_ptr<Vst::ThreadChecker> threadChecker_;
|
||||||
|
|
|
||||||
|
|
@ -8,61 +8,51 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
OSCUpdate::~OSCUpdate()
|
void QueuedUpdates::enqueue(IPtr<FObject> update)
|
||||||
{
|
{
|
||||||
clear();
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
for (std::pair<IDependent* const, List>& item : updates_)
|
||||||
|
item.second.push_back(update);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSCUpdate::clear()
|
auto QueuedUpdates::getUpdates(IDependent* dep) -> List
|
||||||
{
|
{
|
||||||
if (allocated_)
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
delete[] reinterpret_cast<const uint8_t*>(data_);
|
List list;
|
||||||
data_ = nullptr;
|
auto it = updates_.find(dep);
|
||||||
size_ = 0;
|
if (it != updates_.end())
|
||||||
allocated_ = false;
|
std::swap(list, it->second);
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OSCUpdate::setMessage(const void* data, uint32_t size, bool copy)
|
void QueuedUpdates::addDependent(IDependent* dep)
|
||||||
{
|
{
|
||||||
clear();
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
FObject::addDependent(dep);
|
||||||
|
updates_.emplace(dep, List());
|
||||||
|
}
|
||||||
|
|
||||||
if (copy) {
|
void QueuedUpdates::removeDependent(IDependent* dep)
|
||||||
uint8_t *buffer = new uint8_t[size];
|
{
|
||||||
std::memcpy(buffer, data, size);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
data = buffer;
|
FObject::removeDependent(dep);
|
||||||
}
|
updates_.erase(dep);
|
||||||
|
|
||||||
data_ = data;
|
|
||||||
size_ = size;
|
|
||||||
allocated_ = copy;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
NoteUpdate::~NoteUpdate()
|
OSCUpdate::OSCUpdate(const uint8* data, uint32 size)
|
||||||
{
|
{
|
||||||
clear();
|
uint8* copy = new uint8[size];
|
||||||
|
std::copy_n(data, size, copy);
|
||||||
|
data_.reset(copy);
|
||||||
|
size_ = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NoteUpdate::clear()
|
///
|
||||||
|
NoteUpdate::NoteUpdate(const Item* items, uint32 count)
|
||||||
{
|
{
|
||||||
if (allocated_)
|
Item* copy = new Item[count];
|
||||||
delete[] events_;
|
std::copy_n(items, count, copy);
|
||||||
events_ = nullptr;
|
events_.reset(copy);
|
||||||
count_ = 0;
|
|
||||||
allocated_ = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NoteUpdate::setEvents(const std::pair<uint32_t, float>* events, uint32_t count, bool copy)
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
|
|
||||||
if (copy) {
|
|
||||||
auto *buffer = new std::pair<uint32_t, float>[count];
|
|
||||||
std::copy_n(events, count, buffer);
|
|
||||||
events = buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
events_ = events;
|
|
||||||
count_ = count;
|
count_ = count;
|
||||||
allocated_ = copy;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,62 +8,64 @@
|
||||||
#include "SfizzVstState.h"
|
#include "SfizzVstState.h"
|
||||||
#include <base/source/fobject.h>
|
#include <base/source/fobject.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Update which notifies a FIFO queue of one-time updates
|
||||||
|
*/
|
||||||
|
class QueuedUpdates : public Steinberg::FObject {
|
||||||
|
public:
|
||||||
|
using List = std::vector<IPtr<FObject>>;
|
||||||
|
|
||||||
|
void enqueue(IPtr<FObject> update);
|
||||||
|
List getUpdates(IDependent* dep);
|
||||||
|
|
||||||
|
void addDependent(IDependent* dep) override;
|
||||||
|
void removeDependent(IDependent* dep) override;
|
||||||
|
|
||||||
|
OBJ_METHODS(QueuedUpdates, FObject)
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::mutex mutex_;
|
||||||
|
std::map<IDependent*, List> updates_;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Update which notifies a single OSC message
|
* @brief Update which notifies a single OSC message
|
||||||
* Is is supposed to be used synchronously.
|
|
||||||
* (ie. FObject::changed or UpdateHandler::triggerUpdates)
|
|
||||||
*/
|
*/
|
||||||
class OSCUpdate : public Steinberg::FObject {
|
class OSCUpdate : public Steinberg::FObject {
|
||||||
public:
|
public:
|
||||||
OSCUpdate() = default;
|
OSCUpdate(const uint8* data, uint32 size);
|
||||||
~OSCUpdate();
|
const uint8* data() const noexcept { return data_.get(); }
|
||||||
void clear();
|
uint32_t size() const noexcept { return size_; }
|
||||||
void setMessage(const void* data, uint32_t size, bool copy);
|
|
||||||
|
|
||||||
const void* data() const noexcept { return data_; }
|
|
||||||
const uint32_t size() const noexcept { return size_; }
|
|
||||||
|
|
||||||
OBJ_METHODS(OSCUpdate, FObject)
|
OBJ_METHODS(OSCUpdate, FObject)
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const void* data_ = nullptr;
|
std::unique_ptr<uint8[]> data_;
|
||||||
uint32_t size_ = 0;
|
uint32 size_ = 0;
|
||||||
bool allocated_ = false;
|
|
||||||
|
|
||||||
private:
|
|
||||||
OSCUpdate(const OSCUpdate&) = delete;
|
|
||||||
OSCUpdate& operator=(const OSCUpdate&) = delete;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Update which notifies one or more note on/off events
|
* @brief Update which notifies one or more note on/off events
|
||||||
* Is is supposed to be used synchronously.
|
|
||||||
* (ie. FObject::changed or UpdateHandler::triggerUpdates)
|
|
||||||
*/
|
*/
|
||||||
class NoteUpdate : public Steinberg::FObject {
|
class NoteUpdate : public Steinberg::FObject {
|
||||||
public:
|
public:
|
||||||
NoteUpdate() = default;
|
using Item = std::pair<uint32_t, float>;
|
||||||
~NoteUpdate();
|
|
||||||
void clear();
|
|
||||||
void setEvents(const std::pair<uint32_t, float>* events, uint32_t count, bool copy);
|
|
||||||
|
|
||||||
const std::pair<uint32_t, float>* events() const noexcept { return events_; }
|
NoteUpdate(const Item* items, uint32 count);
|
||||||
|
const Item* events() const noexcept { return events_.get(); }
|
||||||
const uint32_t count() const noexcept { return count_; }
|
const uint32_t count() const noexcept { return count_; }
|
||||||
|
|
||||||
OBJ_METHODS(NoteUpdate, FObject)
|
OBJ_METHODS(NoteUpdate, FObject)
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::pair<uint32_t, float>* events_ = nullptr;
|
std::unique_ptr<Item[]> events_;
|
||||||
uint32_t count_ = 0;
|
uint32_t count_ = 0;
|
||||||
bool allocated_ = false;
|
|
||||||
|
|
||||||
private:
|
|
||||||
NoteUpdate(const NoteUpdate&) = delete;
|
|
||||||
NoteUpdate& operator=(const NoteUpdate&) = delete;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue