{-# LANGUAGE DeriveGeneric #-}

-- |
-- Module      :  Text.CueSheet.Types
-- Copyright   :  © 2016–present Mark Karpov
-- License     :  BSD 3 clause
--
-- Maintainer  :  Mark Karpov <markkarpov92@gmail.com>
-- Stability   :  experimental
-- Portability :  portable
--
-- Types describing structure of a CUE sheet. You probably want to import
-- "Text.CueSheet" instead.
module Text.CueSheet.Types
  ( CueSheet (..),
    CueFile (..),
    CueFileType (..),
    CueTrack (..),
    CueTrackType (..),
    CueTime (..),
    fromMmSsFf,
    toMmSsFf,
    showMmSsFf,
    Mcn,
    mkMcn,
    unMcn,
    CueText,
    mkCueText,
    unCueText,
    Isrc,
    mkIsrc,
    unIsrc,
    CueSheetException (..),
  )
where

import Control.Monad.Catch
import Data.Char (isAscii, isDigit, isLetter)
import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.List.NonEmpty as NE
import Data.Text (Text)
import qualified Data.Text as T
import GHC.Generics
import Numeric.Natural
import Test.QuickCheck
import Text.Printf (printf)

-- | CUE sheet, contains one or more files (see 'CueFile').
data CueSheet = CueSheet
  { -- | Disc's Media Catalog Number (see 'Mcn').
    CueSheet -> Maybe Mcn
cueCatalog :: !(Maybe Mcn),
    -- | Name of the file that contains the encoded CD-Text information for
    -- the disc.
    CueSheet -> Maybe FilePath
cueCdTextFile :: !(Maybe FilePath),
    -- | Performer of the entire disc.
    CueSheet -> Maybe CueText
cuePerformer :: !(Maybe CueText),
    -- | Title of the entire disc.
    CueSheet -> Maybe CueText
cueTitle :: !(Maybe CueText),
    -- | Songwriter of the entire disc.
    CueSheet -> Maybe CueText
cueSongwriter :: !(Maybe CueText),
    -- | Number of the first track. Typically 1, but may be greater than 1.
    CueSheet -> Natural
cueFirstTrackNumber :: !Natural,
    -- | Collection of files to be written.
    CueSheet -> NonEmpty CueFile
cueFiles :: !(NonEmpty CueFile)
  }
  deriving (Int -> CueSheet -> ShowS
[CueSheet] -> ShowS
CueSheet -> FilePath
(Int -> CueSheet -> ShowS)
-> (CueSheet -> FilePath) -> ([CueSheet] -> ShowS) -> Show CueSheet
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
showList :: [CueSheet] -> ShowS
$cshowList :: [CueSheet] -> ShowS
show :: CueSheet -> FilePath
$cshow :: CueSheet -> FilePath
showsPrec :: Int -> CueSheet -> ShowS
$cshowsPrec :: Int -> CueSheet -> ShowS
Show, CueSheet -> CueSheet -> Bool
(CueSheet -> CueSheet -> Bool)
-> (CueSheet -> CueSheet -> Bool) -> Eq CueSheet
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CueSheet -> CueSheet -> Bool
$c/= :: CueSheet -> CueSheet -> Bool
== :: CueSheet -> CueSheet -> Bool
$c== :: CueSheet -> CueSheet -> Bool
Eq, Eq CueSheet
Eq CueSheet
-> (CueSheet -> CueSheet -> Ordering)
-> (CueSheet -> CueSheet -> Bool)
-> (CueSheet -> CueSheet -> Bool)
-> (CueSheet -> CueSheet -> Bool)
-> (CueSheet -> CueSheet -> Bool)
-> (CueSheet -> CueSheet -> CueSheet)
-> (CueSheet -> CueSheet -> CueSheet)
-> Ord CueSheet
CueSheet -> CueSheet -> Bool
CueSheet -> CueSheet -> Ordering
CueSheet -> CueSheet -> CueSheet
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: CueSheet -> CueSheet -> CueSheet
$cmin :: CueSheet -> CueSheet -> CueSheet
max :: CueSheet -> CueSheet -> CueSheet
$cmax :: CueSheet -> CueSheet -> CueSheet
>= :: CueSheet -> CueSheet -> Bool
$c>= :: CueSheet -> CueSheet -> Bool
> :: CueSheet -> CueSheet -> Bool
$c> :: CueSheet -> CueSheet -> Bool
<= :: CueSheet -> CueSheet -> Bool
$c<= :: CueSheet -> CueSheet -> Bool
< :: CueSheet -> CueSheet -> Bool
$c< :: CueSheet -> CueSheet -> Bool
compare :: CueSheet -> CueSheet -> Ordering
$ccompare :: CueSheet -> CueSheet -> Ordering
$cp1Ord :: Eq CueSheet
Ord, (forall x. CueSheet -> Rep CueSheet x)
-> (forall x. Rep CueSheet x -> CueSheet) -> Generic CueSheet
forall x. Rep CueSheet x -> CueSheet
forall x. CueSheet -> Rep CueSheet x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep CueSheet x -> CueSheet
$cfrom :: forall x. CueSheet -> Rep CueSheet x
Generic)

instance Arbitrary CueSheet where
  arbitrary :: Gen CueSheet
arbitrary =
    Maybe Mcn
-> Maybe FilePath
-> Maybe CueText
-> Maybe CueText
-> Maybe CueText
-> Natural
-> NonEmpty CueFile
-> CueSheet
CueSheet
      (Maybe Mcn
 -> Maybe FilePath
 -> Maybe CueText
 -> Maybe CueText
 -> Maybe CueText
 -> Natural
 -> NonEmpty CueFile
 -> CueSheet)
-> Gen (Maybe Mcn)
-> Gen
     (Maybe FilePath
      -> Maybe CueText
      -> Maybe CueText
      -> Maybe CueText
      -> Natural
      -> NonEmpty CueFile
      -> CueSheet)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (Maybe Mcn)
forall a. Arbitrary a => Gen a
arbitrary
      Gen
  (Maybe FilePath
   -> Maybe CueText
   -> Maybe CueText
   -> Maybe CueText
   -> Natural
   -> NonEmpty CueFile
   -> CueSheet)
-> Gen (Maybe FilePath)
-> Gen
     (Maybe CueText
      -> Maybe CueText
      -> Maybe CueText
      -> Natural
      -> NonEmpty CueFile
      -> CueSheet)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> [Gen (Maybe FilePath)] -> Gen (Maybe FilePath)
forall a. [Gen a] -> Gen a
oneof [Maybe FilePath -> Gen (Maybe FilePath)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe FilePath
forall a. Maybe a
Nothing, FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just (FilePath -> Maybe FilePath)
-> Gen FilePath -> Gen (Maybe FilePath)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen FilePath
filepath]
      Gen
  (Maybe CueText
   -> Maybe CueText
   -> Maybe CueText
   -> Natural
   -> NonEmpty CueFile
   -> CueSheet)
-> Gen (Maybe CueText)
-> Gen
     (Maybe CueText
      -> Maybe CueText -> Natural -> NonEmpty CueFile -> CueSheet)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (Maybe CueText)
forall a. Arbitrary a => Gen a
arbitrary
      Gen
  (Maybe CueText
   -> Maybe CueText -> Natural -> NonEmpty CueFile -> CueSheet)
-> Gen (Maybe CueText)
-> Gen (Maybe CueText -> Natural -> NonEmpty CueFile -> CueSheet)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (Maybe CueText)
forall a. Arbitrary a => Gen a
arbitrary
      Gen (Maybe CueText -> Natural -> NonEmpty CueFile -> CueSheet)
-> Gen (Maybe CueText)
-> Gen (Natural -> NonEmpty CueFile -> CueSheet)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (Maybe CueText)
forall a. Arbitrary a => Gen a
arbitrary
      Gen (Natural -> NonEmpty CueFile -> CueSheet)
-> Gen Natural -> Gen (NonEmpty CueFile -> CueSheet)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Integer -> Natural
forall a. Num a => Integer -> a
fromInteger (Integer -> Natural)
-> (Positive Integer -> Integer) -> Positive Integer -> Natural
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Positive Integer -> Integer
forall a. Positive a -> a
getPositive (Positive Integer -> Natural)
-> Gen (Positive Integer) -> Gen Natural
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (Positive Integer)
forall a. Arbitrary a => Gen a
arbitrary)
      Gen (NonEmpty CueFile -> CueSheet)
