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 };*/
|