2 Calf Box, an open source musical instrument.
3 Copyright (C) 2010-2011 Krzysztof Foltman
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "scripting.h"
34 struct cbox_command_target
*target
;
38 PyCboxCallback_New(PyTypeObject
*type
, PyObject
*args
, PyObject
*kwds
)
40 struct PyCboxCallback
*self
;
42 self
= (struct PyCboxCallback
*)type
->tp_alloc(type
, 0);
47 return (PyObject
*)self
;
51 PyCboxCallback_Init(struct PyCboxCallback
*self
, PyObject
*args
, PyObject
*kwds
)
53 PyObject
*cobj
= NULL
;
54 if (!PyArg_ParseTuple(args
, "O!:init", &PyCapsule_Type
, &cobj
))
57 self
->target
= PyCapsule_GetPointer(cobj
, NULL
);
60 static PyObject
*cbox_python_do_cmd_on(struct cbox_command_target
*ct
, PyObject
*self
, PyObject
*args
);
63 PyCboxCallback_Call(PyObject
*_self
, PyObject
*args
, PyObject
*kwds
)
65 struct PyCboxCallback
*self
= (struct PyCboxCallback
*)_self
;
67 return cbox_python_do_cmd_on(self
->target
, _self
, args
);
70 PyTypeObject CboxCallbackType
= {
71 PyObject_HEAD_INIT(NULL
)
72 .tp_name
= "_cbox.Callback",
73 .tp_basicsize
= sizeof(struct PyCboxCallback
),
74 .tp_flags
= Py_TPFLAGS_DEFAULT
,
75 .tp_doc
= "Callback for feedback channel to Cbox C code",
76 .tp_init
= (initproc
)PyCboxCallback_Init
,
77 .tp_new
= PyCboxCallback_New
,
78 .tp_call
= PyCboxCallback_Call
81 static gboolean
set_error_from_python(GError
**error
)
83 PyObject
*ptype
= NULL
, *pvalue
= NULL
, *ptraceback
= NULL
;
84 PyErr_Fetch(&ptype
, &pvalue
, &ptraceback
);
85 PyObject
*ptypestr
= PyObject_Str(ptype
);
86 PyObject
*pvaluestr
= PyObject_Str(pvalue
);
87 PyObject
*ptypestr_unicode
= PyUnicode_AsUTF8String(ptypestr
);
88 PyObject
*pvaluestr_unicode
= PyUnicode_AsUTF8String(pvaluestr
);
89 g_set_error(error
, CBOX_MODULE_ERROR
, CBOX_MODULE_ERROR_FAILED
, "%s: %s", PyBytes_AsString(ptypestr_unicode
), PyBytes_AsString(pvaluestr_unicode
));
90 Py_DECREF(pvaluestr_unicode
);
91 Py_DECREF(ptypestr_unicode
);
92 //g_error("%s:%s", PyString_AsString(ptypestr), PyString_AsString(pvaluestr));
97 Py_XDECREF(ptraceback
);
101 static gboolean
bridge_to_python_callback(struct cbox_command_target
*ct
, struct cbox_command_target
*fb
, struct cbox_osc_command
*cmd
, GError
**error
)
103 PyObject
*callback
= ct
->user_data
;
105 int argc
= strlen(cmd
->arg_types
);
106 PyObject
*arg_values
= PyList_New(argc
);
107 for (int i
= 0; i
< argc
; i
++)
109 if (cmd
->arg_types
[i
] == 's')
111 PyList_SetItem(arg_values
, i
, PyUnicode_FromString(cmd
->arg_values
[i
]));
114 if (cmd
->arg_types
[i
] == 'o')
116 struct cbox_objhdr
*oh
= cmd
->arg_values
[i
];
118 uuid_unparse(oh
->instance_uuid
.uuid
, buf
);
119 PyList_SetItem(arg_values
, i
, PyUnicode_FromString(buf
));
122 if (cmd
->arg_types
[i
] == 'i')
124 PyList_SetItem(arg_values
, i
, PyLong_FromLong(*(int *)cmd
->arg_values
[i
]));
127 if (cmd
->arg_types
[i
] == 'f')
129 PyList_SetItem(arg_values
, i
, PyFloat_FromDouble(*(double *)cmd
->arg_values
[i
]));
132 if (cmd
->arg_types
[i
] == 'b')
134 struct cbox_blob
*blob
= cmd
->arg_values
[i
];
135 PyList_SetItem(arg_values
, i
, PyByteArray_FromStringAndSize(blob
->data
, blob
->size
));
139 PyList_SetItem(arg_values
, i
, Py_None
);
143 struct PyCboxCallback
*fbcb
= NULL
;
145 PyObject
*args
= PyTuple_New(3);
146 PyTuple_SetItem(args
, 0, PyUnicode_FromString(cmd
->command
));
147 PyObject
*pyfb
= NULL
;
150 struct PyCboxCallback
*fbcb
= PyObject_New(struct PyCboxCallback
, &CboxCallbackType
);
152 pyfb
= (PyObject
*)fbcb
;
159 PyTuple_SetItem(args
, 1, pyfb
);
160 PyTuple_SetItem(args
, 2, arg_values
);
162 PyObject
*result
= PyObject_Call(callback
, args
, NULL
);
174 return set_error_from_python(error
);
177 static PyObject
*cbox_python_do_cmd_on(struct cbox_command_target
*ct
, PyObject
*self
, PyObject
*args
)
179 const char *command
= NULL
;
180 PyObject
*callback
= NULL
;
181 PyObject
*list
= NULL
;
182 if (!PyArg_ParseTuple(args
, "sOO!:do_cmd", &command
, &callback
, &PyList_Type
, &list
))
185 int len
= PyList_Size(list
);
186 void *extra
= malloc(len
* sizeof(double));
187 struct cbox_osc_command cmd
;
188 GError
*error
= NULL
;
189 char *arg_types
= malloc(len
+ 1);
190 void **arg_values
= malloc(2 * len
* sizeof(void *));
191 void **arg_extra
= &arg_values
[len
];
192 cmd
.command
= command
;
193 cmd
.arg_types
= arg_types
;
194 cmd
.arg_values
= arg_values
;
195 double *arg_space
= extra
;
196 gboolean free_blobs
= FALSE
;
197 for (int i
= 0; i
< len
; i
++)
199 cmd
.arg_values
[i
] = &arg_space
[i
];
200 PyObject
*value
= PyList_GetItem(list
, i
);
202 if (PyLong_Check(value
))
205 *(int *)arg_values
[i
] = PyLong_AsLong(value
);
208 if (PyFloat_Check(value
))
211 *(double *)arg_values
[i
] = PyFloat_AsDouble(value
);
214 if (PyUnicode_Check(value
))
216 PyObject
*utf8str
= PyUnicode_AsUTF8String(value
);
218 arg_extra
[i
] = utf8str
;
219 arg_values
[i
] = PyBytes_AsString(utf8str
);
222 if (PyByteArray_Check(value
))
224 const void *buf
= PyByteArray_AsString(value
);
225 ssize_t len
= PyByteArray_Size(value
);
229 // note: this is not really acquired, the blob is freed using free and not cbox_blob_destroy
230 struct cbox_blob
*blob
= cbox_blob_new_acquire_data((void *)buf
, len
);
232 arg_values
[i
] = blob
;
240 PyObject
*ob_type
= (PyObject
*)value
->ob_type
;
241 PyObject
*typename_unicode
= PyObject_Str(ob_type
);
242 PyObject
*typename_bytes
= PyUnicode_AsUTF8String(typename_unicode
);
243 g_error("Cannot serialize Python type '%s'", PyBytes_AsString(typename_bytes
));
244 Py_DECREF(typename_bytes
);
245 Py_DECREF(typename_unicode
);
250 arg_types
[len
] = '\0';
252 struct cbox_command_target target
;
253 cbox_command_target_init(&target
, bridge_to_python_callback
, callback
);
255 // cbox_osc_command_dump(&cmd);
257 gboolean result
= ct
->process_cmd(ct
, callback
!= Py_None
? &target
: NULL
, &cmd
, &error
);
262 for (int i
= 0; i
< len
; i
++)
264 if (arg_types
[i
] == 'b')
266 if (arg_types
[i
] == 's')
267 Py_DECREF((PyObject
*)arg_extra
[i
]);
275 return PyErr_Format(PyExc_Exception
, "%s", error
? error
->message
: "Unknown error");
280 static PyObject
*cbox_python_do_cmd(PyObject
*self
, PyObject
*args
)
282 return cbox_python_do_cmd_on(&app
.cmd_target
, self
, args
);
285 static PyMethodDef CboxMethods
[] = {
286 {"do_cmd", cbox_python_do_cmd
, METH_VARARGS
, "Execute a CalfBox command using a global path."},
287 {NULL
, NULL
, 0, NULL
}
290 static PyModuleDef CboxModule
= {
291 PyModuleDef_HEAD_INIT
, "_cbox", NULL
, -1, CboxMethods
,
292 NULL
, NULL
, NULL
, NULL
298 PyObject
*m
= PyModule_Create(&CboxModule
);
299 PyModule_AddObject(m
, "Callback", (PyObject
*)&CboxCallbackType
);
303 void cbox_script_run(const char *name
)
305 FILE *fp
= fopen(name
, "rb");
308 g_warning("Cannot open script file '%s': %s", name
, strerror(errno
));
311 PyImport_AppendInittab("_cbox", &PyInit_cbox
);
313 if (PyType_Ready(&CboxCallbackType
) < 0)
315 g_warning("Cannot install the C callback type");
318 Py_INCREF(&CboxCallbackType
);
320 if (PyRun_SimpleFile(fp
, name
) == 1)
322 GError
*error
= NULL
;
323 set_error_from_python(&error
);
324 cbox_print_error(error
);