            (pos? (:current-time @st)))
 
      toggle-play
-     #(go (>! (:chan @st) (if (is-playing)
-                            :pause
-                            [:play src])))
+     #((:command @st) (if (is-playing)
+                        :pause
+                        [:play src]))
 
      seek-time
-     #(go (>! (:chan @st) [:seek @mouse-time]))
+     #((:command @st) [:seek @mouse-time])
 
      update-mouse-time
      (fn [ev]

         (seek-time)))

     enable-preload
     #(go (>! (:chan @st) [:preload src]))]

    (into
      [:div.audio-player (r/merge-props

                 (prn "audio player: status changed")
                 (prn "   - source: " (:src @st))
                 (prn "   - status: " status)
                 (swap! st assoc-in [:status] status))

               command-handler
               (fn [command]
                 (match [command]
                    [:pause]         (do (.pause audio))
                    [[:play src]]    (do (ensure-src src)
                                         (when (let [st (:status @st)]
                                                 (or (= st :error)
                                                     (= st :aborted)))
                                           (.load audio))
                                         (.play audio))
                    [[:preload src]] (do (ensure-src src)
                                         (set! (.-preload audio) true))
                    [[:seek time]]   (do (set! (.-currentTime audio) time))
                    [bad-command]    (do (prn "audio player: bad command, "
                                              bad-command))))]

           (reset! st (state command-handler))
           (reset!
             events
             [(events/listen audio "durationchange" update-time)
