diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,17 @@
+# v1.3
+- Add `filename` key.
+- Add `playlist` key and move existing keys to it.
+- Customize ordering of displayed output JSON.
+- Add cabal tested-with GHC versions
+
 # v1.2.0.0
 - Move literate Org Mode code to LITERATE.org file
 - Move functions from executable source Main.hs to their own library
 - Bump dependency versions for `aeson` and `bytestring`
+- Changed status.state from "play" to "playing" and "pause" to
+  "paused".
+  The reason why it was "play" and "pause" before was because
+  that was the socket answer string.
 
 # v1.1.0.2
 [comment]: # (2023-10-23)
diff --git a/README.org b/README.org
--- a/README.org
+++ b/README.org
@@ -3,21 +3,31 @@
 #+OPTIONS: toc:1
 
 * Installation
-: cabal install mpd-current-json
-or
+Packages are available:
+- [[https://aur.archlinux.org/packages/mpd-current-json][in the AUR]]
+- in Hackage:
+  : cabal install mpd-current-json
+
+or compile it from source:
 #+begin_example
 git clone https://codeberg.org/useless-utils/mpd-current-json
 cd mpd-current-json
 #+end_example
-and to install the executable to =./dist=, in the current directory:
+to install the executable to =./dist=, in the current directory:
 : cabal install --install-method=copy --overwrite-policy=always --installdir=dist
 or to install to =${CABAL_DIR}/bin= remove the =--installdir=dist=
 argument. =CABAL_DIR= defaults to =~/.local/share/cabal=.
 
 * Usage
-get values
-: mpd-current-json | jaq .tags.album
-: mpd-current-json | jaq .status.elapsed_percent
+- Get values
+  : mpd-current-json | jaq .tags.album
+  : mpd-current-json | jaq .status.elapsed_percent
 
-provide host and port with
-: mpd-current-json -h 'localhost' -p 4321
+- Provide host and port with
+  : mpd-current-json -h 'localhost' -p 4321
+
+- Provide password
+  : mpd-current-json --password 'abc123'
+  note that the password will be sent as plain text.
+
+Run =mpd-current-json --help= for all the available options.
diff --git a/lib/Network/MPD/Parse.hs b/lib/Network/MPD/Parse.hs
--- a/lib/Network/MPD/Parse.hs
+++ b/lib/Network/MPD/Parse.hs
@@ -2,6 +2,7 @@
   ( getStatusItem
   , getTag
   , processSong
+  , maybePath
   , headMay
   , valueToStringMay
   , (.=?)
@@ -45,6 +46,13 @@
 processSong tag (Just song) = do
   let tagVal = MPD.sgGetTag tag song
   valueToStringMay =<< (headMay =<< tagVal)
+
+maybePath :: Either a (Maybe Song) -> Maybe String
+maybePath cs =
+  case cs of
+    Left _ -> Nothing
+    Right Nothing -> Nothing
+    Right (Just song) -> Just $ MPD.toString $ MPD.sgFilePath song
 
 {- | Safely get the head of a list. Same as [Safe.headMay](Safe#headMay).
 -}
diff --git a/mpd-current-json.cabal b/mpd-current-json.cabal
--- a/mpd-current-json.cabal
+++ b/mpd-current-json.cabal
@@ -7,7 +7,7 @@
 -- PVP summary:     +-+------- breaking API changes
 --                  | | +----- non-breaking API additions
 --                  | | | +--- code changes with no API change
-version:            1.2.0.0
+version:            1.3.0.0
 synopsis:           Print current MPD song and status as JSON
 
 -- A longer description of the package.
@@ -24,13 +24,15 @@
 -- A copyright notice.
 -- copyright:
 category:           Network
-extra-source-files: CHANGELOG.md
+extra-doc-files:    CHANGELOG.md
                     README.org
 
 source-repository head
     type:      git
     location:  https://codeberg.org/useless-utils/mpd-current-json
 
+-- tested-with: GHC == 9.4.8
+
 library
     -- exposed: False
     exposed-modules:  Network.MPD.Parse
@@ -58,7 +60,7 @@
                     , aeson
                     , bytestring >=0.11 && <0.13
                     , aeson-pretty == 0.8.*
-                    , mpd-current-json == 1.2.*
+                    , mpd-current-json == 1.3.*
 
     -- Directories containing source files.
     hs-source-dirs:   src
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -6,16 +6,21 @@
 import Network.MPD
        ( Metadata(..), PlaybackState(Stopped, Playing, Paused) )
 import Data.Maybe ( catMaybes )
-import Data.Aeson ( object, KeyValue(..) )
-import Data.Aeson.Encode.Pretty ( encodePretty )
+import Data.Aeson ( object, KeyValue((.=)), Value )
+import Data.Aeson.Encode.Pretty
+       ( defConfig, encodePretty', keyOrder, Config(confCompare) )
 import qualified Data.ByteString.Lazy.Char8 as C
 import Text.Printf ( printf )
 import Options
     ( optsParserInfo, execParser, Opts(optPass, optHost, optPort) )
 
 import Network.MPD.Parse ( getStatusItem
-                             , getTag
-                             , (.=?) )
+                         , getTag
+                         , maybePath
+                         , (.=?) )
+
+import Text.Read (readMaybe)
+import Data.Aeson.Types (Pair)
 {- | Where the program connects to MPD and uses the helper functions to
 extract values, organize them into a list of key/value pairs, make
 them a 'Data.Aeson.Value' using 'Data.Aeson.object', then encode it to
@@ -69,20 +74,20 @@
       elapsed = case time of
         Just t -> case t of
                     Just (e, _) -> Just e
-                    _           -> Nothing
+                    _noTag      -> Nothing
         Nothing -> Nothing
 
       duration = case time of
         Just t -> case t of
                     Just (_, d) -> Just d
-                    _           -> Nothing
+                    _noTag      -> Nothing
         Nothing -> Nothing
 
       elapsedPercent :: Maybe Double
       elapsedPercent = case time of
         Just t -> case t of
-                    Just t1 -> Just (read $ printf "%.2f" (uncurry (/) t1 * 100))
-                    Nothing -> Just 0
+                   Just t1 -> readMaybe $ printf "%.2f" (uncurry (/) t1 * 100)
+                   Nothing -> Just 0
         Nothing -> Nothing
 
       repeatSt       = getStatusItem st MPD.stRepeat
@@ -95,8 +100,10 @@
       audioFormat    = getStatusItem st MPD.stAudio
       errorSt        = getStatusItem st MPD.stError
 
+  let filename = maybePath cs
+
   -- sgTags
-  let jTags = object . catMaybes $
+  let jTags = objectJson
         [ "artist"                     .=? artist
         , "artist_sort"                .=? artistSort
         , "album"                      .=? album
@@ -126,23 +133,61 @@
         ]
 
   -- status
-  let jStatus = object . catMaybes $
+  let jStatus = objectJson
         [ "state"           .=? state
         , "repeat"          .=? repeatSt
-        , "elapsed"         .=? elapsed
-        , "duration"        .=? duration
-        , "elapsed_percent" .=? elapsedPercent
         , "random"          .=? randomSt
         , "single"          .=? singleSt
         , "consume"         .=? consumeSt
-        , "song_position"   .=? pos
-        , "playlist_length" .=? playlistLength
-        , "bitrate"         .=? bitrate
+        , "duration"        .=? duration
+        , "elapsed"         .=? elapsed
+        , "elapsed_percent" .=? elapsedPercent
         , "audio_format"    .=? audioFormat
+        , "bitrate"         .=? bitrate
         , "error"           .=? errorSt
         ]
 
-  let jObject = object [ "tags"   .= jTags
-                       , "status" .= jStatus ]
+  -- let jFilename = objectJson [ "file" .=? filename ]
 
-  C.putStrLn $ encodePretty jObject
+  let jPlaylist = objectJson
+        [ "position" .=? pos
+        , "length"           .=? playlistLength
+        ]
+
+  let jObject = object [ "filename" .= filename
+                       , "playlist" .= jPlaylist
+                       , "status"   .= jStatus
+                       , "tags"     .= jTags
+                       ]
+
+  C.putStrLn $ encodePretty' customEncodeConf jObject
+
+customEncodeConf :: Config
+customEncodeConf = defConfig
+  { confCompare = keyOrder [ "title", "name"
+                           , "artist", "album_artist", "artist_sort", "album_artist_sort"
+                           , "album", "album_sort"
+                           , "track", "disc"
+                           , "date", "original_date"
+                           , "genre", "composer", "performer", "conductor"
+                           , "work", "grouping", "label"
+                           , "comment"
+                           , "musicbrainz_artistid"
+                           , "musicbrainz_albumid"
+                           , "musicbrainz_albumartistid"
+                           , "musicbrainz_trackid"
+                           , "musicbrainz_releasetrackid"
+                           , "musicbrainz_workid"
+                           -- status
+                           , "state", "repeat", "random", "single", "consume"
+                           , "duration", "elapsed", "elapsed_percent"
+                           , "audio_format", "bitrate"
+                           , "error"
+                           ]
+  }
+
+-- | Helper function for creating an JSON 'Data.Aeson.object' where
+-- 'Data.Maybe.catMaybes' won't include items from the '[Maybe Pair]'
+-- list that return 'Nothing'.
+objectJson :: [Maybe Pair] -> Value
+objectJson = object . catMaybes