-> Gen (NonEmpty CueFile) -> Gen CueSheet
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (NonEmpty CueFile) -> Gen (NonEmpty CueFile)
forall a. Gen a -> Gen a
scaleDown ([CueFile] -> NonEmpty CueFile
forall a. [a] -> NonEmpty a
NE.fromList ([CueFile] -> NonEmpty CueFile)
-> (NonEmptyList CueFile -> [CueFile])
-> NonEmptyList CueFile
-> NonEmpty CueFile
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmptyList CueFile -> [CueFile]
forall a. NonEmptyList a -> [a]
getNonEmpty (NonEmptyList CueFile -> NonEmpty CueFile)
-> Gen (NonEmptyList CueFile) -> Gen (NonEmpty CueFile)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (NonEmptyList CueFile)
forall a. Arbitrary a => Gen a
arbitrary)

-- | A file to be written. Single file can be divided into one or more
-- tracks (see 'CueTrack').
data CueFile = CueFile
  { -- | Name of file.
    CueFile -> FilePath
cueFileName :: !FilePath,
    -- | Type of file.
    CueFile -> CueFileType
cueFileType :: !CueFileType,
    -- | Collection of tracks in the file.
    CueFile -> NonEmpty CueTrack
cueFileTracks :: !(NonEmpty CueTrack)
  }
  deriving (Int -> CueFile -> ShowS
[CueFile] -> ShowS
CueFile -> FilePath
(Int -> CueFile -> ShowS)
-> (CueFile -> FilePath) -> ([CueFile] -> ShowS) -> Show CueFile
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
showList :: [CueFile] -> ShowS
$cshowList :: [CueFile] -> ShowS
show :: CueFile -> FilePath
$cshow :: CueFile -> FilePath
showsPrec :: Int -> CueFile -> ShowS
$cshowsPrec :: Int -> CueFile -> ShowS
Show, CueFile -> CueFile -> Bool
(CueFile -> CueFile -> Bool)
-> (CueFile -> CueFile -> Bool) -> Eq CueFile
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CueFile -> CueFile -> Bool
$c/= :: CueFile -> CueFile -> Bool
== :: CueFile -> CueFile -> Bool
$c== :: CueFile -> CueFile -> Bool
Eq, Eq CueFile
Eq CueFile
-> (CueFile -> CueFile -> Ordering)
-> (CueFile -> CueFile -> Bool)
-> (CueFile -> CueFile -> Bool)
-> (CueFile -> CueFile -> Bool)
-> (CueFile -> CueFile -> Bool)
-> (CueFile -> CueFile -> CueFile)
-> (CueFile -> CueFile -> CueFile)
-> Ord CueFile
CueFile -> CueFile -> Bool
CueFile -> CueFile -> Ordering
CueFile -> CueFile -> CueFile
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: CueFile -> CueFile -> CueFile
$cmin :: CueFile -> CueFile -> CueFile
max :: CueFile -> CueFile -> CueFile
$cmax :: CueFile -> CueFile -> CueFile
>= :: CueFile -> CueFile -> Bool
$c>= :: CueFile -> CueFile -> Bool
> :: CueFile -> CueFile -> Bool
$c> :: CueFile -> CueFile -> Bool
<= :: CueFile -> CueFile -> Bool
$c<= :: CueFile -> CueFile -> Bool
< :: CueFile -> CueFile -> Bool
$c< :: CueFile -> CueFile -> Bool
compare :: CueFile -> CueFile -> Ordering
$ccompare :: CueFile -> CueFile -> Ordering
$cp1Ord :: Eq CueFile
Ord, (forall x. CueFile -> Rep CueFile x)
-> (forall x. Rep CueFile x -> CueFile) -> Generic CueFile
forall x. Rep CueFile x -> CueFile
forall x. CueFile -> Rep CueFile x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep CueFile x -> CueFile
$cfrom :: forall x. CueFile -> Rep CueFile x
Generic)

instance Arbitrary CueFile where
  arbitrary :: Gen CueFile
arbitrary =
    FilePath -> CueFileType -> NonEmpty CueTrack -> CueFile
CueFile
      (FilePath -> CueFileType -> NonEmpty CueTrack -> CueFile)
-> Gen FilePath
-> Gen (CueFileType -> NonEmpty CueTrack -> CueFile)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen FilePath
filepath
      Gen (CueFileType -> NonEmpty CueTrack -> CueFile)
-> Gen CueFileType -> Gen (NonEmpty CueTrack -> CueFile)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen CueFileType
forall a. Arbitrary a => Gen a
arbitrary
      Gen (NonEmpty CueTrack -> CueFile)
-> Gen (NonEmpty CueTrack) -> Gen CueFile
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (NonEmpty CueTrack) -> Gen (NonEmpty CueTrack)
forall a. Gen a -> Gen a
scaleDown ([CueTrack] -> NonEmpty CueTrack
forall a. [a] -> NonEmpty a
NE.fromList ([CueTrack] -> NonEmpty CueTrack)
-> (NonEmptyList CueTrack -> [CueTrack])
-> NonEmptyList CueTrack
-> NonEmpty CueTrack
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmptyList CueTrack -> [CueTrack]
forall a. NonEmptyList a -> [a]
getNonEmpty (NonEmptyList CueTrack -> NonEmpty CueTrack)
-> Gen (NonEmptyList CueTrack) -> Gen (NonEmpty CueTrack)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (NonEmptyList CueTrack)
forall a. Arbitrary a => Gen a
arbitrary)

