]> sigrok.org Git - pulseview.git/blobdiff - pv/session.cpp
SignalBase: Add SignalGroup class and handling
[pulseview.git] / pv / session.cpp
index 6b879cf91dcdd4e4b6127cb99a780366042d09a1..9ec8bd07264036e85c052c05695749f4bccf797b 100644 (file)
@@ -105,6 +105,7 @@ using Gst::ElementFactory;
 using Gst::Pipeline;
 #endif
 
+using pv::data::SignalGroup;
 using pv::util::Timestamp;
 using pv::views::trace::Signal;
 using pv::views::trace::AnalogSignal;
@@ -115,6 +116,7 @@ namespace pv {
 shared_ptr<sigrok::Context> Session::sr_context;
 
 Session::Session(DeviceManager &device_manager, QString name) :
+       shutting_down_(false),
        device_manager_(device_manager),
        default_name_(name),
        name_(name),
@@ -126,8 +128,15 @@ Session::Session(DeviceManager &device_manager, QString name) :
 
 Session::~Session()
 {
+       shutting_down_ = true;
+
        // Stop and join to the thread
        stop_capture();
+
+       for (SignalGroup* group : signal_groups_) {
+               group->clear();
+               delete group;
+       }
 }
 
 DeviceManager& Session::device_manager()
@@ -500,14 +509,22 @@ void Session::set_device(shared_ptr<devices::Device> device)
 
        // Remove all stored data and reset all views
        for (shared_ptr<views::ViewBase> view : views_) {
-               view->clear_signals();
+               view->clear_signalbases();
 #ifdef ENABLE_DECODE
                view->clear_decode_signals();
 #endif
                view->reset_view_state();
        }
+
+       for (SignalGroup* group : signal_groups_) {
+               group->clear();
+               delete group;
+       }
+       signal_groups_.clear();
+
        for (const shared_ptr<data::SignalData>& d : all_signal_data_)
                d->clear();
+
        all_signal_data_.clear();
        signalbases_.clear();
        cur_logic_segment_.reset();
@@ -857,15 +874,29 @@ const vector< shared_ptr<data::SignalBase> > Session::signalbases() const
        return signalbases_;
 }
 
-bool Session::all_segments_complete(uint32_t segment_id) const
+void Session::add_generated_signal(shared_ptr<data::SignalBase> signal)
 {
-       bool all_complete = true;
+       signalbases_.push_back(signal);
 
-       for (const shared_ptr<data::SignalBase>& base : signalbases_)
-               if (!base->segment_is_complete(segment_id))
-                       all_complete = false;
+       for (shared_ptr<views::ViewBase>& view : views_)
+               view->add_signalbase(signal);
 
-       return all_complete;
+       update_signals();
+}
+
+void Session::remove_generated_signal(shared_ptr<data::SignalBase> signal)
+{
+       if (shutting_down_)
+               return;
+
+       signalbases_.erase(std::remove_if(signalbases_.begin(), signalbases_.end(),
+               [&](shared_ptr<data::SignalBase> s) { return s == signal; }),
+               signalbases_.end());
+
+       for (shared_ptr<views::ViewBase>& view : views_)
+               view->remove_signalbase(signal);
+
+       update_signals();
 }
 
 #ifdef ENABLE_DECODE
@@ -894,6 +925,9 @@ shared_ptr<data::DecodeSignal> Session::add_decode_signal()
 
 void Session::remove_decode_signal(shared_ptr<data::DecodeSignal> signal)
 {
+       if (shutting_down_)
+               return;
+
        signalbases_.erase(std::remove_if(signalbases_.begin(), signalbases_.end(),
                [&](shared_ptr<data::SignalBase> s) { return s == signal; }),
                signalbases_.end());
@@ -905,6 +939,22 @@ void Session::remove_decode_signal(shared_ptr<data::DecodeSignal> signal)
 }
 #endif
 
