diff options
Diffstat (limited to 'gtk2_ardour')
31 files changed, 959 insertions, 1365 deletions
diff --git a/gtk2_ardour/ardour.keys.in b/gtk2_ardour/ardour.keys.in index 7456ea2339..62aea52b30 100644 --- a/gtk2_ardour/ardour.keys.in +++ b/gtk2_ardour/ardour.keys.in @@ -341,11 +341,9 @@ This mode provides many different operations on both regions and control points, ;; numbers @vis|Editor/cycle-zoom-focus|1|cycle to next zoom focus -@grid|Editor/cycle-snap-mode|2|cycle to next grid snap mode -@grid|Editor/prev-snap-choice|3|use next grid unit -@grid|Editor/prev-snap-choice-music-only|<@PRIMARY@>3|use previous grid unit -@grid|Editor/next-snap-choice|4|use next grid unit -@grid|Editor/next-snap-choice-music-only|<@PRIMARY@>4|use next musical grid unit +@grid|Editor/cycle-snap-mode|2|cycle to next snap mode +@grid|Editor/prev-grid-choice|3|use prev grid unit +@grid|Editor/next-grid-choice|4|use next grid unit @gmode|Transport/ToggleAutoPlay|5|toggle auto play @gmode|Transport/ToggleAutoReturn|6|toggle auto return @gmode|Transport/ToggleClick|7|toggle click (metronome) diff --git a/gtk2_ardour/ardour.menus.in b/gtk2_ardour/ardour.menus.in index dd6ba9c8e8..03d9d2a663 100644 --- a/gtk2_ardour/ardour.menus.in +++ b/gtk2_ardour/ardour.menus.in @@ -232,48 +232,29 @@ <menuitem action='cycle-edit-point'/> <menuitem action='cycle-edit-point-with-marker'/> </menu> - <menu name='SnapMode' action='SnapMode'> - <menuitem action='snap-off'/> - <menuitem action='snap-normal'/> - <menuitem action='snap-magnetic'/> + <menuitem action='cycle-snap-mode'/> + <menu name='GridChoice' action='GridChoice'> + <menuitem action='prev-grid-choice'/> + <menuitem action='next-grid-choice'/> <separator/> - <menuitem action='cycle-snap-mode'/> - <menuitem action='next-snap-choice'/> - <menuitem action='prev-snap-choice'/> - <menuitem action='next-snap-choice-music-only'/> - <menuitem action='prev-snap-choice-music-only'/> - </menu> - <menu name='SnapTo' action='SnapTo'> - <menuitem action='snap-to-cd-frame'/> - <menuitem action='snap-to-timecode-frame'/> - <menuitem action='snap-to-timecode-seconds'/> - <menuitem action='snap-to-timecode-minutes'/> - <menuitem action='snap-to-seconds'/> - <menuitem action='snap-to-minutes'/> - <menuitem action='snap-to-onetwentyeighths'/> - <menuitem action='snap-to-sixtyfourths'/> - <menuitem action='snap-to-thirtyseconds'/> - <menuitem action='snap-to-twentyeighths'/> - <menuitem action='snap-to-twentyfourths'/> - <menuitem action='snap-to-twentieths'/> - <menuitem action='snap-to-asixteenthbeat'/> - <menuitem action='snap-to-fourteenths'/> - <menuitem action='snap-to-twelfths'/> - <menuitem action='snap-to-tenths'/> - <menuitem action='snap-to-eighths'/> - <menuitem action='snap-to-sevenths'/> - <menuitem action='snap-to-sixths'/> - <menuitem action='snap-to-fifths'/> - <menuitem action='snap-to-quarters'/> - <menuitem action='snap-to-thirds'/> - <menuitem action='snap-to-halves'/> - <menuitem action='snap-to-beat'/> - <menuitem action='snap-to-bar'/> - <menuitem action='snap-to-mark'/> - <menuitem action='snap-to-region-start'/> - <menuitem action='snap-to-region-end'/> - <menuitem action='snap-to-region-sync'/> - <menuitem action='snap-to-region-boundary'/> + <menuitem action='grid-type-none'/> + <menuitem action='grid-type-bar'/> + <menuitem action='grid-type-beat'/> + <menuitem action='grid-type-halves'/> + <menuitem action='grid-type-quarters'/> + <menuitem action='grid-type-eighths'/> + <menuitem action='grid-type-asixteenthbeat'/> + <menuitem action='grid-type-thirtyseconds'/> + <menuitem action='grid-type-thirds'/> + <menuitem action='grid-type-sixths'/> + <menuitem action='grid-type-twelfths'/> + <menuitem action='grid-type-twentyfourths'/> + <menuitem action='grid-type-fifths'/> + <menuitem action='grid-type-tenths'/> + <menuitem action='grid-type-twentieths'/> + <menuitem action='grid-type-sevenths'/> + <menuitem action='grid-type-fourteenths'/> + <menuitem action='grid-type-twentyeighths'/> </menu> <separator/> <menu action="TempoMenu"> @@ -532,7 +513,6 @@ <menuitem action='show-editor-list'/> <menuitem action='ToggleMixerList'/> <menuitem action='ToggleMonitorSection'/> - <menuitem action='ToggleMeasureVisibility'/> <menuitem action='ToggleSummary'/> <menuitem action='ToggleGroupTabs'/> <menuitem action='show-marker-lines'/> diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 3c61b74eef..37474b498f 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -1531,8 +1531,7 @@ ARDOUR_UI::every_second () void ARDOUR_UI::every_point_one_seconds () { - // TODO get rid of this.. - // ShuttleControl is updated directly via TransportStateChange signal + if (editor) editor->build_region_boundary_cache(); } void diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index c6984d75c4..bef477cbbb 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -200,6 +200,9 @@ public: bool get_smart_mode () const; + RCOptionEditor* get_rc_option_editor() { return rc_option_editor; } + void show_tabbable (ArdourWidgets::Tabbable*); + int get_session_parameters (bool quit_on_cancel, bool should_be_new = false, std::string load_template = ""); int build_session_from_dialog (SessionDialog&, const std::string& session_name, const std::string& session_path); bool ask_about_loading_existing_session (const std::string& session_path); @@ -392,7 +395,6 @@ private: bool _initial_verbose_plugin_scan; bool first_time_engine_run; - void show_tabbable (ArdourWidgets::Tabbable*); void hide_tabbable (ArdourWidgets::Tabbable*); void detach_tabbable (ArdourWidgets::Tabbable*); void attach_tabbable (ArdourWidgets::Tabbable*); diff --git a/gtk2_ardour/ardour_ui_options.cc b/gtk2_ardour/ardour_ui_options.cc index 21a1449f30..15d9d560c5 100644 --- a/gtk2_ardour/ardour_ui_options.cc +++ b/gtk2_ardour/ardour_ui_options.cc @@ -517,7 +517,10 @@ ARDOUR_UI::parameter_changed (std::string p) /* force a redraw */ gtk_rc_reset_styles (gtk_settings_get_default()); } + } else if ( (p == "snap-to-region-sync") || (p == "snap-to-region-start") || (p == "snap-to-region-end") ) { + if (editor) editor->mark_region_boundary_cache_dirty(); } + } void diff --git a/gtk2_ardour/editing.cc b/gtk2_ardour/editing.cc index 70a71ee082..b7f624e7ef 100644 --- a/gtk2_ardour/editing.cc +++ b/gtk2_ardour/editing.cc @@ -27,7 +27,7 @@ using namespace std; // This involves some cpp magic. --taybin -#define SNAPTYPE(a) /*empty*/ +#define GRIDTYPE(a) /*empty*/ #define SNAPMODE(a) /*empty*/ #define REGIONLISTSORTTYPE(a) /*empty*/ #define MOUSEMODE(a) /*empty*/ @@ -37,24 +37,24 @@ using namespace std; namespace Editing { -// SNAPTYPE -#undef SNAPTYPE -#define SNAPTYPE(s) if (!strcmp(type, #s)) {return s;} -SnapType -str2snaptype (const string & str) { +// GRIDTYPE +#undef GRIDTYPE +#define GRIDTYPE(s) if (!strcmp(type, #s)) {return s;} +GridType +str2gridtype (const string & str) { const char* type = str.c_str(); #include "editing_syms.h" - return SnapToBar; + return GridTypeBar; } -#undef SNAPTYPE -#define SNAPTYPE(s) N_(#s), -const char *snaptypestrs[] = { +#undef GRIDTYPE +#define GRIDTYPE(s) N_(#s), +const char *gridtypestrs[] = { #include "editing_syms.h" 0 }; -#undef SNAPTYPE -#define SNAPTYPE(a) /*empty*/ +#undef GRIDTYPE +#define GRIDTYPE(a) /*empty*/ // SNAPMODE #undef SNAPMODE @@ -63,7 +63,7 @@ SnapMode str2snapmode (const string & str) { const char* type = str.c_str(); #include "editing_syms.h" - return SnapNormal; + return SnapMagnetic; } #undef SNAPMODE diff --git a/gtk2_ardour/editing.h b/gtk2_ardour/editing.h index 5558f19460..1145e76b40 100644 --- a/gtk2_ardour/editing.h +++ b/gtk2_ardour/editing.h @@ -26,7 +26,7 @@ // This involves some cpp magic. --taybin -#define SNAPTYPE(a) /*empty*/ +#define GRIDTYPE(a) /*empty*/ #define SNAPMODE(a) /*empty*/ #define REGIONLISTSORTTYPE(a) /*empty*/ #define MOUSEMODE(a) /*empty*/ @@ -43,19 +43,19 @@ namespace Editing { -// SNAPTYPE -#undef SNAPTYPE -#define SNAPTYPE(a) a, -enum SnapType { +// GRIDTYPE +#undef GRIDTYPE +#define GRIDTYPE(a) a, +enum GridType { #include "editing_syms.h" }; -extern const char *snaptypestrs[]; -inline const char* enum2str(SnapType m) {return snaptypestrs[m];} -SnapType str2snaptype(const std::string &); +extern const char *gridtypestrs[]; +inline const char* enum2str(GridType m) {return gridtypestrs[m];} +GridType str2gridtype(const std::string &); -#undef SNAPTYPE -#define SNAPTYPE(a) /*empty*/ +#undef GRIDTYPE +#define GRIDTYPE(a) /*empty*/ // SNAPMODE #undef SNAPMODE diff --git a/gtk2_ardour/editing_convert.h b/gtk2_ardour/editing_convert.h index 02e899b2e9..e4205c2190 100644 --- a/gtk2_ardour/editing_convert.h +++ b/gtk2_ardour/editing_convert.h @@ -27,7 +27,7 @@ namespace PBD { DEFINE_ENUM_CONVERT(Editing::ZoomFocus) -DEFINE_ENUM_CONVERT(Editing::SnapType) +DEFINE_ENUM_CONVERT(Editing::GridType) DEFINE_ENUM_CONVERT(Editing::SnapMode) DEFINE_ENUM_CONVERT(Editing::EditPoint) DEFINE_ENUM_CONVERT(Editing::RegionListSortType) diff --git a/gtk2_ardour/editing_syms.h b/gtk2_ardour/editing_syms.h index 715202bfc9..2483f86da0 100644 --- a/gtk2_ardour/editing_syms.h +++ b/gtk2_ardour/editing_syms.h @@ -18,36 +18,28 @@ */ /* Changing this order will break the menu */ -SNAPTYPE(SnapToCDFrame) -SNAPTYPE(SnapToTimecodeFrame) -SNAPTYPE(SnapToTimecodeSeconds) -SNAPTYPE(SnapToTimecodeMinutes) -SNAPTYPE(SnapToSeconds) -SNAPTYPE(SnapToMinutes) -SNAPTYPE(SnapToBeatDiv128) -SNAPTYPE(SnapToBeatDiv64) -SNAPTYPE(SnapToBeatDiv32) -SNAPTYPE(SnapToBeatDiv28) -SNAPTYPE(SnapToBeatDiv24) -SNAPTYPE(SnapToBeatDiv20) -SNAPTYPE(SnapToBeatDiv16) -SNAPTYPE(SnapToBeatDiv14) -SNAPTYPE(SnapToBeatDiv12) -SNAPTYPE(SnapToBeatDiv10) -SNAPTYPE(SnapToBeatDiv8) -SNAPTYPE(SnapToBeatDiv7) -SNAPTYPE(SnapToBeatDiv6) -SNAPTYPE(SnapToBeatDiv5) -SNAPTYPE(SnapToBeatDiv4) -SNAPTYPE(SnapToBeatDiv3) -SNAPTYPE(SnapToBeatDiv2) -SNAPTYPE(SnapToBeat) -SNAPTYPE(SnapToBar) -SNAPTYPE(SnapToMark) -SNAPTYPE(SnapToRegionStart) -SNAPTYPE(SnapToRegionEnd) -SNAPTYPE(SnapToRegionSync) -SNAPTYPE(SnapToRegionBoundary) +GRIDTYPE(GridTypeNone) +GRIDTYPE(GridTypeBar) +GRIDTYPE(GridTypeBeat) +GRIDTYPE(GridTypeBeatDiv2) +GRIDTYPE(GridTypeBeatDiv4) +GRIDTYPE(GridTypeBeatDiv8) +GRIDTYPE(GridTypeBeatDiv16) +GRIDTYPE(GridTypeBeatDiv32) +GRIDTYPE(GridTypeBeatDiv3) //Triplet eighths +GRIDTYPE(GridTypeBeatDiv6) +GRIDTYPE(GridTypeBeatDiv12) +GRIDTYPE(GridTypeBeatDiv24) +GRIDTYPE(GridTypeBeatDiv5) //Quintuplet eighths +GRIDTYPE(GridTypeBeatDiv10) +GRIDTYPE(GridTypeBeatDiv20) +GRIDTYPE(GridTypeBeatDiv7) //Septuplet eighths +GRIDTYPE(GridTypeBeatDiv14) +GRIDTYPE(GridTypeBeatDiv28) +GRIDTYPE(GridTypeSmpte) +GRIDTYPE(GridTypeMinSec) +GRIDTYPE(GridTypeSamples) + /* Changing this order will break the menu */ SNAPMODE(SnapOff) 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 (); diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 5829927d1a..1d20fe5958 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -128,6 +128,7 @@ class RulerDialog; class Selection; class SoundFileOmega; class StreamView; +class GridLines; class TempoLines; class TimeAxisView; class TimeInfoBox; @@ -161,18 +162,15 @@ public: double trackviews_height () const; void cycle_snap_mode (); - void next_snap_choice (); - void next_snap_choice_music_only (); - void next_snap_choice_music_and_time (); - void prev_snap_choice (); - void prev_snap_choice_music_only (); - void prev_snap_choice_music_and_time (); - void set_snap_to (Editing::SnapType); + void next_grid_choice (); + void prev_grid_choice (); + void set_grid_to (Editing::GridType); void set_snap_mode (Editing::SnapMode); Editing::SnapMode snap_mode () const; - Editing::SnapType snap_type () const; - bool snap_musical () const; + Editing::GridType grid_type () const; + bool grid_musical () const; + bool grid_nonmusical () const; void undo (uint32_t n = 1); void redo (uint32_t n = 1); @@ -273,8 +271,7 @@ public: /* tempo */ - void set_show_measures (bool yn); - bool show_measures () const { return _show_measures; } + void update_grid (); /* analysis window */ @@ -361,7 +358,6 @@ public: void toggle_zero_line_visibility (); void set_summary (); void set_group_tabs (); - void toggle_measure_visibility (); /* returns the left-most and right-most time that the gui should allow the user to scroll to */ std::pair <samplepos_t,samplepos_t> session_gui_extents (bool use_extra = true) const; @@ -458,19 +454,16 @@ public: void snap_to (ARDOUR::MusicSample& first, ARDOUR::RoundMode direction = ARDOUR::RoundNearest, + ARDOUR::SnapPref pref = ARDOUR::SnapToAny, bool for_mark = false, - bool ensure_snap = false); + bool ensure_snap = false); void snap_to_with_modifier (ARDOUR::MusicSample& first, GdkEvent const * ev, ARDOUR::RoundMode direction = ARDOUR::RoundNearest, + ARDOUR::SnapPref pref = ARDOUR::SnapToAny, bool for_mark = false); - void snap_to (ARDOUR::MusicSample& first, - ARDOUR::MusicSample& last, - ARDOUR::RoundMode direction = ARDOUR::RoundNearest, - bool for_mark = false); - void set_snapped_cursor_position (samplepos_t pos); void begin_selection_op_history (); @@ -614,9 +607,9 @@ private: void on_samples_per_pixel_changed (); Editing::MouseMode mouse_mode; - Editing::SnapType pre_internal_snap_type; + Editing::GridType pre_internal_grid_type; Editing::SnapMode pre_internal_snap_mode; - Editing::SnapType internal_snap_type; + Editing::GridType internal_grid_type; Editing::SnapMode internal_snap_mode; Editing::MouseMode effective_mouse_mode () const; @@ -816,7 +809,6 @@ private: size_t push_canvas_cursor (Gdk::Cursor*); void pop_canvas_cursor (); - Gdk::Cursor* which_grabber_cursor () const; Gdk::Cursor* which_track_cursor () const; Gdk::Cursor* which_mode_cursor () const; Gdk::Cursor* which_trim_cursor (bool left_side) const; @@ -1068,7 +1060,9 @@ private: ARDOUR::samplepos_t find_next_region_boundary (ARDOUR::samplepos_t, int32_t dir, const TrackViewList&); std::vector<ARDOUR::samplepos_t> region_boundary_cache; + void mark_region_boundary_cache_dirty () { _region_boundary_cache_dirty = true; } void build_region_boundary_cache (); + bool _region_boundary_cache_dirty; Gtk::HBox toplevel_hpacker; @@ -1530,7 +1524,7 @@ private: void move_range_selection_start_or_end_to_region_boundary (bool, bool); - Editing::SnapType _snap_type; + Editing::GridType _grid_type; Editing::SnapMode _snap_mode; bool ignore_gui_changes; @@ -1668,7 +1662,6 @@ private: /* display control */ - bool _show_measures; /// true if the editor should follow the playhead, otherwise false bool _follow_playhead; /// true if we scroll the tracks rather than the playhead @@ -1676,17 +1669,17 @@ private: /// true if we are in fullscreen mode bool _maximised; - TempoLines* tempo_lines; + std::vector<ArdourCanvas::Ruler::Mark> grid_marks; + GridLines* grid_lines; ArdourCanvas::Container* global_rect_group; ArdourCanvas::Container* time_line_group; - void hide_measures (); - void draw_measures (std::vector<ARDOUR::TempoMap::BBTPoint>&); + void hide_grid_lines (); + void maybe_draw_grid_lines (); void new_tempo_section (); - void remove_tempo_marker (ArdourCanvas::Item*); void remove_meter_marker (ArdourCanvas::Item*); gint real_remove_tempo_marker (ARDOUR::TempoSection*); @@ -1761,7 +1754,8 @@ private: void tempo_map_changed (const PBD::PropertyChange&); void tempometric_position_changed (const PBD::PropertyChange&); - void redisplay_tempo (bool immediate_redraw); + + void redisplay_grid (bool immediate_redraw); uint32_t bbt_beat_subdivision; @@ -1821,22 +1815,25 @@ private: void set_edit_mode (ARDOUR::EditMode); void cycle_edit_mode (); - ArdourWidgets::ArdourDropdown snap_type_selector; - void build_snap_type_menu (); + ArdourWidgets::ArdourDropdown grid_type_selector; + void build_grid_type_menu (); + + ArdourWidgets::ArdourButton snap_mode_button; + bool snap_mode_button_clicked (GdkEventButton *); - ArdourWidgets::ArdourDropdown snap_mode_selector; - void build_snap_mode_menu (); Gtk::HBox snap_box; - std::vector<std::string> snap_type_strings; + Gtk::HBox _box; + + std::vector<std::string> grid_type_strings; std::vector<std::string> snap_mode_strings; - void snap_type_selection_done (Editing::SnapType); + void grid_type_selection_done (Editing::GridType); void snap_mode_selection_done (Editing::SnapMode); void snap_mode_chosen (Editing::SnapMode); - void snap_type_chosen (Editing::SnapType); + void grid_type_chosen (Editing::GridType); - Glib::RefPtr<Gtk::RadioAction> snap_type_action (Editing::SnapType); + Glib::RefPtr<Gtk::RadioAction> grid_type_action (Editing::GridType); Glib::RefPtr<Gtk::RadioAction> snap_mode_action (Editing::SnapMode); //zoom focus meu stuff @@ -2187,14 +2184,18 @@ private: void select_next_stripable (bool routes_only = true); void select_prev_stripable (bool routes_only = true); + samplepos_t snap_to_grid ( std::vector<ArdourCanvas::Ruler::Mark> marks, + samplepos_t presnap, + ARDOUR::RoundMode direction = ARDOUR::RoundNearest); + void snap_to_internal (ARDOUR::MusicSample& first, ARDOUR::RoundMode direction = ARDOUR::RoundNearest, + ARDOUR::SnapPref gpref = ARDOUR::SnapToAny, bool for_mark = false, - bool ensure_snap = false); + bool ensure_snap = false); - void timecode_snap_to_internal (ARDOUR::MusicSample& first, - ARDOUR::RoundMode direction = ARDOUR::RoundNearest, - bool for_mark = false); + samplepos_t marker_snap_to_internal (samplepos_t presnap, + ARDOUR::RoundMode direction = ARDOUR::RoundNearest); RhythmFerret* rhythm_ferret; diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc index 9061a1d657..39e7e53579 100644 --- a/gtk2_ardour/editor_actions.cc +++ b/gtk2_ardour/editor_actions.cc @@ -543,55 +543,48 @@ Editor::register_actions () myactions.register_action (editor_actions, "set-edit-lock", S_("EditMode|Lock"), sigc::bind (sigc::mem_fun (*this, &Editor::set_edit_mode), Lock)); myactions.register_action (editor_actions, "cycle-edit-mode", _("Cycle Edit Mode"), sigc::mem_fun (*this, &Editor::cycle_edit_mode)); - myactions.register_action (editor_actions, X_("SnapTo"), _("Snap to")); - myactions.register_action (editor_actions, X_("SnapMode"), _("Snap Mode")); + myactions.register_action (editor_actions, X_("GridChoice"), _("Snap & Grid")); RadioAction::Group snap_mode_group; - myactions.register_radio_action (editor_actions, snap_mode_group, X_("snap-off"), _("No Grid"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_chosen), Editing::SnapOff))); - myactions.register_radio_action (editor_actions, snap_mode_group, X_("snap-normal"), _("Grid"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_chosen), Editing::SnapNormal))); - myactions.register_radio_action (editor_actions, snap_mode_group, X_("snap-magnetic"), _("Magnetic"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_chosen), Editing::SnapMagnetic))); + /* deprecated */ myactions.register_radio_action (editor_actions, snap_mode_group, X_("snap-off"), _("No Grid"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_chosen), Editing::SnapOff))); + /* deprecated */ myactions.register_radio_action (editor_actions, snap_mode_group, X_("snap-normal"), _("Grid"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_chosen), Editing::SnapNormal))); //deprecated + /* deprecated */ myactions.register_radio_action (editor_actions, snap_mode_group, X_("snap-magnetic"), _("Magnetic"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_chosen), Editing::SnapMagnetic))); - myactions.register_action (editor_actions, X_("cycle-snap-mode"), _("Next Snap Mode"), sigc::mem_fun (*this, &Editor::cycle_snap_mode)); - myactions.register_action (editor_actions, X_("next-snap-choice"), _("Next Snap Choice"), sigc::mem_fun (*this, &Editor::next_snap_choice)); - myactions.register_action (editor_actions, X_("next-snap-choice-music-only"), _("Next Musical Snap Choice"), sigc::mem_fun (*this, &Editor::next_snap_choice_music_only)); - myactions.register_action (editor_actions, X_("prev-snap-choice"), _("Previous Snap Choice"), sigc::mem_fun (*this, &Editor::prev_snap_choice)); - myactions.register_action (editor_actions, X_("prev-snap-choice-music-only"), _("Previous Musical Snap Choice"), sigc::mem_fun (*this, &Editor::prev_snap_choice_music_only)); + snap_mode_button.set_text (_("Snap")); + snap_mode_button.set_name ("mouse mode button"); + snap_mode_button.signal_button_press_event().connect (sigc::mem_fun (*this, &Editor::snap_mode_button_clicked), false); + + myactions.register_action (editor_actions, X_("cycle-snap-mode"), _("Toggle Snap"), sigc::mem_fun (*this, &Editor::cycle_snap_mode)); + myactions.register_action (editor_actions, X_("next-grid-choice"), _("Next Quantize Grid Choice"), sigc::mem_fun (*this, &Editor::next_grid_choice)); + myactions.register_action (editor_actions, X_("prev-grid-choice"), _("Previous Quantize Grid Choice"), sigc::mem_fun (*this, &Editor::prev_grid_choice)); Glib::RefPtr<ActionGroup> snap_actions = myactions.create_action_group (X_("Snap")); - RadioAction::Group snap_choice_group; - - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-cd-frame"), _("Snap to CD Frame"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToCDFrame))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-timecode-frame"), _("Snap to Timecode Frame"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToTimecodeFrame))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-timecode-seconds"), _("Snap to Timecode Seconds"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToTimecodeSeconds))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-timecode-minutes"), _("Snap to Timecode Minutes"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToTimecodeMinutes))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-seconds"), _("Snap to Seconds"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToSeconds))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-minutes"), _("Snap to Minutes"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToMinutes))); - - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-onetwentyeighths"), _("Snap to One Twenty Eighths"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToBeatDiv128))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-sixtyfourths"), _("Snap to Sixty Fourths"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToBeatDiv64))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-thirtyseconds"), _("Snap to Thirty Seconds"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToBeatDiv32))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-twentyeighths"), _("Snap to Twenty Eighths"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToBeatDiv28))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-twentyfourths"), _("Snap to Twenty Fourths"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToBeatDiv24))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-twentieths"), _("Snap to Twentieths"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToBeatDiv20))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-asixteenthbeat"), _("Snap to Sixteenths"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToBeatDiv16))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-fourteenths"), _("Snap to Fourteenths"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToBeatDiv14))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-twelfths"), _("Snap to Twelfths"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToBeatDiv12))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-tenths"), _("Snap to Tenths"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToBeatDiv10))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-eighths"), _("Snap to Eighths"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToBeatDiv8))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-sevenths"), _("Snap to Sevenths"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToBeatDiv7))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-sixths"), _("Snap to Sixths"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToBeatDiv6))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-fifths"), _("Snap to Fifths"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToBeatDiv5))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-quarters"), _("Snap to Quarters"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToBeatDiv4))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-thirds"), _("Snap to Thirds"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToBeatDiv3))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-halves"), _("Snap to Halves"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToBeatDiv2))); - - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-beat"), _("Snap to Beat"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToBeat))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-bar"), _("Snap to Bar"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToBar))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-mark"), _("Snap to Mark"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToMark))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-region-start"), _("Snap to Region Start"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToRegionStart))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-region-end"), _("Snap to Region End"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToRegionEnd))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-region-sync"), _("Snap to Region Sync"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToRegionSync))); - myactions.register_radio_action (snap_actions, snap_choice_group, X_("snap-to-region-boundary"), _("Snap to Region Boundary"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_chosen), Editing::SnapToRegionBoundary))); + RadioAction::Group grid_choice_group; + + myactions.register_radio_action (snap_actions, grid_choice_group, X_("grid-type-thirtyseconds"), grid_type_strings[(int)GridTypeBeatDiv32].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv32))); + myactions.register_radio_action (snap_actions, grid_choice_group, X_("grid-type-twentyeighths"), grid_type_strings[(int)GridTypeBeatDiv28].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv28))); + myactions.register_radio_action (snap_actions, grid_choice_group, X_("grid-type-twentyfourths"), grid_type_strings[(int)GridTypeBeatDiv24].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv24))); + myactions.register_radio_action (snap_actions, grid_choice_group, X_("grid-type-twentieths"), grid_type_strings[(int)GridTypeBeatDiv20].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv20))); + myactions.register_radio_action (snap_actions, grid_choice_group, X_("grid-type-asixteenthbeat"), grid_type_strings[(int)GridTypeBeatDiv16].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv16))); + myactions.register_radio_action (snap_actions, grid_choice_group, X_("grid-type-fourteenths"), grid_type_strings[(int)GridTypeBeatDiv14].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv14))); + myactions.register_radio_action (snap_actions, grid_choice_group, X_("grid-type-twelfths"), grid_type_strings[(int)GridTypeBeatDiv12].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv12))); + myactions.register_radio_action (snap_actions, grid_choice_group, X_("grid-type-tenths"), grid_type_strings[(int)GridTypeBeatDiv10].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv10))); + myactions.register_radio_action (snap_actions, grid_choice_group, X_("grid-type-eighths"), grid_type_strings[(int)GridTypeBeatDiv8].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv8))); + myactions.register_radio_action (snap_actions, grid_choice_group, X_("grid-type-sevenths"), grid_type_strings[(int)GridTypeBeatDiv7].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv7))); + myactions.register_radio_action (snap_actions, grid_choice_group, X_("grid-type-sixths"), grid_type_strings[(int)GridTypeBeatDiv6].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv6))); + myactions.register_radio_action (snap_actions, grid_choice_group, X_("grid-type-fifths"), grid_type_strings[(int)GridTypeBeatDiv5].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv5))); + myactions.register_radio_action (snap_actions, grid_choice_group, X_("grid-type-quarters"), grid_type_strings[(int)GridTypeBeatDiv4].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv4))); + myactions.register_radio_action (snap_actions, grid_choice_group, X_("grid-type-thirds"), grid_type_strings[(int)GridTypeBeatDiv3].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv3))); + myactions.register_radio_action (snap_actions, grid_choice_group, X_("grid-type-halves"), grid_type_strings[(int)GridTypeBeatDiv2].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeatDiv2))); + + myactions.register_radio_action (snap_actions, grid_choice_group, X_("grid-type-smpte"), grid_type_strings[(int)GridTypeSmpte].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeSmpte))); + myactions.register_radio_action (snap_actions, grid_choice_group, X_("grid-type-minsec"), grid_type_strings[(int)GridTypeMinSec].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeMinSec))); + myactions.register_radio_action (snap_actions, grid_choice_group, X_("grid-type-samples"), grid_type_strings[(int)GridTypeSamples].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeSamples))); + + myactions.register_radio_action (snap_actions, grid_choice_group, X_("grid-type-beat"), grid_type_strings[(int)GridTypeBeat].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBeat))); + myactions.register_radio_action (snap_actions, grid_choice_group, X_("grid-type-bar"), grid_type_strings[(int)GridTypeBar].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeBar))); + + myactions.register_radio_action (snap_actions, grid_choice_group, X_("grid-type-none"), grid_type_strings[(int)GridTypeNone].c_str(), (sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_chosen), Editing::GridTypeNone))); myactions.register_toggle_action (editor_actions, X_("show-marker-lines"), _("Show Marker Lines"), sigc::mem_fun (*this, &Editor::toggle_marker_lines)); @@ -738,8 +731,6 @@ Editor::register_actions () myactions.register_toggle_action (editor_actions, X_("ToggleGroupTabs"), _("Show Group Tabs"), sigc::mem_fun (*this, &Editor::set_group_tabs)); - myactions.register_toggle_action (editor_actions, X_("ToggleMeasureVisibility"), _("Show Measure Lines"), sigc::mem_fun (*this, &Editor::toggle_measure_visibility)); - myactions.register_action (editor_actions, X_("toggle-midi-input-active"), _("Toggle MIDI Input Active for Editor-Selected Tracks/Busses"), sigc::bind (sigc::mem_fun (*this, &Editor::toggle_midi_input_active), false)); @@ -1027,16 +1018,6 @@ Editor::set_xjadeo_viewoption (int what) } void -Editor::toggle_measure_visibility () -{ - Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility")); - if (act) { - Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act); - set_show_measures (tact->get_active()); - } -} - -void Editor::edit_current_meter () { ARDOUR::MeterSection* ms = const_cast<ARDOUR::MeterSection*>(&_session->tempo_map().meter_section_at_sample (ARDOUR_UI::instance()->primary_clock->absolute_time())); @@ -1051,101 +1032,74 @@ Editor::edit_current_tempo () } RefPtr<RadioAction> -Editor::snap_type_action (SnapType type) +Editor::grid_type_action (GridType type) { const char* action = 0; RefPtr<Action> act; switch (type) { - case Editing::SnapToCDFrame: - action = "snap-to-cd-frame"; - break; - case Editing::SnapToTimecodeFrame: - action = "snap-to-timecode-frame"; - break; - case Editing::SnapToTimecodeSeconds: - action = "snap-to-timecode-seconds"; - break; - case Editing::SnapToTimecodeMinutes: - action = "snap-to-timecode-minutes"; - break; - case Editing::SnapToSeconds: - action = "snap-to-seconds"; - break; - case Editing::SnapToMinutes: - action = "snap-to-minutes"; - break; - case Editing::SnapToBeatDiv128: - action = "snap-to-onetwentyeighths"; - break; - case Editing::SnapToBeatDiv64: - action = "snap-to-sixtyfourths"; - break; - case Editing::SnapToBeatDiv32: - action = "snap-to-thirtyseconds"; + case Editing::GridTypeBeatDiv32: + action = "grid-type-thirtyseconds"; break; - case Editing::SnapToBeatDiv28: - action = "snap-to-twentyeighths"; + case Editing::GridTypeBeatDiv28: + action = "grid-type-twentyeighths"; break; - case Editing::SnapToBeatDiv24: - action = "snap-to-twentyfourths"; + case Editing::GridTypeBeatDiv24: + action = "grid-type-twentyfourths"; break; - case Editing::SnapToBeatDiv20: - action = "snap-to-twentieths"; + case Editing::GridTypeBeatDiv20: + action = "grid-type-twentieths"; break; - case Editing::SnapToBeatDiv16: - action = "snap-to-asixteenthbeat"; + case Editing::GridTypeBeatDiv16: + action = "grid-type-asixteenthbeat"; break; - case Editing::SnapToBeatDiv14: - action = "snap-to-fourteenths"; + case Editing::GridTypeBeatDiv14: + action = "grid-type-fourteenths"; break; - case Editing::SnapToBeatDiv12: - action = "snap-to-twelfths"; + case Editing::GridTypeBeatDiv12: + action = "grid-type-twelfths"; break; - case Editing::SnapToBeatDiv10: - action = "snap-to-tenths"; + case Editing::GridTypeBeatDiv10: + action = "grid-type-tenths"; break; - case Editing::SnapToBeatDiv8: - action = "snap-to-eighths"; + case Editing::GridTypeBeatDiv8: + action = "grid-type-eighths"; break; - case Editing::SnapToBeatDiv7: - action = "snap-to-sevenths"; + case Editing::GridTypeBeatDiv7: + action = "grid-type-sevenths"; break; - case Editing::SnapToBeatDiv6: - action = "snap-to-sixths"; + case Editing::GridTypeBeatDiv6: + action = "grid-type-sixths"; break; - case Editing::SnapToBeatDiv5: - action = "snap-to-fifths"; + case Editing::GridTypeBeatDiv5: + action = "grid-type-fifths"; break; - case Editing::SnapToBeatDiv4: - action = "snap-to-quarters"; + case Editing::GridTypeBeatDiv4: + action = "grid-type-quarters"; break; - case Editing::SnapToBeatDiv3: - action = "snap-to-thirds"; + case Editing::GridTypeBeatDiv3: + action = "grid-type-thirds"; break; - case Editing::SnapToBeatDiv2: - action = "snap-to-halves"; + case Editing::GridTypeBeatDiv2: + action = "grid-type-halves"; break; - case Editing::SnapToBeat: - action = "snap-to-beat"; + case Editing::GridTypeBeat: + action = "grid-type-beat"; break; - case Editing::SnapToBar: - action = "snap-to-bar"; + case Editing::GridTypeBar: + action = "grid-type-bar"; break; - case Editing::SnapToMark: - action = "snap-to-mark"; + case Editing::GridTypeNone: + action = "grid-type-none"; break; - case Editing::SnapToRegionStart: - action = "snap-to-region-start"; + case Editing::GridTypeSmpte: + action = "grid-type-smpte"; break; - case Editing::SnapToRegionEnd: - action = "snap-to-region-end"; + case Editing::GridTypeSamples: + action = "grid-type-samples"; break; - case Editing::SnapToRegionSync: - action = "snap-to-region-sync"; - break; - case Editing::SnapToRegionBoundary: - action = "snap-to-region-boundary"; + case Editing::GridTypeMinSec: + action = "grid-type-minsec"; break; default: fatal << string_compose (_("programming error: %1: %2"), "Editor: impossible snap-to type", (int) type) << endmsg; @@ -1159,371 +1113,113 @@ Editor::snap_type_action (SnapType type) return ract; } else { - error << string_compose (_("programming error: %1"), "Editor::snap_type_chosen could not find action to match type.") << endmsg; + error << string_compose (_("programming error: %1"), "Editor::grid_type_chosen could not find action to match type.") << endmsg; return RefPtr<RadioAction>(); } } void -Editor::next_snap_choice () +Editor::next_grid_choice () { - switch (_snap_type) { - case Editing::SnapToCDFrame: - set_snap_to (Editing::SnapToTimecodeFrame); - break; - case Editing::SnapToTimecodeFrame: - set_snap_to (Editing::SnapToTimecodeSeconds); - break; - case Editing::SnapToTimecodeSeconds: - set_snap_to (Editing::SnapToTimecodeMinutes); - break; - case Editing::SnapToTimecodeMinutes: - set_snap_to (Editing::SnapToSeconds); - break; - case Editing::SnapToSeconds: - set_snap_to (Editing::SnapToMinutes); - break; - case Editing::SnapToMinutes: - set_snap_to (Editing::SnapToBeatDiv128); - break; - case Editing::SnapToBeatDiv128: - set_snap_to (Editing::SnapToBeatDiv64); - break; - case Editing::SnapToBeatDiv64: - set_snap_to (Editing::SnapToBeatDiv32); - break; - case Editing::SnapToBeatDiv32: - set_snap_to (Editing::SnapToBeatDiv28); - break; - case Editing::SnapToBeatDiv28: - set_snap_to (Editing::SnapToBeatDiv24); - break; - case Editing::SnapToBeatDiv24: - set_snap_to (Editing::SnapToBeatDiv20); - break; - case Editing::SnapToBeatDiv20: - set_snap_to (Editing::SnapToBeatDiv16); - break; - case Editing::SnapToBeatDiv16: - set_snap_to (Editing::SnapToBeatDiv14); - break; - case Editing::SnapToBeatDiv14: - set_snap_to (Editing::SnapToBeatDiv12); - break; - case Editing::SnapToBeatDiv12: - set_snap_to (Editing::SnapToBeatDiv10); - break; - case Editing::SnapToBeatDiv10: - set_snap_to (Editing::SnapToBeatDiv8); - break; - case Editing::SnapToBeatDiv8: - set_snap_to (Editing::SnapToBeatDiv7); - break; - case Editing::SnapToBeatDiv7: - set_snap_to (Editing::SnapToBeatDiv6); - break; - case Editing::SnapToBeatDiv6: - set_snap_to (Editing::SnapToBeatDiv5); - break; - case Editing::SnapToBeatDiv5: - set_snap_to (Editing::SnapToBeatDiv4); - break; - case Editing::SnapToBeatDiv4: - set_snap_to (Editing::SnapToBeatDiv3); - break; - case Editing::SnapToBeatDiv3: - set_snap_to (Editing::SnapToBeatDiv2); - break; - case Editing::SnapToBeatDiv2: - set_snap_to (Editing::SnapToBeat); - break; - case Editing::SnapToBeat: - set_snap_to (Editing::SnapToBar); - break; - case Editing::SnapToBar: - set_snap_to (Editing::SnapToMark); - break; - case Editing::SnapToMark: - set_snap_to (Editing::SnapToRegionStart); - break; - case Editing::SnapToRegionStart: - set_snap_to (Editing::SnapToRegionEnd); - break; - case Editing::SnapToRegionEnd: - set_snap_to (Editing::SnapToRegionSync); - break; - case Editing::SnapToRegionSync: - set_snap_to (Editing::SnapToRegionBoundary); - break; - case Editing::SnapToRegionBoundary: - set_snap_to (Editing::SnapToCDFrame); - break; + switch (_grid_type) { + case Editing::GridTypeBeatDiv32: + set_grid_to (Editing::GridTypeNone); + break; + case Editing::GridTypeBeatDiv16: + set_grid_to (Editing::GridTypeBeatDiv32); + break; + case Editing::GridTypeBeatDiv8: + set_grid_to (Editing::GridTypeBeatDiv16); + break; + case Editing::GridTypeBeatDiv4: + set_grid_to (Editing::GridTypeBeatDiv8); + break; + case Editing::GridTypeBeatDiv2: + set_grid_to (Editing::GridTypeBeatDiv4); + break; + case Editing::GridTypeBeat: + set_grid_to (Editing::GridTypeBeatDiv2); + break; + case Editing::GridTypeBar: + set_grid_to (Editing::GridTypeBeat); + break; + case Editing::GridTypeNone: + set_grid_to (Editing::GridTypeBar); + break; + case Editing::GridTypeBeatDiv3: + case Editing::GridTypeBeatDiv6: + case Editing::GridTypeBeatDiv12: + case Editing::GridTypeBeatDiv24: + case Editing::GridTypeBeatDiv5: + case Editing::GridTypeBeatDiv10: + case Editing::GridTypeBeatDiv20: + case Editing::GridTypeBeatDiv7: + case Editing::GridTypeBeatDiv14: + case Editing::GridTypeBeatDiv28: + case Editing::GridTypeSmpte: + case Editing::GridTypeMinSec: + case Editing::GridTypeSamples: + break; //do nothing } } void -Editor::prev_snap_choice () +Editor::prev_grid_choice () { - switch (_snap_type) { - case Editing::SnapToCDFrame: - set_snap_to (Editing::SnapToRegionBoundary); - break; - case Editing::SnapToTimecodeFrame: - set_snap_to (Editing::SnapToCDFrame); - break; - case Editing::SnapToTimecodeSeconds: - set_snap_to (Editing::SnapToTimecodeFrame); - break; - case Editing::SnapToTimecodeMinutes: - set_snap_to (Editing::SnapToTimecodeSeconds); - break; - case Editing::SnapToSeconds: - set_snap_to (Editing::SnapToTimecodeMinutes); - break; - case Editing::SnapToMinutes: - set_snap_to (Editing::SnapToSeconds); - break; - case Editing::SnapToBeatDiv128: - set_snap_to (Editing::SnapToMinutes); - break; - case Editing::SnapToBeatDiv64: - set_snap_to (Editing::SnapToBeatDiv128); - break; - case Editing::SnapToBeatDiv32: - set_snap_to (Editing::SnapToBeatDiv64); - break; - case Editing::SnapToBeatDiv28: - set_snap_to (Editing::SnapToBeatDiv32); - break; - case Editing::SnapToBeatDiv24: - set_snap_to (Editing::SnapToBeatDiv28); - break; - case Editing::SnapToBeatDiv20: - set_snap_to (Editing::SnapToBeatDiv24); - break; - case Editing::SnapToBeatDiv16: - set_snap_to (Editing::SnapToBeatDiv20); - break; - case Editing::SnapToBeatDiv14: - set_snap_to (Editing::SnapToBeatDiv16); - break; - case Editing::SnapToBeatDiv12: - set_snap_to (Editing::SnapToBeatDiv14); - break; - case Editing::SnapToBeatDiv10: - set_snap_to (Editing::SnapToBeatDiv12); - break; - case Editing::SnapToBeatDiv8: - set_snap_to (Editing::SnapToBeatDiv10); - break; - case Editing::SnapToBeatDiv7: - set_snap_to (Editing::SnapToBeatDiv8); - break; - case Editing::SnapToBeatDiv6: - set_snap_to (Editing::SnapToBeatDiv7); - break; - case Editing::SnapToBeatDiv5: - set_snap_to (Editing::SnapToBeatDiv6); - break; - case Editing::SnapToBeatDiv4: - set_snap_to (Editing::SnapToBeatDiv5); - break; - case Editing::SnapToBeatDiv3: - set_snap_to (Editing::SnapToBeatDiv4); - break; - case Editing::SnapToBeatDiv2: - set_snap_to (Editing::SnapToBeatDiv3); - break; - case Editing::SnapToBeat: - set_snap_to (Editing::SnapToBeatDiv2); - break; - case Editing::SnapToBar: - set_snap_to (Editing::SnapToBeat); - break; - case Editing::SnapToMark: - set_snap_to (Editing::SnapToBar); - break; - case Editing::SnapToRegionStart: - set_snap_to (Editing::SnapToMark); - break; - case Editing::SnapToRegionEnd: - set_snap_to (Editing::SnapToRegionStart); - break; - case Editing::SnapToRegionSync: - set_snap_to (Editing::SnapToRegionEnd); - break; - case Editing::SnapToRegionBoundary: - set_snap_to (Editing::SnapToRegionSync); - break; + switch (_grid_type) { + case Editing::GridTypeBeatDiv32: + set_grid_to (Editing::GridTypeBeatDiv16); + break; + case Editing::GridTypeBeatDiv16: + set_grid_to (Editing::GridTypeBeatDiv8); + break; + case Editing::GridTypeBeatDiv8: + set_grid_to (Editing::GridTypeBeatDiv4); + break; + case Editing::GridTypeBeatDiv4: + set_grid_to (Editing::GridTypeBeatDiv2); + break; + case Editing::GridTypeBeatDiv2: + set_grid_to (Editing::GridTypeBeat); + break; + case Editing::GridTypeBeat: + set_grid_to (Editing::GridTypeBar); + break; + case Editing::GridTypeBar: + set_grid_to (Editing::GridTypeNone); + break; + case Editing::GridTypeNone: + set_grid_to (Editing::GridTypeBeatDiv32); + break; + case Editing::GridTypeBeatDiv3: + case Editing::GridTypeBeatDiv6: + case Editing::GridTypeBeatDiv12: + case Editing::GridTypeBeatDiv24: + case Editing::GridTypeBeatDiv5: + case Editing::GridTypeBeatDiv10: + case Editing::GridTypeBeatDiv20: + case Editing::GridTypeBeatDiv7: + case Editing::GridTypeBeatDiv14: + case Editing::GridTypeBeatDiv28: + case Editing::GridTypeSmpte: + case Editing::GridTypeMinSec: + case Editing::GridTypeSamples: + break; //do nothing } } void -Editor::next_snap_choice_music_only () -{ - switch (_snap_type) { - case Editing::SnapToMark: - case Editing::SnapToRegionStart: - case Editing::SnapToRegionEnd: - case Editing::SnapToRegionSync: - case Editing::SnapToRegionBoundary: - case Editing::SnapToCDFrame: - case Editing::SnapToTimecodeFrame: - case Editing::SnapToTimecodeSeconds: - case Editing::SnapToTimecodeMinutes: - case Editing::SnapToSeconds: - case Editing::SnapToMinutes: - set_snap_to (Editing::SnapToBeatDiv128); - break; - case Editing::SnapToBeatDiv128: - set_snap_to (Editing::SnapToBeatDiv64); - break; - case Editing::SnapToBeatDiv64: - set_snap_to (Editing::SnapToBeatDiv32); - break; - case Editing::SnapToBeatDiv32: - set_snap_to (Editing::SnapToBeatDiv28); - break; - case Editing::SnapToBeatDiv28: - set_snap_to (Editing::SnapToBeatDiv24); - break; - case Editing::SnapToBeatDiv24: - set_snap_to (Editing::SnapToBeatDiv20); - break; - case Editing::SnapToBeatDiv20: - set_snap_to (Editing::SnapToBeatDiv16); - break; - case Editing::SnapToBeatDiv16: - set_snap_to (Editing::SnapToBeatDiv14); - break; - case Editing::SnapToBeatDiv14: - set_snap_to (Editing::SnapToBeatDiv12); - break; - case Editing::SnapToBeatDiv12: - set_snap_to (Editing::SnapToBeatDiv10); - break; - case Editing::SnapToBeatDiv10: - set_snap_to (Editing::SnapToBeatDiv8); - break; - case Editing::SnapToBeatDiv8: - set_snap_to (Editing::SnapToBeatDiv7); - break; - case Editing::SnapToBeatDiv7: - set_snap_to (Editing::SnapToBeatDiv6); - break; - case Editing::SnapToBeatDiv6: - set_snap_to (Editing::SnapToBeatDiv5); - break; - case Editing::SnapToBeatDiv5: - set_snap_to (Editing::SnapToBeatDiv4); - break; - case Editing::SnapToBeatDiv4: - set_snap_to (Editing::SnapToBeatDiv3); - break; - case Editing::SnapToBeatDiv3: - set_snap_to (Editing::SnapToBeatDiv2); - break; - case Editing::SnapToBeatDiv2: - set_snap_to (Editing::SnapToBeat); - break; - case Editing::SnapToBeat: - set_snap_to (Editing::SnapToBar); - break; - case Editing::SnapToBar: - set_snap_to (Editing::SnapToBeatDiv128); - break; - } -} - -void -Editor::prev_snap_choice_music_only () -{ - switch (_snap_type) { - case Editing::SnapToMark: - case Editing::SnapToRegionStart: - case Editing::SnapToRegionEnd: - case Editing::SnapToRegionSync: - case Editing::SnapToRegionBoundary: - case Editing::SnapToCDFrame: - case Editing::SnapToTimecodeFrame: - case Editing::SnapToTimecodeSeconds: - case Editing::SnapToTimecodeMinutes: - case Editing::SnapToSeconds: - case Editing::SnapToMinutes: - set_snap_to (Editing::SnapToBar); - break; - case Editing::SnapToBeatDiv128: - set_snap_to (Editing::SnapToBeat); - break; - case Editing::SnapToBeatDiv64: - set_snap_to (Editing::SnapToBeatDiv128); - break; - case Editing::SnapToBeatDiv32: - set_snap_to (Editing::SnapToBeatDiv64); - break; - case Editing::SnapToBeatDiv28: - set_snap_to (Editing::SnapToBeatDiv32); - break; - case Editing::SnapToBeatDiv24: - set_snap_to (Editing::SnapToBeatDiv28); - break; - case Editing::SnapToBeatDiv20: - set_snap_to (Editing::SnapToBeatDiv24); - break; - case Editing::SnapToBeatDiv16: - set_snap_to (Editing::SnapToBeatDiv20); - break; - case Editing::SnapToBeatDiv14: - set_snap_to (Editing::SnapToBeatDiv16); - break; - case Editing::SnapToBeatDiv12: - set_snap_to (Editing::SnapToBeatDiv14); - break; - case Editing::SnapToBeatDiv10: - set_snap_to (Editing::SnapToBeatDiv12); - break; - case Editing::SnapToBeatDiv8: - set_snap_to (Editing::SnapToBeatDiv10); - break; - case Editing::SnapToBeatDiv7: - set_snap_to (Editing::SnapToBeatDiv8); - break; - case Editing::SnapToBeatDiv6: - set_snap_to (Editing::SnapToBeatDiv7); - break; - case Editing::SnapToBeatDiv5: - set_snap_to (Editing::SnapToBeatDiv6); - break; - case Editing::SnapToBeatDiv4: - set_snap_to (Editing::SnapToBeatDiv5); - break; - case Editing::SnapToBeatDiv3: - set_snap_to (Editing::SnapToBeatDiv4); - break; - case Editing::SnapToBeatDiv2: - set_snap_to (Editing::SnapToBeatDiv3); - break; - case Editing::SnapToBeat: - set_snap_to (Editing::SnapToBeatDiv2); - break; - case Editing::SnapToBar: - set_snap_to (Editing::SnapToBeat); - break; - } -} - -void -Editor::snap_type_chosen (SnapType type) +Editor::grid_type_chosen (GridType type) { /* this is driven by a toggle on a radio group, and so is invoked twice, once for the item that became inactive and once for the one that became active. */ - RefPtr<RadioAction> ract = snap_type_action (type); + RefPtr<RadioAction> ract = grid_type_action (type); if (ract && ract->get_active()) { - set_snap_to (type); + set_grid_to (type); } } @@ -1565,8 +1261,6 @@ Editor::cycle_snap_mode () { switch (_snap_mode) { case SnapOff: - set_snap_mode (SnapNormal); - break; case SnapNormal: set_snap_mode (SnapMagnetic); break; @@ -1584,6 +1278,10 @@ Editor::snap_mode_chosen (SnapMode mode) active. */ + if (mode == SnapNormal) { + mode = SnapMagnetic; + } + RefPtr<RadioAction> ract = snap_mode_action (mode); if (ract && ract->get_active()) { diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc index a60d3eab9c..cf25538d49 100644 --- a/gtk2_ardour/editor_canvas.cc +++ b/gtk2_ardour/editor_canvas.cc @@ -306,7 +306,7 @@ Editor::track_canvas_viewport_size_allocated () } update_fixed_rulers(); - redisplay_tempo (false); + redisplay_grid (false); _summary->set_overlays_dirty (); } @@ -1044,7 +1044,7 @@ Editor::color_handler() _track_canvas->queue_draw (); /* - redisplay_tempo (true); + redisplay_grid (true); if (_session) _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks); // redraw metric markers @@ -1149,26 +1149,6 @@ Editor::pop_canvas_cursor () } Gdk::Cursor* -Editor::which_grabber_cursor () const -{ - Gdk::Cursor* c = _cursors->grabber; - - switch (_edit_point) { - case EditAtMouse: - c = _cursors->grabber_edit_point; - break; - default: - boost::shared_ptr<Movable> m = _movable.lock(); - if (m && m->locked()) { - c = _cursors->speaker; - } - break; - } - - return c; -} - -Gdk::Cursor* Editor::which_trim_cursor (bool left) const { if (!entered_regionview) { @@ -1267,7 +1247,7 @@ Editor::which_track_cursor () const switch (_join_object_range_state) { case JOIN_OBJECT_RANGE_NONE: case JOIN_OBJECT_RANGE_OBJECT: - cursor = which_grabber_cursor (); + cursor = _cursors->grabber; break; case JOIN_OBJECT_RANGE_RANGE: cursor = _cursors->selector; @@ -1314,14 +1294,7 @@ Editor::which_canvas_cursor(ItemType type) const cursor = which_track_cursor (); break; case PlayheadCursorItem: - switch (_edit_point) { - case EditAtMouse: - cursor = _cursors->grabber_edit_point; - break; - default: - cursor = _cursors->grabber; - break; - } + cursor = _cursors->grabber; break; case SelectionItem: cursor = _cursors->selector; @@ -1431,7 +1404,7 @@ Editor::which_canvas_cursor(ItemType type) const case VideoBarItem: case TransportMarkerBarItem: case DropZoneItem: - cursor = which_grabber_cursor(); + cursor = _cursors->grabber; break; default: diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc index 0dab9d8d0f..e80f28171c 100644 --- a/gtk2_ardour/editor_drag.cc +++ b/gtk2_ardour/editor_drag.cc @@ -293,16 +293,9 @@ Drag::start_grab (GdkEvent* event, Gdk::Cursor *cursor) _was_rolling = false; } - switch (_editor->snap_type()) { - case SnapToRegionStart: - case SnapToRegionEnd: - case SnapToRegionSync: - case SnapToRegionBoundary: - _editor->build_region_boundary_cache (); - break; - default: - break; - } +// if ( UIConfiguration::instance().get_snap_to_region_start() || UIConfiguration::instance().get_snap_to_region_end() || UIConfiguration::instance().get_snap_to_region_sync() ) { +// _editor->build_region_boundary_cache (); +// } } /** Call to end a drag `successfully'. Ungrabs item and calls @@ -388,7 +381,7 @@ Drag::setup_snap_delta (MusicSample pos) { TempoMap& map (_editor->session()->tempo_map()); MusicSample snap (pos); - _editor->snap_to (snap, ARDOUR::RoundNearest, false, true); + _editor->snap_to (snap, ARDOUR::RoundNearest, ARDOUR::SnapToAny, false, true); _snap_delta = snap.sample - pos.sample; _snap_delta_music = 0.0; @@ -3231,7 +3224,7 @@ TrimDrag::setup_pointer_sample_offset () MeterMarkerDrag::MeterMarkerDrag (Editor* e, ArdourCanvas::Item* i, bool c) : Drag (e, i) , _copy (c) - , _old_snap_type (e->snap_type()) + , _old_grid_type (e->grid_type()) , _old_snap_mode (e->snap_mode()) , before_state (0) { @@ -3304,14 +3297,14 @@ MeterMarkerDrag::motion (GdkEvent* event, bool first_move) } /* only snap to bars. leave snap mode alone for audio locked meters.*/ if (_real_section->position_lock_style() != AudioTime) { - _editor->set_snap_to (SnapToBar); - _editor->set_snap_mode (SnapNormal); + _editor->set_grid_to (GridTypeBar); + _editor->set_snap_mode (SnapMagnetic); } } samplepos_t pf = adjusted_current_sample (event); - if (_real_section->position_lock_style() == AudioTime && _editor->snap_musical()) { + if (_real_section->position_lock_style() == AudioTime && _editor->grid_musical()) { /* never snap to music for audio locked */ pf = adjusted_current_sample (event, false); } @@ -3336,7 +3329,7 @@ MeterMarkerDrag::finished (GdkEvent* event, bool movement_occurred) } /* reinstate old snap setting */ - _editor->set_snap_to (_old_snap_type); + _editor->set_grid_to (_old_grid_type); _editor->set_snap_mode (_old_snap_mode); TempoMap& map (_editor->session()->tempo_map()); @@ -3356,7 +3349,7 @@ MeterMarkerDrag::aborted (bool moved) _marker->set_position (_marker->meter().sample ()); if (moved) { /* reinstate old snap setting */ - _editor->set_snap_to (_old_snap_type); + _editor->set_grid_to (_old_grid_type); _editor->set_snap_mode (_old_snap_mode); _editor->session()->tempo_map().set_state (*before_state, Stateful::current_state_version); @@ -3473,7 +3466,7 @@ TempoMarkerDrag::motion (GdkEvent* event, bool first_move) } else if (_movable && !_real_section->locked_to_meter()) { samplepos_t pf; - if (_editor->snap_musical()) { + if (_editor->grid_musical()) { /* we can't snap to a grid that we are about to move. * gui_move_tempo() will sort out snap using the supplied beat divisions. */ @@ -3607,7 +3600,7 @@ BBTRulerDrag::motion (GdkEvent* event, bool first_move) TempoMap& map (_editor->session()->tempo_map()); samplepos_t pf; - if (_editor->snap_musical()) { + if (_editor->grid_musical()) { pf = adjusted_current_sample (event, false); } else { pf = adjusted_current_sample (event); @@ -3755,7 +3748,7 @@ TempoTwistDrag::motion (GdkEvent* event, bool first_move) samplepos_t pf; - if (_editor->snap_musical()) { + if (_editor->grid_musical()) { pf = adjusted_current_sample (event, false); } else { pf = adjusted_current_sample (event); @@ -5099,7 +5092,7 @@ RubberbandSelectDrag::motion (GdkEvent* event, bool) MusicSample grab (grab_sample (), 0); if (UIConfiguration::instance().get_rubberbanding_snaps_to_grid ()) { - _editor->snap_to_with_modifier (grab, event); + _editor->snap_to_with_modifier (grab, event, RoundNearest, SnapToGrid); } else { grab.sample = raw_grab_sample (); } @@ -6078,7 +6071,7 @@ NoteDrag::total_dx (GdkEvent * event) const /* possibly snap and return corresponding delta in quarter notes */ MusicSample snap (st, 0); - _editor->snap_to_with_modifier (snap, event); + _editor->snap_to_with_modifier (snap, event, RoundNearest, SnapToGrid); double ret = map.exact_qn_at_sample (snap.sample, snap.division) - n_qn - snap_delta_music (event->button.state); /* prevent the earliest note being dragged earlier than the region's start position */ diff --git a/gtk2_ardour/editor_drag.h b/gtk2_ardour/editor_drag.h index 3dde8d80ad..7ffb7ef57e 100644 --- a/gtk2_ardour/editor_drag.h +++ b/gtk2_ardour/editor_drag.h @@ -759,7 +759,7 @@ private: ARDOUR::MeterSection* _real_section; bool _copy; - Editing::SnapType _old_snap_type; + Editing::GridType _old_grid_type; Editing::SnapMode _old_snap_mode; XMLNode* before_state; }; diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index bb8b2accae..930b17a708 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -58,6 +58,7 @@ #include "marker.h" #include "streamview.h" #include "region_gain_line.h" +#include "rc_option_editor.h" #include "automation_time_axis.h" #include "control_point.h" #include "selection.h" @@ -217,6 +218,25 @@ Editor::mouse_mode_object_range_toggled() set_mouse_mode(m, true); //call this so the button styles can get updated } +bool +Editor::snap_mode_button_clicked (GdkEventButton* ev) +{ + if (ev->button != 3) { + cycle_snap_mode(); + return true; + } + + RCOptionEditor* rc_option_editor = ARDOUR_UI::instance()->get_rc_option_editor(); + if ( rc_option_editor ) { + ARDOUR_UI::instance()->show_tabbable (rc_option_editor); + rc_option_editor->set_current_page (_("Editor/Snap")); + } + + return true; +} + + + static Glib::RefPtr<Action> get_mouse_mode_action(MouseMode m) { @@ -296,10 +316,10 @@ Editor::mouse_mode_toggled (MouseMode m) this must toggle the actions and not call set_snap_*() directly, otherwise things get out of sync and the combo box stops working. */ if (!was_internal && internal_editing()) { - snap_type_action(internal_snap_type)->set_active(true); + grid_type_action(internal_grid_type)->set_active(true); snap_mode_action(internal_snap_mode)->set_active(true); } else if (was_internal && !internal_editing()) { - snap_type_action(pre_internal_snap_type)->set_active(true); + grid_type_action(pre_internal_grid_type)->set_active(true); snap_mode_action(pre_internal_snap_mode)->set_active(true); } @@ -1571,7 +1591,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT case MarkerBarItem: if (!_dragging_playhead) { - snap_to_with_modifier (where, event, RoundNearest, true); + snap_to_with_modifier (where, event, RoundNearest, SnapToAny, true); mouse_add_new_marker (where.sample); } return true; @@ -1579,7 +1599,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT case CdMarkerBarItem: if (!_dragging_playhead) { // if we get here then a dragged range wasn't done - snap_to_with_modifier (where, event, RoundNearest, true); + snap_to_with_modifier (where, event, RoundNearest, SnapToAny, true); mouse_add_new_marker (where.sample, true); } return true; @@ -2085,7 +2105,7 @@ Editor::motion_handler (ArdourCanvas::Item* /*item*/, GdkEvent* event, bool from snap_to_with_modifier (where, event); set_snapped_cursor_position (where.sample); } - + //drags might also change the snapped_cursor location, because we are snapping the thing being dragged, not the actual mouse cursor if (_drags->active ()) { return _drags->motion_handler (event, from_autoscroll); @@ -2377,23 +2397,10 @@ Editor::mouse_rename_region (ArdourCanvas::Item* /*item*/, GdkEvent* /*event*/) void Editor::mouse_brush_insert_region (RegionView* rv, samplepos_t pos) { - /* no brushing without a useful snap setting */ - - switch (_snap_mode) { - case SnapMagnetic: - return; /* can't work because it allows region to be placed anywhere */ - default: - break; /* OK */ - } - - switch (_snap_type) { - case SnapToMark: + /* no brushing without a useful quantize setting */ + if (_grid_type == GridTypeNone) return; - default: - break; - } - /* don't brush a copy over the original */ if (pos == rv->region()->position()) { diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index d29d28ba28..d94506012b 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -193,16 +193,16 @@ Editor::split_regions_at (MusicSample where, RegionSelection& regions, bool snap // region boundaries, don't pay attention to them if (regions.size() == 1) { - switch (_snap_type) { - case SnapToRegionStart: - case SnapToRegionSync: - case SnapToRegionEnd: - break; - default: - if (snap_sample) { +// switch (_snap_type) { //ToDo !!! +// case SnapToRegionStart: +// case SnapToRegionSync: +// case SnapToRegionEnd: +// break; +// default: +// if (snap_sample) { snap_to (where); - } - } +// } +// } } else { if (snap_sample) { snap_to (where); @@ -707,6 +707,13 @@ Editor::move_to_end () void Editor::build_region_boundary_cache () { + + //ToDo: maybe set a timer so we don't recalutate when lots of changes are coming in + //ToDo: maybe somehow defer this until session is fully loaded. + + if ( !_region_boundary_cache_dirty ) + return; + samplepos_t pos = 0; vector<RegionPoint> interesting_points; boost::shared_ptr<Region> r; @@ -720,37 +727,30 @@ Editor::build_region_boundary_cache () } bool maybe_first_sample = false; - - switch (_snap_type) { - case SnapToRegionStart: + + if ( UIConfiguration::instance().get_snap_to_region_start() ) { interesting_points.push_back (Start); maybe_first_sample = true; - break; - case SnapToRegionEnd: + } + + if ( UIConfiguration::instance().get_snap_to_region_end() ) { interesting_points.push_back (End); - break; - case SnapToRegionSync: + } + + if ( UIConfiguration::instance().get_snap_to_region_sync() ) { interesting_points.push_back (SyncPoint); - break; - case SnapToRegionBoundary: - interesting_points.push_back (Start); - interesting_points.push_back (End); - maybe_first_sample = true; - break; - default: - fatal << string_compose (_("build_region_boundary_cache called with snap_type = %1"), _snap_type) << endmsg; - abort(); /*NOTREACHED*/ - return; } - + TimeAxisView *ontrack = 0; TrackViewList tlist; - if (!selection->tracks.empty()) { - tlist = selection->tracks.filter_to_unique_playlists (); - } else { + //in the past, we used the track selection to limit snap. I think this is not desired. + //or if it is, it needs to be updated every time the track selection changes (so the snapped-cursor can show it) +// if (!selection->tracks.empty()) { +// tlist = selection->tracks.filter_to_unique_playlists (); +// } else { tlist = track_views.filter_to_unique_playlists (); - } +// } if (maybe_first_sample) { TrackViewList::const_iterator i; @@ -822,6 +822,8 @@ Editor::build_region_boundary_cache () /* finally sort to be sure that the order is correct */ sort (region_boundary_cache.begin(), region_boundary_cache.end()); + + _region_boundary_cache_dirty = false; } boost::shared_ptr<Region> @@ -7057,7 +7059,7 @@ Editor::snap_regions_to_grid () (*r)->region()->clear_changes (); MusicSample start ((*r)->region()->first_sample (), 0); - snap_to (start); + snap_to (start, RoundNearest, SnapToGrid ); (*r)->region()->set_position (start.sample, start.division); _session->add_command(new StatefulDiffCommand ((*r)->region())); } @@ -7266,7 +7268,7 @@ Editor::playhead_forward_to_grid () if (pos.sample < max_samplepos - 1) { pos.sample += 2; - snap_to_internal (pos, RoundUpAlways, false, true); + snap_to_internal (pos, RoundUpAlways, SnapToGrid, false, true); _session->request_locate (pos.sample); } } @@ -7283,7 +7285,7 @@ Editor::playhead_backward_to_grid () if (pos.sample > 2) { pos.sample -= 2; - snap_to_internal (pos, RoundDownAlways, false, true); + snap_to_internal (pos, RoundDownAlways, SnapToGrid, false, true); _session->request_locate (pos.sample); } } diff --git a/gtk2_ardour/editor_regions.cc b/gtk2_ardour/editor_regions.cc index f331b8ca4e..4dd037dee0 100644 --- a/gtk2_ardour/editor_regions.cc +++ b/gtk2_ardour/editor_regions.cc @@ -516,6 +516,15 @@ EditorRegions::remove_unused_regions () void EditorRegions::region_changed (boost::shared_ptr<Region> r, const PropertyChange& what_changed) { + //maybe update the grid here + PropertyChange grid_interests; + grid_interests.add (ARDOUR::Properties::position); + grid_interests.add (ARDOUR::Properties::length); + grid_interests.add (ARDOUR::Properties::sync_position); + if (what_changed.contains (grid_interests)) { + _editor->mark_region_boundary_cache_dirty(); + } + PropertyChange our_interests; our_interests.add (ARDOUR::Properties::name); diff --git a/gtk2_ardour/editor_rulers.cc b/gtk2_ardour/editor_rulers.cc index 661184b9ad..c9e8bbf443 100644 --- a/gtk2_ardour/editor_rulers.cc +++ b/gtk2_ardour/editor_rulers.cc @@ -585,7 +585,7 @@ Editor::update_ruler_visibility () compute_fixed_ruler_scale (); update_fixed_rulers(); - redisplay_tempo (false); + redisplay_grid (false); /* Changing ruler visibility means that any lines on markers might need updating */ for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) { @@ -989,73 +989,72 @@ Editor::compute_bbt_ruler_scale (samplepos_t lower, samplepos_t upper) bbt_ruler_scale = bbt_show_many; - switch (_snap_type) { - case SnapToBeatDiv2: + switch (_grid_type) { + case GridTypeBeatDiv2: bbt_beat_subdivision = 2; break; - case SnapToBeatDiv3: + case GridTypeBeatDiv3: bbt_beat_subdivision = 3; break; - case SnapToBeatDiv4: + case GridTypeBeatDiv4: bbt_beat_subdivision = 4; break; - case SnapToBeatDiv5: + case GridTypeBeatDiv5: bbt_beat_subdivision = 5; bbt_accent_modulo = 2; // XXX YIKES break; - case SnapToBeatDiv6: + case GridTypeBeatDiv6: bbt_beat_subdivision = 6; bbt_accent_modulo = 2; // XXX YIKES break; - case SnapToBeatDiv7: + case GridTypeBeatDiv7: bbt_beat_subdivision = 7; bbt_accent_modulo = 2; // XXX YIKES break; - case SnapToBeatDiv8: + case GridTypeBeatDiv8: bbt_beat_subdivision = 8; bbt_accent_modulo = 2; break; - case SnapToBeatDiv10: + case GridTypeBeatDiv10: bbt_beat_subdivision = 10; bbt_accent_modulo = 2; // XXX YIKES break; - case SnapToBeatDiv12: + case GridTypeBeatDiv12: bbt_beat_subdivision = 12; bbt_accent_modulo = 3; break; - case SnapToBeatDiv14: + case GridTypeBeatDiv14: bbt_beat_subdivision = 14; bbt_accent_modulo = 3; // XXX YIKES! break; - case SnapToBeatDiv16: + case GridTypeBeatDiv16: bbt_beat_subdivision = 16; bbt_accent_modulo = 4; break; - case SnapToBeatDiv20: + case GridTypeBeatDiv20: bbt_beat_subdivision = 20; bbt_accent_modulo = 5; break; - case SnapToBeatDiv24: + case GridTypeBeatDiv24: bbt_beat_subdivision = 24; bbt_accent_modulo = 6; break; - case SnapToBeatDiv28: + case GridTypeBeatDiv28: bbt_beat_subdivision = 28; bbt_accent_modulo = 7; break; - case SnapToBeatDiv32: + case GridTypeBeatDiv32: bbt_beat_subdivision = 32; bbt_accent_modulo = 8; break; - case SnapToBeatDiv64: - bbt_beat_subdivision = 64; - bbt_accent_modulo = 8; - break; - case SnapToBeatDiv128: - bbt_beat_subdivision = 128; - bbt_accent_modulo = 8; + case GridTypeBar: + case GridTypeBeat: + bbt_beat_subdivision = 4; break; - default: + case GridTypeNone: + case GridTypeSmpte: + case GridTypeMinSec: + case GridTypeSamples: bbt_beat_subdivision = 4; break; } @@ -1075,6 +1074,21 @@ Editor::compute_bbt_ruler_scale (samplepos_t lower, samplepos_t upper) bbt_bar_helper_on = true; } + //set upper limits on the beat_density based on the user's grid selection + if ( _grid_type == GridTypeBar ) { + beat_density = fmax (beat_density, 16.01); + } else if ( _grid_type == GridTypeBeat ) { + beat_density = fmax (beat_density, 4.001); + } else if ( _grid_type == GridTypeBeatDiv4) { + beat_density = fmax (beat_density, 2.001); + } else if ( _grid_type == GridTypeBeatDiv8) { + beat_density = fmax (beat_density, 1.001); + } else if ( _grid_type == GridTypeBeatDiv16) { + beat_density = fmax (beat_density, 0.2501); + } else if ( _grid_type == GridTypeBeatDiv32) { + beat_density = fmax (beat_density, 0.12501); + } + if (beat_density > 8192) { bbt_ruler_scale = bbt_show_many; } else if (beat_density > 1024) { @@ -1084,16 +1098,14 @@ Editor::compute_bbt_ruler_scale (samplepos_t lower, samplepos_t upper) } else if (beat_density > 128) { bbt_ruler_scale = bbt_show_4; } else if (beat_density > 16) { - bbt_ruler_scale = bbt_show_1; - } else if (beat_density > 2) { + bbt_ruler_scale = bbt_show_1; + } else if (beat_density > 4) { bbt_ruler_scale = bbt_show_beats; - } else if (beat_density > 0.5) { + } else if (beat_density > 1) { bbt_ruler_scale = bbt_show_ticks; - } else { + } else if (beat_density > 0.25) { bbt_ruler_scale = bbt_show_ticks_detail; - } - - if ((bbt_ruler_scale == bbt_show_ticks_detail) && beats < 3) { + } else { bbt_ruler_scale = bbt_show_ticks_super_detail; } } @@ -1713,6 +1725,10 @@ Editor::metric_get_minsec (std::vector<ArdourCanvas::Ruler::Mark>& marks, gdoubl lower = 0; } + if ( minsec_mark_interval== 0) { //we got here too early; divide-by-zero imminent + return; + } + pos = (((1000 * (samplepos_t) floor(lower)) + (minsec_mark_interval/2))/minsec_mark_interval) * minsec_mark_interval; switch (minsec_ruler_scale) { diff --git a/gtk2_ardour/editor_tempodisplay.cc b/gtk2_ardour/editor_tempodisplay.cc index 7817e419be..df4613f7be 100644 --- a/gtk2_ardour/editor_tempodisplay.cc +++ b/gtk2_ardour/editor_tempodisplay.cc @@ -48,7 +48,7 @@ #include "rgb_macros.h" #include "gui_thread.h" #include "time_axis_view.h" -#include "tempo_lines.h" +#include "grid_lines.h" #include "ui_config.h" #include "pbd/i18n.h" @@ -180,18 +180,12 @@ Editor::tempo_map_changed (const PropertyChange& /*ignored*/) ENSURE_GUI_THREAD (*this, &Editor::tempo_map_changed, ignored); - if (tempo_lines) { - tempo_lines->tempo_map_changed(_session->tempo_map().music_origin()); - } - compute_bbt_ruler_scale (_leftmost_sample, _leftmost_sample + current_page_samples()); - std::vector<TempoMap::BBTPoint> grid; - if (bbt_ruler_scale != bbt_show_many) { - compute_current_bbt_points (grid, _leftmost_sample, _leftmost_sample + current_page_samples()); - } + _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks); // redraw metric markers - draw_measures (grid); update_tempo_based_rulers (); + + maybe_draw_grid_lines (); } void @@ -203,10 +197,6 @@ Editor::tempometric_position_changed (const PropertyChange& /*ignored*/) ENSURE_GUI_THREAD (*this, &Editor::tempo_map_changed); - if (tempo_lines) { - tempo_lines->tempo_map_changed(_session->tempo_map().music_origin()); - } - TempoSection* prev_ts = 0; double max_tempo = 0.0; double min_tempo = DBL_MAX; @@ -281,18 +271,14 @@ Editor::tempometric_position_changed (const PropertyChange& /*ignored*/) } compute_bbt_ruler_scale (_leftmost_sample, _leftmost_sample + current_page_samples()); - 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); update_tempo_based_rulers (); + + maybe_draw_grid_lines (); } void -Editor::redisplay_tempo (bool immediate_redraw) +Editor::redisplay_grid (bool immediate_redraw) { if (!_session) { return; @@ -300,20 +286,12 @@ Editor::redisplay_tempo (bool immediate_redraw) if (immediate_redraw) { -//only recalculate bbt_ruler_scale on a zoom or snap-change; not every redraw; if a case is found where this is necessary, uncomment this line. -// compute_bbt_ruler_scale (_leftmost_sample, _leftmost_sample + current_page_samples()); - - 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); - update_tempo_based_rulers (); // redraw rulers and measure lines + update_tempo_based_rulers (); + update_grid(); + } else { - Glib::signal_idle().connect (sigc::bind_return (sigc::bind (sigc::mem_fun (*this, &Editor::redisplay_tempo), true), false)); + Glib::signal_idle().connect (sigc::bind_return (sigc::bind (sigc::mem_fun (*this, &Editor::redisplay_grid), true), false)); } } void @@ -379,26 +357,39 @@ Editor::compute_current_bbt_points (std::vector<TempoMap::BBTPoint>& grid, sampl } void -Editor::hide_measures () +Editor::hide_grid_lines () { - if (tempo_lines) { - tempo_lines->hide(); + if (grid_lines) { + grid_lines->hide(); } } void -Editor::draw_measures (std::vector<ARDOUR::TempoMap::BBTPoint>& grid) +Editor::maybe_draw_grid_lines () { - if (_session == 0 || _show_measures == false || distance (grid.begin(), grid.end()) == 0) { + if ( _session == 0 ) { return; } - if (tempo_lines == 0) { - tempo_lines = new TempoLines (time_line_group, ArdourCanvas::LineSet::Vertical, new BeatsSamplesConverter (_session->tempo_map(), _session->tempo_map().music_origin())); + if (grid_lines == 0) { + grid_lines = new GridLines (time_line_group, ArdourCanvas::LineSet::Vertical); + } + + grid_marks.clear(); + samplepos_t rightmost_sample = _leftmost_sample + current_page_samples(); + + if ( grid_musical() ) { + metric_get_bbt (grid_marks, _leftmost_sample, rightmost_sample, 12); + } else if (_grid_type== GridTypeSmpte) { + metric_get_timecode (grid_marks, _leftmost_sample, rightmost_sample, 12); + } else if (_grid_type == GridTypeSamples) { + metric_get_samples (grid_marks, _leftmost_sample, rightmost_sample, 12); + } else if (_grid_type == GridTypeMinSec) { + metric_get_minsec (grid_marks, _leftmost_sample, rightmost_sample, 12); } - const unsigned divisions = get_grid_beat_divisions(_leftmost_sample); - tempo_lines->draw (grid, divisions, _leftmost_sample, _session->sample_rate()); + grid_lines->draw ( grid_marks ); + grid_lines->show(); } void diff --git a/gtk2_ardour/enums.cc b/gtk2_ardour/enums.cc index 542f69dfa9..4b8a138a98 100644 --- a/gtk2_ardour/enums.cc +++ b/gtk2_ardour/enums.cc @@ -45,7 +45,7 @@ setup_gtk_ardour_enums () EditPoint edit_point; LayerDisplay layer_display; RegionListSortType region_list_sort_type; - SnapType snap_type; + GridType grid_type; SnapMode snap_mode; ZoomFocus zoom_focus; ItemType item_type; @@ -94,37 +94,28 @@ setup_gtk_ardour_enums () REGISTER_ENUM (ByTimestamp); REGISTER (region_list_sort_type); - REGISTER_ENUM (SnapToCDFrame); - REGISTER_ENUM (SnapToTimecodeFrame); - REGISTER_ENUM (SnapToTimecodeSeconds); - REGISTER_ENUM (SnapToTimecodeMinutes); - REGISTER_ENUM (SnapToSeconds); - REGISTER_ENUM (SnapToMinutes); - REGISTER_ENUM (SnapToBeatDiv128); - REGISTER_ENUM (SnapToBeatDiv64); - REGISTER_ENUM (SnapToBeatDiv32); - REGISTER_ENUM (SnapToBeatDiv28); - REGISTER_ENUM (SnapToBeatDiv24); - REGISTER_ENUM (SnapToBeatDiv20); - REGISTER_ENUM (SnapToBeatDiv16); - REGISTER_ENUM (SnapToBeatDiv14); - REGISTER_ENUM (SnapToBeatDiv12); - REGISTER_ENUM (SnapToBeatDiv10); - REGISTER_ENUM (SnapToBeatDiv8); - REGISTER_ENUM (SnapToBeatDiv7); - REGISTER_ENUM (SnapToBeatDiv6); - REGISTER_ENUM (SnapToBeatDiv5); - REGISTER_ENUM (SnapToBeatDiv4); - REGISTER_ENUM (SnapToBeatDiv3); - REGISTER_ENUM (SnapToBeatDiv2); - REGISTER_ENUM (SnapToBeat); - REGISTER_ENUM (SnapToBar); - REGISTER_ENUM (SnapToMark); - REGISTER_ENUM (SnapToRegionStart); - REGISTER_ENUM (SnapToRegionEnd); - REGISTER_ENUM (SnapToRegionSync); - REGISTER_ENUM (SnapToRegionBoundary); - REGISTER (snap_type); + REGISTER_ENUM (GridTypeNone); + REGISTER_ENUM (GridTypeBar); + REGISTER_ENUM (GridTypeBeat); + REGISTER_ENUM (GridTypeBeatDiv2); + REGISTER_ENUM (GridTypeBeatDiv4); + REGISTER_ENUM (GridTypeBeatDiv8); + REGISTER_ENUM (GridTypeBeatDiv16); + REGISTER_ENUM (GridTypeBeatDiv32); + REGISTER_ENUM (GridTypeBeatDiv3); + REGISTER_ENUM (GridTypeBeatDiv6); + REGISTER_ENUM (GridTypeBeatDiv12); + REGISTER_ENUM (GridTypeBeatDiv24); + REGISTER_ENUM (GridTypeBeatDiv5); + REGISTER_ENUM (GridTypeBeatDiv10); + REGISTER_ENUM (GridTypeBeatDiv20); + REGISTER_ENUM (GridTypeBeatDiv7); + REGISTER_ENUM (GridTypeBeatDiv14); + REGISTER_ENUM (GridTypeBeatDiv28); + REGISTER_ENUM (GridTypeSmpte); + REGISTER_ENUM (GridTypeMinSec); + REGISTER_ENUM (GridTypeSamples); + REGISTER (grid_type); REGISTER_ENUM (SnapOff); REGISTER_ENUM (SnapNormal); diff --git a/gtk2_ardour/luainstance.cc b/gtk2_ardour/luainstance.cc index 9fe03ea077..36436af285 100644 --- a/gtk2_ardour/luainstance.cc +++ b/gtk2_ardour/luainstance.cc @@ -834,7 +834,7 @@ LuaInstance::register_classes (lua_State* L) .endClass () .beginClass <PublicEditor> ("Editor") - .addFunction ("snap_type", &PublicEditor::snap_type) + .addFunction ("grid_type", &PublicEditor::grid_type) .addFunction ("snap_mode", &PublicEditor::snap_mode) .addFunction ("set_snap_mode", &PublicEditor::set_snap_mode) @@ -865,8 +865,7 @@ LuaInstance::register_classes (lua_State* L) .addFunction ("add_location_from_playhead_cursor", &PublicEditor::add_location_from_playhead_cursor) .addFunction ("remove_location_at_playhead_cursor", &PublicEditor::remove_location_at_playhead_cursor) - .addFunction ("set_show_measures", &PublicEditor::set_show_measures) - .addFunction ("show_measures", &PublicEditor::show_measures) + .addFunction ("update_grid", &PublicEditor::update_grid) .addFunction ("remove_tracks", &PublicEditor::remove_tracks) .addFunction ("set_loop_range", &PublicEditor::set_loop_range) @@ -1028,7 +1027,7 @@ LuaInstance::register_classes (lua_State* L) // Editing Symbols #undef ZOOMFOCUS -#undef SNAPTYPE +#undef GRIDTYPE #undef SNAPMODE #undef MOUSEMODE #undef DISPLAYCONTROL @@ -1037,7 +1036,7 @@ LuaInstance::register_classes (lua_State* L) #undef IMPORTDISPOSITION #define ZOOMFOCUS(NAME) .addConst (stringify(NAME), (Editing::ZoomFocus)Editing::NAME) -#define SNAPTYPE(NAME) .addConst (stringify(NAME), (Editing::SnapType)Editing::NAME) +#define GRIDTYPE(NAME) .addConst (stringify(NAME), (Editing::GridType)Editing::NAME) #define SNAPMODE(NAME) .addConst (stringify(NAME), (Editing::SnapMode)Editing::NAME) #define MOUSEMODE(NAME) .addConst (stringify(NAME), (Editing::MouseMode)Editing::NAME) #define DISPLAYCONTROL(NAME) .addConst (stringify(NAME), (Editing::DisplayControl)Editing::NAME) diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index 80ec342af5..c83e1b87ad 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -3511,7 +3511,7 @@ MidiRegionView::nudge_notes (bool forward, bool fine) next_pos.sample -= 1; } - trackview.editor().snap_to (next_pos, (forward ? RoundUpAlways : RoundDownAlways), false); + trackview.editor().snap_to (next_pos, (forward ? RoundUpAlways : RoundDownAlways), SnapToGrid, false); const samplecnt_t distance = ref_point - next_pos.sample; delta = region_samples_to_region_beats (fabs ((double)distance)); } diff --git a/gtk2_ardour/mouse_cursors.cc b/gtk2_ardour/mouse_cursors.cc index afe743a7d3..c5940e8fd0 100644 --- a/gtk2_ardour/mouse_cursors.cc +++ b/gtk2_ardour/mouse_cursors.cc @@ -44,7 +44,6 @@ MouseCursors::MouseCursors () , selector (0) , grabber (0) , grabber_note (0) - , grabber_edit_point (0) , zoom_in (0) , zoom_out (0) , time_fx (0) @@ -94,7 +93,6 @@ MouseCursors::drop_all () delete selector; selector = 0; delete grabber; grabber = 0; delete grabber_note; grabber_note = 0; - delete grabber_edit_point; grabber_edit_point = 0; delete zoom_in; zoom_in = 0; delete zoom_out; zoom_out = 0; delete time_fx; time_fx = 0; @@ -164,7 +162,6 @@ MouseCursors::set_cursor_set (const std::string& name) scissors = make_cursor ("scissors", 5, 0); grabber = make_cursor ("grabber", 5, 0); grabber_note = make_cursor ("grabber_note", 5, 10); - grabber_edit_point = make_cursor ("grabber_edit_point", 5, 17); left_side_trim = make_cursor ("trim_left_cursor", 5, 11); anchored_left_side_trim = make_cursor ("anchored_trim_left_cursor", 5, 11); right_side_trim = make_cursor ("trim_right_cursor", 23, 11); diff --git a/gtk2_ardour/mouse_cursors.h b/gtk2_ardour/mouse_cursors.h index ed29840b68..da3317dffa 100644 --- a/gtk2_ardour/mouse_cursors.h +++ b/gtk2_ardour/mouse_cursors.h @@ -48,7 +48,6 @@ public: Gdk::Cursor* selector; Gdk::Cursor* grabber; Gdk::Cursor* grabber_note; - Gdk::Cursor* grabber_edit_point; Gdk::Cursor* zoom_in; Gdk::Cursor* zoom_out; Gdk::Cursor* time_fx; diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index 6df7777818..42ec913bc1 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -133,9 +133,9 @@ public: /** Set the snap type. * @param t Snap type (defined in editing_syms.h) */ - virtual void set_snap_to (Editing::SnapType t) = 0; + virtual void set_grid_to (Editing::GridType t) = 0; - virtual Editing::SnapType snap_type () const = 0; + virtual Editing::GridType grid_type () const = 0; virtual Editing::SnapMode snap_mode () const = 0; /** Set the snap mode. @@ -149,6 +149,7 @@ public: */ virtual void snap_to (ARDOUR::MusicSample& first, ARDOUR::RoundMode direction = ARDOUR::RoundNearest, + ARDOUR::SnapPref gpref = ARDOUR::SnapToAny, bool for_mark = false, bool ensure_snap = false) = 0; @@ -219,8 +220,7 @@ public: virtual void trigger_script (int nth) = 0; virtual void add_location_from_playhead_cursor () = 0; virtual void remove_location_at_playhead_cursor () = 0; - virtual void set_show_measures (bool yn) = 0; - virtual bool show_measures () const = 0; + virtual void update_grid () = 0; virtual void remove_tracks () = 0; virtual void set_loop_range (samplepos_t start, samplepos_t end, std::string cmd) = 0; virtual void set_punch_range (samplepos_t start, samplepos_t end, std::string cmd) = 0; @@ -461,7 +461,8 @@ public: virtual void snap_to_with_modifier (ARDOUR::MusicSample& first, GdkEvent const * ev, ARDOUR::RoundMode direction = ARDOUR::RoundNearest, - bool for_mark = false) = 0; + ARDOUR::SnapPref gpref = ARDOUR::SnapToAny, + bool for_mark = false) = 0; virtual void set_snapped_cursor_position (samplepos_t pos) = 0; @@ -471,6 +472,9 @@ public: virtual void get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const = 0; virtual void get_per_region_note_selection (std::list<std::pair<PBD::ID, std::set<boost::shared_ptr<Evoral::Note<Temporal::Beats> > > > >&) const = 0; + virtual void build_region_boundary_cache () = 0; + virtual void mark_region_boundary_cache_dirty () = 0; + virtual void mouse_add_new_tempo_event (samplepos_t where) = 0; virtual void mouse_add_new_meter_event (samplepos_t where) = 0; virtual void edit_tempo_section (ARDOUR::TempoSection*) = 0; diff --git a/gtk2_ardour/quantize_dialog.cc b/gtk2_ardour/quantize_dialog.cc index a70750ae8d..178ff08b08 100644 --- a/gtk2_ardour/quantize_dialog.cc +++ b/gtk2_ardour/quantize_dialog.cc @@ -33,7 +33,7 @@ using namespace Gtkmm2ext; using namespace ARDOUR; static const gchar *_grid_strings[] = { - N_("main grid"), + N_("Main Grid"), N_("Beats/128"), N_("Beats/64"), N_("Beats/32"), diff --git a/gtk2_ardour/rc_option_editor.cc b/gtk2_ardour/rc_option_editor.cc index ce099883fe..0122e925f9 100644 --- a/gtk2_ardour/rc_option_editor.cc +++ b/gtk2_ardour/rc_option_editor.cc @@ -2306,14 +2306,6 @@ RCOptionEditor::RCOptionEditor () add_option (_("Editor"), new OptionEditorHeading (_("General"))); - add_option (_("Editor"), - new BoolOption ( - "rubberbanding-snaps-to-grid", - _("Snap rubberband to grid"), - sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_rubberbanding_snaps_to_grid), - sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_rubberbanding_snaps_to_grid) - )); - bo = new BoolOption ( "name-new-markers", _("Prompt for new marker names"), @@ -2509,6 +2501,49 @@ RCOptionEditor::RCOptionEditor () sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_snapped_cursor), sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_snapped_cursor) )); + + add_option (_("Editor/Snap"), + new BoolOption ( + "rubberbanding-snaps-to-grid", + _("Snap rubberband to grid"), + sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_rubberbanding_snaps_to_grid), + sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_rubberbanding_snaps_to_grid) + )); + + add_option (_("Editor/Snap"), new OptionEditorHeading (_("When \"Snap\" is enabled, snap to:"))); + + + add_option (_("Editor/Snap"), + new BoolOption ( + "snap-to-region-sync", + _("Region Sync Points"), + sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_to_region_sync), + sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_to_region_sync) + )); + + add_option (_("Editor/Snap"), + new BoolOption ( + "snap-to-region-start", + _("Region Starts"), + sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_to_region_start), + sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_to_region_start) + )); + + add_option (_("Editor/Snap"), + new BoolOption ( + "snap-to-region-end", + _("Region Ends"), + sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_to_region_end), + sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_to_region_end) + )); + + add_option (_("Editor/Snap"), + new BoolOption ( + "snap-to-grid", + _("Grid"), + sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_to_grid), + sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_to_grid) + )); add_option (_("Editor/Modifiers"), new OptionEditorHeading (_("Keyboard Modifiers"))); add_option (_("Editor/Modifiers"), new KeyboardOptions); diff --git a/gtk2_ardour/region_view.cc b/gtk2_ardour/region_view.cc index daca247297..c2a83a4cd9 100644 --- a/gtk2_ardour/region_view.cc +++ b/gtk2_ardour/region_view.cc @@ -948,12 +948,12 @@ RegionView::snap_sample_to_sample (sampleoffset_t x, bool ensure_snap) const /* try a snap in either direction */ MusicSample sample (session_sample, 0); - editor.snap_to (sample, RoundNearest, false, ensure_snap); + editor.snap_to (sample, RoundNearest, SnapToAny, false, ensure_snap); /* if we went off the beginning of the region, snap forwards */ if (sample.sample < _region->position ()) { sample.sample = session_sample; - editor.snap_to (sample, RoundUpAlways, false, ensure_snap); + editor.snap_to (sample, RoundUpAlways, SnapToAny, false, ensure_snap); } /* back to region relative, keeping the relevant divisor */ diff --git a/gtk2_ardour/ui_config_vars.h b/gtk2_ardour/ui_config_vars.h index f4b516495c..c1a6ef6181 100644 --- a/gtk2_ardour/ui_config_vars.h +++ b/gtk2_ardour/ui_config_vars.h @@ -103,3 +103,8 @@ UI_CONFIG_VARIABLE (std::string, stripable_color_palette, "stripable-color-palet UI_CONFIG_VARIABLE (bool, show_snapped_cursor, "show-snapped-cursor", true) UI_CONFIG_VARIABLE (uint32_t, snap_threshold, "snap-threshold", 25) +UI_CONFIG_VARIABLE (bool, snap_to_marks, "snap-to-marks", true) +UI_CONFIG_VARIABLE (bool, snap_to_region_sync, "snap-to-region-sync", true) +UI_CONFIG_VARIABLE (bool, snap_to_region_start, "snap-to-region-start", true) +UI_CONFIG_VARIABLE (bool, snap_to_region_end, "snap-to-region-end", true) +UI_CONFIG_VARIABLE (bool, snap_to_grid, "snap-to-grid", false) diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript index 411744fab9..a564c3c109 100644 --- a/gtk2_ardour/wscript +++ b/gtk2_ardour/wscript @@ -253,7 +253,7 @@ gtk2_ardour_sources = [ 'template_dialog.cc', 'tempo_curve.cc', 'tempo_dialog.cc', - 'tempo_lines.cc', + 'grid_lines.cc', 'time_axis_view.cc', 'time_axis_view_item.cc', 'time_fx_dialog.cc', |