                          (.getModifiers f) java.lang.reflect.Modifier/STATIC))]
       [(keyword (.getName f)) (.get f obj)])))
 
-(defmacro apply-method [& args]
+(defmacro apply-member [& args]
   `(~@(drop-last args) ~@(eval (last args))))
 
-;; utils
 (defn rekey
   ([m kold knew]
     (-> m (dissoc kold) (assoc knew (get m kold))))

  (-> settings
    (data-object-to-map)
    (assoc :frames (range (.numFrames settings))
           :channels (map ChannelSpec-to-map (.channels settings))
           :positions (map MultiStagePosition-to-map (.positions settings)))
    (rekey
      :slicesFirst             :slices-first

              1 [(.x stage-pos)]
              2 [(.x stage-pos) (.y stage-pos)])])))})

;; acq-engine

(defn set-stage-position
  ([stage-dev z] (. mmc setPosition stage-dev z))
  ([stage-dev x y] (. mmc setXYPosition stage-dev x y)))
  
(def device-agents
  (let [devs (seq (. mmc getLoadedDevices))]
    (zipmap devs (repeatedly (count devs) #(agent nil)))))
    
(defn create-presnap-actions [event]
  (into {} (concat
    (for [[axis pos] (get-in event [:position :axes])]
      [axis #(apply set-stage-position axis pos)])
    (for [prop (get-in event [:channel :properties])]
      [(prop 0) #(.setProperty mmc (prop 0) (prop 1) (prop 2))]))))

(defn send-device-action [dev action]
  (send-off (device-agents dev) (fn [_] (action))))

(defn run-actions [action-map]
  (doseq [[dev action] action-map]
    (send-device-action dev action))
  (doseq [dev (keys action-map)]
    (send-device-action dev #(. mmc waitForDevice dev)))
  (apply await-for 10000 (vals device-agents)))

(defn snap-image [event auto-shutter]
  (if (and auto-shutter (. mmc getShutterOpen))
