]> sigrok.org Git - pulseview.git/blobdiff - pv/session.cpp
LogicSegment: Don't use new/delete in get_unpacked_sample()
[pulseview.git] / pv / session.cpp
index a44ceb99b669aec396c97d92c19c733a6f489698..605cc05c65fd8ab234f5509d5885f30f276f805d 100644 (file)
@@ -681,11 +681,12 @@ int Session::get_segment_count() const
 {
        int min_val = INT_MAX;
 
+       // Find the lowest common number of segments
        for (shared_ptr<data::SignalData> data : all_signal_data_)
                if (data->get_segment_count() < min_val)
                        min_val = data->get_segment_count();
 
-       return min_val;
+       return (min_val != INT_MAX) ? min_val : 0;
 }
 
 const unordered_set< shared_ptr<data::SignalBase> > Session::signalbases() const
@@ -899,6 +900,13 @@ void Session::sample_thread_proc(function<void (const QString)> error_handler)
 
        out_of_memory_ = false;
 
+       {
+               lock_guard<recursive_mutex> lock(data_mutex_);
+               cur_logic_segment_.reset();
+               cur_analog_segments_.clear();
+       }
+       highest_segment_id_ = -1;
+
        try {
                device_->start();
        } catch (Error e) {
@@ -950,9 +958,60 @@ void Session::free_unused_memory()
        }
 }
 
+void Session::signal_new_segment()
+{
+       int new_segment_id = 0;
+
+       if ((cur_logic_segment_ != nullptr) || !cur_analog_segments_.empty()) {
+
+               // Determine new frame/segment number, assuming that all
+               // signals have the same number of frames/segments
+               if (cur_logic_segment_) {
+                       new_segment_id = logic_data_->get_segment_count() - 1;
+               } else {
+                       shared_ptr<sigrok::Channel> any_channel =
+                               (*cur_analog_segments_.begin()).first;
+
+                       shared_ptr<data::SignalBase> base = signalbase_from_channel(any_channel);
+                       assert(base);
+
+                       shared_ptr<data::Analog> data(base->analog_data());
+                       assert(data);
+
+                       new_segment_id = data->get_segment_count() - 1;
+               }
+       }
+
+       if (new_segment_id > highest_segment_id_) {
+               highest_segment_id_ = new_segment_id;
+               new_segment(highest_segment_id_);
+       }
+}
+
+void Session::signal_segment_completed()
+{
+       int segment_id = 0;
+
+       for (shared_ptr<data::SignalBase> signalbase : signalbases_) {
+               // We only care about analog and logic channels, not derived ones
+               if (signalbase->type() == data::SignalBase::AnalogChannel) {
+                       segment_id = signalbase->analog_data()->get_segment_count() - 1;
+                       break;
+               }
+
+               if (signalbase->type() == data::SignalBase::LogicChannel) {
+                       segment_id = signalbase->logic_data()->get_segment_count() - 1;
+                       break;
+               }
+       }
+
+       if (segment_id >= 0)
+               segment_completed(segment_id);
+}
+
 void Session::feed_in_header()
 {
-       cur_samplerate_ = device_->read_config<uint64_t>(ConfigKey::SAMPLERATE);
+       // Nothing to do here for now
 }
 
 void Session::feed_in_meta(shared_ptr<Meta> meta)
@@ -1002,27 +1061,39 @@ void Session::feed_in_trigger()
 void Session::feed_in_frame_begin()
 {
        frame_began_ = true;
-
-       if (cur_logic_segment_ || !cur_analog_segments_.empty())
-               frame_began();
 }
 
 void Session::feed_in_frame_end()
 {
+       if (!frame_began_)
+               return;
+
        {
                lock_guard<recursive_mutex> lock(data_mutex_);
+
+               if (cur_logic_segment_)
+                       cur_logic_segment_->set_complete();
+
+               for (auto entry : cur_analog_segments_) {
+                       shared_ptr<data::AnalogSegment> segment = entry.second;
+                       segment->set_complete();
+               }
+
                cur_logic_segment_.reset();
                cur_analog_segments_.clear();
        }
 
-       if (frame_began_) {
+       if (frame_began_)
                frame_began_ = false;
-               frame_ended();
-       }
+
+       signal_segment_completed();
 }
 
 void Session::feed_in_logic(shared_ptr<Logic> logic)
 {
+       if (!cur_samplerate_)
+               cur_samplerate_ = device_->read_config<uint64_t>(ConfigKey::SAMPLERATE);
+
        lock_guard<recursive_mutex> lock(data_mutex_);
 
        if (!logic_data_) {
@@ -1041,11 +1112,7 @@ void Session::feed_in_logic(shared_ptr<Logic> logic)
                        *logic_data_, logic->unit_size(), cur_samplerate_);
                logic_data_->push_segment(cur_logic_segment_);
 
-               // @todo Putting this here means that only listeners querying
-               // for logic will be notified. Currently the only user of
-               // frame_began is DecoderStack, but in future we need to signal
-               // this after both analog and logic sweeps have begun.
-               frame_began();
+               signal_new_segment();
        }
 
        cur_logic_segment_->append_payload(logic);
@@ -1055,6 +1122,9 @@ void Session::feed_in_logic(shared_ptr<Logic> logic)
 
 void Session::feed_in_analog(shared_ptr<Analog> analog)
 {
+       if (!cur_samplerate_)
+               cur_samplerate_ = device_->read_config<uint64_t>(ConfigKey::SAMPLERATE);
+
        lock_guard<recursive_mutex> lock(data_mutex_);
 
        const vector<shared_ptr<Channel>> channels = analog->channels();
@@ -1062,7 +1132,7 @@ void Session::feed_in_analog(shared_ptr<Analog> analog)
        const size_t sample_count = analog->num_samples() / channel_count;
        bool sweep_beginning = false;
 
-       unique_ptr<float> data(new float[analog->num_samples()]);
+       unique_ptr<float[]> data(new float[analog->num_samples()]);
        analog->get_data_as_float(data.get());
 
        if (signalbases_.empty())
@@ -1097,6 +1167,8 @@ void Session::feed_in_analog(shared_ptr<Analog> analog)
 
                        // Push the segment into the analog data.
                        data->push_segment(segment);
+
+                       signal_new_segment();
                }
 
                assert(segment);