Skip to content

Commit 69f7c32

Browse files
szeli1allejok96
andauthored
Fix knob linking / refactor linking (#7883)
Closes #7869 This PR aims to fix linking bugs and it aims to make linking code faster. In the future I would like to replace controller and automation code with linked models, so it is essential for this feature to work as efficiently as possible. Before this PR: - AutomatableModels store a list of AutomatableModels that they are linked to. - setValue() and other functions make recursive calls to themself resulting in the #7869 crash. - Each AutomatableModel can unlink from other AutomatableModels, unlinking is the inverse operation to linking. After this PR: - AutomatableModels store a pointer to an other AutomatableModel making a linked list. The end is connected to the first element resulting in a "ring". - setValue() and others are now recursion free, the code runs for every linked model, more efficiently than before. - Each AutomatableModel can NOT unlink form other AutomatableModels, unlinking is NOT the inverse operation to linking. AutomatableModels can unlink themself from the linked list, they can not unlink themself from single models. --------- Co-authored-by: allejok96 <allejok96@gmail.com>
1 parent c92741f commit 69f7c32

File tree

13 files changed

+334
-217
lines changed

13 files changed

+334
-217
lines changed
Lines changed: 76 additions & 0 deletions
Loading
Lines changed: 76 additions & 0 deletions
Loading

include/AutomatableModel.h

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,6 @@ class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject
7777
{
7878
Q_OBJECT
7979
public:
80-
using AutoModelVector = std::vector<AutomatableModel*>;
81-
8280
enum class ScaleType
8381
{
8482
Linear,
@@ -150,22 +148,26 @@ class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject
150148
template<class T>
151149
inline T value( int frameOffset = 0 ) const
152150
{
153-
if (m_controllerConnection)
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+
157+
if (m_useControllerValue)
154158
{
155-
if (!m_useControllerValue)
159+
if (m_controllerConnection)
156160
{
157-
return castValue<T>(m_value);
161+
return castValue<T>(controllerValue(frameOffset));
158162
}
159-
else
163+
for (auto next = m_nextLink; next != this; next = next->m_nextLink)
160164
{
161-
return castValue<T>(controllerValue(frameOffset));
165+
if (next->controllerConnection() && next->useControllerValue())
166+
{
167+
return castValue<T>(fittedValue(next->controllerValue(frameOffset)));
168+
}
162169
}
163170
}
164-
else if (hasLinkedModels())
165-
{
166-
return castValue<T>( controllerValue( frameOffset ) );
167-
}
168-
169171
return castValue<T>( m_value );
170172
}
171173

@@ -211,8 +213,7 @@ class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject
211213

212214
void setInitValue( const float value );
213215

214-
void setAutomatedValue( const float value );
215-
void setValue( const float value );
216+
void setValue(const float value, const bool isAutomated = false);
216217

217218
void incValue( int steps )
218219
{
@@ -249,11 +250,10 @@ class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject
249250
m_centerValue = centerVal;
250251
}
251252

252-
//! link @p m1 and @p m2, let @p m1 take the values of @p m2
253-
static void linkModels( AutomatableModel* m1, AutomatableModel* m2 );
254-
static void unlinkModels( AutomatableModel* m1, AutomatableModel* m2 );
255-
256-
void unlinkAllModels();
253+
//! link this to @p model, copying the value from @p model
254+
void linkToModel(AutomatableModel* model);
255+
//! @return number of other models linked to this
256+
size_t countLinks() const;
257257

258258
/**
259259
* @brief Saves settings (value, automation links and controller connections) of AutomatableModel into
@@ -276,9 +276,9 @@ class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject
276276

277277
virtual QString displayValue( const float val ) const = 0;
278278

279-
bool hasLinkedModels() const
279+
bool isLinked() const
280280
{
281-
return !m_linkedModels.empty();
281+
return m_nextLink != this;
282282
}
283283

284284
// a way to track changed values in the model and avoid using signals/slots - useful for speed-critical code.
@@ -311,13 +311,14 @@ class LMMS_EXPORT AutomatableModel : public Model, public JournallingObject
311311
s_periodCounter = 0;
312312
}
313313

314-
bool useControllerValue()
314+
bool useControllerValue() const
315315
{
316316
return m_useControllerValue;
317317
}
318318

319319
public slots:
320320
virtual void reset();
321+
void unlink();
321322
void unlinkControllerConnection();
322323
void setUseControllerValue(bool b = true);
323324

@@ -367,9 +368,15 @@ public slots:
367368
loadSettings( element, "value" );
368369
}
369370

370-
void linkModel( AutomatableModel* model );
371-
void unlinkModel( AutomatableModel* model );
371+
void setValueInternal(const float value);
372372

373+
//! linking is stored in a linked list ring
374+
//! @return the model whose `m_nextLink` is `this`,
375+
//! or `this` if there are no linked models
376+
AutomatableModel* getLastLinkedModel() const;
377+
//! @return true if the `model` is in the linked list
378+
bool isLinkedToModel(AutomatableModel* model) const;
379+
373380
//! @brief Scales @value from linear to logarithmic.
374381
//! Value should be within [0,1]
375382
template<class T> T logToLinearScale( T value ) const;
@@ -389,16 +396,15 @@ public slots:
389396
float m_centerValue;
390397

391398
bool m_valueChanged;
392-
393-
// currently unused?
394-
float m_oldValue;
395-
int m_setValueDepth;
399+
float m_oldValue; //!< used by valueBuffer for interpolation
396400

397401
// used to determine if step size should be applied strictly (ie. always)
398402
// or only when value set from gui (default)
399403
bool m_hasStrictStepSize;
400404

401-
AutoModelVector m_linkedModels;
405+
//! an `AutomatableModel` can be linked together with others in a linked list
406+
//! the list has no end, the last model is connected to the first forming a ring
407+
AutomatableModel* m_nextLink;
402408

403409

404410
//! NULL if not appended to controller, otherwise connection info

include/AutomatableModelView.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ public slots:
9898
void execConnectionDialog();
9999
void removeConnection();
100100
void editSongGlobalAutomation();
101-
void unlinkAllModels();
102101
void removeSongGlobalAutomation();
103102

104103
private slots:

plugins/Vestige/Vestige.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,8 +1052,8 @@ void ManageVestigeInstrumentView::syncPlugin( void )
10521052
std::snprintf(paramStr.data(), paramStr.size(), "param%d", i);
10531053
s_dumpValues = dump[paramStr.data()].split(":");
10541054
float f_value = LocaleHelper::toFloat(s_dumpValues.at(2));
1055-
m_vi->knobFModel[ i ]->setAutomatedValue( f_value );
1056-
m_vi->knobFModel[ i ]->setInitValue( f_value );
1055+
m_vi->knobFModel[i]->setValue(f_value, true);
1056+
m_vi->knobFModel[i]->setInitValue(f_value);
10571057
}
10581058
}
10591059
syncParameterText();

plugins/VstEffect/VstEffectControls.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -455,8 +455,8 @@ void ManageVSTEffectView::syncPlugin()
455455
std::snprintf(paramStr.data(), paramStr.size(), "param%d", i);
456456
s_dumpValues = dump[paramStr.data()].split(":");
457457
float f_value = LocaleHelper::toFloat(s_dumpValues.at(2));
458-
m_vi2->knobFModel[ i ]->setAutomatedValue( f_value );
459-
m_vi2->knobFModel[ i ]->setInitValue( f_value );
458+
m_vi2->knobFModel[i]->setValue(f_value, true);
459+
m_vi2->knobFModel[i]->setInitValue(f_value);
460460
}
461461
}
462462
syncParameterText();

0 commit comments

Comments
 (0)