mpvd

Control mpv using the MPD protocol

git clone https://git.8pit.net/mpvd.git

 1(import mpd [mpv.message [DELIMITER]]
 2  [mpv.util [same-song]]
 3  [protocol [commands]])
 4
 5;; Mapping of MPV tag names to MPD tag names.
 6;; See: src/tag/Names.c in MPD source.
 7(setv MPD-TAG-NAMES {
 8    "title"        "Title"
 9    "artist"       "Artist"
10    "album"        "Album"
11    "genre"        "Genre"
12    "track"        "Track"
13    "disc"         "Disc"
14    "album_artist" "AlbumArtist"
15  })
16
17(defn lowercase-metadata [metadata]
18  (dict (map (fn [tag]
19               (, (.lower (first tag)) (last tag)))
20             (.items metadata))))
21
22(defn convert-metadata [metadata]
23  (reduce (fn [dict pair]
24            (if (in (first pair) MPD-TAG-NAMES)
25              (assoc dict (get MPD-TAG-NAMES (first pair)) (last pair)))
26            dict)
27          (.items (lowercase-metadata metadata)) {}))
28
29;; See https://github.com/MusicPlayerDaemon/MPD/blob/d663f81/src/command/PlayerCommands.cxx#L119-L129
30(defn current-state [mpv]
31  ;; TODO: Support "stop" state
32  (if (mpv.get-property "pause") "pause" "play"))
33
34(with-decorator (commands.add "currentsong")
35  (defn current-song [mpv cmd]
36    (with [(same-song mpv)]
37      ;; See https://github.com/MusicPlayerDaemon/MPD/blob/d663f81/src/SongPrint.cxx#L82
38      {#** {
39             "file"     (mpv.get-property "path")
40             "Pos"      (mpv.get-property "playlist-pos")
41             "duration" (mpv.get-property "duration")
42           }
43       #** (convert-metadata (mpv.get-property "metadata"))})))
44
45(with-decorator (commands.add "status")
46  (defn status [mpv cmd]
47    (with [(same-song mpv)]
48      (setv [curtime maxtime] (,
49        (mpv.get-property "time-pos")
50        (mpv.get-property "duration")))
51
52      ;; See https://github.com/MusicPlayerDaemon/MPD/blob/d663f81/src/command/PlayerCommands.cxx#L110
53      {
54        "volume"         (mpv.get-property "volume")
55        "repeat"         (mpv.get-property "options/loop")
56        "random"         (mpv.get-property "options/shuffle")
57        "playlistlength" (mpv.get-property "playlist-count")
58        "state"          (current-state mpv)
59        "song"           (mpv.get-property "playlist-pos")
60        "time"           (.format "{}:{}"
61                           (round curtime)
62                           (round maxtime))
63        "elapsed"        curtime
64        "duration"       maxtime
65        "bitrate"        (/ (mpv.get-property "audio-bitrate" 0) 1000)
66      })))