samplerate_(samplerate),
unit_size_(unit_size),
iterator_count_(0),
- mem_optimization_requested_(false)
+ mem_optimization_requested_(false),
+ is_complete_(false)
{
lock_guard<recursive_mutex> lock(mutex_);
assert(unit_size_ > 0);
return unit_size_;
}
+void Segment::set_complete()
+{
+ is_complete_ = true;
+}
+
+bool Segment::is_complete() const
+{
+ return is_complete_;
+}
+
void Segment::free_unused_memory()
{
lock_guard<recursive_mutex> lock(mutex_);
unsigned int unit_size() const;
+ void set_complete();
+ bool is_complete() const;
+
void free_unused_memory();
protected:
unsigned int unit_size_;
int iterator_count_;
bool mem_optimization_requested_;
+ bool is_complete_;
friend struct SegmentTest::SmallSize8Single;
friend struct SegmentTest::MediumSize8Single;
return result;
}
+bool SignalBase::segment_is_complete(uint32_t segment_id) const
+{
+ bool result = true;
+
+ if (channel_type_ == AnalogChannel)
+ {
+ shared_ptr<Analog> data = dynamic_pointer_cast<Analog>(data_);
+ auto segments = data->analog_segments();
+ try {
+ result = segments.at(segment_id)->is_complete();
+ } catch (out_of_range) {
+ // Do nothing
+ }
+ }
+
+ if (channel_type_ == LogicChannel)
+ {
+ shared_ptr<Logic> data = dynamic_pointer_cast<Logic>(data_);
+ auto segments = data->logic_segments();
+ try {
+ result = segments.at(segment_id)->is_complete();
+ } catch (out_of_range) {
+ // Do nothing
+ }
+ }
+
+ return result;
+}
+
SignalBase::ConversionType SignalBase::get_conversion_type() const
{
return conversion_type_;
*/
shared_ptr<pv::data::Logic> logic_data() const;
+ /**
+ * Determines whether a given segment is complete (i.e. end-of-frame has
+ * been seen). It only considers the original data, not the converted data.
+ */
+ bool segment_is_complete(uint32_t segment_id) const;
+
/**
* Queries the kind of conversion performed on this channel.
*/
}
}
+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()
{
// Nothing to do here for now
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_)
frame_began_ = false;
+
+ signal_segment_completed();
}
void Session::feed_in_logic(shared_ptr<Logic> logic)
void free_unused_memory();
void signal_new_segment();
+ void signal_segment_completed();
void feed_in_header();
void trigger_event(util::Timestamp location);
void new_segment(int new_segment_id);
+ void segment_completed(int segment_id);
void data_received();
if (segment_display_mode_ == ShowLastSegmentOnly)
segment = segments.back();
- if (segment_display_mode_ == ShowSingleSegmentOnly) {
+ if ((segment_display_mode_ == ShowSingleSegmentOnly) ||
+ (segment_display_mode_ == ShowLastCompleteSegmentOnly)) {
try {
segment = segments.at(current_segment_);
} catch (out_of_range) {
if (segment_display_mode_ == ShowLastSegmentOnly)
segment = segments.back();
- if (segment_display_mode_ == ShowSingleSegmentOnly) {
+ if ((segment_display_mode_ == ShowSingleSegmentOnly) ||
+ (segment_display_mode_ == ShowLastCompleteSegmentOnly)) {
try {
segment = segments.at(current_segment_);
} catch (out_of_range) {
segment = segments.back();
}
- if (segment_display_mode_ == ShowSingleSegmentOnly) {
+ if ((segment_display_mode_ == ShowSingleSegmentOnly) ||
+ (segment_display_mode_ == ShowLastCompleteSegmentOnly)) {
try {
segment = segments.at(current_segment_);
} catch (out_of_range) {
connect(&session_, SIGNAL(new_segment(int)),
this, SLOT(on_new_segment(int)));
+ connect(&session_, SIGNAL(segment_completed(int)),
+ view_, SLOT(on_segment_completed(int)));
+
connect(segment_selector_, SIGNAL(valueChanged(int)),
this, SLOT(on_segment_selected(int)));
connect(view_, SIGNAL(segment_changed(int)),
void StandardBar::on_new_segment(int new_segment_id)
{
- if (new_segment_id > 1) {
+ if (new_segment_id > 0) {
show_multi_segment_ui(true);
segment_selector_->setMaximum(new_segment_id + 1);
} else
/**
* Allowed values for the multi-segment display mode.
*
- * Note: Consider @ref View::set_segment_display_mode when updating the list.
+ * Note: Consider these locations when updating the list:
+ * *
+ * @ref View::set_segment_display_mode
+ * @ref AnalogSignal::get_analog_segment_to_paint
+ * @ref AnalogSignal::get_logic_segment_to_paint
+ * @ref LogicSignal::get_logic_segment_to_paint
*/
enum SegmentDisplayMode {
ShowLastSegmentOnly = 1,
+ ShowLastCompleteSegmentOnly,
ShowSingleSegmentOnly,
ShowAllSegments,
ShowAccumulatedIntensity
}
}
+void View::set_current_segment(uint32_t segment_id)
+{
+ current_segment_ = segment_id;
+
+ for (shared_ptr<Signal> signal : signals_)
+ signal->set_current_segment(current_segment_);
+ for (shared_ptr<DecodeTrace> dt : decode_traces_)
+ dt->set_current_segment(current_segment_);
+
+ viewport_->update();
+}
+
bool View::segment_is_selectable() const
{
return segment_selectable_;
// Enable sticky scrolling if the setting is enabled
sticky_scrolling_ = settings.value(GlobalSettings::Key_View_StickyScrolling).toBool();
+
+ // Reset all traces to segment 0
+ current_segment_ = 0;
+ set_current_segment(current_segment_);
}
if (state == Session::Stopped) {
segment_changed(new_segment_id);
}
+void View::on_segment_completed(int segment_id)
+{
+ on_segment_changed(segment_id);
+ segment_changed(segment_id);
+}
+
void View::on_segment_changed(int segment)
{
switch (segment_display_mode_) {
case Trace::ShowLastSegmentOnly:
case Trace::ShowSingleSegmentOnly:
- current_segment_ = segment;
- for (shared_ptr<Signal> signal : signals_)
- signal->set_current_segment(current_segment_);
- for (shared_ptr<DecodeTrace> dt : decode_traces_)
- dt->set_current_segment(current_segment_);
- viewport_->update();
+ set_current_segment(segment);
+ break;
+
+ case Trace::ShowLastCompleteSegmentOnly:
+ {
+ // Only update if all segments are complete
+ bool all_complete = true;
+
+ for (shared_ptr<Signal> signal : signals_)
+ if (!signal->base()->segment_is_complete(segment))
+ all_complete = false;
+
+ if (all_complete)
+ set_current_segment(segment);
+ }
break;
case Trace::ShowAllSegments:
void capture_state_updated(int state);
void on_new_segment(int new_segment_id);
+ void on_segment_completed(int new_segment_id);
void on_segment_changed(int segment);
virtual void perform_delayed_view_update();
*/
void set_time_unit(pv::util::TimeUnit time_unit);
+ /**
+ * Sets the current segment with the first segment starting at 0.
+ */
+ void set_current_segment(uint32_t segment_id);
+
private:
CustomScrollArea *scrollarea_;
Viewport *viewport_;
(void)new_segment_id;
}
+void ViewBase::on_segment_completed(int new_segment_id)
+{
+ (void)new_segment_id;
+}
+
void ViewBase::capture_state_updated(int state)
{
(void)state;
virtual void signals_changed();
virtual void capture_state_updated(int state);
virtual void on_new_segment(int new_segment_id);
+ virtual void on_segment_completed(int new_segment_id);
virtual void perform_delayed_view_update();
private Q_SLOTS: