-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Haskell Open Sound Control
--   
--   <tt>hosc</tt> implements a subset of the Open Sound Control byte
--   protocol, <a>http://opensoundcontrol.org/</a>.
--   
--   See <a>Sound.OSC.Core</a> or <a>Sound.OSC</a> or <a>Sound.OSC.FD</a>.
@package hosc
@version 0.16


-- | Bit-level type casts and byte layout string typecasts.
module Sound.OSC.Coding.Cast

-- | The IEEE byte representation of a float.
f32_w32 :: Float -> Word32

-- | Inverse of <a>f32_w32</a>.
w32_f32 :: Word32 -> Float

-- | The IEEE byte representation of a double.
f64_w64 :: Double -> Word64

-- | Inverse of <tt>f64_i64</tt>.
w64_f64 :: Word64 -> Double

-- | Transform a haskell string into a C string (a null suffixed byte
--   string).
str_cstr :: String -> [Word8]

-- | Inverse of <a>str_cstr</a>.
cstr_str :: [Word8] -> String

-- | Transform a haskell string to a pascal string (a length prefixed byte
--   string).
str_pstr :: String -> [Word8]

-- | Inverse of <a>str_pstr</a>.
pstr_str :: [Word8] -> String


-- | Type conversion.
module Sound.OSC.Coding.Convert

-- | Type specialised <a>fromIntegral</a>
int_to_word8 :: Int -> Word8

-- | Type specialised <a>fromIntegral</a>
int_to_word32 :: Int -> Word32

-- | Type specialised <a>fromIntegral</a>.
int_to_word16 :: Int -> Word16

-- | Type specialised <a>fromIntegral</a>
int_to_int8 :: Int -> Int8

-- | Type specialised <a>fromIntegral</a>
int_to_int16 :: Int -> Int16

-- | Type specialised <a>fromIntegral</a>
int_to_int32 :: Int -> Int32

-- | Type specialised <a>fromIntegral</a>
int8_to_int :: Int8 -> Int

-- | Type specialised <a>fromIntegral</a>
int16_to_int :: Int16 -> Int

-- | Type specialised <a>fromIntegral</a>
int32_to_int :: Int32 -> Int

-- | Type specialised <a>fromIntegral</a>
word8_to_int :: Word8 -> Int

-- | Type specialised <a>fromIntegral</a>
word16_to_int :: Word16 -> Int

-- | Type specialised <a>fromIntegral</a>
word32_to_int :: Word32 -> Int


-- | Byte-level coding utility functions. Plain forms are big-endian,
--   little-endian forms have <tt>_le</tt> suffix.
module Sound.OSC.Coding.Byte

-- | Encode a signed 8-bit integer.
encode_i8 :: Int -> ByteString

-- | Encode an un-signed 8-bit integer.
encode_u8 :: Int -> ByteString

-- | Type specialised <a>encode</a>.
--   
--   <pre>
--   encode_w16 0x0102 == L.pack [1,2]
--   </pre>
encode_w16 :: Word16 -> ByteString

-- | Little-endian.
--   
--   <pre>
--   encode_w16_le 0x0102 == L.pack [2,1]
--   </pre>
encode_w16_le :: Word16 -> ByteString

-- | Encode an un-signed 16-bit integer.
--   
--   <pre>
--   encode_u16 0x0102 == L.pack [1,2]
--   </pre>
encode_u16 :: Int -> ByteString

-- | Little-endian.
--   
--   <pre>
--   encode_u16_le 0x0102 == L.pack [2,1]
--   </pre>
encode_u16_le :: Int -> ByteString

-- | Encode a signed 16-bit integer.
encode_i16 :: Int -> ByteString

-- | Encode a signed 32-bit integer.
encode_i32 :: Int -> ByteString

-- | Type specialised <a>encode</a>.
encode_w32 :: Word32 -> ByteString

-- | Encode an unsigned 32-bit integer.
--   
--   <pre>
--   encode_u32 0x01020304 == L.pack [1,2,3,4]
--   </pre>
encode_u32 :: Int -> ByteString

-- | Little-endian variant of <a>encode_w32</a>.
encode_w32_le :: Word32 -> ByteString

-- | Little-endian.
--   
--   <pre>
--   encode_u32_le 0x01020304 == L.pack [4,3,2,1]
--   </pre>
encode_u32_le :: Int -> ByteString

-- | Encode a signed 64-bit integer.
encode_i64 :: Int64 -> ByteString

-- | Encode an unsigned 64-bit integer.
encode_u64 :: Word64 -> ByteString

-- | Encode a 32-bit IEEE floating point number.
encode_f32 :: Float -> ByteString

-- | Little-endian variant of <a>encode_f32</a>.
encode_f32_le :: Float -> ByteString

-- | Encode a 64-bit IEEE floating point number.
encode_f64 :: Double -> ByteString

-- | Encode an ASCII string (ASCII at Datum is an alias for a Char8
--   Bytetring).
encode_str :: ByteString -> ByteString

-- | Decode an un-signed 8-bit integer.
decode_u8 :: ByteString -> Int

-- | Decode a signed 8-bit integer.
decode_i8 :: ByteString -> Int

-- | Type specialised <a>decode</a>.
decode_word16 :: ByteString -> Word16

-- | Decode an unsigned 8-bit integer.
decode_u16 :: ByteString -> Int

-- | Little-endian variant of <a>decode_word16</a>.
decode_word16_le :: ByteString -> Word16

-- | Little-endian variant of <a>decode_u16</a>.
decode_u16_le :: ByteString -> Int

-- | Type specialised <a>decode</a>.
decode_int16 :: ByteString -> Int16

-- | Decode a signed 16-bit integer.
decode_i16 :: ByteString -> Int

-- | Little-endian variant of <a>decode_i16</a>.
decode_i16_le :: ByteString -> Int

-- | Decode a signed 32-bit integer.
decode_i32 :: ByteString -> Int

-- | Type specialised <a>decode</a>.
decode_word32 :: ByteString -> Word32

-- | Decode an unsigned 32-bit integer.
--   
--   <pre>
--   decode_u32 (L.pack [1,2,3,4]) == 0x01020304
--   </pre>
decode_u32 :: ByteString -> Int

-- | Little-endian variant of <a>decode_word32</a>.
decode_word32_le :: ByteString -> Word32

-- | Little-endian variant of decode_u32.
--   
--   <pre>
--   decode_u32_le (L.pack [1,2,3,4]) == 0x04030201
--   </pre>
decode_u32_le :: ByteString -> Int

-- | Type specialised <a>decode</a>.
decode_i64 :: ByteString -> Int64

-- | Type specialised <a>decode</a>.
decode_u64 :: ByteString -> Word64

-- | Decode a 32-bit IEEE floating point number.
decode_f32 :: ByteString -> Float

-- | Little-endian variant of <a>decode_f32</a>.
decode_f32_le :: ByteString -> Float

-- | Decode a 64-bit IEEE floating point number.
decode_f64 :: ByteString -> Double

-- | Decode an ASCII string, inverse of <a>encode_str</a>.
decode_str :: ByteString -> ByteString

-- | <a>decode_u32</a> of <a>hGet</a>.
read_u32 :: Handle -> IO Int

-- | <a>decode_u32_le</a> of <a>hGet</a>.
read_u32_le :: Handle -> IO Int

-- | <a>hPut</a> of <a>encode_u32</a>.
write_u32 :: Handle -> Int -> IO ()

-- | <a>hPut</a> of <a>encode_u32_le</a>.
write_u32_le :: Handle -> Int -> IO ()

-- | Bundle header as a (strict) <a>ByteString</a>.
bundleHeader_strict :: ByteString

-- | Bundle header as a lazy ByteString.
bundleHeader :: ByteString

-- | The number of bytes required to align an OSC value to the next 4-byte
--   boundary.
--   
--   <pre>
--   map align [0::Int .. 7] == [0,3,2,1,0,3,2,1]
--   </pre>
align :: (Num i, Bits i) => i -> i


-- | OSC related timing functions. OSC timestamps are <tt>NTP</tt> values,
--   <a>http://ntp.org/</a>.
module Sound.OSC.Time

-- | Type for integer (binary) representation of <tt>NTP</tt> time.
type NTPi = Word64

-- | <tt>NTP</tt> time in real-valued (fractional) form (ie.
--   <tt>ntpr</tt>).
type Time = Double

-- | Constant indicating a bundle to be executed immediately.
immediately :: Time

-- | <tt>Unix/Posix</tt> epoch time in real-valued (fractional) form.
type UT = Double

-- | Convert a real-valued NTP timestamp to an <a>NTPi</a> timestamp.
--   
--   <pre>
--   fmap ntpr_to_ntpi time
--   </pre>
ntpr_to_ntpi :: RealFrac n => n -> NTPi

-- | Convert an <a>NTPi</a> timestamp to a real-valued NTP timestamp.
ntpi_to_ntpr :: Fractional n => NTPi -> n

-- | Difference (in seconds) between <i>NTP</i> and <i>UT</i> epochs.
--   
--   <pre>
--   ntp_ut_epoch_diff / (24 * 60 * 60) == 25567
--   </pre>
ntp_ut_epoch_diff :: Num n => n

