-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix knob linking / refactor linking #7883
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Hey Bro! Nice job I was just testint It and I have a problem I think. When you link mixer channels to the volume fader It changes them so fast that It was jumping for o to 4 really fast thought I think a better way to do this would be to divide the volume range by the number of mixers channels so It is more responsive I guess I don't know if thats challenging but I guess so anyway I got ninja and could test it that for each volume step mixer channels got update right so this is very subjective right but I think It'll feel alot better. |
This is because internally everything is stored as a float even the mute buttons, but these internal values do not range from 0 to 1, but from a custom min value to a custom max value. Each widget receives the same value and interprets it with their own min-max. For example the mixer channel lcd widget gets "2" as input and sends it over to the mute button, the mute button ranges from 0 to 1 so it clamps the "2" to "1" and turns on. If you connect a mixer channel lcd widget to a volume knob, the volume knob ranges from 0 to 200 but the lcd widget ranges from 0 to the number of mixer channels, for example 4. This leads to the behavior you are experiencing. Its feels badly designed, I will see what I can do. |
I tested this, and it definitely seems to fix the bug. Also it seems like you also addressed #7621, somehow. One thing I noticed is that now if two knobs with different ranges are linked (like volume and panning), if you move one knob out of the range of the other knob (like moving panning to negative), it lets you do that and just sets the value of the other knob to within its own bounds (volume doesn't go below 0). However, on master, if you try to turn one knob past the end of a linked knob, it won't let you, it will stop you from turning it. If you try to turn panning below 0, it won't let you. Well, sometimes. Sometimes it would still let you do it if you did some complicated linking between multiple knobs. Maybe that's a good thing in this PR? It feels like it probably gives users more freedom. Though of course it means if you move the other knob, the first knob will snap back, which might not be desirable idk. But if it's also in master sometimes... idk, this PR feels like a much cleaner system. |
Tried to cause the crash described in the corresponding issue, and couldn't! 🎉 It seems the image for the "Remove all linked controls" is missing and I get this issue:
I also observe this on master. |
LCD linking to other LCD items isn't possible. Interestingly, you can link LCDs to knobs. |
Thanks for testing @regulus79 and @bratpeki |
Yes sounds like LCD widgets do not accept the link for some reason. |
I can make it work like in old lmms, but currently linking isn't saved so this new behavior won't change anyone's project and It will add an additional loop for setValue which would make setValue more computationally expensive. This isn't ideal for the next step: removing controller connection and replacing it with linking. |
I find this very strange, TBH. Can someome check they're also getting this in the terminal when removing linking in the context menu? |
I got this message also, there is no "edit-delete" file in the theme. I could fix it if you want it, but I'm unsure what kind of picture to use / make. |
I also get that message. Also, 1.2.2 doesn't appear to have the icon either, although I don't get any warning in the terminal. |
I added a new svg for unlinking @bratpeki |
Cool! Any idea why the old one was missing? Or maybe it was never there? |
I see! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested this quite rigorously, didn't find any issues. Just have a few style nitpicks.
m_vi->knobFModel[ i ]->setValue(f_value, true); | ||
m_vi->knobFModel[ i ]->setInitValue( f_value ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
m_vi->knobFModel[ i ]->setValue(f_value, true); | |
m_vi->knobFModel[ i ]->setInitValue( f_value ); | |
m_vi->knobFModel[i]->setValue(f_value, true); | |
m_vi->knobFModel[i]->setInitValue(f_value); |
m_vi2->knobFModel[ i ]->setValue(f_value, true); | ||
m_vi2->knobFModel[ i ]->setInitValue( f_value ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
m_vi2->knobFModel[ i ]->setValue(f_value, true); | |
m_vi2->knobFModel[ i ]->setInitValue( f_value ); | |
m_vi2->knobFModel[i]->setValue(f_value, true); | |
m_vi2->knobFModel[i]->setInitValue(f_value); |
m_range( max - min ), | ||
m_centerValue( m_minValue ), | ||
m_valueChanged( false ), |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
m_hasStrictStepSize( false ), | ||
m_nextLink(nullptr), | ||
m_controllerConnection( nullptr ), | ||
m_valueBuffer( static_cast<int>( Engine::audioEngine()->framesPerPeriod() ) ), | ||
m_lastUpdatedPeriod( -1 ), |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
m_linkedModels.erase( m_linkedModels.end() - 1 ); | ||
} | ||
// unlink this from anything else | ||
unlinkModel(); | ||
|
||
if( m_controllerConnection ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if( m_controllerConnection ) | |
if(m_controllerConnection) |
template<class T> T AutomatableModel::logToLinearScale( T value ) const | ||
{ | ||
return castValue<T>( lmms::logToLinearScale( minValue<float>(), maxValue<float>(), static_cast<float>( value ) ) ); |
This comment was marked as off-topic.
This comment was marked as off-topic.
Sorry, something went wrong.
menu->addAction( embed::getIconPixmap( "edit_unlink" ), | ||
AutomatableModel::tr( "Remove all linked controls" ), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
menu->addAction( embed::getIconPixmap( "edit_unlink" ), | |
AutomatableModel::tr( "Remove all linked controls" ), | |
menu->addAction(embed::getIconPixmap("edit_unlink"), | |
AutomatableModel::tr("Remove all linked controls"), |
} | ||
} | ||
|
||
if( m_oldValue != val ) | ||
if (m_oldValue != val) | ||
{ | ||
m_valueBuffer.interpolate( m_oldValue, val ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
m_valueBuffer.interpolate( m_oldValue, val ); | |
m_valueBuffer.interpolate(m_oldValue, val); |
@@ -342,16 +342,18 @@ void LadspaControl::unlinkControls( LadspaControl * _control ) | |||
switch( m_port->data_type ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
switch( m_port->data_type ) | |
switch(m_port->data_type) |
void setAutomatedValue( const float value ); | ||
void setValue( const float value ); | ||
void setAutomatedValue(float value); | ||
void setValue(float value, bool isAutomated = false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the difference between setting the automated value via setAutomatedValue()
and setValue(..., true)
?
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 ofAutomatableModels
that they are linked to.setValue()
and other functions make recursive calls to themself resulting in the Linked controls can cause crashes #7869 crashAutomatableModel
can unlink form otherAutomatableModels
, unlinking is the inverse operation to linking.After this PR:
AutomatableModels
store a pointer to an otherAutomatableModel
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.AutomatableModel
can NOT unlink form otherAutomatableModels
, unlinking is NOT the inverse operation to linking.AutomatableModels
can unlink themself from the linked list, they can not unlink themself from single models.Issues:
AutomatableModel::value()
uses a hack non constsetValue()
to update linked widgets if a controller is connected.How to test: