fazekasgy@37: /* fazekasgy@37: fazekasgy@37: * Vampy : This plugin is a wrapper around the Vamp plugin API. fazekasgy@37: * It allows for writing Vamp plugins in Python. fazekasgy@37: fazekasgy@37: * Centre for Digital Music, Queen Mary University of London. fazekasgy@37: * Copyright (C) 2008-2009 Gyorgy Fazekas, QMUL. (See Vamp sources fazekasgy@37: * for licence information.) fazekasgy@37: fazekasgy@37: */ fazekasgy@37: fazekasgy@37: #include fazekasgy@37: #include "PyRealTime.h" fazekasgy@37: #include "vamp-sdk/Plugin.h" fazekasgy@37: #include fazekasgy@37: fazekasgy@37: using namespace std; fazekasgy@37: using namespace Vamp; fazekasgy@37: using Vamp::Plugin; fazekasgy@37: using Vamp::RealTime; fazekasgy@37: fazekasgy@37: fazekasgy@37: /* CONSTRUCTOR: New RealTime object from sec and nsec */ fazekasgy@37: static PyObject* fazekasgy@37: RealTime_new(PyTypeObject *type, PyObject *args, PyObject *kw) fazekasgy@37: { fazekasgy@37: unsigned int sec = 0; fazekasgy@37: unsigned int nsec = 0; fazekasgy@37: double unary = 0; fazekasgy@37: const char *fmt = NULL; fazekasgy@37: fazekasgy@37: if ( fazekasgy@37: /// new RealTime from ('format',float) e.g. ('seconds',2.34123) fazekasgy@37: !PyArg_ParseTuple(args, "|sd:RealTime.new ", fazekasgy@37: (const char *) &fmt, fazekasgy@37: (double *) &unary) && fazekasgy@37: fazekasgy@37: /// new RealTime from (sec{int},nsec{int}) e.g. (2,34) fazekasgy@37: !PyArg_ParseTuple(args, "|II:RealTime.new ", fazekasgy@37: (unsigned int*) &sec, fazekasgy@37: (unsigned int*) &nsec) fazekasgy@37: fazekasgy@37: ) { fazekasgy@37: PyErr_SetString(PyExc_TypeError, fazekasgy@37: "RealTime initialised with wrong arguments."); fazekasgy@37: return NULL; fazekasgy@37: } fazekasgy@37: fazekasgy@37: // PyErr_Clear(); fazekasgy@37: fazekasgy@37: // RealTimeObject *self = PyObject_New(RealTimeObject, &RealTime_Type); fazekasgy@37: RealTimeObject *self = (RealTimeObject*)type->tp_alloc(type, 0); fazekasgy@37: fazekasgy@37: if (self == NULL) return NULL; fazekasgy@37: fazekasgy@37: self->rt = NULL; fazekasgy@37: fazekasgy@37: if (sec == 0 && nsec == 0 && fmt == 0) fazekasgy@37: self->rt = new RealTime(); fazekasgy@37: else if (fmt == 0) fazekasgy@37: self->rt = new RealTime(sec,nsec); fazekasgy@37: else { fazekasgy@37: /// new RealTime from seconds or milliseconds: i.e. >>>RealTime('seconds',12.3) fazekasgy@37: if (!string(fmt).compare("float") || fazekasgy@37: !string(fmt).compare("seconds")) fazekasgy@37: self->rt = new RealTime( fazekasgy@37: RealTime::fromSeconds((double) unary)); fazekasgy@37: fazekasgy@37: if (!string(fmt).compare("milliseconds")) { fazekasgy@37: self->rt = new RealTime( fazekasgy@37: RealTime::fromSeconds((double) unary / 1000.0)); } fazekasgy@37: } fazekasgy@37: fazekasgy@37: if (!self->rt) { fazekasgy@37: PyErr_SetString(PyExc_TypeError, fazekasgy@37: "RealTime initialised with wrong arguments."); fazekasgy@37: return NULL; fazekasgy@37: } fazekasgy@37: fazekasgy@37: return (PyObject *) self; fazekasgy@37: } fazekasgy@37: fazekasgy@37: /* DESTRUCTOR: delete type object */ fazekasgy@37: static void fazekasgy@37: RealTimeObject_dealloc(RealTimeObject *self) fazekasgy@37: { fazekasgy@37: if (self->rt) delete self->rt; //delete the C object fazekasgy@37: PyObject_Del(self); //delete the Python object (original) fazekasgy@37: /// this requires PyType_Ready() which fills ob_type fazekasgy@37: // self->ob_type->tp_free((PyObject*)self); fazekasgy@37: } fazekasgy@37: fazekasgy@37: /* RealTime Object's Methods */ fazekasgy@37: //these are internals not exposed by the module but the object fazekasgy@37: fazekasgy@37: /* Returns a Tuple containing sec and nsec values */ fazekasgy@37: static PyObject * fazekasgy@37: RealTime_values(RealTimeObject *self) fazekasgy@37: { fazekasgy@37: return Py_BuildValue("(ii)",self->rt->sec,self->rt->nsec); fazekasgy@37: } fazekasgy@37: fazekasgy@37: /* Returns a Text representation */ fazekasgy@37: static PyObject * fazekasgy@37: RealTime_toString(RealTimeObject *self, PyObject *args) fazekasgy@37: { fazekasgy@37: return Py_BuildValue("s",self->rt->toText().c_str()); fazekasgy@37: } fazekasgy@37: fazekasgy@37: /* Frame representation */ fazekasgy@37: static PyObject * fazekasgy@37: RealTime_toFrame(PyObject *self, PyObject *args) fazekasgy@37: { fazekasgy@37: unsigned int samplerate; fazekasgy@37: fazekasgy@37: if ( !PyArg_ParseTuple(args, "I:realtime.toFrame object ", fazekasgy@37: (unsigned int *) &samplerate )) { fazekasgy@37: PyErr_SetString(PyExc_ValueError,"Integer Sample Rate Required."); fazekasgy@37: return NULL; fazekasgy@37: } fazekasgy@37: fazekasgy@37: return Py_BuildValue("k", fazekasgy@37: RealTime::realTime2Frame( fazekasgy@37: *(const RealTime*) ((RealTimeObject*)self)->rt, fazekasgy@37: (unsigned int) samplerate)); fazekasgy@37: } fazekasgy@37: fazekasgy@37: /* Conversion of realtime to a double precision floating point value */ fazekasgy@37: /* ...in Python called by e.g. float(realtime) */ fazekasgy@37: static PyObject * fazekasgy@37: RealTime_float(PyObject *s) fazekasgy@37: { fazekasgy@37: double drt = ((double) ((RealTimeObject*)s)->rt->sec + fazekasgy@37: (double)((double) ((RealTimeObject*)s)->rt->nsec)/1000000000); fazekasgy@37: return PyFloat_FromDouble(drt); fazekasgy@37: } fazekasgy@37: fazekasgy@37: fazekasgy@37: /* Type object's (RealTime) methods table */ fazekasgy@37: static PyMethodDef RealTime_methods[] = fazekasgy@37: { fazekasgy@37: {"values", (PyCFunction)RealTime_values, METH_NOARGS, fazekasgy@37: PyDoc_STR("values() -> Tuple of sec,nsec representation.")}, fazekasgy@37: fazekasgy@37: {"toString", (PyCFunction)RealTime_toString, METH_NOARGS, fazekasgy@37: PyDoc_STR("toString() -> Return a user-readable string to the nearest millisecond in a form like HH:MM:SS.mmm")}, fazekasgy@37: fazekasgy@37: {"toFrame", (PyCFunction)RealTime_toFrame, METH_VARARGS, fazekasgy@37: PyDoc_STR("toFrame(samplerate) -> Sample count for given sample rate.")}, fazekasgy@37: fazekasgy@37: {"toFloat", (PyCFunction)RealTime_float, METH_NOARGS, fazekasgy@37: PyDoc_STR("toFloat() -> Floating point representation.")}, fazekasgy@37: fazekasgy@37: {NULL, NULL} /* sentinel */ fazekasgy@37: }; fazekasgy@37: fazekasgy@37: fazekasgy@37: /* Methods implementing protocols */ fazekasgy@37: // these functions are called by the interpreter fazekasgy@37: fazekasgy@37: /* Object Protocol */ fazekasgy@37: fazekasgy@37: static int fazekasgy@37: RealTime_setattr(RealTimeObject *self, char *name, PyObject *value) fazekasgy@37: { fazekasgy@37: fazekasgy@37: if ( !string(name).compare("sec")) { fazekasgy@37: self->rt->sec= (int) PyInt_AS_LONG(value); fazekasgy@37: return 0; fazekasgy@37: } fazekasgy@37: fazekasgy@37: if ( !string(name).compare("nsec")) { fazekasgy@37: self->rt->nsec= (int) PyInt_AS_LONG(value); fazekasgy@37: return 0; fazekasgy@37: } fazekasgy@37: fazekasgy@37: return -1; fazekasgy@37: } fazekasgy@37: fazekasgy@37: static PyObject * fazekasgy@37: RealTime_getattr(RealTimeObject *self, char *name) fazekasgy@37: { fazekasgy@37: fazekasgy@37: if ( !string(name).compare("sec") ) { fazekasgy@37: return PyInt_FromSsize_t( fazekasgy@37: (Py_ssize_t) self->rt->sec); fazekasgy@37: } fazekasgy@37: fazekasgy@37: if ( !string(name).compare("nsec") ) { fazekasgy@37: return PyInt_FromSsize_t( fazekasgy@37: (Py_ssize_t) self->rt->nsec); fazekasgy@37: } fazekasgy@37: fazekasgy@37: return Py_FindMethod(RealTime_methods, fazekasgy@37: (PyObject *)self, name); fazekasgy@37: } fazekasgy@37: fazekasgy@37: /* String representation called by e.g. str(realtime), print realtime*/ fazekasgy@37: static PyObject * fazekasgy@37: RealTime_repr(PyObject *self) fazekasgy@37: { fazekasgy@37: return Py_BuildValue("s", fazekasgy@37: ((RealTimeObject*)self)->rt->toString().c_str()); fazekasgy@37: } fazekasgy@37: fazekasgy@37: fazekasgy@37: /* Number Protocol */ fazekasgy@37: /// Only add and substract make sense, or what about the fazekasgy@37: /// square root of Monday morning? fazekasgy@37: /// Divide by integer maybe for durations? fazekasgy@37: fazekasgy@37: static PyObject * fazekasgy@37: RealTime_add(PyObject *s, PyObject *w) fazekasgy@37: { fazekasgy@37: RealTimeObject *result = fazekasgy@37: PyObject_New(RealTimeObject, &RealTime_Type); fazekasgy@37: if (result == NULL) return NULL; fazekasgy@37: fazekasgy@37: result->rt = new RealTime( fazekasgy@37: *((RealTimeObject*)s)->rt + *((RealTimeObject*)w)->rt); fazekasgy@37: return (PyObject*)result; fazekasgy@37: } fazekasgy@37: fazekasgy@37: static PyObject * fazekasgy@37: RealTime_subtract(PyObject *s, PyObject *w) fazekasgy@37: { fazekasgy@37: RealTimeObject *result = fazekasgy@37: PyObject_New(RealTimeObject, &RealTime_Type); fazekasgy@37: if (result == NULL) return NULL; fazekasgy@37: fazekasgy@37: result->rt = new RealTime( fazekasgy@37: *((RealTimeObject*)s)->rt - *((RealTimeObject*)w)->rt); fazekasgy@37: return (PyObject*)result; fazekasgy@37: } fazekasgy@37: fazekasgy@37: static PyNumberMethods realtime_as_number = fazekasgy@37: { fazekasgy@37: RealTime_add, /*nb_add*/ fazekasgy@37: RealTime_subtract, /*nb_subtract*/ fazekasgy@37: 0, /*nb_multiply*/ fazekasgy@37: 0, /*nb_divide*/ fazekasgy@37: 0, /*nb_remainder*/ fazekasgy@37: 0, /*nb_divmod*/ fazekasgy@37: 0, /*nb_power*/ fazekasgy@37: 0, /*nb_neg*/ fazekasgy@37: 0, /*nb_pos*/ fazekasgy@37: 0, /*(unaryfunc)array_abs,*/ fazekasgy@37: 0, /*nb_nonzero*/ fazekasgy@37: 0, /*nb_invert*/ fazekasgy@37: 0, /*nb_lshift*/ fazekasgy@37: 0, /*nb_rshift*/ fazekasgy@37: 0, /*nb_and*/ fazekasgy@37: 0, /*nb_xor*/ fazekasgy@37: 0, /*nb_or*/ fazekasgy@37: 0, /*nb_coerce*/ fazekasgy@37: 0, /*nb_int*/ fazekasgy@37: 0, /*nb_long*/ fazekasgy@37: (unaryfunc)RealTime_float,/*nb_float*/ fazekasgy@37: 0, /*nb_oct*/ fazekasgy@37: 0, /*nb_hex*/ fazekasgy@37: }; fazekasgy@37: fazekasgy@37: /* REAL-TIME TYPE OBJECT */ fazekasgy@37: fazekasgy@37: #define RealTime_alloc PyType_GenericAlloc fazekasgy@37: #define RealTime_free PyObject_Del fazekasgy@37: fazekasgy@37: /* Doc:: 10.3 Type Objects */ /* static */ fazekasgy@37: PyTypeObject RealTime_Type = fazekasgy@37: { fazekasgy@37: PyObject_HEAD_INIT(NULL) fazekasgy@37: 0, /*ob_size*/ fazekasgy@37: "vampy.RealTime", /*tp_name*/ fazekasgy@37: sizeof(RealTimeObject), /*tp_basicsize*/ fazekasgy@37: 0,//sizeof(RealTime), /*tp_itemsize*/ fazekasgy@37: /* methods */ fazekasgy@37: (destructor)RealTimeObject_dealloc, /*tp_dealloc*/ fazekasgy@37: 0, /*tp_print*/ fazekasgy@37: (getattrfunc)RealTime_getattr, /*tp_getattr*/ fazekasgy@37: (setattrfunc)RealTime_setattr, /*tp_setattr*/ fazekasgy@37: 0, /*tp_compare*/ fazekasgy@37: RealTime_repr, /*tp_repr*/ fazekasgy@37: &realtime_as_number, /*tp_as_number*/ fazekasgy@37: 0, /*tp_as_sequence*/ fazekasgy@37: 0, /*tp_as_mapping*/ fazekasgy@37: 0, /*tp_hash*/ fazekasgy@37: 0,//(ternaryfunc)RealTime_new, /*tp_call*/ fazekasgy@37: 0, /*tp_str*/ fazekasgy@37: 0, /*tp_getattro*/ fazekasgy@37: 0, /*tp_setattro*/ fazekasgy@37: 0, /*tp_as_buffer*/ fazekasgy@37: Py_TPFLAGS_DEFAULT, /*tp_flags*/ fazekasgy@37: "RealTime Object", /*tp_doc*/ fazekasgy@37: 0, /*tp_traverse*/ fazekasgy@37: 0, /*tp_clear*/ fazekasgy@37: 0, /*tp_richcompare*/ fazekasgy@37: 0, /*tp_weaklistoffset*/ fazekasgy@37: 0, /*tp_iter*/ fazekasgy@37: 0, /*tp_iternext*/ fazekasgy@37: RealTime_methods, /*tp_methods*/ //TypeObject Methods fazekasgy@37: 0, /*tp_members*/ fazekasgy@37: 0, /*tp_getset*/ fazekasgy@37: 0, /*tp_base*/ fazekasgy@37: 0, /*tp_dict*/ fazekasgy@37: 0, /*tp_descr_get*/ fazekasgy@37: 0, /*tp_descr_set*/ fazekasgy@37: 0, /*tp_dictoffset*/ fazekasgy@37: 0, /*tp_init*/ fazekasgy@37: RealTime_alloc, /*tp_alloc*/ fazekasgy@37: RealTime_new, /*tp_new*/ fazekasgy@37: RealTime_free, /*tp_free*/ fazekasgy@37: 0, /*tp_is_gc*/ fazekasgy@37: }; fazekasgy@37: fazekasgy@37: fazekasgy@37: fazekasgy@37: /* PyRealTime C++ API */ fazekasgy@37: fazekasgy@37: /*PyRealTime from RealTime pointer fazekasgy@37: PyObject* fazekasgy@37: PyRealTime_FromRealTime(Vamp::RealTime *rt) { fazekasgy@37: fazekasgy@37: RealTimeObject *self = fazekasgy@37: PyObject_New(RealTimeObject, &RealTime_Type); fazekasgy@37: if (self == NULL) return NULL; fazekasgy@37: fazekasgy@37: self->rt = new RealTime(*rt); fazekasgy@37: return (PyObject*) self; fazekasgy@37: }*/ fazekasgy@37: fazekasgy@37: fazekasgy@37: /*PyRealTime from RealTime*/ fazekasgy@37: PyObject* fazekasgy@37: PyRealTime_FromRealTime(Vamp::RealTime& rt) { fazekasgy@37: fazekasgy@37: RealTimeObject *self = fazekasgy@37: PyObject_New(RealTimeObject, &RealTime_Type); fazekasgy@37: if (self == NULL) return NULL; fazekasgy@37: fazekasgy@37: self->rt = new RealTime(rt); fazekasgy@37: return (PyObject*) self; fazekasgy@37: } fazekasgy@37: fazekasgy@37: /*RealTime* from PyRealTime*/ fazekasgy@37: const Vamp::RealTime* fazekasgy@37: PyRealTime_AsRealTime (PyObject *self) { fazekasgy@37: fazekasgy@37: RealTimeObject *s = (RealTimeObject*) self; fazekasgy@37: fazekasgy@37: if (!PyRealTime_Check(s)) { fazekasgy@37: PyErr_SetString(PyExc_TypeError, "RealTime Object Expected."); fazekasgy@37: cerr << "in call PyRealTime_AsPointer(): RealTime Object Expected. " << endl; fazekasgy@37: return NULL; } fazekasgy@37: return s->rt; fazekasgy@37: }; fazekasgy@37: