hosc 0.14.1 → 0.15
raw patch · 6 files changed
+126/−100 lines, 6 filesdep ~binarydep ~hoscPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: binary, hosc
API changes (from Hackage documentation)
+ Sound.OSC.Coding.Byte: decode_u8 :: ByteString -> Int
+ Sound.OSC.Coding.Byte: encode_u8 :: Int -> ByteString
+ Sound.OSC.Type: ascii :: String -> ASCII
+ Sound.OSC.Type: ascii_to_string :: ASCII -> String
+ Sound.OSC.Type: floatPP :: RealFloat n => Maybe Int -> n -> String
+ Sound.OSC.Type: type FP_Precision = Maybe Int
- Sound.OSC.Type: bundlePP :: Bundle -> String
+ Sound.OSC.Type: bundlePP :: FP_Precision -> Bundle -> String
- Sound.OSC.Type: datumPP :: Datum -> String
+ Sound.OSC.Type: datumPP :: FP_Precision -> Datum -> String
- Sound.OSC.Type: messagePP :: Message -> String
+ Sound.OSC.Type: messagePP :: FP_Precision -> Message -> String
- Sound.OSC.Type: packetPP :: Packet -> String
+ Sound.OSC.Type: packetPP :: FP_Precision -> Packet -> String
- Sound.OSC.Type: timePP :: Time -> String
+ Sound.OSC.Type: timePP :: FP_Precision -> Time -> String
Files
- README +10/−3
- Sound/OSC/Coding/Byte.hs +33/−25
- Sound/OSC/Coding/Decode/Binary.hs +31/−43
- Sound/OSC/Datum.hs +1/−0
- Sound/OSC/Type.hs +44/−22
- hosc.cabal +7/−7
README view
@@ -3,22 +3,29 @@ [hosc][hosc] provides `Sound.OSC`, a [haskell][hs] module implementing a subset of the [Open Sound Control][osc] byte protocol.+hosc is required by the [hsc3][hsc3] haskell [supercollider][sc3] bindings. -© [rohan drape][rd], [stefan kersten][sk] and others, 2006-2013,+There are a number of related projects:++- [hosc-json](?t=hosc-json): JSON text encoding of OSC+- [hosc-utils](?t=hosc-utils): command line utilities++© [rohan drape][rd], [stefan kersten][sk] and others, 2007-2014, [gpl][gpl]. with contributions by: - [alex mclean][am] - [henning thielemann][ht] -see the [darcs][darcs] [history][hosc-history] for details+see the [darcs][darcs] [history](?t=hosc&q=history) for details [hosc]: http://rd.slavepianos.org/?t=hosc [hs]: http://haskell.org/ [osc]: http://opensoundcontrol.org/+[hsc3]: http://rd.slavepianos.org/?t=hsc3+[sc3]: http://audiosynth.com/ [rd]: http://rd.slavepianos.org/ [sk]: http://space.k-hornz.de/ [am]: http://yaxu.org/ [ht]: http://www.henning-thielemann.de/Research.html [darcs]: http://darcs.net/ [gpl]: http://gnu.org/copyleft/-[hosc-history]: http://rd.slavepianos.org/r/d/darcsweb.cgi?r=hosc
Sound/OSC/Coding/Byte.hs view
@@ -3,97 +3,105 @@ import Data.Binary {- base -} import Data.Bits {- base -}-import qualified Data.ByteString as S.B {- bytestring -}+import qualified Data.ByteString as S {- bytestring -} import qualified Data.ByteString.Char8 as S.C {- bytestring -}-import qualified Data.ByteString.Lazy as B {- bytestring -}-import qualified Data.ByteString.Lazy.Char8 as C {- bytestring -}+import qualified Data.ByteString.Lazy as L {- bytestring -}+import qualified Data.ByteString.Lazy.Char8 as L.C {- bytestring -} import Data.Int {- base -} import Sound.OSC.Coding.Cast import Sound.OSC.Type -- | Encode a signed 8-bit integer.-encode_i8 :: Int -> B.ByteString+encode_i8 :: Int -> L.ByteString encode_i8 n = encode (fromIntegral n :: Int8) +-- | Encode an un-signed 8-bit integer.+encode_u8 :: Int -> L.ByteString+encode_u8 n = encode (fromIntegral n :: Word8)+ -- | Encode a signed 16-bit integer.-encode_i16 :: Int -> B.ByteString+encode_i16 :: Int -> L.ByteString encode_i16 n = encode (fromIntegral n :: Int16) -- | Encode a signed 32-bit integer.-encode_i32 :: Int -> B.ByteString+encode_i32 :: Int -> L.ByteString encode_i32 n = encode (fromIntegral n :: Int32) -- | Encode an unsigned 16-bit integer.-encode_u32 :: Int -> B.ByteString+encode_u32 :: Int -> L.ByteString encode_u32 n = encode (fromIntegral n :: Word32) -- | Encode a signed 64-bit integer.-encode_i64 :: Int64 -> B.ByteString+encode_i64 :: Int64 -> L.ByteString encode_i64 = encode -- | Encode an unsigned 64-bit integer.-encode_u64 :: Word64 -> B.ByteString+encode_u64 :: Word64 -> L.ByteString encode_u64 = encode -- | Encode a 32-bit IEEE floating point number.-encode_f32 :: Float -> B.ByteString+encode_f32 :: Float -> L.ByteString encode_f32 = encode . f32_w32 -- | Encode a 64-bit IEEE floating point number.-encode_f64 :: Double -> B.ByteString+encode_f64 :: Double -> L.ByteString encode_f64 = encode . f64_w64 -- | Encode an ASCII string.-encode_str :: ASCII -> B.ByteString+encode_str :: ASCII -> L.ByteString {-# INLINE encode_str #-}-encode_str = B.pack . S.B.unpack+encode_str = L.pack . S.unpack +-- | Decode an un-signed 8-bit integer.+decode_u8 :: L.ByteString -> Int+decode_u8 = fromIntegral . L.head+ -- | Decode a signed 8-bit integer.-decode_i8 :: B.ByteString -> Int+decode_i8 :: L.ByteString -> Int decode_i8 b = fromIntegral (decode b :: Int8) -- | Decode a signed 16-bit integer.-decode_i16 :: B.ByteString -> Int+decode_i16 :: L.ByteString -> Int decode_i16 b = fromIntegral (decode b :: Int16) -- | Decode a signed 32-bit integer.-decode_i32 :: B.ByteString -> Int+decode_i32 :: L.ByteString -> Int decode_i32 b = fromIntegral (decode b :: Int32) -- | Decode an unsigned 32-bit integer.-decode_u32 :: B.ByteString -> Int+decode_u32 :: L.ByteString -> Int decode_u32 b = fromIntegral (decode b :: Word32) -- | Decode a signed 64-bit integer.-decode_i64 :: B.ByteString -> Int64+decode_i64 :: L.ByteString -> Int64 decode_i64 = decode -- | Decode an unsigned 64-bit integer.-decode_u64 :: B.ByteString -> Word64+decode_u64 :: L.ByteString -> Word64 decode_u64 = decode -- | Decode a 32-bit IEEE floating point number.-decode_f32 :: B.ByteString -> Float+decode_f32 :: L.ByteString -> Float decode_f32 b = w32_f32 (decode b :: Word32) -- | Decode a 64-bit IEEE floating point number.-decode_f64 :: B.ByteString -> Double+decode_f64 :: L.ByteString -> Double decode_f64 b = w64_f64 (decode b :: Word64) -- | Decode an ASCII string.-decode_str :: B.ByteString -> ASCII+decode_str :: L.ByteString -> ASCII {-# INLINE decode_str #-}-decode_str = S.C.pack . C.unpack+decode_str = S.C.pack . L.C.unpack -- | Bundle header as a (strict) 'S.C.ByteString'. bundleHeader_strict :: S.C.ByteString bundleHeader_strict = S.C.pack "#bundle\0" -- | Bundle header as a lazy ByteString.-bundleHeader :: B.ByteString+bundleHeader :: L.ByteString {-# INLINE bundleHeader #-}-bundleHeader = C.fromChunks [bundleHeader_strict]+bundleHeader = L.C.fromChunks [bundleHeader_strict] -- | The number of bytes required to align an OSC value to the next -- 4-byte boundary.
Sound/OSC/Coding/Decode/Binary.hs view
@@ -6,7 +6,7 @@ import Control.Applicative {- base -} import Control.Monad (when) {- base -}-import Data.Binary.Get {- binary -}+import qualified Data.Binary.Get as G {- binary -} import qualified Data.Binary.IEEE754 as I {- data-binary-ieee754 -} import qualified Data.ByteString.Char8 as S.C {- bytestring -} import qualified Data.ByteString.Lazy as B {- bytestring -}@@ -18,51 +18,39 @@ import Sound.OSC.Time import Sound.OSC.Type --- | Isolate an action to operating within a fixed block of bytes. The--- action is required to consume all the bytes that it is isolated to.-isolate' :: Word32 -> Get a -> Get a-isolate' n m = do- s <- get_bytes n- case runGetOrFail m s of- Left (_, _, e) -> fail e- Right (s', _, a) ->- if B.null s'- then return a- else fail "isolate': not all bytes consumed"- -- | Get a 32 bit integer in big-endian byte order.-getInt32be :: Get Int32-getInt32be = fromIntegral <$> getWord32be+getInt32be :: G.Get Int32+getInt32be = fromIntegral <$> G.getWord32be -- | Get a 64 bit integer in big-endian byte order.-getInt64be :: Get Int64-getInt64be = fromIntegral <$> getWord64be+getInt64be :: G.Get Int64+getInt64be = fromIntegral <$> G.getWord64be -- | Get an aligned OSC string.-get_string :: Get String+get_string :: G.Get String get_string = do- s <- getLazyByteStringNul- skip (fromIntegral (align (B.length s + 1)))+ s <- G.getLazyByteStringNul+ G.skip (fromIntegral (align (B.length s + 1))) return $ C.unpack s -- | Get an aligned OSC string.-get_ascii :: Get ASCII+get_ascii :: G.Get ASCII get_ascii = do- s <- getLazyByteStringNul- skip (fromIntegral (align (B.length s + 1)))+ s <- G.getLazyByteStringNul+ G.skip (fromIntegral (align (B.length s + 1))) return (S.C.pack (C.unpack s)) -- | Get binary data prefixed by byte count.-get_bytes :: Word32 -> Get B.ByteString+get_bytes :: Word32 -> G.Get B.ByteString get_bytes n = do- b <- getLazyByteString (fromIntegral n)+ b <- G.getLazyByteString (fromIntegral n) if n /= fromIntegral (B.length b) then fail "get_bytes: end of stream"- else skip (fromIntegral (align n))+ else G.skip (fromIntegral (align n)) return b -- | Get an OSC datum.-get_datum :: Datum_Type -> Get Datum+get_datum :: Datum_Type -> G.Get Datum get_datum ty = case ty of 'i' -> Int32 <$> fromIntegral <$> getInt32be@@ -70,17 +58,17 @@ 'f' -> Float <$> realToFrac <$> I.getFloat32be 'd' -> Double <$> I.getFloat64be 's' -> ASCII_String <$> get_ascii- 'b' -> Blob <$> (get_bytes =<< getWord32be)- 't' -> TimeStamp <$> ntpi_to_ntpr <$> getWord64be- 'm' -> do b0 <- getWord8- b1 <- getWord8- b2 <- getWord8- b3 <- getWord8+ 'b' -> Blob <$> (get_bytes =<< G.getWord32be)+ 't' -> TimeStamp <$> ntpi_to_ntpr <$> G.getWord64be+ 'm' -> do b0 <- G.getWord8+ b1 <- G.getWord8+ b2 <- G.getWord8+ b3 <- G.getWord8 return $ Midi (MIDI b0 b1 b2 b3) _ -> fail ("get_datum: illegal type " ++ show ty) -- | Get an OSC 'Message'.-get_message :: Get Message+get_message :: G.Get Message get_message = do cmd <- get_string dsc <- get_ascii@@ -91,27 +79,27 @@ _ -> fail "get_message: invalid type descriptor string" -- | Get a sequence of OSC 'Message's, each one headed by its length.-get_message_seq :: Get [Message]+get_message_seq :: G.Get [Message] get_message_seq = do- b <- isEmpty+ b <- G.isEmpty if b then return [] else do- p <- flip isolate' get_message =<< getWord32be+ p <- flip G.isolate get_message . fromIntegral =<< G.getWord32be ps <- get_message_seq return (p:ps) -- | Get a bundle. Fail if bundle header is not found in packet.-get_bundle :: Get Bundle+get_bundle :: G.Get Bundle get_bundle = do- h <- getByteString (S.C.length bundleHeader_strict)+ h <- G.getByteString (S.C.length bundleHeader_strict) when (h /= bundleHeader_strict) (fail "get_bundle: not a bundle")- t <- ntpi_to_ntpr <$> getWord64be+ t <- ntpi_to_ntpr <$> G.getWord64be ps <- get_message_seq return $ Bundle t ps -- | Get an OSC 'Packet'.-getPacket :: Get Packet+getPacket :: G.Get Packet getPacket = (Packet_Bundle <$> get_bundle) <|> (Packet_Message <$> get_message) -- | Decode an OSC packet from a lazy ByteString.@@ -120,9 +108,9 @@ -- > in decodeOSC b == Message "/g_free" [Int 0] decodePacket :: B.ByteString -> Packet {-# INLINE decodePacket #-}-decodePacket = runGet getPacket+decodePacket = G.runGet getPacket -- | Decode an OSC packet from a strict ByteString. decodePacket_strict :: S.C.ByteString -> Packet {-# INLINE decodePacket_strict #-}-decodePacket_strict = runGet getPacket . B.fromChunks . (:[])+decodePacket_strict = G.runGet getPacket . B.fromChunks . (:[])
Sound/OSC/Datum.hs view
@@ -35,6 +35,7 @@ -- | 'C.unpack' of 'd_get'. -- -- > datum_string (d_put (C.pack "string")) == Just "string"+-- > map datum_string [string "string",Int32 5] == [Just "string",Nothing] datum_string :: Datum -> Maybe String datum_string = fmap C.unpack . datum_ascii
Sound/OSC/Type.hs view
@@ -25,6 +25,14 @@ -- | Type for ASCII strings (strict 'Char'8 'C.ByteString'). type ASCII = C.ByteString +-- | Type-specialised 'C.pack'.+ascii :: String -> ASCII+ascii = C.pack++-- | Type-specialised 'C.unpack'.+ascii_to_string :: ASCII -> String+ascii_to_string = C.unpack+ -- | Four-byte midi message. data MIDI = MIDI Word8 Word8 Word8 Word8 deriving (Eq,Show,Read)@@ -298,12 +306,26 @@ -- * Pretty printing --- | Pretty printer for 'Time' (truncate to 4 decimal places).+-- | Perhaps a precision value for floating point numbers.+type FP_Precision = Maybe Int++-- | Variant of 'showFFloat' that deletes trailing zeros. ----- > timePP (1/3) == "0.3333"-timePP :: Time -> String-timePP t = showGFloat (Just 4) t ""+-- > map (floatPP (Just 4)) [1,pi] == ["1.0","3.1416"]+floatPP :: RealFloat n => Maybe Int -> n -> String+floatPP p n =+ let s = showFFloat p n ""+ s' = dropWhile (== '0') (reverse s)+ in case s' of+ '.':_ -> reverse ('0' : s')+ _ -> reverse s' +-- | Pretty printer for 'Time'.+--+-- > timePP (Just 4) (1/3) == "0.3333"+timePP :: FP_Precision -> Time -> String+timePP = floatPP+ -- | Pretty printer for vectors. -- -- > vecPP [1::Int,2,3] == "<1,2,3>"@@ -314,36 +336,36 @@ -- -- > let d = [Int32 1,Float 1.2,string "str",midi (0,0x90,0x40,0x60)] -- > in map datumPP d == ["1","1.2","\"str\"","<0,144,64,96>"]-datumPP :: Datum -> String-datumPP d =+datumPP :: FP_Precision -> Datum -> String+datumPP p d = case d of Int32 n -> show n Int64 n -> show n- Float n -> show n- Double n -> show n+ Float n -> floatPP p n+ Double n -> floatPP p n ASCII_String s -> show (C.unpack s) Blob s -> show s- TimeStamp t -> timePP t- Midi (MIDI p q r s) -> vecPP [p,q,r,s]+ TimeStamp t -> timePP p t+ Midi (MIDI b1 b2 b3 b4) -> vecPP [b1,b2,b3,b4] -- | Pretty printer for 'Message'.-messagePP :: Message -> String-messagePP (Message a d) =- let d' = map datumPP d+messagePP :: FP_Precision -> Message -> String+messagePP p (Message a d) =+ let d' = map (datumPP p) d in unwords ("#message" : a : d') -- | Pretty printer for 'Bundle'.-bundlePP :: Bundle -> String-bundlePP (Bundle t m) =- let m' = intersperse ";" (map messagePP m)- in unwords ("#bundle" : timePP t : m')+bundlePP :: FP_Precision -> Bundle -> String+bundlePP p (Bundle t m) =+ let m' = intersperse ";" (map (messagePP p) m)+ in unwords ("#bundle" : timePP p t : m') -- | Pretty printer for 'Packet'.-packetPP :: Packet -> String-packetPP p =- case p of- Packet_Message m -> messagePP m- Packet_Bundle b -> bundlePP b+packetPP :: FP_Precision -> Packet -> String+packetPP p pkt =+ case pkt of+ Packet_Message m -> messagePP p m+ Packet_Bundle b -> bundlePP p b -- * Parser
hosc.cabal view
@@ -1,5 +1,5 @@ Name: hosc-Version: 0.14.1+Version: 0.15 Synopsis: Haskell Open Sound Control Description: @hosc@ implements a subset of the /Open Sound Control/ byte protocol, <http://opensoundcontrol.org/>.@@ -16,19 +16,19 @@ Composite modules are at "Sound.OSC" and "Sound.OSC.FD". License: GPL Category: Sound-Copyright: (c) Rohan Drape, Stefan Kersten and others, 2006-2013+Copyright: (c) Rohan Drape, Stefan Kersten and others, 2007-2014 Author: Rohan Drape, Stefan Kersten Maintainer: rd@slavepianos.org Stability: Experimental-Homepage: http://rd.slavepianos.org/?t=hosc-Tested-With: GHC == 7.6.1+Homepage: http://rd.slavepianos.org/t/hosc+Tested-With: GHC == 7.8.2 Build-Type: Simple Cabal-Version: >= 1.8 Data-Files: README Library Build-Depends: base == 4.*,- binary >= 0.6,+ binary >= 0.7.2, blaze-builder >= 0.3, bytestring, data-binary-ieee754,@@ -69,7 +69,7 @@ Sound.OSC.NFData Build-Depends: base == 4.*- , hosc == 0.14.*+ , hosc == 0.15.* , bytestring , criterion , deepseq@@ -85,7 +85,7 @@ Build-Depends: base == 4.* , bytestring >= 0.10- , hosc == 0.14.*+ , hosc == 0.15.* , QuickCheck >= 2 , test-framework >= 0.2 , test-framework-quickcheck2 >= 0.2