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 <vladimir@thecybershadow.net> 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 final class SDLTimer : Timer 23 { 24 override TimerEvent setTimeout (AppCallback fn, uint ms) { return add(fn, ms, false); } 25 override TimerEvent setInterval(AppCallback fn, uint ms) { return add(fn, ms, true ); } 26 27 private: 28 TimerEvent add(AppCallback fn, uint ms, bool recurring) 29 { 30 auto event = new SDLTimerEvent; 31 event.fn = fn; 32 event.recurring = recurring; 33 event.id = sdlEnforce(SDL_AddTimer(ms, &sdlCallback, cast(void*)event)); 34 return event; 35 } 36 37 extern(C) static uint sdlCallback(uint ms, void* param) nothrow 38 { 39 auto event = cast(SDLTimerEvent)param; 40 try 41 if (event.call()) 42 return ms; 43 else 44 return 0; 45 catch (Exception e) 46 throw new Error("Exception thrown from timer event", e); 47 } 48 } 49 50 private final class SDLTimerEvent : TimerEvent 51 { 52 SDL_TimerID id; 53 AppCallback fn; 54 bool recurring, calling, cancelled; 55 56 // Returns true if it should be rescheduled. 57 bool call() 58 { 59 calling = true; 60 fn.call(); 61 calling = false; 62 return recurring && !cancelled; 63 } 64 65 override void cancel() 66 { 67 if (calling) 68 cancelled = true; 69 else 70 SDL_RemoveTimer(id); 71 } 72 }