-- The idea is that the stream of data coming from the MIDI input port -- will be sorted in three categories: note on events, controller -- events and other events. The latter will be transmitted as is -- through the whole systems. module RMCA.Translator.SortMessage where import qualified Data.Bifunctor as BF import Data.Function (on) import Data.List (groupBy) import Data.Maybe import RMCA.Semantics import RMCA.Translator.Message import RMCA.Translator.Note sortRawMessages :: [(Frames, RawMessage)] -> ([(Frames,Message)], [(Frames,RawMessage)]) sortRawMessages = sortRawMessages' ([],[]) where sortRawMessages' r [] = r sortRawMessages' (m, rm) (x@(n,xm):xs) | isNothing nm = sortRawMessages' (m, x:rm) xs | otherwise = sortRawMessages' ((n,fromJust nm) :m, rm) xs where nm = fromRawMessage xm -- Direct each message to a specific channel. -- /!\ To be modified. sortChannel :: [Message] -> [(Int,[Message])] sortChannel = map ((,) <$> (fst . head) <*> map snd) . groupBy ((==) `on` fst) . map sortChannel' where sortChannel' :: Message -> (Int, Message) sortChannel' m = let c = getChannel m in (c,m) -- NoteOn messages are on the right, other Control messages are on the -- left. For now we throw away NoteOff messages. sortNotes :: [(Frames, Message)] -> ([(Frames,Message)], [(Frames,Message)]) sortNotes = sortNotes' ([],[]) where sortNotes' r [] = r sortNotes' (n, c) (x@(_,m):xs) | isNoteOn m = sortNotes' (x:n, c) xs | isNoteOff m = sortNotes' (n,c) xs | isControl m = sortNotes' (n,x:c) xs | otherwise = sortNotes' (n,c) xs -- Note messages are converted to PlayHeads convertMessages :: [(Frames,Message)] -> [(Frames,Note)] convertMessages = map (BF.second messageToNote)