{-# LANGUAGE ForeignFunctionInterface #-}

{-|
Description:    Objects used to describe the CD and filesystem format.

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

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

Like any drive, discs may store their data according to many different
filesystem structures.  These are abstracted to a degree in libcdio, but as
each track may store its data differently, and at the very least 'Audio' is
handled differently than any of the file-oriented layouts, it is still helpful
to know the underlying structure.


= @cd_types.h@

== Defines
* CDIO_FSTYPE                       (removed; cdio_fs_anal_t represented differently in Haskell)
* CDIO_FS_UNKNOWN                   (removed; handled via 'Nothing')

== Types
* @cdio_fs_t@                       -> 'Foreign.Libcdio.CdTypes.Filesystem'

    - @CDIO_FS_INTERACTIVE@         -> 'Foreign.Libcdio.CdTypes.CdI'
    - @CDIO_FS_ISO_HFS@             -> 'Foreign.Libcdio.CdTypes.Hfs' with a 'Just' 'Foreign.Libcdio.CdTypes.IsoAnalysis'
    - @CDIO_FS_ISO_9660_INTERACTIVE@ -> 'Foreign.Libcdio.CdTypes.CdI' with a 'Just' 'Foreign.Libcdio.CdTypes.IsoAnalysis'
    - @CDIO_FS_ISO_UDF@             -> 'Foreign.Libcdio.CdTypes.Udf' with a 'Just' 'Foreign.Libcdio.CdTypes.IsoAnalysis'
    - @CDIO_FS_ISO_XISO@            -> 'Foreign.Libcdio.CdTypes.XboxIso'
    - @CDIO_FS_ISO_UDFX@            -> 'Foreign.Libcdio.CdTypes.XboxUdf'

* @cdio_fs_cap_t@                   -> 'Foreign.Libcdio.CdTypes.FilesystemClass'

    Note that some values are not included in the Haskell type, as the indexing
    implementation is stricter than the equivalent bit operations in C.

    - @CDIO_FS_MASK@                (removed; cdio_fs_anal_t represented differently in Haskell)
    - @CDIO_FS_ANAL_VCD_ANY@        -> 'Foreign.Libcdio.CdTypes.fsAnyVcd'
    - @CDIO_FS_MATCH_ALL@           -> 'Foreign.Libcdio.CdTypes.fsAny'
    - @CDIO_FS_ANAL_CDTV@           -> 'Foreign.Libcdio.CdTypes.CommodoreCdtv'
    - @CDIO_FS_ANAL_SVCD@           -> 'Foreign.Libcdio.CdTypes.SuperVideoCd'
    - @CDIO_FS_ANAL_CVD@            -> 'Foreign.Libcdio.CdTypes.ChoijiVideoCd'
    - @CDIO_FS_ANAL_XISO@           -> 'Foreign.Libcdio.CdTypes.XboxIsoClass'

* @cdio_iso_analysis_t@             -> 'Foreign.Libcdio.CdTypes.IsoAnalysis'

    - @joliet_level@                -> 'Foreign.Libcdio.CdTypes.jolietLevel'
    - @iso_label@                   -> 'Foreign.Libcdio.CdTypes.label'
    - @isofs_size@                  -> 'Foreign.Libcdio.CdTypes.fsSize'
    - @UDFVerMajor@                 -> 'fst' 'Foreign.Libcdio.CdTypes.udfVersion'
    - @UDFVerMinor@                 -> 'snd' 'Foreign.Libcdio.CdTypes.udfVersion'

== Symbols
* @cdio_guess_cd_type@              -> 'Foreign.Libcdio.CdTypes.trackType'


= "Sound.Libcdio.Read.Filesystem"

* 'trackType'                       -> 'Sound.Libcdio.Read.Filesystem.filesystemType'
-}
module Foreign.Libcdio.CdTypes
    ( -- * Types
      Filesystem ( .. )
    , FilesystemClass ( .. )
    , FilesystemClasses
    , fsAny, fsAnyVcd
    , IsoAnalysis ( .. )
      -- * Access
    , trackType
    ) where


import qualified Data.Maybe as Y
import qualified Data.Word as W

import qualified Data.Array.BitArray as A

import qualified Foreign.C.String as C
import qualified Foreign.C.Types as C
import qualified Foreign.Ptr as C

import qualified Foreign.Marshal.Alloc as M
import qualified Foreign.Storable as S

import Foreign.Libcdio.Marshal
import Foreign.Libcdio.Track
import Foreign.Libcdio.Types.Enums
import Foreign.Libcdio.Types.Offsets
import Foreign.Libcdio.Types.Internal


-- | Types of filesystem which may be read from a disc.
data Filesystem
    = Audio
    | HighSierra
    | Iso9660
    | CdI
    | Cd3do
    | Ext2
    | Hfs
    | Ufs
    | Udf
    | XboxIso
    | XboxUdf
  deriving ( Filesystem -> Filesystem -> Bool
(Filesystem -> Filesystem -> Bool)
-> (Filesystem -> Filesystem -> Bool) -> Eq Filesystem
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Filesystem -> Filesystem -> Bool
$c/= :: Filesystem -> Filesystem -> Bool
== :: Filesystem -> Filesystem -> Bool
$c== :: Filesystem -> Filesystem -> Bool
Eq, Int -> Filesystem -> ShowS
[Filesystem] -> ShowS
Filesystem -> String
(Int -> Filesystem -> ShowS)
-> (Filesystem -> String)
-> ([Filesystem] -> ShowS)
-> Show Filesystem
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Filesystem] -> ShowS
$cshowList :: [Filesystem] -> ShowS
show :: Filesystem -> String
$cshow :: Filesystem -> String
showsPrec :: Int -> Filesystem -> ShowS
$cshowsPrec :: Int -> Filesystem -> ShowS
Show, ReadPrec [Filesystem]
ReadPrec Filesystem
Int -> ReadS Filesystem
ReadS [Filesystem]
(Int -> ReadS Filesystem)
-> ReadS [Filesystem]
-> ReadPrec Filesystem
-> ReadPrec [Filesystem]
-> Read Filesystem
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Filesystem]
$creadListPrec :: ReadPrec [Filesystem]
readPrec :: ReadPrec Filesystem
$creadPrec :: ReadPrec Filesystem
readList :: ReadS [Filesystem]
$creadList :: ReadS [Filesystem]
readsPrec :: Int -> ReadS Filesystem
$creadsPrec :: Int -> ReadS Filesystem
Read, Eq Filesystem
Eq Filesystem
-> (Filesystem -> Filesystem -> Ordering)
-> (Filesystem -> Filesystem -> Bool)
-> (Filesystem -> Filesystem -> Bool)
-> (Filesystem -> Filesystem -> Bool)
-> (Filesystem -> Filesystem -> Bool)
-> (Filesystem -> Filesystem -> Filesystem)
-> (Filesystem -> Filesystem -> Filesystem)
-> Ord Filesystem
Filesystem -> Filesystem -> Bool
Filesystem -> Filesystem -> Ordering
Filesystem -> Filesystem -> Filesystem
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 :: Filesystem -> Filesystem -> Filesystem
$cmin :: Filesystem -> Filesystem -> Filesystem
max :: Filesystem -> Filesystem -> Filesystem
$cmax :: Filesystem -> Filesystem -> Filesystem
>= :: Filesystem -> Filesystem -> Bool
$c>= :: Filesystem -> Filesystem -> Bool
> :: Filesystem -> Filesystem -> Bool
$c> :: Filesystem -> Filesystem -> Bool
<= :: Filesystem -> Filesystem -> Bool
$c<= :: Filesystem -> Filesystem -> Bool
< :: Filesystem -> Filesystem -> Bool
$c< :: Filesystem -> Filesystem -> Bool
compare :: Filesystem -> Filesystem -> Ordering
$ccompare :: Filesystem -> Filesystem -> Ordering
$cp1Ord :: Eq Filesystem
Ord, Int -> Filesystem
Filesystem -> Int
Filesystem -> [Filesystem]
Filesystem -> Filesystem
Filesystem -> Filesystem -> [Filesystem]
Filesystem -> Filesystem -> Filesystem -> [Filesystem]
(Filesystem -> Filesystem)
-> (Filesystem -> Filesystem)
-> (Int -> Filesystem)
-> (Filesystem -> Int)
-> (Filesystem -> [Filesystem])
-> (Filesystem -> Filesystem -> [Filesystem])
-> (Filesystem -> Filesystem -> [Filesystem])
-> (Filesystem -> Filesystem -> Filesystem -> [Filesystem])
-> Enum Filesystem
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 :: Filesystem -> Filesystem -> Filesystem -> [Filesystem]
$cenumFromThenTo :: Filesystem -> Filesystem -> Filesystem -> [Filesystem]
enumFromTo :: Filesystem -> Filesystem -> [Filesystem]
$cenumFromTo :: Filesystem -> Filesystem -> [Filesystem]
enumFromThen :: Filesystem -> Filesystem -> [Filesystem]
$cenumFromThen :: Filesystem -> Filesystem -> [Filesystem]
enumFrom :: Filesystem -> [Filesystem]
$cenumFrom :: Filesystem -> [Filesystem]
fromEnum :: Filesystem -> Int
$cfromEnum :: Filesystem -> Int
toEnum :: Int -> Filesystem
$ctoEnum :: Int -> Filesystem
pred :: Filesystem -> Filesystem
$cpred :: Filesystem -> Filesystem
succ :: Filesystem -> Filesystem
$csucc :: Filesystem -> Filesystem
Enum, Filesystem
Filesystem -> Filesystem -> Bounded Filesystem
forall a. a -> a -> Bounded a
maxBound :: Filesystem
$cmaxBound :: Filesystem
minBound :: Filesystem
$cminBound :: Filesystem
Bounded )


