Lv2Ports.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*
  2. * Lv2Ports.h - Lv2 port classes definitions
  3. *
  4. * Copyright (c) 2019-2020 Johannes Lorenz <jlsf2013$users.sourceforge.net, $=@>
  5. *
  6. * This file is part of LMMS - https://lmms.io
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2 of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public
  19. * License along with this program (see COPYING); if not, write to the
  20. * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  21. * Boston, MA 02110-1301 USA.
  22. *
  23. */
  24. #ifndef LV2PORTS_H
  25. #define LV2PORTS_H
  26. #include "lmmsconfig.h"
  27. #ifdef LMMS_HAVE_LV2
  28. #include <lilv/lilv.h>
  29. #include <memory>
  30. #include <vector>
  31. #include "lmms_basics.h"
  32. #include "PluginIssue.h"
  33. struct ConnectPortVisitor;
  34. typedef struct LV2_Evbuf_Impl LV2_Evbuf;
  35. namespace Lv2Ports {
  36. /*
  37. port structs
  38. */
  39. enum class Flow {
  40. Unknown,
  41. Input,
  42. Output
  43. };
  44. enum class Type {
  45. Unknown,
  46. Control,
  47. Audio,
  48. AtomSeq,
  49. Cv //!< TODO: unused, describe
  50. };
  51. //! Port visualization
  52. //! @note All Lv2 audio ports are float, this is only the visualisation
  53. enum class Vis {
  54. Generic, //!< nothing specific, a generic knob or slider shall be used
  55. Integer, //!< counter
  56. Enumeration, //!< selection from enumerated values
  57. Toggled //!< boolean widget
  58. };
  59. const char* toStr(Lv2Ports::Flow pf);
  60. const char* toStr(Lv2Ports::Type pt);
  61. const char* toStr(Lv2Ports::Vis pv);
  62. struct ControlPortBase;
  63. struct Control;
  64. struct Audio;
  65. struct Cv;
  66. struct AtomSeq;
  67. struct Unknown;
  68. struct ConstVisitor
  69. {
  70. virtual void visit(const Lv2Ports::ControlPortBase& ) {}
  71. virtual void visit(const Lv2Ports::Control& ) {}
  72. virtual void visit(const Lv2Ports::Audio& ) {}
  73. virtual void visit(const Lv2Ports::Cv& ) {}
  74. virtual void visit(const Lv2Ports::AtomSeq& ) {}
  75. virtual void visit(const Lv2Ports::Unknown& ) {}
  76. virtual ~ConstVisitor();
  77. };
  78. struct Visitor
  79. {
  80. virtual void visit(Lv2Ports::ControlPortBase& ) {}
  81. virtual void visit(Lv2Ports::Control& ) {}
  82. virtual void visit(Lv2Ports::Audio& ) {}
  83. virtual void visit(Lv2Ports::Cv& ) {}
  84. virtual void visit(Lv2Ports::AtomSeq& ) {}
  85. virtual void visit(Lv2Ports::Unknown& ) {}
  86. virtual ~Visitor();
  87. };
  88. struct Meta
  89. {
  90. Type m_type = Type::Unknown;
  91. Flow m_flow = Flow::Unknown;
  92. Vis m_vis = Vis::Generic;
  93. bool m_logarithmic = false;
  94. bool m_optional = false;
  95. bool m_used = true;
  96. std::vector<PluginIssue> get(const LilvPlugin* plugin, std::size_t portNum);
  97. float def() const { return m_def; }
  98. float min(sample_rate_t sr) const { return m_sampleRate ? sr * m_min : m_min; }
  99. float max(sample_rate_t sr) const { return m_sampleRate ? sr * m_max : m_max; }
  100. private:
  101. float m_def = .0f, m_min = .0f, m_max = .0f;
  102. bool m_sampleRate = false;
  103. };
  104. struct PortBase : public Meta
  105. {
  106. const LilvPort* m_port = nullptr;
  107. const LilvPlugin* m_plugin = nullptr;
  108. virtual void accept(Visitor& v) = 0;
  109. virtual void accept(ConstVisitor& v) const = 0;
  110. QString name() const;
  111. QString uri() const;
  112. virtual ~PortBase();
  113. };
  114. template<typename Derived, typename Base>
  115. struct VisitablePort : public Base
  116. {
  117. void accept(Visitor& v) override { v.visit(static_cast<Derived&>(*this)); }
  118. void accept(ConstVisitor& v) const override { v.visit(static_cast<const Derived&>(*this)); }
  119. };
  120. struct ControlPortBase : public VisitablePort<ControlPortBase, PortBase>
  121. {
  122. //! LMMS models
  123. //! Always up-to-date, except during runs
  124. std::unique_ptr<class AutomatableModel> m_connectedModel;
  125. //! Enumerate float values
  126. //! lv2 defines scale points as
  127. //! "single float Points (for control inputs)"
  128. std::vector<float> m_scalePointMap;
  129. };
  130. struct Control : public VisitablePort<Control, ControlPortBase>
  131. {
  132. //! Data location which Lv2 plugins see
  133. //! Model values are being copied here every run
  134. //! Between runs, this data is not up-to-date
  135. float m_val;
  136. };
  137. struct Cv : public VisitablePort<Cv, ControlPortBase>
  138. {
  139. //! Data location which Lv2 plugins see
  140. //! Model values are being copied here every run
  141. //! Between runs, this data is not up-to-date
  142. std::vector<float> m_buffer;
  143. };
  144. struct Audio : public VisitablePort<Audio, PortBase>
  145. {
  146. Audio(std::size_t bufferSize, bool isSidechain);
  147. //! Copy buffer passed by LMMS into our ports
  148. //! @param channel channel index into each sample frame
  149. void copyBuffersFromCore(const sampleFrame *lmmsBuf,
  150. unsigned channel, fpp_t frames);
  151. //! Add buffer passed by LMMS into our ports, and halve the result
  152. //! @param channel channel index into each sample frame
  153. void averageWithBuffersFromCore(const sampleFrame *lmmsBuf,
  154. unsigned channel, fpp_t frames);
  155. //! Copy our ports into buffers passed by LMMS
  156. //! @param channel channel index into each sample frame
  157. void copyBuffersToCore(sampleFrame *lmmsBuf,
  158. unsigned channel, fpp_t frames) const;
  159. bool isSideChain() const { return m_sidechain; }
  160. bool isOptional() const { return m_optional; }
  161. bool mustBeUsed() const { return !isSideChain() && !isOptional(); }
  162. std::size_t bufferSize() const { return m_buffer.size(); }
  163. private:
  164. //! the buffer where Lv2 reads/writes the data from/to
  165. std::vector<float> m_buffer;
  166. bool m_sidechain;
  167. // the only case when data of m_buffer may be referenced:
  168. friend struct ::ConnectPortVisitor;
  169. };
  170. struct AtomSeq : public VisitablePort<AtomSeq, PortBase>
  171. {
  172. enum FlagType
  173. {
  174. None = 0,
  175. Midi = 1
  176. };
  177. unsigned flags = FlagType::None;
  178. struct Lv2EvbufDeleter
  179. {
  180. void operator()(LV2_Evbuf* n);
  181. };
  182. using AutoLv2Evbuf = std::unique_ptr<LV2_Evbuf, Lv2EvbufDeleter>;
  183. AutoLv2Evbuf m_buf;
  184. };
  185. struct Unknown : public VisitablePort<Unknown, PortBase>
  186. {
  187. };
  188. /*
  189. port casts
  190. */
  191. template<class Target>
  192. struct DCastVisitor : public Visitor
  193. {
  194. Target* m_result = nullptr;
  195. void visit(Target& tar) { m_result = &tar; }
  196. };
  197. template<class Target>
  198. struct ConstDCastVisitor : public ConstVisitor
  199. {
  200. const Target* m_result = nullptr;
  201. void visit(const Target& tar) { m_result = &tar; }
  202. };
  203. //! If you don't want to use a whole visitor, you can use dcast
  204. template<class Target>
  205. Target* dcast(PortBase* base)
  206. {
  207. DCastVisitor<Target> vis;
  208. base->accept(vis);
  209. return vis.m_result;
  210. }
  211. //! const overload
  212. template<class Target>
  213. const Target* dcast(const PortBase* base)
  214. {
  215. ConstDCastVisitor<Target> vis;
  216. base->accept(vis);
  217. return vis.m_result;
  218. }
  219. } // namespace Lv2Ports
  220. #endif // LMMS_HAVE_LV2
  221. #endif // LV2PORTS_H