]> git.sesse.net Git - nageru/blobdiff - glwidget.cpp
Release Nageru 1.7.2.
[nageru] / glwidget.cpp
index 7caee374becc777d2af42575d58427bac5848d6b..bf537de2dbdb0806d2c41fec0b8ebf3fcd74d8e7 100644 (file)
@@ -8,6 +8,7 @@
 #include <stdint.h>
 #include <QAction>
 #include <QActionGroup>
+#include <QInputDialog>
 #include <QList>
 #include <QMenu>
 #include <QPoint>
@@ -32,11 +33,23 @@ class QMouseEvent;
 #include <movit/util.h>
 #include <string>
 
-
 using namespace movit;
 using namespace std;
 using namespace std::placeholders;
 
+namespace {
+
+double srgb_to_linear(double x)
+{
+       if (x < 0.04045) {
+               return x / 12.92;
+       } else {
+               return pow((x + 0.055) / 1.055, 2.4);
+       }
+}
+
+}  // namespace
+
 GLWidget::GLWidget(QWidget *parent)
     : QGLWidget(parent, global_share_widget)
 {
@@ -55,6 +68,22 @@ void GLWidget::shutdown()
        global_mixer->remove_frame_ready_callback(output, this);
 }
 
+void GLWidget::grab_white_balance(unsigned channel, unsigned x, unsigned y)
+{
+       // Set the white balance to neutral for the grab. It's probably going to
+       // flicker a bit, but hopefully this display is not live anyway.
+       global_mixer->set_wb(output, 0.5, 0.5, 0.5);
+       global_mixer->wait_for_next_frame();
+
+       // Mark that the next paintGL() should grab the given pixel.
+       grab_x = x;
+       grab_y = y;
+       grab_output = Mixer::Output(Mixer::OUTPUT_INPUT0 + channel);
+       should_grab = true;
+
+       updateGL();
+}
+
 void GLWidget::initializeGL()
 {
        static once_flag flag;
@@ -121,6 +150,17 @@ void GLWidget::paintGL()
        } else {
                assert(resource_pool == frame.chain->get_resource_pool());
        }
+
+       if (should_grab) {
+               GLfloat reference_color[4];
+               glReadPixels(grab_x, current_height - grab_y - 1, 1, 1, GL_BGRA, GL_FLOAT, reference_color);
+
+               double r = srgb_to_linear(reference_color[2]);
+               double g = srgb_to_linear(reference_color[1]);
+               double b = srgb_to_linear(reference_color[0]);
+               global_mixer->set_wb(grab_output, r, g, b);
+               should_grab = false;
+       }
 }
 
 void GLWidget::mousePressEvent(QMouseEvent *event)
@@ -175,6 +215,18 @@ void GLWidget::show_preview_context_menu(unsigned signal_num, const QPoint &pos)
        QMenu card_submenu;
        QActionGroup card_group(&card_submenu);
 
+       QMenu interpretation_submenu;
+       QActionGroup interpretation_group(&interpretation_submenu);
+
+       QMenu video_input_submenu;
+       QActionGroup video_input_group(&video_input_submenu);
+
+       QMenu audio_input_submenu;
+       QActionGroup audio_input_group(&audio_input_submenu);
+
+       QMenu mode_submenu;
+       QActionGroup mode_group(&mode_submenu);
+
        unsigned num_cards = global_mixer->get_num_cards();
        unsigned current_card = global_mixer->map_signal(signal_num);
        bool is_ffmpeg = global_mixer->card_is_ffmpeg(current_card);
@@ -196,9 +248,6 @@ void GLWidget::show_preview_context_menu(unsigned signal_num, const QPoint &pos)
 
                // Note that this setting depends on which card is active.
 
-               QMenu interpretation_submenu;
-               QActionGroup interpretation_group(&interpretation_submenu);
-
                YCbCrInterpretation current_interpretation = global_mixer->get_input_ycbcr_interpretation(current_card);
                {
                        QAction *action = new QAction("Auto", &interpretation_group);
@@ -239,10 +288,16 @@ void GLWidget::show_preview_context_menu(unsigned signal_num, const QPoint &pos)
        // --- The choices in the next few options depend a lot on which card is active ---
 
        bool has_auto_mode = false;
-       if (!is_ffmpeg) {
+       QAction *change_url_action = nullptr;
+       if (is_ffmpeg) {
+               // Add a menu to change the source URL if we're an FFmpeg card.
+               // (The theme can still override.)
+               if (global_mixer->card_is_ffmpeg(current_card)) {
+                       change_url_action = new QAction("Change source filename/URL…", &menu);
+                       menu.addAction(change_url_action);
+               }
+       } else {
                // Add a submenu for selecting video input, with an action for each input.
-               QMenu video_input_submenu;
-               QActionGroup video_input_group(&video_input_submenu);
                std::map<uint32_t, string> video_inputs = global_mixer->get_available_video_inputs(current_card);
                uint32_t current_video_input = global_mixer->get_current_video_input(current_card);
                for (const auto &mode : video_inputs) {
@@ -260,8 +315,6 @@ void GLWidget::show_preview_context_menu(unsigned signal_num, const QPoint &pos)
                menu.addMenu(&video_input_submenu);
 
                // The same for audio input.
-               QMenu audio_input_submenu;
-               QActionGroup audio_input_group(&audio_input_submenu);
                std::map<uint32_t, string> audio_inputs = global_mixer->get_available_audio_inputs(current_card);
                uint32_t current_audio_input = global_mixer->get_current_audio_input(current_card);
                for (const auto &mode : audio_inputs) {
@@ -279,8 +332,6 @@ void GLWidget::show_preview_context_menu(unsigned signal_num, const QPoint &pos)
                menu.addMenu(&audio_input_submenu);
 
                // The same for resolution.
-               QMenu mode_submenu;
-               QActionGroup mode_group(&mode_submenu);
                std::map<uint32_t, bmusb::VideoMode> video_modes = global_mixer->get_available_video_modes(current_card);
                uint32_t current_video_mode = global_mixer->get_current_video_mode(current_card);
                for (const auto &mode : video_modes) {
@@ -341,6 +392,17 @@ void GLWidget::show_preview_context_menu(unsigned signal_num, const QPoint &pos)
        QAction *selected_item = menu.exec(global_pos);
        if (audio_source_action != nullptr && selected_item == audio_source_action) {
                global_audio_mixer->set_simple_input(current_card);
+       } else if (change_url_action != nullptr && selected_item == change_url_action) {
+               // NOTE: We can't use “this” as parent, since the dialog would inherit our style sheet.
+               bool ok;
+               const string url = global_mixer->get_ffmpeg_filename(current_card);
+               QString new_url = QInputDialog::getText(window(), tr("Change URL"),
+                       tr("Enter new filename/URL for the given video input:"), QLineEdit::Normal,
+                               QString::fromStdString(url), &ok);
+               // FIXME prefill the input
+               if (ok) {
+                       global_mixer->set_ffmpeg_filename(current_card, new_url.toStdString());
+               }
        } else if (selected_item == master_clock_action) {
                global_mixer->set_master_clock(signal_num);
        } else if (selected_item != nullptr) {