dsys2

changeset 4:95f010f7eadc

*burp*
author John Tsiombikas <nuclear@siggraph.org>
date Thu, 01 Sep 2011 07:55:22 +0300
parents eec499998960
children 94ce16dd20c0
files src/dsys.c src/dsys_impl.h
diffstat 2 files changed, 133 insertions(+), 16 deletions(-) [+]
line diff
     1.1 --- a/src/dsys.c	Wed Aug 31 23:23:38 2011 +0300
     1.2 +++ b/src/dsys.c	Thu Sep 01 07:55:22 2011 +0300
     1.3 @@ -6,27 +6,45 @@
     1.4  #include "dsys2.h"
     1.5  #include "dsys_impl.h"
     1.6  
     1.7 +static int read_script(struct dsys_demo *demo, FILE *fp, const char *fname);
     1.8 +
     1.9  static float eval_step(struct dsys_event *ev, demotime_t t);
    1.10  static float eval_lerp(struct dsys_event *ev, demotime_t t);
    1.11  static float eval_sigmoid(struct dsys_event *ev, demotime_t t);
    1.12  
    1.13  static void free_event(struct dsys_event *ev);
    1.14  
    1.15 +static struct dsys_event *sort_evlist(struct dsys_event *list, int num_ev);
    1.16 +static struct dsys_event *merge_evlists(struct dsys_event *list1, struct dsys_event *list2);
    1.17  
    1.18  
    1.19  struct dsys_demo *dsys_open(const char *fname)
    1.20  {
    1.21  	FILE *fp;
    1.22 -	struct dsys_demo *res;
    1.23 +	struct dsys_demo *demo;
    1.24  
    1.25  	if(!(fp = fopen(fname, "r"))) {
    1.26  		fprintf(stderr, "failed to open demoscript: %s: %s\n", fname, strerror(errno));
    1.27  		return 0;
    1.28  	}
    1.29  
    1.30 -	res = dsys_open_stream(fp);
    1.31 +	if(!(demo = malloc(sizeof *demo))) {
    1.32 +		perror("failed to allocate memory");
    1.33 +		fclose(fp);
    1.34 +		return 0;
    1.35 +	}
    1.36 +	memset(demo, 0, sizeof *demo);
    1.37 +
    1.38 +	demo->src_tm = demo->start_tm = -1;
    1.39 +
    1.40 +	if(read_script(demo, fp, fname) == -1) {
    1.41 +		free(demo);
    1.42 +		fclose(fp);
    1.43 +		return 0;
    1.44 +	}
    1.45 +
    1.46  	fclose(fp);
    1.47 -	return res;
    1.48 +	return demo;
    1.49  }
    1.50  
    1.51  struct dsys_demo *dsys_open_stream(FILE *fp)
    1.52 @@ -41,7 +59,7 @@
    1.53  
    1.54  	demo->src_tm = demo->start_tm = -1;
    1.55  
    1.56 -	if(read_script(demo, fp) == -1) {
    1.57 +	if(read_script(demo, fp, 0) == -1) {
    1.58  		free(demo);
    1.59  		return 0;
    1.60  	}
    1.61 @@ -51,9 +69,9 @@
    1.62  
    1.63  void dsys_close(struct dsys_demo *demo)
    1.64  {
    1.65 -	while(demo->ev) {
    1.66 -		struct dsys_event *ev = demo->ev;
    1.67 -		demo->ev = demo->ev->next;
    1.68 +	while(demo->evlist) {
    1.69 +		struct dsys_event *ev = demo->evlist;
    1.70 +		demo->evlist = demo->evlist->next;
    1.71  		free_event(ev);
    1.72  	}
    1.73  
    1.74 @@ -61,14 +79,19 @@
    1.75  }
    1.76  
    1.77  
    1.78 +#define SEP	" \t\n\r"
    1.79  
    1.80 -static int read_script(struct dsys_demo *demo, FILE *fp)
    1.81 +static int read_script(struct dsys_demo *demo, FILE *fp, const char *fname)
    1.82  {
    1.83  	int nline = 0;
    1.84 -	char buf[512], *line, tok;
    1.85 -	int timestamp;
    1.86 +	char buf[512], *line, *tok, *endp;
    1.87 +	unsigned int t0, t1;
    1.88  	struct dsys_event *ev;
    1.89  
    1.90 +	if(!fname) {
    1.91 +		fname = "<unknown>";
    1.92 +	}
    1.93 +
    1.94  	while(fgets(buf, sizeof buf, fp)) {
    1.95  		nline++;
    1.96  
    1.97 @@ -78,17 +101,26 @@
    1.98  			continue;
    1.99  		}
   1.100  
   1.101 -		if(!(tok = strtok(line, SEP)) || !isdigit(*tok)) {
   1.102 -			fprintf(stderr, "error reading script at line: %d: expected timestamp\n", nline);
   1.103 +		if(!(tok = strtok(line, SEP)) || (t0 = strtol(tok, &endp, 10), endp == tok)) {
   1.104 +			fprintf(stderr, "%s line: %d, error: expected timestamp t0\n", fname, nline);
   1.105  			return -1;
   1.106  		}
   1.107 -		timestamp = atoi(tok);
   1.108  
   1.109  		if(!(tok = strtok(0, SEP))) {
   1.110 -			fprintf(stderr, "error reading script at line: %d: expected event name\n", nline);
   1.111 +			fprintf(stderr, "%s line: %d, error: expected second timestamp or event name\n", fname, nline);
   1.112  			return -1;
   1.113  		}
   1.114  
   1.115 +		t1 = strtol(tok, &endp, 10);
   1.116 +		if(endp == tok) {
   1.117 +			t1 = t0;
   1.118 +		} else {
   1.119 +			if(!(tok = strtok(0, SEP))) {
   1.120 +				fprintf(stderr, "%s line: %d, error: expected event name\n", fname, nline);
   1.121 +				return -1;
   1.122 +			}
   1.123 +		}
   1.124 +
   1.125  		if(!(ev = malloc(sizeof *ev))) {
   1.126  			perror("read_script: failed to allocate memory for an event\n");
   1.127  			return -1;
   1.128 @@ -101,8 +133,21 @@
   1.129  			sprintf("read_script: failed to allocate memory for the event name: %s\n", tok);
   1.130  			return -1;
   1.131  		}
   1.132 +		strcpy(ev->name, tok);
   1.133 +
   1.134 +		ev->eval_func = t0 == t1 ? eval_step : eval_lerp;
   1.135 +
   1.136 +		ev->next = demo->evlist;
   1.137 +		ev->prev = 0;
   1.138 +		if(demo->evlist) {
   1.139 +			demo->evlist->prev = ev;
   1.140 +		}
   1.141 +		demo->evlist = ev;
   1.142 +		demo->num_ev++;
   1.143  	}
   1.144  
   1.145 +	demo->evlist = sort_evlist(demo->evlist, demo->num_ev);
   1.146 +
   1.147  	return 0;
   1.148  }
   1.149  
   1.150 @@ -240,3 +285,74 @@
   1.151  		free(cb);
   1.152  	}
   1.153  }
   1.154 +
   1.155 +static struct dsys_event *sort_evlist(struct dsys_event *list, int num_ev)
   1.156 +{
   1.157 +	int i, num_left, num_right;
   1.158 +	struct dsys_event *left, *right, *node = list;
   1.159 +
   1.160 +	if(num_ev < 2) {
   1.161 +		return list;
   1.162 +	}
   1.163 +
   1.164 +	num_left = num_ev / 2;
   1.165 +	num_right = num_ev - num_left;
   1.166 +
   1.167 +	for(i=0; i<num_ev/2; i++) {
   1.168 +		node = node->next;
   1.169 +	}
   1.170 +
   1.171 +	if(node->prev) {
   1.172 +		node->prev->next = 0;
   1.173 +		node->prev = 0;
   1.174 +	}
   1.175 +
   1.176 +	left = sort_evlist(list, num_left);
   1.177 +	right = sort_evlist(node, num_right);
   1.178 +
   1.179 +	return merge_evlists(left, right);
   1.180 +}
   1.181 +
   1.182 +static struct dsys_event *merge_evlists(struct dsys_event *list1, struct dsys_event *list2)
   1.183 +{
   1.184 +	struct dsys_event *head, *tail, *node;
   1.185 +
   1.186 +	if(!list1) {
   1.187 +		return list2;
   1.188 +	}
   1.189 +	if(!list2) {
   1.190 +		return list1;
   1.191 +	}
   1.192 +
   1.193 +	head = tail = 0;
   1.194 +
   1.195 +	while(list1 && list2) {
   1.196 +		if(list1->t0 < list2->t0) {
   1.197 +			node = list1;
   1.198 +			list1 = list1->next;
   1.199 +		} else {
   1.200 +			node = list2;
   1.201 +			list2 = list2->next;
   1.202 +		}
   1.203 +
   1.204 +		node->next = 0;
   1.205 +		node->prev = tail;
   1.206 +
   1.207 +		if(!head) {
   1.208 +			head = node;
   1.209 +		} else {
   1.210 +			tail->next = node;
   1.211 +		}
   1.212 +		tail = node;
   1.213 +	}
   1.214 +
   1.215 +	if(list1) {
   1.216 +		tail->next = list1;
   1.217 +		list1->prev = tail;
   1.218 +	} else if(list2) {
   1.219 +		tail->next = list2;
   1.220 +		list2->prev = tail;
   1.221 +	}
   1.222 +
   1.223 +	return head;
   1.224 +}
     2.1 --- a/src/dsys_impl.h	Wed Aug 31 23:23:38 2011 +0300
     2.2 +++ b/src/dsys_impl.h	Thu Sep 01 07:55:22 2011 +0300
     2.3 @@ -7,7 +7,7 @@
     2.4  	demotime_t tm, src_tm, start_tm, stop_tm, duration;
     2.5  	demotime_t stoppage_tm;
     2.6  
     2.7 -	struct dsys_event *ev;
     2.8 +	struct dsys_event *evlist;
     2.9  	int num_ev;
    2.10  
    2.11  	int running;
    2.12 @@ -24,10 +24,11 @@
    2.13  struct dsys_event {
    2.14  	enum dsys_evtype type;
    2.15  
    2.16 +	char *name;
    2.17  	demotime_t t0, t1;
    2.18  	float val;
    2.19  
    2.20 -	float (*eval_func)(struct dsys_event*);
    2.21 +	float (*eval_func)(struct dsys_event*, demotime_t);
    2.22  
    2.23  	struct callback *cblist;
    2.24