# HG changeset patch # User Benjamin Golinvaux # Date 1564561449 -7200 # Node ID 86ac61a040c9fcaf7028110df1a16cf95e9c3bf8 # Parent 775ebd43bd3b121cbd6c78f2ce050fb4ccba243d Added getters and notifications to allow clients of the loaders (DicomStructureSetLoader, OrthancSeriesVolumeProgressiveLoader and OrthancMultiframeVolumeLoader) to know when the loading is finished + added ability for SDL event loop to execute a callback repeatedly (used to check the view loading state) diff -r 775ebd43bd3b -r 86ac61a040c9 Applications/Generic/GuiAdapter.cpp --- a/Applications/Generic/GuiAdapter.cpp Mon Jul 29 15:39:45 2019 +0200 +++ b/Applications/Generic/GuiAdapter.cpp Wed Jul 31 10:24:09 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 775ebd43bd3b -r 86ac61a040c9 Applications/Generic/GuiAdapter.h --- a/Applications/Generic/GuiAdapter.h Mon Jul 29 15:39:45 2019 +0200 +++ b/Applications/Generic/GuiAdapter.h Wed Jul 31 10:24:09 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 /** diff -r 775ebd43bd3b -r 86ac61a040c9 Framework/Loaders/DicomStructureSetLoader.cpp --- a/Framework/Loaders/DicomStructureSetLoader.cpp Mon Jul 29 15:39:45 2019 +0200 +++ b/Framework/Loaders/DicomStructureSetLoader.cpp Wed Jul 31 10:24:09 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,10 +226,12 @@ DicomStructureSetLoader::DicomStructureSetLoader(IOracle& oracle, IObservable& oracleObservable) : + IObservable(oracleObservable.GetBroker()), LoaderStateMachine(oracle, oracleObservable), revision_(0), countProcessedInstances_(0), - countReferencedInstances_(0) + countReferencedInstances_(0), + structuresReady_(false) { } @@ -266,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 775ebd43bd3b -r 86ac61a040c9 Framework/Loaders/DicomStructureSetLoader.h --- a/Framework/Loaders/DicomStructureSetLoader.h Mon Jul 29 15:39:45 2019 +0200 +++ b/Framework/Loaders/DicomStructureSetLoader.h Wed Jul 31 10:24:09 2019 +0200 @@ -29,7 +29,8 @@ { class DicomStructureSetLoader : public LoaderStateMachine, - public IVolumeSlicer + public IVolumeSlicer, + public IObservable { private: class Slice; @@ -44,8 +45,13 @@ 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); @@ -54,5 +60,9 @@ void LoadInstance(const std::string& instanceId); virtual IExtractedSlice* ExtractSlice(const CoordinateSystem3D& cuttingPlane); + + void SetStructuresReady(); + + bool AreStructuresReady() const; }; } diff -r 775ebd43bd3b -r 86ac61a040c9 Framework/Loaders/LoaderCache.cpp --- a/Framework/Loaders/LoaderCache.cpp Mon Jul 29 15:39:45 2019 +0200 +++ b/Framework/Loaders/LoaderCache.cpp Wed Jul 31 10:24:09 2019 +0200 @@ -119,6 +119,18 @@ } } + 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 diff -r 775ebd43bd3b -r 86ac61a040c9 Framework/Loaders/LoaderCache.h --- a/Framework/Loaders/LoaderCache.h Mon Jul 29 15:39:45 2019 +0200 +++ b/Framework/Loaders/LoaderCache.h Wed Jul 31 10:24:09 2019 +0200 @@ -50,8 +50,13 @@ 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); diff -r 775ebd43bd3b -r 86ac61a040c9 Framework/Loaders/OrthancMultiframeVolumeLoader.cpp --- a/Framework/Loaders/OrthancMultiframeVolumeLoader.cpp Mon Jul 29 15:39:45 2019 +0200 +++ b/Framework/Loaders/OrthancMultiframeVolumeLoader.cpp Wed Jul 31 10:24:09 2019 +0200 @@ -316,6 +316,7 @@ volume_->IncrementRevision(); + pixelDataLoaded_ = true; BroadcastMessage(DicomVolumeImage::ContentUpdatedMessage(*volume_)); } @@ -325,7 +326,8 @@ IObservable& oracleObservable) : LoaderStateMachine(oracle, oracleObservable), IObservable(oracleObservable.GetBroker()), - volume_(volume) + volume_(volume), + pixelDataLoaded_(false) { if (volume.get() == NULL) { diff -r 775ebd43bd3b -r 86ac61a040c9 Framework/Loaders/OrthancMultiframeVolumeLoader.h --- a/Framework/Loaders/OrthancMultiframeVolumeLoader.h Mon Jul 29 15:39:45 2019 +0200 +++ b/Framework/Loaders/OrthancMultiframeVolumeLoader.h Wed Jul 31 10:24:09 2019 +0200 @@ -41,6 +41,7 @@ boost::shared_ptr volume_; std::string instanceId_; std::string transferSyntaxUid_; + bool pixelDataLoaded_; const std::string& GetInstanceId() const; @@ -62,6 +63,11 @@ virtual ~OrthancMultiframeVolumeLoader(); + bool IsPixelDataLoaded() const + { + return pixelDataLoaded_; + } + void LoadInstance(const std::string& instanceId); }; } diff -r 775ebd43bd3b -r 86ac61a040c9 Framework/Loaders/OrthancSeriesVolumeProgressiveLoader.cpp --- a/Framework/Loaders/OrthancSeriesVolumeProgressiveLoader.cpp Mon Jul 29 15:39:45 2019 +0200 +++ b/Framework/Loaders/OrthancSeriesVolumeProgressiveLoader.cpp Wed Jul 31 10:24:09 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 diff -r 775ebd43bd3b -r 86ac61a040c9 Framework/Loaders/OrthancSeriesVolumeProgressiveLoader.h --- a/Framework/Loaders/OrthancSeriesVolumeProgressiveLoader.h Mon Jul 29 15:39:45 2019 +0200 +++ b/Framework/Loaders/OrthancSeriesVolumeProgressiveLoader.h Wed Jul 31 10:24:09 2019 +0200 @@ -104,17 +104,21 @@ 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); @@ -123,6 +127,11 @@ void SetSimultaneousDownloads(unsigned int count); + bool IsVolumeImageReadyInHighQuality() const + { + return volumeImageReadyInHighQuality_; + } + void LoadSeries(const std::string& seriesId); /**