+ SignalBase::save_settings(settings);
+
+ // TODO Save decoder stack, channel mapping and decoder options
+}
+
+void DecodeSignal::restore_settings(QSettings &settings)
+{
+ SignalBase::restore_settings(settings);
+
+ // TODO Restore decoder stack, channel mapping and decoder options
+}
+
+uint64_t DecodeSignal::inc_annotation_count()
+{
+ return (annotation_count_++);
+}
+
+void DecodeSignal::update_channel_list()
+{
+ vector<data::DecodeChannel> prev_channels = channels_;
+ channels_.clear();
+
+ uint16_t id = 0;
+
+ // Copy existing entries, create new as needed
+ for (shared_ptr<Decoder> decoder : stack_) {
+ const srd_decoder* srd_d = decoder->decoder();
+ const GSList *l;
+
+ // Mandatory channels
+ for (l = srd_d->channels; l; l = l->next) {
+ const struct srd_channel *const pdch = (struct srd_channel *)l->data;
+ bool ch_added = false;
+
+ // Copy but update ID if this channel was in the list before
+ for (data::DecodeChannel &ch : prev_channels)
+ if (ch.pdch_ == pdch) {
+ ch.id = id++;
+ channels_.push_back(ch);
+ ch_added = true;
+ break;
+ }
+
+ if (!ch_added) {
+ // Create new entry without a mapped signal
+ data::DecodeChannel ch = {id++, false, nullptr,
+ QString::fromUtf8(pdch->name), QString::fromUtf8(pdch->desc),
+ SRD_INITIAL_PIN_SAME_AS_SAMPLE0, decoder, pdch};
+ channels_.push_back(ch);
+ }
+ }
+
+ // Optional channels
+ for (l = srd_d->opt_channels; l; l = l->next) {
+ const struct srd_channel *const pdch = (struct srd_channel *)l->data;
+ bool ch_added = false;
+
+ // Copy but update ID if this channel was in the list before
+ for (data::DecodeChannel &ch : prev_channels)
+ if (ch.pdch_ == pdch) {
+ ch.id = id++;
+ channels_.push_back(ch);
+ ch_added = true;
+ break;
+ }
+
+ if (!ch_added) {
+ // Create new entry without a mapped signal
+ data::DecodeChannel ch = {id++, true, nullptr,
+ QString::fromUtf8(pdch->name), QString::fromUtf8(pdch->desc),
+ SRD_INITIAL_PIN_SAME_AS_SAMPLE0, decoder, pdch};
+ channels_.push_back(ch);
+ }
+ }
+ }
+
+ // Invalidate the logic output data if the channel assignment changed
+ if (prev_channels.size() != channels_.size()) {
+ // The number of channels changed, there's definitely a difference
+ logic_mux_data_invalid_ = true;
+ } else {
+ // Same number but assignment may still differ, so compare all channels
+ for (size_t i = 0; i < channels_.size(); i++) {
+ const data::DecodeChannel &p_ch = prev_channels[i];
+ const data::DecodeChannel &ch = channels_[i];
+
+ if ((p_ch.pdch_ != ch.pdch_) ||
+ (p_ch.assigned_signal != ch.assigned_signal)) {
+ logic_mux_data_invalid_ = true;
+ break;
+ }
+ }
+
+ }
+
+ channels_updated();
+}
+
+void DecodeSignal::logic_mux_proc()
+{
+
+}
+
+optional<int64_t> DecodeSignal::wait_for_data() const
+{
+ unique_lock<mutex> input_lock(input_mutex_);
+
+ // Do wait if we decoded all samples but we're still capturing
+ // Do not wait if we're done capturing
+ while (!decode_interrupt_ && !frame_complete_ &&
+ (samples_decoded_ >= sample_count_) &&
+ (session_.get_capture_state() != Session::Stopped)) {
+
+ decode_input_cond_.wait(input_lock);
+ }
+
+ // Return value is valid if we're not aborting the decode,
+ return boost::make_optional(!decode_interrupt_ &&
+ // and there's more work to do...
+ (samples_decoded_ < sample_count_ || !frame_complete_) &&
+ // and if the end of the data hasn't been reached yet
+ (!((samples_decoded_ >= sample_count_) && (session_.get_capture_state() == Session::Stopped))),
+ sample_count_);
+}
+
+void DecodeSignal::decode_data(
+ const int64_t abs_start_samplenum, const int64_t sample_count,
+ srd_session *const session)
+{
+ const unsigned int unit_size = segment_->unit_size();
+ const unsigned int chunk_sample_count = DecodeChunkLength / unit_size;
+
+ for (int64_t i = abs_start_samplenum;
+ !decode_interrupt_ && (i < (abs_start_samplenum + sample_count));
+ i += chunk_sample_count) {
+
+ const int64_t chunk_end = min(i + chunk_sample_count,
+ abs_start_samplenum + sample_count);
+
+ const uint8_t* chunk = segment_->get_samples(i, chunk_end);
+
+ if (srd_session_send(session, i, chunk_end, chunk,
+ (chunk_end - i) * unit_size, unit_size) != SRD_OK) {
+ error_message_ = tr("Decoder reported an error");
+ delete[] chunk;
+ break;
+ }
+ delete[] chunk;
+
+ {
+ lock_guard<mutex> lock(output_mutex_);
+ samples_decoded_ = chunk_end;
+ }
+ }
+}
+
+void DecodeSignal::decode_proc()
+{
+ optional<int64_t> sample_count;
+ srd_session *session;
+ srd_decoder_inst *prev_di = nullptr;
+
+ // Prevent any other decode threads from accessing libsigrokdecode
+ lock_guard<mutex> srd_lock(global_srd_mutex_);
+
+ // Create the session
+ srd_session_new(&session);
+ assert(session);
+
+ // Create the decoders
+ for (const shared_ptr<decode::Decoder> &dec : stack_) {
+ srd_decoder_inst *const di = dec->create_decoder_inst(session);
+
+ if (!di) {
+ error_message_ = tr("Failed to create decoder instance");
+ srd_session_destroy(session);
+ return;
+ }
+
+ if (prev_di)
+ srd_inst_stack(session, prev_di, di);
+
+ prev_di = di;
+ }
+
+ // Get the initial sample count
+ {
+ unique_lock<mutex> input_lock(input_mutex_);
+ sample_count = sample_count_ = get_working_sample_count();
+ }
+
+ // Start the session
+ srd_session_metadata_set(session, SRD_CONF_SAMPLERATE,
+ g_variant_new_uint64(samplerate_));
+
+ srd_pd_output_callback_add(session, SRD_OUTPUT_ANN,
+ DecodeSignal::annotation_callback, this);
+
+ srd_session_start(session);
+
+ int64_t abs_start_samplenum = 0;
+ do {
+ decode_data(abs_start_samplenum, *sample_count, session);
+ abs_start_samplenum = *sample_count;
+ } while (error_message_.isEmpty() && (sample_count = wait_for_data()));
+
+ // Make sure all annotations are known to the frontend