]> git.sesse.net Git - nageru/blobdiff - futatabi/mainwindow.cpp
Fix an overflow issue with long (>= 10 min) clips.
[nageru] / futatabi / mainwindow.cpp
index 189102b88cdf63e8659e8c1fe7e75de5ab95510a..a5592930e2a3217df0b980db3d65165a362c4781 100644 (file)
@@ -6,6 +6,7 @@
 #include "frame_on_disk.h"
 #include "player.h"
 #include "futatabi_midi_mapping.pb.h"
+#include "midi_mapping_dialog.h"
 #include "shared/aboutdialog.h"
 #include "shared/disk_space_estimator.h"
 #include "shared/post_to_main_thread.h"
@@ -64,8 +65,11 @@ MainWindow::MainWindow()
                        global_flags.interpolation_quality = settings.interpolation_quality() - 1;
                }
        }
-       if (!global_flags.cue_point_padding_set) {
-               global_flags.cue_point_padding_seconds = settings.cue_point_padding_seconds();  // Default 0 is fine.
+       if (!global_flags.cue_in_point_padding_set) {
+               global_flags.cue_in_point_padding_seconds = settings.cue_in_point_padding_seconds();  // Default 0 is fine.
+       }
+       if (!global_flags.cue_out_point_padding_set) {
+               global_flags.cue_out_point_padding_seconds = settings.cue_out_point_padding_seconds();  // Default 0 is fine.
        }
        if (global_flags.interpolation_quality == 0) {
                // Allocate something just for simplicity; we won't be using it
@@ -77,6 +81,7 @@ MainWindow::MainWindow()
        save_settings();
 
        // The menus.
+       connect(ui->midi_mapping_action, &QAction::triggered, this, &MainWindow::midi_mapping_triggered);
        connect(ui->exit_action, &QAction::triggered, this, &MainWindow::exit_triggered);
        connect(ui->export_cliplist_clip_multitrack_action, &QAction::triggered, this, &MainWindow::export_cliplist_clip_multitrack_triggered);
        connect(ui->export_playlist_clip_interpolated_action, &QAction::triggered, this, &MainWindow::export_playlist_clip_interpolated_triggered);
@@ -113,27 +118,49 @@ MainWindow::MainWindow()
        connect(ui->quality_3_action, &QAction::toggled, bind(&MainWindow::quality_toggled, this, 3, _1));
        connect(ui->quality_4_action, &QAction::toggled, bind(&MainWindow::quality_toggled, this, 4, _1));
 
-       // The cue point padding group.
-       QActionGroup *padding_group = new QActionGroup(ui->interpolation_menu);
-       padding_group->addAction(ui->padding_0_action);
-       padding_group->addAction(ui->padding_1_action);
-       padding_group->addAction(ui->padding_2_action);
-       padding_group->addAction(ui->padding_5_action);
-       if (global_flags.cue_point_padding_seconds <= 1e-3) {
-               ui->padding_0_action->setChecked(true);
-       } else if (fabs(global_flags.cue_point_padding_seconds - 1.0) < 1e-3) {
-               ui->padding_1_action->setChecked(true);
-       } else if (fabs(global_flags.cue_point_padding_seconds - 2.0) < 1e-3) {
-               ui->padding_2_action->setChecked(true);
-       } else if (fabs(global_flags.cue_point_padding_seconds - 5.0) < 1e-3) {
-               ui->padding_5_action->setChecked(true);
+       // The cue-in point padding group.
+       QActionGroup *in_padding_group = new QActionGroup(ui->in_padding_menu);
+       in_padding_group->addAction(ui->in_padding_0_action);
+       in_padding_group->addAction(ui->in_padding_1_action);
+       in_padding_group->addAction(ui->in_padding_2_action);
+       in_padding_group->addAction(ui->in_padding_5_action);
+       if (global_flags.cue_in_point_padding_seconds <= 1e-3) {
+               ui->in_padding_0_action->setChecked(true);
+       } else if (fabs(global_flags.cue_in_point_padding_seconds - 1.0) < 1e-3) {
+               ui->in_padding_1_action->setChecked(true);
+       } else if (fabs(global_flags.cue_in_point_padding_seconds - 2.0) < 1e-3) {
+               ui->in_padding_2_action->setChecked(true);
+       } else if (fabs(global_flags.cue_in_point_padding_seconds - 5.0) < 1e-3) {
+               ui->in_padding_5_action->setChecked(true);
+       } else {
+               // Nothing to check, which is fine.
+       }
+       connect(ui->in_padding_0_action, &QAction::toggled, bind(&MainWindow::in_padding_toggled, this, 0.0, _1));
+       connect(ui->in_padding_1_action, &QAction::toggled, bind(&MainWindow::in_padding_toggled, this, 1.0, _1));
+       connect(ui->in_padding_2_action, &QAction::toggled, bind(&MainWindow::in_padding_toggled, this, 2.0, _1));
+       connect(ui->in_padding_5_action, &QAction::toggled, bind(&MainWindow::in_padding_toggled, this, 5.0, _1));
+
+       // Same for the cue-out padding.
+       QActionGroup *out_padding_group = new QActionGroup(ui->out_padding_menu);
+       out_padding_group->addAction(ui->out_padding_0_action);
+       out_padding_group->addAction(ui->out_padding_1_action);
+       out_padding_group->addAction(ui->out_padding_2_action);
+       out_padding_group->addAction(ui->out_padding_5_action);
+       if (global_flags.cue_out_point_padding_seconds <= 1e-3) {
+               ui->out_padding_0_action->setChecked(true);
+       } else if (fabs(global_flags.cue_out_point_padding_seconds - 1.0) < 1e-3) {
+               ui->out_padding_1_action->setChecked(true);
+       } else if (fabs(global_flags.cue_out_point_padding_seconds - 2.0) < 1e-3) {
+               ui->out_padding_2_action->setChecked(true);
+       } else if (fabs(global_flags.cue_out_point_padding_seconds - 5.0) < 1e-3) {
+               ui->out_padding_5_action->setChecked(true);
        } else {
                // Nothing to check, which is fine.
        }
-       connect(ui->padding_0_action, &QAction::toggled, bind(&MainWindow::padding_toggled, this, 0.0, _1));
-       connect(ui->padding_1_action, &QAction::toggled, bind(&MainWindow::padding_toggled, this, 1.0, _1));
-       connect(ui->padding_2_action, &QAction::toggled, bind(&MainWindow::padding_toggled, this, 2.0, _1));
-       connect(ui->padding_5_action, &QAction::toggled, bind(&MainWindow::padding_toggled, this, 5.0, _1));
+       connect(ui->out_padding_0_action, &QAction::toggled, bind(&MainWindow::out_padding_toggled, this, 0.0, _1));
+       connect(ui->out_padding_1_action, &QAction::toggled, bind(&MainWindow::out_padding_toggled, this, 1.0, _1));
+       connect(ui->out_padding_2_action, &QAction::toggled, bind(&MainWindow::out_padding_toggled, this, 2.0, _1));
+       connect(ui->out_padding_5_action, &QAction::toggled, bind(&MainWindow::out_padding_toggled, this, 5.0, _1));
 
        global_disk_space_estimator = new DiskSpaceEstimator(bind(&MainWindow::report_disk_space, this, _1, _2));
        disk_free_label = new QLabel(this);
@@ -310,7 +337,10 @@ void MainWindow::change_num_cameras()
 
 MainWindow::~MainWindow()
 {
-       // Empty so that we can forward-declare Player in the .h file.
+       // We don't have a context to release Player's OpenGL resources in here,
+       // so instead of crashing on exit, leak it.
+       live_player.release();
+       preview_player.release();
 }
 
 void MainWindow::cue_in_clicked()
@@ -319,7 +349,7 @@ void MainWindow::cue_in_clicked()
                cliplist_clips->mutable_back()->pts_in = current_pts;
        } else {
                Clip clip;
-               clip.pts_in = max<int64_t>(current_pts - lrint(global_flags.cue_point_padding_seconds * TIMEBASE), 0);
+               clip.pts_in = max<int64_t>(current_pts - lrint(global_flags.cue_in_point_padding_seconds * TIMEBASE), 0);
                cliplist_clips->add_clip(clip);
                playlist_selection_changed();
        }
@@ -338,7 +368,7 @@ void MainWindow::cue_out_clicked()
                return;
        }
 
-       cliplist_clips->mutable_back()->pts_out = current_pts + lrint(global_flags.cue_point_padding_seconds * TIMEBASE);
+       cliplist_clips->mutable_back()->pts_out = current_pts + lrint(global_flags.cue_out_point_padding_seconds * TIMEBASE);
 
        // Select the item so that we can jog it.
        ui->clip_list->setFocus();
@@ -604,7 +634,8 @@ void MainWindow::save_settings()
 {
        SettingsProto settings;
        settings.set_interpolation_quality(global_flags.interpolation_quality + 1);
-       settings.set_cue_point_padding_seconds(global_flags.cue_point_padding_seconds);
+       settings.set_cue_in_point_padding_seconds(global_flags.cue_in_point_padding_seconds);
+       settings.set_cue_out_point_padding_seconds(global_flags.cue_out_point_padding_seconds);
        db.store_settings(settings);
 }
 
@@ -648,6 +679,7 @@ void MainWindow::speed_slider_changed(int percent)
        float speed = percent / 100.0f;
        ui->speed_lock_btn->setText(QString::fromStdString(" " + to_string(percent) + "%"));
        live_player->set_master_speed(speed);
+       midi_mapper.set_speed_light(speed);
 }
 
 void MainWindow::speed_lock_clicked()
