|
- /*
- * Carla Bridge UI, LV2 version
- * Copyright (C) 2011-2014 Filipe Coelho <falktx@falktx.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * For a full copy of the GNU General Public License see the doc/GPL.txt file.
- */
-
- #include "CarlaBridgeClient.hpp"
- #include "CarlaBase64Utils.hpp"
- #include "CarlaLv2Utils.hpp"
- #include "CarlaMIDI.h"
- #include "LinkedList.hpp"
-
- #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"
-
- using juce::File;
-
- CARLA_BRIDGE_START_NAMESPACE
-
- // -----------------------------------------------------
-
- //static uint32_t gBufferSize = 1024;
- static int gBufferSizei = 1024;
- static double gSampleRate = 44100.0;
-
- // Maximum default buffer size
- const unsigned int MAX_DEFAULT_BUFFER_SIZE = 8192; // 0x2000
-
- // LV2 URI Map Ids
- const uint32_t CARLA_URI_MAP_ID_NULL = 0;
- const uint32_t CARLA_URI_MAP_ID_ATOM_BLANK = 1;
- const uint32_t CARLA_URI_MAP_ID_ATOM_BOOL = 2;
- const uint32_t CARLA_URI_MAP_ID_ATOM_CHUNK = 3;
- const uint32_t CARLA_URI_MAP_ID_ATOM_DOUBLE = 4;
- const uint32_t CARLA_URI_MAP_ID_ATOM_EVENT = 5;
- const uint32_t CARLA_URI_MAP_ID_ATOM_FLOAT = 6;
- const uint32_t CARLA_URI_MAP_ID_ATOM_INT = 7;
- const uint32_t CARLA_URI_MAP_ID_ATOM_LITERAL = 8;
- const uint32_t CARLA_URI_MAP_ID_ATOM_LONG = 9;
- const uint32_t CARLA_URI_MAP_ID_ATOM_NUMBER = 10;
- const uint32_t CARLA_URI_MAP_ID_ATOM_OBJECT = 11;
- const uint32_t CARLA_URI_MAP_ID_ATOM_PATH = 12;
- const uint32_t CARLA_URI_MAP_ID_ATOM_PROPERTY = 13;
- const uint32_t CARLA_URI_MAP_ID_ATOM_RESOURCE = 14;
- const uint32_t CARLA_URI_MAP_ID_ATOM_SEQUENCE = 15;
- const uint32_t CARLA_URI_MAP_ID_ATOM_SOUND = 16;
- const uint32_t CARLA_URI_MAP_ID_ATOM_STRING = 17;
- 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_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;
-
- // LV2 Feature Ids
- const uint32_t kFeatureIdLogs = 0;
- const uint32_t kFeatureIdOptions = 1;
- const uint32_t kFeatureIdPrograms = 2;
- const uint32_t kFeatureIdStateMakePath = 3;
- const uint32_t kFeatureIdStateMapPath = 4;
- const uint32_t kFeatureIdUriMap = 5;
- const uint32_t kFeatureIdUridMap = 6;
- const uint32_t kFeatureIdUridUnmap = 7;
- const uint32_t kFeatureIdUiIdleInterface = 8;
- const uint32_t kFeatureIdUiFixedSize = 9;
- const uint32_t kFeatureIdUiMakeResident = 10;
- const uint32_t kFeatureIdUiNoUserResize = 11;
- const uint32_t kFeatureIdUiParent = 12;
- const uint32_t kFeatureIdUiPortMap = 13;
- const uint32_t kFeatureIdUiPortSubscribe = 14;
- const uint32_t kFeatureIdUiResize = 15;
- const uint32_t kFeatureIdUiTouch = 16;
- const uint32_t kFeatureCount = 17;
-
- // -------------------------------------------------------------------------
-
- struct Lv2PluginOptions {
- enum OptIndex {
- MaxBlockLenth = 0,
- MinBlockLenth,
- SequenceSize,
- SampleRate,
- FrontendWinId,
- Null
- };
-
- int maxBufferSize;
- int minBufferSize;
- int sequenceSize;
- double sampleRate;
- int64_t frontendWinId;
- LV2_Options_Option opts[6];
-
- Lv2PluginOptions()
- : maxBufferSize(0),
- minBufferSize(0),
- sequenceSize(MAX_DEFAULT_BUFFER_SIZE),
- sampleRate(0.0),
- frontendWinId(0)
- {
- LV2_Options_Option& optMaxBlockLenth(opts[MaxBlockLenth]);
- optMaxBlockLenth.context = LV2_OPTIONS_INSTANCE;
- optMaxBlockLenth.subject = 0;
- optMaxBlockLenth.key = CARLA_URI_MAP_ID_BUF_MAX_LENGTH;
- optMaxBlockLenth.size = sizeof(int);
- optMaxBlockLenth.type = CARLA_URI_MAP_ID_ATOM_INT;
- optMaxBlockLenth.value = &maxBufferSize;
-
- LV2_Options_Option& optMinBlockLenth(opts[MinBlockLenth]);
- optMinBlockLenth.context = LV2_OPTIONS_INSTANCE;
- optMinBlockLenth.subject = 0;
- optMinBlockLenth.key = CARLA_URI_MAP_ID_BUF_MIN_LENGTH;
- optMinBlockLenth.size = sizeof(int);
- optMinBlockLenth.type = CARLA_URI_MAP_ID_ATOM_INT;
- optMinBlockLenth.value = &minBufferSize;
-
- LV2_Options_Option& optSequenceSize(opts[SequenceSize]);
- optSequenceSize.context = LV2_OPTIONS_INSTANCE;
- optSequenceSize.subject = 0;
- optSequenceSize.key = CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE;
- optSequenceSize.size = sizeof(int);
- optSequenceSize.type = CARLA_URI_MAP_ID_ATOM_INT;
- optSequenceSize.value = &sequenceSize;
-
- LV2_Options_Option& optSampleRate(opts[SampleRate]);
- optSampleRate.context = LV2_OPTIONS_INSTANCE;
- optSampleRate.subject = 0;
- optSampleRate.key = CARLA_URI_MAP_ID_PARAM_SAMPLE_RATE;
- optSampleRate.size = sizeof(double);
- optSampleRate.type = CARLA_URI_MAP_ID_ATOM_DOUBLE;
- optSampleRate.value = &sampleRate;
-
- LV2_Options_Option& optFrontendWinId(opts[FrontendWinId]);
- optFrontendWinId.context = LV2_OPTIONS_INSTANCE;
- optFrontendWinId.subject = 0;
- optFrontendWinId.key = CARLA_URI_MAP_ID_FRONTEND_WIN_ID;
- optFrontendWinId.size = sizeof(int64_t);
- optFrontendWinId.type = CARLA_URI_MAP_ID_ATOM_LONG;
- optFrontendWinId.value = &frontendWinId;
-
- LV2_Options_Option& optNull(opts[Null]);
- optNull.context = LV2_OPTIONS_INSTANCE;
- optNull.subject = 0;
- optNull.key = CARLA_URI_MAP_ID_NULL;
- optNull.size = 0;
- optNull.type = CARLA_URI_MAP_ID_NULL;
- optNull.value = nullptr;
- }
- };
-
- // -------------------------------------------------------------------------
-
- class CarlaLv2Client : public CarlaBridgeClient
- {
- public:
- CarlaLv2Client(const char* const uiTitle)
- : CarlaBridgeClient(uiTitle),
- fHandle(nullptr),
- fWidget(nullptr),
- fDescriptor(nullptr),
- fRdfDescriptor(nullptr),
- fRdfUiDescriptor(nullptr),
- fOptions(),
- fIsReady(false),
- #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11)
- fIsResizable(false),
- #else
- fIsResizable(true),
- #endif
- fCustomURIDs(),
- fExt(),
- leakDetector_CarlaLv2Client()
- {
- carla_fill<LV2_Feature*>(fFeatures, nullptr, kFeatureCount+1);
-
- for (uint32_t i=0; i < CARLA_URI_MAP_ID_COUNT; ++i)
- fCustomURIDs.append(nullptr);
-
- // ---------------------------------------------------------------
- // initialize options
-
- fOptions.minBufferSize = gBufferSizei;
- fOptions.maxBufferSize = gBufferSizei;
- fOptions.sampleRate = gSampleRate;
-
- // ---------------------------------------------------------------
- // initialize features (part 1)
-
- LV2_Log_Log* const logFt = new LV2_Log_Log;
- logFt->handle = this;
- logFt->printf = carla_lv2_log_printf;
- logFt->vprintf = carla_lv2_log_vprintf;
-
- LV2_State_Make_Path* const stateMakePathFt = new LV2_State_Make_Path;
- stateMakePathFt->handle = this;
- stateMakePathFt->path = carla_lv2_state_make_path;
-
- LV2_State_Map_Path* const stateMapPathFt = new LV2_State_Map_Path;
- stateMapPathFt->handle = this;
- stateMapPathFt->abstract_path = carla_lv2_state_map_abstract_path;
- stateMapPathFt->absolute_path = carla_lv2_state_map_absolute_path;
-
- LV2_Programs_Host* const programsFt = new LV2_Programs_Host;
- programsFt->handle = this;
- programsFt->program_changed = carla_lv2_program_changed;
-
- LV2_URI_Map_Feature* const uriMapFt = new LV2_URI_Map_Feature;
- uriMapFt->callback_data = this;
- uriMapFt->uri_to_id = carla_lv2_uri_to_id;
-
- LV2_URID_Map* const uridMapFt = new LV2_URID_Map;
- uridMapFt->handle = this;
- uridMapFt->map = carla_lv2_urid_map;
-
- LV2_URID_Unmap* const uridUnmapFt = new LV2_URID_Unmap;
- uridUnmapFt->handle = this;
- uridUnmapFt->unmap = carla_lv2_urid_unmap;
-
- LV2UI_Port_Map* const uiPortMapFt = new LV2UI_Port_Map;
- uiPortMapFt->handle = this;
- uiPortMapFt->port_index = carla_lv2_ui_port_map;
-
- LV2UI_Resize* const uiResizeFt = new LV2UI_Resize;
- uiResizeFt->handle = this;
- uiResizeFt->ui_resize = carla_lv2_ui_resize;
-
- // ---------------------------------------------------------------
- // initialize features (part 2)
-
- for (uint32_t i=0; i < kFeatureCount; ++i)
- fFeatures[i] = new LV2_Feature;
-
- fFeatures[kFeatureIdLogs]->URI = LV2_LOG__log;
- fFeatures[kFeatureIdLogs]->data = logFt;
-
- fFeatures[kFeatureIdOptions]->URI = LV2_OPTIONS__options;
- fFeatures[kFeatureIdOptions]->data = fOptions.opts;
-
- fFeatures[kFeatureIdPrograms]->URI = LV2_PROGRAMS__Host;
- fFeatures[kFeatureIdPrograms]->data = programsFt;
-
- fFeatures[kFeatureIdStateMakePath]->URI = LV2_STATE__makePath;
- fFeatures[kFeatureIdStateMakePath]->data = stateMakePathFt;
-
- fFeatures[kFeatureIdStateMapPath]->URI = LV2_STATE__mapPath;
- fFeatures[kFeatureIdStateMapPath]->data = stateMapPathFt;
-
- fFeatures[kFeatureIdUriMap]->URI = LV2_URI_MAP_URI;
- fFeatures[kFeatureIdUriMap]->data = uriMapFt;
-
- fFeatures[kFeatureIdUridMap]->URI = LV2_URID__map;
- fFeatures[kFeatureIdUridMap]->data = uridMapFt;
-
- fFeatures[kFeatureIdUridUnmap]->URI = LV2_URID__unmap;
- fFeatures[kFeatureIdUridUnmap]->data = uridUnmapFt;
-
- fFeatures[kFeatureIdUiIdleInterface]->URI = LV2_UI__idleInterface;
- fFeatures[kFeatureIdUiIdleInterface]->data = nullptr;
-
- fFeatures[kFeatureIdUiFixedSize]->URI = LV2_UI__fixedSize;
- fFeatures[kFeatureIdUiFixedSize]->data = nullptr;
-
- fFeatures[kFeatureIdUiMakeResident]->URI = LV2_UI__makeResident;
- fFeatures[kFeatureIdUiMakeResident]->data = nullptr;
-
- fFeatures[kFeatureIdUiNoUserResize]->URI = LV2_UI__noUserResize;
- fFeatures[kFeatureIdUiNoUserResize]->data = nullptr;
-
- fFeatures[kFeatureIdUiParent]->URI = LV2_UI__parent;
- fFeatures[kFeatureIdUiParent]->data = nullptr;
-
- fFeatures[kFeatureIdUiPortMap]->URI = LV2_UI__portMap;
- fFeatures[kFeatureIdUiPortMap]->data = uiPortMapFt;
-
- fFeatures[kFeatureIdUiPortSubscribe]->URI = LV2_UI__portSubscribe;
- fFeatures[kFeatureIdUiPortSubscribe]->data = nullptr;
-
- fFeatures[kFeatureIdUiResize]->URI = LV2_UI__resize;
- fFeatures[kFeatureIdUiResize]->data = uiResizeFt;
-
- fFeatures[kFeatureIdUiTouch]->URI = LV2_UI__touch;
- fFeatures[kFeatureIdUiTouch]->data = nullptr;
- }
-
- ~CarlaLv2Client() override
- {
- if (fRdfDescriptor != nullptr)
- delete fRdfDescriptor;
-
- delete (LV2_Log_Log*)fFeatures[kFeatureIdLogs]->data;
- delete (LV2_State_Make_Path*)fFeatures[kFeatureIdStateMakePath]->data;
- delete (LV2_State_Map_Path*)fFeatures[kFeatureIdStateMapPath]->data;
- delete (LV2_Programs_Host*)fFeatures[kFeatureIdPrograms]->data;
- delete (LV2_URI_Map_Feature*)fFeatures[kFeatureIdUriMap]->data;
- delete (LV2_URID_Map*)fFeatures[kFeatureIdUridMap]->data;
- delete (LV2_URID_Unmap*)fFeatures[kFeatureIdUridUnmap]->data;
- delete (LV2UI_Port_Map*)fFeatures[kFeatureIdUiPortMap]->data;
- delete (LV2UI_Resize*)fFeatures[kFeatureIdUiResize]->data;
-
- for (uint32_t i=0; i < kFeatureCount; ++i)
- {
- if (fFeatures[i] != nullptr)
- {
- delete fFeatures[i];
- fFeatures[i] = nullptr;
- }
- }
-
- for (LinkedList<const char*>::Itenerator it = fCustomURIDs.begin(); it.valid(); it.next())
- {
- const char* const uri(it.getValue());
-
- if (uri != nullptr)
- delete[] uri;
- }
-
- fCustomURIDs.clear();
- }
-
- // ---------------------------------------------------------------------
- // ui initialization
-
- bool uiInit(const char* pluginURI, const char* uiURI, const char* uiBundle) override
- {
- // -----------------------------------------------------------------
- // load bundle
-
- Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
-
- Lilv::Node bundleNode(lv2World.new_file_uri(nullptr, uiBundle));
- CARLA_SAFE_ASSERT_RETURN(bundleNode.is_uri(), false);
-
- CarlaString sBundle(bundleNode.as_uri());
-
- if (! sBundle.endsWith("/"))
- sBundle += "/";
-
- lv2World.load_bundle(sBundle);
-
- // -----------------------------------------------------------------
- // init
-
- CarlaBridgeClient::uiInit(pluginURI, uiURI, uiBundle);
-
- // -----------------------------------------------------------------
- // get plugin from lv2_rdf (lilv)
-
- fRdfDescriptor = lv2_rdf_new(pluginURI, true);
-
- if (fRdfDescriptor == nullptr)
- return false;
-
- // -----------------------------------------------------------------
- // find requested UI
-
- for (uint32_t i=0; i < fRdfDescriptor->UICount; ++i)
- {
- if (std::strcmp(fRdfDescriptor->UIs[i].URI, uiURI) == 0)
- {
- fRdfUiDescriptor = &fRdfDescriptor->UIs[i];
- break;
- }
- }
-
- if (fRdfUiDescriptor == nullptr)
- {
- carla_stderr("Failed to find requested UI");
- return false;
- }
-
- // -----------------------------------------------------------------
- // open DLL
-
- if (! uiLibOpen(fRdfUiDescriptor->Binary))
- {
- carla_stderr("Failed to load UI binary, error was:\n%s", uiLibError());
- return false;
- }
-
- // -----------------------------------------------------------------
- // get DLL main entry
-
- const LV2UI_DescriptorFunction ui_descFn = (LV2UI_DescriptorFunction)uiLibSymbol("lv2ui_descriptor");
-
- if (ui_descFn == nullptr)
- return false;
-
- // -----------------------------------------------------------
- // get descriptor that matches URI
-
- uint32_t i = 0;
- while ((fDescriptor = ui_descFn(i++)))
- {
- if (std::strcmp(fDescriptor->URI, uiURI) == 0)
- break;
- }
-
- if (fDescriptor == nullptr)
- {
- carla_stderr("Failed to find UI descriptor");
- return false;
- }
-
- // -----------------------------------------------------------
- // initialize UI
-
- #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11)
- fFeatures[kFeatureIdUiParent]->data = getContainerId();
- #endif
-
- fHandle = fDescriptor->instantiate(fDescriptor, fRdfDescriptor->URI, fRdfUiDescriptor->Bundle, carla_lv2_ui_write_function, this, &fWidget, fFeatures);
-
- if (fHandle == nullptr)
- {
- carla_stderr("Failed to init UI");
- return false;
- }
-
- // -----------------------------------------------------------
- // check if not resizable
-
- for (uint32_t j=0; j < fRdfUiDescriptor->FeatureCount && fIsResizable; ++j)
- {
- if (std::strcmp(fRdfUiDescriptor->Features[j].URI, LV2_UI__fixedSize ) == 0 ||
- std::strcmp(fRdfUiDescriptor->Features[j].URI, LV2_UI__noUserResize) == 0)
- {
- fIsResizable = false;
- break;
- }
- }
-
- // -----------------------------------------------------------
- // check for known extensions
-
- if (fDescriptor->extension_data != nullptr)
- {
- fExt.programs = (const LV2_Programs_UI_Interface*)fDescriptor->extension_data(LV2_PROGRAMS__UIInterface);
- fExt.options = (const LV2_Options_Interface*)fDescriptor->extension_data(LV2_OPTIONS__interface);
- fExt.idle = (const LV2UI_Idle_Interface*)fDescriptor->extension_data(LV2_UI__idleInterface);
-
- // check if invalid
- if (fExt.programs != nullptr && fExt.programs->select_program == nullptr)
- fExt.programs = nullptr;
- if (fExt.idle != nullptr && fExt.idle->idle == nullptr)
- fExt.idle = nullptr;
- }
-
- return true;
- }
-
- void uiIdle() override
- {
- if (fHandle != nullptr && fExt.idle != nullptr)
- fExt.idle->idle(fHandle);
- }
-
- void uiClose() override
- {
- if (fHandle != nullptr && fDescriptor != nullptr && fDescriptor->cleanup != nullptr)
- {
- fDescriptor->cleanup(fHandle);
- fHandle = nullptr;
- }
-
- CarlaBridgeClient::uiClose();
- uiLibClose();
- }
-
- // ---------------------------------------------------------------------
- // ui management
-
- void* getWidget() const override
- {
- return fWidget;
- }
-
- bool isResizable() const override
- {
- return fIsResizable;
- }
-
- // ---------------------------------------------------------------------
- // ui processing
-
- void setParameter(const int32_t rindex, const float value) override
- {
- CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,)
- CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
- CARLA_SAFE_ASSERT_RETURN(rindex >= 0,)
-
- if (fDescriptor->port_event == nullptr)
- return;
-
- fDescriptor->port_event(fHandle, static_cast<uint32_t>(rindex), sizeof(float), 0, &value);
- }
-
- void setProgram(const uint32_t) override
- {
- }
-
- void setMidiProgram(const uint32_t bank, const uint32_t program) override
- {
- CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,)
-
- if (fExt.programs == nullptr)
- return;
-
- fExt.programs->select_program(fHandle, bank, program);
- }
-
- void noteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) override
- {
- CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,)
- CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
-
- if (fDescriptor->port_event == nullptr)
- return;
-
- LV2_Atom_MidiEvent midiEv;
- midiEv.event.time.frames = 0;
- midiEv.event.body.type = CARLA_URI_MAP_ID_MIDI_EVENT;
- midiEv.event.body.size = 3;
- midiEv.data[0] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT));
- midiEv.data[1] = note;
- midiEv.data[2] = velo;
-
- fDescriptor->port_event(fHandle, 0, 3, CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM, &midiEv);
- }
-
- void noteOff(const uint8_t channel, const uint8_t note) override
- {
- CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,)
- CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
-
- if (fDescriptor->port_event == nullptr)
- return;
-
- LV2_Atom_MidiEvent midiEv;
- midiEv.event.time.frames = 0;
- midiEv.event.body.type = CARLA_URI_MAP_ID_MIDI_EVENT;
- midiEv.event.body.size = 3;
- midiEv.data[0] = uint8_t(MIDI_STATUS_NOTE_OFF | (channel & MIDI_CHANNEL_BIT));
- midiEv.data[1] = note;
- midiEv.data[2] = 0;
-
- fDescriptor->port_event(fHandle, 0, 3, CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM, &midiEv);
- }
-
- // ---------------------------------------------------------------------
-
- void waitForOscURIs()
- {
- sendOscUpdate();
-
- for (;;)
- {
- if (fIsReady || ! oscIdle(true))
- return;
- }
- }
-
- // ---------------------------------------------------------------------
-
- LV2_URID getCustomURID(const char* const uri)
- {
- CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', CARLA_URI_MAP_ID_NULL);
- carla_debug("CarlaLv2Client::getCustomURID(\"%s\")", uri);
-
- LV2_URID urid = CARLA_URI_MAP_ID_NULL;
-
- for (uint32_t i=0, count=static_cast<uint32_t>(fCustomURIDs.count()); i<count; ++i)
- {
- const char* const thisUri(fCustomURIDs.getAt(i, nullptr));
-
- if (thisUri != nullptr && std::strcmp(thisUri, uri) == 0)
- {
- urid = i;
- break;
- }
- }
-
- if (urid == CARLA_URI_MAP_ID_NULL)
- {
- urid = static_cast<LV2_URID>(fCustomURIDs.count());
- fCustomURIDs.append(carla_strdup(uri));
- }
-
- if (isOscControlRegistered())
- sendOscLv2UridMap(urid, uri);
-
- return urid;
- }
-
- const char* getCustomURIString(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);
-
- return fCustomURIDs.getAt(urid, nullptr);
- }
-
- // ---------------------------------------------------------------------
-
- void handleProgramChanged(const int32_t /*index*/)
- {
- if (isOscControlRegistered())
- sendOscConfigure("reloadprograms", "");
- }
-
- uint32_t handleUiPortMap(const char* const symbol)
- {
- CARLA_SAFE_ASSERT_RETURN(symbol != nullptr && symbol[0] != '\0', LV2UI_INVALID_PORT_INDEX);
- carla_debug("CarlaLv2Client::handleUiPortMap(\"%s\")", symbol);
-
- for (uint32_t i=0; i < fRdfDescriptor->PortCount; ++i)
- {
- if (std::strcmp(fRdfDescriptor->Ports[i].Symbol, symbol) == 0)
- return i;
- }
-
- return LV2UI_INVALID_PORT_INDEX;
- }
-
- int handleUiResize(const int width, const int height)
- {
- CARLA_SAFE_ASSERT_RETURN(width > 0, 1);
- CARLA_SAFE_ASSERT_RETURN(height > 0, 1);
- carla_debug("CarlaLv2Client::handleUiResize(%i, %i)", width, height);
-
- toolkitResize(width, height);
-
- return 0;
- }
-
- void handleUiWrite(uint32_t portIndex, uint32_t bufferSize, uint32_t format, const void* buffer)
- {
- CARLA_SAFE_ASSERT_RETURN(buffer != nullptr,);
- CARLA_SAFE_ASSERT_RETURN(bufferSize > 0,);
- carla_debug("CarlaLv2Client::handleUiWrite(%i, %i, %i, %p)", portIndex, bufferSize, format, buffer);
-
- if (format == 0)
- {
- CARLA_ASSERT(buffer != nullptr);
- CARLA_ASSERT(bufferSize == sizeof(float));
-
- if (bufferSize != sizeof(float))
- return;
-
- if (buffer == nullptr || bufferSize != sizeof(float))
- return;
-
- const float value(*(const float*)buffer);
-
- if (isOscControlRegistered())
- sendOscControl(static_cast<int32_t>(portIndex), value);
- }
- else if (format == CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM || CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT)
- {
- CARLA_ASSERT(bufferSize != 0);
- CARLA_ASSERT(buffer != nullptr);
-
- if (bufferSize == 0 || buffer == nullptr)
- return;
-
- if (isOscControlRegistered())
- sendOscLv2AtomTransfer(portIndex, CarlaString::asBase64(buffer, bufferSize).buffer());
- }
- else
- {
- carla_stdout("CarlaLv2Client::handleUiWrite(%i, %i, %i:\"%s\", %p) - unknown format", portIndex, bufferSize, format, carla_lv2_urid_unmap(this, format), buffer);
- }
- }
-
- // ---------------------------------------------------------------------
-
- void handleAtomTransfer(const uint32_t portIndex, const LV2_Atom* const atom)
- {
- CARLA_ASSERT(atom != nullptr);
- carla_debug("CarlaLv2Client::handleTransferEvent(%i, %p)", portIndex, atom);
-
- if (atom != nullptr && fHandle != nullptr && fDescriptor != nullptr && fDescriptor->port_event != nullptr)
- fDescriptor->port_event(fHandle, portIndex, lv2_atom_total_size(atom), CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT, atom);
- }
-
- void handleUridMap(const LV2_URID urid, const char* const uri)
- {
- CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0',);
- carla_stdout("CarlaLv2Client::handleUridMap(%i, \"%s\")", urid, uri);
-
- if (urid == CARLA_URI_MAP_ID_NULL)
- {
- CARLA_SAFE_ASSERT_RETURN(std::strcmp(uri, "Complete") == 0,);
- carla_stdout("URID map from host complete");
- fIsReady = true;
- return;
- }
-
- const uint32_t uridCount(static_cast<uint32_t>(fCustomURIDs.count()));
-
- if (urid < uridCount)
- {
- if (const char* const ourURI = carla_lv2_urid_unmap(this, urid))
- {
- if (std::strcmp(ourURI, uri) != 0)
- carla_stderr2("UI :: wrong URI '%s' vs '%s'", ourURI, uri);
- }
- else
- {
- uint32_t i=0;
- for (LinkedList<const char*>::Itenerator it = fCustomURIDs.begin(); it.valid(); it.next())
- {
- if (i != urid)
- continue;
- CARLA_SAFE_ASSERT(it.getValue() == nullptr);
- it.setValue(carla_strdup(uri));
- break;
- }
- }
- }
- else if (urid > uridCount)
- {
- for (uint32_t i=uridCount; i < urid; ++i)
- fCustomURIDs.append(nullptr);
-
- fCustomURIDs.append(carla_strdup(uri));
- }
- else // urid == uridCount
- {
- fCustomURIDs.append(carla_strdup(uri));
- }
- }
-
- private:
- LV2UI_Handle fHandle;
- LV2UI_Widget fWidget;
- LV2_Feature* fFeatures[kFeatureCount+1];
-
- const LV2UI_Descriptor* fDescriptor;
- const LV2_RDF_Descriptor* fRdfDescriptor;
- const LV2_RDF_UI* fRdfUiDescriptor;
- Lv2PluginOptions fOptions;
-
- bool fIsReady;
- bool fIsResizable;
- LinkedList<const char*> fCustomURIDs;
-
- struct Extensions {
- const LV2_Options_Interface* options;
- const LV2UI_Idle_Interface* idle;
- const LV2_Programs_UI_Interface* programs;
-
- Extensions()
- : options(nullptr),
- idle(nullptr),
- programs(nullptr) {}
- } fExt;
-
- // -------------------------------------------------------------------
- // Logs Feature
-
- static int carla_lv2_log_printf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, ...)
- {
- CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 0);
- CARLA_SAFE_ASSERT_RETURN(type != CARLA_URI_MAP_ID_NULL, 0);
- CARLA_SAFE_ASSERT_RETURN(fmt != nullptr, 0);
-
- #ifndef DEBUG
- if (type == CARLA_URI_MAP_ID_LOG_TRACE)
- return 0;
- #endif
-
- va_list args;
- va_start(args, fmt);
- const int ret(carla_lv2_log_vprintf(handle, type, fmt, args));
- va_end(args);
-
- return ret;
- }
-
- static int carla_lv2_log_vprintf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, va_list ap)
- {
- CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 0);
- CARLA_SAFE_ASSERT_RETURN(type != CARLA_URI_MAP_ID_NULL, 0);
- CARLA_SAFE_ASSERT_RETURN(fmt != nullptr, 0);
-
- #ifndef DEBUG
- if (type == CARLA_URI_MAP_ID_LOG_TRACE)
- return 0;
- #endif
-
- int ret = 0;
-
- switch (type)
- {
- case CARLA_URI_MAP_ID_LOG_ERROR:
- std::fprintf(stderr, "\x1b[31m");
- ret = std::vfprintf(stderr, fmt, ap);
- std::fprintf(stderr, "\x1b[0m");
- break;
-
- case CARLA_URI_MAP_ID_LOG_NOTE:
- ret = std::vfprintf(stdout, fmt, ap);
- break;
-
- case CARLA_URI_MAP_ID_LOG_TRACE:
- #ifdef DEBUG
- std::fprintf(stdout, "\x1b[30;1m");
- ret = std::vfprintf(stdout, fmt, ap);
- std::fprintf(stdout, "\x1b[0m");
- #endif
- break;
-
- case CARLA_URI_MAP_ID_LOG_WARNING:
- ret = std::vfprintf(stderr, fmt, ap);
- break;
-
- default:
- break;
- }
-
- return ret;
- }
-
- // -------------------------------------------------------------------
- // Programs Feature
-
- static void carla_lv2_program_changed(LV2_Programs_Handle handle, int32_t index)
- {
- CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
- carla_debug("carla_lv2_program_changed(%p, %i)", handle, index);
-
- ((CarlaLv2Client*)handle)->handleProgramChanged(index);
- }
-
- // -------------------------------------------------------------------
- // State Feature
-
- static char* carla_lv2_state_make_path(LV2_State_Make_Path_Handle handle, const char* path)
- {
- CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
- CARLA_SAFE_ASSERT_RETURN(path != nullptr && path[0] != '\0', nullptr);
- carla_debug("carla_lv2_state_make_path(%p, \"%s\")", handle, path);
-
- File file;
-
- if (File::isAbsolutePath(path))
- file = File(path);
- else
- file = File::getCurrentWorkingDirectory().getChildFile(path);
-
- file.getParentDirectory().createDirectory();
-
- return strdup(file.getFullPathName().toRawUTF8());
- }
-
- static char* carla_lv2_state_map_abstract_path(LV2_State_Map_Path_Handle handle, const char* absolute_path)
- {
- CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
- CARLA_SAFE_ASSERT_RETURN(absolute_path != nullptr && absolute_path[0] != '\0', nullptr);
- carla_debug("carla_lv2_state_map_abstract_path(%p, \"%s\")", handle, absolute_path);
-
- // may already be an abstract path
- if (! File::isAbsolutePath(absolute_path))
- return strdup(absolute_path);
-
- return strdup(File(absolute_path).getRelativePathFrom(File::getCurrentWorkingDirectory()).toRawUTF8());
- }
-
- static char* carla_lv2_state_map_absolute_path(LV2_State_Map_Path_Handle handle, const char* abstract_path)
- {
- CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
- CARLA_SAFE_ASSERT_RETURN(abstract_path != nullptr && abstract_path[0] != '\0', nullptr);
- carla_debug("carla_lv2_state_map_absolute_path(%p, \"%s\")", handle, abstract_path);
-
- // may already be an absolute path
- if (File::isAbsolutePath(abstract_path))
- return strdup(abstract_path);
-
- return strdup(File::getCurrentWorkingDirectory().getChildFile(abstract_path).getFullPathName().toRawUTF8());
- }
-
- // -------------------------------------------------------------------
- // URI-Map Feature
-
- static uint32_t carla_lv2_uri_to_id(LV2_URI_Map_Callback_Data data, const char* map, const char* uri)
- {
- carla_debug("carla_lv2_uri_to_id(%p, \"%s\", \"%s\")", data, map, uri);
- return carla_lv2_urid_map((LV2_URID_Map_Handle*)data, uri);
-
- // unused
- (void)map;
- }
-
- // -------------------------------------------------------------------
- // URID Feature
-
- static LV2_URID carla_lv2_urid_map(LV2_URID_Map_Handle handle, const char* uri)
- {
- CARLA_SAFE_ASSERT_RETURN(handle != nullptr, CARLA_URI_MAP_ID_NULL);
- CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', CARLA_URI_MAP_ID_NULL);
- carla_debug("carla_lv2_urid_map(%p, \"%s\")", handle, uri);
-
- // Atom types
- if (std::strcmp(uri, LV2_ATOM__Blank) == 0)
- return CARLA_URI_MAP_ID_ATOM_BLANK;
- if (std::strcmp(uri, LV2_ATOM__Bool) == 0)
- return CARLA_URI_MAP_ID_ATOM_BOOL;
- if (std::strcmp(uri, LV2_ATOM__Chunk) == 0)
- return CARLA_URI_MAP_ID_ATOM_CHUNK;
- if (std::strcmp(uri, LV2_ATOM__Double) == 0)
- return CARLA_URI_MAP_ID_ATOM_DOUBLE;
- if (std::strcmp(uri, LV2_ATOM__Event) == 0)
- return CARLA_URI_MAP_ID_ATOM_EVENT;
- if (std::strcmp(uri, LV2_ATOM__Float) == 0)
- return CARLA_URI_MAP_ID_ATOM_FLOAT;
- if (std::strcmp(uri, LV2_ATOM__Int) == 0)
- return CARLA_URI_MAP_ID_ATOM_INT;
- if (std::strcmp(uri, LV2_ATOM__Literal) == 0)
- return CARLA_URI_MAP_ID_ATOM_LITERAL;
- if (std::strcmp(uri, LV2_ATOM__Long) == 0)
- return CARLA_URI_MAP_ID_ATOM_LONG;
- if (std::strcmp(uri, LV2_ATOM__Number) == 0)
- return CARLA_URI_MAP_ID_ATOM_NUMBER;
- if (std::strcmp(uri, LV2_ATOM__Object) == 0)
- return CARLA_URI_MAP_ID_ATOM_OBJECT;
- if (std::strcmp(uri, LV2_ATOM__Path) == 0)
- return CARLA_URI_MAP_ID_ATOM_PATH;
- if (std::strcmp(uri, LV2_ATOM__Property) == 0)
- return CARLA_URI_MAP_ID_ATOM_PROPERTY;
- if (std::strcmp(uri, LV2_ATOM__Resource) == 0)
- return CARLA_URI_MAP_ID_ATOM_RESOURCE;
- if (std::strcmp(uri, LV2_ATOM__Sequence) == 0)
- return CARLA_URI_MAP_ID_ATOM_SEQUENCE;
- if (std::strcmp(uri, LV2_ATOM__Sound) == 0)
- return CARLA_URI_MAP_ID_ATOM_SOUND;
- if (std::strcmp(uri, LV2_ATOM__String) == 0)
- return CARLA_URI_MAP_ID_ATOM_STRING;
- if (std::strcmp(uri, LV2_ATOM__Tuple) == 0)
- return CARLA_URI_MAP_ID_ATOM_TUPLE;
- if (std::strcmp(uri, LV2_ATOM__URI) == 0)
- return CARLA_URI_MAP_ID_ATOM_URI;
- if (std::strcmp(uri, LV2_ATOM__URID) == 0)
- return CARLA_URI_MAP_ID_ATOM_URID;
- if (std::strcmp(uri, LV2_ATOM__Vector) == 0)
- return CARLA_URI_MAP_ID_ATOM_VECTOR;
- if (std::strcmp(uri, LV2_ATOM__atomTransfer) == 0)
- return CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM;
- if (std::strcmp(uri, LV2_ATOM__eventTransfer) == 0)
- return CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT;
-
- // BufSize types
- if (std::strcmp(uri, LV2_BUF_SIZE__maxBlockLength) == 0)
- return CARLA_URI_MAP_ID_BUF_MAX_LENGTH;
- if (std::strcmp(uri, LV2_BUF_SIZE__minBlockLength) == 0)
- return CARLA_URI_MAP_ID_BUF_MIN_LENGTH;
- if (std::strcmp(uri, LV2_BUF_SIZE__sequenceSize) == 0)
- return CARLA_URI_MAP_ID_BUF_SEQUENCE_SIZE;
-
- // Log types
- if (std::strcmp(uri, LV2_LOG__Error) == 0)
- return CARLA_URI_MAP_ID_LOG_ERROR;
- if (std::strcmp(uri, LV2_LOG__Note) == 0)
- return CARLA_URI_MAP_ID_LOG_NOTE;
- if (std::strcmp(uri, LV2_LOG__Trace) == 0)
- return CARLA_URI_MAP_ID_LOG_TRACE;
- if (std::strcmp(uri, LV2_LOG__Warning) == 0)
- return CARLA_URI_MAP_ID_LOG_WARNING;
-
- // Time types
- if (std::strcmp(uri, LV2_TIME__Position) == 0)
- return CARLA_URI_MAP_ID_TIME_POSITION;
- if (std::strcmp(uri, LV2_TIME__bar) == 0)
- return CARLA_URI_MAP_ID_TIME_BAR;
- if (std::strcmp(uri, LV2_TIME__barBeat) == 0)
- return CARLA_URI_MAP_ID_TIME_BAR_BEAT;
- if (std::strcmp(uri, LV2_TIME__beat) == 0)
- return CARLA_URI_MAP_ID_TIME_BEAT;
- if (std::strcmp(uri, LV2_TIME__beatUnit) == 0)
- return CARLA_URI_MAP_ID_TIME_BEAT_UNIT;
- if (std::strcmp(uri, LV2_TIME__beatsPerBar) == 0)
- return CARLA_URI_MAP_ID_TIME_BEATS_PER_BAR;
- if (std::strcmp(uri, LV2_TIME__beatsPerMinute) == 0)
- return CARLA_URI_MAP_ID_TIME_BEATS_PER_MINUTE;
- if (std::strcmp(uri, LV2_TIME__frame) == 0)
- return CARLA_URI_MAP_ID_TIME_FRAME;
- if (std::strcmp(uri, LV2_TIME__framesPerSecond) == 0)
- return CARLA_URI_MAP_ID_TIME_FRAMES_PER_SECOND;
- if (std::strcmp(uri, LV2_TIME__speed) == 0)
- return CARLA_URI_MAP_ID_TIME_SPEED;
-
- // 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;
-
- // 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;
-
- // Custom types
- return ((CarlaLv2Client*)handle)->getCustomURID(uri);
- }
-
- static const char* carla_lv2_urid_unmap(LV2_URID_Map_Handle handle, LV2_URID urid)
- {
- CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
- CARLA_SAFE_ASSERT_RETURN(urid != CARLA_URI_MAP_ID_NULL, nullptr);
- carla_debug("carla_lv2_urid_unmap(%p, %i)", handle, urid);
-
- // Atom types
- if (urid == CARLA_URI_MAP_ID_ATOM_BLANK)
- return LV2_ATOM__Blank;
- if (urid == CARLA_URI_MAP_ID_ATOM_BOOL)
- return LV2_ATOM__Bool;
- 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_EVENT)
- return LV2_ATOM__Event;
- if (urid == CARLA_URI_MAP_ID_ATOM_FLOAT)
- return LV2_ATOM__Float;
- if (urid == CARLA_URI_MAP_ID_ATOM_INT)
- return LV2_ATOM__Int;
- if (urid == CARLA_URI_MAP_ID_ATOM_LITERAL)
- return LV2_ATOM__Literal;
- if (urid == CARLA_URI_MAP_ID_ATOM_LONG)
- return LV2_ATOM__Long;
- if (urid == CARLA_URI_MAP_ID_ATOM_NUMBER)
- return LV2_ATOM__Number;
- if (urid == CARLA_URI_MAP_ID_ATOM_OBJECT)
- return LV2_ATOM__Object;
- if (urid == CARLA_URI_MAP_ID_ATOM_PATH)
- return LV2_ATOM__Path;
- if (urid == CARLA_URI_MAP_ID_ATOM_PROPERTY)
- return LV2_ATOM__Property;
- if (urid == CARLA_URI_MAP_ID_ATOM_RESOURCE)
- return LV2_ATOM__Resource;
- if (urid == CARLA_URI_MAP_ID_ATOM_SEQUENCE)
- return LV2_ATOM__Sequence;
- if (urid == CARLA_URI_MAP_ID_ATOM_SOUND)
- return LV2_ATOM__Sound;
- if (urid == CARLA_URI_MAP_ID_ATOM_STRING)
- return LV2_ATOM__String;
- if (urid == CARLA_URI_MAP_ID_ATOM_TUPLE)
- return LV2_ATOM__Tuple;
- if (urid == CARLA_URI_MAP_ID_ATOM_URI)
- return LV2_ATOM__URI;
- if (urid == CARLA_URI_MAP_ID_ATOM_URID)
- 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)
- 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;
- if (urid == CARLA_URI_MAP_ID_LOG_NOTE)
- return LV2_LOG__Note;
- if (urid == CARLA_URI_MAP_ID_LOG_TRACE)
- return LV2_LOG__Trace;
- if (urid == CARLA_URI_MAP_ID_LOG_WARNING)
- return LV2_LOG__Warning;
-
- // Time types
- if (urid == CARLA_URI_MAP_ID_TIME_POSITION)
- return LV2_TIME__Position;
- if (urid == CARLA_URI_MAP_ID_TIME_BAR)
- return LV2_TIME__bar;
- if (urid == CARLA_URI_MAP_ID_TIME_BAR_BEAT)
- return LV2_TIME__barBeat;
- if (urid == CARLA_URI_MAP_ID_TIME_BEAT)
- return LV2_TIME__beat;
- if (urid == CARLA_URI_MAP_ID_TIME_BEAT_UNIT)
- return LV2_TIME__beatUnit;
- if (urid == CARLA_URI_MAP_ID_TIME_BEATS_PER_BAR)
- return LV2_TIME__beatsPerBar;
- if (urid == CARLA_URI_MAP_ID_TIME_BEATS_PER_MINUTE)
- return LV2_TIME__beatsPerMinute;
- if (urid == CARLA_URI_MAP_ID_TIME_FRAME)
- return LV2_TIME__frame;
- if (urid == CARLA_URI_MAP_ID_TIME_FRAMES_PER_SECOND)
- return LV2_TIME__framesPerSecond;
- if (urid == CARLA_URI_MAP_ID_TIME_SPEED)
- return LV2_TIME__speed;
-
- // 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;
-
- // Custom types
- return ((CarlaLv2Client*)handle)->getCustomURIString(urid);
- }
-
- // -------------------------------------------------------------------
- // UI Port-Map Feature
-
- static uint32_t carla_lv2_ui_port_map(LV2UI_Feature_Handle handle, const char* symbol)
- {
- CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2UI_INVALID_PORT_INDEX);
- carla_debug("carla_lv2_ui_port_map(%p, \"%s\")", handle, symbol);
-
- return ((CarlaLv2Client*)handle)->handleUiPortMap(symbol);
- }
-
- // -------------------------------------------------------------------
- // UI Resize Feature
-
- static int carla_lv2_ui_resize(LV2UI_Feature_Handle handle, int width, int height)
- {
- CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 1);
- carla_debug("carla_lv2_ui_resize(%p, %i, %i)", handle, width, height);
-
- return ((CarlaLv2Client*)handle)->handleUiResize(width, height);
- }
-
- // -------------------------------------------------------------------
- // UI Extension
-
- static void carla_lv2_ui_write_function(LV2UI_Controller controller, uint32_t port_index, uint32_t buffer_size, uint32_t format, const void* buffer)
- {
- CARLA_SAFE_ASSERT_RETURN(controller != nullptr,);
- carla_debug("carla_lv2_ui_write_function(%p, %i, %i, %i, %p)", controller, port_index, buffer_size, format, buffer);
-
- ((CarlaLv2Client*)controller)->handleUiWrite(port_index, buffer_size, format, buffer);
- }
-
- CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaLv2Client)
- };
-
- #define lv2ClientPtr ((CarlaLv2Client*)kClient)
-
- int CarlaBridgeOsc::handleMsgLv2AtomTransfer(CARLA_BRIDGE_OSC_HANDLE_ARGS)
- {
- CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(2, "is");
- carla_debug("CarlaBridgeOsc::handleMsgLv2AtomTransfer()");
-
- if (kClient == nullptr)
- return 1;
-
- const int32_t portIndex = argv[0]->i;
- const char* const atomBuf = (const char*)&argv[1]->s;
-
- if (portIndex < 0)
- return 0;
-
- std::vector<uint8_t> chunk(carla_getChunkFromBase64String(atomBuf));
- CARLA_SAFE_ASSERT_RETURN(chunk.size() > 0, 0);
-
- const LV2_Atom* const atom((const LV2_Atom*)chunk.data());
- lv2ClientPtr->handleAtomTransfer(static_cast<uint32_t>(portIndex), atom);
- return 0;
- }
-
- int CarlaBridgeOsc::handleMsgLv2UridMap(CARLA_BRIDGE_OSC_HANDLE_ARGS)
- {
- CARLA_BRIDGE_OSC_CHECK_OSC_TYPES(2, "is");
- carla_debug("CarlaBridgeOsc::handleMsgLv2UridMap()");
-
- if (kClient == nullptr)
- return 1;
-
- const int32_t urid = argv[0]->i;
- const char* const uri = (const char*)&argv[1]->s;
-
- if (urid < 0)
- return 0;
-
- lv2ClientPtr->handleUridMap(static_cast<LV2_URID>(urid), uri);
- return 0;
- }
-
- #undef lv2ClientPtr
-
- CARLA_BRIDGE_END_NAMESPACE
-
- int main(int argc, char* argv[])
- {
- CARLA_BRIDGE_USE_NAMESPACE
-
- if (argc != 6)
- {
- carla_stderr("usage: %s <osc-url|\"null\"> <plugin-bundle> <plugin-uri> <ui-uri> <ui-title>", argv[0]);
- return 1;
- }
-
- const char* oscUrl = argv[1];
- const char* pluginURI = argv[2];
- const char* uiURI = argv[3];
- const char* uiBundle = argv[4];
- const char* uiTitle = argv[5];
-
- const bool useOsc(std::strcmp(oscUrl, "null") != 0);
-
- // try to get sampleRate value
- if (const char* const sampleRateStr = std::getenv("CARLA_SAMPLE_RATE"))
- gSampleRate = std::atof(sampleRateStr);
-
- // Init LV2 client
- CarlaLv2Client client(uiTitle);
-
- // Init OSC
- if (useOsc)
- {
- client.oscInit(oscUrl);
- client.waitForOscURIs();
- }
-
- // Load UI
- int ret;
-
- if (client.uiInit(pluginURI, uiURI, uiBundle))
- {
- client.toolkitExec(!useOsc);
- ret = 0;
- }
- else
- {
- ret = 1;
- }
-
- // Close OSC
- if (useOsc)
- client.oscClose();
-
- // Close LV2 client
- client.uiClose();
-
- return ret;
- }
|