Triggers Global Expressions
The Triggers menu at the top of the window lets you define two expressions that can manage values you want to make available to all your other Trigger expressions.
To support that, all Trigger expressions have access to a Clojure
atom named globals
that is
shared with all other Trigger expressions, so that’s a great place to
put things for them to find. The atom starts out holding an empty
map, which allows
you to add key/value pairs to organize the information you want to
share across expressions.
Global Setup Expression
This is run when Beat Link Trigger starts up, or when you open a new Trigger file, so it runs before any of your individual trigger expressions. As a simple example of what you might want to do, here is an expression that reconfigures the Player Status window so that the line that normally shows the artist who created a track instead shows the track comment (in case that’s more useful for communicating with your front-of-house staff):
(replace-artist-line (fn [metadata _player] (.getComment metadata)))
This won’t affect any tracks whose metadata is already displayed in the Player Status window, if that was already open when you added this to Global Setup. If that happens to you, load a new track to see the results. |
The replace-artist-line
function gets passed a function that takes
the track metadata object and the player number, and returns the
string you want displayed on the second player status line. In this
example we are ignoring the player number, but you could use it to
look up other things if you need to.
We could combine this with another expression that opens the Player Status window:
(beat-link-trigger.triggers/show-player-status)
Having this in your Global Setup Expression will automatically open the Player Status window whenever Beat Link Trigger launches.
If you ever start up BLT in offline mode with this Global Setup Expression in place, however, you will be presented with an error dialog, complaining “Must be Online to show Player Status window.” To avoid being inconvenienced by that, we can make the expression smarter, so it only tries to open Player Status when already Online:
(when (.isRunning (VirtualCdj/getInstance)) (1)
(beat-link-trigger.triggers/show-player-status)) (2)
1 | A when clause in Clojure only executes its body if a test
expression returns a true value. In this case we ask the Beat Link
VirtualCdj object if it is running, which is only true when Beat
Link Trigger is online. |
2 | This means the expression body, which is the same as our first attempt at opening Player Status, is only run when it is safe to do so. |
But there is an even better way to do this, now that version 0.5.4 has added the Came Online Expression which runs once Beat Link Trigger has successfully connected to a DJ Link network. Using that expression to show the Player Status window means it will always be safe to try, and — even better — the window will be reopened every time you go back online, not just when initially starting the program.
Here is an even more sophisticated example that creates a
DatagramSocket
for sending a remote trigger command to the ChamSys MagicQ lighting
control software using its
remote
ethernet protocol:
(let [chamsys-address (InetSocketAddress. (1)
(InetAddress/getByName "172.16.42.255") 6553)
trigger-on (byte-array (map int "71,1H")) (2)
trigger-off (byte-array (map int "71,0H"))]
(swap! globals assoc (3)
:chamsys-socket (DatagramSocket.) (4)
:chamsys-on (DatagramPacket. trigger-on (count trigger-on) (5)
chamsys-address)
:chamsys-off (DatagramPacket. trigger-off (count trigger-off)
chamsys-address)))
This begins with a let
binding which sets up some values that will
be used later in the expression.
1 | chamsys-address gets set to a
SocketAddress
representing port 6553 (the default port used by MagicQ) on the
broadcast address for the Deep Symmetry show network (you will need to
use the value appropriate for your own network). |
2 | trigger-on and trigger-off are arrays of bytes containing the
characters that make up the commands for turning a MagicQ remote
programming trigger on and off. |
3 | Those values are then used in the
swap!
call, which is the way you modify a Clojure atom. In this case we are
modifying the map in globals by using
assoc
to add some new key-value pairs to it: |
4 | :chamsys-socket gets associated with a newly-allocated
DatagramSocket
that triggers will be able to use for sending UDP messages to MagicQ, |
5 | and the actual command packets are created as
DatagramPacket
objects preconfigured with the correct command bytes and destination
address and port, in :chamsys-on and :chamsys-off . |
The Beat Expression below shows how these globals are actually used.
Came Online Expression
This is run whenever Beat Link Trigger has successfully connected to a DJ Link network, either at initial startup or when you have told it manually to go online. At initial startup, or whenever you open a new Triggers file, it will run after the Global Setup expression as long as you are online. It runs by itself when you choose to successfully transition from an offline to an online state.
You have access to the expression globals if you need to use anything in them.
This is the perfect place to take actions that can only succeed when Beat Link Trigger is online, such as opening the Player Status window. The simplest approach described above is safe to use in this expression, unlike in the Global Setup expression:
(beat-link-trigger.triggers/show-player-status)
With this in place, every time you successfully go online, either at startup or using
, the Player Status window will open for you.Similarly, if you want the OBS overlay server to automatically start once Beat Link Trigger is online, you can add this to your Came Online expression:
(overlay/run-server)
You can combine both of the above lines, in either order, if you want both features to automatically activate for you. |
Another example came up in the community chat room, from a user who wanted to set up a turn-key lighting system that automatically started Beat Link Trigger and Carabiner. If you are in a situation like that, you can set up a Came Online Expression to automatically open the Carabiner window and connect to it:
(carabiner/show-window nil) (1)
(carabiner/connect) (2)
(carabiner/sync-mode :passive) (3)
(carabiner/sync-link true) (4)
(carabiner/align-bars true) (5)
1 | Opens the Carabiner window. |
2 | Tries to connect to the Carabiner daemon. |
3 | Allows the DJ Link network to become
Tempo Master for Ableton Link. Other choices are :off ,
:triggers , and
:full . |
4 | Causes Ableton Link to actually follow the DJ Link Tempo Master. |
5 | Aligns Ableton Link and the DJ Link network at the level of entire four-beat measures, rather than simple beat alignment. |
If you are using the above Carabiner configuration functions in an expression, you need to perform the first three steps in the order they are shown, because each will only work when the preceding step has been succesfully accomplished. Functions 4 and 5 can be called in any order. |
Going Offline Expression
This is run whenever Beat Link Trigger is online and you manually take it offline by choosing Global Shutdown expression. It gives you a chance to gracefully close any connections and release any system resources you allocated in your Came Online Expression.
, exit the program, open a new Trigger file, or choose to delete all triggers. In any of the situations where you are doing more than just going offline, it runs right before theYou have access to the expression globals if you need to use anything in them.
Global Shutdown Expression
This is run when Beat Link Trigger is exiting, or before it opens a new Trigger file (or when you choose to delete all triggers). It gives you a chance to close any connections and release any system resources that you allocated in your Global Setup Expression. Here is how we would do that for the ChamSys MagicQ example we started above:
(.close (:chamsys-socket @globals))
This simply looks up the
DatagramSocket
that was created in the setup expression, and closes it. There is no
need to remove the key/value pairs themselves from the globals
atom
because Beat Link Trigger will reset it to hold an empty map once the
shutdown expression finishes.