-- | A collection of disc/filesystem descriptions.
type FilesystemClasses = A.BitArray FilesystemClass

-- | Any sort of Video CD.
fsAnyVcd :: FilesystemClasses
fsAnyVcd :: FilesystemClasses
fsAnyVcd = [FilesystemClass] -> FilesystemClasses
forall a. (Bounded a, Ix a) => [a] -> BitArray a
genBitArray
    [ FilesystemClass
VideoCd
    , FilesystemClass
SuperVideoCd
    , FilesystemClass
ChoijiVideoCd
    ]

-- | The set of every 'FilesystemClass'.
fsAny :: FilesystemClasses
fsAny :: FilesystemClasses
fsAny = [FilesystemClass] -> FilesystemClasses
forall a. (Bounded a, Ix a) => [a] -> BitArray a
genBitArray [FilesystemClass
forall a. Bounded a => a
minBound .. FilesystemClass
forall a. Bounded a => a
maxBound]


-- | A collection of data describing a disc using the ISO 9660 standard.
data IsoAnalysis = IsoAnalysis
    { IsoAnalysis -> Maybe Word
jolietLevel :: Maybe Word
    , IsoAnalysis -> String
label       :: String
    , IsoAnalysis -> Word
fsSize      :: Word
    , IsoAnalysis -> Maybe (Word8, Word8)
udfVersion  :: Maybe (W.Word8, W.Word8)
    }
  deriving ( IsoAnalysis -> IsoAnalysis -> Bool
(IsoAnalysis -> IsoAnalysis -> Bool)
-> (IsoAnalysis -> IsoAnalysis -> Bool) -> Eq IsoAnalysis
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: IsoAnalysis -> IsoAnalysis -> Bool
$c/= :: IsoAnalysis -> IsoAnalysis -> Bool
== :: IsoAnalysis -> IsoAnalysis -> Bool
$c== :: IsoAnalysis -> IsoAnalysis -> Bool
Eq, Int -> IsoAnalysis -> ShowS
[IsoAnalysis] -> ShowS
IsoAnalysis -> String
(Int -> IsoAnalysis -> ShowS)
-> (IsoAnalysis -> String)
-> ([IsoAnalysis] -> ShowS)
-> Show IsoAnalysis
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IsoAnalysis] -> ShowS
$cshowList :: [IsoAnalysis] -> ShowS
show :: IsoAnalysis -> String
$cshow :: IsoAnalysis -> String
showsPrec :: Int -> IsoAnalysis -> ShowS
$cshowsPrec :: Int -> IsoAnalysis -> ShowS
Show, ReadPrec [IsoAnalysis]
ReadPrec IsoAnalysis
Int -> ReadS IsoAnalysis
ReadS [IsoAnalysis]
(Int -> ReadS IsoAnalysis)
-> ReadS [IsoAnalysis]
-> ReadPrec IsoAnalysis
-> ReadPrec [IsoAnalysis]
-> Read IsoAnalysis
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [IsoAnalysis]
$creadListPrec :: ReadPrec [IsoAnalysis]
readPrec :: ReadPrec IsoAnalysis
$creadPrec :: ReadPrec IsoAnalysis
readList :: ReadS [IsoAnalysis]
$creadList :: ReadS [IsoAnalysis]
readsPrec :: Int -> ReadS IsoAnalysis
$creadsPrec :: Int -> ReadS IsoAnalysis
Read )
instance S.Storable IsoAnalysis where
    sizeOf :: IsoAnalysis -> Int