+bool Session::all_segments_complete(uint32_t segment_id) const
+{
+       bool all_complete = true;
+
+       for (const shared_ptr<data::SignalBase>& base : signalbases_)
+               if (!base->segment_is_complete(segment_id))
+                       all_complete = false;
+
+       return all_complete;
+}
+
+MetadataObjManager* Session::metadata_obj_manager()
+{
+       return &metadata_obj_manager_;
+}
+
 void Session::set_capture_state(capture_state state)
 {
        bool changed;
@@ -930,7 +980,7 @@ void Session::update_signals()
                signalbases_.clear();
                logic_data_.reset();
                for (shared_ptr<views::ViewBase>& view : views_) {
-                       view->clear_signals();
+                       view->clear_signalbases();
 #ifdef ENABLE_DECODE
                        view->clear_decode_signals();
 #endif
@@ -945,7 +995,7 @@ void Session::update_signals()
                signalbases_.clear();
                logic_data_.reset();
                for (shared_ptr<views::ViewBase>& view : views_) {
-                       view->clear_signals();
+                       view->clear_signalbases();
 #ifdef ENABLE_DECODE
                        view->clear_decode_signals();
 #endif
@@ -960,7 +1010,7 @@ void Session::update_signals()
                [] (shared_ptr<Channel> channel) {
                        return channel->type() == sigrok::ChannelType::LOGIC; });
 
-       // Create data containers for the logic data segments
+       // Create a common data container for the logic signalbases
        {
                lock_guard<recursive_mutex> data_lock(data_mutex_);
 
@@ -968,97 +1018,96 @@ void Session::update_signals()
                        logic_data_.reset();
                } else if (!logic_data_ ||
                        logic_data_->num_channels() != logic_channel_count) {
-                       logic_data_.reset(new data::Logic(
-                               logic_channel_count));
+                       logic_data_.reset(new data::Logic(logic_channel_count));
                        assert(logic_data_);
                }
        }
 
-       // Make the signals list
-       for (shared_ptr<views::ViewBase>& viewbase : views_) {
-               views::trace::View *trace_view =
-                       qobject_cast<views::trace::View*>(viewbase.get());
-
-               if (trace_view) {
-                       vector< shared_ptr<Signal> > prev_sigs(trace_view->signals());
-                       trace_view->clear_signals();
-
-                       for (auto channel : sr_dev->channels()) {
-                               shared_ptr<data::SignalBase> signalbase;
-                               shared_ptr<Signal> signal;
-
-                               // Find the channel in the old signals
-                               const auto iter = find_if(
-                                       prev_sigs.cbegin(), prev_sigs.cend(),
-                                       [&](const shared_ptr<Signal> &s) {
-                                               return s->base()->channel() == channel;
-                                       });
-                               if (iter != prev_sigs.end()) {
-                                       // Copy the signal from the old set to the new
-                                       signal = *iter;
-                                       trace_view->add_signal(signal);
-                               } else {
-                                       // Find the signalbase for this channel if possible
-                                       signalbase.reset();
-                                       for (const shared_ptr<data::SignalBase>& b : signalbases_)
-                                               if (b->channel() == channel)
-                                                       signalbase = b;
-
-                                       shared_ptr<Signal> signal;
-
-                                       switch(channel->type()->id()) {
-                                       case SR_CHANNEL_LOGIC:
-                                               if (!signalbase) {
-                                                       signalbase = make_shared<data::SignalBase>(channel,
-                                                               data::SignalBase::LogicChannel);
-                                                       signalbases_.push_back(signalbase);
-
-                                                       all_signal_data_.insert(logic_data_);
-                                                       signalbase->set_data(logic_data_);
-
-                                                       connect(this, SIGNAL(capture_state_changed(int)),
-                                                               signalbase.get(), SLOT(on_capture_state_changed(int)));
-                                               }
-
-                                               signal = shared_ptr<Signal>(new LogicSignal(*this, device_, signalbase));
-                                               break;
+       // Create signalbases if necessary
+       for (auto channel : sr_dev->channels()) {
 
-                                       case SR_CHANNEL_ANALOG:
-                                       {
-                                               if (!signalbase) {
-                                                       signalbase = make_shared<data::SignalBase>(channel,
-                                                               data::SignalBase::AnalogChannel);
-                                                       signalbases_.push_back(signalbase);
+               // Try to find the channel in the list of existing signalbases
+               const auto iter = find_if(signalbases_.cbegin(), signalbases_.cend(),
+                       [&](const shared_ptr<SignalBase> &sb) { return sb->channel() == channel; });
 
-                                                       shared_ptr<data::Analog> data(new data::Analog());
-                                                       all_signal_data_.insert(data);
-                                                       signalbase->set_data(data);
+               // Not found, let's make a signalbase for it
+               if (iter == signalbases_.cend()) {
+                       shared_ptr<SignalBase> signalbase;
+                       switch(channel->type()->id()) {
+                       case SR_CHANNEL_LOGIC:
+                               signalbase = make_shared<data::SignalBase>(channel, data::SignalBase::LogicChannel);
+                               signalbases_.push_back(signalbase);
 
-                                                       connect(this, SIGNAL(capture_state_changed(int)),
-                                                               signalbase.get(), SLOT(on_capture_state_changed(int)));
-                                               }
+                               all_signal_data_.insert(logic_data_);
+                               signalbase->set_data(logic_data_);
 
-                                               signal = shared_ptr<Signal>(new AnalogSignal(*this, signalbase));
-                                               break;
-                                       }
+                               connect(this, SIGNAL(capture_state_changed(int)),
+                                       signalbase.get(), SLOT(on_capture_state_changed(int)));
+                               break;
 
-                                       default:
-                                               assert(false);
-                                               break;
-                                       }
+                       case SR_CHANNEL_ANALOG:
+                               signalbase = make_shared<data::SignalBase>(channel, data::SignalBase::AnalogChannel);
+                               signalbases_.push_back(signalbase);
 
-                                       // New views take their signal settings from the main view
-                                       if (!viewbase->is_main_view()) {
-                                               shared_ptr<pv::views::trace::View> main_tv =
-                                                       dynamic_pointer_cast<pv::views::trace::View>(main_view_);
-                                               shared_ptr<Signal> main_signal =
-                                                       main_tv->get_signal_by_signalbase(signalbase);
-                                               signal->restore_settings(main_signal->save_settings());
-                                       }
+                               shared_ptr<data::Analog> data(new data::Analog());
+                               all_signal_data_.insert(data);
+                               signalbase->set_data(data);
+
+                               connect(this, SIGNAL(capture_state_changed(int)),
+                                       signalbase.get(), SLOT(on_capture_state_changed(int)));
+                               break;
+                       }
+               }
+       }
 
-                                       trace_view->add_signal(signal);
+       // Create and assign default signal groups if needed
+       if (signal_groups_.empty()) {
+               for (auto& entry : sr_dev->channel_groups()) {
+                       const shared_ptr<sigrok::ChannelGroup>& group = entry.second;
+
+                       if (group->channels().size() <= 1)
+                               continue;
+
+                       SignalGroup* sg = new SignalGroup(QString::fromStdString(entry.first));
+                       for (const shared_ptr<sigrok::Channel>& channel : group->channels()) {
+                               for (shared_ptr<data::SignalBase> s : signalbases_) {
+                                       if (s->channel() == channel) {
+                                               sg->append_signal(s);
+                                               break;
+                                       }
                                }
                        }
+                       signal_groups_.emplace_back(sg);
+               }
+       }
+
+       // Update all views
+       for (shared_ptr<views::ViewBase>& viewbase : views_) {
+               vector< shared_ptr<SignalBase> > view_signalbases =
+                               viewbase->signalbases();
+
+               // Add all non-decode signalbases that don't yet exist in the view
+               for (shared_ptr<SignalBase>& session_sb : signalbases_) {
+                       if (session_sb->type() == SignalBase::DecodeChannel)
+                               continue;
+
+                       const auto iter = find_if(view_signalbases.cbegin(), view_signalbases.cend(),
+                               [&](const shared_ptr<SignalBase> &sb) { return sb == session_sb; });
+
+                       if (iter == view_signalbases.cend())
+                               viewbase->add_signalbase(session_sb);
+               }
+
+               // Remove all non-decode signalbases that no longer exist
+               for (shared_ptr<SignalBase>& view_sb : view_signalbases) {
+                       if (view_sb->type() == SignalBase::DecodeChannel)
+                               continue;
+
+                       const auto iter = find_if(signalbases_.cbegin(), signalbases_.cend(),
+                               [&](const shared_ptr<SignalBase> &sb) { return sb == view_sb; });
+
+                       if (iter == signalbases_.cend())
+                               viewbase->remove_signalbase(view_sb);
                }
        }
 
@@ -1124,6 +1173,8 @@ void Session::sample_thread_proc(function<void (const QString)> error_handler)
                lock_guard<recursive_mutex> lock(data_mutex_);
                cur_logic_segment_.reset();
                cur_analog_segments_.clear();
+               for (shared_ptr<data::SignalBase> sb : signalbases_)
+                       sb->clear_sample_data();
        }
        highest_segment_id_ = -1;
        frame_began_ = false;
@@ -1366,7 +1417,7 @@ void Session::feed_in_frame_end()
        signal_segment_completed();
 }
 
-void Session::feed_in_logic(shared_ptr<Logic> logic)
+void Session::feed_in_logic(shared_ptr<sigrok::Logic> logic)
 {
        if (logic->data_length() == 0) {
                qDebug() << "WARNING: Received logic packet with 0 samples.";
@@ -1410,7 +1461,7 @@ void Session::feed_in_logic(shared_ptr<Logic> logic)
        data_received();
 }
 
-void Session::feed_in_analog(shared_ptr<Analog> analog)
+void Session::feed_in_analog(shared_ptr<sigrok::Analog> analog)
 {
        if (analog->num_samples() == 0) {
                qDebug() << "WARNING: Received analog packet with 0 samples.";