@@ -981,6 +1013,11 @@ void MainWindow::report_disk_space(off_t free_bytes, double estimated_seconds_le
        });
 }
 
+void MainWindow::midi_mapping_triggered()
+{
+       MIDIMappingDialog(&midi_mapper).exec();
+}
+
 void MainWindow::exit_triggered()
 {
        close();
@@ -1119,12 +1156,21 @@ void MainWindow::quality_toggled(int quality, bool checked)
        save_settings();
 }
 
-void MainWindow::padding_toggled(double seconds, bool checked)
+void MainWindow::in_padding_toggled(double seconds, bool checked)
+{
+       if (!checked) {
+               return;
+       }
+       global_flags.cue_in_point_padding_seconds = seconds;
+       save_settings();
+}
+
+void MainWindow::out_padding_toggled(double seconds, bool checked)
 {
        if (!checked) {
                return;
        }
-       global_flags.cue_point_padding_seconds = seconds;
+       global_flags.cue_out_point_padding_seconds = seconds;
        save_settings();
 }
 
@@ -1302,6 +1348,7 @@ void MainWindow::set_master_speed(float speed)
                ui->speed_lock_btn->setText(QString::fromStdString(" " + to_string(percent) + "%"));
 
                live_player->set_master_speed(speed);
+               midi_mapper.set_speed_light(speed);
        });
 }