method pushcontextframe/popcontextframe (m4l)

    Dec 04 2013 | 1:10 am
    Hi fellows, I'm having these two messages in the Max Window. Have you ever seen them?
    "method pushcontextframe called on invalid object" "method popcontextframe called on invalid object"
    This is the simple code (inside M4L):
    inlets = 1; outlets = 1;
    var paramValue = new Array();
    root = new LiveAPI(param_callback);
    function setup() { root.path = "live_set view"; = "selected_parameter";
    function param_callback(args) { if(args[2] != 0) { //filter Id 0 paramValue[0] = args[1]; paramValue[1] = args[2]; value = new LiveAPI(paramValue); outlet(0, value.get("max")); } }

    • Dec 04 2013 | 8:04 am
      Hey Kevinripper,
      I got the same error and talked to ableton support about it. They couldn't give me any answers as to why it happens. I did ask if I should just ignore it (since it doesnt seem to cause any significant error) and they said, it probably should be ignored.
    • Dec 04 2013 | 4:35 pm
      the callback is called each time selected_parameter property changes. wouldn't it be a problem of thread-like interference ?
    • Dec 05 2013 | 2:02 pm
      Thanks @newtfish!
      @Julien, I'm not following you on this one. The code is very very simple, you now it, just get the max value of the parameter selected. I don't know why these messages appear 'cause if I code another function to get the max value they don't appear... but I would have to call two different functions and I want this all automated. Achieving this with max objects is nothing really I mean (path live_set view selected_parameter) -> [live.path] -> [deferlow] -> [t b l] -> (get max) -> [live.object] but I want to build everything in js now...and although my code works I find annoying to see those messages in the Max Window.
    • Dec 05 2013 | 2:54 pm
      Hi, never use that form of LiveAPI, always pass a path in, try:
      root = new LiveAPI( paramcallback, "live_set selected_parameter" );
      you're 2nd call to LiveAPI is not valid as the first parameter is always a callback and you've passed it an array.
      you probably want something like
      control = new LiveAPI( nullcallback, "id " + args[ 0 ] ); max = control.get( "max" );
      I can have a better look when I get home, but this is the gist of it...
    • Dec 05 2013 | 2:57 pm
      ultimately, you are probably seeing those messages as it thinks it can call those methods on "paramValue" which it expecting to be a function, but it's not, it's an array
    • Dec 05 2013 | 3:08 pm
      @Julien, js code is all single threaded so there are no threading concerns...
    • Dec 05 2013 | 3:52 pm
      @LEE, the array I'm passing it's a "valid id" (the id of the parameter I'm selecting) and in the max window the message "invalid path" is not appearing so my guess is that is working just fine. I test your code and it's not working :S
    • Dec 05 2013 | 3:56 pm
      i'm at work, i can't try it - was just trying to get the idea across... i have to try later
    • Dec 05 2013 | 3:58 pm
      No worries, it's nothing urgent. Thanks in advance!
    • Dec 05 2013 | 5:28 pm
      Apparently there is a strange behavior when calling the LiveAPI constructor in a callback.
      The solution by Andrew Pask:
      inlets = 1; outlets = 1;
      root = new LiveAPI(param_callback);
      var value = new LiveAPI();
      function setup() { root.path = "live_set view"; = "selected_parameter"; }
      function param_callback(args) { if(args[2] != 0) { //filter Id 0 = args[2]; outlet(0, value.get("max")); } }
    • Dec 05 2013 | 5:57 pm
      Here a code to observe the current value and the max value of the selected parameter:
      inlets = 1; outlets = 2;
      var root = new LiveAPI(param_callback); var value = new LiveAPI(value_callback);
      function setup() { root.path = "live_set view"; = "selected_parameter"; }
      function param_callback(args){ if(args[2] != 0) { = args[2]; = ("value"); } }
      function value_callback(vals){ outlet(0, value.get("value")); outlet(1, value.get("max")); }
    • Dec 06 2013 | 6:41 pm
      ive not had chance to look in this in detail yet (sorry), but I've just fired up my m4l abstraction and it spews these messages all over the place - this is new, it never used to... this has only started happening since 9.1 (i have to check if it was in 9.1 beta), but it didn't happen to me in 9.0...
      i'll look into it more tomorrow when I get some time...
    • Dec 06 2013 | 7:06 pm
      The short answer is don't put LiveAPI constructors inside your callback functions. That's what's causing the error in this case. We have a ticket for investigating it.
    • Dec 07 2013 | 3:29 pm
      ok, thanks Andrew.
    • Feb 18 2014 | 1:33 pm
      ive been learning javascript and found that I needed to send a message out of a js outlet into a deferlow object then that would trigger the Bang() in the javascript. not tried the code above but that's my solution that works for me.
    • Mar 14 2014 | 5:38 pm
      Given that I'm not supposed to call LiveAPI constructors in callbacks, does anyone have a way to
      1. Observe track changes, (i.e. the live_set property 'tracks') 2. Populate a list of track names in response to changes (i.e. iterating through live_set.get('tracks') which returns an array of track ids)
      without throwing this pushcontextframe error?
      Any help much appreciated!
    • Mar 15 2014 | 11:50 am
      I'm wondering this too... Andrew, as this used to be ok and you indicated you are investigating, does this imply something has been changed and you are investigating a way to make this work again in the old way?
      e.g. when a new clip is added and I want to monitor properties I now have to send a message out of an outlet, defer it, and then back in to monitor the new properties which is alot more hassle than just creating a new LiveAPI object which we used to be able to do...
    • Mar 17 2014 | 3:08 pm
      Adding constructors in callbacks has never been officially supported. I have no further news on this issue ATM
    • Mar 17 2014 | 6:15 pm
      ok, shame - it does complicate dealing with this situation somewhat...
    • Mar 17 2014 | 8:09 pm
      ok, may I please have a small code example of this going wrong to support?
    • Mar 17 2014 | 9:41 pm
      ok never mind, I have one here.
      Can you guys verify that the error seems harmless? I see my LiveAPI code still working right, despite the deluge
    • Mar 24 2014 | 2:19 pm
      I'm seeing this exact error and so far it seems harmless.
    • Mar 24 2014 | 5:27 pm
      it is harmless in one way in the fact that stuff appears to work fine - however, it sends lots of stuff to the MAX window - as more stuff goes to the MAX window, it starts to slow down... once it gets to 10000 rows you'll start getting status lines appearing in the devices - Also, if there is any useful information sent to the window, it is hard to track down as it's surrounded by noise
      so, more of an annoyance in the short term, but one that ultimately needs to be dealt with by the coder (whereas if the behaviour is not a problem then it would be better if the message were not generated)
    • Nov 26 2014 | 4:28 am
      I may have found a different workaround if you want to see if it works for you. Just to clear a couple things up first, the first one reiterating that the 'push/popcontextframe error' comes up when you're creating new LiveAPIs in a callback.
      So what I ended up doing was creating a new function for what I wanted to do (create more new LiveAPI's). Regardless of if it's a function outside the scope of the original containing the callback, you'll still get that push/pop error, but if you call that function using a Task
      with a little bit of delay (I'm fine with 10msm haven't checked less), then I stop getting the errors. This also works for that other ol' famous error when too much is being asked of the LiveAPI all at once (which is actually what made me think of trying this.
      So something like:
      autowatch = 1;
      outlets = 2;
      var LiveObj = {}, trackArr = [], getTest = new Task(getRest, this);
      function trackVol() {
      	var liveSet = new LiveAPI(getTracks);
      	liveSet.path = 'live_set'; = 'tracks';
      	function getTracks(args) {
      		if (args[0] == 'tracks') {
      			trackArr = [];
      			for (var i = 0; i < args.length; i += 2)
      		trackArr.splice(0, 1);
      function getRest() {
      	var mixApi,
      	mixArr = [],
      	volArr = [];
      	LiveObj = {};
      	for (var j = 0; j < trackArr.length; j++) {
      		mixApi = new LiveAPI('live_set tracks ' + j + ' mixer_device');
      		getVol = mixApi.get('volume');
      		mixArr[j] = getVol[1];
      		volApi = new LiveAPI('id ' + mixArr[j]);
      		vol = volApi.get('value');
      		LiveObj['track' + j] = {
      			'id' : trackArr[j],
      			'mixer' : mixArr[j],
      			'vol' : volArr[j]
      	outlet(1, LiveObj.toSource());
    • Dec 11 2014 | 8:31 pm
      another approach might be this: - function 'X' contains the usage of LiveAPI constructors - function 'Y' gets called when a LiveAPI property changes - function 'Y' then calls 'outlet(0,"x")' ...and outlet 0 is connected, via a deferlow object, to the js inlet!
      So function 'Y' calls function 'X' with a deferlow in between. thats how I solved this issue for myself...
    • May 10 2015 | 7:35 am
      Andrew, I am also seeing this warning when creating LiveAPI objects in LiveAPI callbacks. I am not seeing any behavioral side effects when the warning is given and it seems like it could be hidden. It does make debugging difficult. However, if calling the constructor isn't supported from callbacks, maybe hiding the current stack warning and adding an appropriate warning as you might do for calls becoming obsolete in the future?
      Anyway, just thoughts. Thanks so much!
    • Dec 23 2015 | 11:10 pm
      Just chiming in that this is still an issue in 7.1
    • May 11 2016 | 10:36 pm
      Hi, I am just joining the thread. Here is a simple example of something that I think you should be able to do. Each time the playing_slot_index of a track changes I think we should be able tot set up an observer for that clip.
      This shows the general premise.:
      function callback (args) {
      	var playingSlotOberserver = new LiveAPI(clipCallback, 'live_set tracks 0 clip_slots ' + args[1] + 'clip');
      function clipCallback (args) {
      	post('The color is ' + args[1]);
      var trackObserver = new LiveAPI(callback, 'live_set tracks 0'); = 'playing_slot_index';
    • May 11 2016 | 10:37 pm
      If you can not do that, how are we able to observe a dynamically changing path? The other alternative seems to be to set up a callback for every clip. Is there a better way?