diff options
author | Bert Vermeulen <bert@biot.com> | 2013-11-14 00:19:28 +0100 |
---|---|---|
committer | Bert Vermeulen <bert@biot.com> | 2013-11-15 22:05:54 +0100 |
commit | 7ee0c40b4ac605c68a8ec2008ef4ab61a1872475 (patch) | |
tree | ab7dbaf517ff82ecae11b3d61c2b20a9705bf1ee /type_decoder.c | |
parent | 0b9224604aa166775a6693efba215a33ce594b70 (diff) | |
download | libsigrokdecode-7ee0c40b4ac605c68a8ec2008ef4ab61a1872475.tar.gz libsigrokdecode-7ee0c40b4ac605c68a8ec2008ef4ab61a1872475.zip |
Implement OUTPUT_META
This replaces the Decoder.add() method with Decoder.register().
The first argument is still output type, but all arguments are now
optional:
Decoder.register(output_type,
id='someid',
meta=(object-type, 'Name', 'Description'))
'id' defaults to the protocol decoder instance id, and only needs changing
if a decoder chain needs to fork.
'object-type' refers to a Python object, such as int or str.
After registering, the PD submits data as usual with Decoder.put(), with
the only argument a value of the registered object-type.
Diffstat (limited to 'type_decoder.c')
-rw-r--r-- | type_decoder.c | 121 |
1 files changed, 110 insertions, 11 deletions
diff --git a/type_decoder.c b/type_decoder.c index bf4a6b1..52f7ca0 100644 --- a/type_decoder.c +++ b/type_decoder.c @@ -27,6 +27,7 @@ static const char *OUTPUT_TYPES[] = { "OUTPUT_ANN", "OUTPUT_PYTHON", "OUTPUT_BINARY", + "OUTPUT_META", }; static int convert_annotation(struct srd_decoder_inst *di, PyObject *obj, @@ -92,6 +93,36 @@ static int convert_annotation(struct srd_decoder_inst *di, PyObject *obj, return SRD_OK; } +static int convert_meta(struct srd_proto_data *pdata, PyObject *obj) +{ + long long intvalue; + double dvalue; + + if (pdata->pdo->meta_type == G_VARIANT_TYPE_INT64) { + if (!PyLong_Check(obj)) { + PyErr_Format(PyExc_TypeError, "This output was registered " + "as 'int', but '%s' was passed.", obj->ob_type->tp_name); + return SRD_ERR_PYTHON; + } + intvalue = PyLong_AsLongLong(obj); + if (PyErr_Occurred()) + return SRD_ERR_PYTHON; + pdata->data = g_variant_new_int64(intvalue); + } else if (pdata->pdo->meta_type == G_VARIANT_TYPE_DOUBLE) { + if (!PyFloat_Check(obj)) { + PyErr_Format(PyExc_TypeError, "This output was registered " + "as 'float', but '%s' was passed.", obj->ob_type->tp_name); + return SRD_ERR_PYTHON; + } + dvalue = PyFloat_AsDouble(obj); + if (PyErr_Occurred()) + return SRD_ERR_PYTHON; + pdata->data = g_variant_new_double(dvalue); + } + + return SRD_OK; +} + static PyObject *Decoder_put(PyObject *self, PyObject *args) { GSList *l; @@ -170,6 +201,16 @@ static PyObject *Decoder_put(PyObject *self, PyObject *args) case SRD_OUTPUT_BINARY: srd_err("SRD_OUTPUT_BINARY not yet supported."); break; + case SRD_OUTPUT_META: + if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) { + /* Annotations need converting from PyObject. */ + if (convert_meta(pdata, py_data) != SRD_OK) { + /* An exception was already set up. */ + break; + } + cb->cb(pdata, cb->cb_data); + } + break; default: srd_err("Protocol decoder %s submitted invalid output type %d.", di->decoder->name, pdo->output_type); @@ -181,36 +222,94 @@ static PyObject *Decoder_put(PyObject *self, PyObject *args) Py_RETURN_NONE; } -static PyObject *Decoder_add(PyObject *self, PyObject *args) +static PyObject *Decoder_register(PyObject *self, PyObject *args, + PyObject *kwargs) { - PyObject *ret; struct srd_decoder_inst *di; - char *proto_id; - int output_type, pdo_id; + struct srd_pd_output *pdo; + PyObject *py_new_output_id; + PyTypeObject *meta_type_py; + const GVariantType *meta_type_gv; + int output_type; + char *proto_id, *meta_name, *meta_descr; + char *keywords[] = {"output_type", "proto_id", "meta", NULL}; + + meta_type_py = NULL; + meta_type_gv = NULL; + meta_name = meta_descr = NULL; if (!(di = srd_inst_find_by_obj(NULL, self))) { PyErr_SetString(PyExc_Exception, "decoder instance not found"); return NULL; } - if (!PyArg_ParseTuple(args, "is", &output_type, &proto_id)) { + /* Default to instance id, which defaults to class id. */ + proto_id = di->inst_id; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|s(Oss)", keywords, + &output_type, &proto_id, + &meta_type_py, &meta_name, &meta_descr)) { /* Let Python raise this exception. */ return NULL; } - pdo_id = srd_inst_pd_output_add(di, output_type, proto_id); - if (pdo_id < 0) - Py_RETURN_NONE; - else - ret = Py_BuildValue("i", pdo_id); + /* Check if the meta value's type is supported. */ + if (output_type == SRD_OUTPUT_META) { + if (meta_type_py == &PyLong_Type) + meta_type_gv = G_VARIANT_TYPE_INT64; + else if (meta_type_py == &PyFloat_Type) + meta_type_gv = G_VARIANT_TYPE_DOUBLE; + else { + PyErr_Format(PyExc_TypeError, "Unsupported type '%s'.", + meta_type_py->tp_name); + return NULL; + } + } + + srd_dbg("Instance %s creating new output type %d for %s.", + di->inst_id, output_type, proto_id); + + if (!(pdo = g_try_malloc(sizeof(struct srd_pd_output)))) { + PyErr_SetString(PyExc_MemoryError, "struct srd_pd_output"); + return NULL; + } + + /* pdo_id is just a simple index, nothing is deleted from this list anyway. */ + pdo->pdo_id = g_slist_length(di->pd_output); + pdo->output_type = output_type; + pdo->di = di; + pdo->proto_id = g_strdup(proto_id); + + if (output_type == SRD_OUTPUT_META) { + pdo->meta_type = meta_type_gv; + pdo->meta_name = g_strdup(meta_name); + pdo->meta_descr = g_strdup(meta_descr); + } + + di->pd_output = g_slist_append(di->pd_output, pdo); + py_new_output_id = Py_BuildValue("i", pdo->pdo_id); + + return py_new_output_id; +} + +/* TODO: this is just a stub that calls _register() until all PDs + * are changed to use the new register API. */ +static PyObject *Decoder_add(PyObject *self, PyObject *args) +{ + PyObject *py_keywords, *py_new_output_id; + + py_keywords = PyDict_New(); + py_new_output_id = Decoder_register(self, args, py_keywords); + Py_DecRef(py_keywords); - return ret; + return py_new_output_id; } static PyMethodDef Decoder_methods[] = { {"put", Decoder_put, METH_VARARGS, "Accepts a dictionary with the following keys: startsample, endsample, data"}, {"add", Decoder_add, METH_VARARGS, "Create a new output stream"}, + {"register", (PyCFunction)Decoder_register, METH_VARARGS|METH_KEYWORDS, + "Register a new output stream"}, {NULL, NULL, 0, NULL} }; |