rev |
line source |
nuclear@2
|
1 #include <stdio.h>
|
nuclear@2
|
2 #include <math.h>
|
nuclear@2
|
3 #include <stdlib.h>
|
nuclear@2
|
4 #include <string.h>
|
nuclear@2
|
5 #include <errno.h>
|
nuclear@2
|
6 #include "dsys2.h"
|
nuclear@2
|
7 #include "dsys_impl.h"
|
nuclear@2
|
8
|
nuclear@4
|
9 static int read_script(struct dsys_demo *demo, FILE *fp, const char *fname);
|
nuclear@4
|
10
|
nuclear@6
|
11 static void proc_event(struct dsys_event *ev, demotime_t tm);
|
nuclear@6
|
12 static void link_callback(struct dsys_event *ev, void *cls);
|
nuclear@2
|
13 static void free_event(struct dsys_event *ev);
|
nuclear@2
|
14
|
nuclear@4
|
15 static struct dsys_event *sort_evlist(struct dsys_event *list, int num_ev);
|
nuclear@4
|
16 static struct dsys_event *merge_evlists(struct dsys_event *list1, struct dsys_event *list2);
|
nuclear@2
|
17
|
nuclear@2
|
18
|
nuclear@2
|
19 struct dsys_demo *dsys_open(const char *fname)
|
nuclear@2
|
20 {
|
nuclear@2
|
21 FILE *fp;
|
nuclear@4
|
22 struct dsys_demo *demo;
|
nuclear@2
|
23
|
nuclear@2
|
24 if(!(fp = fopen(fname, "r"))) {
|
nuclear@2
|
25 fprintf(stderr, "failed to open demoscript: %s: %s\n", fname, strerror(errno));
|
nuclear@2
|
26 return 0;
|
nuclear@2
|
27 }
|
nuclear@2
|
28
|
nuclear@4
|
29 if(!(demo = malloc(sizeof *demo))) {
|
nuclear@4
|
30 perror("failed to allocate memory");
|
nuclear@4
|
31 fclose(fp);
|
nuclear@4
|
32 return 0;
|
nuclear@4
|
33 }
|
nuclear@4
|
34 memset(demo, 0, sizeof *demo);
|
nuclear@4
|
35
|
nuclear@4
|
36 demo->src_tm = demo->start_tm = -1;
|
nuclear@4
|
37
|
nuclear@4
|
38 if(read_script(demo, fp, fname) == -1) {
|
nuclear@4
|
39 free(demo);
|
nuclear@4
|
40 fclose(fp);
|
nuclear@4
|
41 return 0;
|
nuclear@4
|
42 }
|
nuclear@4
|
43
|
nuclear@2
|
44 fclose(fp);
|
nuclear@4
|
45 return demo;
|
nuclear@2
|
46 }
|
nuclear@2
|
47
|
nuclear@2
|
48 struct dsys_demo *dsys_open_stream(FILE *fp)
|
nuclear@2
|
49 {
|
nuclear@2
|
50 struct dsys_demo *demo;
|
nuclear@2
|
51
|
nuclear@2
|
52 if(!(demo = malloc(sizeof *demo))) {
|
nuclear@2
|
53 perror("failed to allocate memory");
|
nuclear@2
|
54 return 0;
|
nuclear@2
|
55 }
|
nuclear@2
|
56 memset(demo, 0, sizeof *demo);
|
nuclear@2
|
57
|
nuclear@2
|
58 demo->src_tm = demo->start_tm = -1;
|
nuclear@2
|
59
|
nuclear@4
|
60 if(read_script(demo, fp, 0) == -1) {
|
nuclear@3
|
61 free(demo);
|
nuclear@3
|
62 return 0;
|
nuclear@3
|
63 }
|
nuclear@3
|
64
|
nuclear@2
|
65 return demo;
|
nuclear@2
|
66 }
|
nuclear@2
|
67
|
nuclear@2
|
68 void dsys_close(struct dsys_demo *demo)
|
nuclear@2
|
69 {
|
nuclear@4
|
70 while(demo->evlist) {
|
nuclear@4
|
71 struct dsys_event *ev = demo->evlist;
|
nuclear@4
|
72 demo->evlist = demo->evlist->next;
|
nuclear@2
|
73 free_event(ev);
|
nuclear@2
|
74 }
|
nuclear@2
|
75
|
nuclear@2
|
76 free(demo);
|
nuclear@2
|
77 }
|
nuclear@2
|
78
|
nuclear@2
|
79
|
nuclear@4
|
80 #define SEP " \t\n\r"
|
nuclear@3
|
81
|
nuclear@4
|
82 static int read_script(struct dsys_demo *demo, FILE *fp, const char *fname)
|
nuclear@3
|
83 {
|
nuclear@3
|
84 int nline = 0;
|
nuclear@4
|
85 char buf[512], *line, *tok, *endp;
|
nuclear@4
|
86 unsigned int t0, t1;
|
nuclear@3
|
87 struct dsys_event *ev;
|
nuclear@3
|
88
|
nuclear@4
|
89 if(!fname) {
|
nuclear@4
|
90 fname = "<unknown>";
|
nuclear@4
|
91 }
|
nuclear@4
|
92
|
nuclear@3
|
93 while(fgets(buf, sizeof buf, fp)) {
|
nuclear@3
|
94 nline++;
|
nuclear@3
|
95
|
nuclear@3
|
96 line = buf;/*strip_ws(buf);*/
|
nuclear@3
|
97
|
nuclear@3
|
98 if(!line || !*line) {
|
nuclear@3
|
99 continue;
|
nuclear@3
|
100 }
|
nuclear@3
|
101
|
nuclear@4
|
102 if(!(tok = strtok(line, SEP)) || (t0 = strtol(tok, &endp, 10), endp == tok)) {
|
nuclear@4
|
103 fprintf(stderr, "%s line: %d, error: expected timestamp t0\n", fname, nline);
|
nuclear@3
|
104 return -1;
|
nuclear@3
|
105 }
|
nuclear@3
|
106
|
nuclear@3
|
107 if(!(tok = strtok(0, SEP))) {
|
nuclear@4
|
108 fprintf(stderr, "%s line: %d, error: expected second timestamp or event name\n", fname, nline);
|
nuclear@3
|
109 return -1;
|
nuclear@3
|
110 }
|
nuclear@3
|
111
|
nuclear@4
|
112 t1 = strtol(tok, &endp, 10);
|
nuclear@4
|
113 if(endp == tok) {
|
nuclear@4
|
114 t1 = t0;
|
nuclear@4
|
115 } else {
|
nuclear@4
|
116 if(!(tok = strtok(0, SEP))) {
|
nuclear@4
|
117 fprintf(stderr, "%s line: %d, error: expected event name\n", fname, nline);
|
nuclear@4
|
118 return -1;
|
nuclear@4
|
119 }
|
nuclear@4
|
120 }
|
nuclear@4
|
121
|
nuclear@3
|
122 if(!(ev = malloc(sizeof *ev))) {
|
nuclear@3
|
123 perror("read_script: failed to allocate memory for an event\n");
|
nuclear@3
|
124 return -1;
|
nuclear@3
|
125 }
|
nuclear@3
|
126 ev->t0 = t0;
|
nuclear@3
|
127 ev->t1 = t1;
|
nuclear@3
|
128
|
nuclear@3
|
129 if(!(ev->name = malloc(strlen(tok) + 1))) {
|
nuclear@3
|
130 free(ev);
|
nuclear@5
|
131 fprintf(stderr, "read_script: failed to allocate memory for the event name: %s\n", tok);
|
nuclear@3
|
132 return -1;
|
nuclear@3
|
133 }
|
nuclear@4
|
134 strcpy(ev->name, tok);
|
nuclear@4
|
135
|
nuclear@6
|
136 ev->eval = t0 == t1 ? dsys_eval_step : dsys_eval_lerp;
|
nuclear@4
|
137
|
nuclear@4
|
138 ev->next = demo->evlist;
|
nuclear@4
|
139 ev->prev = 0;
|
nuclear@4
|
140 if(demo->evlist) {
|
nuclear@4
|
141 demo->evlist->prev = ev;
|
nuclear@4
|
142 }
|
nuclear@4
|
143 demo->evlist = ev;
|
nuclear@4
|
144 demo->num_ev++;
|
nuclear@3
|
145 }
|
nuclear@3
|
146
|
nuclear@4
|
147 demo->evlist = sort_evlist(demo->evlist, demo->num_ev);
|
nuclear@4
|
148
|
nuclear@3
|
149 return 0;
|
nuclear@3
|
150 }
|
nuclear@3
|
151
|
nuclear@3
|
152
|
nuclear@2
|
153 void dsys_update(struct dsys_demo *demo, demotime_t tm)
|
nuclear@2
|
154 {
|
nuclear@6
|
155 struct dsys_event *ev;
|
nuclear@6
|
156
|
nuclear@2
|
157 demo->src_tm = tm;
|
nuclear@2
|
158
|
nuclear@2
|
159 if(demo->start_tm == -1) {
|
nuclear@2
|
160 dsys_start(demo);
|
nuclear@2
|
161 }
|
nuclear@2
|
162
|
nuclear@6
|
163 if(!demo->running) {
|
nuclear@6
|
164 return; /* nothing changes */
|
nuclear@2
|
165 }
|
nuclear@2
|
166
|
nuclear@6
|
167 demo->tm = tm - demo->start_tm - demo->stoppage_tm;
|
nuclear@6
|
168
|
nuclear@6
|
169 while(demo->active->t1 < demo->tm) {
|
nuclear@6
|
170 proc_event(demo->active, demo->tm);
|
nuclear@6
|
171 demo->active = demo->active->next;
|
nuclear@6
|
172 }
|
nuclear@6
|
173
|
nuclear@6
|
174 ev = demo->active;
|
nuclear@6
|
175 while(ev->t0 <= demo->tm) {
|
nuclear@6
|
176 proc_event(ev, demo->tm);
|
nuclear@6
|
177 ev = ev->next;
|
nuclear@6
|
178 }
|
nuclear@6
|
179 demo->nextev = ev;
|
nuclear@6
|
180 }
|
nuclear@6
|
181
|
nuclear@6
|
182 static void proc_event(struct dsys_event *ev, demotime_t tm)
|
nuclear@6
|
183 {
|
nuclear@6
|
184 float val = ev->eval(ev, tm);
|
nuclear@6
|
185
|
nuclear@6
|
186 if(ev->val != val) {
|
nuclear@6
|
187 struct callback *cb = ev->cblist;
|
nuclear@6
|
188
|
nuclear@6
|
189 while(cb) {
|
nuclear@6
|
190 cb->func(ev, cb->cls);
|
nuclear@6
|
191 cb = cb->next;
|
nuclear@6
|
192 }
|
nuclear@6
|
193 ev->val = val;
|
nuclear@6
|
194 }
|
nuclear@2
|
195 }
|
nuclear@2
|
196
|
nuclear@2
|
197 void dsys_start(struct dsys_demo *demo)
|
nuclear@2
|
198 {
|
nuclear@2
|
199 if(demo->running) {
|
nuclear@2
|
200 return;
|
nuclear@2
|
201 }
|
nuclear@2
|
202
|
nuclear@2
|
203 if(demo->start_tm == -1) {
|
nuclear@2
|
204 demo->start_tm = demo->src_tm;
|
nuclear@6
|
205 demo->nextev = demo->active = demo->evlist;
|
nuclear@2
|
206 } else {
|
nuclear@2
|
207 demo->stoppage_tm += demo->src_tm - demo->stop_tm;
|
nuclear@2
|
208 }
|
nuclear@2
|
209
|
nuclear@2
|
210 demo->running = 1;
|
nuclear@2
|
211 }
|
nuclear@2
|
212
|
nuclear@2
|
213 void dsys_stop(struct dsys_demo *demo)
|
nuclear@2
|
214 {
|
nuclear@2
|
215 if(!demo->running) {
|
nuclear@2
|
216 return;
|
nuclear@2
|
217 }
|
nuclear@2
|
218
|
nuclear@2
|
219 demo->stop_tm = demo->src_tm;
|
nuclear@2
|
220 demo->running = 0;
|
nuclear@2
|
221 }
|
nuclear@2
|
222
|
nuclear@2
|
223 int dsys_is_running(struct dsys_demo *demo)
|
nuclear@2
|
224 {
|
nuclear@2
|
225 return demo->running;
|
nuclear@2
|
226 }
|
nuclear@2
|
227
|
nuclear@2
|
228
|
nuclear@2
|
229 demotime_t dsys_duration(struct dsys_demo *demo)
|
nuclear@2
|
230 {
|
nuclear@2
|
231 return demo->duration;
|
nuclear@2
|
232 }
|
nuclear@2
|
233
|
nuclear@2
|
234 demotime_t dsys_time(struct dsys_demo *demo)
|
nuclear@2
|
235 {
|
nuclear@2
|
236 return demo->tm;
|
nuclear@2
|
237 }
|
nuclear@2
|
238
|
nuclear@2
|
239 float dsys_progress(struct dsys_demo *demo)
|
nuclear@2
|
240 {
|
nuclear@2
|
241 return demo->tm / demo->duration;
|
nuclear@2
|
242 }
|
nuclear@2
|
243
|
nuclear@2
|
244 /* seek without continuity */
|
nuclear@2
|
245 void dsys_seek(struct dsys_demo *demo, demotime_t tm)
|
nuclear@2
|
246 {
|
nuclear@6
|
247 demo->start_tm = demo->src_tm - tm;
|
nuclear@6
|
248 demo->stoppage_tm = 0;
|
nuclear@2
|
249 }
|
nuclear@2
|
250
|
nuclear@2
|
251 void dsys_seek_norm(struct dsys_demo *demo, float t)
|
nuclear@2
|
252 {
|
nuclear@2
|
253 dsys_seek(demo, t * demo->duration);
|
nuclear@2
|
254 }
|
nuclear@2
|
255
|
nuclear@2
|
256 /* seek by accelerating time */
|
nuclear@6
|
257 void dsys_warp(struct dsys_demo *demo, demotime_t tm)
|
nuclear@6
|
258 {
|
nuclear@6
|
259 fprintf(stderr, "dsys_warp not implemented yet\n");
|
nuclear@6
|
260 }
|
nuclear@6
|
261
|
nuclear@6
|
262 void dsys_warp_norm(struct dsys_demo *demo, float t)
|
nuclear@6
|
263 {
|
nuclear@6
|
264 dsys_warp(demo, t * demo->duration);
|
nuclear@6
|
265 }
|
nuclear@2
|
266
|
nuclear@2
|
267
|
nuclear@2
|
268 /* events */
|
nuclear@5
|
269 struct dsys_event *dsys_event(struct dsys_demo *demo, const char *name)
|
nuclear@5
|
270 {
|
nuclear@5
|
271 struct dsys_event *iter = demo->evlist;
|
nuclear@2
|
272
|
nuclear@5
|
273 while(iter) {
|
nuclear@5
|
274 if(strcmp(iter->name, name) == 0) {
|
nuclear@5
|
275 return iter;
|
nuclear@5
|
276 }
|
nuclear@5
|
277 iter = iter->next;
|
nuclear@5
|
278 }
|
nuclear@5
|
279 return 0;
|
nuclear@5
|
280 }
|
nuclear@2
|
281
|
nuclear@5
|
282 enum dsys_evtype dsys_event_type(struct dsys_event *ev)
|
nuclear@5
|
283 {
|
nuclear@5
|
284 return ev->type;
|
nuclear@5
|
285 }
|
nuclear@5
|
286
|
nuclear@5
|
287 float dsys_event_value(struct dsys_event *ev)
|
nuclear@5
|
288 {
|
nuclear@6
|
289 return ev->val;
|
nuclear@5
|
290 }
|
nuclear@5
|
291
|
nuclear@6
|
292 int dsys_event_callback(struct dsys_event *ev, void (*func)(struct dsys_event*, void*), void *cls)
|
nuclear@5
|
293 {
|
nuclear@6
|
294 struct callback *cb;
|
nuclear@6
|
295
|
nuclear@6
|
296 if(!(cb = malloc(sizeof *cb))) {
|
nuclear@6
|
297 perror("failed to allocate memory");
|
nuclear@6
|
298 return -1;
|
nuclear@6
|
299 }
|
nuclear@6
|
300 cb->func = func;
|
nuclear@6
|
301 cb->cls = cls;
|
nuclear@6
|
302 cb->next = ev->cblist;
|
nuclear@6
|
303 ev->cblist = cb;
|
nuclear@6
|
304 return 0;
|
nuclear@5
|
305 }
|
nuclear@5
|
306
|
nuclear@6
|
307 int dsys_event_link(struct dsys_event *ev, float *link)
|
nuclear@6
|
308 {
|
nuclear@6
|
309 return dsys_event_callback(ev, link_callback, link);
|
nuclear@6
|
310 }
|
nuclear@6
|
311
|
nuclear@6
|
312 static void link_callback(struct dsys_event *ev, void *cls)
|
nuclear@6
|
313 {
|
nuclear@6
|
314 *(float*)cls = ev->val;
|
nuclear@6
|
315 }
|
nuclear@2
|
316
|
nuclear@2
|
317
|
nuclear@2
|
318 /* time conversion */
|
nuclear@2
|
319 demotime_t dsys_sec_to_dtime(float sec)
|
nuclear@2
|
320 {
|
nuclear@2
|
321 return sec;
|
nuclear@2
|
322 }
|
nuclear@2
|
323
|
nuclear@2
|
324 demotime_t dsys_msec_to_dtime(unsigned long msec)
|
nuclear@2
|
325 {
|
nuclear@2
|
326 return (demotime_t)msec / 1000.0;
|
nuclear@2
|
327 }
|
nuclear@2
|
328
|
nuclear@2
|
329 float dsys_dtime_to_sec(demotime_t tm)
|
nuclear@2
|
330 {
|
nuclear@2
|
331 return tm;
|
nuclear@2
|
332 }
|
nuclear@2
|
333
|
nuclear@2
|
334 unsigned long dsys_dtime_to_msec(demotime_t tm)
|
nuclear@2
|
335 {
|
nuclear@2
|
336 return (unsigned long)(tm * 1000.0);
|
nuclear@2
|
337 }
|
nuclear@2
|
338
|
nuclear@2
|
339
|
nuclear@5
|
340 float dsys_eval_step(struct dsys_event *ev, demotime_t t)
|
nuclear@2
|
341 {
|
nuclear@2
|
342 return t >= ev->t1 ? 1.0 : 0.0;
|
nuclear@2
|
343 }
|
nuclear@2
|
344
|
nuclear@5
|
345 float dsys_eval_lerp(struct dsys_event *ev, demotime_t t)
|
nuclear@2
|
346 {
|
nuclear@2
|
347 return (t - ev->t0) / (ev->t1 - ev->t0);
|
nuclear@2
|
348 }
|
nuclear@2
|
349
|
nuclear@5
|
350 float dsys_eval_sigmoid(struct dsys_event *ev, demotime_t t)
|
nuclear@2
|
351 {
|
nuclear@5
|
352 t = dsys_eval_lerp(ev, t);
|
nuclear@2
|
353 return 1.0 - (cos(t * M_PI) * 0.5 + 0.5);
|
nuclear@2
|
354 }
|
nuclear@2
|
355
|
nuclear@2
|
356 static void free_event(struct dsys_event *ev)
|
nuclear@2
|
357 {
|
nuclear@2
|
358 while(ev->cblist) {
|
nuclear@2
|
359 struct callback *cb = ev->cblist;
|
nuclear@2
|
360 ev->cblist = ev->cblist->next;
|
nuclear@2
|
361 free(cb);
|
nuclear@2
|
362 }
|
nuclear@2
|
363 }
|
nuclear@4
|
364
|
nuclear@4
|
365 static struct dsys_event *sort_evlist(struct dsys_event *list, int num_ev)
|
nuclear@4
|
366 {
|
nuclear@4
|
367 int i, num_left, num_right;
|
nuclear@4
|
368 struct dsys_event *left, *right, *node = list;
|
nuclear@4
|
369
|
nuclear@4
|
370 if(num_ev < 2) {
|
nuclear@4
|
371 return list;
|
nuclear@4
|
372 }
|
nuclear@4
|
373
|
nuclear@4
|
374 num_left = num_ev / 2;
|
nuclear@4
|
375 num_right = num_ev - num_left;
|
nuclear@4
|
376
|
nuclear@4
|
377 for(i=0; i<num_ev/2; i++) {
|
nuclear@4
|
378 node = node->next;
|
nuclear@4
|
379 }
|
nuclear@4
|
380
|
nuclear@4
|
381 if(node->prev) {
|
nuclear@4
|
382 node->prev->next = 0;
|
nuclear@4
|
383 node->prev = 0;
|
nuclear@4
|
384 }
|
nuclear@4
|
385
|
nuclear@4
|
386 left = sort_evlist(list, num_left);
|
nuclear@4
|
387 right = sort_evlist(node, num_right);
|
nuclear@4
|
388
|
nuclear@4
|
389 return merge_evlists(left, right);
|
nuclear@4
|
390 }
|
nuclear@4
|
391
|
nuclear@4
|
392 static struct dsys_event *merge_evlists(struct dsys_event *list1, struct dsys_event *list2)
|
nuclear@4
|
393 {
|
nuclear@4
|
394 struct dsys_event *head, *tail, *node;
|
nuclear@4
|
395
|
nuclear@4
|
396 if(!list1) {
|
nuclear@4
|
397 return list2;
|
nuclear@4
|
398 }
|
nuclear@4
|
399 if(!list2) {
|
nuclear@4
|
400 return list1;
|
nuclear@4
|
401 }
|
nuclear@4
|
402
|
nuclear@4
|
403 head = tail = 0;
|
nuclear@4
|
404
|
nuclear@4
|
405 while(list1 && list2) {
|
nuclear@4
|
406 if(list1->t0 < list2->t0) {
|
nuclear@4
|
407 node = list1;
|
nuclear@4
|
408 list1 = list1->next;
|
nuclear@4
|
409 } else {
|
nuclear@4
|
410 node = list2;
|
nuclear@4
|
411 list2 = list2->next;
|
nuclear@4
|
412 }
|
nuclear@4
|
413
|
nuclear@4
|
414 node->next = 0;
|
nuclear@4
|
415 node->prev = tail;
|
nuclear@4
|
416
|
nuclear@4
|
417 if(!head) {
|
nuclear@4
|
418 head = node;
|
nuclear@4
|
419 } else {
|
nuclear@4
|
420 tail->next = node;
|
nuclear@4
|
421 }
|
nuclear@4
|
422 tail = node;
|
nuclear@4
|
423 }
|
nuclear@4
|
424
|
nuclear@4
|
425 if(list1) {
|
nuclear@4
|
426 tail->next = list1;
|
nuclear@4
|
427 list1->prev = tail;
|
nuclear@4
|
428 } else if(list2) {
|
nuclear@4
|
429 tail->next = list2;
|
nuclear@4
|
430 list2->prev = tail;
|
nuclear@4
|
431 }
|
nuclear@4
|
432
|
nuclear@4
|
433 return head;
|
nuclear@4
|
434 }
|