fazekasgy@37
|
1 /*
|
fazekasgy@37
|
2
|
fazekasgy@37
|
3 * Vampy : This plugin is a wrapper around the Vamp plugin API.
|
fazekasgy@37
|
4 * It allows for writing Vamp plugins in Python.
|
fazekasgy@37
|
5
|
fazekasgy@37
|
6 * Centre for Digital Music, Queen Mary University of London.
|
fazekasgy@37
|
7 * Copyright (C) 2008-2009 Gyorgy Fazekas, QMUL. (See Vamp sources
|
fazekasgy@37
|
8 * for licence information.)
|
fazekasgy@37
|
9
|
fazekasgy@37
|
10 */
|
fazekasgy@37
|
11
|
fazekasgy@37
|
12 #include <Python.h>
|
fazekasgy@37
|
13 #include "PyRealTime.h"
|
fazekasgy@37
|
14 #include "vamp-sdk/Plugin.h"
|
fazekasgy@37
|
15 #include <string>
|
fazekasgy@37
|
16
|
fazekasgy@37
|
17 using namespace std;
|
fazekasgy@37
|
18 using namespace Vamp;
|
fazekasgy@37
|
19 using Vamp::Plugin;
|
fazekasgy@37
|
20 using Vamp::RealTime;
|
fazekasgy@37
|
21
|
fazekasgy@37
|
22
|
fazekasgy@37
|
23 /* CONSTRUCTOR: New RealTime object from sec and nsec */
|
fazekasgy@37
|
24 static PyObject*
|
fazekasgy@37
|
25 RealTime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
|
fazekasgy@37
|
26 {
|
fazekasgy@37
|
27 unsigned int sec = 0;
|
fazekasgy@37
|
28 unsigned int nsec = 0;
|
fazekasgy@37
|
29 double unary = 0;
|
fazekasgy@37
|
30 const char *fmt = NULL;
|
fazekasgy@37
|
31
|
fazekasgy@37
|
32 if (
|
fazekasgy@37
|
33 /// new RealTime from ('format',float) e.g. ('seconds',2.34123)
|
fazekasgy@37
|
34 !PyArg_ParseTuple(args, "|sd:RealTime.new ",
|
fazekasgy@37
|
35 (const char *) &fmt,
|
fazekasgy@37
|
36 (double *) &unary) &&
|
fazekasgy@37
|
37
|
fazekasgy@37
|
38 /// new RealTime from (sec{int},nsec{int}) e.g. (2,34)
|
fazekasgy@37
|
39 !PyArg_ParseTuple(args, "|II:RealTime.new ",
|
fazekasgy@37
|
40 (unsigned int*) &sec,
|
fazekasgy@37
|
41 (unsigned int*) &nsec)
|
fazekasgy@37
|
42
|
fazekasgy@37
|
43 ) {
|
fazekasgy@37
|
44 PyErr_SetString(PyExc_TypeError,
|
fazekasgy@37
|
45 "RealTime initialised with wrong arguments.");
|
fazekasgy@37
|
46 return NULL;
|
fazekasgy@37
|
47 }
|
fazekasgy@37
|
48
|
fazekasgy@37
|
49 // PyErr_Clear();
|
fazekasgy@37
|
50
|
fazekasgy@37
|
51 // RealTimeObject *self = PyObject_New(RealTimeObject, &RealTime_Type);
|
fazekasgy@37
|
52 RealTimeObject *self = (RealTimeObject*)type->tp_alloc(type, 0);
|
fazekasgy@37
|
53
|
fazekasgy@37
|
54 if (self == NULL) return NULL;
|
fazekasgy@37
|
55
|
fazekasgy@37
|
56 self->rt = NULL;
|
fazekasgy@37
|
57
|
fazekasgy@37
|
58 if (sec == 0 && nsec == 0 && fmt == 0)
|
fazekasgy@37
|
59 self->rt = new RealTime();
|
fazekasgy@37
|
60 else if (fmt == 0)
|
fazekasgy@37
|
61 self->rt = new RealTime(sec,nsec);
|
fazekasgy@37
|
62 else {
|
fazekasgy@37
|
63 /// new RealTime from seconds or milliseconds: i.e. >>>RealTime('seconds',12.3)
|
fazekasgy@37
|
64 if (!string(fmt).compare("float") ||
|
fazekasgy@37
|
65 !string(fmt).compare("seconds"))
|
fazekasgy@37
|
66 self->rt = new RealTime(
|
fazekasgy@37
|
67 RealTime::fromSeconds((double) unary));
|
fazekasgy@37
|
68
|
fazekasgy@37
|
69 if (!string(fmt).compare("milliseconds")) {
|
fazekasgy@37
|
70 self->rt = new RealTime(
|
fazekasgy@37
|
71 RealTime::fromSeconds((double) unary / 1000.0)); }
|
fazekasgy@37
|
72 }
|
fazekasgy@37
|
73
|
fazekasgy@37
|
74 if (!self->rt) {
|
fazekasgy@37
|
75 PyErr_SetString(PyExc_TypeError,
|
fazekasgy@37
|
76 "RealTime initialised with wrong arguments.");
|
fazekasgy@37
|
77 return NULL;
|
fazekasgy@37
|
78 }
|
fazekasgy@37
|
79
|
fazekasgy@37
|
80 return (PyObject *) self;
|
fazekasgy@37
|
81 }
|
fazekasgy@37
|
82
|
fazekasgy@37
|
83 /* DESTRUCTOR: delete type object */
|
fazekasgy@37
|
84 static void
|
fazekasgy@37
|
85 RealTimeObject_dealloc(RealTimeObject *self)
|
fazekasgy@37
|
86 {
|
fazekasgy@37
|
87 if (self->rt) delete self->rt; //delete the C object
|
fazekasgy@37
|
88 PyObject_Del(self); //delete the Python object (original)
|
fazekasgy@37
|
89 /// this requires PyType_Ready() which fills ob_type
|
fazekasgy@37
|
90 // self->ob_type->tp_free((PyObject*)self);
|
fazekasgy@37
|
91 }
|
fazekasgy@37
|
92
|
fazekasgy@37
|
93 /* RealTime Object's Methods */
|
fazekasgy@37
|
94 //these are internals not exposed by the module but the object
|
fazekasgy@37
|
95
|
fazekasgy@37
|
96 /* Returns a Tuple containing sec and nsec values */
|
fazekasgy@37
|
97 static PyObject *
|
fazekasgy@37
|
98 RealTime_values(RealTimeObject *self)
|
fazekasgy@37
|
99 {
|
fazekasgy@37
|
100 return Py_BuildValue("(ii)",self->rt->sec,self->rt->nsec);
|
fazekasgy@37
|
101 }
|
fazekasgy@37
|
102
|
fazekasgy@37
|
103 /* Returns a Text representation */
|
fazekasgy@37
|
104 static PyObject *
|
fazekasgy@37
|
105 RealTime_toString(RealTimeObject *self, PyObject *args)
|
fazekasgy@37
|
106 {
|
fazekasgy@37
|
107 return Py_BuildValue("s",self->rt->toText().c_str());
|
fazekasgy@37
|
108 }
|
fazekasgy@37
|
109
|
fazekasgy@37
|
110 /* Frame representation */
|
fazekasgy@37
|
111 static PyObject *
|
fazekasgy@37
|
112 RealTime_toFrame(PyObject *self, PyObject *args)
|
fazekasgy@37
|
113 {
|
fazekasgy@37
|
114 unsigned int samplerate;
|
fazekasgy@37
|
115
|
fazekasgy@37
|
116 if ( !PyArg_ParseTuple(args, "I:realtime.toFrame object ",
|
fazekasgy@37
|
117 (unsigned int *) &samplerate )) {
|
fazekasgy@37
|
118 PyErr_SetString(PyExc_ValueError,"Integer Sample Rate Required.");
|
fazekasgy@37
|
119 return NULL;
|
fazekasgy@37
|
120 }
|
fazekasgy@37
|
121
|
fazekasgy@37
|
122 return Py_BuildValue("k",
|
fazekasgy@37
|
123 RealTime::realTime2Frame(
|
fazekasgy@37
|
124 *(const RealTime*) ((RealTimeObject*)self)->rt,
|
fazekasgy@37
|
125 (unsigned int) samplerate));
|
fazekasgy@37
|
126 }
|
fazekasgy@37
|
127
|
fazekasgy@37
|
128 /* Conversion of realtime to a double precision floating point value */
|
fazekasgy@37
|
129 /* ...in Python called by e.g. float(realtime) */
|
fazekasgy@37
|
130 static PyObject *
|
fazekasgy@37
|
131 RealTime_float(PyObject *s)
|
fazekasgy@37
|
132 {
|
fazekasgy@37
|
133 double drt = ((double) ((RealTimeObject*)s)->rt->sec +
|
fazekasgy@37
|
134 (double)((double) ((RealTimeObject*)s)->rt->nsec)/1000000000);
|
fazekasgy@37
|
135 return PyFloat_FromDouble(drt);
|
fazekasgy@37
|
136 }
|
fazekasgy@37
|
137
|
fazekasgy@37
|
138
|
fazekasgy@37
|
139 /* Type object's (RealTime) methods table */
|
fazekasgy@37
|
140 static PyMethodDef RealTime_methods[] =
|
fazekasgy@37
|
141 {
|
fazekasgy@37
|
142 {"values", (PyCFunction)RealTime_values, METH_NOARGS,
|
fazekasgy@37
|
143 PyDoc_STR("values() -> Tuple of sec,nsec representation.")},
|
fazekasgy@37
|
144
|
fazekasgy@37
|
145 {"toString", (PyCFunction)RealTime_toString, METH_NOARGS,
|
fazekasgy@37
|
146 PyDoc_STR("toString() -> Return a user-readable string to the nearest millisecond in a form like HH:MM:SS.mmm")},
|
fazekasgy@37
|
147
|
fazekasgy@37
|
148 {"toFrame", (PyCFunction)RealTime_toFrame, METH_VARARGS,
|
fazekasgy@37
|
149 PyDoc_STR("toFrame(samplerate) -> Sample count for given sample rate.")},
|
fazekasgy@37
|
150
|
fazekasgy@37
|
151 {"toFloat", (PyCFunction)RealTime_float, METH_NOARGS,
|
fazekasgy@37
|
152 PyDoc_STR("toFloat() -> Floating point representation.")},
|
fazekasgy@37
|
153
|
fazekasgy@37
|
154 {NULL, NULL} /* sentinel */
|
fazekasgy@37
|
155 };
|
fazekasgy@37
|
156
|
fazekasgy@37
|
157
|
fazekasgy@37
|
158 /* Methods implementing protocols */
|
fazekasgy@37
|
159 // these functions are called by the interpreter
|
fazekasgy@37
|
160
|
fazekasgy@37
|
161 /* Object Protocol */
|
fazekasgy@37
|
162
|
fazekasgy@37
|
163 static int
|
fazekasgy@37
|
164 RealTime_setattr(RealTimeObject *self, char *name, PyObject *value)
|
fazekasgy@37
|
165 {
|
fazekasgy@37
|
166
|
fazekasgy@37
|
167 if ( !string(name).compare("sec")) {
|
fazekasgy@37
|
168 self->rt->sec= (int) PyInt_AS_LONG(value);
|
fazekasgy@37
|
169 return 0;
|
fazekasgy@37
|
170 }
|
fazekasgy@37
|
171
|
fazekasgy@37
|
172 if ( !string(name).compare("nsec")) {
|
fazekasgy@37
|
173 self->rt->nsec= (int) PyInt_AS_LONG(value);
|
fazekasgy@37
|
174 return 0;
|
fazekasgy@37
|
175 }
|
fazekasgy@37
|
176
|
fazekasgy@37
|
177 return -1;
|
fazekasgy@37
|
178 }
|
fazekasgy@37
|
179
|
fazekasgy@37
|
180 static PyObject *
|
fazekasgy@37
|
181 RealTime_getattr(RealTimeObject *self, char *name)
|
fazekasgy@37
|
182 {
|
fazekasgy@37
|
183
|
fazekasgy@37
|
184 if ( !string(name).compare("sec") ) {
|
fazekasgy@37
|
185 return PyInt_FromSsize_t(
|
fazekasgy@37
|
186 (Py_ssize_t) self->rt->sec);
|
fazekasgy@37
|
187 }
|
fazekasgy@37
|
188
|
fazekasgy@37
|
189 if ( !string(name).compare("nsec") ) {
|
fazekasgy@37
|
190 return PyInt_FromSsize_t(
|
fazekasgy@37
|
191 (Py_ssize_t) self->rt->nsec);
|
fazekasgy@37
|
192 }
|
fazekasgy@37
|
193
|
fazekasgy@37
|
194 return Py_FindMethod(RealTime_methods,
|
fazekasgy@37
|
195 (PyObject *)self, name);
|
fazekasgy@37
|
196 }
|
fazekasgy@37
|
197
|
fazekasgy@37
|
198 /* String representation called by e.g. str(realtime), print realtime*/
|
fazekasgy@37
|
199 static PyObject *
|
fazekasgy@37
|
200 RealTime_repr(PyObject *self)
|
fazekasgy@37
|
201 {
|
fazekasgy@37
|
202 return Py_BuildValue("s",
|
fazekasgy@37
|
203 ((RealTimeObject*)self)->rt->toString().c_str());
|
fazekasgy@37
|
204 }
|
fazekasgy@37
|
205
|
fazekasgy@37
|
206
|
fazekasgy@37
|
207 /* Number Protocol */
|
fazekasgy@37
|
208 /// Only add and substract make sense, or what about the
|
fazekasgy@37
|
209 /// square root of Monday morning?
|
fazekasgy@37
|
210 /// Divide by integer maybe for durations?
|
fazekasgy@37
|
211
|
fazekasgy@37
|
212 static PyObject *
|
fazekasgy@37
|
213 RealTime_add(PyObject *s, PyObject *w)
|
fazekasgy@37
|
214 {
|
fazekasgy@37
|
215 RealTimeObject *result =
|
fazekasgy@37
|
216 PyObject_New(RealTimeObject, &RealTime_Type);
|
fazekasgy@37
|
217 if (result == NULL) return NULL;
|
fazekasgy@37
|
218
|
fazekasgy@37
|
219 result->rt = new RealTime(
|
fazekasgy@37
|
220 *((RealTimeObject*)s)->rt + *((RealTimeObject*)w)->rt);
|
fazekasgy@37
|
221 return (PyObject*)result;
|
fazekasgy@37
|
222 }
|
fazekasgy@37
|
223
|
fazekasgy@37
|
224 static PyObject *
|
fazekasgy@37
|
225 RealTime_subtract(PyObject *s, PyObject *w)
|
fazekasgy@37
|
226 {
|
fazekasgy@37
|
227 RealTimeObject *result =
|
fazekasgy@37
|
228 PyObject_New(RealTimeObject, &RealTime_Type);
|
fazekasgy@37
|
229 if (result == NULL) return NULL;
|
fazekasgy@37
|
230
|
fazekasgy@37
|
231 result->rt = new RealTime(
|
fazekasgy@37
|
232 *((RealTimeObject*)s)->rt - *((RealTimeObject*)w)->rt);
|
fazekasgy@37
|
233 return (PyObject*)result;
|
fazekasgy@37
|
234 }
|
fazekasgy@37
|
235
|
fazekasgy@37
|
236 static PyNumberMethods realtime_as_number =
|
fazekasgy@37
|
237 {
|
fazekasgy@37
|
238 RealTime_add, /*nb_add*/
|
fazekasgy@37
|
239 RealTime_subtract, /*nb_subtract*/
|
fazekasgy@37
|
240 0, /*nb_multiply*/
|
fazekasgy@37
|
241 0, /*nb_divide*/
|
fazekasgy@37
|
242 0, /*nb_remainder*/
|
fazekasgy@37
|
243 0, /*nb_divmod*/
|
fazekasgy@37
|
244 0, /*nb_power*/
|
fazekasgy@37
|
245 0, /*nb_neg*/
|
fazekasgy@37
|
246 0, /*nb_pos*/
|
fazekasgy@37
|
247 0, /*(unaryfunc)array_abs,*/
|
fazekasgy@37
|
248 0, /*nb_nonzero*/
|
fazekasgy@37
|
249 0, /*nb_invert*/
|
fazekasgy@37
|
250 0, /*nb_lshift*/
|
fazekasgy@37
|
251 0, /*nb_rshift*/
|
fazekasgy@37
|
252 0, /*nb_and*/
|
fazekasgy@37
|
253 0, /*nb_xor*/
|
fazekasgy@37
|
254 0, /*nb_or*/
|
fazekasgy@37
|
255 0, /*nb_coerce*/
|
fazekasgy@37
|
256 0, /*nb_int*/
|
fazekasgy@37
|
257 0, /*nb_long*/
|
fazekasgy@37
|
258 (unaryfunc)RealTime_float,/*nb_float*/
|
fazekasgy@37
|
259 0, /*nb_oct*/
|
fazekasgy@37
|
260 0, /*nb_hex*/
|
fazekasgy@37
|
261 };
|
fazekasgy@37
|
262
|
fazekasgy@37
|
263 /* REAL-TIME TYPE OBJECT */
|
fazekasgy@37
|
264
|
fazekasgy@37
|
265 #define RealTime_alloc PyType_GenericAlloc
|
fazekasgy@37
|
266 #define RealTime_free PyObject_Del
|
fazekasgy@37
|
267
|
fazekasgy@37
|
268 /* Doc:: 10.3 Type Objects */ /* static */
|
fazekasgy@37
|
269 PyTypeObject RealTime_Type =
|
fazekasgy@37
|
270 {
|
fazekasgy@37
|
271 PyObject_HEAD_INIT(NULL)
|
fazekasgy@37
|
272 0, /*ob_size*/
|
fazekasgy@37
|
273 "vampy.RealTime", /*tp_name*/
|
fazekasgy@37
|
274 sizeof(RealTimeObject), /*tp_basicsize*/
|
fazekasgy@37
|
275 0,//sizeof(RealTime), /*tp_itemsize*/
|
fazekasgy@37
|
276 /* methods */
|
fazekasgy@37
|
277 (destructor)RealTimeObject_dealloc, /*tp_dealloc*/
|
fazekasgy@37
|
278 0, /*tp_print*/
|
fazekasgy@37
|
279 (getattrfunc)RealTime_getattr, /*tp_getattr*/
|
fazekasgy@37
|
280 (setattrfunc)RealTime_setattr, /*tp_setattr*/
|
fazekasgy@37
|
281 0, /*tp_compare*/
|
fazekasgy@37
|
282 RealTime_repr, /*tp_repr*/
|
fazekasgy@37
|
283 &realtime_as_number, /*tp_as_number*/
|
fazekasgy@37
|
284 0, /*tp_as_sequence*/
|
fazekasgy@37
|
285 0, /*tp_as_mapping*/
|
fazekasgy@37
|
286 0, /*tp_hash*/
|
fazekasgy@37
|
287 0,//(ternaryfunc)RealTime_new, /*tp_call*/
|
fazekasgy@37
|
288 0, /*tp_str*/
|
fazekasgy@37
|
289 0, /*tp_getattro*/
|
fazekasgy@37
|
290 0, /*tp_setattro*/
|
fazekasgy@37
|
291 0, /*tp_as_buffer*/
|
fazekasgy@37
|
292 Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
fazekasgy@37
|
293 "RealTime Object", /*tp_doc*/
|
fazekasgy@37
|
294 0, /*tp_traverse*/
|
fazekasgy@37
|
295 0, /*tp_clear*/
|
fazekasgy@37
|
296 0, /*tp_richcompare*/
|
fazekasgy@37
|
297 0, /*tp_weaklistoffset*/
|
fazekasgy@37
|
298 0, /*tp_iter*/
|
fazekasgy@37
|
299 0, /*tp_iternext*/
|
fazekasgy@37
|
300 RealTime_methods, /*tp_methods*/ //TypeObject Methods
|
fazekasgy@37
|
301 0, /*tp_members*/
|
fazekasgy@37
|
302 0, /*tp_getset*/
|
fazekasgy@37
|
303 0, /*tp_base*/
|
fazekasgy@37
|
304 0, /*tp_dict*/
|
fazekasgy@37
|
305 0, /*tp_descr_get*/
|
fazekasgy@37
|
306 0, /*tp_descr_set*/
|
fazekasgy@37
|
307 0, /*tp_dictoffset*/
|
fazekasgy@37
|
308 0, /*tp_init*/
|
fazekasgy@37
|
309 RealTime_alloc, /*tp_alloc*/
|
fazekasgy@37
|
310 RealTime_new, /*tp_new*/
|
fazekasgy@37
|
311 RealTime_free, /*tp_free*/
|
fazekasgy@37
|
312 0, /*tp_is_gc*/
|
fazekasgy@37
|
313 };
|
fazekasgy@37
|
314
|
fazekasgy@37
|
315
|
fazekasgy@37
|
316
|
fazekasgy@37
|
317 /* PyRealTime C++ API */
|
fazekasgy@37
|
318
|
fazekasgy@37
|
319 /*PyRealTime from RealTime pointer
|
fazekasgy@37
|
320 PyObject*
|
fazekasgy@37
|
321 PyRealTime_FromRealTime(Vamp::RealTime *rt) {
|
fazekasgy@37
|
322
|
fazekasgy@37
|
323 RealTimeObject *self =
|
fazekasgy@37
|
324 PyObject_New(RealTimeObject, &RealTime_Type);
|
fazekasgy@37
|
325 if (self == NULL) return NULL;
|
fazekasgy@37
|
326
|
fazekasgy@37
|
327 self->rt = new RealTime(*rt);
|
fazekasgy@37
|
328 return (PyObject*) self;
|
fazekasgy@37
|
329 }*/
|
fazekasgy@37
|
330
|
fazekasgy@37
|
331
|
fazekasgy@37
|
332 /*PyRealTime from RealTime*/
|
fazekasgy@37
|
333 PyObject*
|
fazekasgy@37
|
334 PyRealTime_FromRealTime(Vamp::RealTime& rt) {
|
fazekasgy@37
|
335
|
fazekasgy@37
|
336 RealTimeObject *self =
|
fazekasgy@37
|
337 PyObject_New(RealTimeObject, &RealTime_Type);
|
fazekasgy@37
|
338 if (self == NULL) return NULL;
|
fazekasgy@37
|
339
|
fazekasgy@37
|
340 self->rt = new RealTime(rt);
|
fazekasgy@37
|
341 return (PyObject*) self;
|
fazekasgy@37
|
342 }
|
fazekasgy@37
|
343
|
fazekasgy@37
|
344 /*RealTime* from PyRealTime*/
|
fazekasgy@37
|
345 const Vamp::RealTime*
|
fazekasgy@37
|
346 PyRealTime_AsRealTime (PyObject *self) {
|
fazekasgy@37
|
347
|
fazekasgy@37
|
348 RealTimeObject *s = (RealTimeObject*) self;
|
fazekasgy@37
|
349
|
fazekasgy@37
|
350 if (!PyRealTime_Check(s)) {
|
fazekasgy@37
|
351 PyErr_SetString(PyExc_TypeError, "RealTime Object Expected.");
|
fazekasgy@37
|
352 cerr << "in call PyRealTime_AsPointer(): RealTime Object Expected. " << endl;
|
fazekasgy@37
|
353 return NULL; }
|
fazekasgy@37
|
354 return s->rt;
|
fazekasgy@37
|
355 };
|
fazekasgy@37
|
356
|