diff --git a/haskell-player.cabal b/haskell-player.cabal
--- a/haskell-player.cabal
+++ b/haskell-player.cabal
@@ -1,5 +1,5 @@
 name:                haskell-player
-version:             0.1.3.2
+version:             0.1.3.3
 synopsis:            A terminal music player based on afplay
 description:         A minimal graphical interface on top of afplay and afinfo
                      built using brick.
@@ -32,6 +32,7 @@
                      , process >= 1.2.3 && < 1.3
                      , text >= 1.2.2.1 && < 1.3
                      , transformers >= 0.4.2 && < 0.5
+                     , unix >= 2.7.1 && < 2.8
                      , vector >= 0.11 && < 0.12
                      , vty >= 5.5 && < 5.6
                      , xml-conduit >= 1.3.5 && < 1.4
diff --git a/src/Sound/Player.hs b/src/Sound/Player.hs
--- a/src/Sound/Player.hs
+++ b/src/Sound/Player.hs
@@ -1,8 +1,3 @@
--- TODO: playlist
--- TODO: search
--- TODO: go to playing song
--- TODO: help dialog
-
 {-# LANGUAGE OverloadedStrings #-}
 
 module Sound.Player (
@@ -19,6 +14,7 @@
 import Brick.Util (on)
 import Control.Concurrent (Chan, ThreadId, forkIO, killThread, newChan,
   writeChan, threadDelay)
+import Control.Exception (SomeException, catch)
 import Control.Monad.IO.Class (MonadIO, liftIO)
 import Data.Default (def)
 import Data.List (isPrefixOf, stripPrefix)
@@ -168,10 +164,14 @@
   where
     songs = L.listElements l
     song = songs Vec.! pos
+    failSongInfo :: SomeException -> IO SongInfo
+    failSongInfo _ = return $ SongInfo (-1)
     playSong :: Song -> IO (ProcessHandle, Double, ThreadId)
     playSong (Song _ path _) = do
       musicDir <- defaultMusicDirectory
-      (SongInfo duration) <- fetchSongInfo $ musicDir </> path
+      (SongInfo duration) <- catch
+        (fetchSongInfo $ musicDir </> path)
+        failSongInfo
       proc <- AP.play $ musicDir </> path
       tId <- playheadAdvanceLoop chan
       return (proc, duration, tId)
@@ -179,7 +179,7 @@
 
 -- Stops current song and play selected song.
 stopAndPlaySelected :: (MonadIO m) => PlayerApp -> m PlayerApp
-stopAndPlaySelected app = play mPos =<< stop app
+stopAndPlaySelected app = stop app >>= play mPos
   where
     mPos = songsList app ^. L.listSelectedL
 
@@ -188,7 +188,7 @@
 stopAndPlayDelta :: (MonadIO m) => Int -> PlayerApp -> m PlayerApp
 stopAndPlayDelta _ app@(PlayerApp _ _ _ Nothing) = return app
 stopAndPlayDelta delta app@(PlayerApp l _ _ (Just (Playback playPos _ _ _ _))) =
-    play (Just pos) =<< stop app
+    stop app >>= play (Just pos)
   where
     pos = (playPos + delta) `mod` Vec.length (L.listElements l)
 
@@ -243,7 +243,7 @@
     stripMusicDirectory musicDir = fromMaybe musicDir . stripPrefix musicDir
 
 
--- | The default music directory is /$HOME\/Music/.
+-- | The default music directory is @$HOME/Music@.
 defaultMusicDirectory :: IO FilePath
 defaultMusicDirectory = (</> "Music/") <$> getEnv "HOME"
 
diff --git a/src/Sound/Player/AudioInfo.hs b/src/Sound/Player/AudioInfo.hs
--- a/src/Sound/Player/AudioInfo.hs
+++ b/src/Sound/Player/AudioInfo.hs
@@ -5,11 +5,12 @@
   fetchSongInfo
 ) where
 
-import Control.Exception (SomeException)
+import Control.Exception (SomeException(SomeException), Exception)
 import Data.ByteString.Lazy (ByteString, hGetContents)
 import qualified Data.Text as T
 import System.Process (StdStream(CreatePipe), CreateProcess(std_out),
   createProcess, proc)
+import Text.Read (readMaybe)
 import Text.XML (def, parseLBS)
 import Text.XML.Cursor (($//), (&//), fromDocument, content, element)
 
@@ -19,6 +20,14 @@
   } deriving (Show)
 
 
+newtype SongInfoParsingException = SongInfoParsingException String
+
+instance Exception SongInfoParsingException
+
+instance Show SongInfoParsingException where
+  showsPrec _ (SongInfoParsingException err) = showString err
+
+
 fetchSongInfo :: FilePath -> IO SongInfo
 fetchSongInfo path = do
   songInfoXML <- fetchRawSongInfo path
@@ -39,8 +48,15 @@
 parseSongInfo :: ByteString -> Either SomeException SongInfo
 parseSongInfo contents = do
     doc <- parseLBS def contents
-    let durations = fromDocument doc $// durationElement &// content
-    return . SongInfo . read . T.unpack . T.concat $ durations
+    maybe
+      (Left . SomeException $ parsingException)
+      (Right . SongInfo)
+      (readFirst $ durations doc)
   where
+    parsingException = SongInfoParsingException "Can't find song duration"
+    durations doc = fromDocument doc $// durationElement &// content
+    readFirst :: [T.Text] -> Maybe Double
+    readFirst (d:_) = readMaybe (T.unpack d)
+    readFirst _ = Nothing
     durationElement =
       element "{http://apple.com/core_audio/audio_info}duration"
diff --git a/src/Sound/Player/AudioPlay.hs b/src/Sound/Player/AudioPlay.hs
--- a/src/Sound/Player/AudioPlay.hs
+++ b/src/Sound/Player/AudioPlay.hs
@@ -5,37 +5,49 @@
   stop
 ) where
 
-import Control.Monad (void)
-import Data.Maybe (fromJust)
-import System.Process (ProcessHandle, createProcess, proc, terminateProcess)
+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),
-  PHANDLE, withProcessHandle)
+  withProcessHandle)
 
 
+-- | Creates an @afplay@ process to play file at @path@.
+--
+-- Note: it suppresses process' @stderr@.
 play :: FilePath -> IO ProcessHandle
 play path = do
-  (_, _, _, processHandle) <- createProcess (proc "afplay" [path])
+  (_, _, _, 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 = do
-  mPid <- getPid ph
-  void $ createProcess (proc "kill" ["-17", show $ fromJust mPid])
+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 = do
-  mPid <- getPid ph
-  void $ createProcess (proc "kill" ["-19", show $ fromJust mPid])
+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 PHANDLE)
+getPid :: ProcessHandle -> IO (Maybe ProcessID)
 getPid ph = withProcessHandle ph (return . go)
   where
     go (OpenHandle pid) = Just pid