-- | Convert a <a>UT</a> timestamp to an <a>NTPi</a> timestamp.
ut_to_ntpi :: UT -> NTPi

-- | Convert <tt>Unix/Posix</tt> to <tt>NTP</tt>.
ut_to_ntpr :: Num n => n -> n

-- | Convert <tt>NTP</tt> to <tt>Unix/Posix</tt>.
ntpr_to_ut :: Num n => n -> n

-- | Convert <a>NTPi</a> to <tt>Unix/Posix</tt>.
ntpi_to_ut :: NTPi -> UT

-- | Convert <a>Time</a> to <a>POSIXTime</a>.
ntpr_to_posixtime :: Time -> POSIXTime

-- | Convert <a>POSIXTime</a> to <a>Time</a>.
posixtime_to_ntpr :: POSIXTime -> Time

-- | The time at 1970-01-01:00:00:00.
ut_epoch :: UTCTime

-- | Convert <a>UTCTime</a> to <tt>Unix/Posix</tt>.
utc_to_ut :: Fractional n => UTCTime -> n

-- | Read current real-valued <tt>NTP</tt> timestamp.
--   
--   <pre>
--   do {ct &lt;- fmap utc_to_ut T.getCurrentTime
--      ;pt &lt;- fmap realToFrac T.getPOSIXTime
--      ;print (pt - ct,pt - ct &lt; 1e-5)}
--   </pre>
time :: MonadIO m => m Time

-- | The <a>pauseThread</a> limit (in seconds). Values larger than this
--   require a different thread delay mechanism, see <a>sleepThread</a>.
--   The value is the number of microseconds in <tt>maxBound::Int</tt>.
pauseThreadLimit :: Fractional n => n

-- | Pause current thread for the indicated duration (in seconds), see
--   <a>pauseThreadLimit</a>.
pauseThread :: (MonadIO m, RealFrac n) => n -> m ()

-- | Type restricted <a>pauseThread</a>.
wait :: MonadIO m => Double -> m ()

-- | Pause current thread until the given <a>Time</a>, see
--   <a>pauseThreadLimit</a>.
pauseThreadUntil :: MonadIO m => Time -> m ()

-- | Sleep current thread for the indicated duration (in seconds). Divides
--   long sleeps into parts smaller than <a>pauseThreadLimit</a>.
sleepThread :: (RealFrac n, MonadIO m) => n -> m ()

-- | Sleep current thread until the given <a>Time</a>. Divides long sleeps
--   into parts smaller than <a>pauseThreadLimit</a>.
sleepThreadUntil :: MonadIO m => Time -> m ()

-- | Detailed 37-character ISO 8601 format, including fractional seconds
--   and '+0000' suffix.
iso_8601_fmt :: String

-- | Parse time according to <a>iso_8601_fmt</a>
--   
--   <pre>
--   iso_8601_to_utctime "2015-11-26T00:29:37,145875000000+0000"
--   </pre>
iso_8601_to_utctime :: String -> Maybe UTCTime

-- | UTC time in <a>iso_8601_fmt</a>.
--   
--   <pre>
--   tm &lt;- fmap (utctime_to_iso_8601 . T.posixSecondsToUTCTime) T.getPOSIXTime
--   (length tm,sum [4+1+2+1+2,1,2+1+2+1+2,1,12,1,4],sum [10,1,8,1,12,1,4])
--   </pre>
utctime_to_iso_8601 :: UTCTime -> String

-- | ISO 8601 of <a>Time</a>.
--   
--   <pre>
--   tm &lt;- fmap ntpr_to_iso_8601 time
--   import System.Process {- process -}
--   rawSystem "date" ["-d",tm]
--   </pre>
--   
--   <pre>
--   ntpr_to_iso_8601 (ntpi_to_ntpr 15708783354150518784)
--   </pre>
ntpr_to_iso_8601 :: Time -> String

-- | <a>Time</a> of ISO 8601.
--   
--   <pre>
--   fmap ntpr_to_ntpi (iso_8601_to_ntpr "2015-11-26T00:22:19,366058349609+0000")
--   </pre>
iso_8601_to_ntpr :: String -> Maybe Time

-- | Alias for <a>ntpr_to_iso_8601</a>.
--   
--   <pre>
--   fmap time_pp time
--   </pre>
time_pp :: Time -> String


-- | Data type for OSC datum.
module Sound.OSC.Datum

-- | Type enumerating Datum categories.
type Datum_Type = Char

-- | Type for ASCII strings (strict <a>Char</a>8 <a>ByteString</a>).
type ASCII = ByteString

-- | Type-specialised <a>pack</a>.
ascii :: String -> ASCII

-- | Type-specialised <a>unpack</a>.
ascii_to_string :: ASCII -> String

-- | Type for <a>Word8</a> arrays, these are stored with an <a>Int32</a>
--   length prefix.
type BLOB = ByteString

-- | Type-specialised <a>pack</a>.
blob_pack :: [Word8] -> BLOB

-- | Type-specialised <a>unpack</a>.
blob_unpack :: BLOB -> [Word8]

-- | Four-byte midi message: port-id, status-byte, data, data.
data MIDI
MIDI :: Word8 -> Word8 -> Word8 -> Word8 -> MIDI

-- | The basic elements of OSC messages.
data Datum
Int32 :: Int32 -> Datum
[d_int32] :: Datum -> Int32
Int64 :: Int64 -> Datum
[d_int64] :: Datum -> Int64
Float :: Float -> Datum
[d_float] :: Datum -> Float
Double :: Double -> Datum
[d_double] :: Datum -> Double
ASCII_String :: ASCII -> Datum
[d_ascii_string] :: Datum -> ASCII
Blob :: BLOB -> Datum
[d_blob] :: Datum -> BLOB
TimeStamp :: Time -> Datum
[d_timestamp] :: Datum -> Time
Midi :: MIDI -> Datum
[d_midi] :: Datum -> MIDI

-- | List of required data types (tag,name).
osc_types_required :: [(Datum_Type, String)]

-- | List of optional data types (tag,name).
osc_types_optional :: [(Datum_Type, String)]

-- | List of all data types (tag,name).
osc_types :: [(Datum_Type, String)]

-- | Lookup name of type.
osc_type_name :: Datum_Type -> Maybe String

-- | Erroring variant.
osc_type_name_err :: Datum_Type -> String

-- | Single character identifier of an OSC datum.
datum_tag :: Datum -> Datum_Type

-- | Type and name of <a>Datum</a>.
datum_type_name :: Datum -> (Datum_Type, String)

-- | <a>Datum</a> as <a>Integral</a> if Int32 or Int64.
--   
--   <pre>
--   let d = [Int32 5,Int64 5,Float 5.5,Double 5.5]
--   in map datum_integral d == [Just (5::Int),Just 5,Nothing,Nothing]
--   </pre>
datum_integral :: Integral i => Datum -> Maybe i

-- | <a>Datum</a> as <a>Floating</a> if Int32, Int64, Float, Double or
--   TimeStamp.
--   
--   <pre>
--   let d = [Int32 5,Int64 5,Float 5,Double 5,TimeStamp 5]
--   in Data.Maybe.mapMaybe datum_floating d == replicate 5 (5::Double)
--   </pre>
datum_floating :: Floating n => Datum -> Maybe n

-- | Type generalised Int32.
--   
--   <pre>
--   int32 (1::Int32) == int32 (1::Integer)
--   d_int32 (int32 (maxBound::Int32)) == maxBound
--   int32 (((2::Int) ^ (64::Int))::Int) == Int32 0
--   </pre>
int32 :: Integral n => n -> Datum

-- | Type generalised Int64.
--   
--   <pre>
--   int64 (1::Int32) == int64 (1::Integer)
--   d_int64 (int64 (maxBound::Int64)) == maxBound
--   </pre>
int64 :: Integral n => n -> Datum

-- | Type generalised Float.
--   
--   <pre>
--   float (1::Int) == float (1::Double)
--   floatRange (undefined::Float) == (-125,128)
--   isInfinite (d_float (float (encodeFloat 1 256 :: Double))) == True
--   </pre>
float :: Real n => n -> Datum

-- | Type generalised Double.
--   
--   <pre>
--   double (1::Int) == double (1::Double)
--   double (encodeFloat 1 256 :: Double) == Double 1.157920892373162e77
--   </pre>
double :: Real n => n -> Datum

-- | <a>ASCII_String</a> of <a>pack</a>.
--   
--   <pre>
--   string "string" == ASCII_String (Char8.pack "string")
--   </pre>
string :: String -> Datum

-- | Four-tuple variant of <a>Midi</a> <a>.</a> <a>MIDI</a>.
--   
--   <pre>
--   midi (0,0,0,0) == Midi (MIDI 0 0 0 0)
--   </pre>
midi :: (Word8, Word8, Word8, Word8) -> Datum

-- | Message argument types are given by a descriptor.
--   
--   <pre>
--   Char8.unpack (descriptor [Int32 1,Float 1,string "1"]) == ",ifs"
--   </pre>
descriptor :: [Datum] -> ASCII

