mirror of https://github.com/GNOME/gimp.git
1005 lines
27 KiB
C
1005 lines
27 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 2 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, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#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>
|
|
|
|
#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++) {
|
|
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;
|
|
|
|
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(¶ms[i].data.d_color);
|
|
break;
|
|
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_DRAWABLE:
|
|
value = pygimp_drawable_new(NULL, params[i].data.d_drawable);
|
|
break;
|
|
case GIMP_PDB_SELECTION:
|
|
value = pygimp_layer_new(params[i].data.d_selection);
|
|
break;
|
|
case GIMP_PDB_BOUNDARY:
|
|
value = PyInt_FromLong(params[i].data.d_boundary);
|
|
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, *r, *g, *b, *x, *y, *w, *h;
|
|
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");
|
|
return NULL;
|
|
}
|
|
|
|
if (PyTuple_Size(tuple) != nparams) {
|
|
PyErr_SetString(PyExc_TypeError, "wrong number of parameters");
|
|
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);
|
|
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, tmprgb;
|
|
|
|
if (!pygimp_rgb_check(item)) {
|
|
check(!PySequence_Check(item) ||
|
|
PySequence_Length(item) < 3);
|
|
r = PySequence_GetItem(item, 0);
|
|
g = PySequence_GetItem(item, 1);
|
|
b = PySequence_GetItem(item, 2);
|
|
check(!PyInt_Check(r) || !PyInt_Check(g) ||
|
|
!PyInt_Check(b));
|
|
gimp_rgba_set_uchar(&tmprgb, PyInt_AsLong(r),
|
|
PyInt_AsLong(g), PyInt_AsLong(b), 255);
|
|
rgb = &tmprgb;
|
|
} else {
|
|
rgb = pyg_boxed_get(item, GimpRGB);
|
|
}
|
|
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:
|
|
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_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:
|
|
check(!pygimp_layer_check(item));
|
|
ret[i].data.d_selection = ((PyGimpLayer *)item)->ID;
|
|
break;
|
|
case GIMP_PDB_BOUNDARY:
|
|
check(!PyInt_Check(item));
|
|
ret[i].data.d_boundary = PyInt_AsLong(item);
|
|
break;
|
|
case GIMP_PDB_VECTORS:
|
|
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_free(names);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static PyMethodDef pdb_methods[] = {
|
|
{"query", (PyCFunction)pdb_query, METH_VARARGS},
|
|
{NULL, NULL} /* sentinel */
|
|
};
|
|
|
|
/* ---------- */
|
|
|
|
|
|
PyObject *
|
|
pygimp_pdb_new(void)
|
|
{
|
|
PyGimpPDB *self;
|
|
|
|
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 = {
|
|
(inquiry)0, /*mp_length*/
|
|
(binaryfunc)pdb_subscript, /*mp_subscript*/
|
|
(objobjargproc)0, /*mp_ass_subscript*/
|
|
};
|
|
|
|
/* -------------------------------------------------------- */
|
|
|
|
static PyObject *
|
|
pdb_getattro(PyGimpPDB *self, PyObject *attr)
|
|
{
|
|
PyObject *ret;
|
|
|
|
ret = PyObject_GenericGetAttr((PyObject *)self, attr);
|
|
|
|
if (ret)
|
|
return ret;
|
|
|
|
PyErr_Clear();
|
|
|
|
return pygimp_pdb_function_new_from_proc_db(PyString_AsString(attr));
|
|
}
|
|
|
|
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) {
|
|
int 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_EXECUTION_ERROR:
|
|
#if PG_DEBUG > 0
|
|
g_printerr("execution error\n");
|
|
#endif
|
|
gimp_destroy_params(ret, nret);
|
|
PyErr_SetString(PyExc_RuntimeError, "execution error");
|
|
return NULL;
|
|
break;
|
|
|
|
case GIMP_PDB_CALLING_ERROR:
|
|
#if PG_DEBUG > 0
|
|
g_printerr("calling error\n");
|
|
#endif
|
|
gimp_destroy_params(ret, nret);
|
|
PyErr_SetString(PyExc_TypeError, "invalid arguments");
|
|
return NULL;
|
|
break;
|
|
|
|
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;
|
|
|
|
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;
|
|
break;
|
|
}
|
|
|
|
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;
|
|
}
|