mmp

The mini music player, an alternative to MPD

git clone https://git.8pit.net/mmp.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 single? [self]
15    (= self.start self.end))
16
17  (defn infinite? [self]
18    (not self.end))
19
20  (defn to-range [self &optional max]
21    (if (.single? self)
22      (range self.start (inc self.end))
23      (if (and (self.infinite?) (is None max))
24        (raise (ValueError "Range has infinite length and no maximum supplied"))
25        (range self.start self.end)))))
26
27(defclass Command [object]
28  (defn __init__ [self cmd]
29    (setv self.name (.decode cmd.name))
30    (let [args (self.argv-list cmd.argc cmd.argv)]
31      (setv self.args (list (map self.convert-argument args)))))
32
33  (defn list? [self]
34    (or (= self.name "command_list_begin")
35        (= self.name "command_list_ok_begin")))
36
37  (defn argv-list [self argc argv]
38    (lfor
39      idx (range argc)
40      (. (get argv idx) contents)))
41
42  (defn convert-argument [self arg]
43    (let [t arg.type v arg.v]
44      (cond
45        [(= t MPDVal.INT) v.ival]
46        [(= t MPDVal.UINT) v.uval]
47        [(= t MPDVal.STR) (v.sval.decode)]
48        [(= t MPDVal.FLOAT) v.fval]
49        [(= t MPDVal.BOOL) v.bval]
50        [(= t MPDVal.RANGE)
51         (Range v.rval.start
52                   (if (= -1 v.rval.end) None v.rval.end))]
53        [(= t MPDVal.CMD)
54         (Command v.cmdval.contents)]
55        [(= t MPDVal.EXPR)
56         (raise (NotImplementedError "Expression not implemented yet"))]
57        [True (raise (TypeError (+ "unknown type " (str t))))]))))
58
59(defn parse-command [string]
60  (setv inptr (ctypes.c_char_p))
61  (setv inptr.value (string.encode))
62  (let [outptr (parse inptr)]
63    (if (bool outptr)
64      (let [cmd (Command outptr.contents)]
65        (freecmd outptr)
66        cmd)
67      (raise (ValueError "not a valid MPD command")))))