Mercurial > hg > orthanc-webviewer
annotate Plugin/Plugin.cpp @ 100:f5b1a9267da0 refactoring
remove unused classes
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Fri, 27 Nov 2015 21:45:21 +0100 |
parents | 46ec13a1177c |
children | 21123729ac71 |
rev | line source |
---|---|
0 | 1 /** |
2 * Orthanc - A Lightweight, RESTful DICOM Store | |
3 * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics | |
4 * Department, University Hospital of Liege, Belgium | |
5 * | |
6 * This program is free software: you can redistribute it and/or | |
7 * modify it under the terms of the GNU Affero General Public License | |
8 * as published by the Free Software Foundation, either version 3 of | |
9 * the License, or (at your option) any later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, but | |
12 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 * Affero General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU Affero General Public License | |
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 **/ | |
19 | |
20 | |
21 #include <boost/thread.hpp> | |
22 #include <boost/lexical_cast.hpp> | |
23 #include <EmbeddedResources.h> | |
4
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
24 #include <boost/filesystem.hpp> |
0 | 25 |
26 | 26 #include "../Orthanc/Core/OrthancException.h" |
0 | 27 #include "ViewerToolbox.h" |
28 #include "ViewerPrefetchPolicy.h" | |
29 #include "DecodedImageAdapter.h" | |
30 #include "SeriesInformationAdapter.h" | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
31 #include "../Orthanc/Plugins/Samples/GdcmDecoder/GdcmImageDecoder.h" |
99
46ec13a1177c
use of ordered-slices
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
96
diff
changeset
|
32 #include "../Orthanc/Core/Toolbox.h" |
74
ab5218c18b7a
compatibility with forthcoming sdk 0.9.5
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
58
diff
changeset
|
33 |
0 | 34 |
75
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
35 static OrthancPluginContext* context_ = NULL; |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
36 |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
37 |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
38 |
0 | 39 class CacheContext |
40 { | |
41 private: | |
75
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
42 class DynamicString : public Orthanc::IDynamicObject |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
43 { |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
44 private: |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
45 std::string value_; |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
46 |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
47 public: |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
48 DynamicString(const char* value) : value_(value) |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
49 { |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
50 } |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
51 |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
52 const std::string& GetValue() const |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
53 { |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
54 return value_; |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
55 } |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
56 }; |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
57 |
58 | 58 Orthanc::FilesystemStorage storage_; |
59 Orthanc::SQLite::Connection db_; | |
60 | |
0 | 61 std::auto_ptr<OrthancPlugins::CacheManager> cache_; |
62 std::auto_ptr<OrthancPlugins::CacheScheduler> scheduler_; | |
63 | |
75
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
64 Orthanc::SharedMessageQueue newInstances_; |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
65 bool stop_; |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
66 boost::thread newInstancesThread_; |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
67 |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
68 |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
69 static void NewInstancesThread(CacheContext* cache) |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
70 { |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
71 while (!cache->stop_) |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
72 { |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
73 std::auto_ptr<Orthanc::IDynamicObject> obj(cache->newInstances_.Dequeue(100)); |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
74 if (obj.get() != NULL) |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
75 { |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
76 const std::string& instanceId = dynamic_cast<DynamicString&>(*obj).GetValue(); |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
77 |
100
f5b1a9267da0
remove unused classes
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
99
diff
changeset
|
78 // On the reception of a new instance, indalidate the parent series of the instance |
75
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
79 std::string uri = "/instances/" + std::string(instanceId); |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
80 Json::Value instance; |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
81 if (OrthancPlugins::GetJsonFromOrthanc(instance, context_, uri)) |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
82 { |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
83 std::string seriesId = instance["ParentSeries"].asString(); |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
84 cache->GetScheduler().Invalidate(OrthancPlugins::CacheBundle_SeriesInformation, seriesId); |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
85 } |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
86 } |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
87 } |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
88 } |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
89 |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
90 |
0 | 91 public: |
75
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
92 CacheContext(const std::string& path) : storage_(path), stop_(false) |
0 | 93 { |
94 boost::filesystem::path p(path); | |
58 | 95 db_.Open((p / "cache.db").string()); |
0 | 96 |
58 | 97 cache_.reset(new OrthancPlugins::CacheManager(db_, storage_)); |
0 | 98 //cache_->SetSanityCheckEnabled(true); // For debug |
99 | |
100 scheduler_.reset(new OrthancPlugins::CacheScheduler(*cache_, 100)); | |
75
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
101 |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
102 newInstancesThread_ = boost::thread(NewInstancesThread, this); |
0 | 103 } |
104 | |
58 | 105 ~CacheContext() |
106 { | |
75
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
107 stop_ = true; |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
108 if (newInstancesThread_.joinable()) |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
109 { |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
110 newInstancesThread_.join(); |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
111 } |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
112 |
58 | 113 scheduler_.reset(NULL); |
114 cache_.reset(NULL); | |
115 } | |
116 | |
0 | 117 OrthancPlugins::CacheScheduler& GetScheduler() |
118 { | |
119 return *scheduler_; | |
120 } | |
75
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
121 |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
122 void SignalNewInstance(const char* instanceId) |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
123 { |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
124 newInstances_.Enqueue(new DynamicString(instanceId)); |
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
125 } |
0 | 126 }; |
127 | |
128 | |
75
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
129 |
0 | 130 static CacheContext* cache_ = NULL; |
131 | |
132 | |
133 | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
134 static OrthancPluginErrorCode OnChangeCallback(OrthancPluginChangeType changeType, |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
135 OrthancPluginResourceType resourceType, |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
136 const char* resourceId) |
0 | 137 { |
138 try | |
139 { | |
140 if (changeType == OrthancPluginChangeType_NewInstance && | |
141 resourceType == OrthancPluginResourceType_Instance) | |
142 { | |
75
e15a59a4b4d4
Fix possible deadlock with other plugins in OnChangeCallback()
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
74
diff
changeset
|
143 cache_->SignalNewInstance(resourceId); |
0 | 144 } |
145 | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
146 return OrthancPluginErrorCode_Success; |
0 | 147 } |
148 catch (std::runtime_error& e) | |
149 { | |
150 OrthancPluginLogError(context_, e.what()); | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
151 return OrthancPluginErrorCode_Success; // Ignore error |
0 | 152 } |
153 } | |
154 | |
155 | |
156 | |
157 template <enum OrthancPlugins::CacheBundle bundle> | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
158 static OrthancPluginErrorCode ServeCache(OrthancPluginRestOutput* output, |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
159 const char* url, |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
160 const OrthancPluginHttpRequest* request) |
0 | 161 { |
162 try | |
163 { | |
164 if (request->method != OrthancPluginHttpMethod_Get) | |
165 { | |
166 OrthancPluginSendMethodNotAllowed(context_, output, "GET"); | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
167 return OrthancPluginErrorCode_Success; |
0 | 168 } |
169 | |
170 const std::string id = request->groups[0]; | |
171 std::string content; | |
172 | |
173 if (cache_->GetScheduler().Access(content, bundle, id)) | |
174 { | |
175 OrthancPluginAnswerBuffer(context_, output, content.c_str(), content.size(), "application/json"); | |
176 } | |
177 else | |
178 { | |
179 OrthancPluginSendHttpStatusCode(context_, output, 404); | |
180 } | |
181 | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
182 return OrthancPluginErrorCode_Success; |
0 | 183 } |
184 catch (Orthanc::OrthancException& e) | |
185 { | |
186 OrthancPluginLogError(context_, e.What()); | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
187 return OrthancPluginErrorCode_Plugin; |
0 | 188 } |
189 catch (std::runtime_error& e) | |
190 { | |
191 OrthancPluginLogError(context_, e.what()); | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
192 return OrthancPluginErrorCode_Plugin; |
0 | 193 } |
194 catch (boost::bad_lexical_cast&) | |
195 { | |
196 OrthancPluginLogError(context_, "Bad lexical cast"); | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
197 return OrthancPluginErrorCode_Plugin; |
0 | 198 } |
199 } | |
200 | |
201 | |
202 | |
203 | |
204 #if ORTHANC_STANDALONE == 0 | |
99
46ec13a1177c
use of ordered-slices
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
96
diff
changeset
|
205 static OrthancPluginErrorCode ServeWebViewer(OrthancPluginRestOutput* output, |
46ec13a1177c
use of ordered-slices
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
96
diff
changeset
|
206 const char* url, |
46ec13a1177c
use of ordered-slices
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
96
diff
changeset
|
207 const OrthancPluginHttpRequest* request) |
0 | 208 { |
209 if (request->method != OrthancPluginHttpMethod_Get) | |
210 { | |
211 OrthancPluginSendMethodNotAllowed(context_, output, "GET"); | |
99
46ec13a1177c
use of ordered-slices
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
96
diff
changeset
|
212 return OrthancPluginErrorCode_Success; |
0 | 213 } |
214 | |
215 const std::string path = std::string(WEB_VIEWER_PATH) + std::string(request->groups[0]); | |
216 const char* mime = OrthancPlugins::GetMimeType(path); | |
217 | |
218 std::string s; | |
99
46ec13a1177c
use of ordered-slices
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
96
diff
changeset
|
219 try |
0 | 220 { |
99
46ec13a1177c
use of ordered-slices
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
96
diff
changeset
|
221 Orthanc::Toolbox::ReadFile(s, path); |
0 | 222 const char* resource = s.size() ? s.c_str() : NULL; |
223 OrthancPluginAnswerBuffer(context_, output, resource, s.size(), mime); | |
224 } | |
99
46ec13a1177c
use of ordered-slices
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
96
diff
changeset
|
225 catch (Orthanc::OrthancException&) |
0 | 226 { |
227 std::string s = "Inexistent file in served folder: " + path; | |
228 OrthancPluginLogError(context_, s.c_str()); | |
229 OrthancPluginSendHttpStatusCode(context_, output, 404); | |
230 } | |
231 | |
99
46ec13a1177c
use of ordered-slices
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
96
diff
changeset
|
232 return OrthancPluginErrorCode_Success; |
0 | 233 } |
234 #endif | |
235 | |
236 | |
237 | |
31 | 238 template <enum Orthanc::EmbeddedResources::DirectoryResourceId folder> |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
239 static OrthancPluginErrorCode ServeEmbeddedFolder(OrthancPluginRestOutput* output, |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
240 const char* url, |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
241 const OrthancPluginHttpRequest* request) |
0 | 242 { |
243 if (request->method != OrthancPluginHttpMethod_Get) | |
244 { | |
245 OrthancPluginSendMethodNotAllowed(context_, output, "GET"); | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
246 return OrthancPluginErrorCode_Success; |
0 | 247 } |
248 | |
249 std::string path = "/" + std::string(request->groups[0]); | |
250 const char* mime = OrthancPlugins::GetMimeType(path); | |
251 | |
252 try | |
253 { | |
254 std::string s; | |
31 | 255 Orthanc::EmbeddedResources::GetDirectoryResource(s, folder, path.c_str()); |
0 | 256 |
257 const char* resource = s.size() ? s.c_str() : NULL; | |
258 OrthancPluginAnswerBuffer(context_, output, resource, s.size(), mime); | |
259 | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
260 return OrthancPluginErrorCode_Success; |
0 | 261 } |
262 catch (std::runtime_error&) | |
263 { | |
264 std::string s = "Unknown static resource in plugin: " + std::string(request->groups[0]); | |
265 OrthancPluginLogError(context_, s.c_str()); | |
266 OrthancPluginSendHttpStatusCode(context_, output, 404); | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
267 return OrthancPluginErrorCode_Success; |
0 | 268 } |
269 } | |
270 | |
271 | |
272 | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
273 static OrthancPluginErrorCode IsStableSeries(OrthancPluginRestOutput* output, |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
274 const char* url, |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
275 const OrthancPluginHttpRequest* request) |
19 | 276 { |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
277 try |
19 | 278 { |
279 if (request->method != OrthancPluginHttpMethod_Get) | |
280 { | |
281 OrthancPluginSendMethodNotAllowed(context_, output, "GET"); | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
282 return OrthancPluginErrorCode_Success; |
19 | 283 } |
284 | |
285 const std::string id = request->groups[0]; | |
286 Json::Value series; | |
287 | |
288 if (OrthancPlugins::GetJsonFromOrthanc(series, context_, "/series/" + id) && | |
289 series.type() == Json::objectValue) | |
290 { | |
291 bool value = (series["IsStable"].asBool() || | |
292 series["Status"].asString() == "Complete"); | |
293 std::string answer = value ? "true" : "false"; | |
294 OrthancPluginAnswerBuffer(context_, output, answer.c_str(), answer.size(), "application/json"); | |
295 } | |
296 else | |
297 { | |
298 OrthancPluginSendHttpStatusCode(context_, output, 404); | |
299 } | |
300 | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
301 return OrthancPluginErrorCode_Success; |
19 | 302 } |
303 catch (Orthanc::OrthancException& e) | |
304 { | |
305 OrthancPluginLogError(context_, e.What()); | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
306 return OrthancPluginErrorCode_Plugin; |
19 | 307 } |
308 catch (std::runtime_error& e) | |
309 { | |
310 OrthancPluginLogError(context_, e.what()); | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
311 return OrthancPluginErrorCode_Plugin; |
19 | 312 } |
313 catch (boost::bad_lexical_cast&) | |
314 { | |
315 OrthancPluginLogError(context_, "Bad lexical cast"); | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
316 return OrthancPluginErrorCode_Plugin; |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
317 } |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
318 } |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
319 |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
320 |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
321 static OrthancPluginErrorCode DecodeImageCallback(OrthancPluginImage** target, |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
322 const void* dicom, |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
323 const uint32_t size, |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
324 uint32_t frameIndex) |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
325 { |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
326 try |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
327 { |
96 | 328 std::auto_ptr<OrthancPlugins::OrthancImageWrapper> image; |
329 | |
330 #if 0 | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
331 // Do not use the cache |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
332 OrthancPlugins::GdcmImageDecoder decoder(dicom, size); |
96 | 333 image.reset(new OrthancPlugins::OrthancImageWrapper(context_, decoder, frameIndex)); |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
334 #else |
96 | 335 using namespace OrthancPlugins; |
336 ICacheFactory& factory = cache_->GetScheduler().GetFactory(CacheBundle_DecodedImage); | |
337 image.reset(dynamic_cast<DecodedImageAdapter&>(factory).GetDecoderCache().Decode(context_, dicom, size, frameIndex)); | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
338 #endif |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
339 |
96 | 340 *target = image->Release(); |
341 | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
342 return OrthancPluginErrorCode_Success; |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
343 } |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
344 catch (std::runtime_error& e) |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
345 { |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
346 *target = NULL; |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
347 |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
348 std::string s = "Cannot decode image using GDCM: " + std::string(e.what()); |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
349 OrthancPluginLogError(context_, s.c_str()); |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
350 return OrthancPluginErrorCode_Plugin; |
19 | 351 } |
352 } | |
353 | |
0 | 354 |
355 extern "C" | |
356 { | |
357 ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* context) | |
358 { | |
359 using namespace OrthancPlugins; | |
360 | |
361 context_ = context; | |
362 OrthancPluginLogWarning(context_, "Initializing the Web viewer"); | |
363 | |
364 | |
365 /* Check the version of the Orthanc core */ | |
366 if (OrthancPluginCheckVersion(context_) == 0) | |
367 { | |
368 char info[1024]; | |
369 sprintf(info, "Your version of Orthanc (%s) must be above %d.%d.%d to run this plugin", | |
370 context_->orthancVersion, | |
371 ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER, | |
372 ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER, | |
373 ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER); | |
374 OrthancPluginLogError(context_, info); | |
375 return -1; | |
376 } | |
377 | |
378 OrthancPluginSetDescription(context_, "Provides a Web viewer of DICOM series within Orthanc."); | |
379 | |
380 | |
95
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
381 // Replace the default decoder of DICOM images that is built in Orthanc |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
382 OrthancPluginRegisterDecodeImageCallback(context_, DecodeImageCallback); |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
383 |
dbe7c97b6b4a
replace built-in decoder
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
86
diff
changeset
|
384 |
0 | 385 /* By default, use half of the available processing cores for the decoding of DICOM images */ |
386 int decodingThreads = boost::thread::hardware_concurrency() / 2; | |
387 if (decodingThreads == 0) | |
388 { | |
389 decodingThreads = 1; | |
390 } | |
391 | |
392 | |
393 try | |
394 { | |
395 /* Read the configuration of the Web viewer */ | |
396 Json::Value configuration; | |
397 if (!ReadConfiguration(configuration, context)) | |
398 { | |
399 OrthancPluginLogError(context_, "Unable to read the configuration file of Orthanc"); | |
400 return -1; | |
401 } | |
402 | |
4
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
403 // By default, the cache of the Web viewer is located inside the |
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
404 // "StorageDirectory" of Orthanc |
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
405 boost::filesystem::path cachePath = GetStringValue(configuration, "StorageDirectory", "."); |
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
406 cachePath /= "WebViewerCache"; |
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
407 int cacheSize = 100; // By default, a cache of 100 MB is used |
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
408 |
0 | 409 if (configuration.isMember("WebViewer")) |
410 { | |
4
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
411 std::string key = "CachePath"; |
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
412 if (!configuration["WebViewer"].isMember(key)) |
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
413 { |
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
414 // For backward compatibility with the initial release of the Web viewer |
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
415 key = "Cache"; |
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
416 } |
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
417 |
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
418 cachePath = GetStringValue(configuration["WebViewer"], key, cachePath.string()); |
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
419 cacheSize = GetIntegerValue(configuration["WebViewer"], "CacheSize", cacheSize); |
0 | 420 decodingThreads = GetIntegerValue(configuration["WebViewer"], "Threads", decodingThreads); |
421 } | |
422 | |
423 std::string message = ("Web viewer using " + boost::lexical_cast<std::string>(decodingThreads) + | |
424 " threads for the decoding of the DICOM images"); | |
425 OrthancPluginLogWarning(context_, message.c_str()); | |
426 | |
4
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
427 if (decodingThreads <= 0 || |
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
428 cacheSize <= 0) |
0 | 429 { |
430 throw Orthanc::OrthancException(Orthanc::ErrorCode_ParameterOutOfRange); | |
431 } | |
432 | |
4
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
433 message = "Storing the cache of the Web viewer in folder: " + cachePath.string(); |
0 | 434 OrthancPluginLogWarning(context_, message.c_str()); |
435 | |
436 | |
437 /* Create the cache */ | |
4
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
438 cache_ = new CacheContext(cachePath.string()); |
0 | 439 cache_->GetScheduler().RegisterPolicy(new ViewerPrefetchPolicy(context_)); |
440 cache_->GetScheduler().Register(CacheBundle_SeriesInformation, | |
441 new SeriesInformationAdapter(context_, cache_->GetScheduler()), 1); | |
442 cache_->GetScheduler().Register(CacheBundle_DecodedImage, | |
443 new DecodedImageAdapter(context_), decodingThreads); | |
4
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
444 |
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
445 |
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
446 /* Set the quotas */ |
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
447 cache_->GetScheduler().SetQuota(CacheBundle_SeriesInformation, 1000, 0); // Keep info about 1000 series |
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
448 |
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
449 message = "Web viewer using a cache of " + boost::lexical_cast<std::string>(cacheSize) + " MB"; |
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
450 OrthancPluginLogWarning(context_, message.c_str()); |
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
451 |
ecefd45026bf
configuration of the cache
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
0
diff
changeset
|
452 cache_->GetScheduler().SetQuota(CacheBundle_DecodedImage, 0, static_cast<uint64_t>(cacheSize) * 1024 * 1024); |
0 | 453 } |
454 catch (std::runtime_error& e) | |
455 { | |
456 OrthancPluginLogError(context_, e.what()); | |
457 return -1; | |
458 } | |
459 catch (Orthanc::OrthancException& e) | |
460 { | |
461 OrthancPluginLogError(context_, e.What()); | |
462 return -1; | |
463 } | |
464 | |
465 | |
466 /* Install the callbacks */ | |
467 OrthancPluginRegisterRestCallback(context_, "/web-viewer/series/(.*)", ServeCache<CacheBundle_SeriesInformation>); | |
19 | 468 OrthancPluginRegisterRestCallback(context_, "/web-viewer/is-stable-series/(.*)", IsStableSeries); |
0 | 469 OrthancPluginRegisterRestCallback(context_, "/web-viewer/instances/(.*)", ServeCache<CacheBundle_DecodedImage>); |
31 | 470 OrthancPluginRegisterRestCallback(context, "/web-viewer/libs/(.*)", ServeEmbeddedFolder<Orthanc::EmbeddedResources::JAVASCRIPT_LIBS>); |
0 | 471 |
472 #if ORTHANC_STANDALONE == 1 | |
31 | 473 OrthancPluginRegisterRestCallback(context, "/web-viewer/app/(.*)", ServeEmbeddedFolder<Orthanc::EmbeddedResources::WEB_VIEWER>); |
0 | 474 #else |
475 OrthancPluginRegisterRestCallback(context, "/web-viewer/app/(.*)", ServeWebViewer); | |
476 #endif | |
477 | |
478 OrthancPluginRegisterOnChangeCallback(context, OnChangeCallback); | |
479 | |
480 | |
481 /* Extend the default Orthanc Explorer with custom JavaScript */ | |
482 std::string explorer; | |
31 | 483 Orthanc::EmbeddedResources::GetFileResource(explorer, Orthanc::EmbeddedResources::ORTHANC_EXPLORER); |
0 | 484 OrthancPluginExtendOrthancExplorer(context_, explorer.c_str()); |
485 | |
486 return 0; | |
487 } | |
488 | |
489 | |
490 ORTHANC_PLUGINS_API void OrthancPluginFinalize() | |
491 { | |
492 OrthancPluginLogWarning(context_, "Finalizing the Web viewer"); | |
493 | |
494 if (cache_ != NULL) | |
495 { | |
496 delete cache_; | |
497 cache_ = NULL; | |
498 } | |
499 } | |
500 | |
501 | |
502 ORTHANC_PLUGINS_API const char* OrthancPluginGetName() | |
503 { | |
504 return "web-viewer"; | |
505 } | |
506 | |
507 | |
508 ORTHANC_PLUGINS_API const char* OrthancPluginGetVersion() | |
509 { | |
12 | 510 return ORTHANC_WEBVIEWER_VERSION; |
0 | 511 } |
512 } |