1 /**
2 	Driver implentation for WinRT
3 
4 	This is only implemented for timers and files.
5 
6 	See_Also:
7 		`vibe.core.driver` = interface definition
8 
9 	Copyright: © 2012-2015 Sönke Ludwig
10 	Authors: Sönke Ludwig
11 	License: Subject to the terms of the MIT license, as written in the included LICENSE.txt file.
12 */
13 module vibe.core.drivers.winrt;
14 
15 version(VibeWinrtDriver)
16 {
17 
18 	import vibe.core.driver;
19 	import vibe.inet.url;
20 	import deimos.winrt.windows.applicationmodel.core;
21 	import deimos.winrt.windows.ui.core;
22 	import deimos.winrt.windows.ui.xaml._ : DispatcherTimer;
23 	import winrtd.generics;
24 	import deimos.winrt.windows.foundation._;
25 	import deimos.winrt._;
26 	import deimos.winrt.roapi;
27 	import winrtd.comsupport;
28 	import winrtd.roapi;
29 
30 	import core.atomic;
31 	import core.time;
32 
33 	shared static this()
34 	{
35 		comCheck(RoInitialize(RO_INIT_TYPE.MULTITHREADED), "RoInitialize");
36 	}
37 
38 	shared static ~this()
39 	{
40 		RoUninitialize();
41 	}
42 
43 	final class WinRTEventDriver : EventDriver {
44 		private {
45 			DriverCore m_core;
46 			bool m_exit = false;
47 		}
48 
49 		this(DriverCore core)
50 		{
51 			m_core = core;
52 
53 		}
54 
55 		void dispose()
56 		{
57 		}
58 
59 		int runEventLoop()
60 		{
61 			processEventsInternal(CoreProcessEventsOption.ProcessUntilQuit);
62 			return 0;
63 		}
64 
65 		int runEventLoopOnce()
66 		{
67 			processEventsInternal(CoreProcessEventsOption.ProcessOneAndAllPending);
68 			return 0;
69 		}
70 
71 		bool processEvents()
72 		{
73 			return processEventsInternal(CoreProcessEventsOption.ProcessAllIfPresent);
74 		}
75 
76 		bool processEventsInternal(CoreProcessEventsOption mode)
77 		{
78 			auto window = CoreWindow.getForCurrentThread();
79 			window.dispatcher.processEvents(mode);
80 			return window.visible;
81 		}
82 
83 		void exitEventLoop()
84 		{
85 			CoreWindow.getForCurrentThread().close();
86 			//CoreApplication.exit();
87 		}
88 
89 		FileStream openFile(Path path, FileMode mode)
90 		{
91 			//return new WinRTFileStream(path, mode);
92 			import vibe.core.drivers.threadedfile;
93 			return new ThreadedFileStream(path, mode);
94 		}
95 
96 		DirectoryWatcher watchDirectory(Path path, bool recursive)
97 		{
98 			assert(false);
99 		}
100 
101 		NetworkAddress resolveHost(string host, ushort family, bool use_dns)
102 		{
103 			assert(false);
104 		}
105 
106 		WinRTTCPConnection connectTCP(string host, ushort port)
107 		{
108 			assert(false);
109 		}
110 
111 		TCPListener listenTCP(ushort port, void delegate(TCPConnection conn) conn_callback, string bind_address, TCPListenOptions options)
112 		{
113 			assert(false);
114 		}
115 
116 		UDPConnection listenUDP(ushort port, string bind_address = "0.0.0.0")
117 		{
118 			assert(false);
119 		}
120 
121 		WinRTManualEvent createManualEvent()
122 		{
123 			return new WinRTManualEvent(this);
124 		}
125 
126 		WinRTTimer createTimer(void delegate() callback)
127 		{
128 			return new WinRTTimer(this, callback);
129 		}
130 	}
131 
132 	class WinRTManualEvent : ManualEvent {
133 		private {
134 			WinRTEventDriver m_driver;
135 			shared(int) m_emitCount;
136 			Task[] m_waiters;
137 		}
138 
139 		this(WinRTEventDriver driver)
140 		{
141 			m_driver = driver;
142 		}
143 
144 		@property int emitCount() const { return m_emitCount; }
145 
146 		void emit()
147 		{
148 			atomicOp!"+="(m_emitCount, 1);
149 			auto wtrs = m_waiters;
150 			m_waiters = null;
151 			foreach (t; wtrs)
152 				m_driver.m_core.resumeTask(t);
153 		}
154 
155 		void wait()
156 		{
157 			wait(this.emitCount);
158 		}
159 
160 		int wait(int reference_emit_count)
161 		{
162 			m_waiters ~= Task.getThis();
163 			int rc;
164 			while ((rc = this.emitCount) == reference_emit_count) m_driver.m_core.yieldForEvent();
165 			return rc;
166 		}
167 
168 		int wait(Duration timeout, int reference_emit_count)
169 		{
170 			assert(false);
171 		}
172 	}
173 
174 	class WinRTTimer : Timer {
175 		private {
176 			WinRTEventDriver m_driver;
177 			void delegate() m_callback;
178 			DispatcherTimer m_timer;
179 			EventConnection m_eventConn;
180 			bool m_periodic;
181 			Task[] m_waiters;
182 		}
183 
184 		this(WinRTEventDriver driver, void delegate() callback)
185 		{
186 			m_driver = driver;
187 			m_callback = callback;
188 			m_eventConn = m_timer.invokeOnTick((sender, timer) {
189 				if (m_callback) m_callback();
190 				foreach (t; m_waiters)
191 					m_driver.m_core.resumeTask(t);
192 			});
193 		}
194 
195 		~this()
196 		{
197 			m_eventConn.disconnect();
198 		}
199 
200 		@property bool pending() { return m_timer.isEnabled; }
201 
202 		void rearm(Duration dur, bool periodic = false)
203 		{
204 			if (m_timer) m_timer.stop();
205 			else m_timer = new DispatcherTimer;
206 			m_timer.interval = TimeSpan(dur.total!"hnsecs"());
207 			m_timer.start();
208 			m_periodic = periodic;
209 		}
210 
211 		void stop()
212 		{
213 			if (m_timer.isEnabled)
214 				m_timer.stop();
215 		}
216 
217 		void wait()
218 		{
219 			while (m_timer.isEnabled)
220 				m_driver.m_core.yieldForEvent();
221 		}
222 	}
223 
224 	class WinRTFileStream : FileStream {
225 		private {
226 		}
227 
228 		this(Path path, FileMode mode)
229 		{
230 			assert(false);
231 		}
232 
233 		void close()
234 		{
235 		}
236 
237 		@property Path path() const { assert(false); }
238 
239 		@property bool isOpen() const { assert(false); }
240 
241 		@property ulong size()
242 		const {
243 			assert(false);
244 		}
245 
246 		@property bool readable()
247 		const {
248 			assert(false);
249 		}
250 
251 		@property bool writable()
252 		const {
253 			assert(false);
254 		}
255 
256 		void seek(ulong offset)
257 		{
258 		}
259 
260 		ulong tell()
261 		{
262 			assert(false);
263 		}
264 
265 		@property bool empty() { assert(false); }
266 
267 		@property ulong leastSize() { assert(false); }
268 
269 		@property bool dataAvailableForRead() { assert(false); }
270 
271 		const(ubyte)[] peek() { assert(false); }
272 
273 		void read(ubyte[] dst)
274 		{
275 		}
276 
277 		void write(in ubyte[] bytes)
278 		{
279 		}
280 
281 		void flush()
282 		{
283 		}
284 
285 		void finalize()
286 		{
287 		}
288 	}
289 
290 	class WinRTTCPConnection : TCPConnection {
291 		private {
292 			bool m_tcpNoDelay;
293 			bool m_keepAlive;
294 			Duration m_readTimeout;
295 		}
296 
297 		@property void tcpNoDelay(bool enabled)
298 		{
299 			m_tcpNoDelay = enabled;
300 			assert(false);
301 		}
302 		@property bool tcpNoDelay() const { return m_tcpNoDelay; }
303 
304 		@property void readTimeout(Duration v){
305 			m_readTimeout = v;
306 			assert(false);
307 		}
308 		@property Duration readTimeout() const { return m_readTimeout; }
309 
310 		@property void keepAlive(bool enabled)
311 		{
312 			m_keepAlive = enabled;
313 			assert(false);
314 		}
315 		@property bool keepAlive() const { return m_keepAlive; }
316 
317 		void close()
318 		{
319 		}
320 
321 		@property bool connected()
322 		const {
323 			assert(false);
324 		}
325 
326 		@property string peerAddress()
327 		const {
328 			assert(false);
329 		}
330 
331 		bool waitForData(Duration timeout)
332 		{
333 			assert(false);
334 		}
335 
336 		@property bool empty() { assert(false); }
337 
338 		@property ulong leastSize() { assert(false); }
339 
340 		@property bool dataAvailableForRead() { assert(false); }
341 
342 		const(ubyte)[] peek() { assert(false); }
343 
344 		void read(ubyte[] dst)
345 		{
346 		}
347 
348 		void write(in ubyte[] bytes)
349 		{
350 		}
351 
352 		void flush()
353 		{
354 		}
355 
356 		void finalize()
357 		{
358 		}
359 	}
360 
361 } // version(VibeWinrtDriver)