From: Bert Vermeulen Date: Tue, 29 Apr 2014 21:00:47 +0000 (-0700) Subject: output/gnuplot: Support getting samplerate from meta packets. X-Git-Tag: libsigrok-0.3.0~57 X-Git-Url: https://sigrok.org/gitweb/?p=libsigrok.git;a=commitdiff_plain;h=83023573d9a3c0fc1d5823d4dc5f9e85b72084d9 output/gnuplot: Support getting samplerate from meta packets. --- diff --git a/output/gnuplot.c b/output/gnuplot.c index 33a3ee0a..a9feec67 100644 --- a/output/gnuplot.c +++ b/output/gnuplot.c @@ -29,48 +29,32 @@ struct context { unsigned int num_enabled_channels; + uint64_t samplerate; uint64_t samplecount; - GString *header; + gboolean header_done; uint8_t *prevsample; int *channel_index; }; static const char *gnuplot_header = "\ -# Sample data in space-separated columns format usable by gnuplot\n\ -#\n\ -# Generated by: %s on %s%s\ -# Period: %s\n\ -#\n\ -# Column\tChannel\n\ -# -------------------------------------\ -----------------------------------------\n\ -# 0\t\tSample counter (for internal gnuplot purposes)\n%s\n"; - -static const char *gnuplot_header_comment = "\ -# Comment: Acquisition with %d/%d channels at %s\n"; +# Sample data in space-separated columns format usable by gnuplot.\n"; +static const char *gnuplot_header2 = "\ +#\n# Column\tChannel\n\ +# -----------------------------------------------------------------------------\n\ +# 0\t\tSample counter (for internal gnuplot purposes)\n"; + static int init(struct sr_output *o) { struct context *ctx; struct sr_channel *ch; GSList *l; - GVariant *gvar; - uint64_t samplerate; - unsigned int i, j; - int num_channels; - char *c, *frequency_s; - char wbuf[1000], comment[128]; - time_t t; - - if (!o) - return SR_ERR_ARG; + unsigned int i; - if (!o->sdi) + if (!o || !o->sdi) return SR_ERR_ARG; - if (!(ctx = g_malloc0(sizeof(struct context)))) - return SR_ERR_MALLOC; - + ctx = g_malloc0(sizeof(struct context)); o->internal = ctx; ctx->num_enabled_channels = 0; for (l = o->sdi->channels; l; l = l->next) { @@ -87,56 +71,72 @@ static int init(struct sr_output *o) } ctx->channel_index = g_malloc(sizeof(int) * ctx->num_enabled_channels); - num_channels = g_slist_length(o->sdi->channels); - comment[0] = '\0'; - samplerate = 0; - if (sr_config_get(o->sdi->driver, o->sdi, NULL, SR_CONF_SAMPLERATE, - &gvar) == SR_OK) { - samplerate = g_variant_get_uint64(gvar); - g_variant_unref(gvar); - if (!(frequency_s = sr_samplerate_string(samplerate))) { - sr_err("%s: sr_samplerate_string failed", __func__); - g_free(ctx); - return SR_ERR; - } - snprintf(comment, 127, gnuplot_header_comment, - ctx->num_enabled_channels, num_channels, frequency_s); - g_free(frequency_s); - } - - /* Columns / channels */ - wbuf[0] = '\0'; - for (i = 0, j = 0, l = o->sdi->channels; l; l = l->next, i++) { + /* Once more to map the enabled channels. */ + for (i = 0, l = o->sdi->channels; l; l = l->next) { ch = l->data; if (ch->type != SR_CHANNEL_LOGIC) continue; if (!ch->enabled) continue; - c = (char *)&wbuf + strlen((const char *)&wbuf); - sprintf(c, "# %d\t\t%s\n", i + 1, ch->name); - /* Remember the enabled channel's index while we're at it. */ - ctx->channel_index[j++] = i; + ctx->channel_index[i++] = ch->index; } - if (!(frequency_s = sr_period_string(samplerate))) { - sr_err("%s: sr_period_string failed", __func__); - g_free(ctx); - return SR_ERR; + return SR_OK; +} + +static GString *gen_header(struct sr_output *o) +{ + struct context *ctx; + struct sr_channel *ch; + GVariant *gvar; + GString *header; + time_t t; + unsigned int num_channels, i; + char *samplerate_s; + + ctx = o->internal; + if (ctx->samplerate == 0) { + if (sr_config_get(o->sdi->driver, o->sdi, NULL, SR_CONF_SAMPLERATE, + &gvar) == SR_OK) { + ctx->samplerate = g_variant_get_uint64(gvar); + g_variant_unref(gvar); + } } t = time(NULL); - ctx->header = g_string_sized_new(512); - g_string_printf(ctx->header, gnuplot_header, PACKAGE_STRING, - ctime(&t), comment, frequency_s, (char *)&wbuf); - g_free(frequency_s); + header = g_string_sized_new(512); + g_string_printf(header, "%s", gnuplot_header); + g_string_append_printf(header, "# Generated by %s on %s", + PACKAGE_STRING, ctime(&t)); + + num_channels = g_slist_length(o->sdi->channels); + g_string_append_printf(header, "# Acquisition with %d/%d channels", + ctx->num_enabled_channels, num_channels); + if (ctx->samplerate != 0) { + samplerate_s = sr_samplerate_string(ctx->samplerate); + g_string_append_printf(header, " at %s", samplerate_s); + g_free(samplerate_s); + } + g_string_append_printf(header, "\n"); - return 0; + g_string_append_printf(header, "%s", gnuplot_header2); + + /* Columns / channels */ + for (i = 0; i < ctx->num_enabled_channels; i++) { + ch = g_slist_nth_data(o->sdi->channels, ctx->channel_index[i]); + g_string_append_printf(header, "# %d\t\t%s\n", i + 1, ch->name); + } + + return header; } static int receive(struct sr_output *o, const struct sr_datafeed_packet *packet, GString **out) { + const struct sr_datafeed_meta *meta; const struct sr_datafeed_logic *logic; + const struct sr_config *src; + GSList *l; struct context *ctx; const uint8_t *sample; unsigned int curbit, p, idx, i; @@ -146,24 +146,28 @@ static int receive(struct sr_output *o, const struct sr_datafeed_packet *packet, return SR_ERR_BUG; ctx = o->internal; + if (packet->type == SR_DF_META) { + meta = packet->payload; + for (l = meta->config; l; l = l->next) { + src = l->data; + if (src->key != SR_CONF_SAMPLERATE) + continue; + ctx->samplerate = g_variant_get_uint64(src->data); + } + } + if (packet->type != SR_DF_LOGIC) return SR_OK; logic = packet->payload; if (!ctx->prevsample) { /* Can't allocate this until we know the stream's unitsize. */ - if (!(ctx->prevsample = g_malloc0(logic->unitsize))) { - g_free(ctx); - sr_err("%s: ctx->prevsample malloc failed", __func__); - return SR_ERR_MALLOC; - } + ctx->prevsample = g_malloc0(logic->unitsize); } - if (ctx->header) { - /* The header is still here, this must be the first packet. */ - *out = ctx->header; - ctx->header = NULL; - ctx->samplecount = 0; + if (!ctx->header_done) { + *out = gen_header(o); + ctx->header_done = TRUE; } else { *out = g_string_sized_new(512); } @@ -206,8 +210,6 @@ static int cleanup(struct sr_output *o) ctx = o->internal; g_free(ctx->channel_index); g_free(ctx->prevsample); - if (ctx->header) - g_string_free(ctx->header, TRUE); g_free(ctx); return SR_OK;