comparison src/animate.c @ 48:bdf711cbf0fb

Use absolute time to dispatch animation actions.
author Thinker K.F. Li <thinker@branda.to>
date Sat, 09 Aug 2008 18:26:20 +0800
parents f3818d996f4f
children c986e45c1e91
comparison
equal deleted inserted replaced
47:f3818d996f4f 48:bdf711cbf0fb
28 /*! \brief A word is a set of concurrent actions in a program. 28 /*! \brief A word is a set of concurrent actions in a program.
29 */ 29 */
30 struct _mb_word { 30 struct _mb_word {
31 mb_timeval_t start_time; /*!< time to start the word */ 31 mb_timeval_t start_time; /*!< time to start the word */
32 mb_timeval_t playing_time; /*!< time duration of playing */ 32 mb_timeval_t playing_time; /*!< time duration of playing */
33 mb_timeval_t abs_start, abs_stop;
33 STAILQ(mb_action_t) actions; 34 STAILQ(mb_action_t) actions;
34 }; 35 };
35 36
36 /*! \brief A program describe a series of actions to animate shapes. 37 /*! \brief A program describe a series of actions to animate shapes.
37 */ 38 */
163 */ 164 */
164 static void mb_progm_step(const mb_timeval_t *tmo, 165 static void mb_progm_step(const mb_timeval_t *tmo,
165 const mb_timeval_t *now, 166 const mb_timeval_t *now,
166 void *arg) { 167 void *arg) {
167 mb_progm_t *progm = (mb_progm_t *)arg; 168 mb_progm_t *progm = (mb_progm_t *)arg;
168 mb_timeval_t next_tmo, word_stop; 169 mb_timeval_t next_tmo;
169 mb_timeval_t tmo_diff, next_diff;
170 mb_word_t *word; 170 mb_word_t *word;
171 mb_timer_t *timer; 171 mb_timer_t *timer;
172 int i; 172 int i;
173 173
174 MB_TIMEVAL_CP(&tmo_diff, tmo); 174 MB_TIMEVAL_SET(&next_tmo, 0, STEP_INTERVAL);
175 MB_TIMEVAL_DIFF(&tmo_diff, &progm->start_time); 175 MB_TIMEVAL_ADD(&next_tmo, tmo);
176 176
177 MB_TIMEVAL_SET(&next_diff, 0, STEP_INTERVAL); 177 /* _step() or _stop() words that in playing. */
178 MB_TIMEVAL_ADD(&next_diff, &tmo_diff);
179
180 i = progm->first_playing; 178 i = progm->first_playing;
181 for(word = progm->words + i; 179 for(word = progm->words + i;
182 i < progm->n_words && 180 i < progm->n_words && MB_TIMEVAL_LATER(tmo, &word->abs_start);
183 MB_TIMEVAL_LATER(&tmo_diff, &word->start_time);
184 word = progm->words + ++i) { 181 word = progm->words + ++i) {
185 MB_TIMEVAL_CP(&word_stop, &word->start_time); 182 if(MB_TIMEVAL_LATER(tmo, &word->abs_stop))
186 MB_TIMEVAL_ADD(&word_stop, &word->playing_time); 183 continue;
187 if(MB_TIMEVAL_LATER(&next_diff, &word_stop)) 184 if(MB_TIMEVAL_LATER(&next_tmo, &word->abs_stop))
188 mb_word_stop(word, tmo, now, progm->rdman); 185 mb_word_stop(word, tmo, now, progm->rdman);
189 else 186 else
190 mb_word_step(word, tmo, now, progm->rdman); 187 mb_word_step(word, tmo, now, progm->rdman);
191 } 188 }
192 189
190 /* Start words that their abs_start is in duration
191 * from now to timeout for next update.
192 */
193 for(word = progm->words + i; 193 for(word = progm->words + i;
194 i < progm->n_words && 194 i < progm->n_words && MB_TIMEVAL_LATER(&next_tmo, &word->abs_start);
195 MB_TIMEVAL_LATER(&next_diff, &word->start_time);
196 word = progm->words + ++i) { 195 word = progm->words + ++i) {
197 mb_word_start(word, tmo, now, progm->rdman); 196 mb_word_start(word, tmo, now, progm->rdman);
198 MB_TIMEVAL_CP(&word_stop, &word->start_time); 197 if(MB_TIMEVAL_LATER(&next_tmo, &word->abs_stop))
199 MB_TIMEVAL_ADD(&word_stop, &word->playing_time);
200 if(MB_TIMEVAL_LATER(&next_diff, &word_stop))
201 mb_word_stop(word, tmo, now, progm->rdman); 198 mb_word_stop(word, tmo, now, progm->rdman);
202 } 199 }
203 200
201 /* Find a new first_playing if any consequence words, following current
202 * first_playing word, are stoped.
203 */
204 i = progm->first_playing; 204 i = progm->first_playing;
205 for(word = progm->words + i; 205 for(word = progm->words + i;
206 i < progm->n_words && 206 i < progm->n_words && MB_TIMEVAL_LATER(&next_tmo, &word->abs_stop);
207 MB_TIMEVAL_LATER(&next_diff, &word->start_time);
208 word = progm->words + ++i) { 207 word = progm->words + ++i) {
209 MB_TIMEVAL_CP(&word_stop, &word->start_time);
210 MB_TIMEVAL_ADD(&word_stop, &word->playing_time);
211 if(!MB_TIMEVAL_LATER(&next_diff, &word_stop))
212 break;
213 progm->first_playing++; 208 progm->first_playing++;
214 } 209 }
215 210
211 /* Setup timeout for next update. */
216 if(progm->first_playing < progm->n_words) { 212 if(progm->first_playing < progm->n_words) {
217 word = progm->words + progm->first_playing; 213 word = progm->words + progm->first_playing;
218 if(MB_TIMEVAL_LATER(&word->start_time, &next_diff)) { 214 if(MB_TIMEVAL_LATER(&word->abs_start, &next_tmo))
219 MB_TIMEVAL_CP(&next_tmo, &word->start_time); 215 MB_TIMEVAL_CP(&next_tmo, &word->abs_start);
220 MB_TIMEVAL_ADD(&next_tmo, &progm->start_time);
221 } else {
222 MB_TIMEVAL_CP(&next_tmo, &next_diff);
223 MB_TIMEVAL_ADD(&next_tmo, &progm->start_time);
224 }
225 timer = mb_tman_timeout(progm->tman, &next_tmo, 216 timer = mb_tman_timeout(progm->tman, &next_tmo,
226 mb_progm_step, progm); 217 mb_progm_step, progm);
227 } 218 }
228 } 219 }
229 220
230 void mb_progm_start(mb_progm_t *progm, mb_tman_t *tman, 221 void mb_progm_start(mb_progm_t *progm, mb_tman_t *tman,
231 mb_timeval_t *now) { 222 mb_timeval_t *now) {
232 mb_timeval_t next_time;
233 mb_timer_t *timer; 223 mb_timer_t *timer;
224 mb_word_t *word;
225 int i;
234 226
235 if(progm->n_words == 0) 227 if(progm->n_words == 0)
236 return; 228 return;
237 229
238 progm->tman = tman; 230 progm->tman = tman;
239 MB_TIMEVAL_CP(&progm->start_time, now); 231 MB_TIMEVAL_CP(&progm->start_time, now);
240 progm->first_playing = 0; 232 progm->first_playing = 0;
241 233
242 MB_TIMEVAL_CP(&next_time, &progm->words[0].start_time); 234 for(i = 0; i < progm->n_words; i++) {
243 MB_TIMEVAL_ADD(&next_time, now); 235 word = progm->words + i;
244 if(!MB_TIMEVAL_LATER(&next_time, now)) { 236 MB_TIMEVAL_CP(&word->abs_start, &word->start_time);
245 mb_progm_step(&next_time, now, progm); 237 MB_TIMEVAL_ADD(&word->abs_start, now);
238 MB_TIMEVAL_CP(&word->abs_stop, &word->abs_start);
239 MB_TIMEVAL_ADD(&word->abs_stop, &word->playing_time);
240 }
241
242 if(MB_TIMEVAL_EQ(&progm->words[0].abs_start, now)) {
243 mb_progm_step(now, now, progm);
246 return; 244 return;
247 } 245 }
248 246
249 timer = mb_tman_timeout(tman, &next_time, mb_progm_step, progm); 247 timer = mb_tman_timeout(tman, &progm->words[0].abs_start,
248 mb_progm_step, progm);
250 ASSERT(timer != NULL); 249 ASSERT(timer != NULL);
251 } 250 }
252 251
253 void mb_progm_abort(mb_progm_t *progm, mb_tman_t *tman) { 252 void mb_progm_abort(mb_progm_t *progm, mb_tman_t *tman) {
254 } 253 }