-- | Descriptor tags are <tt>comma</tt> prefixed.
descriptor_tags :: ASCII -> ASCII

-- | Perhaps a precision value for floating point numbers.
type FP_Precision = Maybe Int

-- | Variant of <a>showFFloat</a> that deletes trailing zeros.
--   
--   <pre>
--   map (floatPP (Just 4)) [1,pi] == ["1.0","3.1416"]
--   </pre>
floatPP :: RealFloat n => Maybe Int -> n -> String

-- | Pretty printer for <a>Time</a>.
--   
--   <pre>
--   timePP (Just 4) (1/3) == "0.3333"
--   </pre>
timePP :: FP_Precision -> Time -> String

-- | Pretty printer for vectors.
--   
--   <pre>
--   vecPP [1::Int,2,3] == "&lt;1,2,3&gt;"
--   </pre>
vecPP :: Show a => [a] -> String

-- | Pretty printer for <a>Datum</a>.
--   
--   <pre>
--   let d = [Int32 1,Float 1.2,string "str",midi (0,0x90,0x40,0x60)]
--   in map (datumPP (Just 5)) d ==  ["1","1.2","\"str\"","&lt;0,144,64,96&gt;"]
--   </pre>
datumPP :: FP_Precision -> Datum -> String

-- | Variant of <a>datumPP</a> that appends the <a>datum_type_name</a>.
datum_pp_typed :: FP_Precision -> Datum -> String

-- | Variant of <a>read</a>.
readMaybe :: (Read a) => String -> Maybe a

-- | Given <a>Datum_Type</a> attempt to parse <a>Datum</a> at
--   <a>String</a>.
--   
--   <pre>
--   parse_datum 'i' "42" == Just (Int32 42)
--   parse_datum 'h' "42" == Just (Int64 42)
--   parse_datum 'f' "3.14159" == Just (Float 3.14159)
--   parse_datum 'd' "3.14159" == Just (Double 3.14159)
--   parse_datum 's' "\"pi\"" == Just (string "pi")
--   parse_datum 'b' "[112,105]" == Just (Blob (blob_pack [112,105]))
--   parse_datum 'm' "(0,144,60,90)" == Just (midi (0,144,60,90))
--   </pre>
parse_datum :: Datum_Type -> String -> Maybe Datum

-- | Erroring variant of <a>parse_datum</a>.
parse_datum_err :: Datum_Type -> String -> Datum
instance GHC.Show.Show Sound.OSC.Datum.Datum
instance GHC.Read.Read Sound.OSC.Datum.Datum
instance GHC.Classes.Eq Sound.OSC.Datum.Datum
instance GHC.Read.Read Sound.OSC.Datum.MIDI
instance GHC.Show.Show Sound.OSC.Datum.MIDI
instance GHC.Classes.Eq Sound.OSC.Datum.MIDI


-- | Data types for OSC messages, bundles and packets.
module Sound.OSC.Packet

-- | OSC address pattern. This is strictly an ASCII value, but it is very
--   common to pattern match on addresses and matching on <a>ByteString</a>
--   requires <tt>OverloadedStrings</tt>.
type Address_Pattern = String

-- | An OSC message.
data Message
Message :: Address_Pattern -> [Datum] -> Message
[messageAddress] :: Message -> Address_Pattern
[messageDatum] :: Message -> [Datum]

-- | <a>Message</a> constructor. It is an <a>error</a> if the
--   <a>Address_Pattern</a> doesn't conform to the OSC specification.
message :: Address_Pattern -> [Datum] -> Message

-- | An OSC bundle.
data Bundle
Bundle :: Time -> [Message] -> Bundle
[bundleTime] :: Bundle -> Time
[bundleMessages] :: Bundle -> [Message]

-- | <a>Bundle</a> constructor. It is an <a>error</a> if the <a>Message</a>
--   list is empty.
bundle :: Time -> [Message] -> Bundle

-- | An OSC <a>Packet</a> is either a <a>Message</a> or a <a>Bundle</a>.
data Packet
Packet_Message :: Message -> Packet
[packetMessage] :: Packet -> Message
Packet_Bundle :: Bundle -> Packet
[packetBundle] :: Packet -> Bundle

-- | <a>Packet_Bundle</a> <a>.</a> <a>bundle</a>.
p_bundle :: Time -> [Message] -> Packet

-- | <a>Packet_Message</a> <a>.</a> <a>message</a>.
p_message :: Address_Pattern -> [Datum] -> Packet

-- | The <a>Time</a> of <a>Packet</a>, if the <a>Packet</a> is a
--   <a>Message</a> this is <a>immediately</a>.
packetTime :: Packet -> Time

-- | Retrieve the set of <a>Message</a>s from a <a>Packet</a>.
packetMessages :: Packet -> [Message]

-- | If <a>Packet</a> is a <a>Message</a> add <a>immediately</a> timestamp,
--   else <a>id</a>.
packet_to_bundle :: Packet -> Bundle

-- | If <a>Packet</a> is a <a>Message</a> or a <a>Bundle</a> with an
--   <i>immediate</i> time tag and with one element, return the
--   <a>Message</a>, else <a>Nothing</a>.
packet_to_message :: Packet -> Maybe Message

-- | Is <a>Packet</a> immediate, ie. a <a>Bundle</a> with timestamp
--   <a>immediately</a>, or a plain Message.
packet_is_immediate :: Packet -> Bool

-- | Variant of <a>either</a> for <a>Packet</a>.
at_packet :: (Message -> a) -> (Bundle -> a) -> Packet -> a

-- | Does <a>Message</a> have the specified <a>Address_Pattern</a>.
message_has_address :: Address_Pattern -> Message -> Bool

-- | Do any of the <a>Message</a>s at <a>Bundle</a> have the specified
--   <a>Address_Pattern</a>.
bundle_has_address :: Address_Pattern -> Bundle -> Bool

-- | Does <a>Packet</a> have the specified <a>Address_Pattern</a>, ie.
--   <a>message_has_address</a> or <a>bundle_has_address</a>.
packet_has_address :: Address_Pattern -> Packet -> Bool

-- | Pretty printer for <a>Message</a>.
messagePP :: FP_Precision -> Message -> String

-- | Pretty printer for <a>Bundle</a>.
bundlePP :: FP_Precision -> Bundle -> String

-- | Pretty printer for <a>Packet</a>.
packetPP :: FP_Precision -> Packet -> String
instance GHC.Show.Show Sound.OSC.Packet.Packet
instance GHC.Read.Read Sound.OSC.Packet.Packet
instance GHC.Classes.Eq Sound.OSC.Packet.Packet
instance GHC.Show.Show Sound.OSC.Packet.Bundle
instance GHC.Read.Read Sound.OSC.Packet.Bundle
instance GHC.Classes.Eq Sound.OSC.Packet.Bundle
instance GHC.Show.Show Sound.OSC.Packet.Message
instance GHC.Read.Read Sound.OSC.Packet.Message
instance GHC.Classes.Eq Sound.OSC.Packet.Message
instance GHC.Classes.Ord Sound.OSC.Packet.Bundle


-- | Packet coercion.
module Sound.OSC.Packet.Coerce

-- | Map a normalising function over datum at an OSC <a>Message</a>.
message_coerce :: (Datum -> Datum) -> Message -> Message

-- | Map a normalising function over datum at an OSC <a>Bundle</a>.
bundle_coerce :: (Datum -> Datum) -> Bundle -> Bundle


-- | Unpack <a>Datum</a> lists into tuples.
module Sound.OSC.Datum.Unpack

-- | Strictly unpack to (s,f).
unpackS_sf :: [Datum] -> Maybe (String, Float)

-- | Strictly unpack to (i,f).
unpackS_if :: [Datum] -> Maybe (Int32, Float)

-- | Casting unpack to (s,d).
unpackC_sf :: [Datum] -> Maybe (String, Double)

-- | Casting unpack to (i,d).
unpackC_if :: [Datum] -> Maybe (Int, Double)


-- | Datum normalisation.
module Sound.OSC.Datum.Normalise

-- | Lift <a>Int32</a> to <a>Int64</a> and <a>Float</a> to <a>Double</a>.
--   
--   <pre>
--   map normalise_datum [Int32 1,Float 1] == [Int64 1,Double 1]
--   </pre>
normalise_datum :: Datum -> Datum

-- | A normalised <a>Message</a> has only <a>Int64</a> and <a>Double</a>
--   numerical values.
--   
--   <pre>
--   let m = message "/m" [Int32 0,Float 0]
--   in normalise_message m == message "/m" [Int64 0,Double 0]
--   </pre>
normalise_message :: Message -> Message

-- | A normalised <a>Bundle</a> has only <a>Int64</a> and <a>Double</a>
--   numerical values.
normalise_bundle :: Bundle -> Bundle

-- | Map a normalising function over datum at an OSC <a>Message</a>.
message_coerce :: (Datum -> Datum) -> Message -> Message

