dsys2

annotate src/dsys.c @ 8:4ad7a01c4ff5

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