+/**
+ * Queue analog data of a channel for srzip archive writes.
+ *
+ * @param[in] o Output module instance.
+ * @param[in] analog Sample data (session feed packet format).
+ * @param[in] flush Force ZIP archive update (queue by default).
+ *
+ * @returns SR_OK et al error codes.
+ */
+static int zip_append_analog_queue(const struct sr_output *o,
+ const struct sr_datafeed_analog *analog, gboolean flush)
+{
+ struct out_context *outc;
+ const struct sr_channel *ch;
+ size_t idx, nr;
+ struct analog_buff *buff;
+ float *values, *wrptr, *rdptr;
+ size_t send_size, remain, copy_size;
+ int ret;
+
+ outc = o->priv;
+
+ /* Is this the DF_END flush call without samples submission? */
+ if (!analog && flush) {
+ for (idx = 0; idx < outc->analog_ch_count; idx++) {
+ nr = outc->first_analog_index + idx;
+ buff = &outc->analog_buff[idx];
+ if (!buff->fill_size)
+ continue;
+ ret = zip_append_analog(o,
+ buff->samples, buff->fill_size, nr);
+ if (ret != SR_OK)
+ return ret;
+ buff->fill_size = 0;
+ }
+ return SR_OK;
+ }
+
+ /* Lookup index and number of the analog channel. */
+ /* TODO: support packets covering multiple channels */
+ if (g_slist_length(analog->meaning->channels) != 1) {
+ sr_err("Analog packets covering multiple channels not supported yet");
+ return SR_ERR;
+ }
+ ch = g_slist_nth_data(analog->meaning->channels, 0);
+ for (idx = 0; idx < outc->analog_ch_count; idx++) {
+ if (outc->analog_index_map[idx] == ch->index)
+ break;
+ }
+ if (idx == outc->analog_ch_count)
+ return SR_ERR_ARG;
+ nr = outc->first_analog_index + idx;
+ buff = &outc->analog_buff[idx];
+
+ /* Convert the analog data to an array of float values. */
+ values = g_try_malloc0(analog->num_samples * sizeof(values[0]));
+ if (!values)
+ return SR_ERR_MALLOC;
+ ret = sr_analog_to_float(analog, values);
+ if (ret != SR_OK) {
+ g_free(values);
+ return ret;
+ }
+
+ /*
+ * Queue most recently received samples to the local buffer.
+ * Flush to the ZIP archive when the buffer space is exhausted.
+ */
+ rdptr = values;
+ send_size = analog->num_samples;
+ while (send_size) {
+ remain = buff->alloc_size - buff->fill_size;
+ if (remain) {
+ wrptr = &buff->samples[buff->fill_size];
+ copy_size = MIN(send_size, remain);
+ send_size -= copy_size;
+ buff->fill_size += copy_size;
+ memcpy(wrptr, rdptr, copy_size * sizeof(values[0]));
+ rdptr += copy_size;
+ remain -= copy_size;
+ }
+ if (send_size && !remain) {
+ ret = zip_append_analog(o,
+ buff->samples, buff->fill_size, nr);
+ if (ret != SR_OK) {
+ g_free(values);
+ return ret;
+ }
+ buff->fill_size = 0;
+ remain = buff->alloc_size - buff->fill_size;
+ }
+ }
+ g_free(values);