From f245cb0d0453e0e8bd5c7d40720bd0a5b50454ee Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Fri, 22 Jan 2016 01:43:20 +0100 Subject: [PATCH] Make signal mapping changeable by right-clicking on the preview. --- bmusb | 2 +- glwidget.cpp | 38 ++++++++++++++++++++++++++++++++++++++ glwidget.h | 3 +++ mixer.h | 22 ++++++++++++++++++++++ theme.cpp | 37 +++++++++++++++++++++++++++++++------ theme.h | 6 +++++- theme.lua | 15 +++++++++++++++ 7 files changed, 115 insertions(+), 8 deletions(-) diff --git a/bmusb b/bmusb index 4a27515..cd4dd0e 160000 --- a/bmusb +++ b/bmusb @@ -1 +1 @@ -Subproject commit 4a275155fbd23690652c0478b12363d254f84e16 +Subproject commit cd4dd0ed2eaf14fc50f0601295c821a41b603490 diff --git a/glwidget.cpp b/glwidget.cpp index 3d5b0f9..e71ac40 100644 --- a/glwidget.cpp +++ b/glwidget.cpp @@ -6,6 +6,8 @@ #include // Needs to come before egl.h. #include #include +#include +#include #include #include @@ -31,6 +33,7 @@ class QWidget; #include using namespace std; +using namespace std::placeholders; GLWidget::GLWidget(QWidget *parent) : QGLWidget(parent, global_share_widget) @@ -59,6 +62,15 @@ void GLWidget::initializeGL() emit resolution_updated(output); }); + if (output >= Mixer::OUTPUT_INPUT0) { + int signal_num = global_mixer->get_channel_signal(output); + if (signal_num != -1) { + setContextMenuPolicy(Qt::CustomContextMenu); + connect(this, &QWidget::customContextMenuRequested, + bind(&GLWidget::show_context_menu, this, signal_num, _1)); + } + } + glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); @@ -99,3 +111,29 @@ void GLWidget::mousePressEvent(QMouseEvent *event) { emit clicked(); } + +void GLWidget::show_context_menu(int signal_num, const QPoint &pos) +{ + QPoint global_pos = mapToGlobal(pos); + + QMenu menu; + QActionGroup group(&menu); + + unsigned num_cards = global_mixer->get_num_cards(); + unsigned current_card = global_mixer->map_signal(signal_num); + for (unsigned card_index = 0; card_index < num_cards; ++card_index) { + QString description(QString::fromStdString(global_mixer->get_card_description(card_index))); + QAction *action = new QAction(description, &group); + action->setCheckable(true); + if (current_card == card_index) { + action->setChecked(true); + } + action->setData(card_index); + menu.addAction(action); + } + QAction *selected_item = menu.exec(global_pos); + if (selected_item) { + unsigned card_index = selected_item->data().toInt(nullptr); + global_mixer->set_signal_mapping(signal_num, card_index); + } +} diff --git a/glwidget.h b/glwidget.h index 857d733..ed5e486 100644 --- a/glwidget.h +++ b/glwidget.h @@ -48,6 +48,9 @@ signals: void transition_names_updated(std::vector transition_names); void resolution_updated(Mixer::Output output); +private slots: + void show_context_menu(int signal_num, const QPoint &pos); + private: Mixer::Output output; GLuint vao, program_num; diff --git a/mixer.h b/mixer.h index 3c1a952..32e8168 100644 --- a/mixer.h +++ b/mixer.h @@ -126,6 +126,21 @@ public: return theme->get_channel_name(channel); } + int get_channel_signal(unsigned channel) const + { + return theme->get_channel_signal(channel); + } + + int map_signal(unsigned channel) + { + return theme->map_signal(channel); + } + + void set_signal_mapping(int signal, int card) + { + return theme->set_signal_mapping(signal, card); + } + bool get_supports_set_wb(unsigned channel) const { return theme->get_supports_set_wb(channel); @@ -209,6 +224,13 @@ public: void reset_meters(); + unsigned get_num_cards() const { return num_cards; } + + std::string get_card_description(unsigned card_index) const { + assert(card_index < num_cards); + return cards[card_index].usb->get_description(); + } + private: void bm_frame(unsigned card_index, uint16_t timecode, FrameAllocator::Frame video_frame, size_t video_offset, uint16_t video_format, diff --git a/theme.cpp b/theme.cpp index 3f387f8..0c74a8b 100644 --- a/theme.cpp +++ b/theme.cpp @@ -782,6 +782,22 @@ string Theme::get_channel_name(unsigned channel) return ret; } +int Theme::get_channel_signal(unsigned channel) +{ + unique_lock lock(m); + lua_getglobal(L, "channel_signal"); + lua_pushnumber(L, channel); + if (lua_pcall(L, 1, 1, 0) != 0) { + fprintf(stderr, "error running function `channel_signal': %s\n", lua_tostring(L, -1)); + exit(1); + } + + int ret = luaL_checknumber(L, 1); + lua_pop(L, 1); + assert(lua_gettop(L) == 0); + return ret; +} + bool Theme::get_supports_set_wb(unsigned channel) { unique_lock lock(m); @@ -837,14 +853,23 @@ vector Theme::get_transition_names(float t) int Theme::map_signal(int signal_num) { + unique_lock lock(map_m); + if (signal_to_card_mapping.count(signal_num)) { + return signal_to_card_mapping[signal_num]; + } if (signal_num >= int(num_cards)) { - if (signals_warned_about.insert(signal_num).second) { - fprintf(stderr, "WARNING: Theme asked for input %d, but we only have %u card(s).\n", signal_num, num_cards); - fprintf(stderr, "Mapping to card %d instead.\n", signal_num % num_cards); - } - signal_num %= num_cards; + fprintf(stderr, "WARNING: Theme asked for input %d, but we only have %u card(s).\n", signal_num, num_cards); + fprintf(stderr, "Mapping to card %d instead.\n", signal_num % num_cards); } - return signal_num; + signal_to_card_mapping[signal_num] = signal_num % num_cards; + return signal_num % num_cards; +} + +void Theme::set_signal_mapping(int signal_num, int card_num) +{ + unique_lock lock(map_m); + assert(card_num < int(num_cards)); + signal_to_card_mapping[signal_num] = card_num; } void Theme::transition_clicked(int transition_num, float t) diff --git a/theme.h b/theme.h index 4803973..660a2cd 100644 --- a/theme.h +++ b/theme.h @@ -54,7 +54,9 @@ public: int get_num_channels() const { return num_channels; } int map_signal(int signal_num); + void set_signal_mapping(int signal_num, int card_num); std::string get_channel_name(unsigned channel); + int get_channel_signal(unsigned channel); bool get_supports_set_wb(unsigned channel); void set_wb(unsigned channel, double r, double g, double b); @@ -75,7 +77,9 @@ private: movit::ResourcePool *resource_pool; int num_channels; unsigned num_cards; - std::set signals_warned_about; + + std::mutex map_m; + std::map signal_to_card_mapping; // Protected by . friend class LiveInputWrapper; }; diff --git a/theme.lua b/theme.lua index f561613..243b352 100644 --- a/theme.lua +++ b/theme.lua @@ -298,6 +298,21 @@ function channel_name(channel) end end +-- API ENTRY POINT +-- Returns, given a channel number, which signal it corresponds to (starting from 0). +-- Should return -1 if the channel does not correspond to a simple signal. +-- Called once for each channel, at the start of the program. +-- Will never be called for live (0) or preview (1). +function channel_signal(channel) + if channel == 2 then + return 0 + elseif channel == 3 then + return 1 + else + return -1 + end +end + -- API ENTRY POINT -- Returns if a given channel supports setting white balance (starting from 2). -- Called only once for each channel, at the start of the program. -- 2.39.2