X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=pv%2Fdata%2Fdecodesignal.cpp;h=77784de07f84dcdce9431ef03fc634de56aed02e;hb=88a2597864920ecdbe66cf0cd4b8172bdabb2263;hp=a66e69d967b9fe7c54363da06e0f5703df6798e2;hpb=6a26fc4417798ab21654197e105e707a14d462f0;p=pulseview.git diff --git a/pv/data/decodesignal.cpp b/pv/data/decodesignal.cpp index a66e69d9..77784de0 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,7 +83,7 @@ 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); // Include the newly created decode channels in the channel lists @@ -136,8 +131,8 @@ bool DecodeSignal::toggle_decoder_visibility(int index) // Toggle decoder visibility bool state = false; if (dec) { - state = !dec->shown(); - dec->show(state); + state = !dec->visible(); + dec->set_visible(state); } return state; @@ -145,6 +140,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 +159,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(); @@ -437,7 +432,7 @@ vector DecodeSignal::get_rows(bool visible_only) for (const shared_ptr& dec : stack_) { assert(dec); - if (visible_only && !dec->shown()) + if (visible_only && !dec->visible()) continue; for (Row* row : dec->get_rows()) @@ -453,7 +448,7 @@ vector DecodeSignal::get_rows(bool visible_only) const for (const shared_ptr& dec : stack_) { assert(dec); - if (visible_only && !dec->shown()) + if (visible_only && !dec->visible()) continue; for (const Row* row : dec->get_rows()) @@ -474,17 +469,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 +491,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 +642,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); @@ -679,7 +667,7 @@ void DecodeSignal::save_settings(QSettings &settings) const settings.beginGroup("decoder" + QString::number(decoder_idx++)); settings.setValue("id", decoder->get_srd_decoder()->id); - settings.setValue("shown", decoder->shown()); + settings.setValue("visible", decoder->visible()); // Save decoder options const map& options = decoder->options(); @@ -697,6 +685,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,10 +750,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()); stack_.push_back(decoder); - decoder->show(settings.value("shown", true).toBool()); + decoder->set_visible(settings.value("visible", true).toBool()); // Restore decoder options that differ from their default int options = settings.value("options").toInt(); @@ -762,6 +768,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->visible = settings.value("visible", true).toBool(); + settings.endGroup(); + i++; + } + break; } } @@ -773,7 +798,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 +1392,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 +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 @@ -1411,15 +1439,50 @@ void DecodeSignal::annotation_callback(srd_proto_data *pdata, void *decode_signa assert(dec); AnnotationClass* ann_class = dec->get_ann_class_by_id(pda->ann_class); - assert(ann_class); + if (!ann_class) { + qWarning() << "Decoder" << ds->display_name() << "wanted to add annotation" << + "with class ID" << pda->ann_class << "but there are only" << + dec->ann_classes().size() << "known classes"; + return; + } const Row* row = ann_class->row; 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); + + // Add the annotation to the global annotation list + deque& all_annotations = + ds->segments_[ds->current_segment_id_].all_annotations; + 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)