X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=glwidget.cpp;h=bf537de2dbdb0806d2c41fec0b8ebf3fcd74d8e7;hb=778fe6ec989e7ed640a6c3d209099b6be3945bba;hp=7caee374becc777d2af42575d58427bac5848d6b;hpb=c6c5e2ca4ea51426e32608f8b8e2cbcd5f1ab74f;p=nageru diff --git a/glwidget.cpp b/glwidget.cpp index 7caee37..bf537de 100644 --- a/glwidget.cpp +++ b/glwidget.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -32,11 +33,23 @@ class QMouseEvent; #include #include - 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 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 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 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) {