sizeOf IsoAnalysis
_    = Int
iaSizeOf
    alignment :: IsoAnalysis -> Int
alignment IsoAnalysis
_ = Int
iaAlign
    peek :: Ptr IsoAnalysis -> IO IsoAnalysis
peek Ptr IsoAnalysis
c = do
        CUInt
j <- Ptr IsoAnalysis -> Int -> IO CUInt
forall a b. Storable a => Ptr b -> Int -> IO a
S.peekByteOff Ptr IsoAnalysis
c Int
iaJolietLevel :: IO C.CUInt
        String
l <- CString -> IO String
C.peekCString (CString -> IO String) -> CString -> IO String
forall a b. (a -> b) -> a -> b
$ Ptr IsoAnalysis -> Int -> CString
forall a b. Ptr a -> Int -> Ptr b
C.plusPtr Ptr IsoAnalysis
c Int
iaLabel
        CUInt
s <- Ptr IsoAnalysis -> Int -> IO CUInt
forall a b. Storable a => Ptr b -> Int -> IO a
S.peekByteOff Ptr IsoAnalysis
c Int
iaIsoSize :: IO C.CUInt
        Word8
a <- Ptr IsoAnalysis -> Int -> IO Word8
forall a b. Storable a => Ptr b -> Int -> IO a
S.peekByteOff Ptr IsoAnalysis
c Int
iaUDFMajor
        Word8
