1 /** 2 * ae.ui.timer.sdl2.timer 3 * 4 * License: 5 * This Source Code Form is subject to the terms of 6 * the Mozilla Public License, v. 2.0. If a copy of 7 * the MPL was not distributed with this file, You 8 * can obtain one at http://mozilla.org/MPL/2.0/. 9 * 10 * Authors: 11 * Vladimir Panteleev <ae@cy.md> 12 */ 13 14 module ae.ui.timer.sdl2.timer; 15 16 import derelict.sdl2.sdl; 17 18 public import ae.ui.timer.timer; 19 import ae.ui.app.application; 20 import ae.ui.shell.sdl2.shell : sdlEnforce; 21 22 /// SDL implementation of `Timer`. 23 final class SDLTimer : Timer 24 { 25 override TimerEvent setTimeout (AppCallback fn, uint ms) { return add(fn, ms, false); } /// 26 override TimerEvent setInterval(AppCallback fn, uint ms) { return add(fn, ms, true ); } /// 27 28 private: 29 TimerEvent add(AppCallback fn, uint ms, bool recurring) 30 { 31 auto event = new SDLTimerEvent; 32 event.fn = fn; 33 event.recurring = recurring; 34 event.id = sdlEnforce(SDL_AddTimer(ms, &sdlCallback, cast(void*)event)); 35 return event; 36 } 37 38 extern(C) static uint sdlCallback(uint ms, void* param) nothrow 39 { 40 auto event = cast(SDLTimerEvent)param; 41 try 42 if (event.call()) 43 return ms; 44 else 45 return 0; 46 catch (Exception e) 47 throw new Error("Exception thrown from timer event", e); 48 } 49 } 50 51 private final class SDLTimerEvent : TimerEvent 52 { 53 SDL_TimerID id; 54 AppCallback fn; 55 bool recurring, calling, cancelled; 56 57 // Returns true if it should be rescheduled. 58 bool call() 59 { 60 calling = true; 61 fn.call(); 62 calling = false; 63 return recurring && !cancelled; 64 } 65 66 override void cancel() 67 { 68 if (calling) 69 cancelled = true; 70 else 71 SDL_RemoveTimer(id); 72 } 73 }