X-Git-Url: http://git.cielonegro.org/gitweb.cgi?a=blobdiff_plain;f=Sound%2FEsounD%2FPlayer.hs;h=b48dfee9a849f15245ecfb3f702ebdd8ca32e5ec;hb=9be39a0e8dc40b5fbd3280a5d06f7a85626e0b33;hp=b60eda08a87213b3bd7f5be2c1ecadd4f8454194;hpb=332de27c05d195598689979c035bd136a47f4394;p=EsounD.git diff --git a/Sound/EsounD/Player.hs b/Sound/EsounD/Player.hs index b60eda0..b48dfee 100644 --- a/Sound/EsounD/Player.hs +++ b/Sound/EsounD/Player.hs @@ -1,26 +1,36 @@ +{-# LANGUAGE + FlexibleContexts + , FlexibleInstances + , KindSignatures + , MultiParamTypeClasses + , UnicodeSyntax + , ScopedTypeVariables + #-} -- | EsounD player streams. module Sound.EsounD.Player ( Player , openPlayer ) where - import Bindings.EsounD +import Control.Exception.Peel import Control.Monad.IO.Class +import Control.Monad.IO.Peel import Control.Monad.Trans.Region import Control.Monad.Trans.Region.OnExit import Control.Monad.Unicode import Data.Bits -import Foreign.C.String +import Data.StorableVector.Lazy as L import Network import Prelude.Unicode +import Sound.EsounD.Streams 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 ∷ * → *) +data Player fr ch (r ∷ ★ → ★) = Player { plRate ∷ !Int -- THINKME: We really want to use RegionalFileHandle but we @@ -34,19 +44,28 @@ instance Dup (Player fr ch) where dup pl = do ch' ← dup (plCloseH pl) return pl { plCloseH = ch' } +instance Frame fr ⇒ Writable (Player fr Mono) (L.Vector fr) where + write pl v + = liftIO $ sanitizeIOError $ L.hPut (plHandle pl) v + +instance Frame fr ⇒ Writable (Player fr Stereo) (L.Vector fr, L.Vector fr) where + write pl (l, r) + = liftIO $ sanitizeIOError $ L.hPut (plHandle pl) (interleave l r) + -- | Open an ESD handle for playing a stream. openPlayer ∷ ∀fr ch s pr. ( Frame fr , Channels ch - , MonadIO pr + , MonadPeelIO pr ) - ⇒ Int -- ^ sample rate for the stream. - → HostName -- ^ host to connect to. - → Maybe String -- ^ name used to identify this stream to - -- ESD (if any). + ⇒ Int -- ^ sample rate for the stream. + → Maybe 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 + = block $ + do h ← liftIO openSocket ch ← onExit $ sanitizeIOError $ closeSocket h return Player { plRate = rate @@ -55,17 +74,27 @@ openPlayer rate host name } where fmt :: C'esd_format_t - fmt = frameFmt ((⊥) ∷ fr) .&. - channelFmt ((⊥) ∷ ch) .&. - c'ESD_STREAM .&. + fmt = frameFmt ((⊥) ∷ fr) .|. + channelFmt ((⊥) ∷ ch) .|. + c'ESD_STREAM .|. c'ESD_PLAY openSocket :: IO Handle - openSocket = withCString host $ \hostPtr → + openSocket = withCStrOrNull host $ \hostPtr → withCStrOrNull name $ \namePtr → c'esd_play_stream fmt (fromIntegral rate) hostPtr namePtr - ≫= wrapSocket "esd_play_stream() returned an error" + ≫= wrapSocket + ( "esd_play_stream(" + ⧺ show fmt + ⧺ ", " + ⧺ show rate + ⧺ ", " + ⧺ show host + ⧺ ", " + ⧺ show name + ⧺ ") returned an error" + )