dbf-udg

annotate libs/dsys2/dsys.c @ 9:7056437a361b

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