dbf-udg

view libs/dsys2/dsys.c @ 11:5f99c4c7a9fe

now it looks pretty much ok
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 20 Feb 2013 04:55:03 +0200
parents 7056437a361b
children 1abbed71e9c9
line source
1 #include <stdio.h>
2 #include <math.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <ctype.h>
6 #include <errno.h>
7 #include "dsys.h"
8 #include "dsys_impl.h"
10 static int read_script(struct dsys_demo *demo, FILE *fp, const char *fname);
11 static char *strip_ws(char *buf);
12 static void dbg_print_events(struct dsys_event *ev);
14 static void proc_event(struct dsys_event *ev, demotime_t tm);
15 static void link_callback(struct dsys_event *ev, void *cls);
16 static void free_event(struct dsys_event *ev);
18 static struct dsys_event *sort_evlist(struct dsys_event *list, int num_ev);
19 static struct dsys_event *merge_evlists(struct dsys_event *list1, struct dsys_event *list2);
22 struct dsys_demo *dsys_open(const char *fname)
23 {
24 FILE *fp;
25 struct dsys_demo *demo;
27 if(!(fp = fopen(fname, "r"))) {
28 fprintf(stderr, "failed to open demoscript: %s: %s\n", fname, strerror(errno));
29 return 0;
30 }
32 if(!(demo = malloc(sizeof *demo))) {
33 perror("failed to allocate memory");
34 fclose(fp);
35 return 0;
36 }
37 memset(demo, 0, sizeof *demo);
39 demo->src_tm = demo->start_tm = -1;
41 if(read_script(demo, fp, fname) == -1) {
42 free(demo);
43 fclose(fp);
44 return 0;
45 }
47 fclose(fp);
48 return demo;
49 }
51 struct dsys_demo *dsys_open_stream(FILE *fp)
52 {
53 struct dsys_demo *demo;
55 if(!(demo = malloc(sizeof *demo))) {
56 perror("failed to allocate memory");
57 return 0;
58 }
59 memset(demo, 0, sizeof *demo);
61 demo->src_tm = demo->start_tm = -1;
63 if(read_script(demo, fp, 0) == -1) {
64 free(demo);
65 return 0;
66 }
68 return demo;
69 }
71 void dsys_close(struct dsys_demo *demo)
72 {
73 while(demo->evlist) {
74 struct dsys_event *ev = demo->evlist;
75 demo->evlist = demo->evlist->next;
76 free_event(ev);
77 }
79 free(demo);
80 }
83 #define SEP " \t\n\r"
85 static int read_script(struct dsys_demo *demo, FILE *fp, const char *fname)
86 {
87 int nline = 0;
88 char buf[512], *line, *tok, *endp;
89 unsigned int t0, t1;
90 struct dsys_event *ev;
92 if(!fname) {
93 fname = "<unknown>";
94 }
96 demo->duration = dsys_msec_to_dtime(0);
98 while(fgets(buf, sizeof buf, fp)) {
99 nline++;
101 line = strip_ws(buf);
103 if(!line || !*line) {
104 continue;
105 }
107 if(!(tok = strtok(line, SEP)) || (t0 = strtol(tok, &endp, 10), endp == tok)) {
108 fprintf(stderr, "%s line: %d, error: expected timestamp t0\n", fname, nline);
109 return -1;
110 }
112 if(!(tok = strtok(0, SEP))) {
113 fprintf(stderr, "%s line: %d, error: expected second timestamp or event name\n", fname, nline);
114 return -1;
115 }
117 t1 = strtol(tok, &endp, 10);
118 if(endp == tok) {
119 t1 = t0;
120 } else {
121 if(!(tok = strtok(0, SEP))) {
122 fprintf(stderr, "%s line: %d, error: expected event name\n", fname, nline);
123 return -1;
124 }
125 }
127 if(!(ev = malloc(sizeof *ev))) {
128 perror("read_script: failed to allocate memory for an event\n");
129 return -1;
130 }
131 memset(ev, 0, sizeof *ev);
132 ev->t0 = dsys_msec_to_dtime(t0);
133 ev->t1 = dsys_msec_to_dtime(t1);
135 if(!(ev->name = malloc(strlen(tok) + 1))) {
136 free(ev);
137 fprintf(stderr, "read_script: failed to allocate memory for the event name: %s\n", tok);
138 return -1;
139 }
140 strcpy(ev->name, tok);
142 ev->eval = t0 == t1 ? dsys_eval_step : dsys_eval_lerp;
144 ev->next = demo->evlist;
145 ev->prev = 0;
146 if(demo->evlist) {
147 demo->evlist->prev = ev;
148 }
149 demo->evlist = ev;
150 demo->num_ev++;
152 if(ev->t1 > demo->duration) {
153 demo->duration = ev->t1;
154 }
155 }
157 demo->evlist = sort_evlist(demo->evlist, demo->num_ev);
159 /*dbg_print_events(demo->evlist);*/
161 return 0;
162 }
164 static char *strip_ws(char *buf)
165 {
166 char *ptr;
168 while(isspace(*buf)) {
169 buf++;
170 }
172 ptr = buf;
173 while(*ptr) {
174 if(*ptr == '\n' || *ptr == '\r' || *ptr == '#') {
175 *ptr = 0;
176 break;
177 }
178 ptr++;
179 }
181 return buf;
182 }
184 static void dbg_print_events(struct dsys_event *ev)
185 {
186 int i;
188 for(i=0; ev; i++) {
189 printf("%02d - %s (%f -> %f) [%s]\n", i, ev->eval == dsys_eval_step ? "step" : "lerp",
190 ev->t0, ev->t1, ev->name);
191 ev = ev->next;
192 }
193 }
195 void dsys_update(struct dsys_demo *demo, demotime_t tm)
196 {
197 struct dsys_event *ev;
199 demo->src_tm = tm;
201 if(demo->start_tm == -1) {
202 dsys_start(demo);
203 }
205 if(!demo->running) {
206 return; /* nothing changes */
207 }
209 demo->tm = tm - demo->start_tm - demo->stoppage_tm;
211 if(demo->tm < 0) {
212 demo->tm = 0;
213 }
214 if(demo->tm > demo->duration) {
215 demo->tm = demo->duration;
216 }
218 while(demo->active && demo->active->t1 <= demo->tm) {
219 proc_event(demo->active, demo->tm);
220 demo->active = demo->active->next;
221 }
223 ev = demo->active;
224 while(ev && ev->t0 <= demo->tm) {
225 proc_event(ev, demo->tm);
226 ev = ev->next;
227 }
228 demo->nextev = ev;
231 if(demo->tm >= demo->duration) {
232 dsys_stop(demo);
233 }
234 }
236 static void proc_event(struct dsys_event *ev, demotime_t tm)
237 {
238 float val = ev->eval(ev, tm);
240 if(ev->val != val) {
241 struct callback *cb = ev->cblist;
243 ev->val = val;
245 while(cb) {
246 cb->func(ev, cb->cls);
247 cb = cb->next;
248 }
249 }
250 }
252 void dsys_start(struct dsys_demo *demo)
253 {
254 if(demo->running) {
255 return;
256 }
258 if(demo->start_tm == -1) {
259 demo->start_tm = demo->src_tm;
260 demo->nextev = demo->active = demo->evlist;
261 } else {
262 demo->stoppage_tm += demo->src_tm - demo->stop_tm;
263 }
265 demo->running = 1;
266 }
268 void dsys_stop(struct dsys_demo *demo)
269 {
270 if(!demo->running) {
271 return;
272 }
274 demo->stop_tm = demo->src_tm;
275 demo->running = 0;
276 }
278 int dsys_is_running(struct dsys_demo *demo)
279 {
280 return demo->running;
281 }
284 demotime_t dsys_duration(struct dsys_demo *demo)
285 {
286 return demo->duration;
287 }
289 demotime_t dsys_time(struct dsys_demo *demo)
290 {
291 return demo->tm;
292 }
294 float dsys_progress(struct dsys_demo *demo)
295 {
296 return demo->tm / demo->duration;
297 }
299 /* seek without continuity */
300 void dsys_seek(struct dsys_demo *demo, demotime_t tm)
301 {
302 struct dsys_event *ev;
304 if(tm < 0) {
305 tm = 0;
306 }
307 if(tm > demo->duration) {
308 tm = demo->duration;
309 }
311 if(tm < demo->tm) {
312 /* on backwards seek, invalidate the sliding window */
313 demo->nextev = demo->active = demo->evlist;
314 }
316 demo->start_tm = demo->src_tm - tm;
317 demo->stoppage_tm = 0;
318 demo->stop_tm = demo->src_tm;
319 demo->tm = tm;
321 /* recalculate events */
322 ev = demo->evlist;
323 while(ev) {
324 proc_event(ev, tm);
325 ev = ev->next;
326 }
327 }
329 void dsys_seek_norm(struct dsys_demo *demo, float t)
330 {
331 dsys_seek(demo, t * demo->duration);
332 }
334 /* seek by accelerating time */
335 void dsys_warp(struct dsys_demo *demo, demotime_t tm)
336 {
337 fprintf(stderr, "dsys_warp not implemented yet\n");
338 }
340 void dsys_warp_norm(struct dsys_demo *demo, float t)
341 {
342 dsys_warp(demo, t * demo->duration);
343 }
346 /* events */
347 struct dsys_event *dsys_event(struct dsys_demo *demo, const char *name)
348 {
349 struct dsys_event *iter = demo->evlist;
351 while(iter) {
352 if(strcmp(iter->name, name) == 0) {
353 return iter;
354 }
355 iter = iter->next;
356 }
357 return 0;
358 }
360 void dsys_set_event_eval(struct dsys_event *ev, float (*eval)(struct dsys_event*, demotime_t))
361 {
362 ev->eval = eval;
363 }
365 enum dsys_evtype dsys_event_type(struct dsys_event *ev)
366 {
367 return ev->type;
368 }
370 float dsys_event_value(struct dsys_event *ev)
371 {
372 return ev->val;
373 }
375 int dsys_event_callback(struct dsys_event *ev, void (*func)(struct dsys_event*, void*), void *cls)
376 {
377 struct callback *cb;
379 if(!(cb = malloc(sizeof *cb))) {
380 perror("failed to allocate memory");
381 return -1;
382 }
383 cb->func = func;
384 cb->cls = cls;
385 cb->next = ev->cblist;
386 ev->cblist = cb;
387 return 0;
388 }
390 int dsys_event_link(struct dsys_event *ev, float *link)
391 {
392 return dsys_event_callback(ev, link_callback, link);
393 }
395 static void link_callback(struct dsys_event *ev, void *cls)
396 {
397 *(float*)cls = ev->val;
398 }
401 /* time conversion */
402 demotime_t dsys_sec_to_dtime(float sec)
403 {
404 return sec;
405 }
407 demotime_t dsys_msec_to_dtime(unsigned long msec)
408 {
409 return (demotime_t)msec / 1000.0;
410 }
412 float dsys_dtime_to_sec(demotime_t tm)
413 {
414 return tm;
415 }
417 unsigned long dsys_dtime_to_msec(demotime_t tm)
418 {
419 return (unsigned long)(tm * 1000.0);
420 }
423 float dsys_eval_step(struct dsys_event *ev, demotime_t t)
424 {
425 return t >= ev->t1 ? 1.0 : 0.0;
426 }
428 #define CLAMP(x, low, high) ((x) < (low) ? (low) : ((x) > (high) ? (high) : (x)))
430 float dsys_eval_lerp(struct dsys_event *ev, demotime_t t)
431 {
432 float res = (t - ev->t0) / (ev->t1 - ev->t0);
433 return CLAMP(res, 0.0, 1.0);
434 }
436 float dsys_eval_sigmoid(struct dsys_event *ev, demotime_t t)
437 {
438 t = dsys_eval_lerp(ev, t);
439 return 1.0 - (cos(t * M_PI) * 0.5 + 0.5);
440 }
442 static void free_event(struct dsys_event *ev)
443 {
444 while(ev->cblist) {
445 struct callback *cb = ev->cblist;
446 ev->cblist = ev->cblist->next;
447 free(cb);
448 }
449 }
451 static struct dsys_event *sort_evlist(struct dsys_event *list, int num_ev)
452 {
453 int i, num_left, num_right;
454 struct dsys_event *left, *right, *node = list;
456 if(num_ev < 2) {
457 return list;
458 }
460 num_left = num_ev / 2;
461 num_right = num_ev - num_left;
463 for(i=0; i<num_ev/2; i++) {
464 node = node->next;
465 }
467 if(node->prev) {
468 node->prev->next = 0;
469 node->prev = 0;
470 }
472 left = sort_evlist(list, num_left);
473 right = sort_evlist(node, num_right);
475 return merge_evlists(left, right);
476 }
478 static struct dsys_event *merge_evlists(struct dsys_event *list1, struct dsys_event *list2)
479 {
480 struct dsys_event *head, *tail, *node;
482 if(!list1) {
483 return list2;
484 }
485 if(!list2) {
486 return list1;
487 }
489 head = tail = 0;
491 while(list1 && list2) {
492 if(list1->t0 < list2->t0) {
493 node = list1;
494 list1 = list1->next;
495 } else {
496 node = list2;
497 list2 = list2->next;
498 }
500 node->next = 0;
501 node->prev = tail;
503 if(!head) {
504 head = node;
505 } else {
506 tail->next = node;
507 }
508 tail = node;
509 }
511 if(list1) {
512 tail->next = list1;
513 list1->prev = tail;
514 } else if(list2) {
515 tail->next = list2;
516 list2->prev = tail;
517 }
519 return head;
520 }