{:triggers [{:bar true, :start "Start", :channel 5, :note 127, :gear false, :stop true, :expressions {:setup ";; Establish OSC link to BLT-Live and define a handler function that will tell it when playback\n;; speed changes, or position jumps due to loops or other DJ activity.\n(let [client (osc/osc-client \"localhost\" 17001)\n\t handler (reify org.deepsymmetry.beatlink.data.TrackPositionListener\n (movementChanged [this update]\n (osc/osc-send client \"/master/time\" (int (.milliseconds update)))\n (osc/osc-send client \"/master/speed\"(float (.pitch update)))))]\n (swap! locals assoc :blt-live client\n :handler handler))", :shutdown ";; Close the OSC link to BLT-live.\n(when-let [blt-live (:blt-live @locals)]\n (osc/osc-close blt-live))\n\n;; Unregister the handler function in case the shutdown expression was not called.\n (when-let [handler (:handler @locals)]\n (.removeTrackPositionListener (org.deepsymmetry.beatlink.data.TimeFinder/getInstance) handler))", :activation ";; Send MIDI to Ableton to select the proper track.\n(let [[midi-note midi-channel] (get-in @globals [:my-track-map [track-artist track-title track-album]])]\n ;; We know midi-note and midi-channel will have values, because the Enabled Filter only allows activation\n ;; when a recognized track is playing.\n (timbre/info \"TRACK STARTED:\" rekordbox-id \" - \" track-artist \" - \" track-title)\n (when trigger-output\n (midi/midi-note-on trigger-output (dec midi-note) 127 (dec midi-channel))\n ;; Record the note sent so we can use it in the Deactivation or Tracked Update (for cross-fades) expressions.\n (swap! locals assoc :sent-activation-note [midi-note midi-channel])))\n\n;; Register a position listener so we get updates when playback speed changes or the DJ jumps, then\n;; tell BLT-Live to start playing, and the current playback time and speed.\n(let [blt-live (:blt-live @locals) \n time-finder (org.deepsymmetry.beatlink.data.TimeFinder/getInstance)]\n (.addTrackPositionListener time-finder device-number (:handler @locals))\n (osc/osc-send blt-live \"/master/enable\" (int 1))\n (osc/osc-send blt-live \"/master/time\" (int (.getTimeFor time-finder status)))\n (osc/osc-send blt-live \"/master/speed\" (float pitch-multiplier)))\n\n;; Record the Master player number so we can detect crossfades.\n(swap! locals assoc :master-number device-number)", :deactivation ";; Remove our position update handler and tell BLT-Live to stop playing.\n(let [blt-live (:blt-live @locals) \n time-finder (org.deepsymmetry.beatlink.data.TimeFinder/getInstance)]\n (.removeTrackPositionListener time-finder (:handler @locals))\n (osc/osc-send blt-live \"/master/enable\" (int 0)))\n\n;; If we sent a MIDI note to Ableton to activate a track, deactivate it now.\n(when-let [[midi-note midi-channel] (:sent-activation-note @locals)]\n (when trigger-output\n (midi/midi-note-on trigger-output (dec midi-note) 127 (dec midi-channel)))\n (swap! locals dissoc :sent-activation-note))\n\n;; Note that there is no longer a known Master Player\n(swap! locals dissoc :master-number)\n\n(timbre/info \"RECOGNIZED PLAYBACK STOPPED\")", :enabled ";; This trigger is only enabled when the TimeFinder is running (which you can ensure by opening the\n;; Player Status window), and a recognized track is playing in the Master player.\n(and (.isRunning (org.deepsymmetry.beatlink.data.TimeFinder/getInstance))\n (get-in @globals [:my-track-map [track-artist track-title track-album]]))", :tracked "(when (and trigger-active? (not= device-number (:master-number @locals)))\n ;; A different player has become master, we need to react to the new track.\n\n ;; If we sent a MIDI note to Ableton to activate the old track, deactivate it now.\n (when-let [[midi-note midi-channel] (:sent-activation-note @locals)]\n (when trigger-output\n (midi/midi-note-on trigger-output (dec midi-note) 127 (dec midi-channel)))\n (swap! locals dissoc :sent-activation-note))\n\n ;; Send MIDI to Ableton to select the new track.\n (let [[midi-note midi-channel] (get-in @globals [:my-track-map [track-artist track-title track-album]])]\n (timbre/info \"TRACK CROSSFADE:\" rekordbox-id \" - \" track-artist \" - \" track-title)\n (when trigger-output\n (midi/midi-note-on trigger-output (dec midi-note) 127 (dec midi-channel))\n ;; Record the note sent so we can use it in the Deactivation or Tracked Update (for cross-fades) expressions.\n (swap! locals assoc :sent-activation-note [midi-note midi-channel])))\n\n ;; Remove the listener attached to the old master player, register one to the new master, and\n ;; tell BLT-Live to jump to the position reported by the new Master player, and update the speed.\n (let [blt-live (:blt-live @locals) \n time-finder (org.deepsymmetry.beatlink.data.TimeFinder/getInstance)\n handler (:handler @locals)]\n (.removeTrackPositionListener time-finder handler)\n (.addTrackPositionListener time-finder device-number handler)\n (osc/osc-send blt-live \"/master/time\" (int (.getTimeFor time-finder status)))\n (osc/osc-send blt-live \"/master/speed\" (float pitch-multiplier)))\n\n ;; Record the new Master player number so we can detect the next crossfade.\n (swap! locals assoc :master-number device-number))", :beat ";; Once per measure, on the down beat, if the trigger is active, resynchronize BLT-Live position.\n(when (and trigger-active? (= beat-within-bar 1))\n ;; Send the current position to BLT-Live to avoid sync drift.\n (let [blt-live (:blt-live @locals) \n time-finder (org.deepsymmetry.beatlink.data.TimeFinder/getInstance)]\n (osc/osc-send blt-live \"/master/time\" (int (.getTimeFor time-finder status)))))"}, :comment "Midi to Ableton and and OSC to BLT-Live.amxd port 17001", :outputs #beat_link_trigger.triggers.MidiChoice{:full-name "CoreMIDI4J - IAC Driver IAC Bus 2"}, :send true, :players #beat_link_trigger.triggers.PlayerChoice{:number 0}, :channel-label "Channel:", :enabled "Custom", :message "Custom"} {:bar true, :start "Start", :channel 1, :note 127, :gear false, :stop true, :expressions {:setup ";; Establish OSC link to SMPTED in Max and define a handler function that will tell it when playback\n;; speed changes, or position jumps due to loops or other DJ activity.\n(let [client (osc/osc-client \"localhost\" 17002)\n\t handler (reify org.deepsymmetry.beatlink.data.TrackPositionListener\n (movementChanged [this update]\n (osc/osc-send client \"/left/time\" (int (.milliseconds update)))\n (osc/osc-send client \"/left/speed\" (float (.pitch update)))))]\n (swap! locals assoc :smpted client\n :handler handler))", :deactivation ";; Remove our position update handler and tell SMPTED to stop playing.\n(.removeTrackPositionListener (org.deepsymmetry.beatlink.data.TimeFinder/getInstance)\n (:handler @locals))\n(osc/osc-send (:smpted @locals) \"/left/enable\" (int 0))", :activation ";; Register a position listener so we get updates when playback speed changes or the DJ jumps, then\n;; tell SMPTED to start playing, and the current playback time and speed.\n(let [smpted (:smpted @locals) \n time-finder (org.deepsymmetry.beatlink.data.TimeFinder/getInstance)]\n (.addTrackPositionListener time-finder device-number (:handler @locals))\n (osc/osc-send smpted \"/left/enable\" (int 1)))\n\n;; Record the Master player number so we can detect crossfades.\n(swap! locals assoc :master-number device-number)", :shutdown "", :enabled ";; This trigger is only enabled when the TimeFinder is running (which you can ensure by opening the\n;; Player Status window), and a recognized track is playing in the Master player.\n(and (.isRunning (org.deepsymmetry.beatlink.data.TimeFinder/getInstance))\n (get-in @globals [:my-track-map [track-artist track-title track-album]]))", :tracked "(when (and trigger-active? (not= device-number (:master-number @locals)))\n ;; A different player has become master.\n ;; Remove the listener attached to the old master player, register one to the new master, and\n ;; tell SMPTED to jump to the position reported by the new Master player, and update the speed.\n (let [smpted (:smpted @locals) \n time-finder (org.deepsymmetry.beatlink.data.TimeFinder/getInstance)\n handler (:handler @locals)]\n (.removeTrackPositionListener time-finder handler)\n (.addTrackPositionListener time-finder device-number handler)\n (osc/osc-send smpted \"/left/time\" (int (.getTimeFor time-finder status)))\n (osc/osc-send smpted \"/left/speed\" (float pitch-multiplier)))\n\n ;; Record the new Master player number so we can detect the next crossfade.\n (swap! locals assoc :master-number device-number))"}, :comment "OSC to Max SMPTED port 17002", :outputs #beat_link_trigger.triggers.MidiChoice{:full-name "CoreMIDI4J - IAC Driver IAC Bus 1"}, :send true, :players #beat_link_trigger.triggers.PlayerChoice{:number 0}, :channel-label "Channel:", :enabled "Custom", :message "Custom"}], :expressions {:setup ";(swap! globals assoc :player-status-always-on-top true)\n\n;; Show the Player Status window to make sure the TimeFinder is running.\n(beat-link-trigger.triggers/show-player-status)\n\n(swap! globals assoc :my-track-map {\n ;; Map keys and values have the following format:\n\t;; [\"Artist\" \"Track Title\" \"Album\"] [midi-note midi-channel]\n\t[\"Ace Frehley\" \"New York Groove\" \"Goe Vur In Den Otto\"] [1 8]\n\t[\"Agnostic Front\" \"Gotta Go\" \"GVIDOS Mix\"] [2 8]\n\t[\"Airbourne + Black Sabbath\" \"TooMuchTooYoungTooFast + IronMan\" \"GVIDOS Combo\"] [3 8]\n\t[\"Airbourne + JudasPriest + IronMaiden\" \"RunninWild + BreakingTheLaw + TheTrooper\" \"GVIDOS Combo\"] [4 8]\n\t[\"AndrewWK + BeastieBoys + Turbonegro\" \"AndrewFightsForHisRight + AgeOfPamparius\" \"GVIDOS Combo\"] [5 8]\n\t[\"Anthrax\" \"Bring The Noise\" \"Goe Vur In Den Otto\"] [6 8]\n\t[\"Anthrax\" \"Antisocial\" \"GVIDOS Mix\"] [7 8]\n\t[\"Biohazard\" \"How It Is\" \"Goe Vur In Den Otto\"] [9 8]\n\t[\"Black Sabbath\" \"Paranoid\" \"Goe Vur In Den Otto\"] [10 8]\n\t[\"Body Count\" \"Body Count's In The House\" \"Goe Vur In Den Otto\"] [11 8]\n\t[\"BonJovi + IronMaiden + AliceCooper\" \"YouGiveLoveABadName + RunToTheHills + Poison\" \"GVIDOS Combo\"] [12 8]\n\t[\"Carnivore\" \"Carnivore\" \"Goe Vur In Den Otto\"] [13 8]\n\t[\"Corrosion Of Conformity\" \"Vote With A Bullet\" \"Goe Vur In Den Otto\"] [14 8]\n\t[\"Cro-Mags\" \"World peace\" \"Goe Vur In Den Otto\"] [15 8]\n\t[\"Cro-Mags\" \"We gotta know\" \"Goe Vur In Den Otto\"] [16 8]\n\t[\"Danzig\" \"Mother\" \"Goe Vur In Den Otto\"] [17 8]\n\t[\"Dead kennedys\" \"Holiday in Cambodia\" \"Goe Vur In Den Otto\"] [18 8]\n\t[\"Europe\" \"Rock The Night\" \"GVIDOS Mix\"] [19 8]\n\t[\"FooFighters + QOTSA\" \"WhiteLimo + FeelGoodHit\" \"Filefuif 20180216\"] [20 8]\n\t[\"Goe Vur In Den Otto\" \"Justice Genesis\" \"GVIDOS Intro\"] [21 8]\n\t[\"Goe Vur In Den Otto\" \"GirlsGirlsGirls + LivinOnAPrayer + SharpDressed + YouShookMe (new)\" \"GVIDOS Combo\"] [22 8]\n\t[\"Goe Vur In Den Otto\" \"WelcomeTTJ tot Woman\" \"GVIDOS Combo\"] [23 8]\n\t[\"Goe Vur In Den Otto\" \"NeverGonnaStop + Lovercall + TickTickBoom + WholeLottaSabbath FADEIN\" \"GVIDOS Combo\"] [24 8]\n\t[\"GunsNRoses + Kiss\" \"SweetChildOMine + IWasMadeForLovinYou\" \"GVIDOS Combo\"] [25 8]\n\t[\"Hatebreed\" \"Proven\" \"GVIDOS Mix\"] [26 8]\n\t[\"Hatebreed\" \"Destroy Everything\" \"Goe Vur In Den Otto\"] [27 8]\n\t[\"Journey\" \"Don't Stop Believin'\" \"Goe Vur In Den Otto\"] [28 8]\n\t[\"Judas Priest\" \"Hell Bent For Leather\" \"GVIDOS Mix\"] [29 8]\n\t[\"Korn\" \"Word Up!\" \"GVIDOS Mix\"] [30 8]\n\t[\"Korn + RobZombie + Rammstein + Metallica\" \"GotTheLife + Dragula + DuHast + Fuel\" \"GVIDOS Combo\"] [31 8]\n\t[\"Life of Agony\" \"River runs red\" \"Goe Vur In Den Otto\"] [32 8]\n\t[\"Limp Bizkit\" \"Rollin' (kort)\" \"GVIDOS Mix\"] [33 8]\n\t[\"Madball\" \"Down By Law\" \"Goe Vur In Den Otto\"] [34 8]\n\t[\"Metallica\" \"Seek & Destroy\" \"GVIDOS Mix\"] [35 8]\n\t[\"Metallica + BloodyBeetroots + Crookers\" \"MasterOfPuppets + NewNoise + Thunderstruck\" \"GVIDOS Combo\"] [36 8]\n\t[\"Michael Jackson + Iron Maiden\" \"Beat It Trooper\" \"Filefuif\"] [37 8]\n\t[\"Misfits\" \"Skulls\" \"Goe Vur In Den Otto\"] [38 8]\n\t[\"Motley Crue\" \"Dr Feelgood\" \"GVIDOS Mix\"] [39 8]\n\t[\"Motorhead\" \"Ramones\" \"Goe Vur In Den Otto\"] [40 8]\n\t[\"Motorhead\" \"Ace Of Spades\" \"Goe Vur In Den Otto\"] [41 8]\n\t[\"Motorhead\" \"Speedfreak\" \"Goe Vur in den Otto\"] [42 8]\n\t[\"Motörhead + SteelPanther + MötleyCrue + IronMaiden\" \"RoadCrew + DeathTABM + KickstartMH + 2Minutes\" \"GVIDOS Combo\"] [43 8]\n\t[\"Municipal Waste\" \"Headbanger Face Rip\" \"Goe Vur In Den Otto\"] [44 8]\n\t[\"Municipal Waste + Metallica + Slay\" \"Born To Party-Motorbreath-Raining Blood\" \"GVIDOS Combo\"] [45 8]\n\t[\"Pantera\" \"Fucking Hostile\" \"Goe Vur In Den Otto\"] [46 8]\n\t[\"Rammstein\" \"Feuer Frei\" \"GVIDOS Mix\"] [47 8]\n\t[\"Ramones\" \"I Wanna Be Sedated\" \"GVIDOS Mix\"] [48 8]\n\t[\"Ramones + ElectricSix\" \"BlitzkriegBop + GayBar\" \"GVIDOS Combo\"] [49 8]\n\t[\"Rancid\" \"Time Bomb\" \"GVIDOS Mix\"] [50 8]\n\t[\"Riot + Saxon + Manowar\" \"Swords&Tequila + Denim&Leather + FightingTheWorld\" \"GVIDOS Combo\"] [51 8]\n\t[\"Rob Zombie\" \"Well Everybody's Fucking in a UFO\" \"GVIDOS Mix\"] [52 8]\n\t[\"Rob Zombie\" \"Living Dead Girl\" \"GVIDOS Mix\"] [53 8]\n\t[\"Sacred Reich\" \"Surf Nicaragua\" \"GVIDOS Mix\"] [54 8]\n\t[\"Scorpions\" \"Rock You Like A Hurricane\" \"GVIDOS Mix\"] [55 8]\n\t[\"Sex Pistols\" \"Bodies\" \"Goe Vur In Den Otto\"] [56 8]\n\t[\"Slayer & Ice-T\" \"Disorder\" \"Goe Vur In Den Otto\"] [57 8]\n\t[\"SOD + Anthrax\" \"March Of The SOD + Caught In A Mosh\" \"GVIDOS Combo\"] [58 8]\n\t[\"Steel Panther\" \"Party All Day\" \"GVIDOS Mix\"] [59 8]\n\t[\"Suicidal Tendencies\" \"You can't bring me down\" \"GVIDOS Mix\"] [60 8]\n\t[\"Suicidal Tendencies\" \"Pledge Your Allegiance\" \"Goe Vur In Den Otto\"] [61 8]\n\t[\"SystemOfADown + Slipknot\" \"ChopSueyWAKEUP + Duality\" \"GVIDOS Combo\"] [62 8]\n\t[\"The Offspring\" \"Nitro\" \"GVIDOS Mix\"] [63 8]\n\t[\"The Runaways\" \"School Days\" \"Goe Vur in den Otto\"] [64 8]\n\t[\"TheDarkness + JudasPriest + Volbeat\" \"OneWayTicket + LivinAfterMidnight + HeavenNorHell (edit + sample)\" \"GVIDOS Combo\"] [65 8]\n\t[\"Turbonegro\" \"All my Friends Are Dead\" \"Goe Vur In Den Otto\"] [66 8]\n\t[\"Twisted Sister\" \"I Wanna Rock\" \"GVIDOS Mix\"] [67 8]\n\t[\"Type O Negative\" \"We Hate Everyone\" \"GVIDOS Mix\"] [68 8]\n\t[\"Van Halen + Abba\" \"Super Jumper\" \"Filefuif\"] [69 8]\n\t[\"Volbeat\" \"Seal The Deal\" \"GVIDOS Mix\"] [70 8]\n\t[\"W.A.S.P.\" \"I Wanna Be Somebody\" \"GVIDOS Mix\"] [71 8]\n\t[\"Journey + MontyPython\" \"DontStopBelieving + AlwaysLookOnTheBrightSideOfLife\" \"GVIDOS Combo\"] [72 8]\n\t\n })"}, :comment "SMPTE", :outputs #beat_link_trigger.triggers.MidiChoice{:full-name "CoreMIDI4J - Bus 1"}, :send true, :beat-link-trigger-version "0.3.8-SNAPSHOT", :players #beat_link_trigger.triggers.PlayerChoice{:number 3}, :channel-label "Channel:", :enabled "Always", :request-metadata? true, :message "Note"}