{-| Description: Information about the division of a single disc into tracks. Copyright: (c) 2019-2021 Sam May License: GPL-3.0-or-later Maintainer: ag@eitilt.life Stability: stable Portability: non-portable (requires libcdio) What many people would think of as the most important division on a CD isn't quite as an integral a part of the physical data layout: they are described in a table of contents before the first track of any recording session, and may have lower-resolution "echoes" in the subchannels alongside the data, but it would be hard to otherwise recover the track boundaries from the data itself. This module, then, provides the functions to retrieve that metadata from the table of contents and from the subchannels. -} module Sound.Libcdio.Track ( -- * Types Foreign.Track ( .. ) , Foreign.minTrack , Foreign.maxTrack , Foreign.TrackNum , Foreign.TrackFormat ( .. ) -- * Location , firstDiscTrack , lastDiscTrack , tracks -- ** Address , trackAt , pregap , offset , offsetEnd , totalLength -- * Data , format , isGreen , hasPreemphasis , copyPermit , quadAudio ) where import qualified Foreign.Libcdio.Disc as Foreign import qualified Foreign.Libcdio.Track as Foreign import Sound.Libcdio.Read.Data import Sound.Libcdio.Types.Cdio -- | The number of the first track on the disc. This will almost always be 1, -- but that is not strictly guaranteed; the (perhaps theoretical) example is of -- a multi-disc set, where later discs pick the numbering back up where the -- previous one left off. -- -- Returns 'Nothing' if the disc table of contents can't be read. firstDiscTrack :: Cdio (Maybe Foreign.Track) firstDiscTrack = liftCdio Foreign.firstTrackNum -- | The number of the last track on the disc. -- -- Returns 'Nothing' if the disc table of contents can't be read. lastDiscTrack :: Cdio (Maybe Foreign.Track) lastDiscTrack = liftCdio Foreign.lastTrackNum -- | Get the number of tracks on a CD. -- -- Returns 'Nothing' if the disc table of contents can't be read. tracks :: Cdio (Maybe Foreign.Track) tracks = liftCdio Foreign.numTracks -- | The track which contains the given address. -- -- Returns 'Nothing' if the address is beyond the written data on the disc. -- Note that 'Foreign.DiscLeadout' is treated as if it were a single sector -- long: -- -- >>> Just endTrack <- lastDiscTrack -- >>> Just endAddr <- offsetEnd endTrack -- >>> trackAt $ endAddr + 1 -- Just DiscLeadout -- >>> trackAt $ endAddr + 2 -- Nothing trackAt :: Lsn -> Cdio (Maybe Foreign.Track) trackAt = liftCdio . flip Foreign.trackAt -- | The address of the start of any pregap before the given track. pregap :: Foreign.Track -> Cdio (Maybe Lsn) pregap = liftCdio . flip Foreign.pregapLsn -- | The address of the start of the given track. offset :: Foreign.Track -> Cdio (Maybe Lsn) offset = liftCdio . flip Foreign.trackLsn -- | The address of the end of the given track. offsetEnd :: Foreign.Track -> Cdio (Maybe Lsn) offsetEnd = liftCdio . flip Foreign.trackLastLsn -- | The number of sectors "assigned" to the specified track, including any in -- the pregap between it and the following one. totalLength :: Foreign.Track -> Cdio (Maybe Word) totalLength = liftCdio . flip Foreign.sectorCount -- | The raw data structure of a track. format :: Foreign.Track -> Cdio (Maybe Foreign.TrackFormat) format = liftCdio . flip Foreign.trackFormat -- | Whether the track data was stored using the Green Book (CD-i) standard. isGreen :: Foreign.Track -> Cdio (Maybe Bool) isGreen = liftCdio . flip Foreign.isGreen -- | Whether preemphasis has been applied to the track for noise reduction. hasPreemphasis :: Foreign.Track -> Cdio (Maybe Bool) hasPreemphasis = liftCdio . flip Foreign.hasPreemphasis -- | Whether the track may be legally copied. copyPermit :: Foreign.Track -> Cdio (Maybe Bool) copyPermit = liftCdio . flip Foreign.copyPermit -- | Whether the track was encoded with a richer 4-channel structure, or -- whether it just includes the standard stereo (2-channel) layout. quadAudio :: Foreign.Track -> Cdio (Maybe Bool) quadAudio t = liftCdio $ \c -> fmap (> 2) <$> Foreign.numChannels c t