dsys2

view src/dsys.c @ 6:80f86f0f67ec

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