packages feed

vrpn (empty) → 0.2.0.0

raw patch · 7 files changed

+869/−0 lines, 7 filesdep +basesetup-changed

Dependencies added: base

Files

+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2015 Brian W Bush++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ ReadMe.md view
@@ -0,0 +1,44 @@+Bindings for VRPN+=================++This package contains bindings to VRPN, <<https://github.com/vrpn/vrpn/wiki>> and is loosely modeled on the code in <<https://github.com/vrpn/vrpn/blob/master/client_src/vrpn_print_devices.C>>.  This has been tested using VRPN 07.30 on Linux.  It requires the VRPN C++ header files.++Please report issues at <<https://bwbush.atlassian.net/projects/HVRPN/issues/>>.+++Skeletal example illustrating the use of VRPN bindings+------------------------------------------------------++```haskell+data ButtonType = LeftButton | RightButton+  deriving (Enum, Eq, Show)++main :: IO ()+main =+  do+    putStrLn "Press the left button to exit."+    done <- newEmptyMVar+    let+      -- A remote button that signals completion when the left button is released.+      button :: Device Int ButtonType Double+      button =+        Button "spacenav0@localhost"+          $ Just+          $ \time button state ->+            do+              print (time, button, state)+              if button == LeftButton && not state+                then void $ tryPutMVar done ()+                else return ()+      -- An analog device.+      analog :: Device Int Int Int Double+      analog = Analog "spacenav0@localhost"+        $ Just+        $ curry print+    -- Open the remote devices.+    devices <- sequence [openDevice button, openDevice analog]+    -- Loop until a signal to complete is received.+    mainLoops (not <$> isEmptyMVar done) 10 devices+    -- Close the remote devices.+    mapM_ closeDevice devices+```
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/Main.hs view
@@ -0,0 +1,51 @@+{-|+Module      :  Main+Copyright   :  (c) 2015 Brian W Bush+License     :  MIT+Maintainer  :  Brian W Bush <consult@brianwbush.info>+Stability   :  Stable+Portability :  Portable++Simple VRPN client.+-}+++module Main (+  main+) where+++import Network.VRPN (Device(..), closeDevice, mainLoops, openDevice)+import System.Environment (getArgs)+import System.IO (hFlush, stdout)+++-- | Action for a simple VRPN client.+main :: IO ()+main =+  do+    names <- getArgs+    let+      out s = putStrLn s >> hFlush stdout+      devices :: [Device Int Int Int Double]+      devices =+        concat+          [+            [+              Tracker name+                (Just $ \t s p o -> out $ show t ++ ", sensor " ++ show s ++ ", position " ++ show p ++ ", orientation " ++ show o)+                (Just $ \t s v o d -> out $ show t ++ ", sensor " ++ show s ++ ", velocity " ++ show v ++ ", orientation " ++ show o ++ ", delta " ++ show d)+                (Just $ \t s a o d -> out $ show t ++ ", sensor " ++ show s ++ ", acceleration " ++ show a ++ ", orientation " ++ show o ++ ", delta " ++ show d)+            , Button name+                (Just $ \t b p -> out $ show t ++ ", button " ++ show b ++ ", pressed " ++ show p)+            , Analog name+                (Just $ \t v -> out $ show t ++ ", analog " ++ show v)+            , Dial name+                (Just $ \t d c -> out $ show t ++ ", dial " ++ show d ++ ", change " ++ show c)+            ]+          |+            name <- names+          ]+    remotes <- mapM openDevice devices+    mainLoops (return False) (10 :: Double) remotes+    mapM_ closeDevice remotes
+ src/Network/VRPN.hs view
@@ -0,0 +1,501 @@+{-|+Module      :  Network.VRPN+Copyright   :  (c) 2015 Brian W Bush+License     :  MIT+Maintainer  :  Brian W Bush <consult@brianwbush.info>+Stability   :  Stable+Portability :  Portable++Bindings to VRPN, \<<https://github.com/vrpn/vrpn/wiki>\>, and is loosely modeled on the code in \<<https://github.com/vrpn/vrpn/blob/master/client_src/vrpn_print_devices.C>\>.  This has been tested using VRPN 07.30 on Linux.  It requires the VRPN C++ header files.++Here is a simple example that illustrates the use of this module:++@+data ButtonType = LeftButton | RightButton+  deriving (Enum, Eq, Show)++main :: IO ()+main =+  do+    putStrLn "Press the left button to exit."+    done <- newEmptyMVar+    let+      -- A remote button that signals completion when the left button is released.+      button :: Device Int ButtonType Double+      button =+        Button "spacenav0@localhost"+          $ Just+          $ \time button state ->+            do+              print (time, button, state)+              if button == LeftButton && not state+                then void $ tryPutMVar done ()+                else return ()+      -- An analog device.+      analog :: Device Int Int Int Double+      analog = Analog "spacenav0@localhost"+        $ Just+        $ curry print+    -- Open the remote devices.+    devices <- sequence [openDevice button, openDevice analog]+    -- Loop until a signal to complete is received.+    mainLoops (not <$> isEmptyMVar done) 10 devices+    -- Close the remote devices.+    mapM_ closeDevice devices+@+-}+++{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE RecordWildCards          #-}+++module Network.VRPN (+-- * Devices+  Device(..)+, RemoteDevice+-- * Callbacks+, PositionCallback+, VelocityCallback+, AccelerationCallback+, ButtonCallback+, AnalogCallback+, DialCallback+, ExitCallback+-- * Operations on devices+, openDevice+, closeDevice+, mainLoop+, mainLoops+-- * Time+, TimeVal(..)+, sleep+) where+++import Control.Monad (unless)+import Foreign.C.String (CString, withCString) +import Foreign.C.Types (CDouble(..), CInt(..), CLong(..))+import Foreign.Concurrent (newForeignPtr)+import Foreign.Marshal.Array (peekArray)+import Foreign.ForeignPtr (ForeignPtr, finalizeForeignPtr, withForeignPtr)+import Foreign.Ptr (FunPtr, Ptr, freeHaskellFunPtr, nullFunPtr)+++-- | A VRPN device.+data Device s b d a =+    -- | A tracker.+    Tracker+    {+      device               :: String                           -- ^ The device name.+    , positionCallback     :: Maybe (PositionCallback s a)     -- ^ The position callback.+    , velocityCallback     :: Maybe (VelocityCallback s a)     -- ^ The velocity callback.+    , accelerationCallback :: Maybe (AccelerationCallback s a) -- ^ The acceleration callback.+    }+    -- | A button.+  | Button+    {+      device               :: String                           -- ^ The device name.+    , buttonCallback       :: Maybe (ButtonCallback b)         -- ^ The button callback.+    }+    -- | An analog device.+  | Analog+    {+      device               :: String                           -- ^ The device name.+    , analogCallback       :: Maybe (AnalogCallback a)         -- ^ The analog callback.+    }+    -- | A dial.+  | Dial+    {+      device               :: String                           -- ^ The device name.+    , dialCallback         :: Maybe (DialCallback d a)         -- ^ The dial callback.+    }+++-- | Timestamps in seconds and fractions of a section.+data TimeVal =+  TimeVal+  {+    timeSeconds      :: Int -- ^ The seconds.+  , timeMicroSeconds :: Int -- ^ The microseconds.+  }+    deriving (Eq, Ord, Read, Show)+++-- | Callback for position information.+type PositionCallback s a =  TimeVal      -- ^ The timestamp.+                          -> s            -- ^ Which sensor is reporting.+                          -> (a, a, a)    -- ^ The position vector.+                          -> (a, a, a, a) -- ^ The orientation quaternion.+                          -> IO ()        -- ^ The action performed by the callback.+++-- | Callback for position information.+type PositionCallback' =  CLong   -- ^ Seconds of the timestamp.+                       -> CLong   -- ^ Microseconds of the timestamp.+                       -> CInt    -- ^ Which sensor is reporting.+                       -> CDouble -- ^ 1st component of the position vector.+                       -> CDouble -- ^ 2nd component of the position vector.+                       -> CDouble -- ^ 3rd component of the position vector.+                       -> CDouble -- ^ 1st component of the orientation quaternion.+                       -> CDouble -- ^ 2nd component of the orientation quaternion.+                       -> CDouble -- ^ 3rd component of the orientation quaternion.+                       -> CDouble -- ^ 4th component of the orientation quaternion.+                       -> IO ()   -- ^ The action performed by the callback.++-- | Wrap a position callback.+foreign import ccall "wrapper"+  wrapPositionCallback :: PositionCallback' -> IO (FunPtr PositionCallback')+++-- | Make a position callback suitable for FFI.+makePositionCallback :: (Enum s, RealFloat a)+                     => PositionCallback s a -- ^ The callback.+                     -> PositionCallback'    -- ^ An equivalent FFI callback.+makePositionCallback callback seconds microseconds sensor px py pz ox oy oz ow =+  callback+    (TimeVal (fromEnum seconds) (fromEnum microseconds))+    (toEnum $ fromEnum sensor)+    (realToFrac px, realToFrac py, realToFrac pz)+    (realToFrac ox, realToFrac oy, realToFrac oz, realToFrac ow)+++-- | Callback for velocity information.+type VelocityCallback s a =  TimeVal      -- ^ The timestamp.+                          -> s            -- ^ Which sensor is reporting.+                          -> (a, a, a)    -- ^ The velocity vector.+                          -> (a, a, a, a) -- ^ The future orientation quaternion.+                          -> a            -- ^ Delta time for the future orientation quaternion, in seconds.+                          -> IO ()        -- ^ The action performed by the callback.+++-- | Callback for velocity information.+type VelocityCallback' =  CLong   -- ^ Seconds of the timestamp.+                       -> CLong   -- ^ Microseconds of the timestamp.+                       -> CInt    -- ^ Which sensor is reporting.+                       -> CDouble -- ^ 1st component of the velocity vector.+                       -> CDouble -- ^ 2nd component of the velocity vector.+                       -> CDouble -- ^ 3rd component of the velocity vector.+                       -> CDouble -- ^ 1st component of the future orientation quaternion.+                       -> CDouble -- ^ 2nd component of the future orientation quaternion.+                       -> CDouble -- ^ 3rd component of the future orientation quaternion.+                       -> CDouble -- ^ 4th component of the future orientation quaternion.+                       -> CDouble -- ^ Delta time for the future orientation quaternion, in seconds.+                       -> IO ()   -- ^ The action performed by the callback.+++-- | Wrap a velocity callback.+foreign import ccall "wrapper"+  wrapVelocityCallback :: VelocityCallback' -> IO (FunPtr VelocityCallback')+++-- | Make a velocity callback suitable for FFI.+makeVelocityCallback :: (Enum s, RealFloat a)+                     => VelocityCallback s a -- ^ The callback.+                     -> VelocityCallback'    -- ^ An equivalent FFI callback.+makeVelocityCallback callback seconds microseconds sensor vx vy vz ox oy oz ow dt =+  callback+    (TimeVal (fromEnum seconds) (fromEnum microseconds))+    (toEnum $ fromEnum sensor)+    (realToFrac vx, realToFrac vy, realToFrac vz)+    (realToFrac ox, realToFrac oy, realToFrac oz, realToFrac ow)+    (realToFrac dt)+++-- | Callback for acceleration information.+type AccelerationCallback s a =  TimeVal      -- ^ The timestamp.+                              -> s            -- ^ Which sensor is reporting.+                              -> (a, a, a)    -- ^ The acceleration vector.+                              -> (a, a, a, a) -- ^ The acceleration orientation quaternion.+                              -> a            -- ^ Delta time for the acceleration quaternion, in seconds.+                              -> IO ()        -- ^ The action performed by the callback.+++-- | Callback for acceleration information.+type AccelerationCallback' =  CLong   -- ^ Seconds of the timestamp.+                           -> CLong   -- ^ Microseconds of the timestamp.+                           -> CInt    -- ^ Which sensor is reporting.+                           -> CDouble -- ^ 1st component of the acceleration vector.+                           -> CDouble -- ^ 2nd component of the acceleration vector.+                           -> CDouble -- ^ 3rd component of the acceleration vector.+                           -> CDouble -- ^ 1st component of the acceleration quaternion.+                           -> CDouble -- ^ 2nd component of the acceleration quaternion.+                           -> CDouble -- ^ 3rd component of the acceleration quaternion.+                           -> CDouble -- ^ 4th component of the acceleration quaternion.+                           -> CDouble -- ^ Delta time for the acceleration quaternion, in seconds.+                           -> IO ()   -- ^ The action performed by the callback.+++-- | Wrap an acceleration callback.+foreign import ccall "wrapper"+  wrapAccelerationCallback :: AccelerationCallback' -> IO (FunPtr AccelerationCallback')+++-- | Make an acceleration callback suitable for FFI.+makeAccelerationCallback :: (Enum s, RealFloat a)+                         => AccelerationCallback s a -- ^ The callback.+                         -> AccelerationCallback'    -- ^ An equivalent FFI callback.+makeAccelerationCallback callback seconds microseconds sensor ax ay az ox oy oz ow dt =+  callback+    (TimeVal (fromEnum seconds) (fromEnum microseconds))+    (toEnum $ fromEnum sensor)+    (realToFrac ax, realToFrac ay, realToFrac az)+    (realToFrac ox, realToFrac oy, realToFrac oz, realToFrac ow)+    (realToFrac dt)+++-- | Callback for button information.+type ButtonCallback b =  TimeVal -- ^ The timestamp.+                      -> b       -- ^ Which button was pressed, counting from 0.+                      -> Bool    -- ^ Whether the button is pressed.+                      -> IO ()   -- ^ The action performed by the callback.+++-- | Callback for button information.+type ButtonCallback' =  CLong   -- ^ Seconds of the timestamp.+                     -> CLong   -- ^ Microseconds of the timestamp.+                     -> CInt    -- ^ Which button was pressed, counting from 0.+                     -> CInt    -- ^ The button state (0 = off, 1 = on).+                     -> IO ()   -- ^ The action performed by the callback.+++-- | Wrap a button callback.+foreign import ccall "wrapper"+  wrapButtonCallback :: ButtonCallback' -> IO (FunPtr ButtonCallback')+++-- | Make a button callback suitable for FFI.+makeButtonCallback :: Enum b+                   => ButtonCallback b -- ^ The callback.+                   -> ButtonCallback'  -- ^ An equivalent FFI callback.+makeButtonCallback callback seconds microseconds button state =+  callback+    (TimeVal (fromEnum seconds) (fromEnum microseconds))+    (toEnum $ fromEnum button)+    (state /= 0)+++-- | Callback for analog information.+type AnalogCallback a =  TimeVal -- ^ The timestamp.+                      -> [a]     -- ^ The analog values.+                      -> IO ()   -- ^ The action performed by the callback.+++-- | Callback for analog information.+type AnalogCallback' =  CLong      -- ^ Seconds of the timestamp.+                     -> CLong      -- ^ Microseconds of the timestamp.+                     -> CInt        -- ^ The number of values.+                     -> Ptr CDouble -- ^ The analog values.+                     -> IO ()       -- ^ The action performed by the callback.+++-- | Wrap an analog callback.+foreign import ccall "wrapper"+  wrapAnalogCallback :: AnalogCallback' -> IO (FunPtr AnalogCallback')+++-- | Make an analog callback suitable for FFI.+makeAnalogCallback :: RealFloat a+                   => AnalogCallback a -- ^ The callback.+                   -> AnalogCallback'  -- ^ An equivalent FFI callback.+makeAnalogCallback callback seconds microseconds n ptr =+  do+    values <- peekArray (fromEnum n) ptr+    callback+      (TimeVal (fromEnum seconds) (fromEnum microseconds))+      (map realToFrac values)+++-- | Callback for dial information.+type DialCallback d a =  TimeVal -- ^ The timestamp.+                      -> d       -- ^ Which dial changed.+                      -> a       -- ^ The fraction of a revolution it changed.+                      -> IO ()   -- ^ The action performed by the callback.+++-- | Callback for dial information.+type DialCallback' =  CLong   -- ^ Seconds of the timestamp.+                   -> CLong   -- ^ Microseconds of the timestamp.+                   -> CInt    -- ^ Which dial changed.+                   -> CDouble -- ^ The fraction of a revolution it changed.+                   -> IO ()   -- ^ The action performed by the callback.+++-- | Wrap a dial callback.+foreign import ccall "wrapper"+  wrapDialCallback :: DialCallback' -> IO (FunPtr DialCallback')+++-- | Make an analog callback suitable for FFI.+makeDialCallback :: (Enum d, RealFloat a)+                 => DialCallback d a -- ^ The callback.+                 -> DialCallback'    -- ^ An equivalent FFI callback.+makeDialCallback callback seconds microseconds dial value =+  callback+    (TimeVal (fromEnum seconds) (fromEnum microseconds))+    (toEnum $ fromEnum dial)+    (realToFrac value)+++-- | Callback for exiting the main loop.+type ExitCallback = IO Bool -- ^ An action indicate whether to exit the main loop.+++-- | A remote object.+data Remote+++-- | Construct a remote tracker.+foreign import ccall "makeTracker"+  makeTracker :: CString -> FunPtr PositionCallback' -> FunPtr VelocityCallback' -> FunPtr AccelerationCallback' -> IO (Ptr Remote)+++-- | Run the main loop of a remote tracker.+foreign import ccall "mainloopTracker"+  mainloopTracker :: Ptr Remote -> IO ()+++-- | Destroy a remote tracker.+foreign import ccall "deleteTracker"+  deleteTracker :: Ptr Remote -> IO ()+++-- | Construct a remote button.+foreign import ccall "makeButton"+  makeButton :: CString -> FunPtr ButtonCallback' -> IO (Ptr Remote)+++-- | Run the main loop of a remote button.+foreign import ccall "mainloopButton"+  mainloopButton :: Ptr Remote -> IO ()+++-- | Destory a remote button.+foreign import ccall "deleteButton"+  deleteButton :: Ptr Remote -> IO ()+++-- | Construct a remote analog.+foreign import ccall "makeAnalog"+  makeAnalog :: CString -> FunPtr AnalogCallback' -> IO (Ptr Remote)+++-- | Run the main loop of a remote analog.+foreign import ccall "mainloopAnalog"+  mainloopAnalog :: Ptr Remote -> IO ()+++-- | Destroy a remote analog.+foreign import ccall "deleteAnalog"+  deleteAnalog :: Ptr Remote -> IO ()+++-- | Construction a remote dial.+foreign import ccall "makeDial"+  makeDial :: CString -> FunPtr DialCallback' -> IO (Ptr Remote)+++-- | Run the main loop of a remote dial.+foreign import ccall "mainloopDial"+  mainloopDial :: Ptr Remote -> IO ()+++-- | Destory a remote dial.+foreign import ccall "deleteDial"+  deleteDial :: Ptr Remote -> IO ()+++-- | Sleep for the specified milliseconds.+foreign import ccall "vrpnSleep"+  vrpnSleep :: CDouble -> IO ()+++-- | Sleep for the specified amount of time.+sleep :: RealFloat a => a     -- ^ The number of milliseconds.+                     -> IO () -- ^ An action to sleep the specified amount of time+sleep = vrpnSleep . realToFrac+++-- | A remote VRPN device.+newtype RemoteDevice = RemoteDevice (ForeignPtr Remote, ForeignPtr Remote -> IO ())+++-- | Open a remote VRPN device.+openDevice :: (Enum s, Enum b, Enum d, RealFloat a)+           => Device s b d a                -- ^ The device.+           -> IO RemoteDevice               -- ^ An action for opening the device.+openDevice Tracker{..} =+  do+    positionCallback'     <- maybe (return nullFunPtr) (wrapPositionCallback     . makePositionCallback    ) positionCallback+    velocityCallback'     <- maybe (return nullFunPtr) (wrapVelocityCallback     . makeVelocityCallback    ) velocityCallback+    accelerationCallback' <- maybe (return nullFunPtr) (wrapAccelerationCallback . makeAccelerationCallback) accelerationCallback+    ptr <-+      withCString device $ \device' ->+        makeTracker device' positionCallback' velocityCallback' accelerationCallback'+    ptr' <-+      newForeignPtr ptr $ do+        deleteTracker ptr+        freeHaskellFunPtr positionCallback'+        freeHaskellFunPtr velocityCallback'+        freeHaskellFunPtr accelerationCallback'+    return $ RemoteDevice (ptr', flip withForeignPtr mainloopTracker)+openDevice Button{..} =+  do+    buttonCallback' <- maybe (return nullFunPtr) (wrapButtonCallback . makeButtonCallback) buttonCallback+    ptr <-+      withCString device $ \device' ->+        makeButton device' buttonCallback'+    ptr' <-+      newForeignPtr ptr $ do+        deleteButton ptr+        freeHaskellFunPtr buttonCallback'+    return $ RemoteDevice (ptr', flip withForeignPtr mainloopButton)+openDevice Analog{..} =+  do+    analogCallback' <- maybe (return nullFunPtr) (wrapAnalogCallback . makeAnalogCallback) analogCallback+    ptr <-+      withCString device $ \device' ->+        makeAnalog device' analogCallback'+    ptr' <-+      newForeignPtr ptr $ do+        deleteAnalog ptr+        freeHaskellFunPtr analogCallback'+    return $ RemoteDevice (ptr', flip withForeignPtr mainloopAnalog)+openDevice Dial{..} =+  do+    dialCallback' <- maybe (return nullFunPtr) (wrapDialCallback . makeDialCallback) dialCallback+    ptr <-+      withCString device $ \device' ->+        makeDial device' dialCallback'+    ptr' <-+      newForeignPtr ptr $ do+        deleteDial ptr+        freeHaskellFunPtr dialCallback'+    return $ RemoteDevice (ptr', flip withForeignPtr mainloopDial)+++-- | Close a remote device.+closeDevice :: RemoteDevice -- ^ The device.+            -> IO ()        -- ^ An action for closing the device.+closeDevice (RemoteDevice (device, _)) = finalizeForeignPtr device+++-- | Run the main loop of a device *once*.+mainLoop :: RemoteDevice -- ^ The device.+         -> IO ()        -- ^ An action for running the main loop of the device *once*.+mainLoop (RemoteDevice (device, mainloopDevice)) = mainloopDevice device+++-- | Run the main loops of devices *repeatedly*.+mainLoops :: RealFloat a+          => ExitCallback   -- ^ Callback for exiting the loop.+          -> a              -- ^ The number of milliseconds to idle after each device's main loop is run once.+          -> [RemoteDevice] -- ^ The devices.+          -> IO ()          -- ^ An action for running the main loops *repeatedly*.+mainLoops exitCallback milliseconds devices =+  do+    mapM_ mainLoop devices+    sleep milliseconds+    exit <- exitCallback+    unless exit+      $ mainLoops exitCallback milliseconds devices
+ src/vrpn.cpp view
@@ -0,0 +1,208 @@+#include <stdio.h>+#include <stdlib.h>+#include <vrpn_Analog.h>+#include <vrpn_Dial.h>+#include <vrpn_Button.h>+#include <vrpn_Tracker.h>+++typedef void (PositionCallback)(long, long, int, double, double, double, double, double, double, double);+++void VRPN_CALLBACK handle_tracker_pos_quat(void *callback, const vrpn_TRACKERCB tracker)+{+  ((PositionCallback*) callback)(+    tracker.msg_time.tv_sec+  , tracker.msg_time.tv_usec+  , tracker.sensor+  , tracker.pos[0]+  , tracker.pos[1]+  , tracker.pos[2]+  , tracker.quat[0]+  , tracker.quat[1]+  , tracker.quat[2]+  , tracker.quat[3]+  );+}+++typedef void (VelocityCallback)(long, long, int, double, double, double, double, double, double, double, double);+++void VRPN_CALLBACK handle_tracker_vel(void *callback, const vrpn_TRACKERVELCB tracker)+{+  ((VelocityCallback*) callback)(+    tracker.msg_time.tv_sec+  , tracker.msg_time.tv_usec+  , tracker.sensor+  , tracker.vel[0]+  , tracker.vel[1]+  , tracker.vel[2]+  , tracker.vel_quat[0]+  , tracker.vel_quat[1]+  , tracker.vel_quat[2]+  , tracker.vel_quat[3]+  , tracker.vel_quat_dt+  );+}+++typedef void (AccelerationCallback)(long, long, int, double, double, double, double, double, double, double, double);+++void VRPN_CALLBACK handle_tracker_acc(void *callback, const vrpn_TRACKERACCCB tracker)+{+  ((AccelerationCallback*) callback)(+    tracker.msg_time.tv_sec+  , tracker.msg_time.tv_usec+  , tracker.sensor+  , tracker.acc[0]+  , tracker.acc[1]+  , tracker.acc[2]+  , tracker.acc_quat[0]+  , tracker.acc_quat[1]+  , tracker.acc_quat[2]+  , tracker.acc_quat[3]+  , tracker.acc_quat_dt+  );+}+++typedef void (ButtonCallback)(long, long, int, int);+++void VRPN_CALLBACK handle_button(void *callback, const vrpn_BUTTONCB button)+{+  ((ButtonCallback*) callback)(+    button.msg_time.tv_sec+  , button.msg_time.tv_usec+  , button.button+  , button.state+  );+}+++typedef void (AnalogCallback)(long, long, int, const double*);+++void VRPN_CALLBACK handle_analog (void *callback, const vrpn_ANALOGCB analog)+{+  ((AnalogCallback*) callback)(+    analog.msg_time.tv_sec+  , analog.msg_time.tv_usec+  , analog.num_channel+  , analog.channel+  );+}+++typedef void (DialCallback)(long, long, int, double);+++void VRPN_CALLBACK handle_dial(void *callback, const vrpn_DIALCB dial)+{+  ((DialCallback*) callback)(+    dial.msg_time.tv_sec+  , dial.msg_time.tv_usec+  , dial.dial+  , dial.change+  );+}+++extern "C" vrpn_Tracker_Remote* makeTracker(char* device, PositionCallback positionCallback, VelocityCallback velocityCallback, AccelerationCallback accelerationCallback)+{+  vrpn_Tracker_Remote* tracker = new vrpn_Tracker_Remote(device);+  if (tracker && positionCallback)+    tracker->register_change_handler((void*) positionCallback, handle_tracker_pos_quat);+  if (tracker && velocityCallback)+    tracker->register_change_handler((void*) velocityCallback, handle_tracker_vel);+  if (tracker && accelerationCallback)+    tracker->register_change_handler((void*) accelerationCallback, handle_tracker_acc);+  return tracker;+}+++extern "C" void mainloopTracker(vrpn_Tracker_Remote* tracker)+{+  if (tracker)+    tracker->mainloop();+}+++extern "C" void deleteTracker(vrpn_Tracker_Remote* tracker)+{+  delete tracker;+}+++extern "C" vrpn_Button_Remote* makeButton(char* device, ButtonCallback buttonCallback)+{+  vrpn_Button_Remote* button = new vrpn_Button_Remote(device);+  if (button && buttonCallback)+    button->register_change_handler((void*) buttonCallback, handle_button);+  return button;+}+++extern "C" void mainloopButton(vrpn_Button_Remote* button)+{+  if (button)+    button->mainloop();+}+++extern "C" void deleteButton(vrpn_Button_Remote* button)+{+  delete button;+}+++extern "C" vrpn_Analog_Remote* makeAnalog(char* device, AnalogCallback analogCallback)+{+  vrpn_Analog_Remote* analog = new vrpn_Analog_Remote(device);+  if (analog && analogCallback)+    analog->register_change_handler((void*) analogCallback, handle_analog);+  return analog;+} +++extern "C" void mainloopAnalog(vrpn_Analog_Remote* analog)+{+  if (analog)+    analog->mainloop();+}+++extern "C" void deleteAnalog(vrpn_Analog_Remote* analog)+{+  delete analog;+}+++extern "C" vrpn_Dial_Remote* makeDial(char* device, DialCallback dialCallback)+{+  vrpn_Dial_Remote* dial = new vrpn_Dial_Remote(device);+  if (dial && dialCallback)+    dial->register_change_handler((void*) dialCallback, handle_dial);+  return dial;+}+++extern "C" void mainloopDial(vrpn_Dial_Remote* dial)+{+  if (dial)+    dial->mainloop();+}+++extern "C" void deleteDial(vrpn_Dial_Remote* dial)+{+  delete dial;+}+++extern "C" void vrpnSleep(long t)+{+  vrpn_SleepMsecs(t);+}
+ vrpn.cabal view
@@ -0,0 +1,43 @@+name:                vrpn+version:             0.2.0.0+synopsis:            Bindings to VRPN.+description:         See \<<https://github.com/vrpn/vrpn/wiki>\> for information on VRPN.  This has been tested using VRPN 07.30 on Linux.+license:             MIT+license-file:        LICENSE+author:              Brian W Bush <consult@brianwbush.info>+maintainer:          Brian W Bush <consult@brianwbush.info>+copyright:           (c) 2015 Brian W Bush+category:            Network+build-type:          Simple+cabal-version:       >= 1.10+homepage:            https://bitbucket.org/bwbush/vrpn+bug-reports:         https://bwbush.atlassian.net/projects/HVRPN/issues/+package-url:         https://bitbucket.org/bwbush/vrpn/vrp-0.2.0.0.tar.gz++extra-source-files:  ReadMe.md++source-repository head+  type: git+  location: https://bwbush@bitbucket.org/bwbush/vrpn.git+ +library+  exposed-modules:     Network.VRPN+  build-depends:       base >= 4.8.1 && < 5+  hs-source-dirs:      src+  ghc-options:         -Wall+  default-language:    Haskell2010+  C-sources:           src/vrpn.cpp+  include-dirs:        /usr/local/include+  extra-lib-dirs:      /usr/local/lib+  extra-libraries:     vrpn stdc++++executable test-vrpn+  main-is:             Main.hs+  build-depends:       base+  hs-source-dirs:      src+  ghc-options:         -Wall+  default-language:    Haskell2010+  C-sources:           src/vrpn.cpp+  include-dirs:        /usr/local/include+  extra-lib-dirs:      /usr/local/lib+  extra-libraries:     vrpn stdc++