In Futatabi, make it possible to set custom source labels.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 17 Feb 2020 22:13:29 +0000 (23:13 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 17 Feb 2020 22:13:31 +0000 (23:13 +0100)
An operator was consistently confused by having 3 on a left camera
and 4 on a right camera, and wanted L3 and R4 labels, so here goes :-)
There's no auto-import from Nageru at this point; it needs to be set
using --source-label NUM:LABEL (or -l NUM:LABEL) from the command line.

futatabi/flags.cpp
futatabi/flags.h
futatabi/jpeg_frame_view.cpp
futatabi/jpeg_frame_view.h
futatabi/mainwindow.cpp

index fa1fe6e..a8ae958 100644 (file)
@@ -44,6 +44,7 @@ void usage()
        fprintf(stderr, "      --http-port PORT            which port to listen on for output\n");
        fprintf(stderr, "      --tally-url URL             URL to get tally color from (polled every 100 ms)\n");
        fprintf(stderr, "      --midi-mapping=FILE         start with the given MIDI controller mapping\n");
+       fprintf(stderr, "  -l  --source-label NUM:LABEL    label source NUM as LABEL, if visible\n");
 }
 
 void parse_flags(int argc, char *const argv[])
@@ -61,11 +62,12 @@ void parse_flags(int argc, char *const argv[])
                { "cue-in-point-padding", required_argument, 0, OPTION_CUE_IN_POINT_PADDING },
                { "cue-out-point-padding", required_argument, 0, OPTION_CUE_OUT_POINT_PADDING },
                { "midi-mapping", required_argument, 0, OPTION_MIDI_MAPPING },
+               { "source-label", required_argument, 0, 'l' },
                { 0, 0, 0, 0 }
        };
        for (;;) {
                int option_index = 0;
-               int c = getopt_long(argc, argv, "w:h:r:q:d:", long_options, &option_index);
+               int c = getopt_long(argc, argv, "w:h:r:q:d:l:", long_options, &option_index);
 
                if (c == -1) {
                        break;
@@ -99,6 +101,18 @@ void parse_flags(int argc, char *const argv[])
                case 'd':
                        global_flags.working_directory = optarg;
                        break;
+               case 'l': {
+                       int prefix_len;
+                       unsigned channel_idx;
+                       if (sscanf(optarg, "%u:%n", &channel_idx, &prefix_len) == 1) {
+                               const char *label = optarg + prefix_len;
+                               global_flags.source_labels[channel_idx] = label;
+                       } else {
+                               fprintf(stderr, "Invalid source label format (must be on the form NUM:LABEL)\n");
+                               exit(1);
+                       }
+                       break;
+               }
                case OPTION_HTTP_PORT:
                        global_flags.http_port = atoi(optarg);
                        break;
index 88379b5..6e59d9d 100644 (file)
@@ -4,6 +4,7 @@
 #include "defs.h"
 
 #include <string>
+#include <unordered_map>
 
 struct Flags {
        int width = 1280, height = 720;
@@ -20,6 +21,7 @@ struct Flags {
        double cue_out_point_padding_seconds = 0.0;  // Can be changed in the menus.
        bool cue_out_point_padding_set = false;
        std::string midi_mapping_filename;  // Empty for none.
+       std::unordered_map<unsigned, std::string> source_labels;
 };
 extern Flags global_flags;
 
index adc3764..eb0ed09 100644 (file)
@@ -465,10 +465,25 @@ void JPEGFrameView::set_overlay(const string &text)
                return;
        }
 
+       // Figure out how large the texture needs to be.
+       {
+               QImage img(overlay_width, overlay_height, QImage::Format_Grayscale8);
+               QPainter painter(&img);
+               QFont font = painter.font();
+               font.setPointSize(12);
+               QFontMetrics metrics(font);
+               overlay_base_width = lrint(metrics.boundingRect(QString::fromStdString(text)).width() + 8.0);
+               overlay_base_height = lrint(metrics.height());
+       }
+
        float dpr = QGuiApplication::primaryScreen()->devicePixelRatio();
        overlay_width = lrint(overlay_base_width * dpr);
        overlay_height = lrint(overlay_base_height * dpr);
 
+       // Work around OpenGL alignment issues.
+       while (overlay_width % 4 != 0) ++overlay_width;
+
+       // Now do the actual drawing.
        overlay_image.reset(new QImage(overlay_width, overlay_height, QImage::Format_Grayscale8));
        overlay_image->setDevicePixelRatio(dpr);
        overlay_image->fill(0);
index b66e265..108aa73 100644 (file)
@@ -65,7 +65,7 @@ private:
        std::shared_ptr<Frame> current_frame;  // So that we hold on to the pixels.
        std::shared_ptr<Frame> current_secondary_frame;  // Same.
 
-       static constexpr int overlay_base_width = 16, overlay_base_height = 16;
+       int overlay_base_width = 16, overlay_base_height = 16;
        int overlay_width = overlay_base_width, overlay_height = overlay_base_height;
        std::unique_ptr<QImage> overlay_image;  // If nullptr, no overlay.
        std::unique_ptr<movit::EffectChain> overlay_chain;  // Just to get the overlay on screen in the easiest way possible.
index 0ebb75c..49581e5 100644 (file)
@@ -324,7 +324,11 @@ void MainWindow::change_num_cameras()
                display->setAutoFillBackground(true);
                layout->addWidget(display);
 
-               display->set_overlay(to_string(i + 1));
+               if (global_flags.source_labels.count(i + 1)) {
+                       display->set_overlay(global_flags.source_labels[i + 1]);
+               } else {
+                       display->set_overlay(to_string(i + 1));
+               }
 
                QPushButton *preview_btn = new QPushButton(this);
                preview_btn->setMaximumSize(20, 17);