dbf-halloween2015
diff 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 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/dsys/dsys.c Sun Nov 01 00:09:12 2015 +0200 1.3 @@ -0,0 +1,515 @@ 1.4 +#include <stdio.h> 1.5 +#include <math.h> 1.6 +#include <stdlib.h> 1.7 +#include <string.h> 1.8 +#include <ctype.h> 1.9 +#include <errno.h> 1.10 +#include "dsys.h" 1.11 +#include "dsys_impl.h" 1.12 + 1.13 +static int read_script(struct dsys_demo *demo, FILE *fp, const char *fname); 1.14 +static char *strip_ws(char *buf); 1.15 +static void dbg_print_events(struct dsys_event *ev); 1.16 + 1.17 +static void proc_event(struct dsys_event *ev, demotime_t tm); 1.18 +static void link_callback(struct dsys_event *ev, void *cls); 1.19 +static void free_event(struct dsys_event *ev); 1.20 + 1.21 +static struct dsys_event *sort_evlist(struct dsys_event *list, int num_ev); 1.22 +static struct dsys_event *merge_evlists(struct dsys_event *list1, struct dsys_event *list2); 1.23 + 1.24 + 1.25 +struct dsys_demo *dsys_open(const char *fname) 1.26 +{ 1.27 + FILE *fp; 1.28 + struct dsys_demo *demo; 1.29 + 1.30 + if(!(fp = fopen(fname, "r"))) { 1.31 + fprintf(stderr, "failed to open demoscript: %s: %s\n", fname, strerror(errno)); 1.32 + return 0; 1.33 + } 1.34 + 1.35 + if(!(demo = malloc(sizeof *demo))) { 1.36 + perror("failed to allocate memory"); 1.37 + fclose(fp); 1.38 + return 0; 1.39 + } 1.40 + memset(demo, 0, sizeof *demo); 1.41 + 1.42 + demo->src_tm = demo->start_tm = -1; 1.43 + 1.44 + if(read_script(demo, fp, fname) == -1) { 1.45 + free(demo); 1.46 + fclose(fp); 1.47 + return 0; 1.48 + } 1.49 + 1.50 + fclose(fp); 1.51 + return demo; 1.52 +} 1.53 + 1.54 +struct dsys_demo *dsys_open_stream(FILE *fp) 1.55 +{ 1.56 + struct dsys_demo *demo; 1.57 + 1.58 + if(!(demo = malloc(sizeof *demo))) { 1.59 + perror("failed to allocate memory"); 1.60 + return 0; 1.61 + } 1.62 + memset(demo, 0, sizeof *demo); 1.63 + 1.64 + demo->src_tm = demo->start_tm = -1; 1.65 + 1.66 + if(read_script(demo, fp, 0) == -1) { 1.67 + free(demo); 1.68 + return 0; 1.69 + } 1.70 + 1.71 + return demo; 1.72 +} 1.73 + 1.74 +void dsys_close(struct dsys_demo *demo) 1.75 +{ 1.76 + while(demo->evlist) { 1.77 + struct dsys_event *ev = demo->evlist; 1.78 + demo->evlist = demo->evlist->next; 1.79 + free_event(ev); 1.80 + } 1.81 + 1.82 + free(demo); 1.83 +} 1.84 + 1.85 + 1.86 +#define SEP " \t\n\r" 1.87 + 1.88 +static int read_script(struct dsys_demo *demo, FILE *fp, const char *fname) 1.89 +{ 1.90 + int nline = 0; 1.91 + char buf[512], *line, *tok, *endp; 1.92 + unsigned int t0, t1; 1.93 + struct dsys_event *ev; 1.94 + 1.95 + if(!fname) { 1.96 + fname = "<unknown>"; 1.97 + } 1.98 + 1.99 + demo->duration = dsys_msec_to_dtime(0); 1.100 + 1.101 + while(fgets(buf, sizeof buf, fp)) { 1.102 + nline++; 1.103 + 1.104 + line = strip_ws(buf); 1.105 + 1.106 + if(!line || !*line) { 1.107 + continue; 1.108 + } 1.109 + 1.110 + if(!(tok = strtok(line, SEP)) || (t0 = strtol(tok, &endp, 10), endp == tok)) { 1.111 + fprintf(stderr, "%s line: %d, error: expected timestamp t0\n", fname, nline); 1.112 + return -1; 1.113 + } 1.114 + 1.115 + if(!(tok = strtok(0, SEP))) { 1.116 + fprintf(stderr, "%s line: %d, error: expected second timestamp or event name\n", fname, nline); 1.117 + return -1; 1.118 + } 1.119 + 1.120 + t1 = strtol(tok, &endp, 10); 1.121 + if(endp == tok) { 1.122 + t1 = t0; 1.123 + } else { 1.124 + if(!(tok = strtok(0, SEP))) { 1.125 + fprintf(stderr, "%s line: %d, error: expected event name\n", fname, nline); 1.126 + return -1; 1.127 + } 1.128 + } 1.129 + 1.130 + if(!(ev = malloc(sizeof *ev))) { 1.131 + perror("read_script: failed to allocate memory for an event\n"); 1.132 + return -1; 1.133 + } 1.134 + memset(ev, 0, sizeof *ev); 1.135 + ev->t0 = dsys_msec_to_dtime(t0); 1.136 + ev->t1 = dsys_msec_to_dtime(t1); 1.137 + 1.138 + if(!(ev->name = malloc(strlen(tok) + 1))) { 1.139 + free(ev); 1.140 + fprintf(stderr, "read_script: failed to allocate memory for the event name: %s\n", tok); 1.141 + return -1; 1.142 + } 1.143 + strcpy(ev->name, tok); 1.144 + 1.145 + ev->eval = t0 == t1 ? dsys_eval_step : dsys_eval_lerp; 1.146 + 1.147 + ev->next = demo->evlist; 1.148 + ev->prev = 0; 1.149 + if(demo->evlist) { 1.150 + demo->evlist->prev = ev; 1.151 + } 1.152 + demo->evlist = ev; 1.153 + demo->num_ev++; 1.154 + 1.155 + if(ev->t1 > demo->duration) { 1.156 + demo->duration = ev->t1; 1.157 + } 1.158 + } 1.159 + 1.160 + demo->evlist = sort_evlist(demo->evlist, demo->num_ev); 1.161 + 1.162 + /*dbg_print_events(demo->evlist);*/ 1.163 + 1.164 + return 0; 1.165 +} 1.166 + 1.167 +static char *strip_ws(char *buf) 1.168 +{ 1.169 + char *ptr; 1.170 + 1.171 + while(isspace(*buf)) { 1.172 + buf++; 1.173 + } 1.174 + 1.175 + ptr = buf; 1.176 + while(*ptr) { 1.177 + if(*ptr == '\n' || *ptr == '\r' || *ptr == '#') { 1.178 + *ptr = 0; 1.179 + break; 1.180 + } 1.181 + ptr++; 1.182 + } 1.183 + 1.184 + return buf; 1.185 +} 1.186 + 1.187 +/*static void dbg_print_events(struct dsys_event *ev) 1.188 +{ 1.189 + int i; 1.190 + 1.191 + for(i=0; ev; i++) { 1.192 + printf("%02d - %s (%f -> %f) [%s]\n", i, ev->eval == dsys_eval_step ? "step" : "lerp", 1.193 + ev->t0, ev->t1, ev->name); 1.194 + ev = ev->next; 1.195 + } 1.196 +}*/ 1.197 + 1.198 +void dsys_update(struct dsys_demo *demo, demotime_t tm) 1.199 +{ 1.200 + struct dsys_event *ev; 1.201 + 1.202 + demo->src_tm = tm; 1.203 + 1.204 + if(demo->start_tm == -1) { 1.205 + dsys_start(demo); 1.206 + } 1.207 + 1.208 + if(!demo->running) { 1.209 + return; /* nothing changes */ 1.210 + } 1.211 + 1.212 + demo->tm = tm - demo->start_tm - demo->stoppage_tm; 1.213 + 1.214 + if(demo->tm < 0) { 1.215 + demo->tm = 0; 1.216 + } 1.217 + if(demo->tm > demo->duration) { 1.218 + demo->tm = demo->duration; 1.219 + } 1.220 + 1.221 + while(demo->active && demo->active->t1 <= demo->tm) { 1.222 + proc_event(demo->active, demo->tm); 1.223 + demo->active = demo->active->next; 1.224 + } 1.225 + 1.226 + ev = demo->active; 1.227 + while(ev && ev->t0 <= demo->tm) { 1.228 + proc_event(ev, demo->tm); 1.229 + ev = ev->next; 1.230 + } 1.231 + demo->nextev = ev; 1.232 + 1.233 + 1.234 + if(demo->tm >= demo->duration) { 1.235 + dsys_stop(demo); 1.236 + } 1.237 +} 1.238 + 1.239 +static void proc_event(struct dsys_event *ev, demotime_t tm) 1.240 +{ 1.241 + float val = ev->eval(ev, tm); 1.242 + 1.243 + if(ev->val != val) { 1.244 + struct callback *cb = ev->cblist; 1.245 + 1.246 + ev->val = val; 1.247 + 1.248 + while(cb) { 1.249 + cb->func(ev, cb->cls); 1.250 + cb = cb->next; 1.251 + } 1.252 + } 1.253 +} 1.254 + 1.255 +void dsys_start(struct dsys_demo *demo) 1.256 +{ 1.257 + if(demo->running) { 1.258 + return; 1.259 + } 1.260 + 1.261 + if(demo->start_tm == -1) { 1.262 + demo->start_tm = demo->src_tm; 1.263 + demo->nextev = demo->active = demo->evlist; 1.264 + } else { 1.265 + demo->stoppage_tm += demo->src_tm - demo->stop_tm; 1.266 + } 1.267 + 1.268 + demo->running = 1; 1.269 +} 1.270 + 1.271 +void dsys_stop(struct dsys_demo *demo) 1.272 +{ 1.273 + if(!demo->running) { 1.274 + return; 1.275 + } 1.276 + 1.277 + demo->stop_tm = demo->src_tm; 1.278 + demo->running = 0; 1.279 +} 1.280 + 1.281 +int dsys_is_running(struct dsys_demo *demo) 1.282 +{ 1.283 + return demo->running; 1.284 +} 1.285 + 1.286 + 1.287 +demotime_t dsys_duration(struct dsys_demo *demo) 1.288 +{ 1.289 + return demo->duration; 1.290 +} 1.291 + 1.292 +demotime_t dsys_time(struct dsys_demo *demo) 1.293 +{ 1.294 + return demo->tm; 1.295 +} 1.296 + 1.297 +float dsys_progress(struct dsys_demo *demo) 1.298 +{ 1.299 + return demo->tm / demo->duration; 1.300 +} 1.301 + 1.302 +/* seek without continuity */ 1.303 +void dsys_seek(struct dsys_demo *demo, demotime_t tm) 1.304 +{ 1.305 + struct dsys_event *ev; 1.306 + 1.307 + if(tm < 0) { 1.308 + tm = 0; 1.309 + } 1.310 + if(tm > demo->duration) { 1.311 + tm = demo->duration; 1.312 + } 1.313 + 1.314 + if(tm < demo->tm) { 1.315 + /* on backwards seek, invalidate the sliding window */ 1.316 + demo->nextev = demo->active = demo->evlist; 1.317 + } 1.318 + 1.319 + demo->start_tm = demo->src_tm - tm; 1.320 + demo->stoppage_tm = 0; 1.321 + demo->stop_tm = demo->src_tm; 1.322 + demo->tm = tm; 1.323 + 1.324 + /* recalculate events */ 1.325 + ev = demo->evlist; 1.326 + while(ev) { 1.327 + proc_event(ev, tm); 1.328 + ev = ev->next; 1.329 + } 1.330 +} 1.331 + 1.332 +void dsys_seek_norm(struct dsys_demo *demo, float t) 1.333 +{ 1.334 + dsys_seek(demo, t * demo->duration); 1.335 +} 1.336 + 1.337 +/* seek by accelerating time */ 1.338 +void dsys_warp(struct dsys_demo *demo, demotime_t tm) 1.339 +{ 1.340 + fprintf(stderr, "dsys_warp not implemented yet\n"); 1.341 +} 1.342 + 1.343 +void dsys_warp_norm(struct dsys_demo *demo, float t) 1.344 +{ 1.345 + dsys_warp(demo, t * demo->duration); 1.346 +} 1.347 + 1.348 + 1.349 +/* events */ 1.350 +struct dsys_event *dsys_event(struct dsys_demo *demo, const char *name) 1.351 +{ 1.352 + struct dsys_event *iter = demo->evlist; 1.353 + 1.354 + while(iter) { 1.355 + if(strcmp(iter->name, name) == 0) { 1.356 + return iter; 1.357 + } 1.358 + iter = iter->next; 1.359 + } 1.360 + return 0; 1.361 +} 1.362 + 1.363 +enum dsys_evtype dsys_event_type(struct dsys_event *ev) 1.364 +{ 1.365 + return ev->type; 1.366 +} 1.367 + 1.368 +float dsys_event_value(struct dsys_event *ev) 1.369 +{ 1.370 + return ev->val; 1.371 +} 1.372 + 1.373 +int dsys_event_callback(struct dsys_event *ev, void (*func)(struct dsys_event*, void*), void *cls) 1.374 +{ 1.375 + struct callback *cb; 1.376 + 1.377 + if(!(cb = malloc(sizeof *cb))) { 1.378 + perror("failed to allocate memory"); 1.379 + return -1; 1.380 + } 1.381 + cb->func = func; 1.382 + cb->cls = cls; 1.383 + cb->next = ev->cblist; 1.384 + ev->cblist = cb; 1.385 + return 0; 1.386 +} 1.387 + 1.388 +int dsys_event_link(struct dsys_event *ev, float *link) 1.389 +{ 1.390 + return dsys_event_callback(ev, link_callback, link); 1.391 +} 1.392 + 1.393 +static void link_callback(struct dsys_event *ev, void *cls) 1.394 +{ 1.395 + *(float*)cls = ev->val; 1.396 +} 1.397 + 1.398 + 1.399 +/* time conversion */ 1.400 +demotime_t dsys_sec_to_dtime(float sec) 1.401 +{ 1.402 + return sec; 1.403 +} 1.404 + 1.405 +demotime_t dsys_msec_to_dtime(unsigned long msec) 1.406 +{ 1.407 + return (demotime_t)msec / 1000.0; 1.408 +} 1.409 + 1.410 +float dsys_dtime_to_sec(demotime_t tm) 1.411 +{ 1.412 + return tm; 1.413 +} 1.414 + 1.415 +unsigned long dsys_dtime_to_msec(demotime_t tm) 1.416 +{ 1.417 + return (unsigned long)(tm * 1000.0); 1.418 +} 1.419 + 1.420 + 1.421 +float dsys_eval_step(struct dsys_event *ev, demotime_t t) 1.422 +{ 1.423 + return t >= ev->t1 ? 1.0 : 0.0; 1.424 +} 1.425 + 1.426 +#define CLAMP(x, low, high) ((x) < (low) ? (low) : ((x) > (high) ? (high) : (x))) 1.427 + 1.428 +float dsys_eval_lerp(struct dsys_event *ev, demotime_t t) 1.429 +{ 1.430 + float res = (t - ev->t0) / (ev->t1 - ev->t0); 1.431 + return CLAMP(res, 0.0, 1.0); 1.432 +} 1.433 + 1.434 +float dsys_eval_sigmoid(struct dsys_event *ev, demotime_t t) 1.435 +{ 1.436 + t = dsys_eval_lerp(ev, t); 1.437 + return 1.0 - (cos(t * M_PI) * 0.5 + 0.5); 1.438 +} 1.439 + 1.440 +static void free_event(struct dsys_event *ev) 1.441 +{ 1.442 + while(ev->cblist) { 1.443 + struct callback *cb = ev->cblist; 1.444 + ev->cblist = ev->cblist->next; 1.445 + free(cb); 1.446 + } 1.447 +} 1.448 + 1.449 +static struct dsys_event *sort_evlist(struct dsys_event *list, int num_ev) 1.450 +{ 1.451 + int i, num_left, num_right; 1.452 + struct dsys_event *left, *right, *node = list; 1.453 + 1.454 + if(num_ev < 2) { 1.455 + return list; 1.456 + } 1.457 + 1.458 + num_left = num_ev / 2; 1.459 + num_right = num_ev - num_left; 1.460 + 1.461 + for(i=0; i<num_ev/2; i++) { 1.462 + node = node->next; 1.463 + } 1.464 + 1.465 + if(node->prev) { 1.466 + node->prev->next = 0; 1.467 + node->prev = 0; 1.468 + } 1.469 + 1.470 + left = sort_evlist(list, num_left); 1.471 + right = sort_evlist(node, num_right); 1.472 + 1.473 + return merge_evlists(left, right); 1.474 +} 1.475 + 1.476 +static struct dsys_event *merge_evlists(struct dsys_event *list1, struct dsys_event *list2) 1.477 +{ 1.478 + struct dsys_event *head, *tail, *node; 1.479 + 1.480 + if(!list1) { 1.481 + return list2; 1.482 + } 1.483 + if(!list2) { 1.484 + return list1; 1.485 + } 1.486 + 1.487 + head = tail = 0; 1.488 + 1.489 + while(list1 && list2) { 1.490 + if(list1->t0 < list2->t0) { 1.491 + node = list1; 1.492 + list1 = list1->next; 1.493 + } else { 1.494 + node = list2; 1.495 + list2 = list2->next; 1.496 + } 1.497 + 1.498 + node->next = 0; 1.499 + node->prev = tail; 1.500 + 1.501 + if(!head) { 1.502 + head = node; 1.503 + } else { 1.504 + tail->next = node; 1.505 + } 1.506 + tail = node; 1.507 + } 1.508 + 1.509 + if(list1) { 1.510 + tail->next = list1; 1.511 + list1->prev = tail; 1.512 + } else if(list2) { 1.513 + tail->next = list2; 1.514 + list2->prev = tail; 1.515 + } 1.516 + 1.517 + return head; 1.518 +}