Add "maybe" rounding modes for rounding only if necessary.
authorDavid Robillard <d@drobilla.net>
Sun, 16 Nov 2014 07:01:02 +0000 (02:01 -0500)
committerDavid Robillard <d@drobilla.net>
Mon, 17 Nov 2014 03:35:45 +0000 (22:35 -0500)
gtk2_ardour/editor.cc
gtk2_ardour/editor_drag.cc
libs/ardour/ardour/types.h
libs/ardour/tempo.cc

index ac59ecab4fda1e0df317e4400a83fd26f00be2e9..e50ef982901634ce0879ec3af18ec935775d7370 100644 (file)
@@ -2588,7 +2588,10 @@ Editor::timecode_snap_to_internal (framepos_t& start, RoundMode direction, bool
 
        switch (_snap_type) {
        case SnapToTimecodeFrame:
-               if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
+               if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
+                   fmod((double)start, (double)_session->frames_per_timecode_frame()) == 0) {
+                       /* start is already on a whole timecode frame, do nothing */
+               } else if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
                        start = (framepos_t) (ceil ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
                } else {
                        start = (framepos_t) (floor ((double) start / _session->frames_per_timecode_frame()) *  _session->frames_per_timecode_frame());
@@ -2601,7 +2604,10 @@ Editor::timecode_snap_to_internal (framepos_t& start, RoundMode direction, bool
                } else {
                        start -= _session->config.get_timecode_offset ();
                }
-               if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
+               if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
+                   (start % one_timecode_second == 0)) {
+                       /* start is already on a whole second, do nothing */
+               } else if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
                        start = (framepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
                } else {
                        start = (framepos_t) floor ((double) start / one_timecode_second) * one_timecode_second;
@@ -2620,7 +2626,10 @@ Editor::timecode_snap_to_internal (framepos_t& start, RoundMode direction, bool
                } else {
                        start -= _session->config.get_timecode_offset ();
                }
-               if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
+               if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
+                   (start % one_timecode_minute == 0)) {
+                       /* start is already on a whole minute, do nothing */
+               } else if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
                        start = (framepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
                } else {
                        start = (framepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
@@ -2653,7 +2662,10 @@ Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark)
                return timecode_snap_to_internal (start, direction, for_mark);
 
        case SnapToCDFrame:
-               if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
+               if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
+                   start % (one_second/75) == 0) {
+                       /* start is already on a whole CD frame, do nothing */
+               } else if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
                        start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
                } else {
                        start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
@@ -2661,7 +2673,10 @@ Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark)
                break;
 
        case SnapToSeconds:
-               if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
+               if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
+                   start % one_second == 0) {
+                       /* start is already on a whole second, do nothing */
+               } else if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
                        start = (framepos_t) ceil ((double) start / one_second) * one_second;
                } else {
                        start = (framepos_t) floor ((double) start / one_second) * one_second;
@@ -2669,7 +2684,10 @@ Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark)
                break;
 
        case SnapToMinutes:
