Mercurial > hg > vampy
comparison host/pyRealTime.cpp @ 11:4610f2b8477d
added pyRealTime object impl to host
author | fazekasgy |
---|---|
date | Mon, 16 Jun 2008 09:44:48 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
10:8e9fbe4dc94d | 11:4610f2b8477d |
---|---|
1 /* | |
2 | |
3 This module exposes a Type Object wrapping VAMP::RealTime | |
4 together with module level functions to create | |
5 new pyRealTime objects from frame count, samplerate or sec,nsec tuples. | |
6 | |
7 A small API is provided for the C/C++ programmer and relevant | |
8 functions are exposed to Python. | |
9 | |
10 TODO: implement number protocol (i.e. wrap arithmetic operators) | |
11 partly done | |
12 | |
13 */ | |
14 | |
15 #include <Python.h> | |
16 #include <pyRealTime.h> | |
17 #include "vamp-sdk/Plugin.h" | |
18 #include <string> | |
19 | |
20 using namespace std; | |
21 using namespace Vamp; | |
22 | |
23 using Vamp::Plugin; | |
24 using Vamp::RealTime; | |
25 | |
26 /* REAL-TIME TYPE OBJECT */ | |
27 | |
28 | |
29 /* Documentation for our new module */ | |
30 PyDoc_STRVAR(module_doc, | |
31 "This module is a thin wrapper around VAMP::RealTime."); | |
32 | |
33 | |
34 /* RealTime Object's Methods */ | |
35 //Note: these are internals, not exposed by the module but the object | |
36 | |
37 /* Returns a Tuple containing sec and nsec values */ | |
38 static PyObject * | |
39 RealTime_values(RealTimeObject *self) | |
40 { | |
41 return Py_BuildValue("(ii)", | |
42 self->rt->sec,self->rt->nsec); | |
43 } | |
44 | |
45 /* Returns a Text representation */ | |
46 static PyObject * | |
47 RealTime_toText(RealTimeObject *self, PyObject *args) | |
48 { | |
49 return Py_BuildValue("s", | |
50 self->rt->toText().c_str()); | |
51 } | |
52 | |
53 /* String representation called by e.g. str(realtime), print realtime*/ | |
54 static PyObject * | |
55 RealTime_repr(PyObject *self) | |
56 { | |
57 return Py_BuildValue("s", | |
58 ((RealTimeObject*)self)->rt->toString().c_str()); | |
59 } | |
60 | |
61 | |
62 /* Frame representation */ | |
63 static PyObject * | |
64 RealTime_toFrame(PyObject *self, PyObject *args) | |
65 { | |
66 unsigned int samplerate; | |
67 | |
68 if ( !PyArg_ParseTuple(args, "I:realtime.toFrame object ", | |
69 (unsigned int *) &samplerate )) { | |
70 PyErr_SetString(PyExc_ValueError, | |
71 "Sample Rate Required."); | |
72 return NULL; | |
73 } | |
74 | |
75 return Py_BuildValue("k", | |
76 RealTime::realTime2Frame( | |
77 *(const RealTime*) ((RealTimeObject*)self)->rt, | |
78 (unsigned int) samplerate)); | |
79 } | |
80 | |
81 /* Conversion of realtime to a double precision floating point value */ | |
82 /* ...in Python called by e.g. float(realtime) */ | |
83 static PyObject * | |
84 RealTime_float(PyObject *s) | |
85 { | |
86 double drt = ((double) ((RealTimeObject*)s)->rt->sec + | |
87 (double)((double) ((RealTimeObject*)s)->rt->nsec)/1000000000); | |
88 return PyFloat_FromDouble(drt); | |
89 } | |
90 | |
91 /* test */ | |
92 static PyObject * | |
93 RealTime_test(PyObject *self) | |
94 { | |
95 | |
96 long frame = 100; | |
97 unsigned int sampleRate = 22050; | |
98 | |
99 const RealTime t = RealTime::frame2RealTime(frame,sampleRate); | |
100 long back = RealTime::realTime2Frame(t,sampleRate); | |
101 cerr << "Reverse Conversion: " << back << endl; | |
102 | |
103 return Py_BuildValue("s", | |
104 ((RealTimeObject*)self)->rt->toString().c_str()); | |
105 } | |
106 | |
107 | |
108 /* Type object's (RealTime) methods table */ | |
109 static PyMethodDef RealTime_methods[] = { | |
110 | |
111 {"toText", (PyCFunction)RealTime_toText, METH_NOARGS, | |
112 PyDoc_STR("toText() -> Return a user-readable string to the nearest millisecond in a form like HH:MM:SS.mmm")}, | |
113 | |
114 {"values", (PyCFunction)RealTime_values, METH_NOARGS, | |
115 PyDoc_STR("values() -> Tuple of sec,nsec representation.")}, | |
116 | |
117 {"toFrame", (PyCFunction)RealTime_toFrame, METH_VARARGS, | |
118 PyDoc_STR("frame(samplerate) -> Sample count for given sample rate.")}, | |
119 | |
120 {"toFloat", (PyCFunction)RealTime_float, METH_NOARGS, | |
121 PyDoc_STR("float() -> Floating point representation.")}, | |
122 | |
123 {"test", (PyCFunction)RealTime_test, METH_VARARGS, | |
124 PyDoc_STR("test() -> .")}, | |
125 | |
126 {NULL, NULL} /* sentinel */ | |
127 }; | |
128 | |
129 | |
130 | |
131 /* Function to set basic attributes */ | |
132 static int | |
133 RealTime_setattr(RealTimeObject *self, char *name, PyObject *value) | |
134 { | |
135 | |
136 if ( !string(name).compare("sec")) { | |
137 self->rt->sec= (int) PyInt_AS_LONG(value); | |
138 return 0; | |
139 } | |
140 | |
141 if ( !string(name).compare("nsec")) { | |
142 self->rt->nsec= (int) PyInt_AS_LONG(value); | |
143 return 0; | |
144 } | |
145 | |
146 return -1; | |
147 } | |
148 | |
149 /* Function to get basic attributes */ | |
150 static PyObject * | |
151 RealTime_getattr(RealTimeObject *self, char *name) | |
152 { | |
153 | |
154 if ( !string(name).compare("sec") ) { | |
155 return PyInt_FromSsize_t( | |
156 (Py_ssize_t) self->rt->sec); | |
157 } | |
158 | |
159 if ( !string(name).compare("nsec") ) { | |
160 return PyInt_FromSsize_t( | |
161 (Py_ssize_t) self->rt->nsec); | |
162 } | |
163 | |
164 return Py_FindMethod(RealTime_methods, | |
165 (PyObject *)self, name); | |
166 } | |
167 | |
168 | |
169 /* DESTRUCTOR: delete type object */ | |
170 static void | |
171 RealTimeObject_dealloc(RealTimeObject *self) | |
172 { | |
173 delete self->rt; //delete the C object | |
174 PyObject_Del(self); //delete the Python object | |
175 } | |
176 | |
177 /* Number Protocol */ | |
178 | |
179 | |
180 static PyObject * | |
181 RealTime_add(PyObject *s, PyObject *w) | |
182 { | |
183 | |
184 RealTimeObject *result = | |
185 PyObject_New(RealTimeObject, &RealTime_Type); | |
186 if (result == NULL) return NULL; | |
187 | |
188 result->rt = new RealTime::RealTime( | |
189 *((RealTimeObject*)s)->rt + *((RealTimeObject*)w)->rt); | |
190 return (PyObject*)result; | |
191 } | |
192 | |
193 static PyObject * | |
194 RealTime_subtract(PyObject *s, PyObject *w) | |
195 { | |
196 | |
197 RealTimeObject *result = | |
198 PyObject_New(RealTimeObject, &RealTime_Type); | |
199 if (result == NULL) return NULL; | |
200 | |
201 result->rt = new RealTime::RealTime( | |
202 *((RealTimeObject*)s)->rt - *((RealTimeObject*)w)->rt); | |
203 return (PyObject*)result; | |
204 } | |
205 | |
206 | |
207 static PyNumberMethods realtime_as_number = { | |
208 RealTime_add, /*nb_add*/ | |
209 RealTime_subtract, /*nb_subtract*/ | |
210 0, /*nb_multiply*/ | |
211 0, /*nb_divide*/ | |
212 0, /*nb_remainder*/ | |
213 0, /*nb_divmod*/ | |
214 0, /*nb_power*/ | |
215 0, /*nb_neg*/ | |
216 0, /*nb_pos*/ | |
217 0, /*(unaryfunc)array_abs,*/ | |
218 0, /*nb_nonzero*/ | |
219 0, /*nb_invert*/ | |
220 0, /*nb_lshift*/ | |
221 0, /*nb_rshift*/ | |
222 0, /*nb_and*/ | |
223 0, /*nb_xor*/ | |
224 0, /*nb_or*/ | |
225 0, /*nb_coerce*/ | |
226 0, /*nb_int*/ | |
227 0, /*nb_long*/ | |
228 (unaryfunc)RealTime_float, /*nb_float*/ | |
229 0, /*nb_oct*/ | |
230 0, /*nb_hex*/ | |
231 }; | |
232 | |
233 /* pyRealTime TypeObject */ | |
234 | |
235 | |
236 /* Doc:: 10.3 Type Objects */ | |
237 /* static */ PyTypeObject RealTime_Type = { | |
238 /* The ob_type field must be initialized in the module init function | |
239 * to be portable to Windows without using C++. */ | |
240 PyObject_HEAD_INIT(NULL) | |
241 0, /*ob_size*/ | |
242 "pyRealTime.realtime", /*tp_name*/ | |
243 sizeof(RealTimeObject), /*tp_basicsize*/ | |
244 sizeof(RealTime), /*tp_itemsize*/ | |
245 /* methods */ | |
246 (destructor)RealTimeObject_dealloc, /*tp_dealloc*/ | |
247 0, /*tp_print*/ | |
248 (getattrfunc)RealTime_getattr, /*tp_getattr*/ | |
249 (setattrfunc)RealTime_setattr, /*tp_setattr*/ | |
250 0, /*tp_compare*/ | |
251 RealTime_repr, /*tp_repr*/ | |
252 &realtime_as_number, /*tp_as_number*/ | |
253 0, /*tp_as_sequence*/ | |
254 0, /*tp_as_mapping*/ | |
255 0, /*tp_hash*/ | |
256 0,//(ternaryfunc)RealTime_new, /*tp_call*/ | |
257 0, /*tp_str*/ | |
258 0, /*tp_getattro*/ | |
259 0, /*tp_setattro*/ | |
260 0, /*tp_as_buffer*/ | |
261 Py_TPFLAGS_DEFAULT, /*tp_flags*/ | |
262 0, /*tp_doc*/ | |
263 0, /*tp_traverse*/ | |
264 0, /*tp_clear*/ | |
265 0, /*tp_richcompare*/ | |
266 0, /*tp_weaklistoffset*/ | |
267 0, /*tp_iter*/ | |
268 0, /*tp_iternext*/ | |
269 RealTime_methods, /*tp_methods*/ //TypeObject Methods | |
270 0, /*tp_members*/ | |
271 0, /*tp_getset*/ | |
272 0, /*tp_base*/ | |
273 0, /*tp_dict*/ | |
274 0, /*tp_descr_get*/ | |
275 0, /*tp_descr_set*/ | |
276 0, /*tp_dictoffset*/ | |
277 0, /*tp_init*/ | |
278 0, /*tp_alloc*/ | |
279 0, /*tp_new*/ | |
280 0, /*tp_free*/ | |
281 0, /*tp_is_gc*/ | |
282 }; | |
283 | |
284 | |
285 /* Remaining Functions Exposed by the MODULE */ | |
286 | |
287 | |
288 /* New RealTime object from Frame (with given samplerate) */ | |
289 /*static*/ PyObject * | |
290 RealTime_frame2RealTime(PyObject *ignored, PyObject *args) | |
291 { | |
292 | |
293 long frame; | |
294 unsigned int sampleRate; | |
295 | |
296 if (!PyArg_ParseTuple(args, "lI:realtime.fame2RealTime ", | |
297 &frame, | |
298 &sampleRate)) | |
299 return NULL; | |
300 /*Doc:: 5.5 Parsing arguments and building values*/ | |
301 | |
302 RealTimeObject *self; | |
303 self = PyObject_New(RealTimeObject, &RealTime_Type); | |
304 if (self == NULL) | |
305 return NULL; | |
306 | |
307 self->rt = new RealTime::RealTime( | |
308 RealTime::frame2RealTime(frame,sampleRate)); | |
309 | |
310 return (PyObject *) self; | |
311 } | |
312 | |
313 /* New RealTime object from sec and nsec */ | |
314 /*static*/ PyObject * | |
315 RealTime_new(PyObject *ignored, PyObject *args) | |
316 { | |
317 | |
318 unsigned int sec = 0; | |
319 unsigned int nsec = 0; | |
320 double unary = 0; | |
321 const char *fmt = NULL; | |
322 | |
323 /*Doc:: 5.5 Parsing arguments and building values*/ | |
324 if ( | |
325 | |
326 !PyArg_ParseTuple(args, "|sd:realtime.new ", | |
327 (const char *) &fmt, | |
328 (double *) &unary) && | |
329 | |
330 !PyArg_ParseTuple(args, "|II:realtime.new ", | |
331 (unsigned int*) &sec, | |
332 (unsigned int*) &nsec) | |
333 | |
334 ) { | |
335 PyErr_SetString(PyExc_TypeError, | |
336 "RealTime initialised with wrong arguments."); | |
337 return NULL; } | |
338 | |
339 PyErr_Clear(); | |
340 | |
341 RealTimeObject *self = | |
342 PyObject_New(RealTimeObject, &RealTime_Type); | |
343 if (self == NULL) return NULL; | |
344 | |
345 self->rt = NULL; | |
346 | |
347 if (sec == 0 && nsec == 0 && fmt == 0) | |
348 self->rt = new RealTime::RealTime(); | |
349 else if (fmt == 0) | |
350 self->rt = new RealTime::RealTime(sec,nsec); | |
351 else { | |
352 | |
353 if (!string(fmt).compare("float") || | |
354 !string(fmt).compare("seconds")) | |
355 self->rt = new RealTime::RealTime( | |
356 RealTime::fromSeconds((double) unary)); | |
357 | |
358 if (!string(fmt).compare("milliseconds")) { | |
359 self->rt = new RealTime::RealTime( | |
360 RealTime::fromSeconds((double) unary / 1000.0)); } | |
361 } | |
362 | |
363 if (!self->rt) { | |
364 PyErr_SetString(PyExc_TypeError, | |
365 "RealTime initialised with wrong arguments."); | |
366 return NULL; | |
367 } | |
368 | |
369 return (PyObject *) self; | |
370 } | |
371 | |
372 | |
373 /* pyRealTime Module's methods table */ | |
374 static PyMethodDef Module_methods[] = { | |
375 | |
376 {"frame2RealTime", (PyCFunction)RealTime_frame2RealTime, METH_VARARGS, | |
377 PyDoc_STR("frame2RealTime((int64)frame, (uint32)sampleRate ) -> returns new RealTime object from frame.")}, | |
378 | |
379 {"realtime", RealTime_new, METH_VARARGS, | |
380 PyDoc_STR("realtime() -> returns new RealTime object")}, | |
381 | |
382 {NULL, NULL} /* sentinel */ | |
383 }; | |
384 | |
385 | |
386 /* PyRealTime C API functions */ | |
387 | |
388 | |
389 | |
390 /*RealTime from PyRealTime*/ | |
391 RealTime* | |
392 PyRealTime_AsPointer (PyObject *self) { | |
393 | |
394 RealTimeObject *s = (RealTimeObject*) self; | |
395 | |
396 if (!PyRealTime_Check(s)) { | |
397 PyErr_SetString(PyExc_TypeError, "RealTime Object Expected."); | |
398 cerr << "in call PyRealTime_AsPointer(): RealTime Object Expected. " << endl; | |
399 return NULL; } | |
400 return s->rt; }; | |
401 | |
402 /*PyRealTime from RealTime*/ | |
403 PyObject* | |
404 PyRealTime_FromRealTime(Vamp::RealTime *rt) { | |
405 | |
406 RealTimeObject *self = | |
407 PyObject_New(RealTimeObject, &RealTime_Type); | |
408 if (self == NULL) return NULL; | |
409 | |
410 self->rt = new RealTime::RealTime(*rt); | |
411 return (PyObject*) self; | |
412 } | |
413 | |
414 | |
415 /* Module initialization (includes extern "C" {...}) */ | |
416 PyMODINIT_FUNC | |
417 initpyRealTime(void) | |
418 { | |
419 PyObject *m; | |
420 | |
421 /* Finalize the type object including setting type of the new type | |
422 * object; doing it here is required for portability to Windows | |
423 * without requiring C++. */ | |
424 if (PyType_Ready(&RealTime_Type) < 0) | |
425 return; | |
426 | |
427 /* Create the module and add the functions */ | |
428 m = Py_InitModule3("pyRealTime", Module_methods, module_doc); | |
429 if (m == NULL) | |
430 return; | |
431 | |
432 // PyModule_AddObject(m, "realtime", (PyObject *)&RealTime_Type); | |
433 | |
434 } |