annotate PyFeature.cpp @ 53:7e59caea821b

* Make a better job of preloading Python, especially when it's in a framework. Go for the Python file in the frameworks directory in preference to any libpythonX.Y.dylib. Particularly, don't try to preload any library without an absolute path until we've exhausted all our framework possibilities (so as to avoid picking up an ancient system library).
author cannam
date Fri, 09 Oct 2009 13:48:25 +0000
parents 27bab3a16c9a
children 5664fe298af2
rev   line source
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 "PyExtensionModule.h"
fazekasgy@37 14 #include "PyFeature.h"
fazekasgy@37 15 #include "vamp-sdk/Plugin.h"
fazekasgy@37 16 #include <string>
fazekasgy@37 17
fazekasgy@37 18 using namespace std;
fazekasgy@37 19 using namespace Vamp;
fazekasgy@37 20 using Vamp::Plugin;
fazekasgy@37 21
fazekasgy@37 22 /* CONSTRUCTOR: New Feature object */
fazekasgy@37 23 static PyObject *
fazekasgy@37 24 Feature_new(PyTypeObject *type, PyObject *args, PyObject *kw)
fazekasgy@37 25 {
fazekasgy@37 26 // FeatureObject *self = PyObject_New(FeatureObject, &Feature_Type);
fazekasgy@37 27 FeatureObject *self = (FeatureObject*)type->tp_alloc(type, 0);
fazekasgy@37 28 if (self == NULL) return NULL;
fazekasgy@37 29 self->dict = PyDict_New();
fazekasgy@37 30 if (self->dict == NULL) return NULL;
fazekasgy@37 31
fazekasgy@37 32 /// 4 args max.: {values|self_copy},timestamp,duration,label
fazekasgy@37 33 if(args && PyTuple_GET_SIZE(args)>0) {
fazekasgy@37 34 int s = PyTuple_GET_SIZE(args);
fazekasgy@37 35 PyObject* arg0 = PyTuple_GET_ITEM(args,0);
fazekasgy@37 36 if (s == 1 && PyFeature_CheckExact(arg0))
fazekasgy@37 37 PyDict_Merge(self->dict,PyFeature_AS_DICT(arg0),0);
fazekasgy@37 38 else
fazekasgy@37 39 PyDict_SetItemString(self->dict, "values", arg0);
fazekasgy@37 40 if (s>1) {
fazekasgy@37 41 PyDict_SetItemString(self->dict, "timestamp", PyTuple_GET_ITEM(args,1));
fazekasgy@37 42 PyDict_SetItemString(self->dict, "hasTimestamp", Py_True);
fazekasgy@37 43 }
fazekasgy@37 44 if (s>2) {
fazekasgy@37 45 PyDict_SetItemString(self->dict, "duration", PyTuple_GET_ITEM(args,2));
fazekasgy@37 46 PyDict_SetItemString(self->dict, "hasDuration", Py_True);
fazekasgy@37 47 }
fazekasgy@37 48 if (s>3) {
fazekasgy@37 49 PyDict_SetItemString(self->dict, "label", PyTuple_GET_ITEM(args,3));
fazekasgy@37 50 }
fazekasgy@37 51 }
fazekasgy@37 52
fazekasgy@37 53 /// accept keyword arguments:
fazekasgy@37 54 /// e.g. Feature(values = theOutputArray)
fazekasgy@37 55 if (!kw || !PyDict_Size(kw)) return (PyObject *) self;
fazekasgy@37 56 PyDict_Merge(self->dict,kw,0);
fazekasgy@37 57
fazekasgy@37 58 static char *kwlist[] = {"timestamp", "hasTimestamp", "duration", "hasDuration", 0};
fazekasgy@37 59
fazekasgy@37 60 int i = 0;
fazekasgy@37 61 while (kwlist[i]) {
fazekasgy@37 62 char* name = kwlist[i];
fazekasgy@37 63 char* attr = kwlist[++i];
fazekasgy@37 64 i++;
fazekasgy@37 65 PyObject *key = PyString_FromString(name);
fazekasgy@37 66 if (!key) break;
fazekasgy@37 67 if (PyDict_Contains(kw,key)) {
fazekasgy@37 68 if (PyDict_SetItem(self->dict,PyString_FromString(attr),Py_True) != 0)
fazekasgy@37 69 PyErr_SetString(PyExc_TypeError,
fazekasgy@37 70 "Error: in keyword arguments of vampy.Feature().");
fazekasgy@37 71 }
fazekasgy@37 72 Py_DECREF(key);
fazekasgy@37 73 }
fazekasgy@37 74
fazekasgy@37 75 return (PyObject *) self;
fazekasgy@37 76 }
fazekasgy@37 77
fazekasgy@37 78 /* DESTRUCTOR: delete type object */
fazekasgy@37 79 static void
fazekasgy@37 80 FeatureObject_dealloc(FeatureObject *self)
fazekasgy@37 81 {
fazekasgy@37 82 Py_XDECREF(self->dict);
fazekasgy@37 83 self->ob_type->tp_free((PyObject*)self);
fazekasgy@37 84 }
fazekasgy@37 85
fazekasgy@37 86 /* Feature Object's Methods */
fazekasgy@37 87 //Feature objects have no callable methods
fazekasgy@37 88
fazekasgy@37 89 /* PyFeature methods implementing protocols */
fazekasgy@37 90 // these functions are called by the interpreter automatically
fazekasgy@37 91
fazekasgy@37 92 /* Set attributes */
fazekasgy@37 93 static int
fazekasgy@37 94 Feature_setattr(FeatureObject *self, char *name, PyObject *v)
fazekasgy@37 95 {
fazekasgy@37 96 if (v == NULL)
fazekasgy@37 97 {
fazekasgy@37 98 int rv = PyDict_DelItemString(self->dict, name);
fazekasgy@37 99 if (rv < 0)
fazekasgy@37 100 PyErr_SetString(PyExc_AttributeError,"non-existing Feature attribute");
fazekasgy@37 101 return rv;
fazekasgy@37 102 }
fazekasgy@37 103 else return PyDict_SetItemString(self->dict, name, v);
fazekasgy@37 104 }
fazekasgy@37 105
fazekasgy@37 106
fazekasgy@37 107 /* Get attributes */
fazekasgy@37 108 static PyObject *
fazekasgy@37 109 Feature_getattr(FeatureObject *self, char *name)
fazekasgy@37 110 {
fazekasgy@37 111 if (self->dict != NULL) {
fazekasgy@37 112 PyObject *v = PyDict_GetItemString(self->dict, name);
fazekasgy@37 113 if (v != NULL)
fazekasgy@37 114 {
fazekasgy@37 115 Py_INCREF(v);
fazekasgy@37 116 return v;
fazekasgy@37 117 }
fazekasgy@37 118 }
fazekasgy@37 119 return NULL;
fazekasgy@37 120 }
fazekasgy@37 121
fazekasgy@37 122 /* The problem with this is that we'd need to implement two-way
fazekasgy@37 123 conversions which is really unnecesary: The case for using
fazekasgy@37 124 a Vamp::Feature in Python for anything else than returning
fazekasgy@37 125 values is rather obscure. It's not really worth it. */
fazekasgy@37 126
fazekasgy@37 127 /* Set Attribute: Using wrapped Vamp::Feature
fazekasgy@37 128 static int
fazekasgy@37 129 Feature_setattr(FeatureObject *self, char *name, PyObject *value)
fazekasgy@37 130 {
fazekasgy@37 131 std::string key = std::string(name);
fazekasgy@37 132 if (self->ti.SetValue(*(self->feature),key,value)) return 0;
fazekasgy@37 133 else return -1;
fazekasgy@37 134 }*/
fazekasgy@37 135
fazekasgy@37 136 /* Get Attribute: Using wrapped Vamp::Feature
fazekasgy@37 137 static PyObject *
fazekasgy@37 138 Feature_getattr(FeatureObject *self, char *name)
fazekasgy@37 139 {
fazekasgy@37 140 std::string key = std::string(name);
fazekasgy@37 141 PyObject* pyValue;
fazekasgy@37 142 if (self->ti.GetValue(*(self->feature),key,pyValue))
fazekasgy@37 143 return pyValue;
fazekasgy@37 144 else return NULL;
fazekasgy@37 145 }*/
fazekasgy@37 146
fazekasgy@37 147 /*
fazekasgy@37 148 static int
fazekasgy@37 149 Feature_init(FeatureObject *self, PyObject *args, PyObject *kwds)
fazekasgy@37 150 {
fazekasgy@37 151 cerr << "FeatureObject Init called" << endl;
fazekasgy@37 152 return 0;
fazekasgy@37 153 }
fazekasgy@37 154
fazekasgy@37 155 PyObject*
fazekasgy@37 156 Feature_test(PyObject *self, PyObject *args, PyObject *kwds)
fazekasgy@37 157 {
fazekasgy@37 158 cerr << "FeatureObject TEST called" << endl;
fazekasgy@37 159 return self;
fazekasgy@37 160 }
fazekasgy@37 161 */
fazekasgy@37 162
fazekasgy@37 163 /* String representation */
fazekasgy@37 164 static PyObject *
fazekasgy@37 165 Feature_repr(PyObject *self)
fazekasgy@37 166 {
fazekasgy@37 167 FeatureObject* v = (FeatureObject*)self;
fazekasgy@37 168 if (v->dict) return PyDict_Type.tp_repr((PyObject *)v->dict);
fazekasgy@37 169 else return PyString_FromString("Feature()");
fazekasgy@37 170 }
fazekasgy@37 171
fazekasgy@37 172 #define Feature_alloc PyType_GenericAlloc
fazekasgy@37 173 #define Feature_free PyObject_Del
fazekasgy@37 174
fazekasgy@37 175
fazekasgy@37 176 /* FEATURE TYPE OBJECT */
fazekasgy@37 177
fazekasgy@37 178 PyTypeObject Feature_Type = {
fazekasgy@37 179 PyObject_HEAD_INIT(NULL)
fazekasgy@37 180 0, /*ob_size*/
fazekasgy@37 181 "vampy.Feature", /*tp_name*/
fazekasgy@37 182 sizeof(FeatureObject), /*tp_basicsize*/
fazekasgy@37 183 0, /*tp_itemsize*/
fazekasgy@37 184 (destructor)FeatureObject_dealloc, /*tp_dealloc*/
fazekasgy@37 185 0, /*tp_print*/
fazekasgy@37 186 (getattrfunc)Feature_getattr, /*tp_getattr*/
fazekasgy@37 187 (setattrfunc)Feature_setattr, /*tp_setattr*/
fazekasgy@37 188 0, /*tp_compare*/
fazekasgy@37 189 Feature_repr, /*tp_repr*/
fazekasgy@37 190 0, /*tp_as_number*/
fazekasgy@37 191 0, /*tp_as_sequence*/
fazekasgy@37 192 0, /*tp_as_mapping*/
fazekasgy@37 193 0, /*tp_hash*/
fazekasgy@37 194 0,//Feature_test, /*tp_call*/ // call on an instance
fazekasgy@37 195 0, /*tp_str*/
fazekasgy@37 196 0, /*tp_getattro*/
fazekasgy@37 197 0, /*tp_setattro*/
fazekasgy@37 198 0, /*tp_as_buffer*/
fazekasgy@37 199 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
fazekasgy@37 200 0, /*tp_doc*/
fazekasgy@37 201 0, /*tp_traverse*/
fazekasgy@37 202 0, /*tp_clear*/
fazekasgy@37 203 0, /*tp_richcompare*/
fazekasgy@37 204 0, /*tp_weaklistoffset*/
fazekasgy@37 205 0, /*tp_iter*/
fazekasgy@37 206 0, /*tp_iternext*/
fazekasgy@37 207 0, /*tp_methods*/ //TypeObject Methods
fazekasgy@37 208 0, /*tp_members*/
fazekasgy@37 209 0, /*tp_getset*/
fazekasgy@37 210 0, /*tp_base*/
fazekasgy@37 211 0, /*tp_dict*/
fazekasgy@37 212 0, /*tp_descr_get*/
fazekasgy@37 213 0, /*tp_descr_set*/
fazekasgy@37 214 0, /*tp_dictoffset*/
fazekasgy@37 215 0,//(initproc)Feature_init, /*tp_init*/
fazekasgy@37 216 Feature_alloc, /*tp_alloc*/
fazekasgy@37 217 Feature_new, /*tp_new*/
fazekasgy@37 218 Feature_free, /*tp_free*/
fazekasgy@37 219 0, /*tp_is_gc*/
fazekasgy@37 220 };
fazekasgy@37 221
fazekasgy@37 222 /* PyRealTime C++ API */
fazekasgy@37 223
fazekasgy@37 224 /*Feature* from PyFeature
fazekasgy@37 225 const Vamp::Plugin::Feature*
fazekasgy@37 226 PyFeature_AsFeature (PyObject *self) {
fazekasgy@37 227
fazekasgy@37 228 FeatureObject *s = (FeatureObject*) self;
fazekasgy@37 229
fazekasgy@37 230 if (!PyFeature_Check(s)) {
fazekasgy@37 231 PyErr_SetString(PyExc_TypeError, "Feature Object Expected.");
fazekasgy@37 232 cerr << "in call PyFeature_AsPointer(): Feature Object Expected. " << endl;
fazekasgy@37 233 return NULL; }
fazekasgy@37 234 return s->feature;
fazekasgy@37 235 };*/