module Hemokit.Start
( EmotivArgs (..)
, emotivArgsParser
, parseModel
, parseArgs
, getEmotivDeviceFromArgs
) where
import Data.List
import Options.Applicative
import System.IO (stdin)
import Hemokit hiding (serial)
data EmotivArgs = EmotivArgs
{ model :: EmotivModel
, serial :: Maybe SerialNumber
, fromFile :: Maybe FilePath
} deriving (Eq, Show)
parseModel :: Monad m => String -> m EmotivModel
parseModel s = case s of
"consumer" -> return Consumer
"developer" -> return Developer
_ -> fail "Model is not valid. Must be 'consumer' or 'developer'."
emotivArgsParser :: Parser EmotivArgs
emotivArgsParser = EmotivArgs
<$> nullOption
( long "model" <> metavar "MODEL"
<> reader parseModel <> value Consumer
<> help "Consumer or Developer model, Consumer by default" )
<*> (optional . nullOption)
( long "serial" <> metavar "SERIALNUMBER"
<> maybeReader makeSerialNumberFromString "Serial number of has invalid format"
<> help "The serial to use. If no --from-file is given, this will select the device" )
<*> (optional . strOption)
( long "from-file" <> metavar "PATH"
<> help "The file path to read from (e.g. /dev/hidraw0 or myfile.dump)" )
where
maybeReader mbFn msg = reader $ maybe (fail msg) pure . mbFn
parseArgs :: String -> Parser a -> IO a
parseArgs programDescription parser = execParser $ info (helper <*> parser)
(progDesc programDescription)
getEmotivDeviceFromArgs :: EmotivArgs -> IO (Either String EmotivDevice)
getEmotivDeviceFromArgs EmotivArgs{ model, serial, fromFile } = case fromFile of
Just f | Just s <- serial -> Right <$> if f == "-" then openEmotivDeviceHandle model s stdin
else openEmotivDeviceFile model s f
| otherwise -> fail "A serial number must be provided when using --from-file"
Nothing -> do
devices <- getEmotivDevices
case devices of
[] -> fail "No devices found."
_ -> case serial of
Just s -> case find ((Just s ==) . deviceInfoSerial) devices of
Nothing -> fail $ "No device with serial " ++ show s
Just d -> Right <$> openEmotivDevice model d
_ -> Right <$> openEmotivDevice model (last devices)