htaglib-1.2.1: Sound/HTagLib/Setter.hs
{-# LANGUAGE RecordWildCards #-}
-- |
-- Module : Sound.HTagLib.Setter
-- Copyright : © 2015–present Mark Karpov
-- License : BSD 3 clause
--
-- Maintainer : Mark Karpov <markkarpov92@gmail.com>
-- Stability : experimental
-- Portability : portable
--
-- An interface for writing audio meta data. You don't need to import this
-- module directly, import "Sound.HTagLib" instead.
module Sound.HTagLib.Setter
( -- * High-level API
TagSetter,
setTags,
setTags',
-- * Built-in setters
titleSetter,
artistSetter,
albumSetter,
commentSetter,
genreSetter,
yearSetter,
trackNumberSetter,
)
where
import Control.Applicative ((<|>))
import Control.Monad.IO.Class
import Data.Foldable (forM_)
import Sound.HTagLib.Internal qualified as I
import Sound.HTagLib.Type
-- | A composable entity that can be used together with the 'setTags' or the
-- 'setTags'' functions to write meta data to an audio file.
--
-- Note that in case of (for example):
--
-- > titleSetter "foo" <> titleSetter "bar"
--
-- The first value wins.
data TagSetter = TagSetter
{ sdTitle :: Maybe Title,
sdArtist :: Maybe Artist,
sdAlbum :: Maybe Album,
sdComment :: Maybe Comment,
sdGenre :: Maybe Genre,
sdYear :: Maybe (Maybe Year),
sdTrackNumber :: Maybe (Maybe TrackNumber)
}
-- | @since 1.2.0
instance Semigroup TagSetter where
x <> y =
let f g = g x <|> g y
in TagSetter
{ sdTitle = f sdTitle,
sdArtist = f sdArtist,
sdAlbum = f sdAlbum,
sdComment = f sdComment,
sdGenre = f sdGenre,
sdYear = f sdYear,
sdTrackNumber = f sdTrackNumber
}
instance Monoid TagSetter where
mempty =
TagSetter
{ sdTitle = Nothing,
sdArtist = Nothing,
sdAlbum = Nothing,
sdComment = Nothing,
sdGenre = Nothing,
sdYear = Nothing,
sdTrackNumber = Nothing
}
mappend = (<>)
-- | Set tags in a specified file using the given setter.
--
-- Throws 'I.HTagLibException'.
setTags ::
(MonadIO m) =>
-- | Path to audio file
FilePath ->
-- | Encoding for ID3v2 frames
Maybe ID3v2Encoding ->
-- | Setter
TagSetter ->
m ()
setTags path enc = execSetter path enc Nothing
-- | Similar to 'setTags', but you can also specify the type of the audio
-- file explicitly (otherwise it's guessed from the file extension).
setTags' ::
(MonadIO m) =>
-- | Path to audio file
FilePath ->
-- | Encoding for ID3v2 frames
Maybe ID3v2Encoding ->
-- | Type of audio file
FileType ->
-- | Setter
TagSetter ->
m ()
setTags' path enc t = execSetter path enc (Just t)
-- | The most general way to set meta data. 'setTags' and 'setTags'' are
-- just wrappers around this function.
execSetter ::
(MonadIO m) =>
-- | Path to audio file
FilePath ->
-- | Encoding for ID3v2 frames
Maybe ID3v2Encoding ->
-- | Type of audio file (if known)
Maybe FileType ->
-- | Setter
TagSetter ->
m ()
execSetter path enc t TagSetter {..} = liftIO . I.withFile path t $ \fid -> do
forM_ enc I.id3v2SetEncoding
let writeTag x f = forM_ x (`f` fid)
writeTag sdTitle I.setTitle
writeTag sdArtist I.setArtist
writeTag sdAlbum I.setAlbum
writeTag sdComment I.setComment
writeTag sdGenre I.setGenre
writeTag sdYear I.setYear
writeTag sdTrackNumber I.setTrackNumber
I.saveFile path fid
-- | Setter for the track title.
titleSetter :: Title -> TagSetter
titleSetter x = mempty {sdTitle = Just x}
-- | Setter for the track artist.
artistSetter :: Artist -> TagSetter
artistSetter x = mempty {sdArtist = Just x}
-- | Setter for the track album.
albumSetter :: Album -> TagSetter
albumSetter x = mempty {sdAlbum = Just x}
-- | Setter for the track comment.
commentSetter :: Comment -> TagSetter
commentSetter x = mempty {sdComment = Just x}
-- | Setter for the track genre.
genreSetter :: Genre -> TagSetter
genreSetter x = mempty {sdGenre = Just x}
-- | Setter for the year tag, use 'Nothing' to clear the field.
yearSetter :: Maybe Year -> TagSetter
yearSetter x = mempty {sdYear = Just x}
-- | Setter for the track number, use 'Nothing' to clear the field.
trackNumberSetter :: Maybe TrackNumber -> TagSetter
trackNumberSetter x = mempty {sdTrackNumber = Just x}