No internet connection
  1. Home
  2. How to
  3. Ableton Live

ableton toggle active track states

By Micha @Micha
    2025-09-22 10:45:33.087Z

    Title

    ableton toggle active track states

    What do you expect to happen when you run the script/macro?

    toggle track active buttons on 2 tracks in ableton project

    Are you seeing an error?

    system argument out of range exception. unsupported expression (parameter: expression)

    What happens when you run this script?

    error message

    How were you running this script?

    I used a Stream Deck button

    How important is this issue to you?

    5

    Details

    {
        "inputExpected": "toggle track active buttons on 2 tracks in ableton project",
        "inputIsError": true,
        "inputError": "system argument out of range exception. unsupported expression (parameter: expression)",
        "inputWhatHappens": "error message",
        "inputHowRun": {
            "key": "-MpfwmPg-2Sb-HxHQAff",
            "title": "I used a Stream Deck button"
        },
        "inputImportance": 5,
        "inputTitle": "ableton toggle active track states"
    }

    Source

    (async () => {
      try {
        // Get current Live set
        const set = await sf.abletonLive.getCurrentSet();
        const tracks = set.tracks;
    
        // EDIT THESE NAMES EXACTLY to match your Ableton track names
        const nameA = "Nyx Bass Guitar Guide";
        const nameB = "Nyx Bass Guitar Live";
    
        const tA = tracks.find(t => t.name === nameA);
        const tB = tracks.find(t => t.name === nameB);
    
        if (!tA || !tB) {
          const found = tracks.map(t => t.name).slice(0,40).join(", ");
          sf.ui.showToast(`Tracks not found. First tracks: ${found}`);
          sf.log("Tracks present:", tracks.map(t => t.name));
          return;
        }
    
        // Toggle their 'isActive' states
        await tA.set("isActive", !tA.isActive);
        await tB.set("isActive", !tB.isActive);
    
        sf.ui.showToast(`Toggled: ${tA.name} / ${tB.name}`);
      } catch (err) {
        sf.ui.showToast("Error: " + (err.message || err));
        sf.log(err);
      }
    })();
    
    

    Links

    User UID: 90VwGojZF3hvy2smqFsCCR3UQhl2

    Feedback Key: sffeedback:90VwGojZF3hvy2smqFsCCR3UQhl2:-O_l0q0Q-RMUPvcIWqX8

    Feedback ZIP: XmqrTSepaJYgDllZSh2YcPS28QZZZirR5JkEoVuis/5o53KTsJeriyy4dwPS5Dh7BHRycjqRy819Uw3Lts+VC2kqaD0FH50SXmEnoYYp7r7ncoG4GoR0q/3eP63C3LOwQHJwSNNNYt4kdTL/x2wQ+wEeTb//sslzl6P0eR8T2SMOHVEBdjY7tZH626O57eIPP18iBfYV4Dm/dPopE50z2ssllUBtS4S/VWQNN2Tr7svQX7CYe7aTUY456lavt7e80gXN4IGz/9fulCWJmzqcG7UXLT88aT3Xk1CAGsoESpERI2nAFIM17f7JseAYDDeDKXf1wR9Bkm5z4O8Not2seg==

    Solved in post #2, click to view
    • 7 replies
    1. Chad Wahlbrink @Chad2025-09-24 01:22:24.729Z

      Hi, @Micha,

      Thanks for the question! This is a great use case for using SoundFlow with Ableton.

      The code you shared is generating errors because it uses elements that don't exist in the SoundFlow API. In the SoundFlow Editor, you'll notice that the script has some red underlines:

      These underlined sections are bits of code that can't compile because they don't exist within SoundFlow's API.

      I'm going to assume this likely came from an AI tool, which is totally okay. This is a common reason for code not executing in SoundFlow.

      ChatGPT or other AI tools are great at coding JavaScript, AppleScript, and Shell scripts, but these tools often don't fully understand SoundFlow, and thus, AI can struggle to produce accurate code.

      No worries, though. Here's a quick video showing where I ended up:

      https://www.loom.com/share/60e6297200fc417dabea5a1a655e4a02

      And here is the code that is working on my system for toggling two tracks active state in Ableton:

      
      // Bail out if Ableton is not running
      if (!sf.ui.abletonLive.isRunning) throw `Ableton Live is not running`;
      
      // Define the Track Names
      const nameA = "Nyx Bass Guitar Guide";
      const nameB = "Nyx Bass Guitar Live";
      
      // Store the tracks in the current set.
      let tracks = sf.app.abletonLive.song.tracks.invalidate();
      
      // Get the track objects
      let trackA = tracks.find(track => track.name.stringValue === nameA);
      let trackB = tracks.find(track => track.name.stringValue === nameB);
      
      // Set the Mute States to the Opposite for Each Track
      trackA.mute.setValue({ value: !trackA.mute.boolValue })
      trackB.mute.setValue({ value: !trackB.mute.boolValue })
      

      If you have any trouble getting this to run, let me know. Note that you will need to have the SoundFlow Control Surface assigned in your Link, Tempo & MIDI settings for this script to work. See this article for more detail:

      https://soundflow.org/docs/getting-started/ableton-live#installing-the-ableton-live-integration

      Reply1 LikeSolution
      1. M
        In reply toMicha:
        Micha @Micha
          2025-09-26 11:28:30.742Z

          Hey Chad,

          Thank you so much for your help on this! I have managed to take the code ever further by getting the value of the first track & applying some logic that makes sure the other track is always in the opposite state. Here is the code if anyone finds it useful:

          // Bail out if Ableton is not running 
          if (!sf.ui.abletonLive.isRunning) throw `Ableton Live is not running`;
          
          // Define the Track Names
          const nameA = "Nyx Bass Guitar Guide"; 
          const nameB = "Nyx Bass Guitar Live";
          
          // Get all tracks
          let tracks = sf.app.abletonLive.song.tracks.invalidate();
          
          // Find the track objects
          let trackA = tracks.find(track => track.name.stringValue === nameA);
          let trackB = tracks.find(track => track.name.stringValue === nameB);
          
          if (!trackA || !trackB) throw "Could not find one or both tracks";
          
          // Read current state of Track A
          const aCurrent = trackA.mute.boolValue;
          
          // Set Track B to match Track A’s current state
          trackB.mute.setValue({ value: aCurrent });
          
          // Toggle Track A
          trackA.mute.setValue({ value: !aCurrent });
          
          1. M
            In reply toMicha:
            Micha @Micha
              2025-09-26 11:32:28.379Z2025-09-26 11:56:02.559Z

              Additonal to this, I read in the forum that it's still not possible to change the colour of the button based on the value of the mute button. I really I'd like the track button to go red or some other colour to show when the live input track is active or green when the guide track is playing. This application is for a live band project where there are recorded guide tracks - so for example if I need my bass guitar guide to carry on playing for me while I check on something & then to be able to quickly press the button again and continue playing when done. Are there any visual options possible at all - eg text colour change, icon change, or any other kind of visual identification on the buttons?

              1. Chad Wahlbrink @Chad2025-10-15 20:57:22.645Z

                Hi, @Micha,

                Currently, dynamic button states are not supported for the deck editor. You can read more about the reasons we have yet to implement this from Christian here:

                There are some semi-dynamic options for SoundFlow, like the Generic Button Commands - but this wouldn't exactly satisfy what you are after.

                That said, I will note this down as an idea for future implementation in the official Ableton Live Package, as I do think it would be possible to implement this functionality from the developer side.

                I'll follow up with you here if we do implement this in any way.

              2. M
                In reply toMicha:
                Micha @Micha
                  2025-09-26 11:49:30.389Z

                  Additionally, I wanted to create a second row of buttons that just mute / unmutes the guide recording - thats for say the odd occasion if I wanted the guide recording to play as well as the live input track being active so I can check how I am supposed to be playing a part & try play along. For this I just copied the code from above & removed the second track from the script. It does work but just wondering if the code can be simplified - or if this is fine? Does more lines of code mean a button takes longer to action the script? If not then I don't think it matters that much - because as I say, it is working.

                  Here is the code for the mute / unmute button:

                  // Bail out if Ableton is not running 
                  if (!sf.ui.abletonLive.isRunning) throw `Ableton Live is not running`;
                  
                  // Define the Track Names
                  const nameA = "Crow Vox Guide";
                  
                  
                  // Store the tracks in the current set. 
                  let tracks = sf.app.abletonLive.song.tracks.invalidate();
                  
                  // Get the track objects 
                  let trackA = tracks.find(track => track.name.stringValue === nameA);
                  
                  
                  // Set the Mute States to the Opposite for Each Track
                  trackA.mute.setValue({ value: !trackA.mute.boolValue })
                  
                  
                  1. Chad Wahlbrink @Chad2025-10-15 21:18:39.241Z

                    The script you shared is perfect in this scenario!

                    The only way to make it "faster" would be to remove the invalidate() call, as shown in the code below. Invalidation essentially refreshes the "cache" of tracks in the session. You technically only need to do this once, whenever you're adding or removing tracks from the session, to ensure the new track is cached.

                    Lengthier discussion on this here:
                    When to use invalidate() #post-2

                    Example without invalidation:

                    // Bail out if Ableton is not running 
                    if (!sf.ui.abletonLive.isRunning) throw `Ableton Live is not running`;
                    
                    // Define the Track Names
                    const nameA = "Crow Vox Guide";
                    
                    // Store the tracks in the current set - .invalidate() removed
                    let tracks = sf.app.abletonLive.song.tracks;
                    
                    // Get the track objects 
                    let trackA = tracks.find(track => track.name.stringValue === nameA);
                    
                    // Set the Mute States to the Opposite for Each Track
                    trackA.mute.setValue({ value: !trackA.mute.boolValue })
                    
                  2. S
                    In reply toMicha:
                    SoundFlow Bot @soundflowbot
                      2025-10-15 20:57:31.312Z

                      This issue is now tracked internally by SoundFlow as SF-3026