X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=type_decoder.c;h=cf7ec8e7c383b40b502201e4034b4b9b98e0a8de;hb=27a86cefb655ecdfb8d912a5388fe8768b264ff5;hp=67cdbb245a33be9502190093a06a5186b2d60460;hpb=e4bea07dd4e58b1b1becdcc5df6aa6fe33205c65;p=libsigrokdecode.git diff --git a/type_decoder.c b/type_decoder.c index 67cdbb2..cf7ec8e 100644 --- a/type_decoder.c +++ b/type_decoder.c @@ -33,7 +33,7 @@ typedef struct { /* This is only used for nicer srd_dbg() output. */ SRD_PRIV const char *output_type_name(unsigned int idx) { - static const char names[][16] = { + static const char *names[] = { "OUTPUT_ANN", "OUTPUT_PYTHON", "OUTPUT_BINARY", @@ -397,7 +397,10 @@ static void release_meta(GVariant *gvar) } PyDoc_STRVAR(Decoder_put_doc, - "Accepts a dictionary with the following keys: startsample, endsample, data" + "Put an annotation for the specified span of samples.\n" + "\n" + "Arguments: start and end sample number, stream id, annotation data.\n" + "Annotation data's layout depends on the output stream type." ); static PyObject *Decoder_put(PyObject *self, PyObject *args) @@ -559,7 +562,7 @@ err: } PyDoc_STRVAR(Decoder_register_doc, - "Register a new output stream" + "Register a new output stream." ); static PyObject *Decoder_register(PyObject *self, @@ -961,7 +964,20 @@ static int set_skip_condition(struct srd_decoder_inst *di, uint64_t count) } PyDoc_STRVAR(Decoder_wait_doc, - "Wait for one or more conditions to occur" + "Wait for one or more conditions to occur.\n" + "\n" + "Returns the sample data at the next position where the condition\n" + "is seen. When the optional condition is missing or empty, the next\n" + "sample number is used. The condition can be a dictionary with one\n" + "condition's details, or a list of dictionaries specifying multiple\n" + "conditions of which at least one condition must be true. Dicts can\n" + "contain one or more key/value pairs, all of which must be true for\n" + "the dict's condition to be considered true. The key either is a\n" + "channel index or a keyword, the value is the operation's parameter.\n" + "\n" + "Supported parameters for channel number keys: 'h', 'l', 'r', 'f',\n" + "or 'e' for level or edge conditions. Other supported keywords:\n" + "'skip' to advance over the given number of samples.\n" ); static PyObject *Decoder_wait(PyObject *self, PyObject *args) @@ -1073,6 +1089,27 @@ static PyObject *Decoder_wait(PyObject *self, PyObject *args) /* Signal the main thread that we handled all samples. */ g_cond_signal(&di->handled_all_samples_cond); + /* + * When EOF was provided externally, communicate the + * Python EOFError exception to .decode() and return + * from the .wait() method call. This is motivated by + * the use of Python context managers, so that .decode() + * methods can "close" incompletely accumulated data + * when the sample data is exhausted. + */ + if (di->communicate_eof) { + /* Advance self.samplenum to the (absolute) last sample number. */ + py_samplenum = PyLong_FromUnsignedLongLong(di->abs_cur_samplenum); + PyObject_SetAttrString(di->py_inst, "samplenum", py_samplenum); + Py_DECREF(py_samplenum); + /* Raise an EOFError Python exception. */ + srd_dbg("%s: %s: Raising EOF from wait().", + di->inst_id, __func__); + g_mutex_unlock(&di->data_mutex); + PyErr_SetString(PyExc_EOFError, "samples exhausted"); + goto err; + } + /* * When termination of wait() and decode() was requested, * then exit the loop after releasing the mutex. @@ -1098,7 +1135,11 @@ err: } PyDoc_STRVAR(Decoder_has_channel_doc, - "Report whether a channel was supplied" + "Check whether input data is supplied for a given channel.\n" + "\n" + "Argument: A channel index.\n" + "Returns: A boolean, True if the channel is connected,\n" + "False if the channel is open (won't see any input data).\n" ); /** @@ -1176,7 +1217,7 @@ static PyMethodDef Decoder_methods[] = { Decoder_has_channel, METH_VARARGS, Decoder_has_channel_doc, }, - {NULL, NULL, 0, NULL} + ALL_ZERO, }; /** @@ -1193,7 +1234,7 @@ SRD_PRIV PyObject *srd_Decoder_type_new(void) { Py_tp_doc, Decoder_doc }, { Py_tp_methods, Decoder_methods }, { Py_tp_new, (void *)&PyType_GenericNew }, - { 0, NULL } + ALL_ZERO, }; PyObject *py_obj; PyGILState_STATE gstate;