Mercurial > MadButterfly
comparison src/animate.c @ 1044:5d4bc2a93c09
Merge from refine_backend_if branch
author | Thinker K.F. Li <thinker@codemud.net> |
---|---|
date | Tue, 23 Nov 2010 11:58:04 +0800 |
parents | 63f2f1daf5d3 |
children | e415c55b4a0d |
comparison
equal
deleted
inserted
replaced
1035:18329b6f77a4 | 1044:5d4bc2a93c09 |
---|---|
24 * called periodically in duration of playing time start at | 24 * called periodically in duration of playing time start at |
25 * 'start time'. When the clock run out the playing time of | 25 * 'start time'. When the clock run out the playing time of |
26 * a word, it call stop of actions in the word. | 26 * a word, it call stop of actions in the word. |
27 * | 27 * |
28 * A program is driven by a timer. Once a program is started, it registers | 28 * A program is driven by a timer. Once a program is started, it registers |
29 * with timer for periodic running. \ref mb_tman_t is timer of | 29 * with timer for periodic running. \ref mb_timer_man_t is timer of |
30 * MadButterfly. The update frequence is 10fps by default, now. | 30 * MadButterfly. The update frequence is 10fps by default, now. |
31 * | 31 * |
32 * \section use_progm How to Use Animation Program? | 32 * \section use_progm How to Use Animation Program? |
33 * Following code block creates a program with 2 words. First word is | 33 * Following code block creates a program with 2 words. First word is |
34 * started immediately after the program been started. It is consisted | 34 * started immediately after the program been started. It is consisted |
59 * act = mb_shift_new(0, -20, coord2, word); | 59 * act = mb_shift_new(0, -20, coord2, word); |
60 * act = mb_visibility_new(VIS_HIDDEN, coord3, word); | 60 * act = mb_visibility_new(VIS_HIDDEN, coord3, word); |
61 * | 61 * |
62 * gettimeofday(&tv, NULL); | 62 * gettimeofday(&tv, NULL); |
63 * MB_TIMEVAL_SET(&mbtv, tv.tv_sec, tv.tv_usec); | 63 * MB_TIMEVAL_SET(&mbtv, tv.tv_sec, tv.tv_usec); |
64 * mb_progm_start(progm, tman, &mbtv); | 64 * mb_progm_start(progm, timer_man, &mbtv); |
65 * \endcode | 65 * \endcode |
66 * | 66 * |
67 * | 67 * |
68 * \sa \ref animate.c | 68 * \sa \ref animate.c |
69 */ | 69 */ |
96 struct _mb_progm { | 96 struct _mb_progm { |
97 redraw_man_t *rdman; | 97 redraw_man_t *rdman; |
98 | 98 |
99 mb_timeval_t start_time; | 99 mb_timeval_t start_time; |
100 int first_playing; /*!< first playing word. */ | 100 int first_playing; /*!< first playing word. */ |
101 mb_tman_t *tman; | 101 mb_timer_man_t *timer_man; |
102 subject_t *complete; /*!< notify when a program is completed. */ | 102 subject_t *complete; /*!< notify when a program is completed. */ |
103 mb_timer_t *cur_timer; | 103 int cur_timer; |
104 | 104 |
105 int n_words; | 105 int n_words; |
106 int max_words; | 106 int max_words; |
107 mb_word_t words[1]; | 107 mb_word_t words[1]; |
108 }; | 108 }; |
137 | 137 |
138 progm->n_words = 0; | 138 progm->n_words = 0; |
139 progm->max_words = max_words; | 139 progm->max_words = max_words; |
140 for(i = 0; i < max_words; i++) | 140 for(i = 0; i < max_words; i++) |
141 STAILQ_INIT(progm->words[i].actions); | 141 STAILQ_INIT(progm->words[i].actions); |
142 progm->cur_timer = -1; | |
142 return progm; | 143 return progm; |
143 } | 144 } |
144 | 145 |
145 void mb_progm_free(mb_progm_t *progm) { | 146 void mb_progm_free(mb_progm_t *progm) { |
146 int n_words; | 147 int n_words; |
231 * \note Program will take a big step at last monent. It is because | 232 * \note Program will take a big step at last monent. It is because |
232 * mb_progm_step() running mb_word_stop() if the word being stop | 233 * mb_progm_step() running mb_word_stop() if the word being stop |
233 * between now and next_tmo. It is not obviously if time stepping | 234 * between now and next_tmo. It is not obviously if time stepping |
234 * small. | 235 * small. |
235 */ | 236 */ |
236 static void mb_progm_step(const mb_timeval_t *tmo, | 237 static void mb_progm_step(int timer_hdl, |
238 const mb_timeval_t *tmo, | |
237 const mb_timeval_t *now, | 239 const mb_timeval_t *now, |
238 void *arg) { | 240 void *arg) { |
239 mb_progm_t *progm = (mb_progm_t *)arg; | 241 mb_progm_t *progm = (mb_progm_t *)arg; |
240 #ifndef UNITTEST | 242 #ifndef UNITTEST |
241 /*! \todo Leverage aspective programming to prevent problem of unittest. | 243 /*! \todo Leverage aspective programming to prevent problem of unittest. |
287 /* Setup timeout for next update. */ | 289 /* Setup timeout for next update. */ |
288 if(progm->first_playing < progm->n_words) { | 290 if(progm->first_playing < progm->n_words) { |
289 word = progm->words + progm->first_playing; | 291 word = progm->words + progm->first_playing; |
290 if(MB_TIMEVAL_LATER(&word->abs_start, &next_tmo)) | 292 if(MB_TIMEVAL_LATER(&word->abs_start, &next_tmo)) |
291 MB_TIMEVAL_CP(&next_tmo, &word->abs_start); | 293 MB_TIMEVAL_CP(&next_tmo, &word->abs_start); |
292 timer = mb_tman_timeout(progm->tman, &next_tmo, | 294 timer = mb_timer_man_timeout(progm->timer_man, &next_tmo, |
293 mb_progm_step, progm); | 295 mb_progm_step, progm); |
294 progm->cur_timer = timer; | 296 progm->cur_timer = timer; |
295 } else { | 297 } else { |
296 /* Make program to complete. */ | 298 /* Make program to complete. */ |
297 #ifndef UNITTEST | 299 #ifndef UNITTEST |
298 comp_evt.event.type = EVT_PROGM_COMPLETE; | 300 comp_evt.event.type = EVT_PROGM_COMPLETE; |
299 comp_evt.event.tgt = comp_evt.event.cur_tgt = progm->complete; | 301 comp_evt.event.tgt = comp_evt.event.cur_tgt = progm->complete; |
300 comp_evt.progm = progm; | 302 comp_evt.progm = progm; |
301 subject_notify(progm->complete, &comp_evt.event); | 303 subject_notify(progm->complete, &comp_evt.event); |
302 #endif /* UNITTEST */ | 304 #endif /* UNITTEST */ |
303 progm->cur_timer = NULL; | 305 progm->cur_timer = -1; |
304 } | 306 } |
305 } | 307 } |
306 | 308 |
307 void mb_progm_start(mb_progm_t *progm, mb_tman_t *tman, | 309 void mb_progm_start(mb_progm_t *progm, mb_timer_man_t *timer_man, |
308 mb_timeval_t *now) { | 310 mb_timeval_t *now) { |
309 mb_timer_t *timer; | 311 int timer; |
310 mb_word_t *word; | 312 mb_word_t *word; |
311 int i; | 313 int i; |
312 | 314 |
313 if(progm->n_words == 0) | 315 if(progm->n_words == 0) |
314 return; | 316 return; |
315 | 317 |
316 progm->tman = tman; | 318 progm->timer_man = timer_man; |
317 MB_TIMEVAL_CP(&progm->start_time, now); | 319 MB_TIMEVAL_CP(&progm->start_time, now); |
318 progm->first_playing = 0; | 320 progm->first_playing = 0; |
319 | 321 |
320 for(i = 0; i < progm->n_words; i++) { | 322 for(i = 0; i < progm->n_words; i++) { |
321 word = progm->words + i; | 323 word = progm->words + i; |
324 MB_TIMEVAL_CP(&word->abs_stop, &word->abs_start); | 326 MB_TIMEVAL_CP(&word->abs_stop, &word->abs_start); |
325 MB_TIMEVAL_ADD(&word->abs_stop, &word->playing_time); | 327 MB_TIMEVAL_ADD(&word->abs_stop, &word->playing_time); |
326 } | 328 } |
327 | 329 |
328 if(MB_TIMEVAL_EQ(&progm->words[0].abs_start, now)) { | 330 if(MB_TIMEVAL_EQ(&progm->words[0].abs_start, now)) { |
329 mb_progm_step(now, now, progm); | 331 mb_progm_step(-1, now, now, progm); |
330 return; | 332 return; |
331 } | 333 } |
332 | 334 |
333 timer = mb_tman_timeout(tman, &progm->words[0].abs_start, | 335 timer = mb_timer_man_timeout(timer_man, &progm->words[0].abs_start, |
334 mb_progm_step, progm); | 336 mb_progm_step, progm); |
335 ASSERT(timer != NULL); | 337 ASSERT(timer != -1); |
336 | 338 |
337 /* We need timer to abort it. */ | 339 /* We need timer to abort it. */ |
338 progm->cur_timer = timer; | 340 progm->cur_timer = timer; |
339 } | 341 } |
340 | 342 |
341 void mb_progm_finish(mb_progm_t *progm) { | 343 void mb_progm_finish(mb_progm_t *progm) { |
342 mb_timeval_t infi; | 344 mb_timeval_t infi; |
343 | 345 |
344 mb_progm_abort(progm); | 346 mb_progm_abort(progm); |
345 MB_TIMEVAL_SET(&infi, 0x7fffffff,0); | 347 MB_TIMEVAL_SET(&infi, 0x7fffffff,0); |
346 mb_progm_step(&progm->start_time, &infi,progm); | 348 mb_progm_step(-1, &progm->start_time, &infi,progm); |
347 } | 349 } |
348 void mb_progm_abort(mb_progm_t *progm) { | 350 void mb_progm_abort(mb_progm_t *progm) { |
349 /*! \todo Make sure abort release resources. */ | 351 /*! \todo Make sure abort release resources. */ |
350 if(progm->cur_timer) { | 352 if(progm->cur_timer != -1) { |
351 mb_tman_remove(progm->tman, progm->cur_timer); | 353 mb_timer_man_remove(progm->timer_man, progm->cur_timer); |
352 progm->cur_timer = NULL; | 354 progm->cur_timer = -1; |
353 } | 355 } |
354 } | 356 } |
355 | 357 |
356 /*! \brief Return event subject for completion of a program. | 358 /*! \brief Return event subject for completion of a program. |
357 */ | 359 */ |
373 subject_add_observer(complete, _free_completed_hdlr, progm); | 375 subject_add_observer(complete, _free_completed_hdlr, progm); |
374 } | 376 } |
375 | 377 |
376 #ifdef UNITTEST | 378 #ifdef UNITTEST |
377 | 379 |
380 #include "mb_backend_utils.h" | |
378 #include <CUnit/Basic.h> | 381 #include <CUnit/Basic.h> |
379 | 382 |
380 typedef struct _mb_dummy mb_dummy_t; | 383 typedef struct _mb_dummy mb_dummy_t; |
381 | 384 |
382 struct _mb_dummy { | 385 struct _mb_dummy { |
439 | 442 |
440 void test_animate_words(void) { | 443 void test_animate_words(void) { |
441 mb_progm_t *progm; | 444 mb_progm_t *progm; |
442 mb_word_t *word; | 445 mb_word_t *word; |
443 mb_action_t *acts[4]; | 446 mb_action_t *acts[4]; |
447 mb_timer_man_t *timer_man; | |
444 mb_tman_t *tman; | 448 mb_tman_t *tman; |
445 mb_timeval_t tv1, tv2, now, tmo_after; | 449 mb_timeval_t tv1, tv2, now, tmo_after; |
446 int logcnt = 0; | 450 int logcnt = 0; |
447 int logs[256]; | 451 int logs[256]; |
448 int r; | 452 int r; |
449 | 453 |
450 tman = mb_tman_new(); | 454 timer_man = mb_timer_man_new(&tman_timer_factory); |
451 CU_ASSERT(tman != NULL); | 455 CU_ASSERT(timer_man != -1); |
456 | |
457 tman = tman_timer_man_get_tman(timer_man); | |
452 | 458 |
453 progm = mb_progm_new(3, NULL); | 459 progm = mb_progm_new(3, NULL); |
454 CU_ASSERT(progm != NULL); | 460 CU_ASSERT(progm != NULL); |
455 | 461 |
456 MB_TIMEVAL_SET(&tv1, 1, 0); | 462 MB_TIMEVAL_SET(&tv1, 1, 0); |
473 CU_ASSERT(word != NULL); | 479 CU_ASSERT(word != NULL); |
474 acts[2] = mb_dummy_new(2, &logcnt, logs, word); | 480 acts[2] = mb_dummy_new(2, &logcnt, logs, word); |
475 CU_ASSERT(acts[2] != NULL); | 481 CU_ASSERT(acts[2] != NULL); |
476 | 482 |
477 MB_TIMEVAL_SET(&now, 0, 0); | 483 MB_TIMEVAL_SET(&now, 0, 0); |
478 mb_progm_start(progm, tman, &now); | 484 mb_progm_start(progm, timer_man, &now); |
479 | 485 |
480 r = mb_tman_next_timeout(tman, &now, &tmo_after); | 486 r = mb_tman_next_timeout(tman, &now, &tmo_after); |
481 CU_ASSERT(r == 0); | 487 CU_ASSERT(r == 0); |
482 CU_ASSERT(MB_TIMEVAL_SEC(&tmo_after) == 1 && | 488 CU_ASSERT(MB_TIMEVAL_SEC(&tmo_after) == 1 && |
483 MB_TIMEVAL_USEC(&tmo_after) == 0); | 489 MB_TIMEVAL_USEC(&tmo_after) == 0); |
539 | 545 |
540 r = mb_tman_next_timeout(tman, &now, &tmo_after); | 546 r = mb_tman_next_timeout(tman, &now, &tmo_after); |
541 CU_ASSERT(r == -1); | 547 CU_ASSERT(r == -1); |
542 | 548 |
543 mb_progm_free(progm); | 549 mb_progm_free(progm); |
544 mb_tman_free(tman); | 550 mb_timer_man_free(&tman_timer_factory, timer_man); |
545 } | 551 } |
546 | 552 |
547 CU_pSuite get_animate_suite(void) { | 553 CU_pSuite get_animate_suite(void) { |
548 CU_pSuite suite; | 554 CU_pSuite suite; |
549 | 555 |