Cleanup
[carla.git] / source / backend / plugin / CarlaPluginLV2.cpp
blob6cb5ebcab4d94d7f40f88eb1179925bef851e683
1 // SPDX-FileCopyrightText: 2011-2024 Filipe Coelho <falktx@falktx.com>
2 // SPDX-License-Identifier: GPL-2.0-or-later
4 // testing macros
5 // #define LV2_UIS_ONLY_BRIDGES
6 // #define LV2_UIS_ONLY_INPROCESS
8 #include "CarlaPluginInternal.hpp"
9 #include "CarlaEngine.hpp"
11 #include "CarlaLv2Utils.hpp"
13 #include "CarlaBackendUtils.hpp"
14 #include "CarlaBase64Utils.hpp"
15 #include "CarlaEngineUtils.hpp"
16 #include "CarlaPipeUtils.hpp"
17 #include "CarlaPluginUI.hpp"
18 #include "CarlaScopeUtils.hpp"
19 #include "Lv2AtomRingBuffer.hpp"
21 #include "../modules/lilv/config/lilv_config.h"
23 extern "C" {
24 #include "rtmempool/rtmempool-lv2.h"
27 #include "water/files/File.h"
28 #include "water/misc/Time.h"
30 #ifdef CARLA_OS_MAC
31 # include "CarlaMacUtils.hpp"
32 # if defined(CARLA_OS_64BIT) && defined(HAVE_LIBMAGIC) && ! defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
33 # define ADAPT_FOR_APPLE_SILLICON
34 # include "CarlaBinaryUtils.hpp"
35 # endif
36 #endif
38 #ifdef CARLA_OS_WASM
39 # define LV2_UIS_ONLY_INPROCESS
40 #endif
42 #include <string>
43 #include <vector>
45 using water::File;
47 #define URI_CARLA_ATOM_WORKER_IN "http://kxstudio.sf.net/ns/carla/atomWorkerIn"
48 #define URI_CARLA_ATOM_WORKER_RESP "http://kxstudio.sf.net/ns/carla/atomWorkerResp"
49 #define URI_CARLA_PARAMETER_CHANGE "http://kxstudio.sf.net/ns/carla/parameterChange"
51 CARLA_BACKEND_START_NAMESPACE
53 // -------------------------------------------------------------------------------------------------------------------
54 // Fallback data
56 static const CustomData kCustomDataFallback = { nullptr, nullptr, nullptr };
57 static /* */ CustomData kCustomDataFallbackNC = { nullptr, nullptr, nullptr };
58 static const ExternalMidiNote kExternalMidiNoteFallback = { -1, 0, 0 };
59 static const char* const kUnmapFallback = "urn:null";
61 // -------------------------------------------------------------------------------------------------------------------
63 // Maximum default buffer size
64 const uint MAX_DEFAULT_BUFFER_SIZE = 8192; // 0x2000
66 // Extra Plugin Hints
67 const uint PLUGIN_HAS_EXTENSION_OPTIONS = 0x01000;
68 const uint PLUGIN_HAS_EXTENSION_PROGRAMS = 0x02000;
69 const uint PLUGIN_HAS_EXTENSION_STATE = 0x04000;
70 const uint PLUGIN_HAS_EXTENSION_WORKER = 0x08000;
71 const uint PLUGIN_HAS_EXTENSION_INLINE_DISPLAY = 0x10000;
72 const uint PLUGIN_HAS_EXTENSION_MIDNAM = 0x20000;
74 // LV2 Event Data/Types
75 const uint CARLA_EVENT_DATA_ATOM = 0x01;
76 const uint CARLA_EVENT_DATA_EVENT = 0x02;
77 const uint CARLA_EVENT_DATA_MIDI_LL = 0x04;
78 const uint CARLA_EVENT_TYPE_MESSAGE = 0x10; // unused
79 const uint CARLA_EVENT_TYPE_MIDI = 0x20;
80 const uint CARLA_EVENT_TYPE_TIME = 0x40;
82 // LV2 URI Map Ids
83 enum CarlaLv2URIDs {
84 kUridNull = 0,
85 kUridAtomBlank,
86 kUridAtomBool,
87 kUridAtomChunk,
88 kUridAtomDouble,
89 kUridAtomEvent,
90 kUridAtomFloat,
91 kUridAtomInt,
92 kUridAtomLiteral,
93 kUridAtomLong,
94 kUridAtomNumber,
95 kUridAtomObject,
96 kUridAtomPath,
97 kUridAtomProperty,
98 kUridAtomResource,
99 kUridAtomSequence,
100 kUridAtomSound,
101 kUridAtomString,
102 kUridAtomTuple,
103 kUridAtomURI,
104 kUridAtomURID,
105 kUridAtomVector,
106 kUridAtomTransferAtom,
107 kUridAtomTransferEvent,
108 kUridBufMaxLength,
109 kUridBufMinLength,
110 kUridBufNominalLength,
111 kUridBufSequenceSize,
112 kUridLogError,
113 kUridLogNote,
114 kUridLogTrace,
115 kUridLogWarning,
116 kUridPatchSet,
117 kUridPatchProperty,
118 kUridPatchSubject,
119 kUridPatchValue,
120 // time base type
121 kUridTimePosition,
122 // time values
123 kUridTimeBar,
124 kUridTimeBarBeat,
125 kUridTimeBeat,
126 kUridTimeBeatUnit,
127 kUridTimeBeatsPerBar,
128 kUridTimeBeatsPerMinute,
129 kUridTimeFrame,
130 kUridTimeFramesPerSecond,
131 kUridTimeSpeed,
132 kUridTimeTicksPerBeat,
133 kUridMidiEvent,
134 kUridParamSampleRate,
135 // ui stuff
136 kUridBackgroundColor,
137 kUridForegroundColor,
138 #ifndef CARLA_OS_MAC
139 kUridScaleFactor,
140 #endif
141 kUridWindowTitle,
142 // custom carla props
143 kUridCarlaAtomWorkerIn,
144 kUridCarlaAtomWorkerResp,
145 kUridCarlaParameterChange,
146 kUridCarlaTransientWindowId,
147 // count
148 kUridCount
151 // LV2 Feature Ids
152 enum CarlaLv2Features {
153 // DSP features
154 kFeatureIdBufSizeBounded = 0,
155 kFeatureIdBufSizeFixed,
156 kFeatureIdBufSizePowerOf2,
157 kFeatureIdEvent,
158 kFeatureIdHardRtCapable,
159 kFeatureIdInPlaceBroken,
160 kFeatureIdIsLive,
161 kFeatureIdLogs,
162 kFeatureIdOptions,
163 kFeatureIdPrograms,
164 kFeatureIdResizePort,
165 kFeatureIdRtMemPool,
166 kFeatureIdRtMemPoolOld,
167 kFeatureIdStateFreePath,
168 kFeatureIdStateMakePath,
169 kFeatureIdStateMapPath,
170 kFeatureIdStrictBounds,
171 kFeatureIdUriMap,
172 kFeatureIdUridMap,
173 kFeatureIdUridUnmap,
174 kFeatureIdWorker,
175 kFeatureIdInlineDisplay,
176 kFeatureIdMidnam,
177 kFeatureIdCtrlInPortChangeReq,
178 kFeatureCountPlugin,
179 // UI features
180 kFeatureIdUiDataAccess = kFeatureCountPlugin,
181 kFeatureIdUiInstanceAccess,
182 kFeatureIdUiIdleInterface,
183 kFeatureIdUiFixedSize,
184 kFeatureIdUiMakeResident,
185 kFeatureIdUiMakeResident2,
186 kFeatureIdUiNoUserResize,
187 kFeatureIdUiParent,
188 kFeatureIdUiPortMap,
189 kFeatureIdUiPortSubscribe,
190 kFeatureIdUiResize,
191 kFeatureIdUiRequestValue,
192 kFeatureIdUiTouch,
193 kFeatureIdExternalUi,
194 kFeatureIdExternalUiOld,
195 kFeatureCountAll
198 // LV2 Feature Ids (special state handlers)
199 enum CarlaLv2StateFeatures {
200 kStateFeatureIdFreePath,
201 kStateFeatureIdMakePath,
202 kStateFeatureIdMapPath,
203 kStateFeatureIdWorker,
204 kStateFeatureCountAll
207 // -------------------------------------------------------------------------------------------------------------------
209 struct Lv2EventData {
210 uint32_t type;
211 uint32_t rindex;
212 CarlaEngineEventPort* port;
214 union {
215 LV2_Atom_Buffer* atom;
216 LV2_Event_Buffer* event;
217 LV2_MIDI midi;
220 Lv2EventData() noexcept
221 : type(0x0),
222 rindex(0),
223 port(nullptr) {}
225 ~Lv2EventData() noexcept
227 if (port != nullptr)
229 delete port;
230 port = nullptr;
233 const uint32_t rtype = type;
234 type = 0x0;
236 if (rtype & CARLA_EVENT_DATA_ATOM)
238 CARLA_SAFE_ASSERT_RETURN(atom != nullptr,);
240 std::free(atom);
241 atom = nullptr;
243 else if (rtype & CARLA_EVENT_DATA_EVENT)
245 CARLA_SAFE_ASSERT_RETURN(event != nullptr,);
247 std::free(event);
248 event = nullptr;
250 else if (rtype & CARLA_EVENT_DATA_MIDI_LL)
252 CARLA_SAFE_ASSERT_RETURN(midi.data != nullptr,);
254 delete[] midi.data;
255 midi.data = nullptr;
259 CARLA_DECLARE_NON_COPYABLE(Lv2EventData)
262 union LV2EventIters {
263 LV2_Atom_Buffer_Iterator atom;
264 LV2_Event_Iterator event;
265 LV2_MIDIState midiState;
268 struct CarlaPluginLV2EventData {
269 uint32_t count;
270 Lv2EventData* data;
271 LV2EventIters* iters;
272 Lv2EventData* ctrl; // default port, either this->data[x] or pData->portIn/Out
273 uint32_t ctrlIndex;
275 CarlaPluginLV2EventData() noexcept
276 : count(0),
277 data(nullptr),
278 iters(nullptr),
279 ctrl(nullptr),
280 ctrlIndex(0) {}
282 ~CarlaPluginLV2EventData() noexcept
284 CARLA_SAFE_ASSERT_INT(count == 0, count);
285 CARLA_SAFE_ASSERT(data == nullptr);
286 CARLA_SAFE_ASSERT(iters == nullptr);
287 CARLA_SAFE_ASSERT(ctrl == nullptr);
288 CARLA_SAFE_ASSERT_INT(ctrlIndex == 0, ctrlIndex);
291 void createNew(const uint32_t newCount)
293 CARLA_SAFE_ASSERT_INT(count == 0, count);
294 CARLA_SAFE_ASSERT_INT(ctrlIndex == 0, ctrlIndex);
295 CARLA_SAFE_ASSERT_RETURN(data == nullptr,);
296 CARLA_SAFE_ASSERT_RETURN(iters == nullptr,);
297 CARLA_SAFE_ASSERT_RETURN(ctrl == nullptr,);
298 CARLA_SAFE_ASSERT_RETURN(newCount > 0,);
300 data = new Lv2EventData[newCount];
301 iters = new LV2EventIters[newCount];
302 count = newCount;
304 ctrl = nullptr;
305 ctrlIndex = 0;
308 void clear(CarlaEngineEventPort* const portToIgnore) noexcept
310 if (data != nullptr)
312 for (uint32_t i=0; i < count; ++i)
314 if (data[i].port != nullptr)
316 if (data[i].port != portToIgnore)
317 delete data[i].port;
318 data[i].port = nullptr;
322 delete[] data;
323 data = nullptr;
326 if (iters != nullptr)
328 delete[] iters;
329 iters = nullptr;
332 count = 0;
334 ctrl = nullptr;
335 ctrlIndex = 0;
338 void initBuffers() const noexcept
340 for (uint32_t i=0; i < count; ++i)
342 if (data[i].port != nullptr && (ctrl == nullptr || data[i].port != ctrl->port))
343 data[i].port->initBuffer();
347 CARLA_DECLARE_NON_COPYABLE(CarlaPluginLV2EventData)
350 // -------------------------------------------------------------------------------------------------------------------
352 struct CarlaPluginLV2Options {
353 enum OptIndex {
354 MaxBlockLenth = 0,
355 MinBlockLenth,
356 NominalBlockLenth,
357 SequenceSize,
358 SampleRate,
359 TransientWinId,
360 BackgroundColor,
361 ForegroundColor,
362 #ifndef CARLA_OS_MAC
363 ScaleFactor,
364 #endif
365 WindowTitle,
366 Null,
367 Count
370 int maxBufferSize;
371 int minBufferSize;
372 int nominalBufferSize;
373 int sequenceSize;
374 float sampleRate;
375 int64_t transientWinId;
376 uint32_t bgColor;
377 uint32_t fgColor;
378 float uiScale;
379 const char* windowTitle;
380 LV2_Options_Option opts[Count];
382 CarlaPluginLV2Options() noexcept
383 : maxBufferSize(0),
384 minBufferSize(0),
385 nominalBufferSize(0),
386 sequenceSize(MAX_DEFAULT_BUFFER_SIZE),
387 sampleRate(0.0),
388 transientWinId(0),
389 bgColor(0x000000ff),
390 fgColor(0xffffffff),
391 uiScale(1.0f),
392 windowTitle(nullptr)
394 LV2_Options_Option& optMaxBlockLenth(opts[MaxBlockLenth]);
395 optMaxBlockLenth.context = LV2_OPTIONS_INSTANCE;
396 optMaxBlockLenth.subject = 0;
397 optMaxBlockLenth.key = kUridBufMaxLength;
398 optMaxBlockLenth.size = sizeof(int);
399 optMaxBlockLenth.type = kUridAtomInt;
400 optMaxBlockLenth.value = &maxBufferSize;
402 LV2_Options_Option& optMinBlockLenth(opts[MinBlockLenth]);
403 optMinBlockLenth.context = LV2_OPTIONS_INSTANCE;
404 optMinBlockLenth.subject = 0;
405 optMinBlockLenth.key = kUridBufMinLength;
406 optMinBlockLenth.size = sizeof(int);
407 optMinBlockLenth.type = kUridAtomInt;
408 optMinBlockLenth.value = &minBufferSize;
410 LV2_Options_Option& optNominalBlockLenth(opts[NominalBlockLenth]);
411 optNominalBlockLenth.context = LV2_OPTIONS_INSTANCE;
412 optNominalBlockLenth.subject = 0;
413 optNominalBlockLenth.key = kUridBufNominalLength;
414 optNominalBlockLenth.size = sizeof(int);
415 optNominalBlockLenth.type = kUridAtomInt;
416 optNominalBlockLenth.value = &nominalBufferSize;
418 LV2_Options_Option& optSequenceSize(opts[SequenceSize]);
419 optSequenceSize.context = LV2_OPTIONS_INSTANCE;
420 optSequenceSize.subject = 0;
421 optSequenceSize.key = kUridBufSequenceSize;
422 optSequenceSize.size = sizeof(int);
423 optSequenceSize.type = kUridAtomInt;
424 optSequenceSize.value = &sequenceSize;
426 LV2_Options_Option& optBackgroundColor(opts[BackgroundColor]);
427 optBackgroundColor.context = LV2_OPTIONS_INSTANCE;
428 optBackgroundColor.subject = 0;
429 optBackgroundColor.key = kUridBackgroundColor;
430 optBackgroundColor.size = sizeof(int32_t);
431 optBackgroundColor.type = kUridAtomInt;
432 optBackgroundColor.value = &bgColor;
434 LV2_Options_Option& optForegroundColor(opts[ForegroundColor]);
435 optForegroundColor.context = LV2_OPTIONS_INSTANCE;
436 optForegroundColor.subject = 0;
437 optForegroundColor.key = kUridForegroundColor;
438 optForegroundColor.size = sizeof(int32_t);
439 optForegroundColor.type = kUridAtomInt;
440 optForegroundColor.value = &fgColor;
442 #ifndef CARLA_OS_MAC
443 LV2_Options_Option& optScaleFactor(opts[ScaleFactor]);
444 optScaleFactor.context = LV2_OPTIONS_INSTANCE;
445 optScaleFactor.subject = 0;
446 optScaleFactor.key = kUridScaleFactor;
447 optScaleFactor.size = sizeof(float);
448 optScaleFactor.type = kUridAtomFloat;
449 optScaleFactor.value = &uiScale;
450 #endif
452 LV2_Options_Option& optSampleRate(opts[SampleRate]);
453 optSampleRate.context = LV2_OPTIONS_INSTANCE;
454 optSampleRate.subject = 0;
455 optSampleRate.key = kUridParamSampleRate;
456 optSampleRate.size = sizeof(float);
457 optSampleRate.type = kUridAtomFloat;
458 optSampleRate.value = &sampleRate;
460 LV2_Options_Option& optTransientWinId(opts[TransientWinId]);
461 optTransientWinId.context = LV2_OPTIONS_INSTANCE;
462 optTransientWinId.subject = 0;
463 optTransientWinId.key = kUridCarlaTransientWindowId;
464 optTransientWinId.size = sizeof(int64_t);
465 optTransientWinId.type = kUridAtomLong;
466 optTransientWinId.value = &transientWinId;
468 LV2_Options_Option& optWindowTitle(opts[WindowTitle]);
469 optWindowTitle.context = LV2_OPTIONS_INSTANCE;
470 optWindowTitle.subject = 0;
471 optWindowTitle.key = kUridWindowTitle;
472 optWindowTitle.size = 0;
473 optWindowTitle.type = kUridAtomString;
474 optWindowTitle.value = nullptr;
476 LV2_Options_Option& optNull(opts[Null]);
477 optNull.context = LV2_OPTIONS_INSTANCE;
478 optNull.subject = 0;
479 optNull.key = kUridNull;
480 optNull.size = 0;
481 optNull.type = kUridNull;
482 optNull.value = nullptr;
485 ~CarlaPluginLV2Options() noexcept
487 LV2_Options_Option& optWindowTitle(opts[WindowTitle]);
489 optWindowTitle.size = 0;
490 optWindowTitle.value = nullptr;
492 if (windowTitle != nullptr)
494 std::free(const_cast<char*>(windowTitle));
495 windowTitle = nullptr;
499 CARLA_DECLARE_NON_COPYABLE(CarlaPluginLV2Options);
502 #ifndef LV2_UIS_ONLY_INPROCESS
503 // -------------------------------------------------------------------------------------------------------------------
505 class CarlaPluginLV2;
507 class CarlaPipeServerLV2 : public CarlaPipeServer
509 public:
510 enum UiState {
511 UiNone = 0,
512 UiHide,
513 UiShow,
514 UiCrashed
517 CarlaPipeServerLV2(CarlaEngine* const engine, CarlaPluginLV2* const plugin)
518 : kEngine(engine),
519 kPlugin(plugin),
520 fFilename(),
521 fPluginURI(),
522 fUiURI(),
523 fUiState(UiNone) {}
525 ~CarlaPipeServerLV2() noexcept override
527 CARLA_SAFE_ASSERT_INT(fUiState == UiNone, fUiState);
530 UiState getAndResetUiState() noexcept
532 const UiState uiState(fUiState);
533 fUiState = UiNone;
534 return uiState;
537 void setData(const char* const filename, const char* const pluginURI, const char* const uiURI) noexcept
539 fFilename = filename;
540 fPluginURI = pluginURI;
541 fUiURI = uiURI;
544 bool startPipeServer(const int size) noexcept
546 char sampleRateStr[32];
548 const CarlaScopedLocale csl;
549 std::snprintf(sampleRateStr, 31, "%.12g", kEngine->getSampleRate());
551 sampleRateStr[31] = '\0';
553 const ScopedEngineEnvironmentLocker _seel(kEngine);
554 const CarlaScopedEnvVar _sev1("LV2_PATH", kEngine->getOptions().pathLV2);
555 #ifdef CARLA_OS_LINUX
556 const CarlaScopedEnvVar _sev2("LD_PRELOAD", nullptr);
557 #endif
558 carla_setenv("CARLA_SAMPLE_RATE", sampleRateStr);
560 return CarlaPipeServer::startPipeServer(fFilename, fPluginURI, fUiURI, size);
563 void writeUiTitleMessage(const char* const title) const noexcept
565 CARLA_SAFE_ASSERT_RETURN(title != nullptr && title[0] != '\0',);
567 const CarlaMutexLocker cml(getPipeLock());
569 if (! _writeMsgBuffer("uiTitle\n", 8))
570 return;
571 if (! writeAndFixMessage(title))
572 return;
574 syncMessages();
577 protected:
578 // returns true if msg was handled
579 bool msgReceived(const char* const msg) noexcept override;
581 private:
582 CarlaEngine* const kEngine;
583 CarlaPluginLV2* const kPlugin;
585 CarlaString fFilename;
586 CarlaString fPluginURI;
587 CarlaString fUiURI;
588 UiState fUiState;
590 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPipeServerLV2)
593 // -------------------------------------------------------------------------------------------------------------------
594 #endif
596 static void initAtomForge(LV2_Atom_Forge& atomForge) noexcept
598 carla_zeroStruct(atomForge);
600 atomForge.Bool = kUridAtomBool;
601 atomForge.Chunk = kUridAtomChunk;
602 atomForge.Double = kUridAtomDouble;
603 atomForge.Float = kUridAtomFloat;
604 atomForge.Int = kUridAtomInt;
605 atomForge.Literal = kUridAtomLiteral;
606 atomForge.Long = kUridAtomLong;
607 atomForge.Object = kUridAtomObject;
608 atomForge.Path = kUridAtomPath;
609 atomForge.Property = kUridAtomProperty;
610 atomForge.Sequence = kUridAtomSequence;
611 atomForge.String = kUridAtomString;
612 atomForge.Tuple = kUridAtomTuple;
613 atomForge.URI = kUridAtomURI;
614 atomForge.URID = kUridAtomURID;
615 atomForge.Vector = kUridAtomVector;
617 #if defined(__clang__)
618 # pragma clang diagnostic push
619 # pragma clang diagnostic ignored "-Wdeprecated-declarations"
620 #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
621 # pragma GCC diagnostic push
622 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
623 #endif
624 atomForge.Blank = kUridAtomBlank;
625 atomForge.Resource = kUridAtomResource;
626 #if defined(__clang__)
627 # pragma clang diagnostic pop
628 #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
629 # pragma GCC diagnostic pop
630 #endif
633 // -------------------------------------------------------------------------------------------------------------------
635 class CarlaPluginLV2 : public CarlaPlugin,
636 private CarlaPluginUI::Callback
638 public:
639 CarlaPluginLV2(CarlaEngine* const engine, const uint id)
640 : CarlaPlugin(engine, id),
641 fHandle(nullptr),
642 fHandle2(nullptr),
643 fDescriptor(nullptr),
644 fRdfDescriptor(nullptr),
645 fAudioInBuffers(nullptr),
646 fAudioOutBuffers(nullptr),
647 fCvInBuffers(nullptr),
648 fCvOutBuffers(nullptr),
649 fParamBuffers(nullptr),
650 fHasLoadDefaultState(false),
651 fHasThreadSafeRestore(false),
652 fNeedsFixedBuffers(false),
653 fNeedsUiClose(false),
654 fInlineDisplayNeedsRedraw(false),
655 fInlineDisplayLastRedrawTime(0),
656 fLatencyIndex(-1),
657 fStrictBounds(-1),
658 fAtomBufferEvIn(),
659 fAtomBufferUiOut(),
660 fAtomBufferWorkerIn(),
661 fAtomBufferWorkerResp(),
662 fAtomBufferUiOutTmpData(nullptr),
663 fAtomBufferWorkerInTmpData(nullptr),
664 fAtomBufferRealtime(nullptr),
665 fAtomBufferRealtimeSize(0),
666 fEventsIn(),
667 fEventsOut(),
668 fLv2Options(),
669 #ifndef LV2_UIS_ONLY_INPROCESS
670 fPipeServer(engine, this),
671 #endif
672 fCustomURIDs(kUridCount, std::string("urn:null")),
673 fFirstActive(true),
674 fLastStateChunk(nullptr),
675 fLastTimeInfo(),
676 fFilePathURI(),
677 fExt(),
678 fUI()
680 carla_debug("CarlaPluginLV2::CarlaPluginLV2(%p, %i)", engine, id);
681 CARLA_SAFE_ASSERT(fCustomURIDs.size() == kUridCount);
683 carla_zeroPointers(fFeatures, kFeatureCountAll+1);
684 carla_zeroPointers(fStateFeatures, kStateFeatureCountAll+1);
687 ~CarlaPluginLV2() override
689 carla_debug("CarlaPluginLV2::~CarlaPluginLV2()");
691 fInlineDisplayNeedsRedraw = false;
693 // close UI
694 if (fUI.type != UI::TYPE_NULL)
696 showCustomUI(false);
698 #ifndef LV2_UIS_ONLY_INPROCESS
699 if (fUI.type == UI::TYPE_BRIDGE)
701 fPipeServer.stopPipeServer(pData->engine->getOptions().uiBridgesTimeout);
703 else
704 #endif
706 if (fFeatures[kFeatureIdUiDataAccess] != nullptr && fFeatures[kFeatureIdUiDataAccess]->data != nullptr)
707 delete (LV2_Extension_Data_Feature*)fFeatures[kFeatureIdUiDataAccess]->data;
709 if (fFeatures[kFeatureIdUiPortMap] != nullptr && fFeatures[kFeatureIdUiPortMap]->data != nullptr)
710 delete (LV2UI_Port_Map*)fFeatures[kFeatureIdUiPortMap]->data;
712 if (fFeatures[kFeatureIdUiRequestValue] != nullptr && fFeatures[kFeatureIdUiRequestValue]->data != nullptr)
713 delete (LV2UI_Request_Value*)fFeatures[kFeatureIdUiRequestValue]->data;
715 if (fFeatures[kFeatureIdUiResize] != nullptr && fFeatures[kFeatureIdUiResize]->data != nullptr)
716 delete (LV2UI_Resize*)fFeatures[kFeatureIdUiResize]->data;
718 if (fFeatures[kFeatureIdUiTouch] != nullptr && fFeatures[kFeatureIdUiTouch]->data != nullptr)
719 delete (LV2UI_Touch*)fFeatures[kFeatureIdUiTouch]->data;
721 if (fFeatures[kFeatureIdExternalUi] != nullptr && fFeatures[kFeatureIdExternalUi]->data != nullptr)
722 delete (LV2_External_UI_Host*)fFeatures[kFeatureIdExternalUi]->data;
724 fUI.descriptor = nullptr;
725 pData->uiLibClose();
728 #ifndef LV2_UIS_ONLY_BRIDGES
729 if (fUI.window != nullptr)
731 delete fUI.window;
732 fUI.window = nullptr;
734 #endif
736 fUI.rdfDescriptor = nullptr;
739 pData->singleMutex.lock();
740 pData->masterMutex.lock();
742 if (pData->client != nullptr && pData->client->isActive())
743 pData->client->deactivate(true);
745 if (pData->active)
747 deactivate();
748 pData->active = false;
751 if (fExt.state != nullptr)
753 const File tmpDir(handleStateMapToAbsolutePath(false, false, true, "."));
755 if (tmpDir.exists())
756 tmpDir.deleteRecursively();
759 if (fDescriptor != nullptr)
761 if (fDescriptor->cleanup != nullptr)
763 if (fHandle != nullptr)
764 fDescriptor->cleanup(fHandle);
765 if (fHandle2 != nullptr)
766 fDescriptor->cleanup(fHandle2);
769 fHandle = nullptr;
770 fHandle2 = nullptr;
771 fDescriptor = nullptr;
774 if (fRdfDescriptor != nullptr)
776 delete fRdfDescriptor;
777 fRdfDescriptor = nullptr;
780 if (fFeatures[kFeatureIdEvent] != nullptr && fFeatures[kFeatureIdEvent]->data != nullptr)
781 delete (LV2_Event_Feature*)fFeatures[kFeatureIdEvent]->data;
783 if (fFeatures[kFeatureIdLogs] != nullptr && fFeatures[kFeatureIdLogs]->data != nullptr)
784 delete (LV2_Log_Log*)fFeatures[kFeatureIdLogs]->data;
786 if (fFeatures[kFeatureIdStateFreePath] != nullptr && fFeatures[kFeatureIdStateFreePath]->data != nullptr)
787 delete (LV2_State_Free_Path*)fFeatures[kFeatureIdStateFreePath]->data;
789 if (fFeatures[kFeatureIdStateMakePath] != nullptr && fFeatures[kFeatureIdStateMakePath]->data != nullptr)
790 delete (LV2_State_Make_Path*)fFeatures[kFeatureIdStateMakePath]->data;
792 if (fFeatures[kFeatureIdStateMapPath] != nullptr && fFeatures[kFeatureIdStateMapPath]->data != nullptr)
793 delete (LV2_State_Map_Path*)fFeatures[kFeatureIdStateMapPath]->data;
795 if (fFeatures[kFeatureIdPrograms] != nullptr && fFeatures[kFeatureIdPrograms]->data != nullptr)
796 delete (LV2_Programs_Host*)fFeatures[kFeatureIdPrograms]->data;
798 if (fFeatures[kFeatureIdResizePort] != nullptr && fFeatures[kFeatureIdResizePort]->data != nullptr)
799 delete (LV2_Resize_Port_Resize*)fFeatures[kFeatureIdResizePort]->data;
801 if (fFeatures[kFeatureIdRtMemPool] != nullptr && fFeatures[kFeatureIdRtMemPool]->data != nullptr)
802 delete (LV2_RtMemPool_Pool*)fFeatures[kFeatureIdRtMemPool]->data;
804 if (fFeatures[kFeatureIdRtMemPoolOld] != nullptr && fFeatures[kFeatureIdRtMemPoolOld]->data != nullptr)
805 delete (LV2_RtMemPool_Pool_Deprecated*)fFeatures[kFeatureIdRtMemPoolOld]->data;
807 if (fFeatures[kFeatureIdUriMap] != nullptr && fFeatures[kFeatureIdUriMap]->data != nullptr)
808 delete (LV2_URI_Map_Feature*)fFeatures[kFeatureIdUriMap]->data;
810 if (fFeatures[kFeatureIdUridMap] != nullptr && fFeatures[kFeatureIdUridMap]->data != nullptr)
811 delete (LV2_URID_Map*)fFeatures[kFeatureIdUridMap]->data;
813 if (fFeatures[kFeatureIdUridUnmap] != nullptr && fFeatures[kFeatureIdUridUnmap]->data != nullptr)
814 delete (LV2_URID_Unmap*)fFeatures[kFeatureIdUridUnmap]->data;
816 if (fFeatures[kFeatureIdWorker] != nullptr && fFeatures[kFeatureIdWorker]->data != nullptr)
817 delete (LV2_Worker_Schedule*)fFeatures[kFeatureIdWorker]->data;
819 if (fFeatures[kFeatureIdInlineDisplay] != nullptr && fFeatures[kFeatureIdInlineDisplay]->data != nullptr)
820 delete (LV2_Inline_Display*)fFeatures[kFeatureIdInlineDisplay]->data;
822 if (fFeatures[kFeatureIdMidnam] != nullptr && fFeatures[kFeatureIdMidnam]->data != nullptr)
823 delete (LV2_Midnam*)fFeatures[kFeatureIdMidnam]->data;
825 if (fFeatures[kFeatureIdCtrlInPortChangeReq] != nullptr && fFeatures[kFeatureIdCtrlInPortChangeReq]->data != nullptr)
826 delete (LV2_ControlInputPort_Change_Request*)fFeatures[kFeatureIdCtrlInPortChangeReq]->data;
828 for (uint32_t i=0; i < kFeatureCountAll; ++i)
830 if (fFeatures[i] != nullptr)
832 delete fFeatures[i];
833 fFeatures[i] = nullptr;
837 if (fStateFeatures[kStateFeatureIdMakePath] != nullptr && fStateFeatures[kStateFeatureIdMakePath]->data != nullptr)
838 delete (LV2_State_Make_Path*)fStateFeatures[kStateFeatureIdMakePath]->data;
840 if (fStateFeatures[kStateFeatureIdMapPath] != nullptr && fStateFeatures[kStateFeatureIdMapPath]->data != nullptr)
841 delete (LV2_State_Map_Path*)fStateFeatures[kStateFeatureIdMapPath]->data;
843 for (uint32_t i=0; i < kStateFeatureCountAll; ++i)
845 if (fStateFeatures[i] != nullptr)
847 delete fStateFeatures[i];
848 fStateFeatures[i] = nullptr;
852 if (fLastStateChunk != nullptr)
854 std::free(fLastStateChunk);
855 fLastStateChunk = nullptr;
858 if (fAtomBufferUiOutTmpData != nullptr)
860 delete[] fAtomBufferUiOutTmpData;
861 fAtomBufferUiOutTmpData = nullptr;
864 if (fAtomBufferWorkerInTmpData != nullptr)
866 delete[] fAtomBufferWorkerInTmpData;
867 fAtomBufferWorkerInTmpData = nullptr;
870 if (fAtomBufferRealtime != nullptr)
872 std::free(fAtomBufferRealtime);
873 fAtomBufferRealtime = nullptr;
876 clearBuffers();
879 // -------------------------------------------------------------------
880 // Information (base)
882 PluginType getType() const noexcept override
884 return PLUGIN_LV2;
887 PluginCategory getCategory() const noexcept override
889 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, CarlaPlugin::getCategory());
891 const LV2_Property cat1(fRdfDescriptor->Type[0]);
892 const LV2_Property cat2(fRdfDescriptor->Type[1]);
894 if (LV2_IS_DELAY(cat1, cat2))
895 return PLUGIN_CATEGORY_DELAY;
896 if (LV2_IS_DISTORTION(cat1, cat2))
897 return PLUGIN_CATEGORY_OTHER;
898 if (LV2_IS_DYNAMICS(cat1, cat2))
899 return PLUGIN_CATEGORY_DYNAMICS;
900 if (LV2_IS_EQ(cat1, cat2))
901 return PLUGIN_CATEGORY_EQ;
902 if (LV2_IS_FILTER(cat1, cat2))
903 return PLUGIN_CATEGORY_FILTER;
904 if (LV2_IS_GENERATOR(cat1, cat2))
905 return PLUGIN_CATEGORY_SYNTH;
906 if (LV2_IS_MODULATOR(cat1, cat2))
907 return PLUGIN_CATEGORY_MODULATOR;
908 if (LV2_IS_REVERB(cat1, cat2))
909 return PLUGIN_CATEGORY_DELAY;
910 if (LV2_IS_SIMULATOR(cat1, cat2))
911 return PLUGIN_CATEGORY_OTHER;
912 if (LV2_IS_SPATIAL(cat1, cat2))
913 return PLUGIN_CATEGORY_OTHER;
914 if (LV2_IS_SPECTRAL(cat1, cat2))
915 return PLUGIN_CATEGORY_UTILITY;
916 if (LV2_IS_UTILITY(cat1, cat2))
917 return PLUGIN_CATEGORY_UTILITY;
919 return CarlaPlugin::getCategory();
922 uint32_t getLatencyInFrames() const noexcept override
924 if (fLatencyIndex < 0 || fParamBuffers == nullptr)
925 return 0;
927 const float latency(fParamBuffers[fLatencyIndex]);
928 CARLA_SAFE_ASSERT_RETURN(latency >= 0.0f, 0);
930 return static_cast<uint32_t>(latency);
933 // -------------------------------------------------------------------
934 // Information (count)
936 uint32_t getMidiInCount() const noexcept override
938 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, 0);
940 uint32_t count = 0;
942 for (uint32_t i=0; i < fRdfDescriptor->PortCount; ++i)
944 const LV2_Property portTypes(fRdfDescriptor->Ports[i].Types);
946 if (LV2_IS_PORT_INPUT(portTypes) && LV2_PORT_SUPPORTS_MIDI_EVENT(portTypes))
947 ++count;
950 return count;
953 uint32_t getMidiOutCount() const noexcept override
955 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, 0);
957 uint32_t count = 0;
959 for (uint32_t i=0; i < fRdfDescriptor->PortCount; ++i)
961 const LV2_Property portTypes(fRdfDescriptor->Ports[i].Types);
963 if (LV2_IS_PORT_OUTPUT(portTypes) && LV2_PORT_SUPPORTS_MIDI_EVENT(portTypes))
964 ++count;
967 return count;
970 uint32_t getParameterScalePointCount(const uint32_t parameterId) const noexcept override
972 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, 0);
973 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0);
975 const int32_t rindex(pData->param.data[parameterId].rindex);
977 if (rindex < static_cast<int32_t>(fRdfDescriptor->PortCount))
979 const LV2_RDF_Port* const port(&fRdfDescriptor->Ports[rindex]);
980 return port->ScalePointCount;
983 return 0;
986 // -------------------------------------------------------------------
987 // Information (current data)
989 uint getAudioPortHints(bool isOutput, uint32_t portIndex) const noexcept override
991 uint hints = 0x0;
993 for (uint32_t i=0, j=0; i<fRdfDescriptor->PortCount; ++i)
995 LV2_RDF_Port& port(fRdfDescriptor->Ports[i]);
997 if (! LV2_IS_PORT_AUDIO(port.Types))
998 continue;
1000 if (isOutput)
1002 if (! LV2_IS_PORT_OUTPUT(port.Types))
1003 continue;
1005 else
1007 if (! LV2_IS_PORT_INPUT(port.Types))
1008 continue;
1011 if (j++ != portIndex)
1012 continue;
1014 if (LV2_IS_PORT_SIDECHAIN(port.Properties))
1015 hints |= AUDIO_PORT_IS_SIDECHAIN;
1017 break;
1020 return hints;
1023 // -------------------------------------------------------------------
1024 // Information (per-plugin data)
1026 uint getOptionsAvailable() const noexcept override
1028 uint options = 0x0;
1030 // can't disable fixed buffers if using latency or MIDI output
1031 if (fLatencyIndex == -1 && getMidiOutCount() == 0 && ! fNeedsFixedBuffers)
1032 options |= PLUGIN_OPTION_FIXED_BUFFERS;
1034 // can't disable forced stereo if enabled in the engine
1035 if (pData->engine->getOptions().forceStereo)
1036 pass();
1037 // if there are event outputs, we can't force stereo
1038 else if (fEventsOut.count != 0)
1039 pass();
1040 // if inputs or outputs are just 1, then yes we can force stereo
1041 else if ((pData->audioIn.count == 1 || pData->audioOut.count == 1) || fHandle2 != nullptr)
1042 options |= PLUGIN_OPTION_FORCE_STEREO;
1044 if (fExt.programs != nullptr)
1045 options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
1047 if (getMidiInCount() != 0)
1049 options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
1050 options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
1051 options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
1052 options |= PLUGIN_OPTION_SEND_PITCHBEND;
1053 options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
1054 options |= PLUGIN_OPTION_SEND_PROGRAM_CHANGES;
1055 options |= PLUGIN_OPTION_SKIP_SENDING_NOTES;
1058 return options;
1061 float getParameterValue(const uint32_t parameterId) const noexcept override
1063 CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr, 0.0f);
1064 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f);
1066 if (pData->param.data[parameterId].type == PARAMETER_INPUT)
1068 if (pData->param.data[parameterId].hints & PARAMETER_IS_STRICT_BOUNDS)
1069 pData->param.ranges[parameterId].fixValue(fParamBuffers[parameterId]);
1071 else
1073 if (fStrictBounds >= 0 && (pData->param.data[parameterId].hints & PARAMETER_IS_STRICT_BOUNDS) == 0)
1074 pData->param.ranges[parameterId].fixValue(fParamBuffers[parameterId]);
1077 return fParamBuffers[parameterId];
1080 float getParameterScalePointValue(const uint32_t parameterId, const uint32_t scalePointId) const noexcept override
1082 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, 0.0f);
1083 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f);
1085 const int32_t rindex(pData->param.data[parameterId].rindex);
1087 if (rindex < static_cast<int32_t>(fRdfDescriptor->PortCount))
1089 const LV2_RDF_Port* const port(&fRdfDescriptor->Ports[rindex]);
1090 CARLA_SAFE_ASSERT_RETURN(scalePointId < port->ScalePointCount, 0.0f);
1092 const LV2_RDF_PortScalePoint* const portScalePoint(&port->ScalePoints[scalePointId]);
1093 return portScalePoint->Value;
1096 return 0.0f;
1099 bool getLabel(char* const strBuf) const noexcept override
1101 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
1102 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor->URI != nullptr, false);
1104 std::strncpy(strBuf, fRdfDescriptor->URI, STR_MAX);
1105 return true;
1108 bool getMaker(char* const strBuf) const noexcept override
1110 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
1112 if (fRdfDescriptor->Author != nullptr)
1114 std::strncpy(strBuf, fRdfDescriptor->Author, STR_MAX);
1115 return true;
1118 return false;
1121 bool getCopyright(char* const strBuf) const noexcept override
1123 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
1125 if (fRdfDescriptor->License != nullptr)
1127 std::strncpy(strBuf, fRdfDescriptor->License, STR_MAX);
1128 return true;
1131 return false;
1134 bool getRealName(char* const strBuf) const noexcept override
1136 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
1138 if (fRdfDescriptor->Name != nullptr)
1140 std::strncpy(strBuf, fRdfDescriptor->Name, STR_MAX);
1141 return true;
1144 return false;
1147 bool getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override
1149 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
1150 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
1152 int32_t rindex = pData->param.data[parameterId].rindex;
1153 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
1155 if (rindex < static_cast<int32_t>(fRdfDescriptor->PortCount))
1157 std::strncpy(strBuf, fRdfDescriptor->Ports[rindex].Name, STR_MAX);
1158 return true;
1161 rindex -= static_cast<int32_t>(fRdfDescriptor->PortCount);
1163 if (rindex < static_cast<int32_t>(fRdfDescriptor->ParameterCount))
1165 std::strncpy(strBuf, fRdfDescriptor->Parameters[rindex].Label, STR_MAX);
1166 return true;
1169 return CarlaPlugin::getParameterName(parameterId, strBuf);
1172 bool getParameterSymbol(const uint32_t parameterId, char* const strBuf) const noexcept override
1174 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
1175 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
1177 int32_t rindex = pData->param.data[parameterId].rindex;
1178 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
1180 if (rindex < static_cast<int32_t>(fRdfDescriptor->PortCount))
1182 std::strncpy(strBuf, fRdfDescriptor->Ports[rindex].Symbol, STR_MAX);
1183 return true;
1186 rindex -= static_cast<int32_t>(fRdfDescriptor->PortCount);
1188 if (rindex < static_cast<int32_t>(fRdfDescriptor->ParameterCount))
1190 std::strncpy(strBuf, fRdfDescriptor->Parameters[rindex].URI, STR_MAX);
1191 return true;
1194 return CarlaPlugin::getParameterSymbol(parameterId, strBuf);
1197 bool getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override
1199 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
1200 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
1202 LV2_RDF_PortUnit* portUnit = nullptr;
1204 int32_t rindex = pData->param.data[parameterId].rindex;
1205 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
1207 if (rindex < static_cast<int32_t>(fRdfDescriptor->PortCount))
1209 portUnit = &fRdfDescriptor->Ports[rindex].Unit;
1211 else
1213 rindex -= static_cast<int32_t>(fRdfDescriptor->PortCount);
1215 if (rindex < static_cast<int32_t>(fRdfDescriptor->ParameterCount))
1217 portUnit = &fRdfDescriptor->Parameters[rindex].Unit;
1221 if (portUnit != nullptr)
1223 if (LV2_HAVE_PORT_UNIT_SYMBOL(portUnit->Hints) && portUnit->Symbol != nullptr)
1225 std::strncpy(strBuf, portUnit->Symbol, STR_MAX);
1226 return true;
1229 if (LV2_HAVE_PORT_UNIT_UNIT(portUnit->Hints))
1231 switch (portUnit->Unit)
1233 case LV2_PORT_UNIT_BAR:
1234 std::strncpy(strBuf, "bars", STR_MAX);
1235 return true;
1236 case LV2_PORT_UNIT_BEAT:
1237 std::strncpy(strBuf, "beats", STR_MAX);
1238 return true;
1239 case LV2_PORT_UNIT_BPM:
1240 std::strncpy(strBuf, "BPM", STR_MAX);
1241 return true;
1242 case LV2_PORT_UNIT_CENT:
1243 std::strncpy(strBuf, "ct", STR_MAX);
1244 return true;
1245 case LV2_PORT_UNIT_CM:
1246 std::strncpy(strBuf, "cm", STR_MAX);
1247 return true;
1248 case LV2_PORT_UNIT_COEF:
1249 std::strncpy(strBuf, "(coef)", STR_MAX);
1250 return true;
1251 case LV2_PORT_UNIT_DB:
1252 std::strncpy(strBuf, "dB", STR_MAX);
1253 return true;
1254 case LV2_PORT_UNIT_DEGREE:
1255 std::strncpy(strBuf, "deg", STR_MAX);
1256 return true;
1257 case LV2_PORT_UNIT_FRAME:
1258 std::strncpy(strBuf, "frames", STR_MAX);
1259 return true;
1260 case LV2_PORT_UNIT_HZ:
1261 std::strncpy(strBuf, "Hz", STR_MAX);
1262 return true;
1263 case LV2_PORT_UNIT_INCH:
1264 std::strncpy(strBuf, "in", STR_MAX);
1265 return true;
1266 case LV2_PORT_UNIT_KHZ:
1267 std::strncpy(strBuf, "kHz", STR_MAX);
1268 return true;
1269 case LV2_PORT_UNIT_KM:
1270 std::strncpy(strBuf, "km", STR_MAX);
1271 return true;
1272 case LV2_PORT_UNIT_M:
1273 std::strncpy(strBuf, "m", STR_MAX);
1274 return true;
1275 case LV2_PORT_UNIT_MHZ:
1276 std::strncpy(strBuf, "MHz", STR_MAX);
1277 return true;
1278 case LV2_PORT_UNIT_MIDINOTE:
1279 std::strncpy(strBuf, "note", STR_MAX);
1280 return true;
1281 case LV2_PORT_UNIT_MILE:
1282 std::strncpy(strBuf, "mi", STR_MAX);
1283 return true;
1284 case LV2_PORT_UNIT_MIN:
1285 std::strncpy(strBuf, "min", STR_MAX);
1286 return true;
1287 case LV2_PORT_UNIT_MM:
1288 std::strncpy(strBuf, "mm", STR_MAX);
1289 return true;
1290 case LV2_PORT_UNIT_MS:
1291 std::strncpy(strBuf, "ms", STR_MAX);
1292 return true;
1293 case LV2_PORT_UNIT_OCT:
1294 std::strncpy(strBuf, "oct", STR_MAX);
1295 return true;
1296 case LV2_PORT_UNIT_PC:
1297 std::strncpy(strBuf, "%", STR_MAX);
1298 return true;
1299 case LV2_PORT_UNIT_S:
1300 std::strncpy(strBuf, "s", STR_MAX);
1301 return true;
1302 case LV2_PORT_UNIT_SEMITONE:
1303 std::strncpy(strBuf, "semi", STR_MAX);
1304 return true;
1305 case LV2_PORT_UNIT_VOLTS:
1306 std::strncpy(strBuf, "v", STR_MAX);
1307 return true;
1312 return CarlaPlugin::getParameterUnit(parameterId, strBuf);
1315 bool getParameterComment(const uint32_t parameterId, char* const strBuf) const noexcept override
1317 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
1318 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
1320 int32_t rindex = pData->param.data[parameterId].rindex;
1321 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
1323 if (rindex < static_cast<int32_t>(fRdfDescriptor->PortCount))
1325 if (const char* const comment = fRdfDescriptor->Ports[rindex].Comment)
1327 std::strncpy(strBuf, comment, STR_MAX);
1328 return true;
1330 return false;
1333 rindex -= static_cast<int32_t>(fRdfDescriptor->PortCount);
1335 if (rindex < static_cast<int32_t>(fRdfDescriptor->ParameterCount))
1337 if (const char* const comment = fRdfDescriptor->Parameters[rindex].Comment)
1339 std::strncpy(strBuf, comment, STR_MAX);
1340 return true;
1342 return false;
1345 return CarlaPlugin::getParameterComment(parameterId, strBuf);
1348 bool getParameterGroupName(const uint32_t parameterId, char* const strBuf) const noexcept override
1350 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
1351 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
1353 int32_t rindex = pData->param.data[parameterId].rindex;
1354 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
1356 const char* uri = nullptr;
1358 if (rindex < static_cast<int32_t>(fRdfDescriptor->PortCount))
1360 uri = fRdfDescriptor->Ports[rindex].GroupURI;
1362 else
1364 rindex -= static_cast<int32_t>(fRdfDescriptor->PortCount);
1366 if (rindex < static_cast<int32_t>(fRdfDescriptor->ParameterCount))
1367 uri = fRdfDescriptor->Parameters[rindex].GroupURI;
1370 if (uri == nullptr)
1371 return false;
1373 for (uint32_t i=0; i<fRdfDescriptor->PortGroupCount; ++i)
1375 if (std::strcmp(fRdfDescriptor->PortGroups[i].URI, uri) == 0)
1377 const char* const name = fRdfDescriptor->PortGroups[i].Name;
1378 const char* const symbol = fRdfDescriptor->PortGroups[i].Symbol;
1380 if (name != nullptr && symbol != nullptr)
1382 std::snprintf(strBuf, STR_MAX, "%s:%s", symbol, name);
1383 return true;
1385 return false;
1389 return false;
1392 bool getParameterScalePointLabel(const uint32_t parameterId, const uint32_t scalePointId, char* const strBuf) const noexcept override
1394 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
1395 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
1397 const int32_t rindex(pData->param.data[parameterId].rindex);
1398 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
1400 if (rindex < static_cast<int32_t>(fRdfDescriptor->PortCount))
1402 const LV2_RDF_Port* const port(&fRdfDescriptor->Ports[rindex]);
1403 CARLA_SAFE_ASSERT_RETURN(scalePointId < port->ScalePointCount, false);
1405 const LV2_RDF_PortScalePoint* const portScalePoint(&port->ScalePoints[scalePointId]);
1407 if (portScalePoint->Label != nullptr)
1409 std::strncpy(strBuf, portScalePoint->Label, STR_MAX);
1410 return true;
1414 return CarlaPlugin::getParameterScalePointLabel(parameterId, scalePointId, strBuf);
1417 // -------------------------------------------------------------------
1418 // Set data (state)
1420 void prepareForSave(const bool temporary) override
1422 CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
1424 if (fExt.state != nullptr && fExt.state->save != nullptr)
1426 // move temporary stuff to main state dir on full save
1427 if (! temporary)
1429 const File tmpDir(handleStateMapToAbsolutePath(false, false, true, "."));
1431 if (tmpDir.exists())
1433 const File stateDir(handleStateMapToAbsolutePath(true, false, false, "."));
1435 if (stateDir.isNotNull())
1436 tmpDir.moveFileTo(stateDir);
1440 fExt.state->save(fHandle, carla_lv2_state_store, this, LV2_STATE_IS_POD, fStateFeatures);
1442 if (fHandle2 != nullptr)
1443 fExt.state->save(fHandle2, carla_lv2_state_store, this, LV2_STATE_IS_POD, fStateFeatures);
1447 // -------------------------------------------------------------------
1448 // Set data (internal stuff)
1450 void setName(const char* const newName) override
1452 const File tmpDir1(handleStateMapToAbsolutePath(false, false, true, "."));
1454 CarlaPlugin::setName(newName);
1456 if (tmpDir1.exists())
1458 const File tmpDir2(handleStateMapToAbsolutePath(false, false, true, "."));
1460 carla_stdout("dir1 %s, dir2 %s",
1461 tmpDir1.getFullPathName().toRawUTF8(),
1462 tmpDir2.getFullPathName().toRawUTF8());
1464 if (tmpDir2.isNotNull())
1466 if (tmpDir2.exists())
1467 tmpDir2.deleteRecursively();
1469 tmpDir1.moveFileTo(tmpDir2);
1473 if (fLv2Options.windowTitle != nullptr && pData->uiTitle.isEmpty())
1474 setWindowTitle(nullptr);
1477 void setWindowTitle(const char* const title) noexcept
1479 CarlaString uiTitle;
1481 if (title != nullptr)
1483 uiTitle = title;
1485 else
1487 uiTitle = pData->name;
1488 uiTitle += " (GUI)";
1491 std::free(const_cast<char*>(fLv2Options.windowTitle));
1492 fLv2Options.windowTitle = uiTitle.releaseBufferPointer();
1494 fLv2Options.opts[CarlaPluginLV2Options::WindowTitle].size = (uint32_t)std::strlen(fLv2Options.windowTitle);
1495 fLv2Options.opts[CarlaPluginLV2Options::WindowTitle].value = fLv2Options.windowTitle;
1497 if (fFeatures[kFeatureIdExternalUi] != nullptr && fFeatures[kFeatureIdExternalUi]->data != nullptr)
1498 ((LV2_External_UI_Host*)fFeatures[kFeatureIdExternalUi]->data)->plugin_human_id = fLv2Options.windowTitle;
1500 #ifndef LV2_UIS_ONLY_INPROCESS
1501 if (fPipeServer.isPipeRunning())
1502 fPipeServer.writeUiTitleMessage(fLv2Options.windowTitle);
1503 #endif
1505 #ifndef LV2_UIS_ONLY_BRIDGES
1506 if (fUI.window != nullptr)
1508 try {
1509 fUI.window->setTitle(fLv2Options.windowTitle);
1510 } CARLA_SAFE_EXCEPTION("set custom title");
1512 #endif
1515 // -------------------------------------------------------------------
1516 // Set data (plugin-specific stuff)
1518 float setParamterValueCommon(const uint32_t parameterId, const float value) noexcept
1520 const float fixedValue(pData->param.getFixedValue(parameterId, value));
1521 fParamBuffers[parameterId] = fixedValue;
1523 if (pData->param.data[parameterId].rindex >= static_cast<int32_t>(fRdfDescriptor->PortCount))
1525 const uint32_t rparamId = static_cast<uint32_t>(pData->param.data[parameterId].rindex) - fRdfDescriptor->PortCount;
1526 CARLA_SAFE_ASSERT_UINT2_RETURN(rparamId < fRdfDescriptor->ParameterCount,
1527 rparamId, fRdfDescriptor->PortCount, fixedValue);
1529 uint8_t atomBuf[256];
1530 LV2_Atom_Forge atomForge;
1531 initAtomForge(atomForge);
1532 lv2_atom_forge_set_buffer(&atomForge, atomBuf, sizeof(atomBuf));
1534 LV2_Atom_Forge_Frame forgeFrame;
1535 lv2_atom_forge_object(&atomForge, &forgeFrame, kUridNull, kUridPatchSet);
1537 lv2_atom_forge_key(&atomForge, kUridCarlaParameterChange);
1538 lv2_atom_forge_bool(&atomForge, true);
1540 lv2_atom_forge_key(&atomForge, kUridPatchProperty);
1541 lv2_atom_forge_urid(&atomForge, getCustomURID(fRdfDescriptor->Parameters[rparamId].URI));
1543 lv2_atom_forge_key(&atomForge, kUridPatchValue);
1545 switch (fRdfDescriptor->Parameters[rparamId].Type)
1547 case LV2_PARAMETER_TYPE_BOOL:
1548 lv2_atom_forge_bool(&atomForge, fixedValue > 0.5f);
1549 break;
1550 case LV2_PARAMETER_TYPE_INT:
1551 lv2_atom_forge_int(&atomForge, static_cast<int32_t>(fixedValue + 0.5f));
1552 break;
1553 case LV2_PARAMETER_TYPE_LONG:
1554 lv2_atom_forge_long(&atomForge, static_cast<int64_t>(fixedValue + 0.5f));
1555 break;
1556 case LV2_PARAMETER_TYPE_FLOAT:
1557 lv2_atom_forge_float(&atomForge, fixedValue);
1558 break;
1559 case LV2_PARAMETER_TYPE_DOUBLE:
1560 lv2_atom_forge_double(&atomForge, fixedValue);
1561 break;
1562 default:
1563 carla_stderr2("setParameterValue called for invalid parameter, expect issues!");
1564 break;
1567 lv2_atom_forge_pop(&atomForge, &forgeFrame);
1569 LV2_Atom* const atom((LV2_Atom*)atomBuf);
1570 CARLA_SAFE_ASSERT(atom->size < sizeof(atomBuf));
1572 fAtomBufferEvIn.put(atom, fEventsIn.ctrlIndex);
1575 return fixedValue;
1578 void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
1580 CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr,);
1581 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
1583 const float fixedValue = setParamterValueCommon(parameterId, value);
1585 CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback);
1588 void setParameterValueRT(const uint32_t parameterId, const float value, const uint32_t frameOffset, const bool sendCallbackLater) noexcept override
1590 CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr,);
1591 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
1593 const float fixedValue = setParamterValueCommon(parameterId, value);
1595 CarlaPlugin::setParameterValueRT(parameterId, fixedValue, frameOffset, sendCallbackLater);
1598 void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override
1600 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
1601 CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
1602 CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',);
1603 CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
1604 CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
1605 carla_debug("CarlaPluginLV2::setCustomData(\"%s\", \"%s\", \"%s\", %s)", type, key, value, bool2str(sendGui));
1607 if (std::strcmp(type, CUSTOM_DATA_TYPE_PATH) == 0)
1609 if (std::strcmp(key, "file") != 0)
1610 return;
1612 CARLA_SAFE_ASSERT_RETURN(fFilePathURI.isNotEmpty(),);
1613 CARLA_SAFE_ASSERT_RETURN(value[0] != '\0',);
1615 carla_stdout("LV2 file path to send: '%s'", value);
1616 writeAtomPath(value, getCustomURID(fFilePathURI));
1617 return;
1620 if (std::strcmp(type, CUSTOM_DATA_TYPE_PROPERTY) == 0)
1621 return CarlaPlugin::setCustomData(type, key, value, sendGui);
1623 // See if this key is from a parameter exposed by carla, apply value if yes
1624 for (uint32_t i=0; i < fRdfDescriptor->ParameterCount; ++i)
1626 const LV2_RDF_Parameter& rdfParam(fRdfDescriptor->Parameters[i]);
1628 if (std::strcmp(rdfParam.URI, key) == 0)
1630 uint32_t parameterId = UINT32_MAX;
1631 const int32_t rindex = static_cast<int32_t>(fRdfDescriptor->PortCount + i);
1633 switch (rdfParam.Type)
1635 case LV2_PARAMETER_TYPE_BOOL:
1636 case LV2_PARAMETER_TYPE_INT:
1637 // case LV2_PARAMETER_TYPE_LONG:
1638 case LV2_PARAMETER_TYPE_FLOAT:
1639 case LV2_PARAMETER_TYPE_DOUBLE:
1640 for (uint32_t j=0; j < pData->param.count; ++j)
1642 if (pData->param.data[j].rindex == rindex)
1644 parameterId = j;
1645 break;
1648 break;
1651 if (parameterId == UINT32_MAX)
1652 break;
1654 std::vector<uint8_t> chunk(carla_getChunkFromBase64String(value));
1655 CARLA_SAFE_ASSERT_RETURN(chunk.size() > 0,);
1657 #ifdef CARLA_PROPER_CPP11_SUPPORT
1658 const uint8_t* const valueptr = chunk.data();
1659 #else
1660 const uint8_t* const valueptr = &chunk.front();
1661 #endif
1662 float rvalue;
1664 switch (rdfParam.Type)
1666 case LV2_PARAMETER_TYPE_BOOL:
1667 rvalue = *(const int32_t*)valueptr != 0 ? 1.0f : 0.0f;
1668 break;
1669 case LV2_PARAMETER_TYPE_INT:
1670 rvalue = static_cast<float>(*(const int32_t*)valueptr);
1671 break;
1672 case LV2_PARAMETER_TYPE_FLOAT:
1673 rvalue = *(const float*)valueptr;
1674 break;
1675 case LV2_PARAMETER_TYPE_DOUBLE:
1676 rvalue = static_cast<float>(*(const double*)valueptr);
1677 break;
1678 default:
1679 // making compilers happy
1680 rvalue = pData->param.ranges[parameterId].def;
1681 break;
1684 fParamBuffers[parameterId] = pData->param.getFixedValue(parameterId, rvalue);
1685 break;
1689 CarlaPlugin::setCustomData(type, key, value, sendGui);
1692 void setProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool doingInit) noexcept override
1694 CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
1695 CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->prog.count),);
1696 CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,);
1698 if (index >= 0 && index < static_cast<int32_t>(fRdfDescriptor->PresetCount))
1700 const LV2_URID_Map* const uridMap = (const LV2_URID_Map*)fFeatures[kFeatureIdUridMap]->data;
1702 LilvState* const state = Lv2WorldClass::getInstance().getStateFromURI(fRdfDescriptor->Presets[index].URI,
1703 uridMap);
1704 CARLA_SAFE_ASSERT_RETURN(state != nullptr,);
1706 // invalidate midi-program selection
1707 CarlaPlugin::setMidiProgram(-1, false, false, sendCallback, false);
1709 if (fExt.state != nullptr)
1711 const bool block = (sendGui || sendOsc || sendCallback) && !fHasThreadSafeRestore;
1712 const ScopedSingleProcessLocker spl(this, block);
1714 lilv_state_restore(state, fExt.state, fHandle, carla_lilv_set_port_value, this, 0, fFeatures);
1716 if (fHandle2 != nullptr)
1717 lilv_state_restore(state, fExt.state, fHandle2, carla_lilv_set_port_value, this, 0, fFeatures);
1719 else
1721 lilv_state_emit_port_values(state, carla_lilv_set_port_value, this);
1724 lilv_state_free(state);
1727 CarlaPlugin::setProgram(index, sendGui, sendOsc, sendCallback, doingInit);
1730 void setMidiProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool doingInit) noexcept override
1732 CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
1733 CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->midiprog.count),);
1734 CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback || doingInit,);
1736 if (index >= 0 && fExt.programs != nullptr && fExt.programs->select_program != nullptr)
1738 const uint32_t bank(pData->midiprog.data[index].bank);
1739 const uint32_t program(pData->midiprog.data[index].program);
1741 const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback));
1743 try {
1744 fExt.programs->select_program(fHandle, bank, program);
1745 } CARLA_SAFE_EXCEPTION("select program");
1747 if (fHandle2 != nullptr)
1749 try {
1750 fExt.programs->select_program(fHandle2, bank, program);
1751 } CARLA_SAFE_EXCEPTION("select program 2");
1755 CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback, doingInit);
1758 void setMidiProgramRT(const uint32_t uindex, const bool sendCallbackLater) noexcept override
1760 CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
1761 CARLA_SAFE_ASSERT_RETURN(uindex < pData->midiprog.count,);
1763 if (fExt.programs != nullptr && fExt.programs->select_program != nullptr)
1765 const uint32_t bank(pData->midiprog.data[uindex].bank);
1766 const uint32_t program(pData->midiprog.data[uindex].program);
1768 try {
1769 fExt.programs->select_program(fHandle, bank, program);
1770 } CARLA_SAFE_EXCEPTION("select program RT");
1772 if (fHandle2 != nullptr)
1774 try {
1775 fExt.programs->select_program(fHandle2, bank, program);
1776 } CARLA_SAFE_EXCEPTION("select program RT 2");
1780 CarlaPlugin::setMidiProgramRT(uindex, sendCallbackLater);
1783 // -------------------------------------------------------------------
1784 // Set ui stuff
1786 void setCustomUITitle(const char* const title) noexcept override
1788 setWindowTitle(title);
1789 CarlaPlugin::setCustomUITitle(title);
1792 void showCustomUI(const bool yesNo) override
1794 if (fUI.type == UI::TYPE_NULL)
1796 if (yesNo && fFilePathURI.isNotEmpty())
1798 const char* const path = pData->engine->runFileCallback(FILE_CALLBACK_OPEN, false, "Open File", "");
1800 if (path != nullptr && path[0] != '\0')
1802 carla_stdout("LV2 file path to send: '%s'", path);
1803 writeAtomPath(path, getCustomURID(fFilePathURI));
1806 else
1808 CARLA_SAFE_ASSERT(!yesNo);
1810 pData->engine->callback(true, true,
1811 ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0, 0.0f, nullptr);
1812 return;
1815 const uintptr_t frontendWinId = pData->engine->getOptions().frontendWinId;
1817 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1818 if (! yesNo)
1819 pData->transientTryCounter = 0;
1820 #endif
1822 #ifndef LV2_UIS_ONLY_INPROCESS
1823 if (fUI.type == UI::TYPE_BRIDGE)
1825 if (yesNo)
1827 if (fPipeServer.isPipeRunning())
1829 fPipeServer.writeFocusMessage();
1830 return;
1833 if (! fPipeServer.startPipeServer(std::min(fLv2Options.sequenceSize, 819200)))
1835 pData->engine->callback(true, true,
1836 ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0, 0.0f, nullptr);
1837 return;
1840 // manually write messages so we can take the lock for ourselves
1842 char tmpBuf[0xff];
1843 tmpBuf[0xfe] = '\0';
1845 const CarlaMutexLocker cml(fPipeServer.getPipeLock());
1846 const CarlaScopedLocale csl;
1848 // write URI mappings
1849 uint32_t u = 0;
1850 for (std::vector<std::string>::iterator it=fCustomURIDs.begin(), end=fCustomURIDs.end(); it != end; ++it, ++u)
1852 if (u < kUridCount)
1853 continue;
1854 const std::string& uri(*it);
1856 if (! fPipeServer.writeMessage("urid\n", 5))
1857 return;
1859 std::snprintf(tmpBuf, 0xfe, "%u\n", u);
1860 if (! fPipeServer.writeMessage(tmpBuf))
1861 return;
1863 std::snprintf(tmpBuf, 0xfe, "%lu\n", static_cast<long unsigned>(uri.length()));
1864 if (! fPipeServer.writeMessage(tmpBuf))
1865 return;
1867 if (! fPipeServer.writeAndFixMessage(uri.c_str()))
1868 return;
1871 // write UI options
1872 if (! fPipeServer.writeMessage("uiOptions\n", 10))
1873 return;
1875 const EngineOptions& opts(pData->engine->getOptions());
1877 std::snprintf(tmpBuf, 0xff, "%g\n", pData->engine->getSampleRate());
1878 if (! fPipeServer.writeMessage(tmpBuf))
1879 return;
1881 std::snprintf(tmpBuf, 0xff, "%u\n", opts.bgColor);
1882 if (! fPipeServer.writeMessage(tmpBuf))
1883 return;
1885 std::snprintf(tmpBuf, 0xff, "%u\n", opts.fgColor);
1886 if (! fPipeServer.writeMessage(tmpBuf))
1887 return;
1889 std::snprintf(tmpBuf, 0xff, "%.12g\n", static_cast<double>(opts.uiScale));
1890 if (! fPipeServer.writeMessage(tmpBuf))
1891 return;
1893 std::snprintf(tmpBuf, 0xff, "%s\n", bool2str(true)); // useTheme
1894 if (! fPipeServer.writeMessage(tmpBuf))
1895 return;
1897 std::snprintf(tmpBuf, 0xff, "%s\n", bool2str(true)); // useThemeColors
1898 if (! fPipeServer.writeMessage(tmpBuf))
1899 return;
1901 if (! fPipeServer.writeAndFixMessage(fLv2Options.windowTitle != nullptr
1902 ? fLv2Options.windowTitle
1903 : ""))
1904 return;
1906 std::snprintf(tmpBuf, 0xff, P_INTPTR "\n", frontendWinId);
1907 if (! fPipeServer.writeMessage(tmpBuf))
1908 return;
1910 // write parameter values
1911 for (uint32_t i=0; i < pData->param.count; ++i)
1913 ParameterData& pdata(pData->param.data[i]);
1915 if (pdata.hints & PARAMETER_IS_NOT_SAVED)
1917 int32_t rindex = pdata.rindex;
1918 CARLA_SAFE_ASSERT_CONTINUE(rindex - static_cast<int32_t>(fRdfDescriptor->PortCount) >= 0);
1920 rindex -= static_cast<int32_t>(fRdfDescriptor->PortCount);
1921 CARLA_SAFE_ASSERT_CONTINUE(rindex < static_cast<int32_t>(fRdfDescriptor->ParameterCount));
1923 if (! fPipeServer.writeLv2ParameterMessage(fRdfDescriptor->Parameters[rindex].URI,
1924 getParameterValue(i), false))
1925 return;
1927 else
1929 if (! fPipeServer.writeControlMessage(static_cast<uint32_t>(pData->param.data[i].rindex),
1930 getParameterValue(i), false))
1931 return;
1935 // ready to show
1936 if (! fPipeServer.writeMessage("show\n", 5))
1937 return;
1939 fPipeServer.syncMessages();
1942 #ifndef BUILD_BRIDGE
1943 if (fUI.rdfDescriptor->Type == LV2_UI_MOD)
1944 pData->tryTransient();
1945 #endif
1947 else
1949 fPipeServer.stopPipeServer(pData->engine->getOptions().uiBridgesTimeout);
1951 return;
1953 #endif
1955 // take some precautions
1956 CARLA_SAFE_ASSERT_RETURN(fUI.descriptor != nullptr,);
1957 CARLA_SAFE_ASSERT_RETURN(fUI.rdfDescriptor != nullptr,);
1959 if (yesNo)
1961 CARLA_SAFE_ASSERT_RETURN(fUI.descriptor->instantiate != nullptr,);
1962 CARLA_SAFE_ASSERT_RETURN(fUI.descriptor->cleanup != nullptr,);
1964 else
1966 if (fUI.handle == nullptr)
1967 return;
1970 if (yesNo)
1972 if (fUI.handle == nullptr)
1974 #ifndef LV2_UIS_ONLY_BRIDGES
1975 if (fUI.type == UI::TYPE_EMBED && fUI.rdfDescriptor->Type != LV2_UI_NONE && fUI.window == nullptr)
1977 const char* msg = nullptr;
1978 const bool isStandalone = pData->engine->getOptions().pluginsAreStandalone;
1980 switch (fUI.rdfDescriptor->Type)
1982 case LV2_UI_GTK2:
1983 case LV2_UI_GTK3:
1984 case LV2_UI_QT4:
1985 case LV2_UI_QT5:
1986 case LV2_UI_EXTERNAL:
1987 case LV2_UI_OLD_EXTERNAL:
1988 msg = "Invalid UI type";
1989 break;
1991 case LV2_UI_COCOA:
1992 # ifdef CARLA_OS_MAC
1993 fUI.window = CarlaPluginUI::newCocoa(this, frontendWinId, isStandalone, isUiResizable());
1994 # else
1995 msg = "UI is for MacOS only";
1996 # endif
1997 break;
1999 case LV2_UI_WINDOWS:
2000 # ifdef CARLA_OS_WIN
2001 fUI.window = CarlaPluginUI::newWindows(this, frontendWinId, isStandalone, isUiResizable());
2002 # else
2003 msg = "UI is for Windows only";
2004 # endif
2005 break;
2007 case LV2_UI_X11:
2008 # ifdef HAVE_X11
2009 fUI.window = CarlaPluginUI::newX11(this, frontendWinId, isStandalone, isUiResizable(), true);
2010 # else
2011 msg = "UI is only for systems with X11";
2012 # endif
2013 break;
2015 default:
2016 msg = "Unknown UI type";
2017 break;
2020 if (fUI.window == nullptr && fExt.uishow == nullptr)
2021 return pData->engine->callback(true, true,
2022 ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, -1, 0, 0, 0.0f, msg);
2024 if (fUI.window != nullptr)
2025 fFeatures[kFeatureIdUiParent]->data = fUI.window->getPtr();
2027 #endif
2028 fUI.widget = nullptr;
2029 fUI.handle = fUI.descriptor->instantiate(fUI.descriptor, fRdfDescriptor->URI, fUI.rdfDescriptor->Bundle,
2030 carla_lv2_ui_write_function, this, &fUI.widget, fFeatures);
2032 if (fUI.window != nullptr)
2034 if (fUI.widget != nullptr)
2035 fUI.window->setChildWindow(fUI.widget);
2036 fUI.window->setTitle(fLv2Options.windowTitle);
2040 CARLA_SAFE_ASSERT(fUI.handle != nullptr);
2041 CARLA_SAFE_ASSERT(fUI.type != UI::TYPE_EXTERNAL || fUI.widget != nullptr);
2043 if (fUI.handle == nullptr || (fUI.type == UI::TYPE_EXTERNAL && fUI.widget == nullptr))
2045 fUI.widget = nullptr;
2047 if (fUI.handle != nullptr)
2049 fUI.descriptor->cleanup(fUI.handle);
2050 fUI.handle = nullptr;
2053 return pData->engine->callback(true, true,
2054 ENGINE_CALLBACK_UI_STATE_CHANGED,
2055 pData->id,
2057 0, 0, 0.0f,
2058 "Plugin refused to open its own UI");
2061 updateUi();
2063 #ifndef LV2_UIS_ONLY_BRIDGES
2064 if (fUI.type == UI::TYPE_EMBED)
2066 if (fUI.window != nullptr)
2068 fUI.window->show();
2070 else if (fExt.uishow != nullptr)
2072 fExt.uishow->show(fUI.handle);
2073 # ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
2074 pData->tryTransient();
2075 # endif
2078 else
2079 #endif
2081 LV2_EXTERNAL_UI_SHOW((LV2_External_UI_Widget*)fUI.widget);
2082 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
2083 pData->tryTransient();
2084 #endif
2087 else
2089 #ifndef LV2_UIS_ONLY_BRIDGES
2090 if (fUI.type == UI::TYPE_EMBED)
2092 if (fUI.window != nullptr)
2093 fUI.window->hide();
2094 else if (fExt.uishow != nullptr)
2095 fExt.uishow->hide(fUI.handle);
2097 else
2098 #endif
2100 CARLA_SAFE_ASSERT(fUI.widget != nullptr);
2102 if (fUI.widget != nullptr)
2103 LV2_EXTERNAL_UI_HIDE((LV2_External_UI_Widget*)fUI.widget);
2106 fUI.descriptor->cleanup(fUI.handle);
2107 fUI.handle = nullptr;
2108 fUI.widget = nullptr;
2110 if (fUI.type == UI::TYPE_EMBED && fUI.window != nullptr)
2112 delete fUI.window;
2113 fUI.window = nullptr;
2118 #ifndef LV2_UIS_ONLY_BRIDGES
2119 void* embedCustomUI(void* const ptr) override
2121 CARLA_SAFE_ASSERT_RETURN(fUI.type == UI::TYPE_EMBED, nullptr);
2122 CARLA_SAFE_ASSERT_RETURN(fUI.descriptor != nullptr, nullptr);
2123 CARLA_SAFE_ASSERT_RETURN(fUI.descriptor->instantiate != nullptr, nullptr);
2124 CARLA_SAFE_ASSERT_RETURN(fUI.descriptor->cleanup != nullptr, nullptr);
2125 CARLA_SAFE_ASSERT_RETURN(fUI.rdfDescriptor->Type != LV2_UI_NONE, nullptr);
2126 CARLA_SAFE_ASSERT_RETURN(fUI.window == nullptr, nullptr);
2128 fFeatures[kFeatureIdUiParent]->data = ptr;
2130 fUI.embedded = true;
2131 fUI.widget = nullptr;
2132 fUI.handle = fUI.descriptor->instantiate(fUI.descriptor, fRdfDescriptor->URI, fUI.rdfDescriptor->Bundle,
2133 carla_lv2_ui_write_function, this, &fUI.widget, fFeatures);
2135 updateUi();
2137 return fUI.widget;
2139 #endif
2141 void idle() override
2143 if (fAtomBufferWorkerIn.isDataAvailableForReading())
2145 Lv2AtomRingBuffer tmpRingBuffer(fAtomBufferWorkerIn, fAtomBufferWorkerInTmpData);
2146 CARLA_SAFE_ASSERT_RETURN(tmpRingBuffer.isDataAvailableForReading(),);
2147 CARLA_SAFE_ASSERT_RETURN(fExt.worker != nullptr && fExt.worker->work != nullptr,);
2149 const size_t localSize = fAtomBufferWorkerIn.getSize();
2150 uint8_t* const localData = new uint8_t[localSize];
2151 LV2_Atom* const localAtom = static_cast<LV2_Atom*>(static_cast<void*>(localData));
2152 localAtom->size = localSize;
2153 uint32_t portIndex;
2155 for (; tmpRingBuffer.get(portIndex, localAtom); localAtom->size = localSize)
2157 CARLA_SAFE_ASSERT_CONTINUE(localAtom->type == kUridCarlaAtomWorkerIn);
2158 fExt.worker->work(fHandle, carla_lv2_worker_respond, this, localAtom->size, LV2_ATOM_BODY_CONST(localAtom));
2161 delete[] localData;
2164 if (fInlineDisplayNeedsRedraw)
2166 // TESTING
2167 CARLA_SAFE_ASSERT(pData->enabled)
2168 CARLA_SAFE_ASSERT(!pData->engine->isAboutToClose());
2169 CARLA_SAFE_ASSERT(pData->client->isActive());
2171 if (pData->enabled && !pData->engine->isAboutToClose() && pData->client->isActive())
2173 const int64_t timeNow = water::Time::currentTimeMillis();
2175 if (timeNow - fInlineDisplayLastRedrawTime > (1000 / 30))
2177 fInlineDisplayNeedsRedraw = false;
2178 fInlineDisplayLastRedrawTime = timeNow;
2179 pData->engine->callback(true, true,
2180 ENGINE_CALLBACK_INLINE_DISPLAY_REDRAW,
2181 pData->id,
2182 0, 0, 0, 0.0f, nullptr);
2185 else
2187 fInlineDisplayNeedsRedraw = false;
2191 CarlaPlugin::idle();
2194 void uiIdle() override
2196 if (const char* const fileNeededForURI = fUI.fileNeededForURI)
2198 fUI.fileBrowserOpen = true;
2199 fUI.fileNeededForURI = nullptr;
2201 const char* const path = pData->engine->runFileCallback(FILE_CALLBACK_OPEN,
2202 /* isDir */ false,
2203 /* title */ "File open",
2204 /* filters */ "");
2206 fUI.fileBrowserOpen = false;
2208 if (path != nullptr)
2210 carla_stdout("LV2 requested path to send: '%s'", path);
2211 writeAtomPath(path, getCustomURID(fileNeededForURI));
2214 // this function will be called recursively, stop here
2215 return;
2218 if (fAtomBufferUiOut.isDataAvailableForReading())
2220 Lv2AtomRingBuffer tmpRingBuffer(fAtomBufferUiOut, fAtomBufferUiOutTmpData);
2221 CARLA_SAFE_ASSERT(tmpRingBuffer.isDataAvailableForReading());
2223 const size_t localSize = fAtomBufferUiOut.getSize();
2224 uint8_t* const localData = new uint8_t[localSize];
2225 LV2_Atom* const localAtom = static_cast<LV2_Atom*>(static_cast<void*>(localData));
2226 localAtom->size = localSize;
2228 uint32_t portIndex;
2229 const bool hasPortEvent(fUI.handle != nullptr &&
2230 fUI.descriptor != nullptr &&
2231 fUI.descriptor->port_event != nullptr);
2233 for (; tmpRingBuffer.get(portIndex, localAtom); localAtom->size = localSize)
2235 #ifndef LV2_UIS_ONLY_INPROCESS
2236 if (fUI.type == UI::TYPE_BRIDGE)
2238 if (fPipeServer.isPipeRunning())
2239 fPipeServer.writeLv2AtomMessage(portIndex, localAtom);
2241 else
2242 #endif
2244 if (hasPortEvent && ! fNeedsUiClose)
2245 fUI.descriptor->port_event(fUI.handle, portIndex, lv2_atom_total_size(localAtom), kUridAtomTransferEvent, localAtom);
2248 inspectAtomForParameterChange(localAtom);
2251 delete[] localData;
2254 #ifndef LV2_UIS_ONLY_INPROCESS
2255 if (fPipeServer.isPipeRunning())
2257 fPipeServer.idlePipe();
2259 switch (fPipeServer.getAndResetUiState())
2261 case CarlaPipeServerLV2::UiNone:
2262 case CarlaPipeServerLV2::UiShow:
2263 break;
2264 case CarlaPipeServerLV2::UiHide:
2265 fPipeServer.stopPipeServer(2000);
2266 // fall through
2267 case CarlaPipeServerLV2::UiCrashed:
2268 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
2269 pData->transientTryCounter = 0;
2270 #endif
2271 pData->engine->callback(true, true,
2272 ENGINE_CALLBACK_UI_STATE_CHANGED,
2273 pData->id,
2275 0, 0, 0.0f, nullptr);
2276 break;
2279 else
2281 // TODO - detect if ui-bridge crashed
2283 #endif
2285 if (fNeedsUiClose)
2287 fNeedsUiClose = false;
2288 showCustomUI(false);
2289 pData->engine->callback(true, true,
2290 ENGINE_CALLBACK_UI_STATE_CHANGED,
2291 pData->id,
2293 0, 0, 0.0f, nullptr);
2295 else if (fUI.handle != nullptr && fUI.descriptor != nullptr)
2297 if (fUI.type == UI::TYPE_EXTERNAL && fUI.widget != nullptr)
2298 LV2_EXTERNAL_UI_RUN((LV2_External_UI_Widget*)fUI.widget);
2299 #ifndef LV2_UIS_ONLY_BRIDGES
2300 else if (fUI.type == UI::TYPE_EMBED && fUI.window != nullptr)
2301 fUI.window->idle();
2303 // note: UI might have been closed by window idle
2304 if (fNeedsUiClose)
2306 pass();
2308 else if (fUI.handle != nullptr && fExt.uiidle != nullptr && fExt.uiidle->idle(fUI.handle) != 0)
2310 showCustomUI(false);
2311 pData->engine->callback(true, true,
2312 ENGINE_CALLBACK_UI_STATE_CHANGED,
2313 pData->id,
2315 0, 0, 0.0f, nullptr);
2316 CARLA_SAFE_ASSERT(fUI.handle == nullptr);
2318 #endif
2321 CarlaPlugin::uiIdle();
2324 // -------------------------------------------------------------------
2325 // Plugin state
2327 void reload() override
2329 CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,);
2330 CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
2331 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
2332 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr,);
2333 carla_debug("CarlaPluginLV2::reload() - start");
2335 const EngineProcessMode processMode(pData->engine->getProccessMode());
2337 // Safely disable plugin for reload
2338 const ScopedDisabler sd(this);
2340 if (pData->active)
2341 deactivate();
2343 clearBuffers();
2345 const float sampleRate(static_cast<float>(pData->engine->getSampleRate()));
2346 const uint32_t portCount(fRdfDescriptor->PortCount);
2348 uint32_t aIns, aOuts, cvIns, cvOuts, params;
2349 aIns = aOuts = cvIns = cvOuts = params = 0;
2350 LinkedList<uint> evIns, evOuts;
2352 const uint32_t eventBufferSize = static_cast<uint32_t>(fLv2Options.sequenceSize) + 0xff;
2354 bool forcedStereoIn, forcedStereoOut;
2355 forcedStereoIn = forcedStereoOut = false;
2357 bool needsCtrlIn, needsCtrlOut, hasPatchParameterOutputs;
2358 needsCtrlIn = needsCtrlOut = hasPatchParameterOutputs = false;
2360 for (uint32_t i=0; i < portCount; ++i)
2362 const LV2_Property portTypes = fRdfDescriptor->Ports[i].Types;
2364 if (LV2_IS_PORT_AUDIO(portTypes))
2366 if (LV2_IS_PORT_INPUT(portTypes))
2367 aIns += 1;
2368 else if (LV2_IS_PORT_OUTPUT(portTypes))
2369 aOuts += 1;
2371 else if (LV2_IS_PORT_CV(portTypes))
2373 if (LV2_IS_PORT_INPUT(portTypes))
2374 cvIns += 1;
2375 else if (LV2_IS_PORT_OUTPUT(portTypes))
2376 cvOuts += 1;
2378 else if (LV2_IS_PORT_ATOM_SEQUENCE(portTypes))
2380 if (LV2_IS_PORT_INPUT(portTypes))
2381 evIns.append(CARLA_EVENT_DATA_ATOM);
2382 else if (LV2_IS_PORT_OUTPUT(portTypes))
2383 evOuts.append(CARLA_EVENT_DATA_ATOM);
2385 else if (LV2_IS_PORT_EVENT(portTypes))
2387 if (LV2_IS_PORT_INPUT(portTypes))
2388 evIns.append(CARLA_EVENT_DATA_EVENT);
2389 else if (LV2_IS_PORT_OUTPUT(portTypes))
2390 evOuts.append(CARLA_EVENT_DATA_EVENT);
2392 else if (LV2_IS_PORT_MIDI_LL(portTypes))
2394 if (LV2_IS_PORT_INPUT(portTypes))
2395 evIns.append(CARLA_EVENT_DATA_MIDI_LL);
2396 else if (LV2_IS_PORT_OUTPUT(portTypes))
2397 evOuts.append(CARLA_EVENT_DATA_MIDI_LL);
2399 else if (LV2_IS_PORT_CONTROL(portTypes))
2400 params += 1;
2403 for (uint32_t i=0; i < fRdfDescriptor->ParameterCount; ++i)
2405 switch (fRdfDescriptor->Parameters[i].Type)
2407 case LV2_PARAMETER_TYPE_BOOL:
2408 case LV2_PARAMETER_TYPE_INT:
2409 // case LV2_PARAMETER_TYPE_LONG:
2410 case LV2_PARAMETER_TYPE_FLOAT:
2411 case LV2_PARAMETER_TYPE_DOUBLE:
2412 params += 1;
2413 break;
2414 case LV2_PARAMETER_TYPE_PATH:
2415 if (fFilePathURI.isEmpty())
2416 fFilePathURI = fRdfDescriptor->Parameters[i].URI;
2417 break;
2421 if ((pData->options & PLUGIN_OPTION_FORCE_STEREO) != 0 && aIns <= 1 && aOuts <= 1 && evOuts.count() == 0 && fExt.state == nullptr && fExt.worker == nullptr)
2423 if (fHandle2 == nullptr)
2425 try {
2426 fHandle2 = fDescriptor->instantiate(fDescriptor, sampleRate, fRdfDescriptor->Bundle, fFeatures);
2427 } catch(...) {}
2430 if (fHandle2 != nullptr)
2432 if (aIns == 1)
2434 aIns = 2;
2435 forcedStereoIn = true;
2438 if (aOuts == 1)
2440 aOuts = 2;
2441 forcedStereoOut = true;
2446 if (aIns > 0)
2448 pData->audioIn.createNew(aIns);
2449 fAudioInBuffers = new float*[aIns];
2451 for (uint32_t i=0; i < aIns; ++i)
2452 fAudioInBuffers[i] = nullptr;
2455 if (aOuts > 0)
2457 pData->audioOut.createNew(aOuts);
2458 fAudioOutBuffers = new float*[aOuts];
2459 needsCtrlIn = true;
2461 for (uint32_t i=0; i < aOuts; ++i)
2462 fAudioOutBuffers[i] = nullptr;
2465 if (cvIns > 0)
2467 pData->cvIn.createNew(cvIns);
2468 fCvInBuffers = new float*[cvIns];
2470 for (uint32_t i=0; i < cvIns; ++i)
2471 fCvInBuffers[i] = nullptr;
2474 if (cvOuts > 0)
2476 pData->cvOut.createNew(cvOuts);
2477 fCvOutBuffers = new float*[cvOuts];
2479 for (uint32_t i=0; i < cvOuts; ++i)
2480 fCvOutBuffers[i] = nullptr;
2483 if (params > 0)
2485 pData->param.createNew(params, true);
2486 fParamBuffers = new float[params];
2487 carla_zeroFloats(fParamBuffers, params);
2490 if (const uint32_t count = static_cast<uint32_t>(evIns.count()))
2492 fEventsIn.createNew(count);
2494 for (uint32_t i=0; i < count; ++i)
2496 const uint32_t type = evIns.getAt(i, 0x0);
2498 if (type == CARLA_EVENT_DATA_ATOM)
2500 fEventsIn.data[i].type = CARLA_EVENT_DATA_ATOM;
2501 fEventsIn.data[i].atom = lv2_atom_buffer_new(eventBufferSize, kUridNull, kUridAtomSequence, true);
2503 else if (type == CARLA_EVENT_DATA_EVENT)
2505 fEventsIn.data[i].type = CARLA_EVENT_DATA_EVENT;
2506 fEventsIn.data[i].event = lv2_event_buffer_new(eventBufferSize, LV2_EVENT_AUDIO_STAMP);
2508 else if (type == CARLA_EVENT_DATA_MIDI_LL)
2510 fEventsIn.data[i].type = CARLA_EVENT_DATA_MIDI_LL;
2511 fEventsIn.data[i].midi.capacity = eventBufferSize;
2512 fEventsIn.data[i].midi.data = new uchar[eventBufferSize];
2516 else
2518 fEventsIn.createNew(1);
2519 fEventsIn.ctrl = &fEventsIn.data[0];
2522 if (const uint32_t count = static_cast<uint32_t>(evOuts.count()))
2524 fEventsOut.createNew(count);
2526 for (uint32_t i=0; i < count; ++i)
2528 const uint32_t type = evOuts.getAt(i, 0x0);
2530 if (type == CARLA_EVENT_DATA_ATOM)
2532 fEventsOut.data[i].type = CARLA_EVENT_DATA_ATOM;
2533 fEventsOut.data[i].atom = lv2_atom_buffer_new(eventBufferSize, kUridNull, kUridAtomSequence, false);
2535 else if (type == CARLA_EVENT_DATA_EVENT)
2537 fEventsOut.data[i].type = CARLA_EVENT_DATA_EVENT;
2538 fEventsOut.data[i].event = lv2_event_buffer_new(eventBufferSize, LV2_EVENT_AUDIO_STAMP);
2540 else if (type == CARLA_EVENT_DATA_MIDI_LL)
2542 fEventsOut.data[i].type = CARLA_EVENT_DATA_MIDI_LL;
2543 fEventsOut.data[i].midi.capacity = eventBufferSize;
2544 fEventsOut.data[i].midi.data = new uchar[eventBufferSize];
2549 const uint portNameSize(pData->engine->getMaxPortNameSize());
2550 CarlaString portName;
2551 uint32_t iCtrl = 0;
2553 for (uint32_t i=0, iAudioIn=0, iAudioOut=0, iCvIn=0, iCvOut=0, iEvIn=0, iEvOut=0; i < portCount; ++i)
2555 const LV2_Property portTypes(fRdfDescriptor->Ports[i].Types);
2557 portName.clear();
2559 if (LV2_IS_PORT_AUDIO(portTypes) || LV2_IS_PORT_CV(portTypes) || LV2_IS_PORT_ATOM_SEQUENCE(portTypes) || LV2_IS_PORT_EVENT(portTypes) || LV2_IS_PORT_MIDI_LL(portTypes))
2561 if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
2563 portName = pData->name;
2564 portName += ":";
2567 portName += fRdfDescriptor->Ports[i].Name;
2568 portName.truncate(portNameSize);
2571 if (LV2_IS_PORT_AUDIO(portTypes))
2573 if (LV2_IS_PORT_INPUT(portTypes))
2575 const uint32_t j = iAudioIn++;
2576 pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, j);
2577 pData->audioIn.ports[j].rindex = i;
2579 if (forcedStereoIn)
2581 portName += "_2";
2582 pData->audioIn.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, 1);
2583 pData->audioIn.ports[1].rindex = i;
2586 else if (LV2_IS_PORT_OUTPUT(portTypes))
2588 const uint32_t j = iAudioOut++;
2589 pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, j);
2590 pData->audioOut.ports[j].rindex = i;
2592 if (forcedStereoOut)
2594 portName += "_2";
2595 pData->audioOut.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, 1);
2596 pData->audioOut.ports[1].rindex = i;
2599 else
2600 carla_stderr2("WARNING - Got a broken Port (Audio, but not input or output)");
2602 else if (LV2_IS_PORT_CV(portTypes))
2604 const LV2_RDF_PortPoints portPoints(fRdfDescriptor->Ports[i].Points);
2605 float min, max;
2607 // min value
2608 if (LV2_HAVE_MINIMUM_PORT_POINT(portPoints.Hints))
2609 min = portPoints.Minimum;
2610 else
2611 min = -1.0f;
2613 // max value
2614 if (LV2_HAVE_MAXIMUM_PORT_POINT(portPoints.Hints))
2615 max = portPoints.Maximum;
2616 else
2617 max = 1.0f;
2619 if (LV2_IS_PORT_INPUT(portTypes))
2621 const uint32_t j = iCvIn++;
2622 pData->cvIn.ports[j].port = (CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV, portName, true, j);
2623 pData->cvIn.ports[j].rindex = i;
2624 pData->cvIn.ports[j].port->setRange(min, max);
2626 else if (LV2_IS_PORT_OUTPUT(portTypes))
2628 const uint32_t j = iCvOut++;
2629 pData->cvOut.ports[j].port = (CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV, portName, false, j);
2630 pData->cvOut.ports[j].rindex = i;
2631 pData->cvOut.ports[j].port->setRange(min, max);
2633 else
2634 carla_stderr("WARNING - Got a broken Port (CV, but not input or output)");
2636 else if (LV2_IS_PORT_ATOM_SEQUENCE(portTypes))
2638 if (LV2_IS_PORT_INPUT(portTypes))
2640 const uint32_t j = iEvIn++;
2642 fDescriptor->connect_port(fHandle, i, &fEventsIn.data[j].atom->atoms);
2644 if (fHandle2 != nullptr)
2645 fDescriptor->connect_port(fHandle2, i, &fEventsIn.data[j].atom->atoms);
2647 fEventsIn.data[j].rindex = i;
2649 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2650 fEventsIn.data[j].type |= CARLA_EVENT_TYPE_MIDI;
2651 if (portTypes & LV2_PORT_DATA_PATCH_MESSAGE)
2652 fEventsIn.data[j].type |= CARLA_EVENT_TYPE_MESSAGE;
2653 if (portTypes & LV2_PORT_DATA_TIME_POSITION)
2654 fEventsIn.data[j].type |= CARLA_EVENT_TYPE_TIME;
2656 if (evIns.count() == 1)
2658 fEventsIn.ctrl = &fEventsIn.data[j];
2659 fEventsIn.ctrlIndex = j;
2661 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2662 needsCtrlIn = true;
2664 else
2666 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2667 fEventsIn.data[j].port = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, j);
2669 if (LV2_IS_PORT_DESIGNATION_CONTROL(fRdfDescriptor->Ports[i].Designation))
2671 fEventsIn.ctrl = &fEventsIn.data[j];
2672 fEventsIn.ctrlIndex = j;
2676 else if (LV2_IS_PORT_OUTPUT(portTypes))
2678 const uint32_t j = iEvOut++;
2680 fDescriptor->connect_port(fHandle, i, &fEventsOut.data[j].atom->atoms);
2682 if (fHandle2 != nullptr)
2683 fDescriptor->connect_port(fHandle2, i, &fEventsOut.data[j].atom->atoms);
2685 fEventsOut.data[j].rindex = i;
2687 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2688 fEventsOut.data[j].type |= CARLA_EVENT_TYPE_MIDI;
2689 if (portTypes & LV2_PORT_DATA_PATCH_MESSAGE)
2690 fEventsOut.data[j].type |= CARLA_EVENT_TYPE_MESSAGE;
2691 if (portTypes & LV2_PORT_DATA_TIME_POSITION)
2692 fEventsOut.data[j].type |= CARLA_EVENT_TYPE_TIME;
2694 if (evOuts.count() == 1)
2696 fEventsOut.ctrl = &fEventsOut.data[j];
2697 fEventsOut.ctrlIndex = j;
2699 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2700 needsCtrlOut = true;
2702 else
2704 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2705 fEventsOut.data[j].port = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, j);
2707 if (LV2_IS_PORT_DESIGNATION_CONTROL(fRdfDescriptor->Ports[i].Designation))
2709 fEventsOut.ctrl = &fEventsOut.data[j];
2710 fEventsOut.ctrlIndex = j;
2714 else
2715 carla_stderr2("WARNING - Got a broken Port (Atom-Sequence, but not input or output)");
2717 else if (LV2_IS_PORT_EVENT(portTypes))
2719 if (LV2_IS_PORT_INPUT(portTypes))
2721 const uint32_t j = iEvIn++;
2723 fDescriptor->connect_port(fHandle, i, fEventsIn.data[j].event);
2725 if (fHandle2 != nullptr)
2726 fDescriptor->connect_port(fHandle2, i, fEventsIn.data[j].event);
2728 fEventsIn.data[j].rindex = i;
2730 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2731 fEventsIn.data[j].type |= CARLA_EVENT_TYPE_MIDI;
2732 if (portTypes & LV2_PORT_DATA_PATCH_MESSAGE)
2733 fEventsIn.data[j].type |= CARLA_EVENT_TYPE_MESSAGE;
2734 if (portTypes & LV2_PORT_DATA_TIME_POSITION)
2735 fEventsIn.data[j].type |= CARLA_EVENT_TYPE_TIME;
2737 if (evIns.count() == 1)
2739 fEventsIn.ctrl = &fEventsIn.data[j];
2740 fEventsIn.ctrlIndex = j;
2742 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2743 needsCtrlIn = true;
2745 else
2747 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2748 fEventsIn.data[j].port = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, j);
2750 if (LV2_IS_PORT_DESIGNATION_CONTROL(fRdfDescriptor->Ports[i].Designation))
2752 fEventsIn.ctrl = &fEventsIn.data[j];
2753 fEventsIn.ctrlIndex = j;
2757 else if (LV2_IS_PORT_OUTPUT(portTypes))
2759 const uint32_t j = iEvOut++;
2761 fDescriptor->connect_port(fHandle, i, fEventsOut.data[j].event);
2763 if (fHandle2 != nullptr)
2764 fDescriptor->connect_port(fHandle2, i, fEventsOut.data[j].event);
2766 fEventsOut.data[j].rindex = i;
2768 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2769 fEventsOut.data[j].type |= CARLA_EVENT_TYPE_MIDI;
2770 if (portTypes & LV2_PORT_DATA_PATCH_MESSAGE)
2771 fEventsOut.data[j].type |= CARLA_EVENT_TYPE_MESSAGE;
2772 if (portTypes & LV2_PORT_DATA_TIME_POSITION)
2773 fEventsOut.data[j].type |= CARLA_EVENT_TYPE_TIME;
2775 if (evOuts.count() == 1)
2777 fEventsOut.ctrl = &fEventsOut.data[j];
2778 fEventsOut.ctrlIndex = j;
2780 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2781 needsCtrlOut = true;
2783 else
2785 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2786 fEventsOut.data[j].port = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, j);
2788 if (LV2_IS_PORT_DESIGNATION_CONTROL(fRdfDescriptor->Ports[i].Designation))
2790 fEventsOut.ctrl = &fEventsOut.data[j];
2791 fEventsOut.ctrlIndex = j;
2795 else
2796 carla_stderr2("WARNING - Got a broken Port (Event, but not input or output)");
2798 else if (LV2_IS_PORT_MIDI_LL(portTypes))
2800 if (LV2_IS_PORT_INPUT(portTypes))
2802 const uint32_t j = iEvIn++;
2804 fDescriptor->connect_port(fHandle, i, &fEventsIn.data[j].midi);
2806 if (fHandle2 != nullptr)
2807 fDescriptor->connect_port(fHandle2, i, &fEventsIn.data[j].midi);
2809 fEventsIn.data[j].type |= CARLA_EVENT_TYPE_MIDI;
2810 fEventsIn.data[j].rindex = i;
2812 if (evIns.count() == 1)
2814 needsCtrlIn = true;
2815 fEventsIn.ctrl = &fEventsIn.data[j];
2816 fEventsIn.ctrlIndex = j;
2818 else
2820 fEventsIn.data[j].port = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, j);
2822 if (LV2_IS_PORT_DESIGNATION_CONTROL(fRdfDescriptor->Ports[i].Designation))
2824 fEventsIn.ctrl = &fEventsIn.data[j];
2825 fEventsIn.ctrlIndex = j;
2829 else if (LV2_IS_PORT_OUTPUT(portTypes))
2831 const uint32_t j = iEvOut++;
2833 fDescriptor->connect_port(fHandle, i, &fEventsOut.data[j].midi);
2835 if (fHandle2 != nullptr)
2836 fDescriptor->connect_port(fHandle2, i, &fEventsOut.data[j].midi);
2838 fEventsOut.data[j].type |= CARLA_EVENT_TYPE_MIDI;
2839 fEventsOut.data[j].rindex = i;
2841 if (evOuts.count() == 1)
2843 needsCtrlOut = true;
2844 fEventsOut.ctrl = &fEventsOut.data[j];
2845 fEventsOut.ctrlIndex = j;
2847 else
2849 fEventsOut.data[j].port = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, j);
2851 if (LV2_IS_PORT_DESIGNATION_CONTROL(fRdfDescriptor->Ports[i].Designation))
2853 fEventsOut.ctrl = &fEventsOut.data[j];
2854 fEventsOut.ctrlIndex = j;
2858 else
2859 carla_stderr2("WARNING - Got a broken Port (MIDI, but not input or output)");
2861 else if (LV2_IS_PORT_CONTROL(portTypes))
2863 const LV2_Property portProps(fRdfDescriptor->Ports[i].Properties);
2864 const LV2_Property portDesignation(fRdfDescriptor->Ports[i].Designation);
2865 const LV2_RDF_PortPoints portPoints(fRdfDescriptor->Ports[i].Points);
2867 const uint32_t j = iCtrl++;
2868 pData->param.data[j].index = static_cast<int32_t>(j);
2869 pData->param.data[j].rindex = static_cast<int32_t>(i);
2871 float min, max, def, step, stepSmall, stepLarge;
2873 // min value
2874 if (LV2_HAVE_MINIMUM_PORT_POINT(portPoints.Hints))
2875 min = portPoints.Minimum;
2876 else
2877 min = 0.0f;
2879 // max value
2880 if (LV2_HAVE_MAXIMUM_PORT_POINT(portPoints.Hints))
2881 max = portPoints.Maximum;
2882 else
2883 max = 1.0f;
2885 if (LV2_IS_PORT_SAMPLE_RATE(portProps))
2887 min *= sampleRate;
2888 max *= sampleRate;
2889 pData->param.data[j].hints |= PARAMETER_USES_SAMPLERATE;
2892 // stupid hack for ir.lv2 (broken plugin)
2893 if (std::strcmp(fRdfDescriptor->URI, "http://factorial.hu/plugins/lv2/ir") == 0 && std::strncmp(fRdfDescriptor->Ports[i].Name, "FileHash", 8) == 0)
2895 min = 0.0f;
2896 max = (float)0xffffff;
2899 if (min >= max)
2901 carla_stderr2("WARNING - Broken plugin parameter '%s': min >= max", fRdfDescriptor->Ports[i].Name);
2902 max = min + 0.1f;
2905 // default value
2906 if (LV2_HAVE_DEFAULT_PORT_POINT(portPoints.Hints))
2908 def = portPoints.Default;
2910 else
2912 // no default value
2913 if (min < 0.0f && max > 0.0f)
2914 def = 0.0f;
2915 else
2916 def = min;
2919 if (def < min)
2920 def = min;
2921 else if (def > max)
2922 def = max;
2924 if (LV2_IS_PORT_TOGGLED(portProps))
2926 step = max - min;
2927 stepSmall = step;
2928 stepLarge = step;
2929 pData->param.data[j].hints |= PARAMETER_IS_BOOLEAN;
2931 else if (LV2_IS_PORT_INTEGER(portProps))
2933 step = 1.0f;
2934 stepSmall = 1.0f;
2935 stepLarge = 10.0f;
2936 pData->param.data[j].hints |= PARAMETER_IS_INTEGER;
2938 else
2940 float range = max - min;
2941 step = range/100.0f;
2942 stepSmall = range/1000.0f;
2943 stepLarge = range/10.0f;
2946 if (LV2_IS_PORT_INPUT(portTypes))
2948 pData->param.data[j].type = PARAMETER_INPUT;
2950 if (LV2_IS_PORT_DESIGNATION_LATENCY(portDesignation))
2952 carla_stderr("Plugin has latency input port, this should not happen!");
2954 else if (LV2_IS_PORT_DESIGNATION_SAMPLE_RATE(portDesignation))
2956 def = sampleRate;
2957 step = 1.0f;
2958 stepSmall = 1.0f;
2959 stepLarge = 1.0f;
2960 pData->param.special[j] = PARAMETER_SPECIAL_SAMPLE_RATE;
2962 else if (LV2_IS_PORT_DESIGNATION_FREEWHEELING(portDesignation))
2964 pData->param.special[j] = PARAMETER_SPECIAL_FREEWHEEL;
2966 else if (LV2_IS_PORT_DESIGNATION_TIME(portDesignation))
2968 pData->param.special[j] = PARAMETER_SPECIAL_TIME;
2970 else
2972 pData->param.data[j].hints |= PARAMETER_IS_ENABLED;
2973 pData->param.data[j].hints |= PARAMETER_IS_AUTOMATABLE;
2974 needsCtrlIn = true;
2976 if (! LV2_IS_PORT_CAUSES_ARTIFACTS(portProps) &&
2977 ! LV2_IS_PORT_ENUMERATION(portProps) &&
2978 ! LV2_IS_PORT_EXPENSIVE(portProps) &&
2979 ! LV2_IS_PORT_NOT_AUTOMATIC(portProps) &&
2980 ! LV2_IS_PORT_NOT_ON_GUI(portProps) &&
2981 ! LV2_IS_PORT_TRIGGER(portProps))
2983 pData->param.data[j].hints |= PARAMETER_CAN_BE_CV_CONTROLLED;
2987 // MIDI CC value
2988 const LV2_RDF_PortMidiMap& portMidiMap(fRdfDescriptor->Ports[i].MidiMap);
2990 if (LV2_IS_PORT_MIDI_MAP_CC(portMidiMap.Type))
2992 if (portMidiMap.Number < MAX_MIDI_CONTROL && ! MIDI_IS_CONTROL_BANK_SELECT(portMidiMap.Number))
2993 pData->param.data[j].mappedControlIndex = static_cast<int16_t>(portMidiMap.Number);
2996 else if (LV2_IS_PORT_OUTPUT(portTypes))
2998 pData->param.data[j].type = PARAMETER_OUTPUT;
3000 if (LV2_IS_PORT_DESIGNATION_LATENCY(portDesignation))
3002 min = 0.0f;
3003 max = sampleRate;
3004 def = 0.0f;
3005 step = 1.0f;
3006 stepSmall = 1.0f;
3007 stepLarge = 1.0f;
3008 pData->param.special[j] = PARAMETER_SPECIAL_LATENCY;
3009 CARLA_SAFE_ASSERT_INT2(fLatencyIndex == static_cast<int32_t>(j), fLatencyIndex, j);
3011 else if (LV2_IS_PORT_DESIGNATION_SAMPLE_RATE(portDesignation))
3013 def = sampleRate;
3014 step = 1.0f;
3015 stepSmall = 1.0f;
3016 stepLarge = 1.0f;
3017 pData->param.special[j] = PARAMETER_SPECIAL_SAMPLE_RATE;
3019 else if (LV2_IS_PORT_DESIGNATION_FREEWHEELING(portDesignation))
3021 carla_stderr("Plugin has freewheeling output port, this should not happen!");
3023 else if (LV2_IS_PORT_DESIGNATION_TIME(portDesignation))
3025 pData->param.special[j] = PARAMETER_SPECIAL_TIME;
3027 else
3029 pData->param.data[j].hints |= PARAMETER_IS_ENABLED;
3030 pData->param.data[j].hints |= PARAMETER_IS_AUTOMATABLE;
3031 needsCtrlOut = true;
3034 else
3036 pData->param.data[j].type = PARAMETER_UNKNOWN;
3037 carla_stderr2("WARNING - Got a broken Port (Control, but not input or output)");
3040 // extra parameter hints
3041 if (LV2_IS_PORT_LOGARITHMIC(portProps))
3042 pData->param.data[j].hints |= PARAMETER_IS_LOGARITHMIC;
3044 if (LV2_IS_PORT_TRIGGER(portProps))
3045 pData->param.data[j].hints |= PARAMETER_IS_TRIGGER;
3047 if (LV2_IS_PORT_STRICT_BOUNDS(portProps))
3048 pData->param.data[j].hints |= PARAMETER_IS_STRICT_BOUNDS;
3050 if (LV2_IS_PORT_ENUMERATION(portProps))
3051 pData->param.data[j].hints |= PARAMETER_USES_SCALEPOINTS;
3053 // check if parameter is not enabled or automatable
3054 if (LV2_IS_PORT_NOT_ON_GUI(portProps))
3055 pData->param.data[j].hints &= ~(PARAMETER_IS_ENABLED|PARAMETER_IS_AUTOMATABLE);
3056 else if (LV2_IS_PORT_CAUSES_ARTIFACTS(portProps) || LV2_IS_PORT_EXPENSIVE(portProps))
3057 pData->param.data[j].hints &= ~PARAMETER_IS_AUTOMATABLE;
3058 else if (LV2_IS_PORT_NOT_AUTOMATIC(portProps) || LV2_IS_PORT_NON_AUTOMATABLE(portProps))
3059 pData->param.data[j].hints &= ~PARAMETER_IS_AUTOMATABLE;
3061 pData->param.ranges[j].min = min;
3062 pData->param.ranges[j].max = max;
3063 pData->param.ranges[j].def = def;
3064 pData->param.ranges[j].step = step;
3065 pData->param.ranges[j].stepSmall = stepSmall;
3066 pData->param.ranges[j].stepLarge = stepLarge;
3068 // Start parameters in their default values (except freewheel, which is off by default)
3069 if (pData->param.data[j].type == PARAMETER_INPUT && pData->param.special[j] == PARAMETER_SPECIAL_FREEWHEEL)
3070 fParamBuffers[j] = min;
3071 else
3072 fParamBuffers[j] = def;
3074 fDescriptor->connect_port(fHandle, i, &fParamBuffers[j]);
3076 if (fHandle2 != nullptr)
3077 fDescriptor->connect_port(fHandle2, i, &fParamBuffers[j]);
3079 else
3081 // Port Type not supported, but it's optional anyway
3082 fDescriptor->connect_port(fHandle, i, nullptr);
3084 if (fHandle2 != nullptr)
3085 fDescriptor->connect_port(fHandle2, i, nullptr);
3089 for (uint32_t i=0; i < fRdfDescriptor->ParameterCount; ++i)
3091 const LV2_RDF_Parameter& rdfParam(fRdfDescriptor->Parameters[i]);
3093 switch (rdfParam.Type)
3095 case LV2_PARAMETER_TYPE_BOOL:
3096 case LV2_PARAMETER_TYPE_INT:
3097 // case LV2_PARAMETER_TYPE_LONG:
3098 case LV2_PARAMETER_TYPE_FLOAT:
3099 case LV2_PARAMETER_TYPE_DOUBLE:
3100 break;
3101 default:
3102 continue;
3105 const LV2_RDF_PortPoints& portPoints(rdfParam.Points);
3107 const uint32_t j = iCtrl++;
3108 pData->param.data[j].index = static_cast<int32_t>(j);
3109 pData->param.data[j].rindex = static_cast<int32_t>(fRdfDescriptor->PortCount + i);
3111 float min, max, def, step, stepSmall, stepLarge;
3113 // min value
3114 if (LV2_HAVE_MINIMUM_PORT_POINT(portPoints.Hints))
3115 min = portPoints.Minimum;
3116 else
3117 min = 0.0f;
3119 // max value
3120 if (LV2_HAVE_MAXIMUM_PORT_POINT(portPoints.Hints))
3121 max = portPoints.Maximum;
3122 else
3123 max = 1.0f;
3125 if (min >= max)
3127 carla_stderr2("WARNING - Broken plugin parameter '%s': min >= max", rdfParam.Label);
3128 max = min + 0.1f;
3131 // default value
3132 if (LV2_HAVE_DEFAULT_PORT_POINT(portPoints.Hints))
3134 def = portPoints.Default;
3136 else
3138 // no default value
3139 if (min < 0.0f && max > 0.0f)
3140 def = 0.0f;
3141 else
3142 def = min;
3145 if (def < min)
3146 def = min;
3147 else if (def > max)
3148 def = max;
3150 switch (rdfParam.Type)
3152 case LV2_PARAMETER_TYPE_BOOL:
3153 step = max - min;
3154 stepSmall = step;
3155 stepLarge = step;
3156 pData->param.data[j].hints |= PARAMETER_IS_BOOLEAN;
3157 break;
3159 case LV2_PARAMETER_TYPE_INT:
3160 case LV2_PARAMETER_TYPE_LONG:
3161 step = 1.0f;
3162 stepSmall = 1.0f;
3163 stepLarge = 10.0f;
3164 pData->param.data[j].hints |= PARAMETER_IS_INTEGER;
3165 break;
3167 default:
3168 const float range = max - min;
3169 step = range/100.0f;
3170 stepSmall = range/1000.0f;
3171 stepLarge = range/10.0f;
3172 break;
3175 if (rdfParam.Flags & LV2_PARAMETER_FLAG_INPUT)
3177 pData->param.data[j].type = PARAMETER_INPUT;
3178 pData->param.data[j].hints |= PARAMETER_IS_ENABLED;
3179 pData->param.data[j].hints |= PARAMETER_IS_AUTOMATABLE;
3180 pData->param.data[j].hints |= PARAMETER_IS_NOT_SAVED;
3181 needsCtrlIn = true;
3183 if (rdfParam.Flags & LV2_PARAMETER_FLAG_OUTPUT)
3184 hasPatchParameterOutputs = true;
3186 if (LV2_IS_PORT_MIDI_MAP_CC(rdfParam.MidiMap.Type))
3188 if (rdfParam.MidiMap.Number < MAX_MIDI_CONTROL && ! MIDI_IS_CONTROL_BANK_SELECT(rdfParam.MidiMap.Number))
3189 pData->param.data[j].mappedControlIndex = static_cast<int16_t>(rdfParam.MidiMap.Number);
3192 else if (rdfParam.Flags & LV2_PARAMETER_FLAG_OUTPUT)
3194 pData->param.data[j].type = PARAMETER_OUTPUT;
3195 pData->param.data[j].hints |= PARAMETER_IS_ENABLED;
3196 pData->param.data[j].hints |= PARAMETER_IS_AUTOMATABLE;
3197 needsCtrlOut = true;
3198 hasPatchParameterOutputs = true;
3201 pData->param.ranges[j].min = min;
3202 pData->param.ranges[j].max = max;
3203 pData->param.ranges[j].def = def;
3204 pData->param.ranges[j].step = step;
3205 pData->param.ranges[j].stepSmall = stepSmall;
3206 pData->param.ranges[j].stepLarge = stepLarge;
3208 fParamBuffers[j] = def;
3211 if (needsCtrlIn)
3213 portName.clear();
3215 if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
3217 portName = pData->name;
3218 portName += ":";
3221 portName += "events-in";
3222 portName.truncate(portNameSize);
3224 pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, 0);
3225 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
3226 pData->event.cvSourcePorts = pData->client->createCVSourcePorts();
3227 #endif
3230 if (needsCtrlOut)
3232 portName.clear();
3234 if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
3236 portName = pData->name;
3237 portName += ":";
3240 portName += "events-out";
3241 portName.truncate(portNameSize);
3243 pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, 0);
3246 if (fExt.worker != nullptr && fEventsIn.ctrl != nullptr)
3248 fAtomBufferWorkerIn.createBuffer(eventBufferSize, true);
3249 fAtomBufferWorkerResp.createBuffer(eventBufferSize, true);
3250 fAtomBufferRealtimeSize = fAtomBufferWorkerIn.getSize(); // actual buffer size will be next power of 2
3251 fAtomBufferRealtime = static_cast<LV2_Atom*>(std::malloc(fAtomBufferRealtimeSize));
3252 fAtomBufferWorkerInTmpData = new uint8_t[fAtomBufferRealtimeSize];
3253 carla_mlock(fAtomBufferRealtime, fAtomBufferRealtimeSize);
3256 if (fRdfDescriptor->ParameterCount > 0 ||
3257 (fUI.type != UI::TYPE_NULL && fEventsIn.count > 0 && (fEventsIn.data[0].type & CARLA_EVENT_DATA_ATOM) != 0))
3259 fAtomBufferEvIn.createBuffer(eventBufferSize, true);
3261 if (fAtomBufferRealtimeSize == 0)
3263 fAtomBufferRealtimeSize = fAtomBufferEvIn.getSize(); // actual buffer size will be next power of 2
3264 fAtomBufferRealtime = static_cast<LV2_Atom*>(std::malloc(fAtomBufferRealtimeSize));
3265 carla_mlock(fAtomBufferRealtime, fAtomBufferRealtimeSize);
3269 if (hasPatchParameterOutputs ||
3270 (fUI.type != UI::TYPE_NULL && fEventsOut.count > 0 && (fEventsOut.data[0].type & CARLA_EVENT_DATA_ATOM) != 0))
3272 fAtomBufferUiOut.createBuffer(std::min(eventBufferSize*32, 1638400U), true);
3273 fAtomBufferUiOutTmpData = new uint8_t[fAtomBufferUiOut.getSize()];
3276 if (fEventsIn.ctrl != nullptr && fEventsIn.ctrl->port == nullptr)
3277 fEventsIn.ctrl->port = pData->event.portIn;
3279 if (fEventsOut.ctrl != nullptr && fEventsOut.ctrl->port == nullptr)
3280 fEventsOut.ctrl->port = pData->event.portOut;
3282 if (fEventsIn.ctrl != nullptr && fExt.midnam != nullptr)
3284 if (char* const midnam = fExt.midnam->midnam(fHandle))
3286 fEventsIn.ctrl->port->setMetaData("http://www.midi.org/dtds/MIDINameDocument10.dtd",
3287 midnam, "text/xml");
3288 if (fExt.midnam->free != nullptr)
3289 fExt.midnam->free(midnam);
3293 if (forcedStereoIn || forcedStereoOut)
3294 pData->options |= PLUGIN_OPTION_FORCE_STEREO;
3295 else
3296 pData->options &= ~PLUGIN_OPTION_FORCE_STEREO;
3298 // plugin hints
3299 pData->hints = (pData->hints & PLUGIN_HAS_INLINE_DISPLAY) ? PLUGIN_HAS_INLINE_DISPLAY : 0
3300 | (pData->hints & PLUGIN_NEEDS_UI_MAIN_THREAD) ? PLUGIN_NEEDS_UI_MAIN_THREAD : 0;
3302 if (isRealtimeSafe())
3303 pData->hints |= PLUGIN_IS_RTSAFE;
3305 if (fUI.type != UI::TYPE_NULL || fFilePathURI.isNotEmpty())
3307 pData->hints |= PLUGIN_HAS_CUSTOM_UI;
3309 if (fUI.type == UI::TYPE_EMBED)
3311 switch (fUI.rdfDescriptor->Type)
3313 case LV2_UI_GTK2:
3314 case LV2_UI_GTK3:
3315 case LV2_UI_QT4:
3316 case LV2_UI_QT5:
3317 case LV2_UI_EXTERNAL:
3318 case LV2_UI_OLD_EXTERNAL:
3319 break;
3320 default:
3321 pData->hints |= PLUGIN_HAS_CUSTOM_EMBED_UI;
3322 break;
3326 if (fUI.type == UI::TYPE_EMBED || fUI.type == UI::TYPE_EXTERNAL)
3327 pData->hints |= PLUGIN_NEEDS_UI_MAIN_THREAD;
3328 else if (fFilePathURI.isNotEmpty())
3329 pData->hints |= PLUGIN_HAS_CUSTOM_UI_USING_FILE_OPEN;
3332 if (LV2_IS_GENERATOR(fRdfDescriptor->Type[0], fRdfDescriptor->Type[1]))
3333 pData->hints |= PLUGIN_IS_SYNTH;
3335 if (aOuts > 0 && (aIns == aOuts || aIns == 1))
3336 pData->hints |= PLUGIN_CAN_DRYWET;
3338 if (aOuts > 0)
3339 pData->hints |= PLUGIN_CAN_VOLUME;
3341 if (aOuts >= 2 && aOuts % 2 == 0)
3342 pData->hints |= PLUGIN_CAN_BALANCE;
3344 // extra plugin hints
3345 pData->extraHints = 0x0;
3347 // check initial latency
3348 findInitialLatencyValue(aIns, cvIns, aOuts, cvOuts);
3350 bufferSizeChanged(pData->engine->getBufferSize());
3351 reloadPrograms(true);
3353 evIns.clear();
3354 evOuts.clear();
3356 if (pData->active)
3357 activate();
3359 carla_debug("CarlaPluginLV2::reload() - end");
3362 void findInitialLatencyValue(const uint32_t aIns,
3363 const uint32_t cvIns,
3364 const uint32_t aOuts,
3365 const uint32_t cvOuts) const
3367 if (fLatencyIndex < 0)
3368 return;
3370 // we need to pre-run the plugin so it can update its latency control-port
3371 const uint32_t bufferSize = static_cast<uint32_t>(fLv2Options.nominalBufferSize);
3373 float* tmpIn[96];
3374 float* tmpOut[96];
3377 uint32_t i=0;
3378 for (; i < aIns; ++i)
3380 tmpIn[i] = new float[bufferSize];
3381 carla_zeroFloats(tmpIn[i], bufferSize);
3383 try {
3384 fDescriptor->connect_port(fHandle, pData->audioIn.ports[i].rindex, tmpIn[i]);
3385 } CARLA_SAFE_EXCEPTION("LV2 connect_port latency audio input");
3388 for (uint32_t j=0; j < cvIns; ++i, ++j)
3390 tmpIn[i] = new float[bufferSize];
3391 carla_zeroFloats(tmpIn[i], bufferSize);
3393 try {
3394 fDescriptor->connect_port(fHandle, pData->cvIn.ports[j].rindex, tmpIn[i]);
3395 } CARLA_SAFE_EXCEPTION("LV2 connect_port latency cv input");
3400 uint32_t i=0;
3401 for (; i < aOuts; ++i)
3403 tmpOut[i] = new float[bufferSize];
3404 carla_zeroFloats(tmpOut[i], bufferSize);
3406 try {
3407 fDescriptor->connect_port(fHandle, pData->audioOut.ports[i].rindex, tmpOut[i]);
3408 } CARLA_SAFE_EXCEPTION("LV2 connect_port latency audio output");
3411 for (uint32_t j=0; j < cvOuts; ++i, ++j)
3413 tmpOut[i] = new float[bufferSize];
3414 carla_zeroFloats(tmpOut[i], bufferSize);
3416 try {
3417 fDescriptor->connect_port(fHandle, pData->cvOut.ports[j].rindex, tmpOut[i]);
3418 } CARLA_SAFE_EXCEPTION("LV2 connect_port latency cv output");
3422 if (fDescriptor->activate != nullptr)
3424 try {
3425 fDescriptor->activate(fHandle);
3426 } CARLA_SAFE_EXCEPTION("LV2 latency activate");
3429 try {
3430 fDescriptor->run(fHandle, bufferSize);
3431 } CARLA_SAFE_EXCEPTION("LV2 latency run");
3433 if (fDescriptor->deactivate != nullptr)
3435 try {
3436 fDescriptor->deactivate(fHandle);
3437 } CARLA_SAFE_EXCEPTION("LV2 latency deactivate");
3440 // done, let's get the value
3441 if (const uint32_t latency = getLatencyInFrames())
3443 pData->client->setLatency(latency);
3444 #ifndef BUILD_BRIDGE
3445 pData->latency.recreateBuffers(std::max(aIns, aOuts), latency);
3446 #endif
3449 for (uint32_t i=0; i < aIns + cvIns; ++i)
3450 delete[] tmpIn[i];
3452 for (uint32_t i=0; i < aOuts + cvOuts; ++i)
3453 delete[] tmpOut[i];
3456 void reloadPrograms(const bool doInit) override
3458 carla_debug("CarlaPluginLV2::reloadPrograms(%s)", bool2str(doInit));
3459 const uint32_t oldCount = pData->midiprog.count;
3460 const int32_t current = pData->midiprog.current;
3462 // special LV2 programs handling
3463 if (doInit)
3465 pData->prog.clear();
3467 const uint32_t presetCount(fRdfDescriptor->PresetCount);
3469 if (presetCount > 0)
3471 pData->prog.createNew(presetCount);
3473 for (uint32_t i=0; i < presetCount; ++i)
3474 pData->prog.names[i] = carla_strdup(fRdfDescriptor->Presets[i].Label);
3478 // Delete old programs
3479 pData->midiprog.clear();
3481 // Query new programs
3482 uint32_t newCount = 0;
3483 if (fExt.programs != nullptr && fExt.programs->get_program != nullptr && fExt.programs->select_program != nullptr)
3485 for (; fExt.programs->get_program(fHandle, newCount);)
3486 ++newCount;
3489 if (newCount > 0)
3491 pData->midiprog.createNew(newCount);
3493 // Update data
3494 for (uint32_t i=0; i < newCount; ++i)
3496 const LV2_Program_Descriptor* const pdesc(fExt.programs->get_program(fHandle, i));
3497 CARLA_SAFE_ASSERT_CONTINUE(pdesc != nullptr);
3498 CARLA_SAFE_ASSERT(pdesc->name != nullptr);
3500 pData->midiprog.data[i].bank = pdesc->bank;
3501 pData->midiprog.data[i].program = pdesc->program;
3502 pData->midiprog.data[i].name = carla_strdup(pdesc->name);
3506 if (doInit)
3508 if (newCount > 0)
3510 setMidiProgram(0, false, false, false, true);
3512 else if (fHasLoadDefaultState)
3514 // load default state
3515 if (LilvState* const state = Lv2WorldClass::getInstance().getStateFromURI(fDescriptor->URI,
3516 (const LV2_URID_Map*)fFeatures[kFeatureIdUridMap]->data))
3518 lilv_state_restore(state, fExt.state, fHandle, carla_lilv_set_port_value, this, 0, fFeatures);
3520 if (fHandle2 != nullptr)
3521 lilv_state_restore(state, fExt.state, fHandle2, carla_lilv_set_port_value, this, 0, fFeatures);
3523 lilv_state_free(state);
3527 else
3529 // Check if current program is invalid
3530 bool programChanged = false;
3532 if (newCount == oldCount+1)
3534 // one midi program added, probably created by user
3535 pData->midiprog.current = static_cast<int32_t>(oldCount);
3536 programChanged = true;
3538 else if (current < 0 && newCount > 0)
3540 // programs exist now, but not before
3541 pData->midiprog.current = 0;
3542 programChanged = true;
3544 else if (current >= 0 && newCount == 0)
3546 // programs existed before, but not anymore
3547 pData->midiprog.current = -1;
3548 programChanged = true;
3550 else if (current >= static_cast<int32_t>(newCount))
3552 // current midi program > count
3553 pData->midiprog.current = 0;
3554 programChanged = true;
3556 else
3558 // no change
3559 pData->midiprog.current = current;
3562 if (programChanged)
3563 setMidiProgram(pData->midiprog.current, true, true, true, false);
3565 pData->engine->callback(true, true, ENGINE_CALLBACK_RELOAD_PROGRAMS, pData->id, 0, 0, 0, 0.0f, nullptr);
3569 // -------------------------------------------------------------------
3570 // Plugin processing
3572 void activate() noexcept override
3574 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
3575 CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
3577 if (fDescriptor->activate != nullptr)
3579 try {
3580 fDescriptor->activate(fHandle);
3581 } CARLA_SAFE_EXCEPTION("LV2 activate");
3583 if (fHandle2 != nullptr)
3585 try {
3586 fDescriptor->activate(fHandle2);
3587 } CARLA_SAFE_EXCEPTION("LV2 activate #2");
3591 fFirstActive = true;
3594 void deactivate() noexcept override
3596 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
3597 CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
3599 if (fDescriptor->deactivate != nullptr)
3601 try {
3602 fDescriptor->deactivate(fHandle);
3603 } CARLA_SAFE_EXCEPTION("LV2 deactivate");
3605 if (fHandle2 != nullptr)
3607 try {
3608 fDescriptor->deactivate(fHandle2);
3609 } CARLA_SAFE_EXCEPTION("LV2 deactivate #2");
3614 void process(const float* const* const audioIn, float** const audioOut,
3615 const float* const* const cvIn, float** const cvOut, const uint32_t frames) override
3617 // --------------------------------------------------------------------------------------------------------
3618 // Check if active
3620 if (! pData->active)
3622 // disable any output sound
3623 for (uint32_t i=0; i < pData->audioOut.count; ++i)
3624 carla_zeroFloats(audioOut[i], frames);
3625 for (uint32_t i=0; i < pData->cvOut.count; ++i)
3626 carla_zeroFloats(cvOut[i], frames);
3627 return;
3630 // --------------------------------------------------------------------------------------------------------
3631 // Event itenerators from different APIs (input)
3633 for (uint32_t i=0; i < fEventsIn.count; ++i)
3635 if (fEventsIn.data[i].type & CARLA_EVENT_DATA_ATOM)
3637 lv2_atom_buffer_reset(fEventsIn.data[i].atom, true);
3638 lv2_atom_buffer_begin(&fEventsIn.iters[i].atom, fEventsIn.data[i].atom);
3640 else if (fEventsIn.data[i].type & CARLA_EVENT_DATA_EVENT)
3642 lv2_event_buffer_reset(fEventsIn.data[i].event, LV2_EVENT_AUDIO_STAMP, fEventsIn.data[i].event->data);
3643 lv2_event_begin(&fEventsIn.iters[i].event, fEventsIn.data[i].event);
3645 else if (fEventsIn.data[i].type & CARLA_EVENT_DATA_MIDI_LL)
3647 fEventsIn.data[i].midi.event_count = 0;
3648 fEventsIn.data[i].midi.size = 0;
3649 LV2_MIDIState& midiState(fEventsIn.iters[i].midiState);
3650 midiState.midi = &fEventsIn.data[i].midi;
3651 midiState.frame_count = frames;
3652 midiState.position = 0;
3656 for (uint32_t i=0; i < fEventsOut.count; ++i)
3658 if (fEventsOut.data[i].type & CARLA_EVENT_DATA_ATOM)
3660 lv2_atom_buffer_reset(fEventsOut.data[i].atom, false);
3662 else if (fEventsOut.data[i].type & CARLA_EVENT_DATA_EVENT)
3664 lv2_event_buffer_reset(fEventsOut.data[i].event, LV2_EVENT_AUDIO_STAMP, fEventsOut.data[i].event->data);
3666 else if (fEventsOut.data[i].type & CARLA_EVENT_DATA_MIDI_LL)
3668 // not needed
3672 // --------------------------------------------------------------------------------------------------------
3673 // Check if needs reset
3675 if (pData->needsReset)
3677 if (fEventsIn.ctrl != nullptr && (fEventsIn.ctrl->type & CARLA_EVENT_TYPE_MIDI) != 0)
3679 const uint32_t j = fEventsIn.ctrlIndex;
3680 CARLA_ASSERT(j < fEventsIn.count);
3682 uint8_t midiData[3] = { 0, 0, 0 };
3684 if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
3686 for (uint8_t i=0; i < MAX_MIDI_CHANNELS; ++i)
3688 midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (i & MIDI_CHANNEL_BIT));
3689 midiData[1] = MIDI_CONTROL_ALL_NOTES_OFF;
3691 if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM)
3692 lv2_atom_buffer_write(&fEventsIn.iters[j].atom, 0, 0, kUridMidiEvent, 3, midiData);
3694 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT)
3695 lv2_event_write(&fEventsIn.iters[j].event, 0, 0, kUridMidiEvent, 3, midiData);
3697 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL)
3698 lv2midi_put_event(&fEventsIn.iters[j].midiState, 0.0, 3, midiData);
3700 midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (i & MIDI_CHANNEL_BIT));
3701 midiData[1] = MIDI_CONTROL_ALL_SOUND_OFF;
3703 if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM)
3704 lv2_atom_buffer_write(&fEventsIn.iters[j].atom, 0, 0, kUridMidiEvent, 3, midiData);
3706 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT)
3707 lv2_event_write(&fEventsIn.iters[j].event, 0, 0, kUridMidiEvent, 3, midiData);
3709 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL)
3710 lv2midi_put_event(&fEventsIn.iters[j].midiState, 0.0, 3, midiData);
3713 else if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS)
3715 for (uint8_t k=0; k < MAX_MIDI_NOTE; ++k)
3717 midiData[0] = uint8_t(MIDI_STATUS_NOTE_OFF | (pData->ctrlChannel & MIDI_CHANNEL_BIT));
3718 midiData[1] = k;
3720 if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM)
3721 lv2_atom_buffer_write(&fEventsIn.iters[j].atom, 0, 0, kUridMidiEvent, 3, midiData);
3723 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT)
3724 lv2_event_write(&fEventsIn.iters[j].event, 0, 0, kUridMidiEvent, 3, midiData);
3726 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL)
3727 lv2midi_put_event(&fEventsIn.iters[j].midiState, 0.0, 3, midiData);
3732 pData->needsReset = false;
3735 // --------------------------------------------------------------------------------------------------------
3736 // TimeInfo
3738 const EngineTimeInfo timeInfo(pData->engine->getTimeInfo());
3740 if (fFirstActive || fLastTimeInfo != timeInfo)
3742 bool doPostRt;
3743 int32_t rindex;
3745 const double barBeat = static_cast<double>(timeInfo.bbt.beat - 1)
3746 + (timeInfo.bbt.tick / timeInfo.bbt.ticksPerBeat);
3748 // update input ports
3749 for (uint32_t k=0; k < pData->param.count; ++k)
3751 if (pData->param.data[k].type != PARAMETER_INPUT)
3752 continue;
3753 if (pData->param.special[k] != PARAMETER_SPECIAL_TIME)
3754 continue;
3756 doPostRt = false;
3757 rindex = pData->param.data[k].rindex;
3759 CARLA_SAFE_ASSERT_CONTINUE(rindex >= 0 && rindex < static_cast<int32_t>(fRdfDescriptor->PortCount));
3761 switch (fRdfDescriptor->Ports[rindex].Designation)
3763 // Non-BBT
3764 case LV2_PORT_DESIGNATION_TIME_SPEED:
3765 if (fLastTimeInfo.playing != timeInfo.playing)
3767 fParamBuffers[k] = timeInfo.playing ? 1.0f : 0.0f;
3768 doPostRt = true;
3770 break;
3772 case LV2_PORT_DESIGNATION_TIME_FRAME:
3773 if (fLastTimeInfo.frame != timeInfo.frame)
3775 fParamBuffers[k] = static_cast<float>(timeInfo.frame);
3776 doPostRt = true;
3778 break;
3780 case LV2_PORT_DESIGNATION_TIME_FRAMES_PER_SECOND:
3781 break;
3783 // BBT
3784 case LV2_PORT_DESIGNATION_TIME_BAR:
3785 if (timeInfo.bbt.valid && fLastTimeInfo.bbt.bar != timeInfo.bbt.bar)
3787 fParamBuffers[k] = static_cast<float>(timeInfo.bbt.bar - 1);
3788 doPostRt = true;
3790 break;
3792 case LV2_PORT_DESIGNATION_TIME_BAR_BEAT:
3793 if (timeInfo.bbt.valid && (carla_isNotEqual(fLastTimeInfo.bbt.tick, timeInfo.bbt.tick) ||
3794 fLastTimeInfo.bbt.beat != timeInfo.bbt.beat))
3796 fParamBuffers[k] = static_cast<float>(barBeat);
3797 doPostRt = true;
3799 break;
3801 case LV2_PORT_DESIGNATION_TIME_BEAT:
3802 if (timeInfo.bbt.valid && fLastTimeInfo.bbt.beat != timeInfo.bbt.beat)
3804 fParamBuffers[k] = static_cast<float>(timeInfo.bbt.beat - 1);
3805 doPostRt = true;
3807 break;
3809 case LV2_PORT_DESIGNATION_TIME_BEAT_UNIT:
3810 if (timeInfo.bbt.valid && carla_isNotEqual(fLastTimeInfo.bbt.beatType, timeInfo.bbt.beatType))
3812 fParamBuffers[k] = timeInfo.bbt.beatType;
3813 doPostRt = true;
3815 break;
3816 case LV2_PORT_DESIGNATION_TIME_BEATS_PER_BAR:
3817 if (timeInfo.bbt.valid && carla_isNotEqual(fLastTimeInfo.bbt.beatsPerBar, timeInfo.bbt.beatsPerBar))
3819 fParamBuffers[k] = timeInfo.bbt.beatsPerBar;
3820 doPostRt = true;
3822 break;
3824 case LV2_PORT_DESIGNATION_TIME_BEATS_PER_MINUTE:
3825 if (timeInfo.bbt.valid && carla_isNotEqual(fLastTimeInfo.bbt.beatsPerMinute, timeInfo.bbt.beatsPerMinute))
3827 fParamBuffers[k] = static_cast<float>(timeInfo.bbt.beatsPerMinute);
3828 doPostRt = true;
3830 break;
3832 case LV2_PORT_DESIGNATION_TIME_TICKS_PER_BEAT:
3833 if (timeInfo.bbt.valid && carla_isNotEqual(fLastTimeInfo.bbt.ticksPerBeat, timeInfo.bbt.ticksPerBeat))
3835 fParamBuffers[k] = static_cast<float>(timeInfo.bbt.ticksPerBeat);
3836 doPostRt = true;
3838 break;
3841 if (doPostRt)
3842 pData->postponeParameterChangeRtEvent(true, static_cast<int32_t>(k), fParamBuffers[k]);
3845 for (uint32_t i=0; i < fEventsIn.count; ++i)
3847 if ((fEventsIn.data[i].type & CARLA_EVENT_DATA_ATOM) == 0 || (fEventsIn.data[i].type & CARLA_EVENT_TYPE_TIME) == 0)
3848 continue;
3850 uint8_t timeInfoBuf[256];
3851 LV2_Atom_Forge atomForge;
3852 initAtomForge(atomForge);
3853 lv2_atom_forge_set_buffer(&atomForge, timeInfoBuf, sizeof(timeInfoBuf));
3855 LV2_Atom_Forge_Frame forgeFrame;
3856 lv2_atom_forge_object(&atomForge, &forgeFrame, kUridNull, kUridTimePosition);
3858 lv2_atom_forge_key(&atomForge, kUridTimeSpeed);
3859 lv2_atom_forge_float(&atomForge, timeInfo.playing ? 1.0f : 0.0f);
3861 lv2_atom_forge_key(&atomForge, kUridTimeFrame);
3862 lv2_atom_forge_long(&atomForge, static_cast<int64_t>(timeInfo.frame));
3864 if (timeInfo.bbt.valid)
3866 lv2_atom_forge_key(&atomForge, kUridTimeBar);
3867 lv2_atom_forge_long(&atomForge, timeInfo.bbt.bar - 1);
3869 lv2_atom_forge_key(&atomForge, kUridTimeBarBeat);
3870 lv2_atom_forge_float(&atomForge, static_cast<float>(barBeat));
3872 lv2_atom_forge_key(&atomForge, kUridTimeBeat);
3873 lv2_atom_forge_double(&atomForge, timeInfo.bbt.beat - 1);
3875 lv2_atom_forge_key(&atomForge, kUridTimeBeatUnit);
3876 lv2_atom_forge_int(&atomForge, static_cast<int32_t>(timeInfo.bbt.beatType));
3878 lv2_atom_forge_key(&atomForge, kUridTimeBeatsPerBar);
3879 lv2_atom_forge_float(&atomForge, timeInfo.bbt.beatsPerBar);
3881 lv2_atom_forge_key(&atomForge, kUridTimeBeatsPerMinute);
3882 lv2_atom_forge_float(&atomForge, static_cast<float>(timeInfo.bbt.beatsPerMinute));
3884 lv2_atom_forge_key(&atomForge, kUridTimeTicksPerBeat);
3885 lv2_atom_forge_double(&atomForge, timeInfo.bbt.ticksPerBeat);
3888 lv2_atom_forge_pop(&atomForge, &forgeFrame);
3890 LV2_Atom* const atom((LV2_Atom*)timeInfoBuf);
3891 CARLA_SAFE_ASSERT_BREAK(atom->size < 256);
3893 // send only deprecated blank object for now
3894 lv2_atom_buffer_write(&fEventsIn.iters[i].atom, 0, 0, kUridAtomBlank, atom->size, LV2_ATOM_BODY_CONST(atom));
3896 // for atom:object
3897 //lv2_atom_buffer_write(&fEventsIn.iters[i].atom, 0, 0, atom->type, atom->size, LV2_ATOM_BODY_CONST(atom));
3900 pData->postRtEvents.trySplice();
3902 fLastTimeInfo = timeInfo;
3905 // --------------------------------------------------------------------------------------------------------
3906 // Event Input and Processing
3908 if (fEventsIn.ctrl != nullptr)
3910 // ----------------------------------------------------------------------------------------------------
3911 // Message Input
3913 if (fAtomBufferEvIn.tryLock())
3915 if (fAtomBufferEvIn.isDataAvailableForReading())
3917 uint32_t j, portIndex;
3918 LV2_Atom* const atom = fAtomBufferRealtime;
3919 atom->size = fAtomBufferRealtimeSize;
3921 for (; fAtomBufferEvIn.get(portIndex, atom); atom->size = fAtomBufferRealtimeSize)
3923 j = (portIndex < fEventsIn.count) ? portIndex : fEventsIn.ctrlIndex;
3925 if (! lv2_atom_buffer_write(&fEventsIn.iters[j].atom, 0, 0, atom->type, atom->size, LV2_ATOM_BODY_CONST(atom)))
3927 carla_stderr2("Event input buffer full, at least 1 message lost");
3928 continue;
3931 inspectAtomForParameterChange(atom);
3935 fAtomBufferEvIn.unlock();
3938 // ----------------------------------------------------------------------------------------------------
3939 // MIDI Input (External)
3941 if (pData->extNotes.mutex.tryLock())
3943 if ((fEventsIn.ctrl->type & CARLA_EVENT_TYPE_MIDI) == 0)
3945 // does not handle MIDI
3946 pData->extNotes.data.clear();
3948 else
3950 const uint32_t j = fEventsIn.ctrlIndex;
3952 for (RtLinkedList<ExternalMidiNote>::Itenerator it = pData->extNotes.data.begin2(); it.valid(); it.next())
3954 const ExternalMidiNote& note(it.getValue(kExternalMidiNoteFallback));
3955 CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS);
3957 uint8_t midiEvent[3];
3958 midiEvent[0] = uint8_t((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT));
3959 midiEvent[1] = note.note;
3960 midiEvent[2] = note.velo;
3962 if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM)
3963 lv2_atom_buffer_write(&fEventsIn.iters[j].atom, 0, 0, kUridMidiEvent, 3, midiEvent);
3965 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT)
3966 lv2_event_write(&fEventsIn.iters[j].event, 0, 0, kUridMidiEvent, 3, midiEvent);
3968 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL)
3969 lv2midi_put_event(&fEventsIn.iters[j].midiState, 0.0, 3, midiEvent);
3972 pData->extNotes.data.clear();
3975 pData->extNotes.mutex.unlock();
3977 } // End of MIDI Input (External)
3979 // ----------------------------------------------------------------------------------------------------
3980 // Event Input (System)
3982 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
3983 bool allNotesOffSent = false;
3984 #endif
3985 bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0;
3987 uint32_t startTime = 0;
3988 uint32_t timeOffset = 0;
3989 uint32_t nextBankId;
3991 if (pData->midiprog.current >= 0 && pData->midiprog.count > 0)
3992 nextBankId = pData->midiprog.data[pData->midiprog.current].bank;
3993 else
3994 nextBankId = 0;
3996 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
3997 if (cvIn != nullptr && pData->event.cvSourcePorts != nullptr)
3998 pData->event.cvSourcePorts->initPortBuffers(cvIn + pData->cvIn.count, frames, isSampleAccurate, pData->event.portIn);
3999 #endif
4001 const uint32_t numEvents = (fEventsIn.ctrl->port != nullptr) ? fEventsIn.ctrl->port->getEventCount() : 0;
4003 for (uint32_t i=0; i < numEvents; ++i)
4005 EngineEvent& event(fEventsIn.ctrl->port->getEvent(i));
4007 uint32_t eventTime = event.time;
4008 CARLA_SAFE_ASSERT_UINT2_CONTINUE(eventTime < frames, eventTime, frames);
4010 if (eventTime < timeOffset)
4012 carla_stderr2("Timing error, eventTime:%u < timeOffset:%u for '%s'",
4013 eventTime, timeOffset, pData->name);
4014 eventTime = timeOffset;
4017 if (isSampleAccurate && eventTime > timeOffset)
4019 if (processSingle(audioIn, audioOut, cvIn, cvOut, eventTime - timeOffset, timeOffset))
4021 startTime = 0;
4022 timeOffset = eventTime;
4024 if (pData->midiprog.current >= 0 && pData->midiprog.count > 0)
4025 nextBankId = pData->midiprog.data[pData->midiprog.current].bank;
4026 else
4027 nextBankId = 0;
4029 for (uint32_t j=0; j < fEventsIn.count; ++j)
4031 if (fEventsIn.data[j].type & CARLA_EVENT_DATA_ATOM)
4033 lv2_atom_buffer_reset(fEventsIn.data[j].atom, true);
4034 lv2_atom_buffer_begin(&fEventsIn.iters[j].atom, fEventsIn.data[j].atom);
4036 else if (fEventsIn.data[j].type & CARLA_EVENT_DATA_EVENT)
4038 lv2_event_buffer_reset(fEventsIn.data[j].event, LV2_EVENT_AUDIO_STAMP, fEventsIn.data[j].event->data);
4039 lv2_event_begin(&fEventsIn.iters[j].event, fEventsIn.data[j].event);
4041 else if (fEventsIn.data[j].type & CARLA_EVENT_DATA_MIDI_LL)
4043 fEventsIn.data[j].midi.event_count = 0;
4044 fEventsIn.data[j].midi.size = 0;
4045 fEventsIn.iters[j].midiState.position = eventTime;
4049 for (uint32_t j=0; j < fEventsOut.count; ++j)
4051 if (fEventsOut.data[j].type & CARLA_EVENT_DATA_ATOM)
4053 lv2_atom_buffer_reset(fEventsOut.data[j].atom, false);
4055 else if (fEventsOut.data[j].type & CARLA_EVENT_DATA_EVENT)
4057 lv2_event_buffer_reset(fEventsOut.data[j].event, LV2_EVENT_AUDIO_STAMP, fEventsOut.data[j].event->data);
4059 else if (fEventsOut.data[j].type & CARLA_EVENT_DATA_MIDI_LL)
4061 // not needed
4065 else
4067 startTime += timeOffset;
4071 switch (event.type)
4073 case kEngineEventTypeNull:
4074 break;
4076 case kEngineEventTypeControl: {
4077 EngineControlEvent& ctrlEvent(event.ctrl);
4079 switch (ctrlEvent.type)
4081 case kEngineControlEventTypeNull:
4082 break;
4084 case kEngineControlEventTypeParameter: {
4085 float value;
4087 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
4088 // non-midi
4089 if (event.channel == kEngineEventNonMidiChannel)
4091 const uint32_t k = ctrlEvent.param;
4092 CARLA_SAFE_ASSERT_CONTINUE(k < pData->param.count);
4094 ctrlEvent.handled = true;
4095 value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.normalizedValue);
4096 setParameterValueRT(k, value, event.time, true);
4097 continue;
4100 // Control backend stuff
4101 if (event.channel == pData->ctrlChannel)
4103 if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0)
4105 ctrlEvent.handled = true;
4106 value = ctrlEvent.normalizedValue;
4107 setDryWetRT(value, true);
4109 else if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0)
4111 ctrlEvent.handled = true;
4112 value = ctrlEvent.normalizedValue*127.0f/100.0f;
4113 setVolumeRT(value, true);
4115 else if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0)
4117 float left, right;
4118 value = ctrlEvent.normalizedValue/0.5f - 1.0f;
4120 if (value < 0.0f)
4122 left = -1.0f;
4123 right = (value*2.0f)+1.0f;
4125 else if (value > 0.0f)
4127 left = (value*2.0f)-1.0f;
4128 right = 1.0f;
4130 else
4132 left = -1.0f;
4133 right = 1.0f;
4136 ctrlEvent.handled = true;
4137 setBalanceLeftRT(left, true);
4138 setBalanceRightRT(right, true);
4141 #endif
4142 // Control plugin parameters
4143 uint32_t k;
4144 for (k=0; k < pData->param.count; ++k)
4146 if (pData->param.data[k].midiChannel != event.channel)
4147 continue;
4148 if (pData->param.data[k].mappedControlIndex != ctrlEvent.param)
4149 continue;
4150 if (pData->param.data[k].type != PARAMETER_INPUT)
4151 continue;
4152 if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMATABLE) == 0)
4153 continue;
4155 ctrlEvent.handled = true;
4157 if (pData->param.data[k].mappedFlags & PARAMETER_MAPPING_MIDI_DELTA)
4158 value = pData->param.getFinalValueWithMidiDelta(k, fParamBuffers[k], ctrlEvent.midiValue);
4159 else
4160 value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.normalizedValue);
4162 setParameterValueRT(k, value, event.time, true);
4165 if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param < MAX_MIDI_VALUE)
4167 uint8_t midiData[3];
4168 midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT));
4169 midiData[1] = uint8_t(ctrlEvent.param);
4170 midiData[2] = uint8_t(ctrlEvent.normalizedValue*127.0f + 0.5f);
4172 const uint32_t mtime(isSampleAccurate ? startTime : eventTime);
4174 if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM)
4175 lv2_atom_buffer_write(&fEventsIn.iters[fEventsIn.ctrlIndex].atom, mtime, 0, kUridMidiEvent, 3, midiData);
4177 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT)
4178 lv2_event_write(&fEventsIn.iters[fEventsIn.ctrlIndex].event, mtime, 0, kUridMidiEvent, 3, midiData);
4180 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL)
4181 lv2midi_put_event(&fEventsIn.iters[fEventsIn.ctrlIndex].midiState, mtime, 3, midiData);
4184 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
4185 if (! ctrlEvent.handled)
4186 checkForMidiLearn(event);
4187 #endif
4188 break;
4189 } // case kEngineControlEventTypeParameter
4191 case kEngineControlEventTypeMidiBank:
4192 if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES)
4194 if (event.channel == pData->ctrlChannel)
4195 nextBankId = ctrlEvent.param;
4197 else if (pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES)
4199 uint8_t midiData[3];
4200 midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT));
4201 midiData[1] = MIDI_CONTROL_BANK_SELECT;
4202 midiData[2] = uint8_t(ctrlEvent.param);
4204 const uint32_t mtime(isSampleAccurate ? startTime : eventTime);
4206 if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM)
4207 lv2_atom_buffer_write(&fEventsIn.iters[fEventsIn.ctrlIndex].atom, mtime, 0, kUridMidiEvent, 3, midiData);
4209 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT)
4210 lv2_event_write(&fEventsIn.iters[fEventsIn.ctrlIndex].event, mtime, 0, kUridMidiEvent, 3, midiData);
4212 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL)
4213 lv2midi_put_event(&fEventsIn.iters[fEventsIn.ctrlIndex].midiState, mtime, 3, midiData);
4215 break;
4217 case kEngineControlEventTypeMidiProgram:
4218 if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES)
4220 if (event.channel == pData->ctrlChannel)
4222 const uint32_t nextProgramId(ctrlEvent.param);
4224 for (uint32_t k=0; k < pData->midiprog.count; ++k)
4226 if (pData->midiprog.data[k].bank == nextBankId && pData->midiprog.data[k].program == nextProgramId)
4228 setMidiProgramRT(k, true);
4229 break;
4234 else if (pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES)
4236 uint8_t midiData[2];
4237 midiData[0] = uint8_t(MIDI_STATUS_PROGRAM_CHANGE | (event.channel & MIDI_CHANNEL_BIT));
4238 midiData[1] = uint8_t(ctrlEvent.param);
4240 const uint32_t mtime(isSampleAccurate ? startTime : eventTime);
4242 if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM)
4243 lv2_atom_buffer_write(&fEventsIn.iters[fEventsIn.ctrlIndex].atom, mtime, 0, kUridMidiEvent, 2, midiData);
4245 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT)
4246 lv2_event_write(&fEventsIn.iters[fEventsIn.ctrlIndex].event, mtime, 0, kUridMidiEvent, 2, midiData);
4248 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL)
4249 lv2midi_put_event(&fEventsIn.iters[fEventsIn.ctrlIndex].midiState, mtime, 2, midiData);
4251 break;
4253 case kEngineControlEventTypeAllSoundOff:
4254 if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
4256 const uint32_t mtime(isSampleAccurate ? startTime : eventTime);
4258 uint8_t midiData[3];
4259 midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT));
4260 midiData[1] = MIDI_CONTROL_ALL_SOUND_OFF;
4261 midiData[2] = 0;
4263 if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM)
4264 lv2_atom_buffer_write(&fEventsIn.iters[fEventsIn.ctrlIndex].atom, mtime, 0, kUridMidiEvent, 3, midiData);
4266 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT)
4267 lv2_event_write(&fEventsIn.iters[fEventsIn.ctrlIndex].event, mtime, 0, kUridMidiEvent, 3, midiData);
4269 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL)
4270 lv2midi_put_event(&fEventsIn.iters[fEventsIn.ctrlIndex].midiState, mtime, 3, midiData);
4272 break;
4274 case kEngineControlEventTypeAllNotesOff:
4275 if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
4277 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
4278 if (event.channel == pData->ctrlChannel && ! allNotesOffSent)
4280 allNotesOffSent = true;
4281 postponeRtAllNotesOff();
4283 #endif
4285 const uint32_t mtime(isSampleAccurate ? startTime : eventTime);
4287 uint8_t midiData[3];
4288 midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT));
4289 midiData[1] = MIDI_CONTROL_ALL_NOTES_OFF;
4290 midiData[2] = 0;
4292 if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM)
4293 lv2_atom_buffer_write(&fEventsIn.iters[fEventsIn.ctrlIndex].atom, mtime, 0, kUridMidiEvent, 3, midiData);
4295 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT)
4296 lv2_event_write(&fEventsIn.iters[fEventsIn.ctrlIndex].event, mtime, 0, kUridMidiEvent, 3, midiData);
4298 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL)
4299 lv2midi_put_event(&fEventsIn.iters[fEventsIn.ctrlIndex].midiState, mtime, 3, midiData);
4301 break;
4302 } // switch (ctrlEvent.type)
4303 break;
4304 } // case kEngineEventTypeControl
4306 case kEngineEventTypeMidi: {
4307 const EngineMidiEvent& midiEvent(event.midi);
4309 const uint8_t* const midiData = midiEvent.size > EngineMidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data;
4311 uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiData));
4313 if ((status == MIDI_STATUS_NOTE_OFF || status == MIDI_STATUS_NOTE_ON) && (pData->options & PLUGIN_OPTION_SKIP_SENDING_NOTES))
4314 continue;
4315 if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0)
4316 continue;
4317 if (status == MIDI_STATUS_CONTROL_CHANGE && (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0)
4318 continue;
4319 if (status == MIDI_STATUS_POLYPHONIC_AFTERTOUCH && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0)
4320 continue;
4321 if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0)
4322 continue;
4324 // Fix bad note-off (per LV2 spec)
4325 if (status == MIDI_STATUS_NOTE_ON && midiData[2] == 0)
4326 status = MIDI_STATUS_NOTE_OFF;
4328 const uint32_t j = fEventsIn.ctrlIndex;
4329 const uint32_t mtime = isSampleAccurate ? startTime : eventTime;
4331 // put back channel in data
4332 uint8_t midiData2[4]; // FIXME
4333 if (midiEvent.size > 4)
4334 continue;
4336 midiData2[0] = uint8_t(status | (event.channel & MIDI_CHANNEL_BIT));
4337 std::memcpy(midiData2+1, midiData+1, static_cast<std::size_t>(midiEvent.size-1));
4340 if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM)
4341 lv2_atom_buffer_write(&fEventsIn.iters[j].atom, mtime, 0, kUridMidiEvent, midiEvent.size, midiData2);
4343 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT)
4344 lv2_event_write(&fEventsIn.iters[j].event, mtime, 0, kUridMidiEvent, midiEvent.size, midiData2);
4346 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL)
4347 lv2midi_put_event(&fEventsIn.iters[j].midiState, mtime, midiEvent.size, midiData2);
4349 if (status == MIDI_STATUS_NOTE_ON)
4351 pData->postponeNoteOnRtEvent(true, event.channel, midiData[1], midiData[2]);
4353 else if (status == MIDI_STATUS_NOTE_OFF)
4355 pData->postponeNoteOffRtEvent(true, event.channel, midiData[1]);
4357 } break;
4358 } // switch (event.type)
4361 pData->postRtEvents.trySplice();
4363 if (frames > timeOffset)
4364 processSingle(audioIn, audioOut, cvIn, cvOut, frames - timeOffset, timeOffset);
4366 } // End of Event Input and Processing
4368 // --------------------------------------------------------------------------------------------------------
4369 // Plugin processing (no events)
4371 else
4373 processSingle(audioIn, audioOut, cvIn, cvOut, frames, 0);
4375 } // End of Plugin processing (no events)
4377 // --------------------------------------------------------------------------------------------------------
4378 // Final work
4380 if (fEventsIn.ctrl != nullptr && fExt.worker != nullptr && fAtomBufferWorkerResp.tryLock())
4382 if (fAtomBufferWorkerResp.isDataAvailableForReading())
4384 uint32_t portIndex;
4385 LV2_Atom* const atom = fAtomBufferRealtime;
4386 atom->size = fAtomBufferRealtimeSize;
4388 for (; fAtomBufferWorkerResp.get(portIndex, atom); atom->size = fAtomBufferRealtimeSize)
4390 CARLA_SAFE_ASSERT_CONTINUE(atom->type == kUridCarlaAtomWorkerResp);
4391 fExt.worker->work_response(fHandle, atom->size, LV2_ATOM_BODY_CONST(atom));
4395 fAtomBufferWorkerResp.unlock();
4398 if (fExt.worker != nullptr && fExt.worker->end_run != nullptr)
4400 fExt.worker->end_run(fHandle);
4402 if (fHandle2 != nullptr)
4403 fExt.worker->end_run(fHandle2);
4406 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
4407 // --------------------------------------------------------------------------------------------------------
4408 // Control Output
4410 if (pData->event.portOut != nullptr)
4412 uint8_t channel;
4413 uint16_t param;
4414 float value;
4416 for (uint32_t k=0; k < pData->param.count; ++k)
4418 if (pData->param.data[k].type != PARAMETER_OUTPUT)
4419 continue;
4421 if (fStrictBounds >= 0 && (pData->param.data[k].hints & PARAMETER_IS_STRICT_BOUNDS) != 0)
4422 // plugin is responsible to ensure correct bounds
4423 pData->param.ranges[k].fixValue(fParamBuffers[k]);
4425 if (pData->param.data[k].mappedControlIndex > 0)
4427 channel = pData->param.data[k].midiChannel;
4428 param = static_cast<uint16_t>(pData->param.data[k].mappedControlIndex);
4429 value = pData->param.ranges[k].getNormalizedValue(fParamBuffers[k]);
4430 pData->event.portOut->writeControlEvent(0, channel, kEngineControlEventTypeParameter,
4431 param, -1, value);
4434 } // End of Control Output
4435 #endif
4437 // --------------------------------------------------------------------------------------------------------
4438 // Events/MIDI Output
4440 for (uint32_t i=0; i < fEventsOut.count; ++i)
4442 uint32_t lastFrame = 0;
4443 Lv2EventData& evData(fEventsOut.data[i]);
4445 if (evData.type & CARLA_EVENT_DATA_ATOM)
4447 const LV2_Atom_Event* ev;
4448 LV2_Atom_Buffer_Iterator iter;
4450 uint8_t* data;
4451 lv2_atom_buffer_begin(&iter, evData.atom);
4453 for (;;)
4455 data = nullptr;
4456 ev = lv2_atom_buffer_get(&iter, &data);
4458 if (ev == nullptr || ev->body.size == 0 || data == nullptr)
4459 break;
4461 if (ev->body.type == kUridMidiEvent)
4463 if (evData.port != nullptr)
4465 CARLA_SAFE_ASSERT_CONTINUE(ev->time.frames >= 0);
4466 CARLA_SAFE_ASSERT_CONTINUE(ev->body.size < 0xFF);
4468 uint32_t currentFrame = static_cast<uint32_t>(ev->time.frames);
4469 if (currentFrame < lastFrame)
4470 currentFrame = lastFrame;
4471 else if (currentFrame >= frames)
4472 currentFrame = frames - 1;
4474 evData.port->writeMidiEvent(currentFrame, static_cast<uint8_t>(ev->body.size), data);
4477 else if (fAtomBufferUiOutTmpData != nullptr)
4479 fAtomBufferUiOut.put(&ev->body, evData.rindex);
4482 lv2_atom_buffer_increment(&iter);
4485 else if ((evData.type & CARLA_EVENT_DATA_EVENT) != 0 && evData.port != nullptr)
4487 const LV2_Event* ev;
4488 LV2_Event_Iterator iter;
4490 uint8_t* data;
4491 lv2_event_begin(&iter, evData.event);
4493 for (;;)
4495 data = nullptr;
4496 ev = lv2_event_get(&iter, &data);
4498 if (ev == nullptr || data == nullptr)
4499 break;
4501 uint32_t currentFrame = ev->frames;
4502 if (currentFrame < lastFrame)
4503 currentFrame = lastFrame;
4504 else if (currentFrame >= frames)
4505 currentFrame = frames - 1;
4507 if (ev->type == kUridMidiEvent)
4509 CARLA_SAFE_ASSERT_CONTINUE(ev->size < 0xFF);
4510 evData.port->writeMidiEvent(currentFrame, static_cast<uint8_t>(ev->size), data);
4513 lv2_event_increment(&iter);
4516 else if ((evData.type & CARLA_EVENT_DATA_MIDI_LL) != 0 && evData.port != nullptr)
4518 LV2_MIDIState state = { &evData.midi, frames, 0 };
4520 uint32_t eventSize;
4521 double eventTime;
4522 uchar* eventData;
4524 for (;;)
4526 eventSize = 0;
4527 eventTime = 0.0;
4528 eventData = nullptr;
4529 lv2midi_get_event(&state, &eventTime, &eventSize, &eventData);
4531 if (eventData == nullptr || eventSize == 0)
4532 break;
4534 CARLA_SAFE_ASSERT_CONTINUE(eventSize < 0xFF);
4535 CARLA_SAFE_ASSERT_CONTINUE(eventTime >= 0.0);
4537 evData.port->writeMidiEvent(static_cast<uint32_t>(eventTime), static_cast<uint8_t>(eventSize), eventData);
4538 lv2midi_step(&state);
4543 fFirstActive = false;
4545 // --------------------------------------------------------------------------------------------------------
4548 bool processSingle(const float* const* const audioIn, float** const audioOut,
4549 const float* const* const cvIn, float** const cvOut,
4550 const uint32_t frames, const uint32_t timeOffset)
4552 CARLA_SAFE_ASSERT_RETURN(frames > 0, false);
4554 if (pData->audioIn.count > 0)
4556 CARLA_SAFE_ASSERT_RETURN(audioIn != nullptr, false);
4557 CARLA_SAFE_ASSERT_RETURN(fAudioInBuffers != nullptr, false);
4559 if (pData->audioOut.count > 0)
4561 CARLA_SAFE_ASSERT_RETURN(audioOut != nullptr, false);
4562 CARLA_SAFE_ASSERT_RETURN(fAudioOutBuffers != nullptr, false);
4564 if (pData->cvIn.count > 0)
4566 CARLA_SAFE_ASSERT_RETURN(cvIn != nullptr, false);
4568 if (pData->cvOut.count > 0)
4570 CARLA_SAFE_ASSERT_RETURN(cvOut != nullptr, false);
4573 // --------------------------------------------------------------------------------------------------------
4574 // Try lock, silence otherwise
4576 #ifndef STOAT_TEST_BUILD
4577 if (pData->engine->isOffline())
4579 pData->singleMutex.lock();
4581 else
4582 #endif
4583 if (! pData->singleMutex.tryLock())
4585 for (uint32_t i=0; i < pData->audioOut.count; ++i)
4587 for (uint32_t k=0; k < frames; ++k)
4588 audioOut[i][k+timeOffset] = 0.0f;
4590 for (uint32_t i=0; i < pData->cvOut.count; ++i)
4592 for (uint32_t k=0; k < frames; ++k)
4593 cvOut[i][k+timeOffset] = 0.0f;
4596 return false;
4599 // --------------------------------------------------------------------------------------------------------
4600 // Set audio buffers
4602 for (uint32_t i=0; i < pData->audioIn.count; ++i)
4603 carla_copyFloats(fAudioInBuffers[i], audioIn[i]+timeOffset, frames);
4605 for (uint32_t i=0; i < pData->audioOut.count; ++i)
4606 carla_zeroFloats(fAudioOutBuffers[i], frames);
4608 // --------------------------------------------------------------------------------------------------------
4609 // Set CV buffers
4611 for (uint32_t i=0; i < pData->cvIn.count; ++i)
4612 carla_copyFloats(fCvInBuffers[i], cvIn[i]+timeOffset, frames);
4614 for (uint32_t i=0; i < pData->cvOut.count; ++i)
4615 carla_zeroFloats(fCvOutBuffers[i], frames);
4617 // --------------------------------------------------------------------------------------------------------
4618 // Run plugin
4620 fDescriptor->run(fHandle, frames);
4622 if (fHandle2 != nullptr)
4623 fDescriptor->run(fHandle2, frames);
4625 // --------------------------------------------------------------------------------------------------------
4626 // Handle trigger parameters
4628 for (uint32_t k=0; k < pData->param.count; ++k)
4630 if (pData->param.data[k].type != PARAMETER_INPUT)
4631 continue;
4633 if (pData->param.data[k].hints & PARAMETER_IS_TRIGGER)
4635 if (carla_isNotEqual(fParamBuffers[k], pData->param.ranges[k].def))
4637 fParamBuffers[k] = pData->param.ranges[k].def;
4638 pData->postponeParameterChangeRtEvent(true, static_cast<int32_t>(k), fParamBuffers[k]);
4643 pData->postRtEvents.trySplice();
4645 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
4646 // --------------------------------------------------------------------------------------------------------
4647 // Post-processing (dry/wet, volume and balance)
4650 const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && carla_isNotEqual(pData->postProc.dryWet, 1.0f);
4651 const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && ! (carla_isEqual(pData->postProc.balanceLeft, -1.0f) && carla_isEqual(pData->postProc.balanceRight, 1.0f));
4652 const bool isMono = (pData->audioIn.count == 1);
4654 bool isPair;
4655 float bufValue;
4656 float* const oldBufLeft = pData->postProc.extraBuffer;
4658 for (uint32_t i=0; i < pData->audioOut.count; ++i)
4660 // Dry/Wet
4661 if (doDryWet)
4663 const uint32_t c = isMono ? 0 : i;
4665 for (uint32_t k=0; k < frames; ++k)
4667 # ifndef BUILD_BRIDGE
4668 if (k < pData->latency.frames && pData->latency.buffers != nullptr)
4669 bufValue = pData->latency.buffers[c][k];
4670 else if (pData->latency.frames < frames)
4671 bufValue = fAudioInBuffers[c][k-pData->latency.frames];
4672 else
4673 # endif
4674 bufValue = fAudioInBuffers[c][k];
4676 fAudioOutBuffers[i][k] = (fAudioOutBuffers[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet));
4680 // Balance
4681 if (doBalance)
4683 isPair = (i % 2 == 0);
4685 if (isPair)
4687 CARLA_ASSERT(i+1 < pData->audioOut.count);
4688 carla_copyFloats(oldBufLeft, fAudioOutBuffers[i], frames);
4691 float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f;
4692 float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f;
4694 for (uint32_t k=0; k < frames; ++k)
4696 if (isPair)
4698 // left
4699 fAudioOutBuffers[i][k] = oldBufLeft[k] * (1.0f - balRangeL);
4700 fAudioOutBuffers[i][k] += fAudioOutBuffers[i+1][k] * (1.0f - balRangeR);
4702 else
4704 // right
4705 fAudioOutBuffers[i][k] = fAudioOutBuffers[i][k] * balRangeR;
4706 fAudioOutBuffers[i][k] += oldBufLeft[k] * balRangeL;
4711 // Volume (and buffer copy)
4713 for (uint32_t k=0; k < frames; ++k)
4714 audioOut[i][k+timeOffset] = fAudioOutBuffers[i][k] * pData->postProc.volume;
4717 } // End of Post-processing
4719 # ifndef BUILD_BRIDGE
4720 // --------------------------------------------------------------------------------------------------------
4721 // Save latency values for next callback
4723 if (pData->latency.frames != 0 && pData->latency.buffers != nullptr)
4725 CARLA_SAFE_ASSERT(timeOffset == 0);
4726 const uint32_t latframes = pData->latency.frames;
4728 if (latframes <= frames)
4730 for (uint32_t i=0; i < pData->audioIn.count; ++i)
4731 carla_copyFloats(pData->latency.buffers[i], audioIn[i]+(frames-latframes), latframes);
4733 else
4735 const uint32_t diff = latframes - frames;
4737 for (uint32_t i=0, k; i<pData->audioIn.count; ++i)
4739 // push back buffer by 'frames'
4740 for (k=0; k < diff; ++k)
4741 pData->latency.buffers[i][k] = pData->latency.buffers[i][k+frames];
4743 // put current input at the end
4744 for (uint32_t j=0; k < latframes; ++j, ++k)
4745 pData->latency.buffers[i][k] = audioIn[i][j];
4749 # endif
4750 #else // BUILD_BRIDGE_ALTERNATIVE_ARCH
4751 for (uint32_t i=0; i < pData->audioOut.count; ++i)
4753 for (uint32_t k=0; k < frames; ++k)
4754 audioOut[i][k+timeOffset] = fAudioOutBuffers[i][k];
4756 #endif
4758 for (uint32_t i=0; i < pData->cvOut.count; ++i)
4760 for (uint32_t k=0; k < frames; ++k)
4761 cvOut[i][k+timeOffset] = fCvOutBuffers[i][k];
4764 // --------------------------------------------------------------------------------------------------------
4766 pData->singleMutex.unlock();
4767 return true;
4770 void bufferSizeChanged(const uint32_t newBufferSize) override
4772 CARLA_ASSERT_INT(newBufferSize > 0, newBufferSize);
4773 carla_debug("CarlaPluginLV2::bufferSizeChanged(%i) - start", newBufferSize);
4775 for (uint32_t i=0; i < pData->audioIn.count; ++i)
4777 if (fAudioInBuffers[i] != nullptr)
4778 delete[] fAudioInBuffers[i];
4779 fAudioInBuffers[i] = new float[newBufferSize];
4782 for (uint32_t i=0; i < pData->audioOut.count; ++i)
4784 if (fAudioOutBuffers[i] != nullptr)
4785 delete[] fAudioOutBuffers[i];
4786 fAudioOutBuffers[i] = new float[newBufferSize];
4789 if (fHandle2 == nullptr)
4791 for (uint32_t i=0; i < pData->audioIn.count; ++i)
4793 CARLA_ASSERT(fAudioInBuffers[i] != nullptr);
4794 fDescriptor->connect_port(fHandle, pData->audioIn.ports[i].rindex, fAudioInBuffers[i]);
4797 for (uint32_t i=0; i < pData->audioOut.count; ++i)
4799 CARLA_ASSERT(fAudioOutBuffers[i] != nullptr);
4800 fDescriptor->connect_port(fHandle, pData->audioOut.ports[i].rindex, fAudioOutBuffers[i]);
4803 else
4805 if (pData->audioIn.count > 0)
4807 CARLA_ASSERT(pData->audioIn.count == 2);
4808 CARLA_ASSERT(fAudioInBuffers[0] != nullptr);
4809 CARLA_ASSERT(fAudioInBuffers[1] != nullptr);
4811 fDescriptor->connect_port(fHandle, pData->audioIn.ports[0].rindex, fAudioInBuffers[0]);
4812 fDescriptor->connect_port(fHandle2, pData->audioIn.ports[1].rindex, fAudioInBuffers[1]);
4815 if (pData->audioOut.count > 0)
4817 CARLA_ASSERT(pData->audioOut.count == 2);
4818 CARLA_ASSERT(fAudioOutBuffers[0] != nullptr);
4819 CARLA_ASSERT(fAudioOutBuffers[1] != nullptr);
4821 fDescriptor->connect_port(fHandle, pData->audioOut.ports[0].rindex, fAudioOutBuffers[0]);
4822 fDescriptor->connect_port(fHandle2, pData->audioOut.ports[1].rindex, fAudioOutBuffers[1]);
4826 for (uint32_t i=0; i < pData->cvIn.count; ++i)
4828 if (fCvInBuffers[i] != nullptr)
4829 delete[] fCvInBuffers[i];
4830 fCvInBuffers[i] = new float[newBufferSize];
4832 fDescriptor->connect_port(fHandle, pData->cvIn.ports[i].rindex, fCvInBuffers[i]);
4834 if (fHandle2 != nullptr)
4835 fDescriptor->connect_port(fHandle2, pData->cvIn.ports[i].rindex, fCvInBuffers[i]);
4838 for (uint32_t i=0; i < pData->cvOut.count; ++i)
4840 if (fCvOutBuffers[i] != nullptr)
4841 delete[] fCvOutBuffers[i];
4842 fCvOutBuffers[i] = new float[newBufferSize];
4844 fDescriptor->connect_port(fHandle, pData->cvOut.ports[i].rindex, fCvOutBuffers[i]);
4846 if (fHandle2 != nullptr)
4847 fDescriptor->connect_port(fHandle2, pData->cvOut.ports[i].rindex, fCvOutBuffers[i]);
4850 const int newBufferSizeInt(static_cast<int>(newBufferSize));
4852 if (fLv2Options.maxBufferSize != newBufferSizeInt || (fLv2Options.minBufferSize != 1 && fLv2Options.minBufferSize != newBufferSizeInt))
4854 fLv2Options.maxBufferSize = fLv2Options.nominalBufferSize = newBufferSizeInt;
4856 if (fLv2Options.minBufferSize != 1)
4857 fLv2Options.minBufferSize = newBufferSizeInt;
4859 if (fExt.options != nullptr && fExt.options->set != nullptr)
4861 LV2_Options_Option options[4];
4862 carla_zeroStructs(options, 4);
4864 carla_copyStruct(options[0], fLv2Options.opts[CarlaPluginLV2Options::MaxBlockLenth]);
4865 carla_copyStruct(options[1], fLv2Options.opts[CarlaPluginLV2Options::NominalBlockLenth]);
4867 if (fLv2Options.minBufferSize != 1)
4868 carla_copyStruct(options[2], fLv2Options.opts[CarlaPluginLV2Options::MinBlockLenth]);
4870 fExt.options->set(fHandle, options);
4874 carla_debug("CarlaPluginLV2::bufferSizeChanged(%i) - end", newBufferSize);
4876 CarlaPlugin::bufferSizeChanged(newBufferSize);
4879 void sampleRateChanged(const double newSampleRate) override
4881 CARLA_ASSERT_INT(newSampleRate > 0.0, newSampleRate);
4882 carla_debug("CarlaPluginLV2::sampleRateChanged(%g) - start", newSampleRate);
4884 const float sampleRatef = static_cast<float>(newSampleRate);
4886 if (carla_isNotEqual(fLv2Options.sampleRate, sampleRatef))
4888 fLv2Options.sampleRate = sampleRatef;
4890 if (fExt.options != nullptr && fExt.options->set != nullptr)
4892 LV2_Options_Option options[2];
4893 carla_copyStruct(options[0], fLv2Options.opts[CarlaPluginLV2Options::SampleRate]);
4894 carla_zeroStruct(options[1]);
4896 fExt.options->set(fHandle, options);
4900 for (uint32_t k=0; k < pData->param.count; ++k)
4902 if (pData->param.data[k].type != PARAMETER_INPUT)
4903 continue;
4904 if (pData->param.special[k] != PARAMETER_SPECIAL_SAMPLE_RATE)
4905 continue;
4907 fParamBuffers[k] = sampleRatef;
4908 pData->postponeParameterChangeRtEvent(true, static_cast<int32_t>(k), fParamBuffers[k]);
4909 break;
4912 carla_debug("CarlaPluginLV2::sampleRateChanged(%g) - end", newSampleRate);
4915 void offlineModeChanged(const bool isOffline) override
4917 for (uint32_t k=0; k < pData->param.count; ++k)
4919 if (pData->param.data[k].type == PARAMETER_INPUT && pData->param.special[k] == PARAMETER_SPECIAL_FREEWHEEL)
4921 fParamBuffers[k] = isOffline ? pData->param.ranges[k].max : pData->param.ranges[k].min;
4922 pData->postponeParameterChangeRtEvent(true, static_cast<int32_t>(k), fParamBuffers[k]);
4923 break;
4928 // -------------------------------------------------------------------
4929 // Plugin buffers
4931 void initBuffers() const noexcept override
4933 fEventsIn.initBuffers();
4934 fEventsOut.initBuffers();
4936 CarlaPlugin::initBuffers();
4939 void clearBuffers() noexcept override
4941 carla_debug("CarlaPluginLV2::clearBuffers() - start");
4943 if (fAudioInBuffers != nullptr)
4945 for (uint32_t i=0; i < pData->audioIn.count; ++i)
4947 if (fAudioInBuffers[i] != nullptr)
4949 delete[] fAudioInBuffers[i];
4950 fAudioInBuffers[i] = nullptr;
4954 delete[] fAudioInBuffers;
4955 fAudioInBuffers = nullptr;
4958 if (fAudioOutBuffers != nullptr)
4960 for (uint32_t i=0; i < pData->audioOut.count; ++i)
4962 if (fAudioOutBuffers[i] != nullptr)
4964 delete[] fAudioOutBuffers[i];
4965 fAudioOutBuffers[i] = nullptr;
4969 delete[] fAudioOutBuffers;
4970 fAudioOutBuffers = nullptr;
4973 if (fCvInBuffers != nullptr)
4975 for (uint32_t i=0; i < pData->cvIn.count; ++i)
4977 if (fCvInBuffers[i] != nullptr)
4979 delete[] fCvInBuffers[i];
4980 fCvInBuffers[i] = nullptr;
4984 delete[] fCvInBuffers;
4985 fCvInBuffers = nullptr;
4988 if (fCvOutBuffers != nullptr)
4990 for (uint32_t i=0; i < pData->cvOut.count; ++i)
4992 if (fCvOutBuffers[i] != nullptr)
4994 delete[] fCvOutBuffers[i];
4995 fCvOutBuffers[i] = nullptr;
4999 delete[] fCvOutBuffers;
5000 fCvOutBuffers = nullptr;
5003 if (fParamBuffers != nullptr)
5005 delete[] fParamBuffers;
5006 fParamBuffers = nullptr;
5009 fEventsIn.clear(pData->event.portIn);
5010 fEventsOut.clear(pData->event.portOut);
5012 CarlaPlugin::clearBuffers();
5014 carla_debug("CarlaPluginLV2::clearBuffers() - end");
5017 // -------------------------------------------------------------------
5018 // Post-poned UI Stuff
5020 void uiParameterChange(const uint32_t index, const float value) noexcept override
5022 CARLA_SAFE_ASSERT_RETURN(fUI.type != UI::TYPE_NULL || fFilePathURI.isNotEmpty(),);
5023 CARLA_SAFE_ASSERT_RETURN(index < pData->param.count,);
5024 CARLA_SAFE_ASSERT_RETURN(pData->param.data[index].rindex >= 0,);
5026 #ifndef LV2_UIS_ONLY_INPROCESS
5027 if (fUI.type == UI::TYPE_BRIDGE)
5029 if (! fPipeServer.isPipeRunning())
5030 return;
5032 else
5033 #endif
5035 if (fUI.handle == nullptr)
5036 return;
5037 if (fUI.descriptor == nullptr || fUI.descriptor->port_event == nullptr)
5038 return;
5039 if (fNeedsUiClose)
5040 return;
5043 ParameterData& pdata(pData->param.data[index]);
5045 if (pdata.hints & PARAMETER_IS_NOT_SAVED)
5047 int32_t rindex = pdata.rindex;
5048 CARLA_SAFE_ASSERT_RETURN(rindex - static_cast<int32_t>(fRdfDescriptor->PortCount) >= 0,);
5050 rindex -= static_cast<int32_t>(fRdfDescriptor->PortCount);
5051 CARLA_SAFE_ASSERT_RETURN(rindex < static_cast<int32_t>(fRdfDescriptor->ParameterCount),);
5053 const char* const uri = fRdfDescriptor->Parameters[rindex].URI;
5055 #ifndef LV2_UIS_ONLY_INPROCESS
5056 if (fUI.type == UI::TYPE_BRIDGE)
5058 fPipeServer.writeLv2ParameterMessage(uri, value);
5060 else
5061 #endif
5062 if (fEventsIn.ctrl != nullptr)
5064 uint8_t atomBuf[256];
5065 LV2_Atom_Forge atomForge;
5066 initAtomForge(atomForge);
5067 lv2_atom_forge_set_buffer(&atomForge, atomBuf, sizeof(atomBuf));
5069 LV2_Atom_Forge_Frame forgeFrame;
5070 lv2_atom_forge_object(&atomForge, &forgeFrame, kUridNull, kUridPatchSet);
5072 lv2_atom_forge_key(&atomForge, kUridCarlaParameterChange);
5073 lv2_atom_forge_bool(&atomForge, true);
5075 lv2_atom_forge_key(&atomForge, kUridPatchProperty);
5076 lv2_atom_forge_urid(&atomForge, getCustomURID(uri));
5078 lv2_atom_forge_key(&atomForge, kUridPatchValue);
5080 switch (fRdfDescriptor->Parameters[rindex].Type)
5082 case LV2_PARAMETER_TYPE_BOOL:
5083 lv2_atom_forge_bool(&atomForge, value > 0.5f);
5084 break;
5085 case LV2_PARAMETER_TYPE_INT:
5086 lv2_atom_forge_int(&atomForge, static_cast<int32_t>(value + 0.5f));
5087 break;
5088 case LV2_PARAMETER_TYPE_LONG:
5089 lv2_atom_forge_long(&atomForge, static_cast<int64_t>(value + 0.5f));
5090 break;
5091 case LV2_PARAMETER_TYPE_FLOAT:
5092 lv2_atom_forge_float(&atomForge, value);
5093 break;
5094 case LV2_PARAMETER_TYPE_DOUBLE:
5095 lv2_atom_forge_double(&atomForge, value);
5096 break;
5097 default:
5098 carla_stderr2("uiParameterChange called for invalid parameter, abort!");
5099 return;
5102 lv2_atom_forge_pop(&atomForge, &forgeFrame);
5104 LV2_Atom* const atom((LV2_Atom*)atomBuf);
5105 CARLA_SAFE_ASSERT(atom->size < sizeof(atomBuf));
5107 fUI.descriptor->port_event(fUI.handle,
5108 fEventsIn.ctrl->rindex,
5109 lv2_atom_total_size(atom),
5110 kUridAtomTransferEvent,
5111 atom);
5114 else
5116 #ifndef LV2_UIS_ONLY_INPROCESS
5117 if (fUI.type == UI::TYPE_BRIDGE)
5119 fPipeServer.writeControlMessage(static_cast<uint32_t>(pData->param.data[index].rindex), value);
5121 else
5122 #endif
5124 fUI.descriptor->port_event(fUI.handle,
5125 static_cast<uint32_t>(pData->param.data[index].rindex),
5126 sizeof(float), kUridNull, &value);
5131 void uiMidiProgramChange(const uint32_t index) noexcept override
5133 CARLA_SAFE_ASSERT_RETURN(fUI.type != UI::TYPE_NULL || fFilePathURI.isNotEmpty(),);
5134 CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,);
5136 #ifndef LV2_UIS_ONLY_INPROCESS
5137 if (fUI.type == UI::TYPE_BRIDGE)
5139 if (fPipeServer.isPipeRunning())
5140 fPipeServer.writeMidiProgramMessage(pData->midiprog.data[index].bank, pData->midiprog.data[index].program);
5142 else
5143 #endif
5145 if (fExt.uiprograms != nullptr && fExt.uiprograms->select_program != nullptr && ! fNeedsUiClose)
5146 fExt.uiprograms->select_program(fUI.handle, pData->midiprog.data[index].bank, pData->midiprog.data[index].program);
5150 void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) noexcept override
5152 CARLA_SAFE_ASSERT_RETURN(fUI.type != UI::TYPE_NULL || fFilePathURI.isNotEmpty(),);
5153 CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
5154 CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
5155 CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,);
5157 #if 0
5158 if (fUI.type == UI::TYPE_BRIDGE)
5160 if (fPipeServer.isPipeRunning())
5161 fPipeServer.writeMidiNoteMessage(false, channel, note, velo);
5163 else
5165 if (fUI.handle != nullptr && fUI.descriptor != nullptr && fUI.descriptor->port_event != nullptr && fEventsIn.ctrl != nullptr && ! fNeedsUiClose)
5167 LV2_Atom_MidiEvent midiEv;
5168 midiEv.atom.type = kUridMidiEvent;
5169 midiEv.atom.size = 3;
5170 midiEv.data[0] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT));
5171 midiEv.data[1] = note;
5172 midiEv.data[2] = velo;
5174 fUI.descriptor->port_event(fUI.handle, fEventsIn.ctrl->rindex, lv2_atom_total_size(midiEv), kUridAtomTransferEvent, &midiEv);
5177 #endif
5180 void uiNoteOff(const uint8_t channel, const uint8_t note) noexcept override
5182 CARLA_SAFE_ASSERT_RETURN(fUI.type != UI::TYPE_NULL || fFilePathURI.isNotEmpty(),);
5183 CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
5184 CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
5186 #if 0
5187 if (fUI.type == UI::TYPE_BRIDGE)
5189 if (fPipeServer.isPipeRunning())
5190 fPipeServer.writeMidiNoteMessage(false, channel, note, 0);
5192 else
5194 if (fUI.handle != nullptr && fUI.descriptor != nullptr && fUI.descriptor->port_event != nullptr && fEventsIn.ctrl != nullptr && ! fNeedsUiClose)
5196 LV2_Atom_MidiEvent midiEv;
5197 midiEv.atom.type = kUridMidiEvent;
5198 midiEv.atom.size = 3;
5199 midiEv.data[0] = uint8_t(MIDI_STATUS_NOTE_OFF | (channel & MIDI_CHANNEL_BIT));
5200 midiEv.data[1] = note;
5201 midiEv.data[2] = 0;
5203 fUI.descriptor->port_event(fUI.handle, fEventsIn.ctrl->rindex, lv2_atom_total_size(midiEv), kUridAtomTransferEvent, &midiEv);
5206 #endif
5209 // -------------------------------------------------------------------
5210 // Internal helper functions
5212 void cloneLV2Files(const CarlaPlugin& other) override
5214 CARLA_SAFE_ASSERT_RETURN(other.getType() == PLUGIN_LV2,);
5216 const CarlaPluginLV2& otherLV2((const CarlaPluginLV2&)other);
5218 const File tmpDir(handleStateMapToAbsolutePath(false, false, true, "."));
5220 if (tmpDir.exists())
5221 tmpDir.deleteRecursively();
5223 const File otherStateDir(otherLV2.handleStateMapToAbsolutePath(false, false, false, "."));
5225 if (otherStateDir.exists())
5226 otherStateDir.copyDirectoryTo(tmpDir);
5228 const File otherTmpDir(otherLV2.handleStateMapToAbsolutePath(false, false, true, "."));
5230 if (otherTmpDir.exists())
5231 otherTmpDir.copyDirectoryTo(tmpDir);
5234 void restoreLV2State(const bool temporary) noexcept override
5236 if (fExt.state == nullptr || fExt.state->restore == nullptr)
5237 return;
5239 if (! temporary)
5241 const File tmpDir(handleStateMapToAbsolutePath(false, false, true, "."));
5243 if (tmpDir.exists())
5244 tmpDir.deleteRecursively();
5247 LV2_State_Status status = LV2_STATE_ERR_UNKNOWN;
5250 const ScopedSingleProcessLocker spl(this, !fHasThreadSafeRestore);
5252 try {
5253 status = fExt.state->restore(fHandle,
5254 carla_lv2_state_retrieve,
5255 this,
5256 LV2_STATE_IS_POD,
5257 temporary ? fFeatures : fStateFeatures);
5258 } catch(...) {}
5260 if (fHandle2 != nullptr)
5262 try {
5263 fExt.state->restore(fHandle,
5264 carla_lv2_state_retrieve,
5265 this,
5266 LV2_STATE_IS_POD,
5267 temporary ? fFeatures : fStateFeatures);
5268 } catch(...) {}
5272 switch (status)
5274 case LV2_STATE_SUCCESS:
5275 carla_debug("CarlaPluginLV2::updateLV2State() - success");
5276 break;
5277 case LV2_STATE_ERR_UNKNOWN:
5278 carla_stderr("CarlaPluginLV2::updateLV2State() - unknown error");
5279 break;
5280 case LV2_STATE_ERR_BAD_TYPE:
5281 carla_stderr("CarlaPluginLV2::updateLV2State() - error, bad type");
5282 break;
5283 case LV2_STATE_ERR_BAD_FLAGS:
5284 carla_stderr("CarlaPluginLV2::updateLV2State() - error, bad flags");
5285 break;
5286 case LV2_STATE_ERR_NO_FEATURE:
5287 carla_stderr("CarlaPluginLV2::updateLV2State() - error, missing feature");
5288 break;
5289 case LV2_STATE_ERR_NO_PROPERTY:
5290 carla_stderr("CarlaPluginLV2::updateLV2State() - error, missing property");
5291 break;
5292 case LV2_STATE_ERR_NO_SPACE:
5293 carla_stderr("CarlaPluginLV2::updateLV2State() - error, insufficient space");
5294 break;
5298 // -------------------------------------------------------------------
5300 bool isRealtimeSafe() const noexcept
5302 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
5304 for (uint32_t i=0; i < fRdfDescriptor->FeatureCount; ++i)
5306 if (std::strcmp(fRdfDescriptor->Features[i].URI, LV2_CORE__hardRTCapable) == 0)
5307 return true;
5310 return false;
5313 // -------------------------------------------------------------------
5315 bool isUiBridgeable(const uint32_t uiId) const noexcept
5317 CARLA_SAFE_ASSERT_RETURN(uiId < fRdfDescriptor->UICount, false);
5319 #ifndef LV2_UIS_ONLY_INPROCESS
5320 const LV2_RDF_UI* const rdfUI(&fRdfDescriptor->UIs[uiId]);
5322 for (uint32_t i=0; i < rdfUI->FeatureCount; ++i)
5324 const LV2_RDF_Feature& feat(rdfUI->Features[i]);
5326 if (! feat.Required)
5327 continue;
5328 if (std::strcmp(feat.URI, LV2_INSTANCE_ACCESS_URI) == 0)
5329 return false;
5330 if (std::strcmp(feat.URI, LV2_DATA_ACCESS_URI) == 0)
5331 return false;
5334 // Calf UIs are mostly useless without their special graphs
5335 // but they can be crashy under certain conditions, so follow user preferences
5336 if (std::strstr(rdfUI->URI, "http://calf.sourceforge.net/plugins/gui/") != nullptr)
5337 return pData->engine->getOptions().preferUiBridges;
5339 // LSP-Plugins UIs make heavy use of URIDs, for which carla right now is very slow
5340 // FIXME after some optimization, remove this
5341 if (std::strstr(rdfUI->URI, "http://lsp-plug.in/ui/lv2/") != nullptr)
5342 return false;
5344 return true;
5345 #else
5346 return false;
5347 #endif
5350 bool isUiResizable() const noexcept
5352 CARLA_SAFE_ASSERT_RETURN(fUI.rdfDescriptor != nullptr, false);
5354 for (uint32_t i=0; i < fUI.rdfDescriptor->FeatureCount; ++i)
5356 if (std::strcmp(fUI.rdfDescriptor->Features[i].URI, LV2_UI__fixedSize) == 0)
5357 return false;
5358 if (std::strcmp(fUI.rdfDescriptor->Features[i].URI, LV2_UI__noUserResize) == 0)
5359 return false;
5362 return true;
5365 const char* getUiBridgeBinary(const LV2_Property type) const
5367 CarlaString bridgeBinary(pData->engine->getOptions().binaryDir);
5369 if (bridgeBinary.isEmpty())
5370 return nullptr;
5372 switch (type)
5374 case LV2_UI_GTK2:
5375 bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-gtk2";
5376 break;
5377 case LV2_UI_GTK3:
5378 bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-gtk3";
5379 break;
5380 case LV2_UI_QT4:
5381 bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-qt4";
5382 break;
5383 case LV2_UI_QT5:
5384 bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-qt5";
5385 break;
5386 case LV2_UI_COCOA:
5387 bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-cocoa";
5388 break;
5389 case LV2_UI_WINDOWS:
5390 bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-windows";
5391 break;
5392 case LV2_UI_X11:
5393 bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-x11";
5394 break;
5395 case LV2_UI_MOD:
5396 bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-modgui";
5397 break;
5398 #if 0
5399 case LV2_UI_EXTERNAL:
5400 case LV2_UI_OLD_EXTERNAL:
5401 bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-external";
5402 break;
5403 #endif
5404 default:
5405 return nullptr;
5408 #ifdef CARLA_OS_WIN
5409 bridgeBinary += ".exe";
5410 #endif
5412 if (! File(bridgeBinary.buffer()).existsAsFile())
5413 return nullptr;
5415 return bridgeBinary.dupSafe();
5418 // -------------------------------------------------------------------
5420 void recheckExtensions()
5422 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr,);
5423 carla_debug("CarlaPluginLV2::recheckExtensions()");
5425 fExt.options = nullptr;
5426 fExt.programs = nullptr;
5427 fExt.state = nullptr;
5428 fExt.worker = nullptr;
5429 fExt.inlineDisplay = nullptr;
5431 for (uint32_t i=0; i < fRdfDescriptor->ExtensionCount; ++i)
5433 const char* const extension = fRdfDescriptor->Extensions[i];
5434 CARLA_SAFE_ASSERT_CONTINUE(extension != nullptr);
5436 /**/ if (std::strcmp(extension, LV2_OPTIONS__interface) == 0)
5437 pData->hints |= PLUGIN_HAS_EXTENSION_OPTIONS;
5438 else if (std::strcmp(extension, LV2_PROGRAMS__Interface) == 0)
5439 pData->hints |= PLUGIN_HAS_EXTENSION_PROGRAMS;
5440 else if (std::strcmp(extension, LV2_STATE__interface) == 0)
5441 pData->hints |= PLUGIN_HAS_EXTENSION_STATE;
5442 else if (std::strcmp(extension, LV2_WORKER__interface) == 0)
5443 pData->hints |= PLUGIN_HAS_EXTENSION_WORKER;
5444 else if (std::strcmp(extension, LV2_INLINEDISPLAY__interface) == 0)
5445 pData->hints |= PLUGIN_HAS_EXTENSION_INLINE_DISPLAY;
5446 else if (std::strcmp(extension, LV2_MIDNAM__interface) == 0)
5447 pData->hints |= PLUGIN_HAS_EXTENSION_MIDNAM;
5448 else
5449 carla_stdout("Plugin '%s' has non-supported extension: '%s'", fRdfDescriptor->URI, extension);
5452 // Fix for broken plugins, nasty!
5453 for (uint32_t i=0; i < fRdfDescriptor->FeatureCount; ++i)
5455 const LV2_RDF_Feature& feature(fRdfDescriptor->Features[i]);
5457 if (std::strcmp(feature.URI, LV2_INLINEDISPLAY__queue_draw) == 0)
5459 if (pData->hints & PLUGIN_HAS_EXTENSION_INLINE_DISPLAY)
5460 break;
5462 carla_stdout("Plugin '%s' uses inline-display but does not set extension data, nasty!", fRdfDescriptor->URI);
5463 pData->hints |= PLUGIN_HAS_EXTENSION_INLINE_DISPLAY;
5465 else if (std::strcmp(feature.URI, LV2_MIDNAM__update) == 0)
5467 if (pData->hints & PLUGIN_HAS_EXTENSION_MIDNAM)
5468 break;
5470 carla_stdout("Plugin '%s' uses midnam but does not set extension data, nasty!", fRdfDescriptor->URI);
5471 pData->hints |= PLUGIN_HAS_EXTENSION_MIDNAM;
5475 if (fDescriptor->extension_data != nullptr)
5477 if (pData->hints & PLUGIN_HAS_EXTENSION_OPTIONS)
5478 fExt.options = (const LV2_Options_Interface*)fDescriptor->extension_data(LV2_OPTIONS__interface);
5480 if (pData->hints & PLUGIN_HAS_EXTENSION_PROGRAMS)
5481 fExt.programs = (const LV2_Programs_Interface*)fDescriptor->extension_data(LV2_PROGRAMS__Interface);
5483 if (pData->hints & PLUGIN_HAS_EXTENSION_STATE)
5484 fExt.state = (const LV2_State_Interface*)fDescriptor->extension_data(LV2_STATE__interface);
5486 if (pData->hints & PLUGIN_HAS_EXTENSION_WORKER)
5487 fExt.worker = (const LV2_Worker_Interface*)fDescriptor->extension_data(LV2_WORKER__interface);
5489 if (pData->hints & PLUGIN_HAS_EXTENSION_INLINE_DISPLAY)
5490 fExt.inlineDisplay = (const LV2_Inline_Display_Interface*)fDescriptor->extension_data(LV2_INLINEDISPLAY__interface);
5492 if (pData->hints & PLUGIN_HAS_EXTENSION_MIDNAM)
5493 fExt.midnam = (const LV2_Midnam_Interface*)fDescriptor->extension_data(LV2_MIDNAM__interface);
5495 // check if invalid
5496 if (fExt.options != nullptr && fExt.options->get == nullptr && fExt.options->set == nullptr)
5497 fExt.options = nullptr;
5499 if (fExt.programs != nullptr && (fExt.programs->get_program == nullptr || fExt.programs->select_program == nullptr))
5500 fExt.programs = nullptr;
5502 if (fExt.state != nullptr && (fExt.state->save == nullptr || fExt.state->restore == nullptr))
5503 fExt.state = nullptr;
5505 if (fExt.worker != nullptr && fExt.worker->work == nullptr)
5506 fExt.worker = nullptr;
5508 if (fExt.inlineDisplay != nullptr)
5510 if (fExt.inlineDisplay->render != nullptr)
5512 pData->hints |= PLUGIN_HAS_INLINE_DISPLAY;
5513 pData->setCanDeleteLib(false);
5515 else
5517 fExt.inlineDisplay = nullptr;
5521 if (fExt.midnam != nullptr && fExt.midnam->midnam == nullptr)
5522 fExt.midnam = nullptr;
5525 CARLA_SAFE_ASSERT_RETURN(fLatencyIndex == -1,);
5527 int32_t iCtrl=0;
5528 for (uint32_t i=0, count=fRdfDescriptor->PortCount; i<count; ++i)
5530 const LV2_Property portTypes(fRdfDescriptor->Ports[i].Types);
5532 if (! LV2_IS_PORT_CONTROL(portTypes))
5533 continue;
5535 const CarlaScopedValueSetter<int32_t> svs(iCtrl, iCtrl, iCtrl+1);
5537 if (! LV2_IS_PORT_OUTPUT(portTypes))
5538 continue;
5540 const LV2_Property portDesignation(fRdfDescriptor->Ports[i].Designation);
5542 if (! LV2_IS_PORT_DESIGNATION_LATENCY(portDesignation))
5543 continue;
5545 fLatencyIndex = iCtrl;
5546 break;
5550 // -------------------------------------------------------------------
5552 void updateUi()
5554 CARLA_SAFE_ASSERT_RETURN(fUI.handle != nullptr,);
5555 CARLA_SAFE_ASSERT_RETURN(fUI.descriptor != nullptr,);
5556 carla_debug("CarlaPluginLV2::updateUi()");
5558 // update midi program
5559 if (fExt.uiprograms != nullptr && pData->midiprog.count > 0 && pData->midiprog.current >= 0)
5561 const MidiProgramData& curData(pData->midiprog.getCurrent());
5562 fExt.uiprograms->select_program(fUI.handle, curData.bank, curData.program);
5565 // update control ports
5566 if (fUI.descriptor->port_event != nullptr)
5568 float value;
5569 for (uint32_t i=0; i < pData->param.count; ++i)
5571 value = getParameterValue(i);
5572 fUI.descriptor->port_event(fUI.handle, static_cast<uint32_t>(pData->param.data[i].rindex), sizeof(float), kUridNull, &value);
5577 void inspectAtomForParameterChange(const LV2_Atom* const atom)
5579 if (atom->type != kUridAtomBlank && atom->type != kUridAtomObject)
5580 return;
5582 const LV2_Atom_Object_Body* const objbody = (const LV2_Atom_Object_Body*)(atom + 1);
5584 if (objbody->otype != kUridPatchSet)
5585 return;
5587 const LV2_Atom_URID *property = NULL;
5588 const LV2_Atom_Bool *carlaParam = NULL;
5589 const LV2_Atom *value = NULL;
5591 lv2_atom_object_body_get(atom->size, objbody,
5592 kUridCarlaParameterChange, (const LV2_Atom**)&carlaParam,
5593 kUridPatchProperty, (const LV2_Atom**)&property,
5594 kUridPatchValue, &value,
5597 if (carlaParam != nullptr && carlaParam->body != 0)
5598 return;
5600 if (property == nullptr || value == nullptr)
5601 return;
5603 switch (value->type)
5605 case kUridAtomBool:
5606 case kUridAtomInt:
5607 //case kUridAtomLong:
5608 case kUridAtomFloat:
5609 case kUridAtomDouble:
5610 break;
5611 default:
5612 return;
5615 uint32_t parameterId;
5616 if (! getParameterIndexForURID(property->body, parameterId))
5617 return;
5619 const uint8_t* const vbody = (const uint8_t*)(value + 1);
5620 float rvalue;
5622 switch (value->type)
5624 case kUridAtomBool:
5625 rvalue = *(const int32_t*)vbody != 0 ? 1.0f : 0.0f;
5626 break;
5627 case kUridAtomInt:
5628 rvalue = static_cast<float>(*(const int32_t*)vbody);
5629 break;
5631 case kUridAtomLong:
5632 rvalue = *(int64_t*)vbody;
5633 break;
5635 case kUridAtomFloat:
5636 rvalue = *(const float*)vbody;
5637 break;
5638 case kUridAtomDouble:
5639 rvalue = static_cast<float>(*(const double*)vbody);
5640 break;
5641 default:
5642 rvalue = 0.0f;
5643 break;
5646 rvalue = pData->param.getFixedValue(parameterId, rvalue);
5647 fParamBuffers[parameterId] = rvalue;
5649 CarlaPlugin::setParameterValue(parameterId, rvalue, false, true, true);
5652 bool getParameterIndexForURI(const char* const uri, uint32_t& parameterId) noexcept
5654 parameterId = UINT32_MAX;
5656 for (uint32_t i=0; i < fRdfDescriptor->ParameterCount; ++i)
5658 const LV2_RDF_Parameter& rdfParam(fRdfDescriptor->Parameters[i]);
5660 switch (rdfParam.Type)
5662 case LV2_PARAMETER_TYPE_BOOL:
5663 case LV2_PARAMETER_TYPE_INT:
5664 // case LV2_PARAMETER_TYPE_LONG:
5665 case LV2_PARAMETER_TYPE_FLOAT:
5666 case LV2_PARAMETER_TYPE_DOUBLE:
5667 break;
5668 default:
5669 continue;
5672 if (std::strcmp(rdfParam.URI, uri) == 0)
5674 const int32_t rindex = static_cast<int32_t>(fRdfDescriptor->PortCount + i);
5676 for (uint32_t j=0; j < pData->param.count; ++j)
5678 if (pData->param.data[j].rindex == rindex)
5680 parameterId = j;
5681 break;
5684 break;
5688 return (parameterId != UINT32_MAX);
5691 bool getParameterIndexForURID(const LV2_URID urid, uint32_t& parameterId) noexcept
5693 parameterId = UINT32_MAX;
5695 if (urid >= fCustomURIDs.size())
5696 return false;
5698 for (uint32_t i=0; i < fRdfDescriptor->ParameterCount; ++i)
5700 const LV2_RDF_Parameter& rdfParam(fRdfDescriptor->Parameters[i]);
5702 switch (rdfParam.Type)
5704 case LV2_PARAMETER_TYPE_BOOL:
5705 case LV2_PARAMETER_TYPE_INT:
5706 // case LV2_PARAMETER_TYPE_LONG:
5707 case LV2_PARAMETER_TYPE_FLOAT:
5708 case LV2_PARAMETER_TYPE_DOUBLE:
5709 break;
5710 default:
5711 continue;
5714 const std::string& uri(fCustomURIDs[urid]);
5716 if (uri != rdfParam.URI)
5717 continue;
5719 const int32_t rindex = static_cast<int32_t>(fRdfDescriptor->PortCount + i);
5721 for (uint32_t j=0; j < pData->param.count; ++j)
5723 if (pData->param.data[j].rindex == rindex)
5725 parameterId = j;
5726 break;
5729 break;
5732 return (parameterId != UINT32_MAX);
5735 // -------------------------------------------------------------------
5737 LV2_URID getCustomURID(const char* const uri)
5739 CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', kUridNull);
5740 carla_debug("CarlaPluginLV2::getCustomURID(\"%s\")", uri);
5742 const std::string s_uri(uri);
5743 const std::ptrdiff_t s_pos(std::find(fCustomURIDs.begin(), fCustomURIDs.end(), s_uri) - fCustomURIDs.begin());
5745 if (s_pos <= 0 || s_pos >= INT32_MAX)
5746 return kUridNull;
5748 const LV2_URID urid = static_cast<LV2_URID>(s_pos);
5749 const LV2_URID uriCount = static_cast<LV2_URID>(fCustomURIDs.size());
5751 if (urid < uriCount)
5752 return urid;
5754 CARLA_SAFE_ASSERT(urid == uriCount);
5756 fCustomURIDs.push_back(uri);
5758 #ifndef LV2_UIS_ONLY_INPROCESS
5759 if (fUI.type == UI::TYPE_BRIDGE && fPipeServer.isPipeRunning())
5760 fPipeServer.writeLv2UridMessage(urid, uri);
5761 #endif
5763 return urid;
5766 const char* getCustomURIDString(const LV2_URID urid) const noexcept
5768 CARLA_SAFE_ASSERT_RETURN(urid != kUridNull, kUnmapFallback);
5769 CARLA_SAFE_ASSERT_RETURN(urid < fCustomURIDs.size(), kUnmapFallback);
5770 carla_debug("CarlaPluginLV2::getCustomURIString(%i)", urid);
5772 return fCustomURIDs[urid].c_str();
5775 // -------------------------------------------------------------------
5777 void handleProgramChanged(const int32_t index)
5779 CARLA_SAFE_ASSERT_RETURN(index >= -1,);
5780 carla_debug("CarlaPluginLV2::handleProgramChanged(%i)", index);
5782 if (index == -1)
5784 const ScopedSingleProcessLocker spl(this, true);
5785 return reloadPrograms(false);
5788 if (index < static_cast<int32_t>(pData->midiprog.count) && fExt.programs != nullptr && fExt.programs->get_program != nullptr)
5790 if (const LV2_Program_Descriptor* const progDesc = fExt.programs->get_program(fHandle, static_cast<uint32_t>(index)))
5792 CARLA_SAFE_ASSERT_RETURN(progDesc->name != nullptr,);
5794 if (pData->midiprog.data[index].name != nullptr)
5795 delete[] pData->midiprog.data[index].name;
5797 pData->midiprog.data[index].name = carla_strdup(progDesc->name);
5799 if (index == pData->midiprog.current)
5800 pData->engine->callback(true, true, ENGINE_CALLBACK_UPDATE, pData->id, 0, 0, 0, 0.0, nullptr);
5801 else
5802 pData->engine->callback(true, true, ENGINE_CALLBACK_RELOAD_PROGRAMS, pData->id, 0, 0, 0, 0.0, nullptr);
5807 // -------------------------------------------------------------------
5809 LV2_Resize_Port_Status handleResizePort(const uint32_t index, const size_t size)
5811 CARLA_SAFE_ASSERT_RETURN(size > 0, LV2_RESIZE_PORT_ERR_UNKNOWN);
5812 carla_debug("CarlaPluginLV2::handleResizePort(%i, " P_SIZE ")", index, size);
5814 // TODO
5815 return LV2_RESIZE_PORT_ERR_NO_SPACE;
5816 (void)index;
5819 // -------------------------------------------------------------------
5821 char* handleStateMapToAbstractPath(const bool temporary, const char* const absolutePath) const
5823 // may already be an abstract path
5824 if (! File::isAbsolutePath(absolutePath))
5825 return strdup(absolutePath);
5827 File projectDir, targetDir;
5829 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
5830 if (const char* const projFolder = pData->engine->getCurrentProjectFolder())
5831 projectDir = projFolder;
5832 else
5833 #endif
5834 projectDir = File::getCurrentWorkingDirectory();
5836 if (projectDir.isNull())
5838 carla_stdout("Project directory not set, cannot map absolutePath %s", absolutePath);
5839 return nullptr;
5842 CarlaString basedir(pData->engine->getName());
5844 if (temporary)
5845 basedir += ".tmp";
5847 targetDir = projectDir.getChildFile(basedir)
5848 .getChildFile(getName());
5850 if (! targetDir.exists())
5851 targetDir.createDirectory();
5853 const File wabsolutePath(absolutePath);
5855 // we may be saving to non-tmp path, let's check
5856 if (! temporary)
5858 const File tmpDir = projectDir.getChildFile(basedir + ".tmp")
5859 .getChildFile(getName());
5861 if (wabsolutePath.getFullPathName().startsWith(tmpDir.getFullPathName()))
5863 // gotcha, the temporary path is now the real one
5864 targetDir = tmpDir;
5866 else if (! wabsolutePath.getFullPathName().startsWith(targetDir.getFullPathName()))
5868 // seems like a normal save, let's be nice and put a symlink
5869 const water::String abstractFilename(wabsolutePath.getFileName());
5870 const File targetPath(targetDir.getChildFile(abstractFilename.toRawUTF8()));
5872 wabsolutePath.createSymbolicLink(targetPath, true);
5874 carla_stdout("Creating symlink for '%s' in '%s'", absolutePath, targetDir.getFullPathName().toRawUTF8());
5875 return strdup(abstractFilename.toRawUTF8());
5879 carla_stdout("Mapping absolutePath '%s' relative to targetDir '%s'",
5880 absolutePath, targetDir.getFullPathName().toRawUTF8());
5882 return strdup(wabsolutePath.getRelativePathFrom(targetDir).toRawUTF8());
5885 File handleStateMapToAbsolutePath(const bool createDirIfNeeded,
5886 const bool symlinkIfNeeded,
5887 const bool temporary,
5888 const char* const abstractPath) const
5890 File targetDir, targetPath;
5892 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
5893 if (const char* const projFolder = pData->engine->getCurrentProjectFolder())
5894 targetDir = projFolder;
5895 else
5896 #endif
5897 targetDir = File::getCurrentWorkingDirectory();
5899 if (targetDir.isNull())
5901 carla_stdout("Project directory not set, cannot map abstractPath '%s'", abstractPath);
5902 return File();
5905 CarlaString basedir(pData->engine->getName());
5907 if (temporary)
5908 basedir += ".tmp";
5910 targetDir = targetDir.getChildFile(basedir)
5911 .getChildFile(getName());
5913 if (createDirIfNeeded && ! targetDir.exists())
5914 targetDir.createDirectory();
5916 if (File::isAbsolutePath(abstractPath))
5918 File wabstractPath(abstractPath);
5919 targetPath = targetDir.getChildFile(wabstractPath.getFileName().toRawUTF8());
5921 if (symlinkIfNeeded)
5923 carla_stdout("Creating symlink for '%s' in '%s'",
5924 abstractPath, targetDir.getFullPathName().toRawUTF8());
5925 wabstractPath.createSymbolicLink(targetPath, true);
5928 else
5930 targetPath = targetDir.getChildFile(abstractPath);
5931 targetDir = targetPath.getParentDirectory();
5933 if (createDirIfNeeded && ! targetDir.exists())
5934 targetDir.createDirectory();
5937 if (std::strcmp(abstractPath, ".") != 0)
5938 carla_stdout("Mapping abstractPath '%s' relative to targetDir '%s'",
5939 abstractPath, targetDir.getFullPathName().toRawUTF8());
5941 return targetPath;
5944 LV2_State_Status handleStateStore(const uint32_t key, const void* const value, const size_t size, const uint32_t type, const uint32_t flags)
5946 CARLA_SAFE_ASSERT_RETURN(key != kUridNull, LV2_STATE_ERR_NO_PROPERTY);
5947 CARLA_SAFE_ASSERT_RETURN(value != nullptr, LV2_STATE_ERR_NO_PROPERTY);
5948 CARLA_SAFE_ASSERT_RETURN(size > 0, LV2_STATE_ERR_NO_PROPERTY);
5949 CARLA_SAFE_ASSERT_RETURN(type != kUridNull, LV2_STATE_ERR_BAD_TYPE);
5951 // FIXME linuxsampler does not set POD flag
5952 // CARLA_SAFE_ASSERT_RETURN(flags & LV2_STATE_IS_POD, LV2_STATE_ERR_BAD_FLAGS);
5954 carla_debug("CarlaPluginLV2::handleStateStore(%i:\"%s\", %p, " P_SIZE ", %i:\"%s\", %i)",
5955 key, carla_lv2_urid_unmap(this, key), value, size, type, carla_lv2_urid_unmap(this, type), flags);
5957 const char* const skey(carla_lv2_urid_unmap(this, key));
5958 const char* const stype(carla_lv2_urid_unmap(this, type));
5960 CARLA_SAFE_ASSERT_RETURN(skey != nullptr && skey != kUnmapFallback, LV2_STATE_ERR_BAD_TYPE);
5961 CARLA_SAFE_ASSERT_RETURN(stype != nullptr && stype != kUnmapFallback, LV2_STATE_ERR_BAD_TYPE);
5963 // Check if we already have this key
5964 for (LinkedList<CustomData>::Itenerator it = pData->custom.begin2(); it.valid(); it.next())
5966 CustomData& cData(it.getValue(kCustomDataFallbackNC));
5967 CARLA_SAFE_ASSERT_CONTINUE(cData.isValid());
5969 if (std::strcmp(cData.key, skey) == 0)
5971 // found it
5972 delete[] cData.value;
5974 if (type == kUridAtomString || type == kUridAtomPath)
5975 cData.value = carla_strdup((const char*)value);
5976 else
5977 cData.value = CarlaString::asBase64(value, size).dup();
5979 return LV2_STATE_SUCCESS;
5983 // Otherwise store it
5984 CustomData newData;
5985 newData.type = carla_strdup(stype);
5986 newData.key = carla_strdup(skey);
5988 if (type == kUridAtomString || type == kUridAtomPath)
5989 newData.value = carla_strdup((const char*)value);
5990 else
5991 newData.value = CarlaString::asBase64(value, size).dup();
5993 pData->custom.append(newData);
5995 return LV2_STATE_SUCCESS;
5997 // unused
5998 (void)flags;
6001 const void* handleStateRetrieve(const uint32_t key, size_t* const size, uint32_t* const type, uint32_t* const flags)
6003 CARLA_SAFE_ASSERT_RETURN(key != kUridNull, nullptr);
6004 CARLA_SAFE_ASSERT_RETURN(size != nullptr, nullptr);
6005 CARLA_SAFE_ASSERT_RETURN(type != nullptr, nullptr);
6006 CARLA_SAFE_ASSERT_RETURN(flags != nullptr, nullptr);
6007 carla_debug("CarlaPluginLV2::handleStateRetrieve(%i, %p, %p, %p)", key, size, type, flags);
6009 const char* const skey(carla_lv2_urid_unmap(this, key));
6010 CARLA_SAFE_ASSERT_RETURN(skey != nullptr && skey != kUnmapFallback, nullptr);
6012 const char* stype = nullptr;
6013 const char* stringData = nullptr;
6015 for (LinkedList<CustomData>::Itenerator it = pData->custom.begin2(); it.valid(); it.next())
6017 const CustomData& cData(it.getValue(kCustomDataFallback));
6018 CARLA_SAFE_ASSERT_CONTINUE(cData.isValid());
6020 if (std::strcmp(cData.key, skey) == 0)
6022 stype = cData.type;
6023 stringData = cData.value;
6024 break;
6028 if (stype == nullptr || stringData == nullptr)
6030 carla_stderr("Plugin requested value for '%s' which is not available", skey);
6031 *size = *type = *flags = 0;
6032 return nullptr;
6035 *type = carla_lv2_urid_map(this, stype);
6036 *flags = LV2_STATE_IS_POD;
6038 if (*type == kUridAtomString || *type == kUridAtomPath)
6040 *size = std::strlen(stringData);
6041 return stringData;
6044 if (fLastStateChunk != nullptr)
6046 std::free(fLastStateChunk);
6047 fLastStateChunk = nullptr;
6050 std::vector<uint8_t> chunk(carla_getChunkFromBase64String(stringData));
6051 CARLA_SAFE_ASSERT_RETURN(chunk.size() > 0, nullptr);
6053 fLastStateChunk = std::malloc(chunk.size());
6054 CARLA_SAFE_ASSERT_RETURN(fLastStateChunk != nullptr, nullptr);
6056 #ifdef CARLA_PROPER_CPP11_SUPPORT
6057 std::memcpy(fLastStateChunk, chunk.data(), chunk.size());
6058 #else
6059 std::memcpy(fLastStateChunk, &chunk.front(), chunk.size());
6060 #endif
6062 *size = chunk.size();
6063 return fLastStateChunk;
6066 // -------------------------------------------------------------------
6068 LV2_Worker_Status handleWorkerSchedule(const uint32_t size, const void* const data)
6070 CARLA_SAFE_ASSERT_RETURN(fExt.worker != nullptr && fExt.worker->work != nullptr, LV2_WORKER_ERR_UNKNOWN);
6071 CARLA_SAFE_ASSERT_RETURN(fEventsIn.ctrl != nullptr, LV2_WORKER_ERR_UNKNOWN);
6072 carla_debug("CarlaPluginLV2::handleWorkerSchedule(%i, %p)", size, data);
6074 if (pData->engine->isOffline())
6076 fExt.worker->work(fHandle, carla_lv2_worker_respond, this, size, data);
6077 return LV2_WORKER_SUCCESS;
6080 LV2_Atom atom;
6081 atom.size = size;
6082 atom.type = kUridCarlaAtomWorkerIn;
6084 return fAtomBufferWorkerIn.putChunk(&atom, data, fEventsOut.ctrlIndex) ? LV2_WORKER_SUCCESS : LV2_WORKER_ERR_NO_SPACE;
6087 LV2_Worker_Status handleWorkerRespond(const uint32_t size, const void* const data)
6089 CARLA_SAFE_ASSERT_RETURN(fExt.worker != nullptr && fExt.worker->work_response != nullptr, LV2_WORKER_ERR_UNKNOWN);
6090 carla_debug("CarlaPluginLV2::handleWorkerRespond(%i, %p)", size, data);
6092 LV2_Atom atom;
6093 atom.size = size;
6094 atom.type = kUridCarlaAtomWorkerResp;
6096 return fAtomBufferWorkerResp.putChunk(&atom, data, fEventsIn.ctrlIndex) ? LV2_WORKER_SUCCESS : LV2_WORKER_ERR_NO_SPACE;
6099 // -------------------------------------------------------------------
6101 void handleInlineDisplayQueueRedraw()
6103 switch (pData->engine->getProccessMode())
6105 case ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS:
6106 case ENGINE_PROCESS_MODE_PATCHBAY:
6107 fInlineDisplayNeedsRedraw = true;
6108 break;
6109 default:
6110 break;
6114 const LV2_Inline_Display_Image_Surface* renderInlineDisplay(const uint32_t width, const uint32_t height) const
6116 CARLA_SAFE_ASSERT_RETURN(fExt.inlineDisplay != nullptr && fExt.inlineDisplay->render != nullptr, nullptr);
6117 CARLA_SAFE_ASSERT_RETURN(width > 0, nullptr);
6118 CARLA_SAFE_ASSERT_RETURN(height > 0, nullptr);
6120 return fExt.inlineDisplay->render(fHandle, width, height);
6123 // -------------------------------------------------------------------
6125 void handleMidnamUpdate()
6127 CARLA_SAFE_ASSERT_RETURN(fExt.midnam != nullptr,);
6129 if (fEventsIn.ctrl == nullptr)
6130 return;
6132 char* const midnam = fExt.midnam->midnam(fHandle);
6133 CARLA_SAFE_ASSERT_RETURN(midnam != nullptr,);
6135 fEventsIn.ctrl->port->setMetaData("http://www.midi.org/dtds/MIDINameDocument10.dtd", midnam, "text/xml");
6137 if (fExt.midnam->free != nullptr)
6138 fExt.midnam->free(midnam);
6141 // -------------------------------------------------------------------
6143 LV2_ControlInputPort_Change_Status handleCtrlInPortChangeReq(const uint32_t rindex, const float value)
6145 CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr, LV2_CONTROL_INPUT_PORT_CHANGE_ERR_UNKNOWN);
6147 for (uint32_t i=0; i < pData->param.count; ++i)
6149 if (pData->param.data[i].rindex != static_cast<int32_t>(rindex))
6150 continue;
6152 const uint32_t index = i;
6153 const float fixedValue = pData->param.getFixedValue(index, value);
6154 fParamBuffers[index] = fixedValue;
6156 CarlaPlugin::setParameterValueRT(index, fixedValue, 0, true);
6157 return LV2_CONTROL_INPUT_PORT_CHANGE_SUCCESS;
6160 return LV2_CONTROL_INPUT_PORT_CHANGE_ERR_INVALID_INDEX;
6163 // -------------------------------------------------------------------
6165 void handleExternalUIClosed()
6167 CARLA_SAFE_ASSERT_RETURN(fUI.type == UI::TYPE_EXTERNAL,);
6168 carla_debug("CarlaPluginLV2::handleExternalUIClosed()");
6170 fNeedsUiClose = true;
6173 void handlePluginUIClosed() override
6175 CARLA_SAFE_ASSERT_RETURN(fUI.type == UI::TYPE_EMBED,);
6176 CARLA_SAFE_ASSERT_RETURN(fUI.window != nullptr,);
6177 carla_debug("CarlaPluginLV2::handlePluginUIClosed()");
6179 fNeedsUiClose = true;
6182 void handlePluginUIResized(const uint width, const uint height) override
6184 CARLA_SAFE_ASSERT_RETURN(fUI.type == UI::TYPE_EMBED,);
6185 CARLA_SAFE_ASSERT_RETURN(fUI.window != nullptr,);
6186 carla_debug("CarlaPluginLV2::handlePluginUIResized(%u, %u)", width, height);
6188 if (fUI.handle != nullptr && fExt.uiresize != nullptr)
6189 fExt.uiresize->ui_resize(fUI.handle, static_cast<int>(width), static_cast<int>(height));
6192 // -------------------------------------------------------------------
6194 uint32_t handleUIPortMap(const char* const symbol) const noexcept
6196 CARLA_SAFE_ASSERT_RETURN(symbol != nullptr && symbol[0] != '\0', LV2UI_INVALID_PORT_INDEX);
6197 carla_debug("CarlaPluginLV2::handleUIPortMap(\"%s\")", symbol);
6199 for (uint32_t i=0; i < fRdfDescriptor->PortCount; ++i)
6201 if (std::strcmp(fRdfDescriptor->Ports[i].Symbol, symbol) == 0)
6202 return i;
6205 return LV2UI_INVALID_PORT_INDEX;
6208 LV2UI_Request_Value_Status handleUIRequestValue(const LV2_URID key,
6209 const LV2_URID type,
6210 const LV2_Feature* const* features)
6212 CARLA_SAFE_ASSERT_RETURN(fUI.type != UI::TYPE_NULL, LV2UI_REQUEST_VALUE_ERR_UNKNOWN);
6213 carla_debug("CarlaPluginLV2::handleUIRequestValue(%u, %u, %p)", key, type, features);
6215 if (type != kUridAtomPath)
6216 return LV2UI_REQUEST_VALUE_ERR_UNSUPPORTED;
6218 const char* const uri = getCustomURIDString(key);
6219 CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri != kUnmapFallback, LV2UI_REQUEST_VALUE_ERR_UNKNOWN);
6221 // check if a file browser is already open
6222 if (fUI.fileNeededForURI != nullptr || fUI.fileBrowserOpen)
6223 return LV2UI_REQUEST_VALUE_BUSY;
6225 for (uint32_t i=0; i < fRdfDescriptor->ParameterCount; ++i)
6227 if (fRdfDescriptor->Parameters[i].Type != LV2_PARAMETER_TYPE_PATH)
6228 continue;
6229 if (std::strcmp(fRdfDescriptor->Parameters[i].URI, uri) != 0)
6230 continue;
6232 // TODO file browser filters, also store label to use for title
6233 fUI.fileNeededForURI = uri;
6235 return LV2UI_REQUEST_VALUE_SUCCESS;
6238 return LV2UI_REQUEST_VALUE_ERR_UNSUPPORTED;
6240 // may be unused
6241 (void)features;
6244 int handleUIResize(const int width, const int height)
6246 CARLA_SAFE_ASSERT_RETURN(width > 0, 1);
6247 CARLA_SAFE_ASSERT_RETURN(height > 0, 1);
6248 carla_debug("CarlaPluginLV2::handleUIResize(%i, %i)", width, height);
6250 if (fUI.embedded)
6252 pData->engine->callback(true, true,
6253 ENGINE_CALLBACK_EMBED_UI_RESIZED,
6254 pData->id, width, height,
6255 0, 0.0f, nullptr);
6257 else
6259 CARLA_SAFE_ASSERT_RETURN(fUI.window != nullptr, 1);
6260 fUI.window->setSize(static_cast<uint>(width), static_cast<uint>(height), true, true);
6263 return 0;
6266 void handleUITouch(const uint32_t rindex, const bool touch)
6268 carla_debug("CarlaPluginLV2::handleUITouch(%u, %s)", rindex, bool2str(touch));
6270 uint32_t index = LV2UI_INVALID_PORT_INDEX;
6272 for (uint32_t i=0; i < pData->param.count; ++i)
6274 if (pData->param.data[i].rindex != static_cast<int32_t>(rindex))
6275 continue;
6276 index = i;
6277 break;
6280 CARLA_SAFE_ASSERT_RETURN(index != LV2UI_INVALID_PORT_INDEX,);
6282 pData->engine->touchPluginParameter(pData->id, index, touch);
6285 void handleUIWrite(const uint32_t rindex, const uint32_t bufferSize, const uint32_t format, const void* const buffer)
6287 CARLA_SAFE_ASSERT_RETURN(buffer != nullptr,);
6288 CARLA_SAFE_ASSERT_RETURN(bufferSize > 0,);
6289 carla_debug("CarlaPluginLV2::handleUIWrite(%i, %i, %i, %p)", rindex, bufferSize, format, buffer);
6291 uint32_t index = LV2UI_INVALID_PORT_INDEX;
6293 switch (format)
6295 case kUridNull: {
6296 CARLA_SAFE_ASSERT_RETURN(rindex < fRdfDescriptor->PortCount,);
6297 CARLA_SAFE_ASSERT_RETURN(bufferSize == sizeof(float),);
6299 for (uint32_t i=0; i < pData->param.count; ++i)
6301 if (pData->param.data[i].rindex != static_cast<int32_t>(rindex))
6302 continue;
6303 index = i;
6304 break;
6307 CARLA_SAFE_ASSERT_RETURN(index != LV2UI_INVALID_PORT_INDEX,);
6309 const float value(*(const float*)buffer);
6311 // check if we should feedback message back to UI
6312 bool sendGui = false;
6314 if (const uint32_t notifCount = fUI.rdfDescriptor->PortNotificationCount)
6316 const char* const portSymbol = fRdfDescriptor->Ports[rindex].Symbol;
6318 for (uint32_t i=0; i < notifCount; ++i)
6320 const LV2_RDF_UI_PortNotification& portNotif(fUI.rdfDescriptor->PortNotifications[i]);
6322 if (portNotif.Protocol != LV2_UI_PORT_PROTOCOL_FLOAT)
6323 continue;
6325 if (portNotif.Symbol != nullptr)
6327 if (std::strcmp(portNotif.Symbol, portSymbol) != 0)
6328 continue;
6330 else if (portNotif.Index != rindex)
6332 continue;
6335 sendGui = true;
6336 break;
6340 setParameterValue(index, value, sendGui, true, true);
6342 } break;
6344 case kUridAtomTransferAtom:
6345 case kUridAtomTransferEvent: {
6346 CARLA_SAFE_ASSERT_RETURN(bufferSize >= sizeof(LV2_Atom),);
6348 const LV2_Atom* const atom((const LV2_Atom*)buffer);
6350 // plugins sometimes fail on this, not good...
6351 const uint32_t totalSize = lv2_atom_total_size(atom);
6352 const uint32_t paddedSize = lv2_atom_pad_size(totalSize);
6354 if (bufferSize != totalSize && bufferSize != paddedSize)
6355 carla_stderr2("Warning: LV2 UI sending atom with invalid size %u! size: %u, padded-size: %u",
6356 bufferSize, totalSize, paddedSize);
6358 for (uint32_t i=0; i < fEventsIn.count; ++i)
6360 if (fEventsIn.data[i].rindex != rindex)
6361 continue;
6362 index = i;
6363 break;
6366 // for bad plugins
6367 if (index == LV2UI_INVALID_PORT_INDEX)
6369 CARLA_SAFE_ASSERT(index != LV2UI_INVALID_PORT_INDEX); // FIXME
6370 index = fEventsIn.ctrlIndex;
6373 fAtomBufferEvIn.put(atom, index);
6374 } break;
6376 default:
6377 carla_stdout("CarlaPluginLV2::handleUIWrite(%i, %i, %i:\"%s\", %p) - unknown format",
6378 rindex, bufferSize, format, carla_lv2_urid_unmap(this, format), buffer);
6379 break;
6383 void handleUIBridgeParameter(const char* const uri, const float value)
6385 CARLA_SAFE_ASSERT_RETURN(uri != nullptr,);
6386 carla_debug("CarlaPluginLV2::handleUIBridgeParameter(%s, %f)", uri, static_cast<double>(value));
6388 uint32_t parameterId;
6390 if (getParameterIndexForURI(uri, parameterId))
6391 setParameterValue(parameterId, value, false, true, true);
6394 // -------------------------------------------------------------------
6396 void handleLilvSetPortValue(const char* const portSymbol, const void* const value, const uint32_t size, const uint32_t type)
6398 CARLA_SAFE_ASSERT_RETURN(portSymbol != nullptr && portSymbol[0] != '\0',);
6399 CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
6400 CARLA_SAFE_ASSERT_RETURN(size > 0,);
6401 CARLA_SAFE_ASSERT_RETURN(type != kUridNull,);
6402 carla_debug("CarlaPluginLV2::handleLilvSetPortValue(\"%s\", %p, %i, %i)", portSymbol, value, size, type);
6404 int32_t rindex = -1;
6406 for (uint32_t i=0; i < fRdfDescriptor->PortCount; ++i)
6408 if (std::strcmp(fRdfDescriptor->Ports[i].Symbol, portSymbol) == 0)
6410 rindex = static_cast<int32_t>(i);
6411 break;
6415 CARLA_SAFE_ASSERT_RETURN(rindex >= 0,);
6417 float paramValue;
6419 switch (type)
6421 case kUridAtomBool:
6422 CARLA_SAFE_ASSERT_RETURN(size == sizeof(int32_t),);
6423 paramValue = *(const int32_t*)value != 0 ? 1.0f : 0.0f;
6424 break;
6425 case kUridAtomDouble:
6426 CARLA_SAFE_ASSERT_RETURN(size == sizeof(double),);
6427 paramValue = static_cast<float>((*(const double*)value));
6428 break;
6429 case kUridAtomFloat:
6430 CARLA_SAFE_ASSERT_RETURN(size == sizeof(float),);
6431 paramValue = *(const float*)value;
6432 break;
6433 case kUridAtomInt:
6434 CARLA_SAFE_ASSERT_RETURN(size == sizeof(int32_t),);
6435 paramValue = static_cast<float>(*(const int32_t*)value);
6436 break;
6437 case kUridAtomLong:
6438 CARLA_SAFE_ASSERT_RETURN(size == sizeof(int64_t),);
6439 paramValue = static_cast<float>(*(const int64_t*)value);
6440 break;
6441 default:
6442 carla_stdout("CarlaPluginLV2::handleLilvSetPortValue(\"%s\", %p, %i, %i:\"%s\") - unknown type",
6443 portSymbol, value, size, type, carla_lv2_urid_unmap(this, type));
6444 return;
6447 for (uint32_t i=0; i < pData->param.count; ++i)
6449 if (pData->param.data[i].rindex == rindex)
6451 setParameterValueRT(i, paramValue, 0, true);
6452 break;
6457 // -------------------------------------------------------------------
6459 void* getNativeHandle() const noexcept override
6461 return fHandle;
6464 const void* getNativeDescriptor() const noexcept override
6466 return fDescriptor;
6469 #ifndef LV2_UIS_ONLY_INPROCESS
6470 uintptr_t getUiBridgeProcessId() const noexcept override
6472 return fPipeServer.isPipeRunning() ? fPipeServer.getPID() : 0;
6474 #endif
6476 // -------------------------------------------------------------------
6478 public:
6479 bool init(const CarlaPluginPtr plugin,
6480 const char* const name, const char* const uri, const uint options,
6481 const char*& needsArchBridge)
6483 CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);
6485 // ---------------------------------------------------------------
6486 // first checks
6488 if (pData->client != nullptr)
6490 pData->engine->setLastError("Plugin client is already registered");
6491 return false;
6494 if (uri == nullptr || uri[0] == '\0')
6496 pData->engine->setLastError("null uri");
6497 return false;
6500 const EngineOptions& opts(pData->engine->getOptions());
6502 // ---------------------------------------------------------------
6503 // Init LV2 World if needed, sets LV2_PATH for lilv
6505 Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
6507 if (opts.pathLV2 != nullptr && opts.pathLV2[0] != '\0')
6508 lv2World.initIfNeeded(opts.pathLV2);
6509 else if (const char* const LV2_PATH = std::getenv("LV2_PATH"))
6510 lv2World.initIfNeeded(LV2_PATH);
6511 else
6512 lv2World.initIfNeeded(LILV_DEFAULT_LV2_PATH);
6514 // ---------------------------------------------------------------
6515 // get plugin from lv2_rdf (lilv)
6517 fRdfDescriptor = lv2_rdf_new(uri, true);
6519 if (fRdfDescriptor == nullptr)
6521 pData->engine->setLastError("Failed to find the requested plugin");
6522 return false;
6525 #ifdef ADAPT_FOR_APPLE_SILLICON
6526 // ---------------------------------------------------------------
6527 // check if we can open this binary, might need a bridge
6530 const CarlaMagic magic;
6532 if (const char* const output = magic.getFileDescription(fRdfDescriptor->Binary))
6534 # ifdef __aarch64__
6535 if (std::strstr(output, "arm64") == nullptr && std::strstr(output, "x86_64") != nullptr)
6536 needsArchBridge = "x86_64";
6537 # else
6538 if (std::strstr(output, "x86_64") == nullptr && std::strstr(output, "arm64") != nullptr)
6539 needsArchBridge = "arm64";
6540 # endif
6541 if (needsArchBridge != nullptr)
6542 return false;
6545 #endif // ADAPT_FOR_APPLE_SILLICON
6547 // ---------------------------------------------------------------
6548 // open DLL
6550 #ifdef CARLA_OS_MAC
6551 // Binary might be in quarentine due to Apple stupid notarization rules, let's remove that if possible
6552 removeFileFromQuarantine(fRdfDescriptor->Binary);
6553 #endif
6555 if (! pData->libOpen(fRdfDescriptor->Binary))
6557 pData->engine->setLastError(pData->libError(fRdfDescriptor->Binary));
6558 return false;
6561 // ---------------------------------------------------------------
6562 // try to get DLL main entry via new mode
6564 if (const LV2_Lib_Descriptor_Function libDescFn = pData->libSymbol<LV2_Lib_Descriptor_Function>("lv2_lib_descriptor"))
6566 // -----------------------------------------------------------
6567 // all ok, get lib descriptor
6569 const LV2_Lib_Descriptor* const libDesc = libDescFn(fRdfDescriptor->Bundle, nullptr);
6571 if (libDesc == nullptr)
6573 pData->engine->setLastError("Could not find the LV2 Descriptor");
6574 return false;
6577 // -----------------------------------------------------------
6578 // get descriptor that matches URI (new mode)
6580 uint32_t i = 0;
6581 while ((fDescriptor = libDesc->get_plugin(libDesc->handle, i++)))
6583 if (std::strcmp(fDescriptor->URI, uri) == 0)
6584 break;
6587 else
6589 // -----------------------------------------------------------
6590 // get DLL main entry (old mode)
6592 const LV2_Descriptor_Function descFn = pData->libSymbol<LV2_Descriptor_Function>("lv2_descriptor");
6594 if (descFn == nullptr)
6596 pData->engine->setLastError("Could not find the LV2 Descriptor in the plugin library");
6597 return false;
6600 // -----------------------------------------------------------
6601 // get descriptor that matches URI (old mode)
6603 uint32_t i = 0;
6604 while ((fDescriptor = descFn(i++)))
6606 if (std::strcmp(fDescriptor->URI, uri) == 0)
6607 break;
6611 if (fDescriptor == nullptr)
6613 pData->engine->setLastError("Could not find the requested plugin URI in the plugin library");
6614 return false;
6617 // ---------------------------------------------------------------
6618 // check supported port-types and features
6620 bool canContinue = true;
6622 // Check supported ports
6623 for (uint32_t j=0; j < fRdfDescriptor->PortCount; ++j)
6625 const LV2_Property portTypes(fRdfDescriptor->Ports[j].Types);
6627 if (! is_lv2_port_supported(portTypes))
6629 if (! LV2_IS_PORT_OPTIONAL(fRdfDescriptor->Ports[j].Properties))
6631 pData->engine->setLastError("Plugin requires a port type that is not currently supported");
6632 canContinue = false;
6633 break;
6638 // Check supported features
6639 for (uint32_t j=0; j < fRdfDescriptor->FeatureCount && canContinue; ++j)
6641 const LV2_RDF_Feature& feature(fRdfDescriptor->Features[j]);
6643 if (std::strcmp(feature.URI, LV2_DATA_ACCESS_URI) == 0 || std::strcmp(feature.URI, LV2_INSTANCE_ACCESS_URI) == 0)
6645 carla_stderr("Plugin DSP wants UI feature '%s', ignoring this", feature.URI);
6647 else if (std::strcmp(feature.URI, LV2_BUF_SIZE__fixedBlockLength) == 0)
6649 fNeedsFixedBuffers = true;
6651 else if (std::strcmp(feature.URI, LV2_PORT_PROPS__supportsStrictBounds) == 0)
6653 fStrictBounds = feature.Required ? 1 : 0;
6655 else if (std::strcmp(feature.URI, LV2_STATE__loadDefaultState) == 0)
6657 fHasLoadDefaultState = true;
6659 else if (std::strcmp(feature.URI, LV2_STATE__threadSafeRestore) == 0)
6661 fHasThreadSafeRestore = true;
6663 else if (feature.Required && ! is_lv2_feature_supported(feature.URI))
6665 CarlaString msg("Plugin wants a feature that is not supported:\n");
6666 msg += feature.URI;
6668 canContinue = false;
6669 pData->engine->setLastError(msg);
6670 break;
6674 if (! canContinue)
6676 // error already set
6677 return false;
6680 if (fNeedsFixedBuffers && ! pData->engine->usesConstantBufferSize())
6682 pData->engine->setLastError("Cannot use this plugin under the current engine.\n"
6683 "The plugin requires a fixed block size which is not possible right now.");
6684 return false;
6687 // ---------------------------------------------------------------
6688 // set icon
6690 if (std::strncmp(fDescriptor->URI, "http://distrho.sf.net/", 22) == 0)
6691 pData->iconName = carla_strdup_safe("distrho");
6693 // ---------------------------------------------------------------
6694 // set info
6696 if (name != nullptr && name[0] != '\0')
6697 pData->name = pData->engine->getUniquePluginName(name);
6698 else
6699 pData->name = pData->engine->getUniquePluginName(fRdfDescriptor->Name);
6701 // ---------------------------------------------------------------
6702 // register client
6704 pData->client = pData->engine->addClient(plugin);
6706 if (pData->client == nullptr || ! pData->client->isOk())
6708 pData->engine->setLastError("Failed to register plugin client");
6709 return false;
6712 // ---------------------------------------------------------------
6713 // initialize options
6715 const int bufferSize = static_cast<int>(pData->engine->getBufferSize());
6717 fLv2Options.minBufferSize = fNeedsFixedBuffers ? bufferSize : 1;
6718 fLv2Options.maxBufferSize = bufferSize;
6719 fLv2Options.nominalBufferSize = bufferSize;
6720 fLv2Options.sampleRate = static_cast<float>(pData->engine->getSampleRate());
6721 fLv2Options.transientWinId = static_cast<int64_t>(opts.frontendWinId);
6723 uint32_t eventBufferSize = MAX_DEFAULT_BUFFER_SIZE;
6725 for (uint32_t j=0; j < fRdfDescriptor->PortCount; ++j)
6727 const LV2_Property portTypes(fRdfDescriptor->Ports[j].Types);
6729 if (LV2_IS_PORT_ATOM_SEQUENCE(portTypes) || LV2_IS_PORT_EVENT(portTypes) || LV2_IS_PORT_MIDI_LL(portTypes))
6731 if (fRdfDescriptor->Ports[j].MinimumSize > eventBufferSize)
6732 eventBufferSize = fRdfDescriptor->Ports[j].MinimumSize;
6736 fLv2Options.sequenceSize = static_cast<int>(eventBufferSize);
6738 fLv2Options.bgColor = opts.bgColor;
6739 fLv2Options.fgColor = opts.fgColor;
6740 fLv2Options.uiScale = opts.uiScale;
6742 // ---------------------------------------------------------------
6743 // initialize features (part 1)
6745 LV2_Event_Feature* const eventFt = new LV2_Event_Feature;
6746 eventFt->callback_data = this;
6747 eventFt->lv2_event_ref = carla_lv2_event_ref;
6748 eventFt->lv2_event_unref = carla_lv2_event_unref;
6750 LV2_Log_Log* const logFt = new LV2_Log_Log;
6751 logFt->handle = this;
6752 logFt->printf = carla_lv2_log_printf;
6753 logFt->vprintf = carla_lv2_log_vprintf;
6755 LV2_State_Free_Path* const stateFreePathFt = new LV2_State_Free_Path;
6756 stateFreePathFt->handle = this;
6757 stateFreePathFt->free_path = carla_lv2_state_free_path;
6759 LV2_State_Make_Path* const stateMakePathFt = new LV2_State_Make_Path;
6760 stateMakePathFt->handle = this;
6761 stateMakePathFt->path = carla_lv2_state_make_path_tmp;
6763 LV2_State_Map_Path* const stateMapPathFt = new LV2_State_Map_Path;
6764 stateMapPathFt->handle = this;
6765 stateMapPathFt->abstract_path = carla_lv2_state_map_to_abstract_path_tmp;
6766 stateMapPathFt->absolute_path = carla_lv2_state_map_to_absolute_path_tmp;
6768 LV2_Programs_Host* const programsFt = new LV2_Programs_Host;
6769 programsFt->handle = this;
6770 programsFt->program_changed = carla_lv2_program_changed;
6772 LV2_Resize_Port_Resize* const rsPortFt = new LV2_Resize_Port_Resize;
6773 rsPortFt->data = this;
6774 rsPortFt->resize = carla_lv2_resize_port;
6776 LV2_RtMemPool_Pool* const rtMemPoolFt = new LV2_RtMemPool_Pool;
6777 lv2_rtmempool_init(rtMemPoolFt);
6779 LV2_RtMemPool_Pool_Deprecated* const rtMemPoolOldFt = new LV2_RtMemPool_Pool_Deprecated;
6780 lv2_rtmempool_init_deprecated(rtMemPoolOldFt);
6782 LV2_URI_Map_Feature* const uriMapFt = new LV2_URI_Map_Feature;
6783 uriMapFt->callback_data = this;
6784 uriMapFt->uri_to_id = carla_lv2_uri_to_id;
6786 LV2_URID_Map* const uridMapFt = new LV2_URID_Map;
6787 uridMapFt->handle = this;
6788 uridMapFt->map = carla_lv2_urid_map;
6790 LV2_URID_Unmap* const uridUnmapFt = new LV2_URID_Unmap;
6791 uridUnmapFt->handle = this;
6792 uridUnmapFt->unmap = carla_lv2_urid_unmap;
6794 LV2_Worker_Schedule* const workerFt = new LV2_Worker_Schedule;
6795 workerFt->handle = this;
6796 workerFt->schedule_work = carla_lv2_worker_schedule;
6798 LV2_Inline_Display* const inlineDisplay = new LV2_Inline_Display;
6799 inlineDisplay->handle = this;
6800 inlineDisplay->queue_draw = carla_lv2_inline_display_queue_draw;
6802 LV2_Midnam* const midnam = new LV2_Midnam;
6803 midnam->handle = this;
6804 midnam->update = carla_lv2_midnam_update;
6806 LV2_ControlInputPort_Change_Request* const portChangeReq = new LV2_ControlInputPort_Change_Request;
6807 portChangeReq->handle = this;
6808 portChangeReq->request_change = carla_lv2_ctrl_in_port_change_req;
6810 // ---------------------------------------------------------------
6811 // initialize features (part 2)
6813 for (uint32_t j=0; j < kFeatureCountPlugin; ++j)
6814 fFeatures[j] = new LV2_Feature;
6816 fFeatures[kFeatureIdBufSizeBounded]->URI = LV2_BUF_SIZE__boundedBlockLength;
6817 fFeatures[kFeatureIdBufSizeBounded]->data = nullptr;
6819 fFeatures[kFeatureIdBufSizeFixed]->URI = fNeedsFixedBuffers
6820 ? LV2_BUF_SIZE__fixedBlockLength
6821 : LV2_BUF_SIZE__boundedBlockLength;
6822 fFeatures[kFeatureIdBufSizeFixed]->data = nullptr;
6824 fFeatures[kFeatureIdBufSizePowerOf2]->URI = LV2_BUF_SIZE__powerOf2BlockLength;
6825 fFeatures[kFeatureIdBufSizePowerOf2]->data = nullptr;
6827 fFeatures[kFeatureIdEvent]->URI = LV2_EVENT_URI;
6828 fFeatures[kFeatureIdEvent]->data = eventFt;
6830 fFeatures[kFeatureIdHardRtCapable]->URI = LV2_CORE__hardRTCapable;
6831 fFeatures[kFeatureIdHardRtCapable]->data = nullptr;
6833 fFeatures[kFeatureIdInPlaceBroken]->URI = LV2_CORE__inPlaceBroken;
6834 fFeatures[kFeatureIdInPlaceBroken]->data = nullptr;
6836 fFeatures[kFeatureIdIsLive]->URI = LV2_CORE__isLive;
6837 fFeatures[kFeatureIdIsLive]->data = nullptr;
6839 fFeatures[kFeatureIdLogs]->URI = LV2_LOG__log;
6840 fFeatures[kFeatureIdLogs]->data = logFt;
6842 fFeatures[kFeatureIdOptions]->URI = LV2_OPTIONS__options;
6843 fFeatures[kFeatureIdOptions]->data = fLv2Options.opts;
6845 fFeatures[kFeatureIdPrograms]->URI = LV2_PROGRAMS__Host;
6846 fFeatures[kFeatureIdPrograms]->data = programsFt;
6848 fFeatures[kFeatureIdResizePort]->URI = LV2_RESIZE_PORT__resize;
6849 fFeatures[kFeatureIdResizePort]->data = rsPortFt;
6851 fFeatures[kFeatureIdRtMemPool]->URI = LV2_RTSAFE_MEMORY_POOL__Pool;
6852 fFeatures[kFeatureIdRtMemPool]->data = rtMemPoolFt;
6854 fFeatures[kFeatureIdRtMemPoolOld]->URI = LV2_RTSAFE_MEMORY_POOL_DEPRECATED_URI;
6855 fFeatures[kFeatureIdRtMemPoolOld]->data = rtMemPoolOldFt;
6857 fFeatures[kFeatureIdStateFreePath]->URI = LV2_STATE__freePath;
6858 fFeatures[kFeatureIdStateFreePath]->data = stateFreePathFt;
6860 fFeatures[kFeatureIdStateMakePath]->URI = LV2_STATE__makePath;
6861 fFeatures[kFeatureIdStateMakePath]->data = stateMakePathFt;
6863 fFeatures[kFeatureIdStateMapPath]->URI = LV2_STATE__mapPath;
6864 fFeatures[kFeatureIdStateMapPath]->data = stateMapPathFt;
6866 fFeatures[kFeatureIdStrictBounds]->URI = LV2_PORT_PROPS__supportsStrictBounds;
6867 fFeatures[kFeatureIdStrictBounds]->data = nullptr;
6869 fFeatures[kFeatureIdUriMap]->URI = LV2_URI_MAP_URI;
6870 fFeatures[kFeatureIdUriMap]->data = uriMapFt;
6872 fFeatures[kFeatureIdUridMap]->URI = LV2_URID__map;
6873 fFeatures[kFeatureIdUridMap]->data = uridMapFt;
6875 fFeatures[kFeatureIdUridUnmap]->URI = LV2_URID__unmap;
6876 fFeatures[kFeatureIdUridUnmap]->data = uridUnmapFt;
6878 fFeatures[kFeatureIdWorker]->URI = LV2_WORKER__schedule;
6879 fFeatures[kFeatureIdWorker]->data = workerFt;
6881 fFeatures[kFeatureIdInlineDisplay]->URI = LV2_INLINEDISPLAY__queue_draw;
6882 fFeatures[kFeatureIdInlineDisplay]->data = inlineDisplay;
6884 fFeatures[kFeatureIdMidnam]->URI = LV2_MIDNAM__update;
6885 fFeatures[kFeatureIdMidnam]->data = midnam;
6887 fFeatures[kFeatureIdCtrlInPortChangeReq]->URI = LV2_CONTROL_INPUT_PORT_CHANGE_REQUEST_URI;
6888 fFeatures[kFeatureIdCtrlInPortChangeReq]->data = portChangeReq;
6890 // ---------------------------------------------------------------
6891 // initialize features (part 3)
6893 LV2_State_Make_Path* const stateMakePathFt2 = new LV2_State_Make_Path;
6894 stateMakePathFt2->handle = this;
6895 stateMakePathFt2->path = carla_lv2_state_make_path_real;
6897 LV2_State_Map_Path* const stateMapPathFt2 = new LV2_State_Map_Path;
6898 stateMapPathFt2->handle = this;
6899 stateMapPathFt2->abstract_path = carla_lv2_state_map_to_abstract_path_real;
6900 stateMapPathFt2->absolute_path = carla_lv2_state_map_to_absolute_path_real;
6902 for (uint32_t j=0; j < kStateFeatureCountAll; ++j)
6903 fStateFeatures[j] = new LV2_Feature;
6905 fStateFeatures[kStateFeatureIdFreePath]->URI = LV2_STATE__freePath;
6906 fStateFeatures[kStateFeatureIdFreePath]->data = stateFreePathFt;
6908 fStateFeatures[kStateFeatureIdMakePath]->URI = LV2_STATE__makePath;
6909 fStateFeatures[kStateFeatureIdMakePath]->data = stateMakePathFt2;
6911 fStateFeatures[kStateFeatureIdMapPath]->URI = LV2_STATE__mapPath;
6912 fStateFeatures[kStateFeatureIdMapPath]->data = stateMapPathFt2;
6914 fStateFeatures[kStateFeatureIdWorker]->URI = LV2_WORKER__schedule;
6915 fStateFeatures[kStateFeatureIdWorker]->data = workerFt;
6917 // ---------------------------------------------------------------
6918 // initialize plugin
6920 try {
6921 fHandle = fDescriptor->instantiate(fDescriptor, pData->engine->getSampleRate(), fRdfDescriptor->Bundle, fFeatures);
6922 } catch(...) {}
6924 if (fHandle == nullptr)
6926 pData->engine->setLastError("Plugin failed to initialize");
6927 return false;
6930 recheckExtensions();
6932 // ---------------------------------------------------------------
6933 // set options
6935 pData->options = 0x0;
6937 if (fLatencyIndex >= 0 || getMidiOutCount() != 0 || fNeedsFixedBuffers)
6938 pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;
6939 else if (options & PLUGIN_OPTION_FIXED_BUFFERS)
6940 pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;
6942 if (opts.forceStereo)
6943 pData->options |= PLUGIN_OPTION_FORCE_STEREO;
6944 else if (options & PLUGIN_OPTION_FORCE_STEREO)
6945 pData->options |= PLUGIN_OPTION_FORCE_STEREO;
6947 if (getMidiInCount() != 0)
6949 if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CONTROL_CHANGES))
6950 pData->options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
6951 if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CHANNEL_PRESSURE))
6952 pData->options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
6953 if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH))
6954 pData->options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
6955 if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PITCHBEND))
6956 pData->options |= PLUGIN_OPTION_SEND_PITCHBEND;
6957 if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_ALL_SOUND_OFF))
6958 pData->options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
6959 if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PROGRAM_CHANGES))
6960 pData->options |= PLUGIN_OPTION_SEND_PROGRAM_CHANGES;
6961 if (isPluginOptionInverseEnabled(options, PLUGIN_OPTION_SKIP_SENDING_NOTES))
6962 pData->options |= PLUGIN_OPTION_SKIP_SENDING_NOTES;
6965 if (fExt.programs != nullptr && (pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES) == 0)
6967 if (isPluginOptionEnabled(options, PLUGIN_OPTION_MAP_PROGRAM_CHANGES))
6968 pData->options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
6971 // ---------------------------------------------------------------
6972 // gui stuff
6974 if (fRdfDescriptor->UICount != 0)
6975 initUi();
6977 return true;
6979 // might be unused
6980 (void)needsArchBridge;
6983 // -------------------------------------------------------------------
6985 void initUi()
6987 // ---------------------------------------------------------------
6988 // find the most appropriate ui
6990 int eQt4, eQt5, eGtk2, eGtk3, eCocoa, eWindows, eX11, eMod, iCocoa, iWindows, iX11, iExt, iFinal;
6991 eQt4 = eQt5 = eGtk2 = eGtk3 = eCocoa = eWindows = eX11 = eMod = iCocoa = iWindows = iX11 = iExt = iFinal = -1;
6993 #if defined(LV2_UIS_ONLY_BRIDGES)
6994 const bool preferUiBridges = true;
6995 #elif defined(BUILD_BRIDGE)
6996 const bool preferUiBridges = false;
6997 #else
6998 const bool preferUiBridges = pData->engine->getOptions().preferUiBridges;
6999 #endif
7000 bool hasShowInterface = false;
7002 for (uint32_t i=0; i < fRdfDescriptor->UICount; ++i)
7004 CARLA_SAFE_ASSERT_CONTINUE(fRdfDescriptor->UIs[i].URI != nullptr);
7006 const int ii(static_cast<int>(i));
7008 switch (fRdfDescriptor->UIs[i].Type)
7010 case LV2_UI_QT4:
7011 if (isUiBridgeable(i))
7012 eQt4 = ii;
7013 break;
7014 case LV2_UI_QT5:
7015 if (isUiBridgeable(i))
7016 eQt5 = ii;
7017 break;
7018 case LV2_UI_GTK2:
7019 if (isUiBridgeable(i))
7020 eGtk2 = ii;
7021 break;
7022 case LV2_UI_GTK3:
7023 if (isUiBridgeable(i))
7024 eGtk3 = ii;
7025 break;
7026 #ifdef CARLA_OS_MAC
7027 case LV2_UI_COCOA:
7028 if (isUiBridgeable(i) && preferUiBridges)
7029 eCocoa = ii;
7030 iCocoa = ii;
7031 break;
7032 #endif
7033 #ifdef CARLA_OS_WIN
7034 case LV2_UI_WINDOWS:
7035 if (isUiBridgeable(i) && preferUiBridges)
7036 eWindows = ii;
7037 iWindows = ii;
7038 break;
7039 #endif
7040 case LV2_UI_X11:
7041 if (isUiBridgeable(i) && preferUiBridges)
7042 eX11 = ii;
7043 iX11 = ii;
7044 break;
7045 case LV2_UI_EXTERNAL:
7046 case LV2_UI_OLD_EXTERNAL:
7047 iExt = ii;
7048 break;
7049 case LV2_UI_MOD:
7050 eMod = ii;
7051 break;
7052 default:
7053 break;
7057 /**/ if (eQt4 >= 0)
7058 iFinal = eQt4;
7059 else if (eQt5 >= 0)
7060 iFinal = eQt5;
7061 else if (eGtk2 >= 0)
7062 iFinal = eGtk2;
7063 else if (eGtk3 >= 0)
7064 iFinal = eGtk3;
7065 #ifdef CARLA_OS_MAC
7066 else if (eCocoa >= 0)
7067 iFinal = eCocoa;
7068 #endif
7069 #ifdef CARLA_OS_WIN
7070 else if (eWindows >= 0)
7071 iFinal = eWindows;
7072 #endif
7073 #ifdef HAVE_X11
7074 else if (eX11 >= 0)
7075 iFinal = eX11;
7076 #endif
7077 #ifndef LV2_UIS_ONLY_BRIDGES
7078 # ifdef CARLA_OS_MAC
7079 else if (iCocoa >= 0)
7080 iFinal = iCocoa;
7081 # endif
7082 # ifdef CARLA_OS_WIN
7083 else if (iWindows >= 0)
7084 iFinal = iWindows;
7085 # endif
7086 # ifdef HAVE_X11
7087 else if (iX11 >= 0)
7088 iFinal = iX11;
7089 # endif
7090 #endif
7091 else if (iExt >= 0)
7092 iFinal = iExt;
7094 #ifndef BUILD_BRIDGE
7095 if (iFinal < 0)
7096 #endif
7098 // no suitable UI found, see if there's one which supports ui:showInterface
7099 for (uint32_t i=0; i < fRdfDescriptor->UICount && ! hasShowInterface; ++i)
7101 LV2_RDF_UI* const ui(&fRdfDescriptor->UIs[i]);
7103 for (uint32_t j=0; j < ui->ExtensionCount; ++j)
7105 CARLA_SAFE_ASSERT_CONTINUE(ui->Extensions[j] != nullptr);
7107 if (std::strcmp(ui->Extensions[j], LV2_UI__showInterface) != 0)
7108 continue;
7110 iFinal = static_cast<int>(i);
7111 hasShowInterface = true;
7112 break;
7116 if (iFinal < 0)
7118 if (eMod < 0)
7120 carla_stderr("Failed to find an appropriate LV2 UI for this plugin");
7121 return;
7124 // use MODGUI as last resort
7125 iFinal = eMod;
7129 fUI.rdfDescriptor = &fRdfDescriptor->UIs[iFinal];
7131 // ---------------------------------------------------------------
7132 // check supported ui features
7134 bool canContinue = true;
7135 bool canDelete = true;
7137 for (uint32_t i=0; i < fUI.rdfDescriptor->FeatureCount; ++i)
7139 const char* const uri(fUI.rdfDescriptor->Features[i].URI);
7140 CARLA_SAFE_ASSERT_CONTINUE(uri != nullptr && uri[0] != '\0');
7142 if (! is_lv2_ui_feature_supported(uri))
7144 if (fUI.rdfDescriptor->Features[i].Required)
7146 carla_stderr("Plugin UI requires a feature that is not supported:\n%s", uri);
7147 canContinue = false;
7148 break;
7151 carla_stderr("Plugin UI wants a feature that is not supported (ignored):\n%s", uri);
7154 if (std::strcmp(uri, LV2_UI__makeResident) == 0 || std::strcmp(uri, LV2_UI__makeSONameResident) == 0)
7155 canDelete = false;
7156 else if (std::strcmp(uri, LV2_UI__requestValue) == 0)
7157 pData->hints |= PLUGIN_NEEDS_UI_MAIN_THREAD;
7160 if (! canContinue)
7162 fUI.rdfDescriptor = nullptr;
7163 return;
7166 // ---------------------------------------------------------------
7167 // initialize ui according to type
7169 const LV2_Property uiType = fUI.rdfDescriptor->Type;
7171 #ifndef LV2_UIS_ONLY_INPROCESS
7172 if (
7173 (iFinal == eQt4 ||
7174 iFinal == eQt5 ||
7175 iFinal == eGtk2 ||
7176 iFinal == eGtk3 ||
7177 iFinal == eCocoa ||
7178 iFinal == eWindows ||
7179 iFinal == eX11 ||
7180 iFinal == eMod)
7181 #ifdef BUILD_BRIDGE
7182 && ! hasShowInterface
7183 #endif
7186 // -----------------------------------------------------------
7187 // initialize ui-bridge
7189 if (const char* const bridgeBinary = getUiBridgeBinary(uiType))
7191 carla_stdout("Will use UI-Bridge for '%s', binary: \"%s\"", pData->name, bridgeBinary);
7193 CarlaString uiTitle;
7195 if (pData->uiTitle.isNotEmpty())
7197 uiTitle = pData->uiTitle;
7199 else
7201 uiTitle = pData->name;
7202 uiTitle += " (GUI)";
7205 fLv2Options.windowTitle = uiTitle.releaseBufferPointer();
7207 fUI.type = UI::TYPE_BRIDGE;
7208 fPipeServer.setData(bridgeBinary, fRdfDescriptor->URI, fUI.rdfDescriptor->URI);
7210 delete[] bridgeBinary;
7211 return;
7214 if (iFinal == eQt4 || iFinal == eQt5 || iFinal == eGtk2 || iFinal == eGtk3 || iFinal == eMod)
7216 carla_stderr2("Failed to find UI bridge binary for '%s', cannot use UI", pData->name);
7217 fUI.rdfDescriptor = nullptr;
7218 return;
7221 #endif
7223 #ifdef LV2_UIS_ONLY_BRIDGES
7224 carla_stderr2("Failed to get an UI working, canBridge:%s", bool2str(isUiBridgeable(static_cast<uint32_t>(iFinal))));
7225 fUI.rdfDescriptor = nullptr;
7226 return;
7227 #endif
7229 // ---------------------------------------------------------------
7230 // open UI DLL
7232 #ifdef CARLA_OS_MAC
7233 // Binary might be in quarentine due to Apple stupid notarization rules, let's remove that if possible
7234 removeFileFromQuarantine(fUI.rdfDescriptor->Binary);
7235 #endif
7237 if (! pData->uiLibOpen(fUI.rdfDescriptor->Binary, canDelete))
7239 carla_stderr2("Could not load UI library, error was:\n%s", pData->libError(fUI.rdfDescriptor->Binary));
7240 fUI.rdfDescriptor = nullptr;
7241 return;
7244 // ---------------------------------------------------------------
7245 // get UI DLL main entry
7247 LV2UI_DescriptorFunction uiDescFn = pData->uiLibSymbol<LV2UI_DescriptorFunction>("lv2ui_descriptor");
7249 if (uiDescFn == nullptr)
7251 carla_stderr2("Could not find the LV2UI Descriptor in the UI library");
7252 pData->uiLibClose();
7253 fUI.rdfDescriptor = nullptr;
7254 return;
7257 // ---------------------------------------------------------------
7258 // get UI descriptor that matches UI URI
7260 uint32_t i = 0;
7261 while ((fUI.descriptor = uiDescFn(i++)))
7263 if (std::strcmp(fUI.descriptor->URI, fUI.rdfDescriptor->URI) == 0)
7264 break;
7267 if (fUI.descriptor == nullptr)
7269 carla_stderr2("Could not find the requested GUI in the plugin UI library");
7270 pData->uiLibClose();
7271 fUI.rdfDescriptor = nullptr;
7272 return;
7275 // ---------------------------------------------------------------
7276 // check if ui is usable
7278 switch (uiType)
7280 case LV2_UI_NONE:
7281 carla_stdout("Will use LV2 Show Interface for '%s'", pData->name);
7282 fUI.type = UI::TYPE_EMBED;
7283 break;
7284 case LV2_UI_QT4:
7285 carla_stdout("Will use LV2 Qt4 UI for '%s', NOT!", pData->name);
7286 fUI.type = UI::TYPE_EMBED;
7287 break;
7288 case LV2_UI_QT5:
7289 carla_stdout("Will use LV2 Qt5 UI for '%s', NOT!", pData->name);
7290 fUI.type = UI::TYPE_EMBED;
7291 break;
7292 case LV2_UI_GTK2:
7293 carla_stdout("Will use LV2 Gtk2 UI for '%s', NOT!", pData->name);
7294 fUI.type = UI::TYPE_EMBED;
7295 break;
7296 case LV2_UI_GTK3:
7297 carla_stdout("Will use LV2 Gtk3 UI for '%s', NOT!", pData->name);
7298 fUI.type = UI::TYPE_EMBED;
7299 break;
7300 #ifdef CARLA_OS_MAC
7301 case LV2_UI_COCOA:
7302 carla_stdout("Will use LV2 Cocoa UI for '%s'", pData->name);
7303 fUI.type = UI::TYPE_EMBED;
7304 break;
7305 #endif
7306 #ifdef CARLA_OS_WIN
7307 case LV2_UI_WINDOWS:
7308 carla_stdout("Will use LV2 Windows UI for '%s'", pData->name);
7309 fUI.type = UI::TYPE_EMBED;
7310 break;
7311 #endif
7312 case LV2_UI_X11:
7313 #ifdef HAVE_X11
7314 carla_stdout("Will use LV2 X11 UI for '%s'", pData->name);
7315 #else
7316 carla_stdout("Will use LV2 X11 UI for '%s', NOT!", pData->name);
7317 #endif
7318 fUI.type = UI::TYPE_EMBED;
7319 break;
7320 case LV2_UI_EXTERNAL:
7321 case LV2_UI_OLD_EXTERNAL:
7322 carla_stdout("Will use LV2 External UI for '%s'", pData->name);
7323 fUI.type = UI::TYPE_EXTERNAL;
7324 break;
7327 if (fUI.type == UI::TYPE_NULL)
7329 pData->uiLibClose();
7330 fUI.descriptor = nullptr;
7331 fUI.rdfDescriptor = nullptr;
7332 return;
7335 // ---------------------------------------------------------------
7336 // initialize ui data
7339 CarlaString uiTitle;
7341 if (pData->uiTitle.isNotEmpty())
7343 uiTitle = pData->uiTitle;
7345 else
7347 uiTitle = pData->name;
7348 uiTitle += " (GUI)";
7351 fLv2Options.windowTitle = uiTitle.releaseBufferPointer();
7354 fLv2Options.opts[CarlaPluginLV2Options::WindowTitle].size = (uint32_t)std::strlen(fLv2Options.windowTitle);
7355 fLv2Options.opts[CarlaPluginLV2Options::WindowTitle].value = fLv2Options.windowTitle;
7357 // ---------------------------------------------------------------
7358 // initialize ui features (part 1)
7360 LV2_Extension_Data_Feature* const uiDataFt = new LV2_Extension_Data_Feature;
7361 uiDataFt->data_access = fDescriptor->extension_data;
7363 LV2UI_Port_Map* const uiPortMapFt = new LV2UI_Port_Map;
7364 uiPortMapFt->handle = this;
7365 uiPortMapFt->port_index = carla_lv2_ui_port_map;
7367 LV2UI_Request_Value* const uiRequestValueFt = new LV2UI_Request_Value;
7368 uiRequestValueFt->handle = this;
7369 uiRequestValueFt->request = carla_lv2_ui_request_value;
7371 LV2UI_Resize* const uiResizeFt = new LV2UI_Resize;
7372 uiResizeFt->handle = this;
7373 uiResizeFt->ui_resize = carla_lv2_ui_resize;
7375 LV2UI_Touch* const uiTouchFt = new LV2UI_Touch;
7376 uiTouchFt->handle = this;
7377 uiTouchFt->touch = carla_lv2_ui_touch;
7379 LV2_External_UI_Host* const uiExternalHostFt = new LV2_External_UI_Host;
7380 uiExternalHostFt->ui_closed = carla_lv2_external_ui_closed;
7381 uiExternalHostFt->plugin_human_id = fLv2Options.windowTitle;
7383 // ---------------------------------------------------------------
7384 // initialize ui features (part 2)
7386 for (uint32_t j=kFeatureCountPlugin; j < kFeatureCountAll; ++j)
7387 fFeatures[j] = new LV2_Feature;
7389 fFeatures[kFeatureIdUiDataAccess]->URI = LV2_DATA_ACCESS_URI;
7390 fFeatures[kFeatureIdUiDataAccess]->data = uiDataFt;
7392 fFeatures[kFeatureIdUiInstanceAccess]->URI = LV2_INSTANCE_ACCESS_URI;
7393 fFeatures[kFeatureIdUiInstanceAccess]->data = fHandle;
7395 fFeatures[kFeatureIdUiIdleInterface]->URI = LV2_UI__idleInterface;
7396 fFeatures[kFeatureIdUiIdleInterface]->data = nullptr;
7398 fFeatures[kFeatureIdUiFixedSize]->URI = LV2_UI__fixedSize;
7399 fFeatures[kFeatureIdUiFixedSize]->data = nullptr;
7401 fFeatures[kFeatureIdUiMakeResident]->URI = LV2_UI__makeResident;
7402 fFeatures[kFeatureIdUiMakeResident]->data = nullptr;
7404 fFeatures[kFeatureIdUiMakeResident2]->URI = LV2_UI__makeSONameResident;
7405 fFeatures[kFeatureIdUiMakeResident2]->data = nullptr;
7407 fFeatures[kFeatureIdUiNoUserResize]->URI = LV2_UI__noUserResize;
7408 fFeatures[kFeatureIdUiNoUserResize]->data = nullptr;
7410 fFeatures[kFeatureIdUiParent]->URI = LV2_UI__parent;
7411 fFeatures[kFeatureIdUiParent]->data = nullptr;
7413 fFeatures[kFeatureIdUiPortMap]->URI = LV2_UI__portMap;
7414 fFeatures[kFeatureIdUiPortMap]->data = uiPortMapFt;
7416 fFeatures[kFeatureIdUiPortSubscribe]->URI = LV2_UI__portSubscribe;
7417 fFeatures[kFeatureIdUiPortSubscribe]->data = nullptr;
7419 fFeatures[kFeatureIdUiRequestValue]->URI = LV2_UI__requestValue;
7420 fFeatures[kFeatureIdUiRequestValue]->data = uiRequestValueFt;
7422 fFeatures[kFeatureIdUiResize]->URI = LV2_UI__resize;
7423 fFeatures[kFeatureIdUiResize]->data = uiResizeFt;
7425 fFeatures[kFeatureIdUiTouch]->URI = LV2_UI__touch;
7426 fFeatures[kFeatureIdUiTouch]->data = uiTouchFt;
7428 fFeatures[kFeatureIdExternalUi]->URI = LV2_EXTERNAL_UI__Host;
7429 fFeatures[kFeatureIdExternalUi]->data = uiExternalHostFt;
7431 fFeatures[kFeatureIdExternalUiOld]->URI = LV2_EXTERNAL_UI_DEPRECATED_URI;
7432 fFeatures[kFeatureIdExternalUiOld]->data = uiExternalHostFt;
7434 // ---------------------------------------------------------------
7435 // initialize ui extensions
7437 if (fUI.descriptor->extension_data == nullptr)
7438 return;
7440 fExt.uiidle = (const LV2UI_Idle_Interface*)fUI.descriptor->extension_data(LV2_UI__idleInterface);
7441 fExt.uishow = (const LV2UI_Show_Interface*)fUI.descriptor->extension_data(LV2_UI__showInterface);
7442 fExt.uiresize = (const LV2UI_Resize*)fUI.descriptor->extension_data(LV2_UI__resize);
7443 fExt.uiprograms = (const LV2_Programs_UI_Interface*)fUI.descriptor->extension_data(LV2_PROGRAMS__UIInterface);
7445 // check if invalid
7446 if (fExt.uiidle != nullptr && fExt.uiidle->idle == nullptr)
7447 fExt.uiidle = nullptr;
7449 if (fExt.uishow != nullptr && (fExt.uishow->show == nullptr || fExt.uishow->hide == nullptr))
7450 fExt.uishow = nullptr;
7452 if (fExt.uiresize != nullptr && fExt.uiresize->ui_resize == nullptr)
7453 fExt.uiresize = nullptr;
7455 if (fExt.uiprograms != nullptr && fExt.uiprograms->select_program == nullptr)
7456 fExt.uiprograms = nullptr;
7458 // don't use uiidle if external
7459 if (fUI.type == UI::TYPE_EXTERNAL)
7460 fExt.uiidle = nullptr;
7463 // -------------------------------------------------------------------
7465 void handleTransferAtom(const uint32_t portIndex, const LV2_Atom* const atom)
7467 CARLA_SAFE_ASSERT_RETURN(atom != nullptr,);
7468 carla_debug("CarlaPluginLV2::handleTransferAtom(%i, %p)", portIndex, atom);
7470 fAtomBufferEvIn.put(atom, portIndex);
7473 void handleUridMap(const LV2_URID urid, const char* const uri)
7475 CARLA_SAFE_ASSERT_RETURN(urid != kUridNull,);
7476 CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0',);
7477 carla_debug("CarlaPluginLV2::handleUridMap(%i v " P_SIZE ", \"%s\")", urid, fCustomURIDs.size()-1, uri);
7479 const std::size_t uriCount(fCustomURIDs.size());
7481 if (urid < uriCount)
7483 const char* const ourURI(carla_lv2_urid_unmap(this, urid));
7484 CARLA_SAFE_ASSERT_RETURN(ourURI != nullptr && ourURI != kUnmapFallback,);
7486 if (std::strcmp(ourURI, uri) != 0)
7488 carla_stderr2("PLUGIN :: wrong URI '%s' vs '%s'", ourURI, uri);
7491 else
7493 CARLA_SAFE_ASSERT_RETURN(urid == uriCount,);
7494 fCustomURIDs.push_back(uri);
7498 // -------------------------------------------------------------------
7500 void writeAtomPath(const char* const path, const LV2_URID urid)
7502 uint8_t atomBuf[4096];
7503 LV2_Atom_Forge atomForge;
7504 initAtomForge(atomForge);
7505 lv2_atom_forge_set_buffer(&atomForge, atomBuf, sizeof(atomBuf));
7507 LV2_Atom_Forge_Frame forgeFrame;
7508 lv2_atom_forge_object(&atomForge, &forgeFrame, kUridNull, kUridPatchSet);
7510 lv2_atom_forge_key(&atomForge, kUridCarlaParameterChange);
7511 lv2_atom_forge_bool(&atomForge, true);
7513 lv2_atom_forge_key(&atomForge, kUridPatchProperty);
7514 lv2_atom_forge_urid(&atomForge, urid);
7516 lv2_atom_forge_key(&atomForge, kUridPatchValue);
7517 lv2_atom_forge_path(&atomForge, path, static_cast<uint32_t>(std::strlen(path))+1);
7519 lv2_atom_forge_pop(&atomForge, &forgeFrame);
7521 LV2_Atom* const atom((LV2_Atom*)atomBuf);
7522 CARLA_SAFE_ASSERT(atom->size < sizeof(atomBuf));
7524 fAtomBufferEvIn.put(atom, fEventsIn.ctrlIndex);
7527 // -------------------------------------------------------------------
7529 private:
7530 LV2_Handle fHandle;
7531 LV2_Handle fHandle2;
7532 LV2_Feature* fFeatures[kFeatureCountAll+1];
7533 LV2_Feature* fStateFeatures[kStateFeatureCountAll+1];
7534 const LV2_Descriptor* fDescriptor;
7535 const LV2_RDF_Descriptor* fRdfDescriptor;
7537 float** fAudioInBuffers;
7538 float** fAudioOutBuffers;
7539 float** fCvInBuffers;
7540 float** fCvOutBuffers;
7541 float* fParamBuffers;
7543 bool fHasLoadDefaultState : 1;
7544 bool fHasThreadSafeRestore : 1;
7545 bool fNeedsFixedBuffers : 1;
7546 bool fNeedsUiClose : 1;
7547 bool fInlineDisplayNeedsRedraw : 1;
7548 int64_t fInlineDisplayLastRedrawTime;
7549 int32_t fLatencyIndex; // -1 if invalid
7550 int fStrictBounds; // -1 unsupported, 0 optional, 1 required
7552 Lv2AtomRingBuffer fAtomBufferEvIn;
7553 Lv2AtomRingBuffer fAtomBufferUiOut;
7554 Lv2AtomRingBuffer fAtomBufferWorkerIn;
7555 Lv2AtomRingBuffer fAtomBufferWorkerResp;
7556 uint8_t* fAtomBufferUiOutTmpData;
7557 uint8_t* fAtomBufferWorkerInTmpData;
7558 LV2_Atom* fAtomBufferRealtime;
7559 uint32_t fAtomBufferRealtimeSize;
7561 CarlaPluginLV2EventData fEventsIn;
7562 CarlaPluginLV2EventData fEventsOut;
7563 CarlaPluginLV2Options fLv2Options;
7564 #ifndef LV2_UIS_ONLY_INPROCESS
7565 CarlaPipeServerLV2 fPipeServer;
7566 #endif
7568 std::vector<std::string> fCustomURIDs;
7570 bool fFirstActive; // first process() call after activate()
7571 void* fLastStateChunk;
7572 EngineTimeInfo fLastTimeInfo;
7574 // if plugin provides path parameter, use it as fake "gui"
7575 CarlaString fFilePathURI;
7577 struct Extensions {
7578 const LV2_Options_Interface* options;
7579 const LV2_State_Interface* state;
7580 const LV2_Worker_Interface* worker;
7581 const LV2_Inline_Display_Interface* inlineDisplay;
7582 const LV2_Midnam_Interface* midnam;
7583 const LV2_Programs_Interface* programs;
7584 const LV2UI_Idle_Interface* uiidle;
7585 const LV2UI_Show_Interface* uishow;
7586 const LV2UI_Resize* uiresize;
7587 const LV2_Programs_UI_Interface* uiprograms;
7589 Extensions()
7590 : options(nullptr),
7591 state(nullptr),
7592 worker(nullptr),
7593 inlineDisplay(nullptr),
7594 midnam(nullptr),
7595 programs(nullptr),
7596 uiidle(nullptr),
7597 uishow(nullptr),
7598 uiresize(nullptr),
7599 uiprograms(nullptr) {}
7601 CARLA_DECLARE_NON_COPYABLE(Extensions);
7602 } fExt;
7604 struct UI {
7605 enum Type {
7606 TYPE_NULL = 0,
7607 #ifndef LV2_UIS_ONLY_INPROCESS
7608 TYPE_BRIDGE,
7609 #endif
7610 TYPE_EMBED,
7611 TYPE_EXTERNAL
7614 Type type;
7615 LV2UI_Handle handle;
7616 LV2UI_Widget widget;
7617 const LV2UI_Descriptor* descriptor;
7618 const LV2_RDF_UI* rdfDescriptor;
7620 bool embedded;
7621 bool fileBrowserOpen;
7622 const char* fileNeededForURI;
7623 CarlaPluginUI* window;
7625 UI()
7626 : type(TYPE_NULL),
7627 handle(nullptr),
7628 widget(nullptr),
7629 descriptor(nullptr),
7630 rdfDescriptor(nullptr),
7631 embedded(false),
7632 fileBrowserOpen(false),
7633 fileNeededForURI(nullptr),
7634 window(nullptr) {}
7636 ~UI()
7638 CARLA_SAFE_ASSERT(handle == nullptr);
7639 CARLA_SAFE_ASSERT(widget == nullptr);
7640 CARLA_SAFE_ASSERT(descriptor == nullptr);
7641 CARLA_SAFE_ASSERT(rdfDescriptor == nullptr);
7642 CARLA_SAFE_ASSERT(! fileBrowserOpen);
7643 CARLA_SAFE_ASSERT(fileNeededForURI == nullptr);
7644 CARLA_SAFE_ASSERT(window == nullptr);
7647 CARLA_DECLARE_NON_COPYABLE(UI);
7648 } fUI;
7650 // -------------------------------------------------------------------
7651 // Event Feature
7653 static uint32_t carla_lv2_event_ref(LV2_Event_Callback_Data callback_data, LV2_Event* event)
7655 CARLA_SAFE_ASSERT_RETURN(callback_data != nullptr, 0);
7656 CARLA_SAFE_ASSERT_RETURN(event != nullptr, 0);
7657 carla_debug("carla_lv2_event_ref(%p, %p)", callback_data, event);
7659 return 0;
7662 static uint32_t carla_lv2_event_unref(LV2_Event_Callback_Data callback_data, LV2_Event* event)
7664 CARLA_SAFE_ASSERT_RETURN(callback_data != nullptr, 0);
7665 CARLA_SAFE_ASSERT_RETURN(event != nullptr, 0);
7666 carla_debug("carla_lv2_event_unref(%p, %p)", callback_data, event);
7668 return 0;
7671 // -------------------------------------------------------------------
7672 // Logs Feature
7674 static int carla_lv2_log_printf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, ...)
7676 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 0);
7677 CARLA_SAFE_ASSERT_RETURN(type != kUridNull, 0);
7678 CARLA_SAFE_ASSERT_RETURN(fmt != nullptr, 0);
7680 #ifndef DEBUG
7681 if (type == kUridLogTrace)
7682 return 0;
7683 #endif
7685 va_list args;
7686 va_start(args, fmt);
7687 const int ret(carla_lv2_log_vprintf(handle, type, fmt, args));
7688 va_end(args);
7690 return ret;
7693 static int carla_lv2_log_vprintf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, va_list ap)
7695 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 0);
7696 CARLA_SAFE_ASSERT_RETURN(type != kUridNull, 0);
7697 CARLA_SAFE_ASSERT_RETURN(fmt != nullptr, 0);
7699 int ret = 0;
7701 switch (type)
7703 case kUridLogError:
7704 std::fprintf(stderr, "\x1b[31m");
7705 ret = std::vfprintf(stderr, fmt, ap);
7706 std::fprintf(stderr, "\x1b[0m");
7707 break;
7709 case kUridLogNote:
7710 ret = std::vfprintf(stdout, fmt, ap);
7711 break;
7713 case kUridLogTrace:
7714 #ifdef DEBUG
7715 std::fprintf(stdout, "\x1b[30;1m");
7716 ret = std::vfprintf(stdout, fmt, ap);
7717 std::fprintf(stdout, "\x1b[0m");
7718 #endif
7719 break;
7721 case kUridLogWarning:
7722 ret = std::vfprintf(stderr, fmt, ap);
7723 break;
7725 default:
7726 break;
7729 return ret;
7732 // -------------------------------------------------------------------
7733 // Programs Feature
7735 static void carla_lv2_program_changed(LV2_Programs_Handle handle, int32_t index)
7737 CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
7738 carla_debug("carla_lv2_program_changed(%p, %i)", handle, index);
7740 ((CarlaPluginLV2*)handle)->handleProgramChanged(index);
7743 // -------------------------------------------------------------------
7744 // Resize Port Feature
7746 static LV2_Resize_Port_Status carla_lv2_resize_port(LV2_Resize_Port_Feature_Data data, uint32_t index, size_t size)
7748 CARLA_SAFE_ASSERT_RETURN(data != nullptr, LV2_RESIZE_PORT_ERR_UNKNOWN);
7749 carla_debug("carla_lv2_program_changed(%p, %i, " P_SIZE ")", data, index, size);
7751 return ((CarlaPluginLV2*)data)->handleResizePort(index, size);
7754 // -------------------------------------------------------------------
7755 // State Feature
7757 static void carla_lv2_state_free_path(LV2_State_Free_Path_Handle handle, char* const path)
7759 CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
7760 carla_debug("carla_lv2_state_free_path(%p, \"%s\")", handle, path);
7762 std::free(path);
7765 static char* carla_lv2_state_make_path_real(LV2_State_Make_Path_Handle handle, const char* path)
7767 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
7768 CARLA_SAFE_ASSERT_RETURN(path != nullptr, nullptr);
7769 carla_debug("carla_lv2_state_make_path_real(%p, \"%s\")", handle, path);
7771 // allow empty paths to mean "current dir"
7772 if (path[0] == '\0')
7773 path = ".";
7775 const File file(((CarlaPluginLV2*)handle)->handleStateMapToAbsolutePath(true, false, false, path));
7776 return file.isNotNull() ? strdup(file.getFullPathName().toRawUTF8()) : nullptr;
7779 static char* carla_lv2_state_make_path_tmp(LV2_State_Make_Path_Handle handle, const char* path)
7781 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
7782 CARLA_SAFE_ASSERT_RETURN(path != nullptr, nullptr);
7783 carla_debug("carla_lv2_state_make_path_tmp(%p, \"%s\")", handle, path);
7785 // allow empty paths to mean "current dir"
7786 if (path[0] == '\0')
7787 path = ".";
7789 const File file(((CarlaPluginLV2*)handle)->handleStateMapToAbsolutePath(true, false, true, path));
7790 return file.isNotNull() ? strdup(file.getFullPathName().toRawUTF8()) : nullptr;
7793 static char* carla_lv2_state_map_to_abstract_path_real(LV2_State_Map_Path_Handle handle, const char* const absolute_path)
7795 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
7796 CARLA_SAFE_ASSERT_RETURN(absolute_path != nullptr, nullptr);
7797 carla_debug("carla_lv2_state_map_to_abstract_path_real(%p, \"%s\")", handle, absolute_path);
7799 // handle invalid empty paths the same way as lilv
7800 if (absolute_path[0] == '\0')
7801 return strdup("");
7803 return ((CarlaPluginLV2*)handle)->handleStateMapToAbstractPath(false, absolute_path);
7806 static char* carla_lv2_state_map_to_abstract_path_tmp(LV2_State_Map_Path_Handle handle, const char* const absolute_path)
7808 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
7809 CARLA_SAFE_ASSERT_RETURN(absolute_path != nullptr, nullptr);
7810 carla_debug("carla_lv2_state_map_to_abstract_path_tmp(%p, \"%s\")", handle, absolute_path);
7812 // handle invalid empty paths the same way as lilv
7813 if (absolute_path[0] == '\0')
7814 return strdup("");
7816 return ((CarlaPluginLV2*)handle)->handleStateMapToAbstractPath(true, absolute_path);
7819 static char* carla_lv2_state_map_to_absolute_path_real(LV2_State_Map_Path_Handle handle, const char* abstract_path)
7821 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
7822 CARLA_SAFE_ASSERT_RETURN(abstract_path != nullptr, nullptr);
7823 carla_debug("carla_lv2_state_map_to_absolute_path_real(%p, \"%s\")", handle, abstract_path);
7825 // allow empty paths to mean "current dir"
7826 if (abstract_path[0] == '\0')
7827 abstract_path = ".";
7829 const File file(((CarlaPluginLV2*)handle)->handleStateMapToAbsolutePath(true, true, false, abstract_path));
7830 return file.isNotNull() ? strdup(file.getFullPathName().toRawUTF8()) : nullptr;
7833 static char* carla_lv2_state_map_to_absolute_path_tmp(LV2_State_Map_Path_Handle handle, const char* abstract_path)
7835 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
7836 CARLA_SAFE_ASSERT_RETURN(abstract_path != nullptr, nullptr);
7837 carla_debug("carla_lv2_state_map_to_absolute_path_tmp(%p, \"%s\")", handle, abstract_path);
7839 // allow empty paths to mean "current dir"
7840 if (abstract_path[0] == '\0')
7841 abstract_path = ".";
7843 const File file(((CarlaPluginLV2*)handle)->handleStateMapToAbsolutePath(true, true, true, abstract_path));
7844 return file.isNotNull() ? strdup(file.getFullPathName().toRawUTF8()) : nullptr;
7847 static LV2_State_Status carla_lv2_state_store(LV2_State_Handle handle, uint32_t key, const void* value, size_t size, uint32_t type, uint32_t flags)
7849 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2_STATE_ERR_UNKNOWN);
7850 carla_debug("carla_lv2_state_store(%p, %i, %p, " P_SIZE ", %i, %i)", handle, key, value, size, type, flags);
7852 return ((CarlaPluginLV2*)handle)->handleStateStore(key, value, size, type, flags);
7855 static const void* carla_lv2_state_retrieve(LV2_State_Handle handle, uint32_t key, size_t* size, uint32_t* type, uint32_t* flags)
7857 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
7858 carla_debug("carla_lv2_state_retrieve(%p, %i, %p, %p, %p)", handle, key, size, type, flags);
7860 return ((CarlaPluginLV2*)handle)->handleStateRetrieve(key, size, type, flags);
7863 // -------------------------------------------------------------------
7864 // URI-Map Feature
7866 static uint32_t carla_lv2_uri_to_id(LV2_URI_Map_Callback_Data data, const char* map, const char* uri)
7868 carla_debug("carla_lv2_uri_to_id(%p, \"%s\", \"%s\")", data, map, uri);
7869 return carla_lv2_urid_map((LV2_URID_Map_Handle*)data, uri);
7871 // unused
7872 (void)map;
7875 // -------------------------------------------------------------------
7876 // URID Feature
7878 static LV2_URID carla_lv2_urid_map(LV2_URID_Map_Handle handle, const char* uri)
7880 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, kUridNull);
7881 CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', kUridNull);
7882 carla_debug("carla_lv2_urid_map(%p, \"%s\")", handle, uri);
7884 // Atom types
7885 if (std::strcmp(uri, LV2_ATOM__Blank) == 0)
7886 return kUridAtomBlank;
7887 if (std::strcmp(uri, LV2_ATOM__Bool) == 0)
7888 return kUridAtomBool;
7889 if (std::strcmp(uri, LV2_ATOM__Chunk) == 0)
7890 return kUridAtomChunk;
7891 if (std::strcmp(uri, LV2_ATOM__Double) == 0)
7892 return kUridAtomDouble;
7893 if (std::strcmp(uri, LV2_ATOM__Event) == 0)
7894 return kUridAtomEvent;
7895 if (std::strcmp(uri, LV2_ATOM__Float) == 0)
7896 return kUridAtomFloat;
7897 if (std::strcmp(uri, LV2_ATOM__Int) == 0)
7898 return kUridAtomInt;
7899 if (std::strcmp(uri, LV2_ATOM__Literal) == 0)
7900 return kUridAtomLiteral;
7901 if (std::strcmp(uri, LV2_ATOM__Long) == 0)
7902 return kUridAtomLong;
7903 if (std::strcmp(uri, LV2_ATOM__Number) == 0)
7904 return kUridAtomNumber;
7905 if (std::strcmp(uri, LV2_ATOM__Object) == 0)
7906 return kUridAtomObject;
7907 if (std::strcmp(uri, LV2_ATOM__Path) == 0)
7908 return kUridAtomPath;
7909 if (std::strcmp(uri, LV2_ATOM__Property) == 0)
7910 return kUridAtomProperty;
7911 if (std::strcmp(uri, LV2_ATOM__Resource) == 0)
7912 return kUridAtomResource;
7913 if (std::strcmp(uri, LV2_ATOM__Sequence) == 0)
7914 return kUridAtomSequence;
7915 if (std::strcmp(uri, LV2_ATOM__Sound) == 0)
7916 return kUridAtomSound;
7917 if (std::strcmp(uri, LV2_ATOM__String) == 0)
7918 return kUridAtomString;
7919 if (std::strcmp(uri, LV2_ATOM__Tuple) == 0)
7920 return kUridAtomTuple;
7921 if (std::strcmp(uri, LV2_ATOM__URI) == 0)
7922 return kUridAtomURI;
7923 if (std::strcmp(uri, LV2_ATOM__URID) == 0)
7924 return kUridAtomURID;
7925 if (std::strcmp(uri, LV2_ATOM__Vector) == 0)
7926 return kUridAtomVector;
7927 if (std::strcmp(uri, LV2_ATOM__atomTransfer) == 0)
7928 return kUridAtomTransferAtom;
7929 if (std::strcmp(uri, LV2_ATOM__eventTransfer) == 0)
7930 return kUridAtomTransferEvent;
7932 // BufSize types
7933 if (std::strcmp(uri, LV2_BUF_SIZE__maxBlockLength) == 0)
7934 return kUridBufMaxLength;
7935 if (std::strcmp(uri, LV2_BUF_SIZE__minBlockLength) == 0)
7936 return kUridBufMinLength;
7937 if (std::strcmp(uri, LV2_BUF_SIZE__nominalBlockLength) == 0)
7938 return kUridBufNominalLength;
7939 if (std::strcmp(uri, LV2_BUF_SIZE__sequenceSize) == 0)
7940 return kUridBufSequenceSize;
7942 // Log types
7943 if (std::strcmp(uri, LV2_LOG__Error) == 0)
7944 return kUridLogError;
7945 if (std::strcmp(uri, LV2_LOG__Note) == 0)
7946 return kUridLogNote;
7947 if (std::strcmp(uri, LV2_LOG__Trace) == 0)
7948 return kUridLogTrace;
7949 if (std::strcmp(uri, LV2_LOG__Warning) == 0)
7950 return kUridLogWarning;
7952 // Patch types
7953 if (std::strcmp(uri, LV2_PATCH__Set) == 0)
7954 return kUridPatchSet;
7955 if (std::strcmp(uri, LV2_PATCH__property) == 0)
7956 return kUridPatchProperty;
7957 if (std::strcmp(uri, LV2_PATCH__subject) == 0)
7958 return kUridPatchSubject;
7959 if (std::strcmp(uri, LV2_PATCH__value) == 0)
7960 return kUridPatchValue;
7962 // Time types
7963 if (std::strcmp(uri, LV2_TIME__Position) == 0)
7964 return kUridTimePosition;
7965 if (std::strcmp(uri, LV2_TIME__bar) == 0)
7966 return kUridTimeBar;
7967 if (std::strcmp(uri, LV2_TIME__barBeat) == 0)
7968 return kUridTimeBarBeat;
7969 if (std::strcmp(uri, LV2_TIME__beat) == 0)
7970 return kUridTimeBeat;
7971 if (std::strcmp(uri, LV2_TIME__beatUnit) == 0)
7972 return kUridTimeBeatUnit;
7973 if (std::strcmp(uri, LV2_TIME__beatsPerBar) == 0)
7974 return kUridTimeBeatsPerBar;
7975 if (std::strcmp(uri, LV2_TIME__beatsPerMinute) == 0)
7976 return kUridTimeBeatsPerMinute;
7977 if (std::strcmp(uri, LV2_TIME__frame) == 0)
7978 return kUridTimeFrame;
7979 if (std::strcmp(uri, LV2_TIME__framesPerSecond) == 0)
7980 return kUridTimeFramesPerSecond;
7981 if (std::strcmp(uri, LV2_TIME__speed) == 0)
7982 return kUridTimeSpeed;
7983 if (std::strcmp(uri, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat) == 0)
7984 return kUridTimeTicksPerBeat;
7986 // Others
7987 if (std::strcmp(uri, LV2_MIDI__MidiEvent) == 0)
7988 return kUridMidiEvent;
7989 if (std::strcmp(uri, LV2_PARAMETERS__sampleRate) == 0)
7990 return kUridParamSampleRate;
7991 if (std::strcmp(uri, LV2_UI__backgroundColor) == 0)
7992 return kUridBackgroundColor;
7993 if (std::strcmp(uri, LV2_UI__foregroundColor) == 0)
7994 return kUridForegroundColor;
7995 #ifndef CARLA_OS_MAC
7996 if (std::strcmp(uri, LV2_UI__scaleFactor) == 0)
7997 return kUridScaleFactor;
7998 #endif
7999 if (std::strcmp(uri, LV2_UI__windowTitle) == 0)
8000 return kUridWindowTitle;
8002 // Custom Carla types
8003 if (std::strcmp(uri, URI_CARLA_ATOM_WORKER_IN) == 0)
8004 return kUridCarlaAtomWorkerIn;
8005 if (std::strcmp(uri, URI_CARLA_ATOM_WORKER_RESP) == 0)
8006 return kUridCarlaAtomWorkerResp;
8007 if (std::strcmp(uri, URI_CARLA_PARAMETER_CHANGE) == 0)
8008 return kUridCarlaParameterChange;
8009 if (std::strcmp(uri, LV2_KXSTUDIO_PROPERTIES__TransientWindowId) == 0)
8010 return kUridCarlaTransientWindowId;
8012 // Custom plugin types
8013 return ((CarlaPluginLV2*)handle)->getCustomURID(uri);
8016 static const char* carla_lv2_urid_unmap(LV2_URID_Map_Handle handle, LV2_URID urid)
8018 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
8019 CARLA_SAFE_ASSERT_RETURN(urid != kUridNull, nullptr);
8020 carla_debug("carla_lv2_urid_unmap(%p, %i)", handle, urid);
8022 switch (urid)
8024 // Atom types
8025 case kUridAtomBlank:
8026 return LV2_ATOM__Blank;
8027 case kUridAtomBool:
8028 return LV2_ATOM__Bool;
8029 case kUridAtomChunk:
8030 return LV2_ATOM__Chunk;
8031 case kUridAtomDouble:
8032 return LV2_ATOM__Double;
8033 case kUridAtomEvent:
8034 return LV2_ATOM__Event;
8035 case kUridAtomFloat:
8036 return LV2_ATOM__Float;
8037 case kUridAtomInt:
8038 return LV2_ATOM__Int;
8039 case kUridAtomLiteral:
8040 return LV2_ATOM__Literal;
8041 case kUridAtomLong:
8042 return LV2_ATOM__Long;
8043 case kUridAtomNumber:
8044 return LV2_ATOM__Number;
8045 case kUridAtomObject:
8046 return LV2_ATOM__Object;
8047 case kUridAtomPath:
8048 return LV2_ATOM__Path;
8049 case kUridAtomProperty:
8050 return LV2_ATOM__Property;
8051 case kUridAtomResource:
8052 return LV2_ATOM__Resource;
8053 case kUridAtomSequence:
8054 return LV2_ATOM__Sequence;
8055 case kUridAtomSound:
8056 return LV2_ATOM__Sound;
8057 case kUridAtomString:
8058 return LV2_ATOM__String;
8059 case kUridAtomTuple:
8060 return LV2_ATOM__Tuple;
8061 case kUridAtomURI:
8062 return LV2_ATOM__URI;
8063 case kUridAtomURID:
8064 return LV2_ATOM__URID;
8065 case kUridAtomVector:
8066 return LV2_ATOM__Vector;
8067 case kUridAtomTransferAtom:
8068 return LV2_ATOM__atomTransfer;
8069 case kUridAtomTransferEvent:
8070 return LV2_ATOM__eventTransfer;
8072 // BufSize types
8073 case kUridBufMaxLength:
8074 return LV2_BUF_SIZE__maxBlockLength;
8075 case kUridBufMinLength:
8076 return LV2_BUF_SIZE__minBlockLength;
8077 case kUridBufNominalLength:
8078 return LV2_BUF_SIZE__nominalBlockLength;
8079 case kUridBufSequenceSize:
8080 return LV2_BUF_SIZE__sequenceSize;
8082 // Log types
8083 case kUridLogError:
8084 return LV2_LOG__Error;
8085 case kUridLogNote:
8086 return LV2_LOG__Note;
8087 case kUridLogTrace:
8088 return LV2_LOG__Trace;
8089 case kUridLogWarning:
8090 return LV2_LOG__Warning;
8092 // Patch types
8093 case kUridPatchSet:
8094 return LV2_PATCH__Set;
8095 case kUridPatchProperty:
8096 return LV2_PATCH__property;
8097 case kUridPatchSubject:
8098 return LV2_PATCH__subject;
8099 case kUridPatchValue:
8100 return LV2_PATCH__value;
8102 // Time types
8103 case kUridTimePosition:
8104 return LV2_TIME__Position;
8105 case kUridTimeBar:
8106 return LV2_TIME__bar;
8107 case kUridTimeBarBeat:
8108 return LV2_TIME__barBeat;
8109 case kUridTimeBeat:
8110 return LV2_TIME__beat;
8111 case kUridTimeBeatUnit:
8112 return LV2_TIME__beatUnit;
8113 case kUridTimeBeatsPerBar:
8114 return LV2_TIME__beatsPerBar;
8115 case kUridTimeBeatsPerMinute:
8116 return LV2_TIME__beatsPerMinute;
8117 case kUridTimeFrame:
8118 return LV2_TIME__frame;
8119 case kUridTimeFramesPerSecond:
8120 return LV2_TIME__framesPerSecond;
8121 case kUridTimeSpeed:
8122 return LV2_TIME__speed;
8123 case kUridTimeTicksPerBeat:
8124 return LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat;
8126 // Others
8127 case kUridMidiEvent:
8128 return LV2_MIDI__MidiEvent;
8129 case kUridParamSampleRate:
8130 return LV2_PARAMETERS__sampleRate;
8131 case kUridBackgroundColor:
8132 return LV2_UI__backgroundColor;
8133 case kUridForegroundColor:
8134 return LV2_UI__foregroundColor;
8135 #ifndef CARLA_OS_MAC
8136 case kUridScaleFactor:
8137 return LV2_UI__scaleFactor;
8138 #endif
8139 case kUridWindowTitle:
8140 return LV2_UI__windowTitle;
8142 // Custom Carla types
8143 case kUridCarlaAtomWorkerIn:
8144 return URI_CARLA_ATOM_WORKER_IN;
8145 case kUridCarlaAtomWorkerResp:
8146 return URI_CARLA_ATOM_WORKER_RESP;
8147 case kUridCarlaParameterChange:
8148 return URI_CARLA_PARAMETER_CHANGE;
8149 case kUridCarlaTransientWindowId:
8150 return LV2_KXSTUDIO_PROPERTIES__TransientWindowId;
8153 // Custom plugin types
8154 return ((CarlaPluginLV2*)handle)->getCustomURIDString(urid);
8157 // -------------------------------------------------------------------
8158 // Worker Feature
8160 static LV2_Worker_Status carla_lv2_worker_schedule(LV2_Worker_Schedule_Handle handle, uint32_t size, const void* data)
8162 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2_WORKER_ERR_UNKNOWN);
8163 carla_debug("carla_lv2_worker_schedule(%p, %i, %p)", handle, size, data);
8165 return ((CarlaPluginLV2*)handle)->handleWorkerSchedule(size, data);
8168 static LV2_Worker_Status carla_lv2_worker_respond(LV2_Worker_Respond_Handle handle, uint32_t size, const void* data)
8170 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2_WORKER_ERR_UNKNOWN);
8171 carla_debug("carla_lv2_worker_respond(%p, %i, %p)", handle, size, data);
8173 return ((CarlaPluginLV2*)handle)->handleWorkerRespond(size, data);
8176 // -------------------------------------------------------------------
8177 // Inline Display Feature
8179 static void carla_lv2_inline_display_queue_draw(LV2_Inline_Display_Handle handle)
8181 CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
8182 // carla_debug("carla_lv2_inline_display_queue_draw(%p)", handle);
8184 ((CarlaPluginLV2*)handle)->handleInlineDisplayQueueRedraw();
8187 // -------------------------------------------------------------------
8188 // Midnam Feature
8190 static void carla_lv2_midnam_update(LV2_Midnam_Handle handle)
8192 CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
8193 carla_stdout("carla_lv2_midnam_update(%p)", handle);
8195 ((CarlaPluginLV2*)handle)->handleMidnamUpdate();
8198 // -------------------------------------------------------------------
8199 // ControlInputPort change request Feature
8201 static LV2_ControlInputPort_Change_Status carla_lv2_ctrl_in_port_change_req(
8202 LV2_ControlInputPort_Change_Request_Handle handle, uint32_t index, float value)
8204 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2_CONTROL_INPUT_PORT_CHANGE_ERR_UNKNOWN);
8205 carla_stdout("carla_lv2_ctrl_in_port_change_req(%p, %u, %f)", handle, index, value);
8207 return ((CarlaPluginLV2*)handle)->handleCtrlInPortChangeReq(index, value);
8210 // -------------------------------------------------------------------
8211 // External UI Feature
8213 static void carla_lv2_external_ui_closed(LV2UI_Controller controller)
8215 CARLA_SAFE_ASSERT_RETURN(controller != nullptr,);
8216 carla_debug("carla_lv2_external_ui_closed(%p)", controller);
8218 ((CarlaPluginLV2*)controller)->handleExternalUIClosed();
8221 // -------------------------------------------------------------------
8222 // UI Port-Map Feature
8224 static uint32_t carla_lv2_ui_port_map(LV2UI_Feature_Handle handle, const char* symbol)
8226 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2UI_INVALID_PORT_INDEX);
8227 carla_debug("carla_lv2_ui_port_map(%p, \"%s\")", handle, symbol);
8229 return ((CarlaPluginLV2*)handle)->handleUIPortMap(symbol);
8232 // ----------------------------------------------------------------------------------------------------------------
8233 // UI Request Parameter Feature
8235 static LV2UI_Request_Value_Status carla_lv2_ui_request_value(LV2UI_Feature_Handle handle,
8236 LV2_URID key,
8237 LV2_URID type,
8238 const LV2_Feature* const* features)
8240 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2UI_REQUEST_VALUE_ERR_UNKNOWN);
8241 carla_debug("carla_lv2_ui_request_value(%p, %u, %u, %p)", handle, key, type, features);
8243 return ((CarlaPluginLV2*)handle)->handleUIRequestValue(key, type, features);
8246 // -------------------------------------------------------------------
8247 // UI Resize Feature
8249 static int carla_lv2_ui_resize(LV2UI_Feature_Handle handle, int width, int height)
8251 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 1);
8252 carla_debug("carla_lv2_ui_resize(%p, %i, %i)", handle, width, height);
8254 return ((CarlaPluginLV2*)handle)->handleUIResize(width, height);
8257 // -------------------------------------------------------------------
8258 // UI Touch Feature
8260 static void carla_lv2_ui_touch(LV2UI_Feature_Handle handle, uint32_t port_index, bool touch)
8262 CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
8263 carla_debug("carla_lv2_ui_touch(%p, %u, %s)", handle, port_index, bool2str(touch));
8265 ((CarlaPluginLV2*)handle)->handleUITouch(port_index, touch);
8268 // -------------------------------------------------------------------
8269 // UI Extension
8271 static void carla_lv2_ui_write_function(LV2UI_Controller controller, uint32_t port_index, uint32_t buffer_size, uint32_t format, const void* buffer)
8273 CARLA_SAFE_ASSERT_RETURN(controller != nullptr,);
8274 carla_debug("carla_lv2_ui_write_function(%p, %i, %i, %i, %p)", controller, port_index, buffer_size, format, buffer);
8276 ((CarlaPluginLV2*)controller)->handleUIWrite(port_index, buffer_size, format, buffer);
8279 // -------------------------------------------------------------------
8280 // Lilv State
8282 static void carla_lilv_set_port_value(const char* port_symbol, void* user_data, const void* value, uint32_t size, uint32_t type)
8284 CARLA_SAFE_ASSERT_RETURN(user_data != nullptr,);
8285 carla_debug("carla_lilv_set_port_value(\"%s\", %p, %p, %i, %i", port_symbol, user_data, value, size, type);
8287 ((CarlaPluginLV2*)user_data)->handleLilvSetPortValue(port_symbol, value, size, type);
8290 // -------------------------------------------------------------------
8292 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginLV2)
8295 // -------------------------------------------------------------------------------------------------------------------
8297 #ifndef LV2_UIS_ONLY_INPROCESS
8298 bool CarlaPipeServerLV2::msgReceived(const char* const msg) noexcept
8300 if (std::strcmp(msg, "exiting") == 0)
8302 closePipeServer();
8303 fUiState = UiHide;
8304 return true;
8307 if (std::strcmp(msg, "control") == 0)
8309 uint32_t index;
8310 float value;
8312 CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true);
8313 CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true);
8315 try {
8316 kPlugin->handleUIWrite(index, sizeof(float), kUridNull, &value);
8317 } CARLA_SAFE_EXCEPTION("magReceived control");
8319 return true;
8322 if (std::strcmp(msg, "pcontrol") == 0)
8324 const char* uri;
8325 float value;
8327 CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(uri, true), true);
8328 CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true);
8330 try {
8331 kPlugin->handleUIBridgeParameter(uri, value);
8332 } CARLA_SAFE_EXCEPTION("magReceived pcontrol");
8334 return true;
8337 if (std::strcmp(msg, "atom") == 0)
8339 uint32_t index, atomTotalSize, base64Size;
8340 const char* base64atom;
8342 CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true);
8343 CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(atomTotalSize), true);
8344 CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(base64Size), true);
8345 CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(base64atom, false, base64Size), true);
8347 std::vector<uint8_t> chunk(carla_getChunkFromBase64String(base64atom));
8348 CARLA_SAFE_ASSERT_UINT2_RETURN(chunk.size() >= sizeof(LV2_Atom), chunk.size(), sizeof(LV2_Atom), true);
8350 #ifdef CARLA_PROPER_CPP11_SUPPORT
8351 const LV2_Atom* const atom((const LV2_Atom*)chunk.data());
8352 #else
8353 const LV2_Atom* const atom((const LV2_Atom*)&chunk.front());
8354 #endif
8355 CARLA_SAFE_ASSERT_RETURN(lv2_atom_total_size(atom) == chunk.size(), true);
8357 try {
8358 kPlugin->handleUIWrite(index, lv2_atom_total_size(atom), kUridAtomTransferEvent, atom);
8359 } CARLA_SAFE_EXCEPTION("magReceived atom");
8361 return true;
8364 if (std::strcmp(msg, "program") == 0)
8366 uint32_t index;
8368 CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true);
8370 try {
8371 kPlugin->setMidiProgram(static_cast<int32_t>(index), false, true, true, false);
8372 } CARLA_SAFE_EXCEPTION("msgReceived program");
8374 return true;
8377 if (std::strcmp(msg, "urid") == 0)
8379 uint32_t urid, size;
8380 const char* uri;
8382 CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(urid), true);
8383 CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(size), true);
8384 CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(uri, false, size), true);
8386 if (urid != 0)
8388 try {
8389 kPlugin->handleUridMap(urid, uri);
8390 } CARLA_SAFE_EXCEPTION("msgReceived urid");
8393 return true;
8396 if (std::strcmp(msg, "reloadprograms") == 0)
8398 int32_t index;
8400 CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(index), true);
8402 try {
8403 kPlugin->handleProgramChanged(index);
8404 } CARLA_SAFE_EXCEPTION("handleProgramChanged");
8406 return true;
8409 if (std::strcmp(msg, "requestvalue") == 0)
8411 uint32_t key, type;
8413 CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(key), true);
8414 CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(type), true);
8416 if (key != 0)
8418 try {
8419 kPlugin->handleUIRequestValue(key, type, nullptr);
8420 } CARLA_SAFE_EXCEPTION("msgReceived requestvalue");
8423 return true;
8426 return false;
8428 #endif
8430 // -------------------------------------------------------------------------------------------------------------------
8432 CarlaPluginPtr CarlaPlugin::newLV2(const Initializer& init)
8434 carla_debug("CarlaPlugin::newLV2({%p, \"%s\", \"%s\"})", init.engine, init.name, init.label);
8436 std::shared_ptr<CarlaPluginLV2> plugin(new CarlaPluginLV2(init.engine, init.id));
8438 const char* needsArchBridge = nullptr;
8439 if (plugin->init(plugin, init.name, init.label, init.options, needsArchBridge))
8440 return plugin;
8442 #ifndef CARLA_OS_WASM
8443 if (needsArchBridge != nullptr)
8445 CarlaString bridgeBinary(init.engine->getOptions().binaryDir);
8446 bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-native";
8448 return CarlaPlugin::newBridge(init, BINARY_NATIVE, PLUGIN_LV2, needsArchBridge, bridgeBinary);
8450 #endif
8452 return nullptr;
8455 // used in CarlaStandalone.cpp
8456 const void* carla_render_inline_display_lv2(const CarlaPluginPtr& plugin, uint32_t width, uint32_t height);
8458 const void* carla_render_inline_display_lv2(const CarlaPluginPtr& plugin, uint32_t width, uint32_t height)
8460 const std::shared_ptr<CarlaPluginLV2>& lv2Plugin((const std::shared_ptr<CarlaPluginLV2>&)plugin);
8462 return lv2Plugin->renderInlineDisplay(width, height);
8465 // -------------------------------------------------------------------------------------------------------------------
8467 CARLA_BACKEND_END_NAMESPACE