logic_mux_thread_.join();
}
+ decode_pause_mutex_.unlock();
+ decode_paused_ = false;
+
class_rows_.clear();
current_segment_id_ = 0;
segments_.clear();
decode_thread_ = std::thread(&DecodeSignal::decode_proc, this);
}
+void DecodeSignal::pause_decode()
+{
+ decode_paused_ = true;
+}
+
+void DecodeSignal::resume_decode()
+{
+ // Manual unlocking is done before notifying, to avoid waking up the
+ // waiting thread only to block again (see notify_one for details)
+ decode_pause_mutex_.unlock();
+ decode_pause_cond_.notify_one();
+ decode_paused_ = false;
+}
+
+bool DecodeSignal::is_paused() const
+{
+ return decode_paused_;
+}
+
QString DecodeSignal::error_message() const
{
lock_guard<mutex> lock(output_mutex_);
// Notify the frontend that we processed some data and
// possibly have new annotations as well
new_annotations();
+
+ if (decode_paused_) {
+ unique_lock<mutex> pause_wait_lock(decode_pause_mutex_);
+ decode_pause_cond_.wait(pause_wait_lock);
+ }
}
}
void reset_decode(bool shutting_down = false);
void begin_decode();
+ void pause_decode();
+ void resume_decode();
+ bool is_paused() const;
QString error_message() const;
const vector<data::DecodeChannel> get_channels() const;
vector<DecodeSegment> segments_;
uint32_t current_segment_id_;
- mutable mutex input_mutex_, output_mutex_, logic_mux_mutex_;
- mutable condition_variable decode_input_cond_, logic_mux_cond_;
+ mutable mutex input_mutex_, output_mutex_, decode_pause_mutex_, logic_mux_mutex_;
+ mutable condition_variable decode_input_cond_, decode_pause_cond_,
+ logic_mux_cond_;
std::thread decode_thread_, logic_mux_thread_;
atomic<bool> decode_interrupt_, logic_mux_interrupt_;
+ bool decode_paused_;
+
QString error_message_;
};
QMenu *const menu = new QMenu(parent);
+ if (decode_signal_->is_paused()) {
+ QAction *const resume =
+ new QAction(tr("Resume decoding"), this);
+ resume->setIcon(QIcon::fromTheme("media-playback-start",
+ QIcon(":/icons/media-playback-start.png")));
+ connect(resume, SIGNAL(triggered()), this, SLOT(on_pause_decode()));
+ menu->addAction(resume);
+ } else {
+ QAction *const pause =
+ new QAction(tr("Pause decoding"), this);
+ pause->setIcon(QIcon::fromTheme("media-playback-pause",
+ QIcon(":/icons/media-playback-pause.png")));
+ connect(pause, SIGNAL(triggered()), this, SLOT(on_pause_decode()));
+ menu->addAction(pause);
+ }
+
+ menu->addSeparator();
+
QAction *const export_all_rows =
- new QAction(tr("Export all annotations"), this);
+ new QAction(tr("Export all annotations"), this);
export_all_rows->setIcon(QIcon::fromTheme("document-save-as",
QIcon(":/icons/document-save-as.png")));
connect(export_all_rows, SIGNAL(triggered()), this, SLOT(on_export_all_rows()));
menu->addAction(export_all_rows);
QAction *const export_row =
- new QAction(tr("Export all annotations for this row"), this);
+ new QAction(tr("Export all annotations for this row"), this);
export_row->setIcon(QIcon::fromTheme("document-save-as",
QIcon(":/icons/document-save-as.png")));
connect(export_row, SIGNAL(triggered()), this, SLOT(on_export_row()));
owner_->row_item_appearance_changed(false, true);
}
+void DecodeTrace::on_pause_decode()
+{
+ if (decode_signal_->is_paused())
+ decode_signal_->resume_decode();
+ else
+ decode_signal_->pause_decode();
+}
+
void DecodeTrace::delete_pressed()
{
on_delete();