-- | Map a normalising function over datum at an OSC <a>Bundle</a>.
bundle_coerce :: (Datum -> Datum) -> Bundle -> Bundle

-- | Coerce <a>Int32</a>, <a>Int64</a> and <a>Float</a> to <a>Double</a>.
--   
--   <pre>
--   map datum_promote [Int32 5,Float 5] == [Double 5,Double 5]
--   </pre>
datum_promote :: Datum -> Datum

-- | <a>Datum</a> as <a>Int64</a> if <a>Int32</a>, <a>Int64</a>,
--   <a>Float</a> or <a>Double</a>.
--   
--   <pre>
--   let d = [Int32 5,Int64 5,Float 5.5,Double 5.5,string "5"]
--   in map datum_floor d == [Int64 5,Int64 5,Int64 5,Int64 5,string "5"]
--   </pre>
datum_floor :: Datum -> Datum


-- | A class for translating to and from <a>Datum</a>.
module Sound.OSC.Datum.Datem

-- | Class for translating to and from <a>Datum</a>. There are instances
--   for the direct <a>Datum</a> field types.
--   
--   <pre>
--   d_put (1::Int32) == Int32 1
--   d_put (1::Int64) == Int64 1
--   d_put (1::Float) == Float 1
--   d_put (1::Double) == Double 1
--   d_put (Char8.pack "str") == ASCII_String (Char8.pack "str")
--   d_put (Lazy.pack [37,37]) == Blob (blob_pack [37,37])
--   d_put (MIDI 0 0 0 0) == Midi (MIDI 0 0 0 0)
--   </pre>
--   
--   There are also instances for standard Haskell types.
--   
--   <pre>
--   d_put (1::Int) == Int64 1
--   d_put (1::Integer) == Int64 1
--   </pre>
class Datem a
d_put :: Datem a => a -> Datum
d_get :: Datem a => Datum -> Maybe a

-- | Error variant of <a>d_get</a>.
d_get_err :: Datem a => Datum -> a

-- | Type specialised <a>d_get</a>.
--   
--   <pre>
--   map datum_int32 [Int32 1,Float 1] == [Just 1,Nothing]
--   </pre>
datum_int32 :: Datum -> Maybe Int32

-- | Type specialised <a>d_get</a>.
datum_int64 :: Datum -> Maybe Int64

-- | Type specialised <a>d_get</a>.
datum_float :: Datum -> Maybe Float

-- | Type specialised <a>d_get</a>.
datum_double :: Datum -> Maybe Double

-- | Type specialised <a>d_get</a>.
--   
--   <pre>
--   datum_ascii (d_put (Char8.pack "string")) == Just (Char8.pack "string")
--   </pre>
datum_ascii :: Datum -> Maybe ASCII

-- | <a>unpack</a> of <a>d_get</a>.
--   
--   <pre>
--   datum_string (d_put (Char8.pack "string")) == Just "string"
--   map datum_string [string "string",Int32 5] == [Just "string",Nothing]
--   </pre>
datum_string :: Datum -> Maybe String

-- | Type specialised <a>d_get</a>.
datum_blob :: Datum -> Maybe ByteString

-- | <a>Maybe</a> variant of <a>d_timestamp</a>.
datum_timestamp :: Datum -> Maybe Time

-- | Type specialised <a>d_get</a>.
datum_midi :: Datum -> Maybe MIDI

-- | <a>Datum</a> as sequence of <a>Word8</a> if <a>ASCII_String</a>,
--   <a>Blob</a> or <a>Midi</a>.
--   
--   <pre>
--   let d = [string "5",Blob (Lazy.pack [53]),midi (0x00,0x90,0x40,0x60)]
--   in Data.Maybe.mapMaybe datum_sequence d == [[53],[53],[0,144,64,96]]
--   </pre>
datum_sequence :: Datum -> Maybe [Word8]
instance Sound.OSC.Datum.Datem.Datem GHC.Int.Int32
instance Sound.OSC.Datum.Datem.Datem GHC.Int.Int64
instance Sound.OSC.Datum.Datem.Datem GHC.Types.Int
instance Sound.OSC.Datum.Datem.Datem GHC.Integer.Type.Integer
instance Sound.OSC.Datum.Datem.Datem GHC.Types.Float
instance Sound.OSC.Datum.Datem.Datem GHC.Types.Double
instance Sound.OSC.Datum.Datem.Datem Data.ByteString.Internal.ByteString
instance Sound.OSC.Datum.Datem.Datem Data.ByteString.Lazy.Internal.ByteString
instance Sound.OSC.Datum.Datem.Datem Sound.OSC.Datum.MIDI


-- | Optimised encode function for OSC packets.
module Sound.OSC.Coding.Encode.Builder

-- | Builder for an OSC <a>Packet</a>.
build_packet :: Packet -> Builder

-- | Encode an OSC <a>Message</a>.
--   
--   <pre>
--   let b = L.pack [47,103,95,102,114,101,101,0,44,105,0,0,0,0,0,0]
--   encodeMessage (Message "/g_free" [Int32 0]) == b
--   </pre>
encodeMessage :: Message -> ByteString

-- | Encode an OSC <a>Bundle</a>.
encodeBundle :: Bundle -> ByteString

-- | Encode an OSC <a>Packet</a>.
encodePacket :: Packet -> ByteString

-- | Encode an OSC <a>Packet</a> to a strict <a>ByteString</a>.
encodePacket_strict :: Packet -> ByteString


-- | Base-level encode function for OSC packets (slow). For ordinary use
--   see <a>Builder</a>.
module Sound.OSC.Coding.Encode.Base

-- | Align byte string, if required.
extend :: Word8 -> ByteString -> ByteString

-- | Encode OSC <a>Datum</a>.
encode_datum :: Datum -> ByteString

-- | Encode OSC <a>Message</a>.
encodeMessage :: Message -> ByteString

-- | Encode OSC <a>Message</a> as an OSC blob.
encode_message_blob :: Message -> Datum

-- | Encode OSC <a>Bundle</a>.
encodeBundle :: Bundle -> ByteString

-- | Encode OSC <a>Packet</a>.
encodePacket :: Packet -> ByteString


-- | Optimised decode function for OSC packets.
module Sound.OSC.Coding.Decode.Binary

-- | Get an OSC <a>Packet</a>.
get_packet :: Get Packet

-- | Decode an OSC <a>Message</a> from a lazy ByteString.
--   
--   <pre>
--   let b = B.pack [47,103,95,102,114,101,101,0,44,105,0,0,0,0,0,0]
--   decodeMessage b == Message "/g_free" [Int32 0]
--   </pre>
decodeMessage :: ByteString -> Message

-- | Decode an OSC <a>Bundle</a> from a lazy ByteString.
decodeBundle :: ByteString -> Bundle

-- | Decode an OSC packet from a lazy ByteString.
--   
--   <pre>
--   let b = B.pack [47,103,95,102,114,101,101,0,44,105,0,0,0,0,0,0]
--   decodePacket b == Packet_Message (Message "/g_free" [Int32 0])
--   </pre>
decodePacket :: ByteString -> Packet

-- | Decode an OSC packet from a strict ByteString.
decodePacket_strict :: ByteString -> Packet


-- | A type-class to provide coding operations to different data types
--   using the same function names.
module Sound.OSC.Coding.Class

-- | Converting from and to binary packet representations.
class Coding a
encodePacket :: Coding a => Packet -> a
decodePacket :: Coding a => a -> Packet

-- | <a>encodePacket</a> <a>.</a> <a>Packet_Message</a>.
encodeMessage :: Coding c => Message -> c

-- | <a>encodePacket</a> <a>.</a> <a>Packet_Bundle</a>.
encodeBundle :: Coding c => Bundle -> c

-- | <a>packet_to_message</a> <a>.</a> <a>decodePacket</a>.
decodeMessage :: Coding c => c -> Maybe Message

-- | <a>packet_to_bundle</a> <a>.</a> <a>decodePacket</a>.
decodeBundle :: Coding c => c -> Bundle
instance Sound.OSC.Coding.Class.Coding Data.ByteString.Internal.ByteString
instance Sound.OSC.Coding.Class.Coding Data.ByteString.Lazy.Internal.ByteString


-- | Typeclass for encoding and decoding OSC packets.
module Sound.OSC.Packet.Class

-- | A type-class for values that can be translated to and from OSC
--   <a>Packet</a>s.
class OSC o
toPacket :: OSC o => o -> Packet
fromPacket :: OSC o => Packet -> Maybe o

-- | <a>encodePacket</a> <a>.</a> <a>toPacket</a>.
encodeOSC :: (Coding c, OSC o) => o -> c

-- | <a>fromPacket</a> <a>.</a> <a>decodePacket</a>.
decodeOSC :: (Coding c, OSC o) => c -> Maybe o
instance Sound.OSC.Packet.Class.OSC Sound.OSC.Packet.Message
instance Sound.OSC.Packet.Class.OSC Sound.OSC.Packet.Bundle
instance Sound.OSC.Packet.Class.OSC Sound.OSC.Packet.Packet


