evdev-1.0.0.0: src/Evdev/Stream.hs
module Evdev.Stream (
allDevices,
allEvents,
makeDevices,
readEvents,
readEventsMany,
) where
import Control.Exception
import Control.Monad
import System.IO.Error
import RawFilePath.Directory (doesFileExist,listDirectory)
import System.Posix.ByteString (RawFilePath)
import System.Posix.FilePath ((</>))
import Streamly
import qualified Streamly.Prelude as S
import Evdev
-- | Read all events from a device.
readEvents :: Device -> SerialT IO Event
readEvents dev = S.repeatM $ nextEvent dev defaultReadFlags
-- | Concurrently read events from multiple devices.
readEventsMany :: IsStream t => AsyncT IO Device -> t IO (Device, Event)
readEventsMany ds = asyncly $ do
d <- ds
S.map (d,) $ serially $ readEvents d
-- | Create devices for all paths in the stream.
-- | Will throw an exception if a path doesn't correspond to a valid input device.
makeDevices :: IsStream t => t IO RawFilePath -> t IO Device
makeDevices = S.mapM newDevice
-- | All events on all valid devices (in /dev/input).
allEvents :: IsStream t => t IO (Device, Event)
allEvents = readEventsMany allDevices
-- | All valid devices (in /dev/input).
allDevices :: (IsStream t, Monad (t IO)) => t IO Device
allDevices =
let maybeNewDevice path = catchJust (guard . isIllegalOperation) (Just <$> newDevice path) (\() -> return Nothing)
paths = S.filterM doesFileExist $ S.map (evdevDir </>) $ S.fromFoldable =<< S.yieldM (listDirectory evdevDir)
in S.mapMaybeM maybeNewDevice paths