gimp/plug-ins/pygimp/pygimp-pdb.c

1111 lines
30 KiB
C

/* -*- Mode: C; c-basic-offset: 4 -*-
* Gimp-Python - allows the writing of Gimp plugins in Python.
* Copyright (C) 1997-2002 James Henstridge <james@daa.com.au>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#define NO_IMPORT_PYGOBJECT
#include <pygobject.h>
#include "pygimp.h"
#define NO_IMPORT_PYGIMPCOLOR
#include "pygimpcolor-api.h"
#include <structmember.h>
#include <glib-object.h>
#include <glib/gprintf.h>
#ifndef PG_DEBUG
# define PG_DEBUG 0
#endif
/* ----------------------------------------------------- */
/* Declarations for objects of type pdb */
typedef struct {
PyObject_HEAD
} PyGimpPDB;
/* ---------------------------------------------------------------- */
/* Declarations for objects of type pdbFunc */
typedef struct {
PyObject_HEAD
char *name;
PyObject *proc_name, *proc_blurb, *proc_help, *proc_author,
*proc_copyright, *proc_date, *proc_type, *py_params,
*py_return_vals;
int nparams, nreturn_vals;
GimpParamDef *params, *return_vals;
} PyGimpPDBFunction;
static PyObject *pygimp_pdb_function_new_from_proc_db(char *name);
/* ---------------------------------------------------------------- */
/* routines to convert between Python tuples and gimp GimpParam's */
#if PG_DEBUG > 0
static void
pygimp_param_print(int nparams, GimpParam *params)
{
int i;
for (i = 0; i < nparams; i++) {
g_printf("param_print: type: %d, PDB_ITEM: %d\n", params[i].type, GIMP_PDB_ITEM);
switch(params[i].type) {
case GIMP_PDB_INT32:
g_printerr("%i. int %i\n", i,
params[i].data.d_int32);
break;
case GIMP_PDB_INT16:
g_printerr("%i. int %i\n", i,
params[i].data.d_int16);
break;
case GIMP_PDB_INT8:
g_printerr("%i. int %u\n", i,
params[i].data.d_int8);
break;
case GIMP_PDB_FLOAT:
g_printerr("%i. float %f\n", i,
params[i].data.d_float);
break;
case GIMP_PDB_STRING:
g_printerr("%i. string %s\n", i,
params[i].data.d_string);
break;
case GIMP_PDB_INT32ARRAY:
case GIMP_PDB_INT16ARRAY:
case GIMP_PDB_INT8ARRAY:
case GIMP_PDB_FLOATARRAY:
case GIMP_PDB_STRINGARRAY:
g_printerr("%i. array of type %i %s\n", i,
params[i].type,
params[i].data.d_int32array == NULL ? "(null)":"");
break;
case GIMP_PDB_STATUS:
g_printerr("%i. status %i\n", i,
params[i].data.d_status);
break;
default:
g_printerr("%i. other %i\n", i,
params[i].data.d_int32);
break;
}
}
}
#endif
PyObject *
pygimp_param_to_tuple(int nparams, const GimpParam *params)
{
PyObject *args, *tmp;
int i, j, n;
args = PyTuple_New(nparams);
for (i = 0; i < nparams && params[i].type != GIMP_PDB_END; i++) {
PyObject *value = NULL;
#if PG_DEBUG > 1
g_printf("param_to_tuple: type: %d, PDB_ITEM: %d\n", params[i].type, GIMP_PDB_ITEM);
#endif
switch(params[i].type) {
case GIMP_PDB_INT32:
value = PyInt_FromLong(params[i].data.d_int32);
break;
case GIMP_PDB_INT16:
value = PyInt_FromLong(params[i].data.d_int16);
break;
case GIMP_PDB_INT8:
value = PyInt_FromLong(params[i].data.d_int8);
break;
case GIMP_PDB_FLOAT:
value = PyFloat_FromDouble(params[i].data.d_float);
break;
case GIMP_PDB_STRING:
if (params[i].data.d_string == NULL) {
Py_INCREF(Py_None);
value = Py_None;
} else
value = PyString_FromString(params[i].data.d_string);
break;
/* For these to work, the previous argument must have
* been an integer
*/
case GIMP_PDB_INT32ARRAY:
if (params[i].data.d_int32array == NULL) {
value = PyTuple_New(0);
break;
}
if ((tmp=PyTuple_GetItem(args, i-1)) == NULL) {
Py_DECREF(args);
return NULL;
}
if (!PyInt_Check(tmp)) {
PyErr_SetString(PyExc_TypeError,
"count type must be integer");
Py_DECREF(args);
return NULL;
}
n = PyInt_AsLong(tmp);
value = PyTuple_New(n);
for (j = 0; j < n; j++)
PyTuple_SetItem(value, j,
PyInt_FromLong(params[i].data.d_int32array[j]));
break;
case GIMP_PDB_INT16ARRAY:
if (params[i].data.d_int16array == NULL) {
value = PyTuple_New(0);
break;
}
if ((tmp=PyTuple_GetItem(args, i-1)) == NULL) {
Py_DECREF(args);
return NULL;
}
if (!PyInt_Check(tmp)) {
PyErr_SetString(PyExc_TypeError,
"count type must be integer");
Py_DECREF(args);
return NULL;
}
n = PyInt_AsLong(tmp);
value = PyTuple_New(n);
for (j = 0; j < n; j++)
PyTuple_SetItem(value, j,
PyInt_FromLong(params[i].data.d_int16array[j]));
break;
case GIMP_PDB_INT8ARRAY:
if (params[i].data.d_int8array == NULL) {
value = PyTuple_New(0);
break;
}
if ((tmp=PyTuple_GetItem(args, i-1)) == NULL) {
Py_DECREF(args);
return NULL;
}
if (!PyInt_Check(tmp)) {
PyErr_SetString(PyExc_TypeError,
"count type must be integer");
Py_DECREF(args);
return NULL;
}
n = PyInt_AsLong(tmp);
value = PyTuple_New(n);
for (j = 0; j < n; j++)
PyTuple_SetItem(value, j,
PyInt_FromLong(params[i].data.d_int8array[j]));
break;
case GIMP_PDB_FLOATARRAY:
if (params[i].data.d_floatarray == NULL) {
value = PyTuple_New(0);
break;
}
if ((tmp=PyTuple_GetItem(args, i-1)) == NULL) {
Py_DECREF(args);
return NULL;
}
if (!PyInt_Check(tmp)) {
PyErr_SetString(PyExc_TypeError,
"count type must be integer");
Py_DECREF(args);
return NULL;
}
n = PyInt_AsLong(tmp);
value = PyTuple_New(n);
for (j = 0; j < n; j++)
PyTuple_SetItem(value, j,
PyFloat_FromDouble(params[i].data.d_floatarray[j]));
break;
case GIMP_PDB_STRINGARRAY:
if (params[i].data.d_stringarray == NULL) {
value = PyTuple_New(0);
break;
}
if ((tmp=PyTuple_GetItem(args, i-1)) == NULL) {
Py_DECREF(args);
return NULL;
}
if (!PyInt_Check(tmp)) {
PyErr_SetString(PyExc_TypeError,
"count type must be integer");
Py_DECREF(args);
return NULL;
}
n = PyInt_AsLong(tmp);
value = PyTuple_New(n);
for (j = 0; j < n; j++)
PyTuple_SetItem(value, j,
params[i].data.d_stringarray[j] ?
PyString_FromString(params[i].data.d_stringarray[j]) :
PyString_FromString(""));
break;
case GIMP_PDB_COLOR:
value = pygimp_rgb_new(&params[i].data.d_color);
break;
/*
GIMP_PDB_REGION is deprecated in libgimpbase/gimpbaseenums.h
and conflicts with GIMP_PDB_ITEM
case GIMP_PDB_REGION:
value = Py_BuildValue("(iiii)",
(int) params[i].data.d_region.x,
(int) params[i].data.d_region.y,
(int) params[i].data.d_region.width,
(int) params[i].data.d_region.height);
break;
*/
case GIMP_PDB_DISPLAY:
value = pygimp_display_new(params[i].data.d_display);
break;
case GIMP_PDB_IMAGE:
value = pygimp_image_new(params[i].data.d_image);
break;
case GIMP_PDB_LAYER:
value = pygimp_layer_new(params[i].data.d_layer);
break;
case GIMP_PDB_CHANNEL:
value = pygimp_channel_new(params[i].data.d_channel);
break;
case GIMP_PDB_ITEM:
value = pygimp_item_new(params[i].data.d_item);
break;
case GIMP_PDB_DRAWABLE:
value = pygimp_drawable_new(NULL, params[i].data.d_drawable);
break;
case GIMP_PDB_SELECTION:
value = pygimp_channel_new(params[i].data.d_selection);
break;
case GIMP_PDB_COLORARRAY:
if (params[i].data.d_colorarray == NULL) {
value = PyTuple_New(0);
break;
}
if ((tmp=PyTuple_GetItem(args, i-1)) == NULL) {
Py_DECREF(args);
return NULL;
}
if (!PyInt_Check(tmp)) {
PyErr_SetString(PyExc_TypeError,
"count type must be integer");
Py_DECREF(args);
return NULL;
}
n = PyInt_AsLong(tmp);
value = PyTuple_New(n);
for (j = 0; j < n; j++)
PyTuple_SetItem(value, j,
pygimp_rgb_new(&params[i].data.d_colorarray[j]));
break;
case GIMP_PDB_VECTORS:
value = pygimp_vectors_new(params[i].data.d_vectors);
break;
case GIMP_PDB_PARASITE:
value = pygimp_parasite_new(gimp_parasite_copy(
&(params[i].data.d_parasite)));
break;
case GIMP_PDB_STATUS:
value = PyInt_FromLong(params[i].data.d_status);
break;
case GIMP_PDB_END:
break;
}
PyTuple_SetItem(args, i, value);
}
return args;
}
GimpParam *
pygimp_param_from_tuple(PyObject *args, const GimpParamDef *ptype, int nparams)
{
PyObject *tuple, *item, *x, *y;
GimpParam *ret;
int i, j, len;
gint32 *i32a; gint16 *i16a; guint8 *i8a; gdouble *fa; gchar **sa;
if (nparams == 0)
tuple = PyTuple_New(0);
else if (!PyTuple_Check(args) && nparams == 1)
tuple = Py_BuildValue("(O)", args);
else {
Py_INCREF(args);
tuple = args;
}
if (!PyTuple_Check(tuple)) {
PyErr_SetString(PyExc_TypeError, "wrong type of parameter");
Py_DECREF(tuple);
return NULL;
}
if (PyTuple_Size(tuple) != nparams) {
PyErr_SetString(PyExc_TypeError, "wrong number of parameters");
Py_DECREF(tuple);
return NULL;
}
ret = g_new(GimpParam, nparams+1);
for (i = 0; i <= nparams; i++)
ret[i].type = GIMP_PDB_STATUS;
#define check(expr) if (expr) { \
PyErr_SetString(PyExc_TypeError, "wrong parameter type"); \
Py_DECREF(tuple); \
gimp_destroy_params(ret, nparams); \
return NULL; \
}
#define arraycheck(expr, ar) if (expr) { \
PyErr_SetString(PyExc_TypeError, "subscript of wrong type"); \
Py_DECREF(tuple); \
gimp_destroy_params(ret, nparams); \
g_free(ar); \
return NULL; \
}
for (i = 1; i <= nparams; i++) {
item = PyTuple_GetItem(tuple, i-1);
#if PG_DEBUG > 1
g_printf("param_from_tuple: type: %d, PDB_ITEM: %d\n", ptype[i-1].type, GIMP_PDB_ITEM);
#endif
switch (ptype[i-1].type) {
case GIMP_PDB_INT32:
check((x = PyNumber_Int(item)) == NULL);
ret[i].data.d_int32 = (gint32)PyInt_AsLong(x);
Py_DECREF(x);
break;
case GIMP_PDB_INT16:
check((x = PyNumber_Int(item)) == NULL);
ret[i].data.d_int16 = (gint16)PyInt_AsLong(x);
Py_DECREF(x);
break;
case GIMP_PDB_INT8:
check((x = PyNumber_Int(item)) == NULL);
ret[i].data.d_int8 = (guint8)PyInt_AsLong(x);
Py_DECREF(x);
break;
case GIMP_PDB_FLOAT:
check((x = PyNumber_Float(item)) == NULL);
ret[i].data.d_float = PyFloat_AsDouble(x);
Py_DECREF(x);
break;
case GIMP_PDB_STRING:
if (item == Py_None) {
ret[i].data.d_string = NULL;
break;
}
check((x = PyObject_Str(item)) == NULL);
ret[i].data.d_string = g_strdup(PyString_AsString(x));
Py_DECREF(x);
break;
case GIMP_PDB_INT32ARRAY:
check(!PySequence_Check(item));
len = PySequence_Length(item);
i32a = g_new(gint32, len);
for (j = 0; j < len; j++) {
x = PySequence_GetItem(item, j);
arraycheck((y=PyNumber_Int(x))==NULL,
i32a);
i32a[j] = PyInt_AsLong(y);
Py_DECREF(y);
}
ret[i].data.d_int32array = i32a;
break;
case GIMP_PDB_INT16ARRAY:
check(!PySequence_Check(item));
len = PySequence_Length(item);
i16a = g_new(gint16, len);
for (j = 0; j < len; j++) {
x = PySequence_GetItem(item, j);
arraycheck((y=PyNumber_Int(x))==NULL,
i16a);
i16a[j] = PyInt_AsLong(y);
Py_DECREF(y);
}
ret[i].data.d_int16array = i16a;
break;
case GIMP_PDB_INT8ARRAY:
check(!PySequence_Check(item));
len = PySequence_Length(item);
i8a = g_new(guint8, len);
for (j = 0; j < len; j++) {
x = PySequence_GetItem(item, j);
arraycheck((y=PyNumber_Int(x))==NULL,
i8a);
i8a[j] = PyInt_AsLong(y);
Py_DECREF(y);
}
ret[i].data.d_int8array = i8a;
break;
case GIMP_PDB_FLOATARRAY:
check(!PySequence_Check(item));
len = PySequence_Length(item);
fa = g_new(gdouble, len);
for (j = 0; j < len; j++) {
x = PySequence_GetItem(item, j);
arraycheck((y=PyNumber_Float(x))==NULL,
fa);
fa[j] = PyFloat_AsDouble(y);
Py_DECREF(y);
}
ret[i].data.d_floatarray = fa;
break;
case GIMP_PDB_STRINGARRAY:
check(!PySequence_Check(item));
len = PySequence_Length(item);
sa = g_new(gchar *, len);
for (j = 0; j < len; j++) {
x = PySequence_GetItem(item, j);
if (x == Py_None) {
sa[j] = NULL;
continue;
}
arraycheck((y=PyObject_Str(x))==NULL,
sa);
sa[j] = g_strdup(PyString_AsString(y));
Py_DECREF(y);
}
ret[i].data.d_stringarray = sa;
break;
case GIMP_PDB_COLOR:
{
GimpRGB rgb;
if (!pygimp_rgb_from_pyobject(item, &rgb)) {
Py_DECREF(tuple);
gimp_destroy_params(ret, nparams);
return NULL;
}
ret[i].data.d_color = rgb;
}
break;
/*
case GIMP_PDB_REGION:
check(!PySequence_Check(item) ||
PySequence_Length(item) < 4);
x = PySequence_GetItem(item, 0);
y = PySequence_GetItem(item, 1);
w = PySequence_GetItem(item, 2);
h = PySequence_GetItem(item, 3);
check(!PyInt_Check(x) || !PyInt_Check(y) ||
!PyInt_Check(w) || !PyInt_Check(h));
ret[i].data.d_region.x = PyInt_AsLong(x);
ret[i].data.d_region.y = PyInt_AsLong(y);
ret[i].data.d_region.width = PyInt_AsLong(w);
ret[i].data.d_region.height = PyInt_AsLong(h);
break;
*/
case GIMP_PDB_DISPLAY:
if (item == Py_None) {
ret[i].data.d_display = -1;
break;
}
check(!pygimp_display_check(item));
ret[i].data.d_display = ((PyGimpDisplay *)item)->ID;
break;
case GIMP_PDB_IMAGE:
if (item == Py_None) {
ret[i].data.d_image = -1;
break;
}
check(!pygimp_image_check(item));
ret[i].data.d_image = ((PyGimpImage *)item)->ID;
break;
case GIMP_PDB_LAYER:
if (item == Py_None) {
ret[i].data.d_layer = -1;
break;
}
check(!pygimp_layer_check(item));
ret[i].data.d_layer = ((PyGimpLayer *)item)->ID;
break;
case GIMP_PDB_CHANNEL:
if (item == Py_None) {
ret[i].data.d_channel = -1;
break;
}
check(!pygimp_channel_check(item));
ret[i].data.d_channel = ((PyGimpChannel *)item)->ID;
break;
case GIMP_PDB_ITEM:
if (item == Py_None) {
ret[i].data.d_channel = -1;
break;
}
check(!pygimp_item_check(item));
ret[i].data.d_item = ((PyGimpItem *)item)->ID;
break;
case GIMP_PDB_DRAWABLE:
if (item == Py_None) {
ret[i].data.d_channel = -1;
break;
}
check(!pygimp_drawable_check(item));
ret[i].data.d_channel = ((PyGimpDrawable *)item)->ID;
break;
case GIMP_PDB_SELECTION:
if (item == Py_None) {
ret[i].data.d_channel = -1;
break;
}
check(!pygimp_channel_check(item));
ret[i].data.d_selection = ((PyGimpChannel *)item)->ID;
break;
case GIMP_PDB_COLORARRAY:
{
GimpRGB *rgb;
check(!PySequence_Check(item));
len = PySequence_Length(item);
rgb = g_new(GimpRGB, len);
for (j = 0; j < len; j++) {
if (!pygimp_rgb_from_pyobject(item, &rgb[j])) {
Py_DECREF(tuple);
g_free(rgb);
gimp_destroy_params(ret, nparams);
return NULL;
}
}
ret[i].data.d_colorarray = rgb;
}
break;
case GIMP_PDB_VECTORS:
if (item == Py_None) {
ret[i].data.d_vectors = -1;
break;
}
check(!pygimp_vectors_check(item));
ret[i].data.d_vectors = ((PyGimpVectors *)item)->ID;
break;
case GIMP_PDB_PARASITE:
/* can't do anything, since size of GimpParasite is not known */
break;
case GIMP_PDB_STATUS:
check(!PyInt_Check(item));
ret[i].data.d_status = PyInt_AsLong(item);
break;
case GIMP_PDB_END:
break;
}
#undef check
#undef arraycheck
ret[i].type = ptype[i-1].type;
}
Py_DECREF(tuple);
return ret;
}
/* ---------------------------------------------------------------- */
static PyObject *
pdb_query(PyGimpPDB *self, PyObject *args)
{
char *n=".*", *b=".*", *h=".*", *a=".*", *c=".*", *d=".*", *t=".*";
int num, i;
char **names;
PyObject *ret;
if (!PyArg_ParseTuple(args, "|zzzzzzz:gimp.pdb.query", &n, &b, &h, &a,
&c, &d, &t))
return NULL;
gimp_procedural_db_query(n, b, h, a, c, d, t, &num, &names);
ret = PyList_New(num);
for (i = 0; i < num; i++)
PyList_SetItem(ret, i, PyString_FromString(names[i]));
g_strfreev(names);
return ret;
}
static PyMethodDef pdb_methods[] = {
{"query", (PyCFunction)pdb_query, METH_VARARGS},
{NULL, NULL} /* sentinel */
};
/* ---------- */
PyObject *
pygimp_pdb_new(void)
{
PyGimpPDB *self = PyObject_NEW(PyGimpPDB, &PyGimpPDB_Type);
if (self == NULL)
return NULL;
return (PyObject *)self;
}
static void
pdb_dealloc(PyGimpPDB *self)
{
PyObject_DEL(self);
}
static PyObject *
pdb_repr(PyGimpPDB *self)
{
return PyString_FromString("<gimp procedural database>");
}
/* Code to access pdb objects as mappings */
static PyObject *
pdb_subscript(PyGimpPDB *self, PyObject *key)
{
PyObject *r;
if (!PyString_Check(key)) {
PyErr_SetString(PyExc_TypeError, "Subscript must be a string");
return NULL;
}
r = (PyObject *)pygimp_pdb_function_new_from_proc_db(PyString_AsString(key));
if (r == NULL) {
PyErr_Clear();
PyErr_SetObject(PyExc_KeyError, key);
}
return r;
}
static PyMappingMethods pdb_as_mapping = {
(lenfunc)0, /*mp_length*/
(binaryfunc)pdb_subscript, /*mp_subscript*/
(objobjargproc)0, /*mp_ass_subscript*/
};
/* -------------------------------------------------------- */
static PyObject *
build_procedure_list(void)
{
int num, i;
char **names, *name, *p;
PyObject *ret;
gimp_procedural_db_query(".*", ".*", ".*", ".*", ".*", ".*", ".*",
&num, &names);
ret = PyList_New(num);
for (i = 0; i < num; i++) {
name = g_strdup(names[i]);
for (p = name; *p != '\0'; p++) {
if (*p == '-')
*p = '_';
}
PyList_SetItem(ret, i, PyString_FromString(name));
}
g_strfreev(names);
return ret;
}
static PyObject *
pdb_getattro(PyGimpPDB *self, PyObject *attr)
{
char *attr_name;
PyObject *ret;
attr_name = PyString_AsString(attr);
if (!attr_name) {
PyErr_Clear();
return PyObject_GenericGetAttr((PyObject *)self, attr);
}
if (attr_name[0] == '_') {
if (!strcmp(attr_name, "__members__")) {
return build_procedure_list();
} else {
return PyObject_GenericGetAttr((PyObject *)self, attr);
}
}
ret = PyObject_GenericGetAttr((PyObject *)self, attr);
if (ret)
return ret;
PyErr_Clear();
return pygimp_pdb_function_new_from_proc_db(attr_name);
}
PyTypeObject PyGimpPDB_Type = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"gimp.PDB", /* tp_name */
sizeof(PyGimpPDB), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)pdb_dealloc, /* tp_dealloc */
(printfunc)0, /* tp_print */
(getattrfunc)0, /* tp_getattr */
(setattrfunc)0, /* tp_setattr */
(cmpfunc)0, /* tp_compare */
(reprfunc)pdb_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
&pdb_as_mapping, /* tp_as_mapping */
(hashfunc)0, /* tp_hash */
(ternaryfunc)0, /* tp_call */
(reprfunc)0, /* tp_str */
(getattrofunc)pdb_getattro, /* tp_getattro */
(setattrofunc)0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
NULL, /* Documentation string */
(traverseproc)0, /* tp_traverse */
(inquiry)0, /* tp_clear */
(richcmpfunc)0, /* tp_richcompare */
0, /* tp_weaklistoffset */
(getiterfunc)0, /* tp_iter */
(iternextfunc)0, /* tp_iternext */
pdb_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
(PyTypeObject *)0, /* tp_base */
(PyObject *)0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)0, /* tp_init */
(allocfunc)0, /* tp_alloc */
(newfunc)0, /* tp_new */
};
/* End of code for pdb objects */
/* -------------------------------------------------------- */
static PyObject *
pygimp_pdb_function_new_from_proc_db(char *name)
{
PyObject *ret;
char *b,*h,*a,*c,*d;
int np, nr;
GimpPDBProcType pt;
GimpParamDef *p, *r;
if (!gimp_procedural_db_proc_info (name, &b, &h, &a, &c, &d, &pt,
&np, &nr, &p, &r)) {
PyErr_SetString(pygimp_error, "procedure not found");
return NULL;
}
ret = pygimp_pdb_function_new(name, b, h, a, c, d, pt, np, nr, p, r);
g_free(b); g_free(h); g_free(a); g_free(c); g_free(d);
return ret;
}
static void
pf_dealloc(PyGimpPDBFunction *self)
{
g_free(self->name);
Py_DECREF(self->proc_name);
Py_DECREF(self->proc_blurb);
Py_DECREF(self->proc_help);
Py_DECREF(self->proc_author);
Py_DECREF(self->proc_copyright);
Py_DECREF(self->proc_date);
Py_DECREF(self->proc_type);
Py_DECREF(self->py_params);
Py_DECREF(self->py_return_vals);
gimp_destroy_paramdefs(self->params, self->nparams);
gimp_destroy_paramdefs(self->return_vals, self->nreturn_vals);
PyObject_DEL(self);
}
#define OFF(x) offsetof(PyGimpPDBFunction, x)
static struct PyMemberDef pf_members[] = {
{"proc_name", T_OBJECT, OFF(proc_name), RO},
{"proc_blurb", T_OBJECT, OFF(proc_blurb), RO},
{"proc_help", T_OBJECT, OFF(proc_help), RO},
{"proc_author", T_OBJECT, OFF(proc_author), RO},
{"proc_copyright", T_OBJECT, OFF(proc_copyright), RO},
{"proc_date", T_OBJECT, OFF(proc_date), RO},
{"proc_type", T_OBJECT, OFF(proc_type), RO},
{"nparams", T_INT, OFF(nparams), RO},
{"nreturn_vals", T_INT, OFF(nreturn_vals), RO},
{"params", T_OBJECT, OFF(py_params), RO},
{"return_vals", T_OBJECT, OFF(py_return_vals), RO},
{NULL} /* Sentinel */
};
#undef OFF
static PyObject *
pf_repr(PyGimpPDBFunction *self)
{
return PyString_FromFormat("<pdb function '%s'>",
PyString_AsString(self->proc_name));
}
static PyObject *
pf_call(PyGimpPDBFunction *self, PyObject *args, PyObject *kwargs)
{
GimpParam *params, *ret;
int nret;
PyObject *t = NULL, *r;
GimpRunMode run_mode = GIMP_RUN_NONINTERACTIVE;
#if PG_DEBUG > 0
g_printerr("--- %s --- ", PyString_AsString(self->proc_name));
#endif
if (kwargs) {
Py_ssize_t len, pos;
PyObject *key, *val;
len = PyDict_Size(kwargs);
if (len == 1) {
pos = 0;
PyDict_Next(kwargs, &pos, &key, &val);
if (!PyString_Check(key)) {
PyErr_SetString(PyExc_TypeError,
"keyword argument name is not a string");
return NULL;
}
if (strcmp(PyString_AsString(key), "run_mode") != 0) {
PyErr_SetString(PyExc_TypeError,
"only 'run_mode' keyword argument accepted");
return NULL;
}
if (pyg_enum_get_value(GIMP_TYPE_RUN_MODE, val, (gpointer)&run_mode))
return NULL;
} else if (len != 0) {
PyErr_SetString(PyExc_TypeError,
"expecting at most one keyword argument");
return NULL;
}
}
if (self->nparams > 0 && !strcmp(self->params[0].name, "run-mode")) {
params = pygimp_param_from_tuple(args, self->params + 1,
self->nparams - 1);
if (params == NULL)
return NULL;
params[0].type = self->params[0].type;
params[0].data.d_int32 = run_mode;
#if PG_DEBUG > 1
pygimp_param_print(self->nparams, params);
#endif
ret = gimp_run_procedure2(self->name, &nret, self->nparams, params);
} else {
params = pygimp_param_from_tuple(args, self->params, self->nparams);
if (params == NULL)
return NULL;
#if PG_DEBUG > 1
pygimp_param_print(self->nparams, params+1);
#endif
ret = gimp_run_procedure2(self->name, &nret, self->nparams, params + 1);
}
gimp_destroy_params(params, self->nparams);
if (!ret) {
PyErr_SetString(pygimp_error, "no status returned");
#if PG_DEBUG >= 1
g_printerr("ret == NULL\n");
#endif
return NULL;
}
switch(ret[0].data.d_status) {
case GIMP_PDB_SUCCESS:
#if PG_DEBUG > 0
g_printerr("success\n");
#endif
t = pygimp_param_to_tuple(nret-1, ret+1);
gimp_destroy_params(ret, nret);
if (t == NULL) {
PyErr_SetString(pygimp_error, "could not make return value");
return NULL;
}
break;
case GIMP_PDB_EXECUTION_ERROR:
#if PG_DEBUG > 0
g_printerr("execution error\n");
#endif
PyErr_SetString(PyExc_RuntimeError, gimp_get_pdb_error());
gimp_destroy_params(ret, nret);
return NULL;
case GIMP_PDB_CALLING_ERROR:
#if PG_DEBUG > 0
g_printerr("calling error\n");
#endif
PyErr_SetString(PyExc_RuntimeError, gimp_get_pdb_error());
gimp_destroy_params(ret, nret);
return NULL;
case GIMP_PDB_CANCEL:
#if PG_DEBUG > 0
g_printerr("cancel\n");
#endif
PyErr_SetString(PyExc_RuntimeError, gimp_get_pdb_error());
gimp_destroy_params(ret, nret);
return NULL;
default:
#if PG_DEBUG > 0
g_printerr("unknown - %i (type %i)\n",
ret[0].data.d_status, ret[0].type);
#endif
PyErr_SetString(pygimp_error, "unknown return code");
return NULL;
}
if (PyTuple_Size(t) == 1) {
r = PyTuple_GetItem(t, 0);
Py_INCREF(r);
Py_DECREF(t);
return r;
}
if (PyTuple_Size(t) == 0) {
r = Py_None;
Py_INCREF(r);
Py_DECREF(t);
return r;
}
return t;
}
PyTypeObject PyGimpPDBFunction_Type = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
"gimp.PDBFunction", /* tp_name */
sizeof(PyGimpPDBFunction), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor)pf_dealloc, /* tp_dealloc */
(printfunc)0, /* tp_print */
(getattrfunc)0, /* tp_getattr */
(setattrfunc)0, /* tp_setattr */
(cmpfunc)0, /* tp_compare */
(reprfunc)pf_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)0, /* tp_hash */
(ternaryfunc)pf_call, /* tp_call */
(reprfunc)0, /* tp_str */
(getattrofunc)0, /* tp_getattro */
(setattrofunc)0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
NULL, /* Documentation string */
(traverseproc)0, /* tp_traverse */
(inquiry)0, /* tp_clear */
(richcmpfunc)0, /* tp_richcompare */
0, /* tp_weaklistoffset */
(getiterfunc)0, /* tp_iter */
(iternextfunc)0, /* tp_iternext */
0, /* tp_methods */
pf_members, /* tp_members */
0, /* tp_getset */
(PyTypeObject *)0, /* tp_base */
(PyObject *)0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)0, /* tp_init */
(allocfunc)0, /* tp_alloc */
(newfunc)0, /* tp_new */
};
PyObject *
pygimp_pdb_function_new(const char *name, const char *blurb, const char *help,
const char *author, const char *copyright,
const char *date, GimpPDBProcType proc_type,
int n_params, int n_return_vals,
GimpParamDef *params, GimpParamDef *return_vals)
{
PyGimpPDBFunction *self;
int i;
self = PyObject_NEW(PyGimpPDBFunction, &PyGimpPDBFunction_Type);
if (self == NULL)
return NULL;
self->name = g_strdup(name);
self->proc_name = PyString_FromString(name ? name : "");
self->proc_blurb = PyString_FromString(blurb ? blurb : "");
self->proc_help = PyString_FromString(help ? help : "");
self->proc_author = PyString_FromString(author ? author : "");
self->proc_copyright = PyString_FromString(copyright ? copyright : "");
self->proc_date = PyString_FromString(date ? date : "");
self->proc_type = PyInt_FromLong(proc_type);
self->nparams = n_params;
self->nreturn_vals = n_return_vals;
self->params = params;
self->return_vals = return_vals;
self->py_params = PyTuple_New(n_params);
for (i = 0; i < n_params; i++)
PyTuple_SetItem(self->py_params, i,
Py_BuildValue("(iss)",
params[i].type,
params[i].name,
params[i].description));
self->py_return_vals = PyTuple_New(n_return_vals);
for (i = 0; i < n_return_vals; i++)
PyTuple_SetItem(self->py_return_vals, i,
Py_BuildValue("(iss)",
return_vals[i].type,
return_vals[i].name,
return_vals[i].description));
return (PyObject *)self;
}