module Sound.Osc.Text where
import Control.Monad
import Data.Char
import Numeric
import Text.Printf
import qualified Text.ParserCombinators.Parsec as P
import Sound.Osc.Datum
import Sound.Osc.Packet
import Sound.Osc.Time
type FpPrecision = Maybe Int
showFloatWithPrecision :: RealFloat n => FpPrecision -> n -> String
showFloatWithPrecision :: forall n. RealFloat n => FpPrecision -> n -> [Char]
showFloatWithPrecision FpPrecision
p n
n =
let s :: [Char]
s = forall a. RealFloat a => FpPrecision -> a -> ShowS
showFFloat FpPrecision
p n
n [Char]
""
s' :: [Char]
s' = forall a. (a -> Bool) -> [a] -> [a]
dropWhile (forall a. Eq a => a -> a -> Bool
== Char
'0') (forall a. [a] -> [a]
reverse [Char]
s)
in case [Char]
s' of
Char
'.':[Char]
_ -> forall a. [a] -> [a]
reverse (Char
'0' forall a. a -> [a] -> [a]
: [Char]
s')
[Char]
_ -> forall a. [a] -> [a]
reverse [Char]
s'
showBytes :: [Int] -> String
showBytes :: [Int] -> [Char]
showBytes = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (forall r. PrintfType r => [Char] -> r
printf [Char]
"%02x")
escapeString :: String -> String
escapeString :: ShowS
escapeString [Char]
txt =
case [Char]
txt of
[] -> []
Char
c:[Char]
txt' -> if Char
c forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Char]
"\\\t\n " then Char
'\\' forall a. a -> [a] -> [a]
: Char
c forall a. a -> [a] -> [a]
: ShowS
escapeString [Char]
txt' else Char
c forall a. a -> [a] -> [a]
: ShowS
escapeString [Char]
txt'
showDatum :: FpPrecision -> Datum -> String
showDatum :: FpPrecision -> Datum -> [Char]
showDatum FpPrecision
p Datum
d =
case Datum
d of
Int32 Int32
n -> forall a. Show a => a -> [Char]
show Int32
n
Int64 Int64
n -> forall a. Show a => a -> [Char]
show Int64
n
Float Float
n -> forall n. RealFloat n => FpPrecision -> n -> [Char]
showFloatWithPrecision FpPrecision
p Float
n
Double Double
n -> forall n. RealFloat n => FpPrecision -> n -> [Char]
showFloatWithPrecision FpPrecision
p Double
n
AsciiString Ascii
s -> ShowS
escapeString (Ascii -> [Char]
ascii_to_string Ascii
s)
Blob Blob
s -> [Int] -> [Char]
showBytes (Blob -> [Int]
blob_unpack_int Blob
s)
TimeStamp Double
t -> forall a. Show a => a -> [Char]
show (Double -> Ntp64
ntpr_to_ntpi Double
t)
Midi MidiData
m -> [Int] -> [Char]
showBytes (MidiData -> [Int]
midi_unpack_int MidiData
m)
showMessage :: FpPrecision -> Message -> String
showMessage :: FpPrecision -> Message -> [Char]
showMessage FpPrecision
precision Message
aMessage =
[[Char]] -> [Char]
unwords
[Message -> [Char]
messageAddress Message
aMessage
,Message -> [Char]
messageSignature Message
aMessage
,[[Char]] -> [Char]
unwords (forall a b. (a -> b) -> [a] -> [b]
map (FpPrecision -> Datum -> [Char]
showDatum FpPrecision
precision) (Message -> [Datum]
messageDatum Message
aMessage))]
showBundle :: FpPrecision -> Bundle -> String
showBundle :: FpPrecision -> Bundle -> [Char]
showBundle FpPrecision
precision Bundle
aBundle =
let messages :: [Message]
messages = Bundle -> [Message]
bundleMessages Bundle
aBundle
in [[Char]] -> [Char]
unwords
[[Char]
"#bundle"
,forall a. Show a => a -> [Char]
show (Double -> Ntp64
ntpr_to_ntpi (Bundle -> Double
bundleTime Bundle
aBundle))
,forall a. Show a => a -> [Char]
show (forall (t :: * -> *) a. Foldable t => t a -> Int
length [Message]
messages)
,[[Char]] -> [Char]
unwords (forall a b. (a -> b) -> [a] -> [b]
map (FpPrecision -> Message -> [Char]
showMessage FpPrecision
precision) [Message]
messages)]
showPacket :: FpPrecision -> Packet -> String
showPacket :: FpPrecision -> Packet -> [Char]
showPacket FpPrecision
precision = forall a. (Message -> a) -> (Bundle -> a) -> Packet -> a
at_packet (FpPrecision -> Message -> [Char]
showMessage FpPrecision
precision) (FpPrecision -> Bundle -> [Char]
showBundle FpPrecision
precision)
type P a = P.GenParser Char () a
(>>~) :: Monad m => m t -> m u -> m t
m t
p >>~ :: forall (m :: * -> *) t u. Monad m => m t -> m u -> m t
>>~ m u
q = m t
p forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \t
x -> m u
q forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return t
x
lexemeP :: P t -> P t
lexemeP :: forall t. P t -> P t
lexemeP P t
p = P t
p forall (m :: * -> *) t u. Monad m => m t -> m u -> m t
>>~ forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
P.many forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
P.space
stringCharP :: P Char
stringCharP :: P Char
stringCharP = (forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'\\' forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
P.space) forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
P.<|> forall s (m :: * -> *) u.
Stream s m Char =>
(Char -> Bool) -> ParsecT s u m Char
P.satisfy (\Char
c -> Bool -> Bool
not (Char -> Bool
isSpace Char
c))
stringP :: P String
stringP :: P [Char]
stringP = forall t. P t -> P t
lexemeP (forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
P.many1 P Char
stringCharP)
oscAddressP :: P String
oscAddressP :: P [Char]
oscAddressP = do
Char
forwardSlash <- forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'/'
[Char]
address <- P [Char]
stringP
forall (m :: * -> *) a. Monad m => a -> m a
return (Char
forwardSlash forall a. a -> [a] -> [a]
: [Char]
address)
oscSignatureP :: P String
oscSignatureP :: P [Char]
oscSignatureP = forall t. P t -> P t
lexemeP (do
Char
comma <- forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
','
[Char]
types <- forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
P.many1 (forall s (m :: * -> *) u.
Stream s m Char =>
[Char] -> ParsecT s u m Char
P.oneOf [Char]
"ifsbhtdm")
forall (m :: * -> *) a. Monad m => a -> m a
return (Char
comma forall a. a -> [a] -> [a]
: [Char]
types))
digitP :: P Char
digitP :: P Char
digitP = forall s (m :: * -> *) u.
Stream s m Char =>
[Char] -> ParsecT s u m Char
P.oneOf [Char]
"0123456789"
allowNegativeP :: Num n => P n -> P n
allowNegativeP :: forall n. Num n => P n -> P n
allowNegativeP P n
p = do
let optionMaybe :: ParsecT s u m a -> ParsecT s u m (Maybe a)
optionMaybe ParsecT s u m a
x = forall s (m :: * -> *) t a u.
Stream s m t =>
a -> ParsecT s u m a -> ParsecT s u m a
P.option forall a. Maybe a
Nothing (forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM forall a. a -> Maybe a
Just ParsecT s u m a
x)
Maybe Char
maybeNegative <- forall {s} {m :: * -> *} {t} {u} {a}.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m (Maybe a)
optionMaybe (forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'-')
n
number <- P n
p
forall (m :: * -> *) a. Monad m => a -> m a
return (forall b a. b -> (a -> b) -> Maybe a -> b
maybe n
number (forall a b. a -> b -> a
const (forall a. Num a => a -> a
negate n
number)) Maybe Char
maybeNegative)
nonNegativeIntegerP :: (Integral n, Read n) => P n
nonNegativeIntegerP :: forall n. (Integral n, Read n) => P n
nonNegativeIntegerP = forall t. P t -> P t
lexemeP (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. Read a => [Char] -> a
read (forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
P.many1 P Char
digitP))
integerP :: (Integral n, Read n) => P n
integerP :: forall n. (Integral n, Read n) => P n
integerP = forall n. Num n => P n -> P n
allowNegativeP forall n. (Integral n, Read n) => P n
nonNegativeIntegerP
nonNegativeFloatP :: (Fractional n, Read n) => P n
nonNegativeFloatP :: forall n. (Fractional n, Read n) => P n
nonNegativeFloatP = forall t. P t -> P t
lexemeP (do
[Char]
integerPart <- forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
P.many1 P Char
digitP
Char
_ <- forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'.'
[Char]
fractionalPart <- forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
P.many1 P Char
digitP
forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. Read a => [Char] -> a
read (forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Char]
integerPart, [Char]
".", [Char]
fractionalPart])))
floatP :: (Fractional n, Read n) => P n
floatP :: forall n. (Fractional n, Read n) => P n
floatP = forall n. Num n => P n -> P n
allowNegativeP forall n. (Fractional n, Read n) => P n
nonNegativeFloatP
hexdigitP :: P Char
hexdigitP :: P Char
hexdigitP = forall s (m :: * -> *) u.
Stream s m Char =>
[Char] -> ParsecT s u m Char
P.oneOf [Char]
"0123456789abcdef"
byteP :: (Integral n, Read n) => P n
byteP :: forall n. (Integral n, Read n) => P n
byteP = do
Char
c1 <- P Char
hexdigitP
Char
c2 <- P Char
hexdigitP
case forall a. (Eq a, Num a) => ReadS a
readHex [Char
c1, Char
c2] of
[(n
r,[Char]
"")] -> forall (m :: * -> *) a. Monad m => a -> m a
return n
r
[(n, [Char])]
_ -> forall a. HasCallStack => [Char] -> a
error [Char]
"byteP?"
byteSeqP :: (Integral n, Read n) => P [n]
byteSeqP :: forall n. (Integral n, Read n) => P [n]
byteSeqP = forall t. P t -> P t
lexemeP (forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m [a]
P.many1 forall n. (Integral n, Read n) => P n
byteP)
datumP :: Char -> P Datum
datumP :: Char -> P Datum
datumP Char
typeChar = do
case Char
typeChar of
Char
'i' -> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Int32 -> Datum
Int32 forall n. (Integral n, Read n) => P n
integerP
Char
'f' -> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Float -> Datum
Float forall n. (Fractional n, Read n) => P n
floatP
Char
's' -> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Char] -> Datum
string P [Char]
stringP
Char
'b' -> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Word8] -> Datum
blob forall n. (Integral n, Read n) => P [n]
byteSeqP
Char
'h' -> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Int64 -> Datum
Int64 forall n. (Integral n, Read n) => P n
integerP
Char
'd' -> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Double -> Datum
Double forall n. (Fractional n, Read n) => P n
floatP
Char
'm' -> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (MidiData -> Datum
Midi forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Word8] -> MidiData
midi_pack) (forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
4 forall n. (Integral n, Read n) => P n
byteP)
Char
't' -> forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Double -> Datum
TimeStamp forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ntp64 -> Double
ntpi_to_ntpr) forall n. (Integral n, Read n) => P n
integerP
Char
_ -> forall a. HasCallStack => [Char] -> a
error [Char]
"datumP: type?"
messageP :: P Message
messageP :: P Message
messageP = do
[Char]
address <- P [Char]
oscAddressP
[Char]
typeSignature <- P [Char]
oscSignatureP
[Datum]
datum <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Char -> P Datum
datumP (forall a. [a] -> [a]
tail [Char]
typeSignature)
forall (m :: * -> *) a. Monad m => a -> m a
return ([Char] -> [Datum] -> Message
Message [Char]
address [Datum]
datum)
bundleTagP :: P String
bundleTagP :: P [Char]
bundleTagP = forall t. P t -> P t
lexemeP (forall s (m :: * -> *) u.
Stream s m Char =>
[Char] -> ParsecT s u m [Char]
P.string [Char]
"#bundle")
bundleP :: P Bundle
bundleP :: P Bundle
bundleP = do
[Char]
_ <- P [Char]
bundleTagP
Double
timestamp <- forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Ntp64 -> Double
ntpi_to_ntpr forall n. (Integral n, Read n) => P n
integerP
Int
messageCount <- forall n. (Integral n, Read n) => P n
integerP
[Message]
messages <- forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
replicateM Int
messageCount P Message
messageP
forall (m :: * -> *) a. Monad m => a -> m a
return (Double -> [Message] -> Bundle
Bundle Double
timestamp [Message]
messages)
packetP :: P Packet
packetP :: P Packet
packetP = (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Bundle -> Packet
Packet_Bundle P Bundle
bundleP) forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
P.<|> (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Message -> Packet
Packet_Message P Message
messageP)
runP :: P t -> String -> t
runP :: forall t. P t -> [Char] -> t
runP P t
p [Char]
txt =
case forall s t a.
Stream s Identity t =>
Parsec s () a -> [Char] -> s -> Either ParseError a
P.parse P t
p [Char]
"" [Char]
txt of
Left ParseError
err -> forall a. HasCallStack => [Char] -> a
error (forall a. Show a => a -> [Char]
show ParseError
err)
Right t
r -> t
r
parseDatum :: Char -> String -> Datum
parseDatum :: Char -> [Char] -> Datum
parseDatum Char
typ = forall t. P t -> [Char] -> t
runP (Char -> P Datum
datumP Char
typ)
parseMessage :: String -> Message
parseMessage :: [Char] -> Message
parseMessage = forall t. P t -> [Char] -> t
runP P Message
messageP
parseBundle :: String -> Bundle
parseBundle :: [Char] -> Bundle
parseBundle = forall t. P t -> [Char] -> t
runP P Bundle
bundleP
parsePacket :: String -> Packet
parsePacket :: [Char] -> Packet
parsePacket = forall t. P t -> [Char] -> t
runP P Packet
packetP