-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
api.lisp
141 lines (126 loc) · 5.77 KB
/
api.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
(in-package #:rsbag-renderer)
(define-api shutdown () ()
(stop :quit T))
(define-api error (&optional message) ()
(error (or message "An utterly surprising error.")))
(defun safely-parse-date (string)
(local-time:parse-timestring
string :allow-missing-elements T
:allow-missing-date-part T
:allow-missing-time-part NIL
:allow-missing-timezone-part T))
(define-api transform (transform) ()
(let ((transform (or (transform transform)
(error "No such transform ~s" transform))))
(with-api-output ("Transform data")
(with-json-object ()
(pair "identifier" (identifier transform))
(pair "description" (description transform))))))
(define-api transform/list () ()
(with-api-output ("Transform listing")
(with-json-array ()
(dolist (transform (list-transforms))
(entry (identifier transform))))))
(define-api transform/remove (transform) ()
(unless (transform transform)
(error "No such transform ~s" transform))
(remove-transform transform)
(with-api-output ("Transform removed.")
(json-null)))
(define-api visualizer (visualizer) ()
(let ((visualizer (or (visualizer visualizer)
(error "No such visualizer ~s" visualizer))))
(with-api-output ("Visualizer data")
(with-json-object ()
(pair "identifier" (identifier visualizer))
(pair "description" (description visualizer))
(with-json-value ("payload")
(with-json-object ()
(pair "js" (js visualizer))
(pair "html" (html visualizer))
(pair "css" (css visualizer))))))))
(define-api visualizer/list () ()
(with-api-output ("Visualization listing")
(with-json-array ()
(dolist (visualizer (list-visualizers))
(entry (identifier visualizer))))))
(define-api visualizer/remove (visualizer) ()
(unless (visualizer visualizer)
(error "No such visualizer ~s" visualizer))
(remove-visualizer visualizer)
(with-api-output ("Visualizer removed.")
(json-null)))
(define-api source (source) ()
(let ((source (or (source source)
(error "No such source ~s" source))))
(with-api-output ("Source data")
(with-json-object ()
(pair "identifier" (identifier source))
(pair "description" (description source))))))
(define-api source/list () ()
(with-api-output ("Source listing")
(with-json-array ()
(dolist (source (list-sources))
(entry (identifier source))))))
(define-api source/remove (source) ()
(close-source (or (source source)
(error "No such source ~s" source)))
(with-api-output ("Source removed.")
(json-null)))
(define-api source/channel (source channel) ()
(let* ((source (or (source source)
(error "No such source ~s" source)))
(channel (or (channel source channel)
(error "No such channel ~s" channel))))
(with-api-output ("Channel data")
(with-json-object ()
(pair "identifier" (identifier channel))
(pair "length" (channel-length channel))
(pair "resolution" (resolution channel))
(pair "duration" (duration channel))
(pair "start" (local-time:timestamp-to-unix (start-timestamp channel)))
(pair "end" (local-time:timestamp-to-unix (end-timestamp channel)))))))
(define-api source/channel/list (source) ()
(let ((source (or (source source)
(error "No such source ~s" source))))
(with-api-output ("Channel listing")
(with-json-array ()
(dolist (channel (channels source))
(entry (identifier channel)))))))
(define-api source/channel/event (source channel &optional (transform "direct") (skip "0") amount from to) ()
(declare (optimize speed))
(let* ((source (or (source source)
(error "No such source ~s" source)))
(channels (loop for chan in (ensure-list channel)
collect (or (channel source chan)
(error "No such channel ~s" chan))))
(minlength (loop for chan in channels
minimize (channel-length chan)))
(transform (or (transform transform)
(error "No such transform ~s" transform)))
(skip (the fixnum (parse-integer skip)))
(amount (and amount (parse-integer amount)))
(from (and from (safely-parse-date from)))
(to (and to (safely-parse-date to))))
(assert (<= 0 skip) () "SKIP must be 0 or greater.")
(assert (or (null amount) (<= 0 amount)) () "AMOUNT must be 0 or greater.")
(assert (or (null from) (null to) (local-time:timestamp<= from to)) () "TO cannot be a time before FROM.")
(with-api-output ("Event delivery")
(with-json-array ()
(loop with in-range = (not from)
for i from skip below minlength
for count from 0
for events = (mapcar (<< #'event i) channels)
while (and (or (not amount) (< (the fixnum count) (the fixnum amount)))
(or (not to) (loop for ev in events always (local-time:timestamp<= ev to))))
do (cond (in-range
(with-json-entry ()
(with-json-object ()
(pair "id" i)
(pair "timestamp" (local-time:timestamp-to-unix (timestamp (first events))))
(with-json-value ("data")
(transform-events transform events)))))
;; Not the best way to handle this. Ideally, stepping should
;; happen on a per-channel basis or something similar.
((loop for ev in events always (local-time:timestamp<= from ev))
(setf in-range T))))))))