-- | Enumeration of audio or file's data types.
data CueFileType
  = -- | Intel binary file (least significant byte first). Use for data
    -- files.
    Binary
  | -- | Motorola binary file (most significant file first). Use for data
    -- files.
    Motorola
  | -- | Audio AIFF file (44.1 kHz, 16 bit stereo).
    Aiff
  | -- | Audio WAVE file (44.1 kHz, 16 bit stereo).
    Wave
  | -- | Audio MP3 file (44.1 kHz 16 bit stereo).
    MP3
  deriving (Int -> CueFileType -> ShowS
[CueFileType] -> ShowS
CueFileType -> FilePath
(Int -> CueFileType -> ShowS)
-> (CueFileType -> FilePath)
-> ([CueFileType] -> ShowS)
-> Show CueFileType
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
showList :: [CueFileType] -> ShowS
$cshowList :: [CueFileType] -> ShowS
show :: CueFileType -> FilePath
$cshow :: CueFileType -> FilePath
showsPrec :: Int -> CueFileType -> ShowS
$cshowsPrec :: Int -> CueFileType -> ShowS
Show, ReadPrec [CueFileType]
ReadPrec CueFileType
Int -> ReadS CueFileType
ReadS [CueFileType]
(Int -> ReadS CueFileType)
-> ReadS [CueFileType]
-> ReadPrec CueFileType
-> ReadPrec [CueFileType]
-> Read CueFileType
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [CueFileType]
$creadListPrec :: ReadPrec [CueFileType]
readPrec :: ReadPrec CueFileType
$creadPrec :: ReadPrec CueFileType
readList :: ReadS [CueFileType]
$creadList :: ReadS [CueFileType]
readsPrec :: Int -> ReadS CueFileType
$creadsPrec :: Int -> ReadS CueFileType
Read, CueFileType -> CueFileType -> Bool
(CueFileType -> CueFileType -> Bool)
-> (CueFileType -> CueFileType -> Bool) -> Eq CueFileType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CueFileType -> CueFileType -> Bool
$c/= :: CueFileType -> CueFileType -> Bool
== :: CueFileType -> CueFileType -> Bool
$c== :: CueFileType -> CueFileType -> Bool
Eq, Eq CueFileType
Eq CueFileType
-> (CueFileType -> CueFileType -> Ordering)
-> (CueFileType -> CueFileType -> Bool)
-> (CueFileType -> CueFileType -> Bool)
-> (CueFileType -> CueFileType -> Bool)
-> (CueFileType -> CueFileType -> Bool)
-> (CueFileType -> CueFileType -> CueFileType)
-> (CueFileType -> CueFileType -> CueFileType)
-> Ord CueFileType
CueFileType -> CueFileType -> Bool
CueFileType -> CueFileType -> Ordering
CueFileType -> CueFileType -> CueFileType
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: CueFileType -> CueFileType -> CueFileType
$cmin :: CueFileType -> CueFileType -> CueFileType
max :: CueFileType -> CueFileType -> CueFileType
$cmax :: CueFileType -> CueFileType -> CueFileType
>= :: CueFileType -> CueFileType -> Bool
$c>= :: CueFileType -> CueFileType -> Bool
> :: CueFileType -> CueFileType -> Bool
$c> :: CueFileType -> CueFileType -> Bool
<= :: CueFileType -> CueFileType -> Bool
$c<= :: CueFileType -> CueFileType -> Bool
< :: CueFileType -> CueFileType -> Bool
$c< :: CueFileType -> CueFileType -> Bool
compare :: CueFileType -> CueFileType -> Ordering
$ccompare :: CueFileType -> CueFileType -> Ordering
$cp1Ord :: Eq CueFileType
Ord, CueFileType
CueFileType -> CueFileType -> Bounded CueFileType
forall a. a -> a -> Bounded a
maxBound :: CueFileType
$cmaxBound :: CueFileType
minBound :: CueFileType
$cminBound :: CueFileType
Bounded, Int -> CueFileType
CueFileType -> Int
CueFileType -> [CueFileType]
CueFileType -> CueFileType
CueFileType -> CueFileType -> [CueFileType]
CueFileType -> CueFileType -> CueFileType -> [CueFileType]
(CueFileType -> CueFileType)
-> (CueFileType -> CueFileType)
-> (Int -> CueFileType)
-> (CueFileType -> Int)
-> (CueFileType -> [CueFileType])
-> (CueFileType -> CueFileType -> [CueFileType])
-> (CueFileType -> CueFileType -> [CueFileType])
-> (CueFileType -> CueFileType -> CueFileType -> [CueFileType])
-> Enum CueFileType
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: CueFileType -> CueFileType -> CueFileType -> [CueFileType]
$cenumFromThenTo :: CueFileType -> CueFileType -> CueFileType -> [CueFileType]
enumFromTo :: CueFileType -> CueFileType -> [CueFileType]
$cenumFromTo :: CueFileType -> CueFileType -> [CueFileType]
enumFromThen :: CueFileType -> CueFileType -> [CueFileType]
$cenumFromThen :: CueFileType -> CueFileType -> [CueFileType]
enumFrom :: CueFileType -> [CueFileType]
$cenumFrom :: CueFileType -> [CueFileType]
fromEnum :: CueFileType -> Int
$cfromEnum :: CueFileType -> Int
toEnum :: Int -> CueFileType
$ctoEnum :: Int -> CueFileType
pred :: CueFileType -> CueFileType
$cpred :: CueFileType -> CueFileType
succ :: CueFileType -> CueFileType
$csucc :: CueFileType -> CueFileType
Enum, (forall x. CueFileType -> Rep CueFileType x)
-> (forall x. Rep CueFileType x -> CueFileType)
-> Generic CueFileType
forall x. Rep CueFileType x -> CueFileType
forall x. CueFileType -> Rep CueFileType x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep CueFileType x -> CueFileType
$cfrom :: forall x. CueFileType -> Rep CueFileType x
Generic)

instance Arbitrary CueFileType where
  arbitrary :: Gen CueFileType
arbitrary = [CueFileType] -> Gen CueFileType
forall a. [a] -> Gen a
elements [CueFileType
forall a. Bounded a => a
minBound .. CueFileType
forall a. Bounded a => a
maxBound]

-- | A track. Single track can have one or more indices.
data CueTrack = CueTrack
  { -- | Flag: digital copy permitted.
    CueTrack -> Bool
cueTrackDigitalCopyPermitted :: !Bool,
    -- | Flag: four channel audio.
    CueTrack -> Bool
cueTrackFourChannelAudio :: !Bool,
    -- | Flag: pre-emphasis enabled (audio track only).
    CueTrack -> Bool
cueTrackPreemphasisEnabled :: !Bool,
    -- | Flag: serial copy management system (not supported by all
    -- recorders).
    CueTrack -> Bool
cueTrackSerialCopyManagement :: !Bool,
    -- | Type datatype.
    CueTrack -> CueTrackType
cueTrackType :: !CueTrackType,
    -- | The track's International Standard Recording Code (ISRC).
    CueTrack -> Maybe Isrc
cueTrackIsrc :: !(Maybe Isrc),
    -- | Title of the track.
    CueTrack -> Maybe CueText
cueTrackTitle :: !(Maybe CueText),
    -- | Performer of the track.
    CueTrack -> Maybe CueText
cueTrackPerformer :: !(Maybe CueText),
    -- | Songwriter of the track.
    CueTrack -> Maybe CueText
cueTrackSongwriter :: !(Maybe CueText),
    -- | Track's pregap.
    CueTrack -> Maybe CueTime
cueTrackPregap :: !(Maybe CueTime),
    -- | Starting time of track pregap, a.k.a. INDEX 0.
    CueTrack -> Maybe CueTime
cueTrackPregapIndex :: !(Maybe CueTime),
    -- | Collection of indices for the track starting with index 1. The
    -- index specifies the starting time of the track data. Index 1 is the
    -- only index that's stored in the disc's table of contents.
    CueTrack -> NonEmpty CueTime
cueTrackIndices :: !(NonEmpty CueTime),
    -- | Track's postgap.
    CueTrack -> Maybe CueTime
cueTrackPostgap :: !(Maybe CueTime)
  }
  deriving (Int -> CueTrack -> ShowS
[CueTrack] -> ShowS
CueTrack -> FilePath
(Int -> CueTrack -> ShowS)
-> (CueTrack -> FilePath) -> ([CueTrack] -> ShowS) -> Show CueTrack
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
showList :: [CueTrack] -> ShowS
$cshowList :: [CueTrack] -> ShowS
show :: CueTrack -> FilePath
$cshow :: CueTrack -> FilePath
showsPrec :: Int -> CueTrack -> ShowS
$cshowsPrec :: Int -> CueTrack -> ShowS
Show, CueTrack -> CueTrack -> Bool
(CueTrack -> CueTrack -> Bool)
-> (CueTrack -> CueTrack -> Bool) -> Eq CueTrack
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CueTrack -> CueTrack -> Bool
$c/= :: CueTrack -> CueTrack -> Bool
== :: CueTrack -> CueTrack -> Bool
$c== :: CueTrack -> CueTrack -> Bool
Eq, Eq CueTrack
Eq CueTrack
-> (CueTrack -> CueTrack -> Ordering)
-> (CueTrack -> CueTrack -> Bool)
-> (CueTrack -> CueTrack -> Bool)
-> (CueTrack -> CueTrack -> Bool)
-> (CueTrack -> CueTrack -> Bool)
-> (CueTrack -> CueTrack -> CueTrack)
-> (CueTrack -> CueTrack -> CueTrack)
-> Ord CueTrack
CueTrack -> CueTrack -> Bool
CueTrack -> CueTrack -> Ordering
CueTrack -> CueTrack -> CueTrack
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: CueTrack -> CueTrack -> CueTrack
$cmin :: CueTrack -> CueTrack -> CueTrack
max :: CueTrack -> CueTrack -> CueTrack
$cmax :: CueTrack -> CueTrack -> CueTrack
>= :: CueTrack -> CueTrack -> Bool
$c>= :: CueTrack -> CueTrack -> Bool
> :: CueTrack -> CueTrack -> Bool
$c> :: CueTrack -> CueTrack -> Bool
<= :: CueTrack -> CueTrack -> Bool
$c<= :: CueTrack -> CueTrack -> Bool
< :: CueTrack -> CueTrack -> Bool
$c< :: CueTrack -> CueTrack -> Bool
compare :: CueTrack -> CueTrack -> Ordering
$ccompare :: CueTrack -> CueTrack -> Ordering
$cp1Ord :: Eq CueTrack
Ord, (forall x. CueTrack -> Rep CueTrack x)
-> (forall x. Rep CueTrack x -> CueTrack) -> Generic CueTrack
forall x. Rep CueTrack x -> CueTrack
forall x. CueTrack -> Rep CueTrack x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep CueTrack x -> CueTrack
$cfrom :: forall x. CueTrack -> Rep CueTrack x
Generic)

