スレッド化されたループ サウンド クリップがあります。
(def f
(future
(let [sound-file (java.io.File. "/path/to/file.wav")
sound-in (javax.sound.sampled.AudioSystem/getAudioInputStream sound-file)
format (.getFormat sound-in)
info (javax.sound.sampled.DataLine$Info. javax.sound.sampled.Clip format)
clip (javax.sound.sampled.AudioSystem/getLine info)]
(.open clip sound-in)
(.loop clip javax.sound.sampled.Clip/LOOP_CONTINUOUSLY))))
問題は、スレッドを強制終了しようとしたときです。
(future-cancel f)
永久に再生されるクリップは停止しません。(.stop clip)
それを停止する唯一の方法は、明示的に呼び出すことであることがわかりました。私の質問:これを行うための最良/慣用的な方法は何ですか? 私はClojureにかなり慣れてfuture
いないので、これまでのところ実験しただけagent
ですが、このコンテキストではもっと適しているでしょうか?
更新:.loop
関数がノンブロッキングであることを考えると(以下で説明したように)、頭文字を取り除くことで設計を簡素化しましたfuture
:
(defn play-loop [wav-fn]
(let [sound-file (java.io.File. wav-fn)
sound-in (javax.sound.sampled.AudioSystem/getAudioInputStream sound-file)
format (.getFormat sound-in)
info (javax.sound.sampled.DataLine$Info. javax.sound.sampled.Clip format)
clip (javax.sound.sampled.AudioSystem/getLine info)]
(.open clip sound-in)
(.loop clip javax.sound.sampled.Clip/LOOP_CONTINUOUSLY)
clip))
制御とともにatom
:
(def ^:dynamic *clip* (atom nil))
私はループを開始します:
(when (nil? @*clip*)
(reset! *clip* (play-loop "/path/to/file.wav")))
そしてそれを止めます:
(when @*clip*
(future (.stop @*clip*) ; to avoid a slight delay caused by .stop
(reset! *clip* nil)))