#include "ardour/vca.h"
#include "canvas/debug.h"
+#include "canvas/note.h"
#include "canvas/text.h"
#include "widgets/ardour_spacer.h"
#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"
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_("Timecode"),
+ N_("MinSec"),
+ N_("CD Frames"),
0
};
};
#endif
-#define COMBO_TRIANGLE_WIDTH 25 // ArdourButton _diameter (11) + 2 * arrow-padding (2*2) + 2 * text-padding (2*5)
+/* Robin says: this should be odd to accomodate cairo drawing offset (width/2 rounds up to pixel boundary) */
+#ifdef __APPLE__
+#define COMBO_TRIANGLE_WIDTH 19 // ArdourButton _diameter (11) + 2 * arrow-padding (2*2) + 2 * text-padding (2*5)
+#else
+#define COMBO_TRIANGLE_WIDTH 11 // as-measured for win/linux.
+#endif
Editor::Editor ()
: PublicEditor (global_hpacker)
, 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)
, cd_mark_label (_("CD Markers"))
, videotl_label (_("Video Timeline"))
, 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)
, scrub_reverse_distance (0)
, have_pending_keyboard_selection (false)
, pending_keyboard_selection_start (0)
- , _snap_type (SnapToBeat)
+ , _grid_type (GridTypeBeat)
, _snap_mode (SnapOff)
- , snap_threshold (5.0)
, ignore_gui_changes (false)
, _drags (new DragManager (this))
, lock_dialog (0)
/* , 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)
, _ignore_region_action (false)
, _last_region_menu_was_main (false)
, _track_selection_change_without_scroll (false)
+ , _editor_track_selection_change_without_scroll (false)
, cd_marker_bar_drag_rect (0)
, range_bar_drag_rect (0)
, transport_bar_drag_rect (0)
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);
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");
_summary = new EditorSummary (this);
selection->TimeChanged.connect (sigc::mem_fun(*this, &Editor::time_selection_changed));
+ selection->TracksChanged.connect (sigc::mem_fun(*this, &Editor::track_selection_changed));
editor_regions_selection_changed_connection = selection->RegionsChanged.connect (sigc::mem_fun(*this, &Editor::region_selection_changed));
pad_line_1->set_outline_color (0xFF0000FF);
pad_line_1->show();
- // CAIROCANVAS
+ /* CAIROCANVAS */
time_pad->show();
edit_packer.set_col_spacings (0);
time_bars_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
time_bars_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
+ ArdourWidgets::ArdourDropShadow *axis_view_shadow = manage (new (ArdourWidgets::ArdourDropShadow));
+ axis_view_shadow->set_size_request (4, -1);
+ axis_view_shadow->set_name("EditorWindow");
+ axis_view_shadow->show();
+
+ edit_packer.attach (*axis_view_shadow, 0, 1, 0, 2, FILL, FILL|EXPAND, 0, 0);
+
/* labels for the time bars */
- edit_packer.attach (time_bars_event_box, 0, 1, 0, 1, FILL, SHRINK, 0, 0);
+ edit_packer.attach (time_bars_event_box, 1, 2, 0, 1, FILL, SHRINK, 0, 0);
/* track controls */
- edit_packer.attach (controls_layout, 0, 1, 1, 2, FILL, FILL|EXPAND, 0, 0);
+ edit_packer.attach (controls_layout, 1, 2, 1, 2, FILL, FILL|EXPAND, 0, 0);
/* canvas */
- edit_packer.attach (*_track_canvas_viewport, 1, 2, 0, 2, FILL|EXPAND, FILL|EXPAND, 0, 0);
+ edit_packer.attach (*_track_canvas_viewport, 2, 3, 0, 2, FILL|EXPAND, FILL|EXPAND, 0, 0);
bottom_hbox.set_border_width (2);
bottom_hbox.set_spacing (3);
VBox* summary_arrows_right = manage (new VBox);
summary_arrows_right->pack_start (*summary_arrow_right);
- Frame* summary_sample = manage (new Frame);
- summary_sample->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
+ Frame* summary_frame = manage (new Frame);
+ summary_frame->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
- summary_sample->add (*_summary);
- summary_sample->show ();
+ summary_frame->add (*_summary);
+ summary_frame->show ();
_summary_hbox.pack_start (*summary_arrows_left, false, false);
- _summary_hbox.pack_start (*summary_sample, true, true);
+ _summary_hbox.pack_start (*summary_frame, true, true);
_summary_hbox.pack_start (*summary_arrows_right, false, false);
if (!ARDOUR::Profile->get_trx()) {
}
editor_summary_pane.set_divider (0, fract);
- global_vpacker.set_spacing (2);
+ global_vpacker.set_spacing (0);
global_vpacker.set_border_width (0);
- //the next three EventBoxes provide the ability for their child widgets to have a background color. That is all.
+ /* the next three EventBoxes provide the ability for their child widgets to have a background color. That is all. */
- Gtk::EventBox* ebox = manage (new Gtk::EventBox); //a themeable box
+ Gtk::EventBox* ebox = manage (new Gtk::EventBox); // a themeable box
ebox->set_name("EditorWindow");
- ebox->add (toolbar_hbox);
+ ebox->add (ebox_hpacker);
- Gtk::EventBox* epane_box = manage (new EventBoxExt); //a themeable box
+ Gtk::EventBox* epane_box = manage (new EventBoxExt); // a themeable box
epane_box->set_name("EditorWindow");
epane_box->add (edit_pane);
- Gtk::EventBox* epane_box2 = manage (new EventBoxExt); //a themeable box
+ Gtk::EventBox* epane_box2 = manage (new EventBoxExt); // a themeable box
epane_box2->set_name("EditorWindow");
epane_box2->add (global_vpacker);
+ ArdourWidgets::ArdourDropShadow *toolbar_shadow = manage (new (ArdourWidgets::ArdourDropShadow));
+ toolbar_shadow->set_size_request (-1, 4);
+ toolbar_shadow->set_mode(ArdourWidgets::ArdourDropShadow::DropShadowBoth);
+ toolbar_shadow->set_name("EditorWindow");
+ toolbar_shadow->show();
+
+ global_vpacker.pack_start (*toolbar_shadow, false, false);
global_vpacker.pack_start (*ebox, false, false);
global_vpacker.pack_start (*epane_box, true, true);
global_hpacker.pack_start (*epane_box2, true, true);
*/
global_hpacker.show ();
+ ebox_hpacker.show();
+ ebox->show();
/* register actions now so that set_state() can find them and set toggles/checks etc */
setup_fade_images ();
+ set_grid_to (GridTypeNone);
+
instant_save ();
}
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
Editor::deferred_control_scroll (samplepos_t /*target*/)
{
_session->request_locate (*_control_scroll_target, _session->transport_rolling());
- // reset for next stream
+ /* reset for next stream */
_control_scroll_target = boost::none;
_dragging_playhead = false;
return false;
ENSURE_GUI_THREAD (*this, &Editor::access_action, action_group, action_item)
RefPtr<Action> act;
- act = ActionManager::get_action( action_group.c_str(), action_item.c_str() );
+ act = ActionManager::get_action (action_group.c_str(), action_item.c_str());
if (act) {
act->activate();
return;
}
- //initialize _leftmost_sample to the extents of the session
- //this prevents a bogus setting of leftmost = "0" if the summary view asks for the leftmost sample before the visible state has been loaded from instant.xml
+ /* initialize _leftmost_sample to the extents of the session
+ * this prevents a bogus setting of leftmost = "0" if the summary view asks for the leftmost sample
+ * before the visible state has been loaded from instant.xml */
_leftmost_sample = session_gui_extents().first;
-
+
_playlist_selector->set_session (_session);
nudge_clock->set_session (_session);
_summary->set_session (_session);
loc = _session->locations()->auto_punch_location();
if (loc != 0) {
- // force name
+ /* force name */
loc->set_name (_("Punch"));
}
refresh_location_display ();
/* This must happen after refresh_location_display(), as (amongst other things) we restore
- the selected Marker; this needs the LocationMarker list to be available.
- */
+ * the selected Marker; this needs the LocationMarker list to be available.
+ */
XMLNode* node = ARDOUR_UI::instance()->editor_settings();
set_state (*node, Stateful::loading_state_version);
_session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
_session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
+ playhead_cursor->track_canvas_item().reparent ((ArdourCanvas::Item*) get_cursor_scroll_group());
playhead_cursor->show ();
+ snapped_cursor->track_canvas_item().reparent ((ArdourCanvas::Item*) get_cursor_scroll_group());
+ snapped_cursor->set_color (UIConfiguration::instance().color ("edit point"));
+ snapped_cursor->show ();
+
boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
Config->map_parameters (pc);
_session->config.map_parameters (pc);
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);
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 GridTypeTimecode:
+ case GridTypeMinSec:
+ case GridTypeCDFrame:
+ return false;
}
-
return false;
}
+bool
+Editor::grid_nonmusical() const
+{
+ switch (_grid_type) {
+ case GridTypeTimecode:
+ case GridTypeMinSec:
+ case GridTypeCDFrame:
+ 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
{
}
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;
+ }
- if (internal_editing()) {
- internal_snap_type = st;
+ unsigned int grid_ind = (unsigned int)gt;
+
+ if (internal_editing() && UIConfiguration::instance().get_grid_follows_internal()) {
+ 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 != grid_type_selector.get_text()) {
+ grid_type_selector.set_text (str);
+ }
- if (str != snap_type_selector.get_text()) {
- snap_type_selector.set_text (str);
+ /* show appropriate rulers for this grid setting.
+ */
+ if (grid_musical()) {
+ ruler_tempo_action->set_active(true);
+ ruler_meter_action->set_active(true);
+ ruler_bbt_action->set_active(true);
+
+ if ( UIConfiguration::instance().get_rulers_follow_grid() ) {
+ ruler_timecode_action->set_active(false);
+ ruler_minsec_action->set_active(false);
+ ruler_samples_action->set_active(false);
+ }
+ } else if (_grid_type == GridTypeTimecode) {
+ ruler_timecode_action->set_active(true);
+
+ if ( UIConfiguration::instance().get_rulers_follow_grid() ) {
+ ruler_tempo_action->set_active(false);
+ ruler_meter_action->set_active(false);
+ ruler_bbt_action->set_active(false);
+ ruler_minsec_action->set_active(false);
+ ruler_samples_action->set_active(false);
+ }
+ } else if (_grid_type == GridTypeMinSec) {
+ ruler_minsec_action->set_active(true);
+
+ if ( UIConfiguration::instance().get_rulers_follow_grid() ) {
+ 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_samples_action->set_active(false);
+ }
+ } else if (_grid_type == GridTypeCDFrame) {
+ ruler_cd_marker_action->set_active(true);
+ ruler_minsec_action->set_active(true);
+
+ if ( UIConfiguration::instance().get_rulers_follow_grid() ) {
+ 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_samples_action->set_active(false);
+ }
}
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 */
}
void
Editor::set_snap_mode (SnapMode mode)
{
- string str = snap_mode_strings[(int)mode];
-
if (internal_editing()) {
internal_snap_mode = mode;
} else {
_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 ();
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)) {
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;
set_edit_point_preference (_edit_point);
}
- node.get_property ("show-measures", _show_measures);
-
if (node.get_property ("follow-playhead", yn)) {
set_follow_playhead (yn);
}
*/
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) {
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);
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);
}
if (y < 0) {
- return std::make_pair ( (TimeAxisView *) 0, 0);
+ return std::make_pair ((TimeAxisView *) 0, 0);
}
for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
}
}
- return std::make_pair ( (TimeAxisView *) 0, 0);
+ return std::make_pair ((TimeAxisView *) 0, 0);
+}
+
+void
+Editor::set_snapped_cursor_position (samplepos_t pos)
+{
+ if (_edit_point == EditAtMouse) {
+ snapped_cursor->set_position(pos);
+ }
}
+
/** Snap a position to the grid, if appropriate, taking into account current
* grid settings and also the state of any snap modifier keys that may be pressed.
* @param start Position to snap.
* @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;
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);
}
}
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;
+ if (marks.empty()) return presnap;
+
samplepos_t before;
samplepos_t after;
+ samplepos_t test = presnap;
- 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 = 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 grid 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 ( (pref == SnapToAny) && 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 (
+ (pref == SnapToAny) &&
+ (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);
- } else {
- next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start.sample);
- }
-
+ vector<samplepos_t>::iterator prev = region_boundary_cache.begin();
+ vector<samplepos_t>::iterator next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), presnap);
if (next != region_boundary_cache.begin ()) {
prev = next;
prev--;
}
- 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;
- } else {
- start.sample = p;
+ if ((direction == RoundUpMaybe || direction == RoundUpAlways))
+ test = *next;
+ else if ((direction == RoundDownMaybe || direction == RoundDownAlways))
+ test = *prev;
+ else if (direction == 0) {
+ if ((presnap - *prev) < (*next - presnap)) {
+ test = *prev;
+ } else {
+ test = *next;
+ }
}
+
}
- start.set (start.sample, 0);
+ check_best_snap(presnap, test, dist, best);
+ }
- break;
+ /* check Grid */
+ if (UIConfiguration::instance().get_snap_to_grid() && (_grid_type != GridTypeNone)) {
+ test = snap_to_grid (grid_marks, presnap, direction);
+ check_best_snap(presnap, test, dist, best);
}
- switch (_snap_mode) {
- case SnapNormal:
+ /* 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;
-
- case SnapMagnetic:
-
- if (ensure_snap) {
- return;
+ } else if (presnap > best) {
+ if (presnap > (best+ snap_threshold_s)) {
+ best = presnap;
}
-
- if (presnap > start.sample) {
- if (presnap > (start.sample + pixel_to_sample(snap_threshold))) {
- start.set (presnap, 0);
- }
-
- } else if (presnap < start.sample) {
- if (presnap < (start.sample - pixel_to_sample(snap_threshold))) {
- start.set (presnap, 0);
- }
+ } else if (presnap < best) {
+ if (presnap < (best - snap_threshold_s)) {
+ best = presnap;
}
-
- default:
- /* handled at entry */
- return;
}
+
+ start.set (best, 0);
}
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);
if (!ARDOUR::Profile->get_mixbus()) {
mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
+ mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
}
if (!ARDOUR::Profile->get_trx()) {
mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
- mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
mouse_mode_hbox->pack_start (mouse_content_button, false, false);
}
if (!ARDOUR::Profile->get_trx()) {
mode_box->pack_start (edit_mode_selector, false, false);
+ mode_box->pack_start (*(manage (new ArdourVSpacer ())), false, false, 3);
+ mode_box->pack_start (edit_point_selector, false, false);
+ mode_box->pack_start (*(manage (new ArdourVSpacer ())), false, false, 3);
}
mode_box->pack_start (*mouse_mode_box, false, false);
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);
-
- /* Edit Point*/
- HBox *ep_box = manage (new HBox);
- ep_box->set_spacing (2);
- ep_box->set_border_width (2);
-
- ep_box->pack_start (edit_point_selector, false, false);
+ snap_box.pack_start (snap_mode_button, false, false);
+ snap_box.pack_start (grid_type_selector, false, false);
/* Nudge */
toolbar_hbox.set_spacing (2);
toolbar_hbox.set_border_width (2);
- toolbar_hbox.pack_start (*mode_box, false, false);
+ ArdourWidgets::ArdourDropShadow *tool_shadow = manage (new (ArdourWidgets::ArdourDropShadow));
+ tool_shadow->set_size_request (4, -1);
+ tool_shadow->show();
- if (!ARDOUR::Profile->get_trx()) {
+ ebox_hpacker.pack_start (*tool_shadow, false, false);
+ ebox_hpacker.pack_start(ebox_vpacker, true, true);
- toolbar_hbox.pack_start (*(manage (new ArdourVSpacer ())), false, false, 3);
+ Gtk::EventBox* spacer = manage (new Gtk::EventBox); // extra space under the mouse toolbar, for aesthetics
+ spacer->set_name("EditorWindow");
+ spacer->set_size_request(-1,4);
+ spacer->show();
- toolbar_hbox.pack_start (_zoom_box, false, false);
+ ebox_vpacker.pack_start(toolbar_hbox, false, false);
+ ebox_vpacker.pack_start(*spacer, false, false);
+ ebox_vpacker.show();
- toolbar_hbox.pack_start (*(manage (new ArdourVSpacer ())), false, false, 3);
+ toolbar_hbox.pack_start (*mode_box, false, false);
- toolbar_hbox.pack_start (_track_box, false, false);
+ if (!ARDOUR::Profile->get_trx()) {
toolbar_hbox.pack_start (*(manage (new ArdourVSpacer ())), false, false, 3);
toolbar_hbox.pack_start (*(manage (new ArdourVSpacer ())), false, false, 3);
- toolbar_hbox.pack_start (*ep_box, false, false);
+ toolbar_hbox.pack_start (*nudge_box, false, false);
- toolbar_hbox.pack_start (*(manage (new ArdourVSpacer ())), false, false, 3);
+ toolbar_hbox.pack_end (_zoom_box, false, false, 2);
+
+ toolbar_hbox.pack_end (*(manage (new ArdourVSpacer ())), false, false, 3);
+
+ toolbar_hbox.pack_end (_track_box, false, false);
- toolbar_hbox.pack_start (*nudge_box, false, false);
}
toolbar_hbox.show_all ();
{
using namespace Menu_Helpers;
- edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
+ edit_point_selector.AddMenuElem (MenuElem (edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
if(!Profile->get_mixbus())
- edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
- edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
+ edit_point_selector.AddMenuElem (MenuElem (edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
+ edit_point_selector.AddMenuElem (MenuElem (edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
set_size_request_to_display_given_text (edit_point_selector, edit_point_strings, COMBO_TRIANGLE_WIDTH, 2);
}
{
using namespace Menu_Helpers;
- edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
-// edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Splice], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
- edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
- edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Lock], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
+ edit_mode_selector.AddMenuElem (MenuElem (edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
+ edit_mode_selector.AddMenuElem (MenuElem (edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
+ edit_mode_selector.AddMenuElem (MenuElem (edit_mode_strings[(int)Lock], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
+ /* Note: Splice was removed */
set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
}
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)));
-
- set_size_request_to_display_given_text (snap_mode_selector, snap_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
-}
+ /* 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));
-void
-Editor::build_snap_type_menu ()
-{
- using namespace Menu_Helpers;
+ /* 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));
- 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);
+ /* 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));
+ grid_type_selector.AddMenuElem(SeparatorElem());
+ grid_type_selector.AddMenuElem (MenuElem (grid_type_strings[(int)GridTypeTimecode], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeTimecode)));
+ 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)GridTypeCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeCDFrame)));
}
void
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)"));
if (selection_op_cmd_depth == 1) {
if (selection_op_history_it > 0 && selection_op_history_it < selection_op_history.size()) {
- /**
- The user has undone some selection ops and then made a new one,
- making anything earlier in the list invalid.
- */
+ /* The user has undone some selection ops and then made a new one,
+ * making anything earlier in the list invalid.
+ */
list<XMLNode *>::iterator it = selection_op_history.begin();
list<XMLNode *>::iterator e_it = it;
advance (e_it, selection_op_history_it);
- for ( ; it != e_it; ++it) {
+ for (; it != e_it; ++it) {
delete *it;
}
selection_op_history.erase (selection_op_history.begin(), e_it);
RegionSelection rs = get_regions_from_selection_and_entered ();
- if ( selection->time.length() == 0 && rs.empty()) {
+ if (selection->time.length() == 0 && rs.empty()) {
return;
}
times = adjustment.get_value();
}
- if ((current_mouse_mode() == Editing::MouseRange)) {
+ if ((current_mouse_mode() == MouseRange)) {
if (selection->time.length()) {
duplicate_selection (times);
}
}
void
-Editor::edit_mode_selection_done ( EditMode m )
+Editor::edit_mode_selection_done (EditMode m)
{
- Config->set_edit_mode ( m );
+ Config->set_edit_mode (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 ();
}
void
Editor::edit_point_selection_done (EditPoint ep)
{
- set_edit_point_preference ( ep );
+ set_edit_point_preference (ep);
}
void
{
using namespace Menu_Helpers;
- zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
- zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
- zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
- zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
- zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
- zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
+ zoom_focus_selector.AddMenuElem (MenuElem (zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
+ zoom_focus_selector.AddMenuElem (MenuElem (zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
+ zoom_focus_selector.AddMenuElem (MenuElem (zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
+ zoom_focus_selector.AddMenuElem (MenuElem (zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
+ zoom_focus_selector.AddMenuElem (MenuElem (zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
+ zoom_focus_selector.AddMenuElem (MenuElem (zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
set_size_request_to_display_given_text (zoom_focus_selector, zoom_focus_strings, COMBO_TRIANGLE_WIDTH, 2);
}
void
-Editor::zoom_focus_selection_done ( ZoomFocus f )
+Editor::zoom_focus_selection_done (ZoomFocus f)
{
RefPtr<RadioAction> ract = zoom_focus_action (f);
if (ract) {
void
Editor::set_zoom_preset (int64_t ms)
{
- if ( ms <= 0 ) {
+ if (ms <= 0) {
temporal_zoom_session();
return;
}
ARDOUR::samplecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
- temporal_zoom( (sample_rate * ms / 1000) / _visible_canvas_width );
+ temporal_zoom ((sample_rate * ms / 1000) / _visible_canvas_width);
}
void
Editor::override_visible_track_count ()
{
_visible_track_count = -1;
- visible_tracks_selector.set_text ( _("*") );
+ visible_tracks_selector.set_text (_("*"));
}
bool
}
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 ();
}
}
{
if (_stationary_playhead != yn) {
if ((_stationary_playhead = yn) == true) {
- /* catch up */
- // FIXME need a 3.0 equivalent of this 2.X call
+ /* catch up -- FIXME need a 3.0 equivalent of this 2.X call */
// update_current_screen ();
}
instant_save ();
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 GridTypeTimecode: return 0;
+ case GridTypeMinSec: return 0;
+ case GridTypeCDFrame: return 0;
+ default: return 0;
}
return 0;
}
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 GridTypeTimecode: return 0;
+ case GridTypeMinSec: return 0;
+ case GridTypeCDFrame: return 0;
}
return 0;
}
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());
dialog.add_button (_("Keep Remaining"), RESPONSE_NO); // ditto
dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
- // by default gtk uses the left most button
+ /* by default gtk uses the left most button */
keep->grab_focus ();
switch (dialog.run ()) {
VisualState* vs = redo_visual_stack.back();
redo_visual_stack.pop_back();
- // can 'vs' really be 0? Is there a place that puts NULL pointers onto the stack?
- // why do we check here?
+ /* XXX: can 'vs' really be 0? Is there a place that puts NULL pointers onto the stack? */
undo_visual_stack.push_back (current_visual_state (vs ? (vs->gui_state != 0) : false));
if (vs) {
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 ()) {
Editor::ensure_visual_change_idle_handler ()
{
if (pending_visual_change.idle_handler_id < 0) {
- // see comment in add_to_idle_resize above.
+ /* see comment in add_to_idle_resize above. */
pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_visual_changer, this, NULL);
pending_visual_change.being_handled = false;
}
}
if (!(vc.pending & VisualChange::ZoomLevel)) {
- /**
- * If the canvas is not being zoomed then the canvas items will not change
+ /* If the canvas is not being zoomed then the canvas items will not change
* and cause Item::prepare_for_render to be called so do it here manually.
- *
* Not ideal, but I can't think of a better solution atm.
*/
_track_canvas->prepare_for_render();
}
- // If we are only scrolling vertically there is no need to update these
+ /* 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.
return entered_marker->position();
}
- if ( (ignore==EDIT_IGNORE_PHEAD) && ep == EditAtPlayhead) {
+ if ((ignore == EDIT_IGNORE_PHEAD) && ep == EditAtPlayhead) {
ep = EditAtSelectedMarker;
}
- if ( (ignore==EDIT_IGNORE_MOUSE) && ep == EditAtMouse) {
+ if ((ignore == EDIT_IGNORE_MOUSE) && ep == EditAtMouse) {
ep = EditAtPlayhead;
}
switch (ep) {
case EditAtPlayhead:
- if (_dragging_playhead && _control_scroll_target) {
- where = *_control_scroll_target;
+ if (_dragging_playhead) {
+ /* NOTE: since the user is dragging with the mouse, this operation will implicitly be Snapped */
+ where = playhead_cursor->current_sample();
} else {
where = _session->audible_sample();
}
{
RegionSelection regions;
- if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
+ if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty()) {
regions.add (entered_regionview);
} else {
regions = selection->regions;
}
- if ( regions.empty() ) {
+ if (regions.empty()) {
TrackViewList tracks = selection->tracks;
if (!tracks.empty()) {
{
RegionSelection regions;
- if (entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
+ if (entered_regionview && selection->tracks.empty() && selection->regions.empty()) {
regions.add (entered_regionview);
} else {
regions = selection->regions;
}
- if ( regions.empty() ) {
+ if (regions.empty()) {
TrackViewList tracks = selection->tracks;
if (!tracks.empty()) {
selection->set (rs);
- // first idle adds route children (automation tracks), so we need to redisplay here
+ /* first idle adds route children (automation tracks), so we need to redisplay here */
_routes->redisplay ();
delete dialog;
}
_summary->set_background_dirty ();
+
+ mark_region_boundary_cache_dirty ();
}
void
Editor::region_view_removed ()
{
_summary->set_background_dirty ();
+
+ mark_region_boundary_cache_dirty ();
}
AxisView*
PresentationInfo::ChangeSuspender cs;
if (apply_to_selection) {
- for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
+ for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end();) {
TrackSelection::iterator j = i;
++j;
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
- // this will hide the mixer strip
+ /* this will hide the mixer strip */
set_selected_mixer_strip (*tv);
}
current_mixer_strip->fast_update ();
}
- /* PLAYHEAD AND VIEWPORT */
-
- /* 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
- * when the editor requests a locate there is a chance that this method
- * will move the playhead before the locate request is processed, causing
- * a visual glitch.
- * 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
- * 3. if we're still at the same sample that we were last time, there's nothing to do.
- */
- if (_pending_locate_request || !_session->transport_rolling ()) {
- _last_update_time = 0;
- return;
- }
-
- if (_dragging_playhead) {
- _last_update_time = 0;
- return;
- }
-
bool latent_locate = false;
samplepos_t sample = _session->audible_sample (&latent_locate);
const int64_t now = g_get_monotonic_time ();
_last_update_time = 0;
}
+ if (!_session->transport_rolling ()) {
+ /* Do not interpolate the playhead position; just set it */
+ _last_update_time = 0;
+ }
+
if (_last_update_time > 0) {
/* interpolate and smoothen playhead position */
const double ds = (now - _last_update_time) * _session->transport_speed() * _session->nominal_sample_rate () * 1e-6;
_last_update_time = now;
}
+ /* snapped cursor stuff (the snapped_cursor shows where an operation is going to occur) */
+ bool ignored;
+ MusicSample where (sample, 0);
+ if (!UIConfiguration::instance().get_show_snapped_cursor()) {
+ snapped_cursor->hide ();
+ } else if (_edit_point == EditAtPlayhead && !_dragging_playhead) {
+ /* EditAtPlayhead does not snap */
+ } else if (_edit_point == EditAtSelectedMarker) {
+ /* NOTE: I don't think EditAtSelectedMarker should snap. They are what they are.
+ * however, the current editing code -does- snap so I'll draw it that way for now.
+ */
+ if (!selection->markers.empty()) {
+ MusicSample ms (selection->markers.front()->position(), 0);
+ snap_to (ms); // should use snap_to_with_modifier?
+ snapped_cursor->set_position (ms.sample);
+ snapped_cursor->show ();
+ }
+ } else if (mouse_sample (where.sample, ignored)) { // cursor is in the editing canvas. show it.
+ snapped_cursor->show ();
+ } 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
+ * when the editor requests a locate there is a chance that this method
+ * will move the playhead before the locate request is processed, causing
+ * a visual glitch.
+ * 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
+ * 3. if we're still at the same frame that we were last time, there's nothing to do.
+ */
+ if (_pending_locate_request) {
+ _last_update_time = 0;
+ return;
+ }
+
+ if (_dragging_playhead) {
+ _last_update_time = 0;
+ return;
+ }
+
if (playhead_cursor->current_sample () == sample) {
return;
}
if (target <= 0.0) {
target = 0.0;
}
- // compare to EditorCursor::set_position()
+ /* compare to EditorCursor::set_position() */
double const old_pos = sample_to_pixel_unrounded (_leftmost_sample);
double const new_pos = sample_to_pixel_unrounded (target);
if (rint (new_pos) != rint (old_pos)) {
/* 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 ();
if (_verbose_cursor) {
playhead_cursor->set_sensitive (UIConfiguration::instance().get_draggable_playhead());
}
+ } else if (parameter == "use-note-bars-for-velocity") {
+ ArdourCanvas::Note::set_show_velocity_bars (UIConfiguration::instance().get_use_note_bars_for_velocity());
+ _track_canvas->request_redraw (_track_canvas->visible_area());
+ } else if (parameter == "use-note-color-for-velocity") {
+ /* handled individually by each MidiRegionView */
}
}