Abstract out sockets from the MPD monad.
[libmpd_haskell.git] / Network / MPD.hs
blob6e8184b039ea67f413209e72a6695f85c3d9bbe0
1 {-
2 libmpd for Haskell, an MPD client library.
3 Copyright (C) 2005-2007 Ben Sinclair <bsinclai@turing.une.edu.au>
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 -- | Module : Network.MPD
21 -- Copyright : (c) Ben Sinclair 2005-2007
22 -- License : LGPL
23 -- Maintainer : bsinclai@turing.une.edu.au
24 -- Stability : alpha
25 -- Portability : Haskell 98
27 -- MPD client library.
29 module Network.MPD (
30 -- * Basic data types
31 AbstractMPD, MPD, Conn(..), SocketConn, MPDError(..), ACKType(..), Response,
32 -- * Connections
33 withMPD, withMPDEx,
34 module Network.MPD.Commands,
35 ) where
37 import Network.MPD.Commands
38 import Network.MPD.Prim
39 import Network.MPD.SocketConn
41 import Control.Monad (liftM)
42 import Data.Maybe (listToMaybe)
43 import Data.IORef (newIORef, atomicModifyIORef)
44 import System.Environment (getEnv)
45 import System.IO
46 import System.IO.Error (isDoesNotExistError, ioError)
48 -- | Run an MPD action using localhost:6600 as the default host:port,
49 -- or whatever is found in the environment variables MPD_HOST and
50 -- MPD_PORT. If MPD_HOST is of the form \"password\@host\" then the
51 -- password will be supplied as well.
52 withMPD :: MPD a -> IO (Response a)
53 withMPD m = do
54 port <- liftM read (getEnvDefault "MPD_PORT" "6600")
55 (pw,host) <- liftM (break (== '@')) (getEnvDefault "MPD_HOST" "localhost")
56 let (host',pw') = if null host then (pw,host) else (drop 1 host,pw)
57 pwGen <- mkPasswordGen [pw']
58 withMPDEx host' port pwGen m
59 where
60 getEnvDefault x dflt =
61 catch (getEnv x) (\e -> if isDoesNotExistError e
62 then return dflt else ioError e)
64 -- | Create an action that produces passwords for a connection. You
65 -- can pass these to 'withMPDEx' and it will use them to get passwords
66 -- to send to the server until one works or it runs out of them.
68 -- > do gen <- mkPasswordGen ["password1", "password2"]
69 -- > withMPDEx "localhost" 6600 gen (update [])
70 mkPasswordGen :: [String] -> IO (IO (Maybe String))
71 mkPasswordGen = liftM f . newIORef
72 where f = flip atomicModifyIORef $ \xs -> (drop 1 xs, listToMaybe xs)