gboolean zip_created;
uint64_t samplerate;
char *filename;
+ gint first_analog_index;
+ gint *analog_index_map;
};
static int init(struct sr_output *o, GHashTable *options)
const char *devgroup;
char *s, *metabuf;
gsize metalen;
- guint logic_channels = 0, analog_channels = 0;
+ guint logic_channels = 0, enabled_logic_channels = 0;
+ guint enabled_analog_channels = 0;
+ guint index;
outc = o->priv;
SR_PACKAGE_VERSION_STRING);
devgroup = "device 1";
- g_key_file_set_string(meta, devgroup, "capturefile", "logic-1");
-
- s = sr_samplerate_string(outc->samplerate);
- g_key_file_set_string(meta, devgroup, "samplerate", s);
- g_free(s);
for (l = o->sdi->channels; l; l = l->next) {
ch = l->data;
+
switch (ch->type) {
- case SR_CHANNEL_LOGIC:
- logic_channels++;
- break;
- case SR_CHANNEL_ANALOG:
- analog_channels++;
- break;
+ case SR_CHANNEL_LOGIC:
+ if (ch->enabled)
+ enabled_logic_channels++;
+ logic_channels++;
+ break;
+ case SR_CHANNEL_ANALOG:
+ if (ch->enabled)
+ enabled_analog_channels++;
+ break;
}
}
- g_key_file_set_integer(meta, devgroup, "total probes", logic_channels);
- g_key_file_set_integer(meta, devgroup, "total analog", analog_channels);
+ /* When reading the file, the first index of the analog channels
+ * can only be deduced through the "total probes" count, so the
+ * first analog index must follow the last logic one, enabled or not. */
+ if (enabled_logic_channels > 0)
+ outc->first_analog_index = logic_channels + 1;
+ else
+ outc->first_analog_index = 1;
+
+ /* Only set capturefile and probes if we will actually save logic data. */
+ if (enabled_logic_channels > 0) {
+ g_key_file_set_string(meta, devgroup, "capturefile", "logic-1");
+ g_key_file_set_integer(meta, devgroup, "total probes", logic_channels);
+ }
+
+ s = sr_samplerate_string(outc->samplerate);
+ g_key_file_set_string(meta, devgroup, "samplerate", s);
+ g_free(s);
+
+ g_key_file_set_integer(meta, devgroup, "total analog", enabled_analog_channels);
+
+ /* Make the array one entry larger than needed so we can use the final
+ * entry as terminator, which is set to -1. */
+ outc->analog_index_map = g_malloc0(sizeof(gint) * (enabled_analog_channels + 1));
+ outc->analog_index_map[enabled_analog_channels] = -1;
+ index = 0;
for (l = o->sdi->channels; l; l = l->next) {
ch = l->data;
+ if (!ch->enabled)
+ continue;
+
switch (ch->type) {
- case SR_CHANNEL_LOGIC:
- s = g_strdup_printf("probe%d", ch->index + 1);
- break;
- case SR_CHANNEL_ANALOG:
- s = g_strdup_printf("analog%d", ch->index + 1);
- break;
+ case SR_CHANNEL_LOGIC:
+ s = g_strdup_printf("probe%d", ch->index + 1);
+ break;
+ case SR_CHANNEL_ANALOG:
+ outc->analog_index_map[index] = ch->index;
+ s = g_strdup_printf("analog%d", outc->first_analog_index + index);
+ index++;
+ break;
}
- if (ch->enabled)
- g_key_file_set_string(meta, devgroup, s, ch->name);
+ g_key_file_set_string(meta, devgroup, s, ch->name);
g_free(s);
}
float *chunkbuf;
gsize chunksize;
char *chunkname;
- unsigned int next_chunk_num;
+ unsigned int next_chunk_num, index;
outc = o->priv;
- if (!(archive = zip_open(outc->filename, 0, NULL)))
- return SR_ERR;
-
- if (zip_stat(archive, "metadata", 0, &zs) < 0) {
- sr_err("Failed to open metadata: %s", zip_strerror(archive));
- zip_discard(archive);
- return SR_ERR;
- }
/* TODO: support packets covering multiple channels */
if (g_slist_length(analog->meaning->channels) != 1) {
}
channel = analog->meaning->channels->data;
- basename = g_strdup_printf("analog-1-%u", channel->index + 1);
+ /* When reading the file, analog channels must be consecutive.
+ * Thus we need a global channel index map as we don't know in
+ * which order the channel data comes in. */
+ for (index = 0; outc->analog_index_map[index] != -1; index++)
+ if (outc->analog_index_map[index] == channel->index)
+ break;
+ if (outc->analog_index_map[index] == -1)
+ return SR_ERR_ARG; /* Channel index was not in the list */
+
+ index += outc->first_analog_index;
+
+ if (!(archive = zip_open(outc->filename, 0, NULL)))
+ return SR_ERR;
+
+ if (zip_stat(archive, "metadata", 0, &zs) < 0) {
+ sr_err("Failed to open metadata: %s", zip_strerror(archive));
+ goto err_zip_discard;
+ }
+
+ basename = g_strdup_printf("analog-1-%u", index);
baselen = strlen(basename);
next_chunk_num = 1;
num_files = zip_get_num_entries(archive, 0);
chunksize = sizeof(float) * analog->num_samples;
if (!(chunkbuf = g_try_malloc(chunksize)))
- return SR_ERR;
+ goto err_free_basename;
+
if (sr_analog_to_float(analog, chunkbuf) != SR_OK)
- return SR_ERR;
+ goto err_free_chunkbuf;
analogsrc = zip_source_buffer(archive, chunkbuf, chunksize, FALSE);
chunkname = g_strdup_printf("%s-%u", basename, next_chunk_num);
if (i < 0) {
sr_err("Failed to add chunk '%s': %s", chunkname, zip_strerror(archive));
zip_source_free(analogsrc);
- zip_discard(archive);
- return SR_ERR;
+ goto err_free_chunkbuf;
}
if (zip_close(archive) < 0) {
sr_err("Error saving session file: %s", zip_strerror(archive));
- zip_discard(archive);
- return SR_ERR;
+ goto err_free_chunkbuf;
}
+ g_free(basename);
+ g_free(chunkbuf);
+
return SR_OK;
+
+err_free_chunkbuf:
+ g_free(chunkbuf);
+err_free_basename:
+ g_free(basename);
+err_zip_discard:
+ zip_discard(archive);
+
+ return SR_ERR;
}
static int receive(const struct sr_output *o, const struct sr_datafeed_packet *packet,
outc = o->priv;
g_variant_unref(options[0].def);
+ g_free(outc->analog_index_map);
g_free(outc->filename);
g_free(outc);
o->priv = NULL;