hscdio-0.1.0.0: src/Sound/Libcdio/Device.hs
{-|
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