mtp-0.1.1.1: MTP/Handle.hs
-- |
-- Module : MTP.Handle
-- Copyright : (c) Joachim Fasting 2010
-- License : LGPL
--
-- Maintainer : Joachim Fasting <joachim.fasting@gmail.com>
-- 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)