diff host/pyRealTime.cpp @ 11:4610f2b8477d

added pyRealTime object impl to host
author fazekasgy
date Mon, 16 Jun 2008 09:44:48 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/host/pyRealTime.cpp	Mon Jun 16 09:44:48 2008 +0000
@@ -0,0 +1,434 @@
+/*
+
+This module exposes a Type Object wrapping VAMP::RealTime
+together with module level functions to create 
+new pyRealTime objects from frame count, samplerate or sec,nsec tuples.
+
+A small API is provided for the C/C++ programmer and relevant
+functions are exposed to Python.
+
+TODO: implement number protocol (i.e. wrap arithmetic operators) 
+partly done
+
+*/
+
+#include <Python.h>
+#include <pyRealTime.h>
+#include "vamp-sdk/Plugin.h"
+#include <string>
+
+using namespace std;
+using namespace Vamp;
+
+using Vamp::Plugin;
+using Vamp::RealTime;
+
+/*						REAL-TIME TYPE OBJECT						*/
+
+
+/* Documentation for our new module */
+PyDoc_STRVAR(module_doc,
+"This module is a thin wrapper around VAMP::RealTime.");
+
+
+/*					 RealTime Object's Methods 					*/ 
+//Note: these are internals, not exposed by the module but the object
+
+/* Returns a Tuple containing sec and nsec values */
+static PyObject *
+RealTime_values(RealTimeObject *self)
+{
+	return Py_BuildValue("(ii)",
+	self->rt->sec,self->rt->nsec);
+}
+
+/* Returns a Text representation */
+static PyObject *
+RealTime_toText(RealTimeObject *self, PyObject *args)
+{
+	return Py_BuildValue("s",
+	self->rt->toText().c_str());
+}
+
+/* String representation called by e.g. str(realtime), print realtime*/
+static PyObject *
+RealTime_repr(PyObject *self)
+{
+	return Py_BuildValue("s",
+	((RealTimeObject*)self)->rt->toString().c_str());
+}
+
+
+/* Frame representation */
+static PyObject *
+RealTime_toFrame(PyObject *self, PyObject *args)
+{
+	unsigned int samplerate;
+	
+	if ( !PyArg_ParseTuple(args, "I:realtime.toFrame object ", 
+	(unsigned int *) &samplerate )) {
+		PyErr_SetString(PyExc_ValueError, 
+		"Sample Rate Required.");
+		return NULL;
+	}
+	
+	return Py_BuildValue("k", 
+	RealTime::realTime2Frame( 
+	*(const RealTime*) ((RealTimeObject*)self)->rt, 
+	(unsigned int) samplerate));
+}
+
+/* Conversion of realtime to a double precision floating point value */
+/* ...in Python called by e.g. float(realtime) */
+static PyObject *
+RealTime_float(PyObject *s)
+{
+	double drt = ((double) ((RealTimeObject*)s)->rt->sec + 
+	(double)((double) ((RealTimeObject*)s)->rt->nsec)/1000000000);
+	return PyFloat_FromDouble(drt);	
+}
+
+/* test */
+static PyObject *
+RealTime_test(PyObject *self)
+{
+
+	long frame = 100;
+	unsigned int sampleRate = 22050;
+	
+	const RealTime t = RealTime::frame2RealTime(frame,sampleRate);
+	long back = RealTime::realTime2Frame(t,sampleRate);
+	cerr << "Reverse Conversion: " << back << endl;
+
+	return Py_BuildValue("s",
+	((RealTimeObject*)self)->rt->toString().c_str());
+}
+
+
+/* Type object's (RealTime) methods table */
+static PyMethodDef RealTime_methods[] = {
+
+	{"toText",	(PyCFunction)RealTime_toText,	METH_NOARGS,
+		PyDoc_STR("toText() -> Return a user-readable string to the nearest millisecond in a form like HH:MM:SS.mmm")},
+
+	{"values",	(PyCFunction)RealTime_values,	METH_NOARGS,
+		PyDoc_STR("values() -> Tuple of sec,nsec representation.")},
+
+	{"toFrame",	(PyCFunction)RealTime_toFrame,	METH_VARARGS,
+		PyDoc_STR("frame(samplerate) -> Sample count for given sample rate.")},
+
+	{"toFloat",	(PyCFunction)RealTime_float,	METH_NOARGS,
+		PyDoc_STR("float() -> Floating point representation.")},
+
+	{"test",	(PyCFunction)RealTime_test,	METH_VARARGS,
+		PyDoc_STR("test() -> .")},
+	
+	{NULL,		NULL}		/* sentinel */
+};
+
+
+
+/* Function to set basic attributes */
+static int
+RealTime_setattr(RealTimeObject *self, char *name, PyObject *value)
+{
+
+	if ( !string(name).compare("sec")) { 
+		self->rt->sec= (int) PyInt_AS_LONG(value);
+		return 0;
+	}
+
+	if ( !string(name).compare("nsec")) { 
+		self->rt->nsec= (int) PyInt_AS_LONG(value);
+		return 0;
+	}
+
+	return -1;
+}
+
+/* Function to get basic attributes */
+static PyObject *
+RealTime_getattr(RealTimeObject *self, char *name)
+{
+
+	if ( !string(name).compare("sec") ) { 
+		return PyInt_FromSsize_t(
+		(Py_ssize_t) self->rt->sec); 
+	} 
+
+	if ( !string(name).compare("nsec") ) { 
+		return PyInt_FromSsize_t(
+		(Py_ssize_t) self->rt->nsec); 
+	} 
+
+	return Py_FindMethod(RealTime_methods, 
+	(PyObject *)self, name);
+}
+
+
+/* DESTRUCTOR: delete type object */
+static void
+RealTimeObject_dealloc(RealTimeObject *self)
+{
+	delete self->rt; 	//delete the C object
+	PyObject_Del(self); //delete the Python object
+}
+
+/*					 Number Protocol 					*/
+
+
+static PyObject *
+RealTime_add(PyObject *s, PyObject *w)
+{
+
+	RealTimeObject *result = 
+    PyObject_New(RealTimeObject, &RealTime_Type); 
+	if (result == NULL) return NULL;
+
+	result->rt = new RealTime::RealTime(
+	*((RealTimeObject*)s)->rt + *((RealTimeObject*)w)->rt);
+	return (PyObject*)result;
+}
+
+static PyObject *
+RealTime_subtract(PyObject *s, PyObject *w)
+{
+
+	RealTimeObject *result = 
+    PyObject_New(RealTimeObject, &RealTime_Type); 
+	if (result == NULL) return NULL;
+
+	result->rt = new RealTime::RealTime(
+	*((RealTimeObject*)s)->rt - *((RealTimeObject*)w)->rt);
+	return (PyObject*)result;
+}
+
+
+static PyNumberMethods realtime_as_number = {
+	RealTime_add,			/*nb_add*/
+	RealTime_subtract,		/*nb_subtract*/
+	0,						/*nb_multiply*/
+	0,				 		/*nb_divide*/
+    0,						/*nb_remainder*/
+    0,      	            /*nb_divmod*/
+    0,                   	/*nb_power*/
+    0,                  	/*nb_neg*/
+    0,                		/*nb_pos*/
+    0,                  	/*(unaryfunc)array_abs,*/
+    0,                    	/*nb_nonzero*/
+    0,                    	/*nb_invert*/
+    0,       				/*nb_lshift*/
+    0,      				/*nb_rshift*/
+    0,      				/*nb_and*/
+    0,      				/*nb_xor*/
+    0,       				/*nb_or*/
+    0,                      /*nb_coerce*/
+    0,						/*nb_int*/
+    0,				        /*nb_long*/
+    (unaryfunc)RealTime_float,             /*nb_float*/
+    0,               		/*nb_oct*/
+    0,               		/*nb_hex*/
+};
+
+/*					 pyRealTime TypeObject 					*/
+
+
+/* Doc:: 10.3 Type Objects */
+/* static */ PyTypeObject RealTime_Type = {
+	/* The ob_type field must be initialized in the module init function
+	 * to be portable to Windows without using C++. */
+	PyObject_HEAD_INIT(NULL)
+	0,						/*ob_size*/
+	"pyRealTime.realtime",				/*tp_name*/
+	sizeof(RealTimeObject),	/*tp_basicsize*/
+	sizeof(RealTime),		/*tp_itemsize*/
+	/*	 	methods	 	*/
+	(destructor)RealTimeObject_dealloc, /*tp_dealloc*/
+	0,						/*tp_print*/
+	(getattrfunc)RealTime_getattr, /*tp_getattr*/
+	(setattrfunc)RealTime_setattr, /*tp_setattr*/
+	0,						/*tp_compare*/
+	RealTime_repr,			/*tp_repr*/
+	&realtime_as_number,	/*tp_as_number*/
+	0,						/*tp_as_sequence*/
+	0,						/*tp_as_mapping*/
+	0,						/*tp_hash*/
+	0,//(ternaryfunc)RealTime_new,                      /*tp_call*/
+    0,                      /*tp_str*/
+    0,                      /*tp_getattro*/
+    0,                      /*tp_setattro*/
+    0,                      /*tp_as_buffer*/
+    Py_TPFLAGS_DEFAULT,     /*tp_flags*/
+    0,                      /*tp_doc*/
+    0,                      /*tp_traverse*/
+    0,                      /*tp_clear*/
+    0,                      /*tp_richcompare*/
+    0,                      /*tp_weaklistoffset*/
+    0,                      /*tp_iter*/
+    0,                      /*tp_iternext*/
+    RealTime_methods,       /*tp_methods*/ //TypeObject Methods
+    0,                      /*tp_members*/
+    0,                      /*tp_getset*/
+    0,                      /*tp_base*/
+    0,                      /*tp_dict*/
+    0,                      /*tp_descr_get*/
+    0,                      /*tp_descr_set*/
+    0,                      /*tp_dictoffset*/
+    0,                      /*tp_init*/
+    0,                      /*tp_alloc*/
+    0,                      /*tp_new*/
+    0,			            /*tp_free*/
+    0,                      /*tp_is_gc*/
+};
+
+
+/*		 Remaining Functions Exposed by the MODULE 					*/
+
+
+/* New RealTime object from Frame (with given samplerate) */
+/*static*/ PyObject *
+RealTime_frame2RealTime(PyObject *ignored, PyObject *args)
+{
+
+	long frame;
+	unsigned int sampleRate;
+
+	if (!PyArg_ParseTuple(args, "lI:realtime.fame2RealTime ", 
+	&frame, 
+	&sampleRate))
+		return NULL;
+	/*Doc:: 5.5 Parsing arguments and building values*/
+
+	RealTimeObject *self;
+	self = PyObject_New(RealTimeObject, &RealTime_Type); 
+	if (self == NULL)
+		return NULL;
+
+	self->rt = new RealTime::RealTime(
+	RealTime::frame2RealTime(frame,sampleRate));
+
+	return (PyObject *) self;
+}
+
+/* New RealTime object from sec and nsec */
+/*static*/ PyObject *
+RealTime_new(PyObject *ignored, PyObject *args)
+{
+
+	unsigned int sec = 0;
+	unsigned int nsec = 0;
+	double unary = 0;
+	const char *fmt = NULL;
+
+	/*Doc:: 5.5 Parsing arguments and building values*/
+	if (
+		
+	!PyArg_ParseTuple(args, "|sd:realtime.new ", 
+	(const char *) &fmt, 
+	(double *) &unary) 	&&
+
+	!PyArg_ParseTuple(args, "|II:realtime.new ", 
+	(unsigned int*) &sec, 
+	(unsigned int*) &nsec) 
+		
+	) { 
+		PyErr_SetString(PyExc_TypeError, 
+		"RealTime initialised with wrong arguments.");
+		return NULL; }
+
+	PyErr_Clear();
+
+	RealTimeObject *self = 
+	PyObject_New(RealTimeObject, &RealTime_Type); 
+	if (self == NULL) return NULL;
+
+	self->rt = NULL;
+
+	if (sec == 0 && nsec == 0 && fmt == 0) 
+		self->rt = new RealTime::RealTime();
+	else if (fmt == 0)
+		self->rt = new RealTime::RealTime(sec,nsec);
+	else { 
+
+		if (!string(fmt).compare("float") ||
+			!string(fmt).compare("seconds"))  
+			self->rt = new RealTime::RealTime( 
+			RealTime::fromSeconds((double) unary)); 
+
+		if (!string(fmt).compare("milliseconds")) {
+			self->rt = new RealTime::RealTime( 
+			RealTime::fromSeconds((double) unary / 1000.0)); }
+	}
+
+	if (!self->rt) { 
+		PyErr_SetString(PyExc_TypeError, 
+		"RealTime initialised with wrong arguments.");
+		return NULL; 
+	}
+
+	return (PyObject *) self;
+}
+
+
+/* pyRealTime Module's methods table */
+static PyMethodDef Module_methods[] = {
+
+	{"frame2RealTime",	(PyCFunction)RealTime_frame2RealTime,	METH_VARARGS,
+		PyDoc_STR("frame2RealTime((int64)frame, (uint32)sampleRate ) -> returns new RealTime object from frame.")},
+
+	{"realtime",	RealTime_new,		METH_VARARGS,
+		PyDoc_STR("realtime() -> returns new RealTime object")},
+	
+	{NULL,		NULL}		/* sentinel */
+};
+
+
+/*				 PyRealTime C API functions 					*/
+
+
+
+/*RealTime from PyRealTime*/
+RealTime*
+PyRealTime_AsPointer (PyObject *self) { 
+
+	RealTimeObject *s = (RealTimeObject*) self; 
+
+	if (!PyRealTime_Check(s)) {
+		PyErr_SetString(PyExc_TypeError, "RealTime Object Expected.");
+		cerr << "in call PyRealTime_AsPointer(): RealTime Object Expected. " << endl;
+		return NULL; }
+	return s->rt; };
+
+/*PyRealTime from RealTime*/
+PyObject* 
+PyRealTime_FromRealTime(Vamp::RealTime *rt) {
+
+	RealTimeObject *self =
+	PyObject_New(RealTimeObject, &RealTime_Type); 
+	if (self == NULL) return NULL;
+
+	self->rt = new RealTime::RealTime(*rt);
+	return (PyObject*) self;
+}
+
+
+/* Module initialization (includes extern "C" {...}) */
+PyMODINIT_FUNC
+initpyRealTime(void)
+{
+	PyObject *m;
+
+	/* Finalize the type object including setting type of the new type
+	 * object; doing it here is required for portability to Windows 
+	 * without requiring C++. */
+	if (PyType_Ready(&RealTime_Type) < 0)
+		return;
+
+	/* Create the module and add the functions */
+	m = Py_InitModule3("pyRealTime", Module_methods, module_doc);
+	if (m == NULL)
+		return;
+
+//	PyModule_AddObject(m, "realtime", (PyObject *)&RealTime_Type);
+
+}