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