5 , MultiParamTypeClasses
9 -- | EsounD player streams.
10 module Sound.EsounD.Player
15 import Bindings.EsounD
16 import Control.Monad.IO.Class
17 import Control.Monad.Trans.Region
18 import Control.Monad.Trans.Region.OnExit
19 import Control.Monad.Unicode
21 import Data.StorableVector.Lazy as L
23 import Prelude.Unicode
24 import Sound.EsounD.Streams
25 import Sound.EsounD.Internals
27 import System.IO.SaferFileHandles.Unsafe
30 -- ^ An opaque ESD handle for playing a stream.
31 data Player fr ch (r ∷ ★ → ★)
34 -- THINKME: We really want to use RegionalFileHandle but we
35 -- can't, because safer-file-handles currently provides no ways
36 -- to wrap ordinary handles into safer handles.
38 , plCloseH ∷ !(FinalizerHandle r)
41 instance Dup (Player fr ch) where
42 dup pl = do ch' ← dup (plCloseH pl)
43 return pl { plCloseH = ch' }
45 instance Frame fr ⇒ Writable (Player fr Mono) (L.Vector fr) where
47 = liftIO $ sanitizeIOError $ L.hPut (plHandle pl) v
49 instance Frame fr ⇒ Writable (Player fr Stereo) (L.Vector fr, L.Vector fr) where
51 = liftIO $ sanitizeIOError $ L.hPut (plHandle pl) (interleave l r)
53 -- | Open an ESD handle for playing a stream.
54 openPlayer ∷ ∀fr ch s pr.
59 ⇒ Int -- ^ sample rate for the stream.
60 → Maybe HostName -- ^ host to connect to.
61 → Maybe String -- ^ name used to identify this stream to
63 → RegionT s pr (Player fr ch (RegionT s pr))
64 openPlayer rate host name
65 = do h ← liftIO openSocket
66 ch ← onExit $ sanitizeIOError $ closeSocket h
74 fmt = frameFmt ((⊥) ∷ fr) .|.
75 channelFmt ((⊥) ∷ ch) .|.
79 openSocket :: IO Handle
80 openSocket = withCStrOrNull host $ \hostPtr →
81 withCStrOrNull name $ \namePtr →
96 ⧺ ") returned an error"