summaryrefslogtreecommitdiff
path: root/src/imaging/TrackerConfig.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/imaging/TrackerConfig.cpp')
-rw-r--r--src/imaging/TrackerConfig.cpp268
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"));
+}
+
+}