diff options
Diffstat (limited to 'src/wrapper/WrapHelper.h')
-rw-r--r-- | src/wrapper/WrapHelper.h | 397 |
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 |