module Sound.MIDI.Message.System.Exclusive (
T(..), get, getIncomplete, put,
) where
import qualified Sound.MIDI.Manufacturer as Manufacturer
import Sound.MIDI.IO (ByteList)
import Sound.MIDI.Parser.Primitive
import qualified Sound.MIDI.Parser.Class as Parser
import qualified Sound.MIDI.Writer.Basic as Writer
import Sound.MIDI.Monoid ((+#+))
import qualified Control.Monad.Trans.Class as MT
import qualified Control.Monad.Exception.Asynchronous as Async
import Data.Maybe (fromMaybe, )
data T =
Commercial Manufacturer.T ByteList
| NonCommercial ByteList
| NonRealTime NonRealTime
| RealTime RealTime
newtype NonRealTime = NonRealTimeCons ByteList
newtype RealTime = RealTimeCons ByteList
get :: Parser.C parser => Parser.Fragile parser T
get =
do (Async.Exceptional err sysex) <- getIncomplete
maybe (return sysex) Parser.giveUp err
getIncomplete :: Parser.C parser => Parser.Partial (Parser.Fragile parser) T
getIncomplete =
do manu <- Manufacturer.get
incBody <- MT.lift getBody
return $ flip fmap incBody $ \body ->
fromMaybe (Commercial manu body) $
lookup manu $
(Manufacturer.nonCommercial, NonCommercial body) :
(Manufacturer.nonRealTime, NonRealTime $ NonRealTimeCons body) :
(Manufacturer.realTime, RealTime $ RealTimeCons body) :
[]
getBody :: Parser.C parser => Parser.Partial parser ByteList
getBody = Parser.until (0xf7 ==) getByte
put :: Writer.C writer => T -> writer
put sysex =
case sysex of
Commercial manu body ->
Manufacturer.put manu +#+
Writer.putByteList body
NonCommercial body ->
Manufacturer.put Manufacturer.nonCommercial +#+
Writer.putByteList body
NonRealTime (NonRealTimeCons body) ->
Manufacturer.put Manufacturer.nonRealTime +#+
Writer.putByteList body
RealTime (RealTimeCons body) ->
Manufacturer.put Manufacturer.realTime +#+
Writer.putByteList body