dsys2

annotate src/dsys.c @ 13:6bab2c0b0e4b

- added a shared library rule - changed all the names from dsys2 to dsys
author John Tsiombikas <nuclear@mutantstargoat.com>
date Mon, 05 Sep 2011 04:08:40 +0300
parents d7d173fcd44e
children 26e3e0359f5b
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@13 7 #include "dsys.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@10 131 memset(ev, 0, sizeof *ev);
nuclear@7 132 ev->t0 = dsys_msec_to_dtime(t0);
nuclear@7 133 ev->t1 = dsys_msec_to_dtime(t1);
nuclear@3 134
nuclear@3 135 if(!(ev->name = malloc(strlen(tok) + 1))) {
nuclear@3 136 free(ev);
nuclear@5 137 fprintf(stderr, "read_script: failed to allocate memory for the event name: %s\n", tok);
nuclear@3 138 return -1;
nuclear@3 139 }
nuclear@4 140 strcpy(ev->name, tok);
nuclear@4 141
nuclear@6 142 ev->eval = t0 == t1 ? dsys_eval_step : dsys_eval_lerp;
nuclear@4 143
nuclear@4 144 ev->next = demo->evlist;
nuclear@4 145 ev->prev = 0;
nuclear@4 146 if(demo->evlist) {
nuclear@4 147 demo->evlist->prev = ev;
nuclear@4 148 }
nuclear@4 149 demo->evlist = ev;
nuclear@4 150 demo->num_ev++;
nuclear@7 151
nuclear@7 152 if(ev->t1 > demo->duration) {
nuclear@7 153 demo->duration = ev->t1;
nuclear@7 154 }
nuclear@3 155 }
nuclear@3 156
nuclear@4 157 demo->evlist = sort_evlist(demo->evlist, demo->num_ev);
nuclear@4 158
nuclear@10 159 /*dbg_print_events(demo->evlist);*/
nuclear@7 160
nuclear@3 161 return 0;
nuclear@3 162 }
nuclear@3 163
nuclear@7 164 static char *strip_ws(char *buf)
nuclear@7 165 {
nuclear@7 166 char *ptr;
nuclear@7 167
nuclear@7 168 while(isspace(*buf)) {
nuclear@7 169 buf++;
nuclear@7 170 }
nuclear@7 171
nuclear@7 172 ptr = buf;
nuclear@7 173 while(*ptr) {
nuclear@7 174 if(*ptr == '\n' || *ptr == '\r' || *ptr == '#') {
nuclear@7 175 *ptr = 0;
nuclear@7 176 break;
nuclear@7 177 }
nuclear@7 178 ptr++;
nuclear@7 179 }
nuclear@7 180
nuclear@7 181 return buf;
nuclear@7 182 }
nuclear@7 183
nuclear@7 184 static void dbg_print_events(struct dsys_event *ev)
nuclear@7 185 {
nuclear@7 186 int i;
nuclear@7 187
nuclear@7 188 for(i=0; ev; i++) {
nuclear@7 189 printf("%02d - %s (%f -> %f) [%s]\n", i, ev->eval == dsys_eval_step ? "step" : "lerp",
nuclear@7 190 ev->t0, ev->t1, ev->name);
nuclear@7 191 ev = ev->next;
nuclear@7 192 }
nuclear@7 193 }
nuclear@3 194
nuclear@2 195 void dsys_update(struct dsys_demo *demo, demotime_t tm)
nuclear@2 196 {
nuclear@6 197 struct dsys_event *ev;
nuclear@6 198
nuclear@2 199 demo->src_tm = tm;
nuclear@2 200
nuclear@2 201 if(demo->start_tm == -1) {
nuclear@2 202 dsys_start(demo);
nuclear@2 203 }
nuclear@2 204
nuclear@12 205 if(!demo->running) {
nuclear@12 206 return; /* nothing changes */
nuclear@12 207 }
nuclear@12 208
nuclear@6 209 demo->tm = tm - demo->start_tm - demo->stoppage_tm;
nuclear@6 210
nuclear@7 211 if(demo->tm < 0) {
nuclear@7 212 demo->tm = 0;
nuclear@7 213 }
nuclear@7 214 if(demo->tm > demo->duration) {
nuclear@7 215 demo->tm = demo->duration;
nuclear@7 216 }
nuclear@7 217
nuclear@10 218 while(demo->active && demo->active->t1 <= demo->tm) {
nuclear@6 219 proc_event(demo->active, demo->tm);
nuclear@6 220 demo->active = demo->active->next;
nuclear@6 221 }
nuclear@6 222
nuclear@6 223 ev = demo->active;
nuclear@7 224 while(ev && ev->t0 <= demo->tm) {
nuclear@6 225 proc_event(ev, demo->tm);
nuclear@6 226 ev = ev->next;
nuclear@6 227 }
nuclear@6 228 demo->nextev = ev;
nuclear@7 229
nuclear@7 230
nuclear@7 231 if(demo->tm >= demo->duration) {
nuclear@7 232 dsys_stop(demo);
nuclear@7 233 }
nuclear@6 234 }
nuclear@6 235
nuclear@6 236 static void proc_event(struct dsys_event *ev, demotime_t tm)
nuclear@6 237 {
nuclear@6 238 float val = ev->eval(ev, tm);
nuclear@6 239
nuclear@6 240 if(ev->val != val) {
nuclear@6 241 struct callback *cb = ev->cblist;
nuclear@6 242
nuclear@10 243 ev->val = val;
nuclear@10 244
nuclear@6 245 while(cb) {
nuclear@6 246 cb->func(ev, cb->cls);
nuclear@6 247 cb = cb->next;
nuclear@6 248 }
nuclear@6 249 }
nuclear@2 250 }
nuclear@2 251
nuclear@2 252 void dsys_start(struct dsys_demo *demo)
nuclear@2 253 {
nuclear@2 254 if(demo->running) {
nuclear@2 255 return;
nuclear@2 256 }
nuclear@2 257
nuclear@2 258 if(demo->start_tm == -1) {
nuclear@2 259 demo->start_tm = demo->src_tm;
nuclear@6 260 demo->nextev = demo->active = demo->evlist;
nuclear@2 261 } else {
nuclear@2 262 demo->stoppage_tm += demo->src_tm - demo->stop_tm;
nuclear@2 263 }
nuclear@2 264
nuclear@2 265 demo->running = 1;
nuclear@2 266 }
nuclear@2 267
nuclear@2 268 void dsys_stop(struct dsys_demo *demo)
nuclear@2 269 {
nuclear@2 270 if(!demo->running) {
nuclear@2 271 return;
nuclear@2 272 }
nuclear@2 273
nuclear@2 274 demo->stop_tm = demo->src_tm;
nuclear@2 275 demo->running = 0;
nuclear@2 276 }
nuclear@2 277
nuclear@2 278 int dsys_is_running(struct dsys_demo *demo)
nuclear@2 279 {
nuclear@2 280 return demo->running;
nuclear@2 281 }
nuclear@2 282
nuclear@2 283
nuclear@2 284 demotime_t dsys_duration(struct dsys_demo *demo)
nuclear@2 285 {
nuclear@2 286 return demo->duration;
nuclear@2 287 }
nuclear@2 288
nuclear@2 289 demotime_t dsys_time(struct dsys_demo *demo)
nuclear@2 290 {
nuclear@2 291 return demo->tm;
nuclear@2 292 }
nuclear@2 293
nuclear@2 294 float dsys_progress(struct dsys_demo *demo)
nuclear@2 295 {
nuclear@2 296 return demo->tm / demo->duration;
nuclear@2 297 }
nuclear@2 298
nuclear@2 299 /* seek without continuity */
nuclear@2 300 void dsys_seek(struct dsys_demo *demo, demotime_t tm)
nuclear@2 301 {
nuclear@8 302 struct dsys_event *ev;
nuclear@8 303
nuclear@7 304 if(tm < 0) {
nuclear@7 305 tm = 0;
nuclear@7 306 }
nuclear@7 307 if(tm > demo->duration) {
nuclear@7 308 tm = demo->duration;
nuclear@7 309 }
nuclear@7 310
nuclear@10 311 if(tm < demo->tm) {
nuclear@10 312 /* on backwards seek, invalidate the sliding window */
nuclear@10 313 demo->nextev = demo->active = demo->evlist;
nuclear@10 314 }
nuclear@10 315
nuclear@6 316 demo->start_tm = demo->src_tm - tm;
nuclear@6 317 demo->stoppage_tm = 0;
nuclear@10 318 demo->stop_tm = demo->src_tm;
nuclear@10 319 demo->tm = tm;
nuclear@8 320
nuclear@8 321 /* recalculate events */
nuclear@8 322 ev = demo->evlist;
nuclear@8 323 while(ev) {
nuclear@8 324 proc_event(ev, tm);
nuclear@8 325 ev = ev->next;
nuclear@8 326 }
nuclear@2 327 }
nuclear@2 328
nuclear@2 329 void dsys_seek_norm(struct dsys_demo *demo, float t)
nuclear@2 330 {
nuclear@2 331 dsys_seek(demo, t * demo->duration);
nuclear@2 332 }
nuclear@2 333
nuclear@2 334 /* seek by accelerating time */
nuclear@6 335 void dsys_warp(struct dsys_demo *demo, demotime_t tm)
nuclear@6 336 {
nuclear@6 337 fprintf(stderr, "dsys_warp not implemented yet\n");
nuclear@6 338 }
nuclear@6 339
nuclear@6 340 void dsys_warp_norm(struct dsys_demo *demo, float t)
nuclear@6 341 {
nuclear@6 342 dsys_warp(demo, t * demo->duration);
nuclear@6 343 }
nuclear@2 344
nuclear@2 345
nuclear@2 346 /* events */
nuclear@5 347 struct dsys_event *dsys_event(struct dsys_demo *demo, const char *name)
nuclear@5 348 {
nuclear@5 349 struct dsys_event *iter = demo->evlist;
nuclear@2 350
nuclear@5 351 while(iter) {
nuclear@5 352 if(strcmp(iter->name, name) == 0) {
nuclear@5 353 return iter;
nuclear@5 354 }
nuclear@5 355 iter = iter->next;
nuclear@5 356 }
nuclear@5 357 return 0;
nuclear@5 358 }
nuclear@2 359
nuclear@5 360 enum dsys_evtype dsys_event_type(struct dsys_event *ev)
nuclear@5 361 {
nuclear@5 362 return ev->type;
nuclear@5 363 }
nuclear@5 364
nuclear@5 365 float dsys_event_value(struct dsys_event *ev)
nuclear@5 366 {
nuclear@6 367 return ev->val;
nuclear@5 368 }
nuclear@5 369
nuclear@6 370 int dsys_event_callback(struct dsys_event *ev, void (*func)(struct dsys_event*, void*), void *cls)
nuclear@5 371 {
nuclear@6 372 struct callback *cb;
nuclear@6 373
nuclear@6 374 if(!(cb = malloc(sizeof *cb))) {
nuclear@6 375 perror("failed to allocate memory");
nuclear@6 376 return -1;
nuclear@6 377 }
nuclear@6 378 cb->func = func;
nuclear@6 379 cb->cls = cls;
nuclear@6 380 cb->next = ev->cblist;
nuclear@6 381 ev->cblist = cb;
nuclear@6 382 return 0;
nuclear@5 383 }
nuclear@5 384
nuclear@6 385 int dsys_event_link(struct dsys_event *ev, float *link)
nuclear@6 386 {
nuclear@6 387 return dsys_event_callback(ev, link_callback, link);
nuclear@6 388 }
nuclear@6 389
nuclear@6 390 static void link_callback(struct dsys_event *ev, void *cls)
nuclear@6 391 {
nuclear@6 392 *(float*)cls = ev->val;
nuclear@6 393 }
nuclear@2 394
nuclear@2 395
nuclear@2 396 /* time conversion */
nuclear@2 397 demotime_t dsys_sec_to_dtime(float sec)
nuclear@2 398 {
nuclear@2 399 return sec;
nuclear@2 400 }
nuclear@2 401
nuclear@2 402 demotime_t dsys_msec_to_dtime(unsigned long msec)
nuclear@2 403 {
nuclear@2 404 return (demotime_t)msec / 1000.0;
nuclear@2 405 }
nuclear@2 406
nuclear@2 407 float dsys_dtime_to_sec(demotime_t tm)
nuclear@2 408 {
nuclear@2 409 return tm;
nuclear@2 410 }
nuclear@2 411
nuclear@2 412 unsigned long dsys_dtime_to_msec(demotime_t tm)
nuclear@2 413 {
nuclear@2 414 return (unsigned long)(tm * 1000.0);
nuclear@2 415 }
nuclear@2 416
nuclear@2 417
nuclear@5 418 float dsys_eval_step(struct dsys_event *ev, demotime_t t)
nuclear@2 419 {
nuclear@2 420 return t >= ev->t1 ? 1.0 : 0.0;
nuclear@2 421 }
nuclear@2 422
nuclear@7 423 #define CLAMP(x, low, high) ((x) < (low) ? (low) : ((x) > (high) ? (high) : (x)))
nuclear@7 424
nuclear@5 425 float dsys_eval_lerp(struct dsys_event *ev, demotime_t t)
nuclear@2 426 {
nuclear@7 427 float res = (t - ev->t0) / (ev->t1 - ev->t0);
nuclear@7 428 return CLAMP(res, 0.0, 1.0);
nuclear@2 429 }
nuclear@2 430
nuclear@5 431 float dsys_eval_sigmoid(struct dsys_event *ev, demotime_t t)
nuclear@2 432 {
nuclear@5 433 t = dsys_eval_lerp(ev, t);
nuclear@2 434 return 1.0 - (cos(t * M_PI) * 0.5 + 0.5);
nuclear@2 435 }
nuclear@2 436
nuclear@2 437 static void free_event(struct dsys_event *ev)
nuclear@2 438 {
nuclear@2 439 while(ev->cblist) {
nuclear@2 440 struct callback *cb = ev->cblist;
nuclear@2 441 ev->cblist = ev->cblist->next;
nuclear@2 442 free(cb);
nuclear@2 443 }
nuclear@2 444 }
nuclear@4 445
nuclear@4 446 static struct dsys_event *sort_evlist(struct dsys_event *list, int num_ev)
nuclear@4 447 {
nuclear@4 448 int i, num_left, num_right;
nuclear@4 449 struct dsys_event *left, *right, *node = list;
nuclear@4 450
nuclear@4 451 if(num_ev < 2) {
nuclear@4 452 return list;
nuclear@4 453 }
nuclear@4 454
nuclear@4 455 num_left = num_ev / 2;
nuclear@4 456 num_right = num_ev - num_left;
nuclear@4 457
nuclear@4 458 for(i=0; i<num_ev/2; i++) {
nuclear@4 459 node = node->next;
nuclear@4 460 }
nuclear@4 461
nuclear@4 462 if(node->prev) {
nuclear@4 463 node->prev->next = 0;
nuclear@4 464 node->prev = 0;
nuclear@4 465 }
nuclear@4 466
nuclear@4 467 left = sort_evlist(list, num_left);
nuclear@4 468 right = sort_evlist(node, num_right);
nuclear@4 469
nuclear@4 470 return merge_evlists(left, right);
nuclear@4 471 }
nuclear@4 472
nuclear@4 473 static struct dsys_event *merge_evlists(struct dsys_event *list1, struct dsys_event *list2)
nuclear@4 474 {
nuclear@4 475 struct dsys_event *head, *tail, *node;
nuclear@4 476
nuclear@4 477 if(!list1) {
nuclear@4 478 return list2;
nuclear@4 479 }
nuclear@4 480 if(!list2) {
nuclear@4 481 return list1;
nuclear@4 482 }
nuclear@4 483
nuclear@4 484 head = tail = 0;
nuclear@4 485
nuclear@4 486 while(list1 && list2) {
nuclear@4 487 if(list1->t0 < list2->t0) {
nuclear@4 488 node = list1;
nuclear@4 489 list1 = list1->next;
nuclear@4 490 } else {
nuclear@4 491 node = list2;
nuclear@4 492 list2 = list2->next;
nuclear@4 493 }
nuclear@4 494
nuclear@4 495 node->next = 0;
nuclear@4 496 node->prev = tail;
nuclear@4 497
nuclear@4 498 if(!head) {
nuclear@4 499 head = node;
nuclear@4 500 } else {
nuclear@4 501 tail->next = node;
nuclear@4 502 }
nuclear@4 503 tail = node;
nuclear@4 504 }
nuclear@4 505
nuclear@4 506 if(list1) {
nuclear@4 507 tail->next = list1;
nuclear@4 508 list1->prev = tail;
nuclear@4 509 } else if(list2) {
nuclear@4 510 tail->next = list2;
nuclear@4 511 list2->prev = tail;
nuclear@4 512 }
nuclear@4 513
nuclear@4 514 return head;
nuclear@4 515 }