module Text.CueSheet.Render
( renderCueSheet )
where
import Control.Monad
import Control.Monad.State
import Control.Monad.Writer.Lazy
import Data.Char (isSpace, chr)
import Data.Maybe (catMaybes)
import Data.Text (Text)
import Numeric.Natural
import Text.CueSheet.Types
import Text.Printf (printf)
import qualified Data.ByteString as B
import qualified Data.ByteString.Builder as BB
import qualified Data.ByteString.Lazy as BL
import qualified Data.List.NonEmpty as NE
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
renderCueSheet
:: Bool
-> CueSheet
-> BL.ByteString
renderCueSheet csrf CueSheet {..} =
BB.toLazyByteString . execWriter . flip evalStateT (max cueFirstTrackNumber 1) $ do
let eol = tell (if csrf then "\r\n" else "\n")
tellText x =
let raw = T.encodeUtf8 x
in tell . BB.byteString $
if B.any (isSpace . chr . fromIntegral) raw || B.null raw
then "\"" <> raw <> "\""
else raw
forM_ cueCatalog $ \x -> do
tell "CATALOG "
tellText (unMcn x)
eol
forM_ cueCdTextFile $ \x -> do
tell "CDTEXTFILE "
tellText (T.pack x)
eol
forM_ cuePerformer $ \x -> do
tell "PERFORMER "
tellText (unCueText x)
eol
forM_ cueTitle $ \x -> do
tell "TITLE "
tellText (unCueText x)
eol
forM_ cueSongwriter $ \x -> do
tell "SONGWRITER "
tellText (unCueText x)
eol
forM_ cueFiles $ \CueFile {..} -> do
tell "FILE "
tellText (T.pack cueFileName)
tell " "
tellText (renderFileType cueFileType)
eol
forM_ cueFileTracks $ \CueTrack {..} -> do
currentTrack <- get
modify succ
tell " TRACK "
tellText (formatNat currentTrack)
tell " "
tellText (renderTrackType cueTrackType)
eol
let flags = catMaybes
[ if cueTrackDigitalCopyPermitted then Just "DCP" else Nothing
, if cueTrackFourChannelAudio then Just "4CH" else Nothing
, if cueTrackPreemphasisEnabled then Just "PRE" else Nothing
, if cueTrackSerialCopyManagement then Just "SCMS" else Nothing ]
unless (null flags) $ do
tell " FLAGS "
(tell . BB.byteString) (B.intercalate " " flags)
eol
forM_ cueTrackIsrc $ \x -> do
tell " ISRC "
tellText (unIsrc x)
eol
forM_ cueTrackTitle $ \x -> do
tell " TITLE "
tellText (unCueText x)
eol
forM_ cueTrackPerformer $ \x -> do
tell " PERFORMER "
tellText (unCueText x)
eol
forM_ cueTrackSongwriter $ \x -> do
tell " SONGWRITER "
tellText (unCueText x)
eol
forM_ cueTrackPregap $ \x -> do
tell " PREGAP "
tellText (showMmSsFf x)
eol
forM_ cueTrackPregapIndex $ \x -> do
tell " INDEX 00 "
tellText (showMmSsFf x)
eol
forM_ (NE.zip (NE.fromList [1..]) cueTrackIndices) $ \(n, index) -> do
tell " INDEX "
tellText (formatNat n)
tell " "
tellText (showMmSsFf index)
eol
forM_ cueTrackPostgap $ \x -> do
tell " POSTGAP "
tellText (showMmSsFf x)
eol
formatNat :: Natural -> Text
formatNat = T.pack . printf "%02d"
renderFileType :: CueFileType -> Text
renderFileType Binary = "BINARY"
renderFileType Motorola = "MOTOROLA"
renderFileType Aiff = "AIFF"
renderFileType Wave = "WAVE"
renderFileType MP3 = "MP3"
renderTrackType :: CueTrackType -> Text
renderTrackType CueTrackAudio = "AUDIO"
renderTrackType CueTrackCdg = "CDG"
renderTrackType CueTrackMode1_2048 = "MODE1/2048"
renderTrackType CueTrackMode1_2352 = "MODE1/2352"
renderTrackType CueTrackMode2_2336 = "MODE2/2336"
renderTrackType CueTrackMode2_2352 = "MODE2/2352"
renderTrackType CueTrackCdi2336 = "CDI/2336"
renderTrackType CueTrackCdi2352 = "CDI/2352"