-- | Base-level decode function for OSC packets (slow). For ordinary use
--   see <a>Binary</a>.
module Sound.OSC.Coding.Decode.Base

-- | Decode an OSC <a>Message</a>.
decodeMessage :: ByteString -> Message

-- | Decode an OSC <a>Bundle</a>.
decodeBundle :: ByteString -> Bundle

-- | Decode an OSC <a>Packet</a>.
--   
--   <pre>
--   let b = B.pack [47,103,95,102,114,101,101,0,44,105,0,0,0,0,0,0]
--   in decodePacket b == Message "/g_free" [Int 0]
--   </pre>
decodePacket :: ByteString -> Packet


-- | Waiting (for replies).
module Sound.OSC.Wait

-- | Real valued variant of <a>timeout</a>.
timeout_r :: Double -> IO a -> IO (Maybe a)

-- | Repeat action until predicate <i>f</i> is <a>True</a> when applied to
--   result.
untilPredicate :: Monad m => (a -> Bool) -> m a -> m a

-- | Repeat action until <i>f</i> does not give <a>Nothing</a> when applied
--   to result.
untilMaybe :: Monad m => (a -> Maybe b) -> m a -> m b


-- | An abstract transport layer with implementations for <tt>UDP</tt> and
--   <tt>TCP</tt> transport.
module Sound.OSC.Transport.FD

-- | Abstract over the underlying transport protocol.
class Transport t

-- | Encode and send an OSC packet.
sendOSC :: (Transport t, OSC o) => t -> o -> IO ()

-- | Receive and decode an OSC packet.
recvPacket :: Transport t => t -> IO Packet

-- | Close an existing connection.
close :: Transport t => t -> IO ()

-- | Bracket OSC communication.
withTransport :: Transport t => IO t -> (t -> IO a) -> IO a

-- | Type restricted synonym for <a>sendOSC</a>.
sendMessage :: Transport t => t -> Message -> IO ()

-- | Type restricted synonym for <a>sendOSC</a>.
sendBundle :: Transport t => t -> Bundle -> IO ()

-- | Variant of <a>recvPacket</a> that runs <a>fromPacket</a>.
recvOSC :: (Transport t, OSC o) => t -> IO (Maybe o)

-- | Variant of <a>recvPacket</a> that runs <a>packet_to_bundle</a>.
recvBundle :: (Transport t) => t -> IO Bundle

-- | Variant of <a>recvPacket</a> that runs <a>packet_to_message</a>.
recvMessage :: (Transport t) => t -> IO (Maybe Message)

-- | Variant of <a>recvPacket</a> that runs <a>packetMessages</a>.
recvMessages :: (Transport t) => t -> IO [Message]

-- | Variant of <a>recvPacket</a> that implements an <i>n</i> second
--   <tt>timeout</tt>.
recvPacketTimeout :: (Transport t) => Double -> t -> IO (Maybe Packet)

-- | Wait for a <a>Packet</a> where the supplied predicate is <a>True</a>,
--   discarding intervening packets.
waitUntil :: (Transport t) => t -> (Packet -> Bool) -> IO Packet

-- | Wait for a <a>Packet</a> where the supplied function does not give
--   <a>Nothing</a>, discarding intervening packets.
waitFor :: (Transport t) => t -> (Packet -> Maybe a) -> IO a

-- | <a>waitUntil</a> <a>packet_is_immediate</a>.
waitImmediate :: Transport t => t -> IO Packet

-- | <a>waitFor</a> <a>packet_to_message</a>, ie. an incoming
--   <a>Message</a> or immediate mode <a>Bundle</a> with one element.
waitMessage :: Transport t => t -> IO Message

-- | A <a>waitFor</a> for variant using <a>packet_has_address</a> to match
--   on the <a>Address_Pattern</a> of incoming <tt>Packets</tt>.
waitAddress :: Transport t => t -> Address_Pattern -> IO Packet

-- | Variant on <a>waitAddress</a> that returns matching <a>Message</a>.
waitReply :: Transport t => t -> Address_Pattern -> IO Message

-- | Variant of <a>waitReply</a> that runs <a>messageDatum</a>.
waitDatum :: Transport t => t -> Address_Pattern -> IO [Datum]


-- | Monad class implementing an Open Sound Control transport.
module Sound.OSC.Transport.Monad

-- | Sender monad.
class Monad m => SendOSC m

-- | Encode and send an OSC packet.
sendOSC :: (SendOSC m, OSC o) => o -> m ()

-- | Receiver monad.
class Monad m => RecvOSC m

-- | Receive and decode an OSC packet.
recvPacket :: RecvOSC m => m Packet

-- | <a>DuplexOSC</a> is the union of <a>SendOSC</a> and <a>RecvOSC</a>.
class (SendOSC m, RecvOSC m) => DuplexOSC m

-- | <a>Transport</a> is <a>DuplexOSC</a> with a <a>MonadIO</a> constraint.
class (DuplexOSC m, MonadIO m) => Transport m

-- | Transport connection.
type Connection t a = ReaderT t IO a

-- | Bracket Open Sound Control communication.
withTransport :: Transport t => IO t -> Connection t a -> IO a

-- | Type restricted synonym for <a>sendOSC</a>.
sendMessage :: SendOSC m => Message -> m ()

-- | Type restricted synonym for <a>sendOSC</a>.
sendBundle :: SendOSC m => Bundle -> m ()

-- | Variant of <a>recvPacket</a> that runs <a>fromPacket</a>.
recvOSC :: (RecvOSC m, OSC o) => m (Maybe o)

-- | Variant of <a>recvPacket</a> that runs <a>packet_to_bundle</a>.
recvBundle :: (RecvOSC m) => m Bundle

-- | Variant of <a>recvPacket</a> that runs <a>packet_to_message</a>.
recvMessage :: (RecvOSC m) => m (Maybe Message)

-- | Erroring variant.
recvMessage_err :: RecvOSC m => m Message

-- | Variant of <a>recvPacket</a> that runs <a>packetMessages</a>.
recvMessages :: (RecvOSC m) => m [Message]

-- | Wait for a <a>Packet</a> where the supplied predicate is <a>True</a>,
--   discarding intervening packets.
waitUntil :: (RecvOSC m) => (Packet -> Bool) -> m Packet

-- | Wait for a <a>Packet</a> where the supplied function does not give
--   <a>Nothing</a>, discarding intervening packets.
waitFor :: (RecvOSC m) => (Packet -> Maybe a) -> m a

-- | <a>waitUntil</a> <a>packet_is_immediate</a>.
waitImmediate :: RecvOSC m => m Packet

-- | <a>waitFor</a> <a>packet_to_message</a>, ie. an incoming
--   <a>Message</a> or immediate mode <a>Bundle</a> with one element.
waitMessage :: RecvOSC m => m Message

-- | A <a>waitFor</a> for variant using <a>packet_has_address</a> to match
--   on the <a>Address_Pattern</a> of incoming <tt>Packets</tt>.
waitAddress :: RecvOSC m => Address_Pattern -> m Packet

-- | Variant on <a>waitAddress</a> that returns matching <a>Message</a>.
waitReply :: RecvOSC m => Address_Pattern -> m Message

-- | Variant of <a>waitReply</a> that runs <a>messageDatum</a>.
waitDatum :: RecvOSC m => Address_Pattern -> m [Datum]
instance (Sound.OSC.Transport.FD.Transport t, Control.Monad.IO.Class.MonadIO io) => Sound.OSC.Transport.Monad.Transport (Control.Monad.Trans.Reader.ReaderT t io)
instance (Sound.OSC.Transport.FD.Transport t, Control.Monad.IO.Class.MonadIO io) => Sound.OSC.Transport.Monad.DuplexOSC (Control.Monad.Trans.Reader.ReaderT t io)
instance (Sound.OSC.Transport.FD.Transport t, Control.Monad.IO.Class.MonadIO io) => Sound.OSC.Transport.Monad.RecvOSC (Control.Monad.Trans.Reader.ReaderT t io)
instance (Sound.OSC.Transport.FD.Transport t, Control.Monad.IO.Class.MonadIO io) => Sound.OSC.Transport.Monad.SendOSC (Control.Monad.Trans.Reader.ReaderT t io)


-- | OSC over UDP implementation.
module Sound.OSC.Transport.FD.UDP

-- | The UDP transport handle data type.
data UDP
UDP :: Socket -> UDP
[udpSocket] :: UDP -> Socket

-- | Return the port number associated with the UDP socket.
udpPort :: Integral n => UDP -> IO n

-- | Create and initialise UDP socket.
udp_socket :: (Socket -> SockAddr -> IO ()) -> String -> Int -> IO UDP

-- | Set option, ie. <a>Broadcast</a> or <a>RecvTimeOut</a>.
set_udp_opt :: SocketOption -> Int -> UDP -> IO ()

-- | Get option.
get_udp_opt :: SocketOption -> UDP -> IO Int

-- | Make a <a>UDP</a> connection.
--   
--   <pre>
--   let t = openUDP "127.0.0.1" 57110
--   in withTransport t (\fd -&gt; recvT 0.5 fd &gt;&gt;= print)
--   </pre>
openUDP :: String -> Int -> IO UDP

