Detecting "is_recording" of Clip Slots - Max for Live


    Jan 14 2012 | 1:14 am
    Hello All,
    I'm having a problem with a Max for Live patch I'm working on. I'm trying to detect when a user begins recording a clip and when they stop recording. I've included a procedure on how to show the problem I'm having in the patch that I've attached.
    Debugging procedure: - load device on any track in Ableton Live - start recording in the first clip slot ('clip slot 0') - click 'path this_device" while recording - watch status box change to indicate recording is taking place - stop clip - watch status box change to indicate recording has completed - delete clip - record new clip - note status box does not change now when recording. - ..!?
    According to the LOM, I should be able to observe this property. I'm not sure where I'm going wrong. Any help would be greatly appreciated.
    Thanks Mike

    • Jan 14 2012 | 1:58 pm
      When deleting the clip the previous path calculation (ID assignment) becomes invalid. So I think for observing a new clip you may need to click 'path this_device' again.
    • Mar 16 2017 | 11:46 am
      Hi Guys,
      I update this thread because it's kind of a continuation, but with the js point of view. I setup an observer in a js object, but I don't understand why it doesn't react as the same action programmed with max object... . With the max code provided on the first post of this thread, the observer "bang" a 1 message when the record starts in the clip slot, and a 0 message when the record stops. Why does my js object doesn't post a message in the max window when the record starts and stops ?
      Many thanks for your feedback.
      { "boxes" : [ { "box" : { "maxclass" : "newobj", "text" : "s status", "numoutlets" : 0, "style" : "", "patching_rect" : [ 286.0, 201.0, 51.0, 20.0 ], "numinlets" : 1, "fontsize" : 10.0, "id" : "obj-20", "fontname" : "Arial Bold" }
      } , { "box" : { "maxclass" : "button", "numoutlets" : 1, "outlettype" : [ "bang" ], "style" : "", "patching_rect" : [ 245.0, 198.0, 20.0, 20.0 ], "numinlets" : 1, "id" : "obj-23" }
      } , { "box" : { "maxclass" : "number", "parameter_enable" : 0, "numoutlets" : 2, "outlettype" : [ "", "bang" ], "style" : "", "patching_rect" : [ 245.0, 165.0, 50.0, 20.0 ], "numinlets" : 1, "fontsize" : 10.0, "id" : "obj-27", "fontname" : "Arial Bold" }
      } , { "box" : { "maxclass" : "message", "text" : "property is_recording", "numoutlets" : 1, "outlettype" : [ "" ], "style" : "", "patching_rect" : [ 245.0, 125.0, 114.0, 20.0 ], "numinlets" : 2, "fontsize" : 10.0, "id" : "obj-28", "fontname" : "Arial Bold" }
      } , { "box" : { "maxclass" : "newobj", "text" : "live.observer", "numoutlets" : 2, "outlettype" : [ "", "" ], "style" : "", "patching_rect" : [ 245.0, 144.0, 148.0, 20.0 ], "numinlets" : 2, "fontsize" : 10.0, "id" : "obj-30", "fontname" : "Arial Bold", "saved_object_attributes" : { "_persistence" : 1 }
      }
      } , { "box" : { "maxclass" : "newobj", "text" : "t b l", "numoutlets" : 2, "outlettype" : [ "bang", "" ], "style" : "", "patching_rect" : [ 245.0, 104.0, 147.5, 20.0 ], "numinlets" : 1, "fontsize" : 10.0, "id" : "obj-31", "fontname" : "Arial Bold" }
      } , { "box" : { "maxclass" : "message", "text" : "path live_set tracks 7 clip_slots 0 clip", "numoutlets" : 1, "outlettype" : [ "" ], "style" : "", "patching_rect" : [ 245.0, 25.0, 196.0, 20.0 ], "numinlets" : 2, "fontsize" : 10.0, "id" : "obj-14", "fontname" : "Arial Bold" }
      } , { "box" : { "maxclass" : "newobj", "text" : "live.path", "numoutlets" : 3, "outlettype" : [ "", "", "" ], "style" : "", "patching_rect" : [ 245.0, 59.0, 51.0, 20.0 ], "numinlets" : 1, "fontsize" : 10.0, "id" : "obj-13", "fontname" : "Arial Bold" }
      } , { "box" : { "maxclass" : "button", "numoutlets" : 1, "outlettype" : [ "bang" ], "style" : "", "patching_rect" : [ 49.0, 34.0, 24.0, 24.0 ], "numinlets" : 1, "id" : "obj-52" }
      } , { "box" : { "maxclass" : "newobj", "text" : "js clipobstest.js", "numoutlets" : 2, "outlettype" : [ "", "" ], "style" : "", "patching_rect" : [ 49.0, 77.0, 91.0, 22.0 ], "numinlets" : 2, "id" : "obj-51", "saved_object_attributes" : { "filename" : "clipobstest.js", "parameter_enable" : 0 }
      }
      } ], "lines" : [ { "patchline" : { "source" : [ "obj-14", 0 ], "destination" : [ "obj-13", 0 ], "hidden" : 0, "disabled" : 0 }
      } , { "patchline" : { "source" : [ "obj-27", 0 ], "destination" : [ "obj-20", 0 ], "hidden" : 0, "midpoints" : [ 254.5, 188.0, 295.5, 188.0 ], "disabled" : 0 }
      } , { "patchline" : { "source" : [ "obj-27", 0 ], "destination" : [ "obj-23", 0 ], "hidden" : 0, "disabled" : 0 }
      } , { "patchline" : { "source" : [ "obj-31", 1 ], "destination" : [ "obj-30", 1 ], "hidden" : 0, "disabled" : 0 }
      } , { "patchline" : { "source" : [ "obj-30", 0 ], "destination" : [ "obj-27", 0 ], "hidden" : 0, "disabled" : 0 }
      } , { "patchline" : { "source" : [ "obj-28", 0 ], "destination" : [ "obj-30", 0 ], "hidden" : 0, "disabled" : 0 }
      } , { "patchline" : { "source" : [ "obj-31", 0 ], "destination" : [ "obj-28", 0 ], "hidden" : 0, "disabled" : 0 }
      } , { "patchline" : { "source" : [ "obj-13", 1 ], "destination" : [ "obj-31", 0 ], "hidden" : 0, "disabled" : 0 }
      } , { "patchline" : { "source" : [ "obj-52", 0 ], "destination" : [ "obj-51", 0 ], "hidden" : 0, "disabled" : 0 }
      } ], "appversion" : { "major" : 7, "minor" : 3, "revision" : 1, "architecture" : "x64", "modernui" : 1 }
      }
    • Mar 16 2017 | 2:54 pm
      It's generally a better idea - when you want to post a patch - to select the patch or part of the patch you want to copy, choose Edit > Copy Compressed, and paste that into your posting. It keeps things a lot more readable. :-)
    • Mar 16 2017 | 3:00 pm
      Thanks for the tip! I didn't managed to edit my post, but here is the compressed copy :
    • Mar 16 2017 | 5:47 pm
      Here's the solution I currently use. This follows the clip slot as the user records different clips.
    • Mar 16 2017 | 6:35 pm
      Here's the same thing using Javascript.
      /**
       * @author Michael Dean 
       * @link https://soundcloud.com/wiklow
       */
      
      /**
       * Inlet is provided for the live.thisdevice object.
       */
      inlets = 1
      outlets = 1
      
      /**
       * Trigger the clip operations.
       */
      function bang() {	
      	get_playing_slot_index();
      }
      
      /**
       * Observe the playing_slot_index property of the track this device is placed on.
       */
      function get_playing_slot_index() {
      	
      	//Create object to observe a property
      	var this_track = new LiveAPI(observe_property);
      	
      	//Get the LiveObject of the track this device is placed on
      	this_track.path = "this_device canonical_parent";
      	
      	//Observe the playing_slot_index property of this_track
      	this_track.property = "playing_slot_index";
      }
      
      /**
       * Observe property changes.
       */
      function observe_property(args) {
      	
      	//Output the playing slot index each time the property is updated
      	outlet(0,args[1]);
      }
      
      
    • Mar 20 2017 | 3:27 pm
      Hi Mike,
      Many thanks for your answer. Can someone confirm this, to be sure I have understood well: - a clip cannot be observe until it is created, which means I can't setup an "is_recording" observer before it's already recording or recorded ; - if I want to detect a clip is recording, I need to observe the playing_slot_index property of a track, (or maybe the "is_triggered" property of a clip slot) and use this information to observe the clip itself after it has been created (even if not finished) ;
    • Mar 21 2017 | 2:41 am
      Looks correct, I would observe "has_clip" instead though, probably less variables involved.