return names[MIN(idx, G_N_ELEMENTS(names) - 1)];
}
+static void release_annotation(struct srd_proto_data_annotation *pda)
+{
+ if (!pda)
+ return;
+ if (pda->ann_text)
+ g_strfreev(pda->ann_text);
+ g_free(pda);
+}
+
static int convert_annotation(struct srd_decoder_inst *di, PyObject *obj,
struct srd_proto_data *pdata)
{
return SRD_ERR_PYTHON;
}
+static void release_binary(struct srd_proto_data_binary *pdb)
+{
+ if (!pdb)
+ return;
+ if (pdb->data)
+ g_free((void *)pdb->data);
+ g_free(pdb);
+}
+
static int convert_binary(struct srd_decoder_inst *di, PyObject *obj,
struct srd_proto_data *pdata)
{
return SRD_ERR_PYTHON;
}
+static void release_meta(GVariant *gvar)
+{
+ if (!gvar)
+ return;
+ g_variant_unref(gvar);
+}
+
static PyObject *Decoder_put(PyObject *self, PyObject *args)
{
GSList *l;
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;
PyGILState_STATE gstate;
+ py_data = NULL;
+
gstate = PyGILState_Ensure();
if (!(di = srd_inst_find_by_obj(NULL, self))) {
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
+ release_annotation(pdata.data);
}
break;
case SRD_OUTPUT_PYTHON:
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
+ release_binary(pdata.data);
}
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
+ release_meta(pdata.data);
}
break;
default:
break;
}
- PyGILState_Release(gstate);
+ if (py_data)
+ Py_DECREF(py_data);
- g_free(pdata);
+ PyGILState_Release(gstate);
Py_RETURN_NONE;
err:
+ if (py_data)
+ Py_DECREF(py_data);
+
PyGILState_Release(gstate);
return NULL;
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();
}
/* 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)
}
}
+ 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);
} else {
PyObject_SetAttrString(di->py_inst, "matched", Py_None);
}
-
+
py_pinvalues = get_current_pinvalues(di);
g_mutex_unlock(&di->data_mutex);
*/
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)
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;
}