});
global_mixer->set_frame_ready_callback(output, [this]{
QMetaObject::invokeMethod(this, "update", Qt::AutoConnection);
- emit transition_names_updated(global_mixer->get_transition_names());
- emit resolution_updated(output);
- emit color_updated(output);
});
-
+ if (output == Mixer::OUTPUT_LIVE) {
+ global_mixer->set_transition_names_updated_callback(output, [this](const vector<string> &names){
+ emit transition_names_updated(names);
+ });
+ }
if (output >= Mixer::OUTPUT_INPUT0) {
+ global_mixer->set_name_updated_callback(output, [this](const string &name){
+ emit name_updated(output, name);
+ });
+ global_mixer->set_color_updated_callback(output, [this](const string &color){
+ emit color_updated(output, color);
+ });
+
int signal_num = global_mixer->get_channel_signal(output);
if (signal_num != -1) {
setContextMenuPolicy(Qt::CustomContextMenu);
signals:
void clicked();
void transition_names_updated(std::vector<std::string> transition_names);
- void resolution_updated(Mixer::Output output);
- void color_updated(Mixer::Output output);
+ void name_updated(Mixer::Output output, const std::string &name);
+ void color_updated(Mixer::Output output, const std::string &color);
private slots:
void show_context_menu(unsigned signal_num, const QPoint &pos);
using namespace std;
using namespace std::placeholders;
+Q_DECLARE_METATYPE(std::string);
Q_DECLARE_METATYPE(std::vector<std::string>);
MainWindow *global_mainwindow = nullptr;
transition_btn1 = ui->transition_btn1;
transition_btn2 = ui->transition_btn2;
transition_btn3 = ui->transition_btn3;
+ qRegisterMetaType<string>("std::string");
qRegisterMetaType<vector<string>>("std::vector<std::string>");
connect(ui->me_preview, &GLWidget::transition_names_updated, this, &MainWindow::set_transition_names);
qRegisterMetaType<Mixer::Output>("Mixer::Output");
connect(ui_display->display, &GLWidget::clicked, bind(&MainWindow::channel_clicked, this, i));
// Let the theme update the text whenever the resolution or color changed.
- connect(ui_display->display, &GLWidget::resolution_updated, this, &MainWindow::update_channel_name);
+ connect(ui_display->display, &GLWidget::name_updated, this, &MainWindow::update_channel_name);
connect(ui_display->display, &GLWidget::color_updated, this, &MainWindow::update_channel_color);
// Hook up the keyboard key.
}
}
-void MainWindow::update_channel_name(Mixer::Output output)
+void MainWindow::update_channel_name(Mixer::Output output, const string &name)
{
if (output >= Mixer::OUTPUT_INPUT0) {
unsigned channel = output - Mixer::OUTPUT_INPUT0;
- previews[channel]->label->setText(global_mixer->get_channel_name(output).c_str());
+ previews[channel]->label->setText(name.c_str());
}
}
-void MainWindow::update_channel_color(Mixer::Output output)
+void MainWindow::update_channel_color(Mixer::Output output, const string &color)
{
if (output >= Mixer::OUTPUT_INPUT0) {
unsigned channel = output - Mixer::OUTPUT_INPUT0;
- string color = global_mixer->get_channel_color(output);
previews[channel]->frame->setStyleSheet(QString::fromStdString("background-color:" + color));
}
}
void channel_clicked(int channel_number);
void wb_button_clicked(int channel_number);
void set_transition_names(std::vector<std::string> transition_names);
- void update_channel_name(Mixer::Output output);
- void update_channel_color(Mixer::Output output);
+ void update_channel_name(Mixer::Output output, const std::string &name);
+ void update_channel_color(Mixer::Output output, const std::string &color);
void gain_staging_knob_changed(int value);
void final_makeup_gain_knob_changed(int value);
void cutoff_knob_changed(int value);
theme.reset(new Theme(global_flags.theme_filename.c_str(), resource_pool.get(), num_cards));
for (unsigned i = 0; i < NUM_OUTPUTS; ++i) {
output_channel[i].parent = this;
+ output_channel[i].channel = i;
}
ImageFormat inout_format;
has_ready_frame = true;
}
- if (has_new_frame_ready_callback) {
+ if (new_frame_ready_callback) {
new_frame_ready_callback();
}
+
+ // Reduce the number of callbacks by filtering duplicates. The reason
+ // why we bother doing this is that Qt seemingly can get into a state
+ // where its builds up an essentially unbounded queue of signals,
+ // consuming more and more memory, and there's no good way of collapsing
+ // user-defined signals or limiting the length of the queue.
+ if (transition_names_updated_callback) {
+ vector<string> transition_names = global_mixer->get_transition_names();
+ bool changed = false;
+ if (transition_names.size() != last_transition_names.size()) {
+ changed = true;
+ } else {
+ for (unsigned i = 0; i < transition_names.size(); ++i) {
+ if (transition_names[i] != last_transition_names[i]) {
+ changed = true;
+ break;
+ }
+ }
+ }
+ if (changed) {
+ transition_names_updated_callback(transition_names);
+ last_transition_names = transition_names;
+ }
+ }
+ if (name_updated_callback) {
+ string name = global_mixer->get_channel_name(channel);
+ if (name != last_name) {
+ name_updated_callback(name);
+ last_name = name;
+ }
+ }
+ if (color_updated_callback) {
+ string color = global_mixer->get_channel_color(channel);
+ if (color != last_color) {
+ color_updated_callback(color);
+ last_color = color;
+ }
+ }
}
bool Mixer::OutputChannel::get_display_frame(DisplayFrame *frame)
void Mixer::OutputChannel::set_frame_ready_callback(Mixer::new_frame_ready_callback_t callback)
{
new_frame_ready_callback = callback;
- has_new_frame_ready_callback = true;
+}
+
+void Mixer::OutputChannel::set_transition_names_updated_callback(Mixer::transition_names_updated_callback_t callback)
+{
+ transition_names_updated_callback = callback;
+}
+
+void Mixer::OutputChannel::set_name_updated_callback(Mixer::name_updated_callback_t callback)
+{
+ name_updated_callback = callback;
+}
+
+void Mixer::OutputChannel::set_color_updated_callback(Mixer::color_updated_callback_t callback)
+{
+ color_updated_callback = callback;
}
mutex RefCountedGLsync::fence_lock;
output_channel[output].set_frame_ready_callback(callback);
}
+ // TODO: Should this really be per-channel? Shouldn't it just be called for e.g. the live output?
+ typedef std::function<void(const std::vector<std::string> &)> transition_names_updated_callback_t;
+ void set_transition_names_updated_callback(Output output, transition_names_updated_callback_t callback)
+ {
+ output_channel[output].set_transition_names_updated_callback(callback);
+ }
+
+ typedef std::function<void(const std::string &)> name_updated_callback_t;
+ void set_name_updated_callback(Output output, name_updated_callback_t callback)
+ {
+ output_channel[output].set_name_updated_callback(callback);
+ }
+
+ typedef std::function<void(const std::string &)> color_updated_callback_t;
+ void set_color_updated_callback(Output output, color_updated_callback_t callback)
+ {
+ output_channel[output].set_color_updated_callback(callback);
+ }
+
typedef std::function<void(float level_lufs, float peak_db,
float global_level_lufs, float range_low_lufs, float range_high_lufs,
float gain_staging_db, float final_makeup_gain_db,
void output_frame(DisplayFrame frame);
bool get_display_frame(DisplayFrame *frame);
void set_frame_ready_callback(new_frame_ready_callback_t callback);
+ 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);
private:
friend class Mixer;
+ unsigned channel;
Mixer *parent = nullptr; // Not owned.
std::mutex frame_mutex;
DisplayFrame current_frame, ready_frame; // protected by <frame_mutex>
bool has_current_frame = false, has_ready_frame = false; // protected by <frame_mutex>
new_frame_ready_callback_t new_frame_ready_callback;
- bool has_new_frame_ready_callback = false;
+ transition_names_updated_callback_t transition_names_updated_callback;
+ name_updated_callback_t name_updated_callback;
+ color_updated_callback_t color_updated_callback;
+
+ std::vector<std::string> last_transition_names;
+ std::string last_name, last_color;
};
OutputChannel output_channel[NUM_OUTPUTS];