changeset 242:092db46c6291 am

improved SDL/Wasm unification
author am@osimis.io
date Wed, 20 Jun 2018 14:20:55 +0200
parents a4197519eb55
children 50fb32abf85e
files Applications/BasicApplicationContext.h Applications/IBasicApplication.cpp Applications/IBasicApplication.h Applications/Samples/SampleApplicationBase.h Applications/Samples/SampleApplicationContext.h Applications/Samples/SampleMainSdl.cpp Applications/Samples/SampleMainWasm.cpp Applications/Samples/SimpleViewerApplication.h Applications/Sdl/BasicSdlApplication.cpp Applications/Sdl/BasicSdlApplication.h Applications/Sdl/BasicSdlApplicationContext.cpp Applications/Sdl/BasicSdlApplicationContext.h Applications/Wasm/BasicWasmApplication.cpp Applications/Wasm/BasicWasmApplication.h Applications/Wasm/StartupParametersBuilder.cpp Applications/Wasm/StartupParametersBuilder.h Platforms/Generic/CMakeLists.txt Platforms/Generic/OracleWebService.h Platforms/Wasm/CMakeLists.txt Platforms/Wasm/Defaults.cpp Platforms/Wasm/Defaults.h Platforms/Wasm/WasmViewport.cpp Platforms/Wasm/WasmViewport.h Resources/CMake/OrthancStoneConfiguration.cmake
diffstat 24 files changed, 245 insertions(+), 233 deletions(-) [+]
line wrap: on
line diff
--- a/Applications/BasicApplicationContext.h	Wed Jun 20 09:50:25 2018 +0200
+++ b/Applications/BasicApplicationContext.h	Wed Jun 20 14:20:55 2018 +0200
@@ -31,10 +31,15 @@
   class BasicApplicationContext : public boost::noncopyable
   {
 
+  protected:
+    IWebService& webService_;
   public:
-    BasicApplicationContext() {}
+    BasicApplicationContext(IWebService& webService)
+      : webService_(webService)
+    {
+    }
 
-    virtual IWebService& GetWebService() = 0;
+    virtual IWebService& GetWebService() {return webService_;}
 //    virtual IWidget& SetCentralWidget(IWidget* widget) = 0;   // Takes ownership
 
     virtual ~BasicApplicationContext() {}
--- a/Applications/IBasicApplication.cpp	Wed Jun 20 09:50:25 2018 +0200
+++ b/Applications/IBasicApplication.cpp	Wed Jun 20 14:20:55 2018 +0200
@@ -30,34 +30,5 @@
 
 namespace OrthancStone
 {
-    void IBasicApplication::DeclareStringStartupOption(const std::string& name, const std::string& defaultValue, const std::string& helpText) {
-        StartupOption option;
-        option.name = name;
-        option.defaultValue = defaultValue;
-        option.helpText = helpText = helpText;
-        option.type = StartupOption::string;
-
-        startupOptions_.push_back(option);
-    }
-
-    void IBasicApplication::DeclareBoolStartupOption(const std::string& name, bool defaultValue, const std::string& helpText) {
-        StartupOption option;
-        option.name = name;
-        option.defaultValue = (defaultValue ? "true" : "false");
-        option.helpText = helpText = helpText;
-        option.type = StartupOption::boolean;
-
-        startupOptions_.push_back(option);
-    }
-
-    void IBasicApplication::DeclareIntegerStartupOption(const std::string& name, const int& defaultValue, const std::string& helpText) {
-        StartupOption option;
-        option.name = name;
-        option.defaultValue = std::to_string(defaultValue);
-        option.helpText = helpText = helpText;
-        option.type = StartupOption::integer;
-
-        startupOptions_.push_back(option);
-    }
 
 }
--- a/Applications/IBasicApplication.h	Wed Jun 20 09:50:25 2018 +0200
+++ b/Applications/IBasicApplication.h	Wed Jun 20 14:20:55 2018 +0200
@@ -29,26 +29,24 @@
 {
   class IBasicApplication : public boost::noncopyable
   {
+  protected:
+    BasicApplicationContext* context_;
+
   public:
     virtual ~IBasicApplication()
     {
     }
 
     virtual void DeclareStartupOptions(boost::program_options::options_description& options) = 0;
-    virtual void Initialize(IStatusBar& statusBar,
+    virtual void Initialize(BasicApplicationContext* context,
+                            IStatusBar& statusBar,
                             const boost::program_options::variables_map& parameters) = 0;
-
-#if ORTHANC_ENABLE_SDL == 1
-  virtual BasicApplicationContext& CreateApplicationContext(Orthanc::WebServiceParameters& orthancWebService, OrthancStone::WidgetViewport* centralViewport) = 0;
-#else
-  virtual BasicApplicationContext& CreateApplicationContext(IWebService& orthancWebService, std::shared_ptr<WidgetViewport> centralViewport) = 0;
+#if ORTHANC_ENABLE_SDL==0
+    virtual void InitializeWasm() {}  // specific initialization when the app is running in WebAssembly.  This is called after the other Initialize()
 #endif
 
     virtual std::string GetTitle() const = 0;
-
-//    virtual void Initialize(BasicApplicationContext& context,
-//                            IStatusBar& statusBar,
-//                            const std::map<std::string, std::string>& startupOptions) = 0;
+    virtual IWidget* GetCentralWidget() = 0;
 
     virtual void Finalize() = 0;
 
--- a/Applications/Samples/SampleApplicationBase.h	Wed Jun 20 09:50:25 2018 +0200
+++ b/Applications/Samples/SampleApplicationBase.h	Wed Jun 20 14:20:55 2018 +0200
@@ -21,55 +21,58 @@
 
 #pragma once
 
-#if ORTHANC_ENABLE_SDL==1
-#include "../../Applications/Sdl/BasicSdlApplication.h"
-#else
-#include "../../Applications/Wasm/BasicWasmApplication.h"
-#endif
+//#if ORTHANC_ENABLE_SDL==1
+//#include "../../Applications/Sdl/BasicSdlApplication.h"
+//#else
+//#include "../../Applications/Wasm/BasicWasmApplication.h"
+//#endif
+#include "../../Applications/IBasicApplication.h"
 #include "../../Framework/Viewport/WidgetViewport.h"
-#include "SampleApplicationContext.h"
+//#include "SampleApplicationContext.h"
 
 namespace OrthancStone
 {
   namespace Samples
   {
 
-#if ORTHANC_ENABLE_SDL==1
-    class SampleSdlApplicationBase : public BasicSdlApplication {
-    protected:
-      std::unique_ptr<SampleApplicationContext> context_;
-    public:
-      virtual BasicApplicationContext& CreateApplicationContext(Orthanc::WebServiceParameters& orthanc, WidgetViewport* centralViewport) {
-        context_.reset(new SampleApplicationContext(orthanc, centralViewport));
+//#if ORTHANC_ENABLE_SDL==1
+//    class SampleSdlApplicationBase : public BasicSdlApplication {
+//    protected:
+//    public:
+//      virtual BasicApplicationContext& CreateApplicationContext(Orthanc::WebServiceParameters& orthanc, WidgetViewport* centralViewport) {
+//        context_.reset(new SampleApplicationContext(orthanc, centralViewport));
 
-        return *context_;
-      }
-    };
+//        return *context_;
+//      }
+//    };
 
-    typedef SampleSdlApplicationBase SampleApplicationBase_;
-#else
-    class SampleWasmApplicationBase : public BasicWasmApplication {
-    protected:
-      std::unique_ptr<SampleApplicationContext> context_;
-    public:
-      virtual BasicApplicationContext& CreateApplicationContext(IWebService& orthancWebService, std::shared_ptr<WidgetViewport> centralViewport) {
-        context_.reset(new SampleApplicationContext(orthancWebService));
-        return *context_;
-      }
+//    typedef SampleSdlApplicationBase SampleApplicationBase_;
+//#else
+//    class SampleWasmApplicationBase : public BasicWasmApplication {
+//    protected:
+//      std::unique_ptr<SampleApplicationContext> context_;
+//    public:
+//      virtual BasicApplicationContext& CreateApplicationContext(IWebService& orthancWebService, std::shared_ptr<WidgetViewport> centralViewport) {
+//        context_.reset(new SampleApplicationContext(orthancWebService));
+//        return *context_;
+//      }
 
-    };
+//    };
 
-    typedef SampleWasmApplicationBase SampleApplicationBase_;
+//    typedef SampleWasmApplicationBase SampleApplicationBase_;
 
-#endif
+//#endif
 
-    class SampleApplicationBase : public SampleApplicationBase_
+    class SampleApplicationBase : public IBasicApplication
     {
     public:
       virtual std::string GetTitle() const
       {
         return "Stone of Orthanc - Sample";
       }
+
+      virtual void CustomInitialize() {}
+
     };
 
 
--- a/Applications/Samples/SampleApplicationContext.h	Wed Jun 20 09:50:25 2018 +0200
+++ b/Applications/Samples/SampleApplicationContext.h	Wed Jun 20 14:20:55 2018 +0200
@@ -41,11 +41,12 @@
 namespace OrthancStone
 {
 
-#if ORTHANC_ENABLE_SDL==1
-  class SampleApplicationContext : public BasicSdlApplicationContext
-#else
+//#if ORTHANC_ENABLE_SDL==1
+//  class SampleApplicationContext : public BasicSdlApplicationContext
+//#else
+//  class SampleApplicationContext : public BasicWasmApplicationContext
+//#endif
   class SampleApplicationContext : public BasicWasmApplicationContext
-#endif
   {
   private:
     typedef std::list<ISlicedVolume*>          SlicedVolumes;  // this is actually used by the samples and shall be moved to a SampleApplicationContext
--- a/Applications/Samples/SampleMainSdl.cpp	Wed Jun 20 09:50:25 2018 +0200
+++ b/Applications/Samples/SampleMainSdl.cpp	Wed Jun 20 14:20:55 2018 +0200
@@ -18,7 +18,9 @@
  * along with this program. If not, see <http://www.gnu.org/licenses/>.
  **/
 
+
 #include "SampleList.h"
+#include "../Sdl/BasicSdlApplication.h"
 
 int main(int argc, char* argv[]) 
 {
--- a/Applications/Samples/SampleMainWasm.cpp	Wed Jun 20 09:50:25 2018 +0200
+++ b/Applications/Samples/SampleMainWasm.cpp	Wed Jun 20 14:20:55 2018 +0200
@@ -26,12 +26,7 @@
 #include "SampleList.h"
 
 
-OrthancStone::BasicWasmApplication* CreateUserApplication() {
+OrthancStone::IBasicApplication* CreateUserApplication() {
   
-  printf("C++: CreateUserApplication\n");
-  OrthancStone::WidgetViewport* viewport = CreateWasmViewportFromCpp("canvas");  
-  OrthancStone::WidgetViewport* viewport2 = CreateWasmViewportFromCpp("canvas2");  
-  printf("C++: CreateUserApplication - wasm viewport created\n");
-  
-  return new Application(viewport, viewport2);
+  return new Application();
 }
\ No newline at end of file
--- a/Applications/Samples/SimpleViewerApplication.h	Wed Jun 20 09:50:25 2018 +0200
+++ b/Applications/Samples/SimpleViewerApplication.h	Wed Jun 20 14:20:55 2018 +0200
@@ -203,6 +203,7 @@
       {
       }
 
+      std::unique_ptr<Interactor>     interactor_;
       LayoutWidget*                   mainLayout_;
       LayoutWidget*                   thumbnailsLayout_;
       LayerWidget*                    mainViewport_;
@@ -216,13 +217,13 @@
       unsigned int                    slice_;
       
     public:
-      SimpleViewerApplication(OrthancStone::WidgetViewport* wasmViewport1, OrthancStone::WidgetViewport* wasmViewport2) :
+      SimpleViewerApplication() :
         mainLayout_(NULL),
         currentInstanceIndex_(0),
         source_(NULL),
         slice_(0),
-        wasmViewport1_(wasmViewport1),
-        wasmViewport2_(wasmViewport2)
+        wasmViewport1_(NULL),
+        wasmViewport2_(NULL)
       {
       }
       
@@ -244,11 +245,13 @@
         options.add(generic);    
       }
 
-      virtual void Initialize(IStatusBar& statusBar,
+      virtual void Initialize(BasicApplicationContext* context,
+                              IStatusBar& statusBar,
                               const boost::program_options::variables_map& parameters)
       {
         using namespace OrthancStone;
 
+        context_ = context;
         statusBar.SetMessage("Use the key \"s\" to reinitialize the layout");
 
         if (parameters.count("instance1") < 1)
@@ -301,15 +304,17 @@
         thumbnails_[1]->AddLayer(thumb1);
 
         mainLayout_->SetTransmitMouseOver(true);
-        mainViewport_->SetInteractor(context_->AddInteractor(new Interactor(*this)));
-#if ORTHANC_ENABLE_SDL == 1
-        context_->SetCentralWidget(mainLayout_);
-#else
-  wasmViewport1_->SetCentralWidget(thumbnailsLayout_);
-  wasmViewport2_->SetCentralWidget(mainViewport_);
+        interactor_.reset(new Interactor(*this));
+        mainViewport_->SetInteractor(*interactor_);
+      }
 
+#if ORTHANC_ENABLE_SDL==0
+      virtual void InitializeWasm() {
+
+        AttachWidgetToWasmViewport("canvas", thumbnailsLayout_);
+        AttachWidgetToWasmViewport("canvas2", mainViewport_);
+      }
 #endif
-      }
     };
   }
 }
--- a/Applications/Sdl/BasicSdlApplication.cpp	Wed Jun 20 09:50:25 2018 +0200
+++ b/Applications/Sdl/BasicSdlApplication.cpp	Wed Jun 20 14:20:55 2018 +0200
@@ -79,7 +79,7 @@
   }
 
 
-  int BasicSdlApplication::ExecuteWithSdl(BasicSdlApplication& application,
+  int BasicSdlApplication::ExecuteWithSdl(IBasicApplication& application,
                                         int argc,
                                         char* argv[])
   {
@@ -184,27 +184,27 @@
        * Initialize the connection to the Orthanc server
        ****************************************************************/
 
-      Orthanc::WebServiceParameters webService;
+      Orthanc::WebServiceParameters webServiceParameters;
 
       if (parameters.count("orthanc"))
       {
-        webService.SetUrl(parameters["orthanc"].as<std::string>());
+        webServiceParameters.SetUrl(parameters["orthanc"].as<std::string>());
       }
 
       if (parameters.count("username"))
       {
-        webService.SetUsername(parameters["username"].as<std::string>());
+        webServiceParameters.SetUsername(parameters["username"].as<std::string>());
       }
 
       if (parameters.count("password"))
       {
-        webService.SetPassword(parameters["password"].as<std::string>());
+        webServiceParameters.SetPassword(parameters["password"].as<std::string>());
       }
 
-      LOG(WARNING) << "URL to the Orthanc REST API: " << webService.GetUrl();
+      LOG(WARNING) << "URL to the Orthanc REST API: " << webServiceParameters.GetUrl();
 
       {
-        OrthancPlugins::OrthancHttpConnection orthanc(webService);
+        OrthancPlugins::OrthancHttpConnection orthanc(webServiceParameters);
         if (!MessagingToolbox::CheckOrthancVersion(orthanc))
         {
           LOG(ERROR) << "Your version of Orthanc is incompatible with Stone of Orthanc, please upgrade";
@@ -220,13 +220,17 @@
       LOG(WARNING) << "Creating the widgets of the application";
 
       LogStatusBar statusBar;
-      OrthancStone::WidgetViewport* centralViewport = new OrthancStone::WidgetViewport();
-      BasicSdlApplicationContext& context = dynamic_cast<BasicSdlApplicationContext&>(application.CreateApplicationContext(webService, centralViewport));
 
-      application.Initialize(statusBar, parameters);
+      boost::mutex stoneGlobalMutex;
+      Oracle oracle(stoneGlobalMutex, 4); // use 4 threads to download content
+      OracleWebService webService(oracle, webServiceParameters);
+      BasicSdlApplicationContext context(webService);
+
+      application.Initialize(&context, statusBar, parameters);
 
       {
         BasicSdlApplicationContext::ViewportLocker locker(context);
+        context.SetCentralWidget(application.GetCentralWidget());
         locker.GetViewport().SetStatusBar(statusBar);
       }
 
--- a/Applications/Sdl/BasicSdlApplication.h	Wed Jun 20 09:50:25 2018 +0200
+++ b/Applications/Sdl/BasicSdlApplication.h	Wed Jun 20 14:20:55 2018 +0200
@@ -41,7 +41,7 @@
     {
     }
 
-    static int ExecuteWithSdl(BasicSdlApplication& application,
+    static int ExecuteWithSdl(IBasicApplication& application,
                               int argc,
                               char* argv[]);
 
--- a/Applications/Sdl/BasicSdlApplicationContext.cpp	Wed Jun 20 09:50:25 2018 +0200
+++ b/Applications/Sdl/BasicSdlApplicationContext.cpp	Wed Jun 20 14:20:55 2018 +0200
@@ -44,11 +44,13 @@
   }
   
 
-  BasicSdlApplicationContext::BasicSdlApplicationContext(Orthanc::WebServiceParameters& orthanc, WidgetViewport* centralViewport) :
-    oracle_(viewportMutex_, 4),  // Use 4 threads to download
-    //oracle_(viewportMutex_, 1),  // Disable threading to be reproducible
-    webService_(oracle_, orthanc),
-    centralViewport_(centralViewport),
+  BasicSdlApplicationContext::BasicSdlApplicationContext(OracleWebService& webService) : // Orthanc::WebServiceParameters& orthanc, WidgetViewport* centralViewport) :
+    BasicApplicationContext(webService),
+    oracleWebService_(&webService),
+//    oracle_(viewportMutex_, 4),  // Use 4 threads to download
+//    webService_(oracle_, orthanc),
+//    centralViewport_(centralViewport),
+    centralViewport_(new OrthancStone::WidgetViewport()),
     stopped_(true),
     updateDelay_(100)   // By default, 100ms between each refresh of the content
   {
@@ -58,7 +60,7 @@
 
   void BasicSdlApplicationContext::Start()
   {
-    oracle_.Start();
+    oracleWebService_->Start();
 
     if (centralViewport_->HasUpdateContent())
     {
@@ -77,6 +79,6 @@
       updateThread_.join();
     }
     
-    oracle_.Stop();
+    oracleWebService_->Stop();
   }
 }
--- a/Applications/Sdl/BasicSdlApplicationContext.h	Wed Jun 20 09:50:25 2018 +0200
+++ b/Applications/Sdl/BasicSdlApplicationContext.h	Wed Jun 20 14:20:55 2018 +0200
@@ -39,8 +39,7 @@
 
     static void UpdateThread(BasicSdlApplicationContext* that);
 
-    Oracle              oracle_;
-    OracleWebService    webService_;
+    OracleWebService*   oracleWebService_;
     boost::mutex        viewportMutex_;
     std::unique_ptr<WidgetViewport>      centralViewport_;
     boost::thread       updateThread_;
@@ -68,7 +67,7 @@
     };
 
     
-    BasicSdlApplicationContext(Orthanc::WebServiceParameters& orthanc, WidgetViewport* centralViewport);
+    BasicSdlApplicationContext(OracleWebService& webService);
 
     virtual ~BasicSdlApplicationContext() {}
 
--- a/Applications/Wasm/BasicWasmApplication.cpp	Wed Jun 20 09:50:25 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-#include "BasicWasmApplication.h"
-
-namespace OrthancStone
-{
-
-
-    void BasicWasmApplication::SetStartupParameter(const char* name, const char* value) {
-        startupParameters_.push_back(std::make_tuple(name, value));
-    }
-
-    void BasicWasmApplication::GetStartupParameters(boost::program_options::variables_map& parameters) {
-        boost::program_options::options_description options;
-        DeclareStartupOptions(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++;
-        }
-
-        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());
-        }
-
-    }
-}
\ No newline at end of file
--- a/Applications/Wasm/BasicWasmApplication.h	Wed Jun 20 09:50:25 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/**
- * Stone of Orthanc
- * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
- * Department, University Hospital of Liege, Belgium
- * Copyright (C) 2017-2018 Osimis S.A., Belgium
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- **/
-
-
-#pragma once
-
-#include "../BasicApplicationContext.h"
-#include "../IBasicApplication.h"
-
-#include <boost/program_options.hpp>
-#include <tuple>
-
-#if ORTHANC_ENABLE_SDL == 1
-#error this file shall be included only with the ORTHANC_ENABLE_SDL set to 0
-#endif
-
-namespace OrthancStone
-{
-  class BasicWasmApplication : public IBasicApplication
-  {
-    typedef std::list<std::tuple<std::string, std::string>> StartupParameters;
-    StartupParameters startupParameters_;
-
-  public:
-    virtual ~BasicWasmApplication()
-    {
-    }
-
-    void SetStartupParameter(const char* name, const char* value);
-    void GetStartupParameters(boost::program_options::variables_map& parameters_);
-    
-    virtual IWidget* GetCentralWidget() = 0;
-
-    //static int ExecuteWithWasm(BasicWasmApplication& application);
-  };
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Applications/Wasm/StartupParametersBuilder.cpp	Wed Jun 20 14:20:55 2018 +0200
@@ -0,0 +1,43 @@
+#include "StartupParametersBuilder.h"
+
+namespace OrthancStone
+{
+    void StartupParametersBuilder::Clear() {
+        startupParameters_.clear();
+    }
+
+    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) {
+        
+        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++;
+        }
+
+        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());
+        }
+
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Applications/Wasm/StartupParametersBuilder.h	Wed Jun 20 14:20:55 2018 +0200
@@ -0,0 +1,50 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017-2018 Osimis S.A., Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include <boost/program_options.hpp>
+#include <tuple>
+
+#if ORTHANC_ENABLE_SDL == 1
+#error this file shall be included only with the ORTHANC_ENABLE_SDL set to 0
+#endif
+
+namespace OrthancStone
+{
+  // This class is used to generate boost program options from a dico.
+  // In a Wasm context, startup options are passed as URI arguments that
+  // are then passed to this class as a dico.
+  // This class regenerates a fake command-line and parses it to produce
+  // the same output as if the app was started at command-line.
+  class StartupParametersBuilder
+  {
+    typedef std::list<std::tuple<std::string, std::string>> StartupParameters;
+    StartupParameters startupParameters_;
+
+  public:
+
+    void Clear();
+    void SetStartupParameter(const char* name, const char* value);
+    void GetStartupParameters(boost::program_options::variables_map& parameters_, const boost::program_options::options_description& options);
+  };
+
+}
--- a/Platforms/Generic/CMakeLists.txt	Wed Jun 20 09:50:25 2018 +0200
+++ b/Platforms/Generic/CMakeLists.txt	Wed Jun 20 14:20:55 2018 +0200
@@ -48,7 +48,7 @@
 macro(BuildSample Target Header Sample)
   add_executable(${Target}
     ${ORTHANC_STONE_ROOT}/Applications/Samples/SampleMainSdl.cpp
-    ${ORTHANC_STONE_ROOT}/Applications/Samples/SampleApplicationContext.cpp
+#    ${ORTHANC_STONE_ROOT}/Applications/Samples/SampleApplicationContext.cpp
     ${ORTHANC_STONE_ROOT}/Applications/Samples/SampleInteractor.h
     ${ORTHANC_STONE_ROOT}/Applications/Samples/SampleApplicationBase.h
     ${ORTHANC_STONE_ROOT}/Applications/Samples/${Header}
@@ -61,13 +61,13 @@
 
 # TODO - Re-enable all these samples!
 
-BuildSample(OrthancStoneEmpty EmptyApplication.h 1)
-BuildSample(OrthancStoneTestPattern TestPatternApplication.h 2)
-BuildSample(OrthancStoneSingleFrame SingleFrameApplication.h 3)
-BuildSample(OrthancStoneSingleVolume SingleVolumeApplication.h 4)
-#BuildSample(OrthancStoneBasicPetCtFusion 5)
-#BuildSample(OrthancStoneSynchronizedSeries 6)
-#BuildSample(OrthancStoneLayoutPetCtFusion 7)
+#BuildSample(OrthancStoneEmpty EmptyApplication.h 1)
+#BuildSample(OrthancStoneTestPattern TestPatternApplication.h 2)
+#BuildSample(OrthancStoneSingleFrame SingleFrameApplication.h 3)
+#BuildSample(OrthancStoneSingleVolume SingleVolumeApplication.h 4)
+##BuildSample(OrthancStoneBasicPetCtFusion 5)
+##BuildSample(OrthancStoneSynchronizedSeries 6)
+##BuildSample(OrthancStoneLayoutPetCtFusion 7)
 BuildSample(OrthancStoneSimpleViewer SimpleViewerApplication.h 8)
 
 
--- a/Platforms/Generic/OracleWebService.h	Wed Jun 20 09:50:25 2018 +0200
+++ b/Platforms/Generic/OracleWebService.h	Wed Jun 20 14:20:55 2018 +0200
@@ -56,5 +56,15 @@
     {
       oracle_.Submit(new WebServicePostCommand(callback, parameters_, uri, body, payload));
     }
+
+    void Start()
+    {
+        oracle_.Start();
+    }
+
+    void Stop()
+    {
+        oracle_.Start();
+    }
   };
 }
--- a/Platforms/Wasm/CMakeLists.txt	Wed Jun 20 09:50:25 2018 +0200
+++ b/Platforms/Wasm/CMakeLists.txt	Wed Jun 20 14:20:55 2018 +0200
@@ -63,9 +63,10 @@
   add_executable(${Target}
     ${ORTHANC_STONE_ROOT}/Platforms/Wasm/Defaults.cpp
     ${ORTHANC_STONE_ROOT}/Platforms/Wasm/WasmWebService.cpp
+    ${ORTHANC_STONE_ROOT}/Platforms/Wasm/WasmViewport.cpp
 
     ${ORTHANC_STONE_ROOT}/Applications/Samples/SampleMainWasm.cpp
-    ${ORTHANC_STONE_ROOT}/Applications/Samples/SampleApplicationContext.cpp
+#    ${ORTHANC_STONE_ROOT}/Applications/Samples/SampleApplicationContext.cpp
     ${ORTHANC_STONE_ROOT}/Applications/Samples/SampleInteractor.h
     ${ORTHANC_STONE_ROOT}/Applications/Samples/SampleApplicationBase.h
     ${ORTHANC_STONE_ROOT}/Applications/Samples/${Header}
--- a/Platforms/Wasm/Defaults.cpp	Wed Jun 20 09:50:25 2018 +0200
+++ b/Platforms/Wasm/Defaults.cpp	Wed Jun 20 14:20:55 2018 +0200
@@ -6,13 +6,17 @@
 #include <Framework/Viewport/WidgetViewport.h>
 #include <Framework/Widgets/LayerWidget.h>
 #include <algorithm>
+#include "Applications/Wasm/StartupParametersBuilder.h"
 
 static unsigned int width_ = 0;
 static unsigned int height_ = 0;
 
 /**********************************/
 
-static std::auto_ptr<OrthancStone::BasicWasmApplication> application;
+static std::unique_ptr<OrthancStone::IBasicApplication> application;
+static std::unique_ptr<OrthancStone::BasicApplicationContext> context;
+static OrthancStone::StartupParametersBuilder startupParametersBuilder;
+
 static OrthancStone::ChangeObserver changeObserver_;
 static OrthancStone::StatusBar statusBar_;
 
@@ -64,13 +68,12 @@
 
     application.reset(CreateUserApplication());
 
-    boost::program_options::options_description options;
-    application->DeclareStartupOptions(options);
+    startupParametersBuilder.Clear();
   }
 
   void EMSCRIPTEN_KEEPALIVE SetStartupParameter(const char* keyc,
                                                   const char* value) {
-    application->SetStartupParameter(keyc, value);
+    startupParametersBuilder.SetStartupParameter(keyc, value);
   }
 
   void EMSCRIPTEN_KEEPALIVE StartWasmApplication() {
@@ -79,10 +82,13 @@
 
     // recreate a command line from uri arguments and parse it
     boost::program_options::variables_map parameters;
-    application->GetStartupParameters(parameters);
+    boost::program_options::options_description options;
+    application->DeclareStartupOptions(options);
+    startupParametersBuilder.GetStartupParameters(parameters, options);
 
-    BasicWasmApplicationContext& context = dynamic_cast<BasicWasmApplicationContext&>(application->CreateApplicationContext(OrthancStone::WasmWebService::GetInstance(), NULL));
-    application->Initialize(statusBar_, parameters);
+    context.reset(new OrthancStone::BasicApplicationContext(OrthancStone::WasmWebService::GetInstance()));
+    application->Initialize(context.get(), statusBar_, parameters);
+    application->InitializeWasm();
 
 //    viewport->SetSize(width_, height_);
     printf("StartWasmApplication - completed\n");
--- a/Platforms/Wasm/Defaults.h	Wed Jun 20 09:50:25 2018 +0200
+++ b/Platforms/Wasm/Defaults.h	Wed Jun 20 14:20:55 2018 +0200
@@ -6,8 +6,7 @@
 #include <Framework/Viewport/WidgetViewport.h>
 #include <Framework/Widgets/LayerWidget.h>
 #include <Framework/Widgets/LayoutWidget.h>
-#include <Applications/Wasm/BasicWasmApplication.h>
-#include <Applications/Wasm/BasicWasmApplicationContext.h>
+#include <Applications/IBasicApplication.h>
 
 typedef OrthancStone::WidgetViewport* ViewportHandle; // the objects exchanged between JS and C++
 
@@ -25,7 +24,7 @@
 }
 #endif
 
-extern OrthancStone::BasicWasmApplication* CreateUserApplication();
+extern OrthancStone::IBasicApplication* CreateUserApplication();
 
 namespace OrthancStone {
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/Wasm/WasmViewport.cpp	Wed Jun 20 14:20:55 2018 +0200
@@ -0,0 +1,13 @@
+#include "WasmViewport.h"
+
+#include <vector>
+#include <memory>
+
+std::vector<std::shared_ptr<OrthancStone::WidgetViewport>> wasmViewports;
+
+void AttachWidgetToWasmViewport(const char* htmlCanvasId, OrthancStone::IWidget* centralWidget) {
+    std::shared_ptr<OrthancStone::WidgetViewport> viewport(CreateWasmViewportFromCpp(htmlCanvasId));
+    viewport->SetCentralWidget(centralWidget);
+
+    wasmViewports.push_back(viewport);
+}
\ No newline at end of file
--- a/Platforms/Wasm/WasmViewport.h	Wed Jun 20 09:50:25 2018 +0200
+++ b/Platforms/Wasm/WasmViewport.h	Wed Jun 20 14:20:55 2018 +0200
@@ -13,4 +13,6 @@
 
 #ifdef __cplusplus
 }
-#endif
\ No newline at end of file
+#endif
+
+extern void AttachWidgetToWasmViewport(const char* htmlCanvasId, OrthancStone::IWidget* centralWidget);
--- a/Resources/CMake/OrthancStoneConfiguration.cmake	Wed Jun 20 09:50:25 2018 +0200
+++ b/Resources/CMake/OrthancStoneConfiguration.cmake	Wed Jun 20 14:20:55 2018 +0200
@@ -157,8 +157,8 @@
     )
 else()
   list(APPEND APPLICATIONS_SOURCES
-    ${ORTHANC_STONE_ROOT}/Applications/Wasm/BasicWasmApplication.cpp
-    ${ORTHANC_STONE_ROOT}/Applications/Wasm/BasicWasmApplicationContext.cpp
+    ${ORTHANC_STONE_ROOT}/Applications/Wasm/StartupParametersBuilder.cpp
+    # ${ORTHANC_STONE_ROOT}/Applications/Wasm/BasicWasmApplicationContext.cpp
     )
 endif()