# HG changeset patch # User Chris Cannam # Date 1416822649 0 # Node ID ffaa1fb3d7de709fbb5407b47abaf1fe7dd96ce2 # Parent 40a01bb24209ac0ac521f32e7811d9b759045d08 inline is not a useful keyword with contemporary compilers diff -r 40a01bb24209 -r ffaa1fb3d7de Makefile.linux --- a/Makefile.linux Thu Nov 20 13:02:50 2014 +0000 +++ b/Makefile.linux Mon Nov 24 09:50:49 2014 +0000 @@ -4,7 +4,7 @@ -I/usr/include/python2.7 \ -I/usr/lib/python2.7/dist-packages/numpy/core/include -LDFLAGS := -shared -Wl,-Bstatic -lvamp-sdk -Wl,-Bdynamic -lpython2.7 -lpthread -Wl,--version-script=vamp-plugin.map +LDFLAGS := -shared -Wl,-Bstatic -lvamp-sdk -Wl,-Bdynamic -Wl,-z,defs -lpython2.7 -lpthread -Wl,--version-script=vamp-plugin.map -ldl default: vampy.so diff -r 40a01bb24209 -r ffaa1fb3d7de PyPlugin.cpp --- a/PyPlugin.cpp Thu Nov 20 13:02:50 2014 +0000 +++ b/PyPlugin.cpp Mon Nov 24 09:50:49 2014 +0000 @@ -475,3 +475,100 @@ } +/// optimised process call +PyPlugin::FeatureSet +PyPlugin::processMethodCall(const float *const *inputBuffers,Vamp::RealTime timestamp) +{ + + /// Optimizations: 1) we avoid ...ObjArg functions since we know + /// the number of arguments, and we don't like va_list parsing + /// in the process. 2) Also: we're supposed to incref args, + /// but instead, we let the arguments tuple steal the references + /// and decref them when it is deallocated. + /// 3) all conversions are now using the fast sequence protocol + /// (indexing the underlying object array). + + FeatureSet rFeatureSet; + PyObject *pyChannelList = NULL; + + if (m_processType == numpy_bufferProcess) { + pyChannelList = m_ti.InputBuffers_As_SharedMemoryList( + inputBuffers,m_channels,m_blockSize,m_inputDomain); + } + + if (m_processType == legacyProcess) { + pyChannelList = m_ti.InputBuffers_As_PythonLists( + inputBuffers,m_channels,m_blockSize,m_inputDomain); + } + +#ifdef HAVE_NUMPY + if (m_processType == numpy_arrayProcess) { + pyChannelList = m_ti.InputBuffers_As_NumpyArray( + inputBuffers,m_channels,m_blockSize,m_inputDomain); + } +#endif + +/// we don't expect these to fail unless out of memory (which is very unlikely on modern systems) +#ifdef _DEBUG + if (!pyChannelList) { + if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();} + std::string method = PyString_AsString(m_pyProcess); + cerr << PLUGIN_ERROR << "Failed to create channel list." << endl; + return rFeatureSet; + } +#endif + + PyObject *pyTimeStamp = NULL; + + if (m_useRealTimeFlag) { + //(1) pass TimeStamp as PyRealTime object + pyTimeStamp = PyRealTime_FromRealTime(timestamp); + + } else { + //(2) pass TimeStamp as frame count (long Sample Count) + pyTimeStamp = PyLong_FromLong(Vamp::RealTime::realTime2Frame + (timestamp, (unsigned int) m_inputSampleRate)); + } + + +#ifdef _DEBUG + if (!pyTimeStamp) { + if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();} + std::string method = PyString_AsString(m_pyProcess); + cerr << PLUGIN_ERROR << "Failed to create RealTime time stamp." << endl; + Py_DECREF(pyChannelList); + return rFeatureSet; + } +#endif + + /// Old method: Call python process (returns new reference) + /// PyObject *pyValue = PyObject_CallMethodObjArgs + /// (m_pyInstance,m_pyProcess,pyChannelList,pyTimeStamp,NULL); + + PyObject *pyArgs = PyTuple_New(2); + PyTuple_SET_ITEM(pyArgs, 0, pyChannelList); + PyTuple_SET_ITEM(pyArgs, 1, pyTimeStamp); + + /// Call python process (returns new reference) {kwArgs = NULL} + PyObject *pyValue = PyObject_Call(m_pyProcessCallable,pyArgs,NULL); + + if (!pyValue) { + if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();} + std::string method = PyString_AsString(m_pyProcess); + cerr << PLUGIN_ERROR << "An error occurred while evaluating Python process." << endl; + Py_CLEAR(pyValue); + Py_CLEAR(pyArgs); + return rFeatureSet; + } + + rFeatureSet = m_ti.PyValue_To_FeatureSet(pyValue); + if (!m_ti.error) { + Py_DECREF(pyValue); + Py_DECREF(pyArgs); + } else { + typeErrorHandler(PyString_AsString(m_pyProcess),true); + Py_CLEAR(pyValue); + Py_CLEAR(pyArgs); + } + return rFeatureSet; +} diff -r 40a01bb24209 -r ffaa1fb3d7de PyPlugin.h --- a/PyPlugin.h Thu Nov 20 13:02:50 2014 +0000 +++ b/PyPlugin.h Mon Nov 24 09:50:49 2014 +0000 @@ -363,102 +363,4 @@ }; -/// optimised process call -inline PyPlugin::FeatureSet -PyPlugin::processMethodCall(const float *const *inputBuffers,Vamp::RealTime timestamp) -{ - - /// Optimizations: 1) we avoid ...ObjArg functions since we know - /// the number of arguments, and we don't like va_list parsing - /// in the process. 2) Also: we're supposed to incref args, - /// but instead, we let the arguments tuple steal the references - /// and decref them when it is deallocated. - /// 3) all conversions are now using the fast sequence protocol - /// (indexing the underlying object array). - - FeatureSet rFeatureSet; - PyObject *pyChannelList = NULL; - - if (m_processType == numpy_bufferProcess) { - pyChannelList = m_ti.InputBuffers_As_SharedMemoryList( - inputBuffers,m_channels,m_blockSize,m_inputDomain); - } - - if (m_processType == legacyProcess) { - pyChannelList = m_ti.InputBuffers_As_PythonLists( - inputBuffers,m_channels,m_blockSize,m_inputDomain); - } - -#ifdef HAVE_NUMPY - if (m_processType == numpy_arrayProcess) { - pyChannelList = m_ti.InputBuffers_As_NumpyArray( - inputBuffers,m_channels,m_blockSize,m_inputDomain); - } #endif - -/// we don't expect these to fail unless out of memory (which is very unlikely on modern systems) -#ifdef _DEBUG - if (!pyChannelList) { - if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();} - std::string method = PyString_AsString(m_pyProcess); - cerr << PLUGIN_ERROR << "Failed to create channel list." << endl; - return rFeatureSet; - } -#endif - - PyObject *pyTimeStamp = NULL; - - if (m_useRealTimeFlag) { - //(1) pass TimeStamp as PyRealTime object - pyTimeStamp = PyRealTime_FromRealTime(timestamp); - - } else { - //(2) pass TimeStamp as frame count (long Sample Count) - pyTimeStamp = PyLong_FromLong(Vamp::RealTime::realTime2Frame - (timestamp, (unsigned int) m_inputSampleRate)); - } - - -#ifdef _DEBUG - if (!pyTimeStamp) { - if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();} - std::string method = PyString_AsString(m_pyProcess); - cerr << PLUGIN_ERROR << "Failed to create RealTime time stamp." << endl; - Py_DECREF(pyChannelList); - return rFeatureSet; - } -#endif - - /// Old method: Call python process (returns new reference) - /// PyObject *pyValue = PyObject_CallMethodObjArgs - /// (m_pyInstance,m_pyProcess,pyChannelList,pyTimeStamp,NULL); - - PyObject *pyArgs = PyTuple_New(2); - PyTuple_SET_ITEM(pyArgs, 0, pyChannelList); - PyTuple_SET_ITEM(pyArgs, 1, pyTimeStamp); - - /// Call python process (returns new reference) {kwArgs = NULL} - PyObject *pyValue = PyObject_Call(m_pyProcessCallable,pyArgs,NULL); - - if (!pyValue) { - if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();} - std::string method = PyString_AsString(m_pyProcess); - cerr << PLUGIN_ERROR << "An error occurred while evaluating Python process." << endl; - Py_CLEAR(pyValue); - Py_CLEAR(pyArgs); - return rFeatureSet; - } - - rFeatureSet = m_ti.PyValue_To_FeatureSet(pyValue); - if (!m_ti.error) { - Py_DECREF(pyValue); - Py_DECREF(pyArgs); - } else { - typeErrorHandler(PyString_AsString(m_pyProcess),true); - Py_CLEAR(pyValue); - Py_CLEAR(pyArgs); - } - return rFeatureSet; -} - -#endif diff -r 40a01bb24209 -r ffaa1fb3d7de PyTypeConversions.h --- a/PyTypeConversions.h Thu Nov 20 13:02:50 2014 +0000 +++ b/PyTypeConversions.h Mon Nov 24 09:50:49 2014 +0000 @@ -136,7 +136,7 @@ } /// this is a special case. numpy.float64 has an array conversions but no array descriptor - inline std::vector PyArray0D_Convert(PyArrayInterface *ai) const + std::vector PyArray0D_Convert(PyArrayInterface *ai) const { std::vector rValue; if ((ai->typekind) == *"f") diff -r 40a01bb24209 -r ffaa1fb3d7de PyTypeInterface.cpp --- a/PyTypeInterface.cpp Thu Nov 20 13:02:50 2014 +0000 +++ b/PyTypeInterface.cpp Mon Nov 24 09:50:49 2014 +0000 @@ -230,7 +230,7 @@ /// passing the sample buffers as builtin python lists /// Optimization: using fast sequence protocol -inline PyObject* +PyObject* PyTypeInterface::InputBuffers_As_PythonLists(const float *const *inputBuffers,const size_t& channels, const size_t& blockSize, const Vamp::Plugin::InputDomain& dtype) { //create a list of lists (new references) @@ -289,7 +289,7 @@ /// numpy buffer interface: passing the sample buffers as shared memory buffers /// Optimization: using sequence protocol for creating the buffer list -inline PyObject* +PyObject* PyTypeInterface::InputBuffers_As_SharedMemoryList(const float *const *inputBuffers,const size_t& channels, const size_t& blockSize, const Vamp::Plugin::InputDomain& dtype) { //create a list of buffers (returns new references) @@ -320,7 +320,7 @@ /// numpy array interface: passing the sample buffers as 2D numpy array /// Optimization: using array API (needs numpy headers) #ifdef HAVE_NUMPY -inline PyObject* +PyObject* PyTypeInterface::InputBuffers_As_NumpyArray(const float *const *inputBuffers,const size_t& channels, const size_t& blockSize, const Vamp::Plugin::InputDomain& dtype) { /* diff -r 40a01bb24209 -r ffaa1fb3d7de PyTypeInterface.h --- a/PyTypeInterface.h Thu Nov 20 13:02:50 2014 +0000 +++ b/PyTypeInterface.h Mon Nov 24 09:50:49 2014 +0000 @@ -244,44 +244,44 @@ //Vamp specific types Vamp::Plugin::FeatureSet PyValue_To_FeatureSet(PyObject*) const; - inline void PyValue_To_rValue(PyObject *pyValue, Vamp::Plugin::FeatureSet &r) const + void PyValue_To_rValue(PyObject *pyValue, Vamp::Plugin::FeatureSet &r) const { r = this->PyValue_To_FeatureSet(pyValue); } Vamp::RealTime PyValue_To_RealTime(PyObject*) const; - inline void PyValue_To_rValue(PyObject *pyValue, Vamp::RealTime &r) const + void PyValue_To_rValue(PyObject *pyValue, Vamp::RealTime &r) const { r = this->PyValue_To_RealTime(pyValue); } Vamp::Plugin::OutputDescriptor::SampleType PyValue_To_SampleType(PyObject*) const; Vamp::Plugin::InputDomain PyValue_To_InputDomain(PyObject*) const; - inline void PyValue_To_rValue(PyObject *pyValue, Vamp::Plugin::InputDomain &r) const + void PyValue_To_rValue(PyObject *pyValue, Vamp::Plugin::InputDomain &r) const { r = this->PyValue_To_InputDomain(pyValue); } /* Overloaded PyValue_To_rValue() to support generic functions */ - inline void PyValue_To_rValue(PyObject *pyValue, float &defValue) const + void PyValue_To_rValue(PyObject *pyValue, float &defValue) const { float tmp = m_conv.PyValue_To_Float(pyValue); if(!m_error) defValue = tmp; } - inline void PyValue_To_rValue(PyObject *pyValue, size_t &defValue) const + void PyValue_To_rValue(PyObject *pyValue, size_t &defValue) const { size_t tmp = m_conv.PyValue_To_Size_t(pyValue); if(!m_error) defValue = tmp; } - inline void PyValue_To_rValue(PyObject *pyValue, bool &defValue) const + void PyValue_To_rValue(PyObject *pyValue, bool &defValue) const { bool tmp = m_conv.PyValue_To_Bool(pyValue); if(!m_error) defValue = tmp; } - inline void PyValue_To_rValue(PyObject *pyValue, std::string &defValue) const + void PyValue_To_rValue(PyObject *pyValue, std::string &defValue) const { std::string tmp = m_conv.PyValue_To_String(pyValue); if(!m_error) defValue = tmp; } /*used by templates where we expect no return value, if there is one it will be ignored*/ - inline void PyValue_To_rValue(PyObject *pyValue, NoneType &defValue) const + void PyValue_To_rValue(PyObject *pyValue, NoneType &defValue) const { if (m_strict && pyValue != Py_None) setValueError("Strict conversion error: Expected 'None' type.",m_strict); } /* convert sequence types to Vamp List types */ - inline void PyValue_To_rValue(PyObject *pyValue, Vamp::Plugin::OutputList &r) const + void PyValue_To_rValue(PyObject *pyValue, Vamp::Plugin::OutputList &r) const { r = this->PyValue_To_VampList(pyValue); } - inline void PyValue_To_rValue(PyObject *pyValue, Vamp::Plugin::ParameterList &r) const + void PyValue_To_rValue(PyObject *pyValue, Vamp::Plugin::ParameterList &r) const { r = this->PyValue_To_VampList(pyValue); } - inline void PyValue_To_rValue(PyObject *pyValue, Vamp::Plugin::FeatureList &r) const + void PyValue_To_rValue(PyObject *pyValue, Vamp::Plugin::FeatureList &r) const { r = this->PyValue_To_VampList(pyValue); } /// this is only needed for RealTime->Frame conversion @@ -299,32 +299,32 @@ ValueError& lastError() const; /* Overloaded _convert(), bypasses error checking to avoid doing it twice in internals. */ - inline void _convert(PyObject *pyValue,float &r) const + void _convert(PyObject *pyValue,float &r) const { r = m_conv.PyValue_To_Float(pyValue); } - inline void _convert(PyObject *pyValue,size_t &r) const + void _convert(PyObject *pyValue,size_t &r) const { r = m_conv.PyValue_To_Size_t(pyValue); } - inline void _convert(PyObject *pyValue,bool &r) const + void _convert(PyObject *pyValue,bool &r) const { r = m_conv.PyValue_To_Bool(pyValue); } - inline void _convert(PyObject *pyValue,std::string &r) const + void _convert(PyObject *pyValue,std::string &r) const { r = m_conv.PyValue_To_String(pyValue); } - inline void _convert(PyObject *pyValue,std::vector &r) const + void _convert(PyObject *pyValue,std::vector &r) const { r = m_conv.PyValue_To_StringVector(pyValue); } - inline void _convert(PyObject *pyValue,std::vector &r) const + void _convert(PyObject *pyValue,std::vector &r) const { r = m_conv.PyValue_To_FloatVector(pyValue); } - inline void _convert(PyObject *pyValue,Vamp::RealTime &r) const + void _convert(PyObject *pyValue,Vamp::RealTime &r) const { r = PyValue_To_RealTime(pyValue); } - inline void _convert(PyObject *pyValue,Vamp::Plugin::OutputDescriptor::SampleType &r) const + void _convert(PyObject *pyValue,Vamp::Plugin::OutputDescriptor::SampleType &r) const { r = PyValue_To_SampleType(pyValue); } - // inline void _convert(PyObject *pyValue,Vamp::Plugin::InputDomain &r) const + // void _convert(PyObject *pyValue,Vamp::Plugin::InputDomain &r) const // { r = m_conv.PyValue_To_InputDomain(pyValue); } /* Identify descriptors for error reporting */ - inline std::string getDescriptorId(Vamp::Plugin::OutputDescriptor d) const + std::string getDescriptorId(Vamp::Plugin::OutputDescriptor d) const {return std::string("Output Descriptor '") + d.identifier +"' ";} - inline std::string getDescriptorId(Vamp::Plugin::ParameterDescriptor d) const + std::string getDescriptorId(Vamp::Plugin::ParameterDescriptor d) const {return std::string("Parameter Descriptor '") + d.identifier +"' ";} - inline std::string getDescriptorId(Vamp::Plugin::Feature f) const + std::string getDescriptorId(Vamp::Plugin::Feature f) const {return std::string("Feature (") + f.label + ")"; } public: