# HG changeset patch # User Alain Mazy # Date 1564760324 -7200 # Node ID acc172f2b7820ac77a68d4972dce95eebc234d91 # Parent 861c080ef47b76658021a1f7da340cb64dd674e7# Parent ab90628e70d910a646635715d7095e9376a5ccab merge diff -r 861c080ef47b -r acc172f2b782 .hgtags --- a/.hgtags Fri Aug 02 17:38:31 2019 +0200 +++ b/.hgtags Fri Aug 02 17:38:44 2019 +0200 @@ -5,3 +5,7 @@ fe96057e97b94eb8a46c1a33ba350c354b5c4afc toa2019062502 60a403f01c3112249f9d4a1a6149bef1de9766bf toa2019062503 81d30cd93b6586c2d190283eb23622822db0666d toa2019072201 +e594e76e0a81d6342e7e18b67e9ac2fe62a6ce62 toa2019072202 +fc38c4ab17e31b3ccc20c8d8bc557ae8ad4c3b0e toa2019072401 +401808e7ff2e0f8cb889f9fa90baaddad1c97e57 toa2019072901 +eaaa9b574e054feed6f0e71302b14b068cfe338a toa2019073101 diff -r 861c080ef47b -r acc172f2b782 Applications/Generic/GuiAdapter.cpp --- a/Applications/Generic/GuiAdapter.cpp Fri Aug 02 17:38:31 2019 +0200 +++ b/Applications/Generic/GuiAdapter.cpp Fri Aug 02 17:38:44 2019 +0200 @@ -51,7 +51,7 @@ } #if ORTHANC_ENABLE_WASM == 1 - void GuiAdapter::Run() + void GuiAdapter::Run(GuiAdapterRunFunc /*func*/, void* /*cookie*/) { } @@ -723,7 +723,7 @@ # endif // SDL ONLY - void GuiAdapter::Run() + void GuiAdapter::Run(GuiAdapterRunFunc func, void* cookie) { #if 1 // TODO: MAKE THIS DYNAMIC !!! See SdlOpenGLViewport vs Cairo in ViewportWrapper @@ -741,6 +741,8 @@ { { LockingEmitter::WriterLock lock(lockingEmitter_); + if(func != NULL) + (*func)(cookie); OnAnimationFrame(); // in SDL we must call it } diff -r 861c080ef47b -r acc172f2b782 Applications/Generic/GuiAdapter.h --- a/Applications/Generic/GuiAdapter.h Fri Aug 02 17:38:31 2019 +0200 +++ b/Applications/Generic/GuiAdapter.h Fri Aug 02 17:38:44 2019 +0200 @@ -218,6 +218,8 @@ #endif + typedef void (*GuiAdapterRunFunc)(void*); + class GuiAdapter { public: @@ -276,7 +278,7 @@ Under wasm, it returns without doing anything, since the event loop is managed by the browser. */ - void Run(); + void Run(GuiAdapterRunFunc func = NULL, void* cookie = NULL); #if ORTHANC_ENABLE_WASM != 1 /** @@ -364,7 +366,12 @@ for (size_t i = 0; i < widgets_.size(); i++) { boost::shared_ptr widget = widgets_[i].lock(); - func(widget); + + // TODO: we need to clean widgets! + if (widget.get() != NULL) + { + func(widget); + } } } }; diff -r 861c080ef47b -r acc172f2b782 Framework/Loaders/DicomStructureSetLoader.cpp --- a/Framework/Loaders/DicomStructureSetLoader.cpp Fri Aug 02 17:38:31 2019 +0200 +++ b/Framework/Loaders/DicomStructureSetLoader.cpp Fri Aug 02 17:38:44 2019 +0200 @@ -58,6 +58,7 @@ // All the referenced instances have been loaded, finalize the RT-STRUCT loader.content_->CheckReferencedSlices(); loader.revision_++; + loader.SetStructuresReady(); } } }; @@ -225,14 +226,21 @@ DicomStructureSetLoader::DicomStructureSetLoader(IOracle& oracle, IObservable& oracleObservable) : + IObservable(oracleObservable.GetBroker()), LoaderStateMachine(oracle, oracleObservable), revision_(0), countProcessedInstances_(0), - countReferencedInstances_(0) + countReferencedInstances_(0), + structuresReady_(false) { } + DicomStructureSetLoader::~DicomStructureSetLoader() + { + LOG(TRACE) << "DicomStructureSetLoader::~DicomStructureSetLoader()"; + } + void DicomStructureSetLoader::LoadInstance(const std::string& instanceId) { Start(); @@ -261,4 +269,17 @@ return new Slice(*content_, revision_, cuttingPlane); } } + + void DicomStructureSetLoader::SetStructuresReady() + { + ORTHANC_ASSERT(!structuresReady_); + structuresReady_ = true; + BroadcastMessage(DicomStructureSetLoader::StructuresReady(*this)); + } + + bool DicomStructureSetLoader::AreStructuresReady() const + { + return structuresReady_; + } + } diff -r 861c080ef47b -r acc172f2b782 Framework/Loaders/DicomStructureSetLoader.h --- a/Framework/Loaders/DicomStructureSetLoader.h Fri Aug 02 17:38:31 2019 +0200 +++ b/Framework/Loaders/DicomStructureSetLoader.h Fri Aug 02 17:38:44 2019 +0200 @@ -29,7 +29,8 @@ { class DicomStructureSetLoader : public LoaderStateMachine, - public IVolumeSlicer + public IVolumeSlicer, + public IObservable { private: class Slice; @@ -44,13 +45,24 @@ std::string instanceId_; unsigned int countProcessedInstances_; unsigned int countReferencedInstances_; + + // will be set to true once the loading is finished + bool structuresReady_; public: + ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, StructuresReady, DicomStructureSetLoader); + DicomStructureSetLoader(IOracle& oracle, IObservable& oracleObservable); + ~DicomStructureSetLoader(); + void LoadInstance(const std::string& instanceId); virtual IExtractedSlice* ExtractSlice(const CoordinateSystem3D& cuttingPlane); + + void SetStructuresReady(); + + bool AreStructuresReady() const; }; } diff -r 861c080ef47b -r acc172f2b782 Framework/Loaders/LoaderCache.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Loaders/LoaderCache.cpp Fri Aug 02 17:38:44 2019 +0200 @@ -0,0 +1,249 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 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 "LoaderCache.h" + +#include "OrthancSeriesVolumeProgressiveLoader.h" +#include "OrthancMultiframeVolumeLoader.h" +#include "DicomStructureSetLoader.h" + +#if ORTHANC_ENABLE_WASM == 1 +# include +# include "../Oracle/WebAssemblyOracle.h" +#else +# include "../Oracle/ThreadedOracle.h" +#endif + +#include "../Messages/LockingEmitter.h" +#include "../Volumes/DicomVolumeImage.h" +#include "../Volumes/DicomVolumeImageMPRSlicer.h" + +#include +#include + +namespace OrthancStone +{ +#if ORTHANC_ENABLE_WASM == 1 + LoaderCache::LoaderCache(WebAssemblyOracle& oracle) + : oracle_(oracle) + { + + } +#else + LoaderCache::LoaderCache(ThreadedOracle& oracle, LockingEmitter& lockingEmitter) + : oracle_(oracle) + , lockingEmitter_(lockingEmitter) + { + } +#endif + + boost::shared_ptr + LoaderCache::GetSeriesVolumeProgressiveLoader(std::string seriesUuid) + { + try + { + + // normalize keys a little + seriesUuid = Orthanc::Toolbox::StripSpaces(seriesUuid); + Orthanc::Toolbox::ToLowerCase(seriesUuid); + + // find in cache + if (seriesVolumeProgressiveLoaders_.find(seriesUuid) == seriesVolumeProgressiveLoaders_.end()) + { +// LOG(TRACE) << "LoaderCache::GetSeriesVolumeProgressiveLoader : CACHEMISS --> need to load seriesUUid = " << seriesUuid; +#if ORTHANC_ENABLE_WASM == 1 +// LOG(TRACE) << "Performing request for series " << seriesUuid << " sbrk(0) = " << sbrk(0); +#else +// LOG(TRACE) << "Performing request for series " << seriesUuid; +#endif + boost::shared_ptr volumeImage(new DicomVolumeImage); + boost::shared_ptr loader; +// LOG(TRACE) << "volumeImage = " << volumeImage.get(); + { +#if ORTHANC_ENABLE_WASM == 1 + loader.reset(new OrthancSeriesVolumeProgressiveLoader(volumeImage, oracle_, oracle_)); +#else + LockingEmitter::WriterLock lock(lockingEmitter_); + loader.reset(new OrthancSeriesVolumeProgressiveLoader(volumeImage, oracle_, lock.GetOracleObservable())); +#endif +// LOG(TRACE) << "LoaderCache::GetSeriesVolumeProgressiveLoader : loader = " << loader.get(); + loader->LoadSeries(seriesUuid); +// LOG(TRACE) << "LoaderCache::GetSeriesVolumeProgressiveLoader : loader->LoadSeries successful"; + } + seriesVolumeProgressiveLoaders_[seriesUuid] = loader; + } + else + { +// LOG(TRACE) << "LoaderCache::GetSeriesVolumeProgressiveLoader : returning cached loader for seriesUUid = " << seriesUuid; + } + return seriesVolumeProgressiveLoaders_[seriesUuid]; + } + catch (const Orthanc::OrthancException& e) + { + if (e.HasDetails()) + { + LOG(ERROR) << "OrthancException in LoaderCache: " << e.What() << " Details: " << e.GetDetails(); + } + else + { + LOG(ERROR) << "OrthancException in LoaderCache: " << e.What(); + } + throw; + } + catch (const std::exception& e) + { + LOG(ERROR) << "std::exception in LoaderCache: " << e.what(); + throw; + } + catch (...) + { + LOG(ERROR) << "Unknown exception in LoaderCache"; + throw; + } + } + + boost::shared_ptr LoaderCache::GetMultiframeVolumeLoader(std::string instanceUuid) + { + // if the loader is not available, let's trigger its creation + if(multiframeVolumeLoaders_.find(instanceUuid) == multiframeVolumeLoaders_.end()) + { + GetMultiframeDicomVolumeImageMPRSlicer(instanceUuid); + } + ORTHANC_ASSERT(multiframeVolumeLoaders_.find(instanceUuid) != multiframeVolumeLoaders_.end()); + + return multiframeVolumeLoaders_[instanceUuid]; + } + + boost::shared_ptr LoaderCache::GetMultiframeDicomVolumeImageMPRSlicer(std::string instanceUuid) + { + try + { + // normalize keys a little + instanceUuid = Orthanc::Toolbox::StripSpaces(instanceUuid); + Orthanc::Toolbox::ToLowerCase(instanceUuid); + + // find in cache + if (dicomVolumeImageMPRSlicers_.find(instanceUuid) == dicomVolumeImageMPRSlicers_.end()) + { + boost::shared_ptr volumeImage(new DicomVolumeImage); + boost::shared_ptr loader; + + { +#if ORTHANC_ENABLE_WASM == 1 + loader.reset(new OrthancMultiframeVolumeLoader(volumeImage, oracle_, oracle_)); +#else + LockingEmitter::WriterLock lock(lockingEmitter_); + loader.reset(new OrthancMultiframeVolumeLoader(volumeImage, oracle_, lock.GetOracleObservable())); +#endif + loader->LoadInstance(instanceUuid); + } + multiframeVolumeLoaders_[instanceUuid] = loader; + boost::shared_ptr mprSlicer(new DicomVolumeImageMPRSlicer(volumeImage)); + dicomVolumeImageMPRSlicers_[instanceUuid] = mprSlicer; + } + return dicomVolumeImageMPRSlicers_[instanceUuid]; + } + catch (const Orthanc::OrthancException& e) + { + if (e.HasDetails()) + { + LOG(ERROR) << "OrthancException in LoaderCache: " << e.What() << " Details: " << e.GetDetails(); + } + else + { + LOG(ERROR) << "OrthancException in LoaderCache: " << e.What(); + } + throw; + } + catch (const std::exception& e) + { + LOG(ERROR) << "std::exception in LoaderCache: " << e.what(); + throw; + } + catch (...) + { + LOG(ERROR) << "Unknown exception in LoaderCache"; + throw; + } + } + + boost::shared_ptr LoaderCache::GetDicomStructureSetLoader(std::string instanceUuid) + { + try + { + // normalize keys a little + instanceUuid = Orthanc::Toolbox::StripSpaces(instanceUuid); + Orthanc::Toolbox::ToLowerCase(instanceUuid); + + // find in cache + if (dicomStructureSetLoaders_.find(instanceUuid) == dicomStructureSetLoaders_.end()) + { + boost::shared_ptr loader; + + { +#if ORTHANC_ENABLE_WASM == 1 + loader.reset(new DicomStructureSetLoader(oracle_, oracle_)); +#else + LockingEmitter::WriterLock lock(lockingEmitter_); + loader.reset(new DicomStructureSetLoader(oracle_, lock.GetOracleObservable())); +#endif + loader->LoadInstance(instanceUuid); + } + dicomStructureSetLoaders_[instanceUuid] = loader; + } + return dicomStructureSetLoaders_[instanceUuid]; + } + catch (const Orthanc::OrthancException& e) + { + if (e.HasDetails()) + { + LOG(ERROR) << "OrthancException in LoaderCache: " << e.What() << " Details: " << e.GetDetails(); + } + else + { + LOG(ERROR) << "OrthancException in LoaderCache: " << e.What(); + } + throw; + } + catch (const std::exception& e) + { + LOG(ERROR) << "std::exception in LoaderCache: " << e.what(); + throw; + } + catch (...) + { + LOG(ERROR) << "Unknown exception in LoaderCache"; + throw; + } + } + + + void LoaderCache::ClearCache() + { +#if ORTHANC_ENABLE_WASM != 1 + LockingEmitter::WriterLock lock(lockingEmitter_); +#endif + seriesVolumeProgressiveLoaders_.clear(); + multiframeVolumeLoaders_.clear(); + dicomVolumeImageMPRSlicers_.clear(); + dicomStructureSetLoaders_.clear(); + } + +} diff -r 861c080ef47b -r acc172f2b782 Framework/Loaders/LoaderCache.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Framework/Loaders/LoaderCache.h Fri Aug 02 17:38:44 2019 +0200 @@ -0,0 +1,84 @@ +/** + * Stone of Orthanc + * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * Copyright (C) 2017-2019 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 + +#include +#include + +namespace OrthancStone +{ + class OrthancSeriesVolumeProgressiveLoader; + class DicomVolumeImageMPRSlicer; + class DicomStructureSetLoader; + class OrthancMultiframeVolumeLoader; + +#if ORTHANC_ENABLE_WASM == 1 + class WebAssemblyOracle; +#else + class ThreadedOracle; + class LockingEmitter; +#endif + + class LoaderCache + { + public: +#if ORTHANC_ENABLE_WASM == 1 + LoaderCache(WebAssemblyOracle& oracle); +#else + LoaderCache(ThreadedOracle& oracle, LockingEmitter& lockingEmitter); +#endif + + boost::shared_ptr + GetSeriesVolumeProgressiveLoader (std::string seriesUuid); + + boost::shared_ptr + GetMultiframeDicomVolumeImageMPRSlicer(std::string instanceUuid); + + boost::shared_ptr + GetMultiframeVolumeLoader(std::string instanceUuid); + + boost::shared_ptr + GetDicomStructureSetLoader (std::string instanceUuid); + + void ClearCache(); + + private: + +#if ORTHANC_ENABLE_WASM == 1 + WebAssemblyOracle& oracle_; +#else + ThreadedOracle& oracle_; + LockingEmitter& lockingEmitter_; +#endif + + std::map > + seriesVolumeProgressiveLoaders_; + std::map > + multiframeVolumeLoaders_; + std::map > + dicomVolumeImageMPRSlicers_; + std::map > + dicomStructureSetLoaders_; + }; +} + diff -r 861c080ef47b -r acc172f2b782 Framework/Loaders/OrthancMultiframeVolumeLoader.cpp --- a/Framework/Loaders/OrthancMultiframeVolumeLoader.cpp Fri Aug 02 17:38:31 2019 +0200 +++ b/Framework/Loaders/OrthancMultiframeVolumeLoader.cpp Fri Aug 02 17:38:44 2019 +0200 @@ -127,8 +127,7 @@ GetLoader().SetTransferSyntax(message.GetAnswer()); } }; - - + class OrthancMultiframeVolumeLoader::LoadUncompressedPixelData : public State { public: @@ -142,8 +141,7 @@ GetLoader().SetUncompressedPixelData(message.GetAnswer()); } }; - - + const std::string& OrthancMultiframeVolumeLoader::GetInstanceId() const { if (IsActive()) @@ -156,7 +154,6 @@ } } - void OrthancMultiframeVolumeLoader::ScheduleFrameDownloads() { if (transferSyntaxUid_.empty() || @@ -243,13 +240,18 @@ ORTHANC_FORCE_INLINE - static void CopyPixel(uint32_t& target, - const void* source) + static void CopyPixel(uint32_t& target, const void* source) { // TODO - check alignement? target = le32toh(*reinterpret_cast(source)); } - + + ORTHANC_FORCE_INLINE + static void CopyPixel(uint16_t& target, const void* source) + { + // TODO - check alignement? + target = le16toh(*reinterpret_cast(source)); + } template void OrthancMultiframeVolumeLoader::CopyPixelData(const std::string& pixelData) @@ -305,13 +307,16 @@ case Orthanc::PixelFormat_Grayscale32: CopyPixelData(pixelData); break; - + case Orthanc::PixelFormat_Grayscale16: + CopyPixelData(pixelData); + break; default: throw Orthanc::OrthancException(Orthanc::ErrorCode_NotImplemented); } volume_->IncrementRevision(); + pixelDataLoaded_ = true; BroadcastMessage(DicomVolumeImage::ContentUpdatedMessage(*volume_)); } @@ -321,7 +326,8 @@ IObservable& oracleObservable) : LoaderStateMachine(oracle, oracleObservable), IObservable(oracleObservable.GetBroker()), - volume_(volume) + volume_(volume), + pixelDataLoaded_(false) { if (volume.get() == NULL) { @@ -329,6 +335,10 @@ } } + OrthancMultiframeVolumeLoader::~OrthancMultiframeVolumeLoader() + { + LOG(TRACE) << "OrthancMultiframeVolumeLoader::~OrthancMultiframeVolumeLoader()"; + } void OrthancMultiframeVolumeLoader::LoadInstance(const std::string& instanceId) { diff -r 861c080ef47b -r acc172f2b782 Framework/Loaders/OrthancMultiframeVolumeLoader.h --- a/Framework/Loaders/OrthancMultiframeVolumeLoader.h Fri Aug 02 17:38:31 2019 +0200 +++ b/Framework/Loaders/OrthancMultiframeVolumeLoader.h Fri Aug 02 17:38:44 2019 +0200 @@ -41,6 +41,7 @@ boost::shared_ptr volume_; std::string instanceId_; std::string transferSyntaxUid_; + bool pixelDataLoaded_; const std::string& GetInstanceId() const; @@ -59,6 +60,13 @@ OrthancMultiframeVolumeLoader(boost::shared_ptr volume, IOracle& oracle, IObservable& oracleObservable); + + virtual ~OrthancMultiframeVolumeLoader(); + + bool IsPixelDataLoaded() const + { + return pixelDataLoaded_; + } void LoadInstance(const std::string& instanceId); }; diff -r 861c080ef47b -r acc172f2b782 Framework/Loaders/OrthancSeriesVolumeProgressiveLoader.cpp --- a/Framework/Loaders/OrthancSeriesVolumeProgressiveLoader.cpp Fri Aug 02 17:38:31 2019 +0200 +++ b/Framework/Loaders/OrthancSeriesVolumeProgressiveLoader.cpp Fri Aug 02 17:38:44 2019 +0200 @@ -264,10 +264,14 @@ if (quality == BEST_QUALITY) { std::auto_ptr tmp(new GetOrthancImageCommand); - // TODO: review the following comment. Commented out by bgo on 2019-07-19 - // reason: Alain has seen cases where gzipping the uint16 image took 11 sec - // to produce 5mb. The unzipped request was much much faster. - //tmp->SetHttpHeader("Accept-Encoding", "gzip"); + // TODO: review the following comment. + // - Commented out by bgo on 2019-07-19 | reason: Alain has seen cases + // where gzipping the uint16 image took 11 sec to produce 5mb. + // The unzipped request was much much faster. + // - Re-enabled on 2019-07-30. Reason: in Web Assembly, the browser + // does not use the Accept-Encoding header and always requests + // compression. Furthermore, NOT + tmp->SetHttpHeader("Accept-Encoding", "gzip"); tmp->SetHttpHeader("Accept", std::string(Orthanc::EnumerationToString(Orthanc::MimeType_Pam))); tmp->SetInstanceUri(instance, slice.GetExpectedPixelFormat()); tmp->SetExpectedPixelFormat(slice.GetExpectedPixelFormat()); @@ -288,6 +292,12 @@ command->SetPayload(new Orthanc::SingleValueObject(sliceIndex)); oracle_.Schedule(*this, command.release()); } + else + { + // loading is finished! + volumeImageReadyInHighQuality_ = true; + BroadcastMessage(OrthancSeriesVolumeProgressiveLoader::VolumeImageReadyInHighQuality(*this)); + } } /** @@ -415,7 +425,8 @@ active_(false), simultaneousDownloads_(4), volume_(volume), - sorter_(new BasicFetchingItemsSorter::Factory) + sorter_(new BasicFetchingItemsSorter::Factory), + volumeImageReadyInHighQuality_(false) { oracleObservable.RegisterObserverCallback( new Callable @@ -430,6 +441,10 @@ (*this, &OrthancSeriesVolumeProgressiveLoader::LoadJpegSliceContent)); } + OrthancSeriesVolumeProgressiveLoader::~OrthancSeriesVolumeProgressiveLoader() + { + LOG(TRACE) << "OrthancSeriesVolumeProgressiveLoader::~OrthancSeriesVolumeProgressiveLoader()"; + } void OrthancSeriesVolumeProgressiveLoader::SetSimultaneousDownloads(unsigned int count) { @@ -450,8 +465,10 @@ void OrthancSeriesVolumeProgressiveLoader::LoadSeries(const std::string& seriesId) { +// LOG(TRACE) << "OrthancSeriesVolumeProgressiveLoader::LoadSeries seriesId=" << seriesId; if (active_) { +// LOG(TRACE) << "OrthancSeriesVolumeProgressiveLoader::LoadSeries NOT ACTIVE! --> ERROR"; throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls); } else @@ -461,7 +478,9 @@ std::auto_ptr command(new OrthancRestApiCommand); command->SetUri("/series/" + seriesId + "/instances-tags"); +// LOG(TRACE) << "OrthancSeriesVolumeProgressiveLoader::LoadSeries about to call oracle_.Schedule"; oracle_.Schedule(*this, command.release()); +// LOG(TRACE) << "OrthancSeriesVolumeProgressiveLoader::LoadSeries called oracle_.Schedule"; } } diff -r 861c080ef47b -r acc172f2b782 Framework/Loaders/OrthancSeriesVolumeProgressiveLoader.h --- a/Framework/Loaders/OrthancSeriesVolumeProgressiveLoader.h Fri Aug 02 17:38:31 2019 +0200 +++ b/Framework/Loaders/OrthancSeriesVolumeProgressiveLoader.h Fri Aug 02 17:38:44 2019 +0200 @@ -104,23 +104,34 @@ void LoadJpegSliceContent(const GetOrthancWebViewerJpegCommand::SuccessMessage& message); - IOracle& oracle_; - bool active_; - unsigned int simultaneousDownloads_; - SeriesGeometry seriesGeometry_; - boost::shared_ptr volume_; - std::auto_ptr sorter_; - std::auto_ptr strategy_; - std::vector slicesQuality_; + IOracle& oracle_; + bool active_; + unsigned int simultaneousDownloads_; + SeriesGeometry seriesGeometry_; + boost::shared_ptr volume_; + std::auto_ptr sorter_; + std::auto_ptr strategy_; + std::vector slicesQuality_; + bool volumeImageReadyInHighQuality_; public: + ORTHANC_STONE_DEFINE_ORIGIN_MESSAGE(__FILE__, __LINE__, VolumeImageReadyInHighQuality, OrthancSeriesVolumeProgressiveLoader); + + OrthancSeriesVolumeProgressiveLoader(const boost::shared_ptr& volume, IOracle& oracle, IObservable& oracleObservable); + virtual ~OrthancSeriesVolumeProgressiveLoader(); + void SetSimultaneousDownloads(unsigned int count); + bool IsVolumeImageReadyInHighQuality() const + { + return volumeImageReadyInHighQuality_; + } + void LoadSeries(const std::string& seriesId); /** diff -r 861c080ef47b -r acc172f2b782 Framework/Oracle/WebAssemblyOracle.cpp --- a/Framework/Oracle/WebAssemblyOracle.cpp Fri Aug 02 17:38:31 2019 +0200 +++ b/Framework/Oracle/WebAssemblyOracle.cpp Fri Aug 02 17:38:44 2019 +0200 @@ -153,6 +153,10 @@ **/ std::auto_ptr context(reinterpret_cast(fetch->userData)); + if (fetch->userData == NULL) + { + LOG(ERROR) << "WebAssemblyOracle::FetchContext::SuccessCallback fetch->userData is NULL!!!!!!!"; + } std::string answer; if (fetch->numBytes > 0) @@ -170,12 +174,14 @@ **/ HttpHeaders headers; - if (!context->GetExpectedContentType().empty()) + if (fetch->userData != NULL) { - headers["Content-Type"] = context->GetExpectedContentType(); + if (!context->GetExpectedContentType().empty()) + { + headers["Content-Type"] = context->GetExpectedContentType(); + } } - emscripten_fetch_close(fetch); @@ -394,22 +400,53 @@ void WebAssemblyOracle::Execute(const IObserver& receiver, OrthancRestApiCommand* command) { - FetchCommand fetch(*this, receiver, command); + try + { + //LOG(TRACE) << "*********** WebAssemblyOracle::Execute."; + //LOG(TRACE) << "WebAssemblyOracle::Execute | command = " << command; + FetchCommand fetch(*this, receiver, command); + + fetch.SetMethod(command->GetMethod()); + fetch.SetUri(command->GetUri()); + fetch.SetHttpHeaders(command->GetHttpHeaders()); + fetch.SetTimeout(command->GetTimeout()); + + if (command->GetMethod() == Orthanc::HttpMethod_Post || + command->GetMethod() == Orthanc::HttpMethod_Put) + { + std::string body; + command->SwapBody(body); + fetch.SetBody(body); + } - fetch.SetMethod(command->GetMethod()); - fetch.SetUri(command->GetUri()); - fetch.SetHttpHeaders(command->GetHttpHeaders()); - fetch.SetTimeout(command->GetTimeout()); - - if (command->GetMethod() == Orthanc::HttpMethod_Post || - command->GetMethod() == Orthanc::HttpMethod_Put) + fetch.Execute(); + //LOG(TRACE) << "*********** successful end of WebAssemblyOracle::Execute."; + } + catch (const Orthanc::OrthancException& e) { - std::string body; - command->SwapBody(body); - fetch.SetBody(body); + if (e.HasDetails()) + { + LOG(ERROR) << "OrthancException in WebAssemblyOracle::Execute: " << e.What() << " Details: " << e.GetDetails(); + } + else + { + LOG(ERROR) << "OrthancException in WebAssemblyOracle::Execute: " << e.What(); + } + //LOG(TRACE) << "*********** failing end of WebAssemblyOracle::Execute."; + throw; } - - fetch.Execute(); + catch (const std::exception& e) + { + LOG(ERROR) << "std::exception in WebAssemblyOracle::Execute: " << e.what(); +// LOG(TRACE) << "*********** failing end of WebAssemblyOracle::Execute."; + throw; + } + catch (...) + { + LOG(ERROR) << "Unknown exception in WebAssemblyOracle::Execute"; +// LOG(TRACE) << "*********** failing end of WebAssemblyOracle::Execute."; + throw; + } } @@ -453,14 +490,36 @@ switch (command->GetType()) { case IOracleCommand::Type_OrthancRestApi: + //// DIAGNOSTIC. PLEASE REMOVE IF IT HAS BEEN COMMITTED BY MISTAKE + //{ + // const IObserver* pReceiver = &receiver; + // LOG(TRACE) << "WebAssemblyOracle::Schedule | pReceiver is " << pReceiver; + // LOG(TRACE) << "WebAssemblyOracle::Schedule | command = " << command; + // OrthancRestApiCommand* rac = dynamic_cast(protection.get()); + // LOG(TRACE) << "WebAssemblyOracle::Schedule | typed command = " << rac; + // LOG(TRACE) << "WebAssemblyOracle::Schedule" << rac->GetUri(); + //} + //// END OF BLOCK TO REMOVE Execute(receiver, dynamic_cast(protection.release())); break; case IOracleCommand::Type_GetOrthancImage: + //// DIAGNOSTIC. PLEASE REMOVE IF IT HAS BEEN COMMITTED BY MISTAKE + //{ + // GetOrthancImageCommand* rac = dynamic_cast(protection.get()); + // LOG(TRACE) << "WebAssemblyOracle::Schedule" << rac->GetUri(); + //} + //// END OF BLOCK TO REMOVE Execute(receiver, dynamic_cast(protection.release())); break; case IOracleCommand::Type_GetOrthancWebViewerJpeg: + //// DIAGNOSTIC. PLEASE REMOVE IF IT HAS BEEN COMMITTED BY MISTAKE + //{ + // GetOrthancWebViewerJpegCommand* rac = dynamic_cast(protection.get()); + // LOG(TRACE) << "WebAssemblyOracle::Schedule" << rac->GetUri(); + //} + //// END OF BLOCK TO REMOVE Execute(receiver, dynamic_cast(protection.release())); break; diff -r 861c080ef47b -r acc172f2b782 Framework/Radiography/RadiographyScene.cpp --- a/Framework/Radiography/RadiographyScene.cpp Fri Aug 02 17:38:31 2019 +0200 +++ b/Framework/Radiography/RadiographyScene.cpp Fri Aug 02 17:38:44 2019 +0200 @@ -606,8 +606,8 @@ Extent2D extent = GetSceneExtent(); - int w = static_cast(std::round(extent.GetWidth() / pixelSpacingX)); - int h = static_cast(std::round(extent.GetHeight() / pixelSpacingY)); + int w = boost::math::iround(extent.GetWidth() / pixelSpacingX); + int h = boost::math::iround(extent.GetHeight() / pixelSpacingY); if (w < 0 || h < 0) { diff -r 861c080ef47b -r acc172f2b782 Framework/Scene2D/Scene2D.cpp --- a/Framework/Scene2D/Scene2D.cpp Fri Aug 02 17:38:31 2019 +0200 +++ b/Framework/Scene2D/Scene2D.cpp Fri Aug 02 17:38:44 2019 +0200 @@ -132,7 +132,7 @@ if (found != content_.end()) { - LOG(INFO) << "DeleteLayer --found-- (" << depth << ")"; + LOG(TRACE) << "DeleteLayer --found-- (" << depth << ")"; assert(found->second != NULL); delete found->second; content_.erase(found); diff -r 861c080ef47b -r acc172f2b782 Framework/Volumes/DicomVolumeImageMPRSlicer.cpp --- a/Framework/Volumes/DicomVolumeImageMPRSlicer.cpp Fri Aug 02 17:38:31 2019 +0200 +++ b/Framework/Volumes/DicomVolumeImageMPRSlicer.cpp Fri Aug 02 17:38:44 2019 +0200 @@ -100,7 +100,12 @@ } - IVolumeSlicer::IExtractedSlice* + DicomVolumeImageMPRSlicer::~DicomVolumeImageMPRSlicer() + { + LOG(TRACE) << "DicomVolumeImageMPRSlicer::~DicomVolumeImageMPRSlicer()"; + } + + IVolumeSlicer::IExtractedSlice* DicomVolumeImageMPRSlicer::ExtractSlice(const CoordinateSystem3D& cuttingPlane) { if (volume_->HasGeometry()) diff -r 861c080ef47b -r acc172f2b782 Framework/Volumes/DicomVolumeImageMPRSlicer.h --- a/Framework/Volumes/DicomVolumeImageMPRSlicer.h Fri Aug 02 17:38:31 2019 +0200 +++ b/Framework/Volumes/DicomVolumeImageMPRSlicer.h Fri Aug 02 17:38:44 2019 +0200 @@ -89,6 +89,8 @@ { } + virtual ~DicomVolumeImageMPRSlicer(); + virtual IExtractedSlice* ExtractSlice(const CoordinateSystem3D& cuttingPlane) ORTHANC_OVERRIDE; }; } diff -r 861c080ef47b -r acc172f2b782 Framework/Volumes/VolumeSceneLayerSource.cpp --- a/Framework/Volumes/VolumeSceneLayerSource.cpp Fri Aug 02 17:38:31 2019 +0200 +++ b/Framework/Volumes/VolumeSceneLayerSource.cpp Fri Aug 02 17:38:44 2019 +0200 @@ -55,6 +55,10 @@ } } + VolumeSceneLayerSource::~VolumeSceneLayerSource() + { + ClearLayer(); + } void VolumeSceneLayerSource::RemoveConfigurator() { diff -r 861c080ef47b -r acc172f2b782 Framework/Volumes/VolumeSceneLayerSource.h --- a/Framework/Volumes/VolumeSceneLayerSource.h Fri Aug 02 17:38:31 2019 +0200 +++ b/Framework/Volumes/VolumeSceneLayerSource.h Fri Aug 02 17:38:44 2019 +0200 @@ -53,6 +53,8 @@ int layerDepth, const boost::shared_ptr& slicer); + ~VolumeSceneLayerSource(); + const IVolumeSlicer& GetSlicer() const { return *slicer_; diff -r 861c080ef47b -r acc172f2b782 Resources/CMake/OrthancStoneConfiguration.cmake --- a/Resources/CMake/OrthancStoneConfiguration.cmake Fri Aug 02 17:38:31 2019 +0200 +++ b/Resources/CMake/OrthancStoneConfiguration.cmake Fri Aug 02 17:38:44 2019 +0200 @@ -410,6 +410,8 @@ ${ORTHANC_STONE_ROOT}/Framework/Loaders/BasicFetchingItemsSorter.cpp ${ORTHANC_STONE_ROOT}/Framework/Loaders/BasicFetchingStrategy.cpp ${ORTHANC_STONE_ROOT}/Framework/Loaders/DicomStructureSetLoader.cpp + ${ORTHANC_STONE_ROOT}/Framework/Loaders/LoaderCache.h + ${ORTHANC_STONE_ROOT}/Framework/Loaders/LoaderCache.cpp ${ORTHANC_STONE_ROOT}/Framework/Loaders/LoaderStateMachine.cpp ${ORTHANC_STONE_ROOT}/Framework/Loaders/OrthancMultiframeVolumeLoader.cpp ${ORTHANC_STONE_ROOT}/Framework/Loaders/OrthancSeriesVolumeProgressiveLoader.cpp diff -r 861c080ef47b -r acc172f2b782 Samples/MultiPlatform/BasicScene/mainSdl.cpp --- a/Samples/MultiPlatform/BasicScene/mainSdl.cpp Fri Aug 02 17:38:31 2019 +0200 +++ b/Samples/MultiPlatform/BasicScene/mainSdl.cpp Fri Aug 02 17:38:44 2019 +0200 @@ -183,7 +183,7 @@ SdlOpenGLViewport viewport("Hello", 1024, 768); MessageBroker broker; boost::shared_ptr undoStack(new UndoStack); - boost::shared_ptr controller = boost::make_shared(undoStack, boost::ref(broker), viewport); + boost::shared_ptr controller = boost::make_shared(undoStack, boost::ref(broker), boost::ref(viewport)); interactor.reset(new BasicScene2DInteractor(controller)); PrepareScene(controller->GetScene()); Run(controller); diff -r 861c080ef47b -r acc172f2b782 Samples/Sdl/FusionMprSdl.cpp --- a/Samples/Sdl/FusionMprSdl.cpp Fri Aug 02 17:38:31 2019 +0200 +++ b/Samples/Sdl/FusionMprSdl.cpp Fri Aug 02 17:38:44 2019 +0200 @@ -103,7 +103,8 @@ void FusionMprSdlApp::DisplayInfoText() { // do not try to use stuff too early! - if (compositor_.get() == NULL) + ICompositor* pCompositor = &(viewport_.GetCompositor()); + if (pCompositor == NULL) return; std::stringstream msg; @@ -116,10 +117,10 @@ std::string msgS = msg.str(); TextSceneLayer* layerP = NULL; - if (GetScene()->HasLayer(FIXED_INFOTEXT_LAYER_ZINDEX)) + if (GetScene().HasLayer(FIXED_INFOTEXT_LAYER_ZINDEX)) { TextSceneLayer& layer = dynamic_cast( - GetScene()->GetLayer(FIXED_INFOTEXT_LAYER_ZINDEX)); + GetScene().GetLayer(FIXED_INFOTEXT_LAYER_ZINDEX)); layerP = &layer; } else @@ -131,29 +132,29 @@ layer->SetBorder(20); layer->SetAnchor(BitmapAnchor_TopLeft); //layer->SetPosition(0,0); - GetScene()->SetLayer(FIXED_INFOTEXT_LAYER_ZINDEX, layer.release()); + GetScene().SetLayer(FIXED_INFOTEXT_LAYER_ZINDEX, layer.release()); } // position the fixed info text in the upper right corner layerP->SetText(msgS.c_str()); - double cX = compositor_->GetCanvasWidth() * (-0.5); - double cY = compositor_->GetCanvasHeight() * (-0.5); - GetScene()->GetCanvasToSceneTransform().Apply(cX,cY); + double cX = viewport_.GetCompositor().GetCanvasWidth() * (-0.5); + double cY = viewport_.GetCompositor().GetCanvasHeight() * (-0.5); + GetScene().GetCanvasToSceneTransform().Apply(cX,cY); layerP->SetPosition(cX, cY); } void FusionMprSdlApp::DisplayFloatingCtrlInfoText(const PointerEvent& e) { - ScenePoint2D p = e.GetMainPosition().Apply(GetScene()->GetCanvasToSceneTransform()); + ScenePoint2D p = e.GetMainPosition().Apply(GetScene().GetCanvasToSceneTransform()); char buf[128]; sprintf(buf, "S:(%0.02f,%0.02f) C:(%0.02f,%0.02f)", p.GetX(), p.GetY(), e.GetMainPosition().GetX(), e.GetMainPosition().GetY()); - if (GetScene()->HasLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)) + if (GetScene().HasLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)) { TextSceneLayer& layer = - dynamic_cast(GetScene()->GetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)); + dynamic_cast(GetScene().GetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX)); layer.SetText(buf); layer.SetPosition(p.GetX(), p.GetY()); } @@ -165,13 +166,13 @@ layer->SetBorder(20); layer->SetAnchor(BitmapAnchor_BottomCenter); layer->SetPosition(p.GetX(), p.GetY()); - GetScene()->SetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX, layer.release()); + GetScene().SetLayer(FLOATING_INFOTEXT_LAYER_ZINDEX, layer.release()); } } void FusionMprSdlApp::HideInfoText() { - GetScene()->DeleteLayer(FLOATING_INFOTEXT_LAYER_ZINDEX); + GetScene().DeleteLayer(FLOATING_INFOTEXT_LAYER_ZINDEX); } void FusionMprSdlApp::HandleApplicationEvent( @@ -191,7 +192,7 @@ // The "left-ctrl" key is down, while no tracker is present // Let's display the info text PointerEvent e; - e.AddPosition(compositor_->GetPixelCenterCoordinates( + e.AddPosition(controller_->GetViewport().GetPixelCenterCoordinates( event.button.x, event.button.y)); DisplayFloatingCtrlInfoText(e); @@ -204,7 +205,7 @@ { //LOG(TRACE) << "(activeTracker_.get() != NULL)"; PointerEvent e; - e.AddPosition(compositor_->GetPixelCenterCoordinates( + e.AddPosition(controller_->GetViewport().GetPixelCenterCoordinates( event.button.x, event.button.y)); //LOG(TRACE) << "event.button.x = " << event.button.x << " " << @@ -223,7 +224,7 @@ if (activeTracker_) { PointerEvent e; - e.AddPosition(compositor_->GetPixelCenterCoordinates(event.button.x, event.button.y)); + e.AddPosition(controller_->GetViewport().GetPixelCenterCoordinates(event.button.x, event.button.y)); activeTracker_->PointerUp(e); if (!activeTracker_->IsAlive()) activeTracker_.reset(); @@ -232,7 +233,7 @@ else if (event.type == SDL_MOUSEBUTTONDOWN) { PointerEvent e; - e.AddPosition(compositor_->GetPixelCenterCoordinates( + e.AddPosition(controller_->GetViewport().GetPixelCenterCoordinates( event.button.x, event.button.y)); if (activeTracker_) { @@ -270,8 +271,8 @@ } break; case SDLK_s: - controller_->FitContent(compositor_->GetCanvasWidth(), - compositor_->GetCanvasHeight()); + controller_->FitContent(viewport_.GetCompositor().GetCanvasWidth(), + viewport_.GetCompositor().GetCanvasHeight()); break; case SDLK_z: @@ -309,8 +310,8 @@ case SDLK_c: TakeScreenshot( "screenshot.png", - compositor_->GetCanvasWidth(), - compositor_->GetCanvasHeight()); + viewport_.GetCompositor().GetCanvasWidth(), + viewport_.GetCompositor().GetCanvasHeight()); break; default: @@ -340,7 +341,7 @@ case SDL_BUTTON_RIGHT: return boost::shared_ptr(new ZoomSceneTracker - (controller_, e, compositor_->GetCanvasHeight())); + (controller_, e, viewport_.GetCompositor().GetCanvasHeight())); case SDL_BUTTON_LEFT: { @@ -372,7 +373,7 @@ controller_, e)); case FusionMprGuiTool_Zoom: return boost::shared_ptr(new ZoomSceneTracker( - controller_, e, compositor_->GetCanvasHeight())); + controller_, e, viewport_.GetCompositor().GetCanvasHeight())); //case GuiTool_AngleMeasure: // return new AngleMeasureTracker(GetScene(), e); //case GuiTool_CircleMeasure: @@ -409,6 +410,7 @@ , oracle_(*this) , currentTool_(FusionMprGuiTool_Rotate) , undoStack_(new UndoStack) + , viewport_("Hello", 1024, 1024, false) // False means we do NOT let Windows treat this as a legacy application that needs to be scaled { //oracleObservable.RegisterObserverCallback //(new Callable @@ -427,7 +429,7 @@ (*this, &FusionMprSdlApp::Handle)); controller_ = boost::shared_ptr( - new ViewportController(undoStack_, broker_)); + new ViewportController(undoStack_, broker_, viewport_)); controller_->RegisterObserverCallback( new Callable @@ -466,7 +468,7 @@ p[4] = 0; p[5] = 0; - GetScene()->SetLayer(TEXTURE_2x2_1_ZINDEX, new ColorTextureSceneLayer(i)); + GetScene().SetLayer(TEXTURE_2x2_1_ZINDEX, new ColorTextureSceneLayer(i)); } } @@ -483,7 +485,7 @@ unsigned int canvasWidth, unsigned int canvasHeight) { - CairoCompositor compositor(*GetScene(), canvasWidth, canvasHeight); + CairoCompositor compositor(GetScene(), canvasWidth, canvasHeight); compositor.SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, FONT_SIZE_0, Orthanc::Encoding_Latin1); compositor.Refresh(); @@ -557,7 +559,7 @@ const boost::shared_ptr& volume, OrthancStone::ILayerStyleConfigurator* style) { - source1_.reset(new OrthancStone::VolumeSceneLayerSource(*controller_->GetScene(), depth, volume)); + source1_.reset(new OrthancStone::VolumeSceneLayerSource(controller_->GetScene(), depth, volume)); if (style != NULL) { @@ -569,7 +571,7 @@ const boost::shared_ptr& volume, OrthancStone::ILayerStyleConfigurator* style) { - source2_.reset(new OrthancStone::VolumeSceneLayerSource(*controller_->GetScene(), depth, volume)); + source2_.reset(new OrthancStone::VolumeSceneLayerSource(controller_->GetScene(), depth, volume)); if (style != NULL) { @@ -580,25 +582,21 @@ void FusionMprSdlApp::SetStructureSet(int depth, const boost::shared_ptr& volume) { - source3_.reset(new OrthancStone::VolumeSceneLayerSource(*controller_->GetScene(), depth, volume)); + source3_.reset(new OrthancStone::VolumeSceneLayerSource(controller_->GetScene(), depth, volume)); } void FusionMprSdlApp::Run() { // False means we do NOT let Windows treat this as a legacy application // that needs to be scaled - SdlOpenGLContext window("Hello", 1024, 1024, false); - - controller_->FitContent(window.GetCanvasWidth(), window.GetCanvasHeight()); + controller_->FitContent(viewport_.GetCanvasWidth(), viewport_.GetCanvasHeight()); glEnable(GL_DEBUG_OUTPUT); glDebugMessageCallback(OpenGLMessageCallback, 0); - compositor_.reset(new OpenGLCompositor(window, *GetScene())); - - compositor_->SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, + viewport_.GetCompositor().SetFont(0, Orthanc::EmbeddedResources::UBUNTU_FONT, FONT_SIZE_0, Orthanc::Encoding_Latin1); - compositor_->SetFont(1, Orthanc::EmbeddedResources::UBUNTU_FONT, + viewport_.GetCompositor().SetFont(1, Orthanc::EmbeddedResources::UBUNTU_FONT, FONT_SIZE_1, Orthanc::Encoding_Latin1); @@ -675,7 +673,7 @@ while (!g_stopApplication) { - compositor_->Refresh(); + viewport_.GetCompositor().Refresh(); //////// from loader if (source1_.get() != NULL) @@ -713,12 +711,11 @@ switch (event.key.keysym.sym) { case SDLK_f: - window.GetWindow().ToggleMaximize(); + viewport_.GetWindow().ToggleMaximize(); break; case SDLK_s: - controller_->FitContent( - window.GetCanvasWidth(), window.GetCanvasHeight()); + controller_->FitContent(viewport_.GetCanvasWidth(), viewport_.GetCanvasHeight()); break; case SDLK_q: @@ -733,10 +730,6 @@ SDL_Delay(1); } - // the following is paramount because the compositor holds a reference - // to the scene and we do not want this reference to become dangling - compositor_.reset(NULL); - //// from loader //Orthanc::SystemToolbox::ServerBarrier(); diff -r 861c080ef47b -r acc172f2b782 Samples/Sdl/FusionMprSdl.h --- a/Samples/Sdl/FusionMprSdl.h Fri Aug 02 17:38:31 2019 +0200 +++ b/Samples/Sdl/FusionMprSdl.h Fri Aug 02 17:38:44 2019 +0200 @@ -18,6 +18,8 @@ * along with this program. If not, see . **/ +#include "../../Framework/Viewport/SdlViewport.h" + #include "../../Framework/Messages/IObserver.h" #include "../../Framework/Messages/IMessageEmitter.h" #include "../../Framework/Oracle/OracleCommandExceptionMessage.h" @@ -41,7 +43,7 @@ class ThreadedOracle; class VolumeSceneLayerSource; class NativeFusionMprApplicationContext; - + class SdlOpenGLViewport; enum FusionMprGuiTool { @@ -80,8 +82,8 @@ void SetInfoDisplayMessage(std::string key, std::string value); void DisableTracker(); - boost::shared_ptr GetScene(); - boost::shared_ptr GetScene() const; + Scene2D& GetScene(); + const Scene2D& GetScene() const; void HandleApplicationEvent(const SDL_Event& event); @@ -174,7 +176,6 @@ boost::shared_ptr source1_, source2_, source3_; - std::auto_ptr compositor_; /** WARNING: the measuring tools do store a reference to the scene, and it paramount that the scene gets destroyed AFTER the measurement tools. @@ -196,7 +197,7 @@ FusionMprGuiTool currentTool_; boost::shared_ptr undoStack_; - + SdlOpenGLViewport viewport_; }; } diff -r 861c080ef47b -r acc172f2b782 Samples/Sdl/TrackerSampleApp.cpp --- a/Samples/Sdl/TrackerSampleApp.cpp Fri Aug 02 17:38:31 2019 +0200 +++ b/Samples/Sdl/TrackerSampleApp.cpp Fri Aug 02 17:38:44 2019 +0200 @@ -641,7 +641,7 @@ static bool g_stopApplication = false; - OpenGLCompositor& TrackerSampleApp::GetCompositor() + ICompositor& TrackerSampleApp::GetCompositor() { using namespace Orthanc; try @@ -655,7 +655,7 @@ } } - const OpenGLCompositor& TrackerSampleApp::GetCompositor() const + const ICompositor& TrackerSampleApp::GetCompositor() const { using namespace Orthanc; try @@ -705,7 +705,7 @@ switch (event.key.keysym.sym) { case SDLK_f: - viewport_.GetContext().GetWindow().ToggleMaximize(); + viewport_.GetWindow().ToggleMaximize(); break; case SDLK_q: diff -r 861c080ef47b -r acc172f2b782 Samples/Sdl/TrackerSampleApp.h --- a/Samples/Sdl/TrackerSampleApp.h Fri Aug 02 17:38:31 2019 +0200 +++ b/Samples/Sdl/TrackerSampleApp.h Fri Aug 02 17:38:44 2019 +0200 @@ -84,12 +84,12 @@ In the case of this app, the viewport is an SDL viewport and it has a OpenGLCompositor& GetCompositor() method */ - OpenGLCompositor& GetCompositor(); + ICompositor& GetCompositor(); /** See the other overload */ - const OpenGLCompositor& GetCompositor() const; + const ICompositor& GetCompositor() const; /** This returns a random point in the canvas part of the scene, but in