X-Git-Url: https://sigrok.org/gitweb/?p=libsigrokdecode.git;a=blobdiff_plain;f=type_decoder.c;h=880dbade0a7697d054308001b1e3a66b988d829c;hp=f2033776e89e8e4ccf42330e19f1e8ab826aaa8c;hb=b66bfd9573bada4d3249e9029e6c6c6112d7b4ac;hpb=514b2edc54efda9c6698456748c4256bb901eddd diff --git a/type_decoder.c b/type_decoder.c index f203377..880dbad 100644 --- a/type_decoder.c +++ b/type_decoder.c @@ -235,7 +235,7 @@ static PyObject *Decoder_put(PyObject *self, PyObject *args) PyObject *py_data, *py_res; struct srd_decoder_inst *di, *next_di; struct srd_pd_output *pdo; - struct srd_proto_data *pdata; + struct srd_proto_data pdata; uint64_t start_sample, end_sample; int output_id; struct srd_pd_callback *cb; @@ -270,22 +270,22 @@ static PyObject *Decoder_put(PyObject *self, PyObject *args) di->inst_id, start_sample, end_sample, output_type_name(pdo->output_type), output_id); - pdata = g_malloc0(sizeof(struct srd_proto_data)); - pdata->start_sample = start_sample; - pdata->end_sample = end_sample; - pdata->pdo = pdo; + pdata.start_sample = start_sample; + pdata.end_sample = end_sample; + pdata.pdo = pdo; + pdata.data = NULL; switch (pdo->output_type) { case SRD_OUTPUT_ANN: /* Annotations are only fed to callbacks. */ if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) { /* Convert from PyDict to srd_proto_data_annotation. */ - if (convert_annotation(di, py_data, pdata) != SRD_OK) { + if (convert_annotation(di, py_data, &pdata) != SRD_OK) { /* An error was already logged. */ break; } Py_BEGIN_ALLOW_THREADS - cb->cb(pdata, cb->cb_data); + cb->cb(&pdata, cb->cb_data); Py_END_ALLOW_THREADS } break; @@ -305,31 +305,31 @@ static PyObject *Decoder_put(PyObject *self, PyObject *args) if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) { /* Frontends aren't really supposed to get Python * callbacks, but it's useful for testing. */ - pdata->data = py_data; - cb->cb(pdata, cb->cb_data); + pdata.data = py_data; + cb->cb(&pdata, cb->cb_data); } break; case SRD_OUTPUT_BINARY: if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) { /* Convert from PyDict to srd_proto_data_binary. */ - if (convert_binary(di, py_data, pdata) != SRD_OK) { + if (convert_binary(di, py_data, &pdata) != SRD_OK) { /* An error was already logged. */ break; } Py_BEGIN_ALLOW_THREADS - cb->cb(pdata, cb->cb_data); + cb->cb(&pdata, cb->cb_data); Py_END_ALLOW_THREADS } 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) { + if (convert_meta(&pdata, py_data) != SRD_OK) { /* An exception was already set up. */ break; } Py_BEGIN_ALLOW_THREADS - cb->cb(pdata, cb->cb_data); + cb->cb(&pdata, cb->cb_data); Py_END_ALLOW_THREADS } break; @@ -341,8 +341,6 @@ static PyObject *Decoder_put(PyObject *self, PyObject *args) PyGILState_Release(gstate); - g_free(pdata); - Py_RETURN_NONE; err: @@ -363,6 +361,9 @@ static PyObject *Decoder_register(PyObject *self, PyObject *args, char *proto_id, *meta_name, *meta_descr; char *keywords[] = {"output_type", "proto_id", "meta", NULL}; PyGILState_STATE gstate; + gboolean is_meta; + GSList *l; + struct srd_pd_output *cmp; gstate = PyGILState_Ensure(); @@ -385,7 +386,8 @@ static PyObject *Decoder_register(PyObject *self, PyObject *args, } /* Check if the meta value's type is supported. */ - if (output_type == SRD_OUTPUT_META) { + is_meta = output_type == SRD_OUTPUT_META; + if (is_meta) { if (meta_type_py == &PyLong_Type) meta_type_gv = G_VARIANT_TYPE_INT64; else if (meta_type_py == &PyFloat_Type) @@ -396,6 +398,28 @@ static PyObject *Decoder_register(PyObject *self, PyObject *args, } } + pdo = NULL; + for (l = di->pd_output; l; l = l->next) { + cmp = l->data; + if (cmp->output_type != output_type) + continue; + if (strcmp(cmp->proto_id, proto_id) != 0) + continue; + if (is_meta && cmp->meta_type != meta_type_gv) + continue; + if (is_meta && strcmp(cmp->meta_name, meta_name) != 0) + continue; + if (is_meta && strcmp(cmp->meta_descr, meta_descr) != 0) + continue; + pdo = cmp; + break; + } + if (pdo) { + py_new_output_id = Py_BuildValue("i", pdo->pdo_id); + PyGILState_Release(gstate); + return py_new_output_id; + } + srd_dbg("Instance %s creating new output type %d for %s.", di->inst_id, output_type, proto_id); @@ -800,7 +824,7 @@ static PyObject *Decoder_wait(PyObject *self, PyObject *args) } else { PyObject_SetAttrString(di->py_inst, "matched", Py_None); } - + py_pinvalues = get_current_pinvalues(di); g_mutex_unlock(&di->data_mutex); @@ -857,9 +881,8 @@ err: */ static PyObject *Decoder_has_channel(PyObject *self, PyObject *args) { - int idx, max_idx; + int idx, count; struct srd_decoder_inst *di; - PyObject *py_channel; PyGILState_STATE gstate; if (!self || !args) @@ -872,24 +895,20 @@ static PyObject *Decoder_has_channel(PyObject *self, PyObject *args) goto err; } - /* Parse the argument of self.has_channel() into 'py_channel'. */ - if (!PyArg_ParseTuple(args, "O", &py_channel)) { + /* + * Get the integer argument of self.has_channel(). Check for + * the range of supported PD input channel numbers. + */ + if (!PyArg_ParseTuple(args, "i", &idx)) { /* Let Python raise this exception. */ goto err; } - if (!PyLong_Check(py_channel)) { - PyErr_SetString(PyExc_Exception, "channel index not a number"); - goto err; - } - - idx = PyLong_AsLong(py_channel); - max_idx = g_slist_length(di->decoder->channels) - + g_slist_length(di->decoder->opt_channels) - 1; - - if (idx < 0 || idx > max_idx) { - srd_err("Invalid channel index %d/%d.", idx, max_idx); - PyErr_SetString(PyExc_Exception, "invalid channel"); + count = g_slist_length(di->decoder->channels) + + g_slist_length(di->decoder->opt_channels); + if (idx < 0 || idx >= count) { + srd_err("Invalid index %d, PD channel count %d.", idx, count); + PyErr_SetString(PyExc_IndexError, "invalid channel index"); goto err; }