timer.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #include "timer.h"
  2. #include <SDL.h>
  3. bbInt g_mojo_app_AppInstance_AddAsyncCallback(bbFunction<void()> l_func);
  4. void g_mojo_app_AppInstance_RemoveAsyncCallback( bbInt id );
  5. void g_mojo_app_AppInstance_EnableAsyncCallback( bbInt id );
  6. void g_mojo_app_AppInstance_DisableAsyncCallback( bbInt id );
  7. struct bbTimer::Rep{
  8. int _freq;
  9. int _interval;
  10. int _remainder;
  11. int _accumulator;
  12. bool _suspended;
  13. bool _cancelled;
  14. bool _reset;
  15. int _callback;
  16. int _timer;
  17. };
  18. namespace{
  19. const int INVOKE=0x40000000;
  20. const int REMOVE=0x80000000;
  21. void postEvent( int code ){
  22. SDL_UserEvent event;
  23. event.type=SDL_USEREVENT;
  24. event.code=code;
  25. event.data1=0;
  26. event.data2=0;
  27. if( SDL_PeepEvents( (SDL_Event*)&event,1,SDL_ADDEVENT,SDL_FIRSTEVENT,SDL_LASTEVENT )!=1 ){
  28. printf(" SDL_PeepEvents error!\n" );fflush( stdout );
  29. }
  30. }
  31. }
  32. bbTimer::bbTimer( int freq,bbFunction<void()> fired ){
  33. int p=1000/freq;
  34. _rep=new Rep;
  35. _rep->_freq=freq;
  36. _rep->_interval=p;
  37. _rep->_remainder=1000-p*freq;
  38. _rep->_accumulator=0;
  39. _rep->_suspended=true;
  40. _rep->_cancelled=false;
  41. _rep->_reset=false;
  42. _rep->_callback=g_mojo_app_AppInstance_AddAsyncCallback( fired );
  43. setSuspended( false );
  44. }
  45. bool bbTimer::suspended(){
  46. if( !_rep ) return false;
  47. return _rep->_suspended;
  48. }
  49. void bbTimer::setSuspended( bool suspended ){
  50. if( !_rep ) return;
  51. if( suspended==_rep->_suspended ) return;
  52. if( _rep->_suspended=suspended ){
  53. SDL_RemoveTimer( _rep->_timer );
  54. g_mojo_app_AppInstance_DisableAsyncCallback( _rep->_callback );
  55. }else{
  56. g_mojo_app_AppInstance_EnableAsyncCallback( _rep->_callback );
  57. _rep->_timer=SDL_AddTimer( _rep->_interval,sdl_timer_callback,(void*)_rep );
  58. }
  59. }
  60. void bbTimer::reset(){
  61. if( !_rep ) return;
  62. _rep->_reset=true;
  63. }
  64. void bbTimer::cancel(){
  65. if( !_rep ) return;
  66. g_mojo_app_AppInstance_RemoveAsyncCallback( _rep->_callback );
  67. _rep->_suspended=true;
  68. _rep->_cancelled=true;
  69. _rep=nullptr;
  70. }
  71. unsigned bbTimer::sdl_timer_callback( unsigned interval,void *param ){
  72. bbTimer::Rep *rep=(bbTimer::Rep*)param;
  73. if( rep->_suspended ){
  74. if( rep->_cancelled ) delete rep;
  75. return 0;
  76. }
  77. /*
  78. if( rep->_reset ){
  79. rep->_reset=false;
  80. rep->_accumulator=0;
  81. return SDL_GetTicks()+interval;
  82. }
  83. */
  84. postEvent( rep->_callback|INVOKE );
  85. rep->_accumulator+=rep->_remainder;
  86. if( rep->_accumulator>=rep->_freq ){
  87. rep->_accumulator-=rep->_freq;
  88. return rep->_interval+1;
  89. }
  90. return rep->_interval;
  91. }