Safe Haskell | Safe-Inferred |
---|
Support for generating and parsing sysex files from a "spec" file.
TODO I need to support disjoint subsections, e.g. the different effects blocks depending on the value of an enum.
Synopsis
- type Parser a = B.ByteString -> Either.Either String a
- type Patch = (Patch.Patch, Common.Common ())
- parse_dir :: [Parser [Patch]] -> FilePath -> IO [Patch]
- parse_file :: [Parser [Patch]] -> FilePath -> B.ByteString -> Either.Either String [Patch]
- parse_builtins :: Int -> Parser [Patch] -> FilePath -> IO [Patch]
- try_parsers :: [Parser a] -> B.ByteString -> Either.Either String a
- initialize_program :: Int -> Midi.Program -> Patch -> Patch
- initialize_sysex :: B.ByteString -> Patch.Patch -> Patch.Patch
- add_file :: FilePath -> Common.Common a -> Common.Common a
- type RMap = Map Name Record
- data Record
- type Error = String
- type EnumName = Text
- data RecordType
- spec_to_rmap :: Specs -> RMap
- show_flat :: RMap -> [String]
- class RecordVal a where
- val_type :: RecordVal a => a -> RecordType
- record_type :: Record -> RecordType
- get_rmap :: forall a. RecordVal a => String -> RMap -> Either.Either String a
- put_rmap :: (Show a, RecordVal a) => String -> a -> RMap -> Either.Either String RMap
- expect_bytes :: B.ByteString -> B.ByteString -> Either.Either String B.ByteString
- hex :: B.ByteString -> String
- extract_sysex :: B.ByteString -> [B.ByteString]
- break_after :: (Word8 -> Bool) -> B.ByteString -> (B.ByteString, B.ByteString)
- data Config = Config {
- decode_num :: NumRange -> B.ByteString -> Int
- encode_num :: NumRange -> Int -> B.ByteString
- range_bytes :: NumRange -> Int
- config_8bit :: Config
- type EncodeM a = Except.ExceptT Error (Writer.Writer Builder.Builder) a
- encode :: Config -> Specs -> RMap -> Either.Either Error B.ByteString
- run_encode :: EncodeM () -> Either.Either Error B.ByteString
- encode_spec :: Config -> [String] -> RMap -> (Name, Spec) -> EncodeM ()
- encode_byte :: RMap -> [(Name, BitField)] -> Either.Either (Name, Error) Word8
- encode_range :: Range -> Record -> Either.Either String Int
- rmap_lookup :: RMap -> Name -> Either.Either Error Record
- decode :: Config -> Specs -> B.ByteString -> Either.Either Error (RMap, B.ByteString)
- decode_range :: Int -> Range -> Either.Either String Record
- decode_byte :: [Name] -> [(Name, BitField)] -> Word8 -> Either.Either String [(String, Record)]
- show_path :: [Name] -> String
- encode_bits :: [Int] -> [Word8] -> Word8
- decode_bits :: [Int] -> Word8 -> [Word8]
- to_signed :: (Integral a, Bits a) => Int -> a -> Int
- from_signed :: Int -> Int -> Word8
- type Specs = [(Name, Spec)]
- data Spec
- data Range
- type NumRange = (Int, Int)
- num_range :: Range -> NumRange
- range_signed :: Range -> Bool
- type BitField = (Bits, Range)
- type Name = String
- type Bits = Int
- type Bytes = Int
- spec_bytes :: Config -> Specs -> Int
- validate :: Specs -> Maybe String
- assert_valid :: Config -> String -> Int -> Specs -> Specs
- unsigned :: Int -> Spec
- ranged :: Int -> Int -> Spec
- signed :: Int -> Spec
- enum :: [EnumName] -> Spec
- bool :: Spec
- bits :: Int -> BitField
- ranged_bits :: Int -> (Int, Int) -> BitField
- enum_bits :: Int -> [EnumName] -> BitField
- bool_bit :: BitField
- unparsed_bits :: Int -> (String, BitField)
parse files
type Parser a = B.ByteString -> Either.Either String a Source #
type Patch = (Patch.Patch, Common.Common ()) Source #
parse_dir :: [Parser [Patch]] -> FilePath -> IO [Patch] Source #
For every file below the directory ending with .syx, try all of the given parsers on it.
parse_file :: [Parser [Patch]] -> FilePath -> B.ByteString -> Either.Either String [Patch] Source #
parse_builtins :: Int -> Parser [Patch] -> FilePath -> IO [Patch] Source #
Parse a file just like parse_file
. But this file is expected to be
the dump of the patches currently loaded in the synthesizer, and will be
given ProgramChange msgs for initialization rather than sysex dumps.
try_parsers :: [Parser a] -> B.ByteString -> Either.Either String a Source #
Try each parser in turn, and fail only if they all fail.
initialize_program :: Int -> Midi.Program -> Patch -> Patch Source #
Assume the sysex midi channel is 0.
add_file :: FilePath -> Common.Common a -> Common.Common a Source #
record
RMap RMap | A List is represented as an RMap with numbered keys. |
RUnion RMap | Which one this is is determined by an RStr elsewhere. |
RNum Int | |
RStr Text | |
RUnparsed B.ByteString |
data RecordType Source #
Instances
Show RecordType Source # | |
Defined in Instrument.Sysex showsPrec :: Int -> RecordType -> ShowS # show :: RecordType -> String # showList :: [RecordType] -> ShowS # | |
Eq RecordType Source # | |
Defined in Instrument.Sysex (==) :: RecordType -> RecordType -> Bool # (/=) :: RecordType -> RecordType -> Bool # |
spec_to_rmap :: Specs -> RMap Source #
Create a Record from a Spec, defaulting everything to 0, "", or the first enum val.
val_type :: RecordVal a => a -> RecordType Source #
record_type :: Record -> RecordType Source #
put_rmap :: (Show a, RecordVal a) => String -> a -> RMap -> Either.Either String RMap Source #
Put the given val into the rmap at a certain path. This only modifies existing fields, it won't create new ones, and you can't change the type of a field.
util
hex :: B.ByteString -> String Source #
extract_sysex :: B.ByteString -> [B.ByteString] Source #
Extract substrings delimited by sox_byte and eox_byte. Bytes not within the delimeters are stripped.
break_after :: (Word8 -> Bool) -> B.ByteString -> (B.ByteString, B.ByteString) Source #
config
Config | |
|
config_8bit :: Config Source #
Encode for 8bit bytes, where numbers are never more than 1 byte.
encode
type EncodeM a = Except.ExceptT Error (Writer.Writer Builder.Builder) a Source #
encode :: Config -> Specs -> RMap -> Either.Either Error B.ByteString Source #
run_encode :: EncodeM () -> Either.Either Error B.ByteString Source #
encode_byte :: RMap -> [(Name, BitField)] -> Either.Either (Name, Error) Word8 Source #
encode_range :: Range -> Record -> Either.Either String Int Source #
rmap_lookup :: RMap -> Name -> Either.Either Error Record Source #
decode
decode :: Config -> Specs -> B.ByteString -> Either.Either Error (RMap, B.ByteString) Source #
decode_range :: Int -> Range -> Either.Either String Record Source #
decode_byte :: [Name] -> [(Name, BitField)] -> Word8 -> Either.Either String [(String, Record)] Source #
bit fiddling
to_signed :: (Integral a, Bits a) => Int -> a -> Int Source #
Convert an n bit 2s complement word to a signed integer.
spec
Bits [(Name, BitField)] | A set of bitfields encoded in a single byte. The BitField widths must
add up to 8. They start at the least significant end of the byte, so
given |
Num Range | |
Str Bytes | |
SubSpec Specs | |
List Int Specs | |
Union Name Bytes [(EnumName, Specs)] | The content of this section depends on a previous enum value. The Name is the name of the enum to reference |
Unparsed Bytes | A chunk of unparsed bytes. If the name is "", then its considered unused padding. On input it will be ignored, and on output will become zeros. |
Constant B.ByteString | Assert that these bytes are set literally. This is useful for failing quickly when the required header isn't found. |
range_signed :: Range -> Bool Source #
assert_valid :: Config -> String -> Int -> Specs -> Specs Source #
Hokey runtime check to make sure the Specs is valid and has the expected size.