#include "sanepython.h" /* PySANEHandle type */ void PySANEHandle_dealloc(PySANEHandle* self) { if (self->handle) sane_close(self->handle); self->ob_type->tp_free((PyObject*)self); } PyObject* PySANEHandle_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PySANEHandle *self; self = (PySANEHandle *) type->tp_alloc(type, 0); if (self != NULL) { self->handle = NULL; } return (PyObject *)self; } /* Option descriptor methods */ PyObject* PySANEOptionDescriptor_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PySANEOptionDescriptor *self; self = (PySANEOptionDescriptor *) type->tp_alloc(type, 0); if (self != NULL) { self->descriptor = NULL; self->option = 0; self->type = 0; self->unit = 0; self->size = 0; self->name = Py_None; Py_INCREF(Py_None); self->title = Py_None; Py_INCREF(Py_None); self->description = Py_None; Py_INCREF(Py_None); } return (PyObject *)self; } void PySANEOptionDescriptor_dealloc(PySANEOptionDescriptor* self) { Py_DECREF(self->name); Py_DECREF(self->title); Py_DECREF(self->description); self->ob_type->tp_free((PyObject*)self); } PyObject* PySANEOptionDescriptor_FromDescriptor(int option, const SANE_Option_Descriptor *descriptor) { PySANEOptionDescriptor *self; PyObject *constraint; self = (PySANEOptionDescriptor *) PySANEOptionDescriptorType.tp_alloc(&PySANEOptionDescriptorType, 0); if (self != NULL) { self->descriptor = descriptor; self->option = option; self->type = descriptor->type; self->unit = descriptor->unit; self->size = descriptor->size; self->capabilities = descriptor->cap; self->constraintType = descriptor->constraint_type; if (descriptor->name != NULL) self->name = PyString_FromString(descriptor->name); else self->name = PyString_FromString(""); Py_INCREF(self->name); if (descriptor->title != NULL) self->title = PyString_FromString(descriptor->title); else self->title = PyString_FromString(""); Py_INCREF(self->title); if (descriptor->desc != NULL) self->description = PyString_FromString(descriptor->desc); else self->description = PyString_FromString(""); Py_INCREF(self->description); if (self->constraintType == SANE_CONSTRAINT_NONE) constraint = Py_None; else if (self->constraintType == SANE_CONSTRAINT_RANGE) { constraint = PyTuple_New(3); PyTuple_SetItem(constraint, 0, PyInt_FromLong(self->descriptor->constraint.range->min)); PyTuple_SetItem(constraint, 1, PyInt_FromLong(self->descriptor->constraint.range->max)); PyTuple_SetItem(constraint, 2, PyInt_FromLong(self->descriptor->constraint.range->quant)); } else if (self->constraintType == SANE_CONSTRAINT_WORD_LIST) { int i; constraint = PyTuple_New(self->descriptor->constraint.word_list[0]); for (i = 1; i < self->descriptor->constraint.word_list[0]; i++) PyTuple_SetItem(constraint, i, PyInt_FromLong(self->descriptor->constraint.word_list[i])); } else if (self->constraintType == SANE_CONSTRAINT_STRING_LIST) { int i; constraint = PyList_New(0); for (i = 0; self->descriptor->constraint.string_list[i]; i++) PyList_Append(constraint, PyString_FromString(self->descriptor->constraint.string_list[i])); } Py_INCREF(constraint); self->constraint = constraint; } return (PyObject *)self; } PyObject* PySANEOptionDescriptor_get_constraint_word_list(PySANEOptionDescriptor* self) { PyObject *pyret; if (self->descriptor->constraint_type != SANE_CONSTRAINT_WORD_LIST) { pyret = PyList_New(0); } else { pyret = PyList_New(self->descriptor->constraint.word_list[0]); } Py_INCREF(pyret); return pyret; } PyObject* PySANEOptionDescriptor_get_constraint_string_list(PySANEOptionDescriptor* self) { PyObject *pyret; if (self->descriptor->constraint_type != SANE_CONSTRAINT_STRING_LIST) { pyret = PyList_New(0); } else { pyret = PyList_New(0); } Py_INCREF(pyret); return pyret; } PyObject* PySANEOptionDescriptor_get_constraint_range(PySANEOptionDescriptor* self) { PyObject *pyret; if (self->descriptor->constraint_type != SANE_CONSTRAINT_RANGE) { Py_INCREF(Py_None); return Py_None; } pyret = PyTuple_New(3); PyTuple_SetItem(pyret, 0, PyInt_FromLong(self->descriptor->constraint.range->min)); PyTuple_SetItem(pyret, 1, PyInt_FromLong(self->descriptor->constraint.range->max)); PyTuple_SetItem(pyret, 2, PyInt_FromLong(self->descriptor->constraint.range->quant)); Py_INCREF(pyret); return pyret; } PyObject* PySANEOptionDescriptor_str(PySANEOptionDescriptor* self) { PyObject *pyret; char s[1024]; sprintf(s, "", self->option, self->descriptor->name, self->descriptor->title, self->descriptor->desc, self->descriptor->type, self->descriptor->cap, self->descriptor->unit, self->descriptor->size, self->descriptor->constraint_type); pyret = PyString_FromString(s); Py_INCREF(pyret); return pyret; } /* Parameters */ void PySANEParameters_dealloc(PySANEParameters* self) { self->ob_type->tp_free((PyObject*)self); } PyObject* PySANEParameters_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PySANEParameters *self; fprintf(stderr, "params new\n"); self = (PySANEParameters *) type->tp_alloc(type, 0); fprintf(stderr, "params new 2\n"); return (PyObject *)self; } /* The module content */ PyObject* py_sane_init(PyObject *self, PyObject *args) { int status; PyObject *pyret, *authFunc; int version; authFunc = NULL; if (!PyArg_ParseTuple(args, "|iO", &version, &authFunc)) return NULL; if (authFunc) Py_INCREF(authFunc); status = sane_init(&version, NULL); pyret = PyInt_FromLong(status); Py_INCREF(pyret); return pyret; } PyObject* py_sane_strstatus(PyObject *self, PyObject *args) { PyObject *pyret; int statusCode; SANE_String_Const message; if (!PyArg_ParseTuple(args, "i", &statusCode)) return NULL; message = sane_strstatus(statusCode); if (message) pyret = PyString_FromString(message); else pyret = Py_None; Py_INCREF(pyret); return pyret; } PyObject* py_sane_exit(PyObject *self, PyObject *args) { sane_exit(); Py_INCREF(Py_None); return Py_None; } PyObject* py_sane_get_devices(PyObject *self, PyObject *args) { int i; int local; int status; PyObject *deviceList, *pyBool, *deviceTuple, *pyret; const SANE_Device **device_list; if (!PyArg_ParseTuple(args, "|O", &pyBool)) return NULL; local = (pyBool == Py_True); status = sane_get_devices(&device_list, local); pyret = PyTuple_New(2); PyTuple_SetItem(pyret, 0, PyInt_FromLong(status)); if (status == SANE_STATUS_GOOD) { deviceList = PyList_New(0); Py_INCREF(deviceList); for (i = 0; (device_list[i] && device_list[i]->model && device_list[i]->vendor && device_list[i]->name); i++) { deviceTuple = PyTuple_New(3); PyTuple_SetItem(deviceTuple, 0, PyString_FromString(device_list[i]->model)); PyTuple_SetItem(deviceTuple, 1, PyString_FromString(device_list[i]->vendor)); PyTuple_SetItem(deviceTuple, 2, PyString_FromString(device_list[i]->name)); Py_INCREF(deviceTuple); PyList_Append(deviceList, deviceTuple); } PyTuple_SetItem(pyret, 1, deviceList); } else { Py_INCREF(Py_None); PyTuple_SetItem(pyret, 1, Py_None); } return pyret; } PyObject* py_sane_open(PyObject *self, PyObject *args) { int ret; char *name; SANE_Handle sanehandle; PyObject *pyhandle, *pyret, *pyint; if (!PyArg_ParseTuple(args, "s", &name)) return NULL; ret = sane_open(name, &sanehandle); pyret = PyList_New(2); Py_INCREF(pyret); pyint = PyInt_FromLong(ret); Py_INCREF(pyint); PyList_SetItem(pyret, 0, pyint); if (ret == SANE_STATUS_GOOD) { pyhandle = PySANEHandle_new(&PySANEHandleType, NULL, NULL); ((PySANEHandle *) pyhandle)->handle = sanehandle; Py_INCREF(pyhandle); PyList_SetItem(pyret, 1, pyhandle); } else { Py_INCREF(Py_None); PyList_SetItem(pyret, 1, Py_None); } return pyret; } PyObject* py_sane_close(PyObject *self, PyObject *args) { PySANEHandle *pyhandle; if (!PyArg_ParseTuple(args, "O!", &PySANEHandleType, &pyhandle)) return NULL; if (!pyhandle) return NULL; if (pyhandle->handle == NULL) { PyErr_SetObject(PyExc_ValueError, PyString_FromString("handle not open")); return NULL; } sane_close(pyhandle->handle); ((PySANEHandle *) pyhandle)->handle = NULL; Py_INCREF(Py_None); return Py_None; } PyObject* py_sane_get_option_descriptor(PyObject *self, PyObject *args) { int index; const SANE_Option_Descriptor *descriptor; PySANEHandle *pyhandle; PyObject *pyret; if (!PyArg_ParseTuple(args, "O!i", &PySANEHandleType, &pyhandle, &index)) return NULL; if (pyhandle->handle == NULL) { PyErr_SetObject(PyExc_ValueError, PyString_FromString("handle not open")); return NULL; } descriptor = sane_get_option_descriptor(pyhandle->handle, index); if (!descriptor) { char msg[128]; sprintf(msg, "option %d is invalid", index); PyErr_SetObject(PyExc_ValueError, PyString_FromString(msg)); return NULL; } pyret = PySANEOptionDescriptor_FromDescriptor(index, descriptor); Py_INCREF(pyret); return pyret; } PyObject* py_sane_control_option(PyObject *self, PyObject *args) { const SANE_Option_Descriptor *descriptor; int index, action, errors, status, ret; PyObject *pyret, *argValue; PySANEHandle *pyhandle; if (!PyArg_ParseTuple(args, "O!ii|O", &PySANEHandleType, &pyhandle, &index, &action, &argValue)) return NULL; if (pyhandle->handle == NULL) { PyErr_SetObject(PyExc_ValueError, PyString_FromString("handle not open")); return NULL; } descriptor = sane_get_option_descriptor(pyhandle->handle, index); if (descriptor->cap & SANE_CAP_INACTIVE) { char excmsg[128]; sprintf(excmsg, "option %d is inactive", index); PyErr_SetString(PyExc_ValueError, excmsg); return NULL; } pyret = PyTuple_New(3); PyTuple_SetItem(pyret, 0, Py_None); PyTuple_SetItem(pyret, 1, Py_None); PyTuple_SetItem(pyret, 2, Py_None); if (action == SANE_ACTION_GET_VALUE) { if (descriptor->type == SANE_TYPE_INT || descriptor->type == SANE_TYPE_FIXED) { SANE_Int i; ret = sane_control_option(pyhandle->handle, index, action, &i, &status); if (ret == SANE_STATUS_GOOD) PyTuple_SetItem(pyret, 2, PyInt_FromLong(i)); } else if (descriptor->type == SANE_TYPE_BOOL) { SANE_Bool b; ret = sane_control_option(pyhandle->handle, index, action, &b, &status); if (ret == SANE_STATUS_GOOD) if (b == SANE_TRUE) { PyTuple_SetItem(pyret, 2, Py_True); } else { PyTuple_SetItem(pyret, 2, Py_False); } } else if (descriptor->type == SANE_TYPE_STRING) { char s[255]; ret = sane_control_option(pyhandle->handle, index, action, &s, &status); if (ret == SANE_STATUS_GOOD) PyTuple_SetItem(pyret, 2, PyString_FromString(s)); } else if (descriptor->type == SANE_TYPE_GROUP) { PyTuple_SetItem(pyret, 2, Py_None); } } else if (action == SANE_ACTION_SET_VALUE) { if (argValue) { void *pargValue; if (PyNumber_Check(argValue) && descriptor->type == SANE_TYPE_INT) { int i; i = PyInt_AsLong(PyNumber_Int(argValue)); pargValue = (void *) &i; if (descriptor->constraint_type == SANE_CONSTRAINT_RANGE) { if (i < descriptor->constraint.range->min || i > descriptor->constraint.range->max || (descriptor->constraint.range->quant != 0 && i % descriptor->constraint.range->quant) ) { char s[1024]; if (descriptor->constraint.range->quant != 0 && i % descriptor->constraint.range->quant) sprintf(s, "value must be between %d and %d and quantizied with %d", descriptor->constraint.range->min, descriptor->constraint.range->max, descriptor->constraint.range->quant); else sprintf(s, "value must be between %d and %d", descriptor->constraint.range->min, descriptor->constraint.range->max); PyErr_SetObject(PyExc_ValueError, PyString_FromString(s)); return NULL; } } } else if (PyString_Check(argValue) && descriptor->type == SANE_TYPE_STRING) { char *s; s = PyString_AsString(PyObject_Str(argValue)); if (descriptor->constraint_type == SANE_CONSTRAINT_STRING_LIST) { int i; int found; found = 0; for (i = 0; descriptor->constraint.string_list[i]; i++) if (strcmp(descriptor->constraint.string_list[i], s)) found += 1; if (!found) { char msg[1024]; sprintf(msg, "constraint forced"); PyErr_SetObject(PyExc_ValueError, PyString_FromString(msg)); return NULL; } } pargValue = (void *) s; } ret = sane_control_option(pyhandle->handle, index, action, pargValue, &status); } } else if (action == SANE_ACTION_SET_AUTO) { ret = sane_control_option(pyhandle->handle, index, action, NULL, &status); } if (ret >= 0) { PyTuple_SetItem(pyret, 0, PyInt_FromLong(ret)); PyTuple_SetItem(pyret, 1, PyInt_FromLong(status)); } Py_INCREF(pyret); return pyret; } PyObject* py_sane_get_parameters(PyObject *self, PyObject *args) { SANE_Status ret; SANE_Parameters parameters; PyObject *pyret; PySANEHandle *pyhandle; PySANEParameters *pyparams; pyparams = (PySANEParameters *) PySANEParameters_new(&PySANEParametersType, NULL, NULL); if (!PyArg_ParseTuple(args, "O!", &PySANEHandleType, &pyhandle)) return NULL; pyret = PyTuple_New(2); ret = sane_get_parameters(pyhandle->handle, ¶meters); PyTuple_SetItem(pyret, 0, PyInt_FromLong(ret)); if (ret == SANE_STATUS_GOOD) { /* pyparams->format = parameters.format; pyparams->last_frame = parameters.last_frame; pyparams->lines = parameters.lines; pyparams->depth = parameters.depth; pyparams->pixels_per_line = parameters.pixels_per_line; pyparams->bytes_per_line = parameters.bytes_per_line; */ PyTuple_SetItem(pyret, 1, (PyObject *) pyparams); } else PyTuple_SetItem(pyret, 1, Py_None); Py_INCREF(pyret); return pyret; } PyMODINIT_FUNC initsanepython(void) { PyObject* module; if (PyType_Ready(&PySANEHandleType) < 0) return; if (PyType_Ready(&PySANEOptionDescriptorType) < 0) return; module = Py_InitModule3("sanepython", module_methods, "SANE interface for Python."); if (module == NULL) return; PyModule_AddIntConstant(module, "SANE_CURRENT_MAJOR", SANE_CURRENT_MAJOR); PyModule_AddIntConstant(module, "SANE_STATUS_GOOD", SANE_STATUS_GOOD); PyModule_AddIntConstant(module, "SANE_STATUS_NO_MEM", SANE_STATUS_NO_MEM); PyModule_AddIntConstant(module, "SANE_STATUS_DEVICE_BUSY", SANE_STATUS_DEVICE_BUSY); PyModule_AddIntConstant(module, "SANE_STATUS_INVAL", SANE_STATUS_INVAL); PyModule_AddIntConstant(module, "SANE_STATUS_IO_ERROR", SANE_STATUS_IO_ERROR); PyModule_AddIntConstant(module, "SANE_STATUS_ACCESS_DENIED", SANE_STATUS_ACCESS_DENIED); PyModule_AddIntConstant(module, "SANE_ACTION_GET_VALUE", SANE_ACTION_GET_VALUE); PyModule_AddIntConstant(module, "SANE_ACTION_SET_VALUE", SANE_ACTION_SET_VALUE); PyModule_AddIntConstant(module, "SANE_ACTION_SET_AUTO", SANE_ACTION_SET_AUTO); PyModule_AddIntConstant(module, "SANE_TYPE_BOOL", SANE_TYPE_BOOL); PyModule_AddIntConstant(module, "SANE_TYPE_INT", SANE_TYPE_INT); PyModule_AddIntConstant(module, "SANE_TYPE_FIXED", SANE_TYPE_FIXED); PyModule_AddIntConstant(module, "SANE_TYPE_STRING", SANE_TYPE_STRING); PyModule_AddIntConstant(module, "SANE_TYPE_BUTTON", SANE_TYPE_BUTTON); PyModule_AddIntConstant(module, "SANE_TYPE_GROUP", SANE_TYPE_GROUP); PyModule_AddIntConstant(module, "SANE_UNIT_NONE", SANE_UNIT_NONE); PyModule_AddIntConstant(module, "SANE_UNIT_PIXEL", SANE_UNIT_PIXEL); PyModule_AddIntConstant(module, "SANE_UNIT_BIT", SANE_UNIT_BIT); PyModule_AddIntConstant(module, "SANE_UNIT_MM", SANE_UNIT_MM); PyModule_AddIntConstant(module, "SANE_UNIT_DPI", SANE_UNIT_DPI); PyModule_AddIntConstant(module, "SANE_UNIT_PERCENT", SANE_UNIT_PERCENT); PyModule_AddIntConstant(module, "SANE_UNIT_MICROSECOND", SANE_UNIT_MICROSECOND); PyModule_AddIntConstant(module, "SANE_CAP_SOFT_SELECT", SANE_CAP_SOFT_SELECT); PyModule_AddIntConstant(module, "SANE_CAP_HARD_SELECT", SANE_CAP_HARD_SELECT); PyModule_AddIntConstant(module, "SANE_CAP_SOFT_DETECT", SANE_CAP_SOFT_DETECT); PyModule_AddIntConstant(module, "SANE_CAP_EMULATED", SANE_CAP_EMULATED); PyModule_AddIntConstant(module, "SANE_CAP_AUTOMATIC", SANE_CAP_AUTOMATIC); PyModule_AddIntConstant(module, "SANE_CAP_INACTIVE", SANE_CAP_INACTIVE); PyModule_AddIntConstant(module, "SANE_CAP_ADVANCED", SANE_CAP_ADVANCED); PyModule_AddIntConstant(module, "SANE_CONSTRAINT_NONE", SANE_CONSTRAINT_NONE); PyModule_AddIntConstant(module, "SANE_CONSTRAINT_RANGE", SANE_CONSTRAINT_RANGE); PyModule_AddIntConstant(module, "SANE_CONSTRAINT_WORD_LIST", SANE_CONSTRAINT_WORD_LIST); PyModule_AddIntConstant(module, "SANE_CONSTRAINT_STRING_LIST", SANE_CONSTRAINT_STRING_LIST); Py_INCREF(&PySANEHandleType); PyModule_AddObject(module, "SANEHandle", (PyObject *) &PySANEHandleType); PyModule_AddObject(module, "SANEOptionDescriptor", (PyObject *) &PySANEOptionDescriptorType); }