AutomatableModel.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. /*
  2. * AutomatableModel.h - declaration of class AutomatableModel
  3. *
  4. * Copyright (c) 2007-2014 Tobias Doerffel <tobydox/at/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 AUTOMATABLE_MODEL_H
  25. #define AUTOMATABLE_MODEL_H
  26. #include <QtCore/QMap>
  27. #include <QtCore/QMutex>
  28. #include "JournallingObject.h"
  29. #include "Model.h"
  30. #include "MidiTime.h"
  31. #include "ValueBuffer.h"
  32. #include "MemoryManager.h"
  33. // simple way to map a property of a view to a model
  34. #define mapPropertyFromModelPtr(type,getfunc,setfunc,modelname) \
  35. public: \
  36. type getfunc() const \
  37. { \
  38. return (type) modelname->value(); \
  39. } \
  40. public slots: \
  41. void setfunc( const type val ) \
  42. { \
  43. modelname->setValue( val ); \
  44. }
  45. #define mapPropertyFromModel(type,getfunc,setfunc,modelname) \
  46. public: \
  47. type getfunc() const \
  48. { \
  49. return (type) modelname.value(); \
  50. } \
  51. public slots: \
  52. void setfunc( const type val ) \
  53. { \
  54. modelname.setValue( (float) val ); \
  55. }
  56. class ControllerConnection;
  57. class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject
  58. {
  59. Q_OBJECT
  60. MM_OPERATORS
  61. public:
  62. typedef QVector<AutomatableModel *> AutoModelVector;
  63. enum ScaleType
  64. {
  65. Linear,
  66. Logarithmic,
  67. Decibel
  68. };
  69. virtual ~AutomatableModel();
  70. bool isAutomated() const;
  71. bool isAutomatedOrControlled() const
  72. {
  73. return isAutomated() || m_controllerConnection != NULL;
  74. }
  75. ControllerConnection* controllerConnection() const
  76. {
  77. return m_controllerConnection;
  78. }
  79. void setControllerConnection( ControllerConnection* c );
  80. template<class T>
  81. static T castValue( const float v )
  82. {
  83. return (T)( v );
  84. }
  85. template<bool>
  86. static bool castValue( const float v )
  87. {
  88. return ( qRound( v ) != 0 );
  89. }
  90. template<class T>
  91. inline T value( int frameOffset = 0 ) const
  92. {
  93. if( unlikely( hasLinkedModels() || m_controllerConnection != NULL ) )
  94. {
  95. return castValue<T>( controllerValue( frameOffset ) );
  96. }
  97. return castValue<T>( m_value );
  98. }
  99. float controllerValue( int frameOffset ) const;
  100. //! @brief Function that returns sample-exact data as a ValueBuffer
  101. //! @return pointer to model's valueBuffer when s.ex.data exists, NULL otherwise
  102. ValueBuffer * valueBuffer();
  103. template<class T>
  104. T initValue() const
  105. {
  106. return castValue<T>( m_initValue );
  107. }
  108. bool isAtInitValue() const
  109. {
  110. return m_value == m_initValue;
  111. }
  112. template<class T>
  113. T minValue() const
  114. {
  115. return castValue<T>( m_minValue );
  116. }
  117. template<class T>
  118. T maxValue() const
  119. {
  120. return castValue<T>( m_maxValue );
  121. }
  122. template<class T>
  123. T step() const
  124. {
  125. return castValue<T>( m_step );
  126. }
  127. //! @brief Returns value scaled with the scale type and min/max values of this model
  128. float scaledValue( float value ) const;
  129. //! @brief Returns value applied with the inverse of this model's scale type
  130. float inverseScaledValue( float value ) const;
  131. void setInitValue( const float value );
  132. void setAutomatedValue( const float value );
  133. void setValue( const float value );
  134. void incValue( int steps )
  135. {
  136. setValue( m_value + steps * m_step );
  137. }
  138. float range() const
  139. {
  140. return m_range;
  141. }
  142. void setRange( const float min, const float max, const float step = 1 );
  143. void setScaleType( ScaleType sc ) {
  144. m_scaleType = sc;
  145. }
  146. void setScaleLogarithmic( bool setToTrue = true )
  147. {
  148. setScaleType( setToTrue ? Logarithmic : Linear );
  149. }
  150. bool isScaleLogarithmic() const
  151. {
  152. return m_scaleType == Logarithmic;
  153. }
  154. void setStep( const float step );
  155. float centerValue() const
  156. {
  157. return m_centerValue;
  158. }
  159. void setCenterValue( const float centerVal )
  160. {
  161. m_centerValue = centerVal;
  162. }
  163. static void linkModels( AutomatableModel* m1, AutomatableModel* m2 );
  164. static void unlinkModels( AutomatableModel* m1, AutomatableModel* m2 );
  165. void unlinkAllModels();
  166. /**
  167. * @brief Saves settings (value, automation links and controller connections) of AutomatableModel into
  168. * specified DOM element using <name> as attribute/node name
  169. * @param doc TODO
  170. * @param element Where this option shall be saved.
  171. * Depending on the model, this can be done in an attribute or in a subnode.
  172. * @param name Name to store this model as.
  173. */
  174. virtual void saveSettings( QDomDocument& doc, QDomElement& element, const QString& name );
  175. /*! \brief Loads settings (value, automation links and controller connections) of AutomatableModel from
  176. specified DOM element using <name> as attribute/node name */
  177. virtual void loadSettings( const QDomElement& element, const QString& name );
  178. virtual QString nodeName() const
  179. {
  180. return "automatablemodel";
  181. }
  182. virtual QString displayValue( const float val ) const = 0;
  183. bool hasLinkedModels() const
  184. {
  185. return !m_linkedModels.empty();
  186. }
  187. // a way to track changed values in the model and avoid using signals/slots - useful for speed-critical code.
  188. // note that this method should only be called once per period since it resets the state of the variable - so if your model
  189. // has to be accessed by more than one object, then this function shouldn't be used.
  190. bool isValueChanged()
  191. {
  192. if( m_valueChanged || valueBuffer() )
  193. {
  194. m_valueChanged = false;
  195. return true;
  196. }
  197. return false;
  198. }
  199. float globalAutomationValueAt( const MidiTime& time );
  200. void setStrictStepSize( const bool b )
  201. {
  202. m_hasStrictStepSize = b;
  203. }
  204. static void incrementPeriodCounter()
  205. {
  206. ++s_periodCounter;
  207. }
  208. static void resetPeriodCounter()
  209. {
  210. s_periodCounter = 0;
  211. }
  212. public slots:
  213. virtual void reset();
  214. void unlinkControllerConnection();
  215. protected:
  216. AutomatableModel(
  217. const float val = 0,
  218. const float min = 0,
  219. const float max = 0,
  220. const float step = 0,
  221. Model* parent = NULL,
  222. const QString& displayName = QString(),
  223. bool defaultConstructed = false );
  224. //! returns a value which is in range between min() and
  225. //! max() and aligned according to the step size (step size 0.05 -> value
  226. //! 0.12345 becomes 0.10 etc.). You should always call it at the end after
  227. //! doing your own calculations.
  228. float fittedValue( float value ) const;
  229. private:
  230. virtual void saveSettings( QDomDocument& doc, QDomElement& element )
  231. {
  232. saveSettings( doc, element, "value" );
  233. }
  234. virtual void loadSettings( const QDomElement& element )
  235. {
  236. loadSettings( element, "value" );
  237. }
  238. void linkModel( AutomatableModel* model );
  239. void unlinkModel( AutomatableModel* model );
  240. //! @brief Scales @value from linear to logarithmic.
  241. //! Value should be within [0,1]
  242. template<class T> T logToLinearScale( T value ) const;
  243. //! rounds @a value to @a where if it is close to it
  244. //! @param value will be modified to rounded value
  245. template<class T> void roundAt( T &value, const T &where ) const;
  246. ScaleType m_scaleType; //! scale type, linear by default
  247. float m_value;
  248. float m_initValue;
  249. float m_minValue;
  250. float m_maxValue;
  251. float m_step;
  252. float m_range;
  253. float m_centerValue;
  254. bool m_valueChanged;
  255. // currently unused?
  256. float m_oldValue;
  257. int m_setValueDepth;
  258. // used to determine if step size should be applied strictly (ie. always)
  259. // or only when value set from gui (default)
  260. bool m_hasStrictStepSize;
  261. AutoModelVector m_linkedModels;
  262. //! NULL if not appended to controller, otherwise connection info
  263. ControllerConnection* m_controllerConnection;
  264. ValueBuffer m_valueBuffer;
  265. long m_lastUpdatedPeriod;
  266. static long s_periodCounter;
  267. bool m_hasSampleExactData;
  268. // prevent several threads from attempting to write the same vb at the same time
  269. QMutex m_valueBufferMutex;
  270. signals:
  271. void initValueChanged( float val );
  272. void destroyed( jo_id_t id );
  273. } ;
  274. template <typename T> class LMMS_EXPORT TypedAutomatableModel : public AutomatableModel
  275. {
  276. public:
  277. using AutomatableModel::AutomatableModel;
  278. T value( int frameOffset = 0 ) const
  279. {
  280. return AutomatableModel::value<T>( frameOffset );
  281. }
  282. T initValue() const
  283. {
  284. return AutomatableModel::initValue<T>();
  285. }
  286. T minValue() const
  287. {
  288. return AutomatableModel::minValue<T>();
  289. }
  290. T maxValue() const
  291. {
  292. return AutomatableModel::maxValue<T>();
  293. }
  294. };
  295. // some typed AutomatableModel-definitions
  296. class LMMS_EXPORT FloatModel : public TypedAutomatableModel<float>
  297. {
  298. Q_OBJECT
  299. public:
  300. FloatModel( float val = 0, float min = 0, float max = 0, float step = 0,
  301. Model * parent = NULL,
  302. const QString& displayName = QString(),
  303. bool defaultConstructed = false ) :
  304. TypedAutomatableModel( val, min, max, step, parent, displayName, defaultConstructed )
  305. {
  306. }
  307. float getRoundedValue() const;
  308. int getDigitCount() const;
  309. QString displayValue( const float val ) const override;
  310. } ;
  311. class LMMS_EXPORT IntModel : public TypedAutomatableModel<int>
  312. {
  313. Q_OBJECT
  314. public:
  315. IntModel( int val = 0, int min = 0, int max = 0,
  316. Model* parent = NULL,
  317. const QString& displayName = QString(),
  318. bool defaultConstructed = false ) :
  319. TypedAutomatableModel( val, min, max, 1, parent, displayName, defaultConstructed )
  320. {
  321. }
  322. QString displayValue( const float val ) const override;
  323. } ;
  324. class LMMS_EXPORT BoolModel : public TypedAutomatableModel<bool>
  325. {
  326. Q_OBJECT
  327. public:
  328. BoolModel( const bool val = false,
  329. Model* parent = NULL,
  330. const QString& displayName = QString(),
  331. bool defaultConstructed = false ) :
  332. TypedAutomatableModel( val, false, true, 1, parent, displayName, defaultConstructed )
  333. {
  334. }
  335. QString displayValue( const float val ) const override;
  336. } ;
  337. typedef QMap<AutomatableModel*, float> AutomatedValueMap;
  338. #endif