i <- Ptr IsoAnalysis -> Int -> IO Word8
forall a b. Storable a => Ptr b -> Int -> IO a
S.peekByteOff Ptr IsoAnalysis
c Int
iaUDFMinor
        IsoAnalysis -> IO IsoAnalysis
forall (m :: * -> *) a. Monad m => a -> m a
return (IsoAnalysis -> IO IsoAnalysis) -> IsoAnalysis -> IO IsoAnalysis
forall a b. (a -> b) -> a -> b
$ IsoAnalysis :: Maybe Word -> String -> Word -> Maybe (Word8, Word8) -> IsoAnalysis
IsoAnalysis
            { jolietLevel :: Maybe Word
jolietLevel = if CUInt
j CUInt -> CUInt -> Bool
forall a. Eq a => a -> a -> Bool
== CUInt
0 then Maybe Word
forall a. Maybe a
Nothing else Word -> Maybe Word
forall a. a -> Maybe a
Just (Word -> Maybe Word) -> Word -> Maybe Word
forall a b. (a -> b) -> a -> b
$ CUInt -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral CUInt
j
            , label :: String
label = String
l
            , fsSize :: Word
fsSize = CUInt -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral CUInt
s
            , udfVersion :: Maybe (Word8, Word8)
udfVersion = if Word8
a Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0 then Maybe (Word8, Word8)
forall a. Maybe a
Nothing else (Word8, Word8) -> Maybe (Word8, Word8)
forall a. a -> Maybe a
Just (Word8
a, Word8
i)
            }
    poke :: Ptr IsoAnalysis -> IsoAnalysis -> IO ()
poke Ptr IsoAnalysis
c IsoAnalysis
hs = do
        let (Word8
a, Word8
i) = (Word8, Word8) -> Maybe (Word8, Word8) -> (Word8, Word8)
forall a. a -> Maybe a -> a
Y.fromMaybe (Word8
0, Word8
0) (Maybe (Word8, Word8) -> (Word8, Word8))
-> Maybe (Word8, Word8) -> (Word8, Word8)
forall a b. (a -> b) -> a -> b
$ IsoAnalysis -> Maybe (Word8, Word8)
udfVersion IsoAnalysis
hs
        Ptr IsoAnalysis -> Int -> CUInt -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