instance Arbitrary CueTrack where
  arbitrary :: Gen CueTrack
arbitrary =
    Bool
-> Bool
-> Bool
-> Bool
-> CueTrackType
-> Maybe Isrc
-> Maybe CueText
-> Maybe CueText
-> Maybe CueText
-> Maybe CueTime
-> Maybe CueTime
-> NonEmpty CueTime
-> Maybe CueTime
-> CueTrack
CueTrack
      (Bool
 -> Bool
 -> Bool
 -> Bool
 -> CueTrackType
 -> Maybe Isrc
 -> Maybe CueText
 -> Maybe CueText
 -> Maybe CueText
 -> Maybe CueTime
 -> Maybe CueTime
 -> NonEmpty CueTime
 -> Maybe CueTime
 -> CueTrack)
-> Gen Bool
-> Gen
     (Bool
      -> Bool
      -> Bool
      -> CueTrackType
      -> Maybe Isrc
      -> Maybe CueText
      -> Maybe CueText
      -> Maybe CueText
      -> Maybe CueTime
      -> Maybe CueTime
      -> NonEmpty CueTime
      -> Maybe CueTime
      -> CueTrack)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Bool
forall a. Arbitrary a => Gen a
arbitrary
      Gen
  (Bool
   -> Bool
   -> Bool
   -> CueTrackType
   -> Maybe Isrc
   -> Maybe CueText
   -> Maybe CueText
   -> Maybe CueText
   -> Maybe CueTime
   -> Maybe CueTime
   -> NonEmpty CueTime
   -> Maybe CueTime
   -> CueTrack)
-> Gen Bool
-> Gen
     (Bool
      -> Bool
      -> CueTrackType
      -> Maybe Isrc
      -> Maybe CueText
      -> Maybe CueText
      -> Maybe CueText
      -> Maybe CueTime
      -> Maybe CueTime
      -> NonEmpty CueTime
      -> Maybe CueTime
      -> CueTrack)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen Bool
forall a. Arbitrary a => Gen a
arbitrary
      Gen
  (Bool
   -> Bool
   -> CueTrackType
   -> Maybe Isrc
   -> Maybe CueText
   -> Maybe CueText
   -> Maybe CueText
   -> Maybe CueTime
   -> Maybe CueTime
   -> NonEmpty CueTime
   -> Maybe CueTime
   -> CueTrack)
-> Gen Bool
-> Gen
     (Bool
      -> CueTrackType
      -> Maybe Isrc
      -> Maybe CueText
      -> Maybe CueText
      -> Maybe CueText
      -> Maybe CueTime
      -> Maybe CueTime
      -> NonEmpty CueTime
      -> Maybe CueTime
      -> CueTrack)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen Bool
forall a. Arbitrary a => Gen a
arbitrary
      Gen
  (Bool
   -> CueTrackType
   -> Maybe Isrc
   -> Maybe CueText
   -> Maybe CueText
   -> Maybe CueText
   -> Maybe CueTime
   -> Maybe CueTime
   -> NonEmpty CueTime
   -> Maybe CueTime
   -> CueTrack)
-> Gen Bool
-> Gen
     (CueTrackType
      -> Maybe Isrc
      -> Maybe CueText
      -> Maybe CueText
      -> Maybe CueText
      -> Maybe CueTime
      -> Maybe CueTime
      -> NonEmpty CueTime
      -> Maybe CueTime
      -> CueTrack)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen Bool
forall a. Arbitrary a => Gen a
arbitrary
      Gen
  (CueTrackType
   -> Maybe Isrc
   -> Maybe CueText
   -> Maybe CueText
   -> Maybe CueText
   -> Maybe CueTime
   -> Maybe CueTime
   -> NonEmpty CueTime
   -> Maybe CueTime
   -> CueTrack)
-> Gen CueTrackType
-> Gen
     (Maybe Isrc
      -> Maybe CueText
      -> Maybe CueText
      -> Maybe CueText
      -> Maybe CueTime
      -> Maybe CueTime
      -> NonEmpty CueTime
      -> Maybe CueTime
      -> CueTrack)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen CueTrackType
forall a. Arbitrary a => Gen a
arbitrary
      Gen
  (Maybe Isrc
   -> Maybe CueText
   -> Maybe CueText
   -> Maybe CueText
   -> Maybe CueTime
   -> Maybe CueTime
   -> NonEmpty CueTime
   -> Maybe CueTime
   -> CueTrack)
-> Gen (Maybe Isrc)
-> Gen
     (Maybe CueText
      -> Maybe CueText
      -> Maybe CueText
      -> Maybe CueTime
      -> Maybe CueTime
      -> NonEmpty CueTime
      -> Maybe CueTime
      -> CueTrack)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (Maybe Isrc)
forall a. Arbitrary a => Gen a
arbitrary
      Gen
  (Maybe CueText
   -> Maybe CueText
   -> Maybe CueText
   -> Maybe CueTime
   -> Maybe CueTime
   -> NonEmpty CueTime
   -> Maybe CueTime
   -> CueTrack)
-> Gen (Maybe CueText)
-> Gen
     (Maybe CueText
      -> Maybe CueText
      -> Maybe CueTime
      -> Maybe CueTime
      -> NonEmpty CueTime
      -> Maybe CueTime
      -> CueTrack)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (Maybe CueText)
forall a. Arbitrary a => Gen a
arbitrary
      Gen
  (Maybe CueText
   -> Maybe CueText
   -> Maybe CueTime
   -> Maybe CueTime
   -> NonEmpty CueTime
   -> Maybe CueTime
   -> CueTrack)
-> Gen (Maybe CueText)
-> Gen
     (Maybe CueText
      -> Maybe CueTime
      -> Maybe CueTime
      -> NonEmpty CueTime
      -> Maybe CueTime
      -> CueTrack)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (Maybe CueText)
forall a. Arbitrary a => Gen a
arbitrary
      Gen
  (Maybe CueText
   -> Maybe CueTime
   -> Maybe CueTime
   -> NonEmpty CueTime
   -> Maybe CueTime
   -> CueTrack)
-> Gen (Maybe CueText)
-> Gen
     (Maybe CueTime
      -> Maybe CueTime -> NonEmpty CueTime -> Maybe CueTime -> CueTrack)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (Maybe CueText)
forall a. Arbitrary a => Gen a
arbitrary
      Gen
  (Maybe CueTime
   -> Maybe CueTime -> NonEmpty CueTime -> Maybe CueTime -> CueTrack)
-> Gen (Maybe CueTime)
-> Gen
     (Maybe CueTime -> NonEmpty CueTime -> Maybe CueTime -> CueTrack)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (Maybe CueTime)
forall a. Arbitrary a => Gen a
arbitrary
      Gen
  (Maybe CueTime -> NonEmpty CueTime -> Maybe CueTime -> CueTrack)
-> Gen (Maybe CueTime)
-> Gen (NonEmpty CueTime -> Maybe CueTime -> CueTrack)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (Maybe CueTime)
forall a. Arbitrary a => Gen a
arbitrary
      Gen (NonEmpty CueTime -> Maybe CueTime -> CueTrack)
-> Gen (NonEmpty CueTime) -> Gen (Maybe CueTime -> CueTrack)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (NonEmpty CueTime) -> Gen (NonEmpty CueTime)
forall a. Gen a -> Gen a
scaleDown ([CueTime] -> NonEmpty CueTime
forall a. [a] -> NonEmpty a
NE.fromList ([CueTime] -> NonEmpty CueTime)
-> (NonEmptyList CueTime -> [CueTime])
-> NonEmptyList CueTime
-> NonEmpty CueTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmptyList CueTime -> [CueTime]
forall a. NonEmptyList a -> [a]
getNonEmpty (NonEmptyList CueTime -> NonEmpty CueTime)
-> Gen (NonEmptyList CueTime) -> Gen (NonEmpty CueTime)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (NonEmptyList CueTime)
forall a. Arbitrary a => Gen a
arbitrary)
      Gen (Maybe CueTime -> CueTrack)
