module Sound.OSC.Type.JSON where
import qualified Data.Aeson as A
import qualified Data.ByteString.Char8 as Char8
import qualified Data.ByteString.Lazy as Lazy
import qualified Data.ByteString.Lazy.UTF8 as UTF8
import qualified Sound.OSC as O
import qualified Sound.OSC.Datum.Datem as D
import qualified Sound.OSC.Type.JSON.Aeson as J
type Value = A.Value
encode_json_str :: Value -> String
encode_json_str = UTF8.toString . J.encode_json
decode_json_str :: String -> Maybe Value
decode_json_str = J.decode_json . UTF8.fromString
type Number = Either Integer Double
encode_number :: Number -> Value
encode_number = either J.encode_integer J.encode_double
encode_timestamp :: O.Time -> Value
encode_timestamp n = J.encode_assoc ("timestamp",J.encode_double n)
encode_integral :: Integral n => n -> Value
encode_integral = J.encode_integer . fromIntegral
encode_floating :: Real n => n -> Value
encode_floating = J.encode_double . realToFrac
encode_blob :: Lazy.ByteString -> Value
encode_blob b =
let a = J.encode_list (map encode_integral (Lazy.unpack b))
in J.encode_assoc ("blob",a)
encode_midi :: O.MIDI -> A.Value
encode_midi (O.MIDI p q r s) =
let a = J.encode_list (map encode_integral [p,q,r,s])
in J.encode_assoc ("midi",a)
encode_datum :: O.Datum -> Value
encode_datum d =
case d of
O.Int32 n -> encode_integral n
O.Int64 n -> encode_integral n
O.Float n -> encode_floating n
O.Double n -> encode_floating n
O.ASCII_String s -> J.encode_string (Char8.unpack s)
O.Blob b -> encode_blob b
O.TimeStamp n -> encode_timestamp n
O.Midi m -> encode_midi m
encode_message :: O.Message -> Value
encode_message (O.Message a d) =
let a' = J.encode_string a
d' = map encode_datum d
in J.encode_list (a' : d')
encode_bundle :: O.Bundle -> Value
encode_bundle (O.Bundle t m) =
let b = J.encode_string "#bundle"
t' = encode_timestamp t
m' = map encode_message m
in J.encode_list (b : t' : m')
encode_packet :: O.Packet -> Value
encode_packet p =
case p of
O.Packet_Message m -> encode_message m
O.Packet_Bundle b -> encode_bundle b
decode_message :: Value -> Maybe O.Message
decode_message j =
case J.decode_list j of
Just (m : d) ->
case J.decode_datum m of
Just (O.ASCII_String m') ->
mapM J.decode_datum d >>=
Just . O.message (Char8.unpack m')
_ -> Nothing
_ -> Nothing
decode_bundle :: Value -> Maybe O.Bundle
decode_bundle j =
case J.decode_list j of
Just (b : t : m) ->
case (D.datum_string =<< J.decode_datum b,J.decode_datum t) of
(Just "#bundle",Just (O.TimeStamp t')) ->
mapM decode_message m >>= Just . O.Bundle t'
_ -> Nothing
_ -> Nothing
decode_packet :: Value -> Maybe O.Packet
decode_packet v =
case decode_bundle v of
Just b -> Just (O.Packet_Bundle b)
Nothing -> case decode_message v of
Just m -> Just (O.Packet_Message m)
Nothing -> Nothing