The APC40 is a great controller, but it does basically one thing: launch clips. Hans Petrov decided to improve on this diminutive feature set by writing the APC_64-40 remote script in Python to add new control modes for the clip grid, faders, and encoders. When Live 9 came out, the closed-source API for these scripts changed, and Fabrizio Poce took over the project to keep it up-to-date with the latest changes. In January of 2014 he stopped maintaining the project, but it continues to be useful to many APC40 owners, as well as other writers of custom scripts.

The original script makes the controller much more useful for producing as well as performing by adding note trigger modes as well as step sequencer controls. However, once you make the move to the arrange view while producing a song, the controller is less than useful even with the new modes. However, I felt the hardware could still be helpful for mixing and arranging, because one feature I’ve always wanted from the APC 40 is live VU metering of channels on the clip grid. So, it’s my pleasure to introduce a new version: the APC_64-40_9 Remote Script (VU Meter edition):

Download and install

Download the remote script (63kb)View on Github

To install the script, just unzip the archive and copy the resulting “APC_64_40_9” folder to the Ableton Remote Scripts directory. On Windows, it should be at:
“C:\Program Files\Ableton\Live 8.x.x\Resources\MIDI Remote Scripts\”.

On Mac OS X, find the Ableton application file and right click -> “Show Package Contents”. You’ll find the Remote Script folder in
“Contents/App-Resources/MIDI Remote Scripts”.

Once the script is in place, launch Live and open the preferences window. In the “MIDI / Sync” tab, you’ll find a listing of your connected MIDI gear. Find your APC40, and in the left column, change the default selection to “APC 64 40 vu” as shown. Hold the shift button and press the various Track Selection buttons to switch modes. If the clip grid changes to show new layouts, it’s installed correctly.

Screen Shot 2015-04-19 at 1.49.29 AM

How it works

The basic idea behind remote scripts is simple enough: the Ableton application contains a folder called “Remote Scripts” that contains python files for mapping popular controllers to Ableton’s native features. Since python is a full programming language and not just a markup script, you can also create interactive modes and make the controls dynamic by writing a few classes and enabling them based on the control input. Hanz Petrov’s script already implements the shift-mode selection function, and I was able to get a head start by lifting a few functions from Will Marshall’s APCAdvanced script to add observers to the channel meters.

The main mode selection function (abridged) is below. It simply listens to the number corresponding to the button pushed, enables or disables the session view, and enables or disables the metering functions. When the 8th mode is selected, it creates a new instance of the VUMeters class, which contains the code to listen to the audio channels and outputs their signal to the button matrix.

def _set_modes(self):
  # Clip Launch
  if (self._mode_index == 0): 
      self._session_zoom._on_zoom_value(1) #zoom 

  # Session Overview
  elif (self._mode_index == 1): 
     self._session_zoom._is_zoomed_out = True


  # VU Meters
  elif (self._mode_index == 7):  

In the VUMeters class, we first gather all of the visible tracks (those not collapsed) into an array for ease of access. Then we iterate on that array (offset by current session view’s position on the screen) and add VUMeter objects to our list of meters until we have 8 meters (if the channel is audio and not MIDI). Then we use the native Live API function add_output_meter_left_listener to call back into the observe function of our VUMeter object with the audio level every time it updates.

class VUMeters(ControlSurfaceComponent):
 def observe(self, session_offset):

  self.master_meter = VUMeter(self, self.song().master_track)
  visible_tracks = []

  i = 0
  while i < len(self.song().tracks):
    track = self.song().tracks[i]
    if track.is_visible:
    i +=1

  for row_index in range(NUM_METERS):
    self._tracks[row_index] = visible_tracks[row_index + session_offset]

    if self._tracks[row_index].has_audio_output:
      self._meters[row_index] = VUMeter(self, self._tracks[row_index])

Finally, in the VUMeter class, we listen to the level reported by the listener function, calculate the root-mean-square (RMS) value of the signal based on a few frames of audio so we don’t unnecessarily overload the APC with update messages, and convert that value into a series of messages to the controller which turn the corresponding LEDs on and off.

