{-# OPTIONS -fglasgow-exts #-} module Eg.Music.Simulator where import Control.Monad (when) import Data.Dynamic data Simulator = Simulator { nextSearchComplete :: Integer , nextPlayStarted :: Integer , nextPlayComplete :: Integer , simulatorTime :: Integer , searchCompleteAction :: IO () , playStartedAction :: IO () , playCompleteAction :: IO () } deriving Typeable newSimulator = Simulator 0 0 0 0 (return ()) (return ()) (return ()) sooner sim event soon = if event > simulatorTime sim && event < soon then event else soon nextEvent sim bound = sooner sim (nextSearchComplete sim) . sooner sim (nextPlayStarted sim) . sooner sim (nextPlayComplete sim) $ bound perform sim = do let time = simulatorTime sim when (time == nextSearchComplete sim) (searchCompleteAction sim) when (time == nextPlayStarted sim) (playStartedAction sim) when (time == nextPlayComplete sim) (playCompleteAction sim) return () advance sim future = if simulatorTime sim < future then do let sim' = sim { simulatorTime = nextEvent sim future } perform sim' advance sim' future else return sim schedule sim secs = simulatorTime sim + round (1000.0 * secs) delay sim secs = advance sim (schedule sim secs) waitSearchComplete sim = advance sim (nextSearchComplete sim) waitPlayStarted sim = advance sim (nextPlayStarted sim) waitPlayComplete sim = advance sim (nextPlayComplete sim)