26#if JUCE_PLUGINHOST_LV2
40template <
typename Struct,
typename Value>
41auto with (Struct
s, Value Struct::* member, Value
value)
noexcept
43 s.*member = std::move (
value);
50static const LV2_Atom* convertToAtomPtr (
const void* ptr,
size_t size)
52 if (
size <
sizeof (LV2_Atom))
58 const auto header = readUnaligned<LV2_Atom> (ptr);
60 if (
size < header.size + sizeof (LV2_Atom))
67 return reinterpret_cast<const LV2_Atom*
> (
ptr);
76 constexpr SimpleSpan (T* beginIn, T* endIn) :
b (beginIn),
e (endIn) {}
78 constexpr auto begin()
const {
return b; }
79 constexpr auto end()
const {
return e; }
82 constexpr auto& operator[] (
size_t index) {
return b[index]; }
85 constexpr auto size()
const {
return (
size_t) (
e -
b); }
93constexpr auto makeSimpleSpan (T*
b, T*
e) {
return SimpleSpan<T> {
b,
e }; }
96constexpr auto makeSimpleSpan (R&
r) {
return makeSimpleSpan (
r.data(),
r.data() +
r.size()); }
98struct PhysicalResizeListener
100 virtual ~PhysicalResizeListener() =
default;
101 virtual void viewRequestedResizeInPhysicalPixels (
int width,
int height) = 0;
104struct LogicalResizeListener
106 virtual ~LogicalResizeListener() =
default;
107 virtual void viewRequestedResizeInLogicalPixels (
int width,
int height) = 0;
111class WindowSizeChangeDetector
114 WindowSizeChangeDetector()
115 : hook (SetWindowsHookEx (WH_CALLWNDPROC,
121 ~WindowSizeChangeDetector()
noexcept
123 UnhookWindowsHookEx (hook);
126 static void addListener (
HWND hwnd, PhysicalResizeListener& listener)
128 getActiveEditors().emplace (
hwnd, &listener);
131 static void removeListener (
HWND hwnd)
133 getActiveEditors().erase (
hwnd);
137 static std::map<HWND, PhysicalResizeListener*>& getActiveEditors()
139 static std::map<HWND, PhysicalResizeListener*> map;
143 static void processMessage (
int nCode,
const CWPSTRUCT*
info)
145 if (nCode < 0 ||
info ==
nullptr)
148 constexpr UINT events[] { WM_SIZING,
WM_SIZE, WM_WINDOWPOSCHANGING, WM_WINDOWPOSCHANGED };
150 if (std::find (std::begin (events), std::end (events),
info->message) == std::end (events))
153 auto& map = getActiveEditors();
154 auto iter = map.find (
info->hwnd);
156 if (iter == map.end())
161 iter->second->viewRequestedResizeInPhysicalPixels (rect.
right - rect.
left, rect.
bottom - rect.
top);
166 processMessage (nCode, lv2_shared::wordCast<CWPSTRUCT*> (lParam));
167 return CallNextHookEx ({}, nCode, wParam, lParam);
173class WindowSizeChangeListener
176 WindowSizeChangeListener (
HWND hwndIn, PhysicalResizeListener&
l)
179 detector->addListener (
hwnd,
l);
182 ~WindowSizeChangeListener()
184 detector->removeListener (
hwnd);
188 SharedResourcePointer<WindowSizeChangeDetector> detector;
200using OwningNode = std::unique_ptr<LilvNode, FreeLilvNode>;
202template <
typename Traits>
203class TypesafeLilvNode
206 template <
typename... Ts>
207 TypesafeLilvNode (Ts&&... ts)
208 : node (Traits::construct (std::forward<Ts> (ts)...)) {}
210 bool equals (
const TypesafeLilvNode& other)
const noexcept
217 auto getTyped()
const noexcept -> decltype (Traits::access (
nullptr))
219 return Traits::access (node.get());
222 static TypesafeLilvNode claim (
LilvNode* node)
224 return TypesafeLilvNode { node };
233 explicit TypesafeLilvNode (
LilvNode* ptr)
236 jassert (ptr ==
nullptr || Traits::verify (node.get()));
244struct UriConstructorTrait
260struct StringConstructorTrait {
static constexpr auto construct =
lilv_new_string;
264using NodeUri = TypesafeLilvNode<UriConstructorTrait>;
265using NodeString = TypesafeLilvNode<StringConstructorTrait>;
274 #define X(str) const NodeUri m##str { world, str };
294template <
typename Ptr,
typename Free>
295struct OwningPtrTraits
297 using type = std::unique_ptr<Ptr, Free>;
298 static const Ptr*
get (
const type&
t)
noexcept {
return t.get(); }
301template <
typename Ptr>
302struct NonOwningPtrTraits
304 using type =
const Ptr*;
305 static const Ptr*
get (
const type&
t)
noexcept {
return t; }
308struct PluginsIteratorTraits
318using PluginsIterator = lv2_shared::Iterator<PluginsIteratorTraits>;
320struct PluginClassesIteratorTraits
330using PluginClassesIterator = lv2_shared::Iterator<PluginClassesIteratorTraits>;
332struct NodesIteratorTraits
342using NodesIterator = lv2_shared::Iterator<NodesIteratorTraits>;
344struct ScalePointsIteratorTraits
354using ScalePointsIterator = lv2_shared::Iterator<ScalePointsIteratorTraits>;
356struct UisIteratorTraits
358 using Container =
const LilvUIs*;
366using UisIterator = lv2_shared::Iterator<UisIteratorTraits>;
368template <
typename PtrTraits>
372 using type =
typename PtrTraits::type;
374 template <
typename Ptr>
375 explicit NodesImpl (Ptr* ptr)
378 explicit NodesImpl (
type ptr)
385 return nodes ==
nullptr ? NodesIterator{}
386 : NodesIterator { PtrTraits::get (nodes) };
400using OwningNodes = NodesImpl<OwningPtrTraits<LilvNodes, NodesFree>>;
401using NonOwningNodes = NodesImpl<NonOwningPtrTraits<LilvNodes>>;
411 return points ==
nullptr ? ScalePointsIterator{}
412 : ScalePointsIterator { points };
436 float defaultValue,
min,
max;
459 : plugin (pluginIn),
port (portIn) {}
461 Direction getDirection (
const UsefulUris&
uris)
const noexcept
463 if (isA (
uris.mLV2_CORE__InputPort))
464 return Direction::input;
466 if (isA (
uris.mLV2_CORE__OutputPort))
467 return Direction::output;
469 return Direction::unknown;
472 Kind getKind (
const UsefulUris&
uris)
const noexcept
474 if (isA (
uris.mLV2_CORE__ControlPort))
475 return Kind::control;
477 if (isA (
uris.mLV2_CORE__AudioPort))
480 if (isA (
uris.mLV2_CORE__CVPort))
483 if (isA (
uris.mLV2_ATOM__AtomPort))
486 return Kind::unknown;
489 OwningNode
get (
const LilvNode* predicate)
const noexcept
491 return OwningNode {
lilv_port_get (plugin, port, predicate) };
519 bool hasProperty (
const NodeUri&
uri)
const noexcept
526 static float getFloatValue (
const LilvNode* node,
float fallback)
534 bool supportsEvent (
const LilvNode* node)
const noexcept
547 const OwningNode defOwner { def };
548 const OwningNode minOwner {
min };
549 const OwningNode maxOwner {
max };
551 return { getFloatValue (def, 0.0f),
552 getFloatValue (
min, 0.0f),
553 getFloatValue (
max, 1.0f) };
559 bool isA (
const NodeUri&
uri)
const noexcept
585 Port getPortByIndex (
uint32_t index)
const noexcept
590 Port getPortByDesignation (
const LilvNode* portClass,
const LilvNode* designation)
const noexcept
605 bool hasExtensionData (
const NodeUri&
uri)
const noexcept
610 bool hasFeature (
const NodeUri&
uri)
const noexcept
615 template <
typename... Classes>
616 uint32_t getNumPortsOfClass (
const Classes&... classes)
const noexcept
638 SymbolMap() =
default;
640 SymbolMap (std::initializer_list<const char*>
uris)
642 for (
const auto* str :
uris)
648 const auto comparator = [
this] (
size_t index,
const String& str)
650 return strings[index] < str;
654 const auto it = std::lower_bound (indices.cbegin(), indices.cend(), uriString, comparator);
656 if (it != indices.cend() && strings[*it] == uriString)
657 return static_cast<LV2_URID> (*it + 1);
659 const auto index = strings.size();
660 indices.insert (it, index);
661 strings.push_back (uriString);
662 return static_cast<LV2_URID> (index + 1);
667 const auto index = urid - 1;
668 return index < strings.size() ? strings[index].toRawUTF8()
674 return static_cast<SymbolMap*
> (handle)->map (
uri);
679 return static_cast<SymbolMap*
> (handle)->
unmap (urid);
682 LV2_URID_Map getMapFeature() {
return {
this, mapUri }; }
686 std::vector<String> strings;
687 std::vector<size_t> indices;
694 explicit UsefulUrids (SymbolMap&
m) : symap (
m) {}
698 #define X(token) const LV2_URID m##token = symap.map (token);
737 explicit Log (
const UsefulUrids*
u) : urids (
u) {}
739 LV2_Log_Log* getLogFeature() {
return &logFeature; }
746 return std::vfprintf (stderr,
fmt, ap);
754 return static_cast<const Log*
> (handle)->vprintfCallback (
type,
fmt, ap);
760 va_start (list,
fmt);
766 const UsefulUrids* urids =
nullptr;
767 LV2_Log_Log logFeature {
this, printfCallback, vprintfCallback };
774 explicit Features (std::vector<LV2_Feature>&&
f)
775 : features (std::
move (
f)) {}
777 static std::vector<String> getUris (
const std::vector<LV2_Feature>& features)
779 std::vector<String>
result;
780 result.reserve (features.size());
782 for (
const auto& feature : features)
788 std::vector<LV2_Feature> features;
789 std::vector<const LV2_Feature*>
pointers = makeNullTerminatedArray();
792 std::vector<const LV2_Feature*> makeNullTerminatedArray()
794 std::vector<const LV2_Feature*>
result;
795 result.reserve (features.size() + 1);
797 for (
const auto& feature : features)
798 result.push_back (&feature);
800 result.push_back (
nullptr);
808template <
typename Extension>
809struct OptionalExtension
811 OptionalExtension() =
default;
813 explicit OptionalExtension (Extension extensionIn) : extension (extensionIn), valid (
true) {}
827 using Ptr = std::unique_ptr<LilvInstance, Free>;
828 using GetExtensionData =
const void* (*) (
const char*);
830 Instance (
const Plugin& pluginIn,
double sampleRate,
const LV2_Feature*
const* features)
849 template <
typename Extension>
850 OptionalExtension<Extension> getExtensionData (
const NodeUri&
uri)
const noexcept
852 if (plugin.get() ==
nullptr || ! plugin.hasExtensionData (
uri) || instance.get() ==
nullptr)
860 return instance->lv2_descriptor->extension_data;
863 bool operator== (std::nullptr_t)
const noexcept {
return instance ==
nullptr; }
864 bool operator!= (std::nullptr_t)
const noexcept {
return ! (*
this ==
nullptr); }
873enum class Realtime {
no,
yes };
878 static WorkResponder getDefault() {
return {
nullptr,
nullptr }; }
882 return worker->work_response (handle,
size,
data);
885 bool isValid()
const {
return handle !=
nullptr && worker !=
nullptr; }
891struct WorkerResponseListener
893 virtual ~WorkerResponseListener() =
default;
901 if (realtime == Realtime::yes)
902 return listener.responseGenerated (responder,
size,
data);
904 return responder.processResponse (
size,
data);
911 return static_cast<const RespondHandle*
> (handle)->respond (
size,
data);
914 WorkResponder responder;
915 WorkerResponseListener& listener;
922 static WorkSubmitter getDefault() {
return {
nullptr,
nullptr,
nullptr,
nullptr }; }
935 RespondHandle respondHandle { WorkResponder { handle, worker }, *listener, realtime };
936 return worker->work (handle, RespondHandle::respond, &respondHandle,
size,
data);
939 bool isValid()
const {
return handle !=
nullptr && worker !=
nullptr && listener !=
nullptr && workMutex !=
nullptr; }
943 WorkerResponseListener* listener;
944 CriticalSection* workMutex;
947template <typename Trivial, std::enable_if_t<std::is_trivial<Trivial>::value,
int> = 0>
948static auto toChars (Trivial
value)
950 std::array<char,
sizeof (Trivial)>
result;
955template <
typename Context>
959 static_assert (std::is_trivial<Context>::value,
"Context must be copyable as bytes");
961 explicit WorkQueue (
int size)
966 const auto* bytes =
static_cast<const char*
> (contents);
967 const auto numToWrite =
sizeof (Header) +
size;
969 if (
static_cast<size_t> (fifo.getFreeSpace()) < numToWrite)
972 Header header {
size, context };
973 const auto headerBuffer = toChars (header);
975 const auto scope = fifo.write (
static_cast<int> (numToWrite));
979 scope.forEach ([&] (
int i)
981 data[
static_cast<size_t> (
i)] = index < headerBuffer.size() ? headerBuffer[index]
982 : bytes[index - headerBuffer.size()];
989 Context pop (std::vector<char>& dest)
995 const auto numReady = fifo.getNumReady();
997 if (
static_cast<size_t> (numReady) <
sizeof (Header))
1000 return Context::getDefault();
1003 std::array<char,
sizeof (Header)> headerBuffer;
1007 fifo.read (
sizeof (Header)).forEach ([&] (
int i)
1009 headerBuffer[index++] =
data[
static_cast<size_t> (
i)];
1013 const auto header = readUnaligned<Header> (headerBuffer.data());
1015 jassert (
static_cast<size_t> (fifo.getNumReady()) >= header.size);
1017 dest.resize (header.size);
1021 fifo.read (
static_cast<int> (header.size)).forEach ([&] (
int i)
1023 dest[index++] =
data[
static_cast<size_t> (
i)];
1027 return header.context;
1038 std::vector<char>
data;
1052 const SpinLock::ScopedLockType lock (
mutex);
1053 handles.insert (handle);
1058 const SpinLock::ScopedLockType lock (
mutex);
1059 handles.erase (handle);
1062 template <
typename Fn>
1065 const SpinLock::ScopedLockType lock (
mutex);
1067 if (handles.find (handle) != handles.cend())
1074 std::set<LV2_Handle> handles;
1088class SharedThreadedWorker :
public WorkerResponseListener
1091 ~SharedThreadedWorker()
noexcept override
1101 return registry.ifContains (submitter.handle, [&]
1103 return incoming.push (submitter, size, data);
1109 const void*
data)
override
1111 return registry.ifContains (responder.handle, [&]
1113 return outgoing.push (responder, size, data);
1117 void processResponses()
1121 auto workerResponder = outgoing.pop (
message);
1123 if (!
message.empty() && workerResponder.isValid())
1130 void registerHandle (
LV2_Handle handle) { registry.insert (handle); }
1131 void deregisterHandle (
LV2_Handle handle) { registry.erase (handle); }
1134 static constexpr auto queueSize = 8192;
1135 std::atomic<bool> shouldExit {
false };
1136 WorkQueue<WorkSubmitter> incoming { queueSize };
1137 WorkQueue<WorkResponder> outgoing { queueSize };
1138 std::vector<char>
message = std::vector<char> (queueSize);
1139 std::thread thread { [
this]
1141 std::vector<char>
buffer (queueSize);
1143 while (! shouldExit)
1145 const auto submitter = incoming.pop (buffer);
1147 if (!
buffer.empty() && submitter.isValid())
1150 std::this_thread::sleep_for (std::chrono::milliseconds (1));
1153 HandleRegistry registry;
1160 virtual ~HandleHolder() =
default;
1168 explicit WorkScheduler (HandleHolder& handleHolderIn)
1169 : handleHolder (handleHolderIn) {}
1171 void processResponses() { workerThread->processResponses(); }
1175 void setNonRealtime (
bool nonRealtime) { realtime = ! nonRealtime; }
1177 void registerHandle (
LV2_Handle handle) { workerThread->registerHandle (handle); }
1178 void deregisterHandle (
LV2_Handle handle) { workerThread->deregisterHandle (handle); }
1183 WorkSubmitter submitter { handleHolder.getHandle(),
1184 handleHolder.getWorkerInterface(),
1192 return realtime ? workerThread->schedule (submitter,
size,
data)
1193 : submitter.doWork (Realtime::no,
size,
data);
1200 return static_cast<WorkScheduler*
> (handle)->scheduleWork (
size,
data);
1203 SharedResourcePointer<SharedThreadedWorker> workerThread;
1204 HandleHolder& handleHolder;
1206 CriticalSection workMutex;
1207 bool realtime =
true;
1212struct FeaturesDataListener
1214 virtual ~FeaturesDataListener() =
default;
1221 explicit Resize (FeaturesDataListener&
l)
1224 LV2_Resize_Port_Resize& getFeature() {
return resize; }
1229 return listener.resizeCallback (index,
size);
1234 return static_cast<Resize*
> (
data)->resizeCallback (index,
size);
1237 FeaturesDataListener& listener;
1238 LV2_Resize_Port_Resize resize {
this, resizeCallback };
1244 FeaturesData (HandleHolder& handleHolder,
1245 FeaturesDataListener&
l,
1248 const UsefulUrids*
u)
1251 maxBlockSize (maxBlockSizeIn),
1252 sequenceSize (sequenceSizeIn),
1253 workScheduler (handleHolder)
1260 void setNonRealtime (
bool newValue) { realtime = ! newValue; }
1264 static std::vector<String> getFeatureUris()
1266 return Features::getUris (makeFeatures ({}, {}, {}, {}, {}, {}));
1269 void processResponses() { workScheduler.processResponses(); }
1271 void registerHandle (
LV2_Handle handle) { workScheduler.registerHandle (handle); }
1272 void deregisterHandle (
LV2_Handle handle) { workScheduler.deregisterHandle (handle); }
1275 static std::vector<LV2_Feature> makeFeatures (
LV2_URID_Map* map,
1279 LV2_Resize_Port_Resize* resize,
1301 urids->symap.map (uid),
1307 const UsefulUrids* urids;
1311 const int32_t minBlockSize = 0, maxBlockSize = 0, sequenceSize = 0;
1313 std::vector<LV2_Options_Option> options
1321 WorkScheduler workScheduler;
1325 Features features { makeFeatures (&map,
1328 &workScheduler.getWorkerSchedule(),
1329 &resize.getFeature(),
1330 log.getLogFeature()) };
1332 bool realtime =
true;
1338struct TryLockAndCall
1340 template <
typename Fn>
1341 void operator() (SpinLock&
mutex, Fn&&
fn)
1343 const SpinLock::ScopedTryLockType lock (
mutex);
1345 if (lock.isLocked())
1352 template <
typename Fn>
1353 void operator() (SpinLock&
mutex, Fn&&
fn)
1355 const SpinLock::ScopedLockType lock (
mutex);
1360struct RealtimeReadTrait
1362 using Read = TryLockAndCall;
1363 using Write = LockAndCall;
1366struct RealtimeWriteTrait
1368 using Read = LockAndCall;
1369 using Write = TryLockAndCall;
1378template <
typename Header>
1379struct MessageBufferInterface
1381 virtual ~MessageBufferInterface() =
default;
1382 virtual void pushMessage (Header header,
uint32_t size,
const void* buffer) = 0;
1385template <
typename Header,
typename LockTraits>
1386class Messages :
public MessageBufferInterface<Header>
1388 using Read =
typename LockTraits::Read;
1389 using Write =
typename LockTraits::Write;
1398 Messages() {
data.reserve (initialBufferSize); }
1400 void pushMessage (Header header,
uint32_t size,
const void* buffer)
override
1404 const auto chars = toChars (FullHeader { header,
size });
1405 const auto bufferAsChars =
static_cast<const char*
> (
buffer);
1406 data.insert (
data.end(), chars.begin(), chars.end());
1407 data.insert (
data.end(), bufferAsChars, bufferAsChars +
size);
1411 template <
typename Callback>
1412 void readAllAndClear (Callback&&
callback)
1421 for (
auto ptr =
data.data(); ptr < end;)
1423 const auto header = readUnaligned<FullHeader> (ptr);
1424 callback (header.header, header.size, ptr + sizeof (header));
1425 ptr +=
sizeof (header) + header.size;
1433 static constexpr auto initialBufferSize = 8192;
1435 std::vector<char>
data;
1441class LambdaTimer :
private Timer
1444 explicit LambdaTimer (std::function<
void()>
c) :
callback (
c) {}
1446 ~LambdaTimer()
noexcept override { stopTimer(); }
1448 using Timer::startTimer;
1449 using Timer::startTimerHz;
1450 using Timer::stopTimer;
1453 void timerCallback()
override {
callback(); }
1458struct UiEventListener :
public MessageBufferInterface<MessageHeader>
1460 virtual int idle() = 0;
1463struct UiMessageHeader
1465 UiEventListener* listener;
1466 MessageHeader header;
1469class ProcessorToUi :
public MessageBufferInterface<UiMessageHeader>
1472 ProcessorToUi() { timer.startTimerHz (60); }
1477 void pushMessage (UiMessageHeader header,
uint32_t size,
const void* buffer)
override
1479 processorToUi.pushMessage (header,
size, buffer);
1483 Messages<UiMessageHeader, RealtimeWriteTrait> processorToUi;
1484 std::set<UiEventListener*> activeUis;
1485 LambdaTimer timer { [
this]
1487 for (
auto*
l : activeUis)
1491 processorToUi.readAllAndClear ([&] (
const UiMessageHeader& header,
uint32_t size,
const char*
data)
1493 if (activeUis.find (header.listener) != activeUis.cend())
1494 header.listener->pushMessage (header.header,
size,
data);
1500struct StatefulPortUrids
1502 explicit StatefulPortUrids (SymbolMap& map)
1509 const LV2_URID Float, Double, Int, Long;
1516template <
typename Value>
1520 using iterator =
typename std::vector<Value>:: iterator;
1521 using const_iterator =
typename std::vector<Value>::const_iterator;
1523 template <
typename Other>
1524 const_iterator find (
const Other& other)
const noexcept
1526 const auto it = std::lower_bound (storage.cbegin(), storage.cend(), other);
1528 if (it != storage.cend() && ! (other < *it))
1531 return storage.cend();
1534 void insert (Value&&
value) { insertImpl (std::move (
value)); }
1535 void insert (
const Value&
value) { insertImpl (
value); }
1542 const_iterator cbegin()
const noexcept {
return storage.cbegin(); }
1546 const_iterator cend()
const noexcept {
return storage.cend(); }
1548 auto& operator[] (
size_t index)
const {
return storage[index]; }
1551 template <
typename Arg>
1552 void insertImpl (Arg&&
value)
1554 const auto it = std::lower_bound (storage.cbegin(), storage.cend(),
value);
1556 if (it == storage.cend() ||
value < *it)
1557 storage.insert (it, std::forward<Arg> (
value));
1560 std::vector<Value> storage;
1563struct StoredScalePoint
1568 bool operator< (
const StoredScalePoint& other)
const noexcept {
return value < other.value; }
1571inline bool operator< (
const StoredScalePoint&
a,
float b)
noexcept {
return a.value <
b; }
1572inline bool operator< (
float a,
const StoredScalePoint&
b)
noexcept {
return a <
b.value; }
1576 ParameterInfo() =
default;
1578 ParameterInfo (SafeSortedSet<StoredScalePoint> scalePointsIn,
1579 String identifierIn,
1580 float defaultValueIn,
1586 : scalePoints (std::
move (scalePointsIn)),
1587 identifier (std::
move (identifierIn)),
1588 defaultValue (defaultValueIn),
1591 isToggle (isToggleIn),
1592 isInteger (isIntegerIn),
1596 static SafeSortedSet<StoredScalePoint> getScalePoints (
const Port& port)
1598 SafeSortedSet<StoredScalePoint> scalePoints;
1602 const ScalePoint wrapper {
p };
1603 const auto value = wrapper.getValue();
1604 const auto label = wrapper.getLabel();
1613 static ParameterInfo getInfoForPort (
const UsefulUris&
uris,
const Port& port)
1615 const auto range =
port.getRange();
1617 return { getScalePoints (port),
1622 port.hasProperty (
uris.mLV2_CORE__toggled),
1623 port.hasProperty (
uris.mLV2_CORE__integer),
1624 port.hasProperty (
uris.mLV2_CORE__enumeration) };
1627 SafeSortedSet<StoredScalePoint> scalePoints;
1632 float defaultValue = 0.0f,
min = 0.0f,
max = 1.0f;
1633 bool isToggle =
false, isInteger =
false, isEnum =
false;
1643 Port::Direction direction;
1648 ControlPort (
const PortHeader& headerIn,
const ParameterInfo& infoIn)
1649 : header (headerIn),
info (infoIn) {}
1653 float currentValue =
info.defaultValue;
1666template <
size_t Alignment>
1667class SingleSizeAlignedStorage
1670 SingleSizeAlignedStorage() =
default;
1672 explicit SingleSizeAlignedStorage (
size_t sizeInBytes)
1673 : storage (new char[sizeInBytes + Alignment]),
1674 alignedPointer (storage.
get()),
1675 space (sizeInBytes + Alignment)
1677 alignedPointer = std::align (Alignment, sizeInBytes, alignedPointer, space);
1680 void*
data()
const {
return alignedPointer; }
1681 size_t size()
const {
return space; }
1684 std::unique_ptr<char[]> storage;
1685 void* alignedPointer =
nullptr;
1689template <
size_t Alignment>
1690static SingleSizeAlignedStorage<Alignment> grow (SingleSizeAlignedStorage<Alignment> storage,
size_t size)
1692 if (
size <= storage.size())
1695 SingleSizeAlignedStorage<Alignment> newStorage {
jmax (
size, (storage.size() * 3) / 2) };
1696 std::memcpy (newStorage.data(), storage.data(), storage.size());
1700enum class SupportsTime {
no,
yes };
1705 AtomPort (PortHeader
h,
size_t bytes, SymbolMap& map, SupportsTime supportsTime)
1706 : header (
h), contents (bytes), forge (map.getMapFeature()),
time (supportsTime) {}
1710 void replaceWithChunk()
1713 forge.writeChunk ((
uint32_t) (
size() -
sizeof (LV2_Atom)));
1716 void replaceBufferWithAtom (
const LV2_Atom* atom)
1718 const auto totalSize = atom->
size +
sizeof (LV2_Atom);
1720 if (totalSize <=
size())
1721 std::memcpy (
data(), atom, totalSize);
1726 void beginSequence()
1741 void addAtomToSequence (int64_t timestamp,
const LV2_Atom* atom)
1746 addEventToSequence (timestamp,
1749 reinterpret_cast<const char*
> (atom) + sizeof (LV2_Atom));
1759 void ensureSizeInBytes (
size_t size)
1761 contents = grow (std::move (contents),
size);
1769 lv2_shared::AtomForge& getForge() {
return forge; }
1770 const lv2_shared::AtomForge& getForge()
const {
return forge; }
1772 bool getSupportsTime()
const {
return time == SupportsTime::yes; }
1775 template <
typename This>
1776 static auto data (This&
t) ->
decltype (
t.data())
1782 SingleSizeAlignedStorage<8> contents;
1783 lv2_shared::AtomForge forge;
1785 SupportsTime
time = SupportsTime::no;
1807template <
typename PtrTraits>
1808class PluginClassesImpl
1811 using type =
typename PtrTraits::type;
1813 explicit PluginClassesImpl (
type ptr)
1814 : classes (std::
move (
ptr)) {}
1818 PluginClassesIterator
begin()
const noexcept {
return PluginClassesIterator { PtrTraits::get (classes) }; }
1819 PluginClassesIterator
end()
const noexcept {
return PluginClassesIterator{}; }
1830struct PluginClassesFree
1835using OwningPluginClasses = PluginClassesImpl<OwningPtrTraits<LilvPluginClasses, PluginClassesFree>>;
1836using NonOwningPluginClasses = PluginClassesImpl<NonOwningPtrTraits<LilvPluginClasses>>;
1856 NodeUri newUri (
const char*
uri) {
return NodeUri {
world.get(),
uri }; }
1857 NodeUri newFileUri (
const char* host,
const char* path) {
return NodeUri {
world.get(), host, path }; }
1858 NodeString newString (
const char* str) {
return NodeString {
world.get(), str }; }
1883 std::unique_ptr<LilvWorld, Free>
world;
1889 static constexpr auto sequenceSize = 8192;
1891 template <
typename Callback>
1892 void forEachPort (Callback&&
callback)
const
1894 for (
const auto& port : controlPorts)
1897 for (
const auto& port : cvPorts)
1900 for (
const auto& port : audioPorts)
1903 for (
const auto& port : atomPorts)
1907 auto getControlPorts() {
return makeSimpleSpan (controlPorts); }
1908 auto getControlPorts()
const {
return makeSimpleSpan (controlPorts); }
1909 auto getCvPorts() {
return makeSimpleSpan (cvPorts); }
1910 auto getCvPorts()
const {
return makeSimpleSpan (cvPorts); }
1911 auto getAudioPorts() {
return makeSimpleSpan (audioPorts); }
1912 auto getAudioPorts()
const {
return makeSimpleSpan (audioPorts); }
1913 auto getAtomPorts() {
return makeSimpleSpan (atomPorts); }
1914 auto getAtomPorts()
const {
return makeSimpleSpan (atomPorts); }
1916 static Optional<Ports> getPorts (World&
world,
const UsefulUris&
uris,
const Plugin& plugin, SymbolMap& symap)
1919 bool successful =
true;
1921 const auto numPorts = plugin.getNumPorts();
1926 const auto port = plugin.getPortByIndex (
i);
1935 case Port::Kind::control:
1937 value.controlPorts.push_back ({ header, ParameterInfo::getInfoForPort (
uris, port) });
1941 case Port::Kind::cv:
1942 value.cvPorts.push_back ({ header });
1945 case Port::Kind::audio:
1947 value.audioPorts.push_back ({ header });
1951 case Port::Kind::atom:
1953 const auto supportsTime =
port.supportsEvent (timeNode.get());
1954 value.atomPorts.push_back ({ header,
1955 (size_t) Ports::sequenceSize,
1957 supportsTime ? SupportsTime::yes : SupportsTime::
no });
1961 case Port::Kind::unknown:
1967 for (
auto& atomPort :
value.atomPorts)
1969 const auto port = plugin.getPortByIndex (atomPort.header.index);
1970 const auto minSize =
port.get (
uris.mLV2_RESIZE_PORT__minimumSize.get());
1972 if (minSize !=
nullptr)
1980 std::vector<ControlPort> controlPorts;
1981 std::vector<CVPort> cvPorts;
1982 std::vector<AudioPort> audioPorts;
1983 std::vector<AtomPort> atomPorts;
1986class InstanceWithSupports :
private FeaturesDataListener,
1987 private HandleHolder
1990 InstanceWithSupports (World&
world,
1991 std::unique_ptr<SymbolMap>&& symapIn,
1992 const Plugin& plugin,
1996 : symap (std::
move (symapIn)),
1998 features (*this, *this, initialBufferSize, lv2_host::Ports::sequenceSize, &urids),
1999 instance (plugin, sampleRate, features.getFeatureArray()),
2002 if (instance ==
nullptr)
2005 for (
auto& port :
ports.getControlPorts())
2006 instance.connectPort (
port.header.index, &
port.currentValue);
2008 for (
auto& port :
ports.getAtomPorts())
2009 instance.connectPort (
port.header.index,
port.data());
2011 for (
auto& port :
ports.getCvPorts())
2012 instance.connectPort (
port.header.index,
nullptr);
2014 for (
auto& port :
ports.getAudioPorts())
2015 instance.connectPort (
port.header.index,
nullptr);
2017 features.registerHandle (instance.getHandle());
2020 ~InstanceWithSupports()
override
2022 if (instance !=
nullptr)
2023 features.deregisterHandle (instance.getHandle());
2026 std::unique_ptr<SymbolMap> symap;
2027 const UsefulUrids urids { *symap };
2029 FeaturesData features;
2031 Messages<MessageHeader, RealtimeReadTrait> uiToProcessor;
2032 SharedResourcePointer<ProcessorToUi> processorToUi;
2036 OptionalExtension<LV2_Worker_Interface> workerInterface;
2038 LV2_Handle getHandle()
const override {
return handle; }
2039 const LV2_Worker_Interface* getWorkerInterface()
const override {
return workerInterface.valid ? &workerInterface.extension :
nullptr; }
2043 if (
ports.getAtomPorts().
size() <= index)
2046 auto&
port =
ports.getAtomPorts()[index];
2048 if (
port.header.direction != Port::Direction::output)
2052 instance.connectPort (
port.header.index,
port.data());
2072 explicit PortMap (Ports& ports)
2074 for (
auto& port :
ports.getControlPorts())
2075 symbolToControlPortMap.emplace (
port.header.symbol, &port);
2078 PortState getState (
const String& symbol,
const StatefulPortUrids& urids)
2080 if (
auto* port = getControlPortForSymbol (symbol))
2081 return { &
port->currentValue,
sizeof (float), urids.Float };
2086 return {
nullptr, 0, 0 };
2089 void restoreState (
const String& symbol,
const StatefulPortUrids& urids, PortState ps)
2091 if (
auto* port = getControlPortForSymbol (symbol))
2093 port->currentValue = [&]() ->
float
2095 if (ps.kind == urids.Float)
2096 return getValueFrom<float> (ps.data, ps.size);
2098 if (ps.kind == urids.Double)
2099 return getValueFrom<double> (ps.data, ps.size);
2101 if (ps.kind == urids.Int)
2102 return getValueFrom<int32_t> (ps.data, ps.size);
2104 if (ps.kind == urids.Long)
2105 return getValueFrom<int64_t> (ps.data, ps.size);
2116 template <
typename Value>
2120 return (
float) readUnaligned<Value> (
data);
2123 ControlPort* getControlPortForSymbol (
const String& symbol)
const
2125 const auto iter = symbolToControlPortMap.find (symbol);
2126 return iter != symbolToControlPortMap.cend() ? iter->second :
nullptr;
2129 std::map<String, ControlPort*> symbolToControlPortMap;
2133struct FreeString {
void operator() (
void* ptr)
const noexcept {
lilv_free (ptr); } };
2138 PluginState() =
default;
2145 void restore (InstanceWithSupports& instance, PortMap& portMap)
const
2147 if (state !=
nullptr)
2148 SaveRestoreHandle { instance, portMap }.restore (state.get());
2159 return std::string {
result.get() };
2162 String getLabel()
const
2167 void setLabel (
const String& label)
2172 class SaveRestoreHandle
2175 explicit SaveRestoreHandle (InstanceWithSupports& instanceIn, PortMap& portMap)
2176 : instance (instanceIn.instance.
get()),
2177 features (instanceIn.features.getFeatureArray()),
2178 urids (*instanceIn.symap),
2208 static const void* getPortValue (
const char* portSymbol,
2213 auto& handle = *
static_cast<SaveRestoreHandle*
> (userData);
2215 const auto state = handle.map.getState (portSymbol, handle.urids);
2221 static void setPortValue (
const char* portSymbol,
2227 const auto& handle = *
static_cast<const SaveRestoreHandle*
> (userData);
2228 handle.map.restoreState (portSymbol, handle.urids, { static_cast<const char*> (value), size, type });
2233 const StatefulPortUrids urids;
2243 std::unique_ptr<LilvState, Free> state;
2251struct UiDescriptorLibrary
2255 UiDescriptorLibrary() =
default;
2257 explicit UiDescriptorLibrary (
const String& libraryPath)
2258 : library (std::make_unique<DynamicLibrary> (libraryPath)),
2259 getDescriptor (lv2_shared::wordCast<GetDescriptor> (library->getFunction (
"lv2ui_descriptor"))) {}
2261 std::unique_ptr<DynamicLibrary> library;
2262 GetDescriptor getDescriptor =
nullptr;
2265class UiDescriptorArgs
2271 auto withLibraryPath (String
v)
const noexcept {
return with (&UiDescriptorArgs::libraryPath,
v); }
2272 auto withUiUri (String
v)
const noexcept {
return with (&UiDescriptorArgs::uiUri,
v); }
2275 UiDescriptorArgs with (String UiDescriptorArgs::* member, String
value)
const noexcept
2277 return juce::lv2_host::with (*
this, member, std::move (
value));
2287 UiDescriptor() =
default;
2289 explicit UiDescriptor (
const UiDescriptorArgs& args)
2290 : library (args.libraryPath),
2291 descriptor (extractUiDescriptor (library, args.uiUri.toRawUTF8()))
2298 const void* buffer)
const
2302 if (
auto* lv2Descriptor =
get())
2303 if (
auto*
callback = lv2Descriptor->port_event)
2307 bool hasExtensionData (World&
world,
const char* uid)
const
2311 world.newUri (uid).get());
2314 template <
typename Extension>
2315 OptionalExtension<Extension> getExtensionData (World&
world,
const char* uid)
const
2317 if (! hasExtensionData (
world, uid))
2320 if (
auto* lv2Descriptor =
get())
2321 if (
auto* extension = lv2Descriptor->extension_data)
2322 return OptionalExtension<Extension> (readUnaligned<Extension> (extension (uid)));
2330 static const LV2UI_Descriptor* extractUiDescriptor (
const UiDescriptorLibrary&
lib,
const char* uiUri)
2332 if (
lib.getDescriptor ==
nullptr)
2347 UiDescriptorLibrary library;
2353enum class Update {
no,
yes };
2361class ParameterValuesAndFlags
2364 ParameterValuesAndFlags() =
default;
2366 explicit ParameterValuesAndFlags (
size_t sizeIn)
2368 needsUiUpdate (sizeIn),
2369 needsProcessorUpdate (sizeIn)
2371 std::fill (values.begin(), values.end(), 0.0f);
2376 void set (
size_t index,
float value, Update update)
2379 values[index].store (
value, std::memory_order_relaxed);
2380 needsUiUpdate .set (index, update == Update::yes ? 1 : 0);
2381 needsProcessorUpdate.set (index, update == Update::yes ? 1 : 0);
2384 float get (
size_t index)
const noexcept
2387 return values[index].load (std::memory_order_relaxed);
2390 template <
typename Callback>
2391 void ifProcessorValuesChanged (Callback&&
callback)
2393 ifChanged (needsProcessorUpdate, std::forward<Callback> (
callback));
2396 template <
typename Callback>
2397 void ifUiValuesChanged (Callback&&
callback)
2399 ifChanged (needsUiUpdate, std::forward<Callback> (
callback));
2402 void clearUiFlags() { needsUiUpdate.clear(); }
2405 template <
typename Callback>
2406 void ifChanged (FlagCache<1>& flags, Callback&&
callback)
2410 callback (groupIndex, values[groupIndex].load (std::memory_order_relaxed));
2414 std::vector<std::atomic<float>> values;
2415 FlagCache<1> needsUiUpdate;
2416 FlagCache<1> needsProcessorUpdate;
2421class LV2Parameter :
public AudioPluginInstance::HostedParameter
2424 LV2Parameter (
const String& nameIn,
2425 const ParameterInfo& infoIn,
2426 ParameterValuesAndFlags& floatCache)
2427 : cache (floatCache),
2431 normalisedDefault (range.convertTo0to1 (infoIn.defaultValue))
2436 return range.convertTo0to1 (getDenormalisedValue());
2439 void setValue (
float f)
override
2441 cache.set ((
size_t) getParameterIndex(), range.convertFrom0to1 (
f), Update::yes);
2444 void setDenormalisedValue (
float denormalised)
2446 cache.set ((
size_t) getParameterIndex(), denormalised, Update::yes);
2447 sendValueChangedMessageToListeners (range.convertTo0to1 (denormalised));
2450 void setDenormalisedValueWithoutTriggeringUpdate (
float denormalised)
2452 cache.set ((
size_t) getParameterIndex(), denormalised, Update::no);
2453 sendValueChangedMessageToListeners (range.convertTo0to1 (denormalised));
2458 return cache.get ((
size_t) getParameterIndex());
2461 float getDefaultValue()
const override {
return normalisedDefault; }
2462 float getDenormalisedDefaultValue()
const {
return info.defaultValue; }
2464 float getValueForText (
const String&
text)
const override
2467 return range.convertTo0to1 (
text.getFloatValue());
2469 const auto it = std::find_if (
info.scalePoints.begin(),
2470 info.scalePoints.end(),
2471 [&] (
const StoredScalePoint& stored) { return stored.label == text; });
2472 return it !=
info.scalePoints.end() ? range.convertTo0to1 (it->value) : normalisedDefault;
2475 int getNumSteps()
const override
2481 return static_cast<int> (
info.scalePoints.size());
2484 return static_cast<int> (range.getRange().getLength()) + 1;
2486 return AudioProcessorParameter::getNumSteps();
2489 bool isDiscrete()
const override {
return info.isEnum ||
info.isInteger ||
info.isToggle; }
2490 bool isBoolean()
const override {
return info.isToggle; }
2492 StringArray getAllValueStrings()
const override
2497 return AudioProcessorParameter::getAllValueStrings();
2500 String
getText (
float normalisedValue,
int)
const override
2502 const auto denormalised = range.convertFrom0to1 (normalisedValue);
2504 if (
info.isEnum && !
info.scalePoints.empty())
2509 const auto index = std::distance (midPoints.begin(),
2510 std::lower_bound (midPoints.begin(), midPoints.end(), normalisedValue));
2511 jassert (isPositiveAndBelow (index,
info.scalePoints.size()));
2512 return info.scalePoints[(size_t) index].label;
2515 return getFallbackParameterString (denormalised);
2518 String getParameterID()
const override
2520 return info.identifier;
2523 String getName (
int maxLength)
const override
2525 return name.substring (0, maxLength);
2528 String getLabel()
const override
2535 String getFallbackParameterString (
float denormalised)
const
2538 return denormalised > 0.0f ?
"On" :
"Off";
2541 return String {
static_cast<int> (denormalised) };
2543 return String { denormalised };
2546 static std::vector<float> findScalePointMidPoints (
const SafeSortedSet<StoredScalePoint>& set)
2551 std::vector<float>
result;
2553 for (
auto it = std::next (set.begin()); it != set.end(); ++it)
2554 result.push_back ((std::prev (it)->
value + it->value) * 0.5f);
2561 ParameterValuesAndFlags& cache;
2562 const ParameterInfo
info;
2563 const std::vector<float> midPoints = findScalePointMidPoints (
info.scalePoints);
2564 const NormalisableRange<float> range;
2566 const float normalisedDefault;
2577 auto withBundlePath (File
v)
const noexcept {
return with (&UiInstanceArgs::bundlePath, std::move (
v)); }
2578 auto withPluginUri (URL
v)
const noexcept {
return with (&UiInstanceArgs::pluginUri, std::move (
v)); }
2581 template <
typename Member>
2582 UiInstanceArgs with (Member UiInstanceArgs::* member, Member
value)
const noexcept
2584 return juce::lv2_host::with (*
this, member, std::move (
value));
2588static File bundlePathFromUri (
const char*
uri)
2599 UiInstance (World&
world,
2600 const UiDescriptor* descriptorIn,
2601 const UiInstanceArgs& args,
2603 MessageBufferInterface<MessageHeader>& messagesIn,
2605 PhysicalResizeListener& rl)
2607 resizeListener (rl),
2608 uiToProcessor (messagesIn),
2612 instance (makeInstance (args.pluginUri, args.bundlePath, features)),
2623 void pushMessage (MessageHeader header,
uint32_t size,
const void* buffer)
2625 descriptor->portEvent (getHandle(), header.portIndex,
size, header.protocol, buffer);
2630 if (idleCallback.valid && idleCallback.extension.idle !=
nullptr)
2631 return idleCallback.extension.idle (getHandle());
2636 template <
typename Extension>
2637 OptionalExtension<Extension> getExtensionData (World&
world,
const char* uid)
const
2642 Rectangle<int> getDetectedViewBounds()
const
2645 const auto frame = [(NSView*) widget frame];
2646 return { (
int) frame.size.width, (
int) frame.size.height };
2647 #elif JUCE_LINUX || JUCE_BSD
2650 unsigned int ww = 0, wh = 0, bw = 0, bitDepth = 0;
2652 XWindowSystemUtilities::ScopedXLock xLock;
2653 auto* display = XWindowSystem::getInstance()->getDisplay();
2654 X11Symbols::getInstance()->xGetGeometry (display,
2655 (::Drawable) widget,
2664 return { (
int)
ww, (
int) wh };
2680 Instance makeInstance (
const URL& pluginUri,
const File& bundlePath,
const LV2_Feature*
const* features)
2686 pluginUri.toString (
false).toRawUTF8(),
2697 const LV2_URID protocols[] { 0, mLV2_UI__floatProtocol, mLV2_ATOM__atomTransfer, mLV2_ATOM__eventTransfer };
2698 const auto it = std::find (std::begin (protocols), std::end (protocols), protocol);
2700 if (it != std::end (protocols))
2702 uiToProcessor.pushMessage ({ portIndex, protocol }, bufferSize,
buffer);
2713 static_cast<UiInstance*
> (
controller)->write (portIndex, bufferSize, portProtocol, buffer);
2716 PhysicalResizeListener& resizeListener;
2717 MessageBufferInterface<MessageHeader>& uiToProcessor;
2719 const LV2_URID mLV2_UI__floatProtocol;
2720 const LV2_URID mLV2_ATOM__atomTransfer;
2721 const LV2_URID mLV2_ATOM__eventTransfer;
2723 OptionalExtension<LV2UI_Idle_Interface> idleCallback;
2726 NSViewFrameWatcher frameWatcher { (NSView*) widget, [
this]
2728 const auto bounds = getDetectedViewBounds();
2729 resizeListener.viewRequestedResizeInPhysicalPixels (bounds.getWidth(), bounds.getHeight());
2732 WindowSizeChangeListener frameWatcher { (
HWND) widget, resizeListener };
2740 virtual ~TouchListener() =
default;
2741 virtual void controlGrabbed (
uint32_t port,
bool grabbed) = 0;
2744class AsyncFn :
public AsyncUpdater
2747 explicit AsyncFn (std::function<
void()> callbackIn)
2750 ~AsyncFn()
override { cancelPendingUpdate(); }
2752 void handleAsyncUpdate()
override {
callback(); }
2758class UiFeaturesDataOptions
2761 float initialScaleFactor = 0.0f, sampleRate = 0.0f;
2763 auto withInitialScaleFactor (
float v)
const {
return with (&UiFeaturesDataOptions::initialScaleFactor,
v); }
2764 auto withSampleRate (
float v)
const {
return with (&UiFeaturesDataOptions::sampleRate,
v); }
2767 UiFeaturesDataOptions with (
float UiFeaturesDataOptions::* member,
float value)
const
2769 return juce::lv2_host::with (*
this, member,
value);
2776 UiFeaturesData (PhysicalResizeListener& rl,
2780 Instance::GetExtensionData getExtensionData,
2783 const UiFeaturesDataOptions& optIn)
2785 resizeListener (rl),
2787 instance (instanceIn),
2790 dataAccess { getExtensionData },
2791 portIndices (makePortIndices (
ports))
2797 static std::vector<String> getFeatureUris()
2799 return Features::getUris (makeFeatures ({}, {}, {}, {}, {}, {}, {}, {}, {}, {}));
2802 Rectangle<int> getLastRequestedBounds()
const {
return { lastRequestedWidth, lastRequestedHeight }; }
2805 static std::vector<LV2_Feature> makeFeatures (
LV2UI_Resize* resize,
2808 LV2_Extension_Data_Feature*
data,
2831 lastRequestedWidth =
width;
2832 lastRequestedHeight =
height;
2833 resizeListener.viewRequestedResizeInPhysicalPixels (
width,
height);
2839 return static_cast<UiFeaturesData*
> (handle)->resizeCallback (
width,
height);
2842 uint32_t portIndexCallback (
const char* symbol)
const
2844 const auto it = portIndices.find (symbol);
2850 return static_cast<const UiFeaturesData*
> (handle)->portIndexCallback (symbol);
2853 void touchCallback (
uint32_t portIndex,
bool grabbed)
const
2855 touchListener.controlGrabbed (portIndex, grabbed);
2860 return static_cast<const UiFeaturesData*
> (handle)->touchCallback (index,
b);
2863 static std::map<String, uint32_t> makePortIndices (
const Ports& ports)
2865 std::map<String, uint32_t>
result;
2867 ports.forEachPort ([&] (
const PortHeader& header)
2869 const auto emplaced =
result.emplace (header.symbol, header.index);
2879 const UiFeaturesDataOptions opts;
2880 PhysicalResizeListener& resizeListener;
2881 TouchListener& touchListener;
2885 const UsefulUrids urids { symap };
2887 int lastRequestedWidth = 0, lastRequestedHeight = 0;
2893 &opts.initialScaleFactor },
2906 LV2_Extension_Data_Feature dataAccess;
2907 std::map<String, uint32_t> portIndices;
2908 Features features { makeFeatures (&resize,
2917 log.getLogFeature()) };
2922class UiInstanceWithSupports
2925 UiInstanceWithSupports (World&
world,
2926 PhysicalResizeListener& resizeListener,
2927 TouchListener& touchListener,
2929 const UiInstanceArgs& args,
2931 InstanceWithSupports& engineInstance,
2932 const UiFeaturesDataOptions& opts)
2933 : features (resizeListener,
2935 engineInstance.instance.getHandle(),
2937 engineInstance.instance.getExtensionDataCallback(),
2938 engineInstance.
ports,
2939 *engineInstance.symap,
2944 features.getFeatureArray(),
2945 engineInstance.uiToProcessor,
2946 *engineInstance.symap,
2950 UiFeaturesData features;
2951 UiInstance instance;
2956struct RequiredFeatures
2958 explicit RequiredFeatures (OwningNodes nodes)
2959 : values (std::
move (nodes)) {}
2964struct OptionalFeatures
2966 explicit OptionalFeatures (OwningNodes nodes)
2967 : values (std::
move (nodes)) {}
2972template <
typename Range,
typename Predicate>
2973static bool noneOf (Range&& range, Predicate&& pred)
2978 return std::none_of (begin (range), end (range), std::forward<Predicate> (pred));
2981class PeerChangedListener :
private ComponentMovementWatcher
2984 PeerChangedListener (Component&
c, std::function<
void()> peerChangedIn)
2985 : ComponentMovementWatcher (&
c), peerChanged (std::
move (peerChangedIn))
2989 void componentMovedOrResized (
bool,
bool)
override {}
2990 void componentPeerChanged()
override { NullCheckedInvocation::invoke (peerChanged); }
2991 void componentVisibilityChanged()
override {}
2993 using ComponentMovementWatcher::componentVisibilityChanged;
2994 using ComponentMovementWatcher::componentMovedOrResized;
2997 std::function<
void()> peerChanged;
3000struct ViewSizeListener :
private ComponentMovementWatcher
3002 ViewSizeListener (Component&
c, PhysicalResizeListener&
l)
3003 : ComponentMovementWatcher (&
c), listener (
l)
3007 void componentMovedOrResized (
bool,
bool wasResized)
override
3011 const auto physicalSize = Desktop::getInstance().getDisplays()
3012 .logicalToPhysical (getComponent()->localAreaToGlobal (getComponent()->getLocalBounds()));
3013 const auto width = physicalSize.getWidth();
3014 const auto height = physicalSize.getHeight();
3017 listener.viewRequestedResizeInPhysicalPixels (
width,
height);
3021 void componentPeerChanged()
override {}
3022 void componentVisibilityChanged()
override {}
3024 using ComponentMovementWatcher::componentVisibilityChanged;
3025 using ComponentMovementWatcher::componentMovedOrResized;
3027 PhysicalResizeListener& listener;
3030class ConfiguredEditorComponent :
public Component,
3031 private PhysicalResizeListener
3034 ConfiguredEditorComponent (World&
world,
3035 InstanceWithSupports& instance,
3036 UiDescriptor& uiDescriptor,
3037 LogicalResizeListener& resizeListenerIn,
3038 TouchListener& touchListener,
3039 const String& uiBundleUri,
3040 const UiFeaturesDataOptions& opts)
3041 : resizeListener (resizeListenerIn),
3044 uiInstance (new UiInstanceWithSupports (
world,
3048 UiInstanceArgs{}.withBundlePath (bundlePathFromUri (uiBundleUri.toRawUTF8()))
3049 .withPluginUri (URL (instance.instance.getUri())),
3050 viewComponent.getWidget(),
3056 jassert (uiInstance !=
nullptr);
3059 addAndMakeVisible (viewComponent);
3061 const auto boundsToUse = [&]
3063 const auto requested = uiInstance->features.getLastRequestedBounds();
3065 if (requested.getWidth() > 10 && requested.getHeight() > 10)
3068 return uiInstance->instance.getDetectedViewBounds();
3071 const auto scaled = lv2ToComponentRect (boundsToUse);
3072 lastWidth = scaled.getWidth();
3073 lastHeight = scaled.getHeight();
3074 setSize (lastWidth, lastHeight);
3077 ~ConfiguredEditorComponent()
override
3079 viewComponent.prepareForDestruction();
3082 void paint (Graphics&
g)
override
3084 g.fillAll (Colours::black);
3087 void resized()
override
3089 viewComponent.setBounds (getLocalBounds());
3092 void updateViewBounds()
3096 if (uiInstance !=
nullptr)
3098 if (resizeClient.valid && resizeClient.extension.ui_resize !=
nullptr)
3100 const auto physicalSize = componentToLv2Rect (getLocalBounds());
3102 resizeClient.extension.ui_resize (uiInstance->instance.getHandle(),
3103 physicalSize.getWidth(),
3104 physicalSize.getHeight());
3109 void pushMessage (MessageHeader header,
uint32_t size,
const void* buffer)
3111 if (uiInstance !=
nullptr)
3112 uiInstance->instance.pushMessage (header,
size, buffer);
3117 if (uiInstance !=
nullptr)
3118 return uiInstance->instance.idle();
3123 void childBoundsChanged (Component*
c)
override
3129 void setUserScaleFactor (
float userScale) { userScaleFactor = userScale; }
3131 void sendScaleFactorToPlugin()
3133 const auto factor = getEffectiveScale();
3138 { {}, {}, {}, {}, {}, {} }
3141 if (optionsInterface.valid)
3142 optionsInterface.extension.set (uiInstance->instance.getHandle(), options);
3144 applyLastRequestedPhysicalSize();
3148 void viewRequestedResizeInPhysicalPixels (
int width,
int height)
override
3152 const auto logical = lv2ToComponentRect ({
width,
height });
3153 resizeListener.viewRequestedResizeInLogicalPixels (logical.getWidth(), logical.getHeight());
3156 void resizeToFitView()
3158 viewComponent.fitToView();
3159 resizeListener.viewRequestedResizeInLogicalPixels (viewComponent.getWidth(), viewComponent.getHeight());
3162 void applyLastRequestedPhysicalSize()
3164 viewRequestedResizeInPhysicalPixels (lastWidth, lastHeight);
3165 viewComponent.forceViewToSize();
3169 Rectangle<int> componentToLv2Rect (Rectangle<int>
r)
const
3171 return localAreaToGlobal (
r) * nativeScaleFactor * getDesktopScaleFactor();
3175 Rectangle<int> lv2ToComponentRect (Rectangle<int> vr)
const
3177 return getLocalArea (
nullptr, vr / (nativeScaleFactor * getDesktopScaleFactor()));
3180 float getEffectiveScale()
const {
return nativeScaleFactor * userScaleFactor; }
3184 #if JUCE_LINUX || JUCE_BSD
3187 struct Inner :
public XEmbedComponent
3189 Inner() : XEmbedComponent (
true,
true)
3199 struct ViewComponent :
public InnerHolder,
3200 public XEmbedComponent
3202 explicit ViewComponent (PhysicalResizeListener&
l)
3203 : XEmbedComponent ((unsigned long) inner.getPeer()->getNativeHandle(),
true,
false),
3214 void prepareForDestruction()
3216 inner.removeClient();
3219 LV2UI_Widget getWidget() {
return lv2_shared::wordCast<LV2UI_Widget> (inner.getHostWindowID()); }
3220 void forceViewToSize() {}
3223 ViewSizeListener listener;
3226 struct ViewComponent :
public NSViewComponentWithParent
3228 explicit ViewComponent (PhysicalResizeListener&)
3229 : NSViewComponentWithParent (WantsNudge::
no) {}
3231 void forceViewToSize() {}
3232 void fitToView() { resizeToFitView(); }
3233 void prepareForDestruction() {}
3236 struct ViewComponent :
public HWNDComponent
3238 explicit ViewComponent (PhysicalResizeListener&)
3241 inner.addToDesktop (0);
3243 if (
auto* peer = inner.getPeer())
3244 setHWND (peer->getNativeHandle());
3247 void paint (Graphics&
g)
override {
g.fillAll (Colours::black); }
3251 void forceViewToSize() { updateHWNDBounds(); }
3252 void fitToView() { resizeToFit(); }
3254 void prepareForDestruction() {}
3257 struct Inner :
public Component
3259 Inner() { setOpaque (
true); }
3260 void paint (Graphics&
g)
override {
g.fillAll (Colours::black); }
3266 struct ViewComponent :
public Component
3268 explicit ViewComponent (PhysicalResizeListener&) {}
3269 void* getWidget() {
return nullptr; }
3270 void forceViewToSize() {}
3272 void prepareForDestruction() {}
3276 struct ScaleNotifierCallback
3278 ConfiguredEditorComponent&
window;
3280 void operator() (
float platformScale)
const
3282 MessageManager::callAsync ([ref = Component::SafePointer<ConfiguredEditorComponent> (&window), platformScale]
3284 if (
auto*
r = ref.getComponent())
3286 if (std::exchange (
r->nativeScaleFactor, platformScale) == platformScale)
3289 r->nativeScaleFactor = platformScale;
3290 r->sendScaleFactorToPlugin();
3296 LogicalResizeListener& resizeListener;
3297 int lastWidth = 0, lastHeight = 0;
3298 float nativeScaleFactor = 1.0f, userScaleFactor = 1.0f;
3299 NativeScaleFactorNotifier scaleNotifier {
this, ScaleNotifierCallback { *
this } };
3300 ViewComponent viewComponent { *
this };
3301 LV2_URID floatUrid, scaleFactorUrid;
3302 std::unique_ptr<UiInstanceWithSupports> uiInstance;
3303 OptionalExtension<LV2UI_Resize> resizeClient;
3304 OptionalExtension<LV2_Options_Interface> optionsInterface;
3305 PeerChangedListener peerListener { *
this, [
this]
3307 applyLastRequestedPhysicalSize();
3315struct EditorListener
3317 virtual ~EditorListener() =
default;
3329 virtual void viewCreated (UiEventListener* newListener) = 0;
3331 virtual void notifyEditorBeingDeleted() = 0;
3337struct InstanceProvider
3339 virtual ~InstanceProvider()
noexcept = default;
3341 virtual InstanceWithSupports* getInstanceWithSupports()
const = 0;
3344class Editor : public AudioProcessorEditor,
3345 public UiEventListener,
3346 private LogicalResizeListener
3349 Editor (World& worldIn,
3350 AudioPluginInstance&
p,
3351 InstanceProvider& instanceProviderIn,
3352 UiDescriptor& uiDescriptorIn,
3353 TouchListener& touchListenerIn,
3354 EditorListener& listenerIn,
3355 const String& uiBundleUriIn,
3356 RequiredFeatures requiredIn,
3357 OptionalFeatures optionalIn)
3358 : AudioProcessorEditor (
p),
3360 instanceProvider (&instanceProviderIn),
3361 uiDescriptor (&uiDescriptorIn),
3362 touchListener (&touchListenerIn),
3363 listener (&listenerIn),
3364 uiBundleUri (uiBundleUriIn),
3365 required (std::
move (requiredIn)),
3366 optional (std::
move (optionalIn))
3368 setResizable (isResizable (required, optional),
false);
3374 instanceProvider->getInstanceWithSupports()->processorToUi->addUi (*
this);
3379 instanceProvider->getInstanceWithSupports()->processorToUi->removeUi (*
this);
3381 listener->notifyEditorBeingDeleted();
3386 const auto initialScale = userScaleFactor * (float) [&]
3388 if (
auto*
p = getPeer())
3389 return p->getPlatformScaleFactor();
3394 const auto opts = UiFeaturesDataOptions{}.withInitialScaleFactor (initialScale)
3395 .withSampleRate ((
float) processor.getSampleRate());
3396 configuredEditor =
nullptr;
3398 *instanceProvider->getInstanceWithSupports(),
3404 parentHierarchyChanged();
3405 const auto initialSize = configuredEditor->getBounds();
3406 setSize (initialSize.getWidth(), initialSize.getHeight());
3408 listener->viewCreated (
this);
3413 configuredEditor =
nullptr;
3416 void paint (Graphics&
g)
override
3418 g.fillAll (Colours::black);
3421 void resized()
override
3423 const ScopedValueSetter<bool>
scope (resizeFromHost,
true);
3425 if (
auto* inner = configuredEditor.get())
3427 inner->setBounds (getLocalBounds());
3428 inner->updateViewBounds();
3432 void parentHierarchyChanged()
override
3434 if (
auto*
comp = configuredEditor.get())
3437 addAndMakeVisible (
comp);
3439 removeChildComponent (
comp);
3443 void pushMessage (MessageHeader header,
uint32_t size,
const void* buffer)
override
3445 if (
auto*
comp = configuredEditor.get())
3446 comp->pushMessage (header,
size, buffer);
3451 if (
auto*
comp = configuredEditor.get())
3452 return comp->idle();
3457 void setScaleFactor (
float newScale)
override
3459 userScaleFactor = newScale;
3461 if (configuredEditor !=
nullptr)
3463 configuredEditor->setUserScaleFactor (userScaleFactor);
3464 configuredEditor->sendScaleFactorToPlugin();
3469 bool isResizable (
const RequiredFeatures& requiredFeatures,
3470 const OptionalFeatures& optionalFeatures)
const
3472 const auto uriMatches = [] (
const LilvNode* node)
3480 && noneOf (requiredFeatures.values, uriMatches)
3481 && noneOf (optionalFeatures.values, uriMatches);
3484 bool isScalable()
const
3489 void viewRequestedResizeInLogicalPixels (
int width,
int height)
override
3491 if (! resizeFromHost)
3496 InstanceProvider* instanceProvider;
3497 UiDescriptor* uiDescriptor;
3498 TouchListener* touchListener;
3499 EditorListener* listener;
3501 const RequiredFeatures required;
3502 const OptionalFeatures optional;
3503 std::unique_ptr<ConfiguredEditorComponent> configuredEditor;
3504 float userScaleFactor = 1.0f;
3505 bool resizeFromHost =
false;
3520 const LilvUI* getByUri (
const NodeUri&
uri)
const
3531 std::unique_ptr<LilvUIs, Free> uis;
3552using FloatWriter =
void (*) (LV2_Atom_Forge*, float);
3554struct ParameterWriterUrids
3562struct MessageHeaderAndSize
3564 MessageHeader header;
3568class ParameterWriter
3571 ParameterWriter (ControlPort*
p)
3572 :
data (PortBacking {
p }), kind (Kind::
port) {}
3574 ParameterWriter (FloatWriter write,
LV2_URID urid,
uint32_t controlPortIndex)
3575 :
data (PatchBacking { write, urid, controlPortIndex }), kind (Kind::patch) {}
3577 void writeToProcessor (
const ParameterWriterUrids urids, LV2_Atom_Forge* forge,
float value)
const
3583 if (forge !=
nullptr)
3586 writeSetToForge (urids, *forge,
value);
3598 MessageHeaderAndSize writeToUi (
const ParameterWriterUrids urids, LV2_Atom_Forge& forge,
float value)
const
3600 const auto getWrittenBytes = [&]() ->
uint32_t
3602 if (
const auto* atom = convertToAtomPtr (forge.
buf, forge.
size))
3612 writeSetToForge (urids, forge,
value);
3613 return { {
data.patch.controlPortIndex, urids.mLV2_ATOM__eventTransfer }, getWrittenBytes() };
3617 return { {
data.port.port->header.index, 0 },
sizeof (
value) };
3620 return { { 0, 0 }, 0 };
3625 return kind == Kind::patch ? &
data.patch.urid :
nullptr;
3628 const uint32_t* getPortIndex()
const
3630 return kind == Kind::port ? &
data.port.port->header.index :
nullptr;
3634 void writeSetToForge (
const ParameterWriterUrids urids, LV2_Atom_Forge& forge,
float value)
const
3636 lv2_shared::ObjectFrame
object { &forge, (
uint32_t) 0, urids.mLV2_PATCH__Set };
3659 static_assert (std::is_trivial<PortBacking>::value,
"PortBacking must be trivial");
3660 static_assert (std::is_trivial<PatchBacking>::value,
"PatchBacking must be trivial");
3662 explicit Data (PortBacking
p) :
port (
p) {}
3663 explicit Data (PatchBacking
p) : patch (
p) {}
3669 enum class Kind {
port, patch };
3677static String lilvNodeToUriString (
const LilvNode* node)
3682static String lilvNodeToString (
const LilvNode* node)
3694class IntermediateParameterTree
3697 explicit IntermediateParameterTree (World& worldIn)
3700 const auto groups = getGroups (
world);
3704 for (
const auto& group : groups)
3706 const auto symbol = lilvNodeToString (
world.get (
group.get(), symbolNode.get(),
nullptr).get());
3707 const auto name = lilvNodeToString (
world.get (
group.get(), nameNode .get(),
nullptr).get());
3708 owning.emplace (lilvNodeToUriString (
group.get()),
3709 std::make_unique<AudioProcessorParameterGroup> (symbol,
name,
"|"));
3713 void addParameter (StringRef group, std::unique_ptr<LV2Parameter> param)
3715 if (param ==
nullptr)
3718 const auto it = owning.find (group);
3719 (it != owning.cend() ? *it->second : topLevel).addChild (std::move (param));
3722 static AudioProcessorParameterGroup getTree (IntermediateParameterTree tree)
3724 std::map<String, AudioProcessorParameterGroup*> nonowning;
3726 for (
const auto& pair :
tree.owning)
3727 nonowning.emplace (pair.first, pair.second.get());
3729 const auto groups = getGroups (
tree.world);
3732 for (
const auto& group : groups)
3734 const auto innerIt =
tree.owning.find (lilvNodeToUriString (
group.get()));
3736 if (innerIt ==
tree.owning.cend())
3739 const auto outer = lilvNodeToUriString (
tree.world.get (
group.get(), subgroupNode.get(),
nullptr).get());
3740 const auto outerIt = nonowning.find (outer);
3742 if (outerIt != nonowning.cend() && containsParameters (outerIt->second))
3743 outerIt->second->addChild (std::move (innerIt->second));
3746 for (
auto& subgroup :
tree.owning)
3747 if (containsParameters (subgroup.second.get()))
3748 tree.topLevel.addChild (std::move (subgroup.second));
3750 return std::move (
tree.topLevel);
3754 static std::vector<OwningNode> getGroups (World&
world)
3756 std::vector<OwningNode> names;
3765 static bool containsParameters (
const AudioProcessorParameterGroup*
g)
3770 for (
auto* node : *
g)
3772 if (node->getParameter() !=
nullptr)
3775 if (
auto* group = node->getGroup())
3776 if (containsParameters (group))
3784 AudioProcessorParameterGroup topLevel;
3785 std::map<String, std::unique_ptr<AudioProcessorParameterGroup>> owning;
3790struct BypassParameter :
public LV2Parameter
3792 BypassParameter (
const ParameterInfo& parameterInfo, ParameterValuesAndFlags& cacheIn)
3793 : LV2Parameter (
"Bypass", parameterInfo, cacheIn) {}
3797 return LV2Parameter::getValue() > 0.0f ? 0.0f : 1.0f;
3800 void setValue (
float newValue)
override
3802 LV2Parameter::setValue (newValue > 0.0f ? 0.0f : 1.0f);
3805 float getDefaultValue()
const override {
return 0.0f; }
3806 bool isAutomatable()
const override {
return true; }
3807 bool isDiscrete()
const override {
return true; }
3808 bool isBoolean()
const override {
return true; }
3809 int getNumSteps()
const override {
return 2; }
3810 StringArray getAllValueStrings()
const override {
return {
TRANS (
"Off"),
TRANS (
"On") }; }
3816 ParameterWriter writer;
3821template <
typename T>
3822static auto getPortPointers (SimpleSpan<T> range)
3827 for (
auto& port : range)
3829 result.resize (std::max ((
size_t) (
port.header.index + 1),
result.size()),
nullptr);
3836static std::unique_ptr<LV2Parameter> makeParameter (
const uint32_t* enabledPortIndex,
3837 const ParameterData&
data,
3838 ParameterValuesAndFlags& cache)
3845 if (enabledPortIndex !=
nullptr)
3846 if (
auto* index =
data.writer.getPortIndex())
3847 if (*index == *enabledPortIndex)
3848 return std::make_unique<BypassParameter> (
data.info, cache);
3850 return std::make_unique<LV2Parameter> (
data.name,
data.info, cache);
3853class ControlPortAccelerationStructure
3856 ControlPortAccelerationStructure (SimpleSpan<ControlPort> controlPorts)
3857 : indexedControlPorts (getPortPointers (controlPorts))
3859 for (
const auto& port : controlPorts)
3860 if (
port.header.direction == Port::Direction::output)
3861 outputPorts.push_back (&port);
3864 const std::vector<ControlPort*>& getIndexedControlPorts() {
return indexedControlPorts; }
3866 ControlPort* getControlPortByIndex (
uint32_t index)
const
3868 if (isPositiveAndBelow (index, indexedControlPorts.size()))
3869 return indexedControlPorts[index];
3874 void writeOutputPorts (UiEventListener* target, MessageBufferInterface<UiMessageHeader>& uiMessages)
const
3876 if (target ==
nullptr)
3879 for (
const auto* port : outputPorts)
3881 const auto chars = toChars (
port->currentValue);
3882 uiMessages.pushMessage ({ target, {
port->header.index, 0 } }, (
uint32_t) chars.size(), chars.data());
3887 std::vector<ControlPort*> indexedControlPorts;
3888 std::vector<const ControlPort*> outputPorts;
3891class ParameterValueCache
3897 ParameterValueCache (AudioPluginInstance& processor,
3900 const std::vector<ParameterData>&
data,
3901 ControlPort* enabledPort)
3902 : uiForge (mapFeature),
3910 std::map<AudioProcessorParameter*, ParameterWriter> writerForParameter;
3912 IntermediateParameterTree
tree {
world };
3914 const auto* enabledPortIndex = enabledPort !=
nullptr ? &enabledPort->header.index
3917 for (
const auto& item :
data)
3919 auto param = makeParameter (enabledPortIndex, item, cache);
3921 if (
auto* urid = item.writer.getUrid())
3922 urids.emplace (*urid, param.get());
3924 if (
auto* index = item.writer.getPortIndex())
3925 portIndices.emplace (*index, param.get());
3927 writerForParameter.emplace (param.get(), item.writer);
3929 tree.addParameter (item.group, std::move (param));
3932 processor.setHostedParameterTree (IntermediateParameterTree::getTree (std::move (tree)));
3935 writers.reserve (
data.size());
3937 for (
auto* param : processor.getParameters())
3939 const auto it = writerForParameter.find (param);
3940 jassert (it != writerForParameter.end());
3941 writers.push_back (it->second);
3945 jassert (processor.getParameters().size() == (
int) (urids.size() + portIndices.size()));
3948 const auto setToDefault = [] (
auto& container)
3950 for (auto& item : container)
3951 item.second->setDenormalisedValueWithoutTriggeringUpdate (item.second->getDenormalisedDefaultValue());
3954 setToDefault (urids);
3955 setToDefault (portIndices);
3958 void postChangedParametersToProcessor (
const ParameterWriterUrids helperUrids,
3959 LV2_Atom_Forge* forge)
3961 cache.ifProcessorValuesChanged ([&] (
size_t index,
float value)
3963 writers[index].writeToProcessor (helperUrids, forge,
value);
3967 void postChangedParametersToUi (UiEventListener* target,
3968 const ParameterWriterUrids helperUrids,
3969 MessageBufferInterface<UiMessageHeader>& uiMessages)
3971 if (target ==
nullptr)
3974 cache.ifUiValuesChanged ([&] (
size_t index,
float value)
3976 writeParameterToUi (target, writers[index],
value, helperUrids, uiMessages);
3980 void postAllParametersToUi (UiEventListener* target,
3981 const ParameterWriterUrids helperUrids,
3982 MessageBufferInterface<UiMessageHeader>& uiMessages)
3984 if (target ==
nullptr)
3987 const auto numWriters = writers.size();
3989 for (
size_t i = 0;
i < numWriters; ++
i)
3990 writeParameterToUi (target, writers[
i], cache.get (
i), helperUrids, uiMessages);
3992 cache.clearUiFlags();
3995 LV2Parameter* getParamByUrid (
LV2_URID urid)
const
3997 const auto it = urids.find (urid);
3998 return it != urids.end() ? it->second :
nullptr;
4001 LV2Parameter* getParamByPortIndex (
uint32_t portIndex)
const
4003 const auto it = portIndices.find (portIndex);
4004 return it != portIndices.end() ? it->second :
nullptr;
4007 void updateFromControlPorts (
const ControlPortAccelerationStructure& ports)
const
4009 for (
const auto& pair : portIndices)
4010 if (
auto* port =
ports.getControlPortByIndex (pair.first))
4011 if (
auto* param = pair.second)
4012 param->setDenormalisedValueWithoutTriggeringUpdate (
port->currentValue);
4016 void writeParameterToUi (UiEventListener* target,
4017 const ParameterWriter& writer,
4019 const ParameterWriterUrids helperUrids,
4020 MessageBufferInterface<UiMessageHeader>& uiMessages)
4024 uiForge.setBuffer (forgeStorage.data(), forgeStorage.size());
4025 const auto messageHeader = writer.writeToUi (helperUrids, *uiForge.get(),
value);
4026 uiMessages.pushMessage ({ target, messageHeader.header }, messageHeader.size, forgeStorage.data());
4029 SingleSizeAlignedStorage<8> forgeStorage { 256 };
4030 lv2_shared::AtomForge uiForge;
4032 ParameterValuesAndFlags cache;
4033 std::vector<ParameterWriter> writers;
4034 std::map<LV2_URID, LV2Parameter*> urids;
4035 std::map<uint32_t, LV2Parameter*> portIndices;
4040struct PatchSetCallback
4042 explicit PatchSetCallback (ParameterValueCache&
x) : cache (
x) {}
4046 void setParameter (
LV2_URID property,
float value)
const noexcept
4048 if (
auto* param = cache.getParamByUrid (property))
4049 param->setDenormalisedValueWithoutTriggeringUpdate (
value);
4054 ParameterValueCache& cache;
4057struct SupportedParameter
4064static SupportedParameter getInfoForPatchParameter (World& worldIn,
4065 const UsefulUrids& urids,
4066 const NodeUri& property)
4068 const auto rangeUri = worldIn.newUri (
LILV_NS_RDFS "range");
4069 const auto type = worldIn.get (property.get(), rangeUri.get(),
nullptr);
4071 if (
type ==
nullptr)
4072 return { {},
false, {} };
4076 const LV2_URID types[] { urids.mLV2_ATOM__Int,
4077 urids.mLV2_ATOM__Long,
4078 urids.mLV2_ATOM__Float,
4079 urids.mLV2_ATOM__Double,
4080 urids.mLV2_ATOM__Bool };
4082 if (std::find (std::begin (types), std::end (types), typeUrid) == std::end (types))
4083 return { {},
false, {} };
4085 const auto getValue = [&] (
const char*
uri,
float fallback)
4087 return Port::getFloatValue (worldIn.get (property.get(), worldIn.newUri (
uri).get(),
nullptr).get(), fallback);
4090 const auto hasPortProperty = [&] (
const char*
uri)
4092 return worldIn.ask (property.get(),
4094 worldIn.newUri (
uri).get());
4097 const auto metadataScalePoints = worldIn.findNodes (property.get(),
4100 SafeSortedSet<StoredScalePoint> parsedScalePoints;
4102 for (
const auto* scalePoint : metadataScalePoints)
4104 const auto label = worldIn.get (scalePoint, worldIn.newUri (
LILV_NS_RDFS "label").get(),
nullptr);
4105 const auto value = worldIn.get (scalePoint, worldIn.newUri (
LILV_NS_RDF "value").get(),
nullptr);
4107 if (label !=
nullptr &&
value !=
nullptr)
4116 return { { std::move (parsedScalePoints),
4122 typeUrid == urids.mLV2_ATOM__Int || typeUrid == urids.mLV2_ATOM__Long,
4128static std::vector<ParameterData> getPortBasedParameters (World&
world,
4129 const Plugin& plugin,
4130 std::initializer_list<const ControlPort*> hiddenPorts,
4131 SimpleSpan<ControlPort> controlPorts)
4133 std::vector<ParameterData>
result;
4137 for (
auto& port : controlPorts)
4139 if (
port.header.direction != Port::Direction::input)
4142 if (std::find (std::begin (hiddenPorts), std::end (hiddenPorts), &port) != std::end (hiddenPorts))
4145 const auto lilvPort = plugin.getPortByIndex (
port.header.index);
4146 const auto group = lilvNodeToUriString (lilvPort.get (groupNode.get()).get());
4160static std::vector<ParameterData> getPatchBasedParameters (World&
world,
4161 const Plugin& plugin,
4162 const UsefulUrids& urids,
4169 const auto writableControls =
world.findNodes (plugin.getUri().get(),
4179 std::vector<DataAndUri> resultWithUris;
4183 for (
auto* ctrl : writableControls)
4185 const auto labelString = [&]
4194 const auto info = getInfoForPatchParameter (
world, urids,
world.newUri (
uri.toRawUTF8()));
4196 if (!
info.supported)
4199 const auto write = [&]
4201 if (
info.type == urids.mLV2_ATOM__Int)
4202 return writeIntToForge;
4204 if (
info.type == urids.mLV2_ATOM__Long)
4205 return writeLongToForge;
4207 if (
info.type == urids.mLV2_ATOM__Double)
4208 return writeDoubleToForge;
4210 if (
info.type == urids.mLV2_ATOM__Bool)
4211 return writeBoolToForge;
4213 return writeFloatToForge;
4216 const auto group = lilvNodeToUriString (
world.get (ctrl, groupNode.get(),
nullptr).get());
4217 resultWithUris.push_back ({ {
info.info,
4218 ParameterWriter { write, urids.symap.map (
uri.toRawUTF8()), controlPortIndex },
4224 const auto compareUris = [] (
const DataAndUri&
a,
const DataAndUri&
b) {
return a.uri <
b.uri; };
4225 std::sort (resultWithUris.begin(), resultWithUris.end(), compareUris);
4227 std::vector<ParameterData>
result;
4229 for (
const auto& item : resultWithUris)
4230 result.push_back (item.data);
4235static std::vector<ParameterData> getJuceParameterInfo (World&
world,
4236 const Plugin& plugin,
4237 const UsefulUrids& urids,
4238 std::initializer_list<const ControlPort*> hiddenPorts,
4239 SimpleSpan<ControlPort> controlPorts,
4242 auto port = getPortBasedParameters (
world, plugin, hiddenPorts, controlPorts);
4243 auto patch = getPatchBasedParameters (
world, plugin, urids, controlPortIndex);
4245 port.insert (
port.end(), patch.begin(), patch.end());
4253#if JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX || JUCE_BSD
4254 constexpr auto editorFunctionalityEnabled =
true;
4256 constexpr auto editorFunctionalityEnabled =
false;
4259template <
bool editorEnabled = editorFunctionalityEnabled>
class OptionalEditor;
4262class OptionalEditor<
true>
4265 OptionalEditor (String uiBundleUriIn, UiDescriptor uiDescriptorIn, std::function<
void()> timerCallback)
4266 : uiBundleUri (std::
move (uiBundleUriIn)),
4267 uiDescriptor (std::
move (uiDescriptorIn)),
4268 changedParameterFlusher (std::
move (timerCallback)) {}
4272 if (
auto* editor = editorPointer.getComponent())
4273 editor->createView();
4278 if (
auto* editor = editorPointer.getComponent())
4279 editor->destroyView();
4282 std::unique_ptr<AudioProcessorEditor> createEditor (World&
world,
4283 AudioPluginInstance&
p,
4284 InstanceProvider& instanceProviderIn,
4285 TouchListener& touchListenerIn,
4286 EditorListener& listenerIn)
4291 const auto queryFeatures = [
this, &
world] (
const char* kind)
4293 return world.findNodes (
world.newUri (uiDescriptor.get()->URI).get(),
4294 world.newUri (kind).get(),
4298 auto newEditor = std::make_unique<Editor> (
world,
4308 editorPointer = newEditor.get();
4310 changedParameterFlusher.startTimerHz (60);
4315 bool hasEditor()
const
4317 return uiDescriptor.get() !=
nullptr;
4320 void prepareToDestroyEditor()
4322 changedParameterFlusher.stopTimer();
4326 Component::SafePointer<Editor> editorPointer =
nullptr;
4328 UiDescriptor uiDescriptor;
4329 LambdaTimer changedParameterFlusher;
4333class OptionalEditor<
false>
4336 OptionalEditor (String, UiDescriptor, std::function<
void()>) {}
4338 void createView() {}
4339 void destroyView() {}
4341 std::unique_ptr<AudioProcessorEditor> createEditor(World&,
4342 AudioPluginInstance&,
4350 bool hasEditor()
const {
return false; }
4351 void prepareToDestroyEditor() {}
4355class LV2AudioPluginInstance :
public AudioPluginInstance,
4356 private TouchListener,
4357 private EditorListener,
4358 private InstanceProvider
4361 LV2AudioPluginInstance (std::shared_ptr<World> worldIn,
4362 const Plugin& pluginIn,
4363 const UsefulUris&
uris,
4364 std::unique_ptr<InstanceWithSupports>&&
in,
4365 PluginDescription&& desc,
4366 std::vector<String> knownPresetUris,
4367 PluginState stateToApply,
4368 String uiBundleUriIn,
4369 UiDescriptor uiDescriptorIn)
4370 : LV2AudioPluginInstance (worldIn,
4374 std::
move (knownPresetUris),
4375 std::
move (stateToApply),
4376 std::
move (uiBundleUriIn),
4377 std::
move (uiDescriptorIn),
4378 getParsedBuses (*worldIn, pluginIn,
uris)) {}
4380 void fillInPluginDescription (PluginDescription&
d)
const override {
d = description; }
4382 const String getName()
const override {
return description.name; }
4384 void prepareToPlay (
double sampleRate,
int numSamples)
override
4402 getStateInformation (mb);
4404 instance = std::make_unique<InstanceWithSupports> (*
world,
4405 std::move (instance->symap),
4407 std::move (instance->ports),
4412 setStateInformationImpl (mb.
getData(), (
int) mb.
getSize(), ConcurrentWithAudioCallback::no);
4414 jassert (numSamples == instance->features.getMaxBlockSize());
4416 optionalEditor.createView();
4420 void releaseResources()
override {
deactivate(); }
4422 using AudioPluginInstance::processBlock;
4423 using AudioPluginInstance::processBlockBypassed;
4425 void processBlock (AudioBuffer<float>& audio, MidiBuffer& midi)
override
4427 processBlockImpl (audio, midi);
4430 void processBlockBypassed (AudioBuffer<float>& audio, MidiBuffer& midi)
override
4432 if (bypassParam !=
nullptr)
4433 processBlockImpl (audio, midi);
4435 AudioPluginInstance::processBlockBypassed (audio, midi);
4438 double getTailLengthSeconds()
const override {
return {}; }
4440 bool acceptsMidi()
const override
4442 if (instance ==
nullptr)
4445 auto ports = instance->ports.getAtomPorts();
4449 if (a.header.direction != Port::Direction::input)
4452 return portAtIndexSupportsMidi (a.header.index);
4456 bool producesMidi()
const override
4458 if (instance ==
nullptr)
4461 auto ports = instance->ports.getAtomPorts();
4465 if (a.header.direction != Port::Direction::output)
4468 return portAtIndexSupportsMidi (a.header.index);
4472 AudioProcessorEditor* createEditor()
override
4474 return optionalEditor.createEditor (*
world, *
this, *
this, *
this, *
this).release();
4477 bool hasEditor()
const override
4479 return optionalEditor.hasEditor();
4482 int getNumPrograms()
override {
return (
int) presetUris.size(); }
4484 int getCurrentProgram()
override
4486 return lastAppliedPreset;
4489 void setCurrentProgram (
int newProgram)
override
4493 if (! isPositiveAndBelow (newProgram, presetUris.size()))
4496 lastAppliedPreset = newProgram;
4497 applyStateWithAppropriateLocking (loadStateWithUri (presetUris[(
size_t) newProgram]),
4498 ConcurrentWithAudioCallback::yes);
4501 const String getProgramName (
int program)
override
4505 if (isPositiveAndBelow (program, presetUris.size()))
4506 return loadStateWithUri (presetUris[(
size_t) program]).getLabel();
4511 void changeProgramName (
int program,
const String& label)
override
4515 if (isPositiveAndBelow (program, presetUris.size()))
4516 loadStateWithUri (presetUris[(
size_t) program]).setLabel (label);
4519 void getStateInformation (MemoryBlock& block)
override
4524 PortMap portStateManager (instance->ports);
4525 const auto stateUri =
String::fromUTF8 (instance->instance.getUri()) +
"/savedState";
4526 auto mapFeature = instance->symap->getMapFeature();
4527 auto unmapFeature = instance->symap->getUnmapFeature();
4528 const auto state = PluginState::SaveRestoreHandle (*instance, portStateManager).save (plugin.get(), &mapFeature);
4529 const auto string = state.toString (
world->get(), &mapFeature, &unmapFeature, stateUri.toRawUTF8());
4530 block.replaceAll (
string.
data(),
string.
size());
4533 void setStateInformation (
const void*
data,
int size)
override
4535 setStateInformationImpl (
data,
size, ConcurrentWithAudioCallback::yes);
4538 void setNonRealtime (
bool newValue)
noexcept override
4542 AudioPluginInstance::setNonRealtime (newValue);
4543 instance->features.setNonRealtime (newValue);
4546 bool isBusesLayoutSupported (
const BusesLayout& layout)
const override
4548 for (
const auto& pair : { std::make_tuple (&layout.inputBuses, &declaredBusLayout.inputs),
4549 std::make_tuple (&layout.outputBuses, &declaredBusLayout.outputs) })
4551 const auto& requested = *std::get<0> (pair);
4552 const auto& allowed = *std::get<1> (pair);
4554 if ((
size_t) requested.size() != allowed.size())
4557 for (
size_t busIndex = 0; busIndex < allowed.size(); ++busIndex)
4559 const auto& requestedBus = requested[(
int) busIndex];
4560 const auto& allowedBus = allowed[busIndex];
4562 if (! allowedBus.isCompatible (requestedBus))
4570 void processorLayoutsChanged()
override { ioMap = lv2_shared::PortToAudioBufferMap { getBusesLayout(), declaredBusLayout }; }
4572 AudioProcessorParameter* getBypassParameter()
const override {
return bypassParam; }
4575 enum class ConcurrentWithAudioCallback {
no,
yes };
4577 LV2AudioPluginInstance (std::shared_ptr<World> worldIn,
4578 const Plugin& pluginIn,
4579 std::unique_ptr<InstanceWithSupports>&&
in,
4580 PluginDescription&& desc,
4581 std::vector<String> knownPresetUris,
4582 PluginState stateToApply,
4583 String uiBundleUriIn,
4584 UiDescriptor uiDescriptorIn,
4585 const lv2_shared::ParsedBuses& parsedBuses)
4586 : AudioPluginInstance (getBusesProperties (parsedBuses, *worldIn)),
4587 declaredBusLayout (parsedBuses),
4590 description (std::
move (desc)),
4591 presetUris (std::
move (knownPresetUris)),
4592 instance (std::
move (
in)),
4593 optionalEditor (std::
move (uiBundleUriIn),
4594 std::
move (uiDescriptorIn),
4595 [this] { postChangedParametersToUi(); })
4597 applyStateWithAppropriateLocking (std::move (stateToApply), ConcurrentWithAudioCallback::no);
4600 void setStateInformationImpl (
const void*
data,
int size, ConcurrentWithAudioCallback concurrent)
4607 auto begin =
static_cast<const char*
> (
data);
4608 std::vector<char>
copy (begin, begin +
size);
4610 auto mapFeature = instance->symap->getMapFeature();
4622 optionalEditor.destroyView();
4628 instance->instance.activate();
4636 instance->instance.deactivate();
4641 void processBlockImpl (AudioBuffer<float>& audio, MidiBuffer& midi)
4643 preparePortsForRun (audio, midi);
4645 instance->instance.run (
static_cast<uint32_t> (audio.getNumSamples()));
4646 instance->features.processResponses();
4648 processPortsAfterRun (midi);
4651 bool portAtIndexSupportsMidi (
uint32_t index)
const noexcept
4653 const auto port = plugin.getPortByIndex (index);
4655 if (!
port.isValid())
4661 void controlGrabbed (
uint32_t port,
bool grabbed)
override
4663 if (
auto* param = parameterValues.getParamByPortIndex (port))
4666 param->beginChangeGesture();
4668 param->endChangeGesture();
4672 void viewCreated (UiEventListener* newListener)
override
4674 uiEventListener = newListener;
4675 postAllParametersToUi();
4678 ParameterWriterUrids getParameterWriterUrids()
const
4680 return { instance->urids.mLV2_PATCH__Set,
4681 instance->urids.mLV2_PATCH__property,
4682 instance->urids.mLV2_PATCH__value,
4683 instance->urids.mLV2_ATOM__eventTransfer };
4686 void postAllParametersToUi()
4688 parameterValues.postAllParametersToUi (uiEventListener, getParameterWriterUrids(), *instance->processorToUi);
4689 controlPortStructure.writeOutputPorts (uiEventListener, *instance->processorToUi);
4692 void postChangedParametersToUi()
4694 parameterValues.postChangedParametersToUi (uiEventListener, getParameterWriterUrids(), *instance->processorToUi);
4695 controlPortStructure.writeOutputPorts (uiEventListener, *instance->processorToUi);
4698 void notifyEditorBeingDeleted()
override
4700 optionalEditor.prepareToDestroyEditor();
4701 uiEventListener =
nullptr;
4702 editorBeingDeleted (getActiveEditor());
4705 InstanceWithSupports* getInstanceWithSupports()
const override
4707 return instance.get();
4710 void applyStateWithAppropriateLocking (PluginState&& state, ConcurrentWithAudioCallback concurrent)
4712 PortMap portStateManager (instance->ports);
4716 if (hasThreadSafeRestore || concurrent == ConcurrentWithAudioCallback::no)
4718 state.restore (*instance, portStateManager);
4723 state.restore (*instance, portStateManager);
4726 parameterValues.updateFromControlPorts (controlPortStructure);
4727 asyncFullUiParameterUpdate.triggerAsyncUpdate();
4730 PluginState loadStateWithUri (
const String& str)
4732 auto mapFeature = instance->symap->getMapFeature();
4738 void connectPorts (AudioBuffer<float>& audio)
4743 for (
const auto& port : instance->ports.getAudioPorts())
4745 const auto channel = ioMap.getChannelForPort (
port.header.index);
4748 instance->instance.connectPort (
port.header.index, ptr);
4751 for (
const auto& port : instance->ports.getCvPorts())
4752 instance->instance.connectPort (
port.header.index,
nullptr);
4754 for (
auto& port : instance->ports.getAtomPorts())
4755 instance->instance.connectPort (
port.header.index,
port.data());
4758 void writeTimeInfoToPort (AtomPort& port)
4760 if (
port.header.direction != Port::Direction::input || !
port.getSupportsTime())
4763 auto* forge =
port.getForge().get();
4764 auto* playhead = getPlayHead();
4766 if (playhead ==
nullptr)
4770 const auto info = playhead->getPosition();
4772 if (!
info.hasValue())
4775 const auto& urids = instance->urids;
4779 lv2_shared::ObjectFrame
object { forge, (
uint32_t) 0, urids.mLV2_TIME__Position };
4784 if (
const auto samples =
info->getTimeInSamples())
4790 if (
const auto bar =
info->getBarCount())
4796 if (
const auto beat =
info->getPpqPosition())
4798 if (
const auto barStart =
info->getPpqPositionOfLastBarStart())
4808 if (
const auto sig =
info->getTimeSignature())
4817 if (
const auto bpm =
info->getBpm())
4824 void preparePortsForRun (AudioBuffer<float>& audio, MidiBuffer& midiBuffer)
4826 connectPorts (audio);
4828 for (
auto& port : instance->ports.getAtomPorts())
4830 switch (
port.header.direction)
4832 case Port::Direction::input:
4833 port.beginSequence();
4836 case Port::Direction::output:
4837 port.replaceWithChunk();
4840 case Port::Direction::unknown:
4846 for (
auto& port : instance->ports.getAtomPorts())
4847 writeTimeInfoToPort (port);
4849 const auto controlPortForge = controlPort !=
nullptr ? controlPort->getForge().get()
4852 parameterValues.postChangedParametersToProcessor (getParameterWriterUrids(), controlPortForge);
4854 instance->uiToProcessor.readAllAndClear ([
this] (MessageHeader header,
uint32_t size,
const void* buffer)
4856 pushMessage (header,
size, buffer);
4859 for (
auto& port : instance->ports.getAtomPorts())
4861 if (
port.header.direction == Port::Direction::input)
4863 for (
const auto meta : midiBuffer)
4865 port.addEventToSequence (meta.samplePosition,
4866 instance->urids.mLV2_MIDI__MidiEvent,
4867 static_cast<uint32_t> (meta.numBytes),
4875 if (freeWheelingPort !=
nullptr)
4876 freeWheelingPort->currentValue = isNonRealtime() ? freeWheelingPort->info.max
4877 : freeWheelingPort->info.min;
4884 if (header.protocol == 0 || header.protocol == instance->urids.mLV2_UI__floatProtocol)
4886 const auto value = readUnaligned<float> (
data);
4888 if (
auto* param = parameterValues.getParamByPortIndex (header.portIndex))
4890 param->setDenormalisedValue (
value);
4892 else if (
auto* port = controlPortStructure.getControlPortByIndex (header.portIndex))
4898 else if (
auto* atomPort = header.portIndex < atomPorts.size() ? atomPorts[header.portIndex] :
nullptr)
4900 if (header.protocol == instance->urids.mLV2_ATOM__eventTransfer)
4902 if (
const auto* atom = convertToAtomPtr (
data, (
size_t)
size))
4904 atomPort->addAtomToSequence (0, atom);
4907 if (atom->
type == instance->urids.mLV2_ATOM__Object)
4908 patchSetHelper.processPatchSet (
reinterpret_cast<const LV2_Atom_Object*
> (
data), PatchSetCallback { parameterValues });
4911 else if (header.protocol == instance->urids.mLV2_ATOM__atomTransfer)
4913 if (
const auto* atom = convertToAtomPtr (
data, (
size_t)
size))
4914 atomPort->replaceBufferWithAtom (atom);
4919 void processPortsAfterRun (MidiBuffer& midi)
4923 for (
auto& port : instance->ports.getAtomPorts())
4924 processAtomPort (port, midi);
4926 if (latencyPort !=
nullptr)
4927 setLatencySamples ((
int) latencyPort->currentValue);
4930 void processAtomPort (
const AtomPort& port, MidiBuffer& midi)
4932 if (
port.header.direction != Port::Direction::output)
4936 const auto* atom =
reinterpret_cast<const LV2_Atom*
> (
port.data());
4938 if (atom->
type != instance->urids.mLV2_ATOM__Sequence)
4942 const auto* sequence =
reinterpret_cast<const LV2_Atom_Sequence*
> (
port.data());
4945 jassert (sequence->body.unit == 0 || sequence->body.unit == instance->urids.mLV2_UNITS__frame);
4947 for (
const auto* event : lv2_shared::SequenceIterator { lv2_shared::SequenceWithSize { sequence } })
4950 instance->processorToUi->pushMessage ({ uiEventListener, {
port.header.index, instance->urids.mLV2_ATOM__eventTransfer } },
4951 (
uint32_t) (
event->body.size +
sizeof (LV2_Atom)),
4954 if (event->body.type == instance->urids.mLV2_MIDI__MidiEvent)
4955 midi.
addEvent (event + 1,
static_cast<int> (event->body.size),
static_cast<int> (event->time.frames));
4958 if (
reinterpret_cast<const LV2_Atom_Object_Body*
> (event + 1)->otype == instance->urids.mLV2_STATE__StateChanged)
4959 updateHostDisplay (ChangeDetails{}.withNonParameterStateChanged (
true));
4961 patchSetHelper.processPatchSet (event, PatchSetCallback { parameterValues });
4967 static std::set<lv2_shared::SinglePortInfo> validateAndRedesignatePorts (std::set<lv2_shared::SinglePortInfo>
info)
4969 const auto channelSet = lv2_shared::ParsedGroup::getEquivalentSet (
info);
4971 if ((
int)
info.size() == channelSet.size())
4974 std::set<lv2_shared::SinglePortInfo>
result;
4975 auto designation = (
int) AudioChannelSet::discreteChannel0;
4977 for (
auto& item :
info)
4980 copy.designation = (AudioChannelSet::ChannelType) designation++;
4987 static AudioChannelSet::ChannelType getPortDesignation (World&
world,
const Port& port,
size_t indexInGroup)
4989 const auto defaultResult = (AudioChannelSet::ChannelType) (AudioChannelSet::discreteChannel0 + indexInGroup);
4992 if (node ==
nullptr)
4993 return defaultResult;
4995 const auto it = lv2_shared::channelDesignationMap.find (lilvNodeToUriString (node.get()));
4997 if (it == lv2_shared::channelDesignationMap.
end())
4998 return defaultResult;
5003 static lv2_shared::ParsedBuses getParsedBuses (World&
world,
const Plugin&
p,
const UsefulUris&
uris)
5008 std::map<String, std::set<lv2_shared::SinglePortInfo>> inputGroups, outputGroups;
5009 std::set<lv2_shared::SinglePortInfo> ungroupedInputs, ungroupedOutputs;
5011 for (
uint32_t i = 0, numPorts =
p.getNumPorts();
i < numPorts; ++
i)
5013 const auto port =
p.getPortByIndex (
i);
5015 if (
port.getKind (
uris) != Port::Kind::audio)
5018 const auto groupUri = lilvNodeToUriString (
port.get (groupPropertyUri.get()).get());
5020 auto& set = [&]() ->
auto&
5022 if (groupUri.isEmpty())
5023 return port.getDirection (
uris) == Port::Direction::input ? ungroupedInputs : ungroupedOutputs;
5025 auto&
group =
port.getDirection (
uris) == Port::Direction::input ? inputGroups : outputGroups;
5026 return group[groupUri];
5029 set.insert ({
port.getIndex(), getPortDesignation (
world, port, set.size()),
port.hasProperty (optionalUri) });
5032 for (
auto* groups : { &inputGroups, &outputGroups })
5033 for (
auto& pair : *groups)
5034 pair.second = validateAndRedesignatePorts (std::move (pair.second));
5037 const auto getMainGroupName = [&] (
const char* propertyName)
5039 for (
const auto* item :
p.getValue (
world.newUri (propertyName).get()))
5040 return lilvNodeToUriString (item);
5050 static String getNameForUri (World&
world, StringRef
uri)
5059 if (node ==
nullptr)
5065 static BusesProperties getBusesProperties (
const lv2_shared::ParsedBuses& parsedBuses, World&
world)
5069 for (
const auto& pair : { std::make_tuple (&parsedBuses.inputs, &
result.inputLayouts),
5070 std::make_tuple (&parsedBuses.outputs, &
result.outputLayouts) })
5072 const auto& buses = *std::get<0> (pair);
5073 auto& layout = *std::get<1> (pair);
5075 for (
const auto& bus : buses)
5077 layout.add (AudioProcessor::BusProperties { getNameForUri (
world, bus.uid),
5078 bus.getEquivalentSet(),
5079 bus.isRequired() });
5086 LV2_URID map (
const char* str)
const
5088 return instance !=
nullptr ? instance->symap->map (str)
5092 ControlPort* findControlPortWithIndex (
uint32_t index)
const
5094 auto ports = instance->ports.getControlPorts();
5095 const auto indexMatches = [&] (
const ControlPort&
p) {
return p.header.index == index; };
5098 return it !=
ports.
end() ? &(*it) :
nullptr;
5101 const lv2_shared::ParsedBuses declaredBusLayout;
5102 lv2_shared::PortToAudioBufferMap ioMap { getBusesLayout(), declaredBusLayout };
5103 std::shared_ptr<World>
world;
5105 PluginDescription description;
5106 std::vector<String> presetUris;
5107 std::unique_ptr<InstanceWithSupports> instance;
5108 AsyncFn asyncFullUiParameterUpdate { [
this] { postAllParametersToUi(); } };
5110 std::vector<AtomPort*> atomPorts = getPortPointers (instance->ports.getAtomPorts());
5112 AtomPort*
const controlPort = [&]() -> AtomPort*
5117 if (!
port.isValid())
5120 const auto index =
port.getIndex();
5122 if (! isPositiveAndBelow (index, atomPorts.size()))
5125 return atomPorts[index];
5128 ControlPort*
const latencyPort = [&]() -> ControlPort*
5130 if (! plugin.hasLatency())
5133 return findControlPortWithIndex (plugin.getLatencyPortIndex());
5136 ControlPort*
const freeWheelingPort = [&]() -> ControlPort*
5141 if (!
port.isValid())
5144 return findControlPortWithIndex (
port.getIndex());
5147 ControlPort*
const enabledPort = [&]() -> ControlPort*
5152 if (!
port.isValid())
5155 return findControlPortWithIndex (
port.getIndex());
5158 lv2_shared::PatchSetHelper patchSetHelper { instance->symap->getMapFeature(), plugin.getUri().getTyped() };
5159 ControlPortAccelerationStructure controlPortStructure { instance->ports.getControlPorts() };
5160 ParameterValueCache parameterValues { *
this,
5162 instance->symap->getMapFeature(),
5163 getJuceParameterInfo (*
world,
5166 { latencyPort, freeWheelingPort },
5167 instance->ports.getControlPorts(),
5168 controlPort !=
nullptr ? controlPort->header.index : 0),
5170 LV2Parameter* bypassParam = enabledPort !=
nullptr ? parameterValues.getParamByPortIndex (enabledPort->header.index)
5173 std::atomic<UiEventListener*> uiEventListener {
nullptr };
5174 OptionalEditor<> optionalEditor;
5175 int lastAppliedPreset = 0;
5177 bool active {
false };
5185class LV2PluginFormat::Pimpl
5192 const auto tempFile = lv2ResourceFolder.getFile();
5194 if (tempFile.createDirectory())
5196 for (
const auto& bundle : lv2::Bundle::getAllBundles())
5198 const auto pathToBundle = tempFile.getChildFile (bundle.name + String (
".lv2"));
5200 if (! pathToBundle.createDirectory())
5203 for (
const auto& resource : bundle.contents)
5204 pathToBundle.getChildFile (resource.name).replaceWithText (resource.contents);
5207 world->loadBundle (
world->newFileUri (
nullptr, pathString.toRawUTF8()));
5214 lv2ResourceFolder.getFile().deleteRecursively();
5217 void findAllTypesForFile (OwnedArray<PluginDescription>&
result,
5218 const String& identifier)
5220 auto desc = getDescription (findPluginByUri (identifier));
5222 if (desc.fileOrIdentifier.isNotEmpty())
5223 result.add (std::make_unique<PluginDescription> (desc));
5226 bool fileMightContainThisPluginType (
const String&
file)
const
5229 const auto*
data =
file.toRawUTF8();
5230 const auto numBytes =
file.getNumBytesAsUTF8();
5231 std::vector<uint8_t> vec (numBytes + 1, 0);
5232 std::copy (
data,
data + numBytes, vec.begin());
5236 String getNameOfPluginFromIdentifier (
const String& identifier)
5243 bool pluginNeedsRescanning (
const PluginDescription&)
5248 bool doesPluginStillExist (
const PluginDescription& description)
5250 return findPluginByUri (description.fileOrIdentifier) !=
nullptr;
5253 StringArray searchPathsForPlugins (
const FileSearchPath&,
bool,
bool)
5259 for (
const auto* plugin :
world->getAllPlugins())
5260 result.add (lv2_host::Plugin { plugin }.getUri().getTyped());
5265 FileSearchPath getDefaultLocationsToSearch() {
return {}; }
5267 const LilvUI* findEmbeddableUi (
const lv2_host::Uis* pluginUis, std::true_type)
5269 if (pluginUis ==
nullptr)
5272 const std::vector<const LilvUI*> allUis (pluginUis->begin(), pluginUis->end());
5277 constexpr const char* rawUri =
5282 #elif JUCE_LINUX || JUCE_BSD
5289 const auto nativeUiUri =
world->newUri (rawUri);
5291 struct UiWithSuitability
5294 unsigned suitability;
5296 bool operator< (
const UiWithSuitability& other)
const noexcept
5298 return suitability < other.suitability;
5301 static unsigned uiIsSupported (
const char* hostUri,
const char* pluginUri)
5303 if (strcmp (hostUri, pluginUri) == 0)
5310 std::vector<UiWithSuitability> uisWithSuitability;
5311 uisWithSuitability.reserve (allUis.size());
5313 std::transform (allUis.cbegin(), allUis.cend(), std::back_inserter (uisWithSuitability), [&] (
const LilvUI*
ui)
5315 const LilvNode* type = nullptr;
5316 return UiWithSuitability { ui, lilv_ui_is_supported (ui, UiWithSuitability::uiIsSupported, nativeUiUri.get(), &type) };
5319 std::sort (uisWithSuitability.begin(), uisWithSuitability.end());
5321 if (uisWithSuitability.back().suitability != 0)
5322 return uisWithSuitability.back().ui;
5327 const LilvUI* findEmbeddableUi (
const lv2_host::Uis*, std::false_type)
5332 const LilvUI* findEmbeddableUi (
const lv2_host::Uis* pluginUis)
5334 return findEmbeddableUi (pluginUis, std::integral_constant<bool, lv2_host::editorFunctionalityEnabled>{});
5337 static lv2_host::UiDescriptor getUiDescriptor (
const LilvUI*
ui)
5344 return lv2_host::UiDescriptor { lv2_host::UiDescriptorArgs{}.withLibraryPath (libraryFile.get())
5349 template <
typename RequiredFeatures,
typename AvailableFeatures>
5350 static std::vector<String> findMissingFeatures (RequiredFeatures&& required,
5351 AvailableFeatures&& available)
5353 std::vector<String>
result;
5355 for (
const auto* node : required)
5359 if (std::find (std::begin (available), std::end (available), nodeString) == std::end (available))
5360 result.push_back (nodeString);
5366 void createPluginInstance (
const PluginDescription& desc,
5367 double initialSampleRate,
5368 int initialBufferSize,
5371 const auto*
pluginPtr = findPluginByUri (desc.fileOrIdentifier);
5374 return callback (
nullptr,
"Unable to locate plugin with the requested URI");
5376 const lv2_host::Plugin plugin {
pluginPtr };
5378 auto symap = std::make_unique<lv2_host::SymbolMap>();
5380 const auto missingFeatures = findMissingFeatures (plugin.getRequiredFeatures(),
5381 lv2_host::FeaturesData::getFeatureUris());
5383 if (! missingFeatures.empty())
5385 const auto missingFeaturesString = StringArray (missingFeatures.data(), (
int) missingFeatures.size()).joinIntoString (
", ");
5387 return callback (
nullptr,
"plugin requires missing features: " + missingFeaturesString);
5390 auto stateToApply = [&]
5393 return lv2_host::PluginState{};
5395 auto map = symap->getMapFeature();
5399 auto ports = lv2_host::Ports::getPorts (*
world,
uris, plugin, *symap);
5401 if (!
ports.hasValue())
5402 return callback (
nullptr,
"Plugin has ports of an unsupported type");
5404 auto instance = std::make_unique<lv2_host::InstanceWithSupports> (*
world,
5411 if (instance->instance ==
nullptr)
5412 return callback (
nullptr,
"Plugin was located, but could not be opened");
5414 auto potentialPresets =
world->findNodes (
nullptr,
5416 plugin.getUri().get());
5418 const lv2_host::Uis pluginUis { plugin.get() };
5420 const auto uiToUse = [&]() ->
const LilvUI*
5422 const auto bestMatch = findEmbeddableUi (&pluginUis);
5424 if (bestMatch ==
nullptr)
5430 const auto queryUi = [&] (
const char* featureUri)
5432 const auto featureUriNode =
world->newUri (featureUri);
5433 return world->findNodes (uiUri, featureUriNode.get(),
nullptr);
5437 lv2_host::UiFeaturesData::getFeatureUris());
5439 return missingUiFeatures.empty() ? bestMatch :
nullptr;
5445 auto wrapped = std::make_unique<lv2_host::LV2AudioPluginInstance> (
world,
5448 std::move (instance),
5450 findPresetUrisForPlugin (plugin.get()),
5451 std::move (stateToApply),
5452 std::move (uiBundleUri),
5453 getUiDescriptor (uiToUse));
5454 callback (std::move (wrapped), {});
5458 struct Free {
void operator() (
char* ptr)
const noexcept { free (ptr); } };
5459 using StringPtr = std::unique_ptr<char, Free>;
5461 const LilvPlugin* findPluginByUri (
const String&
s)
5463 return world->getAllPlugins().getByUri (
world->newUri (
s.toRawUTF8()));
5466 template <
typename Fn>
5472 const lv2_host::PluginClass wrapped {
c };
5475 const auto parentUri = wrapped.getParentUri();
5477 if (parentUri.get() !=
nullptr)
5478 visitParentClasses (
world->getPluginClasses().getByUri (parentUri),
fn);
5481 std::vector<lv2_host::NodeUri> collectPluginClassUris (
const LilvPluginClass*
c)
const
5483 std::vector<lv2_host::NodeUri> results;
5485 visitParentClasses (
c, [&results] (
const lv2_host::PluginClass& wrapped)
5487 results.emplace_back (wrapped.getUri());
5493 PluginDescription getDescription (
const LilvPlugin* plugin)
5495 if (plugin ==
nullptr)
5498 const auto wrapped = lv2_host::Plugin { plugin };
5499 const auto bundle = wrapped.getBundleUri().getTyped();
5500 const auto bundleFile = File { StringPtr {
lilv_file_uri_parse (bundle,
nullptr) }.get() };
5502 const auto numInputs = wrapped.getNumPortsOfClass (
uris.mLV2_CORE__AudioPort,
uris.mLV2_CORE__InputPort);
5503 const auto numOutputs = wrapped.getNumPortsOfClass (
uris.mLV2_CORE__AudioPort,
uris.mLV2_CORE__OutputPort);
5505 PluginDescription
result;
5506 result.name = wrapped.getName().getTyped();
5507 result.descriptiveName = wrapped.getName().getTyped();
5508 result.lastFileModTime = bundleFile.getLastModificationTime();
5509 result.lastInfoUpdateTime = Time::getCurrentTime();
5510 result.manufacturerName = wrapped.getAuthorName().getTyped();
5511 result.pluginFormatName = LV2PluginFormat::getFormatName();
5512 result.numInputChannels =
static_cast<int> (numInputs);
5513 result.numOutputChannels =
static_cast<int> (numOutputs);
5515 const auto classPtr = wrapped.getClass();
5516 const auto classes = collectPluginClassUris (classPtr);
5517 const auto isInstrument = std::any_of (classes.cbegin(),
5519 [
this] (
const lv2_host::NodeUri&
uri)
5521 return uri.equals (uris.mLV2_CORE__GeneratorPlugin);
5524 result.category = lv2_host::PluginClass { classPtr }.getLabel().getTyped();
5525 result.isInstrument = isInstrument;
5528 result.fileOrIdentifier = wrapped.getUri().getTyped();
5530 const auto uid = DefaultHashFunctions::generateHash (
result.fileOrIdentifier, std::numeric_limits<int>::max());;
5535 std::vector<String> findPresetUrisForPlugin (
const LilvPlugin* plugin)
5537 std::vector<String> presetUris;
5541 for (
const auto* potentialPreset : potentialPresets)
5547 TemporaryFile lv2ResourceFolder;
5548 std::shared_ptr<lv2_host::World>
world = std::make_shared<lv2_host::World>();
5549 lv2_host::UsefulUris
uris {
world->get() };
5553LV2PluginFormat::LV2PluginFormat()
5554 : pimpl (std::make_unique<Pimpl>()) {}
5556LV2PluginFormat::~LV2PluginFormat() =
default;
5558void LV2PluginFormat::findAllTypesForFile (OwnedArray<PluginDescription>& results,
5559 const String& fileOrIdentifier)
5561 pimpl->findAllTypesForFile (results, fileOrIdentifier);
5564bool LV2PluginFormat::fileMightContainThisPluginType (
const String& fileOrIdentifier)
5566 return pimpl->fileMightContainThisPluginType (fileOrIdentifier);
5569String LV2PluginFormat::getNameOfPluginFromIdentifier (
const String& fileOrIdentifier)
5571 return pimpl->getNameOfPluginFromIdentifier (fileOrIdentifier);
5574bool LV2PluginFormat::pluginNeedsRescanning (
const PluginDescription& desc)
5576 return pimpl->pluginNeedsRescanning (desc);
5579bool LV2PluginFormat::doesPluginStillExist (
const PluginDescription& desc)
5581 return pimpl->doesPluginStillExist (desc);
5584bool LV2PluginFormat::canScanForPlugins()
const {
return true; }
5585bool LV2PluginFormat::isTrivialToScan()
const {
return true; }
5587StringArray LV2PluginFormat::searchPathsForPlugins (
const FileSearchPath& directoriesToSearch,
5591 return pimpl->searchPathsForPlugins (directoriesToSearch, recursive, allowAsync);
5594FileSearchPath LV2PluginFormat::getDefaultLocationsToSearch()
5596 return pimpl->getDefaultLocationsToSearch();
5599bool LV2PluginFormat::requiresUnblockedMessageThreadDuringCreation (
const PluginDescription&)
const
5604void LV2PluginFormat::createPluginInstance (
const PluginDescription& desc,
5609 pimpl->createPluginInstance (desc, sampleRate, bufferSize, std::move (
callback));
#define juce
Definition AppConfig.h:25
#define copy(x)
Definition ADnoteParameters.cpp:1011
#define constexpr
Definition CarlaDefines.h:94
Type jmax(const Type a, const Type b)
Definition MathsFunctions.h:48
Direction
Definition CarlaStyle.cpp:109
class MasterUI * ui
Definition Connection.cpp:39
Controller controller
Definition main.C:5
pthread_mutex_t mutex
Definition Controller.C:6
#define noexcept
Definition DistrhoDefines.h:72
#define nullptr
Definition DistrhoDefines.h:75
static Audio_Scope * scope
Definition player.cpp:26
uint8_t a
Definition Spc_Cpu.h:141
CAdPlugDatabase::CRecord::RecordType type
Definition adplugdb.cpp:93
static void message(int level, const char *fmt,...)
Definition adplugdb.cpp:120
event_queue * push(event_queue *queue, event_queue *event)
Definition allegrosmfwr.cpp:114
static char ** uris
Definition atom-test-utils.c:27
static uint8_t unmap(const uint8_t in)
Definition base64.c:94
static const LV2_Descriptor descriptor
Definition bindings_test_plugin.c:165
static void run(LV2_Handle instance, uint32_t n_samples)
Definition bindings_test_plugin.c:112
static void deactivate(LV2_Handle instance)
Definition bindings_test_plugin.c:128
static HINSTANCE getCurrentModuleInstanceHandle() noexcept
Definition carla-vst-export-bridged.cpp:35
#define pluginPtr
Definition carla-vst.cpp:950
static String addTrailingSeparator(const String &path)
Definition File.cpp:225
const String & getFullPathName() const noexcept
Definition File.h:152
size_t getSize() const noexcept
Definition MemoryBlock.h:102
void * getData() const noexcept
Definition MemoryBlock.h:91
void addEvent(const MidiMessage &midiMessage, int sampleNumber)
Definition MidiBuffer.cpp:118
void clear() noexcept
Definition MidiBuffer.cpp:106
Definition StringArray.h:41
const char * toRawUTF8() const
Definition String.cpp:1925
static String fromUTF8(const char *utf8buffer, int bufferSizeBytes=-1)
Definition String.cpp:1961
const char * toRawUTF8() const
Definition String.cpp:1925
* e
Definition inflate.c:1404
int * l
Definition inflate.c:1579
unsigned * m
Definition inflate.c:1559
struct huft * t
Definition inflate.c:943
unsigned v[N_MAX]
Definition inflate.c:1584
unsigned d
Definition inflate.c:940
int g
Definition inflate.c:1573
struct huft * u[BMAX]
Definition inflate.c:1583
register unsigned i
Definition inflate.c:1575
unsigned s
Definition inflate.c:1555
unsigned x[BMAX+1]
Definition inflate.c:1586
unsigned f
Definition inflate.c:1572
static Wave_Writer * ww
Definition Wave_Writer.cpp:166
#define LV2_ATOM__Object
http://lv2plug.in/ns/ext/atom#Object
Definition atom.h:47
#define LV2_ATOM__AtomPort
http://lv2plug.in/ns/ext/atom#AtomPort
Definition atom.h:36
#define LV2_ATOM__Float
http://lv2plug.in/ns/ext/atom#Float
Definition atom.h:42
#define LV2_ATOM__beatTime
http://lv2plug.in/ns/ext/atom#beatTime
Definition atom.h:59
#define LV2_ATOM__Int
http://lv2plug.in/ns/ext/atom#Int
Definition atom.h:43
#define LV2_ATOM__atomTransfer
http://lv2plug.in/ns/ext/atom#atomTransfer
Definition atom.h:58
#define LV2_ATOM__frameTime
http://lv2plug.in/ns/ext/atom#frameTime
Definition atom.h:63
#define LV2_ATOM__Double
http://lv2plug.in/ns/ext/atom#Double
Definition atom.h:40
#define LV2_ATOM__Bool
http://lv2plug.in/ns/ext/atom#Bool
Definition atom.h:38
#define LV2_ATOM__Sequence
http://lv2plug.in/ns/ext/atom#Sequence
Definition atom.h:51
#define LV2_ATOM__Long
http://lv2plug.in/ns/ext/atom#Long
Definition atom.h:45
#define LV2_ATOM__eventTransfer
http://lv2plug.in/ns/ext/atom#eventTransfer
Definition atom.h:62
#define LV2_BUF_SIZE__minBlockLength
http://lv2plug.in/ns/ext/buf-size#minBlockLength
Definition buf-size.h:35
#define LV2_BUF_SIZE__sequenceSize
http://lv2plug.in/ns/ext/buf-size#sequenceSize
Definition buf-size.h:38
#define LV2_BUF_SIZE__maxBlockLength
http://lv2plug.in/ns/ext/buf-size#maxBlockLength
Definition buf-size.h:34
#define LV2_BUF_SIZE__boundedBlockLength
http://lv2plug.in/ns/ext/buf-size#boundedBlockLength
Definition buf-size.h:32
#define LV2_DATA_ACCESS_URI
http://lv2plug.in/ns/ext/data-access
Definition data-access.h:30
static PuglViewHint int value
Definition pugl.h:1708
static const char * name
Definition pugl.h:1582
static int int height
Definition pugl.h:1594
static int width
Definition pugl.h:1593
static uintptr_t parent
Definition pugl.h:1644
static LV2_Atom_Forge_Ref lv2_atom_forge_int(LV2_Atom_Forge *forge, int32_t val)
Definition atom-forge.h:374
static LV2_Atom_Forge_Ref lv2_atom_forge_bool(LV2_Atom_Forge *forge, bool val)
Definition atom-forge.h:406
static LV2_Atom_Forge_Ref lv2_atom_forge_long(LV2_Atom_Forge *forge, int64_t val)
Definition atom-forge.h:382
static LV2_Atom_Forge_Ref lv2_atom_forge_sequence_head(LV2_Atom_Forge *forge, LV2_Atom_Forge_Frame *frame, uint32_t unit)
Definition atom-forge.h:661
static bool lv2_atom_forge_is_object_type(const LV2_Atom_Forge *forge, uint32_t type)
Definition atom-forge.h:217
static LV2_Atom_Forge_Ref lv2_atom_forge_raw(LV2_Atom_Forge *forge, const void *data, uint32_t size)
Definition atom-forge.h:293
static LV2_Atom_Forge_Ref lv2_atom_forge_urid(LV2_Atom_Forge *forge, LV2_URID id)
Definition atom-forge.h:414
static LV2_Atom_Forge_Ref lv2_atom_forge_write(LV2_Atom_Forge *forge, const void *data, uint32_t size)
Definition atom-forge.h:324
static LV2_Atom_Forge_Ref lv2_atom_forge_double(LV2_Atom_Forge *forge, double val)
Definition atom-forge.h:398
static void lv2_atom_forge_pop(LV2_Atom_Forge *forge, LV2_Atom_Forge_Frame *frame)
Definition atom-forge.h:201
struct _LV2_Atom_Forge_Frame LV2_Atom_Forge_Frame
static LV2_Atom_Forge_Ref lv2_atom_forge_key(LV2_Atom_Forge *forge, LV2_URID key)
Definition atom-forge.h:635
static LV2_Atom_Forge_Ref lv2_atom_forge_atom(LV2_Atom_Forge *forge, uint32_t size, uint32_t type)
Definition atom-forge.h:354
static LV2_Atom_Forge_Ref lv2_atom_forge_frame_time(LV2_Atom_Forge *forge, int64_t frames)
Definition atom-forge.h:679
static LV2_Atom_Forge_Ref lv2_atom_forge_float(LV2_Atom_Forge *forge, float val)
Definition atom-forge.h:390
#define LV2_INSTANCE_ACCESS_URI
http://lv2plug.in/ns/ext/instance-access
Definition instance-access.h:30
LILV_API const LilvNode * lilv_plugin_class_get_label(const LilvPluginClass *plugin_class)
Definition pluginclass.c:67
LILV_API const LilvNode * lilv_plugin_class_get_uri(const LilvPluginClass *plugin_class)
Definition pluginclass.c:61
LILV_API LilvPluginClasses * lilv_plugin_class_get_children(const LilvPluginClass *plugin_class)
Definition pluginclass.c:73
LILV_API const LilvNode * lilv_plugin_class_get_parent_uri(const LilvPluginClass *plugin_class)
Definition pluginclass.c:55
LILV_API unsigned lilv_plugin_classes_size(const LilvPluginClasses *collection)
LILV_API const LilvUI * lilv_uis_get(const LilvUIs *collection, LilvIter *i)
LILV_API LilvIter * lilv_scale_points_next(const LilvScalePoints *collection, LilvIter *i)
LILV_API LilvIter * lilv_plugin_classes_begin(const LilvPluginClasses *collection)
LILV_API const LilvPluginClass * lilv_plugin_classes_get_by_uri(const LilvPluginClasses *classes, const LilvNode *uri)
Definition collections.c:115
LILV_API unsigned lilv_uis_size(const LilvUIs *collection)
LILV_API void lilv_plugin_classes_free(LilvPluginClasses *collection)
Definition collections.c:212
LILV_API bool lilv_scale_points_is_end(const LilvScalePoints *collection, LilvIter *i)
LILV_API LilvIter * lilv_uis_begin(const LilvUIs *collection)
LILV_API LilvIter * lilv_nodes_begin(const LilvNodes *collection)
LILV_API LilvIter * lilv_uis_next(const LilvUIs *collection, LilvIter *i)
LILV_API const LilvPlugin * lilv_plugins_get_by_uri(const LilvPlugins *plugins, const LilvNode *uri)
Definition collections.c:137
LILV_API bool lilv_plugin_classes_is_end(const LilvPluginClasses *collection, LilvIter *i)
LILV_API LilvIter * lilv_plugins_next(const LilvPlugins *collection, LilvIter *i)
LILV_API const LilvPlugin * lilv_plugins_get(const LilvPlugins *collection, LilvIter *i)
LILV_API LilvIter * lilv_plugin_classes_next(const LilvPluginClasses *collection, LilvIter *i)
LILV_API void lilv_uis_free(LilvUIs *collection)
Definition collections.c:224
LILV_API unsigned lilv_plugins_size(const LilvPlugins *collection)
LILV_API const LilvScalePoint * lilv_scale_points_get(const LilvScalePoints *collection, LilvIter *i)
LILV_API const LilvUI * lilv_uis_get_by_uri(const LilvUIs *uis, const LilvNode *uri)
Definition collections.c:123
LILV_API bool lilv_uis_is_end(const LilvUIs *collection, LilvIter *i)
LILV_API bool lilv_plugins_is_end(const LilvPlugins *collection, LilvIter *i)
LILV_API bool lilv_nodes_is_end(const LilvNodes *collection, LilvIter *i)
LILV_API LilvIter * lilv_nodes_next(const LilvNodes *collection, LilvIter *i)
LILV_API void lilv_nodes_free(LilvNodes *collection)
Definition collections.c:230
LILV_API const LilvNode * lilv_nodes_get(const LilvNodes *collection, LilvIter *i)
LILV_API const LilvPluginClass * lilv_plugin_classes_get(const LilvPluginClasses *collection, LilvIter *i)
LILV_API LilvIter * lilv_scale_points_begin(const LilvScalePoints *collection)
LILV_API unsigned lilv_nodes_size(const LilvNodes *collection)
LILV_API LilvIter * lilv_plugins_begin(const LilvPlugins *collection)
static void lilv_instance_connect_port(LilvInstance *instance, uint32_t port_index, void *data_location)
Definition lilv.h:1916
static const char * lilv_instance_get_uri(const LilvInstance *instance)
Definition lilv.h:1904
static const void * lilv_instance_get_extension_data(const LilvInstance *instance, const char *uri)
Definition lilv.h:1972
LILV_API LilvInstance * lilv_plugin_instantiate(const LilvPlugin *plugin, double sample_rate, const LV2_Feature *const *features)
Definition instance.c:30
static void lilv_instance_run(LilvInstance *instance, uint32_t sample_count)
Definition lilv.h:1946
static void lilv_instance_deactivate(LilvInstance *instance)
Definition lilv.h:1958
static LV2_Handle lilv_instance_get_handle(const LilvInstance *instance)
Definition lilv.h:2004
LILV_API void lilv_instance_free(LilvInstance *instance)
Definition instance.c:104
static void lilv_instance_activate(LilvInstance *instance)
Definition lilv.h:1932
LILV_API bool lilv_node_is_string(const LilvNode *value)
Definition node.c:351
LILV_API LilvNode * lilv_new_uri(LilvWorld *world, const char *uri)
Definition node.c:155
LILV_API LilvNode * lilv_new_file_uri(LilvWorld *world, const char *host, const char *path)
Definition node.c:161
LILV_API int lilv_node_as_int(const LilvNode *value)
Definition node.c:369
LILV_API bool lilv_node_equals(const LilvNode *value, const LilvNode *other)
Definition node.c:238
LILV_API LilvNode * lilv_new_string(LilvWorld *world, const char *str)
Definition node.c:174
LILV_API bool lilv_node_is_float(const LilvNode *value)
Definition node.c:375
LILV_API const char * lilv_node_as_string(const LilvNode *value)
Definition node.c:357
LILV_API float lilv_node_as_float(const LilvNode *value)
Definition node.c:381
LILV_API const char * lilv_node_as_uri(const LilvNode *value)
Definition node.c:311
LILV_API char * lilv_file_uri_parse(const char *uri, char **hostname)
Definition util.c:106
LILV_API LilvNode * lilv_node_duplicate(const LilvNode *val)
Definition node.c:214
LILV_API bool lilv_node_is_int(const LilvNode *value)
Definition node.c:363
LILV_API void lilv_node_free(LilvNode *val)
Definition node.c:229
LILV_API bool lilv_node_is_uri(const LilvNode *value)
Definition node.c:305
LILV_API LilvNodes * lilv_plugin_get_value(const LilvPlugin *plugin, const LilvNode *predicate)
Definition plugin.c:521
LILV_API LilvNodes * lilv_plugin_get_required_features(const LilvPlugin *plugin)
Definition plugin.c:787
LILV_API const LilvNode * lilv_plugin_get_bundle_uri(const LilvPlugin *plugin)
Definition plugin.c:379
LILV_API LilvNode * lilv_plugin_get_author_name(const LilvPlugin *plugin)
Definition plugin.c:922
LILV_API bool lilv_plugin_has_latency(const LilvPlugin *plugin)
Definition plugin.c:637
LILV_API const LilvNode * lilv_plugin_get_uri(const LilvPlugin *plugin)
Definition plugin.c:373
LILV_API bool lilv_plugin_has_feature(const LilvPlugin *plugin, const LilvNode *feature)
Definition plugin.c:749
LILV_API const LilvPort * lilv_plugin_get_port_by_designation(const LilvPlugin *plugin, const LilvNode *port_class, const LilvNode *designation)
Definition plugin.c:699
LILV_API bool lilv_plugin_has_extension_data(const LilvPlugin *plugin, const LilvNode *uri)
Definition plugin.c:797
LILV_API const LilvPluginClass * lilv_plugin_get_class(const LilvPlugin *plugin)
Definition plugin.c:418
LILV_API uint32_t lilv_plugin_get_num_ports_of_class(const LilvPlugin *plugin, const LilvNode *class_1,...)
Definition plugin.c:623
LILV_API bool lilv_plugin_verify(const LilvPlugin *plugin)
Definition plugin.c:464
LILV_API uint32_t lilv_plugin_get_num_ports(const LilvPlugin *plugin)
Definition plugin.c:529
LILV_API const LilvNode * lilv_plugin_get_library_uri(const LilvPlugin *plugin)
Definition plugin.c:385
LILV_API LilvNodes * lilv_plugin_get_optional_features(const LilvPlugin *plugin)
Definition plugin.c:777
LILV_API LilvNodes * lilv_plugin_get_related(const LilvPlugin *plugin, const LilvNode *type)
Definition plugin.c:997
LILV_API LilvNode * lilv_plugin_get_name(const LilvPlugin *plugin)
Definition plugin.c:498
LILV_API uint32_t lilv_plugin_get_latency_port_index(const LilvPlugin *plugin)
Definition plugin.c:724
LILV_API const LilvPort * lilv_plugin_get_port_by_index(const LilvPlugin *plugin, uint32_t index)
Definition plugin.c:820
LILV_API const LilvNode * lilv_port_get_symbol(const LilvPlugin *plugin, const LilvPort *port)
Definition port.c:161
LILV_API LilvNodes * lilv_port_get_properties(const LilvPlugin *plugin, const LilvPort *port)
Definition port.c:265
LILV_API uint32_t lilv_port_get_index(const LilvPlugin *plugin, const LilvPort *port)
Definition port.c:153
LILV_API void lilv_port_get_range(const LilvPlugin *plugin, const LilvPort *port, LilvNode **def, LilvNode **min, LilvNode **max)
Definition port.c:200
LILV_API bool lilv_port_has_property(const LilvPlugin *plugin, const LilvPort *port, const LilvNode *property)
Definition port.c:77
LILV_API bool lilv_port_is_a(const LilvPlugin *plugin, const LilvPort *port, const LilvNode *port_class)
Definition port.c:61
LILV_API LilvNode * lilv_port_get_name(const LilvPlugin *plugin, const LilvPort *port)
Definition port.c:169
LILV_API LilvScalePoints * lilv_port_get_scale_points(const LilvPlugin *plugin, const LilvPort *port)
Definition port.c:232
LILV_API bool lilv_port_supports_event(const LilvPlugin *plugin, const LilvPort *port, const LilvNode *event_type)
Definition port.c:88
LILV_API LilvNode * lilv_port_get(const LilvPlugin *plugin, const LilvPort *port, const LilvNode *predicate)
Definition port.c:139
LILV_API const LilvNodes * lilv_port_get_classes(const LilvPlugin *plugin, const LilvPort *port)
Definition port.c:192
LILV_API const LilvNode * lilv_scale_point_get_label(const LilvScalePoint *point)
Definition scalepoint.c:50
LILV_API const LilvNode * lilv_scale_point_get_value(const LilvScalePoint *point)
Definition scalepoint.c:44
LILV_API LilvState * lilv_state_new_from_world(LilvWorld *world, LV2_URID_Map *map, const LilvNode *node)
Definition state.c:720
LILV_API LilvState * lilv_state_new_from_string(LilvWorld *world, LV2_URID_Map *map, const char *str)
Definition state.c:788
LILV_API LilvState * lilv_state_new_from_instance(const LilvPlugin *plugin, LilvInstance *instance, LV2_URID_Map *map, const char *scratch_dir, const char *copy_dir, const char *link_dir, const char *save_dir, LilvGetPortValueFunc get_value, void *user_data, uint32_t flags, const LV2_Feature *const *features)
Definition state.c:429
LILV_API void lilv_state_free(LilvState *state)
Definition state.c:1436
LILV_API const char * lilv_state_get_label(const LilvState *state)
Definition state.c:1518
LILV_API void lilv_state_set_label(LilvState *state, const char *label)
Definition state.c:1524
LILV_API void lilv_state_restore(const LilvState *state, LilvInstance *instance, LilvSetPortValueFunc set_value, void *user_data, uint32_t flags, const LV2_Feature *const *features)
Definition state.c:522
LILV_API char * lilv_state_to_string(LilvWorld *world, LV2_URID_Map *map, LV2_URID_Unmap *unmap, const LilvState *state, const char *uri, const char *base_uri)
Definition state.c:1280
LILV_API const LilvNode * lilv_ui_get_bundle_uri(const LilvUI *ui)
Definition ui.c:106
LILV_API const LilvNode * lilv_ui_get_binary_uri(const LilvUI *ui)
Definition ui.c:112
LILV_API LilvUIs * lilv_plugin_get_uis(const LilvPlugin *plugin)
Definition plugin.c:946
LILV_API const LilvNode * lilv_ui_get_uri(const LilvUI *ui)
Definition ui.c:66
LILV_API LilvNode * lilv_world_get(LilvWorld *world, const LilvNode *subject, const LilvNode *predicate, const LilvNode *object)
Definition world.c:242
LILV_API LilvNodes * lilv_world_find_nodes(LilvWorld *world, const LilvNode *subject, const LilvNode *predicate, const LilvNode *object)
Definition world.c:208
LILV_API void lilv_world_load_bundle(LilvWorld *world, const LilvNode *bundle_uri)
Definition world.c:741
LILV_API LilvWorld * lilv_world_new(void)
Definition world.c:45
LILV_API int lilv_world_load_resource(LilvWorld *world, const LilvNode *resource)
Definition world.c:1123
LILV_API void lilv_world_load_specifications(LilvWorld *world)
Definition world.c:1008
LILV_API void lilv_world_load_all(LilvWorld *world)
Definition world.c:1058
LILV_API void lilv_world_load_plugin_classes(LilvWorld *world)
Definition world.c:1019
LILV_API const LilvPluginClasses * lilv_world_get_plugin_classes(const LilvWorld *world)
Definition world.c:1192
LILV_API const LilvPlugins * lilv_world_get_all_plugins(const LilvWorld *world)
Definition world.c:1198
LILV_API void lilv_world_free(LilvWorld *world)
Definition world.c:129
LILV_API int lilv_world_unload_bundle(LilvWorld *world, const LilvNode *bundle_uri)
Definition world.c:898
LILV_API int lilv_world_unload_resource(LilvWorld *world, const LilvNode *resource)
Definition world.c:1154
LILV_API bool lilv_world_ask(LilvWorld *world, const LilvNode *subject, const LilvNode *predicate, const LilvNode *object)
Definition world.c:296
void LilvScalePoints
Definition lilv.h:95
struct LilvStateImpl LilvState
Definition lilv.h:90
void LilvPluginClasses
Definition lilv.h:93
void LilvNodes
Definition lilv.h:97
struct LilvUIImpl LilvUI
Definition lilv.h:86
LILV_API void lilv_free(void *ptr)
Definition util.c:37
struct LilvScalePointImpl LilvScalePoint
Definition lilv.h:85
struct LilvPortImpl LilvPort
Definition lilv.h:84
struct LilvWorldImpl LilvWorld
Definition lilv.h:88
struct LilvPluginClassImpl LilvPluginClass
Definition lilv.h:83
struct LilvPluginImpl LilvPlugin
Definition lilv.h:82
struct LilvInstanceImpl LilvInstance
Definition lilv.h:89
struct LilvNodeImpl LilvNode
Definition lilv.h:87
void LilvPlugins
Definition lilv.h:94
void LilvIter
Definition lilv.h:92
void LilvUIs
Definition lilv.h:96
#define LV2_LOG__Warning
http://lv2plug.in/ns/ext/log#Warning
Definition log.h:36
#define LV2_LOG__Error
http://lv2plug.in/ns/ext/log#Error
Definition log.h:33
struct _LV2_Log LV2_Log_Log
#define LV2_LOG__log
http://lv2plug.in/ns/ext/log#log
Definition log.h:37
void * LV2_Log_Handle
Definition log.h:59
#define LV2_LOG__Trace
http://lv2plug.in/ns/ext/log#Trace
Definition log.h:35
#define LV2_LOG__Note
http://lv2plug.in/ns/ext/log#Note
Definition log.h:34
#define LV2_CORE__integer
http://lv2plug.in/ns/lv2core#integer
Definition lv2.h:102
#define LV2_CORE__GeneratorPlugin
http://lv2plug.in/ns/lv2core#GeneratorPlugin
Definition lv2.h:61
#define LV2_CORE__minimum
http://lv2plug.in/ns/lv2core#minimum
Definition lv2.h:107
#define LV2_CORE__maximum
http://lv2plug.in/ns/lv2core#maximum
Definition lv2.h:105
#define LV2_CORE_PREFIX
http://lv2plug.in/ns/lv2core#
Definition lv2.h:35
#define LV2_CORE__freeWheeling
http://lv2plug.in/ns/lv2core#freeWheeling
Definition lv2.h:98
#define LV2_CORE__InputPort
http://lv2plug.in/ns/lv2core#InputPort
Definition lv2.h:63
#define LV2_CORE__symbol
http://lv2plug.in/ns/lv2core#symbol
Definition lv2.h:119
#define LV2_CORE__AudioPort
http://lv2plug.in/ns/lv2core#AudioPort
Definition lv2.h:40
#define LV2_CORE__control
http://lv2plug.in/ns/lv2core#control
Definition lv2.h:92
void * LV2_Handle
Definition lv2.h:133
#define LV2_CORE__portProperty
http://lv2plug.in/ns/lv2core#portProperty
Definition lv2.h:112
#define LV2_CORE__default
http://lv2plug.in/ns/lv2core#default
Definition lv2.h:93
#define LV2_CORE__InstrumentPlugin
http://lv2plug.in/ns/lv2core#InstrumentPlugin
Definition lv2.h:64
#define LV2_CORE__optionalFeature
http://lv2plug.in/ns/lv2core#optionalFeature
Definition lv2.h:110
#define LV2_CORE__toggled
http://lv2plug.in/ns/lv2core#toggled
Definition lv2.h:120
#define LV2_CORE__CVPort
http://lv2plug.in/ns/lv2core#CVPort
Definition lv2.h:42
#define LV2_CORE__scalePoint
http://lv2plug.in/ns/lv2core#scalePoint
Definition lv2.h:118
#define LV2_CORE__name
http://lv2plug.in/ns/lv2core#name
Definition lv2.h:109
#define LV2_CORE__designation
http://lv2plug.in/ns/lv2core#designation
Definition lv2.h:94
#define LV2_CORE__appliesTo
http://lv2plug.in/ns/lv2core#appliesTo
Definition lv2.h:89
#define LV2_CORE__connectionOptional
http://lv2plug.in/ns/lv2core#connectionOptional
Definition lv2.h:91
#define LV2_CORE__ControlPort
http://lv2plug.in/ns/lv2core#ControlPort
Definition lv2.h:47
#define LV2_CORE__enumeration
http://lv2plug.in/ns/lv2core#enumeration
Definition lv2.h:96
#define LV2_CORE__requiredFeature
http://lv2plug.in/ns/lv2core#requiredFeature
Definition lv2.h:116
#define LV2_CORE__extensionData
http://lv2plug.in/ns/lv2core#extensionData
Definition lv2.h:97
#define LV2_CORE__OutputPort
http://lv2plug.in/ns/lv2core#OutputPort
Definition lv2.h:71
struct _LV2_Feature LV2_Feature
#define LV2_MIDI__MidiEvent
http://lv2plug.in/ns/ext/midi#MidiEvent
Definition midi.h:48
struct _LV2_Options_Interface LV2_Options_Interface
#define LV2_OPTIONS__interface
http://lv2plug.in/ns/ext/options#interface
Definition options.h:38
struct _LV2_Options_Option LV2_Options_Option
#define LV2_OPTIONS__options
http://lv2plug.in/ns/ext/options#options
Definition options.h:39
@ LV2_OPTIONS_INSTANCE
Definition options.h:55
#define LV2_PARAMETERS__sampleRate
http://lv2plug.in/ns/ext/parameters#sampleRate
Definition parameters.h:51
#define LV2_PATCH__Set
http://lv2plug.in/ns/ext/patch#Set
Definition patch.h:47
#define LV2_PATCH__writable
http://lv2plug.in/ns/ext/patch#writable
Definition patch.h:60
#define LV2_PATCH__value
http://lv2plug.in/ns/ext/patch#value
Definition patch.h:58
#define LV2_PATCH__property
http://lv2plug.in/ns/ext/patch#property
Definition patch.h:52
#define LV2_PORT_GROUPS__mainInput
http://lv2plug.in/ns/ext/port-groups#mainInput
Definition port-groups.h:54
#define LV2_PORT_GROUPS__subGroupOf
http://lv2plug.in/ns/ext/port-groups#subGroupOf
Definition port-groups.h:65
#define LV2_PORT_GROUPS__OutputGroup
http://lv2plug.in/ns/ext/port-groups#OutputGroup
Definition port-groups.h:41
#define LV2_PORT_GROUPS__mainOutput
http://lv2plug.in/ns/ext/port-groups#mainOutput
Definition port-groups.h:55
#define LV2_PORT_GROUPS__Group
http://lv2plug.in/ns/ext/port-groups#Group
Definition port-groups.h:37
#define LV2_PORT_GROUPS__InputGroup
http://lv2plug.in/ns/ext/port-groups#InputGroup
Definition port-groups.h:38
#define LV2_PORT_GROUPS__group
http://lv2plug.in/ns/ext/port-groups#group
Definition port-groups.h:51
#define LV2_PRESETS__Preset
http://lv2plug.in/ns/ext/presets#Preset
Definition presets.h:32
#define LV2_RESIZE_PORT__resize
http://lv2plug.in/ns/ext/port#resize
Definition resize-port.h:36
#define LV2_RESIZE_PORT__minimumSize
http://lv2plug.in/ns/ext/port#minimumSize
Definition resize-port.h:35
LV2_Resize_Port_Status
Definition resize-port.h:45
void * LV2_Resize_Port_Feature_Data
Definition resize-port.h:52
@ LV2_RESIZE_PORT_ERR_UNKNOWN
Definition resize-port.h:47
@ LV2_RESIZE_PORT_SUCCESS
Definition resize-port.h:46
SERD_PURE_API bool serd_uri_string_has_scheme(const uint8_t *SERD_NULLABLE utf8)
Return true iff utf8 starts with a valid URI scheme.
#define LV2_STATE__loadDefaultState
http://lv2plug.in/ns/ext/state#loadDefaultState
Definition state.h:42
#define LV2_STATE__threadSafeRestore
http://lv2plug.in/ns/ext/state#threadSafeRestore
Definition state.h:47
#define LV2_STATE__StateChanged
http://lv2plug.in/ns/ext/state#StateChanged
Definition state.h:48
@ LV2_STATE_IS_PORTABLE
Definition state.h:89
@ LV2_STATE_IS_POD
Definition state.h:78
#define LV2_TIME__beat
http://lv2plug.in/ns/ext/time#beat
Definition time.h:41
#define LV2_TIME__frame
http://lv2plug.in/ns/ext/time#frame
Definition time.h:45
#define LV2_TIME__barBeat
http://lv2plug.in/ns/ext/time#barBeat
Definition time.h:39
#define LV2_TIME__Position
http://lv2plug.in/ns/ext/time#Position
Definition time.h:36
#define LV2_TIME__beatsPerMinute
http://lv2plug.in/ns/ext/time#beatsPerMinute
Definition time.h:44
#define LV2_TIME__speed
http://lv2plug.in/ns/ext/time#speed
Definition time.h:47
#define LV2_TIME__beatUnit
http://lv2plug.in/ns/ext/time#beatUnit
Definition time.h:42
#define LV2_TIME__beatsPerBar
http://lv2plug.in/ns/ext/time#beatsPerBar
Definition time.h:43
#define LV2_TIME__bar
http://lv2plug.in/ns/ext/time#bar
Definition time.h:40
void * LV2UI_Controller
Definition ui.h:104
#define LV2_UI__portMap
http://lv2plug.in/ns/extensions/ui#portMap
Definition ui.h:59
#define LV2_UI__X11UI
http://lv2plug.in/ns/extensions/ui#X11UI
Definition ui.h:48
#define LV2_UI__floatProtocol
http://lv2plug.in/ns/extensions/ui#floatProtocol
Definition ui.h:63
#define LV2_UI__CocoaUI
http://lv2plug.in/ns/extensions/ui#CocoaUI
Definition ui.h:39
struct _LV2UI_Idle_Interface LV2UI_Idle_Interface
#define LV2_UI__idleInterface
http://lv2plug.in/ns/extensions/ui#idleInterface
Definition ui.h:53
#define LV2_UI__touch
http://lv2plug.in/ns/extensions/ui#touch
Definition ui.h:69
void * LV2UI_Widget
Definition ui.h:90
#define LV2_UI__parent
http://lv2plug.in/ns/extensions/ui#parent
Definition ui.h:56
struct _LV2UI_Port_Map LV2UI_Port_Map
struct _LV2UI_Descriptor LV2UI_Descriptor
#define LV2_UI__resize
http://lv2plug.in/ns/extensions/ui#resize
Definition ui.h:66
#define LV2_UI__WindowsUI
http://lv2plug.in/ns/extensions/ui#WindowsUI
Definition ui.h:47
#define LV2_UI__scaleFactor
http://lv2plug.in/ns/extensions/ui#scaleFactor
Definition ui.h:67
#define LV2_UI__noUserResize
http://lv2plug.in/ns/extensions/ui#noUserResize
Definition ui.h:54
struct _LV2UI_Resize LV2UI_Resize
void * LV2UI_Handle
Definition ui.h:97
void * LV2UI_Feature_Handle
Definition ui.h:109
#define LV2UI_INVALID_PORT_INDEX
Definition ui.h:77
struct _LV2UI_Touch LV2UI_Touch
#define LV2_UNITS__frame
http://lv2plug.in/ns/ext/units#frame
Definition units.h:43
#define LV2_UNITS__beat
http://lv2plug.in/ns/ext/units#beat
Definition units.h:35
void * LV2_URID_Map_Handle
Definition urid.h:48
#define LV2_URID__map
http://lv2plug.in/ns/ext/urid#map
Definition urid.h:33
uint32_t LV2_URID
Definition urid.h:58
struct _LV2_URID_Unmap LV2_URID_Unmap
void * LV2_URID_Unmap_Handle
Definition urid.h:53
struct _LV2_URID_Map LV2_URID_Map
#define LV2_URID__unmap
http://lv2plug.in/ns/ext/urid#unmap
Definition urid.h:34
#define LV2_WORKER__schedule
http://lv2plug.in/ns/ext/worker#schedule
Definition worker.h:37
LV2_Worker_Status
Definition worker.h:46
struct _LV2_Worker_Schedule LV2_Worker_Schedule
#define LV2_WORKER__interface
http://lv2plug.in/ns/ext/worker#interface
Definition worker.h:36
void * LV2_Worker_Schedule_Handle
Definition worker.h:124
struct _LV2_Worker_Interface LV2_Worker_Interface
void * LV2_Worker_Respond_Handle
Definition worker.h:53
@ LV2_WORKER_SUCCESS
Definition worker.h:47
@ LV2_WORKER_ERR_UNKNOWN
Definition worker.h:48
@ LV2_WORKER_ERR_NO_SPACE
Definition worker.h:49
struct backing_store_struct * info
Definition jmemsys.h:183
JSAMPIMAGE data
Definition jpeglib.h:945
#define JUCE_BEGIN_IGNORE_WARNINGS_MSVC(warnings)
Definition juce_CompilerWarnings.h:198
#define JUCE_END_IGNORE_WARNINGS_MSVC
Definition juce_CompilerWarnings.h:199
#define X(str)
Definition juce_LV2Common.h:197
#define JUCE_LEAK_DETECTOR(OwnerClass)
Definition juce_LeakedObjectDetector.h:138
#define TRANS(stringLiteral)
Definition juce_LocalisedStrings.h:208
#define JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED
Definition juce_MessageManager.h:465
#define JUCE_ASSERT_MESSAGE_THREAD
Definition juce_MessageManager.h:473
static const LV2_Lib_Descriptor lib
Definition lib_descriptor.c:100
float control
Definition lilv_test.c:1462
static LilvWorld * world
Definition lilv_test.c:64
float in
Definition lilv_test.c:1460
static int JUCE_CDECL comp(const void *a, const void *b)
Definition lsp.c:298
int int32_t
Definition mid.cpp:97
unsigned int uint32_t
Definition mid.cpp:100
static void ** pointers
Definition misc.c:24
@ unknown
Definition VstPlugin.cpp:75
bool verify(tresult result)
Definition vstpresetfile.cpp:75
void move(void *from, void *to)
Definition juce_FixedSizeFunction.h:53
auto & get(ProcessorChain< Processors... > &chain) noexcept
Definition juce_ProcessorChain.h:133
JOCTET * buffer
Definition juce_JPEGLoader.cpp:302
Definition carla_juce.cpp:31
jack_client_t client jack_client_t client jack_client_t client jack_client_t JackInfoShutdownCallback void arg jack_client_t jack_port_t * port
Definition juce_linux_JackAudio.cpp:65
@ no
Definition juce_AlertWindow.cpp:567
@ yes
Definition juce_AlertWindow.cpp:567
CriticalSection::ScopedLockType ScopedLock
Definition juce_CriticalSection.h:186
juce::String toString(const Steinberg::char8 *string) noexcept
Definition juce_VST3Common.h:159
Type unalignedPointerCast(void *ptr) noexcept
Definition juce_Memory.h:88
JUCE_END_IGNORE_WARNINGS_MSVC Optional< std::decay_t< Value > > makeOptional(Value &&v)
Definition juce_Optional.h:298
RangedDirectoryIterator end(const RangedDirectoryIterator &)
Definition juce_RangedDirectoryIterator.h:184
jack_client_t client jack_client_t client jack_client_t client jack_client_t JackInfoShutdownCallback void arg jack_client_t jack_port_t port void func jack_client_t const char const char unsigned long flags const jack_port_t port jack_client_t jack_port_id_t port_id const jack_port_t const char port_name const jack_port_t port void * ptr
Definition juce_linux_JackAudio.cpp:79
void ignoreUnused(Types &&...) noexcept
Definition juce_MathsFunctions.h:333
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
Definition juce_MathsFunctions.h:279
void writeUnaligned(void *dstPtr, Type value) noexcept
Definition juce_Memory.h:74
@ window
Definition juce_AccessibilityRole.h:63
@ list
Definition juce_AccessibilityRole.h:56
@ tree
Definition juce_AccessibilityRole.h:58
@ label
Definition juce_AccessibilityRole.h:44
@ group
Definition juce_AccessibilityRole.h:61
RangedDirectoryIterator begin(const RangedDirectoryIterator &it)
Definition juce_RangedDirectoryIterator.h:179
constexpr Nullopt nullopt
Definition juce_Optional.h:48
std::unique_ptr< T > rawToUniquePtr(T *ptr)
Definition juce_Memory.h:195
jack_client_t client jack_client_t client jack_client_t client jack_client_t JackInfoShutdownCallback void arg jack_client_t jack_port_t port void func jack_client_t const char const char unsigned long flags
Definition juce_linux_JackAudio.cpp:69
auto getText(std::string_view name) -> QString
Definition embed.cpp:125
float maximum(const float *abs_spectrum, unsigned int spec_size)
Definition fft_helpers.cpp:40
rtosc::Ports ports
Definition MiddleWare.cpp:383
const AbsTime * time
Definition PADnoteParameters.h:189
#define true
Definition ordinals.h:82
#define false
Definition ordinals.h:83
#define min(x, y)
Definition os.h:74
#define max(x, y)
Definition os.h:78
void * data
Definition lv2.h:157
uint32_t size
Definition atom-forge.h:105
uint8_t * buf
Definition atom-forge.h:103
uint32_t size
Definition atom.h:107
uint32_t type
Definition atom.h:108
const char * URI
Definition lv2.h:188
void(* cleanup)(LV2_Handle instance)
Definition lv2.h:337
LV2_Handle(* instantiate)(const struct LV2_Descriptor *descriptor, double sample_rate, const char *bundle_path, const LV2_Feature *const *features)
Definition lv2.h:217
void * data
Definition lv2.h:171
LONG bottom
Definition swell-types.h:232
LONG left
Definition swell-types.h:232
LONG top
Definition swell-types.h:232
LONG right
Definition swell-types.h:232
itr_t end() const
Definition ports.h:171
itr_t begin() const
Definition ports.h:168
size_t size() const
Definition ports.h:174
const char const char const char const char char * fn
Definition swell-functions.h:168
const char * text
Definition swell-functions.h:167
RECT const char void(* callback)(const char *droppath))) SWELL_API_DEFINE(BOOL
Definition swell-functions.h:1004
RECT const char void HWND hwnd
Definition swell-functions.h:1066
bool GetWindowRect(HWND hwnd, RECT *r)
Definition swell-generic-headless.cpp:130
void * HINSTANCE
Definition swell-types.h:212
LONG_PTR LRESULT
Definition swell-types.h:171
unsigned int UINT
Definition swell-types.h:166
LONG_PTR LPARAM
Definition swell-types.h:170
ULONG_PTR WPARAM
Definition swell-types.h:169
struct HWND__ * HWND
Definition swell-types.h:210
#define CALLBACK
Definition swell-types.h:635
DWORD GetCurrentThreadId()
Definition swell.cpp:471
static LV2_State_Status save(LV2_Handle instance, LV2_State_Store_Function store, void *callback_data, uint32_t flags, const LV2_Feature *const *features)
Definition test.c:161
static LV2_State_Status restore(LV2_Handle instance, LV2_State_Retrieve_Function retrieve, void *callback_data, uint32_t flags, const LV2_Feature *const *features)
Definition test.c:292
uch * p
Definition crypt.c:594
return c
Definition crypt.c:175
for(n=0;n< RAND_HEAD_LEN;n++)
Definition crypt.c:467
int r
Definition crypt.c:458
uch h[RAND_HEAD_LEN]
Definition crypt.c:459
fmt[0]
Definition fileio.c:2503
int result
Definition process.c:1455
typedef int(UZ_EXP MsgFn)()
#define void
Definition unzip.h:396
struct zdirent * file
Definition win32.c:1500
_WDL_CSTRING_PREFIX void INT_PTR const char * format
Definition wdlcstring.h:263
#define const
Definition zconf.h:137