module Network.UI.Kafka.VRPN (
vrpnLoop
) where
import Control.Concurrent (MVar, forkIO, isEmptyMVar, newEmptyMVar, putMVar, takeMVar)
import Control.Monad (void, zipWithM_)
import Network.UI.Kafka (ExitAction, LoopAction, Sensor, TopicConnection, producerLoop)
import Network.UI.Kafka.Types (Button(..), Event(..))
import qualified Network.VRPN as V
data VrpnCallback =
Tracker
|
Button
|
Analog
|
Dial
deriving (Bounded, Enum, Eq, Ord, Read, Show)
vrpnLoop :: String
-> TopicConnection
-> Sensor
-> [VrpnCallback]
-> IO (ExitAction, LoopAction)
vrpnLoop device topicConnection sensor callbacks =
do
exitNow <- newEmptyMVar
nextEvent <- newEmptyMVar
devices <-
mapM (V.openDevice . snd)
$ filter ((`elem` callbacks) . fst)
[
(Tracker, V.Tracker device (Just $ positionCallback nextEvent) Nothing Nothing)
, (Button , V.Button device (Just $ buttonCallback nextEvent) )
, (Analog , V.Analog device (Just $ analogCallback nextEvent) )
, (Dial , V.Dial device (Just $ dialCallback nextEvent) )
]
(exit, loop) <-
producerLoop topicConnection sensor
$ (: [])
<$> takeMVar nextEvent
return
(
do
putMVar exitNow ()
exit
, do
void
. forkIO
$ V.mainLoops (not <$> isEmptyMVar exitNow) (1 :: Double) devices
loop
)
positionCallback :: MVar Event
-> V.PositionCallback Int Double
positionCallback nextEvent _ _ p o =
do
putMVar nextEvent
$ LocationEvent p
putMVar nextEvent
$ OrientationEvent o
buttonCallback :: MVar Event
-> V.ButtonCallback Int
buttonCallback nextEvent _ i x =
putMVar nextEvent
$ ButtonEvent (IndexButton i, toEnum $ fromEnum $ not x)
analogCallback :: MVar Event
-> V.AnalogCallback Double
analogCallback nextEvent _ =
zipWithM_
((putMVar nextEvent .) . AnalogEvent)
[0..]
dialCallback :: MVar Event
-> V.DialCallback Int Double
dialCallback nextEvent _ i x =
putMVar nextEvent
$ DialEvent i x