nuclear@2: #include nuclear@2: #include nuclear@2: #include nuclear@2: #include nuclear@2: #include nuclear@2: #include "dsys2.h" nuclear@2: #include "dsys_impl.h" nuclear@2: nuclear@2: static float eval_step(struct dsys_event *ev, demotime_t t); nuclear@2: static float eval_lerp(struct dsys_event *ev, demotime_t t); nuclear@2: static float eval_sigmoid(struct dsys_event *ev, demotime_t t); nuclear@2: nuclear@2: static void free_event(struct dsys_event *ev); nuclear@2: nuclear@2: nuclear@2: nuclear@2: struct dsys_demo *dsys_open(const char *fname) nuclear@2: { nuclear@2: FILE *fp; nuclear@2: struct dsys_demo *res; nuclear@2: nuclear@2: if(!(fp = fopen(fname, "r"))) { nuclear@2: fprintf(stderr, "failed to open demoscript: %s: %s\n", fname, strerror(errno)); nuclear@2: return 0; nuclear@2: } nuclear@2: nuclear@2: res = dsys_open_stream(fp); nuclear@2: fclose(fp); nuclear@2: return res; nuclear@2: } nuclear@2: nuclear@2: struct dsys_demo *dsys_open_stream(FILE *fp) nuclear@2: { nuclear@2: struct dsys_demo *demo; nuclear@2: nuclear@2: if(!(demo = malloc(sizeof *demo))) { nuclear@2: perror("failed to allocate memory"); nuclear@2: return 0; nuclear@2: } nuclear@2: memset(demo, 0, sizeof *demo); nuclear@2: nuclear@2: demo->src_tm = demo->start_tm = -1; nuclear@2: nuclear@3: if(read_script(demo, fp) == -1) { nuclear@3: free(demo); nuclear@3: return 0; nuclear@3: } nuclear@3: nuclear@2: return demo; nuclear@2: } nuclear@2: nuclear@2: void dsys_close(struct dsys_demo *demo) nuclear@2: { nuclear@2: while(demo->ev) { nuclear@2: struct dsys_event *ev = demo->ev; nuclear@2: demo->ev = demo->ev->next; nuclear@2: free_event(ev); nuclear@2: } nuclear@2: nuclear@2: free(demo); nuclear@2: } nuclear@2: nuclear@2: nuclear@3: nuclear@3: static int read_script(struct dsys_demo *demo, FILE *fp) nuclear@3: { nuclear@3: int nline = 0; nuclear@3: char buf[512], *line, tok; nuclear@3: int timestamp; nuclear@3: struct dsys_event *ev; nuclear@3: nuclear@3: while(fgets(buf, sizeof buf, fp)) { nuclear@3: nline++; nuclear@3: nuclear@3: line = buf;/*strip_ws(buf);*/ nuclear@3: nuclear@3: if(!line || !*line) { nuclear@3: continue; nuclear@3: } nuclear@3: nuclear@3: if(!(tok = strtok(line, SEP)) || !isdigit(*tok)) { nuclear@3: fprintf(stderr, "error reading script at line: %d: expected timestamp\n", nline); nuclear@3: return -1; nuclear@3: } nuclear@3: timestamp = atoi(tok); nuclear@3: nuclear@3: if(!(tok = strtok(0, SEP))) { nuclear@3: fprintf(stderr, "error reading script at line: %d: expected event name\n", nline); nuclear@3: return -1; nuclear@3: } nuclear@3: nuclear@3: if(!(ev = malloc(sizeof *ev))) { nuclear@3: perror("read_script: failed to allocate memory for an event\n"); nuclear@3: return -1; nuclear@3: } nuclear@3: ev->t0 = t0; nuclear@3: ev->t1 = t1; nuclear@3: nuclear@3: if(!(ev->name = malloc(strlen(tok) + 1))) { nuclear@3: free(ev); nuclear@3: sprintf("read_script: failed to allocate memory for the event name: %s\n", tok); nuclear@3: return -1; nuclear@3: } nuclear@3: } nuclear@3: nuclear@3: return 0; nuclear@3: } nuclear@3: nuclear@3: nuclear@2: void dsys_update(struct dsys_demo *demo, demotime_t tm) nuclear@2: { nuclear@2: demo->src_tm = tm; nuclear@2: nuclear@2: if(demo->start_tm == -1) { nuclear@2: dsys_start(demo); nuclear@2: } nuclear@2: nuclear@2: if(demo->running) { nuclear@2: demo->tm = tm - demo->start_tm - demo->stoppage_tm; nuclear@2: } nuclear@2: nuclear@2: /* TODO check the events list etc etc */ nuclear@2: } nuclear@2: nuclear@2: void dsys_start(struct dsys_demo *demo) nuclear@2: { nuclear@2: if(demo->running) { nuclear@2: return; nuclear@2: } nuclear@2: nuclear@2: if(demo->start_tm == -1) { nuclear@2: demo->start_tm = demo->src_tm; nuclear@2: } else { nuclear@2: demo->stoppage_tm += demo->src_tm - demo->stop_tm; nuclear@2: } nuclear@2: nuclear@2: demo->running = 1; nuclear@2: } nuclear@2: nuclear@2: void dsys_stop(struct dsys_demo *demo) nuclear@2: { nuclear@2: if(!demo->running) { nuclear@2: return; nuclear@2: } nuclear@2: nuclear@2: demo->stop_tm = demo->src_tm; nuclear@2: demo->running = 0; nuclear@2: } nuclear@2: nuclear@2: int dsys_is_running(struct dsys_demo *demo) nuclear@2: { nuclear@2: return demo->running; nuclear@2: } nuclear@2: nuclear@2: nuclear@2: demotime_t dsys_duration(struct dsys_demo *demo) nuclear@2: { nuclear@2: return demo->duration; nuclear@2: } nuclear@2: nuclear@2: demotime_t dsys_time(struct dsys_demo *demo) nuclear@2: { nuclear@2: return demo->tm; nuclear@2: } nuclear@2: nuclear@2: float dsys_progress(struct dsys_demo *demo) nuclear@2: { nuclear@2: return demo->tm / demo->duration; nuclear@2: } nuclear@2: nuclear@2: /* seek without continuity */ nuclear@2: void dsys_seek(struct dsys_demo *demo, demotime_t tm) nuclear@2: { nuclear@2: /* TODO */ nuclear@2: } nuclear@2: nuclear@2: void dsys_seek_norm(struct dsys_demo *demo, float t) nuclear@2: { nuclear@2: dsys_seek(demo, t * demo->duration); nuclear@2: } nuclear@2: nuclear@2: /* seek by accelerating time */ nuclear@2: void dsys_warp(struct dsys_demo *demo, demotime_t tm); nuclear@2: void dsys_warp_norm(struct dsys_demo *demo, float t); nuclear@2: nuclear@2: nuclear@2: /* events */ nuclear@2: struct dsys_event *dsys_event(struct dsys_demo *demo, const char *name); nuclear@2: nuclear@2: enum dsys_evtype dsys_event_type(struct dsys_event *ev); nuclear@2: float dsys_event_value(struct dsys_event *ev); nuclear@2: nuclear@2: void dsys_event_callback(struct dsys_event *ev, void (*func)(void*), void *cls); nuclear@2: void dsys_event_link(struct dsys_event *ev, float *link); nuclear@2: nuclear@2: nuclear@2: /* time conversion */ nuclear@2: demotime_t dsys_sec_to_dtime(float sec) nuclear@2: { nuclear@2: return sec; nuclear@2: } nuclear@2: nuclear@2: demotime_t dsys_msec_to_dtime(unsigned long msec) nuclear@2: { nuclear@2: return (demotime_t)msec / 1000.0; nuclear@2: } nuclear@2: nuclear@2: float dsys_dtime_to_sec(demotime_t tm) nuclear@2: { nuclear@2: return tm; nuclear@2: } nuclear@2: nuclear@2: unsigned long dsys_dtime_to_msec(demotime_t tm) nuclear@2: { nuclear@2: return (unsigned long)(tm * 1000.0); nuclear@2: } nuclear@2: nuclear@2: nuclear@2: static float eval_step(struct dsys_event *ev, demotime_t t) nuclear@2: { nuclear@2: return t >= ev->t1 ? 1.0 : 0.0; nuclear@2: } nuclear@2: nuclear@2: static float eval_lerp(struct dsys_event *ev, demotime_t t) nuclear@2: { nuclear@2: return (t - ev->t0) / (ev->t1 - ev->t0); nuclear@2: } nuclear@2: nuclear@2: static float eval_sigmoid(struct dsys_event *ev, demotime_t t) nuclear@2: { nuclear@2: t = eval_lerp(ev, t); nuclear@2: return 1.0 - (cos(t * M_PI) * 0.5 + 0.5); nuclear@2: } nuclear@2: nuclear@2: static void free_event(struct dsys_event *ev) nuclear@2: { nuclear@2: while(ev->cblist) { nuclear@2: struct callback *cb = ev->cblist; nuclear@2: ev->cblist = ev->cblist->next; nuclear@2: free(cb); nuclear@2: } nuclear@2: }