dbf-halloween2015

annotate src/dsys/dsys.c @ 0:50683c78264e

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