             [overtone.midi :as midi]
             [taoensso.timbre :refer [info error]])
   (:import [java.util.regex Pattern]
-           [java.util.concurrent LinkedBlockingQueue]))
+           [java.util.concurrent LinkedBlockingDeque]))
 
 (def ^:private max-clock-intervals
   "How many MIDI clock pulses should be kept around for averaging?"

  (atom nil))

(defn- delegated-message-handler
  "Takes incoming MIDI events from the core.async channel on a thread
  with access to all Afterglow classes. Fields incoming MIDI
  messages, looks for registered interest in them (metronome sync,
  variable mappings, etc.) and dispatches to the appropriate specific
  handler."
  []
  (let [running (atom true)]
    (loop [msg (.take midi-queue)]

  (doseq [handler (vals (get-in @control-mappings [(:name (:device msg)) (:channel msg) (:note msg)]))]
    (handler msg)))

(defonce ^:private ^{:doc "The queue used to hand MIDI events from the
  extension thread to our world, since there seem to be classloader
  compatibility issues, and the Java3d classes are not available to
  threads that are directly dispatching MIDI events. Although we
  allocate a capacity of 100 elements, it is expected that the queue
  will be drained much more quickly than events arrive, and so it will
  almost always be empty."} midi-queue
  (LinkedBlockingDeque. 100))

(defonce ^:private ^{:doc "The thread used to hand MIDI events from
  the extension thread to our world, since there seem to be
