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.