-
-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Play automation pattern when midi controller connected #5657
Conversation
🤖 Hey, I'm @LmmsBot from github.com/lmms/bot and I made downloads for this pull request, click me to make them magically appear! 🎩
Linux
Windows
🤖{"platform_name_to_artifacts": {"Linux": [{"artifact": {"title": {"title": "(AppImage)", "platform_name": "Linux"}, "link": {"link": "https://12187-15778896-gh.circle-artifacts.com/0/lmms-1.3.0-alpha.1.68%2Bgbd850b8-linux-x86_64.AppImage"}}, "build_link": "https://circleci.com/gh/LMMS/lmms/12187?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link"}], "Windows": [{"artifact": {"title": {"title": "32-bit", "platform_name": "Windows"}, "link": {"link": "https://12188-15778896-gh.circle-artifacts.com/0/lmms-1.3.0-alpha.1.68%2Bgbd850b8d3-mingw-win32.exe"}}, "build_link": "https://circleci.com/gh/LMMS/lmms/12188?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link"}, {"artifact": {"title": {"title": "64-bit", "platform_name": "Windows"}, "link": {"link": "https://12189-15778896-gh.circle-artifacts.com/0/lmms-1.3.0-alpha.1.68%2Bgbd850b8d3-mingw-win64.exe"}}, "build_link": "https://circleci.com/gh/LMMS/lmms/12189?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link"}, {"artifact": {"title": {"title": "32-bit", "platform_name": "Windows"}, "link": {"link": "https://ci.appveyor.com/api/buildjobs/amntmm6u8b73mcqm/artifacts/build/lmms-1.3.0-alpha-msvc2017-win32.exe"}}, "build_link": "https://ci.appveyor.com/project/Lukas-W/lmms/builds/37363583"}, {"artifact": {"title": {"title": "64-bit", "platform_name": "Windows"}, "link": {"link": "https://ci.appveyor.com/api/buildjobs/w3orkxotxbvr43c3/artifacts/build/lmms-1.3.0-alpha-msvc2017-win64.exe"}}, "build_link": "https://ci.appveyor.com/project/Lukas-W/lmms/builds/37363583"}]}, "commit_sha": "406575f780048978350b33febb3a57edd499e600"} |
It just works 👍 Love it :D |
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 by @qnebra and style looks okay to me. Sorry for the massive delay.
Sorry about the late review! The PR improves the behavior to be closer to what an user would expect, thanks a lot for putting some effort on it! From a first review I didn't notice any bugs on the code, but there are a few points that concern me on its current state:
What I think could be done instead (there's a small very raw sketch with an example later):
That logic can be used just for MIDI controllers as you're doing on your PR too, though I don't think it's strictly necessary: The user should know that connecting a model to a LFO controller and having automations simultaneously will cause conflicts, so having the automation override the LFO is just one of the alternatives, no better and no worse IMHO. Here's the example, it's very raw and needs some improvements, but gives a broad idea: I'm at the disposal to help if you'd like to give this alternative a try! |
Sorry for the delay.
I assumed (maybe wrong) that controllers would have to take precedence over linked automations.
If an automation pattern is recording, As for the other points you made I would like to see your example code to comment. |
No problem! If it happens that you like this alternative solution and want to apply it here you can just copy it, I don't mind authorship at all and this has been your PR from the beginning, the approach I came up with even though different was derived from your work anyways. I think other devs should share what they think as well though, I shouldn't be the only one weighting in.
I wasn't sure neither, later I found out that linked controllers are an abstraction of those LADSPA plugins linked channels, where one channel's parameters are linked to the other channel's parameters (to be used with Lv2). Then I believe it makes sense they have precedence over the controllers.
I missed that, ignore that point then! 😁 |
@IanCaio I checked your code and I think it's a more elegant approach, but this PR approach I think is more flexible, e.g. : Before entering any automation patterns you can use the midi controller and then play / listen to those automation patterns all in one song play. This avoids deleting / muting the automation patterns in order to use the midi controller. If there are recording patterns between other automation patterns, you can record after playing / listening to the automatic patterns, also all in one song play. |
I haven't tested both in a while but from what I remember of the code you're right, in terms of UX I think your approach behave better. Still, if we are to use it, I think we should find a way to reorganize the code in a clearer way to future readers, in its current state it can be a bit confusing. I'll read the diff again and try to think of something. |
I made an improved version of this PR. Here. |
Nice! I like the changes, they made it easier to understand than the previous version.
For now that's what I noticed, could you commit those changes to the PR? Then I can help you out by suggesting the changes for removing the MIDI logic for example. |
Moving the linked button of a button with a controller doesn't affect it, so I think it's not very intuitive for automation to do it.That was the behavior before this PR, so I added that clause because with the code changes it was necessary to keep the old behavior (forgot to mention that). I will commit the new version and remove the specific midi controller code soon. |
Hopefully it would still work after commiting new version. |
That happens because the linked models are being handled on
The current behavior is messy, I'd advise we touch this the least possible so we have less code to fix later. I still need to figure out which parts of your code that adds conditionals to the linked models are necessary now and which might not be. Again, this problem comes from before your PR, I'm just trying to make sure it doesn't add complexity for something that will have to be fixed later! Thanks for being patient with my reviewing 😬
Awesome, that will definitely make it even simpler! Let me know when you commit it by commenting here. While you're at it I'll be still trying to figure out that last linked models issue, and once that's done I think it will be ready for merge. |
Done. I commited the code. |
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.
Left another review on the updated code. It's being hard to review the parts related to linked models because I think their current implementation needs some fixing, but I'm trying to make sure the behavior is close to the expected.
Do you happen to use Discord? Maybe using LMMS server Dev channels would make discussions about this PR faster than Github comments.
{ | ||
if( (*it)->m_setValueDepth < 1 && | ||
(*it)->fittedValue( m_value ) != (*it)->m_value ) | ||
if (!((*it)->controllerConnection()) && (*it)->m_setValueDepth < 1 && |
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 (!((*it)->controllerConnection()) && (*it)->m_setValueDepth < 1 && | |
if ((*it)->m_setValueDepth < 1 && |
Considering a strict link between models, if one model is affected by the automation its linked models probably should have their values set as well, even if they are connected to a controller.
However, that suggested change has a side effect I still don't know how to deal with: Currently the m_useControllerValue
variable is set through signals, one of them being triggered when an automation ceases being part of a particular time frame of the song being played. If the linked model has setAutomationValue
called m_useControllerValue
will be set to false. But since this was triggered from the automation of another model, there will be no signal throughout the rest of the track to set m_useControllerValue
back to true (the code using m_oldAutomatedValues
), only when the song stop.
I'm not sure that side effect is much of an issue, since the models should be strictly linked, meaning that if one of them is automated the other should follow its value as well. That is not true even before that PR: controllers end up preceding linked models, which goes back to the matter of having to reorganize the code of linked models.
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.
However, that suggested change has a side effect I still don't know how to deal with:
We can notify the linked models in setUseControllerValue().
But before we get into the linked code, I think we need to decide whether to keep the old behavior or to touch it a minimum (even if this is buggy) to fix it later.
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.
I think that would do it, but you're right. I'll ask other devs what they think. Maybe it would be simpler to keep the code as you wrote it and fix the linked models behavior later.
} | ||
if( lm && lm->controllerConnection() && lm->controllerConnection()->getController()->isSampleExact() ) | ||
|
||
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.
I think that conditional could be removed. If this model has a controller, but the value of the controller wasn't used (useControllerValue == false
, meaning previous conditional was skipped), shouldn't it check for the linked models?
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 useControllerValue == false it means that it's playing an automation pattern so it shouldn't check the linked models
I prefer to keep the discussion here, I'm not in a hurry. |
No problem! I'll check with other devs about the linked models issue and let you know what they say. Once that last detail is decided we can ask people to test it again and approve it. Sorry about the nitpicking on the linked models code, I know it's currently a mess so this isn't your PRs fault at all. Just trying to look on the long run what will make fixing the code less demanding in the future. |
Co-authored-by: IanCaio <[email protected]>
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.
I didn't receive much feedback on the Linked Models issue. I'm approving those changes since I think the code was improved a lot in terms of being clearer.
One note not directly related to this PR: We will have to refactor the Linked Models code in the future, it's not very well designed IMHO and overlaps too much with the controller code. Because of that it's hard to make changes on the way we handle controllers without affecting the linked models, as can be see on the reviewing history.
That aside, I think this is good code-wise and ready for testing.
Quick test:
Not big deal and doesn't break overall functionality. When "automated LFO" and "controller LFO" for example had different 'speed' values during playing some sort of "values fight" occurs. I think mainly because LFO constantly sends signals to connected parameters. Not big deal, and for me not related to this PR. It was more in terms of how LFO works in lmms "as is". |
@serdnab Thanks for the work and patience with the reviewing! And sorry about the delay with merging, I missed that there was a second approval and only recently noticed it. |
It's possible that I'll have to revert the commit that merges this PR. I noticed a bug, where some projects will crash when they are reloaded and the Play button is pressed. The backtrace points to
|
Can you send a project, or describe how to reproduce it? Just wanted to check if it crashed for me too. |
* Play automation pattern when midi controller connected * empty line removed * Improved for clarity * removed midi specific controller logic * formatting changes * comments added Co-authored-by: IanCaio <[email protected]> Co-authored-by: IanCaio <[email protected]>
I can confirm there is something or introduced by this PR, or exposed by this PR, which can cause crashes in specific workflow. |
There was a bug introduced by LMMS#5657 where reloading a project and playing it could cause a Segmentation Fault crash. After some debugging, @DomClark tracked the issue to be likely a use-after-free being caused by m_oldAutomatedValues not being cleared when the project was loaded again. This commit adds a line to clear the m_oldAutomatedValues map on Song::clearProject(), which is called from Song::loadProject(). Co-authored-by: Dominic Clark <[email protected]>
Now, instead of using a Signal/Slot connection to move the control of the models back to the controllers, every time the song is processing the automations, the control of the models that were processed in the last cycle are moved back to the controller. The same is done under Song::stop(), so the last cycle models control is moved back to the controller. That removes the need to have a pointer to the controlled model in the controller object.
* Fix bug introduced by #5657 There was a bug introduced by #5657 where reloading a project and playing it could cause a Segmentation Fault crash. After some debugging, @DomClark tracked the issue to be likely a use-after-free being caused by m_oldAutomatedValues not being cleared when the project was loaded again. This commit adds a line to clear the m_oldAutomatedValues map on Song::clearProject(), which is called from Song::loadProject(). Now, instead of using a Signal/Slot connection to move the control of the models back to the controllers, every time the song is processing the automations, the control of the models that were processed in the last cycle are moved back to the controller. The same is done under Song::stop(), so the last cycle models control is moved back to the controller. That removes the need to have a pointer to the controlled model in the controller object. Adds mixer model change request to avoid race condition. Co-authored-by: Dominic Clark <[email protected]>
* Play automation pattern when midi controller connected * empty line removed * Improved for clarity * removed midi specific controller logic * formatting changes * comments added Co-authored-by: IanCaio <[email protected]> Co-authored-by: IanCaio <[email protected]>
* Fix bug introduced by LMMS#5657 There was a bug introduced by LMMS#5657 where reloading a project and playing it could cause a Segmentation Fault crash. After some debugging, @DomClark tracked the issue to be likely a use-after-free being caused by m_oldAutomatedValues not being cleared when the project was loaded again. This commit adds a line to clear the m_oldAutomatedValues map on Song::clearProject(), which is called from Song::loadProject(). Now, instead of using a Signal/Slot connection to move the control of the models back to the controllers, every time the song is processing the automations, the control of the models that were processed in the last cycle are moved back to the controller. The same is done under Song::stop(), so the last cycle models control is moved back to the controller. That removes the need to have a pointer to the controlled model in the controller object. Adds mixer model change request to avoid race condition. Co-authored-by: Dominic Clark <[email protected]>
fix for #4554
When a button is connected to a midi controller it now plays the automation patterns.
I added a flag that when it is playing an automation pattern it does not look for
controllerValue()
butm_value
.Also I added:
isControllerMidi()
toControllerConnection.h
that is set when the controller is midithis code so that when an automatable model exits automation the midi controller takes back control
a signal connection so that when the song stops the midi controller takes back control