X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=pv%2Fdata%2Fdecodesignal.cpp;h=811aff65589529887d8b57b7924c6df05b5024f2;hb=86d4b8e3e52a422fe3a6956d6bbef27f1859717b;hp=a488817525ec9f64a6e08400e3812a7e07ef28e5;hpb=f54e68b03d5d24c7787962fcc701d8d52b0ec8ab;p=pulseview.git diff --git a/pv/data/decodesignal.cpp b/pv/data/decodesignal.cpp index a4888175..811aff65 100644 --- a/pv/data/decodesignal.cpp +++ b/pv/data/decodesignal.cpp @@ -358,7 +358,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; @@ -1420,6 +1420,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 @@ -1453,10 +1456,62 @@ void DecodeSignal::annotation_callback(srd_proto_data *pdata, void *decode_signa // Add the annotation to the row const Annotation* ann = row_data.emplace_annotation(pdata); - // Add the annotation to the global annotation list + // 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; - all_annotations.emplace_back(ann); + + 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)