hunk ./Sound/OpenSoundControl/Type.hs 76 +-- | 'Datum' as integral number if 'Double', 'Float' or 'Int', else +-- 'Nothing'. +-- +-- > map datum_int [Int 5,Float 5.5,String "5"] == [Just 5,Just 5,Nothing] +datum_int :: Integral i => Datum -> Maybe i +datum_int d = + case d of + Int x -> Just (fromIntegral x) + Float x -> Just (floor x) + Double x -> Just (floor x) + _ -> Nothing + +-- | A 'fromJust' variant of 'datum_int'. +-- +-- > map datum_int' [Int 5,Float 5.5] == [5,5] +datum_int' :: Integral i => Datum -> i +datum_int' = fromJust . datum_int + hunk ./Sound/OpenSoundControl.hs 12 -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 +module Sound.OpenSoundControl (module O) where hunk ./Sound/OpenSoundControl.hs 14 -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. --- --- > 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) - --- | Trivial udp server. -udpServer :: String -> Int -> IO UDP -udpServer = udpServer' (C.encodeOSC,C.decodeOSC) - --- | Make a TCP connection. -openTCP :: String -> Int -> IO TCP -openTCP = openTCP' (C.encodeOSC,C.decodeOSC) - --- | A trivial TCP OSC server. -tcpServer :: Int -> (TCP -> IO ()) -> IO () -tcpServer = tcpServer' (C.encodeOSC,C.decodeOSC) +import Sound.OpenSoundControl.Class as O +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 addfile ./Sound/OpenSoundControl/Class.hs hunk ./Sound/OpenSoundControl/Class.hs 1 +-- | Typeclass for encoding OSC packets. +module Sound.OpenSoundControl.Class where + +import Sound.OpenSoundControl.Type +import Sound.OpenSoundControl.Coding + +class OSC o where + encodeOSC :: Coding c => o -> c + +instance OSC Message where + encodeOSC = encodePacket . Left + +instance OSC Bundle where + encodeOSC = encodePacket . Right + +encodeMessage :: Coding c => Message -> c +encodeMessage = encodeOSC + +encodeBundle :: Coding c => Message -> c +encodeBundle = encodeOSC + +decodeMessage :: Coding c => c -> Message +decodeMessage = packet_to_message . decodePacket + +decodeBundle :: Coding c => c -> Bundle +decodeBundle = packet_to_bundle . decodePacket hunk ./Sound/OpenSoundControl/Coding.hs 9 -import Sound.OpenSoundControl.Type (OSC) +import Sound.OpenSoundControl.Type hunk ./Sound/OpenSoundControl/Coding.hs 16 - encodeOSC :: OSC -> a + encodePacket :: Packet -> a hunk ./Sound/OpenSoundControl/Coding.hs 18 - decodeOSC :: a -> OSC + decodePacket :: a -> Packet hunk ./Sound/OpenSoundControl/Coding.hs 21 - encodeOSC = Builder.encodeOSC' - decodeOSC = Binary.decodeOSC' + encodePacket = Builder.encodePacket_strict + decodePacket = Binary.decodePacket_strict hunk ./Sound/OpenSoundControl/Coding.hs 25 - encodeOSC = Builder.encodeOSC - decodeOSC = Binary.decodeOSC + encodePacket = Builder.encodePacket + decodePacket = Binary.decodePacket hunk ./Sound/OpenSoundControl/Coding.hs 29 - encodeOSC = C.unpack . encodeOSC - decodeOSC = decodeOSC . C.pack + encodePacket = C.unpack . encodePacket + decodePacket = decodePacket . C.pack hunk ./Sound/OpenSoundControl/Coding.hs 32 --- | An 'encodeOSC' and 'decodeOSC' pair over 'B.ByteString'. -type Coder = (OSC -> B.ByteString,B.ByteString -> OSC) +-- | An 'encodePacket' and 'decodePacket' pair over 'B.ByteString'. +type Coder = (Packet -> B.ByteString,B.ByteString -> Packet) hunk ./Sound/OpenSoundControl/Coding/Coerce.hs 6 --- | Map a normalizing function over datum at an osc packet. -coerce :: (Datum -> Datum) -> OSC -> OSC -coerce f o = - case o of - Message s xs -> Message s (map f xs) - Bundle t xs -> Bundle t (map (coerce f) xs) +-- | Map a normalizing function over datum at an OSC 'Message'. +message_coerce :: (Datum -> Datum) -> Message -> Message +message_coerce f (Message s xs) = Message s (map f xs) + +-- | Map a normalizing function over datum at an OSC 'Bundle'. +bundle_coerce :: (Datum -> Datum) -> Bundle -> Bundle +bundle_coerce f (Bundle t xs) = Bundle t (map (message_coerce f) xs) hunk ./Sound/OpenSoundControl/Coding/Coerce.hs 38 -normalize :: OSC -> OSC -normalize = coerce f_to_d +--normalize :: OSC -> OSC +--normalize = coerce f_to_d hunk ./Sound/OpenSoundControl/Coding/Decode/Base.hs 3 -module Sound.OpenSoundControl.Coding.Decode.Base (decodeOSC) where +module Sound.OpenSoundControl.Coding.Decode.Base (decodeMessage + ,decodeBundle + ,decodePacket) where hunk ./Sound/OpenSoundControl/Coding/Decode/Base.hs 46 - 't' -> TimeStamp $ NTPi (decode_u64 b) + 't' -> TimeStamp (NTPi (decode_u64 b)) hunk ./Sound/OpenSoundControl/Coding/Decode/Base.hs 57 --- Decode an OSC message. -decode_message :: B.ByteString -> OSC -decode_message b = +-- | Decode an OSC 'Message'. +decodeMessage :: B.ByteString -> Message +decodeMessage b = hunk ./Sound/OpenSoundControl/Coding/Decode/Base.hs 68 -decode_message_seq :: B.ByteString -> [OSC] +decode_message_seq :: B.ByteString -> [Message] hunk ./Sound/OpenSoundControl/Coding/Decode/Base.hs 71 - m = decode_message $ b_drop 4 b - nxt = decode_message_seq $ b_drop (4+s) b + m = decodeMessage (b_drop 4 b) + nxt = decode_message_seq (b_drop (4+s) b) hunk ./Sound/OpenSoundControl/Coding/Decode/Base.hs 75 -decode_bundle :: B.ByteString -> OSC -decode_bundle b = +-- | Decode an OSC 'Bundle'. +decodeBundle :: B.ByteString -> Bundle +decodeBundle b = hunk ./Sound/OpenSoundControl/Coding/Decode/Base.hs 81 - ms = decode_message_seq $ b_drop (h+t) b + ms = decode_message_seq (b_drop (h+t) b) hunk ./Sound/OpenSoundControl/Coding/Decode/Base.hs 84 --- | Decode an OSC packet. +-- | Decode an OSC 'Packet'. hunk ./Sound/OpenSoundControl/Coding/Decode/Base.hs 87 --- > in decodeOSC b == Message "/g_free" [Int 0] -decodeOSC :: B.ByteString -> OSC -decodeOSC b = +-- > in decodePacket b == Message "/g_free" [Int 0] +decodePacket :: B.ByteString -> Either Message Bundle +decodePacket b = hunk ./Sound/OpenSoundControl/Coding/Decode/Base.hs 91 - then decode_bundle b - else decode_message b + then Right (decodeBundle b) + else Left (decodeMessage b) hunk ./Sound/OpenSoundControl/Coding/Decode/Binary.hs 2 -module Sound.OpenSoundControl.Coding.Decode.Binary (getOSC - ,decodeOSC - ,decodeOSC') where +module Sound.OpenSoundControl.Coding.Decode.Binary + (getPacket + ,decodePacket + ,decodePacket_strict) where hunk ./Sound/OpenSoundControl/Coding/Decode/Binary.hs 65 --- | Get an OSC message. -get_message :: Get OSC +-- | Get an OSC 'Message'. +get_message :: Get Message hunk ./Sound/OpenSoundControl/Coding/Decode/Binary.hs 76 --- | Get an OSC packet. -get_packet :: Get OSC -get_packet = do - h <- uncheckedLookAhead (L.length bundleHeader) - if h == bundleHeader - then get_bundle - else get_message - --- | Get a sequence of OSC messages, each one headed by its length. -get_packet_seq :: Get [OSC] -get_packet_seq = do +-- | Get a sequence of OSC 'Message's, each one headed by its length. +get_message_seq :: Get [Message] +get_message_seq = do hunk ./Sound/OpenSoundControl/Coding/Decode/Binary.hs 83 - p <- flip isolate get_packet =<< getWord32be - ps <- get_packet_seq + p <- flip isolate get_message =<< getWord32be + ps <- get_message_seq hunk ./Sound/OpenSoundControl/Coding/Decode/Binary.hs 87 -get_bundle :: Get OSC +get_bundle :: Get Bundle hunk ./Sound/OpenSoundControl/Coding/Decode/Binary.hs 91 - ps <- get_packet_seq + ps <- get_message_seq hunk ./Sound/OpenSoundControl/Coding/Decode/Binary.hs 94 --- | Get an OSC packet. -getOSC :: Get OSC -getOSC = get_packet +-- | Get an OSC 'Packet'. +getPacket :: Get Packet +getPacket = do + h <- uncheckedLookAhead (L.length bundleHeader) + if h == bundleHeader + then fmap Right get_bundle + else fmap Left get_message + hunk ./Sound/OpenSoundControl/Coding/Decode/Binary.hs 107 -decodeOSC :: L.ByteString -> OSC -{-# INLINE decodeOSC #-} -decodeOSC = runGet getOSC +decodePacket :: L.ByteString -> Packet +{-# INLINE decodePacket #-} +decodePacket = runGet getPacket hunk ./Sound/OpenSoundControl/Coding/Decode/Binary.hs 112 -decodeOSC' :: S.ByteString -> OSC -{-# INLINE decodeOSC' #-} -decodeOSC' = runGet getOSC . L.fromChunks . (:[]) +decodePacket_strict :: S.ByteString -> Either Message Bundle +{-# INLINE decodePacket_strict #-} +decodePacket_strict = runGet getPacket . L.fromChunks . (:[]) hunk ./Sound/OpenSoundControl/Coding/Encode/Base.hs 3 -module Sound.OpenSoundControl.Coding.Encode.Base (encodeOSC) where +module Sound.OpenSoundControl.Coding.Encode.Base (encodeMessage + ,encodeBundle + ,encodePacket) where hunk ./Sound/OpenSoundControl/Coding/Encode/Base.hs 34 --- Encode an OSC message. -encode_message :: String -> [Datum] -> B.ByteString -encode_message c l = +-- | Encode an OSC 'Message'. +encodeMessage :: Message -> B.ByteString +encodeMessage (Message c l) = hunk ./Sound/OpenSoundControl/Coding/Encode/Base.hs 41 --- Encode an OSC packet as an OSC blob. -encode_osc_blob :: OSC -> Datum -encode_osc_blob = Blob . encodeOSC +-- Encode an OSC 'Message' as an OSC blob. +encode_message_blob :: Message -> Datum +encode_message_blob = Blob . encodeMessage hunk ./Sound/OpenSoundControl/Coding/Encode/Base.hs 46 -encode_bundle_ntpi :: NTPi -> [OSC] -> B.ByteString +encode_bundle_ntpi :: NTPi -> [Message] -> B.ByteString hunk ./Sound/OpenSoundControl/Coding/Encode/Base.hs 50 - ,B.concat (map (encode_datum . encode_osc_blob) l) ] + ,B.concat (map (encode_datum . encode_message_blob) l) ] hunk ./Sound/OpenSoundControl/Coding/Encode/Base.hs 52 --- | Encode an OSC packet. -encodeOSC :: OSC -> B.ByteString -encodeOSC o = - case o of - Message c l -> encode_message c l +-- | Encode an OSC 'Bundle'. +encodeBundle :: Bundle -> B.ByteString +encodeBundle b = + case b of hunk ./Sound/OpenSoundControl/Coding/Encode/Base.hs 59 + +-- | Encode an OSC 'Packet'. +encodePacket :: Packet -> B.ByteString +encodePacket o = + case o of + Left m -> encodeMessage m + Right b -> encodeBundle b hunk ./Sound/OpenSoundControl/Coding/Encode/Builder.hs 2 -module Sound.OpenSoundControl.Coding.Encode.Builder (buildOSC - ,encodeOSC - ,encodeOSC') where +module Sound.OpenSoundControl.Coding.Encode.Builder + (build_packet + ,encodeMessage + ,encodeBundle + ,encodePacket + ,encodePacket_strict) where hunk ./Sound/OpenSoundControl/Coding/Encode/Builder.hs 18 -import Sound.OpenSoundControl.Type (Datum(..), OSC(..), tag) +import Sound.OpenSoundControl.Type hunk ./Sound/OpenSoundControl/Coding/Encode/Builder.hs 40 -build_datum (Int i) = B.fromInt32be (fromIntegral i) -build_datum (Float f) = B.fromWord32be (I.floatToWord (realToFrac f)) -build_datum (Double d) = B.fromWord64be (I.doubleToWord d) -build_datum (TimeStamp t) = B.fromWord64be (fromIntegral (as_ntpi t)) -build_datum (String s) = build_string s -build_datum (Midi (b0,b1,b2,b3)) = B.fromWord8s [b0,b1,b2,b3] -build_datum (Blob b) = build_bytes b +build_datum d = + case d of + Int i -> B.fromInt32be (fromIntegral i) + Float n -> B.fromWord32be (I.floatToWord (realToFrac n)) + Double n -> B.fromWord64be (I.doubleToWord n) + TimeStamp t -> B.fromWord64be (fromIntegral (as_ntpi t)) + String s -> build_string s + Midi (b0,b1,b2,b3) -> B.fromWord8s [b0,b1,b2,b3] + Blob b -> build_bytes b hunk ./Sound/OpenSoundControl/Coding/Encode/Builder.hs 50 --- Encode an OSC message. -build_message :: String -> [Datum] -> B.Builder -build_message c l = - mconcat [ build_string c - , build_string (descriptor l) - , mconcat $ map build_datum l ] +-- Encode an OSC 'Message'. +build_message :: Message -> B.Builder +build_message (Message c l) = + mconcat [build_string c + ,build_string (descriptor l) + ,mconcat $ map build_datum l] hunk ./Sound/OpenSoundControl/Coding/Encode/Builder.hs 57 --- Encode an OSC bundle. -build_bundle_ntpi :: NTPi -> [OSC] -> B.Builder +-- Encode an OSC 'Bundle'. +build_bundle_ntpi :: NTPi -> [Message] -> B.Builder hunk ./Sound/OpenSoundControl/Coding/Encode/Builder.hs 60 - mconcat [ B.fromLazyByteString bundleHeader - , B.fromWord64be t - , mconcat $ map (build_bytes . B.toLazyByteString . buildOSC) l ] + mconcat [B.fromLazyByteString bundleHeader + ,B.fromWord64be t + ,mconcat $ map (build_bytes . B.toLazyByteString . build_message) l] hunk ./Sound/OpenSoundControl/Coding/Encode/Builder.hs 64 --- | Builder monoid for an OSC packet. -buildOSC :: OSC -> B.Builder -buildOSC (Message c l) = build_message c l -buildOSC (Bundle (NTPi t) l) = build_bundle_ntpi t l -buildOSC (Bundle (NTPr t) l) = build_bundle_ntpi (ntpr_ntpi t) l -buildOSC (Bundle (UTCr t) l) = build_bundle_ntpi (utcr_ntpi t) l +-- | Builder monoid for an OSC 'Packet'. +build_packet :: Packet -> B.Builder +build_packet o = + case o of + Left m -> build_message m + Right (Bundle (NTPi t) l) -> build_bundle_ntpi t l + Right (Bundle (NTPr t) l) -> build_bundle_ntpi (ntpr_ntpi t) l + Right (Bundle (UTCr t) l) -> build_bundle_ntpi (utcr_ntpi t) l hunk ./Sound/OpenSoundControl/Coding/Encode/Builder.hs 73 --- | Encode an OSC packet to a lazy ByteString. +{-# INLINE encodeMessage #-} +{-# INLINE encodeBundle #-} +{-# INLINE encodePacket #-} +{-# INLINE encodePacket_strict #-} + +-- | Encode an OSC 'Message'. +encodeMessage :: Message -> L.ByteString +encodeMessage = B.toLazyByteString . build_packet . Left + +-- | Encode an OSC 'Bundle'. +encodeBundle :: Bundle -> L.ByteString +encodeBundle = B.toLazyByteString . build_packet . Right + +-- | Encode an OSC 'Packet' to a lazy 'L.ByteString'. hunk ./Sound/OpenSoundControl/Coding/Encode/Builder.hs 90 -encodeOSC :: OSC -> L.ByteString -{-# INLINE encodeOSC #-} -encodeOSC = B.toLazyByteString . buildOSC +encodePacket :: Packet -> L.ByteString +encodePacket = B.toLazyByteString . build_packet hunk ./Sound/OpenSoundControl/Coding/Encode/Builder.hs 93 --- | Encode an OSC packet to a strict ByteString. -encodeOSC' :: OSC -> S.ByteString -{-# INLINE encodeOSC' #-} -encodeOSC' = B.toByteString . buildOSC +-- | Encode an Packet packet to a strict ByteString. +encodePacket_strict :: Packet -> S.ByteString +encodePacket_strict = B.toByteString . build_packet hunk ./Sound/OpenSoundControl/Transport.hs 3 -module Sound.OpenSoundControl.Transport (Transport(..) - ,withTransport - ,recvT - ,waitFor,wait) where +module Sound.OpenSoundControl.Transport where hunk ./Sound/OpenSoundControl/Transport.hs 6 +import Sound.OpenSoundControl.Class hunk ./Sound/OpenSoundControl/Transport.hs 13 - send :: t -> OSC -> IO () + send :: OSC o => t -> o -> IO () hunk ./Sound/OpenSoundControl/Transport.hs 15 - recv :: t -> IO OSC + recv :: t -> IO Packet hunk ./Sound/OpenSoundControl/Transport.hs 19 --- Does the OSC message have the specified address. -has_address :: String -> OSC -> Bool -has_address x o = - case o of - Message y _ -> x == y - _ -> False - hunk ./Sound/OpenSoundControl/Transport.hs 31 --- | Variant that wraps 'recv' in an /n/ second 'timeout'. -recvT :: Transport t => Double -> t -> IO (Maybe OSC) +-- | Variant of 'recv' that implements an /n/ second 'timeout'. +recvT :: (Transport t) => Double -> t -> IO (Maybe Packet) hunk ./Sound/OpenSoundControl/Transport.hs 35 +-- | Variant of 'recv' that runs 'packet_to_message'. +recvMessage :: (Transport t) => t -> IO Message +recvMessage = fmap packet_to_message . recv + hunk ./Sound/OpenSoundControl/Transport.hs 41 -waitFor :: Transport t => t -> (OSC -> Maybe a) -> IO a +waitFor :: (Transport t) => t -> (Packet -> Maybe a) -> IO a hunk ./Sound/OpenSoundControl/Transport.hs 44 --- | A 'waitFor' for variant matching on the address string of --- incoming messages. -wait :: Transport t => t -> String -> IO OSC -wait t s = waitFor t (\o -> if has_address s o then Just o else Nothing) +-- | A 'waitFor' for variant matching on the 'Address_Pattern' of +-- incoming 'Packets'. +wait :: Transport t => t -> Address_Pattern -> IO Packet +wait t s = + let f o = if packet_has_address s o then Just o else Nothing + in waitFor t f + +-- | Variant on 'wait' that returns matching 'Packet' as a 'Message'. +waitMessage :: Transport t => t -> Address_Pattern -> IO Message +waitMessage t = fmap packet_to_message . wait t hunk ./Sound/OpenSoundControl/Transport/TCP.hs 1 +{-# Language Rank2Types #-} hunk ./Sound/OpenSoundControl/Transport/TCP.hs 3 -module Sound.OpenSoundControl.Transport.TCP (TCP(..) - ,openTCP' - ,tcpServer') where +module Sound.OpenSoundControl.Transport.TCP where hunk ./Sound/OpenSoundControl/Transport/TCP.hs 8 +import Sound.OpenSoundControl.Class hunk ./Sound/OpenSoundControl/Transport/TCP.hs 12 -import Sound.OpenSoundControl.Type hunk ./Sound/OpenSoundControl/Transport/TCP.hs 15 -data TCP = TCP {tcpEncode :: OSC -> B.ByteString - ,tcpDecode :: B.ByteString -> OSC - ,tcpHandle :: Handle} +data TCP = TCP {tcpHandle :: Handle} hunk ./Sound/OpenSoundControl/Transport/TCP.hs 18 - send (TCP enc _ fd) msg = - do let b = enc msg + send (TCP fd) msg = + do let b = encodeOSC msg hunk ./Sound/OpenSoundControl/Transport/TCP.hs 23 - recv (TCP _ dec fd) = + recv (TCP fd) = hunk ./Sound/OpenSoundControl/Transport/TCP.hs 26 - return (dec b1) - close (TCP _ _ fd) = hClose fd + return (decodePacket b1) + close (TCP fd) = hClose fd hunk ./Sound/OpenSoundControl/Transport/TCP.hs 29 --- | Make a TCP connection using specified coder. -openTCP' :: Coder -> String -> Int -> IO TCP -openTCP' (enc,dec) host = - liftM (TCP enc dec) . +-- | Make a 'TCP' connection. +openTCP :: String -> Int -> IO TCP +openTCP host = + liftM TCP . hunk ./Sound/OpenSoundControl/Transport/TCP.hs 37 --- | A trivial TCP OSC server using specified coder. -tcpServer' :: Coder -> Int -> (TCP -> IO ()) -> IO () -tcpServer' (enc,dec) p f = do +-- | A trivial 'TCP' /OSC/ server. +tcpServer' :: Int -> (TCP -> IO ()) -> IO () +tcpServer' p f = do hunk ./Sound/OpenSoundControl/Transport/TCP.hs 42 - f (TCP enc dec fd) + f (TCP fd) hunk ./Sound/OpenSoundControl/Transport/UDP.hs 2 -module Sound.OpenSoundControl.Transport.UDP (UDP(..),udpPort - ,openUDP' - ,udpServer' - ,sendTo,recvFrom) where +module Sound.OpenSoundControl.Transport.UDP where hunk ./Sound/OpenSoundControl/Transport/UDP.hs 10 +import Sound.OpenSoundControl.Class hunk ./Sound/OpenSoundControl/Transport/UDP.hs 16 -data UDP = UDP {udpEncode :: OSC -> B.ByteString - ,udpDecode :: B.ByteString -> OSC - ,udpSocket :: N.Socket} +data UDP = UDP {udpSocket :: N.Socket} hunk ./Sound/OpenSoundControl/Transport/UDP.hs 20 -udpPort (UDP _ _ fd) = fmap fromIntegral (N.socketPort fd) +udpPort (UDP fd) = fmap fromIntegral (N.socketPort fd) hunk ./Sound/OpenSoundControl/Transport/UDP.hs 23 - 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 + send (UDP fd) msg = C.send fd (encodeOSC msg) >> return () + recv (UDP fd) = liftM decodePacket (C.recv fd 8192) + close (UDP fd) = N.sClose fd hunk ./Sound/OpenSoundControl/Transport/UDP.hs 27 --- | Make a UDP connection with specified coder. -openUDP' :: Coder -> String -> Int -> IO UDP -openUDP' (enc,dec) host port = do +-- | Make a 'UDP' connection. +-- +-- > let t = openUDP "127.0.0.1" 57110 +-- > in withTransport t (\fd -> recvT 0.5 fd >>= print) +openUDP :: String -> Int -> IO UDP +openUDP host port = do hunk ./Sound/OpenSoundControl/Transport/UDP.hs 37 - return (UDP enc dec fd) + return (UDP fd) hunk ./Sound/OpenSoundControl/Transport/UDP.hs 39 --- | Trivial udp server with specified coder. -udpServer' :: Coder -> String -> Int -> IO UDP -udpServer' (enc,dec) host port = do +-- | Trivial 'UDP' server. +udpServer :: String -> Int -> IO UDP +udpServer host port = do hunk ./Sound/OpenSoundControl/Transport/UDP.hs 46 - return (UDP enc dec fd) + return (UDP fd) hunk ./Sound/OpenSoundControl/Transport/UDP.hs 49 -sendTo :: UDP -> OSC -> N.SockAddr -> IO () -sendTo (UDP enc _ fd) o a = do +sendTo :: OSC o => UDP -> o -> N.SockAddr -> IO () +sendTo (UDP fd) o a = do hunk ./Sound/OpenSoundControl/Transport/UDP.hs 52 - let o' = S.pack (B.unpack (enc o)) + let o' = S.pack (B.unpack (encodeOSC o)) hunk ./Sound/OpenSoundControl/Transport/UDP.hs 56 -recvFrom :: UDP -> IO (OSC, N.SockAddr) -recvFrom (UDP _ dec fd) = do +recvFrom :: UDP -> IO (Packet, N.SockAddr) +recvFrom (UDP fd) = do hunk ./Sound/OpenSoundControl/Transport/UDP.hs 61 - return (dec s',a) + return (decodePacket s',a) hunk ./Sound/OpenSoundControl/Type.hs 19 --- | An OSC packet. -data OSC = Message String [Datum] - | Bundle Time [OSC] - deriving (Eq,Read,Show) +-- | OSC address pattern. +type Address_Pattern = String hunk ./Sound/OpenSoundControl/Type.hs 22 --- | OSC bundles can be ordered (time ascending). Bundles and --- messages compare 'EQ'. -instance Ord OSC where +-- | An OSC message. +data Message = Message Address_Pattern [Datum] + deriving (Eq,Read,Show) + +-- | An OSC bundle. +data Bundle = Bundle Time [Message] + deriving (Eq,Read,Show) + +-- | An OSC 'Packet' is either a 'Message' or a 'Bundle'. +type Packet = Either Message Bundle + +-- | OSC 'Bundle's can be ordered (time ascending). +instance Ord Bundle where hunk ./Sound/OpenSoundControl/Type.hs 36 - compare _ _ = EQ hunk ./Sound/OpenSoundControl/Type.hs 49 --- | Bundle constructor. It is an 'error' if the 'OSC' list is empty. -bundle :: Time -> [OSC] -> OSC +-- | 'Bundle' constructor. It is an 'error' if the 'Message' list is +-- empty. +bundle :: Time -> [Message] -> Bundle hunk ./Sound/OpenSoundControl/Type.hs 57 --- | Message constructor. It is an 'error' if the address doesn't --- conform to the OSC specification. -message :: String -> [Datum] -> OSC +-- | 'Message' constructor. It is an 'error' if the 'Address_Pattern' +-- doesn't conform to the OSC specification. +message :: Address_Pattern -> [Datum] -> Message hunk ./Sound/OpenSoundControl/Type.hs 63 - _ -> error "message: ill-formed address" + _ -> error "message: ill-formed address pattern" hunk ./Sound/OpenSoundControl/Type.hs 117 + +-- | Does the OSC 'Message' have the specified 'Address_Pattern'. +message_has_address :: Address_Pattern -> Message -> Bool +message_has_address x (Message y _) = x == y + +-- | Does the OSC 'Message' have the specified 'Address_Pattern'. +bundle_has_address :: Address_Pattern -> Bundle -> Bool +bundle_has_address x b = + case b of + Bundle _ (m:_) -> message_has_address x m + _ -> error "bundle_has_address: empty bundle?" + +-- | Does 'Packet' have the specified 'Address_Pattern'. +packet_has_address :: Address_Pattern -> Packet -> Bool +packet_has_address x p = + case p of + Left m -> message_has_address x m + Right b -> bundle_has_address x b + +packet_to_message :: Packet -> Message +packet_to_message p = + case p of + Left m -> m + Right (Bundle _ (m:_)) -> m + Right _ -> error "packet_to_message: empty bundle?" + +packet_to_bundle :: Packet -> Bundle +packet_to_bundle p = + case p of + Left m -> Bundle immediately [m] + Right b -> b hunk ./hosc.cabal 29 + Sound.OpenSoundControl.Class