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.

1146 lines
47KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2022 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 7 End-User License
  8. Agreement and JUCE Privacy Policy.
  9. End User License Agreement: www.juce.com/juce-7-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. #pragma once
  19. namespace juce
  20. {
  21. class ARADocumentController;
  22. class ARADocument;
  23. class ARAMusicalContext;
  24. class ARARegionSequence;
  25. class ARAAudioSource;
  26. class ARAAudioModification;
  27. class ARAPlaybackRegion;
  28. /** Base class used by the JUCE ARA model objects to provide listenable interfaces.
  29. @tags{ARA}
  30. */
  31. template <class ListenerType>
  32. class JUCE_API ARAListenableModelClass
  33. {
  34. public:
  35. /** Constructor. */
  36. ARAListenableModelClass() = default;
  37. /** Destructor. */
  38. virtual ~ARAListenableModelClass() = default;
  39. /** Subscribe \p l to notified by changes to the object.
  40. @param l The listener instance.
  41. */
  42. void addListener (ListenerType* l) { listeners.add (l); }
  43. /** Unsubscribe \p l from object notifications.
  44. @param l The listener instance.
  45. */
  46. void removeListener (ListenerType* l) { listeners.remove (l); }
  47. /** Call the provided callback for each of the added listeners. */
  48. template <typename Callback>
  49. void notifyListeners (Callback&& callback)
  50. {
  51. listeners.call (callback);
  52. }
  53. private:
  54. ListenerList<ListenerType> listeners;
  55. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ARAListenableModelClass)
  56. };
  57. /** Create a derived implementation of this class and pass it to ARAObject::visit() to retrieve the
  58. concrete type of a model object.
  59. Combined with ARAObject::traverse() on the ARADocument object it is possible to discover the
  60. entire model graph.
  61. Note that the references passed to the visit member functions are only guaranteed to live for
  62. the duration of the function call, so don't store pointers to these objects!
  63. @tags{Audio}
  64. */
  65. class ARAObjectVisitor
  66. {
  67. public:
  68. /** Destructor. */
  69. virtual ~ARAObjectVisitor() = default;
  70. /** Called when visiting an ARADocument object. */
  71. virtual void visitDocument (juce::ARADocument&) {}
  72. /** Called when visiting an ARAMusicalContext object. */
  73. virtual void visitMusicalContext (juce::ARAMusicalContext&) {}
  74. /** Called when visiting an ARARegionSequence object. */
  75. virtual void visitRegionSequence (juce::ARARegionSequence&) {}
  76. /** Called when visiting an ARAPlaybackRegion object. */
  77. virtual void visitPlaybackRegion (juce::ARAPlaybackRegion&) {}
  78. /** Called when visiting an ARAAudioModification object. */
  79. virtual void visitAudioModification (juce::ARAAudioModification&) {}
  80. /** Called when visiting an ARAAudioSource object. */
  81. virtual void visitAudioSource (juce::ARAAudioSource&) {}
  82. };
  83. /** Common base class for all JUCE ARA model objects to aid with the discovery and traversal of the
  84. entire ARA model graph.
  85. @tags{ARA}
  86. */
  87. class ARAObject
  88. {
  89. public:
  90. /** Destructor. */
  91. virtual ~ARAObject() = default;
  92. /** Returns the number of ARA model objects aggregated by this object. Objects that are merely
  93. referred to, but not aggregated by the current object are not included in this count, e.g.
  94. a referenced RegionSequence does not count as a child of the referring PlaybackRegion.
  95. See the ARA documentation's ARA Model Graph Overview for more details.
  96. */
  97. virtual size_t getNumChildren() const noexcept = 0;
  98. /** Returns the child object associated with the given index.
  99. The index should be smaller than the value returned by getNumChildren().
  100. Note that the index of a particular object may change when the ARA model graph is edited.
  101. */
  102. virtual ARAObject* getChild (size_t index) = 0;
  103. /** Returns the ARA model object that aggregates this object.
  104. Returns nullptr for the ARADocument root object.
  105. */
  106. virtual ARAObject* getParent() = 0;
  107. /** Implements a depth first traversal of the ARA model graph starting from the current object,
  108. and visiting its children recursively.
  109. The provided function should accept a single ARAObject& parameter.
  110. */
  111. template <typename Fn>
  112. void traverse (Fn&& fn)
  113. {
  114. fn (*this);
  115. for (size_t i = 0; i < getNumChildren(); ++i)
  116. {
  117. getChild (i)->traverse (fn);
  118. }
  119. }
  120. /** Allows the retrieval of the concrete type of a model object.
  121. To use this, create a new class derived from ARAObjectVisitor and override its functions
  122. depending on which concrete types you are interested in.
  123. Calling this function inside the function passed to ARAObject::traverse() allows you to
  124. map the entire ARA model graph.
  125. */
  126. virtual void visit (ARAObjectVisitor& visitor) = 0;
  127. };
  128. /** A base class for listeners that want to know about changes to an ARADocument object.
  129. Use ARADocument::addListener() to register your listener with an ARADocument.
  130. @tags{ARA}
  131. */
  132. class JUCE_API ARADocumentListener
  133. {
  134. public:
  135. /** Destructor */
  136. virtual ~ARADocumentListener() = default;
  137. ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_BEGIN
  138. /** Called before the document enters an editing state.
  139. @param document The document about to enter an editing state.
  140. */
  141. virtual void willBeginEditing (ARADocument* document)
  142. {
  143. ignoreUnused (document);
  144. }
  145. /** Called after the document exits an editing state.
  146. @param document The document about exit an editing state.
  147. */
  148. virtual void didEndEditing (ARADocument* document)
  149. {
  150. ignoreUnused (document);
  151. }
  152. /** Called before sending model updates do the host.
  153. @param document The document whose model updates are about to be sent.
  154. */
  155. virtual void willNotifyModelUpdates (ARADocument* document)
  156. {
  157. ignoreUnused (document);
  158. }
  159. /** Called after sending model updates do the host.
  160. @param document The document whose model updates have just been sent.
  161. */
  162. virtual void didNotifyModelUpdates (ARADocument* document)
  163. {
  164. ignoreUnused (document);
  165. }
  166. /** Called before the document's properties are updated.
  167. @param document The document whose properties will be updated.
  168. @param newProperties The document properties that will be assigned to \p document.
  169. */
  170. virtual void willUpdateDocumentProperties (ARADocument* document,
  171. ARA::PlugIn::PropertiesPtr<ARA::ARADocumentProperties> newProperties)
  172. {
  173. ignoreUnused (document, newProperties);
  174. }
  175. /** Called after the document's properties are updated.
  176. @param document The document whose properties were updated.
  177. */
  178. virtual void didUpdateDocumentProperties (ARADocument* document)
  179. {
  180. ignoreUnused (document);
  181. }
  182. /** Called after a musical context is added to the document.
  183. @param document The document that \p musicalContext was added to.
  184. @param musicalContext The musical context that was added to \p document.
  185. */
  186. virtual void didAddMusicalContextToDocument (ARADocument* document, ARAMusicalContext* musicalContext)
  187. {
  188. ignoreUnused (document, musicalContext);
  189. }
  190. /** Called before a musical context is removed from the document.
  191. @param document The document that \p musicalContext will be removed from.
  192. @param musicalContext The musical context that will be removed from \p document.
  193. */
  194. virtual void willRemoveMusicalContextFromDocument (ARADocument* document,
  195. ARAMusicalContext* musicalContext)
  196. {
  197. ignoreUnused (document, musicalContext);
  198. }
  199. /** Called after the musical contexts are reordered in an ARA document
  200. Musical contexts are sorted by their order index -
  201. this callback signals a change in this ordering within the document.
  202. @param document The document with reordered musical contexts.
  203. */
  204. virtual void didReorderMusicalContextsInDocument (ARADocument* document)
  205. {
  206. ignoreUnused (document);
  207. }
  208. /** Called after a region sequence is added to the document.
  209. @param document The document that \p regionSequence was added to.
  210. @param regionSequence The region sequence that was added to \p document.
  211. */
  212. virtual void didAddRegionSequenceToDocument (ARADocument* document, ARARegionSequence* regionSequence)
  213. {
  214. ignoreUnused (document, regionSequence);
  215. }
  216. /** Called before a region sequence is removed from the document.
  217. @param document The document that \p regionSequence will be removed from.
  218. @param regionSequence The region sequence that will be removed from \p document.
  219. */
  220. virtual void willRemoveRegionSequenceFromDocument (ARADocument* document,
  221. ARARegionSequence* regionSequence)
  222. {
  223. ignoreUnused (document, regionSequence);
  224. }
  225. /** Called after the region sequences are reordered in an ARA document
  226. Region sequences are sorted by their order index -
  227. this callback signals a change in this ordering within the document.
  228. @param document The document with reordered region sequences.
  229. */
  230. virtual void didReorderRegionSequencesInDocument (ARADocument* document)
  231. {
  232. ignoreUnused (document);
  233. }
  234. /** Called after an audio source is added to the document.
  235. @param document The document that \p audioSource was added to.
  236. @param audioSource The audio source that was added to \p document.
  237. */
  238. virtual void didAddAudioSourceToDocument (ARADocument* document, ARAAudioSource* audioSource)
  239. {
  240. ignoreUnused (document, audioSource);
  241. }
  242. /** Called before an audio source is removed from the document.
  243. @param document The document that \p audioSource will be removed from .
  244. @param audioSource The audio source that will be removed from \p document.
  245. */
  246. virtual void willRemoveAudioSourceFromDocument (ARADocument* document, ARAAudioSource* audioSource)
  247. {
  248. ignoreUnused (document, audioSource);
  249. }
  250. /** Called before the document is destroyed by the ARA host.
  251. @param document The document that will be destroyed.
  252. */
  253. virtual void willDestroyDocument (ARADocument* document)
  254. {
  255. ignoreUnused (document);
  256. }
  257. ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_END
  258. };
  259. //==============================================================================
  260. /** Base class representing an ARA document.
  261. @tags{ARA}
  262. */
  263. class JUCE_API ARADocument : public ARA::PlugIn::Document,
  264. public ARAListenableModelClass<ARADocumentListener>,
  265. public ARAObject
  266. {
  267. public:
  268. using PropertiesPtr = ARA::PlugIn::PropertiesPtr<ARA::ARADocumentProperties>;
  269. using Listener = ARADocumentListener;
  270. using ARA::PlugIn::Document::Document;
  271. /** Returns the result of ARA::PlugIn::Document::getAudioSources() with the pointers within
  272. cast to ARAAudioSource*.
  273. If you have overridden ARADocumentControllerSpecialisation::doCreateAudioSource(), then
  274. you can use the template parameter to cast the pointers to your subclass of ARAAudioSource.
  275. */
  276. template <typename AudioSource_t = ARAAudioSource>
  277. const std::vector<AudioSource_t*>& getAudioSources() const noexcept
  278. {
  279. return ARA::PlugIn::Document::getAudioSources<AudioSource_t>();
  280. }
  281. /** Returns the result of ARA::PlugIn::Document::getMusicalContexts() with the pointers within
  282. cast to ARAMusicalContext*.
  283. If you have overridden ARADocumentControllerSpecialisation::doCreateMusicalContext(), then
  284. you can use the template parameter to cast the pointers to your subclass of ARAMusicalContext.
  285. */
  286. template <typename MusicalContext_t = ARAMusicalContext>
  287. const std::vector<MusicalContext_t*>& getMusicalContexts() const noexcept
  288. {
  289. return ARA::PlugIn::Document::getMusicalContexts<MusicalContext_t>();
  290. }
  291. /** Returns the result of ARA::PlugIn::Document::getRegionSequences() with the pointers within
  292. cast to ARARegionSequence*.
  293. If you have overridden ARADocumentControllerSpecialisation::doCreateRegionSequence(), then
  294. you can use the template parameter to cast the pointers to your subclass of ARARegionSequence.
  295. */
  296. template <typename RegionSequence_t = ARARegionSequence>
  297. const std::vector<RegionSequence_t*>& getRegionSequences() const noexcept
  298. {
  299. return ARA::PlugIn::Document::getRegionSequences<RegionSequence_t>();
  300. }
  301. size_t getNumChildren() const noexcept override;
  302. ARAObject* getChild (size_t index) override;
  303. ARAObject* getParent() override { return nullptr; }
  304. void visit (ARAObjectVisitor& visitor) override { visitor.visitDocument (*this); }
  305. };
  306. /** A base class for listeners that want to know about changes to an ARAMusicalContext object.
  307. Use ARAMusicalContext::addListener() to register your listener with an ARAMusicalContext.
  308. @tags{ARA}
  309. */
  310. class JUCE_API ARAMusicalContextListener
  311. {
  312. public:
  313. virtual ~ARAMusicalContextListener() = default;
  314. ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_BEGIN
  315. /** Called before the musical context's properties are updated.
  316. @param musicalContext The musical context whose properties will be updated.
  317. @param newProperties The musical context properties that will be assigned to \p musicalContext.
  318. */
  319. virtual void willUpdateMusicalContextProperties (ARAMusicalContext* musicalContext,
  320. ARA::PlugIn::PropertiesPtr<ARA::ARAMusicalContextProperties> newProperties)
  321. {
  322. ignoreUnused (musicalContext, newProperties);
  323. }
  324. /** Called after the musical context's properties are updated by the host.
  325. @param musicalContext The musical context whose properties were updated.
  326. */
  327. virtual void didUpdateMusicalContextProperties (ARAMusicalContext* musicalContext)
  328. {
  329. ignoreUnused (musicalContext);
  330. }
  331. /** Called when the musical context's content (i.e tempo entries or chords) changes.
  332. @param musicalContext The musical context with updated content.
  333. @param scopeFlags The scope of the content update indicating what has changed.
  334. */
  335. virtual void doUpdateMusicalContextContent (ARAMusicalContext* musicalContext,
  336. ARAContentUpdateScopes scopeFlags)
  337. {
  338. ignoreUnused (musicalContext, scopeFlags);
  339. }
  340. /** Called after a region sequence is added to the musical context.
  341. @param musicalContext The musical context that \p regionSequence was added to.
  342. @param regionSequence The region sequence that was added to \p musicalContext.
  343. */
  344. virtual void didAddRegionSequenceToMusicalContext (ARAMusicalContext* musicalContext,
  345. ARARegionSequence* regionSequence)
  346. {
  347. ignoreUnused (musicalContext, regionSequence);
  348. }
  349. /** Called before a region sequence is removed from the musical context.
  350. @param musicalContext The musical context that \p regionSequence will be removed from.
  351. @param regionSequence The region sequence that will be removed from \p musicalContext.
  352. */
  353. virtual void willRemoveRegionSequenceFromMusicalContext (ARAMusicalContext* musicalContext,
  354. ARARegionSequence* regionSequence)
  355. {
  356. ignoreUnused (musicalContext, regionSequence);
  357. }
  358. /** Called after the region sequences are reordered in an ARA MusicalContext
  359. Region sequences are sorted by their order index -
  360. this callback signals a change in this ordering within the musical context.
  361. @param musicalContext The musical context with reordered region sequences.
  362. */
  363. virtual void didReorderRegionSequencesInMusicalContext (ARAMusicalContext* musicalContext)
  364. {
  365. ignoreUnused (musicalContext);
  366. }
  367. /** Called before the musical context is destroyed.
  368. @param musicalContext The musical context that will be destroyed.
  369. */
  370. virtual void willDestroyMusicalContext (ARAMusicalContext* musicalContext)
  371. {
  372. ignoreUnused (musicalContext);
  373. }
  374. ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_END
  375. };
  376. //==============================================================================
  377. /** Base class representing an ARA musical context.
  378. @tags{ARA}
  379. */
  380. class JUCE_API ARAMusicalContext : public ARA::PlugIn::MusicalContext,
  381. public ARAListenableModelClass<ARAMusicalContextListener>,
  382. public ARAObject
  383. {
  384. public:
  385. using PropertiesPtr = ARA::PlugIn::PropertiesPtr<ARA::ARAMusicalContextProperties>;
  386. using Listener = ARAMusicalContextListener;
  387. using ARA::PlugIn::MusicalContext::MusicalContext;
  388. /** Returns the result of ARA::PlugIn::MusicalContext::getDocument() with the pointer cast
  389. to ARADocument*.
  390. If you have overridden ARADocumentControllerSpecialisation::doCreateDocument(), then you
  391. can use the template parameter to cast the pointers to your subclass of ARADocument.
  392. */
  393. template <typename Document_t = ARADocument>
  394. Document_t* getDocument() const noexcept
  395. {
  396. return ARA::PlugIn::MusicalContext::getDocument<Document_t>();
  397. }
  398. /** Returns the result of ARA::PlugIn::MusicalContext::getRegionSequences() with the pointers
  399. within cast to ARARegionSequence*.
  400. If you have overridden ARADocumentControllerSpecialisation::doCreateRegionSequence(), then you
  401. can use the template parameter to cast the pointers to your subclass of ARARegionSequence.
  402. */
  403. template <typename RegionSequence_t = ARARegionSequence>
  404. const std::vector<RegionSequence_t*>& getRegionSequences() const noexcept
  405. {
  406. return ARA::PlugIn::MusicalContext::getRegionSequences<RegionSequence_t>();
  407. }
  408. size_t getNumChildren() const noexcept override { return 0; }
  409. ARAObject* getChild (size_t) override { return nullptr; }
  410. ARAObject* getParent() override { return getDocument(); }
  411. void visit (ARAObjectVisitor& visitor) override { visitor.visitMusicalContext (*this); }
  412. };
  413. /** A base class for listeners that want to know about changes to an ARAPlaybackRegion object.
  414. Use ARAPlaybackRegion::addListener() to register your listener with an ARAPlaybackRegion.
  415. @tags{ARA}
  416. */
  417. class JUCE_API ARAPlaybackRegionListener
  418. {
  419. public:
  420. /** Destructor. */
  421. virtual ~ARAPlaybackRegionListener() = default;
  422. ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_BEGIN
  423. /** Called before the playback region's properties are updated.
  424. @param playbackRegion The playback region whose properties will be updated.
  425. @param newProperties The playback region properties that will be assigned to \p playbackRegion.
  426. */
  427. virtual void willUpdatePlaybackRegionProperties (ARAPlaybackRegion* playbackRegion,
  428. ARA::PlugIn::PropertiesPtr<ARA::ARAPlaybackRegionProperties> newProperties)
  429. {
  430. ignoreUnused (playbackRegion, newProperties);
  431. }
  432. /** Called after the playback region's properties are updated.
  433. @param playbackRegion The playback region whose properties were updated.
  434. */
  435. virtual void didUpdatePlaybackRegionProperties (ARAPlaybackRegion* playbackRegion)
  436. {
  437. ignoreUnused (playbackRegion);
  438. }
  439. /** Called when the playback region's content (i.e. samples or notes) changes.
  440. @param playbackRegion The playback region with updated content.
  441. @param scopeFlags The scope of the content update.
  442. */
  443. virtual void didUpdatePlaybackRegionContent (ARAPlaybackRegion* playbackRegion,
  444. ARAContentUpdateScopes scopeFlags)
  445. {
  446. ignoreUnused (playbackRegion, scopeFlags);
  447. }
  448. /** Called before the playback region is destroyed.
  449. @param playbackRegion The playback region that will be destroyed.
  450. */
  451. virtual void willDestroyPlaybackRegion (ARAPlaybackRegion* playbackRegion)
  452. {
  453. ignoreUnused (playbackRegion);
  454. }
  455. ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_END
  456. };
  457. //==============================================================================
  458. /** Base class representing an ARA playback region.
  459. @tags{ARA}
  460. */
  461. class JUCE_API ARAPlaybackRegion : public ARA::PlugIn::PlaybackRegion,
  462. public ARAListenableModelClass<ARAPlaybackRegionListener>,
  463. public ARAObject
  464. {
  465. public:
  466. using PropertiesPtr = ARA::PlugIn::PropertiesPtr<ARA::ARAPlaybackRegionProperties>;
  467. using Listener = ARAPlaybackRegionListener;
  468. using ARA::PlugIn::PlaybackRegion::PlaybackRegion;
  469. /** Returns the result of ARA::PlugIn::PlaybackRegion::getAudioModification() with the pointer cast
  470. to ARAAudioModification*.
  471. If you have overridden ARADocumentControllerSpecialisation::doCreateAudioModification(), then you
  472. can use the template parameter to cast the pointers to your subclass of ARAAudioModification.
  473. */
  474. template <typename AudioModification_t = ARAAudioModification>
  475. AudioModification_t* getAudioModification() const noexcept
  476. {
  477. return ARA::PlugIn::PlaybackRegion::getAudioModification<AudioModification_t>();
  478. }
  479. /** Returns the result of ARA::PlugIn::PlaybackRegion::getRegionSequence() with the pointer cast
  480. to ARARegionSequence*.
  481. If you have overridden ARADocumentControllerSpecialisation::doCreateRegionSequence(), then you
  482. can use the template parameter to cast the pointers to your subclass of ARARegionSequence.
  483. */
  484. template <typename RegionSequence_t = ARARegionSequence>
  485. RegionSequence_t* getRegionSequence() const noexcept
  486. {
  487. return ARA::PlugIn::PlaybackRegion::getRegionSequence<RegionSequence_t>();
  488. }
  489. size_t getNumChildren() const noexcept override { return 0; }
  490. ARAObject* getChild (size_t) override { return nullptr; }
  491. ARAObject* getParent() override;
  492. void visit (ARAObjectVisitor& visitor) override { visitor.visitPlaybackRegion (*this); }
  493. /** Used in getTimeRange to indicate whether the head and tail times should be included in the result.
  494. */
  495. enum class IncludeHeadAndTail { no, yes };
  496. /** Returns the playback time range of this playback region.
  497. @param includeHeadAndTail Whether or not the range includes the head and tail
  498. time of all playback regions in the sequence.
  499. */
  500. Range<double> getTimeRange (IncludeHeadAndTail includeHeadAndTail = IncludeHeadAndTail::no) const;
  501. /** Returns the playback sample range of this playback region.
  502. @param sampleRate The rate at which the sample position should be calculated from
  503. the time range.
  504. @param includeHeadAndTail Whether or not the range includes the head and tail
  505. time of all playback regions in the sequence.
  506. */
  507. Range<int64> getSampleRange (double sampleRate, IncludeHeadAndTail includeHeadAndTail = IncludeHeadAndTail::no) const;
  508. /** Get the head length in seconds before the start of the region's playback time. */
  509. double getHeadTime() const;
  510. /** Get the tail length in seconds after the end of the region's playback time. */
  511. double getTailTime() const;
  512. /** Notify the ARA host and any listeners of a content update initiated by the plug-in.
  513. This must be called by the plug-in model management code on the message thread whenever updating
  514. the internal content representation, such as after the user edited the pitch of a note in the
  515. underlying audio modification.
  516. Listeners will be notified immediately. If \p notifyARAHost is true, a notification to the host
  517. will be enqueued and sent out the next time it polls for updates.
  518. @param scopeFlags The scope of the content update.
  519. @param notifyARAHost If true, the ARA host will be notified of the content change.
  520. */
  521. void notifyContentChanged (ARAContentUpdateScopes scopeFlags, bool notifyARAHost);
  522. };
  523. /** A base class for listeners that want to know about changes to an ARARegionSequence object.
  524. Use ARARegionSequence::addListener() to register your listener with an ARARegionSequence.
  525. @tags{ARA}
  526. */
  527. class JUCE_API ARARegionSequenceListener
  528. {
  529. public:
  530. /** Destructor. */
  531. virtual ~ARARegionSequenceListener() = default;
  532. ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_BEGIN
  533. /** Called before the region sequence's properties are updated.
  534. @param regionSequence The region sequence whose properties will be updated.
  535. @param newProperties The region sequence properties that will be assigned to \p regionSequence.
  536. */
  537. virtual void willUpdateRegionSequenceProperties (ARARegionSequence* regionSequence,
  538. ARA::PlugIn::PropertiesPtr<ARA::ARARegionSequenceProperties> newProperties)
  539. {
  540. ignoreUnused (regionSequence, newProperties);
  541. }
  542. /** Called after the region sequence's properties are updated.
  543. @param regionSequence The region sequence whose properties were updated.
  544. */
  545. virtual void didUpdateRegionSequenceProperties (ARARegionSequence* regionSequence)
  546. {
  547. ignoreUnused (regionSequence);
  548. }
  549. /** Called before a playback region is removed from the region sequence.
  550. @param regionSequence The region sequence that \p playbackRegion will be removed from.
  551. @param playbackRegion The playback region that will be removed from \p regionSequence.
  552. */
  553. virtual void willRemovePlaybackRegionFromRegionSequence (ARARegionSequence* regionSequence,
  554. ARAPlaybackRegion* playbackRegion)
  555. {
  556. ignoreUnused (regionSequence, playbackRegion);
  557. }
  558. /** Called after a playback region is added to the region sequence.
  559. @param regionSequence The region sequence that \p playbackRegion was added to.
  560. @param playbackRegion The playback region that was added to \p regionSequence.
  561. */
  562. virtual void didAddPlaybackRegionToRegionSequence (ARARegionSequence* regionSequence,
  563. ARAPlaybackRegion* playbackRegion)
  564. {
  565. ignoreUnused (regionSequence, playbackRegion);
  566. }
  567. /** Called before the region sequence is destroyed.
  568. @param regionSequence The region sequence that will be destroyed.
  569. */
  570. virtual void willDestroyRegionSequence (ARARegionSequence* regionSequence)
  571. {
  572. ignoreUnused (regionSequence);
  573. }
  574. ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_END
  575. };
  576. //==============================================================================
  577. /** Base class representing an ARA region sequence.
  578. @tags{ARA}
  579. */
  580. class JUCE_API ARARegionSequence : public ARA::PlugIn::RegionSequence,
  581. public ARAListenableModelClass<ARARegionSequenceListener>,
  582. public ARAObject
  583. {
  584. public:
  585. using PropertiesPtr = ARA::PlugIn::PropertiesPtr<ARA::ARARegionSequenceProperties>;
  586. using Listener = ARARegionSequenceListener;
  587. using ARA::PlugIn::RegionSequence::RegionSequence;
  588. /** Returns the result of ARA::PlugIn::RegionSequence::getDocument() with the pointer cast
  589. to ARADocument*.
  590. If you have overridden ARADocumentControllerSpecialisation::doCreateDocument(), then you
  591. can use the template parameter to cast the pointers to your subclass of ARADocument.
  592. */
  593. template <typename Document_t = ARADocument>
  594. Document_t* getDocument() const noexcept
  595. {
  596. return ARA::PlugIn::RegionSequence::getDocument<Document_t>();
  597. }
  598. /** Returns the result of ARA::PlugIn::RegionSequence::getMusicalContext() with the pointer cast
  599. to ARAMusicalContext*.
  600. If you have overridden ARADocumentControllerSpecialisation::doCreateMusicalContext(), then you
  601. can use the template parameter to cast the pointers to your subclass of ARAMusicalContext.
  602. */
  603. template <typename MusicalContext_t = ARAMusicalContext>
  604. MusicalContext_t* getMusicalContext() const noexcept
  605. {
  606. return ARA::PlugIn::RegionSequence::getMusicalContext<MusicalContext_t>();
  607. }
  608. /** Returns the result of ARA::PlugIn::RegionSequence::getPlaybackRegions() with the pointers within cast
  609. to ARAPlaybackRegion*.
  610. If you have overridden ARADocumentControllerSpecialisation::doCreatePlaybackRegion(), then you
  611. can use the template parameter to cast the pointers to your subclass of ARAPlaybackRegion.
  612. */
  613. template <typename PlaybackRegion_t = ARAPlaybackRegion>
  614. const std::vector<PlaybackRegion_t*>& getPlaybackRegions() const noexcept
  615. {
  616. return ARA::PlugIn::RegionSequence::getPlaybackRegions<PlaybackRegion_t>();
  617. }
  618. size_t getNumChildren() const noexcept override;
  619. ARAObject* getChild (size_t index) override;
  620. ARAObject* getParent () override { return getDocument(); }
  621. void visit (ARAObjectVisitor& visitor) override { visitor.visitRegionSequence (*this); }
  622. /** Returns the playback time range covered by the regions in this sequence.
  623. @param includeHeadAndTail Whether or not the range includes the playback region's head and tail time.
  624. */
  625. Range<double> getTimeRange (ARAPlaybackRegion::IncludeHeadAndTail includeHeadAndTail = ARAPlaybackRegion::IncludeHeadAndTail::no) const;
  626. /** If all audio sources used by the playback regions in this region sequence have the same
  627. sample rate, this rate is returned here, otherwise 0.0 is returned.
  628. If the region sequence has no playback regions, this also returns 0.0.
  629. */
  630. double getCommonSampleRate() const;
  631. };
  632. /** A base class for listeners that want to know about changes to an ARAAudioSource object.
  633. Use ARAAudioSource::addListener() to register your listener with an ARAAudioSource.
  634. @tags{ARA}
  635. */
  636. class JUCE_API ARAAudioSourceListener
  637. {
  638. public:
  639. /** Destructor. */
  640. virtual ~ARAAudioSourceListener() = default;
  641. ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_BEGIN
  642. /** Called before the audio source's properties are updated.
  643. @param audioSource The audio source whose properties will be updated.
  644. @param newProperties The audio source properties that will be assigned to \p audioSource.
  645. */
  646. virtual void willUpdateAudioSourceProperties (ARAAudioSource* audioSource,
  647. ARA::PlugIn::PropertiesPtr<ARA::ARAAudioSourceProperties> newProperties)
  648. {
  649. ignoreUnused (audioSource, newProperties);
  650. }
  651. /** Called after the audio source's properties are updated.
  652. @param audioSource The audio source whose properties were updated.
  653. */
  654. virtual void didUpdateAudioSourceProperties (ARAAudioSource* audioSource)
  655. {
  656. ignoreUnused (audioSource);
  657. }
  658. /** Called when the audio source's content (i.e. samples or notes) changes.
  659. @param audioSource The audio source with updated content.
  660. @param scopeFlags The scope of the content update.
  661. */
  662. virtual void doUpdateAudioSourceContent (ARAAudioSource* audioSource, ARAContentUpdateScopes scopeFlags)
  663. {
  664. ignoreUnused (audioSource, scopeFlags);
  665. }
  666. /** Called to notify progress when an audio source is being analyzed.
  667. @param audioSource The audio source being analyzed.
  668. @param state Indicates start, intermediate update or completion of the analysis.
  669. @param progress Progress normalized to the 0..1 range.
  670. */
  671. virtual void didUpdateAudioSourceAnalysisProgress (ARAAudioSource* audioSource,
  672. ARA::ARAAnalysisProgressState state,
  673. float progress)
  674. {
  675. ignoreUnused (audioSource, state, progress);
  676. }
  677. /** Called before access to an audio source's samples is enabled or disabled.
  678. @param audioSource The audio source whose sample access state will be changed.
  679. @param enable A bool indicating whether or not sample access will be enabled or disabled.
  680. */
  681. virtual void willEnableAudioSourceSamplesAccess (ARAAudioSource* audioSource, bool enable)
  682. {
  683. ignoreUnused (audioSource, enable);
  684. }
  685. /** Called after access to an audio source's samples is enabled or disabled.
  686. @param audioSource The audio source whose sample access state was changed.
  687. @param enable A bool indicating whether or not sample access was enabled or disabled.
  688. */
  689. virtual void didEnableAudioSourceSamplesAccess (ARAAudioSource* audioSource, bool enable)
  690. {
  691. ignoreUnused (audioSource, enable);
  692. }
  693. /** Called before an audio source is activated or deactivated when being removed / added from the host's undo history.
  694. @param audioSource The audio source that will be activated or deactivated
  695. @param deactivate A bool indicating whether \p audioSource was deactivated or activated.
  696. */
  697. virtual void willDeactivateAudioSourceForUndoHistory (ARAAudioSource* audioSource, bool deactivate)
  698. {
  699. ignoreUnused (audioSource, deactivate);
  700. }
  701. /** Called after an audio source is activated or deactivated when being removed / added from the host's undo history.
  702. @param audioSource The audio source that was activated or deactivated
  703. @param deactivate A bool indicating whether \p audioSource was deactivated or activated.
  704. */
  705. virtual void didDeactivateAudioSourceForUndoHistory (ARAAudioSource* audioSource, bool deactivate)
  706. {
  707. ignoreUnused (audioSource, deactivate);
  708. }
  709. /** Called after an audio modification is added to the audio source.
  710. @param audioSource The region sequence that \p audioModification was added to.
  711. @param audioModification The playback region that was added to \p audioSource.
  712. */
  713. virtual void didAddAudioModificationToAudioSource (ARAAudioSource* audioSource,
  714. ARAAudioModification* audioModification)
  715. {
  716. ignoreUnused (audioSource, audioModification);
  717. }
  718. /** Called before an audio modification is removed from the audio source.
  719. @param audioSource The audio source that \p audioModification will be removed from.
  720. @param audioModification The audio modification that will be removed from \p audioSource.
  721. */
  722. virtual void willRemoveAudioModificationFromAudioSource (ARAAudioSource* audioSource,
  723. ARAAudioModification* audioModification)
  724. {
  725. ignoreUnused (audioSource, audioModification);
  726. }
  727. /** Called before the audio source is destroyed.
  728. @param audioSource The audio source that will be destroyed.
  729. */
  730. virtual void willDestroyAudioSource (ARAAudioSource* audioSource)
  731. {
  732. ignoreUnused (audioSource);
  733. }
  734. ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_END
  735. };
  736. //==============================================================================
  737. /** Base class representing an ARA audio source.
  738. @tags{ARA}
  739. */
  740. class JUCE_API ARAAudioSource : public ARA::PlugIn::AudioSource,
  741. public ARAListenableModelClass<ARAAudioSourceListener>,
  742. public ARAObject
  743. {
  744. public:
  745. using PropertiesPtr = ARA::PlugIn::PropertiesPtr<ARA::ARAAudioSourceProperties>;
  746. using ARAAnalysisProgressState = ARA::ARAAnalysisProgressState;
  747. using Listener = ARAAudioSourceListener;
  748. using ARA::PlugIn::AudioSource::AudioSource;
  749. /** Returns the result of ARA::PlugIn::AudioSource::getDocument() with the pointer cast
  750. to ARADocument*.
  751. If you have overridden ARADocumentControllerSpecialisation::doCreateDocument(), then you
  752. can use the template parameter to cast the pointers to your subclass of ARADocument.
  753. */
  754. template <typename Document_t = ARADocument>
  755. Document_t* getDocument() const noexcept
  756. {
  757. return ARA::PlugIn::AudioSource::getDocument<Document_t>();
  758. }
  759. /** Returns the result of ARA::PlugIn::AudioSource::getAudioModifications() with the pointers
  760. within cast to ARAAudioModification*.
  761. If you have overridden ARADocumentControllerSpecialisation::doCreateAudioModification(),
  762. then you can use the template parameter to cast the pointers to your subclass of
  763. ARAAudioModification.
  764. */
  765. template <typename AudioModification_t = ARAAudioModification>
  766. const std::vector<AudioModification_t*>& getAudioModifications() const noexcept
  767. {
  768. return ARA::PlugIn::AudioSource::getAudioModifications<AudioModification_t>();
  769. }
  770. size_t getNumChildren() const noexcept override;
  771. ARAObject* getChild (size_t index) override;
  772. ARAObject* getParent() override { return getDocument(); }
  773. void visit (ARAObjectVisitor& visitor) override { visitor.visitAudioSource (*this); }
  774. /** Notify the ARA host and any listeners of analysis progress.
  775. Contrary to most ARA functions, this call can be made from any thread.
  776. The implementation will enqueue these notifications and later post them from the message thread.
  777. Calling code must ensure start and completion state are always balanced,
  778. and must send updates in ascending order.
  779. */
  780. void notifyAnalysisProgressStarted();
  781. /** \copydoc notifyAnalysisProgressStarted
  782. @param progress Progress normalized to the 0..1 range.
  783. */
  784. void notifyAnalysisProgressUpdated (float progress);
  785. /** \copydoc notifyAnalysisProgressStarted
  786. */
  787. void notifyAnalysisProgressCompleted();
  788. /** Notify the ARA host and any listeners of a content update initiated by the plug-in.
  789. This must be called by the plug-in model management code on the message thread whenever updating
  790. the internal content representation, such as after successfully analyzing a new tempo map.
  791. Listeners will be notified immediately. If \p notifyARAHost is true, a notification to the host
  792. will be enqueued and sent out the next time it polls for updates.
  793. \p notifyARAHost must be false if the update was triggered by the host via doUpdateAudioSourceContent().
  794. Furthermore, \p notifyARAHost must be false if the updated content is being restored from an archive.
  795. @param scopeFlags The scope of the content update.
  796. @param notifyARAHost If true, the ARA host will be notified of the content change.
  797. */
  798. void notifyContentChanged (ARAContentUpdateScopes scopeFlags, bool notifyARAHost);
  799. public:
  800. friend ARADocumentController;
  801. ARA::PlugIn::AnalysisProgressTracker internalAnalysisProgressTracker;
  802. };
  803. /** A base class for listeners that want to know about changes to an ARAAudioModification object.
  804. Use ARAAudioModification::addListener() to register your listener with an ARAAudioModification.
  805. @tags{ARA}
  806. */
  807. class JUCE_API ARAAudioModificationListener
  808. {
  809. public:
  810. /** Destructor. */
  811. virtual ~ARAAudioModificationListener() = default;
  812. ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_BEGIN
  813. /** Called before the audio modification's properties are updated.
  814. @param audioModification The audio modification whose properties will be updated.
  815. @param newProperties The audio modification properties that will be assigned to \p audioModification.
  816. */
  817. virtual void willUpdateAudioModificationProperties (ARAAudioModification* audioModification,
  818. ARA::PlugIn::PropertiesPtr<ARA::ARAAudioModificationProperties> newProperties)
  819. {
  820. ignoreUnused (audioModification, newProperties);
  821. }
  822. /** Called after the audio modification's properties are updated.
  823. @param audioModification The audio modification whose properties were updated.
  824. */
  825. virtual void didUpdateAudioModificationProperties (ARAAudioModification* audioModification)
  826. {
  827. ignoreUnused (audioModification);
  828. }
  829. /** Called when the audio modification's content (i.e. samples or notes) changes.
  830. @param audioModification The audio modification with updated content.
  831. @param scopeFlags The scope of the content update.
  832. */
  833. virtual void didUpdateAudioModificationContent (ARAAudioModification* audioModification, ARAContentUpdateScopes scopeFlags)
  834. {
  835. ignoreUnused (audioModification, scopeFlags);
  836. }
  837. /** Called before an audio modification is activated or deactivated when being removed / added from the host's undo history.
  838. @param audioModification The audio modification that was activated or deactivated
  839. @param deactivate A bool indicating whether \p audioModification was deactivated or activated.
  840. */
  841. virtual void willDeactivateAudioModificationForUndoHistory (ARAAudioModification* audioModification, bool deactivate)
  842. {
  843. ignoreUnused (audioModification, deactivate);
  844. }
  845. /** Called after an audio modification is activated or deactivated when being removed / added from the host's undo history.
  846. @param audioModification The audio modification that was activated or deactivated
  847. @param deactivate A bool indicating whether \p audioModification was deactivated or activated.
  848. */
  849. virtual void didDeactivateAudioModificationForUndoHistory (ARAAudioModification* audioModification, bool deactivate)
  850. {
  851. ignoreUnused (audioModification, deactivate);
  852. }
  853. /** Called after a playback region is added to the audio modification.
  854. @param audioModification The audio modification that \p playbackRegion was added to.
  855. @param playbackRegion The playback region that was added to \p audioModification.
  856. */
  857. virtual void didAddPlaybackRegionToAudioModification (ARAAudioModification* audioModification,
  858. ARAPlaybackRegion* playbackRegion)
  859. {
  860. ignoreUnused (audioModification, playbackRegion);
  861. }
  862. /** Called before a playback region is removed from the audio modification.
  863. @param audioModification The audio modification that \p playbackRegion will be removed from.
  864. @param playbackRegion The playback region that will be removed from \p audioModification.
  865. */
  866. virtual void willRemovePlaybackRegionFromAudioModification (ARAAudioModification* audioModification,
  867. ARAPlaybackRegion* playbackRegion)
  868. {
  869. ignoreUnused (audioModification, playbackRegion);
  870. }
  871. /** Called before the audio modification is destroyed.
  872. @param audioModification The audio modification that will be destroyed.
  873. */
  874. virtual void willDestroyAudioModification (ARAAudioModification* audioModification)
  875. {
  876. ignoreUnused (audioModification);
  877. }
  878. ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_END
  879. };
  880. //==============================================================================
  881. /** Base class representing an ARA audio modification.
  882. @tags{ARA}
  883. */
  884. class JUCE_API ARAAudioModification : public ARA::PlugIn::AudioModification,
  885. public ARAListenableModelClass<ARAAudioModificationListener>,
  886. public ARAObject
  887. {
  888. public:
  889. using PropertiesPtr = ARA::PlugIn::PropertiesPtr<ARA::ARAAudioModificationProperties>;
  890. using Listener = ARAAudioModificationListener;
  891. using ARA::PlugIn::AudioModification::AudioModification;
  892. /** Returns the result of ARA::PlugIn::AudioModification::getAudioSource() with the pointer cast
  893. to ARAAudioSource*.
  894. If you have overridden ARADocumentControllerSpecialisation::doCreateAudioSource(), then you
  895. can use the template parameter to cast the pointers to your subclass of ARAAudioSource.
  896. */
  897. template <typename AudioSource_t = ARAAudioSource>
  898. AudioSource_t* getAudioSource() const noexcept
  899. {
  900. return ARA::PlugIn::AudioModification::getAudioSource<AudioSource_t>();
  901. }
  902. /** Returns the result of ARA::PlugIn::AudioModification::getPlaybackRegions() with the
  903. pointers within cast to ARAPlaybackRegion*.
  904. If you have overridden ARADocumentControllerSpecialisation::doCreatePlaybackRegion(), then
  905. you can use the template parameter to cast the pointers to your subclass of ARAPlaybackRegion.
  906. */
  907. template <typename PlaybackRegion_t = ARAPlaybackRegion>
  908. const std::vector<PlaybackRegion_t*>& getPlaybackRegions() const noexcept
  909. {
  910. return ARA::PlugIn::AudioModification::getPlaybackRegions<PlaybackRegion_t>();
  911. }
  912. size_t getNumChildren() const noexcept override;
  913. ARAObject* getChild (size_t index) override;
  914. ARAObject* getParent() override { return getAudioSource(); }
  915. void visit (ARAObjectVisitor& visitor) override { visitor.visitAudioModification (*this); }
  916. /** Notify the ARA host and any listeners of a content update initiated by the plug-in.
  917. This must be called by the plug-in model management code on the message thread whenever updating
  918. the internal content representation, such as after the user editing the pitch of a note.
  919. Listeners will be notified immediately. If \p notifyARAHost is true, a notification to the host
  920. will be enqueued and sent out the next time it polls for updates.
  921. \p notifyARAHost must be false if the updated content is being restored from an archive.
  922. @param scopeFlags The scope of the content update.
  923. @param notifyARAHost If true, the ARA host will be notified of the content change.
  924. */
  925. void notifyContentChanged (ARAContentUpdateScopes scopeFlags, bool notifyARAHost);
  926. };
  927. } // namespace juce