changeset 603:70992b38aa8a

new routable logging system in STDIO mode + flag support (with no value) in StartupParametersBuilder + 80 col indent
author Benjamin Golinvaux <bgo@osimis.io>
date Mon, 29 Apr 2019 15:09:48 +0200
parents 03c4b998fcd0
children 86dfde451f4c
files Applications/Generic/NativeStoneApplicationRunner.cpp Applications/Samples/rt-viewer-demo/main.cpp Applications/Wasm/StartupParametersBuilder.cpp Applications/Wasm/StartupParametersBuilder.h Platforms/Wasm/Defaults.cpp Platforms/Wasm/Defaults.h Platforms/Wasm/default-library.js Platforms/Wasm/logger.ts Platforms/Wasm/stone-framework-loader.ts Platforms/Wasm/wasm-application-runner.ts
diffstat 10 files changed, 244 insertions(+), 83 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/Generic/NativeStoneApplicationRunner.cpp	Mon Apr 29 14:40:01 2019 +0200
+++ b/Applications/Generic/NativeStoneApplicationRunner.cpp	Mon Apr 29 15:09:48 2019 +0200
@@ -81,11 +81,13 @@
       generic.add_options()
           ("help", "Display this help and exit")
           ("verbose", "Be verbose in logs")
-          ("orthanc", boost::program_options::value<std::string>()->default_value("http://localhost:8042/"),
+          ("orthanc", boost::program_options::value<std::string>()->
+            default_value("http://localhost:8042/"),
            "URL to the Orthanc server")
           ("username", "Username for the Orthanc server")
           ("password", "Password for the Orthanc server")
-          ("https-verify", boost::program_options::value<bool>()->default_value(true), "Check HTTPS certificates")
+          ("https-verify", boost::program_options::value<bool>()->
+            default_value(true), "Check HTTPS certificates")
           ;
 
       options.add(generic);
@@ -102,13 +104,15 @@
 
     try
     {
-      boost::program_options::store(boost::program_options::command_line_parser(argc, argv).
-                                    options(options).run(), parameters);
+      boost::program_options::store(
+        boost::program_options::command_line_parser(argc, argv).
+          options(options).run(), parameters);
       boost::program_options::notify(parameters);
     }
     catch (boost::program_options::error& e)
     {
-      LOG(ERROR) << "Error while parsing the command-line arguments: " << e.what();
+      LOG(ERROR) << 
+        "Error while parsing the command-line arguments: " << e.what();
       error = true;
     }
 
@@ -120,12 +124,11 @@
     if (error || parameters.count("help"))
     {
       std::cout << std::endl
-                << "Usage: " << argv[0] << " [OPTION]..."
-                << std::endl
-                << "Orthanc, lightweight, RESTful DICOM server for healthcare and medical research."
-                << std::endl << std::endl
-                << "Demonstration application of Orthanc Stone in native environment."
-                << std::endl;
+                << "Usage: " << argv[0] << " [OPTION]..." << std::endl
+                << "Orthanc, lightweight, RESTful DICOM server for healthcare "
+                << "and medical research." << std::endl << std::endl
+                << "Demonstration application of Orthanc Stone in native "
+                << "environment." << std::endl;
 
       std::cout << options << "\n";
       return error ? -1 : 0;
@@ -138,21 +141,24 @@
       Orthanc::HttpClient::ConfigureSsl(false, "");
     }
 
+    LOG(ERROR) << "???????? if (parameters.count(\"verbose\"))";
     if (parameters.count("verbose"))
     {
+      LOG(ERROR) << "parameters.count(\"verbose\") != 0";
       Orthanc::Logging::EnableInfoLevel(true);
       LOG(INFO) << "Verbose logs are enabled";
     }
 
+`    LOG(ERROR) << "???????? if (parameters.count(\"trace\"))";
     if (parameters.count("trace"))
     {
+      LOG(ERROR) << "parameters.count(\"trace\") != 0";
       Orthanc::Logging::EnableTraceLevel(true);
       VLOG(1) << "Trace logs are enabled";
     }
 
     ParseCommandLineOptions(parameters);
 
-
     bool success = true;
     try
     {
@@ -169,17 +175,20 @@
 
       if (parameters.count("username") && parameters.count("password"))
       {
-        webServiceParameters.SetCredentials(parameters["username"].as<std::string>(),
-            parameters["password"].as<std::string>());
+        webServiceParameters.SetCredentials(parameters["username"].
+          as<std::string>(),
+          parameters["password"].as<std::string>());
       }
 
-      LOG(WARNING) << "URL to the Orthanc REST API: " << webServiceParameters.GetUrl();
+      LOG(WARNING) << "URL to the Orthanc REST API: " << 
+        webServiceParameters.GetUrl();
 
       {
         OrthancPlugins::OrthancHttpConnection orthanc(webServiceParameters);
         if (!MessagingToolbox::CheckOrthancVersion(orthanc))
         {
-          LOG(ERROR) << "Your version of Orthanc is incompatible with Stone of Orthanc, please upgrade";
+          LOG(ERROR) << "Your version of Orthanc is incompatible with Stone of "
+            << "Orthanc, please upgrade";
           throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol);
         }
       }
@@ -196,11 +205,15 @@
       NativeStoneApplicationContext context(broker_);
 
       {
-        Oracle oracle(6); // use multiple threads to execute asynchronous tasks like download content
+        // use multiple threads to execute asynchronous tasks like 
+        // download content
+        Oracle oracle(6); 
         oracle.Start();
 
         {
-          OracleWebService webService(broker_, oracle, webServiceParameters, context);
+          OracleWebService webService(
+            broker_, oracle, webServiceParameters, context);
+          
           context.SetWebService(webService);
           context.SetOrthancBaseUrl(webServiceParameters.GetUrl());
 
@@ -255,5 +268,4 @@
 
     return (success ? 0 : -1);
   }
-
 }
--- a/Applications/Samples/rt-viewer-demo/main.cpp	Mon Apr 29 14:40:01 2019 +0200
+++ b/Applications/Samples/rt-viewer-demo/main.cpp	Mon Apr 29 15:09:48 2019 +0200
@@ -546,6 +546,24 @@
 
       void ParseParameters(const boost::program_options::variables_map&  parameters)
       {
+        // Generic
+        {
+          if (parameters.count("verbose"))
+          {
+            Orthanc::Logging::EnableInfoLevel(true);
+            LOG(INFO) << "Verbose logs (info) are enabled";
+          }
+        }
+
+        {
+          if (parameters.count("trace"))
+          {
+            LOG(INFO) << "parameters.count(\"trace\") != 0";
+            Orthanc::Logging::EnableTraceLevel(true);
+            VLOG(1) << "Trace logs (debug) are enabled";
+          }
+        }
+
         // CT series
         {
 
@@ -570,12 +588,14 @@
             if (parameters.count("dose-series") != 1)
             {
               LOG(ERROR) << "the RTDOSE series is missing";
-              throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+              throw Orthanc::OrthancException(
+                Orthanc::ErrorCode_ParameterOutOfRange);
             }
             doseSeries_ = parameters["ct"].as<std::string>();
 #endif
             LOG(ERROR) << "the RTSTRUCT instance is missing";
-            throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+            throw Orthanc::OrthancException(
+              Orthanc::ErrorCode_ParameterOutOfRange);
           }
         }
         
@@ -592,26 +612,40 @@
             if (parameters.count("struct-series") != 1)
             {
               LOG(ERROR) << "the RTSTRUCT series is missing";
-              throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+              throw Orthanc::OrthancException(
+                Orthanc::ErrorCode_ParameterOutOfRange);
             }
-            structSeries_ = parametersstruct - series"].as<std::string>();
+            structSeries_ = parameters["struct-series"].as<std::string>();
 #endif
             LOG(ERROR) << "the RTSTRUCT instance is missing";
-            throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange);
+            throw Orthanc::OrthancException(
+              Orthanc::ErrorCode_ParameterOutOfRange);
           }
         }
       }
 
-      virtual void DeclareStartupOptions(boost::program_options::options_description& options)
+      virtual void DeclareStartupOptions(
+        boost::program_options::options_description& options)
       {
-        boost::program_options::options_description generic("RtViewerDemo options. Please note that some of these options are mutually exclusive");
+        boost::program_options::options_description generic(
+          "RtViewerDemo options. Please note that some of these options "
+          "are mutually exclusive");
         generic.add_options()
-          ("ct-series", boost::program_options::value<std::string>(),"Orthanc ID of the CT series")
-          ("dose-instance", boost::program_options::value<std::string>(), "Orthanc ID of the RTDOSE instance (incompatible with dose-series)")
-          ("dose-series", boost::program_options::value<std::string>(), "NOT IMPLEMENTED YET. Orthanc ID of the RTDOSE series (incompatible with dose-instance)")
-          ("struct-instance", boost::program_options::value<std::string>(), "Orthanc ID of the RTSTRUCT instance (incompatible with struct-series)")
-          ("struct-series", boost::program_options::value<std::string>(), "NOT IMPLEMENTED YET. Orthanc ID of the RTSTRUCT (incompatible with struct-instance)")
-          ("smooth", boost::program_options::value<bool>()->default_value(true),"Enable bilinear image smoothing")
+          ("ct-series", boost::program_options::value<std::string>(),
+            "Orthanc ID of the CT series")
+          ("dose-instance", boost::program_options::value<std::string>(), 
+            "Orthanc ID of the RTDOSE instance (incompatible with dose-series)")
+          ("dose-series", boost::program_options::value<std::string>(), 
+            "NOT IMPLEMENTED YET. Orthanc ID of the RTDOSE series (incompatible"
+            " with dose-instance)")
+          ("struct-instance", boost::program_options::value<std::string>(), 
+            "Orthanc ID of the RTSTRUCT instance (incompatible with struct-"
+            "series)")
+          ("struct-series", boost::program_options::value<std::string>(), 
+            "NOT IMPLEMENTED YET. Orthanc ID of the RTSTRUCT (incompatible with"
+            " struct-instance)")
+          ("smooth", boost::program_options::value<bool>()->default_value(true),
+            "Enable bilinear image smoothing")
           ;
 
         options.add(generic);
@@ -637,8 +671,10 @@
           ct_.reset(new OrthancStone::OrthancVolumeImage(
             IObserver::GetBroker(), context->GetOrthancApiClient(), false));
           ct_->ScheduleLoadSeries(ctSeries_);
-          //ct_->ScheduleLoadSeries("a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa");  // IBA
-          //ct_->ScheduleLoadSeries("03677739-1d8bca40-db1daf59-d74ff548-7f6fc9c0");  // 0522c0001 TCIA
+          //ct_->ScheduleLoadSeries(
+          //  "a04ecf01-79b2fc33-58239f7e-ad9db983-28e81afa"); // IBA
+          //ct_->ScheduleLoadSeries(
+          //  "03677739-1d8bca40-db1daf59-d74ff548-7f6fc9c0"); // 0522c0001 TCIA
         }
 
         if (!doseSeries_.empty() ||
@@ -665,8 +701,10 @@
             dose_->ScheduleLoadInstance(doseInstance_);
           }
 
-          //dose_->ScheduleLoadInstance("830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb");  // IBA 1
-          //dose_->ScheduleLoadInstance("269f26f4-0c83eeeb-2e67abbd-5467a40f-f1bec90c");  // 0522c0001 TCIA
+          //dose_->ScheduleLoadInstance(
+            //"830a69ff-8e4b5ee3-b7f966c8-bccc20fb-d322dceb");  // IBA 1
+          //dose_->ScheduleLoadInstance(
+            //"269f26f4-0c83eeeb-2e67abbd-5467a40f-f1bec90c"); //0522c0001 TCIA
         }
 
         if (!structInstance_.empty())
@@ -676,8 +714,10 @@
 
           struct_->ScheduleLoadInstance(structInstance_);
 
-          //struct_->ScheduleLoadInstance("54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9");  // IBA
-          //struct_->ScheduleLoadInstance("17cd032b-ad92a438-ca05f06a-f9e96668-7e3e9e20");  // 0522c0001 TCIA
+          //struct_->ScheduleLoadInstance(
+            //"54460695-ba3885ee-ddf61ac0-f028e31d-a6e474d9"); // IBA
+          //struct_->ScheduleLoadInstance(
+            //"17cd032b-ad92a438-ca05f06a-f9e96668-7e3e9e20"); // 0522c0001 TCIA
         }
 
         mainWidget_ = new LayoutWidget("main-layout");
--- a/Applications/Wasm/StartupParametersBuilder.cpp	Mon Apr 29 14:40:01 2019 +0200
+++ b/Applications/Wasm/StartupParametersBuilder.cpp	Mon Apr 29 15:09:48 2019 +0200
@@ -1,43 +1,66 @@
 #include "StartupParametersBuilder.h"
+#include <iostream>
 
 namespace OrthancStone
 {
-    void StartupParametersBuilder::Clear() {
-        startupParameters_.clear();
-    }
+  void StartupParametersBuilder::Clear()
+  {
+    startupParameters_.clear();
+  }
+
+  void StartupParametersBuilder::SetStartupParameter(
+    const char* name,
+    const char* value)
+  {
+    startupParameters_.push_back(std::make_tuple(name, value));
+  }
 
-    void StartupParametersBuilder::SetStartupParameter(const char* name, const char* value) {
-        startupParameters_.push_back(std::make_tuple(name, value));
+  void StartupParametersBuilder::GetStartupParameters(
+    boost::program_options::variables_map& parameters,
+    const boost::program_options::options_description& options) 
+  {
+    std::vector<std::string> argvStrings(startupParameters_.size() + 1);
+    // argv mirrors pointers to the internal argvStrings buffers.
+    // ******************************************************
+    // THIS IS HIGHLY DANGEROUS SO BEWARE!!!!!!!!!!!!!!
+    // ******************************************************
+    std::vector<const char*> argv(startupParameters_.size() + 1);
+    
+    int argCounter = 0;
+    argvStrings[argCounter] = "Toto.exe";
+    argv[argCounter] = argvStrings[argCounter].c_str();
+    
+    argCounter++;
+
+    std::string cmdLine = "";
+    for ( StartupParameters::const_iterator it = startupParameters_.begin(); 
+          it != startupParameters_.end(); 
+          it++)
+    {
+        std::stringstream argSs;
+
+        argSs << "--" << std::get<0>(*it);
+        if(std::get<1>(*it).length() > 0)
+          argSs << "=" << std::get<1>(*it);
+
+        argvStrings[argCounter] = argSs.str();
+        cmdLine = cmdLine + " " + argvStrings[argCounter];
+        argv[argCounter] = argvStrings[argCounter].c_str();
+        argCounter++;
     }
 
-    void StartupParametersBuilder::GetStartupParameters(boost::program_options::variables_map& parameters, const boost::program_options::options_description& options) {
-        
-        const char* argv[startupParameters_.size() + 1];
-        int argCounter = 0;
-        argv[0] = "Toto.exe";
-        argCounter++;
-
-        std::string cmdLine = "";
-        for (StartupParameters::const_iterator it = startupParameters_.begin(); it != startupParameters_.end(); it++) {
-            char* arg = new char[128];
-            snprintf(arg, 128, "--%s=%s", std::get<0>(*it).c_str(), std::get<1>(*it).c_str());
-            argv[argCounter] = arg;
-            cmdLine = cmdLine + " --" + std::get<0>(*it) + "=" + std::get<1>(*it);
-            argCounter++;
-        }
+    std::cout << "simulated cmdLine = \"" << cmdLine.c_str() << "\"\n";
 
-        printf("simulated cmdLine = %s\n", cmdLine.c_str());
-
-        try
-        {
-            boost::program_options::store(boost::program_options::command_line_parser(argCounter, argv).
-                                            options(options).run(), parameters);
-            boost::program_options::notify(parameters);
-        }
-        catch (boost::program_options::error& e)
-        {
-            printf("Error while parsing the command-line arguments: %s\n", e.what());
-        }
-
+    try
+    {
+      boost::program_options::store(
+        boost::program_options::command_line_parser(argCounter, argv.data()).
+          options(options).run(), parameters);
+      boost::program_options::notify(parameters);
     }
-}
\ No newline at end of file
+    catch (boost::program_options::error& e)
+    {
+      std::cerr << "Error while parsing the command-line arguments: " <<
+        e.what() << std::endl;    }
+  }
+}
--- a/Applications/Wasm/StartupParametersBuilder.h	Mon Apr 29 14:40:01 2019 +0200
+++ b/Applications/Wasm/StartupParametersBuilder.h	Mon Apr 29 15:09:48 2019 +0200
@@ -43,8 +43,12 @@
   public:
 
     void Clear();
+    // Please note that if a parameter is a flag-style one, the value that 
+    // is passed should be an empty string
     void SetStartupParameter(const char* name, const char* value);
-    void GetStartupParameters(boost::program_options::variables_map& parameters_, const boost::program_options::options_description& options);
+    void GetStartupParameters(
+      boost::program_options::variables_map& parameters_, 
+      const boost::program_options::options_description& options);
   };
 
 }
--- a/Platforms/Wasm/Defaults.cpp	Mon Apr 29 14:40:01 2019 +0200
+++ b/Platforms/Wasm/Defaults.cpp	Mon Apr 29 15:09:48 2019 +0200
@@ -5,9 +5,12 @@
 #include <Framework/dev.h>
 #include "Framework/Widgets/TestCairoWidget.h"
 #include <Framework/Viewport/WidgetViewport.h>
+#include <Applications/Wasm/StartupParametersBuilder.h>
+#include <Platforms/Wasm/WasmPlatformApplicationAdapter.h>
+#include <Core/Logging.h>
+
 #include <algorithm>
-#include "Applications/Wasm/StartupParametersBuilder.h"
-#include "Platforms/Wasm/WasmPlatformApplicationAdapter.h"
+
 
 static unsigned int width_ = 0;
 static unsigned int height_ = 0;
@@ -88,6 +91,10 @@
 
     printf("StartWasmApplication\n");
 
+    Orthanc::Logging::SetErrorWarnInfoTraceLoggingFunctions(
+      stone_console_error, stone_console_warning,
+      stone_console_info, stone_console_trace);
+
     // recreate a command line from uri arguments and parse it
     boost::program_options::variables_map parameters;
     boost::program_options::options_description options;
@@ -106,6 +113,16 @@
     printf("StartWasmApplication - completed\n");
   }
   
+  bool EMSCRIPTEN_KEEPALIVE WasmIsTraceLevelEnabled()
+  {
+    return Orthanc::Logging::IsTraceLevelEnabled();
+  }
+
+  bool EMSCRIPTEN_KEEPALIVE WasmIsInfoLevelEnabled()
+  {
+    return Orthanc::Logging::IsInfoLevelEnabled();
+  }
+  
   void EMSCRIPTEN_KEEPALIVE WasmDoAnimation()
   {
     for (auto viewport : viewports_) {
--- a/Platforms/Wasm/Defaults.h	Mon Apr 29 14:40:01 2019 +0200
+++ b/Platforms/Wasm/Defaults.h	Mon Apr 29 15:09:48 2019 +0200
@@ -18,7 +18,11 @@
   extern void ScheduleWebViewportRedrawFromCpp(ViewportHandle cppViewportHandle);
   extern void UpdateStoneApplicationStatusFromCppWithString(const char* statusUpdateMessage);
   extern void UpdateStoneApplicationStatusFromCppWithSerializedMessage(const char* statusUpdateMessage);
-  
+  extern void stone_console_error(const char*);
+  extern void stone_console_warning(const char*);
+  extern void stone_console_info(const char*);
+  extern void stone_console_trace(const char*);
+
   // C++ methods accessible from JS
   extern void EMSCRIPTEN_KEEPALIVE CreateWasmApplication(ViewportHandle cppViewportHandle);
   extern void EMSCRIPTEN_KEEPALIVE SetStartupParameter(const char* keyc, const char* value);
--- a/Platforms/Wasm/default-library.js	Mon Apr 29 14:40:01 2019 +0200
+++ b/Platforms/Wasm/default-library.js	Mon Apr 29 15:09:48 2019 +0200
@@ -1,21 +1,49 @@
 // this file contains the JS method you want to expose to C++ code
 
 mergeInto(LibraryManager.library, {
+
   ScheduleWebViewportRedrawFromCpp: function(cppViewportHandle) {
     window.ScheduleWebViewportRedraw(cppViewportHandle);
   },
+
   CreateWasmViewportFromCpp: function(htmlCanvasId) {
     return window.CreateWasmViewport(htmlCanvasId);
   },
+
   // each time the StoneApplication updates its status, it may signal it 
   // through this method. i.e, to change the status of a button in the web interface
   UpdateStoneApplicationStatusFromCppWithString: function(statusUpdateMessage) {
     var statusUpdateMessage_ = UTF8ToString(statusUpdateMessage);
     window.UpdateWebApplicationWithString(statusUpdateMessage_);
   },
+
   // same, but with a serialized message
   UpdateStoneApplicationStatusFromCppWithSerializedMessage: function(statusUpdateMessage) {
     var statusUpdateMessage_ = UTF8ToString(statusUpdateMessage);
     window.UpdateWebApplicationWithSerializedMessage(statusUpdateMessage_);
+  },
+
+  // These functions are called from C++ (through an extern declaration) 
+  // and call the standard logger that, here, routes to the console.
+
+  stone_console_error : function(message) {
+    var text = UTF8ToString(message);
+    window.errorFromCpp(text);
+  },
+
+  stone_console_warning : function(message) {
+    var text = UTF8ToString(message);
+    window.warningFromCpp(text);
+  },
+
+  stone_console_info: function(message) {
+    var text = UTF8ToString(message);
+    window.infoFromCpp(text);
+  },
+  
+  stone_console_trace : function(message) {
+    var text = UTF8ToString(message);
+    window.debugFromCpp(text);
   }
+
 });
--- a/Platforms/Wasm/logger.ts	Mon Apr 29 14:40:01 2019 +0200
+++ b/Platforms/Wasm/logger.ts	Mon Apr 29 15:09:48 2019 +0200
@@ -10,6 +10,10 @@
     this._debug(LogSource.Typescript, ...args);
   }
 
+  public debugFromCpp(...args: any[]): void {
+    this._debug(LogSource.Cpp, ...args);
+  }
+
   public info(...args: any[]): void {
     this._info(LogSource.Typescript, ...args);
   }
@@ -22,6 +26,10 @@
     this._warning(LogSource.Typescript, ...args);
   }
 
+  public warningFromCpp(message: string): void {
+    this._warning(LogSource.Cpp, message);
+  }
+
   public error(...args: any[]): void {
     this._error(LogSource.Typescript, ...args);
   }
@@ -31,13 +39,25 @@
   }
 
   public _debug(source: LogSource, ...args: any[]): void {
-    var output = this.getOutput(source, args);
-    console.debug(...output);
+    if ((<any> window).IsTraceLevelEnabled)
+    {
+      if ((<any> window).IsTraceLevelEnabled())
+      {
+        var output = this.getOutput(source, args);
+        console.debug(...output);
+      }
+    }
   }
 
   private _info(source: LogSource, ...args: any[]): void {
-    var output = this.getOutput(source, args);
-    console.info(...output);
+    if ((<any> window).IsInfoLevelEnabled)
+    {
+      if ((<any> window).IsInfoLevelEnabled())
+      {
+        var output = this.getOutput(source, args);
+        console.info(...output);
+      }
+    }
   }
 
   public _warning(source: LogSource, ...args: any[]): void {
@@ -88,3 +108,4 @@
 }
 
 export var defaultLogger: StandardConsoleLogger = new TimeConsoleLogger();
+
--- a/Platforms/Wasm/stone-framework-loader.ts	Mon Apr 29 14:40:01 2019 +0200
+++ b/Platforms/Wasm/stone-framework-loader.ts	Mon Apr 29 15:09:48 2019 +0200
@@ -59,6 +59,11 @@
   {
     Logger.defaultLogger.debug('Initializing WebAssembly Module');
 
+    (<any> window).errorFromCpp = function(text:any) { Logger.defaultLogger.errorFromCpp(text); };
+    (<any> window).warningFromCpp = function(text:any) { Logger.defaultLogger.warningFromCpp(text); };
+    (<any> window).infoFromCpp = function(text:any) { Logger.defaultLogger.infoFromCpp(text); };
+    (<any> window).debugFromCpp = function(text:any) { Logger.defaultLogger.debugFromCpp(text); };
+
     // (<any> window).
     (<any> window).StoneFrameworkModule = {
       preRun: [ 
--- a/Platforms/Wasm/wasm-application-runner.ts	Mon Apr 29 14:40:01 2019 +0200
+++ b/Platforms/Wasm/wasm-application-runner.ts	Mon Apr 29 15:09:48 2019 +0200
@@ -27,7 +27,8 @@
     WasmDoAnimation();
   }
 
-  setTimeout(DoAnimationThread, 100);  // Update the viewport content every 100ms if need be
+  // Update the viewport content every 100ms if need be
+  setTimeout(DoAnimationThread, 100);  
 }
 
 function GetUriParameters(): Map<string, string> {
@@ -42,10 +43,12 @@
       var tmp = tokens[i].split('=');
       if (tmp.length == 2) {
         result[tmp[0]] = decodeURIComponent(tmp[1]);
+      } else if(tmp.length == 1) {
+        // if there is no '=', we treat ot afterwards as a flag-style param
+        result[tmp[0]] = "";
       }
     }
-
-    return result;
+  return result;
   }
   else {
     return new Map<string, string>();
@@ -65,6 +68,8 @@
 
   for (let key in parameters) {
     if (parameters.hasOwnProperty(key)) {
+      Logger.defaultLogger.debug(
+        `About to call SetStartupParameter("${key}","${parameters[key]}")`);
       SetStartupParameter(key, parameters[key]);
     }
   }
@@ -92,6 +97,8 @@
     CreateCppViewport = (<any> window).StoneFrameworkModule.cwrap('CreateCppViewport', 'number', []);
     ReleaseCppViewport = (<any> window).StoneFrameworkModule.cwrap('ReleaseCppViewport', null, ['number']);
     StartWasmApplication = (<any> window).StoneFrameworkModule.cwrap('StartWasmApplication', null, ['string']);
+    (<any> window).IsTraceLevelEnabled = (<any> window).StoneFrameworkModule.cwrap('WasmIsTraceLevelEnabled', 'boolean', null);
+    (<any> window).IsInfoLevelEnabled = (<any> window).StoneFrameworkModule.cwrap('WasmIsInfoLevelEnabled', 'boolean', null);
 
     (<any> window).WasmWebService_NotifyCachedSuccess = (<any> window).StoneFrameworkModule.cwrap('WasmWebService_NotifyCachedSuccess', null, ['number']);
     (<any> window).WasmWebService_NotifySuccess = (<any> window).StoneFrameworkModule.cwrap('WasmWebService_NotifySuccess', null, ['number', 'string', 'array', 'number', 'number']);