From 9d69fa3820986b90df75a431e65f916e023bba7f Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Sun, 4 Oct 2020 22:52:17 -0600 Subject: [PATCH] another day or two's work on timeline type conversion --- gtk2_ardour/ardour_ui3.cc | 14 +- gtk2_ardour/automation_line.cc | 68 +++--- gtk2_ardour/automation_line.h | 7 +- gtk2_ardour/automation_region_view.cc | 8 +- gtk2_ardour/automation_time_axis.cc | 43 ++-- gtk2_ardour/automation_time_axis.h | 2 +- gtk2_ardour/curvetest.cc | 6 +- gtk2_ardour/edit_note_dialog.cc | 53 +++-- gtk2_ardour/editor.cc | 24 ++ gtk2_ardour/editor.h | 20 +- gtk2_ardour/editor_markers.cc | 18 +- gtk2_ardour/editor_mouse.cc | 2 +- gtk2_ardour/editor_routes.cc | 2 +- gtk2_ardour/editor_rulers.cc | 2 +- gtk2_ardour/editor_tempodisplay.cc | 17 +- gtk2_ardour/editor_timefx.cc | 8 +- gtk2_ardour/export_dialog.cc | 2 +- gtk2_ardour/export_video_dialog.cc | 6 +- gtk2_ardour/midi_region_view.cc | 306 ++++++++++++-------------- gtk2_ardour/midi_region_view.h | 18 +- gtk2_ardour/option_editor.cc | 6 +- gtk2_ardour/patch_change_dialog.cc | 1 - gtk2_ardour/patch_change_dialog.h | 1 - gtk2_ardour/public_editor.h | 10 +- gtk2_ardour/region_editor.cc | 34 +-- gtk2_ardour/sfdb_ui.cc | 39 ++-- gtk2_ardour/strip_silence_dialog.cc | 12 +- 27 files changed, 378 insertions(+), 351 deletions(-) diff --git a/gtk2_ardour/ardour_ui3.cc b/gtk2_ardour/ardour_ui3.cc index 9112a7410b..6a76070939 100644 --- a/gtk2_ardour/ardour_ui3.cc +++ b/gtk2_ardour/ardour_ui3.cc @@ -176,19 +176,21 @@ ARDOUR_UI::set_flat_buttons () void -ARDOUR_UI::update_transport_clocks (samplepos_t pos) +ARDOUR_UI::update_transport_clocks (samplepos_t p) { + timepos_t pos (p); + switch (UIConfiguration::instance().get_primary_clock_delta_mode()) { case NoDelta: primary_clock->set (pos); break; case DeltaEditPoint: - primary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD)); + primary_clock->set (pos, false, timecnt_t (editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD))); break; case DeltaOriginMarker: { Location* loc = _session->locations()->clock_origin_location (); - primary_clock->set (pos, false, loc ? loc->start_sample() : 0); + primary_clock->set (pos, false, timecnt_t (loc ? loc->start_sample() : 0)); } break; } @@ -198,12 +200,12 @@ ARDOUR_UI::update_transport_clocks (samplepos_t pos) secondary_clock->set (pos); break; case DeltaEditPoint: - secondary_clock->set (pos, false, editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD)); + secondary_clock->set (pos, false, timecnt_t (editor->get_preferred_edit_position (EDIT_IGNORE_PHEAD))); break; case DeltaOriginMarker: { Location* loc = _session->locations()->clock_origin_location (); - secondary_clock->set (pos, false, loc ? loc->start_sample() : 0); + secondary_clock->set (pos, false, timecnt_t (loc ? loc->start_sample() : 0)); } break; } @@ -213,7 +215,7 @@ ARDOUR_UI::update_transport_clocks (samplepos_t pos) } if (!editor->preview_video_drag_active ()) { - ARDOUR_UI::instance()->video_timeline->manual_seek_video_monitor(pos); + ARDOUR_UI::instance()->video_timeline->manual_seek_video_monitor(p); } } diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc index 343641aa1d..64fc8682d2 100644 --- a/gtk2_ardour/automation_line.cc +++ b/gtk2_ardour/automation_line.cc @@ -50,6 +50,8 @@ #include "ardour/parameter_types.h" #include "ardour/tempo.h" +#include "temporal/range.h" + #include "evoral/Curve.h" #include "canvas/debug.h" @@ -78,7 +80,7 @@ using namespace Editing; #define TIME_TO_SAMPLES(x) (_distance_measure (x, Temporal::AudioTime)) -#define SAMPLES_TO_TIME(x) (_distance_measure (x, alist->time_style())) +#define SAMPLES_TO_TIME(x) (_distance_measure (x, alist->time_domain())) /** @param converter A TimeConverter whose origin_b is the start time of the AutomationList in session samples. * This will not be deleted by AutomationLine. @@ -88,7 +90,7 @@ AutomationLine::AutomationLine (const string& name, ArdourCanvas::Item& parent, boost::shared_ptr al, const ParameterDescriptor& desc, - DistanceMeasure const & m) + Temporal::DistanceMeasure const & m) : trackview (tv) , _name (name) , alist (al) @@ -99,12 +101,6 @@ AutomationLine::AutomationLine (const string& name, , _desc (desc) , _distance_measure (m) { - if (converter) { - _our_time_converter = false; - } else { - _our_time_converter = true; - } - _visible = Line; update_pending = false; @@ -141,10 +137,6 @@ AutomationLine::~AutomationLine () delete *i; } control_points.clear (); - - if (_our_time_converter) { - delete _time_converter; - } } bool @@ -302,13 +294,11 @@ AutomationLine::modify_point_y (ControlPoint& cp, double y) y = min (1.0, y); y = _height - (y * _height); - double const x = trackview.editor().sample_to_pixel_unrounded (_time_converter->to((*cp.model())->when) - _offset); - trackview.editor().begin_reversible_command (_("automation event move")); trackview.editor().session()->add_command ( new MementoCommand (memento_command_binder(), &get_state(), 0)); - cp.move_to (x, y, ControlPoint::Full); + cp.move_to (cp.get_x(), y, ControlPoint::Full); alist->freeze (); sync_model_with_view_point (cp); @@ -787,7 +777,7 @@ AutomationLine::sync_model_with_view_point (ControlPoint& cp) /* if xval has not changed, set it directly from the model to avoid rounding errors */ - timepos_t model_x = alist->control_point_time (**(cp.model())); + timepos_t model_x = (*cp.model())->when; if (view_x != trackview.editor().time_to_pixel_unrounded (model_x.earlier (_offset))) { /* convert from view coordinates, via pixels->samples->timepos_t @@ -800,7 +790,7 @@ AutomationLine::sync_model_with_view_point (ControlPoint& cp) view_to_model_coord_y (view_y); - alist->modify (cp.model(), view_x, view_y); + alist->modify (cp.model(), model_x, view_y); /* convert back from model to view y for clamping position (for integer/boolean/etc) */ model_to_view_coord_y (view_y); @@ -898,20 +888,15 @@ AutomationLine::remove_point (ControlPoint& cp) * @param result Filled in with selectable things; in this case, ControlPoints. */ void -AutomationLine::get_selectables (samplepos_t start, samplepos_t end, double botfrac, double topfrac, list& results) +AutomationLine::get_selectables (timepos_t const & start, timepos_t const & end, double botfrac, double topfrac, list& results) { /* convert fractions to display coordinates with 0 at the top of the track */ double const bot_track = (1 - topfrac) * trackview.current_height (); double const top_track = (1 - botfrac) * trackview.current_height (); for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { - double const model_when = (*(*i)->model())->when; - /* model_when is relative to the start of the source, so we just need to add on the origin_b here - (as it is the session sample position of the start of the source) - */ - - samplepos_t const session_samples_when = _time_converter->to (model_when) + _time_converter->origin_b (); + timepos_t const session_samples_when = timepos_t (session_sample_position ((*i)->model())); if (session_samples_when >= start && session_samples_when <= end && (*i)->get_y() >= bot_track && (*i)->get_y() <= top_track) { results.push_back (*i); @@ -994,20 +979,19 @@ AutomationLine::reset_callback (const Evoral::ControlList& events) for (AutomationList::iterator ai = e.begin(); ai != e.end(); ++ai, ++pi) { - double tx = (*ai)->when; double ty = (*ai)->value; /* convert from model coordinates to canonical view coordinates */ - model_to_view_coord (tx, ty); + timepos_t tx = model_to_view_coord (**ai, ty); - if (isnan_local (tx) || isnan_local (ty)) { + if (isnan_local (ty)) { warning << string_compose (_("Ignoring illegal points on AutomationLine \"%1\""), _name) << endmsg; continue; } - if (tx >= max_samplepos || tx < 0 || tx >= _maximum_time) { + if (tx >= timepos_t::max (tx.time_domain()) || tx.negative() || tx >= _maximum_time) { continue; } @@ -1015,7 +999,7 @@ AutomationLine::reset_callback (const Evoral::ControlList& events) * zoom and scroll into account). */ - tx = trackview.editor().sample_to_pixel_unrounded (tx); + double px = trackview.editor().time_to_pixel_unrounded (tx); /* convert from canonical view height (0..1.0) to actual * height coordinates (using X11's top-left rooted system) @@ -1023,7 +1007,7 @@ AutomationLine::reset_callback (const Evoral::ControlList& events) ty = _height - (ty * _height); - add_visible_control_point (vp, pi, tx, ty, ai, np); + add_visible_control_point (vp, pi, px, ty, ai, np); vp++; } @@ -1187,18 +1171,20 @@ AutomationLine::set_state (const XMLNode &node, int version) Temporal::timepos_t AutomationLine::view_to_model_coord (double x, double& y) const { - assert (alist->time_style() != Temporal::BarTime); + assert (alist->time_domain() != Temporal::BarTime); view_to_model_coord_y (y); Temporal::timepos_t w; - switch (alist->time_style()) { +#warning NUTEMPO FIX ME ... this accepts view coordinate as double and things it can infer beats etc + + switch (alist->time_domain()) { case Temporal::AudioTime: return timepos_t (samplepos_t (x)); break; case Temporal::BeatTime: - return timepos_t (Beats::from_double (x)); + return timepos_t (Temporal::Beats::from_double (x)); break; default: /*NOTREACHED*/ @@ -1275,12 +1261,12 @@ AutomationLine::model_to_view_coord_y (double& y) const y = _desc.to_interface (y); } -double +timepos_t AutomationLine::model_to_view_coord (Evoral::ControlEvent const & ev, double& y) const { - Temporal::timepos_t w (ev.when()); + Temporal::timepos_t w (ev.when); model_to_view_coord_y (y); - return (w).earlier (_offset).samples(); + return (w).earlier (_offset); } /** Called when our list has announced that its interpolation style has changed */ @@ -1373,10 +1359,10 @@ AutomationLine::set_maximum_time (Temporal::timepos_t const & t) /** @return min and max x positions of points that are in the list, in session samples */ -pair +pair AutomationLine::get_point_x_range () const { - pair r (max_samplepos, 0); + pair r (timepos_t::max (the_list()->time_domain()), timepos_t::zero (the_list()->time_domain())); for (AutomationList::const_iterator i = the_list()->begin(); i != the_list()->end(); ++i) { r.first = min (r.first, session_position (i)); @@ -1389,17 +1375,17 @@ AutomationLine::get_point_x_range () const samplepos_t AutomationLine::session_sample_position (AutomationList::const_iterator p) const { - return alist->control_point_time (ev).sample() + _offset.samples() + _distance_measure.origin().samples(); + return (*p)->when.samples() + _offset.samples() + _distance_measure.origin().samples(); } timepos_t AutomationLine::session_position (AutomationList::const_iterator p) const { - return alist->control_point_time (ev) + _offset + _distance_measure.origin(); + return (*p)->when + _offset + _distance_measure.origin(); } void -AutomationLine::set_offset (samplepos_t off) +AutomationLine::set_offset (timecnt_t const & off) { if (_offset == off) { return; diff --git a/gtk2_ardour/automation_line.h b/gtk2_ardour/automation_line.h index 619ab7bf07..754b8dd248 100644 --- a/gtk2_ardour/automation_line.h +++ b/gtk2_ardour/automation_line.h @@ -71,7 +71,8 @@ public: TimeAxisView& tv, ArdourCanvas::Item& parent, boost::shared_ptr al, - const ARDOUR::ParameterDescriptor& desc); + const ARDOUR::ParameterDescriptor& desc, + Temporal::DistanceMeasure const &); virtual ~AutomationLine (); @@ -125,7 +126,7 @@ public: std::string fraction_to_string (double) const; std::string delta_to_string (double) const; double string_to_fraction (std::string const &) const; - Temporal::timepos_t view_to_model_coord (double& x, double& y) const; + Temporal::timepos_t view_to_model_coord (double x, double& y) const; void view_to_model_coord_y (double &) const; Temporal::timepos_t model_to_view_coord (Evoral::ControlEvent const &, double& y) const; void model_to_view_coord_y (double &) const; @@ -150,7 +151,7 @@ public: virtual MementoCommandBinder* memento_command_binder (); - std::pair get_point_x_range () const; + std::pair get_point_x_range () const; void set_maximum_time (Temporal::timepos_t const &); Temporal::timepos_t maximum_time () const { diff --git a/gtk2_ardour/automation_region_view.cc b/gtk2_ardour/automation_region_view.cc index f2654e519a..aa27283926 100644 --- a/gtk2_ardour/automation_region_view.cc +++ b/gtk2_ardour/automation_region_view.cc @@ -1,4 +1,4 @@ -/* +n/* * Copyright (C) 2007-2015 David Robillard * Copyright (C) 2008-2017 Paul Davis * Copyright (C) 2009-2011 Carl Hetherington @@ -208,8 +208,7 @@ AutomationRegionView::add_automation_event (GdkEvent *, timepos_t const & w, dou XMLNode& before = _line->the_list()->get_state(); -<<<<<<< HEAD - if (_line->the_list()->editor_add (when_d, y, with_guard_points)) { +n if (_line->the_list()->editor_add (when, y, with_guard_points)) { if (ac->automation_state () == ARDOUR::Off) { ac->set_automation_state (ARDOUR::Play); @@ -218,9 +217,6 @@ AutomationRegionView::add_automation_event (GdkEvent *, timepos_t const & w, dou RouteTimeAxisView::signal_ctrl_touched (false); } -======= - if (_line->the_list()->editor_add (when, y, with_guard_points)) { ->>>>>>> intermediate, unfinished snapshot of ongoing timeline types work on GTK GUI view->editor().begin_reversible_command (_("add automation event")); XMLNode& after = _line->the_list()->get_state(); diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc index 15d9b9fa4f..53d48c19ef 100644 --- a/gtk2_ardour/automation_time_axis.cc +++ b/gtk2_ardour/automation_time_axis.cc @@ -41,7 +41,7 @@ #include "pbd/unwind.h" #include "ardour/automation_control.h" -#include "ardour/beats_samples_converter.h" +#include "ardour/automation_list.h" #include "ardour/event_type_map.h" #include "ardour/parameter_types.h" #include "ardour/profile.h" @@ -299,13 +299,15 @@ AutomationTimeAxisView::AutomationTimeAxisView ( assert (_control); +#warning NUTEMPO new tempo map API required +#if 0 boost::shared_ptr line ( new AutomationLine ( ARDOUR::EventTypeMap::instance().to_symbol(_parameter), *this, *_canvas_display, _control->alist(), - _control->desc() + _control->desc(), Temporal::DistanceMeasure (_session->tempo_map(), timepos_t()) /* default distance measure, origin at absolute zero */ ) ); @@ -314,6 +316,7 @@ AutomationTimeAxisView::AutomationTimeAxisView ( line->set_fill (true); line->queue_reset (); add_line (line); +#endif 0 } /* make sure labels etc. are correct */ @@ -768,14 +771,14 @@ AutomationTimeAxisView::add_automation_event (GdkEvent* event, samplepos_t sampl return; } - MusicSample when (sample, 0); + timepos_t when (sample); _editor.snap_to_with_modifier (when, event); if (UIConfiguration::instance().get_new_automation_points_on_lane()) { if (_control->list()->size () == 0) { y = _control->get_value (); } else { - y = _control->list()->eval (when.sample); + y = _control->list()->eval (when); } } else { double x = 0; @@ -789,7 +792,7 @@ AutomationTimeAxisView::add_automation_event (GdkEvent* event, samplepos_t sampl XMLNode& before = list->get_state(); std::list results; - if (list->editor_add (when.sample, y, with_guard_points)) { + if (list->editor_add (when, y, with_guard_points)) { if (_control->automation_state () == ARDOUR::Off) { _control->set_automation_state (ARDOUR::Play); @@ -802,7 +805,7 @@ AutomationTimeAxisView::add_automation_event (GdkEvent* event, samplepos_t sampl _editor.begin_reversible_command (_("add automation event")); _session->add_command (new MementoCommand (*list.get (), &before, &after)); - _line->get_selectables (when.sample, when.sample, 0.0, 1.0, results); + _line->get_selectables (when, when, 0.0, 1.0, results); _editor.get_selection ().set (results); _editor.commit_reversible_command (); @@ -811,7 +814,7 @@ AutomationTimeAxisView::add_automation_event (GdkEvent* event, samplepos_t sampl } bool -AutomationTimeAxisView::paste (samplepos_t pos, const Selection& selection, PasteContext& ctx, const int32_t divisions) +AutomationTimeAxisView::paste (timepos_t const & pos, const Selection& selection, PasteContext& ctx) { if (_line) { return paste_one (pos, ctx.count, ctx.times, selection, ctx.counts, ctx.greedy); @@ -832,7 +835,7 @@ AutomationTimeAxisView::paste (samplepos_t pos, const Selection& selection, Past } bool -AutomationTimeAxisView::paste_one (samplepos_t pos, unsigned paste_count, float times, const Selection& selection, ItemCounts& counts, bool greedy) +AutomationTimeAxisView::paste_one (timepos_t const & pos, unsigned paste_count, float times, const Selection& selection, ItemCounts& counts, bool greedy) { boost::shared_ptr alist(_line->the_list()); @@ -858,33 +861,29 @@ AutomationTimeAxisView::paste_one (samplepos_t pos, unsigned paste_count, float Temporal::timecnt_t len = (*p)->length(); Temporal::timepos_t tpos (pos); - assert (line()->the_list()->time_style() != Temporal::BarTime); - - switch (line()->the_list()->time_style()) { + switch (line()->the_list()->time_domain()) { case Temporal::BeatTime: tpos += _editor.get_paste_offset (pos, paste_count > 0 ? 1 : 0, len); break; case Temporal::AudioTime: tpos += _editor.get_paste_offset (pos, paste_count, len); break; - case Temporal::BarTime: - /*NOTREACHED*/ - break; } /* convert position to model's unit and position */ Temporal::DistanceMeasure const & dm (_line->distance_measure()); - Temporal::timepos_t model_pos = dm (_line->distance_measure().origin().distance (tpos), line()->the_list()->time_style()); + Temporal::timepos_t model_pos = dm (_line->distance_measure().origin().distance (tpos), line()->the_list()->time_domain()); XMLNode &before = alist->get_state(); - alist->paste (**p, model_pos, _session->tempo_map()); +#warning NUTEMPO FIX THIS ... WHY DOES the paste call get a type error from the compiler + //alist->paste (**p, model_pos, _session->tempo_map()); _session->add_command (new MementoCommand(*alist.get(), &before, &alist->get_state())); return true; } void -AutomationTimeAxisView::get_selectables (samplepos_t start, samplepos_t end, double top, double bot, list& results, bool /*within*/) +AutomationTimeAxisView::get_selectables (timepos_t const & start, timepos_t const & end, double top, double bot, list& results, bool /*within*/) { if (!_line && !_view) { return; @@ -1148,9 +1147,9 @@ AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& sel XMLNode &before = alist->get_state(); /* convert time selection to automation list model coordinates */ - const Evoral::TimeConverter& tc = line.time_converter (); - double const start = tc.from (selection.time.front().start - tc.origin_b ()); - double const end = tc.from (selection.time.front().end - tc.origin_b ()); + /* convert time selection to automation list model coordinates */ + timepos_t start = selection.time.front().start().earlier (line.distance_measure().origin()); + timepos_t end = selection.time.front().end().earlier (line.distance_measure().origin()); switch (op) { case Delete: @@ -1181,9 +1180,9 @@ AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& sel if (what_we_got) { for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) { - double when = (*x)->when; + timepos_t when = (*x)->when; double val = (*x)->value; - line.model_to_view_coord (when, val); + line.model_to_view_coord (**x, val); (*x)->when = when; (*x)->value = val; } diff --git a/gtk2_ardour/automation_time_axis.h b/gtk2_ardour/automation_time_axis.h index 3024aad54c..555f467cac 100644 --- a/gtk2_ardour/automation_time_axis.h +++ b/gtk2_ardour/automation_time_axis.h @@ -187,7 +187,7 @@ protected: void build_display_menu (); void cut_copy_clear_one (AutomationLine&, Selection&, Editing::CutCopyOp); - bool paste_one (ARDOUR::samplepos_t, unsigned, float times, const Selection&, ItemCounts& counts, bool greedy=false); + bool paste_one (Temporal::timepos_t const &, unsigned, float times, const Selection&, ItemCounts& counts, bool greedy=false); void route_going_away (); void set_automation_state (ARDOUR::AutoState); diff --git a/gtk2_ardour/curvetest.cc b/gtk2_ardour/curvetest.cc index 365665e203..b7669ebdd9 100644 --- a/gtk2_ardour/curvetest.cc +++ b/gtk2_ardour/curvetest.cc @@ -36,7 +36,7 @@ curvetest (string filename) stringstream line; //Evoral::Parameter param(GainAutomation, -1.0, +1.0, 0.0); Evoral::Parameter param(GainAutomation); - AutomationList al (param); + AutomationList al (param, Temporal::AudioTime); double minx = DBL_MAX; double maxx = DBL_MIN; @@ -58,13 +58,13 @@ curvetest (string filename) maxx = x; } - al.add (x, y); + al.add (Temporal::timepos_t (x), y); } float foo[1024]; - al.curve().get_vector (minx, maxx, foo, 1024); + al.curve().get_vector (timepos_t (minx), timepos_t (maxx), foo, 1024); for (int i = 0; i < 1024; ++i) { cout << minx + (((double) i / 1024.0) * (maxx - minx)) << ' ' << foo[i] << endl; diff --git a/gtk2_ardour/edit_note_dialog.cc b/gtk2_ardour/edit_note_dialog.cc index 471f9087ce..dcba68b722 100644 --- a/gtk2_ardour/edit_note_dialog.cc +++ b/gtk2_ardour/edit_note_dialog.cc @@ -31,6 +31,7 @@ #include "pbd/i18n.h" using namespace std; +using namespace Temporal; using namespace Gtk; using namespace Gtkmm2ext; @@ -95,8 +96,11 @@ EditNoteDialog::EditNoteDialog (MidiRegionView* rv, set n) _time_clock.set_session (_region_view->get_time_axis_view().session ()); _time_clock.set_mode (AudioClock::BBT); - _time_clock.set (_region_view->source_relative_time_converter().to - ((*_events.begin())->note()->time()) + (_region_view->region()->position() - _region_view->region()->start()), true); + + timecnt_t dur = _region_view->source_relative_distance (timecnt_t ((*_events.begin())->note()->time(), timepos_t()), BeatTime); + timepos_t pos = _region_view->region()->source_position() + dur; + + _time_clock.set (pos, true); l = manage (left_aligned_label (_("Length"))); table->attach (*l, 0, 1, r, r + 1); @@ -106,10 +110,15 @@ EditNoteDialog::EditNoteDialog (MidiRegionView* rv, set n) _length_clock.set_session (_region_view->get_time_axis_view().session ()); _length_clock.set_mode (AudioClock::BBT); - _length_clock.set ( - _region_view->region_relative_time_converter().to ((*_events.begin())->note()->end_time ()) + _region_view->region()->position(), - true, - _region_view->region_relative_time_converter().to ((*_events.begin())->note()->time ()) + _region_view->region()->position()); + + dur = _region_view->region_relative_distance (timecnt_t ((*_events.begin())->note()->end_time (), timepos_t()), BarTime); + pos = _region_view->region()->nt_position() + dur; + timecnt_t offset; + dur = _region_view->region_relative_distance (timecnt_t ((*_events.begin())->note()->time (), timepos_t()), BarTime); + offset = timecnt_t (_region_view->region()->nt_position(), timepos_t()) + dur; + + _length_clock.set_is_duration (true, pos); + _length_clock.set_duration (offset, true); /* Set up `set all notes...' buttons' sensitivity */ @@ -199,27 +208,41 @@ EditNoteDialog::done (int r) } } - samplecnt_t const region_samples = _time_clock.current_time() - (_region_view->region()->position() - _region_view->region()->start()); - Temporal::Beats const t = _region_view->source_relative_time_converter().from (region_samples); + timepos_t source_start = _region_view->region()->nt_position().earlier (_region_view->region()->nt_start()); + + /* convert current clock time into an offset from the start of the source */ + + timepos_t time_clock_source_relative = _time_clock.current_time().earlier (source_start); + + /* convert that into a position in Beats - this will be the new note time (as an offset inside the source) */ + + Beats const new_note_time_source_relative_beats = time_clock_source_relative.beats (); if (!_time_all.get_sensitive() || _time_all.get_active ()) { for (set::iterator i = _events.begin(); i != _events.end(); ++i) { - if (t != (*i)->note()->time()) { - _region_view->change_note_time (*i, t); + if (new_note_time_source_relative_beats != (*i)->note()->time()) { + _region_view->change_note_time (*i, new_note_time_source_relative_beats); had_change = true; } } } - if (!_length_all.get_sensitive() || _length_all.get_active ()) { + + + /* get current note duration, interpreted as beats at the time indicated by the _time_clock (the new note position) */ + Beats const duration = _length_clock.current_duration (_time_clock.current_time()).beats (); + + /* compute end of note */ + Beats const new_note_end_source_relative_beats = new_note_time_source_relative_beats + duration; + for (set::iterator i = _events.begin(); i != _events.end(); ++i) { - samplepos_t const note_end_sample = region_samples + _length_clock.current_duration (_time_clock.current_time()); - Temporal::Beats const d = _region_view->source_relative_time_converter().from (note_end_sample) - (*i)->note()->time(); - if (d != (*i)->note()->length()) { - _region_view->change_note_length (*i, d); + Beats const new_note_length_beats = new_note_end_source_relative_beats - (*i)->note()->time(); + if (new_note_length_beats != (*i)->note()->length()) { + _region_view->change_note_length (*i, new_note_length_beats); had_change = true; } } + } if (!had_change) { diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 2b9f0c9824..349a65b2e0 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -6383,3 +6383,27 @@ Editor::use_own_window (bool and_fill_it) return win; } + +double +Editor::time_to_pixel (timepos_t const & pos) const +{ + return sample_to_pixel (pos.samples()); +} + +double +Editor::time_to_pixel_unrounded (timepos_t const & pos) const +{ + return sample_to_pixel_unrounded (pos.samples()); +} + +double +Editor::duration_to_pixels (timecnt_t const & dur) const +{ + return sample_to_pixel (dur.samples()); +} + +double +Editor::duration_to_pixels_unrounded (timecnt_t const & dur) const +{ + return sample_to_pixel_unrounded (dur.samples()); +} diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 8995c69f16..8eb8006d88 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -262,6 +262,12 @@ public: return sample / (double) samples_per_pixel; } + double time_to_pixel (Temporal::timepos_t const & pos) const; + double time_to_pixel_unrounded (Temporal::timepos_t const & pos) const; + + double duration_to_pixels (Temporal::timecnt_t const & pos) const; + double duration_to_pixels_unrounded (Temporal::timecnt_t const & pos) const; + /* selection */ Selection& get_selection() const { return *selection; } @@ -569,7 +575,7 @@ public: void metric_get_minsec (std::vector&, gdouble, gdouble, gint); /* editing operations that need to be public */ - void mouse_add_new_marker (Temporal::timepos_t const & where, bool is_cd=false); + void mouse_add_new_marker (Temporal::timepos_t where, bool is_cd=false); void split_regions_at (Temporal::timepos_t const & , RegionSelection&); void split_region_at_points (boost::shared_ptr, ARDOUR::AnalysisFeatureList&, bool can_ferret, bool select_new = false); RegionSelection get_regions_from_selection_and_mouse (Temporal::timepos_t const &); @@ -578,8 +584,8 @@ public: void mouse_brush_insert_region (RegionView*, samplepos_t pos); - void mouse_add_new_tempo_event (samplepos_t where); - void mouse_add_new_meter_event (samplepos_t where); + void mouse_add_new_tempo_event (Temporal::timepos_t where); + void mouse_add_new_meter_event (Temporal::timepos_t where); void edit_tempo_section (ARDOUR::TempoSection*); void edit_meter_section (ARDOUR::MeterSection*); @@ -755,9 +761,9 @@ private: void hide_marker (ArdourCanvas::Item*, GdkEvent*); void clear_marker_display (); - void mouse_add_new_range (samplepos_t); - void mouse_add_new_loop (samplepos_t); - void mouse_add_new_punch (samplepos_t); + void mouse_add_new_range (Temporal::timepos_t); + void mouse_add_new_loop (Temporal::timepos_t); + void mouse_add_new_punch (Temporal::timepos_t); bool choose_new_marker_name(std::string &name, bool is_range=false); void update_cd_marker_display (); void ensure_cd_marker_updated (LocationMarkers* lam, ARDOUR::Location* location); @@ -945,7 +951,7 @@ private: void compute_fixed_ruler_scale (); //calculates the RulerScale of the fixed rulers void update_fixed_rulers (); void update_tempo_based_rulers (); - void popup_ruler_menu (samplepos_t where = 0, ItemType type = RegionItem); + void popup_ruler_menu (Temporal::timepos_t const & where = Temporal::timepos_t (), ItemType type = RegionItem); void update_ruler_visibility (); void toggle_ruler_visibility (); void ruler_toggled (int); diff --git a/gtk2_ardour/editor_markers.cc b/gtk2_ardour/editor_markers.cc index 090c83486c..9f2dc13502 100644 --- a/gtk2_ardour/editor_markers.cc +++ b/gtk2_ardour/editor_markers.cc @@ -668,7 +668,7 @@ Editor::LocationMarkers::setup_lines () } void -Editor::mouse_add_new_marker (timepos_t const & where, bool is_cd) +Editor::mouse_add_new_marker (timepos_t where, bool is_cd) { string markername; int flags = (is_cd ? Location::IsCDMarker|Location::IsMark : Location::IsMark); @@ -700,7 +700,7 @@ Editor::mouse_add_new_marker (timepos_t const & where, bool is_cd) } void -Editor::mouse_add_new_loop (samplepos_t where) +Editor::mouse_add_new_loop (timepos_t where) { if (!_session) { return; @@ -710,13 +710,13 @@ Editor::mouse_add_new_loop (samplepos_t where) it's reasonably easy to manipulate after creation. */ - samplepos_t const end = where + current_page_samples() / 8; + timepos_t const end = where + timecnt_t (current_page_samples() / 8); - set_loop_range (timepos_t (where), timepos_t (end), _("set loop range")); + set_loop_range (where, timepos_t (end), _("set loop range")); } void -Editor::mouse_add_new_punch (samplepos_t where) +Editor::mouse_add_new_punch (timepos_t where) { if (!_session) { return; @@ -726,13 +726,13 @@ Editor::mouse_add_new_punch (samplepos_t where) it's reasonably easy to manipulate after creation. */ - samplepos_t const end = where + current_page_samples() / 8; + timepos_t const end = where + timecnt_t (current_page_samples() / 8); - set_punch_range (timepos_t (where), timepos_t (end), _("set punch range")); + set_punch_range (where, end, _("set punch range")); } void -Editor::mouse_add_new_range (samplepos_t where) +Editor::mouse_add_new_range (timepos_t where) { if (!_session) { return; @@ -742,7 +742,7 @@ Editor::mouse_add_new_range (samplepos_t where) it's reasonably easy to manipulate after creation. */ - samplepos_t const end = where + current_page_samples() / 8; + timepos_t const end = where + timecnt_t (current_page_samples() / 8); string name; _session->locations()->next_available_name (name, _("range")); diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 14ce6f4665..7828a28d81 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -1626,7 +1626,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT case SamplesRulerItem: case MinsecRulerItem: case BBTRulerItem: - popup_ruler_menu (where.sample, item_type); + popup_ruler_menu (timepos_t (where), item_type); break; case MarkerItem: diff --git a/gtk2_ardour/editor_routes.cc b/gtk2_ardour/editor_routes.cc index cf85dc2d54..572170a1f1 100644 --- a/gtk2_ardour/editor_routes.cc +++ b/gtk2_ardour/editor_routes.cc @@ -1805,7 +1805,7 @@ EditorRoutes::solo_changed_so_update_mute () void EditorRoutes::show_tracks_with_regions_at_playhead () { - boost::shared_ptr const r = _session->get_routes_with_regions_at (_session->transport_sample ()); + boost::shared_ptr const r = _session->get_routes_with_regions_at (timepos_t (_session->transport_sample ())); set show; for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) { diff --git a/gtk2_ardour/editor_rulers.cc b/gtk2_ardour/editor_rulers.cc index e8f777d3dc..4716aa21c4 100644 --- a/gtk2_ardour/editor_rulers.cc +++ b/gtk2_ardour/editor_rulers.cc @@ -201,7 +201,7 @@ Editor::ruler_label_button_release (GdkEventButton* ev) } void -Editor::popup_ruler_menu (samplepos_t where, ItemType t) +Editor::popup_ruler_menu (timepos_t const & where, ItemType t) { using namespace Menu_Helpers; diff --git a/gtk2_ardour/editor_tempodisplay.cc b/gtk2_ardour/editor_tempodisplay.cc index 4edc37ab50..85069b971e 100644 --- a/gtk2_ardour/editor_tempodisplay.cc +++ b/gtk2_ardour/editor_tempodisplay.cc @@ -402,15 +402,18 @@ Editor::maybe_draw_grid_lines () } void -Editor::mouse_add_new_tempo_event (samplepos_t sample) +Editor::mouse_add_new_tempo_event (timepos_t pos) { if (_session == 0) { return; } +#warning NUTEMPO requires new tempo map API +#if 0 TempoMap& map(_session->tempo_map()); begin_reversible_command (_("add tempo mark")); + const double pulse = map.exact_qn_at_sample (sample, get_grid_music_divisions (0)) / 4.0; if (pulse > 0.0) { @@ -422,20 +425,21 @@ Editor::mouse_add_new_tempo_event (samplepos_t sample) _session->add_command(new MementoCommand(map, &before, &after)); commit_reversible_command (); } - +#endif //map.dump (cerr); } void -Editor::mouse_add_new_meter_event (samplepos_t sample) +Editor::mouse_add_new_meter_event (timepos_t pos) { if (_session == 0) { return; } - +#warning NUTEMPO requires new tempo map API +#if 0 TempoMap& map(_session->tempo_map()); - MeterDialog meter_dialog (map, sample, _("add")); + MeterDialog meter_dialog (map, pos, _("add")); switch (meter_dialog.run ()) { case RESPONSE_ACCEPT: @@ -454,6 +458,7 @@ Editor::mouse_add_new_meter_event (samplepos_t sample) const double al_sample = map.sample_at_bbt (requested); begin_reversible_command (_("add meter mark")); + XMLNode &before = map.get_state(); if (meter_dialog.get_lock_style() == MusicTime) { @@ -464,7 +469,7 @@ Editor::mouse_add_new_meter_event (samplepos_t sample) _session->add_command(new MementoCommand(map, &before, &map.get_state())); commit_reversible_command (); - +#endif //map.dump (cerr); } diff --git a/gtk2_ardour/editor_timefx.cc b/gtk2_ardour/editor_timefx.cc index 2841bb7a3f..8cb1addb67 100644 --- a/gtk2_ardour/editor_timefx.cc +++ b/gtk2_ardour/editor_timefx.cc @@ -112,7 +112,7 @@ Editor::time_stretch (RegionSelection& regions, float fraction) stretch.run (*i); playlist->replace_region (regions.front()->region(), stretch.results[0], - regions.front()->region()->position()); + regions.front()->region()->nt_position()); midi_playlists_affected.insert (playlist); } @@ -168,9 +168,9 @@ Editor::time_fx (RegionList& regions, float val, bool pitching) return 0; } - const samplecnt_t oldlen = (samplecnt_t) (regions.front()->length()); - const samplecnt_t newlen = (samplecnt_t) (regions.front()->length() * val); - const samplecnt_t pos = regions.front()->position (); + const timecnt_t oldlen = regions.front()->nt_length(); + const timecnt_t newlen = regions.front()->nt_length() * val; + const timecnt_t pos = regions.front()->nt_position (); current_timefx = new TimeFXDialog (*this, pitching, oldlen, newlen, pos); current_timefx->regions = regions; diff --git a/gtk2_ardour/export_dialog.cc b/gtk2_ardour/export_dialog.cc index 7c422a3327..c1a32cfbc2 100644 --- a/gtk2_ardour/export_dialog.cc +++ b/gtk2_ardour/export_dialog.cc @@ -584,7 +584,7 @@ ExportRegionDialog::init_gui () void ExportRegionDialog::init_components () { - string loc_id = profile_manager->set_single_range (region.position(), region.position() + region.length(), region.name()); + string loc_id = profile_manager->set_single_range (region.nt_position(), region.nt_position() + region.nt_length(), region.name()); preset_selector.reset (new ExportPresetSelector ()); timespan_selector.reset (new ExportTimespanSelectorSingle (_session, profile_manager, loc_id)); diff --git a/gtk2_ardour/export_video_dialog.cc b/gtk2_ardour/export_video_dialog.cc index f46127698d..bce5cc8536 100644 --- a/gtk2_ardour/export_video_dialog.cc +++ b/gtk2_ardour/export_video_dialog.cc @@ -731,7 +731,7 @@ ExportVideoDialog::launch_export () end += av_offset; } else if (insnd_combo.get_active_row_number() == 2) { - start = ARDOUR_UI::instance()->video_timeline->quantify_samples_to_apv(export_range.start()); + start = ARDOUR_UI::instance()->video_timeline->quantify_samples_to_apv(export_range.start_sample()); end = ARDOUR_UI::instance()->video_timeline->quantify_samples_to_apv(export_range.end_sample()); } if (end <= 0) { @@ -954,7 +954,7 @@ ExportVideoDialog::encode_pass (int pass) duration_s = (double)duration_f / (double)_session->nominal_sample_rate(); } else if (insnd_combo.get_active_row_number() == 2) { /* selected range */ - duration_s = export_range.length() / (double)_session->nominal_sample_rate(); + duration_s = export_range.length_samples() / (double)_session->nominal_sample_rate(); } else { /* video start to end */ samplecnt_t duration_f = ARDOUR_UI::instance()->video_timeline->get_duration(); @@ -975,7 +975,7 @@ ExportVideoDialog::encode_pass (int pass) start = _session->current_start_sample(); snend = _session->current_end_sample(); } else { - start = export_range.start(); + start = export_range.start_sample(); snend = export_range.end_sample(); } diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index cef7ab33ee..fca2a3bc61 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -110,9 +110,6 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Container* parent, : RegionView (parent, tv, r, spu, basic_color) , _current_range_min(0) , _current_range_max(0) - , _region_relative_time_converter(r->session().tempo_map(), Temporal::Beats::from_double (r->position())) - , _source_relative_time_converter(r->session().tempo_map(), Temporal::Beats::from_double (r->position() - r->start())) - , _region_relative_time_converter_double(r->session().tempo_map(), Temporal::Beats::from_double (r->position())) , _active_notes(0) , _note_group (new ArdourCanvas::Container (group)) , _note_diff_command (0) @@ -155,9 +152,6 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Container* parent, : RegionView (parent, tv, r, spu, basic_color, recording, visibility) , _current_range_min(0) , _current_range_max(0) - , _region_relative_time_converter(r->session().tempo_map(), r->position()) - , _source_relative_time_converter(r->session().tempo_map(), r->position() - r->start()) - , _region_relative_time_converter_double(r->session().tempo_map(), r->position()) , _active_notes(0) , _note_group (new ArdourCanvas::Container (group)) , _note_diff_command (0) @@ -209,9 +203,6 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other) , RegionView (other) , _current_range_min(0) , _current_range_max(0) - , _region_relative_time_converter(other.region_relative_time_converter()) - , _source_relative_time_converter(other.source_relative_time_converter()) - , _region_relative_time_converter_double(other.region_relative_time_converter_double()) , _active_notes(0) , _note_group (new ArdourCanvas::Container (get_canvas_group())) , _note_diff_command (0) @@ -238,9 +229,6 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other, boost::shared_ptr (region)) , _current_range_min(0) , _current_range_max(0) - , _region_relative_time_converter(other.region_relative_time_converter()) - , _source_relative_time_converter(other.source_relative_time_converter()) - , _region_relative_time_converter_double(other.region_relative_time_converter_double()) , _active_notes(0) , _note_group (new ArdourCanvas::Container (get_canvas_group())) , _note_diff_command (0) @@ -863,8 +851,7 @@ MidiRegionView::create_note_at (samplepos_t t, double y, Temporal::Beats length, } // Start of note in samples relative to region start - const int32_t divisions = trackview.editor().get_grid_music_divisions (state); - Temporal::Beats beat_time = snap_sample_to_grid_underneath (t, divisions, shift_snap); + Temporal::Beats beat_time = snap_sample_to_grid_underneath (t, shift_snap); const double note = view->y_to_note(y); const uint8_t chan = mtv->get_channel_for_add(); @@ -1261,12 +1248,12 @@ MidiRegionView::display_patch_changes_on_channel (uint8_t channel, bool active_c if ((p = find_canvas_patch_change (*i)) != 0) { - const samplecnt_t region_samples = source_beats_to_region_samples ((*i)->time()); + const timepos_t region_time = _region->source_beats_to_region_time ((*i)->time()); - if (region_samples < 0 || region_samples >= _region->length()) { + if (region_time < timepos_t() || region_time >= _region->nt_length()) { p->hide(); } else { - const double x = trackview.editor().sample_to_pixel (region_samples); + const double x = trackview.editor().time_to_pixel (region_time); p->canvas_item()->set_position (ArdourCanvas::Duple (x, 1.0)); p->update_name (); @@ -1318,7 +1305,7 @@ MidiRegionView::display_sysexes() for (MidiModel::SysExes::const_iterator i = _model->sysexes().begin(); i != _model->sysexes().end(); ++i) { MidiModel::SysExPtr sysex_ptr = *i; - Temporal::Beats time = sysex_ptr->time(); + timepos_t time = timepos_t (sysex_ptr->time()); if ((*i)->is_spp() || (*i)->is_mtc_quarter() || (*i)->is_mtc_full()) { if (!display_periodic_messages) { @@ -1336,7 +1323,7 @@ MidiRegionView::display_sysexes() } string text = str.str(); - const double x = trackview.editor().sample_to_pixel(source_beats_to_region_samples(time)); + const double x = trackview.editor().time_to_pixel (_region->source_beats_to_region_time (time.beats())); double height = midi_stream_view()->contents_height(); @@ -1354,7 +1341,7 @@ MidiRegionView::display_sysexes() } // Show unless message is beyond the region bounds - if (time - mregion->start_beats() >= mregion->length_beats() || time < mregion->start_beats()) { + if (_region->source_relative_position (time) >= _region->nt_length() || time < _region->nt_start()) { sysex->hide(); } else { sysex->show(); @@ -1389,15 +1376,12 @@ MidiRegionView::region_resized (const PropertyChange& what_changed) RegionView::region_resized(what_changed); // calls RegionView::set_duration() if (what_changed.contains (ARDOUR::Properties::position)) { - _region_relative_time_converter.set_origin_b(_region->position()); - _region_relative_time_converter_double.set_origin_b(_region->position()); /* reset_width dependent_items() redisplays model */ } if (what_changed.contains (ARDOUR::Properties::start) || what_changed.contains (ARDOUR::Properties::position)) { - _source_relative_time_converter.set_origin_b (_region->position() - _region->start()); } /* catch end and start trim so we can update the view*/ if (!what_changed.contains (ARDOUR::Properties::start) && @@ -1481,7 +1465,7 @@ MidiRegionView::apply_note_range (uint8_t min, uint8_t max, bool force) GhostRegion* MidiRegionView::add_ghost (TimeAxisView& tv) { - double unit_position = _region->position () / samples_per_pixel; + double unit_position = trackview.editor().time_to_pixel (_region->nt_position ()); MidiTimeAxisView* mtv = dynamic_cast(&tv); MidiGhostRegion* ghost; @@ -1496,7 +1480,7 @@ MidiRegionView::add_ghost (TimeAxisView& tv) ghost->set_colors (); ghost->set_height (); - ghost->set_duration (_region->length() / samples_per_pixel); + ghost->set_duration (_region->nt_length().samples() / samples_per_pixel); for (Events::iterator i = _events.begin(); i != _events.end(); ++i) { ghost->add_note(i->second); @@ -1550,9 +1534,7 @@ MidiRegionView::resolve_note (uint8_t note, Temporal::Beats end_time) _active_notes[note]->note()->set_length (end_time - _active_notes[note]->note()->time()); /* End time is relative to the region being recorded. */ - const samplepos_t end_time_samples = region_beats_to_region_samples (end_time); - - _active_notes[note]->set_x1 (trackview.editor().sample_to_pixel(end_time_samples)); + _active_notes[note]->set_x1 (trackview.editor().time_to_pixel (_region->region_beats_to_region_time (end_time))); _active_notes[note]->set_outline_all (); _active_notes[note] = 0; } @@ -1570,7 +1552,7 @@ MidiRegionView::extend_active_notes() for (unsigned i = 0; i < 128; ++i) { if (_active_notes[i]) { - _active_notes[i]->set_x1 (trackview.editor().sample_to_pixel(_region->length())); + _active_notes[i]->set_x1 (trackview.editor().duration_to_pixels (_region->nt_length())); } } } @@ -1631,8 +1613,7 @@ MidiRegionView::note_in_region_range (const boost::shared_ptr note, bo const boost::shared_ptr midi_reg = midi_region(); /* must compare double explicitly as Beats::operator< rounds to ppqn */ - const bool outside = (note->time() < midi_reg->start_beats() || - note->time() >= midi_reg->start_beats() + midi_reg->length_beats()); + const bool outside = (timepos_t (note->time()) < _region->nt_start()) || (timepos_t (note->time()) >= _region->nt_start() + _region->nt_length()); visible = (note->note() >= _current_range_min) && (note->note() <= _current_range_max); @@ -1659,14 +1640,11 @@ MidiRegionView::update_note (NoteBase* note, bool update_ghost_regions) void MidiRegionView::update_sustained (Note* ev, bool update_ghost_regions) { - TempoMap& map (trackview.session()->tempo_map()); const boost::shared_ptr mr = midi_region(); boost::shared_ptr note = ev->note(); + const timepos_t note_start = _region->source_beats_to_absolute_time (note->time()); - const double session_source_start = _region->quarter_note() - mr->start_beats(); - const samplepos_t note_start_samples = map.sample_at_quarter_note (note->time() + session_source_start) - _region->position(); - - const double x0 = max (0.,trackview.editor().sample_to_pixel (note_start_samples)); + const double x0 = trackview.editor().time_to_pixel (note_start); double x1; const double y0 = 1 + floor(note_to_y(note->note())); double y1; @@ -1681,21 +1659,19 @@ MidiRegionView::update_sustained (Note* ev, bool update_ghost_regions) /* normal note */ - Temporal::Beats note_end_time = note->end_time(); + timepos_t note_end (note->end_time()); - if (note->end_time() > mr->start_beats() + mr->length_beats()) { - note_end_time = mr->start_beats() + mr->length_beats(); + if (note_end > mr->nt_start() + mr->nt_length()) { + note_end = mr->nt_start() + mr->nt_length(); } - const samplepos_t note_end_samples = map.sample_at_quarter_note (session_source_start + note_end_time) - _region->position(); - - x1 = std::max(1., trackview.editor().sample_to_pixel (note_end_samples)) - 1; + x1 = std::max(1., trackview.editor().time_to_pixel (note_end)) - 1; } else { /* nascent note currently being recorded, noteOff has not yet arrived */ - x1 = std::max(1., trackview.editor().sample_to_pixel (_region->length())) - 1; + x1 = std::max(1., trackview.editor().duration_to_pixels (_region->nt_length())) - 1; } y1 = y0 + std::max(1., floor(note_height()) - 1); @@ -1735,11 +1711,9 @@ void MidiRegionView::update_hit (Hit* ev, bool update_ghost_regions) { boost::shared_ptr note = ev->note(); + const timepos_t note_time = _region->source_beats_to_absolute_time (note->time()); - const double note_time_qn = note->time() + (_region->quarter_note() - midi_region()->start_beats()); - const samplepos_t note_start_samples = trackview.session()->tempo_map().sample_at_quarter_note (note_time_qn) - _region->position(); - - const double x = trackview.editor().sample_to_pixel(note_start_samples); + const double x = trackview.editor().time_to_pixel(note_time); const double diamond_size = std::max(1., floor(note_height()) - 2.); const double y = 1.5 + floor(note_to_y(note->note())) + diamond_size * .5; @@ -1757,7 +1731,6 @@ MidiRegionView::update_hit (Hit* ev, bool update_ghost_regions) const uint32_t base_col = ev->base_color(); ev->set_fill_color(base_col); ev->set_outline_color(ev->calculate_outline(base_col, ev->selected())); - } /** Add a MIDI note to the view (with length). @@ -1835,12 +1808,11 @@ MidiRegionView::step_add_note (uint8_t channel, uint8_t number, uint8_t velocity /* potentially extend region to hold new note */ - samplepos_t end_sample = source_beats_to_absolute_samples (new_note->end_time()); - samplepos_t region_end = _region->last_sample(); + timepos_t note_end = _region->source_beats_to_absolute_time (new_note->end_time()); + timepos_t region_end = _region->nt_last(); - if (end_sample > region_end) { - /* XX sets length in beats from audio space. make musical */ - _region->set_length (end_sample - _region->position(), 0); + if (note_end > region_end) { + _region->set_length (timecnt_t (note_end.earlier (_region->nt_position()), timepos_t())); } MidiTimeAxisView* const mtv = dynamic_cast(&trackview); @@ -1874,8 +1846,8 @@ MidiRegionView::step_sustain (Temporal::Beats beats) void MidiRegionView::add_canvas_patch_change (MidiModel::PatchChangePtr patch) { - samplecnt_t region_samples = source_beats_to_region_samples (patch->time()); - const double x = trackview.editor().sample_to_pixel (region_samples); + timepos_t patch_time = _region->source_beats_to_absolute_time (patch->time()); + const double x = trackview.editor().time_to_pixel (patch_time); double const height = midi_stream_view()->contents_height(); @@ -1894,7 +1866,7 @@ MidiRegionView::add_canvas_patch_change (MidiModel::PatchChangePtr patch) if (patch_change->item().width() < _pixel_width) { // Show unless patch change is beyond the region bounds - if (region_samples < 0 || region_samples >= _region->length()) { + if (patch_time < _region->nt_position() || patch_time >= _region->nt_last()) { patch_change->hide(); } else { patch_change->show(); @@ -2019,19 +1991,17 @@ MidiRegionView::change_patch_change (MidiModel::PatchChangePtr old_change, const * MidiTimeAxisView::get_channel_for_add()) */ void -MidiRegionView::add_patch_change (samplecnt_t t, Evoral::PatchChange const & patch) +MidiRegionView::add_patch_change (timecnt_t const & t, Evoral::PatchChange const & patch) { string name = _("add patch change"); trackview.editor().begin_reversible_command (name); MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (name); + c->add (MidiModel::PatchChangePtr ( - new Evoral::PatchChange ( - absolute_samples_to_source_beats (_region->position() + t), - patch.channel(), patch.program(), patch.bank() - ) - ) - ); + new Evoral::PatchChange + (_region->source_relative_position (_region->nt_position() + t).beats(), + patch.channel(), patch.program(), patch.bank()))); _model->apply_command (*trackview.session(), c); trackview.editor().commit_reversible_command (); @@ -2171,11 +2141,11 @@ MidiRegionView::select_all_notes () } void -MidiRegionView::select_range (samplepos_t start, samplepos_t end) +MidiRegionView::select_range (timepos_t const & start, timepos_t const & end) { PBD::Unwinder uw (_no_sound_notes, true); for (Events::iterator i = _events.begin(); i != _events.end(); ++i) { - samplepos_t t = source_beats_to_absolute_samples(i->first->time()); + timepos_t t = _region->source_beats_to_absolute_time (i->first->time()); if (t >= start && t <= end) { add_to_selection (i->second); } @@ -2403,10 +2373,9 @@ MidiRegionView::update_drag_selection(samplepos_t start, samplepos_t end, double PublicEditor& editor = trackview.editor(); // Convert to local coordinates - const samplepos_t p = _region->position(); const double y = midi_view()->y_position(); - const double x0 = editor.sample_to_pixel(max((samplepos_t)0, start - p)); - const double x1 = editor.sample_to_pixel(max((samplepos_t)0, end - p)); + const double x0 = editor.time_to_pixel (max (timepos_t(), _region->region_relative_position (timepos_t (start)))); + const double x1 = editor.time_to_pixel (max (timepos_t(), _region->region_relative_position (timepos_t (end)))); const double y0 = max(0.0, gy0 - y); const double y1 = max(0.0, gy1 - y); @@ -2433,8 +2402,12 @@ MidiRegionView::update_drag_selection(samplepos_t start, samplepos_t end, double const ATracks& atracks = midi_view()->automation_tracks(); Selectables selectables; editor.get_selection().clear_points(); + + timepos_t st (start); + timepos_t et (end); + for (ATracks::const_iterator a = atracks.begin(); a != atracks.end(); ++a) { - a->second->get_selectables(start, end, gy0, gy1, selectables); + a->second->get_selectables (st, et, gy0, gy1, selectables); for (Selectables::const_iterator s = selectables.begin(); s != selectables.end(); ++s) { ControlPoint* cp = dynamic_cast(*s); if (cp) { @@ -2531,7 +2504,7 @@ MidiRegionView::earliest_in_selection () } void -MidiRegionView::move_selection(double dx_qn, double dy, double cumulative_dy) +MidiRegionView::move_selection(Temporal::Beats const & dx_qn, double dy, double cumulative_dy) { typedef vector > PossibleChord; Editor* editor = dynamic_cast (&trackview.editor()); @@ -2544,8 +2517,9 @@ MidiRegionView::move_selection(double dx_qn, double dy, double cumulative_dy) if (n->note()->time() == earliest) { to_play.push_back (n->note()); } - double const note_time_qn = session_relative_qn (n->note()->time()); + Temporal::Beats const note_time_qn = _region->source_beats_to_absolute_beats (n->note()->time()); double dx = 0.0; + if (midi_view()->note_mode() == Sustained) { dx = editor->sample_to_pixel_unrounded (tmap.sample_at_quarter_note (note_time_qn + dx_qn)) - n->item()->item_to_canvas (ArdourCanvas::Duple (n->x0(), 0)).x; @@ -2640,8 +2614,10 @@ MidiRegionView::move_copies (Temporal::Beats const & dx_qn, double dy, double c if (n->note()->time() == earliest) { to_play.push_back (n->note()); } - Temporal::Beats const note_time_qn = Temporal::Beats::from_double (session_relative_qn (n->note()->time())); + + Temporal::Beats const note_time_qn = _region->source_beats_to_absolute_beats (n->note()->time()); double dx = 0.0; + if (midi_view()->note_mode() == Sustained) { dx = editor->sample_to_pixel_unrounded (tmap.sample_at_quarter_note (note_time_qn + dx_qn)) - n->item()->item_to_canvas (ArdourCanvas::Duple (n->x0(), 0)).x; @@ -2801,13 +2777,13 @@ MidiRegionView::note_dropped(NoteBase *, Temporal::Beats const & d_qn, int8_t dn /** @param x Pixel relative to the region position. * @param ensure_snap defaults to false. true = snap always, ignoring snap mode and magnetic snap. * Used for inverting the snap logic with key modifiers and snap delta calculation. - * @return Snapped sample relative to the region position. + * @return Snapped time relative to the region position. */ -samplepos_t -MidiRegionView::snap_pixel_to_sample(double x, bool ensure_snap) +timepos_t +MidiRegionView::snap_pixel_to_time (double x, bool ensure_snap) { PublicEditor& editor (trackview.editor()); - return snap_sample_to_sample (editor.pixel_to_sample (x), ensure_snap).sample; + return snap_region_time_to_region_time (timepos_t (editor.pixel_to_sample (x)), ensure_snap); } /** @param x Pixel relative to the region position. @@ -2817,21 +2793,20 @@ MidiRegionView::snap_pixel_to_sample(double x, bool ensure_snap) double MidiRegionView::snap_to_pixel(double x, bool ensure_snap) { - return (double) trackview.editor().sample_to_pixel(snap_pixel_to_sample(x, ensure_snap)); + return (double) trackview.editor().time_to_pixel(snap_pixel_to_time(x, ensure_snap)); } double MidiRegionView::get_position_pixels() { - samplepos_t region_sample = get_position(); - return trackview.editor().sample_to_pixel(region_sample); + return trackview.editor().time_to_pixel(get_position()); } double MidiRegionView::get_end_position_pixels() { - samplepos_t sample = get_position() + get_duration (); - return trackview.editor().sample_to_pixel(sample); + const timepos_t end = get_position() + get_duration (); + return trackview.editor().time_to_pixel (end); } void @@ -2886,7 +2861,6 @@ MidiRegionView::begin_resizing (bool /*at_front*/) void MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_x, bool relative, double snap_delta, bool with_snap) { - TempoMap& tmap (trackview.session()->tempo_map()); bool cursor_set = false; bool const ensure_snap = trackview.editor().snap_mode () != SnapMagnetic; @@ -2915,8 +2889,8 @@ MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_ */ current_x = 0; } - if (current_x > trackview.editor().sample_to_pixel(_region->length())) { - current_x = trackview.editor().sample_to_pixel(_region->length()); + if (current_x > trackview.editor().duration_to_pixels (_region->nt_length())) { + current_x = trackview.editor().duration_to_pixels (_region->nt_length()); } if (at_front) { @@ -2935,47 +2909,49 @@ MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_ resize_rect->set_x0 (canvas_note->x0()); } + if (!cursor_set) { /* Convert snap delta from pixels to beats. */ samplepos_t snap_delta_samps = trackview.editor().pixel_to_sample (snap_delta); double snap_delta_beats = 0.0; int sign = 1; + /* negative beat offsets aren't allowed */ if (snap_delta_samps > 0) { - snap_delta_beats = region_samples_to_region_beats_double (snap_delta_samps); + snap_delta_beats = _region->region_distance_to_region_beats (timecnt_t (snap_delta_samps, _region->nt_position())); } else if (snap_delta_samps < 0) { - snap_delta_beats = region_samples_to_region_beats_double (- snap_delta_samps); + snap_delta_beats = _region->region_distance_to_region_beats (timecnt_t (-snap_delta_samps, _region->nt_position())); sign = -1; } - double snapped_x; - int32_t divisions = 0; + timepos_t snapped_x; if (with_snap) { - snapped_x = snap_pixel_to_sample (current_x, ensure_snap); - divisions = trackview.editor().get_grid_music_divisions (0); + snapped_x = snap_pixel_to_time (current_x, ensure_snap); /* units depend on snap settings */ } else { - snapped_x = trackview.editor ().pixel_to_sample (current_x); + snapped_x = trackview.editor ().pixel_to_sample (current_x); /* samples */ } - const Temporal::Beats beats = Temporal::Beats::from_double (tmap.exact_beat_at_sample (snapped_x + midi_region()->position(), divisions) - midi_region()->beat()) + midi_region()->start_beats(); - +#warning NUTEMPO need new tempo map API + //TempoMap& tmap (trackview.session()->tempo_map()); + //const timepos_t abs_beats (tmap.quarter_note_at (snapped_x)); + const timepos_t abs_beats; + const Temporal::Beats beats = _region->absolute_time_to_source_beats (abs_beats); Temporal::Beats len = Temporal::Beats(); if (at_front) { if (beats < canvas_note->note()->end_time()) { - len = canvas_note->note()->time() - beats + (sign * snap_delta_beats); + len = canvas_note->note()->time() - beats + (snap_delta_beats * sign); len += canvas_note->note()->length(); } } else { if (beats >= canvas_note->note()->time()) { - len = beats - canvas_note->note()->time() - (sign * snap_delta_beats); + len = beats - canvas_note->note()->time() - (snap_delta_beats * sign); } } - /* minimum length resulting from a trim is 1 tick */ - len = std::max (Temporal::Beats (0,1), len); + len = std::max (Temporal::Beats::from_double (1 / 512.0), len); char buf[16]; /* represent as float frac to help out the user */ @@ -2984,7 +2960,7 @@ MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_ cursor_set = true; - trackview.editor().set_snapped_cursor_position ( snapped_x + midi_region()->position() ); + trackview.editor().set_snapped_cursor_position ((snapped_x + midi_region()->nt_position()).samples()); } } @@ -3030,41 +3006,41 @@ MidiRegionView::commit_resizing (NoteBase* primary, bool at_front, double delta_ if (current_x < 0) { current_x = 0; } - if (current_x > trackview.editor().sample_to_pixel(_region->length())) { - current_x = trackview.editor().sample_to_pixel(_region->length()); + + if (current_x > trackview.editor().duration_to_pixels (_region->nt_length())) { + current_x = trackview.editor().duration_to_pixels (_region->nt_length()); } /* Convert snap delta from pixels to beats with sign. */ samplepos_t snap_delta_samps = trackview.editor().pixel_to_sample (snap_delta); - double snap_delta_beats = 0.0; + Temporal::Beats snap_delta_beats; int sign = 1; if (snap_delta_samps > 0) { - snap_delta_beats = region_samples_to_region_beats_double (snap_delta_samps); + snap_delta_beats = _region->region_distance_to_region_beats (timecnt_t (snap_delta_samps, _region->nt_position())); } else if (snap_delta_samps < 0) { - snap_delta_beats = region_samples_to_region_beats_double ( - snap_delta_samps); + snap_delta_beats = _region->region_distance_to_region_beats (timecnt_t (-snap_delta_samps, _region->nt_position())); sign = -1; } - uint32_t divisions = 0; /* Convert the new x position to a sample within the source */ - samplepos_t current_fr; + timepos_t current_time; if (with_snap) { - current_fr = snap_pixel_to_sample (current_x, ensure_snap); - divisions = trackview.editor().get_grid_music_divisions (0); + current_time = snap_pixel_to_time (current_x, ensure_snap); } else { - current_fr = trackview.editor().pixel_to_sample (current_x); + current_time = trackview.editor().pixel_to_sample (current_x); } /* and then to beats */ - const double e_qaf = tmap.exact_qn_at_sample (current_fr + midi_region()->position(), divisions); - const double quarter_note_start = _region->quarter_note() - midi_region()->start_beats(); - const Temporal::Beats x_beats = Temporal::Beats::from_double (e_qaf - quarter_note_start); +#warning NUTEMPO need new tempo map + //const timepos_t abs_beats (tmap.quarter_note_at (current_time)); + const timepos_t abs_beats; + const Temporal::Beats x_beats = _region->absolute_time_to_source_beats (abs_beats); if (at_front && x_beats < canvas_note->note()->end_time()) { - const Temporal::Beats new_start = x_beats - (sign * snap_delta_beats); - note_diff_add_change (canvas_note, MidiModel::NoteDiffCommand::StartTime, new_start); - Temporal::Beats len = canvas_note->note()->end_time() - new_start; + note_diff_add_change (canvas_note, MidiModel::NoteDiffCommand::StartTime, x_beats - (snap_delta_beats * sign)); + Temporal::Beats len = canvas_note->note()->time() - x_beats + (snap_delta_beats * sign); + len += canvas_note->note()->length(); if (!!len) { note_diff_add_change (canvas_note, MidiModel::NoteDiffCommand::Length, len); @@ -3072,7 +3048,7 @@ MidiRegionView::commit_resizing (NoteBase* primary, bool at_front, double delta_ } if (!at_front) { - Temporal::Beats len = std::max (Temporal::Beats(0, 1), x_beats - canvas_note->note()->time() - (sign * snap_delta_beats)); + Temporal::Beats len = std::max (Temporal::Beats (0, 1), x_beats - canvas_note->note()->time() - (snap_delta_beats * sign)); note_diff_add_change (canvas_note, MidiModel::NoteDiffCommand::Length, len); } @@ -3363,7 +3339,7 @@ MidiRegionView::change_note_lengths (bool fine, bool shorter, Temporal::Beats de delta = Temporal::Beats::ticks (Temporal::ticks_per_beat / 128); } else { /* grab the current grid distance */ - delta = get_grid_beats(_region->position()); + delta = get_grid_beats (_region->nt_position()); } } @@ -3401,16 +3377,16 @@ MidiRegionView::nudge_notes (bool forward, bool fine) into a vector and sort before using the first one. */ - const samplepos_t ref_point = source_beats_to_absolute_samples ((*(_selection.begin()))->note()->time()); + const timepos_t ref_point = _region->source_beats_to_absolute_time ((*(_selection.begin()))->note()->time()); Temporal::Beats delta; if (trackview.editor().snap_mode() == Editing::SnapOff) { /* grid is off - use nudge distance */ - samplepos_t unused; - const samplecnt_t distance = trackview.editor().get_nudge_distance (ref_point, unused); - delta = region_samples_to_region_beats (fabs ((double)distance)); + timecnt_t unused; + const timecnt_t distance = trackview.editor().get_nudge_distance (ref_point, unused); + delta = _region->region_distance_to_region_beats (timecnt_t (distance.beats(), _region->nt_position())); } else { @@ -3664,7 +3640,7 @@ MidiRegionView::selection_as_cut_buffer () const /** This method handles undo */ bool -MidiRegionView::paste (samplepos_t pos, const ::Selection& selection, PasteContext& ctx, const int32_t sub_num) +MidiRegionView::paste (timepos_t const & pos, const ::Selection& selection, PasteContext& ctx) { bool commit = false; // Paste notes, if available @@ -3681,7 +3657,7 @@ MidiRegionView::paste (samplepos_t pos, const ::Selection& selection, PasteConte typedef RouteTimeAxisView::AutomationTracks ATracks; const ATracks& atracks = midi_view()->automation_tracks(); for (ATracks::const_iterator a = atracks.begin(); a != atracks.end(); ++a) { - if (a->second->paste(pos, selection, ctx, sub_num)) { + if (a->second->paste(pos, selection, ctx)) { if(!commit) { trackview.editor().begin_reversible_command (Operations::paste); } @@ -3697,7 +3673,7 @@ MidiRegionView::paste (samplepos_t pos, const ::Selection& selection, PasteConte /** This method handles undo */ void -MidiRegionView::paste_internal (samplepos_t pos, unsigned paste_count, float times, const MidiCutBuffer& mcb) +MidiRegionView::paste_internal (timepos_t const & pos, unsigned paste_count, float times, const MidiCutBuffer& mcb) { if (mcb.empty()) { return; @@ -3710,14 +3686,14 @@ MidiRegionView::paste_internal (samplepos_t pos, unsigned paste_count, float tim const Temporal::Beats last_time = (*mcb.notes().rbegin())->end_time(); const Temporal::Beats duration = last_time - first_time; const Temporal::Beats snap_duration = duration.snap_to(snap_beats); - const Temporal::Beats paste_offset = snap_duration * paste_count; - const Temporal::Beats quarter_note = absolute_samples_to_source_beats(pos) + paste_offset; - Temporal::Beats end_point = Temporal::Beats(); + const Temporal::Beats paste_offset = snap_duration * int32_t (paste_count); + const Temporal::Beats quarter_note = _region->absolute_time_to_source_beats (pos) + paste_offset; + Temporal::Beats end_point; DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("Paste data spans from %1 to %2 (%3) ; paste pos beats = %4 (based on %5 - %6)\n", first_time, last_time, - duration, pos, _region->position(), + duration, pos, _region->nt_position(), quarter_note)); for (int n = 0; n < (int) times; ++n) { @@ -3737,16 +3713,16 @@ MidiRegionView::paste_internal (samplepos_t pos, unsigned paste_count, float tim /* if we pasted past the current end of the region, extend the region */ - samplepos_t end_sample = source_beats_to_absolute_samples (end_point); - samplepos_t region_end = _region->position() + _region->length() - 1; + timepos_t end = _region->source_beats_to_absolute_time (end_point); + timepos_t region_end = _region->nt_last(); - if (end_sample > region_end) { + if (end > region_end) { - DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("Paste extended region from %1 to %2\n", region_end, end_sample)); + DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("Paste extended region from %1 to %2\n", region_end, end)); _region->clear_changes (); /* we probably need to get the snap modifier somehow to make this correct for non-musical use */ - _region->set_length (end_sample - _region->position(), trackview.editor().get_grid_music_divisions (0)); + _region->set_length (_region->nt_position().distance (end)); trackview.session()->add_command (new StatefulDiffCommand (_region)); } @@ -3903,12 +3879,11 @@ MidiRegionView::update_ghost_note (double x, double y, uint32_t state) samplepos_t const unsnapped_sample = editor.pixel_to_sample (x); - const int32_t divisions = editor.get_grid_music_divisions (state); const bool shift_snap = midi_view()->note_mode() != Percussive; - const Temporal::Beats snapped_beats = snap_sample_to_grid_underneath (unsnapped_sample, divisions, shift_snap); + const Temporal::Beats snapped_beats = snap_sample_to_grid_underneath (unsnapped_sample, shift_snap); /* prevent Percussive mode from displaying a ghost hit at region end */ - if (!shift_snap && snapped_beats >= midi_region()->start_beats() + midi_region()->length_beats()) { + if (!shift_snap && snapped_beats >= _region->nt_start().beats() + _region->nt_length().beats()) { _ghost_note->hide(); hide_verbose_cursor (); return; @@ -3927,14 +3902,13 @@ MidiRegionView::update_ghost_note (double x, double y, uint32_t state) _ghost_note->show(); /* calculate time in beats relative to start of source */ - const Temporal::Beats length = get_grid_beats(unsnapped_sample + _region->position()); + const Temporal::Beats length = get_grid_beats (_region->nt_position() + timepos_t (unsnapped_sample)); _ghost_note->note()->set_time (snapped_beats); _ghost_note->note()->set_length (length); _ghost_note->note()->set_note (y_to_note (y)); _ghost_note->note()->set_channel (mtv->get_channel_for_add ()); _ghost_note->note()->set_velocity (get_velocity_for_add (snapped_beats)); - /* the ghost note does not appear in ghost regions, so pass false in here */ update_note (_ghost_note, false); show_verbose_cursor (_ghost_note->note ()); @@ -4073,7 +4047,7 @@ MidiRegionView::move_step_edit_cursor (Temporal::Beats pos) _step_edit_cursor_position = pos; if (_step_edit_cursor) { - double pixel = trackview.editor().sample_to_pixel (region_beats_to_region_samples (pos)); + double pixel = trackview.editor().time_to_pixel (_region->region_beats_to_region_time (pos)); _step_edit_cursor->set_x0 (pixel); set_step_edit_cursor_width (_step_edit_cursor_width); } @@ -4093,10 +4067,9 @@ MidiRegionView::set_step_edit_cursor_width (Temporal::Beats beats) _step_edit_cursor_width = beats; if (_step_edit_cursor) { - _step_edit_cursor->set_x1 (_step_edit_cursor->x0() - + trackview.editor().sample_to_pixel ( - region_beats_to_region_samples (_step_edit_cursor_position + beats) - - region_beats_to_region_samples (_step_edit_cursor_position))); + _step_edit_cursor->set_x1 (_step_edit_cursor->x0() + trackview.editor().duration_to_pixels ( + _region->region_beats_to_region_time (_step_edit_cursor_position).distance + (_region->region_beats_to_region_time (_step_edit_cursor_position + beats)))); } } @@ -4134,9 +4107,12 @@ MidiRegionView::data_recorded (boost::weak_ptr w) } } - /* convert from session samples to source beats */ - Temporal::Beats const time_beats = _source_relative_time_converter.from( - ev.time() - src->natural_position() + _region->start()); + /* ev.time() is in MidiBuffer::TimeType i.e. samples + + we want to convert to beats relative to source start. + */ + + Temporal::Beats const time_beats = _region->absolute_time_to_source_beats (timepos_t (ev.time())); if (ev.type() == MIDI_CMD_NOTE_ON) { @@ -4174,7 +4150,7 @@ MidiRegionView::trim_front_starting () void MidiRegionView::trim_front_ending () { - if (_region->start() < 0) { + if (_region->nt_start().negative()) { /* Trim drag made start time -ve; fix this */ midi_region()->fix_negative_start (); } @@ -4183,7 +4159,7 @@ MidiRegionView::trim_front_ending () void MidiRegionView::edit_patch_change (PatchChange* pc) { - PatchChangeDialog d (&_source_relative_time_converter, trackview.session(), *pc->patch (), instrument_info(), Gtk::Stock::APPLY, true); + PatchChangeDialog d (trackview.session(), *pc->patch (), instrument_info(), Gtk::Stock::APPLY, true, true, _region); int response = d.run(); @@ -4294,25 +4270,32 @@ MidiRegionView::get_velocity_for_add (MidiModel::TimeType time) const * @return beat duration of p snapped to the grid subdivision underneath it. */ Temporal::Beats -MidiRegionView::snap_sample_to_grid_underneath (samplepos_t p, int32_t divisions, bool shift_snap) const +MidiRegionView::snap_sample_to_grid_underneath (samplepos_t p, bool shift_snap) const { - TempoMap& map (trackview.session()->tempo_map()); - double eqaf = map.exact_qn_at_sample (p + _region->position(), divisions); +#warning NUTEMPO new tempo map API required +#if 0 + Temporal::TempoMap& map (trackview.session()->tempo_map()); + Temporal::Beats eqaf = map.quarter_note_at (p + _region->position_sample()); - if (divisions != 0 && shift_snap) { - const Temporal::Beats qaf = Temporal::Beats::from_double (map.quarter_note_at_sample (p + _region->position())); + + if (shift_snap) { + const Temporal::Beats qaf = map.quarter_note_at (p + _region->position_sample()); /* Hack so that we always snap to the note that we are over, instead of snapping to the next one if we're more than halfway through the one we're over. */ - const Temporal::Beats grid_beats = get_grid_beats (p + _region->position()); - const double rem = eqaf - qaf; - if (rem >= 0.0) { + const Temporal::Beats grid_beats = get_grid_beats (p + _region->position_sample()); + const Temporal::Beats rem = eqaf - qaf; + + if (rem >= Temporal::Beats()) { eqaf -= grid_beats; } } - const double session_start_off = _region->quarter_note() - midi_region()->start_beats(); - return Temporal::Beats::from_double (eqaf - session_start_off); + const timepos_t e (eqaf); + + return _region->absolute_time_to_source_beats (e); +#endif + return Temporal::Beats (); } ChannelMode @@ -4331,14 +4314,16 @@ MidiRegionView::get_selected_channels () const Temporal::Beats -MidiRegionView::get_grid_beats(samplepos_t pos) const +MidiRegionView::get_grid_beats (timepos_t const & pos) const { PublicEditor& editor = trackview.editor(); bool success = false; Temporal::Beats beats = editor.get_grid_type_as_beats (success, pos); + if (!success) { beats = Temporal::Beats (1, 0); } + return beats; } uint8_t @@ -4363,8 +4348,3 @@ MidiRegionView::note_to_y(uint8_t note) const return contents_height() - (note + 1 - _current_range_min) * note_height() + 1; } -double -MidiRegionView::session_relative_qn (double qn) const -{ - return qn + (region()->quarter_note() - midi_region()->start_beats()); -} diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index e41bbe1b66..2a092f172e 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -128,8 +128,8 @@ public: void resolve_note(uint8_t note_num, Temporal::Beats end_time); void cut_copy_clear (Editing::CutCopyOp); - bool paste (samplepos_t pos, const ::Selection& selection, PasteContext& ctx, const int32_t sub_num); - void paste_internal (samplepos_t pos, unsigned paste_count, float times, const MidiCutBuffer&); + bool paste (Temporal::timepos_t const & pos, const ::Selection& selection, PasteContext& ctx); + void paste_internal (Temporal::timepos_t const & pos, unsigned paste_count, float times, const MidiCutBuffer&); void add_canvas_patch_change (ARDOUR::MidiModel::PatchChangePtr patch); void remove_canvas_patch_change (PatchChange* pc); @@ -153,7 +153,7 @@ public: void change_patch_change (PatchChange& old_patch, const MIDI::Name::PatchPrimaryKey& new_patch); void change_patch_change (ARDOUR::MidiModel::PatchChangePtr, Evoral::PatchChange const &); - void add_patch_change (samplecnt_t, Evoral::PatchChange const &); + void add_patch_change (Temporal::timecnt_t const &, Evoral::PatchChange const &); void move_patch_change (PatchChange &, Temporal::Beats); void delete_patch_change (PatchChange *); void edit_patch_change (PatchChange *); @@ -205,12 +205,12 @@ public: void delete_note (boost::shared_ptr); size_t selection_size() { return _selection.size(); } void select_all_notes (); - void select_range(samplepos_t start, samplepos_t end); + void select_range(Temporal::timepos_t const & start, Temporal::timepos_t const & end); void invert_selection (); void extend_selection (); Temporal::Beats earliest_in_selection (); - void move_selection(double dx, double dy, double cumulative_dy); + void move_selection(Temporal::Beats const & dx, double dy, double cumulative_dy); void note_dropped (NoteBase* ev, Temporal::Beats const & d_qn, int8_t d_note, bool copy); NoteBase* copy_selection (NoteBase* primary); void move_copies(Temporal::Beats const & dx_qn, double dy, double cumulative_dy); @@ -450,10 +450,6 @@ public: typedef boost::unordered_map > SysExes; typedef std::vector CopyDragEvents; - ARDOUR::BeatsSamplesConverter _region_relative_time_converter; - ARDOUR::BeatsSamplesConverter _source_relative_time_converter; - ARDOUR::BeatsSamplesConverter _region_relative_time_converter_double; - boost::shared_ptr _model; Events _events; CopyDragEvents _copy_drag_events; @@ -533,7 +529,7 @@ public: void data_recorded (boost::weak_ptr); /** Get grid type as beats, or default to 1 if not snapped to beats. */ - Temporal::Beats get_grid_beats(samplepos_t pos) const; + Temporal::Beats get_grid_beats(Temporal::timepos_t const & pos) const; void remove_ghost_note (); void mouse_mode_changed (); @@ -553,7 +549,7 @@ public: Gtkmm2ext::Color _patch_change_outline; Gtkmm2ext::Color _patch_change_fill; - Temporal::Beats snap_sample_to_grid_underneath (samplepos_t p, int32_t divisions, bool shift_snap) const; + Temporal::Beats snap_sample_to_grid_underneath (samplepos_t p, bool shift_snap) const; PBD::ScopedConnection _mouse_mode_connection; diff --git a/gtk2_ardour/option_editor.cc b/gtk2_ardour/option_editor.cc index 6738848a2d..e2eba9617e 100644 --- a/gtk2_ardour/option_editor.cc +++ b/gtk2_ardour/option_editor.cc @@ -643,20 +643,20 @@ ClockOption::set_state_from_config () Timecode::Time TC; samplepos_t when; if (!Timecode::parse_timecode_format(_get(), TC)) { - _clock.set (0, true); + _clock.set (timepos_t (0), true); } TC.rate = _session->samples_per_timecode_frame(); TC.drop = _session->timecode_drop_frames(); _session->timecode_to_sample(TC, when, false, false); if (TC.negative) { when=-when; } - _clock.set (when, true); + _clock.set (timepos_t (when), true); } void ClockOption::save_clock_time () { Timecode::Time TC; - _session->sample_to_timecode(_clock.current_time(), TC, false, false); + _session->sample_to_timecode (_clock.current_time().samples(), TC, false, false); _set (Timecode::timecode_format_time(TC)); } diff --git a/gtk2_ardour/patch_change_dialog.cc b/gtk2_ardour/patch_change_dialog.cc index a6ea57f109..9b8acaee7f 100644 --- a/gtk2_ardour/patch_change_dialog.cc +++ b/gtk2_ardour/patch_change_dialog.cc @@ -42,7 +42,6 @@ using namespace Gtkmm2ext; /** @param tc If non-0, a time converter for this patch change. If 0, time control will be desensitized */ PatchChangeDialog::PatchChangeDialog ( - const ARDOUR::BeatsSamplesConverter* tc, ARDOUR::Session* session, Evoral::PatchChange const& patch, ARDOUR::InstrumentInfo& info, diff --git a/gtk2_ardour/patch_change_dialog.h b/gtk2_ardour/patch_change_dialog.h index d45c2d2a20..65cd243e99 100644 --- a/gtk2_ardour/patch_change_dialog.h +++ b/gtk2_ardour/patch_change_dialog.h @@ -42,7 +42,6 @@ class PatchChangeDialog : public ArdourDialog { public: PatchChangeDialog ( - const ARDOUR::BeatsSamplesConverter*, ARDOUR::Session*, Evoral::PatchChange const&, ARDOUR::InstrumentInfo&, diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h index 72845155a0..9bc7c88ee4 100644 --- a/gtk2_ardour/public_editor.h +++ b/gtk2_ardour/public_editor.h @@ -210,6 +210,10 @@ public: virtual samplepos_t playhead_cursor_sample () const = 0; virtual double sample_to_pixel (samplepos_t sample) const = 0; virtual double sample_to_pixel_unrounded (samplepos_t sample) const = 0; + virtual double time_to_pixel (Temporal::timepos_t const &) const = 0; + virtual double time_to_pixel_unrounded (Temporal::timepos_t const &) const = 0; + virtual double duration_to_pixels (Temporal::timecnt_t const &) const = 0; + virtual double duration_to_pixels_unrounded (Temporal::timecnt_t const &) const = 0; virtual Selection& get_selection () const = 0; virtual bool get_selection_extents (samplepos_t &start, samplepos_t &end) const = 0; @@ -354,7 +358,7 @@ public: virtual void toggle_meter_updating() = 0; virtual void split_regions_at (Temporal::timepos_t const &, RegionSelection&) = 0; virtual void split_region_at_points (boost::shared_ptr, ARDOUR::AnalysisFeatureList&, bool can_ferret, bool select_new = false) = 0; - virtual void mouse_add_new_marker (Temporal::timepos_t const & where, bool is_cd=false) = 0; + virtual void mouse_add_new_marker (Temporal::timepos_t where, bool is_cd=false) = 0; virtual void foreach_time_axis_view (sigc::slot) = 0; virtual void add_to_idle_resize (TimeAxisView*, int32_t) = 0; virtual Temporal::timecnt_t get_nudge_distance (Temporal::timepos_t const & pos, Temporal::timecnt_t& next) = 0; @@ -512,8 +516,8 @@ public: virtual void build_region_boundary_cache () = 0; virtual void mark_region_boundary_cache_dirty () = 0; - virtual void mouse_add_new_tempo_event (samplepos_t where) = 0; - virtual void mouse_add_new_meter_event (samplepos_t where) = 0; + virtual void mouse_add_new_tempo_event (Temporal::timepos_t where) = 0; + virtual void mouse_add_new_meter_event (Temporal::timepos_t where) = 0; virtual void edit_tempo_section (ARDOUR::TempoSection*) = 0; virtual void edit_meter_section (ARDOUR::MeterSection*) = 0; diff --git a/gtk2_ardour/region_editor.cc b/gtk2_ardour/region_editor.cc index e5a63c08a3..b9dc925387 100644 --- a/gtk2_ardour/region_editor.cc +++ b/gtk2_ardour/region_editor.cc @@ -107,7 +107,7 @@ RegionEditor::RegionEditor (Session* s, boost::shared_ptr r) start_label.set_text (_("File start:")); _sources_label.set_name ("RegionEditorLabel"); - if (_region->n_channels() > 1) { + if (_region->sources().size() > 1) { _sources_label.set_text (_("Sources:")); } else { _sources_label.set_text (_("Source:")); @@ -174,7 +174,7 @@ RegionEditor::RegionEditor (Session* s, boost::shared_ptr r) set_title (string_compose (_("Region '%1'"), _region->name())); - for (uint32_t i = 0; i < _region->n_channels(); ++i) { + for (uint32_t i = 0; i < _region->sources().size(); ++i) { _sources.append_text (_region->source(i)->name()); } @@ -321,13 +321,13 @@ RegionEditor::end_clock_changed () PublicEditor::instance().commit_reversible_command (); } - end_clock.set (_region->position() + _region->length() - 1, true); + end_clock.set (_region->nt_last(), true); } void RegionEditor::length_clock_changed () { - samplecnt_t samples = length_clock.current_time(); + timecnt_t len = length_clock.current_duration(); bool in_command = false; boost::shared_ptr pl = _region->playlist(); @@ -336,7 +336,7 @@ RegionEditor::length_clock_changed () in_command = true; _region->clear_changes (); - _region->trim_end (_region->position() + samples - 1); + _region->trim_end (_region->nt_position() + len.decrement()); _session->add_command(new StatefulDiffCommand (_region)); } @@ -344,7 +344,7 @@ RegionEditor::length_clock_changed () PublicEditor::instance().commit_reversible_command (); } - length_clock.set (_region->length()); + length_clock.set_duration (_region->nt_length()); } void @@ -369,33 +369,33 @@ void RegionEditor::bounds_changed (const PropertyChange& what_changed) { if (what_changed.contains (ARDOUR::Properties::position) && what_changed.contains (ARDOUR::Properties::length)) { - position_clock.set (_region->position(), true); - end_clock.set (_region->position() + _region->length() - 1, true); - length_clock.set (_region->length(), true); + position_clock.set (_region->nt_position(), true); + end_clock.set (_region->nt_last(), true); + length_clock.set_duration (_region->nt_length(), true); } else if (what_changed.contains (ARDOUR::Properties::position)) { - position_clock.set (_region->position(), true); - end_clock.set (_region->position() + _region->length() - 1, true); + position_clock.set (_region->nt_position(), true); + end_clock.set (_region->nt_last(), true); } else if (what_changed.contains (ARDOUR::Properties::length)) { - end_clock.set (_region->position() + _region->length() - 1, true); - length_clock.set (_region->length(), true); + end_clock.set (_region->nt_last(), true); + length_clock.set_duration (_region->nt_length(), true); } if (what_changed.contains (ARDOUR::Properties::sync_position) || what_changed.contains (ARDOUR::Properties::position)) { int dir; - sampleoffset_t off = _region->sync_offset (dir); + timecnt_t off = _region->sync_offset (dir); if (dir == -1) { off = -off; } if (what_changed.contains (ARDOUR::Properties::sync_position)) { - sync_offset_relative_clock.set (off, true); + sync_offset_relative_clock.set_duration (off, true); } - sync_offset_absolute_clock.set (off + _region->position (), true); + sync_offset_absolute_clock (_region->nt_position () + off, true); } if (what_changed.contains (ARDOUR::Properties::start)) { - start_clock.set (_region->start(), true); + start_clock.set (_region->nt_start(), true); } } diff --git a/gtk2_ardour/sfdb_ui.cc b/gtk2_ardour/sfdb_ui.cc index 1210ba6076..36e939ce1e 100644 --- a/gtk2_ardour/sfdb_ui.cc +++ b/gtk2_ardour/sfdb_ui.cc @@ -209,6 +209,7 @@ SoundFileBox::SoundFileBox (bool /*persistent*/) table.attach (timecode_clock, 1, 2, 5, 6, FILL, FILL); table.attach (tempomap_value, 1, 2, 6, 7, FILL, FILL); + length_clock.set_is_duration (true, timepos_t()); length_clock.set_mode (ARDOUR_UI::instance()->primary_clock->mode()); timecode_clock.set_mode (AudioClock::Timecode); @@ -342,7 +343,7 @@ SoundFileBox::setup_labels (const string& filename) format_text.set_text ("MIDI"); samplerate_value.set_text ("-"); tags_entry.get_buffer()->set_text (""); - timecode_clock.set (0); + timecode_clock.set (timepos_t ()); tags_entry.set_sensitive (false); if (ms) { @@ -355,7 +356,7 @@ SoundFileBox::setup_labels (const string& filename) channels_value.set_text (to_string(ms->num_tracks())); } } - length_clock.set (ms->length(ms->natural_position())); + length_clock.set_duration (timecnt_t (0)); switch (ms->num_tempos()) { case 0: tempomap_value.set_text (_("No tempo data")); @@ -376,7 +377,7 @@ SoundFileBox::setup_labels (const string& filename) } } else { channels_value.set_text (""); - length_clock.set (0); + length_clock.set (timepos_t()); tempomap_value.set_text (_("No tempo data")); } @@ -397,8 +398,8 @@ SoundFileBox::setup_labels (const string& filename) samplerate_value.set_text (""); tags_entry.get_buffer()->set_text (""); - length_clock.set (0); - timecode_clock.set (0); + length_clock.set (timepos_t()); + timecode_clock.set (timepos_t()); tags_entry.set_sensitive (false); play_btn.set_sensitive (false); @@ -429,8 +430,9 @@ SoundFileBox::setup_labels (const string& filename) samplecnt_t const nfr = _session ? _session->nominal_sample_rate() : 25; double src_coef = (double) nfr / sf_info.samplerate; - length_clock.set (sf_info.length * src_coef + 0.5, true); - timecode_clock.set (sf_info.timecode * src_coef + 0.5, true); + length_clock.set_is_duration (true, timepos_t()); + length_clock.set_duration (timecnt_t (samplecnt_t (llrint (sf_info.length * src_coef + 0.5))), true); + timecode_clock.set (timepos_t (samplepos_t (llrint (sf_info.timecode * src_coef + 0.5))), true); // this is a hack that is fixed in trunk, i think (august 26th, 2007) @@ -510,7 +512,7 @@ SoundFileBox::audition () PropertyList plist; plist.add (ARDOUR::Properties::start, 0); - plist.add (ARDOUR::Properties::length, ms->length(ms->natural_position())); + plist.add (ARDOUR::Properties::length, ms->length()); plist.add (ARDOUR::Properties::name, rname); plist.add (ARDOUR::Properties::layer, 0); @@ -559,28 +561,29 @@ SoundFileBox::audition () PropertyList plist; plist.add (ARDOUR::Properties::start, 0); - plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->natural_position())); + plist.add (ARDOUR::Properties::length, srclist[0]->length()); plist.add (ARDOUR::Properties::name, rname); plist.add (ARDOUR::Properties::layer, 0); r = boost::dynamic_pointer_cast (RegionFactory::create (srclist, plist, false)); } - sampleoffset_t audition_position = 0; - switch(_import_position) { + timepos_t audition_position; + + switch (_import_position) { case ImportAtTimestamp: - audition_position = 0; break; case ImportAtPlayhead: - audition_position = _session->transport_sample(); + audition_position = timepos_t (_session->transport_sample()); break; case ImportAtStart: - audition_position = _session->current_start_sample(); + audition_position = timepos_t (_session->current_start_sample()); break; case ImportAtEditPoint: audition_position = PublicEditor::instance().get_preferred_edit_position (); break; } + r->set_position(audition_position); _session->audition_region(r); @@ -2074,7 +2077,7 @@ SoundFileOmega::do_something (int action) ImportMode mode = get_mode (); ImportDisposition chns = get_channel_disposition (); PluginInfoPtr instrument = instrument_combo.selected_instrument(); - samplepos_t where; + timepos_t where; MidiTrackNameSource mts = get_midi_track_name_source (); MidiTempoMapDisposition mtd = (get_use_smf_tempo_map () ? SMFTempoUse : SMFTempoIgnore); bool with_midi_markers = get_use_smf_markers (); @@ -2084,13 +2087,13 @@ SoundFileOmega::do_something (int action) where = PublicEditor::instance().get_preferred_edit_position (); break; case ImportAtTimestamp: - where = -1; + where = timepos_t::max (Temporal::AudioTime); break; case ImportAtPlayhead: - where = _session->transport_sample(); + where = timepos_t (_session->transport_sample()); break; case ImportAtStart: - where = _session->current_start_sample(); + where = timepos_t (_session->current_start_sample()); break; } diff --git a/gtk2_ardour/strip_silence_dialog.cc b/gtk2_ardour/strip_silence_dialog.cc index f6be03ca11..e2f0545ebf 100644 --- a/gtk2_ardour/strip_silence_dialog.cc +++ b/gtk2_ardour/strip_silence_dialog.cc @@ -63,6 +63,9 @@ StripSilenceDialog::StripSilenceDialog (Session* s, list const & v) views.push_back (ViewInterval (*r)); } + _minimum_length->set_is_duration (true, views.front().view->region()->nt_position()); + _fade_length->set_is_duration (true, views.front().view->region()->nt_position()); + Gtk::HBox* hbox = Gtk::manage (new Gtk::HBox); Gtk::Table* table = Gtk::manage (new Gtk::Table (3, 3)); @@ -95,7 +98,7 @@ StripSilenceDialog::StripSilenceDialog (Session* s, list const & v) _minimum_length->set_session (s); _minimum_length->set_mode (AudioClock::Samples); - _minimum_length->set (_minimum_length_value, true); + _minimum_length->set_duration (timecnt_t (_minimum_length_value), true); table->attach (*Gtk::manage (new Gtk::Label (_("Fade length"), 1, 0.5)), 0, 1, n, n + 1, Gtk::FILL); table->attach (*_fade_length, 1, 2, n, n + 1, Gtk::FILL); @@ -103,7 +106,8 @@ StripSilenceDialog::StripSilenceDialog (Session* s, list const & v) _fade_length->set_session (s); _fade_length->set_mode (AudioClock::Samples); - _fade_length->set (_fade_length_value, true); + _fade_length->set_is_duration (true); + _fade_length->set_duration (timecnt_t (_fade_length_value), true); hbox->pack_start (*table); @@ -341,13 +345,13 @@ StripSilenceDialog::threshold_changed () samplecnt_t StripSilenceDialog::minimum_length () const { - return std::max((samplecnt_t)1, _minimum_length->current_duration (views.front().view->region()->position())); + return std::max((samplecnt_t)1, _minimum_length->current_duration (views.front().view->region()->nt_position()).samples()); } samplecnt_t StripSilenceDialog::fade_length () const { - return std::max((samplecnt_t)0, _fade_length->current_duration (views.front().view->region()->position())); + return std::max((samplecnt_t)0, _fade_length->current_duration (views.front().view->region()->nt_position()).samples()); } void