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