1(import [random [randrange]] os)
2(require [hy.contrib.walk [let]])
3
4(defclass Song []
5 (setv path None)
6 (setv metadata {})
7 (setv position 0)
8
9 (defn __init__ [self path metadata]
10 (if (not (os.path.isfile path))
11 (raise (FileNotFoundError
12 (.format "file '{}' does not exist" path))))
13
14 (setv self.path path)
15 (setv self.metadata metadata)))
16
17(defclass Playlist []
18 (setv mode {
19 :repeat False :random False
20 :single False :consume False
21 })
22
23 (defn __init__ [self]
24 (setv self._current None)
25 (setv self._next None)
26 (setv self._list []))
27
28 (defn __iter__ [self]
29 (iter self._list))
30
31 (defn _get-song [self index]
32 (let [song (get self._list index)]
33 (setv song.position index)
34 song))
35
36 (defn psize [self]
37 (len self._list))
38
39 (defn current [self]
40 (if (is None self._current)
41 None
42 (get self._list self._current)))
43
44 (defn add [self song]
45 (if (isinstance song Song)
46 (.append self._list song)
47 (raise (TypeError "not an instance of Song"))))
48
49 (defn get [self index]
50 (._get-song self index))
51
52 (defn remove [self range]
53 (let [start (. range start) stop (. range stop)]
54 (if (= (len range) 1)
55 (.pop self._list start)
56 (setv self._list (cut self._list start stop)))))
57
58 (defn reset [self]
59 (setv self._current None)
60 (setv self._next None))
61
62 (defn nextup [self index]
63 (if (>= index (len self._list))
64 (raise (IndexError "song position out of range"))
65 (setv self._next index)))
66
67 (defn next [self]
68 (defn next-index [mode]
69 (cond
70 [(not self._list) None]
71 [(is None self._current) 0]
72 [(get mode :single)
73 (if (get mode :repeat)
74 (. self _current)
75 None)]
76 [True
77 (let [n (if (get mode :random)
78 (randrange (len self._list))
79 (inc self._current))]
80 (if (>= n (len self._list))
81 (if (get mode :repeat) 0 None)
82 n))]))
83
84 (if (get self.mode :consume)
85 (.pop self._current))
86 (let [idx (if (is None self._next)
87 (next-index self.mode)
88 (. self _next))]
89 (setv self._next None)
90 (setv self._current idx)
91 (if (is None idx)
92 None
93 (._get-song self idx)))))