autowatch=0;inlets=1;outlets=2;var SENTINEL="::demon::";var trackObs=null;var cueObs=null;var timeObs=null;var hostTrackId=null;var armed=false;var lastTime=0;var cueList=[];var pollCount=0;var clockApi=null;var silentPath=null;var setApi=null;var lastFilePath=null;function status(){var words=Array.prototype.slice.call(arguments);outlet(1,words.length?words:["…"])}function getName(api){var raw=api.get("name");if(raw===undefined||raw===null)return"";if(Array.isArray(raw))return raw.join(" ");return String(raw)}function getStr(api,prop){var raw=api.get(prop);if(raw===undefined||raw===null)return"";if(Array.isArray(raw))return raw.join(" ");return String(raw)}function reportFilePath(){if(!setApi)return;lastFilePath=getStr(setApi,"file_path");outlet(0,"live_path",lastFilePath)}function parseToken(name){var i=name.indexOf(SENTINEL);if(i<0)return null;var rest=name.slice(i+SENTINEL.length).replace(/^\s+/,"");var tok=rest.split(/\s+/)[0];return tok||null}function buildName(name,token){var i=name.indexOf(SENTINEL);var label=(i<0?name:name.slice(0,i)).replace(/\s+$/,"");return(label?label+" ":"")+SENTINEL+token}function isValid(api){return api&&api.id&&Number(api.id)!==0}function bang(){init()}function init(){if(trackObs)return;trackObs=new LiveAPI(onPlayingSlot,"this_device canonical_parent");hostTrackId=trackObs.id;trackObs.property="playing_slot_index";cueObs=new LiveAPI(onCuePoints,"live_set");cueObs.property="cue_points";timeObs=new LiveAPI(onSongTime,"live_set");timeObs.property="current_song_time";clockApi=new LiveAPI(null,"live_set");setApi=new LiveAPI(null,"live_set");rebuildCues();lastTime=Number(clockApi.get("current_song_time"))||0;reportFilePath();armed=true;status("LOM","ready")}function clipNameAt(idx){var base="this_device canonical_parent clip_slots "+idx;var slot=new LiveAPI(null,base);if(!isValid(slot)||Number(slot.get("has_clip"))!==1)return null;var clip=new LiveAPI(null,base+" clip");return isValid(clip)?getName(clip):null}function onPlayingSlot(args){if(!armed)return;var idx=args&&args.length>1?Number(args[1]):Number(trackObs.get("playing_slot_index"));if(!(idx>=0))return;var name=clipNameAt(idx);if(!name)return;var tok=parseToken(name);if(tok){outlet(0,"recall",tok);status("recall","from","clip")}}function silentpath(){var parts=Array.prototype.slice.call(arguments);silentPath=parts.length?parts.join(" "):null}function snapshot(token){if(token===undefined||token===null)return;token=String(token);var slot=new LiveAPI(null,"live_set view highlighted_clip_slot");if(!isValid(slot)){status("select","a","slot","first");return}var parent=new LiveAPI(null,"live_set view highlighted_clip_slot canonical_parent");if(!isValid(parent)||String(parent.id)!==String(hostTrackId)){status("select","a","slot","on","the","DEMON","track");return}var trackName=String(parent.get("name"));if(Number(slot.get("has_clip"))!==1){if(!silentPath){status("no","silent","asset");return}slot.call("create_audio_clip",silentPath);if(Number(slot.get("has_clip"))!==1){status("need","an","audio","track");return}}var clip=new LiveAPI(null,"live_set view highlighted_clip_slot clip");if(!isValid(clip)){status("clip","create","failed");return}clip.set("looping",1);clip.set("name",buildName(getName(clip),token));if(String(parent.get("name"))!==trackName)parent.set("name",trackName);status("saved","preset","to","clip")}function rebuildCues(){cueList=[];var ls=new LiveAPI(null,"live_set");var raw=ls.get("cue_points");if(!raw||!raw.length)return;for(var i=0;i+1<raw.length;i+=2){if(String(raw[i])!=="id")continue;var id=raw[i+1];var cp=new LiveAPI(null,"id "+id);if(!isValid(cp))continue;cueList.push({time:Number(cp.get("time")),id:id})}cueList.sort(function(a,b){return a.time-b.time})}function onCuePoints(){rebuildCues()}function crossTo(t){if(!armed){lastTime=t;return}if(t>lastTime){for(var i=0;i<cueList.length;i++){var c=cueList[i];if(c.time>lastTime&&c.time<=t){var cp=new LiveAPI(null,"id "+c.id);var tok=isValid(cp)?parseToken(getName(cp)):null;if(tok){outlet(0,"recall",tok);status("recall","from","locator")}}}}lastTime=t}function poll(){if(!armed||!clockApi)return;if(pollCount++%10===0){rebuildCues();reportFilePath()}var t=Number(clockApi.get("current_song_time"))||0;outlet(0,"songbeat",t);crossTo(t)}function onSongTime(args){crossTo(args&&args.length>1?Number(args[1]):0)}