-> Gen (Maybe CueTime) -> Gen CueTrack
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (Maybe CueTime)
forall a. Arbitrary a => Gen a
arbitrary

-- | Track datatype.
data CueTrackType
  = -- | Audio\/Music (2352).
    CueTrackAudio
  | -- | Karaoke CD+G (2448).
    CueTrackCdg
  | -- | CD-ROM Mode1 data (cooked).
    CueTrackMode1_2048
  | -- | CD-ROM Mode1 data (raw).
    CueTrackMode1_2352
  | -- | CD-ROM XA Mode2 data.
    CueTrackMode2_2336
  | -- | CD-ROM XA Mode2 data.
    CueTrackMode2_2352
  | -- | CD-I Mode2 data.
    CueTrackCdi2336
  | -- | CD-I Mode2 data.
    CueTrackCdi2352
  deriving (Int -> CueTrackType -> ShowS
[CueTrackType] -> ShowS
CueTrackType -> FilePath
(Int -> CueTrackType -> ShowS)
-> (CueTrackType -> FilePath)
-> ([CueTrackType] -> ShowS)
-> Show CueTrackType
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
showList :: [CueTrackType] -> ShowS
$cshowList :: [CueTrackType] -> ShowS
show :: CueTrackType -> FilePath
$cshow :: CueTrackType -> FilePath
showsPrec :: Int -> CueTrackType -> ShowS
$cshowsPrec :: Int -> CueTrackType -> ShowS
Show, ReadPrec [CueTrackType]
ReadPrec CueTrackType
Int -> ReadS CueTrackType
ReadS [CueTrackType]
(Int -> ReadS CueTrackType)
-> ReadS [CueTrackType]
-> ReadPrec CueTrackType
-> ReadPrec [CueTrackType]
-> Read CueTrackType
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [CueTrackType]
$creadListPrec :: ReadPrec [CueTrackType]
readPrec :: ReadPrec CueTrackType
$creadPrec :: ReadPrec CueTrackType
readList :: ReadS [CueTrackType]
$creadList :: ReadS [CueTrackType]
readsPrec :: Int -> ReadS CueTrackType
$creadsPrec :: Int -> ReadS CueTrackType
Read, CueTrackType -> CueTrackType -> Bool
(CueTrackType -> CueTrackType -> Bool)
-> (CueTrackType -> CueTrackType -> Bool) -> Eq CueTrackType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CueTrackType -> CueTrackType -> Bool
$c/= :: CueTrackType -> CueTrackType -> Bool
== :: CueTrackType -> CueTrackType -> Bool
$c== :: CueTrackType -> CueTrackType -> Bool
Eq, Eq CueTrackType
Eq CueTrackType
-> (CueTrackType -> CueTrackType -> Ordering)
-> (CueTrackType -> CueTrackType -> Bool)
-> (CueTrackType -> CueTrackType -> Bool)
-> (CueTrackType -> CueTrackType -> Bool)
-> (CueTrackType -> CueTrackType -> Bool)
-> (CueTrackType -> CueTrackType -> CueTrackType)
-> (CueTrackType -> CueTrackType -> CueTrackType)
-> Ord CueTrackType
CueTrackType -> CueTrackType -> Bool
CueTrackType -> CueTrackType -> Ordering
CueTrackType -> CueTrackType -> CueTrackType
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: CueTrackType -> CueTrackType -> CueTrackType
$cmin :: CueTrackType -> CueTrackType -> CueTrackType
max :: CueTrackType -> CueTrackType -> CueTrackType
$cmax :: CueTrackType -> CueTrackType -> CueTrackType
>= :: CueTrackType -> CueTrackType -> Bool
$c>= :: CueTrackType -> CueTrackType -> Bool
> :: CueTrackType -> CueTrackType -> Bool
$c> :: CueTrackType -> CueTrackType -> Bool
<= :: CueTrackType -> CueTrackType -> Bool
$c<= :: CueTrackType -> CueTrackType -> Bool
< :: CueTrackType -> CueTrackType -> Bool
$c< :: CueTrackType -> CueTrackType -> Bool
compare :: CueTrackType -> CueTrackType -> Ordering
$ccompare :: CueTrackType -> CueTrackType -> Ordering
$cp1Ord :: Eq CueTrackType
Ord, CueTrackType
CueTrackType -> CueTrackType -> Bounded CueTrackType
forall a. a -> a -> Bounded a
maxBound :: CueTrackType
$cmaxBound :: CueTrackType
minBound :: CueTrackType
$cminBound :: CueTrackType
Bounded, Int -> CueTrackType
CueTrackType -> Int
CueTrackType -> [CueTrackType]
CueTrackType -> CueTrackType
CueTrackType -> CueTrackType -> [CueTrackType]
CueTrackType -> CueTrackType -> CueTrackType -> [CueTrackType]
(CueTrackType -> CueTrackType)
-> (CueTrackType -> CueTrackType)
-> (Int -> CueTrackType)
-> (CueTrackType -> Int)
-> (CueTrackType -> [CueTrackType])
-> (CueTrackType -> CueTrackType -> [CueTrackType])
-> (CueTrackType -> CueTrackType -> [CueTrackType])
-> (CueTrackType -> CueTrackType -> CueTrackType -> [CueTrackType])
-> Enum CueTrackType
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: CueTrackType -> CueTrackType -> CueTrackType -> [CueTrackType]
$cenumFromThenTo :: CueTrackType -> CueTrackType -> CueTrackType -> [CueTrackType]
enumFromTo :: CueTrackType -> CueTrackType -> [CueTrackType]
$cenumFromTo :: CueTrackType -> CueTrackType -> [CueTrackType]
enumFromThen :: CueTrackType -> CueTrackType -> [CueTrackType]
$cenumFromThen :: CueTrackType -> CueTrackType -> [CueTrackType]
enumFrom :: CueTrackType -> [CueTrackType]
$cenumFrom :: CueTrackType -> [CueTrackType]
fromEnum :: CueTrackType -> Int
$cfromEnum :: CueTrackType -> Int
toEnum :: Int -> CueTrackType
$ctoEnum :: Int -> CueTrackType
pred :: CueTrackType -> CueTrackType
$cpred :: CueTrackType -> CueTrackType
succ :: CueTrackType -> CueTrackType
$csucc :: CueTrackType -> CueTrackType
Enum, (forall x. CueTrackType -> Rep CueTrackType x)
-> (forall x. Rep CueTrackType x -> CueTrackType)
-> Generic CueTrackType
forall x. Rep CueTrackType x -> CueTrackType
forall x. CueTrackType -> Rep CueTrackType x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep CueTrackType x -> CueTrackType
$cfrom :: forall x. CueTrackType -> Rep CueTrackType x
Generic)

instance Arbitrary CueTrackType where
  arbitrary :: Gen CueTrackType
arbitrary = [CueTrackType] -> Gen CueTrackType
forall a. [a] -> Gen a
elements [CueTrackType
forall a. Bounded a => a
minBound .. CueTrackType
forall a. Bounded a => a
maxBound]

