13
0

Relative snap

This commit is contained in:
nick_m 2015-05-16 04:15:52 +10:00
parent e73b4e6f55
commit 68a8330afc
14 changed files with 369 additions and 59 deletions

View File

@ -222,6 +222,9 @@
<menuitem action='cycle-edit-point-with-marker'/> <menuitem action='cycle-edit-point-with-marker'/>
</menu> </menu>
<menu name='SnapMode' action='SnapMode'> <menu name='SnapMode' action='SnapMode'>
<menuitem action='snap-absolute'/>
<menuitem action='snap-relative'/>
<separator/>
<menuitem action='snap-off'/> <menuitem action='snap-off'/>
<menuitem action='snap-normal'/> <menuitem action='snap-normal'/>
<menuitem action='snap-magnetic'/> <menuitem action='snap-magnetic'/>

View File

@ -29,6 +29,7 @@ using namespace std;
// This involves some cpp magic. --taybin // This involves some cpp magic. --taybin
#define SNAPTYPE(a) /*empty*/ #define SNAPTYPE(a) /*empty*/
#define SNAPDELTA(a) /*empty*/
#define SNAPMODE(a) /*empty*/ #define SNAPMODE(a) /*empty*/
#define REGIONLISTSORTTYPE(a) /*empty*/ #define REGIONLISTSORTTYPE(a) /*empty*/
#define MOUSEMODE(a) /*empty*/ #define MOUSEMODE(a) /*empty*/
@ -57,6 +58,27 @@ const char *snaptypestrs[] = {
#undef SNAPTYPE #undef SNAPTYPE
#define SNAPTYPE(a) /*empty*/ #define SNAPTYPE(a) /*empty*/
// SNAPDELTA
#undef SNAPDELTA
#define SNAPDELTA(s) if (!strcmp(type, #s)) {return s;}
SnapDelta
str2snapdelta (const string & str) {
const char* type = str.c_str();
#include "editing_syms.h"
return SnapAbsolute;
}
#undef SNAPDELTA
#define SNAPDELTA(s) N_(#s),
const char *snapdeltastrs[] = {
#include "editing_syms.h"
0
};
#undef SNAPDELTA
#define SNAPDELTA(a) /*empty*/
// SNAPMODE // SNAPMODE
#undef SNAPMODE #undef SNAPMODE
#define SNAPMODE(s) if (!strcmp(type, #s)) {return s;} #define SNAPMODE(s) if (!strcmp(type, #s)) {return s;}

View File

@ -28,6 +28,7 @@
#define SNAPTYPE(a) /*empty*/ #define SNAPTYPE(a) /*empty*/
#define SNAPMODE(a) /*empty*/ #define SNAPMODE(a) /*empty*/
#define SNAPDELTA(a) /*empty*/
#define REGIONLISTSORTTYPE(a) /*empty*/ #define REGIONLISTSORTTYPE(a) /*empty*/
#define MOUSEMODE(a) /*empty*/ #define MOUSEMODE(a) /*empty*/
#define MIDIEDITMODE(a) /*empty*/ #define MIDIEDITMODE(a) /*empty*/
@ -71,6 +72,19 @@ SnapMode str2snapmode(const std::string &);
#undef SNAPMODE #undef SNAPMODE
#define SNAPMODE(a) /*empty*/ #define SNAPMODE(a) /*empty*/
// SNAPDELTA
#undef SNAPDELTA
#define SNAPDELTA(a) a,
enum SnapDelta {
#include "editing_syms.h"
};
extern const char *snapdeltastrs[];
inline const char* enum2str(SnapDelta m) {return snapdeltastrs[m];}
SnapDelta str2snapdelta(const std::string &);
#undef SNAPDELTA
#define SNAPDELTA(a) /*empty*/
// REGIONLISTSORTTYPE // REGIONLISTSORTTYPE
#undef REGIONLISTSORTTYPE #undef REGIONLISTSORTTYPE
#define REGIONLISTSORTTYPE(a) a, #define REGIONLISTSORTTYPE(a) a,

View File

@ -54,6 +54,9 @@ SNAPMODE(SnapOff)
SNAPMODE(SnapNormal) SNAPMODE(SnapNormal)
SNAPMODE(SnapMagnetic) SNAPMODE(SnapMagnetic)
SNAPDELTA(SnapAbsolute)
SNAPDELTA(SnapRelative)
REGIONLISTSORTTYPE(ByEndInFile) REGIONLISTSORTTYPE(ByEndInFile)
REGIONLISTSORTTYPE(ByLength) REGIONLISTSORTTYPE(ByLength)
REGIONLISTSORTTYPE(ByName) REGIONLISTSORTTYPE(ByName)

View File

@ -177,6 +177,12 @@ static const gchar *_snap_type_strings[] = {
0 0
}; };
static const gchar *_snap_delta_strings[] = {
N_("Absolute"),
N_("Relative"),
0
};
static const gchar *_snap_mode_strings[] = { static const gchar *_snap_mode_strings[] = {
N_("No Grid"), N_("No Grid"),
N_("Grid"), N_("Grid"),
@ -329,6 +335,7 @@ Editor::Editor ()
tempo_lines = 0; tempo_lines = 0;
snap_type_strings = I18N (_snap_type_strings); snap_type_strings = I18N (_snap_type_strings);
snap_delta_strings = I18N (_snap_delta_strings);
snap_mode_strings = I18N (_snap_mode_strings); snap_mode_strings = I18N (_snap_mode_strings);
zoom_focus_strings = I18N (_zoom_focus_strings); zoom_focus_strings = I18N (_zoom_focus_strings);
edit_mode_strings = I18N (_edit_mode_strings); edit_mode_strings = I18N (_edit_mode_strings);
@ -341,6 +348,7 @@ Editor::Editor ()
build_edit_mode_menu(); build_edit_mode_menu();
build_zoom_focus_menu(); build_zoom_focus_menu();
build_track_count_menu(); build_track_count_menu();
build_snap_delta_menu();
build_snap_mode_menu(); build_snap_mode_menu();
build_snap_type_menu(); build_snap_type_menu();
build_edit_point_menu(); build_edit_point_menu();
@ -678,6 +686,8 @@ Editor::Editor ()
set_visible_track_count (_visible_track_count); set_visible_track_count (_visible_track_count);
_snap_type = SnapToBeat; _snap_type = SnapToBeat;
set_snap_to (_snap_type); set_snap_to (_snap_type);
_snap_delta = SnapAbsolute;
set_snap_delta (_snap_delta);
_snap_mode = SnapOff; _snap_mode = SnapOff;
set_snap_mode (_snap_mode); set_snap_mode (_snap_mode);
set_mouse_mode (MouseObject, true); set_mouse_mode (MouseObject, true);
@ -2036,6 +2046,12 @@ Editor::snap_type() const
return _snap_type; return _snap_type;
} }
SnapDelta
Editor::snap_delta() const
{
return _snap_delta;
}
SnapMode SnapMode
Editor::snap_mode() const Editor::snap_mode() const
{ {
@ -2114,6 +2130,20 @@ Editor::set_snap_to (SnapType st)
SnapChanged (); /* EMIT SIGNAL */ SnapChanged (); /* EMIT SIGNAL */
} }
void
Editor::set_snap_delta (SnapDelta delta)
{
string str = snap_delta_strings[(int)delta];
_snap_delta = delta;
if (str != snap_delta_selector.get_text ()) {
snap_delta_selector.set_text (str);
}
instant_save ();
}
void void
Editor::set_snap_mode (SnapMode mode) Editor::set_snap_mode (SnapMode mode)
{ {
@ -2133,6 +2163,7 @@ Editor::set_snap_mode (SnapMode mode)
instant_save (); instant_save ();
} }
void void
Editor::set_edit_point_preference (EditPoint ep, bool force) Editor::set_edit_point_preference (EditPoint ep, bool force)
{ {
@ -2272,6 +2303,10 @@ Editor::set_state (const XMLNode& node, int /*version*/)
snap_type_selection_done ((SnapType) string_2_enum (prop->value(), _snap_type)); snap_type_selection_done ((SnapType) string_2_enum (prop->value(), _snap_type));
} }
if ((prop = node.property ("snap-delta"))) {
snap_delta_selection_done((SnapDelta) string_2_enum (prop->value(), _snap_delta));
}
if ((prop = node.property ("snap-mode"))) { if ((prop = node.property ("snap-mode"))) {
snap_mode_selection_done((SnapMode) string_2_enum (prop->value(), _snap_mode)); snap_mode_selection_done((SnapMode) string_2_enum (prop->value(), _snap_mode));
} }
@ -2497,6 +2532,7 @@ Editor::get_state ()
snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel); snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel);
node->add_property ("zoom", buf); node->add_property ("zoom", buf);
node->add_property ("snap-to", enum_2_string (_snap_type)); node->add_property ("snap-to", enum_2_string (_snap_type));
node->add_property ("snap-delta", enum_2_string (_snap_delta));
node->add_property ("snap-mode", enum_2_string (_snap_mode)); node->add_property ("snap-mode", enum_2_string (_snap_mode));
node->add_property ("internal-snap-to", enum_2_string (internal_snap_type)); node->add_property ("internal-snap-to", enum_2_string (internal_snap_type));
node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode)); node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode));
@ -2906,6 +2942,7 @@ Editor::setup_toolbar ()
mouse_mode_size_group->add_widget (visible_tracks_selector); 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_type_selector);
mouse_mode_size_group->add_widget (snap_delta_selector);
mouse_mode_size_group->add_widget (snap_mode_selector); mouse_mode_size_group->add_widget (snap_mode_selector);
mouse_mode_size_group->add_widget (edit_point_selector); mouse_mode_size_group->add_widget (edit_point_selector);
@ -3058,10 +3095,12 @@ Editor::setup_toolbar ()
snap_type_selector.set_name ("mouse mode button"); snap_type_selector.set_name ("mouse mode button");
snap_delta_selector.set_name ("mouse mode button");
snap_mode_selector.set_name ("mouse mode button"); snap_mode_selector.set_name ("mouse mode button");
edit_point_selector.set_name ("mouse mode button"); edit_point_selector.set_name ("mouse mode button");
snap_box.pack_start (snap_delta_selector, false, false);
snap_box.pack_start (snap_mode_selector, false, false); snap_box.pack_start (snap_mode_selector, false, false);
snap_box.pack_start (snap_type_selector, false, false); snap_box.pack_start (snap_type_selector, false, false);
snap_box.pack_start (edit_point_selector, false, false); snap_box.pack_start (edit_point_selector, false, false);
@ -3161,6 +3200,17 @@ Editor::build_edit_mode_menu ()
set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, COMBO_TRIANGLE_WIDTH, 2); set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
} }
void
Editor::build_snap_delta_menu ()
{
using namespace Menu_Helpers;
snap_delta_selector.AddMenuElem (MenuElem ( snap_delta_strings[(int)SnapAbsolute], sigc::bind (sigc::mem_fun(*this, &Editor::snap_delta_selection_done), (SnapDelta) SnapAbsolute)));
snap_delta_selector.AddMenuElem (MenuElem ( snap_delta_strings[(int)SnapRelative], sigc::bind (sigc::mem_fun(*this, &Editor::snap_delta_selection_done), (SnapDelta) SnapRelative)));
set_size_request_to_display_given_text (snap_delta_selector, snap_delta_strings, COMBO_TRIANGLE_WIDTH, 2);
}
void void
Editor::build_snap_mode_menu () Editor::build_snap_mode_menu ()
{ {
@ -3236,6 +3286,7 @@ Editor::setup_tooltips ()
ARDOUR_UI::instance()->set_tip (tav_shrink_button, _("Shrink Tracks")); ARDOUR_UI::instance()->set_tip (tav_shrink_button, _("Shrink Tracks"));
ARDOUR_UI::instance()->set_tip (visible_tracks_selector, _("Number of visible tracks")); ARDOUR_UI::instance()->set_tip (visible_tracks_selector, _("Number of visible tracks"));
ARDOUR_UI::instance()->set_tip (snap_type_selector, _("Snap/Grid Units")); ARDOUR_UI::instance()->set_tip (snap_type_selector, _("Snap/Grid Units"));
ARDOUR_UI::instance()->set_tip (snap_delta_selector, _("Relative Snap Mode"));
ARDOUR_UI::instance()->set_tip (snap_mode_selector, _("Snap/Grid Mode")); ARDOUR_UI::instance()->set_tip (snap_mode_selector, _("Snap/Grid Mode"));
ARDOUR_UI::instance()->set_tip (edit_point_selector, _("Edit point")); ARDOUR_UI::instance()->set_tip (edit_point_selector, _("Edit point"));
ARDOUR_UI::instance()->set_tip (edit_mode_selector, _("Edit Mode")); ARDOUR_UI::instance()->set_tip (edit_mode_selector, _("Edit Mode"));
@ -3632,6 +3683,16 @@ Editor::snap_type_selection_done (SnapType snaptype)
} }
} }
void
Editor::snap_delta_selection_done (SnapDelta delta)
{
RefPtr<RadioAction> ract = snap_delta_action (delta);
if (ract) {
ract->set_active (true);
}
}
void void
Editor::snap_mode_selection_done (SnapMode mode) Editor::snap_mode_selection_done (SnapMode mode)
{ {

View File

@ -162,9 +162,11 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void prev_snap_choice_music_only (); void prev_snap_choice_music_only ();
void prev_snap_choice_music_and_time (); void prev_snap_choice_music_and_time ();
void set_snap_to (Editing::SnapType); void set_snap_to (Editing::SnapType);
void set_snap_delta (Editing::SnapDelta);
void set_snap_mode (Editing::SnapMode); void set_snap_mode (Editing::SnapMode);
void set_snap_threshold (double pixel_distance) {snap_threshold = pixel_distance;} void set_snap_threshold (double pixel_distance) {snap_threshold = pixel_distance;}
Editing::SnapDelta snap_delta () const;
Editing::SnapMode snap_mode () const; Editing::SnapMode snap_mode () const;
Editing::SnapType snap_type () const; Editing::SnapType snap_type () const;
@ -1471,6 +1473,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void move_range_selection_start_or_end_to_region_boundary (bool, bool); void move_range_selection_start_or_end_to_region_boundary (bool, bool);
Editing::SnapType _snap_type; Editing::SnapType _snap_type;
Editing::SnapDelta _snap_delta;
Editing::SnapMode _snap_mode; Editing::SnapMode _snap_mode;
/// Snap threshold in pixels /// Snap threshold in pixels
@ -1751,19 +1754,25 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
ArdourDropdown snap_type_selector; ArdourDropdown snap_type_selector;
void build_snap_type_menu (); void build_snap_type_menu ();
ArdourDropdown snap_delta_selector;
ArdourDropdown snap_mode_selector; ArdourDropdown snap_mode_selector;
void build_snap_delta_menu ();
void build_snap_mode_menu (); void build_snap_mode_menu ();
Gtk::HBox snap_box; Gtk::HBox snap_box;
std::vector<std::string> snap_type_strings; std::vector<std::string> snap_type_strings;
std::vector<std::string> snap_delta_strings;
std::vector<std::string> snap_mode_strings; std::vector<std::string> snap_mode_strings;
void snap_type_selection_done (Editing::SnapType); void snap_type_selection_done (Editing::SnapType);
void snap_delta_selection_done (Editing::SnapDelta);
void snap_mode_selection_done (Editing::SnapMode); void snap_mode_selection_done (Editing::SnapMode);
void snap_delta_chosen (Editing::SnapDelta);
void snap_mode_chosen (Editing::SnapMode); void snap_mode_chosen (Editing::SnapMode);
void snap_type_chosen (Editing::SnapType); void snap_type_chosen (Editing::SnapType);
Glib::RefPtr<Gtk::RadioAction> snap_type_action (Editing::SnapType); Glib::RefPtr<Gtk::RadioAction> snap_type_action (Editing::SnapType);
Glib::RefPtr<Gtk::RadioAction> snap_delta_action (Editing::SnapDelta);
Glib::RefPtr<Gtk::RadioAction> snap_mode_action (Editing::SnapMode); Glib::RefPtr<Gtk::RadioAction> snap_mode_action (Editing::SnapMode);
//zoom focus meu stuff //zoom focus meu stuff

View File

@ -512,9 +512,13 @@ Editor::register_actions ()
ActionManager::register_action (editor_actions, "set-edit-lock", S_("EditMode|Lock"), sigc::bind (sigc::mem_fun (*this, &Editor::set_edit_mode), Lock)); ActionManager::register_action (editor_actions, "set-edit-lock", S_("EditMode|Lock"), sigc::bind (sigc::mem_fun (*this, &Editor::set_edit_mode), Lock));
ActionManager::register_action (editor_actions, "cycle-edit-mode", _("Cycle Edit Mode"), sigc::mem_fun (*this, &Editor::cycle_edit_mode)); ActionManager::register_action (editor_actions, "cycle-edit-mode", _("Cycle Edit Mode"), sigc::mem_fun (*this, &Editor::cycle_edit_mode));
ActionManager::register_action (editor_actions, X_("SnapDelta"), _("Snap Delta"));
RadioAction::Group snap_delta_group;
ActionManager::register_radio_action (editor_actions, snap_delta_group, X_("snap-absolute"), _("Absolute"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_delta_chosen), Editing::SnapAbsolute)));
ActionManager::register_radio_action (editor_actions, snap_delta_group, X_("snap-relative"), _("Relative"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_delta_chosen), Editing::SnapRelative)));
ActionManager::register_action (editor_actions, X_("SnapTo"), _("Snap to")); ActionManager::register_action (editor_actions, X_("SnapTo"), _("Snap to"));
ActionManager::register_action (editor_actions, X_("SnapMode"), _("Snap Mode")); ActionManager::register_action (editor_actions, X_("SnapMode"), _("Snap Mode"));
RadioAction::Group snap_mode_group; RadioAction::Group snap_mode_group;
ActionManager::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))); ActionManager::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)));
ActionManager::register_radio_action (editor_actions, snap_mode_group, X_("snap-normal"), _("Grid"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_chosen), Editing::SnapNormal))); ActionManager::register_radio_action (editor_actions, snap_mode_group, X_("snap-normal"), _("Grid"), (sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_chosen), Editing::SnapNormal)));
@ -1463,6 +1467,36 @@ Editor::snap_type_chosen (SnapType type)
} }
} }
RefPtr<RadioAction>
Editor::snap_delta_action (SnapDelta delta)
{
const char* action = 0;
RefPtr<Action> act;
switch (delta) {
case Editing::SnapAbsolute:
action = X_("snap-absolute");
break;
case Editing::SnapRelative:
action = X_("snap-relative");
break;
default:
fatal << string_compose (_("programming error: %1: %2"), "Editor: impossible snap delta type", (int) delta) << endmsg;
abort(); /*NOTREACHED*/
}
act = ActionManager::get_action (X_("Editor"), action);
if (act) {
RefPtr<RadioAction> ract = RefPtr<RadioAction>::cast_dynamic(act);
return ract;
} else {
error << string_compose (_("programming error: %1: %2"), "Editor::snap_delta_chosen could not find action to match mode.", action) << endmsg;
return RefPtr<RadioAction> ();
}
}
RefPtr<RadioAction> RefPtr<RadioAction>
Editor::snap_mode_action (SnapMode mode) Editor::snap_mode_action (SnapMode mode)
{ {
@ -1512,6 +1546,21 @@ Editor::cycle_snap_mode ()
} }
} }
void
Editor::snap_delta_chosen (SnapDelta rel)
{
/* 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_delta_action (rel);
if (ract && ract->get_active()) {
set_snap_delta (rel);
}
}
void void
Editor::snap_mode_chosen (SnapMode mode) Editor::snap_mode_chosen (SnapMode mode)
{ {

View File

@ -264,6 +264,7 @@ Drag::start_grab (GdkEvent* event, Gdk::Cursor *cursor)
} }
_raw_grab_frame = _editor->canvas_event_sample (event, &_grab_x, &_grab_y); _raw_grab_frame = _editor->canvas_event_sample (event, &_grab_x, &_grab_y);
setup_pointer_frame_offset (); setup_pointer_frame_offset ();
_grab_frame = adjusted_frame (_raw_grab_frame, event); _grab_frame = adjusted_frame (_raw_grab_frame, event);
_last_pointer_frame = _grab_frame; _last_pointer_frame = _grab_frame;
@ -559,6 +560,7 @@ RegionMotionDrag::RegionMotionDrag (Editor* e, ArdourCanvas::Item* i, RegionView
, _ndropzone (0) , _ndropzone (0)
, _pdropzone (0) , _pdropzone (0)
, _ddropzone (0) , _ddropzone (0)
, _snap_delta (0)
{ {
DEBUG_TRACE (DEBUG::Drags, "New RegionMotionDrag\n"); DEBUG_TRACE (DEBUG::Drags, "New RegionMotionDrag\n");
} }
@ -568,6 +570,12 @@ RegionMotionDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
{ {
Drag::start_grab (event, cursor); Drag::start_grab (event, cursor);
if (_editor->snap_delta () == SnapRelative) {
framepos_t temp = _last_frame_position;
_editor->snap_to_with_modifier (temp, event, RoundUpMaybe);
_snap_delta = temp - _last_frame_position;
}
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::TertiaryModifier)) { if (Keyboard::modifier_state_contains (event->button.state, Keyboard::TertiaryModifier)) {
_single_axis = true; _single_axis = true;
} }
@ -588,7 +596,7 @@ RegionMotionDrag::compute_x_delta (GdkEvent const * event, framepos_t* pending_r
/* compute the amount of pointer motion in frames, and where /* compute the amount of pointer motion in frames, and where
the region would be if we moved it by that much. the region would be if we moved it by that much.
*/ */
*pending_region_position = adjusted_current_frame (event); *pending_region_position = adjusted_frame (_drags->current_pointer_frame () + _snap_delta, event, true);
framepos_t sync_frame; framepos_t sync_frame;
framecnt_t sync_offset; framecnt_t sync_offset;
@ -600,11 +608,11 @@ RegionMotionDrag::compute_x_delta (GdkEvent const * event, framepos_t* pending_r
*/ */
if (sync_dir >= 0 || (sync_dir < 0 && *pending_region_position >= sync_offset)) { if (sync_dir >= 0 || (sync_dir < 0 && *pending_region_position >= sync_offset)) {
sync_frame = *pending_region_position + (sync_dir*sync_offset); sync_frame = *pending_region_position + (sync_dir * sync_offset);
_editor->snap_to_with_modifier (sync_frame, event); _editor->snap_to_with_modifier (sync_frame, event);
*pending_region_position = _primary->region()->adjust_to_sync (sync_frame); *pending_region_position = _primary->region()->adjust_to_sync (sync_frame) - _snap_delta;
} else { } else {
*pending_region_position = _last_frame_position; *pending_region_position = _last_frame_position;
@ -2318,6 +2326,7 @@ RegionCreateDrag::aborted (bool)
NoteResizeDrag::NoteResizeDrag (Editor* e, ArdourCanvas::Item* i) NoteResizeDrag::NoteResizeDrag (Editor* e, ArdourCanvas::Item* i)
: Drag (e, i) : Drag (e, i)
, region (0) , region (0)
, _snap_delta (0)
{ {
DEBUG_TRACE (DEBUG::Drags, "New NoteResizeDrag\n"); DEBUG_TRACE (DEBUG::Drags, "New NoteResizeDrag\n");
} }
@ -2342,6 +2351,21 @@ NoteResizeDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*ignored*/)
region = &cnote->region_view(); region = &cnote->region_view();
if (_editor->snap_delta () == SnapRelative) {
double temp;
temp = region->snap_to_pixel(cnote->x0 ());
_snap_delta = temp - cnote->x0 ();
/*
if (at_front) {
temp = region->snap_to_pixel(cnote->x0 ());
_snap_delta = temp - cnote->x0 ();
} else {
temp = region->snap_to_pixel(cnote->x1 ());
_snap_delta = temp - cnote->x1 ();
}
*/
}
_item->grab (); _item->grab ();
if (event->motion.state & Keyboard::PrimaryModifier) { if (event->motion.state & Keyboard::PrimaryModifier) {
@ -2385,7 +2409,7 @@ NoteResizeDrag::motion (GdkEvent* /*event*/, bool /*first_move*/)
assert (nb); assert (nb);
MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(*r); MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(*r);
if (mrv) { if (mrv) {
mrv->update_resizing (nb, at_front, _drags->current_pointer_x() - grab_x(), relative); mrv->update_resizing (nb, at_front, _drags->current_pointer_x() - grab_x(), relative, _snap_delta);
} }
} }
} }
@ -2399,7 +2423,7 @@ NoteResizeDrag::finished (GdkEvent*, bool /*movement_occurred*/)
assert (nb); assert (nb);
MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(*r); MidiRegionView* mrv = dynamic_cast<MidiRegionView*>(*r);
if (mrv) { if (mrv) {
mrv->commit_resizing (nb, at_front, _drags->current_pointer_x() - grab_x(), relative); mrv->commit_resizing (nb, at_front, _drags->current_pointer_x() - grab_x(), relative, _snap_delta);
} }
} }
@ -2577,6 +2601,7 @@ TrimDrag::TrimDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<Region
: RegionDrag (e, i, p, v) : RegionDrag (e, i, p, v)
, _preserve_fade_anchor (preserve_fade_anchor) , _preserve_fade_anchor (preserve_fade_anchor)
, _jump_position_when_done (false) , _jump_position_when_done (false)
, _snap_delta (0)
{ {
DEBUG_TRACE (DEBUG::Drags, "New TrimDrag\n"); DEBUG_TRACE (DEBUG::Drags, "New TrimDrag\n");
} }
@ -2598,6 +2623,12 @@ TrimDrag::start_grab (GdkEvent* event, Gdk::Cursor*)
framepos_t const pf = adjusted_current_frame (event); framepos_t const pf = adjusted_current_frame (event);
if (_editor->snap_delta () == SnapRelative) {
framepos_t temp = region_start;
_editor->snap_to_with_modifier (temp, event, RoundUpMaybe);
_snap_delta = temp - region_start;
}
if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) { if (Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier)) {
/* Move the contents of the region around without changing the region bounds */ /* Move the contents of the region around without changing the region bounds */
_operation = ContentsTrim; _operation = ContentsTrim;
@ -2636,7 +2667,7 @@ TrimDrag::start_grab (GdkEvent* event, Gdk::Cursor*)
} }
break; break;
case EndTrim: case EndTrim:
show_verbose_cursor_time (region_end); show_verbose_cursor_duration (region_start, region_end);
break; break;
case ContentsTrim: case ContentsTrim:
show_verbose_cursor_time (pf); show_verbose_cursor_time (pf);
@ -2662,8 +2693,8 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
if (tv && tv->is_track()) { if (tv && tv->is_track()) {
speed = tv->track()->speed(); speed = tv->track()->speed();
} }
framecnt_t adj_frame = adjusted_frame (_drags->current_pointer_frame () + _snap_delta, event, true);
framecnt_t dt = adjusted_current_frame (event) - raw_grab_frame () + _pointer_frame_offset; framecnt_t dt = adj_frame - raw_grab_frame () + _pointer_frame_offset - _snap_delta;
if (first_move) { if (first_move) {
@ -2769,7 +2800,7 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
if (arv) { if (arv) {
boost::shared_ptr<AudioRegion> ar (arv->audio_region()); boost::shared_ptr<AudioRegion> ar (arv->audio_region());
framecnt_t len = ar->fade_out()->back()->when; framecnt_t len = ar->fade_out()->back()->when;
framecnt_t diff = 1 + ar->last_frame() - i->initial_end; framecnt_t diff = ar->last_frame() - i->initial_end;
framepos_t new_length = len + diff; framepos_t new_length = len + diff;
i->anchored_fade_length = min (ar->length(), new_length); i->anchored_fade_length = min (ar->length(), new_length);
//i->anchored_fade_length = ar->verify_xfade_bounds (new_length, false /*END*/ ); //i->anchored_fade_length = ar->verify_xfade_bounds (new_length, false /*END*/ );
@ -2795,7 +2826,7 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
show_verbose_cursor_time ((framepos_t) (rv->region()->position() / speed)); show_verbose_cursor_time ((framepos_t) (rv->region()->position() / speed));
break; break;
case EndTrim: case EndTrim:
show_verbose_cursor_time ((framepos_t) (rv->region()->last_frame() / speed)); show_verbose_cursor_duration ((framepos_t) rv->region()->position() / speed, (framepos_t) rv->region()->last_frame() / speed);
break; break;
case ContentsTrim: case ContentsTrim:
// show_verbose_cursor_time (frame_delta); // show_verbose_cursor_time (frame_delta);
@ -3213,6 +3244,7 @@ CursorDrag::CursorDrag (Editor* e, EditorCursor& c, bool s)
: Drag (e, &c.track_canvas_item(), false) : Drag (e, &c.track_canvas_item(), false)
, _cursor (c) , _cursor (c)
, _stop (s) , _stop (s)
, _snap_delta (0)
{ {
DEBUG_TRACE (DEBUG::Drags, "New CursorDrag\n"); DEBUG_TRACE (DEBUG::Drags, "New CursorDrag\n");
} }
@ -3248,9 +3280,15 @@ CursorDrag::start_grab (GdkEvent* event, Gdk::Cursor* c)
{ {
Drag::start_grab (event, c); Drag::start_grab (event, c);
if (_editor->snap_delta () == SnapRelative) {
framepos_t temp = _editor->playhead_cursor->current_frame ();
_editor->snap_to_with_modifier (temp, event);
_snap_delta = temp - _editor->playhead_cursor->current_frame ();
}
_grab_zoom = _editor->samples_per_pixel; _grab_zoom = _editor->samples_per_pixel;
framepos_t where = _editor->canvas_event_sample (event); framepos_t where = _editor->canvas_event_sample (event) + _snap_delta;
_editor->snap_to_with_modifier (where, event); _editor->snap_to_with_modifier (where, event);
@ -3288,15 +3326,16 @@ CursorDrag::start_grab (GdkEvent* event, Gdk::Cursor* c)
} }
} }
fake_locate (where); fake_locate (where - _snap_delta);
} }
void void
CursorDrag::motion (GdkEvent* event, bool) CursorDrag::motion (GdkEvent* event, bool)
{ {
framepos_t const adjusted_frame = adjusted_current_frame (event); framepos_t where = _editor->canvas_event_sample (event) + _snap_delta;
if (adjusted_frame != last_pointer_frame()) { _editor->snap_to_with_modifier (where, event);
fake_locate (adjusted_frame); if (where != last_pointer_frame()) {
fake_locate (where - _snap_delta);
} }
} }
@ -3336,6 +3375,7 @@ CursorDrag::aborted (bool)
FadeInDrag::FadeInDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v) FadeInDrag::FadeInDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v)
: RegionDrag (e, i, p, v) : RegionDrag (e, i, p, v)
, _snap_delta (0)
{ {
DEBUG_TRACE (DEBUG::Drags, "New FadeInDrag\n"); DEBUG_TRACE (DEBUG::Drags, "New FadeInDrag\n");
} }
@ -3348,6 +3388,12 @@ FadeInDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary); AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary);
boost::shared_ptr<AudioRegion> const r = arv->audio_region (); boost::shared_ptr<AudioRegion> const r = arv->audio_region ();
if (_editor->snap_delta () == SnapRelative) {
framepos_t temp = r->position();
_editor->snap_to_with_modifier (temp, event);
_snap_delta = temp - r->position();
}
show_verbose_cursor_duration (r->position(), r->position() + r->fade_in()->back()->when, 32); show_verbose_cursor_duration (r->position(), r->position() + r->fade_in()->back()->when, 32);
} }
@ -3363,7 +3409,11 @@ void
FadeInDrag::motion (GdkEvent* event, bool) FadeInDrag::motion (GdkEvent* event, bool)
{ {
framecnt_t fade_length; framecnt_t fade_length;
framepos_t const pos = adjusted_current_frame (event);
framepos_t pos = _editor->canvas_event_sample (event) + _snap_delta;
_editor->snap_to_with_modifier (pos, event);
pos -= _snap_delta;
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ()); boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ());
if (pos < (region->position() + 64)) { if (pos < (region->position() + 64)) {
@ -3396,8 +3446,9 @@ FadeInDrag::finished (GdkEvent* event, bool movement_occurred)
} }
framecnt_t fade_length; framecnt_t fade_length;
framepos_t pos = _editor->canvas_event_sample (event) + _snap_delta;
framepos_t const pos = adjusted_current_frame (event); _editor->snap_to_with_modifier (pos, event);
pos -= _snap_delta;
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ()); boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ());
@ -3460,6 +3511,12 @@ FadeOutDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary); AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary);
boost::shared_ptr<AudioRegion> r = arv->audio_region (); boost::shared_ptr<AudioRegion> r = arv->audio_region ();
if (_editor->snap_delta () == SnapRelative) {
framepos_t temp = r->last_frame ();
_editor->snap_to_with_modifier (temp, event);
_snap_delta = temp - r->last_frame();
}
show_verbose_cursor_duration (r->last_frame() - r->fade_out()->back()->when, r->last_frame()); show_verbose_cursor_duration (r->last_frame() - r->fade_out()->back()->when, r->last_frame());
} }
@ -3476,7 +3533,9 @@ FadeOutDrag::motion (GdkEvent* event, bool)
{ {
framecnt_t fade_length; framecnt_t fade_length;
framepos_t const pos = adjusted_current_frame (event); framepos_t pos = _editor->canvas_event_sample (event) + _snap_delta;
_editor->snap_to_with_modifier (pos, event);
pos -= _snap_delta;
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ()); boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ());
@ -3511,7 +3570,9 @@ FadeOutDrag::finished (GdkEvent* event, bool movement_occurred)
framecnt_t fade_length; framecnt_t fade_length;
framepos_t const pos = adjusted_current_frame (event); framepos_t pos = _editor->canvas_event_sample (event) + _snap_delta;
_editor->snap_to_with_modifier (pos, event);
pos -= _snap_delta;
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ()); boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ());
@ -3965,6 +4026,16 @@ ControlPointDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
_fixed_grab_x = _point->get_x(); _fixed_grab_x = _point->get_x();
_fixed_grab_y = _point->get_y(); _fixed_grab_y = _point->get_y();
framepos_t pos = _editor->pixel_to_sample (_fixed_grab_x);
if (_editor->snap_delta () == SnapRelative) {
framepos_t temp = pos;
if (!_x_constrained) {
_editor->snap_to_with_modifier (temp, event);
}
_snap_delta = temp - pos;
}
float const fraction = 1 - (_point->get_y() / _point->line().height()); float const fraction = 1 - (_point->get_y() / _point->line().height());
_point->line().start_drag_single (_point, _fixed_grab_x, fraction); _point->line().start_drag_single (_point, _fixed_grab_x, fraction);
@ -4017,12 +4088,13 @@ ControlPointDrag::motion (GdkEvent* event, bool)
cy = max (0.0, cy); cy = max (0.0, cy);
cy = min ((double) _point->line().height(), cy); cy = min ((double) _point->line().height(), cy);
framepos_t cx_frames = _editor->pixel_to_sample (cx); framepos_t cx_frames = _editor->pixel_to_sample (cx) + _snap_delta;
if (!_x_constrained) { if (!_x_constrained) {
_editor->snap_to_with_modifier (cx_frames, event); _editor->snap_to_with_modifier (cx_frames, event);
} }
cx_frames -= _snap_delta;
cx_frames = min (cx_frames, _point->line().maximum_time()); cx_frames = min (cx_frames, _point->line().maximum_time());
float const fraction = 1.0 - (cy / _point->line().height()); float const fraction = 1.0 - (cy / _point->line().height());
@ -4070,9 +4142,9 @@ ControlPointDrag::active (Editing::MouseMode m)
} }
LineDrag::LineDrag (Editor* e, ArdourCanvas::Item* i) LineDrag::LineDrag (Editor* e, ArdourCanvas::Item* i)
: Drag (e, i), : Drag (e, i)
_line (0), , _line (0)
_cumulative_y_drag (0) , _cumulative_y_drag (0)
{ {
DEBUG_TRACE (DEBUG::Drags, "New LineDrag\n"); DEBUG_TRACE (DEBUG::Drags, "New LineDrag\n");
} }
@ -4423,6 +4495,7 @@ RubberbandSelectDrag::aborted (bool)
TimeFXDrag::TimeFXDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, std::list<RegionView*> const & v) TimeFXDrag::TimeFXDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, std::list<RegionView*> const & v)
: RegionDrag (e, i, p, v) : RegionDrag (e, i, p, v)
, _snap_delta (0)
{ {
DEBUG_TRACE (DEBUG::Drags, "New TimeFXDrag\n"); DEBUG_TRACE (DEBUG::Drags, "New TimeFXDrag\n");
} }
@ -4432,7 +4505,16 @@ TimeFXDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
{ {
Drag::start_grab (event, cursor); Drag::start_grab (event, cursor);
show_verbose_cursor_time (adjusted_current_frame (event)); _editor->get_selection().add (_primary);
framepos_t where = _primary->region()->position();
if (_editor->snap_delta () == SnapRelative) {
framepos_t temp = where;
_editor->snap_to_with_modifier (temp, event);
_snap_delta = temp - where;
}
show_verbose_cursor_duration (where, adjusted_current_frame (event), 0);
} }
void void
@ -4444,14 +4526,15 @@ TimeFXDrag::motion (GdkEvent* event, bool)
pair<TimeAxisView*, double> const tv = _editor->trackview_by_y_position (grab_y()); pair<TimeAxisView*, double> const tv = _editor->trackview_by_y_position (grab_y());
int layer = tv.first->layer_display() == Overlaid ? 0 : tv.second; int layer = tv.first->layer_display() == Overlaid ? 0 : tv.second;
int layers = tv.first->layer_display() == Overlaid ? 1 : cv->layers(); int layers = tv.first->layer_display() == Overlaid ? 1 : cv->layers();
framepos_t pf = _editor->canvas_event_sample (event) + _snap_delta;
framepos_t const pf = adjusted_current_frame (event); _editor->snap_to_with_modifier (pf, event);
pf -= _snap_delta;
if (pf > rv->region()->position()) { if (pf > rv->region()->position()) {
rv->get_time_axis_view().show_timestretch (rv->region()->position(), pf, layers, layer); rv->get_time_axis_view().show_timestretch (rv->region()->position(), pf, layers, layer);
} }
show_verbose_cursor_time (pf); show_verbose_cursor_duration (_primary->region()->position(), pf, 0);
} }
void void
@ -5117,6 +5200,7 @@ NoteDrag::NoteDrag (Editor* e, ArdourCanvas::Item* i)
: Drag (e, i) : Drag (e, i)
, _cumulative_dx (0) , _cumulative_dx (0)
, _cumulative_dy (0) , _cumulative_dy (0)
, _snap_delta (0)
{ {
DEBUG_TRACE (DEBUG::Drags, "New NoteDrag\n"); DEBUG_TRACE (DEBUG::Drags, "New NoteDrag\n");
@ -5131,6 +5215,13 @@ NoteDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
{ {
Drag::start_grab (event); Drag::start_grab (event);
if (_editor->snap_delta () == SnapRelative) {
framepos_t where = _region->source_beats_to_absolute_frames (_primary->note()->time ());
framepos_t temp = where;
_editor->snap_to_with_modifier (temp, event);
_snap_delta = temp - where;
}
if (!(_was_selected = _primary->selected())) { if (!(_was_selected = _primary->selected())) {
/* tertiary-click means extend selection - we'll do that on button release, /* tertiary-click means extend selection - we'll do that on button release,
@ -5166,7 +5257,7 @@ NoteDrag::total_dx () const
frameoffset_t const n = _region->source_beats_to_absolute_frames (_primary->note()->time ()); frameoffset_t const n = _region->source_beats_to_absolute_frames (_primary->note()->time ());
/* new time of the primary note in session frames */ /* new time of the primary note in session frames */
frameoffset_t st = n + dx; frameoffset_t st = n + dx + _snap_delta;
framepos_t const rp = _region->region()->position (); framepos_t const rp = _region->region()->position ();
@ -5174,7 +5265,7 @@ NoteDrag::total_dx () const
st = max (st, rp); st = max (st, rp);
/* snap and return corresponding delta */ /* snap and return corresponding delta */
return _region->snap_frame_to_frame (st - rp) + rp - n; return _region->snap_frame_to_frame (st - rp) + rp - n - _snap_delta;
} }
/** @return Current total drag y change in note number */ /** @return Current total drag y change in note number */
@ -5880,7 +5971,7 @@ RegionCutDrag::RegionCutDrag (Editor* e, ArdourCanvas::Item* item, framepos_t po
, line (new EditorCursor (*e)) , line (new EditorCursor (*e))
{ {
line->set_position (pos); line->set_position (pos);
line->show (); line->how ();
} }
RegionCutDrag::~RegionCutDrag () RegionCutDrag::~RegionCutDrag ()

View File

@ -213,7 +213,7 @@ protected:
return _last_pointer_y; return _last_pointer_y;
} }
double last_pointer_frame () const { ARDOUR::framepos_t last_pointer_frame () const {
return _last_pointer_frame; return _last_pointer_frame;
} }
@ -341,6 +341,7 @@ private:
uint32_t _ndropzone; uint32_t _ndropzone;
uint32_t _pdropzone; uint32_t _pdropzone;
uint32_t _ddropzone; uint32_t _ddropzone;
int32_t _snap_delta; ///< delta between the initial position and next snap point
}; };
@ -503,6 +504,7 @@ private:
MidiRegionView* region; MidiRegionView* region;
bool relative; bool relative;
bool at_front; bool at_front;
double _snap_delta;
}; };
/** Drags to move MIDI notes */ /** Drags to move MIDI notes */
@ -527,6 +529,7 @@ class NoteDrag : public Drag
double _cumulative_dy; double _cumulative_dy;
bool _was_selected; bool _was_selected;
double _note_height; double _note_height;
int32_t _snap_delta;
}; };
class NoteCreateDrag : public Drag class NoteCreateDrag : public Drag
@ -646,6 +649,7 @@ private:
bool _preserve_fade_anchor; bool _preserve_fade_anchor;
bool _jump_position_when_done; bool _jump_position_when_done;
int32_t _snap_delta;
}; };
/** Meter marker drag */ /** Meter marker drag */
@ -728,6 +732,7 @@ private:
EditorCursor& _cursor; EditorCursor& _cursor;
bool _stop; ///< true to stop the transport on starting the drag, otherwise false bool _stop; ///< true to stop the transport on starting the drag, otherwise false
double _grab_zoom; ///< editor frames per unit when our grab started double _grab_zoom; ///< editor frames per unit when our grab started
int32_t _snap_delta;
}; };
/** Region fade-in drag */ /** Region fade-in drag */
@ -746,6 +751,8 @@ public:
} }
void setup_pointer_frame_offset (); void setup_pointer_frame_offset ();
private:
int32_t _snap_delta;
}; };
/** Region fade-out drag */ /** Region fade-out drag */
@ -764,6 +771,8 @@ public:
} }
void setup_pointer_frame_offset (); void setup_pointer_frame_offset ();
private:
int32_t _snap_delta;
}; };
/** Marker drag */ /** Marker drag */
@ -827,6 +836,7 @@ private:
double _cumulative_y_drag; double _cumulative_y_drag;
bool _pushing; bool _pushing;
uint32_t _final_index; uint32_t _final_index;
int32_t _snap_delta;
static double _zero_gain_fraction; static double _zero_gain_fraction;
}; };
@ -951,6 +961,8 @@ public:
void motion (GdkEvent *, bool); void motion (GdkEvent *, bool);
void finished (GdkEvent *, bool); void finished (GdkEvent *, bool);
void aborted (bool); void aborted (bool);
private:
int32_t _snap_delta;
}; };
/** Scrub drag in audition mode */ /** Scrub drag in audition mode */

