# HG changeset patch
# User am@osimis.io
# Date 1528718462 -7200
# Node ID d7b2590744f88bcec5f2d25c6b22ba450b8b74b2
# Parent 26e3bfe30e663426e9fd61549c88d326a8bcd36b
wip: building applications reusable in SDL and WASM
diff -r 26e3bfe30e66 -r d7b2590744f8 Applications/BasicApplication.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Applications/BasicApplication.cpp Mon Jun 11 14:01:02 2018 +0200
@@ -0,0 +1,291 @@
+/**
+ * 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 .
+ **/
+
+
+#include "IBasicApplication.h"
+
+#include "../Framework/Toolbox/MessagingToolbox.h"
+#include "Sdl/SdlEngine.h"
+
+#include
+#include
+#include
+
+namespace OrthancStone
+{
+ // Anonymous namespace to avoid clashes against other compilation modules
+ namespace
+ {
+ class LogStatusBar : public IStatusBar
+ {
+ public:
+ virtual void ClearMessage()
+ {
+ }
+
+ virtual void SetMessage(const std::string& message)
+ {
+ LOG(WARNING) << message;
+ }
+ };
+ }
+
+
+#if ORTHANC_ENABLE_SDL == 1
+ static void DeclareSdlCommandLineOptions(boost::program_options::options_description& options)
+ {
+ // Declare the supported parameters
+ boost::program_options::options_description generic("Generic options");
+ generic.add_options()
+ ("help", "Display this help and exit")
+ ("verbose", "Be verbose in logs")
+ ("orthanc", boost::program_options::value()->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()->default_value(true), "Check HTTPS certificates")
+ ;
+
+ options.add(generic);
+
+ boost::program_options::options_description sdl("SDL options");
+ sdl.add_options()
+ ("width", boost::program_options::value()->default_value(1024), "Initial width of the SDL window")
+ ("height", boost::program_options::value()->default_value(768), "Initial height of the SDL window")
+ ("opengl", boost::program_options::value()->default_value(true), "Enable OpenGL in SDL")
+ ;
+
+ options.add(sdl);
+ }
+
+
+ int IBasicApplication::ExecuteWithSdl(IBasicApplication& application,
+ int argc,
+ char* argv[])
+ {
+ /******************************************************************
+ * Initialize all the subcomponents of Orthanc Stone
+ ******************************************************************/
+
+ Orthanc::Logging::Initialize();
+ Orthanc::HttpClient::InitializeOpenSsl();
+ Orthanc::HttpClient::GlobalInitialize();
+ SdlWindow::GlobalInitialize();
+
+
+ /******************************************************************
+ * Declare and parse the command-line options of the application
+ ******************************************************************/
+
+ boost::program_options::options_description options;
+ DeclareSdlCommandLineOptions(options);
+ application.DeclareCommandLineOptions(options);
+
+ boost::program_options::variables_map parameters;
+ bool error = false;
+
+ try
+ {
+ 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();
+ error = true;
+ }
+
+
+ /******************************************************************
+ * Configure the application with the command-line parameters
+ ******************************************************************/
+
+ 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 using SDL."
+ << std::endl;
+
+ std::cout << options << "\n";
+ return error ? -1 : 0;
+ }
+
+ if (parameters.count("https-verify") &&
+ !parameters["https-verify"].as())
+ {
+ LOG(WARNING) << "Turning off verification of HTTPS certificates (unsafe)";
+ Orthanc::HttpClient::ConfigureSsl(false, "");
+ }
+
+ if (parameters.count("verbose"))
+ {
+ Orthanc::Logging::EnableInfoLevel(true);
+ }
+
+ if (!parameters.count("width") ||
+ !parameters.count("height") ||
+ !parameters.count("opengl"))
+ {
+ LOG(ERROR) << "Parameter \"width\", \"height\" or \"opengl\" is missing";
+ return -1;
+ }
+
+ int w = parameters["width"].as();
+ int h = parameters["height"].as();
+ if (w <= 0 || h <= 0)
+ {
+ LOG(ERROR) << "Parameters \"width\" and \"height\" must be positive";
+ return -1;
+ }
+
+ unsigned int width = static_cast(w);
+ unsigned int height = static_cast(h);
+ LOG(WARNING) << "Initial display size: " << width << "x" << height;
+
+ bool opengl = parameters["opengl"].as();
+ if (opengl)
+ {
+ LOG(WARNING) << "OpenGL is enabled, disable it with option \"--opengl=off\" if the application crashes";
+ }
+ else
+ {
+ LOG(WARNING) << "OpenGL is disabled, enable it with option \"--opengl=on\" for best performance";
+ }
+
+ bool success = true;
+ try
+ {
+ /****************************************************************
+ * Initialize the connection to the Orthanc server
+ ****************************************************************/
+
+ Orthanc::WebServiceParameters webService;
+
+ if (parameters.count("orthanc"))
+ {
+ webService.SetUrl(parameters["orthanc"].as());
+ }
+
+ if (parameters.count("username"))
+ {
+ webService.SetUsername(parameters["username"].as());
+ }
+
+ if (parameters.count("password"))
+ {
+ webService.SetPassword(parameters["password"].as());
+ }
+
+ LOG(WARNING) << "URL to the Orthanc REST API: " << webService.GetUrl();
+
+ {
+ OrthancPlugins::OrthancHttpConnection orthanc(webService);
+ if (!MessagingToolbox::CheckOrthancVersion(orthanc))
+ {
+ LOG(ERROR) << "Your version of Orthanc is incompatible with Stone of Orthanc, please upgrade";
+ throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol);
+ }
+ }
+
+
+ /****************************************************************
+ * Initialize the application
+ ****************************************************************/
+
+ LOG(WARNING) << "Creating the widgets of the application";
+
+ LogStatusBar statusBar;
+ BasicApplicationContext context(webService);
+
+ application.Initialize(context, statusBar, parameters);
+
+ {
+ BasicApplicationContext::ViewportLocker locker(context);
+ locker.GetViewport().SetStatusBar(statusBar);
+ }
+
+ std::string title = application.GetTitle();
+ if (title.empty())
+ {
+ title = "Stone of Orthanc";
+ }
+
+ {
+ /**************************************************************
+ * Run the application inside a SDL window
+ **************************************************************/
+
+ LOG(WARNING) << "Starting the application";
+
+ SdlWindow window(title.c_str(), width, height, opengl);
+ SdlEngine sdl(window, context);
+
+ {
+ BasicApplicationContext::ViewportLocker locker(context);
+ locker.GetViewport().Register(sdl); // (*)
+ }
+
+ context.Start();
+ sdl.Run();
+
+ LOG(WARNING) << "Stopping the application";
+
+ // Don't move the "Stop()" command below out of the block,
+ // otherwise the application might crash, because the
+ // "SdlEngine" is an observer of the viewport (*) and the
+ // update thread started by "context.Start()" would call a
+ // destructed object (the "SdlEngine" is deleted with the
+ // lexical scope).
+ context.Stop();
+ }
+
+
+ /****************************************************************
+ * Finalize the application
+ ****************************************************************/
+
+ LOG(WARNING) << "The application has stopped";
+ application.Finalize();
+ }
+ catch (Orthanc::OrthancException& e)
+ {
+ LOG(ERROR) << "EXCEPTION: " << e.What();
+ success = false;
+ }
+
+
+ /******************************************************************
+ * Finalize all the subcomponents of Orthanc Stone
+ ******************************************************************/
+
+ SdlWindow::GlobalFinalize();
+ Orthanc::HttpClient::GlobalFinalize();
+ Orthanc::HttpClient::FinalizeOpenSsl();
+
+ return (success ? 0 : -1);
+ }
+#endif
+
+}
diff -r 26e3bfe30e66 -r d7b2590744f8 Applications/BasicApplication.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Applications/BasicApplication.h Mon Jun 11 14:01:02 2018 +0200
@@ -0,0 +1,68 @@
+/**
+ * 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 .
+ **/
+
+
+#pragma once
+
+#include "BasicApplicationContext.h"
+
+#include
+
+#if ORTHANC_ENABLE_SDL == 1
+# include // Necessary to avoid undefined reference to `SDL_main'
+#endif
+
+namespace OrthancStone
+{
+ class IBasicApplication : public boost::noncopyable
+ {
+ public:
+ virtual ~IBasicApplication()
+ {
+ }
+
+ virtual void DeclareStartupOption(const std::string& name, const std::string& defaultValue, const std::string& helpText) = 0;
+ virtual void Initialize(IStatusBar& statusBar, const std::map startupOptions);
+
+
+ virtual void DeclareCommandLineOptions(boost::program_options::options_description& options) = 0;
+
+ virtual std::string GetTitle() const = 0;
+
+ virtual void Initialize(BasicApplicationContext& context,
+ IStatusBar& statusBar,
+ const boost::program_options::variables_map& parameters) = 0;
+
+ virtual void Finalize() = 0;
+
+#if ORTHANC_ENABLE_SDL == 1
+ static int ExecuteWithSdl(IBasicApplication& application,
+ int argc,
+ char* argv[]);
+#endif
+ };
+
+ class IBasicSdlApplication : public IBasicApplication
+ {
+ public:
+
+
+ }
+}
diff -r 26e3bfe30e66 -r d7b2590744f8 Applications/BasicApplicationContext.cpp
--- a/Applications/BasicApplicationContext.cpp Fri Jun 08 14:41:45 2018 +0200
+++ b/Applications/BasicApplicationContext.cpp Mon Jun 11 14:01:02 2018 +0200
@@ -48,81 +48,18 @@
}
- BasicApplicationContext::~BasicApplicationContext()
- {
- for (Interactors::iterator it = interactors_.begin(); it != interactors_.end(); ++it)
- {
- assert(*it != NULL);
- delete *it;
- }
-
- for (SlicedVolumes::iterator it = slicedVolumes_.begin(); it != slicedVolumes_.end(); ++it)
- {
- assert(*it != NULL);
- delete *it;
- }
-
- for (VolumeLoaders::iterator it = volumeLoaders_.begin(); it != volumeLoaders_.end(); ++it)
- {
- assert(*it != NULL);
- delete *it;
- }
- }
-
-
IWidget& BasicApplicationContext::SetCentralWidget(IWidget* widget) // Takes ownership
{
- viewport_.SetCentralWidget(widget);
+ centralViewport_.SetCentralWidget(widget);
return *widget;
}
- ISlicedVolume& BasicApplicationContext::AddSlicedVolume(ISlicedVolume* volume)
- {
- if (volume == NULL)
- {
- throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
- }
- else
- {
- slicedVolumes_.push_back(volume);
- return *volume;
- }
- }
-
-
- IVolumeLoader& BasicApplicationContext::AddVolumeLoader(IVolumeLoader* loader)
- {
- if (loader == NULL)
- {
- throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
- }
- else
- {
- volumeLoaders_.push_back(loader);
- return *loader;
- }
- }
-
-
- IWorldSceneInteractor& BasicApplicationContext::AddInteractor(IWorldSceneInteractor* interactor)
- {
- if (interactor == NULL)
- {
- throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
- }
-
- interactors_.push_back(interactor);
-
- return *interactor;
- }
-
-
void BasicApplicationContext::Start()
{
oracle_.Start();
- if (viewport_.HasUpdateContent())
+ if (centralViewport_.HasUpdateContent())
{
stopped_ = false;
updateThread_ = boost::thread(UpdateThread, this);
diff -r 26e3bfe30e66 -r d7b2590744f8 Applications/BasicApplicationContext.h
--- a/Applications/BasicApplicationContext.h Fri Jun 08 14:41:45 2018 +0200
+++ b/Applications/BasicApplicationContext.h Mon Jun 11 14:01:02 2018 +0200
@@ -35,19 +35,14 @@
class BasicApplicationContext : public boost::noncopyable
{
private:
- typedef std::list SlicedVolumes;
- typedef std::list VolumeLoaders;
- typedef std::list Interactors;
static void UpdateThread(BasicApplicationContext* that);
+
Oracle oracle_;
OracleWebService webService_;
boost::mutex viewportMutex_;
- WidgetViewport viewport_;
- SlicedVolumes slicedVolumes_;
- VolumeLoaders volumeLoaders_;
- Interactors interactors_;
+ WidgetViewport centralViewport_;
boost::thread updateThread_;
bool stopped_;
unsigned int updateDelay_;
@@ -62,7 +57,7 @@
public:
ViewportLocker(BasicApplicationContext& that) :
lock_(that.viewportMutex_),
- viewport_(that.viewport_)
+ viewport_(that.centralViewport_)
{
}
@@ -75,7 +70,7 @@
BasicApplicationContext(Orthanc::WebServiceParameters& orthanc);
- ~BasicApplicationContext();
+ virtual ~BasicApplicationContext() {}
IWidget& SetCentralWidget(IWidget* widget); // Takes ownership
@@ -84,12 +79,6 @@
return webService_;
}
- ISlicedVolume& AddSlicedVolume(ISlicedVolume* volume);
-
- IVolumeLoader& AddVolumeLoader(IVolumeLoader* loader);
-
- IWorldSceneInteractor& AddInteractor(IWorldSceneInteractor* interactor);
-
void Start();
void Stop();
diff -r 26e3bfe30e66 -r d7b2590744f8 Applications/IBasicApplication.cpp
--- a/Applications/IBasicApplication.cpp Fri Jun 08 14:41:45 2018 +0200
+++ b/Applications/IBasicApplication.cpp Mon Jun 11 14:01:02 2018 +0200
@@ -30,262 +30,34 @@
namespace OrthancStone
{
- // Anonymous namespace to avoid clashes against other compilation modules
- namespace
- {
- class LogStatusBar : public IStatusBar
- {
- public:
- virtual void ClearMessage()
- {
- }
-
- virtual void SetMessage(const std::string& message)
- {
- LOG(WARNING) << message;
- }
- };
- }
-
-
-#if ORTHANC_ENABLE_SDL == 1
- static void DeclareSdlCommandLineOptions(boost::program_options::options_description& options)
- {
- // Declare the supported parameters
- boost::program_options::options_description generic("Generic options");
- generic.add_options()
- ("help", "Display this help and exit")
- ("verbose", "Be verbose in logs")
- ("orthanc", boost::program_options::value()->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()->default_value(true), "Check HTTPS certificates")
- ;
-
- options.add(generic);
-
- boost::program_options::options_description sdl("SDL options");
- sdl.add_options()
- ("width", boost::program_options::value()->default_value(1024), "Initial width of the SDL window")
- ("height", boost::program_options::value()->default_value(768), "Initial height of the SDL window")
- ("opengl", boost::program_options::value()->default_value(true), "Enable OpenGL in SDL")
- ;
-
- options.add(sdl);
- }
-
-
- int IBasicApplication::ExecuteWithSdl(IBasicApplication& application,
- int argc,
- char* argv[])
- {
- /******************************************************************
- * Initialize all the subcomponents of Orthanc Stone
- ******************************************************************/
-
- Orthanc::Logging::Initialize();
- Orthanc::HttpClient::InitializeOpenSsl();
- Orthanc::HttpClient::GlobalInitialize();
- SdlWindow::GlobalInitialize();
-
-
- /******************************************************************
- * Declare and parse the command-line options of the application
- ******************************************************************/
+ 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;
- boost::program_options::options_description options;
- DeclareSdlCommandLineOptions(options);
- application.DeclareCommandLineOptions(options);
-
- boost::program_options::variables_map parameters;
- bool error = false;
-
- try
- {
- 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();
- error = true;
- }
-
-
- /******************************************************************
- * Configure the application with the command-line parameters
- ******************************************************************/
-
- 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 using SDL."
- << std::endl;
-
- std::cout << options << "\n";
- return error ? -1 : 0;
- }
-
- if (parameters.count("https-verify") &&
- !parameters["https-verify"].as())
- {
- LOG(WARNING) << "Turning off verification of HTTPS certificates (unsafe)";
- Orthanc::HttpClient::ConfigureSsl(false, "");
- }
-
- if (parameters.count("verbose"))
- {
- Orthanc::Logging::EnableInfoLevel(true);
- }
-
- if (!parameters.count("width") ||
- !parameters.count("height") ||
- !parameters.count("opengl"))
- {
- LOG(ERROR) << "Parameter \"width\", \"height\" or \"opengl\" is missing";
- return -1;
- }
-
- int w = parameters["width"].as();
- int h = parameters["height"].as();
- if (w <= 0 || h <= 0)
- {
- LOG(ERROR) << "Parameters \"width\" and \"height\" must be positive";
- return -1;
+ startupOptions_.push_back(option);
}
- unsigned int width = static_cast(w);
- unsigned int height = static_cast(h);
- LOG(WARNING) << "Initial display size: " << width << "x" << height;
+ 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;
- bool opengl = parameters["opengl"].as();
- if (opengl)
- {
- LOG(WARNING) << "OpenGL is enabled, disable it with option \"--opengl=off\" if the application crashes";
- }
- else
- {
- LOG(WARNING) << "OpenGL is disabled, enable it with option \"--opengl=on\" for best performance";
+ startupOptions_.push_back(option);
}
- bool success = true;
- try
- {
- /****************************************************************
- * Initialize the connection to the Orthanc server
- ****************************************************************/
-
- Orthanc::WebServiceParameters webService;
-
- if (parameters.count("orthanc"))
- {
- webService.SetUrl(parameters["orthanc"].as());
- }
-
- if (parameters.count("username"))
- {
- webService.SetUsername(parameters["username"].as());
- }
-
- if (parameters.count("password"))
- {
- webService.SetPassword(parameters["password"].as());
- }
-
- LOG(WARNING) << "URL to the Orthanc REST API: " << webService.GetUrl();
-
- {
- OrthancPlugins::OrthancHttpConnection orthanc(webService);
- if (!MessagingToolbox::CheckOrthancVersion(orthanc))
- {
- LOG(ERROR) << "Your version of Orthanc is incompatible with Stone of Orthanc, please upgrade";
- throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol);
- }
- }
-
-
- /****************************************************************
- * Initialize the application
- ****************************************************************/
-
- LOG(WARNING) << "Creating the widgets of the application";
-
- LogStatusBar statusBar;
- BasicApplicationContext context(webService);
-
- application.Initialize(context, statusBar, parameters);
+ 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;
- {
- BasicApplicationContext::ViewportLocker locker(context);
- locker.GetViewport().SetStatusBar(statusBar);
- }
-
- std::string title = application.GetTitle();
- if (title.empty())
- {
- title = "Stone of Orthanc";
- }
-
- {
- /**************************************************************
- * Run the application inside a SDL window
- **************************************************************/
-
- LOG(WARNING) << "Starting the application";
-
- SdlWindow window(title.c_str(), width, height, opengl);
- SdlEngine sdl(window, context);
-
- {
- BasicApplicationContext::ViewportLocker locker(context);
- locker.GetViewport().Register(sdl); // (*)
- }
-
- context.Start();
- sdl.Run();
-
- LOG(WARNING) << "Stopping the application";
-
- // Don't move the "Stop()" command below out of the block,
- // otherwise the application might crash, because the
- // "SdlEngine" is an observer of the viewport (*) and the
- // update thread started by "context.Start()" would call a
- // destructed object (the "SdlEngine" is deleted with the
- // lexical scope).
- context.Stop();
- }
-
-
- /****************************************************************
- * Finalize the application
- ****************************************************************/
-
- LOG(WARNING) << "The application has stopped";
- application.Finalize();
- }
- catch (Orthanc::OrthancException& e)
- {
- LOG(ERROR) << "EXCEPTION: " << e.What();
- success = false;
+ startupOptions_.push_back(option);
}
-
- /******************************************************************
- * Finalize all the subcomponents of Orthanc Stone
- ******************************************************************/
-
- SdlWindow::GlobalFinalize();
- Orthanc::HttpClient::GlobalFinalize();
- Orthanc::HttpClient::FinalizeOpenSsl();
-
- return (success ? 0 : -1);
- }
-#endif
-
}
diff -r 26e3bfe30e66 -r d7b2590744f8 Applications/IBasicApplication.h
--- a/Applications/IBasicApplication.h Fri Jun 08 14:41:45 2018 +0200
+++ b/Applications/IBasicApplication.h Mon Jun 11 14:01:02 2018 +0200
@@ -22,36 +22,62 @@
#pragma once
#include "BasicApplicationContext.h"
-
#include
-#if ORTHANC_ENABLE_SDL == 1
-# include // Necessary to avoid undefined reference to `SDL_main'
-#endif
-
namespace OrthancStone
{
class IBasicApplication : public boost::noncopyable
{
+ protected:
+// struct StartupOptionValue {
+// enum Type {
+// boolean,
+// string,
+// integer
+// };
+// Type type;
+// std::string value;
+
+// int asInt() {return std::stoi(value);}
+// bool asBool() {return value == "true"; }
+// std::string asString() {return value; }
+// };
+
+// struct StartupOptionDefinition {
+// std::string name;
+// std::string helpText;
+// std::string defaultValue;
+// StartupOptionValue::Type type;
+// };
+
+// typedef std::list StartupOptions;
+
+// StartupOptions startupOptions_;
+
public:
virtual ~IBasicApplication()
{
}
- virtual void DeclareCommandLineOptions(boost::program_options::options_description& options) = 0;
+ virtual void DeclareStartupOptions(boost::program_options::options_description& options) = 0;
+ virtual void Initialize(IStatusBar& statusBar,
+ const boost::program_options::variables_map& parameters) = 0;
+
+ virtual BasicApplicationContext& CreateApplicationContext(Orthanc::WebServiceParameters& orthanc) = 0;
+
virtual std::string GetTitle() const = 0;
- virtual void Initialize(BasicApplicationContext& context,
- IStatusBar& statusBar,
- const boost::program_options::variables_map& parameters) = 0;
+// virtual void Initialize(BasicApplicationContext& context,
+// IStatusBar& statusBar,
+// const std::map& startupOptions) = 0;
virtual void Finalize() = 0;
-#if ORTHANC_ENABLE_SDL == 1
- static int ExecuteWithSdl(IBasicApplication& application,
- int argc,
- char* argv[]);
-#endif
+//protected:
+// virtual void DeclareStringStartupOption(const std::string& name, const std::string& defaultValue, const std::string& helpText);
+// virtual void DeclareIntegerStartupOption(const std::string& name, const int& defaultValue, const std::string& helpText);
+// virtual void DeclareBoolStartupOption(const std::string& name, bool defaultValue, const std::string& helpText);
};
+
}
diff -r 26e3bfe30e66 -r d7b2590744f8 Applications/Samples/SampleApplicationBase.h
--- a/Applications/Samples/SampleApplicationBase.h Fri Jun 08 14:41:45 2018 +0200
+++ b/Applications/Samples/SampleApplicationBase.h Mon Jun 11 14:01:02 2018 +0200
@@ -21,27 +21,38 @@
#pragma once
-#include "../IBasicApplication.h"
+#include "../../Applications/Sdl/BasicSdlApplication.h"
+#include "SampleApplicationContext.h"
namespace OrthancStone
{
namespace Samples
{
- class SampleApplicationBase : public IBasicApplication
+
+#ifdef ORTHANC_ENABLE_SDL
+ class SampleSdlApplicationBase : BasicSdlApplication {
+ private:
+ std::unique_ptr context_;
+
+ BasicApplicationContext& CreateApplicationContext(Orthanc::WebServiceParameters& orthanc) {
+ context_.reset(new SampleApplicationContext(orthanc));
+ }
+ };
+
+ typedef SampleApplicationBase_ SampleSdlApplicationBase;
+#else
+
+#endif
+
+ class SampleApplicationBase : public SampleApplicationBase_
{
public:
virtual std::string GetTitle() const
{
return "Stone of Orthanc - Sample";
}
-
- virtual void DeclareCommandLineOptions(boost::program_options::options_description& options)
- {
- }
+ };
- virtual void Finalize()
- {
- }
- };
+
}
}
diff -r 26e3bfe30e66 -r d7b2590744f8 Applications/Samples/SampleApplicationContext.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Applications/Samples/SampleApplicationContext.cpp Mon Jun 11 14:01:02 2018 +0200
@@ -0,0 +1,94 @@
+/**
+ * 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 .
+ **/
+
+
+#include "SampleApplicationContext.h"
+
+namespace OrthancStone
+{
+ SampleApplicationContext::SampleApplicationContext(Orthanc::WebServiceParameters& orthanc) :
+ BaseApplicationContext(orthanc)
+ {
+ }
+
+
+ SampleApplicationContext::~SampleApplicationContext()
+ {
+ for (Interactors::iterator it = interactors_.begin(); it != interactors_.end(); ++it)
+ {
+ assert(*it != NULL);
+ delete *it;
+ }
+
+ for (SlicedVolumes::iterator it = slicedVolumes_.begin(); it != slicedVolumes_.end(); ++it)
+ {
+ assert(*it != NULL);
+ delete *it;
+ }
+
+ for (VolumeLoaders::iterator it = volumeLoaders_.begin(); it != volumeLoaders_.end(); ++it)
+ {
+ assert(*it != NULL);
+ delete *it;
+ }
+ }
+
+
+ ISlicedVolume& SampleApplicationContext::AddSlicedVolume(ISlicedVolume* volume)
+ {
+ if (volume == NULL)
+ {
+ throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
+ }
+ else
+ {
+ slicedVolumes_.push_back(volume);
+ return *volume;
+ }
+ }
+
+
+ IVolumeLoader& SampleApplicationContext::AddVolumeLoader(IVolumeLoader* loader)
+ {
+ if (loader == NULL)
+ {
+ throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
+ }
+ else
+ {
+ volumeLoaders_.push_back(loader);
+ return *loader;
+ }
+ }
+
+
+ IWorldSceneInteractor& SampleApplicationContext::AddInteractor(IWorldSceneInteractor* interactor)
+ {
+ if (interactor == NULL)
+ {
+ throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
+ }
+
+ interactors_.push_back(interactor);
+
+ return *interactor;
+ }
+}
+
diff -r 26e3bfe30e66 -r d7b2590744f8 Applications/Samples/SampleApplicationContext.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Applications/Samples/SampleApplicationContext.h Mon Jun 11 14:01:02 2018 +0200
@@ -0,0 +1,60 @@
+/**
+ * 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 .
+ **/
+
+
+#pragma once
+
+#include "../../Framework/Viewport/WidgetViewport.h"
+#include "../../Framework/Volumes/ISlicedVolume.h"
+#include "../../Framework/Volumes/IVolumeLoader.h"
+#include "../../Framework/Widgets/IWorldSceneInteractor.h"
+#include "../../Platforms/Generic/OracleWebService.h"
+#include "../BasicApplicationContext.h"
+
+#include
+#include
+
+
+namespace OrthancStone
+{
+ class SampleApplicationContext : public BasicApplicationContext
+ {
+ private:
+ typedef std::list SlicedVolumes; // this is actually used by the samples and shall be moved to a SampleApplicationContext
+ typedef std::list VolumeLoaders;
+ typedef std::list Interactors;
+
+ SlicedVolumes slicedVolumes_;
+ VolumeLoaders volumeLoaders_;
+ Interactors interactors_;
+
+ public:
+
+ SampleApplicationContext(Orthanc::WebServiceParameters& orthanc);
+
+ virtual ~SampleApplicationContext();
+
+ ISlicedVolume& AddSlicedVolume(ISlicedVolume* volume);
+
+ IVolumeLoader& AddVolumeLoader(IVolumeLoader* loader);
+
+ IWorldSceneInteractor& AddInteractor(IWorldSceneInteractor* interactor);
+ };
+}
diff -r 26e3bfe30e66 -r d7b2590744f8 Applications/Sdl/BasicSdlApplication.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Applications/Sdl/BasicSdlApplication.cpp Mon Jun 11 14:01:02 2018 +0200
@@ -0,0 +1,316 @@
+/**
+ * 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 .
+ **/
+
+
+#if ORTHANC_ENABLE_SDL != 1
+#error this file shall be included only with the ORTHANC_ENABLE_SDL set to 1
+#endif
+
+#include "BasicSdlApplication.h"
+
+#include "../../Framework/Toolbox/MessagingToolbox.h"
+#include "SdlEngine.h"
+
+#include
+#include
+#include
+
+namespace OrthancStone
+{
+ // Anonymous namespace to avoid clashes against other compilation modules
+ namespace
+ {
+ class LogStatusBar : public IStatusBar
+ {
+ public:
+ virtual void ClearMessage()
+ {
+ }
+
+ virtual void SetMessage(const std::string& message)
+ {
+ LOG(WARNING) << message;
+ }
+ };
+ }
+
+
+ static void DeclareSdlCommandLineOptions(boost::program_options::options_description& options)
+ {
+ // Declare the supported parameters
+ boost::program_options::options_description generic("Generic options");
+ generic.add_options()
+ ("help", "Display this help and exit")
+ ("verbose", "Be verbose in logs")
+ ("orthanc", boost::program_options::value()->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()->default_value(true), "Check HTTPS certificates")
+ ;
+
+ options.add(generic);
+
+ boost::program_options::options_description sdl("SDL options");
+ sdl.add_options()
+ ("width", boost::program_options::value()->default_value(1024), "Initial width of the SDL window")
+ ("height", boost::program_options::value()->default_value(768), "Initial height of the SDL window")
+ ("opengl", boost::program_options::value()->default_value(true), "Enable OpenGL in SDL")
+ ;
+
+ options.add(sdl);
+ }
+
+// void BasicSdlApplication::DeclareCommandLineOptions(boost::program_options::options_description &options) {
+// boost::program_options::options_description app("Application specifi options");
+
+// for (IBasicApplication::StartupOptions::const_iterator it = startupOptions_.begin(); it != startupOptions_.end(); it++) {
+// switch (it->type) {
+// case IBasicApplication::StartupOptionValue::boolean:
+// app.add_options()
+// (it->name.c_str(), boost::program_options::value()->default_value(std::stoi(it->defaultValue)), it->helpText.c_str());
+// break;
+// case IBasicApplication::StartupOptionValue::integer:
+// app.add_options()
+// (it->name.c_str(), boost::program_options::value()->default_value(it->defaultValue == "true"), it->helpText.c_str());
+// break;
+// case IBasicApplication::StartupOptionValue::string:
+// app.add_options()
+// (it->name.c_str(), boost::program_options::value()->default_value(it->defaultValue), it->helpText.c_str());
+// break;
+// default:
+// throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented);
+// }
+// }
+// options.add(app);
+// }
+
+ int BasicSdlApplication::ExecuteWithSdl(BasicSdlApplication& application,
+ int argc,
+ char* argv[])
+ {
+ /******************************************************************
+ * Initialize all the subcomponents of Orthanc Stone
+ ******************************************************************/
+
+ Orthanc::Logging::Initialize();
+ Orthanc::HttpClient::InitializeOpenSsl();
+ Orthanc::HttpClient::GlobalInitialize();
+ SdlWindow::GlobalInitialize();
+
+
+ /******************************************************************
+ * Declare and parse the command-line options of the application
+ ******************************************************************/
+
+ boost::program_options::options_description options;
+ DeclareSdlCommandLineOptions(options);
+ application.DeclareStartupOptions(options);
+
+ boost::program_options::variables_map parameters;
+ bool error = false;
+
+ try
+ {
+ 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();
+ error = true;
+ }
+
+
+ /******************************************************************
+ * Configure the application with the command-line parameters
+ ******************************************************************/
+
+ 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 using SDL."
+ << std::endl;
+
+ std::cout << options << "\n";
+ return error ? -1 : 0;
+ }
+
+ if (parameters.count("https-verify") &&
+ !parameters["https-verify"].as())
+ {
+ LOG(WARNING) << "Turning off verification of HTTPS certificates (unsafe)";
+ Orthanc::HttpClient::ConfigureSsl(false, "");
+ }
+
+ if (parameters.count("verbose"))
+ {
+ Orthanc::Logging::EnableInfoLevel(true);
+ }
+
+ if (!parameters.count("width") ||
+ !parameters.count("height") ||
+ !parameters.count("opengl"))
+ {
+ LOG(ERROR) << "Parameter \"width\", \"height\" or \"opengl\" is missing";
+ return -1;
+ }
+
+ int w = parameters["width"].as();
+ int h = parameters["height"].as();
+ if (w <= 0 || h <= 0)
+ {
+ LOG(ERROR) << "Parameters \"width\" and \"height\" must be positive";
+ return -1;
+ }
+
+ unsigned int width = static_cast(w);
+ unsigned int height = static_cast(h);
+ LOG(WARNING) << "Initial display size: " << width << "x" << height;
+
+ bool opengl = parameters["opengl"].as();
+ if (opengl)
+ {
+ LOG(WARNING) << "OpenGL is enabled, disable it with option \"--opengl=off\" if the application crashes";
+ }
+ else
+ {
+ LOG(WARNING) << "OpenGL is disabled, enable it with option \"--opengl=on\" for best performance";
+ }
+
+ bool success = true;
+ try
+ {
+ /****************************************************************
+ * Initialize the connection to the Orthanc server
+ ****************************************************************/
+
+ Orthanc::WebServiceParameters webService;
+
+ if (parameters.count("orthanc"))
+ {
+ webService.SetUrl(parameters["orthanc"].as());
+ }
+
+ if (parameters.count("username"))
+ {
+ webService.SetUsername(parameters["username"].as());
+ }
+
+ if (parameters.count("password"))
+ {
+ webService.SetPassword(parameters["password"].as());
+ }
+
+ LOG(WARNING) << "URL to the Orthanc REST API: " << webService.GetUrl();
+
+ {
+ OrthancPlugins::OrthancHttpConnection orthanc(webService);
+ if (!MessagingToolbox::CheckOrthancVersion(orthanc))
+ {
+ LOG(ERROR) << "Your version of Orthanc is incompatible with Stone of Orthanc, please upgrade";
+ throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol);
+ }
+ }
+
+
+ /****************************************************************
+ * Initialize the application
+ ****************************************************************/
+
+ LOG(WARNING) << "Creating the widgets of the application";
+
+ LogStatusBar statusBar;
+ BasicApplicationContext& context = application.CreateApplicationContext(webService);
+
+ application.Initialize(statusBar, parameters);
+
+ {
+ BasicApplicationContext::ViewportLocker locker(context);
+ locker.GetViewport().SetStatusBar(statusBar);
+ }
+
+ std::string title = application.GetTitle();
+ if (title.empty())
+ {
+ title = "Stone of Orthanc";
+ }
+
+ {
+ /**************************************************************
+ * Run the application inside a SDL window
+ **************************************************************/
+
+ LOG(WARNING) << "Starting the application";
+
+ SdlWindow window(title.c_str(), width, height, opengl);
+ SdlEngine sdl(window, context);
+
+ {
+ BasicApplicationContext::ViewportLocker locker(context);
+ locker.GetViewport().Register(sdl); // (*)
+ }
+
+ context.Start();
+ sdl.Run();
+
+ LOG(WARNING) << "Stopping the application";
+
+ // Don't move the "Stop()" command below out of the block,
+ // otherwise the application might crash, because the
+ // "SdlEngine" is an observer of the viewport (*) and the
+ // update thread started by "context.Start()" would call a
+ // destructed object (the "SdlEngine" is deleted with the
+ // lexical scope).
+ context.Stop();
+ }
+
+
+ /****************************************************************
+ * Finalize the application
+ ****************************************************************/
+
+ LOG(WARNING) << "The application has stopped";
+ application.Finalize();
+ }
+ catch (Orthanc::OrthancException& e)
+ {
+ LOG(ERROR) << "EXCEPTION: " << e.What();
+ success = false;
+ }
+
+
+ /******************************************************************
+ * Finalize all the subcomponents of Orthanc Stone
+ ******************************************************************/
+
+ SdlWindow::GlobalFinalize();
+ Orthanc::HttpClient::GlobalFinalize();
+ Orthanc::HttpClient::FinalizeOpenSsl();
+
+ return (success ? 0 : -1);
+ }
+
+}
diff -r 26e3bfe30e66 -r d7b2590744f8 Applications/Sdl/BasicSdlApplication.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Applications/Sdl/BasicSdlApplication.h Mon Jun 11 14:01:02 2018 +0200
@@ -0,0 +1,49 @@
+/**
+ * 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 .
+ **/
+
+
+#pragma once
+
+#include "../BasicApplicationContext.h"
+#include "../IBasicApplication.h"
+
+#include
+
+#if ORTHANC_ENABLE_SDL != 1
+#error this file shall be included only with the ORTHANC_ENABLE_SDL set to 1
+#endif
+
+#include // Necessary to avoid undefined reference to `SDL_main'
+
+namespace OrthancStone
+{
+ class BasicSdlApplication : public IBasicApplication
+ {
+ public:
+ virtual ~BasicSdlApplication()
+ {
+ }
+
+ static int ExecuteWithSdl(BasicSdlApplication& application,
+ int argc,
+ char* argv[]);
+ };
+
+}
diff -r 26e3bfe30e66 -r d7b2590744f8 Applications/Wasm/BasicWasmApplication.cpp
diff -r 26e3bfe30e66 -r d7b2590744f8 Applications/Wasm/BasicWasmApplication.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Applications/Wasm/BasicWasmApplication.h Mon Jun 11 14:01:02 2018 +0200
@@ -0,0 +1,45 @@
+/**
+ * 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 .
+ **/
+
+
+#pragma once
+
+#include "../BasicApplicationContext.h"
+#include "../IBasicApplication.h"
+
+#include
+
+#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
+ {
+ public:
+ virtual ~BasicWasmApplication()
+ {
+ }
+
+ //static int ExecuteWithWasm(BasicWasmApplication& application);
+ };
+
+}
diff -r 26e3bfe30e66 -r d7b2590744f8 Platforms/Generic/CMakeLists.txt
--- a/Platforms/Generic/CMakeLists.txt Fri Jun 08 14:41:45 2018 +0200
+++ b/Platforms/Generic/CMakeLists.txt Mon Jun 11 14:01:02 2018 +0200
@@ -45,9 +45,13 @@
## Build all the sample applications
#####################################################################
-macro(BuildSample Target Sample)
+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/SampleInteractor.h
+ ${ORTHANC_STONE_ROOT}/Applications/Samples/SampleApplicationBase.h
+ ${ORTHANC_STONE_ROOT}/Applications/Samples/${Header}
${APPLICATIONS_SOURCES}
)
set_target_properties(${Target} PROPERTIES COMPILE_DEFINITIONS ORTHANC_STONE_SAMPLE=${Sample})
@@ -57,10 +61,10 @@
# TODO - Re-enable all these samples!
-BuildSample(OrthancStoneEmpty 1)
-BuildSample(OrthancStoneTestPattern 2)
-BuildSample(OrthancStoneSingleFrame 3)
-BuildSample(OrthancStoneSingleVolume 4)
+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)
diff -r 26e3bfe30e66 -r d7b2590744f8 Platforms/WebAssembly/WasmWebService.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/WebAssembly/WasmWebService.cpp Mon Jun 11 14:01:02 2018 +0200
@@ -0,0 +1,90 @@
+#include "WasmWebService.h"
+
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ extern void WasmWebService_ScheduleGetRequest(void* callback,
+ const char* uri,
+ void* payload);
+
+ extern void WasmWebService_SchedulePostRequest(void* callback,
+ const char* uri,
+ const void* body,
+ size_t bodySize,
+ void* payload);
+
+ void EMSCRIPTEN_KEEPALIVE WasmWebService_NotifyError(void* callback,
+ const char* uri,
+ void* payload)
+ {
+ if (callback == NULL)
+ {
+ throw;
+ }
+ else
+ {
+ reinterpret_cast(callback)->
+ NotifyError(uri, reinterpret_cast(payload));
+ }
+ }
+
+ void EMSCRIPTEN_KEEPALIVE WasmWebService_NotifySuccess(void* callback,
+ const char* uri,
+ const void* body,
+ size_t bodySize,
+ void* payload)
+ {
+ if (callback == NULL)
+ {
+ throw;
+ }
+ else
+ {
+ reinterpret_cast(callback)->
+ NotifySuccess(uri, body, bodySize, reinterpret_cast(payload));
+ }
+ }
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+namespace OrthancStone
+{
+ void WasmWebService::SetBaseUrl(const std::string base)
+ {
+ // Make sure the base url ends with "/"
+ if (base.empty() ||
+ base[base.size() - 1] != '/')
+ {
+ base_ = base + "/";
+ }
+ else
+ {
+ base_ = base;
+ }
+ }
+
+ void WasmWebService::ScheduleGetRequest(ICallback& callback,
+ const std::string& uri,
+ Orthanc::IDynamicObject* payload)
+ {
+ std::string url = base_ + uri;
+ WasmWebService_ScheduleGetRequest(&callback, url.c_str(), payload);
+ }
+
+ void WasmWebService::SchedulePostRequest(ICallback& callback,
+ const std::string& uri,
+ const std::string& body,
+ Orthanc::IDynamicObject* payload)
+ {
+ std::string url = base_ + uri;
+ WasmWebService_SchedulePostRequest(&callback, url.c_str(),
+ body.c_str(), body.size(), payload);
+ }
+}
diff -r 26e3bfe30e66 -r d7b2590744f8 Platforms/WebAssembly/WasmWebService.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/WebAssembly/WasmWebService.h Mon Jun 11 14:01:02 2018 +0200
@@ -0,0 +1,44 @@
+#pragma once
+
+#include
+
+namespace OrthancStone
+{
+ class WasmWebService : public IWebService
+ {
+ private:
+ std::string base_;
+
+ // Private constructor => Singleton design pattern
+ WasmWebService() :
+ base_("../../")
+ {
+ }
+
+ public:
+ static WasmWebService& GetInstance()
+ {
+ static WasmWebService instance;
+ return instance;
+ }
+
+ void SetBaseUrl(const std::string base);
+
+ virtual void ScheduleGetRequest(ICallback& callback,
+ const std::string& uri,
+ Orthanc::IDynamicObject* payload);
+
+ virtual void SchedulePostRequest(ICallback& callback,
+ const std::string& uri,
+ const std::string& body,
+ Orthanc::IDynamicObject* payload);
+
+ virtual void Start()
+ {
+ }
+
+ virtual void Stop()
+ {
+ }
+ };
+}
diff -r 26e3bfe30e66 -r d7b2590744f8 Platforms/WebAssembly/WasmWebService.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/WebAssembly/WasmWebService.js Mon Jun 11 14:01:02 2018 +0200
@@ -0,0 +1,51 @@
+mergeInto(LibraryManager.library, {
+ WasmWebService_ScheduleGetRequest: function(callback, url, payload) {
+ // Directly use XMLHttpRequest (no jQuery) to retrieve the raw binary data
+ // http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/
+ var xhr = new XMLHttpRequest();
+ var tmp = UTF8ToString(url);
+ xhr.open('GET', tmp, true);
+ xhr.responseType = 'arraybuffer';
+
+ xhr.onreadystatechange = function() {
+ if (this.readyState == XMLHttpRequest.DONE) {
+ if (xhr.status === 200) {
+ // TODO - Is "new Uint8Array()" necessary? This copies the
+ // answer to the WebAssembly stack, hence necessitating
+ // increasing the TOTAL_STACK parameter of Emscripten
+ WasmWebService_NotifySuccess(callback, tmp, new Uint8Array(this.response),
+ this.response.byteLength, payload);
+ } else {
+ WasmWebService_NotifyError(callback, tmp, payload);
+ }
+ }
+ }
+
+ xhr.send();
+ },
+
+ WasmWebService_SchedulePostRequest: function(callback, url, body, bodySize, payload) {
+ var xhr = new XMLHttpRequest();
+ var tmp = UTF8ToString(url);
+ xhr.open('POST', tmp, true);
+ xhr.responseType = 'arraybuffer';
+ xhr.setRequestHeader('Content-type', 'application/octet-stream');
+
+ xhr.onreadystatechange = function() {
+ if (this.readyState == XMLHttpRequest.DONE) {
+ if (xhr.status === 200) {
+ WasmWebService_NotifySuccess(callback, tmp, new Uint8Array(this.response),
+ this.response.byteLength, payload);
+ } else {
+ WasmWebService_NotifyError(callback, tmp, payload);
+ }
+ }
+ }
+
+ xhr.send(new Uint8ClampedArray(HEAPU8.buffer, body, bodySize));
+ },
+
+ ScheduleRedraw: function() {
+ ScheduleRedraw();
+ }
+});
diff -r 26e3bfe30e66 -r d7b2590744f8 Resources/CMake/OrthancStoneConfiguration.cmake
--- a/Resources/CMake/OrthancStoneConfiguration.cmake Fri Jun 08 14:41:45 2018 +0200
+++ b/Resources/CMake/OrthancStoneConfiguration.cmake Mon Jun 11 14:01:02 2018 +0200
@@ -135,6 +135,10 @@
## All the source files required to build Stone of Orthanc
#####################################################################
+set(APPLICATIONS_SOURCES
+ ${ORTHANC_STONE_ROOT}/Applications/IBasicApplication.h
+ )
+
if (NOT ORTHANC_SANDBOXED)
set(PLATFORM_SOURCES
${ORTHANC_STONE_ROOT}/Platforms/Generic/WebServiceGetCommand.cpp
@@ -142,14 +146,18 @@
${ORTHANC_STONE_ROOT}/Platforms/Generic/Oracle.cpp
)
- set(APPLICATIONS_SOURCES
+ list(APPEND APPLICATIONS_SOURCES
${ORTHANC_STONE_ROOT}/Applications/BasicApplicationContext.cpp
- ${ORTHANC_STONE_ROOT}/Applications/IBasicApplication.cpp
+ ${ORTHANC_STONE_ROOT}/Applications/Sdl/BasicSdlApplication.cpp
${ORTHANC_STONE_ROOT}/Applications/Sdl/SdlEngine.cpp
${ORTHANC_STONE_ROOT}/Applications/Sdl/SdlCairoSurface.cpp
${ORTHANC_STONE_ROOT}/Applications/Sdl/SdlOrthancSurface.cpp
${ORTHANC_STONE_ROOT}/Applications/Sdl/SdlWindow.cpp
)
+else()
+ list(APPEND APPLICATIONS_SOURCES
+ ${ORTHANC_STONE_ROOT}/Applications/Wasm/BasicWasmApplication.cpp
+ )
endif()
list(APPEND ORTHANC_STONE_SOURCES
@@ -222,3 +230,4 @@
${SDL_SOURCES}
${BOOST_EXTENDED_SOURCES}
)
+