{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}

-- |
-- Module      :  Text.CueSheet.Render
-- Copyright   :  © 2016–present Mark Karpov
-- License     :  BSD 3 clause
--
-- Maintainer  :  Mark Karpov <markkarpov92@gmail.com>
-- Stability   :  experimental
-- Portability :  portable
--
-- The module contains a CUE sheet render. You probably want to import
-- "Text.CueSheet" instead.
module Text.CueSheet.Render
  ( renderCueSheet,
  )
where

import Control.Monad
import Control.Monad.State
import Control.Monad.Writer.Lazy
import qualified Data.ByteString as B
import qualified Data.ByteString.Builder as BB
import qualified Data.ByteString.Lazy as BL
import Data.Char (chr, isSpace)
import qualified Data.List.NonEmpty as NE
import Data.Maybe (catMaybes)
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import Numeric.Natural
import Text.CueSheet.Types
import Text.Printf (printf)

-- | Render a CUE sheet as a lazy 'BL.ByteString'. All 'Text' values in the
-- 'CueSheet' will be UTF-8 encoded.
renderCueSheet ::
  -- | Use CRLF sequence as “end of line” separator
  Bool ->
  -- | The 'CueSheet' to render
  CueSheet ->
  -- | The result
  BL.ByteString
renderCueSheet :: Bool -> CueSheet -> ByteString
renderCueSheet Bool
csrf CueSheet {Natural
Maybe FilePath
Maybe CueText
Maybe Mcn
NonEmpty CueFile
cueFiles :: CueSheet -> NonEmpty CueFile
cueFirstTrackNumber :: CueSheet -> Natural
cueSongwriter :: CueSheet -> Maybe CueText
cueTitle :: CueSheet -> Maybe CueText
cuePerformer :: CueSheet -> Maybe CueText
cueCdTextFile :: CueSheet -> Maybe FilePath
cueCatalog :: CueSheet -> Maybe Mcn
cueFiles :: NonEmpty CueFile
cueFirstTrackNumber :: Natural
cueSongwriter :: Maybe CueText
cueTitle :: Maybe CueText
cuePerformer :: Maybe CueText
cueCdTextFile :: Maybe FilePath
cueCatalog :: Maybe Mcn
..} =
  Builder -> ByteString
BB.toLazyByteString (Builder -> ByteString)
-> (StateT Natural (WriterT Builder Identity) () -> Builder)
-> StateT Natural (WriterT Builder Identity) ()
-> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Writer Builder () -> Builder
forall w a. Writer w a -> w
execWriter (Writer Builder () -> Builder)
-> (StateT Natural (WriterT Builder Identity) ()
    -> Writer Builder ())
-> StateT Natural (WriterT Builder Identity) ()
-> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (StateT Natural (WriterT Builder Identity) ()
 -> Natural -> Writer Builder ())
-> Natural
-> StateT Natural (WriterT Builder Identity) ()
-> Writer Builder ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip StateT Natural (WriterT Builder Identity) ()
-> Natural -> Writer Builder ()
forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
evalStateT (Natural -> Natural -> Natural
forall a. Ord a => a -> a -> a
max Natural
cueFirstTrackNumber Natural
1) (StateT Natural (WriterT Builder Identity) () -> ByteString)
-> StateT Natural (WriterT Builder Identity) () -> ByteString
forall a b. (a -> b) -> a -> b
$ do
    let eol :: StateT Natural (WriterT Builder Identity) ()
eol = Builder -> StateT Natural (WriterT Builder Identity) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell (if Bool
csrf then Builder
"\r\n" else Builder
"\n")
        tellText :: Text -> m ()
tellText Text
x =
          let raw :: ByteString
raw = Text -> ByteString
T.encodeUtf8 Text
x
           in Builder -> m ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell (Builder -> m ()) -> (ByteString -> Builder) -> ByteString -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Builder
BB.byteString (ByteString -> m ()) -> ByteString -> m ()
forall a b. (a -> b) -> a -> b
$
                if (Word8 -> Bool) -> ByteString -> Bool
B.any (Char -> Bool
isSpace (Char -> Bool) -> (Word8 -> Char) -> Word8 -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Char
chr (Int -> Char) -> (Word8 -> Int) -> Word8 -> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral) ByteString
raw Bool -> Bool -> Bool
|| ByteString -> Bool
B.null ByteString
raw
                  then ByteString
