   ;; Open and configure any newly available devices.
   (open-inputs-if-needed!)
   (open-outputs-if-needed!))
+
+(defn- handle-environment-changed
+  "Called when we had an event posted to the MIDI event queue telling
+  us that the environment has changed, i.e. a device has been added or
+  removed. Update our notion of the environment state accordingly."
+  []
+  (timbre/info "MIDI Environment changed!")
+  (scan-midi-environment))
 
 (defn- delegated-message-handler
   "Takes incoming MIDI events from the incoming queue on a thread with

      (when @running (recur (.take midi-queue))))))

(defn- start-handoff-thread
  "Creates the thread used to deliver MIDI events when needed. Also
  checks whether [CoreMIDI4J](https://github.com/DerekCook/CoreMidi4J)
  is installed, and if so, registers our notification handler to let
  us know when the MIDI environment changes."
  [old-thread]
  (or old-thread
      (do
        (when (clojure.reflect/resolve-class (.getContextClassLoader (Thread/currentThread))
                                             'uk.co.xfactorylibrarians.coremidi4j.CoreMidiNotification)
          (require '[afterglow.coremidi4j])
          ((resolve 'afterglow.coremidi4j/add-environment-change-handler) environment-changed))
        ;; TODO: Start polling-based environment-change notification system otherwise!
        (doto (Thread. delegated-message-handler "MIDI event handoff")
          (.setDaemon true)
          (.start)))))

(defn- tap-handler
  "Called when a tap tempo event has occurred for a tap tempo handler

    (.close device))
  (timbre/info "Lost contact with MIDI output: " vanished))

(defn scan-midi-environment
  "Called either periodically to check for changes, or, if CoreMidi4J
  is installed, proactively in response to a reported change in the
  MIDI environment. Updates our notion of what MIDI devices are
  available, and notifies registered listeners of any changes.

  Also sets up the thread used to process incoming MIDI events if that
  is not already running, and arranges for this function to be called
  as needed to keep up with future changes in the MIDI environment."
  []
  ;; Clean up devices which are no longer present, notifying registered listeners of their departure.
  (let [f (create-midi-port-filter)]
    (doseq [device (clojure.set/difference (set (keys @midi-inputs))
