{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE LambdaCase #-}
module Codec.Audio.FLAC.Metadata.Internal.Level2Interface
(
withChain,
chainStatus,
chainRead,
chainWrite,
chainSortPadding,
withIterator,
iteratorGetBlockType,
iteratorGetBlock,
iteratorSetBlock,
iteratorDeleteBlock,
iteratorInsertBlockAfter,
)
where
import Codec.Audio.FLAC.Metadata.Internal.Types
import Codec.Audio.FLAC.Util
import Control.Monad.Catch
import Control.Monad.IO.Class (MonadIO (..))
import Foreign.C.String
import Foreign.C.Types
withChain :: (MetaChain -> IO a) -> IO a
withChain :: (MetaChain -> IO a) -> IO a
withChain f :: MetaChain -> IO a
f = IO (Maybe MetaChain)
-> (Maybe MetaChain -> IO ()) -> (Maybe MetaChain -> IO a) -> IO a
forall (m :: * -> *) a c b.
MonadMask m =>
m a -> (a -> m c) -> (a -> m b) -> m b
bracket IO (Maybe MetaChain)
chainNew ((MetaChain -> IO ()) -> Maybe MetaChain -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ MetaChain -> IO ()
chainDelete) ((Maybe MetaChain -> IO a) -> IO a)
-> (Maybe MetaChain -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ \case
Nothing ->
MetaException -> IO a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM
(MetaChainStatus -> MetaException
MetaGeneralProblem MetaChainStatus
MetaChainStatusMemoryAllocationError)
Just x :: MetaChain
x -> MetaChain -> IO a
f MetaChain
x
chainNew :: IO (Maybe MetaChain)
chainNew :: IO (Maybe MetaChain)
chainNew = MetaChain -> Maybe MetaChain
forall a p. Coercible a (Ptr p) => a -> Maybe a
maybePtr (MetaChain -> Maybe MetaChain)
-> IO MetaChain -> IO (Maybe MetaChain)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO MetaChain
c_chain_new
foreign import ccall unsafe "FLAC__metadata_chain_new"
c_chain_new :: IO MetaChain
chainDelete :: MetaChain -> IO ()
chainDelete :: MetaChain -> IO ()
chainDelete = MetaChain -> IO ()
c_chain_delete
foreign import ccall unsafe "FLAC__metadata_chain_delete"
c_chain_delete :: MetaChain -> IO ()
chainStatus :: MetaChain -> IO MetaChainStatus
chainStatus :: MetaChain -> IO MetaChainStatus
chainStatus = (CUInt -> MetaChainStatus) -> IO CUInt -> IO MetaChainStatus
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap CUInt -> MetaChainStatus
forall a b. (Integral a, Enum b) => a -> b
toEnum' (IO CUInt -> IO MetaChainStatus)
-> (MetaChain -> IO CUInt) -> MetaChain -> IO MetaChainStatus
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MetaChain -> IO CUInt
c_chain_status
foreign import ccall unsafe "FLAC__metadata_chain_status"
c_chain_status :: MetaChain -> IO CUInt
chainRead :: MetaChain -> FilePath -> IO Bool
chainRead :: MetaChain -> FilePath -> IO Bool
chainRead chain :: MetaChain
chain path :: FilePath
path = FilePath -> (CString -> IO Bool) -> IO Bool
forall a. FilePath -> (CString -> IO a) -> IO a
withCString FilePath
path (MetaChain -> CString -> IO Bool
c_chain_read MetaChain
chain)
foreign import ccall unsafe "FLAC__metadata_chain_read"
c_chain_read :: MetaChain -> CString -> IO Bool
chainWrite ::
MetaChain ->
Bool ->
Bool ->
IO Bool
chainWrite :: MetaChain -> Bool -> Bool -> IO Bool
chainWrite chain :: MetaChain
chain usePadding :: Bool
usePadding preserveStats :: Bool
preserveStats =
MetaChain -> CInt -> CInt -> IO Bool
c_chain_write MetaChain
chain (Bool -> CInt
forall a b. (Integral a, Enum b) => b -> a
fromEnum' Bool
usePadding) (Bool -> CInt
forall a b. (Integral a, Enum b) => b -> a
fromEnum' Bool
preserveStats)
foreign import ccall unsafe "FLAC__metadata_chain_write"
c_chain_write :: MetaChain -> CInt -> CInt -> IO Bool
chainSortPadding :: MetaChain -> IO ()
chainSortPadding :: MetaChain -> IO ()
chainSortPadding = MetaChain -> IO ()
c_chain_sort_padding
foreign import ccall unsafe "FLAC__metadata_chain_sort_padding"
c_chain_sort_padding :: MetaChain -> IO ()
withIterator ::
(MonadMask m, MonadIO m) =>
MetaChain ->
(MetaIterator -> m (Maybe a)) ->
m [a]
withIterator :: MetaChain -> (MetaIterator -> m (Maybe a)) -> m [a]
withIterator chain :: MetaChain
chain f :: MetaIterator -> m (Maybe a)
f = m (Maybe MetaIterator)
-> (Maybe MetaIterator -> m ())
-> (Maybe MetaIterator -> m [a])
-> m [a]
forall (m :: * -> *) a c b.
MonadMask m =>
m a -> (a -> m c) -> (a -> m b) -> m b
bracket m (Maybe MetaIterator)
acquire Maybe MetaIterator -> m ()
release Maybe MetaIterator -> m [a]
action
where
acquire :: m (Maybe MetaIterator)
acquire = IO (Maybe MetaIterator) -> m (Maybe MetaIterator)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO (Maybe MetaIterator)
iteratorNew
release :: Maybe MetaIterator -> m ()
release = (MetaIterator -> m ()) -> Maybe MetaIterator -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> (MetaIterator -> IO ()) -> MetaIterator -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MetaIterator -> IO ()
iteratorDelete)
action :: Maybe MetaIterator -> m [a]
action mi :: Maybe MetaIterator
mi =
case Maybe MetaIterator
mi of
Nothing ->
MetaException -> m [a]
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM
(MetaChainStatus -> MetaException
MetaGeneralProblem MetaChainStatus
MetaChainStatusMemoryAllocationError)
Just i :: MetaIterator
i -> do
IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (MetaIterator -> MetaChain -> IO ()
iteratorInit MetaIterator
i MetaChain
chain)
let go :: Bool -> m [a]
go thisNext :: Bool
thisNext =
if Bool
thisNext
then do
Maybe a
res <- MetaIterator -> m (Maybe a)
f MetaIterator
i
let next :: m [a]
next = IO Bool -> m Bool
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (MetaIterator -> IO Bool
iteratorNext MetaIterator
i) m Bool -> (Bool -> m [a]) -> m [a]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Bool -> m [a]
go
case Maybe a
res of
Nothing -> m [a]
next
Just x :: a
x -> (a
x a -> [a] -> [a]
forall a. a -> [a] -> [a]
:) ([a] -> [a]) -> m [a] -> m [a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m [a]
next
else [a] -> m [a]
forall (m :: * -> *) a. Monad m => a -> m a
return []
Bool -> m [a]
go Bool
True
iteratorNew :: IO (Maybe MetaIterator)
iteratorNew :: IO (Maybe MetaIterator)
iteratorNew = MetaIterator -> Maybe MetaIterator
forall a p. Coercible a (Ptr p) => a -> Maybe a
maybePtr (MetaIterator -> Maybe MetaIterator)
-> IO MetaIterator -> IO (Maybe MetaIterator)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO MetaIterator
c_iterator_new
foreign import ccall unsafe "FLAC__metadata_iterator_new"
c_iterator_new :: IO MetaIterator
iteratorDelete :: MetaIterator -> IO ()
iteratorDelete :: MetaIterator -> IO ()
iteratorDelete = MetaIterator -> IO ()
c_iterator_delete
foreign import ccall unsafe "FLAC__metadata_iterator_delete"
c_iterator_delete :: MetaIterator -> IO ()
iteratorInit ::
MetaIterator ->
MetaChain ->
IO ()
iteratorInit :: MetaIterator -> MetaChain -> IO ()
iteratorInit = MetaIterator -> MetaChain -> IO ()
c_iterator_init
foreign import ccall unsafe "FLAC__metadata_iterator_init"
c_iterator_init :: MetaIterator -> MetaChain -> IO ()
iteratorNext :: MetaIterator -> IO Bool
iteratorNext :: MetaIterator -> IO Bool
iteratorNext = MetaIterator -> IO Bool
c_iterator_next
foreign import ccall unsafe "FLAC__metadata_iterator_next"
c_iterator_next :: MetaIterator -> IO Bool
iteratorGetBlockType :: MetaIterator -> IO MetadataType
iteratorGetBlockType :: MetaIterator -> IO MetadataType
iteratorGetBlockType = (CUInt -> MetadataType) -> IO CUInt -> IO MetadataType
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap CUInt -> MetadataType
forall a b. (Integral a, Enum b) => a -> b
toEnum' (IO CUInt -> IO MetadataType)
-> (MetaIterator -> IO CUInt) -> MetaIterator -> IO MetadataType
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MetaIterator -> IO CUInt
c_iterator_get_block_type
foreign import ccall unsafe "FLAC__metadata_iterator_get_block_type"
c_iterator_get_block_type :: MetaIterator -> IO CUInt
iteratorGetBlock :: MetaIterator -> IO Metadata
iteratorGetBlock :: MetaIterator -> IO Metadata
iteratorGetBlock = MetaIterator -> IO Metadata
c_iterator_get_block
foreign import ccall unsafe "FLAC__metadata_iterator_get_block"
c_iterator_get_block :: MetaIterator -> IO Metadata
iteratorSetBlock :: MetaIterator -> Metadata -> IO Bool
iteratorSetBlock :: MetaIterator -> Metadata -> IO Bool
iteratorSetBlock = MetaIterator -> Metadata -> IO Bool
c_iterator_set_block
foreign import ccall unsafe "FLAC__metadata_iterator_set_block"
c_iterator_set_block :: MetaIterator -> Metadata -> IO Bool
iteratorDeleteBlock ::
MetaIterator ->
IO Bool
iteratorDeleteBlock :: MetaIterator -> IO Bool
iteratorDeleteBlock block :: MetaIterator
block = MetaIterator -> Bool -> IO Bool
c_iterator_delete_block MetaIterator
block Bool
False
foreign import ccall unsafe "FLAC__metadata_iterator_delete_block"
c_iterator_delete_block :: MetaIterator -> Bool -> IO Bool
iteratorInsertBlockAfter :: MetaIterator -> Metadata -> IO Bool
iteratorInsertBlockAfter :: MetaIterator -> Metadata -> IO Bool
iteratorInsertBlockAfter = MetaIterator -> Metadata -> IO Bool
c_iterator_insert_block_after
foreign import ccall unsafe "FLAC__metadata_iterator_insert_block_after"
c_iterator_insert_block_after :: MetaIterator -> Metadata -> IO Bool