another day or two's work on timeline type conversion

This commit is contained in:
Paul Davis 2020-10-04 22:52:17 -06:00
parent 04e8dbb342
commit 9d69fa3820
27 changed files with 378 additions and 351 deletions

View file

@ -176,19 +176,21 @@ ARDOUR_UI::set_flat_buttons ()
void 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()) { switch (UIConfiguration::instance().get_primary_clock_delta_mode()) {
case NoDelta: case NoDelta:
primary_clock->set (pos); primary_clock->set (pos);
break; break;
case DeltaEditPoint: 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; break;
case DeltaOriginMarker: case DeltaOriginMarker:
{ {
Location* loc = _session->locations()->clock_origin_location (); 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; break;
} }
@ -198,12 +200,12 @@ ARDOUR_UI::update_transport_clocks (samplepos_t pos)
secondary_clock->set (pos); secondary_clock->set (pos);
break; break;
case DeltaEditPoint: 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; break;
case DeltaOriginMarker: case DeltaOriginMarker:
{ {
Location* loc = _session->locations()->clock_origin_location (); 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; break;
} }
@ -213,7 +215,7 @@ ARDOUR_UI::update_transport_clocks (samplepos_t pos)
} }
if (!editor->preview_video_drag_active ()) { 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);
} }
} }

View file

