From 12fc672ab7cb2cd7d2bbad10d1a038395a75941e Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Mon, 8 May 2017 23:58:02 +0200 Subject: [PATCH] Add a preview display to the frame analyzer window. --- analyzer.cpp | 9 ++++++++- analyzer.h | 1 + glwidget.cpp | 7 ++++++- glwidget.h | 1 + mixer.cpp | 19 ++++++++++++++----- mixer.h | 16 ++++++++++++---- ui_analyzer.ui | 23 +++++++++++++++++++++++ 7 files changed, 65 insertions(+), 11 deletions(-) diff --git a/analyzer.cpp b/analyzer.cpp index 353229e..2ed00f1 100644 --- a/analyzer.cpp +++ b/analyzer.cpp @@ -30,7 +30,9 @@ Analyzer::Analyzer() } connect(ui->grab_btn, &QPushButton::clicked, bind(&Analyzer::grab_clicked, this)); - //ui->display->set_output(Mixer::OUTPUT_LIVE); + connect(ui->input_box, static_cast(&QComboBox::currentIndexChanged), bind(&Analyzer::signal_changed, this)); + signal_changed(); + surface = create_surface(QSurfaceFormat::defaultFormat()); context = create_context(surface); @@ -143,3 +145,8 @@ void Analyzer::grab_clicked() check_error(); } +void Analyzer::signal_changed() +{ + Mixer::Output channel = static_cast(ui->input_box->currentData().value()); + ui->display->set_output(channel); +} diff --git a/analyzer.h b/analyzer.h index d239c0e..3cefdc9 100644 --- a/analyzer.h +++ b/analyzer.h @@ -28,6 +28,7 @@ public: private: void grab_clicked(); + void signal_changed(); Ui::Analyzer *ui; QSurface *surface; diff --git a/glwidget.cpp b/glwidget.cpp index 27f290d..43517fa 100644 --- a/glwidget.cpp +++ b/glwidget.cpp @@ -40,6 +40,11 @@ GLWidget::GLWidget(QWidget *parent) { } +GLWidget::~GLWidget() +{ + global_mixer->remove_frame_ready_callback(output, this); +} + void GLWidget::clean_context() { if (resource_pool != nullptr) { @@ -57,7 +62,7 @@ void GLWidget::initializeGL() global_mainwindow->mixer_created(global_mixer); global_mixer->start(); }); - global_mixer->set_frame_ready_callback(output, [this]{ + global_mixer->add_frame_ready_callback(output, this, [this]{ QMetaObject::invokeMethod(this, "update", Qt::AutoConnection); }); if (output == Mixer::OUTPUT_LIVE) { diff --git a/glwidget.h b/glwidget.h index 9095e48..12757fc 100644 --- a/glwidget.h +++ b/glwidget.h @@ -30,6 +30,7 @@ class GLWidget : public QGLWidget public: GLWidget(QWidget *parent = 0); + ~GLWidget(); void set_output(Mixer::Output output) { diff --git a/mixer.cpp b/mixer.cpp index c21ac95..3132821 100644 --- a/mixer.cpp +++ b/mixer.cpp @@ -1327,10 +1327,12 @@ void Mixer::OutputChannel::output_frame(DisplayFrame frame) } ready_frame = frame; has_ready_frame = true; - } - if (new_frame_ready_callback) { - new_frame_ready_callback(); + // Call the callbacks under the mutex (they should be short), + // so that we don't race against a callback removal. + for (const auto &key_and_callback : new_frame_ready_callbacks) { + key_and_callback.second(); + } } // Reduce the number of callbacks by filtering duplicates. The reason @@ -1397,9 +1399,16 @@ bool Mixer::OutputChannel::get_display_frame(DisplayFrame *frame) return true; } -void Mixer::OutputChannel::set_frame_ready_callback(Mixer::new_frame_ready_callback_t callback) +void Mixer::OutputChannel::add_frame_ready_callback(void *key, Mixer::new_frame_ready_callback_t callback) { - new_frame_ready_callback = callback; + unique_lock lock(frame_mutex); + new_frame_ready_callbacks[key] = callback; +} + +void Mixer::OutputChannel::remove_frame_ready_callback(void *key) +{ + unique_lock lock(frame_mutex); + new_frame_ready_callbacks.erase(key); } void Mixer::OutputChannel::set_transition_names_updated_callback(Mixer::transition_names_updated_callback_t callback) diff --git a/mixer.h b/mixer.h index 5fb195e..6828bc6 100644 --- a/mixer.h +++ b/mixer.h @@ -139,10 +139,17 @@ public: return output_channel[output].get_display_frame(frame); } + // NOTE: Callbacks will be called with a mutex held, so you should probably + // not do real work in them. typedef std::function new_frame_ready_callback_t; - void set_frame_ready_callback(Output output, new_frame_ready_callback_t callback) + void add_frame_ready_callback(Output output, void *key, new_frame_ready_callback_t callback) { - output_channel[output].set_frame_ready_callback(callback); + output_channel[output].add_frame_ready_callback(key, callback); + } + + void remove_frame_ready_callback(Output output, void *key) + { + output_channel[output].remove_frame_ready_callback(key); } // TODO: Should this really be per-channel? Shouldn't it just be called for e.g. the live output? @@ -457,7 +464,8 @@ private: ~OutputChannel(); void output_frame(DisplayFrame frame); bool get_display_frame(DisplayFrame *frame); - void set_frame_ready_callback(new_frame_ready_callback_t callback); + void add_frame_ready_callback(void *key, new_frame_ready_callback_t callback); + void remove_frame_ready_callback(void *key); void set_transition_names_updated_callback(transition_names_updated_callback_t callback); void set_name_updated_callback(name_updated_callback_t callback); void set_color_updated_callback(color_updated_callback_t callback); @@ -470,7 +478,7 @@ private: std::mutex frame_mutex; DisplayFrame current_frame, ready_frame; // protected by bool has_current_frame = false, has_ready_frame = false; // protected by - new_frame_ready_callback_t new_frame_ready_callback; + std::map new_frame_ready_callbacks; // protected by transition_names_updated_callback_t transition_names_updated_callback; name_updated_callback_t name_updated_callback; color_updated_callback_t color_updated_callback; diff --git a/ui_analyzer.ui b/ui_analyzer.ui index 254014f..b43345a 100644 --- a/ui_analyzer.ui +++ b/ui_analyzer.ui @@ -13,6 +13,22 @@ Dialog + + + + 10 + 10 + 320 + 180 + + + + false + + + background: rgb(233, 185, 110) + + @@ -182,6 +198,13 @@ + + + GLWidget + QWidget +
glwidget.h
+
+
-- 2.39.2