1 module RCMA.Global.Clock where
3 import Control.Concurrent
6 import Data.ReactiveValue
8 import RCMA.Auxiliary.Auxiliary
11 tempo :: Tempo -> SF () Tempo
14 -- The initial value is arbitrary but never appears because the switch
16 metronome :: SF Tempo (Event Beat)
17 metronome = switch ((repeatedly (tempoToDTime 60) ())
19 (onChange')) (metronome')
20 where metronome' :: Tempo -> SF Tempo (Event Beat)
21 metronome' t = (switch ((repeatedly (4 * tempoToDTime t) ())
23 onChange) (metronome'))
25 -- Tempo is the number of whole notes per minute.
26 tempoToDTime :: Tempo -> DTime
27 tempoToDTime = (15/) . fromIntegral
29 type TickingClock = (CBMVar (), ThreadId)
31 -- Ticking clock in the IO monad, sending callbacks every t milliseconds.
32 mkClock :: DTime -> IO TickingClock
35 tid <- forkIO $ forever $ do
39 where dInt = floor $ d * (10^3)
41 clockRV :: TickingClock -> ReactiveFieldRead IO ThreadId
42 clockRV (mvar, tid) = ReactiveFieldRead (return tid)
43 (installCallbackCBMVar mvar)
45 mkClockRV :: DTime -> IO (ReactiveFieldRead IO ThreadId)
46 mkClockRV d = clockRV <$> mkClock d
48 stopClock :: TickingClock -> IO ()
49 stopClock (_,t) = killThread t