1(import [mpd.ffi [*]] ctypes)2(require [hy.contrib.walk [let]])34(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)89(defclass Range [object]10 (defn --init-- [self start &optional end]11 (setv self.start start)12 (setv self.end end))1314 (defn infinite? [self]15 (not self.end))1617 (defn to-range [self]18 (if (self.infinite?)19 (raise (ValueError "Range has infinite length"))20 (range self.start self.end))))2122(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)))))2728 (defn list? [self]29 (or (= self.name "command_list_begin")30 (= self.name "command_list_ok_begin")))3132 (defn argv-list [self argc argv]33 (lfor34 idx (range argc)35 (. (get argv idx) contents)))3637 (defn convert-argument [self arg]38 (let [t arg.type v arg.v]39 (cond40 [(= 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.start47 (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))))]))))5354(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")))))