summaryrefslogtreecommitdiff
path: root/src/base
diff options
context:
space:
mode:
authorDimitri John Ledkov <xnox@ubuntu.com>2014-06-24 20:05:13 +0100
committerDimitri John Ledkov <xnox@ubuntu.com>2014-06-24 20:05:13 +0100
commitdd22bd15f6ed3e5eb5c77ab427029be50fe20148 (patch)
treed9491ee40d80688b7f5b1f20504f022686827a57 /src/base
libavg (1.8.1-1) unstable; urgency=medium
* New upstream release (Closes: #739664) * Mark libdc1394-22-dev as linux-any build-dependency. * Add libvdpau-dev build-dependency. * Add libavresample-dev build-dependency. # imported from the archive
Diffstat (limited to 'src/base')
-rw-r--r--src/base/Backtrace.cpp120
-rw-r--r--src/base/Backtrace.h36
-rw-r--r--src/base/BezierCurve.cpp56
-rw-r--r--src/base/BezierCurve.h56
-rw-r--r--src/base/CmdQueue.h56
-rw-r--r--src/base/Command.h56
-rw-r--r--src/base/ConfigMgr.cpp361
-rw-r--r--src/base/ConfigMgr.h93
-rw-r--r--src/base/CubicSpline.cpp104
-rw-r--r--src/base/CubicSpline.h56
-rw-r--r--src/base/DAG.cpp130
-rw-r--r--src/base/DAG.h64
-rw-r--r--src/base/DirEntry.cpp65
-rw-r--r--src/base/DirEntry.h67
-rw-r--r--src/base/Directory.cpp135
-rw-r--r--src/base/Directory.h64
-rw-r--r--src/base/DlfcnWrapper.cpp61
-rw-r--r--src/base/DlfcnWrapper.h41
-rw-r--r--src/base/Exception.cpp99
-rw-r--r--src/base/Exception.h88
-rw-r--r--src/base/FileHelper.cpp164
-rw-r--r--src/base/FileHelper.h53
-rw-r--r--src/base/GLMHelper.cpp183
-rw-r--r--src/base/GLMHelper.h70
-rw-r--r--src/base/GeomHelper.cpp178
-rw-r--r--src/base/GeomHelper.h51
-rw-r--r--src/base/IFrameEndListener.h37
-rw-r--r--src/base/ILogSink.h53
-rw-r--r--src/base/IPlaybackEndListener.h38
-rw-r--r--src/base/IPreRenderListener.h35
-rw-r--r--src/base/Logger.cpp280
-rw-r--r--src/base/Logger.h154
-rw-r--r--src/base/Makefile.am35
-rw-r--r--src/base/MathHelper.cpp78
-rw-r--r--src/base/MathHelper.h93
-rw-r--r--src/base/OSHelper.cpp308
-rw-r--r--src/base/OSHelper.h52
-rw-r--r--src/base/ObjectCounter.cpp187
-rw-r--r--src/base/ObjectCounter.h61
-rw-r--r--src/base/ProfilingZone.cpp91
-rw-r--r--src/base/ProfilingZone.h69
-rw-r--r--src/base/ProfilingZoneID.cpp57
-rw-r--r--src/base/ProfilingZoneID.h50
-rw-r--r--src/base/Queue.h160
-rw-r--r--src/base/Rect.h213
-rw-r--r--src/base/ScopeTimer.cpp35
-rw-r--r--src/base/ScopeTimer.h60
-rw-r--r--src/base/Signal.h119
-rw-r--r--src/base/StandardLogSink.cpp54
-rw-r--r--src/base/StandardLogSink.h39
-rw-r--r--src/base/StringHelper.cpp145
-rw-r--r--src/base/StringHelper.h133
-rw-r--r--src/base/Test.cpp114
-rw-r--r--src/base/Test.h81
-rw-r--r--src/base/TestSuite.cpp72
-rw-r--r--src/base/TestSuite.h49
-rw-r--r--src/base/ThreadHelper.cpp94
-rw-r--r--src/base/ThreadHelper.h37
-rw-r--r--src/base/ThreadProfiler.cpp184
-rw-r--r--src/base/ThreadProfiler.h88
-rw-r--r--src/base/TimeSource.cpp128
-rw-r--r--src/base/TimeSource.h60
-rw-r--r--src/base/Triangle.cpp105
-rw-r--r--src/base/Triangle.h52
-rw-r--r--src/base/UTF8String.cpp62
-rw-r--r--src/base/UTF8String.h46
-rw-r--r--src/base/WideLine.cpp53
-rw-r--r--src/base/WideLine.h48
-rw-r--r--src/base/WorkerThread.cpp41
-rw-r--r--src/base/WorkerThread.h169
-rw-r--r--src/base/XMLHelper.cpp225
-rw-r--r--src/base/XMLHelper.h78
-rw-r--r--src/base/testbase.cpp1024
-rw-r--r--src/base/triangulate/AdvancingFront.cpp104
-rw-r--r--src/base/triangulate/AdvancingFront.h118
-rw-r--r--src/base/triangulate/Makefile.am8
-rw-r--r--src/base/triangulate/Shapes.cpp353
-rw-r--r--src/base/triangulate/Shapes.h296
-rw-r--r--src/base/triangulate/Sweep.cpp796
-rw-r--r--src/base/triangulate/Sweep.h201
-rw-r--r--src/base/triangulate/SweepContext.cpp196
-rw-r--r--src/base/triangulate/SweepContext.h181
-rw-r--r--src/base/triangulate/Triangulate.cpp90
-rw-r--r--src/base/triangulate/Triangulate.h33
-rw-r--r--src/base/triangulate/Utils.h124
85 files changed, 10453 insertions, 0 deletions
diff --git a/src/base/Backtrace.cpp b/src/base/Backtrace.cpp
new file mode 100644
index 0000000..2b85cde
--- /dev/null
+++ b/src/base/Backtrace.cpp
@@ -0,0 +1,120 @@
+//
+// 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 "Backtrace.h"
+
+#include "StringHelper.h"
+
+#ifndef _WIN32
+#include <execinfo.h>
+#include <cxxabi.h>
+#endif
+
+#include <stdlib.h>
+#include <iostream>
+#include <stdio.h>
+
+using namespace std;
+
+namespace avg {
+
+void dumpBacktrace()
+{
+#ifndef _WIN32
+ vector<string> sFuncs;
+ getBacktrace(sFuncs);
+ vector<string>::iterator it = sFuncs.begin();
+ ++it;
+ for (; it != sFuncs.end(); ++it) {
+ cerr << " " << *it << endl;
+ }
+#endif
+}
+
+string funcNameFromLine(const string& sLine)
+{
+ try {
+#ifdef __APPLE__
+ string::size_type addressPos = sLine.find("0x");
+ string::size_type namePos = sLine.find(" ", addressPos);
+ namePos++;
+ string::size_type nameEndPos = sLine.find(" ", namePos);
+#else
+ string::size_type namePos = sLine.find("(");
+ namePos++;
+ string::size_type nameEndPos = sLine.find_first_of(")+", namePos);
+#endif
+ return sLine.substr(namePos, nameEndPos-namePos);
+ } catch (exception&) {
+ return sLine;
+ }
+}
+
+void consolidateRepeatedLines(vector<string>& sFuncs, unsigned& i, unsigned numSameLines)
+{
+ unsigned firstSameLine = i - numSameLines;
+ sFuncs[firstSameLine+1] = " [...]";
+ sFuncs.erase(sFuncs.begin()+firstSameLine+2, sFuncs.begin()+i-1);
+ i = firstSameLine + 3;
+}
+
+void getBacktrace(vector<string>& sFuncs)
+{
+#ifndef _WIN32
+ void* callstack[128];
+ int numFrames = backtrace(callstack, 128);
+ char** ppszLines = backtrace_symbols(callstack, numFrames);
+ for (int i = 1; i < numFrames; ++i) {
+ string sLine = ppszLines[i];
+ string sFuncName = funcNameFromLine(sLine);
+ int result;
+ char * pszDemangledFuncName = abi::__cxa_demangle(sFuncName.c_str(), 0, 0,
+ &result);
+ if (!result) {
+ sFuncName = pszDemangledFuncName;
+ free(pszDemangledFuncName);
+ }
+ char szLineNum[10];
+ sprintf(szLineNum, "%3d", i);
+ sFuncs.push_back(string(szLineNum)+" "+sFuncName);
+ }
+ free(ppszLines);
+
+ unsigned numSameLines = 1;
+ unsigned i = 1;
+ for (i = 1; i < sFuncs.size(); ++i) {
+ if (sFuncs[i].substr(4, string::npos) == sFuncs[i-1].substr(4, string::npos)) {
+ numSameLines++;
+ } else {
+ if (numSameLines > 3) {
+ consolidateRepeatedLines(sFuncs, i, numSameLines);
+ }
+ numSameLines = 1;
+ }
+ }
+ if (numSameLines > 2) {
+ consolidateRepeatedLines(sFuncs, i, numSameLines);
+ }
+#endif
+}
+
+}
+
diff --git a/src/base/Backtrace.h b/src/base/Backtrace.h
new file mode 100644
index 0000000..2eee387
--- /dev/null
+++ b/src/base/Backtrace.h
@@ -0,0 +1,36 @@
+//
+// 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
+//
+
+#ifndef _Backtrace_H_
+#define _Backtrace_H_
+
+#include <vector>
+#include <string>
+
+namespace avg {
+
+void dumpBacktrace();
+
+void getBacktrace(std::vector<std::string>& sFuncs);
+
+}
+
+#endif
diff --git a/src/base/BezierCurve.cpp b/src/base/BezierCurve.cpp
new file mode 100644
index 0000000..7e5fb8e
--- /dev/null
+++ b/src/base/BezierCurve.cpp
@@ -0,0 +1,56 @@
+//
+// 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 "BezierCurve.h"
+
+#include "GLMHelper.h"
+
+#include <iostream>
+
+using namespace std;
+
+namespace avg {
+
+BezierCurve::BezierCurve(const glm::vec2& p0, const glm::vec2& p1, const glm::vec2& p2,
+ const glm::vec2& p3)
+ : m_P0(p0),
+ m_P1(p1),
+ m_P2(p2),
+ m_P3(p3)
+{
+}
+
+glm::vec2 BezierCurve::interpolate(float t) const
+{
+ return (1.f-t)*(1.f-t)*(1.f-t)*m_P0+
+ 3.f*t*(1.f-t)*(1.f-t) *m_P1+
+ 3.f*t*t*(1.f-t) *m_P2+
+ t*t*t *m_P3;
+}
+
+glm::vec2 BezierCurve::getDeriv(float t) const
+{
+ return 3.f*(m_P1-m_P0)*(1.f-t)*(1.f-t)+
+ 6.f*(m_P2-m_P1)*(1.f-t)*t+
+ 3.f*(m_P3-m_P2)*t*t;
+}
+
+}
diff --git a/src/base/BezierCurve.h b/src/base/BezierCurve.h
new file mode 100644
index 0000000..b2ec1dc
--- /dev/null
+++ b/src/base/BezierCurve.h
@@ -0,0 +1,56 @@
+//
+// 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
+//
+
+#ifndef _BezierCurve_H_
+#define _BezierCurve_H_
+
+#include "../api.h"
+
+#include "../glm/glm.hpp"
+
+#include <boost/shared_ptr.hpp>
+#include <vector>
+
+namespace avg {
+
+class AVG_API BezierCurve {
+public:
+ BezierCurve(const glm::vec2& p0, const glm::vec2& p1, const glm::vec2& p2,
+ const glm::vec2& p3);
+
+ glm::vec2 interpolate(float t) const;
+ glm::vec2 getDeriv(float t) const;
+
+private:
+ glm::vec2 m_P0;
+ glm::vec2 m_P1;
+ glm::vec2 m_P2;
+ glm::vec2 m_P3;
+};
+
+typedef boost::shared_ptr<BezierCurve> BezierCurvePtr;
+
+}
+
+#endif
+
+
+
diff --git a/src/base/CmdQueue.h b/src/base/CmdQueue.h
new file mode 100644
index 0000000..9d38f37
--- /dev/null
+++ b/src/base/CmdQueue.h
@@ -0,0 +1,56 @@
+//
+// 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
+//
+
+#ifndef _CmdQueue_H_
+#define _CmdQueue_H_
+
+#include "Command.h"
+#include "Queue.h"
+
+#include "../api.h"
+
+namespace avg {
+
+template<class RECEIVER>
+class AVG_TEMPLATE_API CmdQueue: public Queue<Command<RECEIVER> >
+{
+public:
+ CmdQueue(int maxSize=-1);
+ typedef typename Queue<Command<RECEIVER> >::QElementPtr CmdPtr;
+ void pushCmd(typename Command<RECEIVER>::CmdFunc func);
+
+};
+
+template<class RECEIVER>
+CmdQueue<RECEIVER>::CmdQueue(int maxSize)
+ : Queue<Command<RECEIVER> >(maxSize)
+{
+}
+
+template<class RECEIVER>
+void CmdQueue<RECEIVER>::pushCmd(typename Command<RECEIVER>::CmdFunc func)
+{
+ this->push(CmdPtr(new Command<RECEIVER>(func)));
+}
+
+}
+
+#endif
diff --git a/src/base/Command.h b/src/base/Command.h
new file mode 100644
index 0000000..fe18171
--- /dev/null
+++ b/src/base/Command.h
@@ -0,0 +1,56 @@
+//
+// 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
+//
+
+#ifndef _Command_H_
+#define _Command_H_
+
+#include "../api.h"
+#include <boost/function.hpp>
+
+namespace avg {
+
+template<class RECEIVER>
+class AVG_TEMPLATE_API Command {
+public:
+ typedef boost::function<void(RECEIVER*)> CmdFunc;
+
+ Command(CmdFunc Func);
+ void execute(RECEIVER* pTarget);
+
+private:
+ CmdFunc m_Func;
+};
+
+template<class RECEIVER>
+Command<RECEIVER>::Command(CmdFunc Func)
+ : m_Func(Func)
+{
+}
+
+template<class RECEIVER>
+void Command<RECEIVER>::execute(RECEIVER* pTarget)
+{
+ m_Func(pTarget);
+}
+
+}
+
+#endif
diff --git a/src/base/ConfigMgr.cpp b/src/base/ConfigMgr.cpp
new file mode 100644
index 0000000..0414037
--- /dev/null
+++ b/src/base/ConfigMgr.cpp
@@ -0,0 +1,361 @@
+//
+// 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 "ConfigMgr.h"
+#include "Logger.h"
+#include "Exception.h"
+#include "OSHelper.h"
+
+#include <libxml/xmlmemory.h>
+
+#include <iostream>
+#include <stdlib.h>
+#include <errno.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+
+using namespace std;
+
+namespace avg {
+
+ConfigOption::ConfigOption(const string& sName, const string& sValue)
+ : m_sName(sName),
+ m_sValue(sValue)
+{
+}
+
+ConfigMgr* ConfigMgr::m_pGlobalConfigMgr = 0;
+
+void deleteConfigMgr()
+{
+ delete ConfigMgr::m_pGlobalConfigMgr;
+ ConfigMgr::m_pGlobalConfigMgr = 0;
+}
+
+ConfigMgr* ConfigMgr::get()
+{
+ if (!m_pGlobalConfigMgr) {
+ m_pGlobalConfigMgr = new ConfigMgr;
+ atexit(deleteConfigMgr);
+ }
+ return m_pGlobalConfigMgr;
+}
+
+ConfigMgr::ConfigMgr()
+{
+ addSubsys("scr");
+ addOption("scr", "gles", "false");
+ addOption("scr", "bpp", "24");
+ addOption("scr", "fullscreen", "false");
+ addOption("scr", "windowwidth", "0");
+ addOption("scr", "windowheight", "0");
+ addOption("scr", "dotspermm", "0");
+ addOption("scr", "usepow2textures", "false");
+ addOption("scr", "usepixelbuffers", "true");
+ addOption("scr", "multisamplesamples", "8");
+ addOption("scr", "shaderusage", "auto");
+ addOption("scr", "gamma", "-1,-1,-1");
+ addOption("scr", "vsyncmode", "auto");
+ addOption("scr", "videoaccel", "true");
+
+ addSubsys("aud");
+ addOption("aud", "channels", "2");
+ addOption("aud", "samplerate", "44100");
+ addOption("aud", "outputbuffersamples", "1024");
+
+ addSubsys("gesture");
+ addOption("gesture", "maxtapdist", "15");
+ addOption("gesture", "maxdoubletaptime", "300");
+ addOption("gesture", "minswipedist", "50");
+ addOption("gesture", "swipedirectiontolerance", "0.393"); // pi/8
+ addOption("gesture", "maxswipecontactdist", "100");
+ addOption("gesture", "holddelay", "500");
+ addOption("gesture", "mindragdist", "5");
+ addOption("gesture", "filtermincutoff", "0.1");
+ addOption("gesture", "filterbeta", "0.03");
+ addOption("gesture", "friction", "-1");
+
+ addSubsys("touch");
+ addOption("touch", "area", "0, 0");
+ addOption("touch", "offset", "0, 0");
+
+ m_sFName = "avgrc";
+ loadFile(getGlobalConfigDir()+m_sFName);
+ char * pHome = getenv("HOME");
+ if (pHome) {
+ loadFile(string(pHome)+"/."+m_sFName);
+ }
+}
+
+void ConfigMgr::addSubsys(const string& sName)
+{
+ m_SubsysOptionMap[sName] = ConfigOptionVector();
+}
+
+void ConfigMgr::addOption(const string& sSubsys, const string& sName,
+ const std::string& sDefault)
+{
+ ConfigOptionVector& Subsys = m_SubsysOptionMap[sSubsys];
+ Subsys.push_back(ConfigOption(sName, sDefault));
+}
+
+const ConfigOptionVector* ConfigMgr::getOptions(const string& sSubsys) const
+{
+ SubsysOptionMap::const_iterator it = m_SubsysOptionMap.find(sSubsys);
+ if (it == m_SubsysOptionMap.end()) {
+ return 0;
+ } else {
+ return &(*it).second;
+ }
+}
+
+const string* ConfigMgr::getOption(const string& sSubsys,
+ const string& sName) const
+{
+ const ConfigOptionVector* pOptionVector = getOptions(sSubsys);
+ if (!pOptionVector) {
+ return 0;
+ } else {
+ for (unsigned int i=0; i<pOptionVector->size(); i++) {
+ if ((*pOptionVector)[i].m_sName == sName) {
+ return &(*pOptionVector)[i].m_sValue;
+ }
+ }
+ return 0;
+ }
+}
+
+bool ConfigMgr::getBoolOption(const string& sSubsys,
+ const string& sName, bool bDefault) const
+{
+ const string * psOption = getOption(sSubsys, sName);
+ if (psOption == 0) {
+ return bDefault;
+ }
+ if (*psOption == "true") {
+ return true;
+ } else if (*psOption == "false") {
+ return false;
+ } else {
+ AVG_LOG_ERROR(m_sFName << ": Unrecognized value for option " << sName << ": "
+ << *psOption << ". Must be true or false. Aborting.");
+ exit(-1);
+ }
+}
+
+int ConfigMgr::getIntOption(const string& sSubsys,
+ const string& sName, int Default) const
+{
+ errno = 0;
+ const string * psOption = getOption(sSubsys, sName);
+ if (psOption == 0) {
+ return Default;
+ }
+ int Result = strtol(psOption->c_str(), 0, 10);
+ int rc = errno;
+ if (rc == EINVAL || rc == ERANGE) {
+ AVG_LOG_ERROR(m_sFName << ": Unrecognized value for option "<<sName<<": "
+ << *psOption << ". Must be an integer. Aborting.");
+ exit(-1);
+ }
+ return Result;
+}
+
+void ConfigMgr::getGammaOption(const string& sSubsys,
+ const string& sName, float* Val) const
+{
+ const string * psOption = getOption(sSubsys, sName);
+ if (psOption == 0) {
+ return;
+ }
+ int rc = sscanf(psOption->c_str(), "%f,%f,%f", Val, Val+1, Val+2);
+ if (rc < 3) {
+ AVG_LOG_ERROR(m_sFName << ": Unrecognized value for option "<<sName<<": "
+ << *psOption << ". Must be three comma-separated numbers. Aborting.");
+ exit(-1);
+ }
+}
+
+glm::vec2 ConfigMgr::getSizeOption(const string& sSubsys,
+ const string& sName) const
+{
+ const string * psOption = getOption(sSubsys, sName);
+ if (psOption == 0) {
+ return glm::vec2(0, 0);
+ }
+ float val[2];
+ int rc = sscanf(psOption->c_str(), "%f,%f", val, val+1);
+ if (rc < 2) {
+ AVG_LOG_ERROR(m_sFName << ": Unrecognized value for option " << sName << ": "
+ << *psOption << ". Must be 2 comma-separated numbers(x, y). Aborting.");
+ exit(-1);
+ }
+ return glm::vec2(val[0], val[1]);
+}
+
+void ConfigMgr::getStringOption(const string& sSubsys,
+ const string& sName, const string& sDefault, string& sVal) const
+{
+ const string * psOption = getOption(sSubsys, sName);
+ if (psOption == 0) {
+ sVal = sDefault;
+ } else {
+ sVal = *psOption;
+ }
+}
+
+
+bool ConfigMgr::loadFile(const std::string& sPath)
+{
+ string sSubsys;
+ try {
+#ifndef _WIN32
+ // I don't think read permissions on config files are an issue under windows.
+ int err = access(sPath.c_str(), R_OK);
+ if (err == -1) {
+ if (errno == EACCES) {
+ AVG_LOG_WARNING(sPath+
+ ": File exists, but process doesn't have read permissions!");
+ }
+ return false;
+ }
+#else
+ // but this actually prevents ugly XML parsing errors when file does not exist
+ // and cygwin is used
+ int err = _access(sPath.c_str(), 0);
+ if (err == -1) {
+ return false;
+ }
+#endif
+ xmlDocPtr doc;
+ doc = xmlParseFile(sPath.c_str());
+ if (!doc) {
+ throw Exception(AVG_ERR_XML_VALID, "Error parsing "+sPath
+ +". File is not well-formed.");
+ }
+ xmlNodePtr pRoot = xmlDocGetRootElement(doc);
+ if (xmlStrcmp(pRoot->name, (const xmlChar *)(m_sFName.c_str()))) {
+ AVG_LOG_ERROR(sPath+": Root node must be <"+m_sFName+">, found "
+ << pRoot->name << ". Aborting.");
+ exit(255);
+ }
+ xmlNodePtr pSubsysNode = pRoot->xmlChildrenNode;
+ while (pSubsysNode) {
+ if (xmlStrcmp(pSubsysNode->name, (const xmlChar *)"text") &&
+ xmlStrcmp(pSubsysNode->name, (const xmlChar *)"comment"))
+ {
+ sSubsys = ((const char *)pSubsysNode->name);
+ xmlNodePtr pOptionNode = pSubsysNode->xmlChildrenNode;
+ if (!pOptionNode) {
+ AVG_LOG_ERROR(sPath << ": Option " << sSubsys
+ << " has no value. Ignoring.");
+ } else {
+ ConfigOptionVector& CurSubsys = getSubsys(sSubsys);
+ while (pOptionNode) {
+ if (xmlStrcmp(pOptionNode->name, (const xmlChar *)"text") &&
+ xmlStrcmp(pOptionNode->name, (const xmlChar *)"comment"))
+ {
+ setOption(CurSubsys, doc, pOptionNode);
+ }
+ pOptionNode = pOptionNode->next;
+ }
+ }
+ }
+ pSubsysNode = pSubsysNode->next;
+ }
+ xmlFreeDoc(doc);
+ } catch (Exception& e) {
+ switch (e.getCode()) {
+ case AVG_ERR_OPTION_SUBSYS_UNKNOWN:
+ AVG_LOG_ERROR("While parsing " << sPath << ": Option group " <<
+ e.getStr() << " unknown. Aborting.");
+ exit(255);
+ case AVG_ERR_OPTION_UNKNOWN:
+ AVG_LOG_ERROR("While parsing " << sPath << ": Option " << sSubsys <<
+ ":" << e.getStr() << " unknown. Aborting.");
+ exit(255);
+ default:
+ throw;
+ }
+ }
+ return true;
+}
+
+ConfigOptionVector& ConfigMgr::getSubsys(const string& sName)
+{
+ SubsysOptionMap::iterator pos = m_SubsysOptionMap.find(sName);
+ if (pos == m_SubsysOptionMap.end()) {
+ throw Exception(AVG_ERR_OPTION_SUBSYS_UNKNOWN, sName);
+ } else {
+ return pos->second;
+ }
+}
+
+void ConfigMgr::setOption(ConfigOptionVector& optionVector,
+ xmlDocPtr doc, xmlNodePtr pNode)
+{
+ string sName = (const char *)pNode->name;
+ xmlChar * pVal = xmlNodeListGetString(doc, pNode->xmlChildrenNode, 1);
+ string sValue = (const char *)pVal;
+ xmlFree(pVal);
+ setOption(optionVector, sName, sValue);
+}
+
+void ConfigMgr::setOption(ConfigOptionVector& optionVector,
+ const string& sName, const string& sValue)
+{
+ for (unsigned int i = 0; i < optionVector.size(); i++) {
+ if (optionVector[i].m_sName == sName) {
+ optionVector[i].m_sValue = sValue;
+ return;
+ }
+ }
+ throw Exception(AVG_ERR_OPTION_UNKNOWN, sName);
+}
+
+void ConfigMgr::dump() const
+{
+ SubsysOptionMap::const_iterator it;
+ for (it = m_SubsysOptionMap.begin(); it != m_SubsysOptionMap.end(); ++it) {
+ cerr << (*it).first << ": " << endl;
+ const ConfigOptionVector& SubsysOptions = (*it).second;
+ for (unsigned int j = 0; j < SubsysOptions.size(); ++j) {
+ cerr << " " << SubsysOptions[j].m_sName << ": "
+ << SubsysOptions[j].m_sValue << endl;
+ }
+ }
+}
+
+string getGlobalConfigDir()
+{
+#ifdef _WIN32
+ return getAvgLibPath()+"/etc/";
+#else
+ return "/etc/";
+#endif
+}
+
+}
+
diff --git a/src/base/ConfigMgr.h b/src/base/ConfigMgr.h
new file mode 100644
index 0000000..e2af8f1
--- /dev/null
+++ b/src/base/ConfigMgr.h
@@ -0,0 +1,93 @@
+//
+// 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
+//
+
+#ifndef _ConfigMgr_H_
+#define _ConfigMgr_H_
+
+#include "../api.h"
+
+#include "GLMHelper.h"
+#include <libxml/parser.h>
+
+#include <string>
+#include <vector>
+#include <map>
+
+namespace avg {
+
+struct ConfigOption {
+ ConfigOption(const std::string& sName, const std::string& sValue);
+
+ std::string m_sName;
+ std::string m_sValue;
+};
+
+typedef std::vector<ConfigOption> ConfigOptionVector;
+
+class AVG_API ConfigMgr {
+public:
+ static ConfigMgr* get();
+
+ void addSubsys(const std::string& sName);
+ void addOption(const std::string& sSubsys, const std::string& sName,
+ const std::string& sDefault);
+
+ const ConfigOptionVector* getOptions(const std::string& sSubsys) const;
+ const std::string* getOption(const std::string& sSubsys,
+ const std::string& sName) const;
+ bool getBoolOption(const std::string& sSubsys,
+ const std::string& sName, bool bDefault) const;
+ int getIntOption(const std::string& sSubsys,
+ const std::string& sName, int Default) const;
+ void getGammaOption(const std::string& sSubsys,
+ const std::string& sName, float* Val) const;
+ glm::vec2 getSizeOption(const std::string& sSubsys,
+ const std::string& sName) const;
+ void getStringOption(const std::string& sSubsys,
+ const std::string& sName, const std::string& sDefault, std::string& sVal)
+ const;
+
+ void dump() const;
+
+private:
+ ConfigMgr();
+
+ bool loadFile(const std::string& sPath);
+ ConfigOptionVector& getSubsys(const std::string& sName);
+ void setOption(ConfigOptionVector& optionVector,
+ xmlDocPtr doc, xmlNodePtr pNode);
+ void setOption(ConfigOptionVector& optionVector, const std::string& sName,
+ const std::string& sValue);
+
+ typedef std::map<std::string, ConfigOptionVector> SubsysOptionMap;
+ SubsysOptionMap m_SubsysOptionMap;
+
+ std::string m_sFName;
+
+ static ConfigMgr* m_pGlobalConfigMgr;
+ friend void deleteConfigMgr();
+};
+
+std::string getGlobalConfigDir();
+
+}
+#endif
+
diff --git a/src/base/CubicSpline.cpp b/src/base/CubicSpline.cpp
new file mode 100644
index 0000000..105563d
--- /dev/null
+++ b/src/base/CubicSpline.cpp
@@ -0,0 +1,104 @@
+//
+// 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 "CubicSpline.h"
+#include "Exception.h"
+#include "MathHelper.h"
+
+#include <iostream>
+
+using namespace std;
+
+namespace avg {
+
+CubicSpline::CubicSpline(const vector<float>& x, const vector<float>& y, bool bLoop)
+{
+ AVG_ASSERT(x.size() == y.size());
+ for (unsigned i=0; i<x.size(); ++i) {
+ m_Pts.push_back(glm::vec2(x[i], y[i]));
+ }
+ init();
+}
+
+CubicSpline::CubicSpline(const vector<glm::vec2>& pts, bool bLoop)
+ : m_Pts(pts)
+{
+ init();
+}
+
+CubicSpline::~CubicSpline()
+{
+}
+
+float CubicSpline::interpolate(float orig)
+{
+ int len = m_Pts.size();
+ int low = 0;
+ int high = len-1;
+ // Binary search.
+ while (high - low > 1) {
+ int avg = (high+low) / 2;
+ if (m_Pts[avg].x > orig) {
+ high = avg;
+ } else {
+ low = avg;
+ }
+ }
+ float h = m_Pts[high].x - m_Pts[low].x;
+ float a = (m_Pts[high].x-orig)/h;
+ float b = (orig-m_Pts[low].x)/h;
+
+ float y = a*m_Pts[low].y + b*m_Pts[high].y
+ + ((a*a*a-a)*m_Y2[low] + (b*b*b-b)*m_Y2[high])*(h*h)/6.f;
+ return y;
+}
+
+void CubicSpline::init()
+{
+ int len = m_Pts.size();
+ for (int i=1; i<len; ++i) {
+ if (m_Pts[i].x <= m_Pts[i-1].x) {
+ throw Exception(AVG_ERR_INVALID_ARGS,
+ "CubicSplines must have increasing x coordinates.");
+ }
+ }
+ vector<float> u(len-1,0);
+ m_Y2.push_back(0.f);
+ u[0] = 0.f;
+ for (int i=1; i<len-1; ++i) {
+ float sig = (m_Pts[i].x-m_Pts[i-1].x) / (m_Pts[i+1].x-m_Pts[i-1].x);
+ float p = sig * m_Y2[i-1]+2.0f;
+ m_Y2.push_back((sig-1.0f)/p);
+ u[i] = (m_Pts[i+1].y-m_Pts[i].y) / (m_Pts[i+1].x-m_Pts[i].x) -
+ (m_Pts[i].y - m_Pts[i-1].y) / (m_Pts[i].x-m_Pts[i-1].x);
+ u[i] = (6.f*u[i]/(m_Pts[i+1].x-m_Pts[i-1].x) - sig*u[i-1]) / p;
+ }
+ float qn = 0.f;
+ float un = 0.f;
+
+ m_Y2.push_back((un-qn*u[len-2]) / (qn*m_Y2[len-2]-1.0f));
+
+ for (int i=len-2; i>=0; i--) {
+ m_Y2[i] = m_Y2[i]*m_Y2[i+1]+u[i];
+ }
+}
+
+}
diff --git a/src/base/CubicSpline.h b/src/base/CubicSpline.h
new file mode 100644
index 0000000..a275413
--- /dev/null
+++ b/src/base/CubicSpline.h
@@ -0,0 +1,56 @@
+//
+// 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
+//
+
+#ifndef _CubicSpline_H_
+#define _CubicSpline_H_
+
+#include "../api.h"
+#include "../glm/glm.hpp"
+
+#include <boost/shared_ptr.hpp>
+#include <vector>
+
+namespace avg {
+
+class AVG_API CubicSpline {
+public:
+ CubicSpline(const std::vector<float>& x, const std::vector<float>& y,
+ bool bLoop=false);
+ CubicSpline(const std::vector<glm::vec2>& pts, bool bLoop=false);
+ virtual ~CubicSpline();
+
+ float interpolate(float orig);
+
+private:
+ void init();
+
+ std::vector<glm::vec2> m_Pts;
+ std::vector<float> m_Y2; // Second derivatives
+};
+
+typedef boost::shared_ptr<CubicSpline> CubicSplinePtr;
+
+}
+
+#endif
+
+
+
diff --git a/src/base/DAG.cpp b/src/base/DAG.cpp
new file mode 100644
index 0000000..85ab8bb
--- /dev/null
+++ b/src/base/DAG.cpp
@@ -0,0 +1,130 @@
+//
+// 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 "DAG.h"
+
+#include "Exception.h"
+
+#include <boost/enable_shared_from_this.hpp>
+
+using namespace std;
+
+namespace avg {
+
+class AVG_API DAGNode: public boost::enable_shared_from_this<DAGNode>
+{
+public:
+ DAGNode(long vertexID, const std::set<long>& outgoingIDs);
+ void resolveIDs(DAG* pDAG);
+
+ long m_VertexID;
+ std::set<long> m_OutgoingIDs;
+ std::set<DAGNodePtr> m_pOutgoingNodes;
+ std::set<DAGNodePtr> m_pIncomingNodes;
+};
+
+
+DAGNode::DAGNode(long vertexID, const set<long>& outgoingIDs)
+{
+ m_VertexID = vertexID;
+ m_OutgoingIDs = outgoingIDs;
+}
+
+void DAGNode::resolveIDs(DAG* pDAG)
+{
+ set<long>::iterator it;
+ for (it=m_OutgoingIDs.begin(); it!=m_OutgoingIDs.end(); ++it) {
+ long outgoingID = *it;
+ DAGNodePtr pDestNode = pDAG->findNode(outgoingID);
+ m_pOutgoingNodes.insert(pDestNode);
+ pDestNode->m_pIncomingNodes.insert(shared_from_this());
+ }
+ m_OutgoingIDs.clear();
+}
+
+
+DAG::DAG()
+{
+}
+
+DAG::~DAG()
+{
+}
+
+void DAG::addNode(long vertexID, const set<long>& outgoingIDs)
+{
+ DAGNode* pNode = new DAGNode(vertexID, outgoingIDs);
+ m_pNodes.insert(DAGNodePtr(pNode));
+}
+
+void DAG::sort(vector<long>& pResults)
+{
+ resolveIDs();
+ while (!m_pNodes.empty()) {
+ DAGNodePtr pCurNode = findStartNode(*m_pNodes.begin());
+ removeNode(pCurNode);
+ pResults.push_back(pCurNode->m_VertexID);
+ }
+}
+
+void DAG::resolveIDs()
+{
+ set<DAGNodePtr>::iterator it;
+ for (it=m_pNodes.begin(); it!=m_pNodes.end(); ++it) {
+ (*it)->resolveIDs(this);
+ }
+}
+
+DAGNodePtr DAG::findNode(long id)
+{
+ set<DAGNodePtr>::iterator it;
+ for (it=m_pNodes.begin(); it!=m_pNodes.end(); ++it) {
+ if ((*it)->m_VertexID == id) {
+ return (*it);
+ }
+ }
+ AVG_ASSERT(false);
+ return DAGNodePtr();
+}
+
+void DAG::removeNode(DAGNodePtr pNode)
+{
+ set<DAGNodePtr>::iterator it;
+ for (it=pNode->m_pOutgoingNodes.begin(); it!=pNode->m_pOutgoingNodes.end(); ++it) {
+ DAGNodePtr pDestNode = *it;
+ pDestNode->m_pIncomingNodes.erase(pNode);
+ }
+ m_pNodes.erase(pNode);
+}
+
+DAGNodePtr DAG::findStartNode(DAGNodePtr pNode, unsigned depth)
+{
+ if (pNode->m_pIncomingNodes.empty()) {
+ return pNode;
+ } else {
+ if (depth > m_pNodes.size()) {
+ throw Exception(AVG_ERR_INVALID_ARGS, "cyclic graph");
+ }
+ return findStartNode(*pNode->m_pIncomingNodes.begin(), depth+1);
+ }
+}
+
+}
diff --git a/src/base/DAG.h b/src/base/DAG.h
new file mode 100644
index 0000000..929ecd2
--- /dev/null
+++ b/src/base/DAG.h
@@ -0,0 +1,64 @@
+//
+// 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
+//
+
+#ifndef _DAG_H_
+#define _DAG_H_
+
+#include "../api.h"
+
+#include <set>
+#include <vector>
+#include <boost/shared_ptr.hpp>
+
+namespace avg {
+
+class DAG;
+class DAGNode;
+typedef boost::shared_ptr<DAGNode> DAGNodePtr;
+
+// Directed Acyclic Graph class.
+// Only useful for sorting. The process of sorting destroys the DAG.
+class AVG_API DAG
+{
+public:
+ DAG();
+ virtual ~DAG();
+
+ void addNode(long vertexID, const std::set<long>& outgoingIDs);
+ void sort(std::vector<long>& pResults);
+
+private:
+ friend class DAGNode;
+
+ void resolveIDs();
+ DAGNodePtr findNode(long pID);
+ void removeNode(DAGNodePtr pNode);
+ DAGNodePtr findStartNode(DAGNodePtr pNode, unsigned depth=0);
+
+ std::set<DAGNodePtr> m_pNodes;
+};
+
+}
+
+#endif
+
+
+
diff --git a/src/base/DirEntry.cpp b/src/base/DirEntry.cpp
new file mode 100644
index 0000000..c654e50
--- /dev/null
+++ b/src/base/DirEntry.cpp
@@ -0,0 +1,65 @@
+//
+// 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 "DirEntry.h"
+
+using namespace std;
+
+namespace avg {
+
+#ifdef _WIN32
+DirEntry::DirEntry(string sDirName, const _finddata_t& findData)
+ : m_sDirName(sDirName),
+ m_FindData(findData)
+{
+}
+
+#else
+DirEntry::DirEntry(string sDirName, dirent * pEntry)
+ : m_sDirName(sDirName),
+ m_pEntry(pEntry)
+{
+}
+#endif
+
+DirEntry::~DirEntry()
+{
+}
+
+std::string DirEntry::getName()
+{
+#ifdef _WIN32
+ return m_FindData.name;
+#else
+ return m_pEntry->d_name;
+#endif
+}
+
+void DirEntry::remove()
+{
+#ifdef _WIN32
+ ::_unlink((m_sDirName+"\\"+m_FindData.name).c_str());
+#else
+ ::unlink((m_sDirName+"/"+m_pEntry->d_name).c_str());
+#endif
+}
+
+}
diff --git a/src/base/DirEntry.h b/src/base/DirEntry.h
new file mode 100644
index 0000000..ac2fca9
--- /dev/null
+++ b/src/base/DirEntry.h
@@ -0,0 +1,67 @@
+//
+// 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
+//
+
+#ifndef _DirEntry_H_
+#define _DirEntry_H_
+
+#include "../api.h"
+#include <boost/shared_ptr.hpp>
+
+#ifdef _WIN32
+#include <io.h>
+#else
+#include <dirent.h>
+#endif
+#include <string>
+
+namespace avg {
+
+class AVG_API DirEntry {
+public:
+#ifdef _WIN32
+ DirEntry(std::string sDirName, const _finddata_t& findData);
+#else
+ DirEntry(std::string sDirName, dirent * pEntry);
+#endif
+ virtual ~DirEntry();
+
+ std::string getName();
+ void remove();
+
+private:
+ std::string m_sDirName;
+
+#ifdef _WIN32
+ _finddata_t m_FindData;
+#else
+ dirent * m_pEntry;
+#endif
+
+};
+
+typedef boost::shared_ptr<DirEntry> DirEntryPtr;
+
+}
+
+#endif
+
+
+
diff --git a/src/base/Directory.cpp b/src/base/Directory.cpp
new file mode 100644
index 0000000..bc40ecc
--- /dev/null
+++ b/src/base/Directory.cpp
@@ -0,0 +1,135 @@
+//
+// 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 "Directory.h"
+
+#ifdef _WIN32
+#include <Windows.h>
+#endif
+#include <sys/stat.h>
+#include <iostream>
+
+using namespace std;
+
+namespace avg {
+
+Directory::Directory(std::string sName)
+ : m_sName(sName)
+{
+#ifdef _WIN32
+ m_hFile = -1;
+#else
+ m_pDir = 0;
+#endif
+}
+
+Directory::~Directory()
+{
+#ifdef _WIN32
+ _findclose(m_hFile);
+#else
+ if (m_pDir) {
+ closedir(m_pDir);
+ }
+#endif
+}
+
+int Directory::open(bool bCreateIfMissing)
+{
+#ifdef _WIN32
+ m_hFile = _findfirst((m_sName+"/*").c_str(), &m_FindData);
+ if(m_hFile == -1L) {
+ if (bCreateIfMissing) {
+ int err = CreateDirectory(m_sName.c_str(), 0);
+ if (err == 0) {
+ return -1;
+ } else {
+ m_hFile = _findfirst((m_sName+"/*").c_str(), &m_FindData);
+ m_bFirstFile = true;
+ return 0;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ m_bFirstFile = true;
+ return 0;
+ }
+#else
+ m_pDir = opendir(m_sName.c_str());
+ if (!m_pDir) {
+ if (bCreateIfMissing) {
+ int err = mkdir(m_sName.c_str(),
+ S_IRWXU | S_IRWXG | S_IRWXO);
+ if (err) {
+ return err;
+ } else {
+ m_pDir = opendir(m_sName.c_str());
+ return 0;
+ }
+ } else {
+ return -1;
+ }
+ } else {
+ return 0;
+ }
+#endif
+}
+
+DirEntryPtr Directory::getNextEntry()
+{
+#ifdef _WIN32
+ if (!m_bFirstFile) {
+ int rc = _findnext(m_hFile, &m_FindData);
+ if (rc == -1) {
+ return DirEntryPtr();
+ }
+ }
+ m_bFirstFile = false;
+ return DirEntryPtr(new DirEntry(m_sName, m_FindData));
+#else
+ dirent * pDirent;
+ pDirent = readdir(m_pDir);
+ if (pDirent) {
+ return DirEntryPtr(new DirEntry(m_sName, pDirent));
+ } else {
+ return DirEntryPtr();
+ }
+#endif
+}
+
+const std::string& Directory::getName()
+{
+ return m_sName;
+}
+
+void Directory::empty()
+{
+ DirEntryPtr pEntry;
+ do {
+ pEntry = getNextEntry();
+ if (pEntry) {
+ pEntry->remove();
+ }
+ } while (pEntry);
+}
+
+}
diff --git a/src/base/Directory.h b/src/base/Directory.h
new file mode 100644
index 0000000..f75107d
--- /dev/null
+++ b/src/base/Directory.h
@@ -0,0 +1,64 @@
+//
+// 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
+//
+
+#ifndef _Directory_H_
+#define _Directory_H_
+
+#include "../api.h"
+#include "DirEntry.h"
+
+#ifdef _WIN32
+#include <io.h>
+#else
+#include <dirent.h>
+#endif
+
+#include <string>
+
+namespace avg {
+
+class AVG_API Directory {
+public:
+ Directory(std::string sName);
+ virtual ~Directory();
+
+ int open(bool bCreateIfMissing = false);
+ DirEntryPtr getNextEntry();
+ const std::string& getName();
+ void empty();
+
+private:
+ std::string m_sName;
+
+#ifdef _WIN32
+ _finddata_t m_FindData;
+ intptr_t m_hFile;
+ bool m_bFirstFile;
+#else
+ DIR * m_pDir;
+#endif
+};
+
+}
+
+#endif
+
+
diff --git a/src/base/DlfcnWrapper.cpp b/src/base/DlfcnWrapper.cpp
new file mode 100644
index 0000000..f8011b1
--- /dev/null
+++ b/src/base/DlfcnWrapper.cpp
@@ -0,0 +1,61 @@
+//
+// 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 "DlfcnWrapper.h"
+
+#include <sstream>
+#include <string.h>
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include "windows.h"
+
+using namespace std;
+
+namespace avg {
+
+void* dlopen(const char *pszPath, int ignored)
+{
+ return LoadLibrary(pszPath);
+}
+
+void dlclose(void* handle)
+{
+ FreeLibrary((HMODULE)handle);
+}
+
+void* dlsym(void* handle, const char* functionName)
+{
+ return GetProcAddress((HMODULE)handle, functionName);
+}
+
+const char* dlerror()
+{
+ static char buffer[1024];
+ int err = GetLastError();
+ ostringstream ss;
+ ss << err;
+ strncpy(buffer,ss.str().c_str(),1023);
+ return buffer;
+}
+
+}
diff --git a/src/base/DlfcnWrapper.h b/src/base/DlfcnWrapper.h
new file mode 100644
index 0000000..883fb37
--- /dev/null
+++ b/src/base/DlfcnWrapper.h
@@ -0,0 +1,41 @@
+//
+// 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
+//
+
+#ifndef _DlfcnWrapper_h_
+#define _DlfcnWrapper_h_
+
+#ifdef _WIN32
+#define RTLD_LOCAL 0
+#define RTLD_NOW 0
+
+namespace avg {
+
+void* dlopen(const char *pszPath, int ignored);
+void dlclose(void* handle);
+void* dlsym(void* handle, const char* functionName);
+const char* dlerror();
+
+}
+#else
+#include <dlfcn.h>
+#endif
+
+#endif
diff --git a/src/base/Exception.cpp b/src/base/Exception.cpp
new file mode 100644
index 0000000..eb4f03c
--- /dev/null
+++ b/src/base/Exception.cpp
@@ -0,0 +1,99 @@
+//
+// 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 "Exception.h"
+#include "Backtrace.h"
+#include "Logger.h"
+#include "OSHelper.h"
+
+#include <cstdlib>
+#include <sstream>
+
+#ifdef WIN32
+#include <intrin.h>
+#endif
+
+using namespace std;
+
+namespace avg {
+
+Exception::Exception(int code, const string& sErr)
+ : std::exception(),
+ m_Code (code),
+ m_sErr (sErr)
+{
+}
+
+Exception::Exception(const Exception& ex)
+ : std::exception(),
+ m_Code (ex.getCode()),
+ m_sErr (ex.getStr())
+{
+}
+
+Exception::~Exception() throw()
+{
+}
+
+int Exception::getCode() const
+{
+ return m_Code;
+}
+
+const string& Exception::getStr() const
+{
+ return m_sErr;
+}
+
+const char* Exception::what() const throw()
+{
+ return m_sErr.c_str();
+}
+
+void debugBreak()
+{
+#ifdef _WIN32
+ __debugbreak();
+#else
+ __builtin_trap();
+#endif
+}
+
+void avgAssert(bool b, const char * pszFile, int line, const char * pszReason)
+{
+ if (!b) {
+ string sDummy;
+ static bool bBreak = getEnv("AVG_BREAK_ON_ASSERT", sDummy);
+ if (bBreak) {
+ debugBreak();
+ } else {
+ stringstream ss;
+ ss << "Assertion failed in " << pszFile << ": " << line << endl;
+ if (pszReason) {
+ ss << "Reason: " << pszReason << endl;
+ }
+ dumpBacktrace();
+ throw(Exception(AVG_ERR_ASSERT_FAILED, ss.str()));
+ }
+ }
+}
+
+}
diff --git a/src/base/Exception.h b/src/base/Exception.h
new file mode 100644
index 0000000..b28dc1a
--- /dev/null
+++ b/src/base/Exception.h
@@ -0,0 +1,88 @@
+//
+// 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
+//
+
+#ifndef _Exception_H_
+#define _Exception_H_
+
+#include "../api.h"
+#include <string>
+#include <exception>
+
+#define AVG_ERR_UNKNOWN -1
+#define AVG_ERR_XML_PARSE 1
+#define AVG_ERR_XML_VALID 2
+#define AVG_ERR_XML_EMPTY 3
+#define AVG_ERR_XML_NODE_UNKNOWN 4
+#define AVG_ERR_XML_DUPLICATE_ID 5
+#define AVG_ERR_VIDEO_INIT_FAILED 6
+#define AVG_ERR_VIDEO_GENERAL 7
+#define AVG_ERR_FONT_INIT_FAILED 10
+#define AVG_ERR_VIDEO_LOAD_FAILED 11
+#define AVG_ERR_UNSUPPORTED 12
+#define AVG_ERR_OPTION_SUBSYS_UNKNOWN 13
+#define AVG_ERR_OPTION_UNKNOWN 14
+#define AVG_ERR_FILEIO 15
+#define AVG_ERR_NOT_IN_SCENE 16
+#define AVG_ERR_OUT_OF_RANGE 17
+#define AVG_ERR_ALREADY_CONNECTED 18
+#define AVG_ERR_LOAD_DURING_PLAYBACK 19
+#define AVG_ERR_CANT_PARSE_STRING 20
+#define AVG_ERR_INVALID_CAPTURE 21
+
+#define AVG_ERR_NO_NODE 23
+#define AVG_ERR_NO_ARG 24
+#define AVG_ERR_INVALID_ARGS 25
+#define AVG_ERR_NO_BUILDER 26
+#define AVG_ERR_TYPE 27
+#define AVG_ERR_CORRUPT_PLUGIN 28
+#define AVG_ERR_CAMERA_FATAL 29
+#define AVG_ERR_CAMERA_NONFATAL 30
+#define AVG_ERR_DEPRECATED 31
+#define AVG_ERR_ASSERT_FAILED 32
+#define AVG_ERR_MT_INIT 33
+#define AVG_ERR_DEBUG_CONTEXT_FAILED 34
+
+namespace avg {
+
+class AVG_API Exception: public std::exception
+{
+ public:
+ Exception(int code, const std::string& sErr = "");
+ Exception(const Exception& ex);
+ virtual ~Exception() throw();
+ virtual int getCode() const;
+ virtual const std::string& getStr() const;
+ virtual const char* what() const throw();
+
+ private:
+ int m_Code;
+ std::string m_sErr;
+};
+
+void AVG_API debugBreak();
+void AVG_API avgAssert(bool b, const char * pszFile, int line, const char * pszReason=0);
+
+#define AVG_ASSERT(b) avgAssert((b) != 0, __FILE__, __LINE__);
+#define AVG_ASSERT_MSG(b, pszReason) avgAssert((b) != 0, __FILE__, __LINE__, pszReason);
+
+}
+
+#endif
diff --git a/src/base/FileHelper.cpp b/src/base/FileHelper.cpp
new file mode 100644
index 0000000..d9221c4
--- /dev/null
+++ b/src/base/FileHelper.cpp
@@ -0,0 +1,164 @@
+//
+// 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 "FileHelper.h"
+#include "Exception.h"
+
+#ifndef _WIN32
+#include <libgen.h>
+#else
+#include <direct.h>
+#endif
+#include <stdio.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <vector>
+#include <map>
+#include <cstring>
+#include <iostream>
+#include <fstream>
+
+using namespace std;
+
+namespace avg {
+
+string getPath(const string& sFilename)
+{
+ if (sFilename.length() > 0 && sFilename.at(sFilename.length()-1) == '/') {
+ return sFilename;
+ }
+#ifdef _WIN32
+ int pos = int(sFilename.find_last_of("\\/"));
+ string dirName;
+ if (pos >= 0) {
+ dirName = sFilename.substr(0, pos+1);
+ } else {
+ dirName = sFilename;
+ }
+#else
+ char * pszBuffer = strdup(sFilename.c_str());
+
+ string dirName(dirname(pszBuffer));
+ free(pszBuffer);
+ dirName += "/";
+#endif
+
+ return dirName;
+}
+
+string getFilenamePart(const string& sFilename)
+{
+ if (sFilename.find_last_of("\\/") == 0) {
+ return sFilename;
+ }
+#ifdef _WIN32
+ int pos = int(sFilename.find_last_of("\\/"));
+ string BaseName(sFilename.substr(pos+1));
+#else
+ char * pszBuffer = strdup(sFilename.c_str());
+
+ string BaseName(basename(pszBuffer));
+ free(pszBuffer);
+#endif
+
+ return BaseName;
+}
+
+string getExtension(const string& sFilename)
+{
+ int pos = int(sFilename.find_last_of("."));
+ if (pos == 0) {
+ return "";
+ } else {
+ return sFilename.substr(pos+1);
+ }
+}
+
+string getCWD()
+{
+
+ char szBuf[1024];
+#ifdef _WIN32
+ char * pBuf = _getcwd(szBuf, 1024);
+#else
+ char * pBuf = getcwd(szBuf, 1024);
+#endif
+ return string(pBuf)+"/";
+}
+
+bool isAbsPath(const std::string& path)
+{
+#ifdef _WIN32
+ return ((path.length() != 0) && path[1] == ':') || path[0] == '\\' || path[0] == '/';
+#else
+ return path[0] == '/';
+#endif
+
+}
+
+bool fileExists(const string& sFilename)
+{
+ struct stat myStat;
+ return stat(sFilename.c_str(), &myStat) != -1;
+}
+
+void readWholeFile(const string& sFilename, string& sContent)
+{
+ ifstream file(sFilename.c_str());
+ if (!file) {
+ throw Exception(AVG_ERR_FILEIO, "Opening "+sFilename+
+ " for reading failed.");
+ }
+ vector<char> buffer(65536);
+ sContent.resize(0);
+ while (file) {
+ file.read(&(*buffer.begin()), (streamsize)(buffer.size()));
+ sContent.append(&(*buffer.begin()), (unsigned)file.gcount());
+ }
+ if (!file.eof() || file.bad()) {
+ throw Exception(AVG_ERR_FILEIO, "Reading "+sFilename+
+ " failed.");
+ }
+}
+
+void writeWholeFile(const string& sFilename, const string& sContent)
+{
+ ofstream outFile(sFilename.c_str());
+ if (!outFile) {
+ throw Exception(AVG_ERR_FILEIO, "Opening "+sFilename+
+ " for writing failed.");
+ }
+ outFile << sContent;
+}
+
+
+void copyFile(const string& sSourceFile, const string& sDestFile)
+{
+ string sData;
+
+ readWholeFile(sSourceFile, sData);
+ writeWholeFile(sDestFile, sData);
+}
+
+}
diff --git a/src/base/FileHelper.h b/src/base/FileHelper.h
new file mode 100644
index 0000000..f367d0b
--- /dev/null
+++ b/src/base/FileHelper.h
@@ -0,0 +1,53 @@
+//
+// 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
+//
+
+#ifndef _FileHelper_H_
+#define _FileHelper_H_
+
+#include "../api.h"
+#include <string>
+
+namespace avg {
+
+std::string AVG_API getPath(const std::string& sFilename);
+std::string AVG_API getFilenamePart(const std::string& sFilename);
+std::string AVG_API getExtension(const std::string& sFilename);
+std::string AVG_API getCWD();
+
+bool AVG_API isAbsPath(const std::string& path);
+
+bool AVG_API fileExists(const std::string& sFilename);
+
+void AVG_API readWholeFile(const std::string& sFilename, std::string& sContents);
+
+void AVG_API writeWholeFile(const std::string& sFilename, const std::string& sContent);
+
+void AVG_API copyFile(const std::string& sSourceFile, const std::string& sDestFile);
+
+
+#ifdef WIN32
+#define unlink _unlink
+#endif
+
+}
+
+#endif
+
diff --git a/src/base/GLMHelper.cpp b/src/base/GLMHelper.cpp
new file mode 100644
index 0000000..e4b0f43
--- /dev/null
+++ b/src/base/GLMHelper.cpp
@@ -0,0 +1,183 @@
+//
+// 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 "GLMHelper.h"
+#include "StringHelper.h"
+#include "MathHelper.h"
+
+#include "../glm/gtx/rotate_vector.hpp"
+
+using namespace std;
+
+namespace avg {
+
+glm::vec2 getRotated(const glm::vec2& vec, float angle)
+{
+ return glm::rotate(vec, angle*180/PI);
+}
+
+glm::vec2 getRotatedPivot(const glm::vec2& vec, float angle, const glm::vec2& pivot)
+{
+ // translate pivot to origin
+ glm::vec2 translated = vec - pivot;
+
+ // calculate rotated coordinates about the origin
+ glm::vec2 rotated = glm::rotate(translated, angle*180/PI);
+
+ // re-translate pivot to original position
+ rotated += pivot;
+
+ return rotated;
+}
+
+float getAngle(const glm::vec2& vec)
+{
+ return float(atan2(double(vec.y), double(vec.x)));
+}
+
+glm::vec2 fromPolar(float angle, float radius)
+{
+ return glm::vec2(cos(angle)*radius, sin(angle)*radius);
+}
+
+template<class NUM>
+bool almostEqual(const glm::detail::tvec2<NUM>& v1, const glm::detail::tvec2<NUM>& v2)
+{
+ return (fabs(v1.x-v2.x)+fabs(v1.y-v2.y)) < 0.0001;
+}
+
+template<class NUM>
+bool almostEqual(const glm::detail::tvec4<NUM>& v1, const glm::detail::tvec4<NUM>& v2)
+{
+ return (fabs(v1.x-v2.x)+fabs(v1.y-v2.y)+fabs(v1.z-v2.z)+fabs(v1.w-v2.w)) < 0.0001;
+}
+
+template<class NUM>
+std::ostream& operator<<( std::ostream& os, const glm::detail::tvec2<NUM> &v)
+{
+ os << "(" << v.x << "," << v.y << ")";
+ return os;
+}
+
+template<class NUM>
+std::ostream& operator<<( std::ostream& os, const glm::detail::tvec3<NUM> &v)
+{
+ os << "(" << v.x << "," << v.y << "," << v.z << ")";
+ return os;
+}
+
+template<class NUM>
+std::ostream& operator<<( std::ostream& os, const glm::detail::tvec4<NUM> &v)
+{
+ os << "(" << v.x << "," << v.y << "," << v.z << ", " << v.a << ")";
+ return os;
+}
+
+template<class NUM>
+std::ostream& operator<<( std::ostream& os, const glm::detail::tmat4x4<NUM> &m)
+{
+ os << "(" << m[0] << ", " << endl <<
+ m[1] << ", " << endl <<
+ m[2] << ", " << endl <<
+ m[3] << ", " << endl << ")";
+ return os;
+}
+
+template<class NUM>
+std::istream& operator>>(std::istream& is, glm::detail::tvec2<NUM>& p)
+{
+ skipToken(is, '(');
+ is >> p.x;
+ skipToken(is, ',');
+ is >> p.y;
+ skipToken(is, ')');
+ return is;
+}
+
+template<class NUM>
+std::istream& operator>>(std::istream& is, glm::detail::tvec3<NUM>& p)
+{
+ skipToken(is, '(');
+ is >> p.x;
+ skipToken(is, ',');
+ is >> p.y;
+ skipToken(is, ',');
+ is >> p.z;
+ skipToken(is, ')');
+ return is;
+}
+
+glm::vec2 stringToVec2(const std::string& s)
+{
+ glm::vec2 pt;
+ fromString(s, pt);
+ return pt;
+}
+
+glm::vec3 stringToVec3(const std::string& s)
+{
+ glm::vec3 pt;
+ fromString(s, pt);
+ return pt;
+}
+
+glm::ivec3 stringToIVec3(const std::string& s)
+{
+ glm::ivec3 pt;
+ fromString(s, pt);
+ return pt;
+}
+
+
+template AVG_TEMPLATE_API std::ostream& operator<<(std::ostream& os, const glm::detail::tvec2<int> &p);
+template AVG_TEMPLATE_API std::ostream& operator<<(std::ostream& os, const glm::detail::tvec2<float> &p);
+template AVG_TEMPLATE_API std::ostream& operator<<(std::ostream& os, const glm::detail::tvec2<double> &p);
+
+template AVG_TEMPLATE_API std::istream& operator>>(std::istream& is, glm::detail::tvec2<int>& p);
+template AVG_TEMPLATE_API std::istream& operator>>(std::istream& is, glm::detail::tvec2<float>& p);
+template AVG_TEMPLATE_API std::istream& operator>>(std::istream& is, glm::detail::tvec2<double>& p);
+
+template AVG_TEMPLATE_API std::ostream& operator<<(std::ostream& os, const glm::detail::tvec3<int> &p);
+template AVG_TEMPLATE_API std::ostream& operator<<(std::ostream& os, const glm::detail::tvec3<float> &p);
+template AVG_TEMPLATE_API std::ostream& operator<<(std::ostream& os, const glm::detail::tvec3<double> &p);
+
+template AVG_TEMPLATE_API std::istream& operator>>(std::istream& is, glm::detail::tvec3<int>& p);
+template AVG_TEMPLATE_API std::istream& operator>>(std::istream& is, glm::detail::tvec3<float>& p);
+template AVG_TEMPLATE_API std::istream& operator>>(std::istream& is, glm::detail::tvec3<double>& p);
+
+template AVG_TEMPLATE_API std::ostream& operator<<(std::ostream& os, const glm::detail::tvec4<int> &p);
+template AVG_TEMPLATE_API std::ostream& operator<<(std::ostream& os, const glm::detail::tvec4<float> &p);
+template AVG_TEMPLATE_API std::ostream& operator<<(std::ostream& os, const glm::detail::tvec4<double> &p);
+
+template AVG_TEMPLATE_API std::ostream& operator<<(std::ostream& os, const glm::detail::tmat4x4<float> &p);
+template AVG_TEMPLATE_API std::ostream& operator<<(std::ostream& os,
+ const glm::detail::tmat4x4<double> &p);
+
+template AVG_TEMPLATE_API bool almostEqual(const glm::detail::tvec2<float>& v1,
+ const glm::detail::tvec2<float>& v2);
+template AVG_TEMPLATE_API bool almostEqual(const glm::detail::tvec2<double>& v1,
+ const glm::detail::tvec2<double>& v2);
+template AVG_TEMPLATE_API bool almostEqual(const glm::detail::tvec4<float>& v1,
+ const glm::detail::tvec4<float>& v2);
+template AVG_TEMPLATE_API bool almostEqual(const glm::detail::tvec4<double>& v1,
+ const glm::detail::tvec4<double>& v2);
+}
+
diff --git a/src/base/GLMHelper.h b/src/base/GLMHelper.h
new file mode 100644
index 0000000..4af8991
--- /dev/null
+++ b/src/base/GLMHelper.h
@@ -0,0 +1,70 @@
+//
+// 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
+//
+
+#ifndef _GLMHelper_H_
+#define _GLMHelper_H_
+
+#include "../api.h"
+
+#include "../glm/glm.hpp"
+#include "../glm/gtc/matrix_transform.hpp"
+#include "../glm/gtc/type_ptr.hpp"
+
+#include <iostream>
+#include <vector>
+
+namespace avg {
+
+glm::vec2 getRotated(const glm::vec2& vec, float angle);
+glm::vec2 getRotatedPivot(const glm::vec2& vec, float angle,
+ const glm::vec2& pivot=glm::vec2(0,0));
+float getAngle(const glm::vec2& vec);
+glm::vec2 fromPolar(float angle, float radius);
+
+template<class NUM>
+bool almostEqual(const glm::detail::tvec2<NUM>& v1, const glm::detail::tvec2<NUM>& v2);
+template<class NUM>
+bool almostEqual(const glm::detail::tvec4<NUM>& v1, const glm::detail::tvec4<NUM>& v2);
+
+template<class NUM>
+std::ostream& operator<<(std::ostream& os, const glm::detail::tvec2<NUM> &v);
+template<class NUM>
+std::ostream& operator<<(std::ostream& os, const glm::detail::tvec3<NUM> &v);
+template<class NUM>
+std::ostream& operator<<(std::ostream& os, const glm::detail::tvec4<NUM> &v);
+template<class NUM>
+std::ostream& operator<<(std::ostream& os, const glm::detail::tmat4x4<NUM> &v);
+
+template<class NUM>
+std::istream& operator>>(std::istream& is, glm::detail::tvec2<NUM>& p);
+template<class NUM>
+std::istream& operator>>(std::istream& is, glm::detail::tvec3<NUM>& p);
+
+typedef glm::ivec2 IntPoint;
+typedef std::vector<glm::vec2> Vec2Vector;
+
+glm::vec2 stringToVec2(const std::string& s);
+glm::vec3 stringToVec3(const std::string& s);
+glm::ivec3 stringToIVec3(const std::string& s);
+
+}
+
+#endif
diff --git a/src/base/GeomHelper.cpp b/src/base/GeomHelper.cpp
new file mode 100644
index 0000000..da167ad
--- /dev/null
+++ b/src/base/GeomHelper.cpp
@@ -0,0 +1,178 @@
+//
+// 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 "GeomHelper.h"
+
+#include <math.h>
+#include <iostream>
+
+using namespace std;
+
+namespace avg {
+
+LineSegment::LineSegment(const glm::vec2& pt0, const glm::vec2& pt1)
+ : p0(pt0),
+ p1(pt1)
+{
+}
+
+bool LineSegment::isPointOver(const glm::vec2& pt)
+{
+ glm::vec2 c = pt - p0;
+ glm::vec2 v = (p1 - p0);
+ float d = glm::length(v);
+ v /= d;
+ float t = glm::dot(v, c);
+
+ return (t >= 0 && t <= d);
+}
+
+// Code adapted from Antonio, Franklin, "Faster Line Segment Intersection,"
+// Graphics Gems III (David Kirk, ed.), Academic Press, pp. 199-202, 1992.
+bool lineSegmentsIntersect(const LineSegment& l0, const LineSegment& l1)
+{
+ float xdiff0 = l0.p1.x-l0.p0.x;
+ float xdiff1 = l1.p0.x-l1.p1.x;
+
+ float x1lo, x1hi;
+
+ /* X bound box test*/
+ if (xdiff0 < 0) {
+ x1lo=l0.p1.x;
+ x1hi=l0.p0.x;
+ } else {
+ x1hi=l0.p1.x;
+ x1lo=l0.p0.x;
+ }
+ if (xdiff1 > 0) {
+ if (x1hi < l1.p1.x || l1.p0.x < x1lo) {
+ return false;
+ }
+ } else {
+ if (x1hi < l1.p0.x || l1.p1.x < x1lo) {
+ return false;
+ }
+ }
+
+ float ydiff0 = l0.p1.y-l0.p0.y;
+ float ydiff1 = l1.p0.y-l1.p1.y;
+
+ float y1lo, y1hi;
+
+ /* Y bound box test*/
+ if (ydiff0 < 0) {
+ y1lo=l0.p1.y;
+ y1hi=l0.p0.y;
+ } else {
+ y1hi=l0.p1.y;
+ y1lo=l0.p0.y;
+ }
+ if (ydiff1 > 0) {
+ if (y1hi < l1.p1.y || l1.p0.y < y1lo) {
+ return false;
+ }
+ } else {
+ if (y1hi < l1.p0.y || l1.p1.y < y1lo) {
+ return false;
+ }
+ }
+
+ float Cx = l0.p0.x-l1.p0.x;
+ float Cy = l0.p0.y-l1.p0.y;
+ float d = ydiff1*Cx - xdiff1*Cy; /* alpha numerator*/
+ float f = ydiff0*xdiff1 - xdiff0*ydiff1; /* both denominator*/
+ if (f > 0) { /* alpha tests*/
+ if (d < 0 || d > f) {
+ return false;
+ }
+ } else {
+ if (d > 0 || d < f) {
+ return false;
+ }
+ }
+
+ float e = xdiff0*Cy - ydiff0*Cx; /* beta numerator*/
+ if(f > 0) { /* beta tests*/
+ if (e < 0 || e > f) {
+ return false;
+ }
+ } else {
+ if (e > 0 || e < f) {
+ return false;
+ }
+ }
+
+ if (f == 0) {
+ // Theoretically, lines could still intersect in this case, but we don't care
+ // because given numerical inaccuracies, the result is random anyway :-).
+ return false;
+ }
+
+// /*compute intersection coordinates*/
+// float num = d*xdiff0; /* numerator */
+// offset = SAME_SIGNS(num,f) ? f/2 : -f/2; /* round direction*/
+// *x = x1 + (num+offset) / f; /* intersection x */
+//
+// num = d*ydiff0;
+// offset = SAME_SIGNS(num,f) ? f/2 : -f/2;
+// *y = y1 + (num+offset) / f; /* intersection y */
+
+ return true;
+}
+
+// Original code from:
+// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html.
+// Precomputing a bounding box for the polygon would speed this up a lot,
+// but the function hasn't shown up on any profiles so far.
+bool pointInPolygon(const glm::vec2& pt, const vector<glm::vec2>& poly)
+{
+ if (poly.size() < 3) {
+ return false;
+ }
+ bool bPtInPoly = false;
+ for (unsigned i = 0, j = poly.size()-1; i < poly.size(); j = i++) {
+ if (((poly[i].y > pt.y) != (poly[j].y > pt.y)) &&
+ (pt.x < (poly[j].x-poly[i].x)*(pt.y-poly[i].y) / (poly[j].y-poly[i].y)
+ +poly[i].x))
+ {
+ bPtInPoly = !bPtInPoly;
+ }
+ }
+ return bPtInPoly;
+}
+
+glm::vec2 getLineLineIntersection(const glm::vec2& p1, const glm::vec2& v1,
+ const glm::vec2& p2, const glm::vec2& v2)
+{
+ float denom = v2.y*v1.x-v2.x*v1.y;
+ if (fabs(denom) < 0.0000001) {
+ // If the lines are parallel or coincident, we just return p2!
+ return p2;
+ }
+ float numer = v2.x*(p1.y-p2.y) - v2.y*(p1.x-p2.x);
+ float ua = numer/denom;
+
+ return p1+ua*v1;
+
+}
+
+
+}
diff --git a/src/base/GeomHelper.h b/src/base/GeomHelper.h
new file mode 100644
index 0000000..5774231
--- /dev/null
+++ b/src/base/GeomHelper.h
@@ -0,0 +1,51 @@
+//
+// 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
+//
+
+#ifndef _GeomHelper_H_
+#define _GeomHelper_H_
+
+#include "../api.h"
+
+#include "../glm/glm.hpp"
+
+#include <vector>
+
+namespace avg {
+
+struct AVG_API LineSegment {
+public:
+ LineSegment(const glm::vec2& pt0, const glm::vec2& pt1);
+ glm::vec2 p0;
+ glm::vec2 p1;
+
+ bool isPointOver(const glm::vec2& pt);
+};
+
+bool AVG_API lineSegmentsIntersect(const LineSegment& l0, const LineSegment& l1);
+
+bool AVG_API pointInPolygon(const glm::vec2& pt, const std::vector<glm::vec2>& poly);
+
+glm::vec2 AVG_API getLineLineIntersection(const glm::vec2& p1, const glm::vec2& v1,
+ const glm::vec2& p2, const glm::vec2& v2);
+
+}
+#endif
+
diff --git a/src/base/IFrameEndListener.h b/src/base/IFrameEndListener.h
new file mode 100644
index 0000000..6147dbe
--- /dev/null
+++ b/src/base/IFrameEndListener.h
@@ -0,0 +1,37 @@
+//
+// 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
+//
+
+#ifndef _IFrameEndListener_H_
+#define _IFrameEndListener_H_
+
+#include "../api.h"
+
+namespace avg {
+
+class AVG_API IFrameEndListener {
+public:
+ virtual ~IFrameEndListener() {};
+ virtual void onFrameEnd() = 0;
+};
+
+}
+
+#endif
diff --git a/src/base/ILogSink.h b/src/base/ILogSink.h
new file mode 100644
index 0000000..de4c1da
--- /dev/null
+++ b/src/base/ILogSink.h
@@ -0,0 +1,53 @@
+//
+// 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
+
+#ifndef _ILOGHANDLER_H_
+#define _ILOGHANDLER_H_
+
+#include "UTF8String.h"
+
+#ifdef _WIN32
+#include <time.h>
+#else
+#include <sys/time.h>
+#endif
+
+#include <boost/shared_ptr.hpp>
+
+using namespace std;
+
+namespace avg{
+
+typedef unsigned severity_t;
+typedef UTF8String category_t;
+
+class AVG_API ILogSink
+{
+public:
+ virtual void logMessage(const tm* pTime, unsigned millis, const category_t& category,
+ severity_t severity, const UTF8String& sMsg) = 0;
+
+};
+
+typedef boost::shared_ptr<ILogSink> LogSinkPtr;
+
+}
+
+#endif
diff --git a/src/base/IPlaybackEndListener.h b/src/base/IPlaybackEndListener.h
new file mode 100644
index 0000000..f505177
--- /dev/null
+++ b/src/base/IPlaybackEndListener.h
@@ -0,0 +1,38 @@
+//
+// 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
+//
+
+#ifndef _IPlaybackEndListener_H_
+#define _IPlaybackEndListener_H_
+
+#include "../api.h"
+
+namespace avg {
+
+class AVG_API IPlaybackEndListener {
+public:
+ virtual ~IPlaybackEndListener() {};
+ virtual void onPlaybackEnd() = 0;
+};
+
+}
+
+#endif
+
diff --git a/src/base/IPreRenderListener.h b/src/base/IPreRenderListener.h
new file mode 100644
index 0000000..32c244e
--- /dev/null
+++ b/src/base/IPreRenderListener.h
@@ -0,0 +1,35 @@
+//
+// 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
+//
+
+#ifndef _IPreRenderListener_H_
+#define _IPreRenderListener_H_
+
+namespace avg {
+
+class AVG_API IPreRenderListener {
+public:
+ virtual ~IPreRenderListener() {};
+ virtual void onPreRender() = 0;
+};
+
+}
+
+#endif
diff --git a/src/base/Logger.cpp b/src/base/Logger.cpp
new file mode 100644
index 0000000..dd7efe1
--- /dev/null
+++ b/src/base/Logger.cpp
@@ -0,0 +1,280 @@
+//
+// 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 "Logger.h"
+#include "Exception.h"
+#include "StandardLogSink.h"
+#include "OSHelper.h"
+
+#include <boost/algorithm/string.hpp>
+
+#ifdef _WIN32
+#include <Winsock2.h>
+#include <time.h>
+#include <Mmsystem.h>
+#undef ERROR
+#else
+#include <sys/time.h>
+#include <syslog.h>
+#endif
+#include <iostream>
+#include <iomanip>
+
+using namespace std;
+namespace ba = boost::algorithm;
+
+namespace avg {
+ const severity_t Logger::severity::CRITICAL = 50;
+ const severity_t Logger::severity::ERROR = 40;
+ const severity_t Logger::severity::WARNING = 30;
+ const severity_t Logger::severity::INFO = 20;
+ const severity_t Logger::severity::DEBUG = 10;
+ const severity_t Logger::severity::NONE = 0;
+
+ const category_t Logger::category::NONE = UTF8String("NONE");
+ const category_t Logger::category::PROFILE = UTF8String("PROFILE");
+ const category_t Logger::category::PROFILE_VIDEO = UTF8String("PROFILE_V");
+ const category_t Logger::category::EVENTS = UTF8String("EVENTS");
+ const category_t Logger::category::CONFIG = UTF8String("CONFIG");
+ const category_t Logger::category::MEMORY = UTF8String("MEMORY");
+ const category_t Logger::category::APP = UTF8String("APP");
+ const category_t Logger::category::PLUGIN = UTF8String("PLUGIN");
+ const category_t Logger::category::PLAYER = UTF8String("PLAYER");
+ const category_t Logger::category::SHADER = UTF8String("SHADER");
+ const category_t Logger::category::DEPRECATION = UTF8String("DEPREC");
+
+namespace {
+ Logger* s_pLogger = 0;
+ boost::mutex s_logMutex;
+ boost::mutex s_traceMutex;
+ boost::mutex s_sinkMutex;
+ boost::mutex s_removeStdSinkMutex;
+}
+
+boost::mutex Logger::m_CategoryMutex;
+
+Logger * Logger::get()
+{
+ lock_guard lock(s_logMutex);
+ if (!s_pLogger) {
+ s_pLogger = new Logger;
+ }
+ return s_pLogger;
+}
+
+Logger::Logger()
+{
+ m_Severity = severity::WARNING;
+ string sEnvSeverity;
+ bool bEnvSeveritySet = getEnv("AVG_LOG_SEVERITY", sEnvSeverity);
+ if(bEnvSeveritySet) {
+ m_Severity = Logger::stringToSeverity(sEnvSeverity);
+ }
+ setupCategory();
+
+ string sEnvCategories;
+ bool bEnvSet = getEnv("AVG_LOG_CATEGORIES", sEnvCategories);
+ if (bEnvSet) {
+ vector<string> sCategories;
+ ba::split(sCategories, sEnvCategories, ba::is_any_of(" "), ba::token_compress_on);
+ vector<string>::iterator it;
+ for(it=sCategories.begin(); it!=sCategories.end(); it++) {
+ string::size_type pos = (*it).find(":");
+ string sCategory;
+ string sSeverity = "NONE";
+ if(pos == string::npos) {
+ sCategory = *it;
+ } else {
+ vector<string> tmpValues;
+ ba::split( tmpValues, *it, ba::is_any_of(":"), ba::token_compress_on);
+ sCategory = tmpValues.at(0);
+ sSeverity = tmpValues.at(1);
+ }
+ severity_t severity = stringToSeverity(sSeverity);
+ configureCategory(sCategory, severity);
+ }
+ }
+
+ string sDummy;
+ bool bEnvOmitStdErr = getEnv("AVG_LOG_OMIT_STDERR", sDummy);
+ if (!bEnvOmitStdErr) {
+ m_pStdSink = LogSinkPtr(new StandardLogSink);
+ addLogSink(m_pStdSink);
+ }
+}
+
+Logger::~Logger()
+{
+}
+
+void Logger::addLogSink(const LogSinkPtr& logSink)
+{
+ lock_guard lock(s_sinkMutex);
+ m_pSinks.push_back(logSink);
+}
+
+void Logger::removeLogSink(const LogSinkPtr& logSink)
+{
+ lock_guard lock(s_sinkMutex);
+ std::vector<LogSinkPtr>::iterator it;
+ it = find(m_pSinks.begin(), m_pSinks.end(), logSink);
+ if ( it != m_pSinks.end() ) {
+ m_pSinks.erase(it);
+ }
+}
+
+void Logger::removeStdLogSink()
+{
+ lock_guard lock(s_removeStdSinkMutex);
+ if ( m_pStdSink.get()) {
+ removeLogSink(m_pStdSink);
+ m_pStdSink = LogSinkPtr();
+ }
+}
+
+category_t Logger::configureCategory(category_t category, severity_t severity)
+{
+ lock_guard lock(m_CategoryMutex);
+ severity = (severity == Logger::severity::NONE) ? m_Severity : severity;
+ UTF8String sCategory = boost::to_upper_copy(string(category));
+ CatToSeverityMap::iterator it;
+ it = m_CategorySeverities.find(sCategory);
+ if ( it != m_CategorySeverities.end()) {
+ m_CategorySeverities.erase(sCategory);
+ }
+ pair<const category_t, const severity_t> element(sCategory, severity);
+ m_CategorySeverities.insert(element);
+ return sCategory;
+}
+
+CatToSeverityMap Logger::getCategories()
+{
+ return m_CategorySeverities;
+}
+
+void Logger::trace(const UTF8String& sMsg, const category_t& category,
+ severity_t severity) const
+{
+ lock_guard lock(s_traceMutex);
+ struct tm* pTime;
+ #ifdef _WIN32
+ __int64 now;
+ _time64(&now);
+ pTime = _localtime64(&now);
+ DWORD tms = timeGetTime();
+ unsigned millis = unsigned(tms % 1000);
+ #else
+ struct timeval time;
+ gettimeofday(&time, NULL);
+ pTime = localtime(&time.tv_sec);
+ unsigned millis = time.tv_usec/1000;
+ #endif
+ lock_guard lockHandler(s_sinkMutex);
+ std::vector<LogSinkPtr>::const_iterator it;
+ for(it=m_pSinks.begin(); it!=m_pSinks.end(); ++it){
+ (*it)->logMessage(pTime, millis, category, severity, sMsg);
+ }
+}
+
+void Logger::logDebug(const UTF8String& msg, const category_t& category) const
+{
+ log(msg, category, Logger::severity::DEBUG);
+}
+
+void Logger::logInfo(const UTF8String& msg, const category_t& category) const
+{
+ log(msg, category, Logger::severity::INFO);
+}
+
+void Logger::logWarning(const UTF8String& msg, const category_t& category) const
+{
+ log(msg, category, Logger::severity::WARNING);
+}
+
+void Logger::logError(const UTF8String& msg, const category_t& category) const
+{
+ log(msg, category, Logger::severity::ERROR);
+}
+
+void Logger::logCritical(const UTF8String& msg, const category_t& category) const
+{
+ log(msg, category, Logger::severity::CRITICAL);
+}
+
+void Logger::log(const UTF8String& msg, const category_t& category,
+ severity_t severity) const
+{
+ if(shouldLog(category, severity)) {
+ Logger::trace(msg, category, severity);
+ }
+}
+
+void Logger::setupCategory()
+{
+ configureCategory(category::NONE);
+ configureCategory(category::PROFILE);
+ configureCategory(category::PROFILE_VIDEO);
+ configureCategory(category::EVENTS);
+ configureCategory(category::CONFIG);
+ configureCategory(category::MEMORY);
+ configureCategory(category::APP);
+ configureCategory(category::PLUGIN);
+ configureCategory(category::PLAYER);
+ configureCategory(category::SHADER);
+ configureCategory(category::DEPRECATION);
+}
+
+severity_t Logger::stringToSeverity(const string& sSeverity)
+{
+ string severity = boost::to_upper_copy(string(sSeverity));
+ if (severity == "CRIT") {
+ return Logger::severity::CRITICAL;
+ } else if (severity == "ERR") {
+ return Logger::severity::ERROR;
+ } else if (severity == "WARN") {
+ return Logger::severity::WARNING;
+ } else if (severity == "INFO") {
+ return Logger::severity::INFO;
+ } else if (severity == "DBG") {
+ return Logger::severity::DEBUG;
+ } else if (severity == "NONE") {
+ return Logger::severity::NONE;
+ }
+ throw Exception(AVG_ERR_INVALID_ARGS, severity + " is an invalid log severity");
+}
+
+const char * Logger::severityToString(severity_t severity)
+{
+ if(severity == Logger::severity::CRITICAL) {
+ return "CRIT";
+ } else if(severity == Logger::severity::ERROR) {
+ return "ERR";
+ } else if(severity == Logger::severity::WARNING) {
+ return "WARN";
+ } else if(severity == Logger::severity::INFO) {
+ return "INFO";
+ } else if(severity == Logger::severity::DEBUG) {
+ return "DBG";
+ }
+ throw Exception(AVG_ERR_UNKNOWN, "Unkown log severity");
+}
+
+}
diff --git a/src/base/Logger.h b/src/base/Logger.h
new file mode 100644
index 0000000..197c0c2
--- /dev/null
+++ b/src/base/Logger.h
@@ -0,0 +1,154 @@
+//
+// 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
+//
+
+#ifndef _Logger_H_
+#define _Logger_H_
+
+#include "Exception.h"
+#include "ILogSink.h"
+#include "UTF8String.h"
+#include "ThreadHelper.h"
+#include "../api.h"
+
+#include <boost/noncopyable.hpp>
+#include <boost/functional/hash.hpp>
+#include <boost/unordered_map.hpp>
+
+#include <string>
+#include <vector>
+#include <sstream>
+
+#ifdef ERROR
+#undef ERROR
+#endif
+
+namespace avg {
+
+typedef boost::unordered_map< const category_t, const severity_t > CatToSeverityMap;
+
+#ifdef _WIN32
+// non dll-interface class used as base for dll-interface class
+#pragma warning(disable:4275)
+#endif
+class AVG_API Logger: private boost::noncopyable {
+public:
+ struct AVG_API severity
+ {
+ static const severity_t CRITICAL;
+ static const severity_t ERROR;
+ static const severity_t WARNING;
+ static const severity_t INFO;
+ static const severity_t DEBUG;
+ static const severity_t NONE;
+ };
+
+ struct AVG_API category
+ {
+ static const category_t NONE;
+ static const category_t PROFILE;
+ static const category_t PROFILE_VIDEO;
+ static const category_t EVENTS;
+ static const category_t CONFIG;
+ static const category_t MEMORY;
+ static const category_t APP;
+ static const category_t PLUGIN;
+ static const category_t PLAYER;
+ static const category_t SHADER;
+ static const category_t DEPRECATION;
+ };
+
+ static Logger* get();
+ virtual ~Logger();
+
+ static severity_t stringToSeverity(const string& sSeverity);
+ static const char * severityToString(const severity_t severity);
+
+ void addLogSink(const LogSinkPtr& logSink);
+ void removeLogSink(const LogSinkPtr& logSink);
+ void removeStdLogSink();
+
+ category_t configureCategory(category_t category,
+ severity_t severity=severity::NONE);
+ CatToSeverityMap getCategories();
+
+ void trace(const UTF8String& sMsg, const category_t& category,
+ severity_t severity) const;
+ void logDebug(const UTF8String& msg,
+ const category_t& category=category::APP) const;
+ void logInfo(const UTF8String& msg,
+ const category_t& category=category::APP) const;
+ void logWarning(const UTF8String& msg,
+ const category_t& category=category::APP) const;
+ void logError(const UTF8String& msg,
+ const category_t& category=category::APP) const;
+ void logCritical(const UTF8String& msg,
+ const category_t& category=category::APP) const;
+ void log(const UTF8String& msg, const category_t& category=category::APP,
+ severity_t severity=severity::INFO) const;
+
+ inline bool shouldLog(const category_t& category, severity_t severity) const {
+ lock_guard lock(m_CategoryMutex);
+ try {
+ severity_t targetSeverity = m_CategorySeverities.at(category);
+ return (targetSeverity <= severity);
+ } catch (out_of_range e){
+ string msg("Unknown category: " + category);
+ throw Exception(AVG_ERR_INVALID_ARGS, msg);
+ }
+ }
+
+private:
+ Logger();
+ void setupCategory();
+
+ std::vector<LogSinkPtr> m_pSinks;
+ LogSinkPtr m_pStdSink;
+ CatToSeverityMap m_CategorySeverities;
+ severity_t m_Severity;
+ static boost::mutex m_CategoryMutex;
+};
+
+#define AVG_TRACE(category, severity, sMsg) { \
+if (Logger::get()->shouldLog(category, severity)) { \
+ std::stringstream tmp(std::stringstream::in | std::stringstream::out); \
+ tmp << sMsg; \
+ Logger::get()->trace(tmp.str(), category, severity); \
+ }\
+}\
+
+#define AVG_LOG_ERROR(sMsg){ \
+ AVG_TRACE(Logger::category::NONE, Logger::severity::ERROR, sMsg); \
+}\
+
+#define AVG_LOG_WARNING(sMsg){ \
+ AVG_TRACE(Logger::category::NONE, Logger::severity::WARNING, sMsg); \
+}\
+
+#define AVG_LOG_INFO(sMsg){ \
+ AVG_TRACE(Logger::category::NONE, Logger::severity::INFO, sMsg); \
+}\
+
+#define AVG_LOG_DEBUG(sMsg){ \
+ AVG_TRACE(Logger::category::NONE, Logger::severity::DEBUG, sMsg); \
+}\
+
+}
+#endif
diff --git a/src/base/Makefile.am b/src/base/Makefile.am
new file mode 100644
index 0000000..ce995f2
--- /dev/null
+++ b/src/base/Makefile.am
@@ -0,0 +1,35 @@
+SUBDIRS = triangulate
+
+AM_CPPFLAGS = -I.. @XML2_CFLAGS@ @PTHREAD_CFLAGS@
+ALL_H = FileHelper.h Exception.h Logger.h ConfigMgr.h ObjectCounter.h \
+ XMLHelper.h TimeSource.h ProfilingZone.h ThreadProfiler.h \
+ ScopeTimer.h IFrameEndListener.h IPreRenderListener.h IPlaybackEndListener.h \
+ Test.h TestSuite.h OSHelper.h Queue.h WorkerThread.h Command.h ObjectCounter.h \
+ Rect.h Directory.h DirEntry.h StringHelper.h MathHelper.h GeomHelper.h \
+ CubicSpline.h BezierCurve.h UTF8String.h Triangle.h DAG.h \
+ WideLine.h DlfcnWrapper.h Signal.h Backtrace.h \
+ CmdQueue.h ProfilingZoneID.h GLMHelper.h StandardLogSink.h ILogSink.h \
+ ThreadHelper.h
+
+TESTS = testbase
+
+EXTRA_DIST = DlfcnWrapper.cpp
+
+noinst_LTLIBRARIES = libbase.la
+libbase_la_SOURCES = FileHelper.cpp Exception.cpp Logger.cpp \
+ ConfigMgr.cpp XMLHelper.cpp TimeSource.cpp OSHelper.cpp \
+ ProfilingZone.cpp ThreadProfiler.cpp ScopeTimer.cpp Test.cpp \
+ TestSuite.cpp ObjectCounter.cpp Directory.cpp DirEntry.cpp \
+ StringHelper.cpp MathHelper.cpp GeomHelper.cpp CubicSpline.cpp \
+ BezierCurve.cpp UTF8String.cpp Triangle.cpp DAG.cpp WideLine.cpp \
+ Backtrace.cpp ProfilingZoneID.cpp GLMHelper.cpp \
+ WorkerThread.cpp StandardLogSink.cpp ThreadHelper.cpp \
+ $(ALL_H)
+libbase_a_CXXFLAGS = -Wno-format-y2k
+
+noinst_PROGRAMS = testbase
+testbase_SOURCES = testbase.cpp $(ALL_H)
+testbase_LDADD = ./libbase.la ./triangulate/libtriangulate.la \
+ @BOOST_THREAD_LIBS@ @XML2_LIBS@ @PTHREAD_LIBS@
+# -rdynamic needed only for testBacktrace to work under linux.
+testbase_LDFLAGS = -rdynamic
diff --git a/src/base/MathHelper.cpp b/src/base/MathHelper.cpp
new file mode 100644
index 0000000..388859d
--- /dev/null
+++ b/src/base/MathHelper.cpp
@@ -0,0 +1,78 @@
+//
+// 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 "MathHelper.h"
+
+#include <math.h>
+#include <iostream>
+
+using namespace std;
+
+namespace avg {
+
+bool ispow2(int n)
+{
+ return ((n & (n-1)) == 0);
+}
+
+int nextpow2(int n)
+{
+ n--;
+ n |= n >> 1; // handle 2 bit numbers
+ n |= n >> 2; // handle 4 bit numbers
+ n |= n >> 4; // handle 8 bit numbers
+ n |= n >> 8; // handle 16 bit numbers
+ n |= n >> 16; // handle 32 bit numbers
+ n++;
+ return n;
+}
+
+int safeCeil(float d)
+{
+ if (fabs(d-int(d)) < EPSILON) {
+ return int(d);
+ } else {
+ return int(d)+1;
+ }
+}
+
+float invSqrt(float x)
+{
+#if 0
+ // TODO: This gives incorrect results on Athlon X2, gcc 4.2.
+ float xhalf = 0.5f*x;
+ int i = *(int*)&x; // get bits for floating value
+ i = 0x5f3759d5 - (i>>1); // give initial guess y0
+ x = *(float*)&i; // convert bits back to float
+ x *= 1.5f - xhalf*x*x; // newton step, repeating this step
+ // increases accuracy
+ x *= 1.5f - xhalf*x*x;
+ return x;
+#endif
+ return 1/sqrt(x);
+}
+
+bool almostEqual(float d1, float d2, float epsilon)
+{
+ return (fabs(d1-d2)<epsilon);
+}
+
+}
diff --git a/src/base/MathHelper.h b/src/base/MathHelper.h
new file mode 100644
index 0000000..587ff2c
--- /dev/null
+++ b/src/base/MathHelper.h
@@ -0,0 +1,93 @@
+//
+// 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
+//
+
+#ifndef _MathHelper_H_
+#define _MathHelper_H_
+
+#include "../api.h"
+#include <vector>
+#include <set>
+
+#include <math.h>
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+namespace avg {
+
+static const float PI = 3.14159265358979323846f;
+static const float EPSILON = 0.00001f;
+
+bool ispow2(int n);
+
+int nextpow2(int n);
+
+int safeCeil(float d);
+
+bool almostEqual(float d1, float d2, float epsilon=EPSILON);
+
+float invSqrt(float x);
+
+template<class T>
+T sqr(T d)
+{
+ return d*d;
+}
+
+template<class T>
+int sgn(T val)
+{
+ return int(val/fabs(val));
+}
+
+template<class T>
+std::vector<T> vectorFromCArray(int n, T* pData)
+{
+ std::vector<T> v;
+ for (int i=0; i<n; ++i) {
+ v.push_back(*(pData+i));
+ }
+ return v;
+}
+
+template<class T>
+std::vector<std::vector<T> > vector2DFromCArray(int n, int m, T* pData)
+{
+ std::vector<std::vector<T> > v(4, std::vector<T>());
+ for (int i=0; i<n; ++i) {
+ for (int j=0; j<m; ++j) {
+ v[i].push_back(*(pData+j+i*m));
+ }
+ }
+ return v;
+}
+
+#ifndef round
+template<class T>
+T round(T d)
+{
+ return floor(d + 0.5f);
+}
+#endif
+
+}
+#endif
+
diff --git a/src/base/OSHelper.cpp b/src/base/OSHelper.cpp
new file mode 100644
index 0000000..377e725
--- /dev/null
+++ b/src/base/OSHelper.cpp
@@ -0,0 +1,308 @@
+//
+// 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 "OSHelper.h"
+#include "FileHelper.h"
+#include "Logger.h"
+#include "FileHelper.h"
+#include "Exception.h"
+
+#if defined(_WIN32)
+#include <windows.h>
+#include <psapi.h>
+#undef ERROR
+#undef WARNING
+#elif defined(__APPLE__)
+#include <mach-o/dyld.h>
+#include <mach/mach.h>
+#include <sys/utsname.h>
+#elif defined(__linux)
+#include <fstream>
+#include <unistd.h>
+#include <string.h>
+#endif
+
+#include <stdlib.h>
+#include <iostream>
+#include <cstdlib>
+
+using namespace std;
+
+namespace avg {
+
+#ifdef _WIN32
+string getWinErrMsg(unsigned err)
+{
+ LPVOID lpMsgBuf;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf,
+ 0, NULL );
+ string sMsg((char*)lpMsgBuf);
+ LocalFree(lpMsgBuf);
+ return sMsg;
+}
+#endif
+
+#if defined(__linux)
+// Adapted from binreloc
+static char *
+_br_find_exe_for_symbol (const void *symbol)
+{
+ #define SIZE 1024
+ FILE *f;
+ size_t address_string_len;
+ char *address_string, line[SIZE], *found;
+
+ if (symbol == NULL)
+ return (char *) NULL;
+
+ f = fopen ("/proc/self/maps", "r");
+ if (f == NULL)
+ return (char *) NULL;
+
+ address_string_len = 4;
+ address_string = (char *) malloc(address_string_len);
+ found = (char *) NULL;
+
+
+ while (!feof (f)) {
+ char *start_addr, *end_addr, *end_addr_end, *file;
+ void *start_addr_p, *end_addr_p;
+ size_t len;
+
+ if (fgets (line, SIZE, f) == NULL)
+ break;
+
+ /* Sanity check. */
+ if (strstr (line, " r-xp ") == NULL || strchr (line, '/') == NULL)
+ continue;
+
+ /* Parse line. */
+ start_addr = line;
+ end_addr = strchr (line, '-');
+ file = strchr (line, '/');
+
+ /* More sanity check. */
+ if (!(file > end_addr && end_addr != NULL && end_addr[0] == '-'))
+ continue;
+
+ end_addr[0] = '\0';
+ end_addr++;
+ end_addr_end = strchr (end_addr, ' ');
+ if (end_addr_end == NULL)
+ continue;
+
+ end_addr_end[0] = '\0';
+ len = strlen (file);
+ if (len == 0)
+ continue;
+ if (file[len - 1] == '\n')
+ file[len - 1] = '\0';
+
+ /* Get rid of "(deleted)" from the filename. */
+ len = strlen (file);
+ if (len > 10 && strcmp (file + len - 10, " (deleted)") == 0)
+ file[len - 10] = '\0';
+
+ /* I don't know whether this can happen but better safe than sorry. */
+ len = strlen (start_addr);
+ if (len != strlen (end_addr))
+ continue;
+
+
+ /* Transform the addresses into a string in the form of 0xdeadbeef,
+ * then transform that into a pointer. */
+ if (address_string_len < len + 3) {
+ address_string_len = len + 3;
+ address_string = (char *) realloc (address_string, address_string_len);
+ }
+
+ memcpy (address_string, "0x", 2);
+ memcpy (address_string + 2, start_addr, len);
+ address_string[2 + len] = '\0';
+ sscanf (address_string, "%p", &start_addr_p);
+
+ memcpy (address_string, "0x", 2);
+ memcpy (address_string + 2, end_addr, len);
+ address_string[2 + len] = '\0';
+ sscanf (address_string, "%p", &end_addr_p);
+
+
+ if (symbol >= start_addr_p && symbol < end_addr_p) {
+ found = file;
+ break;
+ }
+ }
+
+ free (address_string);
+ fclose (f);
+
+ if (found == NULL)
+ return (char *) NULL;
+ else
+ return strdup (found);
+}
+#endif
+
+string getAvgLibPath()
+{
+#if defined(_WIN32)
+ HMODULE hModule = GetModuleHandle("avg.pyd");
+ char szFilename[1024];
+ DWORD ok = GetModuleFileName(hModule, szFilename, sizeof(szFilename));
+ if (ok == 0) {
+ AVG_LOG_ERROR("getAvgLibPath(): " << getWinErrMsg(GetLastError()));
+ exit(5);
+ }
+ string sPath=getPath(szFilename);
+ return sPath;
+#elif defined(__APPLE__)
+ // We need to iterate through all images attached to the current executable
+ // and figure out which one is the one we are interested in.
+ uint32_t numImages = _dyld_image_count();
+ for (uint32_t i=0; i<numImages; i++) {
+ const char * pszImageName = _dyld_get_image_name(i);
+ string sFilePart=getFilenamePart(pszImageName);
+ if (sFilePart == "avg.so" || sFilePart == "avg.0.so"
+ || sFilePart == "avg.0.0.0.so")
+ {
+ return getPath(pszImageName);
+ }
+ }
+ char path[1024];
+ uint32_t pathLen = sizeof(path);
+ _NSGetExecutablePath(path, &pathLen);
+ return getPath(path);
+#else
+ char* pszFilename;
+ pszFilename = _br_find_exe_for_symbol((const void *)"");
+ return pszFilename;
+#endif
+}
+
+bool getEnv(const string & sName, string & sVal)
+{
+ const char * pszVal = getenv(sName.c_str());
+ if (pszVal) {
+ sVal = pszVal;
+ }
+ return (pszVal != 0);
+}
+
+void setEnv(const string & sName, const string & sVal)
+{
+#ifdef _WIN32
+ SetEnvironmentVariable(sName.c_str(), sVal.c_str());
+#else
+ setenv(sName.c_str(), sVal.c_str(), true);
+#endif
+}
+
+size_t getMemoryUsage()
+{
+#ifdef __APPLE__
+ kern_return_t rc;
+ mach_port_t task;
+ rc = task_for_pid(mach_task_self(), getpid(), &task);
+ AVG_ASSERT(rc == KERN_SUCCESS);
+ struct task_basic_info taskInfo;
+ mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT;
+ rc = task_info(task, TASK_BASIC_INFO, (task_info_t)&taskInfo, &count);
+ AVG_ASSERT(rc == KERN_SUCCESS);
+ return taskInfo.resident_size;
+#else
+#ifdef _WIN32
+ DWORD pid = GetCurrentProcessId();
+ HANDLE hProcess;
+ PROCESS_MEMORY_COUNTERS pmc;
+ hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
+ BOOL bOk = GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc));
+ CloseHandle(hProcess);
+ return pmc.WorkingSetSize;
+#else
+ unsigned vmsize;
+ unsigned rssize;
+ // See 'man proc' for a documentation of this file's contents.
+ std::ifstream f("/proc/self/statm");
+ f >> vmsize >> rssize;
+ return rssize*(size_t)(getpagesize());
+#endif
+#endif
+}
+
+std::string convertUTF8ToFilename(const std::string & sName)
+{
+#ifdef _WIN32
+ // Conversion from utf-8 to something windows can use:
+ // utf-8 long filename -> utf-16 long filename -> utf-16 short filename (8.3)
+ // -> utf-8 short filename (= ASCII short filename).
+ wchar_t wideString[2048];
+ int err1 = MultiByteToWideChar(CP_UTF8, 0, sName.c_str(), sName.size()+1,
+ wideString, 2048);
+ if (err1 == 0) {
+ AVG_LOG_WARNING("Error in unicode conversion (MultiByteToWideChar): " <<
+ getWinErrMsg(GetLastError()));
+ return sName;
+ }
+ wchar_t wideShortFName[2048];
+ DWORD err2 = GetShortPathNameW(wideString, wideShortFName, 1024);
+ if (err2 != 0) {
+ char pShortName[1024];
+ err1 = WideCharToMultiByte(CP_UTF8, 0, wideShortFName, -1, pShortName,
+ 1024, 0, 0);
+ if (err1 == 0) {
+ AVG_LOG_WARNING("Error in unicode conversion (MultiByteToWideChar): " <<
+ getWinErrMsg(GetLastError()));
+ }
+ return pShortName;
+ } else {
+ return sName;
+ }
+#else
+ return sName;
+#endif
+}
+
+#ifdef __APPLE__
+int reallyGetOSXMajorVersion()
+{
+ utsname sysInfo;
+ int rc = uname(&sysInfo);
+ AVG_ASSERT(rc == 0);
+// cerr << sysInfo.sysname << ", " << sysInfo.nodename << ", " << sysInfo.release <<
+// ", " << sysInfo.version << ", " << sysInfo.machine << endl;
+ istringstream ss(sysInfo.release);
+ int major;
+ int minor;
+ int dot;
+ char c;
+ ss >> major >> c >> minor >> c >> dot;
+ return major;
+}
+
+int getOSXMajorVersion()
+{
+ static int major = reallyGetOSXMajorVersion(); // only called once for speed reasons.
+ return major;
+}
+#endif
+}
diff --git a/src/base/OSHelper.h b/src/base/OSHelper.h
new file mode 100644
index 0000000..6abda5a
--- /dev/null
+++ b/src/base/OSHelper.h
@@ -0,0 +1,52 @@
+//
+// 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
+//
+
+#ifndef _OSHelper_H_
+#define _OSHelper_H_
+
+#include "../api.h"
+#include <string>
+
+namespace avg {
+
+#ifdef _WIN32
+std::string getWinErrMsg(unsigned err);
+#endif
+
+std::string getAvgLibPath();
+
+bool getEnv(const std::string & sName, std::string & sVal);
+void setEnv(const std::string & sName, const std::string & sVal);
+
+size_t getMemoryUsage();
+
+// Converts a utf-8-encoded filename to something windows can use.
+// Under other operating systems, returns the input string.
+AVG_API std::string convertUTF8ToFilename(const std::string & sName);
+
+#ifdef __APPLE__
+int getOSXMajorVersion();
+#endif
+
+}
+
+#endif
+
diff --git a/src/base/ObjectCounter.cpp b/src/base/ObjectCounter.cpp
new file mode 100644
index 0000000..e8136b7
--- /dev/null
+++ b/src/base/ObjectCounter.cpp
@@ -0,0 +1,187 @@
+//
+// 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 "ObjectCounter.h"
+#include "Exception.h"
+#include "Logger.h"
+
+#include <boost/thread/mutex.hpp>
+
+#include <iostream>
+#include <sstream>
+#include <vector>
+#include <algorithm>
+
+#ifdef WIN32
+#include <windows.h>
+#include <Dbghelp.h>
+#else
+#include <cxxabi.h>
+#endif
+
+#define DEBUG_ALLOC 1
+
+namespace avg {
+
+using namespace std;
+
+ObjectCounter* ObjectCounter::s_pObjectCounter = 0;
+bool ObjectCounter::s_bDeleted = false;
+boost::mutex * pCounterMutex;
+
+void deleteObjectCounter()
+{
+ delete ObjectCounter::s_pObjectCounter;
+ delete pCounterMutex;
+ ObjectCounter::s_pObjectCounter = 0;
+}
+
+ObjectCounter::ObjectCounter()
+{
+}
+
+ObjectCounter::~ObjectCounter()
+{
+ s_bDeleted = true;
+}
+
+ObjectCounter * ObjectCounter::get()
+{
+ if (!s_pObjectCounter) {
+ if (s_bDeleted) {
+ // This is _after_ the deleteObjectCounter has been called.
+ return 0;
+ } else {
+ s_pObjectCounter = new ObjectCounter;
+ pCounterMutex = new boost::mutex;
+ atexit(deleteObjectCounter);
+ }
+ }
+ return s_pObjectCounter;
+}
+
+void ObjectCounter::incRef(const std::type_info* pType)
+{
+#ifdef DEBUG_ALLOC
+ lock_guard Lock(*pCounterMutex);
+ TypeMap::iterator MapEntry = m_TypeMap.find(pType);
+ if (MapEntry == m_TypeMap.end()) {
+ m_TypeMap[pType] = 1;
+ } else {
+ (MapEntry->second)++;
+ }
+// cerr << "incRef " << demangle(pType->name()) << ":" << m_TypeMap[pType] << endl;
+#endif
+}
+
+void ObjectCounter::decRef(const std::type_info* pType)
+{
+#ifdef DEBUG_ALLOC
+ if (!this) {
+ // This happens if there are counted static objects that are deleted after
+ // s_pObjectCounter has been deleted.
+ return;
+ }
+ lock_guard Lock(*pCounterMutex);
+ TypeMap::iterator MapEntry = m_TypeMap.find(pType);
+ if (MapEntry == m_TypeMap.end()) {
+ cerr << "ObjectCounter for " << demangle(pType->name())
+ << " does not exist." << endl;
+ // Can't decref a type that hasn't been incref'd.
+ AVG_ASSERT(false);
+ } else {
+ (MapEntry->second)--;
+ if (MapEntry->second < 0) {
+ cerr << "ObjectCounter: refcount for " <<
+ demangle(MapEntry->first->name()) <<
+ " < 0" << endl;
+ AVG_ASSERT(false);
+ }
+ }
+// cerr << "decRef " << demangle(pType->name()) << ":" << MapEntry->second << endl;
+#endif
+}
+
+int ObjectCounter::getCount(const std::type_info* pType)
+{
+ TypeMap::iterator MapEntry = m_TypeMap.find(pType);
+ if (MapEntry == m_TypeMap.end()) {
+ return 0;
+ } else {
+ return MapEntry->second;
+ }
+
+}
+
+std::string ObjectCounter::dump()
+{
+ stringstream ss;
+ ss << "Object dump: " << endl;
+ TypeMap::iterator it;
+ vector<string> strings;
+ for (it = m_TypeMap.begin(); it != m_TypeMap.end(); ++it) {
+ stringstream tempStream;
+ if (it->second > 0) {
+ tempStream << " " << demangle(it->first->name()) << ": " << it->second;
+ strings.push_back(tempStream.str());
+ }
+ }
+ sort(strings.begin(), strings.end());
+ for (vector<string>::iterator it=strings.begin(); it != strings.end(); ++it) {
+ ss << *it << endl;
+ }
+ return ss.str();
+}
+
+string ObjectCounter::demangle(string s)
+{
+ int rc;
+ string sResult;
+#ifdef _WIN32
+ char szDemangledName[2048];
+ rc = int(UnDecorateSymbolName(s.c_str(), szDemangledName, sizeof(szDemangledName),
+ UNDNAME_COMPLETE));
+ if (rc) {
+ sResult = szDemangledName;
+ } else {
+ int error = GetLastError();
+ printf("UnDecorateSymbolName returned error %d\n", error);
+ sResult = s;
+ }
+#else
+ char * pszDemangled = abi::__cxa_demangle(s.c_str(), 0, 0, &rc);
+ if (rc) {
+ sResult = s;
+ } else {
+ sResult = pszDemangled;
+ }
+ if (pszDemangled) {
+ free(pszDemangled);
+ }
+#endif
+ return sResult;
+}
+
+TypeMap ObjectCounter::getObjectCount(){
+ return m_TypeMap;
+}
+
+}
diff --git a/src/base/ObjectCounter.h b/src/base/ObjectCounter.h
new file mode 100644
index 0000000..e370723
--- /dev/null
+++ b/src/base/ObjectCounter.h
@@ -0,0 +1,61 @@
+//
+// 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
+//
+
+#ifndef _ObjectCounter_H_
+#define _ObjectCounter_H_
+
+#include "../api.h"
+#include <string>
+#include <map>
+#include <typeinfo>
+
+namespace avg {
+
+typedef std::map<const std::type_info *, int> TypeMap;
+
+class AVG_API ObjectCounter {
+public:
+ static ObjectCounter* get();
+ virtual ~ObjectCounter();
+
+ void incRef(const std::type_info* pType);
+ void decRef(const std::type_info* pType);
+
+ int getCount(const std::type_info* pType);
+
+ std::string demangle(std::string s);
+ std::string dump();
+ TypeMap getObjectCount();
+
+private:
+ ObjectCounter();
+ static void deleteSingleton();
+
+ TypeMap m_TypeMap;
+
+ static ObjectCounter* s_pObjectCounter;
+ static bool s_bDeleted;
+ friend void deleteObjectCounter();
+};
+
+}
+#endif
+
diff --git a/src/base/ProfilingZone.cpp b/src/base/ProfilingZone.cpp
new file mode 100644
index 0000000..9cdbbfe
--- /dev/null
+++ b/src/base/ProfilingZone.cpp
@@ -0,0 +1,91 @@
+//
+// 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 "ProfilingZone.h"
+#include "ObjectCounter.h"
+
+#include <iostream>
+
+using namespace boost;
+using namespace std;
+
+namespace avg {
+
+ProfilingZone::ProfilingZone(const ProfilingZoneID& zoneID)
+ : m_TimeSum(0),
+ m_AvgTime(0),
+ m_NumFrames(0),
+ m_Indent(0),
+ m_ZoneID(zoneID)
+{
+ ObjectCounter::get()->incRef(&typeid(*this));
+}
+
+ProfilingZone::~ProfilingZone()
+{
+ ObjectCounter::get()->decRef(&typeid(*this));
+}
+
+void ProfilingZone::restart()
+{
+ m_NumFrames = 0;
+ m_AvgTime = 0;
+ m_TimeSum = 0;
+}
+
+void ProfilingZone::reset()
+{
+ m_NumFrames++;
+ m_AvgTime = (m_AvgTime*(m_NumFrames-1)+m_TimeSum)/m_NumFrames;
+ m_TimeSum = 0;
+}
+
+long long ProfilingZone::getUSecs() const
+{
+ return m_TimeSum;
+}
+
+long long ProfilingZone::getAvgUSecs() const
+{
+ return m_AvgTime;
+}
+
+void ProfilingZone::setIndentLevel(int indent)
+{
+ m_Indent = indent;
+}
+
+int ProfilingZone::getIndentLevel() const
+{
+ return m_Indent;
+}
+
+string ProfilingZone::getIndentString() const
+{
+ return string(m_Indent, ' ');
+}
+
+const string& ProfilingZone::getName() const
+{
+ return m_ZoneID.getName();
+}
+
+}
diff --git a/src/base/ProfilingZone.h b/src/base/ProfilingZone.h
new file mode 100644
index 0000000..0d0ee42
--- /dev/null
+++ b/src/base/ProfilingZone.h
@@ -0,0 +1,69 @@
+//
+// 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
+//
+
+#ifndef _ProfilingZone_H_
+#define _ProfilingZone_H_
+
+#include "../api.h"
+#include "ProfilingZoneID.h"
+#include "TimeSource.h"
+
+#include <boost/shared_ptr.hpp>
+
+namespace avg {
+
+class AVG_API ProfilingZone
+{
+public:
+ ProfilingZone(const ProfilingZoneID& zoneID);
+ virtual ~ProfilingZone();
+ void restart();
+
+ void start()
+ {
+ m_StartTime = TimeSource::get()->getCurrentMicrosecs();
+ };
+ void stop()
+ {
+ m_TimeSum += TimeSource::get()->getCurrentMicrosecs()-m_StartTime;
+ };
+ void reset();
+ long long getUSecs() const;
+ long long getAvgUSecs() const;
+ void setIndentLevel(int indent);
+ int getIndentLevel() const;
+ std::string getIndentString() const;
+ const std::string& getName() const;
+
+private:
+ long long m_TimeSum;
+ long long m_AvgTime;
+ long long m_StartTime;
+ int m_NumFrames;
+ int m_Indent;
+ const ProfilingZoneID& m_ZoneID;
+};
+
+typedef boost::shared_ptr<ProfilingZone> ProfilingZonePtr;
+
+}
+
+#endif
diff --git a/src/base/ProfilingZoneID.cpp b/src/base/ProfilingZoneID.cpp
new file mode 100644
index 0000000..7256887
--- /dev/null
+++ b/src/base/ProfilingZoneID.cpp
@@ -0,0 +1,57 @@
+//
+// 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 "ProfilingZoneID.h"
+#include "ThreadProfiler.h"
+
+using namespace std;
+
+namespace avg {
+
+ProfilingZoneID::ProfilingZoneID(const string& sName, bool bMultithreaded)
+ : m_sName(sName),
+ m_bMultithreaded(bMultithreaded),
+ m_pProfiler(0)
+{
+}
+
+ProfilingZoneID::~ProfilingZoneID()
+{
+}
+
+const string& ProfilingZoneID::getName() const
+{
+ return m_sName;
+}
+
+ThreadProfiler* ProfilingZoneID::getProfiler()
+{
+ if (!m_pProfiler) {
+ if (m_bMultithreaded) {
+ return ThreadProfiler::get();
+ } else {
+ m_pProfiler = ThreadProfiler::get();
+ }
+ }
+ return m_pProfiler;
+}
+
+}
diff --git a/src/base/ProfilingZoneID.h b/src/base/ProfilingZoneID.h
new file mode 100644
index 0000000..ca4d637
--- /dev/null
+++ b/src/base/ProfilingZoneID.h
@@ -0,0 +1,50 @@
+//
+// 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
+//
+
+#ifndef _ProfilingZoneID_H_
+#define _ProfilingZoneID_H_
+
+#include "../api.h"
+
+#include <string>
+
+namespace avg {
+
+class ThreadProfiler;
+
+class AVG_API ProfilingZoneID
+{
+public:
+ ProfilingZoneID(const std::string& sName, bool bMultithreaded=false);
+ ~ProfilingZoneID();
+
+ const std::string& getName() const;
+ ThreadProfiler* getProfiler();
+
+private:
+ std::string m_sName;
+ bool m_bMultithreaded;
+ ThreadProfiler* m_pProfiler;
+};
+
+}
+
+#endif
diff --git a/src/base/Queue.h b/src/base/Queue.h
new file mode 100644
index 0000000..36a0eba
--- /dev/null
+++ b/src/base/Queue.h
@@ -0,0 +1,160 @@
+//
+// 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
+//
+
+#ifndef _Queue_H_
+#define _Queue_H_
+
+#include "../api.h"
+#include "Exception.h"
+
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include <deque>
+#include <iostream>
+
+namespace avg {
+
+typedef boost::unique_lock<boost::mutex> unique_lock;
+
+template<class QElement>
+class AVG_TEMPLATE_API Queue
+{
+public:
+ typedef boost::shared_ptr<QElement> QElementPtr;
+
+ Queue(int maxSize=-1);
+ virtual ~Queue();
+
+ bool empty() const;
+ QElementPtr pop(bool bBlock = true);
+ void clear();
+ void push(const QElementPtr& pElem);
+ QElementPtr peek(bool bBlock = true) const;
+ int size() const;
+ int getMaxSize() const;
+
+private:
+ QElementPtr getFrontElement(bool bBlock, unique_lock& Lock) const;
+
+ std::deque<QElementPtr> m_pElements;
+ mutable boost::mutex m_Mutex;
+ mutable boost::condition m_Cond;
+ int m_MaxSize;
+};
+
+template<class QElement>
+Queue<QElement>::Queue(int maxSize)
+ : m_MaxSize(maxSize)
+{
+}
+
+template<class QElement>
+Queue<QElement>::~Queue()
+{
+}
+
+template<class QElement>
+bool Queue<QElement>::empty() const
+{
+ unique_lock Lock(m_Mutex);
+ return m_pElements.empty();
+}
+
+template<class QElement>
+typename Queue<QElement>::QElementPtr Queue<QElement>::pop(bool bBlock)
+{
+ unique_lock lock(m_Mutex);
+ QElementPtr pElem = getFrontElement(bBlock, lock);
+ if (pElem) {
+ m_pElements.pop_front();
+ m_Cond.notify_one();
+ }
+ return pElem;
+}
+
+template<class QElement>
+void Queue<QElement>::clear()
+{
+ QElementPtr pElem;
+ do {
+ pElem = pop(false);
+ } while (pElem);
+}
+
+template<class QElement>
+typename Queue<QElement>::QElementPtr Queue<QElement>::peek(bool bBlock) const
+{
+ unique_lock lock(m_Mutex);
+ QElementPtr pElem = getFrontElement(bBlock, lock);
+ if (pElem) {
+ m_Cond.notify_one();
+ }
+ return pElem;
+}
+
+template<class QElement>
+void Queue<QElement>::push(const QElementPtr& pElem)
+{
+ assert(pElem);
+ unique_lock lock(m_Mutex);
+ if (m_pElements.size() == (unsigned)m_MaxSize) {
+ while (m_pElements.size() == (unsigned)m_MaxSize) {
+ m_Cond.wait(lock);
+ }
+ }
+ m_pElements.push_back(pElem);
+ m_Cond.notify_one();
+}
+
+template<class QElement>
+int Queue<QElement>::size() const
+{
+ unique_lock lock(m_Mutex);
+ return int(m_pElements.size());
+}
+
+template<class QElement>
+int Queue<QElement>::getMaxSize() const
+{
+ unique_lock lock(m_Mutex);
+ return m_MaxSize;
+}
+
+template<class QElement>
+typename Queue<QElement>::QElementPtr
+ Queue<QElement>::getFrontElement(bool bBlock, unique_lock& lock) const
+{
+ if (m_pElements.empty()) {
+ if (bBlock) {
+ while (m_pElements.empty()) {
+ m_Cond.wait(lock);
+ }
+ } else {
+ return QElementPtr();
+ }
+ }
+ return m_pElements.front();
+}
+
+}
+#endif
diff --git a/src/base/Rect.h b/src/base/Rect.h
new file mode 100644
index 0000000..d668338
--- /dev/null
+++ b/src/base/Rect.h
@@ -0,0 +1,213 @@
+//
+// 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
+//
+
+#ifndef _Rect_H_
+#define _Rect_H_
+
+#include "../api.h"
+
+#include "../base/GLMHelper.h"
+#include "../glm/glm.hpp"
+
+#include <algorithm>
+
+namespace avg {
+
+// Simple rectangle class.
+// If NUM is an integer, contains all points from tl up to but not including
+// br.
+template<class NUM>
+class AVG_TEMPLATE_API Rect
+{
+public:
+ typedef glm::detail::tvec2<NUM> Vec2;
+ Vec2 tl;
+ Vec2 br;
+
+ Rect();
+ Rect(NUM left, NUM top, NUM right, NUM bottom);
+ Rect(const Vec2& TL, const Vec2& BR);
+ template<class ORIGNUM> Rect(const Rect<ORIGNUM>& rc);
+
+ bool operator ==(const Rect<NUM>& rect) const;
+ bool operator !=(const Rect<NUM> & rect) const;
+ NUM width() const;
+ NUM height() const;
+ Vec2 center() const;
+ void setWidth(NUM width);
+ void setHeight(NUM height);
+ void setSize(const Vec2& size);
+ bool contains(const Vec2& pt) const;
+ bool contains(const Rect<NUM>& rect) const;
+ bool intersects(const Rect<NUM>& rect) const;
+ void expand(const Rect<NUM>& rect);
+ void intersect(const Rect<NUM>& rect);
+ Vec2 size() const;
+ Vec2 cropPoint(const Vec2& pt) const;
+};
+
+template<class NUM>
+std::ostream& operator<<( std::ostream& os, const Rect<NUM> &r)
+{
+ os << "(" << r.tl << "-" << r.br << ")";
+ return os;
+}
+
+
+typedef Rect<float> FRect;
+typedef Rect<int> IntRect;
+
+template<class NUM>
+Rect<NUM>::Rect()
+{}
+
+template<class NUM>
+Rect<NUM>::Rect(const Vec2& TL, const Vec2& BR)
+ : tl(TL), br(BR)
+{}
+
+template<class NUM>
+Rect<NUM>::Rect(NUM left, NUM top, NUM right, NUM bottom)
+ : tl(left, top),
+ br(right, bottom)
+{}
+
+template<class NUM>
+template<class ORIGNUM>
+Rect<NUM>::Rect(const Rect<ORIGNUM>& rc)
+ : tl (NUM(rc.tl.x), NUM(rc.tl.y)),
+ br (NUM(rc.br.x), NUM(rc.br.y))
+{
+}
+
+template<class NUM>
+bool Rect<NUM>::operator ==(const Rect<NUM> & rect) const
+{
+ return (tl == rect.tl && br == rect.br);
+}
+
+template<class NUM>
+bool Rect<NUM>::operator !=(const Rect<NUM> & rect) const
+{
+ return !(rect==*this);
+}
+
+template<class NUM>
+NUM Rect<NUM>::width() const
+{
+ return br.x-tl.x;
+}
+
+template<class NUM>
+NUM Rect<NUM>::height() const
+{
+ return br.y-tl.y;
+}
+
+template<class NUM>
+glm::detail::tvec2<NUM> Rect<NUM>::center() const
+{
+ return Vec2(tl+br)/2;
+}
+
+template<class NUM>
+void Rect<NUM>::setWidth(NUM width)
+{
+ br.x = tl.x+width;
+}
+
+template<class NUM>
+void Rect<NUM>::setHeight(NUM height)
+{
+ br.y = tl.y+height;
+}
+
+template<class NUM>
+void Rect<NUM>::setSize(const Vec2& size)
+{
+ setWidth(size.x);
+ setHeight(size.y);
+}
+
+template<class NUM>
+bool Rect<NUM>::contains(const Vec2& pt) const
+{
+ return (pt.x >= tl.x && pt.x < br.x &&
+ pt.y >= tl.y && pt.y < br.y);
+}
+
+template<class NUM>
+bool Rect<NUM>::contains(const Rect<NUM>& rect) const
+{
+ Vec2 brpt (rect.br.x-1, rect.br.y-1);
+ return Contains(rect.tl) && Contains(brpt);
+}
+
+template<class NUM>
+bool Rect<NUM>::intersects(const Rect<NUM>& rect) const
+{
+ if (rect.br.x <= tl.x || rect.tl.x >= br.x ||
+ rect.br.y <= tl.y || rect.tl.y >= br.y)
+ return false;
+ else
+ return true;
+}
+
+template<class NUM>
+void Rect<NUM>::expand(const Rect<NUM>& rect)
+{
+ tl.x = glm::min(tl.x, rect.tl.x);
+ tl.y = glm::min(tl.y, rect.tl.y);
+ br.x = glm::max(br.x, rect.br.x);
+ br.y = glm::max(br.y, rect.br.y);
+}
+
+template<class NUM>
+void Rect<NUM>::intersect(const Rect<NUM>& rect)
+{
+ tl.x = glm::max(tl.x, rect.tl.x);
+ tl.y = glm::max(tl.y, rect.tl.y);
+ br.x = glm::min(br.x, rect.br.x);
+ br.y = glm::min(br.y, rect.br.y);
+}
+
+template<class NUM>
+glm::detail::tvec2<NUM> Rect<NUM>::size() const
+{
+ return Vec2(width(), height());
+}
+
+template<class NUM>
+glm::detail::tvec2<NUM> Rect<NUM>::cropPoint(const Vec2& pt) const
+{
+ Vec2 Result;
+ Result.x = std::min(std::max(pt.x, tl.x), br.x-1);
+ Result.y = std::min(std::max(pt.y, tl.y), br.y-1);
+ return Result;
+}
+
+#undef min
+#undef max
+
+}
+
+#endif
+
diff --git a/src/base/ScopeTimer.cpp b/src/base/ScopeTimer.cpp
new file mode 100644
index 0000000..eb95736
--- /dev/null
+++ b/src/base/ScopeTimer.cpp
@@ -0,0 +1,35 @@
+//
+// 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 "ScopeTimer.h"
+
+using namespace std;
+
+namespace avg {
+
+bool ScopeTimer::s_bTimersEnabled = false;
+
+void ScopeTimer::enableTimers(bool bEnable)
+{
+ s_bTimersEnabled = bEnable;
+}
+
+}
diff --git a/src/base/ScopeTimer.h b/src/base/ScopeTimer.h
new file mode 100644
index 0000000..a87263f
--- /dev/null
+++ b/src/base/ScopeTimer.h
@@ -0,0 +1,60 @@
+//
+// 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
+//
+
+#ifndef _ScopeTimer_H_
+#define _ScopeTimer_H_
+
+#include "../api.h"
+#include "ProfilingZoneID.h"
+#include "ThreadProfiler.h"
+
+namespace avg {
+
+class AVG_API ScopeTimer {
+public:
+ ScopeTimer(ProfilingZoneID& zoneID)
+ {
+ if (s_bTimersEnabled) {
+ m_pZoneID = &zoneID;
+ m_pZoneID->getProfiler()->startZone(zoneID);
+ } else {
+ m_pZoneID = 0;
+ }
+ };
+
+ ~ScopeTimer()
+ {
+ if (m_pZoneID) {
+ m_pZoneID->getProfiler()->stopZone(*m_pZoneID);
+ }
+ };
+
+ static void enableTimers(bool bEnable);
+
+private:
+ ProfilingZoneID* m_pZoneID;
+
+ static bool s_bTimersEnabled;
+};
+
+}
+
+#endif
diff --git a/src/base/Signal.h b/src/base/Signal.h
new file mode 100644
index 0000000..b670822
--- /dev/null
+++ b/src/base/Signal.h
@@ -0,0 +1,119 @@
+//
+// 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
+//
+
+#ifndef _Signal_H_
+#define _Signal_H_
+
+#include "../api.h"
+
+#include "Exception.h"
+
+#include <list>
+
+namespace avg {
+
+
+// Simple implementation of a signal/slot mechanism.
+// Might need to be replaced by boost::signal when things get more complicated.
+template <class LISTENEROBJ>
+class AVG_TEMPLATE_API Signal {
+public:
+ typedef void (LISTENEROBJ::*ListenerFunc)() ;
+ Signal(ListenerFunc pFunc);
+ virtual ~Signal();
+
+ void connect(LISTENEROBJ* pListener);
+ void disconnect(LISTENEROBJ* pListener);
+
+ void emit();
+ int getNumListeners() const;
+
+private:
+ ListenerFunc m_pFunc;
+ std::list<LISTENEROBJ*> m_Listeners;
+ typedef typename std::list<LISTENEROBJ*>::iterator ListenerIterator;
+ LISTENEROBJ* m_pCurrentListener;
+ bool m_bKillCurrentListener;
+};
+
+template<class LISTENEROBJ>
+Signal<LISTENEROBJ>::Signal(ListenerFunc pFunc)
+ : m_pFunc(pFunc),
+ m_pCurrentListener(0),
+ m_bKillCurrentListener(false)
+{
+}
+
+template<class LISTENEROBJ>
+Signal<LISTENEROBJ>::~Signal()
+{
+}
+
+template<class LISTENEROBJ>
+void Signal<LISTENEROBJ>::connect(LISTENEROBJ* pListener)
+{
+ ListenerIterator it;
+ it = find(m_Listeners.begin(), m_Listeners.end(), pListener);
+ // If the listener is already connected, something is wrong, unless we're
+ // deleting it at this very moment.
+ AVG_ASSERT(it == m_Listeners.end() ||
+ (*it == m_pCurrentListener && m_bKillCurrentListener));
+ m_Listeners.push_back(pListener);
+}
+
+template<class LISTENEROBJ>
+void Signal<LISTENEROBJ>::disconnect(LISTENEROBJ* pListener)
+{
+ if (m_pCurrentListener == pListener) {
+ m_bKillCurrentListener = true;
+ } else {
+ ListenerIterator it;
+ it = find(m_Listeners.begin(), m_Listeners.end(), pListener);
+ AVG_ASSERT(it != m_Listeners.end());
+ m_Listeners.erase(it);
+ }
+}
+
+template<class LISTENEROBJ>
+void Signal<LISTENEROBJ>::emit()
+{
+ ListenerIterator it;
+ for (it=m_Listeners.begin(); it != m_Listeners.end();) {
+ m_pCurrentListener = *it;
+ ((*it)->*m_pFunc)(); // This is the actual call to the listener.
+ if (m_bKillCurrentListener) {
+ it = m_Listeners.erase(it);
+ m_bKillCurrentListener = false;
+ } else {
+ ++it;
+ }
+ }
+ m_pCurrentListener = 0;
+}
+
+template<class LISTENEROBJ>
+int Signal<LISTENEROBJ>::getNumListeners() const
+{
+ return m_Listeners.size();
+}
+
+}
+#endif
diff --git a/src/base/StandardLogSink.cpp b/src/base/StandardLogSink.cpp
new file mode 100644
index 0000000..510aa0b
--- /dev/null
+++ b/src/base/StandardLogSink.cpp
@@ -0,0 +1,54 @@
+//
+// 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 "StandardLogSink.h"
+#include "Logger.h"
+
+#include <iostream>
+#include <iomanip>
+
+using namespace std;
+
+namespace avg
+{
+
+StandardLogSink::StandardLogSink()
+{
+
+}
+
+StandardLogSink::~StandardLogSink()
+{
+
+}
+
+void StandardLogSink::logMessage(const tm* pTime, unsigned millis,
+ const category_t& category, severity_t severity, const UTF8String& sMsg)
+{
+ char timeString[256];
+ strftime(timeString, sizeof(timeString), "%y-%m-%d %H:%M:%S", pTime);
+ cerr << "[" << timeString << "." <<
+ setw(3) << setfill('0') << millis << setw(0) << "][";
+ cerr << setw(4) << setfill('.') << Logger::severityToString(severity) << "][";
+ cerr << setw(9) << setfill('.') << category << "] : " << sMsg << endl;
+ cerr.flush();
+}
+
+}
diff --git a/src/base/StandardLogSink.h b/src/base/StandardLogSink.h
new file mode 100644
index 0000000..7cbfe2c
--- /dev/null
+++ b/src/base/StandardLogSink.h
@@ -0,0 +1,39 @@
+//
+// 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
+
+#ifndef _StandardLogSink_H_
+#define _StandardLogSink_H_
+
+#include "ILogSink.h"
+
+namespace avg{
+
+class StandardLogSink: public ILogSink
+{
+public:
+ StandardLogSink();
+ virtual ~StandardLogSink ();
+
+ virtual void logMessage(const tm* pTime, unsigned millis, const category_t& category,
+ severity_t severity, const UTF8String& sMsg);
+};
+
+}
+#endif
diff --git a/src/base/StringHelper.cpp b/src/base/StringHelper.cpp
new file mode 100644
index 0000000..6155859
--- /dev/null
+++ b/src/base/StringHelper.cpp
@@ -0,0 +1,145 @@
+//
+// 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 "StringHelper.h"
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <algorithm>
+#include <cstdio>
+#include <iterator>
+
+using namespace std;
+
+namespace avg {
+
+bool isWhitespace(const string& s)
+{
+ return s.find_first_not_of(" \n\r\t") == s.npos;
+}
+
+void skipWhitespace(std::istream& is)
+{
+ string sWhitespace(" \n\r\t");
+ bool bWhitespace;
+ do {
+ int i = is.peek();
+ if (i == EOF) {
+ bWhitespace = false;
+ } else {
+ bWhitespace = (sWhitespace.find(char(i)) != sWhitespace.npos);
+ }
+ if (bWhitespace) {
+ is.ignore();
+ }
+ } while (bWhitespace);
+}
+
+void skipToken(std::istream& is, char token)
+{
+ skipWhitespace(is);
+ int i = is.peek();
+ if (i == token) {
+ is.ignore();
+ } else {
+ is.setstate(ios::failbit);
+ }
+}
+
+int stringToInt(const string& s)
+{
+ int i;
+ fromString(s, i);
+ return i;
+}
+
+float stringToFloat(const string& s)
+{
+ float d;
+ fromString(s, d);
+ return d;
+}
+
+bool stringToBool(const string& s)
+{
+ // avg usually wants xml attributes in lowercase, but python only
+ // sees 'True' as true, so we'll accept that too. Also, python 2.3
+ // has 1 as true, so that has to be ok too.
+ if (s == "True" || s == "true" || s == "1") {
+ return true;
+ }
+ if (s == "False" || s == "false" || s == "0") {
+ return false;
+ }
+ throw (Exception(AVG_ERR_TYPE, string("Could not convert ")+s+" to bool."));
+}
+
+std::string removeStartEndSpaces(const string& s)
+{
+ string sResult = s;
+ while (sResult.size() > 0 && (sResult[0] == ' ' || sResult[0] == '\n'
+ || sResult[0] == '\r' || sResult[0] == '\t'))
+ {
+ sResult.erase(0, 1);
+ }
+ if (sResult.size() == 0) {
+ return sResult;
+ }
+ char c = sResult[sResult.length()-1];
+ while (c == ' ' || c == '\n' || c == '\r' || c == '\t') {
+ sResult.erase(sResult.length()-1, 1);
+ c = sResult[sResult.length()-1];
+ }
+ return sResult;
+}
+
+string toLowerCase(const string& s)
+{
+ string sResult;
+ for (unsigned i=0; i<s.length(); ++i) {
+ sResult.push_back(::tolower(s[i]));
+ }
+ return sResult;
+}
+
+bool equalIgnoreCase(const string& s1, const string& s2)
+{
+ if (s1.length() != s2.length()) {
+ return false;
+ }
+ string sUpper1;
+ string sUpper2;
+ transform(s1.begin(), s1.end(), std::back_inserter(sUpper1), (int(*)(int)) toupper);
+ transform(s2.begin(), s2.end(), std::back_inserter(sUpper2), (int(*)(int)) toupper);
+ return sUpper1 == sUpper2;
+}
+
+string toString(const bool& b)
+{
+ if (b) {
+ return "true";
+ } else {
+ return "false";
+ }
+}
+
+}
+
diff --git a/src/base/StringHelper.h b/src/base/StringHelper.h
new file mode 100644
index 0000000..82713eb
--- /dev/null
+++ b/src/base/StringHelper.h
@@ -0,0 +1,133 @@
+//
+// 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
+//
+
+#ifndef _StringHelper_H_
+#define _StringHelper_H_
+
+#include "../api.h"
+#include "Exception.h"
+
+#include <string>
+#include <sstream>
+#include <typeinfo>
+#include <iostream>
+#include <vector>
+
+#ifdef __GNUC__
+#include <cxxabi.h>
+#endif
+
+namespace avg {
+
+bool AVG_API isWhitespace(const std::string& s);
+void AVG_API skipWhitespace(std::istream& is);
+void AVG_API skipToken(std::istream& is, char token);
+
+template<class T>
+std::istream& operator >>(std::istream& is, std::vector<T>& v)
+{
+ skipToken(is, '(');
+ skipWhitespace(is);
+ int c = is.peek();
+ if (c == ')') {
+ is.ignore();
+ return is;
+ }
+ bool bDone = false;
+ do {
+ T elem;
+ is >> elem;
+ v.push_back(elem);
+ skipWhitespace(is);
+ int c = is.peek();
+ switch(c) {
+ case ',':
+ is.ignore();
+ break;
+ case ')':
+ bDone = true;
+ is.ignore();
+ break;
+ default:
+ is.setstate(std::ios::failbit);
+ bDone = true;
+ }
+ } while (!bDone);
+ return is;
+}
+
+int AVG_API stringToInt(const std::string& s);
+float AVG_API stringToFloat(const std::string& s);
+bool AVG_API stringToBool(const std::string& s);
+
+std::string AVG_API removeStartEndSpaces(const std::string& s);
+
+std::string AVG_API toLowerCase(const std::string& s);
+
+bool AVG_API equalIgnoreCase(const std::string& s1, const std::string& s2);
+
+template<class T>
+std::string toString(const T& i)
+{
+ std::stringstream stream;
+ stream << i;
+ return stream.str();
+}
+
+std::string AVG_API toString(const bool& b);
+
+template<class T>
+std::string getFriendlyTypeName(const T& dummy)
+{
+ std::string sTypeName = typeid(T).name();
+#ifdef __GNUC__
+ int status;
+ char* const pClearName = abi::__cxa_demangle (sTypeName.c_str(), 0, 0, &status);
+ if (status == 0) {
+ sTypeName = pClearName;
+ }
+#endif
+ return sTypeName;
+}
+
+template<class T>
+void fromString(const std::string& s, T& result)
+{
+ std::stringstream stream(s);
+ bool bOk = (stream >> result) != 0;
+ if (bOk) {
+ std::string sLeftover;
+ stream >> sLeftover;
+ bOk = isWhitespace(sLeftover);
+ }
+ if (!bOk) {
+ std::string sTypeName = getFriendlyTypeName(result);
+ throw (Exception(AVG_ERR_TYPE, std::string("Could not convert '")+s
+ + "' to "+sTypeName+"."));
+ }
+}
+
+
+}
+
+
+
+#endif
diff --git a/src/base/Test.cpp b/src/base/Test.cpp
new file mode 100644
index 0000000..b2c0b12
--- /dev/null
+++ b/src/base/Test.cpp
@@ -0,0 +1,114 @@
+//
+// 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 "Test.h"
+
+#include "../base/OSHelper.h"
+
+#include <iostream>
+#include <stdlib.h>
+
+using namespace std;
+
+namespace avg {
+
+string Test::s_sSrcDirName;
+
+Test::Test(const string & sName, int indentLevel)
+ : m_IndentLevel(indentLevel),
+ m_NumSucceeded(0),
+ m_NumFailed(0),
+ m_sName(sName)
+{
+}
+
+Test::~Test()
+{
+}
+
+void Test::test(bool b, const char * pszFile, int line)
+{
+ if (b) {
+ m_NumSucceeded++;
+ } else {
+ cerr << string(m_IndentLevel, ' ') << " ---->> failed at " << pszFile
+ << ", " << line << endl;
+ m_NumFailed++;
+ }
+}
+
+
+bool Test::isOk()
+{
+ return m_NumFailed == 0;
+}
+
+void Test::setFailed()
+{
+ m_NumFailed++;
+}
+
+int Test::getNumSucceeded() const
+{
+ return m_NumSucceeded;
+}
+
+int Test::getNumFailed() const
+{
+ return m_NumFailed;
+}
+
+const std::string& Test::getName() const
+{
+ return m_sName;
+}
+
+void Test::aggregateStatistics(const Test& ChildTest)
+{
+ m_NumSucceeded += ChildTest.getNumSucceeded();
+ m_NumFailed += ChildTest.getNumFailed();
+}
+
+void Test::printResults()
+{
+ if (m_NumFailed == 0) {
+ cerr << string(m_IndentLevel, ' ') << m_sName << " succeeded." << endl;
+ } else {
+ cerr << string(m_IndentLevel, ' ') << "######## " << m_sName <<
+ " failed. ########" << endl;
+ }
+
+}
+
+const string& Test::getSrcDirName()
+{
+ if (s_sSrcDirName == "") {
+ bool bInEnviron = getEnv("srcdir", s_sSrcDirName);
+ if (!bInEnviron) {
+ s_sSrcDirName = ".";
+ }
+ s_sSrcDirName += "/";
+ }
+ return s_sSrcDirName;
+}
+
+}
+
diff --git a/src/base/Test.h b/src/base/Test.h
new file mode 100644
index 0000000..0cc20ba
--- /dev/null
+++ b/src/base/Test.h
@@ -0,0 +1,81 @@
+//
+// 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
+//
+
+#ifndef _Test_H_
+#define _Test_H_
+
+#include "../api.h"
+#include <boost/shared_ptr.hpp>
+
+#include <iostream>
+#include <sstream>
+#include <string>
+
+namespace avg {
+class AVG_API Test
+{
+public:
+ Test(const std::string & sName, int indentLevel);
+ virtual ~Test();
+
+ bool isOk();
+ virtual void runTests() = 0;
+
+ void test(bool b, const char * pszFile, int line);
+ void setFailed();
+
+ int getNumSucceeded() const;
+ int getNumFailed() const;
+ const std::string& getName() const;
+
+ void aggregateStatistics(const Test& childTest);
+ virtual void printResults();
+
+protected:
+ static const std::string& getSrcDirName();
+ static std::string s_sSrcDirName;
+
+ int m_IndentLevel;
+
+private:
+ int m_NumSucceeded;
+ int m_NumFailed;
+ std::string m_sName;
+};
+
+typedef boost::shared_ptr<Test> TestPtr;
+
+#define TEST_FAILED(s) \
+ cerr << string(m_IndentLevel+6, ' ') << s << endl; \
+ test(false, __FILE__, __LINE__);
+
+#define TEST(b) \
+ cerr << string(m_IndentLevel+4, ' ') << " TEST(" << #b << ")" << endl; \
+ test(b, __FILE__, __LINE__);
+
+#define QUIET_TEST(b) \
+ if(!(b)) { \
+ cerr << string(m_IndentLevel+4, ' ') << " TEST(" << #b << ")" << endl; \
+ } \
+ test(b, __FILE__, __LINE__);
+}
+#endif
+
diff --git a/src/base/TestSuite.cpp b/src/base/TestSuite.cpp
new file mode 100644
index 0000000..16a254c
--- /dev/null
+++ b/src/base/TestSuite.cpp
@@ -0,0 +1,72 @@
+//
+// 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 "TestSuite.h"
+#include "Exception.h"
+
+using namespace std;
+
+namespace avg {
+
+TestSuite::TestSuite(const string& sName)
+ : Test(sName, 0)
+{
+}
+
+TestSuite::~TestSuite()
+{
+}
+
+void TestSuite::addTest(TestPtr pNewTest)
+{
+ m_Tests.push_back(pNewTest);
+}
+
+void TestSuite::runTests()
+{
+ cerr << string(m_IndentLevel, ' ') << "Running suite " << getName() << endl;
+ for (unsigned i = 0; i < m_Tests.size(); ++i) {
+ cerr << string(m_IndentLevel, ' ') << " Running "
+ << m_Tests[i]->getName() << endl;
+ try {
+ m_Tests[i]->runTests();
+ aggregateStatistics(*m_Tests[i]);
+ m_Tests[i]->printResults();
+ } catch (Exception& ex) {
+ cerr << string(m_IndentLevel, ' ') << ex.getStr() << endl;
+ setFailed();
+ } catch (std::exception& ex) {
+ cerr << string(m_IndentLevel, ' ') << " ---->> failed, std::exception: "
+ << ex.what() << endl;
+ setFailed();
+ } catch (...) {
+ cerr << string(m_IndentLevel, ' ') <<
+ " ---->> failed, exception caught" << endl;
+ setFailed();
+ }
+ }
+
+ printResults();
+}
+
+
+}
+
diff --git a/src/base/TestSuite.h b/src/base/TestSuite.h
new file mode 100644
index 0000000..124bbc2
--- /dev/null
+++ b/src/base/TestSuite.h
@@ -0,0 +1,49 @@
+//
+// 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
+//
+
+#ifndef _TestSuite_H_
+#define _TestSuite_H_
+
+#include "../api.h"
+#include "Test.h"
+
+#include <iostream>
+#include <sstream>
+#include <vector>
+
+namespace avg {
+class AVG_API TestSuite: public Test
+{
+public:
+ TestSuite(const std::string& sName);
+ virtual ~TestSuite();
+
+ void addTest(TestPtr pNewTest);
+
+ virtual void runTests();
+
+private:
+ std::vector<TestPtr> m_Tests;
+};
+
+}
+#endif
+
diff --git a/src/base/ThreadHelper.cpp b/src/base/ThreadHelper.cpp
new file mode 100644
index 0000000..105e116
--- /dev/null
+++ b/src/base/ThreadHelper.cpp
@@ -0,0 +1,94 @@
+//
+// 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 "ThreadHelper.h"
+#include "OSHelper.h"
+
+#ifdef _WIN32
+#include <Windows.h>
+#endif
+
+namespace avg {
+
+void setAffinityMask(bool bIsMainThread)
+{
+ // The main thread gets the first processor to itself. All other threads share the
+ // rest of the processors available, unless, of course, there is only one processor
+ // in the machine.
+#ifdef linux
+ static cpu_set_t allProcessors;
+ static bool bInitialized = false;
+ if (!bInitialized) {
+ int rc = sched_getaffinity(0, sizeof(allProcessors), &allProcessors);
+ AVG_ASSERT(rc == 0);
+// cerr << "All processors: ";
+// printAffinityMask(allProcessors);
+ bInitialized = true;
+ }
+ cpu_set_t mask;
+ if (bIsMainThread) {
+ CPU_ZERO(&mask);
+ CPU_SET(0, &mask);
+// cerr << "Main Thread: ";
+ } else {
+ mask = allProcessors;
+ if (CPU_COUNT(&mask) > 1) {
+ CPU_CLR(0, &mask);
+ }
+// cerr << "Aux Thread: ";
+ }
+// printAffinityMask(mask);
+ int rc = sched_setaffinity(0, sizeof(mask), &mask);
+ AVG_ASSERT(rc == 0);
+#elif defined _WIN32
+ DWORD processAffinityMask;
+ DWORD systemAffinityMask;
+ BOOL rc = GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask,
+ &systemAffinityMask);
+ AVG_ASSERT(rc == TRUE);
+ DWORD mainThreadMask = 1 << getLowestBitSet(processAffinityMask);
+ DWORD mask;
+ if (bIsMainThread) {
+ mask = mainThreadMask;
+ } else {
+ mask = processAffinityMask & ~mainThreadMask;
+ if (mask == 0) {
+ mask = processAffinityMask;
+ }
+ }
+ DWORD_PTR pPrevMask = SetThreadAffinityMask(GetCurrentThread(), mask);
+ AVG_ASSERT_MSG(pPrevMask != 0, getWinErrMsg(GetLastError()).c_str());
+#endif
+}
+
+unsigned getLowestBitSet(unsigned val)
+{
+ AVG_ASSERT(val != 0); // Doh
+
+ unsigned pos = 0;
+ while (!(val & 1)) {
+ val >>= 1;
+ ++pos;
+ }
+ return pos;
+}
+
+}
diff --git a/src/base/ThreadHelper.h b/src/base/ThreadHelper.h
new file mode 100644
index 0000000..7acf640
--- /dev/null
+++ b/src/base/ThreadHelper.h
@@ -0,0 +1,37 @@
+//
+// 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
+//
+
+#ifndef _ThreadHelper_H_
+#define _ThreadHelper_H_
+
+#include "Exception.h"
+#include <boost/thread.hpp>
+#include <boost/thread/locks.hpp>
+
+namespace avg {
+
+void AVG_API setAffinityMask(bool bIsMainThread);
+typedef boost::lock_guard<boost::mutex> lock_guard;
+unsigned getLowestBitSet(unsigned val);
+
+}
+
+#endif
diff --git a/src/base/ThreadProfiler.cpp b/src/base/ThreadProfiler.cpp
new file mode 100644
index 0000000..1f1a354
--- /dev/null
+++ b/src/base/ThreadProfiler.cpp
@@ -0,0 +1,184 @@
+//
+// 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 "ThreadProfiler.h"
+
+#include "Logger.h"
+#include "Exception.h"
+#include "ProfilingZone.h"
+#include "ScopeTimer.h"
+
+#include <sstream>
+#include <iomanip>
+#include <iostream>
+
+using namespace std;
+using namespace boost;
+
+namespace avg {
+
+thread_specific_ptr<ThreadProfiler*> ThreadProfiler::s_pInstance;
+
+ThreadProfiler* ThreadProfiler::get()
+{
+ if (s_pInstance.get() == 0) {
+ s_pInstance.reset(new (ThreadProfiler*));
+ *s_pInstance = new ThreadProfiler();
+ }
+ return *s_pInstance;
+}
+
+void ThreadProfiler::kill()
+{
+ delete *s_pInstance;
+ s_pInstance.reset();
+}
+
+ThreadProfiler::ThreadProfiler()
+ : m_sName(""),
+ m_LogCategory(Logger::category::PROFILE)
+{
+ m_bRunning = false;
+ ScopeTimer::enableTimers(Logger::get()->shouldLog(m_LogCategory,
+ Logger::severity::INFO));
+}
+
+ThreadProfiler::~ThreadProfiler()
+{
+}
+
+void ThreadProfiler::setLogCategory(category_t category)
+{
+ AVG_ASSERT(!m_bRunning);
+ m_LogCategory = category;
+}
+
+void ThreadProfiler::start()
+{
+ m_bRunning = true;
+}
+
+void ThreadProfiler::restart()
+{
+ ZoneVector::iterator it;
+ for (it = m_Zones.begin(); it != m_Zones.end(); ++it) {
+ (*it)->restart();
+ }
+}
+
+void ThreadProfiler::startZone(const ProfilingZoneID& zoneID)
+{
+ ZoneMap::iterator it = m_ZoneMap.find(&zoneID);
+ // Duplicated code to avoid instantiating a new smart pointer when it's not
+ // necessary.
+ if (it == m_ZoneMap.end()) {
+ ProfilingZonePtr pZone = addZone(zoneID);
+ pZone->start();
+ m_ActiveZones.push_back(pZone);
+ } else {
+ ProfilingZonePtr& pZone = it->second;
+ pZone->start();
+ m_ActiveZones.push_back(pZone);
+ }
+}
+
+void ThreadProfiler::stopZone(const ProfilingZoneID& zoneID)
+{
+ ZoneMap::iterator it = m_ZoneMap.find(&zoneID);
+ ProfilingZonePtr& pZone = it->second;
+ pZone->stop();
+ m_ActiveZones.pop_back();
+}
+
+void ThreadProfiler::dumpStatistics()
+{
+ if (!m_Zones.empty()) {
+ AVG_TRACE(m_LogCategory, Logger::severity::INFO, "Thread " << m_sName);
+ AVG_TRACE(m_LogCategory, Logger::severity::INFO,
+ "Zone name Avg. time");
+ AVG_TRACE(m_LogCategory, Logger::severity::INFO,
+ "--------- ---------");
+
+ ZoneVector::iterator it;
+ for (it = m_Zones.begin(); it != m_Zones.end(); ++it) {
+ AVG_TRACE(m_LogCategory, Logger::severity::INFO,
+ std::setw(35) << std::left
+ << ((*it)->getIndentString()+(*it)->getName())
+ << std::setw(9) << std::right << (*it)->getAvgUSecs());
+ }
+ AVG_TRACE(m_LogCategory, Logger::severity::INFO, "");
+ }
+}
+
+void ThreadProfiler::reset()
+{
+ ZoneVector::iterator it;
+ for (it = m_Zones.begin(); it != m_Zones.end(); ++it) {
+ (*it)->reset();
+ }
+}
+
+int ThreadProfiler::getNumZones()
+{
+ return m_Zones.size();
+}
+
+const std::string& ThreadProfiler::getName() const
+{
+ return m_sName;
+}
+
+void ThreadProfiler::setName(const std::string& sName)
+{
+ m_sName = sName;
+}
+
+
+ProfilingZonePtr ThreadProfiler::addZone(const ProfilingZoneID& zoneID)
+{
+ ProfilingZonePtr pZone(new ProfilingZone(zoneID));
+ m_ZoneMap[&zoneID] = pZone;
+ ZoneVector::iterator it;
+ int parentIndent = -2;
+ if (m_ActiveZones.empty()) {
+ it = m_Zones.end();
+ } else {
+ ProfilingZonePtr pActiveZone = m_ActiveZones.back();
+ bool bParentFound = false;
+ for (it = m_Zones.begin(); it != m_Zones.end(); ++it)
+ {
+ if (pActiveZone == *it) {
+ bParentFound = true;
+ break;
+ }
+ }
+ AVG_ASSERT(bParentFound);
+ parentIndent = pActiveZone->getIndentLevel();
+ ++it;
+ for (; it != m_Zones.end() && (*it)->getIndentLevel() > parentIndent; ++it) {};
+ }
+ m_Zones.insert(it, pZone);
+ pZone->setIndentLevel(parentIndent+2);
+ return pZone;
+}
+
+}
+
diff --git a/src/base/ThreadProfiler.h b/src/base/ThreadProfiler.h
new file mode 100644
index 0000000..a581271
--- /dev/null
+++ b/src/base/ThreadProfiler.h
@@ -0,0 +1,88 @@
+//
+// 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
+//
+
+#ifndef _ThreadProfiler_H_
+#define _ThreadProfiler_H_
+
+#include "../api.h"
+#include "ILogSink.h"
+
+#include <boost/thread.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/thread/tss.hpp>
+
+#include <vector>
+#include <map>
+#if defined(_WIN32) || defined(_LIBCPP_VERSION)
+#include <unordered_map>
+#else
+#include <tr1/unordered_map>
+#endif
+namespace avg {
+
+class ThreadProfiler;
+typedef boost::shared_ptr<ThreadProfiler> ThreadProfilerPtr;
+class ProfilingZone;
+typedef boost::shared_ptr<ProfilingZone> ProfilingZonePtr;
+class ProfilingZoneID;
+
+class AVG_API ThreadProfiler
+{
+public:
+ static ThreadProfiler* get();
+ static void kill();
+ ThreadProfiler();
+ virtual ~ThreadProfiler();
+ void setLogCategory(category_t category);
+
+ void start();
+ void restart();
+ void startZone(const ProfilingZoneID& zoneID);
+ void stopZone(const ProfilingZoneID& zoneID);
+ void dumpStatistics();
+ void reset();
+ int getNumZones();
+
+ const std::string& getName() const;
+ void setName(const std::string& sName);
+
+private:
+ ProfilingZonePtr addZone(const ProfilingZoneID& zoneID);
+ std::string m_sName;
+
+#if defined(_WIN32) || defined(_LIBCPP_VERSION)
+ typedef std::unordered_map<const ProfilingZoneID*, ProfilingZonePtr> ZoneMap;
+#else
+ typedef std::tr1::unordered_map<const ProfilingZoneID*, ProfilingZonePtr> ZoneMap;
+#endif
+ typedef std::vector<ProfilingZonePtr> ZoneVector;
+ ZoneMap m_ZoneMap;
+ ZoneVector m_ActiveZones;
+ ZoneVector m_Zones;
+ bool m_bRunning;
+ category_t m_LogCategory;
+
+ static boost::thread_specific_ptr<ThreadProfiler*> s_pInstance;
+};
+
+}
+
+#endif
diff --git a/src/base/TimeSource.cpp b/src/base/TimeSource.cpp
new file mode 100644
index 0000000..e90575d
--- /dev/null
+++ b/src/base/TimeSource.cpp
@@ -0,0 +1,128 @@
+//
+// 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 "TimeSource.h"
+
+#include "Logger.h"
+#include "Exception.h"
+
+#ifdef _WIN32
+#include <time.h>
+#include <sys/timeb.h>
+#include <windows.h>
+#include <Mmsystem.h>
+#else
+#include <sys/time.h>
+#endif
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <errno.h>
+#include <assert.h>
+#include <iostream>
+#include <sstream>
+#include <unistd.h>
+
+using namespace std;
+
+namespace avg {
+
+TimeSource* TimeSource::m_pTimeSource = 0;
+
+TimeSource * TimeSource::get()
+{
+ if (!m_pTimeSource) {
+#ifdef _WIN32
+ TIMECAPS tc;
+ UINT wTimerRes;
+ MMRESULT err = timeGetDevCaps(&tc, sizeof(TIMECAPS));
+ AVG_ASSERT(err == TIMERR_NOERROR);
+ wTimerRes = max(tc.wPeriodMin, 1);
+ timeBeginPeriod(wTimerRes);
+#endif
+ m_pTimeSource = new TimeSource;
+ }
+ return m_pTimeSource;
+}
+
+TimeSource::TimeSource()
+{
+#ifdef __APPLE__
+ mach_timebase_info(&m_TimebaseInfo);
+#endif
+}
+
+TimeSource::~TimeSource()
+{
+}
+
+long long TimeSource::getCurrentMillisecs()
+{
+ return getCurrentMicrosecs()/1000;
+}
+
+long long TimeSource::getCurrentMicrosecs()
+{
+#ifdef _WIN32
+ return (long long)(timeGetTime())*1000;
+#else
+#ifdef __APPLE__
+ long long systemTime = mach_absolute_time();
+ return (systemTime * m_TimebaseInfo.numer/m_TimebaseInfo.denom)/1000;
+#else
+ struct timespec now;
+ int rc = clock_gettime(CLOCK_MONOTONIC, &now);
+ assert(rc == 0);
+ return ((long long)now.tv_sec)*1000000+now.tv_nsec/1000;
+#endif
+#endif
+}
+
+void TimeSource::sleepUntil(long long targetTime)
+{
+ long long now = getCurrentMillisecs();
+#ifdef __APPLE__
+ if (targetTime > now) {
+ msleep(targetTime-now);
+ }
+#else
+ while (now<targetTime) {
+ if (targetTime-now<=2) {
+ msleep(0);
+ } else {
+ msleep(int(targetTime-now-2));
+ }
+ now = getCurrentMillisecs();
+ }
+#endif
+}
+
+void msleep(int millisecs)
+{
+#if _WIN32
+ Sleep(millisecs);
+#else
+ usleep((long long)(millisecs)*1000);
+#endif
+}
+
+}
+
diff --git a/src/base/TimeSource.h b/src/base/TimeSource.h
new file mode 100644
index 0000000..a4ca9ae
--- /dev/null
+++ b/src/base/TimeSource.h
@@ -0,0 +1,60 @@
+//
+// 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
+//
+
+#ifndef _TimeSource_H_
+#define _TimeSource_H_
+
+#include "../api.h"
+
+#ifdef __APPLE__
+#include <mach/mach_time.h>
+#endif
+
+namespace avg {
+
+
+// This class is a monotonic time source with an undefined start time. Time is guarranteed
+// to increase monotonically. The time source has no jumps and does not go backwards,
+// even if system time is changed.
+class AVG_API TimeSource {
+public:
+ static TimeSource* get();
+ virtual ~TimeSource();
+
+ long long getCurrentMillisecs();
+ long long getCurrentMicrosecs();
+
+ void sleepUntil(long long targetTime);
+
+private:
+ TimeSource();
+#ifdef __APPLE__
+ mach_timebase_info_data_t m_TimebaseInfo;
+#endif
+
+ static TimeSource* m_pTimeSource;
+};
+
+void AVG_API msleep(int millisecs);
+
+}
+
+#endif
diff --git a/src/base/Triangle.cpp b/src/base/Triangle.cpp
new file mode 100644
index 0000000..7efe9f7
--- /dev/null
+++ b/src/base/Triangle.cpp
@@ -0,0 +1,105 @@
+//
+// 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 "Triangle.h"
+
+#include "GLMHelper.h"
+
+#include <math.h>
+
+namespace avg {
+
+Triangle::Triangle(const glm::vec2& P0, const glm::vec2& P1, const glm::vec2& P2)
+ : p0(P0),
+ p1(P1),
+ p2(P2)
+{
+}
+
+Triangle::Triangle()
+{
+}
+
+bool Triangle::operator ==(const Triangle & tri) const
+{
+ return (p0 == tri.p0 && p1 == tri.p1 && p2 == tri.p2);
+}
+
+bool Triangle::isInside(const glm::vec2& pt) const
+{
+/* Slower func that only works for cw triangles.
+
+ glm::vec2 a = p2-p1;
+ glm::vec2 bp = pt-p1;
+ float aCROSSbp = a.x*bp.y - a.y*bp.x;
+ if (aCROSSbp < 0.0) {
+ return false;
+ }
+
+ glm::vec2 b = p0-p2;
+ glm::vec2 cp = pt-p2;
+ float bCROSScp = b.x*cp.y - b.y*cp.x;
+ if (bCROSScp < 0.0) {
+ return false;
+ }
+
+ glm::vec2 c = p1-p0;
+ glm::vec2 ap = pt-p0;
+ float cCROSSap = c.x*ap.y - c.y*ap.x;
+ return cCROSSap >= 0.0;
+*/
+ glm::vec2 v0 = p2 - p0;
+ glm::vec2 v1 = p1 - p0;
+ glm::vec2 v2 = pt - p0;
+
+ float dot00 = glm::dot(v0, v0);
+ float dot01 = glm::dot(v0, v1);
+ float dot02 = glm::dot(v0, v2);
+ float dot11 = glm::dot(v1, v1);
+ float dot12 = glm::dot(v1, v2);
+
+ float invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
+ float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
+ float v = (dot00 * dot12 - dot01 * dot02) * invDenom;
+
+ return (u > 0) && (v > 0) && (u + v < 1);
+
+}
+
+float Triangle::getArea() const
+{
+ return fabs((((p1.x-p0.x)*(p2.y-p0.y)) - ((p1.y-p0.y)*(p2.x-p0.x)))/2);
+}
+
+bool Triangle::isClockwise() const
+{
+ return ((p1.x-p0.x)*(p2.y-p0.y)) - ((p1.y-p0.y)*(p2.x-p0.x)) < 0;
+}
+
+std::ostream& operator<<(std::ostream& os, const Triangle& tri)
+{
+ os << "(" << tri.p0 << "," << tri.p1 << "," << tri.p2 << ")";
+ return os;
+}
+
+
+}
+
diff --git a/src/base/Triangle.h b/src/base/Triangle.h
new file mode 100644
index 0000000..21ad35f
--- /dev/null
+++ b/src/base/Triangle.h
@@ -0,0 +1,52 @@
+//
+// 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
+//
+
+#ifndef _Triangle_H_
+#define _Triangle_H_
+
+#include "../api.h"
+
+#include "../glm/glm.hpp"
+
+#include <iostream>
+
+namespace avg {
+
+struct AVG_API Triangle {
+public:
+ glm::vec2 p0;
+ glm::vec2 p1;
+ glm::vec2 p2;
+
+ Triangle(const glm::vec2& P0, const glm::vec2& P1, const glm::vec2& P2);
+ Triangle();
+
+ bool operator ==(const Triangle & tri) const;
+ bool isInside(const glm::vec2& pt) const;
+ float getArea() const;
+ bool isClockwise() const;
+};
+
+std::ostream& operator<<(std::ostream& os, const Triangle& tri);
+
+}
+
+#endif
diff --git a/src/base/UTF8String.cpp b/src/base/UTF8String.cpp
new file mode 100644
index 0000000..4855364
--- /dev/null
+++ b/src/base/UTF8String.cpp
@@ -0,0 +1,62 @@
+//
+// 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 "UTF8String.h"
+
+#include <iostream>
+
+using namespace std;
+
+namespace avg {
+
+UTF8String::UTF8String()
+{
+}
+
+UTF8String::UTF8String(const string& s)
+ : string(s)
+{
+}
+
+UTF8String::UTF8String(const char * psz)
+ : string(psz)
+{
+
+}
+
+UTF8String& UTF8String::operator =(const string& s)
+{
+ *dynamic_cast<string*>(this) = s;
+ return *this;
+}
+
+UTF8String& UTF8String::operator =(const char* psz)
+{
+ *dynamic_cast<string*>(this) = psz;
+ return *this;
+}
+
+std::size_t hash_value(const avg::UTF8String& x)
+{
+ boost::hash<std::string> hasher;
+ return hasher(x);
+};
+}
diff --git a/src/base/UTF8String.h b/src/base/UTF8String.h
new file mode 100644
index 0000000..3cee69d
--- /dev/null
+++ b/src/base/UTF8String.h
@@ -0,0 +1,46 @@
+//
+// 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
+//
+
+#ifndef _UTF8String_H_
+#define _UTF8String_H_
+
+#include "../api.h"
+#include <boost/functional/hash.hpp>
+#include <string>
+
+namespace avg {
+
+class AVG_TEMPLATE_API UTF8String: public std::string
+{
+public:
+ UTF8String();
+ UTF8String(const std::string& s);
+ UTF8String(const char * psz);
+
+ UTF8String& operator =(const std::string& s);
+ UTF8String& operator =(const char * psz);
+
+};
+
+std::size_t hash_value(const avg::UTF8String& x);
+
+}
+#endif
diff --git a/src/base/WideLine.cpp b/src/base/WideLine.cpp
new file mode 100644
index 0000000..84f4096
--- /dev/null
+++ b/src/base/WideLine.cpp
@@ -0,0 +1,53 @@
+//
+// 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 "WideLine.h"
+
+#include "GLMHelper.h"
+
+namespace avg {
+
+WideLine::WideLine(const glm::vec2& p0, const glm::vec2& p1, float width)
+ : pt0(p0),
+ pt1(p1)
+{
+ glm::vec2 m = glm::normalize(pt1-pt0);
+ glm::vec2 w = glm::vec2(m.y, -m.x)*(width/2);
+ pl0 = p0-w;
+ pr0 = p0+w;
+ pl1 = p1-w;
+ pr1 = p1+w;
+ dir = glm::vec2(w.y, -w.x);
+}
+
+float WideLine::getLen() const
+{
+ return glm::length(pt1-pt0);
+}
+
+std::ostream& operator<<(std::ostream& os, const WideLine& line)
+{
+ os << "(" << line.pt0 << "," << line.pt1 << ")";
+ return os;
+}
+
+}
+
diff --git a/src/base/WideLine.h b/src/base/WideLine.h
new file mode 100644
index 0000000..28584ef
--- /dev/null
+++ b/src/base/WideLine.h
@@ -0,0 +1,48 @@
+//
+// 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
+//
+
+#ifndef _WideLine_H_
+#define _WideLine_H_
+
+#include "../api.h"
+
+#include "../glm/glm.hpp"
+
+#include <iostream>
+
+namespace avg {
+
+struct AVG_API WideLine {
+ WideLine(const glm::vec2& p0, const glm::vec2& p1, float width);
+
+ float getLen() const;
+
+ glm::vec2 pt0, pt1;
+ glm::vec2 pl0, pl1;
+ glm::vec2 pr0, pr1;
+ glm::vec2 dir;
+};
+
+std::ostream& operator<<(std::ostream& os, const WideLine& line);
+
+}
+
+#endif
diff --git a/src/base/WorkerThread.cpp b/src/base/WorkerThread.cpp
new file mode 100644
index 0000000..f2efb0a
--- /dev/null
+++ b/src/base/WorkerThread.cpp
@@ -0,0 +1,41 @@
+//
+// 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 "WorkerThread.h"
+
+#include "OSHelper.h"
+
+namespace avg {
+
+using namespace std;
+
+#ifdef linux
+void printAffinityMask(cpu_set_t& mask)
+{
+ for (int i=0; i<32; ++i) {
+ cerr << int(CPU_ISSET(i, &mask));
+ }
+ cerr << endl;
+}
+#endif
+
+}
+
diff --git a/src/base/WorkerThread.h b/src/base/WorkerThread.h
new file mode 100644
index 0000000..c4cc3c4
--- /dev/null
+++ b/src/base/WorkerThread.h
@@ -0,0 +1,169 @@
+//
+// 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
+//
+
+#ifndef _WorkerThread_H_
+#define _WorkerThread_H_
+
+#include "../api.h"
+#include "Command.h"
+#include "Exception.h"
+#include "Logger.h"
+#include "Queue.h"
+#include "ThreadHelper.h"
+#include "ThreadProfiler.h"
+#include "CmdQueue.h"
+
+#include <boost/shared_ptr.hpp>
+
+#include <iostream>
+
+namespace avg {
+
+
+template<class DERIVED_THREAD>
+class AVG_TEMPLATE_API WorkerThread {
+public:
+ typedef Command<DERIVED_THREAD> Cmd;
+ typedef typename boost::shared_ptr<Cmd> CmdPtr;
+ typedef CmdQueue<DERIVED_THREAD> CQueue;
+ typedef typename boost::shared_ptr<CQueue> CQueuePtr;
+
+ WorkerThread(const std::string& sName, CQueue& CmdQ,
+ category_t logCategory=Logger::category::PROFILE);
+ WorkerThread(WorkerThread const& other);
+ virtual ~WorkerThread();
+ void operator()();
+
+ void waitForCommand();
+ void stop();
+
+protected:
+ int getNumCmdsInQueue() const;
+
+private:
+ virtual bool init();
+ virtual bool work() = 0;
+ virtual void deinit() {};
+
+ void processCommands();
+
+ std::string m_sName;
+ bool m_bShouldStop;
+ CQueue& m_CmdQ;
+ category_t m_LogCategory;
+};
+
+template<class DERIVED_THREAD>
+WorkerThread<DERIVED_THREAD>::WorkerThread(const std::string& sName, CQueue& CmdQ,
+ category_t logCategory)
+ : m_sName(sName),
+ m_bShouldStop(false),
+ m_CmdQ(CmdQ),
+ m_LogCategory(logCategory)
+{
+}
+
+template<class DERIVED_THREAD>
+WorkerThread<DERIVED_THREAD>::WorkerThread(WorkerThread const& other)
+ : m_CmdQ(other.m_CmdQ)
+{
+ m_sName = other.m_sName;
+ m_bShouldStop = other.m_bShouldStop;
+ m_LogCategory = other.m_LogCategory;
+}
+
+template<class DERIVED_THREAD>
+WorkerThread<DERIVED_THREAD>::~WorkerThread()
+{
+}
+
+template<class DERIVED_THREAD>
+void WorkerThread<DERIVED_THREAD>::operator()()
+{
+ try {
+ setAffinityMask(false);
+ ThreadProfiler* pProfiler = ThreadProfiler::get();
+ pProfiler->setName(m_sName);
+ pProfiler->setLogCategory(m_LogCategory);
+ bool bOK;
+ bOK = init();
+ if (!bOK) {
+ return;
+ }
+ pProfiler->start();
+ while (!m_bShouldStop) {
+ bOK = work();
+ if (!bOK) {
+ m_bShouldStop = true;
+ }
+ if (!m_bShouldStop) {
+ processCommands();
+ }
+ }
+ deinit();
+ pProfiler->dumpStatistics();
+ pProfiler->kill();
+ } catch (const Exception& e) {
+ AVG_LOG_ERROR("Uncaught exception in thread " << m_sName << ": " << e.getStr());
+ throw;
+ }
+}
+
+template<class DERIVED_THREAD>
+void WorkerThread<DERIVED_THREAD>::waitForCommand()
+{
+ CmdPtr pCmd = m_CmdQ.pop(true);
+ pCmd->execute(dynamic_cast<DERIVED_THREAD*>(this));
+}
+
+template<class DERIVED_THREAD>
+void WorkerThread<DERIVED_THREAD>::stop()
+{
+ m_bShouldStop = true;
+}
+
+template<class DERIVED_THREAD>
+int WorkerThread<DERIVED_THREAD>::getNumCmdsInQueue() const
+{
+ return m_CmdQ.size();
+}
+
+template<class DERIVED_THREAD>
+bool WorkerThread<DERIVED_THREAD>::init()
+{
+ return true;
+}
+
+template<class DERIVED_THREAD>
+void WorkerThread<DERIVED_THREAD>::processCommands()
+{
+ CmdPtr pCmd = m_CmdQ.pop(false);
+ while (pCmd && !m_bShouldStop) {
+ pCmd->execute(dynamic_cast<DERIVED_THREAD*>(this));
+ if (!m_bShouldStop) {
+ pCmd = m_CmdQ.pop(false);
+ }
+ }
+}
+
+}
+
+#endif
diff --git a/src/base/XMLHelper.cpp b/src/base/XMLHelper.cpp
new file mode 100644
index 0000000..6f362e8
--- /dev/null
+++ b/src/base/XMLHelper.cpp
@@ -0,0 +1,225 @@
+//
+// 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 "XMLHelper.h"
+#include "Exception.h"
+#include "Logger.h"
+
+#include <libxml/parserInternals.h>
+#include <cstring>
+#include <iostream>
+
+using namespace std;
+
+namespace avg {
+
+string getXmlChildrenAsString(const xmlDocPtr xmlDoc, const xmlNodePtr& xmlNode)
+{
+ string s;
+ xmlBufferPtr pBuffer = xmlBufferCreate();
+ xmlNodeDump(pBuffer, xmlDoc, xmlNode, 0, 0);
+
+ s = (const char *)xmlBufferContent(pBuffer);
+ size_t StartPos = s.find('>')+1;
+ size_t EndPos = s.rfind('<')-1;
+ if (StartPos > EndPos) {
+ s = "";
+ } else {
+ s = s.substr(StartPos, EndPos-StartPos+1);
+ }
+ xmlBufferFree(pBuffer);
+ return s;
+}
+
+static xmlExternalEntityLoader DefaultLoaderProc = 0;
+static std::map<string, string> g_DTDMap;
+
+xmlParserInputPtr
+DTDExternalEntityLoader(const char *pURL, const char *pID, xmlParserCtxtPtr ctxt)
+{
+ xmlParserInputPtr ret;
+ /* lookup for the fileID depending on ID */
+ std::map<string, string>::iterator it = g_DTDMap.find(pURL);
+
+ if (it != g_DTDMap.end()) {
+ ret = xmlNewStringInputStream(ctxt, (const xmlChar *)(it->second.c_str()));
+ return(ret);
+ } else {
+ ret = DefaultLoaderProc(pURL, pID, ctxt);
+ return(ret);
+ }
+}
+
+void registerDTDEntityLoader(const string& sID, const string& sDTD)
+{
+ g_DTDMap[sID] = sDTD;
+ if (!DefaultLoaderProc) {
+ DefaultLoaderProc = xmlGetExternalEntityLoader();
+ }
+ xmlSetExternalEntityLoader(DTDExternalEntityLoader);
+}
+
+
+XMLParser::XMLParser()
+ : m_SchemaParserCtxt(0),
+ m_Schema(0),
+ m_SchemaValidCtxt(0),
+ m_DTD(0),
+ m_DTDValidCtxt(0),
+ m_Doc(0)
+{
+ xmlPedanticParserDefault(1);
+ xmlSetGenericErrorFunc(this, errorOutputFunc);
+ xmlDoValidityCheckingDefaultValue = 0;
+}
+
+XMLParser::~XMLParser()
+{
+ if (m_Schema) {
+ xmlSchemaFree(m_Schema);
+ }
+ if (m_SchemaParserCtxt) {
+ xmlSchemaFreeParserCtxt(m_SchemaParserCtxt);
+ }
+ if (m_SchemaValidCtxt) {
+ xmlSchemaFreeValidCtxt(m_SchemaValidCtxt);
+ }
+ if (m_DTD) {
+ xmlFreeDtd(m_DTD);
+ }
+ if (m_DTDValidCtxt) {
+ xmlFreeValidCtxt(m_DTDValidCtxt);
+ }
+ if (m_Doc) {
+ xmlFreeDoc(m_Doc);
+ }
+ xmlSetGenericErrorFunc(0, 0);
+}
+
+void XMLParser::setSchema(const string& sSchema, const string& sSchemaName)
+{
+ AVG_ASSERT(!m_SchemaParserCtxt);
+ AVG_ASSERT(!m_Schema);
+ AVG_ASSERT(!m_SchemaValidCtxt);
+ AVG_ASSERT(!m_DTD);
+ AVG_ASSERT(!m_DTDValidCtxt);
+
+ m_SchemaParserCtxt = xmlSchemaNewMemParserCtxt(sSchema.c_str(), sSchema.length());
+ checkError(!m_SchemaParserCtxt, sSchemaName);
+
+ m_Schema = xmlSchemaParse(m_SchemaParserCtxt);
+ checkError(!m_Schema, sSchemaName);
+
+ m_SchemaValidCtxt = xmlSchemaNewValidCtxt(m_Schema);
+ checkError(!m_SchemaValidCtxt, sSchemaName);
+}
+
+void XMLParser::setDTD(const std::string& sDTD, const std::string& sDTDName)
+{
+ AVG_ASSERT(!m_SchemaParserCtxt);
+ AVG_ASSERT(!m_Schema);
+ AVG_ASSERT(!m_SchemaValidCtxt);
+ AVG_ASSERT(!m_DTD);
+ AVG_ASSERT(!m_DTDValidCtxt);
+
+ registerDTDEntityLoader("memory.dtd", sDTD.c_str());
+ string sDTDFName = "memory.dtd";
+ m_DTD = xmlParseDTD(NULL, (const xmlChar*) sDTDFName.c_str());
+ checkError(!m_DTD, sDTDName);
+
+ m_DTDValidCtxt = xmlNewValidCtxt();
+ checkError(!m_DTDValidCtxt, sDTDName);
+ m_DTDValidCtxt->error = xmlParserValidityError;
+ m_DTDValidCtxt->warning = xmlParserValidityWarning;
+}
+
+void XMLParser::parse(const string& sXML, const string& sXMLName)
+{
+ if (m_Doc) {
+ xmlFreeDoc(m_Doc);
+ }
+ m_Doc = xmlParseMemory(sXML.c_str(), int(sXML.length()));
+ checkError(!m_Doc, sXMLName);
+
+ bool bOK = true;
+ if (m_SchemaValidCtxt) {
+ int err = xmlSchemaValidateDoc(m_SchemaValidCtxt, m_Doc);
+ AVG_ASSERT(err != -1);
+ bOK = (err == 0);
+ }
+ if (m_DTD) {
+ int err = xmlValidateDtd(m_DTDValidCtxt, m_Doc, m_DTD);
+ bOK = (err != 0);
+ }
+ if (!bOK) {
+ xmlFreeDoc(m_Doc);
+ m_Doc = 0;
+ checkError(true, sXMLName);
+ }
+}
+
+xmlDocPtr XMLParser::getDoc()
+{
+ AVG_ASSERT(m_Doc);
+ return m_Doc;
+}
+
+xmlNodePtr XMLParser::getRootNode()
+{
+ AVG_ASSERT(m_Doc);
+ return xmlDocGetRootElement(m_Doc);
+}
+
+void XMLParser::errorOutputFunc(void * ctx, const char * msg, ...)
+{
+ va_list args;
+ va_start(args, msg);
+ ((XMLParser*)ctx)->internalErrorHandler(msg, args);
+ va_end(args);
+}
+
+void XMLParser::internalErrorHandler(const char * msg, va_list args)
+{
+ char psz[1024];
+ vsnprintf(psz, 1024, msg, args);
+ m_sError += psz;
+}
+
+void XMLParser::checkError(bool bError, const string& sXMLName)
+{
+ if (bError) {
+ string sError = "Error parsing "+sXMLName+".\n";
+ sError += m_sError;
+ m_sError = "";
+ throw (Exception(AVG_ERR_XML_PARSE, sError));
+ }
+}
+
+void validateXml(const string& sXML, const string& sSchema, const string& sXMLName,
+ const string& sSchemaName)
+{
+ XMLParser parser;
+ parser.setSchema(sSchema, sSchemaName);
+
+ parser.parse(sXML, sXMLName);
+}
+
+}
diff --git a/src/base/XMLHelper.h b/src/base/XMLHelper.h
new file mode 100644
index 0000000..e258de2
--- /dev/null
+++ b/src/base/XMLHelper.h
@@ -0,0 +1,78 @@
+//
+// 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
+//
+
+#ifndef _XMLHelper_H_
+#define _XMLHelper_H_
+
+#include "../api.h"
+
+#include <libxml/parser.h>
+#include <libxml/xmlwriter.h>
+#include <libxml/xmlschemas.h>
+
+#include <string>
+#include <map>
+#include <sstream>
+
+namespace avg {
+
+std::string getXmlChildrenAsString(const xmlDocPtr xmlDoc, const xmlNodePtr& xmlNode);
+
+void registerDTDEntityLoader(const std::string& sID, const std::string& sDTD);
+
+class XMLParser
+{
+public:
+ XMLParser();
+ virtual ~XMLParser();
+
+ void setSchema(const std::string& sSchema, const std::string& sSchemaName);
+ void setDTD(const std::string& sDTD, const std::string& sDTDName);
+ void parse(const std::string& sXML, const std::string& sXMLName);
+
+ xmlDocPtr getDoc();
+ xmlNodePtr getRootNode();
+
+private:
+ static void errorOutputFunc(void * ctx, const char * msg, ...);
+ void internalErrorHandler(const char * msg, va_list args);
+
+ void checkError(bool bError, const std::string& sXMLName);
+
+ xmlSchemaParserCtxtPtr m_SchemaParserCtxt;
+ xmlSchemaPtr m_Schema;
+ xmlSchemaValidCtxtPtr m_SchemaValidCtxt;
+
+ xmlDtdPtr m_DTD;
+ xmlValidCtxtPtr m_DTDValidCtxt;
+
+ xmlDocPtr m_Doc;
+
+ std::string m_sError;
+};
+
+void validateXml(const std::string& sXML, const std::string& sSchema,
+ const std::string& sXMLName, const std::string& sSchemaName);
+
+}
+
+#endif
+
diff --git a/src/base/testbase.cpp b/src/base/testbase.cpp
new file mode 100644
index 0000000..57faf36
--- /dev/null
+++ b/src/base/testbase.cpp
@@ -0,0 +1,1024 @@
+//
+// 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 "DAG.h"
+#include "Queue.h"
+#include "Command.h"
+#include "WorkerThread.h"
+#include "ObjectCounter.h"
+#include "triangulate/Triangulate.h"
+#include "GLMHelper.h"
+#include "GeomHelper.h"
+#include "OSHelper.h"
+#include "FileHelper.h"
+#include "StringHelper.h"
+#include "MathHelper.h"
+#include "CubicSpline.h"
+#include "BezierCurve.h"
+#include "Signal.h"
+#include "Backtrace.h"
+#include "WideLine.h"
+#include "Rect.h"
+#include "Triangle.h"
+#include "TestSuite.h"
+#include "TimeSource.h"
+#include "XMLHelper.h"
+#include "Logger.h"
+
+#include <boost/thread/thread.hpp>
+
+#include <boost/bind.hpp>
+
+#include <iostream>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+
+using namespace avg;
+using namespace std;
+using namespace boost;
+
+class DAGTest: public Test
+{
+public:
+ DAGTest()
+ : Test("DAGTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ {
+ DAG dag;
+
+ dag.addNode(1, set<long>());
+ long outgoing2[] = {1};
+ dag.addNode(0, makeOutgoing(1, outgoing2));
+
+ long expected[] = {0, 1};
+ checkResults(&dag, expected);
+ }
+ {
+ DAG dag;
+
+ dag.addNode(2, set<long>());
+ long outgoing2[] = {1};
+ dag.addNode(0, makeOutgoing(1, outgoing2));
+ long outgoing3[] = {2};
+ dag.addNode(1, makeOutgoing(1, outgoing3));
+
+ long expected[] = {0, 1, 2};
+ checkResults(&dag, expected);
+ }
+ {
+ DAG dag;
+
+ long outgoing2[] = {1};
+ dag.addNode(0, makeOutgoing(1, outgoing2));
+ dag.addNode(2, set<long>());
+ long outgoing3[] = {2};
+ dag.addNode(1, makeOutgoing(1, outgoing3));
+
+ long expected[] = {0, 1, 2};
+ checkResults(&dag, expected);
+ }
+ {
+ DAG dag;
+
+ dag.addNode(2, set<long>());
+ long outgoing2[] = {1, 2};
+ dag.addNode(0, makeOutgoing(1, outgoing2));
+ long outgoing3[] = {2};
+ dag.addNode(1, makeOutgoing(1, outgoing3));
+
+ long expected[] = {0, 1, 2};
+ checkResults(&dag, expected);
+ }
+ {
+ DAG dag;
+
+ long outgoing2[] = {1};
+ dag.addNode(0, makeOutgoing(1, outgoing2));
+ long outgoing3[] = {0};
+ dag.addNode(1, makeOutgoing(1, outgoing3));
+
+ bool bExceptionThrown = false;
+ long expected[] = {0, 1, 2};
+ try {
+ checkResults(&dag, expected);
+ } catch (const Exception&) {
+ bExceptionThrown = true;
+ }
+ TEST(bExceptionThrown);
+ }
+ }
+
+private:
+ set<long> makeOutgoing(int n, long ids[])
+ {
+ set<long> v;
+ for (int i=0; i<n; ++i) {
+ v.insert(ids[i]);
+ }
+ return v;
+ }
+
+ void checkResults(DAG* pDAG, long expected[])
+ {
+ vector<long> results;
+ pDAG->sort(results);
+
+ for (unsigned i=0; i<results.size(); ++i) {
+ QUIET_TEST(results[i] == expected[i]);
+ }
+ }
+};
+
+class QueueTest: public Test
+{
+public:
+ QueueTest()
+ : Test("QueueTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ runSingleThreadTests();
+ runMultiThreadTests();
+ }
+
+private:
+ typedef Queue<int>::QElementPtr ElemPtr;
+
+ void runSingleThreadTests()
+ {
+ Queue<string> q;
+ typedef Queue<string>::QElementPtr ElemPtr;
+ TEST(q.empty());
+ q.push(ElemPtr(new string("1")));
+ TEST(q.size() == 1);
+ TEST(!q.empty());
+ q.push(ElemPtr(new string("2")));
+ q.push(ElemPtr(new string("3")));
+ TEST(q.size() == 3);
+ TEST(*q.pop() == "1");
+ TEST(*q.pop() == "2");
+ q.push(ElemPtr(new string("4")));
+ TEST(*q.pop() == "3");
+ TEST(*q.peek() == "4");
+ TEST(*q.pop() == "4");
+ TEST(q.empty());
+ ElemPtr pElem = q.pop(false);
+ TEST(!pElem);
+ }
+
+ void runMultiThreadTests()
+ {
+ {
+ Queue<int> q(10);
+ thread pusher(boost::bind(&pushThread, &q, 100));
+ thread popper(boost::bind(&popThread, &q, 100));
+ pusher.join();
+ popper.join();
+ TEST(q.empty());
+ }
+ {
+ Queue<int> q(10);
+ thread pusher1(boost::bind(&pushThread, &q, 100));
+ thread pusher2(boost::bind(&pushThread, &q, 100));
+ thread popper(boost::bind(&popThread, &q, 200));
+ pusher1.join();
+ pusher2.join();
+ popper.join();
+ TEST(q.empty());
+ }
+ {
+ Queue<int> q(10);
+ thread pusher(boost::bind(&pushClearThread, &q, 100));
+ thread popper(boost::bind(&popClearThread, &q));
+ pusher.join();
+ popper.join();
+ TEST(q.empty());
+ }
+ }
+
+ static void pushThread(Queue<int>* pq, int numPushes)
+ {
+ for (int i=0; i<numPushes; ++i) {
+ pq->push(ElemPtr(new int(i)));
+ msleep(1);
+ }
+ }
+
+ static void popThread(Queue<int>* pq, int numPops)
+ {
+ for (int i=0; i<numPops; ++i) {
+ pq->peek();
+ pq->pop();
+ msleep(3);
+ }
+ }
+
+ static void pushClearThread(Queue<int>* pq, int numPushes)
+ {
+ typedef Queue<int>::QElementPtr ElemPtr;
+ for (int i=0; i<numPushes; ++i) {
+ pq->push(ElemPtr(new int(i)));
+ if (i%7 == 0) {
+ pq->clear();
+ }
+ msleep(1);
+ }
+ pq->push(ElemPtr(new int(-1)));
+ }
+
+ static void popClearThread(Queue<int>* pq)
+ {
+ ElemPtr pElem;
+ do {
+ pElem = pq->pop();
+ } while (*pElem != -1);
+ }
+};
+
+class TestWorkerThread: public WorkerThread<TestWorkerThread>
+{
+public:
+ TestWorkerThread(CQueue& cmdQ, int* pNumFuncCalls, int* pIntParam,
+ string* pStringParam)
+ : WorkerThread<TestWorkerThread>("Thread1", cmdQ),
+ m_pNumFuncCalls(pNumFuncCalls),
+ m_pIntParam(pIntParam),
+ m_pStringParam(pStringParam)
+ {
+ }
+
+ bool init()
+ {
+ (*m_pNumFuncCalls)++;
+ return true;
+ }
+
+ bool work()
+ {
+ (*m_pNumFuncCalls)++;
+ waitForCommand();
+ return true;
+ }
+
+ void deinit()
+ {
+ (*m_pNumFuncCalls)++;
+ }
+
+ void doSomething(int i, std::string s)
+ {
+ *m_pIntParam = i;
+ *m_pStringParam = s;
+ }
+
+private:
+ int * m_pNumFuncCalls;
+ int * m_pIntParam;
+ std::string * m_pStringParam;
+};
+
+
+class WorkerThreadTest: public Test
+{
+public:
+ WorkerThreadTest()
+ : Test("WorkerThreadTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ typedef TestWorkerThread::CmdPtr CmdPtr;
+ TestWorkerThread::CQueue cmdQ;
+ boost::thread* pTestThread;
+ int numFuncCalls = 0;
+ int intParam = 0;
+ std::string stringParam;
+ cmdQ.pushCmd(boost::bind(&TestWorkerThread::doSomething, _1, 23, "foo"));
+ cmdQ.pushCmd(boost::bind(&TestWorkerThread::stop, _1));
+ pTestThread = new boost::thread(TestWorkerThread(cmdQ, &numFuncCalls,
+ &intParam, &stringParam));
+ pTestThread->join();
+ delete pTestThread;
+ TEST(numFuncCalls == 3);
+ TEST(intParam == 23);
+ TEST(stringParam == "foo");
+ }
+};
+
+
+class DummyClass
+{
+public:
+ DummyClass()
+ {
+ ObjectCounter::get()->incRef(&typeid(*this));
+ }
+
+ virtual ~DummyClass()
+ {
+ ObjectCounter::get()->decRef(&typeid(*this));
+ }
+
+ int i;
+};
+
+
+class ObjectCounterTest: public Test {
+public:
+ ObjectCounterTest()
+ : Test("ObjectCounterTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ TEST(ObjectCounter::get()->getCount(&typeid(DummyClass)) == 0);
+ {
+ DummyClass dummy1;
+ DummyClass dummy2;
+ TEST(ObjectCounter::get()->getCount(&typeid(dummy1)) == 2);
+ }
+ TEST(ObjectCounter::get()->getCount(&typeid(DummyClass)) == 0);
+ }
+};
+
+
+// The following pragmas avoid a compiler warning (potential division by 0)
+#ifdef _MSC_VER
+#pragma optimize("", off)
+#pragma warning(push)
+#pragma warning(disable:4723)
+#endif
+class GeomTest: public Test
+{
+public:
+ GeomTest()
+ : Test("GeomTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ // TODO: Move to a separate math test once we're done here.
+ TEST(almostEqual(invSqrt(1), 1));
+ TEST(almostEqual(invSqrt(4), 0.5));
+
+ {
+ LineSegment l1(glm::vec2(0,0), glm::vec2(2,2));
+ LineSegment l2(glm::vec2(2,0), glm::vec2(0,2));
+ TEST(lineSegmentsIntersect(l1, l2));
+ TEST(lineSegmentsIntersect(l2, l1));
+ }
+ {
+ LineSegment l1(glm::vec2(0,0), glm::vec2(0,2));
+ LineSegment l2(glm::vec2(2,0), glm::vec2(2,2));
+ TEST(!lineSegmentsIntersect(l1, l2));
+ }
+ {
+ LineSegment l1(glm::vec2(0,0), glm::vec2(2,0));
+ LineSegment l2(glm::vec2(0,2), glm::vec2(2,2));
+ TEST(!lineSegmentsIntersect(l1, l2));
+ }
+ {
+ LineSegment l1(glm::vec2(0,0), glm::vec2(2,0));
+ TEST(l1.isPointOver(glm::vec2(1,23)));
+ TEST(l1.isPointOver(glm::vec2(1.9,-5)));
+ TEST(!l1.isPointOver(glm::vec2(-1,1)));
+ TEST(!l1.isPointOver(glm::vec2(3,-1)));
+ }
+ {
+ glm::vec2 pt0(glm::vec2(1,1));
+ glm::vec2 pt1(glm::vec2(1,3));
+ glm::vec2 pt2(glm::vec2(1,-2));
+ vector<glm::vec2> poly;
+ poly.push_back(glm::vec2(0,0));
+ poly.push_back(glm::vec2(2,0));
+ poly.push_back(glm::vec2(2,2));
+ poly.push_back(glm::vec2(0,2));
+ TEST(pointInPolygon(pt0, poly));
+ TEST(!pointInPolygon(pt1, poly));
+ TEST(!pointInPolygon(pt2, poly));
+ poly.push_back(glm::vec2(2,1));
+ TEST(!pointInPolygon(pt0, poly));
+ }
+ {
+ glm::vec2 p1(glm::vec2(0,0));
+ glm::vec2 v1(glm::vec2(1,1));
+ glm::vec2 p2(glm::vec2(2,1));
+ glm::vec2 v2(glm::vec2(1,0));
+ TEST(getLineLineIntersection(p1, v1, p2, v2) == glm::vec2(1,1));
+ }
+ TEST(almostEqual(getRotatedPivot(glm::vec2(10,0), M_PI, glm::vec2(15,5)),
+ glm::vec2(20,10)));
+ TEST(almostEqual(getRotatedPivot(glm::vec2(10,0), M_PI*0.5, glm::vec2(15,5)),
+ glm::vec2(20,0)));
+ TEST(almostEqual(getRotatedPivot(glm::vec2(10,0), M_PI*1.5, glm::vec2(15,5)),
+ glm::vec2(10,10)));
+ TEST(almostEqual(getRotatedPivot(glm::vec2(10,0), M_PI*2, glm::vec2(15,5)),
+ glm::vec2(10,0)));
+ TEST(almostEqual(getRotatedPivot(glm::vec2(23,0), M_PI*0.5), glm::vec2(0,23)));
+
+ {
+ // TODO: More tests
+ FRect(0,0,10,10);
+ }
+ }
+};
+#ifdef _MSC_VER
+#pragma warning(pop)
+#pragma optimize("", on)
+#endif
+
+
+class TriangleTest: public Test
+{
+public:
+ TriangleTest()
+ : Test("TriangleTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ Triangle tri(glm::vec2(0,0), glm::vec2(4,4), glm::vec2(4,8));
+ TEST(tri.isInside(glm::vec2(3,4)));
+ TEST(!tri.isInside(glm::vec2(1,4)));
+ TEST(!tri.isInside(glm::vec2(2,1)));
+ TEST(!tri.isInside(glm::vec2(-2,5)));
+ TEST(!tri.isInside(glm::vec2(5,5)));
+ tri = Triangle(glm::vec2(0,0), glm::vec2(4,8), glm::vec2(4,4));
+ TEST(tri.isInside(glm::vec2(3,4)));
+
+ glm::vec2 polyArray[] = {glm::vec2(0,0), glm::vec2(8,2), glm::vec2(9,0), glm::vec2(9,3),
+ glm::vec2(1,1), glm::vec2(0,3)};
+
+ Vec2Vector poly = vectorFromCArray(6, polyArray);
+ vector<unsigned int> triangulation;
+ triangulatePolygon(triangulation, poly);
+
+ TEST(triangulation.size() == 4*3);
+ unsigned int baselineIndexes[] = {5,0,4, 1,4,0, 4,1,3, 1,2,3};
+ TEST(triangulation == vectorFromCArray(12, baselineIndexes));
+/*
+ for (unsigned int i=0; i<triangulation.size(); i++) {
+ cerr << i << ":" << triangulation[i] << endl;
+ }
+*/
+ }
+
+};
+
+
+class FileTest: public Test
+{
+public:
+ FileTest()
+ : Test("FileTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ TEST(getPath("/foo/bar.txt") == "/foo/");
+ TEST(getFilenamePart("/foo/bar.txt") == "bar.txt");
+ }
+};
+
+
+class OSTest: public Test
+{
+public:
+ OSTest()
+ : Test("OSTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ cerr << getAvgLibPath() << endl;
+ TEST(getAvgLibPath() != "");
+#ifdef __APPLE__
+ TEST(getMemoryUsage() != 0);
+#endif
+ }
+};
+
+
+class StringTest: public Test
+{
+public:
+ StringTest()
+ : Test("StringTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ TEST(stringToInt("5") == 5);
+ TEST(almostEqual(stringToFloat("5.5"), 5.5f));
+ TEST(stringToBool("False") == false);
+ bool bExceptionThrown = false;
+ try {
+ stringToInt("5a");
+ } catch (const Exception& e) {
+ if (e.getCode() == AVG_ERR_TYPE ) {
+ bExceptionThrown = true;
+ }
+ }
+ TEST(bExceptionThrown);
+ TEST(stringToVec2(" ( 3.4 , 2.1 ) ") == glm::vec2(3.4f, 2.1f));
+ vector<float> v;
+ fromString("(1,2,3,4,5)", v);
+ TEST(v.size() == 5 && v[0] == 1 && v[4] == 5);
+ v.clear();
+ fromString("()", v);
+ TEST(v.size() == 0);
+ }
+};
+
+
+class SplineTest: public Test
+{
+public:
+ SplineTest()
+ : Test("SplineTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ {
+ float xd[] = {0,1,2,3};
+ vector<float> x = vectorFromCArray(4, xd);
+ float yd[] = {3,2,1,0};
+ vector<float> y = vectorFromCArray(4, yd);
+ CubicSpline spline(x, y);
+ TEST(almostEqual(spline.interpolate(-1), 4));
+ TEST(almostEqual(spline.interpolate(0), 3));
+ TEST(almostEqual(spline.interpolate(0.5), 2.5));
+ TEST(almostEqual(spline.interpolate(3), 0));
+ TEST(almostEqual(spline.interpolate(3.5), -0.5));
+ }
+ {
+ float xd[] = {2,4,6,8};
+ vector<float> x = vectorFromCArray(4, xd);
+ float yd[] = {0,1,3,6};
+ vector<float> y = vectorFromCArray(4, yd);
+ CubicSpline spline(x, y);
+ TEST(almostEqual(spline.interpolate(0), -1));
+ TEST(almostEqual(spline.interpolate(2), 0));
+ TEST(spline.interpolate(3) < 0.5);
+ TEST(spline.interpolate(3) > 0);
+ TEST(spline.interpolate(7) > 4);
+ TEST(spline.interpolate(7) < 5);
+ TEST(almostEqual(spline.interpolate(8), 6));
+ TEST(almostEqual(spline.interpolate(10), 9));
+ }
+ {
+ float xd[] = {0,1,1};
+ vector<float> x = vectorFromCArray(3, xd);
+ float yd[] = {1,2,1};
+ vector<float> y = vectorFromCArray(3, yd);
+ bool bExceptionThrown = false;
+ try {
+ CubicSpline spline(x, y);
+ } catch (const Exception&) {
+ bExceptionThrown = true;
+ }
+ TEST(bExceptionThrown);
+ }
+/*
+ {
+ float xd[] = {0,1,2};
+ vector<float> x = vectorFromCArray(3, xd);
+ float yd[] = {1,2,1};
+ vector<float> y = vectorFromCArray(3, yd);
+ CubicSpline spline(x, y, true);
+ TEST(almostEqual(spline.interpolate(0), 1));
+ TEST(almostEqual(spline.interpolate(0.5), 1.5));
+ TEST(almostEqual(spline.interpolate(2), 1));
+ TEST(almostEqual(spline.interpolate(3), 2));
+ }
+*/
+ }
+};
+
+
+class BezierCurveTest: public Test
+{
+public:
+ BezierCurveTest()
+ : Test("BezierCurveTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ BezierCurve curve(glm::vec2(0,0), glm::vec2(1,0), glm::vec2(1,1), glm::vec2(0,1));
+ TEST(almostEqual(curve.interpolate(0), glm::vec2(0,0)));
+ TEST(almostEqual(curve.getDeriv(0), glm::vec2(3, 0)));
+ TEST(almostEqual(curve.interpolate(1), glm::vec2(0,1)));
+ TEST(almostEqual(curve.getDeriv(1), glm::vec2(-3, 0)));
+ TEST(almostEqual(curve.interpolate(0.5), glm::vec2(0.75,0.5)));
+ }
+};
+
+
+class WideLineTest: public Test
+{
+public:
+ WideLineTest()
+ : Test("WideLineTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ WideLine line(glm::vec2(0,0), glm::vec2(4,3), 2);
+ TEST(almostEqual(line.getLen(), 5));
+ }
+};
+
+
+class Listener
+{
+public:
+ Listener(Signal<Listener>& signal)
+ : m_Signal(signal),
+ m_bFuncCalled(false)
+ {
+ }
+
+ virtual ~Listener()
+ {}
+
+ virtual void func()
+ {
+ m_bFuncCalled = true;
+ }
+
+ bool funcCalled() const
+ {
+ return m_bFuncCalled;
+ }
+
+ void reset()
+ {
+ m_bFuncCalled = false;
+ }
+
+protected:
+ Signal<Listener>& m_Signal;
+
+private:
+ bool m_bFuncCalled;
+};
+
+
+class DisconnectingSelfListener: public Listener
+{
+public:
+ DisconnectingSelfListener(Signal<Listener>& signal)
+ : Listener(signal)
+ {
+ }
+
+ virtual void func()
+ {
+ Listener::func();
+ m_Signal.disconnect(this);
+ }
+};
+
+
+class DisconnectingOtherListener: public Listener
+{
+public:
+ DisconnectingOtherListener(Signal<Listener>& signal, Listener* pOther)
+ : Listener(signal),
+ m_pOther(pOther)
+ {
+ }
+
+ virtual void func()
+ {
+ Listener::func();
+ if (m_pOther) {
+ m_Signal.disconnect(m_pOther);
+ m_pOther = 0;
+ }
+ }
+
+private:
+ Listener* m_pOther;
+};
+
+
+class ConnectingOtherListener: public Listener
+{
+public:
+ ConnectingOtherListener(Signal<Listener>& signal, Listener* pOther)
+ : Listener(signal),
+ m_pOther(pOther)
+ {
+ }
+
+ virtual void func()
+ {
+ Listener::func();
+ if (m_pOther) {
+ m_Signal.connect(m_pOther);
+ m_pOther = 0;
+ }
+ }
+
+private:
+ Listener* m_pOther;
+};
+
+
+class SignalTest: public Test
+{
+public:
+ SignalTest()
+ : Test("SignalTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ Signal<Listener> s(&Listener::func);
+ Listener l1(s);
+ Listener l2(s);
+ s.connect(&l1);
+ s.connect(&l2);
+ s.emit();
+ TEST(l1.funcCalled() && l2.funcCalled());
+ l1.reset();
+ l2.reset();
+
+ s.disconnect(&l1);
+ s.emit();
+ TEST(!(l1.funcCalled()) && l2.funcCalled());
+ l2.reset();
+
+ {
+ DisconnectingSelfListener disconnecter(s);
+ s.connect(&disconnecter);
+ s.emit();
+ TEST(l2.funcCalled() && disconnecter.funcCalled());
+ TEST(s.getNumListeners() == 1);
+ l2.reset();
+ disconnecter.reset();
+
+ s.emit();
+ TEST(l2.funcCalled() && !(disconnecter.funcCalled()));
+ l2.reset();
+ }
+ {
+ DisconnectingOtherListener disconnecter(s, &l2);
+ s.connect(&disconnecter);
+ s.emit();
+ TEST(l2.funcCalled() && disconnecter.funcCalled());
+ TEST(s.getNumListeners() == 1);
+ l2.reset();
+ disconnecter.reset();
+
+ s.emit();
+ TEST(!(l2.funcCalled()) && disconnecter.funcCalled());
+ s.disconnect(&disconnecter);
+ }
+ {
+ ConnectingOtherListener connecter(s, &l2);
+ s.connect(&connecter);
+ s.emit();
+ TEST(l2.funcCalled() && connecter.funcCalled());
+ TEST(s.getNumListeners() == 2);
+ l2.reset();
+ connecter.reset();
+
+ s.emit();
+ TEST(l2.funcCalled() && connecter.funcCalled());
+ }
+ }
+};
+
+
+class BacktraceTest: public Test
+{
+public:
+ BacktraceTest()
+ : Test("BacktraceTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ vector<string> sFuncs;
+ getBacktrace(sFuncs);
+#ifndef _WIN32
+ TEST(sFuncs[0].find("runTests") != string::npos);
+#endif
+ }
+};
+
+
+class PolygonTest: public Test
+{
+public:
+ PolygonTest()
+ : Test("PolygonTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ glm::vec2 polyArray[] = {glm::vec2(30,0), glm::vec2(40,20), glm::vec2(60,30),
+ glm::vec2(40,40), glm::vec2(30,60), glm::vec2(20,40), glm::vec2(0,30),
+ glm::vec2(20,20)};
+
+ Vec2Vector poly = vectorFromCArray(8, polyArray);
+ vector<unsigned int> triangulation;
+ triangulatePolygon(triangulation, poly);
+
+ TEST(triangulation.size() == 6*3);
+ unsigned int baselineIndexes[] = {6,7,5, 5,7,1, 7,0,1, 5,1,3, 3,1,2, 4,5,3};
+ TEST(triangulation == vectorFromCArray(18, baselineIndexes));
+/*
+ for (unsigned int i=0; i<triangulation.size(); i++) {
+ cerr << i << ":" << triangulation[i] << endl;
+ }/
+*/
+ }
+
+};
+
+
+class XmlParserTest: public Test
+{
+public:
+ XmlParserTest()
+ : Test("XmlParserTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ string sXmlString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<shiporder orderid=\"889923\">"
+ " <orderperson>John Smith</orderperson>"
+ "</shiporder>";
+
+ {
+ string sSchema = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">"
+ "<xs:element name=\"shiporder\">"
+ " <xs:complexType>"
+ " <xs:sequence>"
+ " <xs:element name=\"orderperson\" type=\"xs:string\"/>"
+ " </xs:sequence>"
+ " <xs:attribute name=\"orderid\" type=\"xs:string\" use=\"required\"/>"
+ " </xs:complexType>"
+ "</xs:element>"
+ "</xs:schema>";
+
+ XMLParser parser;
+ parser.setSchema(sSchema, "shiporder.xsd");
+ parser.parse(sXmlString, "shiporder.xml");
+ }
+ {
+ string sDTD =
+ "<!ELEMENT shiporder (orderperson)* >"
+ "<!ATTLIST shiporder"
+ " orderid CDATA #IMPLIED>"
+ "<!ELEMENT orderperson (#PCDATA) >";
+ XMLParser parser;
+ parser.setDTD(sDTD, "shiporder.dtd");
+ parser.parse(sXmlString, "shiporder.xml");
+ }
+ }
+};
+
+
+class StandardLoggerTest: public Test
+{
+public:
+ StandardLoggerTest()
+ : Test("StandardLoggerTest", 2)
+ {
+ }
+
+ void runTests()
+ {
+ std::stringstream buffer;
+ std::streambuf *sbuf = std::cerr.rdbuf();
+ Logger *logger = Logger::get();
+ {
+ std::cerr.rdbuf(buffer.rdbuf());
+ string msg("Test log message");
+ AVG_TRACE(Logger::category::NONE, Logger::severity::WARNING, msg);
+ std::cerr.rdbuf(sbuf);
+ TEST(buffer.str().find(msg) != string::npos);
+ buffer.str(string());
+
+ std::cerr.rdbuf(buffer.rdbuf());
+ AVG_TRACE(Logger::category::NONE, Logger::severity::DEBUG, msg);
+ std::cerr.rdbuf(sbuf);
+ std::cout << buffer.str();
+ TEST(buffer.str().find(msg) == string::npos);
+ buffer.str(string());
+ }
+ {
+ std::cerr.rdbuf(buffer.rdbuf());
+ category_t CUSTOM_CAT = logger->configureCategory("CUSTOM_CAT 1");
+ string msg("CUSTOM_CAT LOG");
+ AVG_TRACE(CUSTOM_CAT, Logger::severity::WARNING, msg);
+ std::cerr.rdbuf(sbuf);
+ TEST(buffer.str().find(msg) != string::npos);
+ buffer.str(string());
+ }
+ {
+ std::cerr.rdbuf(buffer.rdbuf());
+ category_t CUSTOM_CAT = logger->configureCategory("CUSTOM_CAT 1",
+ Logger::severity::CRITICAL);
+ string msg_info("CUSTOM_CAT LOG INFO");
+ AVG_TRACE(CUSTOM_CAT, Logger::severity::WARNING, msg_info);
+ std::cerr.rdbuf(sbuf);
+ TEST(buffer.str().find(msg_info) == string::npos);
+ buffer.str(string());
+
+ std::cerr.rdbuf(buffer.rdbuf());
+ string msg_critical("CUSTOM_CAT LOG CRITICAL");
+ AVG_TRACE(CUSTOM_CAT, Logger::severity::CRITICAL, msg_critical);
+ std::cerr.rdbuf(sbuf);
+ TEST(buffer.str().find(msg_critical) != string::npos);
+ buffer.str(string());
+ }
+ }
+};
+
+class BaseTestSuite: public TestSuite
+{
+public:
+ BaseTestSuite()
+ : TestSuite("BaseTestSuite")
+ {
+ addTest(TestPtr(new DAGTest));
+ addTest(TestPtr(new QueueTest));
+ addTest(TestPtr(new WorkerThreadTest));
+ addTest(TestPtr(new ObjectCounterTest));
+ addTest(TestPtr(new GeomTest));
+ addTest(TestPtr(new TriangleTest));
+ addTest(TestPtr(new FileTest));
+ addTest(TestPtr(new OSTest));
+ addTest(TestPtr(new StringTest));
+ addTest(TestPtr(new SplineTest));
+ addTest(TestPtr(new BezierCurveTest));
+ addTest(TestPtr(new SignalTest));
+ addTest(TestPtr(new BacktraceTest));
+ addTest(TestPtr(new PolygonTest));
+ addTest(TestPtr(new XmlParserTest));
+ addTest(TestPtr(new StandardLoggerTest));
+ }
+};
+
+
+int main(int nargs, char** args)
+{
+ BaseTestSuite suite;
+ suite.runTests();
+ bool bOK = suite.isOk();
+
+ if (bOK) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
diff --git a/src/base/triangulate/AdvancingFront.cpp b/src/base/triangulate/AdvancingFront.cpp
new file mode 100644
index 0000000..d14f1d3
--- /dev/null
+++ b/src/base/triangulate/AdvancingFront.cpp
@@ -0,0 +1,104 @@
+//
+// 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
+//
+
+//
+// Based on Poly2Tri algorithm.
+// Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+// http://code.google.com/p/poly2tri/
+//
+
+#include "AdvancingFront.h"
+
+namespace avg {
+
+AdvancingFront::AdvancingFront(Node& head, Node& tail)
+{
+ m_Head = &head;
+ m_Tail = &tail;
+ m_SearchNode = &head;
+}
+
+Node* AdvancingFront::locateNode(const double& x)
+{
+ Node* node = m_SearchNode;
+
+ if (x < node->m_Value) {
+ while ((node = node->m_Prev) != NULL) {
+ if (x >= node->m_Value) {
+ m_SearchNode = node;
+ return node;
+ }
+ }
+ } else {
+ while ((node = node->m_Next) != NULL) {
+ if (x < node->m_Value) {
+ m_SearchNode = node->m_Prev;
+ return node->m_Prev;
+ }
+ }
+ }
+ return NULL;
+}
+
+Node* AdvancingFront::findSearchNode(const double& x)
+{
+ // TO DO: implement BST index
+ return m_SearchNode;
+}
+
+Node* AdvancingFront::locatePoint(const Point* point)
+{
+ const double px = point->m_X;
+ Node* node = findSearchNode(px);
+ const double nx = node->m_Point->m_X;
+
+ if (px == nx) {
+ if (point != node->m_Point) {
+ // We might have two nodes with same x value for a short time
+ if (point == node->m_Prev->m_Point) {
+ node = node->m_Prev;
+ } else if (point == node->m_Next->m_Point) {
+ node = node->m_Next;
+ } else {
+ assert(0);
+ }
+ }
+ } else if (px < nx) {
+ while ((node = node->m_Prev) != NULL) {
+ if (point == node->m_Point) {
+ break;
+ }
+ }
+ } else {
+ while ((node = node->m_Next) != NULL) {
+ if (point == node->m_Point)
+ break;
+ }
+ }
+ if (node)
+ m_SearchNode = node;
+ return node;
+}
+
+AdvancingFront::~AdvancingFront() {}
+
+}
+
diff --git a/src/base/triangulate/AdvancingFront.h b/src/base/triangulate/AdvancingFront.h
new file mode 100644
index 0000000..3bb0d5b
--- /dev/null
+++ b/src/base/triangulate/AdvancingFront.h
@@ -0,0 +1,118 @@
+//
+// 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
+//
+
+//
+// Based on Poly2Tri algorithm.
+// Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+// http://code.google.com/p/poly2tri/
+//
+
+#ifndef ADVANCED_FRONT_H
+#define ADVANCED_FRONT_H
+
+#include "Shapes.h"
+
+namespace avg {
+
+struct Node;
+
+struct Node
+{
+ Point* m_Point;
+ TriangulationTriangle* m_Triangle;
+
+ Node* m_Next;
+ Node* m_Prev;
+
+ double m_Value;
+
+ Node() : m_Point(NULL), m_Triangle(NULL), m_Next(NULL), m_Prev(NULL), m_Value(0)
+ {}
+
+ Node(Point& p) : m_Point(&p), m_Triangle(NULL), m_Next(NULL), m_Prev(NULL), m_Value(p.m_X)
+ {}
+
+ Node(Point& p, TriangulationTriangle& t) : m_Point(&p), m_Triangle(&t), m_Next(NULL), m_Prev(NULL), m_Value(p.m_X)
+ {}
+
+};
+
+
+class AdvancingFront
+{
+
+public:
+
+AdvancingFront(Node& head, Node& tail);
+
+~AdvancingFront();
+
+Node* head();
+void setHead(Node* node);
+Node* tail();
+void setTail(Node* node);
+Node* search();
+void setSearch(Node* node);
+
+/// Locate insertion point along advancing front
+Node* locateNode(const double& x);
+
+Node* locatePoint(const Point* point);
+
+private:
+
+Node* m_Head, *m_Tail, *m_SearchNode;
+
+Node* findSearchNode(const double& x);
+};
+
+
+inline Node* AdvancingFront::head()
+{
+ return m_Head;
+}
+inline void AdvancingFront::setHead(Node* node)
+{
+ m_Head = node;
+}
+
+inline Node* AdvancingFront::tail()
+{
+ return m_Tail;
+}
+inline void AdvancingFront::setTail(Node* node)
+{
+ m_Tail = node;
+}
+
+inline Node* AdvancingFront::search()
+{
+ return m_SearchNode;
+}
+
+inline void AdvancingFront::setSearch(Node* node)
+{
+ m_SearchNode = node;
+}
+
+}
+
+#endif
diff --git a/src/base/triangulate/Makefile.am b/src/base/triangulate/Makefile.am
new file mode 100644
index 0000000..9381e58
--- /dev/null
+++ b/src/base/triangulate/Makefile.am
@@ -0,0 +1,8 @@
+AM_CPPFLAGS = -I.. @XML2_CFLAGS@ @PTHREAD_CFLAGS@
+ALL_H = Triangulate.h Shapes.h Utils.h \
+ AdvancingFront.h Sweep.h SweepContext.h
+
+noinst_LTLIBRARIES = libtriangulate.la
+libtriangulate_la_SOURCES = Triangulate.cpp Shapes.cpp \
+ AdvancingFront.cpp Sweep.cpp SweepContext.cpp \
+ $(ALL_H)
diff --git a/src/base/triangulate/Shapes.cpp b/src/base/triangulate/Shapes.cpp
new file mode 100644
index 0000000..08e2e13
--- /dev/null
+++ b/src/base/triangulate/Shapes.cpp
@@ -0,0 +1,353 @@
+//
+// 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
+//
+
+//
+// Based on Poly2Tri algorithm.
+// Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+// http://code.google.com/p/poly2tri/
+//
+
+#include "Shapes.h"
+#include <iostream>
+
+namespace avg {
+
+TriangulationTriangle::TriangulationTriangle(Point& a, Point& b, Point& c)
+{
+ m_Points[0] = &a;
+ m_Points[1] = &b;
+ m_Points[2] = &c;
+ m_Neighbors[0] = NULL;
+ m_Neighbors[1] = NULL;
+ m_Neighbors[2] = NULL;
+ m_ConstrainedEdge[0] = m_ConstrainedEdge[1] = m_ConstrainedEdge[2] = false;
+ m_DelaunayEdge[0] = m_DelaunayEdge[1] = m_DelaunayEdge[2] = false;
+ m_Interior = false;
+}
+
+// Update neighbor pointers
+void TriangulationTriangle::markNeighbor(Point* p1, Point* p2,
+ TriangulationTriangle* t)
+{
+ if ((p1 == m_Points[2] && p2 == m_Points[1])
+ || (p1 == m_Points[1] && p2 == m_Points[2])) {
+ m_Neighbors[0] = t;
+ } else if ((p1 == m_Points[0] && p2 == m_Points[2])
+ || (p1 == m_Points[2] && p2 == m_Points[0])) {
+ m_Neighbors[1] = t;
+ } else if ((p1 == m_Points[0] && p2 == m_Points[1])
+ || (p1 == m_Points[1] && p2 == m_Points[0])) {
+ m_Neighbors[2] = t;
+ } else {
+ assert(0);
+ }
+
+}
+
+// Exhaustive search to update neighbor pointers
+void TriangulationTriangle::markNeighbor(TriangulationTriangle& t)
+{
+ if (t.contains(m_Points[1], m_Points[2])) {
+ m_Neighbors[0] = &t;
+ t.markNeighbor(m_Points[1], m_Points[2], this);
+ } else if (t.contains(m_Points[0], m_Points[2])) {
+ m_Neighbors[1] = &t;
+ t.markNeighbor(m_Points[0], m_Points[2], this);
+ } else if (t.contains(m_Points[0], m_Points[1])) {
+ m_Neighbors[2] = &t;
+ t.markNeighbor(m_Points[0], m_Points[1], this);
+ }
+}
+
+void TriangulationTriangle::clear()
+{
+ TriangulationTriangle *t;
+ for (int i = 0; i < 3; i++) {
+ t = m_Neighbors[i];
+ if (t != NULL) {
+ t->clearNeighbor(this);
+ }
+ }
+ clearNeighbors();
+ m_Points[0] = m_Points[1] = m_Points[2] = NULL;
+}
+
+void TriangulationTriangle::clearNeighbor(TriangulationTriangle *triangle)
+{
+ if (m_Neighbors[0] == triangle) {
+ m_Neighbors[0] = NULL;
+ } else if (m_Neighbors[1] == triangle) {
+ m_Neighbors[1] = NULL;
+ } else {
+ m_Neighbors[2] = NULL;
+ }
+}
+
+void TriangulationTriangle::clearNeighbors()
+{
+ m_Neighbors[0] = NULL;
+ m_Neighbors[1] = NULL;
+ m_Neighbors[2] = NULL;
+}
+
+void TriangulationTriangle::clearDelunayEdges()
+{
+ m_DelaunayEdge[0] = m_DelaunayEdge[1] = m_DelaunayEdge[2] = false;
+}
+
+Point* TriangulationTriangle::oppositePoint(TriangulationTriangle& t,
+ Point& p) {
+ Point *cw = t.pointCW(p);
+ return pointCW(*cw);
+}
+
+// Legalized triangle by rotating clockwise around point(0)
+void TriangulationTriangle::legalize(Point& point)
+{
+ m_Points[1] = m_Points[0];
+ m_Points[0] = m_Points[2];
+ m_Points[2] = &point;
+}
+
+// Legalize triagnle by rotating clockwise around oPoint
+void TriangulationTriangle::legalize(Point& opoint, Point& npoint)
+{
+ if (&opoint == m_Points[0]) {
+ m_Points[1] = m_Points[0];
+ m_Points[0] = m_Points[2];
+ m_Points[2] = &npoint;
+ } else if (&opoint == m_Points[1]) {
+ m_Points[2] = m_Points[1];
+ m_Points[1] = m_Points[0];
+ m_Points[0] = &npoint;
+ } else if (&opoint == m_Points[2]) {
+ m_Points[0] = m_Points[2];
+ m_Points[2] = m_Points[1];
+ m_Points[1] = &npoint;
+ } else {
+ assert(0);
+ }
+}
+
+unsigned int TriangulationTriangle::index(const Point* p)
+{
+ if (p == m_Points[0]) {
+ return 0;
+ } else if (p == m_Points[1]) {
+ return 1;
+ } else if (p == m_Points[2]) {
+ return 2;
+ }
+ assert(0);
+ return 0;
+}
+
+unsigned int TriangulationTriangle::edgeIndex(const Point* p1, const Point* p2)
+{
+ if (m_Points[0] == p1) {
+ if (m_Points[1] == p2) {
+ return 2;
+ } else if (m_Points[2] == p2) {
+ return 1;
+ }
+ } else if (m_Points[1] == p1) {
+ if (m_Points[2] == p2) {
+ return 0;
+ } else if (m_Points[0] == p2) {
+ return 2;
+ }
+ } else if (m_Points[2] == p1) {
+ if (m_Points[0] == p2) {
+ return 1;
+ } else if (m_Points[1] == p2) {
+ return 0;
+ }
+ }
+ return -1;
+}
+
+void TriangulationTriangle::markConstrainedEdge(const int index)
+{
+ m_ConstrainedEdge[index] = true;
+}
+
+void TriangulationTriangle::markConstrainedEdge(Edge& edge)
+{
+ markConstrainedEdge(edge.m_P, edge.m_Q);
+}
+
+void TriangulationTriangle::markConstrainedEdge(Point* p, Point* q)
+{
+ if ((q == m_Points[0] && p == m_Points[1])
+ || (q == m_Points[1] && p == m_Points[0])) {
+ m_ConstrainedEdge[2] = true;
+ } else if ((q == m_Points[0] && p == m_Points[2])
+ || (q == m_Points[2] && p == m_Points[0])) {
+ m_ConstrainedEdge[1] = true;
+ } else if ((q == m_Points[1] && p == m_Points[2])
+ || (q == m_Points[2] && p == m_Points[1])) {
+ m_ConstrainedEdge[0] = true;
+ }
+}
+
+// The point counter-clockwise to given point
+Point* TriangulationTriangle::pointCW(Point& point)
+{
+ if (&point == m_Points[0]) {
+ return m_Points[2];
+ } else if (&point == m_Points[1]) {
+ return m_Points[0];
+ } else if (&point == m_Points[2]) {
+ return m_Points[1];
+ }
+ assert(0);
+ return 0; // Silence compiler warning
+}
+
+Point* TriangulationTriangle::pointCCW(Point& point)
+{
+ if (&point == m_Points[0]) {
+ return m_Points[1];
+ } else if (&point == m_Points[1]) {
+ return m_Points[2];
+ } else if (&point == m_Points[2]) {
+ return m_Points[0];
+ }
+ assert(0);
+ return 0; // Silence compiler warning
+}
+
+TriangulationTriangle* TriangulationTriangle::neighborCW(Point& point)
+{
+ if (&point == m_Points[0]) {
+ return m_Neighbors[1];
+ } else if (&point == m_Points[1]) {
+ return m_Neighbors[2];
+ }
+ return m_Neighbors[0];
+}
+
+TriangulationTriangle* TriangulationTriangle::neighborCCW(Point& point)
+{
+ if (&point == m_Points[0]) {
+ return m_Neighbors[2];
+ } else if (&point == m_Points[1]) {
+ return m_Neighbors[0];
+ }
+ return m_Neighbors[1];
+}
+
+bool TriangulationTriangle::getConstrainedEdgeCCW(Point& p)
+{
+ if (&p == m_Points[0]) {
+ return m_ConstrainedEdge[2];
+ } else if (&p == m_Points[1]) {
+ return m_ConstrainedEdge[0];
+ }
+ return m_ConstrainedEdge[1];
+}
+
+bool TriangulationTriangle::getConstrainedEdgeCW(Point& p)
+{
+ if (&p == m_Points[0]) {
+ return m_ConstrainedEdge[1];
+ } else if (&p == m_Points[1]) {
+ return m_ConstrainedEdge[2];
+ }
+ return m_ConstrainedEdge[0];
+}
+
+void TriangulationTriangle::setConstrainedEdgeCCW(Point& p, bool ce)
+{
+ if (&p == m_Points[0]) {
+ m_ConstrainedEdge[2] = ce;
+ } else if (&p == m_Points[1]) {
+ m_ConstrainedEdge[0] = ce;
+ } else {
+ m_ConstrainedEdge[1] = ce;
+ }
+}
+
+void TriangulationTriangle::setConstrainedEdgeCW(Point& p, bool ce)
+{
+ if (&p == m_Points[0]) {
+ m_ConstrainedEdge[1] = ce;
+ } else if (&p == m_Points[1]) {
+ m_ConstrainedEdge[2] = ce;
+ } else {
+ m_ConstrainedEdge[0] = ce;
+ }
+}
+
+bool TriangulationTriangle::getDelunayEdgeCCW(Point& p)
+{
+ if (&p == m_Points[0]) {
+ return m_DelaunayEdge[2];
+ } else if (&p == m_Points[1]) {
+ return m_DelaunayEdge[0];
+ }
+ return m_DelaunayEdge[1];
+}
+
+bool TriangulationTriangle::getDelunayEdgeCW(Point& p)
+{
+ if (&p == m_Points[0]) {
+ return m_DelaunayEdge[1];
+ } else if (&p == m_Points[1]) {
+ return m_DelaunayEdge[2];
+ }
+ return m_DelaunayEdge[0];
+}
+
+void TriangulationTriangle::setDelunayEdgeCCW(Point& p, bool e)
+{
+ if (&p == m_Points[0]) {
+ m_DelaunayEdge[2] = e;
+ } else if (&p == m_Points[1]) {
+ m_DelaunayEdge[0] = e;
+ } else {
+ m_DelaunayEdge[1] = e;
+ }
+}
+
+void TriangulationTriangle::setDelunayEdgeCW(Point& p, bool e)
+{
+ if (&p == m_Points[0]) {
+ m_DelaunayEdge[1] = e;
+ } else if (&p == m_Points[1]) {
+ m_DelaunayEdge[2] = e;
+ } else {
+ m_DelaunayEdge[0] = e;
+ }
+}
+
+TriangulationTriangle& TriangulationTriangle::neighborAcross(Point& opoint)
+{
+ if (&opoint == m_Points[0]) {
+ return *m_Neighbors[0];
+ } else if (&opoint == m_Points[1]) {
+ return *m_Neighbors[1];
+ }
+ return *m_Neighbors[2];
+}
+
+}
+
diff --git a/src/base/triangulate/Shapes.h b/src/base/triangulate/Shapes.h
new file mode 100644
index 0000000..0417d7c
--- /dev/null
+++ b/src/base/triangulate/Shapes.h
@@ -0,0 +1,296 @@
+//
+// 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
+//
+
+//
+// Based on Poly2Tri algorithm.
+// Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+// http://code.google.com/p/poly2tri/
+//
+
+#ifndef SHAPES_H
+#define SHAPES_H
+
+#include <vector>
+#include <cstddef>
+#include <assert.h>
+#include <cmath>
+
+namespace avg {
+
+struct Edge;
+
+struct Point
+{
+ double m_X, m_Y;
+ int m_Index;
+
+ /// The edges this point constitutes an upper ending point
+ std::vector<Edge*> m_EdgeList;
+
+ /// Default constructor does nothing (for performance).
+ Point() {
+ m_X = 0.0;
+ m_Y = 0.0;
+ m_Index = 0;
+ }
+
+ Point(double x, double y, int index) :
+ m_X(x), m_Y(y), m_Index(index) {}
+
+ void set_zero()
+ {
+ m_X = 0.0;
+ m_Y = 0.0;
+ }
+
+ void set(double x_, double y_)
+ {
+ m_X = x_;
+ m_Y = y_;
+ }
+
+ Point operator -() const
+ {
+ Point v;
+ v.set(-m_X, -m_Y);
+ return v;
+ }
+
+ void operator +=(const Point& v)
+ {
+ m_X += v.m_X;
+ m_Y += v.m_Y;
+ }
+
+ void operator -=(const Point& v)
+ {
+ m_X -= v.m_X;
+ m_Y -= v.m_Y;
+ }
+
+ void operator *=(double a)
+ {
+ m_X *= a;
+ m_Y *= a;
+ }
+
+ double length() const
+ {
+ return sqrt(m_X * m_X + m_Y * m_Y);
+ }
+
+ /// Convert this point into a unit point. Returns the Length.
+ double normalize()
+ {
+ double len = length();
+ m_X /= len;
+ m_Y /= len;
+ return len;
+ }
+
+};
+
+
+// Represents a simple polygon's edge
+struct Edge
+{
+ Point* m_P, *m_Q;
+
+ Edge(Point& p1, Point& p2) :m_P(&p1), m_Q(&p2)
+ {
+ if (p1.m_Y > p2.m_Y) {
+ m_Q = &p1;
+ m_P = &p2;
+ } else if (p1.m_Y == p2.m_Y) {
+ if (p1.m_X > p2.m_X) {
+ m_Q = &p1;
+ m_P = &p2;
+ } else if (p1.m_X == p2.m_X) {
+ // Repeat points
+ assert(false);
+ }
+ }
+ m_Q->m_EdgeList.push_back(this);
+ }
+};
+
+
+class TriangulationTriangle
+{
+
+public:
+
+ TriangulationTriangle(Point& a, Point& b, Point& c);
+
+/// Flags to determine if an edge is a Constrained edge
+ bool m_ConstrainedEdge[3];
+/// Flags to determine if an edge is a Delauney edge
+ bool m_DelaunayEdge[3];
+
+ Point* getPoint(const int& index);
+ Point* pointCW(Point& point);
+ Point* pointCCW(Point& point);
+ Point* oppositePoint(TriangulationTriangle& t, Point& p);
+
+ TriangulationTriangle* getNeighbor(const int& index);
+ void markNeighbor(Point* p1, Point* p2, TriangulationTriangle* t);
+ void markNeighbor(TriangulationTriangle& t);
+
+ void markConstrainedEdge(const int index);
+ void markConstrainedEdge(Edge& edge);
+ void markConstrainedEdge(Point* p, Point* q);
+
+ unsigned int index(const Point* p);
+ unsigned int edgeIndex(const Point* p1, const Point* p2);
+
+ TriangulationTriangle* neighborCW(Point& point);
+ TriangulationTriangle* neighborCCW(Point& point);
+ bool getConstrainedEdgeCCW(Point& p);
+ bool getConstrainedEdgeCW(Point& p);
+ void setConstrainedEdgeCCW(Point& p, bool ce);
+ void setConstrainedEdgeCW(Point& p, bool ce);
+ bool getDelunayEdgeCCW(Point& p);
+ bool getDelunayEdgeCW(Point& p);
+ void setDelunayEdgeCCW(Point& p, bool e);
+ void setDelunayEdgeCW(Point& p, bool e);
+
+ bool contains(Point* p);
+ bool contains(const Edge& e);
+ bool contains(Point* p, Point* q);
+ void legalize(Point& point);
+ void legalize(Point& opoint, Point& npoint);
+
+ void clear();
+ void clearNeighbor(TriangulationTriangle *triangle);
+ void clearNeighbors();
+ void clearDelunayEdges();
+
+ inline bool isInterior();
+ inline void isInterior(bool b);
+
+ TriangulationTriangle& neighborAcross(Point& opoint);
+
+private:
+
+ Point* m_Points[3];
+
+ TriangulationTriangle* m_Neighbors[3];
+
+ bool m_Interior;
+};
+
+inline bool cmp(const Point* a, const Point* b)
+{
+ if (a->m_Y < b->m_Y) {
+ return true;
+ } else if (a->m_Y == b->m_Y) {
+ // Make sure q is point with greater x value
+ if (a->m_X < b->m_X) {
+ return true;
+ }
+ }
+ return false;
+}
+/*
+ inline Point operator +(const Point& a, const Point& b)
+ {
+ return Point(a.x + b.x, a.y + b.y);
+ }
+
+ inline Point operator -(const Point& a, const Point& b)
+ {
+ return Point(a.x - b.x, a.y - b.y);
+ }
+
+ inline Point operator *(double s, const Point& a)
+ {
+ return Point(s * a.x, s * a.y, a.index);
+ } */
+
+inline bool operator ==(const Point& a, const Point& b)
+{
+ return a.m_X == b.m_X && a.m_Y == b.m_Y;
+}
+
+inline bool operator !=(const Point& a, const Point& b)
+{
+ return a.m_X != b.m_X && a.m_Y != b.m_Y;
+}
+
+inline double dot(const Point& a, const Point& b)
+{
+ return a.m_X * b.m_X + a.m_Y * b.m_Y;
+}
+
+inline double cross(const Point& a, const Point& b)
+{
+ return a.m_X * b.m_Y - a.m_Y * b.m_X;
+}
+
+inline Point cross(const Point& a, double s)
+{
+ return Point(s * a.m_Y, -s * a.m_X, a.m_Index);
+}
+
+inline Point cross(const double s, const Point& a)
+{
+ return Point(-s * a.m_Y, s * a.m_X, a.m_Index);
+}
+
+inline Point* TriangulationTriangle::getPoint(const int& index)
+{
+ return m_Points[index];
+}
+
+inline TriangulationTriangle* TriangulationTriangle::getNeighbor(
+ const int& index)
+{
+ return m_Neighbors[index];
+}
+
+inline bool TriangulationTriangle::contains(Point* p)
+{
+ return p == m_Points[0] || p == m_Points[1] || p == m_Points[2];
+}
+
+inline bool TriangulationTriangle::contains(const Edge& e)
+{
+ return contains(e.m_P) && contains(e.m_Q);
+}
+
+inline bool TriangulationTriangle::contains(Point* p, Point* q)
+{
+ return contains(p) && contains(q);
+}
+
+inline bool TriangulationTriangle::isInterior()
+{
+ return m_Interior;
+}
+
+inline void TriangulationTriangle::isInterior(bool b)
+{
+ m_Interior = b;
+}
+
+}
+
+#endif
diff --git a/src/base/triangulate/Sweep.cpp b/src/base/triangulate/Sweep.cpp
new file mode 100644
index 0000000..2655cb0
--- /dev/null
+++ b/src/base/triangulate/Sweep.cpp
@@ -0,0 +1,796 @@
+//
+// 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
+//
+
+//
+// Based on Poly2Tri algorithm.
+// Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+// http://code.google.com/p/poly2tri/
+//
+
+#include <stdexcept>
+#include "Sweep.h"
+#include "SweepContext.h"
+#include "AdvancingFront.h"
+#include "Utils.h"
+
+namespace avg {
+
+void Sweep::Triangulate(SweepContext& sc)
+{
+ arrayCount = 0;
+ for (unsigned int i = 0; i < (unsigned)sc.pointCount(); i++) {
+ m_Nodes.push_back(new Node());
+ }
+ sc.initTriangulation();
+ sc.createAdvancingFront();
+ // Sweep points; build mesh
+ sweepPoints(sc);
+ // Clean up
+ finalizationPolygon(sc);
+}
+
+void Sweep::sweepPoints(SweepContext& sc)
+{
+ for (int i = 1; i < sc.pointCount(); i++) {
+ Point& point = *sc.getPoint(i);
+ Node* node = &pointEvent(sc, point);
+ for (unsigned int i = 0; i < point.m_EdgeList.size(); i++) {
+ edgeEvent(sc, point.m_EdgeList[i], node);
+ }
+ }
+}
+
+void Sweep::finalizationPolygon(SweepContext& sc)
+{
+ // Get an Internal triangle to start with
+ TriangulationTriangle* t = sc.front()->head()->m_Next->m_Triangle;
+ Point* p = sc.front()->head()->m_Next->m_Point;
+ while (!t->getConstrainedEdgeCW(*p)) {
+ t = t->neighborCCW(*p);
+ }
+
+ // Collect interior triangles constrained by edges
+ sc.meshClean(*t);
+}
+
+Node& Sweep::pointEvent(SweepContext& sc, Point& point)
+{
+ Node& node = sc.locateNode(point);
+ Node& new_node = newFrontTriangle(sc, point, node);
+
+ // Only need to check +epsilon since point never have smaller
+ // x value than node due to how we fetch nodes from the front
+ if (point.m_X <= node.m_Point->m_X + EPSILON) {
+ fill(sc, node);
+ }
+
+ //tcx.AddNode(new_node);
+
+ fillAdvancingFront(sc, new_node);
+ return new_node;
+}
+
+void Sweep::edgeEvent(SweepContext& sc, Edge* edge, Node* node)
+{
+ sc.m_EdgeEvent.m_ConstrainedEdge = edge;
+ sc.m_EdgeEvent.m_Right = (edge->m_P->m_X > edge->m_Q->m_X);
+
+ if (isEdgeSideOfTriangle(*node->m_Triangle, *edge->m_P, *edge->m_Q)) {
+ return;
+ }
+
+ // to do: integrate with flip process might give some better performance
+ // but for now this avoid the issue with cases that needs both flips and fills
+ fillEdgeEvent(sc, edge, node);
+ edgeEvent(sc, *edge->m_P, *edge->m_Q, node->m_Triangle, *edge->m_Q);
+}
+
+void Sweep::edgeEvent(SweepContext& sc, Point& ep, Point& eq,
+ TriangulationTriangle* triangle, Point& point)
+{
+ if (isEdgeSideOfTriangle(*triangle, ep, eq)) {
+ return;
+ }
+
+ Point* p1 = triangle->pointCCW(point);
+ Orientation o1 = orient2d(eq, *p1, ep);
+ if (o1 == COLLINEAR) {
+ if (triangle->contains(&eq, p1)) {
+ triangle->markConstrainedEdge(&eq, p1);
+ // We are modifying the constraint maybe it would be better to
+ // not change the given constraint and just keep a variable for the new constraint
+ sc.m_EdgeEvent.m_ConstrainedEdge->m_Q = p1;
+ triangle = &triangle->neighborAcross(point);
+ edgeEvent(sc, ep, *p1, triangle, *p1);
+ } else {
+ std::runtime_error("EdgeEvent - collinear points not supported");
+ assert(0);
+ }
+ return;
+ }
+
+ Point* p2 = triangle->pointCW(point);
+ Orientation o2 = orient2d(eq, *p2, ep);
+ if (o2 == COLLINEAR) {
+ if (triangle->contains(&eq, p2)) {
+ triangle->markConstrainedEdge(&eq, p2);
+ // We are modifying the constraint maybe it would be better to
+ // not change the given constraint and just keep a variable for the new constraint
+ sc.m_EdgeEvent.m_ConstrainedEdge->m_Q = p2;
+ triangle = &triangle->neighborAcross(point);
+ edgeEvent(sc, ep, *p2, triangle, *p2);
+ } else {
+ std::runtime_error("EdgeEvent - collinear points not supported");
+ assert(0);
+ }
+ return;
+ }
+
+ if (o1 == o2) {
+ // Need to decide if we are rotating CW or CCW to get to a triangle
+ // that will cross edge
+ if (o1 == CW) {
+ triangle = triangle->neighborCCW(point);
+ } else {
+ triangle = triangle->neighborCW(point);
+ }
+ edgeEvent(sc, ep, eq, triangle, point);
+ } else {
+ // This triangle crosses constraint so lets flippin start!
+ flipEdgeEvent(sc, ep, eq, triangle, point);
+ }
+}
+
+bool Sweep::isEdgeSideOfTriangle(TriangulationTriangle& triangle, Point& ep,
+ Point& eq)
+{
+ int index = triangle.edgeIndex(&ep, &eq);
+
+ if (index != -1) {
+ triangle.markConstrainedEdge(index);
+ TriangulationTriangle* t = triangle.getNeighbor(index);
+ if (t) {
+ t->markConstrainedEdge(&ep, &eq);
+ }
+ return true;
+ }
+ return false;
+}
+
+Node& Sweep::newFrontTriangle(SweepContext& sc, Point& point, Node& node)
+{
+ TriangulationTriangle* triangle = new TriangulationTriangle(point,
+ *node.m_Point, *node.m_Next->m_Point);
+
+ triangle->markNeighbor(*node.m_Triangle);
+ sc.addToMap(triangle);
+
+ Node* newNode = m_Nodes[arrayCount++]; //new Node(point);
+ newNode->m_Point = &point;
+ newNode->m_Value = point.m_X;
+// m_Nodes.push_back(newNode);
+
+ newNode->m_Next = node.m_Next;
+ newNode->m_Prev = &node;
+ node.m_Next->m_Prev = newNode;
+ node.m_Next = newNode;
+
+ if (!legalize(sc, *triangle)) {
+ sc.mapTriangleToNodes(*triangle);
+ }
+
+ return *newNode;
+}
+
+void Sweep::fill(SweepContext& sc, Node& node)
+{
+ TriangulationTriangle* triangle = new TriangulationTriangle(
+ *node.m_Prev->m_Point, *node.m_Point, *node.m_Next->m_Point);
+
+ // TO DO: should copy the constrained_edge value from neighbor triangles
+ // for now constrained_edge values are copied during the legalize
+ triangle->markNeighbor(*node.m_Prev->m_Triangle);
+ triangle->markNeighbor(*node.m_Triangle);
+
+ sc.addToMap(triangle);
+
+ // Update the advancing front
+ node.m_Prev->m_Next = node.m_Next;
+ node.m_Next->m_Prev = node.m_Prev;
+
+ // If it was legalized the triangle has already been mapped
+ if (!legalize(sc, *triangle)) {
+ sc.mapTriangleToNodes(*triangle);
+ }
+
+}
+
+void Sweep::fillAdvancingFront(SweepContext& sc, Node& n)
+{
+ Node* node = n.m_Next;
+
+ while (node->m_Next) {
+ double angle = holeAngle(*node);
+ if (angle > M_PI_2 || angle < -M_PI_2)
+ break;
+// ---------- LEAK FIX --------------
+// Fill(tcx, *node);
+// node = node->m_next;
+
+
+ Node *tmp = node;
+ node = node->m_Next;
+ fill(sc, *tmp);
+// ----------------------------------
+ }
+
+ node = n.m_Prev;
+
+ while (node->m_Prev) {
+ double angle = holeAngle(*node);
+ if (angle > M_PI_2 || angle < -M_PI_2)
+ break;
+ fill(sc, *node);
+ node = node->m_Prev;
+ }
+
+ if (n.m_Next && n.m_Next->m_Next) {
+ double angle = basinAngle(n);
+ if (angle < PI_3div4) {
+ fillBasin(sc, n);
+ }
+ }
+}
+
+double Sweep::basinAngle(Node& node)
+{
+ double ax = node.m_Point->m_X - node.m_Next->m_Next->m_Point->m_X;
+ double ay = node.m_Point->m_Y - node.m_Next->m_Next->m_Point->m_Y;
+ return atan2(ay, ax);
+}
+
+double Sweep::holeAngle(Node& node)
+{
+ /* Complex plane
+ * ab = cosA +i*sinA
+ * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx)
+ * atan2(y,x) computes the principal value of the argument function
+ * applied to the complex number x+iy
+ * Where x = ax*bx + ay*by
+ * y = ax*by - ay*bx
+ */
+ double ax = node.m_Next->m_Point->m_X - node.m_Point->m_X;
+ double ay = node.m_Next->m_Point->m_Y - node.m_Point->m_Y;
+ double bx = node.m_Prev->m_Point->m_X - node.m_Point->m_X;
+ double by = node.m_Prev->m_Point->m_Y - node.m_Point->m_Y;
+ return atan2(ax * by - ay * bx, ax * bx + ay * by);
+}
+
+bool Sweep::legalize(SweepContext& sc, TriangulationTriangle& t)
+{
+ // To legalize a triangle we start by finding if any of the three edges
+ // violate the Delaunay condition
+ for (int i = 0; i < 3; i++) {
+ if (t.m_DelaunayEdge[i])
+ continue;
+
+ TriangulationTriangle* ot = t.getNeighbor(i);
+
+ if (ot) {
+ Point* p = t.getPoint(i);
+ Point* op = ot->oppositePoint(t, *p);
+ int oi = ot->index(op);
+
+ // If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization)
+ // then we should not try to legalize
+ if (ot->m_ConstrainedEdge[oi] || ot->m_DelaunayEdge[oi]) {
+ t.m_ConstrainedEdge[i] = ot->m_ConstrainedEdge[oi];
+ continue;
+ }
+
+ bool inside = incircle(*p, *t.pointCCW(*p), *t.pointCW(*p), *op);
+
+ if (inside) {
+ // Lets mark this shared edge as Delaunay
+ t.m_DelaunayEdge[i] = true;
+ ot->m_DelaunayEdge[oi] = true;
+
+ // Lets rotate shared edge one vertex CW to legalize it
+ rotateTrianglePair(t, *p, *ot, *op);
+
+ // We now got one valid Delaunay Edge shared by two triangles
+ // This gives us 4 new edges to check for Delaunay
+
+ // Make sure that triangle to node mapping is done only one time for a specific triangle
+ bool notLegalized = !legalize(sc, t);
+ if (notLegalized) {
+ sc.mapTriangleToNodes(t);
+ }
+
+ notLegalized = !legalize(sc, *ot);
+ if (notLegalized)
+ sc.mapTriangleToNodes(*ot);
+
+ // Reset the Delaunay edges, since they only are valid Delaunay edges
+ // until we add a new triangle or point.
+ // XX X: need to think about this. Can these edges be tried after we
+ // return to previous recursive level?
+ t.m_DelaunayEdge[i] = false;
+ ot->m_DelaunayEdge[oi] = false;
+
+ // If triangle have been legalized no need to check the other edges since
+ // the recursive legalization will handles those so we can end here.
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool Sweep::incircle(Point& pa, Point& pb, Point& pc, Point& pd)
+{
+ double adx = pa.m_X - pd.m_X;
+ double ady = pa.m_Y - pd.m_Y;
+ double bdx = pb.m_X - pd.m_X;
+ double bdy = pb.m_Y - pd.m_Y;
+
+ double adxbdy = adx * bdy;
+ double bdxady = bdx * ady;
+ double oabd = adxbdy - bdxady;
+
+ if (oabd <= 0) {
+ return false;
+ }
+
+ double cdx = pc.m_X - pd.m_X;
+ double cdy = pc.m_Y - pd.m_Y;
+
+ double cdxady = cdx * ady;
+ double adxcdy = adx * cdy;
+ double ocad = cdxady - adxcdy;
+
+ if (ocad <= 0) {
+ return false;
+ }
+
+ double bdxcdy = bdx * cdy;
+ double cdxbdy = cdx * bdy;
+
+ double alift = adx * adx + ady * ady;
+ double blift = bdx * bdx + bdy * bdy;
+ double clift = cdx * cdx + cdy * cdy;
+
+ double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd;
+
+ return det > 0;
+}
+
+void Sweep::rotateTrianglePair(TriangulationTriangle& t, Point& p,
+ TriangulationTriangle& ot, Point& op)
+{
+ TriangulationTriangle* n1, *n2, *n3, *n4;
+ n1 = t.neighborCCW(p);
+ n2 = t.neighborCW(p);
+ n3 = ot.neighborCCW(op);
+ n4 = ot.neighborCW(op);
+
+ bool ce1, ce2, ce3, ce4;
+ ce1 = t.getConstrainedEdgeCCW(p);
+ ce2 = t.getConstrainedEdgeCW(p);
+ ce3 = ot.getConstrainedEdgeCCW(op);
+ ce4 = ot.getConstrainedEdgeCW(op);
+
+ bool de1, de2, de3, de4;
+ de1 = t.getDelunayEdgeCCW(p);
+ de2 = t.getDelunayEdgeCW(p);
+ de3 = ot.getDelunayEdgeCCW(op);
+ de4 = ot.getDelunayEdgeCW(op);
+
+ t.legalize(p, op);
+ ot.legalize(op, p);
+
+ // Remap delaunay_edge
+ ot.setDelunayEdgeCCW(p, de1);
+ t.setDelunayEdgeCW(p, de2);
+ t.setDelunayEdgeCCW(op, de3);
+ ot.setDelunayEdgeCW(op, de4);
+
+ // Remap constrained_edge
+ ot.setConstrainedEdgeCCW(p, ce1);
+ t.setConstrainedEdgeCW(p, ce2);
+ t.setConstrainedEdgeCCW(op, ce3);
+ ot.setConstrainedEdgeCW(op, ce4);
+
+ // Remap neighbors
+ // XX X: might optimize the markNeighbor by keeping track of
+ // what side should be assigned to what neighbor after the
+ // rotation. Now mark neighbor does lots of testing to find
+ // the right side.
+ t.clearNeighbors();
+ ot.clearNeighbors();
+ if (n1) {
+ ot.markNeighbor(*n1);
+ }
+ if (n2) {
+ t.markNeighbor(*n2);
+ }
+ if (n3) {
+ t.markNeighbor(*n3);
+ }
+ if (n4) {
+ ot.markNeighbor(*n4);
+ }
+ t.markNeighbor(ot);
+}
+
+void Sweep::fillBasin(SweepContext& sc, Node& node)
+{
+ if (orient2d(*node.m_Point, *node.m_Next->m_Point, *node.m_Next->m_Next->m_Point)
+ == CCW) {
+ sc.m_Basin.m_LeftNode = node.m_Next->m_Next;
+ } else {
+ sc.m_Basin.m_LeftNode = node.m_Next;
+ }
+
+ // Find the bottom and right node
+ sc.m_Basin.m_BottomNode = sc.m_Basin.m_LeftNode;
+ while (sc.m_Basin.m_BottomNode->m_Next
+ && sc.m_Basin.m_BottomNode->m_Point->m_Y
+ >= sc.m_Basin.m_BottomNode->m_Next->m_Point->m_Y) {
+ sc.m_Basin.m_BottomNode = sc.m_Basin.m_BottomNode->m_Next;
+ }
+ if (sc.m_Basin.m_BottomNode == sc.m_Basin.m_LeftNode) {
+ // No valid basin
+ return;
+ }
+
+ sc.m_Basin.m_RightNode = sc.m_Basin.m_BottomNode;
+ while (sc.m_Basin.m_RightNode->m_Next
+ && sc.m_Basin.m_RightNode->m_Point->m_Y
+ < sc.m_Basin.m_RightNode->m_Next->m_Point->m_Y) {
+ sc.m_Basin.m_RightNode = sc.m_Basin.m_RightNode->m_Next;
+ }
+ if (sc.m_Basin.m_RightNode == sc.m_Basin.m_BottomNode) {
+ // No valid basins
+ return;
+ }
+
+ sc.m_Basin.m_Width = sc.m_Basin.m_RightNode->m_Point->m_X
+ - sc.m_Basin.m_LeftNode->m_Point->m_X;
+ sc.m_Basin.m_LeftHighest = sc.m_Basin.m_LeftNode->m_Point->m_Y
+ > sc.m_Basin.m_RightNode->m_Point->m_Y;
+
+ fillBasinReq(sc, sc.m_Basin.m_BottomNode);
+}
+
+void Sweep::fillBasinReq(SweepContext& sc, Node* node)
+{
+ // if shallow stop filling
+ if (isShallow(sc, *node)) {
+ return;
+ }
+
+ fill(sc, *node);
+
+ if (node->m_Prev == sc.m_Basin.m_LeftNode
+ && node->m_Next == sc.m_Basin.m_RightNode) {
+ return;
+ } else if (node->m_Prev == sc.m_Basin.m_LeftNode) {
+ Orientation o = orient2d(*node->m_Point, *node->m_Next->m_Point,
+ *node->m_Next->m_Next->m_Point);
+ if (o == CW) {
+ return;
+ }
+ node = node->m_Next;
+ } else if (node->m_Next == sc.m_Basin.m_RightNode) {
+ Orientation o = orient2d(*node->m_Point, *node->m_Prev->m_Point,
+ *node->m_Prev->m_Prev->m_Point);
+ if (o == CCW) {
+ return;
+ }
+ node = node->m_Prev;
+ } else {
+ // Continue with the neighbor node with lowest Y value
+ if (node->m_Prev->m_Point->m_Y < node->m_Next->m_Point->m_Y) {
+ node = node->m_Prev;
+ } else {
+ node = node->m_Next;
+ }
+ }
+
+ fillBasinReq(sc, node);
+}
+
+bool Sweep::isShallow(SweepContext& sc, Node& node)
+{
+ double height;
+
+ if (sc.m_Basin.m_LeftHighest) {
+ height = sc.m_Basin.m_LeftNode->m_Point->m_Y - node.m_Point->m_Y;
+ } else {
+ height = sc.m_Basin.m_RightNode->m_Point->m_Y - node.m_Point->m_Y;
+ }
+
+ // if shallow stop filling
+ if (sc.m_Basin.m_Width > height) {
+ return true;
+ }
+ return false;
+}
+
+void Sweep::fillEdgeEvent(SweepContext& sc, Edge* edge, Node* node)
+{
+ if (sc.m_EdgeEvent.m_Right) {
+ fillRightAboveEdgeEvent(sc, edge, node);
+ } else {
+ fillLeftAboveEdgeEvent(sc, edge, node);
+ }
+}
+
+void Sweep::fillRightAboveEdgeEvent(SweepContext& sc, Edge* edge, Node* node)
+{
+ while (node->m_Next->m_Point->m_X < edge->m_P->m_X) {
+ // Check if next node is below the edge
+ if (orient2d(*edge->m_Q, *node->m_Next->m_Point, *edge->m_P) == CCW) {
+ fillRightBelowEdgeEvent(sc, edge, *node);
+ } else {
+ node = node->m_Next;
+ }
+ }
+}
+
+void Sweep::fillRightBelowEdgeEvent(SweepContext& sc, Edge* edge, Node& node)
+{
+ if (node.m_Point->m_X < edge->m_P->m_X) {
+ if (orient2d(*node.m_Point, *node.m_Next->m_Point, *node.m_Next->m_Next->m_Point)
+ == CCW) {
+ // Concave
+ fillRightConcaveEdgeEvent(sc, edge, node);
+ } else {
+ // Convex
+ fillRightConvexEdgeEvent(sc, edge, node);
+ // Retry this one
+ fillRightBelowEdgeEvent(sc, edge, node);
+ }
+ }
+}
+
+void Sweep::fillRightConcaveEdgeEvent(SweepContext& sc, Edge* edge, Node& node)
+{
+ fill(sc, *node.m_Next);
+ if (node.m_Next->m_Point != edge->m_P) {
+ // Next above or below edge?
+ if (orient2d(*edge->m_Q, *node.m_Next->m_Point, *edge->m_P) == CCW) {
+ // Below
+ if (orient2d(*node.m_Point, *node.m_Next->m_Point,
+ *node.m_Next->m_Next->m_Point) == CCW) {
+ // Next is concave
+ fillRightConcaveEdgeEvent(sc, edge, node);
+ } else {
+ // Next is convex
+ }
+ }
+ }
+
+}
+
+void Sweep::fillRightConvexEdgeEvent(SweepContext& sc, Edge* edge, Node& node)
+{
+ // Next concave or convex?
+ if (orient2d(*node.m_Next->m_Point, *node.m_Next->m_Next->m_Point,
+ *node.m_Next->m_Next->m_Next->m_Point) == CCW) {
+ // Concave
+ fillRightConcaveEdgeEvent(sc, edge, *node.m_Next);
+ } else {
+ // Convex
+ // Next above or below edge?
+ if (orient2d(*edge->m_Q, *node.m_Next->m_Next->m_Point, *edge->m_P) == CCW) {
+ // Below
+ fillRightConvexEdgeEvent(sc, edge, *node.m_Next);
+ } else {
+ // Above
+ }
+ }
+}
+
+void Sweep::fillLeftAboveEdgeEvent(SweepContext& sc, Edge* edge, Node* node)
+{
+ while (node->m_Prev->m_Point->m_X > edge->m_P->m_X) {
+ // Check if next node is below the edge
+ if (orient2d(*edge->m_Q, *node->m_Prev->m_Point, *edge->m_P) == CW) {
+ fillLeftBelowEdgeEvent(sc, edge, *node);
+ } else {
+ node = node->m_Prev;
+ }
+ }
+}
+
+void Sweep::fillLeftBelowEdgeEvent(SweepContext& sc, Edge* edge, Node& node)
+{
+ if (node.m_Point->m_X > edge->m_P->m_X) {
+ if (orient2d(*node.m_Point, *node.m_Prev->m_Point, *node.m_Prev->m_Prev->m_Point)
+ == CW) {
+ // Concave
+ fillLeftConcaveEdgeEvent(sc, edge, node);
+ } else {
+ // Convex
+ fillLeftConvexEdgeEvent(sc, edge, node);
+ // Retry this one
+ fillLeftBelowEdgeEvent(sc, edge, node);
+ }
+ }
+}
+
+void Sweep::fillLeftConvexEdgeEvent(SweepContext& sc, Edge* edge, Node& node)
+{
+ // Next concave or convex?
+ if (orient2d(*node.m_Prev->m_Point, *node.m_Prev->m_Prev->m_Point,
+ *node.m_Prev->m_Prev->m_Prev->m_Point) == CW) {
+ // Concave
+ fillLeftConcaveEdgeEvent(sc, edge, *node.m_Prev);
+ } else {
+ // Convex
+ // Next above or below edge?
+ if (orient2d(*edge->m_Q, *node.m_Prev->m_Prev->m_Point, *edge->m_P) == CW) {
+ // Below
+ fillLeftConvexEdgeEvent(sc, edge, *node.m_Prev);
+ } else {
+ // Above
+ }
+ }
+}
+
+void Sweep::fillLeftConcaveEdgeEvent(SweepContext& sc, Edge* edge, Node& node)
+{
+ fill(sc, *node.m_Prev);
+ if (node.m_Prev->m_Point != edge->m_P) {
+ // Next above or below edge?
+ if (orient2d(*edge->m_Q, *node.m_Prev->m_Point, *edge->m_P) == CW) {
+ // Below
+ if (orient2d(*node.m_Point, *node.m_Prev->m_Point,
+ *node.m_Prev->m_Prev->m_Point) == CW) {
+ // Next is concave
+ fillLeftConcaveEdgeEvent(sc, edge, node);
+ } else {
+ // Next is convex
+ }
+ }
+ }
+
+}
+
+void Sweep::flipEdgeEvent(SweepContext& sc, Point& ep, Point& eq,
+ TriangulationTriangle* t, Point& p)
+{
+ TriangulationTriangle& ot = t->neighborAcross(p);
+ Point& op = *ot.oppositePoint(*t, p);
+
+ if (&ot == NULL) {
+ // If we want to integrate the fillEdgeEvent do it here
+ // With current implementation we should never get here
+ //throw new RuntimeException( "[BUG:FIXM E] FLIP failed due to missing triangle");
+ assert(0);
+ }
+
+ if (inScanArea(p, *t->pointCCW(p), *t->pointCW(p), op)) {
+ // Lets rotate shared edge one vertex CW
+ rotateTrianglePair(*t, p, ot, op);
+ sc.mapTriangleToNodes(*t);
+ sc.mapTriangleToNodes(ot);
+
+ if (p == eq && op == ep) {
+ if (eq == *sc.m_EdgeEvent.m_ConstrainedEdge->m_Q
+ && ep == *sc.m_EdgeEvent.m_ConstrainedEdge->m_P) {
+ t->markConstrainedEdge(&ep, &eq);
+ ot.markConstrainedEdge(&ep, &eq);
+ legalize(sc, *t);
+ legalize(sc, ot);
+ } else {
+ // One of the triangles should be legalized here?
+ }
+ } else {
+ Orientation o = orient2d(eq, op, ep);
+ t = &nextFlipTriangle(sc, (int) o, *t, ot, p, op);
+ flipEdgeEvent(sc, ep, eq, t, p);
+ }
+ } else {
+ Point& newP = nextFlipPoint(ep, eq, ot, op);
+ flipScanEdgeEvent(sc, ep, eq, *t, ot, newP);
+ edgeEvent(sc, ep, eq, t, p);
+ }
+}
+
+TriangulationTriangle& Sweep::nextFlipTriangle(SweepContext& sc, int o,
+ TriangulationTriangle& t, TriangulationTriangle& ot, Point& p, Point& op)
+{
+ if (o == CCW) {
+ // ot is not crossing edge after flip
+ int edgeIndex = ot.edgeIndex(&p, &op);
+ ot.m_DelaunayEdge[edgeIndex] = true;
+ legalize(sc, ot);
+ ot.clearDelunayEdges();
+ return t;
+ }
+
+ // t is not crossing edge after flip
+ int edgeIndex = t.edgeIndex(&p, &op);
+
+ t.m_DelaunayEdge[edgeIndex] = true;
+ legalize(sc, t);
+ t.clearDelunayEdges();
+ return ot;
+}
+
+Point& Sweep::nextFlipPoint(Point& ep, Point& eq, TriangulationTriangle& ot, Point& op)
+{
+ Orientation o2d = orient2d(eq, op, ep);
+ if (o2d == CW) {
+ // Right
+ return *ot.pointCCW(op);
+ } else if (o2d == CCW) {
+ // Left
+ return *ot.pointCW(op);
+ } else {
+ //throw new RuntimeException("[Unsupported] Opposing point on constrained edge");
+ assert(0);
+ return ep; // Silence compiler warning.
+ }
+}
+
+void Sweep::flipScanEdgeEvent(SweepContext& sc, Point& ep, Point& eq,
+ TriangulationTriangle& flipTriangle, TriangulationTriangle& t, Point& p)
+{
+ TriangulationTriangle& ot = t.neighborAcross(p);
+ Point& op = *ot.oppositePoint(t, p);
+
+ if (&t.neighborAcross(p) == NULL) {
+ // If we want to integrate the fillEdgeEvent do it here
+ // With current implementation we should never get here
+ //throw new RuntimeException( "[BUG:FIXM E] FLIP failed due to missing triangle");
+ assert(0);
+ }
+
+ if (inScanArea(eq, *flipTriangle.pointCCW(eq), *flipTriangle.pointCW(eq),
+ op)) {
+ // flip with new edge op->eq
+ flipEdgeEvent(sc, eq, op, &ot, op);
+ // To do: Actually I just figured out that it should be possible to
+ // improve this by getting the next ot and op before the the above
+ // flip and continue the flipScanEdgeEvent here
+ // set new ot and op here and loop back to inScanArea test
+ // also need to set a new flip_triangle first
+ // Turns out at first glance that this is somewhat complicated
+ // so it will have to wait.
+ } else {
+ Point& newP = nextFlipPoint(ep, eq, ot, op);
+ flipScanEdgeEvent(sc, ep, eq, flipTriangle, ot, newP);
+ }
+}
+
+Sweep::~Sweep()
+{
+ for (unsigned int i = 0; i < m_Nodes.size(); i++) {
+ delete m_Nodes[i];
+ }
+
+}
+
+}
diff --git a/src/base/triangulate/Sweep.h b/src/base/triangulate/Sweep.h
new file mode 100644
index 0000000..48cd13a
--- /dev/null
+++ b/src/base/triangulate/Sweep.h
@@ -0,0 +1,201 @@
+//
+// 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
+//
+
+//
+// Based on Poly2Tri algorithm.
+// Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+// http://code.google.com/p/poly2tri/
+//
+
+#ifndef SWEEP_H
+#define SWEEP_H
+
+#include <vector>
+
+namespace avg {
+
+class SweepContext;
+struct Node;
+struct Point;
+struct Edge;
+class TriangulationTriangle;
+
+class Sweep
+{
+
+public:
+
+ void Triangulate(SweepContext& sc);
+
+ ~Sweep();
+
+private:
+
+ void sweepPoints(SweepContext& sc);
+
+ Node& pointEvent(SweepContext& sc, Point& point);
+
+ void edgeEvent(SweepContext& sc, Edge* edge, Node* node);
+
+ void edgeEvent(SweepContext& sc, Point& ep, Point& eq,
+ TriangulationTriangle* triangle, Point& point);
+
+ Node& newFrontTriangle(SweepContext& sc, Point& point, Node& node);
+
+ void fill(SweepContext& sc, Node& node);
+
+ bool legalize(SweepContext& sc, TriangulationTriangle& t);
+
+ /**
+ * <b>Requirement</b>:<br>
+ * 1. a,b and c form a triangle.<br>
+ * 2. a and d is know to be on opposite side of bc<br>
+ * <pre>
+ * a
+ * +
+ * / \
+ * / \
+ * b/ \c
+ * +-------+
+ * / d \
+ * / \
+ * </pre>
+ * <b>Fact</b>: d has to be in area B to have a chance to be inside the circle formed by
+ * a,b and c<br>
+ * d is outside B if orient2d(a,b,d) or orient2d(c,a,d) is CW<br>
+ * This preknowledge gives us a way to optimize the incircle test
+ * @param a - triangle point, opposite d
+ * @param b - triangle point
+ * @param c - triangle point
+ * @param d - point opposite a
+ * @return true if d is inside circle, false if on circle edge
+ */
+ bool incircle(Point& pa, Point& pb, Point& pc, Point& pd);
+
+ /**
+ * Rotates a triangle pair one vertex CW
+ *<pre>
+ * n2 n2
+ * P +-----+ P +-----+
+ * | t /| |\ t |
+ * | / | | \ |
+ * n1| / |n3 n1| \ |n3
+ * | / | after CW | \ |
+ * |/ oT | | oT \|
+ * +-----+ oP +-----+
+ * n4 n4
+ * </pre>
+ */
+ void rotateTrianglePair(TriangulationTriangle& t, Point& p, TriangulationTriangle& ot,
+ Point& op);
+
+ void fillAdvancingFront(SweepContext& sc, Node& n);
+
+ double holeAngle(Node& node);
+
+ /**
+ * The basin angle is decided against the horizontal line [1,0]
+ */
+ double basinAngle(Node& node);
+
+ void fillBasin(SweepContext& sc, Node& node);
+
+ void fillBasinReq(SweepContext& sc, Node* node);
+
+ bool isShallow(SweepContext& sc, Node& node);
+
+ bool isEdgeSideOfTriangle(TriangulationTriangle& triangle, Point& ep, Point& eq);
+
+ void fillEdgeEvent(SweepContext& sc, Edge* edge, Node* node);
+
+ void fillRightAboveEdgeEvent(SweepContext& sc, Edge* edge, Node* node);
+
+ void fillRightBelowEdgeEvent(SweepContext& sc, Edge* edge, Node& node);
+
+ void fillRightConcaveEdgeEvent(SweepContext& sc, Edge* edge, Node& node);
+
+ void fillRightConvexEdgeEvent(SweepContext& sc, Edge* edge, Node& node);
+
+ void fillLeftAboveEdgeEvent(SweepContext& sc, Edge* edge, Node* node);
+
+ void fillLeftBelowEdgeEvent(SweepContext& sc, Edge* edge, Node& node);
+
+ void fillLeftConcaveEdgeEvent(SweepContext& sc, Edge* edge, Node& node);
+
+ void fillLeftConvexEdgeEvent(SweepContext& sc, Edge* edge, Node& node);
+
+ void flipEdgeEvent(SweepContext& sc, Point& ep, Point& eq, TriangulationTriangle* t,
+ Point& p);
+
+ /**
+ * After a flip we have two triangles and know that only one will still be
+ * intersecting the edge. So decide which to contiune with and legalize the other
+ *
+ * @param sc
+ * @param o - should be the result of an orient2d( eq, op, ep )
+ * @param t - triangle 1
+ * @param ot - triangle 2
+ * @param p - a point shared by both triangles
+ * @param op - another point shared by both triangles
+ * @return returns the triangle still intersecting the edge
+ */
+ TriangulationTriangle& nextFlipTriangle(SweepContext& sc, int o,
+ TriangulationTriangle& t, TriangulationTriangle& ot, Point& p, Point& op);
+
+ /**
+ * When we need to traverse from one triangle to the next we need
+ * the point in current triangle that is the opposite point to the next
+ * triangle.
+ *
+ * @param ep
+ * @param eq
+ * @param ot
+ * @param op
+ * @return
+ */
+ Point& nextFlipPoint(Point& ep, Point& eq, TriangulationTriangle& ot, Point& op);
+
+ /**
+ * Scan part of the FlipScan algorithm<br>
+ * When a triangle pair isn't flippable we will scan for the next
+ * point that is inside the flip triangle scan area. When found
+ * we generate a new flipEdgeEvent
+ *
+ * @param sc
+ * @param ep - last point on the edge we are traversing
+ * @param eq - first point on the edge we are traversing
+ * @param flipTriangle - the current triangle sharing the point eq with edge
+ * @param t
+ * @param p
+ */
+ void flipScanEdgeEvent(SweepContext& sc, Point& ep, Point& eq,
+ TriangulationTriangle& flip_triangle, TriangulationTriangle& t, Point& p);
+
+ void finalizationPolygon(SweepContext& sc);
+
+ std::vector<Node*> m_Nodes;
+ unsigned int arrayCount;
+
+};
+
+}
+
+#endif
diff --git a/src/base/triangulate/SweepContext.cpp b/src/base/triangulate/SweepContext.cpp
new file mode 100644
index 0000000..16e642e
--- /dev/null
+++ b/src/base/triangulate/SweepContext.cpp
@@ -0,0 +1,196 @@
+//
+// 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
+//
+
+//
+// Based on Poly2Tri algorithm.
+// Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+// http://code.google.com/p/poly2tri/
+//
+
+#include "SweepContext.h"
+#include <algorithm>
+#include "AdvancingFront.h"
+
+namespace avg {
+
+SweepContext::SweepContext(std::vector<Point*> polyline)
+{
+ m_Basin = Basin();
+ m_EdgeEvent = EdgeEvent();
+
+ m_Points = polyline;
+
+ initEdges(m_Points);
+}
+
+void SweepContext::addHole(std::vector<Point*> polyline)
+{
+ initEdges(polyline);
+ for (unsigned int i = 0; i < polyline.size(); i++) {
+ m_Points.push_back(polyline[i]);
+ }
+}
+
+void SweepContext::addPoint(Point* point)
+{
+ m_Points.push_back(point);
+}
+
+std::vector<TriangulationTriangle*>& SweepContext::getTriangles()
+{
+ return m_Triangles;
+}
+
+void SweepContext::initTriangulation()
+{
+ double xmax(m_Points[0]->m_X), xmin(m_Points[0]->m_X);
+ double ymax(m_Points[0]->m_Y), ymin(m_Points[0]->m_Y);
+
+ // Calculate bounds.
+ for (unsigned int i = 0; i < m_Points.size(); i++) {
+ Point& p = *m_Points[i];
+ if (p.m_X > xmax) {
+ xmax = p.m_X;
+ }
+ if (p.m_X < xmin) {
+ xmin = p.m_X;
+ }
+ if (p.m_Y > ymax) {
+ ymax = p.m_Y;
+ }
+ if (p.m_Y < ymin) {
+ ymin = p.m_Y;
+ }
+ }
+
+ double dx = kAlpha * (xmax - xmin);
+ double dy = kAlpha * (ymax - ymin);
+ m_Head = new Point(xmax + dx, ymin - dy, 0);
+ m_Tail = new Point(xmin - dx, ymin - dy, 0);
+
+ // Sort along y-axis
+ std::sort(m_Points.begin(), m_Points.end(), cmp);
+
+}
+
+void SweepContext::initEdges(std::vector<Point*> polyline)
+{
+ int numPoints = polyline.size();
+ for (int i = 0; i < numPoints; i++) {
+ int j = i < numPoints - 1 ? i + 1 : 0;
+
+ m_EdgeList.push_back(new Edge(*polyline[i], *polyline[j]));
+ }
+}
+
+Point* SweepContext::getPoint(const int& index)
+{
+ return m_Points[index];
+}
+
+void SweepContext::addToMap(TriangulationTriangle* triangle)
+{
+ m_Map.push_back(triangle);
+}
+
+Node& SweepContext::locateNode(Point& point)
+{
+ // TO DO implement search tree
+ return *m_Front->locateNode(point.m_X);
+}
+
+void SweepContext::createAdvancingFront()
+{
+ // Initial triangle
+ TriangulationTriangle* triangle = new TriangulationTriangle(*m_Points[0], *m_Tail,
+ *m_Head);
+
+ m_Map.push_back(triangle);
+
+ m_AfHead = new Node(*triangle->getPoint(1), *triangle);
+ m_AfMiddle = new Node(*triangle->getPoint(0), *triangle);
+ m_AfTail = new Node(*triangle->getPoint(2));
+ m_Front = new AdvancingFront(*m_AfHead, *m_AfTail);
+
+ m_AfHead->m_Next = m_AfMiddle;
+ m_AfMiddle->m_Next = m_AfTail;
+ m_AfMiddle->m_Prev = m_AfHead;
+ m_AfTail->m_Prev = m_AfMiddle;
+}
+
+void SweepContext::removeNode(Node* node)
+{
+ delete node;
+}
+
+void SweepContext::mapTriangleToNodes(TriangulationTriangle& t)
+{
+ for (int i = 0; i < 3; i++) {
+ if (!t.getNeighbor(i)) {
+ Node* n = m_Front->locatePoint(t.pointCW(*t.getPoint(i)));
+ if (n) {
+ n->m_Triangle = &t;
+ }
+ }
+ }
+}
+
+void SweepContext::removeFromMap(TriangulationTriangle* triangle)
+{
+ m_Map.remove(triangle);
+}
+
+void SweepContext::meshClean(TriangulationTriangle& triangle)
+{
+ if (&triangle != NULL && !triangle.isInterior()) {
+ triangle.isInterior(true);
+ m_Triangles.push_back(&triangle);
+ for (int i = 0; i < 3; i++) {
+ if (!triangle.m_ConstrainedEdge[i])
+ meshClean(*triangle.getNeighbor(i));
+ }
+ }
+}
+
+SweepContext::~SweepContext()
+{
+
+ delete m_Head;
+ delete m_Tail;
+ delete m_Front;
+ delete m_AfHead;
+ delete m_AfMiddle;
+ delete m_AfTail;
+
+ typedef std::list<TriangulationTriangle*> type_list;
+
+ for (type_list::iterator iter = m_Map.begin(); iter != m_Map.end(); ++iter) {
+ TriangulationTriangle* ptr = *iter;
+ delete ptr;
+ }
+
+ for (unsigned int i = 0; i < m_EdgeList.size(); i++) {
+ delete m_EdgeList[i];
+ }
+
+}
+
+}
diff --git a/src/base/triangulate/SweepContext.h b/src/base/triangulate/SweepContext.h
new file mode 100644
index 0000000..0b9e51d
--- /dev/null
+++ b/src/base/triangulate/SweepContext.h
@@ -0,0 +1,181 @@
+//
+// 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
+//
+
+//
+// Based on Poly2Tri algorithm.
+// Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+// http://code.google.com/p/poly2tri/
+//
+
+#ifndef SWEEP_CONTEXT_H
+#define SWEEP_CONTEXT_H
+
+#include <list>
+#include <vector>
+#include <cstddef>
+
+namespace avg {
+
+// Inital triangle factor, seed triangle will extend 30% of
+// PointSet width to both left and right.
+const double kAlpha = 0.3;
+
+struct Point;
+class TriangulationTriangle;
+struct Node;
+struct Edge;
+class AdvancingFront;
+
+class SweepContext
+{
+
+public:
+
+ SweepContext(std::vector<Point*> polyline);
+
+ ~SweepContext();
+
+ void setHead(Point* p1);
+
+ Point* head();
+
+ void setTail(Point* p1);
+
+ Point* tail();
+
+ int pointCount();
+
+ Node& locateNode(Point& point);
+
+ void removeNode(Node* node);
+
+ void createAdvancingFront();
+
+/// Try to map a node to all sides of this triangle that don't have a neighbor
+ void mapTriangleToNodes(TriangulationTriangle& t);
+
+ void addToMap(TriangulationTriangle* triangle);
+
+ Point* getPoint(const int& index);
+
+ Point* GetPoints();
+
+ void removeFromMap(TriangulationTriangle* triangle);
+
+ void addHole(std::vector<Point*> polyline);
+
+ void addPoint(Point* point);
+
+ AdvancingFront* front();
+
+ void meshClean(TriangulationTriangle& triangle);
+
+ std::vector<TriangulationTriangle*>& getTriangles();
+
+ std::vector<Edge*> m_EdgeList;
+
+ struct Basin
+ {
+ Node* m_LeftNode;
+ Node* m_BottomNode;
+ Node* m_RightNode;
+ double m_Width;
+ bool m_LeftHighest;
+
+ Basin()
+ {
+ clear();
+ }
+
+ void clear() {
+ m_LeftNode = NULL;
+ m_BottomNode = NULL;
+ m_RightNode = NULL;
+ m_Width = 0.0;
+ m_LeftHighest = false;
+ }
+ };
+
+ struct EdgeEvent
+ {
+ Edge* m_ConstrainedEdge;
+ bool m_Right;
+
+ EdgeEvent() :
+ m_ConstrainedEdge(NULL), m_Right(false) {
+ }
+ };
+
+ Basin m_Basin;
+ EdgeEvent m_EdgeEvent;
+
+private:
+
+ friend class Sweep;
+
+ std::vector<TriangulationTriangle*> m_Triangles;
+ std::list<TriangulationTriangle*> m_Map;
+ std::vector<Point*> m_Points;
+
+ AdvancingFront* m_Front;
+ Point* m_Head;
+ Point* m_Tail;
+
+ Node *m_AfHead, *m_AfMiddle, *m_AfTail;
+
+ void initTriangulation();
+ void initEdges(std::vector<Point*> polyline);
+
+};
+
+inline AdvancingFront* SweepContext::front()
+{
+ return m_Front;
+}
+
+inline int SweepContext::pointCount()
+{
+ return m_Points.size();
+}
+
+inline void SweepContext::setHead(Point* p1)
+{
+ m_Head = p1;
+}
+
+inline Point* SweepContext::head()
+{
+ return m_Head;
+}
+
+inline void SweepContext::setTail(Point* p1)
+{
+ m_Tail = p1;
+}
+
+inline Point* SweepContext::tail()
+{
+ return m_Tail;
+}
+
+}
+
+#endif
diff --git a/src/base/triangulate/Triangulate.cpp b/src/base/triangulate/Triangulate.cpp
new file mode 100644
index 0000000..9206327
--- /dev/null
+++ b/src/base/triangulate/Triangulate.cpp
@@ -0,0 +1,90 @@
+//
+// 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
+//
+
+//
+// Based on Poly2Tri algorithm.
+// Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+// http://code.google.com/p/poly2tri/
+//
+
+#include "Triangulate.h"
+#include "Sweep.h"
+#include "SweepContext.h"
+
+#include "Shapes.h"
+
+using namespace std;
+
+namespace avg {
+
+void triangulatePolygon(std::vector<unsigned int>& dest, const Vec2Vector& points,
+ const std::vector<unsigned int>& holeIndexes)
+{
+ std::vector<Point*> polyline;
+ std::vector<Point*> holeLine;
+ unsigned int contourEnd;
+
+ if (holeIndexes.size() > 0) {
+ contourEnd = holeIndexes[0];
+ } else {
+ contourEnd = points.size();
+ }
+
+ for (unsigned int i = 0; i < contourEnd; i++) {
+ polyline.push_back(new Point(points[i].x, points[i].y, i));
+ }
+
+ SweepContext* sweepContext = new SweepContext(polyline);
+ Sweep* sweep = new Sweep;
+
+ if (holeIndexes.size() > 0) {
+ for (unsigned int i = 0; i < holeIndexes.size(); i++) {
+ if ( i < holeIndexes.size()-1) {
+ for (unsigned int j = holeIndexes[i]; j < points.size() && j <
+ holeIndexes[i+1]; j++)
+ {
+ holeLine.push_back(new Point(points[j].x, points[j].y, j));
+ }
+ } else {
+ for (unsigned int j = holeIndexes[i]; j < points.size(); j++) {
+ holeLine.push_back(new Point(points[j].x, points[j].y, j));
+ }
+ }
+ sweepContext->addHole(holeLine);
+ holeLine.clear();
+ }
+ }
+
+ sweep->Triangulate(*sweepContext);
+
+ std::vector<avg::TriangulationTriangle*>& triangles = sweepContext->getTriangles();
+ for (unsigned int i = 0; i < triangles.size(); ++i) {
+ dest.push_back(triangles[i]->getPoint(0)->m_Index);
+ dest.push_back(triangles[i]->getPoint(1)->m_Index);
+ dest.push_back(triangles[i]->getPoint(2)->m_Index);
+ }
+
+ delete sweep;
+ delete sweepContext;
+
+ for (unsigned int i = 0; i < polyline.size(); i++) {
+ delete polyline[i];
+ }
+}
+
+}
diff --git a/src/base/triangulate/Triangulate.h b/src/base/triangulate/Triangulate.h
new file mode 100644
index 0000000..af538a6
--- /dev/null
+++ b/src/base/triangulate/Triangulate.h
@@ -0,0 +1,33 @@
+//
+// 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
+//
+
+#ifndef TRIANGULATION_H_
+#define TRIANGULATION_H_
+
+#include "../GLMHelper.h"
+namespace avg {
+
+ void triangulatePolygon(std::vector<unsigned int>& dest, const Vec2Vector& points,
+ const std::vector<unsigned int>& holeIndexes = std::vector<unsigned int>());
+
+}
+
+#endif /* TRIANGULATION_H_ */
diff --git a/src/base/triangulate/Utils.h b/src/base/triangulate/Utils.h
new file mode 100644
index 0000000..5dd6685
--- /dev/null
+++ b/src/base/triangulate/Utils.h
@@ -0,0 +1,124 @@
+/*
+ * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+ * http://code.google.com/p/poly2tri/
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Poly2Tri nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef UTILS_H
+#define UTILS_H
+
+// Otherwise #defines like M_PI are undeclared under Visual Studio
+#define _USE_MATH_DEFINES
+
+#include <exception>
+#include <math.h>
+
+namespace avg {
+
+const double PI_3div4 = 3 * M_PI / 4;
+const double EPSILON = 1e-12;
+
+enum Orientation
+{
+ CW, CCW, COLLINEAR
+};
+
+/**
+ * Forumla to calculate signed area<br>
+ * Positive if CCW<br>
+ * Negative if CW<br>
+ * 0 if collinear<br>
+ * <pre>
+ * A[P1,P2,P3] = (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1)
+ * = (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)
+ * </pre>
+ */
+Orientation orient2d(Point& pa, Point& pb, Point& pc)
+{
+ double detleft = (pa.m_X - pc.m_X) * (pb.m_Y - pc.m_Y);
+ double detright = (pa.m_Y - pc.m_Y) * (pb.m_X - pc.m_X);
+ double val = detleft - detright;
+ if (val > -EPSILON && val < EPSILON) {
+ return COLLINEAR;
+ } else if (val > 0) {
+ return CCW;
+ }
+ return CW;
+}
+
+/*
+ bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
+ {
+ double pdx = pd.x;
+ double pdy = pd.y;
+ double adx = pa.x - pdx;
+ double ady = pa.y - pdy;
+ double bdx = pb.x - pdx;
+ double bdy = pb.y - pdy;
+
+ double adxbdy = adx * bdy;
+ double bdxady = bdx * ady;
+ double oabd = adxbdy - bdxady;
+
+ if (oabd <= EPSILON) {
+ return false;
+ }
+
+ double cdx = pc.x - pdx;
+ double cdy = pc.y - pdy;
+
+ double cdxady = cdx * ady;
+ double adxcdy = adx * cdy;
+ double ocad = cdxady - adxcdy;
+
+ if (ocad <= EPSILON) {
+ return false;
+ }
+
+ return true;
+ }
+
+ */
+
+bool inScanArea(Point& pa, Point& pb, Point& pc, Point& pd)
+{
+ double oadb = (pa.m_X - pb.m_X) * (pd.m_Y - pb.m_Y) - (pd.m_X - pb.m_X) * (pa.m_Y - pb.m_Y);
+ if (oadb >= -EPSILON) {
+ return false;
+ }
+
+ double oadc = (pa.m_X - pc.m_X) * (pd.m_Y - pc.m_Y) - (pd.m_X - pc.m_X) * (pa.m_Y - pc.m_Y);
+ if (oadc <= EPSILON) {
+ return false;
+ }
+ return true;
+}
+
+}
+
+#endif