Move all decoder instances and callbacks into a session struct
authorBert Vermeulen <bert@biot.com>
Thu, 12 Sep 2013 21:54:43 +0000 (23:54 +0200)
committerBert Vermeulen <bert@biot.com>
Mon, 14 Oct 2013 08:43:16 +0000 (10:43 +0200)
The struct srd_session also holds configuration parameters formerly
passed to srd_session_start().

The new call srd_session_new() takes a pointer where a newly allocated
pointer to struct srd_session will be stored. This pointer must be
passed as the first argument to all functions that require it.

The SRD_CONF_NUM_PROBES, SRD_CONF_UNITSIZE and SRD_CONF_SAMPLERATE
keys must be configured with srd_config_set() before srd_session_start()
is called.

A new call srd_session_destroy() is also available. This cleans up all
resources the session holds. This is also called from srd_exit() for
all sessions.

controller.c
decoder.c
libsigrokdecode-internal.h
libsigrokdecode.h.in
type_decoder.c

index 276dc2dcc686cca61dbff2f914789fc08282f6cf..c6347c0a93b3d7f826ce1172a1d6413d6ec381a9 100644 (file)
@@ -24,6 +24,7 @@
 #include <glib.h>
 #include <inttypes.h>
 #include <stdlib.h>
+#include <stdint.h>
 
 /**
  * @mainpage libsigrokdecode API
  * @{
  */
 
-/* List of decoder instances. */
-static GSList *di_list = NULL;
+/** @cond PRIVATE */
 
-/* List of frontend callbacks to receive decoder output. */
-static GSList *callbacks = NULL;
+SRD_PRIV GSList *sessions = NULL;
+static int max_session_id = -1;
 
-/** @cond PRIVATE */
+static int session_is_valid(struct srd_session *sess);
 
 /* decoder.c */
 extern SRD_PRIV GSList *pd_list;
@@ -137,6 +137,11 @@ SRD_API int srd_init(const char *path)
        int ret;
        char *env_path;
 
+       if (max_session_id != -1) {
+               srd_err("libsigrokdecode is already initialized.");
+               return SRD_ERR;
+       }
+
        srd_dbg("Initializing libsigrokdecode.");
 
        /* Add our own module to the list of built-in modules. */
@@ -167,6 +172,8 @@ SRD_API int srd_init(const char *path)
                }
        }
 
+       max_session_id = 0;
+
        return SRD_OK;
 }
 
@@ -186,8 +193,13 @@ SRD_API int srd_init(const char *path)
  */
 SRD_API int srd_exit(void)
 {
+       GSList *l;
+
        srd_dbg("Exiting libsigrokdecode.");
 
+       for (l = sessions; l; l = l->next)
+               srd_session_destroy((struct srd_session *)l->data);
+
        srd_decoder_unload_all();
        g_slist_free(pd_list);
        pd_list = NULL;
@@ -195,6 +207,8 @@ SRD_API int srd_exit(void)
        /* Py_Finalize() returns void, any finalization errors are ignored. */
        Py_Finalize();
 
+       max_session_id = -1;
+
        return SRD_OK;
 }
 
