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)