dbf-udg

annotate libs/dsys2/dsys.c @ 12:1abbed71e9c9

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