Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkCoreActivator.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include "mitkCoreActivator.h"
18 
19 // File IO
22 #include <mitkIOMimeTypes.h>
23 #include <mitkIOUtil.h>
24 #include <mitkImageVtkLegacyIO.h>
25 #include <mitkImageVtkXmlIO.h>
26 #include <mitkItkImageIO.h>
27 #include <mitkMimeTypeProvider.h>
30 #include <mitkRawImageFileReader.h>
31 #include <mitkSurfaceStlIO.h>
32 #include <mitkSurfaceVtkLegacyIO.h>
33 #include <mitkSurfaceVtkXmlIO.h>
34 
37 #include <mitkFileWriter.h>
38 
39 #include <itkGDCMImageIO.h>
40 #include <itkNiftiImageIO.h>
41 
42 // Micro Services
43 #include <usGetModuleContext.h>
44 #include <usModule.h>
45 #include <usModuleActivator.h>
46 #include <usModuleContext.h>
47 #include <usModuleEvent.h>
48 #include <usModuleInitialization.h>
49 #include <usModuleResource.h>
50 #include <usModuleResourceStream.h>
51 #include <usModuleSettings.h>
52 #include <usServiceTracker.h>
53 
54 // ITK "injects" static initialization code for IO factories
55 // via the itkImageIOFactoryRegisterManager.h header (which
56 // is generated in the application library build directory).
57 // To ensure that the code is called *before* the CppMicroServices
58 // static initialization code (which triggers the Activator::Start
59 // method), we include the ITK header here.
61 
62 void HandleMicroServicesMessages(us::MsgType type, const char *msg)
63 {
64  switch (type)
65  {
66  case us::DebugMsg:
67  MITK_DEBUG << msg;
68  break;
69  case us::InfoMsg:
70  MITK_INFO << msg;
71  break;
72  case us::WarningMsg:
73  MITK_WARN << msg;
74  break;
75  case us::ErrorMsg:
76  MITK_ERROR << msg;
77  break;
78  }
79 }
80 
81 void AddMitkAutoLoadPaths(const std::string &programPath)
82 {
84 #ifdef __APPLE__
85  // Walk up three directories since that is where the .dylib files are located
86  // for build trees.
87  std::string additionalPath = programPath;
88  bool addPath = true;
89  for (int i = 0; i < 3; ++i)
90  {
91  std::size_t index = additionalPath.find_last_of('/');
92  if (index != std::string::npos)
93  {
94  additionalPath = additionalPath.substr(0, index);
95  }
96  else
97  {
98  addPath = false;
99  break;
100  }
101  }
102  if (addPath)
103  {
104  us::ModuleSettings::AddAutoLoadPath(additionalPath);
105  }
106 #endif
107 }
108 
109 class ShaderRepositoryTracker : public us::ServiceTracker<mitk::IShaderRepository>
110 {
111 public:
112  ShaderRepositoryTracker() : Superclass(us::GetModuleContext()) {}
113  virtual void Close() override
114  {
115  us::GetModuleContext()->RemoveModuleListener(this, &ShaderRepositoryTracker::HandleModuleEvent);
117  }
118 
119  virtual void Open() override
120  {
121  us::GetModuleContext()->AddModuleListener(this, &ShaderRepositoryTracker::HandleModuleEvent);
123  }
124 
125 private:
127 
128  TrackedType AddingService(const ServiceReferenceType &reference) override
129  {
130  mitk::IShaderRepository *shaderRepo = Superclass::AddingService(reference);
131  if (shaderRepo)
132  {
133  // Add all existing shaders from modules to the new shader repository.
134  // If the shader repository is registered in a modules activator, the
135  // GetLoadedModules() function call below will also return the module
136  // which is currently registering the repository. The HandleModuleEvent
137  // method contains code to avoid double registrations due to a fired
138  // ModuleEvent::LOADED event after the activators Load() method finished.
139  std::vector<us::Module *> modules = us::ModuleRegistry::GetLoadedModules();
140  for (std::vector<us::Module *>::const_iterator iter = modules.begin(), endIter = modules.end(); iter != endIter;
141  ++iter)
142  {
143  this->AddModuleShaderToRepository(*iter, shaderRepo);
144  }
145 
146  m_ShaderRepositories.push_back(shaderRepo);
147  }
148  return shaderRepo;
149  }
150 
151  void RemovedService(const ServiceReferenceType & /*reference*/, TrackedType tracked) override
152  {
153  m_ShaderRepositories.erase(std::remove(m_ShaderRepositories.begin(), m_ShaderRepositories.end(), tracked),
154  m_ShaderRepositories.end());
155  }
156 
157  void HandleModuleEvent(const us::ModuleEvent moduleEvent)
158  {
159  if (moduleEvent.GetType() == us::ModuleEvent::LOADED)
160  {
161  std::vector<mitk::IShaderRepository *> shaderRepos;
162  for (std::map<mitk::IShaderRepository *, std::map<long, std::vector<int>>>::const_iterator
163  shaderMapIter = m_ModuleIdToShaderIds.begin(),
164  shaderMapEndIter = m_ModuleIdToShaderIds.end();
165  shaderMapIter != shaderMapEndIter;
166  ++shaderMapIter)
167  {
168  if (shaderMapIter->second.find(moduleEvent.GetModule()->GetModuleId()) == shaderMapIter->second.end())
169  {
170  shaderRepos.push_back(shaderMapIter->first);
171  }
172  }
173  AddModuleShadersToRepositories(moduleEvent.GetModule(), shaderRepos);
174  }
175  else if (moduleEvent.GetType() == us::ModuleEvent::UNLOADED)
176  {
177  RemoveModuleShadersFromRepositories(moduleEvent.GetModule(), m_ShaderRepositories);
178  }
179  }
180 
181  void AddModuleShadersToRepositories(us::Module *module, const std::vector<mitk::IShaderRepository *> &shaderRepos)
182  {
183  // search and load shader files
184  std::vector<us::ModuleResource> shaderResources = module->FindResources("Shaders", "*.xml", true);
185  for (std::vector<us::ModuleResource>::iterator i = shaderResources.begin(); i != shaderResources.end(); ++i)
186  {
187  if (*i)
188  {
190  for (const auto &shaderRepo : shaderRepos)
191  {
192  int id = (shaderRepo)->LoadShader(rs, i->GetBaseName());
193  if (id >= 0)
194  {
195  m_ModuleIdToShaderIds[shaderRepo][module->GetModuleId()].push_back(id);
196  }
197  }
198  rs.seekg(0, std::ios_base::beg);
199  }
200  }
201  }
202 
203  void AddModuleShaderToRepository(us::Module *module, mitk::IShaderRepository *shaderRepo)
204  {
205  std::vector<mitk::IShaderRepository *> shaderRepos;
206  shaderRepos.push_back(shaderRepo);
207  this->AddModuleShadersToRepositories(module, shaderRepos);
208  }
209 
210  void RemoveModuleShadersFromRepositories(us::Module *module,
211  const std::vector<mitk::IShaderRepository *> &shaderRepos)
212  {
213  for (const auto &shaderRepo : shaderRepos)
214  {
215  std::map<long, std::vector<int>> &moduleIdToShaderIds = m_ModuleIdToShaderIds[shaderRepo];
216  std::map<long, std::vector<int>>::iterator shaderIdsIter = moduleIdToShaderIds.find(module->GetModuleId());
217  if (shaderIdsIter != moduleIdToShaderIds.end())
218  {
219  for (std::vector<int>::iterator idIter = shaderIdsIter->second.begin(); idIter != shaderIdsIter->second.end();
220  ++idIter)
221  {
222  (shaderRepo)->UnloadShader(*idIter);
223  }
224  moduleIdToShaderIds.erase(shaderIdsIter);
225  }
226  }
227  }
228 
229 private:
230  // Maps to each shader repository a map containing module ids and related
231  // shader registration ids
232  std::map<mitk::IShaderRepository *, std::map<long, std::vector<int>>> m_ModuleIdToShaderIds;
233  std::vector<mitk::IShaderRepository *> m_ShaderRepositories;
234 };
235 
236 class FixedNiftiImageIO : public itk::NiftiImageIO
237 {
238 public:
240  typedef FixedNiftiImageIO Self;
241  typedef itk::NiftiImageIO Superclass;
243 
245  itkNewMacro(Self)
246 
247 
248  itkTypeMacro(FixedNiftiImageIO, Superclass)
249 
250  virtual bool SupportsDimension(unsigned long dim) override
251  {
252  return dim > 1 && dim < 5;
253  }
254 };
255 
256 void MitkCoreActivator::Load(us::ModuleContext *context)
257 {
258  // Handle messages from CppMicroServices
260 
261  this->m_Context = context;
262 
263  // Add the current application directory to the auto-load paths.
264  // This is useful for third-party executables.
265  std::string programPath = mitk::IOUtil::GetProgramPath();
266  if (programPath.empty())
267  {
268  MITK_WARN << "Could not get the program path.";
269  }
270  else
271  {
272  AddMitkAutoLoadPaths(programPath);
273  }
274 
275  m_ShaderRepositoryTracker.reset(new ShaderRepositoryTracker);
276 
277  // m_RenderingManager = mitk::RenderingManager::New();
278  // context->RegisterService<mitk::RenderingManager>(renderingManager.GetPointer());
279  m_PlanePositionManager.reset(new mitk::PlanePositionManagerService);
280  context->RegisterService<mitk::PlanePositionManagerService>(m_PlanePositionManager.get());
281 
282  m_PropertyAliases.reset(new mitk::PropertyAliases);
283  context->RegisterService<mitk::IPropertyAliases>(m_PropertyAliases.get());
284 
285  m_PropertyDescriptions.reset(new mitk::PropertyDescriptions);
286  context->RegisterService<mitk::IPropertyDescriptions>(m_PropertyDescriptions.get());
287 
288  m_PropertyExtensions.reset(new mitk::PropertyExtensions);
289  context->RegisterService<mitk::IPropertyExtensions>(m_PropertyExtensions.get());
290 
291  m_PropertyFilters.reset(new mitk::PropertyFilters);
292  context->RegisterService<mitk::IPropertyFilters>(m_PropertyFilters.get());
293 
294  m_PropertyPersistence.reset(new mitk::PropertyPersistence);
295  context->RegisterService<mitk::IPropertyPersistence>(m_PropertyPersistence.get());
296 
297  m_MimeTypeProvider.reset(new mitk::MimeTypeProvider);
298  m_MimeTypeProvider->Start();
299  m_MimeTypeProviderReg = context->RegisterService<mitk::IMimeTypeProvider>(m_MimeTypeProvider.get());
300 
301  this->RegisterDefaultMimeTypes();
302  this->RegisterItkReaderWriter();
303  this->RegisterVtkReaderWriter();
304 
305  // Add custom Reader / Writer Services
306  m_FileReaders.push_back(new mitk::PointSetReaderService());
307  m_FileWriters.push_back(new mitk::PointSetWriterService());
308  m_FileReaders.push_back(new mitk::GeometryDataReaderService());
309  m_FileWriters.push_back(new mitk::GeometryDataWriterService());
310  m_FileReaders.push_back(new mitk::DicomSeriesReaderService());
311  m_FileReaders.push_back(new mitk::RawImageFileReaderService());
312 
313  m_ShaderRepositoryTracker->Open();
314 
315  /*
316  There IS an option to exchange ALL vtkTexture instances against vtkNeverTranslucentTextureFactory.
317  This code is left here as a reminder, just in case we might need to do that some time.
318 
319  vtkNeverTranslucentTextureFactory* textureFactory = vtkNeverTranslucentTextureFactory::New();
320  vtkObjectFactory::RegisterFactory( textureFactory );
321  textureFactory->Delete();
322  */
323 
324  this->RegisterLegacyWriter();
325 }
326 
327 void MitkCoreActivator::Unload(us::ModuleContext *)
328 {
329  for (auto &elem : m_FileReaders)
330  {
331  delete elem;
332  }
333 
334  for (auto &elem : m_FileWriters)
335  {
336  delete elem;
337  }
338 
339  for (auto &elem : m_FileIOs)
340  {
341  delete elem;
342  }
343 
344  for (auto &elem : m_LegacyWriters)
345  {
346  delete elem;
347  }
348 
349  // The mitk::ModuleContext* argument of the Unload() method
350  // will always be 0 for the Mitk library. It makes no sense
351  // to use it at this stage anyway, since all libraries which
352  // know about the module system have already been unloaded.
353 
354  // we need to close the internal service tracker of the
355  // MimeTypeProvider class here. Otherwise it
356  // would hold on to the ModuleContext longer than it is
357  // actually valid.
358  m_MimeTypeProviderReg.Unregister();
359  m_MimeTypeProvider->Stop();
360 
361  for (std::vector<mitk::CustomMimeType *>::const_iterator mimeTypeIter = m_DefaultMimeTypes.begin(),
362  iterEnd = m_DefaultMimeTypes.end();
363  mimeTypeIter != iterEnd;
364  ++mimeTypeIter)
365  {
366  delete *mimeTypeIter;
367  }
368 
369  m_ShaderRepositoryTracker->Close();
370 }
371 
372 void MitkCoreActivator::RegisterDefaultMimeTypes()
373 {
374  // Register some default mime-types
375 
376  std::vector<mitk::CustomMimeType *> mimeTypes = mitk::IOMimeTypes::Get();
377  for (std::vector<mitk::CustomMimeType *>::const_iterator mimeTypeIter = mimeTypes.begin(), iterEnd = mimeTypes.end();
378  mimeTypeIter != iterEnd;
379  ++mimeTypeIter)
380  {
381  m_DefaultMimeTypes.push_back(*mimeTypeIter);
382  m_Context->RegisterService(m_DefaultMimeTypes.back());
383  }
384 }
385 
386 void MitkCoreActivator::RegisterItkReaderWriter()
387 {
388  std::list<itk::LightObject::Pointer> allobjects = itk::ObjectFactoryBase::CreateAllInstance("itkImageIOBase");
389 
390  for (auto &allobject : allobjects)
391  {
392  itk::ImageIOBase *io = dynamic_cast<itk::ImageIOBase *>(allobject.GetPointer());
393 
394  // NiftiImageIO does not provide a correct "SupportsDimension()" methods
395  // and the supported read/write extensions are not ordered correctly
396  if (dynamic_cast<itk::NiftiImageIO *>(io))
397  continue;
398 
399  // Use a custom mime-type for GDCMImageIO below
400  if (dynamic_cast<itk::GDCMImageIO *>(allobject.GetPointer()))
401  {
402  // MITK provides its own DICOM reader (which internally uses GDCMImageIO).
403  continue;
404  }
405 
406  if (io)
407  {
408  m_FileIOs.push_back(new mitk::ItkImageIO(io));
409  }
410  else
411  {
412  MITK_WARN << "Error ImageIO factory did not return an ImageIOBase: " << (allobject)->GetNameOfClass();
413  }
414  }
415 
417  mitk::ItkImageIO *niftiIO = new mitk::ItkImageIO(mitk::IOMimeTypes::NIFTI_MIMETYPE(), itkNiftiIO.GetPointer(), 0);
418  m_FileIOs.push_back(niftiIO);
419 }
420 
421 void MitkCoreActivator::RegisterVtkReaderWriter()
422 {
423  m_FileIOs.push_back(new mitk::SurfaceVtkXmlIO());
424  m_FileIOs.push_back(new mitk::SurfaceStlIO());
425  m_FileIOs.push_back(new mitk::SurfaceVtkLegacyIO());
426 
427  m_FileIOs.push_back(new mitk::ImageVtkXmlIO());
428  m_FileIOs.push_back(new mitk::ImageVtkLegacyIO());
429 }
430 
431 void MitkCoreActivator::RegisterLegacyWriter()
432 {
433  std::list<itk::LightObject::Pointer> allobjects = itk::ObjectFactoryBase::CreateAllInstance("IOWriter");
434 
435  for (std::list<itk::LightObject::Pointer>::iterator i = allobjects.begin(); i != allobjects.end(); ++i)
436  {
437  mitk::FileWriter::Pointer io = dynamic_cast<mitk::FileWriter *>(i->GetPointer());
438  if (io)
439  {
440  std::string description = std::string("Legacy ") + io->GetNameOfClass() + " Writer";
441  mitk::IFileWriter *writer = new mitk::LegacyFileWriterService(io, description);
442  m_LegacyWriters.push_back(writer);
443  }
444  else
445  {
446  MITK_ERROR << "Error IOWriter override is not of type mitk::FileWriter: " << (*i)->GetNameOfClass() << std::endl;
447  }
448  }
449 }
450 
452 
453 // Call CppMicroservices initialization code at the end of the file.
454 // This especially ensures that VTK object factories have already
455 // been registered (VTK initialization code is injected by implicitly
456 // include VTK header files at the top of this file).
Interface of property aliases service.
itk::SmartPointer< Self > Pointer
static std::vector< CustomMimeType * > Get()
#define MITK_INFO
Definition: mitkLogMacros.h:22
void RemoveModuleListener(const ModuleListener &delegate)
void Load(us::ModuleContext *context) override
static void AddAutoLoadPath(const std::string &path)
#define MITK_ERROR
Definition: mitkLogMacros.h:24
#define MITK_DEBUG
Definition: mitkLogMacros.h:26
void RemovedService(const ServiceReferenceType &reference, T service)
Interface of property extensions service.
itkEventMacroDeclaration(FocusChangedEvent, itk::AnyEvent) class MITKCORE_EXPORT TestingRenderingManager typedef RenderingManager Superclass
virtual void Close()
#define US_INITIALIZE_MODULE
Creates initialization code for a module.
void Unload(us::ModuleContext *) override
T AddingService(const ServiceReferenceType &reference)
Interface of property descriptions service.
Module * GetModule() const
#define MITK_WARN
Definition: mitkLogMacros.h:23
Management class for vtkShader XML descriptions.
The IMimeTypeProvider service interface allows to query all registered mime types.
Interface class of writers that write data to files.
static CustomMimeType NIFTI_MIMETYPE()
static std::vector< Module * > GetLoadedModules()
virtual void Open()
Type GetType() const
static std::string GetProgramPath()
Definition: mitkIOUtil.cpp:350
Interface of property persistence service.
MsgHandler installMsgHandler(MsgHandler h)
Definition: usUtils.cpp:263
MITKMATCHPOINTREGISTRATION_EXPORT ResultImageType::Pointer map(const InputImageType *input, const RegistrationType *registration, bool throwOnOutOfInputAreaError=false, const double &paddingValue=0, const ResultImageGeometryType *resultGeometry=NULL, bool throwOnMappingError=true, const double &errorValue=0, mitk::ImageMappingInterpolator::Type interpolatorType=mitk::ImageMappingInterpolator::Linear)
void AddModuleListener(const ModuleListener &delegate)
void HandleMicroServicesMessages(us::MsgType type, const char *msg)
std::vector< ModuleResource > FindResources(const std::string &path, const std::string &filePattern, bool recurse) const
Definition: usModule.cpp:278
Interface of property filters service.
void AddMitkAutoLoadPaths(const std::string &programPath)
The common interface of all MITK file writers.
static ModuleContext * GetModuleContext()
Returns the module context of the calling module.
long GetModuleId() const
Definition: usModule.cpp:211
US_EXPORT_MODULE_ACTIVATOR(mitk::SimulationActivator)
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.