diff --git a/source/backend/plugin/CarlaPluginLV2.cpp b/source/backend/plugin/CarlaPluginLV2.cpp index 1f7a45a5d..46b0afbc5 100644 --- a/source/backend/plugin/CarlaPluginLV2.cpp +++ b/source/backend/plugin/CarlaPluginLV2.cpp @@ -25,6 +25,7 @@ #include "CarlaLv2Utils.hpp" #include "CarlaBase64Utils.hpp" +#include "CarlaPipeUtils.hpp" #include "CarlaPluginUI.hpp" #include "Lv2AtomRingBuffer.hpp" @@ -42,7 +43,6 @@ using juce::File; CARLA_BACKEND_START_NAMESPACE -#if 0 // ----------------------------------------------------- // Maximum default buffer size @@ -379,6 +379,196 @@ struct CarlaPluginLV2Options { CARLA_DECLARE_NON_COPY_STRUCT(CarlaPluginLV2Options); }; +// ----------------------------------------------------------------------- + +class CarlaPluginLV2; + +class CarlaPipeServerLV2 : public CarlaPipeServer +{ +public: + enum UiState { + UiNone = 0, + UiHide, + UiShow, + UiCrashed + }; + + CarlaPipeServerLV2(CarlaPluginLV2* const plugin) + : kPlugin(plugin), + fFilename(), + fPluginURI(), + fUiURI(), + fUiState(UiNone), + leakDetector_CarlaPipeServerLV2() {} + + ~CarlaPipeServerLV2() noexcept override + { + CARLA_SAFE_ASSERT_INT(fUiState == UiNone, fUiState); + } + + UiState getAndResetUiState() noexcept + { + const UiState uiState(fUiState); + fUiState = UiNone; + return uiState; + } + + void setData(const char* const filename, const char* const pluginURI, const char* const uiURI) noexcept + { + fFilename = filename; + fPluginURI = pluginURI; + fUiURI = uiURI; + } + + void startPipeServer() noexcept + { + 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; + +private: + CarlaPluginLV2* const kPlugin; + + CarlaString fFilename; + CarlaString fPluginURI; + CarlaString fUiURI; + UiState fUiState; + + CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPipeServerLV2) +}; + // ----------------------------------------------------- class CarlaPluginLV2 : public CarlaPlugin, @@ -405,6 +595,7 @@ public: fEventsIn(), fEventsOut(), fLv2Options(), + fPipeServer(this), fCustomURIDs(), fFirstActive(true), fLastStateChunk(nullptr), @@ -461,9 +652,9 @@ public: { showCustomUI(false); - if (fUI.type == UI::TYPE_OSC) + if (fUI.type == UI::TYPE_BRIDGE) { - pData->osc.thread.stopThread(static_cast(pData->engine->getOptions().uiBridgesTimeout * 2)); + fPipeServer.stopPipeServer(pData->engine->getOptions().uiBridgesTimeout); } else { @@ -1131,23 +1322,28 @@ public: if (! yesNo) pData->transientTryCounter = 0; - if (fUI.type == UI::TYPE_OSC) + if (fUI.type == UI::TYPE_BRIDGE) { if (yesNo) { - pData->osc.data.clear(); - pData->osc.thread.startThread(); - } - else - { - if (pData->osc.data.target != nullptr) + if (fPipeServer.isPipeRunning()) { - osc_send_hide(pData->osc.data); - osc_send_quit(pData->osc.data); - pData->osc.data.clear(); + fPipeServer.writeFocusMessage(); + return; } - pData->osc.thread.stopThread(static_cast(pData->engine->getOptions().uiBridgesTimeout * 2)); + 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.writeUridMessage(CARLA_URI_MAP_ID_NULL, "Complete"); + + fPipeServer.writeShowMessage(); + } + else + { + fPipeServer.stopPipeServer(pData->engine->getOptions().uiBridgesTimeout); } return; } @@ -1324,13 +1520,10 @@ public: CARLA_SAFE_ASSERT_CONTINUE(fExt.worker != nullptr && fExt.worker->work != nullptr); fExt.worker->work(fHandle, carla_lv2_worker_respond, this, atom->size, LV2_ATOM_BODY_CONST(atom)); } - else if (fUI.type == UI::TYPE_OSC) + else if (fUI.type == UI::TYPE_BRIDGE) { - if (pData->osc.data.target != nullptr) - { - CarlaString chunk(CarlaString::asBase64(atom, lv2_atom_total_size(atom))); - osc_send_lv2_atom_transfer(pData->osc.data, portIndex, chunk.buffer()); - } + if (fPipeServer.isPipeRunning()) + fPipeServer.writeAtomMessage(portIndex, atom); } else { @@ -1367,6 +1560,25 @@ public: carla_safe_assert_int("latency >= 0", __FILE__, __LINE__, latency); } + if (fPipeServer.isPipeRunning()) + { + fPipeServer.idlePipe(); + + switch (fPipeServer.getAndResetUiState()) + { + case CarlaPipeServerLV2::UiNone: + case CarlaPipeServerLV2::UiShow: + break; + case CarlaPipeServerLV2::UiCrashed: + pData->engine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0.0f, nullptr); + break; + case CarlaPipeServerLV2::UiHide: + pData->engine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0.0f, nullptr); + fPipeServer.stopPipeServer(2000); + break; + } + } + if (fUI.handle != nullptr && fUI.descriptor != nullptr) { if (fUI.type == UI::TYPE_EXTERNAL && fUI.widget != nullptr) @@ -3753,19 +3965,6 @@ public: carla_debug("CarlaPluginLV2::clearBuffers() - end"); } - // ------------------------------------------------------------------- - // OSC stuff - - bool updateOscDataExtra() override - { - for (size_t i=CARLA_URI_MAP_ID_COUNT, count=fCustomURIDs.count(); i < count; ++i) - osc_send_lv2_urid_map(pData->osc.data, static_cast(i), fCustomURIDs.getAt(i, nullptr)); - - osc_send_lv2_urid_map(pData->osc.data, CARLA_URI_MAP_ID_NULL, "Complete"); - - return true; - } - // ------------------------------------------------------------------- // Post-poned UI Stuff @@ -3774,10 +3973,10 @@ public: CARLA_SAFE_ASSERT_RETURN(fUI.type != UI::TYPE_NULL,); CARLA_SAFE_ASSERT_RETURN(index < pData->param.count,); - if (fUI.type == UI::TYPE_OSC) + if (fUI.type == UI::TYPE_BRIDGE) { - if (pData->osc.data.target != nullptr) - osc_send_control(pData->osc.data, pData->param.data[index].rindex, value); + if (fPipeServer.isPipeRunning()) + fPipeServer.writeControlMessage(static_cast(pData->param.data[index].rindex), value); } else { @@ -3794,10 +3993,10 @@ public: CARLA_SAFE_ASSERT_RETURN(fUI.type != UI::TYPE_NULL,); CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,); - if (fUI.type == UI::TYPE_OSC) + if (fUI.type == UI::TYPE_BRIDGE) { - if (pData->osc.data.target != nullptr) - osc_send_midi_program(pData->osc.data, pData->midiprog.data[index].bank, pData->midiprog.data[index].program); + if (fPipeServer.isPipeRunning()) + fPipeServer.writeProgramMessage(index); } else { @@ -3813,16 +4012,10 @@ public: CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,); - if (fUI.type == UI::TYPE_OSC) + if (fUI.type == UI::TYPE_BRIDGE) { - if (pData->osc.data.target != nullptr) - { - uint8_t midiData[4] = { 0, 0, 0, 0 }; - midiData[1] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT)); - midiData[2] = note; - midiData[3] = velo; - osc_send_midi(pData->osc.data, midiData); - } + if (fPipeServer.isPipeRunning()) + fPipeServer.writeNoteMessage(false, channel, note, velo); } else { @@ -3846,15 +4039,10 @@ public: CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); - if (fUI.type == UI::TYPE_OSC) + if (fUI.type == UI::TYPE_BRIDGE) { - if (pData->osc.data.target != nullptr) - { - uint8_t midiData[4] = { 0, 0, 0, 0 }; - midiData[1] = uint8_t(MIDI_STATUS_NOTE_OFF | (channel & MIDI_CHANNEL_BIT)); - midiData[2] = note; - osc_send_midi(pData->osc.data, midiData); - } + if (fPipeServer.isPipeRunning()) + fPipeServer.writeNoteMessage(false, channel, note, 0); } else { @@ -4117,8 +4305,8 @@ public: fCustomURIDs.append(carla_strdup(uri)); - if (fUI.type == UI::TYPE_OSC && pData->osc.data.target != nullptr) - osc_send_lv2_urid_map(pData->osc.data, urid, uri); + if (fUI.type == UI::TYPE_BRIDGE && fPipeServer.isPipeRunning()) + fPipeServer.writeUridMessage(urid, uri); return urid; } @@ -4425,7 +4613,7 @@ public: const LV2_Atom* const atom((const LV2_Atom*)buffer); // plugins sometimes fail on this, not good... - CARLA_SAFE_ASSERT_INT2(bufferSize == lv2_atom_pad_size(lv2_atom_total_size(atom)), bufferSize, atom->size); + CARLA_SAFE_ASSERT_INT2(bufferSize == lv2_atom_total_size(atom), bufferSize, atom->size); for (uint32_t i=0; i < fEventsIn.count; ++i) { @@ -5071,13 +5259,13 @@ public: if (iFinal == eQt4 || iFinal == eQt5 || iFinal == eGtk2 || iFinal == eGtk3 || iFinal == eCocoa || iFinal == eWindows || iFinal == eX11 || iFinal == eExt) { // ----------------------------------------------------------- - // initialize osc-bridge + // initialize ui-bridge if (const char* const bridgeBinary = getUiBridgeBinary(uiType)) { - carla_stdout("Will use OSC-Bridge UI, binary: \"%s\"", bridgeBinary); - fUI.type = UI::TYPE_OSC; - pData->osc.thread.setOscData(bridgeBinary, fRdfDescriptor->URI, fUI.rdfDescriptor->URI, fUI.rdfDescriptor->Bundle); + carla_stdout("Will use UI-Bridge, binary: \"%s\"", bridgeBinary); + fUI.type = UI::TYPE_BRIDGE; + fPipeServer.setData(bridgeBinary, fRdfDescriptor->URI, fUI.rdfDescriptor->URI); delete[] bridgeBinary; return; } @@ -5350,6 +5538,7 @@ private: CarlaPluginLV2EventData fEventsIn; CarlaPluginLV2EventData fEventsOut; CarlaPluginLV2Options fLv2Options; + CarlaPipeServerLV2 fPipeServer; LinkedList fCustomURIDs; @@ -5382,10 +5571,10 @@ private: struct UI { enum Type { - TYPE_NULL, + TYPE_NULL = 0, + TYPE_BRIDGE, TYPE_EMBED, - TYPE_EXTERNAL, - TYPE_OSC + TYPE_EXTERNAL }; Type type; @@ -5912,45 +6101,83 @@ private: // ------------------------------------------------------------------------------------------------------------------- -#define lv2PluginPtr ((CarlaPluginLV2*)plugin) - -#ifndef BUILD_BRIDGE -int CarlaEngineOsc::handleMsgLv2AtomTransfer(CARLA_ENGINE_OSC_HANDLE_ARGS2) +bool CarlaPipeServerLV2::msgReceived(const char* const msg) noexcept { - CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "is"); - carla_debug("CarlaOsc::handleMsgLv2AtomTransfer()"); + if (std::strcmp(msg, "exiting") == 0) + { + closePipeServer(); + fUiState = UiHide; + return true; + } - const int32_t portIndex = argv[0]->i; - const char* const atomBuf = (const char*)&argv[1]->s; + if (std::strcmp(msg, "control") == 0) + { + uint32_t index; + float value; - CARLA_SAFE_ASSERT_RETURN(portIndex >= 0, 0); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true); - std::vector chunk(carla_getChunkFromBase64String(atomBuf)); - CARLA_SAFE_ASSERT_RETURN(chunk.size() > 0, 0); + try { + kPlugin->handleUIWrite(index, sizeof(float), CARLA_URI_MAP_ID_NULL, &value); + } CARLA_SAFE_EXCEPTION("magReceived control"); - const LV2_Atom* const atom((const LV2_Atom*)chunk.data()); - lv2PluginPtr->handleTransferAtom(static_cast(portIndex), atom); - return 0; -} + return true; + } -int CarlaEngineOsc::handleMsgLv2UridMap(CARLA_ENGINE_OSC_HANDLE_ARGS2) -{ - CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "is"); - carla_debug("CarlaOsc::handleMsgLv2UridMap()"); + if (std::strcmp(msg, "atom") == 0) + { + uint32_t index, size; + const char* base64atom; - const int32_t urid = argv[0]->i; - const char* const uri = (const char*)&argv[1]->s; + CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(size), true); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(base64atom), true); - CARLA_SAFE_ASSERT_RETURN(urid > 0, 0); + std::vector chunk(carla_getChunkFromBase64String(base64atom)); + delete[] base64atom; + CARLA_SAFE_ASSERT_RETURN(chunk.size() >= sizeof(LV2_Atom), true); - lv2PluginPtr->handleUridMap(static_cast(urid), uri); - return 0; -} -#endif + const LV2_Atom* const atom((const LV2_Atom*)chunk.data()); + CARLA_SAFE_ASSERT_RETURN(atom->size == chunk.size(), true); -#undef lv2PluginPtr + try { + kPlugin->handleUIWrite(index, lv2_atom_total_size(atom), CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT, atom); + } CARLA_SAFE_EXCEPTION("magReceived atom"); -#endif + return true; + } + + if (std::strcmp(msg, "program") == 0) + { + uint32_t index; + + CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true); + + try { + kPlugin->setMidiProgram(static_cast(index), false, true, true); + } CARLA_SAFE_EXCEPTION("msgReceived program"); + + return true; + } + + if (std::strcmp(msg, "urid") == 0) + { + uint32_t urid; + const char* uri; + + CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(urid), true); + CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(uri), true); + + if (urid != 0) + kPlugin->handleUridMap(urid, uri); + + delete[] uri; + return true; + } + + return false; +} // ------------------------------------------------------------------------------------------------------------------- @@ -5958,7 +6185,6 @@ CarlaPlugin* CarlaPlugin::newLV2(const Initializer& init) { carla_debug("CarlaPlugin::newLV2({%p, \"%s\", \"%s\", " P_INT64 "})", init.engine, init.name, init.label, init.uniqueId); -#if 0 CarlaPluginLV2* const plugin(new CarlaPluginLV2(init.engine, init.id)); if (! plugin->init(init.name, init.label)) @@ -5997,9 +6223,6 @@ CarlaPlugin* CarlaPlugin::newLV2(const Initializer& init) } return plugin; -#endif - init.engine->setLastError("LV2 plugins not working due to pending code rewrite."); - return nullptr; } // ------------------------------------------------------------------------------------------------------------------- diff --git a/source/bridges-ui/CarlaBridgeUI-LV2.cpp b/source/bridges-ui/CarlaBridgeUI-LV2.cpp index b77620be7..1d5133164 100644 --- a/source/bridges-ui/CarlaBridgeUI-LV2.cpp +++ b/source/bridges-ui/CarlaBridgeUI-LV2.cpp @@ -23,8 +23,7 @@ #include "juce_core.h" -#define URI_CARLA_FRONTEND_WIN_ID "http://kxstudio.sf.net/ns/carla/frontendWinId" -#define URI_CARLA_WORKER "http://kxstudio.sf.net/ns/carla/worker" +#define URI_CARLA_ATOM_WORKER "http://kxstudio.sf.net/ns/carla/atomWorker" using juce::File; @@ -32,9 +31,8 @@ CARLA_BRIDGE_START_NAMESPACE // ----------------------------------------------------- -//static uint32_t gBufferSize = 1024; -static int gBufferSizei = 1024; -static double gSampleRate = 44100.0; +static int gBufferSize = 1024; +static double gSampleRate = 44100.0; // Maximum default buffer size const unsigned int MAX_DEFAULT_BUFFER_SIZE = 8192; // 0x2000 @@ -62,30 +60,32 @@ const uint32_t CARLA_URI_MAP_ID_ATOM_TUPLE = 18; const uint32_t CARLA_URI_MAP_ID_ATOM_URI = 19; const uint32_t CARLA_URI_MAP_ID_ATOM_URID = 20; const uint32_t CARLA_URI_MAP_ID_ATOM_VECTOR = 21; -const uint32_t CARLA_URI_MAP_ID_ATOM_WORKER = 22; // custom -const uint32_t CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM = 23; -const uint32_t CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT = 24; -const uint32_t CARLA_URI_MAP_ID_BUF_MAX_LENGTH = 25; -const uint32_t CARLA_URI_MAP_ID_BUF_MIN_LENGTH = 26; -const uint32_t CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE = 27; -const uint32_t CARLA_URI_MAP_ID_LOG_ERROR = 28; -const uint32_t CARLA_URI_MAP_ID_LOG_NOTE = 29; -const uint32_t CARLA_URI_MAP_ID_LOG_TRACE = 30; -const uint32_t CARLA_URI_MAP_ID_LOG_WARNING = 31; -const uint32_t CARLA_URI_MAP_ID_TIME_POSITION = 32; // base type -const uint32_t CARLA_URI_MAP_ID_TIME_BAR = 33; // values -const uint32_t CARLA_URI_MAP_ID_TIME_BAR_BEAT = 34; -const uint32_t CARLA_URI_MAP_ID_TIME_BEAT = 35; -const uint32_t CARLA_URI_MAP_ID_TIME_BEAT_UNIT = 36; -const uint32_t CARLA_URI_MAP_ID_TIME_BEATS_PER_BAR = 37; -const uint32_t CARLA_URI_MAP_ID_TIME_BEATS_PER_MINUTE = 38; -const uint32_t CARLA_URI_MAP_ID_TIME_FRAME = 39; -const uint32_t CARLA_URI_MAP_ID_TIME_FRAMES_PER_SECOND = 40; -const uint32_t CARLA_URI_MAP_ID_TIME_SPEED = 41; +const uint32_t CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM = 22; +const uint32_t CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT = 23; +const uint32_t CARLA_URI_MAP_ID_BUF_MAX_LENGTH = 24; +const uint32_t CARLA_URI_MAP_ID_BUF_MIN_LENGTH = 25; +const uint32_t CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE = 26; +const uint32_t CARLA_URI_MAP_ID_LOG_ERROR = 27; +const uint32_t CARLA_URI_MAP_ID_LOG_NOTE = 28; +const uint32_t CARLA_URI_MAP_ID_LOG_TRACE = 29; +const uint32_t CARLA_URI_MAP_ID_LOG_WARNING = 30; +const uint32_t CARLA_URI_MAP_ID_TIME_POSITION = 31; // base type +const uint32_t CARLA_URI_MAP_ID_TIME_BAR = 32; // values +const uint32_t CARLA_URI_MAP_ID_TIME_BAR_BEAT = 33; +const uint32_t CARLA_URI_MAP_ID_TIME_BEAT = 34; +const uint32_t CARLA_URI_MAP_ID_TIME_BEAT_UNIT = 35; +const uint32_t CARLA_URI_MAP_ID_TIME_BEATS_PER_BAR = 36; +const uint32_t CARLA_URI_MAP_ID_TIME_BEATS_PER_MINUTE = 37; +const uint32_t CARLA_URI_MAP_ID_TIME_FRAME = 38; +const uint32_t CARLA_URI_MAP_ID_TIME_FRAMES_PER_SECOND = 39; +const uint32_t CARLA_URI_MAP_ID_TIME_SPEED = 40; +const uint32_t CARLA_URI_MAP_ID_TIME_TICKS_PER_BEAT = 41; const uint32_t CARLA_URI_MAP_ID_MIDI_EVENT = 42; const uint32_t CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE = 43; -const uint32_t CARLA_URI_MAP_ID_FRONTEND_WIN_ID = 44; -const uint32_t CARLA_URI_MAP_ID_COUNT = 45; +const uint32_t CARLA_URI_MAP_ID_UI_WINDOW_TITLE = 44; +const uint32_t CARLA_URI_MAP_ID_CARLA_ATOM_WORKER = 45; +const uint32_t CARLA_URI_MAP_ID_CARLA_TRANSIENT_WIN_ID = 46; +const uint32_t CARLA_URI_MAP_ID_COUNT = 47; // LV2 Feature Ids const uint32_t kFeatureIdLogs = 0; @@ -116,7 +116,9 @@ struct Lv2PluginOptions { SequenceSize, SampleRate, FrontendWinId, - Null + //WindowTitle, + Null, + Count }; int maxBufferSize; @@ -124,14 +126,16 @@ struct Lv2PluginOptions { int sequenceSize; double sampleRate; int64_t frontendWinId; - LV2_Options_Option opts[6]; + const char* windowTitle; + LV2_Options_Option opts[Count]; - Lv2PluginOptions() + Lv2PluginOptions() noexcept : maxBufferSize(0), minBufferSize(0), sequenceSize(MAX_DEFAULT_BUFFER_SIZE), sampleRate(0.0), - frontendWinId(0) + frontendWinId(0), + windowTitle(nullptr) { LV2_Options_Option& optMaxBlockLenth(opts[MaxBlockLenth]); optMaxBlockLenth.context = LV2_OPTIONS_INSTANCE; @@ -168,11 +172,21 @@ struct Lv2PluginOptions { LV2_Options_Option& optFrontendWinId(opts[FrontendWinId]); optFrontendWinId.context = LV2_OPTIONS_INSTANCE; optFrontendWinId.subject = 0; - optFrontendWinId.key = CARLA_URI_MAP_ID_FRONTEND_WIN_ID; + optFrontendWinId.key = CARLA_URI_MAP_ID_CARLA_TRANSIENT_WIN_ID; optFrontendWinId.size = sizeof(int64_t); optFrontendWinId.type = CARLA_URI_MAP_ID_ATOM_LONG; optFrontendWinId.value = &frontendWinId; + /* + LV2_Options_Option& optWindowTitle(opts[WindowTitle]); + optWindowTitle.context = LV2_OPTIONS_INSTANCE; + optWindowTitle.subject = 0; + optWindowTitle.key = CARLA_URI_MAP_ID_UI_WINDOW_TITLE; + optWindowTitle.size = 0; + optWindowTitle.type = CARLA_URI_MAP_ID_ATOM_STRING; + optWindowTitle.value = nullptr; + */ + LV2_Options_Option& optNull(opts[Null]); optNull.context = LV2_OPTIONS_INSTANCE; optNull.subject = 0; @@ -209,8 +223,8 @@ public: // --------------------------------------------------------------- // initialize options - fLv2Options.minBufferSize = gBufferSizei; - fLv2Options.maxBufferSize = gBufferSizei; + fLv2Options.minBufferSize = gBufferSize; + fLv2Options.maxBufferSize = gBufferSize; fLv2Options.sampleRate = gSampleRate; // --------------------------------------------------------------- @@ -604,11 +618,11 @@ public: return urid; } - const char* getCustomURIString(const LV2_URID urid) const noexcept + const char* getCustomURIDString(const LV2_URID urid) const noexcept { CARLA_SAFE_ASSERT_RETURN(urid != CARLA_URI_MAP_ID_NULL, nullptr); CARLA_SAFE_ASSERT_RETURN(urid < fCustomURIDs.count(), nullptr); - carla_debug("CarlaLv2Client::getCustomURIString(%i)", urid); + carla_debug("CarlaLv2Client::getCustomURIDString(%i)", urid); return fCustomURIDs.getAt(urid, nullptr); } @@ -935,18 +949,22 @@ private: return CARLA_URI_MAP_ID_TIME_FRAMES_PER_SECOND; if (std::strcmp(uri, LV2_TIME__speed) == 0) return CARLA_URI_MAP_ID_TIME_SPEED; + if (std::strcmp(uri, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat) == 0) + return CARLA_URI_MAP_ID_TIME_TICKS_PER_BEAT; // Others if (std::strcmp(uri, LV2_MIDI__MidiEvent) == 0) return CARLA_URI_MAP_ID_MIDI_EVENT; if (std::strcmp(uri, LV2_PARAMETERS__sampleRate) == 0) return CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE; + if (std::strcmp(uri, LV2_UI__windowTitle) == 0) + return CARLA_URI_MAP_ID_UI_WINDOW_TITLE; // Custom - if (std::strcmp(uri, URI_CARLA_FRONTEND_WIN_ID) == 0) - return CARLA_URI_MAP_ID_FRONTEND_WIN_ID; - if (std::strcmp(uri, URI_CARLA_WORKER) == 0) - return CARLA_URI_MAP_ID_ATOM_WORKER; + if (std::strcmp(uri, LV2_KXSTUDIO_PROPERTIES__TransientWindowId) == 0) + return CARLA_URI_MAP_ID_CARLA_TRANSIENT_WIN_ID; + if (std::strcmp(uri, URI_CARLA_ATOM_WORKER) == 0) + return CARLA_URI_MAP_ID_CARLA_ATOM_WORKER; // Custom types return ((CarlaLv2Client*)handle)->getCustomURID(uri); @@ -1001,8 +1019,6 @@ private: return LV2_ATOM__URID; if (urid == CARLA_URI_MAP_ID_ATOM_VECTOR) return LV2_ATOM__Vector; - if (urid == CARLA_URI_MAP_ID_ATOM_WORKER) - return URI_CARLA_WORKER; // custom if (urid == CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM) return LV2_ATOM__atomTransfer; if (urid == CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT) @@ -1047,17 +1063,25 @@ private: return LV2_TIME__framesPerSecond; if (urid == CARLA_URI_MAP_ID_TIME_SPEED) return LV2_TIME__speed; + if (urid == CARLA_URI_MAP_ID_TIME_TICKS_PER_BEAT) + return LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat; // 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 (urid == CARLA_URI_MAP_ID_FRONTEND_WIN_ID) - return URI_CARLA_FRONTEND_WIN_ID; + if (urid == CARLA_URI_MAP_ID_UI_WINDOW_TITLE) + return LV2_UI__windowTitle; + + // Custom + if (urid == CARLA_URI_MAP_ID_CARLA_ATOM_WORKER) + return URI_CARLA_ATOM_WORKER; + if (urid == CARLA_URI_MAP_ID_CARLA_TRANSIENT_WIN_ID) + return LV2_KXSTUDIO_PROPERTIES__TransientWindowId; // Custom types - return ((CarlaLv2Client*)handle)->getCustomURIString(urid); + return ((CarlaLv2Client*)handle)->getCustomURIDString(urid); } // ------------------------------------------------------------------- diff --git a/source/includes/CarlaNativeExtUI.hpp b/source/includes/CarlaNativeExtUI.hpp index ec011f828..5d026bc22 100644 --- a/source/includes/CarlaNativeExtUI.hpp +++ b/source/includes/CarlaNativeExtUI.hpp @@ -49,6 +49,7 @@ protected: { if (isPipeRunning()) { + const CarlaMutexLocker cml(getPipeLock()); writeMessage("focus\n", 6); flushMessages(); return;