Mercurial > hg > orthanc-stone
comparison Deprecated/Platforms/Wasm/Defaults.cpp @ 1400:419d0320c344
moved Platforms into Deprecated
author | Alain Mazy <alain@mazy.be> |
---|---|
date | Wed, 29 Apr 2020 20:45:14 +0200 |
parents | Platforms/Wasm/Defaults.cpp@92a043b8e431 |
children | 828a9b4ee1b7 |
comparison
equal
deleted
inserted
replaced
1399:ff8d2e46ac63 | 1400:419d0320c344 |
---|---|
1 #include "Defaults.h" | |
2 | |
3 #include "WasmWebService.h" | |
4 #include "WasmDelayedCallExecutor.h" | |
5 #include "../../Framework/Deprecated/Widgets/TestCairoWidget.h" | |
6 #include <Framework/Deprecated/Viewport/WidgetViewport.h> | |
7 #include <Applications/Wasm/StartupParametersBuilder.h> | |
8 #include <Platforms/Wasm/WasmPlatformApplicationAdapter.h> | |
9 #include <Framework/StoneInitialization.h> | |
10 #include <Core/Logging.h> | |
11 #include <sstream> | |
12 | |
13 #include <algorithm> | |
14 | |
15 | |
16 static unsigned int width_ = 0; | |
17 static unsigned int height_ = 0; | |
18 | |
19 /**********************************/ | |
20 | |
21 static std::unique_ptr<OrthancStone::IStoneApplication> application; | |
22 static std::unique_ptr<OrthancStone::WasmPlatformApplicationAdapter> applicationWasmAdapter = NULL; | |
23 static std::unique_ptr<OrthancStone::StoneApplicationContext> context; | |
24 static OrthancStone::StartupParametersBuilder startupParametersBuilder; | |
25 static OrthancStone::MessageBroker broker; | |
26 | |
27 static OrthancStone::ViewportContentChangedObserver viewportContentChangedObserver_(broker); | |
28 static OrthancStone::StatusBar statusBar_; | |
29 | |
30 static std::list<std::shared_ptr<Deprecated::WidgetViewport>> viewports_; | |
31 | |
32 std::shared_ptr<Deprecated::WidgetViewport> FindViewportSharedPtr(ViewportHandle viewport) { | |
33 for (const auto& v : viewports_) { | |
34 if (v.get() == viewport) { | |
35 return v; | |
36 } | |
37 } | |
38 assert(false); | |
39 return std::shared_ptr<Deprecated::WidgetViewport>(); | |
40 } | |
41 | |
42 #ifdef __cplusplus | |
43 extern "C" { | |
44 #endif | |
45 | |
46 #if 0 | |
47 // rewrite malloc/free in order to monitor allocations. We actually only monitor large allocations (like images ...) | |
48 | |
49 size_t bigChunksTotalSize = 0; | |
50 std::map<void*, size_t> allocatedBigChunks; | |
51 | |
52 extern void* emscripten_builtin_malloc(size_t bytes); | |
53 extern void emscripten_builtin_free(void* mem); | |
54 | |
55 void * __attribute__((noinline)) malloc(size_t size) | |
56 { | |
57 void *ptr = emscripten_builtin_malloc(size); | |
58 if (size > 100000) | |
59 { | |
60 bigChunksTotalSize += size; | |
61 printf("++ Allocated %zu bytes, got %p. (%zu MB consumed by big chunks)\n", size, ptr, bigChunksTotalSize/(1024*1024)); | |
62 allocatedBigChunks[ptr] = size; | |
63 } | |
64 return ptr; | |
65 } | |
66 | |
67 void __attribute__((noinline)) free(void *ptr) | |
68 { | |
69 emscripten_builtin_free(ptr); | |
70 | |
71 std::map<void*, size_t>::iterator it = allocatedBigChunks.find(ptr); | |
72 if (it != allocatedBigChunks.end()) | |
73 { | |
74 bigChunksTotalSize -= it->second; | |
75 printf("-- Freed %zu bytes at %p. (%zu MB consumed by big chunks)\n", it->second, ptr, bigChunksTotalSize/(1024*1024)); | |
76 allocatedBigChunks.erase(it); | |
77 } | |
78 } | |
79 #endif // 0 | |
80 | |
81 using namespace OrthancStone; | |
82 | |
83 // when WASM needs a C++ viewport | |
84 ViewportHandle EMSCRIPTEN_KEEPALIVE CreateCppViewport() { | |
85 | |
86 std::shared_ptr<Deprecated::WidgetViewport> viewport(new Deprecated::WidgetViewport(broker)); | |
87 printf("viewport %x\n", (int)viewport.get()); | |
88 | |
89 viewports_.push_back(viewport); | |
90 | |
91 printf("There are now %lu viewports in C++\n", viewports_.size()); | |
92 | |
93 viewport->SetStatusBar(statusBar_); | |
94 | |
95 viewport->RegisterObserverCallback( | |
96 new Callable<ViewportContentChangedObserver, Deprecated::IViewport::ViewportChangedMessage> | |
97 (viewportContentChangedObserver_, &ViewportContentChangedObserver::OnViewportChanged)); | |
98 | |
99 return viewport.get(); | |
100 } | |
101 | |
102 // when WASM does not need a viewport anymore, it should release it | |
103 void EMSCRIPTEN_KEEPALIVE ReleaseCppViewport(ViewportHandle viewport) { | |
104 viewports_.remove_if([viewport](const std::shared_ptr<Deprecated::WidgetViewport>& v) { return v.get() == viewport;}); | |
105 | |
106 printf("There are now %lu viewports in C++\n", viewports_.size()); | |
107 } | |
108 | |
109 void EMSCRIPTEN_KEEPALIVE CreateWasmApplication(ViewportHandle viewport) { | |
110 printf("Initializing Stone\n"); | |
111 OrthancStone::StoneInitialize(); | |
112 printf("CreateWasmApplication\n"); | |
113 | |
114 application.reset(CreateUserApplication(broker)); | |
115 applicationWasmAdapter.reset(CreateWasmApplicationAdapter(broker, application.get())); | |
116 Deprecated::WasmWebService::SetBroker(broker); | |
117 Deprecated::WasmDelayedCallExecutor::SetBroker(broker); | |
118 | |
119 startupParametersBuilder.Clear(); | |
120 } | |
121 | |
122 void EMSCRIPTEN_KEEPALIVE SetStartupParameter(const char* keyc, | |
123 const char* value) { | |
124 startupParametersBuilder.SetStartupParameter(keyc, value); | |
125 } | |
126 | |
127 void EMSCRIPTEN_KEEPALIVE StartWasmApplication(const char* baseUri) { | |
128 | |
129 printf("StartWasmApplication\n"); | |
130 | |
131 Orthanc::Logging::SetErrorWarnInfoTraceLoggingFunctions( | |
132 stone_console_error, stone_console_warning, | |
133 stone_console_info, stone_console_trace); | |
134 | |
135 // recreate a command line from uri arguments and parse it | |
136 boost::program_options::variables_map parameters; | |
137 boost::program_options::options_description options; | |
138 application->DeclareStartupOptions(options); | |
139 startupParametersBuilder.GetStartupParameters(parameters, options); | |
140 | |
141 context.reset(new OrthancStone::StoneApplicationContext(broker)); | |
142 context->SetOrthancBaseUrl(baseUri); | |
143 printf("Base URL to Orthanc API: [%s]\n", baseUri); | |
144 context->SetWebService(Deprecated::WasmWebService::GetInstance()); | |
145 context->SetDelayedCallExecutor(Deprecated::WasmDelayedCallExecutor::GetInstance()); | |
146 application->Initialize(context.get(), statusBar_, parameters); | |
147 application->InitializeWasm(); | |
148 | |
149 // viewport->SetSize(width_, height_); | |
150 printf("StartWasmApplication - completed\n"); | |
151 } | |
152 | |
153 bool EMSCRIPTEN_KEEPALIVE WasmIsTraceLevelEnabled() | |
154 { | |
155 return Orthanc::Logging::IsTraceLevelEnabled(); | |
156 } | |
157 | |
158 bool EMSCRIPTEN_KEEPALIVE WasmIsInfoLevelEnabled() | |
159 { | |
160 return Orthanc::Logging::IsInfoLevelEnabled(); | |
161 } | |
162 | |
163 void EMSCRIPTEN_KEEPALIVE WasmDoAnimation() | |
164 { | |
165 for (auto viewport : viewports_) { | |
166 // TODO Only launch the JavaScript timer if "HasAnimation()" | |
167 if (viewport->HasAnimation()) | |
168 { | |
169 viewport->DoAnimation(); | |
170 } | |
171 | |
172 } | |
173 | |
174 } | |
175 | |
176 | |
177 void EMSCRIPTEN_KEEPALIVE ViewportSetSize(ViewportHandle viewport, unsigned int width, unsigned int height) | |
178 { | |
179 width_ = width; | |
180 height_ = height; | |
181 | |
182 viewport->SetSize(width, height); | |
183 } | |
184 | |
185 int EMSCRIPTEN_KEEPALIVE ViewportRender(ViewportHandle viewport, | |
186 unsigned int width, | |
187 unsigned int height, | |
188 uint8_t* data) | |
189 { | |
190 viewportContentChangedObserver_.Reset(); | |
191 | |
192 //printf("ViewportRender called %dx%d\n", width, height); | |
193 if (width == 0 || | |
194 height == 0) | |
195 { | |
196 return 1; | |
197 } | |
198 | |
199 Orthanc::ImageAccessor surface; | |
200 surface.AssignWritable(Orthanc::PixelFormat_BGRA32, width, height, 4 * width, data); | |
201 | |
202 viewport->Render(surface); | |
203 | |
204 // Convert from BGRA32 memory layout (only color mode supported by | |
205 // Cairo, which corresponds to CAIRO_FORMAT_ARGB32) to RGBA32 (as | |
206 // expected by HTML5 canvas). This simply amounts to swapping the | |
207 // B and R channels. | |
208 uint8_t* p = data; | |
209 for (unsigned int y = 0; y < height; y++) { | |
210 for (unsigned int x = 0; x < width; x++) { | |
211 uint8_t tmp = p[0]; | |
212 p[0] = p[2]; | |
213 p[2] = tmp; | |
214 | |
215 p += 4; | |
216 } | |
217 } | |
218 | |
219 return 1; | |
220 } | |
221 | |
222 | |
223 void EMSCRIPTEN_KEEPALIVE ViewportMouseDown(ViewportHandle viewport, | |
224 unsigned int rawButton, | |
225 int x, | |
226 int y, | |
227 unsigned int rawModifiers) | |
228 { | |
229 OrthancStone::MouseButton button; | |
230 switch (rawButton) | |
231 { | |
232 case 0: | |
233 button = OrthancStone::MouseButton_Left; | |
234 break; | |
235 | |
236 case 1: | |
237 button = OrthancStone::MouseButton_Middle; | |
238 break; | |
239 | |
240 case 2: | |
241 button = OrthancStone::MouseButton_Right; | |
242 break; | |
243 | |
244 default: | |
245 return; // Unknown button | |
246 } | |
247 | |
248 viewport->MouseDown(button, x, y, OrthancStone::KeyboardModifiers_None, std::vector<Deprecated::Touch>()); | |
249 } | |
250 | |
251 | |
252 void EMSCRIPTEN_KEEPALIVE ViewportMouseWheel(ViewportHandle viewport, | |
253 int deltaY, | |
254 int x, | |
255 int y, | |
256 int isControl) | |
257 { | |
258 if (deltaY != 0) | |
259 { | |
260 OrthancStone::MouseWheelDirection direction = (deltaY < 0 ? | |
261 OrthancStone::MouseWheelDirection_Up : | |
262 OrthancStone::MouseWheelDirection_Down); | |
263 OrthancStone::KeyboardModifiers modifiers = OrthancStone::KeyboardModifiers_None; | |
264 | |
265 if (isControl != 0) | |
266 { | |
267 modifiers = OrthancStone::KeyboardModifiers_Control; | |
268 } | |
269 | |
270 viewport->MouseWheel(direction, x, y, modifiers); | |
271 } | |
272 } | |
273 | |
274 | |
275 void EMSCRIPTEN_KEEPALIVE ViewportMouseMove(ViewportHandle viewport, | |
276 int x, | |
277 int y) | |
278 { | |
279 viewport->MouseMove(x, y, std::vector<Deprecated::Touch>()); | |
280 } | |
281 | |
282 void GetTouchVector(std::vector<Deprecated::Touch>& output, | |
283 int touchCount, | |
284 float x0, | |
285 float y0, | |
286 float x1, | |
287 float y1, | |
288 float x2, | |
289 float y2) | |
290 { | |
291 // TODO: it might be nice to try to pass all the x0,y0 coordinates as arrays but that's not so easy to pass array between JS and C++ | |
292 if (touchCount > 0) | |
293 { | |
294 output.push_back(Deprecated::Touch(x0, y0)); | |
295 } | |
296 if (touchCount > 1) | |
297 { | |
298 output.push_back(Deprecated::Touch(x1, y1)); | |
299 } | |
300 if (touchCount > 2) | |
301 { | |
302 output.push_back(Deprecated::Touch(x2, y2)); | |
303 } | |
304 | |
305 } | |
306 | |
307 void EMSCRIPTEN_KEEPALIVE ViewportTouchStart(ViewportHandle viewport, | |
308 int touchCount, | |
309 float x0, | |
310 float y0, | |
311 float x1, | |
312 float y1, | |
313 float x2, | |
314 float y2) | |
315 { | |
316 // printf("touch start with %d touches\n", touchCount); | |
317 | |
318 std::vector<Deprecated::Touch> touches; | |
319 GetTouchVector(touches, touchCount, x0, y0, x1, y1, x2, y2); | |
320 viewport->TouchStart(touches); | |
321 } | |
322 | |
323 void EMSCRIPTEN_KEEPALIVE ViewportTouchMove(ViewportHandle viewport, | |
324 int touchCount, | |
325 float x0, | |
326 float y0, | |
327 float x1, | |
328 float y1, | |
329 float x2, | |
330 float y2) | |
331 { | |
332 // printf("touch move with %d touches\n", touchCount); | |
333 | |
334 std::vector<Deprecated::Touch> touches; | |
335 GetTouchVector(touches, touchCount, x0, y0, x1, y1, x2, y2); | |
336 viewport->TouchMove(touches); | |
337 } | |
338 | |
339 void EMSCRIPTEN_KEEPALIVE ViewportTouchEnd(ViewportHandle viewport, | |
340 int touchCount, | |
341 float x0, | |
342 float y0, | |
343 float x1, | |
344 float y1, | |
345 float x2, | |
346 float y2) | |
347 { | |
348 // printf("touch end with %d touches remaining\n", touchCount); | |
349 | |
350 std::vector<Deprecated::Touch> touches; | |
351 GetTouchVector(touches, touchCount, x0, y0, x1, y1, x2, y2); | |
352 viewport->TouchEnd(touches); | |
353 } | |
354 | |
355 void EMSCRIPTEN_KEEPALIVE ViewportKeyPressed(ViewportHandle viewport, | |
356 int key, | |
357 const char* keyChar, | |
358 bool isShiftPressed, | |
359 bool isControlPressed, | |
360 bool isAltPressed) | |
361 | |
362 { | |
363 OrthancStone::KeyboardModifiers modifiers = OrthancStone::KeyboardModifiers_None; | |
364 if (isShiftPressed) { | |
365 modifiers = static_cast<OrthancStone::KeyboardModifiers>(modifiers + OrthancStone::KeyboardModifiers_Shift); | |
366 } | |
367 if (isControlPressed) { | |
368 modifiers = static_cast<OrthancStone::KeyboardModifiers>(modifiers + OrthancStone::KeyboardModifiers_Control); | |
369 } | |
370 if (isAltPressed) { | |
371 modifiers = static_cast<OrthancStone::KeyboardModifiers>(modifiers + OrthancStone::KeyboardModifiers_Alt); | |
372 } | |
373 | |
374 char c = 0; | |
375 if (keyChar != NULL && key == OrthancStone::KeyboardKeys_Generic) { | |
376 c = keyChar[0]; | |
377 } | |
378 viewport->KeyPressed(static_cast<OrthancStone::KeyboardKeys>(key), c, modifiers); | |
379 } | |
380 | |
381 | |
382 void EMSCRIPTEN_KEEPALIVE ViewportMouseUp(ViewportHandle viewport) | |
383 { | |
384 viewport->MouseUp(); | |
385 } | |
386 | |
387 | |
388 void EMSCRIPTEN_KEEPALIVE ViewportMouseEnter(ViewportHandle viewport) | |
389 { | |
390 viewport->MouseEnter(); | |
391 } | |
392 | |
393 | |
394 void EMSCRIPTEN_KEEPALIVE ViewportMouseLeave(ViewportHandle viewport) | |
395 { | |
396 viewport->MouseLeave(); | |
397 } | |
398 | |
399 const char* EMSCRIPTEN_KEEPALIVE SendSerializedMessageToStoneApplication(const char* message) | |
400 { | |
401 static std::string output; // we don't want the string to be deallocated when we return to JS code so we always use the same string (this is fine since JS is single-thread) | |
402 | |
403 //printf("SendSerializedMessageToStoneApplication\n"); | |
404 //printf("%s", message); | |
405 | |
406 if (applicationWasmAdapter.get() != NULL) { | |
407 applicationWasmAdapter->HandleSerializedMessageFromWeb(output, std::string(message)); | |
408 return output.c_str(); | |
409 } | |
410 printf("This Stone application does not have a Web Adapter, unable to send messages"); | |
411 return NULL; | |
412 } | |
413 | |
414 #ifdef __cplusplus | |
415 } | |
416 #endif |