From: Soeren Apel Date: Wed, 22 Aug 2018 07:33:48 +0000 (+0200) Subject: Implement decode pausing/resuming X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=556259d2d0a212c20db9b18311b9524b52401a56;p=pulseview.git Implement decode pausing/resuming --- diff --git a/icons/media-playback-pause.png b/icons/media-playback-pause.png new file mode 100644 index 00000000..ee40fc26 Binary files /dev/null and b/icons/media-playback-pause.png differ diff --git a/icons/media-playback-start.png b/icons/media-playback-start.png new file mode 100644 index 00000000..10102d82 Binary files /dev/null and b/icons/media-playback-start.png differ diff --git a/pv/data/decodesignal.cpp b/pv/data/decodesignal.cpp index 05dc3428..4705b104 100644 --- a/pv/data/decodesignal.cpp +++ b/pv/data/decodesignal.cpp @@ -151,6 +151,9 @@ void DecodeSignal::reset_decode(bool shutting_down) logic_mux_thread_.join(); } + decode_pause_mutex_.unlock(); + decode_paused_ = false; + class_rows_.clear(); current_segment_id_ = 0; segments_.clear(); @@ -258,6 +261,25 @@ void DecodeSignal::begin_decode() 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 lock(output_mutex_); @@ -981,6 +1003,11 @@ void DecodeSignal::decode_data( // Notify the frontend that we processed some data and // possibly have new annotations as well new_annotations(); + + if (decode_paused_) { + unique_lock pause_wait_lock(decode_pause_mutex_); + decode_pause_cond_.wait(pause_wait_lock); + } } } diff --git a/pv/data/decodesignal.hpp b/pv/data/decodesignal.hpp index f00a9f1c..ba9c9b5e 100644 --- a/pv/data/decodesignal.hpp +++ b/pv/data/decodesignal.hpp @@ -101,6 +101,9 @@ public: 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 get_channels() const; @@ -215,12 +218,15 @@ private: vector 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 decode_interrupt_, logic_mux_interrupt_; + bool decode_paused_; + QString error_message_; }; diff --git a/pv/views/trace/decodetrace.cpp b/pv/views/trace/decodetrace.cpp index 651b8c3d..574e9d1a 100644 --- a/pv/views/trace/decodetrace.cpp +++ b/pv/views/trace/decodetrace.cpp @@ -341,15 +341,33 @@ QMenu* DecodeTrace::create_view_context_menu(QWidget *parent, QPoint &click_pos) 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())); @@ -1037,6 +1055,14 @@ void DecodeTrace::on_decode_finished() 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(); diff --git a/pv/views/trace/decodetrace.hpp b/pv/views/trace/decodetrace.hpp index 9372f7af..57e46220 100644 --- a/pv/views/trace/decodetrace.hpp +++ b/pv/views/trace/decodetrace.hpp @@ -187,6 +187,7 @@ private Q_SLOTS: void on_delayed_trace_update(); void on_decode_reset(); void on_decode_finished(); + void on_pause_decode(); void on_delete();