   (:require [afterglow.channels :as chan]
             [afterglow.effects.channel :as chan-fx]
             [afterglow.fixtures.qxf :refer [sanitize-name]]))
+
+(defn- build-gobo-entries
+  "Build a list of gobo wheel function entries. If `shake?` is `true`,
+  they are a variable range which sets the shake speed. The individual
+  gobo names are in `names`."
+  {:doc/format :markdown}
+  [shake? names]
+  (map (fn [entry]
+         (let [label (str "Gobo " entry (when shake? " shake"))
+               type-key (keyword (sanitize-name label))]
+           (merge {:type type-key
+                   :label label
+                   :range (if shake? :variable :fixed)}
+                  (when shake? {:var-label "Shake Speed"}))))
+       names))
 
 (defn color-strip
   "[ColorStrip](http://www.chauvetlighting.com/colorstrip.html) LED fixture.

                             (chan/dimmer 7)
                             (build-shutter 8)
                             (build-control-channel 9)]})))))

                                         192 :random-strobe
                                         224 "Shutter Open 4"))
         gobo-names ["Splat" "Spot Sphere" "Fanned Squares" "Box" "Bar" "Blue Starburst" "Perforated Pink"]
         build-gobo-wheel (fn [channel]
                            (chan/functions :gobo channel
                                            (range 0 79 10) (build-gobo-entries false (concat ["Open"] gobo-names))
