]> sigrok.org Git - libsigrok.git/blobdiff - output/bits.c
build: Portability fixes.
[libsigrok.git] / output / bits.c
index 9b4d34876326e49df60fc7f8c7122b43ac7709db..b44f1057d82c645676ec16a4c31094b3221060ea 100644 (file)
@@ -32,10 +32,11 @@ struct context {
        int samples_per_line;
        int spl_cnt;
        int trigger;
+       uint64_t samplerate;
        int *channel_index;
        char **channel_names;
+       gboolean header_done;
        GString **lines;
-       GString *header;
 };
 
 static int init(struct sr_output *o)
@@ -43,23 +44,31 @@ static int init(struct sr_output *o)
        struct context *ctx;
        struct sr_channel *ch;
        GSList *l;
-       GVariant *gvar;
-       uint64_t samplerate;
+       GHashTableIter iter;
+       gpointer key, value;
        unsigned int i, j;
-       int spl, num_channels;
-       char *samplerate_s;
+       int spl;
 
        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) {
@@ -88,33 +97,53 @@ static int init(struct sr_output *o)
                j++;
        }
 
-       ctx->header = g_string_sized_new(512);
-       g_string_printf(ctx->header, "%s\n", PACKAGE_STRING);
+       return SR_OK;
+}
+
+static GString *gen_header(struct sr_output *o)
+{
+       struct context *ctx;
+       GVariant *gvar;
+       GString *header;
+       int num_channels;
+       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);
+               }
+       }
+
+       header = g_string_sized_new(512);
+       g_string_printf(header, "%s\n", PACKAGE_STRING);
        num_channels = g_slist_length(o->sdi->channels);
-       if (sr_config_get(o->sdi->driver, o->sdi, NULL, SR_CONF_SAMPLERATE,
-                       &gvar) == SR_OK) {
-               samplerate = g_variant_get_uint64(gvar);
-               samplerate_s = sr_samplerate_string(samplerate);
-               g_string_append_printf(ctx->header, "Acquisition with %d/%d channels at %s\n",
-                        ctx->num_enabled_channels, num_channels, samplerate_s);
+       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_variant_unref(gvar);
        }
+       g_string_append_printf(header, "\n");
 
-       return SR_OK;
+       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;
        struct context *ctx;
+       GSList *l;
        int idx, offset;
        uint64_t i, j;
        gchar *p, c;
 
-       (void)sdi;
-
        *out = NULL;
        if (!o || !o->sdi)
                return SR_ERR_ARG;
@@ -122,14 +151,22 @@ static int receive(struct sr_output *o, const struct sr_dev_inst *sdi,
                return SR_ERR_ARG;
 
        switch (packet->type) {
+       case 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);
+               }
+               break;
        case SR_DF_TRIGGER:
                ctx->trigger = ctx->spl_cnt;
                break;
        case SR_DF_LOGIC:
-               if (ctx->header) {
-                       /* The header is still here, this must be the first packet. */
-                       *out = ctx->header;
-                       ctx->header = NULL;
+               if (!ctx->header_done) {
+                       *out = gen_header(o);
+                       ctx->header_done = TRUE;
                } else
                        *out = g_string_sized_new(512);
 
@@ -188,14 +225,11 @@ static int cleanup(struct sr_output *o)
        if (!(ctx = o->internal))
                return SR_OK;
 
-       g_free(ctx->header);
        g_free(ctx->channel_index);
        g_free(ctx->channel_names);
        for (i = 0; i < ctx->num_enabled_channels; i++)
                g_string_free(ctx->lines[i], TRUE);
        g_free(ctx->lines);
-       if (ctx->header)
-               g_string_free(ctx->header, TRUE);
        g_free(ctx);
        o->internal = NULL;