Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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.