Make sure PD row colors remain constant by adding a row index
[pulseview.git] / pv / data / decodesignal.cpp
index d17c883c4b380eaac155ae1d04c88d7cfa16330b..9da7de6766c418e759ea1f02d88ba8ab8614c551 100644 (file)
@@ -209,6 +209,7 @@ void DecodeSignal::begin_decode()
                }
 
        // Map out all the annotation classes
+       int row_index = 0;
        for (const shared_ptr<decode::Decoder> &dec : stack_) {
                assert(dec);
                const srd_decoder *const decc = dec->decoder();
@@ -219,7 +220,7 @@ void DecodeSignal::begin_decode()
                                (srd_decoder_annotation_row *)l->data;
                        assert(ann_row);
 
-                       const Row row(decc, ann_row);
+                       const Row row(row_index++, decc, ann_row);
 
                        for (const GSList *ll = ann_row->ann_classes;
                                ll; ll = ll->next)
@@ -279,16 +280,33 @@ void DecodeSignal::auto_assign_signals(const shared_ptr<Decoder> dec)
                if (ch.assigned_signal)
                        continue;
 
+               const QString ch_name = ch.name.toLower();
+
+               shared_ptr<data::SignalBase> match;
                for (shared_ptr<data::SignalBase> s : session_.signalbases()) {
-                       const QString ch_name = ch.name.toLower();
+                       if (!s->enabled())
+                               continue;
+
                        const QString s_name = s->name().toLower();
 
                        if (s->logic_data() &&
                                ((ch_name.contains(s_name)) || (s_name.contains(ch_name)))) {
-                               ch.assigned_signal = s.get();
-                               new_assignment = true;
+                               if (!match)
+                                       match = s;
+                               else {
+                                       // Only replace an existing match if it matches more characters
+                                       int old_unmatched = ch_name.length() - match->name().length();
+                                       int new_unmatched = ch_name.length() - s->name().length();
+                                       if (abs(new_unmatched) < abs(old_unmatched))
+                                               match = s;
+                               }
                        }
                }
+
+               if (match) {
+                       ch.assigned_signal = match.get();
+                       new_assignment = true;
+               }
        }
 
        if (new_assignment) {
@@ -381,7 +399,8 @@ int64_t DecodeSignal::get_working_sample_count(uint32_t segment_id) const
        return (no_signals_assigned ? 0 : count);
 }
 
-int64_t DecodeSignal::get_decoded_sample_count(uint32_t segment_id) const
+int64_t DecodeSignal::get_decoded_sample_count(uint32_t segment_id,
+       bool include_processing) const
 {
        lock_guard<mutex> decode_lock(output_mutex_);
 
@@ -389,7 +408,10 @@ int64_t DecodeSignal::get_decoded_sample_count(uint32_t segment_id) const
 
        try {
                const DecodeSegment *segment = &(segments_.at(segment_id));
-               result = segment->samples_decoded;
+               if (include_processing)
+                       result = segment->samples_decoded_incl;
+               else
+                       result = segment->samples_decoded_excl;
        } catch (out_of_range&) {
                // Do nothing
        }
@@ -411,16 +433,17 @@ vector<Row> DecodeSignal::visible_rows() const
                const srd_decoder *const decc = dec->decoder();
                assert(dec->decoder());
 
+               int row_index = 0;
                // Add a row for the decoder if it doesn't have a row list
                if (!decc->annotation_rows)
-                       rows.emplace_back(decc);
+                       rows.emplace_back(row_index++, decc);
 
                // Add the decoder rows
                for (const GSList *l = decc->annotation_rows; l; l = l->next) {
                        const srd_decoder_annotation_row *const ann_row =
                                (srd_decoder_annotation_row *)l->data;
                        assert(ann_row);
-                       rows.emplace_back(decc, ann_row);
+                       rows.emplace_back(row_index++, decc, ann_row);
                }
        }
 
@@ -885,6 +908,7 @@ void DecodeSignal::logic_mux_proc()
                                logic_mux_cond_.wait(logic_mux_lock);
                        }
                }
+
        } while (!logic_mux_interrupt_);
 }
 
