| @@ -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; | |||
| } | |||
| } | |||
| @@ -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); | |||
| @@ -921,6 +921,8 @@ public: | |||
| } | |||
| } | |||
| fData->postRtEvents.trySplice(); | |||
| } // End of Parameters Input | |||
| CARLA_PROCESS_CONTINUE_CHECK; | |||
| @@ -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: | |||
| @@ -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 <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| @@ -23,8 +23,7 @@ extern "C" { | |||
| #include "rtmempool/rtmempool.h" | |||
| } | |||
| #include <cassert> | |||
| #include <cstring> | |||
| #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<typename T> | |||
| @@ -255,9 +280,10 @@ class RtList : public List<T> | |||
| { | |||
| 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<T>::Data*)rtsafe_memory_pool_allocate_sleepy(fMemPool); | |||
| } | |||
| void _deallocate(typename List<T>::Data* const dataPtr) | |||
| void _deallocate(typename List<T>::Data* const dataPtr) | |||
| { | |||
| rtsafe_memory_pool_deallocate(fMemPool, dataPtr); | |||
| } | |||
| @@ -329,7 +358,7 @@ private: | |||
| return (typename List<T>::Data*)malloc(this->fDataSize); | |||
| } | |||
| void _deallocate(typename List<T>::Data* const dataPtr) | |||
| void _deallocate(typename List<T>::Data* const dataPtr) | |||
| { | |||
| free(dataPtr); | |||
| } | |||
| @@ -355,7 +384,7 @@ private: | |||
| return new typename List<T>::Data; | |||
| } | |||
| void _deallocate(typename List<T>::Data* const dataPtr) | |||
| void _deallocate(typename List<T>::Data* const dataPtr) | |||
| { | |||
| delete dataPtr; | |||
| } | |||