X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=pv%2Fdata%2Fdecodesignal.cpp;h=98275bad4b5f3fb17c84830ad916f5d3906ae533;hb=20c99cfc69d3c7430817abd9a1f810698deb4a18;hp=8d606d43dd9b87c9b4ce5b9c7eda5426d4a4f61a;hpb=56c4de9ada023505b16b6d188fb77d9fb10e52e1;p=pulseview.git diff --git a/pv/data/decodesignal.cpp b/pv/data/decodesignal.cpp index 8d606d43..98275bad 100644 --- a/pv/data/decodesignal.cpp +++ b/pv/data/decodesignal.cpp @@ -33,7 +33,6 @@ #include #include -using std::forward_list; using std::lock_guard; using std::make_shared; using std::min; @@ -84,9 +83,12 @@ void DecodeSignal::stack_decoder(const srd_decoder *decoder, bool restart_decode if ((stack_.empty()) || ((stack_.size() > 0) && (name() == prev_dec_name))) set_name(QString::fromUtf8(decoder->name)); - const shared_ptr dec = make_shared(decoder); + const shared_ptr dec = make_shared(decoder, stack_.size()); stack_.push_back(dec); + connect(dec.get(), SIGNAL(annotation_visibility_changed()), + this, SLOT(on_annotation_visibility_changed())); + // Include the newly created decode channels in the channel lists update_channel_list(); @@ -106,11 +108,12 @@ void DecodeSignal::remove_decoder(int index) assert(index < (int)stack_.size()); // Find the decoder in the stack - auto iter = stack_.begin(); - for (int i = 0; i < index; i++, iter++) - assert(iter != stack_.end()); + auto iter = stack_.begin() + index; + assert(iter != stack_.end()); + + shared_ptr dec = *iter; - decoder_removed(iter->get()); + decoder_removed(dec.get()); // Delete the element stack_.erase(iter); @@ -141,6 +144,8 @@ bool DecodeSignal::toggle_decoder_visibility(int index) void DecodeSignal::reset_decode(bool shutting_down) { + resume_decode(); // Make sure the decode thread isn't blocked by pausing + if (stack_config_changed_ || shutting_down) stop_srd_session(); else @@ -158,8 +163,6 @@ void DecodeSignal::reset_decode(bool shutting_down) logic_mux_thread_.join(); } - resume_decode(); // Make sure the decode thread isn't blocked by pausing - current_segment_id_ = 0; segments_.clear(); @@ -359,7 +362,7 @@ void DecodeSignal::set_initial_pin_state(const uint16_t channel_id, const int in begin_decode(); } -double DecodeSignal::samplerate() const +double DecodeSignal::get_samplerate() const { double result = 0; @@ -643,6 +646,19 @@ const DecodeBinaryClass* DecodeSignal::get_binary_data_class(uint32_t segment_id return nullptr; } +const deque* DecodeSignal::get_all_annotations_by_segment( + uint32_t segment_id) const +{ + try { + const DecodeSegment *segment = &(segments_.at(segment_id)); + return &(segment->all_annotations); + } catch (out_of_range&) { + // Do nothing + } + + return nullptr; +} + void DecodeSignal::save_settings(QSettings &settings) const { SignalBase::save_settings(settings); @@ -686,7 +702,7 @@ void DecodeSignal::save_settings(QSettings &settings) const i = 0; for (const AnnotationClass* ann_class : decoder->ann_classes()) { settings.beginGroup("ann_class" + QString::number(i)); - settings.setValue("visible", ann_class->visible); + settings.setValue("visible", ann_class->visible()); settings.endGroup(); i++; } @@ -738,7 +754,10 @@ void DecodeSignal::restore_settings(QSettings &settings) continue; if (QString::fromUtf8(dec->id) == id) { - shared_ptr decoder = make_shared(dec); + shared_ptr decoder = make_shared(dec, stack_.size()); + + connect(decoder.get(), SIGNAL(annotation_visibility_changed()), + this, SLOT(on_annotation_visibility_changed())); stack_.push_back(decoder); decoder->set_visible(settings.value("visible", true).toBool()); @@ -770,7 +789,7 @@ void DecodeSignal::restore_settings(QSettings &settings) i = 0; for (AnnotationClass* ann_class : decoder->ann_classes()) { settings.beginGroup("ann_class" + QString::number(i)); - ann_class->visible = settings.value("visible", true).toBool(); + ann_class->set_visible(settings.value("visible", true).toBool()); settings.endGroup(); i++; } @@ -803,7 +822,7 @@ void DecodeSignal::restore_settings(QSettings &settings) QString assigned_signal_name = settings.value("assigned_signal_name").toString(); for (const shared_ptr& signal : signalbases) - if (signal->name() == assigned_signal_name) + if ((signal->name() == assigned_signal_name) && (signal->type() != SignalBase::DecodeChannel)) channel->assigned_signal = signal.get(); channel->initial_pin_state = settings.value("initial_pin_state").toInt(); @@ -1380,7 +1399,7 @@ void DecodeSignal::connect_input_notifiers() void DecodeSignal::create_decode_segment() { // Create annotation segment - segments_.emplace_back(DecodeSegment()); + segments_.emplace_back(); // Add annotation classes for (const shared_ptr& dec : stack_) @@ -1408,6 +1427,9 @@ void DecodeSignal::annotation_callback(srd_proto_data *pdata, void *decode_signa if (ds->decode_interrupt_) return; + if (ds->segments_.empty()) + return; + lock_guard lock(ds->output_mutex_); // Get the decoder and the annotation data @@ -1436,8 +1458,67 @@ void DecodeSignal::annotation_callback(srd_proto_data *pdata, void *decode_signa if (!row) row = dec->get_row_by_id(0); - // Add the annotation - ds->segments_[ds->current_segment_id_].annotation_rows.at(row).emplace_annotation(pdata); + RowData& row_data = ds->segments_[ds->current_segment_id_].annotation_rows.at(row); + + // Add the annotation to the row + const Annotation* ann = row_data.emplace_annotation(pdata); + + // We insert the annotation into the global annotation list in a way so that + // the annotation list is sorted by start sample and length. Otherwise, we'd + // have to sort the model, which is expensive + deque& all_annotations = + ds->segments_[ds->current_segment_id_].all_annotations; + + if (all_annotations.empty()) { + all_annotations.emplace_back(ann); + } else { + const uint64_t new_ann_len = (pdata->end_sample - pdata->start_sample); + bool ann_has_earlier_start = (pdata->start_sample < all_annotations.back()->start_sample()); + bool ann_is_longer = (new_ann_len > + (all_annotations.back()->end_sample() - all_annotations.back()->start_sample())); + + if (ann_has_earlier_start && ann_is_longer) { + bool ann_has_same_start; + auto it = all_annotations.end(); + + do { + it--; + ann_has_earlier_start = (pdata->start_sample < (*it)->start_sample()); + ann_has_same_start = (pdata->start_sample == (*it)->start_sample()); + ann_is_longer = (new_ann_len > (*it)->length()); + } while ((ann_has_earlier_start || (ann_has_same_start && ann_is_longer)) && (it != all_annotations.begin())); + + // Allow inserting at the front + if (it != all_annotations.begin()) + it++; + + all_annotations.emplace(it, ann); + } else + all_annotations.emplace_back(ann); + } + + // When emplace_annotation() inserts instead of appends an annotation, + // the pointers in all_annotations that follow the inserted annotation and + // point to annotations for this row are off by one and must be updated + if (&(row_data.annotations().back()) != ann) { + // Search backwards until we find the annotation we just added + auto row_it = row_data.annotations().end(); + auto all_it = all_annotations.end(); + do { + all_it--; + if ((*all_it)->row_data() == &row_data) + row_it--; + } while (&(*row_it) != ann); + + // Update the annotation addresses for this row's annotations until the end + do { + if ((*all_it)->row_data() == &row_data) { + *all_it = &(*row_it); + row_it++; + } + all_it++; + } while (all_it != all_annotations.end()); + } } void DecodeSignal::binary_callback(srd_proto_data *pdata, void *decode_signal) @@ -1517,5 +1598,10 @@ void DecodeSignal::on_data_received() logic_mux_cond_.notify_one(); } +void DecodeSignal::on_annotation_visibility_changed() +{ + annotation_visibility_changed(); +} + } // namespace data } // namespace pv