-- | Trivial <a>UDP</a> server socket.
--   
--   <pre>
--   import Control.Concurrent
--   </pre>
--   
--   <pre>
--   let {f fd = forever (recvMessage fd &gt;&gt;= print)
--       ;t = udpServer "127.0.0.1" 57300}
--   in void (forkIO (withTransport t f))
--   </pre>
--   
--   <pre>
--   let t = openUDP "127.0.0.1" 57300
--   in withTransport t (\fd -&gt; sendMessage fd (message "/n" []))
--   </pre>
udpServer :: String -> Int -> IO UDP

-- | Send variant to send to specified address.
sendTo :: OSC o => UDP -> o -> SockAddr -> IO ()

-- | Recv variant to collect message source address.
recvFrom :: UDP -> IO (Packet, SockAddr)
instance Sound.OSC.Transport.FD.Transport Sound.OSC.Transport.FD.UDP.UDP


-- | OSC over TCP implementation.
module Sound.OSC.Transport.FD.TCP

-- | The TCP transport handle data type.
data TCP
TCP :: Handle -> TCP
[tcpHandle] :: TCP -> Handle

-- | Make a <a>TCP</a> connection.
--   
--   <pre>
--   import Sound.OSC.Core
--   import Sound.OSC.Transport.FD
--   import Sound.OSC.Transport.FD.TCP
--   let t = openTCP "127.0.0.1" 57110
--   let m1 = message "/dumpOSC" [Int32 1]
--   let m2 = message "/g_new" [Int32 1]
--   withTransport t (\fd -&gt; let f = sendMessage fd in f m1 &gt;&gt; f m2)
--   </pre>
openTCP :: String -> Int -> IO TCP

-- | A trivial <a>TCP</a> <i>OSC</i> server.
tcpServer' :: Int -> (TCP -> IO ()) -> IO ()
instance Sound.OSC.Transport.FD.Transport Sound.OSC.Transport.FD.TCP.TCP


-- | Composite of non-transport related modules.
--   
--   Provides the <a>Datum</a>, <a>Message</a>, <a>Time</a>, <a>Bundle</a>
--   and <a>Packet</a> types and the coding functions <a>encodePacket</a>
--   and <a>decodePacket</a>.
--   
--   <pre>
--   import Sound.OSC.Core 
--   
--   let o = bundle immediately [message "/g_free" [Int32 0]]
--   let e = encodeBundle o
--   decodePacket e == Packet_Bundle o
--   </pre>
module Sound.OSC.Core


-- | Composite of <a>Sound.OSC.Core</a> and <a>Sound.OSC.Transport.FD</a>.
module Sound.OSC.FD


-- | Composite of <a>Sound.OSC.Core</a> and
--   <a>Sound.OSC.Transport.Monad</a>.
module Sound.OSC

-- | Monads in which <a>IO</a> computations may be embedded. Any monad
--   built by applying a sequence of monad transformers to the <a>IO</a>
--   monad will be an instance of this class.
--   
--   Instances should satisfy the following laws, which state that
--   <a>liftIO</a> is a transformer of monads:
--   
--   <ul>
--   <li><pre><a>liftIO</a> . <a>return</a> = <a>return</a></pre></li>
--   <li><pre><a>liftIO</a> (m &gt;&gt;= f) = <a>liftIO</a> m &gt;&gt;=
--   (<a>liftIO</a> . f)</pre></li>
--   </ul>
class Monad m => MonadIO (m :: * -> *)

-- | Lift a computation from the <a>IO</a> monad.
liftIO :: MonadIO m => IO a -> m a

-- | <tt>Unix/Posix</tt> epoch time in real-valued (fractional) form.
type UT = Double

-- | <tt>NTP</tt> time in real-valued (fractional) form (ie.
--   <tt>ntpr</tt>).
type Time = Double

-- | Type for integer (binary) representation of <tt>NTP</tt> time.
type NTPi = Word64

-- | Constant indicating a bundle to be executed immediately.
immediately :: Time

-- | Convert a real-valued NTP timestamp to an <a>NTPi</a> timestamp.
--   
--   <pre>
--   fmap ntpr_to_ntpi time
--   </pre>
ntpr_to_ntpi :: RealFrac n => n -> NTPi

-- | Convert an <a>NTPi</a> timestamp to a real-valued NTP timestamp.
ntpi_to_ntpr :: Fractional n => NTPi -> n

-- | Difference (in seconds) between <i>NTP</i> and <i>UT</i> epochs.
--   
--   <pre>
--   ntp_ut_epoch_diff / (24 * 60 * 60) == 25567
--   </pre>
ntp_ut_epoch_diff :: Num n => n

-- | Convert a <a>UT</a> timestamp to an <a>NTPi</a> timestamp.
ut_to_ntpi :: UT -> NTPi

-- | Convert <tt>Unix/Posix</tt> to <tt>NTP</tt>.
ut_to_ntpr :: Num n => n -> n

-- | Convert <tt>NTP</tt> to <tt>Unix/Posix</tt>.
ntpr_to_ut :: Num n => n -> n

-- | Convert <a>NTPi</a> to <tt>Unix/Posix</tt>.
ntpi_to_ut :: NTPi -> UT

-- | Convert <a>Time</a> to <a>POSIXTime</a>.
ntpr_to_posixtime :: Time -> POSIXTime

-- | Convert <a>POSIXTime</a> to <a>Time</a>.
posixtime_to_ntpr :: POSIXTime -> Time

-- | The time at 1970-01-01:00:00:00.
ut_epoch :: UTCTime

-- | Convert <a>UTCTime</a> to <tt>Unix/Posix</tt>.
utc_to_ut :: Fractional n => UTCTime -> n

-- | Read current real-valued <tt>NTP</tt> timestamp.
--   
--   <pre>
--   do {ct &lt;- fmap utc_to_ut T.getCurrentTime
--      ;pt &lt;- fmap realToFrac T.getPOSIXTime
--      ;print (pt - ct,pt - ct &lt; 1e-5)}
--   </pre>
time :: MonadIO m => m Time

-- | The <a>pauseThread</a> limit (in seconds). Values larger than this
--   require a different thread delay mechanism, see <a>sleepThread</a>.
--   The value is the number of microseconds in <tt>maxBound::Int</tt>.
pauseThreadLimit :: Fractional n => n

-- | Pause current thread for the indicated duration (in seconds), see
--   <a>pauseThreadLimit</a>.
pauseThread :: (MonadIO m, RealFrac n) => n -> m ()

-- | Type restricted <a>pauseThread</a>.
wait :: MonadIO m => Double -> m ()

-- | Pause current thread until the given <a>Time</a>, see
--   <a>pauseThreadLimit</a>.
pauseThreadUntil :: MonadIO m => Time -> m ()

-- | Sleep current thread for the indicated duration (in seconds). Divides
--   long sleeps into parts smaller than <a>pauseThreadLimit</a>.
sleepThread :: (RealFrac n, MonadIO m) => n -> m ()

-- | Sleep current thread until the given <a>Time</a>. Divides long sleeps
--   into parts smaller than <a>pauseThreadLimit</a>.
sleepThreadUntil :: MonadIO m => Time -> m ()

-- | Detailed 37-character ISO 8601 format, including fractional seconds
--   and '+0000' suffix.
iso_8601_fmt :: String

-- | Parse time according to <a>iso_8601_fmt</a>
--   
--   <pre>
--   iso_8601_to_utctime "2015-11-26T00:29:37,145875000000+0000"
--   </pre>
iso_8601_to_utctime :: String -> Maybe UTCTime

-- | UTC time in <a>iso_8601_fmt</a>.
--   
--   <pre>
--   tm &lt;- fmap (utctime_to_iso_8601 . T.posixSecondsToUTCTime) T.getPOSIXTime
--   (length tm,sum [4+1+2+1+2,1,2+1+2+1+2,1,12,1,4],sum [10,1,8,1,12,1,4])
--   </pre>
utctime_to_iso_8601 :: UTCTime -> String

-- | ISO 8601 of <a>Time</a>.
--   
--   <pre>
--   tm &lt;- fmap ntpr_to_iso_8601 time
--   import System.Process {- process -}
--   rawSystem "date" ["-d",tm]
--   </pre>
--   
--   <pre>
--   ntpr_to_iso_8601 (ntpi_to_ntpr 15708783354150518784)
--   </pre>
ntpr_to_iso_8601 :: Time -> String

-- | <a>Time</a> of ISO 8601.
--   
--   <pre>
--   fmap ntpr_to_ntpi (iso_8601_to_ntpr "2015-11-26T00:22:19,366058349609+0000")
--   </pre>
iso_8601_to_ntpr :: String -> Maybe Time

-- | Alias for <a>ntpr_to_iso_8601</a>.
--   
--   <pre>
--   fmap time_pp time
--   </pre>
time_pp :: Time -> String

-- | Perhaps a precision value for floating point numbers.
type FP_Precision = Maybe Int