class VUMeter():
  def observe(self):
    level = self.rms(self.frames)
    self.set_leds(self.matrix, level) 

  def rms(self, frames):
    return math.sqrt(sum(frame*frame for frame in frames)/len(frames))

  def set_leds(self, matrix, level):
    for index in range(6):
      button = matrix[index] 
      if index >= (6 - level): 
        if index < 1:
          button.send_value(LED_RED, True)
        elif index < 2:
          button.send_value(LED_ORANGE, True)
          button.send_value(LED_ON, True)
        button.send_value(LED_OFF, True)

(Other functions omitted here for clarity include some simple value scaling to convert the floating point volume value from Live’s API to an integer from 0-6 (because we have 6 lights to represent volume), calculating mean peaks on the master channel and lighting up all the buttons red to warn us of clipping, and utility functions to disconnect the listeners when the mode is switched back to session view or the channel offset is changed an the meters must be re-initialized.)


As you can see, while it’s not beginner-level coding to add additional features to the APC or other hardware – some knowledge of object-oriented programmimng is required, along with some knowledge about the hardware you’re using – neither is it really “hacking.” The API itself is quite accessible, and Hans Petrov has done fantastic job demistifying it on his Remote Script blog for interested users. I’m a complete amateur with Python (I mostly write javascript) and this project only took me a few evenings after work to implement and improve.

I’m delighted to be able to share this script with you, and I hope you have as much fun using it as I did writing it. Enjoy!


  • logicbomb.de says:

    Which version of Live has this been scripted for?

    I’m running Live suite x64 9.1.7 on windowsand it doesn’t seem to work

    placed the unzipped folder in C:\ProgramData\Ableton\Live 9 Suite\Resources\MIDI Remote Scripts

    any ideas? do I need Live 9.1.8?


    • Hey logicbomb,
      I’m running live 9.1.8 (32-bit) on Mac OS X, so I’m not sure what would be the issue. Do you see the “APC 64 40 vu” item in the dropdown in the MIDI menu? What happens when you select it? (you should see the APC lights briefly go off and then back on when the controls are re-enabled). Do any of the modes work?

      If not, you might try installing the original APC 60-40 script just to see if it works without modifications. You can get it from this thread:

      If that one does work and there’s something in my changes that causes the issue, I’ll probably need you to send the Log.txt file from the Ableton Preferences folder, which is in the same place as the Crash report files:

      • Jussi says:

        I had same problem. To fix it you need to change folder name APC_64_40_9-master —> APC_64_40_9_vu

        After that it works.

        • Foxbase says:

          I was gutted when I installed it and it never worked. This post nailed it for me – thanks man.

  • logicbomb.de says:

    heya matt, thanks for the quick reply. I still haven’t done the update for 9.1.8 and IIRC, the control scripts are almost always version specific. have you tried running your modified script in a version older than 9.1.8?

    and to answer your question, no – when I go to the MIDI section int he control panel to select the control surface I don’t see the option for APC 64 40 vu, the option I see is actually the name of the folder that I copied to the MIDI Remotes Scripts location.

    the control surface shows up in the list as “APC_64_40_9-master”

    when I select it, LIve will do its control surface refresh, but the APC just acts like it hasn’t been initialized. its sending raw note and CC data

    anyhow, thanks for your help, I’ll try updating to 9.1.8, I’m pretty sure that’s my issue

    thanks again!

    • dennis says:

      i have the same problem,it is solved already?
      im using also ableton live 9.1.8 64 bit

  • This is just the kick start I was looking for. I just discovered Will through Hanz, and you through how to implement the VU, as it would be a lovely aesthetic for my live sets. Thank you so much for sharing this, you’ve gotten a student re-interested in coding!

    • Awesome, glad to have piqued your interest! A few days after this was published, I saw that Evan Bogunia has published some new expository pieces on working with controllers in M4L and with MIDI remote scripts over on Keith McMillen’s blog. If you’re interested in the programming side, he gives a great barebones example that’s much easier to get your head around than Hanz’ full script.

  • nik says:

    Every time I switch to another track from track selection. The DEVICE ON/OFF button is off even if the effect (a filter in an Audio Effect Rack in this case) I have on the track is actually ON. Is there something I can do?

    I’m using Live 9.1.8

    Thanks in advance and for this awesome script!

  • Paul says:

    Great! can i do this on my APC mini?

Leave a Reply

Your email address will not be published.