Found a way to use timers/animation with Ableton
Recently learned about threading in python, which is a way to have multiple different functions run at the same time.
Without threading, functions would be run one after the other, which means the next function in line needs to wait until the current one is finished.
If, for example, your current function has a sleep_timer set to 10 seconds, then it would take 10 seconds before the next function in line is called.
Because of this, we can’t simply use a timer in our Reactions because it would jam up Ableton until the timer has finished.
With threading however, the function with the sleep_timer could be counting its 10 seconds away while a second function has already fired up.
How to initiate a thread
The following image shows the basics:

When the thread is started, it will run whatever code is inside myFunction.
Notice how myFunction is inserted in the Thread using the keyword argument target.
However, you might want the code in myFunction to be in a loop. How would you exit the loop?
When using your code inside a Reaction, you can use Modifiers to carry the on/off switch:

Example
I’ve added a Reaction to this post with an example. It’s made for MIDI Fighter Twister with a momentary switch, although you could use any controller, as long as you don’t forget to adjust the condition, which checks if the button you’re using as a Listener has a value of 127.
This Reaction uses the following code:

As you can see I made 2 functions:
- lower_volume
- Lowers the master volume by 0.01 every 0.1s when a thread has been activated
- toggle_volume_lowering
- This is the function that is called by the Reaction
- When a thread is already active, it stops that thread
- When no thread is active, it creates and activates a thread that runs the lower_volume function
Post-scriptum
I was also able to make the LED’s on my MFT animate in a pattern (continuously changing colors of the inner and outer buttons of the device) while still being able to use Ableton.
Yes, I think it’s possible. I made flashing LED’s before using this method. Handling the flash and shine like you’re asking shouldn’t be too difficult. I’m finishing up on something else first, then I’ll look into this.
Hi Makill, I’ll post my progress on your request in an answer here. This comment is meant as a notification.
Hi Makill01
The updated user.py can be found here. I’ve also added pre-made Reactions for all of the top row buttons on the MIDIMIX that you can import. It also contains 3 mappings for setting up a Session Box and moving it left and right. I left them in so you could see how the Reactions work with the Session Box, but you may remove those Mappings, they aren’t vital to the Solo buttons.
On my end it seemed to work well. Let me know if you encounter any problems.
1. Little explanation how to call and use the function
I tried to keep the function of the previous function as much the same as it was. The LED functionality can be used on its own. I just added a way for it to trigger another function, which I’ve called an “action” in the parameters of the function. So I also added a separate function, called `MIDIMIX_toggle_solo`, that handles triggering the solo button.
Here’s an example of how the function is called in a Reaction:
self.user.toggle_delayedSwitchLED(0, 1, action=self.user.MIDIMIX_toggle_solo, action_args=(0))
- The first 2 parameters (the 0 and 1) represent the channel and value of the button who’s LED we want to trigger. Channel and value can be found by hovering over the button in the Template. Important: you’ll need to subtract 1 from the channel that’s seen in the Template. Channels in the template start at 1 but in the code channels start at 0.
- The 3rd action parameter needs to call the function that will toggle the solo button. The function is part of user.py and thus needs to be called as
self.user.MIDIMIX_toggle_solo. MIDIMIX_toggle_soloneeds itself 1 parameter, the number of the track we want to manipulate (relative a Session Box, if one’s present). This is done viaaction_args, i.e. the arguments for the action, to which in this example I passed (0). The parentheses aren’t really necessary if there’s only 1 parameter. It’s also possible to pass keyword arguments to the action by passing a dictionary to action_kwargs.MIDIMIX_toggle_solodoesn’t need kwargs, I’m just mentioning it for if someone wants to use this function with a different action.
2. Important for anyone else wanting to use this function
If anyone else wants to use this function, there’s one important keyword argument that isn’t visible in the example: button_type. By default, button_type=”note” because this function was initially built to use with an AKAI MIDIMIX of which the buttons send NOTE messages. But on a lot of other MIDI Controllers, buttons send CC values. If that’s the case, then you need to add the parameter button_type=”cc”.
It’s important when you’re passing a channel and value to the function because the function then has to build the structure of the object that points to the button inside the main script which looks like this: midi_{button_type}_ch_{channel_number}_val_{value_number}. Examples using channel 0 with value 1:
- In case of a NOTE message: midi_note_ch_0_val_1
- In case of a CC message: midi_cc_ch_0_val_1
3. Another way to input a button to the delayedSwitchLED function:
Instead of inputting the channel and value, where you need to keep the button_type in mind, you can also deliver the entire button_string to the function. With button_string I mean (example) midi_note_ch_0_val_1 or midi_cc_ch_0_val_1. You can easily find this button_string by temporarily making a Condition in a Reaction wherein the button you need is selected. The button_string will then be visible under the Condition. Here’s the alternative version of how the above example would be called this way:
self.user.toggle_delayedSwitchLED("midi_note_ch_0_val_1", action=self.user.MIDIMIX_toggle_solo, action_args=(0))
As you can see, the button_string replaces the first 2 parameters of the previous example. It’s important to put this button_string inside quotes. There’s no need to signify a button_type because the button_string already contains the type.
Amazing work, thanks a lot. Just what I’ve been looking for.
Sign up
User registration is currently not allowed.
Would you be able to make flashing led function that could be incorporated into your user.py file and used along side of timer so that it could be used to make buttons behave like delayed switches that flash when toggled and shine when held?
been really interested in your code, so i started doing some changes so that I could use it as delayed on/off switch and figured id be nice if my buttons blinked as well depending on their function.