"\"" ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
raw ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
"\""
                  else ByteString
raw
    Maybe Mcn
-> (Mcn -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe Mcn
cueCatalog ((Mcn -> StateT Natural (WriterT Builder Identity) ())
 -> StateT Natural (WriterT Builder Identity) ())
-> (Mcn -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall a b. (a -> b) -> a -> b
$ \Mcn
x -> do
      Builder -> StateT Natural (WriterT Builder Identity) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell Builder
"CATALOG "
      Text -> StateT Natural (WriterT Builder Identity) ()
forall (m :: * -> *). MonadWriter Builder m => Text -> m ()
tellText (Mcn -> Text
unMcn Mcn
x)
      StateT Natural (WriterT Builder Identity) ()
eol
    Maybe FilePath
-> (FilePath -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe FilePath
cueCdTextFile ((FilePath -> StateT Natural (WriterT Builder Identity) ())
 -> StateT Natural (WriterT Builder Identity) ())
-> (FilePath -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall a b. (a -> b) -> a -> b
$ \FilePath
x -> do
      Builder -> StateT Natural (WriterT Builder Identity) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell Builder
"CDTEXTFILE "
      Text -> StateT Natural (WriterT Builder Identity) ()
forall (m :: * -> *). MonadWriter Builder m => Text -> m ()
tellText (FilePath -> Text
T.pack FilePath
x)
      StateT Natural (WriterT Builder Identity) ()
eol
    Maybe CueText
-> (CueText -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe CueText
cuePerformer ((CueText -> StateT Natural (WriterT Builder Identity) ())
 -> StateT Natural (WriterT Builder Identity) ())
-> (CueText -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall a b. (a -> b) -> a -> b
$ \CueText
x -> do
      Builder -> StateT Natural (WriterT Builder Identity) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell Builder
"PERFORMER "
      Text -> StateT Natural (WriterT Builder Identity) ()
forall (m :: * -> *). MonadWriter Builder m => Text -> m ()
tellText (CueText -> Text
unCueText CueText
x)
      StateT Natural (WriterT Builder Identity) ()
eol
    Maybe CueText
-> (CueText -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe CueText
cueTitle ((CueText -> StateT Natural (WriterT Builder Identity) ())
 -> StateT Natural (WriterT Builder Identity) ())
-> (CueText -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall a b. (a -> b) -> a -> b
$ \CueText
x -> do
      Builder -> StateT Natural (WriterT Builder Identity) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell Builder
"TITLE "
      Text -> StateT Natural (WriterT Builder Identity) ()
forall (m :: * -> *). MonadWriter Builder m => Text -> m ()
tellText (CueText -> Text
unCueText CueText
x)
      StateT Natural (WriterT Builder Identity) ()
eol
    Maybe CueText
-> (CueText -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe CueText
cueSongwriter ((CueText -> StateT Natural (WriterT Builder Identity) ())
 -> StateT Natural (WriterT Builder Identity) ())
-> (CueText -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall a b. (a -> b) -> a -> b
$ \CueText
x -> do
      Builder -> StateT Natural (WriterT Builder Identity) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell Builder
"SONGWRITER "
      Text -> StateT Natural (WriterT Builder Identity) ()
forall (m :: * -> *). MonadWriter Builder m => Text -> m ()
tellText (CueText -> Text
unCueText CueText
x)
      StateT Natural (WriterT Builder Identity) ()
eol
    NonEmpty CueFile
-> (CueFile -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ NonEmpty CueFile
cueFiles ((CueFile -> StateT Natural (WriterT Builder Identity) ())
 -> StateT Natural (WriterT Builder Identity) ())
-> (CueFile -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall a b. (a -> b) -> a -> b
$ \CueFile {FilePath
NonEmpty CueTrack
CueFileType
cueFileTracks :: CueFile -> NonEmpty CueTrack
cueFileType :: CueFile -> CueFileType
cueFileName :: CueFile -> FilePath
cueFileTracks :: NonEmpty CueTrack
cueFileType :: CueFileType
cueFileName :: FilePath
..} -> do
      Builder -> StateT Natural (WriterT Builder Identity) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell Builder
"FILE "
      Text -> StateT Natural (WriterT Builder Identity) ()
forall (m :: * -> *). MonadWriter Builder m => Text -> m ()
tellText (FilePath -> Text
T.pack FilePath
cueFileName)
      Builder -> StateT Natural (WriterT Builder Identity) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell Builder
" "
      Text -> StateT Natural (WriterT Builder Identity) ()
forall (m :: * -> *). MonadWriter Builder m => Text -> m ()
tellText (CueFileType -> Text
renderFileType CueFileType
cueFileType)
      StateT Natural (WriterT Builder Identity) ()
eol
      NonEmpty CueTrack
-> (CueTrack -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ NonEmpty CueTrack
cueFileTracks ((CueTrack -> StateT Natural (WriterT Builder Identity) ())
 -> StateT Natural (WriterT Builder Identity) ())
-> (CueTrack -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall a b. (a -> b) -> a -> b
$ \CueTrack {Bool
Maybe Isrc
Maybe CueText
Maybe CueTime
NonEmpty CueTime
CueTrackType
cueTrackPostgap :: CueTrack -> Maybe CueTime
cueTrackIndices :: CueTrack -> NonEmpty CueTime
cueTrackPregapIndex :: CueTrack -> Maybe CueTime
cueTrackPregap :: CueTrack -> Maybe CueTime
cueTrackSongwriter :: CueTrack -> Maybe CueText
cueTrackPerformer :: CueTrack -> Maybe CueText
cueTrackTitle :: CueTrack -> Maybe CueText
cueTrackIsrc :: CueTrack -> Maybe Isrc
cueTrackType :: CueTrack -> CueTrackType
cueTrackSerialCopyManagement :: CueTrack -> Bool
cueTrackPreemphasisEnabled :: CueTrack -> Bool
cueTrackFourChannelAudio :: CueTrack -> Bool
cueTrackDigitalCopyPermitted :: CueTrack -> Bool
cueTrackPostgap :: Maybe CueTime
cueTrackIndices :: NonEmpty CueTime
cueTrackPregapIndex :: Maybe CueTime
cueTrackPregap :: Maybe CueTime
cueTrackSongwriter :: Maybe CueText
cueTrackPerformer :: Maybe CueText
cueTrackTitle :: Maybe CueText
cueTrackIsrc :: Maybe Isrc
cueTrackType :: CueTrackType
cueTrackSerialCopyManagement :: Bool
cueTrackPreemphasisEnabled :: Bool
cueTrackFourChannelAudio :: Bool
cueTrackDigitalCopyPermitted :: Bool
..} -> do
        Natural
currentTrack <- StateT Natural (WriterT Builder Identity) Natural
forall s (m :: * -> *). MonadState s m => m s
get
        (Natural -> Natural)
-> StateT Natural (WriterT Builder Identity) ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify Natural -> Natural
forall a. Enum a => a -> a
succ
        Builder -> StateT Natural (WriterT Builder Identity) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell Builder
"  TRACK "
        Text -> StateT Natural (WriterT Builder Identity) ()
forall (m :: * -> *). MonadWriter Builder m => Text -> m ()
tellText (Natural -> Text
formatNat Natural
currentTrack)
        Builder -> StateT Natural (WriterT Builder Identity) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell Builder
" "
        Text -> StateT Natural (WriterT Builder Identity) ()
forall (m :: * -> *). MonadWriter Builder m => Text -> m ()
tellText (CueTrackType -> Text
renderTrackType CueTrackType
cueTrackType)
        StateT Natural (WriterT Builder Identity) ()
eol
        let flags :: [ByteString]
flags =
              [Maybe ByteString] -> [ByteString]
forall a. [Maybe a] -> [a]
catMaybes
                [ if Bool
cueTrackDigitalCopyPermitted then ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
"DCP" else Maybe ByteString
forall a. Maybe a
Nothing,
                  if Bool
cueTrackFourChannelAudio then ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
"4CH" else Maybe ByteString
forall a. Maybe a
Nothing,
                  if Bool
cueTrackPreemphasisEnabled then ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
"PRE" else Maybe ByteString
forall a. Maybe a
Nothing,
                  if Bool
cueTrackSerialCopyManagement then ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
"SCMS" else Maybe ByteString
forall a. Maybe a
Nothing
                ]
        Bool
-> StateT Natural (WriterT Builder Identity) ()
-> StateT Natural (WriterT Builder Identity) ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([ByteString] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ByteString]
flags) (StateT Natural (WriterT Builder Identity) ()
 -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
-> StateT Natural (WriterT Builder Identity) ()
forall a b. (a -> b) -> a -> b
$ do
          Builder -> StateT Natural (WriterT Builder Identity) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell Builder
"    FLAGS "
          (Builder -> StateT Natural (WriterT Builder Identity) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell (Builder -> StateT Natural (WriterT Builder Identity) ())
-> (ByteString -> Builder)
-> ByteString
-> StateT Natural (WriterT Builder Identity) ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Builder
BB.byteString) (ByteString -> [ByteString] -> ByteString
B.intercalate ByteString
" " [ByteString]
flags)
          StateT Natural (WriterT Builder Identity) ()
eol
        Maybe Isrc
-> (Isrc -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe Isrc
cueTrackIsrc ((Isrc -> StateT Natural (WriterT Builder Identity) ())
 -> StateT Natural (WriterT Builder Identity) ())
-> (Isrc -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall a b. (a -> b) -> a -> b
$ \Isrc
x -> do
          Builder -> StateT Natural (WriterT Builder Identity) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell Builder
"    ISRC "
          Text -> StateT Natural (WriterT Builder Identity) ()
forall (m :: * -> *). MonadWriter Builder m => Text -> m ()
tellText (Isrc -> Text
unIsrc Isrc
x)
          StateT Natural (WriterT Builder Identity) ()
eol
        Maybe CueText
-> (CueText -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe CueText
cueTrackTitle ((CueText -> StateT Natural (WriterT Builder Identity) ())
 -> StateT Natural (WriterT Builder Identity) ())
-> (CueText -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall a b. (a -> b) -> a -> b
$ \CueText
x -> do
          Builder -> StateT Natural (WriterT Builder Identity) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell Builder
"    TITLE "
          Text -> StateT Natural (WriterT Builder Identity) ()
forall (m :: * -> *). MonadWriter Builder m => Text -> m ()
tellText (CueText -> Text
unCueText CueText
x)
          StateT Natural (WriterT Builder Identity) ()
eol
        Maybe CueText
-> (CueText -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe CueText
cueTrackPerformer ((CueText -> StateT Natural (WriterT Builder Identity) ())
 -> StateT Natural (WriterT Builder Identity) ())
-> (CueText -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall a b. (a -> b) -> a -> b
$ \CueText
x -> do
          Builder -> StateT Natural (WriterT Builder Identity) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell Builder
"    PERFORMER "
          Text -> StateT Natural (WriterT Builder Identity) ()
forall (m :: * -> *). MonadWriter Builder m => Text -> m ()
tellText (CueText -> Text
unCueText CueText
x)
          StateT Natural (WriterT Builder Identity) ()
eol
        Maybe CueText
-> (CueText -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe CueText
cueTrackSongwriter ((CueText -> StateT Natural (WriterT Builder Identity) ())
 -> StateT Natural (WriterT Builder Identity) ())
-> (CueText -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall a b. (a -> b) -> a -> b
$ \CueText
x -> do
          Builder -> StateT Natural (WriterT Builder Identity) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell Builder
"    SONGWRITER "
          Text -> StateT Natural (WriterT Builder Identity) ()
forall (m :: * -> *). MonadWriter Builder m => Text -> m ()
tellText (CueText -> Text
unCueText CueText
x)
          StateT Natural (WriterT Builder Identity) ()
eol
        Maybe CueTime
-> (CueTime -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe CueTime
cueTrackPregap ((CueTime -> StateT Natural (WriterT Builder Identity) ())
 -> StateT Natural (WriterT Builder Identity) ())
-> (CueTime -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall a b. (a -> b) -> a -> b
$ \CueTime
x -> do
          Builder -> StateT Natural (WriterT Builder Identity) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell Builder
"    PREGAP "
          Text -> StateT Natural (WriterT Builder Identity) ()
forall (m :: * -> *). MonadWriter Builder m => Text -> m ()
tellText (CueTime -> Text
showMmSsFf CueTime
x)
          StateT Natural (WriterT Builder Identity) ()
eol
        Maybe CueTime
-> (CueTime -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe CueTime
cueTrackPregapIndex ((CueTime -> StateT Natural (WriterT Builder Identity) ())
 -> StateT Natural (WriterT Builder Identity) ())
-> (CueTime -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall a b. (a -> b) -> a -> b
$ \CueTime
x -> do
          Builder -> StateT Natural (WriterT Builder Identity) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell Builder
"    INDEX 00 "
          Text -> StateT Natural (WriterT Builder Identity) ()
forall (m :: * -> *). MonadWriter Builder m => Text -> m ()
tellText (CueTime -> Text
showMmSsFf CueTime
x)
          StateT Natural (WriterT Builder Identity) ()
eol
        NonEmpty (Natural, CueTime)
-> ((Natural, CueTime)
    -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (NonEmpty Natural -> NonEmpty CueTime -> NonEmpty (Natural, CueTime)
forall a b. NonEmpty a -> NonEmpty b -> NonEmpty (a, b)
NE.zip ([Natural] -> NonEmpty Natural
forall a. [a] -> NonEmpty a
NE.fromList [Natural
1 ..]) NonEmpty CueTime
cueTrackIndices) (((Natural, CueTime)
  -> StateT Natural (WriterT Builder Identity) ())
 -> StateT Natural (WriterT Builder Identity) ())
-> ((Natural, CueTime)
    -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall a b. (a -> b) -> a -> b
$ \(Natural
n, CueTime
index) -> do
          Builder -> StateT Natural (WriterT Builder Identity) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell Builder
"    INDEX "
          Text -> StateT Natural (WriterT Builder Identity) ()
forall (m :: * -> *). MonadWriter Builder m => Text -> m ()
tellText (Natural -> Text
formatNat Natural
n)
          Builder -> StateT Natural (WriterT Builder Identity) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell Builder
" "
          Text -> StateT Natural (WriterT Builder Identity) ()
forall (m :: * -> *). MonadWriter Builder m => Text -> m ()
tellText (CueTime -> Text
showMmSsFf CueTime
index)
          StateT Natural (WriterT Builder Identity) ()
eol
        Maybe CueTime
-> (CueTime -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ Maybe CueTime
cueTrackPostgap ((CueTime -> StateT Natural (WriterT Builder Identity) ())
 -> StateT Natural (WriterT Builder Identity) ())
-> (CueTime -> StateT Natural (WriterT Builder Identity) ())
-> StateT Natural (WriterT Builder Identity) ()
forall a b. (a -> b) -> a -> b
$ \CueTime
x -> do
          Builder -> StateT Natural (WriterT Builder Identity) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell Builder
"    POSTGAP "
          Text -> StateT Natural (WriterT Builder Identity) ()
forall (m :: * -> *). MonadWriter Builder m => Text -> m ()
tellText (CueTime -> Text
showMmSsFf CueTime
x)
          StateT Natural (WriterT Builder Identity) ()
eol

----------------------------------------------------------------------------
-- Helpers

-- | Format a 'Natural' padding it with zeros to 2 digits.
formatNat :: Natural -> Text
formatNat :: Natural -> Text
formatNat = FilePath -> Text
T.pack (FilePath -> Text) -> (Natural -> FilePath) -> Natural -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Natural -> FilePath
forall r. PrintfType r => FilePath -> r
printf FilePath
"%02d"

-- | Render a 'CueFileType' as per the CUE specs.
renderFileType :: CueFileType -> Text
renderFileType :: CueFileType -> Text
renderFileType CueFileType
Binary = Text
"BINARY"
renderFileType CueFileType
Motorola = Text
"MOTOROLA"
renderFileType CueFileType
Aiff = Text
"AIFF"
renderFileType CueFileType
Wave = Text
"WAVE"
renderFileType CueFileType
MP3 = Text
"MP3"

-- | Render a 'CueTrackType' as per the CUE specs.
renderTrackType :: CueTrackType -> Text
renderTrackType :: CueTrackType -> Text
renderTrackType CueTrackType
CueTrackAudio = Text
"AUDIO"
renderTrackType CueTrackType
CueTrackCdg = Text
"CDG"
renderTrackType CueTrackType
CueTrackMode1_2048 = Text
"MODE1/2048"
renderTrackType CueTrackType
CueTrackMode1_2352 = Text
"MODE1/2352"
renderTrackType CueTrackType
CueTrackMode2_2336 = Text
"MODE2/2336"
renderTrackType CueTrackType
CueTrackMode2_2352 = Text
"MODE2/2352"
renderTrackType CueTrackType
CueTrackCdi2336 = Text
"CDI/2336"
renderTrackType CueTrackType
CueTrackCdi2352 = Text
"CDI/2352"