+ if (ctx->header && !ctx->did_header) {
+ /* save_gnuplot knows how many lines we print. */
+ g_string_append_printf(header,
+ "%s CSV generated by %s %s\n%s from %s on %s",
+ ctx->comment, PACKAGE_NAME,
+ sr_package_version_string_get(), ctx->comment,
+ ctx->title, ctime(&hdr->starttime.tv_sec));
+
+ /* Columns / channels */
+ channels = o->sdi ? o->sdi->channels : NULL;
+ num_channels = g_slist_length(channels);
+ g_string_append_printf(header, "%s Channels (%d/%d):",
+ ctx->comment, ctx->num_analog_channels +
+ ctx->num_logic_channels, num_channels);
+ for (l = channels; l; l = l->next) {
+ ch = l->data;
+ if (ch->enabled)
+ g_string_append_printf(header, " %s,", ch->name);
+ }
+ if (channels) {
+ /* Drop last separator. */
+ g_string_truncate(header, header->len - 1);
+ }
+ g_string_append_printf(header, "\n");
+ if (samplerate != 0) {
+ samplerate_s = sr_samplerate_string(samplerate);
+ g_string_append_printf(header, "%s Samplerate: %s\n",
+ ctx->comment, samplerate_s);
+ g_free(samplerate_s);
+ }
+ ctx->did_header = TRUE;
+ }
+
+ return header;
+}
+
+/*
+ * Analog devices can have samples of different types. Since each
+ * packet has only one meaning, it is restricted to having at most one
+ * type of data. So they can send multiple packets for a single sample.
+ * To further complicate things, they can send multiple samples in a
+ * single packet.
+ *
+ * So we need to pull any channels of interest out of a packet and save
+ * them until we have complete samples to output. Some devices make this
+ * simple by sending DF_FRAME_BEGIN/DF_FRAME_END packets, the latter of which
+ * signals the end of a set of samples, so we can dump things there.
+ *
+ * At least one driver (the demo driver) sends packets that contain parts of
+ * multiple samples without wrapping them in DF_FRAME. Possibly this driver
+ * is buggy, but it's also the standard for testing, so it has to be supported
+ * as is.
+ *
+ * Many assumptions about the "shape" of the data here:
+ *
+ * All of the data for a channel is assumed to be in one frame;
+ * otherwise the data in the second packet will overwrite the data in
+ * the first packet.
+ */
+static void process_analog(struct context *ctx,
+ const struct sr_datafeed_analog *analog)
+{
+ int ret;
+ size_t num_rcvd_ch, num_have_ch;
+ size_t idx_have, idx_smpl, idx_rcvd;
+ size_t idx_send;
+ struct sr_analog_meaning *meaning;
+ GSList *l;
+ float *fdata = NULL;
+ struct sr_channel *ch;
+
+ if (!ctx->analog_samples) {
+ ctx->analog_samples = g_malloc(analog->num_samples
+ * sizeof(float) * ctx->num_analog_channels);
+ if (!ctx->num_samples)
+ ctx->num_samples = analog->num_samples;
+ }
+ if (ctx->num_samples != analog->num_samples)
+ sr_warn("Expecting %u analog samples, got %u.",
+ ctx->num_samples, analog->num_samples);
+
+ meaning = analog->meaning;
+ num_rcvd_ch = g_slist_length(meaning->channels);
+ ctx->channels_seen += num_rcvd_ch;
+ sr_dbg("Processing packet of %zu analog channels", num_rcvd_ch);
+ fdata = g_malloc(analog->num_samples * num_rcvd_ch * sizeof(float));
+ if ((ret = sr_analog_to_float(analog, fdata)) != SR_OK)
+ sr_warn("Problems converting data to floating point values.");
+
+ num_have_ch = ctx->num_analog_channels + ctx->num_logic_channels;
+ idx_send = 0;
+ for (idx_have = 0; idx_have < num_have_ch; idx_have++) {
+ if (ctx->channels[idx_have].ch->type != SR_CHANNEL_ANALOG)