CaptureFactory.cpp
Go to the documentation of this file.
00001 /*
00002  * This file is part of ALVAR, A Library for Virtual and Augmented Reality.
00003  *
00004  * Copyright 2007-2012 VTT Technical Research Centre of Finland
00005  *
00006  * Contact: VTT Augmented Reality Team <alvar.info@vtt.fi>
00007  *          <http://www.vtt.fi/multimedia/alvar.html>
00008  *
00009  * ALVAR is free software; you can redistribute it and/or modify it under the
00010  * terms of the GNU Lesser General Public License as published by the Free
00011  * Software Foundation; either version 2.1 of the License, or (at your option)
00012  * any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful, but WITHOUT
00015  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00016  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
00017  * for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public License
00020  * along with ALVAR; if not, see
00021  * <http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html>.
00022  */
00023 
00024 #include "CaptureFactory.h"
00025 
00026 #include "CaptureFactory_private.h"
00027 #include "CapturePlugin.h"
00028 #include "DirectoryIterator.h"
00029 
00030 namespace alvar {
00031 
00032 CaptureFactoryPrivate::CaptureFactoryPrivate()
00033     : mPluginPaths()
00034     , mPluginPrefix()
00035     , mPluginPostfix()
00036     , mLoadedAllPlugins(false)
00037     , mPluginMap()
00038     , mCapturePluginMap()
00039 {
00040     setupPluginPaths();
00041 
00042     mPluginPrefix = pluginPrefix();
00043     mPluginPrefix.append("alvarcaptureplugin");
00044 
00045     mPluginPostfix.append(ALVAR_VERSION_NODOTS);
00046     #if _DEBUG
00047         mPluginPostfix.append("d");
00048     #endif
00049     mPluginPostfix.append(".");
00050     mPluginPostfix.append(pluginExtension());
00051 }
00052 
00053 CaptureFactoryPrivate::~CaptureFactoryPrivate()
00054 {
00055     for (CapturePluginMap::iterator itr = mCapturePluginMap.begin(); itr != mCapturePluginMap.end(); itr++) {
00056         delete itr->second;
00057     }
00058     mCapturePluginMap.clear();
00059     mPluginMap.clear();
00060 }
00061 
00062 void CaptureFactoryPrivate::loadPlugins()
00063 {
00064     // ensure that plugins have not already been loaded
00065     if (mLoadedAllPlugins) {
00066         return;
00067     }
00068 
00069     // iterate over search paths
00070     for (PluginPathsVector::iterator itr = mPluginPaths.begin(); itr != mPluginPaths.end(); ++itr) {
00071         DirectoryIterator directory(*itr);
00072 
00073         // iterate over entries in current path
00074         while (directory.hasNext()) {
00075             std::string entry = directory.next();
00076 
00077             // verify that filename matches the plugin convention
00078             int prefixIndex = entry.find(mPluginPrefix);
00079             int postfixIndex = entry.rfind(mPluginPostfix);
00080             if (prefixIndex == -1 || postfixIndex == -1) {
00081                 continue;
00082             }
00083 
00084             // load the actual plugin
00085             entry = entry.substr(mPluginPrefix.size(), postfixIndex - mPluginPrefix.size());
00086             loadPlugin(entry, directory.currentPath());
00087         }
00088     }
00089 
00090     // this should only be done once
00091     mLoadedAllPlugins = true;
00092 }
00093 
00094 void CaptureFactoryPrivate::loadPlugin(const std::string &captureType)
00095 {
00096     // ensure plugin is not alredy loaded
00097     if (mPluginMap.find(captureType) != mPluginMap.end()) {
00098         return;
00099     }
00100 
00101     // iterate over search paths
00102     for (PluginPathsVector::iterator itr = mPluginPaths.begin(); itr != mPluginPaths.end(); ++itr) {
00103         DirectoryIterator directory(*itr);
00104         
00105         // iterate over entries in current path
00106         while (directory.hasNext()) {
00107             std::string entry = directory.next();
00108 
00109             // verify that filename matches the plugin convention
00110             int prefixIndex = entry.find(mPluginPrefix);
00111             int postfixIndex = entry.rfind(mPluginPostfix);
00112             if (prefixIndex == -1 || postfixIndex == -1) {
00113                 continue;
00114             }
00115 
00116             // verify that filename matches capture type
00117             entry = entry.substr(mPluginPrefix.size(), postfixIndex - mPluginPrefix.size());
00118             if (entry != captureType) {
00119                 continue;
00120             }
00121             
00122             // load the actual plugin
00123             loadPlugin(entry, directory.currentPath());
00124 
00125             // stop searching
00126             break;
00127         }
00128     }
00129 }
00130 
00131 void CaptureFactoryPrivate::loadPlugin(const std::string &captureType, const std::string &filename)
00132 {
00133     // ensure plugin is not alredy loaded
00134     if (mPluginMap.find(captureType) != mPluginMap.end()) {
00135         return;
00136     }
00137 
00138     try {
00139         // create and load the plugin
00140         Plugin plugin(filename);
00141 
00142         // register the plugin
00143         // for this to work, each plugin must export the following method
00144         //   extern "C" __declspec(dllexport) void registerPlugin(const std::string &captureType, alvar::CapturePlugin *capturePlugin);
00145         // which creates a new CapturePlugin object: capturePlugin = new MyCapturePlugin(captureType);
00146         typedef void (*RegisterPlugin)(const std::string &captureType, CapturePlugin *&capturePlugin);
00147         RegisterPlugin registerPlugin = (RegisterPlugin)plugin.resolve("registerPlugin");
00148         CapturePlugin *capturePlugin = NULL;
00149         if (registerPlugin) {
00150             registerPlugin(captureType, capturePlugin);
00151         }
00152 
00153         // return if plugin did not create it's capture plugin
00154         if (capturePlugin == NULL) {
00155             return;
00156         }
00157 
00158         // insert the plugin and capture plugin into maps
00159         mPluginMap.insert(PluginMap::value_type(captureType, plugin));
00160         mCapturePluginMap.insert(CapturePluginMap::value_type(captureType, capturePlugin));
00161     }
00162     catch (AlvarException e) {
00163         // if anything fails, simply ignore it...
00164         #if defined(_DEBUG) || !defined(NDEBUG)
00165             std::cout << e.what() << std::endl;
00166         #endif
00167     }
00168 }
00169 
00170 CapturePlugin *CaptureFactoryPrivate::getPlugin(const std::string &captureType)
00171 {
00172     // find CapturePlugin implementation according to capture type
00173     CapturePluginMap::iterator itr;
00174     itr = mCapturePluginMap.find(captureType);
00175 
00176     // if not found, attempt to load plugin
00177     if (itr == mCapturePluginMap.end()) {
00178         loadPlugin(captureType);
00179         itr = mCapturePluginMap.find(captureType);
00180     }
00181 
00182     // return CapturePlugin implementation if found
00183     CapturePlugin *capturePlugin = NULL;
00184     if (itr != mCapturePluginMap.end()) {
00185         capturePlugin = itr->second;
00186     }
00187     return capturePlugin;
00188 }
00189 
00190 
00191 // static class variables instantiation for singleton implementation
00192 CaptureFactory *CaptureFactory::mInstance = NULL;
00193 Mutex CaptureFactory::mMutex;
00194 CaptureFactory::CaptureFactoryDestroyer CaptureFactory::mDestroyer;
00195 
00196 CaptureFactory *CaptureFactory::instance()
00197 {
00198     // do not use double-checked locking
00199     // http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
00200     // use a destroyer class to properly clean up resources
00201     // http://www.research.ibm.com/designpatterns/pubs/ph-jun96.txt
00202     Lock lock(&mMutex);
00203     if (mInstance == NULL) {
00204         mInstance = new CaptureFactory();
00205         mDestroyer.set(mInstance);
00206     }
00207     return mInstance;
00208 }
00209 
00210 CaptureFactory::CaptureFactory()
00211     : d(new CaptureFactoryPrivate())
00212 {
00213 }
00214 
00215 CaptureFactory::~CaptureFactory()
00216 {
00217     delete d;
00218 }
00219 
00220 CaptureFactory::CapturePluginVector CaptureFactory::enumeratePlugins()
00221 {
00222     // load all plugins
00223     d->loadPlugins();
00224 
00225     // return the available plugins as a vector of plugin names
00226     CaptureFactory::CapturePluginVector keys;
00227     for (CaptureFactoryPrivate::PluginMap::iterator itr = d->mPluginMap.begin(); itr != d->mPluginMap.end(); ++itr) {
00228         keys.push_back(itr->first);
00229     }
00230 
00231     return keys;
00232 }
00233 
00234 CaptureFactory::CaptureDeviceVector CaptureFactory::enumerateDevices(const std::string &captureType)
00235 {
00236     CaptureDeviceVector devices;
00237 
00238     // load all plugins and enumerate their devices
00239     if (captureType.empty()) {
00240         d->loadPlugins();
00241         for (CaptureFactoryPrivate::CapturePluginMap::iterator itr = d->mCapturePluginMap.begin(); itr != d->mCapturePluginMap.end(); ++itr) {
00242             CaptureDeviceVector pluginDevices = itr->second->enumerateDevices();
00243             devices.insert(devices.end(), pluginDevices.begin(), pluginDevices.end());
00244         }
00245     }
00246     // only enumerate the devices of one plugin
00247     else {
00248         CapturePlugin *capturePlugin = d->getPlugin(captureType);
00249         if (capturePlugin) {
00250             devices = capturePlugin->enumerateDevices();
00251         }
00252     }
00253 
00254     return devices;
00255 }
00256 
00257 Capture *CaptureFactory::createCapture(const CaptureDevice captureDevice)
00258 {
00259     // get CapturePlugin implementation
00260     CapturePlugin *capturePlugin = d->getPlugin(captureDevice.captureType());
00261 
00262     // create Capture implementation and return
00263     Capture *capture = NULL;
00264     if (capturePlugin) {
00265         capture = capturePlugin->createCapture(captureDevice);
00266     }
00267     return capture;
00268 }
00269 
00270 } // namespace alvar


ar_track_alvar
Author(s): Scott Niekum
autogenerated on Sat Dec 28 2013 16:46:15