libmpd 0.7.1 → 0.7.2
raw patch · 12 files changed
+126/−120 lines, 12 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- NEWS +4/−0
- Network/MPD.hs +3/−1
- Network/MPD/Commands.hs +1/−1
- Network/MPD/Commands/Arg.hs +1/−1
- Network/MPD/Commands/Parse.hs +1/−1
- Network/MPD/Commands/Util.hs +1/−1
- Network/MPD/Core.hs +9/−9
- Network/MPD/Util.hs +102/−0
- Network/MPD/Utils.hs +0/−102
- libmpd.cabal +2/−2
- tests/Displayable.hs +1/−1
- tests/Properties.hs +1/−1
NEWS view
@@ -1,3 +1,7 @@+* v0.7.2, 2012-02-13+ - Release connections. Reported by Kanisterschleife on GitHub.+ - Some minor internal changes (sol)+ * v0.7.1, 2012-02-07 - Compatible with GHC 7.4.1
Network/MPD.hs view
@@ -20,9 +20,11 @@ module Network.MPD.Commands, ) where +import Prelude hiding (catch)+import Control.Exception import Network.MPD.Commands import Network.MPD.Core-import Network.MPD.Utils+import Network.MPD.Util import Control.Monad (liftM) import System.Environment (getEnv)
Network/MPD/Commands.hs view
@@ -58,7 +58,7 @@ import Network.MPD.Commands.Types import Network.MPD.Commands.Util import Network.MPD.Core-import Network.MPD.Utils+import Network.MPD.Util import Control.Monad (liftM) import Control.Monad.Error (throwError)
Network/MPD/Commands/Arg.hs view
@@ -10,7 +10,7 @@ module Network.MPD.Commands.Arg (Args(..), MPDArg(..), (<++>), (<$>)) where -import Network.MPD.Utils (showBool)+import Network.MPD.Util (showBool) -- | Arguments for getResponse are accumulated as strings in values of -- this type after being converted from whatever type (an instance of
Network/MPD/Commands/Parse.hs view
@@ -16,7 +16,7 @@ import Control.Monad.Error import Data.Maybe (fromMaybe) -import Network.MPD.Utils+import Network.MPD.Util import Network.MPD.Core (MonadMPD, MPDError(Unexpected)) -- | Builds a 'Count' instance from an assoc. list.
Network/MPD/Commands/Util.hs view
@@ -11,7 +11,7 @@ import Network.MPD.Commands.Parse import Network.MPD.Commands.Types import Network.MPD.Core-import Network.MPD.Utils+import Network.MPD.Util import Control.Monad.Error import Data.List (intersperse)
Network/MPD/Core.hs view
@@ -20,12 +20,12 @@ getResponse, kill, ) where -import Network.MPD.Utils+import Network.MPD.Util import Network.MPD.Core.Class import Network.MPD.Core.Error import Data.Char (isDigit)-import Control.Applicative (Applicative(..), (<$>))+import Control.Applicative (Applicative(..), (<$>), (<*)) import Control.Monad (ap, unless) import Control.Monad.Error (ErrorT(..), MonadError(..)) import Control.Monad.Reader (ReaderT(..), ask)@@ -74,10 +74,10 @@ open = mpdOpen close = mpdClose send = mpdSend- getHandle = MPD $ get >>= return . stHandle- getPassword = MPD $ get >>= return . stPassword+ getHandle = MPD $ stHandle <$> get+ getPassword = MPD $ stPassword <$> get setPassword pw = MPD $ modify (\st -> st { stPassword = pw })- getVersion = MPD $ get >>= return . stVersion+ getVersion = MPD $ stVersion <$> get -- | Inner state for MPD data MPDState =@@ -92,9 +92,9 @@ -- | The most configurable API for running an MPD action. withMPDEx :: Host -> Port -> Password -> MPD a -> IO (Response a) withMPDEx host port pw x = withSocketsDo $- runReaderT (evalStateT (runErrorT . runMPD $ open >> x) initState)+ runReaderT (evalStateT (runErrorT . runMPD $ open >> (x <* close)) initState) (host, port)- where initState = MPDState Nothing pw (0, 0, 0)+ where initState = MPDState Nothing pw (0, 0, 0) mpdOpen :: MPD () mpdOpen = MPD $ do@@ -113,7 +113,7 @@ checkConn = do [msg] <- lines <$> send ""- if isPrefixOf "OK MPD" msg+ if "OK MPD" `isPrefixOf` msg then MPD $ checkVersion $ parseVersion msg else return False @@ -203,7 +203,7 @@ parseResponse :: (MonadError MPDError m) => String -> m [String] parseResponse s | null xs = throwError $ NoMPD- | isPrefixOf "ACK" (head xs) = throwError $ parseAck s+ | "ACK" `isPrefixOf` head xs = throwError $ parseAck s | otherwise = return $ Prelude.takeWhile ("OK" /=) xs where xs = lines s
+ Network/MPD/Util.hs view
@@ -0,0 +1,102 @@+-- | Module : Network.MPD.Util+-- Copyright : (c) Ben Sinclair 2005-2009, Joachim Fasting 2010+-- License : LGPL (see LICENSE)+-- Maintainer : Joachim Fasting <joachim.fasting@gmail.com>+-- Stability : alpha+--+-- Utilities.++module Network.MPD.Util (+ parseDate, parseIso8601, formatIso8601, parseNum, parseFrac,+ parseBool, showBool, breakChar, parseTriple,+ toAssoc, toAssocList, splitGroups+ ) where++import Data.Char (isDigit)+import Data.Maybe (fromMaybe)+import Data.Time.Format (ParseTime, parseTime, FormatTime, formatTime)+import System.Locale (defaultTimeLocale)++-- Break a string by character, removing the separator.+breakChar :: Char -> String -> (String, String)+breakChar c s = let (x, y) = break (== c) s in (x, drop 1 y)++-- XXX: need a more robust date parser.+-- Parse a date value.+-- > parseDate "2008" = Just 2008+-- > parseDate "2008-03-01" = Just 2008+parseDate :: String -> Maybe Int+parseDate = parseNum . takeWhile isDigit++-- Parse date in iso 8601 format+parseIso8601 :: (ParseTime t) => String -> Maybe t+parseIso8601 = parseTime defaultTimeLocale iso8601Format++formatIso8601 :: FormatTime t => t -> String+formatIso8601 = formatTime defaultTimeLocale iso8601Format++iso8601Format :: String+iso8601Format = "%FT%TZ"++-- Parse a positive or negative integer value, returning 'Nothing' on failure.+parseNum :: (Read a, Integral a) => String -> Maybe a+parseNum s = do+ [(x, "")] <- return (reads s)+ return x++-- Parse C style floating point value, returning 'Nothing' on failure.+parseFrac :: (Fractional a, Read a) => String -> Maybe a+parseFrac s =+ case s of+ "nan" -> return $ read "NaN"+ "inf" -> return $ read "Infinity"+ "-inf" -> return $ read "-Infinity"+ _ -> do [(x, "")] <- return $ reads s+ return x++-- Inverts 'parseBool'.+showBool :: Bool -> String+showBool x = if x then "1" else "0"++-- Parse a boolean response value.+parseBool :: String -> Maybe Bool+parseBool s = case take 1 s of+ "1" -> Just True+ "0" -> Just False+ _ -> Nothing++-- Break a string into triple.+parseTriple :: Char -> (String -> Maybe a) -> String -> Maybe (a, a, a)+parseTriple c f s = let (u, u') = breakChar c s+ (v, w) = breakChar c u' in+ case (f u, f v, f w) of+ (Just a, Just b, Just c') -> Just (a, b, c')+ _ -> Nothing++-- Break a string into an key-value pair, separating at the first ':'.+toAssoc :: String -> (String, String)+toAssoc x = (k, dropWhile (== ' ') $ drop 1 v)+ where+ (k,v) = break (== ':') x++toAssocList :: [String] -> [(String, String)]+toAssocList = map toAssoc++-- Takes an assoc. list with recurring keys and groups each cycle of+-- keys with their values together. There can be several keys that+-- begin cycles, being listed as the first tuple component in the+-- first parameter. When a cycle finishes all of its pairs are passed+-- to the key's associated function (the second tuple component) and+-- the result appended to the resulting list.+--+-- > splitGroups [(1,id),(5,id)]+-- > [(1,'a'),(2,'b'),(5,'c'),(6,'d'),(1,'z'),(2,'y'),(3,'x')] ==+-- > [[(1,'a'),(2,'b')],[(5,'c'),(6,'d')],[(1,'z'),(2,'y'),(3,'x')]]+splitGroups :: Eq a => [(a,[(a,b)] -> c)] -> [(a, b)] -> [c]+splitGroups [] _ = []+splitGroups _ [] = []+splitGroups wrappers (x@(k,_):xs) =+ fromMaybe (splitGroups wrappers xs) $ do+ f <- k `lookup` wrappers+ let (us,vs) = break (\(k',_) -> k' `elem` map fst wrappers) xs+ return $ f (x:us) : splitGroups wrappers vs
− Network/MPD/Utils.hs
@@ -1,102 +0,0 @@--- | Module : Network.MPD.Utils--- Copyright : (c) Ben Sinclair 2005-2009, Joachim Fasting 2010--- License : LGPL (see LICENSE)--- Maintainer : Joachim Fasting <joachim.fasting@gmail.com>--- Stability : alpha------ Utilities.--module Network.MPD.Utils (- parseDate, parseIso8601, formatIso8601, parseNum, parseFrac,- parseBool, showBool, breakChar, parseTriple,- toAssoc, toAssocList, splitGroups- ) where--import Data.Char (isDigit)-import Data.Maybe (fromMaybe)-import Data.Time.Format (ParseTime, parseTime, FormatTime, formatTime)-import System.Locale (defaultTimeLocale)---- Break a string by character, removing the separator.-breakChar :: Char -> String -> (String, String)-breakChar c s = let (x, y) = break (== c) s in (x, drop 1 y)---- XXX: need a more robust date parser.--- Parse a date value.--- > parseDate "2008" = Just 2008--- > parseDate "2008-03-01" = Just 2008-parseDate :: String -> Maybe Int-parseDate = parseNum . takeWhile isDigit---- Parse date in iso 8601 format-parseIso8601 :: (ParseTime t) => String -> Maybe t-parseIso8601 = parseTime defaultTimeLocale iso8601Format--formatIso8601 :: FormatTime t => t -> String-formatIso8601 = formatTime defaultTimeLocale iso8601Format--iso8601Format :: String-iso8601Format = "%FT%TZ"---- Parse a positive or negative integer value, returning 'Nothing' on failure.-parseNum :: (Read a, Integral a) => String -> Maybe a-parseNum s = do- [(x, "")] <- return (reads s)- return x---- Parse C style floating point value, returning 'Nothing' on failure.-parseFrac :: (Fractional a, Read a) => String -> Maybe a-parseFrac s =- case s of- "nan" -> return $ read "NaN"- "inf" -> return $ read "Infinity"- "-inf" -> return $ read "-Infinity"- _ -> do [(x, "")] <- return $ reads s- return x---- Inverts 'parseBool'.-showBool :: Bool -> String-showBool x = if x then "1" else "0"---- Parse a boolean response value.-parseBool :: String -> Maybe Bool-parseBool s = case take 1 s of- "1" -> Just True- "0" -> Just False- _ -> Nothing---- Break a string into triple.-parseTriple :: Char -> (String -> Maybe a) -> String -> Maybe (a, a, a)-parseTriple c f s = let (u, u') = breakChar c s- (v, w) = breakChar c u' in- case (f u, f v, f w) of- (Just a, Just b, Just c') -> Just (a, b, c')- _ -> Nothing---- Break a string into an key-value pair, separating at the first ':'.-toAssoc :: String -> (String, String)-toAssoc x = (k, dropWhile (== ' ') $ drop 1 v)- where- (k,v) = break (== ':') x--toAssocList :: [String] -> [(String, String)]-toAssocList = map toAssoc---- Takes an assoc. list with recurring keys and groups each cycle of--- keys with their values together. There can be several keys that--- begin cycles, being listed as the first tuple component in the--- first parameter. When a cycle finishes all of its pairs are passed--- to the key's associated function (the second tuple component) and--- the result appended to the resulting list.------ > splitGroups [(1,id),(5,id)]--- > [(1,'a'),(2,'b'),(5,'c'),(6,'d'),(1,'z'),(2,'y'),(3,'x')] ==--- > [[(1,'a'),(2,'b')],[(5,'c'),(6,'d')],[(1,'z'),(2,'y'),(3,'x')]]-splitGroups :: Eq a => [(a,[(a,b)] -> c)] -> [(a, b)] -> [c]-splitGroups [] _ = []-splitGroups _ [] = []-splitGroups wrappers (x@(k,_):xs) =- fromMaybe (splitGroups wrappers xs) $ do- f <- k `lookup` wrappers- let (us,vs) = break (\(k',_) -> k' `elem` map fst wrappers) xs- return $ f (x:us) : splitGroups wrappers vs
libmpd.cabal view
@@ -1,5 +1,5 @@ Name: libmpd-Version: 0.7.1+Version: 0.7.2 License: LGPL License-file: LICENSE Copyright: Ben Sinclair 2005-2009, Joachim Fasting 2012@@ -52,7 +52,7 @@ Network.MPD.Commands.Query, Network.MPD.Commands.Types, Network.MPD.Commands.Util,- Network.MPD.Utils+ Network.MPD.Util ghc-prof-options: -auto-all -prof
tests/Displayable.hs view
@@ -4,7 +4,7 @@ import qualified Data.Map as M import Network.MPD.Commands.Types-import Network.MPD.Utils+import Network.MPD.Util -- | A uniform interface for types that -- can be turned into raw responses
tests/Properties.hs view
@@ -6,7 +6,7 @@ import Network.MPD.Commands.Parse import Network.MPD.Commands.Types-import Network.MPD.Utils+import Network.MPD.Util import Control.Monad import Data.List