-- | -- Module : MTP.Handle -- Copyright : (c) Joachim Fasting 2010 -- License : LGPL -- -- Maintainer : Joachim Fasting -- Stability : unstable -- Portability : not portable -- -- Bindings to libmtp. Device handle. module MTP.Handle (MTPHandle, isClosed, open, close, withMTPHandle) where import MTP.Foreign (MTPDevice) import Control.Concurrent.MVar import Control.Monad import Foreign data HandleState = Closed | Open deriving Eq data MTPHandle_ = MTPHandle_ { haDev :: !(ForeignPtr MTPDevice) , haState :: HandleState } -- | A handle to an MTP device connection. data MTPHandle = MTPHandle (MVar MTPHandle_) -- Open handle, given a device pointer. open :: Ptr MTPDevice -> IO MTPHandle open dptr = do -- XXX: newForeignPtr finalizerFree devptr causes a double free -- error when the finalizer is run. dev <- newForeignPtr_ dptr h_ <- newMVar $ MTPHandle_ dev Open return (MTPHandle h_) -- Close handle. close :: MTPHandle -> IO () close (MTPHandle hv) = modifyMVar_ hv (\x -> return x { haState = Closed }) -- Test whether the handle is closed. isClosed :: MTPHandle -> IO Bool isClosed (MTPHandle hv) = withMVar hv (\x -> return $ haState x == Closed) -- A helper that lifts operations on MTPDevice into MTPHandle. -- Throws error if the handle is unusable. withMTPHandle :: MTPHandle -> (Ptr MTPDevice -> IO a) -> IO a withMTPHandle h@(MTPHandle hv) f = do closed <- isClosed h when closed (fail "MTPHandle is closed") withMVar hv (\x -> withForeignPtr (haDev x) f)