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 }