=========================== Defining a new fixture type =========================== To create a new fixture definition ("personality file"), use the ``define-fixture`` macro from ``(starlet fixture)``:: (define-fixture fixture-class-name (fixture-attributes list of attributes ...) scanout code ...) The ``fixture-class-name`` should be a GOOPS class name (in triangular brackets) for the fixture class, of the form ````, for example ```` for a Robe DL7S profile in mode 3. Each attribute follows one of the following forms:: (attr-continuous 'intensity '(0 100) 0) (attr-colour 'colour white) (attr-list 'prism '(#f 3 5) #f) In all cases, you need to provide a symbol for the name of the attribute. Using the standard names (below) where possible will make things work more smoothly. The last argument in each ``attr-`` form is always the default value for the attribute. For ``attr-continuous``, you need to give the range of possible values. For ``attr-list``, you need to give a list of the possible discrete values. For ``attr-colour``, the value is always a Starlet colour object. The list of attributes is followed by the `scanout code`. This code will be called to convert the attribute values into DMX values. Retrieve the current values with calls of the form ``(get-attr 'intensity)``, and set DMX values using ``(set-chan8 nn val)``, where ``val`` is the DMX value (0 to 255) and ``nn`` is the channel number. The channel numbers are indexed from 1, i.e. ``(set-chan8 1 255)`` will set the fixture's base DMX address to 255. There is also ``(set-chan16 nn val)``, which will set a pair of values to a 16-bit value between 0 and 65535. The lower channel address will get the most significant byte or 'coarse' value. Note that you don't need access (nor do you get access) to the fixture instance itself. The routines ``get-attr``, ``set-chan8`` and ``set-chan16`` automatically know which fixture is being worked on at the time of the procedure call. Tips ==== The fixture class name should include enough of the fixture's name to disambiguate it from other products by the same manufacturer. For example includes ``cw-ww`` to distinguish the `CW/WW` (cold/warm wash) variant from the `CW/WW/A` (cold/warm/amber wash) variant, which has a different channel layout. Use the standard names (see below) for attributes as far as possible. This means that, for example, the same knob on a MIDI control surface can control the same attribute across a range of different fixtures. Note the UK-style spelling of some of the attributes (e.g. ``colour``). In spite of the above paragraph, use the exact manufacturer's spelling for the fixture name itself. Put the fixture definition into a separate Guile module named ``(starlet fixture-library )``. If the fixture has multiple modes, create one fixture class for each and put them all in the same file. Use physically meaningful units where possible. For example, attribute ``colour-temperature`` should be in Kelvin, not arbitrary units. This means that a set of different fixtures types can all be set to the same value. It also makes it easily possible to substitute one fixture for a different one without having to re-program the entire show. Be prepared to do some work in the scanout code. It's almost never as simple as a 1:1 translation from the attributes to DMX channels. Even the cheap 5-channel LED cold/warm fixture in the example below includes some maths. Standard attribute names ======================== * ``intensity`` The overall light intensity, in percent of the maximum value. * ``pan`` in degrees, zero being straight forwards. * ``tilt`` in degrees, zero being straight downwards. * ``colour`` (note UK spelling). The colour of the light. * ``prism`` * ``gobo`` * ``strobe`` boolean for strobe on/off. * ``strobe-frequency`` in Hz * ``colour-temperature`` (note UK spelling) Worked example ============== Here is an annotated version of the definition for the `Stairville Octagon Theatre CW/WW fixture `_ The channels for this fixture are: 1. Cold LED intensity (0-255 min-max) 2. Warm LED intensity (0-255 min-max) 3. Strobe (0-15 off, 16-255 slow-fast) 4. Macro (0-15 direct control with channels 1&2, 16-255 various pre-programmed colour temperatures) 5. Overall intensity The approximate colour temperature range for the fixture is given in the manual as 2800K to 6400K. Temperatures in between will be achieved by mixing the cold and warm LEDs such that the sum is always constant. The midpoint colour temperature (4600K) will therefore correspond to 50% cold and 50% warm intensity. Note that this design choice reduces the absolute maximum intensity possible from this fixture, which would be achieved when channels 1, 2 and 5 are all at maximum. However, we gain the fact that the colour temperature and intensity parameters are orthogonal: changing temperature will not change the intensity, and vice-versa. Given that Starlet is a *theatrical* lighting control system, this kind of trade-off is preferable. We will totally ignore the pre-programmed colour temperatures in favour of having direct control over the cold and warm LED values. The manual does not even say what the pre-programmed temperatures are, so this is no loss at all. The strobe channel is not implemented in this example. Here is the code:: ;; Define a Guile module for the fixture (define-module (starlet fixture-library stairville octagon-theater-cw-ww) #:use-module (starlet fixture) ;; for define-fixture, attr-continuous etc #:use-module (starlet scanout) ;; for set-chan8, get-attr etc #:use-module (starlet utils) ;; for percent->dmxval8 etc #:export ()) (define-fixture ;; Name of the fixture class ;; List of attributes (fixture-attributes (attr-continuous 'intensity '(0 100) 0) (attr-continuous 'colour-temperature '(2800 6400) 3200)) ;; Scanout code follows ;; Set unused macro and strobe channels to zero (set-chan8 4 0) (set-chan8 3 0) ;; Set intensity channel (set-chan8 5 (percent->dmxval8 (get-attr 'intensity)))) ;; Set values of warm and cold LEDs according to colour temperature (let ((coltemp (get-attr 'colour-temperature))) (set-chan8 1 (scale-and-clamp-to-range coltemp '(2800 6400) '(0 255))) (set-chan8 2 (scale-and-clamp-to-range coltemp '(2800 6400) '(255 0)))) There are, of course, many more examples in ``guile/starlet/fixture-library``.