diff --git a/c++/carla-backend/lv2.cpp b/c++/carla-backend/lv2.cpp index 43c4a4a..2536bde 100644 --- a/c++/carla-backend/lv2.cpp +++ b/c++/carla-backend/lv2.cpp @@ -73,24 +73,28 @@ const unsigned int PARAMETER_IS_TRIGGER = 0x2000; //!< LV2 Parameter is tr * \see CarlaPlugin::hints * @{ */ -const uint32_t lv2_feature_id_event = 0; -const uint32_t lv2_feature_id_logs = 1; -const uint32_t lv2_feature_id_programs = 2; -const uint32_t lv2_feature_id_state_make_path = 3; -const uint32_t lv2_feature_id_state_map_path = 4; -const uint32_t lv2_feature_id_strict_bounds = 5; -const uint32_t lv2_feature_id_uri_map = 6; -const uint32_t lv2_feature_id_urid_map = 7; -const uint32_t lv2_feature_id_urid_unmap = 8; -const uint32_t lv2_feature_id_worker = 9; -const uint32_t lv2_feature_id_data_access = 10; -const uint32_t lv2_feature_id_instance_access = 11; -const uint32_t lv2_feature_id_ui_parent = 12; -const uint32_t lv2_feature_id_ui_port_map = 13; -const uint32_t lv2_feature_id_ui_resize = 14; -const uint32_t lv2_feature_id_external_ui = 15; -const uint32_t lv2_feature_id_external_ui_old = 16; -const uint32_t lv2_feature_count = 17; +const uint32_t lv2_feature_id_bufsize_bounded = 0; +const uint32_t lv2_feature_id_bufsize_fixed = 1; +const uint32_t lv2_feature_id_bufsize_powerof2 = 2; +const uint32_t lv2_feature_id_event = 3; +const uint32_t lv2_feature_id_logs = 4; +const uint32_t lv2_feature_id_options = 5; +const uint32_t lv2_feature_id_programs = 6; +const uint32_t lv2_feature_id_state_make_path = 7; +const uint32_t lv2_feature_id_state_map_path = 8; +const uint32_t lv2_feature_id_strict_bounds = 9; +const uint32_t lv2_feature_id_uri_map = 10; +const uint32_t lv2_feature_id_urid_map = 11; +const uint32_t lv2_feature_id_urid_unmap = 12; +const uint32_t lv2_feature_id_worker = 13; +const uint32_t lv2_feature_id_data_access = 14; +const uint32_t lv2_feature_id_instance_access = 15; +const uint32_t lv2_feature_id_ui_parent = 16; +const uint32_t lv2_feature_id_ui_port_map = 17; +const uint32_t lv2_feature_id_ui_resize = 18; +const uint32_t lv2_feature_id_external_ui = 19; +const uint32_t lv2_feature_id_external_ui_old = 20; +const uint32_t lv2_feature_count = 21; /**@}*/ /*! @@ -114,22 +118,28 @@ const unsigned int CARLA_EVENT_TYPE_MIDI = 0x20; * \see CarlaPlugin::hints * @{ */ -const uint32_t CARLA_URI_MAP_ID_NULL = 0; -const uint32_t CARLA_URI_MAP_ID_ATOM_CHUNK = 1; -const uint32_t CARLA_URI_MAP_ID_ATOM_PATH = 2; -const uint32_t CARLA_URI_MAP_ID_ATOM_SEQUENCE = 3; -const uint32_t CARLA_URI_MAP_ID_ATOM_STRING = 4; -const uint32_t CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM = 5; -const uint32_t CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT = 6; -const uint32_t CARLA_URI_MAP_ID_LOG_ERROR = 7; -const uint32_t CARLA_URI_MAP_ID_LOG_NOTE = 8; -const uint32_t CARLA_URI_MAP_ID_LOG_TRACE = 9; -const uint32_t CARLA_URI_MAP_ID_LOG_WARNING = 10; -const uint32_t CARLA_URI_MAP_ID_MIDI_EVENT = 11; -const uint32_t CARLA_URI_MAP_ID_COUNT = 12; +const uint32_t CARLA_URI_MAP_ID_NULL = 0; +const uint32_t CARLA_URI_MAP_ID_ATOM_CHUNK = 1; +const uint32_t CARLA_URI_MAP_ID_ATOM_DOUBLE = 2; +const uint32_t CARLA_URI_MAP_ID_ATOM_INT = 3; +const uint32_t CARLA_URI_MAP_ID_ATOM_PATH = 4; +const uint32_t CARLA_URI_MAP_ID_ATOM_SEQUENCE = 5; +const uint32_t CARLA_URI_MAP_ID_ATOM_STRING = 6; +const uint32_t CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM = 7; +const uint32_t CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT = 8; +const uint32_t CARLA_URI_MAP_ID_BUF_MAX_LENGTH = 9; +const uint32_t CARLA_URI_MAP_ID_BUF_MIN_LENGTH = 10; +const uint32_t CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE = 11; +const uint32_t CARLA_URI_MAP_ID_LOG_ERROR = 12; +const uint32_t CARLA_URI_MAP_ID_LOG_NOTE = 13; +const uint32_t CARLA_URI_MAP_ID_LOG_TRACE = 14; +const uint32_t CARLA_URI_MAP_ID_LOG_WARNING = 15; +const uint32_t CARLA_URI_MAP_ID_MIDI_EVENT = 16; +const uint32_t CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE = 17; +const uint32_t CARLA_URI_MAP_ID_COUNT = 18; /**@}*/ -struct EventData { +struct Lv2EventData { uint32_t type; CarlaEngineMidiPort* port; union { @@ -138,20 +148,40 @@ struct EventData { LV2_MIDI* midi; }; - EventData() + Lv2EventData() : type(0), port(nullptr) {} }; -struct PluginEventData { +struct Lv2PluginEventData { uint32_t count; - EventData* data; + Lv2EventData* data; - PluginEventData() + Lv2PluginEventData() : count(0), data(nullptr) {} }; +struct Lv2PluginOptions { + bool init; + uint32_t eventSize; + uint32_t bufferSize; + double sampleRate; + LV2_Options_Option oNull; + LV2_Options_Option oMaxBlockLenth; + LV2_Options_Option oMinBlockLenth; + LV2_Options_Option oSequenceSize; + LV2_Options_Option oSampleRate; + + Lv2PluginOptions() + : init(false), + eventSize(MAX_EVENT_BUFFER), + bufferSize(0), + sampleRate(0.0) {} +}; + +Lv2PluginOptions lv2Options; + const char* lv2bridge2str(const LV2_Property type) { switch (type) @@ -220,6 +250,38 @@ public: for (uint32_t i=0; i < lv2_feature_count+1; i++) features[i] = nullptr; + + if (! lv2Options.init) + { + lv2Options.init = true; + lv2Options.bufferSize = x_engine->getBufferSize(); + lv2Options.sampleRate = x_engine->getSampleRate(); + + lv2Options.oNull.key = CARLA_URI_MAP_ID_NULL; + lv2Options.oNull.size = 0; + lv2Options.oNull.type = CARLA_URI_MAP_ID_NULL; + lv2Options.oNull.value = nullptr; + + lv2Options.oMaxBlockLenth.key = CARLA_URI_MAP_ID_BUF_MAX_LENGTH; + lv2Options.oMaxBlockLenth.size = sizeof(uint32_t); + lv2Options.oMaxBlockLenth.type = CARLA_URI_MAP_ID_ATOM_INT; + lv2Options.oMaxBlockLenth.value = &lv2Options.bufferSize; + + lv2Options.oMinBlockLenth.key = CARLA_URI_MAP_ID_BUF_MIN_LENGTH; + lv2Options.oMinBlockLenth.size = sizeof(uint32_t); + lv2Options.oMinBlockLenth.type = CARLA_URI_MAP_ID_ATOM_INT; + lv2Options.oMinBlockLenth.value = &lv2Options.bufferSize; + + lv2Options.oSequenceSize.key = CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE; + lv2Options.oSequenceSize.size = sizeof(uint32_t); + lv2Options.oSequenceSize.type = CARLA_URI_MAP_ID_ATOM_INT; + lv2Options.oSequenceSize.value = &lv2Options.eventSize; + + lv2Options.oSampleRate.key = CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE; + lv2Options.oSampleRate.size = sizeof(double); + lv2Options.oSampleRate.type = CARLA_URI_MAP_ID_ATOM_DOUBLE; + lv2Options.oSampleRate.value = &lv2Options.sampleRate; + } } ~Lv2Plugin() @@ -299,7 +361,7 @@ public: if (features[lv2_feature_id_external_ui]) { - lv2_external_ui_host* const uiHost = (lv2_external_ui_host*)features[lv2_feature_id_external_ui]->data; + const lv2_external_ui_host* const uiHost = (const lv2_external_ui_host*)features[lv2_feature_id_external_ui]->data; if (uiHost) { @@ -341,6 +403,12 @@ public: if (features[lv2_feature_id_logs] && features[lv2_feature_id_logs]->data) delete (LV2_Log_Log*)features[lv2_feature_id_logs]->data; + if (features[lv2_feature_id_options] && features[lv2_feature_id_options]->data) + { + const LV2_Options_Option* const options = (const LV2_Options_Option*)features[lv2_feature_id_options]->data; + delete[] options; + } + if (features[lv2_feature_id_programs] && features[lv2_feature_id_programs]->data) delete (LV2_Programs_Host*)features[lv2_feature_id_programs]->data; @@ -1058,7 +1126,7 @@ public: if (evIns.size() > 0) { const size_t size = evIns.size(); - evIn.data = new EventData[size]; + evIn.data = new Lv2EventData[size]; for (j=0; j < size; j++) { @@ -1092,7 +1160,7 @@ public: if (evOuts.size() > 0) { const size_t size = evOuts.size(); - evOut.data = new EventData[size]; + evOut.data = new Lv2EventData[size]; for (j=0; j < size; j++) { @@ -2414,6 +2482,11 @@ public: m_activeBefore = m_active; } + void bufferSizeChanged(const uint32_t newBufferSize) + { + lv2Options.bufferSize = newBufferSize; + } + // ------------------------------------------------------------------- // Post-poned events @@ -3300,6 +3373,10 @@ public: // Atom types if (strcmp(uri, LV2_ATOM__Chunk) == 0) return CARLA_URI_MAP_ID_ATOM_CHUNK; + if (strcmp(uri, LV2_ATOM__Double) == 0) + return CARLA_URI_MAP_ID_ATOM_DOUBLE; + if (strcmp(uri, LV2_ATOM__Int) == 0) + return CARLA_URI_MAP_ID_ATOM_INT; if (strcmp(uri, LV2_ATOM__Path) == 0) return CARLA_URI_MAP_ID_ATOM_PATH; if (strcmp(uri, LV2_ATOM__Sequence) == 0) @@ -3311,6 +3388,14 @@ public: if (strcmp(uri, LV2_ATOM__eventTransfer) == 0) return CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT; + // BufSize types + if (strcmp(uri, LV2_BUF_SIZE__maxBlockLength) == 0) + return CARLA_URI_MAP_ID_BUF_MAX_LENGTH; + if (strcmp(uri, LV2_BUF_SIZE__minBlockLength) == 0) + return CARLA_URI_MAP_ID_BUF_MIN_LENGTH; + if (strcmp(uri, LV2_BUF_SIZE__sequenceSize) == 0) + return CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE; + // Log types if (strcmp(uri, LV2_LOG__Error) == 0) return CARLA_URI_MAP_ID_LOG_ERROR; @@ -3324,6 +3409,8 @@ public: // Others if (strcmp(uri, LV2_MIDI__MidiEvent) == 0) return CARLA_URI_MAP_ID_MIDI_EVENT; + if (strcmp(uri, LV2_PARAMETERS__sampleRate) == 0) + return CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE; if (! handle) return CARLA_URI_MAP_ID_NULL; @@ -3345,6 +3432,10 @@ public: // Atom types if (urid == CARLA_URI_MAP_ID_ATOM_CHUNK) return LV2_ATOM__Chunk; + if (urid == CARLA_URI_MAP_ID_ATOM_DOUBLE) + return LV2_ATOM__Double; + if (urid == CARLA_URI_MAP_ID_ATOM_INT) + return LV2_ATOM__Int; if (urid == CARLA_URI_MAP_ID_ATOM_PATH) return LV2_ATOM__Path; if (urid == CARLA_URI_MAP_ID_ATOM_SEQUENCE) @@ -3356,6 +3447,14 @@ public: if (urid == CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT) return LV2_ATOM__eventTransfer; + // BufSize types + if (urid == CARLA_URI_MAP_ID_BUF_MAX_LENGTH) + return LV2_BUF_SIZE__maxBlockLength; + if (urid == CARLA_URI_MAP_ID_BUF_MIN_LENGTH) + return LV2_BUF_SIZE__minBlockLength; + if (urid == CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE) + return LV2_BUF_SIZE__sequenceSize; + // Log types if (urid == CARLA_URI_MAP_ID_LOG_ERROR) return LV2_LOG__Error; @@ -3369,6 +3468,8 @@ public: // Others if (urid == CARLA_URI_MAP_ID_MIDI_EVENT) return LV2_MIDI__MidiEvent; + if (urid == CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE) + return LV2_PARAMETERS__sampleRate; if (! handle) return nullptr; @@ -3626,6 +3727,34 @@ public: workerFt->handle = this; workerFt->schedule_work = carla_lv2_worker_schedule; + LV2_Options_Option* const optionsFt = new LV2_Options_Option [5]; + optionsFt[0] = lv2Options.oMaxBlockLenth; + optionsFt[1] = lv2Options.oMinBlockLenth; + optionsFt[2] = lv2Options.oSequenceSize; + optionsFt[3] = lv2Options.oSampleRate; + optionsFt[4] = lv2Options.oNull; + + features[lv2_feature_id_bufsize_bounded] = new LV2_Feature; + features[lv2_feature_id_bufsize_bounded]->URI = LV2_BUF_SIZE__boundedBlockLength; + features[lv2_feature_id_bufsize_bounded]->data = nullptr; + + if (carlaOptions.processHighPrecision) + { + features[lv2_feature_id_bufsize_fixed] = new LV2_Feature; + features[lv2_feature_id_bufsize_fixed]->URI = LV2_BUF_SIZE__fixedBlockLength; + features[lv2_feature_id_bufsize_fixed]->data = nullptr; + + features[lv2_feature_id_bufsize_powerof2] = new LV2_Feature; + features[lv2_feature_id_bufsize_powerof2]->URI = LV2_BUF_SIZE__powerOf2BlockLength; + features[lv2_feature_id_bufsize_powerof2]->data = nullptr; + } + else + { + // fake, used to keep a valid array + features[lv2_feature_id_bufsize_fixed] = features[lv2_feature_id_bufsize_bounded]; + features[lv2_feature_id_bufsize_powerof2] = features[lv2_feature_id_bufsize_bounded]; + } + features[lv2_feature_id_event] = new LV2_Feature; features[lv2_feature_id_event]->URI = LV2_EVENT_URI; features[lv2_feature_id_event]->data = eventFt; @@ -3634,6 +3763,10 @@ public: features[lv2_feature_id_logs]->URI = LV2_LOG__log; features[lv2_feature_id_logs]->data = logFt; + features[lv2_feature_id_options] = new LV2_Feature; + features[lv2_feature_id_options]->URI = LV2_OPTIONS__options; + features[lv2_feature_id_options]->data = optionsFt; + features[lv2_feature_id_programs] = new LV2_Feature; features[lv2_feature_id_programs]->URI = LV2_PROGRAMS__Host; features[lv2_feature_id_programs]->data = programsFt; @@ -4075,8 +4208,8 @@ private: } suil; #endif - PluginEventData evIn; - PluginEventData evOut; + Lv2PluginEventData evIn; + Lv2PluginEventData evOut; float* paramBuffers; std::vector customURIDs; }; @@ -4133,7 +4266,7 @@ int CarlaOsc::handle_lv2_atom_transfer(CARLA_OSC_HANDLE_ARGS2) qDebug("CarlaOsc::handle_lv2_atom_transfer()"); //CARLA_OSC_CHECK_OSC_TYPES(2, "ii"); - CarlaBackend::Lv2Plugin* lv2plugin = (CarlaBackend::Lv2Plugin*)plugin; + CarlaBackend::Lv2Plugin* const lv2plugin = (CarlaBackend::Lv2Plugin*)plugin; lv2plugin->handleTransferAtom(); return 0; @@ -4151,7 +4284,7 @@ int CarlaOsc::handle_lv2_event_transfer(CARLA_OSC_HANDLE_ARGS2) const char* const key = (const char*)&argv[1]->s; const char* const value = (const char*)&argv[2]->s; - CarlaBackend::Lv2Plugin* lv2plugin = (CarlaBackend::Lv2Plugin*)plugin; + CarlaBackend::Lv2Plugin* const lv2plugin = (CarlaBackend::Lv2Plugin*)plugin; lv2plugin->handleTransferEvent(type, key, value); return 0; diff --git a/c++/carla-includes/carla_lv2.h b/c++/carla-includes/carla_lv2.h index da819b4..2497af6 100644 --- a/c++/carla-includes/carla_lv2.h +++ b/c++/carla-includes/carla_lv2.h @@ -1454,6 +1454,8 @@ bool is_lv2_feature_supported(const LV2_URI uri) return true; if (strcmp(uri, LV2_LOG__log) == 0) return true; + if (strcmp(uri, LV2_OPTIONS__options) == 0) + return true; if (strcmp(uri, LV2_PROGRAMS__Host) == 0) return true; if (strcmp(uri, LV2_STATE__makePath) == 0) @@ -1484,6 +1486,8 @@ bool is_lv2_ui_feature_supported(const LV2_URI uri) return true; if (strcmp(uri, LV2_UI__fixedSize) == 0) return true; + if (strcmp(uri, LV2_UI__makeResident) == 0) + return true; if (strcmp(uri, LV2_UI__noUserResize) == 0) return true; if (strcmp(uri, LV2_UI__parent) == 0) @@ -1491,13 +1495,11 @@ bool is_lv2_ui_feature_supported(const LV2_URI uri) if (strcmp(uri, LV2_UI__portMap) == 0) return true; if (strcmp(uri, LV2_UI__portSubscribe) == 0) - return false; // TODO: uninplemented + return false; // TODO if (strcmp(uri, LV2_UI__resize) == 0) return true; if (strcmp(uri, LV2_UI__touch) == 0) - return false; // TODO: uninplemented - if (strcmp(uri, LV2_UI__makeResident) == 0) - return true; + return false; // TODO if (strcmp(uri, LV2_EXTERNAL_UI_URI) == 0) return true; if (strcmp(uri, LV2_EXTERNAL_UI_DEPRECATED_URI) == 0) diff --git a/src/carla.py b/src/carla.py index 45fb4d3..ee6f377 100755 --- a/src/carla.py +++ b/src/carla.py @@ -1595,6 +1595,7 @@ class CarlaMainW(QMainWindow, ui_carla.Ui_CarlaMainW): if ptype == "LADSPA": if not x_ladspa_plugins: x_ladspa_plugins = [] + x_ladspa_plugins += toList(self.settings_db.value("Plugins/LADSPA_native", [])) x_ladspa_plugins += toList(self.settings_db.value("Plugins/LADSPA_unix32", [])) x_ladspa_plugins += toList(self.settings_db.value("Plugins/LADSPA_unix64", [])) x_ladspa_plugins += toList(self.settings_db.value("Plugins/LADSPA_win32", [])) @@ -1604,6 +1605,7 @@ class CarlaMainW(QMainWindow, ui_carla.Ui_CarlaMainW): elif ptype == "DSSI": if not x_dssi_plugins: x_dssi_plugins = [] + x_dssi_plugins += toList(self.settings_db.value("Plugins/DSSI_native", [])) x_dssi_plugins += toList(self.settings_db.value("Plugins/DSSI_unix32", [])) x_dssi_plugins += toList(self.settings_db.value("Plugins/DSSI_unix64", [])) x_dssi_plugins += toList(self.settings_db.value("Plugins/DSSI_win32", [])) @@ -1613,6 +1615,7 @@ class CarlaMainW(QMainWindow, ui_carla.Ui_CarlaMainW): elif ptype == "LV2": if not x_lv2_plugins: x_lv2_plugins = [] + x_lv2_plugins += toList(self.settings_db.value("Plugins/LV2_native", [])) x_lv2_plugins += toList(self.settings_db.value("Plugins/LV2_unix32", [])) x_lv2_plugins += toList(self.settings_db.value("Plugins/LV2_unix64", [])) x_lv2_plugins += toList(self.settings_db.value("Plugins/LV2_win32", [])) @@ -1622,6 +1625,7 @@ class CarlaMainW(QMainWindow, ui_carla.Ui_CarlaMainW): elif ptype == "VST": if not x_vst_plugins: x_vst_plugins = [] + x_vst_plugins += toList(self.settings_db.value("Plugins/VST_native", [])) x_vst_plugins += toList(self.settings_db.value("Plugins/VST_unix32", [])) x_vst_plugins += toList(self.settings_db.value("Plugins/VST_unix64", [])) x_vst_plugins += toList(self.settings_db.value("Plugins/VST_win32", []))