{-# LANGUAGE TupleSections #-} module Reactive.Bacon.EventStream.Timed where import Reactive.Bacon.Core import Reactive.Bacon.EventStream.IO import Reactive.Bacon.EventStream.Monadic import System.Time import Control.Concurrent(threadDelay, forkIO) import Control.Monad(void, unless) import Data.IORef laterE :: TimeDiff -> a -> IO (EventStream a) laterE diff x = timedE [(diff, x)] >>= return . fst periodicallyE :: TimeDiff -> a -> IO (EventStream a, Disposable) periodicallyE diff x = timedE (repeat (diff, x)) sequentiallyE :: TimeDiff -> [a] -> IO (EventStream a) sequentiallyE delay xs = timedE (map (delay,) xs) >>= return . fst timedE :: [(TimeDiff, a)] -> IO (EventStream a, Disposable) timedE events = fromStoppableProcess $ \sink stopper -> void $ forkIO $ serve sink events stopper where serve sink [] _ = sink End serve sink ((diff, event) : events) getStopState = do stop <- getStopState unless stop $ do threadDelay (toMicros diff) sink $ Next event serve sink events getStopState delayE :: EventSource s => TimeDiff -> s a -> IO (EventStream a) delayE diff = flatMapE (laterE diff) throttleE :: EventSource s => TimeDiff -> s a -> IO (EventStream a) throttleE diff = switchE (laterE diff) toMicros :: TimeDiff -> Int toMicros diff = fromInteger((toPicos diff) `div` 1000000) where toPicos :: TimeDiff -> Integer toPicos (TimeDiff 0 0 0 h m s p) = p + (fromHours h) + (fromMinutes m) + (fromSeconds s) where fromSeconds s = 1000000000000 * (toInteger s) fromMinutes m = 60 * (fromSeconds m) fromHours h = 60 * (fromMinutes h) -- | Milliseconds to TimeDiff milliseconds :: Integral a => a -> TimeDiff milliseconds ms = noTimeDiff { tdPicosec = (toInteger ms) * 1000000000} -- | Seconds to TimeDiff seconds :: Integral a => a -> TimeDiff seconds = milliseconds . (*1000)