+ 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