comparison Applications/Samples/Sdl/SingleFrameViewer/SdlSimpleViewer.cpp @ 1538:d1806b4e4839

moving OrthancStone/Samples/ as Applications/Samples/
author Sebastien Jodogne <s.jodogne@gmail.com>
date Tue, 11 Aug 2020 13:24:38 +0200
parents OrthancStone/Samples/Sdl/SingleFrameViewer/SdlSimpleViewer.cpp@301571299212
children 6e0da8370270
comparison
equal deleted inserted replaced
1537:de8cf5859e84 1538:d1806b4e4839
1 /**
2 * Stone of Orthanc
3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 * Department, University Hospital of Liege, Belgium
5 * Copyright (C) 2017-2020 Osimis S.A., Belgium
6 *
7 * This program is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU Affero General Public License
9 * as published by the Free Software Foundation, either version 3 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **/
20
21
22 #include "SdlSimpleViewerApplication.h"
23 #include "../SdlHelpers.h"
24 #include "../../Common/SampleHelpers.h"
25
26 #include "../../../Sources/Loaders/GenericLoadersContext.h"
27 #include "../../../Sources/StoneException.h"
28 #include "../../../Sources/StoneEnumerations.h"
29 #include "../../../Sources/StoneInitialization.h"
30 #include "../../../Sources/Viewport/SdlViewport.h"
31
32 #include <Compatibility.h> // For std::unique_ptr<>
33 #include <OrthancException.h>
34
35 #include <boost/program_options.hpp>
36 #include <SDL.h>
37
38 #include <string>
39
40
41 std::string orthancUrl;
42 std::string instanceId;
43 int frameIndex = 0;
44
45
46 static void ProcessOptions(int argc, char* argv[])
47 {
48 namespace po = boost::program_options;
49 po::options_description desc("Usage");
50
51 desc.add_options()
52 ("loglevel", po::value<std::string>()->default_value("WARNING"),
53 "You can choose WARNING, INFO or TRACE for the logging level: Errors and warnings will always be displayed. (default: WARNING)")
54
55 ("orthanc", po::value<std::string>()->default_value("http://localhost:8042"),
56 "Base URL of the Orthanc instance")
57
58 ("instance", po::value<std::string>()->default_value("285dece8-e1956b38-cdc7d084-6ce3371e-536a9ffc"),
59 "Orthanc ID of the instance to display")
60
61 ("frame_index", po::value<int>()->default_value(0),
62 "The zero-based index of the frame (for multi-frame instances)")
63 ;
64
65 std::cout << desc << std::endl;
66
67 po::variables_map vm;
68 try
69 {
70 po::store(po::parse_command_line(argc, argv, desc), vm);
71 po::notify(vm);
72 }
73 catch (std::exception& e)
74 {
75 std::cerr << "Please check your command line options! (\"" << e.what() << "\")" << std::endl;
76 }
77
78 if (vm.count("loglevel") > 0)
79 {
80 std::string logLevel = vm["loglevel"].as<std::string>();
81 OrthancStoneHelpers::SetLogLevel(logLevel);
82 }
83
84 if (vm.count("orthanc") > 0)
85 {
86 // maybe check URL validity here
87 orthancUrl = vm["orthanc"].as<std::string>();
88 }
89
90 if (vm.count("instance") > 0)
91 {
92 instanceId = vm["instance"].as<std::string>();
93 }
94
95 if (vm.count("frame_index") > 0)
96 {
97 frameIndex = vm["frame_index"].as<int>();
98 }
99
100 }
101
102 /**
103 * IMPORTANT: The full arguments to "main()" are needed for SDL on
104 * Windows. Otherwise, one gets the linking error "undefined reference
105 * to `SDL_main'". https://wiki.libsdl.org/FAQWindows
106 **/
107 int main(int argc, char* argv[])
108 {
109 try
110 {
111 OrthancStone::StoneInitialize();
112
113 ProcessOptions(argc, argv);
114
115 //Orthanc::Logging::EnableInfoLevel(true);
116 //Orthanc::Logging::EnableTraceLevel(true);
117
118 {
119
120 #if 1
121 boost::shared_ptr<OrthancStone::SdlViewport> viewport =
122 OrthancStone::SdlOpenGLViewport::Create("Stone of Orthanc", 800, 600);
123 #else
124 boost::shared_ptr<OrthancStone::SdlViewport> viewport =
125 OrthancStone::SdlCairoViewport::Create("Stone of Orthanc", 800, 600);
126 #endif
127
128 OrthancStone::GenericLoadersContext context(1, 4, 1);
129
130 Orthanc::WebServiceParameters orthancWebService;
131 orthancWebService.SetUrl(orthancUrl);
132 context.SetOrthancParameters(orthancWebService);
133
134 context.StartOracle();
135
136 {
137
138 boost::shared_ptr<SdlSimpleViewerApplication> application(
139 SdlSimpleViewerApplication::Create(context, viewport));
140
141 OrthancStone::DicomSource source;
142
143 application->LoadOrthancFrame(source, instanceId, frameIndex);
144
145 OrthancStone::DefaultViewportInteractor interactor;
146 interactor.SetWindowingLayer(0);
147
148 {
149 int scancodeCount = 0;
150 const uint8_t* keyboardState = SDL_GetKeyboardState(&scancodeCount);
151
152 bool stop = false;
153 while (!stop)
154 {
155 bool paint = false;
156 SDL_Event event;
157 while (SDL_PollEvent(&event))
158 {
159 if (event.type == SDL_QUIT)
160 {
161 stop = true;
162 break;
163 }
164 else if (viewport->IsRefreshEvent(event))
165 {
166 paint = true;
167 }
168 else if (event.type == SDL_WINDOWEVENT &&
169 (event.window.event == SDL_WINDOWEVENT_RESIZED ||
170 event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED))
171 {
172 viewport->UpdateSize(event.window.data1, event.window.data2);
173 }
174 else if (event.type == SDL_WINDOWEVENT &&
175 (event.window.event == SDL_WINDOWEVENT_SHOWN ||
176 event.window.event == SDL_WINDOWEVENT_EXPOSED))
177 {
178 paint = true;
179 }
180 else if (event.type == SDL_KEYDOWN &&
181 event.key.repeat == 0 /* Ignore key bounce */)
182 {
183 switch (event.key.keysym.sym)
184 {
185 case SDLK_f:
186 viewport->ToggleMaximize();
187 break;
188
189 case SDLK_s:
190 application->FitContent();
191 break;
192
193 case SDLK_q:
194 stop = true;
195 break;
196
197 default:
198 break;
199 }
200 }
201 else if (event.type == SDL_MOUSEBUTTONDOWN ||
202 event.type == SDL_MOUSEMOTION ||
203 event.type == SDL_MOUSEBUTTONUP)
204 {
205 std::unique_ptr<OrthancStone::IViewport::ILock> lock(viewport->Lock());
206 if (lock->HasCompositor())
207 {
208 OrthancStone::PointerEvent p;
209 OrthancStoneHelpers::GetPointerEvent(p, lock->GetCompositor(),
210 event, keyboardState, scancodeCount);
211
212 switch (event.type)
213 {
214 case SDL_MOUSEBUTTONDOWN:
215 lock->GetController().HandleMousePress(interactor, p,
216 lock->GetCompositor().GetCanvasWidth(),
217 lock->GetCompositor().GetCanvasHeight());
218 lock->Invalidate();
219 break;
220
221 case SDL_MOUSEMOTION:
222 if (lock->GetController().HandleMouseMove(p))
223 {
224 lock->Invalidate();
225 }
226 break;
227
228 case SDL_MOUSEBUTTONUP:
229 lock->GetController().HandleMouseRelease(p);
230 lock->Invalidate();
231 break;
232
233 default:
234 throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
235 }
236 }
237 }
238 }
239
240 if (paint)
241 {
242 viewport->Paint();
243 }
244
245 // Small delay to avoid using 100% of CPU
246 SDL_Delay(1);
247 }
248 }
249 context.StopOracle();
250 }
251 }
252
253 OrthancStone::StoneFinalize();
254 return 0;
255 }
256 catch (Orthanc::OrthancException& e)
257 {
258 LOG(ERROR) << "OrthancException: " << e.What();
259 return -1;
260 }
261 catch (OrthancStone::StoneException& e)
262 {
263 LOG(ERROR) << "StoneException: " << e.What();
264 return -1;
265 }
266 catch (std::runtime_error& e)
267 {
268 LOG(ERROR) << "Runtime error: " << e.what();
269 return -1;
270 }
271 catch (...)
272 {
273 LOG(ERROR) << "Native exception";
274 return -1;
275 }
276 }