{-# LANGUAGE ForeignFunctionInterface #-}

{-|
Description:    Common type definitions used pervasively in libcdio, along with
                low-level features intended for internal use.

Copyright:      (c) 2018-2021 Sam May
License:        GPL-3.0-or-later
Maintainer:     ag@eitilt.life

Stability:      stable
Portability:    non-portable (requires libcdio)

While most of @types.h@ is user-facing, it's undesirable to export the
@newtype@ constructors, for type safety.  Hiding them breaks c2hs automatic
marshalling, which means that we have to write custom marshalling functions.
Exporting those clutters the user surface with unnecessary and
likely-never-used code, so the types in this module got split off for use
internally — at which point the constructors may as well be exported anyway.
-}
module Foreign.Libcdio.Types.Internal
    ( -- * Addresses
      Lba ( .. )
    , CLba
    , Lsn ( .. )
    , CLsn
      -- * Segments
    , Track ( .. )
    , CTrack
    , TrackNum
    , minTrack
    , maxTrack
      -- * Data
    , CBitfield
    , isrcLength
    , mcnLength
      -- * Marshalling
    , invalidLba
    , invalidLsn
    , invalidZeroLsn
    , invalidTrack
    , invalidZeroTrack
    , withLba
    , withLsn
    , withTrack
    ) where


import qualified Data.Bits as B
import qualified Data.Ix as I
import qualified Data.List as L
import qualified Data.Maybe as Y

import qualified Foreign.C.Types as C
import qualified Foreign.Ptr as C
import qualified Foreign.Storable as S

import qualified Text.Printf as P

import Data.Bits ((.&.), (.|.))

import Foreign.Libcdio.Marshal


{- 'Char' is already native.
type CUtf8 = C.CChar

-- | A character explicitly encoded as UTF-8.
newtype Utf8 = Utf8 CUtf8
  deriving ( Eq, Ord, Show, Read, Bounded )
-}


-- | The representation of the various @DriveCaps*@ at the C boundary.
type CBitfield = C.CUInt

{- Accomplished with "Data.Array.BitArray".
-- | The type used for bit-fields in structs with eight or less flags.
newtype Bitfield = Bitfield CBitfield
  deriving ( Eq, Ord, Show, Read, Bounded )
-}


-- | Marshal an address to a type which pins the required size of the C
-- representation, rather than the polymorphism of 'fromIntegral'.
withLba :: Lba -> CLba
withLba :: Lba -> CLba
withLba (Lba CLba
i) = CLba
i

type CLba = C.CInt

-- | The type-safe representation of a Logical Block Address, counting sectors
-- from the very beginning of the write session.  See also 'Lsn'.
newtype Lba = Lba CLba
  deriving ( Lba -> Lba -> Bool
(Lba -> Lba -> Bool) -> (Lba -> Lba -> Bool) -> Eq Lba
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Lba -> Lba -> Bool
$c/= :: Lba -> Lba -> Bool
== :: Lba -> Lba -> Bool
$c== :: Lba -> Lba -> Bool
Eq, Eq Lba
Eq Lba
-> (Lba -> Lba -> Ordering)
-> (Lba -> Lba -> Bool)
-> (Lba -> Lba -> Bool)
-> (Lba -> Lba -> Bool)
-> (Lba -> Lba -> Bool)
-> (Lba -> Lba -> Lba)
-> (Lba -> Lba -> Lba)
-> Ord Lba
Lba -> Lba -> Bool
Lba -> Lba -> Ordering
Lba -> Lba -> Lba
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 :: Lba -> Lba -> Lba
$cmin :: Lba -> Lba -> Lba
max :: Lba -> Lba -> Lba
$cmax :: Lba -> Lba -> Lba
>= :: Lba -> Lba -> Bool
$c>= :: Lba -> Lba -> Bool
> :: Lba -> Lba -> Bool
$c> :: Lba -> Lba -> Bool
<= :: Lba -> Lba -> Bool
$c<= :: Lba -> Lba -> Bool
< :: Lba -> Lba -> Bool
$c< :: Lba -> Lba -> Bool
compare :: Lba -> Lba -> Ordering
$ccompare :: Lba -> Lba -> Ordering
$cp1Ord :: Eq Lba
Ord, Int -> Lba -> ShowS
[Lba] -> ShowS
Lba -> String
(Int -> Lba -> ShowS)
-> (Lba -> String) -> ([Lba] -> ShowS) -> Show Lba
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Lba] -> ShowS
$cshowList :: [Lba] -> ShowS
show :: Lba -> String
$cshow :: Lba -> String
showsPrec :: Int -> Lba -> ShowS
$cshowsPrec :: Int -> Lba -> ShowS
Show, ReadPrec [Lba]
ReadPrec Lba
Int -> ReadS Lba
ReadS [Lba]
(Int -> ReadS Lba)
-> ReadS [Lba] -> ReadPrec Lba -> ReadPrec [Lba] -> Read Lba
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Lba]
$creadListPrec :: ReadPrec [Lba]
readPrec :: ReadPrec Lba
$creadPrec :: ReadPrec Lba
readList :: ReadS [Lba]
$creadList :: ReadS [Lba]
readsPrec :: Int -> ReadS Lba
$creadsPrec :: Int -> ReadS Lba
Read )
instance Bounded Lba where
    minBound :: Lba
minBound = CLba -> Lba
Lba (CLba -> Lba) -> (CLba -> CLba) -> CLba -> Lba
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CLba -> CLba
lsnToLba (CLba -> Lba) -> CLba -> Lba
forall a b. (a -> b) -> a -> b
$ Lsn -> CLba
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Lsn
forall a. Bounded a => a
minBound :: Lsn)
    maxBound :: Lba
maxBound = CLba -> Lba
Lba (CLba -> Lba) -> (CLba -> CLba) -> CLba -> Lba
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CLba -> CLba
lsnToLba (CLba -> Lba) -> CLba -> Lba
forall a b. (a -> b) -> a -> b
$ Lsn -> CLba
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Lsn
forall a. Bounded a => a
maxBound :: Lsn)
instance Enum Lba where
    toEnum :: Int -> Lba
toEnum = CLba -> Lba
Lba (CLba -> Lba) -> (Int -> CLba) -> Int -> Lba
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> CLba
forall a. Enum a => Int -> a
toEnum
    fromEnum :: Lba -> Int
fromEnum (Lba CLba
i) = CLba -> Int
forall a. Enum a => a -> Int
fromEnum CLba
i
instance I.Ix Lba where
    range :: (Lba, Lba) -> [Lba]
