Chris@26
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@26
|
2
|
Chris@26
|
3 /*
|
Chris@26
|
4 VampyHost
|
Chris@26
|
5
|
Chris@26
|
6 Use Vamp audio analysis plugins in Python
|
Chris@26
|
7
|
Chris@26
|
8 Gyorgy Fazekas and Chris Cannam
|
Chris@26
|
9 Centre for Digital Music, Queen Mary, University of London
|
Chris@26
|
10 Copyright 2008-2014 Queen Mary, University of London
|
Chris@26
|
11
|
Chris@26
|
12 Permission is hereby granted, free of charge, to any person
|
Chris@26
|
13 obtaining a copy of this software and associated documentation
|
Chris@26
|
14 files (the "Software"), to deal in the Software without
|
Chris@26
|
15 restriction, including without limitation the rights to use, copy,
|
Chris@26
|
16 modify, merge, publish, distribute, sublicense, and/or sell copies
|
Chris@26
|
17 of the Software, and to permit persons to whom the Software is
|
Chris@26
|
18 furnished to do so, subject to the following conditions:
|
Chris@26
|
19
|
Chris@26
|
20 The above copyright notice and this permission notice shall be
|
Chris@26
|
21 included in all copies or substantial portions of the Software.
|
Chris@26
|
22
|
Chris@26
|
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
Chris@26
|
24 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
Chris@26
|
25 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
Chris@26
|
26 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
Chris@26
|
27 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
Chris@26
|
28 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
Chris@26
|
29 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
Chris@26
|
30
|
Chris@26
|
31 Except as contained in this notice, the names of the Centre for
|
Chris@26
|
32 Digital Music; Queen Mary, University of London; and the authors
|
Chris@26
|
33 shall not be used in advertising or otherwise to promote the sale,
|
Chris@26
|
34 use or other dealings in this Software without prior written
|
Chris@26
|
35 authorization.
|
Chris@26
|
36 */
|
Chris@26
|
37
|
Chris@26
|
38 #include <Python.h>
|
Chris@26
|
39 #include "PyRealTime.h"
|
Chris@26
|
40 #include "vamp-sdk/Plugin.h"
|
Chris@26
|
41 #include <string>
|
Chris@26
|
42
|
Chris@26
|
43 using namespace std;
|
Chris@26
|
44 using namespace Vamp;
|
Chris@26
|
45 using Vamp::Plugin;
|
Chris@26
|
46 using Vamp::RealTime;
|
Chris@26
|
47
|
Chris@26
|
48 /* CONSTRUCTOR: New RealTime object from sec and nsec */
|
Chris@26
|
49 static PyObject*
|
Chris@26
|
50 RealTime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
|
Chris@26
|
51 {
|
Chris@26
|
52 unsigned int sec = 0;
|
Chris@26
|
53 unsigned int nsec = 0;
|
Chris@26
|
54 double unary = 0;
|
Chris@26
|
55 const char *fmt = NULL;
|
Chris@26
|
56
|
Chris@26
|
57 if (
|
Chris@26
|
58 /// new RealTime from ('format',float) e.g. ('seconds',2.34123)
|
Chris@26
|
59 !PyArg_ParseTuple(args, "|sd:RealTime.new ",
|
Chris@26
|
60 (const char *) &fmt,
|
Chris@26
|
61 (double *) &unary) &&
|
Chris@26
|
62
|
Chris@26
|
63 /// new RealTime from (sec{int},nsec{int}) e.g. (2,34)
|
Chris@26
|
64 !PyArg_ParseTuple(args, "|II:RealTime.new ",
|
Chris@26
|
65 (unsigned int*) &sec,
|
Chris@26
|
66 (unsigned int*) &nsec)
|
Chris@26
|
67
|
Chris@26
|
68 ) {
|
Chris@26
|
69 PyErr_SetString(PyExc_TypeError,
|
Chris@26
|
70 "RealTime initialised with wrong arguments.");
|
Chris@26
|
71 return NULL;
|
Chris@26
|
72 }
|
Chris@26
|
73
|
Chris@26
|
74 // PyErr_Clear();
|
Chris@26
|
75
|
Chris@26
|
76 // RealTimeObject *self = PyObject_New(RealTimeObject, &RealTime_Type);
|
Chris@26
|
77 RealTimeObject *self = (RealTimeObject*)type->tp_alloc(type, 0);
|
Chris@26
|
78
|
Chris@26
|
79 if (self == NULL) return NULL;
|
Chris@26
|
80
|
Chris@26
|
81 self->rt = NULL;
|
Chris@26
|
82
|
Chris@26
|
83 if (sec == 0 && nsec == 0 && fmt == 0)
|
Chris@26
|
84 self->rt = new RealTime();
|
Chris@26
|
85 else if (fmt == 0)
|
Chris@26
|
86 self->rt = new RealTime(sec,nsec);
|
Chris@26
|
87 else {
|
Chris@26
|
88 /// new RealTime from seconds or milliseconds: i.e. >>>RealTime('seconds',12.3)
|
Chris@26
|
89 if (!string(fmt).compare("float") ||
|
Chris@26
|
90 !string(fmt).compare("seconds"))
|
Chris@26
|
91 self->rt = new RealTime(
|
Chris@26
|
92 RealTime::fromSeconds((double) unary));
|
Chris@26
|
93
|
Chris@26
|
94 if (!string(fmt).compare("milliseconds")) {
|
Chris@26
|
95 self->rt = new RealTime(
|
Chris@26
|
96 RealTime::fromSeconds((double) unary / 1000.0)); }
|
Chris@26
|
97 }
|
Chris@26
|
98
|
Chris@26
|
99 if (!self->rt) {
|
Chris@26
|
100 PyErr_SetString(PyExc_TypeError,
|
Chris@26
|
101 "RealTime initialised with wrong arguments.");
|
Chris@26
|
102 return NULL;
|
Chris@26
|
103 }
|
Chris@26
|
104
|
Chris@26
|
105 return (PyObject *) self;
|
Chris@26
|
106 }
|
Chris@26
|
107
|
Chris@26
|
108 /* DESTRUCTOR: delete type object */
|
Chris@26
|
109 static void
|
Chris@26
|
110 RealTimeObject_dealloc(RealTimeObject *self)
|
Chris@26
|
111 {
|
Chris@26
|
112 if (self->rt) delete self->rt; //delete the C object
|
Chris@26
|
113 PyObject_Del(self); //delete the Python object (original)
|
Chris@26
|
114 /// this requires PyType_Ready() which fills ob_type
|
Chris@26
|
115 // self->ob_type->tp_free((PyObject*)self);
|
Chris@26
|
116 }
|
Chris@26
|
117
|
Chris@26
|
118 /* RealTime Object's Methods */
|
Chris@26
|
119 //these are internals not exposed by the module but the object
|
Chris@26
|
120
|
Chris@26
|
121 /* Returns a Tuple containing sec and nsec values */
|
Chris@26
|
122 static PyObject *
|
Chris@26
|
123 RealTime_values(RealTimeObject *self)
|
Chris@26
|
124 {
|
Chris@26
|
125 return Py_BuildValue("(ii)",self->rt->sec,self->rt->nsec);
|
Chris@26
|
126 }
|
Chris@26
|
127
|
Chris@26
|
128 /* Returns a Text representation */
|
Chris@26
|
129 static PyObject *
|
Chris@26
|
130 RealTime_toString(RealTimeObject *self, PyObject *args)
|
Chris@26
|
131 {
|
Chris@26
|
132 return Py_BuildValue("s",self->rt->toText().c_str());
|
Chris@26
|
133 }
|
Chris@26
|
134
|
Chris@26
|
135 /* Frame representation */
|
Chris@26
|
136 static PyObject *
|
Chris@26
|
137 RealTime_toFrame(PyObject *self, PyObject *args)
|
Chris@26
|
138 {
|
Chris@26
|
139 unsigned int samplerate;
|
Chris@26
|
140
|
Chris@26
|
141 if ( !PyArg_ParseTuple(args, "I:realtime.toFrame object ",
|
Chris@26
|
142 (unsigned int *) &samplerate )) {
|
Chris@26
|
143 PyErr_SetString(PyExc_ValueError,"Integer Sample Rate Required.");
|
Chris@26
|
144 return NULL;
|
Chris@26
|
145 }
|
Chris@26
|
146
|
Chris@26
|
147 return Py_BuildValue("k",
|
Chris@26
|
148 RealTime::realTime2Frame(
|
Chris@26
|
149 *(const RealTime*) ((RealTimeObject*)self)->rt,
|
Chris@26
|
150 (unsigned int) samplerate));
|
Chris@26
|
151 }
|
Chris@26
|
152
|
Chris@26
|
153 /* Conversion of realtime to a double precision floating point value */
|
Chris@26
|
154 /* ...in Python called by e.g. float(realtime) */
|
Chris@26
|
155 static PyObject *
|
Chris@26
|
156 RealTime_float(PyObject *s)
|
Chris@26
|
157 {
|
Chris@26
|
158 double drt = ((double) ((RealTimeObject*)s)->rt->sec +
|
Chris@26
|
159 (double)((double) ((RealTimeObject*)s)->rt->nsec)/1000000000);
|
Chris@26
|
160 return PyFloat_FromDouble(drt);
|
Chris@26
|
161 }
|
Chris@26
|
162
|
Chris@26
|
163
|
Chris@26
|
164 /* Type object's (RealTime) methods table */
|
Chris@26
|
165 static PyMethodDef RealTime_methods[] =
|
Chris@26
|
166 {
|
Chris@26
|
167 {"values", (PyCFunction)RealTime_values, METH_NOARGS,
|
Chris@26
|
168 PyDoc_STR("values() -> Tuple of sec,nsec representation.")},
|
Chris@26
|
169
|
Chris@26
|
170 {"toString", (PyCFunction)RealTime_toString, METH_NOARGS,
|
Chris@26
|
171 PyDoc_STR("toString() -> Return a user-readable string to the nearest millisecond in a form like HH:MM:SS.mmm")},
|
Chris@26
|
172
|
Chris@26
|
173 {"toFrame", (PyCFunction)RealTime_toFrame, METH_VARARGS,
|
Chris@26
|
174 PyDoc_STR("toFrame(samplerate) -> Sample count for given sample rate.")},
|
Chris@26
|
175
|
Chris@26
|
176 {"toFloat", (PyCFunction)RealTime_float, METH_NOARGS,
|
Chris@26
|
177 PyDoc_STR("toFloat() -> Floating point representation.")},
|
Chris@26
|
178
|
Chris@26
|
179 {NULL, NULL} /* sentinel */
|
Chris@26
|
180 };
|
Chris@26
|
181
|
Chris@26
|
182
|
Chris@26
|
183 /* Methods implementing protocols */
|
Chris@26
|
184 // these functions are called by the interpreter
|
Chris@26
|
185
|
Chris@26
|
186 /* Object Protocol */
|
Chris@26
|
187
|
Chris@26
|
188 static int
|
Chris@26
|
189 RealTime_setattr(RealTimeObject *self, char *name, PyObject *value)
|
Chris@26
|
190 {
|
Chris@26
|
191
|
Chris@26
|
192 if ( !string(name).compare("sec")) {
|
Chris@26
|
193 self->rt->sec= (int) PyInt_AS_LONG(value);
|
Chris@26
|
194 return 0;
|
Chris@26
|
195 }
|
Chris@26
|
196
|
Chris@26
|
197 if ( !string(name).compare("nsec")) {
|
Chris@26
|
198 self->rt->nsec= (int) PyInt_AS_LONG(value);
|
Chris@26
|
199 return 0;
|
Chris@26
|
200 }
|
Chris@26
|
201
|
Chris@26
|
202 return -1;
|
Chris@26
|
203 }
|
Chris@26
|
204
|
Chris@26
|
205 static PyObject *
|
Chris@26
|
206 RealTime_getattr(RealTimeObject *self, char *name)
|
Chris@26
|
207 {
|
Chris@26
|
208
|
Chris@26
|
209 if ( !string(name).compare("sec") ) {
|
Chris@26
|
210 return PyInt_FromSsize_t(
|
Chris@26
|
211 (Py_ssize_t) self->rt->sec);
|
Chris@26
|
212 }
|
Chris@26
|
213
|
Chris@26
|
214 if ( !string(name).compare("nsec") ) {
|
Chris@26
|
215 return PyInt_FromSsize_t(
|
Chris@26
|
216 (Py_ssize_t) self->rt->nsec);
|
Chris@26
|
217 }
|
Chris@26
|
218
|
Chris@26
|
219 return Py_FindMethod(RealTime_methods,
|
Chris@26
|
220 (PyObject *)self, name);
|
Chris@26
|
221 }
|
Chris@26
|
222
|
Chris@26
|
223 /* String representation called by e.g. str(realtime), print realtime*/
|
Chris@26
|
224 static PyObject *
|
Chris@26
|
225 RealTime_repr(PyObject *self)
|
Chris@26
|
226 {
|
Chris@26
|
227 return Py_BuildValue("s",
|
Chris@26
|
228 ((RealTimeObject*)self)->rt->toString().c_str());
|
Chris@26
|
229 }
|
Chris@26
|
230
|
Chris@26
|
231
|
Chris@26
|
232 /* Number Protocol */
|
Chris@26
|
233 /// TODO: implement all methods available in Vamp::RealTime() objects
|
Chris@26
|
234
|
Chris@26
|
235 static PyObject *
|
Chris@26
|
236 RealTime_add(PyObject *s, PyObject *w)
|
Chris@26
|
237 {
|
Chris@26
|
238 RealTimeObject *result =
|
Chris@26
|
239 PyObject_New(RealTimeObject, &RealTime_Type);
|
Chris@26
|
240 if (result == NULL) return NULL;
|
Chris@26
|
241
|
Chris@26
|
242 result->rt = new RealTime(
|
Chris@26
|
243 *((RealTimeObject*)s)->rt + *((RealTimeObject*)w)->rt);
|
Chris@26
|
244 return (PyObject*)result;
|
Chris@26
|
245 }
|
Chris@26
|
246
|
Chris@26
|
247 static PyObject *
|
Chris@26
|
248 RealTime_subtract(PyObject *s, PyObject *w)
|
Chris@26
|
249 {
|
Chris@26
|
250 RealTimeObject *result =
|
Chris@26
|
251 PyObject_New(RealTimeObject, &RealTime_Type);
|
Chris@26
|
252 if (result == NULL) return NULL;
|
Chris@26
|
253
|
Chris@26
|
254 result->rt = new RealTime(
|
Chris@26
|
255 *((RealTimeObject*)s)->rt - *((RealTimeObject*)w)->rt);
|
Chris@26
|
256 return (PyObject*)result;
|
Chris@26
|
257 }
|
Chris@26
|
258
|
Chris@26
|
259 static PyNumberMethods realtime_as_number =
|
Chris@26
|
260 {
|
Chris@26
|
261 RealTime_add, /*nb_add*/
|
Chris@26
|
262 RealTime_subtract, /*nb_subtract*/
|
Chris@26
|
263 0, /*nb_multiply*/
|
Chris@26
|
264 0, /*nb_divide*/
|
Chris@26
|
265 0, /*nb_remainder*/
|
Chris@26
|
266 0, /*nb_divmod*/
|
Chris@26
|
267 0, /*nb_power*/
|
Chris@26
|
268 0, /*nb_neg*/
|
Chris@26
|
269 0, /*nb_pos*/
|
Chris@26
|
270 0, /*(unaryfunc)array_abs,*/
|
Chris@26
|
271 0, /*nb_nonzero*/
|
Chris@26
|
272 0, /*nb_invert*/
|
Chris@26
|
273 0, /*nb_lshift*/
|
Chris@26
|
274 0, /*nb_rshift*/
|
Chris@26
|
275 0, /*nb_and*/
|
Chris@26
|
276 0, /*nb_xor*/
|
Chris@26
|
277 0, /*nb_or*/
|
Chris@26
|
278 0, /*nb_coerce*/
|
Chris@26
|
279 0, /*nb_int*/
|
Chris@26
|
280 0, /*nb_long*/
|
Chris@26
|
281 (unaryfunc)RealTime_float,/*nb_float*/
|
Chris@26
|
282 0, /*nb_oct*/
|
Chris@26
|
283 0, /*nb_hex*/
|
Chris@26
|
284 };
|
Chris@26
|
285
|
Chris@26
|
286 /* REAL-TIME TYPE OBJECT */
|
Chris@26
|
287
|
Chris@26
|
288 #define RealTime_alloc PyType_GenericAlloc
|
Chris@26
|
289 #define RealTime_free PyObject_Del
|
Chris@26
|
290
|
Chris@26
|
291 /* Doc:: 10.3 Type Objects */ /* static */
|
Chris@26
|
292 PyTypeObject RealTime_Type =
|
Chris@26
|
293 {
|
Chris@26
|
294 PyObject_HEAD_INIT(NULL)
|
Chris@26
|
295 0, /*ob_size*/
|
Chris@26
|
296 "vampy.RealTime", /*tp_name*/
|
Chris@26
|
297 sizeof(RealTimeObject), /*tp_basicsize*/
|
Chris@26
|
298 0,//sizeof(RealTime), /*tp_itemsize*/
|
Chris@26
|
299 /* methods */
|
Chris@26
|
300 (destructor)RealTimeObject_dealloc, /*tp_dealloc*/
|
Chris@26
|
301 0, /*tp_print*/
|
Chris@26
|
302 (getattrfunc)RealTime_getattr, /*tp_getattr*/
|
Chris@26
|
303 (setattrfunc)RealTime_setattr, /*tp_setattr*/
|
Chris@26
|
304 0, /*tp_compare*/
|
Chris@26
|
305 RealTime_repr, /*tp_repr*/
|
Chris@26
|
306 &realtime_as_number, /*tp_as_number*/
|
Chris@26
|
307 0, /*tp_as_sequence*/
|
Chris@26
|
308 0, /*tp_as_mapping*/
|
Chris@26
|
309 0, /*tp_hash*/
|
Chris@26
|
310 0,//(ternaryfunc)RealTime_new, /*tp_call*/
|
Chris@26
|
311 0, /*tp_str*/
|
Chris@26
|
312 0, /*tp_getattro*/
|
Chris@26
|
313 0, /*tp_setattro*/
|
Chris@26
|
314 0, /*tp_as_buffer*/
|
Chris@26
|
315 Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
Chris@26
|
316 "RealTime Object", /*tp_doc*/
|
Chris@26
|
317 0, /*tp_traverse*/
|
Chris@26
|
318 0, /*tp_clear*/
|
Chris@26
|
319 0, /*tp_richcompare*/
|
Chris@26
|
320 0, /*tp_weaklistoffset*/
|
Chris@26
|
321 0, /*tp_iter*/
|
Chris@26
|
322 0, /*tp_iternext*/
|
Chris@26
|
323 RealTime_methods, /*tp_methods*/ //TypeObject Methods
|
Chris@26
|
324 0, /*tp_members*/
|
Chris@26
|
325 0, /*tp_getset*/
|
Chris@26
|
326 0, /*tp_base*/
|
Chris@26
|
327 0, /*tp_dict*/
|
Chris@26
|
328 0, /*tp_descr_get*/
|
Chris@26
|
329 0, /*tp_descr_set*/
|
Chris@26
|
330 0, /*tp_dictoffset*/
|
Chris@26
|
331 0, /*tp_init*/
|
Chris@26
|
332 RealTime_alloc, /*tp_alloc*/
|
Chris@26
|
333 RealTime_new, /*tp_new*/
|
Chris@26
|
334 RealTime_free, /*tp_free*/
|
Chris@26
|
335 0, /*tp_is_gc*/
|
Chris@26
|
336 };
|
Chris@26
|
337
|
Chris@26
|
338
|
Chris@26
|
339
|
Chris@26
|
340 /* PyRealTime C++ API */
|
Chris@26
|
341
|
Chris@26
|
342 /*PyRealTime from RealTime*/
|
Chris@26
|
343 PyObject*
|
Chris@26
|
344 PyRealTime_FromRealTime(const Vamp::RealTime& rt) {
|
Chris@26
|
345
|
Chris@26
|
346 RealTimeObject *self =
|
Chris@26
|
347 PyObject_New(RealTimeObject, &RealTime_Type);
|
Chris@26
|
348 if (self == NULL) return NULL;
|
Chris@26
|
349
|
Chris@26
|
350 self->rt = new RealTime(rt);
|
Chris@26
|
351 return (PyObject*) self;
|
Chris@26
|
352 }
|
Chris@26
|
353
|
Chris@26
|
354 /*RealTime* from PyRealTime*/
|
Chris@26
|
355 const Vamp::RealTime*
|
Chris@26
|
356 PyRealTime_AsRealTime (PyObject *self) {
|
Chris@26
|
357
|
Chris@26
|
358 RealTimeObject *s = (RealTimeObject*) self;
|
Chris@26
|
359
|
Chris@26
|
360 if (!PyRealTime_Check(s)) {
|
Chris@26
|
361 PyErr_SetString(PyExc_TypeError, "RealTime Object Expected.");
|
Chris@26
|
362 cerr << "in call PyRealTime_AsPointer(): RealTime Object Expected. " << endl;
|
Chris@26
|
363 return NULL; }
|
Chris@26
|
364 return s->rt;
|
Chris@26
|
365 };
|
Chris@26
|
366
|