LMMS
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
266 virtual void saveSettings( QDomDocument& doc, QDomElement& element, const QString& name );
267
270 virtual void loadSettings( const QDomElement& element, const QString& name );
271
272 QString nodeName() const override
273 {
274 return "automatablemodel";
275 }
276
277 virtual QString displayValue( const float val ) const = 0;
278
279 bool isLinked() const
280 {
281 return m_nextLink != this;
282 }
283
284 // a way to track changed values in the model and avoid using signals/slots - useful for speed-critical code.
285 // note that this method should only be called once per period since it resets the state of the variable - so if your model
286 // has to be accessed by more than one object, then this function shouldn't be used.
288 {
289 if( m_valueChanged || valueBuffer() )
290 {
291 m_valueChanged = false;
292 return true;
293 }
294 return false;
295 }
296
297 float globalAutomationValueAt( const TimePos& time );
298
299 void setStrictStepSize( const bool b )
300 {
302 }
303
305 {
307 }
308
309 static void resetPeriodCounter()
310 {
311 s_periodCounter = 0;
312 }
313
315 {
317 }
318
319public slots:
320 virtual void reset();
321 void unlink();
322 void unlinkControllerConnection();
323 void setUseControllerValue(bool b = true);
324
325
326protected:
328 const float val = 0,
329 const float min = 0,
330 const float max = 0,
331 const float step = 0,
332 Model* parent = nullptr,
333 const QString& displayName = QString(),
334 bool defaultConstructed = false );
339 float fittedValue( float value ) const;
340
341
342private:
343 // dynamicCast implementation
344 template<class Target>
346 {
347 Target* result = nullptr;
348 void visit(Target& tar) { result = &tar; }
349 };
350
351 // dynamicCast implementation
352 template<class Target>
354 {
355 const Target* result = nullptr;
356 void visit(const Target& tar) { result = &tar; }
357 };
358
359 static bool mustQuoteName(const QString &name);
360
361 void saveSettings( QDomDocument& doc, QDomElement& element ) override
362 {
363 saveSettings( doc, element, "value" );
364 }
365
366 void loadSettings( const QDomElement& element ) override
367 {
368 loadSettings( element, "value" );
369 }
370
371 void setValueInternal(const float value);
372
376 AutomatableModel* getLastLinkedModel() const;
378 bool isLinkedToModel(AutomatableModel* model) const;
379
382 template<class T> T logToLinearScale( T value ) const;
383
386 template<class T> void roundAt( T &value, const T &where ) const;
387
388
390 float m_value;
394 float m_step;
395 float m_range;
397
400
401 // used to determine if step size should be applied strictly (ie. always)
402 // or only when value set from gui (default)
404
408
409
412
413
416 static long s_periodCounter;
417
419
420 // prevent several threads from attempting to write the same vb at the same time
422
424
425signals:
426 void initValueChanged( float val );
428
429} ;
430
431
432
433
434template <typename T> class LMMS_EXPORT TypedAutomatableModel : public AutomatableModel
435{
436public:
438 T value( int frameOffset = 0 ) const
439 {
440 return AutomatableModel::value<T>( frameOffset );
441 }
442
443 T initValue() const
444 {
446 }
447
448 T minValue() const
449 {
451 }
452
453 T maxValue() const
454 {
456 }
457};
458
459
460// some typed AutomatableModel-definitions
461
462class LMMS_EXPORT FloatModel : public TypedAutomatableModel<float>
463{
464 Q_OBJECT
466public:
467 FloatModel( float val = 0, float min = 0, float max = 0, float step = 0,
468 Model * parent = nullptr,
469 const QString& displayName = QString(),
470 bool defaultConstructed = false ) :
471 TypedAutomatableModel( val, min, max, step, parent, displayName, defaultConstructed )
472 {
473 }
474 float getRoundedValue() const;
475 int getDigitCount() const;
476 QString displayValue( const float val ) const override;
477} ;
478
479
480class LMMS_EXPORT IntModel : public TypedAutomatableModel<int>
481{
482 Q_OBJECT
484public:
485 IntModel( int val = 0, int min = 0, int max = 0,
486 Model* parent = nullptr,
487 const QString& displayName = QString(),
488 bool defaultConstructed = false ) :
489 TypedAutomatableModel( val, min, max, 1, parent, displayName, defaultConstructed )
490 {
491 }
492 QString displayValue( const float val ) const override;
493} ;
494
495
496class LMMS_EXPORT BoolModel : public TypedAutomatableModel<bool>
497{
498 Q_OBJECT
500public:
501 BoolModel( const bool val = false,
502 Model* parent = nullptr,
503 const QString& displayName = QString(),
504 bool defaultConstructed = false ) :
505 TypedAutomatableModel( val, false, true, 1, parent, displayName, defaultConstructed )
506 {
507 }
508 QString displayValue( const float val ) const override;
509} ;
510
511using AutomatedValueMap = QMap<AutomatableModel*, float>;
512
513} // namespace lmms
514
515#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:287
virtual void loadSettings(const QDomElement &element, const QString &name)
Loads settings (value, automation links and controller connections) of AutomatableModel from specifie...
Definition AutomatableModel.cpp:178
static void resetPeriodCounter()
Definition AutomatableModel.h:309
ValueBuffer m_valueBuffer
Definition AutomatableModel.h:414
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:314
void initValueChanged(float val)
float controllerValue(int frameOffset) const
Definition AutomatableModel.cpp:514
float m_maxValue
Definition AutomatableModel.h:393
void saveSettings(QDomDocument &doc, QDomElement &element) override
Definition AutomatableModel.h:361
static T castValue(const float v)
Definition AutomatableModel.h:136
float m_centerValue
Definition AutomatableModel.h:396
Target * dynamicCast(bool doThrow=false)
Return this class casted to Target.
Definition AutomatableModel.h:104
static long s_periodCounter
Definition AutomatableModel.h:416
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:391
void destroyed(lmms::jo_id_t id)
void setScaleLogarithmic(bool setToTrue=true)
Definition AutomatableModel.h:232
static void incrementPeriodCounter()
Definition AutomatableModel.h:304
float range() const
Definition AutomatableModel.h:223
float m_step
Definition AutomatableModel.h:394
QString nodeName() const override
Definition AutomatableModel.h:272
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:540
static bool castValue(const float v)
Definition AutomatableModel.h:142
bool m_useControllerValue
Definition AutomatableModel.h:423
float m_minValue
Definition AutomatableModel.h:392
bool isAtInitValue() const
Definition AutomatableModel.h:186
float m_oldValue
used by valueBuffer for interpolation
Definition AutomatableModel.h:399
float fittedValue(float value) const
Definition AutomatableModel.cpp:404
void setScaleType(ScaleType sc)
Definition AutomatableModel.h:229
QMutex m_valueBufferMutex
Definition AutomatableModel.h:421
bool m_hasStrictStepSize
Definition AutomatableModel.h:403
long m_lastUpdatedPeriod
Definition AutomatableModel.h:415
AutomatableModel * m_nextLink
Definition AutomatableModel.h:407
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:411
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:366
ScaleType m_scaleType
scale type, linear by default
Definition AutomatableModel.h:389
virtual void accept(ConstModelVisitor &v) const =0
virtual void saveSettings(QDomDocument &doc, QDomElement &element, const QString &name)
Saves settings (value, automation links and controller connections) of AutomatableModel into specifie...
Definition AutomatableModel.cpp:103
float m_value
Definition AutomatableModel.h:390
T step() const
Definition AutomatableModel.h:204
T minValue() const
Definition AutomatableModel.h:192
bool isLinked() const
Definition AutomatableModel.h:279
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:398
void setStrictStepSize(const bool b)
Definition AutomatableModel.h:299
float m_range
Definition AutomatableModel.h:395
bool m_hasSampleExactData
Definition AutomatableModel.h:418
BoolModel(const bool val=false, Model *parent=nullptr, const QString &displayName=QString(), bool defaultConstructed=false)
Definition AutomatableModel.h:501
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:467
IntModel(int val=0, int min=0, int max=0, Model *parent=nullptr, const QString &displayName=QString(), bool defaultConstructed=false)
Definition AutomatableModel.h:485
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:435
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:443
T minValue() const
Definition AutomatableModel.h:448
T maxValue() const
Definition AutomatableModel.h:453
T value(int frameOffset=0) const
Definition AutomatableModel.h:438
Definition ValueBuffer.h:38
unsigned v[N_MAX]
Definition inflate.c:1584
static PuglViewHint int value
Definition pugl.h:1708
static const char * name
Definition pugl.h:1582
static uintptr_t parent
Definition pugl.h:1644
int val
Definition jpeglib.h:956
Definition AudioAlsa.cpp:35
float logToLinearScale(float min, float max, float value)
Scales @value from linear to logarithmic. Value should be within [0,1].
Definition lmms_math.h:239
static void roundAt(T &value, const T &where, const T &stepSize)
Round value to where depending on step size.
Definition lmms_math.h:193
QMap< AutomatableModel *, float > AutomatedValueMap
Definition AutomatableModel.h:511
std::uint32_t jo_id_t
Definition LmmsTypes.h:50
#define true
Definition ordinals.h:82
#define false
Definition ordinals.h:83
#define min(x, y)
Definition os.h:74
#define max(x, y)
Definition os.h:78
Definition AutomatableModel.h:354
void visit(const Target &tar)
Definition AutomatableModel.h:356
const Target * result
Definition AutomatableModel.h:355
Definition AutomatableModel.h:346
Target * result
Definition AutomatableModel.h:347
void visit(Target &tar)
Definition AutomatableModel.h:348
return c
Definition crypt.c:175
b
Definition crypt.c:628