X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=output%2Fgnuplot.c;h=a9feec67ba056f2f55daeed75990fca6eb1619e9;hb=768579456c7800e462a404c2c28af1e306989fd8;hp=056ee29a917bae0166006cfb1d756a545bb7acae;hpb=b240ee0856349d72d30ad75f010a079338b76baa;p=libsigrok.git diff --git a/output/gnuplot.c b/output/gnuplot.c index 056ee29a..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; + unsigned int i; - if (!o) + if (!o || !o->sdi) return SR_ERR_ARG; - if (!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,85 +71,103 @@ 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"); + + g_string_append_printf(header, "%s", gnuplot_header2); - return 0; + /* 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_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_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; - (void)sdi; - *out = NULL; if (!o || !o->internal) 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); } @@ -208,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; @@ -218,7 +218,6 @@ static int cleanup(struct sr_output *o) SR_PRIV struct sr_output_format output_gnuplot = { .id = "gnuplot", .description = "Gnuplot", - .df_type = SR_DF_LOGIC, .init = init, .receive = receive, .cleanup = cleanup,