View File

@ -43,6 +43,7 @@ setup_gtk_ardour_enums ()
LayerDisplay layer_display; LayerDisplay layer_display;
RegionListSortType region_list_sort_type; RegionListSortType region_list_sort_type;
SnapType snap_type; SnapType snap_type;
SnapDelta snap_delta;
SnapMode snap_mode; SnapMode snap_mode;
ZoomFocus zoom_focus; ZoomFocus zoom_focus;
ItemType item_type; ItemType item_type;
@ -90,6 +91,10 @@ setup_gtk_ardour_enums ()
REGISTER_ENUM (ByTimestamp); REGISTER_ENUM (ByTimestamp);
REGISTER (region_list_sort_type); REGISTER (region_list_sort_type);
REGISTER_ENUM (SnapAbsolute);
REGISTER_ENUM (SnapRelative);
REGISTER (snap_delta);
REGISTER_ENUM (SnapToCDFrame); REGISTER_ENUM (SnapToCDFrame);
REGISTER_ENUM (SnapToTimecodeFrame); REGISTER_ENUM (SnapToTimecodeFrame);
REGISTER_ENUM (SnapToTimecodeSeconds); REGISTER_ENUM (SnapToTimecodeSeconds);

View File

@ -104,6 +104,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Container* parent,
, _current_range_max(0) , _current_range_max(0)
, _region_relative_time_converter(r->session().tempo_map(), r->position()) , _region_relative_time_converter(r->session().tempo_map(), r->position())
, _source_relative_time_converter(r->session().tempo_map(), r->position() - r->start()) , _source_relative_time_converter(r->session().tempo_map(), r->position() - r->start())
, _region_relative_time_converter_double(r->session().tempo_map(), r->position())
, _active_notes(0) , _active_notes(0)
, _note_group (new ArdourCanvas::Container (group)) , _note_group (new ArdourCanvas::Container (group))
, _note_diff_command (0) , _note_diff_command (0)
@ -151,6 +152,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Container* parent,
, _current_range_max(0) , _current_range_max(0)
, _region_relative_time_converter(r->session().tempo_map(), r->position()) , _region_relative_time_converter(r->session().tempo_map(), r->position())
, _source_relative_time_converter(r->session().tempo_map(), r->position() - r->start()) , _source_relative_time_converter(r->session().tempo_map(), r->position() - r->start())
, _region_relative_time_converter_double(r->session().tempo_map(), r->position())
, _active_notes(0) , _active_notes(0)
, _note_group (new ArdourCanvas::Container (group)) , _note_group (new ArdourCanvas::Container (group))
, _note_diff_command (0) , _note_diff_command (0)
@ -203,6 +205,7 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other)
, _current_range_max(0) , _current_range_max(0)
, _region_relative_time_converter(other.region_relative_time_converter()) , _region_relative_time_converter(other.region_relative_time_converter())
, _source_relative_time_converter(other.source_relative_time_converter()) , _source_relative_time_converter(other.source_relative_time_converter())
, _region_relative_time_converter_double(other.region_relative_time_converter_double())
, _active_notes(0) , _active_notes(0)
, _note_group (new ArdourCanvas::Container (get_canvas_group())) , _note_group (new ArdourCanvas::Container (get_canvas_group()))
, _note_diff_command (0) , _note_diff_command (0)
@ -234,6 +237,7 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other, boost::shared_ptr<M
, _current_range_max(0) , _current_range_max(0)
, _region_relative_time_converter(other.region_relative_time_converter()) , _region_relative_time_converter(other.region_relative_time_converter())
, _source_relative_time_converter(other.source_relative_time_converter()) , _source_relative_time_converter(other.source_relative_time_converter())
, _region_relative_time_converter_double(other.region_relative_time_converter_double())
, _active_notes(0) , _active_notes(0)
, _note_group (new ArdourCanvas::Container (get_canvas_group())) , _note_group (new ArdourCanvas::Container (get_canvas_group()))
, _note_diff_command (0) , _note_diff_command (0)
@ -1408,6 +1412,7 @@ MidiRegionView::region_resized (const PropertyChange& what_changed)
if (what_changed.contains (ARDOUR::Properties::position)) { if (what_changed.contains (ARDOUR::Properties::position)) {
_region_relative_time_converter.set_origin_b(_region->position()); _region_relative_time_converter.set_origin_b(_region->position());
_region_relative_time_converter_double.set_origin_b(_region->position());
set_duration(_region->length(), 0); set_duration(_region->length(), 0);
if (_enable_display) { if (_enable_display) {
redisplay_model(); redisplay_model();
@ -2685,6 +2690,12 @@ MidiRegionView::region_frames_to_region_beats(framepos_t frames) const
return _region_relative_time_converter.from(frames); return _region_relative_time_converter.from(frames);
} }
double
MidiRegionView::region_frames_to_region_beats_double(framepos_t frames) const
{
return _region_relative_time_converter_double.from(frames);
}
void void
MidiRegionView::begin_resizing (bool /*at_front*/) MidiRegionView::begin_resizing (bool /*at_front*/)
{ {
@ -2733,9 +2744,10 @@ MidiRegionView::begin_resizing (bool /*at_front*/)
* a difference when multiple notes are being resized; in relative mode, each note's length is changed by the * a difference when multiple notes are being resized; in relative mode, each note's length is changed by the
* amount of the drag. In non-relative mode, all selected notes are set to have the same start or end point * amount of the drag. In non-relative mode, all selected notes are set to have the same start or end point
* as the \a primary note. * as the \a primary note.
* @param snap_delta snap offset of the primary note in pixels. used in SnapRelative SnapDelta mode.
*/ */
void void
MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_x, bool relative) MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_x, bool relative, double snap_delta)
{ {
bool cursor_set = false; bool cursor_set = false;
@ -2746,15 +2758,15 @@ MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_
if (at_front) { if (at_front) {
if (relative) { if (relative) {
current_x = canvas_note->x0() + delta_x; current_x = canvas_note->x0() + delta_x + snap_delta;
} else { } else {
current_x = primary->x0() + delta_x; current_x = primary->x0() + delta_x + snap_delta;
} }
} else { } else {
if (relative) { if (relative) {
current_x = canvas_note->x1() + delta_x; current_x = canvas_note->x1() + delta_x + snap_delta;
} else { } else {
current_x = primary->x1() + delta_x; current_x = primary->x1() + delta_x + snap_delta;
} }
} }
@ -2768,26 +2780,38 @@ MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_
} }
if (at_front) { if (at_front) {
resize_rect->set_x0 (snap_to_pixel(current_x)); resize_rect->set_x0 (snap_to_pixel(current_x) - snap_delta);
resize_rect->set_x1 (canvas_note->x1()); resize_rect->set_x1 (canvas_note->x1());
} else { } else {
resize_rect->set_x1 (snap_to_pixel(current_x)); resize_rect->set_x1 (snap_to_pixel(current_x) - snap_delta);
resize_rect->set_x0 (canvas_note->x0()); resize_rect->set_x0 (canvas_note->x0());
} }
if (!cursor_set) { if (!cursor_set) {
/* snap delta is in pixels (sigh) */
framepos_t delta_samps = trackview.editor().pixel_to_sample (snap_delta);
double delta_beats;
int sign = 1;
/* negative beat offsets aren't allowed */
if (delta_samps > 0) {
delta_beats = _region_relative_time_converter_double.from(delta_samps);
} else if (delta_samps < 0) {
delta_beats = _region_relative_time_converter_double.from( - delta_samps);
sign = -1;
}
const double snapped_x = snap_pixel_to_sample (current_x); const double snapped_x = snap_pixel_to_sample (current_x);
Evoral::Beats beats = region_frames_to_region_beats (snapped_x); Evoral::Beats beats = region_frames_to_region_beats (snapped_x);
Evoral::Beats len = Evoral::Beats(); Evoral::Beats len = Evoral::Beats();
if (at_front) { if (at_front) {
if (beats < canvas_note->note()->end_time()) { if (beats < canvas_note->note()->end_time()) {
len = canvas_note->note()->time() - beats; len = canvas_note->note()->time() - beats + (sign * delta_beats);
len += canvas_note->note()->length(); len += canvas_note->note()->length();
} }
} else { } else {
if (beats >= canvas_note->note()->time()) { if (beats >= canvas_note->note()->time()) {
len = beats - canvas_note->note()->time(); len = beats - canvas_note->note()->time() - (sign * delta_beats);
} }
} }
@ -2808,10 +2832,9 @@ MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_
* Parameters the same as for \a update_resizing(). * Parameters the same as for \a update_resizing().
*/ */
void void
MidiRegionView::commit_resizing (NoteBase* primary, bool at_front, double delta_x, bool relative) MidiRegionView::commit_resizing (NoteBase* primary, bool at_front, double delta_x, bool relative, double snap_delta)
{ {
_note_diff_command = _model->new_note_diff_command (_("resize notes")); _note_diff_command = _model->new_note_diff_command (_("resize notes"));
for (std::vector<NoteResizeData *>::iterator i = _resize_data.begin(); i != _resize_data.end(); ++i) { for (std::vector<NoteResizeData *>::iterator i = _resize_data.begin(); i != _resize_data.end(); ++i) {
Note* canvas_note = (*i)->note; Note* canvas_note = (*i)->note;
ArdourCanvas::Rectangle* resize_rect = (*i)->resize_rect; ArdourCanvas::Rectangle* resize_rect = (*i)->resize_rect;
@ -2824,15 +2847,15 @@ MidiRegionView::commit_resizing (NoteBase* primary, bool at_front, double delta_
if (at_front) { if (at_front) {
if (relative) { if (relative) {
current_x = canvas_note->x0() + delta_x; current_x = canvas_note->x0() + delta_x + snap_delta;
} else { } else {
current_x = primary->x0() + delta_x; current_x = primary->x0() + delta_x + snap_delta;
} }
} else { } else {
if (relative) { if (relative) {
current_x = canvas_note->x1() + delta_x; current_x = canvas_note->x1() + delta_x + snap_delta;
} else { } else {
current_x = primary->x1() + delta_x; current_x = primary->x1() + delta_x + snap_delta;
} }
} }
@ -2842,17 +2865,26 @@ MidiRegionView::commit_resizing (NoteBase* primary, bool at_front, double delta_
if (current_x > trackview.editor().sample_to_pixel(_region->length())) { if (current_x > trackview.editor().sample_to_pixel(_region->length())) {
current_x = trackview.editor().sample_to_pixel(_region->length()); current_x = trackview.editor().sample_to_pixel(_region->length());
} }
framepos_t delta_samps = trackview.editor().pixel_to_sample (snap_delta);
double delta_beats;
int sign = 1;
if (delta_samps > 0) {
delta_beats = _region_relative_time_converter_double.from(delta_samps);
} else if (delta_samps < 0) {
delta_beats = _region_relative_time_converter_double.from( - delta_samps);
sign = -1;
}
/* Convert that to a frame within the source */ /* Convert that to a frame within the source */
current_x = snap_pixel_to_sample (current_x) + _region->start (); framepos_t current_fr = snap_pixel_to_sample (current_x) + _region->start ();
double one_frame = region_frames_to_region_beats_double (current_fr) - region_frames_to_region_beats_double (current_fr - 1);
cerr << "commit one frame in beats : " << one_frame << endl;
/* and then to beats */ /* and then to beats */
const Evoral::Beats x_beats = region_frames_to_region_beats (current_x); const Evoral::Beats x_beats = region_frames_to_region_beats (current_fr);
if (at_front && x_beats < canvas_note->note()->end_time()) { if (at_front && x_beats < canvas_note->note()->end_time()) {
note_diff_add_change (canvas_note, MidiModel::NoteDiffCommand::StartTime, x_beats); note_diff_add_change (canvas_note, MidiModel::NoteDiffCommand::StartTime, x_beats - (sign * delta_beats));
Evoral::Beats len = canvas_note->note()->time() - x_beats; Evoral::Beats len = canvas_note->note()->time() - x_beats + (sign * delta_beats);
len += canvas_note->note()->length(); len += canvas_note->note()->length();
if (!!len) { if (!!len) {
@ -2862,7 +2894,7 @@ MidiRegionView::commit_resizing (NoteBase* primary, bool at_front, double delta_
if (!at_front) { if (!at_front) {
const Evoral::Beats len = std::max(Evoral::Beats(1 / 512.0), const Evoral::Beats len = std::max(Evoral::Beats(1 / 512.0),
x_beats - canvas_note->note()->time()); x_beats - canvas_note->note()->time() - (sign * delta_beats) - one_frame);
note_diff_add_change (canvas_note, MidiModel::NoteDiffCommand::Length, len); note_diff_add_change (canvas_note, MidiModel::NoteDiffCommand::Length, len);
} }

View File

@ -223,8 +223,8 @@ public:
*/ */
void begin_resizing(bool at_front); void begin_resizing(bool at_front);
void update_resizing (NoteBase*, bool, double, bool); void update_resizing (NoteBase*, bool, double, bool, double);
void commit_resizing (NoteBase*, bool, double, bool); void commit_resizing (NoteBase*, bool, double, bool, double);
void abort_resizing (); void abort_resizing ();
/** Change the channel of the selection. /** Change the channel of the selection.
@ -268,6 +268,7 @@ public:
} }
/** Convert a timestamp in frames to beats (both relative to region position) */ /** Convert a timestamp in frames to beats (both relative to region position) */
Evoral::Beats region_frames_to_region_beats(framepos_t) const; Evoral::Beats region_frames_to_region_beats(framepos_t) const;
double region_frames_to_region_beats_double(framepos_t) const;
/** Convert a timestamp in beats measured from source start into absolute frames */ /** Convert a timestamp in beats measured from source start into absolute frames */
framepos_t source_beats_to_absolute_frames(Evoral::Beats beats) const; framepos_t source_beats_to_absolute_frames(Evoral::Beats beats) const;
@ -286,6 +287,10 @@ public:
return _source_relative_time_converter; return _source_relative_time_converter;
} }
ARDOUR::DoubleBeatsFramesConverter const & region_relative_time_converter_double () const {
return _region_relative_time_converter_double;
}
void goto_previous_note (bool add_to_selection); void goto_previous_note (bool add_to_selection);
void goto_next_note (bool add_to_selection); void goto_next_note (bool add_to_selection);
void change_note_lengths (bool, bool, Evoral::Beats beats, bool start, bool end); void change_note_lengths (bool, bool, Evoral::Beats beats, bool start, bool end);
@ -400,6 +405,7 @@ private:
ARDOUR::BeatsFramesConverter _region_relative_time_converter; ARDOUR::BeatsFramesConverter _region_relative_time_converter;
ARDOUR::BeatsFramesConverter _source_relative_time_converter; ARDOUR::BeatsFramesConverter _source_relative_time_converter;
ARDOUR::DoubleBeatsFramesConverter _region_relative_time_converter_double;
boost::shared_ptr<ARDOUR::MidiModel> _model; boost::shared_ptr<ARDOUR::MidiModel> _model;
Events _events; Events _events;

View File

@ -129,8 +129,11 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulDestructible, publi
virtual void set_snap_to (Editing::SnapType t) = 0; virtual void set_snap_to (Editing::SnapType t) = 0;
virtual Editing::SnapType snap_type () const = 0; virtual Editing::SnapType snap_type () const = 0;
virtual Editing::SnapDelta snap_delta () const = 0;
virtual Editing::SnapMode snap_mode () const = 0; virtual Editing::SnapMode snap_mode () const = 0;
virtual void set_snap_delta (Editing::SnapDelta m) = 0;
/** Set the snap mode. /** Set the snap mode.
* @param m Snap mode (defined in editing_syms.h) * @param m Snap mode (defined in editing_syms.h)
*/ */

View File

@ -139,7 +139,7 @@ class LIBARDOUR_API Region
/* first_frame() is an alias; last_frame() just hides some math */ /* first_frame() is an alias; last_frame() just hides some math */
framepos_t first_frame () const { return _position; } framepos_t first_frame () const { return _position; }
framepos_t last_frame () const { return _position + _length - 1; } framepos_t last_frame () const { return _position + _length; }
/** Return the earliest possible value of _position given the /** Return the earliest possible value of _position given the
* value of _start within the region's sources * value of _start within the region's sources
@ -151,7 +151,7 @@ class LIBARDOUR_API Region
framepos_t latest_possible_frame () const; framepos_t latest_possible_frame () const;
Evoral::Range<framepos_t> last_range () const { Evoral::Range<framepos_t> last_range () const {
return Evoral::Range<framepos_t> (_last_position, _last_position + _last_length - 1); return Evoral::Range<framepos_t> (_last_position, _last_position + _last_length);
} }
Evoral::Range<framepos_t> range () const { Evoral::Range<framepos_t> range () const {