From: Bert Vermeulen Date: Sun, 20 Apr 2014 20:51:09 +0000 (+0200) Subject: output: Introduce output module API wrappers. X-Git-Tag: libsigrok-0.3.0~72 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=dba3e6826e3d37309ed49dd77cde346b369bc5a9;p=libsigrok.git output: Introduce output module API wrappers. --- diff --git a/Makefile.am b/Makefile.am index 4023778b..a88d264b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -49,17 +49,17 @@ libsigrok_la_SOURCES += \ # Output formats libsigrok_la_SOURCES += \ - output/binary.c \ + output/output.c \ + output/analog.c \ + output/ascii.c \ output/bits.c \ - output/vcd.c \ - output/ols.c \ - output/gnuplot.c \ - output/chronovu_la8.c \ + output/binary.c \ output/csv.c \ - output/analog.c \ - output/output.c \ + output/chronovu_la8.c \ + output/gnuplot.c \ output/hex.c \ - output/ascii.c + output/ols.c \ + output/vcd.c # Hardware (common files) libsigrok_la_SOURCES += \ diff --git a/libsigrok.h b/libsigrok.h index f9678de7..f233b8cc 100644 --- a/libsigrok.h +++ b/libsigrok.h @@ -430,24 +430,21 @@ struct sr_input_format { /** Output (file) format struct. */ struct sr_output { - /** - * A pointer to this output format's 'struct sr_output_format'. - * The frontend can use this to call the module's callbacks. - */ + /** A pointer to this output's format. */ struct sr_output_format *format; /** * The device for which this output module is creating output. This * can be used by the module to find out channel names and numbers. */ - struct sr_dev_inst *sdi; + const struct sr_dev_inst *sdi; /** * An optional parameter which the frontend can pass in to the * output module. How the string is interpreted is entirely up to * the module. */ - char *param; + GHashTable *params; /** * A generic pointer which can be used by the module to keep internal @@ -514,7 +511,7 @@ struct sr_output_format { * @retval SR_OK Success * @retval other Negative error code. */ - int (*receive) (struct sr_output *o, const struct sr_dev_inst *sdi, + int (*receive) (struct sr_output *o, const struct sr_datafeed_packet *packet, GString **out); /** diff --git a/output/analog.c b/output/analog.c index 131e24c4..bdb55733 100644 --- a/output/analog.c +++ b/output/analog.c @@ -206,8 +206,8 @@ static void fancyprint(int unit, int mqflags, float value, GString *out) g_string_append_c(out, '\n'); } -static int receive(struct sr_output *o, const struct sr_dev_inst *sdi, - const struct sr_datafeed_packet *packet, GString **out) +static int receive(struct sr_output *o, const struct sr_datafeed_packet *packet, + GString **out) { const struct sr_datafeed_analog *analog; struct sr_channel *ch; @@ -215,8 +215,6 @@ static int receive(struct sr_output *o, const struct sr_dev_inst *sdi, const float *fdata; int i, p; - (void)sdi; - *out = NULL; if (!o || !o->sdi) return SR_ERR_ARG; diff --git a/output/ascii.c b/output/ascii.c index 884769c8..44bd0b15 100644 --- a/output/ascii.c +++ b/output/ascii.c @@ -48,6 +48,8 @@ static int init(struct sr_output *o) struct sr_channel *ch; GSList *l; GVariant *gvar; + GHashTableIter iter; + gpointer key, value; uint64_t samplerate; unsigned int i, j; int spl, num_channels; @@ -55,15 +57,24 @@ static int init(struct sr_output *o) if (!o || !o->sdi) return SR_ERR_ARG; + + spl = DEFAULT_SAMPLES_PER_LINE; + g_hash_table_iter_init(&iter, o->params); + while (g_hash_table_iter_next(&iter, &key, &value)) { + if (!strcmp(key, "width")) { + if ((spl = strtoul(value, NULL, 10)) < 1) { + sr_err("Invalid width."); + return SR_ERR_ARG; + } + } else { + sr_err("Unknown parameter '%s'.", key); + return SR_ERR_ARG; + } + } + ctx = g_malloc0(sizeof(struct context)); o->internal = ctx; ctx->trigger = -1; - - if (o->param && o->param[0]) { - if ((spl = strtoul(o->param, NULL, 10)) < 1) - return SR_ERR_ARG; - } else - spl = DEFAULT_SAMPLES_PER_LINE; ctx->samples_per_line = spl; for (l = o->sdi->channels; l; l = l->next) { @@ -109,8 +120,8 @@ static int init(struct sr_output *o) return SR_OK; } -static int receive(struct sr_output *o, const struct sr_dev_inst *sdi, - const struct sr_datafeed_packet *packet, GString **out) +static int receive(struct sr_output *o, const struct sr_datafeed_packet *packet, + GString **out) { const struct sr_datafeed_logic *logic; struct context *ctx; @@ -118,8 +129,6 @@ static int receive(struct sr_output *o, const struct sr_dev_inst *sdi, uint64_t i, j; gchar *p, c; - (void)sdi; - *out = NULL; if (!o || !o->sdi) return SR_ERR_ARG; diff --git a/output/binary.c b/output/binary.c index d631773f..6e2531d1 100644 --- a/output/binary.c +++ b/output/binary.c @@ -24,15 +24,14 @@ #include "libsigrok.h" #include "libsigrok-internal.h" -#define LOG_PREFIX "output/binary:" +#define LOG_PREFIX "output/binary" -static int receive(struct sr_output *o, const struct sr_dev_inst *sdi, - const struct sr_datafeed_packet *packet, GString **out) +static int receive(struct sr_output *o, const struct sr_datafeed_packet *packet, + GString **out) { const struct sr_datafeed_logic *logic; (void)o; - (void)sdi; *out = NULL; if (packet->type != SR_DF_LOGIC) @@ -46,6 +45,5 @@ static int receive(struct sr_output *o, const struct sr_dev_inst *sdi, SR_PRIV struct sr_output_format output_binary = { .id = "binary", .description = "Raw binary", - .init = NULL, .receive = receive, }; diff --git a/output/bits.c b/output/bits.c index 9b4d3487..e0c64864 100644 --- a/output/bits.c +++ b/output/bits.c @@ -44,6 +44,8 @@ static int init(struct sr_output *o) struct sr_channel *ch; GSList *l; GVariant *gvar; + GHashTableIter iter; + gpointer key, value; uint64_t samplerate; unsigned int i, j; int spl, num_channels; @@ -51,15 +53,24 @@ static int init(struct sr_output *o) if (!o || !o->sdi) return SR_ERR_ARG; + + spl = DEFAULT_SAMPLES_PER_LINE; + g_hash_table_iter_init(&iter, o->params); + while (g_hash_table_iter_next(&iter, &key, &value)) { + if (!strcmp(key, "width")) { + if ((spl = strtoul(value, NULL, 10)) < 1) { + sr_err("Invalid width."); + return SR_ERR_ARG; + } + } else { + sr_err("Unknown parameter '%s'.", key); + return SR_ERR_ARG; + } + } + ctx = g_malloc0(sizeof(struct context)); o->internal = ctx; ctx->trigger = -1; - - if (o->param && o->param[0]) { - if ((spl = strtoul(o->param, NULL, 10)) < 1) - return SR_ERR_ARG; - } else - spl = DEFAULT_SAMPLES_PER_LINE; ctx->samples_per_line = spl; for (l = o->sdi->channels; l; l = l->next) { @@ -104,8 +115,8 @@ static int init(struct sr_output *o) return SR_OK; } -static int receive(struct sr_output *o, const struct sr_dev_inst *sdi, - const struct sr_datafeed_packet *packet, GString **out) +static int receive(struct sr_output *o, const struct sr_datafeed_packet *packet, + GString **out) { const struct sr_datafeed_logic *logic; struct context *ctx; @@ -113,8 +124,6 @@ static int receive(struct sr_output *o, const struct sr_dev_inst *sdi, uint64_t i, j; gchar *p, c; - (void)sdi; - *out = NULL; if (!o || !o->sdi) return SR_ERR_ARG; diff --git a/output/chronovu_la8.c b/output/chronovu_la8.c index 08164e6b..ad0b5d32 100644 --- a/output/chronovu_la8.c +++ b/output/chronovu_la8.c @@ -101,8 +101,8 @@ static int init(struct sr_output *o) return SR_OK; } -static int receive(struct sr_output *o, const struct sr_dev_inst *sdi, - const struct sr_datafeed_packet *packet, GString **out) +static int receive(struct sr_output *o, const struct sr_datafeed_packet *packet, + GString **out) { const struct sr_datafeed_logic *logic; struct context *ctx; @@ -110,8 +110,6 @@ static int receive(struct sr_output *o, const struct sr_dev_inst *sdi, uint64_t samplerate; gchar c[4]; - (void)sdi; - *out = NULL; if (!o || !o->sdi) return SR_ERR_ARG; diff --git a/output/csv.c b/output/csv.c index 8e012212..0bec7ae2 100644 --- a/output/csv.c +++ b/output/csv.c @@ -117,8 +117,8 @@ static int init(struct sr_output *o) return SR_OK; } -static int receive(struct sr_output *o, const struct sr_dev_inst *sdi, - const struct sr_datafeed_packet *packet, GString **out) +static int receive(struct sr_output *o, const struct sr_datafeed_packet *packet, + GString **out) { const struct sr_datafeed_logic *logic; struct context *ctx; @@ -126,8 +126,6 @@ static int receive(struct sr_output *o, const struct sr_dev_inst *sdi, uint64_t i, j; gchar *p, c; - (void)sdi; - *out = NULL; if (!o || !o->sdi) return SR_ERR_ARG; diff --git a/output/gnuplot.c b/output/gnuplot.c index 0eb116d2..33a3ee0a 100644 --- a/output/gnuplot.c +++ b/output/gnuplot.c @@ -133,16 +133,14 @@ static int init(struct sr_output *o) return 0; } -static int receive(struct sr_output *o, const struct sr_dev_inst *sdi, - const struct sr_datafeed_packet *packet, GString **out) +static int receive(struct sr_output *o, const struct sr_datafeed_packet *packet, + GString **out) { const struct sr_datafeed_logic *logic; struct context *ctx; const uint8_t *sample; unsigned int curbit, p, idx, i; - (void)sdi; - *out = NULL; if (!o || !o->internal) return SR_ERR_BUG; diff --git a/output/hex.c b/output/hex.c index 85ce9069..a49d9d92 100644 --- a/output/hex.c +++ b/output/hex.c @@ -47,6 +47,8 @@ static int init(struct sr_output *o) struct sr_channel *ch; GSList *l; GVariant *gvar; + GHashTableIter iter; + gpointer key, value; uint64_t samplerate; unsigned int i, j; int spl, num_channels; @@ -54,15 +56,24 @@ static int init(struct sr_output *o) if (!o || !o->sdi) return SR_ERR_ARG; + + spl = DEFAULT_SAMPLES_PER_LINE; + g_hash_table_iter_init(&iter, o->params); + while (g_hash_table_iter_next(&iter, &key, &value)) { + if (!strcmp(key, "width")) { + if ((spl = strtoul(value, NULL, 10)) < 1) { + sr_err("Invalid width."); + return SR_ERR_ARG; + } + } else { + sr_err("Unknown parameter '%s'.", key); + return SR_ERR_ARG; + } + } + ctx = g_malloc0(sizeof(struct context)); o->internal = ctx; ctx->trigger = -1; - - if (o->param && o->param[0]) { - if ((spl = strtoul(o->param, NULL, 10)) < 1) - return SR_ERR_ARG; - } else - spl = DEFAULT_SAMPLES_PER_LINE; ctx->samples_per_line = spl; for (l = o->sdi->channels; l; l = l->next) { @@ -109,8 +120,8 @@ static int init(struct sr_output *o) return SR_OK; } -static int receive(struct sr_output *o, const struct sr_dev_inst *sdi, - const struct sr_datafeed_packet *packet, GString **out) +static int receive(struct sr_output *o, const struct sr_datafeed_packet *packet, + GString **out) { const struct sr_datafeed_logic *logic; struct context *ctx; @@ -118,8 +129,6 @@ static int receive(struct sr_output *o, const struct sr_dev_inst *sdi, uint64_t i, j; gchar *p; - (void)sdi; - *out = NULL; if (!o || !o->sdi) return SR_ERR_ARG; diff --git a/output/ols.c b/output/ols.c index 02e34e47..78a41bb0 100644 --- a/output/ols.c +++ b/output/ols.c @@ -88,8 +88,8 @@ static GString *gen_header(const struct sr_dev_inst *sdi, struct context *ctx) return s; } -static int receive(struct sr_output *o, const struct sr_dev_inst *sdi, - const struct sr_datafeed_packet *packet, GString **out) +static int receive(struct sr_output *o, const struct sr_datafeed_packet *packet, + GString **out) { struct context *ctx; const struct sr_datafeed_meta *meta; @@ -117,7 +117,7 @@ static int receive(struct sr_output *o, const struct sr_dev_inst *sdi, logic = packet->payload; if (ctx->num_samples == 0) { /* First logic packet in the feed. */ - *out = gen_header(sdi, ctx); + *out = gen_header(o->sdi, ctx); } else *out = g_string_sized_new(512); for (i = 0; i <= logic->length - logic->unitsize; i += logic->unitsize) { diff --git a/output/output.c b/output/output.c index a0c81e82..941678ec 100644 --- a/output/output.c +++ b/output/output.c @@ -37,13 +37,11 @@ * to change the frontends at all. * * All output modules are fed data in a stream. Devices that can stream data - * into libsigrok live, instead of storing and then transferring the whole - * buffer, can thus generate output live. + * into libsigrok, instead of storing and then transferring the whole buffer, + * can thus generate output live. * - * Output modules are responsible for allocating enough memory to store - * their own output, and passing a pointer to that memory (and length) of - * the allocated memory back to the caller. The caller is then expected to - * free this memory when finished with it. + * Output modules generate a newly allocated GString. The caller is then + * expected to free this with g_string_free() when finished with it. * * @{ */ @@ -62,15 +60,15 @@ extern SR_PRIV struct sr_output_format output_analog; /* @endcond */ static struct sr_output_format *output_module_list[] = { - &output_bits, - &output_hex, &output_ascii, &output_binary, - &output_vcd, - &output_ols, + &output_bits, + &output_csv, &output_gnuplot, + &output_hex, + &output_ols, + &output_vcd, &output_chronovu_la8, - &output_csv, &output_analog, NULL, }; @@ -80,4 +78,40 @@ SR_API struct sr_output_format **sr_output_list(void) return output_module_list; } +SR_API struct sr_output *sr_output_new(struct sr_output_format *of, + GHashTable *params, const struct sr_dev_inst *sdi) +{ + struct sr_output *o; + + o = g_malloc(sizeof(struct sr_output)); + o->format = of; + o->sdi = sdi; + o->params = params; + if (o->format->init && o->format->init(o) != SR_OK) { + g_free(o); + o = NULL; + } + + return o; +} + +SR_API int sr_output_send(struct sr_output *o, + const struct sr_datafeed_packet *packet, GString **out) +{ + return o->format->receive(o, packet, out); +} + +SR_API int sr_output_free(struct sr_output *o) +{ + int ret; + + ret = SR_OK; + if (o->format->cleanup) + ret = o->format->cleanup(o); + g_free(o); + + return ret; +} + + /** @} */ diff --git a/output/vcd.c b/output/vcd.c index 7453b507..4d853057 100644 --- a/output/vcd.c +++ b/output/vcd.c @@ -139,8 +139,8 @@ static int init(struct sr_output *o) return SR_OK; } -static int receive(struct sr_output *o, const struct sr_dev_inst *sdi, - const struct sr_datafeed_packet *packet, GString **out) +static int receive(struct sr_output *o, const struct sr_datafeed_packet *packet, + GString **out) { const struct sr_datafeed_logic *logic; struct context *ctx; @@ -149,8 +149,6 @@ static int receive(struct sr_output *o, const struct sr_dev_inst *sdi, uint8_t *sample; gboolean timestamp_written; - (void)sdi; - *out = NULL; if (!o || !o->internal) return SR_ERR_BUG; diff --git a/proto.h b/proto.h index 16bc269b..06e03766 100644 --- a/proto.h +++ b/proto.h @@ -130,6 +130,11 @@ SR_API struct sr_input_format **sr_input_list(void); /*--- output/output.c -------------------------------------------------------*/ SR_API struct sr_output_format **sr_output_list(void); +SR_API struct sr_output *sr_output_new(struct sr_output_format *of, + GHashTable *params, const struct sr_dev_inst *sdi); +SR_API int sr_output_send(struct sr_output *o, + const struct sr_datafeed_packet *packet, GString **out); +SR_API int sr_output_free(struct sr_output *o); /*--- strutil.c -------------------------------------------------------------*/