-- | This datatype is used to indicate duration and position in time. It
-- contains number of frames. There are 75 frames in one second.
newtype CueTime = CueTime Natural
  deriving (Int -> CueTime -> ShowS
[CueTime] -> ShowS
CueTime -> FilePath
(Int -> CueTime -> ShowS)
-> (CueTime -> FilePath) -> ([CueTime] -> ShowS) -> Show CueTime
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
showList :: [CueTime] -> ShowS
$cshowList :: [CueTime] -> ShowS
show :: CueTime -> FilePath
$cshow :: CueTime -> FilePath
showsPrec :: Int -> CueTime -> ShowS
$cshowsPrec :: Int -> CueTime -> ShowS
Show, ReadPrec [CueTime]
ReadPrec CueTime
Int -> ReadS CueTime
ReadS [CueTime]
(Int -> ReadS CueTime)
-> ReadS [CueTime]
-> ReadPrec CueTime
-> ReadPrec [CueTime]
-> Read CueTime
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [CueTime]
$creadListPrec :: ReadPrec [CueTime]
readPrec :: ReadPrec CueTime
$creadPrec :: ReadPrec CueTime
readList :: ReadS [CueTime]
$creadList :: ReadS [CueTime]
readsPrec :: Int -> ReadS CueTime
$creadsPrec :: Int -> ReadS CueTime
Read, CueTime -> CueTime -> Bool
(CueTime -> CueTime -> Bool)
-> (CueTime -> CueTime -> Bool) -> Eq CueTime
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CueTime -> CueTime -> Bool
$c/= :: CueTime -> CueTime -> Bool
== :: CueTime -> CueTime -> Bool
$c== :: CueTime -> CueTime -> Bool
Eq, Eq CueTime
Eq CueTime
-> (CueTime -> CueTime -> Ordering)
-> (CueTime -> CueTime -> Bool)
-> (CueTime -> CueTime -> Bool)
-> (CueTime -> CueTime -> Bool)
-> (CueTime -> CueTime -> Bool)
-> (CueTime -> CueTime -> CueTime)
-> (CueTime -> CueTime -> CueTime)
-> Ord CueTime
CueTime -> CueTime -> Bool
CueTime -> CueTime -> Ordering
CueTime -> CueTime -> CueTime
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: CueTime -> CueTime -> CueTime
$cmin :: CueTime -> CueTime -> CueTime
max :: CueTime -> CueTime -> CueTime
$cmax :: CueTime -> CueTime -> CueTime
>= :: CueTime -> CueTime -> Bool
$c>= :: CueTime -> CueTime -> Bool
> :: CueTime -> CueTime -> Bool
$c> :: CueTime -> CueTime -> Bool
<= :: CueTime -> CueTime -> Bool
$c<= :: CueTime -> CueTime -> Bool
< :: CueTime -> CueTime -> Bool
$c< :: CueTime -> CueTime -> Bool
compare :: CueTime -> CueTime -> Ordering
$ccompare :: CueTime -> CueTime -> Ordering
$cp1Ord :: Eq CueTime
Ord, (forall x. CueTime -> Rep CueTime x)
-> (forall x. Rep CueTime x -> CueTime) -> Generic CueTime
forall x. Rep CueTime x -> CueTime
forall x. CueTime -> Rep CueTime x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep CueTime x -> CueTime
$cfrom :: forall x. CueTime -> Rep CueTime x
Generic)

instance Arbitrary CueTime where
  arbitrary :: Gen CueTime
arbitrary = Natural -> CueTime
CueTime (Natural -> CueTime)
-> (NonNegative Integer -> Natural)
-> NonNegative Integer
-> CueTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Natural
forall a. Num a => Integer -> a
fromInteger (Integer -> Natural)
-> (NonNegative Integer -> Integer)
-> NonNegative Integer
-> Natural
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonNegative Integer -> Integer
forall a. NonNegative a -> a
getNonNegative (NonNegative Integer -> CueTime)
-> Gen (NonNegative Integer) -> Gen CueTime
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (NonNegative Integer)
forall a. Arbitrary a => Gen a
arbitrary

-- | Construct 'CueTime' from minutes, seconds, and frames. There are 75
-- frames per second. If number of seconds or frames is invalid,
-- 'InvalidSeconds' or 'InvalidFrames' will be thrown.
fromMmSsFf ::
  MonadThrow m =>
  -- | Number of minutes, no limit here
  Natural ->
  -- | Number of seconds, 0–59 inclusive
  Natural ->
  -- | Number of frames, 0–74 inclusive
  Natural ->
  -- | The result
  m CueTime
fromMmSsFf :: Natural -> Natural -> Natural -> m CueTime
fromMmSsFf Natural
mm Natural
ss Natural
ff
  | Natural
ss Natural -> Natural -> Bool
forall a. Ord a => a -> a -> Bool
>= Natural
60 = CueSheetException -> m CueTime
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (Natural -> CueSheetException
InvalidSeconds Natural
ss)
  | Natural
ff Natural -> Natural -> Bool
forall a. Ord a => a -> a -> Bool
>= Natural
75 = CueSheetException -> m CueTime
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (Natural -> CueSheetException
InvalidFrames Natural
ff)
  | Bool
otherwise =
      let ss' :: Natural
ss' = Natural
mm Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
* Natural
60 Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
+ Natural
ss
          ff' :: Natural
ff' = Natural
ss' Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
* Natural
75 Natural -> Natural -> Natural
forall a. Num a => a -> a -> a
+ Natural
ff
       in CueTime -> m CueTime
forall (m :: * -> *) a. Monad m => a -> m a
return (Natural -> CueTime
CueTime Natural
ff')

-- | Get minutes, seconds, and frames from a 'CueTime' value.
toMmSsFf :: CueTime -> (Natural, Natural, Natural)
toMmSsFf :: CueTime -> (Natural, Natural, Natural)
toMmSsFf (CueTime Natural
ff') = (Natural
mm, Natural
ss, Natural
ff)
  where
    (Natural
ss', Natural
ff) = Natural
ff' Natural -> Natural -> (Natural, Natural)
forall a. Integral a => a -> a -> (a, a)
`quotRem` Natural
75
    (Natural
mm, Natural
ss) = Natural
ss' Natural -> Natural -> (Natural, Natural)
forall a. Integral a => a -> a -> (a, a)
`quotRem` Natural
60

-- | Render representation of 'CueTime' in @mm:ss:ff@ format.
showMmSsFf :: CueTime -> Text
showMmSsFf :: CueTime -> Text
showMmSsFf CueTime
x = FilePath -> Text
T.pack (FilePath -> Natural -> Natural -> Natural -> FilePath
forall r. PrintfType r => FilePath -> r
printf FilePath
"%02d:%02d:%02d" Natural
mm Natural
ss Natural
ff)
  where
    (Natural
mm, Natural
ss, Natural
ff) = CueTime -> (Natural, Natural, Natural)
toMmSsFf CueTime
x

-- | Disc's Media Catalog Number (MCN), must be 13 characters long, all the
-- characters must be numeric.
newtype Mcn = Mcn Text
  deriving (Mcn -> Mcn -> Bool
(Mcn -> Mcn -> Bool) -> (Mcn -> Mcn -> Bool) -> Eq Mcn
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Mcn -> Mcn -> Bool
$c/= :: Mcn -> Mcn -> Bool
== :: Mcn -> Mcn -> Bool
$c== :: Mcn -> Mcn -> Bool
Eq, Eq Mcn
Eq Mcn
-> (Mcn -> Mcn -> Ordering)
-> (Mcn -> Mcn -> Bool)
-> (Mcn -> Mcn -> Bool)
-> (Mcn -> Mcn -> Bool)
-> (Mcn -> Mcn -> Bool)
-> (Mcn -> Mcn -> Mcn)
-> (Mcn -> Mcn -> Mcn)
-> Ord Mcn
Mcn -> Mcn -> Bool
Mcn -> Mcn -> Ordering
Mcn -> Mcn -> Mcn
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Mcn -> Mcn -> Mcn
$cmin :: Mcn -> Mcn -> Mcn
max :: Mcn -> Mcn -> Mcn
$cmax :: Mcn -> Mcn -> Mcn
>= :: Mcn -> Mcn -> Bool
$c>= :: Mcn -> Mcn -> Bool
> :: Mcn -> Mcn -> Bool
$c> :: Mcn -> Mcn -> Bool
<= :: Mcn -> Mcn -> Bool
$c<= :: Mcn -> Mcn -> Bool
< :: Mcn -> Mcn -> Bool
$c< :: Mcn -> Mcn -> Bool
compare :: Mcn -> Mcn -> Ordering
$ccompare :: Mcn -> Mcn -> Ordering
$cp1Ord :: Eq Mcn
Ord, (forall x. Mcn -> Rep Mcn x)
-> (forall x. Rep Mcn x -> Mcn) -> Generic Mcn
forall x. Rep Mcn x -> Mcn
forall x. Mcn -> Rep Mcn x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Mcn x -> Mcn
$cfrom :: forall x. Mcn -> Rep Mcn x
Generic)

instance Show Mcn where
  show :: Mcn -> FilePath
show = Text -> FilePath
forall a. Show a => a -> FilePath
show (Text -> FilePath) -> (Mcn -> Text) -> Mcn -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Mcn -> Text
unMcn

instance Arbitrary Mcn where
  arbitrary :: Gen Mcn
arbitrary = Text -> Mcn
Mcn (Text -> Mcn) -> (FilePath -> Text) -> FilePath -> Mcn
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Text
T.pack (FilePath -> Mcn) -> Gen FilePath -> Gen Mcn
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> Gen Char -> Gen FilePath
forall a. Int -> Gen a -> Gen [a]
vectorOf Int
13 (Gen Char
forall a. Arbitrary a => Gen a
arbitrary Gen Char -> (Char -> Bool) -> Gen Char
forall a. Gen a -> (a -> Bool) -> Gen a
`suchThat` Char -> Bool
isDigit)

-- | Make a 'Mcn'. If the provided 'Text' value is not a valid MCN, throw
-- the 'InvalidMcnException'.
mkMcn :: MonadThrow m => Text -> m Mcn
mkMcn :: Text -> m Mcn
mkMcn Text
x =
  if Text -> Bool
isValidMcn Text
x
    then Mcn -> m Mcn
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> Mcn
Mcn Text
x)
    else CueSheetException -> m Mcn
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (Text -> CueSheetException
InvalidMcn Text
x)