range (Lba CLba
a, Lba CLba
b) = (CLba -> Lba) -> [CLba] -> [Lba]
forall a b. (a -> b) -> [a] -> [b]
map CLba -> Lba
Lba [CLba
a..CLba
b]
    inRange :: (Lba, Lba) -> Lba -> Bool
inRange (Lba
a, Lba
b) Lba
i = Lba
a Lba -> Lba -> Bool
forall a. Ord a => a -> a -> Bool
<= Lba
i Bool -> Bool -> Bool
&& Lba
i Lba -> Lba -> Bool
forall a. Ord a => a -> a -> Bool
<= Lba
b
    index :: (Lba, Lba) -> Lba -> Int
index r :: (Lba, Lba)
r@(Lba
a, Lba
b) Lba
i = Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
Y.fromMaybe (String -> Int
forall a. HasCallStack => String -> a
error (String -> Int) -> String -> Int
forall a b. (a -> b) -> a -> b
$ String
"Ix(Lba).index: Index (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Lba -> String
forall a. Show a => a -> String
show Lba
i String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
") out of range (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ (Lba, Lba) -> String
forall a. Show a => a -> String
show (Lba, Lba)
r String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")")
                     (Maybe Int -> Int) -> Maybe Int -> Int
forall a b. (a -> b) -> a -> b
$ Lba -> [Lba] -> Maybe Int
forall a. Eq a => a -> [a] -> Maybe Int
L.elemIndex Lba
i [Lba
a..Lba
b]
instance Num Lba where
    Lba CLba
a + :: Lba -> Lba -> Lba
+ Lba CLba
b = CLba -> Lba
Lba (CLba -> Lba) -> CLba -> Lba
forall a b. (a -> b) -> a -> b
$ CLba
a CLba -> CLba -> CLba
forall a. Num a => a -> a -> a
+ CLba
b
    Lba CLba
a - :: Lba -> Lba -> Lba
- Lba CLba
b = CLba -> Lba
Lba (CLba -> Lba) -> CLba -> Lba
forall a b. (a -> b) -> a -> b
$ CLba
a CLba -> CLba -> CLba
forall a. Num a => a -> a -> a
- CLba
b
    Lba CLba
a * :: Lba -> Lba -> Lba
* Lba CLba
b = CLba -> Lba
Lba (CLba -> Lba) -> CLba -> Lba
forall a b. (a -> b) -> a -> b
$ CLba
a CLba -> CLba -> CLba
forall a. Num a => a -> a -> a
* CLba
b
    abs :: Lba -> Lba
abs (Lba CLba
i) = CLba -> Lba
Lba (CLba -> Lba) -> CLba -> Lba
forall a b. (a -> b) -> a -> b
$ CLba -> CLba
forall a. Num a => a -> a
abs CLba
i
    signum :: Lba -> Lba
signum (Lba CLba
i) = CLba -> Lba
Lba (CLba -> Lba) -> CLba -> Lba
forall a b. (a -> b) -> a -> b
$ CLba -> CLba
forall a. Num a => a -> a
signum CLba
i
    fromInteger :: Integer -> Lba
fromInteger = CLba -> Lba
Lba (CLba -> Lba) -> (Integer -> CLba) -> Integer -> Lba
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> CLba
forall a. Num a => Integer -> a
fromInteger
instance Real Lba where
    toRational :: Lba -> Rational
toRational (Lba CLba
i) = CLba -> Rational
forall a. Real a => a -> Rational
toRational CLba
i
instance Integral Lba where
    quotRem :: Lba -> Lba -> (Lba, Lba)
quotRem (Lba CLba
i) (Lba CLba
d) = (CLba -> Lba
Lba CLba
q, CLba -> Lba
Lba CLba
r)
      where (CLba
q, CLba
r) = CLba -> CLba -> (CLba, CLba)
forall a. Integral a => a -> a -> (a, a)
quotRem CLba
i CLba
d
    toInteger :: Lba -> Integer
toInteger (Lba CLba
i) = CLba -> Integer
forall a. Integral a => a -> Integer
toInteger CLba
i
instance B.Bits Lba where
    (Lba CLba
a) .&. :: Lba -> Lba -> Lba
.&. (Lba CLba
b) = CLba -> Lba
Lba (CLba -> Lba) -> CLba -> Lba
forall a b. (a -> b) -> a -> b
$ CLba
a CLba -> CLba -> CLba
forall a. Bits a => a -> a -> a
.&. CLba
b
    (Lba CLba
a) .|. :: Lba -> Lba -> Lba
.|. (Lba CLba
b) = CLba -> Lba
Lba (CLba -> Lba) -> CLba -> Lba
forall a b. (a -> b) -> a -> b
$ CLba
a CLba -> CLba -> CLba
forall a. Bits a => a -> a -> a
.|. CLba
b
    xor :: Lba -> Lba -> Lba
xor (Lba CLba
a) (Lba CLba
b) = CLba -> Lba
Lba (CLba -> Lba) -> CLba -> Lba
forall a b. (a -> b) -> a -> b
$ CLba -> CLba -> CLba
forall a. Bits a => a -> a -> a
B.xor CLba
a CLba
b
    complement :: Lba -> Lba
complement (Lba CLba
i) = CLba -> Lba
Lba (CLba -> Lba) -> CLba -> Lba
forall a b. (a -> b) -> a -> b
$ CLba -> CLba
forall a. Bits a => a -> a
B.complement CLba
i
    shift :: Lba -> Int -> Lba
shift (Lba CLba
i) = CLba -> Lba
Lba (CLba -> Lba) -> (Int -> CLba) -> Int -> Lba
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CLba -> Int -> CLba
forall a. Bits a => a -> Int -> a
B.shift CLba
i
    rotate :: Lba -> Int -> Lba
rotate (Lba CLba
i) = CLba -> Lba
Lba (CLba -> Lba) -> (Int -> CLba) -> Int -> Lba
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CLba -> Int -> CLba
forall a. Bits a => a -> Int -> a
B.rotate CLba
i
    bitSize :: Lba -> Int
bitSize (Lba CLba
i) = CLba -> Int
forall b. FiniteBits b => b -> Int
B.finiteBitSize CLba
i
    bitSizeMaybe :: Lba -> Maybe Int
bitSizeMaybe (Lba CLba
i) = CLba -> Maybe Int
forall a. Bits a => a -> Maybe Int
B.bitSizeMaybe CLba
i
    isSigned :: Lba -> Bool
isSigned (Lba CLba
i) = CLba -> Bool
forall a. Bits a => a -> Bool
B.isSigned CLba
i
    testBit :: Lba -> Int -> Bool
