module Sound.MIDI.File.Event.SystemExclusive
   (T(..), get, put, ) where

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 Control.Monad (liftM, )



{-# DEPRECATED T "implement this data type properly" #-}
{- |
There are three forms of System Exclusive Messages in MIDI files:
monolithic, chopped into packets, escape form (with unrestricted binary data).

Currently we only support first and last type explicitly.
But we leave the trailing 0xF7 markers
which can be used to detect whether the messages are actually meant as packets.

Since I don't know where manufacturer information is in the packets form,
I omit manufacturer handling for now.
-}
data T =
     Regular ByteList   -- F0
   | Escape  ByteList   -- F7
     deriving (Int -> T -> ShowS
[T] -> ShowS
T -> String
(Int -> T -> ShowS) -> (T -> String) -> ([T] -> ShowS) -> Show T
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [T] -> ShowS
$cshowList :: [T] -> ShowS
show :: T -> String
$cshow :: T -> String
showsPrec :: Int -> T -> ShowS
$cshowsPrec :: Int -> T -> ShowS
Show, T -> T -> Bool
(T -> T -> Bool) -> (T -> T -> Bool) -> Eq T
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: T -> T -> Bool
$c/= :: T -> T -> Bool
== :: T -> T -> Bool
$c== :: T -> T -> Bool
Eq, Eq T
Eq T
-> (T -> T -> Ordering)
-> (T -> T -> Bool)
-> (T -> T -> Bool)
-> (T -> T -> Bool)
-> (T -> T -> Bool)
-> (T -> T -> T)
-> (T -> T -> T)
-> Ord T
T -> T -> Bool
T -> T -> Ordering
T -> T -> T
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: T -> T -> T
$cmin :: T -> T -> T
max :: T -> T -> T
$cmax :: T -> T -> T
>= :: T -> T -> Bool
$c>= :: T -> T -> Bool
> :: T -> T -> Bool
$c> :: T -> T -> Bool
<= :: T -> T -> Bool
$c<= :: T -> T -> Bool
< :: T -> T -> Bool
$c< :: T -> T -> Bool
compare :: T -> T -> Ordering
$ccompare :: T -> T -> Ordering
$cp1Ord :: Eq T
Ord)


get :: Parser.C parser => Int -> Parser.Fragile parser T
get :: Int -> Fragile parser T
get Int
tag =
   case Int
tag of
      Int
0xF0 -> (ByteList -> T)
-> ExceptionalT String parser ByteList -> Fragile parser T
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ByteList -> T
Regular (ExceptionalT String parser ByteList -> Fragile parser T)
-> ExceptionalT String parser ByteList -> Fragile parser T
forall a b. (a -> b) -> a -> b
$ Integer -> ExceptionalT String parser ByteList
forall (parser :: * -> *).
C parser =>
Integer -> Fragile parser ByteList
getBigN (Integer -> ExceptionalT String parser ByteList)
-> ExceptionalT String parser Integer
-> ExceptionalT String parser ByteList
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< ExceptionalT String parser Integer
forall (parser :: * -> *). C parser => Fragile parser Integer
getVar
      Int
0xF7 -> (ByteList -> T)
-> ExceptionalT String parser ByteList -> Fragile parser T
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ByteList -> T
Escape  (ExceptionalT String parser ByteList -> Fragile parser T)
-> ExceptionalT String parser ByteList -> Fragile parser T
forall a b. (a -> b) -> a -> b
$ Integer -> ExceptionalT String parser ByteList
forall (parser :: * -> *).
C parser =>
Integer -> Fragile parser ByteList
getBigN (Integer -> ExceptionalT String parser ByteList)
-> ExceptionalT String parser Integer
-> ExceptionalT String parser ByteList
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< ExceptionalT String parser Integer
forall (parser :: * -> *). C parser => Fragile parser Integer
getVar
      Int
_ -> String -> Fragile parser T
forall (m :: * -> *) a. Monad m => String -> T m a
Parser.giveUp String
"SystemExclusive: unkown message type"

put :: Writer.C writer => T -> writer
put :: T -> writer
put T
sysex =
   case T
sysex of
      Regular ByteList
bytes -> Word8 -> writer
forall m. C m => Word8 -> m
Writer.putByte Word8
0xF0 writer -> writer -> writer
forall m. Monoid m => m -> m -> m
+#+ ByteList -> writer
forall writer. C writer => ByteList -> writer
Writer.putLenByteList ByteList
bytes
      Escape  ByteList
bytes -> Word8 -> writer
forall m. C m => Word8 -> m
Writer.putByte Word8
0xF7 writer -> writer -> writer
forall m. Monoid m => m -> m -> m
+#+ ByteList -> writer
forall writer. C writer => ByteList -> writer
Writer.putLenByteList ByteList
bytes