-               if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
+               if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
+                   start % one_minute == 0) {
+                       /* start is already on a whole minute, do nothing */
+               } else if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
                        start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
                } else {
                        start = (framepos_t) floor ((double) start / one_minute) * one_minute;
index 9df013264fa580ca3237c727b63163c97c23f949..773ef191dfafdc49db1ef81979ed750fef4f298a 100644 (file)
@@ -4221,9 +4221,9 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
                if (first_move) {
                        grab = adjusted_current_frame (event, false);
                        if (grab < pending_position) {
-                               _editor->snap_to (grab, RoundDownAlways);
+                               _editor->snap_to (grab, RoundDownMaybe);
                        }  else {
-                               _editor->snap_to (grab, RoundUpAlways);
+                               _editor->snap_to (grab, RoundUpMaybe);
                        }
                }
 
index 1b0ba5ea3c0113b572c2e4d22686abeb078f3d22..5daf9065e34fc01a5f588d729188c674abe23364 100644 (file)
@@ -217,9 +217,11 @@ namespace ARDOUR {
        };
 
        enum RoundMode {
+               RoundDownMaybe  = -2,  ///< Round down only if necessary
                RoundDownAlways = -1,  ///< Always round down, even if on a division
                RoundNearest    = 0,   ///< Round to nearest
-               RoundUpAlways   = 1    ///< Always round up, even if on a division
+               RoundUpAlways   = 1,   ///< Always round up, even if on a division
+               RoundUpMaybe    = 2    ///< Round up only if necessary
        };
 
        class AnyTime {
index 77128bd0c2482fcc8690cfc8ca4cbf12b6428309..6f667a93b667fd9890880cbd5a7fab674e4493c4 100644 (file)
@@ -1254,11 +1254,14 @@ TempoMap::round_to_beat_subdivision (framepos_t fr, int sub_num, RoundMode dir)
 
        if (dir > 0) {
 
-               /* round to next (even if we're on a subdivision */
+               /* round to next (or same iff dir == RoundUpMaybe) */
 
                uint32_t mod = the_beat.ticks % ticks_one_subdivisions_worth;
 
-               if (mod == 0) {
+               if (mod == 0 && dir == RoundUpMaybe) {
+                       /* right on the subdivision, which is fine, so do nothing */
+
+               } else if (mod == 0) {
                        /* right on the subdivision, so the difference is just the subdivision ticks */
                        the_beat.ticks += ticks_one_subdivisions_worth;
 
@@ -1278,11 +1281,14 @@ TempoMap::round_to_beat_subdivision (framepos_t fr, int sub_num, RoundMode dir)
 
        } else if (dir < 0) {
 
-               /* round to previous (even if we're on a subdivision) */
+               /* round to previous (or same iff dir == RoundDownMaybe) */
 
                uint32_t mod = the_beat.ticks % ticks_one_subdivisions_worth;
 
-               if (mod == 0) {
+               if (mod == 0 && dir == RoundDownMaybe) {
+                       /* right on the subdivision, which is fine, so do nothing */
+
+               } else if (mod == 0) {
                        /* right on the subdivision, so the difference is just the subdivision ticks */
                        difference = ticks_one_subdivisions_worth;
                } else {
@@ -1382,6 +1388,9 @@ TempoMap::round_to_type (framepos_t frame, RoundMode dir, BBTPointType type)
                        }
 
                        if ((*fi).is_bar() && (*fi).frame == frame) {
+                               if (dir == RoundDownMaybe) {
+                                       return frame;
+                               }
                                --fi;
                        }
 
@@ -1400,6 +1409,9 @@ TempoMap::round_to_type (framepos_t frame, RoundMode dir, BBTPointType type)
                        /* find bar following 'frame' */
 
                        if ((*fi).is_bar() && (*fi).frame == frame) {
+                               if (dir == RoundUpMaybe) {
+                                       return frame;
+                               }
                                ++fi;
                        }
 
@@ -1454,7 +1466,7 @@ TempoMap::round_to_type (framepos_t frame, RoundMode dir, BBTPointType type)
                                return 0;
                        }
 
-                       if ((*fi).frame >= frame) {
+                       if ((*fi).frame > frame || ((*fi).frame == frame && dir == RoundDownAlways)) {
                                DEBUG_TRACE (DEBUG::SnapBBT, "requested frame is on beat, step back\n");
                                --fi;
                        }
@@ -1462,7 +1474,7 @@ TempoMap::round_to_type (framepos_t frame, RoundMode dir, BBTPointType type)
                                                                     (*fi).bar, (*fi).beat, (*fi).frame));
                        return (*fi).frame;
                } else if (dir > 0) {
-                       if ((*fi).frame <= frame) {
+                       if ((*fi).frame < frame || ((*fi).frame == frame && dir == RoundUpAlways)) {
                                DEBUG_TRACE (DEBUG::SnapBBT, "requested frame is on beat, step forward\n");
                                ++fi;
                        }