X-Git-Url: http://git.cielonegro.org/gitweb.cgi?p=EsounD.git;a=blobdiff_plain;f=Sound%2FEsounD%2FPlayer.hs;fp=Sound%2FEsounD%2FPlayer.hs;h=0d2b209c32b20fb9ba2ae72a2e518cac83ec8bf7;hp=0000000000000000000000000000000000000000;hb=d2396e7b6183bb033861069aaeb52be53a90bfdf;hpb=951367c7c17ddbc417a998fe9a19d6434f63f386 diff --git a/Sound/EsounD/Player.hs b/Sound/EsounD/Player.hs new file mode 100644 index 0000000..0d2b209 --- /dev/null +++ b/Sound/EsounD/Player.hs @@ -0,0 +1,71 @@ +-- | EsounD player streams. +module Sound.EsounD.Player + ( Player + , openPlayer + ) + where + +import Bindings.EsounD +import Control.Monad.IO.Class +import Control.Monad.Trans.Region +import Control.Monad.Trans.Region.OnExit +import Control.Monad.Unicode +import Data.Bits +import Foreign.C.String +import Network +import Prelude.Unicode +import Sound.EsounD.Internals +import System.IO +import System.IO.SaferFileHandles.Unsafe + + +-- ^ An opaque ESD handle for playing a stream. +data Player fr ch (r ∷ * → *) + = Player { + plRate ∷ !Int + -- THINKME: We really want to use RegionalFileHandle but we + -- can't, because safer-file-handles currently provides no ways + -- to wrap ordinary handles. + , plHandle ∷ !Handle + , plCloseH ∷ !(CloseHandle r) + } + +instance Dup (Player fr ch) where + dup pl = do ch' ← dup (plCloseH pl) + return pl { plCloseH = ch' } + +-- | Open an ESD handle for playing a stream. +openPlayer ∷ ∀fr ch s pr. + ( Frame fr + , Channels ch + , MonadIO pr + ) + ⇒ Int -- ^ sample rate for the stream. + → HostName -- ^ host to connect to. + → Maybe String -- ^ name used to identify this stream to + -- ESD (if any). + → RegionT s pr (Player fr ch (RegionT s pr)) +openPlayer rate host name + = do h ← liftIO openSocket + ch ← onExit $ sanitizeIOError $ closeSocket h + return Player { + plRate = rate + , plHandle = h + , plCloseH = ch + } + where + fmt :: C'esd_format_t + fmt = frameFmt ((⊥) ∷ fr) .&. + channelFmt ((⊥) ∷ ch) .&. + c'ESD_STREAM .&. + c'ESD_PLAY + + openSocket :: IO Handle + openSocket = withCString host $ \hostPtr → + withCStrOrNull name $ \namePtr → + c'esd_play_stream + fmt + (fromIntegral rate) + hostPtr + namePtr + ≫= wrapSocket "esd_play_stream() returned an error"