This is the code I came across using SDL-1.2:
module PlaySound (withSound, playSound) where import Control.Monad import System.IO import System.Directory import Data.Foldable import Control.Exception import qualified Data.ByteString.Lazy as B import Foreign.ForeignPtr import Graphics.UI.SDL as SDL import Graphics.UI.SDL.Mixer as Mix withSound :: IO a -> IO a withSound = bracket_ init cleanup where init = do SDL.init [SDL.InitAudio] getError >>= traverse_ putStrLn ok <- Mix.tryOpenAudio Mix.defaultFrequency Mix.AudioS16LSB 2 4096 unless ok $ putStrLn "Failed to open SDL audio device" cleanup = do Mix.closeAudio SDL.quit playSound :: B.ByteString -> IO () playSound content = do dir <- getTemporaryDirectory (tmp, h) <- openTempFile dir "sdl-input" B.hPutStr h content hClose h mus <- Mix.loadMUS tmp Mix.playMusic mus 1 wait -- This would double-free the Music, as it is also freed via a -- finalizer --Mix.freeMusic mus finalizeForeignPtr mus removeFile tmp wait :: IO () wait = do SDL.delay 50 stillPlaying <- Mix.playingMusic when stillPlaying wait
The program at the end works fine, but
- Compiling SDL bindings on Windows is complicated. I followed this good explanation of how to do this.
- SDL bindings for SDL-1.2 seem unsupported or even not compiled with GHC-7.8 or later . At first I didnโt notice, because my distribution (Debian) fixes such problems, but this means that my users can no longer easily
cabal install dependencies. - there are bindings for SDL-2, but not for SDL_mixer, and I need it (I think).
So, I happily read the best answers.
source share