comparison PyExtensionModule.cpp @ 37:27bab3a16c9a vampy2final

new branch Vampy2final
author fazekasgy
date Mon, 05 Oct 2009 11:28:00 +0000
parents
children af9c4cee95a8
comparison
equal deleted inserted replaced
-1:000000000000 37:27bab3a16c9a
1 /*
2
3 * Vampy : This plugin is a wrapper around the Vamp plugin API.
4 * It allows for writing Vamp plugins in Python.
5
6 * Centre for Digital Music, Queen Mary University of London.
7 * Copyright (C) 2008-2009 Gyorgy Fazekas, QMUL. (See Vamp sources
8 * for licence information.)
9
10 */
11
12 #include <Python.h>
13 #include "PyExtensionModule.h"
14 #include "PyRealTime.h"
15 #include "PyFeature.h"
16 #include "PyFeatureSet.h"
17 #include "PyParameterDescriptor.h"
18 #include "PyOutputDescriptor.h"
19 #include "vamp/vamp.h"
20 #include "vamp-sdk/Plugin.h"
21
22 using namespace std;
23 using namespace Vamp;
24 using Vamp::Plugin;
25 using Vamp::RealTime;
26
27 /* Functions Exposed by Vampy */
28
29 /* Creating PyRealTime Objects from frame count */
30
31 /* New RealTime object from Frame (with given samplerate) */
32 static PyObject *
33 RealTime_frame2RealTime(PyObject *ignored, PyObject *args)
34 {
35 long frame;
36 unsigned int sampleRate;
37
38 if (!(args && PyTuple_GET_SIZE(args) == 2)) {
39 PyErr_SetString(PyExc_ValueError,"frame2RealTime requires two arguments: frame and sample rate.");
40 return NULL;
41 }
42
43 PyObject* pyFrame = PyTuple_GET_ITEM(args,0);
44 PyObject* pySampleRate = PyTuple_GET_ITEM(args,1);
45
46 /// frame
47 if (PyInt_Check(pyFrame)) frame = PyInt_AS_LONG(pyFrame);
48 else if (PyLong_Check(pyFrame)) frame = PyLong_AsLong(pyFrame);
49 else {
50 PyErr_SetString(PyExc_ValueError,"frame2RealTime 'frame' argument must be long integer.");
51 return NULL;
52 }
53
54 /// sample rate
55 if (PyInt_Check(pySampleRate))
56 sampleRate = _long2uint(PyInt_AS_LONG(pySampleRate));
57 else if (PyFloat_Check(pySampleRate))
58 sampleRate = _dbl2uint(PyFloat_AS_DOUBLE(pySampleRate));
59 else if (PyLong_Check(pySampleRate))
60 sampleRate = _long2uint(PyLong_AsLong(pySampleRate));
61 else {
62 PyErr_SetString(PyExc_ValueError,"frame2RealTime 'sample rate' argument must be int, long or float.");
63 return NULL;
64 }
65
66 if (!sampleRate) {
67 PyErr_SetString(PyExc_ValueError,"frame2RealTime 'sample rate' argument overflow error. Argument must be 0 < arg < UINT_MAX.");
68 cerr << "Value: " << sampleRate << endl;
69 return NULL;
70 }
71
72 // simpler but slower:
73 // if (!PyArg_ParseTuple(args, "lI:realtime.frame2RealTime ",
74 // &frame,&sampleRate))
75 // return NULL;
76
77 RealTimeObject *self;
78 self = PyObject_New(RealTimeObject, &RealTime_Type);
79 if (self == NULL) return NULL;
80
81 self->rt = new RealTime(
82 RealTime::frame2RealTime(frame,sampleRate));
83
84 return (PyObject *) self;
85 }
86
87 /*
88
89 Note: these functions are not very interesting on their own, but
90 they can be used to make the semantics of the plugin clearer.
91 They return ordinary Python list objects. All type checking
92 is performed in the type interface.
93
94 */
95
96 /* New PyOutputList Objects */
97 static PyObject *
98 OutputList_new(PyObject *ignored, PyObject *args)
99 {
100 if (args and PyTuple_Check(args))
101 return PySequence_List(args);
102 else return (PyObject *) PyList_New(0);
103 }
104
105
106 /* New PyParameterList Objects */
107 static PyObject *
108 ParameterList_new(PyObject *ignored, PyObject *args)
109 {
110 if (args and PyTuple_Check(args))
111 return PySequence_List(args);
112 else return (PyObject *) PyList_New(0);
113 }
114
115 /* New PyFeatureList Objects */
116 static PyObject *
117 FeatureList_new(PyObject *ignored, PyObject *args)
118 {
119 if (args and PyTuple_Check(args))
120 return PySequence_List(args);
121 else return (PyObject *) PyList_New(0);
122 }
123
124
125 /* Declare the methods exposed by the vampy module */
126
127
128 PyMethodDef VampyMethods[] = {
129 /*NOTE: This is conventionally static, but limiting the scope
130 here will cause seg fault if the declared functions are
131 called back from a Python function wrapped in a C++ class.*/
132
133 {"frame2RealTime", (PyCFunction)RealTime_frame2RealTime, METH_VARARGS,
134 PyDoc_STR("frame2RealTime((int64)frame, (uint32)sampleRate ) -> returns new RealTime object from frame.")},
135
136 {"OutputList", OutputList_new, METH_VARARGS,
137 PyDoc_STR("OutputList() -> returns new OutputList object")},
138
139 {"ParameterList", ParameterList_new, METH_VARARGS,
140 PyDoc_STR("ParameterList() -> returns new ParameterList object")},
141
142 {"FeatureList", FeatureList_new, METH_VARARGS,
143 PyDoc_STR("FeatureList() -> returns new FeatureList object")},
144
145 {NULL, NULL, 0, NULL}
146 };
147
148 /* Module Documentation */
149 // PyDoc_STRVAR(vampy_doc,"This module exposes Vamp plugin data type wrappers.");
150
151 static int
152 setint(PyObject *d, char *name, int value)
153 {
154 PyObject *v;
155 int err;
156 v = PyInt_FromLong((long)value);
157 err = PyDict_SetItemString(d, name, v);
158 Py_XDECREF(v);
159 return err;
160 }
161
162 static int
163 setdbl(PyObject *d, char *name, double value)
164 {
165 PyObject *v;
166 int err;
167 v = PyFloat_FromDouble(value);
168 err = PyDict_SetItemString(d, name, v);
169 Py_XDECREF(v);
170 return err;
171 }
172
173 static int
174 setstr(PyObject *d, char *name, char *value)
175 {
176 PyObject *v;
177 int err;
178 v = PyString_FromString(value);
179 err = PyDict_SetItemString(d, name, v);
180 Py_XDECREF(v);
181 return err;
182 }
183
184
185 PyMODINIT_FUNC
186 initvampy(void)
187 {
188 PyObject *module, *mdict;
189
190 /* if (PyType_Ready(&Feature_Type) < 0) return;
191 Note: Why do we get a segfault if this is initialised here?
192 PyType_Ready adds these object to the GC.
193 This is OK for an extension module, but it is a mistake here,
194 because the adresses become invalid when the shared library
195 is unloaded. When the GC tries to visit a these objects,
196 it will fail.*/
197
198 RealTime_Type.ob_type = &PyType_Type;
199 Feature_Type.ob_type = &PyType_Type;
200 OutputDescriptor_Type.ob_type = &PyType_Type;
201 ParameterDescriptor_Type.ob_type = &PyType_Type;
202 initFeatureSetType(); // this is derived from the builtin dict
203
204 PyImport_AddModule("vampy");
205 module = Py_InitModule("vampy", VampyMethods);
206 if (!module) goto failure;
207 mdict = PyModule_GetDict(module);
208 if (!mdict) goto failure;
209
210 /// vampy plugin wrapper flags
211 if (setint(mdict, "vf_NULL", vf_NULL) < 0) goto failure;
212 if (setint(mdict, "vf_DEBUG", vf_DEBUG) < 0) goto failure;
213 if (setint(mdict, "vf_STRICT", vf_STRICT) < 0) goto failure;
214 if (setint(mdict, "vf_QUIT", vf_QUIT) < 0) goto failure;
215 if (setint(mdict, "vf_REALTIME", vf_REALTIME) < 0) goto failure;
216 if (setint(mdict, "vf_BUFFER", vf_BUFFER) < 0) goto failure;
217 if (setint(mdict, "vf_ARRAY", vf_ARRAY) < 0) goto failure;
218 if (setint(mdict, "vf_DEFAULT_V2", vf_DEFAULT_V2) < 0) goto failure;
219
220 /// Vamp enum types simulation
221 if (setint(mdict, "OneSamplePerStep", Vamp::Plugin::OutputDescriptor::OneSamplePerStep) < 0) goto failure;
222 if (setint(mdict, "FixedSampleRate", Vamp::Plugin::OutputDescriptor::FixedSampleRate) < 0) goto failure;
223 if (setint(mdict, "VariableSampleRate", Vamp::Plugin::OutputDescriptor::VariableSampleRate) < 0) goto failure;
224 if (setint(mdict, "TimeDomain", Vamp::Plugin::TimeDomain) < 0) goto failure;
225 if (setint(mdict, "FrequencyDomain", Vamp::Plugin::FrequencyDomain) < 0) goto failure;
226
227 /// module attributes
228 if (setstr(mdict, "__name__", "vampy") < 0) goto failure;
229 if (setdbl(mdict, "__version__", 2.0) < 0) goto failure;
230 if (setdbl(mdict, "__VAMP_API_VERSION__", (double) VAMP_API_VERSION) < 0) goto failure;
231 #ifdef HAVE_NUMPY
232 if (setint(mdict, "__numpy__", 1) < 0) goto failure;
233 #else
234 if (setint(mdict, "__numpy__", 0) < 0) goto failure;
235 #endif
236
237 /// type objects
238 Py_INCREF(&RealTime_Type);
239 if (PyModule_AddObject(module,"RealTime",(PyObject*)&RealTime_Type) !=0) goto failure;
240
241 Py_INCREF((PyObject*)&Feature_Type);
242 if (PyModule_AddObject(module,"Feature",(PyObject*)&Feature_Type) !=0) goto failure;
243
244 Py_INCREF((PyObject*)&FeatureSet_Type);
245 if (PyModule_AddObject(module,"FeatureSet",(PyObject*)&FeatureSet_Type) !=0) goto failure;
246
247 Py_INCREF((PyObject*)&OutputDescriptor_Type);
248 if (PyModule_AddObject(module,"OutputDescriptor",(PyObject*)&OutputDescriptor_Type) !=0) goto failure;
249
250 Py_INCREF((PyObject*)&ParameterDescriptor_Type);
251 if (PyModule_AddObject(module,"ParameterDescriptor",(PyObject*)&ParameterDescriptor_Type) !=0) goto failure;
252
253 #ifdef _DEBUG
254 cerr << "Vampy: extension module initialised." << endl;
255 #endif
256
257 return;
258
259 failure :
260 if (PyErr_Occurred()) {PyErr_Print(); PyErr_Clear();}
261 cerr << "Vampy::PyExtensionModule::initvampy: Failed to initialise extension module." << endl;
262 return;
263 }
264
265