module Evdev.Stream ( allDevicePaths, allEvents, filteredEvents, makeDevices, readEvents, readEventsMany, ) where import Control.Monad import RawFilePath.Directory (doesFileExist,listDirectory) import System.Posix.ByteString (RawFilePath) import System.Posix.FilePath (()) import Streamly import qualified Streamly.Prelude as S import Evdev allEvents :: (IsStream t, Monad (t IO)) => t IO (Device, Event) allEvents = filteredEvents $ const True filteredEvents :: (IsStream t, Monad (t IO)) => (Device -> Bool) -> t IO (Device, Event) filteredEvents p = readEventsMany $ S.filter p $ makeDevices allDevicePaths -- |Stream a device's events. readEvents :: IsStream t => Device -> t IO Event readEvents dev = S.repeatM $ nextEvent dev defaultReadFlags readEventsMany :: IsStream t => AsyncT IO Device -> t IO (Device, Event) readEventsMany ds = asyncly $ do d <- ds S.map (d,) $ readEvents d makeDevices :: (IsStream t, Functor (t IO)) => t IO RawFilePath -> t IO Device makeDevices = S.mapMaybeM maybeNewDevice --TODO use Streamly directly allDevicePaths :: (IsStream t, Monad (t IO)) => t IO RawFilePath allDevicePaths = do fs <- S.yieldM $ lsFiles evdevDir S.fromFoldable fs {- Util -} -- lists files only, and returns full paths. lsFiles :: RawFilePath -> IO [RawFilePath] lsFiles p = filterM doesFileExist =<< (map (p ) <$> listDirectory p)