module Sound.Player.AudioPlay ( play, pause, resume, stop ) where import System.Process (ProcessHandle, StdStream(CreatePipe), CreateProcess(std_err), createProcess, proc, terminateProcess) import System.Posix (ProcessID) import System.Posix.Signals (signalProcess) import System.Process.Internals (ProcessHandle__(OpenHandle, ClosedHandle), withProcessHandle) -- | Creates an @afplay@ process to play file at @path@. -- -- Note: it suppresses process' @stderr@. play :: FilePath -> IO ProcessHandle play path = do (_, _, _, processHandle) <- -- TODO: update System.Process version to use NoStream createProcess (proc "afplay" [path]) { std_err = CreatePipe } return processHandle -- | Sends a @17@ signal to @ph@'s process. If @ph@ is the handle of a running -- @afplay@ process it will pause playback. pause :: ProcessHandle -> IO () pause ph = maybe (return ()) (signalProcess 17) =<< getPid ph -- | Sends a @19@ signal to @ph@'s process. If @ph@ is the handle of a running -- @afplay@ process it will resume playback. resume :: ProcessHandle -> IO () resume ph = maybe (return ()) (signalProcess 19) =<< getPid ph -- | Terminates the selected process. If @ph@ is the handle of a running -- @afplay@ process it will stop playback. stop :: ProcessHandle -> IO () stop = terminateProcess -- See https://mail.haskell.org/pipermail/haskell-cafe/2012-October/104028.html getPid :: ProcessHandle -> IO (Maybe ProcessID) getPid ph = withProcessHandle ph (return . go) where go (OpenHandle pid) = Just pid go (ClosedHandle _) = Nothing