diff options
Diffstat (limited to 'python/decoder.c')
-rw-r--r-- | python/decoder.c | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/python/decoder.c b/python/decoder.c new file mode 100644 index 0000000..e75ee9f --- /dev/null +++ b/python/decoder.c @@ -0,0 +1,360 @@ +/*------------------------------------------------------------------------ + * Copyright 2009-2010 (c) Jeff Brown <spadix@users.sourceforge.net> + * + * This file is part of the ZBar Bar Code Reader. + * + * The ZBar Bar Code Reader is free software; you can redistribute it + * and/or modify it under the terms of the GNU Lesser Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * The ZBar Bar Code Reader 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 Lesser Public License for more details. + * + * You should have received a copy of the GNU Lesser Public License + * along with the ZBar Bar Code Reader; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + * + * http://sourceforge.net/projects/zbar + *------------------------------------------------------------------------*/ + +#include "zbarmodule.h" + +static char decoder_doc[] = + PyDoc_STR("low level decode of measured bar/space widths.\n" + "\n" + "FIXME."); + +static zbarDecoder *decoder_new(PyTypeObject *type, PyObject *args, + PyObject *kwds) +{ + static char *kwlist[] = { NULL }; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist)) + return (NULL); + + zbarDecoder *self = (zbarDecoder *)type->tp_alloc(type, 0); + if (!self) + return (NULL); + + self->zdcode = zbar_decoder_create(); + zbar_decoder_set_userdata(self->zdcode, self); + if (!self->zdcode) { + Py_DECREF(self); + return (NULL); + } + + return (self); +} + +static int decoder_traverse(zbarDecoder *self, visitproc visit, void *arg) +{ + Py_VISIT(self->handler); + Py_VISIT(self->args); + return (0); +} + +static int decoder_clear(zbarDecoder *self) +{ + zbar_decoder_set_handler(self->zdcode, NULL); + zbar_decoder_set_userdata(self->zdcode, NULL); + Py_CLEAR(self->handler); + Py_CLEAR(self->args); + return (0); +} + +static void decoder_dealloc(zbarDecoder *self) +{ + decoder_clear(self); + zbar_decoder_destroy(self->zdcode); + ((PyObject *)self)->ob_type->tp_free((PyObject *)self); +} + +static zbarEnumItem *decoder_get_color(zbarDecoder *self, void *closure) +{ + zbar_color_t zcol = zbar_decoder_get_color(self->zdcode); + assert(zcol == ZBAR_BAR || zcol == ZBAR_SPACE); + + struct module_state *st = GETMODSTATE(); + zbarEnumItem *color = st->color_enum[zcol]; + Py_INCREF((PyObject *)color); + return (color); +} + +static zbarEnumItem *decoder_get_type(zbarDecoder *self, void *closure) +{ + zbar_symbol_type_t sym = zbar_decoder_get_type(self->zdcode); + if (sym == ZBAR_NONE) { + /* hardcode most common case */ + struct module_state *st = GETMODSTATE(); + Py_INCREF((PyObject *)st->symbol_NONE); + return (st->symbol_NONE); + } + return (zbarSymbol_LookupEnum(sym)); +} + +static PyObject *decoder_get_configs(zbarDecoder *self, void *closure) +{ + struct module_state *st = GETMODSTATE(); + unsigned int sym = zbar_decoder_get_type(self->zdcode); + unsigned int mask = zbar_decoder_get_configs(self->zdcode, sym); + return (zbarEnum_SetFromMask(st->config_enum, mask)); +} + +static PyObject *decoder_get_modifiers(zbarDecoder *self, void *closure) +{ + unsigned int mask = zbar_decoder_get_modifiers(self->zdcode); + struct module_state *st = GETMODSTATE(); + return (zbarEnum_SetFromMask(st->modifier_enum, mask)); +} + +static PyObject *decoder_get_data(zbarDecoder *self, void *closure) +{ +#if PY_MAJOR_VERSION >= 3 + return (PyUnicode_FromStringAndSize(zbar_decoder_get_data(self->zdcode), + zbar_decoder_get_data_length( + self->zdcode))); +#else + return ( + PyString_FromStringAndSize(zbar_decoder_get_data(self->zdcode), + zbar_decoder_get_data_length(self->zdcode))); +#endif +} + +static PyObject *decoder_get_direction(zbarDecoder *self, void *closure) +{ +#if PY_MAJOR_VERSION >= 3 + return (PyLong_FromLong(zbar_decoder_get_direction(self->zdcode))); +#else + return (PyInt_FromLong(zbar_decoder_get_direction(self->zdcode))); +#endif +} + +static PyGetSetDef decoder_getset[] = { + { + "color", + (getter)decoder_get_color, + }, + { + "type", + (getter)decoder_get_type, + }, + { + "configs", + (getter)decoder_get_configs, + }, + { + "modifiers", + (getter)decoder_get_modifiers, + }, + { + "data", + (getter)decoder_get_data, + }, + { "direction", (getter)decoder_get_direction }, + { + NULL, + }, +}; + +static PyObject *decoder_set_config(zbarDecoder *self, PyObject *args, + PyObject *kwds) +{ + zbar_symbol_type_t sym = ZBAR_NONE; + zbar_config_t cfg = ZBAR_CFG_ENABLE; + int val = 1; + static char *kwlist[] = { "symbology", "config", "value", NULL }; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|iii", kwlist, &sym, &cfg, + &val)) + return (NULL); + + if (zbar_decoder_set_config(self->zdcode, sym, cfg, val)) { + PyErr_SetString(PyExc_ValueError, "invalid configuration setting"); + return (NULL); + } + Py_RETURN_NONE; +} + +static PyObject *decoder_get_configs_meth(zbarDecoder *self, PyObject *args, + PyObject *kwds) +{ + zbar_symbol_type_t sym = ZBAR_NONE; + static char *kwlist[] = { "symbology", NULL }; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &sym)) + return (NULL); + + if (sym == ZBAR_NONE) + sym = zbar_decoder_get_type(self->zdcode); + + struct module_state *st = GETMODSTATE(); + unsigned int mask = zbar_decoder_get_configs(self->zdcode, sym); + return (zbarEnum_SetFromMask(st->config_enum, mask)); +} + +static PyObject *decoder_parse_config(zbarDecoder *self, PyObject *args, + PyObject *kwds) +{ + const char *cfg = NULL; + static char *kwlist[] = { "config", NULL }; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &cfg)) + return (NULL); + + if (zbar_decoder_parse_config(self->zdcode, cfg)) { + PyErr_Format(PyExc_ValueError, "invalid configuration setting: %s", + cfg); + return (NULL); + } + Py_RETURN_NONE; +} + +static PyObject *decoder_reset(zbarDecoder *self, PyObject *args, + PyObject *kwds) +{ + static char *kwlist[] = { NULL }; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist)) + return (NULL); + + zbar_decoder_reset(self->zdcode); + Py_RETURN_NONE; +} + +static PyObject *decoder_new_scan(zbarDecoder *self, PyObject *args, + PyObject *kwds) +{ + static char *kwlist[] = { NULL }; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist)) + return (NULL); + + zbar_decoder_new_scan(self->zdcode); + Py_RETURN_NONE; +} + +void decode_handler(zbar_decoder_t *zdcode) +{ + assert(zdcode); + zbarDecoder *self = zbar_decoder_get_userdata(zdcode); + assert(self); + assert(self->zdcode == zdcode); + assert(self->handler); + assert(self->args); + PyObject *junk = PyObject_Call(self->handler, self->args, NULL); + Py_XDECREF(junk); +} + +static PyObject *decoder_set_handler(zbarDecoder *self, PyObject *args, + PyObject *kwds) +{ + PyObject *handler = Py_None; + PyObject *closure = Py_None; + + static char *kwlist[] = { "handler", "closure", NULL }; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &handler, + &closure)) + return (NULL); + + if (handler != Py_None && !PyCallable_Check(handler)) { + PyErr_Format(PyExc_ValueError, "handler %.50s is not callable", + handler->ob_type->tp_name); + return (NULL); + } + Py_CLEAR(self->handler); + Py_CLEAR(self->args); + + if (handler != Py_None) { + self->args = PyTuple_New(2); + if (!self->args) + return (NULL); + Py_INCREF(self); + Py_INCREF(closure); + PyTuple_SET_ITEM(self->args, 0, (PyObject *)self); + PyTuple_SET_ITEM(self->args, 1, closure); + + Py_INCREF(handler); + self->handler = handler; + + zbar_decoder_set_handler(self->zdcode, decode_handler); + } else { + self->handler = self->args = NULL; + zbar_decoder_set_handler(self->zdcode, NULL); + } + Py_RETURN_NONE; +} + +static zbarEnumItem *decoder_decode_width(zbarDecoder *self, PyObject *args, + PyObject *kwds) +{ + unsigned int width = 0; + static char *kwlist[] = { "width", NULL }; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "I", kwlist, &width)) + return (NULL); + + zbar_symbol_type_t sym = zbar_decode_width(self->zdcode, width); + if (PyErr_Occurred()) + /* propagate errors during callback */ + return (NULL); + if (sym == ZBAR_NONE) { + /* hardcode most common case */ + struct module_state *st = GETMODSTATE(); + Py_INCREF((PyObject *)st->symbol_NONE); + return (st->symbol_NONE); + } + return (zbarSymbol_LookupEnum(sym)); +} + +static PyMethodDef decoder_methods[] = { + { + "set_config", + (PyCFunction)decoder_set_config, + METH_VARARGS | METH_KEYWORDS, + }, + { + "get_configs", + (PyCFunction)decoder_get_configs_meth, + METH_VARARGS | METH_KEYWORDS, + }, + { + "parse_config", + (PyCFunction)decoder_parse_config, + METH_VARARGS | METH_KEYWORDS, + }, + { + "reset", + (PyCFunction)decoder_reset, + METH_VARARGS | METH_KEYWORDS, + }, + { + "new_scan", + (PyCFunction)decoder_new_scan, + METH_VARARGS | METH_KEYWORDS, + }, + { + "set_handler", + (PyCFunction)decoder_set_handler, + METH_VARARGS | METH_KEYWORDS, + }, + { + "decode_width", + (PyCFunction)decoder_decode_width, + METH_VARARGS | METH_KEYWORDS, + }, + { + NULL, + }, +}; + +PyTypeObject zbarDecoder_Type = { + PyVarObject_HEAD_INIT(NULL, 0).tp_name = "zbar.Decoder", + + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, + + .tp_doc = decoder_doc, + .tp_basicsize = sizeof(zbarDecoder), + .tp_new = (newfunc)decoder_new, + .tp_traverse = (traverseproc)decoder_traverse, + .tp_clear = (inquiry)decoder_clear, + .tp_dealloc = (destructor)decoder_dealloc, + .tp_getset = decoder_getset, + .tp_methods = decoder_methods, +}; |