+ goto err;
+ }
+
+ /*
+ * Return an error condition from .wait() when termination is
+ * requested, such that decode() will terminate.
+ */
+ if (di->want_wait_terminate) {
+ srd_dbg("%s: %s: Skip (want_term).", di->inst_id, __func__);
+ goto err;
+ }
+
+ /*
+ * Parse the argument of self.wait() into 'py_conds', and check
+ * the data type. The argument is optional, None is assumed in
+ * its absence. None or an empty dict or an empty list mean that
+ * there is no condition, and the next available sample shall
+ * get returned to the caller.
+ */
+ py_conds = Py_None;
+ if (!PyArg_ParseTuple(args, "|O", &py_conds)) {
+ /* Let Python raise this exception. */
+ goto err;
+ }
+ if (py_conds == Py_None) {
+ /* 'py_conds' is None. */
+ goto ret_9999;
+ } else if (PyList_Check(py_conds)) {
+ /* 'py_conds' is a list. */
+ py_conditionlist = py_conds;
+ num_conditions = PyList_Size(py_conditionlist);
+ if (num_conditions == 0)
+ goto ret_9999; /* The PD invoked self.wait([]). */
+ Py_IncRef(py_conditionlist);
+ } else if (PyDict_Check(py_conds)) {
+ /* 'py_conds' is a dict. */
+ if (PyDict_Size(py_conds) == 0)
+ goto ret_9999; /* The PD invoked self.wait({}). */
+ /* Make a list and put the dict in there for convenience. */
+ py_conditionlist = PyList_New(1);
+ Py_IncRef(py_conds);
+ PyList_SetItem(py_conditionlist, 0, py_conds);
+ num_conditions = 1;
+ } else {
+ srd_err("Condition list is neither a list nor a dict.");
+ goto err;
+ }
+
+ /* Free the old condition list. */
+ condition_list_free(di);
+
+ ret = SRD_OK;
+
+ /* Iterate over the conditions, set di->condition_list accordingly. */
+ for (i = 0; i < num_conditions; i++) {
+ /* Get a condition (dict) from the condition list. */
+ py_dict = PyList_GetItem(py_conditionlist, i);
+ if (!PyDict_Check(py_dict)) {
+ srd_err("Condition is not a dict.");
+ ret = SRD_ERR;
+ break;
+ }
+
+ /* Create the list of terms in this condition. */
+ if ((ret = create_term_list(py_dict, &term_list)) < 0)
+ break;
+
+ /* Add the new condition to the PD instance's condition list. */
+ di->condition_list = g_slist_append(di->condition_list, term_list);
+ }
+
+ Py_DecRef(py_conditionlist);
+
+ PyGILState_Release(gstate);
+
+ return ret;
+
+err:
+ PyGILState_Release(gstate);
+
+ return SRD_ERR;
+
+ret_9999:
+ PyGILState_Release(gstate);
+
+ return 9999;
+}
+
+/**
+ * Create a SKIP condition list for condition-less .wait() calls.
+ *
+ * @param di Decoder instance.
+ * @param count Number of samples to skip.
+ *
+ * @retval SRD_OK The new condition list was set successfully.
+ * @retval SRD_ERR There was an error setting the new condition list.
+ * The contents of di->condition_list are undefined.
+ *
+ * This routine is a reduced and specialized version of the @ref
+ * set_new_condition_list() and @ref create_term_list() routines which
+ * gets invoked when .wait() was called without specifications for
+ * conditions. This minor duplication of the SKIP term list creation
+ * simplifies the logic and avoids the creation of expensive Python
+ * objects with "constant" values which the caller did not pass in the
+ * first place. It results in maximum sharing of match handling code
+ * paths.
+ */
+static int set_skip_condition(struct srd_decoder_inst *di, uint64_t count)
+{
+ struct srd_term *term;
+ GSList *term_list;
+
+ condition_list_free(di);
+ term = g_malloc(sizeof(*term));
+ term->type = SRD_TERM_SKIP;
+ term->num_samples_to_skip = count;
+ term->num_samples_already_skipped = 0;
+ term_list = g_slist_append(NULL, term);
+ di->condition_list = g_slist_append(di->condition_list, term_list);
+
+ return SRD_OK;
+}
+
+static PyObject *Decoder_wait(PyObject *self, PyObject *args)
+{
+ int ret;
+ uint64_t skip_count;
+ unsigned int i;
+ gboolean found_match;
+ struct srd_decoder_inst *di;
+ PyObject *py_pinvalues, *py_matched;
+ PyGILState_STATE gstate;
+
+ if (!self || !args)