{-# LANGUAGE CPP #-}
module Network.MPD (
MonadMPD, MPD, MPDError(..), ACKType(..), Response,
Host, Port, Password,
withMPD, withMPD_, withMPDEx,
module Network.MPD.Commands,
#ifdef TEST
getConnectionSettings, getEnvDefault
#endif
) where
import Prelude
import qualified Control.Exception as E
import Network.MPD.Commands
import Network.MPD.Core
import System.Environment (getEnv)
import System.IO.Error (isDoesNotExistError)
import Data.Maybe (listToMaybe)
withMPD :: MPD a -> IO (Response a)
withMPD :: forall a. MPD a -> IO (Response a)
withMPD = forall a. Maybe String -> Maybe String -> MPD a -> IO (Response a)
withMPD_ forall a. Maybe a
Nothing forall a. Maybe a
Nothing
withMPD_ :: Maybe String
-> Maybe String
-> MPD a -> IO (Response a)
withMPD_ :: forall a. Maybe String -> Maybe String -> MPD a -> IO (Response a)
withMPD_ Maybe String
mHost Maybe String
mPort MPD a
action = do
Either String (String, Port, String)
settings <- Maybe String
-> Maybe String -> IO (Either String (String, Port, String))
getConnectionSettings Maybe String
mHost Maybe String
mPort
case Either String (String, Port, String)
settings of
Right (String
host, Port
port, String
pw) -> forall a. String -> Port -> String -> MPD a -> IO (Response a)
withMPDEx String
host Port
port String
pw MPD a
action
Left String
err -> (forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. a -> Either a b
Left forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> MPDError
Custom) String
err
getConnectionSettings :: Maybe String -> Maybe String -> IO (Either String (Host, Port, Password))
getConnectionSettings :: Maybe String
-> Maybe String -> IO (Either String (String, Port, String))
getConnectionSettings Maybe String
mHost Maybe String
mPort = do
(String
host, String
pw) <- String -> (String, String)
parseHost forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap`
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> String -> IO String
getEnvDefault String
"MPD_HOST" String
"localhost") forall (m :: * -> *) a. Monad m => a -> m a
return Maybe String
mHost
String
port <- forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> String -> IO String
getEnvDefault String
"MPD_PORT" String
"6600") forall (m :: * -> *) a. Monad m => a -> m a
return Maybe String
mPort
case forall a. Read a => String -> Maybe a
maybeRead String
port of
Just Port
p -> (forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. b -> Either a b
Right) (String
host, Port
p, String
pw)
Maybe Port
Nothing -> (forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. a -> Either a b
Left) (forall a. Show a => a -> String
show String
port forall a. [a] -> [a] -> [a]
++ String
" is not a valid port!")
where
parseHost :: String -> (String, String)
parseHost String
s = case Char -> String -> (String, String)
breakChar Char
'@' String
s of
(String
host, String
"") -> (String
host, String
"")
(String
pw, String
host) -> (String
host, String
pw)
getEnvDefault :: String -> String -> IO String
getEnvDefault :: String -> String -> IO String
getEnvDefault String
x String
dflt =
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
E.catch (String -> IO String
getEnv String
x) (\IOError
e -> if IOError -> Bool
isDoesNotExistError IOError
e
then forall (m :: * -> *) a. Monad m => a -> m a
return String
dflt else forall a. IOError -> IO a
ioError IOError
e)
breakChar :: Char -> String -> (String, String)
breakChar :: Char -> String -> (String, String)
breakChar Char
c String
s = let (String
x, String
y) = forall a. (a -> Bool) -> [a] -> ([a], [a])
break (forall a. Eq a => a -> a -> Bool
== Char
c) String
s in (String
x, forall a. Int -> [a] -> [a]
drop Int
1 String
y)
maybeRead :: Read a => String -> Maybe a
maybeRead :: forall a. Read a => String -> Maybe a
maybeRead = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (a, b) -> a
fst forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> Maybe a
listToMaybe forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Read a => ReadS a
reads