packages feed

tttool-1.4: src/PlaySound.hs

{-# LANGUAGE NondecreasingIndentation #-}

module PlaySound (playSound) where

import System.Process
import System.Exit
import Control.Monad
import Control.Exception
import System.IO.Error
import System.IO
import System.Directory
import System.FilePath
import qualified Data.ByteString.Lazy as B
import System.Environment.Executable


players :: FilePath -> FilePath -> [(FilePath, [String])]
players myDir fn =
    [ ("sox",                              ["-q", fn, "-d"])
    , (myDir </> "contrib" </> "playmus",  [fn])
    ]

playSound :: B.ByteString -> IO ()
playSound content = do
    dir <- getTemporaryDirectory
    (tmp, h) <- openTempFile dir "tttool-audio.tmp"
    B.hPutStr h content
    hClose h

    (myDir,_) <- splitExecutablePath

    tryPrograms (players myDir tmp) $ do
        putStrLn "Could not play audio file."
        putStrLn "Do you have \"sox\" installed?"

    removeFile tmp

tryPrograms [] e = e
tryPrograms ((c,args):es) e = do
    -- Missing programs cause exceptions on Windows, but error 127 on Linux.
    -- Try to handle both here.
    r <- tryJust (guard . isDoesNotExistError) $ do
        ph <- runProcess  c args Nothing Nothing Nothing Nothing Nothing
        ret <- waitForProcess ph
        if ret == ExitSuccess then return True
        else if ret == ExitFailure 127 then return False
        else do
            putStrLn $ "Failed to execute \"" ++ c ++ "\" (" ++ show ret ++ ")"
            exitFailure
    case r of
       Right True -> return ()
       _ -> tryPrograms es e