testBit (Lba CLba
i) = CLba -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
B.testBit CLba
i
    bit :: Int -> Lba
bit = CLba -> Lba
Lba (CLba -> Lba) -> (Int -> CLba) -> Int -> Lba
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> CLba
forall a. Bits a => Int -> a
B.bit
    popCount :: Lba -> Int
popCount (Lba CLba
i) = CLba -> Int
forall a. Bits a => a -> Int
B.popCount CLba
i
instance B.FiniteBits Lba where
    finiteBitSize :: Lba -> Int
finiteBitSize (Lba CLba
i) = CLba -> Int
forall b. FiniteBits b => b -> Int
B.finiteBitSize CLba
i
instance P.PrintfArg Lba where
    formatArg :: Lba -> FieldFormatter
formatArg = Int -> FieldFormatter
forall a. PrintfArg a => a -> FieldFormatter
P.formatArg (Int -> FieldFormatter) -> (Lba -> Int) -> Lba -> FieldFormatter
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Lba -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral :: Lba -> Int)
instance S.Storable Lba where
    sizeOf :: Lba -> Int
sizeOf (Lba CLba
i)    = CLba -> Int
forall a. Storable a => a -> Int
S.sizeOf CLba
i
    alignment :: Lba -> Int
alignment (Lba CLba
i) = CLba -> Int
forall a. Storable a => a -> Int
S.alignment CLba
i
    peek :: Ptr Lba -> IO Lba
peek Ptr Lba
p            = CLba -> Lba
Lba (CLba -> Lba) -> IO CLba -> IO Lba
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr CLba -> IO CLba
forall a. Storable a => Ptr a -> IO a
S.peek (Ptr Lba -> Ptr CLba
forall a b. Ptr a -> Ptr b
C.castPtr Ptr Lba
p)
    poke :: Ptr Lba -> Lba -> IO ()
poke Ptr Lba
p (Lba CLba
i)    = Ptr CLba -> CLba -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
S.poke (Ptr Lba -> Ptr CLba
forall a b. Ptr a -> Ptr b
C.castPtr Ptr Lba
p) CLba
i

foreign import ccall safe "cdio/compat/sector.h cdio_lsn_to_lba"
  lsnToLba :: CLsn -> CLba

foreign import ccall safe "cdio/compat/disc.h invalid_lba"
  invalidLba' :: CLba

-- | Filter out @CDIO_INVALID_LBA@ values for type-safe errors.
invalidLba :: CLba -> Maybe Lba
invalidLba :: CLba -> Maybe Lba
invalidLba = (CLba -> Lba) -> Maybe CLba -> Maybe Lba
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap CLba -> Lba
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Maybe CLba -> Maybe Lba)
-> (CLba -> Maybe CLba) -> CLba -> Maybe Lba
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [CLba] -> CLba -> Maybe CLba
forall a. Eq a => [a] -> a -> Maybe a
maybeError [CLba
invalidLba']


-- | Marshal an address to a type which pins the required size of the C
-- representation, rather than the polymorphism of 'fromIntegral'.
withLsn :: Lsn -> CLsn
withLsn :: Lsn -> CLba
withLsn (Lsn CLba
i) = CLba
i

type CLsn = C.CInt

-- | The type-safe representation of a Logical Sector Number, counting sectors
-- from the start of track 1; this notably excludes the blank session lead-in.
-- See also 'Lba'.
newtype Lsn = Lsn CLsn
  deriving ( Lsn -> Lsn -> Bool
(Lsn -> Lsn -> Bool) -> (Lsn -> Lsn -> Bool) -> Eq Lsn
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Lsn -> Lsn -> Bool
$c/= :: Lsn -> Lsn -> Bool
== :: Lsn -> Lsn -> Bool
$c== :: Lsn -> Lsn -> Bool
Eq, Eq Lsn
Eq Lsn
-> (Lsn -> Lsn -> Ordering)
-> (Lsn -> Lsn -> Bool)
-> (Lsn -> Lsn -> Bool)
-> (Lsn -> Lsn -> Bool)
-> (Lsn -> Lsn -> Bool)
-> (Lsn -> Lsn -> Lsn)
-> (Lsn -> Lsn -> Lsn)
-> Ord Lsn
Lsn -> Lsn -> Bool
Lsn -> Lsn -> Ordering
Lsn -> Lsn -> Lsn
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 :: Lsn -> Lsn -> Lsn
$cmin :: Lsn -> Lsn -> Lsn
max :: Lsn -> Lsn -> Lsn
$cmax :: Lsn -> Lsn -> Lsn
>= :: Lsn -> Lsn -> Bool
$c>= :: Lsn -> Lsn -> Bool
> :: Lsn -> Lsn -> Bool
$c> :: Lsn -> Lsn -> Bool
<= :: Lsn -> Lsn -> Bool
$c<= :: Lsn -> Lsn -> Bool
< :: Lsn -> Lsn -> Bool
$c< :: Lsn -> Lsn -> Bool
compare :: Lsn -> Lsn -> Ordering
$ccompare :: Lsn -> Lsn -> Ordering
$cp1Ord :: Eq Lsn
Ord, Int -> Lsn -> ShowS
[Lsn] -> ShowS
Lsn -> String
(Int -> Lsn -> ShowS)
-> (Lsn -> String) -> ([Lsn] -> ShowS) -> Show Lsn
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Lsn] -> ShowS
$cshowList :: [Lsn] -> ShowS
show :: Lsn -> String
$cshow :: Lsn -> String
showsPrec :: Int -> Lsn -> ShowS
$cshowsPrec :: Int -> Lsn -> ShowS
Show, ReadPrec [Lsn]
ReadPrec Lsn
Int -> ReadS Lsn
ReadS [Lsn]
(Int -> ReadS Lsn)
-> ReadS [Lsn] -> ReadPrec Lsn -> ReadPrec [Lsn] -> Read Lsn
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Lsn]
$creadListPrec :: ReadPrec [Lsn]
readPrec :: ReadPrec Lsn
$creadPrec :: ReadPrec Lsn
readList :: ReadS [Lsn]
$creadList :: ReadS [Lsn]
readsPrec :: Int -> ReadS Lsn
$creadsPrec :: Int -> ReadS Lsn
Read )
instance Bounded Lsn where
    minBound :: Lsn
minBound = CLba -> Lsn
Lsn CLba
minLsn
    maxBound :: Lsn
maxBound = CLba -> Lsn
Lsn CLba
maxLsn
instance Enum Lsn where
    toEnum :: Int -> Lsn
