]> git.sesse.net Git - nageru/commitdiff
Allow controlling video mixing from MIDI events.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Fri, 8 Mar 2019 21:56:52 +0000 (22:56 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Fri, 8 Mar 2019 21:56:52 +0000 (22:56 +0100)
Adapted from a patch by Yann Dubreuil, from the BreizhCamp repository.

nageru/mainwindow.cpp
nageru/mainwindow.h
nageru/midi_mapper.cpp
nageru/midi_mapper.h
nageru/midi_mapping_dialog.cpp
nageru/midi_mapping_dialog.h
nageru/nageru_midi_mapping.proto

index d436040f0cede55578b095a7d3eeea1f8a780142..96552a542d35d0dc0c65883903f270982b6b6ae9 100644 (file)
@@ -253,30 +253,16 @@ MainWindow::MainWindow()
        qRegisterMetaType<Mixer::Output>("Mixer::Output");
 
        // Hook up the prev/next buttons on the audio views.
-       auto prev_page = [this]{
-               if (global_audio_mixer->get_mapping_mode() == AudioMixer::MappingMode::MULTICHANNEL) {
-                       ui->audio_views->setCurrentIndex((ui->audio_views->currentIndex() + 2) % 3);
-               } else {
-                       ui->audio_views->setCurrentIndex(2 - ui->audio_views->currentIndex());  // Switch between 0 and 2.
-               }
-       };
-       auto next_page = [this]{
-               if (global_audio_mixer->get_mapping_mode() == AudioMixer::MappingMode::MULTICHANNEL) {
-                       ui->audio_views->setCurrentIndex((ui->audio_views->currentIndex() + 1) % 3);
-               } else {
-                       ui->audio_views->setCurrentIndex(2 - ui->audio_views->currentIndex());  // Switch between 0 and 2.
-               }
-       };
-       connect(ui->compact_prev_page, &QAbstractButton::clicked, prev_page);
-       connect(ui->compact_next_page, &QAbstractButton::clicked, next_page);
-       connect(ui->full_prev_page, &QAbstractButton::clicked, prev_page);
-       connect(ui->full_next_page, &QAbstractButton::clicked, next_page);
-       connect(ui->video_grid_prev_page, &QAbstractButton::clicked, prev_page);
-       connect(ui->video_grid_next_page, &QAbstractButton::clicked, next_page);
+       connect(ui->compact_prev_page, &QAbstractButton::clicked, this, &MainWindow::prev_page);
+       connect(ui->compact_next_page, &QAbstractButton::clicked, this, &MainWindow::next_page);
+       connect(ui->full_prev_page, &QAbstractButton::clicked, this, &MainWindow::prev_page);
+       connect(ui->full_next_page, &QAbstractButton::clicked, this, &MainWindow::next_page);
+       connect(ui->video_grid_prev_page, &QAbstractButton::clicked, this, &MainWindow::prev_page);
+       connect(ui->video_grid_next_page, &QAbstractButton::clicked, this, &MainWindow::next_page);
 
        // And bind the same to PgUp/PgDown.
-       connect(new QShortcut(QKeySequence::MoveToNextPage, this), &QShortcut::activated, next_page);
-       connect(new QShortcut(QKeySequence::MoveToPreviousPage, this), &QShortcut::activated, prev_page);
+       connect(new QShortcut(QKeySequence::MoveToNextPage, this), &QShortcut::activated, this, &MainWindow::next_page);
+       connect(new QShortcut(QKeySequence::MoveToPreviousPage, this), &QShortcut::activated, this, &MainWindow::prev_page);
 
        // When the audio view changes, move the previews.
        connect(ui->audio_views, &QStackedWidget::currentChanged, bind(&MainWindow::audio_view_changed, this, _1));
@@ -295,7 +281,7 @@ MainWindow::MainWindow()
                if (!load_midi_mapping_from_file(global_flags.midi_mapping_filename, &midi_mapping)) {
                        fprintf(stderr, "Couldn't load MIDI mapping '%s'; exiting.\n",
                                global_flags.midi_mapping_filename.c_str());
-                       exit(1);
+                       ::exit(1);
                }
                midi_mapper.set_midi_mapping(midi_mapping);
        }