-- | The basic elements of OSC messages.
data Datum
Int32 :: Int32 -> Datum
[d_int32] :: Datum -> Int32
Int64 :: Int64 -> Datum
[d_int64] :: Datum -> Int64
Float :: Float -> Datum
[d_float] :: Datum -> Float
Double :: Double -> Datum
[d_double] :: Datum -> Double
ASCII_String :: ASCII -> Datum
[d_ascii_string] :: Datum -> ASCII
Blob :: BLOB -> Datum
[d_blob] :: Datum -> BLOB
TimeStamp :: Time -> Datum
[d_timestamp] :: Datum -> Time
Midi :: MIDI -> Datum
[d_midi] :: Datum -> MIDI

-- | Four-byte midi message: port-id, status-byte, data, data.
data MIDI
MIDI :: Word8 -> Word8 -> Word8 -> Word8 -> MIDI

-- | Type for <a>Word8</a> arrays, these are stored with an <a>Int32</a>
--   length prefix.
type BLOB = ByteString

-- | Type for ASCII strings (strict <a>Char</a>8 <a>ByteString</a>).
type ASCII = ByteString

-- | Type enumerating Datum categories.
type Datum_Type = Char

-- | Type-specialised <a>pack</a>.
ascii :: String -> ASCII

-- | Type-specialised <a>unpack</a>.
ascii_to_string :: ASCII -> String

-- | Type-specialised <a>pack</a>.
blob_pack :: [Word8] -> BLOB

-- | Type-specialised <a>unpack</a>.
blob_unpack :: BLOB -> [Word8]

-- | List of required data types (tag,name).
osc_types_required :: [(Datum_Type, String)]

-- | List of optional data types (tag,name).
osc_types_optional :: [(Datum_Type, String)]

-- | List of all data types (tag,name).
osc_types :: [(Datum_Type, String)]

-- | Lookup name of type.
osc_type_name :: Datum_Type -> Maybe String

-- | Erroring variant.
osc_type_name_err :: Datum_Type -> String

-- | Single character identifier of an OSC datum.
datum_tag :: Datum -> Datum_Type

-- | Type and name of <a>Datum</a>.
datum_type_name :: Datum -> (Datum_Type, String)

-- | <a>Datum</a> as <a>Integral</a> if Int32 or Int64.
--   
--   <pre>
--   let d = [Int32 5,Int64 5,Float 5.5,Double 5.5]
--   in map datum_integral d == [Just (5::Int),Just 5,Nothing,Nothing]
--   </pre>
datum_integral :: Integral i => Datum -> Maybe i

-- | <a>Datum</a> as <a>Floating</a> if Int32, Int64, Float, Double or
--   TimeStamp.
--   
--   <pre>
--   let d = [Int32 5,Int64 5,Float 5,Double 5,TimeStamp 5]
--   in Data.Maybe.mapMaybe datum_floating d == replicate 5 (5::Double)
--   </pre>
datum_floating :: Floating n => Datum -> Maybe n

-- | Type generalised Int32.
--   
--   <pre>
--   int32 (1::Int32) == int32 (1::Integer)
--   d_int32 (int32 (maxBound::Int32)) == maxBound
--   int32 (((2::Int) ^ (64::Int))::Int) == Int32 0
--   </pre>
int32 :: Integral n => n -> Datum

-- | Type generalised Int64.
--   
--   <pre>
--   int64 (1::Int32) == int64 (1::Integer)
--   d_int64 (int64 (maxBound::Int64)) == maxBound
--   </pre>
int64 :: Integral n => n -> Datum

-- | Type generalised Float.
--   
--   <pre>
--   float (1::Int) == float (1::Double)
--   floatRange (undefined::Float) == (-125,128)
--   isInfinite (d_float (float (encodeFloat 1 256 :: Double))) == True
--   </pre>
float :: Real n => n -> Datum

-- | Type generalised Double.
--   
--   <pre>
--   double (1::Int) == double (1::Double)
--   double (encodeFloat 1 256 :: Double) == Double 1.157920892373162e77
--   </pre>
double :: Real n => n -> Datum

-- | <a>ASCII_String</a> of <a>pack</a>.
--   
--   <pre>
--   string "string" == ASCII_String (Char8.pack "string")
--   </pre>
string :: String -> Datum

-- | Four-tuple variant of <a>Midi</a> <a>.</a> <a>MIDI</a>.
--   
--   <pre>
--   midi (0,0,0,0) == Midi (MIDI 0 0 0 0)
--   </pre>
midi :: (Word8, Word8, Word8, Word8) -> Datum

-- | Message argument types are given by a descriptor.
--   
--   <pre>
--   Char8.unpack (descriptor [Int32 1,Float 1,string "1"]) == ",ifs"
--   </pre>
descriptor :: [Datum] -> ASCII

-- | Descriptor tags are <tt>comma</tt> prefixed.
descriptor_tags :: ASCII -> ASCII

-- | Variant of <a>showFFloat</a> that deletes trailing zeros.
--   
--   <pre>
--   map (floatPP (Just 4)) [1,pi] == ["1.0","3.1416"]
--   </pre>
floatPP :: RealFloat n => Maybe Int -> n -> String

-- | Pretty printer for <a>Time</a>.
--   
--   <pre>
--   timePP (Just 4) (1/3) == "0.3333"
--   </pre>
timePP :: FP_Precision -> Time -> String

-- | Pretty printer for vectors.
--   
--   <pre>
--   vecPP [1::Int,2,3] == "&lt;1,2,3&gt;"
--   </pre>
vecPP :: Show a => [a] -> String

-- | Pretty printer for <a>Datum</a>.
--   
--   <pre>
--   let d = [Int32 1,Float 1.2,string "str",midi (0,0x90,0x40,0x60)]
--   in map (datumPP (Just 5)) d ==  ["1","1.2","\"str\"","&lt;0,144,64,96&gt;"]
--   </pre>
datumPP :: FP_Precision -> Datum -> String

-- | Variant of <a>datumPP</a> that appends the <a>datum_type_name</a>.
datum_pp_typed :: FP_Precision -> Datum -> String

-- | Variant of <a>read</a>.
readMaybe :: (Read a) => String -> Maybe a

-- | Given <a>Datum_Type</a> attempt to parse <a>Datum</a> at
--   <a>String</a>.
--   
--   <pre>
--   parse_datum 'i' "42" == Just (Int32 42)
--   parse_datum 'h' "42" == Just (Int64 42)
--   parse_datum 'f' "3.14159" == Just (Float 3.14159)
--   parse_datum 'd' "3.14159" == Just (Double 3.14159)
--   parse_datum 's' "\"pi\"" == Just (string "pi")
--   parse_datum 'b' "[112,105]" == Just (Blob (blob_pack [112,105]))
--   parse_datum 'm' "(0,144,60,90)" == Just (midi (0,144,60,90))
--   </pre>
parse_datum :: Datum_Type -> String -> Maybe Datum

-- | Erroring variant of <a>parse_datum</a>.
parse_datum_err :: Datum_Type -> String -> Datum

-- | An OSC <a>Packet</a> is either a <a>Message</a> or a <a>Bundle</a>.
data Packet
Packet_Message :: Message -> Packet
[packetMessage] :: Packet -> Message
Packet_Bundle :: Bundle -> Packet
[packetBundle] :: Packet -> Bundle

-- | An OSC bundle.
data Bundle
Bundle :: Time -> [Message] -> Bundle
[bundleTime] :: Bundle -> Time
[bundleMessages] :: Bundle -> [Message]

-- | An OSC message.
data Message
Message :: Address_Pattern -> [Datum] -> Message
[messageAddress] :: Message -> Address_Pattern
[messageDatum] :: Message -> [Datum]

-- | OSC address pattern. This is strictly an ASCII value, but it is very
--   common to pattern match on addresses and matching on <a>ByteString</a>
--   requires <tt>OverloadedStrings</tt>.
type Address_Pattern = String

-- | <a>Message</a> constructor. It is an <a>error</a> if the
--   <a>Address_Pattern</a> doesn't conform to the OSC specification.
message :: Address_Pattern -> [Datum] -> Message

-- | <a>Bundle</a> constructor. It is an <a>error</a> if the <a>Message</a>
--   list is empty.
bundle :: Time -> [Message] -> Bundle

-- | <a>Packet_Bundle</a> <a>.</a> <a>bundle</a>.
p_bundle :: Time -> [Message] -> Packet

-- | <a>Packet_Message</a> <a>.</a> <a>message</a>.
p_message :: Address_Pattern -> [Datum] -> Packet

-- | The <a>Time</a> of <a>Packet</a>, if the <a>Packet</a> is a
--   <a>Message</a> this is <a>immediately</a>.
packetTime :: Packet -> Time

-- | Retrieve the set of <a>Message</a>s from a <a>Packet</a>.
packetMessages :: Packet -> [Message]

-- | If <a>Packet</a> is a <a>Message</a> add <a>immediately</a> timestamp,
--   else <a>id</a>.
packet_to_bundle :: Packet -> Bundle

-- | If <a>Packet</a> is a <a>Message</a> or a <a>Bundle</a> with an
--   <i>immediate</i> time tag and with one element, return the
--   <a>Message</a>, else <a>Nothing</a>.
packet_to_message :: Packet -> Maybe Message

