rev |
line source |
nuclear@12
|
1 /*
|
nuclear@12
|
2 New demosystem by Nuclear / Mindlapse
|
nuclear@12
|
3 Copyright (C) 2011-2013 John Tsiombikas <nuclear@member.fsf.org>
|
nuclear@12
|
4
|
nuclear@12
|
5 This program is free software: you can redistribute it and/or modify
|
nuclear@12
|
6 it under the terms of the GNU General Public License as published by
|
nuclear@12
|
7 the Free Software Foundation, either version 3 of the License, or
|
nuclear@12
|
8 (at your option) any later version.
|
nuclear@12
|
9
|
nuclear@12
|
10 This program is distributed in the hope that it will be useful,
|
nuclear@12
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
nuclear@12
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
nuclear@12
|
13 GNU General Public License for more details.
|
nuclear@12
|
14
|
nuclear@12
|
15 You should have received a copy of the GNU General Public License
|
nuclear@12
|
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
nuclear@12
|
17 */
|
nuclear@9
|
18 #include <stdio.h>
|
nuclear@9
|
19 #include <math.h>
|
nuclear@9
|
20 #include <stdlib.h>
|
nuclear@9
|
21 #include <string.h>
|
nuclear@9
|
22 #include <ctype.h>
|
nuclear@9
|
23 #include <errno.h>
|
nuclear@9
|
24 #include "dsys.h"
|
nuclear@9
|
25 #include "dsys_impl.h"
|
nuclear@9
|
26
|
nuclear@9
|
27 static int read_script(struct dsys_demo *demo, FILE *fp, const char *fname);
|
nuclear@9
|
28 static char *strip_ws(char *buf);
|
nuclear@9
|
29 static void dbg_print_events(struct dsys_event *ev);
|
nuclear@9
|
30
|
nuclear@9
|
31 static void proc_event(struct dsys_event *ev, demotime_t tm);
|
nuclear@9
|
32 static void link_callback(struct dsys_event *ev, void *cls);
|
nuclear@9
|
33 static void free_event(struct dsys_event *ev);
|
nuclear@9
|
34
|
nuclear@9
|
35 static struct dsys_event *sort_evlist(struct dsys_event *list, int num_ev);
|
nuclear@9
|
36 static struct dsys_event *merge_evlists(struct dsys_event *list1, struct dsys_event *list2);
|
nuclear@9
|
37
|
nuclear@9
|
38
|
nuclear@9
|
39 struct dsys_demo *dsys_open(const char *fname)
|
nuclear@9
|
40 {
|
nuclear@9
|
41 FILE *fp;
|
nuclear@9
|
42 struct dsys_demo *demo;
|
nuclear@9
|
43
|
nuclear@9
|
44 if(!(fp = fopen(fname, "r"))) {
|
nuclear@9
|
45 fprintf(stderr, "failed to open demoscript: %s: %s\n", fname, strerror(errno));
|
nuclear@9
|
46 return 0;
|
nuclear@9
|
47 }
|
nuclear@9
|
48
|
nuclear@9
|
49 if(!(demo = malloc(sizeof *demo))) {
|
nuclear@9
|
50 perror("failed to allocate memory");
|
nuclear@9
|
51 fclose(fp);
|
nuclear@9
|
52 return 0;
|
nuclear@9
|
53 }
|
nuclear@9
|
54 memset(demo, 0, sizeof *demo);
|
nuclear@9
|
55
|
nuclear@9
|
56 demo->src_tm = demo->start_tm = -1;
|
nuclear@9
|
57
|
nuclear@9
|
58 if(read_script(demo, fp, fname) == -1) {
|
nuclear@9
|
59 free(demo);
|
nuclear@9
|
60 fclose(fp);
|
nuclear@9
|
61 return 0;
|
nuclear@9
|
62 }
|
nuclear@9
|
63
|
nuclear@9
|
64 fclose(fp);
|
nuclear@9
|
65 return demo;
|
nuclear@9
|
66 }
|
nuclear@9
|
67
|
nuclear@9
|
68 struct dsys_demo *dsys_open_stream(FILE *fp)
|
nuclear@9
|
69 {
|
nuclear@9
|
70 struct dsys_demo *demo;
|
nuclear@9
|
71
|
nuclear@9
|
72 if(!(demo = malloc(sizeof *demo))) {
|
nuclear@9
|
73 perror("failed to allocate memory");
|
nuclear@9
|
74 return 0;
|
nuclear@9
|
75 }
|
nuclear@9
|
76 memset(demo, 0, sizeof *demo);
|
nuclear@9
|
77
|
nuclear@9
|
78 demo->src_tm = demo->start_tm = -1;
|
nuclear@9
|
79
|
nuclear@9
|
80 if(read_script(demo, fp, 0) == -1) {
|
nuclear@9
|
81 free(demo);
|
nuclear@9
|
82 return 0;
|
nuclear@9
|
83 }
|
nuclear@9
|
84
|
nuclear@9
|
85 return demo;
|
nuclear@9
|
86 }
|
nuclear@9
|
87
|
nuclear@9
|
88 void dsys_close(struct dsys_demo *demo)
|
nuclear@9
|
89 {
|
nuclear@9
|
90 while(demo->evlist) {
|
nuclear@9
|
91 struct dsys_event *ev = demo->evlist;
|
nuclear@9
|
92 demo->evlist = demo->evlist->next;
|
nuclear@9
|
93 free_event(ev);
|
nuclear@9
|
94 }
|
nuclear@9
|
95
|
nuclear@9
|
96 free(demo);
|
nuclear@9
|
97 }
|
nuclear@9
|
98
|
nuclear@9
|
99
|
nuclear@9
|
100 #define SEP " \t\n\r"
|
nuclear@9
|
101
|
nuclear@9
|
102 static int read_script(struct dsys_demo *demo, FILE *fp, const char *fname)
|
nuclear@9
|
103 {
|
nuclear@9
|
104 int nline = 0;
|
nuclear@9
|
105 char buf[512], *line, *tok, *endp;
|
nuclear@9
|
106 unsigned int t0, t1;
|
nuclear@9
|
107 struct dsys_event *ev;
|
nuclear@9
|
108
|
nuclear@9
|
109 if(!fname) {
|
nuclear@9
|
110 fname = "<unknown>";
|
nuclear@9
|
111 }
|
nuclear@9
|
112
|
nuclear@9
|
113 demo->duration = dsys_msec_to_dtime(0);
|
nuclear@9
|
114
|
nuclear@9
|
115 while(fgets(buf, sizeof buf, fp)) {
|
nuclear@9
|
116 nline++;
|
nuclear@9
|
117
|
nuclear@9
|
118 line = strip_ws(buf);
|
nuclear@9
|
119
|
nuclear@9
|
120 if(!line || !*line) {
|
nuclear@9
|
121 continue;
|
nuclear@9
|
122 }
|
nuclear@9
|
123
|
nuclear@9
|
124 if(!(tok = strtok(line, SEP)) || (t0 = strtol(tok, &endp, 10), endp == tok)) {
|
nuclear@9
|
125 fprintf(stderr, "%s line: %d, error: expected timestamp t0\n", fname, nline);
|
nuclear@9
|
126 return -1;
|
nuclear@9
|
127 }
|
nuclear@9
|
128
|
nuclear@9
|
129 if(!(tok = strtok(0, SEP))) {
|
nuclear@9
|
130 fprintf(stderr, "%s line: %d, error: expected second timestamp or event name\n", fname, nline);
|
nuclear@9
|
131 return -1;
|
nuclear@9
|
132 }
|
nuclear@9
|
133
|
nuclear@9
|
134 t1 = strtol(tok, &endp, 10);
|
nuclear@9
|
135 if(endp == tok) {
|
nuclear@9
|
136 t1 = t0;
|
nuclear@9
|
137 } else {
|
nuclear@9
|
138 if(!(tok = strtok(0, SEP))) {
|
nuclear@9
|
139 fprintf(stderr, "%s line: %d, error: expected event name\n", fname, nline);
|
nuclear@9
|
140 return -1;
|
nuclear@9
|
141 }
|
nuclear@9
|
142 }
|
nuclear@9
|
143
|
nuclear@9
|
144 if(!(ev = malloc(sizeof *ev))) {
|
nuclear@9
|
145 perror("read_script: failed to allocate memory for an event\n");
|
nuclear@9
|
146 return -1;
|
nuclear@9
|
147 }
|
nuclear@9
|
148 memset(ev, 0, sizeof *ev);
|
nuclear@9
|
149 ev->t0 = dsys_msec_to_dtime(t0);
|
nuclear@9
|
150 ev->t1 = dsys_msec_to_dtime(t1);
|
nuclear@9
|
151
|
nuclear@9
|
152 if(!(ev->name = malloc(strlen(tok) + 1))) {
|
nuclear@9
|
153 free(ev);
|
nuclear@9
|
154 fprintf(stderr, "read_script: failed to allocate memory for the event name: %s\n", tok);
|
nuclear@9
|
155 return -1;
|
nuclear@9
|
156 }
|
nuclear@9
|
157 strcpy(ev->name, tok);
|
nuclear@9
|
158
|
nuclear@9
|
159 ev->eval = t0 == t1 ? dsys_eval_step : dsys_eval_lerp;
|
nuclear@9
|
160
|
nuclear@9
|
161 ev->next = demo->evlist;
|
nuclear@9
|
162 ev->prev = 0;
|
nuclear@9
|
163 if(demo->evlist) {
|
nuclear@9
|
164 demo->evlist->prev = ev;
|
nuclear@9
|
165 }
|
nuclear@9
|
166 demo->evlist = ev;
|
nuclear@9
|
167 demo->num_ev++;
|
nuclear@9
|
168
|
nuclear@9
|
169 if(ev->t1 > demo->duration) {
|
nuclear@9
|
170 demo->duration = ev->t1;
|
nuclear@9
|
171 }
|
nuclear@9
|
172 }
|
nuclear@9
|
173
|
nuclear@9
|
174 demo->evlist = sort_evlist(demo->evlist, demo->num_ev);
|
nuclear@9
|
175
|
nuclear@9
|
176 /*dbg_print_events(demo->evlist);*/
|
nuclear@9
|
177
|
nuclear@9
|
178 return 0;
|
nuclear@9
|
179 }
|
nuclear@9
|
180
|
nuclear@9
|
181 static char *strip_ws(char *buf)
|
nuclear@9
|
182 {
|
nuclear@9
|
183 char *ptr;
|
nuclear@9
|
184
|
nuclear@9
|
185 while(isspace(*buf)) {
|
nuclear@9
|
186 buf++;
|
nuclear@9
|
187 }
|
nuclear@9
|
188
|
nuclear@9
|
189 ptr = buf;
|
nuclear@9
|
190 while(*ptr) {
|
nuclear@9
|
191 if(*ptr == '\n' || *ptr == '\r' || *ptr == '#') {
|
nuclear@9
|
192 *ptr = 0;
|
nuclear@9
|
193 break;
|
nuclear@9
|
194 }
|
nuclear@9
|
195 ptr++;
|
nuclear@9
|
196 }
|
nuclear@9
|
197
|
nuclear@9
|
198 return buf;
|
nuclear@9
|
199 }
|
nuclear@9
|
200
|
nuclear@9
|
201 static void dbg_print_events(struct dsys_event *ev)
|
nuclear@9
|
202 {
|
nuclear@9
|
203 int i;
|
nuclear@9
|
204
|
nuclear@9
|
205 for(i=0; ev; i++) {
|
nuclear@9
|
206 printf("%02d - %s (%f -> %f) [%s]\n", i, ev->eval == dsys_eval_step ? "step" : "lerp",
|
nuclear@9
|
207 ev->t0, ev->t1, ev->name);
|
nuclear@9
|
208 ev = ev->next;
|
nuclear@9
|
209 }
|
nuclear@9
|
210 }
|
nuclear@9
|
211
|
nuclear@9
|
212 void dsys_update(struct dsys_demo *demo, demotime_t tm)
|
nuclear@9
|
213 {
|
nuclear@9
|
214 struct dsys_event *ev;
|
nuclear@9
|
215
|
nuclear@9
|
216 demo->src_tm = tm;
|
nuclear@9
|
217
|
nuclear@9
|
218 if(demo->start_tm == -1) {
|
nuclear@9
|
219 dsys_start(demo);
|
nuclear@9
|
220 }
|
nuclear@9
|
221
|
nuclear@9
|
222 if(!demo->running) {
|
nuclear@9
|
223 return; /* nothing changes */
|
nuclear@9
|
224 }
|
nuclear@9
|
225
|
nuclear@9
|
226 demo->tm = tm - demo->start_tm - demo->stoppage_tm;
|
nuclear@9
|
227
|
nuclear@9
|
228 if(demo->tm < 0) {
|
nuclear@9
|
229 demo->tm = 0;
|
nuclear@9
|
230 }
|
nuclear@9
|
231 if(demo->tm > demo->duration) {
|
nuclear@9
|
232 demo->tm = demo->duration;
|
nuclear@9
|
233 }
|
nuclear@9
|
234
|
nuclear@9
|
235 while(demo->active && demo->active->t1 <= demo->tm) {
|
nuclear@9
|
236 proc_event(demo->active, demo->tm);
|
nuclear@9
|
237 demo->active = demo->active->next;
|
nuclear@9
|
238 }
|
nuclear@9
|
239
|
nuclear@9
|
240 ev = demo->active;
|
nuclear@9
|
241 while(ev && ev->t0 <= demo->tm) {
|
nuclear@9
|
242 proc_event(ev, demo->tm);
|
nuclear@9
|
243 ev = ev->next;
|
nuclear@9
|
244 }
|
nuclear@9
|
245 demo->nextev = ev;
|
nuclear@9
|
246
|
nuclear@9
|
247
|
nuclear@9
|
248 if(demo->tm >= demo->duration) {
|
nuclear@9
|
249 dsys_stop(demo);
|
nuclear@9
|
250 }
|
nuclear@9
|
251 }
|
nuclear@9
|
252
|
nuclear@9
|
253 static void proc_event(struct dsys_event *ev, demotime_t tm)
|
nuclear@9
|
254 {
|
nuclear@9
|
255 float val = ev->eval(ev, tm);
|
nuclear@9
|
256
|
nuclear@9
|
257 if(ev->val != val) {
|
nuclear@9
|
258 struct callback *cb = ev->cblist;
|
nuclear@9
|
259
|
nuclear@9
|
260 ev->val = val;
|
nuclear@9
|
261
|
nuclear@9
|
262 while(cb) {
|
nuclear@9
|
263 cb->func(ev, cb->cls);
|
nuclear@9
|
264 cb = cb->next;
|
nuclear@9
|
265 }
|
nuclear@9
|
266 }
|
nuclear@9
|
267 }
|
nuclear@9
|
268
|
nuclear@9
|
269 void dsys_start(struct dsys_demo *demo)
|
nuclear@9
|
270 {
|
nuclear@9
|
271 if(demo->running) {
|
nuclear@9
|
272 return;
|
nuclear@9
|
273 }
|
nuclear@9
|
274
|
nuclear@9
|
275 if(demo->start_tm == -1) {
|
nuclear@9
|
276 demo->start_tm = demo->src_tm;
|
nuclear@9
|
277 demo->nextev = demo->active = demo->evlist;
|
nuclear@9
|
278 } else {
|
nuclear@9
|
279 demo->stoppage_tm += demo->src_tm - demo->stop_tm;
|
nuclear@9
|
280 }
|
nuclear@9
|
281
|
nuclear@9
|
282 demo->running = 1;
|
nuclear@9
|
283 }
|
nuclear@9
|
284
|
nuclear@9
|
285 void dsys_stop(struct dsys_demo *demo)
|
nuclear@9
|
286 {
|
nuclear@9
|
287 if(!demo->running) {
|
nuclear@9
|
288 return;
|
nuclear@9
|
289 }
|
nuclear@9
|
290
|
nuclear@9
|
291 demo->stop_tm = demo->src_tm;
|
nuclear@9
|
292 demo->running = 0;
|
nuclear@9
|
293 }
|
nuclear@9
|
294
|
nuclear@9
|
295 int dsys_is_running(struct dsys_demo *demo)
|
nuclear@9
|
296 {
|
nuclear@9
|
297 return demo->running;
|
nuclear@9
|
298 }
|
nuclear@9
|
299
|
nuclear@9
|
300
|
nuclear@9
|
301 demotime_t dsys_duration(struct dsys_demo *demo)
|
nuclear@9
|
302 {
|
nuclear@9
|
303 return demo->duration;
|
nuclear@9
|
304 }
|
nuclear@9
|
305
|
nuclear@9
|
306 demotime_t dsys_time(struct dsys_demo *demo)
|
nuclear@9
|
307 {
|
nuclear@9
|
308 return demo->tm;
|
nuclear@9
|
309 }
|
nuclear@9
|
310
|
nuclear@9
|
311 float dsys_progress(struct dsys_demo *demo)
|
nuclear@9
|
312 {
|
nuclear@9
|
313 return demo->tm / demo->duration;
|
nuclear@9
|
314 }
|
nuclear@9
|
315
|
nuclear@9
|
316 /* seek without continuity */
|
nuclear@9
|
317 void dsys_seek(struct dsys_demo *demo, demotime_t tm)
|
nuclear@9
|
318 {
|
nuclear@9
|
319 struct dsys_event *ev;
|
nuclear@9
|
320
|
nuclear@9
|
321 if(tm < 0) {
|
nuclear@9
|
322 tm = 0;
|
nuclear@9
|
323 }
|
nuclear@9
|
324 if(tm > demo->duration) {
|
nuclear@9
|
325 tm = demo->duration;
|
nuclear@9
|
326 }
|
nuclear@9
|
327
|
nuclear@9
|
328 if(tm < demo->tm) {
|
nuclear@9
|
329 /* on backwards seek, invalidate the sliding window */
|
nuclear@9
|
330 demo->nextev = demo->active = demo->evlist;
|
nuclear@9
|
331 }
|
nuclear@9
|
332
|
nuclear@9
|
333 demo->start_tm = demo->src_tm - tm;
|
nuclear@9
|
334 demo->stoppage_tm = 0;
|
nuclear@9
|
335 demo->stop_tm = demo->src_tm;
|
nuclear@9
|
336 demo->tm = tm;
|
nuclear@9
|
337
|
nuclear@9
|
338 /* recalculate events */
|
nuclear@9
|
339 ev = demo->evlist;
|
nuclear@9
|
340 while(ev) {
|
nuclear@9
|
341 proc_event(ev, tm);
|
nuclear@9
|
342 ev = ev->next;
|
nuclear@9
|
343 }
|
nuclear@9
|
344 }
|
nuclear@9
|
345
|
nuclear@9
|
346 void dsys_seek_norm(struct dsys_demo *demo, float t)
|
nuclear@9
|
347 {
|
nuclear@9
|
348 dsys_seek(demo, t * demo->duration);
|
nuclear@9
|
349 }
|
nuclear@9
|
350
|
nuclear@9
|
351 /* seek by accelerating time */
|
nuclear@9
|
352 void dsys_warp(struct dsys_demo *demo, demotime_t tm)
|
nuclear@9
|
353 {
|
nuclear@9
|
354 fprintf(stderr, "dsys_warp not implemented yet\n");
|
nuclear@9
|
355 }
|
nuclear@9
|
356
|
nuclear@9
|
357 void dsys_warp_norm(struct dsys_demo *demo, float t)
|
nuclear@9
|
358 {
|
nuclear@9
|
359 dsys_warp(demo, t * demo->duration);
|
nuclear@9
|
360 }
|
nuclear@9
|
361
|
nuclear@9
|
362
|
nuclear@9
|
363 /* events */
|
nuclear@9
|
364 struct dsys_event *dsys_event(struct dsys_demo *demo, const char *name)
|
nuclear@9
|
365 {
|
nuclear@9
|
366 struct dsys_event *iter = demo->evlist;
|
nuclear@9
|
367
|
nuclear@9
|
368 while(iter) {
|
nuclear@9
|
369 if(strcmp(iter->name, name) == 0) {
|
nuclear@9
|
370 return iter;
|
nuclear@9
|
371 }
|
nuclear@9
|
372 iter = iter->next;
|
nuclear@9
|
373 }
|
nuclear@9
|
374 return 0;
|
nuclear@9
|
375 }
|
nuclear@9
|
376
|
nuclear@11
|
377 void dsys_set_event_eval(struct dsys_event *ev, float (*eval)(struct dsys_event*, demotime_t))
|
nuclear@11
|
378 {
|
nuclear@11
|
379 ev->eval = eval;
|
nuclear@11
|
380 }
|
nuclear@11
|
381
|
nuclear@9
|
382 enum dsys_evtype dsys_event_type(struct dsys_event *ev)
|
nuclear@9
|
383 {
|
nuclear@9
|
384 return ev->type;
|
nuclear@9
|
385 }
|
nuclear@9
|
386
|
nuclear@9
|
387 float dsys_event_value(struct dsys_event *ev)
|
nuclear@9
|
388 {
|
nuclear@9
|
389 return ev->val;
|
nuclear@9
|
390 }
|
nuclear@9
|
391
|
nuclear@9
|
392 int dsys_event_callback(struct dsys_event *ev, void (*func)(struct dsys_event*, void*), void *cls)
|
nuclear@9
|
393 {
|
nuclear@9
|
394 struct callback *cb;
|
nuclear@9
|
395
|
nuclear@9
|
396 if(!(cb = malloc(sizeof *cb))) {
|
nuclear@9
|
397 perror("failed to allocate memory");
|
nuclear@9
|
398 return -1;
|
nuclear@9
|
399 }
|
nuclear@9
|
400 cb->func = func;
|
nuclear@9
|
401 cb->cls = cls;
|
nuclear@9
|
402 cb->next = ev->cblist;
|
nuclear@9
|
403 ev->cblist = cb;
|
nuclear@9
|
404 return 0;
|
nuclear@9
|
405 }
|
nuclear@9
|
406
|
nuclear@9
|
407 int dsys_event_link(struct dsys_event *ev, float *link)
|
nuclear@9
|
408 {
|
nuclear@9
|
409 return dsys_event_callback(ev, link_callback, link);
|
nuclear@9
|
410 }
|
nuclear@9
|
411
|
nuclear@9
|
412 static void link_callback(struct dsys_event *ev, void *cls)
|
nuclear@9
|
413 {
|
nuclear@9
|
414 *(float*)cls = ev->val;
|
nuclear@9
|
415 }
|
nuclear@9
|
416
|
nuclear@9
|
417
|
nuclear@9
|
418 /* time conversion */
|
nuclear@9
|
419 demotime_t dsys_sec_to_dtime(float sec)
|
nuclear@9
|
420 {
|
nuclear@9
|
421 return sec;
|
nuclear@9
|
422 }
|
nuclear@9
|
423
|
nuclear@9
|
424 demotime_t dsys_msec_to_dtime(unsigned long msec)
|
nuclear@9
|
425 {
|
nuclear@9
|
426 return (demotime_t)msec / 1000.0;
|
nuclear@9
|
427 }
|
nuclear@9
|
428
|
nuclear@9
|
429 float dsys_dtime_to_sec(demotime_t tm)
|
nuclear@9
|
430 {
|
nuclear@9
|
431 return tm;
|
nuclear@9
|
432 }
|
nuclear@9
|
433
|
nuclear@9
|
434 unsigned long dsys_dtime_to_msec(demotime_t tm)
|
nuclear@9
|
435 {
|
nuclear@9
|
436 return (unsigned long)(tm * 1000.0);
|
nuclear@9
|
437 }
|
nuclear@9
|
438
|
nuclear@9
|
439
|
nuclear@9
|
440 float dsys_eval_step(struct dsys_event *ev, demotime_t t)
|
nuclear@9
|
441 {
|
nuclear@9
|
442 return t >= ev->t1 ? 1.0 : 0.0;
|
nuclear@9
|
443 }
|
nuclear@9
|
444
|
nuclear@9
|
445 #define CLAMP(x, low, high) ((x) < (low) ? (low) : ((x) > (high) ? (high) : (x)))
|
nuclear@9
|
446
|
nuclear@9
|
447 float dsys_eval_lerp(struct dsys_event *ev, demotime_t t)
|
nuclear@9
|
448 {
|
nuclear@9
|
449 float res = (t - ev->t0) / (ev->t1 - ev->t0);
|
nuclear@9
|
450 return CLAMP(res, 0.0, 1.0);
|
nuclear@9
|
451 }
|
nuclear@9
|
452
|
nuclear@9
|
453 float dsys_eval_sigmoid(struct dsys_event *ev, demotime_t t)
|
nuclear@9
|
454 {
|
nuclear@9
|
455 t = dsys_eval_lerp(ev, t);
|
nuclear@9
|
456 return 1.0 - (cos(t * M_PI) * 0.5 + 0.5);
|
nuclear@9
|
457 }
|
nuclear@9
|
458
|
nuclear@9
|
459 static void free_event(struct dsys_event *ev)
|
nuclear@9
|
460 {
|
nuclear@9
|
461 while(ev->cblist) {
|
nuclear@9
|
462 struct callback *cb = ev->cblist;
|
nuclear@9
|
463 ev->cblist = ev->cblist->next;
|
nuclear@9
|
464 free(cb);
|
nuclear@9
|
465 }
|
nuclear@9
|
466 }
|
nuclear@9
|
467
|
nuclear@9
|
468 static struct dsys_event *sort_evlist(struct dsys_event *list, int num_ev)
|
nuclear@9
|
469 {
|
nuclear@9
|
470 int i, num_left, num_right;
|
nuclear@9
|
471 struct dsys_event *left, *right, *node = list;
|
nuclear@9
|
472
|
nuclear@9
|
473 if(num_ev < 2) {
|
nuclear@9
|
474 return list;
|
nuclear@9
|
475 }
|
nuclear@9
|
476
|
nuclear@9
|
477 num_left = num_ev / 2;
|
nuclear@9
|
478 num_right = num_ev - num_left;
|
nuclear@9
|
479
|
nuclear@9
|
480 for(i=0; i<num_ev/2; i++) {
|
nuclear@9
|
481 node = node->next;
|
nuclear@9
|
482 }
|
nuclear@9
|
483
|
nuclear@9
|
484 if(node->prev) {
|
nuclear@9
|
485 node->prev->next = 0;
|
nuclear@9
|
486 node->prev = 0;
|
nuclear@9
|
487 }
|
nuclear@9
|
488
|
nuclear@9
|
489 left = sort_evlist(list, num_left);
|
nuclear@9
|
490 right = sort_evlist(node, num_right);
|
nuclear@9
|
491
|
nuclear@9
|
492 return merge_evlists(left, right);
|
nuclear@9
|
493 }
|
nuclear@9
|
494
|
nuclear@9
|
495 static struct dsys_event *merge_evlists(struct dsys_event *list1, struct dsys_event *list2)
|
nuclear@9
|
496 {
|
nuclear@9
|
497 struct dsys_event *head, *tail, *node;
|
nuclear@9
|
498
|
nuclear@9
|
499 if(!list1) {
|
nuclear@9
|
500 return list2;
|
nuclear@9
|
501 }
|
nuclear@9
|
502 if(!list2) {
|
nuclear@9
|
503 return list1;
|
nuclear@9
|
504 }
|
nuclear@9
|
505
|
nuclear@9
|
506 head = tail = 0;
|
nuclear@9
|
507
|
nuclear@9
|
508 while(list1 && list2) {
|
nuclear@9
|
509 if(list1->t0 < list2->t0) {
|
nuclear@9
|
510 node = list1;
|
nuclear@9
|
511 list1 = list1->next;
|
nuclear@9
|
512 } else {
|
nuclear@9
|
513 node = list2;
|
nuclear@9
|
514 list2 = list2->next;
|
nuclear@9
|
515 }
|
nuclear@9
|
516
|
nuclear@9
|
517 node->next = 0;
|
nuclear@9
|
518 node->prev = tail;
|
nuclear@9
|
519
|
nuclear@9
|
520 if(!head) {
|
nuclear@9
|
521 head = node;
|
nuclear@9
|
522 } else {
|
nuclear@9
|
523 tail->next = node;
|
nuclear@9
|
524 }
|
nuclear@9
|
525 tail = node;
|
nuclear@9
|
526 }
|
nuclear@9
|
527
|
nuclear@9
|
528 if(list1) {
|
nuclear@9
|
529 tail->next = list1;
|
nuclear@9
|
530 list1->prev = tail;
|
nuclear@9
|
531 } else if(list2) {
|
nuclear@9
|
532 tail->next = list2;
|
nuclear@9
|
533 list2->prev = tail;
|
nuclear@9
|
534 }
|
nuclear@9
|
535
|
nuclear@9
|
536 return head;
|
nuclear@9
|
537 }
|