comparison Samples/Sdl/SimpleViewer/SdlSimpleViewer.cpp @ 1382:9d138883be66

Proper command-line parameter management for SDL sample
author Benjamin Golinvaux <bgo@osimis.io>
date Wed, 22 Apr 2020 19:55:34 +0200
parents 33da5d02885f
children
comparison
equal deleted inserted replaced
1381:f4a06ad1580b 1382:9d138883be66
1 1
2 #include "SdlSimpleViewerApplication.h" 2 #include "SdlSimpleViewerApplication.h"
3
4 #include <string>
5
6 #include <boost/program_options.hpp>
7
8 #include <SDL.h>
3 9
4 #include <Core/OrthancException.h> 10 #include <Core/OrthancException.h>
5 11
6 #include <Framework/Loaders/GenericLoadersContext.h> 12 #include <Framework/Loaders/GenericLoadersContext.h>
7 #include <Framework/StoneException.h> 13 #include <Framework/StoneException.h>
8 #include <Framework/StoneEnumerations.h> 14 #include <Framework/StoneEnumerations.h>
9 #include <Framework/StoneInitialization.h> 15 #include <Framework/StoneInitialization.h>
10 #include <Framework/Viewport/SdlViewport.h> 16 #include <Framework/Viewport/SdlViewport.h>
11 17
12 #include <SDL.h> 18 #include "../SdlHelpers.h"
13 19 #include "../../CommonHelpers.h"
14 namespace OrthancStone 20
21 std::string orthancUrl;
22 std::string instanceId;
23 int frameIndex = 0;
24
25 static void ProcessOptions(int argc, char* argv[])
15 { 26 {
16 static KeyboardModifiers GetKeyboardModifiers(const uint8_t* keyboardState, 27 namespace po = boost::program_options;
17 const int scancodeCount) 28 po::options_description desc("Usage:");
18 { 29
19 int result = KeyboardModifiers_None; 30 desc.add_options()
20 31 ("log_level", po::value<std::string>()->default_value("WARNING"),
21 if (keyboardState != NULL) 32 "You can choose WARNING, INFO or TRACE for the logging level: Errors and warnings will always be displayed. (default: WARNING)")
22 { 33
23 if (SDL_SCANCODE_LSHIFT < scancodeCount && 34 ("orthanc", po::value<std::string>()->default_value("http://localhost:8042"),
24 keyboardState[SDL_SCANCODE_LSHIFT]) 35 "Base URL of the Orthanc instance")
25 { 36
26 result |= KeyboardModifiers_Shift; 37 ("instance", po::value<std::string>()->default_value("285dece8-e1956b38-cdc7d084-6ce3371e-536a9ffc"),
27 } 38 "Orthanc ID of the instance to display")
28 39
29 if (SDL_SCANCODE_RSHIFT < scancodeCount && 40 ("frame_index", po::value<int>()->default_value(0),
30 keyboardState[SDL_SCANCODE_RSHIFT]) 41 "The zero-based index of the frame (for multi-frame instances)")
31 { 42 ;
32 result |= KeyboardModifiers_Shift; 43
33 } 44 po::variables_map vm;
34 45 try
35 if (SDL_SCANCODE_LCTRL < scancodeCount && 46 {
36 keyboardState[SDL_SCANCODE_LCTRL]) 47 po::store(po::parse_command_line(argc, argv, desc), vm);
37 { 48 po::notify(vm);
38 result |= KeyboardModifiers_Control; 49 }
39 } 50 catch (std::exception& e)
40 51 {
41 if (SDL_SCANCODE_RCTRL < scancodeCount && 52 std::cerr << "Please check your command line options! (\"" << e.what() << "\")" << std::endl;
42 keyboardState[SDL_SCANCODE_RCTRL]) 53 }
43 { 54
44 result |= KeyboardModifiers_Control; 55 if (vm.count("log_level") > 0)
45 } 56 {
46 57 std::string logLevel = vm["log_level"].as<std::string>();
47 if (SDL_SCANCODE_LALT < scancodeCount && 58 OrthancStoneHelpers::SetLogLevel(logLevel);
48 keyboardState[SDL_SCANCODE_LALT]) 59 }
49 { 60
50 result |= KeyboardModifiers_Alt; 61 if (vm.count("orthanc") > 0)
51 } 62 {
52 63 // maybe check URL validity here
53 if (SDL_SCANCODE_RALT < scancodeCount && 64 orthancUrl = vm["orthanc"].as<std::string>();
54 keyboardState[SDL_SCANCODE_RALT]) 65 }
55 { 66
56 result |= KeyboardModifiers_Alt; 67 if (vm.count("instance") > 0)
57 } 68 {
58 } 69 instanceId = vm["instance"].as<std::string>();
59 70 }
60 return static_cast<KeyboardModifiers>(result); 71
61 } 72 if (vm.count("frame_index") > 0)
62 73 {
63 74 frameIndex = vm["frame_index"].as<int>();
64 static void GetPointerEvent(PointerEvent& p, 75 }
65 const ICompositor& compositor, 76
66 SDL_Event event, 77 }
67 const uint8_t* keyboardState, 78
68 const int scancodeCount) 79 extern void f()
69 { 80 {
70 KeyboardModifiers modifiers = GetKeyboardModifiers(keyboardState, scancodeCount); 81 std::cout << "f()" << std::endl;
71
72 switch (event.button.button)
73 {
74 case SDL_BUTTON_LEFT:
75 p.SetMouseButton(OrthancStone::MouseButton_Left);
76 break;
77
78 case SDL_BUTTON_RIGHT:
79 p.SetMouseButton(OrthancStone::MouseButton_Right);
80 break;
81
82 case SDL_BUTTON_MIDDLE:
83 p.SetMouseButton(OrthancStone::MouseButton_Middle);
84 break;
85
86 default:
87 p.SetMouseButton(OrthancStone::MouseButton_None);
88 break;
89 }
90
91 p.AddPosition(compositor.GetPixelCenterCoordinates(event.button.x, event.button.y));
92 p.SetAltModifier(modifiers & KeyboardModifiers_Alt);
93 p.SetControlModifier(modifiers & KeyboardModifiers_Control);
94 p.SetShiftModifier(modifiers & KeyboardModifiers_Shift);
95 }
96
97 } 82 }
98 83
99 /** 84 /**
100 * IMPORTANT: The full arguments to "main()" are needed for SDL on 85 * IMPORTANT: The full arguments to "main()" are needed for SDL on
101 * Windows. Otherwise, one gets the linking error "undefined reference 86 * Windows. Otherwise, one gets the linking error "undefined reference
102 * to `SDL_main'". https://wiki.libsdl.org/FAQWindows 87 * to `SDL_main'". https://wiki.libsdl.org/FAQWindows
103 **/ 88 **/
104 int main(int argc, char* argv[]) 89 int main(int argc, char* argv[])
105 { 90 {
91 f();
92
106 try 93 try
107 { 94 {
108 OrthancStone::StoneInitialize(); 95 OrthancStone::StoneInitialize();
109 Orthanc::Logging::EnableInfoLevel(true); 96
97 ProcessOptions(argc, argv);
98
99 //Orthanc::Logging::EnableInfoLevel(true);
110 //Orthanc::Logging::EnableTraceLevel(true); 100 //Orthanc::Logging::EnableTraceLevel(true);
111 101
112 { 102 {
113 103
114 #if 1 104 #if 1
115 boost::shared_ptr<OrthancStone::SdlViewport> viewport = 105 boost::shared_ptr<OrthancStone::SdlViewport> viewport =
116 OrthancStone::SdlOpenGLViewport::Create("Stone of Orthanc", 800, 600); 106 OrthancStone::SdlOpenGLViewport::Create("Stone of Orthanc", 800, 600);
117 #else 107 #else
118 boost::shared_ptr<OrthancStone::SdlViewport> viewport = 108 boost::shared_ptr<OrthancStone::SdlViewport> viewport =
119 OrthancStone::SdlCairoViewport::Create("Stone of Orthanc", 800, 600); 109 OrthancStone::SdlCairoViewport::Create("Stone of Orthanc", 800, 600);
120 #endif 110 #endif
121 111
122 OrthancStone::GenericLoadersContext context(1, 4, 1); 112 OrthancStone::GenericLoadersContext context(1, 4, 1);
123 113
124 context.StartOracle(); 114 context.StartOracle();
125 115
126 { 116 {
127 117
128 boost::shared_ptr<SdlSimpleViewerApplication> application( 118 boost::shared_ptr<SdlSimpleViewerApplication> application(
129 SdlSimpleViewerApplication::Create(context, viewport)); 119 SdlSimpleViewerApplication::Create(context, viewport));
130 120
131 OrthancStone::DicomSource source; 121 OrthancStone::DicomSource source;
132
133 // Default and command-line parameters
134 const char* instanceId = "285dece8-e1956b38-cdc7d084-6ce3371e-536a9ffc";
135 unsigned int frameIndex = 0;
136
137 if (argc == 1)
138 {
139 LOG(ERROR) << "No instanceId supplied. The default of " << instanceId << " will be used. "
140 << "Please supply the Orthanc instance ID of the frame you wish to display then, optionally, "
141 << "the zero-based index of the frame (for multi-frame instances)";
142 // TODO: frame number as second argument...
143 }
144
145 if (argc >= 2)
146 instanceId = argv[1];
147
148 if (argc >= 3)
149 frameIndex = atoi(argv[1]);
150
151 if (argc > 3)
152 {
153 LOG(ERROR) << "Extra arguments ignored!";
154 }
155
156 122
157 application->LoadOrthancFrame(source, instanceId, frameIndex); 123 application->LoadOrthancFrame(source, instanceId, frameIndex);
158 124
159 OrthancStone::DefaultViewportInteractor interactor; 125 OrthancStone::DefaultViewportInteractor interactor;
160 126
177 else if (viewport->IsRefreshEvent(event)) 143 else if (viewport->IsRefreshEvent(event))
178 { 144 {
179 paint = true; 145 paint = true;
180 } 146 }
181 else if (event.type == SDL_WINDOWEVENT && 147 else if (event.type == SDL_WINDOWEVENT &&
182 (event.window.event == SDL_WINDOWEVENT_RESIZED || 148 (event.window.event == SDL_WINDOWEVENT_RESIZED ||
183 event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)) 149 event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED))
184 { 150 {
185 viewport->UpdateSize(event.window.data1, event.window.data2); 151 viewport->UpdateSize(event.window.data1, event.window.data2);
186 } 152 }
187 else if (event.type == SDL_WINDOWEVENT && 153 else if (event.type == SDL_WINDOWEVENT &&
188 (event.window.event == SDL_WINDOWEVENT_SHOWN || 154 (event.window.event == SDL_WINDOWEVENT_SHOWN ||
189 event.window.event == SDL_WINDOWEVENT_EXPOSED)) 155 event.window.event == SDL_WINDOWEVENT_EXPOSED))
190 { 156 {
191 paint = true; 157 paint = true;
192 } 158 }
193 else if (event.type == SDL_KEYDOWN && 159 else if (event.type == SDL_KEYDOWN &&
194 event.key.repeat == 0 /* Ignore key bounce */) 160 event.key.repeat == 0 /* Ignore key bounce */)
217 { 183 {
218 std::auto_ptr<OrthancStone::IViewport::ILock> lock(viewport->Lock()); 184 std::auto_ptr<OrthancStone::IViewport::ILock> lock(viewport->Lock());
219 if (lock->HasCompositor()) 185 if (lock->HasCompositor())
220 { 186 {
221 OrthancStone::PointerEvent p; 187 OrthancStone::PointerEvent p;
222 OrthancStone::GetPointerEvent(p, lock->GetCompositor(), 188 OrthancStoneHelpers::GetPointerEvent(p, lock->GetCompositor(),
223 event, keyboardState, scancodeCount); 189 event, keyboardState, scancodeCount);
224 190
225 switch (event.type) 191 switch (event.type)
226 { 192 {
227 case SDL_MOUSEBUTTONDOWN: 193 case SDL_MOUSEBUTTONDOWN:
228 lock->GetController().HandleMousePress(interactor, p, 194 lock->GetController().HandleMousePress(interactor, p,
265 } 231 }
266 232
267 OrthancStone::StoneFinalize(); 233 OrthancStone::StoneFinalize();
268 return 0; 234 return 0;
269 } 235 }
270 catch (Orthanc::OrthancException & e) 236 catch (Orthanc::OrthancException& e)
271 { 237 {
272 auto test = e.What(); 238 auto test = e.What();
273 fprintf(stdout, test); 239 fprintf(stdout, test);
274 LOG(ERROR) << "OrthancException: " << e.What(); 240 LOG(ERROR) << "OrthancException: " << e.What();
275 return -1; 241 return -1;
276 } 242 }
277 catch (OrthancStone::StoneException & e) 243 catch (OrthancStone::StoneException& e)
278 { 244 {
279 LOG(ERROR) << "StoneException: " << e.What(); 245 LOG(ERROR) << "StoneException: " << e.What();
280 return -1; 246 return -1;
281 } 247 }
282 catch (std::runtime_error & e) 248 catch (std::runtime_error& e)
283 { 249 {
284 LOG(ERROR) << "Runtime error: " << e.what(); 250 LOG(ERROR) << "Runtime error: " << e.what();
285 return -1; 251 return -1;
286 } 252 }
287 catch (...) 253 catch (...)