-- | Is <a>Packet</a> immediate, ie. a <a>Bundle</a> with timestamp
--   <a>immediately</a>, or a plain Message.
packet_is_immediate :: Packet -> Bool

-- | Variant of <a>either</a> for <a>Packet</a>.
at_packet :: (Message -> a) -> (Bundle -> a) -> Packet -> a

-- | Does <a>Message</a> have the specified <a>Address_Pattern</a>.
message_has_address :: Address_Pattern -> Message -> Bool

-- | Do any of the <a>Message</a>s at <a>Bundle</a> have the specified
--   <a>Address_Pattern</a>.
bundle_has_address :: Address_Pattern -> Bundle -> Bool

-- | Does <a>Packet</a> have the specified <a>Address_Pattern</a>, ie.
--   <a>message_has_address</a> or <a>bundle_has_address</a>.
packet_has_address :: Address_Pattern -> Packet -> Bool

-- | Pretty printer for <a>Message</a>.
messagePP :: FP_Precision -> Message -> String

-- | Pretty printer for <a>Bundle</a>.
bundlePP :: FP_Precision -> Bundle -> String

-- | Pretty printer for <a>Packet</a>.
packetPP :: FP_Precision -> Packet -> String

-- | Builder for an OSC <a>Packet</a>.
build_packet :: Packet -> Builder

-- | Encode an OSC <a>Message</a>.
--   
--   <pre>
--   let b = L.pack [47,103,95,102,114,101,101,0,44,105,0,0,0,0,0,0]
--   encodeMessage (Message "/g_free" [Int32 0]) == b
--   </pre>
encodeMessage :: Message -> ByteString

-- | Encode an OSC <a>Bundle</a>.
encodeBundle :: Bundle -> ByteString

-- | Encode an OSC <a>Packet</a>.
encodePacket :: Packet -> ByteString

-- | Encode an OSC <a>Packet</a> to a strict <a>ByteString</a>.
encodePacket_strict :: Packet -> ByteString

-- | Get an OSC <a>Packet</a>.
get_packet :: Get Packet

-- | Decode an OSC <a>Message</a> from a lazy ByteString.
--   
--   <pre>
--   let b = B.pack [47,103,95,102,114,101,101,0,44,105,0,0,0,0,0,0]
--   decodeMessage b == Message "/g_free" [Int32 0]
--   </pre>
decodeMessage :: ByteString -> Message

-- | Decode an OSC <a>Bundle</a> from a lazy ByteString.
decodeBundle :: ByteString -> Bundle

-- | Decode an OSC packet from a lazy ByteString.
--   
--   <pre>
--   let b = B.pack [47,103,95,102,114,101,101,0,44,105,0,0,0,0,0,0]
--   decodePacket b == Packet_Message (Message "/g_free" [Int32 0])
--   </pre>
decodePacket :: ByteString -> Packet

-- | Decode an OSC packet from a strict ByteString.
decodePacket_strict :: ByteString -> Packet

-- | Real valued variant of <a>timeout</a>.
timeout_r :: Double -> IO a -> IO (Maybe a)

-- | Repeat action until predicate <i>f</i> is <a>True</a> when applied to
--   result.
untilPredicate :: Monad m => (a -> Bool) -> m a -> m a

-- | Repeat action until <i>f</i> does not give <a>Nothing</a> when applied
--   to result.
untilMaybe :: Monad m => (a -> Maybe b) -> m a -> m b

-- | Transport connection.
type Connection t a = ReaderT t IO a

-- | <a>Transport</a> is <a>DuplexOSC</a> with a <a>MonadIO</a> constraint.
class (DuplexOSC m, MonadIO m) => Transport m

-- | <a>DuplexOSC</a> is the union of <a>SendOSC</a> and <a>RecvOSC</a>.
class (SendOSC m, RecvOSC m) => DuplexOSC m

-- | Receiver monad.
class Monad m => RecvOSC m

-- | Receive and decode an OSC packet.
recvPacket :: RecvOSC m => m Packet

-- | Sender monad.
class Monad m => SendOSC m

-- | Encode and send an OSC packet.
sendOSC :: (SendOSC m, OSC o) => o -> m ()

-- | Bracket Open Sound Control communication.
withTransport :: Transport t => IO t -> Connection t a -> IO a

-- | Type restricted synonym for <a>sendOSC</a>.
sendMessage :: SendOSC m => Message -> m ()

-- | Type restricted synonym for <a>sendOSC</a>.
sendBundle :: SendOSC m => Bundle -> m ()

-- | Variant of <a>recvPacket</a> that runs <a>fromPacket</a>.
recvOSC :: (RecvOSC m, OSC o) => m (Maybe o)

-- | Variant of <a>recvPacket</a> that runs <a>packet_to_bundle</a>.
recvBundle :: (RecvOSC m) => m Bundle

-- | Variant of <a>recvPacket</a> that runs <a>packet_to_message</a>.
recvMessage :: (RecvOSC m) => m (Maybe Message)

-- | Erroring variant.
recvMessage_err :: RecvOSC m => m Message

-- | Variant of <a>recvPacket</a> that runs <a>packetMessages</a>.
recvMessages :: (RecvOSC m) => m [Message]

-- | Wait for a <a>Packet</a> where the supplied predicate is <a>True</a>,
--   discarding intervening packets.
waitUntil :: (RecvOSC m) => (Packet -> Bool) -> m Packet

-- | Wait for a <a>Packet</a> where the supplied function does not give
--   <a>Nothing</a>, discarding intervening packets.
waitFor :: (RecvOSC m) => (Packet -> Maybe a) -> m a

-- | <a>waitUntil</a> <a>packet_is_immediate</a>.
waitImmediate :: RecvOSC m => m Packet

-- | <a>waitFor</a> <a>packet_to_message</a>, ie. an incoming
--   <a>Message</a> or immediate mode <a>Bundle</a> with one element.
waitMessage :: RecvOSC m => m Message

-- | A <a>waitFor</a> for variant using <a>packet_has_address</a> to match
--   on the <a>Address_Pattern</a> of incoming <tt>Packets</tt>.
waitAddress :: RecvOSC m => Address_Pattern -> m Packet

-- | Variant on <a>waitAddress</a> that returns matching <a>Message</a>.
waitReply :: RecvOSC m => Address_Pattern -> m Message

-- | Variant of <a>waitReply</a> that runs <a>messageDatum</a>.
waitDatum :: RecvOSC m => Address_Pattern -> m [Datum]

-- | The UDP transport handle data type.
data UDP
UDP :: Socket -> UDP
[udpSocket] :: UDP -> Socket

-- | Return the port number associated with the UDP socket.
udpPort :: Integral n => UDP -> IO n

-- | Create and initialise UDP socket.
udp_socket :: (Socket -> SockAddr -> IO ()) -> String -> Int -> IO UDP

-- | Set option, ie. <a>Broadcast</a> or <a>RecvTimeOut</a>.
set_udp_opt :: SocketOption -> Int -> UDP -> IO ()

-- | Get option.
get_udp_opt :: SocketOption -> UDP -> IO Int

-- | Make a <a>UDP</a> connection.
--   
--   <pre>
--   let t = openUDP "127.0.0.1" 57110
--   in withTransport t (\fd -&gt; recvT 0.5 fd &gt;&gt;= print)
--   </pre>
openUDP :: String -> Int -> IO UDP

-- | Trivial <a>UDP</a> server socket.
--   
--   <pre>
--   import Control.Concurrent
--   </pre>
--   
--   <pre>
--   let {f fd = forever (recvMessage fd &gt;&gt;= print)
--       ;t = udpServer "127.0.0.1" 57300}
--   in void (forkIO (withTransport t f))
--   </pre>
--   
--   <pre>
--   let t = openUDP "127.0.0.1" 57300
--   in withTransport t (\fd -&gt; sendMessage fd (message "/n" []))
--   </pre>
udpServer :: String -> Int -> IO UDP

-- | Send variant to send to specified address.
sendTo :: OSC o => UDP -> o -> SockAddr -> IO ()

-- | Recv variant to collect message source address.
recvFrom :: UDP -> IO (Packet, SockAddr)

-- | The TCP transport handle data type.
data TCP
TCP :: Handle -> TCP
[tcpHandle] :: TCP -> Handle

-- | Make a <a>TCP</a> connection.
--   
--   <pre>
--   import Sound.OSC.Core
--   import Sound.OSC.Transport.FD
--   import Sound.OSC.Transport.FD.TCP
--   let t = openTCP "127.0.0.1" 57110
--   let m1 = message "/dumpOSC" [Int32 1]
--   let m2 = message "/g_new" [Int32 1]
--   withTransport t (\fd -&gt; let f = sendMessage fd in f m1 &gt;&gt; f m2)
--   </pre>
openTCP :: String -> Int -> IO TCP

-- | A trivial <a>TCP</a> <i>OSC</i> server.
tcpServer' :: Int -> (TCP -> IO ()) -> IO ()
