+void MainWindow::jog_internal(JogDestination jog_destination, int row, int column, int stream_idx, int pts_delta)
+{
+ constexpr int camera_pts_per_pixel = 1500; // One click of most mice (15 degrees), multiplied by the default wheel_sensitivity.
+
+ int in_column, out_column, camera_column;
+ if (jog_destination == JOG_CLIP_LIST) {
+ in_column = int(ClipList::Column::IN);
+ out_column = int(ClipList::Column::OUT);
+ camera_column = -1;
+ } else if (jog_destination == JOG_PLAYLIST) {
+ in_column = int(PlayList::Column::IN);
+ out_column = int(PlayList::Column::OUT);
+ camera_column = int(PlayList::Column::CAMERA);
+ } else {
+ assert(false);
+ }
+
+ currently_deferring_model_changes = true;
+ {
+ current_change_id = (jog_destination == JOG_CLIP_LIST) ? "cliplist:" : "playlist:";
+ ClipProxy clip = (jog_destination == JOG_CLIP_LIST) ? cliplist_clips->mutable_clip(row) : playlist_clips->mutable_clip(row);
+ if (jog_destination == JOG_PLAYLIST) {
+ stream_idx = clip->stream_idx;
+ }
+
+ if (column == in_column) {
+ current_change_id += "in:" + to_string(row);
+ int64_t pts = clip->pts_in + pts_delta;
+ set_pts_in(pts, current_pts, clip);
+ preview_single_frame(pts, stream_idx, FIRST_AT_OR_AFTER);
+ } else if (column == out_column) {
+ current_change_id += "out:" + to_string(row);
+ int64_t pts = clip->pts_out + pts_delta;
+ pts = std::max(pts, clip->pts_in);
+ pts = std::min(pts, current_pts);
+ clip->pts_out = pts;
+ preview_single_frame(pts, stream_idx, LAST_BEFORE);
+ } else if (column == camera_column) {
+ current_change_id += "camera:" + to_string(row);
+ int angle_degrees = pts_delta;
+ if (last_mousewheel_camera_row == row) {
+ angle_degrees += leftover_angle_degrees;
+ }
+
+ int stream_idx = clip->stream_idx + angle_degrees / camera_pts_per_pixel;
+ stream_idx = std::max(stream_idx, 0);
+ stream_idx = std::min<int>(stream_idx, num_cameras - 1);
+ clip->stream_idx = stream_idx;
+
+ last_mousewheel_camera_row = row;
+ leftover_angle_degrees = angle_degrees % camera_pts_per_pixel;
+
+ // Don't update the live view, that's rarely what the operator wants.
+ }
+ }
+ currently_deferring_model_changes = false;
+}
+