toEnum = CLba -> Lsn
Lsn (CLba -> Lsn) -> (Int -> CLba) -> Int -> Lsn
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> CLba
forall a. Enum a => Int -> a
toEnum
    fromEnum :: Lsn -> Int
fromEnum (Lsn CLba
i) = CLba -> Int
forall a. Enum a => a -> Int
fromEnum CLba
i
instance I.Ix Lsn where
    range :: (Lsn, Lsn) -> [Lsn]
range (Lsn CLba
a, Lsn CLba
b) = (CLba -> Lsn) -> [CLba] -> [Lsn]
forall a b. (a -> b) -> [a] -> [b]
map CLba -> Lsn
Lsn [CLba
a..CLba
b]
    inRange :: (Lsn, Lsn) -> Lsn -> Bool
inRange (Lsn
a, Lsn
b) Lsn
i = Lsn
a Lsn -> Lsn -> Bool
forall a. Ord a => a -> a -> Bool
<= Lsn
i Bool -> Bool -> Bool
&& Lsn
i Lsn -> Lsn -> Bool
forall a. Ord a => a -> a -> Bool
<= Lsn
b
    index :: (Lsn, Lsn) -> Lsn -> Int
index r :: (Lsn, Lsn)
r@(Lsn
a, Lsn
b) Lsn
i = Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
Y.fromMaybe (String -> Int
forall a. HasCallStack => String -> a
error (String -> Int) -> String -> Int
forall a b. (a -> b) -> a -> b
$ String
"Ix(Lsn).index: Index (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Lsn -> String
forall a. Show a => a -> String
show Lsn
i String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
") out of range (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ (Lsn, Lsn) -> String
forall a. Show a => a -> String
show (Lsn, Lsn)
r String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")")
                     (Maybe Int -> Int) -> Maybe Int -> Int
forall a b. (a -> b) -> a -> b
$ Lsn -> [Lsn] -> Maybe Int
forall a. Eq a => a -> [a] -> Maybe Int
L.elemIndex Lsn
i [Lsn
a..Lsn
b]
instance Num Lsn where
    Lsn CLba
a + :: Lsn -> Lsn -> Lsn
+ Lsn CLba
b = CLba -> Lsn
Lsn (CLba -> Lsn) -> CLba -> Lsn
forall a b. (a -> b) -> a -> b
$ CLba
a CLba -> CLba -> CLba
forall a. Num a => a -> a -> a
+ CLba
b
    Lsn CLba
a - :: Lsn -> Lsn -> Lsn
- Lsn CLba
b = CLba -> Lsn
Lsn (CLba -> Lsn) -> CLba -> Lsn
forall a b. (a -> b) -> a -> b
$ CLba
a CLba -> CLba -> CLba
forall a. Num a => a -> a -> a
- CLba
b
    Lsn CLba
a * :: Lsn -> Lsn -> Lsn
* Lsn CLba
b = CLba -> Lsn
Lsn (CLba -> Lsn) -> CLba -> Lsn
forall a b. (a -> b) -> a -> b
$ CLba
a CLba -> CLba -> CLba
forall a. Num a => a -> a -> a
* CLba
b
    abs :: Lsn -> Lsn
abs (Lsn CLba
i) = CLba -> Lsn
Lsn (CLba -> Lsn) -> CLba -> Lsn
forall a b. (a -> b) -> a -> b
$ CLba -> CLba
forall a. Num a => a -> a
abs CLba
i
    signum :: Lsn -> Lsn
signum (Lsn CLba
i) = CLba -> Lsn
Lsn (CLba -> Lsn) -> CLba -> Lsn
forall a b. (a -> b) -> a -> b
$ CLba -> CLba
forall a. Num a => a -> a
signum CLba
i
    fromInteger :: Integer -> Lsn
fromInteger = CLba -> Lsn
Lsn (CLba -> Lsn) -> (Integer -> CLba) -> Integer -> Lsn
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> CLba
forall a. Num a => Integer -> a
fromInteger
instance Real Lsn where
    toRational :: Lsn -> Rational
toRational (Lsn CLba
i) = CLba -> Rational
forall a. Real a => a -> Rational
toRational CLba
i
instance Integral Lsn where
    quotRem :: Lsn -> Lsn -> (Lsn, Lsn)
quotRem (Lsn CLba
i) (Lsn CLba
d) = (CLba -> Lsn
Lsn CLba
q, CLba -> Lsn
Lsn CLba
r)
      where (CLba
q, CLba
r) = CLba -> CLba -> (CLba, CLba)
forall a. Integral a => a -> a -> (a, a)
quotRem CLba
i CLba
d
    toInteger :: Lsn -> Integer
toInteger (Lsn CLba
i) = CLba -> Integer
forall a. Integral a => a -> Integer
toInteger CLba
i
instance B.Bits Lsn where
    (Lsn CLba
a) .&. :: Lsn -> Lsn -> Lsn
.&. (Lsn CLba
b) = CLba -> Lsn
Lsn (CLba -> Lsn) -> CLba -> Lsn
forall a b. (a -> b) -> a -> b
$ CLba
a CLba -> CLba -> CLba
forall a. Bits a => a -> a -> a
.&. CLba
b
    (Lsn CLba
a) .|. :: Lsn -> Lsn -> Lsn
.|. (Lsn CLba
b) = CLba -> Lsn
Lsn (CLba -> Lsn) -> CLba -> Lsn
forall a b. (a -> b) -> a -> b
$ CLba
a CLba -> CLba -> CLba
forall a. Bits a => a -> a -> a
.|. CLba
b
    xor :: Lsn -> Lsn -> Lsn
xor (Lsn CLba
a) (Lsn CLba
b) = CLba -> Lsn
Lsn (CLba -> Lsn) -> CLba -> Lsn
forall a b. (a -> b) -> a -> b
$ CLba -> CLba -> CLba
forall a. Bits a => a -> a -> a
B.xor CLba
a CLba
b
    complement :: Lsn -> Lsn
complement (Lsn CLba
i) = CLba -> Lsn
Lsn (CLba -> Lsn) -> CLba -> Lsn
forall a b. (a -> b) -> a -> b
$ CLba -> CLba
forall a. Bits a => a -> a
B.complement CLba
i
    shift :: Lsn -> Int -> Lsn
shift (Lsn CLba
i) = CLba -> Lsn
Lsn (CLba -> Lsn) -> (Int -> CLba) -> Int -> Lsn
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CLba -> Int -> CLba
forall a. Bits a => a -> Int -> a
B.shift CLba
i
    rotate :: Lsn -> Int -> Lsn
