1 /*
2 * Carla LV2 Plugin
3 * Copyright (C) 2011-2021 Filipe Coelho <falktx@falktx.com>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
16 */
17
18 // testing macros
19 // #define LV2_UIS_ONLY_BRIDGES
20 // #define LV2_UIS_ONLY_INPROCESS
21
22 #include "CarlaPluginInternal.hpp"
23 #include "CarlaEngine.hpp"
24
25 #include "CarlaLv2Utils.hpp"
26
27 #include "CarlaBackendUtils.hpp"
28 #include "CarlaBase64Utils.hpp"
29 #include "CarlaEngineUtils.hpp"
30 #include "CarlaPipeUtils.hpp"
31 #include "CarlaPluginUI.hpp"
32 #include "CarlaScopeUtils.hpp"
33 #include "Lv2AtomRingBuffer.hpp"
34
35 #include "../modules/lilv/config/lilv_config.h"
36
37 extern "C" {
38 #include "rtmempool/rtmempool-lv2.h"
39 }
40
41 #include "water/files/File.h"
42 #include "water/misc/Time.h"
43
44 #ifdef CARLA_OS_MAC
45 # include "CarlaMacUtils.hpp"
46 # if defined(CARLA_OS_64BIT) && defined(HAVE_LIBMAGIC) && ! defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
47 # define ADAPT_FOR_APPLE_SILLICON
48 # include "CarlaBinaryUtils.hpp"
49 # endif
50 #endif
51
52 #include <string>
53 #include <vector>
54
55 using water::File;
56
57 #define URI_CARLA_ATOM_WORKER_IN "http://kxstudio.sf.net/ns/carla/atomWorkerIn"
58 #define URI_CARLA_ATOM_WORKER_RESP "http://kxstudio.sf.net/ns/carla/atomWorkerResp"
59 #define URI_CARLA_PARAMETER_CHANGE "http://kxstudio.sf.net/ns/carla/parameterChange"
60
61 CARLA_BACKEND_START_NAMESPACE
62
63 // -------------------------------------------------------------------------------------------------------------------
64 // Fallback data
65
66 static const CustomData kCustomDataFallback = { nullptr, nullptr, nullptr };
67 static /* */ CustomData kCustomDataFallbackNC = { nullptr, nullptr, nullptr };
68 static const ExternalMidiNote kExternalMidiNoteFallback = { -1, 0, 0 };
69 static const char* const kUnmapFallback = "urn:null";
70
71 // -------------------------------------------------------------------------------------------------------------------
72
73 // Maximum default buffer size
74 const uint MAX_DEFAULT_BUFFER_SIZE = 8192; // 0x2000
75
76 // Extra Plugin Hints
77 const uint PLUGIN_HAS_EXTENSION_OPTIONS = 0x01000;
78 const uint PLUGIN_HAS_EXTENSION_PROGRAMS = 0x02000;
79 const uint PLUGIN_HAS_EXTENSION_STATE = 0x04000;
80 const uint PLUGIN_HAS_EXTENSION_WORKER = 0x08000;
81 const uint PLUGIN_HAS_EXTENSION_INLINE_DISPLAY = 0x10000;
82 const uint PLUGIN_HAS_EXTENSION_MIDNAM = 0x20000;
83
84 // LV2 Event Data/Types
85 const uint CARLA_EVENT_DATA_ATOM = 0x01;
86 const uint CARLA_EVENT_DATA_EVENT = 0x02;
87 const uint CARLA_EVENT_DATA_MIDI_LL = 0x04;
88 const uint CARLA_EVENT_TYPE_MESSAGE = 0x10; // unused
89 const uint CARLA_EVENT_TYPE_MIDI = 0x20;
90 const uint CARLA_EVENT_TYPE_TIME = 0x40;
91
92 // LV2 URI Map Ids
93 enum CarlaLv2URIDs {
94 kUridNull = 0,
95 kUridAtomBlank,
96 kUridAtomBool,
97 kUridAtomChunk,
98 kUridAtomDouble,
99 kUridAtomEvent,
100 kUridAtomFloat,
101 kUridAtomInt,
102 kUridAtomLiteral,
103 kUridAtomLong,
104 kUridAtomNumber,
105 kUridAtomObject,
106 kUridAtomPath,
107 kUridAtomProperty,
108 kUridAtomResource,
109 kUridAtomSequence,
110 kUridAtomSound,
111 kUridAtomString,
112 kUridAtomTuple,
113 kUridAtomURI,
114 kUridAtomURID,
115 kUridAtomVector,
116 kUridAtomTransferAtom,
117 kUridAtomTransferEvent,
118 kUridBufMaxLength,
119 kUridBufMinLength,
120 kUridBufNominalLength,
121 kUridBufSequenceSize,
122 kUridLogError,
123 kUridLogNote,
124 kUridLogTrace,
125 kUridLogWarning,
126 kUridPatchSet,
127 kUridPatchProperty,
128 kUridPatchSubject,
129 kUridPatchValue,
130 // time base type
131 kUridTimePosition,
132 // time values
133 kUridTimeBar,
134 kUridTimeBarBeat,
135 kUridTimeBeat,
136 kUridTimeBeatUnit,
137 kUridTimeBeatsPerBar,
138 kUridTimeBeatsPerMinute,
139 kUridTimeFrame,
140 kUridTimeFramesPerSecond,
141 kUridTimeSpeed,
142 kUridTimeTicksPerBeat,
143 kUridMidiEvent,
144 kUridParamSampleRate,
145 // ui stuff
146 kUridBackgroundColor,
147 kUridForegroundColor,
148 kUridScaleFactor,
149 kUridWindowTitle,
150 // custom carla props
151 kUridCarlaAtomWorkerIn,
152 kUridCarlaAtomWorkerResp,
153 kUridCarlaParameterChange,
154 kUridCarlaTransientWindowId,
155 // count
156 kUridCount
157 };
158
159 // LV2 Feature Ids
160 enum CarlaLv2Features {
161 // DSP features
162 kFeatureIdBufSizeBounded = 0,
163 kFeatureIdBufSizeFixed,
164 kFeatureIdBufSizePowerOf2,
165 kFeatureIdEvent,
166 kFeatureIdHardRtCapable,
167 kFeatureIdInPlaceBroken,
168 kFeatureIdIsLive,
169 kFeatureIdLogs,
170 kFeatureIdOptions,
171 kFeatureIdPrograms,
172 kFeatureIdResizePort,
173 kFeatureIdRtMemPool,
174 kFeatureIdRtMemPoolOld,
175 kFeatureIdStateFreePath,
176 kFeatureIdStateMakePath,
177 kFeatureIdStateMapPath,
178 kFeatureIdStrictBounds,
179 kFeatureIdUriMap,
180 kFeatureIdUridMap,
181 kFeatureIdUridUnmap,
182 kFeatureIdWorker,
183 kFeatureIdInlineDisplay,
184 kFeatureIdMidnam,
185 kFeatureCountPlugin,
186 // UI features
187 kFeatureIdUiDataAccess = kFeatureCountPlugin,
188 kFeatureIdUiInstanceAccess,
189 kFeatureIdUiIdleInterface,
190 kFeatureIdUiFixedSize,
191 kFeatureIdUiMakeResident,
192 kFeatureIdUiMakeResident2,
193 kFeatureIdUiNoUserResize,
194 kFeatureIdUiParent,
195 kFeatureIdUiPortMap,
196 kFeatureIdUiPortSubscribe,
197 kFeatureIdUiResize,
198 kFeatureIdUiRequestValue,
199 kFeatureIdUiTouch,
200 kFeatureIdExternalUi,
201 kFeatureIdExternalUiOld,
202 kFeatureCountAll
203 };
204
205 // LV2 Feature Ids (special state handlers)
206 enum CarlaLv2StateFeatures {
207 kStateFeatureIdFreePath,
208 kStateFeatureIdMakePath,
209 kStateFeatureIdMapPath,
210 kStateFeatureIdWorker,
211 kStateFeatureCountAll
212 };
213
214 // -------------------------------------------------------------------------------------------------------------------
215
216 struct Lv2EventData {
217 uint32_t type;
218 uint32_t rindex;
219 CarlaEngineEventPort* port;
220
221 union {
222 LV2_Atom_Buffer* atom;
223 LV2_Event_Buffer* event;
224 LV2_MIDI midi;
225 };
226
Lv2EventDataLv2EventData227 Lv2EventData() noexcept
228 : type(0x0),
229 rindex(0),
230 port(nullptr) {}
231
~Lv2EventDataLv2EventData232 ~Lv2EventData() noexcept
233 {
234 if (port != nullptr)
235 {
236 delete port;
237 port = nullptr;
238 }
239
240 const uint32_t rtype(type);
241 type = 0x0;
242
243 if (rtype & CARLA_EVENT_DATA_ATOM)
244 {
245 CARLA_SAFE_ASSERT_RETURN(atom != nullptr,);
246
247 std::free(atom);
248 atom = nullptr;
249 }
250 else if (rtype & CARLA_EVENT_DATA_EVENT)
251 {
252 CARLA_SAFE_ASSERT_RETURN(event != nullptr,);
253
254 std::free(event);
255 event = nullptr;
256 }
257 else if (rtype & CARLA_EVENT_DATA_MIDI_LL)
258 {
259 CARLA_SAFE_ASSERT_RETURN(midi.data != nullptr,);
260
261 delete[] midi.data;
262 midi.data = nullptr;
263 }
264 }
265
266 CARLA_DECLARE_NON_COPY_STRUCT(Lv2EventData)
267 };
268
269 struct CarlaPluginLV2EventData {
270 uint32_t count;
271 Lv2EventData* data;
272 Lv2EventData* ctrl; // default port, either this->data[x] or pData->portIn/Out
273 uint32_t ctrlIndex;
274
CarlaPluginLV2EventDataCarlaPluginLV2EventData275 CarlaPluginLV2EventData() noexcept
276 : count(0),
277 data(nullptr),
278 ctrl(nullptr),
279 ctrlIndex(0) {}
280
~CarlaPluginLV2EventDataCarlaPluginLV2EventData281 ~CarlaPluginLV2EventData() noexcept
282 {
283 CARLA_SAFE_ASSERT_INT(count == 0, count);
284 CARLA_SAFE_ASSERT(data == nullptr);
285 CARLA_SAFE_ASSERT(ctrl == nullptr);
286 CARLA_SAFE_ASSERT_INT(ctrlIndex == 0, ctrlIndex);
287 }
288
createNewCarlaPluginLV2EventData289 void createNew(const uint32_t newCount)
290 {
291 CARLA_SAFE_ASSERT_INT(count == 0, count);
292 CARLA_SAFE_ASSERT_INT(ctrlIndex == 0, ctrlIndex);
293 CARLA_SAFE_ASSERT_RETURN(data == nullptr,);
294 CARLA_SAFE_ASSERT_RETURN(ctrl == nullptr,);
295 CARLA_SAFE_ASSERT_RETURN(newCount > 0,);
296
297 data = new Lv2EventData[newCount];
298 count = newCount;
299
300 ctrl = nullptr;
301 ctrlIndex = 0;
302 }
303
clearCarlaPluginLV2EventData304 void clear(CarlaEngineEventPort* const portToIgnore) noexcept
305 {
306 if (data != nullptr)
307 {
308 for (uint32_t i=0; i < count; ++i)
309 {
310 if (data[i].port != nullptr)
311 {
312 if (data[i].port != portToIgnore)
313 delete data[i].port;
314 data[i].port = nullptr;
315 }
316 }
317
318 delete[] data;
319 data = nullptr;
320 }
321
322 count = 0;
323
324 ctrl = nullptr;
325 ctrlIndex = 0;
326 }
327
initBuffersCarlaPluginLV2EventData328 void initBuffers() const noexcept
329 {
330 for (uint32_t i=0; i < count; ++i)
331 {
332 if (data[i].port != nullptr && (ctrl == nullptr || data[i].port != ctrl->port))
333 data[i].port->initBuffer();
334 }
335 }
336
337 CARLA_DECLARE_NON_COPY_STRUCT(CarlaPluginLV2EventData)
338 };
339
340 // -------------------------------------------------------------------------------------------------------------------
341
342 struct CarlaPluginLV2Options {
343 enum OptIndex {
344 MaxBlockLenth = 0,
345 MinBlockLenth,
346 NominalBlockLenth,
347 SequenceSize,
348 SampleRate,
349 TransientWinId,
350 BackgroundColor,
351 ForegroundColor,
352 ScaleFactor,
353 WindowTitle,
354 Null,
355 Count
356 };
357
358 int maxBufferSize;
359 int minBufferSize;
360 int nominalBufferSize;
361 int sequenceSize;
362 float sampleRate;
363 int64_t transientWinId;
364 uint32_t bgColor;
365 uint32_t fgColor;
366 float uiScale;
367 const char* windowTitle;
368 LV2_Options_Option opts[Count];
369
CarlaPluginLV2OptionsCarlaPluginLV2Options370 CarlaPluginLV2Options() noexcept
371 : maxBufferSize(0),
372 minBufferSize(0),
373 nominalBufferSize(0),
374 sequenceSize(MAX_DEFAULT_BUFFER_SIZE),
375 sampleRate(0.0),
376 transientWinId(0),
377 bgColor(0x000000ff),
378 fgColor(0xffffffff),
379 uiScale(1.0f),
380 windowTitle(nullptr)
381 {
382 LV2_Options_Option& optMaxBlockLenth(opts[MaxBlockLenth]);
383 optMaxBlockLenth.context = LV2_OPTIONS_INSTANCE;
384 optMaxBlockLenth.subject = 0;
385 optMaxBlockLenth.key = kUridBufMaxLength;
386 optMaxBlockLenth.size = sizeof(int);
387 optMaxBlockLenth.type = kUridAtomInt;
388 optMaxBlockLenth.value = &maxBufferSize;
389
390 LV2_Options_Option& optMinBlockLenth(opts[MinBlockLenth]);
391 optMinBlockLenth.context = LV2_OPTIONS_INSTANCE;
392 optMinBlockLenth.subject = 0;
393 optMinBlockLenth.key = kUridBufMinLength;
394 optMinBlockLenth.size = sizeof(int);
395 optMinBlockLenth.type = kUridAtomInt;
396 optMinBlockLenth.value = &minBufferSize;
397
398 LV2_Options_Option& optNominalBlockLenth(opts[NominalBlockLenth]);
399 optNominalBlockLenth.context = LV2_OPTIONS_INSTANCE;
400 optNominalBlockLenth.subject = 0;
401 optNominalBlockLenth.key = kUridBufNominalLength;
402 optNominalBlockLenth.size = sizeof(int);
403 optNominalBlockLenth.type = kUridAtomInt;
404 optNominalBlockLenth.value = &nominalBufferSize;
405
406 LV2_Options_Option& optSequenceSize(opts[SequenceSize]);
407 optSequenceSize.context = LV2_OPTIONS_INSTANCE;
408 optSequenceSize.subject = 0;
409 optSequenceSize.key = kUridBufSequenceSize;
410 optSequenceSize.size = sizeof(int);
411 optSequenceSize.type = kUridAtomInt;
412 optSequenceSize.value = &sequenceSize;
413
414 LV2_Options_Option& optBackgroundColor(opts[BackgroundColor]);
415 optBackgroundColor.context = LV2_OPTIONS_INSTANCE;
416 optBackgroundColor.subject = 0;
417 optBackgroundColor.key = kUridBackgroundColor;
418 optBackgroundColor.size = sizeof(int32_t);
419 optBackgroundColor.type = kUridAtomInt;
420 optBackgroundColor.value = &bgColor;
421
422 LV2_Options_Option& optForegroundColor(opts[ForegroundColor]);
423 optForegroundColor.context = LV2_OPTIONS_INSTANCE;
424 optForegroundColor.subject = 0;
425 optForegroundColor.key = kUridForegroundColor;
426 optForegroundColor.size = sizeof(int32_t);
427 optForegroundColor.type = kUridAtomInt;
428 optForegroundColor.value = &fgColor;
429
430 LV2_Options_Option& optScaleFactor(opts[ScaleFactor]);
431 optScaleFactor.context = LV2_OPTIONS_INSTANCE;
432 optScaleFactor.subject = 0;
433 optScaleFactor.key = kUridScaleFactor;
434 optScaleFactor.size = sizeof(float);
435 optScaleFactor.type = kUridAtomFloat;
436 optScaleFactor.value = &uiScale;
437
438 LV2_Options_Option& optSampleRate(opts[SampleRate]);
439 optSampleRate.context = LV2_OPTIONS_INSTANCE;
440 optSampleRate.subject = 0;
441 optSampleRate.key = kUridParamSampleRate;
442 optSampleRate.size = sizeof(float);
443 optSampleRate.type = kUridAtomFloat;
444 optSampleRate.value = &sampleRate;
445
446 LV2_Options_Option& optTransientWinId(opts[TransientWinId]);
447 optTransientWinId.context = LV2_OPTIONS_INSTANCE;
448 optTransientWinId.subject = 0;
449 optTransientWinId.key = kUridCarlaTransientWindowId;
450 optTransientWinId.size = sizeof(int64_t);
451 optTransientWinId.type = kUridAtomLong;
452 optTransientWinId.value = &transientWinId;
453
454 LV2_Options_Option& optWindowTitle(opts[WindowTitle]);
455 optWindowTitle.context = LV2_OPTIONS_INSTANCE;
456 optWindowTitle.subject = 0;
457 optWindowTitle.key = kUridWindowTitle;
458 optWindowTitle.size = 0;
459 optWindowTitle.type = kUridAtomString;
460 optWindowTitle.value = nullptr;
461
462 LV2_Options_Option& optNull(opts[Null]);
463 optNull.context = LV2_OPTIONS_INSTANCE;
464 optNull.subject = 0;
465 optNull.key = kUridNull;
466 optNull.size = 0;
467 optNull.type = kUridNull;
468 optNull.value = nullptr;
469 }
470
~CarlaPluginLV2OptionsCarlaPluginLV2Options471 ~CarlaPluginLV2Options() noexcept
472 {
473 LV2_Options_Option& optWindowTitle(opts[WindowTitle]);
474
475 optWindowTitle.size = 0;
476 optWindowTitle.value = nullptr;
477
478 if (windowTitle != nullptr)
479 {
480 std::free(const_cast<char*>(windowTitle));
481 windowTitle = nullptr;
482 }
483 }
484
485 CARLA_DECLARE_NON_COPY_STRUCT(CarlaPluginLV2Options);
486 };
487
488 // -------------------------------------------------------------------------------------------------------------------
489
490 class CarlaPluginLV2;
491
492 class CarlaPipeServerLV2 : public CarlaPipeServer
493 {
494 public:
495 enum UiState {
496 UiNone = 0,
497 UiHide,
498 UiShow,
499 UiCrashed
500 };
501
CarlaPipeServerLV2(CarlaEngine * const engine,CarlaPluginLV2 * const plugin)502 CarlaPipeServerLV2(CarlaEngine* const engine, CarlaPluginLV2* const plugin)
503 : kEngine(engine),
504 kPlugin(plugin),
505 fFilename(),
506 fPluginURI(),
507 fUiURI(),
508 fUiState(UiNone) {}
509
~CarlaPipeServerLV2()510 ~CarlaPipeServerLV2() noexcept override
511 {
512 CARLA_SAFE_ASSERT_INT(fUiState == UiNone, fUiState);
513 }
514
getAndResetUiState()515 UiState getAndResetUiState() noexcept
516 {
517 const UiState uiState(fUiState);
518 fUiState = UiNone;
519 return uiState;
520 }
521
setData(const char * const filename,const char * const pluginURI,const char * const uiURI)522 void setData(const char* const filename, const char* const pluginURI, const char* const uiURI) noexcept
523 {
524 fFilename = filename;
525 fPluginURI = pluginURI;
526 fUiURI = uiURI;
527 }
528
startPipeServer(const int size)529 bool startPipeServer(const int size) noexcept
530 {
531 char sampleRateStr[32];
532 {
533 const CarlaScopedLocale csl;
534 std::snprintf(sampleRateStr, 31, "%.12g", kEngine->getSampleRate());
535 }
536 sampleRateStr[31] = '\0';
537
538 const ScopedEngineEnvironmentLocker _seel(kEngine);
539 const CarlaScopedEnvVar _sev1("LV2_PATH", kEngine->getOptions().pathLV2);
540 #ifdef CARLA_OS_LINUX
541 const CarlaScopedEnvVar _sev2("LD_PRELOAD", nullptr);
542 #endif
543 carla_setenv("CARLA_SAMPLE_RATE", sampleRateStr);
544
545 return CarlaPipeServer::startPipeServer(fFilename, fPluginURI, fUiURI, size);
546 }
547
writeUiTitleMessage(const char * const title) const548 void writeUiTitleMessage(const char* const title) const noexcept
549 {
550 CARLA_SAFE_ASSERT_RETURN(title != nullptr && title[0] != '\0',);
551
552 const CarlaMutexLocker cml(getPipeLock());
553
554 if (! _writeMsgBuffer("uiTitle\n", 8))
555 return;
556 if (! writeAndFixMessage(title))
557 return;
558
559 flushMessages();
560 }
561
562 protected:
563 // returns true if msg was handled
564 bool msgReceived(const char* const msg) noexcept override;
565
566 private:
567 CarlaEngine* const kEngine;
568 CarlaPluginLV2* const kPlugin;
569
570 CarlaString fFilename;
571 CarlaString fPluginURI;
572 CarlaString fUiURI;
573 UiState fUiState;
574
575 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPipeServerLV2)
576 };
577
578 // -------------------------------------------------------------------------------------------------------------------
579
initAtomForge(LV2_Atom_Forge & atomForge)580 static void initAtomForge(LV2_Atom_Forge& atomForge) noexcept
581 {
582 carla_zeroStruct(atomForge);
583
584 atomForge.Bool = kUridAtomBool;
585 atomForge.Chunk = kUridAtomChunk;
586 atomForge.Double = kUridAtomDouble;
587 atomForge.Float = kUridAtomFloat;
588 atomForge.Int = kUridAtomInt;
589 atomForge.Literal = kUridAtomLiteral;
590 atomForge.Long = kUridAtomLong;
591 atomForge.Object = kUridAtomObject;
592 atomForge.Path = kUridAtomPath;
593 atomForge.Property = kUridAtomProperty;
594 atomForge.Sequence = kUridAtomSequence;
595 atomForge.String = kUridAtomString;
596 atomForge.Tuple = kUridAtomTuple;
597 atomForge.URI = kUridAtomURI;
598 atomForge.URID = kUridAtomURID;
599 atomForge.Vector = kUridAtomVector;
600
601 #if defined(__clang__)
602 # pragma clang diagnostic push
603 # pragma clang diagnostic ignored "-Wdeprecated-declarations"
604 #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
605 # pragma GCC diagnostic push
606 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
607 #endif
608 atomForge.Blank = kUridAtomBlank;
609 atomForge.Resource = kUridAtomResource;
610 #if defined(__clang__)
611 # pragma clang diagnostic pop
612 #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
613 # pragma GCC diagnostic pop
614 #endif
615 }
616
617 // -------------------------------------------------------------------------------------------------------------------
618
619 class CarlaPluginLV2 : public CarlaPlugin,
620 private CarlaPluginUI::Callback
621 {
622 public:
CarlaPluginLV2(CarlaEngine * const engine,const uint id)623 CarlaPluginLV2(CarlaEngine* const engine, const uint id)
624 : CarlaPlugin(engine, id),
625 fHandle(nullptr),
626 fHandle2(nullptr),
627 fDescriptor(nullptr),
628 fRdfDescriptor(nullptr),
629 fAudioInBuffers(nullptr),
630 fAudioOutBuffers(nullptr),
631 fCvInBuffers(nullptr),
632 fCvOutBuffers(nullptr),
633 fParamBuffers(nullptr),
634 fHasLoadDefaultState(false),
635 fHasThreadSafeRestore(false),
636 fNeedsFixedBuffers(false),
637 fNeedsUiClose(false),
638 fInlineDisplayNeedsRedraw(false),
639 fInlineDisplayLastRedrawTime(0),
640 fLatencyIndex(-1),
641 fStrictBounds(-1),
642 fAtomBufferEvIn(),
643 fAtomBufferUiOut(),
644 fAtomBufferWorkerIn(),
645 fAtomBufferWorkerResp(),
646 fAtomBufferUiOutTmpData(nullptr),
647 fAtomBufferWorkerInTmpData(nullptr),
648 fEventsIn(),
649 fEventsOut(),
650 fLv2Options(),
651 fPipeServer(engine, this),
652 fCustomURIDs(kUridCount, std::string("urn:null")),
653 fFirstActive(true),
654 fLastStateChunk(nullptr),
655 fLastTimeInfo(),
656 fFilePathURI(),
657 fExt(),
658 fUI()
659 {
660 carla_debug("CarlaPluginLV2::CarlaPluginLV2(%p, %i)", engine, id);
661 CARLA_SAFE_ASSERT(fCustomURIDs.size() == kUridCount);
662
663 carla_zeroPointers(fFeatures, kFeatureCountAll+1);
664 carla_zeroPointers(fStateFeatures, kStateFeatureCountAll+1);
665 }
666
~CarlaPluginLV2()667 ~CarlaPluginLV2() override
668 {
669 carla_debug("CarlaPluginLV2::~CarlaPluginLV2()");
670
671 fInlineDisplayNeedsRedraw = false;
672
673 // close UI
674 if (fUI.type != UI::TYPE_NULL)
675 {
676 showCustomUI(false);
677
678 if (fUI.type == UI::TYPE_BRIDGE)
679 {
680 fPipeServer.stopPipeServer(pData->engine->getOptions().uiBridgesTimeout);
681 }
682 else
683 {
684 if (fFeatures[kFeatureIdUiDataAccess] != nullptr && fFeatures[kFeatureIdUiDataAccess]->data != nullptr)
685 delete (LV2_Extension_Data_Feature*)fFeatures[kFeatureIdUiDataAccess]->data;
686
687 if (fFeatures[kFeatureIdUiPortMap] != nullptr && fFeatures[kFeatureIdUiPortMap]->data != nullptr)
688 delete (LV2UI_Port_Map*)fFeatures[kFeatureIdUiPortMap]->data;
689
690 if (fFeatures[kFeatureIdUiRequestValue] != nullptr && fFeatures[kFeatureIdUiRequestValue]->data != nullptr)
691 delete (LV2UI_Request_Value*)fFeatures[kFeatureIdUiRequestValue]->data;
692
693 if (fFeatures[kFeatureIdUiResize] != nullptr && fFeatures[kFeatureIdUiResize]->data != nullptr)
694 delete (LV2UI_Resize*)fFeatures[kFeatureIdUiResize]->data;
695
696 if (fFeatures[kFeatureIdUiTouch] != nullptr && fFeatures[kFeatureIdUiTouch]->data != nullptr)
697 delete (LV2UI_Touch*)fFeatures[kFeatureIdUiTouch]->data;
698
699 if (fFeatures[kFeatureIdExternalUi] != nullptr && fFeatures[kFeatureIdExternalUi]->data != nullptr)
700 delete (LV2_External_UI_Host*)fFeatures[kFeatureIdExternalUi]->data;
701
702 fUI.descriptor = nullptr;
703 pData->uiLibClose();
704 }
705
706 #ifndef LV2_UIS_ONLY_BRIDGES
707 if (fUI.window != nullptr)
708 {
709 delete fUI.window;
710 fUI.window = nullptr;
711 }
712 #endif
713
714 fUI.rdfDescriptor = nullptr;
715 }
716
717 pData->singleMutex.lock();
718 pData->masterMutex.lock();
719
720 if (pData->client != nullptr && pData->client->isActive())
721 pData->client->deactivate(true);
722
723 if (pData->active)
724 {
725 deactivate();
726 pData->active = false;
727 }
728
729 if (fExt.state != nullptr)
730 {
731 const File tmpDir(handleStateMapToAbsolutePath(false, false, true, "."));
732
733 if (tmpDir.exists())
734 tmpDir.deleteRecursively();
735 }
736
737 if (fDescriptor != nullptr)
738 {
739 if (fDescriptor->cleanup != nullptr)
740 {
741 if (fHandle != nullptr)
742 fDescriptor->cleanup(fHandle);
743 if (fHandle2 != nullptr)
744 fDescriptor->cleanup(fHandle2);
745 }
746
747 fHandle = nullptr;
748 fHandle2 = nullptr;
749 fDescriptor = nullptr;
750 }
751
752 if (fRdfDescriptor != nullptr)
753 {
754 delete fRdfDescriptor;
755 fRdfDescriptor = nullptr;
756 }
757
758 if (fFeatures[kFeatureIdEvent] != nullptr && fFeatures[kFeatureIdEvent]->data != nullptr)
759 delete (LV2_Event_Feature*)fFeatures[kFeatureIdEvent]->data;
760
761 if (fFeatures[kFeatureIdLogs] != nullptr && fFeatures[kFeatureIdLogs]->data != nullptr)
762 delete (LV2_Log_Log*)fFeatures[kFeatureIdLogs]->data;
763
764 if (fFeatures[kFeatureIdStateFreePath] != nullptr && fFeatures[kFeatureIdStateFreePath]->data != nullptr)
765 delete (LV2_State_Free_Path*)fFeatures[kFeatureIdStateFreePath]->data;
766
767 if (fFeatures[kFeatureIdStateMakePath] != nullptr && fFeatures[kFeatureIdStateMakePath]->data != nullptr)
768 delete (LV2_State_Make_Path*)fFeatures[kFeatureIdStateMakePath]->data;
769
770 if (fFeatures[kFeatureIdStateMapPath] != nullptr && fFeatures[kFeatureIdStateMapPath]->data != nullptr)
771 delete (LV2_State_Map_Path*)fFeatures[kFeatureIdStateMapPath]->data;
772
773 if (fFeatures[kFeatureIdPrograms] != nullptr && fFeatures[kFeatureIdPrograms]->data != nullptr)
774 delete (LV2_Programs_Host*)fFeatures[kFeatureIdPrograms]->data;
775
776 if (fFeatures[kFeatureIdResizePort] != nullptr && fFeatures[kFeatureIdResizePort]->data != nullptr)
777 delete (LV2_Resize_Port_Resize*)fFeatures[kFeatureIdResizePort]->data;
778
779 if (fFeatures[kFeatureIdRtMemPool] != nullptr && fFeatures[kFeatureIdRtMemPool]->data != nullptr)
780 delete (LV2_RtMemPool_Pool*)fFeatures[kFeatureIdRtMemPool]->data;
781
782 if (fFeatures[kFeatureIdRtMemPoolOld] != nullptr && fFeatures[kFeatureIdRtMemPoolOld]->data != nullptr)
783 delete (LV2_RtMemPool_Pool_Deprecated*)fFeatures[kFeatureIdRtMemPoolOld]->data;
784
785 if (fFeatures[kFeatureIdUriMap] != nullptr && fFeatures[kFeatureIdUriMap]->data != nullptr)
786 delete (LV2_URI_Map_Feature*)fFeatures[kFeatureIdUriMap]->data;
787
788 if (fFeatures[kFeatureIdUridMap] != nullptr && fFeatures[kFeatureIdUridMap]->data != nullptr)
789 delete (LV2_URID_Map*)fFeatures[kFeatureIdUridMap]->data;
790
791 if (fFeatures[kFeatureIdUridUnmap] != nullptr && fFeatures[kFeatureIdUridUnmap]->data != nullptr)
792 delete (LV2_URID_Unmap*)fFeatures[kFeatureIdUridUnmap]->data;
793
794 if (fFeatures[kFeatureIdWorker] != nullptr && fFeatures[kFeatureIdWorker]->data != nullptr)
795 delete (LV2_Worker_Schedule*)fFeatures[kFeatureIdWorker]->data;
796
797 if (fFeatures[kFeatureIdInlineDisplay] != nullptr && fFeatures[kFeatureIdInlineDisplay]->data != nullptr)
798 delete (LV2_Inline_Display*)fFeatures[kFeatureIdInlineDisplay]->data;
799
800 if (fFeatures[kFeatureIdMidnam] != nullptr && fFeatures[kFeatureIdMidnam]->data != nullptr)
801 delete (LV2_Midnam*)fFeatures[kFeatureIdMidnam]->data;
802
803 for (uint32_t i=0; i < kFeatureCountAll; ++i)
804 {
805 if (fFeatures[i] != nullptr)
806 {
807 delete fFeatures[i];
808 fFeatures[i] = nullptr;
809 }
810 }
811
812 if (fStateFeatures[kStateFeatureIdMakePath] != nullptr && fStateFeatures[kStateFeatureIdMakePath]->data != nullptr)
813 delete (LV2_State_Make_Path*)fStateFeatures[kStateFeatureIdMakePath]->data;
814
815 if (fStateFeatures[kStateFeatureIdMapPath] != nullptr && fStateFeatures[kStateFeatureIdMapPath]->data != nullptr)
816 delete (LV2_State_Map_Path*)fStateFeatures[kStateFeatureIdMapPath]->data;
817
818 for (uint32_t i=0; i < kStateFeatureCountAll; ++i)
819 {
820 if (fStateFeatures[i] != nullptr)
821 {
822 delete fStateFeatures[i];
823 fStateFeatures[i] = nullptr;
824 }
825 }
826
827 if (fLastStateChunk != nullptr)
828 {
829 std::free(fLastStateChunk);
830 fLastStateChunk = nullptr;
831 }
832
833 if (fAtomBufferUiOutTmpData != nullptr)
834 {
835 delete[] fAtomBufferUiOutTmpData;
836 fAtomBufferUiOutTmpData = nullptr;
837 }
838
839 if (fAtomBufferWorkerInTmpData != nullptr)
840 {
841 delete[] fAtomBufferWorkerInTmpData;
842 fAtomBufferWorkerInTmpData = nullptr;
843 }
844
845 clearBuffers();
846 }
847
848 // -------------------------------------------------------------------
849 // Information (base)
850
getType() const851 PluginType getType() const noexcept override
852 {
853 return PLUGIN_LV2;
854 }
855
getCategory() const856 PluginCategory getCategory() const noexcept override
857 {
858 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, CarlaPlugin::getCategory());
859
860 const LV2_Property cat1(fRdfDescriptor->Type[0]);
861 const LV2_Property cat2(fRdfDescriptor->Type[1]);
862
863 if (LV2_IS_DELAY(cat1, cat2))
864 return PLUGIN_CATEGORY_DELAY;
865 if (LV2_IS_DISTORTION(cat1, cat2))
866 return PLUGIN_CATEGORY_OTHER;
867 if (LV2_IS_DYNAMICS(cat1, cat2))
868 return PLUGIN_CATEGORY_DYNAMICS;
869 if (LV2_IS_EQ(cat1, cat2))
870 return PLUGIN_CATEGORY_EQ;
871 if (LV2_IS_FILTER(cat1, cat2))
872 return PLUGIN_CATEGORY_FILTER;
873 if (LV2_IS_GENERATOR(cat1, cat2))
874 return PLUGIN_CATEGORY_SYNTH;
875 if (LV2_IS_MODULATOR(cat1, cat2))
876 return PLUGIN_CATEGORY_MODULATOR;
877 if (LV2_IS_REVERB(cat1, cat2))
878 return PLUGIN_CATEGORY_DELAY;
879 if (LV2_IS_SIMULATOR(cat1, cat2))
880 return PLUGIN_CATEGORY_OTHER;
881 if (LV2_IS_SPATIAL(cat1, cat2))
882 return PLUGIN_CATEGORY_OTHER;
883 if (LV2_IS_SPECTRAL(cat1, cat2))
884 return PLUGIN_CATEGORY_UTILITY;
885 if (LV2_IS_UTILITY(cat1, cat2))
886 return PLUGIN_CATEGORY_UTILITY;
887
888 return CarlaPlugin::getCategory();
889 }
890
getLatencyInFrames() const891 uint32_t getLatencyInFrames() const noexcept override
892 {
893 if (fLatencyIndex < 0 || fParamBuffers == nullptr)
894 return 0;
895
896 const float latency(fParamBuffers[fLatencyIndex]);
897 CARLA_SAFE_ASSERT_RETURN(latency >= 0.0f, 0);
898
899 return static_cast<uint32_t>(latency);
900 }
901
902 // -------------------------------------------------------------------
903 // Information (count)
904
getMidiInCount() const905 uint32_t getMidiInCount() const noexcept override
906 {
907 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, 0);
908
909 uint32_t count = 0;
910
911 for (uint32_t i=0; i < fRdfDescriptor->PortCount; ++i)
912 {
913 const LV2_Property portTypes(fRdfDescriptor->Ports[i].Types);
914
915 if (LV2_IS_PORT_INPUT(portTypes) && LV2_PORT_SUPPORTS_MIDI_EVENT(portTypes))
916 ++count;
917 }
918
919 return count;
920 }
921
getMidiOutCount() const922 uint32_t getMidiOutCount() const noexcept override
923 {
924 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, 0);
925
926 uint32_t count = 0;
927
928 for (uint32_t i=0; i < fRdfDescriptor->PortCount; ++i)
929 {
930 const LV2_Property portTypes(fRdfDescriptor->Ports[i].Types);
931
932 if (LV2_IS_PORT_OUTPUT(portTypes) && LV2_PORT_SUPPORTS_MIDI_EVENT(portTypes))
933 ++count;
934 }
935
936 return count;
937 }
938
getParameterScalePointCount(const uint32_t parameterId) const939 uint32_t getParameterScalePointCount(const uint32_t parameterId) const noexcept override
940 {
941 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, 0);
942 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0);
943
944 const int32_t rindex(pData->param.data[parameterId].rindex);
945
946 if (rindex < static_cast<int32_t>(fRdfDescriptor->PortCount))
947 {
948 const LV2_RDF_Port* const port(&fRdfDescriptor->Ports[rindex]);
949 return port->ScalePointCount;
950 }
951
952 return 0;
953 }
954
955 // -------------------------------------------------------------------
956 // Information (current data)
957
958 // nothing
959
960 // -------------------------------------------------------------------
961 // Information (per-plugin data)
962
getOptionsAvailable() const963 uint getOptionsAvailable() const noexcept override
964 {
965 uint options = 0x0;
966
967 // can't disable fixed buffers if using latency or MIDI output
968 if (fLatencyIndex == -1 && getMidiOutCount() == 0 && ! fNeedsFixedBuffers)
969 options |= PLUGIN_OPTION_FIXED_BUFFERS;
970
971 // can't disable forced stereo if enabled in the engine
972 if (pData->engine->getOptions().forceStereo)
973 pass();
974 // if there are event outputs, we can't force stereo
975 else if (fEventsOut.count != 0)
976 pass();
977 // if inputs or outputs are just 1, then yes we can force stereo
978 else if ((pData->audioIn.count == 1 || pData->audioOut.count == 1) || fHandle2 != nullptr)
979 options |= PLUGIN_OPTION_FORCE_STEREO;
980
981 if (fExt.programs != nullptr)
982 options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
983
984 if (getMidiInCount() != 0)
985 {
986 options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
987 options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
988 options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
989 options |= PLUGIN_OPTION_SEND_PITCHBEND;
990 options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
991 options |= PLUGIN_OPTION_SEND_PROGRAM_CHANGES;
992 options |= PLUGIN_OPTION_SKIP_SENDING_NOTES;
993 }
994
995 return options;
996 }
997
getParameterValue(const uint32_t parameterId) const998 float getParameterValue(const uint32_t parameterId) const noexcept override
999 {
1000 CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr, 0.0f);
1001 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f);
1002
1003 if (pData->param.data[parameterId].type == PARAMETER_INPUT)
1004 {
1005 if (pData->param.data[parameterId].hints & PARAMETER_IS_STRICT_BOUNDS)
1006 pData->param.ranges[parameterId].fixValue(fParamBuffers[parameterId]);
1007 }
1008 else
1009 {
1010 if (fStrictBounds >= 0 && (pData->param.data[parameterId].hints & PARAMETER_IS_STRICT_BOUNDS) == 0)
1011 pData->param.ranges[parameterId].fixValue(fParamBuffers[parameterId]);
1012 }
1013
1014 return fParamBuffers[parameterId];
1015 }
1016
getParameterScalePointValue(const uint32_t parameterId,const uint32_t scalePointId) const1017 float getParameterScalePointValue(const uint32_t parameterId, const uint32_t scalePointId) const noexcept override
1018 {
1019 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, 0.0f);
1020 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f);
1021
1022 const int32_t rindex(pData->param.data[parameterId].rindex);
1023
1024 if (rindex < static_cast<int32_t>(fRdfDescriptor->PortCount))
1025 {
1026 const LV2_RDF_Port* const port(&fRdfDescriptor->Ports[rindex]);
1027 CARLA_SAFE_ASSERT_RETURN(scalePointId < port->ScalePointCount, 0.0f);
1028
1029 const LV2_RDF_PortScalePoint* const portScalePoint(&port->ScalePoints[scalePointId]);
1030 return portScalePoint->Value;
1031 }
1032
1033 return 0.0f;
1034 }
1035
getLabel(char * const strBuf) const1036 bool getLabel(char* const strBuf) const noexcept override
1037 {
1038 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
1039 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor->URI != nullptr, false);
1040
1041 std::strncpy(strBuf, fRdfDescriptor->URI, STR_MAX);
1042 return true;
1043 }
1044
getMaker(char * const strBuf) const1045 bool getMaker(char* const strBuf) const noexcept override
1046 {
1047 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
1048
1049 if (fRdfDescriptor->Author != nullptr)
1050 {
1051 std::strncpy(strBuf, fRdfDescriptor->Author, STR_MAX);
1052 return true;
1053 }
1054
1055 return false;
1056 }
1057
getCopyright(char * const strBuf) const1058 bool getCopyright(char* const strBuf) const noexcept override
1059 {
1060 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
1061
1062 if (fRdfDescriptor->License != nullptr)
1063 {
1064 std::strncpy(strBuf, fRdfDescriptor->License, STR_MAX);
1065 return true;
1066 }
1067
1068 return false;
1069 }
1070
getRealName(char * const strBuf) const1071 bool getRealName(char* const strBuf) const noexcept override
1072 {
1073 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
1074
1075 if (fRdfDescriptor->Name != nullptr)
1076 {
1077 std::strncpy(strBuf, fRdfDescriptor->Name, STR_MAX);
1078 return true;
1079 }
1080
1081 return false;
1082 }
1083
getParameterName(const uint32_t parameterId,char * const strBuf) const1084 bool getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override
1085 {
1086 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
1087 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
1088
1089 int32_t rindex = pData->param.data[parameterId].rindex;
1090 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
1091
1092 if (rindex < static_cast<int32_t>(fRdfDescriptor->PortCount))
1093 {
1094 std::strncpy(strBuf, fRdfDescriptor->Ports[rindex].Name, STR_MAX);
1095 return true;
1096 }
1097
1098 rindex -= static_cast<int32_t>(fRdfDescriptor->PortCount);
1099
1100 if (rindex < static_cast<int32_t>(fRdfDescriptor->ParameterCount))
1101 {
1102 std::strncpy(strBuf, fRdfDescriptor->Parameters[rindex].Label, STR_MAX);
1103 return true;
1104 }
1105
1106 return CarlaPlugin::getParameterName(parameterId, strBuf);
1107 }
1108
getParameterSymbol(const uint32_t parameterId,char * const strBuf) const1109 bool getParameterSymbol(const uint32_t parameterId, char* const strBuf) const noexcept override
1110 {
1111 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
1112 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
1113
1114 int32_t rindex = pData->param.data[parameterId].rindex;
1115 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
1116
1117 if (rindex < static_cast<int32_t>(fRdfDescriptor->PortCount))
1118 {
1119 std::strncpy(strBuf, fRdfDescriptor->Ports[rindex].Symbol, STR_MAX);
1120 return true;
1121 }
1122
1123 rindex -= static_cast<int32_t>(fRdfDescriptor->PortCount);
1124
1125 if (rindex < static_cast<int32_t>(fRdfDescriptor->ParameterCount))
1126 {
1127 std::strncpy(strBuf, fRdfDescriptor->Parameters[rindex].URI, STR_MAX);
1128 return true;
1129 }
1130
1131 return CarlaPlugin::getParameterSymbol(parameterId, strBuf);
1132 }
1133
getParameterUnit(const uint32_t parameterId,char * const strBuf) const1134 bool getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override
1135 {
1136 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
1137 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
1138
1139 LV2_RDF_PortUnit* portUnit = nullptr;
1140
1141 int32_t rindex = pData->param.data[parameterId].rindex;
1142 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
1143
1144 if (rindex < static_cast<int32_t>(fRdfDescriptor->PortCount))
1145 {
1146 portUnit = &fRdfDescriptor->Ports[rindex].Unit;
1147 }
1148 else
1149 {
1150 rindex -= static_cast<int32_t>(fRdfDescriptor->PortCount);
1151
1152 if (rindex < static_cast<int32_t>(fRdfDescriptor->ParameterCount))
1153 {
1154 portUnit = &fRdfDescriptor->Parameters[rindex].Unit;
1155 }
1156 }
1157
1158 if (portUnit != nullptr)
1159 {
1160 if (LV2_HAVE_PORT_UNIT_SYMBOL(portUnit->Hints) && portUnit->Symbol != nullptr)
1161 {
1162 std::strncpy(strBuf, portUnit->Symbol, STR_MAX);
1163 return true;
1164 }
1165
1166 if (LV2_HAVE_PORT_UNIT_UNIT(portUnit->Hints))
1167 {
1168 switch (portUnit->Unit)
1169 {
1170 case LV2_PORT_UNIT_BAR:
1171 std::strncpy(strBuf, "bars", STR_MAX);
1172 return true;
1173 case LV2_PORT_UNIT_BEAT:
1174 std::strncpy(strBuf, "beats", STR_MAX);
1175 return true;
1176 case LV2_PORT_UNIT_BPM:
1177 std::strncpy(strBuf, "BPM", STR_MAX);
1178 return true;
1179 case LV2_PORT_UNIT_CENT:
1180 std::strncpy(strBuf, "ct", STR_MAX);
1181 return true;
1182 case LV2_PORT_UNIT_CM:
1183 std::strncpy(strBuf, "cm", STR_MAX);
1184 return true;
1185 case LV2_PORT_UNIT_COEF:
1186 std::strncpy(strBuf, "(coef)", STR_MAX);
1187 return true;
1188 case LV2_PORT_UNIT_DB:
1189 std::strncpy(strBuf, "dB", STR_MAX);
1190 return true;
1191 case LV2_PORT_UNIT_DEGREE:
1192 std::strncpy(strBuf, "deg", STR_MAX);
1193 return true;
1194 case LV2_PORT_UNIT_FRAME:
1195 std::strncpy(strBuf, "frames", STR_MAX);
1196 return true;
1197 case LV2_PORT_UNIT_HZ:
1198 std::strncpy(strBuf, "Hz", STR_MAX);
1199 return true;
1200 case LV2_PORT_UNIT_INCH:
1201 std::strncpy(strBuf, "in", STR_MAX);
1202 return true;
1203 case LV2_PORT_UNIT_KHZ:
1204 std::strncpy(strBuf, "kHz", STR_MAX);
1205 return true;
1206 case LV2_PORT_UNIT_KM:
1207 std::strncpy(strBuf, "km", STR_MAX);
1208 return true;
1209 case LV2_PORT_UNIT_M:
1210 std::strncpy(strBuf, "m", STR_MAX);
1211 return true;
1212 case LV2_PORT_UNIT_MHZ:
1213 std::strncpy(strBuf, "MHz", STR_MAX);
1214 return true;
1215 case LV2_PORT_UNIT_MIDINOTE:
1216 std::strncpy(strBuf, "note", STR_MAX);
1217 return true;
1218 case LV2_PORT_UNIT_MILE:
1219 std::strncpy(strBuf, "mi", STR_MAX);
1220 return true;
1221 case LV2_PORT_UNIT_MIN:
1222 std::strncpy(strBuf, "min", STR_MAX);
1223 return true;
1224 case LV2_PORT_UNIT_MM:
1225 std::strncpy(strBuf, "mm", STR_MAX);
1226 return true;
1227 case LV2_PORT_UNIT_MS:
1228 std::strncpy(strBuf, "ms", STR_MAX);
1229 return true;
1230 case LV2_PORT_UNIT_OCT:
1231 std::strncpy(strBuf, "oct", STR_MAX);
1232 return true;
1233 case LV2_PORT_UNIT_PC:
1234 std::strncpy(strBuf, "%", STR_MAX);
1235 return true;
1236 case LV2_PORT_UNIT_S:
1237 std::strncpy(strBuf, "s", STR_MAX);
1238 return true;
1239 case LV2_PORT_UNIT_SEMITONE:
1240 std::strncpy(strBuf, "semi", STR_MAX);
1241 return true;
1242 }
1243 }
1244 }
1245
1246 return CarlaPlugin::getParameterUnit(parameterId, strBuf);
1247 }
1248
getParameterComment(const uint32_t parameterId,char * const strBuf) const1249 bool getParameterComment(const uint32_t parameterId, char* const strBuf) const noexcept override
1250 {
1251 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
1252 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
1253
1254 int32_t rindex = pData->param.data[parameterId].rindex;
1255 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
1256
1257 if (rindex < static_cast<int32_t>(fRdfDescriptor->PortCount))
1258 {
1259 if (const char* const comment = fRdfDescriptor->Ports[rindex].Comment)
1260 {
1261 std::strncpy(strBuf, comment, STR_MAX);
1262 return true;
1263 }
1264 return false;
1265 }
1266
1267 rindex -= static_cast<int32_t>(fRdfDescriptor->PortCount);
1268
1269 if (rindex < static_cast<int32_t>(fRdfDescriptor->ParameterCount))
1270 {
1271 if (const char* const comment = fRdfDescriptor->Parameters[rindex].Comment)
1272 {
1273 std::strncpy(strBuf, comment, STR_MAX);
1274 return true;
1275 }
1276 return false;
1277 }
1278
1279 return CarlaPlugin::getParameterComment(parameterId, strBuf);
1280 }
1281
getParameterGroupName(const uint32_t parameterId,char * const strBuf) const1282 bool getParameterGroupName(const uint32_t parameterId, char* const strBuf) const noexcept override
1283 {
1284 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
1285 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
1286
1287 int32_t rindex = pData->param.data[parameterId].rindex;
1288 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
1289
1290 const char* uri = nullptr;
1291
1292 if (rindex < static_cast<int32_t>(fRdfDescriptor->PortCount))
1293 {
1294 uri = fRdfDescriptor->Ports[rindex].GroupURI;
1295 }
1296 else
1297 {
1298 rindex -= static_cast<int32_t>(fRdfDescriptor->PortCount);
1299
1300 if (rindex < static_cast<int32_t>(fRdfDescriptor->ParameterCount))
1301 uri = fRdfDescriptor->Parameters[rindex].GroupURI;
1302 }
1303
1304 if (uri == nullptr)
1305 return false;
1306
1307 for (uint32_t i=0; i<fRdfDescriptor->PortGroupCount; ++i)
1308 {
1309 if (std::strcmp(fRdfDescriptor->PortGroups[i].URI, uri) == 0)
1310 {
1311 const char* const name = fRdfDescriptor->PortGroups[i].Name;
1312 const char* const symbol = fRdfDescriptor->PortGroups[i].Symbol;
1313
1314 if (name != nullptr && symbol != nullptr)
1315 {
1316 std::snprintf(strBuf, STR_MAX, "%s:%s", symbol, name);
1317 return true;
1318 }
1319 return false;
1320 }
1321 }
1322
1323 return false;
1324 }
1325
getParameterScalePointLabel(const uint32_t parameterId,const uint32_t scalePointId,char * const strBuf) const1326 bool getParameterScalePointLabel(const uint32_t parameterId, const uint32_t scalePointId, char* const strBuf) const noexcept override
1327 {
1328 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
1329 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
1330
1331 const int32_t rindex(pData->param.data[parameterId].rindex);
1332 CARLA_SAFE_ASSERT_RETURN(rindex >= 0, false);
1333
1334 if (rindex < static_cast<int32_t>(fRdfDescriptor->PortCount))
1335 {
1336 const LV2_RDF_Port* const port(&fRdfDescriptor->Ports[rindex]);
1337 CARLA_SAFE_ASSERT_RETURN(scalePointId < port->ScalePointCount, false);
1338
1339 const LV2_RDF_PortScalePoint* const portScalePoint(&port->ScalePoints[scalePointId]);
1340
1341 if (portScalePoint->Label != nullptr)
1342 {
1343 std::strncpy(strBuf, portScalePoint->Label, STR_MAX);
1344 return true;
1345 }
1346 }
1347
1348 return CarlaPlugin::getParameterScalePointLabel(parameterId, scalePointId, strBuf);
1349 }
1350
1351 // -------------------------------------------------------------------
1352 // Set data (state)
1353
prepareForSave(const bool temporary)1354 void prepareForSave(const bool temporary) override
1355 {
1356 CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
1357
1358 if (fExt.state != nullptr && fExt.state->save != nullptr)
1359 {
1360 // move temporary stuff to main state dir on full save
1361 if (! temporary)
1362 {
1363 const File tmpDir(handleStateMapToAbsolutePath(false, false, true, "."));
1364
1365 if (tmpDir.exists())
1366 {
1367 const File stateDir(handleStateMapToAbsolutePath(true, false, false, "."));
1368
1369 if (stateDir.isNotNull())
1370 tmpDir.moveFileTo(stateDir);
1371 }
1372 }
1373
1374 fExt.state->save(fHandle, carla_lv2_state_store, this, LV2_STATE_IS_POD, fStateFeatures);
1375
1376 if (fHandle2 != nullptr)
1377 fExt.state->save(fHandle2, carla_lv2_state_store, this, LV2_STATE_IS_POD, fStateFeatures);
1378 }
1379 }
1380
1381 // -------------------------------------------------------------------
1382 // Set data (internal stuff)
1383
setName(const char * const newName)1384 void setName(const char* const newName) override
1385 {
1386 const File tmpDir1(handleStateMapToAbsolutePath(false, false, true, "."));
1387
1388 CarlaPlugin::setName(newName);
1389
1390 if (tmpDir1.exists())
1391 {
1392 const File tmpDir2(handleStateMapToAbsolutePath(false, false, true, "."));
1393
1394 carla_stdout("dir1 %s, dir2 %s",
1395 tmpDir1.getFullPathName().toRawUTF8(),
1396 tmpDir2.getFullPathName().toRawUTF8());
1397
1398 if (tmpDir2.isNotNull())
1399 {
1400 if (tmpDir2.exists())
1401 tmpDir2.deleteRecursively();
1402
1403 tmpDir1.moveFileTo(tmpDir2);
1404 }
1405 }
1406
1407 if (fLv2Options.windowTitle != nullptr && pData->uiTitle.isEmpty())
1408 setWindowTitle(nullptr);
1409 }
1410
setWindowTitle(const char * const title)1411 void setWindowTitle(const char* const title) noexcept
1412 {
1413 CarlaString uiTitle;
1414
1415 if (title != nullptr)
1416 {
1417 uiTitle = title;
1418 }
1419 else
1420 {
1421 uiTitle = pData->name;
1422 uiTitle += " (GUI)";
1423 }
1424
1425 std::free(const_cast<char*>(fLv2Options.windowTitle));
1426 fLv2Options.windowTitle = uiTitle.releaseBufferPointer();
1427
1428 fLv2Options.opts[CarlaPluginLV2Options::WindowTitle].size = (uint32_t)std::strlen(fLv2Options.windowTitle);
1429 fLv2Options.opts[CarlaPluginLV2Options::WindowTitle].value = fLv2Options.windowTitle;
1430
1431 if (fFeatures[kFeatureIdExternalUi] != nullptr && fFeatures[kFeatureIdExternalUi]->data != nullptr)
1432 ((LV2_External_UI_Host*)fFeatures[kFeatureIdExternalUi]->data)->plugin_human_id = fLv2Options.windowTitle;
1433
1434 if (fPipeServer.isPipeRunning())
1435 fPipeServer.writeUiTitleMessage(fLv2Options.windowTitle);
1436
1437 #ifndef LV2_UIS_ONLY_BRIDGES
1438 if (fUI.window != nullptr)
1439 {
1440 try {
1441 fUI.window->setTitle(fLv2Options.windowTitle);
1442 } CARLA_SAFE_EXCEPTION("set custom title");
1443 }
1444 #endif
1445 }
1446
1447 // -------------------------------------------------------------------
1448 // Set data (plugin-specific stuff)
1449
setParamterValueCommon(const uint32_t parameterId,const float value)1450 float setParamterValueCommon(const uint32_t parameterId, const float value) noexcept
1451 {
1452 const float fixedValue(pData->param.getFixedValue(parameterId, value));
1453 fParamBuffers[parameterId] = fixedValue;
1454
1455 if (pData->param.data[parameterId].rindex >= static_cast<int32_t>(fRdfDescriptor->PortCount))
1456 {
1457 const uint32_t rparamId = static_cast<uint32_t>(pData->param.data[parameterId].rindex) - fRdfDescriptor->PortCount;
1458 CARLA_SAFE_ASSERT_UINT2_RETURN(rparamId < fRdfDescriptor->ParameterCount,
1459 rparamId, fRdfDescriptor->PortCount, fixedValue);
1460
1461 uint8_t atomBuf[256];
1462 LV2_Atom_Forge atomForge;
1463 initAtomForge(atomForge);
1464 lv2_atom_forge_set_buffer(&atomForge, atomBuf, sizeof(atomBuf));
1465
1466 LV2_Atom_Forge_Frame forgeFrame;
1467 lv2_atom_forge_object(&atomForge, &forgeFrame, kUridNull, kUridPatchSet);
1468
1469 lv2_atom_forge_key(&atomForge, kUridCarlaParameterChange);
1470 lv2_atom_forge_bool(&atomForge, true);
1471
1472 lv2_atom_forge_key(&atomForge, kUridPatchProperty);
1473 lv2_atom_forge_urid(&atomForge, getCustomURID(fRdfDescriptor->Parameters[rparamId].URI));
1474
1475 lv2_atom_forge_key(&atomForge, kUridPatchValue);
1476
1477 switch (fRdfDescriptor->Parameters[rparamId].Type)
1478 {
1479 case LV2_PARAMETER_TYPE_BOOL:
1480 lv2_atom_forge_bool(&atomForge, fixedValue > 0.5f);
1481 break;
1482 case LV2_PARAMETER_TYPE_INT:
1483 lv2_atom_forge_int(&atomForge, static_cast<int32_t>(fixedValue + 0.5f));
1484 break;
1485 case LV2_PARAMETER_TYPE_LONG:
1486 lv2_atom_forge_long(&atomForge, static_cast<int64_t>(fixedValue + 0.5f));
1487 break;
1488 case LV2_PARAMETER_TYPE_FLOAT:
1489 lv2_atom_forge_float(&atomForge, fixedValue);
1490 break;
1491 case LV2_PARAMETER_TYPE_DOUBLE:
1492 lv2_atom_forge_double(&atomForge, fixedValue);
1493 break;
1494 default:
1495 carla_stderr2("setParameterValue called for invalid parameter, expect issues!");
1496 break;
1497 }
1498
1499 lv2_atom_forge_pop(&atomForge, &forgeFrame);
1500
1501 LV2_Atom* const atom((LV2_Atom*)atomBuf);
1502 CARLA_SAFE_ASSERT(atom->size < sizeof(atomBuf));
1503
1504 fAtomBufferEvIn.put(atom, fEventsIn.ctrlIndex);
1505 }
1506
1507 return fixedValue;
1508 }
1509
setParameterValue(const uint32_t parameterId,const float value,const bool sendGui,const bool sendOsc,const bool sendCallback)1510 void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
1511 {
1512 CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr,);
1513 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
1514
1515 const float fixedValue = setParamterValueCommon(parameterId, value);
1516
1517 CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback);
1518 }
1519
setParameterValueRT(const uint32_t parameterId,const float value,const bool sendCallbackLater)1520 void setParameterValueRT(const uint32_t parameterId, const float value, const bool sendCallbackLater) noexcept override
1521 {
1522 CARLA_SAFE_ASSERT_RETURN(fParamBuffers != nullptr,);
1523 CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
1524
1525 const float fixedValue = setParamterValueCommon(parameterId, value);
1526
1527 CarlaPlugin::setParameterValueRT(parameterId, fixedValue, sendCallbackLater);
1528 }
1529
setCustomData(const char * const type,const char * const key,const char * const value,const bool sendGui)1530 void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override
1531 {
1532 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
1533 CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
1534 CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',);
1535 CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
1536 CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
1537 carla_debug("CarlaPluginLV2::setCustomData(%s, %s, %s, %s)", type, key, value, bool2str(sendGui));
1538
1539 if (std::strcmp(type, CUSTOM_DATA_TYPE_PROPERTY) == 0)
1540 return CarlaPlugin::setCustomData(type, key, value, sendGui);
1541
1542 // See if this key is from a parameter exposed by carla, apply value if yes
1543 for (uint32_t i=0; i < fRdfDescriptor->ParameterCount; ++i)
1544 {
1545 const LV2_RDF_Parameter& rdfParam(fRdfDescriptor->Parameters[i]);
1546
1547 if (std::strcmp(rdfParam.URI, key) == 0)
1548 {
1549 uint32_t parameterId = UINT32_MAX;
1550 const int32_t rindex = static_cast<int32_t>(fRdfDescriptor->PortCount + i);
1551
1552 switch (rdfParam.Type)
1553 {
1554 case LV2_PARAMETER_TYPE_BOOL:
1555 case LV2_PARAMETER_TYPE_INT:
1556 // case LV2_PARAMETER_TYPE_LONG:
1557 case LV2_PARAMETER_TYPE_FLOAT:
1558 case LV2_PARAMETER_TYPE_DOUBLE:
1559 for (uint32_t j=0; j < pData->param.count; ++j)
1560 {
1561 if (pData->param.data[j].rindex == rindex)
1562 {
1563 parameterId = j;
1564 break;
1565 }
1566 }
1567 break;
1568 }
1569
1570 if (parameterId == UINT32_MAX)
1571 break;
1572
1573 std::vector<uint8_t> chunk(carla_getChunkFromBase64String(value));
1574 CARLA_SAFE_ASSERT_RETURN(chunk.size() > 0,);
1575
1576 #ifdef CARLA_PROPER_CPP11_SUPPORT
1577 const uint8_t* const valueptr = chunk.data();
1578 #else
1579 const uint8_t* const valueptr = &chunk.front();
1580 #endif
1581 float rvalue;
1582
1583 switch (rdfParam.Type)
1584 {
1585 case LV2_PARAMETER_TYPE_BOOL:
1586 rvalue = *(const int32_t*)valueptr != 0 ? 1.0f : 0.0f;
1587 break;
1588 case LV2_PARAMETER_TYPE_INT:
1589 rvalue = static_cast<float>(*(const int32_t*)valueptr);
1590 break;
1591 case LV2_PARAMETER_TYPE_FLOAT:
1592 rvalue = *(const float*)valueptr;
1593 break;
1594 case LV2_PARAMETER_TYPE_DOUBLE:
1595 rvalue = static_cast<float>(*(const double*)valueptr);
1596 break;
1597 default:
1598 // making compilers happy
1599 rvalue = pData->param.ranges[parameterId].def;
1600 break;
1601 }
1602
1603 fParamBuffers[parameterId] = pData->param.getFixedValue(parameterId, rvalue);
1604 break;
1605 }
1606 }
1607
1608 CarlaPlugin::setCustomData(type, key, value, sendGui);
1609 }
1610
setProgram(const int32_t index,const bool sendGui,const bool sendOsc,const bool sendCallback,const bool doingInit)1611 void setProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool doingInit) noexcept override
1612 {
1613 CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
1614 CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->prog.count),);
1615 CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,);
1616
1617 if (index >= 0 && index < static_cast<int32_t>(fRdfDescriptor->PresetCount))
1618 {
1619 const LV2_URID_Map* const uridMap = (const LV2_URID_Map*)fFeatures[kFeatureIdUridMap]->data;
1620
1621 LilvState* const state = Lv2WorldClass::getInstance().getStateFromURI(fRdfDescriptor->Presets[index].URI,
1622 uridMap);
1623 CARLA_SAFE_ASSERT_RETURN(state != nullptr,);
1624
1625 // invalidate midi-program selection
1626 CarlaPlugin::setMidiProgram(-1, false, false, sendCallback, false);
1627
1628 if (fExt.state != nullptr)
1629 {
1630 const bool block = (sendGui || sendOsc || sendCallback) && !fHasThreadSafeRestore;
1631 const ScopedSingleProcessLocker spl(this, block);
1632
1633 lilv_state_restore(state, fExt.state, fHandle, carla_lilv_set_port_value, this, 0, fFeatures);
1634
1635 if (fHandle2 != nullptr)
1636 lilv_state_restore(state, fExt.state, fHandle2, carla_lilv_set_port_value, this, 0, fFeatures);
1637 }
1638 else
1639 {
1640 lilv_state_emit_port_values(state, carla_lilv_set_port_value, this);
1641 }
1642
1643 lilv_state_free(state);
1644 }
1645
1646 CarlaPlugin::setProgram(index, sendGui, sendOsc, sendCallback, doingInit);
1647 }
1648
setMidiProgram(const int32_t index,const bool sendGui,const bool sendOsc,const bool sendCallback,const bool doingInit)1649 void setMidiProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool doingInit) noexcept override
1650 {
1651 CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
1652 CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->midiprog.count),);
1653 CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback || doingInit,);
1654
1655 if (index >= 0 && fExt.programs != nullptr && fExt.programs->select_program != nullptr)
1656 {
1657 const uint32_t bank(pData->midiprog.data[index].bank);
1658 const uint32_t program(pData->midiprog.data[index].program);
1659
1660 const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback));
1661
1662 try {
1663 fExt.programs->select_program(fHandle, bank, program);
1664 } CARLA_SAFE_EXCEPTION("select program");
1665
1666 if (fHandle2 != nullptr)
1667 {
1668 try {
1669 fExt.programs->select_program(fHandle2, bank, program);
1670 } CARLA_SAFE_EXCEPTION("select program 2");
1671 }
1672 }
1673
1674 CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback, doingInit);
1675 }
1676
setMidiProgramRT(const uint32_t uindex,const bool sendCallbackLater)1677 void setMidiProgramRT(const uint32_t uindex, const bool sendCallbackLater) noexcept override
1678 {
1679 CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
1680 CARLA_SAFE_ASSERT_RETURN(uindex < pData->midiprog.count,);
1681
1682 if (fExt.programs != nullptr && fExt.programs->select_program != nullptr)
1683 {
1684 const uint32_t bank(pData->midiprog.data[uindex].bank);
1685 const uint32_t program(pData->midiprog.data[uindex].program);
1686
1687 try {
1688 fExt.programs->select_program(fHandle, bank, program);
1689 } CARLA_SAFE_EXCEPTION("select program RT");
1690
1691 if (fHandle2 != nullptr)
1692 {
1693 try {
1694 fExt.programs->select_program(fHandle2, bank, program);
1695 } CARLA_SAFE_EXCEPTION("select program RT 2");
1696 }
1697 }
1698
1699 CarlaPlugin::setMidiProgramRT(uindex, sendCallbackLater);
1700 }
1701
1702 // -------------------------------------------------------------------
1703 // Set ui stuff
1704
setCustomUITitle(const char * const title)1705 void setCustomUITitle(const char* const title) noexcept override
1706 {
1707 setWindowTitle(title);
1708 CarlaPlugin::setCustomUITitle(title);
1709 }
1710
showCustomUI(const bool yesNo)1711 void showCustomUI(const bool yesNo) override
1712 {
1713 if (fUI.type == UI::TYPE_NULL)
1714 {
1715 if (yesNo && fFilePathURI.isNotEmpty())
1716 {
1717 const char* const path = pData->engine->runFileCallback(FILE_CALLBACK_OPEN, false, "Open File", "");
1718
1719 if (path != nullptr && path[0] != '\0')
1720 {
1721 carla_stdout("LV2 file path to send: '%s'", path);
1722 writeAtomPath(path, getCustomURID(fFilePathURI));
1723 }
1724 }
1725 else
1726 {
1727 CARLA_SAFE_ASSERT(!yesNo);
1728 }
1729 pData->engine->callback(true, true,
1730 ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0, 0.0f, nullptr);
1731 return;
1732 }
1733
1734 const uintptr_t frontendWinId = pData->engine->getOptions().frontendWinId;
1735
1736 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1737 if (! yesNo)
1738 pData->transientTryCounter = 0;
1739 #endif
1740
1741 if (fUI.type == UI::TYPE_BRIDGE)
1742 {
1743 if (yesNo)
1744 {
1745 if (fPipeServer.isPipeRunning())
1746 {
1747 fPipeServer.writeFocusMessage();
1748 return;
1749 }
1750
1751 if (! fPipeServer.startPipeServer(std::min(fLv2Options.sequenceSize, 819200)))
1752 {
1753 pData->engine->callback(true, true,
1754 ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0, 0.0f, nullptr);
1755 return;
1756 }
1757
1758 // manually write messages so we can take the lock for ourselves
1759 {
1760 char tmpBuf[0xff];
1761 tmpBuf[0xfe] = '\0';
1762
1763 const CarlaMutexLocker cml(fPipeServer.getPipeLock());
1764 const CarlaScopedLocale csl;
1765
1766 // write URI mappings
1767 uint32_t u = 0;
1768 for (std::vector<std::string>::iterator it=fCustomURIDs.begin(), end=fCustomURIDs.end(); it != end; ++it, ++u)
1769 {
1770 if (u < kUridCount)
1771 continue;
1772 const std::string& uri(*it);
1773
1774 if (! fPipeServer.writeMessage("urid\n", 5))
1775 return;
1776
1777 std::snprintf(tmpBuf, 0xfe, "%u\n", u);
1778 if (! fPipeServer.writeMessage(tmpBuf))
1779 return;
1780
1781 std::snprintf(tmpBuf, 0xfe, "%lu\n", static_cast<long unsigned>(uri.length()));
1782 if (! fPipeServer.writeMessage(tmpBuf))
1783 return;
1784
1785 if (! fPipeServer.writeAndFixMessage(uri.c_str()))
1786 return;
1787 }
1788
1789 // write UI options
1790 if (! fPipeServer.writeMessage("uiOptions\n", 10))
1791 return;
1792
1793 const EngineOptions& opts(pData->engine->getOptions());
1794
1795 std::snprintf(tmpBuf, 0xff, "%g\n", pData->engine->getSampleRate());
1796 if (! fPipeServer.writeMessage(tmpBuf))
1797 return;
1798
1799 std::snprintf(tmpBuf, 0xff, "%u\n", opts.bgColor);
1800 if (! fPipeServer.writeMessage(tmpBuf))
1801 return;
1802
1803 std::snprintf(tmpBuf, 0xff, "%u\n", opts.fgColor);
1804 if (! fPipeServer.writeMessage(tmpBuf))
1805 return;
1806
1807 std::snprintf(tmpBuf, 0xff, "%.12g\n", static_cast<double>(opts.uiScale));
1808 if (! fPipeServer.writeMessage(tmpBuf))
1809 return;
1810
1811 std::snprintf(tmpBuf, 0xff, "%s\n", bool2str(true)); // useTheme
1812 if (! fPipeServer.writeMessage(tmpBuf))
1813 return;
1814
1815 std::snprintf(tmpBuf, 0xff, "%s\n", bool2str(true)); // useThemeColors
1816 if (! fPipeServer.writeMessage(tmpBuf))
1817 return;
1818
1819 if (! fPipeServer.writeAndFixMessage(fLv2Options.windowTitle != nullptr
1820 ? fLv2Options.windowTitle
1821 : ""))
1822 return;
1823
1824 std::snprintf(tmpBuf, 0xff, P_INTPTR "\n", frontendWinId);
1825 if (! fPipeServer.writeMessage(tmpBuf))
1826 return;
1827
1828 // write parameter values
1829 for (uint32_t i=0; i < pData->param.count; ++i)
1830 {
1831 ParameterData& pdata(pData->param.data[i]);
1832
1833 if (pdata.hints & PARAMETER_IS_NOT_SAVED)
1834 {
1835 int32_t rindex = pdata.rindex;
1836 CARLA_SAFE_ASSERT_CONTINUE(rindex - static_cast<int32_t>(fRdfDescriptor->PortCount) >= 0);
1837
1838 rindex -= static_cast<int32_t>(fRdfDescriptor->PortCount);
1839 CARLA_SAFE_ASSERT_CONTINUE(rindex < static_cast<int32_t>(fRdfDescriptor->ParameterCount));
1840
1841 if (! fPipeServer.writeLv2ParameterMessage(fRdfDescriptor->Parameters[rindex].URI,
1842 getParameterValue(i), false))
1843 return;
1844 }
1845 else
1846 {
1847 if (! fPipeServer.writeControlMessage(static_cast<uint32_t>(pData->param.data[i].rindex),
1848 getParameterValue(i), false))
1849 return;
1850 }
1851 }
1852
1853 // ready to show
1854 if (! fPipeServer.writeMessage("show\n", 5))
1855 return;
1856
1857 fPipeServer.flushMessages();
1858 }
1859
1860 #ifndef BUILD_BRIDGE
1861 if (fUI.rdfDescriptor->Type == LV2_UI_MOD)
1862 pData->tryTransient();
1863 #endif
1864 }
1865 else
1866 {
1867 fPipeServer.stopPipeServer(pData->engine->getOptions().uiBridgesTimeout);
1868 }
1869 return;
1870 }
1871
1872 // take some precautions
1873 CARLA_SAFE_ASSERT_RETURN(fUI.descriptor != nullptr,);
1874 CARLA_SAFE_ASSERT_RETURN(fUI.rdfDescriptor != nullptr,);
1875
1876 if (yesNo)
1877 {
1878 CARLA_SAFE_ASSERT_RETURN(fUI.descriptor->instantiate != nullptr,);
1879 CARLA_SAFE_ASSERT_RETURN(fUI.descriptor->cleanup != nullptr,);
1880 }
1881 else
1882 {
1883 if (fUI.handle == nullptr)
1884 return;
1885 }
1886
1887 if (yesNo)
1888 {
1889 if (fUI.handle == nullptr)
1890 {
1891 #ifndef LV2_UIS_ONLY_BRIDGES
1892 if (fUI.type == UI::TYPE_EMBED && fUI.rdfDescriptor->Type != LV2_UI_NONE && fUI.window == nullptr)
1893 {
1894 const char* msg = nullptr;
1895 const bool isStandalone = pData->engine->getOptions().pluginsAreStandalone;
1896
1897 switch (fUI.rdfDescriptor->Type)
1898 {
1899 case LV2_UI_GTK2:
1900 case LV2_UI_GTK3:
1901 case LV2_UI_QT4:
1902 case LV2_UI_QT5:
1903 case LV2_UI_EXTERNAL:
1904 case LV2_UI_OLD_EXTERNAL:
1905 msg = "Invalid UI type";
1906 break;
1907
1908 case LV2_UI_COCOA:
1909 # ifdef CARLA_OS_MAC
1910 fUI.window = CarlaPluginUI::newCocoa(this, frontendWinId, isStandalone, isUiResizable());
1911 # else
1912 msg = "UI is for MacOS only";
1913 # endif
1914 break;
1915
1916 case LV2_UI_WINDOWS:
1917 # ifdef CARLA_OS_WIN
1918 fUI.window = CarlaPluginUI::newWindows(this, frontendWinId, isStandalone, isUiResizable());
1919 # else
1920 msg = "UI is for Windows only";
1921 # endif
1922 break;
1923
1924 case LV2_UI_X11:
1925 # ifdef HAVE_X11
1926 fUI.window = CarlaPluginUI::newX11(this, frontendWinId, isStandalone, isUiResizable(), true);
1927 # else
1928 msg = "UI is only for systems with X11";
1929 # endif
1930 break;
1931
1932 default:
1933 msg = "Unknown UI type";
1934 break;
1935 }
1936
1937 if (fUI.window == nullptr && fExt.uishow == nullptr)
1938 return pData->engine->callback(true, true,
1939 ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, -1, 0, 0, 0.0f, msg);
1940
1941 if (fUI.window != nullptr)
1942 fFeatures[kFeatureIdUiParent]->data = fUI.window->getPtr();
1943 }
1944 #endif
1945 fUI.widget = nullptr;
1946 fUI.handle = fUI.descriptor->instantiate(fUI.descriptor, fRdfDescriptor->URI, fUI.rdfDescriptor->Bundle,
1947 carla_lv2_ui_write_function, this, &fUI.widget, fFeatures);
1948
1949 if (fUI.window != nullptr)
1950 {
1951 if (fUI.widget != nullptr)
1952 fUI.window->setChildWindow(fUI.widget);
1953 fUI.window->setTitle(fLv2Options.windowTitle);
1954 }
1955 }
1956
1957 CARLA_SAFE_ASSERT(fUI.handle != nullptr);
1958 CARLA_SAFE_ASSERT(fUI.type != UI::TYPE_EXTERNAL || fUI.widget != nullptr);
1959
1960 if (fUI.handle == nullptr || (fUI.type == UI::TYPE_EXTERNAL && fUI.widget == nullptr))
1961 {
1962 fUI.widget = nullptr;
1963
1964 if (fUI.handle != nullptr)
1965 {
1966 fUI.descriptor->cleanup(fUI.handle);
1967 fUI.handle = nullptr;
1968 }
1969
1970 return pData->engine->callback(true, true,
1971 ENGINE_CALLBACK_UI_STATE_CHANGED,
1972 pData->id,
1973 -1,
1974 0, 0, 0.0f,
1975 "Plugin refused to open its own UI");
1976 }
1977
1978 updateUi();
1979
1980 #ifndef LV2_UIS_ONLY_BRIDGES
1981 if (fUI.type == UI::TYPE_EMBED)
1982 {
1983 if (fUI.window != nullptr)
1984 {
1985 fUI.window->show();
1986 }
1987 else if (fExt.uishow != nullptr)
1988 {
1989 fExt.uishow->show(fUI.handle);
1990 # ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1991 pData->tryTransient();
1992 # endif
1993 }
1994 }
1995 else
1996 #endif
1997 {
1998 LV2_EXTERNAL_UI_SHOW((LV2_External_UI_Widget*)fUI.widget);
1999 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
2000 pData->tryTransient();
2001 #endif
2002 }
2003 }
2004 else
2005 {
2006 #ifndef LV2_UIS_ONLY_BRIDGES
2007 if (fUI.type == UI::TYPE_EMBED)
2008 {
2009 if (fUI.window != nullptr)
2010 fUI.window->hide();
2011 else if (fExt.uishow != nullptr)
2012 fExt.uishow->hide(fUI.handle);
2013 }
2014 else
2015 #endif
2016 {
2017 CARLA_SAFE_ASSERT(fUI.widget != nullptr);
2018
2019 if (fUI.widget != nullptr)
2020 LV2_EXTERNAL_UI_HIDE((LV2_External_UI_Widget*)fUI.widget);
2021 }
2022
2023 fUI.descriptor->cleanup(fUI.handle);
2024 fUI.handle = nullptr;
2025 fUI.widget = nullptr;
2026
2027 if (fUI.type == UI::TYPE_EMBED && fUI.window != nullptr)
2028 {
2029 delete fUI.window;
2030 fUI.window = nullptr;
2031 }
2032 }
2033 }
2034
2035 #ifndef LV2_UIS_ONLY_BRIDGES
embedCustomUI(void * const ptr)2036 void* embedCustomUI(void* const ptr) override
2037 {
2038 CARLA_SAFE_ASSERT_RETURN(fUI.type == UI::TYPE_EMBED, nullptr);
2039 CARLA_SAFE_ASSERT_RETURN(fUI.descriptor != nullptr, nullptr);
2040 CARLA_SAFE_ASSERT_RETURN(fUI.descriptor->instantiate != nullptr, nullptr);
2041 CARLA_SAFE_ASSERT_RETURN(fUI.descriptor->cleanup != nullptr, nullptr);
2042 CARLA_SAFE_ASSERT_RETURN(fUI.rdfDescriptor->Type != LV2_UI_NONE, nullptr);
2043 CARLA_SAFE_ASSERT_RETURN(fUI.window == nullptr, nullptr);
2044
2045 fFeatures[kFeatureIdUiParent]->data = ptr;
2046
2047 fUI.embedded = true;
2048 fUI.widget = nullptr;
2049 fUI.handle = fUI.descriptor->instantiate(fUI.descriptor, fRdfDescriptor->URI, fUI.rdfDescriptor->Bundle,
2050 carla_lv2_ui_write_function, this, &fUI.widget, fFeatures);
2051
2052 updateUi();
2053
2054 return fUI.widget;
2055 }
2056 #endif
2057
idle()2058 void idle() override
2059 {
2060 if (fAtomBufferWorkerIn.isDataAvailableForReading())
2061 {
2062 Lv2AtomRingBuffer tmpRingBuffer(fAtomBufferWorkerIn, fAtomBufferWorkerInTmpData);
2063 CARLA_SAFE_ASSERT_RETURN(tmpRingBuffer.isDataAvailableForReading(),);
2064 CARLA_SAFE_ASSERT_RETURN(fExt.worker != nullptr && fExt.worker->work != nullptr,);
2065
2066 uint32_t portIndex;
2067 const LV2_Atom* atom;
2068
2069 for (; tmpRingBuffer.get(atom, portIndex);)
2070 {
2071 CARLA_SAFE_ASSERT_CONTINUE(atom->type == kUridCarlaAtomWorkerIn);
2072 fExt.worker->work(fHandle, carla_lv2_worker_respond, this, atom->size, LV2_ATOM_BODY_CONST(atom));
2073 }
2074 }
2075
2076 if (fInlineDisplayNeedsRedraw)
2077 {
2078 // TESTING
2079 CARLA_SAFE_ASSERT(pData->enabled)
2080 CARLA_SAFE_ASSERT(!pData->engine->isAboutToClose());
2081 CARLA_SAFE_ASSERT(pData->client->isActive());
2082
2083 if (pData->enabled && !pData->engine->isAboutToClose() && pData->client->isActive())
2084 {
2085 const int64_t timeNow = water::Time::currentTimeMillis();
2086
2087 if (timeNow - fInlineDisplayLastRedrawTime > (1000 / 30))
2088 {
2089 fInlineDisplayNeedsRedraw = false;
2090 fInlineDisplayLastRedrawTime = timeNow;
2091 pData->engine->callback(true, true,
2092 ENGINE_CALLBACK_INLINE_DISPLAY_REDRAW,
2093 pData->id,
2094 0, 0, 0, 0.0f, nullptr);
2095 }
2096 }
2097 else
2098 {
2099 fInlineDisplayNeedsRedraw = false;
2100 }
2101 }
2102
2103 CarlaPlugin::idle();
2104 }
2105
uiIdle()2106 void uiIdle() override
2107 {
2108 if (const char* const fileNeededForURI = fUI.fileNeededForURI)
2109 {
2110 fUI.fileBrowserOpen = true;
2111 fUI.fileNeededForURI = nullptr;
2112
2113 const char* const path = pData->engine->runFileCallback(FILE_CALLBACK_OPEN,
2114 /* isDir */ false,
2115 /* title */ "File open",
2116 /* filters */ "");
2117
2118 fUI.fileBrowserOpen = false;
2119
2120 if (path != nullptr)
2121 {
2122 carla_stdout("LV2 requested path to send: '%s'", path);
2123 writeAtomPath(path, getCustomURID(fileNeededForURI));
2124 }
2125
2126 // this function will be called recursively, stop here
2127 return;
2128 }
2129
2130 if (fAtomBufferUiOut.isDataAvailableForReading())
2131 {
2132 Lv2AtomRingBuffer tmpRingBuffer(fAtomBufferUiOut, fAtomBufferUiOutTmpData);
2133 CARLA_SAFE_ASSERT(tmpRingBuffer.isDataAvailableForReading());
2134
2135 uint32_t portIndex;
2136 const LV2_Atom* atom;
2137 const bool hasPortEvent(fUI.handle != nullptr &&
2138 fUI.descriptor != nullptr &&
2139 fUI.descriptor->port_event != nullptr);
2140
2141 for (; tmpRingBuffer.get(atom, portIndex);)
2142 {
2143 if (fUI.type == UI::TYPE_BRIDGE)
2144 {
2145 if (fPipeServer.isPipeRunning())
2146 fPipeServer.writeLv2AtomMessage(portIndex, atom);
2147 }
2148 else
2149 {
2150 if (hasPortEvent && ! fNeedsUiClose)
2151 fUI.descriptor->port_event(fUI.handle, portIndex, lv2_atom_total_size(atom), kUridAtomTransferEvent, atom);
2152 }
2153
2154 inspectAtomForParameterChange(atom);
2155 }
2156 }
2157
2158 if (fPipeServer.isPipeRunning())
2159 {
2160 fPipeServer.idlePipe();
2161
2162 switch (fPipeServer.getAndResetUiState())
2163 {
2164 case CarlaPipeServerLV2::UiNone:
2165 case CarlaPipeServerLV2::UiShow:
2166 break;
2167 case CarlaPipeServerLV2::UiHide:
2168 fPipeServer.stopPipeServer(2000);
2169 // fall through
2170 case CarlaPipeServerLV2::UiCrashed:
2171 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
2172 pData->transientTryCounter = 0;
2173 #endif
2174 pData->engine->callback(true, true,
2175 ENGINE_CALLBACK_UI_STATE_CHANGED,
2176 pData->id,
2177 0,
2178 0, 0, 0.0f, nullptr);
2179 break;
2180 }
2181 }
2182 else
2183 {
2184 // TODO - detect if ui-bridge crashed
2185 }
2186
2187 if (fNeedsUiClose)
2188 {
2189 fNeedsUiClose = false;
2190 showCustomUI(false);
2191 pData->engine->callback(true, true,
2192 ENGINE_CALLBACK_UI_STATE_CHANGED,
2193 pData->id,
2194 0,
2195 0, 0, 0.0f, nullptr);
2196 }
2197 else if (fUI.handle != nullptr && fUI.descriptor != nullptr)
2198 {
2199 if (fUI.type == UI::TYPE_EXTERNAL && fUI.widget != nullptr)
2200 LV2_EXTERNAL_UI_RUN((LV2_External_UI_Widget*)fUI.widget);
2201 #ifndef LV2_UIS_ONLY_BRIDGES
2202 else if (fUI.type == UI::TYPE_EMBED && fUI.window != nullptr)
2203 fUI.window->idle();
2204
2205 // note: UI might have been closed by window idle
2206 if (fNeedsUiClose)
2207 {
2208 pass();
2209 }
2210 else if (fUI.handle != nullptr && fExt.uiidle != nullptr && fExt.uiidle->idle(fUI.handle) != 0)
2211 {
2212 showCustomUI(false);
2213 pData->engine->callback(true, true,
2214 ENGINE_CALLBACK_UI_STATE_CHANGED,
2215 pData->id,
2216 0,
2217 0, 0, 0.0f, nullptr);
2218 CARLA_SAFE_ASSERT(fUI.handle == nullptr);
2219 }
2220 #endif
2221 }
2222
2223 CarlaPlugin::uiIdle();
2224 }
2225
2226 // -------------------------------------------------------------------
2227 // Plugin state
2228
reload()2229 void reload() override
2230 {
2231 CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,);
2232 CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
2233 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
2234 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr,);
2235 carla_debug("CarlaPluginLV2::reload() - start");
2236
2237 const EngineProcessMode processMode(pData->engine->getProccessMode());
2238
2239 // Safely disable plugin for reload
2240 const ScopedDisabler sd(this);
2241
2242 if (pData->active)
2243 deactivate();
2244
2245 clearBuffers();
2246
2247 const float sampleRate(static_cast<float>(pData->engine->getSampleRate()));
2248 const uint32_t portCount(fRdfDescriptor->PortCount);
2249
2250 uint32_t aIns, aOuts, cvIns, cvOuts, params;
2251 aIns = aOuts = cvIns = cvOuts = params = 0;
2252 LinkedList<uint> evIns, evOuts;
2253
2254 const uint32_t eventBufferSize = static_cast<uint32_t>(fLv2Options.sequenceSize) + 0xff;
2255
2256 bool forcedStereoIn, forcedStereoOut;
2257 forcedStereoIn = forcedStereoOut = false;
2258
2259 bool needsCtrlIn, needsCtrlOut, hasPatchParameterOutputs;
2260 needsCtrlIn = needsCtrlOut = hasPatchParameterOutputs = false;
2261
2262 for (uint32_t i=0; i < portCount; ++i)
2263 {
2264 const LV2_Property portTypes(fRdfDescriptor->Ports[i].Types);
2265
2266 if (LV2_IS_PORT_AUDIO(portTypes))
2267 {
2268 if (LV2_IS_PORT_INPUT(portTypes))
2269 aIns += 1;
2270 else if (LV2_IS_PORT_OUTPUT(portTypes))
2271 aOuts += 1;
2272 }
2273 else if (LV2_IS_PORT_CV(portTypes))
2274 {
2275 if (LV2_IS_PORT_INPUT(portTypes))
2276 cvIns += 1;
2277 else if (LV2_IS_PORT_OUTPUT(portTypes))
2278 cvOuts += 1;
2279 }
2280 else if (LV2_IS_PORT_ATOM_SEQUENCE(portTypes))
2281 {
2282 if (LV2_IS_PORT_INPUT(portTypes))
2283 evIns.append(CARLA_EVENT_DATA_ATOM);
2284 else if (LV2_IS_PORT_OUTPUT(portTypes))
2285 evOuts.append(CARLA_EVENT_DATA_ATOM);
2286 }
2287 else if (LV2_IS_PORT_EVENT(portTypes))
2288 {
2289 if (LV2_IS_PORT_INPUT(portTypes))
2290 evIns.append(CARLA_EVENT_DATA_EVENT);
2291 else if (LV2_IS_PORT_OUTPUT(portTypes))
2292 evOuts.append(CARLA_EVENT_DATA_EVENT);
2293 }
2294 else if (LV2_IS_PORT_MIDI_LL(portTypes))
2295 {
2296 if (LV2_IS_PORT_INPUT(portTypes))
2297 evIns.append(CARLA_EVENT_DATA_MIDI_LL);
2298 else if (LV2_IS_PORT_OUTPUT(portTypes))
2299 evOuts.append(CARLA_EVENT_DATA_MIDI_LL);
2300 }
2301 else if (LV2_IS_PORT_CONTROL(portTypes))
2302 params += 1;
2303 }
2304
2305 for (uint32_t i=0; i < fRdfDescriptor->ParameterCount; ++i)
2306 {
2307 switch (fRdfDescriptor->Parameters[i].Type)
2308 {
2309 case LV2_PARAMETER_TYPE_BOOL:
2310 case LV2_PARAMETER_TYPE_INT:
2311 // case LV2_PARAMETER_TYPE_LONG:
2312 case LV2_PARAMETER_TYPE_FLOAT:
2313 case LV2_PARAMETER_TYPE_DOUBLE:
2314 params += 1;
2315 break;
2316 case LV2_PARAMETER_TYPE_PATH:
2317 if (fFilePathURI.isEmpty())
2318 fFilePathURI = fRdfDescriptor->Parameters[i].URI;
2319 break;
2320 }
2321 }
2322
2323 if ((pData->options & PLUGIN_OPTION_FORCE_STEREO) != 0 && aIns <= 1 && aOuts <= 1 && evOuts.count() == 0 && fExt.state == nullptr && fExt.worker == nullptr)
2324 {
2325 if (fHandle2 == nullptr)
2326 {
2327 try {
2328 fHandle2 = fDescriptor->instantiate(fDescriptor, sampleRate, fRdfDescriptor->Bundle, fFeatures);
2329 } catch(...) {}
2330 }
2331
2332 if (fHandle2 != nullptr)
2333 {
2334 if (aIns == 1)
2335 {
2336 aIns = 2;
2337 forcedStereoIn = true;
2338 }
2339
2340 if (aOuts == 1)
2341 {
2342 aOuts = 2;
2343 forcedStereoOut = true;
2344 }
2345 }
2346 }
2347
2348 if (aIns > 0)
2349 {
2350 pData->audioIn.createNew(aIns);
2351 fAudioInBuffers = new float*[aIns];
2352
2353 for (uint32_t i=0; i < aIns; ++i)
2354 fAudioInBuffers[i] = nullptr;
2355 }
2356
2357 if (aOuts > 0)
2358 {
2359 pData->audioOut.createNew(aOuts);
2360 fAudioOutBuffers = new float*[aOuts];
2361 needsCtrlIn = true;
2362
2363 for (uint32_t i=0; i < aOuts; ++i)
2364 fAudioOutBuffers[i] = nullptr;
2365 }
2366
2367 if (cvIns > 0)
2368 {
2369 pData->cvIn.createNew(cvIns);
2370 fCvInBuffers = new float*[cvIns];
2371
2372 for (uint32_t i=0; i < cvIns; ++i)
2373 fCvInBuffers[i] = nullptr;
2374 }
2375
2376 if (cvOuts > 0)
2377 {
2378 pData->cvOut.createNew(cvOuts);
2379 fCvOutBuffers = new float*[cvOuts];
2380
2381 for (uint32_t i=0; i < cvOuts; ++i)
2382 fCvOutBuffers[i] = nullptr;
2383 }
2384
2385 if (params > 0)
2386 {
2387 pData->param.createNew(params, true);
2388 fParamBuffers = new float[params];
2389 carla_zeroFloats(fParamBuffers, params);
2390 }
2391
2392 if (const uint32_t count = static_cast<uint32_t>(evIns.count()))
2393 {
2394 fEventsIn.createNew(count);
2395
2396 for (uint32_t i=0; i < count; ++i)
2397 {
2398 const uint32_t& type(evIns.getAt(i, 0x0));
2399
2400 if (type == CARLA_EVENT_DATA_ATOM)
2401 {
2402 fEventsIn.data[i].type = CARLA_EVENT_DATA_ATOM;
2403 fEventsIn.data[i].atom = lv2_atom_buffer_new(eventBufferSize, kUridNull, kUridAtomSequence, true);
2404 }
2405 else if (type == CARLA_EVENT_DATA_EVENT)
2406 {
2407 fEventsIn.data[i].type = CARLA_EVENT_DATA_EVENT;
2408 fEventsIn.data[i].event = lv2_event_buffer_new(eventBufferSize, LV2_EVENT_AUDIO_STAMP);
2409 }
2410 else if (type == CARLA_EVENT_DATA_MIDI_LL)
2411 {
2412 fEventsIn.data[i].type = CARLA_EVENT_DATA_MIDI_LL;
2413 fEventsIn.data[i].midi.capacity = eventBufferSize;
2414 fEventsIn.data[i].midi.data = new uchar[eventBufferSize];
2415 }
2416 }
2417 }
2418 else
2419 {
2420 fEventsIn.createNew(1);
2421 fEventsIn.ctrl = &fEventsIn.data[0];
2422 }
2423
2424 if (const uint32_t count = static_cast<uint32_t>(evOuts.count()))
2425 {
2426 fEventsOut.createNew(count);
2427
2428 for (uint32_t i=0; i < count; ++i)
2429 {
2430 const uint32_t& type(evOuts.getAt(i, 0x0));
2431
2432 if (type == CARLA_EVENT_DATA_ATOM)
2433 {
2434 fEventsOut.data[i].type = CARLA_EVENT_DATA_ATOM;
2435 fEventsOut.data[i].atom = lv2_atom_buffer_new(eventBufferSize, kUridNull, kUridAtomSequence, false);
2436 }
2437 else if (type == CARLA_EVENT_DATA_EVENT)
2438 {
2439 fEventsOut.data[i].type = CARLA_EVENT_DATA_EVENT;
2440 fEventsOut.data[i].event = lv2_event_buffer_new(eventBufferSize, LV2_EVENT_AUDIO_STAMP);
2441 }
2442 else if (type == CARLA_EVENT_DATA_MIDI_LL)
2443 {
2444 fEventsOut.data[i].type = CARLA_EVENT_DATA_MIDI_LL;
2445 fEventsOut.data[i].midi.capacity = eventBufferSize;
2446 fEventsOut.data[i].midi.data = new uchar[eventBufferSize];
2447 }
2448 }
2449 }
2450
2451 const uint portNameSize(pData->engine->getMaxPortNameSize());
2452 CarlaString portName;
2453 uint32_t iCtrl = 0;
2454
2455 for (uint32_t i=0, iAudioIn=0, iAudioOut=0, iCvIn=0, iCvOut=0, iEvIn=0, iEvOut=0; i < portCount; ++i)
2456 {
2457 const LV2_Property portTypes(fRdfDescriptor->Ports[i].Types);
2458
2459 portName.clear();
2460
2461 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))
2462 {
2463 if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
2464 {
2465 portName = pData->name;
2466 portName += ":";
2467 }
2468
2469 portName += fRdfDescriptor->Ports[i].Name;
2470 portName.truncate(portNameSize);
2471 }
2472
2473 if (LV2_IS_PORT_AUDIO(portTypes))
2474 {
2475 if (LV2_IS_PORT_INPUT(portTypes))
2476 {
2477 const uint32_t j = iAudioIn++;
2478 pData->audioIn.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, j);
2479 pData->audioIn.ports[j].rindex = i;
2480
2481 if (forcedStereoIn)
2482 {
2483 portName += "_2";
2484 pData->audioIn.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, true, 1);
2485 pData->audioIn.ports[1].rindex = i;
2486 }
2487 }
2488 else if (LV2_IS_PORT_OUTPUT(portTypes))
2489 {
2490 const uint32_t j = iAudioOut++;
2491 pData->audioOut.ports[j].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, j);
2492 pData->audioOut.ports[j].rindex = i;
2493
2494 if (forcedStereoOut)
2495 {
2496 portName += "_2";
2497 pData->audioOut.ports[1].port = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, 1);
2498 pData->audioOut.ports[1].rindex = i;
2499 }
2500 }
2501 else
2502 carla_stderr2("WARNING - Got a broken Port (Audio, but not input or output)");
2503 }
2504 else if (LV2_IS_PORT_CV(portTypes))
2505 {
2506 const LV2_RDF_PortPoints portPoints(fRdfDescriptor->Ports[i].Points);
2507 float min, max;
2508
2509 // min value
2510 if (LV2_HAVE_MINIMUM_PORT_POINT(portPoints.Hints))
2511 min = portPoints.Minimum;
2512 else
2513 min = -1.0f;
2514
2515 // max value
2516 if (LV2_HAVE_MAXIMUM_PORT_POINT(portPoints.Hints))
2517 max = portPoints.Maximum;
2518 else
2519 max = 1.0f;
2520
2521 if (LV2_IS_PORT_INPUT(portTypes))
2522 {
2523 const uint32_t j = iCvIn++;
2524 pData->cvIn.ports[j].port = (CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV, portName, true, j);
2525 pData->cvIn.ports[j].rindex = i;
2526 pData->cvIn.ports[j].port->setRange(min, max);
2527 }
2528 else if (LV2_IS_PORT_OUTPUT(portTypes))
2529 {
2530 const uint32_t j = iCvOut++;
2531 pData->cvOut.ports[j].port = (CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV, portName, false, j);
2532 pData->cvOut.ports[j].rindex = i;
2533 pData->cvOut.ports[j].port->setRange(min, max);
2534 }
2535 else
2536 carla_stderr("WARNING - Got a broken Port (CV, but not input or output)");
2537 }
2538 else if (LV2_IS_PORT_ATOM_SEQUENCE(portTypes))
2539 {
2540 if (LV2_IS_PORT_INPUT(portTypes))
2541 {
2542 const uint32_t j = iEvIn++;
2543
2544 fDescriptor->connect_port(fHandle, i, &fEventsIn.data[j].atom->atoms);
2545
2546 if (fHandle2 != nullptr)
2547 fDescriptor->connect_port(fHandle2, i, &fEventsIn.data[j].atom->atoms);
2548
2549 fEventsIn.data[j].rindex = i;
2550
2551 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2552 fEventsIn.data[j].type |= CARLA_EVENT_TYPE_MIDI;
2553 if (portTypes & LV2_PORT_DATA_PATCH_MESSAGE)
2554 fEventsIn.data[j].type |= CARLA_EVENT_TYPE_MESSAGE;
2555 if (portTypes & LV2_PORT_DATA_TIME_POSITION)
2556 fEventsIn.data[j].type |= CARLA_EVENT_TYPE_TIME;
2557
2558 if (evIns.count() == 1)
2559 {
2560 fEventsIn.ctrl = &fEventsIn.data[j];
2561 fEventsIn.ctrlIndex = j;
2562
2563 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2564 needsCtrlIn = true;
2565 }
2566 else
2567 {
2568 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2569 fEventsIn.data[j].port = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, j);
2570
2571 if (LV2_IS_PORT_DESIGNATION_CONTROL(fRdfDescriptor->Ports[i].Designation))
2572 {
2573 fEventsIn.ctrl = &fEventsIn.data[j];
2574 fEventsIn.ctrlIndex = j;
2575 }
2576 }
2577 }
2578 else if (LV2_IS_PORT_OUTPUT(portTypes))
2579 {
2580 const uint32_t j = iEvOut++;
2581
2582 fDescriptor->connect_port(fHandle, i, &fEventsOut.data[j].atom->atoms);
2583
2584 if (fHandle2 != nullptr)
2585 fDescriptor->connect_port(fHandle2, i, &fEventsOut.data[j].atom->atoms);
2586
2587 fEventsOut.data[j].rindex = i;
2588
2589 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2590 fEventsOut.data[j].type |= CARLA_EVENT_TYPE_MIDI;
2591 if (portTypes & LV2_PORT_DATA_PATCH_MESSAGE)
2592 fEventsOut.data[j].type |= CARLA_EVENT_TYPE_MESSAGE;
2593 if (portTypes & LV2_PORT_DATA_TIME_POSITION)
2594 fEventsOut.data[j].type |= CARLA_EVENT_TYPE_TIME;
2595
2596 if (evOuts.count() == 1)
2597 {
2598 fEventsOut.ctrl = &fEventsOut.data[j];
2599 fEventsOut.ctrlIndex = j;
2600
2601 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2602 needsCtrlOut = true;
2603 }
2604 else
2605 {
2606 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2607 fEventsOut.data[j].port = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, j);
2608
2609 if (LV2_IS_PORT_DESIGNATION_CONTROL(fRdfDescriptor->Ports[i].Designation))
2610 {
2611 fEventsOut.ctrl = &fEventsOut.data[j];
2612 fEventsOut.ctrlIndex = j;
2613 }
2614 }
2615 }
2616 else
2617 carla_stderr2("WARNING - Got a broken Port (Atom-Sequence, but not input or output)");
2618 }
2619 else if (LV2_IS_PORT_EVENT(portTypes))
2620 {
2621 if (LV2_IS_PORT_INPUT(portTypes))
2622 {
2623 const uint32_t j = iEvIn++;
2624
2625 fDescriptor->connect_port(fHandle, i, fEventsIn.data[j].event);
2626
2627 if (fHandle2 != nullptr)
2628 fDescriptor->connect_port(fHandle2, i, fEventsIn.data[j].event);
2629
2630 fEventsIn.data[j].rindex = i;
2631
2632 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2633 fEventsIn.data[j].type |= CARLA_EVENT_TYPE_MIDI;
2634 if (portTypes & LV2_PORT_DATA_PATCH_MESSAGE)
2635 fEventsIn.data[j].type |= CARLA_EVENT_TYPE_MESSAGE;
2636 if (portTypes & LV2_PORT_DATA_TIME_POSITION)
2637 fEventsIn.data[j].type |= CARLA_EVENT_TYPE_TIME;
2638
2639 if (evIns.count() == 1)
2640 {
2641 fEventsIn.ctrl = &fEventsIn.data[j];
2642 fEventsIn.ctrlIndex = j;
2643
2644 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2645 needsCtrlIn = true;
2646 }
2647 else
2648 {
2649 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2650 fEventsIn.data[j].port = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, j);
2651
2652 if (LV2_IS_PORT_DESIGNATION_CONTROL(fRdfDescriptor->Ports[i].Designation))
2653 {
2654 fEventsIn.ctrl = &fEventsIn.data[j];
2655 fEventsIn.ctrlIndex = j;
2656 }
2657 }
2658 }
2659 else if (LV2_IS_PORT_OUTPUT(portTypes))
2660 {
2661 const uint32_t j = iEvOut++;
2662
2663 fDescriptor->connect_port(fHandle, i, fEventsOut.data[j].event);
2664
2665 if (fHandle2 != nullptr)
2666 fDescriptor->connect_port(fHandle2, i, fEventsOut.data[j].event);
2667
2668 fEventsOut.data[j].rindex = i;
2669
2670 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2671 fEventsOut.data[j].type |= CARLA_EVENT_TYPE_MIDI;
2672 if (portTypes & LV2_PORT_DATA_PATCH_MESSAGE)
2673 fEventsOut.data[j].type |= CARLA_EVENT_TYPE_MESSAGE;
2674 if (portTypes & LV2_PORT_DATA_TIME_POSITION)
2675 fEventsOut.data[j].type |= CARLA_EVENT_TYPE_TIME;
2676
2677 if (evOuts.count() == 1)
2678 {
2679 fEventsOut.ctrl = &fEventsOut.data[j];
2680 fEventsOut.ctrlIndex = j;
2681
2682 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2683 needsCtrlOut = true;
2684 }
2685 else
2686 {
2687 if (portTypes & LV2_PORT_DATA_MIDI_EVENT)
2688 fEventsOut.data[j].port = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, j);
2689
2690 if (LV2_IS_PORT_DESIGNATION_CONTROL(fRdfDescriptor->Ports[i].Designation))
2691 {
2692 fEventsOut.ctrl = &fEventsOut.data[j];
2693 fEventsOut.ctrlIndex = j;
2694 }
2695 }
2696 }
2697 else
2698 carla_stderr2("WARNING - Got a broken Port (Event, but not input or output)");
2699 }
2700 else if (LV2_IS_PORT_MIDI_LL(portTypes))
2701 {
2702 if (LV2_IS_PORT_INPUT(portTypes))
2703 {
2704 const uint32_t j = iEvIn++;
2705
2706 fDescriptor->connect_port(fHandle, i, &fEventsIn.data[j].midi);
2707
2708 if (fHandle2 != nullptr)
2709 fDescriptor->connect_port(fHandle2, i, &fEventsIn.data[j].midi);
2710
2711 fEventsIn.data[j].type |= CARLA_EVENT_TYPE_MIDI;
2712 fEventsIn.data[j].rindex = i;
2713
2714 if (evIns.count() == 1)
2715 {
2716 needsCtrlIn = true;
2717 fEventsIn.ctrl = &fEventsIn.data[j];
2718 fEventsIn.ctrlIndex = j;
2719 }
2720 else
2721 {
2722 fEventsIn.data[j].port = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, j);
2723
2724 if (LV2_IS_PORT_DESIGNATION_CONTROL(fRdfDescriptor->Ports[i].Designation))
2725 {
2726 fEventsIn.ctrl = &fEventsIn.data[j];
2727 fEventsIn.ctrlIndex = j;
2728 }
2729 }
2730 }
2731 else if (LV2_IS_PORT_OUTPUT(portTypes))
2732 {
2733 const uint32_t j = iEvOut++;
2734
2735 fDescriptor->connect_port(fHandle, i, &fEventsOut.data[j].midi);
2736
2737 if (fHandle2 != nullptr)
2738 fDescriptor->connect_port(fHandle2, i, &fEventsOut.data[j].midi);
2739
2740 fEventsOut.data[j].type |= CARLA_EVENT_TYPE_MIDI;
2741 fEventsOut.data[j].rindex = i;
2742
2743 if (evOuts.count() == 1)
2744 {
2745 needsCtrlOut = true;
2746 fEventsOut.ctrl = &fEventsOut.data[j];
2747 fEventsOut.ctrlIndex = j;
2748 }
2749 else
2750 {
2751 fEventsOut.data[j].port = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, j);
2752
2753 if (LV2_IS_PORT_DESIGNATION_CONTROL(fRdfDescriptor->Ports[i].Designation))
2754 {
2755 fEventsOut.ctrl = &fEventsOut.data[j];
2756 fEventsOut.ctrlIndex = j;
2757 }
2758 }
2759 }
2760 else
2761 carla_stderr2("WARNING - Got a broken Port (MIDI, but not input or output)");
2762 }
2763 else if (LV2_IS_PORT_CONTROL(portTypes))
2764 {
2765 const LV2_Property portProps(fRdfDescriptor->Ports[i].Properties);
2766 const LV2_Property portDesignation(fRdfDescriptor->Ports[i].Designation);
2767 const LV2_RDF_PortPoints portPoints(fRdfDescriptor->Ports[i].Points);
2768
2769 const uint32_t j = iCtrl++;
2770 pData->param.data[j].index = static_cast<int32_t>(j);
2771 pData->param.data[j].rindex = static_cast<int32_t>(i);
2772
2773 float min, max, def, step, stepSmall, stepLarge;
2774
2775 // min value
2776 if (LV2_HAVE_MINIMUM_PORT_POINT(portPoints.Hints))
2777 min = portPoints.Minimum;
2778 else
2779 min = 0.0f;
2780
2781 // max value
2782 if (LV2_HAVE_MAXIMUM_PORT_POINT(portPoints.Hints))
2783 max = portPoints.Maximum;
2784 else
2785 max = 1.0f;
2786
2787 if (LV2_IS_PORT_SAMPLE_RATE(portProps))
2788 {
2789 min *= sampleRate;
2790 max *= sampleRate;
2791 pData->param.data[j].hints |= PARAMETER_USES_SAMPLERATE;
2792 }
2793
2794 // stupid hack for ir.lv2 (broken plugin)
2795 if (std::strcmp(fRdfDescriptor->URI, "http://factorial.hu/plugins/lv2/ir") == 0 && std::strncmp(fRdfDescriptor->Ports[i].Name, "FileHash", 8) == 0)
2796 {
2797 min = 0.0f;
2798 max = (float)0xffffff;
2799 }
2800
2801 if (min >= max)
2802 {
2803 carla_stderr2("WARNING - Broken plugin parameter '%s': min >= max", fRdfDescriptor->Ports[i].Name);
2804 max = min + 0.1f;
2805 }
2806
2807 // default value
2808 if (LV2_HAVE_DEFAULT_PORT_POINT(portPoints.Hints))
2809 {
2810 def = portPoints.Default;
2811 }
2812 else
2813 {
2814 // no default value
2815 if (min < 0.0f && max > 0.0f)
2816 def = 0.0f;
2817 else
2818 def = min;
2819 }
2820
2821 if (def < min)
2822 def = min;
2823 else if (def > max)
2824 def = max;
2825
2826 if (LV2_IS_PORT_TOGGLED(portProps))
2827 {
2828 step = max - min;
2829 stepSmall = step;
2830 stepLarge = step;
2831 pData->param.data[j].hints |= PARAMETER_IS_BOOLEAN;
2832 }
2833 else if (LV2_IS_PORT_INTEGER(portProps))
2834 {
2835 step = 1.0f;
2836 stepSmall = 1.0f;
2837 stepLarge = 10.0f;
2838 pData->param.data[j].hints |= PARAMETER_IS_INTEGER;
2839 }
2840 else
2841 {
2842 float range = max - min;
2843 step = range/100.0f;
2844 stepSmall = range/1000.0f;
2845 stepLarge = range/10.0f;
2846 }
2847
2848 if (LV2_IS_PORT_INPUT(portTypes))
2849 {
2850 pData->param.data[j].type = PARAMETER_INPUT;
2851
2852 if (LV2_IS_PORT_DESIGNATION_LATENCY(portDesignation))
2853 {
2854 carla_stderr("Plugin has latency input port, this should not happen!");
2855 }
2856 else if (LV2_IS_PORT_DESIGNATION_SAMPLE_RATE(portDesignation))
2857 {
2858 def = sampleRate;
2859 step = 1.0f;
2860 stepSmall = 1.0f;
2861 stepLarge = 1.0f;
2862 pData->param.special[j] = PARAMETER_SPECIAL_SAMPLE_RATE;
2863 }
2864 else if (LV2_IS_PORT_DESIGNATION_FREEWHEELING(portDesignation))
2865 {
2866 pData->param.special[j] = PARAMETER_SPECIAL_FREEWHEEL;
2867 }
2868 else if (LV2_IS_PORT_DESIGNATION_TIME(portDesignation))
2869 {
2870 pData->param.special[j] = PARAMETER_SPECIAL_TIME;
2871 }
2872 else
2873 {
2874 pData->param.data[j].hints |= PARAMETER_IS_ENABLED;
2875 pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE;
2876 needsCtrlIn = true;
2877
2878 if (! LV2_IS_PORT_CAUSES_ARTIFACTS(portProps) &&
2879 ! LV2_IS_PORT_ENUMERATION(portProps) &&
2880 ! LV2_IS_PORT_EXPENSIVE(portProps) &&
2881 ! LV2_IS_PORT_NOT_AUTOMATIC(portProps) &&
2882 ! LV2_IS_PORT_NOT_ON_GUI(portProps) &&
2883 ! LV2_IS_PORT_TRIGGER(portProps))
2884 {
2885 pData->param.data[j].hints |= PARAMETER_CAN_BE_CV_CONTROLLED;
2886 }
2887 }
2888
2889 // MIDI CC value
2890 const LV2_RDF_PortMidiMap& portMidiMap(fRdfDescriptor->Ports[i].MidiMap);
2891
2892 if (LV2_IS_PORT_MIDI_MAP_CC(portMidiMap.Type))
2893 {
2894 if (portMidiMap.Number < MAX_MIDI_CONTROL && ! MIDI_IS_CONTROL_BANK_SELECT(portMidiMap.Number))
2895 pData->param.data[j].mappedControlIndex = static_cast<int16_t>(portMidiMap.Number);
2896 }
2897 }
2898 else if (LV2_IS_PORT_OUTPUT(portTypes))
2899 {
2900 pData->param.data[j].type = PARAMETER_OUTPUT;
2901
2902 if (LV2_IS_PORT_DESIGNATION_LATENCY(portDesignation))
2903 {
2904 min = 0.0f;
2905 max = sampleRate;
2906 def = 0.0f;
2907 step = 1.0f;
2908 stepSmall = 1.0f;
2909 stepLarge = 1.0f;
2910 pData->param.special[j] = PARAMETER_SPECIAL_LATENCY;
2911 CARLA_SAFE_ASSERT_INT2(fLatencyIndex == static_cast<int32_t>(j), fLatencyIndex, j);
2912 }
2913 else if (LV2_IS_PORT_DESIGNATION_SAMPLE_RATE(portDesignation))
2914 {
2915 def = sampleRate;
2916 step = 1.0f;
2917 stepSmall = 1.0f;
2918 stepLarge = 1.0f;
2919 pData->param.special[j] = PARAMETER_SPECIAL_SAMPLE_RATE;
2920 }
2921 else if (LV2_IS_PORT_DESIGNATION_FREEWHEELING(portDesignation))
2922 {
2923 carla_stderr("Plugin has freewheeling output port, this should not happen!");
2924 }
2925 else if (LV2_IS_PORT_DESIGNATION_TIME(portDesignation))
2926 {
2927 pData->param.special[j] = PARAMETER_SPECIAL_TIME;
2928 }
2929 else
2930 {
2931 pData->param.data[j].hints |= PARAMETER_IS_ENABLED;
2932 pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE;
2933 needsCtrlOut = true;
2934 }
2935 }
2936 else
2937 {
2938 pData->param.data[j].type = PARAMETER_UNKNOWN;
2939 carla_stderr2("WARNING - Got a broken Port (Control, but not input or output)");
2940 }
2941
2942 // extra parameter hints
2943 if (LV2_IS_PORT_LOGARITHMIC(portProps))
2944 pData->param.data[j].hints |= PARAMETER_IS_LOGARITHMIC;
2945
2946 if (LV2_IS_PORT_TRIGGER(portProps))
2947 pData->param.data[j].hints |= PARAMETER_IS_TRIGGER;
2948
2949 if (LV2_IS_PORT_STRICT_BOUNDS(portProps))
2950 pData->param.data[j].hints |= PARAMETER_IS_STRICT_BOUNDS;
2951
2952 if (LV2_IS_PORT_ENUMERATION(portProps))
2953 pData->param.data[j].hints |= PARAMETER_USES_SCALEPOINTS;
2954
2955 // check if parameter is not enabled or automable
2956 if (LV2_IS_PORT_NOT_ON_GUI(portProps))
2957 pData->param.data[j].hints &= ~(PARAMETER_IS_ENABLED|PARAMETER_IS_AUTOMABLE);
2958 else if (LV2_IS_PORT_CAUSES_ARTIFACTS(portProps) || LV2_IS_PORT_EXPENSIVE(portProps))
2959 pData->param.data[j].hints &= ~PARAMETER_IS_AUTOMABLE;
2960 else if (LV2_IS_PORT_NOT_AUTOMATIC(portProps) || LV2_IS_PORT_NON_AUTOMABLE(portProps))
2961 pData->param.data[j].hints &= ~PARAMETER_IS_AUTOMABLE;
2962
2963 pData->param.ranges[j].min = min;
2964 pData->param.ranges[j].max = max;
2965 pData->param.ranges[j].def = def;
2966 pData->param.ranges[j].step = step;
2967 pData->param.ranges[j].stepSmall = stepSmall;
2968 pData->param.ranges[j].stepLarge = stepLarge;
2969
2970 // Start parameters in their default values (except freewheel, which is off by default)
2971 if (pData->param.data[j].type == PARAMETER_INPUT && pData->param.special[j] == PARAMETER_SPECIAL_FREEWHEEL)
2972 fParamBuffers[j] = min;
2973 else
2974 fParamBuffers[j] = def;
2975
2976 fDescriptor->connect_port(fHandle, i, &fParamBuffers[j]);
2977
2978 if (fHandle2 != nullptr)
2979 fDescriptor->connect_port(fHandle2, i, &fParamBuffers[j]);
2980 }
2981 else
2982 {
2983 // Port Type not supported, but it's optional anyway
2984 fDescriptor->connect_port(fHandle, i, nullptr);
2985
2986 if (fHandle2 != nullptr)
2987 fDescriptor->connect_port(fHandle2, i, nullptr);
2988 }
2989 }
2990
2991 for (uint32_t i=0; i < fRdfDescriptor->ParameterCount; ++i)
2992 {
2993 const LV2_RDF_Parameter& rdfParam(fRdfDescriptor->Parameters[i]);
2994
2995 switch (rdfParam.Type)
2996 {
2997 case LV2_PARAMETER_TYPE_BOOL:
2998 case LV2_PARAMETER_TYPE_INT:
2999 // case LV2_PARAMETER_TYPE_LONG:
3000 case LV2_PARAMETER_TYPE_FLOAT:
3001 case LV2_PARAMETER_TYPE_DOUBLE:
3002 break;
3003 default:
3004 continue;
3005 }
3006
3007 const LV2_RDF_PortPoints& portPoints(rdfParam.Points);
3008
3009 const uint32_t j = iCtrl++;
3010 pData->param.data[j].index = static_cast<int32_t>(j);
3011 pData->param.data[j].rindex = static_cast<int32_t>(fRdfDescriptor->PortCount + i);
3012
3013 float min, max, def, step, stepSmall, stepLarge;
3014
3015 // min value
3016 if (LV2_HAVE_MINIMUM_PORT_POINT(portPoints.Hints))
3017 min = portPoints.Minimum;
3018 else
3019 min = 0.0f;
3020
3021 // max value
3022 if (LV2_HAVE_MAXIMUM_PORT_POINT(portPoints.Hints))
3023 max = portPoints.Maximum;
3024 else
3025 max = 1.0f;
3026
3027 if (min >= max)
3028 {
3029 carla_stderr2("WARNING - Broken plugin parameter '%s': min >= max", rdfParam.Label);
3030 max = min + 0.1f;
3031 }
3032
3033 // default value
3034 if (LV2_HAVE_DEFAULT_PORT_POINT(portPoints.Hints))
3035 {
3036 def = portPoints.Default;
3037 }
3038 else
3039 {
3040 // no default value
3041 if (min < 0.0f && max > 0.0f)
3042 def = 0.0f;
3043 else
3044 def = min;
3045 }
3046
3047 if (def < min)
3048 def = min;
3049 else if (def > max)
3050 def = max;
3051
3052 switch (rdfParam.Type)
3053 {
3054 case LV2_PARAMETER_TYPE_BOOL:
3055 step = max - min;
3056 stepSmall = step;
3057 stepLarge = step;
3058 pData->param.data[j].hints |= PARAMETER_IS_BOOLEAN;
3059 break;
3060
3061 case LV2_PARAMETER_TYPE_INT:
3062 case LV2_PARAMETER_TYPE_LONG:
3063 step = 1.0f;
3064 stepSmall = 1.0f;
3065 stepLarge = 10.0f;
3066 pData->param.data[j].hints |= PARAMETER_IS_INTEGER;
3067 break;
3068
3069 default:
3070 const float range = max - min;
3071 step = range/100.0f;
3072 stepSmall = range/1000.0f;
3073 stepLarge = range/10.0f;
3074 break;
3075 }
3076
3077 if (rdfParam.Flags & LV2_PARAMETER_FLAG_INPUT)
3078 {
3079 pData->param.data[j].type = PARAMETER_INPUT;
3080 pData->param.data[j].hints |= PARAMETER_IS_ENABLED;
3081 pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE;
3082 pData->param.data[j].hints |= PARAMETER_IS_NOT_SAVED;
3083 needsCtrlIn = true;
3084
3085 if (rdfParam.Flags & LV2_PARAMETER_FLAG_OUTPUT)
3086 hasPatchParameterOutputs = true;
3087
3088 if (LV2_IS_PORT_MIDI_MAP_CC(rdfParam.MidiMap.Type))
3089 {
3090 if (rdfParam.MidiMap.Number < MAX_MIDI_CONTROL && ! MIDI_IS_CONTROL_BANK_SELECT(rdfParam.MidiMap.Number))
3091 pData->param.data[j].mappedControlIndex = static_cast<int16_t>(rdfParam.MidiMap.Number);
3092 }
3093 }
3094 else if (rdfParam.Flags & LV2_PARAMETER_FLAG_OUTPUT)
3095 {
3096 pData->param.data[j].type = PARAMETER_OUTPUT;
3097 pData->param.data[j].hints |= PARAMETER_IS_ENABLED;
3098 pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE;
3099 needsCtrlOut = true;
3100 hasPatchParameterOutputs = true;
3101 }
3102
3103 pData->param.ranges[j].min = min;
3104 pData->param.ranges[j].max = max;
3105 pData->param.ranges[j].def = def;
3106 pData->param.ranges[j].step = step;
3107 pData->param.ranges[j].stepSmall = stepSmall;
3108 pData->param.ranges[j].stepLarge = stepLarge;
3109
3110 fParamBuffers[j] = def;
3111 }
3112
3113 if (needsCtrlIn)
3114 {
3115 portName.clear();
3116
3117 if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
3118 {
3119 portName = pData->name;
3120 portName += ":";
3121 }
3122
3123 portName += "events-in";
3124 portName.truncate(portNameSize);
3125
3126 pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, 0);
3127 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
3128 pData->event.cvSourcePorts = pData->client->createCVSourcePorts();
3129 #endif
3130 }
3131
3132 if (needsCtrlOut)
3133 {
3134 portName.clear();
3135
3136 if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
3137 {
3138 portName = pData->name;
3139 portName += ":";
3140 }
3141
3142 portName += "events-out";
3143 portName.truncate(portNameSize);
3144
3145 pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, 0);
3146 }
3147
3148 if (fExt.worker != nullptr && fEventsIn.ctrl != nullptr)
3149 {
3150 fAtomBufferWorkerIn.createBuffer(eventBufferSize);
3151 fAtomBufferWorkerResp.createBuffer(eventBufferSize);
3152 fAtomBufferWorkerInTmpData = new uint8_t[fAtomBufferWorkerIn.getSize()];
3153 }
3154
3155 if (fRdfDescriptor->ParameterCount > 0 ||
3156 (fUI.type != UI::TYPE_NULL && fEventsIn.count > 0 && (fEventsIn.data[0].type & CARLA_EVENT_DATA_ATOM) != 0))
3157 fAtomBufferEvIn.createBuffer(eventBufferSize);
3158
3159 if (hasPatchParameterOutputs ||
3160 (fUI.type != UI::TYPE_NULL && fEventsOut.count > 0 && (fEventsOut.data[0].type & CARLA_EVENT_DATA_ATOM) != 0))
3161 {
3162 fAtomBufferUiOut.createBuffer(std::min(eventBufferSize*32, 1638400U));
3163 fAtomBufferUiOutTmpData = new uint8_t[fAtomBufferUiOut.getSize()];
3164 }
3165
3166 if (fEventsIn.ctrl != nullptr && fEventsIn.ctrl->port == nullptr)
3167 fEventsIn.ctrl->port = pData->event.portIn;
3168
3169 if (fEventsOut.ctrl != nullptr && fEventsOut.ctrl->port == nullptr)
3170 fEventsOut.ctrl->port = pData->event.portOut;
3171
3172 if (fEventsIn.ctrl != nullptr && fExt.midnam != nullptr)
3173 {
3174 if (char* const midnam = fExt.midnam->midnam(fHandle))
3175 {
3176 fEventsIn.ctrl->port->setMetaData("http://www.midi.org/dtds/MIDINameDocument10.dtd",
3177 midnam, "text/xml");
3178 if (fExt.midnam->free != nullptr)
3179 fExt.midnam->free(midnam);
3180 }
3181 }
3182
3183 if (forcedStereoIn || forcedStereoOut)
3184 pData->options |= PLUGIN_OPTION_FORCE_STEREO;
3185 else
3186 pData->options &= ~PLUGIN_OPTION_FORCE_STEREO;
3187
3188 // plugin hints
3189 pData->hints = (pData->hints & PLUGIN_HAS_INLINE_DISPLAY) ? PLUGIN_HAS_INLINE_DISPLAY : 0
3190 | (pData->hints & PLUGIN_NEEDS_UI_MAIN_THREAD) ? PLUGIN_NEEDS_UI_MAIN_THREAD : 0;
3191
3192 if (isRealtimeSafe())
3193 pData->hints |= PLUGIN_IS_RTSAFE;
3194
3195 if (fUI.type != UI::TYPE_NULL || fFilePathURI.isNotEmpty())
3196 {
3197 pData->hints |= PLUGIN_HAS_CUSTOM_UI;
3198
3199 if (fUI.type == UI::TYPE_EMBED)
3200 {
3201 switch (fUI.rdfDescriptor->Type)
3202 {
3203 case LV2_UI_GTK2:
3204 case LV2_UI_GTK3:
3205 case LV2_UI_QT4:
3206 case LV2_UI_QT5:
3207 case LV2_UI_EXTERNAL:
3208 case LV2_UI_OLD_EXTERNAL:
3209 break;
3210 default:
3211 pData->hints |= PLUGIN_HAS_CUSTOM_EMBED_UI;
3212 break;
3213 }
3214 }
3215
3216 if (fUI.type == UI::TYPE_EMBED || fUI.type == UI::TYPE_EXTERNAL)
3217 pData->hints |= PLUGIN_NEEDS_UI_MAIN_THREAD;
3218 }
3219
3220 if (LV2_IS_GENERATOR(fRdfDescriptor->Type[0], fRdfDescriptor->Type[1]))
3221 pData->hints |= PLUGIN_IS_SYNTH;
3222
3223 if (aOuts > 0 && (aIns == aOuts || aIns == 1))
3224 pData->hints |= PLUGIN_CAN_DRYWET;
3225
3226 if (aOuts > 0)
3227 pData->hints |= PLUGIN_CAN_VOLUME;
3228
3229 if (aOuts >= 2 && aOuts % 2 == 0)
3230 pData->hints |= PLUGIN_CAN_BALANCE;
3231
3232 // extra plugin hints
3233 pData->extraHints = 0x0;
3234
3235 // check initial latency
3236 findInitialLatencyValue(aIns, cvIns, aOuts, cvOuts);
3237
3238 bufferSizeChanged(pData->engine->getBufferSize());
3239 reloadPrograms(true);
3240
3241 evIns.clear();
3242 evOuts.clear();
3243
3244 if (pData->active)
3245 activate();
3246
3247 carla_debug("CarlaPluginLV2::reload() - end");
3248 }
3249
findInitialLatencyValue(const uint32_t aIns,const uint32_t cvIns,const uint32_t aOuts,const uint32_t cvOuts) const3250 void findInitialLatencyValue(const uint32_t aIns,
3251 const uint32_t cvIns,
3252 const uint32_t aOuts,
3253 const uint32_t cvOuts) const
3254 {
3255 if (fLatencyIndex < 0)
3256 return;
3257
3258 // we need to pre-run the plugin so it can update its latency control-port
3259 const uint32_t bufferSize = static_cast<uint32_t>(fLv2Options.nominalBufferSize);
3260
3261 float tmpIn [( aIns+cvIns > 0) ? aIns+cvIns : 1][bufferSize];
3262 float tmpOut[(aOuts+cvOuts > 0) ? aOuts+cvOuts : 1][bufferSize];
3263
3264 {
3265 uint32_t i=0;
3266 for (; i < aIns; ++i)
3267 {
3268 carla_zeroFloats(tmpIn[i], bufferSize);
3269
3270 try {
3271 fDescriptor->connect_port(fHandle, pData->audioIn.ports[i].rindex, tmpIn[i]);
3272 } CARLA_SAFE_EXCEPTION("LV2 connect_port latency audio input");
3273 }
3274
3275 for (uint32_t j=0; j < cvIns; ++i, ++j)
3276 {
3277 carla_zeroFloats(tmpIn[i], bufferSize);
3278
3279 try {
3280 fDescriptor->connect_port(fHandle, pData->cvIn.ports[j].rindex, tmpIn[i]);
3281 } CARLA_SAFE_EXCEPTION("LV2 connect_port latency cv input");
3282 }
3283 }
3284
3285 {
3286 uint32_t i=0;
3287 for (; i < aOuts; ++i)
3288 {
3289 carla_zeroFloats(tmpOut[i], bufferSize);
3290
3291 try {
3292 fDescriptor->connect_port(fHandle, pData->audioOut.ports[i].rindex, tmpOut[i]);
3293 } CARLA_SAFE_EXCEPTION("LV2 connect_port latency audio output");
3294 }
3295
3296 for (uint32_t j=0; j < cvOuts; ++i, ++j)
3297 {
3298 carla_zeroFloats(tmpOut[i], bufferSize);
3299
3300 try {
3301 fDescriptor->connect_port(fHandle, pData->cvOut.ports[j].rindex, tmpOut[i]);
3302 } CARLA_SAFE_EXCEPTION("LV2 connect_port latency cv output");
3303 }
3304 }
3305
3306 if (fDescriptor->activate != nullptr)
3307 {
3308 try {
3309 fDescriptor->activate(fHandle);
3310 } CARLA_SAFE_EXCEPTION("LV2 latency activate");
3311 }
3312
3313 try {
3314 fDescriptor->run(fHandle, bufferSize);
3315 } CARLA_SAFE_EXCEPTION("LV2 latency run");
3316
3317 if (fDescriptor->deactivate != nullptr)
3318 {
3319 try {
3320 fDescriptor->deactivate(fHandle);
3321 } CARLA_SAFE_EXCEPTION("LV2 latency deactivate");
3322 }
3323
3324 // done, let's get the value
3325 if (const uint32_t latency = getLatencyInFrames())
3326 {
3327 pData->client->setLatency(latency);
3328 #ifndef BUILD_BRIDGE
3329 pData->latency.recreateBuffers(std::max(aIns, aOuts), latency);
3330 #endif
3331 }
3332 }
3333
reloadPrograms(const bool doInit)3334 void reloadPrograms(const bool doInit) override
3335 {
3336 carla_debug("CarlaPluginLV2::reloadPrograms(%s)", bool2str(doInit));
3337 const uint32_t oldCount = pData->midiprog.count;
3338 const int32_t current = pData->midiprog.current;
3339
3340 // special LV2 programs handling
3341 if (doInit)
3342 {
3343 pData->prog.clear();
3344
3345 const uint32_t presetCount(fRdfDescriptor->PresetCount);
3346
3347 if (presetCount > 0)
3348 {
3349 pData->prog.createNew(presetCount);
3350
3351 for (uint32_t i=0; i < presetCount; ++i)
3352 pData->prog.names[i] = carla_strdup(fRdfDescriptor->Presets[i].Label);
3353 }
3354 }
3355
3356 // Delete old programs
3357 pData->midiprog.clear();
3358
3359 // Query new programs
3360 uint32_t newCount = 0;
3361 if (fExt.programs != nullptr && fExt.programs->get_program != nullptr && fExt.programs->select_program != nullptr)
3362 {
3363 for (; fExt.programs->get_program(fHandle, newCount);)
3364 ++newCount;
3365 }
3366
3367 if (newCount > 0)
3368 {
3369 pData->midiprog.createNew(newCount);
3370
3371 // Update data
3372 for (uint32_t i=0; i < newCount; ++i)
3373 {
3374 const LV2_Program_Descriptor* const pdesc(fExt.programs->get_program(fHandle, i));
3375 CARLA_SAFE_ASSERT_CONTINUE(pdesc != nullptr);
3376 CARLA_SAFE_ASSERT(pdesc->name != nullptr);
3377
3378 pData->midiprog.data[i].bank = pdesc->bank;
3379 pData->midiprog.data[i].program = pdesc->program;
3380 pData->midiprog.data[i].name = carla_strdup(pdesc->name);
3381 }
3382 }
3383
3384 if (doInit)
3385 {
3386 if (newCount > 0)
3387 {
3388 setMidiProgram(0, false, false, false, true);
3389 }
3390 else if (fHasLoadDefaultState)
3391 {
3392 // load default state
3393 if (LilvState* const state = Lv2WorldClass::getInstance().getStateFromURI(fDescriptor->URI,
3394 (const LV2_URID_Map*)fFeatures[kFeatureIdUridMap]->data))
3395 {
3396 lilv_state_restore(state, fExt.state, fHandle, carla_lilv_set_port_value, this, 0, fFeatures);
3397
3398 if (fHandle2 != nullptr)
3399 lilv_state_restore(state, fExt.state, fHandle2, carla_lilv_set_port_value, this, 0, fFeatures);
3400
3401 lilv_state_free(state);
3402 }
3403 }
3404 }
3405 else
3406 {
3407 // Check if current program is invalid
3408 bool programChanged = false;
3409
3410 if (newCount == oldCount+1)
3411 {
3412 // one midi program added, probably created by user
3413 pData->midiprog.current = static_cast<int32_t>(oldCount);
3414 programChanged = true;
3415 }
3416 else if (current < 0 && newCount > 0)
3417 {
3418 // programs exist now, but not before
3419 pData->midiprog.current = 0;
3420 programChanged = true;
3421 }
3422 else if (current >= 0 && newCount == 0)
3423 {
3424 // programs existed before, but not anymore
3425 pData->midiprog.current = -1;
3426 programChanged = true;
3427 }
3428 else if (current >= static_cast<int32_t>(newCount))
3429 {
3430 // current midi program > count
3431 pData->midiprog.current = 0;
3432 programChanged = true;
3433 }
3434 else
3435 {
3436 // no change
3437 pData->midiprog.current = current;
3438 }
3439
3440 if (programChanged)
3441 setMidiProgram(pData->midiprog.current, true, true, true, false);
3442
3443 pData->engine->callback(true, true, ENGINE_CALLBACK_RELOAD_PROGRAMS, pData->id, 0, 0, 0, 0.0f, nullptr);
3444 }
3445 }
3446
3447 // -------------------------------------------------------------------
3448 // Plugin processing
3449
activate()3450 void activate() noexcept override
3451 {
3452 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
3453 CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
3454
3455 if (fDescriptor->activate != nullptr)
3456 {
3457 try {
3458 fDescriptor->activate(fHandle);
3459 } CARLA_SAFE_EXCEPTION("LV2 activate");
3460
3461 if (fHandle2 != nullptr)
3462 {
3463 try {
3464 fDescriptor->activate(fHandle2);
3465 } CARLA_SAFE_EXCEPTION("LV2 activate #2");
3466 }
3467 }
3468
3469 fFirstActive = true;
3470 }
3471
deactivate()3472 void deactivate() noexcept override
3473 {
3474 CARLA_SAFE_ASSERT_RETURN(fDescriptor != nullptr,);
3475 CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr,);
3476
3477 if (fDescriptor->deactivate != nullptr)
3478 {
3479 try {
3480 fDescriptor->deactivate(fHandle);
3481 } CARLA_SAFE_EXCEPTION("LV2 deactivate");
3482
3483 if (fHandle2 != nullptr)
3484 {
3485 try {
3486 fDescriptor->deactivate(fHandle2);
3487 } CARLA_SAFE_EXCEPTION("LV2 deactivate #2");
3488 }
3489 }
3490 }
3491
process(const float * const * const audioIn,float ** const audioOut,const float * const * const cvIn,float ** const cvOut,const uint32_t frames)3492 void process(const float* const* const audioIn, float** const audioOut,
3493 const float* const* const cvIn, float** const cvOut, const uint32_t frames) override
3494 {
3495 // --------------------------------------------------------------------------------------------------------
3496 // Check if active
3497
3498 if (! pData->active)
3499 {
3500 // disable any output sound
3501 for (uint32_t i=0; i < pData->audioOut.count; ++i)
3502 carla_zeroFloats(audioOut[i], frames);
3503 for (uint32_t i=0; i < pData->cvOut.count; ++i)
3504 carla_zeroFloats(cvOut[i], frames);
3505 return;
3506 }
3507
3508 // --------------------------------------------------------------------------------------------------------
3509 // Event itenerators from different APIs (input)
3510
3511 LV2_Atom_Buffer_Iterator evInAtomIters[fEventsIn.count];
3512 LV2_Event_Iterator evInEventIters[fEventsIn.count];
3513 LV2_MIDIState evInMidiStates[fEventsIn.count];
3514
3515 for (uint32_t i=0; i < fEventsIn.count; ++i)
3516 {
3517 if (fEventsIn.data[i].type & CARLA_EVENT_DATA_ATOM)
3518 {
3519 lv2_atom_buffer_reset(fEventsIn.data[i].atom, true);
3520 lv2_atom_buffer_begin(&evInAtomIters[i], fEventsIn.data[i].atom);
3521 }
3522 else if (fEventsIn.data[i].type & CARLA_EVENT_DATA_EVENT)
3523 {
3524 lv2_event_buffer_reset(fEventsIn.data[i].event, LV2_EVENT_AUDIO_STAMP, fEventsIn.data[i].event->data);
3525 lv2_event_begin(&evInEventIters[i], fEventsIn.data[i].event);
3526 }
3527 else if (fEventsIn.data[i].type & CARLA_EVENT_DATA_MIDI_LL)
3528 {
3529 fEventsIn.data[i].midi.event_count = 0;
3530 fEventsIn.data[i].midi.size = 0;
3531 evInMidiStates[i].midi = &fEventsIn.data[i].midi;
3532 evInMidiStates[i].frame_count = frames;
3533 evInMidiStates[i].position = 0;
3534 }
3535 }
3536
3537 for (uint32_t i=0; i < fEventsOut.count; ++i)
3538 {
3539 if (fEventsOut.data[i].type & CARLA_EVENT_DATA_ATOM)
3540 {
3541 lv2_atom_buffer_reset(fEventsOut.data[i].atom, false);
3542 }
3543 else if (fEventsOut.data[i].type & CARLA_EVENT_DATA_EVENT)
3544 {
3545 lv2_event_buffer_reset(fEventsOut.data[i].event, LV2_EVENT_AUDIO_STAMP, fEventsOut.data[i].event->data);
3546 }
3547 else if (fEventsOut.data[i].type & CARLA_EVENT_DATA_MIDI_LL)
3548 {
3549 // not needed
3550 }
3551 }
3552
3553 // --------------------------------------------------------------------------------------------------------
3554 // Check if needs reset
3555
3556 if (pData->needsReset)
3557 {
3558 if (fEventsIn.ctrl != nullptr && (fEventsIn.ctrl->type & CARLA_EVENT_TYPE_MIDI) != 0)
3559 {
3560 const uint32_t j = fEventsIn.ctrlIndex;
3561 CARLA_ASSERT(j < fEventsIn.count);
3562
3563 uint8_t midiData[3] = { 0, 0, 0 };
3564
3565 if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
3566 {
3567 for (uint8_t i=0; i < MAX_MIDI_CHANNELS; ++i)
3568 {
3569 midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (i & MIDI_CHANNEL_BIT));
3570 midiData[1] = MIDI_CONTROL_ALL_NOTES_OFF;
3571
3572 if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM)
3573 lv2_atom_buffer_write(&evInAtomIters[j], 0, 0, kUridMidiEvent, 3, midiData);
3574
3575 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT)
3576 lv2_event_write(&evInEventIters[j], 0, 0, kUridMidiEvent, 3, midiData);
3577
3578 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL)
3579 lv2midi_put_event(&evInMidiStates[j], 0.0, 3, midiData);
3580
3581 midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (i & MIDI_CHANNEL_BIT));
3582 midiData[1] = MIDI_CONTROL_ALL_SOUND_OFF;
3583
3584 if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM)
3585 lv2_atom_buffer_write(&evInAtomIters[j], 0, 0, kUridMidiEvent, 3, midiData);
3586
3587 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT)
3588 lv2_event_write(&evInEventIters[j], 0, 0, kUridMidiEvent, 3, midiData);
3589
3590 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL)
3591 lv2midi_put_event(&evInMidiStates[j], 0.0, 3, midiData);
3592 }
3593 }
3594 else if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS)
3595 {
3596 for (uint8_t k=0; k < MAX_MIDI_NOTE; ++k)
3597 {
3598 midiData[0] = uint8_t(MIDI_STATUS_NOTE_OFF | (pData->ctrlChannel & MIDI_CHANNEL_BIT));
3599 midiData[1] = k;
3600
3601 if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM)
3602 lv2_atom_buffer_write(&evInAtomIters[j], 0, 0, kUridMidiEvent, 3, midiData);
3603
3604 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT)
3605 lv2_event_write(&evInEventIters[j], 0, 0, kUridMidiEvent, 3, midiData);
3606
3607 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL)
3608 lv2midi_put_event(&evInMidiStates[j], 0.0, 3, midiData);
3609 }
3610 }
3611 }
3612
3613 pData->needsReset = false;
3614 }
3615
3616 // --------------------------------------------------------------------------------------------------------
3617 // TimeInfo
3618
3619 const EngineTimeInfo timeInfo(pData->engine->getTimeInfo());
3620
3621 if (fFirstActive || fLastTimeInfo != timeInfo)
3622 {
3623 bool doPostRt;
3624 int32_t rindex;
3625
3626 const double barBeat = static_cast<double>(timeInfo.bbt.beat - 1)
3627 + (timeInfo.bbt.tick / timeInfo.bbt.ticksPerBeat);
3628
3629 // update input ports
3630 for (uint32_t k=0; k < pData->param.count; ++k)
3631 {
3632 if (pData->param.data[k].type != PARAMETER_INPUT)
3633 continue;
3634 if (pData->param.special[k] != PARAMETER_SPECIAL_TIME)
3635 continue;
3636
3637 doPostRt = false;
3638 rindex = pData->param.data[k].rindex;
3639
3640 CARLA_SAFE_ASSERT_CONTINUE(rindex >= 0 && rindex < static_cast<int32_t>(fRdfDescriptor->PortCount));
3641
3642 switch (fRdfDescriptor->Ports[rindex].Designation)
3643 {
3644 // Non-BBT
3645 case LV2_PORT_DESIGNATION_TIME_SPEED:
3646 if (fLastTimeInfo.playing != timeInfo.playing)
3647 {
3648 fParamBuffers[k] = timeInfo.playing ? 1.0f : 0.0f;
3649 doPostRt = true;
3650 }
3651 break;
3652
3653 case LV2_PORT_DESIGNATION_TIME_FRAME:
3654 if (fLastTimeInfo.frame != timeInfo.frame)
3655 {
3656 fParamBuffers[k] = static_cast<float>(timeInfo.frame);
3657 doPostRt = true;
3658 }
3659 break;
3660
3661 case LV2_PORT_DESIGNATION_TIME_FRAMES_PER_SECOND:
3662 break;
3663
3664 // BBT
3665 case LV2_PORT_DESIGNATION_TIME_BAR:
3666 if (timeInfo.bbt.valid && fLastTimeInfo.bbt.bar != timeInfo.bbt.bar)
3667 {
3668 fParamBuffers[k] = static_cast<float>(timeInfo.bbt.bar - 1);
3669 doPostRt = true;
3670 }
3671 break;
3672
3673 case LV2_PORT_DESIGNATION_TIME_BAR_BEAT:
3674 if (timeInfo.bbt.valid && (carla_isNotEqual(fLastTimeInfo.bbt.tick, timeInfo.bbt.tick) ||
3675 fLastTimeInfo.bbt.beat != timeInfo.bbt.beat))
3676 {
3677 fParamBuffers[k] = static_cast<float>(barBeat);
3678 doPostRt = true;
3679 }
3680 break;
3681
3682 case LV2_PORT_DESIGNATION_TIME_BEAT:
3683 if (timeInfo.bbt.valid && fLastTimeInfo.bbt.beat != timeInfo.bbt.beat)
3684 {
3685 fParamBuffers[k] = static_cast<float>(timeInfo.bbt.beat - 1);
3686 doPostRt = true;
3687 }
3688 break;
3689
3690 case LV2_PORT_DESIGNATION_TIME_BEAT_UNIT:
3691 if (timeInfo.bbt.valid && carla_isNotEqual(fLastTimeInfo.bbt.beatType, timeInfo.bbt.beatType))
3692 {
3693 fParamBuffers[k] = timeInfo.bbt.beatType;
3694 doPostRt = true;
3695 }
3696 break;
3697 case LV2_PORT_DESIGNATION_TIME_BEATS_PER_BAR:
3698 if (timeInfo.bbt.valid && carla_isNotEqual(fLastTimeInfo.bbt.beatsPerBar, timeInfo.bbt.beatsPerBar))
3699 {
3700 fParamBuffers[k] = timeInfo.bbt.beatsPerBar;
3701 doPostRt = true;
3702 }
3703 break;
3704
3705 case LV2_PORT_DESIGNATION_TIME_BEATS_PER_MINUTE:
3706 if (timeInfo.bbt.valid && carla_isNotEqual(fLastTimeInfo.bbt.beatsPerMinute, timeInfo.bbt.beatsPerMinute))
3707 {
3708 fParamBuffers[k] = static_cast<float>(timeInfo.bbt.beatsPerMinute);
3709 doPostRt = true;
3710 }
3711 break;
3712
3713 case LV2_PORT_DESIGNATION_TIME_TICKS_PER_BEAT:
3714 if (timeInfo.bbt.valid && carla_isNotEqual(fLastTimeInfo.bbt.ticksPerBeat, timeInfo.bbt.ticksPerBeat))
3715 {
3716 fParamBuffers[k] = static_cast<float>(timeInfo.bbt.ticksPerBeat);
3717 doPostRt = true;
3718 }
3719 break;
3720 }
3721
3722 if (doPostRt)
3723 pData->postponeParameterChangeRtEvent(true, static_cast<int32_t>(k), fParamBuffers[k]);
3724 }
3725
3726 for (uint32_t i=0; i < fEventsIn.count; ++i)
3727 {
3728 if ((fEventsIn.data[i].type & CARLA_EVENT_DATA_ATOM) == 0 || (fEventsIn.data[i].type & CARLA_EVENT_TYPE_TIME) == 0)
3729 continue;
3730
3731 uint8_t timeInfoBuf[256];
3732 LV2_Atom_Forge atomForge;
3733 initAtomForge(atomForge);
3734 lv2_atom_forge_set_buffer(&atomForge, timeInfoBuf, sizeof(timeInfoBuf));
3735
3736 LV2_Atom_Forge_Frame forgeFrame;
3737 lv2_atom_forge_object(&atomForge, &forgeFrame, kUridNull, kUridTimePosition);
3738
3739 lv2_atom_forge_key(&atomForge, kUridTimeSpeed);
3740 lv2_atom_forge_float(&atomForge, timeInfo.playing ? 1.0f : 0.0f);
3741
3742 lv2_atom_forge_key(&atomForge, kUridTimeFrame);
3743 lv2_atom_forge_long(&atomForge, static_cast<int64_t>(timeInfo.frame));
3744
3745 if (timeInfo.bbt.valid)
3746 {
3747 lv2_atom_forge_key(&atomForge, kUridTimeBar);
3748 lv2_atom_forge_long(&atomForge, timeInfo.bbt.bar - 1);
3749
3750 lv2_atom_forge_key(&atomForge, kUridTimeBarBeat);
3751 lv2_atom_forge_float(&atomForge, static_cast<float>(barBeat));
3752
3753 lv2_atom_forge_key(&atomForge, kUridTimeBeat);
3754 lv2_atom_forge_double(&atomForge, timeInfo.bbt.beat - 1);
3755
3756 lv2_atom_forge_key(&atomForge, kUridTimeBeatUnit);
3757 lv2_atom_forge_int(&atomForge, static_cast<int32_t>(timeInfo.bbt.beatType));
3758
3759 lv2_atom_forge_key(&atomForge, kUridTimeBeatsPerBar);
3760 lv2_atom_forge_float(&atomForge, timeInfo.bbt.beatsPerBar);
3761
3762 lv2_atom_forge_key(&atomForge, kUridTimeBeatsPerMinute);
3763 lv2_atom_forge_float(&atomForge, static_cast<float>(timeInfo.bbt.beatsPerMinute));
3764
3765 lv2_atom_forge_key(&atomForge, kUridTimeTicksPerBeat);
3766 lv2_atom_forge_double(&atomForge, timeInfo.bbt.ticksPerBeat);
3767 }
3768
3769 lv2_atom_forge_pop(&atomForge, &forgeFrame);
3770
3771 LV2_Atom* const atom((LV2_Atom*)timeInfoBuf);
3772 CARLA_SAFE_ASSERT_BREAK(atom->size < 256);
3773
3774 // send only deprecated blank object for now
3775 lv2_atom_buffer_write(&evInAtomIters[i], 0, 0, kUridAtomBlank, atom->size, LV2_ATOM_BODY_CONST(atom));
3776
3777 // for atom:object
3778 //lv2_atom_buffer_write(&evInAtomIters[i], 0, 0, atom->type, atom->size, LV2_ATOM_BODY_CONST(atom));
3779 }
3780
3781 pData->postRtEvents.trySplice();
3782
3783 fLastTimeInfo = timeInfo;
3784 }
3785
3786 // --------------------------------------------------------------------------------------------------------
3787 // Event Input and Processing
3788
3789 if (fEventsIn.ctrl != nullptr)
3790 {
3791 // ----------------------------------------------------------------------------------------------------
3792 // Message Input
3793
3794 if (fAtomBufferEvIn.tryLock())
3795 {
3796 if (fAtomBufferEvIn.isDataAvailableForReading())
3797 {
3798 const LV2_Atom* atom;
3799 uint32_t j, portIndex;
3800
3801 for (; fAtomBufferEvIn.get(atom, portIndex);)
3802 {
3803 j = (portIndex < fEventsIn.count) ? portIndex : fEventsIn.ctrlIndex;
3804
3805 if (! lv2_atom_buffer_write(&evInAtomIters[j], 0, 0, atom->type, atom->size, LV2_ATOM_BODY_CONST(atom)))
3806 {
3807 carla_stderr2("Event input buffer full, at least 1 message lost");
3808 continue;
3809 }
3810
3811 inspectAtomForParameterChange(atom);
3812 }
3813 }
3814
3815 fAtomBufferEvIn.unlock();
3816 }
3817
3818 // ----------------------------------------------------------------------------------------------------
3819 // MIDI Input (External)
3820
3821 if (pData->extNotes.mutex.tryLock())
3822 {
3823 if ((fEventsIn.ctrl->type & CARLA_EVENT_TYPE_MIDI) == 0)
3824 {
3825 // does not handle MIDI
3826 pData->extNotes.data.clear();
3827 }
3828 else
3829 {
3830 const uint32_t j = fEventsIn.ctrlIndex;
3831
3832 for (RtLinkedList<ExternalMidiNote>::Itenerator it = pData->extNotes.data.begin2(); it.valid(); it.next())
3833 {
3834 const ExternalMidiNote& note(it.getValue(kExternalMidiNoteFallback));
3835 CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS);
3836
3837 uint8_t midiEvent[3];
3838 midiEvent[0] = uint8_t((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT));
3839 midiEvent[1] = note.note;
3840 midiEvent[2] = note.velo;
3841
3842 if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM)
3843 lv2_atom_buffer_write(&evInAtomIters[j], 0, 0, kUridMidiEvent, 3, midiEvent);
3844
3845 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT)
3846 lv2_event_write(&evInEventIters[j], 0, 0, kUridMidiEvent, 3, midiEvent);
3847
3848 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL)
3849 lv2midi_put_event(&evInMidiStates[j], 0.0, 3, midiEvent);
3850 }
3851
3852 pData->extNotes.data.clear();
3853 }
3854
3855 pData->extNotes.mutex.unlock();
3856
3857 } // End of MIDI Input (External)
3858
3859 // ----------------------------------------------------------------------------------------------------
3860 // Event Input (System)
3861
3862 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
3863 bool allNotesOffSent = false;
3864 #endif
3865 bool isSampleAccurate = (pData->options & PLUGIN_OPTION_FIXED_BUFFERS) == 0;
3866
3867 uint32_t startTime = 0;
3868 uint32_t timeOffset = 0;
3869 uint32_t nextBankId;
3870
3871 if (pData->midiprog.current >= 0 && pData->midiprog.count > 0)
3872 nextBankId = pData->midiprog.data[pData->midiprog.current].bank;
3873 else
3874 nextBankId = 0;
3875
3876 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
3877 if (cvIn != nullptr && pData->event.cvSourcePorts != nullptr)
3878 pData->event.cvSourcePorts->initPortBuffers(cvIn + pData->cvIn.count, frames, isSampleAccurate, pData->event.portIn);
3879 #endif
3880
3881 const uint32_t numEvents = (fEventsIn.ctrl->port != nullptr) ? fEventsIn.ctrl->port->getEventCount() : 0;
3882
3883 for (uint32_t i=0; i < numEvents; ++i)
3884 {
3885 EngineEvent& event(fEventsIn.ctrl->port->getEvent(i));
3886
3887 uint32_t eventTime = event.time;
3888 CARLA_SAFE_ASSERT_UINT2_CONTINUE(eventTime < frames, eventTime, frames);
3889
3890 if (eventTime < timeOffset)
3891 {
3892 carla_stderr2("Timing error, eventTime:%u < timeOffset:%u for '%s'",
3893 eventTime, timeOffset, pData->name);
3894 eventTime = timeOffset;
3895 }
3896
3897 if (isSampleAccurate && eventTime > timeOffset)
3898 {
3899 if (processSingle(audioIn, audioOut, cvIn, cvOut, eventTime - timeOffset, timeOffset))
3900 {
3901 startTime = 0;
3902 timeOffset = eventTime;
3903
3904 if (pData->midiprog.current >= 0 && pData->midiprog.count > 0)
3905 nextBankId = pData->midiprog.data[pData->midiprog.current].bank;
3906 else
3907 nextBankId = 0;
3908
3909 for (uint32_t j=0; j < fEventsIn.count; ++j)
3910 {
3911 if (fEventsIn.data[j].type & CARLA_EVENT_DATA_ATOM)
3912 {
3913 lv2_atom_buffer_reset(fEventsIn.data[j].atom, true);
3914 lv2_atom_buffer_begin(&evInAtomIters[j], fEventsIn.data[j].atom);
3915 }
3916 else if (fEventsIn.data[j].type & CARLA_EVENT_DATA_EVENT)
3917 {
3918 lv2_event_buffer_reset(fEventsIn.data[j].event, LV2_EVENT_AUDIO_STAMP, fEventsIn.data[j].event->data);
3919 lv2_event_begin(&evInEventIters[j], fEventsIn.data[j].event);
3920 }
3921 else if (fEventsIn.data[j].type & CARLA_EVENT_DATA_MIDI_LL)
3922 {
3923 fEventsIn.data[j].midi.event_count = 0;
3924 fEventsIn.data[j].midi.size = 0;
3925 evInMidiStates[j].position = eventTime;
3926 }
3927 }
3928
3929 for (uint32_t j=0; j < fEventsOut.count; ++j)
3930 {
3931 if (fEventsOut.data[j].type & CARLA_EVENT_DATA_ATOM)
3932 {
3933 lv2_atom_buffer_reset(fEventsOut.data[j].atom, false);
3934 }
3935 else if (fEventsOut.data[j].type & CARLA_EVENT_DATA_EVENT)
3936 {
3937 lv2_event_buffer_reset(fEventsOut.data[j].event, LV2_EVENT_AUDIO_STAMP, fEventsOut.data[j].event->data);
3938 }
3939 else if (fEventsOut.data[j].type & CARLA_EVENT_DATA_MIDI_LL)
3940 {
3941 // not needed
3942 }
3943 }
3944 }
3945 else
3946 {
3947 startTime += timeOffset;
3948 }
3949 }
3950
3951 switch (event.type)
3952 {
3953 case kEngineEventTypeNull:
3954 break;
3955
3956 case kEngineEventTypeControl: {
3957 EngineControlEvent& ctrlEvent(event.ctrl);
3958
3959 switch (ctrlEvent.type)
3960 {
3961 case kEngineControlEventTypeNull:
3962 break;
3963
3964 case kEngineControlEventTypeParameter: {
3965 float value;
3966
3967 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
3968 // non-midi
3969 if (event.channel == kEngineEventNonMidiChannel)
3970 {
3971 const uint32_t k = ctrlEvent.param;
3972 CARLA_SAFE_ASSERT_CONTINUE(k < pData->param.count);
3973
3974 ctrlEvent.handled = true;
3975 value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.normalizedValue);
3976 setParameterValueRT(k, value, true);
3977 continue;
3978 }
3979
3980 // Control backend stuff
3981 if (event.channel == pData->ctrlChannel)
3982 {
3983 if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0)
3984 {
3985 ctrlEvent.handled = true;
3986 value = ctrlEvent.normalizedValue;
3987 setDryWetRT(value, true);
3988 }
3989 else if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0)
3990 {
3991 ctrlEvent.handled = true;
3992 value = ctrlEvent.normalizedValue*127.0f/100.0f;
3993 setVolumeRT(value, true);
3994 }
3995 else if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0)
3996 {
3997 float left, right;
3998 value = ctrlEvent.normalizedValue/0.5f - 1.0f;
3999
4000 if (value < 0.0f)
4001 {
4002 left = -1.0f;
4003 right = (value*2.0f)+1.0f;
4004 }
4005 else if (value > 0.0f)
4006 {
4007 left = (value*2.0f)-1.0f;
4008 right = 1.0f;
4009 }
4010 else
4011 {
4012 left = -1.0f;
4013 right = 1.0f;
4014 }
4015
4016 ctrlEvent.handled = true;
4017 setBalanceLeftRT(left, true);
4018 setBalanceRightRT(right, true);
4019 }
4020 }
4021 #endif
4022 // Control plugin parameters
4023 uint32_t k;
4024 for (k=0; k < pData->param.count; ++k)
4025 {
4026 if (pData->param.data[k].midiChannel != event.channel)
4027 continue;
4028 if (pData->param.data[k].mappedControlIndex != ctrlEvent.param)
4029 continue;
4030 if (pData->param.data[k].type != PARAMETER_INPUT)
4031 continue;
4032 if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0)
4033 continue;
4034
4035 ctrlEvent.handled = true;
4036
4037 if (pData->param.data[k].mappedFlags & PARAMETER_MAPPING_MIDI_DELTA)
4038 value = pData->param.getFinalValueWithMidiDelta(k, fParamBuffers[k], ctrlEvent.midiValue);
4039 else
4040 value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.normalizedValue);
4041
4042 setParameterValueRT(k, value, true);
4043 }
4044
4045 if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param < MAX_MIDI_VALUE)
4046 {
4047 uint8_t midiData[3];
4048 midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT));
4049 midiData[1] = uint8_t(ctrlEvent.param);
4050 midiData[2] = uint8_t(ctrlEvent.normalizedValue*127.0f);
4051
4052 const uint32_t mtime(isSampleAccurate ? startTime : eventTime);
4053
4054 if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM)
4055 lv2_atom_buffer_write(&evInAtomIters[fEventsIn.ctrlIndex], mtime, 0, kUridMidiEvent, 3, midiData);
4056
4057 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT)
4058 lv2_event_write(&evInEventIters[fEventsIn.ctrlIndex], mtime, 0, kUridMidiEvent, 3, midiData);
4059
4060 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL)
4061 lv2midi_put_event(&evInMidiStates[fEventsIn.ctrlIndex], mtime, 3, midiData);
4062 }
4063
4064 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
4065 if (! ctrlEvent.handled)
4066 checkForMidiLearn(event);
4067 #endif
4068 break;
4069 } // case kEngineControlEventTypeParameter
4070
4071 case kEngineControlEventTypeMidiBank:
4072 if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES)
4073 {
4074 if (event.channel == pData->ctrlChannel)
4075 nextBankId = ctrlEvent.param;
4076 }
4077 else if (pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES)
4078 {
4079 uint8_t midiData[3];
4080 midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT));
4081 midiData[1] = MIDI_CONTROL_BANK_SELECT;
4082 midiData[2] = uint8_t(ctrlEvent.param);
4083
4084 const uint32_t mtime(isSampleAccurate ? startTime : eventTime);
4085
4086 if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM)
4087 lv2_atom_buffer_write(&evInAtomIters[fEventsIn.ctrlIndex], mtime, 0, kUridMidiEvent, 3, midiData);
4088
4089 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT)
4090 lv2_event_write(&evInEventIters[fEventsIn.ctrlIndex], mtime, 0, kUridMidiEvent, 3, midiData);
4091
4092 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL)
4093 lv2midi_put_event(&evInMidiStates[fEventsIn.ctrlIndex], mtime, 3, midiData);
4094 }
4095 break;
4096
4097 case kEngineControlEventTypeMidiProgram:
4098 if (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES)
4099 {
4100 if (event.channel == pData->ctrlChannel)
4101 {
4102 const uint32_t nextProgramId(ctrlEvent.param);
4103
4104 for (uint32_t k=0; k < pData->midiprog.count; ++k)
4105 {
4106 if (pData->midiprog.data[k].bank == nextBankId && pData->midiprog.data[k].program == nextProgramId)
4107 {
4108 setMidiProgramRT(k, true);
4109 break;
4110 }
4111 }
4112 }
4113 }
4114 else if (pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES)
4115 {
4116 uint8_t midiData[2];
4117 midiData[0] = uint8_t(MIDI_STATUS_PROGRAM_CHANGE | (event.channel & MIDI_CHANNEL_BIT));
4118 midiData[1] = uint8_t(ctrlEvent.param);
4119
4120 const uint32_t mtime(isSampleAccurate ? startTime : eventTime);
4121
4122 if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM)
4123 lv2_atom_buffer_write(&evInAtomIters[fEventsIn.ctrlIndex], mtime, 0, kUridMidiEvent, 2, midiData);
4124
4125 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT)
4126 lv2_event_write(&evInEventIters[fEventsIn.ctrlIndex], mtime, 0, kUridMidiEvent, 2, midiData);
4127
4128 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL)
4129 lv2midi_put_event(&evInMidiStates[fEventsIn.ctrlIndex], mtime, 2, midiData);
4130 }
4131 break;
4132
4133 case kEngineControlEventTypeAllSoundOff:
4134 if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
4135 {
4136 const uint32_t mtime(isSampleAccurate ? startTime : eventTime);
4137
4138 uint8_t midiData[3];
4139 midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT));
4140 midiData[1] = MIDI_CONTROL_ALL_SOUND_OFF;
4141 midiData[2] = 0;
4142
4143 if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM)
4144 lv2_atom_buffer_write(&evInAtomIters[fEventsIn.ctrlIndex], mtime, 0, kUridMidiEvent, 3, midiData);
4145
4146 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT)
4147 lv2_event_write(&evInEventIters[fEventsIn.ctrlIndex], mtime, 0, kUridMidiEvent, 3, midiData);
4148
4149 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL)
4150 lv2midi_put_event(&evInMidiStates[fEventsIn.ctrlIndex], mtime, 3, midiData);
4151 }
4152 break;
4153
4154 case kEngineControlEventTypeAllNotesOff:
4155 if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
4156 {
4157 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
4158 if (event.channel == pData->ctrlChannel && ! allNotesOffSent)
4159 {
4160 allNotesOffSent = true;
4161 postponeRtAllNotesOff();
4162 }
4163 #endif
4164
4165 const uint32_t mtime(isSampleAccurate ? startTime : eventTime);
4166
4167 uint8_t midiData[3];
4168 midiData[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (event.channel & MIDI_CHANNEL_BIT));
4169 midiData[1] = MIDI_CONTROL_ALL_NOTES_OFF;
4170 midiData[2] = 0;
4171
4172 if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM)
4173 lv2_atom_buffer_write(&evInAtomIters[fEventsIn.ctrlIndex], mtime, 0, kUridMidiEvent, 3, midiData);
4174
4175 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT)
4176 lv2_event_write(&evInEventIters[fEventsIn.ctrlIndex], mtime, 0, kUridMidiEvent, 3, midiData);
4177
4178 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL)
4179 lv2midi_put_event(&evInMidiStates[fEventsIn.ctrlIndex], mtime, 3, midiData);
4180 }
4181 break;
4182 } // switch (ctrlEvent.type)
4183 break;
4184 } // case kEngineEventTypeControl
4185
4186 case kEngineEventTypeMidi: {
4187 const EngineMidiEvent& midiEvent(event.midi);
4188
4189 const uint8_t* const midiData(midiEvent.size > EngineMidiEvent::kDataSize ? midiEvent.dataExt : midiEvent.data);
4190
4191 uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiData));
4192
4193 if ((status == MIDI_STATUS_NOTE_OFF || status == MIDI_STATUS_NOTE_ON) && (pData->options & PLUGIN_OPTION_SKIP_SENDING_NOTES))
4194 continue;
4195 if (status == MIDI_STATUS_CHANNEL_PRESSURE && (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE) == 0)
4196 continue;
4197 if (status == MIDI_STATUS_CONTROL_CHANGE && (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) == 0)
4198 continue;
4199 if (status == MIDI_STATUS_POLYPHONIC_AFTERTOUCH && (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH) == 0)
4200 continue;
4201 if (status == MIDI_STATUS_PITCH_WHEEL_CONTROL && (pData->options & PLUGIN_OPTION_SEND_PITCHBEND) == 0)
4202 continue;
4203
4204 // Fix bad note-off (per LV2 spec)
4205 if (status == MIDI_STATUS_NOTE_ON && midiData[2] == 0)
4206 status = MIDI_STATUS_NOTE_OFF;
4207
4208 const uint32_t j = fEventsIn.ctrlIndex;
4209 const uint32_t mtime = isSampleAccurate ? startTime : eventTime;
4210
4211 // put back channel in data
4212 uint8_t midiData2[midiEvent.size];
4213 midiData2[0] = uint8_t(status | (event.channel & MIDI_CHANNEL_BIT));
4214 std::memcpy(midiData2+1, midiData+1, static_cast<std::size_t>(midiEvent.size-1));
4215
4216 if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM)
4217 lv2_atom_buffer_write(&evInAtomIters[j], mtime, 0, kUridMidiEvent, midiEvent.size, midiData2);
4218
4219 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_EVENT)
4220 lv2_event_write(&evInEventIters[j], mtime, 0, kUridMidiEvent, midiEvent.size, midiData2);
4221
4222 else if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_MIDI_LL)
4223 lv2midi_put_event(&evInMidiStates[j], mtime, midiEvent.size, midiData2);
4224
4225 if (status == MIDI_STATUS_NOTE_ON)
4226 {
4227 pData->postponeNoteOnRtEvent(true, event.channel, midiData[1], midiData[2]);
4228 }
4229 else if (status == MIDI_STATUS_NOTE_OFF)
4230 {
4231 pData->postponeNoteOffRtEvent(true, event.channel, midiData[1]);
4232 }
4233 } break;
4234 } // switch (event.type)
4235 }
4236
4237 pData->postRtEvents.trySplice();
4238
4239 if (frames > timeOffset)
4240 processSingle(audioIn, audioOut, cvIn, cvOut, frames - timeOffset, timeOffset);
4241
4242 } // End of Event Input and Processing
4243
4244 // --------------------------------------------------------------------------------------------------------
4245 // Plugin processing (no events)
4246
4247 else
4248 {
4249 processSingle(audioIn, audioOut, cvIn, cvOut, frames, 0);
4250
4251 } // End of Plugin processing (no events)
4252
4253 // --------------------------------------------------------------------------------------------------------
4254 // Final work
4255
4256 if (fEventsIn.ctrl != nullptr && fExt.worker != nullptr && fAtomBufferWorkerResp.tryLock())
4257 {
4258 if (fAtomBufferWorkerResp.isDataAvailableForReading())
4259 {
4260 const LV2_Atom* atom;
4261 uint32_t portIndex;
4262
4263 for (; fAtomBufferWorkerResp.get(atom, portIndex);)
4264 {
4265 CARLA_SAFE_ASSERT_CONTINUE(atom->type == kUridCarlaAtomWorkerResp);
4266 fExt.worker->work_response(fHandle, atom->size, LV2_ATOM_BODY_CONST(atom));
4267 }
4268 }
4269
4270 fAtomBufferWorkerResp.unlock();
4271 }
4272
4273 if (fExt.worker != nullptr && fExt.worker->end_run != nullptr)
4274 {
4275 fExt.worker->end_run(fHandle);
4276
4277 if (fHandle2 != nullptr)
4278 fExt.worker->end_run(fHandle2);
4279 }
4280
4281 // --------------------------------------------------------------------------------------------------------
4282 // Events/MIDI Output
4283
4284 for (uint32_t i=0; i < fEventsOut.count; ++i)
4285 {
4286 uint32_t lastFrame = 0;
4287 Lv2EventData& evData(fEventsOut.data[i]);
4288
4289 if (evData.type & CARLA_EVENT_DATA_ATOM)
4290 {
4291 const LV2_Atom_Event* ev;
4292 LV2_Atom_Buffer_Iterator iter;
4293
4294 uint8_t* data;
4295 lv2_atom_buffer_begin(&iter, evData.atom);
4296
4297 for (;;)
4298 {
4299 data = nullptr;
4300 ev = lv2_atom_buffer_get(&iter, &data);
4301
4302 if (ev == nullptr || ev->body.size == 0 || data == nullptr)
4303 break;
4304
4305 if (ev->body.type == kUridMidiEvent)
4306 {
4307 if (evData.port != nullptr)
4308 {
4309 CARLA_SAFE_ASSERT_CONTINUE(ev->time.frames >= 0);
4310 CARLA_SAFE_ASSERT_CONTINUE(ev->body.size < 0xFF);
4311
4312 uint32_t currentFrame = static_cast<uint32_t>(ev->time.frames);
4313 if (currentFrame < lastFrame)
4314 currentFrame = lastFrame;
4315 else if (currentFrame >= frames)
4316 currentFrame = frames - 1;
4317
4318 evData.port->writeMidiEvent(currentFrame, static_cast<uint8_t>(ev->body.size), data);
4319 }
4320 }
4321 else if (fAtomBufferUiOutTmpData != nullptr)
4322 {
4323 fAtomBufferUiOut.put(&ev->body, evData.rindex);
4324 }
4325
4326 lv2_atom_buffer_increment(&iter);
4327 }
4328 }
4329 else if ((evData.type & CARLA_EVENT_DATA_EVENT) != 0 && evData.port != nullptr)
4330 {
4331 const LV2_Event* ev;
4332 LV2_Event_Iterator iter;
4333
4334 uint8_t* data;
4335 lv2_event_begin(&iter, evData.event);
4336
4337 for (;;)
4338 {
4339 data = nullptr;
4340 ev = lv2_event_get(&iter, &data);
4341
4342 if (ev == nullptr || data == nullptr)
4343 break;
4344
4345 uint32_t currentFrame = ev->frames;
4346 if (currentFrame < lastFrame)
4347 currentFrame = lastFrame;
4348 else if (currentFrame >= frames)
4349 currentFrame = frames - 1;
4350
4351 if (ev->type == kUridMidiEvent)
4352 {
4353 CARLA_SAFE_ASSERT_CONTINUE(ev->size < 0xFF);
4354 evData.port->writeMidiEvent(currentFrame, static_cast<uint8_t>(ev->size), data);
4355 }
4356
4357 lv2_event_increment(&iter);
4358 }
4359 }
4360 else if ((evData.type & CARLA_EVENT_DATA_MIDI_LL) != 0 && evData.port != nullptr)
4361 {
4362 LV2_MIDIState state = { &evData.midi, frames, 0 };
4363
4364 uint32_t eventSize;
4365 double eventTime;
4366 uchar* eventData;
4367
4368 for (;;)
4369 {
4370 eventSize = 0;
4371 eventTime = 0.0;
4372 eventData = nullptr;
4373 lv2midi_get_event(&state, &eventTime, &eventSize, &eventData);
4374
4375 if (eventData == nullptr || eventSize == 0)
4376 break;
4377
4378 CARLA_SAFE_ASSERT_CONTINUE(eventSize < 0xFF);
4379 CARLA_SAFE_ASSERT_CONTINUE(eventTime >= 0.0);
4380
4381 evData.port->writeMidiEvent(static_cast<uint32_t>(eventTime), static_cast<uint8_t>(eventSize), eventData);
4382 lv2midi_step(&state);
4383 }
4384 }
4385 }
4386
4387 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
4388 // --------------------------------------------------------------------------------------------------------
4389 // Control Output
4390
4391 if (pData->event.portOut != nullptr)
4392 {
4393 uint8_t channel;
4394 uint16_t param;
4395 float value;
4396
4397 for (uint32_t k=0; k < pData->param.count; ++k)
4398 {
4399 if (pData->param.data[k].type != PARAMETER_OUTPUT)
4400 continue;
4401
4402 if (fStrictBounds >= 0 && (pData->param.data[k].hints & PARAMETER_IS_STRICT_BOUNDS) != 0)
4403 // plugin is responsible to ensure correct bounds
4404 pData->param.ranges[k].fixValue(fParamBuffers[k]);
4405
4406 if (pData->param.data[k].mappedControlIndex > 0)
4407 {
4408 channel = pData->param.data[k].midiChannel;
4409 param = static_cast<uint16_t>(pData->param.data[k].mappedControlIndex);
4410 value = pData->param.ranges[k].getNormalizedValue(fParamBuffers[k]);
4411 pData->event.portOut->writeControlEvent(0, channel, kEngineControlEventTypeParameter,
4412 param, -1, value);
4413 }
4414 }
4415 } // End of Control Output
4416 #endif
4417
4418 fFirstActive = false;
4419
4420 // --------------------------------------------------------------------------------------------------------
4421 }
4422
processSingle(const float * const * const audioIn,float ** const audioOut,const float * const * const cvIn,float ** const cvOut,const uint32_t frames,const uint32_t timeOffset)4423 bool processSingle(const float* const* const audioIn, float** const audioOut,
4424 const float* const* const cvIn, float** const cvOut,
4425 const uint32_t frames, const uint32_t timeOffset)
4426 {
4427 CARLA_SAFE_ASSERT_RETURN(frames > 0, false);
4428
4429 if (pData->audioIn.count > 0)
4430 {
4431 CARLA_SAFE_ASSERT_RETURN(audioIn != nullptr, false);
4432 CARLA_SAFE_ASSERT_RETURN(fAudioInBuffers != nullptr, false);
4433 }
4434 if (pData->audioOut.count > 0)
4435 {
4436 CARLA_SAFE_ASSERT_RETURN(audioOut != nullptr, false);
4437 CARLA_SAFE_ASSERT_RETURN(fAudioOutBuffers != nullptr, false);
4438 }
4439 if (pData->cvIn.count > 0)
4440 {
4441 CARLA_SAFE_ASSERT_RETURN(cvIn != nullptr, false);
4442 }
4443 if (pData->cvOut.count > 0)
4444 {
4445 CARLA_SAFE_ASSERT_RETURN(cvOut != nullptr, false);
4446 }
4447
4448 // --------------------------------------------------------------------------------------------------------
4449 // Try lock, silence otherwise
4450
4451 #ifndef STOAT_TEST_BUILD
4452 if (pData->engine->isOffline())
4453 {
4454 pData->singleMutex.lock();
4455 }
4456 else
4457 #endif
4458 if (! pData->singleMutex.tryLock())
4459 {
4460 for (uint32_t i=0; i < pData->audioOut.count; ++i)
4461 {
4462 for (uint32_t k=0; k < frames; ++k)
4463 audioOut[i][k+timeOffset] = 0.0f;
4464 }
4465 for (uint32_t i=0; i < pData->cvOut.count; ++i)
4466 {
4467 for (uint32_t k=0; k < frames; ++k)
4468 cvOut[i][k+timeOffset] = 0.0f;
4469 }
4470
4471 return false;
4472 }
4473
4474 // --------------------------------------------------------------------------------------------------------
4475 // Set audio buffers
4476
4477 for (uint32_t i=0; i < pData->audioIn.count; ++i)
4478 carla_copyFloats(fAudioInBuffers[i], audioIn[i]+timeOffset, frames);
4479
4480 for (uint32_t i=0; i < pData->audioOut.count; ++i)
4481 carla_zeroFloats(fAudioOutBuffers[i], frames);
4482
4483 // --------------------------------------------------------------------------------------------------------
4484 // Set CV buffers
4485
4486 for (uint32_t i=0; i < pData->cvIn.count; ++i)
4487 carla_copyFloats(fCvInBuffers[i], cvIn[i]+timeOffset, frames);
4488
4489 for (uint32_t i=0; i < pData->cvOut.count; ++i)
4490 carla_zeroFloats(fCvOutBuffers[i], frames);
4491
4492 // --------------------------------------------------------------------------------------------------------
4493 // Run plugin
4494
4495 fDescriptor->run(fHandle, frames);
4496
4497 if (fHandle2 != nullptr)
4498 fDescriptor->run(fHandle2, frames);
4499
4500 // --------------------------------------------------------------------------------------------------------
4501 // Handle trigger parameters
4502
4503 for (uint32_t k=0; k < pData->param.count; ++k)
4504 {
4505 if (pData->param.data[k].type != PARAMETER_INPUT)
4506 continue;
4507
4508 if (pData->param.data[k].hints & PARAMETER_IS_TRIGGER)
4509 {
4510 if (carla_isNotEqual(fParamBuffers[k], pData->param.ranges[k].def))
4511 {
4512 fParamBuffers[k] = pData->param.ranges[k].def;
4513 pData->postponeParameterChangeRtEvent(true, static_cast<int32_t>(k), fParamBuffers[k]);
4514 }
4515 }
4516 }
4517
4518 pData->postRtEvents.trySplice();
4519
4520 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
4521 // --------------------------------------------------------------------------------------------------------
4522 // Post-processing (dry/wet, volume and balance)
4523
4524 {
4525 const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && carla_isNotEqual(pData->postProc.dryWet, 1.0f);
4526 const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && ! (carla_isEqual(pData->postProc.balanceLeft, -1.0f) && carla_isEqual(pData->postProc.balanceRight, 1.0f));
4527 const bool isMono = (pData->audioIn.count == 1);
4528
4529 bool isPair;
4530 float bufValue, oldBufLeft[doBalance ? frames : 1];
4531
4532 for (uint32_t i=0; i < pData->audioOut.count; ++i)
4533 {
4534 // Dry/Wet
4535 if (doDryWet)
4536 {
4537 const uint32_t c = isMono ? 0 : i;
4538
4539 for (uint32_t k=0; k < frames; ++k)
4540 {
4541 # ifndef BUILD_BRIDGE
4542 if (k < pData->latency.frames && pData->latency.buffers != nullptr)
4543 bufValue = pData->latency.buffers[c][k];
4544 else if (pData->latency.frames < frames)
4545 bufValue = fAudioInBuffers[c][k-pData->latency.frames];
4546 else
4547 # endif
4548 bufValue = fAudioInBuffers[c][k];
4549
4550 fAudioOutBuffers[i][k] = (fAudioOutBuffers[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet));
4551 }
4552 }
4553
4554 // Balance
4555 if (doBalance)
4556 {
4557 isPair = (i % 2 == 0);
4558
4559 if (isPair)
4560 {
4561 CARLA_ASSERT(i+1 < pData->audioOut.count);
4562 carla_copyFloats(oldBufLeft, fAudioOutBuffers[i], frames);
4563 }
4564
4565 float balRangeL = (pData->postProc.balanceLeft + 1.0f)/2.0f;
4566 float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f;
4567
4568 for (uint32_t k=0; k < frames; ++k)
4569 {
4570 if (isPair)
4571 {
4572 // left
4573 fAudioOutBuffers[i][k] = oldBufLeft[k] * (1.0f - balRangeL);
4574 fAudioOutBuffers[i][k] += fAudioOutBuffers[i+1][k] * (1.0f - balRangeR);
4575 }
4576 else
4577 {
4578 // right
4579 fAudioOutBuffers[i][k] = fAudioOutBuffers[i][k] * balRangeR;
4580 fAudioOutBuffers[i][k] += oldBufLeft[k] * balRangeL;
4581 }
4582 }
4583 }
4584
4585 // Volume (and buffer copy)
4586 {
4587 for (uint32_t k=0; k < frames; ++k)
4588 audioOut[i][k+timeOffset] = fAudioOutBuffers[i][k] * pData->postProc.volume;
4589 }
4590 }
4591 } // End of Post-processing
4592
4593 # ifndef BUILD_BRIDGE
4594 // --------------------------------------------------------------------------------------------------------
4595 // Save latency values for next callback
4596
4597 if (pData->latency.frames != 0 && pData->latency.buffers != nullptr)
4598 {
4599 CARLA_SAFE_ASSERT(timeOffset == 0);
4600 const uint32_t latframes = pData->latency.frames;
4601
4602 if (latframes <= frames)
4603 {
4604 for (uint32_t i=0; i < pData->audioIn.count; ++i)
4605 carla_copyFloats(pData->latency.buffers[i], audioIn[i]+(frames-latframes), latframes);
4606 }
4607 else
4608 {
4609 const uint32_t diff = latframes - frames;
4610
4611 for (uint32_t i=0, k; i<pData->audioIn.count; ++i)
4612 {
4613 // push back buffer by 'frames'
4614 for (k=0; k < diff; ++k)
4615 pData->latency.buffers[i][k] = pData->latency.buffers[i][k+frames];
4616
4617 // put current input at the end
4618 for (uint32_t j=0; k < latframes; ++j, ++k)
4619 pData->latency.buffers[i][k] = audioIn[i][j];
4620 }
4621 }
4622 }
4623 # endif
4624 #else // BUILD_BRIDGE_ALTERNATIVE_ARCH
4625 for (uint32_t i=0; i < pData->audioOut.count; ++i)
4626 {
4627 for (uint32_t k=0; k < frames; ++k)
4628 audioOut[i][k+timeOffset] = fAudioOutBuffers[i][k];
4629 }
4630 #endif
4631
4632 for (uint32_t i=0; i < pData->cvOut.count; ++i)
4633 {
4634 for (uint32_t k=0; k < frames; ++k)
4635 cvOut[i][k+timeOffset] = fCvOutBuffers[i][k];
4636 }
4637
4638 // --------------------------------------------------------------------------------------------------------
4639
4640 pData->singleMutex.unlock();
4641 return true;
4642 }
4643
bufferSizeChanged(const uint32_t newBufferSize)4644 void bufferSizeChanged(const uint32_t newBufferSize) override
4645 {
4646 CARLA_ASSERT_INT(newBufferSize > 0, newBufferSize);
4647 carla_debug("CarlaPluginLV2::bufferSizeChanged(%i) - start", newBufferSize);
4648
4649 for (uint32_t i=0; i < pData->audioIn.count; ++i)
4650 {
4651 if (fAudioInBuffers[i] != nullptr)
4652 delete[] fAudioInBuffers[i];
4653 fAudioInBuffers[i] = new float[newBufferSize];
4654 }
4655
4656 for (uint32_t i=0; i < pData->audioOut.count; ++i)
4657 {
4658 if (fAudioOutBuffers[i] != nullptr)
4659 delete[] fAudioOutBuffers[i];
4660 fAudioOutBuffers[i] = new float[newBufferSize];
4661 }
4662
4663 if (fHandle2 == nullptr)
4664 {
4665 for (uint32_t i=0; i < pData->audioIn.count; ++i)
4666 {
4667 CARLA_ASSERT(fAudioInBuffers[i] != nullptr);
4668 fDescriptor->connect_port(fHandle, pData->audioIn.ports[i].rindex, fAudioInBuffers[i]);
4669 }
4670
4671 for (uint32_t i=0; i < pData->audioOut.count; ++i)
4672 {
4673 CARLA_ASSERT(fAudioOutBuffers[i] != nullptr);
4674 fDescriptor->connect_port(fHandle, pData->audioOut.ports[i].rindex, fAudioOutBuffers[i]);
4675 }
4676 }
4677 else
4678 {
4679 if (pData->audioIn.count > 0)
4680 {
4681 CARLA_ASSERT(pData->audioIn.count == 2);
4682 CARLA_ASSERT(fAudioInBuffers[0] != nullptr);
4683 CARLA_ASSERT(fAudioInBuffers[1] != nullptr);
4684
4685 fDescriptor->connect_port(fHandle, pData->audioIn.ports[0].rindex, fAudioInBuffers[0]);
4686 fDescriptor->connect_port(fHandle2, pData->audioIn.ports[1].rindex, fAudioInBuffers[1]);
4687 }
4688
4689 if (pData->audioOut.count > 0)
4690 {
4691 CARLA_ASSERT(pData->audioOut.count == 2);
4692 CARLA_ASSERT(fAudioOutBuffers[0] != nullptr);
4693 CARLA_ASSERT(fAudioOutBuffers[1] != nullptr);
4694
4695 fDescriptor->connect_port(fHandle, pData->audioOut.ports[0].rindex, fAudioOutBuffers[0]);
4696 fDescriptor->connect_port(fHandle2, pData->audioOut.ports[1].rindex, fAudioOutBuffers[1]);
4697 }
4698 }
4699
4700 for (uint32_t i=0; i < pData->cvIn.count; ++i)
4701 {
4702 if (fCvInBuffers[i] != nullptr)
4703 delete[] fCvInBuffers[i];
4704 fCvInBuffers[i] = new float[newBufferSize];
4705
4706 fDescriptor->connect_port(fHandle, pData->cvIn.ports[i].rindex, fCvInBuffers[i]);
4707
4708 if (fHandle2 != nullptr)
4709 fDescriptor->connect_port(fHandle2, pData->cvIn.ports[i].rindex, fCvInBuffers[i]);
4710 }
4711
4712 for (uint32_t i=0; i < pData->cvOut.count; ++i)
4713 {
4714 if (fCvOutBuffers[i] != nullptr)
4715 delete[] fCvOutBuffers[i];
4716 fCvOutBuffers[i] = new float[newBufferSize];
4717
4718 fDescriptor->connect_port(fHandle, pData->cvOut.ports[i].rindex, fCvOutBuffers[i]);
4719
4720 if (fHandle2 != nullptr)
4721 fDescriptor->connect_port(fHandle2, pData->cvOut.ports[i].rindex, fCvOutBuffers[i]);
4722 }
4723
4724 const int newBufferSizeInt(static_cast<int>(newBufferSize));
4725
4726 if (fLv2Options.maxBufferSize != newBufferSizeInt || (fLv2Options.minBufferSize != 1 && fLv2Options.minBufferSize != newBufferSizeInt))
4727 {
4728 fLv2Options.maxBufferSize = fLv2Options.nominalBufferSize = newBufferSizeInt;
4729
4730 if (fLv2Options.minBufferSize != 1)
4731 fLv2Options.minBufferSize = newBufferSizeInt;
4732
4733 if (fExt.options != nullptr && fExt.options->set != nullptr)
4734 {
4735 LV2_Options_Option options[4];
4736 carla_zeroStructs(options, 4);
4737
4738 carla_copyStruct(options[0], fLv2Options.opts[CarlaPluginLV2Options::MaxBlockLenth]);
4739 carla_copyStruct(options[1], fLv2Options.opts[CarlaPluginLV2Options::NominalBlockLenth]);
4740
4741 if (fLv2Options.minBufferSize != 1)
4742 carla_copyStruct(options[2], fLv2Options.opts[CarlaPluginLV2Options::MinBlockLenth]);
4743
4744 fExt.options->set(fHandle, options);
4745 }
4746 }
4747
4748 carla_debug("CarlaPluginLV2::bufferSizeChanged(%i) - end", newBufferSize);
4749 }
4750
sampleRateChanged(const double newSampleRate)4751 void sampleRateChanged(const double newSampleRate) override
4752 {
4753 CARLA_ASSERT_INT(newSampleRate > 0.0, newSampleRate);
4754 carla_debug("CarlaPluginLV2::sampleRateChanged(%g) - start", newSampleRate);
4755
4756 const float sampleRatef = static_cast<float>(newSampleRate);
4757
4758 if (carla_isNotEqual(fLv2Options.sampleRate, sampleRatef))
4759 {
4760 fLv2Options.sampleRate = sampleRatef;
4761
4762 if (fExt.options != nullptr && fExt.options->set != nullptr)
4763 {
4764 LV2_Options_Option options[2];
4765 carla_copyStruct(options[0], fLv2Options.opts[CarlaPluginLV2Options::SampleRate]);
4766 carla_zeroStruct(options[1]);
4767
4768 fExt.options->set(fHandle, options);
4769 }
4770 }
4771
4772 for (uint32_t k=0; k < pData->param.count; ++k)
4773 {
4774 if (pData->param.data[k].type != PARAMETER_INPUT)
4775 continue;
4776 if (pData->param.special[k] != PARAMETER_SPECIAL_SAMPLE_RATE)
4777 continue;
4778
4779 fParamBuffers[k] = sampleRatef;
4780 pData->postponeParameterChangeRtEvent(true, static_cast<int32_t>(k), fParamBuffers[k]);
4781 break;
4782 }
4783
4784 carla_debug("CarlaPluginLV2::sampleRateChanged(%g) - end", newSampleRate);
4785 }
4786
offlineModeChanged(const bool isOffline)4787 void offlineModeChanged(const bool isOffline) override
4788 {
4789 for (uint32_t k=0; k < pData->param.count; ++k)
4790 {
4791 if (pData->param.data[k].type == PARAMETER_INPUT && pData->param.special[k] == PARAMETER_SPECIAL_FREEWHEEL)
4792 {
4793 fParamBuffers[k] = isOffline ? pData->param.ranges[k].max : pData->param.ranges[k].min;
4794 pData->postponeParameterChangeRtEvent(true, static_cast<int32_t>(k), fParamBuffers[k]);
4795 break;
4796 }
4797 }
4798 }
4799
4800 // -------------------------------------------------------------------
4801 // Plugin buffers
4802
initBuffers() const4803 void initBuffers() const noexcept override
4804 {
4805 fEventsIn.initBuffers();
4806 fEventsOut.initBuffers();
4807
4808 CarlaPlugin::initBuffers();
4809 }
4810
clearBuffers()4811 void clearBuffers() noexcept override
4812 {
4813 carla_debug("CarlaPluginLV2::clearBuffers() - start");
4814
4815 if (fAudioInBuffers != nullptr)
4816 {
4817 for (uint32_t i=0; i < pData->audioIn.count; ++i)
4818 {
4819 if (fAudioInBuffers[i] != nullptr)
4820 {
4821 delete[] fAudioInBuffers[i];
4822 fAudioInBuffers[i] = nullptr;
4823 }
4824 }
4825
4826 delete[] fAudioInBuffers;
4827 fAudioInBuffers = nullptr;
4828 }
4829
4830 if (fAudioOutBuffers != nullptr)
4831 {
4832 for (uint32_t i=0; i < pData->audioOut.count; ++i)
4833 {
4834 if (fAudioOutBuffers[i] != nullptr)
4835 {
4836 delete[] fAudioOutBuffers[i];
4837 fAudioOutBuffers[i] = nullptr;
4838 }
4839 }
4840
4841 delete[] fAudioOutBuffers;
4842 fAudioOutBuffers = nullptr;
4843 }
4844
4845 if (fCvInBuffers != nullptr)
4846 {
4847 for (uint32_t i=0; i < pData->cvIn.count; ++i)
4848 {
4849 if (fCvInBuffers[i] != nullptr)
4850 {
4851 delete[] fCvInBuffers[i];
4852 fCvInBuffers[i] = nullptr;
4853 }
4854 }
4855
4856 delete[] fCvInBuffers;
4857 fCvInBuffers = nullptr;
4858 }
4859
4860 if (fCvOutBuffers != nullptr)
4861 {
4862 for (uint32_t i=0; i < pData->cvOut.count; ++i)
4863 {
4864 if (fCvOutBuffers[i] != nullptr)
4865 {
4866 delete[] fCvOutBuffers[i];
4867 fCvOutBuffers[i] = nullptr;
4868 }
4869 }
4870
4871 delete[] fCvOutBuffers;
4872 fCvOutBuffers = nullptr;
4873 }
4874
4875 if (fParamBuffers != nullptr)
4876 {
4877 delete[] fParamBuffers;
4878 fParamBuffers = nullptr;
4879 }
4880
4881 fEventsIn.clear(pData->event.portIn);
4882 fEventsOut.clear(pData->event.portOut);
4883
4884 CarlaPlugin::clearBuffers();
4885
4886 carla_debug("CarlaPluginLV2::clearBuffers() - end");
4887 }
4888
4889 // -------------------------------------------------------------------
4890 // Post-poned UI Stuff
4891
uiParameterChange(const uint32_t index,const float value)4892 void uiParameterChange(const uint32_t index, const float value) noexcept override
4893 {
4894 CARLA_SAFE_ASSERT_RETURN(fUI.type != UI::TYPE_NULL || fFilePathURI.isNotEmpty(),);
4895 CARLA_SAFE_ASSERT_RETURN(index < pData->param.count,);
4896 CARLA_SAFE_ASSERT_RETURN(pData->param.data[index].rindex >= 0,);
4897
4898 if (fUI.type == UI::TYPE_BRIDGE)
4899 {
4900 if (! fPipeServer.isPipeRunning())
4901 return;
4902 }
4903 else
4904 {
4905 if (fUI.handle == nullptr)
4906 return;
4907 if (fUI.descriptor == nullptr || fUI.descriptor->port_event == nullptr)
4908 return;
4909 if (fNeedsUiClose)
4910 return;
4911 }
4912
4913 ParameterData& pdata(pData->param.data[index]);
4914
4915 if (pdata.hints & PARAMETER_IS_NOT_SAVED)
4916 {
4917 int32_t rindex = pdata.rindex;
4918 CARLA_SAFE_ASSERT_RETURN(rindex - static_cast<int32_t>(fRdfDescriptor->PortCount) >= 0,);
4919
4920 rindex -= static_cast<int32_t>(fRdfDescriptor->PortCount);
4921 CARLA_SAFE_ASSERT_RETURN(rindex < static_cast<int32_t>(fRdfDescriptor->ParameterCount),);
4922
4923 const char* const uri = fRdfDescriptor->Parameters[rindex].URI;
4924
4925 if (fUI.type == UI::TYPE_BRIDGE)
4926 {
4927 fPipeServer.writeLv2ParameterMessage(uri, value);
4928 }
4929 else if (fEventsIn.ctrl != nullptr)
4930 {
4931 uint8_t atomBuf[256];
4932 LV2_Atom_Forge atomForge;
4933 initAtomForge(atomForge);
4934 lv2_atom_forge_set_buffer(&atomForge, atomBuf, sizeof(atomBuf));
4935
4936 LV2_Atom_Forge_Frame forgeFrame;
4937 lv2_atom_forge_object(&atomForge, &forgeFrame, kUridNull, kUridPatchSet);
4938
4939 lv2_atom_forge_key(&atomForge, kUridCarlaParameterChange);
4940 lv2_atom_forge_bool(&atomForge, true);
4941
4942 lv2_atom_forge_key(&atomForge, kUridPatchProperty);
4943 lv2_atom_forge_urid(&atomForge, getCustomURID(uri));
4944
4945 lv2_atom_forge_key(&atomForge, kUridPatchValue);
4946
4947 switch (fRdfDescriptor->Parameters[rindex].Type)
4948 {
4949 case LV2_PARAMETER_TYPE_BOOL:
4950 lv2_atom_forge_bool(&atomForge, value > 0.5f);
4951 break;
4952 case LV2_PARAMETER_TYPE_INT:
4953 lv2_atom_forge_int(&atomForge, static_cast<int32_t>(value + 0.5f));
4954 break;
4955 case LV2_PARAMETER_TYPE_LONG:
4956 lv2_atom_forge_long(&atomForge, static_cast<int64_t>(value + 0.5f));
4957 break;
4958 case LV2_PARAMETER_TYPE_FLOAT:
4959 lv2_atom_forge_float(&atomForge, value);
4960 break;
4961 case LV2_PARAMETER_TYPE_DOUBLE:
4962 lv2_atom_forge_double(&atomForge, value);
4963 break;
4964 default:
4965 carla_stderr2("uiParameterChange called for invalid parameter, abort!");
4966 return;
4967 }
4968
4969 lv2_atom_forge_pop(&atomForge, &forgeFrame);
4970
4971 LV2_Atom* const atom((LV2_Atom*)atomBuf);
4972 CARLA_SAFE_ASSERT(atom->size < sizeof(atomBuf));
4973
4974 fUI.descriptor->port_event(fUI.handle,
4975 fEventsIn.ctrl->rindex,
4976 lv2_atom_total_size(atom),
4977 kUridAtomTransferEvent,
4978 atom);
4979 }
4980 }
4981 else
4982 {
4983 if (fUI.type == UI::TYPE_BRIDGE)
4984 {
4985 fPipeServer.writeControlMessage(static_cast<uint32_t>(pData->param.data[index].rindex), value);
4986 }
4987 else
4988 {
4989 fUI.descriptor->port_event(fUI.handle,
4990 static_cast<uint32_t>(pData->param.data[index].rindex),
4991 sizeof(float), kUridNull, &value);
4992 }
4993 }
4994 }
4995
uiMidiProgramChange(const uint32_t index)4996 void uiMidiProgramChange(const uint32_t index) noexcept override
4997 {
4998 CARLA_SAFE_ASSERT_RETURN(fUI.type != UI::TYPE_NULL || fFilePathURI.isNotEmpty(),);
4999 CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,);
5000
5001 if (fUI.type == UI::TYPE_BRIDGE)
5002 {
5003 if (fPipeServer.isPipeRunning())
5004 fPipeServer.writeMidiProgramMessage(pData->midiprog.data[index].bank, pData->midiprog.data[index].program);
5005 }
5006 else
5007 {
5008 if (fExt.uiprograms != nullptr && fExt.uiprograms->select_program != nullptr && ! fNeedsUiClose)
5009 fExt.uiprograms->select_program(fUI.handle, pData->midiprog.data[index].bank, pData->midiprog.data[index].program);
5010 }
5011 }
5012
uiNoteOn(const uint8_t channel,const uint8_t note,const uint8_t velo)5013 void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) noexcept override
5014 {
5015 CARLA_SAFE_ASSERT_RETURN(fUI.type != UI::TYPE_NULL || fFilePathURI.isNotEmpty(),);
5016 CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
5017 CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
5018 CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,);
5019
5020 #if 0
5021 if (fUI.type == UI::TYPE_BRIDGE)
5022 {
5023 if (fPipeServer.isPipeRunning())
5024 fPipeServer.writeMidiNoteMessage(false, channel, note, velo);
5025 }
5026 else
5027 {
5028 if (fUI.handle != nullptr && fUI.descriptor != nullptr && fUI.descriptor->port_event != nullptr && fEventsIn.ctrl != nullptr && ! fNeedsUiClose)
5029 {
5030 LV2_Atom_MidiEvent midiEv;
5031 midiEv.atom.type = kUridMidiEvent;
5032 midiEv.atom.size = 3;
5033 midiEv.data[0] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT));
5034 midiEv.data[1] = note;
5035 midiEv.data[2] = velo;
5036
5037 fUI.descriptor->port_event(fUI.handle, fEventsIn.ctrl->rindex, lv2_atom_total_size(midiEv), kUridAtomTransferEvent, &midiEv);
5038 }
5039 }
5040 #endif
5041 }
5042
uiNoteOff(const uint8_t channel,const uint8_t note)5043 void uiNoteOff(const uint8_t channel, const uint8_t note) noexcept override
5044 {
5045 CARLA_SAFE_ASSERT_RETURN(fUI.type != UI::TYPE_NULL || fFilePathURI.isNotEmpty(),);
5046 CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,);
5047 CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
5048
5049 #if 0
5050 if (fUI.type == UI::TYPE_BRIDGE)
5051 {
5052 if (fPipeServer.isPipeRunning())
5053 fPipeServer.writeMidiNoteMessage(false, channel, note, 0);
5054 }
5055 else
5056 {
5057 if (fUI.handle != nullptr && fUI.descriptor != nullptr && fUI.descriptor->port_event != nullptr && fEventsIn.ctrl != nullptr && ! fNeedsUiClose)
5058 {
5059 LV2_Atom_MidiEvent midiEv;
5060 midiEv.atom.type = kUridMidiEvent;
5061 midiEv.atom.size = 3;
5062 midiEv.data[0] = uint8_t(MIDI_STATUS_NOTE_OFF | (channel & MIDI_CHANNEL_BIT));
5063 midiEv.data[1] = note;
5064 midiEv.data[2] = 0;
5065
5066 fUI.descriptor->port_event(fUI.handle, fEventsIn.ctrl->rindex, lv2_atom_total_size(midiEv), kUridAtomTransferEvent, &midiEv);
5067 }
5068 }
5069 #endif
5070 }
5071
5072 // -------------------------------------------------------------------
5073 // Internal helper functions
5074
cloneLV2Files(const CarlaPlugin & other)5075 void cloneLV2Files(const CarlaPlugin& other) override
5076 {
5077 CARLA_SAFE_ASSERT_RETURN(other.getType() == PLUGIN_LV2,);
5078
5079 const CarlaPluginLV2& otherLV2((const CarlaPluginLV2&)other);
5080
5081 const File tmpDir(handleStateMapToAbsolutePath(false, false, true, "."));
5082
5083 if (tmpDir.exists())
5084 tmpDir.deleteRecursively();
5085
5086 const File otherStateDir(otherLV2.handleStateMapToAbsolutePath(false, false, false, "."));
5087
5088 if (otherStateDir.exists())
5089 otherStateDir.copyDirectoryTo(tmpDir);
5090
5091 const File otherTmpDir(otherLV2.handleStateMapToAbsolutePath(false, false, true, "."));
5092
5093 if (otherTmpDir.exists())
5094 otherTmpDir.copyDirectoryTo(tmpDir);
5095 }
5096
restoreLV2State(const bool temporary)5097 void restoreLV2State(const bool temporary) noexcept override
5098 {
5099 if (fExt.state == nullptr || fExt.state->restore == nullptr)
5100 return;
5101
5102 if (! temporary)
5103 {
5104 const File tmpDir(handleStateMapToAbsolutePath(false, false, true, "."));
5105
5106 if (tmpDir.exists())
5107 tmpDir.deleteRecursively();
5108 }
5109
5110 LV2_State_Status status = LV2_STATE_ERR_UNKNOWN;
5111
5112 {
5113 const ScopedSingleProcessLocker spl(this, !fHasThreadSafeRestore);
5114
5115 try {
5116 status = fExt.state->restore(fHandle,
5117 carla_lv2_state_retrieve,
5118 this,
5119 LV2_STATE_IS_POD,
5120 temporary ? fFeatures : fStateFeatures);
5121 } catch(...) {}
5122
5123 if (fHandle2 != nullptr)
5124 {
5125 try {
5126 fExt.state->restore(fHandle,
5127 carla_lv2_state_retrieve,
5128 this,
5129 LV2_STATE_IS_POD,
5130 temporary ? fFeatures : fStateFeatures);
5131 } catch(...) {}
5132 }
5133 }
5134
5135 switch (status)
5136 {
5137 case LV2_STATE_SUCCESS:
5138 carla_debug("CarlaPluginLV2::updateLV2State() - success");
5139 break;
5140 case LV2_STATE_ERR_UNKNOWN:
5141 carla_stderr("CarlaPluginLV2::updateLV2State() - unknown error");
5142 break;
5143 case LV2_STATE_ERR_BAD_TYPE:
5144 carla_stderr("CarlaPluginLV2::updateLV2State() - error, bad type");
5145 break;
5146 case LV2_STATE_ERR_BAD_FLAGS:
5147 carla_stderr("CarlaPluginLV2::updateLV2State() - error, bad flags");
5148 break;
5149 case LV2_STATE_ERR_NO_FEATURE:
5150 carla_stderr("CarlaPluginLV2::updateLV2State() - error, missing feature");
5151 break;
5152 case LV2_STATE_ERR_NO_PROPERTY:
5153 carla_stderr("CarlaPluginLV2::updateLV2State() - error, missing property");
5154 break;
5155 case LV2_STATE_ERR_NO_SPACE:
5156 carla_stderr("CarlaPluginLV2::updateLV2State() - error, insufficient space");
5157 break;
5158 }
5159 }
5160
5161 // -------------------------------------------------------------------
5162
isRealtimeSafe() const5163 bool isRealtimeSafe() const noexcept
5164 {
5165 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr, false);
5166
5167 for (uint32_t i=0; i < fRdfDescriptor->FeatureCount; ++i)
5168 {
5169 if (std::strcmp(fRdfDescriptor->Features[i].URI, LV2_CORE__hardRTCapable) == 0)
5170 return true;
5171 }
5172
5173 return false;
5174 }
5175
5176 // -------------------------------------------------------------------
5177
isUiBridgeable(const uint32_t uiId) const5178 bool isUiBridgeable(const uint32_t uiId) const noexcept
5179 {
5180 CARLA_SAFE_ASSERT_RETURN(uiId < fRdfDescriptor->UICount, false);
5181
5182 #ifndef LV2_UIS_ONLY_INPROCESS
5183 const LV2_RDF_UI* const rdfUI(&fRdfDescriptor->UIs[uiId]);
5184
5185 for (uint32_t i=0; i < rdfUI->FeatureCount; ++i)
5186 {
5187 const LV2_RDF_Feature& feat(rdfUI->Features[i]);
5188
5189 if (! feat.Required)
5190 continue;
5191 if (std::strcmp(feat.URI, LV2_INSTANCE_ACCESS_URI) == 0)
5192 return false;
5193 if (std::strcmp(feat.URI, LV2_DATA_ACCESS_URI) == 0)
5194 return false;
5195 }
5196
5197 // Calf UIs are mostly useless without their special graphs
5198 // but they can be crashy under certain conditions, so follow user preferences
5199 if (std::strstr(rdfUI->URI, "http://calf.sourceforge.net/plugins/gui/") != nullptr)
5200 return pData->engine->getOptions().preferUiBridges;
5201
5202 // LSP-Plugins UIs make heavy use of URIDs, for which carla right now is very slow
5203 // FIXME after some optimization, remove this
5204 if (std::strstr(rdfUI->URI, "http://lsp-plug.in/ui/lv2/") != nullptr)
5205 return false;
5206
5207 return true;
5208 #else
5209 return false;
5210 #endif
5211 }
5212
isUiResizable() const5213 bool isUiResizable() const noexcept
5214 {
5215 CARLA_SAFE_ASSERT_RETURN(fUI.rdfDescriptor != nullptr, false);
5216
5217 for (uint32_t i=0; i < fUI.rdfDescriptor->FeatureCount; ++i)
5218 {
5219 if (std::strcmp(fUI.rdfDescriptor->Features[i].URI, LV2_UI__fixedSize) == 0)
5220 return false;
5221 if (std::strcmp(fUI.rdfDescriptor->Features[i].URI, LV2_UI__noUserResize) == 0)
5222 return false;
5223 }
5224
5225 return true;
5226 }
5227
getUiBridgeBinary(const LV2_Property type) const5228 const char* getUiBridgeBinary(const LV2_Property type) const
5229 {
5230 CarlaString bridgeBinary(pData->engine->getOptions().binaryDir);
5231
5232 if (bridgeBinary.isEmpty())
5233 return nullptr;
5234
5235 switch (type)
5236 {
5237 case LV2_UI_GTK2:
5238 bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-gtk2";
5239 break;
5240 case LV2_UI_GTK3:
5241 bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-gtk3";
5242 break;
5243 case LV2_UI_QT4:
5244 bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-qt4";
5245 break;
5246 case LV2_UI_QT5:
5247 bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-qt5";
5248 break;
5249 case LV2_UI_COCOA:
5250 bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-cocoa";
5251 break;
5252 case LV2_UI_WINDOWS:
5253 bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-windows";
5254 break;
5255 case LV2_UI_X11:
5256 bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-x11";
5257 break;
5258 case LV2_UI_MOD:
5259 bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-modgui";
5260 break;
5261 #if 0
5262 case LV2_UI_EXTERNAL:
5263 case LV2_UI_OLD_EXTERNAL:
5264 bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-lv2-external";
5265 break;
5266 #endif
5267 default:
5268 return nullptr;
5269 }
5270
5271 #ifdef CARLA_OS_WIN
5272 bridgeBinary += ".exe";
5273 #endif
5274
5275 if (! File(bridgeBinary.buffer()).existsAsFile())
5276 return nullptr;
5277
5278 return bridgeBinary.dupSafe();
5279 }
5280
5281 // -------------------------------------------------------------------
5282
recheckExtensions()5283 void recheckExtensions()
5284 {
5285 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor != nullptr,);
5286 carla_debug("CarlaPluginLV2::recheckExtensions()");
5287
5288 fExt.options = nullptr;
5289 fExt.programs = nullptr;
5290 fExt.state = nullptr;
5291 fExt.worker = nullptr;
5292 fExt.inlineDisplay = nullptr;
5293
5294 for (uint32_t i=0; i < fRdfDescriptor->ExtensionCount; ++i)
5295 {
5296 const char* const extension = fRdfDescriptor->Extensions[i];
5297 CARLA_SAFE_ASSERT_CONTINUE(extension != nullptr);
5298
5299 /**/ if (std::strcmp(extension, LV2_OPTIONS__interface) == 0)
5300 pData->hints |= PLUGIN_HAS_EXTENSION_OPTIONS;
5301 else if (std::strcmp(extension, LV2_PROGRAMS__Interface) == 0)
5302 pData->hints |= PLUGIN_HAS_EXTENSION_PROGRAMS;
5303 else if (std::strcmp(extension, LV2_STATE__interface) == 0)
5304 pData->hints |= PLUGIN_HAS_EXTENSION_STATE;
5305 else if (std::strcmp(extension, LV2_WORKER__interface) == 0)
5306 pData->hints |= PLUGIN_HAS_EXTENSION_WORKER;
5307 else if (std::strcmp(extension, LV2_INLINEDISPLAY__interface) == 0)
5308 pData->hints |= PLUGIN_HAS_EXTENSION_INLINE_DISPLAY;
5309 else if (std::strcmp(extension, LV2_MIDNAM__interface) == 0)
5310 pData->hints |= PLUGIN_HAS_EXTENSION_MIDNAM;
5311 else
5312 carla_stdout("Plugin '%s' has non-supported extension: '%s'", fRdfDescriptor->URI, extension);
5313 }
5314
5315 // Fix for broken plugins, nasty!
5316 for (uint32_t i=0; i < fRdfDescriptor->FeatureCount; ++i)
5317 {
5318 const LV2_RDF_Feature& feature(fRdfDescriptor->Features[i]);
5319
5320 if (std::strcmp(feature.URI, LV2_INLINEDISPLAY__queue_draw) == 0)
5321 {
5322 if (pData->hints & PLUGIN_HAS_EXTENSION_INLINE_DISPLAY)
5323 break;
5324
5325 carla_stdout("Plugin '%s' uses inline-display but does not set extension data, nasty!", fRdfDescriptor->URI);
5326 pData->hints |= PLUGIN_HAS_EXTENSION_INLINE_DISPLAY;
5327 }
5328 else if (std::strcmp(feature.URI, LV2_MIDNAM__update) == 0)
5329 {
5330 if (pData->hints & PLUGIN_HAS_EXTENSION_MIDNAM)
5331 break;
5332
5333 carla_stdout("Plugin '%s' uses midnam but does not set extension data, nasty!", fRdfDescriptor->URI);
5334 pData->hints |= PLUGIN_HAS_EXTENSION_MIDNAM;
5335 }
5336 }
5337
5338 if (fDescriptor->extension_data != nullptr)
5339 {
5340 if (pData->hints & PLUGIN_HAS_EXTENSION_OPTIONS)
5341 fExt.options = (const LV2_Options_Interface*)fDescriptor->extension_data(LV2_OPTIONS__interface);
5342
5343 if (pData->hints & PLUGIN_HAS_EXTENSION_PROGRAMS)
5344 fExt.programs = (const LV2_Programs_Interface*)fDescriptor->extension_data(LV2_PROGRAMS__Interface);
5345
5346 if (pData->hints & PLUGIN_HAS_EXTENSION_STATE)
5347 fExt.state = (const LV2_State_Interface*)fDescriptor->extension_data(LV2_STATE__interface);
5348
5349 if (pData->hints & PLUGIN_HAS_EXTENSION_WORKER)
5350 fExt.worker = (const LV2_Worker_Interface*)fDescriptor->extension_data(LV2_WORKER__interface);
5351
5352 if (pData->hints & PLUGIN_HAS_EXTENSION_INLINE_DISPLAY)
5353 fExt.inlineDisplay = (const LV2_Inline_Display_Interface*)fDescriptor->extension_data(LV2_INLINEDISPLAY__interface);
5354
5355 if (pData->hints & PLUGIN_HAS_EXTENSION_MIDNAM)
5356 fExt.midnam = (const LV2_Midnam_Interface*)fDescriptor->extension_data(LV2_MIDNAM__interface);
5357
5358 // check if invalid
5359 if (fExt.options != nullptr && fExt.options->get == nullptr && fExt.options->set == nullptr)
5360 fExt.options = nullptr;
5361
5362 if (fExt.programs != nullptr && (fExt.programs->get_program == nullptr || fExt.programs->select_program == nullptr))
5363 fExt.programs = nullptr;
5364
5365 if (fExt.state != nullptr && (fExt.state->save == nullptr || fExt.state->restore == nullptr))
5366 fExt.state = nullptr;
5367
5368 if (fExt.worker != nullptr && fExt.worker->work == nullptr)
5369 fExt.worker = nullptr;
5370
5371 if (fExt.inlineDisplay != nullptr)
5372 {
5373 if (fExt.inlineDisplay->render != nullptr)
5374 {
5375 pData->hints |= PLUGIN_HAS_INLINE_DISPLAY;
5376 pData->setCanDeleteLib(false);
5377 }
5378 else
5379 {
5380 fExt.inlineDisplay = nullptr;
5381 }
5382 }
5383
5384 if (fExt.midnam != nullptr && fExt.midnam->midnam == nullptr)
5385 fExt.midnam = nullptr;
5386 }
5387
5388 CARLA_SAFE_ASSERT_RETURN(fLatencyIndex == -1,);
5389
5390 int32_t iCtrl=0;
5391 for (uint32_t i=0, count=fRdfDescriptor->PortCount; i<count; ++i)
5392 {
5393 const LV2_Property portTypes(fRdfDescriptor->Ports[i].Types);
5394
5395 if (! LV2_IS_PORT_CONTROL(portTypes))
5396 continue;
5397
5398 const CarlaScopedValueSetter<int32_t> svs(iCtrl, iCtrl, iCtrl+1);
5399
5400 if (! LV2_IS_PORT_OUTPUT(portTypes))
5401 continue;
5402
5403 const LV2_Property portDesignation(fRdfDescriptor->Ports[i].Designation);
5404
5405 if (! LV2_IS_PORT_DESIGNATION_LATENCY(portDesignation))
5406 continue;
5407
5408 fLatencyIndex = iCtrl;
5409 break;
5410 }
5411 }
5412
5413 // -------------------------------------------------------------------
5414
updateUi()5415 void updateUi()
5416 {
5417 CARLA_SAFE_ASSERT_RETURN(fUI.handle != nullptr,);
5418 CARLA_SAFE_ASSERT_RETURN(fUI.descriptor != nullptr,);
5419 carla_debug("CarlaPluginLV2::updateUi()");
5420
5421 // update midi program
5422 if (fExt.uiprograms != nullptr && pData->midiprog.count > 0 && pData->midiprog.current >= 0)
5423 {
5424 const MidiProgramData& curData(pData->midiprog.getCurrent());
5425 fExt.uiprograms->select_program(fUI.handle, curData.bank, curData.program);
5426 }
5427
5428 // update control ports
5429 if (fUI.descriptor->port_event != nullptr)
5430 {
5431 float value;
5432 for (uint32_t i=0; i < pData->param.count; ++i)
5433 {
5434 value = getParameterValue(i);
5435 fUI.descriptor->port_event(fUI.handle, static_cast<uint32_t>(pData->param.data[i].rindex), sizeof(float), kUridNull, &value);
5436 }
5437 }
5438 }
5439
inspectAtomForParameterChange(const LV2_Atom * const atom)5440 void inspectAtomForParameterChange(const LV2_Atom* const atom)
5441 {
5442 if (atom->type != kUridAtomBlank && atom->type != kUridAtomObject)
5443 return;
5444
5445 const LV2_Atom_Object_Body* const objbody = (const LV2_Atom_Object_Body*)(atom + 1);
5446
5447 if (objbody->otype != kUridPatchSet)
5448 return;
5449
5450 const LV2_Atom_URID *property = NULL;
5451 const LV2_Atom_Bool *carlaParam = NULL;
5452 const LV2_Atom *value = NULL;
5453
5454 lv2_atom_object_body_get(atom->size, objbody,
5455 kUridCarlaParameterChange, (const LV2_Atom**)&carlaParam,
5456 kUridPatchProperty, (const LV2_Atom**)&property,
5457 kUridPatchValue, &value,
5458 0);
5459
5460 if (carlaParam != nullptr && carlaParam->body != 0)
5461 return;
5462
5463 if (property == nullptr || value == nullptr)
5464 return;
5465
5466 switch (value->type)
5467 {
5468 case kUridAtomBool:
5469 case kUridAtomInt:
5470 //case kUridAtomLong:
5471 case kUridAtomFloat:
5472 case kUridAtomDouble:
5473 break;
5474 default:
5475 return;
5476 }
5477
5478 uint32_t parameterId;
5479 if (! getParameterIndexForURID(property->body, parameterId))
5480 return;
5481
5482 const uint8_t* const vbody = (const uint8_t*)(value + 1);
5483 float rvalue;
5484
5485 switch (value->type)
5486 {
5487 case kUridAtomBool:
5488 rvalue = *(const int32_t*)vbody != 0 ? 1.0f : 0.0f;
5489 break;
5490 case kUridAtomInt:
5491 rvalue = static_cast<float>(*(const int32_t*)vbody);
5492 break;
5493 /*
5494 case kUridAtomLong:
5495 rvalue = *(int64_t*)vbody;
5496 break;
5497 */
5498 case kUridAtomFloat:
5499 rvalue = *(const float*)vbody;
5500 break;
5501 case kUridAtomDouble:
5502 rvalue = static_cast<float>(*(const double*)vbody);
5503 break;
5504 default:
5505 rvalue = 0.0f;
5506 break;
5507 }
5508
5509 rvalue = pData->param.getFixedValue(parameterId, rvalue);
5510 fParamBuffers[parameterId] = rvalue;
5511
5512 CarlaPlugin::setParameterValue(parameterId, rvalue, false, true, true);
5513 }
5514
getParameterIndexForURI(const char * const uri,uint32_t & parameterId)5515 bool getParameterIndexForURI(const char* const uri, uint32_t& parameterId) noexcept
5516 {
5517 parameterId = UINT32_MAX;
5518
5519 for (uint32_t i=0; i < fRdfDescriptor->ParameterCount; ++i)
5520 {
5521 const LV2_RDF_Parameter& rdfParam(fRdfDescriptor->Parameters[i]);
5522
5523 switch (rdfParam.Type)
5524 {
5525 case LV2_PARAMETER_TYPE_BOOL:
5526 case LV2_PARAMETER_TYPE_INT:
5527 // case LV2_PARAMETER_TYPE_LONG:
5528 case LV2_PARAMETER_TYPE_FLOAT:
5529 case LV2_PARAMETER_TYPE_DOUBLE:
5530 break;
5531 default:
5532 continue;
5533 }
5534
5535 if (std::strcmp(rdfParam.URI, uri) == 0)
5536 {
5537 const int32_t rindex = static_cast<int32_t>(fRdfDescriptor->PortCount + i);
5538
5539 for (uint32_t j=0; j < pData->param.count; ++j)
5540 {
5541 if (pData->param.data[j].rindex == rindex)
5542 {
5543 parameterId = j;
5544 break;
5545 }
5546 }
5547 break;
5548 }
5549 }
5550
5551 return (parameterId != UINT32_MAX);
5552 }
5553
getParameterIndexForURID(const LV2_URID urid,uint32_t & parameterId)5554 bool getParameterIndexForURID(const LV2_URID urid, uint32_t& parameterId) noexcept
5555 {
5556 parameterId = UINT32_MAX;
5557
5558 if (urid >= fCustomURIDs.size())
5559 return false;
5560
5561 for (uint32_t i=0; i < fRdfDescriptor->ParameterCount; ++i)
5562 {
5563 const LV2_RDF_Parameter& rdfParam(fRdfDescriptor->Parameters[i]);
5564
5565 switch (rdfParam.Type)
5566 {
5567 case LV2_PARAMETER_TYPE_BOOL:
5568 case LV2_PARAMETER_TYPE_INT:
5569 // case LV2_PARAMETER_TYPE_LONG:
5570 case LV2_PARAMETER_TYPE_FLOAT:
5571 case LV2_PARAMETER_TYPE_DOUBLE:
5572 break;
5573 default:
5574 continue;
5575 }
5576
5577 const std::string& uri(fCustomURIDs[urid]);
5578
5579 if (uri != rdfParam.URI)
5580 continue;
5581
5582 const int32_t rindex = static_cast<int32_t>(fRdfDescriptor->PortCount + i);
5583
5584 for (uint32_t j=0; j < pData->param.count; ++j)
5585 {
5586 if (pData->param.data[j].rindex == rindex)
5587 {
5588 parameterId = j;
5589 break;
5590 }
5591 }
5592 break;
5593 }
5594
5595 return (parameterId != UINT32_MAX);
5596 }
5597
5598 // -------------------------------------------------------------------
5599
getCustomURID(const char * const uri)5600 LV2_URID getCustomURID(const char* const uri)
5601 {
5602 CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', kUridNull);
5603 carla_debug("CarlaPluginLV2::getCustomURID(\"%s\")", uri);
5604
5605 const std::string s_uri(uri);
5606 const std::ptrdiff_t s_pos(std::find(fCustomURIDs.begin(), fCustomURIDs.end(), s_uri) - fCustomURIDs.begin());
5607
5608 if (s_pos <= 0 || s_pos >= INT32_MAX)
5609 return kUridNull;
5610
5611 const LV2_URID urid = static_cast<LV2_URID>(s_pos);
5612 const LV2_URID uriCount = static_cast<LV2_URID>(fCustomURIDs.size());
5613
5614 if (urid < uriCount)
5615 return urid;
5616
5617 CARLA_SAFE_ASSERT(urid == uriCount);
5618
5619 fCustomURIDs.push_back(uri);
5620
5621 if (fUI.type == UI::TYPE_BRIDGE && fPipeServer.isPipeRunning())
5622 fPipeServer.writeLv2UridMessage(urid, uri);
5623
5624 return urid;
5625 }
5626
getCustomURIDString(const LV2_URID urid) const5627 const char* getCustomURIDString(const LV2_URID urid) const noexcept
5628 {
5629 CARLA_SAFE_ASSERT_RETURN(urid != kUridNull, kUnmapFallback);
5630 CARLA_SAFE_ASSERT_RETURN(urid < fCustomURIDs.size(), kUnmapFallback);
5631 carla_debug("CarlaPluginLV2::getCustomURIString(%i)", urid);
5632
5633 return fCustomURIDs[urid].c_str();
5634 }
5635
5636 // -------------------------------------------------------------------
5637
handleProgramChanged(const int32_t index)5638 void handleProgramChanged(const int32_t index)
5639 {
5640 CARLA_SAFE_ASSERT_RETURN(index >= -1,);
5641 carla_debug("CarlaPluginLV2::handleProgramChanged(%i)", index);
5642
5643 if (index == -1)
5644 {
5645 const ScopedSingleProcessLocker spl(this, true);
5646 return reloadPrograms(false);
5647 }
5648
5649 if (index < static_cast<int32_t>(pData->midiprog.count) && fExt.programs != nullptr && fExt.programs->get_program != nullptr)
5650 {
5651 if (const LV2_Program_Descriptor* const progDesc = fExt.programs->get_program(fHandle, static_cast<uint32_t>(index)))
5652 {
5653 CARLA_SAFE_ASSERT_RETURN(progDesc->name != nullptr,);
5654
5655 if (pData->midiprog.data[index].name != nullptr)
5656 delete[] pData->midiprog.data[index].name;
5657
5658 pData->midiprog.data[index].name = carla_strdup(progDesc->name);
5659
5660 if (index == pData->midiprog.current)
5661 pData->engine->callback(true, true, ENGINE_CALLBACK_UPDATE, pData->id, 0, 0, 0, 0.0, nullptr);
5662 else
5663 pData->engine->callback(true, true, ENGINE_CALLBACK_RELOAD_PROGRAMS, pData->id, 0, 0, 0, 0.0, nullptr);
5664 }
5665 }
5666 }
5667
5668 // -------------------------------------------------------------------
5669
handleResizePort(const uint32_t index,const size_t size)5670 LV2_Resize_Port_Status handleResizePort(const uint32_t index, const size_t size)
5671 {
5672 CARLA_SAFE_ASSERT_RETURN(size > 0, LV2_RESIZE_PORT_ERR_UNKNOWN);
5673 carla_debug("CarlaPluginLV2::handleResizePort(%i, " P_SIZE ")", index, size);
5674
5675 // TODO
5676 return LV2_RESIZE_PORT_ERR_NO_SPACE;
5677 (void)index;
5678 }
5679
5680 // -------------------------------------------------------------------
5681
handleStateMapToAbstractPath(const bool temporary,const char * const absolutePath) const5682 char* handleStateMapToAbstractPath(const bool temporary, const char* const absolutePath) const
5683 {
5684 // may already be an abstract path
5685 if (! File::isAbsolutePath(absolutePath))
5686 return strdup(absolutePath);
5687
5688 File projectDir, targetDir;
5689
5690 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
5691 if (const char* const projFolder = pData->engine->getCurrentProjectFolder())
5692 projectDir = projFolder;
5693 else
5694 #endif
5695 projectDir = File::getCurrentWorkingDirectory();
5696
5697 if (projectDir.isNull())
5698 {
5699 carla_stdout("Project directory not set, cannot map absolutePath %s", absolutePath);
5700 return nullptr;
5701 }
5702
5703 water::String basedir(pData->engine->getName());
5704
5705 if (temporary)
5706 basedir += ".tmp";
5707
5708 targetDir = projectDir.getChildFile(basedir)
5709 .getChildFile(getName());
5710
5711 if (! targetDir.exists())
5712 targetDir.createDirectory();
5713
5714 const File wabsolutePath(absolutePath);
5715
5716 // we may be saving to non-tmp path, let's check
5717 if (! temporary)
5718 {
5719 const File tmpDir = projectDir.getChildFile(basedir + ".tmp")
5720 .getChildFile(getName());
5721
5722 if (wabsolutePath.getFullPathName().startsWith(tmpDir.getFullPathName()))
5723 {
5724 // gotcha, the temporary path is now the real one
5725 targetDir = tmpDir;
5726 }
5727 else if (! wabsolutePath.getFullPathName().startsWith(targetDir.getFullPathName()))
5728 {
5729 // seems like a normal save, let's be nice and put a symlink
5730 const water::String abstractFilename(wabsolutePath.getFileName());
5731 const File targetPath(targetDir.getChildFile(abstractFilename));
5732
5733 wabsolutePath.createSymbolicLink(targetPath, true);
5734
5735 carla_stdout("Creating symlink for '%s' in '%s'", absolutePath, targetDir.getFullPathName().toRawUTF8());
5736 return strdup(abstractFilename.toRawUTF8());
5737 }
5738 }
5739
5740 carla_stdout("Mapping absolutePath '%s' relative to targetDir '%s'",
5741 absolutePath, targetDir.getFullPathName().toRawUTF8());
5742
5743 return strdup(wabsolutePath.getRelativePathFrom(targetDir).toRawUTF8());
5744 }
5745
handleStateMapToAbsolutePath(const bool createDirIfNeeded,const bool symlinkIfNeeded,const bool temporary,const char * const abstractPath) const5746 File handleStateMapToAbsolutePath(const bool createDirIfNeeded,
5747 const bool symlinkIfNeeded,
5748 const bool temporary,
5749 const char* const abstractPath) const
5750 {
5751 File targetDir, targetPath;
5752
5753 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
5754 if (const char* const projFolder = pData->engine->getCurrentProjectFolder())
5755 targetDir = projFolder;
5756 else
5757 #endif
5758 targetDir = File::getCurrentWorkingDirectory();
5759
5760 if (targetDir.isNull())
5761 {
5762 carla_stdout("Project directory not set, cannot map abstractPath '%s'", abstractPath);
5763 return File();
5764 }
5765
5766 water::String basedir(pData->engine->getName());
5767
5768 if (temporary)
5769 basedir += ".tmp";
5770
5771 targetDir = targetDir.getChildFile(basedir)
5772 .getChildFile(getName());
5773
5774 if (createDirIfNeeded && ! targetDir.exists())
5775 targetDir.createDirectory();
5776
5777 if (File::isAbsolutePath(abstractPath))
5778 {
5779 File wabstractPath(abstractPath);
5780 targetPath = targetDir.getChildFile(wabstractPath.getFileName());
5781
5782 if (symlinkIfNeeded)
5783 {
5784 carla_stdout("Creating symlink for '%s' in '%s'",
5785 abstractPath, targetDir.getFullPathName().toRawUTF8());
5786 wabstractPath.createSymbolicLink(targetPath, true);
5787 }
5788 }
5789 else
5790 {
5791 targetPath = targetDir.getChildFile(abstractPath);
5792 targetDir = targetPath.getParentDirectory();
5793
5794 if (createDirIfNeeded && ! targetDir.exists())
5795 targetDir.createDirectory();
5796 }
5797
5798 if (std::strcmp(abstractPath, ".") != 0)
5799 carla_stdout("Mapping abstractPath '%s' relative to targetDir '%s'",
5800 abstractPath, targetDir.getFullPathName().toRawUTF8());
5801
5802 return targetPath;
5803 }
5804
handleStateStore(const uint32_t key,const void * const value,const size_t size,const uint32_t type,const uint32_t flags)5805 LV2_State_Status handleStateStore(const uint32_t key, const void* const value, const size_t size, const uint32_t type, const uint32_t flags)
5806 {
5807 CARLA_SAFE_ASSERT_RETURN(key != kUridNull, LV2_STATE_ERR_NO_PROPERTY);
5808 CARLA_SAFE_ASSERT_RETURN(value != nullptr, LV2_STATE_ERR_NO_PROPERTY);
5809 CARLA_SAFE_ASSERT_RETURN(size > 0, LV2_STATE_ERR_NO_PROPERTY);
5810 CARLA_SAFE_ASSERT_RETURN(type != kUridNull, LV2_STATE_ERR_BAD_TYPE);
5811
5812 // FIXME linuxsampler does not set POD flag
5813 // CARLA_SAFE_ASSERT_RETURN(flags & LV2_STATE_IS_POD, LV2_STATE_ERR_BAD_FLAGS);
5814
5815 carla_debug("CarlaPluginLV2::handleStateStore(%i:\"%s\", %p, " P_SIZE ", %i:\"%s\", %i)",
5816 key, carla_lv2_urid_unmap(this, key), value, size, type, carla_lv2_urid_unmap(this, type), flags);
5817
5818 const char* const skey(carla_lv2_urid_unmap(this, key));
5819 const char* const stype(carla_lv2_urid_unmap(this, type));
5820
5821 CARLA_SAFE_ASSERT_RETURN(skey != nullptr && skey != kUnmapFallback, LV2_STATE_ERR_BAD_TYPE);
5822 CARLA_SAFE_ASSERT_RETURN(stype != nullptr && stype != kUnmapFallback, LV2_STATE_ERR_BAD_TYPE);
5823
5824 // Check if we already have this key
5825 for (LinkedList<CustomData>::Itenerator it = pData->custom.begin2(); it.valid(); it.next())
5826 {
5827 CustomData& cData(it.getValue(kCustomDataFallbackNC));
5828 CARLA_SAFE_ASSERT_CONTINUE(cData.isValid());
5829
5830 if (std::strcmp(cData.key, skey) == 0)
5831 {
5832 // found it
5833 delete[] cData.value;
5834
5835 if (type == kUridAtomString || type == kUridAtomPath)
5836 cData.value = carla_strdup((const char*)value);
5837 else
5838 cData.value = CarlaString::asBase64(value, size).dup();
5839
5840 return LV2_STATE_SUCCESS;
5841 }
5842 }
5843
5844 // Otherwise store it
5845 CustomData newData;
5846 newData.type = carla_strdup(stype);
5847 newData.key = carla_strdup(skey);
5848
5849 if (type == kUridAtomString || type == kUridAtomPath)
5850 newData.value = carla_strdup((const char*)value);
5851 else
5852 newData.value = CarlaString::asBase64(value, size).dup();
5853
5854 pData->custom.append(newData);
5855
5856 return LV2_STATE_SUCCESS;
5857
5858 // unused
5859 (void)flags;
5860 }
5861
handleStateRetrieve(const uint32_t key,size_t * const size,uint32_t * const type,uint32_t * const flags)5862 const void* handleStateRetrieve(const uint32_t key, size_t* const size, uint32_t* const type, uint32_t* const flags)
5863 {
5864 CARLA_SAFE_ASSERT_RETURN(key != kUridNull, nullptr);
5865 CARLA_SAFE_ASSERT_RETURN(size != nullptr, nullptr);
5866 CARLA_SAFE_ASSERT_RETURN(type != nullptr, nullptr);
5867 CARLA_SAFE_ASSERT_RETURN(flags != nullptr, nullptr);
5868 carla_debug("CarlaPluginLV2::handleStateRetrieve(%i, %p, %p, %p)", key, size, type, flags);
5869
5870 const char* const skey(carla_lv2_urid_unmap(this, key));
5871 CARLA_SAFE_ASSERT_RETURN(skey != nullptr && skey != kUnmapFallback, nullptr);
5872
5873 const char* stype = nullptr;
5874 const char* stringData = nullptr;
5875
5876 for (LinkedList<CustomData>::Itenerator it = pData->custom.begin2(); it.valid(); it.next())
5877 {
5878 const CustomData& cData(it.getValue(kCustomDataFallback));
5879 CARLA_SAFE_ASSERT_CONTINUE(cData.isValid());
5880
5881 if (std::strcmp(cData.key, skey) == 0)
5882 {
5883 stype = cData.type;
5884 stringData = cData.value;
5885 break;
5886 }
5887 }
5888
5889 if (stype == nullptr || stringData == nullptr)
5890 {
5891 carla_stderr("Plugin requested value for '%s' which is not available", skey);
5892 *size = *type = *flags = 0;
5893 return nullptr;
5894 }
5895
5896 *type = carla_lv2_urid_map(this, stype);
5897 *flags = LV2_STATE_IS_POD;
5898
5899 if (*type == kUridAtomString || *type == kUridAtomPath)
5900 {
5901 *size = std::strlen(stringData);
5902 return stringData;
5903 }
5904
5905 if (fLastStateChunk != nullptr)
5906 {
5907 std::free(fLastStateChunk);
5908 fLastStateChunk = nullptr;
5909 }
5910
5911 std::vector<uint8_t> chunk(carla_getChunkFromBase64String(stringData));
5912 CARLA_SAFE_ASSERT_RETURN(chunk.size() > 0, nullptr);
5913
5914 fLastStateChunk = std::malloc(chunk.size());
5915 CARLA_SAFE_ASSERT_RETURN(fLastStateChunk != nullptr, nullptr);
5916
5917 #ifdef CARLA_PROPER_CPP11_SUPPORT
5918 std::memcpy(fLastStateChunk, chunk.data(), chunk.size());
5919 #else
5920 std::memcpy(fLastStateChunk, &chunk.front(), chunk.size());
5921 #endif
5922
5923 *size = chunk.size();
5924 return fLastStateChunk;
5925 }
5926
5927 // -------------------------------------------------------------------
5928
handleWorkerSchedule(const uint32_t size,const void * const data)5929 LV2_Worker_Status handleWorkerSchedule(const uint32_t size, const void* const data)
5930 {
5931 CARLA_SAFE_ASSERT_RETURN(fExt.worker != nullptr && fExt.worker->work != nullptr, LV2_WORKER_ERR_UNKNOWN);
5932 CARLA_SAFE_ASSERT_RETURN(fEventsIn.ctrl != nullptr, LV2_WORKER_ERR_UNKNOWN);
5933 carla_debug("CarlaPluginLV2::handleWorkerSchedule(%i, %p)", size, data);
5934
5935 if (pData->engine->isOffline())
5936 {
5937 fExt.worker->work(fHandle, carla_lv2_worker_respond, this, size, data);
5938 return LV2_WORKER_SUCCESS;
5939 }
5940
5941 LV2_Atom atom;
5942 atom.size = size;
5943 atom.type = kUridCarlaAtomWorkerIn;
5944
5945 return fAtomBufferWorkerIn.putChunk(&atom, data, fEventsOut.ctrlIndex) ? LV2_WORKER_SUCCESS : LV2_WORKER_ERR_NO_SPACE;
5946 }
5947
handleWorkerRespond(const uint32_t size,const void * const data)5948 LV2_Worker_Status handleWorkerRespond(const uint32_t size, const void* const data)
5949 {
5950 CARLA_SAFE_ASSERT_RETURN(fExt.worker != nullptr && fExt.worker->work_response != nullptr, LV2_WORKER_ERR_UNKNOWN);
5951 carla_debug("CarlaPluginLV2::handleWorkerRespond(%i, %p)", size, data);
5952
5953 LV2_Atom atom;
5954 atom.size = size;
5955 atom.type = kUridCarlaAtomWorkerResp;
5956
5957 return fAtomBufferWorkerResp.putChunk(&atom, data, fEventsIn.ctrlIndex) ? LV2_WORKER_SUCCESS : LV2_WORKER_ERR_NO_SPACE;
5958 }
5959
5960 // -------------------------------------------------------------------
5961
handleInlineDisplayQueueRedraw()5962 void handleInlineDisplayQueueRedraw()
5963 {
5964 switch (pData->engine->getProccessMode())
5965 {
5966 case ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS:
5967 case ENGINE_PROCESS_MODE_PATCHBAY:
5968 fInlineDisplayNeedsRedraw = true;
5969 break;
5970 default:
5971 break;
5972 }
5973 }
5974
renderInlineDisplay(const uint32_t width,const uint32_t height) const5975 const LV2_Inline_Display_Image_Surface* renderInlineDisplay(const uint32_t width, const uint32_t height) const
5976 {
5977 CARLA_SAFE_ASSERT_RETURN(fExt.inlineDisplay != nullptr && fExt.inlineDisplay->render != nullptr, nullptr);
5978 CARLA_SAFE_ASSERT_RETURN(width > 0, nullptr);
5979 CARLA_SAFE_ASSERT_RETURN(height > 0, nullptr);
5980
5981 return fExt.inlineDisplay->render(fHandle, width, height);
5982 }
5983
5984 // -------------------------------------------------------------------
5985
handleMidnamUpdate()5986 void handleMidnamUpdate()
5987 {
5988 CARLA_SAFE_ASSERT_RETURN(fExt.midnam != nullptr,);
5989
5990 if (fEventsIn.ctrl == nullptr)
5991 return;
5992
5993 char* const midnam = fExt.midnam->midnam(fHandle);
5994 CARLA_SAFE_ASSERT_RETURN(midnam != nullptr,);
5995
5996 fEventsIn.ctrl->port->setMetaData("http://www.midi.org/dtds/MIDINameDocument10.dtd", midnam, "text/xml");
5997
5998 if (fExt.midnam->free != nullptr)
5999 fExt.midnam->free(midnam);
6000 }
6001
6002 // -------------------------------------------------------------------
6003
handleExternalUIClosed()6004 void handleExternalUIClosed()
6005 {
6006 CARLA_SAFE_ASSERT_RETURN(fUI.type == UI::TYPE_EXTERNAL,);
6007 carla_debug("CarlaPluginLV2::handleExternalUIClosed()");
6008
6009 fNeedsUiClose = true;
6010 }
6011
handlePluginUIClosed()6012 void handlePluginUIClosed() override
6013 {
6014 CARLA_SAFE_ASSERT_RETURN(fUI.type == UI::TYPE_EMBED,);
6015 CARLA_SAFE_ASSERT_RETURN(fUI.window != nullptr,);
6016 carla_debug("CarlaPluginLV2::handlePluginUIClosed()");
6017
6018 fNeedsUiClose = true;
6019 }
6020
handlePluginUIResized(const uint width,const uint height)6021 void handlePluginUIResized(const uint width, const uint height) override
6022 {
6023 CARLA_SAFE_ASSERT_RETURN(fUI.type == UI::TYPE_EMBED,);
6024 CARLA_SAFE_ASSERT_RETURN(fUI.window != nullptr,);
6025 carla_debug("CarlaPluginLV2::handlePluginUIResized(%u, %u)", width, height);
6026
6027 if (fUI.handle != nullptr && fExt.uiresize != nullptr)
6028 fExt.uiresize->ui_resize(fUI.handle, static_cast<int>(width), static_cast<int>(height));
6029 }
6030
6031 // -------------------------------------------------------------------
6032
handleUIPortMap(const char * const symbol) const6033 uint32_t handleUIPortMap(const char* const symbol) const noexcept
6034 {
6035 CARLA_SAFE_ASSERT_RETURN(symbol != nullptr && symbol[0] != '\0', LV2UI_INVALID_PORT_INDEX);
6036 carla_debug("CarlaPluginLV2::handleUIPortMap(\"%s\")", symbol);
6037
6038 for (uint32_t i=0; i < fRdfDescriptor->PortCount; ++i)
6039 {
6040 if (std::strcmp(fRdfDescriptor->Ports[i].Symbol, symbol) == 0)
6041 return i;
6042 }
6043
6044 return LV2UI_INVALID_PORT_INDEX;
6045 }
6046
handleUIRequestValue(const LV2_URID key,const LV2_URID type,const LV2_Feature * const * features)6047 LV2UI_Request_Value_Status handleUIRequestValue(const LV2_URID key,
6048 const LV2_URID type,
6049 const LV2_Feature* const* features)
6050 {
6051 CARLA_SAFE_ASSERT_RETURN(fUI.type != UI::TYPE_NULL, LV2UI_REQUEST_VALUE_ERR_UNKNOWN);
6052 carla_debug("CarlaPluginLV2::handleUIRequestValue(%u, %u, %p)", key, type, features);
6053
6054 if (type != kUridAtomPath)
6055 return LV2UI_REQUEST_VALUE_ERR_UNSUPPORTED;
6056
6057 const char* const uri = getCustomURIDString(key);
6058 CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri != kUnmapFallback, LV2UI_REQUEST_VALUE_ERR_UNKNOWN);
6059
6060 // check if a file browser is already open
6061 if (fUI.fileNeededForURI != nullptr || fUI.fileBrowserOpen)
6062 return LV2UI_REQUEST_VALUE_BUSY;
6063
6064 for (uint32_t i=0; i < fRdfDescriptor->ParameterCount; ++i)
6065 {
6066 if (fRdfDescriptor->Parameters[i].Type != LV2_PARAMETER_TYPE_PATH)
6067 continue;
6068 if (std::strcmp(fRdfDescriptor->Parameters[i].URI, uri) != 0)
6069 continue;
6070
6071 // TODO file browser filters, also store label to use for title
6072 fUI.fileNeededForURI = uri;
6073
6074 return LV2UI_REQUEST_VALUE_SUCCESS;
6075 }
6076
6077 return LV2UI_REQUEST_VALUE_ERR_UNSUPPORTED;
6078
6079 // may be unused
6080 (void)features;
6081 }
6082
handleUIResize(const int width,const int height)6083 int handleUIResize(const int width, const int height)
6084 {
6085 CARLA_SAFE_ASSERT_RETURN(width > 0, 1);
6086 CARLA_SAFE_ASSERT_RETURN(height > 0, 1);
6087 carla_debug("CarlaPluginLV2::handleUIResize(%i, %i)", width, height);
6088
6089 if (fUI.embedded)
6090 {
6091 pData->engine->callback(true, true,
6092 ENGINE_CALLBACK_EMBED_UI_RESIZED,
6093 pData->id, width, height,
6094 0, 0.0f, nullptr);
6095 }
6096 else
6097 {
6098 CARLA_SAFE_ASSERT_RETURN(fUI.window != nullptr, 1);
6099 fUI.window->setSize(static_cast<uint>(width), static_cast<uint>(height), true);
6100 }
6101
6102 return 0;
6103 }
6104
handleUITouch(const uint32_t rindex,const bool touch)6105 void handleUITouch(const uint32_t rindex, const bool touch)
6106 {
6107 carla_debug("CarlaPluginLV2::handleUITouch(%u, %s)", rindex, bool2str(touch));
6108
6109 uint32_t index = LV2UI_INVALID_PORT_INDEX;
6110
6111 for (uint32_t i=0; i < pData->param.count; ++i)
6112 {
6113 if (pData->param.data[i].rindex != static_cast<int32_t>(rindex))
6114 continue;
6115 index = i;
6116 break;
6117 }
6118
6119 CARLA_SAFE_ASSERT_RETURN(index != LV2UI_INVALID_PORT_INDEX,);
6120
6121 pData->engine->touchPluginParameter(pData->id, index, touch);
6122 }
6123
handleUIWrite(const uint32_t rindex,const uint32_t bufferSize,const uint32_t format,const void * const buffer)6124 void handleUIWrite(const uint32_t rindex, const uint32_t bufferSize, const uint32_t format, const void* const buffer)
6125 {
6126 CARLA_SAFE_ASSERT_RETURN(buffer != nullptr,);
6127 CARLA_SAFE_ASSERT_RETURN(bufferSize > 0,);
6128 carla_debug("CarlaPluginLV2::handleUIWrite(%i, %i, %i, %p)", rindex, bufferSize, format, buffer);
6129
6130 uint32_t index = LV2UI_INVALID_PORT_INDEX;
6131
6132 switch (format)
6133 {
6134 case kUridNull: {
6135 CARLA_SAFE_ASSERT_RETURN(rindex < fRdfDescriptor->PortCount,);
6136 CARLA_SAFE_ASSERT_RETURN(bufferSize == sizeof(float),);
6137
6138 for (uint32_t i=0; i < pData->param.count; ++i)
6139 {
6140 if (pData->param.data[i].rindex != static_cast<int32_t>(rindex))
6141 continue;
6142 index = i;
6143 break;
6144 }
6145
6146 CARLA_SAFE_ASSERT_RETURN(index != LV2UI_INVALID_PORT_INDEX,);
6147
6148 const float value(*(const float*)buffer);
6149
6150 // check if we should feedback message back to UI
6151 bool sendGui = false;
6152
6153 if (const uint32_t notifCount = fUI.rdfDescriptor->PortNotificationCount)
6154 {
6155 const char* const portSymbol = fRdfDescriptor->Ports[rindex].Symbol;
6156
6157 for (uint32_t i=0; i < notifCount; ++i)
6158 {
6159 const LV2_RDF_UI_PortNotification& portNotif(fUI.rdfDescriptor->PortNotifications[i]);
6160
6161 if (portNotif.Protocol != LV2_UI_PORT_PROTOCOL_FLOAT)
6162 continue;
6163
6164 if (portNotif.Symbol != nullptr)
6165 {
6166 if (std::strcmp(portNotif.Symbol, portSymbol) != 0)
6167 continue;
6168 }
6169 else if (portNotif.Index != rindex)
6170 {
6171 continue;
6172 }
6173
6174 sendGui = true;
6175 break;
6176 }
6177 }
6178
6179 setParameterValue(index, value, sendGui, true, true);
6180
6181 } break;
6182
6183 case kUridAtomTransferAtom:
6184 case kUridAtomTransferEvent: {
6185 CARLA_SAFE_ASSERT_RETURN(bufferSize >= sizeof(LV2_Atom),);
6186
6187 const LV2_Atom* const atom((const LV2_Atom*)buffer);
6188
6189 // plugins sometimes fail on this, not good...
6190 const uint32_t totalSize = lv2_atom_total_size(atom);
6191 const uint32_t paddedSize = lv2_atom_pad_size(totalSize);
6192
6193 if (bufferSize != totalSize && bufferSize != paddedSize)
6194 carla_stderr2("Warning: LV2 UI sending atom with invalid size %u! size: %u, padded-size: %u",
6195 bufferSize, totalSize, paddedSize);
6196
6197 for (uint32_t i=0; i < fEventsIn.count; ++i)
6198 {
6199 if (fEventsIn.data[i].rindex != rindex)
6200 continue;
6201 index = i;
6202 break;
6203 }
6204
6205 // for bad plugins
6206 if (index == LV2UI_INVALID_PORT_INDEX)
6207 {
6208 CARLA_SAFE_ASSERT(index != LV2UI_INVALID_PORT_INDEX); // FIXME
6209 index = fEventsIn.ctrlIndex;
6210 }
6211
6212 fAtomBufferEvIn.put(atom, index);
6213 } break;
6214
6215 default:
6216 carla_stdout("CarlaPluginLV2::handleUIWrite(%i, %i, %i:\"%s\", %p) - unknown format",
6217 rindex, bufferSize, format, carla_lv2_urid_unmap(this, format), buffer);
6218 break;
6219 }
6220 }
6221
handleUIBridgeParameter(const char * const uri,const float value)6222 void handleUIBridgeParameter(const char* const uri, const float value)
6223 {
6224 CARLA_SAFE_ASSERT_RETURN(uri != nullptr,);
6225 carla_debug("CarlaPluginLV2::handleUIBridgeParameter(%s, %f)", uri, static_cast<double>(value));
6226
6227 uint32_t parameterId;
6228
6229 if (getParameterIndexForURI(uri, parameterId))
6230 setParameterValue(parameterId, value, false, true, true);
6231 }
6232
6233 // -------------------------------------------------------------------
6234
handleLilvSetPortValue(const char * const portSymbol,const void * const value,const uint32_t size,const uint32_t type)6235 void handleLilvSetPortValue(const char* const portSymbol, const void* const value, const uint32_t size, const uint32_t type)
6236 {
6237 CARLA_SAFE_ASSERT_RETURN(portSymbol != nullptr && portSymbol[0] != '\0',);
6238 CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
6239 CARLA_SAFE_ASSERT_RETURN(size > 0,);
6240 CARLA_SAFE_ASSERT_RETURN(type != kUridNull,);
6241 carla_debug("CarlaPluginLV2::handleLilvSetPortValue(\"%s\", %p, %i, %i)", portSymbol, value, size, type);
6242
6243 int32_t rindex = -1;
6244
6245 for (uint32_t i=0; i < fRdfDescriptor->PortCount; ++i)
6246 {
6247 if (std::strcmp(fRdfDescriptor->Ports[i].Symbol, portSymbol) == 0)
6248 {
6249 rindex = static_cast<int32_t>(i);
6250 break;
6251 }
6252 }
6253
6254 CARLA_SAFE_ASSERT_RETURN(rindex >= 0,);
6255
6256 float paramValue;
6257
6258 switch (type)
6259 {
6260 case kUridAtomBool:
6261 CARLA_SAFE_ASSERT_RETURN(size == sizeof(int32_t),);
6262 paramValue = *(const int32_t*)value != 0 ? 1.0f : 0.0f;
6263 break;
6264 case kUridAtomDouble:
6265 CARLA_SAFE_ASSERT_RETURN(size == sizeof(double),);
6266 paramValue = static_cast<float>((*(const double*)value));
6267 break;
6268 case kUridAtomFloat:
6269 CARLA_SAFE_ASSERT_RETURN(size == sizeof(float),);
6270 paramValue = *(const float*)value;
6271 break;
6272 case kUridAtomInt:
6273 CARLA_SAFE_ASSERT_RETURN(size == sizeof(int32_t),);
6274 paramValue = static_cast<float>(*(const int32_t*)value);
6275 break;
6276 case kUridAtomLong:
6277 CARLA_SAFE_ASSERT_RETURN(size == sizeof(int64_t),);
6278 paramValue = static_cast<float>(*(const int64_t*)value);
6279 break;
6280 default:
6281 carla_stdout("CarlaPluginLV2::handleLilvSetPortValue(\"%s\", %p, %i, %i:\"%s\") - unknown type",
6282 portSymbol, value, size, type, carla_lv2_urid_unmap(this, type));
6283 return;
6284 }
6285
6286 for (uint32_t i=0; i < pData->param.count; ++i)
6287 {
6288 if (pData->param.data[i].rindex == rindex)
6289 {
6290 setParameterValueRT(i, paramValue, true);
6291 break;
6292 }
6293 }
6294 }
6295
6296 // -------------------------------------------------------------------
6297
getNativeHandle() const6298 void* getNativeHandle() const noexcept override
6299 {
6300 return fHandle;
6301 }
6302
getNativeDescriptor() const6303 const void* getNativeDescriptor() const noexcept override
6304 {
6305 return fDescriptor;
6306 }
6307
getUiBridgeProcessId() const6308 uintptr_t getUiBridgeProcessId() const noexcept override
6309 {
6310 return fPipeServer.isPipeRunning() ? fPipeServer.getPID() : 0;
6311 }
6312
6313 // -------------------------------------------------------------------
6314
6315 public:
init(const CarlaPluginPtr plugin,const char * const name,const char * const uri,const uint options,const char * & needsArchBridge)6316 bool init(const CarlaPluginPtr plugin,
6317 const char* const name, const char* const uri, const uint options,
6318 const char*& needsArchBridge)
6319 {
6320 CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);
6321
6322 // ---------------------------------------------------------------
6323 // first checks
6324
6325 if (pData->client != nullptr)
6326 {
6327 pData->engine->setLastError("Plugin client is already registered");
6328 return false;
6329 }
6330
6331 if (uri == nullptr || uri[0] == '\0')
6332 {
6333 pData->engine->setLastError("null uri");
6334 return false;
6335 }
6336
6337 const EngineOptions& opts(pData->engine->getOptions());
6338
6339 // ---------------------------------------------------------------
6340 // Init LV2 World if needed, sets LV2_PATH for lilv
6341
6342 Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
6343
6344 if (opts.pathLV2 != nullptr && opts.pathLV2[0] != '\0')
6345 lv2World.initIfNeeded(opts.pathLV2);
6346 else if (const char* const LV2_PATH = std::getenv("LV2_PATH"))
6347 lv2World.initIfNeeded(LV2_PATH);
6348 else
6349 lv2World.initIfNeeded(LILV_DEFAULT_LV2_PATH);
6350
6351 // ---------------------------------------------------------------
6352 // get plugin from lv2_rdf (lilv)
6353
6354 fRdfDescriptor = lv2_rdf_new(uri, true);
6355
6356 if (fRdfDescriptor == nullptr)
6357 {
6358 pData->engine->setLastError("Failed to find the requested plugin");
6359 return false;
6360 }
6361
6362 #ifdef ADAPT_FOR_APPLE_SILLICON
6363 // ---------------------------------------------------------------
6364 // check if we can open this binary, might need a bridge
6365
6366 {
6367 const CarlaMagic magic;
6368
6369 if (const char* const output = magic.getFileDescription(fRdfDescriptor->Binary))
6370 {
6371 # ifdef __aarch64__
6372 if (std::strstr(output, "arm64") == nullptr && std::strstr(output, "x86_64") != nullptr)
6373 needsArchBridge = "x86_64";
6374 # else
6375 if (std::strstr(output, "x86_64") == nullptr && std::strstr(output, "arm64") != nullptr)
6376 needsArchBridge = "arm64";
6377 # endif
6378 if (needsArchBridge != nullptr)
6379 return false;
6380 }
6381 }
6382 #endif // ADAPT_FOR_APPLE_SILLICON
6383
6384 // ---------------------------------------------------------------
6385 // open DLL
6386
6387 #ifdef CARLA_OS_MAC
6388 // Binary might be in quarentine due to Apple stupid notarization rules, let's remove that if possible
6389 removeFileFromQuarantine(fRdfDescriptor->Binary);
6390 #endif
6391
6392 if (! pData->libOpen(fRdfDescriptor->Binary))
6393 {
6394 pData->engine->setLastError(pData->libError(fRdfDescriptor->Binary));
6395 return false;
6396 }
6397
6398 // ---------------------------------------------------------------
6399 // try to get DLL main entry via new mode
6400
6401 if (const LV2_Lib_Descriptor_Function libDescFn = pData->libSymbol<LV2_Lib_Descriptor_Function>("lv2_lib_descriptor"))
6402 {
6403 // -----------------------------------------------------------
6404 // all ok, get lib descriptor
6405
6406 const LV2_Lib_Descriptor* const libDesc = libDescFn(fRdfDescriptor->Bundle, nullptr);
6407
6408 if (libDesc == nullptr)
6409 {
6410 pData->engine->setLastError("Could not find the LV2 Descriptor");
6411 return false;
6412 }
6413
6414 // -----------------------------------------------------------
6415 // get descriptor that matches URI (new mode)
6416
6417 uint32_t i = 0;
6418 while ((fDescriptor = libDesc->get_plugin(libDesc->handle, i++)))
6419 {
6420 if (std::strcmp(fDescriptor->URI, uri) == 0)
6421 break;
6422 }
6423 }
6424 else
6425 {
6426 // -----------------------------------------------------------
6427 // get DLL main entry (old mode)
6428
6429 const LV2_Descriptor_Function descFn = pData->libSymbol<LV2_Descriptor_Function>("lv2_descriptor");
6430
6431 if (descFn == nullptr)
6432 {
6433 pData->engine->setLastError("Could not find the LV2 Descriptor in the plugin library");
6434 return false;
6435 }
6436
6437 // -----------------------------------------------------------
6438 // get descriptor that matches URI (old mode)
6439
6440 uint32_t i = 0;
6441 while ((fDescriptor = descFn(i++)))
6442 {
6443 if (std::strcmp(fDescriptor->URI, uri) == 0)
6444 break;
6445 }
6446 }
6447
6448 if (fDescriptor == nullptr)
6449 {
6450 pData->engine->setLastError("Could not find the requested plugin URI in the plugin library");
6451 return false;
6452 }
6453
6454 // ---------------------------------------------------------------
6455 // check supported port-types and features
6456
6457 bool canContinue = true;
6458
6459 // Check supported ports
6460 for (uint32_t j=0; j < fRdfDescriptor->PortCount; ++j)
6461 {
6462 const LV2_Property portTypes(fRdfDescriptor->Ports[j].Types);
6463
6464 if (! is_lv2_port_supported(portTypes))
6465 {
6466 if (! LV2_IS_PORT_OPTIONAL(fRdfDescriptor->Ports[j].Properties))
6467 {
6468 pData->engine->setLastError("Plugin requires a port type that is not currently supported");
6469 canContinue = false;
6470 break;
6471 }
6472 }
6473 }
6474
6475 // Check supported features
6476 for (uint32_t j=0; j < fRdfDescriptor->FeatureCount && canContinue; ++j)
6477 {
6478 const LV2_RDF_Feature& feature(fRdfDescriptor->Features[j]);
6479
6480 if (std::strcmp(feature.URI, LV2_DATA_ACCESS_URI) == 0 || std::strcmp(feature.URI, LV2_INSTANCE_ACCESS_URI) == 0)
6481 {
6482 carla_stderr("Plugin DSP wants UI feature '%s', ignoring this", feature.URI);
6483 }
6484 else if (std::strcmp(feature.URI, LV2_BUF_SIZE__fixedBlockLength) == 0)
6485 {
6486 fNeedsFixedBuffers = true;
6487 }
6488 else if (std::strcmp(feature.URI, LV2_PORT_PROPS__supportsStrictBounds) == 0)
6489 {
6490 fStrictBounds = feature.Required ? 1 : 0;
6491 }
6492 else if (std::strcmp(feature.URI, LV2_STATE__loadDefaultState) == 0)
6493 {
6494 fHasLoadDefaultState = true;
6495 }
6496 else if (std::strcmp(feature.URI, LV2_STATE__threadSafeRestore) == 0)
6497 {
6498 fHasThreadSafeRestore = true;
6499 }
6500 else if (feature.Required && ! is_lv2_feature_supported(feature.URI))
6501 {
6502 CarlaString msg("Plugin wants a feature that is not supported:\n");
6503 msg += feature.URI;
6504
6505 canContinue = false;
6506 pData->engine->setLastError(msg);
6507 break;
6508 }
6509 }
6510
6511 if (! canContinue)
6512 {
6513 // error already set
6514 return false;
6515 }
6516
6517 if (fNeedsFixedBuffers && ! pData->engine->usesConstantBufferSize())
6518 {
6519 pData->engine->setLastError("Cannot use this plugin under the current engine.\n"
6520 "The plugin requires a fixed block size which is not possible right now.");
6521 return false;
6522 }
6523
6524 // ---------------------------------------------------------------
6525 // set icon
6526
6527 if (std::strncmp(fDescriptor->URI, "http://distrho.sf.net/", 22) == 0)
6528 pData->iconName = carla_strdup_safe("distrho");
6529
6530 // ---------------------------------------------------------------
6531 // set info
6532
6533 if (name != nullptr && name[0] != '\0')
6534 pData->name = pData->engine->getUniquePluginName(name);
6535 else
6536 pData->name = pData->engine->getUniquePluginName(fRdfDescriptor->Name);
6537
6538 // ---------------------------------------------------------------
6539 // register client
6540
6541 pData->client = pData->engine->addClient(plugin);
6542
6543 if (pData->client == nullptr || ! pData->client->isOk())
6544 {
6545 pData->engine->setLastError("Failed to register plugin client");
6546 return false;
6547 }
6548
6549 // ---------------------------------------------------------------
6550 // initialize options
6551
6552 const int bufferSize = static_cast<int>(pData->engine->getBufferSize());
6553
6554 fLv2Options.minBufferSize = fNeedsFixedBuffers ? bufferSize : 1;
6555 fLv2Options.maxBufferSize = bufferSize;
6556 fLv2Options.nominalBufferSize = bufferSize;
6557 fLv2Options.sampleRate = static_cast<float>(pData->engine->getSampleRate());
6558 fLv2Options.transientWinId = static_cast<int64_t>(opts.frontendWinId);
6559
6560 uint32_t eventBufferSize = MAX_DEFAULT_BUFFER_SIZE;
6561
6562 for (uint32_t j=0; j < fRdfDescriptor->PortCount; ++j)
6563 {
6564 const LV2_Property portTypes(fRdfDescriptor->Ports[j].Types);
6565
6566 if (LV2_IS_PORT_ATOM_SEQUENCE(portTypes) || LV2_IS_PORT_EVENT(portTypes) || LV2_IS_PORT_MIDI_LL(portTypes))
6567 {
6568 if (fRdfDescriptor->Ports[j].MinimumSize > eventBufferSize)
6569 eventBufferSize = fRdfDescriptor->Ports[j].MinimumSize;
6570 }
6571 }
6572
6573 fLv2Options.sequenceSize = static_cast<int>(eventBufferSize);
6574
6575 fLv2Options.bgColor = opts.bgColor;
6576 fLv2Options.fgColor = opts.fgColor;
6577 fLv2Options.uiScale = opts.uiScale;
6578
6579 // ---------------------------------------------------------------
6580 // initialize features (part 1)
6581
6582 LV2_Event_Feature* const eventFt = new LV2_Event_Feature;
6583 eventFt->callback_data = this;
6584 eventFt->lv2_event_ref = carla_lv2_event_ref;
6585 eventFt->lv2_event_unref = carla_lv2_event_unref;
6586
6587 LV2_Log_Log* const logFt = new LV2_Log_Log;
6588 logFt->handle = this;
6589 logFt->printf = carla_lv2_log_printf;
6590 logFt->vprintf = carla_lv2_log_vprintf;
6591
6592 LV2_State_Free_Path* const stateFreePathFt = new LV2_State_Free_Path;
6593 stateFreePathFt->handle = this;
6594 stateFreePathFt->free_path = carla_lv2_state_free_path;
6595
6596 LV2_State_Make_Path* const stateMakePathFt = new LV2_State_Make_Path;
6597 stateMakePathFt->handle = this;
6598 stateMakePathFt->path = carla_lv2_state_make_path_tmp;
6599
6600 LV2_State_Map_Path* const stateMapPathFt = new LV2_State_Map_Path;
6601 stateMapPathFt->handle = this;
6602 stateMapPathFt->abstract_path = carla_lv2_state_map_to_abstract_path_tmp;
6603 stateMapPathFt->absolute_path = carla_lv2_state_map_to_absolute_path_tmp;
6604
6605 LV2_Programs_Host* const programsFt = new LV2_Programs_Host;
6606 programsFt->handle = this;
6607 programsFt->program_changed = carla_lv2_program_changed;
6608
6609 LV2_Resize_Port_Resize* const rsPortFt = new LV2_Resize_Port_Resize;
6610 rsPortFt->data = this;
6611 rsPortFt->resize = carla_lv2_resize_port;
6612
6613 LV2_RtMemPool_Pool* const rtMemPoolFt = new LV2_RtMemPool_Pool;
6614 lv2_rtmempool_init(rtMemPoolFt);
6615
6616 LV2_RtMemPool_Pool_Deprecated* const rtMemPoolOldFt = new LV2_RtMemPool_Pool_Deprecated;
6617 lv2_rtmempool_init_deprecated(rtMemPoolOldFt);
6618
6619 LV2_URI_Map_Feature* const uriMapFt = new LV2_URI_Map_Feature;
6620 uriMapFt->callback_data = this;
6621 uriMapFt->uri_to_id = carla_lv2_uri_to_id;
6622
6623 LV2_URID_Map* const uridMapFt = new LV2_URID_Map;
6624 uridMapFt->handle = this;
6625 uridMapFt->map = carla_lv2_urid_map;
6626
6627 LV2_URID_Unmap* const uridUnmapFt = new LV2_URID_Unmap;
6628 uridUnmapFt->handle = this;
6629 uridUnmapFt->unmap = carla_lv2_urid_unmap;
6630
6631 LV2_Worker_Schedule* const workerFt = new LV2_Worker_Schedule;
6632 workerFt->handle = this;
6633 workerFt->schedule_work = carla_lv2_worker_schedule;
6634
6635 LV2_Inline_Display* const inlineDisplay = new LV2_Inline_Display;
6636 inlineDisplay->handle = this;
6637 inlineDisplay->queue_draw = carla_lv2_inline_display_queue_draw;
6638
6639 LV2_Midnam* const midnam = new LV2_Midnam;
6640 midnam->handle = this;
6641 midnam->update = carla_lv2_midnam_update;
6642
6643 // ---------------------------------------------------------------
6644 // initialize features (part 2)
6645
6646 for (uint32_t j=0; j < kFeatureCountPlugin; ++j)
6647 fFeatures[j] = new LV2_Feature;
6648
6649 fFeatures[kFeatureIdBufSizeBounded]->URI = LV2_BUF_SIZE__boundedBlockLength;
6650 fFeatures[kFeatureIdBufSizeBounded]->data = nullptr;
6651
6652 fFeatures[kFeatureIdBufSizeFixed]->URI = fNeedsFixedBuffers
6653 ? LV2_BUF_SIZE__fixedBlockLength
6654 : LV2_BUF_SIZE__boundedBlockLength;
6655 fFeatures[kFeatureIdBufSizeFixed]->data = nullptr;
6656
6657 fFeatures[kFeatureIdBufSizePowerOf2]->URI = LV2_BUF_SIZE__powerOf2BlockLength;
6658 fFeatures[kFeatureIdBufSizePowerOf2]->data = nullptr;
6659
6660 fFeatures[kFeatureIdEvent]->URI = LV2_EVENT_URI;
6661 fFeatures[kFeatureIdEvent]->data = eventFt;
6662
6663 fFeatures[kFeatureIdHardRtCapable]->URI = LV2_CORE__hardRTCapable;
6664 fFeatures[kFeatureIdHardRtCapable]->data = nullptr;
6665
6666 fFeatures[kFeatureIdInPlaceBroken]->URI = LV2_CORE__inPlaceBroken;
6667 fFeatures[kFeatureIdInPlaceBroken]->data = nullptr;
6668
6669 fFeatures[kFeatureIdIsLive]->URI = LV2_CORE__isLive;
6670 fFeatures[kFeatureIdIsLive]->data = nullptr;
6671
6672 fFeatures[kFeatureIdLogs]->URI = LV2_LOG__log;
6673 fFeatures[kFeatureIdLogs]->data = logFt;
6674
6675 fFeatures[kFeatureIdOptions]->URI = LV2_OPTIONS__options;
6676 fFeatures[kFeatureIdOptions]->data = fLv2Options.opts;
6677
6678 fFeatures[kFeatureIdPrograms]->URI = LV2_PROGRAMS__Host;
6679 fFeatures[kFeatureIdPrograms]->data = programsFt;
6680
6681 fFeatures[kFeatureIdResizePort]->URI = LV2_RESIZE_PORT__resize;
6682 fFeatures[kFeatureIdResizePort]->data = rsPortFt;
6683
6684 fFeatures[kFeatureIdRtMemPool]->URI = LV2_RTSAFE_MEMORY_POOL__Pool;
6685 fFeatures[kFeatureIdRtMemPool]->data = rtMemPoolFt;
6686
6687 fFeatures[kFeatureIdRtMemPoolOld]->URI = LV2_RTSAFE_MEMORY_POOL_DEPRECATED_URI;
6688 fFeatures[kFeatureIdRtMemPoolOld]->data = rtMemPoolOldFt;
6689
6690 fFeatures[kFeatureIdStateFreePath]->URI = LV2_STATE__freePath;
6691 fFeatures[kFeatureIdStateFreePath]->data = stateFreePathFt;
6692
6693 fFeatures[kFeatureIdStateMakePath]->URI = LV2_STATE__makePath;
6694 fFeatures[kFeatureIdStateMakePath]->data = stateMakePathFt;
6695
6696 fFeatures[kFeatureIdStateMapPath]->URI = LV2_STATE__mapPath;
6697 fFeatures[kFeatureIdStateMapPath]->data = stateMapPathFt;
6698
6699 fFeatures[kFeatureIdStrictBounds]->URI = LV2_PORT_PROPS__supportsStrictBounds;
6700 fFeatures[kFeatureIdStrictBounds]->data = nullptr;
6701
6702 fFeatures[kFeatureIdUriMap]->URI = LV2_URI_MAP_URI;
6703 fFeatures[kFeatureIdUriMap]->data = uriMapFt;
6704
6705 fFeatures[kFeatureIdUridMap]->URI = LV2_URID__map;
6706 fFeatures[kFeatureIdUridMap]->data = uridMapFt;
6707
6708 fFeatures[kFeatureIdUridUnmap]->URI = LV2_URID__unmap;
6709 fFeatures[kFeatureIdUridUnmap]->data = uridUnmapFt;
6710
6711 fFeatures[kFeatureIdWorker]->URI = LV2_WORKER__schedule;
6712 fFeatures[kFeatureIdWorker]->data = workerFt;
6713
6714 fFeatures[kFeatureIdInlineDisplay]->URI = LV2_INLINEDISPLAY__queue_draw;
6715 fFeatures[kFeatureIdInlineDisplay]->data = inlineDisplay;
6716
6717 fFeatures[kFeatureIdMidnam]->URI = LV2_MIDNAM__update;
6718 fFeatures[kFeatureIdMidnam]->data = midnam;
6719
6720 // ---------------------------------------------------------------
6721 // initialize features (part 3)
6722
6723 LV2_State_Make_Path* const stateMakePathFt2 = new LV2_State_Make_Path;
6724 stateMakePathFt2->handle = this;
6725 stateMakePathFt2->path = carla_lv2_state_make_path_real;
6726
6727 LV2_State_Map_Path* const stateMapPathFt2 = new LV2_State_Map_Path;
6728 stateMapPathFt2->handle = this;
6729 stateMapPathFt2->abstract_path = carla_lv2_state_map_to_abstract_path_real;
6730 stateMapPathFt2->absolute_path = carla_lv2_state_map_to_absolute_path_real;
6731
6732 for (uint32_t j=0; j < kStateFeatureCountAll; ++j)
6733 fStateFeatures[j] = new LV2_Feature;
6734
6735 fStateFeatures[kStateFeatureIdFreePath]->URI = LV2_STATE__freePath;
6736 fStateFeatures[kStateFeatureIdFreePath]->data = stateFreePathFt;
6737
6738 fStateFeatures[kStateFeatureIdMakePath]->URI = LV2_STATE__makePath;
6739 fStateFeatures[kStateFeatureIdMakePath]->data = stateMakePathFt2;
6740
6741 fStateFeatures[kStateFeatureIdMapPath]->URI = LV2_STATE__mapPath;
6742 fStateFeatures[kStateFeatureIdMapPath]->data = stateMapPathFt2;
6743
6744 fStateFeatures[kStateFeatureIdWorker]->URI = LV2_WORKER__schedule;
6745 fStateFeatures[kStateFeatureIdWorker]->data = workerFt;
6746
6747 // ---------------------------------------------------------------
6748 // initialize plugin
6749
6750 try {
6751 fHandle = fDescriptor->instantiate(fDescriptor, pData->engine->getSampleRate(), fRdfDescriptor->Bundle, fFeatures);
6752 } catch(...) {}
6753
6754 if (fHandle == nullptr)
6755 {
6756 pData->engine->setLastError("Plugin failed to initialize");
6757 return false;
6758 }
6759
6760 recheckExtensions();
6761
6762 // ---------------------------------------------------------------
6763 // set options
6764
6765 pData->options = 0x0;
6766
6767 if (fLatencyIndex >= 0 || getMidiOutCount() != 0 || fNeedsFixedBuffers)
6768 pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;
6769 else if (options & PLUGIN_OPTION_FIXED_BUFFERS)
6770 pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;
6771
6772 if (opts.forceStereo)
6773 pData->options |= PLUGIN_OPTION_FORCE_STEREO;
6774 else if (options & PLUGIN_OPTION_FORCE_STEREO)
6775 pData->options |= PLUGIN_OPTION_FORCE_STEREO;
6776
6777 if (getMidiInCount() != 0)
6778 {
6779 if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CONTROL_CHANGES))
6780 pData->options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
6781 if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CHANNEL_PRESSURE))
6782 pData->options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
6783 if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH))
6784 pData->options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
6785 if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PITCHBEND))
6786 pData->options |= PLUGIN_OPTION_SEND_PITCHBEND;
6787 if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_ALL_SOUND_OFF))
6788 pData->options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
6789 if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PROGRAM_CHANGES))
6790 pData->options |= PLUGIN_OPTION_SEND_PROGRAM_CHANGES;
6791 if (isPluginOptionInverseEnabled(options, PLUGIN_OPTION_SKIP_SENDING_NOTES))
6792 pData->options |= PLUGIN_OPTION_SKIP_SENDING_NOTES;
6793 }
6794
6795 if (fExt.programs != nullptr && (pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES) == 0)
6796 {
6797 if (isPluginOptionEnabled(options, PLUGIN_OPTION_MAP_PROGRAM_CHANGES))
6798 pData->options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
6799 }
6800
6801 // ---------------------------------------------------------------
6802 // gui stuff
6803
6804 if (fRdfDescriptor->UICount != 0)
6805 initUi();
6806
6807 return true;
6808
6809 // might be unused
6810 (void)needsArchBridge;
6811 }
6812
6813 // -------------------------------------------------------------------
6814
initUi()6815 void initUi()
6816 {
6817 // ---------------------------------------------------------------
6818 // find the most appropriate ui
6819
6820 int eQt4, eQt5, eGtk2, eGtk3, eCocoa, eWindows, eX11, eMod, iCocoa, iWindows, iX11, iExt, iFinal;
6821 eQt4 = eQt5 = eGtk2 = eGtk3 = eCocoa = eWindows = eX11 = eMod = iCocoa = iWindows = iX11 = iExt = iFinal = -1;
6822
6823 #if defined(LV2_UIS_ONLY_BRIDGES)
6824 const bool preferUiBridges = true;
6825 #elif defined(BUILD_BRIDGE)
6826 const bool preferUiBridges = false;
6827 #else
6828 const bool preferUiBridges = pData->engine->getOptions().preferUiBridges;
6829 #endif
6830 bool hasShowInterface = false;
6831
6832 for (uint32_t i=0; i < fRdfDescriptor->UICount; ++i)
6833 {
6834 CARLA_SAFE_ASSERT_CONTINUE(fRdfDescriptor->UIs[i].URI != nullptr);
6835
6836 const int ii(static_cast<int>(i));
6837
6838 switch (fRdfDescriptor->UIs[i].Type)
6839 {
6840 case LV2_UI_QT4:
6841 if (isUiBridgeable(i))
6842 eQt4 = ii;
6843 break;
6844 case LV2_UI_QT5:
6845 if (isUiBridgeable(i))
6846 eQt5 = ii;
6847 break;
6848 case LV2_UI_GTK2:
6849 if (isUiBridgeable(i))
6850 eGtk2 = ii;
6851 break;
6852 case LV2_UI_GTK3:
6853 if (isUiBridgeable(i))
6854 eGtk3 = ii;
6855 break;
6856 #ifdef CARLA_OS_MAC
6857 case LV2_UI_COCOA:
6858 if (isUiBridgeable(i) && preferUiBridges)
6859 eCocoa = ii;
6860 iCocoa = ii;
6861 break;
6862 #endif
6863 #ifdef CARLA_OS_WIN
6864 case LV2_UI_WINDOWS:
6865 if (isUiBridgeable(i) && preferUiBridges)
6866 eWindows = ii;
6867 iWindows = ii;
6868 break;
6869 #endif
6870 case LV2_UI_X11:
6871 if (isUiBridgeable(i) && preferUiBridges)
6872 eX11 = ii;
6873 iX11 = ii;
6874 break;
6875 case LV2_UI_EXTERNAL:
6876 case LV2_UI_OLD_EXTERNAL:
6877 iExt = ii;
6878 break;
6879 case LV2_UI_MOD:
6880 eMod = ii;
6881 break;
6882 default:
6883 break;
6884 }
6885 }
6886
6887 /**/ if (eQt4 >= 0)
6888 iFinal = eQt4;
6889 else if (eQt5 >= 0)
6890 iFinal = eQt5;
6891 else if (eGtk2 >= 0)
6892 iFinal = eGtk2;
6893 else if (eGtk3 >= 0)
6894 iFinal = eGtk3;
6895 #ifdef CARLA_OS_MAC
6896 else if (eCocoa >= 0)
6897 iFinal = eCocoa;
6898 #endif
6899 #ifdef CARLA_OS_WIN
6900 else if (eWindows >= 0)
6901 iFinal = eWindows;
6902 #endif
6903 #ifdef HAVE_X11
6904 else if (eX11 >= 0)
6905 iFinal = eX11;
6906 #endif
6907 #ifndef LV2_UIS_ONLY_BRIDGES
6908 # ifdef CARLA_OS_MAC
6909 else if (iCocoa >= 0)
6910 iFinal = iCocoa;
6911 # endif
6912 # ifdef CARLA_OS_WIN
6913 else if (iWindows >= 0)
6914 iFinal = iWindows;
6915 # endif
6916 # ifdef HAVE_X11
6917 else if (iX11 >= 0)
6918 iFinal = iX11;
6919 # endif
6920 #endif
6921 else if (iExt >= 0)
6922 iFinal = iExt;
6923
6924 #ifndef BUILD_BRIDGE
6925 if (iFinal < 0)
6926 #endif
6927 {
6928 // no suitable UI found, see if there's one which supports ui:showInterface
6929 for (uint32_t i=0; i < fRdfDescriptor->UICount && ! hasShowInterface; ++i)
6930 {
6931 LV2_RDF_UI* const ui(&fRdfDescriptor->UIs[i]);
6932
6933 for (uint32_t j=0; j < ui->ExtensionCount; ++j)
6934 {
6935 CARLA_SAFE_ASSERT_CONTINUE(ui->Extensions[j] != nullptr);
6936
6937 if (std::strcmp(ui->Extensions[j], LV2_UI__showInterface) != 0)
6938 continue;
6939
6940 iFinal = static_cast<int>(i);
6941 hasShowInterface = true;
6942 break;
6943 }
6944 }
6945
6946 if (iFinal < 0)
6947 {
6948 if (eMod < 0)
6949 {
6950 carla_stderr("Failed to find an appropriate LV2 UI for this plugin");
6951 return;
6952 }
6953
6954 // use MODGUI as last resort
6955 iFinal = eMod;
6956 }
6957 }
6958
6959 fUI.rdfDescriptor = &fRdfDescriptor->UIs[iFinal];
6960
6961 // ---------------------------------------------------------------
6962 // check supported ui features
6963
6964 bool canContinue = true;
6965 bool canDelete = true;
6966
6967 for (uint32_t i=0; i < fUI.rdfDescriptor->FeatureCount; ++i)
6968 {
6969 const char* const uri(fUI.rdfDescriptor->Features[i].URI);
6970 CARLA_SAFE_ASSERT_CONTINUE(uri != nullptr && uri[0] != '\0');
6971
6972 if (! is_lv2_ui_feature_supported(uri))
6973 {
6974 if (fUI.rdfDescriptor->Features[i].Required)
6975 {
6976 carla_stderr("Plugin UI requires a feature that is not supported:\n%s", uri);
6977 canContinue = false;
6978 break;
6979 }
6980
6981 carla_stderr("Plugin UI wants a feature that is not supported (ignored):\n%s", uri);
6982 }
6983
6984 if (std::strcmp(uri, LV2_UI__makeResident) == 0 || std::strcmp(uri, LV2_UI__makeSONameResident) == 0)
6985 canDelete = false;
6986 else if (std::strcmp(uri, LV2_UI__requestValue) == 0)
6987 pData->hints |= PLUGIN_NEEDS_UI_MAIN_THREAD;
6988 }
6989
6990 if (! canContinue)
6991 {
6992 fUI.rdfDescriptor = nullptr;
6993 return;
6994 }
6995
6996 // ---------------------------------------------------------------
6997 // initialize ui according to type
6998
6999 const LV2_Property uiType(fUI.rdfDescriptor->Type);
7000
7001 if (
7002 (iFinal == eQt4 ||
7003 iFinal == eQt5 ||
7004 iFinal == eGtk2 ||
7005 iFinal == eGtk3 ||
7006 iFinal == eCocoa ||
7007 iFinal == eWindows ||
7008 iFinal == eX11 ||
7009 iFinal == eMod)
7010 #ifdef BUILD_BRIDGE
7011 && ! hasShowInterface
7012 #endif
7013 )
7014 {
7015 // -----------------------------------------------------------
7016 // initialize ui-bridge
7017
7018 if (const char* const bridgeBinary = getUiBridgeBinary(uiType))
7019 {
7020 carla_stdout("Will use UI-Bridge for '%s', binary: \"%s\"", pData->name, bridgeBinary);
7021
7022 CarlaString uiTitle;
7023
7024 if (pData->uiTitle.isNotEmpty())
7025 {
7026 uiTitle = pData->uiTitle;
7027 }
7028 else
7029 {
7030 uiTitle = pData->name;
7031 uiTitle += " (GUI)";
7032 }
7033
7034 fLv2Options.windowTitle = uiTitle.releaseBufferPointer();
7035
7036 fUI.type = UI::TYPE_BRIDGE;
7037 fPipeServer.setData(bridgeBinary, fRdfDescriptor->URI, fUI.rdfDescriptor->URI);
7038
7039 delete[] bridgeBinary;
7040 return;
7041 }
7042
7043 if (iFinal == eQt4 || iFinal == eQt5 || iFinal == eGtk2 || iFinal == eGtk3 || iFinal == eMod)
7044 {
7045 carla_stderr2("Failed to find UI bridge binary for '%s', cannot use UI", pData->name);
7046 fUI.rdfDescriptor = nullptr;
7047 return;
7048 }
7049 }
7050
7051 #ifdef LV2_UIS_ONLY_BRIDGES
7052 carla_stderr2("Failed to get an UI working, canBridge:%s", bool2str(isUiBridgeable(static_cast<uint32_t>(iFinal))));
7053 fUI.rdfDescriptor = nullptr;
7054 return;
7055 #endif
7056
7057 // ---------------------------------------------------------------
7058 // open UI DLL
7059
7060 #ifdef CARLA_OS_MAC
7061 // Binary might be in quarentine due to Apple stupid notarization rules, let's remove that if possible
7062 removeFileFromQuarantine(fUI.rdfDescriptor->Binary);
7063 #endif
7064
7065 if (! pData->uiLibOpen(fUI.rdfDescriptor->Binary, canDelete))
7066 {
7067 carla_stderr2("Could not load UI library, error was:\n%s", pData->libError(fUI.rdfDescriptor->Binary));
7068 fUI.rdfDescriptor = nullptr;
7069 return;
7070 }
7071
7072 // ---------------------------------------------------------------
7073 // get UI DLL main entry
7074
7075 LV2UI_DescriptorFunction uiDescFn = pData->uiLibSymbol<LV2UI_DescriptorFunction>("lv2ui_descriptor");
7076
7077 if (uiDescFn == nullptr)
7078 {
7079 carla_stderr2("Could not find the LV2UI Descriptor in the UI library");
7080 pData->uiLibClose();
7081 fUI.rdfDescriptor = nullptr;
7082 return;
7083 }
7084
7085 // ---------------------------------------------------------------
7086 // get UI descriptor that matches UI URI
7087
7088 uint32_t i = 0;
7089 while ((fUI.descriptor = uiDescFn(i++)))
7090 {
7091 if (std::strcmp(fUI.descriptor->URI, fUI.rdfDescriptor->URI) == 0)
7092 break;
7093 }
7094
7095 if (fUI.descriptor == nullptr)
7096 {
7097 carla_stderr2("Could not find the requested GUI in the plugin UI library");
7098 pData->uiLibClose();
7099 fUI.rdfDescriptor = nullptr;
7100 return;
7101 }
7102
7103 // ---------------------------------------------------------------
7104 // check if ui is usable
7105
7106 switch (uiType)
7107 {
7108 case LV2_UI_NONE:
7109 carla_stdout("Will use LV2 Show Interface for '%s'", pData->name);
7110 fUI.type = UI::TYPE_EMBED;
7111 break;
7112 case LV2_UI_QT4:
7113 carla_stdout("Will use LV2 Qt4 UI for '%s', NOT!", pData->name);
7114 fUI.type = UI::TYPE_EMBED;
7115 break;
7116 case LV2_UI_QT5:
7117 carla_stdout("Will use LV2 Qt5 UI for '%s', NOT!", pData->name);
7118 fUI.type = UI::TYPE_EMBED;
7119 break;
7120 case LV2_UI_GTK2:
7121 carla_stdout("Will use LV2 Gtk2 UI for '%s', NOT!", pData->name);
7122 fUI.type = UI::TYPE_EMBED;
7123 break;
7124 case LV2_UI_GTK3:
7125 carla_stdout("Will use LV2 Gtk3 UI for '%s', NOT!", pData->name);
7126 fUI.type = UI::TYPE_EMBED;
7127 break;
7128 #ifdef CARLA_OS_MAC
7129 case LV2_UI_COCOA:
7130 carla_stdout("Will use LV2 Cocoa UI for '%s'", pData->name);
7131 fUI.type = UI::TYPE_EMBED;
7132 break;
7133 #endif
7134 #ifdef CARLA_OS_WIN
7135 case LV2_UI_WINDOWS:
7136 carla_stdout("Will use LV2 Windows UI for '%s'", pData->name);
7137 fUI.type = UI::TYPE_EMBED;
7138 break;
7139 #endif
7140 case LV2_UI_X11:
7141 #ifdef HAVE_X11
7142 carla_stdout("Will use LV2 X11 UI for '%s'", pData->name);
7143 #else
7144 carla_stdout("Will use LV2 X11 UI for '%s', NOT!", pData->name);
7145 #endif
7146 fUI.type = UI::TYPE_EMBED;
7147 break;
7148 case LV2_UI_EXTERNAL:
7149 case LV2_UI_OLD_EXTERNAL:
7150 carla_stdout("Will use LV2 External UI for '%s'", pData->name);
7151 fUI.type = UI::TYPE_EXTERNAL;
7152 break;
7153 }
7154
7155 if (fUI.type == UI::TYPE_NULL)
7156 {
7157 pData->uiLibClose();
7158 fUI.descriptor = nullptr;
7159 fUI.rdfDescriptor = nullptr;
7160 return;
7161 }
7162
7163 // ---------------------------------------------------------------
7164 // initialize ui data
7165
7166 {
7167 CarlaString uiTitle;
7168
7169 if (pData->uiTitle.isNotEmpty())
7170 {
7171 uiTitle = pData->uiTitle;
7172 }
7173 else
7174 {
7175 uiTitle = pData->name;
7176 uiTitle += " (GUI)";
7177 }
7178
7179 fLv2Options.windowTitle = uiTitle.releaseBufferPointer();
7180 }
7181
7182 fLv2Options.opts[CarlaPluginLV2Options::WindowTitle].size = (uint32_t)std::strlen(fLv2Options.windowTitle);
7183 fLv2Options.opts[CarlaPluginLV2Options::WindowTitle].value = fLv2Options.windowTitle;
7184
7185 // ---------------------------------------------------------------
7186 // initialize ui features (part 1)
7187
7188 LV2_Extension_Data_Feature* const uiDataFt = new LV2_Extension_Data_Feature;
7189 uiDataFt->data_access = fDescriptor->extension_data;
7190
7191 LV2UI_Port_Map* const uiPortMapFt = new LV2UI_Port_Map;
7192 uiPortMapFt->handle = this;
7193 uiPortMapFt->port_index = carla_lv2_ui_port_map;
7194
7195 LV2UI_Request_Value* const uiRequestValueFt = new LV2UI_Request_Value;
7196 uiRequestValueFt->handle = this;
7197 uiRequestValueFt->request = carla_lv2_ui_request_value;
7198
7199 LV2UI_Resize* const uiResizeFt = new LV2UI_Resize;
7200 uiResizeFt->handle = this;
7201 uiResizeFt->ui_resize = carla_lv2_ui_resize;
7202
7203 LV2UI_Touch* const uiTouchFt = new LV2UI_Touch;
7204 uiTouchFt->handle = this;
7205 uiTouchFt->touch = carla_lv2_ui_touch;
7206
7207 LV2_External_UI_Host* const uiExternalHostFt = new LV2_External_UI_Host;
7208 uiExternalHostFt->ui_closed = carla_lv2_external_ui_closed;
7209 uiExternalHostFt->plugin_human_id = fLv2Options.windowTitle;
7210
7211 // ---------------------------------------------------------------
7212 // initialize ui features (part 2)
7213
7214 for (uint32_t j=kFeatureCountPlugin; j < kFeatureCountAll; ++j)
7215 fFeatures[j] = new LV2_Feature;
7216
7217 fFeatures[kFeatureIdUiDataAccess]->URI = LV2_DATA_ACCESS_URI;
7218 fFeatures[kFeatureIdUiDataAccess]->data = uiDataFt;
7219
7220 fFeatures[kFeatureIdUiInstanceAccess]->URI = LV2_INSTANCE_ACCESS_URI;
7221 fFeatures[kFeatureIdUiInstanceAccess]->data = fHandle;
7222
7223 fFeatures[kFeatureIdUiIdleInterface]->URI = LV2_UI__idleInterface;
7224 fFeatures[kFeatureIdUiIdleInterface]->data = nullptr;
7225
7226 fFeatures[kFeatureIdUiFixedSize]->URI = LV2_UI__fixedSize;
7227 fFeatures[kFeatureIdUiFixedSize]->data = nullptr;
7228
7229 fFeatures[kFeatureIdUiMakeResident]->URI = LV2_UI__makeResident;
7230 fFeatures[kFeatureIdUiMakeResident]->data = nullptr;
7231
7232 fFeatures[kFeatureIdUiMakeResident2]->URI = LV2_UI__makeSONameResident;
7233 fFeatures[kFeatureIdUiMakeResident2]->data = nullptr;
7234
7235 fFeatures[kFeatureIdUiNoUserResize]->URI = LV2_UI__noUserResize;
7236 fFeatures[kFeatureIdUiNoUserResize]->data = nullptr;
7237
7238 fFeatures[kFeatureIdUiParent]->URI = LV2_UI__parent;
7239 fFeatures[kFeatureIdUiParent]->data = nullptr;
7240
7241 fFeatures[kFeatureIdUiPortMap]->URI = LV2_UI__portMap;
7242 fFeatures[kFeatureIdUiPortMap]->data = uiPortMapFt;
7243
7244 fFeatures[kFeatureIdUiPortSubscribe]->URI = LV2_UI__portSubscribe;
7245 fFeatures[kFeatureIdUiPortSubscribe]->data = nullptr;
7246
7247 fFeatures[kFeatureIdUiRequestValue]->URI = LV2_UI__requestValue;
7248 fFeatures[kFeatureIdUiRequestValue]->data = uiRequestValueFt;
7249
7250 fFeatures[kFeatureIdUiResize]->URI = LV2_UI__resize;
7251 fFeatures[kFeatureIdUiResize]->data = uiResizeFt;
7252
7253 fFeatures[kFeatureIdUiTouch]->URI = LV2_UI__touch;
7254 fFeatures[kFeatureIdUiTouch]->data = uiTouchFt;
7255
7256 fFeatures[kFeatureIdExternalUi]->URI = LV2_EXTERNAL_UI__Host;
7257 fFeatures[kFeatureIdExternalUi]->data = uiExternalHostFt;
7258
7259 fFeatures[kFeatureIdExternalUiOld]->URI = LV2_EXTERNAL_UI_DEPRECATED_URI;
7260 fFeatures[kFeatureIdExternalUiOld]->data = uiExternalHostFt;
7261
7262 // ---------------------------------------------------------------
7263 // initialize ui extensions
7264
7265 if (fUI.descriptor->extension_data == nullptr)
7266 return;
7267
7268 fExt.uiidle = (const LV2UI_Idle_Interface*)fUI.descriptor->extension_data(LV2_UI__idleInterface);
7269 fExt.uishow = (const LV2UI_Show_Interface*)fUI.descriptor->extension_data(LV2_UI__showInterface);
7270 fExt.uiresize = (const LV2UI_Resize*)fUI.descriptor->extension_data(LV2_UI__resize);
7271 fExt.uiprograms = (const LV2_Programs_UI_Interface*)fUI.descriptor->extension_data(LV2_PROGRAMS__UIInterface);
7272
7273 // check if invalid
7274 if (fExt.uiidle != nullptr && fExt.uiidle->idle == nullptr)
7275 fExt.uiidle = nullptr;
7276
7277 if (fExt.uishow != nullptr && (fExt.uishow->show == nullptr || fExt.uishow->hide == nullptr))
7278 fExt.uishow = nullptr;
7279
7280 if (fExt.uiresize != nullptr && fExt.uiresize->ui_resize == nullptr)
7281 fExt.uiresize = nullptr;
7282
7283 if (fExt.uiprograms != nullptr && fExt.uiprograms->select_program == nullptr)
7284 fExt.uiprograms = nullptr;
7285
7286 // don't use uiidle if external
7287 if (fUI.type == UI::TYPE_EXTERNAL)
7288 fExt.uiidle = nullptr;
7289 }
7290
7291 // -------------------------------------------------------------------
7292
handleTransferAtom(const uint32_t portIndex,const LV2_Atom * const atom)7293 void handleTransferAtom(const uint32_t portIndex, const LV2_Atom* const atom)
7294 {
7295 CARLA_SAFE_ASSERT_RETURN(atom != nullptr,);
7296 carla_debug("CarlaPluginLV2::handleTransferAtom(%i, %p)", portIndex, atom);
7297
7298 fAtomBufferEvIn.put(atom, portIndex);
7299 }
7300
handleUridMap(const LV2_URID urid,const char * const uri)7301 void handleUridMap(const LV2_URID urid, const char* const uri)
7302 {
7303 CARLA_SAFE_ASSERT_RETURN(urid != kUridNull,);
7304 CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0',);
7305 carla_debug("CarlaPluginLV2::handleUridMap(%i v " P_SIZE ", \"%s\")", urid, fCustomURIDs.size()-1, uri);
7306
7307 const std::size_t uriCount(fCustomURIDs.size());
7308
7309 if (urid < uriCount)
7310 {
7311 const char* const ourURI(carla_lv2_urid_unmap(this, urid));
7312 CARLA_SAFE_ASSERT_RETURN(ourURI != nullptr && ourURI != kUnmapFallback,);
7313
7314 if (std::strcmp(ourURI, uri) != 0)
7315 {
7316 carla_stderr2("PLUGIN :: wrong URI '%s' vs '%s'", ourURI, uri);
7317 }
7318 }
7319 else
7320 {
7321 CARLA_SAFE_ASSERT_RETURN(urid == uriCount,);
7322 fCustomURIDs.push_back(uri);
7323 }
7324 }
7325
7326 // -------------------------------------------------------------------
7327
writeAtomPath(const char * const path,const LV2_URID urid)7328 void writeAtomPath(const char* const path, const LV2_URID urid)
7329 {
7330 uint8_t atomBuf[4096];
7331 LV2_Atom_Forge atomForge;
7332 initAtomForge(atomForge);
7333 lv2_atom_forge_set_buffer(&atomForge, atomBuf, sizeof(atomBuf));
7334
7335 LV2_Atom_Forge_Frame forgeFrame;
7336 lv2_atom_forge_object(&atomForge, &forgeFrame, kUridNull, kUridPatchSet);
7337
7338 lv2_atom_forge_key(&atomForge, kUridCarlaParameterChange);
7339 lv2_atom_forge_bool(&atomForge, true);
7340
7341 lv2_atom_forge_key(&atomForge, kUridPatchProperty);
7342 lv2_atom_forge_urid(&atomForge, urid);
7343
7344 lv2_atom_forge_key(&atomForge, kUridPatchValue);
7345 lv2_atom_forge_path(&atomForge, path, static_cast<uint32_t>(std::strlen(path))+1);
7346
7347 lv2_atom_forge_pop(&atomForge, &forgeFrame);
7348
7349 LV2_Atom* const atom((LV2_Atom*)atomBuf);
7350 CARLA_SAFE_ASSERT(atom->size < sizeof(atomBuf));
7351
7352 fAtomBufferEvIn.put(atom, fEventsIn.ctrlIndex);
7353 }
7354
7355 // -------------------------------------------------------------------
7356
7357 private:
7358 LV2_Handle fHandle;
7359 LV2_Handle fHandle2;
7360 LV2_Feature* fFeatures[kFeatureCountAll+1];
7361 LV2_Feature* fStateFeatures[kStateFeatureCountAll+1];
7362 const LV2_Descriptor* fDescriptor;
7363 const LV2_RDF_Descriptor* fRdfDescriptor;
7364
7365 float** fAudioInBuffers;
7366 float** fAudioOutBuffers;
7367 float** fCvInBuffers;
7368 float** fCvOutBuffers;
7369 float* fParamBuffers;
7370
7371 bool fHasLoadDefaultState : 1;
7372 bool fHasThreadSafeRestore : 1;
7373 bool fNeedsFixedBuffers : 1;
7374 bool fNeedsUiClose : 1;
7375 bool fInlineDisplayNeedsRedraw : 1;
7376 int64_t fInlineDisplayLastRedrawTime;
7377 int32_t fLatencyIndex; // -1 if invalid
7378 int fStrictBounds; // -1 unsupported, 0 optional, 1 required
7379
7380 Lv2AtomRingBuffer fAtomBufferEvIn;
7381 Lv2AtomRingBuffer fAtomBufferUiOut;
7382 Lv2AtomRingBuffer fAtomBufferWorkerIn;
7383 Lv2AtomRingBuffer fAtomBufferWorkerResp;
7384 uint8_t* fAtomBufferUiOutTmpData;
7385 uint8_t* fAtomBufferWorkerInTmpData;
7386
7387 CarlaPluginLV2EventData fEventsIn;
7388 CarlaPluginLV2EventData fEventsOut;
7389 CarlaPluginLV2Options fLv2Options;
7390 CarlaPipeServerLV2 fPipeServer;
7391
7392 std::vector<std::string> fCustomURIDs;
7393
7394 bool fFirstActive; // first process() call after activate()
7395 void* fLastStateChunk;
7396 EngineTimeInfo fLastTimeInfo;
7397
7398 // if plugin provides path parameter, use it as fake "gui"
7399 CarlaString fFilePathURI;
7400
7401 struct Extensions {
7402 const LV2_Options_Interface* options;
7403 const LV2_State_Interface* state;
7404 const LV2_Worker_Interface* worker;
7405 const LV2_Inline_Display_Interface* inlineDisplay;
7406 const LV2_Midnam_Interface* midnam;
7407 const LV2_Programs_Interface* programs;
7408 const LV2UI_Idle_Interface* uiidle;
7409 const LV2UI_Show_Interface* uishow;
7410 const LV2UI_Resize* uiresize;
7411 const LV2_Programs_UI_Interface* uiprograms;
7412
ExtensionsCarlaPluginLV2::Extensions7413 Extensions()
7414 : options(nullptr),
7415 state(nullptr),
7416 worker(nullptr),
7417 inlineDisplay(nullptr),
7418 midnam(nullptr),
7419 programs(nullptr),
7420 uiidle(nullptr),
7421 uishow(nullptr),
7422 uiresize(nullptr),
7423 uiprograms(nullptr) {}
7424
7425 CARLA_DECLARE_NON_COPY_STRUCT(Extensions);
7426 } fExt;
7427
7428 struct UI {
7429 enum Type {
7430 TYPE_NULL = 0,
7431 TYPE_BRIDGE,
7432 TYPE_EMBED,
7433 TYPE_EXTERNAL
7434 };
7435
7436 Type type;
7437 LV2UI_Handle handle;
7438 LV2UI_Widget widget;
7439 const LV2UI_Descriptor* descriptor;
7440 const LV2_RDF_UI* rdfDescriptor;
7441
7442 bool embedded;
7443 bool fileBrowserOpen;
7444 const char* fileNeededForURI;
7445 CarlaPluginUI* window;
7446
UICarlaPluginLV2::UI7447 UI()
7448 : type(TYPE_NULL),
7449 handle(nullptr),
7450 widget(nullptr),
7451 descriptor(nullptr),
7452 rdfDescriptor(nullptr),
7453 embedded(false),
7454 fileBrowserOpen(false),
7455 fileNeededForURI(nullptr),
7456 window(nullptr) {}
7457
~UICarlaPluginLV2::UI7458 ~UI()
7459 {
7460 CARLA_SAFE_ASSERT(handle == nullptr);
7461 CARLA_SAFE_ASSERT(widget == nullptr);
7462 CARLA_SAFE_ASSERT(descriptor == nullptr);
7463 CARLA_SAFE_ASSERT(rdfDescriptor == nullptr);
7464 CARLA_SAFE_ASSERT(! fileBrowserOpen);
7465 CARLA_SAFE_ASSERT(fileNeededForURI == nullptr);
7466 CARLA_SAFE_ASSERT(window == nullptr);
7467 }
7468
7469 CARLA_DECLARE_NON_COPY_STRUCT(UI);
7470 } fUI;
7471
7472 // -------------------------------------------------------------------
7473 // Event Feature
7474
carla_lv2_event_ref(LV2_Event_Callback_Data callback_data,LV2_Event * event)7475 static uint32_t carla_lv2_event_ref(LV2_Event_Callback_Data callback_data, LV2_Event* event)
7476 {
7477 CARLA_SAFE_ASSERT_RETURN(callback_data != nullptr, 0);
7478 CARLA_SAFE_ASSERT_RETURN(event != nullptr, 0);
7479 carla_debug("carla_lv2_event_ref(%p, %p)", callback_data, event);
7480
7481 return 0;
7482 }
7483
carla_lv2_event_unref(LV2_Event_Callback_Data callback_data,LV2_Event * event)7484 static uint32_t carla_lv2_event_unref(LV2_Event_Callback_Data callback_data, LV2_Event* event)
7485 {
7486 CARLA_SAFE_ASSERT_RETURN(callback_data != nullptr, 0);
7487 CARLA_SAFE_ASSERT_RETURN(event != nullptr, 0);
7488 carla_debug("carla_lv2_event_unref(%p, %p)", callback_data, event);
7489
7490 return 0;
7491 }
7492
7493 // -------------------------------------------------------------------
7494 // Logs Feature
7495
carla_lv2_log_printf(LV2_Log_Handle handle,LV2_URID type,const char * fmt,...)7496 static int carla_lv2_log_printf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, ...)
7497 {
7498 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 0);
7499 CARLA_SAFE_ASSERT_RETURN(type != kUridNull, 0);
7500 CARLA_SAFE_ASSERT_RETURN(fmt != nullptr, 0);
7501
7502 #ifndef DEBUG
7503 if (type == kUridLogTrace)
7504 return 0;
7505 #endif
7506
7507 va_list args;
7508 va_start(args, fmt);
7509 const int ret(carla_lv2_log_vprintf(handle, type, fmt, args));
7510 va_end(args);
7511
7512 return ret;
7513 }
7514
carla_lv2_log_vprintf(LV2_Log_Handle handle,LV2_URID type,const char * fmt,va_list ap)7515 static int carla_lv2_log_vprintf(LV2_Log_Handle handle, LV2_URID type, const char* fmt, va_list ap)
7516 {
7517 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 0);
7518 CARLA_SAFE_ASSERT_RETURN(type != kUridNull, 0);
7519 CARLA_SAFE_ASSERT_RETURN(fmt != nullptr, 0);
7520
7521 int ret = 0;
7522
7523 switch (type)
7524 {
7525 case kUridLogError:
7526 std::fprintf(stderr, "\x1b[31m");
7527 ret = std::vfprintf(stderr, fmt, ap);
7528 std::fprintf(stderr, "\x1b[0m");
7529 break;
7530
7531 case kUridLogNote:
7532 ret = std::vfprintf(stdout, fmt, ap);
7533 break;
7534
7535 case kUridLogTrace:
7536 #ifdef DEBUG
7537 std::fprintf(stdout, "\x1b[30;1m");
7538 ret = std::vfprintf(stdout, fmt, ap);
7539 std::fprintf(stdout, "\x1b[0m");
7540 #endif
7541 break;
7542
7543 case kUridLogWarning:
7544 ret = std::vfprintf(stderr, fmt, ap);
7545 break;
7546
7547 default:
7548 break;
7549 }
7550
7551 return ret;
7552 }
7553
7554 // -------------------------------------------------------------------
7555 // Programs Feature
7556
carla_lv2_program_changed(LV2_Programs_Handle handle,int32_t index)7557 static void carla_lv2_program_changed(LV2_Programs_Handle handle, int32_t index)
7558 {
7559 CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
7560 carla_debug("carla_lv2_program_changed(%p, %i)", handle, index);
7561
7562 ((CarlaPluginLV2*)handle)->handleProgramChanged(index);
7563 }
7564
7565 // -------------------------------------------------------------------
7566 // Resize Port Feature
7567
carla_lv2_resize_port(LV2_Resize_Port_Feature_Data data,uint32_t index,size_t size)7568 static LV2_Resize_Port_Status carla_lv2_resize_port(LV2_Resize_Port_Feature_Data data, uint32_t index, size_t size)
7569 {
7570 CARLA_SAFE_ASSERT_RETURN(data != nullptr, LV2_RESIZE_PORT_ERR_UNKNOWN);
7571 carla_debug("carla_lv2_program_changed(%p, %i, " P_SIZE ")", data, index, size);
7572
7573 return ((CarlaPluginLV2*)data)->handleResizePort(index, size);
7574 }
7575
7576 // -------------------------------------------------------------------
7577 // State Feature
7578
carla_lv2_state_free_path(LV2_State_Free_Path_Handle handle,char * const path)7579 static void carla_lv2_state_free_path(LV2_State_Free_Path_Handle handle, char* const path)
7580 {
7581 CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
7582 carla_debug("carla_lv2_state_free_path(%p, \"%s\")", handle, path);
7583
7584 std::free(path);
7585 }
7586
carla_lv2_state_make_path_real(LV2_State_Make_Path_Handle handle,const char * const path)7587 static char* carla_lv2_state_make_path_real(LV2_State_Make_Path_Handle handle, const char* const path)
7588 {
7589 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
7590 CARLA_SAFE_ASSERT_RETURN(path != nullptr && path[0] != '\0', nullptr);
7591 carla_debug("carla_lv2_state_make_path_real(%p, \"%s\")", handle, path);
7592
7593 const File file(((CarlaPluginLV2*)handle)->handleStateMapToAbsolutePath(true, false, false, path));
7594 return file.isNotNull() ? strdup(file.getFullPathName().toRawUTF8()) : nullptr;
7595 }
7596
carla_lv2_state_make_path_tmp(LV2_State_Make_Path_Handle handle,const char * const path)7597 static char* carla_lv2_state_make_path_tmp(LV2_State_Make_Path_Handle handle, const char* const path)
7598 {
7599 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
7600 CARLA_SAFE_ASSERT_RETURN(path != nullptr && path[0] != '\0', nullptr);
7601 carla_debug("carla_lv2_state_make_path_tmp(%p, \"%s\")", handle, path);
7602
7603 const File file(((CarlaPluginLV2*)handle)->handleStateMapToAbsolutePath(true, false, true, path));
7604 return file.isNotNull() ? strdup(file.getFullPathName().toRawUTF8()) : nullptr;
7605 }
7606
carla_lv2_state_map_to_abstract_path_real(LV2_State_Map_Path_Handle handle,const char * const absolute_path)7607 static char* carla_lv2_state_map_to_abstract_path_real(LV2_State_Map_Path_Handle handle, const char* const absolute_path)
7608 {
7609 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
7610 CARLA_SAFE_ASSERT_RETURN(absolute_path != nullptr && absolute_path[0] != '\0', nullptr);
7611 carla_debug("carla_lv2_state_map_to_abstract_path_real(%p, \"%s\")", handle, absolute_path);
7612
7613 return ((CarlaPluginLV2*)handle)->handleStateMapToAbstractPath(false, absolute_path);
7614 }
7615
carla_lv2_state_map_to_abstract_path_tmp(LV2_State_Map_Path_Handle handle,const char * const absolute_path)7616 static char* carla_lv2_state_map_to_abstract_path_tmp(LV2_State_Map_Path_Handle handle, const char* const absolute_path)
7617 {
7618 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
7619 CARLA_SAFE_ASSERT_RETURN(absolute_path != nullptr && absolute_path[0] != '\0', nullptr);
7620 carla_debug("carla_lv2_state_map_to_abstract_path_tmp(%p, \"%s\")", handle, absolute_path);
7621
7622 return ((CarlaPluginLV2*)handle)->handleStateMapToAbstractPath(true, absolute_path);
7623 }
7624
carla_lv2_state_map_to_absolute_path_real(LV2_State_Map_Path_Handle handle,const char * const abstract_path)7625 static char* carla_lv2_state_map_to_absolute_path_real(LV2_State_Map_Path_Handle handle, const char* const abstract_path)
7626 {
7627 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
7628 CARLA_SAFE_ASSERT_RETURN(abstract_path != nullptr && abstract_path[0] != '\0', nullptr);
7629 carla_debug("carla_lv2_state_map_to_absolute_path_real(%p, \"%s\")", handle, abstract_path);
7630
7631 const File file(((CarlaPluginLV2*)handle)->handleStateMapToAbsolutePath(true, true, false, abstract_path));
7632 return file.isNotNull() ? strdup(file.getFullPathName().toRawUTF8()) : nullptr;
7633 }
7634
carla_lv2_state_map_to_absolute_path_tmp(LV2_State_Map_Path_Handle handle,const char * const abstract_path)7635 static char* carla_lv2_state_map_to_absolute_path_tmp(LV2_State_Map_Path_Handle handle, const char* const abstract_path)
7636 {
7637 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
7638 CARLA_SAFE_ASSERT_RETURN(abstract_path != nullptr && abstract_path[0] != '\0', nullptr);
7639 carla_debug("carla_lv2_state_map_to_absolute_path_tmp(%p, \"%s\")", handle, abstract_path);
7640
7641 const File file(((CarlaPluginLV2*)handle)->handleStateMapToAbsolutePath(true, true, true, abstract_path));
7642 return file.isNotNull() ? strdup(file.getFullPathName().toRawUTF8()) : nullptr;
7643 }
7644
carla_lv2_state_store(LV2_State_Handle handle,uint32_t key,const void * value,size_t size,uint32_t type,uint32_t flags)7645 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)
7646 {
7647 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2_STATE_ERR_UNKNOWN);
7648 carla_debug("carla_lv2_state_store(%p, %i, %p, " P_SIZE ", %i, %i)", handle, key, value, size, type, flags);
7649
7650 return ((CarlaPluginLV2*)handle)->handleStateStore(key, value, size, type, flags);
7651 }
7652
carla_lv2_state_retrieve(LV2_State_Handle handle,uint32_t key,size_t * size,uint32_t * type,uint32_t * flags)7653 static const void* carla_lv2_state_retrieve(LV2_State_Handle handle, uint32_t key, size_t* size, uint32_t* type, uint32_t* flags)
7654 {
7655 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
7656 carla_debug("carla_lv2_state_retrieve(%p, %i, %p, %p, %p)", handle, key, size, type, flags);
7657
7658 return ((CarlaPluginLV2*)handle)->handleStateRetrieve(key, size, type, flags);
7659 }
7660
7661 // -------------------------------------------------------------------
7662 // URI-Map Feature
7663
carla_lv2_uri_to_id(LV2_URI_Map_Callback_Data data,const char * map,const char * uri)7664 static uint32_t carla_lv2_uri_to_id(LV2_URI_Map_Callback_Data data, const char* map, const char* uri)
7665 {
7666 carla_debug("carla_lv2_uri_to_id(%p, \"%s\", \"%s\")", data, map, uri);
7667 return carla_lv2_urid_map((LV2_URID_Map_Handle*)data, uri);
7668
7669 // unused
7670 (void)map;
7671 }
7672
7673 // -------------------------------------------------------------------
7674 // URID Feature
7675
carla_lv2_urid_map(LV2_URID_Map_Handle handle,const char * uri)7676 static LV2_URID carla_lv2_urid_map(LV2_URID_Map_Handle handle, const char* uri)
7677 {
7678 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, kUridNull);
7679 CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', kUridNull);
7680 carla_debug("carla_lv2_urid_map(%p, \"%s\")", handle, uri);
7681
7682 // Atom types
7683 if (std::strcmp(uri, LV2_ATOM__Blank) == 0)
7684 return kUridAtomBlank;
7685 if (std::strcmp(uri, LV2_ATOM__Bool) == 0)
7686 return kUridAtomBool;
7687 if (std::strcmp(uri, LV2_ATOM__Chunk) == 0)
7688 return kUridAtomChunk;
7689 if (std::strcmp(uri, LV2_ATOM__Double) == 0)
7690 return kUridAtomDouble;
7691 if (std::strcmp(uri, LV2_ATOM__Event) == 0)
7692 return kUridAtomEvent;
7693 if (std::strcmp(uri, LV2_ATOM__Float) == 0)
7694 return kUridAtomFloat;
7695 if (std::strcmp(uri, LV2_ATOM__Int) == 0)
7696 return kUridAtomInt;
7697 if (std::strcmp(uri, LV2_ATOM__Literal) == 0)
7698 return kUridAtomLiteral;
7699 if (std::strcmp(uri, LV2_ATOM__Long) == 0)
7700 return kUridAtomLong;
7701 if (std::strcmp(uri, LV2_ATOM__Number) == 0)
7702 return kUridAtomNumber;
7703 if (std::strcmp(uri, LV2_ATOM__Object) == 0)
7704 return kUridAtomObject;
7705 if (std::strcmp(uri, LV2_ATOM__Path) == 0)
7706 return kUridAtomPath;
7707 if (std::strcmp(uri, LV2_ATOM__Property) == 0)
7708 return kUridAtomProperty;
7709 if (std::strcmp(uri, LV2_ATOM__Resource) == 0)
7710 return kUridAtomResource;
7711 if (std::strcmp(uri, LV2_ATOM__Sequence) == 0)
7712 return kUridAtomSequence;
7713 if (std::strcmp(uri, LV2_ATOM__Sound) == 0)
7714 return kUridAtomSound;
7715 if (std::strcmp(uri, LV2_ATOM__String) == 0)
7716 return kUridAtomString;
7717 if (std::strcmp(uri, LV2_ATOM__Tuple) == 0)
7718 return kUridAtomTuple;
7719 if (std::strcmp(uri, LV2_ATOM__URI) == 0)
7720 return kUridAtomURI;
7721 if (std::strcmp(uri, LV2_ATOM__URID) == 0)
7722 return kUridAtomURID;
7723 if (std::strcmp(uri, LV2_ATOM__Vector) == 0)
7724 return kUridAtomVector;
7725 if (std::strcmp(uri, LV2_ATOM__atomTransfer) == 0)
7726 return kUridAtomTransferAtom;
7727 if (std::strcmp(uri, LV2_ATOM__eventTransfer) == 0)
7728 return kUridAtomTransferEvent;
7729
7730 // BufSize types
7731 if (std::strcmp(uri, LV2_BUF_SIZE__maxBlockLength) == 0)
7732 return kUridBufMaxLength;
7733 if (std::strcmp(uri, LV2_BUF_SIZE__minBlockLength) == 0)
7734 return kUridBufMinLength;
7735 if (std::strcmp(uri, LV2_BUF_SIZE__nominalBlockLength) == 0)
7736 return kUridBufNominalLength;
7737 if (std::strcmp(uri, LV2_BUF_SIZE__sequenceSize) == 0)
7738 return kUridBufSequenceSize;
7739
7740 // Log types
7741 if (std::strcmp(uri, LV2_LOG__Error) == 0)
7742 return kUridLogError;
7743 if (std::strcmp(uri, LV2_LOG__Note) == 0)
7744 return kUridLogNote;
7745 if (std::strcmp(uri, LV2_LOG__Trace) == 0)
7746 return kUridLogTrace;
7747 if (std::strcmp(uri, LV2_LOG__Warning) == 0)
7748 return kUridLogWarning;
7749
7750 // Patch types
7751 if (std::strcmp(uri, LV2_PATCH__Set) == 0)
7752 return kUridPatchSet;
7753 if (std::strcmp(uri, LV2_PATCH__property) == 0)
7754 return kUridPatchProperty;
7755 if (std::strcmp(uri, LV2_PATCH__subject) == 0)
7756 return kUridPatchSubject;
7757 if (std::strcmp(uri, LV2_PATCH__value) == 0)
7758 return kUridPatchValue;
7759
7760 // Time types
7761 if (std::strcmp(uri, LV2_TIME__Position) == 0)
7762 return kUridTimePosition;
7763 if (std::strcmp(uri, LV2_TIME__bar) == 0)
7764 return kUridTimeBar;
7765 if (std::strcmp(uri, LV2_TIME__barBeat) == 0)
7766 return kUridTimeBarBeat;
7767 if (std::strcmp(uri, LV2_TIME__beat) == 0)
7768 return kUridTimeBeat;
7769 if (std::strcmp(uri, LV2_TIME__beatUnit) == 0)
7770 return kUridTimeBeatUnit;
7771 if (std::strcmp(uri, LV2_TIME__beatsPerBar) == 0)
7772 return kUridTimeBeatsPerBar;
7773 if (std::strcmp(uri, LV2_TIME__beatsPerMinute) == 0)
7774 return kUridTimeBeatsPerMinute;
7775 if (std::strcmp(uri, LV2_TIME__frame) == 0)
7776 return kUridTimeFrame;
7777 if (std::strcmp(uri, LV2_TIME__framesPerSecond) == 0)
7778 return kUridTimeFramesPerSecond;
7779 if (std::strcmp(uri, LV2_TIME__speed) == 0)
7780 return kUridTimeSpeed;
7781 if (std::strcmp(uri, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat) == 0)
7782 return kUridTimeTicksPerBeat;
7783
7784 // Others
7785 if (std::strcmp(uri, LV2_MIDI__MidiEvent) == 0)
7786 return kUridMidiEvent;
7787 if (std::strcmp(uri, LV2_PARAMETERS__sampleRate) == 0)
7788 return kUridParamSampleRate;
7789 if (std::strcmp(uri, LV2_UI__backgroundColor) == 0)
7790 return kUridBackgroundColor;
7791 if (std::strcmp(uri, LV2_UI__foregroundColor) == 0)
7792 return kUridForegroundColor;
7793 if (std::strcmp(uri, LV2_UI__scaleFactor) == 0)
7794 return kUridScaleFactor;
7795 if (std::strcmp(uri, LV2_UI__windowTitle) == 0)
7796 return kUridWindowTitle;
7797
7798 // Custom Carla types
7799 if (std::strcmp(uri, URI_CARLA_ATOM_WORKER_IN) == 0)
7800 return kUridCarlaAtomWorkerIn;
7801 if (std::strcmp(uri, URI_CARLA_ATOM_WORKER_RESP) == 0)
7802 return kUridCarlaAtomWorkerResp;
7803 if (std::strcmp(uri, URI_CARLA_PARAMETER_CHANGE) == 0)
7804 return kUridCarlaParameterChange;
7805 if (std::strcmp(uri, LV2_KXSTUDIO_PROPERTIES__TransientWindowId) == 0)
7806 return kUridCarlaTransientWindowId;
7807
7808 // Custom plugin types
7809 return ((CarlaPluginLV2*)handle)->getCustomURID(uri);
7810 }
7811
carla_lv2_urid_unmap(LV2_URID_Map_Handle handle,LV2_URID urid)7812 static const char* carla_lv2_urid_unmap(LV2_URID_Map_Handle handle, LV2_URID urid)
7813 {
7814 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);
7815 CARLA_SAFE_ASSERT_RETURN(urid != kUridNull, nullptr);
7816 carla_debug("carla_lv2_urid_unmap(%p, %i)", handle, urid);
7817
7818 switch (urid)
7819 {
7820 // Atom types
7821 case kUridAtomBlank:
7822 return LV2_ATOM__Blank;
7823 case kUridAtomBool:
7824 return LV2_ATOM__Bool;
7825 case kUridAtomChunk:
7826 return LV2_ATOM__Chunk;
7827 case kUridAtomDouble:
7828 return LV2_ATOM__Double;
7829 case kUridAtomEvent:
7830 return LV2_ATOM__Event;
7831 case kUridAtomFloat:
7832 return LV2_ATOM__Float;
7833 case kUridAtomInt:
7834 return LV2_ATOM__Int;
7835 case kUridAtomLiteral:
7836 return LV2_ATOM__Literal;
7837 case kUridAtomLong:
7838 return LV2_ATOM__Long;
7839 case kUridAtomNumber:
7840 return LV2_ATOM__Number;
7841 case kUridAtomObject:
7842 return LV2_ATOM__Object;
7843 case kUridAtomPath:
7844 return LV2_ATOM__Path;
7845 case kUridAtomProperty:
7846 return LV2_ATOM__Property;
7847 case kUridAtomResource:
7848 return LV2_ATOM__Resource;
7849 case kUridAtomSequence:
7850 return LV2_ATOM__Sequence;
7851 case kUridAtomSound:
7852 return LV2_ATOM__Sound;
7853 case kUridAtomString:
7854 return LV2_ATOM__String;
7855 case kUridAtomTuple:
7856 return LV2_ATOM__Tuple;
7857 case kUridAtomURI:
7858 return LV2_ATOM__URI;
7859 case kUridAtomURID:
7860 return LV2_ATOM__URID;
7861 case kUridAtomVector:
7862 return LV2_ATOM__Vector;
7863 case kUridAtomTransferAtom:
7864 return LV2_ATOM__atomTransfer;
7865 case kUridAtomTransferEvent:
7866 return LV2_ATOM__eventTransfer;
7867
7868 // BufSize types
7869 case kUridBufMaxLength:
7870 return LV2_BUF_SIZE__maxBlockLength;
7871 case kUridBufMinLength:
7872 return LV2_BUF_SIZE__minBlockLength;
7873 case kUridBufNominalLength:
7874 return LV2_BUF_SIZE__nominalBlockLength;
7875 case kUridBufSequenceSize:
7876 return LV2_BUF_SIZE__sequenceSize;
7877
7878 // Log types
7879 case kUridLogError:
7880 return LV2_LOG__Error;
7881 case kUridLogNote:
7882 return LV2_LOG__Note;
7883 case kUridLogTrace:
7884 return LV2_LOG__Trace;
7885 case kUridLogWarning:
7886 return LV2_LOG__Warning;
7887
7888 // Patch types
7889 case kUridPatchSet:
7890 return LV2_PATCH__Set;
7891 case kUridPatchProperty:
7892 return LV2_PATCH__property;
7893 case kUridPatchSubject:
7894 return LV2_PATCH__subject;
7895 case kUridPatchValue:
7896 return LV2_PATCH__value;
7897
7898 // Time types
7899 case kUridTimePosition:
7900 return LV2_TIME__Position;
7901 case kUridTimeBar:
7902 return LV2_TIME__bar;
7903 case kUridTimeBarBeat:
7904 return LV2_TIME__barBeat;
7905 case kUridTimeBeat:
7906 return LV2_TIME__beat;
7907 case kUridTimeBeatUnit:
7908 return LV2_TIME__beatUnit;
7909 case kUridTimeBeatsPerBar:
7910 return LV2_TIME__beatsPerBar;
7911 case kUridTimeBeatsPerMinute:
7912 return LV2_TIME__beatsPerMinute;
7913 case kUridTimeFrame:
7914 return LV2_TIME__frame;
7915 case kUridTimeFramesPerSecond:
7916 return LV2_TIME__framesPerSecond;
7917 case kUridTimeSpeed:
7918 return LV2_TIME__speed;
7919 case kUridTimeTicksPerBeat:
7920 return LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat;
7921
7922 // Others
7923 case kUridMidiEvent:
7924 return LV2_MIDI__MidiEvent;
7925 case kUridParamSampleRate:
7926 return LV2_PARAMETERS__sampleRate;
7927 case kUridBackgroundColor:
7928 return LV2_UI__backgroundColor;
7929 case kUridForegroundColor:
7930 return LV2_UI__foregroundColor;
7931 case kUridScaleFactor:
7932 return LV2_UI__scaleFactor;
7933 case kUridWindowTitle:
7934 return LV2_UI__windowTitle;
7935
7936 // Custom Carla types
7937 case kUridCarlaAtomWorkerIn:
7938 return URI_CARLA_ATOM_WORKER_IN;
7939 case kUridCarlaAtomWorkerResp:
7940 return URI_CARLA_ATOM_WORKER_RESP;
7941 case kUridCarlaParameterChange:
7942 return URI_CARLA_PARAMETER_CHANGE;
7943 case kUridCarlaTransientWindowId:
7944 return LV2_KXSTUDIO_PROPERTIES__TransientWindowId;
7945 }
7946
7947 // Custom plugin types
7948 return ((CarlaPluginLV2*)handle)->getCustomURIDString(urid);
7949 }
7950
7951 // -------------------------------------------------------------------
7952 // Worker Feature
7953
carla_lv2_worker_schedule(LV2_Worker_Schedule_Handle handle,uint32_t size,const void * data)7954 static LV2_Worker_Status carla_lv2_worker_schedule(LV2_Worker_Schedule_Handle handle, uint32_t size, const void* data)
7955 {
7956 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2_WORKER_ERR_UNKNOWN);
7957 carla_debug("carla_lv2_worker_schedule(%p, %i, %p)", handle, size, data);
7958
7959 return ((CarlaPluginLV2*)handle)->handleWorkerSchedule(size, data);
7960 }
7961
carla_lv2_worker_respond(LV2_Worker_Respond_Handle handle,uint32_t size,const void * data)7962 static LV2_Worker_Status carla_lv2_worker_respond(LV2_Worker_Respond_Handle handle, uint32_t size, const void* data)
7963 {
7964 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2_WORKER_ERR_UNKNOWN);
7965 carla_debug("carla_lv2_worker_respond(%p, %i, %p)", handle, size, data);
7966
7967 return ((CarlaPluginLV2*)handle)->handleWorkerRespond(size, data);
7968 }
7969
7970 // -------------------------------------------------------------------
7971 // Inline Display Feature
7972
carla_lv2_inline_display_queue_draw(LV2_Inline_Display_Handle handle)7973 static void carla_lv2_inline_display_queue_draw(LV2_Inline_Display_Handle handle)
7974 {
7975 CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
7976 // carla_debug("carla_lv2_inline_display_queue_draw(%p)", handle);
7977
7978 ((CarlaPluginLV2*)handle)->handleInlineDisplayQueueRedraw();
7979 }
7980
7981 // -------------------------------------------------------------------
7982 // Midnam Feature
7983
carla_lv2_midnam_update(LV2_Midnam_Handle handle)7984 static void carla_lv2_midnam_update(LV2_Midnam_Handle handle)
7985 {
7986 CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
7987 carla_stdout("carla_lv2_midnam_update(%p)", handle);
7988
7989 ((CarlaPluginLV2*)handle)->handleMidnamUpdate();
7990 }
7991
7992 // -------------------------------------------------------------------
7993 // External UI Feature
7994
carla_lv2_external_ui_closed(LV2UI_Controller controller)7995 static void carla_lv2_external_ui_closed(LV2UI_Controller controller)
7996 {
7997 CARLA_SAFE_ASSERT_RETURN(controller != nullptr,);
7998 carla_debug("carla_lv2_external_ui_closed(%p)", controller);
7999
8000 ((CarlaPluginLV2*)controller)->handleExternalUIClosed();
8001 }
8002
8003 // -------------------------------------------------------------------
8004 // UI Port-Map Feature
8005
carla_lv2_ui_port_map(LV2UI_Feature_Handle handle,const char * symbol)8006 static uint32_t carla_lv2_ui_port_map(LV2UI_Feature_Handle handle, const char* symbol)
8007 {
8008 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2UI_INVALID_PORT_INDEX);
8009 carla_debug("carla_lv2_ui_port_map(%p, \"%s\")", handle, symbol);
8010
8011 return ((CarlaPluginLV2*)handle)->handleUIPortMap(symbol);
8012 }
8013
8014 // ----------------------------------------------------------------------------------------------------------------
8015 // UI Request Parameter Feature
8016
carla_lv2_ui_request_value(LV2UI_Feature_Handle handle,LV2_URID key,LV2_URID type,const LV2_Feature * const * features)8017 static LV2UI_Request_Value_Status carla_lv2_ui_request_value(LV2UI_Feature_Handle handle,
8018 LV2_URID key,
8019 LV2_URID type,
8020 const LV2_Feature* const* features)
8021 {
8022 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, LV2UI_REQUEST_VALUE_ERR_UNKNOWN);
8023 carla_debug("carla_lv2_ui_request_value(%p, %u, %u, %p)", handle, key, type, features);
8024
8025 return ((CarlaPluginLV2*)handle)->handleUIRequestValue(key, type, features);
8026 }
8027
8028 // -------------------------------------------------------------------
8029 // UI Resize Feature
8030
carla_lv2_ui_resize(LV2UI_Feature_Handle handle,int width,int height)8031 static int carla_lv2_ui_resize(LV2UI_Feature_Handle handle, int width, int height)
8032 {
8033 CARLA_SAFE_ASSERT_RETURN(handle != nullptr, 1);
8034 carla_debug("carla_lv2_ui_resize(%p, %i, %i)", handle, width, height);
8035
8036 return ((CarlaPluginLV2*)handle)->handleUIResize(width, height);
8037 }
8038
8039 // -------------------------------------------------------------------
8040 // UI Touch Feature
8041
carla_lv2_ui_touch(LV2UI_Feature_Handle handle,uint32_t port_index,bool touch)8042 static void carla_lv2_ui_touch(LV2UI_Feature_Handle handle, uint32_t port_index, bool touch)
8043 {
8044 CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);
8045 carla_debug("carla_lv2_ui_touch(%p, %u, %s)", handle, port_index, bool2str(touch));
8046
8047 ((CarlaPluginLV2*)handle)->handleUITouch(port_index, touch);
8048 }
8049
8050 // -------------------------------------------------------------------
8051 // UI Extension
8052
carla_lv2_ui_write_function(LV2UI_Controller controller,uint32_t port_index,uint32_t buffer_size,uint32_t format,const void * buffer)8053 static void carla_lv2_ui_write_function(LV2UI_Controller controller, uint32_t port_index, uint32_t buffer_size, uint32_t format, const void* buffer)
8054 {
8055 CARLA_SAFE_ASSERT_RETURN(controller != nullptr,);
8056 carla_debug("carla_lv2_ui_write_function(%p, %i, %i, %i, %p)", controller, port_index, buffer_size, format, buffer);
8057
8058 ((CarlaPluginLV2*)controller)->handleUIWrite(port_index, buffer_size, format, buffer);
8059 }
8060
8061 // -------------------------------------------------------------------
8062 // Lilv State
8063
carla_lilv_set_port_value(const char * port_symbol,void * user_data,const void * value,uint32_t size,uint32_t type)8064 static void carla_lilv_set_port_value(const char* port_symbol, void* user_data, const void* value, uint32_t size, uint32_t type)
8065 {
8066 CARLA_SAFE_ASSERT_RETURN(user_data != nullptr,);
8067 carla_debug("carla_lilv_set_port_value(\"%s\", %p, %p, %i, %i", port_symbol, user_data, value, size, type);
8068
8069 ((CarlaPluginLV2*)user_data)->handleLilvSetPortValue(port_symbol, value, size, type);
8070 }
8071
8072 // -------------------------------------------------------------------
8073
8074 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginLV2)
8075 };
8076
8077 // -------------------------------------------------------------------------------------------------------------------
8078
msgReceived(const char * const msg)8079 bool CarlaPipeServerLV2::msgReceived(const char* const msg) noexcept
8080 {
8081 if (std::strcmp(msg, "exiting") == 0)
8082 {
8083 closePipeServer();
8084 fUiState = UiHide;
8085 return true;
8086 }
8087
8088 if (std::strcmp(msg, "control") == 0)
8089 {
8090 uint32_t index;
8091 float value;
8092
8093 CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true);
8094 CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true);
8095
8096 try {
8097 kPlugin->handleUIWrite(index, sizeof(float), kUridNull, &value);
8098 } CARLA_SAFE_EXCEPTION("magReceived control");
8099
8100 return true;
8101 }
8102
8103 if (std::strcmp(msg, "pcontrol") == 0)
8104 {
8105 const char* uri;
8106 float value;
8107
8108 CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(uri, true), true);
8109 CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true);
8110
8111 try {
8112 kPlugin->handleUIBridgeParameter(uri, value);
8113 } CARLA_SAFE_EXCEPTION("magReceived pcontrol");
8114
8115 return true;
8116 }
8117
8118 if (std::strcmp(msg, "atom") == 0)
8119 {
8120 uint32_t index, atomTotalSize, base64Size;
8121 const char* base64atom;
8122
8123 CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true);
8124 CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(atomTotalSize), true);
8125 CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(base64Size), true);
8126 CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(base64atom, false, base64Size), true);
8127
8128 std::vector<uint8_t> chunk(carla_getChunkFromBase64String(base64atom));
8129 CARLA_SAFE_ASSERT_UINT2_RETURN(chunk.size() >= sizeof(LV2_Atom), chunk.size(), sizeof(LV2_Atom), true);
8130
8131 #ifdef CARLA_PROPER_CPP11_SUPPORT
8132 const LV2_Atom* const atom((const LV2_Atom*)chunk.data());
8133 #else
8134 const LV2_Atom* const atom((const LV2_Atom*)&chunk.front());
8135 #endif
8136 CARLA_SAFE_ASSERT_RETURN(lv2_atom_total_size(atom) == chunk.size(), true);
8137
8138 try {
8139 kPlugin->handleUIWrite(index, lv2_atom_total_size(atom), kUridAtomTransferEvent, atom);
8140 } CARLA_SAFE_EXCEPTION("magReceived atom");
8141
8142 return true;
8143 }
8144
8145 if (std::strcmp(msg, "program") == 0)
8146 {
8147 uint32_t index;
8148
8149 CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true);
8150
8151 try {
8152 kPlugin->setMidiProgram(static_cast<int32_t>(index), false, true, true, false);
8153 } CARLA_SAFE_EXCEPTION("msgReceived program");
8154
8155 return true;
8156 }
8157
8158 if (std::strcmp(msg, "urid") == 0)
8159 {
8160 uint32_t urid, size;
8161 const char* uri;
8162
8163 CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(urid), true);
8164 CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(size), true);
8165 CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(uri, false, size), true);
8166
8167 if (urid != 0)
8168 {
8169 try {
8170 kPlugin->handleUridMap(urid, uri);
8171 } CARLA_SAFE_EXCEPTION("msgReceived urid");
8172 }
8173
8174 return true;
8175 }
8176
8177 if (std::strcmp(msg, "reloadprograms") == 0)
8178 {
8179 int32_t index;
8180
8181 CARLA_SAFE_ASSERT_RETURN(readNextLineAsInt(index), true);
8182
8183 try {
8184 kPlugin->handleProgramChanged(index);
8185 } CARLA_SAFE_EXCEPTION("handleProgramChanged");
8186
8187 return true;
8188 }
8189
8190 if (std::strcmp(msg, "requestvalue") == 0)
8191 {
8192 uint32_t key, type;
8193
8194 CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(key), true);
8195 CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(type), true);
8196
8197 if (key != 0)
8198 {
8199 try {
8200 kPlugin->handleUIRequestValue(key, type, nullptr);
8201 } CARLA_SAFE_EXCEPTION("msgReceived requestvalue");
8202 }
8203
8204 return true;
8205 }
8206
8207 return false;
8208 }
8209
8210 // -------------------------------------------------------------------------------------------------------------------
8211
newLV2(const Initializer & init)8212 CarlaPluginPtr CarlaPlugin::newLV2(const Initializer& init)
8213 {
8214 carla_debug("CarlaPlugin::newLV2({%p, \"%s\", \"%s\"})", init.engine, init.name, init.label);
8215
8216 std::shared_ptr<CarlaPluginLV2> plugin(new CarlaPluginLV2(init.engine, init.id));
8217
8218 const char* needsArchBridge = nullptr;
8219 if (plugin->init(plugin, init.name, init.label, init.options, needsArchBridge))
8220 return plugin;
8221
8222 if (needsArchBridge != nullptr)
8223 {
8224 CarlaString bridgeBinary(init.engine->getOptions().binaryDir);
8225 bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-native";
8226
8227 return CarlaPlugin::newBridge(init, BINARY_NATIVE, PLUGIN_LV2, needsArchBridge, bridgeBinary);
8228 }
8229
8230 return nullptr;
8231 }
8232
8233 // used in CarlaStandalone.cpp
8234 const void* carla_render_inline_display_lv2(const CarlaPluginPtr& plugin, uint32_t width, uint32_t height);
8235
carla_render_inline_display_lv2(const CarlaPluginPtr & plugin,uint32_t width,uint32_t height)8236 const void* carla_render_inline_display_lv2(const CarlaPluginPtr& plugin, uint32_t width, uint32_t height)
8237 {
8238 const std::shared_ptr<CarlaPluginLV2>& lv2Plugin((const std::shared_ptr<CarlaPluginLV2>&)plugin);
8239
8240 return lv2Plugin->renderInlineDisplay(width, height);
8241 }
8242
8243 // -------------------------------------------------------------------------------------------------------------------
8244
8245 CARLA_BACKEND_END_NAMESPACE
8246