1 /*******************************************************************
2 scanext - Python extension class for SANE
4 Portions (c) Copyright 2007 Hewlett-Packard Development Company, L.P.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 "_sane.c", part of the Python Imaging Library (PIL)
22 http://www.pythonware.com/products/pil/
24 Modified to work without PIL by Don Welch
26 (C) Copyright 2003 A.M. Kuchling. All Rights Reserved
27 (C) Copyright 2004 A.M. Kuchling, Ralph Heinkel All Rights Reserved
29 Permission to use, copy, modify, and distribute this software and its
30 documentation for any purpose and without fee is hereby granted,
31 provided that the above copyright notice appear in all copies and that
32 both that copyright notice and this permission notice appear in
33 supporting documentation, and that the name of A.M. Kuchling and
34 Ralph Heinkel not be used in advertising or publicity pertaining to
35 distribution of the software without specific, written prior permission.
37 A.M. KUCHLING, R.H. HEINKEL DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
38 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
39 IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
40 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
41 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
42 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
43 PERFORMANCE OF THIS SOFTWARE.
45 *******************************************************************/
48 /* _ScanDevice objects */
54 static PyObject *ErrorObject;
58 PyObject_HEAD SANE_Handle h;
65 /* Raise a SANE exception using a SANE_Status code */
66 PyObject *raiseSaneError (SANE_Status st)
70 if (st == SANE_STATUS_GOOD)
76 string = sane_strstatus (st);
77 //PyErr_SetString (ErrorObject, string);
78 PyErr_SetObject(ErrorObject, PyInt_FromLong(st));
82 /* Raise an exception using a character string */
83 PyObject * raiseError(const char * str)
85 PyErr_SetString (ErrorObject, str);
89 /* Raise an exception using a character string */
90 PyObject * raiseDeviceClosedError(void)
92 return raiseError ("_ScanDevice object is closed");
95 static PyObject *getErrorMessage(PyObject * self, PyObject * args)
99 if (!PyArg_ParseTuple (args, "i", &st))
100 raiseError("Invalid arguments.");
102 return Py_BuildValue("s", sane_strstatus (st));
105 staticforward PyTypeObject ScanDevice_type;
107 #define SaneDevObject_Check(v) ((v)->ob_type == &ScanDevice_type)
109 static _ScanDevice *newScanDeviceObject (void)
113 self = PyObject_NEW (_ScanDevice, &ScanDevice_type);
123 /* _ScanDevice methods */
125 static void deAlloc (_ScanDevice * self)
128 sane_close (self->h);
134 static PyObject *closeScan (_ScanDevice * self, PyObject * args)
136 if (!PyArg_ParseTuple (args, ""))
140 sane_close (self->h);
147 static PyObject *getParameters (_ScanDevice * self, PyObject * args)
151 char *format_name = "unknown";
153 if (!PyArg_ParseTuple (args, ""))
154 raiseError("Invalid arguments.");
157 return raiseDeviceClosedError();
159 Py_BEGIN_ALLOW_THREADS
160 st = sane_get_parameters (self->h, &p);
163 if (st != SANE_STATUS_GOOD)
164 return raiseSaneError (st);
168 case (SANE_FRAME_GRAY):
169 format_name = "gray";
171 case (SANE_FRAME_RGB):
172 format_name = "color";
174 case (SANE_FRAME_RED):
177 case (SANE_FRAME_GREEN):
178 format_name = "green";
180 case (SANE_FRAME_BLUE):
181 format_name = "blue";
185 return Py_BuildValue ("isiiiii", p.format, format_name,
186 p.last_frame, p.pixels_per_line,
187 p.lines, p.depth, p.bytes_per_line);
190 static PyObject *startScan (_ScanDevice * self, PyObject * args)
194 if (!PyArg_ParseTuple (args, ""))
195 raiseError("Invalid arguments.");
198 return raiseDeviceClosedError();
200 /* sane_start can take several seconds, if the user initiates
201 a new scan, while the scan head of a flatbed scanner moves
202 back to the start position after finishing a previous scan.
203 Hence it is worth to allow threads here.
205 Py_BEGIN_ALLOW_THREADS
206 st = sane_start (self->h);
209 if (st != SANE_STATUS_GOOD &&
210 st != SANE_STATUS_EOF &&
211 st != SANE_STATUS_NO_DOCS)
212 return raiseSaneError(st);
214 return Py_BuildValue("i", st);
217 static PyObject *cancelScan (_ScanDevice * self, PyObject * args)
219 if (!PyArg_ParseTuple (args, ""))
220 raiseError("Invalid arguments.");
223 return raiseDeviceClosedError();
225 sane_cancel (self->h);
230 static PyObject *getOptions (_ScanDevice * self, PyObject * args)
232 const SANE_Option_Descriptor *d;
233 PyObject *list, *value;
236 if (!PyArg_ParseTuple (args, ""))
237 raiseError("Invalid arguments.");
240 return raiseDeviceClosedError();
242 if (!(list = PyList_New (0)))
243 raiseError("Unable to allocate list.");
247 d = sane_get_option_descriptor (self->h, i);
250 PyObject *constraint = NULL;
253 switch (d->constraint_type)
255 case (SANE_CONSTRAINT_NONE):
257 constraint = Py_None;
259 case (SANE_CONSTRAINT_RANGE):
260 if (d->type == SANE_TYPE_INT)
262 Py_BuildValue ("iii", d->constraint.range->min,
263 d->constraint.range->max,
264 d->constraint.range->quant);
266 constraint = Py_BuildValue ("ddd",
277 case (SANE_CONSTRAINT_WORD_LIST):
278 constraint = PyList_New (d->constraint.word_list[0]);
280 if (d->type == SANE_TYPE_INT)
281 for (j = 1; j <= d->constraint.word_list[0]; j++)
282 PyList_SetItem (constraint, j - 1,
283 PyInt_FromLong (d->constraint.
286 for (j = 1; j <= d->constraint.word_list[0]; j++)
287 PyList_SetItem (constraint, j - 1,
288 PyFloat_FromDouble (SANE_UNFIX
293 case (SANE_CONSTRAINT_STRING_LIST):
294 constraint = PyList_New (0);
296 for (j = 0; d->constraint.string_list[j] != NULL; j++)
297 PyList_Append (constraint,
298 PyString_FromString (d->constraint.
302 value = Py_BuildValue ("isssiiiiO", i, d->name, d->title, d->desc,
303 d->type, d->unit, d->size, d->cap, constraint);
305 PyList_Append (list, value);
314 static PyObject *getOption (_ScanDevice * self, PyObject * args)
317 const SANE_Option_Descriptor *d;
318 PyObject *value = NULL;
322 if (!PyArg_ParseTuple (args, "i", &n))
323 raiseError("Invalid arguments.");
326 return raiseDeviceClosedError();
328 d = sane_get_option_descriptor (self->h, n);
329 v = malloc (d->size + 1);
330 st = sane_control_option (self->h, n, SANE_ACTION_GET_VALUE, v, NULL);
332 if (st != SANE_STATUS_GOOD)
335 return raiseSaneError(st);
340 case (SANE_TYPE_BOOL):
341 case (SANE_TYPE_INT):
342 value = Py_BuildValue ("i", *((SANE_Int *) v));
345 case (SANE_TYPE_FIXED):
346 value = Py_BuildValue ("d", SANE_UNFIX ((*((SANE_Fixed *) v))));
349 case (SANE_TYPE_STRING):
350 value = Py_BuildValue ("s", v);
353 case (SANE_TYPE_BUTTON):
354 case (SANE_TYPE_GROUP):
355 value = Py_BuildValue ("O", Py_None);
363 static PyObject *setOption (_ScanDevice * self, PyObject * args)
366 const SANE_Option_Descriptor *d;
371 if (!PyArg_ParseTuple (args, "iO", &n, &value))
372 raiseError("Invalid arguments.");
375 return raiseDeviceClosedError();
377 d = sane_get_option_descriptor (self->h, n);
380 case (SANE_TYPE_BOOL):
381 if (!PyInt_Check (value))
382 return raiseError("SANE_Bool requires an integer.");
384 SANE_Bool b = PyInt_AsLong(value);
386 if (b != SANE_FALSE && b > SANE_TRUE)
389 st = sane_control_option (self->h, n, SANE_ACTION_SET_VALUE, (void *)&b, &i);
392 case (SANE_TYPE_INT):
393 if (!PyInt_Check (value))
394 return raiseError("SANE_Int requires an integer.");
396 SANE_Int j = PyInt_AsLong (value);
397 st = sane_control_option (self->h, n, SANE_ACTION_SET_VALUE, (void *)&j, &i);
400 case (SANE_TYPE_FIXED):
401 if (!PyFloat_Check (value))
402 return raiseError("SANE_Fixed requires an float.");
404 SANE_Fixed f = SANE_FIX (PyFloat_AsDouble (value));
405 st = sane_control_option (self->h, n, SANE_ACTION_SET_VALUE, (void *)&f, &i);
408 case (SANE_TYPE_STRING):
409 if (!PyString_Check (value))
410 return raiseError("SANE_String requires a a string.");
412 SANE_String s = malloc (d->size + 1);
413 strncpy (s, PyString_AsString (value), d->size - 1);
414 ((SANE_String) s)[d->size - 1] = 0;
415 st = sane_control_option (self->h, n, SANE_ACTION_SET_VALUE, (void *)s, &i);
419 case (SANE_TYPE_BUTTON):
420 case (SANE_TYPE_GROUP):
424 if (st != SANE_STATUS_GOOD)
425 return raiseSaneError(st);
427 return Py_BuildValue ("i", i);
430 static PyObject *setAutoOption (_ScanDevice * self, PyObject * args)
433 const SANE_Option_Descriptor *d;
437 if (!PyArg_ParseTuple (args, "i", &n))
438 raiseError("Invalid arguments.");
441 return raiseDeviceClosedError();
443 d = sane_get_option_descriptor (self->h, n);
444 st = sane_control_option (self->h, n, SANE_ACTION_SET_AUTO, NULL, &i);
446 if (st != SANE_STATUS_GOOD)
447 return raiseSaneError (st);
449 return Py_BuildValue ("i", i);
452 #define MAX_READSIZE 32768
454 static PyObject *readScan (_ScanDevice * self, PyObject * args)
458 SANE_Byte buffer[MAX_READSIZE];
461 if (!PyArg_ParseTuple (args, "i", &bytes_to_read))
462 raiseError("Invalid arguments.");
464 if (bytes_to_read > MAX_READSIZE)
465 return raiseError("bytes_to_read > MAX_READSIZE");
468 return raiseDeviceClosedError();
470 //Py_BEGIN_ALLOW_THREADS
472 st = sane_read (self->h, buffer, bytes_to_read, &len);
473 //Py_END_ALLOW_THREADS
476 if (st != SANE_STATUS_GOOD &&
477 st != SANE_STATUS_EOF &&
478 st != SANE_STATUS_NO_DOCS)
480 sane_cancel(self->h);
482 return raiseSaneError(st);
485 return Py_BuildValue ("(iz#)", st, buffer, len);
489 static PyMethodDef ScanDevice_methods[] = {
490 {"getParameters", (PyCFunction) getParameters, METH_VARARGS},
492 {"getOptions", (PyCFunction) getOptions, METH_VARARGS},
493 {"getOption", (PyCFunction) getOption, METH_VARARGS},
494 {"setOption", (PyCFunction) setOption, METH_VARARGS},
495 {"setAutoOption", (PyCFunction) setAutoOption, METH_VARARGS},
497 {"startScan", (PyCFunction) startScan, METH_VARARGS},
498 {"cancelScan", (PyCFunction) cancelScan, METH_VARARGS},
499 {"readScan", (PyCFunction) readScan, METH_VARARGS},
500 {"closeScan", (PyCFunction) closeScan, METH_VARARGS},
504 static PyObject *getAttr (_ScanDevice * self, char *name)
506 return Py_FindMethod (ScanDevice_methods, (PyObject *) self, name);
509 staticforward PyTypeObject ScanDevice_type = {
510 PyObject_HEAD_INIT (&PyType_Type) 0, /*ob_size */
511 "_ScanDevice", /*tp_name */
512 sizeof (_ScanDevice), /*tp_basicsize */
515 (destructor) deAlloc, /*tp_dealloc */
517 (getattrfunc) getAttr, /*tp_getattr */
522 0, /*tp_as_sequence */
523 0, /*tp_as_mapping */
527 /* --------------------------------------------------------------------- */
529 static void auth_callback (SANE_String_Const resource,
530 SANE_Char * username, SANE_Char * password)
532 printf("auth_callback\n");
535 static PyObject *init (PyObject * self, PyObject * args)
540 if (!PyArg_ParseTuple (args, ""))
541 raiseError("Invalid arguments.");
543 /* XXX Authorization is not yet supported */
544 st = sane_init (&version, auth_callback);
546 if (st != SANE_STATUS_GOOD)
547 return raiseSaneError (st);
549 return Py_BuildValue ("iiii", version, SANE_VERSION_MAJOR (version),
550 SANE_VERSION_MINOR (version),
551 SANE_VERSION_BUILD (version));
557 static PyObject *deInit (PyObject * self, PyObject * args)
559 if (!PyArg_ParseTuple (args, ""))
560 raiseError("Invalid arguments");
567 static PyObject *getDevices (PyObject * self, PyObject * args)
569 const SANE_Device **device_list;
572 int local_only=SANE_FALSE, i;
574 if (!PyArg_ParseTuple (args, "|i", &local_only))
575 raiseError("Invalid arguments");
577 st = sane_get_devices (&device_list, local_only);
579 if (st != SANE_STATUS_GOOD)
580 return raiseSaneError (st);
582 if (!(list = PyList_New (0)))
583 return raiseError("Unable to allocate device list.");
585 for (i=0; device_list[i]; i++)
587 PyList_Append (list, Py_BuildValue ("ssss", device_list[i]->name, device_list[i]->vendor,
588 device_list[i]->model, device_list[i]->type));
594 /* Function returning new _ScanDevice object */
596 static PyObject *openDevice (PyObject * self, PyObject * args)
602 if (!PyArg_ParseTuple (args, "s", &name))
603 raiseError("Invalid arguments");
605 rv = newScanDeviceObject ();
608 return raiseError("Unable to create _ScanDevice object.");
610 st = sane_open (name, &(rv->h));
612 if (st != SANE_STATUS_GOOD)
615 return raiseSaneError (st);
617 return (PyObject *) rv;
620 static PyObject *isOptionActive (PyObject * self, PyObject * args)
625 if (!PyArg_ParseTuple (args, "l", &lg))
626 raiseError("Invalid arguments");
629 return PyInt_FromLong (SANE_OPTION_IS_ACTIVE (cap));
632 static PyObject *isOptionSettable (PyObject * self, PyObject * args)
637 if (!PyArg_ParseTuple (args, "l", &lg))
638 raiseError("Invalid arguments");
641 return PyInt_FromLong (SANE_OPTION_IS_SETTABLE (cap));
645 /* List of functions defined in the module */
647 static PyMethodDef ScanExt_methods[] = {
648 {"init", init, METH_VARARGS},
649 {"deInit", deInit, METH_VARARGS},
650 {"getDevices", getDevices, METH_VARARGS},
651 {"openDevice", openDevice, METH_VARARGS},
652 {"isOptionActive", isOptionActive, METH_VARARGS},
653 {"isOptionSettable", isOptionSettable, METH_VARARGS},
654 {"getErrorMessage", getErrorMessage, METH_VARARGS},
655 {NULL, NULL} /* sentinel */
659 static void insint (PyObject * d, char *name, int value)
661 PyObject *v = PyInt_FromLong ((long) value);
663 if (!v || PyDict_SetItemString (d, name, v))
664 Py_FatalError ("can't initialize sane module");
669 void initscanext (void)
673 /* Create the module and add the functions */
674 m = Py_InitModule ("scanext", ScanExt_methods);
676 /* Add some symbolic constants to the module */
677 d = PyModule_GetDict (m);
678 ErrorObject = PyString_FromString ("scanext.error");
679 PyDict_SetItemString (d, "error", ErrorObject);
681 insint (d, "INFO_INEXACT", SANE_INFO_INEXACT);
682 insint (d, "INFO_RELOAD_OPTIONS", SANE_INFO_RELOAD_OPTIONS);
683 insint (d, "RELOAD_PARAMS", SANE_INFO_RELOAD_PARAMS);
685 insint (d, "FRAME_GRAY", SANE_FRAME_GRAY);
686 insint (d, "FRAME_RGB", SANE_FRAME_RGB);
687 insint (d, "FRAME_RED", SANE_FRAME_RED);
688 insint (d, "FRAME_GREEN", SANE_FRAME_GREEN);
689 insint (d, "FRAME_BLUE", SANE_FRAME_BLUE);
691 insint (d, "CONSTRAINT_NONE", SANE_CONSTRAINT_NONE);
692 insint (d, "CONSTRAINT_RANGE", SANE_CONSTRAINT_RANGE);
693 insint (d, "CONSTRAINT_WORD_LIST", SANE_CONSTRAINT_WORD_LIST);
694 insint (d, "CONSTRAINT_STRING_LIST", SANE_CONSTRAINT_STRING_LIST);
696 insint (d, "TYPE_BOOL", SANE_TYPE_BOOL);
697 insint (d, "TYPE_INT", SANE_TYPE_INT);
698 insint (d, "TYPE_FIXED", SANE_TYPE_FIXED);
699 insint (d, "TYPE_STRING", SANE_TYPE_STRING);
700 insint (d, "TYPE_BUTTON", SANE_TYPE_BUTTON);
701 insint (d, "TYPE_GROUP", SANE_TYPE_GROUP);
703 insint (d, "UNIT_NONE", SANE_UNIT_NONE);
704 insint (d, "UNIT_PIXEL", SANE_UNIT_PIXEL);
705 insint (d, "UNIT_BIT", SANE_UNIT_BIT);
706 insint (d, "UNIT_MM", SANE_UNIT_MM);
707 insint (d, "UNIT_DPI", SANE_UNIT_DPI);
708 insint (d, "UNIT_PERCENT", SANE_UNIT_PERCENT);
709 insint (d, "UNIT_MICROSECOND", SANE_UNIT_MICROSECOND);
711 insint (d, "CAP_SOFT_SELECT", SANE_CAP_SOFT_SELECT);
712 insint (d, "CAP_HARD_SELECT", SANE_CAP_HARD_SELECT);
713 insint (d, "CAP_SOFT_DETECT", SANE_CAP_SOFT_DETECT);
714 insint (d, "CAP_EMULATED", SANE_CAP_EMULATED);
715 insint (d, "CAP_AUTOMATIC", SANE_CAP_AUTOMATIC);
716 insint (d, "CAP_INACTIVE", SANE_CAP_INACTIVE);
717 insint (d, "CAP_ADVANCED", SANE_CAP_ADVANCED);
719 /* handy for checking array lengths: */
720 insint (d, "SANE_WORD_SIZE", sizeof (SANE_Word));
722 /* possible return values of set_option() */
723 insint (d, "INFO_INEXACT", SANE_INFO_INEXACT);
724 insint (d, "INFO_RELOAD_OPTIONS", SANE_INFO_RELOAD_OPTIONS);
725 insint (d, "INFO_RELOAD_PARAMS", SANE_INFO_RELOAD_PARAMS);
728 insint (d, "SANE_STATUS_GOOD", SANE_STATUS_GOOD); //Operation completed succesfully.
729 insint (d, "SANE_STATUS_UNSUPPORTED", SANE_STATUS_UNSUPPORTED); // Operation is not supported.
730 insint (d, "SANE_STATUS_CANCELLED", SANE_STATUS_CANCELLED); //Operation was cancelled.
731 insint (d, "SANE_STATUS_DEVICE_BUSY", SANE_STATUS_DEVICE_BUSY); // Device is busy---retry later.
732 insint (d, "SANE_STATUS_INVAL", SANE_STATUS_INVAL); // Data or argument is invalid.
733 insint (d, "SANE_STATUS_EOF", SANE_STATUS_EOF); // No more data available (end-of-file).
734 insint (d, "SANE_STATUS_JAMMED", SANE_STATUS_JAMMED); // Document feeder jammed.
735 insint (d, "SANE_STATUS_NO_DOCS", SANE_STATUS_NO_DOCS); // Document feeder out of documents.
736 insint (d, "SANE_STATUS_COVER_OPEN", SANE_STATUS_COVER_OPEN); // Scanner cover is open.
737 insint (d, "SANE_STATUS_IO_ERROR", SANE_STATUS_IO_ERROR); // Error during device I/O.
738 insint (d, "SANE_STATUS_NO_MEM", SANE_STATUS_NO_MEM); // Out of memory.
739 insint (d, "SANE_STATUS_ACCESS_DENIED", SANE_STATUS_ACCESS_DENIED); // Access to resource has been denied.
741 // Maximum buffer size for read()
742 insint(d, "MAX_READSIZE", MAX_READSIZE);
744 /* Check for errors */
745 if (PyErr_Occurred ())
746 Py_FatalError ("can't initialize module scanext");