@@ -896,17 +920,17 @@ void DecodeSignal::decode_data(
        const int64_t chunk_sample_count = DecodeChunkLength / unit_size;
 
        for (int64_t i = abs_start_samplenum;
-               !decode_interrupt_ && (i < (abs_start_samplenum + sample_count));
+               error_message_.isEmpty() && !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);
 
-               // Report this chunk as already decoded so that annotations don't
-               // appear in an area that we claim to not having been been decoded yet
                {
                        lock_guard<mutex> lock(output_mutex_);
-                       segments_.at(current_segment_id_).samples_decoded = chunk_end;
+                       // Update the sample count showing the samples including currently processed ones
+                       segments_.at(current_segment_id_).samples_decoded_incl = chunk_end;
                }
 
                int64_t data_size = (chunk_end - i) * unit_size;
@@ -914,14 +938,17 @@ void DecodeSignal::decode_data(
                input_segment->get_samples(i, chunk_end, chunk);
 
                if (srd_session_send(srd_session_, i, chunk_end, chunk,
-                               data_size, unit_size) != SRD_OK) {
+                               data_size, unit_size) != SRD_OK)
                        set_error_message(tr("Decoder reported an error"));
-                       delete[] chunk;
-                       break;
-               }
 
                delete[] chunk;
 
+               {
+                       lock_guard<mutex> lock(output_mutex_);
+                       // Now that all samples are processed, the exclusive sample count catches up
+                       segments_.at(current_segment_id_).samples_decoded_excl = chunk_end;
+               }
+
                // Notify the frontend that we processed some data and
                // possibly have new annotations as well
                new_annotations();
@@ -1020,8 +1047,12 @@ void DecodeSignal::start_srd_session()
                terminate_srd_session();
 
                // Metadata is cleared also, so re-set it
-               srd_session_metadata_set(srd_session_, SRD_CONF_SAMPLERATE,
-                       g_variant_new_uint64(segments_.at(current_segment_id_).samplerate));
+               uint64_t samplerate = 0;
+               if (segments_.size() > 0)
+                       samplerate = segments_.at(current_segment_id_).samplerate;
+               if (samplerate)
+                       srd_session_metadata_set(srd_session_, SRD_CONF_SAMPLERATE,
+                               g_variant_new_uint64(samplerate));
                for (const shared_ptr<decode::Decoder> &dec : stack_)
                        dec->apply_all_options();
                srd_session_start(srd_session_);
@@ -1052,8 +1083,9 @@ void DecodeSignal::start_srd_session()
        }
 
        // Start the session
-       srd_session_metadata_set(srd_session_, SRD_CONF_SAMPLERATE,
-               g_variant_new_uint64(segments_.at(current_segment_id_).samplerate));
+       if (segments_.size() > 0)
+               srd_session_metadata_set(srd_session_, SRD_CONF_SAMPLERATE,
+                       g_variant_new_uint64(segments_.at(current_segment_id_).samplerate));
 
        srd_pd_output_callback_add(srd_session_, SRD_OUTPUT_ANN,
                DecodeSignal::annotation_callback, this);
@@ -1075,8 +1107,12 @@ void DecodeSignal::terminate_srd_session()
                srd_session_terminate_reset(srd_session_);
 
                // Metadata is cleared also, so re-set it
-               srd_session_metadata_set(srd_session_, SRD_CONF_SAMPLERATE,
-                       g_variant_new_uint64(segments_.at(current_segment_id_).samplerate));
+               uint64_t samplerate = 0;
+               if (segments_.size() > 0)
+                       samplerate = segments_.at(current_segment_id_).samplerate;
+               if (samplerate)
+                       srd_session_metadata_set(srd_session_, SRD_CONF_SAMPLERATE,
+                               g_variant_new_uint64(samplerate));
                for (const shared_ptr<decode::Decoder> &dec : stack_)
                        dec->apply_all_options();
        }
@@ -1125,9 +1161,10 @@ void DecodeSignal::create_decode_segment()
                const srd_decoder *const decc = dec->decoder();
                assert(dec->decoder());
 
+               int row_index = 0;
                // Add a row for the decoder if it doesn't have a row list
                if (!decc->annotation_rows)
-                       (segments_.back().annotation_rows)[Row(decc)] =
+                       (segments_.back().annotation_rows)[Row(row_index++, decc)] =
                                decode::RowData();
 
                // Add the decoder rows
@@ -1136,7 +1173,7 @@ void DecodeSignal::create_decode_segment()
                                (srd_decoder_annotation_row *)l->data;
                        assert(ann_row);
 
-                       const Row row(decc, ann_row);
+                       const Row row(row_index++, decc, ann_row);
 
                        // Add a new empty row data object
                        (segments_.back().annotation_rows)[row] =
@@ -1177,7 +1214,7 @@ void DecodeSignal::annotation_callback(srd_proto_data *pdata, void *decode_signa
                row_iter = ds->segments_.at(ds->current_segment_id_).annotation_rows.find((*r).second);
        else {
                // Failing that, use the decoder as a key
-               row_iter = ds->segments_.at(ds->current_segment_id_).annotation_rows.find(Row(decc));
+               row_iter = ds->segments_.at(ds->current_segment_id_).annotation_rows.find(Row(0, decc));
        }
 
        if (row_iter == ds->segments_.at(ds->current_segment_id_).annotation_rows.end()) {