{-| Description: Information and procedures related to a system's (usually) physical disc drives. Copyright: (c) 2019-2021 Sam May License: GPL-3.0-or-later Maintainer: ag@eitilt.life Stability: stable Portability: non-portable (requires libcdio) Any software dealing with CDs has to deal with the fact that they are, ultimately, a physical medium and thus reading from them requires interfacing with system hardware. This module provides the means to do just that. Note that, unlike the C and "Foreign.Libcdio" interfaces, however, this /doesn't/ provide any means to open a read session; that functionality is instead exported directly from "Sound.Libcdio". -} module Sound.Libcdio.Device ( -- * Types Foreign.HardwareInfo ( .. ) , Foreign.emptyHardwareInfo , Foreign.DriverId ( .. ) , Foreign.DriverReturnCode ( .. ) -- ** Capabilities , Foreign.DriveCaps , Foreign.DriveCapabilityRead ( .. ) , Foreign.DriveReadCaps , Foreign.DriveCapabilityWrite ( .. ) , Foreign.DriveWriteCaps , Foreign.capsWriteCd , Foreign.capsWriteDvd , Foreign.capsWrite , Foreign.DriveCapabilityMisc ( .. ) , Foreign.DriveMiscCaps -- * Drivers , driver , Foreign.drivers , Foreign.osDriver , isImageDriver , isDevice -- * Session , setBlocksize , setSpeed , isMediaChanged -- * Devices , Foreign.devices , Foreign.defaultDevice , Foreign.defaultDeviceDriver , capabilities , deviceCapabilities -- ** Images , isCue , Foreign.isToc , Foreign.isNrg -- ** Hardware , hardware , haveAtapi , ejectDevice , closeDeviceTray , closeDeviceTray' ) where import qualified Data.Maybe as Y import qualified Foreign.Libcdio.Device as Foreign import Sound.Libcdio.Types.Cdio -- | Get the driver through which the disc is being read. driver :: Cdio Foreign.DriverId driver = liftCdio $ fmap (Y.fromMaybe Foreign.DriverUnknown) . Foreign.driverId -- | Whether a particular driver deals with image files saved to disc, or a CD -- drive itself. isImageDriver :: Foreign.DriverId -> Bool isImageDriver = not . flip elem Foreign.deviceDrivers -- | Get a description of the device in use. hardware :: Cdio Foreign.HardwareInfo hardware = liftCdio $ fmap (Y.fromMaybe Foreign.emptyHardwareInfo) . Foreign.hwinfo -- | Which features are provided by the current device. See -- 'deviceCapabilities' when a session has not yet been opened. capabilities :: Cdio Foreign.DriveCaps capabilities = liftCdio Foreign.driveCap -- | Whether ATAPI commands are understood by the current device. -- -- Returns 'Nothing' if the capability can't be determined. haveAtapi :: Cdio (Maybe Bool) haveAtapi = liftCdio Foreign.haveAtapi -- | Which features are provided by a particular device. See 'capabilities' -- for accessing these within a 'Cdio' session. deviceCapabilities :: FilePath -> IO Foreign.DriveCaps deviceCapabilities = Foreign.driveCapDevice -- | Open a particular device's tray or otherwise free any disc it holds for -- removal, replacement, or insertion. ejectDevice :: Maybe FilePath -> IO Foreign.DriverReturnCode ejectDevice = Foreign.ejectDrive -- | If a device supports discs on an extending, motorized tray (i.e. a -- standard CD drive), close it. closeDeviceTray :: Maybe FilePath -> IO Foreign.DriverReturnCode closeDeviceTray = fmap fst . flip Foreign.closeTray Foreign.DriverUnknown -- | As 'closeDeviceTray'', but specify the driver to use in case of ambiguity. closeDeviceTray' :: Maybe FilePath -> Foreign.DriverId -> IO Foreign.DriverReturnCode closeDeviceTray' p = fmap fst . Foreign.closeTray p -- | Specify how much data should be read from a disc at once. Note that this -- only affects the transport; any reading functions operate on independant -- byte counts or other sizes derived from such. setBlocksize :: Int -> Cdio Foreign.DriverReturnCode setBlocksize s = liftCdio $ flip Foreign.setBlocksize s -- | Specify the speed at which the disc is read. Lower values result in -- slower IO, but better accuracy. setSpeed :: Int -> Cdio Foreign.DriverReturnCode setSpeed s = liftCdio $ flip Foreign.setSpeed s -- | Check if any data in the read session has been changed since the last call -- of this function. This is most helpful when multiple 'Cdio' computations -- are run on a partial call of 'Sound.Libcdio.Types.Cdio.open' or similar. isMediaChanged :: Cdio (Either Foreign.DriverReturnCode Bool) isMediaChanged = liftCdio Foreign.isMediaChanged -- | Whether a file is valid according to the (loose) CUE standard. isCue :: FilePath -> IO Bool isCue = fmap Y.isJust . Foreign.binFromCue -- | Whether the path represents a physical disc drive in the system. isDevice :: FilePath -> IO Bool isDevice = flip Foreign.isDevice Foreign.DriverDevice