-
Notifications
You must be signed in to change notification settings - Fork 10
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
Device rewrite #34
base: master
Are you sure you want to change the base?
Device rewrite #34
Conversation
Added the concept of *MidiActions*. It comprises is not only the action to be executed, when the MidiAction is triggered, but also the storing/saving of the binding of midi-messages in the device. A *MidiAction* is a decorator that can be applied to Methods anywhere in the Program. The method which is decorated contains the actual program-code that should be executed, when the *MidiAction* is triggered. In the most simple case it would be a method that is also a handler for a gui-element of the program. the decorator registers the *MidiAction* in a global place. every time a midi action is used from some place in the code, it will tell the midi action which device should be used. the devace - just as before - is merely a container for the data that can be de/serialized easily There are three types of midi actions: * MidiAction - regular single-trigger midi action * MidiRowAction - a midi action that stores a one-dimensional list of bindings * MidiGridAction - a midi action that stores a two-dimensional list of bindings Each of them comes in two variants: * normal: messages with velocity 0 will be ignored * continuous: all messages are interpreted When midi-messages are learned, not the complete message, but only a key is stored in the device. the key is the original midi messages without the velocity. when the action is triggered, however, the velocity is simply routed through to the method. This restriction makes it impossible to bind midi messages with the same signature that differ in velocity only to different midi actions. For instance a button that would send the same midi message with velocity 0 and 127 cannot trigger different things on push and release. However, this should not be encouraged anyways. If this should ever become an issue in the future - say someone wants to add actions that have a relevant "on" and "off" part to them, it is recommended to subclass MidiAction and make a new model that reflects this behaviour (store two midi messages).
The purpose of this pull request is to simplify code and also remove duplicate code. There is no issue with current device format, so there is no need to change device format and break compatibility. Please keep device format as is. |
I think midi message with more than 3 byte are not interesting for superboucle. It is mainly bpm information or power up message from some device. So you can safely just drop thoses messages. |
The code simplification does not work with the original midi device as it depends on knowing which mapping in the device is an input. |
I assume we're only talking about the "single trigger" events right now (not Volume where velocity is routed through). Learn mode: performance: I had a long discussion with @sonejostudios and opposed the idea at first, but in the end implemented it: I just dont't save the velocity in the mapping at all. Whether this is relevant boils down to the following: clearly there are buttons that would send push- and release messages with velocity 0 and 127 respectively. But so far the program does not need to distinguish them: there are no uses for button-release messages. If this would become relevant in the future an elegant workaround is possible by extending the MidiAction class. Can you see a case might have missed? Or do you have any other reason to believe the velocity would have to be saved in the mapping? |
If you don't use velocity with device that send 0 and 127 for push and release, then device will trigger 2 events when you push and release button. So this will start and then stop clip with one push and releaase. |
To avoid this, I am simply ignoring velocity 0 messages. |
midi feedback abstraction is a little bit better now: added a routine to transform midi-id's that are bound in the device for an appropriate output. Most of it is however still launchpad-specific. cleanup: had forgotten to clear the unused processNote method from gui. bugfix: made sure, midi keys are interpreted as tuples (MidiRowAction checked agains lists instead after save/load)
@Vampouille @sonejostudios has tested the branch a bit so far and didn't run into problems. |
This PR have too many modifications. You cannot change file extension, file format... Other people are using superboucle, I don't want to break compatibility. |
Apologies, it seems I haven't made the motivation clear enough. While the original motivation to start these changes was indeed to remove code duplicates: The motivation for this PR is far more, namely to improve flexibility with respect to midi actions - I felt it would take any contributor that wanted to add a new feature whith midi bindings hours of unnecessary work, because
To me it seemed impossible to add a new midi action with the old code while trying to maintain readability. With this PR I have tried to solve all 3 issues to the best of what I could do, while trying to stay close to how the program handled midi learning as much as I could. I absolutely agree, that changing a file format and thereby breaking compatibility comes with a big cost and shouldn't be done without a good reason. If you believe that my attempt to solve them is not the right way, I'd be glad if we could talk about it. |
If you want to add a new Midi-triggerable Action with this version, it is in my opinion a lot easier. Assume there is a method somewhere which implements an action performed by the program, usually via gui (does not have to be in gui.py, but so far all are) that you want to be midi-learnable (and -triggerable)
It has been a month since I implemented all of this, but if i have not forgotten anything, that should be it. I was planning to add a sample midi action (load next or previous sond from the playlist) in an additional commit to make the exact code changes visible in the diff. We've put a lot of thought into the mechanics, but I do not at all claim that it is perfect, and I'd be glad to change things, that don't seem proper, if you were interested in this PR - like we can absolutely talk about the learning of vel-0 messages (I believe it is possible with single-actions, but not with row-actions. with continuous actions also it is no problem.). |
Added the concept of MidiActions.
It comprises not only the action to be executed, when the MidiAction is triggered, but also the storing/saving of the binding of midi-messages in the device.
A MidiAction is a decorator that can be applied to Methods anywhere in the Program.
The method which is decorated contains the actual program-code that should be executed, when the MidiAction is triggered. In the most simple case it would be a method that is also a handler for a gui-element of the program.
the decorator registers the MidiAction in a global place. every time a midi action is used from some place in the code, it will tell the midi action which device should be used. the devace - just as before - is merely a container for the data that can be de/serialized easily
There are three types of midi actions:
Each of them comes in two variants:
When midi-messages are learned, not the complete message, but only a key is stored in the device.
the key is the original midi messages without the velocity.
when the action is triggered, however, the velocity is simply routed through to the method.
This restriction makes it impossible to bind midi messages with the same signature that differ in velocity only to different midi actions. For instance a button that would send the same midi message with velocity 0 and 127 cannot trigger different things on push and release. However, this should not be encouraged anyways.
If this should ever become an issue in the future - say someone wants to add actions that have a relevant "on" and "off" part to them, it is recommended to subclass MidiAction and make a new model that reflects this behavior (store two midi messages).