dsys2

annotate src/dsys.c @ 4:95f010f7eadc

*burp*
author John Tsiombikas <nuclear@siggraph.org>
date Thu, 01 Sep 2011 07:55:22 +0300
parents eec499998960
children 94ce16dd20c0
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@2 11 static float eval_step(struct dsys_event *ev, demotime_t t);
nuclear@2 12 static float eval_lerp(struct dsys_event *ev, demotime_t t);
nuclear@2 13 static float eval_sigmoid(struct dsys_event *ev, demotime_t t);
nuclear@2 14
nuclear@2 15 static void free_event(struct dsys_event *ev);
nuclear@2 16
nuclear@4 17 static struct dsys_event *sort_evlist(struct dsys_event *list, int num_ev);
nuclear@4 18 static struct dsys_event *merge_evlists(struct dsys_event *list1, struct dsys_event *list2);
nuclear@2 19
nuclear@2 20
nuclear@2 21 struct dsys_demo *dsys_open(const char *fname)
nuclear@2 22 {
nuclear@2 23 FILE *fp;
nuclear@4 24 struct dsys_demo *demo;
nuclear@2 25
nuclear@2 26 if(!(fp = fopen(fname, "r"))) {
nuclear@2 27 fprintf(stderr, "failed to open demoscript: %s: %s\n", fname, strerror(errno));
nuclear@2 28 return 0;
nuclear@2 29 }
nuclear@2 30
nuclear@4 31 if(!(demo = malloc(sizeof *demo))) {
nuclear@4 32 perror("failed to allocate memory");
nuclear@4 33 fclose(fp);
nuclear@4 34 return 0;
nuclear@4 35 }
nuclear@4 36 memset(demo, 0, sizeof *demo);
nuclear@4 37
nuclear@4 38 demo->src_tm = demo->start_tm = -1;
nuclear@4 39
nuclear@4 40 if(read_script(demo, fp, fname) == -1) {
nuclear@4 41 free(demo);
nuclear@4 42 fclose(fp);
nuclear@4 43 return 0;
nuclear@4 44 }
nuclear@4 45
nuclear@2 46 fclose(fp);
nuclear@4 47 return demo;
nuclear@2 48 }
nuclear@2 49
nuclear@2 50 struct dsys_demo *dsys_open_stream(FILE *fp)
nuclear@2 51 {
nuclear@2 52 struct dsys_demo *demo;
nuclear@2 53
nuclear@2 54 if(!(demo = malloc(sizeof *demo))) {
nuclear@2 55 perror("failed to allocate memory");
nuclear@2 56 return 0;
nuclear@2 57 }
nuclear@2 58 memset(demo, 0, sizeof *demo);
nuclear@2 59
nuclear@2 60 demo->src_tm = demo->start_tm = -1;
nuclear@2 61
nuclear@4 62 if(read_script(demo, fp, 0) == -1) {
nuclear@3 63 free(demo);
nuclear@3 64 return 0;
nuclear@3 65 }
nuclear@3 66
nuclear@2 67 return demo;
nuclear@2 68 }
nuclear@2 69
nuclear@2 70 void dsys_close(struct dsys_demo *demo)
nuclear@2 71 {
nuclear@4 72 while(demo->evlist) {
nuclear@4 73 struct dsys_event *ev = demo->evlist;
nuclear@4 74 demo->evlist = demo->evlist->next;
nuclear@2 75 free_event(ev);
nuclear@2 76 }
nuclear@2 77
nuclear@2 78 free(demo);
nuclear@2 79 }
nuclear@2 80
nuclear@2 81
nuclear@4 82 #define SEP " \t\n\r"
nuclear@3 83
nuclear@4 84 static int read_script(struct dsys_demo *demo, FILE *fp, const char *fname)
nuclear@3 85 {
nuclear@3 86 int nline = 0;
nuclear@4 87 char buf[512], *line, *tok, *endp;
nuclear@4 88 unsigned int t0, t1;
nuclear@3 89 struct dsys_event *ev;
nuclear@3 90
nuclear@4 91 if(!fname) {
nuclear@4 92 fname = "<unknown>";
nuclear@4 93 }
nuclear@4 94
nuclear@3 95 while(fgets(buf, sizeof buf, fp)) {
nuclear@3 96 nline++;
nuclear@3 97
nuclear@3 98 line = buf;/*strip_ws(buf);*/
nuclear@3 99
nuclear@3 100 if(!line || !*line) {
nuclear@3 101 continue;
nuclear@3 102 }
nuclear@3 103
nuclear@4 104 if(!(tok = strtok(line, SEP)) || (t0 = strtol(tok, &endp, 10), endp == tok)) {
nuclear@4 105 fprintf(stderr, "%s line: %d, error: expected timestamp t0\n", fname, nline);
nuclear@3 106 return -1;
nuclear@3 107 }
nuclear@3 108
nuclear@3 109 if(!(tok = strtok(0, SEP))) {
nuclear@4 110 fprintf(stderr, "%s line: %d, error: expected second timestamp or event name\n", fname, nline);
nuclear@3 111 return -1;
nuclear@3 112 }
nuclear@3 113
nuclear@4 114 t1 = strtol(tok, &endp, 10);
nuclear@4 115 if(endp == tok) {
nuclear@4 116 t1 = t0;
nuclear@4 117 } else {
nuclear@4 118 if(!(tok = strtok(0, SEP))) {
nuclear@4 119 fprintf(stderr, "%s line: %d, error: expected event name\n", fname, nline);
nuclear@4 120 return -1;
nuclear@4 121 }
nuclear@4 122 }
nuclear@4 123
nuclear@3 124 if(!(ev = malloc(sizeof *ev))) {
nuclear@3 125 perror("read_script: failed to allocate memory for an event\n");
nuclear@3 126 return -1;
nuclear@3 127 }
nuclear@3 128 ev->t0 = t0;
nuclear@3 129 ev->t1 = t1;
nuclear@3 130
nuclear@3 131 if(!(ev->name = malloc(strlen(tok) + 1))) {
nuclear@3 132 free(ev);
nuclear@3 133 sprintf("read_script: failed to allocate memory for the event name: %s\n", tok);
nuclear@3 134 return -1;
nuclear@3 135 }
nuclear@4 136 strcpy(ev->name, tok);
nuclear@4 137
nuclear@4 138 ev->eval_func = t0 == t1 ? eval_step : eval_lerp;
nuclear@4 139
nuclear@4 140 ev->next = demo->evlist;
nuclear@4 141 ev->prev = 0;
nuclear@4 142 if(demo->evlist) {
nuclear@4 143 demo->evlist->prev = ev;
nuclear@4 144 }
nuclear@4 145 demo->evlist = ev;
nuclear@4 146 demo->num_ev++;
nuclear@3 147 }
nuclear@3 148
nuclear@4 149 demo->evlist = sort_evlist(demo->evlist, demo->num_ev);
nuclear@4 150
nuclear@3 151 return 0;
nuclear@3 152 }
nuclear@3 153
nuclear@3 154
nuclear@2 155 void dsys_update(struct dsys_demo *demo, demotime_t tm)
nuclear@2 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@2 163 if(demo->running) {
nuclear@2 164 demo->tm = tm - demo->start_tm - demo->stoppage_tm;
nuclear@2 165 }
nuclear@2 166
nuclear@2 167 /* TODO check the events list etc etc */
nuclear@2 168 }
nuclear@2 169
nuclear@2 170 void dsys_start(struct dsys_demo *demo)
nuclear@2 171 {
nuclear@2 172 if(demo->running) {
nuclear@2 173 return;
nuclear@2 174 }
nuclear@2 175
nuclear@2 176 if(demo->start_tm == -1) {
nuclear@2 177 demo->start_tm = demo->src_tm;
nuclear@2 178 } else {
nuclear@2 179 demo->stoppage_tm += demo->src_tm - demo->stop_tm;
nuclear@2 180 }
nuclear@2 181
nuclear@2 182 demo->running = 1;
nuclear@2 183 }
nuclear@2 184
nuclear@2 185 void dsys_stop(struct dsys_demo *demo)
nuclear@2 186 {
nuclear@2 187 if(!demo->running) {
nuclear@2 188 return;
nuclear@2 189 }
nuclear@2 190
nuclear@2 191 demo->stop_tm = demo->src_tm;
nuclear@2 192 demo->running = 0;
nuclear@2 193 }
nuclear@2 194
nuclear@2 195 int dsys_is_running(struct dsys_demo *demo)
nuclear@2 196 {
nuclear@2 197 return demo->running;
nuclear@2 198 }
nuclear@2 199
nuclear@2 200
nuclear@2 201 demotime_t dsys_duration(struct dsys_demo *demo)
nuclear@2 202 {
nuclear@2 203 return demo->duration;
nuclear@2 204 }
nuclear@2 205
nuclear@2 206 demotime_t dsys_time(struct dsys_demo *demo)
nuclear@2 207 {
nuclear@2 208 return demo->tm;
nuclear@2 209 }
nuclear@2 210
nuclear@2 211 float dsys_progress(struct dsys_demo *demo)
nuclear@2 212 {
nuclear@2 213 return demo->tm / demo->duration;
nuclear@2 214 }
nuclear@2 215
nuclear@2 216 /* seek without continuity */
nuclear@2 217 void dsys_seek(struct dsys_demo *demo, demotime_t tm)
nuclear@2 218 {
nuclear@2 219 /* TODO */
nuclear@2 220 }
nuclear@2 221
nuclear@2 222 void dsys_seek_norm(struct dsys_demo *demo, float t)
nuclear@2 223 {
nuclear@2 224 dsys_seek(demo, t * demo->duration);
nuclear@2 225 }
nuclear@2 226
nuclear@2 227 /* seek by accelerating time */
nuclear@2 228 void dsys_warp(struct dsys_demo *demo, demotime_t tm);
nuclear@2 229 void dsys_warp_norm(struct dsys_demo *demo, float t);
nuclear@2 230
nuclear@2 231
nuclear@2 232 /* events */
nuclear@2 233 struct dsys_event *dsys_event(struct dsys_demo *demo, const char *name);
nuclear@2 234
nuclear@2 235 enum dsys_evtype dsys_event_type(struct dsys_event *ev);
nuclear@2 236 float dsys_event_value(struct dsys_event *ev);
nuclear@2 237
nuclear@2 238 void dsys_event_callback(struct dsys_event *ev, void (*func)(void*), void *cls);
nuclear@2 239 void dsys_event_link(struct dsys_event *ev, float *link);
nuclear@2 240
nuclear@2 241
nuclear@2 242 /* time conversion */
nuclear@2 243 demotime_t dsys_sec_to_dtime(float sec)
nuclear@2 244 {
nuclear@2 245 return sec;
nuclear@2 246 }
nuclear@2 247
nuclear@2 248 demotime_t dsys_msec_to_dtime(unsigned long msec)
nuclear@2 249 {
nuclear@2 250 return (demotime_t)msec / 1000.0;
nuclear@2 251 }
nuclear@2 252
nuclear@2 253 float dsys_dtime_to_sec(demotime_t tm)
nuclear@2 254 {
nuclear@2 255 return tm;
nuclear@2 256 }
nuclear@2 257
nuclear@2 258 unsigned long dsys_dtime_to_msec(demotime_t tm)
nuclear@2 259 {
nuclear@2 260 return (unsigned long)(tm * 1000.0);
nuclear@2 261 }
nuclear@2 262
nuclear@2 263
nuclear@2 264 static float eval_step(struct dsys_event *ev, demotime_t t)
nuclear@2 265 {
nuclear@2 266 return t >= ev->t1 ? 1.0 : 0.0;
nuclear@2 267 }
nuclear@2 268
nuclear@2 269 static float eval_lerp(struct dsys_event *ev, demotime_t t)
nuclear@2 270 {
nuclear@2 271 return (t - ev->t0) / (ev->t1 - ev->t0);
nuclear@2 272 }
nuclear@2 273
nuclear@2 274 static float eval_sigmoid(struct dsys_event *ev, demotime_t t)
nuclear@2 275 {
nuclear@2 276 t = eval_lerp(ev, t);
nuclear@2 277 return 1.0 - (cos(t * M_PI) * 0.5 + 0.5);
nuclear@2 278 }
nuclear@2 279
nuclear@2 280 static void free_event(struct dsys_event *ev)
nuclear@2 281 {
nuclear@2 282 while(ev->cblist) {
nuclear@2 283 struct callback *cb = ev->cblist;
nuclear@2 284 ev->cblist = ev->cblist->next;
nuclear@2 285 free(cb);
nuclear@2 286 }
nuclear@2 287 }
nuclear@4 288
nuclear@4 289 static struct dsys_event *sort_evlist(struct dsys_event *list, int num_ev)
nuclear@4 290 {
nuclear@4 291 int i, num_left, num_right;
nuclear@4 292 struct dsys_event *left, *right, *node = list;
nuclear@4 293
nuclear@4 294 if(num_ev < 2) {
nuclear@4 295 return list;
nuclear@4 296 }
nuclear@4 297
nuclear@4 298 num_left = num_ev / 2;
nuclear@4 299 num_right = num_ev - num_left;
nuclear@4 300
nuclear@4 301 for(i=0; i<num_ev/2; i++) {
nuclear@4 302 node = node->next;
nuclear@4 303 }
nuclear@4 304
nuclear@4 305 if(node->prev) {
nuclear@4 306 node->prev->next = 0;
nuclear@4 307 node->prev = 0;
nuclear@4 308 }
nuclear@4 309
nuclear@4 310 left = sort_evlist(list, num_left);
nuclear@4 311 right = sort_evlist(node, num_right);
nuclear@4 312
nuclear@4 313 return merge_evlists(left, right);
nuclear@4 314 }
nuclear@4 315
nuclear@4 316 static struct dsys_event *merge_evlists(struct dsys_event *list1, struct dsys_event *list2)
nuclear@4 317 {
nuclear@4 318 struct dsys_event *head, *tail, *node;
nuclear@4 319
nuclear@4 320 if(!list1) {
nuclear@4 321 return list2;
nuclear@4 322 }
nuclear@4 323 if(!list2) {
nuclear@4 324 return list1;
nuclear@4 325 }
nuclear@4 326
nuclear@4 327 head = tail = 0;
nuclear@4 328
nuclear@4 329 while(list1 && list2) {
nuclear@4 330 if(list1->t0 < list2->t0) {
nuclear@4 331 node = list1;
nuclear@4 332 list1 = list1->next;
nuclear@4 333 } else {
nuclear@4 334 node = list2;
nuclear@4 335 list2 = list2->next;
nuclear@4 336 }
nuclear@4 337
nuclear@4 338 node->next = 0;
nuclear@4 339 node->prev = tail;
nuclear@4 340
nuclear@4 341 if(!head) {
nuclear@4 342 head = node;
nuclear@4 343 } else {
nuclear@4 344 tail->next = node;
nuclear@4 345 }
nuclear@4 346 tail = node;
nuclear@4 347 }
nuclear@4 348
nuclear@4 349 if(list1) {
nuclear@4 350 tail->next = list1;
nuclear@4 351 list1->prev = tail;
nuclear@4 352 } else if(list2) {
nuclear@4 353 tail->next = list2;
nuclear@4 354 list2->prev = tail;
nuclear@4 355 }
nuclear@4 356
nuclear@4 357 return head;
nuclear@4 358 }