]> sigrok.org Git - pulseview.git/blobdiff - pv/data/decodesignal.cpp
DecodeSignal: Add binary data callback
[pulseview.git] / pv / data / decodesignal.cpp
index 68b17a65d076668b182172bee71f5a30605cb232..2f14914529e2fcf348ab0a0d1cede95f62769af0 100644 (file)
@@ -17,6 +17,7 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <cstring>
 #include <forward_list>
 #include <limits>
 
@@ -78,14 +79,19 @@ const vector< shared_ptr<Decoder> >& DecodeSignal::decoder_stack() const
 void DecodeSignal::stack_decoder(const srd_decoder *decoder)
 {
        assert(decoder);
-       const shared_ptr<Decoder> dec = make_shared<decode::Decoder>(decoder);
 
-       stack_.push_back(dec);
+       // Set name if this decoder is the first in the list or the name is unchanged
+       const srd_decoder* prev_dec =
+               stack_.empty() ? nullptr : stack_.back()->decoder();
+       const QString prev_dec_name =
+               prev_dec ? QString::fromUtf8(prev_dec->name) : QString();
 
-       // Set name if this decoder is the first in the list
-       if (stack_.size() == 1)
+       if ((stack_.empty()) || ((stack_.size() > 0) && (name() == prev_dec_name)))
                set_name(QString::fromUtf8(decoder->name));
 
+       const shared_ptr<Decoder> dec = make_shared<decode::Decoder>(decoder);
+       stack_.push_back(dec);
+
        // Include the newly created decode channels in the channel lists
        update_channel_list();
 
@@ -444,7 +450,7 @@ int64_t DecodeSignal::get_decoded_sample_count(uint32_t segment_id,
        return result;
 }
 
-vector<Row> DecodeSignal::visible_rows() const
+vector<Row> DecodeSignal::get_rows(bool visible_only) const
 {
        lock_guard<mutex> lock(output_mutex_);
 
@@ -452,7 +458,7 @@ vector<Row> DecodeSignal::visible_rows() const
 
        for (const shared_ptr<decode::Decoder>& dec : stack_) {
                assert(dec);
-               if (!dec->shown())
+               if (visible_only && !dec->shown())
                        continue;
 
                const srd_decoder *const decc = dec->decoder();
@@ -502,7 +508,7 @@ void DecodeSignal::get_annotation_subset(
 {
        // Note: We put all vectors and lists on the heap, not the stack
 
-       const vector<Row> rows = visible_rows();
+       const vector<Row> rows = get_rows(true);
 
        // Use forward_lists for faster merging
        forward_list<Annotation> *all_ann_list = new forward_list<Annotation>();
@@ -523,6 +529,61 @@ void DecodeSignal::get_annotation_subset(
        delete all_ann_list;
 }
 
+uint32_t DecodeSignal::get_binary_data_chunk_count(uint32_t segment_id) const
+{
+       uint32_t count = 0;
+
+       try {
+               const DecodeSegment *segment = &(segments_.at(segment_id));
+               count = segment->binary_data.size();
+       } catch (out_of_range&) {
+               // Do nothing
+       }
+
+       return count;
+}
+
+void DecodeSignal::get_binary_data_chunk(uint32_t segment_id, uint32_t chunk_id,
+       const vector<uint8_t> **dest, uint64_t *size)
+{
+       try {
+               const DecodeSegment *segment = &(segments_.at(segment_id));
+               if (dest)
+                       *dest = &(segment->binary_data.at(chunk_id).data);
+               if (size)
+                       *size = segment->binary_data.at(chunk_id).data.size();
+       } catch (out_of_range&) {
+               // Do nothing
+       }
+}
+
+void DecodeSignal::get_binary_data_chunks_merged(uint32_t segment_id,
+       uint64_t start_sample, uint64_t end_sample, vector<uint8_t> *dest) const
+{
+       assert(dest != nullptr);
+
+       try {
+               const DecodeSegment *segment = &(segments_.at(segment_id));
+
+               // Determine overall size before copying to resize dest vector only once
+               uint64_t size = 0;
+               for (const DecodeBinaryData& d : segment->binary_data)
+                       if ((d.sample >= start_sample) && (d.sample < end_sample))
+                               size += d.data.size();
+               dest->reserve(size);
+
+               uint64_t index = 0;
+               for (const DecodeBinaryData& d : segment->binary_data)
+                       if ((d.sample >= start_sample) && (d.sample < end_sample)) {
+                               memcpy(dest->data() + index, d.data.data(), d.data.size());
+                               index += d.data.size();
+                       }
+       } catch (out_of_range&) {
+               // Do nothing
+       }
+}
+
+
 void DecodeSignal::save_settings(QSettings &settings) const
 {
        SignalBase::save_settings(settings);
@@ -535,6 +596,7 @@ void DecodeSignal::save_settings(QSettings &settings) const
                settings.beginGroup("decoder" + QString::number(decoder_idx++));
 
                settings.setValue("id", decoder->decoder()->id);
+               settings.setValue("shown", decoder->shown());
 
                // Save decoder options
                const map<string, GVariant*>& options = decoder->options();
@@ -603,6 +665,7 @@ void DecodeSignal::restore_settings(QSettings &settings)
                                        make_shared<decode::Decoder>(dec);
 
                                stack_.push_back(decoder);
+                               decoder->show(settings.value("shown", true).toBool());
 
                                // Restore decoder options that differ from their default
                                int options = settings.value("options").toInt();
@@ -1147,6 +1210,9 @@ void DecodeSignal::start_srd_session()
        srd_pd_output_callback_add(srd_session_, SRD_OUTPUT_ANN,
                DecodeSignal::annotation_callback, this);
 
+       srd_pd_output_callback_add(srd_session_, SRD_OUTPUT_BINARY,
+               DecodeSignal::binary_callback, this);
+
        srd_session_start(srd_session_);
 
        // We just recreated the srd session, so all stack changes are applied now
@@ -1252,19 +1318,19 @@ void DecodeSignal::annotation_callback(srd_proto_data *pdata, void *decode_signa
 
        lock_guard<mutex> lock(ds->output_mutex_);
 
-       // Find the row
+       // Get the decoder and the annotation data
        assert(pdata->pdo);
        assert(pdata->pdo->di);
        const srd_decoder *const decc = pdata->pdo->di->decoder;
        assert(decc);
 
-       const srd_proto_data_annotation *const pda =
-               (const srd_proto_data_annotation*)pdata->data;
+       const srd_proto_data_annotation *const pda = (const srd_proto_data_annotation*)pdata->data;
        assert(pda);
 
+       // Find the row
        auto row_iter = ds->segments_.at(ds->current_segment_id_).annotation_rows.end();
 
-       // Try looking up the sub-row of this class
+       // Try finding a better row match than the default by looking up the sub-row of this class
        const auto format = pda->ann_class;
        const auto r = ds->class_rows_.find(make_pair(decc, format));
        if (r != ds->class_rows_.end())
@@ -1285,6 +1351,32 @@ void DecodeSignal::annotation_callback(srd_proto_data *pdata, void *decode_signa
        (*row_iter).second.emplace_annotation(pdata, &((*row_iter).first));
 }
 
+void DecodeSignal::binary_callback(srd_proto_data *pdata, void *decode_signal)
+{
+       assert(pdata);
+       assert(decode_signal);
+
+       DecodeSignal *const ds = (DecodeSignal*)decode_signal;
+       assert(ds);
+
+       if (ds->decode_interrupt_)
+               return;
+
+       const srd_proto_data_binary *const pdb = (const srd_proto_data_binary*)pdata->data;
+       assert(pdb);
+
+       DecodeSegment* segment = &(ds->segments_.at(ds->current_segment_id_));
+
+       segment->binary_data.emplace_back();
+       DecodeBinaryData* bin_data = &(segment->binary_data.back());
+
+       bin_data->sample = pdata->start_sample;
+       bin_data->data.reserve(pdb->size);
+       memcpy(bin_data->data.data(), pdb->data, pdb->size);
+
+       ds->new_binary_data(ds->current_segment_id_);
+}
+
 void DecodeSignal::on_capture_state_changed(int state)
 {
        // If a new acquisition was started, we need to start decoding from scratch