#include <stdint.h>
#include <QAction>
#include <QActionGroup>
+#include <QInputDialog>
#include <QList>
#include <QMenu>
#include <QPoint>
#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)
{
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;
} 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)
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);
// 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);
// --- 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) {
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) {
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) {
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) {