summaryrefslogtreecommitdiff
path: root/gtk2_ardour/editor.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gtk2_ardour/editor.cc')
-rw-r--r--gtk2_ardour/editor.cc918
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 ();