packages feed

hosc 0.10.1 → 0.11

raw patch · 10 files changed

+94/−70 lines, 10 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Sound.OpenSoundControl.Coding: type Coder = (OSC -> ByteString, ByteString -> OSC)

Files

Sound/OpenSoundControl.hs view
@@ -1,21 +1,35 @@--- | hosc implements a subset of the Open Sound Control byte protocol.---   The protocol is documented at <http://opensoundcontrol.org/>.-module Sound.OpenSoundControl (module O+-- | An implementation of a subset of the /Open Sound Control/ byte+-- protocol, documented at <http://opensoundcontrol.org/>.+--+-- For the most part this top-level module is the only import+-- required.  It provides the 'Datum' and 'OSC' types, 'encodeOSC' and+-- 'decodeOSC' functions, basic 'UDP' and 'TCP' 'Transport' layers,+-- and basic temporal operations 'utcr' to access the current time and+-- 'pauseThread' to delay the current thread.+--+-- > let o = Bundle immediately [Message "/g_free" [Int 0]]+-- > in decodeOSC (encodeOSC o) == o+module Sound.OpenSoundControl (module Sound.OpenSoundControl.Type+                              ,module Sound.OpenSoundControl.Time+                              ,module Sound.OpenSoundControl.Transport+                              ,module Sound.OpenSoundControl.Transport.UDP+                              ,module Sound.OpenSoundControl.Transport.TCP                               ,C.encodeOSC,C.decodeOSC                               ,openUDP,udpServer                               ,openTCP,tcpServer) where -import qualified Sound.OpenSoundControl.Coding.Decode.Binary as C-import qualified Sound.OpenSoundControl.Coding.Encode.Builder as C-import Sound.OpenSoundControl.Type as O-import Sound.OpenSoundControl.Time as O-import Sound.OpenSoundControl.Transport as O-import Sound.OpenSoundControl.Transport.UDP as O-import Sound.OpenSoundControl.Transport.TCP as O+import Sound.OpenSoundControl.Coding.Decode.Binary as C+import Sound.OpenSoundControl.Coding.Encode.Builder as C+import Sound.OpenSoundControl.Type+import Sound.OpenSoundControl.Time+import Sound.OpenSoundControl.Transport+import Sound.OpenSoundControl.Transport.UDP+import Sound.OpenSoundControl.Transport.TCP  -- | Make a UDP connection. ----- > withTransport (openUDP "127.0.0.1" 57110) (\fd -> recvT 0.5 fd >>= print)+-- > let t = openUDP "127.0.0.1" 57110+-- > in withTransport t (\fd -> recvT 0.5 fd >>= print) openUDP :: String -> Int -> IO UDP openUDP = openUDP' (C.encodeOSC,C.decodeOSC) 
Sound/OpenSoundControl/Coding.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE FlexibleInstances,TypeSynonymInstances #-} -- | A type-class to provide coding operations to different data types --   using the same function names.-module Sound.OpenSoundControl.Coding (Coding(..) ) where+module Sound.OpenSoundControl.Coding (Coding(..),Coder) where  import qualified Data.ByteString as S import qualified Data.ByteString.Lazy as B@@ -28,3 +28,6 @@ instance Coding String where     encodeOSC = C.unpack . encodeOSC     decodeOSC = decodeOSC . C.pack++-- | An 'encodeOSC' and 'decodeOSC' pair over 'B.ByteString'.+type Coder = (OSC -> B.ByteString,B.ByteString -> OSC)
Sound/OpenSoundControl/Coding/Decode/Base.hs view
@@ -79,6 +79,9 @@     in Bundle timeStamp ms  -- | Decode an OSC packet.+--+-- > let b = B.pack [47,103,95,102,114,101,101,0,44,105,0,0,0,0,0,0]+-- > in decodeOSC b == Message "/g_free" [Int 0] decodeOSC :: B.ByteString -> OSC decodeOSC b =     if bundleHeader `B.isPrefixOf` b
Sound/OpenSoundControl/Coding/Decode/Binary.hs view
@@ -7,7 +7,7 @@ import Data.Binary.Get import qualified Data.Binary.IEEE754 as I import qualified Data.ByteString as S-import qualified Data.ByteString.Lazy as B+import qualified Data.ByteString.Lazy as L import qualified Data.ByteString.Lazy.Char8 as C import Data.Int (Int32) import Data.Word (Word32)@@ -21,7 +21,7 @@ isolate n m = do     s <- get_bytes n     let (a, s', _) = runGetState m s 0-    if B.null s'+    if L.null s'         then return a         else fail "isolate: not all bytes consumed" @@ -33,14 +33,14 @@ get_string :: Get String get_string = do     s <- getLazyByteStringNul-    skip (fromIntegral (align (B.length s + 1)))+    skip (fromIntegral (align (L.length s + 1)))     return $ C.unpack s  -- | Get binary data prefixed by byte count.-get_bytes :: Word32 -> Get B.ByteString+get_bytes :: Word32 -> Get L.ByteString get_bytes n = do     b <- getLazyByteString (fromIntegral n)-    if n /= fromIntegral (B.length b)+    if n /= fromIntegral (L.length b)         then fail "get_bytes: end of stream"         else skip (fromIntegral (align n))     return b@@ -75,7 +75,7 @@ -- | Get an OSC packet. get_packet :: Get OSC get_packet = do-    h <- uncheckedLookAhead (B.length bundleHeader)+    h <- uncheckedLookAhead (L.length bundleHeader)     if h == bundleHeader         then get_bundle         else get_message@@ -93,7 +93,7 @@  get_bundle :: Get OSC get_bundle = do-    skip (fromIntegral (B.length bundleHeader))+    skip (fromIntegral (L.length bundleHeader))     t <- NTPi <$> getWord64be     ps <- get_packet_seq     return $ Bundle t ps@@ -103,11 +103,14 @@ getOSC = get_packet  -- | Decode an OSC packet from a lazy ByteString.-decodeOSC :: B.ByteString -> OSC+--+-- > let b = L.pack [47,103,95,102,114,101,101,0,44,105,0,0,0,0,0,0]+-- > in decodeOSC b == Message "/g_free" [Int 0]+decodeOSC :: L.ByteString -> OSC {-# INLINE decodeOSC #-} decodeOSC = runGet getOSC  -- | Decode an OSC packet from a strict ByteString. decodeOSC' :: S.ByteString -> OSC {-# INLINE decodeOSC' #-}-decodeOSC' = runGet getOSC . B.fromChunks . (:[])+decodeOSC' = runGet getOSC . L.fromChunks . (:[])
Sound/OpenSoundControl/Coding/Encode/Builder.hs view
@@ -64,6 +64,9 @@ buildOSC (Bundle (UTCr t) l) = build_bundle_ntpi (utcr_ntpi t) l  -- | Encode an OSC packet to a lazy ByteString.+--+-- > let b = L.pack [47,103,95,102,114,101,101,0,44,105,0,0,0,0,0,0]+-- > in encodeOSC (Message "/g_free" [Int 0]) == b encodeOSC :: OSC -> L.ByteString {-# INLINE encodeOSC #-} encodeOSC = B.toLazyByteString . buildOSC
Sound/OpenSoundControl/Time.hs view
@@ -7,10 +7,12 @@ import Data.Word import qualified Data.Time as T +-- * Temporal types+ -- | Type for integer representation of NTP time. type NTPi = Word64 --- | Time is represented in either UTC or NTP form.  The NTP form may+-- | Time is represented in either @UTC@ or @NTP@ form.  The @NTP@ form may --   be either integral or real. data Time = UTCr Double | NTPr Double | NTPi NTPi             deriving (Read, Show)@@ -19,7 +21,7 @@     a == b = as_ntpi a == as_ntpi b     a /= b = as_ntpi a /= as_ntpi b --- | Coerce to NTPi form.+-- | Coerce 'Time' to integral @NTP@ form. as_ntpi :: Time -> NTPi as_ntpi x =     case x of@@ -27,7 +29,7 @@       NTPr t -> ntpr_ntpi t       NTPi t -> t --- | Coerce to UTCr form.+-- | Coerce 'Time' to real-valued @UTC@ form. as_utcr :: Time -> Double as_utcr x =     case x of@@ -44,27 +46,27 @@           (NTPi p',NTPi q') -> compare p' q'           _ -> compare (as_ntpi p) (as_ntpi q) --- | Convert a real-valued NTP timestamp to an NTP timestamp.+-- | Convert a real-valued NTP timestamp to an 'NTPi' timestamp. ntpr_ntpi :: Double -> NTPi ntpr_ntpi t = round (t * 2^(32::Int)) --- | Convert an NTP timestamp to a real-valued NTP timestamp.+-- | Convert an 'NTPi' timestamp to a real-valued NTP timestamp. ntpi_ntpr :: NTPi -> Double ntpi_ntpr t = fromIntegral t / 2^(32::Int) --- | Convert UTC timestamp to NTP timestamp.+-- | Convert a real-valued UTC timestamp to an 'NTPi' timestamp. utcr_ntpi :: Double -> NTPi utcr_ntpi t =     let secdif = (70 * 365 + 17) * 24 * 60 * 60     in ntpr_ntpi (t + secdif) --- | Convert NTP timestamp to UTC timestamp.+-- | Convert a real-valued NTP timestamp to a real-valued UTC timestamp. ntpr_utcr :: Double -> Double ntpr_utcr t =     let secdif = (70 * 365 + 17) * 24 * 60 * 60     in t - secdif --- | Convert NTP timestamp to UTC timestamp.+-- | Convert an 'NTPi' timestamp to a real-valued UTC timestamp. ntpi_utcr :: NTPi -> Double ntpi_utcr = ntpr_utcr . ntpi_ntpr @@ -75,35 +77,41 @@         s = T.secondsToDiffTime 0     in T.UTCTime d s --- | Read current UTCr timestamp.+-- | Constant indicating the bundle is to be executed immediately.+immediately :: Time+immediately = NTPi 1++-- * Clock operations++-- | Read current real-valued @UTC@ timestamp. utcr :: IO Double utcr = do   t <- T.getCurrentTime   return (realToFrac (T.diffUTCTime t utc_base)) --- | Read current NTP timestamp.+-- | Read current 'NTPi' timestamp. ntpi :: IO NTPi ntpi = liftM utcr_ntpi utcr --- | The pauseThread limit (in seconds).  Values larger than this---   require a different thread delay mechanism, see sleepThread.  The---   value is the number of microseconds in maxBound::Int.+-- | The 'pauseThread' limit (in seconds).  Values larger than this+-- require a different thread delay mechanism, see 'sleepThread'.  The+-- value is the number of microseconds in @maxBound::Int@. pauseThreadLimit :: Double pauseThreadLimit = fromIntegral (maxBound::Int) / 1e6  -- | Pause current thread for the indicated duration (in seconds), see---   pauseThreadLimit.  Note also that this function does not attempt---   pauses less than 1e-4.+--   'pauseThreadLimit'.  Note also that this function does not+--   attempt pauses less than @1e-4@. pauseThread :: Double -> IO () pauseThread n = when (n > 1e-4) (threadDelay (floor (n * 1e6))) --- | Pause current thread until the given utcr time, see---   pauseThreadLimit.+-- | Pause current thread until the given real-valued @UTC@ time, see+-- 'pauseThreadLimit'. pauseThreadUntil :: Double -> IO () pauseThreadUntil t = pauseThread . (t -) =<< utcr  -- | Sleep current thread for the indicated duration (in seconds).---   Divides long sleeps into parts smaller than pauseThreadLimit.+--   Divides long sleeps into parts smaller than 'pauseThreadLimit'. sleepThread :: Double -> IO () sleepThread n =     if n >= pauseThreadLimit@@ -111,11 +119,7 @@          in pauseThread n >> sleepThread (n - n')     else pauseThread n --- | Sleep current thread until the given utcr time.  Divides long---   sleeps into parts smaller than pauseThreadLimit.+-- | Sleep current thread until the given real-valued @UTC@ time.+-- Divides long sleeps into parts smaller than 'pauseThreadLimit'. sleepThreadUntil :: Double -> IO () sleepThreadUntil t = sleepThread . (t -) =<< utcr---- | Execute the bundle immediately.-immediately :: Time-immediately = NTPi 1
Sound/OpenSoundControl/Transport/TCP.hs view
@@ -6,6 +6,7 @@ import qualified Data.ByteString.Lazy as B import Control.Monad import Network+import Sound.OpenSoundControl.Coding import Sound.OpenSoundControl.Coding.Byte import Sound.OpenSoundControl.Transport import Sound.OpenSoundControl.Type@@ -27,8 +28,6 @@          b1 <- B.hGet fd (fromIntegral (decode_u32 b0))          return (dec b1)    close (TCP _ _ fd) = hClose fd--type Coder = (OSC -> B.ByteString,B.ByteString -> OSC)  -- | Make a TCP connection using specified coder. openTCP' :: Coder -> String -> Int -> IO TCP
Sound/OpenSoundControl/Transport/UDP.hs view
@@ -10,6 +10,7 @@ import qualified Network.Socket as N import qualified Network.Socket.ByteString as C (sendTo,recvFrom) import qualified Network.Socket.ByteString.Lazy as C (send,recv)+import Sound.OpenSoundControl.Coding import Sound.OpenSoundControl.Transport import Sound.OpenSoundControl.Type @@ -26,8 +27,6 @@    send  (UDP enc _ fd) msg = C.send fd (enc msg) >> return ()    recv  (UDP _ dec fd) = liftM dec (C.recv fd 8192)    close (UDP _ _ fd) = N.sClose fd--type Coder = (OSC -> B.ByteString,B.ByteString -> OSC)  -- | Make a UDP connection with specified coder. openUDP' :: Coder -> String -> Int -> IO UDP
Sound/OpenSoundControl/Type.hs view
@@ -1,9 +1,9 @@ -- | Alegbraic data types for OSC datum and packets.-module Sound.OpenSoundControl.Type ( OSC(..)-                                   , Datum(..)-                                   , message-                                   , bundle-                                   , tag ) where+module Sound.OpenSoundControl.Type (OSC(..)+                                   ,Datum(..)+                                   ,message+                                   ,bundle+                                   ,tag) where  import qualified Data.ByteString.Lazy as B import Data.Word@@ -17,15 +17,15 @@            | Blob B.ByteString            | TimeStamp Time            | Midi (Word8,Word8,Word8,Word8)-             deriving (Eq, Read, Show)+             deriving (Eq,Read,Show)  -- | An OSC packet. data OSC = Message String [Datum]          | Bundle Time [OSC]-           deriving (Eq, Read, Show)+           deriving (Eq,Read,Show)  -- | OSC bundles can be ordered (time ascending).  Bundles and---   messages compare EQ.+--   messages compare 'EQ'. instance Ord OSC where     compare (Bundle a _) (Bundle b _) = compare a b     compare _ _ = EQ@@ -42,21 +42,17 @@       TimeStamp _ -> 't'       Midi _ -> 'm' --- | Bundle constructor.------ Signals an error when @xs@ is empty.+-- | Bundle constructor. It is an 'error' if the 'OSC' list is empty. bundle :: Time -> [OSC] -> OSC bundle t xs =     case xs of       [] -> error "bundle: empty?"       _ -> Bundle t xs --- | Message constructor------ Signals an error when the address @a@ doesn't conform to the OSC--- specification.+-- | Message constructor.  It is an 'error' if the address doesn't+-- conform to the OSC specification. message :: String -> [Datum] -> OSC message a xs =     case a of-      ('/':_) -> Message a xs+      '/':_ -> Message a xs       _ -> error "message: ill-formed address"
hosc.cabal view
@@ -1,9 +1,9 @@ Name:              hosc-Version:           0.10.1+Version:           0.11 Synopsis:          Haskell Open Sound Control-Description:       hosc provides Sound.OpenSoundControl, a haskell-                   module implementing a subset of the Open Sound-                   Control byte protocol.+Description:       @hosc@ provides "Sound.OpenSoundControl", an+                   implementation of a subset of the /Open Sound Control/+                   byte protocol documented at <http://opensoundcontrol.org/>. License:           GPL Category:          Sound Copyright:         (c) Rohan Drape, Stefan Kersten and others, 2006-2011@@ -11,7 +11,7 @@ Maintainer:        rd@slavepianos.org Stability:         Experimental Homepage:          http://slavepianos.org/rd/?t=hosc-Tested-With:       GHC == 7.0.4+Tested-With:       GHC == 7.2.2 Build-Type:        Simple Cabal-Version:     >= 1.8 Data-Files:        README