diff --git a/source/backend/plugin/carla_plugin.cpp b/source/backend/plugin/carla_plugin.cpp index ddeb1bf0d..587b970b7 100644 --- a/source/backend/plugin/carla_plugin.cpp +++ b/source/backend/plugin/carla_plugin.cpp @@ -50,6 +50,7 @@ CarlaPlugin::CarlaPlugin(CarlaEngine* const engine, const unsigned int id) case PROCESS_MODE_MULTIPLE_CLIENTS: fData->ctrlInChannel = 0; break; + case PROCESS_MODE_CONTINUOUS_RACK: CARLA_ASSERT(id < MAX_RACK_PLUGINS && id < MAX_MIDI_CHANNELS); @@ -57,6 +58,10 @@ CarlaPlugin::CarlaPlugin(CarlaEngine* const engine, const unsigned int id) fData->ctrlInChannel = id; break; + + case PROCESS_MODE_PATCHBAY: + case PROCESS_MODE_BRIDGE: + break; } } @@ -1199,7 +1204,7 @@ void CarlaPlugin::postponeRtEvent(const PluginPostRtEventType type, const int32_ void CarlaPlugin::postRtEventsRun() { - unsigned short i = 0; + unsigned short k = 0; PluginPostRtEvent listData[MAX_RT_EVENTS]; // Make a safe copy of events while clearing them @@ -1209,53 +1214,53 @@ void CarlaPlugin::postRtEventsRun() { PluginPostRtEvent& event = fData->postRtEvents.data.getFirst(true); //listData[i++] = event; - std::memcpy(&listData[i++], &event, sizeof(PluginPostRtEvent)); + std::memcpy(&listData[k++], &event, sizeof(PluginPostRtEvent)); } fData->postRtEvents.mutex.unlock(); // Handle events now - for (i=0; i < MAX_RT_EVENTS; i++) + for (unsigned short i=0; i < k; i++) { - const PluginPostRtEvent* const event = &listData[i]; + const PluginPostRtEvent& event = listData[i]; - if (event->type != kPluginPostRtEventNull) - qWarning("postRtEventsRun() - event type %i", i); + if (event.type != kPluginPostRtEventNull) + qWarning("postRtEventsRun() - @ %i", i); - switch (event->type) + switch (event.type) { case kPluginPostRtEventNull: break; case kPluginPostRtEventDebug: - fData->engine->callback(CALLBACK_DEBUG, fData->id, event->value1, event->value2, event->value3, nullptr); + fData->engine->callback(CALLBACK_DEBUG, fData->id, event.value1, event.value2, event.value3, nullptr); break; case kPluginPostRtEventParameterChange: // Update UI - if (event->value1 >= 0) - uiParameterChange(event->value1, event->value3); + if (event.value1 >= 0) + uiParameterChange(event.value1, event.value3); #ifndef BUILD_BRIDGE // Update OSC control client if (fData->engine->isOscControlRegistered()) - fData->engine->osc_send_control_set_parameter_value(fData->id, event->value1, event->value3); + fData->engine->osc_send_control_set_parameter_value(fData->id, event.value1, event.value3); #endif // Update Host - fData->engine->callback(CALLBACK_PARAMETER_VALUE_CHANGED, fData->id, event->value1, 0, event->value3, nullptr); + fData->engine->callback(CALLBACK_PARAMETER_VALUE_CHANGED, fData->id, event.value1, 0, event.value3, nullptr); break; case kPluginPostRtEventProgramChange: // Update UI - if (event->value1 >= 0) - uiProgramChange(event->value1); + if (event.value1 >= 0) + uiProgramChange(event.value1); #ifndef BUILD_BRIDGE // Update OSC control client if (fData->engine->isOscControlRegistered()) { - fData->engine->osc_send_control_set_program(fData->id, event->value1); + fData->engine->osc_send_control_set_program(fData->id, event.value1); for (uint32_t j=0; j < fData->param.count; j++) fData->engine->osc_send_control_set_default_value(fData->id, j, fData->param.ranges[j].def); @@ -1263,19 +1268,19 @@ void CarlaPlugin::postRtEventsRun() #endif // Update Host - fData->engine->callback(CALLBACK_PROGRAM_CHANGED, fData->id, event->value1, 0, 0.0, nullptr); + fData->engine->callback(CALLBACK_PROGRAM_CHANGED, fData->id, event.value1, 0, 0.0, nullptr); break; case kPluginPostRtEventMidiProgramChange: // Update UI - if (event->value1 >= 0) - uiMidiProgramChange(event->value1); + if (event.value1 >= 0) + uiMidiProgramChange(event.value1); #ifndef BUILD_BRIDGE // Update OSC control client if (fData->engine->isOscControlRegistered()) { - fData->engine->osc_send_control_set_midi_program(fData->id, event->value1); + fData->engine->osc_send_control_set_midi_program(fData->id, event.value1); for (uint32_t j=0; j < fData->param.count; j++) fData->engine->osc_send_control_set_default_value(fData->id, j, fData->param.ranges[j].def); @@ -1283,35 +1288,35 @@ void CarlaPlugin::postRtEventsRun() #endif // Update Host - fData->engine->callback(CALLBACK_MIDI_PROGRAM_CHANGED, fData->id, event->value1, 0, 0.0, nullptr); + fData->engine->callback(CALLBACK_MIDI_PROGRAM_CHANGED, fData->id, event.value1, 0, 0.0, nullptr); break; case kPluginPostRtEventNoteOn: // Update UI - uiNoteOn(event->value1, event->value2, int(event->value3)); + uiNoteOn(event.value1, event.value2, int(event.value3)); #ifndef BUILD_BRIDGE // Update OSC control client if (fData->engine->isOscControlRegistered()) - fData->engine->osc_send_control_note_on(fData->id, event->value1, event->value2, int(event->value3)); + fData->engine->osc_send_control_note_on(fData->id, event.value1, event.value2, int(event.value3)); #endif // Update Host - fData->engine->callback(CALLBACK_NOTE_ON, fData->id, event->value1, event->value2, int(event->value3), nullptr); + fData->engine->callback(CALLBACK_NOTE_ON, fData->id, event.value1, event.value2, int(event.value3), nullptr); break; case kPluginPostRtEventNoteOff: // Update UI - uiNoteOff(event->value1, event->value2); + uiNoteOff(event.value1, event.value2); #ifndef BUILD_BRIDGE // Update OSC control client if (fData->engine->isOscControlRegistered()) - fData->engine->osc_send_control_note_off(fData->id, event->value1, event->value2); + fData->engine->osc_send_control_note_off(fData->id, event.value1, event.value2); #endif // Update Host - fData->engine->callback(CALLBACK_NOTE_OFF, fData->id, event->value1, event->value2, 0.0, nullptr); + fData->engine->callback(CALLBACK_NOTE_OFF, fData->id, event.value1, event.value2, 0.0, nullptr); break; } } diff --git a/source/backend/plugin/carla_plugin_internal.hpp b/source/backend/plugin/carla_plugin_internal.hpp index cfa1f94c3..299df61c9 100644 --- a/source/backend/plugin/carla_plugin_internal.hpp +++ b/source/backend/plugin/carla_plugin_internal.hpp @@ -434,10 +434,18 @@ struct CarlaPluginProtectedData { : data(MIN_RT_EVENTS, MAX_RT_EVENTS), dataPendingRT(MIN_RT_EVENTS, MAX_RT_EVENTS) {} + ~PostRtEvents() + { + clear(); + } + void appendRT(const PluginPostRtEvent& event) { dataPendingRT.append(event); + } + void trySplice() + { if (mutex.tryLock()) { dataPendingRT.splice(data, true); @@ -445,6 +453,14 @@ struct CarlaPluginProtectedData { } } + void clear() + { + mutex.lock(); + data.clear(); + dataPendingRT.clear(); + mutex.unlock(); + } + //void appendNonRT(const PluginPostRtEvent& event) //{ // data.append_sleepy(event); diff --git a/source/backend/plugin/ladspa.cpp b/source/backend/plugin/ladspa.cpp index 709a8ba47..bc31eae2c 100644 --- a/source/backend/plugin/ladspa.cpp +++ b/source/backend/plugin/ladspa.cpp @@ -921,6 +921,8 @@ public: } } + fData->postRtEvents.trySplice(); + } // End of Parameters Input CARLA_PROCESS_CONTINUE_CHECK; diff --git a/source/carla_shared.py b/source/carla_shared.py index ecc889f4c..e4d11a78d 100644 --- a/source/carla_shared.py +++ b/source/carla_shared.py @@ -1820,15 +1820,26 @@ class PluginEdit(QDialog): # Check parameters needing update for index, value in self.fParametersToUpdate: if index == PARAMETER_DRYWET: - self.ui.dial_drywet.setValue(value * 1000, True, False) + self.ui.dial_drywet.blockSignals(True) + self.ui.dial_drywet.setValue(value * 1000) + self.ui.dial_drywet.blockSignals(False) elif index == PARAMETER_VOLUME: - self.ui.dial_vol.setValue(value * 1000, True, False) + self.ui.dial_vol.blockSignals(True) + self.ui.dial_vol.setValue(value * 1000) + self.ui.dial_vol.blockSignals(False) elif index == PARAMETER_BALANCE_LEFT: - self.ui.dial_b_left.setValue(value * 1000, True, False) + self.ui.dial_b_left.blockSignals(True) + self.ui.dial_b_left.setValue(value * 1000) + self.ui.dial_b_left.blockSignals(False) elif index == PARAMETER_BALANCE_RIGHT: - self.ui.dial_b_right.setValue(value * 1000, True, False) + self.ui.dial_b_right.blockSignals(True) + self.ui.dial_b_right.setValue(value * 1000) + self.ui.dial_b_right.blockSignals(False) elif index == PARAMETER_PANNING: - pass #self.ui.dial_pan.setValue(value * 1000, True, False) + pass + #self.ui.dial_pan.blockSignals(True) + #self.ui.dial_pan.setValue(value * 1000, True, False) + #self.ui.dial_pan.blockSignals(False) elif index >= 0: for paramType, paramId, paramWidget in self.fParameterList: if paramId == index: diff --git a/source/utils/rt_list.hpp b/source/utils/rt_list.hpp index 04d386d68..0d0440adb 100644 --- a/source/utils/rt_list.hpp +++ b/source/utils/rt_list.hpp @@ -1,5 +1,5 @@ /* - * High-level, real-time safe, templated C++ doubly linked list + * High-level, real-time safe, templated C++ doubly-linked list * Copyright (C) 2013 Filipe Coelho * * This program is free software; you can redistribute it and/or @@ -23,8 +23,7 @@ extern "C" { #include "rtmempool/rtmempool.h" } -#include -#include +#include "carla_utils.hpp" // list_entry C++11 version (using nullptr instead of 0) #undef list_entry @@ -47,7 +46,8 @@ class List { protected: List() - : fDataSize(sizeof(Data)) + : kDataSize(sizeof(Data)), + fCount(0) { _init(); } @@ -55,20 +55,19 @@ protected: public: virtual ~List() { - clear(); + CARLA_ASSERT(fCount == 0); } void clear() { if (fCount != 0) { - Data* data; k_list_head* entry; list_for_each(entry, &fQueue) { - data = list_entry(entry, Data, siblings); - _deallocate(data); + if (Data* data = list_entry(entry, Data, siblings)) + _deallocate(data); } } @@ -98,14 +97,27 @@ public: return false; } + bool insert(const T& value) + { + if (Data* const data = _allocate()) + { + std::memcpy(&data->value, &value, sizeof(T)); + list_add(&data->siblings, &fQueue); + fCount++; + return true; + } + + return false; + } + T& getAt(const size_t index, const bool remove = false) { if (fCount == 0 || index >= fCount) return _retEmpty(); + size_t i = 0; Data* data = nullptr; k_list_head* entry; - size_t i = 0; list_for_each(entry, &fQueue) { @@ -113,20 +125,22 @@ public: continue; data = list_entry(entry, Data, siblings); - assert(data); if (remove) { fCount--; list_del(entry); - _deallocate(data); + + if (data != nullptr) + _deallocate(data); } break; } - assert(data); - return data->value; + CARLA_ASSERT(data != nullptr); + + return (data != nullptr) ? data->value : _retEmpty(); } T& getFirst(const bool remove = false) @@ -147,9 +161,10 @@ public: list_for_each(entry, &fQueue) { data = list_entry(entry, Data, siblings); - assert(data); - if (data->value == value) + CARLA_ASSERT(data != nullptr); + + if (data != nullptr && data->value == value) { fCount--; list_del(entry); @@ -170,9 +185,10 @@ public: list_for_each_safe(entry, tmp, &fQueue) { data = list_entry(entry, Data, siblings); - assert(data); - if (data->value == value) + CARLA_ASSERT(data != nullptr); + + if (data != nullptr && data->value == value) { fCount--; list_del(entry); @@ -184,13 +200,20 @@ public: void splice(List& list, const bool init = false) { if (init) + { list_splice_init(&fQueue, &list.fQueue); + list.fCount += fCount; + fCount = 0; + } else + { list_splice(&fQueue, &list.fQueue); + list.fCount += fCount; + } } protected: - const size_t fDataSize; + const size_t kDataSize; size_t fCount; k_list_head fQueue; @@ -214,15 +237,17 @@ private: if (fCount == 0) return _retEmpty(); - k_list_head* const entry = first ? fQueue.next : fQueue.prev; + k_list_head* const entry = first ? fQueue.prev : fQueue.next; Data* const data = list_entry(entry, Data, siblings); + CARLA_ASSERT(data != nullptr); + if (data == nullptr) return _retEmpty(); T& ret = data->value; - if (data && remove) + if (data != nullptr && remove) { fCount--; list_del(entry); @@ -247,7 +272,7 @@ private: return value; } - //LIST_DECLARATIONS(List) + LIST_DECLARATIONS(List) }; template @@ -255,9 +280,10 @@ class RtList : public List { public: RtList(const size_t minPreallocated, const size_t maxPreallocated) + : fMemPool(nullptr) { - rtsafe_memory_pool_create(&fMemPool, nullptr, this->fDataSize, minPreallocated, maxPreallocated); - assert(fMemPool); + rtsafe_memory_pool_create(&fMemPool, nullptr, this->kDataSize, minPreallocated, maxPreallocated); + CARLA_ASSERT(fMemPool != nullptr); } ~RtList() @@ -280,9 +306,12 @@ public: { this->clear(); - rtsafe_memory_pool_destroy(fMemPool); + if (fMemPool != nullptr) + rtsafe_memory_pool_destroy(fMemPool); + + fMemPool = nullptr; rtsafe_memory_pool_create(&fMemPool, nullptr, this->fDataSize, minPreallocated, maxPreallocated); - assert(fMemPool); + CARLA_ASSERT(fMemPool != nullptr); } private: @@ -303,7 +332,7 @@ private: return (typename List::Data*)rtsafe_memory_pool_allocate_sleepy(fMemPool); } - void _deallocate(typename List::Data* const dataPtr) + void _deallocate(typename List::Data* const dataPtr) { rtsafe_memory_pool_deallocate(fMemPool, dataPtr); } @@ -329,7 +358,7 @@ private: return (typename List::Data*)malloc(this->fDataSize); } - void _deallocate(typename List::Data* const dataPtr) + void _deallocate(typename List::Data* const dataPtr) { free(dataPtr); } @@ -355,7 +384,7 @@ private: return new typename List::Data; } - void _deallocate(typename List::Data* const dataPtr) + void _deallocate(typename List::Data* const dataPtr) { delete dataPtr; }