libmpd 0.9.3.0 → 0.10.0.0
raw patch · 18 files changed
+227/−131 lines, 18 filesdep ~hspec
Dependency ranges changed: hspec
Files
- README.md +1/−1
- changelog.md +15/−0
- libmpd.cabal +5/−3
- src/Network/MPD/Applicative/CurrentPlaylist.hs +17/−5
- src/Network/MPD/Applicative/Database.hs +20/−14
- src/Network/MPD/Applicative/PlaybackControl.hs +9/−1
- src/Network/MPD/Applicative/Status.hs +35/−28
- src/Network/MPD/Commands.hs +1/−0
- src/Network/MPD/Commands/CurrentPlaylist.hs +15/−9
- src/Network/MPD/Commands/Database.hs +18/−2
- src/Network/MPD/Commands/Extensions.hs +4/−22
- src/Network/MPD/Commands/Parse.hs +11/−4
- src/Network/MPD/Commands/PlaybackControl.hs +8/−1
- src/Network/MPD/Commands/Query.hs +18/−15
- src/Network/MPD/Commands/Types.hs +35/−0
- src/Network/MPD/Core.hs +1/−1
- src/Network/MPD/Util.hs +9/−1
- tests/CommandSpec.hs +5/−24
README.md view
@@ -5,7 +5,7 @@ ## About libmpd-haskell is a pure [Haskell] client library for [MPD], the-music playing daemon.+music playing daemon. Requires MPD version 0.19 or later. [MPD]: http://www.musicpd.org [Haskell]: http://www.haskell.org
changelog.md view
@@ -1,3 +1,18 @@+* v0.10.0.0 2021-01-25+ - Require MPD version 0.19 or later.+ - Breaking: `list` now takes a `Query` instead of a `Maybe Artist`, and lists the requested tag of songs matching the query.+ Migrate by changing `list $Tag Nothing` to `list $Tag mempty` and `list Album (Just "someone")` to `list Album (Artist =? "someone")`.+ - Breaking: song ranges now expressed with the `Range` datatype rather than `(Position,Position)`, allowing for partial ranges (see documentation).+ Migrate by changing `(x,y)` to `Range x y`.+ - Breaking: add missing `Metadata` constructors: `AlbumSort`, `OriginalDate`, `Conductor`, `Work`, `Grouping`, `Label`, `MUSICBRAINZ_WORKID`.+ - Breaking: add missing `Subsystem` constructors: `PartitionS`, `NeighborS`, `MountS`.+ - Breaking: add missing `ReplayGainMode` constructor: `AutoMode`.+ - Breaking: move `toggle` from `N.M.C.Extensions` to `N.M.(C|A).PlaybackControl`.+ - Fix: `idle` now properly detects the following subsystems: `PartitionS`, `StickerS`, `SubscriptionS`, `MessageS`, `NeighborS`, `MountS`.+ - Remove deprecated functions: `(<&>)` (use `<>` instead), `updateId`, `addList`, `playlistAddList`.+ - Add monadic versions of `searchAdd` and `searchAddPl` commands (previously only had applicative versions)+ - Fix: The server setting "single: oneshot" now sets `stSingle` to `True` rather than erroring out.+ * v0.9.3.0 2021-01-02 - Drop support for GHC < 8.4, require base > 4.11. - Bump `cabal-version` to 2.4.
libmpd.cabal view
@@ -1,6 +1,6 @@ Cabal-Version: 2.4 Name: libmpd-Version: 0.9.3.0+Version: 0.10.0.0 Synopsis: An MPD client library. Description: A client library for MPD, the Music Player Daemon. Category: Network, Sound@@ -20,7 +20,7 @@ Homepage: http://github.com/vimus/libmpd-haskell#readme Bug-reports: http://github.com/vimus/libmpd-haskell/issues -Tested-With: GHC ==8.4.4, GHC==8.6.5, GHC==8.8.4, GHC==8.10.2+Tested-With: GHC ==8.4.4, GHC==8.6.5, GHC==8.8.4, GHC==8.10.3 Build-Type: Simple Extra-Source-Files:@@ -126,4 +126,6 @@ -- Test dependencies , unix , QuickCheck >= 2.10- , hspec >= 1.3+ , hspec >= 2+ build-tool-depends:+ hspec-discover:hspec-discover
src/Network/MPD/Applicative/CurrentPlaylist.hs view
@@ -72,7 +72,9 @@ delete pos = Command emptyResponse ["delete" <@> pos] -- | Delete a range of songs from the playlist.-deleteRange :: (Position, Position) -> Command ()+--+-- @since 0.10.0.0+deleteRange :: Range -> Command () deleteRange range = Command emptyResponse ["delete" <@> range] -- | Delete song by id.@@ -84,7 +86,9 @@ move pos to = Command emptyResponse ["move" <@> pos <++> to] -- | Move a range of songs.-moveRange :: (Position, Position) -> Position -> Command ()+--+-- @since 0.10.0.0+moveRange :: Range -> Position -> Command () moveRange range to = Command emptyResponse ["move" <@> range <++> to] -- | Move song id to position.@@ -109,7 +113,9 @@ -- | Like 'playlistInfo' but can restrict listing to a range -- of songs.-playlistInfoRange :: Maybe (Position, Position) -> Command [Song]+--+-- @since 0.10.0.0+playlistInfoRange :: Maybe Range -> Command [Song] playlistInfoRange = playlist' "playlistinfo" -- | Get song metadata for all items in the current playlist.@@ -140,7 +146,9 @@ | otherwise = Left "" -- | Set the priority of the specified songs.-prio :: Priority -> (Position, Position) -> Command ()+--+-- @since 0.10.0.0+prio :: Priority -> Range -> Command () prio p range = Command emptyResponse ["prio" <@> p <++> range] -- | Set priority by song id.@@ -149,7 +157,9 @@ -- | Shuffle the current playlist. -- Optionally restrict to a range of songs.-shuffle :: Maybe (Position, Position) -> Command ()+--+-- @since 0.10.0.0+shuffle :: Maybe Range -> Command () shuffle mbRange = Command emptyResponse ["shuffle" <@> mbRange] -- | Swap songs by position.@@ -170,6 +180,8 @@ -- | Specify portion of song that shall be played. -- Both ends of the range are optional; omitting both plays everything.+--+-- Since MPD 0.19. rangeId :: Id -> (Maybe Double, Maybe Double) -> Command () rangeId id' (mbStart, mbEnd) = Command emptyResponse ["rangeid " ++ show id' ++ " " ++ arg ] where arg = maybe "" show mbStart ++ ":" ++ maybe "" show mbEnd
src/Network/MPD/Applicative/Database.hs view
@@ -12,7 +12,21 @@ The music database. -} -module Network.MPD.Applicative.Database where+module Network.MPD.Applicative.Database+ ( count+ , find+ , findAdd+ , list+ , listAll+ , listAllInfo+ , lsInfo+ , readComments+ , search+ , searchAdd+ , searchAddPl+ , update+ , rescan+ ) where import qualified Network.MPD.Commands.Arg as Arg import Network.MPD.Commands.Arg hiding (Command)@@ -39,18 +53,14 @@ findAdd :: Query -> Command () findAdd q = Command emptyResponse ["findadd" <@> q] --- | Lists all tags of the specified type.+-- | List all tags of the specified type of songs that that satisfy the query. ----- Note that the optional artist value is only ever used if the--- metadata type is 'Album', and is then taken to mean that the albums--- by that artist be listed.-list :: Metadata -> Maybe Artist -> Command [Value]+-- @since 0.10.0.0+list :: Metadata -> Query -> Command [Value] list m q = Command p c where p = map Value . takeValues <$> getResponse- c = case m of- Album -> ["list Album" <@> q]- _ -> ["list" <@> m]+ c = ["list" <@> m <++> q] -- | List all songs and directories in a database path. listAll :: Path -> Command [Path]@@ -80,7 +90,7 @@ readComments uri = Command p ["readcomments" <@> uri] where p = map decodePair . toAssocList <$> getResponse --- | Like 'find' but with inexact matching.+-- | Like 'find' but with case insensitive matching. search :: Query -> Command [Song] search q = Command p ["search" <@> q] where@@ -88,14 +98,10 @@ p = liftParser takeSongs -- | Like 'search' but adds the results to the current playlist.------ Since MPD 0.17. searchAdd :: Query -> Command () searchAdd q = Command emptyResponse ["searchadd" <@> q] -- | Like 'searchAdd' but adds results to the named playlist.------ Since MPD 0.17. searchAddPl :: PlaylistName -> Query -> Command () searchAddPl pl q = Command emptyResponse ["searchaddpl" <@> pl <++> q]
src/Network/MPD/Applicative/PlaybackControl.hs view
@@ -15,6 +15,7 @@ module Network.MPD.Applicative.PlaybackControl ( next , pause+ , toggle , play , playId , previous@@ -32,9 +33,16 @@ next :: Command () next = Command emptyResponse ["next"] --- | Toggle pause.+-- | Pauses playback on True, resumes on False. pause :: Bool -> Command () pause f = Command emptyResponse ["pause" <@> f]++-- | Toggles playback.+--+-- @since 0.10.0.0+toggle :: Command ()+toggle = Command emptyResponse ["pause"]+ -- | Begin playback (optionally at a specific position). play :: Maybe Position -> Command ()
src/Network/MPD/Applicative/Status.hs view
@@ -54,6 +54,12 @@ "mixer" -> Right MixerS "output" -> Right OutputS "options" -> Right OptionsS+ "partition" -> Right PartitionS+ "sticker" -> Right StickerS+ "subscription" -> Right SubscriptionS+ "message" -> Right MessageS+ "neighbor" -> Right NeighborS+ "mount" -> Right MountS k -> Left ("Unknown subsystem: " ++ UTF8.toString k) f x = Left ("idle: Unexpected " ++ show x) @@ -82,36 +88,37 @@ parseStatus = foldM go def . toAssocList where go a p@(k, v) = case k of- "volume" -> vol $ \x -> a { stVolume = x }- "repeat" -> bool $ \x -> a { stRepeat = x }- "random" -> bool $ \x -> a { stRandom = x }- "single" -> bool $ \x -> a { stSingle = x }- "consume" -> bool $ \x -> a { stConsume = x }- "playlist" -> num $ \x -> a { stPlaylistVersion = x }- "playlistlength" -> num $ \x -> a { stPlaylistLength = x }- "state" -> state $ \x -> a { stState = x }- "song" -> int $ \x -> a { stSongPos = Just x }- "songid" -> int $ \x -> a { stSongID = Just $ Id x }- "nextsong" -> int $ \x -> a { stNextSongPos = Just x }- "nextsongid" -> int $ \x -> a { stNextSongID = Just $ Id x }- "time" -> time $ \x -> a { stTime = Just x }- "elapsed" -> frac $ \x -> a { stTime = fmap ((x,) . snd) (stTime a) }- "duration" -> frac $ \x -> a { stTime = fmap ((,x) . fst) (stTime a) }- "bitrate" -> int $ \x -> a { stBitrate = Just x }- "xfade" -> num $ \x -> a { stXFadeWidth = x }- "mixrampdb" -> frac $ \x -> a { stMixRampdB = x }- "mixrampdelay" -> frac $ \x -> a { stMixRampDelay = x }- "audio" -> audio $ \x -> a { stAudio = x }- "updating_db" -> num $ \x -> a { stUpdatingDb = Just x }- "error" -> Right a { stError = Just (UTF8.toString v) }- "partition" -> Right a { stPartition = UTF8.toString v }- _ -> Right a+ "volume" -> vol $ \x -> a { stVolume = x }+ "repeat" -> bool $ \x -> a { stRepeat = x }+ "random" -> bool $ \x -> a { stRandom = x }+ "single" -> single $ \x -> a { stSingle = x }+ "consume" -> bool $ \x -> a { stConsume = x }+ "playlist" -> num $ \x -> a { stPlaylistVersion = x }+ "playlistlength" -> num $ \x -> a { stPlaylistLength = x }+ "state" -> state $ \x -> a { stState = x }+ "song" -> int $ \x -> a { stSongPos = Just x }+ "songid" -> int $ \x -> a { stSongID = Just $ Id x }+ "nextsong" -> int $ \x -> a { stNextSongPos = Just x }+ "nextsongid" -> int $ \x -> a { stNextSongID = Just $ Id x }+ "time" -> time $ \x -> a { stTime = Just x }+ "elapsed" -> frac $ \x -> a { stTime = fmap ((x,) . snd) (stTime a) }+ "duration" -> frac $ \x -> a { stTime = fmap ((,x) . fst) (stTime a) }+ "bitrate" -> int $ \x -> a { stBitrate = Just x }+ "xfade" -> num $ \x -> a { stXFadeWidth = x }+ "mixrampdb" -> frac $ \x -> a { stMixRampdB = x }+ "mixrampdelay" -> frac $ \x -> a { stMixRampDelay = x }+ "audio" -> audio $ \x -> a { stAudio = x }+ "updating_db" -> num $ \x -> a { stUpdatingDb = Just x }+ "error" -> Right a { stError = Just (UTF8.toString v) }+ "partition" -> Right a { stPartition = UTF8.toString v }+ _ -> Right a where unexpectedPair = Left ("unexpected key-value pair: " ++ show p)- int f = maybe unexpectedPair (Right . f) (parseNum v :: Maybe Int)- num f = maybe unexpectedPair (Right . f) (parseNum v)- bool f = maybe unexpectedPair (Right . f) (parseBool v)- frac f = maybe unexpectedPair (Right . f) (parseFrac v)+ int f = maybe unexpectedPair (Right . f) (parseNum v :: Maybe Int)+ num f = maybe unexpectedPair (Right . f) (parseNum v)+ bool f = maybe unexpectedPair (Right . f) (parseBool v)+ frac f = maybe unexpectedPair (Right . f) (parseFrac v)+ single f = maybe unexpectedPair (Right . f) (parseSingle v) -- This is sometimes "audio: 0:?:0", so we ignore any parse -- errors.
src/Network/MPD/Commands.hs view
@@ -34,6 +34,7 @@ , Song(..) , Priority(..) , Position+ , Range(..) , Volume , Id(..) , sgGetTag
src/Network/MPD/Commands/CurrentPlaylist.hs view
@@ -67,8 +67,8 @@ -- | Remove a range of songs from the current playlist. ----- @since 0.9.2.0-deleteRange :: MonadMPD m => (Position, Position) -> m ()+-- @since 0.10.0.0+deleteRange :: MonadMPD m => Range -> m () deleteRange = A.runCommand . A.deleteRange -- | Remove a song from the current playlist.@@ -81,8 +81,8 @@ -- | Move a range of songs to a given position in the current playlist. ----- @since 0.9.2.0-moveRange :: MonadMPD m => (Position, Position) -> Position -> m ()+-- @since 0.10.0.0+moveRange :: MonadMPD m => Range -> Position -> m () moveRange range = A.runCommand . A.moveRange range -- | Move a song from (songid) to (playlist index) in the playlist. If to is@@ -111,7 +111,9 @@ playlistInfo = A.runCommand . A.playlistInfo -- | Like 'playlistInfo' but can restrict to a range of songs.-playlistInfoRange :: MonadMPD m => Maybe (Position, Position) -> m [Song]+--+-- @since 0.10.0.0+playlistInfoRange :: MonadMPD m => Maybe Range -> m [Song] playlistInfoRange = A.runCommand . A.playlistInfoRange -- | Displays a list of songs in the playlist.@@ -134,16 +136,20 @@ plChangesPosId = A.runCommand . A.plChangesPosId -- | Set the priority of the specified songs.-prio :: MonadMPD m => Priority -> (Position, Position) -> m ()+--+-- @since 0.10.0.0+prio :: MonadMPD m => Priority -> Range -> m () prio p = A.runCommand . A.prio p -- | Set priority by song id. prioId :: MonadMPD m => Priority -> Id -> m () prioId p = A.runCommand . A.prioId p --- | Shuffle the playlist.-shuffle :: MonadMPD m => Maybe (Position, Position) -- ^ Optional range (start, end)- -> m ()+-- | Shuffle the current playlist.+-- Optionally restrict to a range of songs.+--+-- @since 0.10.0.0+shuffle :: MonadMPD m => Maybe Range -> m () shuffle = A.runCommand . A.shuffle -- | Swap the positions of two songs.
src/Network/MPD/Commands/Database.hs view
@@ -22,6 +22,8 @@ , lsInfo , readComments , search+ , searchAdd+ , searchAddPl , update , rescan ) where@@ -44,10 +46,12 @@ findAdd :: MonadMPD m => Query -> m () findAdd = A.runCommand . A.findAdd --- | List all tags of the specified type.+-- | List all tags of the specified type of songs that that satisfy the query.+--+-- @since 0.10.0.0 list :: MonadMPD m => Metadata -- ^ Metadata to list- -> Maybe Artist -> m [Value]+ -> Query -> m [Value] list m = A.runCommand . A.list m -- | List the songs (without metadata) in a database directory recursively.@@ -69,6 +73,18 @@ -- | Search the database using case insensitive matching. search :: MonadMPD m => Query -> m [Song] search = A.runCommand . A.search++-- | Like 'search' but adds the results to the current playlist.+--+-- @since 0.10.0.0+searchAdd :: MonadMPD m => Query -> m ()+searchAdd = A.runCommand . A.searchAdd++-- | Like 'searchAdd' but adds results to the named playlist.+--+-- @since 0.10.0.0+searchAddPl :: MonadMPD m => PlaylistName -> Query -> m ()+searchAddPl pl = A.runCommand . A.searchAddPl pl -- | Update the server's database. --
src/Network/MPD/Commands/Extensions.hs view
@@ -24,16 +24,6 @@ import Data.Traversable (for) import Data.Foldable (for_) --- | This is exactly the same as `update`.-updateId :: MonadMPD m => Maybe Path -> m Integer-updateId = update-{-# DEPRECATED updateId "use `update` instead" #-}---- | Toggles play\/pause. Plays if stopped.-toggle :: MonadMPD m => m ()-toggle = status >>= \st -> case stState st of Playing -> pause True- _ -> play Nothing- -- | Add a list of songs\/folders to a playlist. -- Should be more efficient than running 'add' many times. addMany :: MonadMPD m => PlaylistName -> [Path] -> m ()@@ -53,16 +43,6 @@ fs <- listAll x A.runCommand $ for fs (`A.addId` Nothing) --- | Like 'add' but returns a list of the files added.-addList :: MonadMPD m => Path -> m [Path]-addList x = add x >> listAll x-{-# DEPRECATED addList "will be removed in a future version" #-}---- | Like 'playlistAdd' but returns a list of the files added.-playlistAddList :: MonadMPD m => PlaylistName -> Path -> m [Path]-playlistAddList plname path = playlistAdd plname path >> listAll path-{-# DEPRECATED playlistAddList "will be removed in a future version" #-}- {- -- | Returns all songs and directories that match the given partial -- path name.@@ -79,12 +59,14 @@ -- | List the artists in the database. listArtists :: MonadMPD m => m [Artist]-listArtists = list Artist Nothing+listArtists = list Artist mempty -- | List the albums in the database, optionally matching a given -- artist. listAlbums :: MonadMPD m => Maybe Artist -> m [Album]-listAlbums = list Album+listAlbums ma = list Album (case ma of+ Nothing -> mempty+ Just a -> Artist =? a) -- | List the songs in an album of some artist. listAlbum :: MonadMPD m => Artist -> Album -> m [Song]
src/Network/MPD/Commands/Parse.hs view
@@ -89,25 +89,32 @@ readMeta k -- Custom-made Read instance- readMeta "ArtistSort" = Just ArtistSort readMeta "Artist" = Just Artist+ readMeta "ArtistSort" = Just ArtistSort readMeta "Album" = Just Album+ readMeta "AlbumSort" = Just AlbumSort readMeta "AlbumArtist" = Just AlbumArtist readMeta "AlbumArtistSort" = Just AlbumArtistSort readMeta "Title" = Just Title- readMeta "Genre" = Just Genre+ readMeta "Track" = Just Track readMeta "Name" = Just Name+ readMeta "Genre" = Just Genre+ readMeta "Date" = Just Date+ readMeta "OriginalDate" = Just OriginalDate readMeta "Composer" = Just Composer readMeta "Performer" = Just Performer+ readMeta "Conductor" = Just Conductor+ readMeta "Work" = Just Work+ readMeta "Grouping" = Just Grouping readMeta "Comment" = Just Comment- readMeta "Date" = Just Date- readMeta "Track" = Just Track readMeta "Disc" = Just Disc+ readMeta "Label" = Just Label readMeta "MUSICBRAINZ_ARTISTID" = Just MUSICBRAINZ_ARTISTID readMeta "MUSICBRAINZ_ALBUMID" = Just MUSICBRAINZ_ALBUMID readMeta "MUSICBRAINZ_ALBUMARTISTID" = Just MUSICBRAINZ_ALBUMARTISTID readMeta "MUSICBRAINZ_TRACKID" = Just MUSICBRAINZ_TRACKID readMeta "MUSICBRAINZ_RELEASETRACKID" = Just MUSICBRAINZ_RELEASETRACKID+ readMeta "MUSICBRAINZ_WORKID" = Just MUSICBRAINZ_WORKID readMeta _ = Nothing -- | A helper that runs a parser on a string and, depending on the
src/Network/MPD/Commands/PlaybackControl.hs view
@@ -15,6 +15,7 @@ module Network.MPD.Commands.PlaybackControl ( next , pause+ , toggle , play , playId , previous@@ -33,9 +34,15 @@ next :: MonadMPD m => m () next = A.runCommand A.next --- | Pause playing.+-- | Pauses playback on True, resumes on False. pause :: MonadMPD m => Bool -> m () pause = A.runCommand . A.pause++-- | Toggles play\/pause. Plays if stopped.+--+-- @since 0.10.0.0+toggle :: MonadMPD m => m ()+toggle = A.runCommand A.toggle -- | Begin\/continue playing. play :: MonadMPD m => Maybe Position -> m ()
src/Network/MPD/Commands/Query.hs view
@@ -10,7 +10,7 @@ Query interface. -} -module Network.MPD.Commands.Query (Query, (=?) ,(/=?), (%?), (~?), (/~?), qNot, qModSince, qFile, qBase, (<&>), anything) where+module Network.MPD.Commands.Query (Query, (=?) ,(/=?), (%?), (~?), (/~?), qNot, qModSince, qFile, qBase, anything) where import Network.MPD.Commands.Arg import Network.MPD.Commands.Types@@ -38,6 +38,7 @@ show (Match meta query) = show meta ++ " \"" ++ toString query ++ "\"" showList xs _ = unwords $ fmap show xs +-- A general MPD 0.21 style filter. data Expr = Exact Match | ExactNot Match | Contains Match@@ -102,36 +103,41 @@ m =? s = Query [Match m s] -- | Create a query matching a tag with anything but a value.--- Requires MPD 0.21 or newer. --+-- Since MPD 0.21.+-- -- @since 0.9.3.0 (/=?) :: Metadata -> Value -> Query m /=? s = Filter (ExactNot (Match m s)) -- | Create a query for a tag containing a value.--- Requires MPD 0.21 or newer. --+-- Since MPD 0.21.+-- -- @since 0.9.3.0 (%?) :: Metadata -> Value -> Query m %? s = Filter (Contains (Match m s)) -- | Create a query matching a tag with regexp.--- Requires MPD 0.21 or newer. --+-- Since MPD 0.21.+-- -- @since 0.9.3.0 (~?) :: Metadata -> Value -> Query m ~? s = Filter (Regex (Match m s)) -- | Create a query matching a tag with anything but a regexp.--- Requires MPD 0.21 or newer. --+-- Since MPD 0.21.+-- -- @since 0.9.3.0 (/~?) :: Metadata -> Value -> Query m /~? s = Filter (RegexNot (Match m s)) -- | Negate a Query.--- Requires MPD 0.21 or newer. --+-- Since MPD 0.21.+-- -- @since 0.9.3.0 qNot :: Query -> Query qNot (Query ms) = Filter (ExprNot (toExpr ms))@@ -139,28 +145,25 @@ qNot (Filter ex) = Filter (ExprNot ex) -- | Create a query for songs modified since a date.--- Requires MPD 0.21 or newer. --+-- Since MPD 0.21.+-- -- @since 0.9.3.0 qModSince :: UTCTime -> Query qModSince time = Filter (ModifiedSince time) -- | Create a query for the full song URI relative to the music directory.--- Requires MPD 0.21 or newer. --+-- Since MPD 0.21.+-- -- @since 0.9.3.0 qFile :: Path -> Query qFile file = Filter (File file) -- | Limit the query to the given directory, relative to the music directory.--- Requires MPD 0.21 or newer. --+-- Since MPD 0.21.+-- -- @since 0.9.3.0 qBase :: Path -> Query qBase dir = Filter (Base dir)---- | Combine queries.-infixr 6 <&>-(<&>) :: Query -> Query -> Query-(<&>) = mappend-{-# DEPRECATED (<&>) "will be removed in the next major version of libmpd, use `(<>)` instead" #-}
src/Network/MPD/Commands/Types.hs view
@@ -28,6 +28,7 @@ , Device(..) , Song(..) , Position+ , Range(..) , Id(..) , Priority(..) , sgGetTag@@ -102,6 +103,7 @@ data Metadata = Artist | ArtistSort | Album+ | AlbumSort -- ^ @since 0.10.0.0 | AlbumArtist | AlbumArtistSort | Title@@ -109,15 +111,21 @@ | Name | Genre | Date+ | OriginalDate -- ^ @since 0.10.0.0 | Composer | Performer+ | Conductor -- ^ @since 0.10.0.0+ | Work -- ^ @since 0.10.0.0+ | Grouping -- ^ @since 0.10.0.0 | Comment | Disc+ | Label -- ^ @since 0.10.0.0 | MUSICBRAINZ_ARTISTID | MUSICBRAINZ_ALBUMID | MUSICBRAINZ_ALBUMARTISTID | MUSICBRAINZ_TRACKID | MUSICBRAINZ_RELEASETRACKID+ | MUSICBRAINZ_WORKID -- ^ @since 0.10.0.0 deriving (Eq, Enum, Ord, Bounded, Show) instance MPDArg Metadata@@ -164,9 +172,18 @@ | MixerS -- ^ The volume mixer | OutputS -- ^ Audio outputs | OptionsS -- ^ Playback options+ | PartitionS -- ^ Partition changes+ --+ -- @since 0.10.0.0 | StickerS -- ^ Sticker database | SubscriptionS -- ^ Subscription | MessageS -- ^ Message on subscribed channel+ | NeighborS -- ^ finding or losing a neighbor+ --+ -- @since 0.10.0.0+ | MountS -- ^ Mount list changes+ --+ -- @since 0.10.0.0 deriving (Eq, Enum, Ord, Bounded, Show) instance MPDArg Subsystem where@@ -178,20 +195,27 @@ prep MixerS = Args ["mixer"] prep OutputS = Args ["output"] prep OptionsS = Args ["options"]+ prep PartitionS = Args ["partition"] prep StickerS = Args ["sticker"] prep SubscriptionS = Args ["subscription"] prep MessageS = Args ["message"]+ prep NeighborS = Args ["neighbor"]+ prep MountS = Args ["mount"] data ReplayGainMode = Off -- ^ Disable replay gain | TrackMode -- ^ Per track mode | AlbumMode -- ^ Per album mode+ | AutoMode -- ^ Auto mode+ --+ -- @since 0.10.0.0 deriving (Eq, Enum, Ord, Bounded, Show) instance MPDArg ReplayGainMode where prep Off = Args ["off"] prep TrackMode = Args ["track"] prep AlbumMode = Args ["album"]+ prep AutoMode = Args ["auto"] -- | Represents the result of running 'count'. data Count =@@ -246,6 +270,16 @@ -- | The position of a song in a playlist. type Position = Int +-- | A range of songs.+data Range+ = Range Position Position -- ^ Start and end of the range, not including the end position.+ | Start Position -- ^ From the given position until the end of the playlist.+ deriving (Eq, Show)++instance MPDArg Range where+ prep (Range start end) = Args [show start ++ ":" ++ show end]+ prep (Start start) = Args [show start ++ ":"]+ newtype Id = Id Int deriving (Eq, Show) @@ -377,6 +411,7 @@ -- | Job ID of currently running update (if any). , stUpdatingDb :: Maybe Integer -- | If True, MPD will play only one song and stop after finishing it.+ -- If single is set to "oneshot" by another client, it's interperted as True. , stSingle :: Bool -- | If True, a song will be removed after it has been played. , stConsume :: Bool
src/Network/MPD/Core.hs view
@@ -155,7 +155,7 @@ modify (\st -> st { stVersion = version }) return True where- requiredVersion = (0, 15, 0)+ requiredVersion = (0, 19, 0) parseVersion = parseTriple '.' parseNum . dropWhile (not . isDigit)
src/Network/MPD/Util.hs view
@@ -9,7 +9,7 @@ module Network.MPD.Util ( parseDate, parseIso8601, formatIso8601, parseNum, parseFrac,- parseBool, showBool, breakChar, parseTriple,+ parseBool, parseSingle, showBool, breakChar, parseTriple, toAssoc, toAssocList, splitGroups, read ) where @@ -78,6 +78,14 @@ parseBool = parseMaybe p where p = A.char '1' *> pure True <|> A.char '0' *> pure False++-- Parse a boolean response value.+parseSingle :: ByteString -> Maybe Bool+parseSingle = parseMaybe p+ where+ p = A.char '1' *> pure True+ <|> A.char '0' *> pure False+ <|> A.string "oneshot" *> pure True -- Break a string into triple. parseTriple :: Char -> (ByteString -> Maybe a) -> ByteString -> Maybe (a, a, a)
tests/CommandSpec.hs view
@@ -119,9 +119,11 @@ describe "crossfade" $ do it "sets crossfade between songs" $ testCrossfade describe "play" $ do- it "toggles playback" $ testPlay+ it "resumes playback" $ testPlay describe "pause" $ do it "pauses playback" $ testPause+ describe "toggle" $ do+ it "toggles playback" $ testToggle describe "stop" $ do it "stops playback" $ testStop describe "next" $ do@@ -160,9 +162,6 @@ it "gets database stats" $ testStats -- * Extensions- describe "toggle" $ do- it "starts playback if paused" $ testTogglePlay- it "stops playback if playing" $ testToggleStop describe "addMany" $ do it "adds multiple paths in one go" $ testAddMany0 it "can also add to stored playlists" $ testAddMany1@@ -299,6 +298,8 @@ testPause = cmd_ [("pause 0", Right "OK")] (pause False) +testToggle = cmd_ [("pause", Right "OK")] (toggle)+ testStop = cmd_ [("stop", Right "OK")] stop testNext = cmd_ [("next", Right "OK")] next@@ -375,26 +376,6 @@ -- -- Extensions\/shortcuts ----testTogglePlay = cmd_- [("status", Right resp)- ,("pause 1", Right "OK")]- toggle- where resp = unparse def { stState = Playing }--testToggleStop = cmd_- [("status", Right resp)- ,("play", Right "OK")]- toggle- where resp = unparse def { stState = Stopped }--{- this overlaps with testToggleStop, no?-testTogglePause = cmd_- [("status", Right resp)- ,("play", Right "OK")]- toggle- where resp = unparse def { stState = Paused }--} testAddMany0 = cmd_ [("add \"bar\"", Right "OK")] (addMany "" ["bar"])