diff options
Diffstat (limited to 'gtk2_ardour/editor.cc')
-rw-r--r-- | gtk2_ardour/editor.cc | 918 |
1 files changed, 409 insertions, 509 deletions
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 9ce693184a..ba9f9d1a74 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -133,7 +133,7 @@ #include "selection.h" #include "simple_progress_dialog.h" #include "sfdb_ui.h" -#include "tempo_lines.h" +#include "grid_lines.h" #include "time_axis_view.h" #include "time_info_box.h" #include "timers.h" @@ -160,44 +160,28 @@ using Gtkmm2ext::Keyboard; double Editor::timebar_height = 15.0; -static const gchar *_snap_type_strings[] = { - N_("CD Samples"), - N_("TC Frames"), - N_("TC Seconds"), - N_("TC Minutes"), - N_("Seconds"), - N_("Minutes"), - N_("Beats/128"), - N_("Beats/64"), - N_("Beats/32"), - N_("Beats/28"), - N_("Beats/24"), - N_("Beats/20"), - N_("Beats/16"), - N_("Beats/14"), - N_("Beats/12"), - N_("Beats/10"), - N_("Beats/8"), - N_("Beats/7"), - N_("Beats/6"), - N_("Beats/5"), - N_("Beats/4"), - N_("Beats/3"), - N_("Beats/2"), - N_("Beats"), - N_("Bars"), - N_("Marks"), - N_("Region starts"), - N_("Region ends"), - N_("Region syncs"), - N_("Region bounds"), - 0 -}; - -static const gchar *_snap_mode_strings[] = { +static const gchar *_grid_type_strings[] = { N_("No Grid"), - N_("Grid"), - N_("Magnetic"), + N_("Bar"), + N_("1/4 Note"), + N_("1/8 Note"), + N_("1/16 Note"), + N_("1/32 Note"), + N_("1/64 Note"), + N_("1/128 Note"), + N_("1/3 (8th triplet)"), // or "1/12" ? + N_("1/6 (16th triplet)"), + N_("1/12 (32nd triplet)"), + N_("1/24 (64th triplet)"), + N_("1/5 (8th quintuplet)"), + N_("1/10 (16th quintuplet)"), + N_("1/20 (32nd quintuplet)"), + N_("1/7 (8th septuplet)"), + N_("1/14 (16th septuplet)"), + N_("1/28 (32nd septuplet)"), + N_("Smpte"), + N_("MinSec"), + N_("Samples"), 0 }; @@ -252,9 +236,9 @@ Editor::Editor () , samples_per_pixel (2048) , zoom_focus (ZoomFocusPlayhead) , mouse_mode (MouseObject) - , pre_internal_snap_type (SnapToBeat) + , pre_internal_grid_type (GridTypeBeat) , pre_internal_snap_mode (SnapOff) - , internal_snap_type (SnapToBeat) + , internal_grid_type (GridTypeBeat) , internal_snap_mode (SnapOff) , _join_object_range_state (JOIN_OBJECT_RANGE_NONE) , _notebook_shrunk (false) @@ -337,6 +321,7 @@ Editor::Editor () , videotl_group (0) , snapped_cursor (0) , playhead_cursor (0) + , _region_boundary_cache_dirty (true) , edit_packer (4, 4, true) , vertical_adjustment (0.0, 0.0, 10.0, 400.0) , horizontal_adjustment (0.0, 0.0, 1e16) @@ -366,7 +351,7 @@ Editor::Editor () , scrub_reverse_distance (0) , have_pending_keyboard_selection (false) , pending_keyboard_selection_start (0) - , _snap_type (SnapToBeat) + , _grid_type (GridTypeBeat) , _snap_mode (SnapOff) , ignore_gui_changes (false) , _drags (new DragManager (this)) @@ -374,11 +359,10 @@ Editor::Editor () /* , last_event_time { 0, 0 } */ /* this initialization style requires C++11 */ , _dragging_playhead (false) , _dragging_edit_point (false) - , _show_measures (true) , _follow_playhead (true) , _stationary_playhead (false) , _maximised (false) - , tempo_lines (0) + , grid_lines (0) , global_rect_group (0) , time_line_group (0) , tempo_marker_menu (0) @@ -472,8 +456,7 @@ Editor::Editor () selection_op_history.clear(); before.clear(); - snap_type_strings = I18N (_snap_type_strings); - snap_mode_strings = I18N (_snap_mode_strings); + grid_type_strings = I18N (_grid_type_strings); zoom_focus_strings = I18N (_zoom_focus_strings); edit_mode_strings = I18N (_edit_mode_strings); edit_point_strings = I18N (_edit_point_strings); @@ -485,8 +468,7 @@ Editor::Editor () build_edit_mode_menu(); build_zoom_focus_menu(); build_track_count_menu(); - build_snap_mode_menu(); - build_snap_type_menu(); + build_grid_type_menu(); build_edit_point_menu(); location_marker_color = UIConfiguration::instance().color ("location marker"); @@ -855,6 +837,8 @@ Editor::Editor () setup_fade_images (); + set_grid_to (GridTypeNone); + instant_save (); } @@ -908,7 +892,7 @@ Editor::button_settings () const bool Editor::get_smart_mode () const { - return ((current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active()); + return ((current_mouse_mode() == MouseObject) && smart_mode_action->get_active()); } void @@ -1429,18 +1413,6 @@ Editor::set_session (Session *t) sigc::mem_fun (*this, &Editor::super_rapid_screen_update) ); - switch (_snap_type) { - case SnapToRegionStart: - case SnapToRegionEnd: - case SnapToRegionSync: - case SnapToRegionBoundary: - build_region_boundary_cache (); - break; - - default: - break; - } - /* register for undo history */ _session->register_with_memento_command_factory(id(), this); _session->register_with_memento_command_factory(_selection_memento->id(), _selection_memento); @@ -2138,43 +2110,73 @@ Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items) edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu)); } -SnapType -Editor::snap_type() const +GridType +Editor::grid_type() const { - return _snap_type; + return _grid_type; } bool -Editor::snap_musical() const -{ - switch (_snap_type) { - case SnapToBeatDiv128: - case SnapToBeatDiv64: - case SnapToBeatDiv32: - case SnapToBeatDiv28: - case SnapToBeatDiv24: - case SnapToBeatDiv20: - case SnapToBeatDiv16: - case SnapToBeatDiv14: - case SnapToBeatDiv12: - case SnapToBeatDiv10: - case SnapToBeatDiv8: - case SnapToBeatDiv7: - case SnapToBeatDiv6: - case SnapToBeatDiv5: - case SnapToBeatDiv4: - case SnapToBeatDiv3: - case SnapToBeatDiv2: - case SnapToBeat: - case SnapToBar: +Editor::grid_musical() const +{ + switch (_grid_type) { + case GridTypeBeatDiv32: + case GridTypeBeatDiv28: + case GridTypeBeatDiv24: + case GridTypeBeatDiv20: + case GridTypeBeatDiv16: + case GridTypeBeatDiv14: + case GridTypeBeatDiv12: + case GridTypeBeatDiv10: + case GridTypeBeatDiv8: + case GridTypeBeatDiv7: + case GridTypeBeatDiv6: + case GridTypeBeatDiv5: + case GridTypeBeatDiv4: + case GridTypeBeatDiv3: + case GridTypeBeatDiv2: + case GridTypeBeat: + case GridTypeBar: return true; - default: - break; + case GridTypeNone: + case GridTypeSmpte: + case GridTypeMinSec: + case GridTypeSamples: + return false; } - return false; } +bool +Editor::grid_nonmusical() const +{ + switch (_grid_type) { + case GridTypeSmpte: + case GridTypeMinSec: + case GridTypeSamples: + return true; + case GridTypeBeatDiv32: + case GridTypeBeatDiv28: + case GridTypeBeatDiv24: + case GridTypeBeatDiv20: + case GridTypeBeatDiv16: + case GridTypeBeatDiv14: + case GridTypeBeatDiv12: + case GridTypeBeatDiv10: + case GridTypeBeatDiv8: + case GridTypeBeatDiv7: + case GridTypeBeatDiv6: + case GridTypeBeatDiv5: + case GridTypeBeatDiv4: + case GridTypeBeatDiv3: + case GridTypeBeatDiv2: + case GridTypeBeat: + case GridTypeBar: + case GridTypeNone: + return false; + } + return false; +} SnapMode Editor::snap_mode() const { @@ -2182,67 +2184,79 @@ Editor::snap_mode() const } void -Editor::set_snap_to (SnapType st) +Editor::set_grid_to (GridType gt) { - unsigned int snap_ind = (unsigned int)st; + if (_grid_type == gt) { //already set + return; + } + + unsigned int grid_ind = (unsigned int)gt; if (internal_editing()) { - internal_snap_type = st; + internal_grid_type = gt; } else { - pre_internal_snap_type = st; + pre_internal_grid_type = gt; } - _snap_type = st; + _grid_type = gt; - if (snap_ind > snap_type_strings.size() - 1) { - snap_ind = 0; - _snap_type = (SnapType)snap_ind; + if (grid_ind > grid_type_strings.size() - 1) { + grid_ind = 0; + _grid_type = (GridType)grid_ind; } - string str = snap_type_strings[snap_ind]; + string str = grid_type_strings[grid_ind]; - if (str != snap_type_selector.get_text()) { - snap_type_selector.set_text (str); + if (str != grid_type_selector.get_text()) { + grid_type_selector.set_text (str); + } + + //show appropriate rulers for this grid setting. (ToDo: perhaps make this optional) + //Currently this is 'required' because the RULER calculates the grid_marks which will be used by grid_lines + if ( grid_musical() ) { + ruler_tempo_action->set_active(true); + ruler_meter_action->set_active(true); + + ruler_bbt_action->set_active(true); + ruler_timecode_action->set_active(false); + ruler_minsec_action->set_active(false); + ruler_samples_action->set_active(false); + } else if (_grid_type == GridTypeSmpte ) { + ruler_tempo_action->set_active(false); + ruler_meter_action->set_active(false); + + ruler_bbt_action->set_active(false); + ruler_timecode_action->set_active(true); + ruler_minsec_action->set_active(false); + ruler_samples_action->set_active(false); + } else if (_grid_type == GridTypeMinSec ) { + ruler_tempo_action->set_active(false); + ruler_meter_action->set_active(false); + + ruler_bbt_action->set_active(false); + ruler_timecode_action->set_active(false); + ruler_minsec_action->set_active(true); + ruler_samples_action->set_active(false); + } else if (_grid_type == GridTypeSamples ) { + ruler_tempo_action->set_active(false); + ruler_meter_action->set_active(false); + + ruler_bbt_action->set_active(false); + ruler_timecode_action->set_active(false); + ruler_minsec_action->set_active(false); + ruler_samples_action->set_active(true); } instant_save (); - switch (_snap_type) { - case SnapToBeatDiv128: - case SnapToBeatDiv64: - case SnapToBeatDiv32: - case SnapToBeatDiv28: - case SnapToBeatDiv24: - case SnapToBeatDiv20: - case SnapToBeatDiv16: - case SnapToBeatDiv14: - case SnapToBeatDiv12: - case SnapToBeatDiv10: - case SnapToBeatDiv8: - case SnapToBeatDiv7: - case SnapToBeatDiv6: - case SnapToBeatDiv5: - case SnapToBeatDiv4: - case SnapToBeatDiv3: - case SnapToBeatDiv2: { + if ( grid_musical() ) { compute_bbt_ruler_scale (_leftmost_sample, _leftmost_sample + current_page_samples()); update_tempo_based_rulers (); - break; } - case SnapToRegionStart: - case SnapToRegionEnd: - case SnapToRegionSync: - case SnapToRegionBoundary: - build_region_boundary_cache (); - break; - - default: - /* relax */ - break; - } + mark_region_boundary_cache_dirty (); - redisplay_tempo (false); + redisplay_grid (false); SnapChanged (); /* EMIT SIGNAL */ } @@ -2250,8 +2264,6 @@ Editor::set_snap_to (SnapType st) void Editor::set_snap_mode (SnapMode mode) { - string str = snap_mode_strings[(int)mode]; - if (internal_editing()) { internal_snap_mode = mode; } else { @@ -2259,9 +2271,11 @@ Editor::set_snap_mode (SnapMode mode) } _snap_mode = mode; - - if (str != snap_mode_selector.get_text ()) { - snap_mode_selector.set_text (str); + + if (_snap_mode == SnapOff ) { + snap_mode_button.set_active_state (Gtkmm2ext::Off); + } else { + snap_mode_button.set_active_state (Gtkmm2ext::ExplicitActive); } instant_save (); @@ -2292,7 +2306,6 @@ Editor::set_edit_point_preference (EditPoint ep, bool force) switch (_edit_point) { case EditAtPlayhead: -//ToDo: hide or show mouse_cursor action = "edit-at-playhead"; break; case EditAtSelectedMarker: @@ -2360,11 +2373,11 @@ Editor::set_state (const XMLNode& node, int version) set_visible_track_count (cnt); } - SnapType snap_type; - if (!node.get_property ("snap-to", snap_type)) { - snap_type = _snap_type; + GridType grid_type; + if (!node.get_property ("grid-type", grid_type)) { + grid_type = _grid_type; } - set_snap_to (snap_type); + set_grid_to (grid_type); SnapMode sm; if (node.get_property ("snap-mode", sm)) { @@ -2378,9 +2391,9 @@ Editor::set_state (const XMLNode& node, int version) set_snap_mode (_snap_mode); } - node.get_property ("internal-snap-to", internal_snap_type); + node.get_property ("internal-grid-type", internal_grid_type); node.get_property ("internal-snap-mode", internal_snap_mode); - node.get_property ("pre-internal-snap-to", pre_internal_snap_type); + node.get_property ("pre-internal-grid-type", pre_internal_grid_type); node.get_property ("pre-internal-snap-mode", pre_internal_snap_mode); std::string mm_str; @@ -2421,8 +2434,6 @@ Editor::set_state (const XMLNode& node, int version) set_edit_point_preference (_edit_point); } - node.get_property ("show-measures", _show_measures); - if (node.get_property ("follow-playhead", yn)) { set_follow_playhead (yn); } @@ -2508,15 +2519,6 @@ Editor::set_state (const XMLNode& node, int version) */ RefPtr<Action> act; - act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility")); - if (act) { - yn = _show_measures; - RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act); - /* do it twice to force the change */ - tact->set_active (!yn); - tact->set_active (yn); - } - act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead")); yn = _follow_playhead; if (act) { @@ -2557,11 +2559,11 @@ Editor::get_state () node->set_property ("zoom-focus", zoom_focus); node->set_property ("zoom", samples_per_pixel); - node->set_property ("snap-to", _snap_type); + node->set_property ("grid-type", _grid_type); node->set_property ("snap-mode", _snap_mode); - node->set_property ("internal-snap-to", internal_snap_type); + node->set_property ("internal-grid-type", internal_grid_type); node->set_property ("internal-snap-mode", internal_snap_mode); - node->set_property ("pre-internal-snap-to", pre_internal_snap_type); + node->set_property ("pre-internal-grid-type", pre_internal_grid_type); node->set_property ("pre-internal-snap-mode", pre_internal_snap_mode); node->set_property ("edit-point", _edit_point); node->set_property ("visible-track-count", _visible_track_count); @@ -2570,7 +2572,6 @@ Editor::get_state () node->set_property ("left-frame", _leftmost_sample); node->set_property ("y-origin", vertical_adjustment.get_value ()); - node->set_property ("show-measures", _show_measures); node->set_property ("maximised", _maximised); node->set_property ("follow-playhead", _follow_playhead); node->set_property ("stationary-playhead", _stationary_playhead); @@ -2658,7 +2659,7 @@ Editor::set_snapped_cursor_position (samplepos_t pos) * @param event Event to get current key modifier information from, or 0. */ void -Editor::snap_to_with_modifier (MusicSample& start, GdkEvent const * event, RoundMode direction, bool for_mark) +Editor::snap_to_with_modifier (MusicSample& start, GdkEvent const * event, RoundMode direction, SnapPref pref, bool for_mark) { if (!_session || !event) { return; @@ -2666,16 +2667,16 @@ Editor::snap_to_with_modifier (MusicSample& start, GdkEvent const * event, Round if (ArdourKeyboard::indicates_snap (event->button.state)) { if (_snap_mode == SnapOff) { - snap_to_internal (start, direction, for_mark); + snap_to_internal (start, direction, pref, for_mark); } else { start.set (start.sample, 0); } } else { if (_snap_mode != SnapOff) { - snap_to_internal (start, direction, for_mark); + snap_to_internal (start, direction, pref, for_mark); } else if (ArdourKeyboard::indicates_snap_delta (event->button.state)) { /* SnapOff, but we pressed the snap_delta modifier */ - snap_to_internal (start, direction, for_mark); + snap_to_internal (start, direction, pref, for_mark); } else { start.set (start.sample, 0); } @@ -2683,249 +2684,142 @@ Editor::snap_to_with_modifier (MusicSample& start, GdkEvent const * event, Round } void -Editor::snap_to (MusicSample& start, RoundMode direction, bool for_mark, bool ensure_snap) +Editor::snap_to (MusicSample& start, RoundMode direction, SnapPref pref, bool for_mark, bool ensure_snap) { if (!_session || (_snap_mode == SnapOff && !ensure_snap)) { start.set (start.sample, 0); return; } - snap_to_internal (start, direction, for_mark, ensure_snap); + snap_to_internal (start, direction, pref, for_mark, ensure_snap); } void -Editor::timecode_snap_to_internal (MusicSample& pos, RoundMode direction, bool /*for_mark*/) +check_best_snap ( samplepos_t presnap, samplepos_t &test, samplepos_t &dist, samplepos_t &best ) { - samplepos_t start = pos.sample; - const samplepos_t one_timecode_second = (samplepos_t)(rint(_session->timecode_frames_per_second()) * _session->samples_per_timecode_frame()); - samplepos_t one_timecode_minute = (samplepos_t)(rint(_session->timecode_frames_per_second()) * _session->samples_per_timecode_frame() * 60); - - switch (_snap_type) { - case SnapToTimecodeFrame: - if ((direction == RoundUpMaybe || direction == RoundDownMaybe) && - fmod((double)start, (double)_session->samples_per_timecode_frame()) == 0) { - /* start is already on a whole timecode frame, do nothing */ - } else if (((direction == 0) && (fmod((double)start, (double)_session->samples_per_timecode_frame()) > (_session->samples_per_timecode_frame() / 2))) || (direction > 0)) { - start = (samplepos_t) (ceil ((double) start / _session->samples_per_timecode_frame()) * _session->samples_per_timecode_frame()); - } else { - start = (samplepos_t) (floor ((double) start / _session->samples_per_timecode_frame()) * _session->samples_per_timecode_frame()); - } - break; - - case SnapToTimecodeSeconds: - if (_session->config.get_timecode_offset_negative()) { - start += _session->config.get_timecode_offset (); - } else { - start -= _session->config.get_timecode_offset (); - } - 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 = (samplepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second; - } else { - start = (samplepos_t) floor ((double) start / one_timecode_second) * one_timecode_second; - } - - if (_session->config.get_timecode_offset_negative()) { - start -= _session->config.get_timecode_offset (); - } else { - start += _session->config.get_timecode_offset (); - } - break; - - case SnapToTimecodeMinutes: - if (_session->config.get_timecode_offset_negative()) { - start += _session->config.get_timecode_offset (); - } else { - start -= _session->config.get_timecode_offset (); - } - 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 = (samplepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute; - } else { - start = (samplepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute; - } - if (_session->config.get_timecode_offset_negative()) { - start -= _session->config.get_timecode_offset (); - } else { - start += _session->config.get_timecode_offset (); - } - break; - default: - fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg; - abort(); /*NOTREACHED*/ + samplepos_t diff = abs( test - presnap ); + if ( diff < dist ) { + dist = diff; + best = test; } - pos.set (start, 0); + test = max_samplepos; //reset this so it doesn't get accidentally reused } -void -Editor::snap_to_internal (MusicSample& start, RoundMode direction, bool for_mark, bool ensure_snap) +samplepos_t +Editor::snap_to_grid (vector<ArdourCanvas::Ruler::Mark> marks, samplepos_t presnap, RoundMode direction) { - const samplepos_t one_second = _session->sample_rate(); - const samplepos_t one_minute = _session->sample_rate() * 60; - samplepos_t presnap = start.sample; samplepos_t before; samplepos_t after; + samplepos_t test; - int snap_threshold_s = pixel_to_sample(UIConfiguration::instance().get_snap_threshold()); - - switch (_snap_type) { - case SnapToTimecodeFrame: - case SnapToTimecodeSeconds: - case SnapToTimecodeMinutes: - return timecode_snap_to_internal (start, direction, for_mark); - - case SnapToCDFrame: - if ((direction == RoundUpMaybe || direction == RoundDownMaybe) && - start.sample % (one_second/75) == 0) { - /* start is already on a whole CD sample, do nothing */ - } else if (((direction == 0) && (start.sample % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) { - start.sample = (samplepos_t) ceil ((double) start.sample / (one_second / 75)) * (one_second / 75); - } else { - start.sample = (samplepos_t) floor ((double) start.sample / (one_second / 75)) * (one_second / 75); - } - - start.set (start.sample, 0); + before = after = max_samplepos; - break; + //get marks to either side of presnap + vector<ArdourCanvas::Ruler::Mark>::const_iterator m = marks.begin(); + while ( m != marks.end() && (m->position < presnap) ) { + ++m; + } - case SnapToSeconds: - if ((direction == RoundUpMaybe || direction == RoundDownMaybe) && - start.sample % one_second == 0) { - /* start is already on a whole second, do nothing */ - } else if (((direction == 0) && (start.sample % one_second > one_second / 2)) || (direction > 0)) { - start.sample = (samplepos_t) ceil ((double) start.sample / one_second) * one_second; - } else { - start.sample = (samplepos_t) floor ((double) start.sample / one_second) * one_second; - } + if (m == marks.end ()) { + /* ran out of marks */ + before = grid_marks.back().position; + } - start.set (start.sample, 0); + after = m->position; - break; + if (m != marks.begin ()) { + --m; + before = m->position; + } - case SnapToMinutes: - if ((direction == RoundUpMaybe || direction == RoundDownMaybe) && - start.sample % one_minute == 0) { - /* start is already on a whole minute, do nothing */ - } else if (((direction == 0) && (start.sample % one_minute > one_minute / 2)) || (direction > 0)) { - start.sample = (samplepos_t) ceil ((double) start.sample / one_minute) * one_minute; - } else { - start.sample = (samplepos_t) floor ((double) start.sample / one_minute) * one_minute; + if (before == max_samplepos && after == max_samplepos) { + /* No smpte to snap to, so just don't snap */ + return presnap; + } else if (before == max_samplepos) { + test = after; + } else if (after == max_samplepos) { + test = before; + } else { + if ((direction == RoundUpMaybe || direction == RoundUpAlways)) + test = after; + else if ((direction == RoundDownMaybe || direction == RoundDownAlways)) + test = before; + else if (direction == 0 ) { + if ((presnap - before) < (after - presnap)) { + test = before; + } else { + test = after; + } } + } - start.set (start.sample, 0); + return test; +} - break; +samplepos_t +Editor::marker_snap_to_internal (samplepos_t presnap, RoundMode direction) +{ + samplepos_t before; + samplepos_t after; + samplepos_t test; + + _session->locations()->marks_either_side (presnap, before, after); + + if (before == max_samplepos && after == max_samplepos) { + /* No marks to snap to, so just don't snap */ + return presnap; + } else if (before == max_samplepos) { + test = after; + } else if (after == max_samplepos) { + test = before; + } else { + if ((direction == RoundUpMaybe || direction == RoundUpAlways)) { + test = after; + } else if ((direction == RoundDownMaybe || direction == RoundDownAlways)) { + test = before; + } else if (direction == 0 ) { + if ((presnap - before) < (after - presnap)) { + test = before; + } else { + test = after; + } + } + } - case SnapToBar: - start = _session->tempo_map().round_to_bar (start.sample, direction); - break; + return test; +} - case SnapToBeat: - start = _session->tempo_map().round_to_beat (start.sample, direction); - break; +void +Editor::snap_to_internal (MusicSample& start, RoundMode direction, SnapPref pref, bool for_mark, bool ensure_snap) +{ + const samplepos_t presnap = start.sample; - case SnapToBeatDiv128: - start = _session->tempo_map().round_to_quarter_note_subdivision (start.sample, 128, direction); - break; - case SnapToBeatDiv64: - start = _session->tempo_map().round_to_quarter_note_subdivision (start.sample, 64, direction); - break; - case SnapToBeatDiv32: - start = _session->tempo_map().round_to_quarter_note_subdivision (start.sample, 32, direction); - break; - case SnapToBeatDiv28: - start = _session->tempo_map().round_to_quarter_note_subdivision (start.sample, 28, direction); - break; - case SnapToBeatDiv24: - start = _session->tempo_map().round_to_quarter_note_subdivision (start.sample, 24, direction); - break; - case SnapToBeatDiv20: - start = _session->tempo_map().round_to_quarter_note_subdivision (start.sample, 20, direction); - break; - case SnapToBeatDiv16: - start = _session->tempo_map().round_to_quarter_note_subdivision (start.sample, 16, direction); - break; - case SnapToBeatDiv14: - start = _session->tempo_map().round_to_quarter_note_subdivision (start.sample, 14, direction); - break; - case SnapToBeatDiv12: - start = _session->tempo_map().round_to_quarter_note_subdivision (start.sample, 12, direction); - break; - case SnapToBeatDiv10: - start = _session->tempo_map().round_to_quarter_note_subdivision (start.sample, 10, direction); - break; - case SnapToBeatDiv8: - start = _session->tempo_map().round_to_quarter_note_subdivision (start.sample, 8, direction); - break; - case SnapToBeatDiv7: - start = _session->tempo_map().round_to_quarter_note_subdivision (start.sample, 7, direction); - break; - case SnapToBeatDiv6: - start = _session->tempo_map().round_to_quarter_note_subdivision (start.sample, 6, direction); - break; - case SnapToBeatDiv5: - start = _session->tempo_map().round_to_quarter_note_subdivision (start.sample, 5, direction); - break; - case SnapToBeatDiv4: - start = _session->tempo_map().round_to_quarter_note_subdivision (start.sample, 4, direction); - break; - case SnapToBeatDiv3: - start = _session->tempo_map().round_to_quarter_note_subdivision (start.sample, 3, direction); - break; - case SnapToBeatDiv2: - start = _session->tempo_map().round_to_quarter_note_subdivision (start.sample, 2, direction); - break; + samplepos_t test = max_samplepos; //for each snap, we'll use this value + samplepos_t dist = max_samplepos; //this records the distance of the best snap result we've found so far + samplepos_t best = max_samplepos; //this records the best snap-result we've found so far - case SnapToMark: + //check snap-to-marker + if ( UIConfiguration::instance().get_snap_to_marks() ) { if (for_mark) { return; } - _session->locations()->marks_either_side (start.sample, before, after); - - if (before == max_samplepos && after == max_samplepos) { - /* No marks to snap to, so just don't snap */ - return; - } else if (before == max_samplepos) { - start.sample = after; - } else if (after == max_samplepos) { - start.sample = before; - } else if (before != max_samplepos && after != max_samplepos) { - if ((direction == RoundUpMaybe || direction == RoundUpAlways)) - start.sample = after; - else if ((direction == RoundDownMaybe || direction == RoundDownAlways)) - start.sample = before; - else if (direction == 0 ) { - if ((start.sample - before) < (after - start.sample)) { - start.sample = before; - } else { - start.sample = after; - } - } - } - - start.set (start.sample, 0); - - break; + test = marker_snap_to_internal ( presnap, direction ); + check_best_snap(presnap, test, dist, best); + } - case SnapToRegionStart: - case SnapToRegionEnd: - case SnapToRegionSync: - case SnapToRegionBoundary: + //check snap-to-region-{start/end/sync} + if ( UIConfiguration::instance().get_snap_to_region_start() || UIConfiguration::instance().get_snap_to_region_end() || UIConfiguration::instance().get_snap_to_region_sync() ) { if (!region_boundary_cache.empty()) { vector<samplepos_t>::iterator prev = region_boundary_cache.end (); vector<samplepos_t>::iterator next = region_boundary_cache.end (); if (direction > 0) { - next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start.sample); + next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), presnap); } else { - next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start.sample); + next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), presnap); } if (next != region_boundary_cache.begin ()) { @@ -2936,43 +2830,45 @@ Editor::snap_to_internal (MusicSample& start, RoundMode direction, bool for_mark samplepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev; samplepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next; - if (start.sample > (p + n) / 2) { - start.sample = n; + if (presnap > (p + n) / 2) { + test = n; } else { - start.sample = p; + test = p; } } - start.set (start.sample, 0); - - break; + check_best_snap(presnap, test, dist, best); } - switch (_snap_mode) { - case SnapNormal: - return; + //check Grid + if (UIConfiguration::instance().get_snap_to_grid() && (_grid_type != GridTypeNone) ) { - case SnapMagnetic: - - if (ensure_snap) { - return; - } - - if (presnap > start.sample) { - if (presnap > (start.sample + snap_threshold_s)) { - start.set (presnap, 0); - } + //if SnapToGrid is selected, the user wants to prioritize the music grid + //in this case we should reset the best distance, so Grid will prevail + dist = max_samplepos; - } else if (presnap < start.sample) { - if (presnap < (start.sample - snap_threshold_s)) { - start.set (presnap, 0); - } - } + test = snap_to_grid (grid_marks, presnap, direction); + check_best_snap(presnap, test, dist, best); + } - default: - /* handled at entry */ + //now check "magnetic" state: is the grid within reasonable on-screen distance to trigger a snap? + //this also helps to avoid snapping to somewhere the user can't see. ( i.e.: I clicked on a region and it disappeared!! ) + //ToDo: perhaps this should only occur if EditPointMouse? + int snap_threshold_s = pixel_to_sample(UIConfiguration::instance().get_snap_threshold()); + if (ensure_snap) { + start.set (best, 0); return; + } else if (presnap > best) { + if (presnap > (best+ snap_threshold_s)) { + best = presnap; + } + } else if (presnap < best) { + if (presnap < (best - snap_threshold_s)) { + best = presnap; + } } + + start.set (best, 0); } @@ -3010,8 +2906,8 @@ Editor::setup_toolbar () mouse_mode_size_group->add_widget (visible_tracks_selector); } - mouse_mode_size_group->add_widget (snap_type_selector); - mouse_mode_size_group->add_widget (snap_mode_selector); + mouse_mode_size_group->add_widget (grid_type_selector); + mouse_mode_size_group->add_widget (snap_mode_button); mouse_mode_size_group->add_widget (edit_point_selector); mouse_mode_size_group->add_widget (edit_mode_selector); @@ -3129,14 +3025,14 @@ Editor::setup_toolbar () snap_box.set_spacing (2); snap_box.set_border_width (2); - snap_type_selector.set_name ("mouse mode button"); + grid_type_selector.set_name ("mouse mode button"); - snap_mode_selector.set_name ("mouse mode button"); + snap_mode_button.set_name ("mouse mode button"); edit_point_selector.set_name ("mouse mode button"); - snap_box.pack_start (snap_mode_selector, false, false); - snap_box.pack_start (snap_type_selector, false, false); + snap_box.pack_start (snap_mode_button, false, false); + snap_box.pack_start (grid_type_selector, false, false); /* Edit Point*/ HBox *ep_box = manage (new HBox); @@ -3219,55 +3115,58 @@ Editor::build_edit_mode_menu () } void -Editor::build_snap_mode_menu () +Editor::build_grid_type_menu () { using namespace Menu_Helpers; - snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff))); - snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal))); - snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic))); + //main grid: bars, quarter-notes, etc + grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeNone], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeNone))); + grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeBar], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBar))); + grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeBeat], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeat))); + grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv2))); + grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv4))); + grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv8))); + grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv16))); + grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv32))); + + //triplet grid + grid_type_selector.AddMenuElem(SeparatorElem()); + Gtk::Menu *_triplet_menu = manage (new Menu); + MenuList& triplet_items (_triplet_menu->items()); + { + triplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv3) )); + triplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv6) )); + triplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv12) )); + triplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv24) )); + } + grid_type_selector.AddMenuElem (Menu_Helpers::MenuElem (_("Triplets"), *_triplet_menu)); - set_size_request_to_display_given_text (snap_mode_selector, snap_mode_strings, COMBO_TRIANGLE_WIDTH, 2); -} + //quintuplet grid + Gtk::Menu *_quintuplet_menu = manage (new Menu); + MenuList& quintuplet_items (_quintuplet_menu->items()); + { + quintuplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv5) )); + quintuplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv10) )); + quintuplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv20) )); + } + grid_type_selector.AddMenuElem (Menu_Helpers::MenuElem (_("Quintuplets"), *_quintuplet_menu)); -void -Editor::build_snap_type_menu () -{ - using namespace Menu_Helpers; + //septuplet grid + Gtk::Menu *_septuplet_menu = manage (new Menu); + MenuList& septuplet_items (_septuplet_menu->items()); + { + septuplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv7) )); + septuplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv14) )); + septuplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv28) )); + } + grid_type_selector.AddMenuElem (Menu_Helpers::MenuElem (_("Septuplets"), *_septuplet_menu)); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToCDFrame))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeFrame))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeSeconds))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeMinutes))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToSeconds))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMinutes))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv128], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv128))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv64], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv64))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv32))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv28))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv24))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv20))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv16))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv14))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv12))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv10))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv8))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv7))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv6))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv5))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv4))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv3))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv2))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeat], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeat))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBar], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBar))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMark], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMark))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionStart], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionStart))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync))); - snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary))); - - set_size_request_to_display_given_text (snap_type_selector, snap_type_strings, COMBO_TRIANGLE_WIDTH, 2); + grid_type_selector.AddMenuElem(SeparatorElem()); + grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeSmpte], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeSmpte))); + grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeMinSec], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeMinSec))); + grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeSamples], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeSamples))); + set_size_request_to_display_given_text (grid_type_selector, "No Grid", COMBO_TRIANGLE_WIDTH, 2); } void @@ -3292,8 +3191,8 @@ Editor::setup_tooltips () set_tooltip (tav_expand_button, _("Expand Tracks")); set_tooltip (tav_shrink_button, _("Shrink Tracks")); set_tooltip (visible_tracks_selector, _("Number of visible tracks")); - set_tooltip (snap_type_selector, _("Snap/Grid Units")); - set_tooltip (snap_mode_selector, _("Snap/Grid Mode")); + set_tooltip (grid_type_selector, _("Grid Mode")); + set_tooltip (snap_mode_button, _("Snap Mode\n\nRight-click to visit Snap preferences.")); set_tooltip (edit_point_selector, _("Edit Point")); set_tooltip (edit_mode_selector, _("Edit Mode")); set_tooltip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)")); @@ -3644,7 +3543,7 @@ Editor::duplicate_range (bool with_dialog) times = adjustment.get_value(); } - if ((current_mouse_mode() == Editing::MouseRange)) { + if ((current_mouse_mode() == MouseRange)) { if (selection->time.length()) { duplicate_selection (times); } @@ -3688,9 +3587,9 @@ Editor::edit_mode_selection_done ( EditMode m ) } void -Editor::snap_type_selection_done (SnapType snaptype) +Editor::grid_type_selection_done (GridType gridtype) { - RefPtr<RadioAction> ract = snap_type_action (snaptype); + RefPtr<RadioAction> ract = grid_type_action (gridtype); if (ract) { ract->set_active (); } @@ -3949,22 +3848,18 @@ Editor::cycle_zoom_focus () } void -Editor::set_show_measures (bool yn) +Editor::update_grid () { - if (_show_measures != yn) { - hide_measures (); - - if ((_show_measures = yn) == true) { - if (tempo_lines) { - tempo_lines->show(); - } - - std::vector<TempoMap::BBTPoint> grid; + if ( grid_musical() ) { + std::vector<TempoMap::BBTPoint> grid; + if (bbt_ruler_scale != bbt_show_many) { compute_current_bbt_points (grid, _leftmost_sample, _leftmost_sample + current_page_samples()); - draw_measures (grid); } - - instant_save (); + maybe_draw_grid_lines (); + } else if ( grid_nonmusical() ) { + maybe_draw_grid_lines (); + } else { + hide_grid_lines (); } } @@ -4044,25 +3939,28 @@ Editor::get_paste_offset (samplepos_t pos, unsigned paste_count, samplecnt_t dur unsigned Editor::get_grid_beat_divisions(samplepos_t position) { - switch (_snap_type) { - case SnapToBeatDiv128: return 128; - case SnapToBeatDiv64: return 64; - case SnapToBeatDiv32: return 32; - case SnapToBeatDiv28: return 28; - case SnapToBeatDiv24: return 24; - case SnapToBeatDiv20: return 20; - case SnapToBeatDiv16: return 16; - case SnapToBeatDiv14: return 14; - case SnapToBeatDiv12: return 12; - case SnapToBeatDiv10: return 10; - case SnapToBeatDiv8: return 8; - case SnapToBeatDiv7: return 7; - case SnapToBeatDiv6: return 6; - case SnapToBeatDiv5: return 5; - case SnapToBeatDiv4: return 4; - case SnapToBeatDiv3: return 3; - case SnapToBeatDiv2: return 2; - default: return 0; + switch (_grid_type) { + case GridTypeBeatDiv32: return 32; + case GridTypeBeatDiv28: return 28; + case GridTypeBeatDiv24: return 24; + case GridTypeBeatDiv20: return 20; + case GridTypeBeatDiv16: return 16; + case GridTypeBeatDiv14: return 14; + case GridTypeBeatDiv12: return 12; + case GridTypeBeatDiv10: return 10; + case GridTypeBeatDiv8: return 8; + case GridTypeBeatDiv7: return 7; + case GridTypeBeatDiv6: return 6; + case GridTypeBeatDiv5: return 5; + case GridTypeBeatDiv4: return 4; + case GridTypeBeatDiv3: return 3; + case GridTypeBeatDiv2: return 2; + + case GridTypeNone: return 0; + case GridTypeSmpte: return 0; + case GridTypeMinSec: return 0; + case GridTypeSamples: return 0; + default: return 0; } return 0; } @@ -4075,35 +3973,37 @@ Editor::get_grid_beat_divisions(samplepos_t position) int32_t Editor::get_grid_music_divisions (uint32_t event_state) { - if (snap_mode() == Editing::SnapOff && !ArdourKeyboard::indicates_snap (event_state)) { + if (snap_mode() == SnapOff && !ArdourKeyboard::indicates_snap (event_state)) { return 0; } - if (snap_mode() != Editing::SnapOff && ArdourKeyboard::indicates_snap (event_state)) { + if (snap_mode() != SnapOff && ArdourKeyboard::indicates_snap (event_state)) { return 0; } - switch (_snap_type) { - case SnapToBeatDiv128: return 128; - case SnapToBeatDiv64: return 64; - case SnapToBeatDiv32: return 32; - case SnapToBeatDiv28: return 28; - case SnapToBeatDiv24: return 24; - case SnapToBeatDiv20: return 20; - case SnapToBeatDiv16: return 16; - case SnapToBeatDiv14: return 14; - case SnapToBeatDiv12: return 12; - case SnapToBeatDiv10: return 10; - case SnapToBeatDiv8: return 8; - case SnapToBeatDiv7: return 7; - case SnapToBeatDiv6: return 6; - case SnapToBeatDiv5: return 5; - case SnapToBeatDiv4: return 4; - case SnapToBeatDiv3: return 3; - case SnapToBeatDiv2: return 2; - case SnapToBeat: return 1; - case SnapToBar : return -1; - default: return 0; + switch (_grid_type) { + case GridTypeBeatDiv32: return 32; + case GridTypeBeatDiv28: return 28; + case GridTypeBeatDiv24: return 24; + case GridTypeBeatDiv20: return 20; + case GridTypeBeatDiv16: return 16; + case GridTypeBeatDiv14: return 14; + case GridTypeBeatDiv12: return 12; + case GridTypeBeatDiv10: return 10; + case GridTypeBeatDiv8: return 8; + case GridTypeBeatDiv7: return 7; + case GridTypeBeatDiv6: return 6; + case GridTypeBeatDiv5: return 5; + case GridTypeBeatDiv4: return 4; + case GridTypeBeatDiv3: return 3; + case GridTypeBeatDiv2: return 2; + case GridTypeBeat: return 1; + case GridTypeBar : return -1; + + case GridTypeNone: return 0; + case GridTypeSmpte: return 0; + case GridTypeMinSec: return 0; + case GridTypeSamples: return 0; } return 0; } @@ -4118,10 +4018,10 @@ Editor::get_grid_type_as_beats (bool& success, samplepos_t position) return Temporal::Beats(1.0 / (double)get_grid_beat_divisions(position)); } - switch (_snap_type) { - case SnapToBeat: + switch (_grid_type) { + case GridTypeBeat: return Temporal::Beats(4.0 / _session->tempo_map().meter_at_sample (position).note_divisor()); - case SnapToBar: + case GridTypeBar: if (_session) { const Meter& m = _session->tempo_map().meter_at_sample (position); return Temporal::Beats((4.0 * m.divisions_per_bar()) / m.note_divisor()); @@ -4534,10 +4434,6 @@ Editor::set_samples_per_pixel (samplecnt_t spp) void Editor::on_samples_per_pixel_changed () { - if (tempo_lines) { - tempo_lines->tempo_map_changed(_session->tempo_map().music_origin()); - } - bool const showing_time_selection = selection->time.length() > 0; if (showing_time_selection && selection->time.start () != selection->time.end_sample ()) { @@ -4691,7 +4587,7 @@ Editor::visual_changer (const VisualChange& vc) // If we are only scrolling vertically there is no need to update these if (vc.pending != VisualChange::YOrigin) { update_fixed_rulers (); - redisplay_tempo (true); + redisplay_grid (true); /* video frames & position need to be updated for zoom, horiz-scroll * and (explicitly) VisualChange::VideoTimeline. @@ -5278,12 +5174,16 @@ Editor::region_view_added (RegionView * rv) } _summary->set_background_dirty (); + + mark_region_boundary_cache_dirty (); } void Editor::region_view_removed () { _summary->set_background_dirty (); + + mark_region_boundary_cache_dirty (); } AxisView* @@ -5853,7 +5753,7 @@ Editor::super_rapid_screen_update () } else { _last_update_time = now; } - + //snapped cursor stuff ( the snapped_cursor shows where an operation is going to occur ) bool ignored; MusicSample where (sample, 0); @@ -5875,7 +5775,7 @@ Editor::super_rapid_screen_update () } else { //mouse is out of the editing canvas. hide the snapped_cursor snapped_cursor->hide (); } - + /* There are a few reasons why we might not update the playhead / viewport stuff: * * 1. we don't update things when there's a pending locate request, otherwise @@ -5989,11 +5889,11 @@ Editor::session_going_away () /* clear tempo/meter rulers */ remove_metric_marks (); - hide_measures (); clear_marker_display (); - delete tempo_lines; - tempo_lines = 0; + hide_grid_lines (); + delete grid_lines; + grid_lines = 0; stop_step_editing (); |