-- | Get 'Text' from 'Mcn'.
unMcn :: Mcn -> Text
unMcn :: Mcn -> Text
unMcn (Mcn Text
x) = Text
x

-- | A type for things like title or performer that should have length
-- between 1 and 80 characters as per spec. We also demand that it does not
-- contain @\"@ and newline characters, as it's not clear from the spec how
-- to escape them properly.
newtype CueText = CueText Text
  deriving (CueText -> CueText -> Bool
(CueText -> CueText -> Bool)
-> (CueText -> CueText -> Bool) -> Eq CueText
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CueText -> CueText -> Bool
$c/= :: CueText -> CueText -> Bool
== :: CueText -> CueText -> Bool
$c== :: CueText -> CueText -> Bool
Eq, Eq CueText
Eq CueText
-> (CueText -> CueText -> Ordering)
-> (CueText -> CueText -> Bool)
-> (CueText -> CueText -> Bool)
-> (CueText -> CueText -> Bool)
-> (CueText -> CueText -> Bool)
-> (CueText -> CueText -> CueText)
-> (CueText -> CueText -> CueText)
-> Ord CueText
CueText -> CueText -> Bool
CueText -> CueText -> Ordering
CueText -> CueText -> CueText
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: CueText -> CueText -> CueText
$cmin :: CueText -> CueText -> CueText
max :: CueText -> CueText -> CueText
$cmax :: CueText -> CueText -> CueText
>= :: CueText -> CueText -> Bool
$c>= :: CueText -> CueText -> Bool
> :: CueText -> CueText -> Bool
$c> :: CueText -> CueText -> Bool
<= :: CueText -> CueText -> Bool
$c<= :: CueText -> CueText -> Bool
< :: CueText -> CueText -> Bool
$c< :: CueText -> CueText -> Bool
compare :: CueText -> CueText -> Ordering
$ccompare :: CueText -> CueText -> Ordering
$cp1Ord :: Eq CueText
Ord, (forall x. CueText -> Rep CueText x)
-> (forall x. Rep CueText x -> CueText) -> Generic CueText
forall x. Rep CueText x -> CueText
forall x. CueText -> Rep CueText x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep CueText x -> CueText
$cfrom :: forall x. CueText -> Rep CueText x
Generic)

instance Show CueText where
  show :: CueText -> FilePath
show = Text -> FilePath
forall a. Show a => a -> FilePath
show (Text -> FilePath) -> (CueText -> Text) -> CueText -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CueText -> Text
unCueText

instance Arbitrary CueText where
  arbitrary :: Gen CueText
arbitrary = Text -> CueText
CueText (Text -> CueText) -> Gen Text -> Gen CueText
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((FilePath -> Text
T.pack (FilePath -> Text) -> Gen FilePath -> Gen Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen FilePath
forall a. Arbitrary a => Gen a
arbitrary) Gen Text -> (Text -> Bool) -> Gen Text
forall a. Gen a -> (a -> Bool) -> Gen a
`suchThat` Text -> Bool
isValidCueText)

-- | Make a 'CueText'. If the provided 'Text' value is not a valid CUE text,
-- throw the 'InvalidCueText' exception.
mkCueText :: MonadThrow m => Text -> m CueText
mkCueText :: Text -> m CueText
mkCueText Text
x =
  if Text -> Bool
isValidCueText Text
x
    then CueText -> m CueText
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> CueText
CueText Text
x)
    else CueSheetException -> m CueText
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (Text -> CueSheetException
InvalidCueText Text
x)

-- | Get 'Text' from 'CueText'.
unCueText :: CueText -> Text
unCueText :: CueText -> Text
unCueText (CueText Text
x) = Text
x

-- | The track's International Standard Recording Code (ISRC). It must be 12
-- characters in length. The first five characters are alphanumeric, the
-- last seven are numeric only.
newtype Isrc = Isrc Text
  deriving (Isrc -> Isrc -> Bool
(Isrc -> Isrc -> Bool) -> (Isrc -> Isrc -> Bool) -> Eq Isrc
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Isrc -> Isrc -> Bool
$c/= :: Isrc -> Isrc -> Bool
== :: Isrc -> Isrc -> Bool
$c== :: Isrc -> Isrc -> Bool
Eq, Eq Isrc
Eq Isrc
-> (Isrc -> Isrc -> Ordering)
-> (Isrc -> Isrc -> Bool)
-> (Isrc -> Isrc -> Bool)
-> (Isrc -> Isrc -> Bool)
-> (Isrc -> Isrc -> Bool)
-> (Isrc -> Isrc -> Isrc)
-> (Isrc -> Isrc -> Isrc)
-> Ord Isrc
Isrc -> Isrc -> Bool
Isrc -> Isrc -> Ordering
Isrc -> Isrc -> Isrc
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Isrc -> Isrc -> Isrc
$cmin :: Isrc -> Isrc -> Isrc
max :: Isrc -> Isrc -> Isrc
$cmax :: Isrc -> Isrc -> Isrc
>= :: Isrc -> Isrc -> Bool
$c>= :: Isrc -> Isrc -> Bool
> :: Isrc -> Isrc -> Bool
$c> :: Isrc -> Isrc -> Bool
<= :: Isrc -> Isrc -> Bool
$c<= :: Isrc -> Isrc -> Bool
< :: Isrc -> Isrc -> Bool
$c< :: Isrc -> Isrc -> Bool
compare :: Isrc -> Isrc -> Ordering
$ccompare :: Isrc -> Isrc -> Ordering
$cp1Ord :: Eq Isrc
Ord, (forall x. Isrc -> Rep Isrc x)
-> (forall x. Rep Isrc x -> Isrc) -> Generic Isrc
forall x. Rep Isrc x -> Isrc
forall x. Isrc -> Rep Isrc x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Isrc x -> Isrc
$cfrom :: forall x. Isrc -> Rep Isrc x
Generic)

instance Show Isrc where
  show :: Isrc -> FilePath
show = Text -> FilePath
forall a. Show a => a -> FilePath
show (Text -> FilePath) -> (Isrc -> Text) -> Isrc -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Isrc -> Text
unIsrc

instance Arbitrary Isrc where
  arbitrary :: Gen Isrc
arbitrary = do
    FilePath
pre <- Int -> Gen Char -> Gen FilePath
forall a. Int -> Gen a -> Gen [a]
vectorOf Int
5 (Gen Char
forall a. Arbitrary a => Gen a
arbitrary Gen Char -> (Char -> Bool) -> Gen Char
forall a. Gen a -> (a -> Bool) -> Gen a
`suchThat` Char -> Bool
isAlphaNum)
    FilePath
post <- Int -> Gen Char -> Gen FilePath
forall a. Int -> Gen a -> Gen [a]
vectorOf Int
7 (Gen Char
forall a. Arbitrary a => Gen a
arbitrary Gen Char -> (Char -> Bool) -> Gen Char
forall a. Gen a -> (a -> Bool) -> Gen a
`suchThat` Char -> Bool
isDigit)
    (Isrc -> Gen Isrc
forall (m :: * -> *) a. Monad m => a -> m a
return (Isrc -> Gen Isrc) -> (FilePath -> Isrc) -> FilePath -> Gen Isrc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Isrc
Isrc (Text -> Isrc) -> (FilePath -> Text) -> FilePath -> Isrc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Text
T.pack) (FilePath
pre FilePath -> ShowS
forall a. Semigroup a => a -> a -> a
<> FilePath
post)

