diff options
Diffstat (limited to 'src/imaging/TrackerConfig.cpp')
-rw-r--r-- | src/imaging/TrackerConfig.cpp | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/src/imaging/TrackerConfig.cpp b/src/imaging/TrackerConfig.cpp new file mode 100644 index 0000000..be4c758 --- /dev/null +++ b/src/imaging/TrackerConfig.cpp @@ -0,0 +1,268 @@ +// +// libavg - Media Playback Engine. +// Copyright (C) 2003-2014 Ulrich von Zadow +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Current versions can be found at www.libavg.de + +#include "TrackerConfig.h" +#include "trackerconfigdtd.h" +#include "DeDistort.h" + +#include "../base/XMLHelper.h" +#include "../base/Logger.h" +#include "../base/FileHelper.h" +#include "../base/Exception.h" +#include "../base/StringHelper.h" +#include "../base/ConfigMgr.h" + +#include <libxml/parser.h> +#include <libxml/xmlwriter.h> +#include <libxml/xmlstring.h> + +#include <cstring> +#include <sstream> +#include <iostream> + +using namespace std; + +namespace avg { + +TrackerConfig::TrackerConfig() + : m_Doc(0) +{ +} + +TrackerConfig::TrackerConfig(const TrackerConfig& other) +{ + m_Doc = 0; + if (other.m_Doc) { + m_Doc = xmlCopyDoc(other.m_Doc, true); + m_sFilename = other.m_sFilename; + m_pRoot = xmlDocGetRootElement(m_Doc); + } +} + +TrackerConfig::~TrackerConfig() +{ + xmlFreeDoc(m_Doc); +} + +void TrackerConfig::loadConfigFile(const string& sFilename) +{ + // TODO: There is duplicated code here and in Player::loadFile which belongs + // in a lower-level xml handling class. + registerDTDEntityLoader("trackerconfig.dtd", g_pTrackerConfigDTD); + xmlDtdPtr dtd; + string sDTDFName = "trackerconfig.dtd"; + dtd = xmlParseDTD(NULL, (const xmlChar*) sDTDFName.c_str()); + if (!dtd) { + AVG_LOG_WARNING("DTD not found at " << sDTDFName + << ". Not validating trackerconfig files."); + } + + // xmlParseFile crashes for some reason under Lion. + string sFileContents; + readWholeFile(sFilename, sFileContents); + m_Doc = xmlParseMemory(sFileContents.c_str(), sFileContents.length()); + if (!m_Doc) { + AVG_LOG_ERROR("Could not open tracker config file " << sFilename << + ". Using defaults which will probably not work."); + return; + } + + xmlValidCtxtPtr cvp = xmlNewValidCtxt(); + cvp->error = xmlParserValidityError; + cvp->warning = xmlParserValidityWarning; + int isValid = xmlValidateDtd(cvp, m_Doc, dtd); + xmlFreeValidCtxt(cvp); + if (!isValid) { + throw (Exception(AVG_ERR_XML_PARSE, sFilename + " does not validate.")); + } + + m_pRoot = xmlDocGetRootElement(m_Doc); + xmlFreeDtd(dtd); + m_sFilename = sFilename; + + AVG_TRACE(Logger::category::CONFIG, Logger::severity::INFO, + "Reading Tracker config file from " << sFilename); +} + +void TrackerConfig::load() +{ + // Give precedence to local configuration + string sFName = "avgtrackerrc"; + if (fileExists(sFName) || !fileExists(getGlobalConfigDir() + sFName)) { + loadConfigFile(sFName); + } else { + loadConfigFile(getGlobalConfigDir() + sFName); + } +} + +xmlXPathObjectPtr TrackerConfig::findConfigNodes(const string& sXPathExpr) const +{ + string sFullPath = string("/trackerconfig"+sXPathExpr); + xmlXPathContextPtr xpCtx; + xmlXPathObjectPtr xpElement; + + xpCtx = xmlXPathNewContext(m_Doc); + if(!xpCtx) { + AVG_LOG_ERROR("Unable to create new XPath context"); + return NULL; + } + + xpElement = xmlXPathEvalExpression(BAD_CAST sFullPath.c_str(), xpCtx); + if(!xpElement) { + AVG_LOG_ERROR("Unable to evaluate XPath expression '" + << sFullPath << "'"); + xmlXPathFreeContext(xpCtx); + return NULL; + } + + xmlXPathFreeContext(xpCtx); + + return xpElement; +} + +void TrackerConfig::setParam(const string& sXPathExpr, const string& sValue) +{ + xmlXPathObjectPtr xpElement = findConfigNodes(sXPathExpr); + xmlNodeSetPtr nodes = xpElement->nodesetval; + + if (!nodes || nodes->nodeNr == 0) + throw (Exception(AVG_ERR_OPTION_UNKNOWN, + string("setParam(): cannot find requested element ")+sXPathExpr)); + + for (int i = nodes->nodeNr-1; i >= 0; i--) { + AVG_ASSERT(nodes->nodeTab[i]); + + xmlNodeSetContent(nodes->nodeTab[i], BAD_CAST sValue.c_str()); + if (nodes->nodeTab[i]->type != XML_NAMESPACE_DECL) + nodes->nodeTab[i] = NULL; + } + + xmlXPathFreeObject(xpElement); +} + +string TrackerConfig::getParam(const string& sXPathExpr) const +{ + xmlXPathObjectPtr xpElement = findConfigNodes(sXPathExpr); + xmlNodeSetPtr nodes = xpElement->nodesetval; + + if (!nodes || nodes->nodeNr == 0) { + throw (Exception(AVG_ERR_OPTION_UNKNOWN, + string("getParam(): cannot find requested element ")+sXPathExpr)); + } else if (nodes->nodeNr > 1) { + AVG_LOG_WARNING( + "getParam(): expression selects more than one node. Returning the first."); + } + + xmlChar* xsRc = xmlNodeGetContent(nodes->nodeTab[0]); + string sValue((char *)xsRc); + + xmlFree(xsRc); + xmlXPathFreeObject(xpElement); + + return sValue; +} + +bool TrackerConfig::getBoolParam(const std::string& sXPathExpr) const +{ + return stringToBool(getParam(sXPathExpr)); +} + +int TrackerConfig::getIntParam(const std::string& sXPathExpr) const +{ + return stringToInt(getParam(sXPathExpr)); +} + +float TrackerConfig::getFloatParam(const std::string& sXPathExpr) const +{ + return stringToFloat(getParam(sXPathExpr)); +} + +glm::vec2 TrackerConfig::getPointParam(const std::string& sXPathExpr) const +{ + return glm::vec2(getFloatParam(sXPathExpr+"@x"), getFloatParam(sXPathExpr+"@y")); +} + +FRect TrackerConfig::getRectParam(const std::string& sXPathExpr) const +{ + glm::vec2 pos1 = glm::vec2(getFloatParam(sXPathExpr+"@x1"), + getFloatParam(sXPathExpr+"@y1")); + glm::vec2 pos2 = glm::vec2(getFloatParam(sXPathExpr+"@x2"), + getFloatParam(sXPathExpr+"@y2")); + return FRect(pos1, pos2); +} + +xmlNodePtr TrackerConfig::getXmlNode(const std::string& sXPathExpr) const +{ + xmlXPathObjectPtr xpElement = findConfigNodes(sXPathExpr); + xmlNodeSetPtr nodes = xpElement->nodesetval; + + if (!nodes || nodes->nodeNr == 0) { + throw (Exception(AVG_ERR_OPTION_UNKNOWN, + string("getParam(): cannot find requested element ")+sXPathExpr)); + } else if (nodes->nodeNr > 1) { + AVG_LOG_WARNING( + "getXmlNode(): expression selects more than one node. Returning the first."); + } + return nodes->nodeTab[0]; +} + +DeDistortPtr TrackerConfig::getTransform() const +{ + glm::vec2 CameraExtents = getPointParam("/camera/size/"); + DeDistortPtr pDD(new DeDistort); + pDD->load(CameraExtents, *this); + return pDD; +} + +void TrackerConfig::setTransform(DeDistortPtr pDeDistort) +{ + pDeDistort->save(*this); +} + +void TrackerConfig::dump() const +{ + string s; + xmlBufferPtr pBuffer = xmlBufferCreate(); + xmlNodeDump(pBuffer, m_Doc, m_pRoot, 0, 0); + cerr << xmlBufferContent(pBuffer) << endl; +} + +void TrackerConfig::save() +{ + AVG_TRACE(Logger::category::CONFIG, Logger::severity::INFO, + "Saving tracker configuration to " << m_sFilename << "."); + + if (m_Doc) { + if (fileExists(m_sFilename)) { + string sBakFile = m_sFilename + ".bak"; + unlink(sBakFile.c_str()); + if (rename(m_sFilename.c_str(), sBakFile.c_str())) { + AVG_LOG_WARNING("Cannot create tracker config backup. Backing " + "it up on current workdir."); + copyFile(m_sFilename, "avgtrackerrc.bak"); + } + } + xmlSaveFileEnc(m_sFilename.c_str(), m_Doc, "utf-8"); + } else + throw (Exception(AVG_ERR_FILEIO, + "save(): tracker configuration not initialized")); +} + +} |