-- | Binary encoders and decoders. module Sound.Sc3.Server.Graphdef.Binary where import System.FilePath {- filepath -} import qualified Data.Binary.Get as Get {- binary -} import qualified Data.Binary.IEEE754 as IEEE754 {- data-binary-ieee754 -} import qualified Data.ByteString.Lazy as L {- bytestring -} import qualified Sound.Osc.Coding.Byte as Byte {- hosc -} import qualified Sound.Osc.Coding.Cast as Cast {- hosc -} import qualified Sound.Osc.Datum as Datum {- hosc -} import Sound.Sc3.Server.Graphdef {- hsc3 -} -- * Binary Get (version 0|1 or 2) -- | Get a 'Name' (Pascal string). get_pstr :: Get.Get Name get_pstr = do n <- fmap fromIntegral Get.getWord8 fmap Byte.decode_ascii (Get.getLazyByteString n) -- | Get_Functions for binary .scsyndef files. binary_get_f :: Get_Functions Get.Get binary_get_f = (get_pstr ,fmap fromIntegral Get.getInt8 ,fmap fromIntegral Get.getInt16be ,fmap fromIntegral Get.getInt32be ,fmap realToFrac IEEE754.getFloat32be) -- * Read {- | Read Graphdef from .scsyndef file. > dir = "/home/rohan/sw/rsc3-disassembler/scsyndef/" > pp nm = read_graphdef_file (dir ++ nm) >>= putStrLn . graphdef_stat > pp "simple.scsyndef" > pp "with-ctl.scsyndef" > pp "mce.scsyndef" > pp "mrg.scsyndef" -} read_graphdef_file :: FilePath -> IO Graphdef read_graphdef_file nm = do b <- L.readFile nm return (Get.runGet (get_graphdef binary_get_f) b) -- * Stat -- | 'read_graphdef_file' and run 'graphdef_stat'. scsyndef_stat :: FilePath -> IO String scsyndef_stat fn = do g <- read_graphdef_file fn return (graphdef_stat g) -- * Encode (version zero) -- | 'Encode_Functions' for 'L.ByteString' enc_bytestring :: Encode_Functions L.ByteString enc_bytestring = (L.concat,encode_pstr,Byte.encode_i8,Byte.encode_i16,Byte.encode_i32,encode_sample ,const L.empty) {- | Pascal (length prefixed) encoding of 'Name'. > L.unpack (encode_pstr (ascii "string")) == [6, 115, 116, 114, 105, 110, 103] -} encode_pstr :: Name -> L.ByteString encode_pstr = L.pack . Cast.str_pstr . Datum.ascii_to_string -- | Byte-encode 'Input'. encode_input :: Input -> L.ByteString encode_input = encode_input_f enc_bytestring -- | Byte-encode 'Control'. encode_control :: Control -> L.ByteString encode_control = encode_control_f enc_bytestring -- | Byte-encode 'Ugen'. encode_ugen :: Ugen -> L.ByteString encode_ugen = encode_ugen_f enc_bytestring -- | Encode 'Sample' as 32-bit IEEE float. encode_sample :: Sample -> L.ByteString encode_sample = Byte.encode_f32 . realToFrac -- | Encode 'Graphdef'. encode_graphdef :: Graphdef -> L.ByteString encode_graphdef = encode_graphdef_f enc_bytestring -- * IO -- | Write 'Graphdef' to indicated file. graphdefWrite :: FilePath -> Graphdef -> IO () graphdefWrite fn = L.writeFile fn . encode_graphdef -- | Write 'Graphdef' to indicated directory. The filename is the -- 'graphdef_name' with the appropriate extension (@scsyndef@). graphdefWrite_dir :: FilePath -> Graphdef -> IO () graphdefWrite_dir dir s = let fn = dir Datum.ascii_to_string (graphdef_name s) <.> "scsyndef" in graphdefWrite fn s