rotate (Lsn CLba
i) = CLba -> Lsn
Lsn (CLba -> Lsn) -> (Int -> CLba) -> Int -> Lsn
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CLba -> Int -> CLba
forall a. Bits a => a -> Int -> a
B.rotate CLba
i
    bitSize :: Lsn -> Int
bitSize (Lsn CLba
i) = CLba -> Int
forall b. FiniteBits b => b -> Int
B.finiteBitSize CLba
i
    bitSizeMaybe :: Lsn -> Maybe Int
bitSizeMaybe (Lsn CLba
i) = CLba -> Maybe Int
forall a. Bits a => a -> Maybe Int
B.bitSizeMaybe CLba
i
    isSigned :: Lsn -> Bool
isSigned (Lsn CLba
i) = CLba -> Bool
forall a. Bits a => a -> Bool
B.isSigned CLba
i
    testBit :: Lsn -> Int -> Bool
testBit (Lsn CLba
i) = CLba -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
B.testBit CLba
i
    bit :: Int -> Lsn
bit = CLba -> Lsn
Lsn (CLba -> Lsn) -> (Int -> CLba) -> Int -> Lsn
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> CLba
forall a. Bits a => Int -> a
B.bit
    popCount :: Lsn -> Int
popCount (Lsn CLba
i) = CLba -> Int
forall a. Bits a => a -> Int
B.popCount CLba
i
instance B.FiniteBits Lsn where
    finiteBitSize :: Lsn -> Int
finiteBitSize (Lsn CLba
i) = CLba -> Int
forall b. FiniteBits b => b -> Int
B.finiteBitSize CLba
i
instance P.PrintfArg Lsn where
    formatArg :: Lsn -> FieldFormatter
formatArg = Int -> FieldFormatter
forall a. PrintfArg a => a -> FieldFormatter
P.formatArg (Int -> FieldFormatter) -> (Lsn -> Int) -> Lsn -> FieldFormatter
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Lsn -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral :: Lsn -> Int)
instance S.Storable Lsn where
    sizeOf :: Lsn -> Int
sizeOf (Lsn CLba
i)    = CLba -> Int
forall a. Storable a => a -> Int
S.sizeOf CLba
i
    alignment :: Lsn -> Int
alignment (Lsn CLba
i) = CLba -> Int
forall a. Storable a => a -> Int
S.alignment CLba
i
    peek :: Ptr Lsn -> IO Lsn
peek Ptr Lsn
p            = CLba -> Lsn
Lsn (CLba -> Lsn) -> IO CLba -> IO Lsn
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr CLba -> IO CLba
forall a. Storable a => Ptr a -> IO a
S.peek (Ptr Lsn -> Ptr CLba
forall a b. Ptr a -> Ptr b
C.castPtr Ptr Lsn
p)
    poke :: Ptr Lsn -> Lsn -> IO ()
poke Ptr Lsn
p (Lsn CLba
i)    = Ptr CLba -> CLba -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
S.poke (Ptr Lsn -> Ptr CLba
forall a b. Ptr a -> Ptr b
C.castPtr Ptr Lsn
p) CLba
i

foreign import ccall safe "cdio/compat/sector.h min_lsn"
  minLsn :: CLsn

foreign import ccall safe "cdio/compat/sector.h max_lsn"
  maxLsn :: CLsn

foreign import ccall safe "cdio/compat/disc.h invalid_lsn"
  invalidLsn' :: CLsn

