CaptureFactory.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ALVAR, A Library for Virtual and Augmented Reality.
3  *
4  * Copyright 2007-2012 VTT Technical Research Centre of Finland
5  *
6  * Contact: VTT Augmented Reality Team <alvar.info@vtt.fi>
7  * <http://www.vtt.fi/multimedia/alvar.html>
8  *
9  * ALVAR is free software; you can redistribute it and/or modify it under the
10  * terms of the GNU Lesser General Public License as published by the Free
11  * Software Foundation; either version 2.1 of the License, or (at your option)
12  * any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
17  * for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with ALVAR; if not, see
21  * <http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html>.
22  */
23 
25 
29 
30 namespace alvar {
31 
33  : mPluginPaths()
34  , mPluginPrefix()
35  , mPluginPostfix()
36  , mLoadedAllPlugins(false)
37  , mPluginMap()
38  , mCapturePluginMap()
39 {
41 
43  mPluginPrefix.append("alvarcaptureplugin");
44 
46  #if _DEBUG
47  mPluginPostfix.append("d");
48  #endif
49  mPluginPostfix.append(".");
51 }
52 
54 {
55  for (CapturePluginMap::iterator itr = mCapturePluginMap.begin(); itr != mCapturePluginMap.end(); itr++) {
56  delete itr->second;
57  }
58  mCapturePluginMap.clear();
59  mPluginMap.clear();
60 }
61 
63 {
64  // ensure that plugins have not already been loaded
65  if (mLoadedAllPlugins) {
66  return;
67  }
68 
69  // iterate over search paths
70  for (PluginPathsVector::iterator itr = mPluginPaths.begin(); itr != mPluginPaths.end(); ++itr) {
71  DirectoryIterator directory(*itr);
72 
73  // iterate over entries in current path
74  while (directory.hasNext()) {
75  std::string entry = directory.next();
76 
77  // verify that filename matches the plugin convention
78  int prefixIndex = entry.find(mPluginPrefix);
79  int postfixIndex = entry.rfind(mPluginPostfix);
80  if (prefixIndex == -1 || postfixIndex == -1) {
81  continue;
82  }
83 
84  // load the actual plugin
85  entry = entry.substr(mPluginPrefix.size(), postfixIndex - mPluginPrefix.size());
86  loadPlugin(entry, directory.currentPath());
87  }
88  }
89 
90  // this should only be done once
91  mLoadedAllPlugins = true;
92 }
93 
94 void CaptureFactoryPrivate::loadPlugin(const std::string &captureType)
95 {
96  // ensure plugin is not alredy loaded
97  if (mPluginMap.find(captureType) != mPluginMap.end()) {
98  return;
99  }
100 
101  // iterate over search paths
102  for (PluginPathsVector::iterator itr = mPluginPaths.begin(); itr != mPluginPaths.end(); ++itr) {
103  DirectoryIterator directory(*itr);
104 
105  // iterate over entries in current path
106  while (directory.hasNext()) {
107  std::string entry = directory.next();
108 
109  // verify that filename matches the plugin convention
110  int prefixIndex = entry.find(mPluginPrefix);
111  int postfixIndex = entry.rfind(mPluginPostfix);
112  if (prefixIndex == -1 || postfixIndex == -1) {
113  continue;
114  }
115 
116  // verify that filename matches capture type
117  entry = entry.substr(mPluginPrefix.size(), postfixIndex - mPluginPrefix.size());
118  if (entry != captureType) {
119  continue;
120  }
121 
122  // load the actual plugin
123  loadPlugin(entry, directory.currentPath());
124 
125  // stop searching
126  break;
127  }
128  }
129 }
130 
131 void CaptureFactoryPrivate::loadPlugin(const std::string &captureType, const std::string &filename)
132 {
133  // ensure plugin is not alredy loaded
134  if (mPluginMap.find(captureType) != mPluginMap.end()) {
135  return;
136  }
137 
138  try {
139  // create and load the plugin
140  Plugin plugin(filename);
141 
142  // register the plugin
143  // for this to work, each plugin must export the following method
144  // extern "C" __declspec(dllexport) void registerPlugin(const std::string &captureType, alvar::CapturePlugin *capturePlugin);
145  // which creates a new CapturePlugin object: capturePlugin = new MyCapturePlugin(captureType);
146  typedef void (*RegisterPlugin)(const std::string &captureType, CapturePlugin *&capturePlugin);
147  RegisterPlugin registerPlugin = (RegisterPlugin)plugin.resolve("registerPlugin");
148  CapturePlugin *capturePlugin = NULL;
149  if (registerPlugin) {
150  registerPlugin(captureType, capturePlugin);
151  }
152 
153  // return if plugin did not create it's capture plugin
154  if (capturePlugin == NULL) {
155  return;
156  }
157 
158  // insert the plugin and capture plugin into maps
159  mPluginMap.insert(PluginMap::value_type(captureType, plugin));
160  mCapturePluginMap.insert(CapturePluginMap::value_type(captureType, capturePlugin));
161  }
162  catch (AlvarException e) {
163  // if anything fails, simply ignore it...
164  #if defined(_DEBUG) || !defined(NDEBUG)
165  std::cout << e.what() << std::endl;
166  #endif
167  }
168 }
169 
170 CapturePlugin *CaptureFactoryPrivate::getPlugin(const std::string &captureType)
171 {
172  // find CapturePlugin implementation according to capture type
173  CapturePluginMap::iterator itr;
174  itr = mCapturePluginMap.find(captureType);
175 
176  // if not found, attempt to load plugin
177  if (itr == mCapturePluginMap.end()) {
178  loadPlugin(captureType);
179  itr = mCapturePluginMap.find(captureType);
180  }
181 
182  // return CapturePlugin implementation if found
183  CapturePlugin *capturePlugin = NULL;
184  if (itr != mCapturePluginMap.end()) {
185  capturePlugin = itr->second;
186  }
187  return capturePlugin;
188 }
189 
190 
191 // static class variables instantiation for singleton implementation
195 
197 {
198  // do not use double-checked locking
199  // http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
200  // use a destroyer class to properly clean up resources
201  // http://www.research.ibm.com/designpatterns/pubs/ph-jun96.txt
202  Lock lock(&mMutex);
203  if (mInstance == NULL) {
204  mInstance = new CaptureFactory();
205  mDestroyer.set(mInstance);
206  }
207  return mInstance;
208 }
209 
211  : d(new CaptureFactoryPrivate())
212 {
213 }
214 
216 {
217  delete d;
218 }
219 
221 {
222  // load all plugins
223  d->loadPlugins();
224 
225  // return the available plugins as a vector of plugin names
227  for (CaptureFactoryPrivate::PluginMap::iterator itr = d->mPluginMap.begin(); itr != d->mPluginMap.end(); ++itr) {
228  keys.push_back(itr->first);
229  }
230 
231  return keys;
232 }
233 
235 {
236  CaptureDeviceVector devices;
237 
238  // load all plugins and enumerate their devices
239  if (captureType.empty()) {
240  d->loadPlugins();
241  for (CaptureFactoryPrivate::CapturePluginMap::iterator itr = d->mCapturePluginMap.begin(); itr != d->mCapturePluginMap.end(); ++itr) {
242  CaptureDeviceVector pluginDevices = itr->second->enumerateDevices();
243  devices.insert(devices.end(), pluginDevices.begin(), pluginDevices.end());
244  }
245  }
246  // only enumerate the devices of one plugin
247  else {
248  CapturePlugin *capturePlugin = d->getPlugin(captureType);
249  if (capturePlugin) {
250  devices = capturePlugin->enumerateDevices();
251  }
252  }
253 
254  return devices;
255 }
256 
258 {
259  // get CapturePlugin implementation
260  CapturePlugin *capturePlugin = d->getPlugin(captureDevice.captureType());
261 
262  // create Capture implementation and return
263  Capture *capture = NULL;
264  if (capturePlugin) {
265  capture = capturePlugin->createCapture(captureDevice);
266  }
267  return capture;
268 }
269 
270 } // namespace alvar
Main ALVAR namespace.
Definition: Alvar.h:174
Capture * createCapture(const CaptureDevice captureDevice)
Create Capture class. Transfers onwership to the caller.
CaptureFactoryDestroyer for deleting the CaptureFactory singleton.
Mutex for synchronizing multiple threads.
Definition: Mutex.h:44
CaptureFactoryPrivate * d
CaptureFactory for creating Capture classes.
static CaptureFactory * instance()
The singleton instance of CaptureFactory.
static const char * ALVAR_VERSION_NODOTS
Entire version string without dots.
Definition: Alvar.h:213
CapturePlugin * getPlugin(const std::string &captureType)
~CaptureFactory()
Destructor.
std::vector< CaptureDevice > CaptureDeviceVector
Vector of CaptureDevices.
bool hasNext()
Verifies if another entry exist in the directory.
Plugin for loading dynamic libraries.
Definition: Plugin.h:47
std::string captureType() const
The type of capture backend.
std::vector< std::string > CapturePluginVector
Vector of strings.
CaptureDevice holder for camera information.
Definition: CaptureDevice.h:44
static CaptureFactory * mInstance
std::string currentPath()
Returns the path of the current entry.
This file implements a capture plugin interface.
std::string next()
Advances the iterator and returns the name of the next entry.
This file implements a directory iterator.
CapturePlugin interface that plugins must implement.
Definition: CapturePlugin.h:44
CaptureDeviceVector enumerateDevices(const std::string &captureType="")
Enumerate capture devices currently available.
Lock for simplifying mutex handling.
Definition: Lock.h:46
ALVAR exception class.
void loadPlugin(const std::string &captureType)
This file implements a capture factory with a plugin interface to allow for different capture backend...
CapturePluginVector enumeratePlugins()
Enumerate capture plugins currently available.
void registerPlugin(const std::string &class_name, const std::string &base_class_name)
Drawable d[32]
Capture interface that plugins must implement.
Definition: Capture.h:46
virtual CaptureDeviceVector enumerateDevices()=0
Enumerate capture devices currently available.
DirectoryIterator for iterating over files and directories.
static CaptureFactoryDestroyer mDestroyer
void * resolve(const char *symbol)
Resolves the address of a symbol.
Definition: Plugin.cpp:61
virtual Capture * createCapture(const CaptureDevice captureDevice)=0
Create Capture class. Transfers onwership to the caller.


ar_track_alvar
Author(s): Scott Niekum
autogenerated on Mon Jun 10 2019 12:47:03