zmidi-core-0.8.0: src/ZMidi/Core/Pretty/Internal.hs
{-# LANGUAGE CPP #-}
{-# OPTIONS -Wall #-}
--------------------------------------------------------------------------------
-- |
-- Module : ZMidi.Core.Pretty.Internal
-- Copyright : (c) Stephen Tetley 2015
-- License : BSD3
--
-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>
-- Stability : unstable
-- Portability : As per dependencies.
--
-- Helper functions to pretty print MIDI as text.
--
-- The functionality is unstable and may change between
-- releases however it is still exposed as it may be useful
-- for writing a custom pretty printer.
--
--------------------------------------------------------------------------------
module ZMidi.Core.Pretty.Internal
(
midi_header_columns
, tellMidiHeader
, byteList
, safeString
, textType
) where
import ZMidi.Core.Datatypes
import ZMidi.Core.Internal.SimpleFormat
import Data.Char
#ifndef MIN_VERSION_GLASGOW_HASKELL
import Data.Monoid
#endif
import Data.Word
-- | Column specs for Header - Header is printed as simple
-- name-value pairs (2 columns).
--
midi_header_columns :: ColumnSpecs
midi_header_columns = ColumnSpecs '|' [ PadR 21, PadR 38 ]
-- | Log the MidiHeader in the Table monad (cf. Writer).
--
tellMidiHeader :: MidiHeader -> Table ()
tellMidiHeader (MidiHeader fmt tcount td) =
localColumns midi_header_columns $ do
tellRow $ \_ _ -> [ text "MIDI Format", ppFormat fmt ]
tellRow $ \_ _ -> [ text "Number of tracks", integral tcount ]
tellRow $ \_ _ -> [ text "Time Division", ppTimeDivision td ]
-- | Decode MidiFormat.
--
ppFormat :: MidiFormat -> WString
ppFormat MF0 = text "Type 0 MIDI File"
ppFormat MF1 = text "Type 1 MIDI File"
ppFormat MF2 = text "Type 2 MIDI File"
-- | Decode TimeDivision.
--
ppTimeDivision :: MidiTimeDivision -> WString
ppTimeDivision (FPS i) = text "FPS" <+> integral i
ppTimeDivision (TPB i) = text "Ticks" <+> integral i
--------------------------------------------------------------------------------
-- Helpers
-- | Print a short byte-list as Hex. Byte-lists longer than
-- 10 chars are printed as ellipses.
--
byteList :: (Show a, Integral a) => a -> [Word8] -> WString
byteList n ws | n < 10 = integral n <+> mconcat (map hex2 ws)
| otherwise = integral n <+> repeatChar 10 '.'
-- | Decode Text Type
--
textType :: MidiTextType -> String
textType GENERIC_TEXT = "generic-text"
textType COPYRIGHT_NOTICE = "copyright-notice"
textType SEQUENCE_NAME = "sequence-name"
textType INSTRUMENT_NAME = "instrument-name"
textType LYRICS = "lyrics"
textType MARKER = "marker"
textType CUE_POINT = "cue-point"
-- | Make a string safe for stdout.
--
-- This is a temporary hack - characters above ASCII 163
-- cause an (invalid character) error when written to stdout
-- on Windows (Cygwin).
--
safeString :: String -> String
safeString = map (f . ord)
where
f i | i < 164 = chr i
| otherwise = '#'