X-Git-Url: http://git.cielonegro.org/gitweb.cgi?a=blobdiff_plain;f=Sound%2FEsounD.hs;h=e9276a0d10219249ccc86f140fcc72e45e4799c5;hb=d2396e7b6183bb033861069aaeb52be53a90bfdf;hp=16e85a5ddd4a61f9fba39eb1a81781ca70ce2197;hpb=d0f6d543044bf4e29825087afefe6062a95ca926;p=EsounD.git diff --git a/Sound/EsounD.hs b/Sound/EsounD.hs index 16e85a5..e9276a0 100644 --- a/Sound/EsounD.hs +++ b/Sound/EsounD.hs @@ -1,114 +1,9 @@ -- | Type-safe bindings to EsounD with monadic regions. module Sound.EsounD - ( Frame - - , Channels - , Mono - , Stereo - - , Player - , openPlayer + ( module Sound.EsounD.Types + , module Sound.EsounD.Player ) where -import Bindings.EsounD -import Control.Monad.IO.Class -import Control.Monad.Trans.Region as R -import Control.Monad.Trans.Region.OnExit -import Control.Monad.Unicode -import Data.Bits -import Data.Int -import Foreign.C.String -import Foreign.C.Types -import Foreign.Ptr -import Network -import Prelude.Unicode -import System.IO -import System.IO.SaferFileHandles.Unsafe -import System.Posix.IO -import System.Posix.Types - -class Frame fr where - frameFmt ∷ fr → C'esd_format_t - -instance Frame Int8 where - frameFmt _ = c'ESD_BITS8 - -instance Frame Int16 where - frameFmt _ = c'ESD_BITS16 - -class Channels ch where - channelFmt ∷ ch → C'esd_format_t - -data Mono -instance Channels Mono where - channelFmt _ = c'ESD_MONO - -data Stereo -instance Channels Stereo where - channelFmt _ = c'ESD_STEREO - - --- ^ An 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' ← R.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" - -wrapSocket :: String -> CInt → IO Handle -wrapSocket e (-1) = fail e -wrapSocket _ fd = fdToHandle (Fd fd) - -closeSocket :: Handle → IO () -closeSocket h = do (Fd fd) ← handleToFd h - _ ← c'esd_close (fromIntegral fd) - return () - -withCStrOrNull :: Maybe String → (CString → IO a) → IO a -withCStrOrNull Nothing f = f nullPtr -withCStrOrNull (Just s) f = withCString s f +import Sound.EsounD.Types +import Sound.EsounD.Player