diff --git a/source/backend/engine/CarlaEngineNative.cpp b/source/backend/engine/CarlaEngineNative.cpp index bbdaa4e67..4e0ba73fa 100644 --- a/source/backend/engine/CarlaEngineNative.cpp +++ b/source/backend/engine/CarlaEngineNative.cpp @@ -73,20 +73,6 @@ public: carla_debug("CarlaEngineNativeUI::~CarlaEngineNativeUI()"); } - void writeShowMessage() noexcept - { - const CarlaMutexLocker cml(getPipeLock()); - writeMessage("show\n", 5); - flushMessages(); - } - - void writeFocusMessage() noexcept - { - const CarlaMutexLocker cml(getPipeLock()); - writeMessage("focus\n", 6); - flushMessages(); - } - protected: bool msgReceived(const char* const msg) noexcept override { diff --git a/source/backend/plugin/CarlaPluginLV2.cpp b/source/backend/plugin/CarlaPluginLV2.cpp index 46b0afbc5..ba09cd96d 100644 --- a/source/backend/plugin/CarlaPluginLV2.cpp +++ b/source/backend/plugin/CarlaPluginLV2.cpp @@ -425,135 +425,6 @@ public: CarlaPipeServer::startPipeServer(fFilename, fPluginURI, fUiURI); } - void writeAtomMessage(const uint32_t index, const LV2_Atom* const atom) const noexcept - { - CARLA_SAFE_ASSERT_RETURN(atom != nullptr,); - - char tmpBuf[0xff+1]; - tmpBuf[0xff] = '\0'; - - CarlaString base64atom(CarlaString::asBase64(atom, lv2_atom_total_size(atom))); - - const CarlaMutexLocker cml(getPipeLock()); - - writeMessage("atom\n", 5); - - { - std::snprintf(tmpBuf, 0xff, "%i\n", index); - writeMessage(tmpBuf); - - std::snprintf(tmpBuf, 0xff, "%i\n", atom->size); - writeMessage(tmpBuf); - - writeAndFixMessage(base64atom.buffer()); - } - - flushMessages(); - } - - void writeUridMessage(const uint32_t urid, const char* const uri) const noexcept - { - CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0',); - - char tmpBuf[0xff+1]; - tmpBuf[0xff] = '\0'; - - const CarlaMutexLocker cml(getPipeLock()); - - writeMessage("urid\n", 5); - - { - std::snprintf(tmpBuf, 0xff, "%i\n", urid); - writeMessage(tmpBuf); - - writeAndFixMessage(uri); - } - - flushMessages(); - } - - void writeControlMessage(const uint32_t index, const float value) const noexcept - { - char tmpBuf[0xff+1]; - tmpBuf[0xff] = '\0'; - - const CarlaMutexLocker cml(getPipeLock()); - const ScopedLocale csl; - - writeMessage("control\n", 8); - - { - std::snprintf(tmpBuf, 0xff, "%i\n", index); - writeMessage(tmpBuf); - - std::snprintf(tmpBuf, 0xff, "%f\n", value); - writeMessage(tmpBuf); - } - - flushMessages(); - } - - void writeProgramMessage(const uint32_t index) const noexcept - { - char tmpBuf[0xff+1]; - tmpBuf[0xff] = '\0'; - - const CarlaMutexLocker cml(getPipeLock()); - - writeMessage("program\n", 8); - - { - std::snprintf(tmpBuf, 0xff, "%i\n", index); - writeMessage(tmpBuf); - } - - flushMessages(); - } - - void writeNoteMessage(const bool onOff, const uint8_t channel, const uint8_t note, const uint8_t velocity) noexcept - { - CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); - CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); - CARLA_SAFE_ASSERT_RETURN(velocity < MAX_MIDI_VALUE,); - - char tmpBuf[0xff+1]; - tmpBuf[0xff] = '\0'; - - const CarlaMutexLocker cml(getPipeLock()); - - writeMessage("note\n", 5); - - { - std::snprintf(tmpBuf, 0xff, "%s\n", bool2str(onOff)); - writeMessage(tmpBuf); - - std::snprintf(tmpBuf, 0xff, "%i\n", channel); - writeMessage(tmpBuf); - - std::snprintf(tmpBuf, 0xff, "%i\n", note); - writeMessage(tmpBuf); - - std::snprintf(tmpBuf, 0xff, "%i\n", velocity); - writeMessage(tmpBuf); - } - - flushMessages(); - } - - void writeShowMessage() noexcept - { - const CarlaMutexLocker cml(getPipeLock()); - writeMessage("show\n", 5); - flushMessages(); - } - - void writeFocusMessage() noexcept - { - const CarlaMutexLocker cml(getPipeLock()); - writeMessage("focus\n", 6); - flushMessages(); - } - protected: // returns true if msg was handled bool msgReceived(const char* const msg) noexcept override; @@ -1335,9 +1206,9 @@ public: fPipeServer.startPipeServer(); for (std::size_t i=CARLA_URI_MAP_ID_COUNT, count=fCustomURIDs.count(); i < count; ++i) - fPipeServer.writeUridMessage(static_cast(i), fCustomURIDs.getAt(i, nullptr)); + fPipeServer.writeLv2UridMessage(static_cast(i), fCustomURIDs.getAt(i, nullptr)); - fPipeServer.writeUridMessage(CARLA_URI_MAP_ID_NULL, "Complete"); + fPipeServer.writeLv2UridMessage(CARLA_URI_MAP_ID_NULL, "Complete"); fPipeServer.writeShowMessage(); } @@ -1523,7 +1394,7 @@ public: else if (fUI.type == UI::TYPE_BRIDGE) { if (fPipeServer.isPipeRunning()) - fPipeServer.writeAtomMessage(portIndex, atom); + fPipeServer.writeLv2AtomMessage(portIndex, atom); } else { @@ -4015,7 +3886,7 @@ public: if (fUI.type == UI::TYPE_BRIDGE) { if (fPipeServer.isPipeRunning()) - fPipeServer.writeNoteMessage(false, channel, note, velo); + fPipeServer.writeMidiNoteMessage(false, channel, note, velo); } else { @@ -4042,7 +3913,7 @@ public: if (fUI.type == UI::TYPE_BRIDGE) { if (fPipeServer.isPipeRunning()) - fPipeServer.writeNoteMessage(false, channel, note, 0); + fPipeServer.writeMidiNoteMessage(false, channel, note, 0); } else { @@ -4306,7 +4177,7 @@ public: fCustomURIDs.append(carla_strdup(uri)); if (fUI.type == UI::TYPE_BRIDGE && fPipeServer.isPipeRunning()) - fPipeServer.writeUridMessage(urid, uri); + fPipeServer.writeLv2UridMessage(urid, uri); return urid; } @@ -6139,7 +6010,7 @@ bool CarlaPipeServerLV2::msgReceived(const char* const msg) noexcept CARLA_SAFE_ASSERT_RETURN(chunk.size() >= sizeof(LV2_Atom), true); const LV2_Atom* const atom((const LV2_Atom*)chunk.data()); - CARLA_SAFE_ASSERT_RETURN(atom->size == chunk.size(), true); + CARLA_SAFE_ASSERT_RETURN(lv2_atom_total_size(atom) == chunk.size(), true); try { kPlugin->handleUIWrite(index, lv2_atom_total_size(atom), CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT, atom); @@ -6170,7 +6041,11 @@ bool CarlaPipeServerLV2::msgReceived(const char* const msg) noexcept CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(uri), true); if (urid != 0) - kPlugin->handleUridMap(urid, uri); + { + try { + kPlugin->handleUridMap(urid, uri); + } CARLA_SAFE_EXCEPTION("msgReceived urid"); + } delete[] uri; return true; diff --git a/source/bridges-ui/CarlaBridgeUI-LV2.cpp b/source/bridges-ui/CarlaBridgeUI-LV2.cpp index 1d5133164..8d74b84fc 100644 --- a/source/bridges-ui/CarlaBridgeUI-LV2.cpp +++ b/source/bridges-ui/CarlaBridgeUI-LV2.cpp @@ -613,7 +613,7 @@ public: } if (isPipeRunning()) - sendURID(urid, uri); + writeLv2UridMessage(urid, uri); return urid; } @@ -632,7 +632,7 @@ public: void handleProgramChanged(const int32_t /*index*/) { if (isPipeRunning()) - sendConfigure("reloadprograms", ""); + writeConfigureMessage("reloadprograms", ""); } uint32_t handleUiPortMap(const char* const symbol) @@ -674,7 +674,7 @@ public: const float value(*(const float*)buffer); if (isPipeRunning()) - sendControl(portIndex, value); + writeControlMessage(portIndex, value); } else if (format == CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM || CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT) { @@ -683,7 +683,7 @@ public: const LV2_Atom* const atom((const LV2_Atom*)buffer); if (isPipeRunning()) - sendAtom(portIndex, atom); + writeLv2AtomMessage(portIndex, atom); } else { diff --git a/source/bridges-ui/CarlaBridgeUI.cpp b/source/bridges-ui/CarlaBridgeUI.cpp index 700886360..a9742a78d 100644 --- a/source/bridges-ui/CarlaBridgeUI.cpp +++ b/source/bridges-ui/CarlaBridgeUI.cpp @@ -76,143 +76,6 @@ CarlaBridgeUI::~CarlaBridgeUI() noexcept } // --------------------------------------------------------------------- -// Host DSP State - -void CarlaBridgeUI::sendControl(const uint32_t index, const float value) const noexcept -{ - char tmpBuf[0xff+1]; - tmpBuf[0xff] = '\0'; - - const CarlaMutexLocker cml(getPipeLock()); - const ScopedLocale csl; - - writeMessage("control\n", 8); - - { - std::snprintf(tmpBuf, 0xff, "%i\n", index); - writeMessage(tmpBuf); - - std::snprintf(tmpBuf, 0xff, "%f\n", value); - writeMessage(tmpBuf); - } - - flushMessages(); -} - -void CarlaBridgeUI::sendProgram(const uint32_t index) const noexcept -{ - char tmpBuf[0xff+1]; - tmpBuf[0xff] = '\0'; - - const CarlaMutexLocker cml(getPipeLock()); - - writeMessage("program\n", 8); - - { - std::snprintf(tmpBuf, 0xff, "%i\n", index); - writeMessage(tmpBuf); - } - - flushMessages(); -} - -void CarlaBridgeUI::sendConfigure(const char* const key, const char* const value) const noexcept -{ - CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); - CARLA_SAFE_ASSERT_RETURN(value != nullptr,); - - const CarlaMutexLocker cml(getPipeLock()); - - writeMessage("configure\n", 10); - - { - writeAndFixMessage(key); - writeAndFixMessage(value); - } - - flushMessages(); -} - -void CarlaBridgeUI::sendNote(const bool onOff, const uint8_t channel, const uint8_t note, const uint8_t velocity) const noexcept -{ - CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); - CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); - CARLA_SAFE_ASSERT_RETURN(velocity < MAX_MIDI_VALUE,); - - char tmpBuf[0xff+1]; - tmpBuf[0xff] = '\0'; - - const CarlaMutexLocker cml(getPipeLock()); - - writeMessage("note\n", 5); - - { - std::snprintf(tmpBuf, 0xff, "%s\n", bool2str(onOff)); - writeMessage(tmpBuf); - - std::snprintf(tmpBuf, 0xff, "%i\n", channel); - writeMessage(tmpBuf); - - std::snprintf(tmpBuf, 0xff, "%i\n", note); - writeMessage(tmpBuf); - - std::snprintf(tmpBuf, 0xff, "%i\n", velocity); - writeMessage(tmpBuf); - } - - flushMessages(); -} - -#ifdef BRIDGE_LV2 -void CarlaBridgeUI::sendAtom(const uint32_t index, const LV2_Atom* const atom) const noexcept -{ - CARLA_SAFE_ASSERT_RETURN(atom != nullptr,); - - char tmpBuf[0xff+1]; - tmpBuf[0xff] = '\0'; - - CarlaString base64atom(CarlaString::asBase64(atom, lv2_atom_total_size(atom))); - - const CarlaMutexLocker cml(getPipeLock()); - - writeMessage("atom\n", 5); - - { - std::snprintf(tmpBuf, 0xff, "%i\n", index); - writeMessage(tmpBuf); - - std::snprintf(tmpBuf, 0xff, "%i\n", atom->size); - writeMessage(tmpBuf); - - writeAndFixMessage(base64atom.buffer()); - } - - flushMessages(); -} - -void CarlaBridgeUI::sendURID(const LV2_URID urid, const char* const uri) const noexcept -{ - CARLA_SAFE_ASSERT_RETURN(urid != 0,); - CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0',); - - char tmpBuf[0xff+1]; - tmpBuf[0xff] = '\0'; - - const CarlaMutexLocker cml(getPipeLock()); - - writeMessage("urid\n", 5); - - { - std::snprintf(tmpBuf, 0xff, "%i\n", urid); - writeMessage(tmpBuf); - - writeAndFixMessage(uri); - } - - flushMessages(); -} -#endif - bool CarlaBridgeUI::libOpen(const char* const filename) noexcept { @@ -329,7 +192,7 @@ bool CarlaBridgeUI::msgReceived(const char* const msg) noexcept CARLA_SAFE_ASSERT_RETURN(chunk.size() >= sizeof(LV2_Atom), true); const LV2_Atom* const atom((const LV2_Atom*)chunk.data()); - CARLA_SAFE_ASSERT_RETURN(atom->size == chunk.size(), true); + CARLA_SAFE_ASSERT_RETURN(lv2_atom_total_size(atom) == chunk.size(), true); dspAtomReceived(index, atom); return true; diff --git a/source/bridges-ui/CarlaBridgeUI.hpp b/source/bridges-ui/CarlaBridgeUI.hpp index 24afebd76..65e450c27 100644 --- a/source/bridges-ui/CarlaBridgeUI.hpp +++ b/source/bridges-ui/CarlaBridgeUI.hpp @@ -55,17 +55,6 @@ protected: virtual ~CarlaBridgeUI() noexcept; // --------------------------------------------------------------------- - // Host DSP State - - void sendControl(const uint32_t index, const float value) const noexcept; - void sendProgram(const uint32_t index) const noexcept; - void sendConfigure(const char* const key, const char* const value) const noexcept; - void sendNote(const bool onOff, const uint8_t channel, const uint8_t note, const uint8_t velocity) const noexcept; - -#ifdef BRIDGE_LV2 - void sendAtom(const uint32_t index, const LV2_Atom* const atom) const noexcept; - void sendURID(const LV2_URID urid, const char* const uri) const noexcept; -#endif bool libOpen(const char* const filename) noexcept; void* libSymbol(const char* const symbol) const noexcept; diff --git a/source/utils/CarlaExternalUI.hpp b/source/utils/CarlaExternalUI.hpp index ba66944ee..c672626a3 100644 --- a/source/utils/CarlaExternalUI.hpp +++ b/source/utils/CarlaExternalUI.hpp @@ -33,7 +33,7 @@ public: UiCrashed }; - CarlaExternalUI() + CarlaExternalUI() noexcept : fFilename(), fSampleRate(), fUiTitle(), @@ -63,12 +63,8 @@ public: { CarlaPipeServer::startPipeServer(fFilename, fSampleRate, fUiTitle); - if (! show) - return; - - const CarlaMutexLocker cml(getPipeLock()); - writeMessage("show\n", 5); - flushMessages(); + if (show) + writeShowMessage(); } protected: diff --git a/source/utils/CarlaPipeUtils.cpp b/source/utils/CarlaPipeUtils.cpp index 1d888f1b1..01145341b 100644 --- a/source/utils/CarlaPipeUtils.cpp +++ b/source/utils/CarlaPipeUtils.cpp @@ -17,8 +17,14 @@ #include "CarlaPipeUtils.hpp" #include "CarlaString.hpp" +#include "CarlaMIDI.h" + +// needed for atom-util +#undef NULL +#define NULL nullptr #include "juce_core.h" +#include "lv2/atom-util.h" #include @@ -709,7 +715,7 @@ bool CarlaPipeCommon::writeAndFixMessage(const char* const msg) const noexcept { std::strcpy(fixedMsg, msg); - for (size_t i=0; i < size; ++i) + for (std::size_t i=0; iwriteLock); + _writeMsgBuffer("show\n", 5); + flushMessages(); +} + +void CarlaPipeCommon::writeFocusMessage() const noexcept +{ + const CarlaMutexLocker cml(pData->writeLock); + _writeMsgBuffer("focus\n", 6); + flushMessages(); +} + +void CarlaPipeCommon::writeHideMessage() const noexcept +{ + const CarlaMutexLocker cml(pData->writeLock); + _writeMsgBuffer("show\n", 5); + flushMessages(); +} + +void CarlaPipeCommon::writeErrorMessage(const char* const error) const noexcept +{ + CARLA_SAFE_ASSERT_RETURN(error != nullptr && error[0] != '\0',); + + const CarlaMutexLocker cml(pData->writeLock); + _writeMsgBuffer("error\n", 6); + writeAndFixMessage(error); + flushMessages(); +} + +// ------------------------------------------------------------------- + +void CarlaPipeCommon::writeControlMessage(const uint32_t index, const float value) const noexcept +{ + char tmpBuf[0xff+1]; + tmpBuf[0xff] = '\0'; + + const CarlaMutexLocker cml(pData->writeLock); + const ScopedLocale csl; + + _writeMsgBuffer("control\n", 8); + + { + std::snprintf(tmpBuf, 0xff, "%i\n", index); + _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf)); + + std::snprintf(tmpBuf, 0xff, "%f\n", value); + _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf)); + } + + flushMessages(); +} + +void CarlaPipeCommon::writeConfigureMessage(const char* const key, const char* const value) const noexcept +{ + CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); + CARLA_SAFE_ASSERT_RETURN(value != nullptr,); + + const CarlaMutexLocker cml(pData->writeLock); + + _writeMsgBuffer("configure\n", 10); + + { + writeAndFixMessage(key); + writeAndFixMessage(value); + } + + flushMessages(); +} + +void CarlaPipeCommon::writeProgramMessage(const uint32_t index) const noexcept +{ + char tmpBuf[0xff+1]; + tmpBuf[0xff] = '\0'; + + const CarlaMutexLocker cml(pData->writeLock); + + _writeMsgBuffer("program\n", 8); + + { + std::snprintf(tmpBuf, 0xff, "%i\n", index); + _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf)); + } + + flushMessages(); +} + +void CarlaPipeCommon::writeMidiProgramMessage(const uint32_t bank, const uint32_t program) const noexcept +{ + char tmpBuf[0xff+1]; + tmpBuf[0xff] = '\0'; + + const CarlaMutexLocker cml(pData->writeLock); + + _writeMsgBuffer("midiprogram\n", 8); + + { + std::snprintf(tmpBuf, 0xff, "%i\n", bank); + _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf)); + + std::snprintf(tmpBuf, 0xff, "%i\n", program); + _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf)); + } + + flushMessages(); +} + +void CarlaPipeCommon::writeMidiNoteMessage(const bool onOff, const uint8_t channel, const uint8_t note, const uint8_t velocity) const noexcept +{ + CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); + CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); + CARLA_SAFE_ASSERT_RETURN(velocity < MAX_MIDI_VALUE,); + + char tmpBuf[0xff+1]; + tmpBuf[0xff] = '\0'; + + const CarlaMutexLocker cml(pData->writeLock); + + _writeMsgBuffer("note\n", 5); + + { + std::snprintf(tmpBuf, 0xff, "%s\n", bool2str(onOff)); + _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf)); + + std::snprintf(tmpBuf, 0xff, "%i\n", channel); + _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf)); + + std::snprintf(tmpBuf, 0xff, "%i\n", note); + _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf)); + + std::snprintf(tmpBuf, 0xff, "%i\n", velocity); + _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf)); + } + + flushMessages(); +} + +void CarlaPipeCommon::writeLv2AtomMessage(const uint32_t index, const LV2_Atom* const atom) const noexcept +{ + CARLA_SAFE_ASSERT_RETURN(atom != nullptr,); + + char tmpBuf[0xff+1]; + tmpBuf[0xff] = '\0'; + + CarlaString base64atom(CarlaString::asBase64(atom, lv2_atom_total_size(atom))); + + const CarlaMutexLocker cml(pData->writeLock); + + _writeMsgBuffer("atom\n", 5); + + { + std::snprintf(tmpBuf, 0xff, "%i\n", index); + _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf)); + + std::snprintf(tmpBuf, 0xff, "%i\n", atom->size); + _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf)); + + writeAndFixMessage(base64atom.buffer()); + } + + flushMessages(); +} + +void CarlaPipeCommon::writeLv2UridMessage(const uint32_t urid, const char* const uri) const noexcept +{ + CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0',); + + char tmpBuf[0xff+1]; + tmpBuf[0xff] = '\0'; + + const CarlaMutexLocker cml(pData->writeLock); + + _writeMsgBuffer("urid\n", 5); + + { + std::snprintf(tmpBuf, 0xff, "%i\n", urid); + _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf)); + + writeAndFixMessage(uri); + } + + flushMessages(); +} + +// ------------------------------------------------------------------- + // internal const char* CarlaPipeCommon::_readline() const noexcept { diff --git a/source/utils/CarlaPipeUtils.hpp b/source/utils/CarlaPipeUtils.hpp index 6c73d57a9..5e9575575 100644 --- a/source/utils/CarlaPipeUtils.hpp +++ b/source/utils/CarlaPipeUtils.hpp @@ -21,6 +21,8 @@ #include "CarlaJuceUtils.hpp" #include "CarlaMutex.hpp" +#include "lv2/atom.h" + // ----------------------------------------------------------------------- // CarlaPipeCommon class @@ -164,6 +166,64 @@ public: bool flushMessages() const noexcept; // ------------------------------------------------------------------- + // write prepared messages, no lock or flush needed (done internally) + + /*! + * Write a single "show" message. + */ + void writeShowMessage() const noexcept; + + /*! + * Write a single "focus" message. + */ + void writeFocusMessage() const noexcept; + + /*! + * Write a single "hide" message. + */ + void writeHideMessage() const noexcept; + + /*! + * Write an "error" message. + */ + void writeErrorMessage(const char* const error) const noexcept; + + /*! + * Write a "control" message used for parameter changes. + */ + void writeControlMessage(const uint32_t index, const float value) const noexcept; + + /*! + * Write a "configure" message used for state changes. + */ + void writeConfigureMessage(const char* const key, const char* const value) const noexcept; + + /*! + * Write a "program" message (using index). + */ + void writeProgramMessage(const uint32_t index) const noexcept; + + /*! + * Write a "midiprogram" message (using bank and program). + */ + void writeMidiProgramMessage(const uint32_t bank, const uint32_t program) const noexcept; + + /*! + * Write a MIDI "note" message. + */ + void writeMidiNoteMessage(const bool onOff, const uint8_t channel, const uint8_t note, const uint8_t velocity) const noexcept; + + /*! + * Write an lv2 "atom" message. + */ + void writeLv2AtomMessage(const uint32_t index, const LV2_Atom* const atom) const noexcept; + + /*! + * Write an lv2 "urid" message. + */ + void writeLv2UridMessage(const uint32_t urid, const char* const uri) const noexcept; + + // ------------------------------------------------------------------- protected: struct PrivateData;