1 -- | Type-safe bindings to EsounD with monadic regions.
14 import Bindings.EsounD
15 import Control.Monad.IO.Class
16 import Control.Monad.Trans.Region
17 import Control.Monad.Trans.Region.OnExit
18 import Control.Monad.Unicode
21 import Foreign.C.String
23 import Prelude.Unicode
24 import Sound.EsounD.Internals
26 import System.IO.SaferFileHandles.Unsafe
29 frameFmt ∷ fr → C'esd_format_t
31 instance Frame Int8 where
32 frameFmt _ = c'ESD_BITS8
34 instance Frame Int16 where
35 frameFmt _ = c'ESD_BITS16
37 class Channels ch where
38 channelFmt ∷ ch → C'esd_format_t
41 instance Channels Mono where
42 channelFmt _ = c'ESD_MONO
45 instance Channels Stereo where
46 channelFmt _ = c'ESD_STEREO
49 -- ^ An ESD handle for playing a stream.
50 data Player fr ch (r ∷ * → *)
53 -- THINKME: We really want to use RegionalFileHandle but we
54 -- can't, because safer-file-handles currently provides no ways
55 -- to wrap ordinary handles.
57 , plCloseH ∷ !(CloseHandle r)
60 instance Dup (Player fr ch) where
61 dup pl = do ch' ← dup (plCloseH pl)
62 return pl { plCloseH = ch' }
64 -- | Open an ESD handle for playing a stream.
65 openPlayer ∷ ∀fr ch s pr.
70 ⇒ Int -- ^ sample rate for the stream.
71 → HostName -- ^ host to connect to.
72 → Maybe String -- ^ name used to identify this stream to
74 → RegionT s pr (Player fr ch (RegionT s pr))
75 openPlayer rate host name
76 = do h ← liftIO openSocket
77 ch ← onExit $ sanitizeIOError $ closeSocket h
85 fmt = frameFmt ((⊥) ∷ fr) .&.
86 channelFmt ((⊥) ∷ ch) .&.
90 openSocket :: IO Handle
91 openSocket = withCString host $ \hostPtr →
92 withCStrOrNull name $ \namePtr →
98 ≫= wrapSocket "esd_play_stream() returned an error"