@ -50,6 +50,8 @@
#include "ardour/parameter_types.h" #include "ardour/parameter_types.h"
#include "ardour/tempo.h" #include "ardour/tempo.h"
#include "temporal/range.h"
#include "evoral/Curve.h" #include "evoral/Curve.h"
#include "canvas/debug.h" #include "canvas/debug.h"
@ -78,7 +80,7 @@ using namespace Editing;
#define TIME_TO_SAMPLES(x) (_distance_measure (x, Temporal::AudioTime)) #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. /** @param converter A TimeConverter whose origin_b is the start time of the AutomationList in session samples.
* This will not be deleted by AutomationLine. * This will not be deleted by AutomationLine.
@ -88,7 +90,7 @@ AutomationLine::AutomationLine (const string& name,
ArdourCanvas::Item& parent, ArdourCanvas::Item& parent,
boost::shared_ptr<AutomationList> al, boost::shared_ptr<AutomationList> al,
const ParameterDescriptor& desc, const ParameterDescriptor& desc,
DistanceMeasure const & m) Temporal::DistanceMeasure const & m)
: trackview (tv) : trackview (tv)
, _name (name) , _name (name)
, alist (al) , alist (al)
@ -99,12 +101,6 @@ AutomationLine::AutomationLine (const string& name,
, _desc (desc) , _desc (desc)
, _distance_measure (m) , _distance_measure (m)
{ {
if (converter) {
_our_time_converter = false;
} else {
_our_time_converter = true;
}
_visible = Line; _visible = Line;
update_pending = false; update_pending = false;
@ -141,10 +137,6 @@ AutomationLine::~AutomationLine ()
delete *i; delete *i;
} }
control_points.clear (); control_points.clear ();
if (_our_time_converter) {
delete _time_converter;
}
} }
bool bool
@ -302,13 +294,11 @@ AutomationLine::modify_point_y (ControlPoint& cp, double y)
y = min (1.0, y); y = min (1.0, y);
y = _height - (y * _height); 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().begin_reversible_command (_("automation event move"));
trackview.editor().session()->add_command ( trackview.editor().session()->add_command (
new MementoCommand<AutomationList> (memento_command_binder(), &get_state(), 0)); new MementoCommand<AutomationList> (memento_command_binder(), &get_state(), 0));
cp.move_to (x, y, ControlPoint::Full); cp.move_to (cp.get_x(), y, ControlPoint::Full);
alist->freeze (); alist->freeze ();
sync_model_with_view_point (cp); 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 */ /* 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))) { if (view_x != trackview.editor().time_to_pixel_unrounded (model_x.earlier (_offset))) {
/* convert from view coordinates, via pixels->samples->timepos_t /* 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); 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) */ /* convert back from model to view y for clamping position (for integer/boolean/etc) */
model_to_view_coord_y (view_y); 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. * @param result Filled in with selectable things; in this case, ControlPoints.
*/ */
void void
AutomationLine::get_selectables (samplepos_t start, samplepos_t end, double botfrac, double topfrac, list<Selectable*>& results) AutomationLine::get_selectables (timepos_t const & start, timepos_t const & end, double botfrac, double topfrac, list<Selectable*>& results)
{ {
/* convert fractions to display coordinates with 0 at the top of the track */ /* convert fractions to display coordinates with 0 at the top of the track */
double const bot_track = (1 - topfrac) * trackview.current_height (); double const bot_track = (1 - topfrac) * trackview.current_height ();
double const top_track = (1 - botfrac) * trackview.current_height (); double const top_track = (1 - botfrac) * trackview.current_height ();
for (vector<ControlPoint*>::iterator i = control_points.begin(); i != control_points.end(); ++i) { for (vector<ControlPoint*>::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 timepos_t const session_samples_when = timepos_t (session_sample_position ((*i)->model()));
(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 ();
if (session_samples_when >= start && session_samples_when <= end && (*i)->get_y() >= bot_track && (*i)->get_y() <= top_track) { if (session_samples_when >= start && session_samples_when <= end && (*i)->get_y() >= bot_track && (*i)->get_y() <= top_track) {
results.push_back (*i); 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) { for (AutomationList::iterator ai = e.begin(); ai != e.end(); ++ai, ++pi) {
double tx = (*ai)->when;
double ty = (*ai)->value; double ty = (*ai)->value;
/* convert from model coordinates to canonical view coordinates */ /* 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\""), warning << string_compose (_("Ignoring illegal points on AutomationLine \"%1\""),
_name) << endmsg; _name) << endmsg;
continue; continue;
} }
if (tx >= max_samplepos || tx < 0 || tx >= _maximum_time) { if (tx >= timepos_t::max (tx.time_domain()) || tx.negative() || tx >= _maximum_time) {
continue; continue;
} }
@ -1015,7 +999,7 @@ AutomationLine::reset_callback (const Evoral::ControlList& events)
* zoom and scroll into account). * 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 /* convert from canonical view height (0..1.0) to actual
* height coordinates (using X11's top-left rooted system) * height coordinates (using X11's top-left rooted system)
@ -1023,7 +1007,7 @@ AutomationLine::reset_callback (const Evoral::ControlList& events)
ty = _height - (ty * _height); 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++; vp++;
} }
@ -1187,18 +1171,20 @@ AutomationLine::set_state (const XMLNode &node, int version)
Temporal::timepos_t Temporal::timepos_t
AutomationLine::view_to_model_coord (double x, double& y) const 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); view_to_model_coord_y (y);
Temporal::timepos_t w; 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: case Temporal::AudioTime:
return timepos_t (samplepos_t (x)); return timepos_t (samplepos_t (x));
break; break;
case Temporal::BeatTime: case Temporal::BeatTime:
return timepos_t (Beats::from_double (x)); return timepos_t (Temporal::Beats::from_double (x));
break; break;
default: default:
/*NOTREACHED*/ /*NOTREACHED*/
@ -1275,12 +1261,12 @@ AutomationLine::model_to_view_coord_y (double& y) const
y = _desc.to_interface (y); y = _desc.to_interface (y);
} }
double timepos_t
AutomationLine::model_to_view_coord (Evoral::ControlEvent const & ev, double& y) const 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); 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 */ /** 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 */ /** @return min and max x positions of points that are in the list, in session samples */
pair<samplepos_t, samplepos_t> pair<timepos_t, timepos_t>
AutomationLine::get_point_x_range () const AutomationLine::get_point_x_range () const
{ {
pair<samplepos_t, samplepos_t> r (max_samplepos, 0); pair<timepos_t, timepos_t> 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) { for (AutomationList::const_iterator i = the_list()->begin(); i != the_list()->end(); ++i) {
r.first = min (r.first, session_position (i)); r.first = min (r.first, session_position (i));
@ -1389,17 +1375,17 @@ AutomationLine::get_point_x_range () const
samplepos_t samplepos_t
AutomationLine::session_sample_position (AutomationList::const_iterator p) const 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 timepos_t
AutomationLine::session_position (AutomationList::const_iterator p) const 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 void
AutomationLine::set_offset (samplepos_t off) AutomationLine::set_offset (timecnt_t const & off)
{ {
if (_offset == off) { if (_offset == off) {
return; return;

View file

@ -71,7 +71,8 @@ public:
TimeAxisView& tv, TimeAxisView& tv,
ArdourCanvas::Item& parent, ArdourCanvas::Item& parent,
boost::shared_ptr<ARDOUR::AutomationList> al, boost::shared_ptr<ARDOUR::AutomationList> al,
const ARDOUR::ParameterDescriptor& desc); const ARDOUR::ParameterDescriptor& desc,
Temporal::DistanceMeasure const &);
virtual ~AutomationLine (); virtual ~AutomationLine ();
@ -125,7 +126,7 @@ public:
std::string fraction_to_string (double) const; std::string fraction_to_string (double) const;
std::string delta_to_string (double) const; std::string delta_to_string (double) const;
double string_to_fraction (std::string const &) 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; void view_to_model_coord_y (double &) const;
Temporal::timepos_t model_to_view_coord (Evoral::ControlEvent const &, double& y) const; Temporal::timepos_t model_to_view_coord (Evoral::ControlEvent const &, double& y) const;
void model_to_view_coord_y (double &) const; void model_to_view_coord_y (double &) const;
@ -150,7 +151,7 @@ public:
virtual MementoCommandBinder<ARDOUR::AutomationList>* memento_command_binder (); virtual MementoCommandBinder<ARDOUR::AutomationList>* memento_command_binder ();
std::pair<ARDOUR::samplepos_t, ARDOUR::samplepos_t> get_point_x_range () const; std::pair<Temporal::timepos_t, Temporal::timepos_t> get_point_x_range () const;
void set_maximum_time (Temporal::timepos_t const &); void set_maximum_time (Temporal::timepos_t const &);
Temporal::timepos_t maximum_time () const { Temporal::timepos_t maximum_time () const {

View file

@ -1,4 +1,4 @@
/* n/*
* Copyright (C) 2007-2015 David Robillard <d@drobilla.net> * Copyright (C) 2007-2015 David Robillard <d@drobilla.net>
* Copyright (C) 2008-2017 Paul Davis <paul@linuxaudiosystems.com> * Copyright (C) 2008-2017 Paul Davis <paul@linuxaudiosystems.com>
* Copyright (C) 2009-2011 Carl Hetherington <carl@carlh.net> * Copyright (C) 2009-2011 Carl Hetherington <carl@carlh.net>
@ -208,8 +208,7 @@ AutomationRegionView::add_automation_event (GdkEvent *, timepos_t const & w, dou
XMLNode& before = _line->the_list()->get_state(); XMLNode& before = _line->the_list()->get_state();
<<<<<<< HEAD n if (_line->the_list()->editor_add (when, y, with_guard_points)) {
if (_line->the_list()->editor_add (when_d, y, with_guard_points)) {
if (ac->automation_state () == ARDOUR::Off) { if (ac->automation_state () == ARDOUR::Off) {
ac->set_automation_state (ARDOUR::Play); 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); 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")); view->editor().begin_reversible_command (_("add automation event"));
XMLNode& after = _line->the_list()->get_state(); XMLNode& after = _line->the_list()->get_state();

View file

@ -41,7 +41,7 @@
#include "pbd/unwind.h" #include "pbd/unwind.h"
#include "ardour/automation_control.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/event_type_map.h"
#include "ardour/parameter_types.h" #include "ardour/parameter_types.h"
#include "ardour/profile.h" #include "ardour/profile.h"
@ -299,13 +299,15 @@ AutomationTimeAxisView::AutomationTimeAxisView (
assert (_control); assert (_control);
#warning NUTEMPO new tempo map API required
#if 0
boost::shared_ptr<AutomationLine> line ( boost::shared_ptr<AutomationLine> line (
new AutomationLine ( new AutomationLine (
ARDOUR::EventTypeMap::instance().to_symbol(_parameter), ARDOUR::EventTypeMap::instance().to_symbol(_parameter),
*this, *this,
*_canvas_display, *_canvas_display,
_control->alist(), _control->alist(),
_control->desc() _control->desc(),
Temporal::DistanceMeasure (_session->tempo_map(), timepos_t()) /* default distance measure, origin at absolute zero */ 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->set_fill (true);
line->queue_reset (); line->queue_reset ();
add_line (line); add_line (line);
#endif 0
} }
/* make sure labels etc. are correct */ /* make sure labels etc. are correct */
@ -768,14 +771,14 @@ AutomationTimeAxisView::add_automation_event (GdkEvent* event, samplepos_t sampl
return; return;
} }
MusicSample when (sample, 0); timepos_t when (sample);
_editor.snap_to_with_modifier (when, event); _editor.snap_to_with_modifier (when, event);
if (UIConfiguration::instance().get_new_automation_points_on_lane()) { if (UIConfiguration::instance().get_new_automation_points_on_lane()) {
if (_control->list()->size () == 0) { if (_control->list()->size () == 0) {
y = _control->get_value (); y = _control->get_value ();
} else { } else {
y = _control->list()->eval (when.sample); y = _control->list()->eval (when);
} }
} else { } else {
double x = 0; double x = 0;
@ -789,7 +792,7 @@ AutomationTimeAxisView::add_automation_event (GdkEvent* event, samplepos_t sampl
XMLNode& before = list->get_state(); XMLNode& before = list->get_state();
std::list<Selectable*> results; std::list<Selectable*> 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) { if (_control->automation_state () == ARDOUR::Off) {
_control->set_automation_state (ARDOUR::Play); _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")); _editor.begin_reversible_command (_("add automation event"));
_session->add_command (new MementoCommand<ARDOUR::AutomationList> (*list.get (), &before, &after)); _session->add_command (new MementoCommand<ARDOUR::AutomationList> (*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.get_selection ().set (results);
_editor.commit_reversible_command (); _editor.commit_reversible_command ();
@ -811,7 +814,7 @@ AutomationTimeAxisView::add_automation_event (GdkEvent* event, samplepos_t sampl
} }
bool 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) { if (_line) {
return paste_one (pos, ctx.count, ctx.times, selection, ctx.counts, ctx.greedy); 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 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<AutomationList> alist(_line->the_list()); boost::shared_ptr<AutomationList> 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::timecnt_t len = (*p)->length();
Temporal::timepos_t tpos (pos); Temporal::timepos_t tpos (pos);
assert (line()->the_list()->time_style() != Temporal::BarTime); switch (line()->the_list()->time_domain()) {
switch (line()->the_list()->time_style()) {
case Temporal::BeatTime: case Temporal::BeatTime:
tpos += _editor.get_paste_offset (pos, paste_count > 0 ? 1 : 0, len); tpos += _editor.get_paste_offset (pos, paste_count > 0 ? 1 : 0, len);
break; break;
case Temporal::AudioTime: case Temporal::AudioTime:
tpos += _editor.get_paste_offset (pos, paste_count, len); tpos += _editor.get_paste_offset (pos, paste_count, len);
break; break;
case Temporal::BarTime:
/*NOTREACHED*/
break;
} }
/* convert position to model's unit and position */ /* convert position to model's unit and position */
Temporal::DistanceMeasure const & dm (_line->distance_measure()); 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(); 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<AutomationList>(*alist.get(), &before, &alist->get_state())); _session->add_command (new MementoCommand<AutomationList>(*alist.get(), &before, &alist->get_state()));
return true; return true;
} }
void void
AutomationTimeAxisView::get_selectables (samplepos_t start, samplepos_t end, double top, double bot, list<Selectable*>& results, bool /*within*/) AutomationTimeAxisView::get_selectables (timepos_t const & start, timepos_t const & end, double top, double bot, list<Selectable*>& results, bool /*within*/)
{ {
if (!_line && !_view) { if (!_line && !_view) {
return; return;
@ -1148,9 +1147,9 @@ AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& sel
XMLNode &before = alist->get_state(); XMLNode &before = alist->get_state();
/* convert time selection to automation list model coordinates */ /* convert time selection to automation list model coordinates */
const Evoral::TimeConverter<double, ARDOUR::samplepos_t>& tc = line.time_converter (); /* convert time selection to automation list model coordinates */
double const start = tc.from (selection.time.front().start - tc.origin_b ()); timepos_t start = selection.time.front().start().earlier (line.distance_measure().origin());
double const end = tc.from (selection.time.front().end - tc.origin_b ()); timepos_t end = selection.time.front().end().earlier (line.distance_measure().origin());
switch (op) { switch (op) {
case Delete: case Delete:
@ -1181,9 +1180,9 @@ AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& sel
if (what_we_got) { if (what_we_got) {
for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) { 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; double val = (*x)->value;
line.model_to_view_coord (when, val); line.model_to_view_coord (**x, val);
(*x)->when = when; (*x)->when = when;
(*x)->value = val; (*x)->value = val;
} }

View file

@ -187,7 +187,7 @@ protected:
void build_display_menu (); void build_display_menu ();
void cut_copy_clear_one (AutomationLine&, Selection&, Editing::CutCopyOp); 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 route_going_away ();
void set_automation_state (ARDOUR::AutoState); void set_automation_state (ARDOUR::AutoState);

View file

@ -36,7 +36,7 @@ curvetest (string filename)
stringstream line; stringstream line;
//Evoral::Parameter param(GainAutomation, -1.0, +1.0, 0.0); //Evoral::Parameter param(GainAutomation, -1.0, +1.0, 0.0);
Evoral::Parameter param(GainAutomation); Evoral::Parameter param(GainAutomation);
AutomationList al (param); AutomationList al (param, Temporal::AudioTime);
double minx = DBL_MAX; double minx = DBL_MAX;
double maxx = DBL_MIN; double maxx = DBL_MIN;
@ -58,13 +58,13 @@ curvetest (string filename)
maxx = x; maxx = x;
} }
al.add (x, y); al.add (Temporal::timepos_t (x), y);
} }
float foo[1024]; 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) { for (int i = 0; i < 1024; ++i) {
cout << minx + (((double) i / 1024.0) * (maxx - minx)) << ' ' << foo[i] << endl; cout << minx + (((double) i / 1024.0) * (maxx - minx)) << ' ' << foo[i] << endl;

View file

@ -31,6 +31,7 @@
#include "pbd/i18n.h" #include "pbd/i18n.h"
using namespace std; using namespace std;
using namespace Temporal;
using namespace Gtk; using namespace Gtk;
using namespace Gtkmm2ext; using namespace Gtkmm2ext;
@ -95,8 +96,11 @@ EditNoteDialog::EditNoteDialog (MidiRegionView* rv, set<NoteBase*> n)
_time_clock.set_session (_region_view->get_time_axis_view().session ()); _time_clock.set_session (_region_view->get_time_axis_view().session ());
_time_clock.set_mode (AudioClock::BBT); _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"))); l = manage (left_aligned_label (_("Length")));
table->attach (*l, 0, 1, r, r + 1); table->attach (*l, 0, 1, r, r + 1);
@ -106,10 +110,15 @@ EditNoteDialog::EditNoteDialog (MidiRegionView* rv, set<NoteBase*> n)
_length_clock.set_session (_region_view->get_time_axis_view().session ()); _length_clock.set_session (_region_view->get_time_axis_view().session ());
_length_clock.set_mode (AudioClock::BBT); _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(), dur = _region_view->region_relative_distance (timecnt_t ((*_events.begin())->note()->end_time (), timepos_t()), BarTime);
true, pos = _region_view->region()->nt_position() + dur;
_region_view->region_relative_time_converter().to ((*_events.begin())->note()->time ()) + _region_view->region()->position()); 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 */ /* 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()); timepos_t source_start = _region_view->region()->nt_position().earlier (_region_view->region()->nt_start());
Temporal::Beats const t = _region_view->source_relative_time_converter().from (region_samples);
/* 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 ()) { if (!_time_all.get_sensitive() || _time_all.get_active ()) {
for (set<NoteBase*>::iterator i = _events.begin(); i != _events.end(); ++i) { for (set<NoteBase*>::iterator i = _events.begin(); i != _events.end(); ++i) {
if (t != (*i)->note()->time()) { if (new_note_time_source_relative_beats != (*i)->note()->time()) {
_region_view->change_note_time (*i, t); _region_view->change_note_time (*i, new_note_time_source_relative_beats);
had_change = true; had_change = true;
} }
} }
} }
if (!_length_all.get_sensitive() || _length_all.get_active ()) { 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<NoteBase*>::iterator i = _events.begin(); i != _events.end(); ++i) { for (set<NoteBase*>::iterator i = _events.begin(); i != _events.end(); ++i) {
samplepos_t const note_end_sample = region_samples + _length_clock.current_duration (_time_clock.current_time()); Beats const new_note_length_beats = new_note_end_source_relative_beats - (*i)->note()->time();
Temporal::Beats const d = _region_view->source_relative_time_converter().from (note_end_sample) - (*i)->note()->time(); if (new_note_length_beats != (*i)->note()->length()) {
if (d != (*i)->note()->length()) { _region_view->change_note_length (*i, new_note_length_beats);
_region_view->change_note_length (*i, d);
had_change = true; had_change = true;
} }
} }
} }
if (!had_change) { if (!had_change) {

View file

@ -6383,3 +6383,27 @@ Editor::use_own_window (bool and_fill_it)
return win; 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());
}

View file

@ -262,6 +262,12 @@ public:
return sample / (double) samples_per_pixel; 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 */
Selection& get_selection() const { return *selection; } Selection& get_selection() const { return *selection; }
@ -569,7 +575,7 @@ public:
void metric_get_minsec (std::vector<ArdourCanvas::Ruler::Mark>&, gdouble, gdouble, gint); void metric_get_minsec (std::vector<ArdourCanvas::Ruler::Mark>&, gdouble, gdouble, gint);
/* editing operations that need to be public */ /* 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_regions_at (Temporal::timepos_t const & , RegionSelection&);
void split_region_at_points (boost::shared_ptr<ARDOUR::Region>, ARDOUR::AnalysisFeatureList&, bool can_ferret, bool select_new = false); 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 (Temporal::timepos_t const &); 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_brush_insert_region (RegionView*, samplepos_t pos);
void mouse_add_new_tempo_event (samplepos_t where); void mouse_add_new_tempo_event (Temporal::timepos_t where);
void mouse_add_new_meter_event (samplepos_t where); void mouse_add_new_meter_event (Temporal::timepos_t where);
void edit_tempo_section (ARDOUR::TempoSection*); void edit_tempo_section (ARDOUR::TempoSection*);
void edit_meter_section (ARDOUR::MeterSection*); void edit_meter_section (ARDOUR::MeterSection*);
@ -755,9 +761,9 @@ private:
void hide_marker (ArdourCanvas::Item*, GdkEvent*); void hide_marker (ArdourCanvas::Item*, GdkEvent*);
void clear_marker_display (); void clear_marker_display ();
void mouse_add_new_range (samplepos_t); void mouse_add_new_range (Temporal::timepos_t);
void mouse_add_new_loop (samplepos_t); void mouse_add_new_loop (Temporal::timepos_t);
void mouse_add_new_punch (samplepos_t); void mouse_add_new_punch (Temporal::timepos_t);
bool choose_new_marker_name(std::string &name, bool is_range=false); bool choose_new_marker_name(std::string &name, bool is_range=false);
void update_cd_marker_display (); void update_cd_marker_display ();
void ensure_cd_marker_updated (LocationMarkers* lam, ARDOUR::Location* location); 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 compute_fixed_ruler_scale (); //calculates the RulerScale of the fixed rulers
void update_fixed_rulers (); void update_fixed_rulers ();
void update_tempo_based_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 update_ruler_visibility ();
void toggle_ruler_visibility (); void toggle_ruler_visibility ();
void ruler_toggled (int); void ruler_toggled (int);

View file

@ -668,7 +668,7 @@ Editor::LocationMarkers::setup_lines ()
} }
void 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; string markername;
int flags = (is_cd ? Location::IsCDMarker|Location::IsMark : Location::IsMark); 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 void
Editor::mouse_add_new_loop (samplepos_t where) Editor::mouse_add_new_loop (timepos_t where)
{ {
if (!_session) { if (!_session) {
return; return;
@ -710,13 +710,13 @@ Editor::mouse_add_new_loop (samplepos_t where)
it's reasonably easy to manipulate after creation. 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 void
Editor::mouse_add_new_punch (samplepos_t where) Editor::mouse_add_new_punch (timepos_t where)
{ {
if (!_session) { if (!_session) {
return; return;
@ -726,13 +726,13 @@ Editor::mouse_add_new_punch (samplepos_t where)
it's reasonably easy to manipulate after creation. 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 void
Editor::mouse_add_new_range (samplepos_t where) Editor::mouse_add_new_range (timepos_t where)
{ {
if (!_session) { if (!_session) {
return; return;
@ -742,7 +742,7 @@ Editor::mouse_add_new_range (samplepos_t where)
it's reasonably easy to manipulate after creation. 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; string name;
_session->locations()->next_available_name (name, _("range")); _session->locations()->next_available_name (name, _("range"));

View file

@ -1626,7 +1626,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT
case SamplesRulerItem: case SamplesRulerItem:
case MinsecRulerItem: case MinsecRulerItem:
case BBTRulerItem: case BBTRulerItem:
popup_ruler_menu (where.sample, item_type); popup_ruler_menu (timepos_t (where), item_type);
break; break;
case MarkerItem: case MarkerItem:

View file

@ -1805,7 +1805,7 @@ EditorRoutes::solo_changed_so_update_mute ()
void void
EditorRoutes::show_tracks_with_regions_at_playhead () EditorRoutes::show_tracks_with_regions_at_playhead ()
{ {
boost::shared_ptr<RouteList> const r = _session->get_routes_with_regions_at (_session->transport_sample ()); boost::shared_ptr<RouteList> const r = _session->get_routes_with_regions_at (timepos_t (_session->transport_sample ()));
set<TimeAxisView*> show; set<TimeAxisView*> show;
for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) { for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {

View file

@ -201,7 +201,7 @@ Editor::ruler_label_button_release (GdkEventButton* ev)
} }
void void
Editor::popup_ruler_menu (samplepos_t where, ItemType t) Editor::popup_ruler_menu (timepos_t const & where, ItemType t)
{ {
using namespace Menu_Helpers; using namespace Menu_Helpers;

View file

@ -402,15 +402,18 @@ Editor::maybe_draw_grid_lines ()
} }
void void
Editor::mouse_add_new_tempo_event (samplepos_t sample) Editor::mouse_add_new_tempo_event (timepos_t pos)
{ {
if (_session == 0) { if (_session == 0) {
return; return;
} }
#warning NUTEMPO requires new tempo map API
#if 0
TempoMap& map(_session->tempo_map()); TempoMap& map(_session->tempo_map());
begin_reversible_command (_("add tempo mark")); begin_reversible_command (_("add tempo mark"));
const double pulse = map.exact_qn_at_sample (sample, get_grid_music_divisions (0)) / 4.0; const double pulse = map.exact_qn_at_sample (sample, get_grid_music_divisions (0)) / 4.0;
if (pulse > 0.0) { if (pulse > 0.0) {
@ -422,20 +425,21 @@ Editor::mouse_add_new_tempo_event (samplepos_t sample)
_session->add_command(new MementoCommand<TempoMap>(map, &before, &after)); _session->add_command(new MementoCommand<TempoMap>(map, &before, &after));
commit_reversible_command (); commit_reversible_command ();
} }
#endif
//map.dump (cerr); //map.dump (cerr);
} }
void void
Editor::mouse_add_new_meter_event (samplepos_t sample) Editor::mouse_add_new_meter_event (timepos_t pos)
{ {
if (_session == 0) { if (_session == 0) {
return; return;
} }
#warning NUTEMPO requires new tempo map API
#if 0
TempoMap& map(_session->tempo_map()); TempoMap& map(_session->tempo_map());
MeterDialog meter_dialog (map, sample, _("add")); MeterDialog meter_dialog (map, pos, _("add"));
switch (meter_dialog.run ()) { switch (meter_dialog.run ()) {
case RESPONSE_ACCEPT: 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); const double al_sample = map.sample_at_bbt (requested);
begin_reversible_command (_("add meter mark")); begin_reversible_command (_("add meter mark"));
XMLNode &before = map.get_state(); XMLNode &before = map.get_state();
if (meter_dialog.get_lock_style() == MusicTime) { 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<TempoMap>(map, &before, &map.get_state())); _session->add_command(new MementoCommand<TempoMap>(map, &before, &map.get_state()));
commit_reversible_command (); commit_reversible_command ();
#endif
//map.dump (cerr); //map.dump (cerr);
} }

View file

@ -112,7 +112,7 @@ Editor::time_stretch (RegionSelection& regions, float fraction)
stretch.run (*i); stretch.run (*i);
playlist->replace_region (regions.front()->region(), stretch.results[0], playlist->replace_region (regions.front()->region(), stretch.results[0],
regions.front()->region()->position()); regions.front()->region()->nt_position());
midi_playlists_affected.insert (playlist); midi_playlists_affected.insert (playlist);
} }
@ -168,9 +168,9 @@ Editor::time_fx (RegionList& regions, float val, bool pitching)
return 0; return 0;
} }
const samplecnt_t oldlen = (samplecnt_t) (regions.front()->length()); const timecnt_t oldlen = regions.front()->nt_length();
const samplecnt_t newlen = (samplecnt_t) (regions.front()->length() * val); const timecnt_t newlen = regions.front()->nt_length() * val;
const samplecnt_t pos = regions.front()->position (); const timecnt_t pos = regions.front()->nt_position ();
current_timefx = new TimeFXDialog (*this, pitching, oldlen, newlen, pos); current_timefx = new TimeFXDialog (*this, pitching, oldlen, newlen, pos);
current_timefx->regions = regions; current_timefx->regions = regions;

View file

@ -584,7 +584,7 @@ ExportRegionDialog::init_gui ()
void void
ExportRegionDialog::init_components () 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 ()); preset_selector.reset (new ExportPresetSelector ());
timespan_selector.reset (new ExportTimespanSelectorSingle (_session, profile_manager, loc_id)); timespan_selector.reset (new ExportTimespanSelectorSingle (_session, profile_manager, loc_id));

View file

@ -731,7 +731,7 @@ ExportVideoDialog::launch_export ()
end += av_offset; end += av_offset;
} }
else if (insnd_combo.get_active_row_number() == 2) { 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()); end = ARDOUR_UI::instance()->video_timeline->quantify_samples_to_apv(export_range.end_sample());
} }
if (end <= 0) { if (end <= 0) {
@ -954,7 +954,7 @@ ExportVideoDialog::encode_pass (int pass)
duration_s = (double)duration_f / (double)_session->nominal_sample_rate(); duration_s = (double)duration_f / (double)_session->nominal_sample_rate();
} else if (insnd_combo.get_active_row_number() == 2) { } else if (insnd_combo.get_active_row_number() == 2) {
/* selected range */ /* selected range */
duration_s = export_range.length() / (double)_session->nominal_sample_rate(); duration_s = export_range.length_samples() / (double)_session->nominal_sample_rate();
} else { } else {
/* video start to end */ /* video start to end */
samplecnt_t duration_f = ARDOUR_UI::instance()->video_timeline->get_duration(); 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(); start = _session->current_start_sample();
snend = _session->current_end_sample(); snend = _session->current_end_sample();
} else { } else {
start = export_range.start(); start = export_range.start_sample();
snend = export_range.end_sample(); snend = export_range.end_sample();
} }

View file

@ -110,9 +110,6 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Container* parent,
: RegionView (parent, tv, r, spu, basic_color) : RegionView (parent, tv, r, spu, basic_color)
, _current_range_min(0) , _current_range_min(0)
, _current_range_max(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) , _active_notes(0)
, _note_group (new ArdourCanvas::Container (group)) , _note_group (new ArdourCanvas::Container (group))
, _note_diff_command (0) , _note_diff_command (0)
@ -155,9 +152,6 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Container* parent,
: RegionView (parent, tv, r, spu, basic_color, recording, visibility) : RegionView (parent, tv, r, spu, basic_color, recording, visibility)
, _current_range_min(0) , _current_range_min(0)
, _current_range_max(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) , _active_notes(0)
, _note_group (new ArdourCanvas::Container (group)) , _note_group (new ArdourCanvas::Container (group))
, _note_diff_command (0) , _note_diff_command (0)
@ -209,9 +203,6 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other)
, RegionView (other) , RegionView (other)
, _current_range_min(0) , _current_range_min(0)
, _current_range_max(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) , _active_notes(0)
, _note_group (new ArdourCanvas::Container (get_canvas_group())) , _note_group (new ArdourCanvas::Container (get_canvas_group()))
, _note_diff_command (0) , _note_diff_command (0)
@ -238,9 +229,6 @@ MidiRegionView::MidiRegionView (const MidiRegionView& other, boost::shared_ptr<M
: RegionView (other, boost::shared_ptr<Region> (region)) : RegionView (other, boost::shared_ptr<Region> (region))
, _current_range_min(0) , _current_range_min(0)
, _current_range_max(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) , _active_notes(0)
, _note_group (new ArdourCanvas::Container (get_canvas_group())) , _note_group (new ArdourCanvas::Container (get_canvas_group()))
, _note_diff_command (0) , _note_diff_command (0)
@ -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 // 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, shift_snap);
Temporal::Beats beat_time = snap_sample_to_grid_underneath (t, divisions, shift_snap);
const double note = view->y_to_note(y); const double note = view->y_to_note(y);
const uint8_t chan = mtv->get_channel_for_add(); 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) { 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(); p->hide();
} else { } 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->canvas_item()->set_position (ArdourCanvas::Duple (x, 1.0));
p->update_name (); p->update_name ();
@ -1318,7 +1305,7 @@ MidiRegionView::display_sysexes()
for (MidiModel::SysExes::const_iterator i = _model->sysexes().begin(); i != _model->sysexes().end(); ++i) { for (MidiModel::SysExes::const_iterator i = _model->sysexes().begin(); i != _model->sysexes().end(); ++i) {
MidiModel::SysExPtr sysex_ptr = *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 ((*i)->is_spp() || (*i)->is_mtc_quarter() || (*i)->is_mtc_full()) {
if (!display_periodic_messages) { if (!display_periodic_messages) {
@ -1336,7 +1323,7 @@ MidiRegionView::display_sysexes()
} }
string text = str.str(); 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(); double height = midi_stream_view()->contents_height();
@ -1354,7 +1341,7 @@ MidiRegionView::display_sysexes()
} }
// Show unless message is beyond the region bounds // 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(); sysex->hide();
} else { } else {
sysex->show(); sysex->show();
@ -1389,15 +1376,12 @@ MidiRegionView::region_resized (const PropertyChange& what_changed)
RegionView::region_resized(what_changed); // calls RegionView::set_duration() RegionView::region_resized(what_changed); // calls RegionView::set_duration()
if (what_changed.contains (ARDOUR::Properties::position)) { if (what_changed.contains (ARDOUR::Properties::position)) {
_region_relative_time_converter.set_origin_b(_region->position());
_region_relative_time_converter_double.set_origin_b(_region->position());
/* reset_width dependent_items() redisplays model */ /* reset_width dependent_items() redisplays model */
} }
if (what_changed.contains (ARDOUR::Properties::start) || if (what_changed.contains (ARDOUR::Properties::start) ||
what_changed.contains (ARDOUR::Properties::position)) { 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*/ /* catch end and start trim so we can update the view*/
if (!what_changed.contains (ARDOUR::Properties::start) && if (!what_changed.contains (ARDOUR::Properties::start) &&
@ -1481,7 +1465,7 @@ MidiRegionView::apply_note_range (uint8_t min, uint8_t max, bool force)
GhostRegion* GhostRegion*
MidiRegionView::add_ghost (TimeAxisView& tv) 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<MidiTimeAxisView*>(&tv); MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*>(&tv);
MidiGhostRegion* ghost; MidiGhostRegion* ghost;
@ -1496,7 +1480,7 @@ MidiRegionView::add_ghost (TimeAxisView& tv)
ghost->set_colors (); ghost->set_colors ();
ghost->set_height (); 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) { for (Events::iterator i = _events.begin(); i != _events.end(); ++i) {
ghost->add_note(i->second); 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()); _active_notes[note]->note()->set_length (end_time - _active_notes[note]->note()->time());
/* End time is relative to the region being recorded. */ /* 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().time_to_pixel (_region->region_beats_to_region_time (end_time)));
_active_notes[note]->set_x1 (trackview.editor().sample_to_pixel(end_time_samples));
_active_notes[note]->set_outline_all (); _active_notes[note]->set_outline_all ();
_active_notes[note] = 0; _active_notes[note] = 0;
} }
@ -1570,7 +1552,7 @@ MidiRegionView::extend_active_notes()
for (unsigned i = 0; i < 128; ++i) { for (unsigned i = 0; i < 128; ++i) {
if (_active_notes[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<NoteType> note, bo
const boost::shared_ptr<ARDOUR::MidiRegion> midi_reg = midi_region(); const boost::shared_ptr<ARDOUR::MidiRegion> midi_reg = midi_region();
/* must compare double explicitly as Beats::operator< rounds to ppqn */ /* must compare double explicitly as Beats::operator< rounds to ppqn */
const bool outside = (note->time() < midi_reg->start_beats() || const bool outside = (timepos_t (note->time()) < _region->nt_start()) || (timepos_t (note->time()) >= _region->nt_start() + _region->nt_length());
note->time() >= midi_reg->start_beats() + midi_reg->length_beats());
visible = (note->note() >= _current_range_min) && visible = (note->note() >= _current_range_min) &&
(note->note() <= _current_range_max); (note->note() <= _current_range_max);
@ -1659,14 +1640,11 @@ MidiRegionView::update_note (NoteBase* note, bool update_ghost_regions)
void void
MidiRegionView::update_sustained (Note* ev, bool update_ghost_regions) MidiRegionView::update_sustained (Note* ev, bool update_ghost_regions)
{ {
TempoMap& map (trackview.session()->tempo_map());
const boost::shared_ptr<ARDOUR::MidiRegion> mr = midi_region(); const boost::shared_ptr<ARDOUR::MidiRegion> mr = midi_region();
boost::shared_ptr<NoteType> note = ev->note(); boost::shared_ptr<NoteType> 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 double x0 = trackview.editor().time_to_pixel (note_start);
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));
double x1; double x1;
const double y0 = 1 + floor(note_to_y(note->note())); const double y0 = 1 + floor(note_to_y(note->note()));
double y1; double y1;
@ -1681,21 +1659,19 @@ MidiRegionView::update_sustained (Note* ev, bool update_ghost_regions)
/* normal note */ /* 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()) { if (note_end > mr->nt_start() + mr->nt_length()) {
note_end_time = mr->start_beats() + mr->length_beats(); 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().time_to_pixel (note_end)) - 1;
x1 = std::max(1., trackview.editor().sample_to_pixel (note_end_samples)) - 1;
} else { } else {
/* nascent note currently being recorded, noteOff has not yet arrived */ /* 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); y1 = y0 + std::max(1., floor(note_height()) - 1);
@ -1735,11 +1711,9 @@ void
MidiRegionView::update_hit (Hit* ev, bool update_ghost_regions) MidiRegionView::update_hit (Hit* ev, bool update_ghost_regions)
{ {
boost::shared_ptr<NoteType> note = ev->note(); boost::shared_ptr<NoteType> 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 double x = trackview.editor().time_to_pixel(note_time);
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 diamond_size = std::max(1., floor(note_height()) - 2.); 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; 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(); const uint32_t base_col = ev->base_color();
ev->set_fill_color(base_col); ev->set_fill_color(base_col);
ev->set_outline_color(ev->calculate_outline(base_col, ev->selected())); ev->set_outline_color(ev->calculate_outline(base_col, ev->selected()));
} }
/** Add a MIDI note to the view (with length). /** 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 */ /* potentially extend region to hold new note */
samplepos_t end_sample = source_beats_to_absolute_samples (new_note->end_time()); timepos_t note_end = _region->source_beats_to_absolute_time (new_note->end_time());
samplepos_t region_end = _region->last_sample(); timepos_t region_end = _region->nt_last();
if (end_sample > region_end) { if (note_end > region_end) {
/* XX sets length in beats from audio space. make musical */ _region->set_length (timecnt_t (note_end.earlier (_region->nt_position()), timepos_t()));
_region->set_length (end_sample - _region->position(), 0);
} }
MidiTimeAxisView* const mtv = dynamic_cast<MidiTimeAxisView*>(&trackview); MidiTimeAxisView* const mtv = dynamic_cast<MidiTimeAxisView*>(&trackview);
@ -1874,8 +1846,8 @@ MidiRegionView::step_sustain (Temporal::Beats beats)
void void
MidiRegionView::add_canvas_patch_change (MidiModel::PatchChangePtr patch) MidiRegionView::add_canvas_patch_change (MidiModel::PatchChangePtr patch)
{ {
samplecnt_t region_samples = source_beats_to_region_samples (patch->time()); timepos_t patch_time = _region->source_beats_to_absolute_time (patch->time());
const double x = trackview.editor().sample_to_pixel (region_samples); const double x = trackview.editor().time_to_pixel (patch_time);
double const height = midi_stream_view()->contents_height(); 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) { if (patch_change->item().width() < _pixel_width) {
// Show unless patch change is beyond the region bounds // 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(); patch_change->hide();
} else { } else {
patch_change->show(); patch_change->show();
@ -2019,19 +1991,17 @@ MidiRegionView::change_patch_change (MidiModel::PatchChangePtr old_change, const
* MidiTimeAxisView::get_channel_for_add()) * MidiTimeAxisView::get_channel_for_add())
*/ */
void void
MidiRegionView::add_patch_change (samplecnt_t t, Evoral::PatchChange<Temporal::Beats> const & patch) MidiRegionView::add_patch_change (timecnt_t const & t, Evoral::PatchChange<Temporal::Beats> const & patch)
{ {
string name = _("add patch change"); string name = _("add patch change");
trackview.editor().begin_reversible_command (name); trackview.editor().begin_reversible_command (name);
MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (name); MidiModel::PatchChangeDiffCommand* c = _model->new_patch_change_diff_command (name);
c->add (MidiModel::PatchChangePtr ( c->add (MidiModel::PatchChangePtr (
new Evoral::PatchChange<Temporal::Beats> ( new Evoral::PatchChange<Temporal::Beats>
absolute_samples_to_source_beats (_region->position() + t), (_region->source_relative_position (_region->nt_position() + t).beats(),
patch.channel(), patch.program(), patch.bank() patch.channel(), patch.program(), patch.bank())));
)
)
);
_model->apply_command (*trackview.session(), c); _model->apply_command (*trackview.session(), c);
trackview.editor().commit_reversible_command (); trackview.editor().commit_reversible_command ();
@ -2171,11 +2141,11 @@ MidiRegionView::select_all_notes ()
} }
void void
MidiRegionView::select_range (samplepos_t start, samplepos_t end) MidiRegionView::select_range (timepos_t const & start, timepos_t const & end)
{ {
PBD::Unwinder<bool> uw (_no_sound_notes, true); PBD::Unwinder<bool> uw (_no_sound_notes, true);
for (Events::iterator i = _events.begin(); i != _events.end(); ++i) { 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) { if (t >= start && t <= end) {
add_to_selection (i->second); add_to_selection (i->second);
} }
@ -2403,10 +2373,9 @@ MidiRegionView::update_drag_selection(samplepos_t start, samplepos_t end, double
PublicEditor& editor = trackview.editor(); PublicEditor& editor = trackview.editor();
// Convert to local coordinates // Convert to local coordinates
const samplepos_t p = _region->position();
const double y = midi_view()->y_position(); const double y = midi_view()->y_position();
const double x0 = editor.sample_to_pixel(max((samplepos_t)0, start - p)); const double x0 = editor.time_to_pixel (max (timepos_t(), _region->region_relative_position (timepos_t (start))));
const double x1 = editor.sample_to_pixel(max((samplepos_t)0, end - p)); 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 y0 = max(0.0, gy0 - y);
const double y1 = max(0.0, gy1 - 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(); const ATracks& atracks = midi_view()->automation_tracks();
Selectables selectables; Selectables selectables;
editor.get_selection().clear_points(); editor.get_selection().clear_points();
timepos_t st (start);
timepos_t et (end);
for (ATracks::const_iterator a = atracks.begin(); a != atracks.end(); ++a) { 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) { for (Selectables::const_iterator s = selectables.begin(); s != selectables.end(); ++s) {
ControlPoint* cp = dynamic_cast<ControlPoint*>(*s); ControlPoint* cp = dynamic_cast<ControlPoint*>(*s);
if (cp) { if (cp) {
@ -2531,7 +2504,7 @@ MidiRegionView::earliest_in_selection ()
} }
void 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<boost::shared_ptr<NoteType> > PossibleChord; typedef vector<boost::shared_ptr<NoteType> > PossibleChord;
Editor* editor = dynamic_cast<Editor*> (&trackview.editor()); Editor* editor = dynamic_cast<Editor*> (&trackview.editor());
@ -2544,8 +2517,9 @@ MidiRegionView::move_selection(double dx_qn, double dy, double cumulative_dy)
if (n->note()->time() == earliest) { if (n->note()->time() == earliest) {
to_play.push_back (n->note()); 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; double dx = 0.0;
if (midi_view()->note_mode() == Sustained) { if (midi_view()->note_mode() == Sustained) {
dx = editor->sample_to_pixel_unrounded (tmap.sample_at_quarter_note (note_time_qn + dx_qn)) 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; - 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) { if (n->note()->time() == earliest) {
to_play.push_back (n->note()); 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; double dx = 0.0;
if (midi_view()->note_mode() == Sustained) { if (midi_view()->note_mode() == Sustained) {
dx = editor->sample_to_pixel_unrounded (tmap.sample_at_quarter_note (note_time_qn + dx_qn)) 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; - 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 x Pixel relative to the region position.
* @param ensure_snap defaults to false. true = snap always, ignoring snap mode and magnetic snap. * @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. * 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 timepos_t
MidiRegionView::snap_pixel_to_sample(double x, bool ensure_snap) MidiRegionView::snap_pixel_to_time (double x, bool ensure_snap)
{ {
PublicEditor& editor (trackview.editor()); 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. /** @param x Pixel relative to the region position.
@ -2817,21 +2793,20 @@ MidiRegionView::snap_pixel_to_sample(double x, bool ensure_snap)
double double
MidiRegionView::snap_to_pixel(double x, bool ensure_snap) 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 double
MidiRegionView::get_position_pixels() MidiRegionView::get_position_pixels()
{ {
samplepos_t region_sample = get_position(); return trackview.editor().time_to_pixel(get_position());
return trackview.editor().sample_to_pixel(region_sample);
} }
double double
MidiRegionView::get_end_position_pixels() MidiRegionView::get_end_position_pixels()
{ {
samplepos_t sample = get_position() + get_duration (); const timepos_t end = get_position() + get_duration ();
return trackview.editor().sample_to_pixel(sample); return trackview.editor().time_to_pixel (end);
} }
void void
@ -2886,7 +2861,6 @@ MidiRegionView::begin_resizing (bool /*at_front*/)
void void
MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_x, bool relative, double snap_delta, bool with_snap) 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 cursor_set = false;
bool const ensure_snap = trackview.editor().snap_mode () != SnapMagnetic; 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; current_x = 0;
} }
if (current_x > trackview.editor().sample_to_pixel(_region->length())) { if (current_x > trackview.editor().duration_to_pixels (_region->nt_length())) {
current_x = trackview.editor().sample_to_pixel(_region->length()); current_x = trackview.editor().duration_to_pixels (_region->nt_length());
} }
if (at_front) { if (at_front) {
@ -2935,47 +2909,49 @@ MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_
resize_rect->set_x0 (canvas_note->x0()); resize_rect->set_x0 (canvas_note->x0());
} }
if (!cursor_set) { if (!cursor_set) {
/* Convert snap delta from pixels to beats. */ /* Convert snap delta from pixels to beats. */
samplepos_t snap_delta_samps = trackview.editor().pixel_to_sample (snap_delta); samplepos_t snap_delta_samps = trackview.editor().pixel_to_sample (snap_delta);
double snap_delta_beats = 0.0; double snap_delta_beats = 0.0;
int sign = 1; int sign = 1;
/* negative beat offsets aren't allowed */ /* negative beat offsets aren't allowed */
if (snap_delta_samps > 0) { 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) { } 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; sign = -1;
} }
double snapped_x; timepos_t snapped_x;
int32_t divisions = 0;
if (with_snap) { if (with_snap) {
snapped_x = snap_pixel_to_sample (current_x, ensure_snap); snapped_x = snap_pixel_to_time (current_x, ensure_snap); /* units depend on snap settings */
divisions = trackview.editor().get_grid_music_divisions (0);
} else { } 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(); Temporal::Beats len = Temporal::Beats();
if (at_front) { if (at_front) {
if (beats < canvas_note->note()->end_time()) { if (beats < canvas_note->note()->end_time()) {
len = canvas_note->note()->time() - beats + (sign * snap_delta_beats); len = canvas_note->note()->time() - beats + (snap_delta_beats * sign);
len += canvas_note->note()->length(); len += canvas_note->note()->length();
} }
} else { } else {
if (beats >= canvas_note->note()->time()) { if (beats >= canvas_note->note()->time()) {
len = beats - canvas_note->note()->time() - (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::from_double (1 / 512.0), len);
len = std::max (Temporal::Beats (0,1), len);
char buf[16]; char buf[16];
/* represent as float frac to help out the user */ /* 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; 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) { if (current_x < 0) {
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. */ /* Convert snap delta from pixels to beats with sign. */
samplepos_t snap_delta_samps = trackview.editor().pixel_to_sample (snap_delta); 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; int sign = 1;
if (snap_delta_samps > 0) { 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) { } 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; sign = -1;
} }
uint32_t divisions = 0;
/* Convert the new x position to a sample within the source */ /* Convert the new x position to a sample within the source */
samplepos_t current_fr; timepos_t current_time;
if (with_snap) { if (with_snap) {
current_fr = snap_pixel_to_sample (current_x, ensure_snap); current_time = snap_pixel_to_time (current_x, ensure_snap);
divisions = trackview.editor().get_grid_music_divisions (0);
} else { } else {
current_fr = trackview.editor().pixel_to_sample (current_x); current_time = trackview.editor().pixel_to_sample (current_x);
} }
/* and then to beats */ /* and then to beats */
const double e_qaf = tmap.exact_qn_at_sample (current_fr + midi_region()->position(), divisions); #warning NUTEMPO need new tempo map
const double quarter_note_start = _region->quarter_note() - midi_region()->start_beats(); //const timepos_t abs_beats (tmap.quarter_note_at (current_time));
const Temporal::Beats x_beats = Temporal::Beats::from_double (e_qaf - quarter_note_start); 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()) { 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, x_beats - (snap_delta_beats * sign));
note_diff_add_change (canvas_note, MidiModel::NoteDiffCommand::StartTime, new_start); Temporal::Beats len = canvas_note->note()->time() - x_beats + (snap_delta_beats * sign);
Temporal::Beats len = canvas_note->note()->end_time() - new_start; len += canvas_note->note()->length();
if (!!len) { if (!!len) {
note_diff_add_change (canvas_note, MidiModel::NoteDiffCommand::Length, 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) { 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); 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); delta = Temporal::Beats::ticks (Temporal::ticks_per_beat / 128);
} else { } else {
/* grab the current grid distance */ /* 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. 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; Temporal::Beats delta;
if (trackview.editor().snap_mode() == Editing::SnapOff) { if (trackview.editor().snap_mode() == Editing::SnapOff) {
/* grid is off - use nudge distance */ /* grid is off - use nudge distance */
samplepos_t unused; timecnt_t unused;
const samplecnt_t distance = trackview.editor().get_nudge_distance (ref_point, unused); const timecnt_t distance = trackview.editor().get_nudge_distance (ref_point, unused);
delta = region_samples_to_region_beats (fabs ((double)distance)); delta = _region->region_distance_to_region_beats (timecnt_t (distance.beats(), _region->nt_position()));
} else { } else {
@ -3664,7 +3640,7 @@ MidiRegionView::selection_as_cut_buffer () const
/** This method handles undo */ /** This method handles undo */
bool 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; bool commit = false;
// Paste notes, if available // Paste notes, if available
@ -3681,7 +3657,7 @@ MidiRegionView::paste (samplepos_t pos, const ::Selection& selection, PasteConte
typedef RouteTimeAxisView::AutomationTracks ATracks; typedef RouteTimeAxisView::AutomationTracks ATracks;
const ATracks& atracks = midi_view()->automation_tracks(); const ATracks& atracks = midi_view()->automation_tracks();
for (ATracks::const_iterator a = atracks.begin(); a != atracks.end(); ++a) { 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) { if(!commit) {
trackview.editor().begin_reversible_command (Operations::paste); trackview.editor().begin_reversible_command (Operations::paste);
} }
@ -3697,7 +3673,7 @@ MidiRegionView::paste (samplepos_t pos, const ::Selection& selection, PasteConte
/** This method handles undo */ /** This method handles undo */
void 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()) { if (mcb.empty()) {
return; 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 last_time = (*mcb.notes().rbegin())->end_time();
const Temporal::Beats duration = last_time - first_time; const Temporal::Beats duration = last_time - first_time;
const Temporal::Beats snap_duration = duration.snap_to(snap_beats); const Temporal::Beats snap_duration = duration.snap_to(snap_beats);
const Temporal::Beats paste_offset = snap_duration * paste_count; const Temporal::Beats paste_offset = snap_duration * int32_t (paste_count);
const Temporal::Beats quarter_note = absolute_samples_to_source_beats(pos) + paste_offset; const Temporal::Beats quarter_note = _region->absolute_time_to_source_beats (pos) + paste_offset;
Temporal::Beats end_point = Temporal::Beats(); 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", 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, first_time,
last_time, last_time,
duration, pos, _region->position(), duration, pos, _region->nt_position(),
quarter_note)); quarter_note));
for (int n = 0; n < (int) times; ++n) { 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 */ /* if we pasted past the current end of the region, extend the region */
samplepos_t end_sample = source_beats_to_absolute_samples (end_point); timepos_t end = _region->source_beats_to_absolute_time (end_point);
samplepos_t region_end = _region->position() + _region->length() - 1; 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 (); _region->clear_changes ();
/* we probably need to get the snap modifier somehow to make this correct for non-musical use */ /* 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)); 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); 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 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 */ /* 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(); _ghost_note->hide();
hide_verbose_cursor (); hide_verbose_cursor ();
return; return;
@ -3927,14 +3902,13 @@ MidiRegionView::update_ghost_note (double x, double y, uint32_t state)
_ghost_note->show(); _ghost_note->show();
/* calculate time in beats relative to start of source */ /* 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_time (snapped_beats);
_ghost_note->note()->set_length (length); _ghost_note->note()->set_length (length);
_ghost_note->note()->set_note (y_to_note (y)); _ghost_note->note()->set_note (y_to_note (y));
_ghost_note->note()->set_channel (mtv->get_channel_for_add ()); _ghost_note->note()->set_channel (mtv->get_channel_for_add ());
_ghost_note->note()->set_velocity (get_velocity_for_add (snapped_beats)); _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); update_note (_ghost_note, false);
show_verbose_cursor (_ghost_note->note ()); show_verbose_cursor (_ghost_note->note ());
@ -4073,7 +4047,7 @@ MidiRegionView::move_step_edit_cursor (Temporal::Beats pos)
_step_edit_cursor_position = pos; _step_edit_cursor_position = pos;
if (_step_edit_cursor) { 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); _step_edit_cursor->set_x0 (pixel);
set_step_edit_cursor_width (_step_edit_cursor_width); 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; _step_edit_cursor_width = beats;
if (_step_edit_cursor) { if (_step_edit_cursor) {
_step_edit_cursor->set_x1 (_step_edit_cursor->x0() _step_edit_cursor->set_x1 (_step_edit_cursor->x0() + trackview.editor().duration_to_pixels (
+ trackview.editor().sample_to_pixel ( _region->region_beats_to_region_time (_step_edit_cursor_position).distance
region_beats_to_region_samples (_step_edit_cursor_position + beats) (_region->region_beats_to_region_time (_step_edit_cursor_position + beats))));
- region_beats_to_region_samples (_step_edit_cursor_position)));
} }
} }
@ -4134,9 +4107,12 @@ MidiRegionView::data_recorded (boost::weak_ptr<MidiSource> w)
} }
} }
/* convert from session samples to source beats */ /* ev.time() is in MidiBuffer::TimeType i.e. samples
Temporal::Beats const time_beats = _source_relative_time_converter.from(
ev.time() - src->natural_position() + _region->start()); 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) { if (ev.type() == MIDI_CMD_NOTE_ON) {
@ -4174,7 +4150,7 @@ MidiRegionView::trim_front_starting ()
void void
MidiRegionView::trim_front_ending () MidiRegionView::trim_front_ending ()
{ {
if (_region->start() < 0) { if (_region->nt_start().negative()) {
/* Trim drag made start time -ve; fix this */ /* Trim drag made start time -ve; fix this */
midi_region()->fix_negative_start (); midi_region()->fix_negative_start ();
} }
@ -4183,7 +4159,7 @@ MidiRegionView::trim_front_ending ()
void void
MidiRegionView::edit_patch_change (PatchChange* pc) 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(); 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. * @return beat duration of p snapped to the grid subdivision underneath it.
*/ */
Temporal::Beats 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()); #warning NUTEMPO new tempo map API required
double eqaf = map.exact_qn_at_sample (p + _region->position(), divisions); #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 /* 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. 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 Temporal::Beats grid_beats = get_grid_beats (p + _region->position_sample());
const double rem = eqaf - qaf; const Temporal::Beats rem = eqaf - qaf;
if (rem >= 0.0) {
if (rem >= Temporal::Beats()) {
eqaf -= grid_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 ChannelMode
@ -4331,14 +4314,16 @@ MidiRegionView::get_selected_channels () const
Temporal::Beats Temporal::Beats
MidiRegionView::get_grid_beats(samplepos_t pos) const MidiRegionView::get_grid_beats (timepos_t const & pos) const
{ {
PublicEditor& editor = trackview.editor(); PublicEditor& editor = trackview.editor();
bool success = false; bool success = false;
Temporal::Beats beats = editor.get_grid_type_as_beats (success, pos); Temporal::Beats beats = editor.get_grid_type_as_beats (success, pos);
if (!success) { if (!success) {
beats = Temporal::Beats (1, 0); beats = Temporal::Beats (1, 0);
} }
return beats; return beats;
} }
uint8_t 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; 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());
}

View file

@ -128,8 +128,8 @@ public:
void resolve_note(uint8_t note_num, Temporal::Beats end_time); void resolve_note(uint8_t note_num, Temporal::Beats end_time);
void cut_copy_clear (Editing::CutCopyOp); void cut_copy_clear (Editing::CutCopyOp);
bool paste (samplepos_t pos, const ::Selection& selection, PasteContext& ctx, const int32_t sub_num); bool paste (Temporal::timepos_t const & pos, const ::Selection& selection, PasteContext& ctx);
void paste_internal (samplepos_t pos, unsigned paste_count, float times, const MidiCutBuffer&); 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 add_canvas_patch_change (ARDOUR::MidiModel::PatchChangePtr patch);
void remove_canvas_patch_change (PatchChange* pc); 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 (PatchChange& old_patch, const MIDI::Name::PatchPrimaryKey& new_patch);
void change_patch_change (ARDOUR::MidiModel::PatchChangePtr, Evoral::PatchChange<Temporal::Beats> const &); void change_patch_change (ARDOUR::MidiModel::PatchChangePtr, Evoral::PatchChange<Temporal::Beats> const &);
void add_patch_change (samplecnt_t, Evoral::PatchChange<Temporal::Beats> const &); void add_patch_change (Temporal::timecnt_t const &, Evoral::PatchChange<Temporal::Beats> const &);
void move_patch_change (PatchChange &, Temporal::Beats); void move_patch_change (PatchChange &, Temporal::Beats);
void delete_patch_change (PatchChange *); void delete_patch_change (PatchChange *);
void edit_patch_change (PatchChange *); void edit_patch_change (PatchChange *);
@ -205,12 +205,12 @@ public:
void delete_note (boost::shared_ptr<NoteType>); void delete_note (boost::shared_ptr<NoteType>);
size_t selection_size() { return _selection.size(); } size_t selection_size() { return _selection.size(); }
void select_all_notes (); 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 invert_selection ();
void extend_selection (); void extend_selection ();
Temporal::Beats earliest_in_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); void note_dropped (NoteBase* ev, Temporal::Beats const & d_qn, int8_t d_note, bool copy);
NoteBase* copy_selection (NoteBase* primary); NoteBase* copy_selection (NoteBase* primary);
void move_copies(Temporal::Beats const & dx_qn, double dy, double cumulative_dy); void move_copies(Temporal::Beats const & dx_qn, double dy, double cumulative_dy);
@ -450,10 +450,6 @@ public:
typedef boost::unordered_map<ARDOUR::MidiModel::constSysExPtr, boost::shared_ptr<SysEx> > SysExes; typedef boost::unordered_map<ARDOUR::MidiModel::constSysExPtr, boost::shared_ptr<SysEx> > SysExes;
typedef std::vector<NoteBase*> CopyDragEvents; typedef std::vector<NoteBase*> CopyDragEvents;
ARDOUR::BeatsSamplesConverter _region_relative_time_converter;
ARDOUR::BeatsSamplesConverter _source_relative_time_converter;
ARDOUR::BeatsSamplesConverter _region_relative_time_converter_double;
boost::shared_ptr<ARDOUR::MidiModel> _model; boost::shared_ptr<ARDOUR::MidiModel> _model;
Events _events; Events _events;
CopyDragEvents _copy_drag_events; CopyDragEvents _copy_drag_events;
@ -533,7 +529,7 @@ public:
void data_recorded (boost::weak_ptr<ARDOUR::MidiSource>); void data_recorded (boost::weak_ptr<ARDOUR::MidiSource>);
/** Get grid type as beats, or default to 1 if not snapped to beats. */ /** 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 remove_ghost_note ();
void mouse_mode_changed (); void mouse_mode_changed ();
@ -553,7 +549,7 @@ public:
Gtkmm2ext::Color _patch_change_outline; Gtkmm2ext::Color _patch_change_outline;
Gtkmm2ext::Color _patch_change_fill; 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; PBD::ScopedConnection _mouse_mode_connection;

View file

@ -643,20 +643,20 @@ ClockOption::set_state_from_config ()
Timecode::Time TC; Timecode::Time TC;
samplepos_t when; samplepos_t when;
if (!Timecode::parse_timecode_format(_get(), TC)) { 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.rate = _session->samples_per_timecode_frame();
TC.drop = _session->timecode_drop_frames(); TC.drop = _session->timecode_drop_frames();
_session->timecode_to_sample(TC, when, false, false); _session->timecode_to_sample(TC, when, false, false);
if (TC.negative) { when=-when; } if (TC.negative) { when=-when; }
_clock.set (when, true); _clock.set (timepos_t (when), true);
} }
void void
ClockOption::save_clock_time () ClockOption::save_clock_time ()
{ {
Timecode::Time TC; 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)); _set (Timecode::timecode_format_time(TC));
} }

View file

@ -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 */ /** @param tc If non-0, a time converter for this patch change. If 0, time control will be desensitized */
PatchChangeDialog::PatchChangeDialog ( PatchChangeDialog::PatchChangeDialog (
const ARDOUR::BeatsSamplesConverter* tc,
ARDOUR::Session* session, ARDOUR::Session* session,
Evoral::PatchChange<Temporal::Beats> const& patch, Evoral::PatchChange<Temporal::Beats> const& patch,
ARDOUR::InstrumentInfo& info, ARDOUR::InstrumentInfo& info,

View file

@ -42,7 +42,6 @@ class PatchChangeDialog : public ArdourDialog
{ {
public: public:
PatchChangeDialog ( PatchChangeDialog (
const ARDOUR::BeatsSamplesConverter*,
ARDOUR::Session*, ARDOUR::Session*,
Evoral::PatchChange<Temporal::Beats> const&, Evoral::PatchChange<Temporal::Beats> const&,
ARDOUR::InstrumentInfo&, ARDOUR::InstrumentInfo&,

View file

@ -210,6 +210,10 @@ public:
virtual samplepos_t playhead_cursor_sample () const = 0; virtual samplepos_t playhead_cursor_sample () const = 0;
virtual double sample_to_pixel (samplepos_t 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 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 Selection& get_selection () const = 0;
virtual bool get_selection_extents (samplepos_t &start, samplepos_t &end) 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 toggle_meter_updating() = 0;
virtual void split_regions_at (Temporal::timepos_t const &, RegionSelection&) = 0; virtual void split_regions_at (Temporal::timepos_t const &, RegionSelection&) = 0;
virtual void split_region_at_points (boost::shared_ptr<ARDOUR::Region>, ARDOUR::AnalysisFeatureList&, bool can_ferret, bool select_new = false) = 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 (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<void,TimeAxisView&>) = 0; virtual void foreach_time_axis_view (sigc::slot<void,TimeAxisView&>) = 0;
virtual void add_to_idle_resize (TimeAxisView*, int32_t) = 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; 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 build_region_boundary_cache () = 0;
virtual void mark_region_boundary_cache_dirty () = 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_tempo_event (Temporal::timepos_t where) = 0;
virtual void mouse_add_new_meter_event (samplepos_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_tempo_section (ARDOUR::TempoSection*) = 0;
virtual void edit_meter_section (ARDOUR::MeterSection*) = 0; virtual void edit_meter_section (ARDOUR::MeterSection*) = 0;

View file

@ -107,7 +107,7 @@ RegionEditor::RegionEditor (Session* s, boost::shared_ptr<Region> r)
start_label.set_text (_("File start:")); start_label.set_text (_("File start:"));
_sources_label.set_name ("RegionEditorLabel"); _sources_label.set_name ("RegionEditorLabel");
if (_region->n_channels() > 1) { if (_region->sources().size() > 1) {
_sources_label.set_text (_("Sources:")); _sources_label.set_text (_("Sources:"));
} else { } else {
_sources_label.set_text (_("Source:")); _sources_label.set_text (_("Source:"));
@ -174,7 +174,7 @@ RegionEditor::RegionEditor (Session* s, boost::shared_ptr<Region> r)
set_title (string_compose (_("Region '%1'"), _region->name())); 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()); _sources.append_text (_region->source(i)->name());
} }
@ -321,13 +321,13 @@ RegionEditor::end_clock_changed ()
PublicEditor::instance().commit_reversible_command (); PublicEditor::instance().commit_reversible_command ();
} }
end_clock.set (_region->position() + _region->length() - 1, true); end_clock.set (_region->nt_last(), true);
} }
void void
RegionEditor::length_clock_changed () RegionEditor::length_clock_changed ()
{ {
samplecnt_t samples = length_clock.current_time(); timecnt_t len = length_clock.current_duration();
bool in_command = false; bool in_command = false;
boost::shared_ptr<Playlist> pl = _region->playlist(); boost::shared_ptr<Playlist> pl = _region->playlist();
@ -336,7 +336,7 @@ RegionEditor::length_clock_changed ()
in_command = true; in_command = true;
_region->clear_changes (); _region->clear_changes ();
_region->trim_end (_region->position() + samples - 1); _region->trim_end (_region->nt_position() + len.decrement());
_session->add_command(new StatefulDiffCommand (_region)); _session->add_command(new StatefulDiffCommand (_region));
} }
@ -344,7 +344,7 @@ RegionEditor::length_clock_changed ()
PublicEditor::instance().commit_reversible_command (); PublicEditor::instance().commit_reversible_command ();
} }
length_clock.set (_region->length()); length_clock.set_duration (_region->nt_length());
} }
void void
@ -369,33 +369,33 @@ void
RegionEditor::bounds_changed (const PropertyChange& what_changed) RegionEditor::bounds_changed (const PropertyChange& what_changed)
{ {
if (what_changed.contains (ARDOUR::Properties::position) && what_changed.contains (ARDOUR::Properties::length)) { if (what_changed.contains (ARDOUR::Properties::position) && what_changed.contains (ARDOUR::Properties::length)) {
position_clock.set (_region->position(), true); position_clock.set (_region->nt_position(), true);
end_clock.set (_region->position() + _region->length() - 1, true); end_clock.set (_region->nt_last(), true);
length_clock.set (_region->length(), true); length_clock.set_duration (_region->nt_length(), true);
} else if (what_changed.contains (ARDOUR::Properties::position)) { } else if (what_changed.contains (ARDOUR::Properties::position)) {
position_clock.set (_region->position(), true); position_clock.set (_region->nt_position(), true);
end_clock.set (_region->position() + _region->length() - 1, true); end_clock.set (_region->nt_last(), true);
} else if (what_changed.contains (ARDOUR::Properties::length)) { } else if (what_changed.contains (ARDOUR::Properties::length)) {
end_clock.set (_region->position() + _region->length() - 1, true); end_clock.set (_region->nt_last(), true);
length_clock.set (_region->length(), true); length_clock.set_duration (_region->nt_length(), true);
} }
if (what_changed.contains (ARDOUR::Properties::sync_position) || what_changed.contains (ARDOUR::Properties::position)) { if (what_changed.contains (ARDOUR::Properties::sync_position) || what_changed.contains (ARDOUR::Properties::position)) {
int dir; int dir;
sampleoffset_t off = _region->sync_offset (dir); timecnt_t off = _region->sync_offset (dir);
if (dir == -1) { if (dir == -1) {
off = -off; off = -off;
} }
if (what_changed.contains (ARDOUR::Properties::sync_position)) { 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)) { if (what_changed.contains (ARDOUR::Properties::start)) {
start_clock.set (_region->start(), true); start_clock.set (_region->nt_start(), true);
} }
} }

View file

@ -209,6 +209,7 @@ SoundFileBox::SoundFileBox (bool /*persistent*/)
table.attach (timecode_clock, 1, 2, 5, 6, FILL, FILL); table.attach (timecode_clock, 1, 2, 5, 6, FILL, FILL);
table.attach (tempomap_value, 1, 2, 6, 7, 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()); length_clock.set_mode (ARDOUR_UI::instance()->primary_clock->mode());
timecode_clock.set_mode (AudioClock::Timecode); timecode_clock.set_mode (AudioClock::Timecode);
@ -342,7 +343,7 @@ SoundFileBox::setup_labels (const string& filename)
format_text.set_text ("MIDI"); format_text.set_text ("MIDI");
samplerate_value.set_text ("-"); samplerate_value.set_text ("-");
tags_entry.get_buffer()->set_text (""); tags_entry.get_buffer()->set_text ("");
timecode_clock.set (0); timecode_clock.set (timepos_t ());
tags_entry.set_sensitive (false); tags_entry.set_sensitive (false);
if (ms) { if (ms) {
@ -355,7 +356,7 @@ SoundFileBox::setup_labels (const string& filename)
channels_value.set_text (to_string(ms->num_tracks())); 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()) { switch (ms->num_tempos()) {
case 0: case 0:
tempomap_value.set_text (_("No tempo data")); tempomap_value.set_text (_("No tempo data"));
@ -376,7 +377,7 @@ SoundFileBox::setup_labels (const string& filename)
} }
} else { } else {
channels_value.set_text (""); channels_value.set_text ("");
length_clock.set (0); length_clock.set (timepos_t());
tempomap_value.set_text (_("No tempo data")); tempomap_value.set_text (_("No tempo data"));
} }
@ -397,8 +398,8 @@ SoundFileBox::setup_labels (const string& filename)
samplerate_value.set_text (""); samplerate_value.set_text ("");
tags_entry.get_buffer()->set_text (""); tags_entry.get_buffer()->set_text ("");
length_clock.set (0); length_clock.set (timepos_t());
timecode_clock.set (0); timecode_clock.set (timepos_t());
tags_entry.set_sensitive (false); tags_entry.set_sensitive (false);
play_btn.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; samplecnt_t const nfr = _session ? _session->nominal_sample_rate() : 25;
double src_coef = (double) nfr / sf_info.samplerate; double src_coef = (double) nfr / sf_info.samplerate;
length_clock.set (sf_info.length * src_coef + 0.5, true); length_clock.set_is_duration (true, timepos_t());
timecode_clock.set (sf_info.timecode * src_coef + 0.5, true); 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) // this is a hack that is fixed in trunk, i think (august 26th, 2007)
@ -510,7 +512,7 @@ SoundFileBox::audition ()
PropertyList plist; PropertyList plist;
plist.add (ARDOUR::Properties::start, 0); 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::name, rname);
plist.add (ARDOUR::Properties::layer, 0); plist.add (ARDOUR::Properties::layer, 0);
@ -559,28 +561,29 @@ SoundFileBox::audition ()
PropertyList plist; PropertyList plist;
plist.add (ARDOUR::Properties::start, 0); 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::name, rname);
plist.add (ARDOUR::Properties::layer, 0); plist.add (ARDOUR::Properties::layer, 0);
r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, plist, false)); r = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (srclist, plist, false));
} }
sampleoffset_t audition_position = 0; timepos_t audition_position;
switch(_import_position) {
switch (_import_position) {
case ImportAtTimestamp: case ImportAtTimestamp:
audition_position = 0;
break; break;
case ImportAtPlayhead: case ImportAtPlayhead:
audition_position = _session->transport_sample(); audition_position = timepos_t (_session->transport_sample());
break; break;
case ImportAtStart: case ImportAtStart:
audition_position = _session->current_start_sample(); audition_position = timepos_t (_session->current_start_sample());
break; break;
case ImportAtEditPoint: case ImportAtEditPoint:
audition_position = PublicEditor::instance().get_preferred_edit_position (); audition_position = PublicEditor::instance().get_preferred_edit_position ();
break; break;
} }
r->set_position(audition_position); r->set_position(audition_position);
_session->audition_region(r); _session->audition_region(r);
@ -2074,7 +2077,7 @@ SoundFileOmega::do_something (int action)
ImportMode mode = get_mode (); ImportMode mode = get_mode ();
ImportDisposition chns = get_channel_disposition (); ImportDisposition chns = get_channel_disposition ();
PluginInfoPtr instrument = instrument_combo.selected_instrument(); PluginInfoPtr instrument = instrument_combo.selected_instrument();
samplepos_t where; timepos_t where;
MidiTrackNameSource mts = get_midi_track_name_source (); MidiTrackNameSource mts = get_midi_track_name_source ();
MidiTempoMapDisposition mtd = (get_use_smf_tempo_map () ? SMFTempoUse : SMFTempoIgnore); MidiTempoMapDisposition mtd = (get_use_smf_tempo_map () ? SMFTempoUse : SMFTempoIgnore);
bool with_midi_markers = get_use_smf_markers (); bool with_midi_markers = get_use_smf_markers ();
@ -2084,13 +2087,13 @@ SoundFileOmega::do_something (int action)
where = PublicEditor::instance().get_preferred_edit_position (); where = PublicEditor::instance().get_preferred_edit_position ();
break; break;
case ImportAtTimestamp: case ImportAtTimestamp:
where = -1; where = timepos_t::max (Temporal::AudioTime);
break; break;
case ImportAtPlayhead: case ImportAtPlayhead:
where = _session->transport_sample(); where = timepos_t (_session->transport_sample());
break; break;
case ImportAtStart: case ImportAtStart:
where = _session->current_start_sample(); where = timepos_t (_session->current_start_sample());
break; break;
} }

View file

@ -63,6 +63,9 @@ StripSilenceDialog::StripSilenceDialog (Session* s, list<RegionView*> const & v)
views.push_back (ViewInterval (*r)); 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::HBox* hbox = Gtk::manage (new Gtk::HBox);
Gtk::Table* table = Gtk::manage (new Gtk::Table (3, 3)); Gtk::Table* table = Gtk::manage (new Gtk::Table (3, 3));
@ -95,7 +98,7 @@ StripSilenceDialog::StripSilenceDialog (Session* s, list<RegionView*> const & v)
_minimum_length->set_session (s); _minimum_length->set_session (s);
_minimum_length->set_mode (AudioClock::Samples); _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 (*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); table->attach (*_fade_length, 1, 2, n, n + 1, Gtk::FILL);
@ -103,7 +106,8 @@ StripSilenceDialog::StripSilenceDialog (Session* s, list<RegionView*> const & v)
_fade_length->set_session (s); _fade_length->set_session (s);
_fade_length->set_mode (AudioClock::Samples); _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); hbox->pack_start (*table);
@ -341,13 +345,13 @@ StripSilenceDialog::threshold_changed ()
samplecnt_t samplecnt_t
StripSilenceDialog::minimum_length () const 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 samplecnt_t
StripSilenceDialog::fade_length () const 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 void