5 , MultiParamTypeClasses
10 -- | EsounD player streams.
11 module Sound.EsounD.Player
16 import Bindings.EsounD
17 import Control.Monad.IO.Class
18 import Control.Monad.Trans.Region
19 import Control.Monad.Trans.Region.OnExit
20 import Control.Monad.Unicode
22 import Data.StorableVector.Lazy as L
23 import Foreign.C.String
25 import Prelude.Unicode
26 import Sound.EsounD.Streams
27 import Sound.EsounD.Internals
29 import System.IO.SaferFileHandles.Unsafe
32 -- ^ An opaque ESD handle for playing a stream.
33 data Player fr ch (r ∷ ★ → ★)
36 -- THINKME: We really want to use RegionalFileHandle but we
37 -- can't, because safer-file-handles currently provides no ways
38 -- to wrap ordinary handles into safer handles.
40 , plCloseH ∷ !(FinalizerHandle r)
43 instance Dup (Player fr ch) where
44 dup pl = do ch' ← dup (plCloseH pl)
45 return pl { plCloseH = ch' }
47 instance (Mux L.Vector fr ch, dvec ~ DemuxedVec L.Vector fr ch) ⇒ Writable (Player fr ch) dvec where
49 = liftIO $ sanitizeIOError $ L.hPut (plHandle pl) (mux dvec)
51 -- | Open an ESD handle for playing a stream.
52 openPlayer ∷ ∀fr ch s pr.
57 ⇒ Int -- ^ sample rate for the stream.
58 → HostName -- ^ host to connect to.
59 → Maybe String -- ^ name used to identify this stream to
61 → RegionT s pr (Player fr ch (RegionT s pr))
62 openPlayer rate host name
63 = do h ← liftIO openSocket
64 ch ← onExit $ sanitizeIOError $ closeSocket h
72 fmt = frameFmt ((⊥) ∷ fr) .&.
73 channelFmt ((⊥) ∷ ch) .&.
77 openSocket :: IO Handle
78 openSocket = withCString host $ \hostPtr →
79 withCStrOrNull name $ \namePtr →
85 ≫= wrapSocket "esd_play_stream() returned an error"