S.pokeByteOff Ptr IsoAnalysis
c Int
iaJolietLevel (CUInt -> IO ()) -> (Maybe Word -> CUInt) -> Maybe Word -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CUInt -> (Word -> CUInt) -> Maybe Word -> CUInt
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (CUInt
0 :: C.CUInt) Word -> CUInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Maybe Word -> IO ()) -> Maybe Word -> IO ()
forall a b. (a -> b) -> a -> b
$ IsoAnalysis -> Maybe Word
jolietLevel IsoAnalysis
hs
        String -> Int -> CString -> IO ()
pokeCString (IsoAnalysis -> String
label IsoAnalysis
hs) Int
33 (CString -> IO ()) -> CString -> IO ()
forall a b. (a -> b) -> a -> b
$ Ptr IsoAnalysis -> Int -> CString
forall a b. Ptr a -> Int -> Ptr b
C.plusPtr Ptr IsoAnalysis
c Int
iaLabel
        Ptr IsoAnalysis -> Int -> CUInt -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
S.pokeByteOff Ptr IsoAnalysis
c Int
iaIsoSize (Word -> CUInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word -> CUInt) -> Word -> CUInt
forall a b. (a -> b) -> a -> b
$ IsoAnalysis -> Word
fsSize IsoAnalysis
hs :: C.CUInt)
        Ptr IsoAnalysis -> Int -> Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
S.pokeByteOff Ptr IsoAnalysis
c Int
iaUDFMajor Word8
a
        Ptr IsoAnalysis -> Int -> Word8 -> IO ()
forall a b. Storable a => Ptr b -> Int -> a -> IO ()
S.pokeByteOff Ptr IsoAnalysis
c Int
iaUDFMinor Word8
i


-- | Determine what type of file system is stored in the given track of a disc.
trackType :: Cdio -> Track -> IO (Maybe Filesystem, FilesystemClasses, Maybe IsoAnalysis)
trackType :: Cdio
-> Track
-> IO (Maybe Filesystem, FilesystemClasses, Maybe IsoAnalysis)
trackType Cdio
c Track
t = do
    Maybe Lsn
l' <- Cdio -> Track -> IO (Maybe Lsn)
trackLsn Cdio
c Track
t
    ((Maybe Filesystem_, FilesystemClasses)
fs, IsoAnalysis
iso') <- case Maybe Lsn
l' of
        Just Lsn
l -> ((Maybe Filesystem_, FilesystemClasses), IsoAnalysis)
-> (Ptr Cdio
    -> IO ((Maybe Filesystem_, FilesystemClasses), IsoAnalysis))
-> IO ((Maybe Filesystem_, FilesystemClasses), IsoAnalysis)
forall b. b -> (Ptr Cdio -> IO b) -> IO b
withCdio' ((Maybe Filesystem_, FilesystemClasses), IsoAnalysis)
forall a. ((Maybe a, FilesystemClasses), IsoAnalysis)
defaultCdType ((Ptr Cdio
  -> IO ((Maybe Filesystem_, FilesystemClasses), IsoAnalysis))
 -> IO ((Maybe Filesystem_, FilesystemClasses), IsoAnalysis))
-> (Ptr Cdio
    -> IO ((Maybe Filesystem_, FilesystemClasses), IsoAnalysis))
-> IO ((Maybe Filesystem_, FilesystemClasses), IsoAnalysis)
forall a b. (a -> b) -> a -> b
$ \Ptr Cdio
c' -> (Ptr IsoAnalysis
 -> IO ((Maybe Filesystem_, FilesystemClasses), IsoAnalysis))
-> IO ((Maybe Filesystem_, FilesystemClasses), IsoAnalysis)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
M.alloca ((Ptr IsoAnalysis
  -> IO ((Maybe Filesystem_, FilesystemClasses), IsoAnalysis))
 -> IO ((Maybe Filesystem_, FilesystemClasses), IsoAnalysis))
