dsys2

annotate src/dsys.c @ 7:3258d163cfbc

hurray it seems like working for the most part
author John Tsiombikas <nuclear@siggraph.org>
date Fri, 02 Sep 2011 08:14:40 +0300
parents 80f86f0f67ec
children 4ad7a01c4ff5
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@7 300 if(tm < 0) {
nuclear@7 301 tm = 0;
nuclear@7 302 }
nuclear@7 303 if(tm > demo->duration) {
nuclear@7 304 tm = demo->duration;
nuclear@7 305 }
nuclear@7 306
nuclear@6 307 demo->start_tm = demo->src_tm - tm;
nuclear@6 308 demo->stoppage_tm = 0;
nuclear@2 309 }
nuclear@2 310
nuclear@2 311 void dsys_seek_norm(struct dsys_demo *demo, float t)
nuclear@2 312 {
nuclear@2 313 dsys_seek(demo, t * demo->duration);
nuclear@2 314 }
nuclear@2 315
nuclear@2 316 /* seek by accelerating time */
nuclear@6 317 void dsys_warp(struct dsys_demo *demo, demotime_t tm)
nuclear@6 318 {
nuclear@6 319 fprintf(stderr, "dsys_warp not implemented yet\n");
nuclear@6 320 }
nuclear@6 321
nuclear@6 322 void dsys_warp_norm(struct dsys_demo *demo, float t)
nuclear@6 323 {
nuclear@6 324 dsys_warp(demo, t * demo->duration);
nuclear@6 325 }
nuclear@2 326
nuclear@2 327
nuclear@2 328 /* events */
nuclear@5 329 struct dsys_event *dsys_event(struct dsys_demo *demo, const char *name)
nuclear@5 330 {
nuclear@5 331 struct dsys_event *iter = demo->evlist;
nuclear@2 332
nuclear@5 333 while(iter) {
nuclear@5 334 if(strcmp(iter->name, name) == 0) {
nuclear@5 335 return iter;
nuclear@5 336 }
nuclear@5 337 iter = iter->next;
nuclear@5 338 }
nuclear@5 339 return 0;
nuclear@5 340 }
nuclear@2 341
nuclear@5 342 enum dsys_evtype dsys_event_type(struct dsys_event *ev)
nuclear@5 343 {
nuclear@5 344 return ev->type;
nuclear@5 345 }
nuclear@5 346
nuclear@5 347 float dsys_event_value(struct dsys_event *ev)
nuclear@5 348 {
nuclear@6 349 return ev->val;
nuclear@5 350 }
nuclear@5 351
nuclear@6 352 int dsys_event_callback(struct dsys_event *ev, void (*func)(struct dsys_event*, void*), void *cls)
nuclear@5 353 {
nuclear@6 354 struct callback *cb;
nuclear@6 355
nuclear@6 356 if(!(cb = malloc(sizeof *cb))) {
nuclear@6 357 perror("failed to allocate memory");
nuclear@6 358 return -1;
nuclear@6 359 }
nuclear@6 360 cb->func = func;
nuclear@6 361 cb->cls = cls;
nuclear@6 362 cb->next = ev->cblist;
nuclear@6 363 ev->cblist = cb;
nuclear@6 364 return 0;
nuclear@5 365 }
nuclear@5 366
nuclear@6 367 int dsys_event_link(struct dsys_event *ev, float *link)
nuclear@6 368 {
nuclear@6 369 return dsys_event_callback(ev, link_callback, link);
nuclear@6 370 }
nuclear@6 371
nuclear@6 372 static void link_callback(struct dsys_event *ev, void *cls)
nuclear@6 373 {
nuclear@6 374 *(float*)cls = ev->val;
nuclear@6 375 }
nuclear@2 376
nuclear@2 377
nuclear@2 378 /* time conversion */
nuclear@2 379 demotime_t dsys_sec_to_dtime(float sec)
nuclear@2 380 {
nuclear@2 381 return sec;
nuclear@2 382 }
nuclear@2 383
nuclear@2 384 demotime_t dsys_msec_to_dtime(unsigned long msec)
nuclear@2 385 {
nuclear@2 386 return (demotime_t)msec / 1000.0;
nuclear@2 387 }
nuclear@2 388
nuclear@2 389 float dsys_dtime_to_sec(demotime_t tm)
nuclear@2 390 {
nuclear@2 391 return tm;
nuclear@2 392 }
nuclear@2 393
nuclear@2 394 unsigned long dsys_dtime_to_msec(demotime_t tm)
nuclear@2 395 {
nuclear@2 396 return (unsigned long)(tm * 1000.0);
nuclear@2 397 }
nuclear@2 398
nuclear@2 399
nuclear@5 400 float dsys_eval_step(struct dsys_event *ev, demotime_t t)
nuclear@2 401 {
nuclear@2 402 return t >= ev->t1 ? 1.0 : 0.0;
nuclear@2 403 }
nuclear@2 404
nuclear@7 405 #define CLAMP(x, low, high) ((x) < (low) ? (low) : ((x) > (high) ? (high) : (x)))
nuclear@7 406
nuclear@5 407 float dsys_eval_lerp(struct dsys_event *ev, demotime_t t)
nuclear@2 408 {
nuclear@7 409 float res = (t - ev->t0) / (ev->t1 - ev->t0);
nuclear@7 410 return CLAMP(res, 0.0, 1.0);
nuclear@2 411 }
nuclear@2 412
nuclear@5 413 float dsys_eval_sigmoid(struct dsys_event *ev, demotime_t t)
nuclear@2 414 {
nuclear@5 415 t = dsys_eval_lerp(ev, t);
nuclear@2 416 return 1.0 - (cos(t * M_PI) * 0.5 + 0.5);
nuclear@2 417 }
nuclear@2 418
nuclear@2 419 static void free_event(struct dsys_event *ev)
nuclear@2 420 {
nuclear@2 421 while(ev->cblist) {
nuclear@2 422 struct callback *cb = ev->cblist;
nuclear@2 423 ev->cblist = ev->cblist->next;
nuclear@2 424 free(cb);
nuclear@2 425 }
nuclear@2 426 }
nuclear@4 427
nuclear@4 428 static struct dsys_event *sort_evlist(struct dsys_event *list, int num_ev)
nuclear@4 429 {
nuclear@4 430 int i, num_left, num_right;
nuclear@4 431 struct dsys_event *left, *right, *node = list;
nuclear@4 432
nuclear@4 433 if(num_ev < 2) {
nuclear@4 434 return list;
nuclear@4 435 }
nuclear@4 436
nuclear@4 437 num_left = num_ev / 2;
nuclear@4 438 num_right = num_ev - num_left;
nuclear@4 439
nuclear@4 440 for(i=0; i<num_ev/2; i++) {
nuclear@4 441 node = node->next;
nuclear@4 442 }
nuclear@4 443
nuclear@4 444 if(node->prev) {
nuclear@4 445 node->prev->next = 0;
nuclear@4 446 node->prev = 0;
nuclear@4 447 }
nuclear@4 448
nuclear@4 449 left = sort_evlist(list, num_left);
nuclear@4 450 right = sort_evlist(node, num_right);
nuclear@4 451
nuclear@4 452 return merge_evlists(left, right);
nuclear@4 453 }
nuclear@4 454
nuclear@4 455 static struct dsys_event *merge_evlists(struct dsys_event *list1, struct dsys_event *list2)
nuclear@4 456 {
nuclear@4 457 struct dsys_event *head, *tail, *node;
nuclear@4 458
nuclear@4 459 if(!list1) {
nuclear@4 460 return list2;
nuclear@4 461 }
nuclear@4 462 if(!list2) {
nuclear@4 463 return list1;
nuclear@4 464 }
nuclear@4 465
nuclear@4 466 head = tail = 0;
nuclear@4 467
nuclear@4 468 while(list1 && list2) {
nuclear@4 469 if(list1->t0 < list2->t0) {
nuclear@4 470 node = list1;
nuclear@4 471 list1 = list1->next;
nuclear@4 472 } else {
nuclear@4 473 node = list2;
nuclear@4 474 list2 = list2->next;
nuclear@4 475 }
nuclear@4 476
nuclear@4 477 node->next = 0;
nuclear@4 478 node->prev = tail;
nuclear@4 479
nuclear@4 480 if(!head) {
nuclear@4 481 head = node;
nuclear@4 482 } else {
nuclear@4 483 tail->next = node;
nuclear@4 484 }
nuclear@4 485 tail = node;
nuclear@4 486 }
nuclear@4 487
nuclear@4 488 if(list1) {
nuclear@4 489 tail->next = list1;
nuclear@4 490 list1->prev = tail;
nuclear@4 491 } else if(list2) {
nuclear@4 492 tail->next = list2;
nuclear@4 493 list2->prev = tail;
nuclear@4 494 }
nuclear@4 495
nuclear@4 496 return head;
nuclear@4 497 }