# HG changeset patch # User am@osimis.io # Date 1535111575 -7200 # Node ID dc1beee33134830fe30713bd175012495df4cb20 # Parent f21ba24685702cd4155bc75f0fa7ea49fa6d17b3 split SdlApplication into NativeApplication and SdlApplication diff -r f21ba2468570 -r dc1beee33134 Applications/Generic/BasicNativeApplication.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Generic/BasicNativeApplication.cpp Fri Aug 24 13:52:55 2018 +0200 @@ -0,0 +1,251 @@ +/** + * 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_NATIVE != 1 +#error this file shall be included only with the ORTHANC_ENABLE_NATIVE set to 1 +#endif + +#include "BasicNativeApplication.h" +#include "BasicNativeApplicationContext.h" +#include + +#include "../../Framework/Toolbox/MessagingToolbox.h" + +#include +#include +#include +#include +#include "../../Platforms/Generic/OracleWebService.h" + +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; + } + }; + } + + int BasicNativeApplication::Execute(MessageBroker& broker, + IBasicApplication& application, + int argc, + char* argv[]) + { + /****************************************************************** + * Initialize all the subcomponents of Orthanc Stone + ******************************************************************/ + + Orthanc::Logging::Initialize(); + Orthanc::Toolbox::InitializeOpenSsl(); + Orthanc::HttpClient::GlobalInitialize(); + + Initialize(); + + /****************************************************************** + * Declare and parse the command-line options of the application + ******************************************************************/ + + boost::program_options::options_description options; + DeclareCommandLineOptions(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 webServiceParameters; + + if (parameters.count("orthanc")) + { + webServiceParameters.SetUrl(parameters["orthanc"].as()); + } + + if (parameters.count("username")) + { + webServiceParameters.SetUsername(parameters["username"].as()); + } + + if (parameters.count("password")) + { + webServiceParameters.SetPassword(parameters["password"].as()); + } + + 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"; + throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol); + } + } + + + /**************************************************************** + * Initialize the application + ****************************************************************/ + + LOG(WARNING) << "Creating the widgets of the application"; + + LogStatusBar statusBar; + + BasicNativeApplicationContext context; + Oracle oracle(4); // use 4 threads to download content + OracleWebService webService(broker, oracle, webServiceParameters, context); + context.SetWebService(webService); + + application.Initialize(&context, statusBar, parameters); + + { + BasicNativeApplicationContext::GlobalMutexLocker locker(context); + context.SetCentralWidget(application.GetCentralWidget()); + context.GetCentralViewport().SetStatusBar(statusBar); + } + + std::string title = application.GetTitle(); + if (title.empty()) + { + title = "Stone of Orthanc"; + } + + /**************************************************************** + * Run the application + ****************************************************************/ + + Run(context, title, width, height, opengl); + + + /**************************************************************** + * 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 + ******************************************************************/ + + Finalize(); + Orthanc::HttpClient::GlobalFinalize(); + Orthanc::Toolbox::FinalizeOpenSsl(); + + return (success ? 0 : -1); + } + +} diff -r f21ba2468570 -r dc1beee33134 Applications/Generic/BasicNativeApplication.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Generic/BasicNativeApplication.h Fri Aug 24 13:52:55 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 "../IBasicApplication.h" + +#if ORTHANC_ENABLE_NATIVE != 1 +#error this file shall be included only with the ORTHANC_ENABLE_NATIVE set to 1 +#endif + +namespace OrthancStone +{ + class BasicNativeApplicationContext; + + class BasicNativeApplication + { + public: + + int Execute(MessageBroker& broker, + IBasicApplication& application, + int argc, + char* argv[]); + + virtual void Initialize() = 0; + virtual void DeclareCommandLineOptions(boost::program_options::options_description& options) = 0; + virtual void Run(BasicNativeApplicationContext& context, const std::string& title, unsigned int width, unsigned int height, bool enableOpenGl) = 0; + virtual void Finalize() = 0; + }; + +} diff -r f21ba2468570 -r dc1beee33134 Applications/Generic/BasicNativeApplicationContext.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Generic/BasicNativeApplicationContext.cpp Fri Aug 24 13:52:55 2018 +0200 @@ -0,0 +1,80 @@ +/** + * 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 "BasicNativeApplicationContext.h" +#include "../../Platforms/Generic/OracleWebService.h" + +namespace OrthancStone +{ + IWidget& BasicNativeApplicationContext::SetCentralWidget(IWidget* widget) // Takes ownership + { + centralViewport_->SetCentralWidget(widget); + return *widget; + } + + + void BasicNativeApplicationContext::UpdateThread(BasicNativeApplicationContext* that) + { + while (!that->stopped_) + { + { + GlobalMutexLocker locker(*that); + that->GetCentralViewport().UpdateContent(); + } + + boost::this_thread::sleep(boost::posix_time::milliseconds(that->updateDelay_)); + } + } + + + BasicNativeApplicationContext::BasicNativeApplicationContext() : // Orthanc::WebServiceParameters& orthanc, WidgetViewport* centralViewport) : + centralViewport_(new OrthancStone::WidgetViewport()), + stopped_(true), + updateDelay_(100) // By default, 100ms between each refresh of the content + { + srand(time(NULL)); + } + + + void BasicNativeApplicationContext::Start() + { + dynamic_cast(webService_)->Start(); + + if (centralViewport_->HasUpdateContent()) + { + stopped_ = false; + updateThread_ = boost::thread(UpdateThread, this); + } + } + + + void BasicNativeApplicationContext::Stop() + { + stopped_ = true; + + if (updateThread_.joinable()) + { + updateThread_.join(); + } + + dynamic_cast(webService_)->Stop(); + } +} diff -r f21ba2468570 -r dc1beee33134 Applications/Generic/BasicNativeApplicationContext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Applications/Generic/BasicNativeApplicationContext.h Fri Aug 24 13:52:55 2018 +0200 @@ -0,0 +1,72 @@ +/** + * 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 +#include +#include "../BasicApplicationContext.h" + +namespace OrthancStone +{ + class BasicNativeApplicationContext : public BasicApplicationContext + { + private: + + static void UpdateThread(BasicNativeApplicationContext* that); + + boost::mutex globalMutex_; + std::unique_ptr centralViewport_; + boost::thread updateThread_; + bool stopped_; + unsigned int updateDelay_; + + public: + class GlobalMutexLocker: public boost::noncopyable + { + boost::mutex::scoped_lock lock_; + public: + GlobalMutexLocker(BasicNativeApplicationContext& that): + lock_(that.globalMutex_) + {} + }; + + BasicNativeApplicationContext(); + + virtual ~BasicNativeApplicationContext() {} + + virtual IWidget& SetCentralWidget(IWidget* widget); // Takes ownership + IViewport& GetCentralViewport() {return *(centralViewport_.get());} + + void Start(); + + void Stop(); + + void SetUpdateDelay(unsigned int delay) // In milliseconds + { + updateDelay_ = delay; + } + }; +} diff -r f21ba2468570 -r dc1beee33134 Applications/IBasicApplication.h --- a/Applications/IBasicApplication.h Fri Aug 24 11:26:59 2018 +0200 +++ b/Applications/IBasicApplication.h Fri Aug 24 13:52:55 2018 +0200 @@ -41,7 +41,7 @@ virtual void Initialize(BasicApplicationContext* context, IStatusBar& statusBar, const boost::program_options::variables_map& parameters) = 0; -#if ORTHANC_ENABLE_SDL==0 +#if ORTHANC_ENABLE_WASM==1 virtual void InitializeWasm() {} // specific initialization when the app is running in WebAssembly. This is called after the other Initialize() #endif diff -r f21ba2468570 -r dc1beee33134 Applications/Samples/SampleApplicationBase.h --- a/Applications/Samples/SampleApplicationBase.h Fri Aug 24 11:26:59 2018 +0200 +++ b/Applications/Samples/SampleApplicationBase.h Fri Aug 24 13:52:55 2018 +0200 @@ -21,48 +21,13 @@ #pragma once -//#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" namespace OrthancStone { namespace Samples { - -//#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_; -// } -// }; - -// typedef SampleSdlApplicationBase SampleApplicationBase_; -//#else -// class SampleWasmApplicationBase : public BasicWasmApplication { -// protected: -// std::unique_ptr context_; -// public: -// virtual BasicApplicationContext& CreateApplicationContext(IWebService& orthancWebService, std::shared_ptr centralViewport) { -// context_.reset(new SampleApplicationContext(orthancWebService)); -// return *context_; -// } - -// }; - -// typedef SampleWasmApplicationBase SampleApplicationBase_; - -//#endif - class SampleApplicationBase : public IBasicApplication { public: @@ -74,7 +39,5 @@ virtual void CustomInitialize() {} }; - - } } diff -r f21ba2468570 -r dc1beee33134 Applications/Samples/SampleMainSdl.cpp --- a/Applications/Samples/SampleMainSdl.cpp Fri Aug 24 11:26:59 2018 +0200 +++ b/Applications/Samples/SampleMainSdl.cpp Fri Aug 24 13:52:55 2018 +0200 @@ -28,5 +28,6 @@ OrthancStone::MessageBroker broker; Application application(broker); - return OrthancStone::BasicSdlApplication::ExecuteWithSdl(broker, application, argc, argv); + OrthancStone::BasicSdlApplication sdlApplication; + return sdlApplication.Execute(broker, application, argc, argv); } diff -r f21ba2468570 -r dc1beee33134 Applications/Samples/SimpleViewerApplication.h --- a/Applications/Samples/SimpleViewerApplication.h Fri Aug 24 11:26:59 2018 +0200 +++ b/Applications/Samples/SimpleViewerApplication.h Fri Aug 24 13:52:55 2018 +0200 @@ -332,11 +332,11 @@ } } -#if ORTHANC_ENABLE_SDL==0 +#if ORTHANC_ENABLE_WASM==1 virtual void InitializeWasm() { AttachWidgetToWasmViewport("canvas", thumbnailsLayout_); - AttachWidgetToWasmViewport("canvas2", mainViewport_); + AttachWidgetToWasmViewport("canvas2", mainWidget_); } #endif diff -r f21ba2468570 -r dc1beee33134 Applications/Sdl/BasicSdlApplication.cpp --- a/Applications/Sdl/BasicSdlApplication.cpp Fri Aug 24 11:26:59 2018 +0200 +++ b/Applications/Sdl/BasicSdlApplication.cpp Fri Aug 24 13:52:55 2018 +0200 @@ -37,266 +37,71 @@ namespace OrthancStone { - // Anonymous namespace to avoid clashes against other compilation modules - namespace + void BasicSdlApplication::Initialize() { - class LogStatusBar : public IStatusBar - { - public: - virtual void ClearMessage() - { - } - - virtual void SetMessage(const std::string& message) - { - LOG(WARNING) << message; - } - }; + SdlWindow::GlobalInitialize(); } - - static void DeclareSdlCommandLineOptions(boost::program_options::options_description& options) + void BasicSdlApplication::DeclareCommandLineOptions(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") - ; + ("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") - ; + ("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 BasicSdlApplication::ExecuteWithSdl(MessageBroker& broker, - IBasicApplication& application, - int argc, - char* argv[]) + void BasicSdlApplication::Run(BasicNativeApplicationContext& context, const std::string& title, unsigned int width, unsigned int height, bool enableOpenGl) { - /****************************************************************** - * Initialize all the subcomponents of Orthanc Stone - ******************************************************************/ - - Orthanc::Logging::Initialize(); - Orthanc::Toolbox::InitializeOpenSsl(); - Orthanc::HttpClient::GlobalInitialize(); - SdlWindow::GlobalInitialize(); - - - /****************************************************************** - * Declare and parse the command-line options of the application - ******************************************************************/ + /************************************************************** + * Run the application inside a SDL window + **************************************************************/ - boost::program_options::options_description options; - DeclareSdlCommandLineOptions(options); - application.DeclareStartupOptions(options); - - boost::program_options::variables_map parameters; - bool error = false; + LOG(WARNING) << "Starting the application"; - 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; - } + SdlWindow window(title.c_str(), width, height, enableOpenGl); + SdlEngine sdl(window, context); - - /****************************************************************** - * 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"; + BasicNativeApplicationContext::GlobalMutexLocker locker(context); + context.GetCentralViewport().Register(sdl); // (*) } - bool success = true; - try - { - /**************************************************************** - * Initialize the connection to the Orthanc server - ****************************************************************/ + context.Start(); + sdl.Run(); - Orthanc::WebServiceParameters webServiceParameters; - - if (parameters.count("orthanc")) - { - webServiceParameters.SetUrl(parameters["orthanc"].as()); - } + LOG(WARNING) << "Stopping the application"; - if (parameters.count("username")) - { - webServiceParameters.SetUsername(parameters["username"].as()); - } - - if (parameters.count("password")) - { - webServiceParameters.SetPassword(parameters["password"].as()); - } + // 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(); + } - 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"; - throw Orthanc::OrthancException(Orthanc::ErrorCode_NetworkProtocol); - } - } + void BasicSdlApplication::Finalize() + { + SdlWindow::GlobalFinalize(); + } - /**************************************************************** - * Initialize the application - ****************************************************************/ - - LOG(WARNING) << "Creating the widgets of the application"; - - LogStatusBar statusBar; - - BasicSdlApplicationContext context; - Oracle oracle(4); // use 4 threads to download content - OracleWebService webService(broker, oracle, webServiceParameters, context); - context.SetWebService(webService); - - application.Initialize(&context, statusBar, parameters); - - { - BasicSdlApplicationContext::GlobalMutexLocker locker(context); - context.SetCentralWidget(application.GetCentralWidget()); - context.GetCentralViewport().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); - - { - BasicSdlApplicationContext::GlobalMutexLocker locker(context); - context.GetCentralViewport().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::Toolbox::FinalizeOpenSsl(); - - return (success ? 0 : -1); - } - } diff -r f21ba2468570 -r dc1beee33134 Applications/Sdl/BasicSdlApplication.h --- a/Applications/Sdl/BasicSdlApplication.h Fri Aug 24 11:26:59 2018 +0200 +++ b/Applications/Sdl/BasicSdlApplication.h Fri Aug 24 13:52:55 2018 +0200 @@ -21,7 +21,7 @@ #pragma once -#include "../IBasicApplication.h" +#include "../Generic/BasicNativeApplication.h" #if ORTHANC_ENABLE_SDL != 1 #error this file shall be included only with the ORTHANC_ENABLE_SDL set to 1 @@ -31,14 +31,13 @@ namespace OrthancStone { - class BasicSdlApplication + class BasicSdlApplication : public BasicNativeApplication { public: - - static int ExecuteWithSdl(MessageBroker& broker, - IBasicApplication& application, - int argc, - char* argv[]); + virtual void Initialize(); + virtual void DeclareCommandLineOptions(boost::program_options::options_description& options); + virtual void Run(BasicNativeApplicationContext& context, const std::string& title, unsigned int width, unsigned int height, bool enableOpenGl); + virtual void Finalize(); }; } diff -r f21ba2468570 -r dc1beee33134 Applications/Sdl/BasicSdlApplicationContext.cpp --- a/Applications/Sdl/BasicSdlApplicationContext.cpp Fri Aug 24 11:26:59 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +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 . - **/ - - -#include "BasicSdlApplicationContext.h" -#include "../../Platforms/Generic/OracleWebService.h" - -namespace OrthancStone -{ - IWidget& BasicSdlApplicationContext::SetCentralWidget(IWidget* widget) // Takes ownership - { - centralViewport_->SetCentralWidget(widget); - return *widget; - } - - - void BasicSdlApplicationContext::UpdateThread(BasicSdlApplicationContext* that) - { - while (!that->stopped_) - { - { - GlobalMutexLocker locker(*that); - that->GetCentralViewport().UpdateContent(); - } - - boost::this_thread::sleep(boost::posix_time::milliseconds(that->updateDelay_)); - } - } - - - BasicSdlApplicationContext::BasicSdlApplicationContext() : // Orthanc::WebServiceParameters& orthanc, WidgetViewport* centralViewport) : - centralViewport_(new OrthancStone::WidgetViewport()), - stopped_(true), - updateDelay_(100) // By default, 100ms between each refresh of the content - { - srand(time(NULL)); - } - - - void BasicSdlApplicationContext::Start() - { - dynamic_cast(webService_)->Start(); - - if (centralViewport_->HasUpdateContent()) - { - stopped_ = false; - updateThread_ = boost::thread(UpdateThread, this); - } - } - - - void BasicSdlApplicationContext::Stop() - { - stopped_ = true; - - if (updateThread_.joinable()) - { - updateThread_.join(); - } - - dynamic_cast(webService_)->Stop(); - } -} diff -r f21ba2468570 -r dc1beee33134 Applications/Sdl/BasicSdlApplicationContext.h --- a/Applications/Sdl/BasicSdlApplicationContext.h Fri Aug 24 11:26:59 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,92 +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 . - **/ - - -#pragma once - -#include "../../Framework/Viewport/WidgetViewport.h" -#include "../../Framework/Volumes/ISlicedVolume.h" -#include "../../Framework/Volumes/IVolumeLoader.h" - -#include -#include -#include "../BasicApplicationContext.h" - -namespace OrthancStone -{ - class BasicSdlApplicationContext : public BasicApplicationContext - { - private: - - static void UpdateThread(BasicSdlApplicationContext* that); - - boost::mutex globalMutex_; - std::unique_ptr centralViewport_; - boost::thread updateThread_; - bool stopped_; - unsigned int updateDelay_; - - public: - class GlobalMutexLocker: public boost::noncopyable - { - boost::mutex::scoped_lock lock_; - public: - GlobalMutexLocker(BasicSdlApplicationContext& that): - lock_(that.globalMutex_) - {} - }; - -// class ViewportLocker : public boost::noncopyable -// { -// private: -// boost::mutex::scoped_lock lock_; -// IViewport& viewport_; - -// public: -// ViewportLocker(BasicSdlApplicationContext& that) : -// lock_(that.viewportMutex_), -// viewport_(*(that.centralViewport_.get())) -// { -// } - -// IViewport& GetViewport() const -// { -// return viewport_; -// } -// }; - - - BasicSdlApplicationContext(); - - virtual ~BasicSdlApplicationContext() {} - - virtual IWidget& SetCentralWidget(IWidget* widget); // Takes ownership - IViewport& GetCentralViewport() {return *(centralViewport_.get());} - - void Start(); - - void Stop(); - - void SetUpdateDelay(unsigned int delay) // In milliseconds - { - updateDelay_ = delay; - } - }; -} diff -r f21ba2468570 -r dc1beee33134 Applications/Sdl/SdlEngine.cpp --- a/Applications/Sdl/SdlEngine.cpp Fri Aug 24 11:26:59 2018 +0200 +++ b/Applications/Sdl/SdlEngine.cpp Fri Aug 24 13:52:55 2018 +0200 @@ -41,7 +41,7 @@ { if (viewportChanged_) { - BasicSdlApplicationContext::GlobalMutexLocker locker(context_); + BasicNativeApplicationContext::GlobalMutexLocker locker(context_); surface_.Render(context_.GetCentralViewport()); viewportChanged_ = false; @@ -98,7 +98,7 @@ SdlEngine::SdlEngine(SdlWindow& window, - BasicSdlApplicationContext& context) : + BasicNativeApplicationContext& context) : window_(window), context_(context), surface_(window), @@ -118,7 +118,7 @@ const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount); { - BasicSdlApplicationContext::GlobalMutexLocker locker(context_); + BasicNativeApplicationContext::GlobalMutexLocker locker(context_); SetSize(window_.GetWidth(), window_.GetHeight()); context_.GetCentralViewport().SetDefaultView(); } @@ -133,7 +133,7 @@ while (!stop && SDL_PollEvent(&event)) { - BasicSdlApplicationContext::GlobalMutexLocker locker(context_); + BasicNativeApplicationContext::GlobalMutexLocker locker(context_); if (event.type == SDL_QUIT) { diff -r f21ba2468570 -r dc1beee33134 Applications/Sdl/SdlEngine.h --- a/Applications/Sdl/SdlEngine.h Fri Aug 24 11:26:59 2018 +0200 +++ b/Applications/Sdl/SdlEngine.h Fri Aug 24 13:52:55 2018 +0200 @@ -24,7 +24,7 @@ #if ORTHANC_ENABLE_SDL == 1 #include "SdlCairoSurface.h" -#include "BasicSdlApplicationContext.h" +#include "../Generic/BasicNativeApplicationContext.h" namespace OrthancStone { @@ -32,7 +32,7 @@ { private: SdlWindow& window_; - BasicSdlApplicationContext& context_; + BasicNativeApplicationContext& context_; SdlCairoSurface surface_; bool viewportChanged_; @@ -46,7 +46,7 @@ public: SdlEngine(SdlWindow& window, - BasicSdlApplicationContext& context); + BasicNativeApplicationContext& context); virtual ~SdlEngine(); diff -r f21ba2468570 -r dc1beee33134 Platforms/Generic/OracleWebService.h --- a/Platforms/Generic/OracleWebService.h Fri Aug 24 11:26:59 2018 +0200 +++ b/Platforms/Generic/OracleWebService.h Fri Aug 24 13:52:55 2018 +0200 @@ -25,7 +25,7 @@ #include "Oracle.h" #include "WebServiceGetCommand.h" #include "WebServicePostCommand.h" -#include "../../Applications/Sdl/BasicSdlApplicationContext.h" +#include "../../Applications/Generic/BasicNativeApplicationContext.h" namespace OrthancStone { @@ -33,14 +33,14 @@ { private: Oracle& oracle_; - BasicSdlApplicationContext& context_; + BasicNativeApplicationContext& context_; Orthanc::WebServiceParameters parameters_; public: OracleWebService(MessageBroker& broker, Oracle& oracle, const Orthanc::WebServiceParameters& parameters, - BasicSdlApplicationContext& context) : + BasicNativeApplicationContext& context) : IWebService(broker), oracle_(oracle), context_(context), diff -r f21ba2468570 -r dc1beee33134 Platforms/Generic/WebServiceCommandBase.cpp --- a/Platforms/Generic/WebServiceCommandBase.cpp Fri Aug 24 11:26:59 2018 +0200 +++ b/Platforms/Generic/WebServiceCommandBase.cpp Fri Aug 24 13:52:55 2018 +0200 @@ -31,7 +31,7 @@ const std::string& uri, const IWebService::Headers& headers, Orthanc::IDynamicObject* payload /* takes ownership */, - BasicSdlApplicationContext& context) : + BasicNativeApplicationContext& context) : IObservable(broker), callback_(callback), parameters_(parameters), @@ -48,7 +48,7 @@ void WebServiceCommandBase::Commit() { - BasicSdlApplicationContext::GlobalMutexLocker lock(context_); // we want to make sure that, i.e, the UpdateThread is not triggered while we are updating the "model" with the result of a WebServiceCommand + BasicNativeApplicationContext::GlobalMutexLocker lock(context_); // we want to make sure that, i.e, the UpdateThread is not triggered while we are updating the "model" with the result of a WebServiceCommand if (success_) { diff -r f21ba2468570 -r dc1beee33134 Platforms/Generic/WebServiceCommandBase.h --- a/Platforms/Generic/WebServiceCommandBase.h Fri Aug 24 11:26:59 2018 +0200 +++ b/Platforms/Generic/WebServiceCommandBase.h Fri Aug 24 13:52:55 2018 +0200 @@ -25,7 +25,7 @@ #include "../../Framework/Toolbox/IWebService.h" #include "../../Framework/Messages/IObservable.h" -#include "../../Applications/Sdl/BasicSdlApplicationContext.h" +#include "../../Applications/Generic/BasicNativeApplicationContext.h" #include @@ -43,7 +43,7 @@ std::auto_ptr payload_; bool success_; std::string answer_; - BasicSdlApplicationContext& context_; + BasicNativeApplicationContext& context_; public: WebServiceCommandBase(MessageBroker& broker, @@ -52,7 +52,7 @@ const std::string& uri, const std::map& headers, Orthanc::IDynamicObject* payload /* takes ownership */, - BasicSdlApplicationContext& context); + BasicNativeApplicationContext& context); virtual void Execute() = 0; diff -r f21ba2468570 -r dc1beee33134 Platforms/Generic/WebServiceGetCommand.cpp --- a/Platforms/Generic/WebServiceGetCommand.cpp Fri Aug 24 11:26:59 2018 +0200 +++ b/Platforms/Generic/WebServiceGetCommand.cpp Fri Aug 24 13:52:55 2018 +0200 @@ -31,7 +31,7 @@ const std::string& uri, const IWebService::Headers& headers, Orthanc::IDynamicObject* payload /* takes ownership */, - BasicSdlApplicationContext& context) : + BasicNativeApplicationContext& context) : WebServiceCommandBase(broker, callback, parameters, uri, headers, payload, context) { } diff -r f21ba2468570 -r dc1beee33134 Platforms/Generic/WebServiceGetCommand.h --- a/Platforms/Generic/WebServiceGetCommand.h Fri Aug 24 11:26:59 2018 +0200 +++ b/Platforms/Generic/WebServiceGetCommand.h Fri Aug 24 13:52:55 2018 +0200 @@ -34,7 +34,7 @@ const std::string& uri, const IWebService::Headers& headers, Orthanc::IDynamicObject* payload /* takes ownership */, - BasicSdlApplicationContext& context); + BasicNativeApplicationContext& context); virtual void Execute(); }; diff -r f21ba2468570 -r dc1beee33134 Platforms/Generic/WebServicePostCommand.cpp --- a/Platforms/Generic/WebServicePostCommand.cpp Fri Aug 24 11:26:59 2018 +0200 +++ b/Platforms/Generic/WebServicePostCommand.cpp Fri Aug 24 13:52:55 2018 +0200 @@ -32,7 +32,7 @@ const IWebService::Headers& headers, const std::string& body, Orthanc::IDynamicObject* payload /* takes ownership */, - BasicSdlApplicationContext& context) : + BasicNativeApplicationContext& context) : WebServiceCommandBase(broker, callback, parameters, uri, headers, payload, context), body_(body) { diff -r f21ba2468570 -r dc1beee33134 Platforms/Generic/WebServicePostCommand.h --- a/Platforms/Generic/WebServicePostCommand.h Fri Aug 24 11:26:59 2018 +0200 +++ b/Platforms/Generic/WebServicePostCommand.h Fri Aug 24 13:52:55 2018 +0200 @@ -38,7 +38,7 @@ const IWebService::Headers& headers, const std::string& body, Orthanc::IDynamicObject* payload /* takes ownership */, - BasicSdlApplicationContext& context); + BasicNativeApplicationContext& context); virtual void Execute(); }; diff -r f21ba2468570 -r dc1beee33134 Platforms/Wasm/CMakeLists.txt --- a/Platforms/Wasm/CMakeLists.txt Fri Aug 24 11:26:59 2018 +0200 +++ b/Platforms/Wasm/CMakeLists.txt Fri Aug 24 13:52:55 2018 +0200 @@ -31,7 +31,9 @@ include(../../Resources/CMake/OrthancStoneParameters.cmake) SET(ORTHANC_SANDBOXED ON) +SET(ENABLE_QT OFF) SET(ENABLE_SDL OFF) +add_definitions(-DORTHANC_ENABLE_WASM=1) include(../../Resources/CMake/OrthancStoneConfiguration.cmake) diff -r f21ba2468570 -r dc1beee33134 Resources/CMake/OrthancStoneConfiguration.cmake --- a/Resources/CMake/OrthancStoneConfiguration.cmake Fri Aug 24 11:26:59 2018 +0200 +++ b/Resources/CMake/OrthancStoneConfiguration.cmake Fri Aug 24 13:52:55 2018 +0200 @@ -39,6 +39,10 @@ message(FATAL_ERROR "Cannot enable SDL in sandboxed environments") endif() + if (ENABLE_QT) + message(FATAL_ERROR "Cannot enable QT in sandboxed environments") + endif() + if (ENABLE_SSL) message(FATAL_ERROR "Cannot enable SSL in sandboxed environments") endif() @@ -69,12 +73,21 @@ endif() -if (ENABLE_SDL) +if (ENABLE_SDL AND ENABLE_QT) + message("SDL and QT may not be defined together") +elseif(ENABLE_SDL) include(${CMAKE_CURRENT_LIST_DIR}/SdlConfiguration.cmake) + add_definitions(-DORTHANC_ENABLE_NATIVE=1) add_definitions(-DORTHANC_ENABLE_SDL=1) +elseif(ENABLE_QT) + include(${CMAKE_CURRENT_LIST_DIR}/QtConfiguration.cmake) + add_definitions(-DORTHANC_ENABLE_NATIVE=1) + add_definitions(-DORTHANC_ENABLE_QT=1) else() unset(USE_SYSTEM_SDL CACHE) add_definitions(-DORTHANC_ENABLE_SDL=0) + add_definitions(-DORTHANC_ENABLE_QT=0) + add_definitions(-DORTHANC_ENABLE_NATIVE=0) endif() @@ -157,14 +170,21 @@ ${ORTHANC_STONE_ROOT}/Platforms/Generic/OracleWebService.h ) - list(APPEND APPLICATIONS_SOURCES - ${ORTHANC_STONE_ROOT}/Applications/Sdl/BasicSdlApplication.cpp - ${ORTHANC_STONE_ROOT}/Applications/Sdl/BasicSdlApplicationContext.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 - ) + if (ENABLE_SDL OR ENABLE_QT) + list(APPEND APPLICATIONS_SOURCES + ${ORTHANC_STONE_ROOT}/Applications/Generic/BasicNativeApplication.cpp + ${ORTHANC_STONE_ROOT}/Applications/Generic/BasicNativeApplicationContext.cpp + ) + if (ENABLE_SDL) + list(APPEND APPLICATIONS_SOURCES + ${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 + ) + endif() + endif() else() list(APPEND APPLICATIONS_SOURCES ${ORTHANC_STONE_ROOT}/Applications/Wasm/StartupParametersBuilder.cpp diff -r f21ba2468570 -r dc1beee33134 Resources/CMake/OrthancStoneParameters.cmake --- a/Resources/CMake/OrthancStoneParameters.cmake Fri Aug 24 11:26:59 2018 +0200 +++ b/Resources/CMake/OrthancStoneParameters.cmake Fri Aug 24 13:52:55 2018 +0200 @@ -50,3 +50,4 @@ ##################################################################### set(ENABLE_SDL ON CACHE INTERNAL "Include support for SDL") +set(ENABLE_QT OFF CACHE INTERNAL "Include support for Qt") diff -r f21ba2468570 -r dc1beee33134 Resources/CMake/QtConfiguration.cmake