-> (Ptr IsoAnalysis
    -> IO ((Maybe Filesystem_, FilesystemClasses), IsoAnalysis))
-> IO ((Maybe Filesystem_, FilesystemClasses), IsoAnalysis)
forall a b. (a -> b) -> a -> b
$ \Ptr IsoAnalysis
i' -> do
            CInt
e' <- Ptr Cdio -> Lsn -> CTrack -> Ptr IsoAnalysis -> IO CInt
cdType_ Ptr Cdio
c' Lsn
l (Track -> CTrack
withTrack Track
t) Ptr IsoAnalysis
i'
            IsoAnalysis
iso <- Ptr IsoAnalysis -> IO IsoAnalysis
forall a. Storable a => Ptr a -> IO a
S.peek Ptr IsoAnalysis
i'
            ((Maybe Filesystem_, FilesystemClasses), IsoAnalysis)
-> IO ((Maybe Filesystem_, FilesystemClasses), IsoAnalysis)
forall (m :: * -> *) a. Monad m => a -> m a
return (CInt -> (Maybe Filesystem_, FilesystemClasses)
forall a b c.
(Integral a, Bits a, Enum b, Bounded b, Enum c, Bounded c, Ix c) =>
a -> (Maybe b, BitArray c)
modEnumFlags CInt
e', IsoAnalysis
iso)
        Maybe Lsn
Nothing -> ((Maybe Filesystem_, FilesystemClasses), IsoAnalysis)
-> IO ((Maybe Filesystem_, FilesystemClasses), IsoAnalysis)
forall (m :: * -> *) a. Monad m => a -> m a
return ((Maybe Filesystem_, FilesystemClasses), IsoAnalysis)
forall a. ((Maybe a, FilesystemClasses), IsoAnalysis)
defaultCdType
    let fc :: FilesystemClasses
fc = (Maybe Filesystem_, FilesystemClasses) -> FilesystemClasses
forall a b. (a, b) -> b
snd (Maybe Filesystem_, FilesystemClasses)
fs
        iso :: Maybe IsoAnalysis
iso = IsoAnalysis -> Maybe IsoAnalysis
forall a. a -> Maybe a
Just IsoAnalysis
iso' { udfVersion :: Maybe (Word8, Word8)
udfVersion = Maybe (Word8, Word8)
forall a. Maybe a
Nothing }
        isoUdf :: Maybe IsoAnalysis
isoUdf = IsoAnalysis -> Maybe IsoAnalysis
forall a. a -> Maybe a
Just IsoAnalysis
iso'
    (Maybe Filesystem, FilesystemClasses, Maybe IsoAnalysis)
-> IO (Maybe Filesystem, FilesystemClasses, Maybe IsoAnalysis)
forall (m :: * -> *) a. Monad m => a -> m a
return ((Maybe Filesystem, FilesystemClasses, Maybe IsoAnalysis)
 -> IO (Maybe Filesystem, FilesystemClasses, Maybe IsoAnalysis))
-> (Maybe Filesystem, FilesystemClasses, Maybe IsoAnalysis)
-> IO (Maybe Filesystem, FilesystemClasses, Maybe IsoAnalysis)
forall a b. (a -> b) -> a -> b
$ case (Maybe Filesystem_, FilesystemClasses) -> Maybe Filesystem_
forall a b. (a, b) -> a
fst (Maybe Filesystem_, FilesystemClasses)
fs of
        Maybe Filesystem_
Nothing -> (Maybe Filesystem
forall a. Maybe a
Nothing, FilesystemClasses
fc, Maybe IsoAnalysis
isoUdf)
        Just Filesystem_
Fs3do -> (Filesystem -> Maybe Filesystem
forall a. a -> Maybe a
Just Filesystem
Cd3do, FilesystemClasses
fc, Maybe IsoAnalysis
iso)
        Just Filesystem_
FsAudio -> (Filesystem -> Maybe Filesystem
forall a. a -> Maybe a
Just Filesystem
Audio, FilesystemClasses
fc, Maybe IsoAnalysis
forall a. Maybe a
Nothing)
        Just Filesystem_
