summaryrefslogtreecommitdiff
path: root/src/wrapper/WrapHelper.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/wrapper/WrapHelper.h')
-rw-r--r--src/wrapper/WrapHelper.h397
1 files changed, 397 insertions, 0 deletions
diff --git a/src/wrapper/WrapHelper.h b/src/wrapper/WrapHelper.h
new file mode 100644
index 0000000..cd86439
--- /dev/null
+++ b/src/wrapper/WrapHelper.h
@@ -0,0 +1,397 @@
+//
+// 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 _WrapHelper_H_
+#define _WrapHelper_H_
+
+#include "../api.h"
+#include "../base/GLMHelper.h"
+#include "../base/Exception.h"
+#include "../base/ILogSink.h"
+
+#include "../player/BoostPython.h"
+#include "../player/Player.h"
+#include "../player/TypeRegistry.h"
+
+#include <string>
+
+template<typename T> const T copyObject(const T& v) { return v; }
+
+template <typename ContainerType>
+struct to_tuple
+{
+ static PyObject* convert(ContainerType const& a)
+ {
+ boost::python::list result;
+ typedef typename ContainerType::const_iterator const_iter;
+ for(const_iter p=a.begin();p!=a.end();p++) {
+ result.append(boost::python::object(*p));
+ }
+ return boost::python::incref(boost::python::tuple(result).ptr());
+ }
+
+ static const PyTypeObject* get_pytype() { return &PyTuple_Type; }
+};
+
+template <typename ContainerType>
+struct to_list
+{
+ static PyObject* convert(ContainerType const& a)
+ {
+ boost::python::list result;
+ typedef typename ContainerType::const_iterator const_iter;
+ for(const_iter p=a.begin();p!=a.end();p++) {
+ result.append(boost::python::object(*p));
+ }
+ return boost::python::incref(result.ptr());
+ }
+
+ static const PyTypeObject* get_pytype() { return &PyList_Type; }
+};
+
+template <typename MapType>
+struct to_dict
+{
+ static PyObject* convert(MapType const& a)
+ {
+ boost::python::dict result;
+ typedef typename MapType::const_iterator const_iter;
+ for(const_iter p=a.begin();p!=a.end();p++){
+ result[p->first] = p->second;
+ }
+ return boost::python::incref(boost::python::dict(result).ptr());
+ }
+ static const PyTypeObject* get_pytype() { return &PyDict_Type; }
+};
+
+struct default_policy
+{
+ static bool check_convertibility_per_element() { return false; }
+
+ template <typename ContainerType>
+ static bool check_size(boost::type<ContainerType>, std::size_t /*sz*/)
+ {
+ return true;
+ }
+
+ template <typename ContainerType>
+ static void assert_size(boost::type<ContainerType>, std::size_t /*sz*/) {}
+
+ template <typename ContainerType>
+ static void reserve(ContainerType& a, std::size_t sz) {}
+};
+
+struct fixed_size_policy
+{
+ static bool check_convertibility_per_element() { return true; }
+
+ template <typename ContainerType>
+ static bool check_size(boost::type<ContainerType>, std::size_t sz)
+ {
+ return ContainerType::size() == sz;
+ }
+
+ template <typename ContainerType>
+ static void assert_size(boost::type<ContainerType>, std::size_t sz)
+ {
+ if (!check_size(boost::type<ContainerType>(), sz)) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "Insufficient elements for fixed-size array.");
+ boost::python::throw_error_already_set();
+ }
+ }
+
+ template <typename ContainerType>
+ static void reserve(ContainerType& /*a*/, std::size_t sz)
+ {
+ if (sz > ContainerType::size()) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "Too many elements for fixed-size array.");
+ boost::python::throw_error_already_set();
+ }
+ }
+
+ template <typename ContainerType, typename ValueType>
+ static void set_value(ContainerType& a, std::size_t i, ValueType const& v)
+ {
+ reserve(a, i+1);
+ a[i] = v;
+ }
+};
+
+struct variable_capacity_policy : default_policy
+{
+ template <typename ContainerType>
+ static void reserve(ContainerType& a, std::size_t sz)
+ {
+ a.reserve(sz);
+ }
+
+ template <typename ContainerType, typename ValueType>
+ static void set_value(
+ ContainerType& a,
+ std::size_t
+#if !defined(NDEBUG)
+ i
+#endif
+ ,
+ ValueType const& v)
+ {
+ assert(a.size() == i);
+ a.push_back(v);
+ }
+};
+
+struct fixed_capacity_policy : variable_capacity_policy
+{
+ template <typename ContainerType>
+ static bool check_size(boost::type<ContainerType>, std::size_t sz)
+ {
+ return ContainerType::max_size() >= sz;
+ }
+};
+
+struct linked_list_policy : default_policy
+{
+ template <typename ContainerType, typename ValueType>
+ static void
+ set_value(ContainerType& a, std::size_t /*i*/, ValueType const& v)
+ {
+ a.push_back(v);
+ }
+};
+
+struct set_policy : default_policy
+{
+ template <typename ContainerType, typename ValueType>
+ static void
+ set_value(ContainerType& a, std::size_t /*i*/, ValueType const& v)
+ {
+ a.insert(v);
+ }
+};
+
+template <typename ContainerType, typename ConversionPolicy>
+struct from_python_sequence
+{
+ typedef typename ContainerType::value_type container_element_type;
+
+ from_python_sequence()
+ {
+ boost::python::converter::registry::push_back(
+ &convertible,
+ &construct,
+ boost::python::type_id<ContainerType>());
+ }
+
+ static void* convertible(PyObject* obj_ptr)
+ {
+ if (!( PyList_Check(obj_ptr)
+ || PyTuple_Check(obj_ptr)
+ || PyIter_Check(obj_ptr)
+ || PyRange_Check(obj_ptr)
+ || ( !PyString_Check(obj_ptr)
+ && !PyUnicode_Check(obj_ptr)
+ && ( obj_ptr->ob_type == 0
+ || obj_ptr->ob_type->ob_type == 0
+ || obj_ptr->ob_type->ob_type->tp_name == 0
+ || std::strcmp(
+ obj_ptr->ob_type->ob_type->tp_name,
+ "Boost.Python.class") != 0)
+ && PyObject_HasAttrString(obj_ptr, "__len__")
+ && PyObject_HasAttrString(obj_ptr, "__getitem__")))) return 0;
+ boost::python::handle<> obj_iter(
+ boost::python::allow_null(PyObject_GetIter(obj_ptr)));
+ if (!obj_iter.get()) { // must be convertible to an iterator
+ PyErr_Clear();
+ return 0;
+ }
+ if (ConversionPolicy::check_convertibility_per_element()) {
+ int obj_size = int(PyObject_Length(obj_ptr));
+ if (obj_size < 0) { // must be a measurable sequence
+ PyErr_Clear();
+ return 0;
+ }
+ if (!ConversionPolicy::check_size(
+ boost::type<ContainerType>(), obj_size)) return 0;
+ bool is_range = PyRange_Check(obj_ptr);
+ std::size_t i=0;
+ if (!all_elements_convertible(obj_iter, is_range, i)) return 0;
+ if (!is_range) assert(i == (std::size_t)obj_size);
+ }
+ return obj_ptr;
+ }
+
+ // This loop factored out by Achim Domma to avoid Visual C++
+ // Internal Compiler Error.
+ static bool
+ all_elements_convertible(
+ boost::python::handle<>& obj_iter,
+ bool is_range,
+ std::size_t& i)
+ {
+ for(;;i++) {
+ boost::python::handle<> py_elem_hdl(
+ boost::python::allow_null(PyIter_Next(obj_iter.get())));
+ if (PyErr_Occurred()) {
+ PyErr_Clear();
+ return false;
+ }
+ if (!py_elem_hdl.get()) break; // end of iteration
+ boost::python::object py_elem_obj(py_elem_hdl);
+ boost::python::extract<container_element_type>
+ elem_proxy(py_elem_obj);
+ if (!elem_proxy.check()) return false;
+ if (is_range) break; // in a range all elements are of the same type
+ }
+ return true;
+ }
+
+ static void construct(
+ PyObject* obj_ptr,
+ boost::python::converter::rvalue_from_python_stage1_data* data)
+ {
+ boost::python::handle<> obj_iter(PyObject_GetIter(obj_ptr));
+ void* storage = (
+ (boost::python::converter::rvalue_from_python_storage<ContainerType>*)
+ data)->storage.bytes;
+ new (storage) ContainerType();
+ data->convertible = storage;
+ ContainerType& result = *((ContainerType*)storage);
+ std::size_t i=0;
+ for(;;i++) {
+ boost::python::handle<> py_elem_hdl(
+ boost::python::allow_null(PyIter_Next(obj_iter.get())));
+ if (PyErr_Occurred()) boost::python::throw_error_already_set();
+ if (!py_elem_hdl.get()) break; // end of iteration
+ boost::python::object py_elem_obj(py_elem_hdl);
+ boost::python::extract<container_element_type> elem_proxy(py_elem_obj);
+ ConversionPolicy::set_value(result, i, elem_proxy());
+ }
+ ConversionPolicy::assert_size(boost::type<ContainerType>(), i);
+ }
+};
+
+template<class T>
+float deprecatedGet(T& node)
+{
+ throw avg::Exception(AVG_ERR_DEPRECATED, "Attribute has been removed from libavg.");
+}
+
+template<class T>
+void deprecatedSet(T& node, float d)
+{
+ throw avg::Exception(AVG_ERR_DEPRECATED, "Attribute has been removed from libavg.");
+}
+
+namespace Vec2Helper
+{
+ int len(const glm::vec2&);
+ float getX(const glm::vec2& pt);
+ float getY(const glm::vec2& pt);
+ void setX(glm::vec2& pt, float val);
+ void setY(glm::vec2& pt, float val);
+ void checkItemRange(int i);
+ float getItem(const glm::vec2& pt, int i);
+ void setItem(glm::vec2& pt, int i, float val);
+ std::string str(const glm::vec2& pt);
+ std::string repr(const glm::vec2& pt);
+ long getHash(const glm::vec2& pt);
+ glm::vec2 safeGetNormalized(const glm::vec2& pt);
+ float getNorm(const glm::vec2& pt);
+ float vecAngle(const glm::vec2& pt1, const glm::vec2& pt2);
+}
+
+class ConstVec2: public glm::vec2
+{
+public:
+ ConstVec2();
+ ConstVec2(const glm::vec2& other);
+ glm::vec2 toVec2() const;
+ //operator glm::vec2() const;
+};
+
+AVG_API void checkEmptyArgs(const boost::python::tuple &args, int numArgs=1);
+
+template<const char * pszType>
+avg::ExportedObjectPtr createExportedObject(const boost::python::tuple &args,
+ const boost::python::dict &attrs)
+{
+ checkEmptyArgs(args);
+ return avg::TypeRegistry::get()->createObject(pszType, attrs);
+}
+
+template<const char * pszType>
+avg::NodePtr createNode(const boost::python::tuple &args,
+ const boost::python::dict &attrs)
+{
+ checkEmptyArgs(args);
+ return avg::Player::get()->createNode(pszType, attrs, args[0]);
+};
+
+template <typename T>struct Exception_to_python_exception
+{
+ static PyObject* convert (const T& ex)
+ {
+ PyObject *arglist = boost::python::incref(
+ Py_BuildValue("(s)", ex.what()));
+ return boost::python::incref(
+ PyObject_CallObject(PyExc_RuntimeError, arglist));
+ }
+};
+
+
+template<typename T> struct ExceptionTranslator
+{
+public:
+ void operator()(const T& ex) const
+ {
+ PyErr_SetString(m_PyExcept, ex.what());
+ }
+
+ ExceptionTranslator(PyObject* py_except): m_PyExcept(py_except)
+ {
+ boost::python::register_exception_translator<T>(*this);
+ }
+
+ ExceptionTranslator(const ExceptionTranslator& other):m_PyExcept(other.m_PyExcept)
+ {
+ }
+
+ private:
+
+ PyObject* m_PyExcept;
+
+};
+
+template <typename T> void translateException(PyObject* e) {
+ ExceptionTranslator<T> my_translator(e);
+}
+
+void exportMessages(boost::python::object& nodeClass, const std::string& sClassName);
+
+void addPythonLogger(PyObject * self, PyObject * pyLogger);
+void removePythonLogger(PyObject * self, PyObject * pyLogger);
+
+void pytrace(PyObject * self, const avg::category_t& category, const avg::UTF8String& sMsg,
+ avg::severity_t severity);
+
+#endif