Afterglow Developer Guide
This section provides an introduction describing this guide and an overview of the Afterglow environment. It then explains the built in web interface, and links to other sections that go into more detail. It is worth reading through this whole page once if you are new to Afterglow, because the orientation it provides will be helpful, and it ends with a walkthrough to help you get started on your way to creating your own light show. Once you know what you are looking for, you can also dive right into it by jumping to the section you want:
Afterglow is a lighting controller designed to support live coding, written in Clojure, intended to enable people to produce spectacular and highly customizable light shows using modern stage and effect lighting, and which are related in deep ways to the phrasing of music being played. (Its creator is a DJ and producer of light and laser shows by avocation.) Currently, the lighting effects and fixture definitions are written and organized through Clojure code, so you will either need to learn Clojure or work with a Clojure programmer to create new ones, but they are controlled through MIDI control surfaces or Open Sound Control, so once they are set up, there is great flexibility in how you can perform them.
Someday a user interface for building shows and fixture definitions may be created, either within Afterglow, or as a companion project, but that is not currently planned. For now the focus is on building rich user interfaces for controlling shows, such as the Ableton Push and Novation Launchpad family mappings and the embedded web interface, while using the concise expressive power of Clojure for writing the fixture definitions, effects, and cues.
The fundamental task of Afterglow is to make light shows happen. It does this by controlling lights, communicating with them through the Open Lighting Architecture, which can work with several kinds of control protocols, most of which are derived from DMX512, or a faster implementation of its basic ideas over Ethernet. When a show is running, Afterglow runs a thread which periodically asks “what should all the lights be doing now?” (resulting in a single “frame” of control values representing that moment in time), and sends the results of that analysis to all of the OLA universes the show is configured to control. By default this happens 40 times each second, but the interval is configurable within the show, and should be decided based on the fastest refresh rate of any physical interfaces you have hooked up to Afterglow. This is described in more detail in the Rendering Loop section.
|In principle you could have more than one show running at a time, each controlling a different set of OLA universes, but most people will not need this capability.|
When you just create a show and call
(show/start!), Afterglow will
send a bunch of zero values to the show’s universes. To make
interesting things happen you add Effects to the
show. The default namespace you are put into when you launch the
Afterglow project using
lein repl has some
example effects that can help get a
feel for this concept. To get a full understanding of how to use (and
create) effects, learn about the
The effects need to know what lights they are supposed to control, what capabilities they have, and how they are connected (what universe, what channels), as well as how they are arranged in space. This is accomplished by patching Fixture Definitions to the show. To work with the actual lights you have available, you will need to create fixture definitions for them, unless they happen to be ones already available in the Afterglow project. Since there are so many kinds of lights, with more being created every month, that seems unlikely unless the project really takes off… and, to that end, if you do create definitions for your lights, please contribute them to the project!
To learn how to install Afterglow and the Open Lighting Architecture, see the project README.
Since Afterglow was developed to create light shows for electronic music events, it is deeply driven by the notion of musical time, through its Metronomes, so it is worth learning how to configure and interact with them. It is also designed to work with MIDI controllers, both to trigger effects, and to synchronize with music, as described in MIDI Mapping and Beat Sync.
Of course, you are not going to want to have to type and evaluate Clojure expressions to create your effects in the heat of the moment of running a light show, so Afterglow shows incorporate a grid of Cues that you can trigger and adjust quickly, both through the embedded web interface described below, and with dedicated physical grid controllers or simpler MIDI controllers.
Although a physical grid controller (especially one as well-designed as the Ableton Push or Novation Launchpad Pro) offers the ideal control surface for running a light show, you can do a lot with just the web interface built in to Afterglow. And even when you have a Push or other grid controller, the web interface makes it all the more powerful by adding at-a-glance documentation of cue names, as well as alternate ways of doing things, or the opportunity to interact with more than one section of the cue grid at once.
If you have started Afterglow by running the jar file, it will have opened a browser window on the web interface by default. Otherwise, you can bring it up by evaluating:
(core/start-web-server 16000 true)
The home page offers some buttons which can take you to this documentation, the Open Lighting Architecture console in case you want to monitor DMX values or configure the universe(s) that your show will be using, and an embedded web REPL that can be used to evaluate arbitrary expressions to configure and control Afterglow. The primary interface, however, is the show page, which is reached by a link in the Shows section. However, when you first start Afterglow on its own, there will be no shows running. The Console can be used to change that:
As menioned in the main project
Readme, the web
console is there for quick hacks, and is no substitute for a rich
Clojure development environment. For any real work you will want to
either start Afterglow from your development REPL in the first place,
or to connect it via
Once you have the web interface open, and a show running, you will
spend most of your time on the show page. Here a look at the cue grid
that gets created for the sample show by
There are a number of different things you can control from this page. The load indicator in the middle of the navigation bar gives you a sense of how much headroom your system has, by showing you what fraction of the time available for rendering the last few frames of lighting effects was used up. As you add more complex effects, the bar will fill in and turn red, warning you if Afterglow might not be able to keep up.
Stop button next to it can be used to temporarily shut down
the show, blacking out all universes that it controls. Clicking it
again restarts the show where it would have been had it not stopped.
If there is a problem communicating with the Open Lighting
Architecture daemon, the status indicator will show Error, and there
will be a
Details button you can click to get more information about
the problem Afterglow is encountering.
The majority of the page is taken up by an 8×8 window on to the Cue grid attached to the show. You can activate any cue shown by clicking on it; running cues will light up, and darken again when they end. To stop a running cue, click it again. Some cues will end immediately, others will continue to run until they reach what they feel is an appropriate stopping point. While they are in the process of ending, the cue cell will blink. If you want the cue to end immediately even though it would otherwise run for a while longer, you can click the blinking cue cell and it will be killed right then.
The text labels within the cue cells are to help identify their purpose, and are established when the cues are created. Similarly, the colors are intended to help identify related cues.
Some cues (especially intense ones like strobes) are configured to run only as long as they are held down. In that case, when you click on the cue cell, a whitened version of its color is displayed as a hint that this is happening, and as soon as you release the mouse, the cue will end. If you want to override this behavior, you can hold down the Shift key as you click on the cue cell, and it will activate as a normal cue, staying on until you click it a second time.
Cues may be mutually exclusive by nature, and if they were created to
reflect this (by using the same keyword to register their effects with
the show, or specifying other effect keys in their
when you activate one, the other cues which use the same keyword are
darkened. This is a hint that when you activate one of them, it will
replace the others, rather than running at the same time. The
Cue Grid section of the Cues documentation goes
into more details about the relationships between cues illustrated in
the above animation.
When any effects are running, whether they were launched by a cue button or some other means, they are listed at the bottom of the show control page, in descending order of priority. (Effects are run in the reverse order that they appear on the screen, so effects towards the top of the list can override things done by those further down. Newly launched effects assigned a given priority appear above older ones with the same priority.)
The name of the effect is shown, along with its prority (if it is anything other than the default of zero), when it was started, in terms of clock time (down to 1/100 of a second), and the show Metronome (phrase, bar, beat, and hundredths of a beat).
If an effect was launched by a cue with any cue variables, they appear after the start time. Numeric cue variables can be adjusted by dragging the associated slider. As shown in the image above, the current value appears as a popup above the slider thumb when the mouse is over the slider. Color cue variables can also be adjusted. The current color value appears as a swatch; clicking on that swatch opens a color picker interface which can be used to adjust the color parameter:
Click anywhere outside the swatch and color picker to dismiss the color adjustment interface.
If cue variables are adjusted somewhere else, such as a mapped MIDI controller or from other code that is running, the web interface will update to show their changed values.
If you have made any adjustments to cue variable values, these are
normally discarded when you end the cue; the next time it begins, it
starts with the values that were configured in the show. You can
change that by saving the cue’s variables. In the effect list, any cues whose variables you’ve adjusted will have a green Save button on the right, like the
Color snowball cue in the photo below:
After clicking Save in this situation, whenever you click the
Color snowball cue in the cue grid, it will start out blue rather
than its previous white color. To reflect this, the color of the cue
in the cue grid is updated to be blue as well, both in the web
interface, and on any attached hardware grid controllers.
Once you have saved a cue’s variables, while it is running, instead of
a green Save button, you will see a gray Clear button
(like the one on the
All Dimmers effect in the photo). Clicking that
will remove the saved values, so the cue goes back to its original
For the moment, saved cue variables last only for the duration of an Afterglow run. The next time you start up a show, all cues are back to their configured values. This may change in a future release.
In addition to saving the values of a single cue, you can also make an entirely new cue which, when you launch it, will start one or more cues that you currently have running, with whatever cue variable values they had when you created the macro. This is a great way to quickly build up a library of looks by combining a bunch of running cues that you like, so you can get back to them in an instant.
To do that, start by clicking the Make Macro button at the bottom of the effect list. Checkboxes will appear in front of all running effects that were created by cues. Check the ones that you want the macro to include, type a name for it, then click on any empty cell in the cue grid. A new cue will appear there with the name you have chosen.
Whenver you click that cue cell, it will start all of the cues that you included in the macro, with the variable settings they had at the time you created the macro.
If you decide you don’t want to create a macro after all, you can click the red Cancel button, and the effect list will return to its normal state.
If you have created a macro and decide you don’t want it any more, you
can right-click on the cue cell and choose the
Delete option that
|Be careful with this: You can delete any cue this way, and if it was not a macro, the only way to get it back is to re-run the code that created it in the first place.|
A running effect can be asked to end by clicking its End button. If the effect takes a while to end, its entire row will take on the color of the End button while it is in the process of ending, and the button becomes a Kill button which can be clicked to instantly terminate the ending effect:
The show may have many more cues than fit on the screen at once; the diamond of blue arrows below the bottom right of the cue grid allow you to page through the larger grid. If there are more cues available in a given direction, that arrow will be enabled, otherwise it is dimmed. Clicking an active arrow scrolls the view one page in that direction. In this grid, it is currently possible to scroll up and to the right.
If you hold down Shift while clicking a scroll arrow, it will scroll you as far as possible in the direction you clicked.
You can also use the arrow keys on your keyboard to scroll in the corresponding direction. (Again, holding Shift will scroll you as far as possible in that direction.)
If you have any compatible grid controllers, Afterglow started
watching for them to be connected as soon as you called
(use-sample-show). If you are defining your own show and want to
learn more about how that works, or lower-level ways of binding to a
specific controller, see the
details in the
Mapping and Sync section.
With auto-binding active, whenever a compatible grid controller is connected and powered on, you will see a link menu appear next to the scroll diamond, as shown in the above screen image. The link menu allows the web interface to be tied to a grid controller, so that each is always looking at the same page of cues. Using the scroll arrows on either the web interface, or on the controller itself if it has them (the Push and Launchpad family do), will cause both to scroll simultaneously. This provides an excellent additional layer of information about the buttons on the physical controller.
|Of course, there may be times you want to break this link, for example so you could have access to one set of cues on the physical buttons of your controller, while simultaneously being able to control others via the screen and mouse. To do that, simply use the link menu to turn off the link.|
In the center of the interface below the cue grid is a slider that lets you adjust the show’s dimmer grand master. This can be used to control the overall brightness of the show, because any dimmer cues that are running will be affected by the value of this master. If it is set at 100% (all the way to the right), the dimmer cues can operate at full brightness. As you slide it to the left, it gradually reduces the maximum brightness that any dimmer cue can achieve. In the middle, all dimmer cues will be reduced by 50%, and all the way to the left, all dimmer cues will be zeroed out.
The final section of the show control interface, left of the Dimmer
Grand Master section, lets you view and adjust the Metronome that the
show is using to keep time with the music that is being played. Since
Afterglow’s effects are generally defined with respect to the
metronome, it is important to keep it synchronized with the music. The
metronome section shows the current speed, in Beats Per Minute, of the
metronome, and the
Tap Tempo button label flashes yellow at each
beat. It also shows you the current phrase number, the bar within that
phrase, and beat within that bar which has been reached.
The most basic way of synchronizing the metronome is to click the
Tempo button at each beat of the music. Tapping the button aligns the
metronome to a beat, and if you tap it three or more times within two
seconds of each preceding tap, sets the metronome’s BPM. Tap it as you
hear each beat of the music, and after three or more taps, the speed
of the metronome will be approximately synchronized with the music.
You can also adjust the BPM by dragging the slider along the bottom,
or fine-tune it with the
- buttons around the current BPM
Once the tempo is correct, you can tell Afterglow which beat is the down beat by holding down Shift while pressing Tap Tempo. (The label of the button will change to Tap Bar while Shift is down). This combination does not change the tempo, but tells Afterglow that the moment when you tapped the button is the down beat (the first beat of a bar).
In order to make longer chases and effects line up properly with the
music, you will also want to make sure the count is right, that the
beat number shows
1 on the down beat, and that the bar numbers are
right as well, so that the start of a phrase is reflected as bar
1. In addition to using Shift with Tap Tempo to
set the down beat, you can adjust the count using the
buttons around the Bar and Beat numbers.
A shortcut that you can use right as a phrase begins is to click the
x button above the phrase number, which resets the metronome to
Phrase 1, Bar 1, Beat 1.
Trying to keep up with tempo changes during dynamic shows can be
tedious, so you will hopefully be able to take advantage of
Afterglow’s metronome synchronization features. If you can get the DJ
to feed you MIDI clock
pulses or Traktor
Beat Phase, or connect via a Local Area Network to Pioneer
professional DJ gear to lock into the beat grid established by
Pro DJ Link, Afterglow
can keep the BPM (with MIDI) and even the beats (with Traktor Beat
Phase or Pro DJ Link) synchronized for you. To configure that
synchronization, click the
Sync button once you have the MIDI clock,
beat phase, or network Pro DJ Link signals reaching the machine
running Afterglow, and choose the sync source you want to use.
|When you are synchronizing with Pro DJ Link, you will almost always want to sync to the mixer, rather than one of the CDJs, so you stay in sync as the DJs mix between tracks.|
The actual list of choices you will see depends on what MIDI and DJ Link Pro traffic Afterglow has seen in the last few seconds, and will update as players and mixers start and stop sending clock or beat grid information.
Once your sync is established, the
Tap Tempo button changes. If you
are using MIDI clock to sync the BPM, it becomes a
Tap Beat button,
which simply establishes where the beat falls. If you are locked in to
a Pro DJ Link or Traktor Beat Phase beat grid, it becomes a
button which, when pressed, indicates that the current beat is the
down beat (start) of a bar. Similarly, if you press the metronome
Reset button (the red x above the phrase counter) while synced to a
Pro DJ Link or Traktor Beat Phase beat grid, the beat itself will not
move, but the beat closest to when you pressed the pad will be
identified as Beat 1. In these sync modes you can also use the
Shift key to align at the next bigger boundary: If tapping
would normally move the bar, shift-tapping will move the phrase.
The Sync button also turns green to indicate that sync is in effect. If something interrupts the sync process (such as the network link being broken, or the DJ software’s MIDI clock generator being turned off), the button will turn red to warn you that it is not working. Pressing the Sync button again will give you more information to troubleshoot the problem.
There is a lot to Afterglow, and already a lot of documentation. In an effort to help you find your way through it, here is a guide to the steps you’ll want to take to get a basic light show up and running. Once you are there, you can branch off and explore extending it in any direction you like, and hopefully contribute back the fixture definitions and new effects and cues you come up with!
If you don’t know any Clojure, you are going to want to learn at least a little. Luckily, it is a fantastic, helpful community, and an amazing language (the existence of Afterglow after a couple of months of spare time work is good proof of that)! The Getting Started page on clojure.org has links to some great resources. Maria is an interactive, online workbook for beginners that provides progressive instruction in the language. And don’t miss Clojure for the Brave and True, a fun book under development which can be read in its entirety online.
Install Afterglow. For now the best way to do that is following the steps in the Installation section on the main project page, to install the Open Lighting Architecture, then create a new Clojure project with Leiningen that includes Afterglow as a dependency.
Set up your universe(s) in OLA. Their own Getting Started page may be helpful. Until OLA is successfully communicating with your lights, whether over a USB DMX interface, Artnet over a LAN, or the like, Afterglow will not be able to control them. Even though their examples show using the command-line tools to configure your interface, today you will likely find the web interface, especially the beta new UI, much more convenient and easy to learn. With a default installation, once you have
oladrunning, you can find that at http://localhost:9090/new/.
Find or create fixture definitions. Once you are able to get your lights to do things by manipulating the Faders section of the OLA web interface, it is time to get Afterglow ready to talk to them. There are a vast number of fixture types out there, and at this early stage almost none of them are built in to Afterglow, so you will probably need to create your own. The documentation explains how, and links to existing fixture definitions as examples. You can also ask for help on the Zulip chat or the Wiki. + At this point you are almost certainly writing enough code that you want to save it for later reuse. The Usage section of the project page explains how you can have Afterglow load files when it starts up when you are running it as a standalone jar, which makes it easier to use your own configuration files. + . Patch your actual fixture channels and locations. Once you have working definitions for your fixtures, you will want to create a show that tells Afterglow what fixtures you have, and the DMX universes and channels you have them connected to, and how you have them arranged in physical space. You will want to create a namespace for your show along the lines of
afterglow.examples, and a function like
use-sample-showwhich sets up your own show.
Create the cues you want. Much as the
make-cuesfunction in the examples namespace creates a bunch of cues that work with the sample show’s fixtures, you will want cues that create effects to make your lights do interesting things, and which are arranged, labeled, and colored in a way that makes sense to you.
Map some cues to a controller, if you have one. If you have an Ableton Push, you are in luck because you will be able to take advantage of the built in support Afterglow offers. Or perhaps a Novation Launchpad? But even if you just have a simple MIDI controller with a few buttons and faders, or even a keyboard, you can map keys, buttons, and faders to trigger cues and adjust variables used by the cues.
Run the show! With or without a physical controller, you can create your show by calling the function you wrote modeled on
use-sample-show, then bring up the embedded web interface to trigger your cues and watch the results.
Create your own custom effects if you want to be fancy. Once you feel constrained by the limits of the effects that are built in to the current release of Afterglow, the whole point of the environment it offers is to enable people to imagine and create brand new effects. You have the full power of the language used to create Afterglow at your fingertips at every moment to create and explore new ideas; you are not constrained to the limited scripting environment that most lighting control software offers, if it offers any at all.
Don’t forget to contribute your fixture definitions and effects to the Afterglow community! If you are confident that you have fully mapped out the functions of a fixture, please make a pull request to include it in afterglow, either within the existing namespace for its manufacturer, or creating a new namespace for a new manufacturer. Similarly, if you have created an awesome new kind of effect, please consider a pull request to add it somewhere within the effects namespace hierarchy. And if you are just tinkering with something new and experimental, please post about it on the Zulip chat!