The problem
Some fixtures have a channel that does different things depending on an other channel's value. "Different things" means that a specific DMX value has a different meaning (for example "rotation" vs. "speed"). It does not mean that a specific DMX value only applies if another channel has a specific value and else has no effect (e.g. "Red" = 147 has no effect if "Intensity" = 0).
Example
Have a look at the Martin MAC 700: https://www.martin.com/Martin.Download.aspx?file=/files/files/productdocuments/11_MANUALS/999/UM_MAC700Profile_DE_A.pdf
It has a gobowheel (rotatable, of course) with 6 gobos that can rotate themselves, too.
It has a Gobo channel (7) with these capabilities:
- a) 1x Open
- b) 6x Static Gobo
- c) 6x Self-Rotating Gobo
- d) 6x Static Gobo Shake (slow–fast)
- e) 6x Self-Rotating Gobo Shake (slow–fast)
- f) 2x Rotating Gobowheel (CW, CCW; slow-fast)
Slow-fast is the speed of goboshake or the whole gobowheel, not the gobo itself.
Then there's a channel (8) for the self-rotation of each gobo.
- I.) If channel 7's value is in the range of a), b) or d), channel 8 simply defines the static gobo rotation angle (DMX 0 = 0° –> DMX 255 = 395°)
- II.) If channel 7's value is in the range of a), b) or d), channel 8 has four capabilites:
- No rotation
- CW, slow-fast
- CCW, fast-slow
- No rotation
So channel 8 changes its functionality (and capabilities) when channel 7's value changes.
Lighting program support
e:cue and QLC+ don't support channels that change behavior depending on an other channel's value yet.
DMXControl 3
Notes: In DMXControl, dmxchannel
s start with zero. <step>
or <range>
are capabilities.
There's a special feature for gobowheels and prisms to difference between gobo/prism rotation (speed) and index (angle). For the Martin MAC 700, these functions can be implemented like this:
There are 6 <step>
s in <gobowheel>
(channel 7). Each of them defines with its attributes the static gobo capability (b), with one <step>
the capability for self-rotating gobo (c) and with one <range>
the capability for static gobo shake (d).
The capability for self-rotating gobo (c) has the attribute for="goborotation"
, which declares that channel 8's behavior II should be used. If this attribute is not set or set to goboindex
, behavior I is used.
<goborotation>
(II) and <goboindex>
(I) define the different capabilities for the different behaviors of channel 8.
<gobowheel dmxchannel="6" >
<goborotation dmxchannel="7" >
<step type="stop" mindmx="0" maxdmx="2" />
<step type="stop" mindmx="253" maxdmx="255" />
<range type="cw" mindmx="3" maxdmx="127" minval="0.1" maxval="8" />
<range type="ccw" mindmx="252" maxdmx="128" minval="0.1" maxval="8" />
</goborotation>
<goboindex dmxchannel="7" >
<range mindmx="0" maxdmx="255" range="395" />
</goboindex>
<goboshake />
<step type="open" caption="Open" mindmx="0" maxdmx="11" />
<step type="gobo" caption="Spiral" mindmx="12" maxdmx="15" val="spiral.png" >
<step for="goborotation" mindmx="36" maxdmx="39" />
<range handler="goboshake" mindmx="60" maxdmx="71" minval="0.1" maxval="3" />
</step>
<step type="gobo" caption="Radial Circles" mindmx="16" maxdmx="19" val="radialcircles.png" >
<step for="goborotation" mindmx="40" maxdmx="43" />
<range handler="goboshake" mindmx="72" maxdmx="83" minval="0.1" maxval="3" />
</step>
<step type="gobo" caption="Fused Dichro Red/Yellow" mindmx="20" maxdmx="23" val="redyellow.png" >
<step for="goborotation" mindmx="44" maxdmx="47" />
<range handler="goboshake" mindmx="84" maxdmx="95" minval="0.1" maxval="3" />
</step>
<step type="gobo" caption="Milky Way" mindmx="24" maxdmx="27" val="milkyway.png" >
<step for="goborotation" mindmx="48" maxdmx="51" />
<range handler="goboshake" mindmx="96" maxdmx="107" minval="0.1" maxval="3" />
</step>
<step type="gobo" caption="Water" mindmx="28" maxdmx="31" val="Water.png" >
<step for="goborotation" mindmx="52" maxdmx="55" />
<range handler="goboshake" mindmx="108" maxdmx="119" minval="0.1" maxval="3" />
</step>
<step type="gobo" caption="Flames" mindmx="32" maxdmx="35" val="flames.png" >
<step for="goborotation" mindmx="56" maxdmx="59" />
<range handler="goboshake" mindmx="120" maxdmx="131" minval="0.1" maxval="3" />
</step>
<wheelrotation>
<range type="cw" mindmx="229" maxdmx="204" minval="0.1" maxval="2" />
<range type="ccw" mindmx="255" maxdmx="230" minval="0.1" maxval="2" />
</wheelrotation>
</gobowheel>
(Possible) solution
We define the trigger channel (normal gobo) and both behaviors for channel 8 as three different channels (no real data):
"availableChannels": {
"Gobo": {
"type": "Gobo",
"defaultValue": 60,
"capabilities": [
{
"range": [0, 11],
"name": "Open"
},
{
"range": [12, 15],
"name": "Gobo 1 (Spiral)"
},
// ...
]
},
"Gobo Rotation Angle": {
"type": "Intensity"
},
"Gobo Rotation Speed": {
"type": "Speed",
"capabilities": [
{
"range": [11, 132],
"name": "Fast-slow (CW)"
},
{
"range": [133, 255],
"name": "Slow-fast (CCW)"
}
]
}
}
Instead of using Gobo Rotation Angle
or Gobo Rotation Speed
directly in a mode's channel list, we define a switchingChannel that says when to use which channel.
"availableChannels": {
// ...
},
"switchingChannels": {
"Gobo Rotation": {
"trigger": "Gobo",
"channels": {
"Gobo Rotation Angle": [60, 131],
"Gobo Rotation Speed": [[0, 59], [132, 255]]
}
}
},
"modes": [{
"name": "2-channel",
"channels": [
"Gobo",
"Gobo Rotation"
]
}]
Schema would be changed like that:
+var Range = Array.of(2, DMXValue)
+var SwitchingChannel = schema({
+ '?name': [String, null], // null: use channel key
+ 'trigger': ChannelKey,
+ 'channels': schema({
+ '*': [Range, Array.of(1, Infinity, Range)] // '*' is the channel key of an switched channel
+ })
+});
+
var Fixture = schema({
// ...
'availableChannels': schema({
'*': Channel // '*' is the channel key
}),
+ '?switchingChannels': schema({
+ '*': SwitchingChannel // '*' is the channel key
+ }),
Tests
What has to be checked in fixture-valid test:
- Channel key must be unique between
availableChannels
and switchingChannels
- A mode containing a switching channel must also contain the trigger channel
- Channels mentioned in a switching channel must exist in
availableChannels
- Ranges in a switching channel must not overlap
- A trigger channel must have the
defaultValue
attribute set (see later why)
Fixture editor
As soon as this feature is implemented, #77 will get a new item to support it in the fixture editor. At the moment, the fixture editor would not be broken as the switching channel is an optional additional feature. Until we implement switching channels in the fixture editor, we only have to prevent errors when an edited or imported fixture uses switching channels (but edit or import isn't implemented yet as well).
Exporting
The problem is that this feature is only implemented for gobowheels / prisms in DMXCreator 3. When using other channel types or other plugins, we need to decide how to deal with switching channels.
I'd propose to just always use one of the switched channels and ignore the other ones. This "default" channel is the one that would be used if the trigger channel was set to its default value (that's why it is required for trigger channels).
In the above example, "Gobo"'s default value is 60 which results in "Gobo Rotation Angle" being the default channel.
QLC+ output for above example
<Channel Name="Gobo">
<Group Byte="0">Gobo</Group>
<Capability Min="0" Max="11">Open</Capability>
<Capability Min="12" Max="15">Gobo 1 (Spiral)</Capability>
<!-- ... -->
</Channel>
<Channel Name="Gobo Rotation">
<Group Byte="0">Intensity</Group>
<Colour>Generic</Colour>
<Capability Min="0" Max="255">0-100%</Capability>
</Channel>
<Mode Name="2-channel">
<Physical>
<!-- ... -->
</Physical>
<Channel Number="0">Gobo</Channel>
<Channel Number="1">Gobo Rotation</Channel>
</Mode>
e:cue output for above example
<ChannelBeam Name="Gobo" DefaultValue="60" Highlight="0" Deflection="0" DmxByte0="1" DmxByte1="0" Constant="0" Crossfade="0" Invert="0" Precedence="LTP" ClassicPos="1">
<Range Name="Open" Start="0" End="11" AutoMenu="1" Centre="0" />
<Range Name="Gobo 1 (Spiral)" Start="12" End="15" AutoMenu="1" Centre="0" />
</ChannelBeam>
<ChannelIntensity Name="Gobo Rotation" DefaultValue="0" Highlight="0" Deflection="0" DmxByte0="2" DmxByte1="0" Constant="0" Crossfade="0" Invert="0" Precedence="LTP" ClassicPos="2" />
As soon as programs like QLC+ support defining multiple channels to be switched depending on another channel's value in a fixture definition file, we will change our export plugins. (It doesn't necessarily mean that a program uses the functionality in user interface but that there is a way to specify it and that it doesn't break current functionality). We are also willing to change our specification if it better suits to the implementation of another lighting software.