mpvd

Control mpv using the MPD protocol

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

 1(import [mpd.ffi [*]] ctypes)
 2(require [hy.contrib.walk [let]])
 3
 4(setv libmpdserver (ctypes.CDLL "libmpdserver.so"))
 5(setv parse libmpdserver.mpd_parse)
 6(setv parse.restype (ctypes.POINTER MPDCmd))
 7(setv freecmd libmpdserver.mpd_free_command)
 8
 9(defclass Range [object]
10  (defn --init-- [self start &optional end]
11    (setv self.start start)
12    (setv self.end end))
13
14  (defn infinite? [self]
15    (not self.end))
16
17  (defn to-range [self]
18    (if (self.infinite?)
19      (raise (ValueError "Range has infinite length"))
20      (range self.start self.end))))
21
22(defclass Command [object]
23  (defn --init-- [self cmd]
24    (setv self.name (.decode cmd.name))
25    (let [args (self.argv-list cmd.argc cmd.argv)]
26      (setv self.args (list (map self.convert-argument args)))))
27
28  (defn list? [self]
29    (or (= self.name "command_list_begin")
30        (= self.name "command_list_ok_begin")))
31
32  (defn argv-list [self argc argv]
33    (lfor
34      idx (range argc)
35      (. (get argv idx) contents)))
36
37  (defn convert-argument [self arg]
38    (let [t arg.type v arg.v]
39      (cond
40        [(= t MPDVal.INT) v.ival]
41        [(= t MPDVal.UINT) v.uval]
42        [(= t MPDVal.STR) (v.sval.decode)]
43        [(= t MPDVal.FLOAT) v.fval]
44        [(= t MPDVal.BOOL) v.bval]
45        [(= t MPDVal.RANGE)
46         (Range v.rval.start
47                   (if (= -1 v.rval.end) None v.rval.end))]
48        [(= t MPDVal.CMD)
49         (Command v.cmdval.contents)]
50        [(= t MPDVal.EXPR)
51         (raise (NotImplementedError "Expression not implemented yet"))]
52        [True (raise (TypeError (+ "unknown type " (string t))))]))))
53
54(defn parse-command [string]
55  (setv inptr (ctypes.c_char_p))
56  (setv inptr.value (string.encode))
57  (let [outptr (parse inptr)]
58    (if (bool outptr)
59      (let [cmd (Command outptr.contents)]
60        (freecmd outptr)
61        cmd)
62      (raise (ValueError "not a valid MPD command")))))