module ZMidi.Core.Pretty.Csv
(
putCsv
, printCsv
) where
import ZMidi.Core.Datatypes
import ZMidi.Core.Internal.SimpleFormat
import ZMidi.Core.Pretty.Internal
import Data.Monoid
putCsv :: MidiFile -> IO ()
putCsv = mapM_ putStrLn . printCsv
printCsv :: MidiFile -> [String]
printCsv (MidiFile hdr tracks) = execTable body_columns $ do
tellHeader hdr
mapM_ tellTrack tracks
infixr 6 <%>
(<%>) :: WString -> WString -> WString
a <%> b = a <> char ',' <+> b
tellHeader :: MidiHeader -> Table ()
tellHeader (MidiHeader fmt ntrks tdiv) =
tellFree $ \track_num acctime ->
int track_num <%> integral acctime <%> text "Header"
<%> int (fromEnum fmt) <%> integral ntrks
<%> division tdiv
where
division (FPS n) = integral n
division (TPB n) = integral n
tellTrack :: MidiTrack -> Table ()
tellTrack (MidiTrack xs) = nextTrack >> mapM_ message xs
body_columns :: ColumnSpecs
body_columns =
ColumnSpecs ' ' [ PadR 60 ]
message :: MidiMessage -> Table ()
message (delta,evt) = do
incrDelta $ fromIntegral delta
tellFree $ \track_num acctime ->
int track_num <%> integral acctime <%> ppEvent evt
ppEvent :: MidiEvent -> WString
ppEvent (MidiEventOther _) = text "Unrecognized_event_other"
ppEvent (VoiceEvent _ e) = ppVoiceEvent e
ppEvent (SysExEvent e) = ppSysExEvent e
ppEvent (SysCommonEvent e) = ppSysCommonEvent e
ppEvent (SysRealTimeEvent e) = ppSysRealTimeEvent e
ppEvent (MetaEvent e) = ppMetaEvent e
ppVoiceEvent :: MidiVoiceEvent -> WString
ppVoiceEvent (Controller c n v) =
text "Control_c" <%> integral c <%> integral n <%> integral v
ppVoiceEvent (ProgramChange c n) =
text "Program_c" <%> integral c <%> integral n
ppVoiceEvent (NoteOff c n v) =
text "Note_off_c" <%> integral c <%> integral n <%> integral v
ppVoiceEvent (NoteOn c n v) =
text "Note_on_c" <%> integral c <%> integral n <%> integral v
ppVoiceEvent (NoteAftertouch c n v) =
text "Poly_aftertouch_c" <%> integral c <%> integral n <%> integral v
ppVoiceEvent (ChanAftertouch c v) =
text "Channel_aftertouch_c" <%> integral c <%> integral v
ppVoiceEvent (PitchBend c v) =
text "Pitch_bend_c" <%> integral c <%> integral v
ppSysExEvent :: MidiSysExEvent -> WString
ppSysExEvent (SysExSingle n _) =
text "System_exclusive" <%> integral n <%> text "..."
ppSysExEvent (SysExCont n _ _) =
text "System_exclusive_continuation" <%> integral n <%> text "..."
ppSysExEvent (SysExEscape n _) =
text "System_exclusive_escape" <%> integral n <%> text "..."
ppSysCommonEvent :: MidiSysCommonEvent -> WString
ppSysCommonEvent (QuarterFrame sb) =
text "Quarter_frame_s" <%> integral sb
ppSysCommonEvent (SongPosPointer a b) =
text "Song_position_pointer_s" <%> integral a <%> integral b
ppSysCommonEvent (SongSelect w) =
text "Song_select_s" <%> integral w
ppSysCommonEvent (UndefinedF4) =
text "Undefined_s" <%> text "0xF4"
ppSysCommonEvent (UndefinedF5) =
text "Undefined_s" <%> text "0xF5"
ppSysCommonEvent (TuneRequest) =
text "Tune_request_s"
ppSysCommonEvent (EOX) =
text "EOX_s"
ppSysRealTimeEvent :: MidiSysRealTimeEvent -> WString
ppSysRealTimeEvent (TimingClock) = text "Timing_clock_s"
ppSysRealTimeEvent (UndefinedF9) = text "Undefined_s" <%> text "0xF9"
ppSysRealTimeEvent (StartSequence) = text "Start_sequence_s"
ppSysRealTimeEvent (ContinueSequence) = text "Continue_sequence_s"
ppSysRealTimeEvent (StopSequence) = text "Stop_sequence_s"
ppSysRealTimeEvent (UndefinedFD) = text "Undefined_s" <%> text "0xFD"
ppSysRealTimeEvent (ActiveSensing) = text "Active_sensing_s"
ppSysRealTimeEvent (SystemReset) = text "System_reset_s"
ppMetaEvent :: MidiMetaEvent -> WString
ppMetaEvent (TextEvent ty s) = ppTextEvent ty s
ppMetaEvent (SequenceNumber w) = text "Sequence_number" <%> integral w
ppMetaEvent (ChannelPrefix ch) = text "Channel_prefix" <%> integral ch
ppMetaEvent (MidiPort w) = text "MIDI_port" <%> integral w
ppMetaEvent (EndOfTrack) = text "End_track"
ppMetaEvent (SetTempo w) = text "Tempo" <%> integral w
ppMetaEvent (SMPTEOffset h m s f sf) =
text "SMTPE_offset" <%> integral h <%> integral m <%> integral s
<%> integral f <%> integral sf
ppMetaEvent (TimeSignature n d m t) =
text "Time_signature" <%> integral n <%> integral d
<%> integral m <%> integral t
ppMetaEvent (KeySignature n sc) =
let scale = case sc of { MAJOR -> "major"
; MINOR -> "minor"
; _ -> "unrecognized" }
in text "Key_signature" <%> integral n <%> text scale
ppMetaEvent (SSME n _) =
text "Sequencer_specific" <%> integral n <%> text "..."
ppMetaEvent (MetaOther ty len _) =
text "Unknown_meta_event" <%> integral ty <%> integral len <%> text "..."
safetext :: String -> WString
safetext = text . safeString
ppTextEvent :: MidiTextType -> String -> WString
ppTextEvent GENERIC_TEXT s = text "Text_t" <%> safetext s
ppTextEvent COPYRIGHT_NOTICE s = text "Copyright_t" <%> safetext s
ppTextEvent SEQUENCE_NAME s = text "Sequence_name_t" <%> safetext s
ppTextEvent INSTRUMENT_NAME s = text "Instrument_name_t" <%> safetext s
ppTextEvent LYRICS s = text "Lyric_t" <%> safetext s
ppTextEvent MARKER s = text "marker" <%> safetext s
ppTextEvent CUE_POINT s = text "cue-point" <%> safetext s