htaglib-1.2.1: Sound/HTagLib/Getter.hs
{-# LANGUAGE DeriveFunctor #-}
-- |
-- Module : Sound.HTagLib.Getter
-- Copyright : © 2015–present Mark Karpov
-- License : BSD 3 clause
--
-- Maintainer : Mark Karpov <markkarpov92@gmail.com>
-- Stability : experimental
-- Portability : portable
--
-- An applicative interface for reading of audio meta data. You don't need
-- to import this module directly, import "Sound.HTagLib" instead.
module Sound.HTagLib.Getter
( -- * High-level API
TagGetter,
getTags,
getTags',
-- * Built-in getters
titleGetter,
artistGetter,
albumGetter,
commentGetter,
genreGetter,
yearGetter,
trackNumberGetter,
durationGetter,
bitRateGetter,
sampleRateGetter,
channelsGetter,
)
where
import Control.Monad.IO.Class
import Sound.HTagLib.Internal qualified as I
import Sound.HTagLib.Type
-- | A composable entity that can be passed to the 'getTags' or 'getTags''
-- functions to read multiple meta data fields at once.
newtype TagGetter a = TagGetter {runGetter :: I.FileId -> IO a}
deriving (Functor)
instance Applicative TagGetter where
pure = TagGetter . const . return
x <*> y = TagGetter $ \fid -> do
f <- runGetter x fid
f <$> runGetter y fid
-- | @getTags path g@ will try to read the file located at @path@ and read
-- the meta data of the file using the getter @g@. The type of the file will
-- be guessed from its extension. If this is not satisfactory and you want
-- to explicitly specify the file type, see 'getTags'' variation of this
-- function.
--
-- Throws 'I.HTagLibException'.
getTags ::
(MonadIO m) =>
-- | Path to audio file
FilePath ->
-- | Getter
TagGetter a ->
-- | Extracted data
m a
getTags path = execGetter path Nothing
-- | This is essentially the same as 'getTags', but allows us to explicitly
-- choose file type (see 'FileType').
getTags' ::
(MonadIO m) =>
-- | Path to audio file
FilePath ->
-- | Type of audio file
FileType ->
-- | Getter
TagGetter a ->
-- | Extracted data
m a
getTags' path t = execGetter path (Just t)
-- | This is the most general way to read meta data from file. 'getTags' and
-- 'getTags'' are just wrappers around the function.
execGetter ::
(MonadIO m) =>
-- | Path to audio file
FilePath ->
-- | Type of audio file (if known)
Maybe FileType ->
-- | Getter
TagGetter a ->
-- | Extracted data
m a
execGetter path t = liftIO . I.withFile path t . runGetter
-- | Getter to retrieve the track title.
titleGetter :: TagGetter Title
titleGetter = TagGetter I.getTitle
-- | Getter to retrieve the track artist.
artistGetter :: TagGetter Artist
artistGetter = TagGetter I.getArtist
-- | Getter to retrieve the track album.
albumGetter :: TagGetter Album
albumGetter = TagGetter I.getAlbum
-- | Getter to retrieve the track comment.
commentGetter :: TagGetter Comment
commentGetter = TagGetter I.getComment
-- | Getter to retrieve the genre of the track.
genreGetter :: TagGetter Genre
genreGetter = TagGetter I.getGenre
-- | Getter to retrieve the year of the track (returns 'Nothing' if the data
-- is missing).
yearGetter :: TagGetter (Maybe Year)
yearGetter = TagGetter I.getYear
-- | Getter to retrieve the track number (returns 'Nothing' if the data is
-- missing).
trackNumberGetter :: TagGetter (Maybe TrackNumber)
trackNumberGetter = TagGetter I.getTrackNumber
-- | Getter to retrieve the duration in seconds.
durationGetter :: TagGetter Duration
durationGetter = TagGetter I.getDuration
-- | Getter to retrieve the bit rate.
bitRateGetter :: TagGetter BitRate
bitRateGetter = TagGetter I.getBitRate
-- | Getter to retrieve the sample rate.
sampleRateGetter :: TagGetter SampleRate
sampleRateGetter = TagGetter I.getSampleRate
-- | Getter to retrieve the number of channels of the audio data.
channelsGetter :: TagGetter Channels
channelsGetter = TagGetter I.getChannels