AutomatableModel.h 10 KB

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