X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=pv%2Fdata%2Fdecodesignal.cpp;h=28157794208c6fbf4a7b65be20b76773bb21b189;hb=f9a0fd83226d97af7458d8c9dac0b88c83a54d29;hp=d6eb924755b15452323c684cf2bdc285cd774a2c;hpb=5d3ca591b02ce030239ad4b86d9b172b925b4c5d;p=pulseview.git diff --git a/pv/data/decodesignal.cpp b/pv/data/decodesignal.cpp index d6eb9247..28157794 100644 --- a/pv/data/decodesignal.cpp +++ b/pv/data/decodesignal.cpp @@ -33,19 +33,14 @@ #include #include -using std::forward_list; using std::lock_guard; -using std::make_pair; using std::make_shared; using std::min; using std::out_of_range; using std::shared_ptr; using std::unique_lock; -using pv::data::decode::Annotation; using pv::data::decode::AnnotationClass; using pv::data::decode::DecodeChannel; -using pv::data::decode::Decoder; -using pv::data::decode::Row; namespace pv { namespace data { @@ -88,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(); @@ -110,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); @@ -145,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 @@ -162,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(); @@ -363,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; @@ -474,17 +473,15 @@ uint64_t DecodeSignal::get_annotation_count(const Row* row, uint32_t segment_id) auto row_it = segment->annotation_rows.find(row); const RowData* rd; - if (row_it == segment->annotation_rows.end()) { - // FIXME Use the fallback row, but how? - assert(false); + if (row_it == segment->annotation_rows.end()) return 0; - } else + else rd = &(row_it->second); return rd->get_annotation_count(); } -void DecodeSignal::get_annotation_subset(vector &dest, +void DecodeSignal::get_annotation_subset(deque &dest, const Row* row, uint32_t segment_id, uint64_t start_sample, uint64_t end_sample) const { @@ -498,37 +495,19 @@ void DecodeSignal::get_annotation_subset(vector &dest, auto row_it = segment->annotation_rows.find(row); const RowData* rd; - if (row_it == segment->annotation_rows.end()) { - // FIXME Use the fallback row, but how? - assert(false); + if (row_it == segment->annotation_rows.end()) return; - } else + else rd = &(row_it->second); rd->get_annotation_subset(dest, start_sample, end_sample); } -void DecodeSignal::get_annotation_subset(vector &dest, +void DecodeSignal::get_annotation_subset(deque &dest, uint32_t segment_id, uint64_t start_sample, uint64_t end_sample) const { - // Use forward_lists for faster merging - forward_list *all_ann_list = new forward_list(); - - vector rows = get_rows(); - for (const Row* row : rows) { - vector *ann_vector = new vector(); - get_annotation_subset(*ann_vector, row, segment_id, start_sample, end_sample); - - forward_list *ann_list = - new forward_list(ann_vector->begin(), ann_vector->end()); - delete ann_vector; - - all_ann_list->merge(*ann_list); - delete ann_list; - } - - move(all_ann_list->begin(), all_ann_list->end(), back_inserter(dest)); - delete all_ann_list; + for (const Row* row : get_rows()) + get_annotation_subset(dest, row, segment_id, start_sample, end_sample); } uint32_t DecodeSignal::get_binary_data_chunk_count(uint32_t segment_id, @@ -667,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); @@ -697,6 +689,24 @@ void DecodeSignal::save_settings(QSettings &settings) const i++; } + // Save row properties + i = 0; + for (const Row* row : decoder->get_rows()) { + settings.beginGroup("row" + QString::number(i)); + settings.setValue("visible", row->visible()); + settings.endGroup(); + i++; + } + + // Save class properties + i = 0; + for (const AnnotationClass* ann_class : decoder->ann_classes()) { + settings.beginGroup("ann_class" + QString::number(i)); + settings.setValue("visible", ann_class->visible()); + settings.endGroup(); + i++; + } + settings.endGroup(); } @@ -744,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()); @@ -762,6 +775,25 @@ void DecodeSignal::restore_settings(QSettings &settings) // Include the newly created decode channels in the channel lists update_channel_list(); + + // Restore row properties + int i = 0; + for (Row* row : decoder->get_rows()) { + settings.beginGroup("row" + QString::number(i)); + row->set_visible(settings.value("visible", true).toBool()); + settings.endGroup(); + i++; + } + + // Restore class properties + i = 0; + for (AnnotationClass* ann_class : decoder->ann_classes()) { + settings.beginGroup("ann_class" + QString::number(i)); + ann_class->set_visible(settings.value("visible", true).toBool()); + settings.endGroup(); + i++; + } + break; } } @@ -773,7 +805,7 @@ void DecodeSignal::restore_settings(QSettings &settings) // Restore channel mapping unsigned int channels = settings.value("channels").toInt(); - const unordered_set< shared_ptr > signalbases = + const vector< shared_ptr > signalbases = session_.signalbases(); for (unsigned int channel_id = 0; channel_id < channels; channel_id++) { @@ -1367,10 +1399,10 @@ 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_) + for (const shared_ptr& dec : stack_) for (Row* row : dec->get_rows()) segments_.back().annotation_rows.emplace(row, RowData(row)); @@ -1395,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 @@ -1423,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) @@ -1504,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