-- | Filter out @CDIO_INVALID_LSN@ values for type-safe errors.
invalidLsn :: CLsn -> Maybe Lsn
invalidLsn :: CLba -> Maybe Lsn
invalidLsn = (CLba -> Lsn) -> Maybe CLba -> Maybe Lsn
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap CLba -> Lsn
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Maybe CLba -> Maybe Lsn)
-> (CLba -> Maybe CLba) -> CLba -> Maybe Lsn
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [CLba] -> CLba -> Maybe CLba
forall a. Eq a => [a] -> a -> Maybe a
maybeError [CLba
invalidLsn']

-- | Filter out both @0@ and @CDIO_INVALID_LSN@ values for type-safe errors.
invalidZeroLsn :: CLsn -> Maybe Lsn
invalidZeroLsn :: CLba -> Maybe Lsn
invalidZeroLsn = (CLba -> Lsn) -> Maybe CLba -> Maybe Lsn
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap CLba -> Lsn
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Maybe CLba -> Maybe Lsn)
-> (CLba -> Maybe CLba) -> CLba -> Maybe Lsn
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [CLba] -> CLba -> Maybe CLba
forall a. Eq a => [a] -> a -> Maybe a
maybeError [CLba
0, CLba
invalidLsn']


-- | Marshal a track number to a type which pins the required size of the C
-- representation, rather than the polymorphism of 'fromIntegral'.  Note that
-- @withTrack 'DiscLeadout' /= fromIntegral (fromEnum 'DiscLeadout')@
withTrack :: Track -> CTrack
withTrack :: Track -> CTrack
withTrack Track
DiscPregap = CTrack
0
withTrack (Track (TrackNum Word
i)) = Word -> CTrack
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word
i CTrack -> CTrack -> CTrack
forall a. Num a => a -> a -> a
+ CTrack
minTrack'
withTrack Track
DiscLeadout = CTrack
leadoutTrack'

type CTrack = C.CUChar

-- | Opaque newtype representing the numeric index of a 'Track', while
-- enforcing the invariants inherant to the specification.  Of very limited
-- utility outside that context.
newtype TrackNum = TrackNum Word
  deriving ( TrackNum -> TrackNum -> Bool
(TrackNum -> TrackNum -> Bool)
-> (TrackNum -> TrackNum -> Bool) -> Eq TrackNum
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TrackNum -> TrackNum -> Bool
$c/= :: TrackNum -> TrackNum -> Bool
== :: TrackNum -> TrackNum -> Bool
$c== :: TrackNum -> TrackNum -> Bool
Eq, Eq TrackNum
Eq TrackNum
-> (TrackNum -> TrackNum -> Ordering)
-> (TrackNum -> TrackNum -> Bool)
-> (TrackNum -> TrackNum -> Bool)
-> (TrackNum -> TrackNum -> Bool)
-> (TrackNum -> TrackNum -> Bool)
-> (TrackNum -> TrackNum -> TrackNum)
-> (TrackNum -> TrackNum -> TrackNum)
-> Ord TrackNum
TrackNum -> TrackNum -> Bool
TrackNum -> TrackNum -> Ordering
TrackNum -> TrackNum -> TrackNum
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 :: TrackNum -> TrackNum -> TrackNum
$cmin :: TrackNum -> TrackNum -> TrackNum
max :: TrackNum -> TrackNum -> TrackNum
$cmax :: TrackNum -> TrackNum -> TrackNum
>= :: TrackNum -> TrackNum -> Bool
$c>= :: TrackNum -> TrackNum -> Bool
> :: TrackNum -> TrackNum -> Bool
$c> :: TrackNum -> TrackNum -> Bool
<= :: TrackNum -> TrackNum -> Bool
$c<= :: TrackNum -> TrackNum -> Bool
< :: TrackNum -> TrackNum -> Bool
$c< :: TrackNum -> TrackNum -> Bool
compare :: TrackNum -> TrackNum -> Ordering
$ccompare :: TrackNum -> TrackNum -> Ordering
$cp1Ord :: Eq TrackNum
Ord )
instance Bounded TrackNum where
    minBound :: TrackNum
minBound = Word -> TrackNum
TrackNum Word
0
    maxBound :: TrackNum
maxBound = Word -> TrackNum
TrackNum (Word -> TrackNum) -> Word -> TrackNum
forall a b. (a -> b) -> a -> b
$ Word
maxTrackW Word -> Word -> Word
forall a. Num a => a -> a -> a
- Word
minTrackW
instance Show TrackNum where
    show :: TrackNum -> String
show (TrackNum Word
i) = Word -> String
forall a. Show a => a -> String
show (Word -> String) -> Word -> String
forall a b. (a -> b) -> a -> b
$ Word
i Word -> Word -> Word
forall a. Num a => a -> a -> a
+ Word
minTrackW
instance Read TrackNum where
    readsPrec :: Int -> ReadS TrackNum
readsPrec Int
d = \String
str -> do
        (Word
i, String
str') <- Int -> ReadS Word
forall a. Read a => Int -> ReadS a
readsPrec Int
d String
str
        (TrackNum, String) -> [(TrackNum, String)]
forall (m :: * -> *) a. Monad m => a -> m a
return (Word -> TrackNum
TrackNum (Word -> TrackNum) -> Word -> TrackNum
forall a b. (a -> b) -> a -> b
$ Word
i Word -> Word -> Word
forall a. Num a => a -> a -> a
- Word
minTrackW, String
str')

-- | An index into the segmentation within a write session on a disc.
data Track
    = DiscPregap
        -- ^ The (usually buffer) data located before the first track on a
        -- disc.
    | Track TrackNum
        -- ^ The common understanding of a CD track: a segment of the data on
        -- the disc containing (usually) a single song.
    | DiscLeadout
        -- ^ Any (usually buffer) data located after the end of the last track
        -- on a disc.
  deriving ( Track -> Track -> Bool
(Track -> Track -> Bool) -> (Track -> Track -> Bool) -> Eq Track
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Track -> Track -> Bool
$c/= :: Track -> Track -> Bool
== :: Track -> Track -> Bool
$c== :: Track -> Track -> Bool
Eq, Eq Track
Eq Track
-> (Track -> Track -> Ordering)
-> (Track -> Track -> Bool)
-> (Track -> Track -> Bool)
-> (Track -> Track -> Bool)
-> (Track -> Track -> Bool)
-> (Track -> Track -> Track)
-> (Track -> Track -> Track)
-> Ord Track
Track -> Track -> Bool
Track -> Track -> Ordering
Track -> Track -> Track
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 :: Track -> Track -> Track
$cmin :: Track -> Track -> Track
max :: Track -> Track -> Track
$cmax :: Track -> Track -> Track
>= :: Track -> Track -> Bool
$c>= :: Track -> Track -> Bool
> :: Track -> Track -> Bool
$c> :: Track -> Track -> Bool
<= :: Track -> Track -> Bool
$c<= :: Track -> Track -> Bool
< :: Track -> Track -> Bool
$c< :: Track -> Track -> Bool
compare :: Track -> Track -> Ordering
$ccompare :: Track -> Track -> Ordering
$cp1Ord :: Eq Track
Ord, Int -> Track -> ShowS
[Track] -> ShowS
Track -> String
(Int -> Track -> ShowS)
-> (Track -> String) -> ([Track] -> ShowS) -> Show Track
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Track] -> ShowS
$cshowList :: [Track] -> ShowS
show :: Track -> String
$cshow :: Track -> String
showsPrec :: Int -> Track -> ShowS
$cshowsPrec :: Int -> Track -> ShowS
Show )
instance Bounded Track where
    minBound :: Track
minBound = Track
DiscPregap
    maxBound :: Track
maxBound = Track
DiscLeadout
-- | Note that @'fromEnum' 'DiscLeadout'@ uses a value (== 100) chosen to be
-- contiguous to the rest of the datatype rather than that used internally
-- (== 0xAA).  'toEnum' accepts both values.
instance Enum Track where
    toEnum :: Int -> Track
toEnum Int
i
        | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< CTrack -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CTrack
minTrack' = Track
DiscPregap
        | Int
i Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> CTrack -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CTrack
maxTrack' = Track
DiscLeadout
        | Bool
otherwise = TrackNum -> Track
Track (TrackNum -> Track) -> (Word -> TrackNum) -> Word -> Track
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word -> TrackNum
TrackNum (Word -> Track) -> Word -> Track
forall a b. (a -> b) -> a -> b
$ Int -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i Word -> Word -> Word
forall a. Num a => a -> a -> a
- Word
minTrackW
    fromEnum :: Track -> Int
fromEnum Track
DiscPregap = CTrack -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CTrack
minTrack' Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
    fromEnum (Track (TrackNum Word
i)) = Word -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word -> Int) -> Word -> Int
forall a b. (a -> b) -> a -> b
$ Word
i Word -> Word -> Word
forall a. Num a => a -> a -> a
+ Word
minTrackW
    fromEnum Track
DiscLeadout = CTrack -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral CTrack
maxTrack' Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
    pred :: Track -> Track
pred Track
DiscPregap = String -> Track
forall a. HasCallStack => String -> a
error String
"Enum.pred(Track): tried to take `pred' of DiscPregap"
    pred (Track n :: TrackNum
n@(TrackNum Word
i))
        | TrackNum
n TrackNum -> TrackNum -> Bool
forall a. Eq a => a -> a -> Bool
== TrackNum
forall a. Bounded a => a
minBound = Track
DiscPregap
        | TrackNum
n TrackNum -> TrackNum -> Bool
forall a. Ord a => a -> a -> Bool
> TrackNum
forall a. Bounded a => a
maxBound = Track
DiscLeadout
        | Bool
otherwise = TrackNum -> Track
Track (TrackNum -> Track) -> (Word -> TrackNum) -> Word -> Track
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word -> TrackNum
TrackNum (Word -> Track) -> Word -> Track
forall a b. (a -> b) -> a -> b
$ Word
i Word -> Word -> Word
forall a. Num a => a -> a -> a
- Word
1
    pred Track
DiscLeadout = TrackNum -> Track
Track TrackNum
forall a. Bounded a => a
maxBound
    succ :: Track -> Track
succ Track
DiscPregap = TrackNum -> Track
Track TrackNum
forall a. Bounded a => a
minBound
    succ (Track n :: TrackNum
n@(TrackNum Word
i))
        | TrackNum
n TrackNum -> TrackNum -> Bool
forall a. Ord a => a -> a -> Bool
>= TrackNum
forall a. Bounded a => a
maxBound = Track
DiscLeadout
        | Bool
otherwise = TrackNum -> Track
Track (TrackNum -> Track) -> (Word -> TrackNum) -> Word -> Track
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word -> TrackNum
TrackNum (Word -> Track) -> Word -> Track
forall a b. (a -> b) -> a -> b
$ Word
i Word -> Word -> Word
forall a. Num a => a -> a -> a
+ Word
1
    succ Track
DiscLeadout = String -> Track
forall a. HasCallStack => String -> a
error String
"Enum.succ(Track): tried to take `succ' of DiscLeadout"
instance Read Track where
    readsPrec :: Int -> ReadS Track
readsPrec Int
d = \String
s ->
        [ (Track
DiscPregap, String
s')
        | (String
"DiscPregap", String
s') <- ReadS String
lex String
s
        ] [(Track, String)] -> [(Track, String)] -> [(Track, String)]
forall a. [a] -> [a] -> [a]
++
        [ (Track
DiscLeadout, String
s')
        | (String
"DiscLeadout", String
s') <- ReadS String
lex String
s
        ] [(Track, String)] -> [(Track, String)] -> [(Track, String)]
forall a. [a] -> [a] -> [a]
++
        [ (Word -> Track
packTrack Word
i, String
s')
        | (Word
i, String
s') <- Bool -> ReadS Word -> ReadS Word
forall a. Bool -> ReadS a -> ReadS a
readParen (Int
d Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
10) ReadS Word
forall a. Read a => String -> [(a, String)]
readsTrack String
s
        ]
      where packTrack :: Word -> Track
packTrack Word
i
                | Word
i Word -> Word -> Bool
forall a. Ord a => a -> a -> Bool
< Word
minTrackW = Track
DiscPregap
                | Word
i Word -> Word -> Bool
forall a. Ord a => a -> a -> Bool
> Word
maxTrackW = Track
DiscLeadout
                | Bool
otherwise = TrackNum -> Track
Track (TrackNum -> Track) -> (Word -> TrackNum) -> Word -> Track
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word -> TrackNum
TrackNum (Word -> Track) -> Word -> Track
forall a b. (a -> b) -> a -> b
$ Word
i Word -> Word -> Word
forall a. Num a => a -> a -> a
- Word
minTrackW
            readsTrack :: String -> [(a, String)]
readsTrack String
s =
                [ (a
i, String
s'')
                | (String
"Track", String
s') <- ReadS String
lex String
s
                , (a
i, String
s'') <- Int -> String -> [(a, String)]
forall a. Read a => Int -> ReadS a
readsPrec Int
10 String
s'
                ]
instance I.Ix Track where
    range :: (Track, Track) -> [Track]
range (Track
a, Track
b) = (Int -> Track) -> [Int] -> [Track]
forall a b. (a -> b) -> [a] -> [b]
map Int -> Track
forall a. Enum a => Int -> a
toEnum [Track -> Int
forall a. Enum a => a -> Int
fromEnum Track
a..Track -> Int
forall a. Enum a => a -> Int
fromEnum Track
b]
    inRange :: (Track, Track) -> Track -> Bool
inRange (Track
a, Track
b) Track
i = Track
a Track -> Track -> Bool
forall a. Ord a => a -> a -> Bool
<= Track
i Bool -> Bool -> Bool
&& Track
i Track -> Track -> Bool
forall a. Ord a => a -> a -> Bool
<= Track
b
    index :: (Track, Track) -> Track -> Int
index r :: (Track, Track)
r@(Track
a, Track
b) Track
i = Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
Y.fromMaybe (String -> Int
forall a. HasCallStack => String -> a
error (String -> Int) -> String -> Int
forall a b. (a -> b) -> a -> b
$ String
"Ix(Track).index: Index (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Track -> String
forall a. Show a => a -> String
show Track
i String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
") out of range (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ (Track, Track) -> String
forall a. Show a => a -> String
show (Track, Track)
r String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")")
                     (Maybe Int -> Int) -> Maybe Int -> Int
forall a b. (a -> b) -> a -> b
$ Track -> [Track] -> Maybe Int
forall a. Eq a => a -> [a] -> Maybe Int
L.elemIndex Track
i [Track
a..Track
b]
instance Num Track where
    Track
a + :: Track -> Track -> Track
+ Track
b = Int -> Track
forall a. Enum a => Int -> a
toEnum (Int -> Track) -> Int -> Track
forall a b. (a -> b) -> a -> b
$ Track -> Int
forall a. Enum a => a -> Int
fromEnum Track
a Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Track -> Int
forall a. Enum a => a -> Int
fromEnum Track
b
    Track
a - :: Track -> Track -> Track
- Track
b = Int -> Track
forall a. Enum a => Int -> a
toEnum (Int -> Track) -> Int -> Track
forall a b. (a -> b) -> a -> b
$ Track -> Int
forall a. Enum a => a -> Int
fromEnum Track
a Int -> Int -> Int
forall a. Num a => a -> a -> a
- Track -> Int
forall a. Enum a => a -> Int
fromEnum Track
b
    Track
a * :: Track -> Track -> Track
* Track
b = Int -> Track
forall a. Enum a => Int -> a
toEnum (Int -> Track) -> Int -> Track
forall a b. (a -> b) -> a -> b
$ Track -> Int
forall a. Enum a => a -> Int
fromEnum Track
a Int -> Int -> Int
forall a. Num a => a -> a -> a
* Track -> Int
forall a. Enum a => a -> Int
fromEnum Track
b
    abs :: Track -> Track
abs Track
t = Track
t
    signum :: Track -> Track
signum Track
_ = Track
DiscPregap
    fromInteger :: Integer -> Track
fromInteger = Int -> Track
forall a. Enum a => Int -> a
toEnum (Int -> Track) -> (Integer -> Int) -> Integer -> Track
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Int
forall a. Num a => Integer -> a
fromInteger
instance P.PrintfArg Track where
    formatArg :: Track -> FieldFormatter
formatArg Track
t = CTrack -> FieldFormatter
forall a. (Integral a, Bounded a) => a -> FieldFormatter
P.formatInt (CTrack -> FieldFormatter) -> CTrack -> FieldFormatter
forall a b. (a -> b) -> a -> b
$ Track -> CTrack
withTrack Track
t
-- | Note that 'S.poke' uses the official representation of 'DiscLeadout'
-- (@CDIO_CDROM_LEADOUT_TRACK == 0xAA@, as used by libcdio) rather than the
-- hscdio @'fromEnum' 'DiscLeadout'@ (== 100), as the latter was chosen for
-- proximity to the other constructors.
instance S.Storable Track where
    sizeOf :: Track -> Int
sizeOf Track
_    = CTrack -> Int
forall a. Storable a => a -> Int
S.sizeOf CTrack
leadoutTrack'
    alignment :: Track -> Int
alignment Track
_ = CTrack -> Int
forall a. Storable a => a -> Int
S.alignment CTrack
leadoutTrack'
    peek :: Ptr Track -> IO Track
peek Ptr Track
p      = Int -> Track
forall a. Enum a => Int -> a
toEnum (Int -> Track) -> (CTrack -> Int) -> CTrack -> Track
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CTrack -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (CTrack -> Track) -> IO CTrack -> IO Track
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Ptr CTrack -> IO CTrack
forall a. Storable a => Ptr a -> IO a
S.peek (Ptr Track -> Ptr CTrack
forall a b. Ptr a -> Ptr b
C.castPtr Ptr Track
p :: C.Ptr CTrack)
    poke :: Ptr Track -> Track -> IO ()
poke Ptr Track
p      = Ptr CTrack -> CTrack -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
S.poke (Ptr Track -> Ptr CTrack
forall a b. Ptr a -> Ptr b
C.castPtr Ptr Track
p) (CTrack -> IO ()) -> (Track -> CTrack) -> Track -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Track -> CTrack
withTrack

-- | The first data track on a disc (i.e. @'Track' 1@).
minTrack :: Track
minTrack :: Track
minTrack = CTrack -> Track
forall a b. (Integral a, Num b) => a -> b
fromIntegral CTrack
minTrack'

minTrackW :: Word
minTrackW :: Word
minTrackW = CTrack -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral CTrack
minTrack'

foreign import ccall safe "cdio/compat/track.h min_tracks"
  minTrack' :: CTrack

-- | The highest data track allowed by the specifications (i.e. @'Track' 99@).
maxTrack :: Track
maxTrack :: Track
maxTrack = CTrack -> Track
forall a b. (Integral a, Num b) => a -> b
fromIntegral CTrack
maxTrack'

maxTrackW :: Word
maxTrackW :: Word
maxTrackW = CTrack -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral CTrack
maxTrack'

foreign import ccall safe "cdio/compat/track.h max_tracks"
  maxTrack' :: CTrack

foreign import ccall safe "cdio/compat/track.h leadout_track"
  leadoutTrack' :: CTrack

foreign import ccall safe "cdio/compat/track.h invalid_track"
  invalidTrack' :: CTrack

-- | Filter out @CDIO_INVALID_TRACK@ values for type-safe errors.
invalidTrack :: CTrack -> Maybe Track
invalidTrack :: CTrack -> Maybe Track
invalidTrack = (CTrack -> Track) -> Maybe CTrack -> Maybe Track
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int -> Track
forall a. Enum a => Int -> a
toEnum (Int -> Track) -> (CTrack -> Int) -> CTrack -> Track
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CTrack -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral) (Maybe CTrack -> Maybe Track)
-> (CTrack -> Maybe CTrack) -> CTrack -> Maybe Track
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [CTrack] -> CTrack -> Maybe CTrack
forall a. Eq a => [a] -> a -> Maybe a
maybeError [CTrack
invalidTrack']

-- | Filter out @CDIO_INVALID_TRACK@ and 'DiscPregap' values for type-safe
-- errors.
invalidZeroTrack :: CTrack -> Maybe Track
invalidZeroTrack :: CTrack -> Maybe Track
invalidZeroTrack = (CTrack -> Track) -> Maybe CTrack -> Maybe Track
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int -> Track
forall a. Enum a => Int -> a
toEnum (Int -> Track) -> (CTrack -> Int) -> CTrack -> Track
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CTrack -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral) (Maybe CTrack -> Maybe Track)
-> (CTrack -> Maybe CTrack) -> CTrack -> Maybe Track
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [CTrack] -> CTrack -> Maybe CTrack
forall a. Eq a => [a] -> a -> Maybe a
maybeError [CTrack
0, CTrack
invalidTrack']


-- | Number of ASCII bytes in a media catalog number.
mcnLength :: Word
mcnLength :: Word
mcnLength = CTrack -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral CTrack
mcnLength'

foreign import ccall safe "cdio/compat/types.h mcn_length"
  mcnLength' :: C.CUChar

{- Never used after definition.
-- | Some Media Catalog Number which identifies a disc; in practice usually a
-- UPC/EAN bar code.
newtype Mcn = Mcn String
  deriving ( Eq, Ord, Show, Read, Bounded )
instance S.Storable Mcn where
    sizeOf _       = S.sizeOf C.nullPtr
    alignment _    = S.alignment C.nullPtr
    peek p         = Mcn <$> C.peekCStringLen (C.castPtr p, mcnLength)
    poke p (Mcn s) = undefined
--}


-- | Number of ASCII characters in an International Standard Recording Code.
isrcLength :: Word
isrcLength :: Word
isrcLength = CTrack -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral CTrack
isrcLength'

foreign import ccall safe "cdio/compat/types.h isrc_length"
  isrcLength' :: C.CUChar

{- Never used after definition.
-- | The International Standard Recording Code attached to a track of a disc,
-- as assigned by a central agency.
newtype Isrc = Isrc String
  deriving ( Eq, Ord, Show, Read, Bounded )
instance S.Storable Isrc where
    sizeOf _        = S.sizeOf C.nullPtr
    alignment _     = S.alignment C.nullPtr
    peek p          = Isrc <$> C.peekCStringLen (C.castPtr p, isrcLength)
    poke p (Isrc s) = undefined
-}