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.

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