FsExt2 -> (Filesystem -> Maybe Filesystem
forall a. a -> Maybe a
Just Filesystem
Ext2, FilesystemClasses
fc, Maybe IsoAnalysis
iso)
        Just Filesystem_
FsHfs -> (Filesystem -> Maybe Filesystem
forall a. a -> Maybe a
Just Filesystem
Hfs, FilesystemClasses
fc, Maybe IsoAnalysis
forall a. Maybe a
Nothing)
        Just Filesystem_
FsIsoHfs -> (Filesystem -> Maybe Filesystem
forall a. a -> Maybe a
Just Filesystem
Hfs, FilesystemClasses
fc, Maybe IsoAnalysis
iso)
        Just Filesystem_
FsHighSierra -> (Filesystem -> Maybe Filesystem
forall a. a -> Maybe a
Just Filesystem
HighSierra, FilesystemClasses
fc, Maybe IsoAnalysis
iso)
        Just Filesystem_
FsInteractive -> (Filesystem -> Maybe Filesystem
forall a. a -> Maybe a
Just Filesystem
CdI, FilesystemClasses
fc, Maybe IsoAnalysis
forall a. Maybe a
Nothing)
        Just Filesystem_
FsIso9660Interactive -> (Filesystem -> Maybe Filesystem
forall a. a -> Maybe a
Just Filesystem
CdI, FilesystemClasses
fc, Maybe IsoAnalysis
iso)
        Just Filesystem_
FsIso9660 -> (Filesystem -> Maybe Filesystem
forall a. a -> Maybe a
Just Filesystem
Iso9660, FilesystemClasses
fc, Maybe IsoAnalysis
iso)
        Just Filesystem_
FsUdf -> (Filesystem -> Maybe Filesystem
forall a. a -> Maybe a
Just Filesystem
Udf, FilesystemClasses
fc, Maybe IsoAnalysis
forall a. Maybe a
Nothing)
        Just Filesystem_
FsIsoUdf -> (Filesystem -> Maybe Filesystem
forall a. a -> Maybe a
Just Filesystem
Udf, FilesystemClasses
fc, Maybe IsoAnalysis
isoUdf)
        Just Filesystem_
FsUdfx -> (Filesystem -> Maybe Filesystem
forall a. a -> Maybe a
Just Filesystem
Udf, FilesystemClasses
fc, Maybe IsoAnalysis
isoUdf)
        Just Filesystem_
FsUfs -> (Filesystem -> Maybe Filesystem
forall a. a -> Maybe a
Just Filesystem
Ufs, FilesystemClasses
fc, Maybe IsoAnalysis
iso)
        Just Filesystem_
FsXiso -> (Filesystem -> Maybe Filesystem
forall a. a -> Maybe a
Just Filesystem
XboxIso, FilesystemClasses
fc, Maybe IsoAnalysis
iso)
  where defaultCdType :: ((Maybe a, FilesystemClasses), IsoAnalysis)
defaultCdType = ((Maybe a
forall a. Maybe a
Nothing, [FilesystemClass] -> FilesystemClasses
forall a. (Bounded a, Ix a) => [a] -> BitArray a
genBitArray []), Maybe Word -> String -> Word -> Maybe (Word8, Word8) -> IsoAnalysis
IsoAnalysis Maybe Word
forall a. Maybe a
Nothing String
"" Word
0 Maybe (Word8, Word8)
forall a. Maybe a
Nothing)
        withCdio' :: b -> (Ptr Cdio -> IO b) -> IO b
withCdio' b
b = (Maybe b -> b) -> IO (Maybe b) -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (b -> Maybe b -> b
forall a. a -> Maybe a -> a
Y.fromMaybe b
b) (IO (Maybe b) -> IO b)
-> ((Ptr Cdio -> IO b) -> IO (Maybe b))
-> (Ptr Cdio -> IO b)
-> IO b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Cdio -> (Ptr Cdio -> IO b) -> IO (Maybe b)
forall b. Cdio -> (Ptr Cdio -> IO b) -> IO (Maybe b)
withCdio Cdio
c

foreign import ccall safe "cdio/compat/cd_types.h cdio_guess_cd_type"
  cdType_ :: C.Ptr Cdio -> Lsn -> CTrack -> C.Ptr IsoAnalysis -> IO C.CInt