Skip to content

Commit

Permalink
switch to ‘Text’, rename un-wrappers
Browse files Browse the repository at this point in the history
  • Loading branch information
mrkkrp committed Dec 23, 2015
1 parent 6971bfc commit ce53d35
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 81 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

* Make the module `Sound.HTagLib.Internal` hidden for end users.

* Make `Text` underlying type for wrappers around textual data (breaking
change, previously it was `String`).

* Rename functions like `getTitle` to `unTitle` (breaking change).

* Fix bug when wrong data is read from files when current locale specifies
encoding other than UTF-8.

## HTagLib 0.1.1

* Missing audio samples used for testing are included in distribution.
Expand Down
22 changes: 11 additions & 11 deletions Sound/HTagLib.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,37 +14,37 @@ module Sound.HTagLib
( -- * Data types
Title
, mkTitle
, getTitle
, unTitle
, Artist
, mkArtist
, getArtist
, unArtist
, Album
, mkAlbum
, getAlbum
, unAlbum
, Comment
, mkComment
, getComment
, unComment
, Genre
, mkGenre
, getGenre
, unGenre
, Year
, mkYear
, getYear
, unYear
, TrackNumber
, mkTrackNumber
, getTrackNumber
, unTrackNumber
, Duration
, mkDuration
, getDuration
, unDuration
, BitRate
, mkBitRate
, getBitRate
, unBitRate
, SampleRate
, mkSampleRate
, getSampleRate
, unSampleRate
, Channels
, mkChannels
, getChannels
, unChannels
, FileType (..)
, ID3v2Encoding (..)
, HTagLibException (..)
Expand Down
28 changes: 15 additions & 13 deletions Sound/HTagLib/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,13 @@ where

import Control.Exception (throw, bracket)
import Control.Monad (when, unless)
import Data.ByteString (packCString, useAsCString)
import Data.Maybe (fromJust)
import Data.Text (Text)
import Data.Text.Encoding (decodeUtf8, encodeUtf8)
import Foreign
import Foreign.C.String
import Foreign.C.Types

import qualified Sound.HTagLib.Type as T

#if !MIN_VERSION_base(4,8,0)
Expand Down Expand Up @@ -250,37 +252,37 @@ getTrackNumber = fmap T.mkTrackNumber . getIntValue c_taglib_tag_track
-- | Set title of track associated with file.

setTitle :: T.Title -> FileId -> IO ()
setTitle v = setStrValue c_taglib_tag_set_title (T.getTitle v)
setTitle v = setStrValue c_taglib_tag_set_title (T.unTitle v)

-- | Set artist of track associated with file.

setArtist :: T.Artist -> FileId -> IO ()
setArtist v = setStrValue c_taglib_tag_set_artist (T.getArtist v)
setArtist v = setStrValue c_taglib_tag_set_artist (T.unArtist v)

-- | Set album of track associated with file.

setAlbum :: T.Album -> FileId -> IO ()
setAlbum v = setStrValue c_taglib_tag_set_album (T.getAlbum v)
setAlbum v = setStrValue c_taglib_tag_set_album (T.unAlbum v)

-- | Set comment of track associated with file.

setComment :: T.Comment -> FileId -> IO ()
setComment v = setStrValue c_taglib_tag_set_comment (T.getComment v)
setComment v = setStrValue c_taglib_tag_set_comment (T.unComment v)

-- | Set genre of track associated with file.

setGenre :: T.Genre -> FileId -> IO ()
setGenre v = setStrValue c_taglib_tag_set_genre (T.getGenre v)
setGenre v = setStrValue c_taglib_tag_set_genre (T.unGenre v)

-- | Set year of track associated with file.

setYear :: Maybe T.Year -> FileId -> IO ()
setYear v = setIntValue c_taglib_tag_set_year (T.getYear <$> v)
setYear v = setIntValue c_taglib_tag_set_year (T.unYear <$> v)

-- | Set track number of track associated with file.

setTrackNumber :: Maybe T.TrackNumber -> FileId -> IO ()
setTrackNumber v = setIntValue c_taglib_tag_set_track (T.getTrackNumber <$> v)
setTrackNumber v = setIntValue c_taglib_tag_set_track (T.unTrackNumber <$> v)

-- Audio properties API

Expand Down Expand Up @@ -320,13 +322,13 @@ id3v2SetEncoding = c_taglib_id3v2_set_default_text_encoding . enumToCInt
getStrValue
:: (Ptr TagLibTag -> IO CString) -- ^ How to get string from the resource
-> FileId -- ^ File ID
-> IO String -- ^ String result
-> IO Text -- ^ String result
getStrValue getStr (FileId ptr) = do
tag <- c_taglib_file_tag ptr
cstr <- getStr tag
result <- peekCString cstr
result <- packCString cstr
free cstr
return result
return (decodeUtf8 result)

getIntValue :: Integral a
=> (Ptr TagLibTag -> IO a) -- ^ How to get value from the resource
Expand All @@ -339,12 +341,12 @@ getIntValue getInt (FileId ptr) = do

setStrValue
:: (Ptr TagLibTag -> CString -> IO ()) -- ^ Setting routine
-> String -- ^ New string value
-> Text -- ^ New string value
-> FileId -- ^ File ID
-> IO ()
setStrValue setStr str (FileId ptr) = do
tag <- c_taglib_file_tag ptr
withCString str $ \cstr ->
useAsCString (encodeUtf8 str) $ \cstr ->
setStr tag cstr

setIntValue :: Integral a
Expand Down
104 changes: 48 additions & 56 deletions Sound/HTagLib/Type.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,131 +10,128 @@
-- Definitions of types used to represent various tags and audio properties.

{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE OverloadedStrings #-}

module Sound.HTagLib.Type
( Title
, mkTitle
, getTitle
, unTitle
, Artist
, mkArtist
, getArtist
, unArtist
, Album
, mkAlbum
, getAlbum
, unAlbum
, Comment
, mkComment
, getComment
, unComment
, Genre
, mkGenre
, getGenre
, unGenre
, Year
, mkYear
, getYear
, unYear
, TrackNumber
, mkTrackNumber
, getTrackNumber
, unTrackNumber
, Duration
, mkDuration
, getDuration
, unDuration
, BitRate
, mkBitRate
, getBitRate
, unBitRate
, SampleRate
, mkSampleRate
, getSampleRate
, unSampleRate
, Channels
, mkChannels
, getChannels
, unChannels
, FileType (..)
, ID3v2Encoding (..)
, HTagLibException (..) )
where

import Control.Exception (Exception)
import Data.String
import Data.Text (Text)
import Data.Typeable (Typeable)
import qualified Data.Text as T

-- | Title tag.

newtype Title = Title
{ -- | Convert 'Title' to 'String'.
getTitle :: String }
deriving (Show, Eq, Ord)
{ unTitle :: Text -- ^ Convert 'Title' to 'Text'.
} deriving (Show, Eq, Ord)

instance IsString Title where
fromString = mkTitle
fromString = mkTitle . fromString

-- | Construction of 'Title' type, null bytes are converted to spaces.

mkTitle :: String -> Title
mkTitle :: Text -> Title
mkTitle = Title . avoidNulls

-- | Artist tag.

newtype Artist = Artist
{ -- | Convert 'Artist' to 'String'.
getArtist :: String }
deriving (Show, Eq, Ord)
{ unArtist :: Text -- ^ Convert 'Artist' to 'Text'.
} deriving (Show, Eq, Ord)

instance IsString Artist where
fromString = mkArtist
fromString = mkArtist . fromString

-- | Construction of 'Artist' type, null bytes are converted to spaces.

mkArtist :: String -> Artist
mkArtist :: Text -> Artist
mkArtist = Artist . avoidNulls

-- | Album tag.

newtype Album = Album
{ -- | Convert 'Album' to 'String'.
getAlbum :: String }
deriving (Show, Eq, Ord)
{ unAlbum :: Text -- ^ Convert 'Album' to 'Text'.
} deriving (Show, Eq, Ord)

instance IsString Album where
fromString = mkAlbum
fromString = mkAlbum . fromString

-- | Construction of 'Album' type, null bytes are converted to spaces.

mkAlbum :: String -> Album
mkAlbum :: Text -> Album
mkAlbum = Album . avoidNulls

-- | Comment tag.

newtype Comment = Comment
{ -- | Convert 'Comment' to 'String'.
getComment :: String }
deriving (Show, Eq, Ord)
{ unComment :: Text -- ^ Convert 'Comment' to 'Text'.
} deriving (Show, Eq, Ord)

instance IsString Comment where
fromString = mkComment
fromString = mkComment . fromString

-- | Construction of 'Comment' type, null bytes are converted to spaces.

mkComment :: String -> Comment
mkComment :: Text -> Comment
mkComment = Comment . avoidNulls

-- | Genre tag.

newtype Genre = Genre
{ -- | Convert 'Genre' to 'String'.
getGenre :: String }
deriving (Show, Eq, Ord)
{ unGenre :: Text -- ^ Convert 'Genre' to 'Text'.
} deriving (Show, Eq, Ord)

instance IsString Genre where
fromString = mkGenre
fromString = mkGenre . fromString

-- | Construction of 'Genre' type, null bytes are converted to spaces.

mkGenre :: String -> Genre
mkGenre :: Text -> Genre
mkGenre = Genre . avoidNulls

-- | Year tag.

newtype Year = Year
{ -- | Convert 'Year' to 'Int'.
getYear :: Int }
deriving (Show, Eq, Ord)
{ unYear :: Int -- ^ Convert 'Year' to 'Int'.
} deriving (Show, Eq, Ord)

-- | Construction of 'Year' type, non-positive values result in 'Nothing'.

Expand All @@ -144,9 +141,8 @@ mkYear = fmap Year . atLeast 1
-- | Track number tag.

newtype TrackNumber = TrackNumber
{ -- | Convert 'TrackNumber' to 'Int'.
getTrackNumber :: Int }
deriving (Show, Eq, Ord)
{ unTrackNumber :: Int -- ^ Convert 'TrackNumber' to 'Int'.
} deriving (Show, Eq, Ord)

-- | Construction of 'TrackNumber' type, non-positive values result in
-- 'Nothing'.
Expand All @@ -157,9 +153,8 @@ mkTrackNumber = fmap TrackNumber . atLeast 1
-- | Duration in seconds.

newtype Duration = Duration
{ -- | Convert 'Duration' to 'Int'.
getDuration :: Int }
deriving (Show, Eq, Ord)
{ unDuration :: Int -- ^ Convert 'Duration' to 'Int'.
} deriving (Show, Eq, Ord)

-- | Construction of 'Duration' values, negative values result in 'Nothing'.

Expand All @@ -169,9 +164,8 @@ mkDuration = fmap Duration . atLeast 0
-- | Bit rate in kb/s.

newtype BitRate = BitRate
{ -- | Convert 'BitRate' to 'Int'.
getBitRate :: Int }
deriving (Show, Eq, Ord)
{ unBitRate :: Int -- ^ Convert 'BitRate' to 'Int'.
} deriving (Show, Eq, Ord)

-- | Construction of 'BitRate' values, negative values result in
-- 'Nothing'.
Expand All @@ -182,9 +176,8 @@ mkBitRate = fmap BitRate . atLeast 0
-- | Sample rate in Hz.

newtype SampleRate = SampleRate
{ -- | Convert 'SampleRate' to 'Int'.
getSampleRate :: Int }
deriving (Show, Eq, Ord)
{ unSampleRate :: Int -- ^ Convert 'SampleRate' to 'Int'.
} deriving (Show, Eq, Ord)

-- | Construction of 'SampleRate' values, non-positive values result in
-- 'Nothing'.
Expand All @@ -195,9 +188,8 @@ mkSampleRate = fmap SampleRate . atLeast 1
-- | Number of channels in the audio stream.

newtype Channels = Channels
{ -- | Convert 'Channels' to 'Int'.
getChannels :: Int }
deriving (Show, Eq, Ord)
{ unChannels :: Int -- ^ Convert 'Channels' to 'Int'.
} deriving (Show, Eq, Ord)

-- | Construction of 'Channels' values, non-positive values result in
-- 'Nothing'.
Expand All @@ -207,8 +199,8 @@ mkChannels = fmap Channels . atLeast 1

-- | Replace null bytes with spaces.

avoidNulls :: String -> String
avoidNulls = let f x = if x == '\0' then ' ' else x in fmap f
avoidNulls :: Text -> Text
avoidNulls = T.replace "\0" " "

-- | @atLeast a b@ returns @Just b@ is @b@ is greater or equal to @a@,
-- otherwise result is @Nothing@.
Expand Down

0 comments on commit ce53d35

Please sign in to comment.