@@ -306,6 +292,24 @@ MainWindow::MainWindow()
        }
 }
 
+void MainWindow::prev_page()
+{
+       if (global_audio_mixer->get_mapping_mode() == AudioMixer::MappingMode::MULTICHANNEL) {
+               ui->audio_views->setCurrentIndex((ui->audio_views->currentIndex() + 2) % 3);
+       } else {
+               ui->audio_views->setCurrentIndex(2 - ui->audio_views->currentIndex());  // Switch between 0 and 2.
+       }
+}
+
+void MainWindow::next_page()
+{
+       if (global_audio_mixer->get_mapping_mode() == AudioMixer::MappingMode::MULTICHANNEL) {
+               ui->audio_views->setCurrentIndex((ui->audio_views->currentIndex() + 1) % 3);
+       } else {
+               ui->audio_views->setCurrentIndex(2 - ui->audio_views->currentIndex());  // Switch between 0 and 2.
+       }
+}
+
 void MainWindow::resizeEvent(QResizeEvent* event)
 {
        QMainWindow::resizeEvent(event);
@@ -1244,6 +1248,42 @@ void MainWindow::toggle_auto_makeup_gain()
        }
 }
 
+void MainWindow::switch_video_channel(int channel_number)
+{
+       global_mixer->channel_clicked(channel_number);
+}
+
+void MainWindow::apply_transition(int transition_number)
+{
+       global_mixer->transition_clicked(transition_number);
+}
+
+void MainWindow::prev_audio_view()
+{
+       post_to_main_thread([this]{
+               prev_page();
+       });
+}
+
+void MainWindow::next_audio_view()
+{
+       post_to_main_thread([this]{
+               next_page();
+       });
+}
+
+void MainWindow::begin_new_segment()
+{
+       global_mixer->schedule_cut();
+}
+
+void MainWindow::exit()
+{
+       post_to_main_thread([this]{
+               close();
+       });
+}
+
 void MainWindow::highlight_locut(bool highlight)
 {
        post_to_main_thread([this, highlight]{
index 36be4b8be01a90dbff75d095c1af61b5bc1aa7d1..37b1ce02006bd06b4557cf9c3851e4d0d3a71d98 100644 (file)
@@ -96,6 +96,13 @@ public slots:
        void toggle_limiter() override;
        void toggle_auto_makeup_gain() override;
 
+       void switch_video_channel(int channel_number) override;
+       void apply_transition(int transition_number) override;
+       void prev_audio_view() override;
+       void next_audio_view() override;
+       void begin_new_segment() override;
+       void exit() override;
+
        void clear_all_highlights() override;
 
        void highlight_locut(bool highlight) override;
@@ -133,6 +140,8 @@ private:
        void update_stereo_label(unsigned bus_index, int stereo_width_percent);
        void update_eq_label(unsigned bus_index, EQBand band, float gain_db);
        void setup_theme_menu();
+       void prev_page();
+       void next_page();
 
        // Called from DiskSpaceEstimator.
        void report_disk_space(off_t free_bytes, double estimated_seconds_left);
index d0a42ec60274e05c00d98ad528162ad3519c5b94..1dccd8e2edc039a6da15ecaa4d87433b6d6c62d2 100644 (file)
@@ -179,6 +179,18 @@ void MIDIMapper::note_on_received(int note)
                bind(&ControllerReceiver::toggle_limiter, receiver));
        match_button(note, MIDIMappingBusProto::kToggleAutoMakeupGainFieldNumber, MIDIMappingProto::kToggleAutoMakeupGainBankFieldNumber,
                bind(&ControllerReceiver::toggle_auto_makeup_gain, receiver));
+       match_button(note, MIDIMappingBusProto::kSwitchVideoChannelFieldNumber, MIDIMappingProto::kSwitchVideoChannelBankFieldNumber,
+               bind(&ControllerReceiver::switch_video_channel, receiver, _1));
+       match_button(note, MIDIMappingBusProto::kApplyTransitionFieldNumber, MIDIMappingProto::kApplyTransitionBankFieldNumber,
+               bind(&ControllerReceiver::apply_transition, receiver, _1));
+       match_button(note, MIDIMappingBusProto::kPrevAudioViewFieldNumber, MIDIMappingProto::kPrevAudioViewBankFieldNumber,
+               bind(&ControllerReceiver::prev_audio_view, receiver));
+       match_button(note, MIDIMappingBusProto::kNextAudioViewFieldNumber, MIDIMappingProto::kNextAudioViewBankFieldNumber,
+               bind(&ControllerReceiver::prev_audio_view, receiver));
+       match_button(note, MIDIMappingBusProto::kBeginNewVideoSegmentFieldNumber, MIDIMappingProto::kBeginNewVideoSegmentBankFieldNumber,
+               bind(&ControllerReceiver::begin_new_segment, receiver));
+       match_button(note, MIDIMappingBusProto::kExitFieldNumber, MIDIMappingProto::kExitBankFieldNumber,
+               bind(&ControllerReceiver::exit, receiver));
 }
 
 void MIDIMapper::update_num_subscribers(unsigned num_subscribers)
index dd5c7ab33a7bf957adf3da5d12264f0a4f11c39b..72272a1846fdf803b02d842551c29de8236ec33b 100644 (file)
@@ -47,6 +47,14 @@ public:
        virtual void toggle_limiter() = 0;
        virtual void toggle_auto_makeup_gain() = 0;
 
+       // Non-audio events.
+       virtual void switch_video_channel(int channel_number) = 0;
+       virtual void apply_transition(int transition_number) = 0;
+       virtual void prev_audio_view() = 0;
+       virtual void next_audio_view() = 0;
+       virtual void begin_new_segment() = 0;
+       virtual void exit() = 0;
+
        // Signals to highlight controls to mark them to the user
        // as MIDI-controllable (or not).
        virtual void clear_all_highlights() = 0;
index d27a0c2315e18c56f0c6005d0ef3d078d291fbf2..8352729960422e6a761f8b70bd7c339a9750029f 100644 (file)
@@ -88,6 +88,18 @@ vector<MIDIMappingDialog::Control> global_lights = {
        { "Auto makeup gain is on",   MIDIMappingBusProto::kAutoMakeupGainIsOnFieldNumber, 0 },
 };
 
+vector<MIDIMappingDialog::Control> global_video = {
+       { "Switch video channel",     MIDIMappingBusProto::kSwitchVideoChannelFieldNumber, MIDIMappingProto::kSwitchVideoChannelBankFieldNumber },
+       { "Apply transition",         MIDIMappingBusProto::kApplyTransitionFieldNumber, MIDIMappingProto::kApplyTransitionBankFieldNumber },
+};
+
+vector<MIDIMappingDialog::Control> main_ui = {
+       { "Previous audio view",       MIDIMappingBusProto::kPrevAudioViewFieldNumber, MIDIMappingProto::kPrevAudioViewBankFieldNumber },
+       { "Next audio view",           MIDIMappingBusProto::kNextAudioViewFieldNumber, MIDIMappingProto::kNextAudioViewBankFieldNumber },
+       { "Begin new video segment",   MIDIMappingBusProto::kBeginNewVideoSegmentFieldNumber, MIDIMappingProto::kBeginNewVideoSegmentBankFieldNumber },
+       { "Exit Nageru",               MIDIMappingBusProto::kExitFieldNumber, MIDIMappingProto::kExitBankFieldNumber },
+};
+
 namespace {
 
 int get_bank(const MIDIMappingProto &mapping_proto, int bank_field_number, int default_value)
@@ -162,8 +174,10 @@ MIDIMappingDialog::MIDIMappingDialog(MIDIMapper *mapper)
        add_controls("Per-bus controllers", ControlType::CONTROLLER, SpinnerGroup::PER_BUS_CONTROLLERS, mapping_proto, per_bus_controllers);
        add_controls("Per-bus buttons", ControlType::BUTTON, SpinnerGroup::PER_BUS_BUTTONS, mapping_proto, per_bus_buttons);
        add_controls("Per-bus lights", ControlType::LIGHT, SpinnerGroup::PER_BUS_LIGHTS, mapping_proto, per_bus_lights);
+       add_controls("Video mixing", ControlType::BUTTON, SpinnerGroup::GLOBAL_BUTTONS, mapping_proto, global_video);
        add_controls("Global controllers", ControlType::CONTROLLER, SpinnerGroup::GLOBAL_CONTROLLERS, mapping_proto, global_controllers);
        add_controls("Global buttons", ControlType::BUTTON, SpinnerGroup::GLOBAL_BUTTONS, mapping_proto, global_buttons);
+       add_controls("Main UI", ControlType::BUTTON, SpinnerGroup::GLOBAL_BUTTONS, mapping_proto, main_ui);
        add_controls("Global lights", ControlType::LIGHT, SpinnerGroup::GLOBAL_LIGHTS, mapping_proto, global_lights);
        fill_controls_from_mapping(mapping_proto);
 
index c36781d1bb6af0521ba5b06e11a29edd1e32ca2d..89374fe82feee7b7033fcc9238388b0b3ee6c45b 100644 (file)
@@ -85,6 +85,13 @@ public:
        void highlight_toggle_limiter(bool highlight) override {}
        void highlight_toggle_auto_makeup_gain(bool highlight) override {}
 
+       void switch_video_channel(int channel_number) override {}
+       void apply_transition(int transition_number) override {}
+       void prev_audio_view() override {}
+       void next_audio_view() override {}
+       void begin_new_segment() override {}
+       void exit() override {}
+
        // Raw events; used for the editor dialog only.
        void controller_changed(unsigned controller) override;
        void note_on(unsigned note) override;
index 6eb8001ba4e00dd539297347aa50ebcb257780f0..a5fbcf99be3e83239b1304163d0fe5b2a430edd4 100644 (file)
@@ -40,6 +40,16 @@ message MIDIMappingBusProto {
        optional MIDIButtonProto toggle_limiter = 20;
        optional MIDIButtonProto toggle_auto_makeup_gain = 21;
 
+       // Video mixing.
+       optional MIDIButtonProto switch_video_channel = 38;
+       optional MIDIButtonProto apply_transition = 39;
+
+       // Main UI. Really global, but see the comment on lo-cut etc. above.
+       optional MIDIButtonProto prev_audio_view = 40;
+       optional MIDIButtonProto next_audio_view = 41;
+       optional MIDIButtonProto begin_new_video_segment = 42;
+       optional MIDIButtonProto exit = 43;
+
        // These are also global (they belong to the master bus), and unlike
        // the bank change commands, one would usually have only one of each,
        // but there's no reason to limit them to one each, and the editor UI
@@ -94,6 +104,10 @@ message MIDIMappingProto {
        optional int32 toggle_compressor_bank = 11;
        optional int32 clear_peak_bank = 12;
 
+       // Bus (not non-audio) buttons.
+       optional int32 switch_video_channel_bank = 24;
+       optional int32 apply_transition_bank = 25;
+
        // Global controller banks.
        optional int32 locut_bank = 13;
        optional int32 limiter_threshold_bank = 14;
@@ -103,5 +117,11 @@ message MIDIMappingProto {
        optional int32 toggle_limiter_bank = 16;
        optional int32 toggle_auto_makeup_gain_bank = 17;
 
+       // Global non-audio buttons.
+       optional int32 prev_audio_view_bank = 20;
+       optional int32 next_audio_view_bank = 21;
+       optional int32 begin_new_video_segment_bank = 22;
+       optional int32 exit_bank = 23;
+
        repeated MIDIMappingBusProto bus_mapping = 18;
 }