dsys2

annotate src/dsys.c @ 6:80f86f0f67ec

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