-- | Make an 'Isrc', if the provided 'Text' value is not a valid ISRC, throw
-- the 'InvalidIsrc' exception.
mkIsrc :: MonadThrow m => Text -> m Isrc
mkIsrc :: Text -> m Isrc
mkIsrc Text
x =
  if Text -> Int
T.length Text
x Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
12
    Bool -> Bool -> Bool
&& (Char -> Bool) -> Text -> Bool
T.all Char -> Bool
isAlphaNum (Int -> Text -> Text
T.take Int
5 Text
x)
    Bool -> Bool -> Bool
&& (Char -> Bool) -> Text -> Bool
T.all Char -> Bool
isDigit (Int -> Text -> Text
T.drop Int
5 Text
x)
    then Isrc -> m Isrc
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> Isrc
Isrc Text
x)
    else CueSheetException -> m Isrc
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM (Text -> CueSheetException
InvalidIsrc Text
x)

-- | Get 'Text' from 'Isrc'.
unIsrc :: Isrc -> Text
unIsrc :: Isrc -> Text
unIsrc (Isrc Text
x) = Text
x

-- | Exception type for the bad things that may happen while you use the
-- library.
data CueSheetException
  = -- | The value is greater than 59 and thus is invalid for 'fromMmSsFf'.
    InvalidSeconds Natural
  | -- | The value is greater than 74 and thus is invalid for 'fromMmSsFf'.
    InvalidFrames Natural
  | -- | Provided text wasn't a correct media catalog number (MCN).
    InvalidMcn Text
  | -- | Provided text wasn't a valid CUE text.
    InvalidCueText Text
  | -- | Provided text wasn't a valid ISRC.
    InvalidIsrc Text
  deriving (CueSheetException -> CueSheetException -> Bool
(CueSheetException -> CueSheetException -> Bool)
-> (CueSheetException -> CueSheetException -> Bool)
-> Eq CueSheetException
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CueSheetException -> CueSheetException -> Bool
$c/= :: CueSheetException -> CueSheetException -> Bool
== :: CueSheetException -> CueSheetException -> Bool
$c== :: CueSheetException -> CueSheetException -> Bool
Eq, Eq CueSheetException
Eq CueSheetException
-> (CueSheetException -> CueSheetException -> Ordering)
-> (CueSheetException -> CueSheetException -> Bool)
-> (CueSheetException -> CueSheetException -> Bool)
-> (CueSheetException -> CueSheetException -> Bool)
-> (CueSheetException -> CueSheetException -> Bool)
-> (CueSheetException -> CueSheetException -> CueSheetException)
-> (CueSheetException -> CueSheetException -> CueSheetException)
-> Ord CueSheetException
CueSheetException -> CueSheetException -> Bool
CueSheetException -> CueSheetException -> Ordering
CueSheetException -> CueSheetException -> CueSheetException
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: CueSheetException -> CueSheetException -> CueSheetException
$cmin :: CueSheetException -> CueSheetException -> CueSheetException
max :: CueSheetException -> CueSheetException -> CueSheetException
$cmax :: CueSheetException -> CueSheetException -> CueSheetException
>= :: CueSheetException -> CueSheetException -> Bool
$c>= :: CueSheetException -> CueSheetException -> Bool
> :: CueSheetException -> CueSheetException -> Bool
$c> :: CueSheetException -> CueSheetException -> Bool
<= :: CueSheetException -> CueSheetException -> Bool
$c<= :: CueSheetException -> CueSheetException -> Bool
< :: CueSheetException -> CueSheetException -> Bool
$c< :: CueSheetException -> CueSheetException -> Bool
compare :: CueSheetException -> CueSheetException -> Ordering
$ccompare :: CueSheetException -> CueSheetException -> Ordering
$cp1Ord :: Eq CueSheetException
Ord, Int -> CueSheetException -> ShowS
[CueSheetException] -> ShowS
CueSheetException -> FilePath
(Int -> CueSheetException -> ShowS)
-> (CueSheetException -> FilePath)
-> ([CueSheetException] -> ShowS)
-> Show CueSheetException
forall a.
(Int -> a -> ShowS) -> (a -> FilePath) -> ([a] -> ShowS) -> Show a
showList :: [CueSheetException] -> ShowS
$cshowList :: [CueSheetException] -> ShowS
show :: CueSheetException -> FilePath
$cshow :: CueSheetException -> FilePath
showsPrec :: Int -> CueSheetException -> ShowS
$cshowsPrec :: Int -> CueSheetException -> ShowS
Show, ReadPrec [CueSheetException]
ReadPrec CueSheetException
Int -> ReadS CueSheetException
ReadS [CueSheetException]
(Int -> ReadS CueSheetException)
-> ReadS [CueSheetException]
-> ReadPrec CueSheetException
-> ReadPrec [CueSheetException]
-> Read CueSheetException
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [CueSheetException]
$creadListPrec :: ReadPrec [CueSheetException]
readPrec :: ReadPrec CueSheetException
$creadPrec :: ReadPrec CueSheetException
readList :: ReadS [CueSheetException]
$creadList :: ReadS [CueSheetException]
readsPrec :: Int -> ReadS CueSheetException
$creadsPrec :: Int -> ReadS CueSheetException
Read, (forall x. CueSheetException -> Rep CueSheetException x)
-> (forall x. Rep CueSheetException x -> CueSheetException)
-> Generic CueSheetException
forall x. Rep CueSheetException x -> CueSheetException
forall x. CueSheetException -> Rep CueSheetException x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep CueSheetException x -> CueSheetException
$cfrom :: forall x. CueSheetException -> Rep CueSheetException x
Generic)

instance Exception CueSheetException

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

-- | Check if the given 'Text' is a valid MCN.
isValidMcn :: Text -> Bool
isValidMcn :: Text -> Bool
isValidMcn Text
x = Text -> Int
T.length Text
x Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
13 Bool -> Bool -> Bool
&& (Char -> Bool) -> Text -> Bool
T.all Char -> Bool
isDigit Text
x

-- | Check if the given 'Text' has valid length and contents to be used in a
-- CUE sheet as performer, title, etc.
isValidCueText :: Text -> Bool
isValidCueText :: Text -> Bool
isValidCueText Text
x = Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
1 Bool -> Bool -> Bool
&& Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
80 Bool -> Bool -> Bool
&& (Char -> Bool) -> Text -> Bool
T.all Char -> Bool
f Text
x
  where
    l :: Int
l = Text -> Int
T.length Text
x
    f :: Char -> Bool
f Char
c = Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'\"' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'\n'

-- | A variant of 'Data.Char.IsAlphaNum' that only permits ASCII letter
-- chars.
isAlphaNum :: Char -> Bool
isAlphaNum :: Char -> Bool
isAlphaNum Char
a = Char -> Bool
isAscii Char
a Bool -> Bool -> Bool
&& (Char -> Bool
isDigit Char
a Bool -> Bool -> Bool
|| Char -> Bool
isLetter Char
a)

-- | Scale down size of 'arbitrary'-generated stuff.
scaleDown :: Gen a -> Gen a
scaleDown :: Gen a -> Gen a
scaleDown = (Int -> Int) -> Gen a -> Gen a
forall a. (Int -> Int) -> Gen a -> Gen a
scale (Int -> Int -> Int
forall a. Integral a => a -> a -> a
`quot` Int
3)

-- | File path generator.
filepath :: Gen FilePath
filepath :: Gen FilePath
filepath = Gen Char -> Gen FilePath
forall a. Gen a -> Gen [a]
listOf (Gen Char
forall a. Arbitrary a => Gen a
arbitrary Gen Char -> (Char -> Bool) -> Gen Char
forall a. Gen a -> (a -> Bool) -> Gen a
`suchThat` Char -> Bool
windowsLikesIt)
  where
    windowsLikesIt :: Char -> Bool
windowsLikesIt = (Char -> FilePath -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` FilePath
"?%*:<>#|\"\\\n")