The base modules the system implements are:
Because of the use of the Pipes-and-Filters and Chain-of-responsibility Deignpatterns the parts are losely coupled and composed
on the startup of the application. They do not know something about each other.
The realtime calculation module implements a pipeline based model. The data is pipelined from one stage to the next until it reaches the dmx output. It is intenden, thta this pipeline can run on a bunch of nodes, each calculating some of the parameters. For redundancy reasons a parameter might be calculated on more than one node. If one fails, the parameter is available from the other node. If intelligently distributed, multible nodes can fail unnoticed by the audience.
The following subcomponents can be identified:
The following is some pseudocode that shows the main operations:
fetch_database_changes() foreach pb PLAYBACKS { update_playback_state(pb) } foreach p PARAMETERS { calculate_parameter(p) compose_parameter(p) pollish_parameter(p) map_parameter_to_dmx(p) } output_dmx_delayed()The block update_playback_state updates the state of the playback for the calculation of the next frame and can be executed, divided from the parameter calculation, on another node. The parameter calculation can be calculated on the node that outputs the dmx data.
calculate_parameter(parametercontainer OUT results, ID_t pid) { foreach pb PLAYBACKS { results[pb.id] = calculate_parameter_for_playback(pb, pid); } }From the example above we can see that each playback results in one value per parameter. The workload is divided into parameters. This makes it possible to distribute the workload to different slaves. These can be different cpu-cores on one computer as well as multible gpgpu cores on one graphic card or even multiple graphic cards. We can divide it up to one cpu per parameter. SPlitting it up any further means that the results needs to be transported to a different node, where it is merged. This is possible but often does not make sense.
The parameter is one of the key elements in the lighting console. It is the smallest controll entity for a lighting device. Therefor the parameter value as a specific state of a parameter is essential for moddeling the lighting control software.
I identified two different types of parameters:
struct ParameterValue { ID_t id; union { double valueReal; uint64_t valueCountable; }; };
In Diva a playback can be a real playback as well as virtual playbacks. A virtual playback is used for example for a live programmer to output it's values.
The playback preparation phase updates the state of the playback for this state and sends back to the application logic. These events can for example inform the application logic that a playback has reached a breakpoint (waits for the go button to be pressed) or the progress of the interpolation.
Parameter calculation for cue stacks and effects is done the same way. The calculation of the parameter values is done by a linear or square interpolation between sample points. The sample points are the values in the cues. To implement the mechanism of a GO Button, a breakpoint can be linked to a sample point to halt the interpolation at the sample point. In the diagram, B1 and B2 are breakpoints. The calculation of this cuestack halts at these breakpoints, until the GO button is pressed and a signal is send to the realtime unit to continue.
In adition to the breakpoint we can add a watchpoint. The calculation stops at the watchpoint, if a specific condition is met. Alternatively we can make the breakpoint more powerfull and add an activation condition to it.
There can be a lot of events, that change the behavior of the realtime calculation. Some of these can for example be: START, STOP, ON, OFF, HALT or PAUSE, WAIT, GO, SKIP, SKIP BACK.
In a theatre centric lighting console, several sources can influence the fadetime of a single channel inside a cue. These might be:
RealCycleTime := EffectCycleTime * PlaybackSpeed
Once the parameters are calculated from the cues, sequences, effects and playbacks, they need to be merged together. The mechanisms available are HTP(Highest Takes Precedence), LaTP(Latest Takes Precedence) and LoTP(Lowest Takes Precedence). HTP is used for Intensity parameters, LaTP for all other parameters and LoTP is used to mask out channels, e.g. to disable a specific channel. For LaTP there are two times, "earliest" and "latest". That means, that a parameter value is always used, if defined or only if no other is defined.
The pollish parameters stage is used to apply some last pollishing to the parameters. This can for example be:
This maps a parameter to one or more dmx channels.
As the primary colorspace for Diva is Lab, the color parameters must be transfered to the device dependend colorspace, either RGB or CMY. This should be done in the "map parameters" module, as it also does the device dependend mapping of parameters to dmx slots.
One device might have RGB(8:8:8) another CMY(8:8:8) and and another a set of 10 discrete colors as colorspace. If you select fixtures, the controllable colorspace should be reduces to the colorspace which can be realized by all selected devices. When the device with the discrete set of colors is selected together with others, the colorspace is reduced to these 10 points, even if the other devices support RGB(8:8:8) as colorspace. Then a crossfade possible for none of the devices. The crossfade can only be done with the smallest resulting colorspace, which can lead to a hard switchover between the indexed colors.
Move in black is one of the harder problems, as it needs planning by the software. It must decide when to change parameters of the fixture based on the time a fixture is black. When you have a black phase of 1 second for a luminary the software needs to change the parameters that should change during that black phase. The software must contain enough logic to be able to decide on its own wether or not the parameter change is possible and when the best time might be. The move in black must be decided sorely on the information available from the playback that the move in black is defined in. A move in black is always defined for a specific crossfade, not for the whole parameter or playback.
There might be a timespan when you as a designer decide that there shall be absolute silence in the house. This is a hint for the application logic when not to make noice due to parameter changes like moving color wheels or moving the device itself. This locks all parameter changes that can produce any sound. Therefor the application logic needs information about what parameters produce sound during parameter changes. Sometimes it is nessesary to do very slow movements that might be much more silent than fast movements.
Outputs DMX at a specific time.
The commandline is used to enter commands into the lighting console. Historicaly, the commandline consisted of a numerical keypad and some function keys like At, Store, Plus, Minus and Thru. To select a channel, the operator has entered the channel number into the keypad followed by the At key and an intensity entered via the numerical keypad. To select more than one channel, the thru key was used to select a range, the plus key to add another channel to the selection or the minus key to remove a channel from the selection. The very early and simple syntax could look like in the following simplified BNF. There have beed two major directions, Polish Notation and Reverse Polish Notation. In Reverse Polish the numbers are entered first followed by the command. In Polish Notation the command is entered first followed by the value. There are lots variations of these two flavours.
COMMAND ::= SELECTION | VALUECHANGE | STORECOMMAND; SELECTION ::= SELECTRANGE | SELECTION PLUS SELECTRANGE | SELECTION MINUS SELECTRANGE ; SELECTRANGE ::= NUMBER | NUMBER THRU NUMBER ; NUMBER ::= NUMBER DIGIT; VALUECHANGE ::= AT DIGIT | AT DIGIT DOT DIGIT ; STORECOMMAND ::= STORE NUMBER STORE ;In modern lighting consoles this syntax is not only expanded a lot, but also gui elements are integrated closely into the commandline syntax. Selecting channels on the screen is only one aspect.
The folowing diagram shows the interaction of a commandline with the surounding components. The events can come from different inputs and the resulting commandline state like the selection is populated to different components. The current selection can be displayed in a channel view.