lmms
Cross-platform music production software
Loading...
Searching...
No Matches
AutomatableModel.h
Go to the documentation of this file.
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
25#ifndef LMMS_AUTOMATABLE_MODEL_H
26#define LMMS_AUTOMATABLE_MODEL_H
27
28#include <cmath>
29#include <QMap>
30#include <QMutex>
31
32#include "JournallingObject.h"
33#include "Model.h"
34#include "TimePos.h"
35#include "ValueBuffer.h"
36#include "ModelVisitor.h"
37
38
39namespace lmms
40{
41
42// simple way to map a property of a view to a model
43#define mapPropertyFromModelPtr(type,getfunc,setfunc,modelname) \
44 public: \
45 type getfunc() const \
46 { \
47 return (type) modelname->value(); \
48 } \
49 public slots: \
50 void setfunc( const type val ) \
51 { \
52 modelname->setValue( val ); \
53 }
54
55#define mapPropertyFromModel(type,getfunc,setfunc,modelname) \
56 public: \
57 type getfunc() const \
58 { \
59 return (type) modelname.value(); \
60 } \
61 public slots: \
62 void setfunc( const type val ) \
63 { \
64 modelname.setValue( (float) val ); \
65 }
66
67// use this to make subclasses visitable
68#define MODEL_IS_VISITABLE \
69 void accept(ModelVisitor& v) override { v.visit(*this); } \
70 void accept(ConstModelVisitor& v) const override { v.visit(*this); }
71
72
73
74class ControllerConnection;
75
76class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject
77{
78 Q_OBJECT
79public:
80 enum class ScaleType
81 {
82 Linear,
83 Logarithmic,
84 Decibel
85 };
86
87
88 ~AutomatableModel() override;
89
90 // Implement those by using the MODEL_IS_VISITABLE macro
91 virtual void accept(ModelVisitor& v) = 0;
92 virtual void accept(ConstModelVisitor& v) const = 0;
93
94public:
103 template<class Target>
104 Target* dynamicCast(bool doThrow = false)
105 {
107 if (doThrow && !vis.result) { Q_ASSERT(false); }
108 return vis.result;
109 }
110
112 template<class Target>
113 const Target* dynamicCast(bool doThrow = false) const
114 {
116 if (doThrow && !vis.result) { Q_ASSERT(false); }
117 return vis.result;
118 }
119
120 bool isAutomated() const;
122 {
123 return isAutomated() || m_controllerConnection != nullptr;
124 }
125
130
131
132 void setControllerConnection( ControllerConnection* c );
133
134
135 template<class T>
136 static T castValue( const float v )
137 {
138 return (T)( v );
139 }
140
141 template<bool>
142 static bool castValue( const float v )
143 {
144 return (std::round(v) != 0);
145 }
146
147
148 template<class T>
149 inline T value( int frameOffset = 0 ) const
150 {
151 // TODO
152 // The `m_value` should only be updated whenever the Controller value changes,
153 // instead of the Model calling `controller->currentValue()` every time.
154 // This becomes even worse in the case of linked Models, where it has to
155 // loop through the list of all links.
156
158 {
160 {
161 return castValue<T>(controllerValue(frameOffset));
162 }
163 for (auto next = m_nextLink; next != this; next = next->m_nextLink)
164 {
165 if (next->controllerConnection() && next->useControllerValue())
166 {
167 return castValue<T>(fittedValue(next->controllerValue(frameOffset)));
168 }
169 }
170 }
171 return castValue<T>( m_value );
172 }
173
174 float controllerValue( int frameOffset ) const;
175
178 ValueBuffer * valueBuffer();
179
180 template<class T>
181 T initValue() const
182 {
183 return castValue<T>( m_initValue );
184 }
185
186 bool isAtInitValue() const
187 {
188 return m_value == m_initValue;
189 }
190
191 template<class T>
192 T minValue() const
193 {
194 return castValue<T>( m_minValue );
195 }
196
197 template<class T>
198 T maxValue() const
199 {
200 return castValue<T>( m_maxValue );
201 }
202
203 template<class T>
204 T step() const
205 {
206 return castValue<T>( m_step );
207 }
208
210 float scaledValue( float value ) const;
212 float inverseScaledValue( float value ) const;
213
214 void setInitValue( const float value );
215
216 void setValue(const float value, const bool isAutomated = false);
217
218 void incValue( int steps )
219 {
220 setValue( m_value + steps * m_step );
221 }
222
223 float range() const
224 {
225 return m_range;
226 }
227
228 void setRange( const float min, const float max, const float step = 1 );
230 m_scaleType = sc;
231 }
232 void setScaleLogarithmic( bool setToTrue = true )
233 {
235 }
237 {
239 }
240
241 void setStep( const float step );
242
243 float centerValue() const
244 {
245 return m_centerValue;
246 }
247
248 void setCenterValue( const float centerVal )
249 {
250 m_centerValue = centerVal;
251 }
252
254 void linkToModel(AutomatableModel* model);
256 size_t countLinks() const;
257
267 virtual void saveSettings(QDomDocument& doc, QDomElement& element, const QString& name);
268
273 virtual void loadSettings(const QDomElement& element, const QString& name);
274
275 QString nodeName() const override
276 {
277 return "automatablemodel";
278 }
279
280 virtual QString displayValue( const float val ) const = 0;
281
282 bool isLinked() const
283 {
284 return m_nextLink != this;
285 }
286
287 // a way to track changed values in the model and avoid using signals/slots - useful for speed-critical code.
288 // note that this method should only be called once per period since it resets the state of the variable - so if your model
289 // has to be accessed by more than one object, then this function shouldn't be used.
291 {
292 if( m_valueChanged || valueBuffer() )
293 {
294 m_valueChanged = false;
295 return true;
296 }
297 return false;
298 }
299
300 float globalAutomationValueAt( const TimePos& time );
301
302 void setStrictStepSize( const bool b )
303 {
305 }
306
308 {
310 }
311
312 static void resetPeriodCounter()
313 {
314 s_periodCounter = 0;
315 }
316
318 {
320 }
321
322public slots:
323 virtual void reset();
324 void unlink();
325 void unlinkControllerConnection();
326 void setUseControllerValue(bool b = true);
327
328
329protected:
331 const float val = 0,
332 const float min = 0,
333 const float max = 0,
334 const float step = 0,
335 Model* parent = nullptr,
336 const QString& displayName = QString(),
337 bool defaultConstructed = false );
342 float fittedValue( float value ) const;
343
344
345private:
346 // dynamicCast implementation
347 template<class Target>
349 {
350 Target* result = nullptr;
351 void visit(Target& tar) { result = &tar; }
352 };
353
354 // dynamicCast implementation
355 template<class Target>
357 {
358 const Target* result = nullptr;
359 void visit(const Target& tar) { result = &tar; }
360 };
361
362 static bool mustQuoteName(const QString &name);
363
364 void saveSettings( QDomDocument& doc, QDomElement& element ) override
365 {
366 saveSettings( doc, element, "value" );
367 }
368
369 void loadSettings( const QDomElement& element ) override
370 {
371 loadSettings( element, "value" );
372 }
373
374 void setValueInternal(const float value);
375
379 AutomatableModel* getLastLinkedModel() const;
380
382 bool isLinkedToModel(AutomatableModel* model) const;
383
386 template<class T> T logToLinearScale(T value) const;
387
391 template<class T> void roundAt(T& value, const T& where) const;
392
393
395 float m_value;
399 float m_step;
400 float m_range;
402
405
406 // used to determine if step size should be applied strictly (ie. always)
407 // or only when value set from gui (default)
409
413
414
417
418
421 static long s_periodCounter;
422
424
425 // prevent several threads from attempting to write the same vb at the same time
427
429
430signals:
431 void initValueChanged( float val );
433
434} ;
435
436
437
438
439template <typename T> class LMMS_EXPORT TypedAutomatableModel : public AutomatableModel
440{
441public:
443 T value( int frameOffset = 0 ) const
444 {
445 return AutomatableModel::value<T>( frameOffset );
446 }
447
448 T initValue() const
449 {
451 }
452
453 T minValue() const
454 {
456 }
457
458 T maxValue() const
459 {
461 }
462};
463
464
465// some typed AutomatableModel-definitions
466
467class LMMS_EXPORT FloatModel : public TypedAutomatableModel<float>
468{
469 Q_OBJECT
471public:
472 FloatModel( float val = 0, float min = 0, float max = 0, float step = 0,
473 Model * parent = nullptr,
474 const QString& displayName = QString(),
475 bool defaultConstructed = false ) :
476 TypedAutomatableModel( val, min, max, step, parent, displayName, defaultConstructed )
477 {
478 }
479 float getRoundedValue() const;
480 int getDigitCount() const;
481 QString displayValue( const float val ) const override;
482} ;
483
484
485class LMMS_EXPORT IntModel : public TypedAutomatableModel<int>
486{
487 Q_OBJECT
489public:
490 IntModel( int val = 0, int min = 0, int max = 0,
491 Model* parent = nullptr,
492 const QString& displayName = QString(),
493 bool defaultConstructed = false ) :
494 TypedAutomatableModel( val, min, max, 1, parent, displayName, defaultConstructed )
495 {
496 }
497 QString displayValue( const float val ) const override;
498} ;
499
500
501class LMMS_EXPORT BoolModel : public TypedAutomatableModel<bool>
502{
503 Q_OBJECT
505public:
506 BoolModel( const bool val = false,
507 Model* parent = nullptr,
508 const QString& displayName = QString(),
509 bool defaultConstructed = false ) :
510 TypedAutomatableModel( val, false, true, 1, parent, displayName, defaultConstructed )
511 {
512 }
513 QString displayValue( const float val ) const override;
514} ;
515
516using AutomatedValueMap = QMap<AutomatableModel*, float>;
517
518} // namespace lmms
519
520#endif // LMMS_AUTOMATABLE_MODEL_H
#define MODEL_IS_VISITABLE
Definition AutomatableModel.h:68
Definition AutomatableModel.h:77
const Target * dynamicCast(bool doThrow=false) const
const overload, see overloaded function
Definition AutomatableModel.h:113
bool isValueChanged()
Definition AutomatableModel.h:290
virtual void loadSettings(const QDomElement &element, const QString &name)
Loads settings of AutomatableModel from a DOM element.
Definition AutomatableModel.cpp:178
static void resetPeriodCounter()
Definition AutomatableModel.h:312
ValueBuffer m_valueBuffer
Definition AutomatableModel.h:419
T initValue() const
Definition AutomatableModel.h:181
bool isAutomatedOrControlled() const
Definition AutomatableModel.h:121
bool isAutomated() const
Definition AutomatableModel.cpp:90
bool useControllerValue() const
Definition AutomatableModel.h:317
void initValueChanged(float val)
float controllerValue(int frameOffset) const
Definition AutomatableModel.cpp:504
float m_maxValue
Definition AutomatableModel.h:398
void saveSettings(QDomDocument &doc, QDomElement &element) override
Definition AutomatableModel.h:364
static T castValue(const float v)
Definition AutomatableModel.h:136
float m_centerValue
Definition AutomatableModel.h:401
Target * dynamicCast(bool doThrow=false)
Return this class casted to Target.
Definition AutomatableModel.h:104
static long s_periodCounter
Definition AutomatableModel.h:421
AutomatableModel(const float val=0, const float min=0, const float max=0, const float step=0, Model *parent=nullptr, const QString &displayName=QString(), bool defaultConstructed=false)
Definition AutomatableModel.cpp:45
float m_initValue
Definition AutomatableModel.h:396
void destroyed(lmms::jo_id_t id)
void setScaleLogarithmic(bool setToTrue=true)
Definition AutomatableModel.h:232
static void incrementPeriodCounter()
Definition AutomatableModel.h:307
float range() const
Definition AutomatableModel.h:223
float m_step
Definition AutomatableModel.h:399
QString nodeName() const override
Definition AutomatableModel.h:275
void setCenterValue(const float centerVal)
Definition AutomatableModel.h:248
float centerValue() const
Definition AutomatableModel.h:243
T maxValue() const
Definition AutomatableModel.h:198
T value(int frameOffset=0) const
Definition AutomatableModel.h:149
ValueBuffer * valueBuffer()
Function that returns sample-exact data as a ValueBuffer.
Definition AutomatableModel.cpp:530
static bool castValue(const float v)
Definition AutomatableModel.h:142
bool m_useControllerValue
Definition AutomatableModel.h:428
float m_minValue
Definition AutomatableModel.h:397
bool isAtInitValue() const
Definition AutomatableModel.h:186
float m_oldValue
used by valueBuffer for interpolation
Definition AutomatableModel.h:404
float fittedValue(float value) const
Definition AutomatableModel.cpp:404
void setScaleType(ScaleType sc)
Definition AutomatableModel.h:229
QMutex m_valueBufferMutex
Definition AutomatableModel.h:426
bool m_hasStrictStepSize
Definition AutomatableModel.h:408
long m_lastUpdatedPeriod
Definition AutomatableModel.h:420
AutomatableModel * m_nextLink
Definition AutomatableModel.h:412
virtual void accept(ModelVisitor &v)=0
void setValue(const float value, const bool isAutomated=false)
Definition AutomatableModel.cpp:294
ControllerConnection * m_controllerConnection
NULL if not appended to controller, otherwise connection info.
Definition AutomatableModel.h:416
bool isScaleLogarithmic() const
Definition AutomatableModel.h:236
ControllerConnection * controllerConnection() const
Definition AutomatableModel.h:126
void incValue(int steps)
Definition AutomatableModel.h:218
void loadSettings(const QDomElement &element) override
Definition AutomatableModel.h:369
ScaleType m_scaleType
scale type, linear by default
Definition AutomatableModel.h:394
virtual void accept(ConstModelVisitor &v) const =0
virtual void saveSettings(QDomDocument &doc, QDomElement &element, const QString &name)
Saves settings of AutomatableModel into a DOM element.
Definition AutomatableModel.cpp:103
float m_value
Definition AutomatableModel.h:395
T step() const
Definition AutomatableModel.h:204
T minValue() const
Definition AutomatableModel.h:192
bool isLinked() const
Definition AutomatableModel.h:282
ScaleType
Definition AutomatableModel.h:81
@ Logarithmic
Definition AutomatableModel.h:83
@ Linear
Definition AutomatableModel.h:82
virtual QString displayValue(const float val) const =0
bool m_valueChanged
Definition AutomatableModel.h:403
void setStrictStepSize(const bool b)
Definition AutomatableModel.h:302
float m_range
Definition AutomatableModel.h:400
bool m_hasSampleExactData
Definition AutomatableModel.h:423
BoolModel(const bool val=false, Model *parent=nullptr, const QString &displayName=QString(), bool defaultConstructed=false)
Definition AutomatableModel.h:506
Definition ModelVisitor.h:54
Definition ControllerConnection.h:53
FloatModel(float val=0, float min=0, float max=0, float step=0, Model *parent=nullptr, const QString &displayName=QString(), bool defaultConstructed=false)
Definition AutomatableModel.h:472
IntModel(int val=0, int min=0, int max=0, Model *parent=nullptr, const QString &displayName=QString(), bool defaultConstructed=false)
Definition AutomatableModel.h:490
JournallingObject()
Definition JournallingObject.cpp:36
Definition Model.h:37
virtual QString displayName() const
Definition Model.cpp:47
Model(Model *parent, QString displayName=QString(), bool defaultConstructed=false)
Definition Model.cpp:30
Definition ModelVisitor.h:40
Definition TimePos.h:68
Definition AutomatableModel.h:440
AutomatableModel(const float val=0, const float min=0, const float max=0, const float step=0, Model *parent=nullptr, const QString &displayName=QString(), bool defaultConstructed=false)
Definition AutomatableModel.cpp:45
T initValue() const
Definition AutomatableModel.h:448
T minValue() const
Definition AutomatableModel.h:453
T maxValue() const
Definition AutomatableModel.h:458
T value(int frameOffset=0) const
Definition AutomatableModel.h:443
Definition ValueBuffer.h:38
Definition RemotePluginBase.cpp:34
float logToLinearScale(float min, float max, float value)
Scales value from linear to logarithmic.
Definition lmms_math.h:241
QMap< AutomatableModel *, float > AutomatedValueMap
Definition AutomatableModel.h:516
std::uint32_t jo_id_t
Definition LmmsTypes.h:50
Definition AutomatableModel.h:357
void visit(const Target &tar)
Definition AutomatableModel.h:359
const Target * result
Definition AutomatableModel.h:358
Definition AutomatableModel.h:349
Target * result
Definition AutomatableModel.h:350
void visit(Target &tar)
Definition AutomatableModel.h:351