if(ENABLE_DECODE)
list(APPEND pulseview_SOURCES
pv/binding/decoder.cpp
+ pv/data/decodesignal.cpp
pv/data/decoderstack.cpp
pv/data/decode/annotation.cpp
pv/data/decode/decoder.cpp
)
list(APPEND pulseview_HEADERS
+ pv/data/decodesignal.hpp
pv/data/decoderstack.hpp
pv/views/trace/decodetrace.hpp
pv/widgets/decodergroupbox.hpp
return rows;
}
+uint64_t DecoderStack::inc_annotation_count()
+{
+ return (annotation_count_++);
+}
+
void DecoderStack::get_annotation_subset(
vector<pv::data::decode::Annotation> &dest,
const Row &row, uint64_t start_sample,
void DecoderStack::clear()
{
sample_count_ = 0;
+ annotation_count_ = 0;
frame_complete_ = false;
samples_decoded_ = 0;
error_message_ = QString();
lock_guard<mutex> lock(output_mutex_);
samples_decoded_ = chunk_end;
}
-
- if (i % DecodeNotifyPeriod == 0)
- new_decode_data();
}
-
- new_decode_data();
}
void DecoderStack::decode_proc()
abs_start_samplenum = *sample_count;
} while (error_message_.isEmpty() && (sample_count = wait_for_data()));
+ // Make sure all annotations are known to the frontend
+ new_annotations();
+
// Destroy the session
srd_session_destroy(session);
}
-void DecoderStack::annotation_callback(srd_proto_data *pdata, void *decoder)
+void DecoderStack::annotation_callback(srd_proto_data *pdata, void *decoder_stack)
{
assert(pdata);
assert(decoder);
- DecoderStack *const d = (DecoderStack*)decoder;
- assert(d);
+ DecoderStack *const ds = (DecoderStack*)decoder_stack;
+ assert(ds);
- lock_guard<mutex> lock(d->output_mutex_);
+ lock_guard<mutex> lock(ds->output_mutex_);
const Annotation a(pdata);
const srd_decoder *const decc = pdata->pdo->di->decoder;
assert(decc);
- auto row_iter = d->rows_.end();
+ auto row_iter = ds->rows_.end();
// Try looking up the sub-row of this class
- const auto r = d->class_rows_.find(make_pair(decc, a.format()));
- if (r != d->class_rows_.end())
- row_iter = d->rows_.find((*r).second);
+ const auto r = ds->class_rows_.find(make_pair(decc, a.format()));
+ if (r != ds->class_rows_.end())
+ row_iter = ds->rows_.find((*r).second);
else {
// Failing that, use the decoder as a key
- row_iter = d->rows_.find(Row(decc));
+ row_iter = ds->rows_.find(Row(decc));
}
- assert(row_iter != d->rows_.end());
- if (row_iter == d->rows_.end()) {
+ assert(row_iter != ds->rows_.end());
+ if (row_iter == ds->rows_.end()) {
qDebug() << "Unexpected annotation: decoder = " << decc <<
", format = " << a.format();
assert(false);
// Add the annotation
(*row_iter).second.push_annotation(a);
+
+ // Notify the frontend every DecodeNotifyPeriod annotations
+ if (ds->inc_annotation_count() % DecodeNotifyPeriod == 0)
+ ds->new_annotations();
}
void DecoderStack::on_new_frame()
vector<decode::Row> get_visible_rows() const;
+ /**
+ * Helper function for static annotation_callback(),
+ * must be public so the function can access it.
+ * Don't use from outside this class.
+ */
+ uint64_t inc_annotation_count();
+
/**
* Extracts sorted annotations between two period into a vector.
*/
void decode_proc();
- static void annotation_callback(srd_proto_data *pdata, void *decoder);
+ static void annotation_callback(srd_proto_data *pdata, void *decoder_stack);
private Q_SLOTS:
void on_new_frame();
void on_frame_ended();
Q_SIGNALS:
- void new_decode_data();
+ void new_annotations();
private:
pv::Session &session_;
mutable mutex input_mutex_;
mutable condition_variable input_cond_;
- int64_t sample_count_;
+ int64_t sample_count_, annotation_count_;
bool frame_complete_;
mutable mutex output_mutex_;
--- /dev/null
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2017 Soeren Apel <soeren@apelpie.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "logic.hpp"
+#include "logicsegment.hpp"
+#include "decodesignal.hpp"
+#include "signaldata.hpp"
+
+#include <pv/binding/decoder.hpp>
+#include <pv/data/decode/decoder.hpp>
+#include <pv/data/decoderstack.hpp>
+#include <pv/session.hpp>
+
+using std::make_shared;
+using std::shared_ptr;
+using pv::data::decode::Decoder;
+
+namespace pv {
+namespace data {
+
+DecodeSignal::DecodeSignal(shared_ptr<pv::data::DecoderStack> decoder_stack) :
+ SignalBase(nullptr, SignalBase::DecodeChannel),
+ decoder_stack_(decoder_stack)
+{
+ set_name(QString::fromUtf8(decoder_stack_->stack().front()->decoder()->name));
+
+ connect(decoder_stack_.get(), SIGNAL(new_annotations()),
+ this, SLOT(on_new_annotations()));
+}
+
+DecodeSignal::~DecodeSignal()
+{
+}
+
+bool DecodeSignal::is_decode_signal() const
+{
+ return true;
+}
+
+shared_ptr<pv::data::DecoderStack> DecodeSignal::decoder_stack() const
+{
+ return decoder_stack_;
+}
+
+void DecodeSignal::stack_decoder(srd_decoder *decoder)
+{
+ assert(decoder);
+ assert(decoder_stack);
+ decoder_stack_->push(make_shared<data::decode::Decoder>(decoder));
+ decoder_stack_->begin_decode();
+}
+
+void DecodeSignal::remove_decoder(int index)
+{
+ decoder_stack_->remove(index);
+ decoder_stack_->begin_decode();
+}
+
+bool DecodeSignal::toggle_decoder_visibility(int index)
+{
+ const list< shared_ptr<Decoder> > stack(decoder_stack_->stack());
+
+ auto iter = stack.cbegin();
+ for (int i = 0; i < index; i++, iter++)
+ assert(iter != stack.end());
+
+ shared_ptr<Decoder> dec = *iter;
+
+ // Toggle decoder visibility
+ bool state = false;
+ if (dec) {
+ state = !dec->shown();
+ dec->show(state);
+ }
+
+ return state;
+}
+
+void DecodeSignal::on_new_annotations()
+{
+ // Forward the signal to the frontend
+ new_annotations();
+}
+
+} // namespace data
+} // namespace pv
--- /dev/null
+/*
+ * This file is part of the PulseView project.
+ *
+ * Copyright (C) 2017 Soeren Apel <soeren@apelpie.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PULSEVIEW_PV_DATA_DECODESIGNAL_HPP
+#define PULSEVIEW_PV_DATA_DECODESIGNAL_HPP
+
+#include <libsigrokdecode/libsigrokdecode.h>
+
+#include <pv/data/signalbase.hpp>
+
+using std::shared_ptr;
+
+namespace pv {
+namespace data {
+
+class DecoderStack;
+class Logic;
+class SignalData;
+
+class DecodeSignal : public SignalBase
+{
+ Q_OBJECT
+
+public:
+ DecodeSignal(shared_ptr<pv::data::DecoderStack> decoder_stack);
+ virtual ~DecodeSignal();
+
+ bool is_decode_signal() const;
+ shared_ptr<pv::data::DecoderStack> decoder_stack() const;
+
+ void stack_decoder(srd_decoder *decoder);
+ void remove_decoder(int index);
+ bool toggle_decoder_visibility(int index);
+
+Q_SIGNALS:
+ void new_annotations();
+
+private Q_SLOTS:
+ void on_new_annotations();
+
+private:
+ shared_ptr<pv::data::DecoderStack> decoder_stack_;
+};
+
+} // namespace data
+} // namespace pv
+
+#endif // PULSEVIEW_PV_DATA_DECODESIGNAL_HPP
#ifdef ENABLE_DECODE
bool SignalBase::is_decode_signal() const
{
- return (decoder_stack_ != nullptr);
+ // DecodeSignal class overrides this method, all others shall return false
+ return false;
}
shared_ptr<pv::data::DecoderStack> SignalBase::decoder_stack() const
{
- return decoder_stack_;
-}
-
-void SignalBase::set_decoder_stack(shared_ptr<pv::data::DecoderStack>
- decoder_stack)
-{
- decoder_stack_ = decoder_stack;
+ // DecodeSignal class overrides this method, all others shall return nothing
+ return nullptr;
}
#endif
void set_conversion_type(ConversionType t);
#ifdef ENABLE_DECODE
- bool is_decode_signal() const;
+ virtual bool is_decode_signal() const;
- shared_ptr<pv::data::DecoderStack> decoder_stack() const;
-
- void set_decoder_stack(shared_ptr<pv::data::DecoderStack> decoder_stack);
+ virtual shared_ptr<pv::data::DecoderStack> decoder_stack() const;
#endif
void save_settings(QSettings &settings) const;
void on_capture_state_changed(int state);
-private:
+protected:
shared_ptr<sigrok::Channel> channel_;
ChannelType channel_type_;
shared_ptr<pv::data::SignalData> data_;
shared_ptr<pv::data::SignalData> converted_data_;
int conversion_type_;
-#ifdef ENABLE_DECODE
- shared_ptr<pv::data::DecoderStack> decoder_stack_;
-#endif
-
std::thread conversion_thread_;
QString internal_name_, name_;
#ifdef ENABLE_DECODE
#include <libsigrokdecode/libsigrokdecode.h>
+#include "data/decodesignal.hpp"
#endif
using std::bad_alloc;
decoder_stack->stack().front()->set_channels(channels);
// Create the decode signal
- shared_ptr<data::SignalBase> signalbase =
- make_shared<data::SignalBase>(nullptr, data::SignalBase::DecodeChannel);
+ shared_ptr<data::DecodeSignal> signal =
+ make_shared<data::DecodeSignal>(decoder_stack);
- signalbase->set_decoder_stack(decoder_stack);
- signalbases_.insert(signalbase);
+ signalbases_.insert(signal);
for (shared_ptr<views::ViewBase> view : views_)
- view->add_decode_signal(signalbase);
+ view->add_decode_signal(signal);
} catch (runtime_error e) {
return false;
}
return true;
}
-void Session::remove_decode_signal(shared_ptr<data::SignalBase> signalbase)
+void Session::remove_decode_signal(shared_ptr<data::DecodeSignal> signal)
{
- signalbases_.erase(signalbase);
+ signalbases_.erase(signal);
for (shared_ptr<views::ViewBase> view : views_)
- view->remove_decode_signal(signalbase);
+ view->remove_decode_signal(signal);
signals_changed();
}
namespace data {
class Analog;
class AnalogSegment;
+class DecodeSignal;
class Logic;
class LogicSegment;
class SignalBase;
#ifdef ENABLE_DECODE
bool add_decoder(srd_decoder *const dec);
- void remove_decode_signal(shared_ptr<data::SignalBase> signalbase);
+ void remove_decode_signal(shared_ptr<data::DecodeSignal> signal);
#endif
private:
#include "viewport.hpp"
#include <pv/globalsettings.hpp>
+#include <pv/session.hpp>
+#include <pv/strnatcmp.hpp>
+#include <pv/data/decodesignal.hpp>
#include <pv/data/decode/annotation.hpp>
#include <pv/data/decode/decoder.hpp>
#include <pv/data/decoderstack.hpp>
#include <pv/data/logic.hpp>
#include <pv/data/logicsegment.hpp>
-#include <pv/session.hpp>
-#include <pv/strnatcmp.hpp>
#include <pv/widgets/decodergroupbox.hpp>
#include <pv/widgets/decodermenu.hpp>
delete_mapper_(this),
show_hide_mapper_(this)
{
- shared_ptr<pv::data::DecoderStack> decoder_stack = base_->decoder_stack();
+ decode_signal_ = dynamic_pointer_cast<data::DecodeSignal>(base_);
// Determine shortest string we want to see displayed in full
QFontMetrics m(QApplication::font());
min_useful_label_width_ = m.width("XX"); // e.g. two hex characters
- base_->set_name(QString::fromUtf8(decoder_stack->stack().front()->decoder()->name));
base_->set_colour(DecodeColours[index % countof(DecodeColours)]);
- connect(decoder_stack.get(), SIGNAL(new_decode_data()),
- this, SLOT(on_new_decode_data()));
+ connect(decode_signal_.get(), SIGNAL(new_annotations()),
+ this, SLOT(on_new_annotations()));
connect(&delete_mapper_, SIGNAL(mapped(int)),
this, SLOT(on_delete_decoder(int)));
connect(&show_hide_mapper_, SIGNAL(mapped(int)),
decoder_stack->begin_decode();
}
-void DecodeTrace::on_new_decode_data()
+void DecodeTrace::on_new_annotations()
{
if (owner_)
owner_->row_item_appearance_changed(false, true);
void DecodeTrace::on_delete()
{
- session_.remove_decode_signal(base_);
+ session_.remove_decode_signal(decode_signal_);
}
void DecodeTrace::on_channel_selected(int)
void DecodeTrace::on_stack_decoder(srd_decoder *decoder)
{
- shared_ptr<pv::data::DecoderStack> decoder_stack = base_->decoder_stack();
-
- assert(decoder);
- assert(decoder_stack);
- decoder_stack->push(make_shared<data::decode::Decoder>(decoder));
- decoder_stack->begin_decode();
+ decode_signal_->stack_decoder(decoder);
create_popup_form();
}
void DecodeTrace::on_delete_decoder(int index)
{
- shared_ptr<pv::data::DecoderStack> decoder_stack = base_->decoder_stack();
-
- decoder_stack->remove(index);
+ decode_signal_->remove_decoder(index);
// Update the popup
create_popup_form();
-
- decoder_stack->begin_decode();
}
void DecodeTrace::on_show_hide_decoder(int index)
{
- using pv::data::decode::Decoder;
-
- shared_ptr<pv::data::DecoderStack> decoder_stack = base_->decoder_stack();
-
- const list< shared_ptr<Decoder> > stack(decoder_stack->stack());
-
- // Find the decoder in the stack
- auto iter = stack.cbegin();
- for (int i = 0; i < index; i++, iter++)
- assert(iter != stack.end());
-
- shared_ptr<Decoder> dec = *iter;
- assert(dec);
-
- const bool show = !dec->shown();
- dec->show(show);
+ const bool state = decode_signal_->toggle_decoder_visibility(index);
assert(index < (int)decoder_forms_.size());
- decoder_forms_[index]->set_decoder_visible(show);
+ decoder_forms_[index]->set_decoder_visible(state);
if (owner_)
owner_->row_item_appearance_changed(false, true);
namespace data {
class DecoderStack;
class SignalBase;
+class DecodeSignal;
namespace decode {
class Annotation;
void hover_point_changed();
private Q_SLOTS:
- void on_new_decode_data();
+ void on_new_annotations();
void on_delete();
private:
pv::Session &session_;
+ shared_ptr<data::DecodeSignal> decode_signal_;
vector<data::decode::Row> visible_rows_;
uint64_t decode_start_, decode_end_;
decode_traces_.clear();
}
-void View::add_decode_signal(shared_ptr<data::SignalBase> signalbase)
+void View::add_decode_signal(shared_ptr<data::DecodeSignal> signal)
{
shared_ptr<DecodeTrace> d(
- new DecodeTrace(session_, signalbase, decode_traces_.size()));
+ new DecodeTrace(session_, signal, decode_traces_.size()));
decode_traces_.push_back(d);
}
-void View::remove_decode_signal(shared_ptr<data::SignalBase> signalbase)
+void View::remove_decode_signal(shared_ptr<data::DecodeSignal> signal)
{
for (auto i = decode_traces_.begin(); i != decode_traces_.end(); i++)
- if ((*i)->base() == signalbase) {
+ if ((*i)->base() == signal) {
decode_traces_.erase(i);
signals_changed();
return;
#ifdef ENABLE_DECODE
virtual void clear_decode_signals();
- virtual void add_decode_signal(shared_ptr<data::SignalBase> signalbase);
+ virtual void add_decode_signal(shared_ptr<data::DecodeSignal> signal);
- virtual void remove_decode_signal(shared_ptr<data::SignalBase> signalbase);
+ virtual void remove_decode_signal(shared_ptr<data::DecodeSignal> signal);
#endif
/**
{
}
-void ViewBase::add_decode_signal(shared_ptr<data::SignalBase> signalbase)
+void ViewBase::add_decode_signal(shared_ptr<data::DecodeSignal> signal)
{
- (void)signalbase;
+ (void)signal;
}
-void ViewBase::remove_decode_signal(shared_ptr<data::SignalBase> signalbase)
+void ViewBase::remove_decode_signal(shared_ptr<data::DecodeSignal> signal)
{
- (void)signalbase;
+ (void)signal;
}
#endif
#include <pv/data/signalbase.hpp>
#include <pv/util.hpp>
+#ifdef ENABLE_DECODE
+#include <pv/data/decodesignal.hpp>
+#endif
+
using std::shared_ptr;
using std::unordered_set;
#ifdef ENABLE_DECODE
virtual void clear_decode_signals();
- virtual void add_decode_signal(shared_ptr<data::SignalBase> signalbase);
+ virtual void add_decode_signal(shared_ptr<data::DecodeSignal> signal);
- virtual void remove_decode_signal(shared_ptr<data::SignalBase> signalbase);
+ virtual void remove_decode_signal(shared_ptr<data::DecodeSignal> signal);
#endif
virtual void save_settings(QSettings &settings) const;
if(ENABLE_DECODE)
list(APPEND pulseview_TEST_SOURCES
${PROJECT_SOURCE_DIR}/pv/binding/decoder.cpp
+ ${PROJECT_SOURCE_DIR}/pv/data/decodesignal.cpp
${PROJECT_SOURCE_DIR}/pv/data/decoderstack.cpp
${PROJECT_SOURCE_DIR}/pv/data/decode/annotation.cpp
${PROJECT_SOURCE_DIR}/pv/data/decode/decoder.cpp
)
list(APPEND pulseview_TEST_HEADERS
+ ${PROJECT_SOURCE_DIR}/pv/data/decodesignal.hpp
${PROJECT_SOURCE_DIR}/pv/data/decoderstack.hpp
${PROJECT_SOURCE_DIR}/pv/views/trace/decodetrace.hpp
${PROJECT_SOURCE_DIR}/pv/widgets/decodergroupbox.hpp