APC40 Mkii Matrix Buttons

Strophe's icon

Hi,
I'm able to observe matrix buttons, change LED colors.
I need to bypass the fire clip function of the buttons I want to manage (sorry for my bad english..)
Thank's for you help !

Andy Maskell's icon

I think you need to provide more details of your setup. I presume that you are using the APC40 with Ableton Live. You will probably need to insert your Max patch between the two and use Max to filter out the required APC commands. How does the APC connect and send the commands - MIDI codes or OSC for example, via USB or network?

I've done something similar with my Beringer X-Touch and Extender modules to provide a switchable interface allowing the X-Touch to control both CuBase and a Behringer X-Mixer and switch seamlessly between the two. Rather than using the X-Touch's built-in protocols to control both systems with cut-down sets of functions, I have inserted my Max patch in the data flow and massively enhanced the functionality of the X-Touch units. It has taken a huge amount of code to capture and modify all the MIDI codes to/from the X-Touch so that the same desk can operate both systems and receive the appropriate feedback. I've also had to learn how to control the X-Mixer with OSC for some functions. But it can be done!

Strophe's icon

Hi Andy, thank you.
Yes I Use it on Live and max for live (we are on the max for live part of this forum ;) )
I use the APC as surface controller of ableton, I just need to bypass some matrix buttons to prevent fire clips, and use them in may max4live patch. So I can read their state, and light leds with the colors I choose
But they still fire clips in my live session.

Andy Maskell's icon

Ok. So you need to find a way to put Max between the two and filter out the clip launching commands but pass everything else through.

Are you using a Mac or PC? Is the APC using MIDI commands to launch the clips?

I had to use LoopMIDI to create virtual ports that I could connect my X-Touch units to and another set of LoopMIDI ports to connect to CuBase. I then created a filter/pass through patch connected to those LoopMIDI ports that use a variety of Max objects and processes to intercept the traffic in both directions and apply the filtering and/or tranformation required. Lots of midiselect, midiparse, route and gate objects did the trick.

In very schematic terms, this is what I did:

You will probably have to do something similar to insert Max between your APC and Ableton.

Strophe's icon

Thx for your experience but no. Actualy ableton use a script to manage the com between the soft and hardware and give a lot of function (I need)

so my question is about M4L and LOM specifics apc40 mkii’s script functions I don’t know and I can’t find.

Andy Maskell's icon

Sadly, I think that you are missing the point here.

I've had a look at the communication protocol document for the APC40 on the Akai web site. The APC is just a simple controller unit and like all similar controllers (and I've had 40 years experience using a whole raft of them) it communicates with the host software using MIDI messages. Yes, the software on the computer is doing all the clever stuff (and that's where all the "scripts" are) but the APC is simply communicating your inputs on the device using simple note on/off commands, MIDI control changes and system exclusive messages, like they all do. Likewise, the APC receives MIDI messages back to control things like the LED's, etc. I doubt very much that there is any (simple) way that you would be able to play around with what goes on at the Ableton end of things.

Specifically, pressing the clip launch buttons on the APC simply generates note on/off message pairs that would be very simple to intercept in Max. For all the other functionality you simply pass everything else through to Ableton. and likewise pass all the messages back from Ableton to the APC to control the LED's. All you need to do is to connect the MIDI ports of the APC to Max and the Max ports to Ableton and join the ports in Max with what would be very simple Max objects (midiin, midiout, sysexin, midiparse, midiselect, route, etc.)

I have had to use LoopMIDI simply because some MIDI drivers do not have the required flexibility to allow direct connections to "software" devices like Max. For example, neither CuBase nor the X-mixer software I use can "see" Max MIDI ports. LoopMIDI has been specifically written for this purpose by creating emulated "hard" ports for software to attach to as though they were physical sockets connected with virtual cables.

How you proceed is entirely up to you but I sincerely believe that this is far easier than you think!

Strophe's icon

Thx again, and I know very well to do all that stuf you described on both Mac and pc, but a lot of M4L devices do what I need without all that tricks. So I keep on digging..
waiting the solution , I use a workaround which is consist in midi assign (in ableton) those matrix buttons to software buttons in presentation mode. So they stop to trig clips..
thx again Andy

Greg Ross's icon

I think what your wanting to do is grab, get, release the control? If you can observe it you probably already have the id for the buttons, you need to send a message to the live.object that grabs the control then one that gets the control, I do that with a push and it does what I believe your trying to do. When you’re done you send the message to release the control and it behaves normally. Check the help or reference and it should tell you what functions to call.

Strophe's icon

Hi Greg, thx a lot.
Yes I know the ID of the buttons I want to use.
when you say grab the control, you mean for example light the LED on ?
And what is the need to send a message to the live.object who gets the control ? Actualy I use a live.observer to get the control.

And what I want more is to bypass his function to launch clips (and keep all the rest of the apc as it should do with Live)

Strophe's icon

OK !
I don't know if it's the right thing to do, but when I getinfo the live.object for those buttons, I have all properties and functions.
I make a call clear_value_listeners for each button I want to disconnect from the ableton script, and voilà !
I can observe and light leds without firing clips !

Greg Ross's icon

Awesome! Glad you got it working

Strophe's icon

Thx Greg, but please I don't undestand what mean grab_control, a function for each matrix button.. I'm searching over the entiere internet (so huge^^) but I don't find something to make me undestand.
You said grab, get, release the control..

Greg Ross's icon

You can use the grab/get messages to get control of any button or pad so that it no longer communicates with the script, then the release message will return it to normal. that way you can use it however you want or not at all. Im not sure about an APC40 but on a push each button is available separately in the script and the button matrix as a whole is also available depending on what your trying to do. Here's a quick example of what I've done, I'm definitely a beginner with Max using the LOM is what got me interested in it to begin with so this may be a bit messy.

{
    "boxes" : [         {
            "box" :             {
                "maxclass" : "comment",
                "text" : "Example of how i did it to get a button of a push2 to use for something else, the object get the control from the script the observer only listens to it.",
                "linecount" : 2,
                "presentation_linecount" : 2,
                "patching_rect" : [ 164.5, 616.5, 686.0, 29.0 ],
                "numinlets" : 1,
                "id" : "obj-25",
                "numoutlets" : 0,
                "textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "comment",
                "text" : "once you have the names of the controls you can grab_control then get_control so its no longer used in the ableton script, you can use it for something else or just ignore it if you dont want to repurpose it. when your done you release the control to return to normal function.",
                "linecount" : 2,
                "presentation_linecount" : 11,
                "patching_rect" : [ 136.5, 441.0, 686.0, 29.0 ],
                "numinlets" : 1,
                "id" : "obj-24",
                "numoutlets" : 0,
                "textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "newobj",
                "text" : "live.thisdevice",
                "patching_rect" : [ 502.25, 216.0, 77.0, 20.0 ],
                "numinlets" : 1,
                "id" : "obj-23",
                "numoutlets" : 3,
                "outlettype" : [ "bang", "int", "int" ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "comment",
                "text" : "click to get a list of functons and properties",
                "linecount" : 2,
                "presentation_linecount" : 2,
                "patching_rect" : [ 292.25, 237.0, 150.0, 29.0 ],
                "numinlets" : 1,
                "id" : "obj-22",
                "numoutlets" : 0,
                "textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "comment",
                "text" : "click to get a list of controls",
                "patching_rect" : [ 143.5, 320.0, 150.0, 18.0 ],
                "numinlets" : 1,
                "id" : "obj-21",
                "numoutlets" : 0,
                "textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "comment",
                "text" : "controll surface number depends on the order its listed in ableton, it starts at 0 at the top",
                "linecount" : 4,
                "patching_rect" : [ 645.0, 297.0, 150.0, 51.0 ],
                "numinlets" : 1,
                "id" : "obj-20",
                "numoutlets" : 0,
                "textcolor" : [ 1.0, 1.0, 1.0, 1.0 ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "message",
                "text" : "call get_control_names",
                "patching_rect" : [ 307.25, 319.0, 120.0, 20.0 ],
                "numinlets" : 2,
                "id" : "obj-18",
                "numoutlets" : 1,
                "outlettype" : [ "" ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "message",
                "text" : "getinfo",
                "patching_rect" : [ 405.0, 267.0, 42.0, 20.0 ],
                "numinlets" : 2,
                "id" : "obj-16",
                "numoutlets" : 1,
                "outlettype" : [ "" ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "newobj",
                "text" : "live.path control_surfaces 0",
                "patching_rect" : [ 502.0, 309.0, 141.0, 20.0 ],
                "numinlets" : 1,
                "id" : "obj-14",
                "numoutlets" : 3,
                "outlettype" : [ "", "", "" ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "newobj",
                "text" : "live.object",
                "patching_rect" : [ 464.0, 355.0, 57.0, 20.0 ],
                "numinlets" : 2,
                "id" : "obj-11",
                "numoutlets" : 1,
                "outlettype" : [ "" ],
                "saved_object_attributes" :                 {
                    "_persistence" : 1
                }

            }

        }
,         {
            "box" :             {
                "maxclass" : "newobj",
                "text" : "print",
                "patching_rect" : [ 464.0, 394.0, 31.0, 20.0 ],
                "numinlets" : 1,
                "id" : "obj-10",
                "numoutlets" : 0
            }

        }
,         {
            "box" :             {
                "maxclass" : "message",
                "text" : "getid",
                "patching_rect" : [ 502.0, 267.0, 32.0, 20.0 ],
                "numinlets" : 2,
                "id" : "obj-8",
                "numoutlets" : 1,
                "outlettype" : [ "" ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "newobj",
                "text" : "t b b b b",
                "patching_rect" : [ 116.75, 701.0, 50.5, 20.0 ],
                "numinlets" : 1,
                "id" : "obj-177",
                "numoutlets" : 4,
                "outlettype" : [ "bang", "bang", "bang", "bang" ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "message",
                "text" : "call send_value 29",
                "patching_rect" : [ 233.5, 832.0, 96.0, 20.0 ],
                "numinlets" : 2,
                "id" : "obj-158",
                "numoutlets" : 1,
                "outlettype" : [ "" ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "newobj",
                "text" : "live.object",
                "patching_rect" : [ 258.5, 865.0, 57.0, 20.0 ],
                "numinlets" : 2,
                "id" : "obj-150",
                "numoutlets" : 1,
                "outlettype" : [ "" ],
                "saved_object_attributes" :                 {
                    "_persistence" : 1
                }

            }

        }
,         {
            "box" :             {
                "maxclass" : "newobj",
                "text" : "route 0 1",
                "patching_rect" : [ 101.25, 664.0, 50.0, 20.0 ],
                "numinlets" : 3,
                "id" : "obj-146",
                "numoutlets" : 3,
                "outlettype" : [ "", "", "" ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "toggle",
                "patching_rect" : [ 101.25, 619.0, 24.0, 24.0 ],
                "numinlets" : 1,
                "id" : "obj-142",
                "numoutlets" : 1,
                "parameter_enable" : 0,
                "outlettype" : [ "int" ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "newobj",
                "text" : "r ---ID",
                "patching_rect" : [ 61.25, 746.0, 35.0, 20.0 ],
                "numinlets" : 0,
                "id" : "obj-140",
                "numoutlets" : 1,
                "outlettype" : [ "" ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "newobj",
                "text" : "s ---ID",
                "patching_rect" : [ 431.25, 814.0, 37.0, 20.0 ],
                "numinlets" : 1,
                "id" : "obj-139",
                "numoutlets" : 0
            }

        }
,         {
            "box" :             {
                "maxclass" : "newobj",
                "text" : "live.thisdevice",
                "patching_rect" : [ 431.25, 720.0, 77.0, 20.0 ],
                "numinlets" : 1,
                "id" : "obj-138",
                "numoutlets" : 3,
                "outlettype" : [ "bang", "int", "int" ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "message",
                "text" : "property value",
                "patching_rect" : [ 233.5, 793.0, 77.0, 20.0 ],
                "numinlets" : 2,
                "id" : "obj-137",
                "numoutlets" : 1,
                "outlettype" : [ "" ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "newobj",
                "text" : "route get_control",
                "patching_rect" : [ 84.75, 865.0, 91.0, 20.0 ],
                "numinlets" : 2,
                "id" : "obj-129",
                "numoutlets" : 2,
                "outlettype" : [ "", "" ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "message",
                "text" : "bang",
                "patching_rect" : [ 113.350006639957428, 966.5, 50.0, 20.0 ],
                "numinlets" : 2,
                "id" : "obj-124",
                "numoutlets" : 1,
                "outlettype" : [ "" ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "newobj",
                "text" : "live.observer",
                "patching_rect" : [ 144.350006639957428, 921.5, 70.0, 20.0 ],
                "numinlets" : 2,
                "id" : "obj-117",
                "numoutlets" : 2,
                "outlettype" : [ "", "" ],
                "saved_object_attributes" :                 {
                    "_persistence" : 1
                }

            }

        }
,         {
            "box" :             {
                "maxclass" : "message",
                "text" : "call release_control 0_Clip_7_Button",
                "patching_rect" : [ 228.5, 762.0, 184.0, 20.0 ],
                "numinlets" : 2,
                "id" : "obj-116",
                "numoutlets" : 1,
                "outlettype" : [ "" ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "message",
                "text" : "call get_control 0_Clip_7_Button",
                "patching_rect" : [ 228.5, 733.0, 164.0, 20.0 ],
                "numinlets" : 2,
                "id" : "obj-115",
                "numoutlets" : 1,
                "outlettype" : [ "" ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "message",
                "text" : "call grab_control 0_Clip_7_Button",
                "patching_rect" : [ 228.5, 706.0, 171.0, 20.0 ],
                "numinlets" : 2,
                "id" : "obj-114",
                "numoutlets" : 1,
                "outlettype" : [ "" ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "newobj",
                "text" : "live.object",
                "patching_rect" : [ 84.75, 832.0, 57.0, 20.0 ],
                "numinlets" : 2,
                "id" : "obj-108",
                "numoutlets" : 1,
                "outlettype" : [ "" ],
                "saved_object_attributes" :                 {
                    "_persistence" : 1
                }

            }

        }
,         {
            "box" :             {
                "maxclass" : "message",
                "text" : "getid",
                "patching_rect" : [ 431.25, 750.0, 50.0, 20.0 ],
                "numinlets" : 2,
                "id" : "obj-100",
                "numoutlets" : 1,
                "outlettype" : [ "" ]
            }

        }
,         {
            "box" :             {
                "maxclass" : "newobj",
                "text" : "live.path control_surfaces 0",
                "patching_rect" : [ 431.25, 778.0, 141.0, 20.0 ],
                "numinlets" : 1,
                "id" : "obj-90",
                "numoutlets" : 3,
                "outlettype" : [ "", "", "" ]
            }

        }
],
    "lines" : [         {
            "patchline" :             {
                "source" : [ "obj-23", 0 ],
                "destination" : [ "obj-8", 0 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-14", 0 ],
                "destination" : [ "obj-11", 1 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-18", 0 ],
                "destination" : [ "obj-11", 0 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-16", 0 ],
                "destination" : [ "obj-11", 0 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-11", 0 ],
                "destination" : [ "obj-10", 0 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-8", 0 ],
                "destination" : [ "obj-14", 0 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-100", 0 ],
                "destination" : [ "obj-90", 0 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-108", 0 ],
                "destination" : [ "obj-129", 0 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-114", 0 ],
                "destination" : [ "obj-108", 0 ],
                "midpoints" : [ 238.0, 778.5, 94.25, 778.5 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-115", 0 ],
                "destination" : [ "obj-108", 0 ],
                "midpoints" : [ 238.0, 792.0, 94.25, 792.0 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-116", 0 ],
                "destination" : [ "obj-108", 0 ],
                "midpoints" : [ 238.0, 806.5, 94.25, 806.5 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-117", 0 ],
                "destination" : [ "obj-124", 1 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-129", 0 ],
                "destination" : [ "obj-117", 1 ],
                "midpoints" : [ 94.25, 902.75, 204.850006639957428, 902.75 ],
                "order" : 1
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-137", 0 ],
                "destination" : [ "obj-117", 0 ],
                "midpoints" : [ 243.0, 900.25, 153.850006639957428, 900.25 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-138", 0 ],
                "destination" : [ "obj-100", 0 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-140", 0 ],
                "destination" : [ "obj-108", 1 ],
                "midpoints" : [ 70.75, 798.5, 132.25, 798.5 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-142", 0 ],
                "destination" : [ "obj-146", 0 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-146", 0 ],
                "destination" : [ "obj-116", 0 ],
                "midpoints" : [ 110.75, 758.0, 238.0, 758.0 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-146", 1 ],
                "destination" : [ "obj-177", 0 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-177", 3 ],
                "destination" : [ "obj-114", 0 ],
                "midpoints" : [ 157.75, 770.0, 191.875, 770.0, 191.875, 695.0, 238.0, 695.0 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-177", 2 ],
                "destination" : [ "obj-115", 0 ],
                "midpoints" : [ 147.25, 770.0, 192.625, 770.0, 192.625, 722.0, 238.0, 722.0 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-177", 1 ],
                "destination" : [ "obj-137", 0 ],
                "midpoints" : [ 136.75, 793.5, 243.0, 793.5 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-90", 0 ],
                "destination" : [ "obj-139", 0 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-158", 0 ],
                "destination" : [ "obj-150", 0 ],
                "midpoints" : [ 243.0, 858.0, 268.0, 858.0 ]
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-129", 0 ],
                "destination" : [ "obj-150", 1 ],
                "midpoints" : [ 94.25, 895.0, 200.125, 895.0, 200.125, 854.0, 306.0, 854.0 ],
                "order" : 0
            }

        }
,         {
            "patchline" :             {
                "source" : [ "obj-177", 0 ],
                "destination" : [ "obj-158", 0 ],
                "midpoints" : [ 126.25, 821.0, 243.0, 821.0 ]
            }

        }
],
    "appversion" :     {
        "major" : 8,
        "minor" : 2,
        "revision" : 2,
        "architecture" : "x64",
        "modernui" : 1
    }
,
    "classnamespace" : "box"
}

Strophe's icon

OMG thank you so much Greg ! it's exactly what I need !!
now I undestand fully this grab get release thing !
I didn't realised that we must add the control_name after grab or get control.. I tried with ID in live.object
thanks a lot you saved my day ;)

Greg Ross's icon

Awesome glad I could help!

Andy Maskell's icon

Great. I'm glad you found the solution!

Randall Packer's icon

Greg, I just tried your approach and it works great for a round-trip send/receive between my Faderfox EC4 midi controller and max for live. Brilliant!!

Greg Ross's icon

Awesome!