@@ -508,6 +522,7 @@ SRD_API int srd_inst_probe_set_all(struct srd_decoder_inst *di,
 /**
  * Create a new protocol decoder instance.
  *
+ * @param sess The session holding the protocol decoder instance.
  * @param decoder_id Decoder 'id' field.
  * @param options GHashtable of options which override the defaults set in
  *                the decoder class. May be NULL.
@@ -517,8 +532,8 @@ SRD_API int srd_inst_probe_set_all(struct srd_decoder_inst *di,
  *
  * @since 0.1.0
  */
-SRD_API struct srd_decoder_inst *srd_inst_new(const char *decoder_id,
-               GHashTable *options)
+SRD_API struct srd_decoder_inst *srd_inst_new(struct srd_session *sess,
+               const char *decoder_id, GHashTable *options)
 {
        int i;
        struct srd_decoder *dec;
@@ -527,6 +542,11 @@ SRD_API struct srd_decoder_inst *srd_inst_new(const char *decoder_id,
 
        srd_dbg("Creating new %s instance.", decoder_id);
 
+       if (session_is_valid(sess) != SRD_OK) {
+               srd_err("Invalid session.");
+               return NULL;
+       }
+
        if (!(dec = srd_decoder_get_by_id(decoder_id))) {
                srd_err("Protocol decoder %s not found.", decoder_id);
                return NULL;
@@ -538,6 +558,7 @@ SRD_API struct srd_decoder_inst *srd_inst_new(const char *decoder_id,
        }
 
        di->decoder = dec;
+       di->sess = sess;
        if (options) {
                inst_id = g_hash_table_lookup(options, "id");
                di->inst_id = g_strdup(inst_id ? inst_id : decoder_id);
@@ -579,7 +600,7 @@ SRD_API struct srd_decoder_inst *srd_inst_new(const char *decoder_id,
        }
 
        /* Instance takes input from a frontend by default. */
-       di_list = g_slist_append(di_list, di);
+       sess->di_list = g_slist_append(sess->di_list, di);
 
        return di;
 }
@@ -587,6 +608,7 @@ SRD_API struct srd_decoder_inst *srd_inst_new(const char *decoder_id,
 /**
  * Stack a decoder instance on top of another.
  *
+ * @param sess The session holding the protocol decoder instances.
  * @param di_from The instance to move.
  * @param di_to The instance on top of which di_from will be stacked.
  *
@@ -594,17 +616,23 @@ SRD_API struct srd_decoder_inst *srd_inst_new(const char *decoder_id,
  *
  * @since 0.1.0
  */
-SRD_API int srd_inst_stack(struct srd_decoder_inst *di_from,
-               struct srd_decoder_inst *di_to)
+SRD_API int srd_inst_stack(struct srd_session *sess,
+               struct srd_decoder_inst *di_from, struct srd_decoder_inst *di_to)
 {
+
+       if (session_is_valid(sess) != SRD_OK) {
+               srd_err("Invalid session.");
+               return SRD_ERR_ARG;
+       }
+
        if (!di_from || !di_to) {
                srd_err("Invalid from/to instance pair.");
                return SRD_ERR_ARG;
        }
 
-       if (g_slist_find(di_list, di_to)) {
+       if (g_slist_find(sess->di_list, di_to)) {
                /* Remove from the unstacked list. */
-               di_list = g_slist_remove(di_list, di_to);
+               sess->di_list = g_slist_remove(sess->di_list, di_to);
        }
 
        /* Stack on top of source di. */
@@ -619,19 +647,26 @@ SRD_API int srd_inst_stack(struct srd_decoder_inst *di_from,
  * Only the bottom level of instances are searched -- instances already stacked
  * on top of another one will not be found.
  *
+ * @param sess The session holding the protocol decoder instance.
  * @param inst_id The instance ID to be found.
  *
  * @return Pointer to struct srd_decoder_inst, or NULL if not found.
  *
  * @since 0.1.0
  */
-SRD_API struct srd_decoder_inst *srd_inst_find_by_id(const char *inst_id)
+SRD_API struct srd_decoder_inst *srd_inst_find_by_id(struct srd_session *sess,
+               const char *inst_id)
 {
        GSList *l;
        struct srd_decoder_inst *tmp, *di;
 
+       if (session_is_valid(sess) != SRD_OK) {
+               srd_err("Invalid session.");
+               return NULL;
+       }
+
        di = NULL;
-       for (l = di_list; l; l = l->next) {
+       for (l = sess->di_list; l; l = l->next) {
                tmp = l->data;
                if (!strcmp(tmp->inst_id, inst_id)) {
                        di = tmp;
@@ -642,11 +677,36 @@ SRD_API struct srd_decoder_inst *srd_inst_find_by_id(const char *inst_id)
        return di;
 }
 
+static struct srd_decoder_inst *srd_sess_inst_find_by_obj(
+               struct srd_session *sess, const GSList *stack,
+               const PyObject *obj)
+{
+       const GSList *l;
+       struct srd_decoder_inst *tmp, *di;
+
+       if (session_is_valid(sess) != SRD_OK) {
+               srd_err("Invalid session.");
+               return NULL;
+       }
+
+       di = NULL;
+       for (l = stack ? stack : sess->di_list; di == NULL && l != NULL; l = l->next) {
+               tmp = l->data;
+               if (tmp->py_inst == obj)
+                       di = tmp;
+               else if (tmp->next_di)
+                       di = srd_sess_inst_find_by_obj(sess, tmp->next_di, obj);
+       }
+
+       return di;
+}
+
 /**
  * Find a decoder instance by its Python object.
  *
  * I.e. find that instance's instantiation of the sigrokdecode.Decoder class.
- * This will recurse to find the instance anywhere in the stack tree.
+ * This will recurse to find the instance anywhere in the stack tree of all
+ * sessions.
  *
  * @param stack Pointer to a GSList of struct srd_decoder_inst, indicating the
  *              stack to search. To start searching at the bottom level of
@@ -662,16 +722,14 @@ SRD_API struct srd_decoder_inst *srd_inst_find_by_id(const char *inst_id)
 SRD_PRIV struct srd_decoder_inst *srd_inst_find_by_obj(const GSList *stack,
                const PyObject *obj)
 {
-       const GSList *l;
-       struct srd_decoder_inst *tmp, *di;
+       struct srd_decoder_inst *di;
+       struct srd_session *sess;
+       GSList *l;
 
        di = NULL;
-       for (l = stack ? stack : di_list; di == NULL && l != NULL; l = l->next) {
-               tmp = l->data;
-               if (tmp->py_inst == obj)
-                       di = tmp;
-               else if (tmp->next_di)
-                       di = srd_inst_find_by_obj(tmp->next_di, obj);
+       for (l = sessions; di == NULL && l != NULL; l = l->next) {
+               sess = l->data;
+               di = srd_sess_inst_find_by_obj(sess, stack, obj);
        }
 
        return di;
@@ -807,21 +865,26 @@ SRD_PRIV void srd_inst_free(struct srd_decoder_inst *di)
 }
 
 /** @private */
-SRD_PRIV void srd_inst_free_all(GSList *stack)
+SRD_PRIV void srd_inst_free_all(struct srd_session *sess, GSList *stack)
 {
        GSList *l;
        struct srd_decoder_inst *di;
 
+       if (session_is_valid(sess) != SRD_OK) {
+               srd_err("Invalid session.");
+               return;
+       }
+
        di = NULL;
-       for (l = stack ? stack : di_list; di == NULL && l != NULL; l = l->next) {
+       for (l = stack ? stack : sess->di_list; di == NULL && l != NULL; l = l->next) {
                di = l->data;
                if (di->next_di)
-                       srd_inst_free_all(di->next_di);
+                       srd_inst_free_all(sess, di->next_di);
                srd_inst_free(di);
        }
        if (!stack) {
-               g_slist_free(di_list);
-               di_list = NULL;
+               g_slist_free(sess->di_list);
+               sess->di_list = NULL;
        }
 }
 
@@ -835,46 +898,107 @@ SRD_PRIV void srd_inst_free_all(GSList *stack)
  * @{
  */
 
+static int session_is_valid(struct srd_session *sess)
+{
+
+       if (!sess || sess->session_id < 1)
+               return SRD_ERR;
+
+       return SRD_OK;
+}
+
+/**
+ * Create a decoding session.
+ *
+ * A session holds all decoder instances, their stack relationships and
+ * output callbacks.
+ *
+ * @param sess. A pointer which will hold a pointer to a newly
+ *              initialized session on return.
+ *
+ * @return SRD_OK upon success, a (negative) error code otherwise.
+ *
+ * @since 0.3.0
+ */
+SRD_API int srd_session_new(struct srd_session **sess)
+{
+
+       if (!sess) {
+               srd_err("Invalid session pointer.");
+               return SRD_ERR;
+       }
+
+       if (!(*sess = g_try_malloc(sizeof(struct srd_session))))
+               return SRD_ERR_MALLOC;
+       (*sess)->session_id = ++max_session_id;
+       (*sess)->num_probes = (*sess)->unitsize = (*sess)->samplerate = 0;
+       (*sess)->di_list = (*sess)->callbacks = NULL;
+
+       /* Keep a list of all sessions, so we can clean up as needed. */
+       sessions = g_slist_append(sessions, *sess);
+
+       srd_dbg("Created session %d.", (*sess)->session_id);
+
+       return SRD_OK;
+}
+
 /**
  * Start a decoding session.
  *
- * Decoders, instances and stack must have been prepared beforehand.
+ * Decoders, instances and stack must have been prepared beforehand,
+ * and all SRD_CONF parameters set.
  *
- * @param num_probes The number of probes which the incoming feed will contain.
- * @param unitsize The number of bytes per sample in the incoming feed.
- * @param samplerate The samplerate of the incoming feed.
+ * @param sess The session to start.
  *
  * @return SRD_OK upon success, a (negative) error code otherwise.
  *
  * @since 0.1.0
  */
-SRD_API int srd_session_start(int num_probes, int unitsize, uint64_t samplerate)
+SRD_API int srd_session_start(struct srd_session *sess)
 {
        PyObject *args;
        GSList *d;
        struct srd_decoder_inst *di;
        int ret;
 
+       if (session_is_valid(sess) != SRD_OK) {
+               srd_err("Invalid session pointer.");
+               return SRD_ERR;
+       }
+       if (sess->num_probes == 0) {
+               srd_err("Session has invalid number of probes.");
+               return SRD_ERR;
+       }
+       if (sess->unitsize == 0) {
+               srd_err("Session has invalid unitsize.");
+               return SRD_ERR;
+       }
+       if (sess->samplerate == 0) {
+               srd_err("Session has invalid samplerate.");
+               return SRD_ERR;
+       }
+
        ret = SRD_OK;
 
-       srd_dbg("Calling start() on all instances with %d probes, "
-               "unitsize %d samplerate %d.", num_probes, unitsize, samplerate);
+       srd_dbg("Calling start() on all instances in session %d with "
+                       "%d probes, unitsize %d samplerate %d.", sess->session_id,
+                       sess->num_probes, sess->unitsize, sess->samplerate);
 
        /*
         * Currently only one item of metadata is passed along to decoders,
         * samplerate. This can be extended as needed.
         */
-       if (!(args = Py_BuildValue("{s:l}", "samplerate", (long)samplerate))) {
+       if (!(args = Py_BuildValue("{s:l}", "samplerate", (long)sess->samplerate))) {
                srd_err("Unable to build Python object for metadata.");
                return SRD_ERR_PYTHON;
        }
 
        /* Run the start() method on all decoders receiving frontend data. */
-       for (d = di_list; d; d = d->next) {
+       for (d = sess->di_list; d; d = d->next) {
                di = d->data;
-               di->data_num_probes = num_probes;
-               di->data_unitsize = unitsize;
-               di->data_samplerate = samplerate;
+               di->data_num_probes = sess->num_probes;
+               di->data_unitsize = sess->unitsize;
+               di->data_samplerate = sess->samplerate;
                if ((ret = srd_inst_start(di, args)) != SRD_OK)
                        break;
        }
@@ -884,9 +1008,54 @@ SRD_API int srd_session_start(int num_probes, int unitsize, uint64_t samplerate)
        return ret;
 }
 
+/**
+ * Set a configuration key in a session.
+ *
+ * @param sess The session to configure.
+ * @param key The configuration key (SRD_CONF_*).
+ * @param data The new value for the key, as a GVariant with GVariantType
+ *             appropriate to that key. A floating reference can be passed
+ *             in; its refcount will be sunk and unreferenced after use.
+ *
+ * @return SRD_OK upon success, a (negative) error code otherwise.
+ *
+ * @since 0.3.0
+ */
+SRD_API int srd_session_config_set(struct srd_session *sess, int key,
+               GVariant *data)
+{
+
+       if (session_is_valid(sess) != SRD_OK) {
+               srd_err("Invalid session.");
+               return SRD_ERR_ARG;
+       }
+
+       if (!g_variant_is_of_type(data, G_VARIANT_TYPE_UINT64)) {
+               srd_err("Value for key %d should be of type uint64.");
+               return SRD_ERR_ARG;
+       }
+
+       switch (key) {
+       case SRD_CONF_NUM_PROBES:
+               sess->num_probes = g_variant_get_uint64(data);
+               break;
+       case SRD_CONF_UNITSIZE:
+               sess->unitsize = g_variant_get_uint64(data);
+               break;
+       case SRD_CONF_SAMPLERATE:
+               sess->samplerate = g_variant_get_uint64(data);
+               break;
+       }
+
+       g_variant_unref(data);
+
+       return SRD_OK;
+}
+
 /**
  * Send a chunk of logic sample data to a running decoder session.
  *
+ * @param sess The session to use.
  * @param start_samplenum The sample number of the first sample in this chunk.
  * @param inbuf Pointer to sample data.
  * @param inbuflen Length in bytes of the buffer.
@@ -895,17 +1064,22 @@ SRD_API int srd_session_start(int num_probes, int unitsize, uint64_t samplerate)
  *
  * @since 0.1.0
  */
-SRD_API int srd_session_send(uint64_t start_samplenum, const uint8_t *inbuf,
-               uint64_t inbuflen)
+SRD_API int srd_session_send(struct srd_session *sess, uint64_t start_samplenum,
+               const uint8_t *inbuf, uint64_t inbuflen)
 {
        GSList *d;
        int ret;
 
+       if (session_is_valid(sess) != SRD_OK) {
+               srd_err("Invalid session.");
+               return SRD_ERR_ARG;
+       }
+
        srd_dbg("Calling decode() on all instances with starting sample "
                "number %" PRIu64 ", %" PRIu64 " bytes at 0x%p",
                start_samplenum, inbuflen, inbuf);
 
-       for (d = di_list; d; d = d->next) {
+       for (d = sess->di_list; d; d = d->next) {
                if ((ret = srd_inst_decode(start_samplenum, d->data, inbuf,
                                           inbuflen)) != SRD_OK)
                        return ret;
@@ -914,6 +1088,34 @@ SRD_API int srd_session_send(uint64_t start_samplenum, const uint8_t *inbuf,
        return SRD_OK;
 }
 
+/**
+ * Destroy a decoding session.
+ *
+ * All decoder instances and output callbacks are properly released.
+ *
+ * @param sess. The session to be destroyed.
+ *
+ * @return SRD_OK upon success, a (negative) error code otherwise.
+ *
+ * @since 0.1.0
+ */
+SRD_API int srd_session_destroy(struct srd_session *sess)
+{
+       int session_id;
+
+       session_id = sess->session_id;
+       if (sess->di_list)
+               srd_inst_free_all(sess, NULL);
+       if (sess->callbacks)
+               g_slist_free_full(sess->callbacks, g_free);
+       sessions = g_slist_remove(sessions, sess);
+       g_free(sess);
+
+       srd_dbg("Destroyed session %d.", session_id);
+
+       return SRD_OK;
+}
+
 /**
  * Register/add a decoder output callback function.
  *
@@ -921,6 +1123,7 @@ SRD_API int srd_session_send(uint64_t start_samplenum, const uint8_t *inbuf,
  * to the PD controller (except for Python objects, which only go up the
  * stack).
  *
+ * @param sess The output session in which to register the callback.
  * @param output_type The output type this callback will receive. Only one
  *                    callback per output type can be registered.
  * @param cb The function to call. Must not be NULL.
@@ -928,11 +1131,16 @@ SRD_API int srd_session_send(uint64_t start_samplenum, const uint8_t *inbuf,
  *
  * @since 0.1.0
  */
-SRD_API int srd_pd_output_callback_add(int output_type,
-               srd_pd_output_callback_t cb, void *cb_data)
+SRD_API int srd_pd_output_callback_add(struct srd_session *sess,
+               int output_type, srd_pd_output_callback_t cb, void *cb_data)
 {
        struct srd_pd_callback *pd_cb;
 
+       if (session_is_valid(sess) != SRD_OK) {
+               srd_err("Invalid session.");
+               return SRD_ERR_ARG;
+       }
+
        srd_dbg("Registering new callback for output type %d.", output_type);
 
        if (!(pd_cb = g_try_malloc(sizeof(struct srd_pd_callback)))) {
@@ -943,19 +1151,25 @@ SRD_API int srd_pd_output_callback_add(int output_type,
        pd_cb->output_type = output_type;
        pd_cb->cb = cb;
        pd_cb->cb_data = cb_data;
-       callbacks = g_slist_append(callbacks, pd_cb);
+       sess->callbacks = g_slist_append(sess->callbacks, pd_cb);
 
        return SRD_OK;
 }
 
 /** @private */
-SRD_PRIV struct srd_pd_callback *srd_pd_output_callback_find(int output_type)
+SRD_PRIV struct srd_pd_callback *srd_pd_output_callback_find(
+               struct srd_session *sess, int output_type)
 {
        GSList *l;
        struct srd_pd_callback *tmp, *pd_cb;
 
+       if (session_is_valid(sess) != SRD_OK) {
+               srd_err("Invalid session.");
+               return NULL;
+       }
+
        pd_cb = NULL;
-       for (l = callbacks; l; l = l->next) {
+       for (l = sess->callbacks; l; l = l->next) {
                tmp = l->data;
                if (tmp->output_type == output_type) {
                        pd_cb = tmp;
index 5eac220a55c5b0a2942963700dce6700efa19f11..76f8682ad98a9d189287093511c5aa602f6f1027 100644 (file)
--- a/decoder.c
+++ b/decoder.c
@@ -42,6 +42,8 @@
 /* The list of protocol decoders. */
 SRD_PRIV GSList *pd_list = NULL;
 
+extern GSList *sessions;
+
 /* module_sigrokdecode.c */
 extern SRD_PRIV PyObject *mod_sigrokdecode;
 
@@ -461,6 +463,7 @@ static void free_probes(GSList *probelist)
 SRD_API int srd_decoder_unload(struct srd_decoder *dec)
 {
        struct srd_decoder_option *o;
+       struct srd_session *sess;
        GSList *l;
 
        srd_dbg("Unloading protocol decoder '%s'.", dec->name);
@@ -471,7 +474,10 @@ SRD_API int srd_decoder_unload(struct srd_decoder *dec)
         * stack. A frontend reloading a decoder thus has to restart all
         * instances, and rebuild the stack.
         */
-       srd_inst_free_all(NULL);
+       for (l = sessions; l; l = l->next) {
+               sess = l->data;
+               srd_inst_free_all(sess, NULL);
+       }
 
        for (l = dec->options; l; l = l->next) {
                o = l->data;
index 600b9fd1e186f76b31212b28802add2a50c0313e..2951fa35c653846728b05ce109f97a89c2c3da84 100644 (file)
 
 #include "libsigrokdecode.h"
 
+struct srd_session {
+       int session_id;
+       uint64_t num_probes;
+       uint64_t unitsize;
+       uint64_t samplerate;
+
+       /* List of decoder instances. */
+       GSList *di_list;
+
+       /* List of frontend callbacks to receive decoder output. */
+       GSList *callbacks;
+};
+
 /*--- controller.c ----------------------------------------------------------*/
 
 SRD_PRIV int srd_decoder_searchpath_add(const char *path);
-SRD_PRIV struct srd_decoder_inst *srd_inst_find_by_obj(const GSList *stack,
-                                                      const PyObject *obj);
+SRD_PRIV struct srd_decoder_inst *srd_inst_find_by_obj( const GSList *stack,
+               const PyObject *obj);
 SRD_PRIV int srd_inst_start(struct srd_decoder_inst *di, PyObject *args);
 SRD_PRIV int srd_inst_decode(uint64_t start_samplenum,
                             const struct srd_decoder_inst *dec,
                             const uint8_t *inbuf, uint64_t inbuflen);
 SRD_PRIV void srd_inst_free(struct srd_decoder_inst *di);
-SRD_PRIV void srd_inst_free_all(GSList *stack);
-SRD_PRIV struct srd_pd_callback *srd_pd_output_callback_find(int output_type);
+SRD_PRIV void srd_inst_free_all(struct srd_session *sess, GSList *stack);
+SRD_PRIV struct srd_pd_callback *srd_pd_output_callback_find(struct srd_session *sess,
+               int output_type);
 SRD_PRIV int srd_inst_pd_output_add(struct srd_decoder_inst *di,
                                    int output_type, const char *output_id);
 
index 97ffa1d0f4c9464eb69d31f55709b62f89e8c160..c61a0e4d17d6c0a11c094fd8509b9d79d676d62e 100644 (file)
@@ -30,6 +30,8 @@
 extern "C" {
 #endif
 
+struct srd_session;
+
 /**
  * @file
  *
@@ -164,6 +166,12 @@ enum {
 
 #define SRD_MAX_NUM_PROBES 64
 
+enum {
+       SRD_CONF_NUM_PROBES = 10000,
+       SRD_CONF_UNITSIZE,
+       SRD_CONF_SAMPLERATE,
+};
+
 struct srd_decoder {
        /** The decoder ID. Must be non-NULL and unique for all decoders. */
        char *id;
@@ -228,6 +236,7 @@ struct srd_decoder_option {
 
 struct srd_decoder_inst {
        struct srd_decoder *decoder;
+       struct srd_session *sess;
        PyObject *py_inst;
        char *inst_id;
        GSList *pd_output;
@@ -287,16 +296,21 @@ SRD_API int srd_inst_option_set(struct srd_decoder_inst *di,
                GHashTable *options);
 SRD_API int srd_inst_probe_set_all(struct srd_decoder_inst *di,
                GHashTable *probes);
-SRD_API struct srd_decoder_inst *srd_inst_new(const char *id,
-               GHashTable *options);
-SRD_API int srd_inst_stack(struct srd_decoder_inst *di_from,
-               struct srd_decoder_inst *di_to);
-SRD_API struct srd_decoder_inst *srd_inst_find_by_id(const char *inst_id);
-SRD_API int srd_session_start(int num_probes, int unitsize, uint64_t samplerate);
-SRD_API int srd_session_send(uint64_t start_samplenum, const uint8_t *inbuf,
-               uint64_t inbuflen);
-SRD_API int srd_pd_output_callback_add(int output_type,
-               srd_pd_output_callback_t cb, void *cb_data);
+SRD_API struct srd_decoder_inst *srd_inst_new(struct srd_session *sess,
+               const char *id, GHashTable *options);
+SRD_API int srd_inst_stack(struct srd_session *sess,
+               struct srd_decoder_inst *di_from, struct srd_decoder_inst *di_to);
+SRD_API struct srd_decoder_inst *srd_inst_find_by_id(struct srd_session *sess,
+               const char *inst_id);
+SRD_API int srd_session_new(struct srd_session **sess);
+SRD_API int srd_session_start(struct srd_session *sess);
+SRD_API int srd_session_config_set(struct srd_session *sess, int key,
+               GVariant *data);
+SRD_API int srd_session_send(struct srd_session *sess,
+               uint64_t start_samplenum, const uint8_t *inbuf, uint64_t inbuflen);
+SRD_API int srd_session_destroy(struct srd_session *sess);
+SRD_API int srd_pd_output_callback_add(struct srd_session *sess,
+               int output_type, srd_pd_output_callback_t cb, void *cb_data);
 
 /*--- decoder.c -------------------------------------------------------------*/
 
index 3f4bae9d774742f791f3ec6d27b81041408ac59d..c8ef09e1021b4be12335eac5af61235f445330e2 100644 (file)
@@ -135,7 +135,7 @@ static PyObject *Decoder_put(PyObject *self, PyObject *args)
        switch (pdo->output_type) {
        case SRD_OUTPUT_ANN:
                /* Annotations are only fed to callbacks. */
-               if ((cb = srd_pd_output_callback_find(pdo->output_type))) {
+               if ((cb = srd_pd_output_callback_find(di->sess, pdo->output_type))) {
                        /* Annotations need converting from PyObject. */
                        if (convert_pyobj(di, data, &pdata->ann_format,
                                          (char ***)&pdata->data) != SRD_OK) {