|
- /*
- * Carla Bridge UI
- * Copyright (C) 2011-2019 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 "CarlaBridgeFormat.hpp"
- #include "CarlaBridgeToolkit.hpp"
-
- #include "CarlaLibUtils.hpp"
- #include "CarlaLv2Utils.hpp"
- #include "CarlaMIDI.h"
- #include "LinkedList.hpp"
-
- #include "water/files/File.h"
-
- #ifdef CARLA_OS_MAC
- # include "CarlaMacUtils.hpp"
- #endif
-
- #include <string>
- #include <vector>
-
- #define URI_CARLA_ATOM_WORKER_IN "http://kxstudio.sf.net/ns/carla/atomWorkerIn"
- #define URI_CARLA_ATOM_WORKER_RESP "http://kxstudio.sf.net/ns/carla/atomWorkerResp"
- #define URI_CARLA_PARAMETER_CHANGE "http://kxstudio.sf.net/ns/carla/parameterChange"
-
- using water::File;
-
- CARLA_BRIDGE_UI_START_NAMESPACE
-
- // --------------------------------------------------------------------------------------------------------------------
-
- static double gInitialSampleRate = 44100.0;
- static const char* const kNullWindowTitle = "TestUI";
- static const uint32_t kNullWindowTitleSize = 6;
- static const char* const kUnmapFallback = "urn:null";
-
- // LV2 URI Map Ids
- enum CarlaLv2URIDs {
- kUridNull = 0,
- kUridAtomBlank,
- kUridAtomBool,
- kUridAtomChunk,
- kUridAtomDouble,
- kUridAtomEvent,
- kUridAtomFloat,
- kUridAtomInt,
- kUridAtomLiteral,
- kUridAtomLong,
- kUridAtomNumber,
- kUridAtomObject,
- kUridAtomPath,
- kUridAtomProperty,
- kUridAtomResource,
- kUridAtomSequence,
- kUridAtomSound,
- kUridAtomString,
- kUridAtomTuple,
- kUridAtomURI,
- kUridAtomURID,
- kUridAtomVector,
- kUridAtomTransferAtom,
- kUridAtomTransferEvent,
- kUridBufMaxLength,
- kUridBufMinLength,
- kUridBufNominalLength,
- kUridBufSequenceSize,
- kUridLogError,
- kUridLogNote,
- kUridLogTrace,
- kUridLogWarning,
- kUridPatchSet,
- kUridPatchProperty,
- kUridPatchSubject,
- kUridPatchValue,
- // time base type
- kUridTimePosition,
- // time values
- kUridTimeBar,
- kUridTimeBarBeat,
- kUridTimeBeat,
- kUridTimeBeatUnit,
- kUridTimeBeatsPerBar,
- kUridTimeBeatsPerMinute,
- kUridTimeFrame,
- kUridTimeFramesPerSecond,
- kUridTimeSpeed,
- kUridTimeTicksPerBeat,
- kUridMidiEvent,
- kUridParamSampleRate,
- // ui stuff
- kUridBackgroundColor,
- kUridForegroundColor,
- kUridScaleFactor,
- kUridWindowTitle,
- // custom carla props
- kUridCarlaAtomWorkerIn,
- kUridCarlaAtomWorkerResp,
- kUridCarlaParameterChange,
- kUridCarlaTransientWindowId,
- // count
- kUridCount
- };
-
- // LV2 Feature Ids
- enum CarlaLv2Features {
- // DSP features
- kFeatureIdLogs = 0,
- kFeatureIdOptions,
- kFeatureIdPrograms,
- kFeatureIdStateFreePath,
- kFeatureIdStateMakePath,
- kFeatureIdStateMapPath,
- kFeatureIdUriMap,
- kFeatureIdUridMap,
- kFeatureIdUridUnmap,
- kFeatureIdUiIdleInterface,
- kFeatureIdUiFixedSize,
- kFeatureIdUiMakeResident,
- kFeatureIdUiMakeResident2,
- kFeatureIdUiNoUserResize,
- kFeatureIdUiParent,
- kFeatureIdUiPortMap,
- kFeatureIdUiPortSubscribe,
- kFeatureIdUiRequestValue,
- kFeatureIdUiResize,
- kFeatureIdUiTouch,
- kFeatureCount
- };
-
- // --------------------------------------------------------------------------------------------------------------------
-
- struct Lv2PluginOptions {
- enum OptIndex {
- SampleRate,
- TransientWinId,
- BackgroundColor,
- ForegroundColor,
- ScaleFactor,
- WindowTitle,
- Null,
- Count
- };
-
- float sampleRate;
- int64_t transientWinId;
- uint32_t bgColor;
- uint32_t fgColor;
- float uiScale;
- LV2_Options_Option opts[Count];
-
- Lv2PluginOptions() noexcept
- : sampleRate(static_cast<float>(gInitialSampleRate)),
- transientWinId(0),
- bgColor(0x000000ff),
- fgColor(0xffffffff),
- uiScale(1.0f)
- {
- LV2_Options_Option& optSampleRate(opts[SampleRate]);
- optSampleRate.context = LV2_OPTIONS_INSTANCE;
- optSampleRate.subject = 0;
- optSampleRate.key = kUridParamSampleRate;
- optSampleRate.size = sizeof(float);
- optSampleRate.type = kUridAtomFloat;
- optSampleRate.value = &sampleRate;
-
- LV2_Options_Option& optBackgroundColor(opts[BackgroundColor]);
- optBackgroundColor.context = LV2_OPTIONS_INSTANCE;
- optBackgroundColor.subject = 0;
- optBackgroundColor.key = kUridBackgroundColor;
- optBackgroundColor.size = sizeof(int32_t);
- optBackgroundColor.type = kUridAtomInt;
- optBackgroundColor.value = &bgColor;
-
- LV2_Options_Option& optForegroundColor(opts[ForegroundColor]);
- optForegroundColor.context = LV2_OPTIONS_INSTANCE;
- optForegroundColor.subject = 0;
- optForegroundColor.key = kUridForegroundColor;
- optForegroundColor.size = sizeof(int32_t);
- optForegroundColor.type = kUridAtomInt;
- optForegroundColor.value = &fgColor;
-
- LV2_Options_Option& optScaleFactor(opts[ScaleFactor]);
- optScaleFactor.context = LV2_OPTIONS_INSTANCE;
- optScaleFactor.subject = 0;
- optScaleFactor.key = kUridScaleFactor;
- optScaleFactor.size = sizeof(float);
- optScaleFactor.type = kUridAtomFloat;
- optScaleFactor.value = &uiScale;
-
- LV2_Options_Option& optTransientWinId(opts[TransientWinId]);
- optTransientWinId.context = LV2_OPTIONS_INSTANCE;
- optTransientWinId.subject = 0;
- optTransientWinId.key = kUridCarlaTransientWindowId;
- optTransientWinId.size = sizeof(int64_t);
- optTransientWinId.type = kUridAtomLong;
- optTransientWinId.value = &transientWinId;
-
- LV2_Options_Option& optWindowTitle(opts[WindowTitle]);
- optWindowTitle.context = LV2_OPTIONS_INSTANCE;
- optWindowTitle.subject = 0;
- optWindowTitle.key = kUridWindowTitle;
- optWindowTitle.size = kNullWindowTitleSize;
- optWindowTitle.type = kUridAtomString;
- optWindowTitle.value = kNullWindowTitle;
-
- LV2_Options_Option& optNull(opts[Null]);
- optNull.context = LV2_OPTIONS_INSTANCE;
- optNull.subject = 0;
- optNull.key = kUridNull;
- optNull.size = 0;
- optNull.type = kUridNull;
- optNull.value = nullptr;
- }
- };
-
- // -------------------------------------------------------------------------------------------------------------------
-
- static void initAtomForge(LV2_Atom_Forge& atomForge) noexcept
- {
- carla_zeroStruct(atomForge);
-
- atomForge.Bool = kUridAtomBool;
- atomForge.Chunk = kUridAtomChunk;
- atomForge.Double = kUridAtomDouble;
- atomForge.Float = kUridAtomFloat;
- atomForge.Int = kUridAtomInt;
- atomForge.Literal = kUridAtomLiteral;
- atomForge.Long = kUridAtomLong;
- atomForge.Object = kUridAtomObject;
- atomForge.Path = kUridAtomPath;
- atomForge.Property = kUridAtomProperty;
- atomForge.Sequence = kUridAtomSequence;
- atomForge.String = kUridAtomString;
- atomForge.Tuple = kUridAtomTuple;
- atomForge.URI = kUridAtomURI;
- atomForge.URID = kUridAtomURID;
- atomForge.Vector = kUridAtomVector;
-
- #if defined(__clang__)
- # pragma clang diagnostic push
- # pragma clang diagnostic ignored "-Wdeprecated-declarations"
- #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
- # pragma GCC diagnostic push
- # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
- #endif
- atomForge.Blank = kUridAtomBlank;
- atomForge.Resource = kUridAtomResource;
- #if defined(__clang__)
- # pragma clang diagnostic pop
- #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
- # pragma GCC diagnostic pop
- #endif
- }
-
- // --------------------------------------------------------------------------------------------------------------------
-
- class CarlaLv2Client : public CarlaBridgeFormat
- {
- public:
- CarlaLv2Client()
- : CarlaBridgeFormat(),
- fHandle(nullptr),
- fWidget(nullptr),
- fDescriptor(nullptr),
- fRdfDescriptor(nullptr),
- fRdfUiDescriptor(nullptr),
- fControlDesignatedPort(0),
- fLv2Options(),
- fUiOptions(),
- fCustomURIDs(kUridCount, std::string("urn:null")),
- fExt()
- {
- CARLA_SAFE_ASSERT(fCustomURIDs.size() == kUridCount);
-
- carla_zeroPointers(fFeatures, kFeatureCount+1);
-
- // ------------------------------------------------------------------------------------------------------------
- // 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_Free_Path* const stateFreePathFt = new LV2_State_Free_Path;
- stateFreePathFt->handle = this;
- stateFreePathFt->free_path = carla_lv2_state_free_path;
-
- LV2_State_Make_Path* const stateMakePathFt = new LV2_State_Make_Path;
- stateMakePathFt->handle = this;
- stateMakePathFt->path = carla_lv2_state_make_path_tmp;
-
- LV2_State_Map_Path* const stateMapPathFt = new LV2_State_Map_Path;
- stateMapPathFt->handle = this;
- stateMapPathFt->abstract_path = carla_lv2_state_map_abstract_path_tmp;
- stateMapPathFt->absolute_path = carla_lv2_state_map_absolute_path_tmp;
-
- 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_Request_Value* const uiRequestValueFt = new LV2UI_Request_Value;
- uiRequestValueFt->handle = this;
- uiRequestValueFt->request = carla_lv2_ui_request_value;
-
- 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 = fLv2Options.opts;
-
- fFeatures[kFeatureIdPrograms]->URI = LV2_PROGRAMS__Host;
- fFeatures[kFeatureIdPrograms]->data = programsFt;
-
- fFeatures[kFeatureIdStateFreePath]->URI = LV2_STATE__freePath;
- fFeatures[kFeatureIdStateFreePath]->data = stateFreePathFt;
-
- 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[kFeatureIdUiMakeResident2]->URI = LV2_UI__makeSONameResident;
- fFeatures[kFeatureIdUiMakeResident2]->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[kFeatureIdUiRequestValue]->URI = LV2_UI__requestValue;
- fFeatures[kFeatureIdUiRequestValue]->data = uiRequestValueFt;
-
- fFeatures[kFeatureIdUiResize]->URI = LV2_UI__resize;
- fFeatures[kFeatureIdUiResize]->data = uiResizeFt;
-
- fFeatures[kFeatureIdUiTouch]->URI = LV2_UI__touch;
- fFeatures[kFeatureIdUiTouch]->data = nullptr;
- }
-
- ~CarlaLv2Client() override
- {
- if (fHandle != nullptr && fDescriptor != nullptr && fDescriptor->cleanup != nullptr)
- {
- fDescriptor->cleanup(fHandle);
- fHandle = nullptr;
- }
-
- if (fRdfDescriptor != nullptr)
- {
- delete fRdfDescriptor;
- fRdfDescriptor = nullptr;
- }
-
- fRdfUiDescriptor = nullptr;
-
- delete (LV2_Log_Log*)fFeatures[kFeatureIdLogs]->data;
- delete (LV2_State_Free_Path*)fFeatures[kFeatureIdStateFreePath]->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_Request_Value*)fFeatures[kFeatureIdUiRequestValue]->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;
- }
- }
- }
-
- // ----------------------------------------------------------------------------------------------------------------
- // UI initialization
-
- bool init(const int argc, const char* argv[]) override
- {
- const char* pluginURI = argv[1];
- const char* uiURI = argc > 2 ? argv[2] : nullptr;
-
- // ------------------------------------------------------------------------------------------------------------
- // load plugin
-
- Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
- lv2World.initIfNeeded(std::getenv("LV2_PATH"));
-
- #if 0
- 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);
- #endif
-
- // ------------------------------------------------------------------------------------------------------------
- // get plugin from lv2_rdf (lilv)
-
- fRdfDescriptor = lv2_rdf_new(pluginURI, false);
- CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
-
- // ------------------------------------------------------------------------------------------------------------
- // find requested UI
-
- if (uiURI == nullptr)
- {
- CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor->UICount > 0, false);
-
- fRdfUiDescriptor = &fRdfDescriptor->UIs[0];
- uiURI = fRdfUiDescriptor->URI;
- }
- else
- {
- for (uint32_t i=0; i < fRdfDescriptor->UICount; ++i)
- {
- if (std::strcmp(fRdfDescriptor->UIs[i].URI, uiURI) == 0)
- {
- fRdfUiDescriptor = &fRdfDescriptor->UIs[i];
- break;
- }
- }
- }
-
- CARLA_SAFE_ASSERT_RETURN(fRdfUiDescriptor != nullptr, false);
-
- // ------------------------------------------------------------------------------------------------------------
- // check if not resizable
-
- for (uint32_t i=0; i < fRdfUiDescriptor->FeatureCount; ++i)
- {
- if (std::strcmp(fRdfUiDescriptor->Features[i].URI, LV2_UI__fixedSize ) == 0 ||
- std::strcmp(fRdfUiDescriptor->Features[i].URI, LV2_UI__noUserResize) == 0)
- {
- fUiOptions.isResizable = false;
- break;
- }
- }
-
- // ------------------------------------------------------------------------------------------------------------
- // init UI
-
- if (! CarlaBridgeFormat::init(argc, argv))
- return false;
-
- // ------------------------------------------------------------------------------------------------------------
- // open DLL
-
- #ifdef CARLA_OS_MAC
- // Binary might be in quarentine due to Apple stupid notarization rules, let's remove that if possible
- CarlaBackend::removeFileFromQuarantine(fRdfUiDescriptor->Binary);
- #endif
-
- if (! libOpen(fRdfUiDescriptor->Binary))
- {
- carla_stderr("Failed to load UI binary, error was:\n%s", libError());
- return false;
- }
-
- // ------------------------------------------------------------------------------------------------------------
- // get DLL main entry
-
- const LV2UI_DescriptorFunction ui_descFn = (LV2UI_DescriptorFunction)libSymbol("lv2ui_descriptor");
-
- if (ui_descFn == nullptr)
- return false;
-
- // ------------------------------------------------------------------------------------------------------------
- // get descriptor that matches URI
-
- for (uint32_t i=0; (fDescriptor = ui_descFn(i++)) != nullptr;)
- {
- 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 = fToolkit->getContainerId();
- #endif
-
- fHandle = fDescriptor->instantiate(fDescriptor, fRdfDescriptor->URI, fRdfUiDescriptor->Bundle,
- carla_lv2_ui_write_function, this, &fWidget, fFeatures);
- CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, false);
-
- #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11)
- if (fWidget != nullptr)
- fToolkit->setChildWindow(fWidget);
- #endif
-
- // ------------------------------------------------------------------------------------------------------------
- // check for known extensions
-
- if (fDescriptor->extension_data != nullptr)
- {
- fExt.options = (const LV2_Options_Interface*)fDescriptor->extension_data(LV2_OPTIONS__interface);
- fExt.programs = (const LV2_Programs_UI_Interface*)fDescriptor->extension_data(LV2_PROGRAMS__UIInterface);
- fExt.idle = (const LV2UI_Idle_Interface*)fDescriptor->extension_data(LV2_UI__idleInterface);
- fExt.resize = (const LV2UI_Resize*)fDescriptor->extension_data(LV2_UI__resize);
-
- // 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;
- if (fExt.resize != nullptr && fExt.resize->ui_resize == nullptr)
- fExt.resize = nullptr;
- }
-
- for (uint32_t i=0; i<fRdfDescriptor->PortCount; ++i)
- {
- if (LV2_IS_PORT_DESIGNATION_CONTROL(fRdfDescriptor->Ports[i].Designation))
- {
- fControlDesignatedPort = i;
- break;
- }
- }
-
- return true;
- }
-
- void idleUI() override
- {
- #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11)
- if (fHandle != nullptr && fExt.idle != nullptr && fExt.idle->idle(fHandle) != 0)
- {
- if (isPipeRunning() && ! fQuitReceived)
- writeExitingMessageAndWait();
- }
- #endif
- }
-
- // ----------------------------------------------------------------------------------------------------------------
- // UI management
-
- void* getWidget() const noexcept override
- {
- return fWidget;
- }
-
- const Options& getOptions() const noexcept override
- {
- return fUiOptions;
- }
-
- // ----------------------------------------------------------------------------------------------------------------
- // DSP Callbacks
-
- void dspParameterChanged(const uint32_t index, const float value) override
- {
- CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,)
- CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
-
- if (fDescriptor->port_event == nullptr)
- return;
-
- fDescriptor->port_event(fHandle, index, sizeof(float), kUridNull, &value);
- }
-
- void dspParameterChanged(const char* const uri, const float value) override
- {
- CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,)
- CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
-
- if (fDescriptor->port_event == nullptr)
- return;
-
- uint32_t parameterId = UINT32_MAX;
-
- for (uint32_t i=0; i < fRdfDescriptor->ParameterCount; ++i)
- {
- const LV2_RDF_Parameter& rdfParam(fRdfDescriptor->Parameters[i]);
-
- if (std::strcmp(rdfParam.URI, uri) == 0)
- {
- parameterId = i;
- break;
- }
- }
-
- if (parameterId == UINT32_MAX)
- return;
-
- uint8_t atomBuf[256];
- LV2_Atom_Forge atomForge;
- initAtomForge(atomForge);
- lv2_atom_forge_set_buffer(&atomForge, atomBuf, sizeof(atomBuf));
-
- LV2_Atom_Forge_Frame forgeFrame;
- lv2_atom_forge_object(&atomForge, &forgeFrame, kUridNull, kUridPatchSet);
-
- lv2_atom_forge_key(&atomForge, kUridCarlaParameterChange);
- lv2_atom_forge_bool(&atomForge, true);
-
- lv2_atom_forge_key(&atomForge, kUridPatchProperty);
- lv2_atom_forge_urid(&atomForge, getCustomURID(uri));
-
- lv2_atom_forge_key(&atomForge, kUridPatchValue);
-
- switch (fRdfDescriptor->Parameters[parameterId].Type)
- {
- case LV2_PARAMETER_TYPE_BOOL:
- lv2_atom_forge_bool(&atomForge, value > 0.5f);
- break;
- case LV2_PARAMETER_TYPE_INT:
- lv2_atom_forge_int(&atomForge, static_cast<int32_t>(value + 0.5f));
- break;
- case LV2_PARAMETER_TYPE_LONG:
- lv2_atom_forge_long(&atomForge, static_cast<int64_t>(value + 0.5f));
- break;
- case LV2_PARAMETER_TYPE_FLOAT:
- lv2_atom_forge_float(&atomForge, value);
- break;
- case LV2_PARAMETER_TYPE_DOUBLE:
- lv2_atom_forge_double(&atomForge, value);
- break;
- default:
- carla_stderr2("dspParameterChanged called for invalid parameter, abort!");
- return;
- }
-
- lv2_atom_forge_pop(&atomForge, &forgeFrame);
-
- LV2_Atom* const atom((LV2_Atom*)atomBuf);
- CARLA_SAFE_ASSERT(atom->size < sizeof(atomBuf));
-
- fDescriptor->port_event(fHandle,
- fControlDesignatedPort,
- lv2_atom_total_size(atom),
- kUridAtomTransferEvent,
- atom);
- }
-
- void dspProgramChanged(const uint32_t index) override
- {
- carla_stderr2("dspProgramChanged(%i) - not handled", index);
- }
-
- void dspMidiProgramChanged(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 dspStateChanged(const char* const, const char* const) override
- {
- }
-
- void dspNoteReceived(const bool onOff, const uint8_t channel, const uint8_t note, const uint8_t velocity) override
- {
- CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,)
- CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
-
- if (fDescriptor->port_event == nullptr)
- return;
-
- LV2_Atom_MidiEvent midiEv;
- midiEv.atom.type = kUridMidiEvent;
- midiEv.atom.size = 3;
- midiEv.data[0] = uint8_t((onOff ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (channel & MIDI_CHANNEL_BIT));
- midiEv.data[1] = note;
- midiEv.data[2] = velocity;
-
- fDescriptor->port_event(fHandle, fControlDesignatedPort, lv2_atom_total_size(midiEv), kUridAtomTransferEvent, &midiEv);
- }
-
- void dspAtomReceived(const uint32_t portIndex, const LV2_Atom* const atom) override
- {
- CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
- CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
- CARLA_SAFE_ASSERT_RETURN(atom != nullptr,);
-
- if (fDescriptor->port_event == nullptr)
- return;
-
- fDescriptor->port_event(fHandle, portIndex, lv2_atom_total_size(atom), kUridAtomTransferEvent, atom);
- }
-
- void dspURIDReceived(const LV2_URID urid, const char* const uri) override
- {
- CARLA_SAFE_ASSERT_RETURN(urid == fCustomURIDs.size(),);
- CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0',);
-
- fCustomURIDs.push_back(uri);
- }
-
- void uiOptionsChanged(const BridgeFormatOptions& opts) override
- {
- carla_debug("CarlaLv2Client::uiOptionsChanged()");
-
- // ------------------------------------------------------------------------------------------------------------
- // sample rate
-
- const float sampleRatef = static_cast<float>(opts.sampleRate);
-
- if (carla_isNotEqual(fLv2Options.sampleRate, sampleRatef))
- {
- fLv2Options.sampleRate = sampleRatef;
-
- if (fExt.options != nullptr && fExt.options->set != nullptr)
- {
- LV2_Options_Option options[2];
- carla_zeroStructs(options, 2);
-
- LV2_Options_Option& optSampleRate(options[0]);
- optSampleRate.context = LV2_OPTIONS_INSTANCE;
- optSampleRate.subject = 0;
- optSampleRate.key = kUridParamSampleRate;
- optSampleRate.size = sizeof(float);
- optSampleRate.type = kUridAtomFloat;
- optSampleRate.value = &fLv2Options.sampleRate;
-
- fExt.options->set(fHandle, options);
- }
- }
-
- // ------------------------------------------------------------------------------------------------------------
- // ui colors and scale
-
- fLv2Options.bgColor = opts.bgColor;
- fLv2Options.fgColor = opts.fgColor;
- fLv2Options.uiScale = opts.uiScale;
-
- // ------------------------------------------------------------------------------------------------------------
- // window title
-
- if (opts.windowTitle != nullptr)
- fUiOptions.windowTitle = opts.windowTitle;
- else
- fUiOptions.windowTitle.clear();
-
- fLv2Options.opts[Lv2PluginOptions::WindowTitle].size = static_cast<uint32_t>(fUiOptions.windowTitle.length());
- fLv2Options.opts[Lv2PluginOptions::WindowTitle].value = fUiOptions.windowTitle.buffer();
-
- // ------------------------------------------------------------------------------------------------------------
- // transient win id
-
- fLv2Options.transientWinId = static_cast<int64_t>(opts.transientWindowId);
- fUiOptions.transientWindowId = opts.transientWindowId;
-
- // ------------------------------------------------------------------------------------------------------------
- // other
-
- fUiOptions.isStandalone = opts.isStandalone;
- fUiOptions.useTheme = opts.useTheme;
- fUiOptions.useThemeColors = opts.useThemeColors;
- }
-
- void setScaleFactor(const double scaleFactor) override
- {
- fLv2Options.uiScale = static_cast<float>(scaleFactor);
- }
-
- void uiResized(const uint width, const uint height) override
- {
- if (fHandle != nullptr && fExt.resize != nullptr)
- fExt.resize->ui_resize(fHandle, static_cast<int>(width), static_cast<int>(height));
- }
-
- // ----------------------------------------------------------------------------------------------------------------
-
- LV2_URID getCustomURID(const char* const uri)
- {
- CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', kUridNull);
- carla_debug("CarlaLv2Client::getCustomURID(\"%s\")", uri);
-
- const std::string s_uri(uri);
- const std::ptrdiff_t s_pos(std::find(fCustomURIDs.begin(), fCustomURIDs.end(), s_uri) - fCustomURIDs.begin());
-
- if (s_pos <= 0 || s_pos >= INT32_MAX)
- return kUridNull;
-
- const LV2_URID urid = static_cast<LV2_URID>(s_pos);
- const LV2_URID uriCount = static_cast<LV2_URID>(fCustomURIDs.size());
-
- if (urid < uriCount)
- return urid;
-
- CARLA_SAFE_ASSERT(urid == uriCount);
-
- fCustomURIDs.push_back(uri);
-
- if (isPipeRunning())
- writeLv2UridMessage(urid, uri);
-
- return urid;
- }
-
- const char* getCustomURIDString(const LV2_URID urid) const noexcept
- {
- CARLA_SAFE_ASSERT_RETURN(urid != kUridNull, kUnmapFallback);
- CARLA_SAFE_ASSERT_RETURN(urid < fCustomURIDs.size(), kUnmapFallback);
- carla_debug("CarlaLv2Client::getCustomURIDString(%i)", urid);
-
- return fCustomURIDs[urid].c_str();
- }
-
- // ----------------------------------------------------------------------------------------------------------------
-
- void handleProgramChanged(const int32_t index)
- {
- if (isPipeRunning())
- writeReloadProgramsMessage(index);
- }
-
- 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;
- }
-
- // ----------------------------------------------------------------------------------------------------------------
-
- char* handleStateMapToAbstractPath(const char* const absolutePath)
- {
- // may already be an abstract path
- if (! File::isAbsolutePath(absolutePath))
- return strdup(absolutePath);
-
- return strdup(File(absolutePath).getRelativePathFrom(File::getCurrentWorkingDirectory()).toRawUTF8());
- }
-
- char* handleStateMapToAbsolutePath(const bool createDir, const char* const abstractPath)
- {
- File target;
-
- if (File::isAbsolutePath(abstractPath))
- {
- target = abstractPath;
- }
- else
- {
- target = File::getCurrentWorkingDirectory().getChildFile(abstractPath);
- }
-
- if (createDir)
- {
- File dir(target.getParentDirectory());
- if (! dir.exists())
- dir.createDirectory();
- }
-
- return strdup(target.getFullPathName().toRawUTF8());
- }
-
- // ----------------------------------------------------------------------------------------------------------------
-
- LV2UI_Request_Value_Status handleUiRequestValue(const LV2_URID key,
- const LV2_URID type,
- const LV2_Feature* const* features)
- {
- CARLA_SAFE_ASSERT_RETURN(fToolkit != nullptr, LV2UI_REQUEST_VALUE_ERR_UNKNOWN);
- carla_debug("CarlaLv2Client::handleUIRequestValue(%u, %u, %p)", key, type, features);
-
- if (type != kUridAtomPath)
- return LV2UI_REQUEST_VALUE_ERR_UNSUPPORTED;
-
- const char* const uri = getCustomURIDString(key);
- CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri != kUnmapFallback, LV2UI_REQUEST_VALUE_ERR_UNKNOWN);
-
- // TODO check if a file browser is already open
-
- for (uint32_t i=0; i < fRdfDescriptor->ParameterCount; ++i)
- {
- if (fRdfDescriptor->Parameters[i].Type != LV2_PARAMETER_TYPE_PATH)
- continue;
- if (std::strcmp(fRdfDescriptor->Parameters[i].URI, uri) != 0)
- continue;
-
- // TODO file browser filters, also label for title
- if (isPipeRunning())
- {
- char tmpBuf[0xff];
-
- const CarlaMutexLocker cml(getPipeLock());
-
- writeMessage("requestvalue\n", 13);
-
- std::snprintf(tmpBuf, 0xff-1, "%u\n", key);
- tmpBuf[0xff-1] = '\0';
- writeMessage(tmpBuf);
-
- std::snprintf(tmpBuf, 0xff-1, "%u\n", type);
- tmpBuf[0xff-1] = '\0';
- writeMessage(tmpBuf);
- }
-
- return LV2UI_REQUEST_VALUE_SUCCESS;
- }
-
- return LV2UI_REQUEST_VALUE_ERR_UNSUPPORTED;
-
- // may be unused
- (void)features;
- }
-
- int handleUiResize(const int width, const int height)
- {
- CARLA_SAFE_ASSERT_RETURN(fToolkit != nullptr, 1);
- CARLA_SAFE_ASSERT_RETURN(width > 0, 1);
- CARLA_SAFE_ASSERT_RETURN(height > 0, 1);
- carla_debug("CarlaLv2Client::handleUiResize(%i, %i)", width, height);
-
- fToolkit->setSize(static_cast<uint>(width), static_cast<uint>(height));
- return 0;
- }
-
- void handleUiWrite(uint32_t rindex, 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)", rindex, bufferSize, format, buffer);
-
- switch (format)
- {
- case kUridNull:
- CARLA_SAFE_ASSERT_RETURN(bufferSize == sizeof(float),);
-
- if (isPipeRunning())
- {
- const float value(*(const float*)buffer);
- writeControlMessage(rindex, value);
- }
- break;
-
- case kUridAtomTransferAtom:
- case kUridAtomTransferEvent:
- CARLA_SAFE_ASSERT_RETURN(bufferSize >= sizeof(LV2_Atom),);
-
- if (isPipeRunning())
- {
- const LV2_Atom* const atom((const LV2_Atom*)buffer);
-
- // plugins sometimes fail on this, not good...
- const uint32_t totalSize = lv2_atom_total_size(atom);
- const uint32_t paddedSize = lv2_atom_pad_size(totalSize);
-
- if (bufferSize != totalSize && bufferSize != paddedSize)
- carla_stderr2("Warning: LV2 UI sending atom with invalid size %u! size: %u, padded-size: %u",
- bufferSize, totalSize, paddedSize);
-
- writeLv2AtomMessage(rindex, atom);
- }
- break;
-
- default:
- carla_stderr("CarlaLv2Client::handleUiWrite(%i, %i, %i:\"%s\", %p) - unknown format",
- rindex, bufferSize, format, carla_lv2_urid_unmap(this, format), buffer);
- break;
- }
- }
-
- // ----------------------------------------------------------------------------------------------------------------
-
- 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;
- uint32_t fControlDesignatedPort;
- Lv2PluginOptions fLv2Options;
-
- Options fUiOptions;
- std::vector<std::string> fCustomURIDs;
-
- struct Extensions {
- const LV2_Options_Interface* options;
- const LV2_Programs_UI_Interface* programs;
- const LV2UI_Idle_Interface* idle;
- const LV2UI_Resize* resize;
-
- Extensions()
- : options(nullptr),
- programs(nullptr),
- idle(nullptr),
- resize(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 != kUridNull, 0);
- CARLA_SAFE_ASSERT_RETURN(fmt != nullptr, 0);
-
- #ifndef DEBUG
- if (type == kUridLogTrace)
- 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 != kUridNull, 0);
- CARLA_SAFE_ASSERT_RETURN(fmt != nullptr, 0);
-
- int ret = 0;
-
- switch (type)
- {
- case kUridLogError:
- std::fprintf(stderr, "\x1b[31m");
- ret = std::vfprintf(stderr, fmt, ap);
- std::fprintf(stderr, "\x1b[0m");
- break;
-
- case kUridLogNote:
- ret = std::vfprintf(stdout, fmt, ap);
- break;
-
- case kUridLogTrace:
- #ifdef DEBUG
- std::fprintf(stdout, "\x1b[30;1m");
- ret = std::vfprintf(stdout, fmt, ap);
- std::fprintf(stdout, "\x1b[0m");
- #endif
- break;
-
- case kUridLogWarning:
- 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 void carla_lv2_state_free_path(LV2_State_Free_Path_Handle handle, char* path)
- {
- CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
- carla_debug("carla_lv2_state_free_path(%p, \"%s\")", handle, path);
-
- std::free(path);
- }
-
- static char* carla_lv2_state_make_path_tmp(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_tmp(%p, \"%s\")", handle, path);
-
- return ((CarlaLv2Client*)handle)->handleStateMapToAbsolutePath(true, path);
- }
-
- static char* carla_lv2_state_map_abstract_path_tmp(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_tmp(%p, \"%s\")", handle, absolute_path);
-
- return ((CarlaLv2Client*)handle)->handleStateMapToAbstractPath(absolute_path);
- }
-
- static char* carla_lv2_state_map_absolute_path_tmp(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_tmp(%p, \"%s\")", handle, abstract_path);
-
- return ((CarlaLv2Client*)handle)->handleStateMapToAbsolutePath(false, abstract_path);
- }
-
- // ----------------------------------------------------------------------------------------------------------------
- // 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, kUridNull);
- CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', kUridNull);
- carla_debug("carla_lv2_urid_map(%p, \"%s\")", handle, uri);
-
- // Atom types
- if (std::strcmp(uri, LV2_ATOM__Blank) == 0)
- return kUridAtomBlank;
- if (std::strcmp(uri, LV2_ATOM__Bool) == 0)
- return kUridAtomBool;
- if (std::strcmp(uri, LV2_ATOM__Chunk) == 0)
- return kUridAtomChunk;
- if (std::strcmp(uri, LV2_ATOM__Double) == 0)
- return kUridAtomDouble;
- if (std::strcmp(uri, LV2_ATOM__Event) == 0)
- return kUridAtomEvent;
- if (std::strcmp(uri, LV2_ATOM__Float) == 0)
- return kUridAtomFloat;
- if (std::strcmp(uri, LV2_ATOM__Int) == 0)
- return kUridAtomInt;
- if (std::strcmp(uri, LV2_ATOM__Literal) == 0)
- return kUridAtomLiteral;
- if (std::strcmp(uri, LV2_ATOM__Long) == 0)
- return kUridAtomLong;
- if (std::strcmp(uri, LV2_ATOM__Number) == 0)
- return kUridAtomNumber;
- if (std::strcmp(uri, LV2_ATOM__Object) == 0)
- return kUridAtomObject;
- if (std::strcmp(uri, LV2_ATOM__Path) == 0)
- return kUridAtomPath;
- if (std::strcmp(uri, LV2_ATOM__Property) == 0)
- return kUridAtomProperty;
- if (std::strcmp(uri, LV2_ATOM__Resource) == 0)
- return kUridAtomResource;
- if (std::strcmp(uri, LV2_ATOM__Sequence) == 0)
- return kUridAtomSequence;
- if (std::strcmp(uri, LV2_ATOM__Sound) == 0)
- return kUridAtomSound;
- if (std::strcmp(uri, LV2_ATOM__String) == 0)
- return kUridAtomString;
- if (std::strcmp(uri, LV2_ATOM__Tuple) == 0)
- return kUridAtomTuple;
- if (std::strcmp(uri, LV2_ATOM__URI) == 0)
- return kUridAtomURI;
- if (std::strcmp(uri, LV2_ATOM__URID) == 0)
- return kUridAtomURID;
- if (std::strcmp(uri, LV2_ATOM__Vector) == 0)
- return kUridAtomVector;
- if (std::strcmp(uri, LV2_ATOM__atomTransfer) == 0)
- return kUridAtomTransferAtom;
- if (std::strcmp(uri, LV2_ATOM__eventTransfer) == 0)
- return kUridAtomTransferEvent;
-
- // BufSize types
- if (std::strcmp(uri, LV2_BUF_SIZE__maxBlockLength) == 0)
- return kUridBufMaxLength;
- if (std::strcmp(uri, LV2_BUF_SIZE__minBlockLength) == 0)
- return kUridBufMinLength;
- if (std::strcmp(uri, LV2_BUF_SIZE__nominalBlockLength) == 0)
- return kUridBufNominalLength;
- if (std::strcmp(uri, LV2_BUF_SIZE__sequenceSize) == 0)
- return kUridBufSequenceSize;
-
- // Log types
- if (std::strcmp(uri, LV2_LOG__Error) == 0)
- return kUridLogError;
- if (std::strcmp(uri, LV2_LOG__Note) == 0)
- return kUridLogNote;
- if (std::strcmp(uri, LV2_LOG__Trace) == 0)
- return kUridLogTrace;
- if (std::strcmp(uri, LV2_LOG__Warning) == 0)
- return kUridLogWarning;
-
- // Patch types
- if (std::strcmp(uri, LV2_PATCH__Set) == 0)
- return kUridPatchSet;
- if (std::strcmp(uri, LV2_PATCH__property) == 0)
- return kUridPatchProperty;
- if (std::strcmp(uri, LV2_PATCH__subject) == 0)
- return kUridPatchSubject;
- if (std::strcmp(uri, LV2_PATCH__value) == 0)
- return kUridPatchValue;
-
- // Time types
- if (std::strcmp(uri, LV2_TIME__Position) == 0)
- return kUridTimePosition;
- if (std::strcmp(uri, LV2_TIME__bar) == 0)
- return kUridTimeBar;
- if (std::strcmp(uri, LV2_TIME__barBeat) == 0)
- return kUridTimeBarBeat;
- if (std::strcmp(uri, LV2_TIME__beat) == 0)
- return kUridTimeBeat;
- if (std::strcmp(uri, LV2_TIME__beatUnit) == 0)
- return kUridTimeBeatUnit;
- if (std::strcmp(uri, LV2_TIME__beatsPerBar) == 0)
- return kUridTimeBeatsPerBar;
- if (std::strcmp(uri, LV2_TIME__beatsPerMinute) == 0)
- return kUridTimeBeatsPerMinute;
- if (std::strcmp(uri, LV2_TIME__frame) == 0)
- return kUridTimeFrame;
- if (std::strcmp(uri, LV2_TIME__framesPerSecond) == 0)
- return kUridTimeFramesPerSecond;
- if (std::strcmp(uri, LV2_TIME__speed) == 0)
- return kUridTimeSpeed;
- if (std::strcmp(uri, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat) == 0)
- return kUridTimeTicksPerBeat;
-
- // Others
- if (std::strcmp(uri, LV2_MIDI__MidiEvent) == 0)
- return kUridMidiEvent;
- if (std::strcmp(uri, LV2_PARAMETERS__sampleRate) == 0)
- return kUridParamSampleRate;
- if (std::strcmp(uri, LV2_UI__backgroundColor) == 0)
- return kUridBackgroundColor;
- if (std::strcmp(uri, LV2_UI__foregroundColor) == 0)
- return kUridForegroundColor;
- if (std::strcmp(uri, LV2_UI__scaleFactor) == 0)
- return kUridScaleFactor;
- if (std::strcmp(uri, LV2_UI__windowTitle) == 0)
- return kUridWindowTitle;
-
- // Custom Carla types
- if (std::strcmp(uri, URI_CARLA_ATOM_WORKER_IN) == 0)
- return kUridCarlaAtomWorkerIn;
- if (std::strcmp(uri, URI_CARLA_ATOM_WORKER_RESP) == 0)
- return kUridCarlaAtomWorkerResp;
- if (std::strcmp(uri, URI_CARLA_PARAMETER_CHANGE) == 0)
- return kUridCarlaParameterChange;
- if (std::strcmp(uri, LV2_KXSTUDIO_PROPERTIES__TransientWindowId) == 0)
- return kUridCarlaTransientWindowId;
-
- // Custom plugin 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 != kUridNull, nullptr);
- carla_debug("carla_lv2_urid_unmap(%p, %i)", handle, urid);
-
- switch (urid)
- {
- // Atom types
- case kUridAtomBlank:
- return LV2_ATOM__Blank;
- case kUridAtomBool:
- return LV2_ATOM__Bool;
- case kUridAtomChunk:
- return LV2_ATOM__Chunk;
- case kUridAtomDouble:
- return LV2_ATOM__Double;
- case kUridAtomEvent:
- return LV2_ATOM__Event;
- case kUridAtomFloat:
- return LV2_ATOM__Float;
- case kUridAtomInt:
- return LV2_ATOM__Int;
- case kUridAtomLiteral:
- return LV2_ATOM__Literal;
- case kUridAtomLong:
- return LV2_ATOM__Long;
- case kUridAtomNumber:
- return LV2_ATOM__Number;
- case kUridAtomObject:
- return LV2_ATOM__Object;
- case kUridAtomPath:
- return LV2_ATOM__Path;
- case kUridAtomProperty:
- return LV2_ATOM__Property;
- case kUridAtomResource:
- return LV2_ATOM__Resource;
- case kUridAtomSequence:
- return LV2_ATOM__Sequence;
- case kUridAtomSound:
- return LV2_ATOM__Sound;
- case kUridAtomString:
- return LV2_ATOM__String;
- case kUridAtomTuple:
- return LV2_ATOM__Tuple;
- case kUridAtomURI:
- return LV2_ATOM__URI;
- case kUridAtomURID:
- return LV2_ATOM__URID;
- case kUridAtomVector:
- return LV2_ATOM__Vector;
- case kUridAtomTransferAtom:
- return LV2_ATOM__atomTransfer;
- case kUridAtomTransferEvent:
- return LV2_ATOM__eventTransfer;
-
- // BufSize types
- case kUridBufMaxLength:
- return LV2_BUF_SIZE__maxBlockLength;
- case kUridBufMinLength:
- return LV2_BUF_SIZE__minBlockLength;
- case kUridBufNominalLength:
- return LV2_BUF_SIZE__nominalBlockLength;
- case kUridBufSequenceSize:
- return LV2_BUF_SIZE__sequenceSize;
-
- // Log types
- case kUridLogError:
- return LV2_LOG__Error;
- case kUridLogNote:
- return LV2_LOG__Note;
- case kUridLogTrace:
- return LV2_LOG__Trace;
- case kUridLogWarning:
- return LV2_LOG__Warning;
-
- // Patch types
- case kUridPatchSet:
- return LV2_PATCH__Set;
- case kUridPatchProperty:
- return LV2_PATCH__property;
- case kUridPatchSubject:
- return LV2_PATCH__subject;
- case kUridPatchValue:
- return LV2_PATCH__value;
-
- // Time types
- case kUridTimePosition:
- return LV2_TIME__Position;
- case kUridTimeBar:
- return LV2_TIME__bar;
- case kUridTimeBarBeat:
- return LV2_TIME__barBeat;
- case kUridTimeBeat:
- return LV2_TIME__beat;
- case kUridTimeBeatUnit:
- return LV2_TIME__beatUnit;
- case kUridTimeBeatsPerBar:
- return LV2_TIME__beatsPerBar;
- case kUridTimeBeatsPerMinute:
- return LV2_TIME__beatsPerMinute;
- case kUridTimeFrame:
- return LV2_TIME__frame;
- case kUridTimeFramesPerSecond:
- return LV2_TIME__framesPerSecond;
- case kUridTimeSpeed:
- return LV2_TIME__speed;
- case kUridTimeTicksPerBeat:
- return LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat;
-
- // Others
- case kUridMidiEvent:
- return LV2_MIDI__MidiEvent;
- case kUridParamSampleRate:
- return LV2_PARAMETERS__sampleRate;
- case kUridBackgroundColor:
- return LV2_UI__backgroundColor;
- case kUridForegroundColor:
- return LV2_UI__foregroundColor;
- case kUridScaleFactor:
- return LV2_UI__scaleFactor;
- case kUridWindowTitle:
- return LV2_UI__windowTitle;
-
- // Custom Carla types
- case kUridCarlaAtomWorkerIn:
- return URI_CARLA_ATOM_WORKER_IN;
- case kUridCarlaAtomWorkerResp:
- return URI_CARLA_ATOM_WORKER_RESP;
- case kUridCarlaParameterChange:
- return URI_CARLA_PARAMETER_CHANGE;
- case kUridCarlaTransientWindowId:
- return LV2_KXSTUDIO_PROPERTIES__TransientWindowId;
- }
-
- // Custom types
- return ((CarlaLv2Client*)handle)->getCustomURIDString(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 Request Parameter Feature
-
- static LV2UI_Request_Value_Status carla_lv2_ui_request_value(LV2UI_Feature_Handle handle,
- LV2_URID key,
- LV2_URID type,
- const LV2_Feature* const* features)
- {
- CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2UI_REQUEST_VALUE_ERR_UNKNOWN);
- carla_debug("carla_lv2_ui_request_value(%p, %u, %u, %p)", handle, key, type, features);
-
- return ((CarlaLv2Client*)handle)->handleUiRequestValue(key, type, features);
- }
-
- // ----------------------------------------------------------------------------------------------------------------
- // 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)
- };
-
- // --------------------------------------------------------------------------------------------------------------------
-
- CARLA_BRIDGE_UI_END_NAMESPACE
-
- // --------------------------------------------------------------------------------------------------------------------
-
- int main(int argc, const char* argv[])
- {
- CARLA_BRIDGE_UI_USE_NAMESPACE
-
- if (argc < 2)
- {
- carla_stderr("usage: %s <plugin-uri> [ui-uri]", argv[0]);
- return 1;
- }
-
- const bool testingModeOnly = (argc != 7);
-
- // try to get sampleRate value
- if (const char* const sampleRateStr = std::getenv("CARLA_SAMPLE_RATE"))
- {
- const CarlaScopedLocale csl;
- gInitialSampleRate = std::atof(sampleRateStr);
- }
-
- // Init LV2 client
- CarlaLv2Client client;
-
- // Load UI
- int ret;
-
- if (client.init(argc, argv))
- {
- client.exec(testingModeOnly);
- ret = 0;
- }
- else
- {
- ret = 1;
- }
-
- return ret;
- }
-
- // --------------------------------------------------------------------------------------------------------------------
-
- #include "CarlaMacUtils.cpp"
-
- // --------------------------------------------------------------------------------------------------------------------
|