{-# LANGUAGE OverloadedStrings #-} {- | Module : Network.MPD.Applicative.CurrentPlaylist Copyright : (c) Joachim Fasting 2012 License : MIT Maintainer : joachifm@fastmail.fm Stability : stable Portability : unportable The current playlist. -} module Network.MPD.Applicative.CurrentPlaylist ( add , addId , clear , delete , deleteRange , deleteId , move , moveId , moveRange , playlistFind , playlistInfo , playlistInfoRange , playlistId , playlistSearch , plChanges , plChangesPosId , prio , prioId , shuffle , swap , swapId , addTagId , clearTagId , rangeId ) where import Network.MPD.Commands.Arg hiding (Command) import qualified Network.MPD.Commands.Arg as Arg import Network.MPD.Util import Network.MPD.Commands.Query import Network.MPD.Commands.Parse import Network.MPD.Commands.Types import Network.MPD.Applicative.Internal import Network.MPD.Applicative.Util -- | Add a song (or a whole directory) to the current playlist. add :: Path -> Command () add path = Command emptyResponse ["add" <@> path] -- | Add a song (non-recursively) and return its id. addId :: Path -> Maybe Position -> Command Id addId path pos = Command p c where c = ["addid" <@> path <++> pos] p = do r <- getResponse case toAssocList r of [("Id", n)] -> maybe (unexpected r) (return . Id) (parseNum n) _ -> unexpected r -- | Clear the current playlist. clear :: Command () clear = Command emptyResponse ["clear"] -- | Delete song at the given playlist position. delete :: Position -> Command () delete pos = Command emptyResponse ["delete" <@> pos] -- | Delete a range of songs from the playlist. deleteRange :: (Position, Position) -> Command () deleteRange range = Command emptyResponse ["delete" <@> range] -- | Delete song by id. deleteId :: Id -> Command () deleteId i = Command emptyResponse ["deleteid" <@> i] -- | Move song from one position to another. move :: Position -> Position -> Command () move pos to = Command emptyResponse ["move" <@> pos <++> to] -- | Move a range of songs. moveRange :: (Position, Position) -> Position -> Command () moveRange range to = Command emptyResponse ["move" <@> range <++> to] -- | Move song id to position. -- If the position is negative, it is relative to the current song. moveId :: Id -> Position -> Command () moveId i to = Command emptyResponse ["moveid" <@> i <++> to] -- Note: 'playlist' deliberately not defined here -- Internal helper for playlist* commands playlist' :: MPDArg a => Arg.Command -> a -> Command [Song] playlist' cmd q = Command (liftParser takeSongs) [cmd <@> q] -- | Find songs in current playlist with strict matching. playlistFind :: Query -> Command [Song] playlistFind = playlist' "playlistfind" -- | Get song metadata for all items in the current playlist. -- Optionally restrict listing the song at the given position. playlistInfo :: Maybe Position -> Command [Song] playlistInfo = playlist' "playlistinfo" -- | Like 'playlistInfo' but can restrict listing to a range -- of songs. playlistInfoRange :: Maybe (Position, Position) -> Command [Song] playlistInfoRange = playlist' "playlistinfo" -- | Get song metadata for all items in the current playlist. -- Optionally restrict selection to a single song id. playlistId :: Maybe Id -> Command [Song] playlistId = playlist' "playlistid" -- | Search case-insensitively for partial matches in current playlist. playlistSearch :: Query -> Command [Song] playlistSearch = playlist' "playlistsearch" -- | Get song metadata for items that have changed in the playlist since -- the given playlist version. plChanges :: Integer -> Command [Song] plChanges = playlist' "plchanges" -- | Get positions and ids of songs that have changed in the playlist -- since the given playlist version. plChangesPosId :: Integer -> Command [(Position, Id)] plChangesPosId ver = Command p ["plchangesposid" <@> ver] where -- XXX: possibly suboptimal definition p :: Parser [(Position, Id)] p = liftParser $ mapM f . splitGroups ["cpos"] . toAssocList f xs | [("cpos", x), ("Id", y)] <- xs , Just (x', y') <- pair parseNum (x, y) = Right (x', Id y') | otherwise = Left "" -- | Set the priority of the specified songs. prio :: Priority -> (Position, Position) -> Command () prio p range = Command emptyResponse ["prio" <@> p <++> range] -- | Set priority by song id. prioId :: Priority -> Id -> Command () prioId p ids = Command emptyResponse ["prioid" <@> p <++> ids] -- | Shuffle the current playlist. -- Optionally restrict to a range of songs. shuffle :: Maybe (Position, Position) -> Command () shuffle mbRange = Command emptyResponse ["shuffle" <@> mbRange] -- | Swap songs by position. swap :: Position -> Position -> Command () swap pos1 pos2 = Command emptyResponse ["swap" <@> pos1 <++> pos2] -- | Swap songs by id. swapId :: Id -> Id -> Command () swapId id1 id2 = Command emptyResponse ["swapid" <@> id1 <++> id2] -- | Add tag to specified (remote) song. addTagId :: Id -> Metadata -> Value -> Command () addTagId id' tag val = Command emptyResponse ["addtagid" <@> id' <++> tag <++> val] -- | Remove tag from specified (remote) song. clearTagId :: Id -> Metadata -> Command () clearTagId id' tags = Command emptyResponse ["cleartagid" <@> id' <++> tags] -- | Specify portion of song that shall be played. -- Both ends of the range are optional; omitting both plays everything. 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