The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1975 lines
63KB

  1. /*
  2. ==============================================================================
  3. Juce LV2 Wrapper
  4. ==============================================================================
  5. */
  6. #include <juce_core/system/juce_CompilerWarnings.h>
  7. #include <juce_core/system/juce_TargetPlatform.h>
  8. #include "../utility/juce_CheckSettingMacros.h"
  9. #if JucePlugin_Build_LV2
  10. #include "../utility/juce_IncludeSystemHeaders.h"
  11. /** Plugin requires processing with a fixed/constant block size */
  12. #ifndef JucePlugin_WantsLV2FixedBlockSize
  13. #define JucePlugin_WantsLV2FixedBlockSize 0
  14. #endif
  15. /** Enable latency port */
  16. #ifndef JucePlugin_WantsLV2Latency
  17. #define JucePlugin_WantsLV2Latency 1
  18. #endif
  19. /** Use non-parameter states */
  20. #ifndef JucePlugin_WantsLV2State
  21. #define JucePlugin_WantsLV2State 1
  22. #endif
  23. /** States are strings, needs custom get/setStateInformationString */
  24. #ifndef JucePlugin_WantsLV2StateString
  25. #define JucePlugin_WantsLV2StateString 0
  26. #endif
  27. /** Export presets */
  28. #ifndef JucePlugin_WantsLV2Presets
  29. #define JucePlugin_WantsLV2Presets 1
  30. #endif
  31. /** Request time position */
  32. #ifndef JucePlugin_WantsLV2TimePos
  33. #define JucePlugin_WantsLV2TimePos 1
  34. #endif
  35. /** Using string states require enabling states first */
  36. #if JucePlugin_WantsLV2StateString && ! JucePlugin_WantsLV2State
  37. #undef JucePlugin_WantsLV2State
  38. #define JucePlugin_WantsLV2State 1
  39. #endif
  40. // LV2 includes..
  41. #include "includes/lv2.h"
  42. #include "includes/atom.h"
  43. #include "includes/atom-util.h"
  44. #include "includes/buf-size.h"
  45. #include "includes/instance-access.h"
  46. #include "includes/midi.h"
  47. #include "includes/options.h"
  48. #include "includes/parameters.h"
  49. #include "includes/port-props.h"
  50. #include "includes/presets.h"
  51. #include "includes/state.h"
  52. #include "includes/time.h"
  53. #include "includes/ui.h"
  54. #include "includes/urid.h"
  55. #include "includes/lv2_external_ui.h"
  56. #include "includes/lv2_programs.h"
  57. #define JUCE_LV2_STATE_STRING_URI "urn:juce:stateString"
  58. #define JUCE_LV2_STATE_BINARY_URI "urn:juce:stateBinary"
  59. #if ! JUCE_AUDIOPROCESSOR_NO_GUI
  60. #define JUCE_GUI_BASICS_INCLUDE_XHEADERS 1
  61. #endif
  62. #include "../utility/juce_IncludeModuleHeaders.h"
  63. #include <juce_audio_processors/format_types/juce_LegacyAudioParameter.cpp>
  64. using namespace juce;
  65. //==============================================================================
  66. // Various helper functions
  67. /** Returns plugin URI */
  68. static const String& getPluginURI()
  69. {
  70. // JucePlugin_LV2URI might be defined as a function (eg. allowing dynamic URIs based on filename)
  71. static const String pluginURI(JucePlugin_LV2URI);
  72. return pluginURI;
  73. }
  74. /** Queries all available plugin audio ports */
  75. void findMaxTotalChannels (std::unique_ptr<AudioProcessor>& filter, int& maxTotalIns, int& maxTotalOuts)
  76. {
  77. filter->enableAllBuses();
  78. #ifdef JucePlugin_PreferredChannelConfigurations
  79. int configs[][2] = { JucePlugin_PreferredChannelConfigurations };
  80. maxTotalIns = maxTotalOuts = 0;
  81. for (auto& config : configs)
  82. {
  83. maxTotalIns = jmax (maxTotalIns, config[0]);
  84. maxTotalOuts = jmax (maxTotalOuts, config[1]);
  85. }
  86. #else
  87. auto numInputBuses = filter->getBusCount (true);
  88. auto numOutputBuses = filter->getBusCount (false);
  89. if (numInputBuses > 1 || numOutputBuses > 1)
  90. {
  91. maxTotalIns = maxTotalOuts = 0;
  92. for (int i = 0; i < numInputBuses; ++i)
  93. maxTotalIns += filter->getChannelCountOfBus (true, i);
  94. for (int i = 0; i < numOutputBuses; ++i)
  95. maxTotalOuts += filter->getChannelCountOfBus (false, i);
  96. }
  97. else
  98. {
  99. maxTotalIns = numInputBuses > 0 ? filter->getBus (true, 0)->getMaxSupportedChannels (64) : 0;
  100. maxTotalOuts = numOutputBuses > 0 ? filter->getBus (false, 0)->getMaxSupportedChannels (64) : 0;
  101. }
  102. #endif
  103. }
  104. //==============================================================================
  105. #if JUCE_LINUX
  106. class SharedMessageThread : public Thread
  107. {
  108. public:
  109. SharedMessageThread()
  110. : Thread ("Lv2MessageThread"),
  111. initialised (false)
  112. {
  113. startThread (7);
  114. while (! initialised)
  115. sleep (1);
  116. }
  117. ~SharedMessageThread()
  118. {
  119. MessageManager::getInstance()->stopDispatchLoop();
  120. waitForThreadToExit (5000);
  121. }
  122. void run() override
  123. {
  124. const ScopedJuceInitialiser_GUI juceInitialiser;
  125. MessageManager::getInstance()->setCurrentThreadAsMessageThread();
  126. #if ! JUCE_AUDIOPROCESSOR_NO_GUI
  127. XWindowSystem::getInstance();
  128. #endif
  129. initialised = true;
  130. MessageManager::getInstance()->runDispatchLoop();
  131. }
  132. private:
  133. volatile bool initialised;
  134. };
  135. #endif
  136. #if ! JUCE_AUDIOPROCESSOR_NO_GUI
  137. //==============================================================================
  138. /**
  139. Lightweight DocumentWindow subclass for external ui
  140. */
  141. class JuceLv2ExternalUIWindow : public DocumentWindow
  142. {
  143. public:
  144. /** Creates a Document Window wrapper */
  145. JuceLv2ExternalUIWindow (AudioProcessorEditor* editor, const String& title) :
  146. DocumentWindow (title, Colours::white, DocumentWindow::minimiseButton | DocumentWindow::closeButton, false),
  147. closed (false),
  148. lastPos (0, 0)
  149. {
  150. setOpaque (true);
  151. setContentNonOwned (editor, true);
  152. setSize (editor->getWidth(), editor->getHeight());
  153. setUsingNativeTitleBar (true);
  154. }
  155. /** Close button handler */
  156. void closeButtonPressed()
  157. {
  158. saveLastPos();
  159. removeFromDesktop();
  160. closed = true;
  161. }
  162. void saveLastPos()
  163. {
  164. lastPos = getScreenPosition();
  165. }
  166. void restoreLastPos()
  167. {
  168. setTopLeftPosition (lastPos.getX(), lastPos.getY());
  169. }
  170. Point<int> getLastPos()
  171. {
  172. return lastPos;
  173. }
  174. bool isClosed()
  175. {
  176. return closed;
  177. }
  178. void reset()
  179. {
  180. closed = false;
  181. }
  182. private:
  183. bool closed;
  184. Point<int> lastPos;
  185. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceLv2ExternalUIWindow);
  186. };
  187. //==============================================================================
  188. /**
  189. Juce LV2 External UI handle
  190. */
  191. class JuceLv2ExternalUIWrapper : public LV2_External_UI_Widget
  192. {
  193. public:
  194. JuceLv2ExternalUIWrapper (AudioProcessorEditor* editor, const String& title)
  195. : window (editor, title)
  196. {
  197. // external UI calls
  198. run = doRun;
  199. show = doShow;
  200. hide = doHide;
  201. }
  202. ~JuceLv2ExternalUIWrapper()
  203. {
  204. if (window.isOnDesktop())
  205. window.removeFromDesktop();
  206. }
  207. void close()
  208. {
  209. window.closeButtonPressed();
  210. }
  211. bool isClosed()
  212. {
  213. return window.isClosed();
  214. }
  215. void reset(const String& title)
  216. {
  217. window.reset();
  218. window.setName(title);
  219. }
  220. void repaint()
  221. {
  222. window.repaint();
  223. }
  224. Point<int> getScreenPosition()
  225. {
  226. if (window.isClosed())
  227. return window.getLastPos();
  228. else
  229. return window.getScreenPosition();
  230. }
  231. void setScreenPos (int x, int y)
  232. {
  233. if (! window.isClosed())
  234. window.setTopLeftPosition(x, y);
  235. }
  236. //==============================================================================
  237. static void doRun (LV2_External_UI_Widget* _this_)
  238. {
  239. const MessageManagerLock mmLock;
  240. JuceLv2ExternalUIWrapper* self = (JuceLv2ExternalUIWrapper*) _this_;
  241. if (! self->isClosed())
  242. self->window.repaint();
  243. }
  244. static void doShow (LV2_External_UI_Widget* _this_)
  245. {
  246. const MessageManagerLock mmLock;
  247. JuceLv2ExternalUIWrapper* self = (JuceLv2ExternalUIWrapper*) _this_;
  248. if (! self->isClosed())
  249. {
  250. if (! self->window.isOnDesktop())
  251. self->window.addToDesktop();
  252. self->window.restoreLastPos();
  253. self->window.setVisible(true);
  254. }
  255. }
  256. static void doHide (LV2_External_UI_Widget* _this_)
  257. {
  258. const MessageManagerLock mmLock;
  259. JuceLv2ExternalUIWrapper* self = (JuceLv2ExternalUIWrapper*) _this_;
  260. if (! self->isClosed())
  261. {
  262. self->window.saveLastPos();
  263. self->window.setVisible(false);
  264. }
  265. }
  266. private:
  267. JuceLv2ExternalUIWindow window;
  268. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceLv2ExternalUIWrapper);
  269. };
  270. //==============================================================================
  271. /**
  272. Juce LV2 Parent UI container, listens for resize events and passes them to ui-resize
  273. */
  274. class JuceLv2ParentContainer : public Component
  275. {
  276. public:
  277. struct SizeListener {
  278. virtual ~SizeListener() {}
  279. virtual void parentWindowSizeChanged(int cw, int ch) = 0;
  280. };
  281. JuceLv2ParentContainer (std::unique_ptr<AudioProcessorEditor>& editor,
  282. SizeListener* const sizeListener_)
  283. : sizeListener(sizeListener_)
  284. {
  285. setOpaque (true);
  286. editor->setOpaque (true);
  287. setBounds (editor->getBounds());
  288. editor->setTopLeftPosition (0, 0);
  289. addAndMakeVisible (editor.get());
  290. }
  291. ~JuceLv2ParentContainer()
  292. {
  293. }
  294. void paint (Graphics&) {}
  295. void paintOverChildren (Graphics&) {}
  296. void childBoundsChanged (Component* child)
  297. {
  298. const int cw = child->getWidth();
  299. const int ch = child->getHeight();
  300. #if JUCE_LINUX
  301. X11Symbols::getInstance()->xResizeWindow (display, (Window) getWindowHandle(), cw, ch);
  302. #else
  303. setSize (cw, ch);
  304. #endif
  305. sizeListener->parentWindowSizeChanged (cw, ch);
  306. }
  307. private:
  308. //==============================================================================
  309. #if JUCE_LINUX
  310. ::Display* const display = XWindowSystem::getInstance()->getDisplay();
  311. #endif
  312. SizeListener* const sizeListener;
  313. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceLv2ParentContainer);
  314. };
  315. static ThreadLocalValue<bool> inParameterChangedCallback;
  316. //==============================================================================
  317. /**
  318. Juce LV2 UI handle
  319. */
  320. class JuceLv2UIWrapper : public AudioProcessorListener,
  321. public Timer,
  322. public JuceLv2ParentContainer::SizeListener
  323. {
  324. public:
  325. #if JUCE_LINUX
  326. static bool hostHasIdleInterface;
  327. #endif
  328. JuceLv2UIWrapper (AudioProcessor* filter_, LV2UI_Write_Function writeFunction_, LV2UI_Controller controller_,
  329. LV2UI_Widget* widget, const LV2_Feature* const* features, bool isExternal_,
  330. int numInChans, int numOutChans)
  331. : filter (filter_),
  332. writeFunction (writeFunction_),
  333. controller (controller_),
  334. isExternal (isExternal_),
  335. controlPortOffset (0),
  336. lastProgramCount (0),
  337. uiTouch (nullptr),
  338. programsHost (nullptr),
  339. externalUIHost (nullptr),
  340. lastExternalUIPos (-1, -1),
  341. uiResize (nullptr)
  342. {
  343. jassert (filter != nullptr);
  344. filter->addListener(this);
  345. if (filter->hasEditor())
  346. {
  347. editor = std::unique_ptr<AudioProcessorEditor>(filter->createEditorIfNeeded());
  348. if (editor == nullptr)
  349. {
  350. *widget = nullptr;
  351. return;
  352. }
  353. }
  354. for (int i = 0; features[i] != nullptr; ++i)
  355. {
  356. if (strcmp(features[i]->URI, LV2_UI__touch) == 0)
  357. uiTouch = (const LV2UI_Touch*)features[i]->data;
  358. else if (strcmp(features[i]->URI, LV2_PROGRAMS__Host) == 0)
  359. programsHost = (const LV2_Programs_Host*)features[i]->data;
  360. }
  361. if (isExternal)
  362. {
  363. resetExternalUI (features);
  364. if (externalUIHost != nullptr)
  365. {
  366. String title (filter->getName());
  367. if (externalUIHost->plugin_human_id != nullptr)
  368. title = externalUIHost->plugin_human_id;
  369. externalUI = std::make_unique<JuceLv2ExternalUIWrapper> (editor.get(), title);
  370. *widget = externalUI.get();
  371. startTimer (100);
  372. }
  373. else
  374. {
  375. *widget = nullptr;
  376. }
  377. }
  378. else
  379. {
  380. resetParentUI (features);
  381. if (parentContainer != nullptr)
  382. *widget = parentContainer->getWindowHandle();
  383. else
  384. *widget = nullptr;
  385. }
  386. #if (JucePlugin_WantsMidiInput || JucePlugin_WantsLV2TimePos)
  387. controlPortOffset += 1;
  388. #endif
  389. #if JucePlugin_ProducesMidiOutput
  390. controlPortOffset += 1;
  391. #endif
  392. controlPortOffset += 1; // freewheel
  393. #if JucePlugin_WantsLV2Latency
  394. controlPortOffset += 1;
  395. #endif
  396. controlPortOffset += numInChans + numOutChans;
  397. lastProgramCount = filter->getNumPrograms();
  398. }
  399. ~JuceLv2UIWrapper()
  400. {
  401. PopupMenu::dismissAllActiveMenus();
  402. filter->removeListener(this);
  403. parentContainer = nullptr;
  404. externalUI = nullptr;
  405. externalUIHost = nullptr;
  406. if (editor != nullptr)
  407. {
  408. filter->editorBeingDeleted (editor.get());
  409. editor = nullptr;
  410. }
  411. }
  412. //==============================================================================
  413. // LV2 core calls
  414. void lv2Cleanup()
  415. {
  416. const MessageManagerLock mmLock;
  417. if (isExternal)
  418. {
  419. if (isTimerRunning())
  420. stopTimer();
  421. externalUIHost = nullptr;
  422. if (externalUI != nullptr)
  423. {
  424. lastExternalUIPos = externalUI->getScreenPosition();
  425. externalUI->close();
  426. }
  427. }
  428. else
  429. {
  430. if (parentContainer)
  431. {
  432. parentContainer->setVisible (false);
  433. if (parentContainer->isOnDesktop())
  434. parentContainer->removeFromDesktop();
  435. }
  436. filter->editorBeingDeleted (editor.get());
  437. editor = nullptr;
  438. parentContainer = nullptr;
  439. }
  440. }
  441. int lv2Idle()
  442. {
  443. #if JUCE_LINUX
  444. Array<IdleMessage> idleMessagesCopy;
  445. {
  446. const ScopedLock sl(idleMessagesLock);
  447. idleMessages.swapWith(idleMessagesCopy);
  448. }
  449. for (auto& msg : idleMessagesCopy)
  450. {
  451. switch (msg.type)
  452. {
  453. case IdleMessage::kMessageParameterChanged:
  454. writeFunction (controller, msg.index + controlPortOffset, sizeof (float), 0, &msg.valuef);
  455. break;
  456. case IdleMessage::kMessageSizeChanged:
  457. uiResize->ui_resize (uiResize->handle, msg.index, msg.valuei);
  458. break;
  459. case IdleMessage::kMessageGestureBegin:
  460. uiTouch->touch (uiTouch->handle, msg.index + controlPortOffset, true);
  461. break;
  462. case IdleMessage::kMessageGestureEnd:
  463. uiTouch->touch (uiTouch->handle, msg.index + controlPortOffset, false);
  464. break;
  465. }
  466. }
  467. #endif
  468. return 0;
  469. }
  470. //==============================================================================
  471. // Juce calls
  472. void audioProcessorParameterChanged (AudioProcessor*, int index, float newValue)
  473. {
  474. if (inParameterChangedCallback.get())
  475. {
  476. inParameterChangedCallback = false;
  477. return;
  478. }
  479. if (writeFunction == nullptr || controller == nullptr)
  480. return;
  481. #if JUCE_LINUX
  482. if (hostHasIdleInterface && ! isExternal)
  483. {
  484. const IdleMessage msg = { IdleMessage::kMessageParameterChanged, index, 0, newValue };
  485. const ScopedLock sl(idleMessagesLock);
  486. idleMessages.add(msg);
  487. }
  488. else
  489. #endif
  490. {
  491. writeFunction (controller, index + controlPortOffset, sizeof (float), 0, &newValue);
  492. }
  493. }
  494. void audioProcessorChanged (AudioProcessor*, const ChangeDetails& details)
  495. {
  496. if (details.programChanged && filter != nullptr && programsHost != nullptr)
  497. {
  498. if (filter->getNumPrograms() != lastProgramCount)
  499. {
  500. programsHost->program_changed (programsHost->handle, -1);
  501. lastProgramCount = filter->getNumPrograms();
  502. }
  503. else
  504. programsHost->program_changed (programsHost->handle, filter->getCurrentProgram());
  505. }
  506. }
  507. void audioProcessorParameterChangeGestureBegin (AudioProcessor*, int parameterIndex)
  508. {
  509. if (uiTouch == nullptr)
  510. return;
  511. #if JUCE_LINUX
  512. if (hostHasIdleInterface && ! isExternal)
  513. {
  514. const IdleMessage msg = { IdleMessage::kMessageGestureBegin, parameterIndex, 0, 0.0f };
  515. const ScopedLock sl(idleMessagesLock);
  516. idleMessages.add(msg);
  517. }
  518. else
  519. #endif
  520. {
  521. uiTouch->touch (uiTouch->handle, parameterIndex + controlPortOffset, true);
  522. }
  523. }
  524. void audioProcessorParameterChangeGestureEnd (AudioProcessor*, int parameterIndex)
  525. {
  526. if (uiTouch == nullptr)
  527. return;
  528. #if JUCE_LINUX
  529. if (hostHasIdleInterface && ! isExternal)
  530. {
  531. const IdleMessage msg = { IdleMessage::kMessageGestureEnd, parameterIndex, 0, 0.0f };
  532. const ScopedLock sl(idleMessagesLock);
  533. idleMessages.add(msg);
  534. }
  535. else
  536. #endif
  537. {
  538. uiTouch->touch (uiTouch->handle, parameterIndex + controlPortOffset, false);
  539. }
  540. }
  541. void parentWindowSizeChanged(int cw, int ch) override
  542. {
  543. if (uiResize == nullptr)
  544. return;
  545. #if JUCE_LINUX
  546. if (hostHasIdleInterface && ! isExternal)
  547. {
  548. const IdleMessage msg = { IdleMessage::kMessageSizeChanged, cw, ch, 0.0f };
  549. const ScopedLock sl(idleMessagesLock);
  550. idleMessages.add(msg);
  551. }
  552. else
  553. #endif
  554. {
  555. uiResize->ui_resize (uiResize->handle, cw, ch);
  556. }
  557. }
  558. void timerCallback()
  559. {
  560. if (externalUI != nullptr && externalUI->isClosed())
  561. {
  562. if (externalUIHost != nullptr)
  563. externalUIHost->ui_closed (controller);
  564. if (isTimerRunning())
  565. stopTimer();
  566. }
  567. }
  568. //==============================================================================
  569. void resetIfNeeded (LV2UI_Write_Function writeFunction_, LV2UI_Controller controller_, LV2UI_Widget* widget,
  570. const LV2_Feature* const* features)
  571. {
  572. writeFunction = writeFunction_;
  573. controller = controller_;
  574. uiTouch = nullptr;
  575. programsHost = nullptr;
  576. for (int i = 0; features[i] != nullptr; ++i)
  577. {
  578. if (strcmp(features[i]->URI, LV2_UI__touch) == 0)
  579. uiTouch = (const LV2UI_Touch*)features[i]->data;
  580. else if (strcmp(features[i]->URI, LV2_PROGRAMS__Host) == 0)
  581. programsHost = (const LV2_Programs_Host*)features[i]->data;
  582. }
  583. if (isExternal)
  584. {
  585. resetExternalUI (features);
  586. *widget = externalUI.get();
  587. }
  588. else
  589. {
  590. if (editor == nullptr)
  591. editor = std::unique_ptr<AudioProcessorEditor>(filter->createEditorIfNeeded());
  592. resetParentUI (features);
  593. *widget = parentContainer->getWindowHandle();
  594. }
  595. }
  596. void repaint()
  597. {
  598. const MessageManagerLock mmLock;
  599. if (editor != nullptr)
  600. editor->repaint();
  601. if (parentContainer != nullptr)
  602. parentContainer->repaint();
  603. if (externalUI != nullptr)
  604. externalUI->repaint();
  605. }
  606. private:
  607. AudioProcessor* const filter;
  608. std::unique_ptr<AudioProcessorEditor> editor;
  609. LV2UI_Write_Function writeFunction;
  610. LV2UI_Controller controller;
  611. const bool isExternal;
  612. uint32 controlPortOffset;
  613. int lastProgramCount;
  614. const LV2UI_Touch* uiTouch;
  615. const LV2_Programs_Host* programsHost;
  616. std::unique_ptr<JuceLv2ExternalUIWrapper> externalUI;
  617. const LV2_External_UI_Host* externalUIHost;
  618. Point<int> lastExternalUIPos;
  619. std::unique_ptr<JuceLv2ParentContainer> parentContainer;
  620. const LV2UI_Resize* uiResize;
  621. #if JUCE_LINUX
  622. struct IdleMessage {
  623. enum {
  624. kMessageParameterChanged,
  625. kMessageSizeChanged,
  626. kMessageGestureBegin,
  627. kMessageGestureEnd,
  628. } type;
  629. int index;
  630. int valuei;
  631. float valuef;
  632. };
  633. Array<IdleMessage> idleMessages;
  634. CriticalSection idleMessagesLock;
  635. ::Display* const display = XWindowSystem::getInstance()->getDisplay();
  636. #endif
  637. //==============================================================================
  638. void resetExternalUI (const LV2_Feature* const* features)
  639. {
  640. externalUIHost = nullptr;
  641. for (int i = 0; features[i] != nullptr; ++i)
  642. {
  643. if (strcmp(features[i]->URI, LV2_EXTERNAL_UI__Host) == 0)
  644. {
  645. externalUIHost = (const LV2_External_UI_Host*)features[i]->data;
  646. break;
  647. }
  648. }
  649. if (externalUI != nullptr)
  650. {
  651. String title(filter->getName());
  652. if (externalUIHost->plugin_human_id != nullptr)
  653. title = externalUIHost->plugin_human_id;
  654. if (lastExternalUIPos.getX() != -1 && lastExternalUIPos.getY() != -1)
  655. externalUI->setScreenPos(lastExternalUIPos.getX(), lastExternalUIPos.getY());
  656. externalUI->reset(title);
  657. startTimer (100);
  658. }
  659. }
  660. void resetParentUI (const LV2_Feature* const* features)
  661. {
  662. void* parent = nullptr;
  663. uiResize = nullptr;
  664. for (int i = 0; features[i] != nullptr; ++i)
  665. {
  666. if (strcmp(features[i]->URI, LV2_UI__parent) == 0)
  667. parent = features[i]->data;
  668. else if (strcmp(features[i]->URI, LV2_UI__resize) == 0)
  669. uiResize = (const LV2UI_Resize*)features[i]->data;
  670. }
  671. if (parent != nullptr)
  672. {
  673. if (parentContainer == nullptr)
  674. parentContainer = std::make_unique<JuceLv2ParentContainer> (editor, this);
  675. parentContainer->setVisible (false);
  676. if (parentContainer->isOnDesktop())
  677. parentContainer->removeFromDesktop();
  678. parentContainer->addToDesktop (ComponentPeer::windowIsResizable, parent);
  679. #if JUCE_LINUX
  680. Window hostWindow = (Window) parent;
  681. Window editorWnd = (Window) parentContainer->getWindowHandle();
  682. X11Symbols::getInstance()->xReparentWindow (display, editorWnd, hostWindow, 0, 0);
  683. #endif
  684. if (uiResize != nullptr)
  685. uiResize->ui_resize (uiResize->handle, parentContainer->getWidth(), parentContainer->getHeight());
  686. parentContainer->setVisible (true);
  687. }
  688. }
  689. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceLv2UIWrapper)
  690. };
  691. #if JUCE_LINUX
  692. bool JuceLv2UIWrapper::hostHasIdleInterface = false;
  693. #endif
  694. #endif /* JUCE_AUDIOPROCESSOR_NO_GUI */
  695. //==============================================================================
  696. /**
  697. Juce LV2 handle
  698. */
  699. class JuceLv2Wrapper : public AudioPlayHead
  700. {
  701. public:
  702. //==============================================================================
  703. JuceLv2Wrapper (double sampleRate_, const LV2_Feature* const* features)
  704. : numInChans (0),
  705. numOutChans (0),
  706. bufferSize (2048),
  707. sampleRate (sampleRate_),
  708. bypassParameter (nullptr),
  709. uridMap (nullptr),
  710. uridAtomBlank (0),
  711. uridAtomObject (0),
  712. uridAtomDouble (0),
  713. uridAtomFloat (0),
  714. uridAtomInt (0),
  715. uridAtomLong (0),
  716. uridAtomSequence (0),
  717. uridMidiEvent (0),
  718. uridTimePos (0),
  719. uridTimeBar (0),
  720. uridTimeBarBeat (0),
  721. uridTimeBeatsPerBar (0),
  722. uridTimeBeatsPerMinute (0),
  723. uridTimeBeatUnit (0),
  724. uridTimeFrame (0),
  725. uridTimeSpeed (0),
  726. usingNominalBlockLength (false)
  727. {
  728. {
  729. const MessageManagerLock mmLock;
  730. filter = std::unique_ptr<AudioProcessor> (createPluginFilterOfType (AudioProcessor::wrapperType_LV2));
  731. }
  732. jassert (filter != nullptr);
  733. findMaxTotalChannels (filter, numInChans, numOutChans);
  734. // You must at least have some channels
  735. jassert (filter->isMidiEffect() || (numInChans > 0 || numOutChans > 0));
  736. filter->setPlayConfigDetails (numInChans, numOutChans, 0, 0);
  737. filter->setPlayHead (this);
  738. filter->refreshParameterList();
  739. bypassParameter = filter->getBypassParameter();
  740. #if (JucePlugin_WantsMidiInput || JucePlugin_WantsLV2TimePos)
  741. portEventsIn = nullptr;
  742. #endif
  743. #if JucePlugin_ProducesMidiOutput
  744. portMidiOut = nullptr;
  745. #endif
  746. portFreewheel = nullptr;
  747. #if JucePlugin_WantsLV2Latency
  748. portLatency = nullptr;
  749. #endif
  750. const Array<AudioProcessorParameter*>& parameters = filter->getParameters();
  751. portAudioIns.insertMultiple (0, nullptr, numInChans);
  752. portAudioOuts.insertMultiple (0, nullptr, numOutChans);
  753. portControls.insertMultiple (0, nullptr, parameters.size());
  754. for (int i=0; i < parameters.size(); ++i)
  755. {
  756. AudioProcessorParameter* const param = parameters.getUnchecked (i);
  757. float value = param->getValue();
  758. if (param == bypassParameter)
  759. value = 1.f - value;
  760. lastControlValues.add (value);
  761. }
  762. curPosInfo.resetToDefault();
  763. // we need URID_Map first
  764. for (int i=0; features[i] != nullptr; ++i)
  765. {
  766. if (strcmp(features[i]->URI, LV2_URID__map) == 0)
  767. {
  768. uridMap = (const LV2_URID_Map*)features[i]->data;
  769. break;
  770. }
  771. }
  772. // we require uridMap to work properly (it's set as required feature)
  773. jassert (uridMap != nullptr);
  774. if (uridMap != nullptr)
  775. {
  776. uridAtomBlank = uridMap->map(uridMap->handle, LV2_ATOM__Blank);
  777. uridAtomObject = uridMap->map(uridMap->handle, LV2_ATOM__Object);
  778. uridAtomDouble = uridMap->map(uridMap->handle, LV2_ATOM__Double);
  779. uridAtomFloat = uridMap->map(uridMap->handle, LV2_ATOM__Float);
  780. uridAtomInt = uridMap->map(uridMap->handle, LV2_ATOM__Int);
  781. uridAtomLong = uridMap->map(uridMap->handle, LV2_ATOM__Long);
  782. uridAtomSequence = uridMap->map(uridMap->handle, LV2_ATOM__Sequence);
  783. uridMidiEvent = uridMap->map(uridMap->handle, LV2_MIDI__MidiEvent);
  784. uridTimePos = uridMap->map(uridMap->handle, LV2_TIME__Position);
  785. uridTimeBar = uridMap->map(uridMap->handle, LV2_TIME__bar);
  786. uridTimeBarBeat = uridMap->map(uridMap->handle, LV2_TIME__barBeat);
  787. uridTimeBeatsPerBar = uridMap->map(uridMap->handle, LV2_TIME__beatsPerBar);
  788. uridTimeBeatsPerMinute = uridMap->map(uridMap->handle, LV2_TIME__beatsPerMinute);
  789. uridTimeBeatUnit = uridMap->map(uridMap->handle, LV2_TIME__beatUnit);
  790. uridTimeFrame = uridMap->map(uridMap->handle, LV2_TIME__frame);
  791. uridTimeSpeed = uridMap->map(uridMap->handle, LV2_TIME__speed);
  792. for (int i=0; features[i] != nullptr; ++i)
  793. {
  794. if (strcmp(features[i]->URI, LV2_OPTIONS__options) == 0)
  795. {
  796. const LV2_Options_Option* options = (const LV2_Options_Option*)features[i]->data;
  797. for (int j=0; options[j].key != 0; ++j)
  798. {
  799. if (options[j].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__nominalBlockLength))
  800. {
  801. if (options[j].type == uridAtomInt)
  802. {
  803. bufferSize = *(int*)options[j].value;
  804. usingNominalBlockLength = true;
  805. }
  806. else
  807. {
  808. std::cerr << "Host provides nominalBlockLength but has wrong value type" << std::endl;
  809. }
  810. break;
  811. }
  812. if (options[j].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__maxBlockLength))
  813. {
  814. if (options[j].type == uridAtomInt)
  815. bufferSize = *(int*)options[j].value;
  816. else
  817. std::cerr << "Host provides maxBlockLength but has wrong value type" << std::endl;
  818. // no break, continue in case host supports nominalBlockLength
  819. }
  820. }
  821. break;
  822. }
  823. }
  824. }
  825. progDesc.bank = 0;
  826. progDesc.program = 0;
  827. progDesc.name = nullptr;
  828. }
  829. ~JuceLv2Wrapper ()
  830. {
  831. const MessageManagerLock mmLock;
  832. #if ! JUCE_AUDIOPROCESSOR_NO_GUI
  833. ui = nullptr;
  834. #endif
  835. filter = nullptr;
  836. if (progDesc.name != nullptr)
  837. free((void*)progDesc.name);
  838. portControls.clear();
  839. lastControlValues.clear();
  840. }
  841. //==============================================================================
  842. // LV2 core calls
  843. void lv2ConnectPort (uint32 portId, void* dataLocation)
  844. {
  845. uint32 index = 0;
  846. #if (JucePlugin_WantsMidiInput || JucePlugin_WantsLV2TimePos)
  847. if (portId == index++)
  848. {
  849. portEventsIn = (LV2_Atom_Sequence*)dataLocation;
  850. return;
  851. }
  852. #endif
  853. #if JucePlugin_ProducesMidiOutput
  854. if (portId == index++)
  855. {
  856. portMidiOut = (LV2_Atom_Sequence*)dataLocation;
  857. return;
  858. }
  859. #endif
  860. if (portId == index++)
  861. {
  862. portFreewheel = (float*)dataLocation;
  863. return;
  864. }
  865. #if JucePlugin_WantsLV2Latency
  866. if (portId == index++)
  867. {
  868. portLatency = (float*)dataLocation;
  869. return;
  870. }
  871. #endif
  872. for (int i=0; i < numInChans; ++i)
  873. {
  874. if (portId == index++)
  875. {
  876. portAudioIns.set(i, (float*)dataLocation);
  877. return;
  878. }
  879. }
  880. for (int i=0; i < numOutChans; ++i)
  881. {
  882. if (portId == index++)
  883. {
  884. portAudioOuts.set(i, (float*)dataLocation);
  885. return;
  886. }
  887. }
  888. const Array<AudioProcessorParameter*>& parameters = filter->getParameters();
  889. for (int i=0; i < parameters.size(); ++i)
  890. {
  891. if (portId == index++)
  892. {
  893. portControls.set(i, (float*)dataLocation);
  894. return;
  895. }
  896. }
  897. }
  898. void lv2Activate()
  899. {
  900. jassert (filter != nullptr);
  901. filter->prepareToPlay (sampleRate, bufferSize);
  902. filter->setPlayConfigDetails (numInChans, numOutChans, sampleRate, bufferSize);
  903. channels.calloc (numInChans + numOutChans);
  904. #if (JucePlugin_WantsMidiInput || JucePlugin_ProducesMidiOutput)
  905. midiEvents.ensureSize (2048);
  906. midiEvents.clear();
  907. #endif
  908. }
  909. void lv2Deactivate()
  910. {
  911. jassert (filter != nullptr);
  912. filter->releaseResources();
  913. channels.free();
  914. }
  915. void lv2Run (uint32 sampleCount)
  916. {
  917. jassert (filter != nullptr);
  918. #if JucePlugin_WantsLV2Latency
  919. if (portLatency != nullptr)
  920. *portLatency = filter->getLatencySamples();
  921. #endif
  922. if (portFreewheel != nullptr)
  923. filter->setNonRealtime (*portFreewheel >= 0.5f);
  924. if (sampleCount == 0)
  925. {
  926. /**
  927. LV2 pre-roll
  928. Hosts might use this to force plugins to update its output control ports.
  929. (plugins can only access port locations during run) */
  930. return;
  931. }
  932. // Check for updated parameters
  933. {
  934. const Array<AudioProcessorParameter*>& parameters = filter->getParameters();
  935. float value;
  936. for (int i = 0; i < portControls.size(); ++i)
  937. {
  938. if (portControls[i] != nullptr)
  939. {
  940. value = *portControls[i];
  941. if (lastControlValues.getUnchecked (i) != value)
  942. {
  943. lastControlValues.setUnchecked (i, value);
  944. if (AudioProcessorParameter* const param = parameters[i])
  945. {
  946. if (param == bypassParameter)
  947. value = 1.f - value;
  948. param->setValue (value);
  949. #if ! JUCE_AUDIOPROCESSOR_NO_GUI
  950. inParameterChangedCallback = true;
  951. #endif
  952. param->sendValueChangedMessageToListeners (value);
  953. }
  954. }
  955. }
  956. }
  957. }
  958. {
  959. const ScopedLock sl (filter->getCallbackLock());
  960. if (filter->isSuspended() && false)
  961. {
  962. for (int i = 0; i < numOutChans; ++i)
  963. zeromem (portAudioOuts[i], sizeof (float) * sampleCount);
  964. }
  965. else
  966. {
  967. int i;
  968. for (i = 0; i < numOutChans; ++i)
  969. {
  970. channels[i] = portAudioOuts[i];
  971. if (i < numInChans && portAudioIns[i] != portAudioOuts[i])
  972. FloatVectorOperations::copy (portAudioOuts[i], const_cast<const float*>(portAudioIns[i]), (int32) sampleCount);
  973. }
  974. for (; i < numInChans; ++i)
  975. channels [i] = portAudioIns[i];
  976. #if (JucePlugin_WantsMidiInput || JucePlugin_WantsLV2TimePos)
  977. if (portEventsIn != nullptr)
  978. {
  979. midiEvents.clear();
  980. LV2_ATOM_SEQUENCE_FOREACH(portEventsIn, iter)
  981. {
  982. const LV2_Atom_Event* event = (const LV2_Atom_Event*)iter;
  983. if (event == nullptr)
  984. continue;
  985. if (event->time.frames >= sampleCount)
  986. break;
  987. #if JucePlugin_WantsMidiInput
  988. if (event->body.type == uridMidiEvent)
  989. {
  990. const uint8* data = (const uint8*)(event + 1);
  991. midiEvents.addEvent(data, event->body.size, static_cast<int>(event->time.frames));
  992. continue;
  993. }
  994. #endif
  995. #if JucePlugin_WantsLV2TimePos
  996. if (event->body.type == uridAtomBlank || event->body.type == uridAtomObject)
  997. {
  998. const LV2_Atom_Object* obj = (LV2_Atom_Object*)&event->body;
  999. if (obj->body.otype != uridTimePos)
  1000. continue;
  1001. LV2_Atom* bar = nullptr;
  1002. LV2_Atom* barBeat = nullptr;
  1003. LV2_Atom* beatUnit = nullptr;
  1004. LV2_Atom* beatsPerBar = nullptr;
  1005. LV2_Atom* beatsPerMinute = nullptr;
  1006. LV2_Atom* frame = nullptr;
  1007. LV2_Atom* speed = nullptr;
  1008. lv2_atom_object_get (obj,
  1009. uridTimeBar, &bar,
  1010. uridTimeBarBeat, &barBeat,
  1011. uridTimeBeatUnit, &beatUnit,
  1012. uridTimeBeatsPerBar, &beatsPerBar,
  1013. uridTimeBeatsPerMinute, &beatsPerMinute,
  1014. uridTimeFrame, &frame,
  1015. uridTimeSpeed, &speed,
  1016. nullptr);
  1017. // need to handle this first as other values depend on it
  1018. if (speed != nullptr)
  1019. {
  1020. /**/ if (speed->type == uridAtomDouble)
  1021. lastPositionData.speed = ((LV2_Atom_Double*)speed)->body;
  1022. else if (speed->type == uridAtomFloat)
  1023. lastPositionData.speed = ((LV2_Atom_Float*)speed)->body;
  1024. else if (speed->type == uridAtomInt)
  1025. lastPositionData.speed = ((LV2_Atom_Int*)speed)->body;
  1026. else if (speed->type == uridAtomLong)
  1027. lastPositionData.speed = ((LV2_Atom_Long*)speed)->body;
  1028. curPosInfo.isPlaying = lastPositionData.speed != 0.0;
  1029. }
  1030. if (bar != nullptr)
  1031. {
  1032. /**/ if (bar->type == uridAtomDouble)
  1033. lastPositionData.bar = ((LV2_Atom_Double*)bar)->body;
  1034. else if (bar->type == uridAtomFloat)
  1035. lastPositionData.bar = ((LV2_Atom_Float*)bar)->body;
  1036. else if (bar->type == uridAtomInt)
  1037. lastPositionData.bar = ((LV2_Atom_Int*)bar)->body;
  1038. else if (bar->type == uridAtomLong)
  1039. lastPositionData.bar = ((LV2_Atom_Long*)bar)->body;
  1040. }
  1041. if (barBeat != nullptr)
  1042. {
  1043. /**/ if (barBeat->type == uridAtomDouble)
  1044. lastPositionData.barBeat = ((LV2_Atom_Double*)barBeat)->body;
  1045. else if (barBeat->type == uridAtomFloat)
  1046. lastPositionData.barBeat = ((LV2_Atom_Float*)barBeat)->body;
  1047. else if (barBeat->type == uridAtomInt)
  1048. lastPositionData.barBeat = ((LV2_Atom_Int*)barBeat)->body;
  1049. else if (barBeat->type == uridAtomLong)
  1050. lastPositionData.barBeat = ((LV2_Atom_Long*)barBeat)->body;
  1051. }
  1052. if (beatUnit != nullptr)
  1053. {
  1054. /**/ if (beatUnit->type == uridAtomDouble)
  1055. lastPositionData.beatUnit = ((LV2_Atom_Double*)beatUnit)->body;
  1056. else if (beatUnit->type == uridAtomFloat)
  1057. lastPositionData.beatUnit = ((LV2_Atom_Float*)beatUnit)->body;
  1058. else if (beatUnit->type == uridAtomInt)
  1059. lastPositionData.beatUnit = ((LV2_Atom_Int*)beatUnit)->body;
  1060. else if (beatUnit->type == uridAtomLong)
  1061. lastPositionData.beatUnit = static_cast<uint32_t>(((LV2_Atom_Long*)beatUnit)->body);
  1062. if (lastPositionData.beatUnit > 0)
  1063. curPosInfo.timeSigDenominator = lastPositionData.beatUnit;
  1064. }
  1065. if (beatsPerBar != nullptr)
  1066. {
  1067. /**/ if (beatsPerBar->type == uridAtomDouble)
  1068. lastPositionData.beatsPerBar = ((LV2_Atom_Double*)beatsPerBar)->body;
  1069. else if (beatsPerBar->type == uridAtomFloat)
  1070. lastPositionData.beatsPerBar = ((LV2_Atom_Float*)beatsPerBar)->body;
  1071. else if (beatsPerBar->type == uridAtomInt)
  1072. lastPositionData.beatsPerBar = ((LV2_Atom_Int*)beatsPerBar)->body;
  1073. else if (beatsPerBar->type == uridAtomLong)
  1074. lastPositionData.beatsPerBar = ((LV2_Atom_Long*)beatsPerBar)->body;
  1075. if (lastPositionData.beatsPerBar > 0.0f)
  1076. curPosInfo.timeSigNumerator = lastPositionData.beatsPerBar;
  1077. }
  1078. if (beatsPerMinute != nullptr)
  1079. {
  1080. /**/ if (beatsPerMinute->type == uridAtomDouble)
  1081. lastPositionData.beatsPerMinute = ((LV2_Atom_Double*)beatsPerMinute)->body;
  1082. else if (beatsPerMinute->type == uridAtomFloat)
  1083. lastPositionData.beatsPerMinute = ((LV2_Atom_Float*)beatsPerMinute)->body;
  1084. else if (beatsPerMinute->type == uridAtomInt)
  1085. lastPositionData.beatsPerMinute = ((LV2_Atom_Int*)beatsPerMinute)->body;
  1086. else if (beatsPerMinute->type == uridAtomLong)
  1087. lastPositionData.beatsPerMinute = ((LV2_Atom_Long*)beatsPerMinute)->body;
  1088. if (lastPositionData.beatsPerMinute > 0.0f)
  1089. {
  1090. curPosInfo.bpm = lastPositionData.beatsPerMinute;
  1091. if (lastPositionData.speed != 0)
  1092. curPosInfo.bpm *= std::abs(lastPositionData.speed);
  1093. }
  1094. }
  1095. if (frame != nullptr)
  1096. {
  1097. /**/ if (frame->type == uridAtomDouble)
  1098. lastPositionData.frame = ((LV2_Atom_Double*)frame)->body;
  1099. else if (frame->type == uridAtomFloat)
  1100. lastPositionData.frame = ((LV2_Atom_Float*)frame)->body;
  1101. else if (frame->type == uridAtomInt)
  1102. lastPositionData.frame = ((LV2_Atom_Int*)frame)->body;
  1103. else if (frame->type == uridAtomLong)
  1104. lastPositionData.frame = ((LV2_Atom_Long*)frame)->body;
  1105. if (lastPositionData.frame >= 0)
  1106. {
  1107. curPosInfo.timeInSamples = lastPositionData.frame;
  1108. curPosInfo.timeInSeconds = double(curPosInfo.timeInSamples)/sampleRate;
  1109. }
  1110. }
  1111. if (lastPositionData.bar >= 0 && lastPositionData.beatsPerBar > 0.0f)
  1112. {
  1113. curPosInfo.ppqPositionOfLastBarStart = lastPositionData.bar * lastPositionData.beatsPerBar;
  1114. if (lastPositionData.barBeat >= 0.0f)
  1115. curPosInfo.ppqPosition = curPosInfo.ppqPositionOfLastBarStart + lastPositionData.barBeat;
  1116. }
  1117. lastPositionData.extraValid = (lastPositionData.beatsPerMinute > 0.0 &&
  1118. lastPositionData.beatUnit > 0 &&
  1119. lastPositionData.beatsPerBar > 0.0f);
  1120. }
  1121. #endif
  1122. }
  1123. }
  1124. #endif
  1125. {
  1126. AudioSampleBuffer chans (channels, jmax (numInChans, numOutChans), sampleCount);
  1127. filter->processBlock (chans, midiEvents);
  1128. }
  1129. }
  1130. }
  1131. #if JucePlugin_WantsLV2TimePos
  1132. // update timePos for next callback
  1133. if (lastPositionData.speed != 0.0)
  1134. {
  1135. if (lastPositionData.speed > 0.0)
  1136. {
  1137. // playing forwards
  1138. lastPositionData.frame += sampleCount;
  1139. }
  1140. else
  1141. {
  1142. // playing backwards
  1143. lastPositionData.frame -= sampleCount;
  1144. if (lastPositionData.frame < 0)
  1145. lastPositionData.frame = 0;
  1146. }
  1147. curPosInfo.timeInSamples = lastPositionData.frame;
  1148. curPosInfo.timeInSeconds = double(curPosInfo.timeInSamples)/sampleRate;
  1149. if (lastPositionData.extraValid)
  1150. {
  1151. const double beatsPerMinute = lastPositionData.beatsPerMinute * lastPositionData.speed;
  1152. const double framesPerBeat = 60.0 * sampleRate / beatsPerMinute;
  1153. const double addedBarBeats = double(sampleCount) / framesPerBeat;
  1154. if (lastPositionData.bar >= 0 && lastPositionData.barBeat >= 0.0f)
  1155. {
  1156. lastPositionData.bar += std::floor((lastPositionData.barBeat+addedBarBeats)/
  1157. lastPositionData.beatsPerBar);
  1158. lastPositionData.barBeat = std::fmod(lastPositionData.barBeat+addedBarBeats,
  1159. lastPositionData.beatsPerBar);
  1160. if (lastPositionData.bar < 0)
  1161. lastPositionData.bar = 0;
  1162. curPosInfo.ppqPositionOfLastBarStart = lastPositionData.bar * lastPositionData.beatsPerBar;
  1163. curPosInfo.ppqPosition = curPosInfo.ppqPositionOfLastBarStart + lastPositionData.barBeat;
  1164. }
  1165. curPosInfo.bpm = std::abs(beatsPerMinute);
  1166. }
  1167. }
  1168. #endif
  1169. #if JucePlugin_ProducesMidiOutput
  1170. if (portMidiOut != nullptr)
  1171. {
  1172. const uint32_t capacity = portMidiOut->atom.size;
  1173. portMidiOut->atom.size = sizeof(LV2_Atom_Sequence_Body);
  1174. portMidiOut->atom.type = uridAtomSequence;
  1175. portMidiOut->body.unit = 0;
  1176. portMidiOut->body.pad = 0;
  1177. if (! midiEvents.isEmpty())
  1178. {
  1179. const uint8* midiEventData;
  1180. int midiEventSize, midiEventPosition;
  1181. MidiBuffer::Iterator i (midiEvents);
  1182. uint32_t size, offset = 0;
  1183. LV2_Atom_Event* aev;
  1184. while (i.getNextEvent (midiEventData, midiEventSize, midiEventPosition))
  1185. {
  1186. jassert (midiEventPosition >= 0 && midiEventPosition < (int)sampleCount);
  1187. if (sizeof(LV2_Atom_Event) + midiEventSize > capacity - offset)
  1188. break;
  1189. aev = (LV2_Atom_Event*)((char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, portMidiOut) + offset);
  1190. aev->time.frames = midiEventPosition;
  1191. aev->body.type = uridMidiEvent;
  1192. aev->body.size = midiEventSize;
  1193. memcpy(LV2_ATOM_BODY(&aev->body), midiEventData, midiEventSize);
  1194. size = lv2_atom_pad_size(sizeof(LV2_Atom_Event) + midiEventSize);
  1195. offset += size;
  1196. portMidiOut->atom.size += size;
  1197. }
  1198. midiEvents.clear();
  1199. }
  1200. } else
  1201. #endif
  1202. if (! midiEvents.isEmpty())
  1203. {
  1204. midiEvents.clear();
  1205. }
  1206. }
  1207. //==============================================================================
  1208. // LV2 extended calls
  1209. uint32_t lv2GetOptions (LV2_Options_Option* options)
  1210. {
  1211. // currently unused
  1212. ignoreUnused(options);
  1213. return LV2_OPTIONS_SUCCESS;
  1214. }
  1215. uint32_t lv2SetOptions (const LV2_Options_Option* options)
  1216. {
  1217. for (int i=0; options[i].key != 0; ++i)
  1218. {
  1219. if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__nominalBlockLength))
  1220. {
  1221. if (options[i].type == uridAtomInt)
  1222. bufferSize = *(const int32_t*)options[i].value;
  1223. else
  1224. std::cerr << "Host changed nominalBlockLength but with wrong value type" << std::endl;
  1225. }
  1226. else if (options[i].key == uridMap->map(uridMap->handle, LV2_BUF_SIZE__maxBlockLength) && ! usingNominalBlockLength)
  1227. {
  1228. if (options[i].type == uridAtomInt)
  1229. bufferSize = *(const int32_t*)options[i].value;
  1230. else
  1231. std::cerr << "Host changed maxBlockLength but with wrong value type" << std::endl;
  1232. }
  1233. else if (options[i].key == uridMap->map(uridMap->handle, LV2_PARAMETERS__sampleRate))
  1234. {
  1235. if (options[i].type == uridAtomFloat)
  1236. sampleRate = *(const float*)options[i].value;
  1237. else
  1238. std::cerr << "Host changed sampleRate but with wrong value type" << std::endl;
  1239. }
  1240. }
  1241. return LV2_OPTIONS_SUCCESS;
  1242. }
  1243. const LV2_Program_Descriptor* lv2GetProgram (uint32_t index)
  1244. {
  1245. jassert (filter != nullptr);
  1246. if (progDesc.name != nullptr)
  1247. {
  1248. free((void*)progDesc.name);
  1249. progDesc.name = nullptr;
  1250. }
  1251. if ((int)index < filter->getNumPrograms())
  1252. {
  1253. progDesc.bank = index / 128;
  1254. progDesc.program = index % 128;
  1255. progDesc.name = strdup(filter->getProgramName(index).toUTF8());
  1256. return &progDesc;
  1257. }
  1258. return nullptr;
  1259. }
  1260. void lv2SelectProgram (uint32_t bank, uint32_t program)
  1261. {
  1262. jassert (filter != nullptr);
  1263. int realProgram = bank * 128 + program;
  1264. if (realProgram < filter->getNumPrograms())
  1265. {
  1266. filter->setCurrentProgram(realProgram);
  1267. // update input control ports now
  1268. const Array<AudioProcessorParameter*>& parameters = filter->getParameters();
  1269. float value;
  1270. for (int i = 0; i < portControls.size(); ++i)
  1271. {
  1272. if (AudioProcessorParameter* const param = parameters[i])
  1273. {
  1274. value = param->getValue();
  1275. if (param == bypassParameter)
  1276. value = 1.f - value;
  1277. lastControlValues.setUnchecked (i, value);
  1278. if (float* const portControlPtr = portControls.getUnchecked(i))
  1279. *portControlPtr = value;
  1280. }
  1281. }
  1282. }
  1283. }
  1284. LV2_State_Status lv2SaveState (LV2_State_Store_Function store, LV2_State_Handle stateHandle)
  1285. {
  1286. jassert (filter != nullptr);
  1287. #if JucePlugin_WantsLV2StateString
  1288. String stateData(filter->getStateInformationString().replace("\r\n","\n"));
  1289. CharPointer_UTF8 charData(stateData.toUTF8());
  1290. store (stateHandle,
  1291. uridMap->map(uridMap->handle, JUCE_LV2_STATE_STRING_URI),
  1292. charData.getAddress(),
  1293. charData.sizeInBytes(),
  1294. uridMap->map(uridMap->handle, LV2_ATOM__String),
  1295. LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE);
  1296. #else
  1297. MemoryBlock chunkMemory;
  1298. filter->getCurrentProgramStateInformation (chunkMemory);
  1299. store (stateHandle,
  1300. uridMap->map(uridMap->handle, JUCE_LV2_STATE_BINARY_URI),
  1301. chunkMemory.getData(),
  1302. chunkMemory.getSize(),
  1303. uridMap->map(uridMap->handle, LV2_ATOM__Chunk),
  1304. LV2_STATE_IS_POD|LV2_STATE_IS_PORTABLE);
  1305. #endif
  1306. return LV2_STATE_SUCCESS;
  1307. }
  1308. LV2_State_Status lv2RestoreState (LV2_State_Retrieve_Function retrieve, LV2_State_Handle stateHandle, uint32_t flags)
  1309. {
  1310. jassert (filter != nullptr);
  1311. size_t size = 0;
  1312. uint32 type = 0;
  1313. const void* data = retrieve (stateHandle,
  1314. #if JucePlugin_WantsLV2StateString
  1315. uridMap->map(uridMap->handle, JUCE_LV2_STATE_STRING_URI),
  1316. #else
  1317. uridMap->map(uridMap->handle, JUCE_LV2_STATE_BINARY_URI),
  1318. #endif
  1319. &size, &type, &flags);
  1320. if (data == nullptr || size == 0 || type == 0)
  1321. return LV2_STATE_ERR_UNKNOWN;
  1322. #if JucePlugin_WantsLV2StateString
  1323. if (type == uridMap->map (uridMap->handle, LV2_ATOM__String))
  1324. {
  1325. String stateData (CharPointer_UTF8(static_cast<const char*>(data)));
  1326. filter->setStateInformationString (stateData);
  1327. #if ! JUCE_AUDIOPROCESSOR_NO_GUI
  1328. if (ui != nullptr)
  1329. ui->repaint();
  1330. #endif
  1331. return LV2_STATE_SUCCESS;
  1332. }
  1333. #else
  1334. if (type == uridMap->map (uridMap->handle, LV2_ATOM__Chunk))
  1335. {
  1336. filter->setCurrentProgramStateInformation (data, static_cast<int>(size));
  1337. #if ! JUCE_AUDIOPROCESSOR_NO_GUI
  1338. if (ui != nullptr)
  1339. ui->repaint();
  1340. #endif
  1341. return LV2_STATE_SUCCESS;
  1342. }
  1343. #endif
  1344. return LV2_STATE_ERR_BAD_TYPE;
  1345. }
  1346. //==============================================================================
  1347. // Juce calls
  1348. bool getCurrentPosition (AudioPlayHead::CurrentPositionInfo& info)
  1349. {
  1350. #if JucePlugin_WantsLV2TimePos
  1351. info = curPosInfo;
  1352. return true;
  1353. #else
  1354. ignoreUnused(info);
  1355. return false;
  1356. #endif
  1357. }
  1358. #if ! JUCE_AUDIOPROCESSOR_NO_GUI
  1359. //==============================================================================
  1360. JuceLv2UIWrapper* getUI (LV2UI_Write_Function writeFunction,
  1361. LV2UI_Controller controller,
  1362. LV2UI_Widget* widget,
  1363. const LV2_Feature* const* features,
  1364. bool isExternal)
  1365. {
  1366. const MessageManagerLock mmLock;
  1367. if (ui != nullptr)
  1368. ui->resetIfNeeded (writeFunction, controller, widget, features);
  1369. else
  1370. ui = std::make_unique<JuceLv2UIWrapper> (filter.get(),
  1371. writeFunction, controller, widget, features, isExternal,
  1372. numInChans, numOutChans);
  1373. return ui.get();
  1374. }
  1375. #endif
  1376. private:
  1377. #if JUCE_LINUX
  1378. SharedResourcePointer<SharedMessageThread> msgThread;
  1379. #else
  1380. SharedResourcePointer<ScopedJuceInitialiser_GUI> sharedJuceGUI;
  1381. #endif
  1382. std::unique_ptr<AudioProcessor> filter;
  1383. #if ! JUCE_AUDIOPROCESSOR_NO_GUI
  1384. std::unique_ptr<JuceLv2UIWrapper> ui;
  1385. #endif
  1386. HeapBlock<float*> channels;
  1387. MidiBuffer midiEvents;
  1388. int numInChans, numOutChans;
  1389. #if (JucePlugin_WantsMidiInput || JucePlugin_WantsLV2TimePos)
  1390. LV2_Atom_Sequence* portEventsIn;
  1391. #endif
  1392. #if JucePlugin_ProducesMidiOutput
  1393. LV2_Atom_Sequence* portMidiOut;
  1394. #endif
  1395. float* portFreewheel;
  1396. #if JucePlugin_WantsLV2Latency
  1397. float* portLatency;
  1398. #endif
  1399. Array<float*> portAudioIns;
  1400. Array<float*> portAudioOuts;
  1401. Array<float*> portControls;
  1402. uint32 bufferSize;
  1403. double sampleRate;
  1404. Array<float> lastControlValues;
  1405. AudioPlayHead::CurrentPositionInfo curPosInfo;
  1406. AudioProcessorParameter* bypassParameter;
  1407. struct Lv2PositionData {
  1408. int64_t bar;
  1409. float barBeat;
  1410. uint32_t beatUnit;
  1411. float beatsPerBar;
  1412. float beatsPerMinute;
  1413. int64_t frame;
  1414. double speed;
  1415. bool extraValid;
  1416. Lv2PositionData()
  1417. : bar(-1),
  1418. barBeat(-1.0f),
  1419. beatUnit(0),
  1420. beatsPerBar(0.0f),
  1421. beatsPerMinute(0.0f),
  1422. frame(-1),
  1423. speed(0.0),
  1424. extraValid(false) {}
  1425. };
  1426. Lv2PositionData lastPositionData;
  1427. const LV2_URID_Map* uridMap;
  1428. LV2_URID uridAtomBlank;
  1429. LV2_URID uridAtomObject;
  1430. LV2_URID uridAtomDouble;
  1431. LV2_URID uridAtomFloat;
  1432. LV2_URID uridAtomInt;
  1433. LV2_URID uridAtomLong;
  1434. LV2_URID uridAtomSequence;
  1435. LV2_URID uridMidiEvent;
  1436. LV2_URID uridTimePos;
  1437. LV2_URID uridTimeBar;
  1438. LV2_URID uridTimeBarBeat;
  1439. LV2_URID uridTimeBeatsPerBar; // timeSigNumerator
  1440. LV2_URID uridTimeBeatsPerMinute; // bpm
  1441. LV2_URID uridTimeBeatUnit; // timeSigDenominator
  1442. LV2_URID uridTimeFrame; // timeInSamples
  1443. LV2_URID uridTimeSpeed;
  1444. bool usingNominalBlockLength; // if false use maxBlockLength
  1445. LV2_Program_Descriptor progDesc;
  1446. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceLv2Wrapper)
  1447. };
  1448. //==============================================================================
  1449. // LV2 descriptor functions
  1450. static LV2_Handle juceLV2_Instantiate (const LV2_Descriptor*, double sampleRate, const char*, const LV2_Feature* const* features)
  1451. {
  1452. return new JuceLv2Wrapper (sampleRate, features);
  1453. }
  1454. #define handlePtr ((JuceLv2Wrapper*)handle)
  1455. static void juceLV2_ConnectPort (LV2_Handle handle, uint32 port, void* dataLocation)
  1456. {
  1457. handlePtr->lv2ConnectPort (port, dataLocation);
  1458. }
  1459. static void juceLV2_Activate (LV2_Handle handle)
  1460. {
  1461. handlePtr->lv2Activate();
  1462. }
  1463. static void juceLV2_Run( LV2_Handle handle, uint32 sampleCount)
  1464. {
  1465. handlePtr->lv2Run (sampleCount);
  1466. }
  1467. static void juceLV2_Deactivate (LV2_Handle handle)
  1468. {
  1469. handlePtr->lv2Deactivate();
  1470. }
  1471. static void juceLV2_Cleanup (LV2_Handle handle)
  1472. {
  1473. delete handlePtr;
  1474. }
  1475. //==============================================================================
  1476. // LV2 extended functions
  1477. static uint32_t juceLV2_getOptions (LV2_Handle handle, LV2_Options_Option* options)
  1478. {
  1479. return handlePtr->lv2GetOptions(options);
  1480. }
  1481. static uint32_t juceLV2_setOptions (LV2_Handle handle, const LV2_Options_Option* options)
  1482. {
  1483. return handlePtr->lv2SetOptions(options);
  1484. }
  1485. static const LV2_Program_Descriptor* juceLV2_getProgram (LV2_Handle handle, uint32_t index)
  1486. {
  1487. return handlePtr->lv2GetProgram(index);
  1488. }
  1489. static void juceLV2_selectProgram (LV2_Handle handle, uint32_t bank, uint32_t program)
  1490. {
  1491. handlePtr->lv2SelectProgram(bank, program);
  1492. }
  1493. #if JucePlugin_WantsLV2State
  1494. static LV2_State_Status juceLV2_SaveState (LV2_Handle handle, LV2_State_Store_Function store, LV2_State_Handle stateHandle,
  1495. uint32_t, const LV2_Feature* const*)
  1496. {
  1497. return handlePtr->lv2SaveState(store, stateHandle);
  1498. }
  1499. static LV2_State_Status juceLV2_RestoreState (LV2_Handle handle, LV2_State_Retrieve_Function retrieve, LV2_State_Handle stateHandle,
  1500. uint32_t flags, const LV2_Feature* const*)
  1501. {
  1502. return handlePtr->lv2RestoreState(retrieve, stateHandle, flags);
  1503. }
  1504. #endif
  1505. #undef handlePtr
  1506. static const void* juceLV2_ExtensionData (const char* uri)
  1507. {
  1508. static const LV2_Options_Interface options = { juceLV2_getOptions, juceLV2_setOptions };
  1509. static const LV2_Programs_Interface programs = { juceLV2_getProgram, juceLV2_selectProgram };
  1510. #if JucePlugin_WantsLV2State
  1511. static const LV2_State_Interface state = { juceLV2_SaveState, juceLV2_RestoreState };
  1512. #endif
  1513. if (strcmp(uri, LV2_OPTIONS__interface) == 0)
  1514. return &options;
  1515. if (strcmp(uri, LV2_PROGRAMS__Interface) == 0)
  1516. return &programs;
  1517. #if JucePlugin_WantsLV2State
  1518. if (strcmp(uri, LV2_STATE__interface) == 0)
  1519. return &state;
  1520. #endif
  1521. return nullptr;
  1522. }
  1523. #if ! JUCE_AUDIOPROCESSOR_NO_GUI
  1524. //==============================================================================
  1525. // LV2 UI descriptor functions
  1526. static LV2UI_Handle juceLV2UI_Instantiate (LV2UI_Write_Function writeFunction, LV2UI_Controller controller,
  1527. LV2UI_Widget* widget, const LV2_Feature* const* features, bool isExternal)
  1528. {
  1529. for (int i = 0; features[i] != nullptr; ++i)
  1530. {
  1531. if (strcmp(features[i]->URI, LV2_INSTANCE_ACCESS_URI) == 0 && features[i]->data != nullptr)
  1532. {
  1533. JuceLv2Wrapper* wrapper = (JuceLv2Wrapper*)features[i]->data;
  1534. return wrapper->getUI(writeFunction, controller, widget, features, isExternal);
  1535. }
  1536. }
  1537. std::cerr << "Host does not support instance-access, cannot use UI" << std::endl;
  1538. return nullptr;
  1539. }
  1540. static LV2UI_Handle juceLV2UI_InstantiateExternal (const LV2UI_Descriptor*, const char*, const char*, LV2UI_Write_Function writeFunction,
  1541. LV2UI_Controller controller, LV2UI_Widget* widget, const LV2_Feature* const* features)
  1542. {
  1543. return juceLV2UI_Instantiate(writeFunction, controller, widget, features, true);
  1544. }
  1545. static LV2UI_Handle juceLV2UI_InstantiateParent (const LV2UI_Descriptor*, const char*, const char*, LV2UI_Write_Function writeFunction,
  1546. LV2UI_Controller controller, LV2UI_Widget* widget, const LV2_Feature* const* features)
  1547. {
  1548. return juceLV2UI_Instantiate(writeFunction, controller, widget, features, false);
  1549. }
  1550. static void juceLV2UI_Cleanup (LV2UI_Handle handle)
  1551. {
  1552. ((JuceLv2UIWrapper*)handle)->lv2Cleanup();
  1553. }
  1554. //==============================================================================
  1555. // LV2 UI extended functions
  1556. static int juceLV2UI_idle (LV2UI_Handle handle)
  1557. {
  1558. return ((JuceLv2UIWrapper*)handle)->lv2Idle();
  1559. }
  1560. static const void* juceLV2UI_ExtensionData (const char* uri)
  1561. {
  1562. static const LV2UI_Idle_Interface idle = { juceLV2UI_idle };
  1563. if (strcmp(uri, LV2_UI__idleInterface) == 0)
  1564. {
  1565. #if JUCE_LINUX
  1566. JuceLv2UIWrapper::hostHasIdleInterface = true;
  1567. #endif
  1568. return &idle;
  1569. }
  1570. return nullptr;
  1571. }
  1572. #endif
  1573. //==============================================================================
  1574. // static LV2 Descriptor objects
  1575. static const LV2_Descriptor JuceLv2Plugin = {
  1576. strdup(getPluginURI().toRawUTF8()),
  1577. juceLV2_Instantiate,
  1578. juceLV2_ConnectPort,
  1579. juceLV2_Activate,
  1580. juceLV2_Run,
  1581. juceLV2_Deactivate,
  1582. juceLV2_Cleanup,
  1583. juceLV2_ExtensionData
  1584. };
  1585. #if ! JUCE_AUDIOPROCESSOR_NO_GUI
  1586. static const LV2UI_Descriptor JuceLv2UI_External = {
  1587. strdup(String(getPluginURI() + "#ExternalUI").toRawUTF8()),
  1588. juceLV2UI_InstantiateExternal,
  1589. juceLV2UI_Cleanup,
  1590. nullptr,
  1591. nullptr
  1592. };
  1593. static const LV2UI_Descriptor JuceLv2UI_Parent = {
  1594. strdup(String(getPluginURI() + "#ParentUI").toRawUTF8()),
  1595. juceLV2UI_InstantiateParent,
  1596. juceLV2UI_Cleanup,
  1597. nullptr,
  1598. juceLV2UI_ExtensionData
  1599. };
  1600. #endif
  1601. static const struct DescriptorCleanup {
  1602. DescriptorCleanup() {}
  1603. ~DescriptorCleanup()
  1604. {
  1605. free((void*)JuceLv2Plugin.URI);
  1606. #if ! JUCE_AUDIOPROCESSOR_NO_GUI
  1607. free((void*)JuceLv2UI_External.URI);
  1608. free((void*)JuceLv2UI_Parent.URI);
  1609. #endif
  1610. }
  1611. } _descCleanup;
  1612. #if JUCE_WINDOWS
  1613. #define JUCE_EXPORTED_FUNCTION extern "C" __declspec (dllexport)
  1614. #else
  1615. #define JUCE_EXPORTED_FUNCTION extern "C" __attribute__ ((visibility("default")))
  1616. #endif
  1617. //==============================================================================
  1618. // startup code..
  1619. JUCE_EXPORTED_FUNCTION const LV2_Descriptor* lv2_descriptor (uint32 index);
  1620. JUCE_EXPORTED_FUNCTION const LV2_Descriptor* lv2_descriptor (uint32 index)
  1621. {
  1622. return (index == 0) ? &JuceLv2Plugin : nullptr;
  1623. }
  1624. #if ! JUCE_AUDIOPROCESSOR_NO_GUI
  1625. JUCE_EXPORTED_FUNCTION const LV2UI_Descriptor* lv2ui_descriptor (uint32 index);
  1626. JUCE_EXPORTED_FUNCTION const LV2UI_Descriptor* lv2ui_descriptor (uint32 index)
  1627. {
  1628. switch (index)
  1629. {
  1630. case 0:
  1631. return &JuceLv2UI_External;
  1632. case 1:
  1633. return &JuceLv2UI_Parent;
  1634. default:
  1635. return nullptr;
  1636. }
  1637. }
  1638. #endif
  1639. #ifndef JUCE_LV2_WRAPPER_WITHOUT_EXPORTER
  1640. #include "juce_LV2_Wrapper_Exporter.cpp"
  1641. #endif
  1642. #endif