summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/audio_region_view.cc7
-rw-r--r--gtk2_ardour/automation_time_axis.cc10
-rw-r--r--gtk2_ardour/editor.cc143
-rw-r--r--gtk2_ardour/editor.h40
-rw-r--r--gtk2_ardour/editor_canvas.cc10
-rw-r--r--gtk2_ardour/editor_drag.cc385
-rw-r--r--gtk2_ardour/editor_drag.h22
-rw-r--r--gtk2_ardour/editor_keys.cc24
-rw-r--r--gtk2_ardour/editor_mouse.cc18
-rw-r--r--gtk2_ardour/editor_ops.cc122
-rw-r--r--gtk2_ardour/midi_region_view.cc13
-rw-r--r--gtk2_ardour/midi_time_axis.cc8
-rw-r--r--gtk2_ardour/midi_time_axis.h2
-rw-r--r--gtk2_ardour/public_editor.h18
-rw-r--r--gtk2_ardour/region_view.cc9
-rw-r--r--gtk2_ardour/step_editor.cc5
-rw-r--r--gtk2_ardour/tempo_dialog.cc2
-rw-r--r--libs/ardour/ardour/audioregion.h2
-rw-r--r--libs/ardour/ardour/midi_playlist.h1
-rw-r--r--libs/ardour/ardour/midi_region.h3
-rw-r--r--libs/ardour/ardour/playlist.h10
-rw-r--r--libs/ardour/ardour/region.h4
-rw-r--r--libs/ardour/ardour/region_factory.h6
-rw-r--r--libs/ardour/ardour/tempo.h8
-rw-r--r--libs/ardour/ardour/types.h21
-rw-r--r--libs/ardour/audioregion.cc6
-rw-r--r--libs/ardour/midi_playlist.cc76
-rw-r--r--libs/ardour/midi_region.cc34
-rw-r--r--libs/ardour/playlist.cc53
-rw-r--r--libs/ardour/region.cc140
-rw-r--r--libs/ardour/region_factory.cc14
-rw-r--r--libs/ardour/strip_silence.cc2
-rw-r--r--libs/ardour/tempo.cc58
33 files changed, 744 insertions, 532 deletions
diff --git a/gtk2_ardour/audio_region_view.cc b/gtk2_ardour/audio_region_view.cc
index 177d0d92e0..ed5665ddb1 100644
--- a/gtk2_ardour/audio_region_view.cc
+++ b/gtk2_ardour/audio_region_view.cc
@@ -1347,11 +1347,10 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev, b
/* don't create points that can't be seen */
update_envelope_visibility ();
-
framepos_t rpos = region ()->position ();
- framepos_t fx = trackview.editor().pixel_to_sample (mx) + rpos;
- trackview.editor ().snap_to_with_modifier (fx, ev);
- fx -= rpos;
+ MusicFrame snap_pos (trackview.editor().pixel_to_sample (mx) + rpos, 0);
+ trackview.editor ().snap_to_with_modifier (snap_pos, ev);
+ framepos_t fx = snap_pos.frame - rpos;
if (fx > _region->length()) {
return;
diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc
index 24d4c13903..2634b87891 100644
--- a/gtk2_ardour/automation_time_axis.cc
+++ b/gtk2_ardour/automation_time_axis.cc
@@ -605,7 +605,7 @@ AutomationTimeAxisView::build_display_menu ()
}
void
-AutomationTimeAxisView::add_automation_event (GdkEvent* event, framepos_t when, double y, bool with_guard_points)
+AutomationTimeAxisView::add_automation_event (GdkEvent* event, framepos_t frame, double y, bool with_guard_points)
{
if (!_line) {
return;
@@ -632,16 +632,18 @@ AutomationTimeAxisView::add_automation_event (GdkEvent* event, framepos_t when,
_line->view_to_model_coord (x, y);
+ MusicFrame when (frame, 0);
_editor.snap_to_with_modifier (when, event);
XMLNode& before = list->get_state();
std::list<Selectable*> results;
- if (list->editor_add (when, y, with_guard_points)) {
+
+ if (list->editor_add (when.frame, y, with_guard_points)) {
XMLNode& after = list->get_state();
_editor.begin_reversible_command (_("add automation event"));
_session->add_command (new MementoCommand<ARDOUR::AutomationList> (*list.get (), &before, &after));
- _line->get_selectables (when, when, 0.0, 1.0, results);
+ _line->get_selectables (when.frame, when.frame, 0.0, 1.0, results);
_editor.get_selection ().set (results);
_editor.commit_reversible_command ();
@@ -650,7 +652,7 @@ AutomationTimeAxisView::add_automation_event (GdkEvent* event, framepos_t when,
}
bool
-AutomationTimeAxisView::paste (framepos_t pos, const Selection& selection, PasteContext& ctx, const int32_t sub_num)
+AutomationTimeAxisView::paste (framepos_t pos, const Selection& selection, PasteContext& ctx, const int32_t divisions)
{
if (_line) {
return paste_one (pos, ctx.count, ctx.times, selection, ctx.counts, ctx.greedy);
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc
index 62ad00a1d9..3ff2d710d0 100644
--- a/gtk2_ardour/editor.cc
+++ b/gtk2_ardour/editor.cc
@@ -2734,7 +2734,7 @@ Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
* @param event Event to get current key modifier information from, or 0.
*/
void
-Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, RoundMode direction, bool for_mark)
+Editor::snap_to_with_modifier (MusicFrame& start, GdkEvent const * event, RoundMode direction, bool for_mark)
{
if (!_session || !event) {
return;
@@ -2743,6 +2743,8 @@ Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, RoundM
if (ArdourKeyboard::indicates_snap (event->button.state)) {
if (_snap_mode == SnapOff) {
snap_to_internal (start, direction, for_mark);
+ } else {
+ start.set (start.frame, 0);
}
} else {
if (_snap_mode != SnapOff) {
@@ -2750,14 +2752,17 @@ Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, RoundM
} else if (ArdourKeyboard::indicates_snap_delta (event->button.state)) {
/* SnapOff, but we pressed the snap_delta modifier */
snap_to_internal (start, direction, for_mark);
+ } else {
+ start.set (start.frame, 0);
}
}
}
void
-Editor::snap_to (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
+Editor::snap_to (MusicFrame& start, RoundMode direction, bool for_mark, bool ensure_snap)
{
if (!_session || (_snap_mode == SnapOff && !ensure_snap)) {
+ start.set (start.frame, 0);
return;
}
@@ -2765,8 +2770,9 @@ Editor::snap_to (framepos_t& start, RoundMode direction, bool for_mark, bool ens
}
void
-Editor::timecode_snap_to_internal (framepos_t& start, RoundMode direction, bool /*for_mark*/)
+Editor::timecode_snap_to_internal (MusicFrame& pos, RoundMode direction, bool /*for_mark*/)
{
+ framepos_t start = pos.frame;
const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->samples_per_timecode_frame());
framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->samples_per_timecode_frame() * 60);
@@ -2828,14 +2834,16 @@ Editor::timecode_snap_to_internal (framepos_t& start, RoundMode direction, bool
fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
abort(); /*NOTREACHED*/
}
+
+ pos.set (start, 0);
}
void
-Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
+Editor::snap_to_internal (MusicFrame& start, RoundMode direction, bool for_mark, bool ensure_snap)
{
const framepos_t one_second = _session->frame_rate();
const framepos_t one_minute = _session->frame_rate() * 60;
- framepos_t presnap = start;
+ framepos_t presnap = start.frame;
framepos_t before;
framepos_t after;
@@ -2847,95 +2855,104 @@ Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark,
case SnapToCDFrame:
if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
- start % (one_second/75) == 0) {
+ start.frame % (one_second/75) == 0) {
/* start is already on a whole CD frame, do nothing */
- } else if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
- start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
+ } else if (((direction == 0) && (start.frame % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
+ start.frame = (framepos_t) ceil ((double) start.frame / (one_second / 75)) * (one_second / 75);
} else {
- start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
+ start.frame = (framepos_t) floor ((double) start.frame / (one_second / 75)) * (one_second / 75);
}
+
+ start.set (start.frame, 0);
+
break;
case SnapToSeconds:
if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
- start % one_second == 0) {
+ start.frame % one_second == 0) {
/* start is already on a whole second, do nothing */
- } else if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
- start = (framepos_t) ceil ((double) start / one_second) * one_second;
+ } else if (((direction == 0) && (start.frame % one_second > one_second / 2)) || (direction > 0)) {
+ start.frame = (framepos_t) ceil ((double) start.frame / one_second) * one_second;
} else {
- start = (framepos_t) floor ((double) start / one_second) * one_second;
+ start.frame = (framepos_t) floor ((double) start.frame / one_second) * one_second;
}
+
+ start.set (start.frame, 0);
+
break;
case SnapToMinutes:
if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
- start % one_minute == 0) {
+ start.frame % one_minute == 0) {
/* start is already on a whole minute, do nothing */
- } else if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
- start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
+ } else if (((direction == 0) && (start.frame % one_minute > one_minute / 2)) || (direction > 0)) {
+ start.frame = (framepos_t) ceil ((double) start.frame / one_minute) * one_minute;
} else {
- start = (framepos_t) floor ((double) start / one_minute) * one_minute;
+ start.frame = (framepos_t) floor ((double) start.frame / one_minute) * one_minute;
}
+
+ start.set (start.frame, 0);
+
break;
case SnapToBar:
- start = _session->tempo_map().round_to_bar (start, direction);
+ start = _session->tempo_map().round_to_bar (start.frame, direction);
break;
case SnapToBeat:
- start = _session->tempo_map().round_to_beat (start, direction);
+ start = _session->tempo_map().round_to_beat (start.frame, direction);
break;
case SnapToBeatDiv128:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 128, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 128, direction);
break;
case SnapToBeatDiv64:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 64, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 64, direction);
break;
case SnapToBeatDiv32:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 32, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 32, direction);
break;
case SnapToBeatDiv28:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 28, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 28, direction);
break;
case SnapToBeatDiv24:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 24, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 24, direction);
break;
case SnapToBeatDiv20:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 20, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 20, direction);
break;
case SnapToBeatDiv16:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 16, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 16, direction);
break;
case SnapToBeatDiv14:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 14, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 14, direction);
break;
case SnapToBeatDiv12:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 12, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 12, direction);
break;
case SnapToBeatDiv10:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 10, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 10, direction);
break;
case SnapToBeatDiv8:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 8, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 8, direction);
break;
case SnapToBeatDiv7:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 7, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 7, direction);
break;
case SnapToBeatDiv6:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 6, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 6, direction);
break;
case SnapToBeatDiv5:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 5, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 5, direction);
break;
case SnapToBeatDiv4:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 4, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 4, direction);
break;
case SnapToBeatDiv3:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 3, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 3, direction);
break;
case SnapToBeatDiv2:
- start = _session->tempo_map().round_to_quarter_note_subdivision (start, 2, direction);
+ start = _session->tempo_map().round_to_quarter_note_subdivision (start.frame, 2, direction);
break;
case SnapToMark:
@@ -2943,29 +2960,31 @@ Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark,
return;
}
- _session->locations()->marks_either_side (start, before, after);
+ _session->locations()->marks_either_side (start.frame, before, after);
if (before == max_framepos && after == max_framepos) {
/* No marks to snap to, so just don't snap */
return;
} else if (before == max_framepos) {
- start = after;
+ start.frame = after;
} else if (after == max_framepos) {
- start = before;
+ start.frame = before;
} else if (before != max_framepos && after != max_framepos) {
if ((direction == RoundUpMaybe || direction == RoundUpAlways))
- start = after;
+ start.frame = after;
else if ((direction == RoundDownMaybe || direction == RoundDownAlways))
- start = before;
+ start.frame = before;
else if (direction == 0 ) {
- if ((start - before) < (after - start)) {
- start = before;
+ if ((start.frame - before) < (after - start.frame)) {
+ start.frame = before;
} else {
- start = after;
+ start.frame = after;
}
}
}
+ start.set (start.frame, 0);
+
break;
case SnapToRegionStart:
@@ -2978,9 +2997,9 @@ Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark,
vector<framepos_t>::iterator next = region_boundary_cache.end ();
if (direction > 0) {
- next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
+ next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start.frame);
} else {
- next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
+ next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start.frame);
}
if (next != region_boundary_cache.begin ()) {
@@ -2991,12 +3010,15 @@ Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark,
framepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
framepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
- if (start > (p + n) / 2) {
- start = n;
+ if (start.frame > (p + n) / 2) {
+ start.frame = n;
} else {
- start = p;
+ start.frame = p;
}
}
+
+ start.set (start.frame, 0);
+
break;
}
@@ -3010,21 +3032,20 @@ Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark,
return;
}
- if (presnap > start) {
- if (presnap > (start + pixel_to_sample(snap_threshold))) {
- start = presnap;
+ if (presnap > start.frame) {
+ if (presnap > (start.frame + pixel_to_sample(snap_threshold))) {
+ start.set (presnap, 0);
}
- } else if (presnap < start) {
- if (presnap < (start - pixel_to_sample(snap_threshold))) {
- start = presnap;
+ } else if (presnap < start.frame) {
+ if (presnap < (start.frame - pixel_to_sample(snap_threshold))) {
+ start.set (presnap, 0);
}
}
default:
/* handled at entry */
return;
-
}
}
@@ -4067,9 +4088,9 @@ Editor::get_paste_offset (framepos_t pos, unsigned paste_count, framecnt_t durat
framecnt_t offset = paste_count * duration;
/* snap offset so pos + offset is aligned to the grid */
- framepos_t offset_pos = pos + offset;
+ MusicFrame offset_pos (pos + offset, 0);
snap_to(offset_pos, RoundUpMaybe);
- offset = offset_pos - pos;
+ offset = offset_pos.frame - pos;
return offset;
}
@@ -4740,6 +4761,8 @@ Editor::get_preferred_edit_position (EditIgnoreOption ignore, bool from_context_
ep = EditAtPlayhead;
}
+ MusicFrame snap_mf (0, 0);
+
switch (ep) {
case EditAtPlayhead:
if (_dragging_playhead) {
@@ -4772,7 +4795,9 @@ Editor::get_preferred_edit_position (EditIgnoreOption ignore, bool from_context_
/* XXX not right but what can we do ? */
return 0;
}
- snap_to (where);
+ snap_mf.frame = where;
+ snap_to (snap_mf);
+ where = snap_mf.frame;
DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
break;
}
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index 8ff19580c6..fa5ed9057a 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -452,20 +452,20 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
TrackViewList axis_views_from_routes (boost::shared_ptr<ARDOUR::RouteList>) const;
- void snap_to (framepos_t& first,
- ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
- bool for_mark = false,
- bool ensure_snap = false);
+ void snap_to (ARDOUR::MusicFrame& first,
+ ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
+ bool for_mark = false,
+ bool ensure_snap = false);
- void snap_to_with_modifier (framepos_t& first,
- GdkEvent const * ev,
- ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
- bool for_mark = false);
+ void snap_to_with_modifier (ARDOUR::MusicFrame& first,
+ GdkEvent const * ev,
+ ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
+ bool for_mark = false);
- void snap_to (framepos_t& first,
- framepos_t& last,
- ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
- bool for_mark = false);
+ void snap_to (ARDOUR::MusicFrame& first,
+ ARDOUR::MusicFrame& last,
+ ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
+ bool for_mark = false);
void begin_selection_op_history ();
void begin_reversible_selection_op (std::string cmd_name);
@@ -542,7 +542,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
/* editing operations that need to be public */
void mouse_add_new_marker (framepos_t where, bool is_cd=false);
- void split_regions_at (framepos_t, RegionSelection&, const int32_t sub_num, bool snap = true);
+ void split_regions_at (ARDOUR::MusicFrame, RegionSelection&, bool snap = true);
void split_region_at_points (boost::shared_ptr<ARDOUR::Region>, ARDOUR::AnalysisFeatureList&, bool can_ferret, bool select_new = false);
RegionSelection get_regions_from_selection_and_mouse (framepos_t);
@@ -2152,14 +2152,14 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD
void select_next_route ();
void select_prev_route ();
- void snap_to_internal (framepos_t& first,
- ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
- bool for_mark = false,
- bool ensure_snap = false);
+ void snap_to_internal (ARDOUR::MusicFrame& first,
+ ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
+ bool for_mark = false,
+ bool ensure_snap = false);
- void timecode_snap_to_internal (framepos_t& first,
- ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
- bool for_mark = false);
+ void timecode_snap_to_internal (ARDOUR::MusicFrame& first,
+ ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
+ bool for_mark = false);
RhythmFerret* rhythm_ferret;
diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc
index bc457453bc..f847a3f707 100644
--- a/gtk2_ardour/editor_canvas.cc
+++ b/gtk2_ardour/editor_canvas.cc
@@ -449,7 +449,6 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context,
{
vector<string> paths;
GdkEvent ev;
- framepos_t frame;
double cy;
if (convert_drop_to_paths (paths, context, x, y, data, info, time) == 0) {
@@ -461,9 +460,8 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context,
ev.button.x = x;
ev.button.y = y;
- frame = window_event_sample (&ev, 0, &cy);
-
- snap_to (frame);
+ MusicFrame when (window_event_sample (&ev, 0, &cy), 0);
+ snap_to (when);
bool copy = ((context->get_actions() & (Gdk::ACTION_COPY | Gdk::ACTION_LINK | Gdk::ACTION_MOVE)) == Gdk::ACTION_COPY);
#ifdef __APPLE__
@@ -471,9 +469,9 @@ Editor::drop_paths (const RefPtr<Gdk::DragContext>& context,
the main event loop with GTK/Quartz. Since import/embed wants
to push up a progress dialog, defer all this till we go idle.
*/
- Glib::signal_idle().connect (sigc::bind (sigc::mem_fun (*this, &Editor::idle_drop_paths), paths, frame, cy, copy));
+ Glib::signal_idle().connect (sigc::bind (sigc::mem_fun (*this, &Editor::idle_drop_paths), paths, when.frame, cy, copy));
#else
- drop_paths_part_two (paths, frame, cy, copy);
+ drop_paths_part_two (paths, when.frame, cy, copy);
#endif
}
diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc
index 9e763ff264..de3be07c8d 100644
--- a/gtk2_ardour/editor_drag.cc
+++ b/gtk2_ardour/editor_drag.cc
@@ -237,7 +237,7 @@ Drag::Drag (Editor* e, ArdourCanvas::Item* i, bool trackview_only)
, _raw_grab_frame (0)
, _grab_frame (0)
, _last_pointer_frame (0)
- , _snap_delta (0)
+ , _snap_delta (0, 0)
, _constraint_pressed (false)
{
@@ -268,7 +268,7 @@ Drag::start_grab (GdkEvent* event, Gdk::Cursor *cursor)
_raw_grab_frame = _editor->canvas_event_sample (event, &_grab_x, &_grab_y);
setup_pointer_frame_offset ();
- _grab_frame = adjusted_frame (_raw_grab_frame, event);
+ _grab_frame = adjusted_frame (_raw_grab_frame, event).frame;
_last_pointer_frame = _grab_frame;
_last_pointer_x = _grab_x;
@@ -324,13 +324,13 @@ Drag::end_grab (GdkEvent* event)
return _move_threshold_passed;
}
-framepos_t
+MusicFrame
Drag::adjusted_frame (framepos_t f, GdkEvent const * event, bool snap) const
{
- framepos_t pos = 0;
+ MusicFrame pos (f, 0);
if (f > _pointer_frame_offset) {
- pos = f - _pointer_frame_offset;
+ pos.frame = f - _pointer_frame_offset;
}
if (snap) {
@@ -343,14 +343,14 @@ Drag::adjusted_frame (framepos_t f, GdkEvent const * event, bool snap) const
framepos_t
Drag::adjusted_current_frame (GdkEvent const * event, bool snap) const
{
- return adjusted_frame (_drags->current_pointer_frame (), event, snap);
+ return adjusted_frame (_drags->current_pointer_frame (), event, snap).frame;
}
frameoffset_t
Drag::snap_delta (guint state) const
{
if (ArdourKeyboard::indicates_snap_delta (state)) {
- return _snap_delta;
+ return _snap_delta.frame;
}
return 0;
@@ -373,11 +373,11 @@ Drag::current_pointer_y () const
}
void
-Drag::setup_snap_delta (framepos_t pos)
+Drag::setup_snap_delta (MusicFrame pos)
{
- framepos_t temp = pos;
- _editor->snap_to (temp, ARDOUR::RoundNearest, false, true);
- _snap_delta = temp - pos;
+ MusicFrame snap (pos);
+ _editor->snap_to (snap, ARDOUR::RoundNearest, false, true);
+ _snap_delta = snap - pos;
}
bool
@@ -513,7 +513,7 @@ Drag::show_verbose_cursor_text (string const & text)
}
boost::shared_ptr<Region>
-Drag::add_midi_region (MidiTimeAxisView* view, bool commit, const int32_t sub_num)
+Drag::add_midi_region (MidiTimeAxisView* view, bool commit)
{
if (_editor->session()) {
const TempoMap& map (_editor->session()->tempo_map());
@@ -522,7 +522,7 @@ Drag::add_midi_region (MidiTimeAxisView* view, bool commit, const int32_t sub_nu
might be wrong.
*/
framecnt_t len = map.frame_at_beat (max (0.0, map.beat_at_frame (pos)) + 1.0) - pos;
- return view->add_region (grab_frame(), len, commit, sub_num);
+ return view->add_region (grab_frame(), len, commit);
}
return boost::shared_ptr<Region>();
@@ -599,33 +599,11 @@ RegionDrag::find_time_axis_view (TimeAxisView* t) const
return i;
}
-/** determines if @pos is the closest frame to an exact musical division when using SnapMagnetic.
- * (SnapMagnetic may snap to an exact division or no division at all).
- * this is a hotfix for musical region position/trim. we should really
- * deliver musical divisors when snapping magnetically to avoid this.
-*/
-int32_t
-RegionDrag::current_music_divisor (framepos_t pos, int32_t button_state)
-{
- int32_t divisions = _editor->get_grid_music_divisions (button_state);
-
- if (_editor->snap_mode() == Editing::SnapMagnetic && !ArdourKeyboard::indicates_snap (button_state)) {
- TempoMap& tmap (_editor->session()->tempo_map());
- const framepos_t exact_qn_pos = tmap.frame_at_quarter_note (tmap.exact_qn_at_frame (pos, divisions));
-
- if (pos != exact_qn_pos) {
- /* magnetic has not snapped */
- divisions = 0;
- }
- }
-
- return divisions;
-}
-
RegionMotionDrag::RegionMotionDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v, bool b)
: RegionDrag (e, i, p, v)
, _brushing (b)
, _ignore_video_lock (false)
+ , _last_position (0, 0)
, _total_x_delta (0)
, _last_pointer_time_axis_view (0)
, _last_pointer_layer (0)
@@ -640,9 +618,9 @@ void
RegionMotionDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
{
Drag::start_grab (event, cursor);
- setup_snap_delta (_last_frame_position);
+ setup_snap_delta (_last_position);
- show_verbose_cursor_time (_last_frame_position);
+ show_verbose_cursor_time (_last_position.frame);
pair<TimeAxisView*, double> const tv = _editor->trackview_by_y_position (current_pointer_y ());
if (tv.first) {
@@ -662,14 +640,13 @@ RegionMotionDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
}
double
-RegionMotionDrag::compute_x_delta (GdkEvent const * event, framepos_t* pending_region_position)
+RegionMotionDrag::compute_x_delta (GdkEvent const * event, MusicFrame* pending_region_position)
{
/* compute the amount of pointer motion in frames, and where
the region would be if we moved it by that much.
*/
*pending_region_position = adjusted_frame (_drags->current_pointer_frame (), event, false);
- framepos_t sync_frame;
framecnt_t sync_offset;
int32_t sync_dir;
@@ -677,34 +654,35 @@ RegionMotionDrag::compute_x_delta (GdkEvent const * event, framepos_t* pending_r
/* we don't handle a sync point that lies before zero.
*/
- if (sync_dir >= 0 || (sync_dir < 0 && *pending_region_position >= sync_offset)) {
+ if (sync_dir >= 0 || (sync_dir < 0 && pending_region_position->frame >= sync_offset)) {
framecnt_t const sd = snap_delta (event->button.state);
- sync_frame = *pending_region_position + (sync_dir * sync_offset) + sd;
-
- _editor->snap_to_with_modifier (sync_frame, event);
-
- *pending_region_position = _primary->region()->adjust_to_sync (sync_frame) - sd;
-
+ MusicFrame sync_snap (pending_region_position->frame + (sync_dir * sync_offset) + sd, 0);
+ _editor->snap_to_with_modifier (sync_snap, event);
+ if (sync_offset == 0 && sd == 0) {
+ *pending_region_position = sync_snap;
+ } else {
+ pending_region_position->set (_primary->region()->adjust_to_sync (sync_snap.frame) - sd, 0);
+ }
} else {
- *pending_region_position = _last_frame_position;
+ *pending_region_position = _last_position;
}
- if (*pending_region_position > max_framepos - _primary->region()->length()) {
- *pending_region_position = _last_frame_position;
+ if (pending_region_position->frame > max_framepos - _primary->region()->length()) {
+ *pending_region_position = _last_position;
}
double dx = 0;
bool const x_move_allowed = !_x_constrained;
- if ((*pending_region_position != _last_frame_position) && x_move_allowed) {
+ if ((pending_region_position->frame != _last_position.frame) && x_move_allowed) {
/* x movement since last time (in pixels) */
- dx = (static_cast<double> (*pending_region_position) - _last_frame_position) / _editor->samples_per_pixel;
+ dx = (static_cast<double> (pending_region_position->frame) - _last_position.frame) / _editor->samples_per_pixel;
/* total x movement */
- framecnt_t total_dx = *pending_region_position;
+ framecnt_t total_dx = pending_region_position->frame;
if (regions_came_from_canvas()) {
total_dx = total_dx - grab_frame ();
}
@@ -713,7 +691,7 @@ RegionMotionDrag::compute_x_delta (GdkEvent const * event, framepos_t* pending_r
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ++i) {
if ((i->view->region()->position() + total_dx) < 0) {
dx = 0;
- *pending_region_position = _last_frame_position;
+ *pending_region_position = _last_position;
break;
}
}
@@ -954,9 +932,9 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
}
/* Work out the change in x */
- framepos_t pending_region_position;
+ MusicFrame pending_region_position (0, 0);
double const x_delta = compute_x_delta (event, &pending_region_position);
- _last_frame_position = pending_region_position;
+ _last_position = pending_region_position;
/* calculate hidden tracks in current y-axis delta */
int delta_skip = 0;
@@ -1159,7 +1137,7 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
i->layer += this_delta_layer;
if (_brushing) {
- _editor->mouse_brush_insert_region (rv, pending_region_position);
+ _editor->mouse_brush_insert_region (rv, pending_region_position.frame);
} else {
Duple track_origin;
@@ -1206,7 +1184,7 @@ RegionMotionDrag::motion (GdkEvent* event, bool first_move)
_total_x_delta += x_delta;
if (x_delta != 0 && !_brushing) {
- show_verbose_cursor_time (_last_frame_position);
+ show_verbose_cursor_time (_last_position.frame);
}
/* keep track of pointer movement */
@@ -1296,12 +1274,7 @@ RegionMoveDrag::motion (GdkEvent* event, bool first_move)
const boost::shared_ptr<const Region> original = rv->region();
boost::shared_ptr<Region> region_copy;
- if (rv == _primary) {
- region_copy = RegionFactory::create (original, true
- , current_music_divisor (original->position(), event->button.state));
- } else {
- region_copy = RegionFactory::create (original, true, 0);
- }
+ region_copy = RegionFactory::create (original, true);
/* need to set this so that the drop zone code can work. This doesn't
actually put the region into the playlist, but just sets a weak pointer
@@ -1399,16 +1372,15 @@ RegionMoveDrag::finished (GdkEvent* ev, bool movement_occurred)
i->view->get_canvas_group()->show ();
}
- bool const changed_position = (_last_frame_position != _primary->region()->position());
+ bool const changed_position = (_last_position.frame != _primary->region()->position());
bool const changed_tracks = (_time_axis_views[_views.front().time_axis_view] != &_views.front().view->get_time_axis_view());
- framecnt_t const drag_delta = _primary->region()->position() - _last_frame_position;
if (_copy) {
finished_copy (
changed_position,
changed_tracks,
- drag_delta,
+ _last_position,
ev->button.state
);
@@ -1417,7 +1389,7 @@ RegionMoveDrag::finished (GdkEvent* ev, bool movement_occurred)
finished_no_copy (
changed_position,
changed_tracks,
- drag_delta,
+ _last_position,
ev->button.state
);
@@ -1462,15 +1434,16 @@ RegionMoveDrag::create_destination_time_axis (boost::shared_ptr<Region> region,
}
void
-RegionMoveDrag::finished_copy (bool const changed_position, bool const /*changed_tracks*/, framecnt_t const drag_delta, int32_t const ev_state)
+RegionMoveDrag::finished_copy (bool const changed_position, bool const /*changed_tracks*/, MusicFrame last_position, int32_t const ev_state)
{
RegionSelection new_views;
PlaylistSet modified_playlists;
RouteTimeAxisView* new_time_axis_view = 0;
+ framecnt_t const drag_delta = _primary->region()->position() - _last_position.frame;
- int32_t divisor = current_music_divisor (_primary->region()->position() - drag_delta, ev_state);
TempoMap& tmap (_editor->session()->tempo_map());
- double qn_delta = _primary->region()->quarter_note() - tmap.exact_qn_at_frame (_primary->region()->position() - drag_delta, divisor);
+ const double last_pos_qn = tmap.exact_qn_at_frame (last_position.frame, last_position.division);
+ const double qn_delta = _primary->region()->quarter_note() - last_pos_qn;
if (_brushing) {
/* all changes were made during motion event handlers */
@@ -1495,12 +1468,16 @@ RegionMoveDrag::finished_copy (bool const changed_position, bool const /*changed
continue;
}
- framepos_t where;
+ MusicFrame where (0, 0);
+ double quarter_note;
if (changed_position && !_x_constrained) {
- where = i->view->region()->position() - drag_delta;
+ where.set (i->view->region()->position() - drag_delta, 0);
+ quarter_note = i->view->region()->quarter_note() - qn_delta;
} else {
- where = i->view->region()->position();
+ /* region has not moved - divisor will not affect musical pos */
+ where.set (i->view->region()->position(), 0);
+ quarter_note = i->view->region()->quarter_note();
}
if (i->time_axis_view < 0 || i->time_axis_view >= (int)_time_axis_views.size()) {
@@ -1528,17 +1505,16 @@ RegionMoveDrag::finished_copy (bool const changed_position, bool const /*changed
if (dest_rtv != 0) {
RegionView* new_view;
- if (i->view == _primary) {
- new_view = insert_region_into_playlist (i->view->region(), dest_rtv, i->layer, where,
- modified_playlists, current_music_divisor (where, ev_state));
+ if (i->view == _primary && !_x_constrained) {
+ new_view = insert_region_into_playlist (i->view->region(), dest_rtv, i->layer, last_position, last_pos_qn,
+ modified_playlists, true);
} else {
if (i->view->region()->position_lock_style() == AudioTime) {
- new_view = insert_region_into_playlist (i->view->region(), dest_rtv, i->layer, where,
- modified_playlists, 0);
+ new_view = insert_region_into_playlist (i->view->region(), dest_rtv, i->layer, where, quarter_note,
+ modified_playlists);
} else {
- where = tmap.frame_at_quarter_note (i->view->region()->quarter_note() - qn_delta);
- new_view = insert_region_into_playlist (i->view->region(), dest_rtv, i->layer, where,
- modified_playlists, 0);
+ new_view = insert_region_into_playlist (i->view->region(), dest_rtv, i->layer, where, quarter_note,
+ modified_playlists, true);
}
}
@@ -1575,7 +1551,7 @@ void
RegionMoveDrag::finished_no_copy (
bool const changed_position,
bool const changed_tracks,
- framecnt_t const drag_delta,
+ MusicFrame last_position,
int32_t const ev_state
)
{
@@ -1584,13 +1560,14 @@ RegionMoveDrag::finished_no_copy (
PlaylistSet frozen_playlists;
set<RouteTimeAxisView*> views_to_update;
RouteTimeAxisView* new_time_axis_view = 0;
+ framecnt_t const drag_delta = _primary->region()->position() - _last_position.frame;
typedef map<boost::shared_ptr<Playlist>, RouteTimeAxisView*> PlaylistMapping;
PlaylistMapping playlist_mapping;
- int32_t divisor = current_music_divisor (_primary->region()->position() - drag_delta, ev_state);
TempoMap& tmap (_editor->session()->tempo_map());
- double qn_delta = _primary->region()->quarter_note() - tmap.exact_qn_at_frame (_primary->region()->position() - drag_delta, divisor);
+ const double last_pos_qn = tmap.exact_qn_at_frame (last_position.frame, last_position.division);
+ const double qn_delta = _primary->region()->quarter_note() - last_pos_qn;
std::set<boost::shared_ptr<const Region> > uniq;
for (list<DraggingView>::const_iterator i = _views.begin(); i != _views.end(); ) {
@@ -1640,12 +1617,15 @@ RegionMoveDrag::finished_no_copy (
views_to_update.insert (dest_rtv);
- framepos_t where;
+ MusicFrame where (0, 0);
+ double quarter_note;
if (changed_position && !_x_constrained) {
- where = rv->region()->position() - drag_delta;
+ where.set (rv->region()->position() - drag_delta, 0);
+ quarter_note = i->view->region()->quarter_note() - qn_delta;
} else {
- where = rv->region()->position();
+ where.set (rv->region()->position(), 0);
+ quarter_note = i->view->region()->quarter_note();
}
if (changed_tracks) {
@@ -1654,21 +1634,20 @@ RegionMoveDrag::finished_no_copy (
RegionView* new_view;
if (rv == _primary) {
new_view = insert_region_into_playlist (
- RegionFactory::create (rv->region (), true), dest_rtv, dest_layer, where,
- modified_playlists, current_music_divisor (where, ev_state)
+ RegionFactory::create (rv->region (), true), dest_rtv, dest_layer, last_position, last_pos_qn,
+ modified_playlists, true
);
} else {
if (rv->region()->position_lock_style() == AudioTime) {
new_view = insert_region_into_playlist (
- RegionFactory::create (rv->region (), true), dest_rtv, dest_layer, where,
- modified_playlists, 0
+ RegionFactory::create (rv->region (), true), dest_rtv, dest_layer, where, quarter_note,
+ modified_playlists
);
} else {
- where = tmap.frame_at_quarter_note (rv->region()->quarter_note() - qn_delta);
new_view = insert_region_into_playlist (
- RegionFactory::create (rv->region (), true), dest_rtv, dest_layer, where,
- modified_playlists, 0
+ RegionFactory::create (rv->region (), true), dest_rtv, dest_layer, where, quarter_note,
+ modified_playlists, true
);
}
}
@@ -1730,13 +1709,14 @@ RegionMoveDrag::finished_no_copy (
playlist->freeze ();
}
if (rv == _primary) {
- rv->region()->set_position (where, current_music_divisor (where, ev_state));
+ rv->region()->set_position (where.frame, last_position.division);
} else {
if (rv->region()->position_lock_style() == AudioTime) {
- rv->region()->set_position (where, 0);
+ /* move by frame offset */
+ rv->region()->set_position (where.frame, 0);
} else {
- rv->region()->set_position (tmap.frame_at_quarter_note (rv->region()->quarter_note() - qn_delta), 0);
-
+ /* move by music offset */
+ rv->region()->set_position_music (rv->region()->quarter_note() - qn_delta);
}
}
_editor->session()->add_command (new StatefulDiffCommand (rv->region()));
@@ -1838,11 +1818,12 @@ RegionMoveDrag::remove_region_from_playlist (
RegionView *
RegionMoveDrag::insert_region_into_playlist (
boost::shared_ptr<Region> region,
- RouteTimeAxisView* dest_rtv,
- layer_t dest_layer,
- framecnt_t where,
- PlaylistSet& modified_playlists,
- const int32_t sub_num
+ RouteTimeAxisView* dest_rtv,
+ layer_t dest_layer,
+ MusicFrame where,
+ double quarter_note,
+ PlaylistSet& modified_playlists,
+ bool for_music
)
{
boost::shared_ptr<Playlist> dest_playlist = dest_rtv->playlist ();
@@ -1859,7 +1840,11 @@ RegionMoveDrag::insert_region_into_playlist (
if (r.second) {
dest_playlist->clear_changes ();
}
- dest_playlist->add_region (region, where, 1.0, false, sub_num);
+ if (for_music) {
+ dest_playlist->add_region (region, where.frame, 1.0, false, where.division, quarter_note, true);
+ } else {
+ dest_playlist->add_region (region, where.frame, 1.0, false, where.division);
+ }
if (dest_rtv->view()->layer_display() == Stacked || dest_rtv->view()->layer_display() == Expanded) {
dest_playlist->set_layer (region, dest_layer);
@@ -1954,13 +1939,13 @@ RegionMoveDrag::RegionMoveDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p,
speed = rtv->track()->speed ();
}
- _last_frame_position = static_cast<framepos_t> (_primary->region()->position() / speed);
+ _last_position = MusicFrame (static_cast<framepos_t> (_primary->region()->position() / speed), 0);
}
void
RegionMoveDrag::setup_pointer_frame_offset ()
{
- _pointer_frame_offset = raw_grab_frame() - _last_frame_position;
+ _pointer_frame_offset = raw_grab_frame() - _last_position.frame;
}
RegionInsertDrag::RegionInsertDrag (Editor* e, boost::shared_ptr<Region> r, RouteTimeAxisView* v, framepos_t pos)
@@ -1977,7 +1962,7 @@ RegionInsertDrag::RegionInsertDrag (Editor* e, boost::shared_ptr<Region> r, Rout
_primary->set_position (pos, 0);
_views.push_back (DraggingView (_primary, this, v));
- _last_frame_position = pos;
+ _last_position = MusicFrame (pos, 0);
_item = _primary->get_canvas_group ();
}
@@ -1997,11 +1982,11 @@ RegionInsertDrag::finished (GdkEvent * event, bool)
_editor->begin_reversible_command (Operations::insert_region);
playlist->clear_changes ();
- playlist->add_region (_primary->region (), _last_frame_position);
+ playlist->add_region (_primary->region (), _last_position.frame, _editor->get_grid_music_divisions (event->button.state));
// Mixbus doesn't seem to ripple when inserting regions from the list: should we? yes, probably
if (Config->get_edit_mode() == Ripple) {
- playlist->ripple (_last_frame_position, _primary->region()->length(), _primary->region());
+ playlist->ripple (_last_position.frame, _primary->region()->length(), _primary->region());
}
_editor->session()->add_command (new StatefulDiffCommand (playlist));
@@ -2278,7 +2263,7 @@ RegionRippleDrag::motion (GdkEvent* event, bool first_move)
framepos_t where = adjusted_current_frame (event);
assert (where >= 0);
- framepos_t after;
+ MusicFrame after (0, 0);
double delta = compute_x_delta (event, &after);
framecnt_t amount = _editor->pixel_to_sample (delta);
@@ -2328,7 +2313,7 @@ RegionRippleDrag::motion (GdkEvent* event, bool first_move)
prev_amount += amount;
}
- _last_frame_position = after;
+ _last_position = after;
}
void
@@ -2409,7 +2394,7 @@ RegionCreateDrag::motion (GdkEvent* event, bool first_move)
{
if (first_move) {
_editor->begin_reversible_command (_("create region"));
- _region = add_midi_region (_view, false, _editor->get_grid_music_divisions (event->button.state));
+ _region = add_midi_region (_view, false);
_view->playlist()->freeze ();
} else {
if (_region) {
@@ -2435,7 +2420,7 @@ void
RegionCreateDrag::finished (GdkEvent* event, bool movement_occurred)
{
if (!movement_occurred) {
- add_midi_region (_view, true, _editor->get_grid_music_divisions (event->button.state));
+ add_midi_region (_view, true);
} else {
_view->playlist()->thaw ();
_editor->commit_reversible_command();
@@ -2867,7 +2852,7 @@ TrimDrag::start_grab (GdkEvent* event, Gdk::Cursor*)
framecnt_t const region_length = (framecnt_t) (_primary->region()->length() / speed);
framepos_t const pf = adjusted_current_frame (event);
- setup_snap_delta (region_start);
+ setup_snap_delta (MusicFrame (region_start, 0));
if (Keyboard::modifier_state_equals (event->button.state, ArdourKeyboard::trim_contents_modifier ())) {
/* Move the contents of the region around without changing the region bounds */
@@ -2930,8 +2915,8 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
if (tv && tv->is_track()) {
speed = tv->track()->speed();
}
- framecnt_t adj_frame = adjusted_frame (_drags->current_pointer_frame () + snap_delta (event->button.state), event, true);
- framecnt_t dt = adj_frame - raw_grab_frame () + _pointer_frame_offset - snap_delta (event->button.state);
+ MusicFrame adj_frame = adjusted_frame (_drags->current_pointer_frame () + snap_delta (event->button.state), event, true);
+ framecnt_t dt = adj_frame.frame - raw_grab_frame () + _pointer_frame_offset - snap_delta (event->button.state);
if (first_move) {
@@ -3012,13 +2997,11 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
}
}
- int32_t divisions = current_music_divisor (adj_frame, event->button.state);
-
switch (_operation) {
case StartTrim:
for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
bool changed = i->view->trim_front (i->initial_position + dt, non_overlap_trim
- , divisions);
+ , adj_frame.division);
if (changed && _preserve_fade_anchor) {
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (i->view);
@@ -3037,7 +3020,7 @@ TrimDrag::motion (GdkEvent* event, bool first_move)
case EndTrim:
for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
- bool changed = i->view->trim_end (i->initial_end + dt, non_overlap_trim, divisions);
+ bool changed = i->view->trim_end (i->initial_end + dt, non_overlap_trim, adj_frame.division);
if (changed && _preserve_fade_anchor) {
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (i->view);
if (arv) {
@@ -3156,7 +3139,7 @@ TrimDrag::finished (GdkEvent* event, bool movement_occurred)
} else {
/* no mouse movement */
- if (adjusted_current_frame (event) != adjusted_frame (_drags->current_pointer_frame(), event, false)) {
+ if (adjusted_current_frame (event) != adjusted_frame (_drags->current_pointer_frame(), event, false).frame) {
_editor->point_trim (event, adjusted_current_frame (event));
}
}
@@ -3648,14 +3631,14 @@ void
CursorDrag::start_grab (GdkEvent* event, Gdk::Cursor* c)
{
Drag::start_grab (event, c);
- setup_snap_delta (_editor->playhead_cursor->current_frame ());
+ const framepos_t current_frame = _editor->playhead_cursor->current_frame();
+ setup_snap_delta (MusicFrame (current_frame, 0));
_grab_zoom = _editor->samples_per_pixel;
- framepos_t where = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
+ MusicFrame where (_editor->canvas_event_sample (event) + snap_delta (event->button.state), 0);
_editor->snap_to_with_modifier (where, event);
-
_editor->_dragging_playhead = true;
Session* s = _editor->session ();
@@ -3690,16 +3673,18 @@ CursorDrag::start_grab (GdkEvent* event, Gdk::Cursor* c)
}
}
- fake_locate (where - snap_delta (event->button.state));
+ fake_locate (where.frame - snap_delta (event->button.state));
}
void
CursorDrag::motion (GdkEvent* event, bool)
{
- framepos_t where = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
+ MusicFrame where (_editor->canvas_event_sample (event) + snap_delta (event->button.state), 0);
+
_editor->snap_to_with_modifier (where, event);
- if (where != last_pointer_frame()) {
- fake_locate (where - snap_delta (event->button.state));
+
+ if (where.frame != last_pointer_frame()) {
+ fake_locate (where.frame - snap_delta (event->button.state));
}
}
@@ -3734,7 +3719,7 @@ CursorDrag::aborted (bool)
_editor->_dragging_playhead = false;
}
- _editor->playhead_cursor->set_position (adjusted_frame (grab_frame (), 0, false));
+ _editor->playhead_cursor->set_position (adjusted_frame (grab_frame (), 0, false).frame);
}
FadeInDrag::FadeInDrag (Editor* e, ArdourCanvas::Item* i, RegionView* p, list<RegionView*> const & v)
@@ -3750,7 +3735,8 @@ FadeInDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary);
boost::shared_ptr<AudioRegion> const r = arv->audio_region ();
- setup_snap_delta (r->position ());
+ const int32_t division = _editor->get_grid_music_divisions (event->button.state);
+ setup_snap_delta (MusicFrame (r->position(), division));
show_verbose_cursor_duration (r->position(), r->position() + r->fade_in()->back()->when, 32);
}
@@ -3768,18 +3754,19 @@ FadeInDrag::motion (GdkEvent* event, bool)
{
framecnt_t fade_length;
- framepos_t pos = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
+ MusicFrame pos (_editor->canvas_event_sample (event) + snap_delta (event->button.state), 0);
_editor->snap_to_with_modifier (pos, event);
- pos -= snap_delta (event->button.state);
+
+ pos.frame -= snap_delta (event->button.state);
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ());
- if (pos < (region->position() + 64)) {
+ if (pos.frame < (region->position() + 64)) {
fade_length = 64; // this should be a minimum defined somewhere
- } else if (pos > region->position() + region->length() - region->fade_out()->back()->when) {
+ } else if (pos.frame > region->position() + region->length() - region->fade_out()->back()->when) {
fade_length = region->length() - region->fade_out()->back()->when - 1;
} else {
- fade_length = pos - region->position();
+ fade_length = pos.frame - region->position();
}
for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
@@ -3804,18 +3791,19 @@ FadeInDrag::finished (GdkEvent* event, bool movement_occurred)
}
framecnt_t fade_length;
- framepos_t pos = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
+ MusicFrame pos (_editor->canvas_event_sample (event) + snap_delta (event->button.state), 0);
+
_editor->snap_to_with_modifier (pos, event);
- pos -= snap_delta (event->button.state);
+ pos.frame -= snap_delta (event->button.state);
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ());
- if (pos < (region->position() + 64)) {
+ if (pos.frame < (region->position() + 64)) {
fade_length = 64; // this should be a minimum defined somewhere
- } else if (pos >= region->position() + region->length() - region->fade_out()->back()->when) {
+ } else if (pos.frame >= region->position() + region->length() - region->fade_out()->back()->when) {
fade_length = region->length() - region->fade_out()->back()->when - 1;
} else {
- fade_length = pos - region->position();
+ fade_length = pos.frame - region->position();
}
bool in_command = false;
@@ -3874,7 +3862,8 @@ FadeOutDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
AudioRegionView* arv = dynamic_cast<AudioRegionView*> (_primary);
boost::shared_ptr<AudioRegion> r = arv->audio_region ();
- setup_snap_delta (r->last_frame ());
+ const int32_t division = _editor->get_grid_music_divisions (event->button.state);
+ setup_snap_delta (MusicFrame (r->last_frame(), division));
show_verbose_cursor_duration (r->last_frame() - r->fade_out()->back()->when, r->last_frame());
}
@@ -3891,19 +3880,19 @@ void
FadeOutDrag::motion (GdkEvent* event, bool)
{
framecnt_t fade_length;
+ MusicFrame pos (_editor->canvas_event_sample (event) + snap_delta (event->button.state), 0);
- framepos_t pos = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
_editor->snap_to_with_modifier (pos, event);
- pos -= snap_delta (event->button.state);
+ pos.frame -= snap_delta (event->button.state);
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ());
- if (pos > (region->last_frame() - 64)) {
+ if (pos.frame > (region->last_frame() - 64)) {
fade_length = 64; // this should really be a minimum fade defined somewhere
- } else if (pos <= region->position() + region->fade_in()->back()->when) {
+ } else if (pos.frame <= region->position() + region->fade_in()->back()->when) {
fade_length = region->length() - region->fade_in()->back()->when - 1;
} else {
- fade_length = region->last_frame() - pos;
+ fade_length = region->last_frame() - pos.frame;
}
for (list<DraggingView>::iterator i = _views.begin(); i != _views.end(); ++i) {
@@ -3928,19 +3917,19 @@ FadeOutDrag::finished (GdkEvent* event, bool movement_occurred)
}
framecnt_t fade_length;
+ MusicFrame pos (_editor->canvas_event_sample (event) + snap_delta (event->button.state), 0);
- framepos_t pos = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
_editor->snap_to_with_modifier (pos, event);
- pos -= snap_delta (event->button.state);
+ pos.frame -= snap_delta (event->button.state);
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (_primary->region ());
- if (pos > (region->last_frame() - 64)) {
+ if (pos.frame > (region->last_frame() - 64)) {
fade_length = 64; // this should really be a minimum fade defined somewhere
- } else if (pos <= region->position() + region->fade_in()->back()->when) {
+ } else if (pos.frame <= region->position() + region->fade_in()->back()->when) {
fade_length = region->length() - region->fade_in()->back()->when - 1;
} else {
- fade_length = region->last_frame() - pos;
+ fade_length = region->last_frame() - pos.frame;
}
bool in_command = false;
@@ -4035,7 +4024,9 @@ MarkerDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
} else {
show_verbose_cursor_time (location->end());
}
- setup_snap_delta (is_start ? location->start() : location->end());
+ const int32_t division = _editor->get_grid_music_divisions (event->button.state);
+ const framepos_t pos = is_start ? location->start() : location->end();
+ setup_snap_delta (MusicFrame (pos, division));
Selection::Operation op = ArdourKeyboard::selection_type (event->button.state);
@@ -4139,7 +4130,7 @@ MarkerDrag::motion (GdkEvent* event, bool)
Location *copy_location = 0;
framecnt_t const sd = snap_delta (event->button.state);
- framecnt_t const newframe = adjusted_frame (_drags->current_pointer_frame () + sd, event, true) - sd;
+ framecnt_t const newframe = adjusted_frame (_drags->current_pointer_frame () + sd, event, true).frame - sd;
framepos_t next = newframe;
if (Keyboard::modifier_state_contains (event->button.state, ArdourKeyboard::push_points_modifier ())) {
@@ -4422,8 +4413,9 @@ ControlPointDrag::start_grab (GdkEvent* event, Gdk::Cursor* /*cursor*/)
_fixed_grab_x = _point->get_x() + _editor->sample_to_pixel_unrounded (_point->line().offset());
_fixed_grab_y = _point->get_y();
- framepos_t pos = _editor->pixel_to_sample (_fixed_grab_x);
- setup_snap_delta (pos);
+ const framepos_t pos = _editor->pixel_to_sample (_fixed_grab_x);
+ const int32_t division = _editor->get_grid_music_divisions (event->button.state);
+ setup_snap_delta (MusicFrame (pos, division));
float const fraction = 1 - (_point->get_y() / _point->line().height());
show_verbose_cursor_text (_point->line().get_verbose_cursor_string (fraction));
@@ -4476,13 +4468,14 @@ ControlPointDrag::motion (GdkEvent* event, bool first_motion)
cy = zero_gain_y;
}
- framepos_t cx_frames = _editor->pixel_to_sample (cx) + snap_delta (event->button.state);
+ MusicFrame cx_mf (_editor->pixel_to_sample (cx) + snap_delta (event->button.state), 0);
+
if (!_x_constrained && need_snap) {
- _editor->snap_to_with_modifier (cx_frames, event);
+ _editor->snap_to_with_modifier (cx_mf, event);
}
- cx_frames -= snap_delta (event->button.state);
- cx_frames = min (cx_frames, _point->line().maximum_time() + _point->line().offset());
+ cx_mf.frame -= snap_delta (event->button.state);
+ cx_mf.frame = min (cx_mf.frame, _point->line().maximum_time() + _point->line().offset());
float const fraction = 1.0 - (cy / _point->line().height());
@@ -4492,7 +4485,7 @@ ControlPointDrag::motion (GdkEvent* event, bool first_motion)
_point->line().start_drag_single (_point, _fixed_grab_x, initial_fraction);
}
pair<double, float> result;
- result = _point->line().drag_motion (_editor->sample_to_pixel_unrounded (cx_frames), fraction, false, _pushing, _final_index);
+ result = _point->line().drag_motion (_editor->sample_to_pixel_unrounded (cx_mf.frame), fraction, false, _pushing, _final_index);
show_verbose_cursor_text (_point->line().get_verbose_cursor_string (result.second));
}
@@ -4755,24 +4748,23 @@ RubberbandSelectDrag::motion (GdkEvent* event, bool)
framepos_t end;
double y1;
double y2;
-
framepos_t const pf = adjusted_current_frame (event, UIConfiguration::instance().get_rubberbanding_snaps_to_grid());
+ MusicFrame grab (grab_frame (), 0);
- framepos_t grab = grab_frame ();
if (UIConfiguration::instance().get_rubberbanding_snaps_to_grid ()) {
_editor->snap_to_with_modifier (grab, event);
} else {
- grab = raw_grab_frame ();
+ grab.frame = raw_grab_frame ();
}
/* base start and end on initial click position */
- if (pf < grab) {
+ if (pf < grab.frame) {
start = pf;
- end = grab;
+ end = grab.frame;
} else {
end = pf;
- start = grab;
+ start = grab.frame;
}
if (current_pointer_y() < grab_y()) {
@@ -4882,7 +4874,7 @@ RubberbandSelectDrag::finished (GdkEvent* event, bool movement_occurred)
/* MIDI track */
if (_editor->selection->empty() && _editor->mouse_mode == MouseDraw) {
/* nothing selected */
- add_midi_region (mtv, true, _editor->get_grid_music_divisions(event->button.state));
+ add_midi_region (mtv, true);
do_deselect = false;
}
}
@@ -4922,7 +4914,8 @@ TimeFXDrag::start_grab (GdkEvent* event, Gdk::Cursor* cursor)
_editor->get_selection().add (_primary);
framepos_t where = _primary->region()->position();
- setup_snap_delta (where);
+ const int32_t division = _editor->get_grid_music_divisions (event->button.state);
+ setup_snap_delta (MusicFrame (where, division));
show_verbose_cursor_duration (where, adjusted_current_frame (event), 0);
}
@@ -4932,19 +4925,19 @@ TimeFXDrag::motion (GdkEvent* event, bool)
{
RegionView* rv = _primary;
StreamView* cv = rv->get_time_axis_view().view ();
-
pair<TimeAxisView*, double> const tv = _editor->trackview_by_y_position (grab_y());
int layer = tv.first->layer_display() == Overlaid ? 0 : tv.second;
int layers = tv.first->layer_display() == Overlaid ? 1 : cv->layers();
- framepos_t pf = _editor->canvas_event_sample (event) + snap_delta (event->button.state);
+ MusicFrame pf (_editor->canvas_event_sample (event) + snap_delta (event->button.state), 0);
+
_editor->snap_to_with_modifier (pf, event);
- pf -= snap_delta (event->button.state);
+ pf.frame -= snap_delta (event->button.state);
- if (pf > rv->region()->position()) {
- rv->get_time_axis_view().show_timestretch (rv->region()->position(), pf, layers, layer);
+ if (pf.frame > rv->region()->position()) {
+ rv->get_time_axis_view().show_timestretch (rv->region()->position(), pf.frame, layers, layer);
}
- show_verbose_cursor_duration (_primary->region()->position(), pf, 0);
+ show_verbose_cursor_duration (_primary->region()->position(), pf.frame, 0);
}
void
@@ -5128,7 +5121,7 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
framepos_t end = 0;
framecnt_t length = 0;
framecnt_t distance = 0;
-
+ MusicFrame start_mf (0, 0);
framepos_t const pending_position = adjusted_current_frame (event);
if (_operation != CreateSelection && pending_position == last_pointer_frame()) {
@@ -5142,23 +5135,22 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
switch (_operation) {
case CreateSelection:
{
- framepos_t grab = grab_frame ();
-
+ MusicFrame grab (grab_frame (), 0);
if (first_move) {
- grab = adjusted_current_frame (event, false);
- if (grab < pending_position) {
+ grab.frame = adjusted_current_frame (event, false);
+ if (grab.frame < pending_position) {
_editor->snap_to (grab, RoundDownMaybe);
} else {
_editor->snap_to (grab, RoundUpMaybe);
}
}
- if (pending_position < grab) {
+ if (pending_position < grab.frame) {
start = pending_position;
- end = grab;
+ end = grab.frame;
} else {
end = pending_position;
- start = grab;
+ start = grab.frame;
}
/* first drag: Either add to the selection
@@ -5269,9 +5261,11 @@ SelectionDrag::motion (GdkEvent* event, bool first_move)
length = end - start;
distance = pending_position - start;
start = pending_position;
- _editor->snap_to (start);
- end = start + length;
+ start_mf.frame = start;
+ _editor->snap_to (start_mf);
+
+ end = start_mf.frame + length;
break;
@@ -5466,15 +5460,15 @@ RangeMarkerBarDrag::motion (GdkEvent* event, bool first_move)
framepos_t const pf = adjusted_current_frame (event);
if (_operation == CreateSkipMarker || _operation == CreateRangeMarker || _operation == CreateTransportMarker || _operation == CreateCDMarker) {
- framepos_t grab = grab_frame ();
+ MusicFrame grab (grab_frame (), 0);
_editor->snap_to (grab);
if (pf < grab_frame()) {
start = pf;
- end = grab;
+ end = grab.frame;
} else {
end = pf;
- start = grab;
+ start = grab.frame;
}
/* first drag: Either add to the selection
@@ -5653,7 +5647,7 @@ NoteDrag::start_grab (GdkEvent* event, Gdk::Cursor *)
_copy = false;
}
- setup_snap_delta (_region->source_beats_to_absolute_frames (_primary->note()->time ()));
+ setup_snap_delta (MusicFrame (_region->source_beats_to_absolute_frames (_primary->note()->time ()), 0));
if (!(_was_selected = _primary->selected())) {
@@ -6616,10 +6610,10 @@ RegionCutDrag::start_grab (GdkEvent* event, Gdk::Cursor* c)
void
RegionCutDrag::motion (GdkEvent* event, bool)
{
- framepos_t pos = _drags->current_pointer_frame();
+ MusicFrame pos (_drags->current_pointer_frame(), 0);
_editor->snap_to_with_modifier (pos, event);
- line->set_position (pos);
+ line->set_position (pos.frame);
}
void
@@ -6627,19 +6621,18 @@ RegionCutDrag::finished (GdkEvent* event, bool)
{
_editor->get_track_canvas()->canvas()->re_enter();
- framepos_t pos = _drags->current_pointer_frame();
- _editor->snap_to_with_modifier (pos, event);
+ MusicFrame pos (_drags->current_pointer_frame(), 0);
+ _editor->snap_to_with_modifier (pos, event);
line->hide ();
- RegionSelection rs = _editor->get_regions_from_selection_and_mouse (pos);
+ RegionSelection rs = _editor->get_regions_from_selection_and_mouse (pos.frame);
if (rs.empty()) {
return;
}
- _editor->split_regions_at (pos, rs, _editor->get_grid_music_divisions (event->button.state),
- false);
+ _editor->split_regions_at (pos, rs, false);
}
void
diff --git a/gtk2_ardour/editor_drag.h b/gtk2_ardour/editor_drag.h
index b5ebc3b39d..e5a02743fc 100644
--- a/gtk2_ardour/editor_drag.h
+++ b/gtk2_ardour/editor_drag.h
@@ -144,7 +144,7 @@ public:
bool motion_handler (GdkEvent*, bool);
void abort ();
- ARDOUR::framepos_t adjusted_frame (ARDOUR::framepos_t, GdkEvent const *, bool snap = true) const;
+ ARDOUR::MusicFrame adjusted_frame (ARDOUR::framepos_t, GdkEvent const *, bool snap = true) const;
ARDOUR::framepos_t adjusted_current_frame (GdkEvent const *, bool snap = true) const;
bool was_double_click() const { return _was_double_click; }
@@ -247,9 +247,9 @@ protected:
double current_pointer_y () const;
/* sets snap delta from unsnapped pos */
- void setup_snap_delta (framepos_t pos);
+ void setup_snap_delta (ARDOUR::MusicFrame pos);
- boost::shared_ptr<ARDOUR::Region> add_midi_region (MidiTimeAxisView*, bool commit, const int32_t sub_num);
+ boost::shared_ptr<ARDOUR::Region> add_midi_region (MidiTimeAxisView*, bool commit);
void show_verbose_cursor_time (framepos_t);
void show_verbose_cursor_duration (framepos_t, framepos_t, double xoffset = 0);
@@ -281,7 +281,7 @@ private:
/* difference between some key position's snapped and unsnapped
* framepos. used for relative snap.
*/
- ARDOUR::frameoffset_t _snap_delta;
+ ARDOUR::MusicFrame _snap_delta;
CursorContext::Handle _cursor_ctx; ///< cursor change context
bool _constraint_pressed; ///< if the keyboard indicated constraint modifier was pressed on start_grab()
};
@@ -328,7 +328,6 @@ protected:
std::vector<TimeAxisView*> _time_axis_views;
int find_time_axis_view (TimeAxisView *) const;
int apply_track_delta (const int start, const int delta, const int skip, const bool distance_only = false) const;
- int32_t current_music_divisor (framepos_t pos, int32_t button_state);
int _visible_y_low;
int _visible_y_high;
@@ -363,12 +362,12 @@ public:
protected:
- double compute_x_delta (GdkEvent const *, ARDOUR::framepos_t *);
+ double compute_x_delta (GdkEvent const *, ARDOUR::MusicFrame *);
virtual bool y_movement_allowed (int, double, int skip_invisible = 0) const;
bool _brushing;
bool _ignore_video_lock;
- ARDOUR::framepos_t _last_frame_position; ///< last position of the thing being dragged
+ ARDOUR::MusicFrame _last_position; ///< last position of the thing being dragged
double _total_x_delta;
int _last_pointer_time_axis_view;
double _last_pointer_layer;
@@ -410,14 +409,14 @@ private:
void finished_no_copy (
bool const,
bool const,
- ARDOUR::framecnt_t const,
+ ARDOUR::MusicFrame,
int32_t const ev_state
);
void finished_copy (
bool const,
bool const,
- ARDOUR::framecnt_t const,
+ ARDOUR::MusicFrame,
int32_t const ev_state
);
@@ -425,9 +424,10 @@ private:
boost::shared_ptr<ARDOUR::Region>,
RouteTimeAxisView*,
ARDOUR::layer_t,
- ARDOUR::framecnt_t,
+ ARDOUR::MusicFrame,
+ double quarter_note,
PlaylistSet&,
- const int32_t sub_num
+ bool for_music = false
);
void remove_region_from_playlist (
diff --git a/gtk2_ardour/editor_keys.cc b/gtk2_ardour/editor_keys.cc
index fba52014bc..2c64d6f4f3 100644
--- a/gtk2_ardour/editor_keys.cc
+++ b/gtk2_ardour/editor_keys.cc
@@ -43,9 +43,8 @@ Editor::keyboard_selection_finish (bool /*add*/, Editing::EditIgnoreOption ign)
{
if (_session) {
- framepos_t start = selection->time.start();
+ MusicFrame start (selection->time.start(), 0);
framepos_t end;
-
if ((_edit_point == EditAtPlayhead) && _session->transport_rolling()) {
end = _session->audible_frame();
} else {
@@ -53,13 +52,13 @@ Editor::keyboard_selection_finish (bool /*add*/, Editing::EditIgnoreOption ign)
}
//snap the selection start/end
- snap_to(start);
+ snap_to (start);
//if no tracks are selected and we're working from the keyboard, enable all tracks (_something_ has to be selected for any range selection)
if ( (_edit_point == EditAtPlayhead) && selection->tracks.empty() )
select_all_tracks();
- selection->set (start, end);
+ selection->set (start.frame, end);
//if session is playing a range, cancel that
if (_session->get_play_range())
@@ -73,26 +72,25 @@ Editor::keyboard_selection_begin (Editing::EditIgnoreOption ign)
{
if (_session) {
- framepos_t start;
- framepos_t end = selection->time.end_frame();
-
+ MusicFrame start (0, 0);
+ MusicFrame end (selection->time.end_frame(), 0);
if ((_edit_point == EditAtPlayhead) && _session->transport_rolling()) {
- start = _session->audible_frame();
+ start.frame = _session->audible_frame();
} else {
- start = get_preferred_edit_position(ign);
+ start.frame = get_preferred_edit_position(ign);
}
//snap the selection start/end
snap_to(start);
//if there's not already a sensible selection endpoint, go "forever"
- if (start > end) {
+ if (start.frame > end.frame) {
#ifdef MIXBUS
// 4hours at most.
// This works around a visual glitch in red-bordered selection rect.
- end = start + _session->nominal_frame_rate() * 60 * 60 * 4;
+ end.frame = start.frame + _session->nominal_frame_rate() * 60 * 60 * 4;
#else
- end = max_framepos;
+ end.frame = max_framepos;
#endif
}
@@ -100,7 +98,7 @@ Editor::keyboard_selection_begin (Editing::EditIgnoreOption ign)
if ( selection->tracks.empty() )
select_all_tracks();
- selection->set (start, end);
+ selection->set (start.frame, end.frame);
//if session is playing a range, cancel that
if (_session->get_play_range())
diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc
index 8e1ef327ab..d5bf07bd78 100644
--- a/gtk2_ardour/editor_mouse.cc
+++ b/gtk2_ardour/editor_mouse.cc
@@ -1269,9 +1269,9 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
UIConfiguration::instance().get_follow_edits() &&
!_session->config.get_external_sync()) {
- framepos_t where = canvas_event_sample (event);
- snap_to(where);
- _session->request_locate (where, false);
+ MusicFrame where (canvas_event_sample (event), 0);
+ snap_to (where);
+ _session->request_locate (where.frame, false);
}
switch (event->button.button) {
@@ -1318,7 +1318,7 @@ Editor::button_release_dispatch (GdkEventButton* ev)
bool
Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type)
{
- framepos_t where = canvas_event_sample (event);
+ MusicFrame where (canvas_event_sample (event), 0);
AutomationTimeAxisView* atv = 0;
_press_cursor_ctx.reset();
@@ -1466,7 +1466,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case SamplesRulerItem:
case MinsecRulerItem:
case BBTRulerItem:
- popup_ruler_menu (where, item_type);
+ popup_ruler_menu (where.frame, item_type);
break;
case MarkerItem:
@@ -1558,7 +1558,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case MarkerBarItem:
if (!_dragging_playhead) {
snap_to_with_modifier (where, event, RoundNearest, true);
- mouse_add_new_marker (where);
+ mouse_add_new_marker (where.frame);
}
return true;
@@ -1566,14 +1566,14 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
if (!_dragging_playhead) {
// if we get here then a dragged range wasn't done
snap_to_with_modifier (where, event, RoundNearest, true);
- mouse_add_new_marker (where, true);
+ mouse_add_new_marker (where.frame, true);
}
return true;
case TempoBarItem:
case TempoCurveItem:
if (!_dragging_playhead) {
snap_to_with_modifier (where, event);
- mouse_add_new_tempo_event (where);
+ mouse_add_new_tempo_event (where.frame);
}
return true;
@@ -1617,7 +1617,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
bool with_guard_points = Keyboard::modifier_state_equals (event->button.state, Keyboard::PrimaryModifier);
atv = dynamic_cast<AutomationTimeAxisView*>(clicked_axisview);
if (atv) {
- atv->add_automation_event (event, where, event->button.y, with_guard_points);
+ atv->add_automation_event (event, where.frame, event->button.y, with_guard_points);
}
return true;
break;
diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
index 4df88b9025..288d12219f 100644
--- a/gtk2_ardour/editor_ops.cc
+++ b/gtk2_ardour/editor_ops.cc
@@ -166,8 +166,7 @@ Editor::redo (uint32_t n)
}
void
-Editor::split_regions_at (framepos_t where, RegionSelection& regions, const int32_t sub_num,
- bool snap_frame)
+Editor::split_regions_at (MusicFrame where, RegionSelection& regions, bool snap_frame)
{
bool frozen = false;
@@ -214,7 +213,7 @@ Editor::split_regions_at (framepos_t where, RegionSelection& regions, const int3
have something to split.
*/
- if (!(*a)->region()->covers (where)) {
+ if (!(*a)->region()->covers (where.frame)) {
++a;
continue;
}
@@ -246,7 +245,7 @@ Editor::split_regions_at (framepos_t where, RegionSelection& regions, const int3
if (pl) {
pl->clear_changes ();
- pl->split_region ((*a)->region(), where, sub_num);
+ pl->split_region ((*a)->region(), where);
_session->add_command (new StatefulDiffCommand (pl));
}
@@ -292,7 +291,7 @@ Editor::split_regions_at (framepos_t where, RegionSelection& regions, const int3
}
for (RegionSelection::iterator ri = latest_regionviews.begin(); ri != latest_regionviews.end(); ri++) {
- if ((*ri)->region()->position() < where) {
+ if ((*ri)->region()->position() < where.frame) {
// new regions created before the split
if (rsas & NewlyCreatedLeft) {
selection->add (*ri);
@@ -4260,7 +4259,7 @@ Editor::cut_copy_points (Editing::CutCopyOp op, Evoral::Beats earliest, bool mid
}
/* Add all selected points to the relevant copy ControlLists */
- framepos_t start = std::numeric_limits<framepos_t>::max();
+ MusicFrame start (std::numeric_limits<framepos_t>::max(), 0);
for (PointSelection::iterator sel_point = selection->points.begin(); sel_point != selection->points.end(); ++sel_point) {
boost::shared_ptr<AutomationList> al = (*sel_point)->line().the_list();
AutomationList::const_iterator ctrl_evt = (*sel_point)->model ();
@@ -4271,7 +4270,7 @@ Editor::cut_copy_points (Editing::CutCopyOp op, Evoral::Beats earliest, bool mid
earliest = std::min(earliest, Evoral::Beats((*ctrl_evt)->when));
} else {
/* Update earliest session start time in frames */
- start = std::min(start, (*sel_point)->line().session_position(ctrl_evt));
+ start.frame = std::min(start.frame, (*sel_point)->line().session_position(ctrl_evt));
}
}
@@ -4282,13 +4281,13 @@ Editor::cut_copy_points (Editing::CutCopyOp op, Evoral::Beats earliest, bool mid
}
earliest.round_down_to_beat();
} else {
- if (start == std::numeric_limits<double>::max()) {
- start = 0; // Weird... don't offset
+ if (start.frame == std::numeric_limits<double>::max()) {
+ start.frame = 0; // Weird... don't offset
}
snap_to(start, RoundDownMaybe);
}
- const double line_offset = midi ? earliest.to_double() : start;
+ const double line_offset = midi ? earliest.to_double() : start.frame;
for (Lists::iterator i = lists.begin(); i != lists.end(); ++i) {
/* Correct this copy list so that it is relative to the earliest
start time, so relative ordering between points is preserved
@@ -4691,22 +4690,21 @@ void
Editor::paste (float times, bool from_context)
{
DEBUG_TRACE (DEBUG::CutNPaste, "paste to preferred edit pos\n");
-
- paste_internal (get_preferred_edit_position (EDIT_IGNORE_NONE, from_context), times, get_grid_music_divisions (0));
+ MusicFrame where (get_preferred_edit_position (EDIT_IGNORE_NONE, from_context), 0);
+ paste_internal (where.frame, times, 0);
}
void
Editor::mouse_paste ()
{
- framepos_t where;
+ MusicFrame where (0, 0);
bool ignored;
-
- if (!mouse_frame (where, ignored)) {
+ if (!mouse_frame (where.frame, ignored)) {
return;
}
snap_to (where);
- paste_internal (where, 1, get_grid_music_divisions (0));
+ paste_internal (where.frame, 1, where.division);
}
void
@@ -6171,10 +6169,10 @@ Editor::update_region_fade_visibility ()
void
Editor::set_edit_point ()
{
- framepos_t where;
bool ignored;
+ MusicFrame where (0, 0);
- if (!mouse_frame (where, ignored)) {
+ if (!mouse_frame (where.frame, ignored)) {
return;
}
@@ -6182,7 +6180,7 @@ Editor::set_edit_point ()
if (selection->markers.empty()) {
- mouse_add_new_marker (where);
+ mouse_add_new_marker (where.frame);
} else {
bool ignored;
@@ -6190,7 +6188,7 @@ Editor::set_edit_point ()
Location* loc = find_location_from_marker (selection->markers.front(), ignored);
if (loc) {
- loc->move_to (where, get_grid_music_divisions(0));
+ loc->move_to (where.frame, where.division);
}
}
}
@@ -6201,17 +6199,17 @@ Editor::set_playhead_cursor ()
if (entered_marker) {
_session->request_locate (entered_marker->position(), _session->transport_rolling());
} else {
- framepos_t where;
+ MusicFrame where (0, 0);
bool ignored;
- if (!mouse_frame (where, ignored)) {
+ if (!mouse_frame (where.frame, ignored)) {
return;
}
snap_to (where);
if (_session) {
- _session->request_locate (where, _session->transport_rolling());
+ _session->request_locate (where.frame, _session->transport_rolling());
}
}
@@ -6239,18 +6237,16 @@ Editor::split_region ()
if (current_mouse_mode() == MouseObject) { //don't try this for Internal Edit, Stretch, Draw, etc.
RegionSelection rs = get_regions_from_selection_and_edit_point ();
-
- framepos_t where = get_preferred_edit_position ();
+ const framepos_t pos = get_preferred_edit_position();
+ const int32_t division = get_grid_music_divisions (0);
+ MusicFrame where (pos, division);
if (rs.empty()) {
return;
}
- if (snap_musical()) {
- split_regions_at (where, rs, get_grid_music_divisions (0));
- } else {
- split_regions_at (where, rs, 0);
- }
+ split_regions_at (where, rs);
+
}
}
@@ -6458,7 +6454,7 @@ Editor::set_punch_start_from_edit_point ()
{
if (_session) {
- framepos_t start = 0;
+ MusicFrame start (0, 0);
framepos_t end = max_framepos;
//use the existing punch end, if any
@@ -6468,20 +6464,20 @@ Editor::set_punch_start_from_edit_point ()
}
if ((_edit_point == EditAtPlayhead) && _session->transport_rolling()) {
- start = _session->audible_frame();
+ start.frame = _session->audible_frame();
} else {
- start = get_preferred_edit_position();
+ start.frame = get_preferred_edit_position();
}
//snap the selection start/end
snap_to(start);
//if there's not already a sensible selection endpoint, go "forever"
- if ( start > end ) {
+ if (start.frame > end ) {
end = max_framepos;
}
- set_punch_range (start, end, _("set punch start from EP"));
+ set_punch_range (start.frame, end, _("set punch start from EP"));
}
}
@@ -6492,7 +6488,7 @@ Editor::set_punch_end_from_edit_point ()
if (_session) {
framepos_t start = 0;
- framepos_t end = max_framepos;
+ MusicFrame end (max_framepos, 0);
//use the existing punch start, if any
Location* tpl = transport_punch_location();
@@ -6501,15 +6497,15 @@ Editor::set_punch_end_from_edit_point ()
}
if ((_edit_point == EditAtPlayhead) && _session->transport_rolling()) {
- end = _session->audible_frame();
+ end.frame = _session->audible_frame();
} else {
- end = get_preferred_edit_position();
+ end.frame = get_preferred_edit_position();
}
//snap the selection start/end
- snap_to(end);
+ snap_to (end);
- set_punch_range (start, end, _("set punch end from EP"));
+ set_punch_range (start, end.frame, _("set punch end from EP"));
}
}
@@ -6519,7 +6515,7 @@ Editor::set_loop_start_from_edit_point ()
{
if (_session) {
- framepos_t start = 0;
+ MusicFrame start (0, 0);
framepos_t end = max_framepos;
//use the existing loop end, if any
@@ -6529,20 +6525,20 @@ Editor::set_loop_start_from_edit_point ()
}
if ((_edit_point == EditAtPlayhead) && _session->transport_rolling()) {
- start = _session->audible_frame();
+ start.frame = _session->audible_frame();
} else {
- start = get_preferred_edit_position();
+ start.frame = get_preferred_edit_position();
}
//snap the selection start/end
- snap_to(start);
+ snap_to (start);
//if there's not already a sensible selection endpoint, go "forever"
- if ( start > end ) {
+ if (start.frame > end ) {
end = max_framepos;
}
- set_loop_range (start, end, _("set loop start from EP"));
+ set_loop_range (start.frame, end, _("set loop start from EP"));
}
}
@@ -6553,7 +6549,7 @@ Editor::set_loop_end_from_edit_point ()
if (_session) {
framepos_t start = 0;
- framepos_t end = max_framepos;
+ MusicFrame end (max_framepos, 0);
//use the existing loop start, if any
Location* tpl = transport_loop_location();
@@ -6562,15 +6558,15 @@ Editor::set_loop_end_from_edit_point ()
}
if ((_edit_point == EditAtPlayhead) && _session->transport_rolling()) {
- end = _session->audible_frame();
+ end.frame = _session->audible_frame();
} else {
- end = get_preferred_edit_position();
+ end.frame = get_preferred_edit_position();
}
//snap the selection start/end
snap_to(end);
- set_loop_range (start, end, _("set loop end from EP"));
+ set_loop_range (start, end.frame, _("set loop end from EP"));
}
}
@@ -6985,9 +6981,9 @@ Editor::snap_regions_to_grid ()
pl->freeze();
}
- framepos_t start_frame = (*r)->region()->first_frame ();
- snap_to (start_frame);
- (*r)->region()->set_position (start_frame);
+ MusicFrame start ((*r)->region()->first_frame (), 0);
+ snap_to (start);
+ (*r)->region()->set_position (start.frame, start.division);
}
while (used_playlists.size() > 0) {
@@ -7187,11 +7183,12 @@ Editor::playhead_forward_to_grid ()
return;
}
- framepos_t pos = playhead_cursor->current_frame ();
- if (pos < max_framepos - 1) {
- pos += 2;
+ MusicFrame pos (playhead_cursor->current_frame (), 0);
+
+ if (pos.frame < max_framepos - 1) {
+ pos.frame += 2;
snap_to_internal (pos, RoundUpAlways, false);
- _session->request_locate (pos);
+ _session->request_locate (pos.frame);
}
}
@@ -7203,11 +7200,12 @@ Editor::playhead_backward_to_grid ()
return;
}
- framepos_t pos = playhead_cursor->current_frame ();
- if (pos > 2) {
- pos -= 2;
+ MusicFrame pos (playhead_cursor->current_frame (), 0);
+
+ if (pos.frame > 2) {
+ pos.frame -= 2;
snap_to_internal (pos, RoundDownAlways, false);
- _session->request_locate (pos);
+ _session->request_locate (pos.frame);
}
}
@@ -7472,7 +7470,7 @@ Editor::insert_time (
if (opt == SplitIntersected) {
/* non musical split */
- (*i)->split (pos, 0);
+ (*i)->split (MusicFrame (pos, 0));
}
(*i)->shift (pos, frames, (opt == MoveIntersected), ignore_music_glue);
diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc
index 397ee66cf5..195cc6f828 100644
--- a/gtk2_ardour/midi_region_view.cc
+++ b/gtk2_ardour/midi_region_view.cc
@@ -3426,21 +3426,20 @@ MidiRegionView::nudge_notes (bool forward, bool fine)
/* use grid */
- framepos_t next_pos = ref_point;
-
+ MusicFrame next_pos (ref_point, 0);
if (forward) {
- if (max_framepos - 1 < next_pos) {
- next_pos += 1;
+ if (max_framepos - 1 < next_pos.frame) {
+ next_pos.frame += 1;
}
} else {
- if (next_pos == 0) {
+ if (next_pos.frame == 0) {
return;
}
- next_pos -= 1;
+ next_pos.frame -= 1;
}
trackview.editor().snap_to (next_pos, (forward ? RoundUpAlways : RoundDownAlways), false);
- const framecnt_t distance = ref_point - next_pos;
+ const framecnt_t distance = ref_point - next_pos.frame;
delta = region_frames_to_region_beats (fabs ((double)distance));
}
diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc
index 6bbc813eb2..00764d0b78 100644
--- a/gtk2_ardour/midi_time_axis.cc
+++ b/gtk2_ardour/midi_time_axis.cc
@@ -1646,9 +1646,11 @@ MidiTimeAxisView::automation_child_menu_item (Evoral::Parameter param)
}
boost::shared_ptr<MidiRegion>
-MidiTimeAxisView::add_region (framepos_t pos, framecnt_t length, bool commit, const int32_t sub_num)
+MidiTimeAxisView::add_region (framepos_t f, framecnt_t length, bool commit)
{
Editor* real_editor = dynamic_cast<Editor*> (&_editor);
+ MusicFrame pos (f, 0);
+
if (commit) {
real_editor->begin_reversible_command (Operations::create_region);
}
@@ -1665,8 +1667,8 @@ MidiTimeAxisView::add_region (framepos_t pos, framecnt_t length, bool commit, co
boost::shared_ptr<Region> region = (RegionFactory::create (src, plist));
/* sets beat position */
- region->set_position (pos, sub_num);
- playlist()->add_region (region, pos, 1.0, false, sub_num);
+ region->set_position (pos.frame, pos.division);
+ playlist()->add_region (region, pos.frame, 1.0, false, pos.division);
_session->add_command (new StatefulDiffCommand (playlist()));
if (commit) {
diff --git a/gtk2_ardour/midi_time_axis.h b/gtk2_ardour/midi_time_axis.h
index a75c965413..ac953c8f96 100644
--- a/gtk2_ardour/midi_time_axis.h
+++ b/gtk2_ardour/midi_time_axis.h
@@ -83,7 +83,7 @@ public:
void set_height (uint32_t, TrackHeightMode m = OnlySelf);
- boost::shared_ptr<ARDOUR::MidiRegion> add_region (ARDOUR::framepos_t, ARDOUR::framecnt_t, bool, const int32_t sub_num);
+ boost::shared_ptr<ARDOUR::MidiRegion> add_region (ARDOUR::framepos_t, ARDOUR::framecnt_t, bool);
void show_all_automation (bool apply_to_selection = false);
void show_existing_automation (bool apply_to_selection = false);
diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h
index a63cd049b3..7516d48099 100644
--- a/gtk2_ardour/public_editor.h
+++ b/gtk2_ardour/public_editor.h
@@ -148,10 +148,10 @@ class PublicEditor : public Gtkmm2ext::Tabbable {
* Snap a value according to the current snap setting.
* ensure_snap overrides SnapOff and magnetic snap
*/
- virtual void snap_to (framepos_t& first,
- ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
- bool for_mark = false,
- bool ensure_snap = false) = 0;
+ virtual void snap_to (ARDOUR::MusicFrame& first,
+ ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
+ bool for_mark = false,
+ bool ensure_snap = false) = 0;
/** Undo some transactions.
* @param n Number of transactions to undo.
@@ -320,7 +320,7 @@ class PublicEditor : public Gtkmm2ext::Tabbable {
virtual void restore_editing_space () = 0;
virtual framepos_t get_preferred_edit_position (Editing::EditIgnoreOption = Editing::EDIT_IGNORE_NONE, bool from_context_menu = false, bool from_outside_canvas = false) = 0;
virtual void toggle_meter_updating() = 0;
- virtual void split_regions_at (framepos_t, RegionSelection&, const int32_t sub_num, bool snap) = 0;
+ virtual void split_regions_at (ARDOUR::MusicFrame, RegionSelection&, bool snap) = 0;
virtual void split_region_at_points (boost::shared_ptr<ARDOUR::Region>, ARDOUR::AnalysisFeatureList&, bool can_ferret, bool select_new = false) = 0;
virtual void mouse_add_new_marker (framepos_t where, bool is_cd=false) = 0;
virtual void foreach_time_axis_view (sigc::slot<void,TimeAxisView&>) = 0;
@@ -435,10 +435,10 @@ class PublicEditor : public Gtkmm2ext::Tabbable {
virtual ARDOUR::Location* find_location_from_marker (ArdourMarker *, bool &) const = 0;
virtual ArdourMarker* find_marker_from_location_id (PBD::ID const &, bool) const = 0;
- virtual void snap_to_with_modifier (framepos_t & first,
- GdkEvent const * ev,
- ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
- bool for_mark = false) = 0;
+ virtual void snap_to_with_modifier (ARDOUR::MusicFrame& first,
+ GdkEvent const * ev,
+ ARDOUR::RoundMode direction = ARDOUR::RoundNearest,
+ bool for_mark = false) = 0;
virtual void get_regions_at (RegionSelection &, framepos_t where, TrackViewList const &) const = 0;
virtual void get_regions_after (RegionSelection&, framepos_t where, const TrackViewList& ts) const = 0;
diff --git a/gtk2_ardour/region_view.cc b/gtk2_ardour/region_view.cc
index cc9a5b61ce..9f6ff645ce 100644
--- a/gtk2_ardour/region_view.cc
+++ b/gtk2_ardour/region_view.cc
@@ -947,20 +947,19 @@ frameoffset_t
RegionView::snap_frame_to_frame (frameoffset_t x, bool ensure_snap) const
{
PublicEditor& editor = trackview.editor();
-
/* x is region relative, convert it to global absolute frames */
framepos_t const session_frame = x + _region->position();
/* try a snap in either direction */
- framepos_t frame = session_frame;
+ MusicFrame frame (session_frame, 0);
editor.snap_to (frame, RoundNearest, false, ensure_snap);
/* if we went off the beginning of the region, snap forwards */
- if (frame < _region->position ()) {
- frame = session_frame;
+ if (frame.frame < _region->position ()) {
+ frame.frame = session_frame;
editor.snap_to (frame, RoundUpAlways, false, ensure_snap);
}
/* back to region relative */
- return frame - _region->position();
+ return frame.frame - _region->position();
}
diff --git a/gtk2_ardour/step_editor.cc b/gtk2_ardour/step_editor.cc
index c45c0f4461..ac51076a46 100644
--- a/gtk2_ardour/step_editor.cc
+++ b/gtk2_ardour/step_editor.cc
@@ -116,13 +116,12 @@ StepEditor::prepare_step_edit_region ()
} else {
const Meter& m = _mtv.session()->tempo_map().meter_at_frame (step_edit_insert_position);
-
double baf = max (0.0, _mtv.session()->tempo_map().beat_at_frame (step_edit_insert_position));
double next_bar_in_beats = baf + m.divisions_per_bar();
framecnt_t next_bar_pos = _mtv.session()->tempo_map().frame_at_beat (next_bar_in_beats);
framecnt_t len = next_bar_pos - step_edit_insert_position;
- step_edit_region = _mtv.add_region (step_edit_insert_position, len, true, _editor.get_grid_music_divisions (0));
+ step_edit_region = _mtv.add_region (step_edit_insert_position, len, true);
RegionView* rv = _mtv.midi_view()->find_view (step_edit_region);
step_edit_region_view = dynamic_cast<MidiRegionView*>(rv);
@@ -411,7 +410,7 @@ StepEditor::step_edit_bar_sync ()
}
framepos_t fpos = step_edit_region_view->region_beats_to_absolute_frames (step_edit_beat_pos);
- fpos = _session->tempo_map().round_to_bar (fpos, RoundUpAlways);
+ fpos = _session->tempo_map().round_to_bar (fpos, RoundUpAlways).frame;
step_edit_beat_pos = step_edit_region_view->region_frames_to_region_beats (fpos - step_edit_region->position()).round_up_to_beat();
step_edit_region_view->move_step_edit_cursor (step_edit_beat_pos);
}
diff --git a/gtk2_ardour/tempo_dialog.cc b/gtk2_ardour/tempo_dialog.cc
index f08fb10dda..0b9a071d7d 100644
--- a/gtk2_ardour/tempo_dialog.cc
+++ b/gtk2_ardour/tempo_dialog.cc
@@ -423,7 +423,7 @@ TempoDialog::tap_tempo_focus_out (GdkEventFocus* )
MeterDialog::MeterDialog (TempoMap& map, framepos_t frame, const string&)
: ArdourDialog (_("New Meter"))
{
- frame = map.round_to_bar(frame, RoundNearest);
+ frame = map.round_to_bar(frame, RoundNearest).frame;
Timecode::BBT_Time when (map.bbt_at_frame (frame));
Meter meter (map.meter_at_frame (frame));
diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h
index d25cf0e421..a2c43460ed 100644
--- a/libs/ardour/ardour/audioregion.h
+++ b/libs/ardour/ardour/audioregion.h
@@ -189,7 +189,7 @@ class LIBARDOUR_API AudioRegion : public Region
AudioRegion (boost::shared_ptr<AudioSource>);
AudioRegion (const SourceList &);
AudioRegion (boost::shared_ptr<const AudioRegion>);
- AudioRegion (boost::shared_ptr<const AudioRegion>, frameoffset_t offset, const int32_t sub_num);
+ AudioRegion (boost::shared_ptr<const AudioRegion>, ARDOUR::MusicFrame offset);
AudioRegion (boost::shared_ptr<const AudioRegion>, const SourceList&);
AudioRegion (SourceList &);
diff --git a/libs/ardour/ardour/midi_playlist.h b/libs/ardour/ardour/midi_playlist.h
index 3c031a994f..49eb892e42 100644
--- a/libs/ardour/ardour/midi_playlist.h
+++ b/libs/ardour/ardour/midi_playlist.h
@@ -87,6 +87,7 @@ public:
int set_state (const XMLNode&, int version);
bool destroy_region (boost::shared_ptr<Region>);
+ void _split_region (boost::shared_ptr<Region>, MusicFrame position);
void set_note_mode (NoteMode m) { _note_mode = m; }
diff --git a/libs/ardour/ardour/midi_region.h b/libs/ardour/ardour/midi_region.h
index 8f1edded21..b41f620e87 100644
--- a/libs/ardour/ardour/midi_region.h
+++ b/libs/ardour/ardour/midi_region.h
@@ -127,7 +127,7 @@ class LIBARDOUR_API MidiRegion : public Region
MidiRegion (const SourceList&);
MidiRegion (boost::shared_ptr<const MidiRegion>);
- MidiRegion (boost::shared_ptr<const MidiRegion>, frameoffset_t offset, const int32_t sub_num = 0);
+ MidiRegion (boost::shared_ptr<const MidiRegion>, ARDOUR::MusicFrame offset);
framecnt_t _read_at (const SourceList&, Evoral::EventSink<framepos_t>& dst,
framepos_t position,
@@ -146,6 +146,7 @@ class LIBARDOUR_API MidiRegion : public Region
void recompute_at_end ();
void set_position_internal (framepos_t pos, bool allow_bbt_recompute, const int32_t sub_num);
+ void set_position_music_internal (double qn);
void set_length_internal (framecnt_t len, const int32_t sub_num);
void set_start_internal (framecnt_t, const int32_t sub_num);
void trim_to_internal (framepos_t position, framecnt_t length, const int32_t sub_num);
diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h
index bdf17eabf0..580b245c47 100644
--- a/libs/ardour/ardour/playlist.h
+++ b/libs/ardour/ardour/playlist.h
@@ -135,14 +135,14 @@ public:
/* Editing operations */
- void add_region (boost::shared_ptr<Region>, framepos_t position, float times = 1, bool auto_partition = false, const int32_t sub_num = 0);
+ void add_region (boost::shared_ptr<Region>, framepos_t position, float times = 1, bool auto_partition = false, int32_t sub_num = 0, double quarter_note = 0.0, bool for_music = false);
void remove_region (boost::shared_ptr<Region>);
void get_equivalent_regions (boost::shared_ptr<Region>, std::vector<boost::shared_ptr<Region> >&);
void get_region_list_equivalent_regions (boost::shared_ptr<Region>, std::vector<boost::shared_ptr<Region> >&);
void get_source_equivalent_regions (boost::shared_ptr<Region>, std::vector<boost::shared_ptr<Region> >&);
void replace_region (boost::shared_ptr<Region> old, boost::shared_ptr<Region> newr, framepos_t pos);
- void split_region (boost::shared_ptr<Region>, framepos_t position, const int32_t sub_num);
- void split (framepos_t at, const int32_t sub_num);
+ void split_region (boost::shared_ptr<Region>, MusicFrame position);
+ void split (MusicFrame at);
void shift (framepos_t at, frameoffset_t distance, bool move_intersected, bool ignore_music_glue);
void partition (framepos_t start, framepos_t end, bool cut = false);
void duplicate (boost::shared_ptr<Region>, framepos_t position, float times);
@@ -372,7 +372,7 @@ public:
virtual XMLNode& state (bool);
- bool add_region_internal (boost::shared_ptr<Region>, framepos_t position, const int32_t sub_num = 0);
+ bool add_region_internal (boost::shared_ptr<Region>, framepos_t position, int32_t sub_num = 0, double quarter_note = 0.0, bool for_music = false);
int remove_region_internal (boost::shared_ptr<Region>);
void copy_regions (RegionList&) const;
@@ -390,7 +390,7 @@ public:
void begin_undo ();
void end_undo ();
- void _split_region (boost::shared_ptr<Region>, framepos_t position, const int32_t sub_num);
+ virtual void _split_region (boost::shared_ptr<Region>, MusicFrame position);
typedef std::pair<boost::shared_ptr<Region>, boost::shared_ptr<Region> > TwoRegions;
diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h
index a01ef703f3..85e0442a41 100644
--- a/libs/ardour/ardour/region.h
+++ b/libs/ardour/ardour/region.h
@@ -215,6 +215,7 @@ class LIBARDOUR_API Region
void set_length (framecnt_t, const int32_t sub_num);
void set_start (framepos_t);
void set_position (framepos_t, int32_t sub_num = 0);
+ void set_position_music (double qn);
void set_initial_position (framepos_t);
void special_set_position (framepos_t);
virtual void update_after_tempo_map_change (bool send_change = true);
@@ -346,7 +347,7 @@ class LIBARDOUR_API Region
Region (boost::shared_ptr<const Region>);
/** Construct a region from another region, at an offset within that region */
- Region (boost::shared_ptr<const Region>, frameoffset_t start_offset, const int32_t sub_num);
+ Region (boost::shared_ptr<const Region>, ARDOUR::MusicFrame start_offset);
/** Construct a region as a copy of another region, but with different sources */
Region (boost::shared_ptr<const Region>, const SourceList&);
@@ -364,6 +365,7 @@ class LIBARDOUR_API Region
virtual int _set_state (const XMLNode&, int version, PBD::PropertyChange& what_changed, bool send_signal);
void post_set (const PBD::PropertyChange&);
virtual void set_position_internal (framepos_t pos, bool allow_bbt_recompute, const int32_t sub_num);
+ virtual void set_position_music_internal (double qn);
virtual void set_length_internal (framecnt_t, const int32_t sub_num);
virtual void set_start_internal (framecnt_t, const int32_t sub_num = 0);
bool verify_start_and_length (framepos_t, framecnt_t&);
diff --git a/libs/ardour/ardour/region_factory.h b/libs/ardour/ardour/region_factory.h
index 6971e77242..4b32da0512 100644
--- a/libs/ardour/ardour/region_factory.h
+++ b/libs/ardour/ardour/region_factory.h
@@ -59,7 +59,7 @@ public:
static PBD::Signal1<void,boost::shared_ptr<Region> > CheckNewRegion;
/** create a "pure copy" of Region @param other */
- static boost::shared_ptr<Region> create (boost::shared_ptr<const Region> other, bool announce = false, const int32_t sub_num = 0);
+ static boost::shared_ptr<Region> create (boost::shared_ptr<const Region> other, bool announce = false);
/** create a region from a single Source */
static boost::shared_ptr<Region> create (boost::shared_ptr<Source>,
@@ -72,8 +72,8 @@ public:
static boost::shared_ptr<Region> create (boost::shared_ptr<Region> other,
const PBD::PropertyList&, bool announce = true);
/** create a copy of @param other starting at @param offset within @param other */
- static boost::shared_ptr<Region> create (boost::shared_ptr<Region> other, frameoffset_t offset,
- const PBD::PropertyList&, bool announce = true, const int32_t sub_num = 0);
+ static boost::shared_ptr<Region> create (boost::shared_ptr<Region> other, ARDOUR::MusicFrame offset,
+ const PBD::PropertyList&, bool announce = true);
/** create a "copy" of @param other but using a different set of sources @param srcs */
static boost::shared_ptr<Region> create (boost::shared_ptr<Region> other, const SourceList& srcs,
const PBD::PropertyList&, bool announce = true);
diff --git a/libs/ardour/ardour/tempo.h b/libs/ardour/ardour/tempo.h
index a3ab8d68f6..1dce6347a0 100644
--- a/libs/ardour/ardour/tempo.h
+++ b/libs/ardour/ardour/tempo.h
@@ -386,10 +386,10 @@ class LIBARDOUR_API TempoMap : public PBD::StatefulDestructible
void replace_meter (const MeterSection&, const Meter&, const Timecode::BBT_Time& where, framepos_t frame, PositionLockStyle pls);
- framepos_t round_to_bar (framepos_t frame, RoundMode dir);
- framepos_t round_to_beat (framepos_t frame, RoundMode dir);
+ MusicFrame round_to_bar (framepos_t frame, RoundMode dir);
+ MusicFrame round_to_beat (framepos_t frame, RoundMode dir);
framepos_t round_to_beat_subdivision (framepos_t fr, int sub_num, RoundMode dir);
- framepos_t round_to_quarter_note_subdivision (framepos_t fr, int sub_num, RoundMode dir);
+ MusicFrame round_to_quarter_note_subdivision (framepos_t fr, int sub_num, RoundMode dir);
void set_length (framepos_t frames);
@@ -564,7 +564,7 @@ private:
void recompute_meters (Metrics& metrics);
void recompute_map (Metrics& metrics, framepos_t end = -1);
- framepos_t round_to_type (framepos_t fr, RoundMode dir, BBTPointType);
+ MusicFrame round_to_type (framepos_t fr, RoundMode dir, BBTPointType);
const MeterSection& first_meter() const;
MeterSection& first_meter();
diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h
index 46ef2bade9..0a2fd62f7b 100644
--- a/libs/ardour/ardour/types.h
+++ b/libs/ardour/ardour/types.h
@@ -319,6 +319,27 @@ namespace ARDOUR {
}
};
+ /* used for translating audio frames to an exact musical position using a note divisor.
+ an exact musical position almost never falls exactly on an audio frame, but for sub-sample
+ musical accuracy we need to derive exact musical locations from a frame position
+ the division follows TempoMap::exact_beat_at_frame().
+ division
+ -1 musical location is the bar closest to frame
+ 0 musical location is the musical position of the frame
+ 1 musical location is the BBT beat closest to frame
+ n musical location is the quarter-note division n closest to frame
+ */
+ struct MusicFrame {
+ framepos_t frame;
+ int32_t division;
+
+ MusicFrame (framepos_t f, int32_t d) : frame (f), division (d) {}
+
+ void set (framepos_t f, int32_t d) {frame = f; division = d; }
+
+ MusicFrame operator- (MusicFrame other) { return MusicFrame (frame - other.frame, 0); }
+ };
+
/* XXX: slightly unfortunate that there is this and Evoral::Range<>,
but this has a uint32_t id which Evoral::Range<> does not.
*/
diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc
index bf4c5c6910..7d8c003791 100644
--- a/libs/ardour/audioregion.cc
+++ b/libs/ardour/audioregion.cc
@@ -279,13 +279,13 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other)
assert (_sources.size() == _master_sources.size());
}
-AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, framecnt_t offset, const int32_t sub_num)
- : Region (other, offset, sub_num)
+AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> other, MusicFrame offset)
+ : Region (other, offset)
, AUDIOREGION_COPY_STATE (other)
/* As far as I can see, the _envelope's times are relative to region position, and have nothing
to do with sources (and hence _start). So when we copy the envelope, we just use the supplied offset.
*/
- , _envelope (Properties::envelope, boost::shared_ptr<AutomationList> (new AutomationList (*other->_envelope.val(), offset, other->_length)))
+ , _envelope (Properties::envelope, boost::shared_ptr<AutomationList> (new AutomationList (*other->_envelope.val(), offset.frame, other->_length)))
, _automatable (other->session())
, _fade_in_suspended (0)
, _fade_out_suspended (0)
diff --git a/libs/ardour/midi_playlist.cc b/libs/ardour/midi_playlist.cc
index 67764d66ae..20c1c77111 100644
--- a/libs/ardour/midi_playlist.cc
+++ b/libs/ardour/midi_playlist.cc
@@ -33,7 +33,9 @@
#include "ardour/midi_region.h"
#include "ardour/midi_source.h"
#include "ardour/midi_state_tracker.h"
+#include "ardour/region_factory.h"
#include "ardour/session.h"
+#include "ardour/tempo.h"
#include "ardour/types.h"
#include "pbd/i18n.h"
@@ -381,6 +383,80 @@ MidiPlaylist::destroy_region (boost::shared_ptr<Region> region)
return changed;
}
+void
+MidiPlaylist::_split_region (boost::shared_ptr<Region> region, MusicFrame playlist_position)
+{
+ if (!region->covers (playlist_position.frame)) {
+ return;
+ }
+
+ if (region->position() == playlist_position.frame ||
+ region->last_frame() == playlist_position.frame) {
+ return;
+ }
+
+ boost::shared_ptr<const MidiRegion> mr = boost::dynamic_pointer_cast<MidiRegion>(region);
+
+ if (mr == 0) {
+ return;
+ }
+
+ boost::shared_ptr<Region> left;
+ boost::shared_ptr<Region> right;
+
+ string before_name;
+ string after_name;
+ const double before_qn = _session.tempo_map().exact_qn_at_frame (playlist_position.frame, playlist_position.division) - region->quarter_note();
+ const double after_qn = mr->length_beats() - before_qn;
+ MusicFrame before (playlist_position.frame - region->position(), playlist_position.division);
+ MusicFrame after (region->length() - before.frame, playlist_position.division);
+
+ /* split doesn't change anything about length, so don't try to splice */
+ bool old_sp = _splicing;
+ _splicing = true;
+
+ RegionFactory::region_name (before_name, region->name(), false);
+
+ {
+ PropertyList plist;
+
+ plist.add (Properties::length, before.frame);
+ plist.add (Properties::length_beats, before_qn);
+ plist.add (Properties::name, before_name);
+ plist.add (Properties::left_of_split, true);
+ plist.add (Properties::layering_index, region->layering_index ());
+ plist.add (Properties::layer, region->layer ());
+
+ /* note: we must use the version of ::create with an offset here,
+ since it supplies that offset to the Region constructor, which
+ is necessary to get audio region gain envelopes right.
+ */
+ left = RegionFactory::create (region, MusicFrame (0, 0), plist, true);
+ }
+
+ RegionFactory::region_name (after_name, region->name(), false);
+
+ {
+ PropertyList plist;
+
+ plist.add (Properties::length, after.frame);
+ plist.add (Properties::length_beats, after_qn);
+ plist.add (Properties::name, after_name);
+ plist.add (Properties::right_of_split, true);
+ plist.add (Properties::layering_index, region->layering_index ());
+ plist.add (Properties::layer, region->layer ());
+
+ /* same note as above */
+ right = RegionFactory::create (region, before, plist, true);
+ }
+
+ add_region_internal (left, region->position(), 0, region->quarter_note(), true);
+ add_region_internal (right, region->position() + before.frame, before.division, region->quarter_note() + before_qn, true);
+
+ remove_region_internal (region);
+
+ _splicing = old_sp;
+}
set<Evoral::Parameter>
MidiPlaylist::contained_automation()
diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc
index 7511aadce8..3c885a8d99 100644
--- a/libs/ardour/midi_region.cc
+++ b/libs/ardour/midi_region.cc
@@ -102,20 +102,20 @@ MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other)
}
/** Create a new MidiRegion that is part of an existing one */
-MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other, frameoffset_t offset, const int32_t sub_num)
- : Region (other, offset, sub_num)
+MidiRegion::MidiRegion (boost::shared_ptr<const MidiRegion> other, MusicFrame offset)
+ : Region (other, offset)
, _start_beats (Properties::start_beats, other->_start_beats)
, _length_beats (Properties::length_beats, other->_length_beats)
{
- if (offset != 0) {
- _start_beats = (_session.tempo_map().exact_qn_at_frame (other->_position + offset, sub_num) - other->_quarter_note) + other->_start_beats;
- update_length_beats (sub_num);
- /* we've potentially shifted _start_beats, now reset _start frames to match */
- _start = _session.tempo_map().frames_between_quarter_notes (_quarter_note - _start_beats, _quarter_note);
- }
register_properties ();
+ const double offset_quarter_note = _session.tempo_map().exact_qn_at_frame (other->_position + offset.frame, offset.division) - other->_quarter_note;
+ if (offset.frame != 0) {
+ _start_beats = other->_start_beats + offset_quarter_note;
+ _length_beats = other->_length_beats - offset_quarter_note;
+ }
+
assert(_name.val().find("/") == string::npos);
midi_source(0)->ModelChanged.connect_same_thread (_source_connection, boost::bind (&MidiRegion::model_changed, this));
model_changed ();
@@ -345,6 +345,24 @@ MidiRegion::set_position_internal (framepos_t pos, bool allow_bbt_recompute, con
}
}
+void
+MidiRegion::set_position_music_internal (double qn)
+{
+ Region::set_position_music_internal (qn);
+ /* set _start to new position in tempo map */
+ _start = _session.tempo_map().frames_between_quarter_notes (quarter_note() - start_beats(), quarter_note());
+
+ if (position_lock_style() == AudioTime) {
+ _length_beats = _session.tempo_map().quarter_note_at_frame (_position + _length) - quarter_note();
+
+ } else {
+ /* leave _length_beats alone, and change _length to reflect the state of things
+ at the new position (tempo map may dictate a different number of frames).
+ */
+ _length = _session.tempo_map().frames_between_quarter_notes (quarter_note(), quarter_note() + length_beats());
+ }
+}
+
framecnt_t
MidiRegion::read_at (Evoral::EventSink<framepos_t>& out,
framepos_t position,
diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc
index 7cea903d5d..99e65ab3e2 100644
--- a/libs/ardour/playlist.cc
+++ b/libs/ardour/playlist.cc
@@ -669,7 +669,7 @@ Playlist::clear_pending ()
/** Note: this calls set_layer (..., DBL_MAX) so it will reset the layering index of region */
void
-Playlist::add_region (boost::shared_ptr<Region> region, framepos_t position, float times, bool auto_partition, const int32_t sub_num)
+Playlist::add_region (boost::shared_ptr<Region> region, framepos_t position, float times, bool auto_partition, int32_t sub_num, double quarter_note, bool for_music)
{
RegionWriteLock rlock (this);
times = fabs (times);
@@ -688,19 +688,18 @@ Playlist::add_region (boost::shared_ptr<Region> region, framepos_t position, flo
}
if (itimes >= 1) {
- add_region_internal (region, pos, sub_num);
+ add_region_internal (region, pos, sub_num, quarter_note, for_music);
set_layer (region, DBL_MAX);
pos += region->length();
--itimes;
}
-
/* note that itimes can be zero if we being asked to just
insert a single fraction of the region.
*/
for (int i = 0; i < itimes; ++i) {
- boost::shared_ptr<Region> copy = RegionFactory::create (region, true, sub_num);
+ boost::shared_ptr<Region> copy = RegionFactory::create (region, true);
add_region_internal (copy, pos, sub_num);
set_layer (copy, DBL_MAX);
pos += region->length();
@@ -743,7 +742,7 @@ Playlist::set_region_ownership ()
}
bool
-Playlist::add_region_internal (boost::shared_ptr<Region> region, framepos_t position, const int32_t sub_num)
+Playlist::add_region_internal (boost::shared_ptr<Region> region, framepos_t position, int32_t sub_num, double quarter_note, bool for_music)
{
if (region->data_type() != _type) {
return false;
@@ -755,8 +754,11 @@ Playlist::add_region_internal (boost::shared_ptr<Region> region, framepos_t posi
boost::shared_ptr<Playlist> foo (shared_from_this());
region->set_playlist (boost::weak_ptr<Playlist>(foo));
}
-
- region->set_position (position, sub_num);
+ if (for_music) {
+ region->set_position_music (quarter_note);
+ } else {
+ region->set_position (position, sub_num);
+ }
regions.insert (upper_bound (regions.begin(), regions.end(), region, cmp), region);
all_regions.insert (region);
@@ -1411,7 +1413,7 @@ Playlist::duplicate_ranges (std::list<AudioRange>& ranges, float times)
}
void
- Playlist::split (framepos_t at, const int32_t sub_num)
+ Playlist::split (MusicFrame at)
{
RegionWriteLock rlock (this);
RegionList copy (regions.rlist());
@@ -1420,33 +1422,34 @@ Playlist::duplicate_ranges (std::list<AudioRange>& ranges, float times)
*/
for (RegionList::iterator r = copy.begin(); r != copy.end(); ++r) {
- _split_region (*r, at, sub_num);
+ _split_region (*r, at);
}
}
void
- Playlist::split_region (boost::shared_ptr<Region> region, framepos_t playlist_position, const int32_t sub_num)
+ Playlist::split_region (boost::shared_ptr<Region> region, MusicFrame playlist_position)
{
RegionWriteLock rl (this);
- _split_region (region, playlist_position, sub_num);
+ _split_region (region, playlist_position);
}
void
- Playlist::_split_region (boost::shared_ptr<Region> region, framepos_t playlist_position, const int32_t sub_num)
+ Playlist::_split_region (boost::shared_ptr<Region> region, MusicFrame playlist_position)
{
- if (!region->covers (playlist_position)) {
+ if (!region->covers (playlist_position.frame)) {
return;
}
- if (region->position() == playlist_position ||
- region->last_frame() == playlist_position) {
+ if (region->position() == playlist_position.frame ||
+ region->last_frame() == playlist_position.frame) {
return;
}
boost::shared_ptr<Region> left;
boost::shared_ptr<Region> right;
- frameoffset_t before;
- frameoffset_t after;
+
+ MusicFrame before (playlist_position.frame - region->position(), playlist_position.division);
+ MusicFrame after (region->length() - before.frame, 0);
string before_name;
string after_name;
@@ -1455,15 +1458,12 @@ Playlist::duplicate_ranges (std::list<AudioRange>& ranges, float times)
bool old_sp = _splicing;
_splicing = true;
- before = playlist_position - region->position();
- after = region->length() - before;
-
RegionFactory::region_name (before_name, region->name(), false);
{
PropertyList plist;
- plist.add (Properties::length, before);
+ plist.add (Properties::length, before.frame);
plist.add (Properties::name, before_name);
plist.add (Properties::left_of_split, true);
plist.add (Properties::layering_index, region->layering_index ());
@@ -1473,7 +1473,7 @@ Playlist::duplicate_ranges (std::list<AudioRange>& ranges, float times)
since it supplies that offset to the Region constructor, which
is necessary to get audio region gain envelopes right.
*/
- left = RegionFactory::create (region, 0, plist, true, sub_num);
+ left = RegionFactory::create (region, MusicFrame (0, 0), plist, true);
}
RegionFactory::region_name (after_name, region->name(), false);
@@ -1481,18 +1481,19 @@ Playlist::duplicate_ranges (std::list<AudioRange>& ranges, float times)
{
PropertyList plist;
- plist.add (Properties::length, after);
+ plist.add (Properties::length, after.frame);
plist.add (Properties::name, after_name);
plist.add (Properties::right_of_split, true);
plist.add (Properties::layering_index, region->layering_index ());
plist.add (Properties::layer, region->layer ());
/* same note as above */
- right = RegionFactory::create (region, before, plist, true, sub_num);
+ right = RegionFactory::create (region, before, plist, true);
}
- add_region_internal (left, region->position());
- add_region_internal (right, region->position() + before);
+ add_region_internal (left, region->position(), 0);
+ add_region_internal (right, region->position() + before.frame, before.division);
+
remove_region_internal (region);
_splicing = old_sp;
diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc
index 0d0a40d17a..4eda001708 100644
--- a/libs/ardour/region.cc
+++ b/libs/ardour/region.cc
@@ -329,7 +329,7 @@ Region::Region (boost::shared_ptr<const Region> other)
the start within \a other is given by \a offset
(i.e. relative to the start of \a other's sources, the start is \a offset + \a other.start()
*/
-Region::Region (boost::shared_ptr<const Region> other, frameoffset_t offset, const int32_t sub_num)
+Region::Region (boost::shared_ptr<const Region> other, MusicFrame offset)
: SessionObject(other->session(), other->name())
, _type (other->data_type())
, REGION_COPY_STATE (other)
@@ -343,7 +343,6 @@ Region::Region (boost::shared_ptr<const Region> other, frameoffset_t offset, con
/* override state that may have been incorrectly inherited from the other region
*/
- _position = other->_position + offset;
_locked = false;
_whole_file = false;
_hidden = false;
@@ -351,9 +350,17 @@ Region::Region (boost::shared_ptr<const Region> other, frameoffset_t offset, con
use_sources (other->_sources);
set_master_sources (other->_master_sources);
- _start = other->_start + offset;
- _beat = _session.tempo_map().exact_beat_at_frame (_position, sub_num);
- _quarter_note = _session.tempo_map().exact_qn_at_frame (_position, sub_num);
+ _position = other->_position + offset.frame;
+ _start = other->_start + offset.frame;
+
+ /* prevent offset of 0 from altering musical position */
+ if (offset.frame != 0) {
+ const double offset_qn = _session.tempo_map().exact_qn_at_frame (other->_position + offset.frame, offset.division)
+ - other->_quarter_note;
+
+ _quarter_note = other->_quarter_note + offset_qn;
+ _beat = _session.tempo_map().beat_at_quarter_note (_quarter_note);
+ }
/* if the other region had a distinct sync point
set, then continue to use it as best we can.
@@ -589,6 +596,13 @@ Region::set_position (framepos_t pos, int32_t sub_num)
return;
}
+ /* do this even if the position is the same. this helps out
+ a GUI that has moved its representation already.
+ */
+ PropertyChange p_and_l;
+
+ p_and_l.add (Properties::position);
+
if (position_lock_style() == AudioTime) {
set_position_internal (pos, true, sub_num);
} else {
@@ -596,67 +610,79 @@ Region::set_position (framepos_t pos, int32_t sub_num)
_beat = _session.tempo_map().exact_beat_at_frame (pos, sub_num);
}
- /* will set pulse accordingly */
+ /* will set quarter note accordingly */
set_position_internal (pos, false, sub_num);
}
- /* do this even if the position is the same. this helps out
- a GUI that has moved its representation already.
- */
- PropertyChange p_and_l;
-
- p_and_l.add (Properties::position);
- /* Currently length change due to position change is only implemented
- for MidiRegion (Region has no length in beats).
- Notify a length change regardless (its more efficient for MidiRegions),
- and when Region has a _length_beats we will need it here anyway).
- */
- p_and_l.add (Properties::length);
+ if (position_lock_style() == MusicTime) {
+ p_and_l.add (Properties::length);
+ }
send_change (p_and_l);
}
-/** A gui may need to create a region, then place it in an initial
- * position determined by the user.
- * When this takes place within one gui operation, we have to reset
- * _last_position to prevent an implied move.
- */
void
-Region::set_initial_position (framepos_t pos)
+Region::set_position_internal (framepos_t pos, bool allow_bbt_recompute, const int32_t sub_num)
{
- if (!can_move()) {
- return;
- }
+ /* We emit a change of Properties::position even if the position hasn't changed
+ (see Region::set_position), so we must always set this up so that
+ e.g. Playlist::notify_region_moved doesn't use an out-of-date last_position.
+ */
+ _last_position = _position;
if (_position != pos) {
_position = pos;
+ if (allow_bbt_recompute) {
+ recompute_position_from_lock_style (sub_num);
+ } else {
+ /* MusicTime dictates that we glue to ardour beats. the pulse may have changed.*/
+ _quarter_note = _session.tempo_map().quarter_note_at_beat (_beat);
+ }
+
/* check that the new _position wouldn't make the current
length impossible - if so, change the length.
XXX is this the right thing to do?
*/
-
if (max_framepos - _length < _position) {
_last_length = _length;
_length = max_framepos - _position;
}
-
- recompute_position_from_lock_style (0);
- /* ensure that this move doesn't cause a range move */
- _last_position = _position;
}
+}
+void
+Region::set_position_music (double qn)
+{
+ if (!can_move()) {
+ return;
+ }
/* do this even if the position is the same. this helps out
a GUI that has moved its representation already.
*/
- send_change (Properties::position);
+ PropertyChange p_and_l;
+
+ p_and_l.add (Properties::position);
+
+ if (!_session.loading()) {
+ _beat = _session.tempo_map().beat_at_quarter_note (qn);
+ }
+
+ /* will set frame accordingly */
+ set_position_music_internal (qn);
+
+ if (position_lock_style() == MusicTime) {
+ p_and_l.add (Properties::length);
+ }
+
+ send_change (p_and_l);
}
void
-Region::set_position_internal (framepos_t pos, bool allow_bbt_recompute, const int32_t sub_num)
+Region::set_position_music_internal (double qn)
{
/* We emit a change of Properties::position even if the position hasn't changed
(see Region::set_position), so we must always set this up so that
@@ -664,26 +690,58 @@ Region::set_position_internal (framepos_t pos, bool allow_bbt_recompute, const i
*/
_last_position = _position;
- if (_position != pos) {
- _position = pos;
+ if (_quarter_note != qn) {
+ _position = _session.tempo_map().frame_at_quarter_note (qn);
+ _quarter_note = qn;
- if (allow_bbt_recompute) {
- recompute_position_from_lock_style (sub_num);
- } else {
- /* MusicTime dictates that we glue to ardour beats. the pulse may have changed.*/
- _quarter_note = _session.tempo_map().quarter_note_at_beat (_beat);
+ /* check that the new _position wouldn't make the current
+ length impossible - if so, change the length.
+
+ XXX is this the right thing to do?
+ */
+ if (max_framepos - _length < _position) {
+ _last_length = _length;
+ _length = max_framepos - _position;
}
+ }
+}
+
+/** A gui may need to create a region, then place it in an initial
+ * position determined by the user.
+ * When this takes place within one gui operation, we have to reset
+ * _last_position to prevent an implied move.
+ */
+void
+Region::set_initial_position (framepos_t pos)
+{
+ if (!can_move()) {
+ return;
+ }
+
+ if (_position != pos) {
+ _position = pos;
/* check that the new _position wouldn't make the current
length impossible - if so, change the length.
XXX is this the right thing to do?
*/
+
if (max_framepos - _length < _position) {
_last_length = _length;
_length = max_framepos - _position;
}
+
+ recompute_position_from_lock_style (0);
+ /* ensure that this move doesn't cause a range move */
+ _last_position = _position;
}
+
+
+ /* do this even if the position is the same. this helps out
+ a GUI that has moved its representation already.
+ */
+ send_change (Properties::position);
}
void
diff --git a/libs/ardour/region_factory.cc b/libs/ardour/region_factory.cc
index 16a9e02e37..78425db88c 100644
--- a/libs/ardour/region_factory.cc
+++ b/libs/ardour/region_factory.cc
@@ -46,7 +46,7 @@ std::map<std::string, PBD::ID> RegionFactory::region_name_map;
RegionFactory::CompoundAssociations RegionFactory::_compound_associations;
boost::shared_ptr<Region>
-RegionFactory::create (boost::shared_ptr<const Region> region, bool announce, const int32_t sub_num)
+RegionFactory::create (boost::shared_ptr<const Region> region, bool announce)
{
boost::shared_ptr<Region> ret;
boost::shared_ptr<const AudioRegion> ar;
@@ -54,7 +54,7 @@ RegionFactory::create (boost::shared_ptr<const Region> region, bool announce, co
if ((ar = boost::dynamic_pointer_cast<const AudioRegion>(region)) != 0) {
- ret = boost::shared_ptr<Region> (new AudioRegion (ar, 0, sub_num));
+ ret = boost::shared_ptr<Region> (new AudioRegion (ar, MusicFrame (0, 0)));
} else if ((mr = boost::dynamic_pointer_cast<const MidiRegion>(region)) != 0) {
@@ -71,7 +71,7 @@ RegionFactory::create (boost::shared_ptr<const Region> region, bool announce, co
source->set_ancestor_name(mr->sources().front()->name());
ret = mr->clone(source);
} else {
- ret = boost::shared_ptr<Region> (new MidiRegion (mr, 0, sub_num));
+ ret = boost::shared_ptr<Region> (new MidiRegion (mr, MusicFrame (0, 0)));
}
} else {
@@ -87,8 +87,6 @@ RegionFactory::create (boost::shared_ptr<const Region> region, bool announce, co
ret->set_position_lock_style (MusicTime);
}
- ret->set_position (region->position(), sub_num);
-
/* pure copy constructor - no property list */
if (announce) {
map_add (ret);
@@ -144,7 +142,7 @@ RegionFactory::create (boost::shared_ptr<Region> region, const PropertyList& pli
}
boost::shared_ptr<Region>
-RegionFactory::create (boost::shared_ptr<Region> region, frameoffset_t offset, const PropertyList& plist, bool announce, const int32_t sub_num)
+RegionFactory::create (boost::shared_ptr<Region> region, MusicFrame offset, const PropertyList& plist, bool announce)
{
boost::shared_ptr<Region> ret;
boost::shared_ptr<const AudioRegion> other_a;
@@ -152,11 +150,11 @@ RegionFactory::create (boost::shared_ptr<Region> region, frameoffset_t offset, c
if ((other_a = boost::dynamic_pointer_cast<AudioRegion>(region)) != 0) {
- ret = boost::shared_ptr<Region> (new AudioRegion (other_a, offset, sub_num));
+ ret = boost::shared_ptr<Region> (new AudioRegion (other_a, offset));
} else if ((other_m = boost::dynamic_pointer_cast<MidiRegion>(region)) != 0) {
- ret = boost::shared_ptr<Region> (new MidiRegion (other_m, offset, sub_num));
+ ret = boost::shared_ptr<Region> (new MidiRegion (other_m, offset));
} else {
fatal << _("programming error: RegionFactory::create() called with unknown Region type")
diff --git a/libs/ardour/strip_silence.cc b/libs/ardour/strip_silence.cc
index 3141f422a8..1cbb81a3ed 100644
--- a/libs/ardour/strip_silence.cc
+++ b/libs/ardour/strip_silence.cc
@@ -116,7 +116,7 @@ StripSilence::run (boost::shared_ptr<Region> r, Progress* progress)
plist.add (Properties::position, r->position() + (i->first - r->start()));
copy = boost::dynamic_pointer_cast<AudioRegion> (
- RegionFactory::create (region, (i->first - r->start()), plist)
+ RegionFactory::create (region, MusicFrame (i->first - r->start(), 0), plist)
);
copy->set_name (RegionFactory::new_region_name (region->name ()));
diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc
index 469bbac4de..d690896c15 100644
--- a/libs/ardour/tempo.cc
+++ b/libs/ardour/tempo.cc
@@ -3676,13 +3676,13 @@ TempoMap::bbt_duration_at (framepos_t pos, const BBT_Time& bbt, int dir)
return 0;
}
-framepos_t
+MusicFrame
TempoMap::round_to_bar (framepos_t fr, RoundMode dir)
{
return round_to_type (fr, dir, Bar);
}
-framepos_t
+MusicFrame
TempoMap::round_to_beat (framepos_t fr, RoundMode dir)
{
return round_to_type (fr, dir, Beat);
@@ -3784,7 +3784,7 @@ TempoMap::round_to_beat_subdivision (framepos_t fr, int sub_num, RoundMode dir)
return ret_frame;
}
-framepos_t
+MusicFrame
TempoMap::round_to_quarter_note_subdivision (framepos_t fr, int sub_num, RoundMode dir)
{
Glib::Threads::RWLock::ReaderLock lm (lock);
@@ -3865,7 +3865,7 @@ TempoMap::round_to_quarter_note_subdivision (framepos_t fr, int sub_num, RoundMo
if (rem > ticks) {
if (beats == 0) {
/* can't go backwards past zero, so ... */
- return 0;
+ return MusicFrame (0, 0);
}
/* step back to previous beat */
--beats;
@@ -3880,35 +3880,46 @@ TempoMap::round_to_quarter_note_subdivision (framepos_t fr, int sub_num, RoundMo
}
}
- const framepos_t ret_frame = frame_at_minute (minute_at_pulse_locked (_metrics, (beats + (ticks / BBT_Time::ticks_per_beat)) / 4.0));
+ MusicFrame ret (0, 0);
+ ret.frame = frame_at_minute (minute_at_pulse_locked (_metrics, (beats + (ticks / BBT_Time::ticks_per_beat)) / 4.0));
+ ret.division = sub_num;
- return ret_frame;
+ return ret;
}
-framepos_t
+MusicFrame
TempoMap::round_to_type (framepos_t frame, RoundMode dir, BBTPointType type)
{
Glib::Threads::RWLock::ReaderLock lm (lock);
-
- const double beat_at_framepos = max (0.0, beat_at_minute_locked (_metrics, minute_at_frame (frame)));
+ const double minute = minute_at_frame (frame);
+ const double beat_at_framepos = max (0.0, beat_at_minute_locked (_metrics, minute));
BBT_Time bbt (bbt_at_beat_locked (_metrics, beat_at_framepos));
+ MusicFrame ret (0, 0);
switch (type) {
case Bar:
+ ret.division = -1;
+
if (dir < 0) {
/* find bar previous to 'frame' */
if (bbt.bars > 0)
--bbt.bars;
bbt.beats = 1;
bbt.ticks = 0;
- return frame_at_minute (minute_at_bbt_locked (_metrics, bbt));
+
+ ret.frame = frame_at_minute (minute_at_bbt_locked (_metrics, bbt));
+
+ return ret;
} else if (dir > 0) {
/* find bar following 'frame' */
++bbt.bars;
bbt.beats = 1;
bbt.ticks = 0;
- return frame_at_minute (minute_at_bbt_locked (_metrics, bbt));
+
+ ret.frame = frame_at_minute (minute_at_bbt_locked (_metrics, bbt));
+
+ return ret;
} else {
/* true rounding: find nearest bar */
framepos_t raw_ft = frame_at_minute (minute_at_bbt_locked (_metrics, bbt));
@@ -3919,26 +3930,39 @@ TempoMap::round_to_type (framepos_t frame, RoundMode dir, BBTPointType type)
framepos_t next_ft = frame_at_minute (minute_at_bbt_locked (_metrics, bbt));
if ((raw_ft - prev_ft) > (next_ft - prev_ft) / 2) {
- return next_ft;
+ ret.frame = next_ft;
+
+ return ret;
} else {
- return prev_ft;
+ --bbt.bars;
+ ret.frame = prev_ft;
+
+ return ret;
}
}
break;
case Beat:
+ ret.division = 1;
+
if (dir < 0) {
- return frame_at_minute (minute_at_beat_locked (_metrics, floor (beat_at_framepos)));
+ ret.frame = frame_at_minute (minute_at_beat_locked (_metrics, floor (beat_at_framepos)));
+
+ return ret;
} else if (dir > 0) {
- return frame_at_minute (minute_at_beat_locked (_metrics, ceil (beat_at_framepos)));
+ ret.frame = frame_at_minute (minute_at_beat_locked (_metrics, ceil (beat_at_framepos)));
+
+ return ret;
} else {
- return frame_at_minute (minute_at_beat_locked (_metrics, floor (beat_at_framepos + 0.5)));
+ ret.frame = frame_at_minute (minute_at_beat_locked (_metrics, floor (beat_at_framepos + 0.5)));
+
+ return ret;
}
break;
}
- return 0;
+ return MusicFrame (0, 0);
}
void